Loading drivers/scsi/libata-bmdma.c +234 −0 Original line number Diff line number Diff line Loading @@ -418,6 +418,240 @@ u8 ata_altstatus(struct ata_port *ap) return inb(ap->ioaddr.altstatus_addr); } /** * 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->ioaddr.bmdma_addr) return; 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 */ } #ifdef CONFIG_PCI static struct ata_probe_ent * ata_probe_ent_alloc(struct device *dev, const struct ata_port_info *port) Loading drivers/scsi/libata-core.c +0 −234 Original line number Diff line number Diff line Loading @@ -4064,240 +4064,6 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc) 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->ioaddr.bmdma_addr) return; 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...) Loading Loading
drivers/scsi/libata-bmdma.c +234 −0 Original line number Diff line number Diff line Loading @@ -418,6 +418,240 @@ u8 ata_altstatus(struct ata_port *ap) return inb(ap->ioaddr.altstatus_addr); } /** * 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->ioaddr.bmdma_addr) return; 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 */ } #ifdef CONFIG_PCI static struct ata_probe_ent * ata_probe_ent_alloc(struct device *dev, const struct ata_port_info *port) Loading
drivers/scsi/libata-core.c +0 −234 Original line number Diff line number Diff line Loading @@ -4064,240 +4064,6 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc) 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->ioaddr.bmdma_addr) return; 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...) Loading