struct ata_device *dev);
static void ata_set_mode(struct ata_port *ap);
static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev);
-static unsigned int ata_dev_xfermask(struct ata_port *ap,
- struct ata_device *dev);
+static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev);
static unsigned int ata_unique_id = 1;
static struct workqueue_struct *ata_wq;
((udma_mask << ATA_SHIFT_UDMA) & ATA_MASK_UDMA);
}
+/**
+ * ata_unpack_xfermask - Unpack xfer_mask into pio, mwdma and udma masks
+ * @xfer_mask: xfer_mask to unpack
+ * @pio_mask: resulting pio_mask
+ * @mwdma_mask: resulting mwdma_mask
+ * @udma_mask: resulting udma_mask
+ *
+ * Unpack @xfer_mask into @pio_mask, @mwdma_mask and @udma_mask.
+ * Any NULL distination masks will be ignored.
+ */
+static void ata_unpack_xfermask(unsigned int xfer_mask,
+ unsigned int *pio_mask,
+ unsigned int *mwdma_mask,
+ unsigned int *udma_mask)
+{
+ if (pio_mask)
+ *pio_mask = (xfer_mask & ATA_MASK_PIO) >> ATA_SHIFT_PIO;
+ if (mwdma_mask)
+ *mwdma_mask = (xfer_mask & ATA_MASK_MWDMA) >> ATA_SHIFT_MWDMA;
+ if (udma_mask)
+ *udma_mask = (xfer_mask & ATA_MASK_UDMA) >> ATA_SHIFT_UDMA;
+}
+
static const struct ata_xfer_ent {
unsigned int shift, bits;
u8 base;
spin_unlock_irqrestore(&ap->host_set->lock, flags);
if (!wait_for_completion_timeout(&wait, ATA_TMOUT_INTERNAL)) {
+ ata_port_flush_task(ap);
+
spin_lock_irqsave(&ap->host_set->lock, flags);
/* We're racing with irq here. If we lose, the
* common ATA, ATAPI feature tests
*/
- /* we require DMA support (bits 8 of word 49) */
- if (!ata_id_has_dma(id)) {
- printk(KERN_DEBUG "ata%u: no dma\n", ap->id);
- rc = -EINVAL;
- goto err_out_nosup;
- }
-
/* find max transfer mode; for printk only */
xfer_mask = ata_id_xfermask(id);
continue;
if (!dev->pio_mode) {
- printk(KERN_WARNING "ata%u: no PIO support\n", ap->id);
+ printk(KERN_WARNING "ata%u: no PIO support for device %d.\n", ap->id, i);
return -1;
}
/* step 1: calculate xfer_mask */
for (i = 0; i < ATA_MAX_DEVICES; i++) {
struct ata_device *dev = &ap->device[i];
- unsigned int xfer_mask;
+ unsigned int pio_mask, dma_mask;
if (!ata_dev_present(dev))
continue;
- xfer_mask = ata_dev_xfermask(ap, dev);
+ ata_dev_xfermask(ap, dev);
- dev->pio_mode = ata_xfer_mask2mode(xfer_mask & ATA_MASK_PIO);
- dev->dma_mode = ata_xfer_mask2mode(xfer_mask & (ATA_MASK_MWDMA |
- ATA_MASK_UDMA));
+ /* TODO: let LLDD filter dev->*_mask here */
+
+ pio_mask = ata_pack_xfermask(dev->pio_mask, 0, 0);
+ dma_mask = ata_pack_xfermask(0, dev->mwdma_mask, dev->udma_mask);
+ dev->pio_mode = ata_xfer_mask2mode(pio_mask);
+ dev->dma_mode = ata_xfer_mask2mode(dma_mask);
}
/* step 2: always set host PIO timings */
* status is checked. Because waiting for "a while" before
* checking status is fine, post SRST, we perform this magic
* delay here as well.
+ *
+ * Old drivers/ide uses the 2mS rule and then waits for ready
*/
msleep(150);
+
+ /* Before we perform post reset processing we want to see if
+ the bus shows 0xFF because the odd clown forgets the D7 pulldown
+ resistor */
+
+ if (ata_check_status(ap) == 0xFF)
+ return 1; /* Positive is failure for some reason */
+
ata_bus_post_reset(ap, devmask);
return 0;
}
static const char * const ata_dma_blacklist [] = {
- "WDC AC11000H",
- "WDC AC22100H",
- "WDC AC32500H",
- "WDC AC33100H",
- "WDC AC31600H",
- "WDC AC32100H",
- "WDC AC23200L",
- "Compaq CRD-8241B",
- "CRD-8400B",
- "CRD-8480B",
- "CRD-8482B",
- "CRD-84",
- "SanDisk SDP3B",
- "SanDisk SDP3B-64",
- "SANYO CD-ROM CRD",
- "HITACHI CDR-8",
- "HITACHI CDR-8335",
- "HITACHI CDR-8435",
- "Toshiba CD-ROM XM-6202B",
- "TOSHIBA CD-ROM XM-1702BC",
- "CD-532E-A",
- "E-IDE CD-ROM CR-840",
- "CD-ROM Drive/F5A",
- "WPI CDD-820",
- "SAMSUNG CD-ROM SC-148C",
- "SAMSUNG CD-ROM SC",
- "SanDisk SDP3B-64",
- "ATAPI CD-ROM DRIVE 40X MAXIMUM",
- "_NEC DV5800A",
+ "WDC AC11000H", NULL,
+ "WDC AC22100H", NULL,
+ "WDC AC32500H", NULL,
+ "WDC AC33100H", NULL,
+ "WDC AC31600H", NULL,
+ "WDC AC32100H", "24.09P07",
+ "WDC AC23200L", "21.10N21",
+ "Compaq CRD-8241B", NULL,
+ "CRD-8400B", NULL,
+ "CRD-8480B", NULL,
+ "CRD-8482B", NULL,
+ "CRD-84", NULL,
+ "SanDisk SDP3B", NULL,
+ "SanDisk SDP3B-64", NULL,
+ "SANYO CD-ROM CRD", NULL,
+ "HITACHI CDR-8", NULL,
+ "HITACHI CDR-8335", NULL,
+ "HITACHI CDR-8435", NULL,
+ "Toshiba CD-ROM XM-6202B", NULL,
+ "TOSHIBA CD-ROM XM-1702BC", NULL,
+ "CD-532E-A", NULL,
+ "E-IDE CD-ROM CR-840", NULL,
+ "CD-ROM Drive/F5A", NULL,
+ "WPI CDD-820", NULL,
+ "SAMSUNG CD-ROM SC-148C", NULL,
+ "SAMSUNG CD-ROM SC", NULL,
+ "SanDisk SDP3B-64", NULL,
+ "ATAPI CD-ROM DRIVE 40X MAXIMUM",NULL,
+ "_NEC DV5800A", NULL,
+ "SAMSUNG CD-ROM SN-124", "N001"
};
+
+static int ata_strim(char *s, size_t len)
+{
+ len = strnlen(s, len);
+
+ /* ATAPI specifies that empty space is blank-filled; remove blanks */
+ while ((len > 0) && (s[len - 1] == ' ')) {
+ len--;
+ s[len] = 0;
+ }
+ return len;
+}
static int ata_dma_blacklisted(const struct ata_device *dev)
{
- unsigned char model_num[41];
+ unsigned char model_num[40];
+ unsigned char model_rev[16];
+ unsigned int nlen, rlen;
int i;
- ata_id_c_string(dev->id, model_num, ATA_ID_PROD_OFS, sizeof(model_num));
-
- for (i = 0; i < ARRAY_SIZE(ata_dma_blacklist); i++)
- if (!strcmp(ata_dma_blacklist[i], model_num))
- return 1;
+ ata_id_string(dev->id, model_num, ATA_ID_PROD_OFS,
+ sizeof(model_num));
+ ata_id_string(dev->id, model_rev, ATA_ID_FW_REV_OFS,
+ sizeof(model_rev));
+ nlen = ata_strim(model_num, sizeof(model_num));
+ rlen = ata_strim(model_rev, sizeof(model_rev));
+ for (i = 0; i < ARRAY_SIZE(ata_dma_blacklist); i += 2) {
+ if (!strncmp(ata_dma_blacklist[i], model_num, nlen)) {
+ if (ata_dma_blacklist[i+1] == NULL)
+ return 1;
+ if (!strncmp(ata_dma_blacklist[i], model_rev, rlen))
+ return 1;
+ }
+ }
return 0;
}
* @ap: Port on which the device to compute xfermask for resides
* @dev: Device to compute xfermask for
*
- * Compute supported xfermask of @dev. This function is
- * responsible for applying all known limits including host
- * controller limits, device blacklist, etc...
+ * Compute supported xfermask of @dev and store it in
+ * dev->*_mask. This function is responsible for applying all
+ * known limits including host controller limits, device
+ * blacklist, etc...
*
* LOCKING:
* None.
- *
- * RETURNS:
- * Computed xfermask.
*/
-static unsigned int ata_dev_xfermask(struct ata_port *ap,
- struct ata_device *dev)
+static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev)
{
unsigned long xfer_mask;
int i;
struct ata_device *d = &ap->device[i];
if (!ata_dev_present(d))
continue;
+ xfer_mask &= ata_pack_xfermask(d->pio_mask, d->mwdma_mask,
+ d->udma_mask);
xfer_mask &= ata_id_xfermask(d->id);
if (ata_dma_blacklisted(d))
xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
printk(KERN_WARNING "ata%u: dev %u is on DMA blacklist, "
"disabling DMA\n", ap->id, dev->devno);
- return xfer_mask;
+ ata_unpack_xfermask(xfer_mask, &dev->pio_mask, &dev->mwdma_mask,
+ &dev->udma_mask);
}
/**
ata_fill_sg(qc);
}
+void ata_noop_qc_prep(struct ata_queued_cmd *qc) { }
+
/**
* ata_sg_init_one - Associate command with memory buffer
* @qc: Command to be associated
case ATA_PROT_ATAPI:
case ATA_PROT_PIO:
- case ATA_PROT_PIO_MULT:
if (ap->flags & ATA_FLAG_PIO_DMA)
return 1;
return 0;
}
-/**
- * ata_bmdma_setup_mmio - Set up PCI IDE BMDMA transaction
- * @qc: Info associated with this ATA transaction.
- *
- * LOCKING:
- * spin_lock_irqsave(host_set lock)
- */
-
-static void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc)
-{
- struct ata_port *ap = qc->ap;
- unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
- u8 dmactl;
- void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
-
- /* load PRD table addr. */
- mb(); /* make sure PRD table writes are visible to controller */
- writel(ap->prd_dma, mmio + ATA_DMA_TABLE_OFS);
-
- /* specify data direction, triple-check start bit is clear */
- dmactl = readb(mmio + ATA_DMA_CMD);
- dmactl &= ~(ATA_DMA_WR | ATA_DMA_START);
- if (!rw)
- dmactl |= ATA_DMA_WR;
- writeb(dmactl, mmio + ATA_DMA_CMD);
-
- /* issue r/w command */
- ap->ops->exec_command(ap, &qc->tf);
-}
-
-/**
- * ata_bmdma_start_mmio - Start a PCI IDE BMDMA transaction
- * @qc: Info associated with this ATA transaction.
- *
- * LOCKING:
- * spin_lock_irqsave(host_set lock)
- */
-
-static void ata_bmdma_start_mmio (struct ata_queued_cmd *qc)
-{
- struct ata_port *ap = qc->ap;
- void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
- u8 dmactl;
-
- /* start host DMA transaction */
- dmactl = readb(mmio + ATA_DMA_CMD);
- writeb(dmactl | ATA_DMA_START, mmio + ATA_DMA_CMD);
-
- /* Strictly, one may wish to issue a readb() here, to
- * flush the mmio write. However, control also passes
- * to the hardware at this point, and it will interrupt
- * us when we are to resume control. So, in effect,
- * we don't care when the mmio write flushes.
- * Further, a read of the DMA status register _immediately_
- * following the write may not be what certain flaky hardware
- * is expected, so I think it is best to not add a readb()
- * without first all the MMIO ATA cards/mobos.
- * Or maybe I'm just being paranoid.
- */
-}
-
-/**
- * ata_bmdma_setup_pio - Set up PCI IDE BMDMA transaction (PIO)
- * @qc: Info associated with this ATA transaction.
- *
- * LOCKING:
- * spin_lock_irqsave(host_set lock)
- */
-
-static void ata_bmdma_setup_pio (struct ata_queued_cmd *qc)
-{
- struct ata_port *ap = qc->ap;
- unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
- u8 dmactl;
-
- /* load PRD table addr. */
- outl(ap->prd_dma, ap->ioaddr.bmdma_addr + ATA_DMA_TABLE_OFS);
-
- /* specify data direction, triple-check start bit is clear */
- dmactl = inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
- dmactl &= ~(ATA_DMA_WR | ATA_DMA_START);
- if (!rw)
- dmactl |= ATA_DMA_WR;
- outb(dmactl, ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
-
- /* issue r/w command */
- ap->ops->exec_command(ap, &qc->tf);
-}
-
-/**
- * ata_bmdma_start_pio - Start a PCI IDE BMDMA transaction (PIO)
- * @qc: Info associated with this ATA transaction.
- *
- * LOCKING:
- * spin_lock_irqsave(host_set lock)
- */
-
-static void ata_bmdma_start_pio (struct ata_queued_cmd *qc)
-{
- struct ata_port *ap = qc->ap;
- u8 dmactl;
-
- /* start host DMA transaction */
- dmactl = inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
- outb(dmactl | ATA_DMA_START,
- ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
-}
-
-
-/**
- * ata_bmdma_start - Start a PCI IDE BMDMA transaction
- * @qc: Info associated with this ATA transaction.
- *
- * Writes the ATA_DMA_START flag to the DMA command register.
- *
- * May be used as the bmdma_start() entry in ata_port_operations.
- *
- * LOCKING:
- * spin_lock_irqsave(host_set lock)
- */
-void ata_bmdma_start(struct ata_queued_cmd *qc)
-{
- if (qc->ap->flags & ATA_FLAG_MMIO)
- ata_bmdma_start_mmio(qc);
- else
- ata_bmdma_start_pio(qc);
-}
-
-
-/**
- * ata_bmdma_setup - Set up PCI IDE BMDMA transaction
- * @qc: Info associated with this ATA transaction.
- *
- * Writes address of PRD table to device's PRD Table Address
- * register, sets the DMA control register, and calls
- * ops->exec_command() to start the transfer.
- *
- * May be used as the bmdma_setup() entry in ata_port_operations.
- *
- * LOCKING:
- * spin_lock_irqsave(host_set lock)
- */
-void ata_bmdma_setup(struct ata_queued_cmd *qc)
-{
- if (qc->ap->flags & ATA_FLAG_MMIO)
- ata_bmdma_setup_mmio(qc);
- else
- ata_bmdma_setup_pio(qc);
-}
-
-
-/**
- * ata_bmdma_irq_clear - Clear PCI IDE BMDMA interrupt.
- * @ap: Port associated with this ATA transaction.
- *
- * Clear interrupt and error flags in DMA status register.
- *
- * May be used as the irq_clear() entry in ata_port_operations.
- *
- * LOCKING:
- * spin_lock_irqsave(host_set lock)
- */
-
-void ata_bmdma_irq_clear(struct ata_port *ap)
-{
- if (ap->flags & ATA_FLAG_MMIO) {
- void __iomem *mmio = ((void __iomem *) ap->ioaddr.bmdma_addr) + ATA_DMA_STATUS;
- writeb(readb(mmio), mmio);
- } else {
- unsigned long addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS;
- outb(inb(addr), addr);
- }
-
-}
-
-
-/**
- * ata_bmdma_status - Read PCI IDE BMDMA status
- * @ap: Port associated with this ATA transaction.
- *
- * Read and return BMDMA status register.
- *
- * May be used as the bmdma_status() entry in ata_port_operations.
- *
- * LOCKING:
- * spin_lock_irqsave(host_set lock)
- */
-
-u8 ata_bmdma_status(struct ata_port *ap)
-{
- u8 host_stat;
- if (ap->flags & ATA_FLAG_MMIO) {
- void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
- host_stat = readb(mmio + ATA_DMA_STATUS);
- } else
- host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
- return host_stat;
-}
-
-
-/**
- * ata_bmdma_stop - Stop PCI IDE BMDMA transfer
- * @qc: Command we are ending DMA for
- *
- * Clears the ATA_DMA_START flag in the dma control register
- *
- * May be used as the bmdma_stop() entry in ata_port_operations.
- *
- * LOCKING:
- * spin_lock_irqsave(host_set lock)
- */
-
-void ata_bmdma_stop(struct ata_queued_cmd *qc)
-{
- struct ata_port *ap = qc->ap;
- if (ap->flags & ATA_FLAG_MMIO) {
- void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
-
- /* clear start/stop bit */
- writeb(readb(mmio + ATA_DMA_CMD) & ~ATA_DMA_START,
- mmio + ATA_DMA_CMD);
- } else {
- /* clear start/stop bit */
- outb(inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD) & ~ATA_DMA_START,
- ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
- }
-
- /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
- ata_altstatus(ap); /* dummy read */
-}
-
/**
* ata_host_intr - Handle host interrupt for given (port, task)
* @ap: Port on which interrupt arrived (possibly...)
#ifdef ATA_IRQ_TRAP
if ((ap->stats.idle_irq % 1000) == 0) {
- handled = 1;
ata_irq_ack(ap, 0); /* debug trap */
printk(KERN_WARNING "ata%d: irq trap\n", ap->id);
+ return 1;
}
#endif
return 0; /* irq not handled */
INIT_WORK(&ap->port_task, NULL, NULL);
INIT_LIST_HEAD(&ap->eh_done_q);
- for (i = 0; i < ATA_MAX_DEVICES; i++)
- ap->device[i].devno = i;
+ for (i = 0; i < ATA_MAX_DEVICES; i++) {
+ struct ata_device *dev = &ap->device[i];
+ dev->devno = i;
+ dev->pio_mask = UINT_MAX;
+ dev->mwdma_mask = UINT_MAX;
+ dev->udma_mask = UINT_MAX;
+ }
#ifdef ATA_IRQ_TRAP
ap->stats.unhandled_irq = 1;
EXPORT_SYMBOL_GPL(ata_host_stop);
EXPORT_SYMBOL_GPL(ata_interrupt);
EXPORT_SYMBOL_GPL(ata_qc_prep);
+EXPORT_SYMBOL_GPL(ata_noop_qc_prep);
EXPORT_SYMBOL_GPL(ata_bmdma_setup);
EXPORT_SYMBOL_GPL(ata_bmdma_start);
EXPORT_SYMBOL_GPL(ata_bmdma_irq_clear);
EXPORT_SYMBOL_GPL(ata_pci_remove_one);
EXPORT_SYMBOL_GPL(ata_pci_device_suspend);
EXPORT_SYMBOL_GPL(ata_pci_device_resume);
+EXPORT_SYMBOL_GPL(ata_pci_default_filter);
+EXPORT_SYMBOL_GPL(ata_pci_clear_simplex);
#endif /* CONFIG_PCI */
EXPORT_SYMBOL_GPL(ata_device_suspend);