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@xxxxxxxxxxxxx> Signed-off-by: Akira Iguchi <akira2.iguchi@xxxxxxxxxxxxx> --- --- 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); - To unsubscribe from this list: send the line "unsubscribe linux-ide" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html