Commit cbe037b4 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev

* 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev: (112 commits)
  [libata] sata_mv: fix irq port status usage
  [PATCH] libata: move IDENTIFY info printing from ata_dev_read_id() to ata_dev_configure()
  [PATCH] libata: use local *id instead of dev->id in ata_dev_configure()
  [PATCH] libata: check Word 88 validity in ata_id_xfer_mask()
  [PATCH] libata: fix class handling in ata_bus_probe()
  [PATCH] ahci: enable prefetching for PACKET commands
  libata: turn on ATAPI by default
  [PATCH] sata_sil24: lengthen softreset timeout
  [PATCH] sata_sil24: exit early from softreset if SStatus reports no device
  [PATCH] libata: fix missing classes[] initialization in ata_bus_probe()
  [PATCH] libata: kill unused xfer_mode functions
  [PATCH] libata: reimplement ata_set_mode() using xfer_mask helpers
  [PATCH] libata: use xfer_mask helpers in ata_dev_set_mode()
  [PATCH] libata: use ata_id_xfermask() in ata_dev_configure()
  [PATCH] libata: add xfer_mask handling functions
  [PATCH] libata: improve xfer mask constants and update ata_mode_string()
  [PATCH] libata: rename ATA_FLAG_FLUSH_PIO_TASK to ATA_FLAG_FLUSH_PORT_TASK
  [PATCH] libata: kill unused pio_task and packet_task
  [PATCH] libata: convert pio_task and packet_task to port_task
  [PATCH] libata: implement port_task
  ...
