* Copyright 2003-2005 Jeff Garzik
* Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer
* Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
- * Copyright (C) 2003 Red Hat Inc <alan@redhat.com>
+ * Copyright (C) 2003 Red Hat Inc
*
* and drivers/ata/ahci.c:
* Copyright 2004-2005 Red Hat, Inc.
* scc_set_dmamode - Initialize host controller PATA DMA timings
* @ap: Port whose timings we are configuring
* @adev: um
- * @udma: udma mode, 0 - 6
*
* Set UDMA mode for device.
*
}
/**
- * scc_bus_post_reset - PATA device post reset
+ * scc_wait_after_reset - wait for devices to become ready after reset
*
- * Note: Original code is ata_bus_post_reset().
+ * Note: Original code is ata_sff_wait_after_reset
*/
-static int scc_bus_post_reset(struct ata_port *ap, unsigned int devmask,
- unsigned long deadline)
+int scc_wait_after_reset(struct ata_link *link, unsigned int devmask,
+ unsigned long deadline)
{
+ struct ata_port *ap = link->ap;
struct ata_ioports *ioaddr = &ap->ioaddr;
unsigned int dev0 = devmask & (1 << 0);
unsigned int dev1 = devmask & (1 << 1);
- int rc;
+ int rc, ret = 0;
+
+ /* Spec mandates ">= 2ms" before checking status. We wait
+ * 150ms, because that was the magic delay used for ATAPI
+ * devices in Hale Landis's ATADRVR, for the period of time
+ * between when the ATA command register is written, and then
+ * 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);
- /* if device 0 was found in ata_devchk, wait for its
- * BSY bit to clear
+ /* always check readiness of the master device */
+ rc = ata_sff_wait_ready(link, deadline);
+ /* -ENODEV means the odd clown forgot the D7 pulldown resistor
+ * and TF status is 0xff, bail out on it too.
*/
- if (dev0) {
- rc = ata_sff_wait_ready(ap, deadline);
- if (rc && rc != -ENODEV)
- return rc;
- }
+ if (rc)
+ return rc;
- /* if device 1 was found in ata_devchk, wait for
- * register access, then wait for BSY to clear
+ /* if device 1 was found in ata_devchk, wait for register
+ * access briefly, then wait for BSY to clear.
*/
- while (dev1) {
- u8 nsect, lbal;
+ if (dev1) {
+ int i;
ap->ops->sff_dev_select(ap, 1);
- nsect = in_be32(ioaddr->nsect_addr);
- lbal = in_be32(ioaddr->lbal_addr);
- if ((nsect == 1) && (lbal == 1))
- break;
- if (time_after(jiffies, deadline))
- return -EBUSY;
- msleep(50); /* give drive a breather */
- }
- if (dev1) {
- rc = ata_sff_wait_ready(ap, deadline);
- if (rc && rc != -ENODEV)
- return rc;
+
+ /* Wait for register access. Some ATAPI devices fail
+ * to set nsect/lbal after reset, so don't waste too
+ * much time on it. We're gonna wait for !BSY anyway.
+ */
+ for (i = 0; i < 2; i++) {
+ u8 nsect, lbal;
+
+ nsect = in_be32(ioaddr->nsect_addr);
+ lbal = in_be32(ioaddr->lbal_addr);
+ if ((nsect == 1) && (lbal == 1))
+ break;
+ msleep(50); /* give drive a breather */
+ }
+
+ rc = ata_sff_wait_ready(link, deadline);
+ if (rc) {
+ if (rc != -ENODEV)
+ return rc;
+ ret = rc;
+ }
}
/* is all this really necessary? */
if (dev0)
ap->ops->sff_dev_select(ap, 0);
- return 0;
+ return ret;
}
/**
udelay(20);
out_be32(ioaddr->ctl_addr, ap->ctl);
- /* wait a while before checking status */
- ata_sff_wait_after_reset(ap, deadline);
-
- /* 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 (scc_check_status(ap) == 0xFF)
- return 0;
-
- scc_bus_post_reset(ap, devmask, deadline);
+ scc_wait_after_reset(&ap->link, devmask, deadline);
return 0;
}
DPRINTK("ENTER\n");
- if (ata_link_offline(link)) {
- classes[0] = ATA_DEV_NONE;
- goto out;
- }
-
/* determine if device 0/1 are present */
if (scc_devchk(ap, 0))
devmask |= (1 << 0);
classes[1] = ata_sff_dev_classify(&ap->link.device[1],
devmask & (1 << 1), &err);
- out:
DPRINTK("EXIT, classes[0]=%u [1]=%u\n", classes[0], classes[1]);
return 0;
}
if (reg & INTSTS_BMSINT) {
unsigned int classes;
- unsigned long deadline = jiffies + ATA_TMOUT_BOOT;
+ unsigned long deadline = ata_deadline(jiffies, ATA_TMOUT_BOOT);
printk(KERN_WARNING "%s: Internal Bus Error\n", DRV_NAME);
out_be32(bmid_base + SCC_DMA_INTST, INTSTS_BMSINT);
/* TBD: SW reset */
in_be32(bmid_base + SCC_DMA_CMD) & ~ATA_DMA_START);
/* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
- ata_sff_altstatus(ap); /* dummy read */
+ ata_sff_dma_pause(ap); /* dummy read */
}
/**
return host_stat;
/* errata A252,A308 workaround: Step4 */
- if ((ata_sff_altstatus(ap) & ATA_ERR) && (int_status & INTSTS_INTRQ))
+ if ((scc_check_altstatus(ap) & ATA_ERR)
+ && (int_status & INTSTS_INTRQ))
return (host_stat | ATA_DMA_INTR);
/* errata A308 workaround Step5 */
static struct ata_port_info scc_port_info[] = {
{
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x00,
+ .pio_mask = ATA_PIO4,
+ /* No MWDMA */
.udma_mask = ATA_UDMA6,
.port_ops = &scc_pata_ops,
},