[PATCH 2/4] libata-core.c: add low-level I/O calls
Akira Iguchi
akira2.iguchi at toshiba.co.jp
Fri Jan 12 21:01:37 EST 2007
Using low-level I/O calls, similar functions
(ex: ata_pio_devchk() and ata_mmio_devchk()) can be merged.
And some branches which check MMIO/PIO flag can be removed.
The idea comes from drivers/ide IN*/OUT* calls.
By default, depending on the flag, default_pio_ops or default_mmio_ops
are used as low-level I/O calls. If your device needs special I/O calls
(ex: 32bit access in Celleb), you must initialize .io_ops in ata_port_info
and pass it to appropriate initialization functions (ex: ata_pci_init_one()).
Signed-off-by: Kou Ishizaki <kou.ishizaki at toshiba.co.jp>
Signed-off-by: Akira Iguchi <akira2.iguchi at toshiba.co.jp>
---
--- linux-2.6.20-rc4/drivers/ata/libata-core.c.orig 2007-01-13 01:01:50.000000000 +0900
+++ linux-2.6.20-rc4/drivers/ata/libata-core.c 2007-01-13 01:02:58.000000000 +0900
@@ -598,51 +598,7 @@ void ata_dev_disable(struct ata_device *
}
/**
- * ata_pio_devchk - PATA device presence detection
- * @ap: ATA channel to examine
- * @device: Device to examine (starting at zero)
- *
- * This technique was originally described in
- * Hale Landis's ATADRVR (www.ata-atapi.com), and
- * later found its way into the ATA/ATAPI spec.
- *
- * Write a pattern to the ATA shadow registers,
- * and if a device is present, it will respond by
- * correctly storing and echoing back the
- * ATA shadow register contents.
- *
- * LOCKING:
- * caller.
- */
-
-static unsigned int ata_pio_devchk(struct ata_port *ap,
- unsigned int device)
-{
- struct ata_ioports *ioaddr = &ap->ioaddr;
- u8 nsect, lbal;
-
- ap->ops->dev_select(ap, device);
-
- outb(0x55, ioaddr->nsect_addr);
- outb(0xaa, ioaddr->lbal_addr);
-
- outb(0xaa, ioaddr->nsect_addr);
- outb(0x55, ioaddr->lbal_addr);
-
- outb(0x55, ioaddr->nsect_addr);
- outb(0xaa, ioaddr->lbal_addr);
-
- nsect = inb(ioaddr->nsect_addr);
- lbal = inb(ioaddr->lbal_addr);
-
- if ((nsect == 0x55) && (lbal == 0xaa))
- return 1; /* we found a device */
-
- return 0; /* nothing found */
-}
-
-/**
- * ata_mmio_devchk - PATA device presence detection
+ * ata_devchk - PATA device presence detection
* @ap: ATA channel to examine
* @device: Device to examine (starting at zero)
*
@@ -659,7 +615,7 @@ static unsigned int ata_pio_devchk(struc
* caller.
*/
-static unsigned int ata_mmio_devchk(struct ata_port *ap,
+static unsigned int ata_devchk(struct ata_port *ap,
unsigned int device)
{
struct ata_ioports *ioaddr = &ap->ioaddr;
@@ -667,17 +623,17 @@ static unsigned int ata_mmio_devchk(stru
ap->ops->dev_select(ap, device);
- writeb(0x55, (void __iomem *) ioaddr->nsect_addr);
- writeb(0xaa, (void __iomem *) ioaddr->lbal_addr);
+ ap->io_ops->OUTB(0x55, ioaddr->nsect_addr);
+ ap->io_ops->OUTB(0xaa, ioaddr->lbal_addr);
- writeb(0xaa, (void __iomem *) ioaddr->nsect_addr);
- writeb(0x55, (void __iomem *) ioaddr->lbal_addr);
+ ap->io_ops->OUTB(0xaa, ioaddr->nsect_addr);
+ ap->io_ops->OUTB(0x55, ioaddr->lbal_addr);
- writeb(0x55, (void __iomem *) ioaddr->nsect_addr);
- writeb(0xaa, (void __iomem *) ioaddr->lbal_addr);
+ ap->io_ops->OUTB(0x55, ioaddr->nsect_addr);
+ ap->io_ops->OUTB(0xaa, ioaddr->lbal_addr);
- nsect = readb((void __iomem *) ioaddr->nsect_addr);
- lbal = readb((void __iomem *) ioaddr->lbal_addr);
+ nsect = ap->io_ops->INB(ioaddr->nsect_addr);
+ lbal = ap->io_ops->INB(ioaddr->lbal_addr);
if ((nsect == 0x55) && (lbal == 0xaa))
return 1; /* we found a device */
@@ -686,27 +642,6 @@ static unsigned int ata_mmio_devchk(stru
}
/**
- * ata_devchk - PATA device presence detection
- * @ap: ATA channel to examine
- * @device: Device to examine (starting at zero)
- *
- * Dispatch ATA device presence detection, depending
- * on whether we are using PIO or MMIO to talk to the
- * ATA shadow registers.
- *
- * LOCKING:
- * caller.
- */
-
-static unsigned int ata_devchk(struct ata_port *ap,
- unsigned int device)
-{
- if (ap->flags & ATA_FLAG_MMIO)
- return ata_mmio_devchk(ap, device);
- return ata_pio_devchk(ap, device);
-}
-
-/**
* ata_dev_classify - determine device type based on ATA-spec signature
* @tf: ATA taskfile register set for device to be identified
*
@@ -923,11 +858,7 @@ void ata_std_dev_select (struct ata_port
else
tmp = ATA_DEVICE_OBS | ATA_DEV1;
- if (ap->flags & ATA_FLAG_MMIO) {
- writeb(tmp, (void __iomem *) ap->ioaddr.device_addr);
- } else {
- outb(tmp, ap->ioaddr.device_addr);
- }
+ ap->io_ops->OUTB(tmp, ap->ioaddr.device_addr);
ata_pause(ap); /* needed; also flushes, for mmio */
}
@@ -2623,13 +2554,8 @@ static void ata_bus_post_reset(struct at
u8 nsect, lbal;
ap->ops->dev_select(ap, 1);
- if (ap->flags & ATA_FLAG_MMIO) {
- nsect = readb((void __iomem *) ioaddr->nsect_addr);
- lbal = readb((void __iomem *) ioaddr->lbal_addr);
- } else {
- nsect = inb(ioaddr->nsect_addr);
- lbal = inb(ioaddr->lbal_addr);
- }
+ nsect = ap->io_ops->INB(ioaddr->nsect_addr);
+ lbal = ap->io_ops->INB(ioaddr->lbal_addr);
if ((nsect == 1) && (lbal == 1))
break;
if (time_after(jiffies, timeout)) {
@@ -2657,19 +2583,11 @@ static unsigned int ata_bus_softreset(st
DPRINTK("ata%u: bus reset via SRST\n", ap->id);
/* software reset. causes dev0 to be selected */
- if (ap->flags & ATA_FLAG_MMIO) {
- writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr);
- udelay(20); /* FIXME: flush */
- writeb(ap->ctl | ATA_SRST, (void __iomem *) ioaddr->ctl_addr);
- udelay(20); /* FIXME: flush */
- writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr);
- } else {
- outb(ap->ctl, ioaddr->ctl_addr);
- udelay(10);
- outb(ap->ctl | ATA_SRST, ioaddr->ctl_addr);
- udelay(10);
- outb(ap->ctl, ioaddr->ctl_addr);
- }
+ ap->io_ops->OUTB(ap->ctl, ioaddr->ctl_addr);
+ udelay(20);
+ ap->io_ops->OUTB(ap->ctl | ATA_SRST, ioaddr->ctl_addr);
+ udelay(20);
+ ap->io_ops->OUTB(ap->ctl, ioaddr->ctl_addr);
/* spec mandates ">= 2ms" before checking status.
* We wait 150ms, because that was the magic delay used for
@@ -2770,10 +2688,7 @@ void ata_bus_reset(struct ata_port *ap)
if (ap->flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST)) {
/* set up device control for ATA_FLAG_SATA_RESET */
- if (ap->flags & ATA_FLAG_MMIO)
- writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr);
- else
- outb(ap->ctl, ioaddr->ctl_addr);
+ ap->io_ops->OUTB(ap->ctl, ioaddr->ctl_addr);
}
DPRINTK("EXIT\n");
@@ -3167,10 +3082,7 @@ void ata_std_postreset(struct ata_port *
/* set up device control */
if (ap->ioaddr.ctl_addr) {
- if (ap->flags & ATA_FLAG_MMIO)
- writeb(ap->ctl, (void __iomem *) ap->ioaddr.ctl_addr);
- else
- outb(ap->ctl, ap->ioaddr.ctl_addr);
+ ap->io_ops->OUTB(ap->ctl, ap->ioaddr.ctl_addr);
}
DPRINTK("EXIT\n");
@@ -3919,19 +3831,13 @@ void ata_mmio_data_xfer(struct ata_devic
unsigned int buflen, int write_data)
{
struct ata_port *ap = adev->ap;
- unsigned int i;
unsigned int words = buflen >> 1;
- u16 *buf16 = (u16 *) buf;
- void __iomem *mmio = (void __iomem *)ap->ioaddr.data_addr;
/* Transfer multiple of 2 bytes */
- if (write_data) {
- for (i = 0; i < words; i++)
- writew(le16_to_cpu(buf16[i]), mmio);
- } else {
- for (i = 0; i < words; i++)
- buf16[i] = cpu_to_le16(readw(mmio));
- }
+ if (write_data)
+ ap->io_ops->OUTSW(ap->ioaddr.data_addr, buf, words);
+ else
+ ap->io_ops->INSW(ap->ioaddr.data_addr, buf, words);
/* Transfer trailing 1 byte, if any. */
if (unlikely(buflen & 0x01)) {
@@ -3940,9 +3846,9 @@ void ata_mmio_data_xfer(struct ata_devic
if (write_data) {
memcpy(align_buf, trailing_buf, 1);
- writew(le16_to_cpu(align_buf[0]), mmio);
+ ap->io_ops->OUTW(le16_to_cpu(align_buf[0]), ap->ioaddr.data_addr);
} else {
- align_buf[0] = cpu_to_le16(readw(mmio));
+ align_buf[0] = cpu_to_le16(ap->io_ops->INW(ap->ioaddr.data_addr));
memcpy(trailing_buf, align_buf, 1);
}
}
@@ -3969,9 +3875,9 @@ void ata_pio_data_xfer(struct ata_device
/* Transfer multiple of 2 bytes */
if (write_data)
- outsw(ap->ioaddr.data_addr, buf, words);
+ ap->io_ops->OUTSW(ap->ioaddr.data_addr, buf, words);
else
- insw(ap->ioaddr.data_addr, buf, words);
+ ap->io_ops->INSW(ap->ioaddr.data_addr, buf, words);
/* Transfer trailing 1 byte, if any. */
if (unlikely(buflen & 0x01)) {
@@ -3980,9 +3886,9 @@ void ata_pio_data_xfer(struct ata_device
if (write_data) {
memcpy(align_buf, trailing_buf, 1);
- outw(le16_to_cpu(align_buf[0]), ap->ioaddr.data_addr);
+ ap->io_ops->OUTW(le16_to_cpu(align_buf[0]), ap->ioaddr.data_addr);
} else {
- align_buf[0] = cpu_to_le16(inw(ap->ioaddr.data_addr));
+ align_buf[0] = cpu_to_le16(ap->io_ops->INW(ap->ioaddr.data_addr));
memcpy(trailing_buf, align_buf, 1);
}
}
@@ -5621,12 +5527,14 @@ void ata_port_init(struct ata_port *ap,
ap->udma_mask = ent->pinfo2->udma_mask;
ap->flags |= ent->pinfo2->flags;
ap->ops = ent->pinfo2->port_ops;
+ ap->io_ops = ent->pinfo2->io_ops;
} else {
ap->pio_mask = ent->pio_mask;
ap->mwdma_mask = ent->mwdma_mask;
ap->udma_mask = ent->udma_mask;
ap->flags |= ent->port_flags;
ap->ops = ent->port_ops;
+ ap->io_ops = ent->io_ops;
}
ap->hw_sata_spd_limit = UINT_MAX;
ap->active_tag = ATA_TAG_POISON;
@@ -5732,6 +5640,126 @@ static struct ata_port * ata_port_add(co
return ap;
}
+/*
+ * Conventional PIO operations for ATA devices
+ */
+
+static u8 ata_inb (unsigned long port)
+{
+ return (u8) inb(port);
+}
+
+static u16 ata_inw (unsigned long port)
+{
+ return (u16) inw(port);
+}
+
+static void ata_insw (unsigned long port, void *addr, u32 count)
+{
+ insw(port, addr, count);
+}
+
+static u32 ata_inl (unsigned long port)
+{
+ return (u32) inl(port);
+}
+
+static void ata_outb (u8 val, unsigned long port)
+{
+ outb(val, port);
+}
+
+static void ata_outw (u16 val, unsigned long port)
+{
+ outw(val, port);
+}
+
+static void ata_outsw (unsigned long port, void *addr, u32 count)
+{
+ outsw(port, addr, count);
+}
+
+static void ata_outl (u32 val, unsigned long port)
+{
+ outl(val, port);
+}
+
+/*
+ * Conventional MMIO operations for ATA devices
+ */
+
+static u8 ata_mm_inb (unsigned long port)
+{
+ return (u8) readb((void __iomem *) port);
+}
+
+static u16 ata_mm_inw (unsigned long port)
+{
+ return (u16) readw((void __iomem *) port);
+}
+
+static void ata_mm_insw (unsigned long port, void *addr, u32 count)
+{
+ unsigned int i;
+ u16 *buf16 = (u16 *) addr;
+ void __iomem *mmio = (void __iomem *) port;
+
+ for (i = 0; i < count; i++)
+ buf16[i] = cpu_to_le16(readw(mmio));
+}
+
+static u32 ata_mm_inl (unsigned long port)
+{
+ return (u32) readl((void __iomem *) port);
+}
+
+static void ata_mm_outb (u8 value, unsigned long port)
+{
+ writeb(value, (void __iomem *) port);
+}
+
+static void ata_mm_outw (u16 value, unsigned long port)
+{
+ writew(value, (void __iomem *) port);
+}
+
+static void ata_mm_outsw (unsigned long port, void *addr, u32 count)
+{
+ unsigned int i;
+ u16 *buf16 = (u16 *) addr;
+ void __iomem *mmio = (void __iomem *) port;
+
+ for (i = 0; i < count; i++)
+ writew(le16_to_cpu(buf16[i]), mmio);
+}
+
+static void ata_mm_outl (u32 value, unsigned long port)
+{
+ writel(value, (void __iomem *) port);
+}
+
+static struct ata_io_operations default_pio_ops = {
+ .OUTB = ata_outb,
+ .OUTW = ata_outw,
+ .OUTL = ata_outl,
+ .OUTSW = ata_outsw,
+ .INB = ata_inb,
+ .INW = ata_inw,
+ .INL = ata_inl,
+ .INSW = ata_insw,
+};
+
+static struct ata_io_operations default_mmio_ops = {
+ .OUTB = ata_mm_outb,
+ .OUTW = ata_mm_outw,
+ .OUTL = ata_mm_outl,
+ .OUTSW = ata_mm_outsw,
+ .INB = ata_mm_inb,
+ .INW = ata_mm_inw,
+ .INL = ata_mm_inl,
+ .INSW = ata_mm_insw,
+};
+
/**
* ata_sas_host_init - Initialize a host struct
* @host: host to initialize
@@ -5745,12 +5773,16 @@ static struct ata_port * ata_port_add(co
*/
void ata_host_init(struct ata_host *host, struct device *dev,
- unsigned long flags, const struct ata_port_operations *ops)
+ unsigned long flags, const struct ata_port_operations *ops,
+ struct ata_io_operations *io_ops)
{
spin_lock_init(&host->lock);
host->dev = dev;
host->flags = flags;
host->ops = ops;
+
+ if (!io_ops)
+ host->io_ops = flags & ATA_FLAG_MMIO ? &default_mmio_ops : &default_pio_ops;
}
/**
@@ -5790,7 +5822,7 @@ int ata_device_add(const struct ata_prob
if (!host)
return 0;
- ata_host_init(host, dev, ent->_host_flags, ent->port_ops);
+ ata_host_init(host, dev, ent->_host_flags, ent->port_ops, ent->io_ops);
host->n_ports = ent->n_ports;
host->irq = ent->irq;
host->irq2 = ent->irq2;
@@ -6110,6 +6142,7 @@ ata_probe_ent_alloc(struct device *dev,
probe_ent->mwdma_mask = port->mwdma_mask;
probe_ent->udma_mask = port->udma_mask;
probe_ent->port_ops = port->port_ops;
+ probe_ent->io_ops = port->io_ops;
probe_ent->private_data = port->private_data;
return probe_ent;
@@ -6500,3 +6533,5 @@ EXPORT_SYMBOL_GPL(ata_eh_thaw_port);
EXPORT_SYMBOL_GPL(ata_eh_qc_complete);
EXPORT_SYMBOL_GPL(ata_eh_qc_retry);
EXPORT_SYMBOL_GPL(ata_do_eh);
+
+EXPORT_SYMBOL_GPL(ata_probe_ent_alloc);
More information about the Linuxppc-dev
mailing list