parents f0481730 cd85f6e2
...@@ -163,7 +163,7 @@ ncr53c8xx-flags-$(CONFIG_SCSI_ZALON) \ ...@@ -163,7 +163,7 @@ ncr53c8xx-flags-$(CONFIG_SCSI_ZALON) \
CFLAGS_ncr53c8xx.o := $(ncr53c8xx-flags-y) $(ncr53c8xx-flags-m) CFLAGS_ncr53c8xx.o := $(ncr53c8xx-flags-y) $(ncr53c8xx-flags-m)
zalon7xx-objs := zalon.o ncr53c8xx.o zalon7xx-objs := zalon.o ncr53c8xx.o
NCR_Q720_mod-objs := NCR_Q720.o ncr53c8xx.o NCR_Q720_mod-objs := NCR_Q720.o ncr53c8xx.o
libata-objs := libata-core.o libata-scsi.o libata-objs := libata-core.o libata-scsi.o libata-bmdma.o
oktagon_esp_mod-objs := oktagon_esp.o oktagon_io.o oktagon_esp_mod-objs := oktagon_esp.o oktagon_io.o
# Files generated that shall be removed upon make clean # Files generated that shall be removed upon make clean
......
...@@ -66,6 +66,9 @@ enum { ...@@ -66,6 +66,9 @@ enum {
AHCI_IRQ_ON_SG = (1 << 31), AHCI_IRQ_ON_SG = (1 << 31),
AHCI_CMD_ATAPI = (1 << 5), AHCI_CMD_ATAPI = (1 << 5),
AHCI_CMD_WRITE = (1 << 6), AHCI_CMD_WRITE = (1 << 6),
AHCI_CMD_PREFETCH = (1 << 7),
AHCI_CMD_RESET = (1 << 8),
AHCI_CMD_CLR_BUSY = (1 << 10),
RX_FIS_D2H_REG = 0x40, /* offset of D2H Register FIS data */ RX_FIS_D2H_REG = 0x40, /* offset of D2H Register FIS data */
...@@ -85,6 +88,7 @@ enum { ...@@ -85,6 +88,7 @@ enum {
/* HOST_CAP bits */ /* HOST_CAP bits */
HOST_CAP_64 = (1 << 31), /* PCI DAC (64-bit DMA) support */ HOST_CAP_64 = (1 << 31), /* PCI DAC (64-bit DMA) support */
HOST_CAP_CLO = (1 << 24), /* Command List Override support */
/* registers for each SATA port */ /* registers for each SATA port */
PORT_LST_ADDR = 0x00, /* command list DMA addr */ PORT_LST_ADDR = 0x00, /* command list DMA addr */
...@@ -138,6 +142,7 @@ enum { ...@@ -138,6 +142,7 @@ enum {
PORT_CMD_LIST_ON = (1 << 15), /* cmd list DMA engine running */ PORT_CMD_LIST_ON = (1 << 15), /* cmd list DMA engine running */
PORT_CMD_FIS_ON = (1 << 14), /* FIS DMA engine running */ PORT_CMD_FIS_ON = (1 << 14), /* FIS DMA engine running */
PORT_CMD_FIS_RX = (1 << 4), /* Enable FIS receive DMA engine */ PORT_CMD_FIS_RX = (1 << 4), /* Enable FIS receive DMA engine */
PORT_CMD_CLO = (1 << 3), /* Command list override */
PORT_CMD_POWER_ON = (1 << 2), /* Power up device */ PORT_CMD_POWER_ON = (1 << 2), /* Power up device */
PORT_CMD_SPIN_UP = (1 << 1), /* Spin up device */ PORT_CMD_SPIN_UP = (1 << 1), /* Spin up device */
PORT_CMD_START = (1 << 0), /* Enable port DMA engine */ PORT_CMD_START = (1 << 0), /* Enable port DMA engine */
...@@ -184,9 +189,9 @@ struct ahci_port_priv { ...@@ -184,9 +189,9 @@ struct ahci_port_priv {
static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg); static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg);
static void ahci_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); static void ahci_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
static int ahci_qc_issue(struct ata_queued_cmd *qc); static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc);
static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *regs); static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
static void ahci_phy_reset(struct ata_port *ap); static int ahci_probe_reset(struct ata_port *ap, unsigned int *classes);
static void ahci_irq_clear(struct ata_port *ap); static void ahci_irq_clear(struct ata_port *ap);
static void ahci_eng_timeout(struct ata_port *ap); static void ahci_eng_timeout(struct ata_port *ap);
static int ahci_port_start(struct ata_port *ap); static int ahci_port_start(struct ata_port *ap);
...@@ -202,11 +207,11 @@ static struct scsi_host_template ahci_sht = { ...@@ -202,11 +207,11 @@ static struct scsi_host_template ahci_sht = {
.name = DRV_NAME, .name = DRV_NAME,
.ioctl = ata_scsi_ioctl, .ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd, .queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error, .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE, .can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID, .this_id = ATA_SHT_THIS_ID,
.sg_tablesize = AHCI_MAX_SG, .sg_tablesize = AHCI_MAX_SG,
.max_sectors = ATA_MAX_SECTORS,
.cmd_per_lun = ATA_SHT_CMD_PER_LUN, .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
.emulated = ATA_SHT_EMULATED, .emulated = ATA_SHT_EMULATED,
.use_clustering = AHCI_USE_CLUSTERING, .use_clustering = AHCI_USE_CLUSTERING,
...@@ -225,7 +230,7 @@ static const struct ata_port_operations ahci_ops = { ...@@ -225,7 +230,7 @@ static const struct ata_port_operations ahci_ops = {
.tf_read = ahci_tf_read, .tf_read = ahci_tf_read,
.phy_reset = ahci_phy_reset, .probe_reset = ahci_probe_reset,
.qc_prep = ahci_qc_prep, .qc_prep = ahci_qc_prep,
.qc_issue = ahci_qc_issue, .qc_issue = ahci_qc_issue,
...@@ -247,8 +252,7 @@ static const struct ata_port_info ahci_port_info[] = { ...@@ -247,8 +252,7 @@ static const struct ata_port_info ahci_port_info[] = {
{ {
.sht = &ahci_sht, .sht = &ahci_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA,
ATA_FLAG_PIO_DMA,
.pio_mask = 0x1f, /* pio0-4 */ .pio_mask = 0x1f, /* pio0-4 */
.udma_mask = 0x7f, /* udma0-6 ; FIXME */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */
.port_ops = &ahci_ops, .port_ops = &ahci_ops,
...@@ -450,17 +454,48 @@ static void ahci_scr_write (struct ata_port *ap, unsigned int sc_reg_in, ...@@ -450,17 +454,48 @@ static void ahci_scr_write (struct ata_port *ap, unsigned int sc_reg_in,
writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4)); writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
} }
static void ahci_phy_reset(struct ata_port *ap) static int ahci_stop_engine(struct ata_port *ap)
{ {
void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr; void __iomem *mmio = ap->host_set->mmio_base;
struct ata_taskfile tf; void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
struct ata_device *dev = &ap->device[0]; int work;
u32 new_tmp, tmp; u32 tmp;
__sata_phy_reset(ap); tmp = readl(port_mmio + PORT_CMD);
tmp &= ~PORT_CMD_START;
writel(tmp, port_mmio + PORT_CMD);
if (ap->flags & ATA_FLAG_PORT_DISABLED) /* wait for engine to stop. TODO: this could be
return; * as long as 500 msec
*/
work = 1000;
while (work-- > 0) {
tmp = readl(port_mmio + PORT_CMD);
if ((tmp & PORT_CMD_LIST_ON) == 0)
return 0;
udelay(10);
}
return -EIO;
}
static void ahci_start_engine(struct ata_port *ap)
{
void __iomem *mmio = ap->host_set->mmio_base;
void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
u32 tmp;
tmp = readl(port_mmio + PORT_CMD);
tmp |= PORT_CMD_START;
writel(tmp, port_mmio + PORT_CMD);
readl(port_mmio + PORT_CMD); /* flush */
}
static unsigned int ahci_dev_classify(struct ata_port *ap)
{
void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
struct ata_taskfile tf;
u32 tmp;
tmp = readl(port_mmio + PORT_SIG); tmp = readl(port_mmio + PORT_SIG);
tf.lbah = (tmp >> 24) & 0xff; tf.lbah = (tmp >> 24) & 0xff;
...@@ -468,15 +503,46 @@ static void ahci_phy_reset(struct ata_port *ap) ...@@ -468,15 +503,46 @@ static void ahci_phy_reset(struct ata_port *ap)
tf.lbal = (tmp >> 8) & 0xff; tf.lbal = (tmp >> 8) & 0xff;
tf.nsect = (tmp) & 0xff; tf.nsect = (tmp) & 0xff;
dev->class = ata_dev_classify(&tf); return ata_dev_classify(&tf);
if (!ata_dev_present(dev)) { }
ata_port_disable(ap);
return; static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, u32 opts)
} {
pp->cmd_slot[0].opts = cpu_to_le32(opts);
pp->cmd_slot[0].status = 0;
pp->cmd_slot[0].tbl_addr = cpu_to_le32(pp->cmd_tbl_dma & 0xffffffff);
pp->cmd_slot[0].tbl_addr_hi = cpu_to_le32((pp->cmd_tbl_dma >> 16) >> 16);
}
static int ahci_hardreset(struct ata_port *ap, int verbose, unsigned int *class)
{
int rc;
DPRINTK("ENTER\n");
ahci_stop_engine(ap);
rc = sata_std_hardreset(ap, verbose, class);
ahci_start_engine(ap);
if (rc == 0)
*class = ahci_dev_classify(ap);
if (*class == ATA_DEV_UNKNOWN)
*class = ATA_DEV_NONE;
DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
return rc;
}
static void ahci_postreset(struct ata_port *ap, unsigned int *class)
{
void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
u32 new_tmp, tmp;
ata_std_postreset(ap, class);
/* Make sure port's ATAPI bit is set appropriately */ /* Make sure port's ATAPI bit is set appropriately */
new_tmp = tmp = readl(port_mmio + PORT_CMD); new_tmp = tmp = readl(port_mmio + PORT_CMD);
if (dev->class == ATA_DEV_ATAPI) if (*class == ATA_DEV_ATAPI)
new_tmp |= PORT_CMD_ATAPI; new_tmp |= PORT_CMD_ATAPI;
else else
new_tmp &= ~PORT_CMD_ATAPI; new_tmp &= ~PORT_CMD_ATAPI;
...@@ -486,6 +552,12 @@ static void ahci_phy_reset(struct ata_port *ap) ...@@ -486,6 +552,12 @@ static void ahci_phy_reset(struct ata_port *ap)
} }
} }
static int ahci_probe_reset(struct ata_port *ap, unsigned int *classes)
{
return ata_drive_probe_reset(ap, NULL, NULL, ahci_hardreset,
ahci_postreset, classes);
}
static u8 ahci_check_status(struct ata_port *ap) static u8 ahci_check_status(struct ata_port *ap)
{ {
void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr; void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr;
...@@ -533,42 +605,36 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc) ...@@ -533,42 +605,36 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc)
{ {
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
struct ahci_port_priv *pp = ap->private_data; struct ahci_port_priv *pp = ap->private_data;
int is_atapi = is_atapi_taskfile(&qc->tf);
u32 opts; u32 opts;
const u32 cmd_fis_len = 5; /* five dwords */ const u32 cmd_fis_len = 5; /* five dwords */
unsigned int n_elem; unsigned int n_elem;
/*
* Fill in command slot information (currently only one slot,
* slot 0, is currently since we don't do queueing)
*/
opts = cmd_fis_len;
if (qc->tf.flags & ATA_TFLAG_WRITE)
opts |= AHCI_CMD_WRITE;
if (is_atapi_taskfile(&qc->tf))
opts |= AHCI_CMD_ATAPI;
pp->cmd_slot[0].opts = cpu_to_le32(opts);
pp->cmd_slot[0].status = 0;
pp->cmd_slot[0].tbl_addr = cpu_to_le32(pp->cmd_tbl_dma & 0xffffffff);
pp->cmd_slot[0].tbl_addr_hi = cpu_to_le32((pp->cmd_tbl_dma >> 16) >> 16);
/* /*
* Fill in command table information. First, the header, * Fill in command table information. First, the header,
* a SATA Register - Host to Device command FIS. * a SATA Register - Host to Device command FIS.
*/ */
ata_tf_to_fis(&qc->tf, pp->cmd_tbl, 0); ata_tf_to_fis(&qc->tf, pp->cmd_tbl, 0);
if (opts & AHCI_CMD_ATAPI) { if (is_atapi) {
memset(pp->cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32); memset(pp->cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32);
memcpy(pp->cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, ap->cdb_len); memcpy(pp->cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb,
qc->dev->cdb_len);
} }
if (!(qc->flags & ATA_QCFLAG_DMAMAP)) n_elem = 0;
return; if (qc->flags & ATA_QCFLAG_DMAMAP)
n_elem = ahci_fill_sg(qc);
n_elem = ahci_fill_sg(qc); /*
* Fill in command slot information.
*/
opts = cmd_fis_len | n_elem << 16;
if (qc->tf.flags & ATA_TFLAG_WRITE)
opts |= AHCI_CMD_WRITE;
if (is_atapi)
opts |= AHCI_CMD_ATAPI | AHCI_CMD_PREFETCH;
pp->cmd_slot[0].opts |= cpu_to_le32(n_elem << 16); ahci_fill_cmd_slot(pp, opts);
} }
static void ahci_restart_port(struct ata_port *ap, u32 irq_stat) static void ahci_restart_port(struct ata_port *ap, u32 irq_stat)
...@@ -576,7 +642,6 @@ static void ahci_restart_port(struct ata_port *ap, u32 irq_stat) ...@@ -576,7 +642,6 @@ static void ahci_restart_port(struct ata_port *ap, u32 irq_stat)
void __iomem *mmio = ap->host_set->mmio_base; void __iomem *mmio = ap->host_set->mmio_base;
void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
u32 tmp; u32 tmp;
int work;
if ((ap->device[0].class != ATA_DEV_ATAPI) || if ((ap->device[0].class != ATA_DEV_ATAPI) ||
((irq_stat & PORT_IRQ_TF_ERR) == 0)) ((irq_stat & PORT_IRQ_TF_ERR) == 0))
...@@ -592,20 +657,7 @@ static void ahci_restart_port(struct ata_port *ap, u32 irq_stat) ...@@ -592,20 +657,7 @@ static void ahci_restart_port(struct ata_port *ap, u32 irq_stat)
readl(port_mmio + PORT_SCR_ERR)); readl(port_mmio + PORT_SCR_ERR));
/* stop DMA */ /* stop DMA */
tmp = readl(port_mmio + PORT_CMD); ahci_stop_engine(ap);
tmp &= ~PORT_CMD_START;
writel(tmp, port_mmio + PORT_CMD);
/* wait for engine to stop. TODO: this could be
* as long as 500 msec
*/
work = 1000;
while (work-- > 0) {
tmp = readl(port_mmio + PORT_CMD);
if ((tmp & PORT_CMD_LIST_ON) == 0)
break;
udelay(10);
}
/* clear SATA phy error, if any */ /* clear SATA phy error, if any */
tmp = readl(port_mmio + PORT_SCR_ERR); tmp = readl(port_mmio + PORT_SCR_ERR);
...@@ -624,10 +676,7 @@ static void ahci_restart_port(struct ata_port *ap, u32 irq_stat) ...@@ -624,10 +676,7 @@ static void ahci_restart_port(struct ata_port *ap, u32 irq_stat)
} }
/* re-start DMA */ /* re-start DMA */
tmp = readl(port_mmio + PORT_CMD); ahci_start_engine(ap);
tmp |= PORT_CMD_START;
writel(tmp, port_mmio + PORT_CMD);
readl(port_mmio + PORT_CMD); /* flush */
} }
static void ahci_eng_timeout(struct ata_port *ap) static void ahci_eng_timeout(struct ata_port *ap)
...@@ -642,25 +691,13 @@ static void ahci_eng_timeout(struct ata_port *ap) ...@@ -642,25 +691,13 @@ static void ahci_eng_timeout(struct ata_port *ap)
spin_lock_irqsave(&host_set->lock, flags); spin_lock_irqsave(&host_set->lock, flags);
ahci_restart_port(ap, readl(port_mmio + PORT_IRQ_STAT));
qc = ata_qc_from_tag(ap, ap->active_tag); qc = ata_qc_from_tag(ap, ap->active_tag);
if (!qc) { qc->err_mask |= AC_ERR_TIMEOUT;
printk(KERN_ERR "ata%u: BUG: timeout without command\n",
ap->id);
} else {
ahci_restart_port(ap, readl(port_mmio + PORT_IRQ_STAT));
/* hack alert! We cannot use the supplied completion
* function from inside the ->eh_strategy_handler() thread.
* libata is the only user of ->eh_strategy_handler() in
* any kernel, so the default scsi_done() assumes it is
* not being called from the SCSI EH.
*/
qc->scsidone = scsi_finish_command;
qc->err_mask |= AC_ERR_OTHER;
ata_qc_complete(qc);
}
spin_unlock_irqrestore(&host_set->lock, flags); spin_unlock_irqrestore(&host_set->lock, flags);
ata_eh_qc_complete(qc);
} }
static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc) static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
...@@ -678,7 +715,7 @@ static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc) ...@@ -678,7 +715,7 @@ static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
ci = readl(port_mmio + PORT_CMD_ISSUE); ci = readl(port_mmio + PORT_CMD_ISSUE);
if (likely((ci & 0x1) == 0)) { if (likely((ci & 0x1) == 0)) {
if (qc) { if (qc) {
assert(qc->err_mask == 0); WARN_ON(qc->err_mask);
ata_qc_complete(qc); ata_qc_complete(qc);
qc = NULL; qc = NULL;
} }
...@@ -697,7 +734,7 @@ static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc) ...@@ -697,7 +734,7 @@ static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
ahci_restart_port(ap, status); ahci_restart_port(ap, status);
if (qc) { if (qc) {
qc->err_mask |= AC_ERR_OTHER; qc->err_mask |= err_mask;
ata_qc_complete(qc); ata_qc_complete(qc);
} }
} }
...@@ -770,7 +807,7 @@ static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs * ...@@ -770,7 +807,7 @@ static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *
return IRQ_RETVAL(handled); return IRQ_RETVAL(handled);
} }
static int ahci_qc_issue(struct ata_queued_cmd *qc) static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
{ {
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr; void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
......
...@@ -101,36 +101,54 @@ enum { ...@@ -101,36 +101,54 @@ enum {
ICH5_PCS = 0x92, /* port control and status */ ICH5_PCS = 0x92, /* port control and status */
PIIX_SCC = 0x0A, /* sub-class code register */ PIIX_SCC = 0x0A, /* sub-class code register */
PIIX_FLAG_AHCI = (1 << 28), /* AHCI possible */ PIIX_FLAG_IGNORE_PCS = (1 << 25), /* ignore PCS present bits */
PIIX_FLAG_CHECKINTR = (1 << 29), /* make sure PCI INTx enabled */ PIIX_FLAG_SCR = (1 << 26), /* SCR available */
PIIX_FLAG_COMBINED = (1 << 30), /* combined mode possible */ PIIX_FLAG_AHCI = (1 << 27), /* AHCI possible */
PIIX_FLAG_CHECKINTR = (1 << 28), /* make sure PCI INTx enabled */
PIIX_FLAG_COMBINED = (1 << 29), /* combined mode possible */
/* ICH6/7 use different scheme for map value */
PIIX_FLAG_COMBINED_ICH6 = PIIX_FLAG_COMBINED | (1 << 30),
/* combined mode. if set, PATA is channel 0. /* combined mode. if set, PATA is channel 0.
* if clear, PATA is channel 1. * if clear, PATA is channel 1.
*/ */
PIIX_COMB_PATA_P0 = (1 << 1),
PIIX_COMB = (1 << 2), /* combined mode enabled? */
PIIX_PORT_ENABLED = (1 << 0), PIIX_PORT_ENABLED = (1 << 0),
PIIX_PORT_PRESENT = (1 << 4), PIIX_PORT_PRESENT = (1 << 4),
PIIX_80C_PRI = (1 << 5) | (1 << 4), PIIX_80C_PRI = (1 << 5) | (1 << 4),
PIIX_80C_SEC = (1 << 7) | (1 << 6), PIIX_80C_SEC = (1 << 7) | (1 << 6),
ich5_pata = 0, /* controller IDs */
ich5_sata = 1, piix4_pata = 0,
piix4_pata = 2, ich5_pata = 1,
ich6_sata = 3, ich5_sata = 2,
ich6_sata_ahci = 4, esb_sata = 3,
ich6_sata = 4,
ich6_sata_ahci = 5,
ich6m_sata_ahci = 6,
/* constants for mapping table */
P0 = 0, /* port 0 */
P1 = 1, /* port 1 */
P2 = 2, /* port 2 */
P3 = 3, /* port 3 */
IDE = -1, /* IDE */
NA = -2, /* not avaliable */
RV = -3, /* reserved */
PIIX_AHCI_DEVICE = 6, PIIX_AHCI_DEVICE = 6,
}; };
struct piix_map_db {
const u32 mask;
const int map[][4];
};
static int piix_init_one (struct pci_dev *pdev, static int piix_init_one (struct pci_dev *pdev,
const struct pci_device_id *ent); const struct pci_device_id *ent);
static void piix_pata_phy_reset(struct ata_port *ap); static int piix_pata_probe_reset(struct ata_port *ap, unsigned int *classes);
static void piix_sata_phy_reset(struct ata_port *ap); static int piix_sata_probe_reset(struct ata_port *ap, unsigned int *classes);
static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev); static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev);
static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev); static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev);
...@@ -147,19 +165,32 @@ static const struct pci_device_id piix_pci_tbl[] = { ...@@ -147,19 +165,32 @@ static const struct pci_device_id piix_pci_tbl[] = {
* list in drivers/pci/quirks.c. * list in drivers/pci/quirks.c.
*/ */
/* 82801EB (ICH5) */
{ 0x8086, 0x24d1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, { 0x8086, 0x24d1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
/* 82801EB (ICH5) */
{ 0x8086, 0x24df, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, { 0x8086, 0x24df, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
{ 0x8086, 0x25a3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, /* 6300ESB (ICH5 variant with broken PCS present bits) */
{ 0x8086, 0x25b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, { 0x8086, 0x25a3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, esb_sata },
/* 6300ESB pretending RAID */
{ 0x8086, 0x25b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, esb_sata },
/* 82801FB/FW (ICH6/ICH6W) */
{ 0x8086, 0x2651, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata }, { 0x8086, 0x2651, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata },
/* 82801FR/FRW (ICH6R/ICH6RW) */
{ 0x8086, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci }, { 0x8086, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
{ 0x8086, 0x2653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci }, /* 82801FBM ICH6M (ICH6R with only port 0 and 2 implemented) */
{ 0x8086, 0x2653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6m_sata_ahci },
/* 82801GB/GR/GH (ICH7, identical to ICH6) */
{ 0x8086, 0x27c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci }, { 0x8086, 0x27c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
{ 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci }, /* 2801GBM/GHM (ICH7M, identical to ICH6M) */
{ 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6m_sata_ahci },
/* Enterprise Southbridge 2 (where's the datasheet?) */
{ 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci }, { 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
/* SATA Controller 1 IDE (ICH8, no datasheet yet) */
{ 0x8086, 0x2820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci }, { 0x8086, 0x2820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
/* SATA Controller 2 IDE (ICH8, ditto) */
{ 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci }, { 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
{ 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci }, /* Mobile SATA Controller IDE (ICH8M, ditto) */
{ 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6m_sata_ahci },
{ } /* terminate list */ { } /* terminate list */
}; };
...@@ -178,11 +209,11 @@ static struct scsi_host_template piix_sht = { ...@@ -178,11 +209,11 @@ static struct scsi_host_template piix_sht = {
.name = DRV_NAME, .name = DRV_NAME,
.ioctl = ata_scsi_ioctl, .ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd, .queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error, .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE, .can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID, .this_id = ATA_SHT_THIS_ID,
.sg_tablesize = LIBATA_MAX_PRD, .sg_tablesize = LIBATA_MAX_PRD,
.max_sectors = ATA_MAX_SECTORS,
.cmd_per_lun = ATA_SHT_CMD_PER_LUN, .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
.emulated = ATA_SHT_EMULATED, .emulated = ATA_SHT_EMULATED,
.use_clustering = ATA_SHT_USE_CLUSTERING, .use_clustering = ATA_SHT_USE_CLUSTERING,
...@@ -205,7 +236,7 @@ static const struct ata_port_operations piix_pata_ops = { ...@@ -205,7 +236,7 @@ static const struct ata_port_operations piix_pata_ops = {
.exec_command = ata_exec_command, .exec_command = ata_exec_command,
.dev_select = ata_std_dev_select, .dev_select = ata_std_dev_select,
.phy_reset = piix_pata_phy_reset, .probe_reset = piix_pata_probe_reset,
.bmdma_setup = ata_bmdma_setup, .bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start, .bmdma_start = ata_bmdma_start,
...@@ -233,7 +264,7 @@ static const struct ata_port_operations piix_sata_ops = { ...@@ -233,7 +264,7 @@ static const struct ata_port_operations piix_sata_ops = {
.exec_command = ata_exec_command, .exec_command = ata_exec_command,
.dev_select = ata_std_dev_select, .dev_select = ata_std_dev_select,
.phy_reset = piix_sata_phy_reset, .probe_reset = piix_sata_probe_reset,
.bmdma_setup = ata_bmdma_setup, .bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start, .bmdma_start = ata_bmdma_start,
...@@ -252,12 +283,62 @@ static const struct ata_port_operations piix_sata_ops = { ...@@ -252,12 +283,62 @@ static const struct ata_port_operations piix_sata_ops = {
.host_stop = ata_host_stop, .host_stop = ata_host_stop,
}; };
static struct piix_map_db ich5_map_db = {
.mask = 0x7,
.map = {
/* PM PS SM SS MAP */
{ P0, NA, P1, NA }, /* 000b */
{ P1, NA, P0, NA }, /* 001b */
{ RV, RV, RV, RV },
{ RV, RV, RV, RV },
{ P0, P1, IDE, IDE }, /* 100b */
{ P1, P0, IDE, IDE }, /* 101b */
{ IDE, IDE, P0, P1 }, /* 110b */
{ IDE, IDE, P1, P0 }, /* 111b */
},
};
static struct piix_map_db ich6_map_db = {
.mask = 0x3,
.map = {
/* PM PS SM SS MAP */
{ P0, P1, P2, P3 }, /* 00b */
{ IDE, IDE, P1, P3 }, /* 01b */
{ P0, P2, IDE, IDE }, /* 10b */
{ RV, RV, RV, RV },
},
};
static struct piix_map_db ich6m_map_db = {
.mask = 0x3,
.map = {
/* PM PS SM SS MAP */
{ P0, P1, P2, P3 }, /* 00b */
{ RV, RV, RV, RV },
{ P0, P2, IDE, IDE }, /* 10b */
{ RV, RV, RV, RV },
},
};
static struct ata_port_info piix_port_info[] = { static struct ata_port_info piix_port_info[] = {
/* piix4_pata */
{
.sht = &piix_sht,
.host_flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f, /* pio0-4 */
#if 0
.mwdma_mask = 0x06, /* mwdma1-2 */
#else
.mwdma_mask = 0x00, /* mwdma broken */
#endif
.udma_mask = ATA_UDMA_MASK_40C,
.port_ops = &piix_pata_ops,
},
/* ich5_pata */ /* ich5_pata */
{ {
.sht = &piix_sht, .sht = &piix_sht,
.host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | .host_flags = ATA_FLAG_SLAVE_POSS | PIIX_FLAG_CHECKINTR,
PIIX_FLAG_CHECKINTR,
.pio_mask = 0x1f, /* pio0-4 */ .pio_mask = 0x1f, /* pio0-4 */
#if 0 #if 0
.mwdma_mask = 0x06, /* mwdma1-2 */ .mwdma_mask = 0x06, /* mwdma1-2 */
...@@ -271,50 +352,63 @@ static struct ata_port_info piix_port_info[] = { ...@@ -271,50 +352,63 @@ static struct ata_port_info piix_port_info[] = {
/* ich5_sata */ /* ich5_sata */
{ {
.sht = &piix_sht, .sht = &piix_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST | .host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED |
PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR, PIIX_FLAG_CHECKINTR,
.pio_mask = 0x1f, /* pio0-4 */ .pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */ .mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x7f, /* udma0-6 */ .udma_mask = 0x7f, /* udma0-6 */
.port_ops = &piix_sata_ops, .port_ops = &piix_sata_ops,
.private_data = &ich5_map_db,
}, },
/* piix4_pata */ /* i6300esb_sata */
{ {
.sht = &piix_sht, .sht = &piix_sht,
.host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED |
PIIX_FLAG_CHECKINTR | PIIX_FLAG_IGNORE_PCS,
.pio_mask = 0x1f, /* pio0-4 */ .pio_mask = 0x1f, /* pio0-4 */
#if 0 .mwdma_mask = 0x07, /* mwdma0-2 */
.mwdma_mask = 0x06, /* mwdma1-2 */ .udma_mask = 0x7f, /* udma0-6 */
#else .port_ops = &piix_sata_ops,
.mwdma_mask = 0x00, /* mwdma broken */ .private_data = &ich5_map_db,
#endif
.udma_mask = ATA_UDMA_MASK_40C,
.port_ops = &piix_pata_ops,
}, },
/* ich6_sata */ /* ich6_sata */
{ {
.sht = &piix_sht, .sht = &piix_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST | .host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 |
PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR | PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR,
ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f, /* pio0-4 */ .pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */ .mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x7f, /* udma0-6 */ .udma_mask = 0x7f, /* udma0-6 */
.port_ops = &piix_sata_ops, .port_ops = &piix_sata_ops,
.private_data = &ich6_map_db,
}, },
/* ich6_sata_ahci */ /* ich6_sata_ahci */
{ {
.sht = &piix_sht, .sht = &piix_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST | .host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 |
PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR | PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR |
ATA_FLAG_SLAVE_POSS | PIIX_FLAG_AHCI, PIIX_FLAG_AHCI,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x7f, /* udma0-6 */
.port_ops = &piix_sata_ops,
.private_data = &ich6_map_db,
},
/* ich6m_sata_ahci */
{
.sht = &piix_sht,
.host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 |
PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR |
PIIX_FLAG_AHCI,
.pio_mask = 0x1f, /* pio0-4 */ .pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */ .mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x7f, /* udma0-6 */ .udma_mask = 0x7f, /* udma0-6 */
.port_ops = &piix_sata_ops, .port_ops = &piix_sata_ops,
.private_data = &ich6m_map_db,
}, },
}; };
...@@ -363,102 +457,123 @@ static void piix_pata_cbl_detect(struct ata_port *ap) ...@@ -363,102 +457,123 @@ static void piix_pata_cbl_detect(struct ata_port *ap)
} }
/** /**
* piix_pata_phy_reset - Probe specified port on PATA host controller * piix_pata_probeinit - probeinit for PATA host controller
* @ap: Port to probe * @ap: Target port
* *
* Probe PATA phy. * Probeinit including cable detection.
* *
* LOCKING: * LOCKING:
* None (inherited from caller). * None (inherited from caller).
*/ */
static void piix_pata_probeinit(struct ata_port *ap)
{
piix_pata_cbl_detect(ap);
ata_std_probeinit(ap);
}
static void piix_pata_phy_reset(struct ata_port *ap) /**
* piix_pata_probe_reset - Perform reset on PATA port and classify
* @ap: Port to reset
* @classes: Resulting classes of attached devices
*
* Reset PATA phy and classify attached devices.
*
* LOCKING:
* None (inherited from caller).
*/
static int piix_pata_probe_reset(struct ata_port *ap, unsigned int *classes)
{ {
struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->hard_port_no])) { if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->hard_port_no])) {
ata_port_disable(ap);
printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
return; return 0;
} }
piix_pata_cbl_detect(ap); return ata_drive_probe_reset(ap, piix_pata_probeinit,
ata_std_softreset, NULL,
ata_port_probe(ap); ata_std_postreset, classes);
ata_bus_reset(ap);
} }
/** /**
* piix_sata_probe - Probe PCI device for present SATA devices * piix_sata_probe - Probe PCI device for present SATA devices
* @ap: Port associated with the PCI device we wish to probe * @ap: Port associated with the PCI device we wish to probe
* *
* Reads SATA PCI device's PCI config register Port Configuration * Reads and configures SATA PCI device's PCI config register
* and Status (PCS) to determine port and device availability. * Port Configuration and Status (PCS) to determine port and
* device availability.
* *
* LOCKING: * LOCKING:
* None (inherited from caller). * None (inherited from caller).
* *
* RETURNS: * RETURNS:
* Non-zero if port is enabled, it may or may not have a device * Mask of avaliable devices on the port.
* attached in that case (PRESENT bit would only be set if BIOS probe
* was done). Zero is returned if port is disabled.
*/ */
static int piix_sata_probe (struct ata_port *ap) static unsigned int piix_sata_probe (struct ata_port *ap)
{ {
struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
int combined = (ap->flags & ATA_FLAG_SLAVE_POSS); const unsigned int *map = ap->host_set->private_data;
int orig_mask, mask, i; int base = 2 * ap->hard_port_no;
unsigned int present_mask = 0;
int port, i;
u8 pcs; u8 pcs;
mask = (PIIX_PORT_PRESENT << ap->hard_port_no) |
(PIIX_PORT_ENABLED << ap->hard_port_no);
pci_read_config_byte(pdev, ICH5_PCS, &pcs); pci_read_config_byte(pdev, ICH5_PCS, &pcs);
orig_mask = (int) pcs & 0xff; DPRINTK("ata%u: ENTER, pcs=0x%x base=%d\n", ap->id, pcs, base);
/* TODO: this is vaguely wrong for ICH6 combined mode,
* where only two of the four SATA ports are mapped
* onto a single ATA channel. It is also vaguely inaccurate
* for ICH5, which has only two ports. However, this is ok,
* as further device presence detection code will handle
* any false positives produced here.
*/
for (i = 0; i < 4; i++) { /* enable all ports on this ap and wait for them to settle */
mask = (PIIX_PORT_ENABLED << i); for (i = 0; i < 2; i++) {
port = map[base + i];
if (port >= 0)
pcs |= 1 << port;
}
pci_write_config_byte(pdev, ICH5_PCS, pcs);
msleep(100);
if ((orig_mask & mask) == mask) /* let's see which devices are present */
if (combined || (i == ap->hard_port_no)) pci_read_config_byte(pdev, ICH5_PCS, &pcs);
return 1;
for (i = 0; i < 2; i++) {
port = map[base + i];
if (port < 0)
continue;
if (ap->flags & PIIX_FLAG_IGNORE_PCS || pcs & 1 << (4 + port))
present_mask |= 1 << i;
else
pcs &= ~(1 << port);
} }
return 0; /* disable offline ports on non-AHCI controllers */
if (!(ap->flags & PIIX_FLAG_AHCI))
pci_write_config_byte(pdev, ICH5_PCS, pcs);
DPRINTK("ata%u: LEAVE, pcs=0x%x present_mask=0x%x\n",
ap->id, pcs, present_mask);
return present_mask;
} }
/** /**
* piix_sata_phy_reset - Probe specified port on SATA host controller * piix_sata_probe_reset - Perform reset on SATA port and classify
* @ap: Port to probe * @ap: Port to reset
* @classes: Resulting classes of attached devices
* *
* Probe SATA phy. * Reset SATA phy and classify attached devices.
* *
* LOCKING: * LOCKING:
* None (inherited from caller). * None (inherited from caller).
*/ */
static int piix_sata_probe_reset(struct ata_port *ap, unsigned int *classes)
static void piix_sata_phy_reset(struct ata_port *ap)
{ {
if (!piix_sata_probe(ap)) { if (!piix_sata_probe(ap)) {
ata_port_disable(ap);
printk(KERN_INFO "ata%u: SATA port has no device.\n", ap->id); printk(KERN_INFO "ata%u: SATA port has no device.\n", ap->id);
return; return 0;
} }
ap->cbl = ATA_CBL_SATA; return ata_drive_probe_reset(ap, ata_std_probeinit,
ata_std_softreset, NULL,
ata_port_probe(ap); ata_std_postreset, classes);
ata_bus_reset(ap);
} }
/** /**
...@@ -627,6 +742,7 @@ static int piix_disable_ahci(struct pci_dev *pdev) ...@@ -627,6 +742,7 @@ static int piix_disable_ahci(struct pci_dev *pdev)
/** /**
* piix_check_450nx_errata - Check for problem 450NX setup * piix_check_450nx_errata - Check for problem 450NX setup
* @ata_dev: the PCI device to check
* *
* Check for the present of 450NX errata #19 and errata #25. If * Check for the present of 450NX errata #19 and errata #25. If
* they are found return an error code so we can turn off DMA * they are found return an error code so we can turn off DMA
...@@ -659,6 +775,54 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev) ...@@ -659,6 +775,54 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev)
return no_piix_dma; return no_piix_dma;
} }
static void __devinit piix_init_sata_map(struct pci_dev *pdev,
struct ata_port_info *pinfo)
{
struct piix_map_db *map_db = pinfo[0].private_data;
const unsigned int *map;
int i, invalid_map = 0;
u8 map_value;
pci_read_config_byte(pdev, ICH5_PMR, &map_value);
map = map_db->map[map_value & map_db->mask];
dev_printk(KERN_INFO, &pdev->dev, "MAP [");
for (i = 0; i < 4; i++) {
switch (map[i]) {
case RV:
invalid_map = 1;
printk(" XX");
break;
case NA:
printk(" --");
break;
case IDE:
WARN_ON((i & 1) || map[i + 1] != IDE);
pinfo[i / 2] = piix_port_info[ich5_pata];
i++;
printk(" IDE IDE");
break;
default:
printk(" P%d", map[i]);
if (i & 1)
pinfo[i / 2].host_flags |= ATA_FLAG_SLAVE_POSS;
break;
}
}
printk(" ]\n");
if (invalid_map)
dev_printk(KERN_ERR, &pdev->dev,
"invalid MAP value %u\n", map_value);
pinfo[0].private_data = (void *)map;
pinfo[1].private_data = (void *)map;
}
/** /**
* piix_init_one - Register PIIX ATA PCI device with kernel services * piix_init_one - Register PIIX ATA PCI device with kernel services
* @pdev: PCI device to register * @pdev: PCI device to register
...@@ -677,9 +841,9 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev) ...@@ -677,9 +841,9 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev)
static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
{ {
static int printed_version; static int printed_version;
struct ata_port_info *port_info[2]; struct ata_port_info port_info[2];
unsigned int combined = 0; struct ata_port_info *ppinfo[2] = { &port_info[0], &port_info[1] };
unsigned int pata_chan = 0, sata_chan = 0; unsigned long host_flags;
if (!printed_version++) if (!printed_version++)
dev_printk(KERN_DEBUG, &pdev->dev, dev_printk(KERN_DEBUG, &pdev->dev,
...@@ -689,10 +853,12 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -689,10 +853,12 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
if (!in_module_init) if (!in_module_init)
return -ENODEV; return -ENODEV;
port_info[0] = &piix_port_info[ent->driver_data]; port_info[0] = piix_port_info[ent->driver_data];
port_info[1] = &piix_port_info[ent->driver_data]; port_info[1] = piix_port_info[ent->driver_data];
host_flags = port_info[0].host_flags;
if (port_info[0]->host_flags & PIIX_FLAG_AHCI) { if (host_flags & PIIX_FLAG_AHCI) {
u8 tmp; u8 tmp;
pci_read_config_byte(pdev, PIIX_SCC, &tmp); pci_read_config_byte(pdev, PIIX_SCC, &tmp);
if (tmp == PIIX_AHCI_DEVICE) { if (tmp == PIIX_AHCI_DEVICE) {
...@@ -702,18 +868,9 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -702,18 +868,9 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
} }
} }
if (port_info[0]->host_flags & PIIX_FLAG_COMBINED) { /* Initialize SATA map */
u8 tmp; if (host_flags & ATA_FLAG_SATA)
pci_read_config_byte(pdev, ICH5_PMR, &tmp); piix_init_sata_map(pdev, port_info);
if (tmp & PIIX_COMB) {
combined = 1;
if (tmp & PIIX_COMB_PATA_P0)
sata_chan = 1;
else
pata_chan = 1;
}
}
/* On ICH5, some BIOSen disable the interrupt using the /* On ICH5, some BIOSen disable the interrupt using the
* PCI_COMMAND_INTX_DISABLE bit added in PCI 2.3. * PCI_COMMAND_INTX_DISABLE bit added in PCI 2.3.
...@@ -721,28 +878,19 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -721,28 +878,19 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
* MSI is disabled (and it is disabled, as we don't use * MSI is disabled (and it is disabled, as we don't use
* message-signalled interrupts currently). * message-signalled interrupts currently).
*/ */
if (port_info[0]->host_flags & PIIX_FLAG_CHECKINTR) if (host_flags & PIIX_FLAG_CHECKINTR)
pci_intx(pdev, 1); pci_intx(pdev, 1);
if (combined) {
port_info[sata_chan] = &piix_port_info[ent->driver_data];
port_info[sata_chan]->host_flags |= ATA_FLAG_SLAVE_POSS;
port_info[pata_chan] = &piix_port_info[ich5_pata];
dev_printk(KERN_WARNING, &pdev->dev,
"combined mode detected (p=%u, s=%u)\n",
pata_chan, sata_chan);
}
if (piix_check_450nx_errata(pdev)) { if (piix_check_450nx_errata(pdev)) {
/* This writes into the master table but it does not /* This writes into the master table but it does not
really matter for this errata as we will apply it to really matter for this errata as we will apply it to
all the PIIX devices on the board */ all the PIIX devices on the board */
port_info[0]->mwdma_mask = 0; port_info[0].mwdma_mask = 0;
port_info[0]->udma_mask = 0; port_info[0].udma_mask = 0;
port_info[1]->mwdma_mask = 0; port_info[1].mwdma_mask = 0;
port_info[1]->udma_mask = 0; port_info[1].udma_mask = 0;
} }
return ata_pci_init_one(pdev, port_info, 2); return ata_pci_init_one(pdev, ppinfo, 2);
} }
static int __init piix_init(void) static int __init piix_init(void)
......
/*
* libata-bmdma.c - helper library for PCI IDE BMDMA
*
* Maintained by: Jeff Garzik <jgarzik@pobox.com>
* Please ALWAYS copy linux-ide@vger.kernel.org
* on emails.
*
* Copyright 2003-2006 Red Hat, Inc. All rights reserved.
* Copyright 2003-2006 Jeff Garzik
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*
* libata documentation is available via 'make {ps|pdf}docs',
* as Documentation/DocBook/libata.*
*
* Hardware documentation available from http://www.t13.org/ and
* http://www.sata-io.org/
*
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/libata.h>
#include "libata.h"
/**
* ata_tf_load_pio - send taskfile registers to host controller
* @ap: Port to which output is sent
* @tf: ATA taskfile register set
*
* Outputs ATA taskfile to standard ATA host controller.
*
* LOCKING:
* Inherited from caller.
*/
static void ata_tf_load_pio(struct ata_port *ap, const struct ata_taskfile *tf)
{
struct ata_ioports *ioaddr = &ap->ioaddr;
unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
if (tf->ctl != ap->last_ctl) {
outb(tf->ctl, ioaddr->ctl_addr);
ap->last_ctl = tf->ctl;
ata_wait_idle(ap);
}
if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
outb(tf->hob_feature, ioaddr->feature_addr);
outb(tf->hob_nsect, ioaddr->nsect_addr);
outb(tf->hob_lbal, ioaddr->lbal_addr);
outb(tf->hob_lbam, ioaddr->lbam_addr);
outb(tf->hob_lbah, ioaddr->lbah_addr);
VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n",
tf->hob_feature,
tf->hob_nsect,
tf->hob_lbal,
tf->hob_lbam,
tf->hob_lbah);
}
if (is_addr) {
outb(tf->feature, ioaddr->feature_addr);
outb(tf->nsect, ioaddr->nsect_addr);
outb(tf->lbal, ioaddr->lbal_addr);
outb(tf->lbam, ioaddr->lbam_addr);
outb(tf->lbah, ioaddr->lbah_addr);
VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n",
tf->feature,
tf->nsect,
tf->lbal,
tf->lbam,
tf->lbah);
}
if (tf->flags & ATA_TFLAG_DEVICE) {
outb(tf->device, ioaddr->device_addr);
VPRINTK("device 0x%X\n", tf->device);
}
ata_wait_idle(ap);
}
/**
* ata_tf_load_mmio - send taskfile registers to host controller
* @ap: Port to which output is sent
* @tf: ATA taskfile register set
*
* Outputs ATA taskfile to standard ATA host controller using MMIO.
*
* LOCKING:
* Inherited from caller.
*/
static void ata_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
{
struct ata_ioports *ioaddr = &ap->ioaddr;
unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
if (tf->ctl != ap->last_ctl) {
writeb(tf->ctl, (void __iomem *) ap->ioaddr.ctl_addr);
ap->last_ctl = tf->ctl;
ata_wait_idle(ap);
}
if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
writeb(tf->hob_feature, (void __iomem *) ioaddr->feature_addr);
writeb(tf->hob_nsect, (void __iomem *) ioaddr->nsect_addr);
writeb(tf->hob_lbal, (void __iomem *) ioaddr->lbal_addr);
writeb(tf->hob_lbam, (void __iomem *) ioaddr->lbam_addr);
writeb(tf->hob_lbah, (void __iomem *) ioaddr->lbah_addr);
VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n",
tf->hob_feature,
tf->hob_nsect,
tf->hob_lbal,
tf->hob_lbam,
tf->hob_lbah);
}
if (is_addr) {
writeb(tf->feature, (void __iomem *) ioaddr->feature_addr);
writeb(tf->nsect, (void __iomem *) ioaddr->nsect_addr);
writeb(tf->lbal, (void __iomem *) ioaddr->lbal_addr);
writeb(tf->lbam, (void __iomem *) ioaddr->lbam_addr);
writeb(tf->lbah, (void __iomem *) ioaddr->lbah_addr);
VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n",
tf->feature,
tf->nsect,
tf->lbal,
tf->lbam,
tf->lbah);
}
if (tf->flags & ATA_TFLAG_DEVICE) {
writeb(tf->device, (void __iomem *) ioaddr->device_addr);
VPRINTK("device 0x%X\n", tf->device);
}
ata_wait_idle(ap);
}
/**
* ata_tf_load - send taskfile registers to host controller
* @ap: Port to which output is sent
* @tf: ATA taskfile register set
*
* Outputs ATA taskfile to standard ATA host controller using MMIO
* or PIO as indicated by the ATA_FLAG_MMIO flag.
* Writes the control, feature, nsect, lbal, lbam, and lbah registers.
* Optionally (ATA_TFLAG_LBA48) writes hob_feature, hob_nsect,
* hob_lbal, hob_lbam, and hob_lbah.
*
* This function waits for idle (!BUSY and !DRQ) after writing
* registers. If the control register has a new value, this
* function also waits for idle after writing control and before
* writing the remaining registers.
*
* May be used as the tf_load() entry in ata_port_operations.
*
* LOCKING:
* Inherited from caller.
*/
void ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
{
if (ap->flags & ATA_FLAG_MMIO)
ata_tf_load_mmio(ap, tf);
else
ata_tf_load_pio(ap, tf);
}
/**
* ata_exec_command_pio - issue ATA command to host controller
* @ap: port to which command is being issued
* @tf: ATA taskfile register set
*
* Issues PIO write to ATA command register, with proper
* synchronization with interrupt handler / other threads.
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
*/
static void ata_exec_command_pio(struct ata_port *ap, const struct ata_taskfile *tf)
{
DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command);
outb(tf->command, ap->ioaddr.command_addr);
ata_pause(ap);
}
/**
* ata_exec_command_mmio - issue ATA command to host controller
* @ap: port to which command is being issued
* @tf: ATA taskfile register set
*
* Issues MMIO write to ATA command register, with proper
* synchronization with interrupt handler / other threads.
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
*/
static void ata_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
{
DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command);
writeb(tf->command, (void __iomem *) ap->ioaddr.command_addr);
ata_pause(ap);
}
/**
* ata_exec_command - issue ATA command to host controller
* @ap: port to which command is being issued
* @tf: ATA taskfile register set
*
* Issues PIO/MMIO write to ATA command register, with proper
* synchronization with interrupt handler / other threads.
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
*/
void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf)
{
if (ap->flags & ATA_FLAG_MMIO)
ata_exec_command_mmio(ap, tf);
else
ata_exec_command_pio(ap, tf);
}
/**
* ata_tf_read_pio - input device's ATA taskfile shadow registers
* @ap: Port from which input is read
* @tf: ATA taskfile register set for storing input
*
* Reads ATA taskfile registers for currently-selected device
* into @tf.
*
* LOCKING:
* Inherited from caller.
*/
static void ata_tf_read_pio(struct ata_port *ap, struct ata_taskfile *tf)
{
struct ata_ioports *ioaddr = &ap->ioaddr;
tf->command = ata_check_status(ap);
tf->feature = inb(ioaddr->error_addr);
tf->nsect = inb(ioaddr->nsect_addr);
tf->lbal = inb(ioaddr->lbal_addr);
tf->lbam = inb(ioaddr->lbam_addr);
tf->lbah = inb(ioaddr->lbah_addr);
tf->device = inb(ioaddr->device_addr);
if (tf->flags & ATA_TFLAG_LBA48) {
outb(tf->ctl | ATA_HOB, ioaddr->ctl_addr);
tf->hob_feature = inb(ioaddr->error_addr);
tf->hob_nsect = inb(ioaddr->nsect_addr);
tf->hob_lbal = inb(ioaddr->lbal_addr);
tf->hob_lbam = inb(ioaddr->lbam_addr);
tf->hob_lbah = inb(ioaddr->lbah_addr);
}
}
/**
* ata_tf_read_mmio - input device's ATA taskfile shadow registers
* @ap: Port from which input is read
* @tf: ATA taskfile register set for storing input
*
* Reads ATA taskfile registers for currently-selected device
* into @tf via MMIO.
*
* LOCKING:
* Inherited from caller.
*/
static void ata_tf_read_mmio(struct ata_port *ap, struct ata_taskfile *tf)
{
struct ata_ioports *ioaddr = &ap->ioaddr;
tf->command = ata_check_status(ap);
tf->feature = readb((void __iomem *)ioaddr->error_addr);
tf->nsect = readb((void __iomem *)ioaddr->nsect_addr);
tf->lbal = readb((void __iomem *)ioaddr->lbal_addr);
tf->lbam = readb((void __iomem *)ioaddr->lbam_addr);
tf->lbah = readb((void __iomem *)ioaddr->lbah_addr);
tf->device = readb((void __iomem *)ioaddr->device_addr);
if (tf->flags & ATA_TFLAG_LBA48) {
writeb(tf->ctl | ATA_HOB, (void __iomem *) ap->ioaddr.ctl_addr);
tf->hob_feature = readb((void __iomem *)ioaddr->error_addr);
tf->hob_nsect = readb((void __iomem *)ioaddr->nsect_addr);
tf->hob_lbal = readb((void __iomem *)ioaddr->lbal_addr);
tf->hob_lbam = readb((void __iomem *)ioaddr->lbam_addr);
tf->hob_lbah = readb((void __iomem *)ioaddr->lbah_addr);
}
}
/**
* ata_tf_read - input device's ATA taskfile shadow registers
* @ap: Port from which input is read
* @tf: ATA taskfile register set for storing input
*
* Reads ATA taskfile registers for currently-selected device
* into @tf.
*
* Reads nsect, lbal, lbam, lbah, and device. If ATA_TFLAG_LBA48
* is set, also reads the hob registers.
*
* May be used as the tf_read() entry in ata_port_operations.
*
* LOCKING:
* Inherited from caller.
*/
void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
{
if (ap->flags & ATA_FLAG_MMIO)
ata_tf_read_mmio(ap, tf);
else
ata_tf_read_pio(ap, tf);
}
/**
* ata_check_status_pio - Read device status reg & clear interrupt
* @ap: port where the device is
*
* Reads ATA taskfile status register for currently-selected device
* and return its value. This also clears pending interrupts
* from this device
*
* LOCKING:
* Inherited from caller.
*/
static u8 ata_check_status_pio(struct ata_port *ap)
{
return inb(ap->ioaddr.status_addr);
}
/**
* ata_check_status_mmio - Read device status reg & clear interrupt
* @ap: port where the device is
*
* Reads ATA taskfile status register for currently-selected device
* via MMIO and return its value. This also clears pending interrupts
* from this device
*
* LOCKING:
* Inherited from caller.
*/
static u8 ata_check_status_mmio(struct ata_port *ap)
{
return readb((void __iomem *) ap->ioaddr.status_addr);
}
/**
* ata_check_status - Read device status reg & clear interrupt
* @ap: port where the device is
*
* Reads ATA taskfile status register for currently-selected device
* and return its value. This also clears pending interrupts
* from this device
*
* May be used as the check_status() entry in ata_port_operations.
*
* LOCKING:
* Inherited from caller.
*/
u8 ata_check_status(struct ata_port *ap)
{
if (ap->flags & ATA_FLAG_MMIO)
return ata_check_status_mmio(ap);
return ata_check_status_pio(ap);
}
/**
* ata_altstatus - Read device alternate status reg
* @ap: port where the device is
*
* Reads ATA taskfile alternate status register for
* currently-selected device and return its value.
*
* Note: may NOT be used as the check_altstatus() entry in
* ata_port_operations.
*
* LOCKING:
* Inherited from caller.
*/
u8 ata_altstatus(struct ata_port *ap)
{
if (ap->ops->check_altstatus)
return ap->ops->check_altstatus(ap);
if (ap->flags & ATA_FLAG_MMIO)
return readb((void __iomem *)ap->ioaddr.altstatus_addr);
return inb(ap->ioaddr.altstatus_addr);
}
#ifdef CONFIG_PCI
static struct ata_probe_ent *
ata_probe_ent_alloc(struct device *dev, const struct ata_port_info *port)
{
struct ata_probe_ent *probe_ent;
probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL);
if (!probe_ent) {
printk(KERN_ERR DRV_NAME "(%s): out of memory\n",
kobject_name(&(dev->kobj)));
return NULL;
}
INIT_LIST_HEAD(&probe_ent->node);
probe_ent->dev = dev;
probe_ent->sht = port->sht;
probe_ent->host_flags = port->host_flags;
probe_ent->pio_mask = port->pio_mask;
probe_ent->mwdma_mask = port->mwdma_mask;
probe_ent->udma_mask = port->udma_mask;
probe_ent->port_ops = port->port_ops;
return probe_ent;
}
/**
* ata_pci_init_native_mode - Initialize native-mode driver
* @pdev: pci device to be initialized
* @port: array[2] of pointers to port info structures.
* @ports: bitmap of ports present
*
* Utility function which allocates and initializes an
* ata_probe_ent structure for a standard dual-port
* PIO-based IDE controller. The returned ata_probe_ent
* structure can be passed to ata_device_add(). The returned
* ata_probe_ent structure should then be freed with kfree().
*
* The caller need only pass the address of the primary port, the
* secondary will be deduced automatically. If the device has non
* standard secondary port mappings this function can be called twice,
* once for each interface.
*/
struct ata_probe_ent *
ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int ports)
{
struct ata_probe_ent *probe_ent =
ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]);
int p = 0;
if (!probe_ent)
return NULL;
probe_ent->irq = pdev->irq;
probe_ent->irq_flags = SA_SHIRQ;
probe_ent->private_data = port[0]->private_data;
if (ports & ATA_PORT_PRIMARY) {
probe_ent->port[p].cmd_addr = pci_resource_start(pdev, 0);
probe_ent->port[p].altstatus_addr =
probe_ent->port[p].ctl_addr =
pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
probe_ent->port[p].bmdma_addr = pci_resource_start(pdev, 4);
ata_std_ports(&probe_ent->port[p]);
p++;
}
if (ports & ATA_PORT_SECONDARY) {
probe_ent->port[p].cmd_addr = pci_resource_start(pdev, 2);
probe_ent->port[p].altstatus_addr =
probe_ent->port[p].ctl_addr =
pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
probe_ent->port[p].bmdma_addr = pci_resource_start(pdev, 4) + 8;
ata_std_ports(&probe_ent->port[p]);
p++;
}
probe_ent->n_ports = p;
return probe_ent;
}
static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev,
struct ata_port_info *port, int port_num)
{
struct ata_probe_ent *probe_ent;
probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port);
if (!probe_ent)
return NULL;
probe_ent->legacy_mode = 1;
probe_ent->n_ports = 1;
probe_ent->hard_port_no = port_num;
probe_ent->private_data = port->private_data;
switch(port_num)
{
case 0:
probe_ent->irq = 14;
probe_ent->port[0].cmd_addr = 0x1f0;
probe_ent->port[0].altstatus_addr =
probe_ent->port[0].ctl_addr = 0x3f6;
break;
case 1:
probe_ent->irq = 15;
probe_ent->port[0].cmd_addr = 0x170;
probe_ent->port[0].altstatus_addr =
probe_ent->port[0].ctl_addr = 0x376;
break;
}
probe_ent->port[0].bmdma_addr =
pci_resource_start(pdev, 4) + 8 * port_num;
ata_std_ports(&probe_ent->port[0]);
return probe_ent;
}
/**
* ata_pci_init_one - Initialize/register PCI IDE host controller
* @pdev: Controller to be initialized
* @port_info: Information from low-level host driver
* @n_ports: Number of ports attached to host controller
*
* This is a helper function which can be called from a driver's
* xxx_init_one() probe function if the hardware uses traditional
* IDE taskfile registers.
*
* This function calls pci_enable_device(), reserves its register
* regions, sets the dma mask, enables bus master mode, and calls
* ata_device_add()
*
* LOCKING:
* Inherited from PCI layer (may sleep).
*
* RETURNS:
* Zero on success, negative on errno-based value on error.
*/
int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
unsigned int n_ports)
{
struct ata_probe_ent *probe_ent = NULL, *probe_ent2 = NULL;
struct ata_port_info *port[2];
u8 tmp8, mask;
unsigned int legacy_mode = 0;
int disable_dev_on_err = 1;
int rc;
DPRINTK("ENTER\n");
port[0] = port_info[0];
if (n_ports > 1)
port[1] = port_info[1];
else
port[1] = port[0];
if ((port[0]->host_flags & ATA_FLAG_NO_LEGACY) == 0
&& (pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
/* TODO: What if one channel is in native mode ... */
pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8);
mask = (1 << 2) | (1 << 0);
if ((tmp8 & mask) != mask)
legacy_mode = (1 << 3);
}
/* FIXME... */
if ((!legacy_mode) && (n_ports > 2)) {
printk(KERN_ERR "ata: BUG: native mode, n_ports > 2\n");
n_ports = 2;
/* For now */
}
/* FIXME: Really for ATA it isn't safe because the device may be
multi-purpose and we want to leave it alone if it was already
enabled. Secondly for shared use as Arjan says we want refcounting
Checking dev->is_enabled is insufficient as this is not set at
boot for the primary video which is BIOS enabled
*/
rc = pci_enable_device(pdev);
if (rc)
return rc;
rc = pci_request_regions(pdev, DRV_NAME);
if (rc) {
disable_dev_on_err = 0;
goto err_out;
}
/* FIXME: Should use platform specific mappers for legacy port ranges */
if (legacy_mode) {
if (!request_region(0x1f0, 8, "libata")) {
struct resource *conflict, res;
res.start = 0x1f0;
res.end = 0x1f0 + 8 - 1;
conflict = ____request_resource(&ioport_resource, &res);
if (!strcmp(conflict->name, "libata"))
legacy_mode |= (1 << 0);
else {
disable_dev_on_err = 0;
printk(KERN_WARNING "ata: 0x1f0 IDE port busy\n");
}
} else
legacy_mode |= (1 << 0);
if (!request_region(0x170, 8, "libata")) {
struct resource *conflict, res;
res.start = 0x170;
res.end = 0x170 + 8 - 1;
conflict = ____request_resource(&ioport_resource, &res);
if (!strcmp(conflict->name, "libata"))
legacy_mode |= (1 << 1);
else {
disable_dev_on_err = 0;
printk(KERN_WARNING "ata: 0x170 IDE port busy\n");
}
} else
legacy_mode |= (1 << 1);
}
/* we have legacy mode, but all ports are unavailable */
if (legacy_mode == (1 << 3)) {
rc = -EBUSY;
goto err_out_regions;
}
rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
if (rc)
goto err_out_regions;
rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
if (rc)
goto err_out_regions;
if (legacy_mode) {
if (legacy_mode & (1 << 0))
probe_ent = ata_pci_init_legacy_port(pdev, port[0], 0);
if (legacy_mode & (1 << 1))
probe_ent2 = ata_pci_init_legacy_port(pdev, port[1], 1);
} else {
if (n_ports == 2)
probe_ent = ata_pci_init_native_mode(pdev, port, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
else
probe_ent = ata_pci_init_native_mode(pdev, port, ATA_PORT_PRIMARY);
}
if (!probe_ent && !probe_ent2) {
rc = -ENOMEM;
goto err_out_regions;
}
pci_set_master(pdev);
/* FIXME: check ata_device_add return */
if (legacy_mode) {
if (legacy_mode & (1 << 0))
ata_device_add(probe_ent);
if (legacy_mode & (1 << 1))
ata_device_add(probe_ent2);
} else
ata_device_add(probe_ent);
kfree(probe_ent);
kfree(probe_ent2);
return 0;
err_out_regions:
if (legacy_mode & (1 << 0))
release_region(0x1f0, 8);
if (legacy_mode & (1 << 1))
release_region(0x170, 8);
pci_release_regions(pdev);
err_out:
if (disable_dev_on_err)
pci_disable_device(pdev);
return rc;
}
#endif /* CONFIG_PCI */
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -151,7 +151,7 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg) ...@@ -151,7 +151,7 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg)
struct scsi_sense_hdr sshdr; struct scsi_sense_hdr sshdr;
enum dma_data_direction data_dir; enum dma_data_direction data_dir;
if (NULL == (void *)arg) if (arg == NULL)
return -EINVAL; return -EINVAL;
if (copy_from_user(args, arg, sizeof(args))) if (copy_from_user(args, arg, sizeof(args)))
...@@ -201,7 +201,7 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg) ...@@ -201,7 +201,7 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg)
/* Need code to retrieve data from check condition? */ /* Need code to retrieve data from check condition? */
if ((argbuf) if ((argbuf)
&& copy_to_user((void *)(arg + sizeof(args)), argbuf, argsize)) && copy_to_user(arg + sizeof(args), argbuf, argsize))
rc = -EFAULT; rc = -EFAULT;
error: error:
if (argbuf) if (argbuf)
...@@ -228,7 +228,7 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg) ...@@ -228,7 +228,7 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg)
u8 args[7]; u8 args[7];
struct scsi_sense_hdr sshdr; struct scsi_sense_hdr sshdr;
if (NULL == (void *)arg) if (arg == NULL)
return -EINVAL; return -EINVAL;
if (copy_from_user(args, arg, sizeof(args))) if (copy_from_user(args, arg, sizeof(args)))
...@@ -553,7 +553,7 @@ void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc) ...@@ -553,7 +553,7 @@ void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc)
/* /*
* Read the controller registers. * Read the controller registers.
*/ */
assert(NULL != qc->ap->ops->tf_read); WARN_ON(qc->ap->ops->tf_read == NULL);
qc->ap->ops->tf_read(qc->ap, tf); qc->ap->ops->tf_read(qc->ap, tf);
/* /*
...@@ -628,7 +628,7 @@ void ata_gen_fixed_sense(struct ata_queued_cmd *qc) ...@@ -628,7 +628,7 @@ void ata_gen_fixed_sense(struct ata_queued_cmd *qc)
/* /*
* Read the controller registers. * Read the controller registers.
*/ */
assert(NULL != qc->ap->ops->tf_read); WARN_ON(qc->ap->ops->tf_read == NULL);
qc->ap->ops->tf_read(qc->ap, tf); qc->ap->ops->tf_read(qc->ap, tf);
/* /*
...@@ -684,23 +684,23 @@ int ata_scsi_slave_config(struct scsi_device *sdev) ...@@ -684,23 +684,23 @@ int ata_scsi_slave_config(struct scsi_device *sdev)
if (sdev->id < ATA_MAX_DEVICES) { if (sdev->id < ATA_MAX_DEVICES) {
struct ata_port *ap; struct ata_port *ap;
struct ata_device *dev; struct ata_device *dev;
unsigned int max_sectors;
ap = (struct ata_port *) &sdev->host->hostdata[0]; ap = (struct ata_port *) &sdev->host->hostdata[0];
dev = &ap->device[sdev->id]; dev = &ap->device[sdev->id];
/* TODO: 1024 is an arbitrary number, not the /* TODO: 2048 is an arbitrary number, not the
* hardware maximum. This should be increased to * hardware maximum. This should be increased to
* 65534 when Jens Axboe's patch for dynamically * 65534 when Jens Axboe's patch for dynamically
* determining max_sectors is merged. * determining max_sectors is merged.
*/ */
if ((dev->flags & ATA_DFLAG_LBA48) && max_sectors = ATA_MAX_SECTORS;
((dev->flags & ATA_DFLAG_LOCK_SECTORS) == 0)) { if (dev->flags & ATA_DFLAG_LBA48)
/* max_sectors = 2048;
* do not overwrite sdev->host->max_sectors, since if (dev->max_sectors)
* other drives on this host may not support LBA48 max_sectors = dev->max_sectors;
*/
blk_queue_max_sectors(sdev->request_queue, 2048); blk_queue_max_sectors(sdev->request_queue, max_sectors);
}
/* /*
* SATA DMA transfers must be multiples of 4 byte, so * SATA DMA transfers must be multiples of 4 byte, so
...@@ -716,6 +716,47 @@ int ata_scsi_slave_config(struct scsi_device *sdev) ...@@ -716,6 +716,47 @@ int ata_scsi_slave_config(struct scsi_device *sdev)
return 0; /* scsi layer doesn't check return value, sigh */ return 0; /* scsi layer doesn't check return value, sigh */
} }
/**
* ata_scsi_timed_out - SCSI layer time out callback
* @cmd: timed out SCSI command
*
* Handles SCSI layer timeout. We race with normal completion of
* the qc for @cmd. If the qc is already gone, we lose and let
* the scsi command finish (EH_HANDLED). Otherwise, the qc has
* timed out and EH should be invoked. Prevent ata_qc_complete()
* from finishing it by setting EH_SCHEDULED and return
* EH_NOT_HANDLED.
*
* LOCKING:
* Called from timer context
*
* RETURNS:
* EH_HANDLED or EH_NOT_HANDLED
*/
enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd)
{
struct Scsi_Host *host = cmd->device->host;
struct ata_port *ap = (struct ata_port *) &host->hostdata[0];
unsigned long flags;
struct ata_queued_cmd *qc;
enum scsi_eh_timer_return ret = EH_HANDLED;
DPRINTK("ENTER\n");
spin_lock_irqsave(&ap->host_set->lock, flags);
qc = ata_qc_from_tag(ap, ap->active_tag);
if (qc) {
WARN_ON(qc->scsicmd != cmd);
qc->flags |= ATA_QCFLAG_EH_SCHEDULED;
qc->err_mask |= AC_ERR_TIMEOUT;
ret = EH_NOT_HANDLED;
}
spin_unlock_irqrestore(&ap->host_set->lock, flags);
DPRINTK("EXIT, ret=%d\n", ret);
return ret;
}
/** /**
* ata_scsi_error - SCSI layer error handler callback * ata_scsi_error - SCSI layer error handler callback
* @host: SCSI host on which error occurred * @host: SCSI host on which error occurred
...@@ -732,23 +773,84 @@ int ata_scsi_slave_config(struct scsi_device *sdev) ...@@ -732,23 +773,84 @@ int ata_scsi_slave_config(struct scsi_device *sdev)
int ata_scsi_error(struct Scsi_Host *host) int ata_scsi_error(struct Scsi_Host *host)
{ {
struct ata_port *ap; struct ata_port *ap;
unsigned long flags;
DPRINTK("ENTER\n"); DPRINTK("ENTER\n");
ap = (struct ata_port *) &host->hostdata[0]; ap = (struct ata_port *) &host->hostdata[0];
spin_lock_irqsave(&ap->host_set->lock, flags);
WARN_ON(ap->flags & ATA_FLAG_IN_EH);
ap->flags |= ATA_FLAG_IN_EH;
WARN_ON(ata_qc_from_tag(ap, ap->active_tag) == NULL);
spin_unlock_irqrestore(&ap->host_set->lock, flags);
ata_port_flush_task(ap);
ap->ops->eng_timeout(ap); ap->ops->eng_timeout(ap);
/* TODO: this is per-command; when queueing is supported WARN_ON(host->host_failed || !list_empty(&host->eh_cmd_q));
* this code will either change or move to a more
* appropriate place scsi_eh_flush_done_q(&ap->eh_done_q);
*/
host->host_failed--; spin_lock_irqsave(&ap->host_set->lock, flags);
INIT_LIST_HEAD(&host->eh_cmd_q); ap->flags &= ~ATA_FLAG_IN_EH;
spin_unlock_irqrestore(&ap->host_set->lock, flags);
DPRINTK("EXIT\n"); DPRINTK("EXIT\n");
return 0; return 0;
} }
static void ata_eh_scsidone(struct scsi_cmnd *scmd)
{
/* nada */
}
static void __ata_eh_qc_complete(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
struct scsi_cmnd *scmd = qc->scsicmd;
unsigned long flags;
spin_lock_irqsave(&ap->host_set->lock, flags);
qc->scsidone = ata_eh_scsidone;
__ata_qc_complete(qc);
WARN_ON(ata_tag_valid(qc->tag));
spin_unlock_irqrestore(&ap->host_set->lock, flags);
scsi_eh_finish_cmd(scmd, &ap->eh_done_q);
}
/**
* ata_eh_qc_complete - Complete an active ATA command from EH
* @qc: Command to complete
*
* Indicate to the mid and upper layers that an ATA command has
* completed. To be used from EH.
*/
void ata_eh_qc_complete(struct ata_queued_cmd *qc)
{
struct scsi_cmnd *scmd = qc->scsicmd;
scmd->retries = scmd->allowed;
__ata_eh_qc_complete(qc);
}
/**
* ata_eh_qc_retry - Tell midlayer to retry an ATA command after EH
* @qc: Command to retry
*
* Indicate to the mid and upper layers that an ATA command
* should be retried. To be used from EH.
*
* SCSI midlayer limits the number of retries to scmd->allowed.
* This function might need to adjust scmd->retries for commands
* which get retried due to unrelated NCQ failures.
*/
void ata_eh_qc_retry(struct ata_queued_cmd *qc)
{
__ata_eh_qc_complete(qc);
}
/** /**
* ata_scsi_start_stop_xlat - Translate SCSI START STOP UNIT command * ata_scsi_start_stop_xlat - Translate SCSI START STOP UNIT command
* @qc: Storage for translated ATA taskfile * @qc: Storage for translated ATA taskfile
...@@ -985,9 +1087,13 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, const u8 *sc ...@@ -985,9 +1087,13 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, const u8 *sc
if (dev->flags & ATA_DFLAG_LBA) { if (dev->flags & ATA_DFLAG_LBA) {
tf->flags |= ATA_TFLAG_LBA; tf->flags |= ATA_TFLAG_LBA;
if (dev->flags & ATA_DFLAG_LBA48) { if (lba_28_ok(block, n_block)) {
if (n_block > (64 * 1024)) /* use LBA28 */
goto invalid_fld; tf->command = ATA_CMD_VERIFY;
tf->device |= (block >> 24) & 0xf;
} else if (lba_48_ok(block, n_block)) {
if (!(dev->flags & ATA_DFLAG_LBA48))
goto out_of_range;
/* use LBA48 */ /* use LBA48 */
tf->flags |= ATA_TFLAG_LBA48; tf->flags |= ATA_TFLAG_LBA48;
...@@ -998,15 +1104,9 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, const u8 *sc ...@@ -998,15 +1104,9 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, const u8 *sc
tf->hob_lbah = (block >> 40) & 0xff; tf->hob_lbah = (block >> 40) & 0xff;
tf->hob_lbam = (block >> 32) & 0xff; tf->hob_lbam = (block >> 32) & 0xff;
tf->hob_lbal = (block >> 24) & 0xff; tf->hob_lbal = (block >> 24) & 0xff;
} else { } else
if (n_block > 256) /* request too large even for LBA48 */
goto invalid_fld; goto out_of_range;
/* use LBA28 */
tf->command = ATA_CMD_VERIFY;
tf->device |= (block >> 24) & 0xf;
}
tf->nsect = n_block & 0xff; tf->nsect = n_block & 0xff;
...@@ -1019,8 +1119,8 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, const u8 *sc ...@@ -1019,8 +1119,8 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, const u8 *sc
/* CHS */ /* CHS */
u32 sect, head, cyl, track; u32 sect, head, cyl, track;
if (n_block > 256) if (!lba_28_ok(block, n_block))
goto invalid_fld; goto out_of_range;
/* Convert LBA to CHS */ /* Convert LBA to CHS */
track = (u32)block / dev->sectors; track = (u32)block / dev->sectors;
...@@ -1139,9 +1239,11 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm ...@@ -1139,9 +1239,11 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
if (dev->flags & ATA_DFLAG_LBA) { if (dev->flags & ATA_DFLAG_LBA) {
tf->flags |= ATA_TFLAG_LBA; tf->flags |= ATA_TFLAG_LBA;
if (dev->flags & ATA_DFLAG_LBA48) { if (lba_28_ok(block, n_block)) {
/* The request -may- be too large for LBA48. */ /* use LBA28 */
if ((block >> 48) || (n_block > 65536)) tf->device |= (block >> 24) & 0xf;
} else if (lba_48_ok(block, n_block)) {
if (!(dev->flags & ATA_DFLAG_LBA48))
goto out_of_range; goto out_of_range;
/* use LBA48 */ /* use LBA48 */
...@@ -1152,15 +1254,9 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm ...@@ -1152,15 +1254,9 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
tf->hob_lbah = (block >> 40) & 0xff; tf->hob_lbah = (block >> 40) & 0xff;
tf->hob_lbam = (block >> 32) & 0xff; tf->hob_lbam = (block >> 32) & 0xff;
tf->hob_lbal = (block >> 24) & 0xff; tf->hob_lbal = (block >> 24) & 0xff;
} else { } else
/* use LBA28 */ /* request too large even for LBA48 */
goto out_of_range;
/* The request -may- be too large for LBA28. */
if ((block >> 28) || (n_block > 256))
goto out_of_range;
tf->device |= (block >> 24) & 0xf;
}
if (unlikely(ata_rwcmd_protocol(qc) < 0)) if (unlikely(ata_rwcmd_protocol(qc) < 0))
goto invalid_fld; goto invalid_fld;
...@@ -1178,7 +1274,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm ...@@ -1178,7 +1274,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
u32 sect, head, cyl, track; u32 sect, head, cyl, track;
/* The request -may- be too large for CHS addressing. */ /* The request -may- be too large for CHS addressing. */
if ((block >> 28) || (n_block > 256)) if (!lba_28_ok(block, n_block))
goto out_of_range; goto out_of_range;
if (unlikely(ata_rwcmd_protocol(qc) < 0)) if (unlikely(ata_rwcmd_protocol(qc) < 0))
...@@ -1225,7 +1321,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm ...@@ -1225,7 +1321,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
return 1; return 1;
} }
static int ata_scsi_qc_complete(struct ata_queued_cmd *qc) static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
{ {
struct scsi_cmnd *cmd = qc->scsicmd; struct scsi_cmnd *cmd = qc->scsicmd;
u8 *cdb = cmd->cmnd; u8 *cdb = cmd->cmnd;
...@@ -1262,7 +1358,7 @@ static int ata_scsi_qc_complete(struct ata_queued_cmd *qc) ...@@ -1262,7 +1358,7 @@ static int ata_scsi_qc_complete(struct ata_queued_cmd *qc)
qc->scsidone(cmd); qc->scsidone(cmd);
return 0; ata_qc_free(qc);
} }
/** /**
...@@ -1328,8 +1424,9 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev, ...@@ -1328,8 +1424,9 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev,
goto early_finish; goto early_finish;
/* select device, send command to hardware */ /* select device, send command to hardware */
if (ata_qc_issue(qc)) qc->err_mask = ata_qc_issue(qc);
goto err_did; if (qc->err_mask)
ata_qc_complete(qc);
VPRINTK("EXIT\n"); VPRINTK("EXIT\n");
return; return;
...@@ -1472,8 +1569,8 @@ unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf, ...@@ -1472,8 +1569,8 @@ unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
if (buflen > 35) { if (buflen > 35) {
memcpy(&rbuf[8], "ATA ", 8); memcpy(&rbuf[8], "ATA ", 8);
ata_dev_id_string(args->id, &rbuf[16], ATA_ID_PROD_OFS, 16); ata_id_string(args->id, &rbuf[16], ATA_ID_PROD_OFS, 16);
ata_dev_id_string(args->id, &rbuf[32], ATA_ID_FW_REV_OFS, 4); ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV_OFS, 4);
if (rbuf[32] == 0 || rbuf[32] == ' ') if (rbuf[32] == 0 || rbuf[32] == ' ')
memcpy(&rbuf[32], "n/a ", 4); memcpy(&rbuf[32], "n/a ", 4);
} }
...@@ -1547,8 +1644,8 @@ unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf, ...@@ -1547,8 +1644,8 @@ unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf,
memcpy(rbuf, hdr, sizeof(hdr)); memcpy(rbuf, hdr, sizeof(hdr));
if (buflen > (ATA_SERNO_LEN + 4 - 1)) if (buflen > (ATA_SERNO_LEN + 4 - 1))
ata_dev_id_string(args->id, (unsigned char *) &rbuf[4], ata_id_string(args->id, (unsigned char *) &rbuf[4],
ATA_ID_SERNO_OFS, ATA_SERNO_LEN); ATA_ID_SERNO_OFS, ATA_SERNO_LEN);
return 0; return 0;
} }
...@@ -1713,15 +1810,12 @@ static int ata_dev_supports_fua(u16 *id) ...@@ -1713,15 +1810,12 @@ static int ata_dev_supports_fua(u16 *id)
if (!ata_id_has_fua(id)) if (!ata_id_has_fua(id))
return 0; return 0;
model[40] = '\0'; ata_id_c_string(id, model, ATA_ID_PROD_OFS, sizeof(model));
fw[8] = '\0'; ata_id_c_string(id, fw, ATA_ID_FW_REV_OFS, sizeof(fw));
ata_dev_id_string(id, model, ATA_ID_PROD_OFS, sizeof(model) - 1);
ata_dev_id_string(id, fw, ATA_ID_FW_REV_OFS, sizeof(fw) - 1);
if (strncmp(model, "Maxtor", 6)) if (strcmp(model, "Maxtor"))
return 1; return 1;
if (strncmp(fw, "BANC1G10", 8)) if (strcmp(fw, "BANC1G10"))
return 1; return 1;
return 0; /* blacklisted */ return 0; /* blacklisted */
...@@ -2015,7 +2109,7 @@ void ata_scsi_badcmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), u8 ...@@ -2015,7 +2109,7 @@ void ata_scsi_badcmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), u8
done(cmd); done(cmd);
} }
static int atapi_sense_complete(struct ata_queued_cmd *qc) static void atapi_sense_complete(struct ata_queued_cmd *qc)
{ {
if (qc->err_mask && ((qc->err_mask & AC_ERR_DEV) == 0)) if (qc->err_mask && ((qc->err_mask & AC_ERR_DEV) == 0))
/* FIXME: not quite right; we don't want the /* FIXME: not quite right; we don't want the
...@@ -2026,7 +2120,7 @@ static int atapi_sense_complete(struct ata_queued_cmd *qc) ...@@ -2026,7 +2120,7 @@ static int atapi_sense_complete(struct ata_queued_cmd *qc)
ata_gen_ata_desc_sense(qc); ata_gen_ata_desc_sense(qc);
qc->scsidone(qc->scsicmd); qc->scsidone(qc->scsicmd);
return 0; ata_qc_free(qc);
} }
/* is it pointless to prefer PIO for "safety reasons"? */ /* is it pointless to prefer PIO for "safety reasons"? */
...@@ -2056,7 +2150,7 @@ static void atapi_request_sense(struct ata_queued_cmd *qc) ...@@ -2056,7 +2150,7 @@ static void atapi_request_sense(struct ata_queued_cmd *qc)
ata_sg_init_one(qc, cmd->sense_buffer, sizeof(cmd->sense_buffer)); ata_sg_init_one(qc, cmd->sense_buffer, sizeof(cmd->sense_buffer));
qc->dma_dir = DMA_FROM_DEVICE; qc->dma_dir = DMA_FROM_DEVICE;
memset(&qc->cdb, 0, ap->cdb_len); memset(&qc->cdb, 0, qc->dev->cdb_len);
qc->cdb[0] = REQUEST_SENSE; qc->cdb[0] = REQUEST_SENSE;
qc->cdb[4] = SCSI_SENSE_BUFFERSIZE; qc->cdb[4] = SCSI_SENSE_BUFFERSIZE;
...@@ -2075,15 +2169,14 @@ static void atapi_request_sense(struct ata_queued_cmd *qc) ...@@ -2075,15 +2169,14 @@ static void atapi_request_sense(struct ata_queued_cmd *qc)
qc->complete_fn = atapi_sense_complete; qc->complete_fn = atapi_sense_complete;
if (ata_qc_issue(qc)) { qc->err_mask = ata_qc_issue(qc);
qc->err_mask |= AC_ERR_OTHER; if (qc->err_mask)
ata_qc_complete(qc); ata_qc_complete(qc);
}
DPRINTK("EXIT\n"); DPRINTK("EXIT\n");
} }
static int atapi_qc_complete(struct ata_queued_cmd *qc) static void atapi_qc_complete(struct ata_queued_cmd *qc)
{ {
struct scsi_cmnd *cmd = qc->scsicmd; struct scsi_cmnd *cmd = qc->scsicmd;
unsigned int err_mask = qc->err_mask; unsigned int err_mask = qc->err_mask;
...@@ -2093,7 +2186,7 @@ static int atapi_qc_complete(struct ata_queued_cmd *qc) ...@@ -2093,7 +2186,7 @@ static int atapi_qc_complete(struct ata_queued_cmd *qc)
if (unlikely(err_mask & AC_ERR_DEV)) { if (unlikely(err_mask & AC_ERR_DEV)) {
cmd->result = SAM_STAT_CHECK_CONDITION; cmd->result = SAM_STAT_CHECK_CONDITION;
atapi_request_sense(qc); atapi_request_sense(qc);
return 1; return;
} }
else if (unlikely(err_mask)) else if (unlikely(err_mask))
...@@ -2133,7 +2226,7 @@ static int atapi_qc_complete(struct ata_queued_cmd *qc) ...@@ -2133,7 +2226,7 @@ static int atapi_qc_complete(struct ata_queued_cmd *qc)
} }
qc->scsidone(cmd); qc->scsidone(cmd);
return 0; ata_qc_free(qc);
} }
/** /**
* atapi_xlat - Initialize PACKET taskfile * atapi_xlat - Initialize PACKET taskfile
...@@ -2159,7 +2252,7 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd) ...@@ -2159,7 +2252,7 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd)
if (ata_check_atapi_dma(qc)) if (ata_check_atapi_dma(qc))
using_pio = 1; using_pio = 1;
memcpy(&qc->cdb, scsicmd, qc->ap->cdb_len); memcpy(&qc->cdb, scsicmd, dev->cdb_len);
qc->complete_fn = atapi_qc_complete; qc->complete_fn = atapi_qc_complete;
...@@ -2519,7 +2612,8 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) ...@@ -2519,7 +2612,8 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
/** /**
* ata_scsi_simulate - simulate SCSI command on ATA device * ata_scsi_simulate - simulate SCSI command on ATA device
* @id: current IDENTIFY data for target device. * @ap: port the device is connected to
* @dev: the target device
* @cmd: SCSI command being sent to device. * @cmd: SCSI command being sent to device.
* @done: SCSI command completion function. * @done: SCSI command completion function.
* *
......
...@@ -45,8 +45,9 @@ extern int libata_fua; ...@@ -45,8 +45,9 @@ extern int libata_fua;
extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
struct ata_device *dev); struct ata_device *dev);
extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc); extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc);
extern void ata_port_flush_task(struct ata_port *ap);
extern void ata_qc_free(struct ata_queued_cmd *qc); extern void ata_qc_free(struct ata_queued_cmd *qc);
extern int ata_qc_issue(struct ata_queued_cmd *qc); extern unsigned int ata_qc_issue(struct ata_queued_cmd *qc);
extern int ata_check_atapi_dma(struct ata_queued_cmd *qc); extern int ata_check_atapi_dma(struct ata_queued_cmd *qc);
extern void ata_dev_select(struct ata_port *ap, unsigned int device, extern void ata_dev_select(struct ata_port *ap, unsigned int device,
unsigned int wait, unsigned int can_sleep); unsigned int wait, unsigned int can_sleep);
......
...@@ -131,7 +131,7 @@ static void adma_host_stop(struct ata_host_set *host_set); ...@@ -131,7 +131,7 @@ static void adma_host_stop(struct ata_host_set *host_set);
static void adma_port_stop(struct ata_port *ap); static void adma_port_stop(struct ata_port *ap);
static void adma_phy_reset(struct ata_port *ap); static void adma_phy_reset(struct ata_port *ap);
static void adma_qc_prep(struct ata_queued_cmd *qc); static void adma_qc_prep(struct ata_queued_cmd *qc);
static int adma_qc_issue(struct ata_queued_cmd *qc); static unsigned int adma_qc_issue(struct ata_queued_cmd *qc);
static int adma_check_atapi_dma(struct ata_queued_cmd *qc); static int adma_check_atapi_dma(struct ata_queued_cmd *qc);
static void adma_bmdma_stop(struct ata_queued_cmd *qc); static void adma_bmdma_stop(struct ata_queued_cmd *qc);
static u8 adma_bmdma_status(struct ata_port *ap); static u8 adma_bmdma_status(struct ata_port *ap);
...@@ -143,11 +143,11 @@ static struct scsi_host_template adma_ata_sht = { ...@@ -143,11 +143,11 @@ static struct scsi_host_template adma_ata_sht = {
.name = DRV_NAME, .name = DRV_NAME,
.ioctl = ata_scsi_ioctl, .ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd, .queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error, .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE, .can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID, .this_id = ATA_SHT_THIS_ID,
.sg_tablesize = LIBATA_MAX_PRD, .sg_tablesize = LIBATA_MAX_PRD,
.max_sectors = ATA_MAX_SECTORS,
.cmd_per_lun = ATA_SHT_CMD_PER_LUN, .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
.emulated = ATA_SHT_EMULATED, .emulated = ATA_SHT_EMULATED,
.use_clustering = ENABLE_CLUSTERING, .use_clustering = ENABLE_CLUSTERING,
...@@ -419,7 +419,7 @@ static inline void adma_packet_start(struct ata_queued_cmd *qc) ...@@ -419,7 +419,7 @@ static inline void adma_packet_start(struct ata_queued_cmd *qc)
writew(aPIOMD4 | aGO, chan + ADMA_CONTROL); writew(aPIOMD4 | aGO, chan + ADMA_CONTROL);
} }
static int adma_qc_issue(struct ata_queued_cmd *qc) static unsigned int adma_qc_issue(struct ata_queued_cmd *qc)
{ {
struct adma_port_priv *pp = qc->ap->private_data; struct adma_port_priv *pp = qc->ap->private_data;
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
#include <asm/io.h> #include <asm/io.h>
#define DRV_NAME "sata_mv" #define DRV_NAME "sata_mv"
#define DRV_VERSION "0.5" #define DRV_VERSION "0.6"
enum { enum {
/* BAR's are enumerated in terms of pci_resource_start() terms */ /* BAR's are enumerated in terms of pci_resource_start() terms */
...@@ -228,7 +228,9 @@ enum { ...@@ -228,7 +228,9 @@ enum {
MV_HP_ERRATA_50XXB2 = (1 << 2), MV_HP_ERRATA_50XXB2 = (1 << 2),
MV_HP_ERRATA_60X1B2 = (1 << 3), MV_HP_ERRATA_60X1B2 = (1 << 3),
MV_HP_ERRATA_60X1C0 = (1 << 4), MV_HP_ERRATA_60X1C0 = (1 << 4),
MV_HP_50XX = (1 << 5), MV_HP_ERRATA_XX42A0 = (1 << 5),
MV_HP_50XX = (1 << 6),
MV_HP_GEN_IIE = (1 << 7),
/* Port private flags (pp_flags) */ /* Port private flags (pp_flags) */
MV_PP_FLAG_EDMA_EN = (1 << 0), MV_PP_FLAG_EDMA_EN = (1 << 0),
...@@ -237,6 +239,9 @@ enum { ...@@ -237,6 +239,9 @@ enum {
#define IS_50XX(hpriv) ((hpriv)->hp_flags & MV_HP_50XX) #define IS_50XX(hpriv) ((hpriv)->hp_flags & MV_HP_50XX)
#define IS_60XX(hpriv) (((hpriv)->hp_flags & MV_HP_50XX) == 0) #define IS_60XX(hpriv) (((hpriv)->hp_flags & MV_HP_50XX) == 0)
#define IS_GEN_I(hpriv) IS_50XX(hpriv)
#define IS_GEN_II(hpriv) IS_60XX(hpriv)
#define IS_GEN_IIE(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_IIE)
enum { enum {
/* Our DMA boundary is determined by an ePRD being unable to handle /* Our DMA boundary is determined by an ePRD being unable to handle
...@@ -255,6 +260,8 @@ enum chip_type { ...@@ -255,6 +260,8 @@ enum chip_type {
chip_5080, chip_5080,
chip_604x, chip_604x,
chip_608x, chip_608x,
chip_6042,
chip_7042,
}; };
/* Command ReQuest Block: 32B */ /* Command ReQuest Block: 32B */
...@@ -265,6 +272,14 @@ struct mv_crqb { ...@@ -265,6 +272,14 @@ struct mv_crqb {
u16 ata_cmd[11]; u16 ata_cmd[11];
}; };
struct mv_crqb_iie {
u32 addr;
u32 addr_hi;
u32 flags;
u32 len;
u32 ata_cmd[4];
};
/* Command ResPonse Block: 8B */ /* Command ResPonse Block: 8B */
struct mv_crpb { struct mv_crpb {
u16 id; u16 id;
...@@ -328,7 +343,8 @@ static void mv_host_stop(struct ata_host_set *host_set); ...@@ -328,7 +343,8 @@ static void mv_host_stop(struct ata_host_set *host_set);
static int mv_port_start(struct ata_port *ap); static int mv_port_start(struct ata_port *ap);
static void mv_port_stop(struct ata_port *ap); static void mv_port_stop(struct ata_port *ap);
static void mv_qc_prep(struct ata_queued_cmd *qc); static void mv_qc_prep(struct ata_queued_cmd *qc);
static int mv_qc_issue(struct ata_queued_cmd *qc); static void mv_qc_prep_iie(struct ata_queued_cmd *qc);
static unsigned int mv_qc_issue(struct ata_queued_cmd *qc);
static irqreturn_t mv_interrupt(int irq, void *dev_instance, static irqreturn_t mv_interrupt(int irq, void *dev_instance,
struct pt_regs *regs); struct pt_regs *regs);
static void mv_eng_timeout(struct ata_port *ap); static void mv_eng_timeout(struct ata_port *ap);
...@@ -362,11 +378,11 @@ static struct scsi_host_template mv_sht = { ...@@ -362,11 +378,11 @@ static struct scsi_host_template mv_sht = {
.name = DRV_NAME, .name = DRV_NAME,
.ioctl = ata_scsi_ioctl, .ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd, .queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error, .eh_strategy_handler = ata_scsi_error,
.can_queue = MV_USE_Q_DEPTH, .can_queue = MV_USE_Q_DEPTH,
.this_id = ATA_SHT_THIS_ID, .this_id = ATA_SHT_THIS_ID,
.sg_tablesize = MV_MAX_SG_CT / 2, .sg_tablesize = MV_MAX_SG_CT / 2,
.max_sectors = ATA_MAX_SECTORS,
.cmd_per_lun = ATA_SHT_CMD_PER_LUN, .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
.emulated = ATA_SHT_EMULATED, .emulated = ATA_SHT_EMULATED,
.use_clustering = ATA_SHT_USE_CLUSTERING, .use_clustering = ATA_SHT_USE_CLUSTERING,
...@@ -430,6 +446,33 @@ static const struct ata_port_operations mv6_ops = { ...@@ -430,6 +446,33 @@ static const struct ata_port_operations mv6_ops = {
.host_stop = mv_host_stop, .host_stop = mv_host_stop,
}; };
static const struct ata_port_operations mv_iie_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load,
.tf_read = ata_tf_read,
.check_status = ata_check_status,
.exec_command = ata_exec_command,
.dev_select = ata_std_dev_select,
.phy_reset = mv_phy_reset,
.qc_prep = mv_qc_prep_iie,
.qc_issue = mv_qc_issue,
.eng_timeout = mv_eng_timeout,
.irq_handler = mv_interrupt,
.irq_clear = mv_irq_clear,
.scr_read = mv_scr_read,
.scr_write = mv_scr_write,
.port_start = mv_port_start,
.port_stop = mv_port_stop,
.host_stop = mv_host_stop,
};
static const struct ata_port_info mv_port_info[] = { static const struct ata_port_info mv_port_info[] = {
{ /* chip_504x */ { /* chip_504x */
.sht = &mv_sht, .sht = &mv_sht,
...@@ -467,6 +510,21 @@ static const struct ata_port_info mv_port_info[] = { ...@@ -467,6 +510,21 @@ static const struct ata_port_info mv_port_info[] = {
.udma_mask = 0x7f, /* udma0-6 */ .udma_mask = 0x7f, /* udma0-6 */
.port_ops = &mv6_ops, .port_ops = &mv6_ops,
}, },
{ /* chip_6042 */
.sht = &mv_sht,
.host_flags = (MV_COMMON_FLAGS | MV_6XXX_FLAGS),
.pio_mask = 0x1f, /* pio0-4 */
.udma_mask = 0x7f, /* udma0-6 */
.port_ops = &mv_iie_ops,
},
{ /* chip_7042 */
.sht = &mv_sht,
.host_flags = (MV_COMMON_FLAGS | MV_6XXX_FLAGS |
MV_FLAG_DUAL_HC),
.pio_mask = 0x1f, /* pio0-4 */
.udma_mask = 0x7f, /* udma0-6 */
.port_ops = &mv_iie_ops,
},
}; };
static const struct pci_device_id mv_pci_tbl[] = { static const struct pci_device_id mv_pci_tbl[] = {
...@@ -477,6 +535,7 @@ static const struct pci_device_id mv_pci_tbl[] = { ...@@ -477,6 +535,7 @@ static const struct pci_device_id mv_pci_tbl[] = {
{PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6040), 0, 0, chip_604x}, {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6040), 0, 0, chip_604x},
{PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6041), 0, 0, chip_604x}, {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6041), 0, 0, chip_604x},
{PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6042), 0, 0, chip_6042},
{PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6080), 0, 0, chip_608x}, {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6080), 0, 0, chip_608x},
{PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6081), 0, 0, chip_608x}, {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6081), 0, 0, chip_608x},
...@@ -572,8 +631,8 @@ static void mv_irq_clear(struct ata_port *ap) ...@@ -572,8 +631,8 @@ static void mv_irq_clear(struct ata_port *ap)
* @base: port base address * @base: port base address
* @pp: port private data * @pp: port private data
* *
* Verify the local cache of the eDMA state is accurate with an * Verify the local cache of the eDMA state is accurate with a
* assert. * WARN_ON.
* *
* LOCKING: * LOCKING:
* Inherited from caller. * Inherited from caller.
...@@ -584,15 +643,15 @@ static void mv_start_dma(void __iomem *base, struct mv_port_priv *pp) ...@@ -584,15 +643,15 @@ static void mv_start_dma(void __iomem *base, struct mv_port_priv *pp)
writelfl(EDMA_EN, base + EDMA_CMD_OFS); writelfl(EDMA_EN, base + EDMA_CMD_OFS);
pp->pp_flags |= MV_PP_FLAG_EDMA_EN; pp->pp_flags |= MV_PP_FLAG_EDMA_EN;
} }
assert(EDMA_EN & readl(base + EDMA_CMD_OFS)); WARN_ON(!(EDMA_EN & readl(base + EDMA_CMD_OFS)));
} }
/** /**
* mv_stop_dma - Disable eDMA engine * mv_stop_dma - Disable eDMA engine
* @ap: ATA channel to manipulate * @ap: ATA channel to manipulate
* *
* Verify the local cache of the eDMA state is accurate with an * Verify the local cache of the eDMA state is accurate with a
* assert. * WARN_ON.
* *
* LOCKING: * LOCKING:
* Inherited from caller. * Inherited from caller.
...@@ -610,7 +669,7 @@ static void mv_stop_dma(struct ata_port *ap) ...@@ -610,7 +669,7 @@ static void mv_stop_dma(struct ata_port *ap)
writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS); writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN; pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
} else { } else {
assert(!(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS))); WARN_ON(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS));
} }
/* now properly wait for the eDMA to stop */ /* now properly wait for the eDMA to stop */
...@@ -773,6 +832,33 @@ static inline void mv_priv_free(struct mv_port_priv *pp, struct device *dev) ...@@ -773,6 +832,33 @@ static inline void mv_priv_free(struct mv_port_priv *pp, struct device *dev)
dma_free_coherent(dev, MV_PORT_PRIV_DMA_SZ, pp->crpb, pp->crpb_dma); dma_free_coherent(dev, MV_PORT_PRIV_DMA_SZ, pp->crpb, pp->crpb_dma);
} }
static void mv_edma_cfg(struct mv_host_priv *hpriv, void __iomem *port_mmio)
{
u32 cfg = readl(port_mmio + EDMA_CFG_OFS);
/* set up non-NCQ EDMA configuration */
cfg &= ~0x1f; /* clear queue depth */
cfg &= ~EDMA_CFG_NCQ; /* clear NCQ mode */
cfg &= ~(1 << 9); /* disable equeue */
if (IS_GEN_I(hpriv))
cfg |= (1 << 8); /* enab config burst size mask */
else if (IS_GEN_II(hpriv))
cfg |= EDMA_CFG_RD_BRST_EXT | EDMA_CFG_WR_BUFF_LEN;
else if (IS_GEN_IIE(hpriv)) {
cfg |= (1 << 23); /* dis RX PM port mask */
cfg &= ~(1 << 16); /* dis FIS-based switching (for now) */
cfg &= ~(1 << 19); /* dis 128-entry queue (for now?) */
cfg |= (1 << 18); /* enab early completion */
cfg |= (1 << 17); /* enab host q cache */
cfg |= (1 << 22); /* enab cutthrough */
}
writelfl(cfg, port_mmio + EDMA_CFG_OFS);
}
/** /**
* mv_port_start - Port specific init/start routine. * mv_port_start - Port specific init/start routine.
* @ap: ATA channel to manipulate * @ap: ATA channel to manipulate
...@@ -786,6 +872,7 @@ static inline void mv_priv_free(struct mv_port_priv *pp, struct device *dev) ...@@ -786,6 +872,7 @@ static inline void mv_priv_free(struct mv_port_priv *pp, struct device *dev)
static int mv_port_start(struct ata_port *ap) static int mv_port_start(struct ata_port *ap)
{ {
struct device *dev = ap->host_set->dev; struct device *dev = ap->host_set->dev;
struct mv_host_priv *hpriv = ap->host_set->private_data;
struct mv_port_priv *pp; struct mv_port_priv *pp;
void __iomem *port_mmio = mv_ap_base(ap); void __iomem *port_mmio = mv_ap_base(ap);
void *mem; void *mem;
...@@ -829,17 +916,26 @@ static int mv_port_start(struct ata_port *ap) ...@@ -829,17 +916,26 @@ static int mv_port_start(struct ata_port *ap)
pp->sg_tbl = mem; pp->sg_tbl = mem;
pp->sg_tbl_dma = mem_dma; pp->sg_tbl_dma = mem_dma;
writelfl(EDMA_CFG_Q_DEPTH | EDMA_CFG_RD_BRST_EXT | mv_edma_cfg(hpriv, port_mmio);
EDMA_CFG_WR_BUFF_LEN, port_mmio + EDMA_CFG_OFS);
writel((pp->crqb_dma >> 16) >> 16, port_mmio + EDMA_REQ_Q_BASE_HI_OFS); writel((pp->crqb_dma >> 16) >> 16, port_mmio + EDMA_REQ_Q_BASE_HI_OFS);
writelfl(pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK, writelfl(pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK,
port_mmio + EDMA_REQ_Q_IN_PTR_OFS); port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
writelfl(0, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS); if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
writelfl(0, port_mmio + EDMA_RSP_Q_IN_PTR_OFS); writelfl(pp->crqb_dma & 0xffffffff,
port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
else
writelfl(0, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
writel((pp->crpb_dma >> 16) >> 16, port_mmio + EDMA_RSP_Q_BASE_HI_OFS); writel((pp->crpb_dma >> 16) >> 16, port_mmio + EDMA_RSP_Q_BASE_HI_OFS);
if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
writelfl(pp->crpb_dma & 0xffffffff,
port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
else
writelfl(0, port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
writelfl(pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK, writelfl(pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK,
port_mmio + EDMA_RSP_Q_OUT_PTR_OFS); port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
...@@ -960,21 +1056,19 @@ static void mv_qc_prep(struct ata_queued_cmd *qc) ...@@ -960,21 +1056,19 @@ static void mv_qc_prep(struct ata_queued_cmd *qc)
struct ata_taskfile *tf; struct ata_taskfile *tf;
u16 flags = 0; u16 flags = 0;
if (ATA_PROT_DMA != qc->tf.protocol) { if (ATA_PROT_DMA != qc->tf.protocol)
return; return;
}
/* the req producer index should be the same as we remember it */ /* the req producer index should be the same as we remember it */
assert(((readl(mv_ap_base(qc->ap) + EDMA_REQ_Q_IN_PTR_OFS) >> WARN_ON(((readl(mv_ap_base(qc->ap) + EDMA_REQ_Q_IN_PTR_OFS) >>
EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) == EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) !=
pp->req_producer); pp->req_producer);
/* Fill in command request block /* Fill in command request block
*/ */
if (!(qc->tf.flags & ATA_TFLAG_WRITE)) { if (!(qc->tf.flags & ATA_TFLAG_WRITE))
flags |= CRQB_FLAG_READ; flags |= CRQB_FLAG_READ;
} WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
assert(MV_MAX_Q_DEPTH > qc->tag);
flags |= qc->tag << CRQB_TAG_SHIFT; flags |= qc->tag << CRQB_TAG_SHIFT;
pp->crqb[pp->req_producer].sg_addr = pp->crqb[pp->req_producer].sg_addr =
...@@ -1029,9 +1123,76 @@ static void mv_qc_prep(struct ata_queued_cmd *qc) ...@@ -1029,9 +1123,76 @@ static void mv_qc_prep(struct ata_queued_cmd *qc)
mv_crqb_pack_cmd(cw++, tf->device, ATA_REG_DEVICE, 0); mv_crqb_pack_cmd(cw++, tf->device, ATA_REG_DEVICE, 0);
mv_crqb_pack_cmd(cw++, tf->command, ATA_REG_CMD, 1); /* last */ mv_crqb_pack_cmd(cw++, tf->command, ATA_REG_CMD, 1); /* last */
if (!(qc->flags & ATA_QCFLAG_DMAMAP)) { if (!(qc->flags & ATA_QCFLAG_DMAMAP))
return;
mv_fill_sg(qc);
}
/**
* mv_qc_prep_iie - Host specific command preparation.
* @qc: queued command to prepare
*
* This routine simply redirects to the general purpose routine
* if command is not DMA. Else, it handles prep of the CRQB
* (command request block), does some sanity checking, and calls
* the SG load routine.
*
* LOCKING:
* Inherited from caller.
*/
static void mv_qc_prep_iie(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
struct mv_port_priv *pp = ap->private_data;
struct mv_crqb_iie *crqb;
struct ata_taskfile *tf;
u32 flags = 0;
if (ATA_PROT_DMA != qc->tf.protocol)
return;
/* the req producer index should be the same as we remember it */
WARN_ON(((readl(mv_ap_base(qc->ap) + EDMA_REQ_Q_IN_PTR_OFS) >>
EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) !=
pp->req_producer);
/* Fill in Gen IIE command request block
*/
if (!(qc->tf.flags & ATA_TFLAG_WRITE))
flags |= CRQB_FLAG_READ;
WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
flags |= qc->tag << CRQB_TAG_SHIFT;
crqb = (struct mv_crqb_iie *) &pp->crqb[pp->req_producer];
crqb->addr = cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
crqb->addr_hi = cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16);
crqb->flags = cpu_to_le32(flags);
tf = &qc->tf;
crqb->ata_cmd[0] = cpu_to_le32(
(tf->command << 16) |
(tf->feature << 24)
);
crqb->ata_cmd[1] = cpu_to_le32(
(tf->lbal << 0) |
(tf->lbam << 8) |
(tf->lbah << 16) |
(tf->device << 24)
);
crqb->ata_cmd[2] = cpu_to_le32(
(tf->hob_lbal << 0) |
(tf->hob_lbam << 8) |
(tf->hob_lbah << 16) |
(tf->hob_feature << 24)
);
crqb->ata_cmd[3] = cpu_to_le32(
(tf->nsect << 0) |
(tf->hob_nsect << 8)
);
if (!(qc->flags & ATA_QCFLAG_DMAMAP))
return; return;
}
mv_fill_sg(qc); mv_fill_sg(qc);
} }
...@@ -1047,7 +1208,7 @@ static void mv_qc_prep(struct ata_queued_cmd *qc) ...@@ -1047,7 +1208,7 @@ static void mv_qc_prep(struct ata_queued_cmd *qc)
* LOCKING: * LOCKING:
* Inherited from caller. * Inherited from caller.
*/ */
static int mv_qc_issue(struct ata_queued_cmd *qc) static unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
{ {
void __iomem *port_mmio = mv_ap_base(qc->ap); void __iomem *port_mmio = mv_ap_base(qc->ap);
struct mv_port_priv *pp = qc->ap->private_data; struct mv_port_priv *pp = qc->ap->private_data;
...@@ -1065,12 +1226,12 @@ static int mv_qc_issue(struct ata_queued_cmd *qc) ...@@ -1065,12 +1226,12 @@ static int mv_qc_issue(struct ata_queued_cmd *qc)
in_ptr = readl(port_mmio + EDMA_REQ_Q_IN_PTR_OFS); in_ptr = readl(port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
/* the req producer index should be the same as we remember it */ /* the req producer index should be the same as we remember it */
assert(((in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) == WARN_ON(((in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) !=
pp->req_producer); pp->req_producer);
/* until we do queuing, the queue should be empty at this point */ /* until we do queuing, the queue should be empty at this point */
assert(((in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) == WARN_ON(((in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) !=
((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS) >> ((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS) >>
EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK)); EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
mv_inc_q_index(&pp->req_producer); /* now incr producer index */ mv_inc_q_index(&pp->req_producer); /* now incr producer index */
...@@ -1090,7 +1251,7 @@ static int mv_qc_issue(struct ata_queued_cmd *qc) ...@@ -1090,7 +1251,7 @@ static int mv_qc_issue(struct ata_queued_cmd *qc)
* *
* This routine is for use when the port is in DMA mode, when it * This routine is for use when the port is in DMA mode, when it
* will be using the CRPB (command response block) method of * will be using the CRPB (command response block) method of
* returning command completion information. We assert indices * returning command completion information. We check indices
* are good, grab status, and bump the response consumer index to * are good, grab status, and bump the response consumer index to
* prove that we're up to date. * prove that we're up to date.
* *
...@@ -1106,16 +1267,16 @@ static u8 mv_get_crpb_status(struct ata_port *ap) ...@@ -1106,16 +1267,16 @@ static u8 mv_get_crpb_status(struct ata_port *ap)
out_ptr = readl(port_mmio + EDMA_RSP_Q_OUT_PTR_OFS); out_ptr = readl(port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
/* the response consumer index should be the same as we remember it */ /* the response consumer index should be the same as we remember it */
assert(((out_ptr >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) == WARN_ON(((out_ptr >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) !=
pp->rsp_consumer); pp->rsp_consumer);
/* increment our consumer index... */ /* increment our consumer index... */
pp->rsp_consumer = mv_inc_q_index(&pp->rsp_consumer); pp->rsp_consumer = mv_inc_q_index(&pp->rsp_consumer);
/* and, until we do NCQ, there should only be 1 CRPB waiting */ /* and, until we do NCQ, there should only be 1 CRPB waiting */
assert(((readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS) >> WARN_ON(((readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS) >>
EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) == EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) !=
pp->rsp_consumer); pp->rsp_consumer);
/* write out our inc'd consumer index so EDMA knows we're caught up */ /* write out our inc'd consumer index so EDMA knows we're caught up */
out_ptr &= EDMA_RSP_Q_BASE_LO_MASK; out_ptr &= EDMA_RSP_Q_BASE_LO_MASK;
...@@ -1192,7 +1353,6 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant, ...@@ -1192,7 +1353,6 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
u32 hc_irq_cause; u32 hc_irq_cause;
int shift, port, port0, hard_port, handled; int shift, port, port0, hard_port, handled;
unsigned int err_mask; unsigned int err_mask;
u8 ata_status = 0;
if (hc == 0) { if (hc == 0) {
port0 = 0; port0 = 0;
...@@ -1210,6 +1370,7 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant, ...@@ -1210,6 +1370,7 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
hc,relevant,hc_irq_cause); hc,relevant,hc_irq_cause);
for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) { for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) {
u8 ata_status = 0;
ap = host_set->ports[port]; ap = host_set->ports[port];
hard_port = port & MV_PORT_MASK; /* range 0-3 */ hard_port = port & MV_PORT_MASK; /* range 0-3 */
handled = 0; /* ensure ata_status is set if handled++ */ handled = 0; /* ensure ata_status is set if handled++ */
...@@ -1681,6 +1842,12 @@ static void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio, ...@@ -1681,6 +1842,12 @@ static void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
m2 |= hpriv->signal[port].pre; m2 |= hpriv->signal[port].pre;
m2 &= ~(1 << 16); m2 &= ~(1 << 16);
/* according to mvSata 3.6.1, some IIE values are fixed */
if (IS_GEN_IIE(hpriv)) {
m2 &= ~0xC30FF01F;
m2 |= 0x0000900F;
}
writel(m2, port_mmio + PHY_MODE2); writel(m2, port_mmio + PHY_MODE2);
} }
...@@ -1846,7 +2013,6 @@ static void mv_phy_reset(struct ata_port *ap) ...@@ -1846,7 +2013,6 @@ static void mv_phy_reset(struct ata_port *ap)
static void mv_eng_timeout(struct ata_port *ap) static void mv_eng_timeout(struct ata_port *ap)
{ {
struct ata_queued_cmd *qc; struct ata_queued_cmd *qc;
unsigned long flags;
printk(KERN_ERR "ata%u: Entering mv_eng_timeout\n",ap->id); printk(KERN_ERR "ata%u: Entering mv_eng_timeout\n",ap->id);
DPRINTK("All regs @ start of eng_timeout\n"); DPRINTK("All regs @ start of eng_timeout\n");
...@@ -1861,22 +2027,8 @@ static void mv_eng_timeout(struct ata_port *ap) ...@@ -1861,22 +2027,8 @@ static void mv_eng_timeout(struct ata_port *ap)
mv_err_intr(ap); mv_err_intr(ap);
mv_stop_and_reset(ap); mv_stop_and_reset(ap);
if (!qc) { qc->err_mask |= AC_ERR_TIMEOUT;
printk(KERN_ERR "ata%u: BUG: timeout without command\n", ata_eh_qc_complete(qc);
ap->id);
} else {
/* hack alert! We cannot use the supplied completion
* function from inside the ->eh_strategy_handler() thread.
* libata is the only user of ->eh_strategy_handler() in
* any kernel, so the default scsi_done() assumes it is
* not being called from the SCSI EH.
*/
spin_lock_irqsave(&ap->host_set->lock, flags);
qc->scsidone = scsi_finish_command;
qc->err_mask |= AC_ERR_OTHER;
ata_qc_complete(qc);
spin_unlock_irqrestore(&ap->host_set->lock, flags);
}
} }
/** /**
...@@ -1995,6 +2147,27 @@ static int mv_chip_id(struct pci_dev *pdev, struct mv_host_priv *hpriv, ...@@ -1995,6 +2147,27 @@ static int mv_chip_id(struct pci_dev *pdev, struct mv_host_priv *hpriv,
} }
break; break;
case chip_7042:
case chip_6042:
hpriv->ops = &mv6xxx_ops;
hp_flags |= MV_HP_GEN_IIE;
switch (rev_id) {
case 0x0:
hp_flags |= MV_HP_ERRATA_XX42A0;
break;
case 0x1:
hp_flags |= MV_HP_ERRATA_60X1C0;
break;
default:
dev_printk(KERN_WARNING, &pdev->dev,
"Applying 60X1C0 workarounds to unknown rev\n");
hp_flags |= MV_HP_ERRATA_60X1C0;
break;
}
break;
default: default:
printk(KERN_ERR DRV_NAME ": BUG: invalid board index %u\n", board_idx); printk(KERN_ERR DRV_NAME ": BUG: invalid board index %u\n", board_idx);
return 1; return 1;
......
...@@ -229,11 +229,11 @@ static struct scsi_host_template nv_sht = { ...@@ -229,11 +229,11 @@ static struct scsi_host_template nv_sht = {
.name = DRV_NAME, .name = DRV_NAME,
.ioctl = ata_scsi_ioctl, .ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd, .queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error, .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE, .can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID, .this_id = ATA_SHT_THIS_ID,
.sg_tablesize = LIBATA_MAX_PRD, .sg_tablesize = LIBATA_MAX_PRD,
.max_sectors = ATA_MAX_SECTORS,
.cmd_per_lun = ATA_SHT_CMD_PER_LUN, .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
.emulated = ATA_SHT_EMULATED, .emulated = ATA_SHT_EMULATED,
.use_clustering = ATA_SHT_USE_CLUSTERING, .use_clustering = ATA_SHT_USE_CLUSTERING,
......
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
#include "sata_promise.h" #include "sata_promise.h"
#define DRV_NAME "sata_promise" #define DRV_NAME "sata_promise"
#define DRV_VERSION "1.03" #define DRV_VERSION "1.04"
enum { enum {
...@@ -58,6 +58,7 @@ enum { ...@@ -58,6 +58,7 @@ enum {
PDC_GLOBAL_CTL = 0x48, /* Global control/status (per port) */ PDC_GLOBAL_CTL = 0x48, /* Global control/status (per port) */
PDC_CTLSTAT = 0x60, /* IDE control and status (per port) */ PDC_CTLSTAT = 0x60, /* IDE control and status (per port) */
PDC_SATA_PLUG_CSR = 0x6C, /* SATA Plug control/status reg */ PDC_SATA_PLUG_CSR = 0x6C, /* SATA Plug control/status reg */
PDC2_SATA_PLUG_CSR = 0x60, /* SATAII Plug control/status reg */
PDC_SLEW_CTL = 0x470, /* slew rate control reg */ PDC_SLEW_CTL = 0x470, /* slew rate control reg */
PDC_ERR_MASK = (1<<19) | (1<<20) | (1<<21) | (1<<22) | PDC_ERR_MASK = (1<<19) | (1<<20) | (1<<21) | (1<<22) |
...@@ -67,8 +68,10 @@ enum { ...@@ -67,8 +68,10 @@ enum {
board_20319 = 1, /* FastTrak S150 TX4 */ board_20319 = 1, /* FastTrak S150 TX4 */
board_20619 = 2, /* FastTrak TX4000 */ board_20619 = 2, /* FastTrak TX4000 */
board_20771 = 3, /* FastTrak TX2300 */ board_20771 = 3, /* FastTrak TX2300 */
board_2057x = 4, /* SATAII150 Tx2plus */
board_40518 = 5, /* SATAII150 Tx4 */
PDC_HAS_PATA = (1 << 1), /* PDC20375 has PATA */ PDC_HAS_PATA = (1 << 1), /* PDC20375/20575 has PATA */
PDC_RESET = (1 << 11), /* HDMA reset */ PDC_RESET = (1 << 11), /* HDMA reset */
...@@ -82,6 +85,10 @@ struct pdc_port_priv { ...@@ -82,6 +85,10 @@ struct pdc_port_priv {
dma_addr_t pkt_dma; dma_addr_t pkt_dma;
}; };
struct pdc_host_priv {
int hotplug_offset;
};
static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg); static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg);
static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
...@@ -95,7 +102,8 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc); ...@@ -95,7 +102,8 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc);
static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf); static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf); static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
static void pdc_irq_clear(struct ata_port *ap); static void pdc_irq_clear(struct ata_port *ap);
static int pdc_qc_issue_prot(struct ata_queued_cmd *qc); static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc);
static void pdc_host_stop(struct ata_host_set *host_set);
static struct scsi_host_template pdc_ata_sht = { static struct scsi_host_template pdc_ata_sht = {
...@@ -103,11 +111,11 @@ static struct scsi_host_template pdc_ata_sht = { ...@@ -103,11 +111,11 @@ static struct scsi_host_template pdc_ata_sht = {
.name = DRV_NAME, .name = DRV_NAME,
.ioctl = ata_scsi_ioctl, .ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd, .queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error, .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE, .can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID, .this_id = ATA_SHT_THIS_ID,
.sg_tablesize = LIBATA_MAX_PRD, .sg_tablesize = LIBATA_MAX_PRD,
.max_sectors = ATA_MAX_SECTORS,
.cmd_per_lun = ATA_SHT_CMD_PER_LUN, .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
.emulated = ATA_SHT_EMULATED, .emulated = ATA_SHT_EMULATED,
.use_clustering = ATA_SHT_USE_CLUSTERING, .use_clustering = ATA_SHT_USE_CLUSTERING,
...@@ -137,7 +145,7 @@ static const struct ata_port_operations pdc_sata_ops = { ...@@ -137,7 +145,7 @@ static const struct ata_port_operations pdc_sata_ops = {
.scr_write = pdc_sata_scr_write, .scr_write = pdc_sata_scr_write,
.port_start = pdc_port_start, .port_start = pdc_port_start,
.port_stop = pdc_port_stop, .port_stop = pdc_port_stop,
.host_stop = ata_pci_host_stop, .host_stop = pdc_host_stop,
}; };
static const struct ata_port_operations pdc_pata_ops = { static const struct ata_port_operations pdc_pata_ops = {
...@@ -158,7 +166,7 @@ static const struct ata_port_operations pdc_pata_ops = { ...@@ -158,7 +166,7 @@ static const struct ata_port_operations pdc_pata_ops = {
.port_start = pdc_port_start, .port_start = pdc_port_start,
.port_stop = pdc_port_stop, .port_stop = pdc_port_stop,
.host_stop = ata_pci_host_stop, .host_stop = pdc_host_stop,
}; };
static const struct ata_port_info pdc_port_info[] = { static const struct ata_port_info pdc_port_info[] = {
...@@ -201,6 +209,26 @@ static const struct ata_port_info pdc_port_info[] = { ...@@ -201,6 +209,26 @@ static const struct ata_port_info pdc_port_info[] = {
.udma_mask = 0x7f, /* udma0-6 ; FIXME */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */
.port_ops = &pdc_sata_ops, .port_ops = &pdc_sata_ops,
}, },
/* board_2057x */
{
.sht = &pdc_ata_sht,
.host_flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
.port_ops = &pdc_sata_ops,
},
/* board_40518 */
{
.sht = &pdc_ata_sht,
.host_flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
.port_ops = &pdc_sata_ops,
},
}; };
static const struct pci_device_id pdc_ata_pci_tbl[] = { static const struct pci_device_id pdc_ata_pci_tbl[] = {
...@@ -217,9 +245,9 @@ static const struct pci_device_id pdc_ata_pci_tbl[] = { ...@@ -217,9 +245,9 @@ static const struct pci_device_id pdc_ata_pci_tbl[] = {
{ PCI_VENDOR_ID_PROMISE, 0x3376, PCI_ANY_ID, PCI_ANY_ID, 0, 0, { PCI_VENDOR_ID_PROMISE, 0x3376, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_2037x }, board_2037x },
{ PCI_VENDOR_ID_PROMISE, 0x3574, PCI_ANY_ID, PCI_ANY_ID, 0, 0, { PCI_VENDOR_ID_PROMISE, 0x3574, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_2037x }, board_2057x },
{ PCI_VENDOR_ID_PROMISE, 0x3d75, PCI_ANY_ID, PCI_ANY_ID, 0, 0, { PCI_VENDOR_ID_PROMISE, 0x3d75, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_2037x }, board_2057x },
{ PCI_VENDOR_ID_PROMISE, 0x3d73, PCI_ANY_ID, PCI_ANY_ID, 0, 0, { PCI_VENDOR_ID_PROMISE, 0x3d73, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_2037x }, board_2037x },
...@@ -227,12 +255,14 @@ static const struct pci_device_id pdc_ata_pci_tbl[] = { ...@@ -227,12 +255,14 @@ static const struct pci_device_id pdc_ata_pci_tbl[] = {
board_20319 }, board_20319 },
{ PCI_VENDOR_ID_PROMISE, 0x3319, PCI_ANY_ID, PCI_ANY_ID, 0, 0, { PCI_VENDOR_ID_PROMISE, 0x3319, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_20319 }, board_20319 },
{ PCI_VENDOR_ID_PROMISE, 0x3515, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_20319 },
{ PCI_VENDOR_ID_PROMISE, 0x3519, PCI_ANY_ID, PCI_ANY_ID, 0, 0, { PCI_VENDOR_ID_PROMISE, 0x3519, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_20319 }, board_20319 },
{ PCI_VENDOR_ID_PROMISE, 0x3d17, PCI_ANY_ID, PCI_ANY_ID, 0, 0, { PCI_VENDOR_ID_PROMISE, 0x3d17, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_20319 }, board_20319 },
{ PCI_VENDOR_ID_PROMISE, 0x3d18, PCI_ANY_ID, PCI_ANY_ID, 0, 0, { PCI_VENDOR_ID_PROMISE, 0x3d18, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_20319 }, board_40518 },
{ PCI_VENDOR_ID_PROMISE, 0x6629, PCI_ANY_ID, PCI_ANY_ID, 0, 0, { PCI_VENDOR_ID_PROMISE, 0x6629, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_20619 }, board_20619 },
...@@ -261,12 +291,11 @@ static int pdc_port_start(struct ata_port *ap) ...@@ -261,12 +291,11 @@ static int pdc_port_start(struct ata_port *ap)
if (rc) if (rc)
return rc; return rc;
pp = kmalloc(sizeof(*pp), GFP_KERNEL); pp = kzalloc(sizeof(*pp), GFP_KERNEL);
if (!pp) { if (!pp) {
rc = -ENOMEM; rc = -ENOMEM;
goto err_out; goto err_out;
} }
memset(pp, 0, sizeof(*pp));
pp->pkt = dma_alloc_coherent(dev, 128, &pp->pkt_dma, GFP_KERNEL); pp->pkt = dma_alloc_coherent(dev, 128, &pp->pkt_dma, GFP_KERNEL);
if (!pp->pkt) { if (!pp->pkt) {
...@@ -298,6 +327,16 @@ static void pdc_port_stop(struct ata_port *ap) ...@@ -298,6 +327,16 @@ static void pdc_port_stop(struct ata_port *ap)
} }
static void pdc_host_stop(struct ata_host_set *host_set)
{
struct pdc_host_priv *hp = host_set->private_data;
ata_pci_host_stop(host_set);
kfree(hp);
}
static void pdc_reset_port(struct ata_port *ap) static void pdc_reset_port(struct ata_port *ap)
{ {
void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr + PDC_CTLSTAT; void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr + PDC_CTLSTAT;
...@@ -394,19 +433,6 @@ static void pdc_eng_timeout(struct ata_port *ap) ...@@ -394,19 +433,6 @@ static void pdc_eng_timeout(struct ata_port *ap)
spin_lock_irqsave(&host_set->lock, flags); spin_lock_irqsave(&host_set->lock, flags);
qc = ata_qc_from_tag(ap, ap->active_tag); qc = ata_qc_from_tag(ap, ap->active_tag);
if (!qc) {
printk(KERN_ERR "ata%u: BUG: timeout without command\n",
ap->id);
goto out;
}
/* hack alert! We cannot use the supplied completion
* function from inside the ->eh_strategy_handler() thread.
* libata is the only user of ->eh_strategy_handler() in
* any kernel, so the default scsi_done() assumes it is
* not being called from the SCSI EH.
*/
qc->scsidone = scsi_finish_command;
switch (qc->tf.protocol) { switch (qc->tf.protocol) {
case ATA_PROT_DMA: case ATA_PROT_DMA:
...@@ -414,7 +440,6 @@ static void pdc_eng_timeout(struct ata_port *ap) ...@@ -414,7 +440,6 @@ static void pdc_eng_timeout(struct ata_port *ap)
printk(KERN_ERR "ata%u: command timeout\n", ap->id); printk(KERN_ERR "ata%u: command timeout\n", ap->id);
drv_stat = ata_wait_idle(ap); drv_stat = ata_wait_idle(ap);
qc->err_mask |= __ac_err_mask(drv_stat); qc->err_mask |= __ac_err_mask(drv_stat);
ata_qc_complete(qc);
break; break;
default: default:
...@@ -424,12 +449,11 @@ static void pdc_eng_timeout(struct ata_port *ap) ...@@ -424,12 +449,11 @@ static void pdc_eng_timeout(struct ata_port *ap)
ap->id, qc->tf.command, drv_stat); ap->id, qc->tf.command, drv_stat);
qc->err_mask |= ac_err_mask(drv_stat); qc->err_mask |= ac_err_mask(drv_stat);
ata_qc_complete(qc);
break; break;
} }
out:
spin_unlock_irqrestore(&host_set->lock, flags); spin_unlock_irqrestore(&host_set->lock, flags);
ata_eh_qc_complete(qc);
DPRINTK("EXIT\n"); DPRINTK("EXIT\n");
} }
...@@ -495,14 +519,15 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *r ...@@ -495,14 +519,15 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *r
VPRINTK("QUICK EXIT 2\n"); VPRINTK("QUICK EXIT 2\n");
return IRQ_NONE; return IRQ_NONE;
} }
spin_lock(&host_set->lock);
mask &= 0xffff; /* only 16 tags possible */ mask &= 0xffff; /* only 16 tags possible */
if (!mask) { if (!mask) {
VPRINTK("QUICK EXIT 3\n"); VPRINTK("QUICK EXIT 3\n");
return IRQ_NONE; goto done_irq;
} }
spin_lock(&host_set->lock);
writel(mask, mmio_base + PDC_INT_SEQMASK); writel(mask, mmio_base + PDC_INT_SEQMASK);
for (i = 0; i < host_set->n_ports; i++) { for (i = 0; i < host_set->n_ports; i++) {
...@@ -519,10 +544,10 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *r ...@@ -519,10 +544,10 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *r
} }
} }
spin_unlock(&host_set->lock);
VPRINTK("EXIT\n"); VPRINTK("EXIT\n");
done_irq:
spin_unlock(&host_set->lock);
return IRQ_RETVAL(handled); return IRQ_RETVAL(handled);
} }
...@@ -544,7 +569,7 @@ static inline void pdc_packet_start(struct ata_queued_cmd *qc) ...@@ -544,7 +569,7 @@ static inline void pdc_packet_start(struct ata_queued_cmd *qc)
readl((void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); /* flush */ readl((void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); /* flush */
} }
static int pdc_qc_issue_prot(struct ata_queued_cmd *qc) static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
{ {
switch (qc->tf.protocol) { switch (qc->tf.protocol) {
case ATA_PROT_DMA: case ATA_PROT_DMA:
...@@ -600,6 +625,8 @@ static void pdc_ata_setup_port(struct ata_ioports *port, unsigned long base) ...@@ -600,6 +625,8 @@ static void pdc_ata_setup_port(struct ata_ioports *port, unsigned long base)
static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe) static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe)
{ {
void __iomem *mmio = pe->mmio_base; void __iomem *mmio = pe->mmio_base;
struct pdc_host_priv *hp = pe->private_data;
int hotplug_offset = hp->hotplug_offset;
u32 tmp; u32 tmp;
/* /*
...@@ -614,12 +641,12 @@ static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe) ...@@ -614,12 +641,12 @@ static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe)
writel(tmp, mmio + PDC_FLASH_CTL); writel(tmp, mmio + PDC_FLASH_CTL);
/* clear plug/unplug flags for all ports */ /* clear plug/unplug flags for all ports */
tmp = readl(mmio + PDC_SATA_PLUG_CSR); tmp = readl(mmio + hotplug_offset);
writel(tmp | 0xff, mmio + PDC_SATA_PLUG_CSR); writel(tmp | 0xff, mmio + hotplug_offset);
/* mask plug/unplug ints */ /* mask plug/unplug ints */
tmp = readl(mmio + PDC_SATA_PLUG_CSR); tmp = readl(mmio + hotplug_offset);
writel(tmp | 0xff0000, mmio + PDC_SATA_PLUG_CSR); writel(tmp | 0xff0000, mmio + hotplug_offset);
/* reduce TBG clock to 133 Mhz. */ /* reduce TBG clock to 133 Mhz. */
tmp = readl(mmio + PDC_TBG_MODE); tmp = readl(mmio + PDC_TBG_MODE);
...@@ -641,6 +668,7 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e ...@@ -641,6 +668,7 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
{ {
static int printed_version; static int printed_version;
struct ata_probe_ent *probe_ent = NULL; struct ata_probe_ent *probe_ent = NULL;
struct pdc_host_priv *hp;
unsigned long base; unsigned long base;
void __iomem *mmio_base; void __iomem *mmio_base;
unsigned int board_idx = (unsigned int) ent->driver_data; unsigned int board_idx = (unsigned int) ent->driver_data;
...@@ -671,13 +699,12 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e ...@@ -671,13 +699,12 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
if (rc) if (rc)
goto err_out_regions; goto err_out_regions;
probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL); probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL);
if (probe_ent == NULL) { if (probe_ent == NULL) {
rc = -ENOMEM; rc = -ENOMEM;
goto err_out_regions; goto err_out_regions;
} }
memset(probe_ent, 0, sizeof(*probe_ent));
probe_ent->dev = pci_dev_to_dev(pdev); probe_ent->dev = pci_dev_to_dev(pdev);
INIT_LIST_HEAD(&probe_ent->node); INIT_LIST_HEAD(&probe_ent->node);
...@@ -688,6 +715,16 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e ...@@ -688,6 +715,16 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
} }
base = (unsigned long) mmio_base; base = (unsigned long) mmio_base;
hp = kzalloc(sizeof(*hp), GFP_KERNEL);
if (hp == NULL) {
rc = -ENOMEM;
goto err_out_free_ent;
}
/* Set default hotplug offset */
hp->hotplug_offset = PDC_SATA_PLUG_CSR;
probe_ent->private_data = hp;
probe_ent->sht = pdc_port_info[board_idx].sht; probe_ent->sht = pdc_port_info[board_idx].sht;
probe_ent->host_flags = pdc_port_info[board_idx].host_flags; probe_ent->host_flags = pdc_port_info[board_idx].host_flags;
probe_ent->pio_mask = pdc_port_info[board_idx].pio_mask; probe_ent->pio_mask = pdc_port_info[board_idx].pio_mask;
...@@ -707,6 +744,10 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e ...@@ -707,6 +744,10 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
/* notice 4-port boards */ /* notice 4-port boards */
switch (board_idx) { switch (board_idx) {
case board_40518:
/* Override hotplug offset for SATAII150 */
hp->hotplug_offset = PDC2_SATA_PLUG_CSR;
/* Fall through */
case board_20319: case board_20319:
probe_ent->n_ports = 4; probe_ent->n_ports = 4;
...@@ -716,6 +757,10 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e ...@@ -716,6 +757,10 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
probe_ent->port[2].scr_addr = base + 0x600; probe_ent->port[2].scr_addr = base + 0x600;
probe_ent->port[3].scr_addr = base + 0x700; probe_ent->port[3].scr_addr = base + 0x700;
break; break;
case board_2057x:
/* Override hotplug offset for SATAII150 */
hp->hotplug_offset = PDC2_SATA_PLUG_CSR;
/* Fall through */
case board_2037x: case board_2037x:
probe_ent->n_ports = 2; probe_ent->n_ports = 2;
break; break;
...@@ -741,8 +786,10 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e ...@@ -741,8 +786,10 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
/* initialize adapter */ /* initialize adapter */
pdc_host_init(board_idx, probe_ent); pdc_host_init(board_idx, probe_ent);
/* FIXME: check ata_device_add return value */ /* FIXME: Need any other frees than hp? */
ata_device_add(probe_ent); if (!ata_device_add(probe_ent))
kfree(hp);
kfree(probe_ent); kfree(probe_ent);
return 0; return 0;
......
...@@ -120,7 +120,7 @@ static void qs_host_stop(struct ata_host_set *host_set); ...@@ -120,7 +120,7 @@ static void qs_host_stop(struct ata_host_set *host_set);
static void qs_port_stop(struct ata_port *ap); static void qs_port_stop(struct ata_port *ap);
static void qs_phy_reset(struct ata_port *ap); static void qs_phy_reset(struct ata_port *ap);
static void qs_qc_prep(struct ata_queued_cmd *qc); static void qs_qc_prep(struct ata_queued_cmd *qc);
static int qs_qc_issue(struct ata_queued_cmd *qc); static unsigned int qs_qc_issue(struct ata_queued_cmd *qc);
static int qs_check_atapi_dma(struct ata_queued_cmd *qc); static int qs_check_atapi_dma(struct ata_queued_cmd *qc);
static void qs_bmdma_stop(struct ata_queued_cmd *qc); static void qs_bmdma_stop(struct ata_queued_cmd *qc);
static u8 qs_bmdma_status(struct ata_port *ap); static u8 qs_bmdma_status(struct ata_port *ap);
...@@ -132,11 +132,11 @@ static struct scsi_host_template qs_ata_sht = { ...@@ -132,11 +132,11 @@ static struct scsi_host_template qs_ata_sht = {
.name = DRV_NAME, .name = DRV_NAME,
.ioctl = ata_scsi_ioctl, .ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd, .queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error, .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE, .can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID, .this_id = ATA_SHT_THIS_ID,
.sg_tablesize = QS_MAX_PRD, .sg_tablesize = QS_MAX_PRD,
.max_sectors = ATA_MAX_SECTORS,
.cmd_per_lun = ATA_SHT_CMD_PER_LUN, .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
.emulated = ATA_SHT_EMULATED, .emulated = ATA_SHT_EMULATED,
//FIXME .use_clustering = ATA_SHT_USE_CLUSTERING, //FIXME .use_clustering = ATA_SHT_USE_CLUSTERING,
...@@ -276,8 +276,8 @@ static unsigned int qs_fill_sg(struct ata_queued_cmd *qc) ...@@ -276,8 +276,8 @@ static unsigned int qs_fill_sg(struct ata_queued_cmd *qc)
unsigned int nelem; unsigned int nelem;
u8 *prd = pp->pkt + QS_CPB_BYTES; u8 *prd = pp->pkt + QS_CPB_BYTES;
assert(qc->__sg != NULL); WARN_ON(qc->__sg == NULL);
assert(qc->n_elem > 0 || qc->pad_len > 0); WARN_ON(qc->n_elem == 0 && qc->pad_len == 0);
nelem = 0; nelem = 0;
ata_for_each_sg(sg, qc) { ata_for_each_sg(sg, qc) {
...@@ -352,7 +352,7 @@ static inline void qs_packet_start(struct ata_queued_cmd *qc) ...@@ -352,7 +352,7 @@ static inline void qs_packet_start(struct ata_queued_cmd *qc)
readl(chan + QS_CCT_CFF); /* flush */ readl(chan + QS_CCT_CFF); /* flush */
} }
static int qs_qc_issue(struct ata_queued_cmd *qc) static unsigned int qs_qc_issue(struct ata_queued_cmd *qc)
{ {
struct qs_port_priv *pp = qc->ap->private_data; struct qs_port_priv *pp = qc->ap->private_data;
......
...@@ -49,24 +49,30 @@ ...@@ -49,24 +49,30 @@
#define DRV_VERSION "0.9" #define DRV_VERSION "0.9"
enum { enum {
/*
* host flags
*/
SIL_FLAG_RERR_ON_DMA_ACT = (1 << 29), SIL_FLAG_RERR_ON_DMA_ACT = (1 << 29),
SIL_FLAG_MOD15WRITE = (1 << 30), SIL_FLAG_MOD15WRITE = (1 << 30),
SIL_DFL_HOST_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_MMIO,
/*
* Controller IDs
*/
sil_3112 = 0, sil_3112 = 0,
sil_3112_m15w = 1, sil_3512 = 1,
sil_3512 = 2, sil_3114 = 2,
sil_3114 = 3,
SIL_FIFO_R0 = 0x40,
SIL_FIFO_W0 = 0x41,
SIL_FIFO_R1 = 0x44,
SIL_FIFO_W1 = 0x45,
SIL_FIFO_R2 = 0x240,
SIL_FIFO_W2 = 0x241,
SIL_FIFO_R3 = 0x244,
SIL_FIFO_W3 = 0x245,
/*
* Register offsets
*/
SIL_SYSCFG = 0x48, SIL_SYSCFG = 0x48,
/*
* Register bits
*/
/* SYSCFG */
SIL_MASK_IDE0_INT = (1 << 22), SIL_MASK_IDE0_INT = (1 << 22),
SIL_MASK_IDE1_INT = (1 << 23), SIL_MASK_IDE1_INT = (1 << 23),
SIL_MASK_IDE2_INT = (1 << 24), SIL_MASK_IDE2_INT = (1 << 24),
...@@ -75,9 +81,12 @@ enum { ...@@ -75,9 +81,12 @@ enum {
SIL_MASK_4PORT = SIL_MASK_2PORT | SIL_MASK_4PORT = SIL_MASK_2PORT |
SIL_MASK_IDE2_INT | SIL_MASK_IDE3_INT, SIL_MASK_IDE2_INT | SIL_MASK_IDE3_INT,
SIL_IDE2_BMDMA = 0x200, /* BMDMA/BMDMA2 */
SIL_INTR_STEERING = (1 << 1), SIL_INTR_STEERING = (1 << 1),
/*
* Others
*/
SIL_QUIRK_MOD15WRITE = (1 << 0), SIL_QUIRK_MOD15WRITE = (1 << 0),
SIL_QUIRK_UDMA5MAX = (1 << 1), SIL_QUIRK_UDMA5MAX = (1 << 1),
}; };
...@@ -90,13 +99,13 @@ static void sil_post_set_mode (struct ata_port *ap); ...@@ -90,13 +99,13 @@ static void sil_post_set_mode (struct ata_port *ap);
static const struct pci_device_id sil_pci_tbl[] = { static const struct pci_device_id sil_pci_tbl[] = {
{ 0x1095, 0x3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w }, { 0x1095, 0x3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
{ 0x1095, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w }, { 0x1095, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
{ 0x1095, 0x3512, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3512 }, { 0x1095, 0x3512, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3512 },
{ 0x1095, 0x3114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3114 }, { 0x1095, 0x3114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3114 },
{ 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w }, { 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
{ 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w }, { 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
{ 0x1002, 0x437a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w }, { 0x1002, 0x437a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
{ } /* terminate list */ { } /* terminate list */
}; };
...@@ -137,11 +146,11 @@ static struct scsi_host_template sil_sht = { ...@@ -137,11 +146,11 @@ static struct scsi_host_template sil_sht = {
.name = DRV_NAME, .name = DRV_NAME,
.ioctl = ata_scsi_ioctl, .ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd, .queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error, .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE, .can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID, .this_id = ATA_SHT_THIS_ID,
.sg_tablesize = LIBATA_MAX_PRD, .sg_tablesize = LIBATA_MAX_PRD,
.max_sectors = ATA_MAX_SECTORS,
.cmd_per_lun = ATA_SHT_CMD_PER_LUN, .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
.emulated = ATA_SHT_EMULATED, .emulated = ATA_SHT_EMULATED,
.use_clustering = ATA_SHT_USE_CLUSTERING, .use_clustering = ATA_SHT_USE_CLUSTERING,
...@@ -159,7 +168,7 @@ static const struct ata_port_operations sil_ops = { ...@@ -159,7 +168,7 @@ static const struct ata_port_operations sil_ops = {
.check_status = ata_check_status, .check_status = ata_check_status,
.exec_command = ata_exec_command, .exec_command = ata_exec_command,
.dev_select = ata_std_dev_select, .dev_select = ata_std_dev_select,
.phy_reset = sata_phy_reset, .probe_reset = ata_std_probe_reset,
.post_set_mode = sil_post_set_mode, .post_set_mode = sil_post_set_mode,
.bmdma_setup = ata_bmdma_setup, .bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start, .bmdma_start = ata_bmdma_start,
...@@ -181,19 +190,7 @@ static const struct ata_port_info sil_port_info[] = { ...@@ -181,19 +190,7 @@ static const struct ata_port_info sil_port_info[] = {
/* sil_3112 */ /* sil_3112 */
{ {
.sht = &sil_sht, .sht = &sil_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | .host_flags = SIL_DFL_HOST_FLAGS | SIL_FLAG_MOD15WRITE,
ATA_FLAG_SRST | ATA_FLAG_MMIO,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x3f, /* udma0-5 */
.port_ops = &sil_ops,
},
/* sil_3112_15w - keep it sync'd w/ sil_3112 */
{
.sht = &sil_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_SRST | ATA_FLAG_MMIO |
SIL_FLAG_MOD15WRITE,
.pio_mask = 0x1f, /* pio0-4 */ .pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */ .mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x3f, /* udma0-5 */ .udma_mask = 0x3f, /* udma0-5 */
...@@ -202,9 +199,7 @@ static const struct ata_port_info sil_port_info[] = { ...@@ -202,9 +199,7 @@ static const struct ata_port_info sil_port_info[] = {
/* sil_3512 */ /* sil_3512 */
{ {
.sht = &sil_sht, .sht = &sil_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | .host_flags = SIL_DFL_HOST_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT,
ATA_FLAG_SRST | ATA_FLAG_MMIO |
SIL_FLAG_RERR_ON_DMA_ACT,
.pio_mask = 0x1f, /* pio0-4 */ .pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */ .mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x3f, /* udma0-5 */ .udma_mask = 0x3f, /* udma0-5 */
...@@ -213,9 +208,7 @@ static const struct ata_port_info sil_port_info[] = { ...@@ -213,9 +208,7 @@ static const struct ata_port_info sil_port_info[] = {
/* sil_3114 */ /* sil_3114 */
{ {
.sht = &sil_sht, .sht = &sil_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | .host_flags = SIL_DFL_HOST_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT,
ATA_FLAG_SRST | ATA_FLAG_MMIO |
SIL_FLAG_RERR_ON_DMA_ACT,
.pio_mask = 0x1f, /* pio0-4 */ .pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */ .mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x3f, /* udma0-5 */ .udma_mask = 0x3f, /* udma0-5 */
...@@ -229,16 +222,17 @@ static const struct { ...@@ -229,16 +222,17 @@ static const struct {
unsigned long tf; /* ATA taskfile register block */ unsigned long tf; /* ATA taskfile register block */
unsigned long ctl; /* ATA control/altstatus register block */ unsigned long ctl; /* ATA control/altstatus register block */
unsigned long bmdma; /* DMA register block */ unsigned long bmdma; /* DMA register block */
unsigned long fifo_cfg; /* FIFO Valid Byte Count and Control */
unsigned long scr; /* SATA control register block */ unsigned long scr; /* SATA control register block */
unsigned long sien; /* SATA Interrupt Enable register */ unsigned long sien; /* SATA Interrupt Enable register */
unsigned long xfer_mode;/* data transfer mode register */ unsigned long xfer_mode;/* data transfer mode register */
unsigned long sfis_cfg; /* SATA FIS reception config register */ unsigned long sfis_cfg; /* SATA FIS reception config register */
} sil_port[] = { } sil_port[] = {
/* port 0 ... */ /* port 0 ... */
{ 0x80, 0x8A, 0x00, 0x100, 0x148, 0xb4, 0x14c }, { 0x80, 0x8A, 0x00, 0x40, 0x100, 0x148, 0xb4, 0x14c },
{ 0xC0, 0xCA, 0x08, 0x180, 0x1c8, 0xf4, 0x1cc }, { 0xC0, 0xCA, 0x08, 0x44, 0x180, 0x1c8, 0xf4, 0x1cc },
{ 0x280, 0x28A, 0x200, 0x300, 0x348, 0x2b4, 0x34c }, { 0x280, 0x28A, 0x200, 0x240, 0x300, 0x348, 0x2b4, 0x34c },
{ 0x2C0, 0x2CA, 0x208, 0x380, 0x3c8, 0x2f4, 0x3cc }, { 0x2C0, 0x2CA, 0x208, 0x244, 0x380, 0x3c8, 0x2f4, 0x3cc },
/* ... port 3 */ /* ... port 3 */
}; };
...@@ -354,22 +348,12 @@ static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val) ...@@ -354,22 +348,12 @@ static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
static void sil_dev_config(struct ata_port *ap, struct ata_device *dev) static void sil_dev_config(struct ata_port *ap, struct ata_device *dev)
{ {
unsigned int n, quirks = 0; unsigned int n, quirks = 0;
unsigned char model_num[40]; unsigned char model_num[41];
const char *s;
unsigned int len;
ata_dev_id_string(dev->id, model_num, ATA_ID_PROD_OFS, ata_id_c_string(dev->id, model_num, ATA_ID_PROD_OFS, sizeof(model_num));
sizeof(model_num));
s = &model_num[0];
len = strnlen(s, sizeof(model_num));
/* ATAPI specifies that empty space is blank-filled; remove blanks */
while ((len > 0) && (s[len - 1] == ' '))
len--;
for (n = 0; sil_blacklist[n].product; n++) for (n = 0; sil_blacklist[n].product; n++)
if (!memcmp(sil_blacklist[n].product, s, if (!strcmp(sil_blacklist[n].product, model_num)) {
strlen(sil_blacklist[n].product))) {
quirks = sil_blacklist[n].quirk; quirks = sil_blacklist[n].quirk;
break; break;
} }
...@@ -380,16 +364,14 @@ static void sil_dev_config(struct ata_port *ap, struct ata_device *dev) ...@@ -380,16 +364,14 @@ static void sil_dev_config(struct ata_port *ap, struct ata_device *dev)
(quirks & SIL_QUIRK_MOD15WRITE))) { (quirks & SIL_QUIRK_MOD15WRITE))) {
printk(KERN_INFO "ata%u(%u): applying Seagate errata fix (mod15write workaround)\n", printk(KERN_INFO "ata%u(%u): applying Seagate errata fix (mod15write workaround)\n",
ap->id, dev->devno); ap->id, dev->devno);
ap->host->max_sectors = 15; dev->max_sectors = 15;
ap->host->hostt->max_sectors = 15;
dev->flags |= ATA_DFLAG_LOCK_SECTORS;
return; return;
} }
/* limit to udma5 */ /* limit to udma5 */
if (quirks & SIL_QUIRK_UDMA5MAX) { if (quirks & SIL_QUIRK_UDMA5MAX) {
printk(KERN_INFO "ata%u(%u): applying Maxtor errata fix %s\n", printk(KERN_INFO "ata%u(%u): applying Maxtor errata fix %s\n",
ap->id, dev->devno, s); ap->id, dev->devno, model_num);
ap->udma_mask &= ATA_UDMA5; ap->udma_mask &= ATA_UDMA5;
return; return;
} }
...@@ -431,13 +413,12 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -431,13 +413,12 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
if (rc) if (rc)
goto err_out_regions; goto err_out_regions;
probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL); probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL);
if (probe_ent == NULL) { if (probe_ent == NULL) {
rc = -ENOMEM; rc = -ENOMEM;
goto err_out_regions; goto err_out_regions;
} }
memset(probe_ent, 0, sizeof(*probe_ent));
INIT_LIST_HEAD(&probe_ent->node); INIT_LIST_HEAD(&probe_ent->node);
probe_ent->dev = pci_dev_to_dev(pdev); probe_ent->dev = pci_dev_to_dev(pdev);
probe_ent->port_ops = sil_port_info[ent->driver_data].port_ops; probe_ent->port_ops = sil_port_info[ent->driver_data].port_ops;
...@@ -474,19 +455,12 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -474,19 +455,12 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
if (cls) { if (cls) {
cls >>= 3; cls >>= 3;
cls++; /* cls = (line_size/8)+1 */ cls++; /* cls = (line_size/8)+1 */
writeb(cls, mmio_base + SIL_FIFO_R0); for (i = 0; i < probe_ent->n_ports; i++)
writeb(cls, mmio_base + SIL_FIFO_W0); writew(cls << 8 | cls,
writeb(cls, mmio_base + SIL_FIFO_R1); mmio_base + sil_port[i].fifo_cfg);
writeb(cls, mmio_base + SIL_FIFO_W1);
if (ent->driver_data == sil_3114) {
writeb(cls, mmio_base + SIL_FIFO_R2);
writeb(cls, mmio_base + SIL_FIFO_W2);
writeb(cls, mmio_base + SIL_FIFO_R3);
writeb(cls, mmio_base + SIL_FIFO_W3);
}
} else } else
dev_printk(KERN_WARNING, &pdev->dev, dev_printk(KERN_WARNING, &pdev->dev,
"cache line size not set. Driver may not function\n"); "cache line size not set. Driver may not function\n");
/* Apply R_ERR on DMA activate FIS errata workaround */ /* Apply R_ERR on DMA activate FIS errata workaround */
if (probe_ent->host_flags & SIL_FLAG_RERR_ON_DMA_ACT) { if (probe_ent->host_flags & SIL_FLAG_RERR_ON_DMA_ACT) {
...@@ -509,10 +483,10 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -509,10 +483,10 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
irq_mask = SIL_MASK_4PORT; irq_mask = SIL_MASK_4PORT;
/* flip the magic "make 4 ports work" bit */ /* flip the magic "make 4 ports work" bit */
tmp = readl(mmio_base + SIL_IDE2_BMDMA); tmp = readl(mmio_base + sil_port[2].bmdma);
if ((tmp & SIL_INTR_STEERING) == 0) if ((tmp & SIL_INTR_STEERING) == 0)
writel(tmp | SIL_INTR_STEERING, writel(tmp | SIL_INTR_STEERING,
mmio_base + SIL_IDE2_BMDMA); mmio_base + sil_port[2].bmdma);
} else { } else {
irq_mask = SIL_MASK_2PORT; irq_mask = SIL_MASK_2PORT;
......
...@@ -249,9 +249,9 @@ static u8 sil24_check_status(struct ata_port *ap); ...@@ -249,9 +249,9 @@ static u8 sil24_check_status(struct ata_port *ap);
static u32 sil24_scr_read(struct ata_port *ap, unsigned sc_reg); static u32 sil24_scr_read(struct ata_port *ap, unsigned sc_reg);
static void sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val); static void sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val);
static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf); static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
static void sil24_phy_reset(struct ata_port *ap); static int sil24_probe_reset(struct ata_port *ap, unsigned int *classes);
static void sil24_qc_prep(struct ata_queued_cmd *qc); static void sil24_qc_prep(struct ata_queued_cmd *qc);
static int sil24_qc_issue(struct ata_queued_cmd *qc); static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc);
static void sil24_irq_clear(struct ata_port *ap); static void sil24_irq_clear(struct ata_port *ap);
static void sil24_eng_timeout(struct ata_port *ap); static void sil24_eng_timeout(struct ata_port *ap);
static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *regs); static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
...@@ -262,6 +262,7 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -262,6 +262,7 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
static const struct pci_device_id sil24_pci_tbl[] = { static const struct pci_device_id sil24_pci_tbl[] = {
{ 0x1095, 0x3124, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3124 }, { 0x1095, 0x3124, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3124 },
{ 0x8086, 0x3124, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3124 },
{ 0x1095, 0x3132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3132 }, { 0x1095, 0x3132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3132 },
{ 0x1095, 0x3131, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3131 }, { 0x1095, 0x3131, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3131 },
{ 0x1095, 0x3531, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3131 }, { 0x1095, 0x3531, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3131 },
...@@ -280,11 +281,11 @@ static struct scsi_host_template sil24_sht = { ...@@ -280,11 +281,11 @@ static struct scsi_host_template sil24_sht = {
.name = DRV_NAME, .name = DRV_NAME,
.ioctl = ata_scsi_ioctl, .ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd, .queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error, .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE, .can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID, .this_id = ATA_SHT_THIS_ID,
.sg_tablesize = LIBATA_MAX_PRD, .sg_tablesize = LIBATA_MAX_PRD,
.max_sectors = ATA_MAX_SECTORS,
.cmd_per_lun = ATA_SHT_CMD_PER_LUN, .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
.emulated = ATA_SHT_EMULATED, .emulated = ATA_SHT_EMULATED,
.use_clustering = ATA_SHT_USE_CLUSTERING, .use_clustering = ATA_SHT_USE_CLUSTERING,
...@@ -305,7 +306,7 @@ static const struct ata_port_operations sil24_ops = { ...@@ -305,7 +306,7 @@ static const struct ata_port_operations sil24_ops = {
.tf_read = sil24_tf_read, .tf_read = sil24_tf_read,
.phy_reset = sil24_phy_reset, .probe_reset = sil24_probe_reset,
.qc_prep = sil24_qc_prep, .qc_prep = sil24_qc_prep,
.qc_issue = sil24_qc_issue, .qc_issue = sil24_qc_issue,
...@@ -335,8 +336,8 @@ static struct ata_port_info sil24_port_info[] = { ...@@ -335,8 +336,8 @@ static struct ata_port_info sil24_port_info[] = {
{ {
.sht = &sil24_sht, .sht = &sil24_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_SRST | ATA_FLAG_MMIO | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
ATA_FLAG_PIO_DMA | SIL24_NPORTS2FLAG(4), SIL24_NPORTS2FLAG(4),
.pio_mask = 0x1f, /* pio0-4 */ .pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */ .mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x3f, /* udma0-5 */ .udma_mask = 0x3f, /* udma0-5 */
...@@ -346,8 +347,8 @@ static struct ata_port_info sil24_port_info[] = { ...@@ -346,8 +347,8 @@ static struct ata_port_info sil24_port_info[] = {
{ {
.sht = &sil24_sht, .sht = &sil24_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_SRST | ATA_FLAG_MMIO | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
ATA_FLAG_PIO_DMA | SIL24_NPORTS2FLAG(2), SIL24_NPORTS2FLAG(2),
.pio_mask = 0x1f, /* pio0-4 */ .pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */ .mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x3f, /* udma0-5 */ .udma_mask = 0x3f, /* udma0-5 */
...@@ -357,8 +358,8 @@ static struct ata_port_info sil24_port_info[] = { ...@@ -357,8 +358,8 @@ static struct ata_port_info sil24_port_info[] = {
{ {
.sht = &sil24_sht, .sht = &sil24_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_SRST | ATA_FLAG_MMIO | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
ATA_FLAG_PIO_DMA | SIL24_NPORTS2FLAG(1), SIL24_NPORTS2FLAG(1),
.pio_mask = 0x1f, /* pio0-4 */ .pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */ .mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x3f, /* udma0-5 */ .udma_mask = 0x3f, /* udma0-5 */
...@@ -370,7 +371,7 @@ static void sil24_dev_config(struct ata_port *ap, struct ata_device *dev) ...@@ -370,7 +371,7 @@ static void sil24_dev_config(struct ata_port *ap, struct ata_device *dev)
{ {
void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
if (ap->cdb_len == 16) if (dev->cdb_len == 16)
writel(PORT_CS_CDB16, port + PORT_CTRL_STAT); writel(PORT_CS_CDB16, port + PORT_CTRL_STAT);
else else
writel(PORT_CS_CDB16, port + PORT_CTRL_CLR); writel(PORT_CS_CDB16, port + PORT_CTRL_CLR);
...@@ -427,14 +428,23 @@ static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf) ...@@ -427,14 +428,23 @@ static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
*tf = pp->tf; *tf = pp->tf;
} }
static int sil24_issue_SRST(struct ata_port *ap) static int sil24_softreset(struct ata_port *ap, int verbose,
unsigned int *class)
{ {
void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
struct sil24_port_priv *pp = ap->private_data; struct sil24_port_priv *pp = ap->private_data;
struct sil24_prb *prb = &pp->cmd_block[0].ata.prb; struct sil24_prb *prb = &pp->cmd_block[0].ata.prb;
dma_addr_t paddr = pp->cmd_block_dma; dma_addr_t paddr = pp->cmd_block_dma;
unsigned long timeout = jiffies + ATA_TMOUT_BOOT * HZ;
u32 irq_enable, irq_stat; u32 irq_enable, irq_stat;
int cnt;
DPRINTK("ENTER\n");
if (!sata_dev_present(ap)) {
DPRINTK("PHY reports no device\n");
*class = ATA_DEV_NONE;
goto out;
}
/* temporarily turn off IRQs during SRST */ /* temporarily turn off IRQs during SRST */
irq_enable = readl(port + PORT_IRQ_ENABLE_SET); irq_enable = readl(port + PORT_IRQ_ENABLE_SET);
...@@ -451,7 +461,7 @@ static int sil24_issue_SRST(struct ata_port *ap) ...@@ -451,7 +461,7 @@ static int sil24_issue_SRST(struct ata_port *ap)
writel((u32)paddr, port + PORT_CMD_ACTIVATE); writel((u32)paddr, port + PORT_CMD_ACTIVATE);
for (cnt = 0; cnt < 100; cnt++) { do {
irq_stat = readl(port + PORT_IRQ_STAT); irq_stat = readl(port + PORT_IRQ_STAT);
writel(irq_stat, port + PORT_IRQ_STAT); /* clear irq */ writel(irq_stat, port + PORT_IRQ_STAT); /* clear irq */
...@@ -459,36 +469,42 @@ static int sil24_issue_SRST(struct ata_port *ap) ...@@ -459,36 +469,42 @@ static int sil24_issue_SRST(struct ata_port *ap)
if (irq_stat & (PORT_IRQ_COMPLETE | PORT_IRQ_ERROR)) if (irq_stat & (PORT_IRQ_COMPLETE | PORT_IRQ_ERROR))
break; break;
msleep(1); msleep(100);
} } while (time_before(jiffies, timeout));
/* restore IRQs */ /* restore IRQs */
writel(irq_enable, port + PORT_IRQ_ENABLE_SET); writel(irq_enable, port + PORT_IRQ_ENABLE_SET);
if (!(irq_stat & PORT_IRQ_COMPLETE)) if (!(irq_stat & PORT_IRQ_COMPLETE)) {
return -1; DPRINTK("EXIT, srst failed\n");
return -EIO;
}
/* update TF */
sil24_update_tf(ap); sil24_update_tf(ap);
*class = ata_dev_classify(&pp->tf);
if (*class == ATA_DEV_UNKNOWN)
*class = ATA_DEV_NONE;
out:
DPRINTK("EXIT, class=%u\n", *class);
return 0; return 0;
} }
static void sil24_phy_reset(struct ata_port *ap) static int sil24_hardreset(struct ata_port *ap, int verbose,
unsigned int *class)
{ {
struct sil24_port_priv *pp = ap->private_data; unsigned int dummy_class;
__sata_phy_reset(ap); /* sil24 doesn't report device signature after hard reset */
if (ap->flags & ATA_FLAG_PORT_DISABLED) return sata_std_hardreset(ap, verbose, &dummy_class);
return; }
if (sil24_issue_SRST(ap) < 0) {
printk(KERN_ERR DRV_NAME
" ata%u: SRST failed, disabling port\n", ap->id);
ap->ops->port_disable(ap);
return;
}
ap->device->class = ata_dev_classify(&pp->tf); static int sil24_probe_reset(struct ata_port *ap, unsigned int *classes)
{
return ata_drive_probe_reset(ap, ata_std_probeinit,
sil24_softreset, sil24_hardreset,
ata_std_postreset, classes);
} }
static inline void sil24_fill_sg(struct ata_queued_cmd *qc, static inline void sil24_fill_sg(struct ata_queued_cmd *qc,
...@@ -533,7 +549,7 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc) ...@@ -533,7 +549,7 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc)
prb = &cb->atapi.prb; prb = &cb->atapi.prb;
sge = cb->atapi.sge; sge = cb->atapi.sge;
memset(cb->atapi.cdb, 0, 32); memset(cb->atapi.cdb, 0, 32);
memcpy(cb->atapi.cdb, qc->cdb, ap->cdb_len); memcpy(cb->atapi.cdb, qc->cdb, qc->dev->cdb_len);
if (qc->tf.protocol != ATA_PROT_ATAPI_NODATA) { if (qc->tf.protocol != ATA_PROT_ATAPI_NODATA) {
if (qc->tf.flags & ATA_TFLAG_WRITE) if (qc->tf.flags & ATA_TFLAG_WRITE)
...@@ -557,7 +573,7 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc) ...@@ -557,7 +573,7 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc)
sil24_fill_sg(qc, sge); sil24_fill_sg(qc, sge);
} }
static int sil24_qc_issue(struct ata_queued_cmd *qc) static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc)
{ {
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
...@@ -638,23 +654,10 @@ static void sil24_eng_timeout(struct ata_port *ap) ...@@ -638,23 +654,10 @@ static void sil24_eng_timeout(struct ata_port *ap)
struct ata_queued_cmd *qc; struct ata_queued_cmd *qc;
qc = ata_qc_from_tag(ap, ap->active_tag); qc = ata_qc_from_tag(ap, ap->active_tag);
if (!qc) {
printk(KERN_ERR "ata%u: BUG: timeout without command\n",
ap->id);
return;
}
/*
* hack alert! We cannot use the supplied completion
* function from inside the ->eh_strategy_handler() thread.
* libata is the only user of ->eh_strategy_handler() in
* any kernel, so the default scsi_done() assumes it is
* not being called from the SCSI EH.
*/
printk(KERN_ERR "ata%u: command timeout\n", ap->id); printk(KERN_ERR "ata%u: command timeout\n", ap->id);
qc->scsidone = scsi_finish_command; qc->err_mask |= AC_ERR_TIMEOUT;
qc->err_mask |= AC_ERR_OTHER; ata_eh_qc_complete(qc);
ata_qc_complete(qc);
sil24_reset_controller(ap); sil24_reset_controller(ap);
} }
...@@ -895,6 +898,7 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -895,6 +898,7 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
probe_ent->sht = pinfo->sht; probe_ent->sht = pinfo->sht;
probe_ent->host_flags = pinfo->host_flags; probe_ent->host_flags = pinfo->host_flags;
probe_ent->pio_mask = pinfo->pio_mask; probe_ent->pio_mask = pinfo->pio_mask;
probe_ent->mwdma_mask = pinfo->mwdma_mask;
probe_ent->udma_mask = pinfo->udma_mask; probe_ent->udma_mask = pinfo->udma_mask;
probe_ent->port_ops = pinfo->port_ops; probe_ent->port_ops = pinfo->port_ops;
probe_ent->n_ports = SIL24_FLAG2NPORTS(pinfo->host_flags); probe_ent->n_ports = SIL24_FLAG2NPORTS(pinfo->host_flags);
......
...@@ -87,11 +87,11 @@ static struct scsi_host_template sis_sht = { ...@@ -87,11 +87,11 @@ static struct scsi_host_template sis_sht = {
.name = DRV_NAME, .name = DRV_NAME,
.ioctl = ata_scsi_ioctl, .ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd, .queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error, .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE, .can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID, .this_id = ATA_SHT_THIS_ID,
.sg_tablesize = ATA_MAX_PRD, .sg_tablesize = ATA_MAX_PRD,
.max_sectors = ATA_MAX_SECTORS,
.cmd_per_lun = ATA_SHT_CMD_PER_LUN, .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
.emulated = ATA_SHT_EMULATED, .emulated = ATA_SHT_EMULATED,
.use_clustering = ATA_SHT_USE_CLUSTERING, .use_clustering = ATA_SHT_USE_CLUSTERING,
......
...@@ -288,11 +288,11 @@ static struct scsi_host_template k2_sata_sht = { ...@@ -288,11 +288,11 @@ static struct scsi_host_template k2_sata_sht = {
.name = DRV_NAME, .name = DRV_NAME,
.ioctl = ata_scsi_ioctl, .ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd, .queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error, .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE, .can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID, .this_id = ATA_SHT_THIS_ID,
.sg_tablesize = LIBATA_MAX_PRD, .sg_tablesize = LIBATA_MAX_PRD,
.max_sectors = ATA_MAX_SECTORS,
.cmd_per_lun = ATA_SHT_CMD_PER_LUN, .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
.emulated = ATA_SHT_EMULATED, .emulated = ATA_SHT_EMULATED,
.use_clustering = ATA_SHT_USE_CLUSTERING, .use_clustering = ATA_SHT_USE_CLUSTERING,
......
...@@ -174,7 +174,7 @@ static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, ...@@ -174,7 +174,7 @@ static void pdc20621_get_from_dimm(struct ata_probe_ent *pe,
static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, static void pdc20621_put_to_dimm(struct ata_probe_ent *pe,
void *psource, u32 offset, u32 size); void *psource, u32 offset, u32 size);
static void pdc20621_irq_clear(struct ata_port *ap); static void pdc20621_irq_clear(struct ata_port *ap);
static int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc); static unsigned int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc);
static struct scsi_host_template pdc_sata_sht = { static struct scsi_host_template pdc_sata_sht = {
...@@ -182,11 +182,11 @@ static struct scsi_host_template pdc_sata_sht = { ...@@ -182,11 +182,11 @@ static struct scsi_host_template pdc_sata_sht = {
.name = DRV_NAME, .name = DRV_NAME,
.ioctl = ata_scsi_ioctl, .ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd, .queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error, .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE, .can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID, .this_id = ATA_SHT_THIS_ID,
.sg_tablesize = LIBATA_MAX_PRD, .sg_tablesize = LIBATA_MAX_PRD,
.max_sectors = ATA_MAX_SECTORS,
.cmd_per_lun = ATA_SHT_CMD_PER_LUN, .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
.emulated = ATA_SHT_EMULATED, .emulated = ATA_SHT_EMULATED,
.use_clustering = ATA_SHT_USE_CLUSTERING, .use_clustering = ATA_SHT_USE_CLUSTERING,
...@@ -460,7 +460,7 @@ static void pdc20621_dma_prep(struct ata_queued_cmd *qc) ...@@ -460,7 +460,7 @@ static void pdc20621_dma_prep(struct ata_queued_cmd *qc)
unsigned int i, idx, total_len = 0, sgt_len; unsigned int i, idx, total_len = 0, sgt_len;
u32 *buf = (u32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ]; u32 *buf = (u32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ];
assert(qc->flags & ATA_QCFLAG_DMAMAP); WARN_ON(!(qc->flags & ATA_QCFLAG_DMAMAP));
VPRINTK("ata%u: ENTER\n", ap->id); VPRINTK("ata%u: ENTER\n", ap->id);
...@@ -678,7 +678,7 @@ static void pdc20621_packet_start(struct ata_queued_cmd *qc) ...@@ -678,7 +678,7 @@ static void pdc20621_packet_start(struct ata_queued_cmd *qc)
} }
} }
static int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc) static unsigned int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc)
{ {
switch (qc->tf.protocol) { switch (qc->tf.protocol) {
case ATA_PROT_DMA: case ATA_PROT_DMA:
...@@ -866,26 +866,12 @@ static void pdc_eng_timeout(struct ata_port *ap) ...@@ -866,26 +866,12 @@ static void pdc_eng_timeout(struct ata_port *ap)
spin_lock_irqsave(&host_set->lock, flags); spin_lock_irqsave(&host_set->lock, flags);
qc = ata_qc_from_tag(ap, ap->active_tag); qc = ata_qc_from_tag(ap, ap->active_tag);
if (!qc) {
printk(KERN_ERR "ata%u: BUG: timeout without command\n",
ap->id);
goto out;
}
/* hack alert! We cannot use the supplied completion
* function from inside the ->eh_strategy_handler() thread.
* libata is the only user of ->eh_strategy_handler() in
* any kernel, so the default scsi_done() assumes it is
* not being called from the SCSI EH.
*/
qc->scsidone = scsi_finish_command;
switch (qc->tf.protocol) { switch (qc->tf.protocol) {
case ATA_PROT_DMA: case ATA_PROT_DMA:
case ATA_PROT_NODATA: case ATA_PROT_NODATA:
printk(KERN_ERR "ata%u: command timeout\n", ap->id); printk(KERN_ERR "ata%u: command timeout\n", ap->id);
qc->err_mask |= __ac_err_mask(ata_wait_idle(ap)); qc->err_mask |= __ac_err_mask(ata_wait_idle(ap));
ata_qc_complete(qc);
break; break;
default: default:
...@@ -895,12 +881,11 @@ static void pdc_eng_timeout(struct ata_port *ap) ...@@ -895,12 +881,11 @@ static void pdc_eng_timeout(struct ata_port *ap)
ap->id, qc->tf.command, drv_stat); ap->id, qc->tf.command, drv_stat);
qc->err_mask |= ac_err_mask(drv_stat); qc->err_mask |= ac_err_mask(drv_stat);
ata_qc_complete(qc);
break; break;
} }
out:
spin_unlock_irqrestore(&host_set->lock, flags); spin_unlock_irqrestore(&host_set->lock, flags);
ata_eh_qc_complete(qc);
DPRINTK("EXIT\n"); DPRINTK("EXIT\n");
} }
......
...@@ -75,11 +75,11 @@ static struct scsi_host_template uli_sht = { ...@@ -75,11 +75,11 @@ static struct scsi_host_template uli_sht = {
.name = DRV_NAME, .name = DRV_NAME,
.ioctl = ata_scsi_ioctl, .ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd, .queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error, .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE, .can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID, .this_id = ATA_SHT_THIS_ID,
.sg_tablesize = LIBATA_MAX_PRD, .sg_tablesize = LIBATA_MAX_PRD,
.max_sectors = ATA_MAX_SECTORS,
.cmd_per_lun = ATA_SHT_CMD_PER_LUN, .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
.emulated = ATA_SHT_EMULATED, .emulated = ATA_SHT_EMULATED,
.use_clustering = ATA_SHT_USE_CLUSTERING, .use_clustering = ATA_SHT_USE_CLUSTERING,
......
...@@ -94,11 +94,11 @@ static struct scsi_host_template svia_sht = { ...@@ -94,11 +94,11 @@ static struct scsi_host_template svia_sht = {
.name = DRV_NAME, .name = DRV_NAME,
.ioctl = ata_scsi_ioctl, .ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd, .queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error, .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE, .can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID, .this_id = ATA_SHT_THIS_ID,
.sg_tablesize = LIBATA_MAX_PRD, .sg_tablesize = LIBATA_MAX_PRD,
.max_sectors = ATA_MAX_SECTORS,
.cmd_per_lun = ATA_SHT_CMD_PER_LUN, .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
.emulated = ATA_SHT_EMULATED, .emulated = ATA_SHT_EMULATED,
.use_clustering = ATA_SHT_USE_CLUSTERING, .use_clustering = ATA_SHT_USE_CLUSTERING,
......
...@@ -251,11 +251,11 @@ static struct scsi_host_template vsc_sata_sht = { ...@@ -251,11 +251,11 @@ static struct scsi_host_template vsc_sata_sht = {
.name = DRV_NAME, .name = DRV_NAME,
.ioctl = ata_scsi_ioctl, .ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd, .queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error, .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE, .can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID, .this_id = ATA_SHT_THIS_ID,
.sg_tablesize = LIBATA_MAX_PRD, .sg_tablesize = LIBATA_MAX_PRD,
.max_sectors = ATA_MAX_SECTORS,
.cmd_per_lun = ATA_SHT_CMD_PER_LUN, .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
.emulated = ATA_SHT_EMULATED, .emulated = ATA_SHT_EMULATED,
.use_clustering = ATA_SHT_USE_CLUSTERING, .use_clustering = ATA_SHT_USE_CLUSTERING,
......
...@@ -584,8 +584,7 @@ static int scsi_request_sense(struct scsi_cmnd *scmd) ...@@ -584,8 +584,7 @@ static int scsi_request_sense(struct scsi_cmnd *scmd)
* keep a list of pending commands for final completion, and once we * keep a list of pending commands for final completion, and once we
* are ready to leave error handling we handle completion for real. * are ready to leave error handling we handle completion for real.
**/ **/
static void scsi_eh_finish_cmd(struct scsi_cmnd *scmd, void scsi_eh_finish_cmd(struct scsi_cmnd *scmd, struct list_head *done_q)
struct list_head *done_q)
{ {
scmd->device->host->host_failed--; scmd->device->host->host_failed--;
scmd->eh_eflags = 0; scmd->eh_eflags = 0;
...@@ -597,6 +596,7 @@ static void scsi_eh_finish_cmd(struct scsi_cmnd *scmd, ...@@ -597,6 +596,7 @@ static void scsi_eh_finish_cmd(struct scsi_cmnd *scmd,
scsi_setup_cmd_retry(scmd); scsi_setup_cmd_retry(scmd);
list_move_tail(&scmd->eh_entry, done_q); list_move_tail(&scmd->eh_entry, done_q);
} }
EXPORT_SYMBOL(scsi_eh_finish_cmd);
/** /**
* scsi_eh_get_sense - Get device sense data. * scsi_eh_get_sense - Get device sense data.
...@@ -1425,7 +1425,7 @@ static void scsi_eh_ready_devs(struct Scsi_Host *shost, ...@@ -1425,7 +1425,7 @@ static void scsi_eh_ready_devs(struct Scsi_Host *shost,
* @done_q: list_head of processed commands. * @done_q: list_head of processed commands.
* *
**/ **/
static void scsi_eh_flush_done_q(struct list_head *done_q) void scsi_eh_flush_done_q(struct list_head *done_q)
{ {
struct scsi_cmnd *scmd, *next; struct scsi_cmnd *scmd, *next;
...@@ -1454,6 +1454,7 @@ static void scsi_eh_flush_done_q(struct list_head *done_q) ...@@ -1454,6 +1454,7 @@ static void scsi_eh_flush_done_q(struct list_head *done_q)
} }
} }
} }
EXPORT_SYMBOL(scsi_eh_flush_done_q);
/** /**
* scsi_unjam_host - Attempt to fix a host which has a cmd that failed. * scsi_unjam_host - Attempt to fix a host which has a cmd that failed.
......
...@@ -267,6 +267,16 @@ struct ata_taskfile { ...@@ -267,6 +267,16 @@ struct ata_taskfile {
((u64) (id)[(n) + 1] << 16) | \ ((u64) (id)[(n) + 1] << 16) | \
((u64) (id)[(n) + 0]) ) ((u64) (id)[(n) + 0]) )
static inline unsigned int ata_id_major_version(const u16 *id)
{
unsigned int mver;
for (mver = 14; mver >= 1; mver--)
if (id[ATA_ID_MAJOR_VER] & (1 << mver))
break;
return mver;
}
static inline int ata_id_current_chs_valid(const u16 *id) static inline int ata_id_current_chs_valid(const u16 *id)
{ {
/* For ATA-1 devices, if the INITIALIZE DEVICE PARAMETERS command /* For ATA-1 devices, if the INITIALIZE DEVICE PARAMETERS command
...@@ -302,4 +312,16 @@ static inline int ata_ok(u8 status) ...@@ -302,4 +312,16 @@ static inline int ata_ok(u8 status)
== ATA_DRDY); == ATA_DRDY);
} }
static inline int lba_28_ok(u64 block, u32 n_block)
{
/* check the ending block number */
return ((block + n_block - 1) < ((u64)1 << 28)) && (n_block <= 256);
}
static inline int lba_48_ok(u64 block, u32 n_block)
{
/* check the ending block number */
return ((block + n_block - 1) < ((u64)1 << 48)) && (n_block <= 65536);
}
#endif /* __LINUX_ATA_H__ */ #endif /* __LINUX_ATA_H__ */
...@@ -35,7 +35,8 @@ ...@@ -35,7 +35,8 @@
#include <linux/workqueue.h> #include <linux/workqueue.h>
/* /*
* compile-time options * compile-time options: to be removed as soon as all the drivers are
* converted to the new debugging mechanism
*/ */
#undef ATA_DEBUG /* debugging output */ #undef ATA_DEBUG /* debugging output */
#undef ATA_VERBOSE_DEBUG /* yet more debugging output */ #undef ATA_VERBOSE_DEBUG /* yet more debugging output */
...@@ -61,15 +62,37 @@ ...@@ -61,15 +62,37 @@
#define BPRINTK(fmt, args...) if (ap->flags & ATA_FLAG_DEBUGMSG) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args) #define BPRINTK(fmt, args...) if (ap->flags & ATA_FLAG_DEBUGMSG) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args)
#ifdef ATA_NDEBUG /* NEW: debug levels */
#define assert(expr) #define HAVE_LIBATA_MSG 1
#else
#define assert(expr) \ enum {
if(unlikely(!(expr))) { \ ATA_MSG_DRV = 0x0001,
printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \ ATA_MSG_INFO = 0x0002,
#expr,__FILE__,__FUNCTION__,__LINE__); \ ATA_MSG_PROBE = 0x0004,
} ATA_MSG_WARN = 0x0008,
#endif ATA_MSG_MALLOC = 0x0010,
ATA_MSG_CTL = 0x0020,
ATA_MSG_INTR = 0x0040,
ATA_MSG_ERR = 0x0080,
};
#define ata_msg_drv(p) ((p)->msg_enable & ATA_MSG_DRV)
#define ata_msg_info(p) ((p)->msg_enable & ATA_MSG_INFO)
#define ata_msg_probe(p) ((p)->msg_enable & ATA_MSG_PROBE)
#define ata_msg_warn(p) ((p)->msg_enable & ATA_MSG_WARN)
#define ata_msg_malloc(p) ((p)->msg_enable & ATA_MSG_MALLOC)
#define ata_msg_ctl(p) ((p)->msg_enable & ATA_MSG_CTL)
#define ata_msg_intr(p) ((p)->msg_enable & ATA_MSG_INTR)
#define ata_msg_err(p) ((p)->msg_enable & ATA_MSG_ERR)
static inline u32 ata_msg_init(int dval, int default_msg_enable_bits)
{
if (dval < 0 || dval >= (sizeof(u32) * 8))
return default_msg_enable_bits; /* should be 0x1 - only driver info msgs */
if (!dval)
return 0;
return (1 << dval) - 1;
}
/* defines only for the constants which don't work well as enums */ /* defines only for the constants which don't work well as enums */
#define ATA_TAG_POISON 0xfafbfcfdU #define ATA_TAG_POISON 0xfafbfcfdU
...@@ -99,8 +122,7 @@ enum { ...@@ -99,8 +122,7 @@ enum {
/* struct ata_device stuff */ /* struct ata_device stuff */
ATA_DFLAG_LBA48 = (1 << 0), /* device supports LBA48 */ ATA_DFLAG_LBA48 = (1 << 0), /* device supports LBA48 */
ATA_DFLAG_PIO = (1 << 1), /* device currently in PIO mode */ ATA_DFLAG_PIO = (1 << 1), /* device currently in PIO mode */
ATA_DFLAG_LOCK_SECTORS = (1 << 2), /* don't adjust max_sectors */ ATA_DFLAG_LBA = (1 << 2), /* device supports LBA */
ATA_DFLAG_LBA = (1 << 3), /* device supports LBA */
ATA_DEV_UNKNOWN = 0, /* unknown device */ ATA_DEV_UNKNOWN = 0, /* unknown device */
ATA_DEV_ATA = 1, /* ATA device */ ATA_DEV_ATA = 1, /* ATA device */
...@@ -115,9 +137,9 @@ enum { ...@@ -115,9 +137,9 @@ enum {
ATA_FLAG_PORT_DISABLED = (1 << 2), /* port is disabled, ignore it */ ATA_FLAG_PORT_DISABLED = (1 << 2), /* port is disabled, ignore it */
ATA_FLAG_SATA = (1 << 3), ATA_FLAG_SATA = (1 << 3),
ATA_FLAG_NO_LEGACY = (1 << 4), /* no legacy mode check */ ATA_FLAG_NO_LEGACY = (1 << 4), /* no legacy mode check */
ATA_FLAG_SRST = (1 << 5), /* use ATA SRST, not E.D.D. */ ATA_FLAG_SRST = (1 << 5), /* (obsolete) use ATA SRST, not E.D.D. */
ATA_FLAG_MMIO = (1 << 6), /* use MMIO, not PIO */ ATA_FLAG_MMIO = (1 << 6), /* use MMIO, not PIO */
ATA_FLAG_SATA_RESET = (1 << 7), /* use COMRESET */ ATA_FLAG_SATA_RESET = (1 << 7), /* (obsolete) use COMRESET */
ATA_FLAG_PIO_DMA = (1 << 8), /* PIO cmds via DMA */ ATA_FLAG_PIO_DMA = (1 << 8), /* PIO cmds via DMA */
ATA_FLAG_NOINTR = (1 << 9), /* FIXME: Remove this once ATA_FLAG_NOINTR = (1 << 9), /* FIXME: Remove this once
* proper HSM is in place. */ * proper HSM is in place. */
...@@ -129,10 +151,14 @@ enum { ...@@ -129,10 +151,14 @@ enum {
ATA_FLAG_PIO_LBA48 = (1 << 13), /* Host DMA engine is LBA28 only */ ATA_FLAG_PIO_LBA48 = (1 << 13), /* Host DMA engine is LBA28 only */
ATA_FLAG_IRQ_MASK = (1 << 14), /* Mask IRQ in PIO xfers */ ATA_FLAG_IRQ_MASK = (1 << 14), /* Mask IRQ in PIO xfers */
ATA_FLAG_FLUSH_PORT_TASK = (1 << 15), /* Flush port task */
ATA_FLAG_IN_EH = (1 << 16), /* EH in progress */
ATA_QCFLAG_ACTIVE = (1 << 1), /* cmd not yet ack'd to scsi lyer */ ATA_QCFLAG_ACTIVE = (1 << 1), /* cmd not yet ack'd to scsi lyer */
ATA_QCFLAG_SG = (1 << 3), /* have s/g table? */ ATA_QCFLAG_SG = (1 << 3), /* have s/g table? */
ATA_QCFLAG_SINGLE = (1 << 4), /* no s/g, just a single buffer */ ATA_QCFLAG_SINGLE = (1 << 4), /* no s/g, just a single buffer */
ATA_QCFLAG_DMAMAP = ATA_QCFLAG_SG | ATA_QCFLAG_SINGLE, ATA_QCFLAG_DMAMAP = ATA_QCFLAG_SG | ATA_QCFLAG_SINGLE,
ATA_QCFLAG_EH_SCHEDULED = (1 << 5), /* EH scheduled */
/* various lengths of time */ /* various lengths of time */
ATA_TMOUT_EDD = 5 * HZ, /* heuristic */ ATA_TMOUT_EDD = 5 * HZ, /* heuristic */
...@@ -162,11 +188,19 @@ enum { ...@@ -162,11 +188,19 @@ enum {
PORT_DISABLED = 2, PORT_DISABLED = 2,
/* encoding various smaller bitmaps into a single /* encoding various smaller bitmaps into a single
* unsigned long bitmap * unsigned int bitmap
*/ */
ATA_SHIFT_UDMA = 0, ATA_BITS_PIO = 5,
ATA_SHIFT_MWDMA = 8, ATA_BITS_MWDMA = 3,
ATA_SHIFT_PIO = 11, ATA_BITS_UDMA = 8,
ATA_SHIFT_PIO = 0,
ATA_SHIFT_MWDMA = ATA_SHIFT_PIO + ATA_BITS_PIO,
ATA_SHIFT_UDMA = ATA_SHIFT_MWDMA + ATA_BITS_MWDMA,
ATA_MASK_PIO = ((1 << ATA_BITS_PIO) - 1) << ATA_SHIFT_PIO,
ATA_MASK_MWDMA = ((1 << ATA_BITS_MWDMA) - 1) << ATA_SHIFT_MWDMA,
ATA_MASK_UDMA = ((1 << ATA_BITS_UDMA) - 1) << ATA_SHIFT_UDMA,
/* size of buffer to pad xfers ending on unaligned boundaries */ /* size of buffer to pad xfers ending on unaligned boundaries */
ATA_DMA_PAD_SZ = 4, ATA_DMA_PAD_SZ = 4,
...@@ -189,10 +223,15 @@ enum hsm_task_states { ...@@ -189,10 +223,15 @@ enum hsm_task_states {
}; };
enum ata_completion_errors { enum ata_completion_errors {
AC_ERR_OTHER = (1 << 0), AC_ERR_DEV = (1 << 0), /* device reported error */
AC_ERR_DEV = (1 << 1), AC_ERR_HSM = (1 << 1), /* host state machine violation */
AC_ERR_ATA_BUS = (1 << 2), AC_ERR_TIMEOUT = (1 << 2), /* timeout */
AC_ERR_HOST_BUS = (1 << 3), AC_ERR_MEDIA = (1 << 3), /* media error */
AC_ERR_ATA_BUS = (1 << 4), /* ATA bus error */
AC_ERR_HOST_BUS = (1 << 5), /* host bus error */
AC_ERR_SYSTEM = (1 << 6), /* system error */
AC_ERR_INVALID = (1 << 7), /* invalid argument */
AC_ERR_OTHER = (1 << 8), /* unknown */
}; };
/* forward declarations */ /* forward declarations */
...@@ -202,7 +241,10 @@ struct ata_port; ...@@ -202,7 +241,10 @@ struct ata_port;
struct ata_queued_cmd; struct ata_queued_cmd;
/* typedefs */ /* typedefs */
typedef int (*ata_qc_cb_t) (struct ata_queued_cmd *qc); typedef void (*ata_qc_cb_t) (struct ata_queued_cmd *qc);
typedef void (*ata_probeinit_fn_t)(struct ata_port *);
typedef int (*ata_reset_fn_t)(struct ata_port *, int, unsigned int *);
typedef void (*ata_postreset_fn_t)(struct ata_port *ap, unsigned int *);
struct ata_ioports { struct ata_ioports {
unsigned long cmd_addr; unsigned long cmd_addr;
...@@ -305,7 +347,7 @@ struct ata_device { ...@@ -305,7 +347,7 @@ struct ata_device {
unsigned long flags; /* ATA_DFLAG_xxx */ unsigned long flags; /* ATA_DFLAG_xxx */
unsigned int class; /* ATA_DEV_xxx */ unsigned int class; /* ATA_DEV_xxx */
unsigned int devno; /* 0 or 1 */ unsigned int devno; /* 0 or 1 */
u16 id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */ u16 *id; /* IDENTIFY xxx DEVICE data */
u8 pio_mode; u8 pio_mode;
u8 dma_mode; u8 dma_mode;
u8 xfer_mode; u8 xfer_mode;
...@@ -313,6 +355,8 @@ struct ata_device { ...@@ -313,6 +355,8 @@ struct ata_device {
unsigned int multi_count; /* sectors count for unsigned int multi_count; /* sectors count for
READ/WRITE MULTIPLE */ READ/WRITE MULTIPLE */
unsigned int max_sectors; /* per-device max sectors */
unsigned int cdb_len;
/* for CHS addressing */ /* for CHS addressing */
u16 cylinders; /* Number of cylinders */ u16 cylinders; /* Number of cylinders */
...@@ -342,7 +386,6 @@ struct ata_port { ...@@ -342,7 +386,6 @@ struct ata_port {
unsigned int mwdma_mask; unsigned int mwdma_mask;
unsigned int udma_mask; unsigned int udma_mask;
unsigned int cbl; /* cable type; ATA_CBL_xxx */ unsigned int cbl; /* cable type; ATA_CBL_xxx */
unsigned int cdb_len;
struct ata_device device[ATA_MAX_DEVICES]; struct ata_device device[ATA_MAX_DEVICES];
...@@ -353,12 +396,14 @@ struct ata_port { ...@@ -353,12 +396,14 @@ struct ata_port {
struct ata_host_stats stats; struct ata_host_stats stats;
struct ata_host_set *host_set; struct ata_host_set *host_set;
struct work_struct packet_task; struct work_struct port_task;
struct work_struct pio_task;
unsigned int hsm_task_state; unsigned int hsm_task_state;
unsigned long pio_task_timeout; unsigned long pio_task_timeout;
u32 msg_enable;
struct list_head eh_done_q;
void *private_data; void *private_data;
}; };
...@@ -378,7 +423,9 @@ struct ata_port_operations { ...@@ -378,7 +423,9 @@ struct ata_port_operations {
u8 (*check_altstatus)(struct ata_port *ap); u8 (*check_altstatus)(struct ata_port *ap);
void (*dev_select)(struct ata_port *ap, unsigned int device); void (*dev_select)(struct ata_port *ap, unsigned int device);
void (*phy_reset) (struct ata_port *ap); void (*phy_reset) (struct ata_port *ap); /* obsolete */
int (*probe_reset) (struct ata_port *ap, unsigned int *classes);
void (*post_set_mode) (struct ata_port *ap); void (*post_set_mode) (struct ata_port *ap);
int (*check_atapi_dma) (struct ata_queued_cmd *qc); int (*check_atapi_dma) (struct ata_queued_cmd *qc);
...@@ -387,7 +434,7 @@ struct ata_port_operations { ...@@ -387,7 +434,7 @@ struct ata_port_operations {
void (*bmdma_start) (struct ata_queued_cmd *qc); void (*bmdma_start) (struct ata_queued_cmd *qc);
void (*qc_prep) (struct ata_queued_cmd *qc); void (*qc_prep) (struct ata_queued_cmd *qc);
int (*qc_issue) (struct ata_queued_cmd *qc); unsigned int (*qc_issue) (struct ata_queued_cmd *qc);
void (*eng_timeout) (struct ata_port *ap); void (*eng_timeout) (struct ata_port *ap);
...@@ -435,6 +482,18 @@ extern void ata_port_probe(struct ata_port *); ...@@ -435,6 +482,18 @@ extern void ata_port_probe(struct ata_port *);
extern void __sata_phy_reset(struct ata_port *ap); extern void __sata_phy_reset(struct ata_port *ap);
extern void sata_phy_reset(struct ata_port *ap); extern void sata_phy_reset(struct ata_port *ap);
extern void ata_bus_reset(struct ata_port *ap); extern void ata_bus_reset(struct ata_port *ap);
extern int ata_drive_probe_reset(struct ata_port *ap,
ata_probeinit_fn_t probeinit,
ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
ata_postreset_fn_t postreset, unsigned int *classes);
extern void ata_std_probeinit(struct ata_port *ap);
extern int ata_std_softreset(struct ata_port *ap, int verbose,
unsigned int *classes);
extern int sata_std_hardreset(struct ata_port *ap, int verbose,
unsigned int *class);
extern void ata_std_postreset(struct ata_port *ap, unsigned int *classes);
extern int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev,
int post_reset);
extern void ata_port_disable(struct ata_port *); extern void ata_port_disable(struct ata_port *);
extern void ata_std_ports(struct ata_ioports *ioaddr); extern void ata_std_ports(struct ata_ioports *ioaddr);
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
...@@ -449,7 +508,10 @@ extern void ata_host_set_remove(struct ata_host_set *host_set); ...@@ -449,7 +508,10 @@ extern void ata_host_set_remove(struct ata_host_set *host_set);
extern int ata_scsi_detect(struct scsi_host_template *sht); extern int ata_scsi_detect(struct scsi_host_template *sht);
extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg); extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg);
extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)); extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *));
extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd);
extern int ata_scsi_error(struct Scsi_Host *host); extern int ata_scsi_error(struct Scsi_Host *host);
extern void ata_eh_qc_complete(struct ata_queued_cmd *qc);
extern void ata_eh_qc_retry(struct ata_queued_cmd *qc);
extern int ata_scsi_release(struct Scsi_Host *host); extern int ata_scsi_release(struct Scsi_Host *host);
extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc); extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc);
extern int ata_scsi_device_resume(struct scsi_device *); extern int ata_scsi_device_resume(struct scsi_device *);
...@@ -457,6 +519,11 @@ extern int ata_scsi_device_suspend(struct scsi_device *); ...@@ -457,6 +519,11 @@ extern int ata_scsi_device_suspend(struct scsi_device *);
extern int ata_device_resume(struct ata_port *, struct ata_device *); extern int ata_device_resume(struct ata_port *, struct ata_device *);
extern int ata_device_suspend(struct ata_port *, struct ata_device *); extern int ata_device_suspend(struct ata_port *, struct ata_device *);
extern int ata_ratelimit(void); extern int ata_ratelimit(void);
extern unsigned int ata_busy_sleep(struct ata_port *ap,
unsigned long timeout_pat,
unsigned long timeout);
extern void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *),
void *data, unsigned long delay);
/* /*
* Default driver ops implementations * Default driver ops implementations
...@@ -470,26 +537,28 @@ extern void ata_std_dev_select (struct ata_port *ap, unsigned int device); ...@@ -470,26 +537,28 @@ extern void ata_std_dev_select (struct ata_port *ap, unsigned int device);
extern u8 ata_check_status(struct ata_port *ap); extern u8 ata_check_status(struct ata_port *ap);
extern u8 ata_altstatus(struct ata_port *ap); extern u8 ata_altstatus(struct ata_port *ap);
extern void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf); extern void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf);
extern int ata_std_probe_reset(struct ata_port *ap, unsigned int *classes);
extern int ata_port_start (struct ata_port *ap); extern int ata_port_start (struct ata_port *ap);
extern void ata_port_stop (struct ata_port *ap); extern void ata_port_stop (struct ata_port *ap);
extern void ata_host_stop (struct ata_host_set *host_set); extern void ata_host_stop (struct ata_host_set *host_set);
extern irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs); extern irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
extern void ata_qc_prep(struct ata_queued_cmd *qc); extern void ata_qc_prep(struct ata_queued_cmd *qc);
extern int ata_qc_issue_prot(struct ata_queued_cmd *qc); extern unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc);
extern void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, extern void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf,
unsigned int buflen); unsigned int buflen);
extern void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg, extern void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg,
unsigned int n_elem); unsigned int n_elem);
extern unsigned int ata_dev_classify(const struct ata_taskfile *tf); extern unsigned int ata_dev_classify(const struct ata_taskfile *tf);
extern void ata_dev_id_string(const u16 *id, unsigned char *s, extern void ata_id_string(const u16 *id, unsigned char *s,
unsigned int ofs, unsigned int len); unsigned int ofs, unsigned int len);
extern void ata_dev_config(struct ata_port *ap, unsigned int i); extern void ata_id_c_string(const u16 *id, unsigned char *s,
unsigned int ofs, unsigned int len);
extern void ata_bmdma_setup (struct ata_queued_cmd *qc); extern void ata_bmdma_setup (struct ata_queued_cmd *qc);
extern void ata_bmdma_start (struct ata_queued_cmd *qc); extern void ata_bmdma_start (struct ata_queued_cmd *qc);
extern void ata_bmdma_stop(struct ata_queued_cmd *qc); extern void ata_bmdma_stop(struct ata_queued_cmd *qc);
extern u8 ata_bmdma_status(struct ata_port *ap); extern u8 ata_bmdma_status(struct ata_port *ap);
extern void ata_bmdma_irq_clear(struct ata_port *ap); extern void ata_bmdma_irq_clear(struct ata_port *ap);
extern void ata_qc_complete(struct ata_queued_cmd *qc); extern void __ata_qc_complete(struct ata_queued_cmd *qc);
extern void ata_eng_timeout(struct ata_port *ap); extern void ata_eng_timeout(struct ata_port *ap);
extern void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev, extern void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev,
struct scsi_cmnd *cmd, struct scsi_cmnd *cmd,
...@@ -586,10 +655,14 @@ static inline unsigned int ata_tag_valid(unsigned int tag) ...@@ -586,10 +655,14 @@ static inline unsigned int ata_tag_valid(unsigned int tag)
return (tag < ATA_MAX_QUEUE) ? 1 : 0; return (tag < ATA_MAX_QUEUE) ? 1 : 0;
} }
static inline unsigned int ata_class_present(unsigned int class)
{
return class == ATA_DEV_ATA || class == ATA_DEV_ATAPI;
}
static inline unsigned int ata_dev_present(const struct ata_device *dev) static inline unsigned int ata_dev_present(const struct ata_device *dev)
{ {
return ((dev->class == ATA_DEV_ATA) || return ata_class_present(dev->class);
(dev->class == ATA_DEV_ATAPI));
} }
static inline u8 ata_chk_status(struct ata_port *ap) static inline u8 ata_chk_status(struct ata_port *ap)
...@@ -657,9 +730,9 @@ static inline u8 ata_wait_idle(struct ata_port *ap) ...@@ -657,9 +730,9 @@ static inline u8 ata_wait_idle(struct ata_port *ap)
if (status & (ATA_BUSY | ATA_DRQ)) { if (status & (ATA_BUSY | ATA_DRQ)) {
unsigned long l = ap->ioaddr.status_addr; unsigned long l = ap->ioaddr.status_addr;
printk(KERN_WARNING if (ata_msg_warn(ap))
"ATA: abnormal status 0x%X on port 0x%lX\n", printk(KERN_WARNING "ATA: abnormal status 0x%X on port 0x%lX\n",
status, l); status, l);
} }
return status; return status;
...@@ -701,6 +774,24 @@ static inline void ata_qc_reinit(struct ata_queued_cmd *qc) ...@@ -701,6 +774,24 @@ static inline void ata_qc_reinit(struct ata_queued_cmd *qc)
ata_tf_init(qc->ap, &qc->tf, qc->dev->devno); ata_tf_init(qc->ap, &qc->tf, qc->dev->devno);
} }
/**
* ata_qc_complete - Complete an active ATA command
* @qc: Command to complete
* @err_mask: ATA Status register contents
*
* Indicate to the mid and upper layers that an ATA
* command has completed, with either an ok or not-ok status.
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
*/
static inline void ata_qc_complete(struct ata_queued_cmd *qc)
{
if (unlikely(qc->flags & ATA_QCFLAG_EH_SCHEDULED))
return;
__ata_qc_complete(qc);
}
/** /**
* ata_irq_on - Enable interrupts on a port. * ata_irq_on - Enable interrupts on a port.
...@@ -751,7 +842,8 @@ static inline u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq) ...@@ -751,7 +842,8 @@ static inline u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq)
status = ata_busy_wait(ap, bits, 1000); status = ata_busy_wait(ap, bits, 1000);
if (status & bits) if (status & bits)
DPRINTK("abnormal status 0x%X\n", status); if (ata_msg_err(ap))
printk(KERN_ERR "abnormal status 0x%X\n", status);
/* get controller status; clear intr, err bits */ /* get controller status; clear intr, err bits */
if (ap->flags & ATA_FLAG_MMIO) { if (ap->flags & ATA_FLAG_MMIO) {
...@@ -769,8 +861,10 @@ static inline u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq) ...@@ -769,8 +861,10 @@ static inline u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq)
post_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); post_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
} }
VPRINTK("irq ack: host_stat 0x%X, new host_stat 0x%X, drv_stat 0x%X\n", if (ata_msg_intr(ap))
host_stat, post_stat, status); printk(KERN_INFO "%s: irq ack: host_stat 0x%X, new host_stat 0x%X, drv_stat 0x%X\n",
__FUNCTION__,
host_stat, post_stat, status);
return status; return status;
} }
...@@ -807,7 +901,7 @@ static inline int ata_try_flush_cache(const struct ata_device *dev) ...@@ -807,7 +901,7 @@ static inline int ata_try_flush_cache(const struct ata_device *dev)
static inline unsigned int ac_err_mask(u8 status) static inline unsigned int ac_err_mask(u8 status)
{ {
if (status & ATA_BUSY) if (status & ATA_BUSY)
return AC_ERR_ATA_BUS; return AC_ERR_HSM;
if (status & (ATA_ERR | ATA_DF)) if (status & (ATA_ERR | ATA_DF))
return AC_ERR_DEV; return AC_ERR_DEV;
return 0; return 0;
......
...@@ -35,6 +35,9 @@ static inline int scsi_sense_valid(struct scsi_sense_hdr *sshdr) ...@@ -35,6 +35,9 @@ static inline int scsi_sense_valid(struct scsi_sense_hdr *sshdr)
} }
extern void scsi_eh_finish_cmd(struct scsi_cmnd *scmd,
struct list_head *done_q);
extern void scsi_eh_flush_done_q(struct list_head *done_q);
extern void scsi_report_bus_reset(struct Scsi_Host *, int); extern void scsi_report_bus_reset(struct Scsi_Host *, int);
extern void scsi_report_device_reset(struct Scsi_Host *, int, int); extern void scsi_report_device_reset(struct Scsi_Host *, int, int);
extern int scsi_block_when_processing_errors(struct scsi_device *); extern int scsi_block_when_processing_errors(struct scsi_device *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment