// SPDX-License-Identifier: GPL-2.0-or-later/* * libata-sff.c - helper library for PCI IDE BMDMA * * Copyright 2003-2006 Red Hat, Inc. All rights reserved. * Copyright 2003-2006 Jeff Garzik * * libata documentation is available via 'make {ps|pdf}docs', * as Documentation/driver-api/libata.rst * * Hardware documentation available from http://www.t13.org/ and * http://www.sata-io.org/ */ #include <linux/kernel.h>#include <linux/gfp.h>#include <linux/pci.h>#include <linux/module.h>#include <linux/libata.h>#include <linux/highmem.h>#include <trace/events/libata.h>#include "libata.h" static struct workqueue_struct *ata_sff_wq; const struct ata_port_operations ata_sff_port_ops = { .inherits = &ata_base_port_ops, .qc_issue = ata_sff_qc_issue, .qc_fill_rtf = ata_sff_qc_fill_rtf, .freeze = ata_sff_freeze, .thaw = ata_sff_thaw, .reset.prereset = ata_sff_prereset, .reset.softreset = ata_sff_softreset, .reset.hardreset = sata_sff_hardreset, .reset.postreset = ata_sff_postreset, .error_handler = ata_sff_error_handler, .sff_dev_select = ata_sff_dev_select, .sff_check_status = ata_sff_check_status, .sff_tf_load = ata_sff_tf_load, .sff_tf_read = ata_sff_tf_read, .sff_exec_command = ata_sff_exec_command, .sff_data_xfer = ata_sff_data_xfer, .sff_drain_fifo = ata_sff_drain_fifo, .lost_interrupt = ata_sff_lost_interrupt,};EXPORT_SYMBOL_GPL(ata_sff_port_ops); /** * ata_sff_check_status - Read device status reg & clear interrupt * @ap: port where the device is * * Reads ATA taskfile status register for currently-selected device * and return its value. This also clears pending interrupts * from this device * * LOCKING: * Inherited from caller. */u8 ata_sff_check_status(struct ata_port *ap){ return ioread8(ap->ioaddr.status_addr);}EXPORT_SYMBOL_GPL(ata_sff_check_status); /** * ata_sff_altstatus - Read device alternate status reg * @ap: port where the device is * @status: pointer to a status value * * Reads ATA alternate status register for currently-selected device * and return its value. * * RETURN: * true if the register exists, false if not. * * LOCKING: * Inherited from caller. */static bool ata_sff_altstatus(struct ata_port *ap, u8 *status){ u8 tmp; if (ap->ops->sff_check_altstatus) { tmp = ap->ops->sff_check_altstatus(ap); goto read; } if (ap->ioaddr.altstatus_addr) { tmp = ioread8(ap->ioaddr.altstatus_addr); goto read; } return false; read: if (status) *status = tmp; return true;} /** * ata_sff_irq_status - Check if the device is busy * @ap: port where the device is * * Determine if the port is currently busy. Uses altstatus * if available in order to avoid clearing shared IRQ status * when finding an IRQ source. Non ctl capable devices don't * share interrupt lines fortunately for us. * * LOCKING: * Inherited from caller. */static u8 ata_sff_irq_status(struct ata_port *ap){ u8 status; /* Not us: We are busy */ if (ata_sff_altstatus(ap, &status) && (status & ATA_BUSY)) return status; /* Clear INTRQ latch */ status = ap->ops->sff_check_status(ap); return status;} /** * ata_sff_sync - Flush writes * @ap: Port to wait for. * * CAUTION: * If we have an mmio device with no ctl and no altstatus * method this will fail. No such devices are known to exist. * * LOCKING: * Inherited from caller. */ static void ata_sff_sync(struct ata_port *ap){ ata_sff_altstatus(ap, NULL);} /** * ata_sff_pause - Flush writes and wait 400nS * @ap: Port to pause for. * * CAUTION: * If we have an mmio device with no ctl and no altstatus * method this will fail. No such devices are known to exist. * * LOCKING: * Inherited from caller. */ void ata_sff_pause(struct ata_port *ap){ ata_sff_sync(ap); ndelay(400);}EXPORT_SYMBOL_GPL(ata_sff_pause); /** * ata_sff_dma_pause - Pause before commencing DMA * @ap: Port to pause for. * * Perform I/O fencing and ensure sufficient cycle delays occur * for the HDMA1:0 transition */ void ata_sff_dma_pause(struct ata_port *ap){ /* * An altstatus read will cause the needed delay without * messing up the IRQ status */ if (ata_sff_altstatus(ap, NULL)) return; /* There are no DMA controllers without ctl. BUG here to ensure we never violate the HDMA1:0 transition timing and risk corruption. */ BUG();}EXPORT_SYMBOL_GPL(ata_sff_dma_pause); static int ata_sff_check_ready(struct ata_link *link){ u8 status = link->ap->ops->sff_check_status(link->ap); return ata_check_ready(status);} /** * ata_sff_wait_ready - sleep until BSY clears, or timeout * @link: SFF link to wait ready status for * @deadline: deadline jiffies for the operation * * Sleep until ATA Status register bit BSY clears, or timeout * occurs. * * LOCKING: * Kernel thread context (may sleep). * * RETURNS: * 0 on success, -errno otherwise. */int ata_sff_wait_ready(struct ata_link *link, unsigned long deadline){ return ata_wait_ready(link, deadline, ata_sff_check_ready);}EXPORT_SYMBOL_GPL(ata_sff_wait_ready); /** * ata_sff_set_devctl - Write device control reg * @ap: port where the device is * @ctl: value to write * * Writes ATA device control register. * * RETURN: * true if the register exists, false if not. * * LOCKING: * Inherited from caller. */static bool ata_sff_set_devctl(struct ata_port *ap, u8 ctl){ if (ap->ops->sff_set_devctl) { ap->ops->sff_set_devctl(ap, ctl); return true; } if (ap->ioaddr.ctl_addr) { iowrite8(ctl, ap->ioaddr.ctl_addr); return true; } return false;} /** * ata_sff_dev_select - Select device 0/1 on ATA bus * @ap: ATA channel to manipulate * @device: ATA device (numbered from zero) to select * * Use the method defined in the ATA specification to * make either device 0, or device 1, active on the * ATA channel. Works with both PIO and MMIO. * * May be used as the dev_select() entry in ata_port_operations. * * LOCKING: * caller. */void ata_sff_dev_select(struct ata_port *ap, unsigned int device){ u8 tmp; if (device == 0) tmp = ATA_DEVICE_OBS; else tmp = ATA_DEVICE_OBS | ATA_DEV1; iowrite8(tmp, ap->ioaddr.device_addr); ata_sff_pause(ap); /* needed; also flushes, for mmio */}EXPORT_SYMBOL_GPL(ata_sff_dev_select); /** * ata_dev_select - Select device 0/1 on ATA bus * @ap: ATA channel to manipulate * @device: ATA device (numbered from zero) to select * @wait: non-zero to wait for Status register BSY bit to clear * @can_sleep: non-zero if context allows sleeping * * Use the method defined in the ATA specification to * make either device 0, or device 1, active on the * ATA channel. * * This is a high-level version of ata_sff_dev_select(), which * additionally provides the services of inserting the proper * pauses and status polling, where needed. * * LOCKING: * caller. */static void ata_dev_select(struct ata_port *ap, unsigned int device, unsigned int wait, unsigned int can_sleep){ if (wait) ata_wait_idle(ap); ap->ops->sff_dev_select(ap, device); if (wait) { if (can_sleep && ap->link.device[device].class == ATA_DEV_ATAPI) ata_msleep(ap, 150); ata_wait_idle(ap); }} /** * ata_sff_irq_on - Enable interrupts on a port. * @ap: Port on which interrupts are enabled. * * Enable interrupts on a legacy IDE device using MMIO or PIO, * wait for idle, clear any pending interrupts. * * Note: may NOT be used as the sff_irq_on() entry in * ata_port_operations. * * LOCKING: * Inherited from caller. */void ata_sff_irq_on(struct ata_port *ap){ if (ap->ops->sff_irq_on) { ap->ops->sff_irq_on(ap); return; } ap->ctl &= ~ATA_NIEN; ap->last_ctl = ap->ctl; ata_sff_set_devctl(ap, ap->ctl); ata_wait_idle(ap); if (ap->ops->sff_irq_clear) ap->ops->sff_irq_clear(ap);}EXPORT_SYMBOL_GPL(ata_sff_irq_on); /** * ata_sff_tf_load - send taskfile registers to host controller * @ap: Port to which output is sent * @tf: ATA taskfile register set * * Outputs ATA taskfile to standard ATA host controller. * * LOCKING: * Inherited from caller. */void ata_sff_tf_load(struct ata_port *ap, const struct ata_taskfile *tf){ struct ata_ioports *ioaddr = &ap->ioaddr; unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR; if (tf->ctl != ap->last_ctl) { if (ioaddr->ctl_addr) iowrite8(tf->ctl, ioaddr->ctl_addr); ap->last_ctl = tf->ctl; ata_wait_idle(ap); } if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) { WARN_ON_ONCE(!ioaddr->ctl_addr); iowrite8(tf->hob_feature, ioaddr->feature_addr); iowrite8(tf->hob_nsect, ioaddr->nsect_addr); iowrite8(tf->hob_lbal, ioaddr->lbal_addr); iowrite8(tf->hob_lbam, ioaddr->lbam_addr); iowrite8(tf->hob_lbah, ioaddr->lbah_addr); } if (is_addr) { iowrite8(tf->feature, ioaddr->feature_addr); iowrite8(tf->nsect, ioaddr->nsect_addr); iowrite8(tf->lbal, ioaddr->lbal_addr); iowrite8(tf->lbam, ioaddr->lbam_addr); iowrite8(tf->lbah, ioaddr->lbah_addr); } if (tf->flags & ATA_TFLAG_DEVICE) iowrite8(tf->device, ioaddr->device_addr); ata_wait_idle(ap);}EXPORT_SYMBOL_GPL(ata_sff_tf_load); /** * ata_sff_tf_read - input device's ATA taskfile shadow registers * @ap: Port from which input is read * @tf: ATA taskfile register set for storing input * * Reads ATA taskfile registers for currently-selected device * into @tf. Assumes the device has a fully SFF compliant task file * layout and behaviour. If you device does not (eg has a different * status method) then you will need to provide a replacement tf_read * * LOCKING: * Inherited from caller. */void ata_sff_tf_read(struct ata_port *ap, struct ata_taskfile *tf){ struct ata_ioports *ioaddr = &ap->ioaddr; tf->status = ata_sff_check_status(ap); tf->error = ioread8(ioaddr->error_addr); tf->nsect = ioread8(ioaddr->nsect_addr); tf->lbal = ioread8(ioaddr->lbal_addr); tf->lbam = ioread8(ioaddr->lbam_addr); tf->lbah = ioread8(ioaddr->lbah_addr); tf->device = ioread8(ioaddr->device_addr); if (tf->flags & ATA_TFLAG_LBA48) { if (likely(ioaddr->ctl_addr)) { iowrite8(tf->ctl | ATA_HOB, ioaddr->ctl_addr); tf->hob_feature = ioread8(ioaddr->error_addr); tf->hob_nsect = ioread8(ioaddr->nsect_addr); tf->hob_lbal = ioread8(ioaddr->lbal_addr); tf->hob_lbam = ioread8(ioaddr->lbam_addr); tf->hob_lbah = ioread8(ioaddr->lbah_addr); iowrite8(tf->ctl, ioaddr->ctl_addr); ap->last_ctl = tf->ctl; } else WARN_ON_ONCE(1); }}EXPORT_SYMBOL_GPL(ata_sff_tf_read); /** * ata_sff_exec_command - issue ATA command to host controller * @ap: port to which command is being issued * @tf: ATA taskfile register set * * Issues ATA command, with proper synchronization with interrupt * handler / other threads. * * LOCKING: * spin_lock_irqsave(host lock) */void ata_sff_exec_command(struct ata_port *ap, const struct ata_taskfile *tf){ iowrite8(tf->command, ap->ioaddr.command_addr); ata_sff_pause(ap);}EXPORT_SYMBOL_GPL(ata_sff_exec_command); /** * ata_tf_to_host - issue ATA taskfile to host controller * @ap: port to which command is being issued * @tf: ATA taskfile register set * @tag: tag of the associated command * * Issues ATA taskfile register set to ATA host controller, * with proper synchronization with interrupt handler and * other threads. * * LOCKING: * spin_lock_irqsave(host lock) */static inline void ata_tf_to_host(struct ata_port *ap, const struct ata_taskfile *tf, unsigned int tag){ trace_ata_tf_load(ap, tf); ap->ops->sff_tf_load(ap, tf); trace_ata_exec_command(ap, tf, tag); ap->ops->sff_exec_command(ap, tf);} /** * ata_sff_data_xfer - Transfer data by PIO * @qc: queued command * @buf: data buffer * @buflen: buffer length * @rw: read/write * * Transfer data from/to the device data register by PIO. * * LOCKING: * Inherited from caller. * * RETURNS: * Bytes consumed. */unsigned int ata_sff_data_xfer(struct ata_queued_cmd *qc, unsigned char *buf, unsigned int buflen, int rw){ struct ata_port *ap = qc->dev->link->ap; void __iomem *data_addr = ap->ioaddr.data_addr; unsigned int words = buflen >> 1; /* Transfer multiple of 2 bytes */ if (rw == READ) ioread16_rep(data_addr, buf, words); else iowrite16_rep(data_addr, buf, words); /* Transfer trailing byte, if any. */ if (unlikely(buflen & 0x01)) { unsigned char pad[2] = { }; /* Point buf to the tail of buffer */ buf += buflen - 1; /* * Use io*16_rep() accessors here as well to avoid pointlessly * swapping bytes to and from on the big endian machines... */ if (rw == READ) { ioread16_rep(data_addr, pad, 1);Lines 1–500 of 3217. Load more
// SPDX-License-Identifier: GPL-2.0-or-later /* * libata-sff.c - helper library for PCI IDE BMDMA * * Copyright 2003-2006 Red Hat, Inc. All rights reserved. * Copyright 2003-2006 Jeff Garzik * * libata documentation is available via 'make {ps|pdf}docs', * as Documentation/driver-api/libata.rst * * Hardware documentation available from http://www.t13.org/ and * http://www.sata-io.org/ */ #include <linux/kernel.h> #include <linux/gfp.h> #include <linux/pci.h> #include <linux/module.h> #include <linux/libata.h> #include <linux/highmem.h> #include <trace/events/libata.h> #include "libata.h" static struct workqueue_struct *ata_sff_wq; const struct ata_port_operations ata_sff_port_ops = { .inherits = &ata_base_port_ops, .qc_issue = ata_sff_qc_issue, .qc_fill_rtf = ata_sff_qc_fill_rtf, .freeze = ata_sff_freeze, .thaw = ata_sff_thaw, .reset.prereset = ata_sff_prereset, .reset.softreset = ata_sff_softreset, .reset.hardreset = sata_sff_hardreset, .reset.postreset = ata_sff_postreset, .error_handler = ata_sff_error_handler, .sff_dev_select = ata_sff_dev_select, .sff_check_status = ata_sff_check_status, .sff_tf_load = ata_sff_tf_load, .sff_tf_read = ata_sff_tf_read, .sff_exec_command = ata_sff_exec_command, .sff_data_xfer = ata_sff_data_xfer, .sff_drain_fifo = ata_sff_drain_fifo, .lost_interrupt = ata_sff_lost_interrupt, }; EXPORT_SYMBOL_GPL(ata_sff_port_ops); /** * ata_sff_check_status - Read device status reg & clear interrupt * @ap: port where the device is * * Reads ATA taskfile status register for currently-selected device * and return its value. This also clears pending interrupts * from this device * * LOCKING: * Inherited from caller. */ u8 ata_sff_check_status(struct ata_port *ap) { return ioread8(ap->ioaddr.status_addr); } EXPORT_SYMBOL_GPL(ata_sff_check_status); /** * ata_sff_altstatus - Read device alternate status reg * @ap: port where the device is * @status: pointer to a status value * * Reads ATA alternate status register for currently-selected device * and return its value. * * RETURN: * true if the register exists, false if not. * * LOCKING: * Inherited from caller. */ static bool ata_sff_altstatus(struct ata_port *ap, u8 *status) { u8 tmp; if (ap->ops->sff_check_altstatus) { tmp = ap->ops->sff_check_altstatus(ap); goto read; } if (ap->ioaddr.altstatus_addr) { tmp = ioread8(ap->ioaddr.altstatus_addr); goto read; } return false; read: if (status) *status = tmp; return true; } /** * ata_sff_irq_status - Check if the device is busy * @ap: port where the device is * * Determine if the port is currently busy. Uses altstatus * if available in order to avoid clearing shared IRQ status * when finding an IRQ source. Non ctl capable devices don't * share interrupt lines fortunately for us. * * LOCKING: * Inherited from caller. */ static u8 ata_sff_irq_status(struct ata_port *ap) { u8 status; /* Not us: We are busy */ if (ata_sff_altstatus(ap, &status) && (status & ATA_BUSY)) return status; /* Clear INTRQ latch */ status = ap->ops->sff_check_status(ap); return status; } /** * ata_sff_sync - Flush writes * @ap: Port to wait for. * * CAUTION: * If we have an mmio device with no ctl and no altstatus * method this will fail. No such devices are known to exist. * * LOCKING: * Inherited from caller. */ static void ata_sff_sync(struct ata_port *ap) { ata_sff_altstatus(ap, NULL); } /** * ata_sff_pause - Flush writes and wait 400nS * @ap: Port to pause for. * * CAUTION: * If we have an mmio device with no ctl and no altstatus * method this will fail. No such devices are known to exist. * * LOCKING: * Inherited from caller. */ void ata_sff_pause(struct ata_port *ap) { ata_sff_sync(ap); ndelay(400); } EXPORT_SYMBOL_GPL(ata_sff_pause); /** * ata_sff_dma_pause - Pause before commencing DMA * @ap: Port to pause for. * * Perform I/O fencing and ensure sufficient cycle delays occur * for the HDMA1:0 transition */ void ata_sff_dma_pause(struct ata_port *ap) { /* * An altstatus read will cause the needed delay without * messing up the IRQ status */ if (ata_sff_altstatus(ap, NULL)) return; /* There are no DMA controllers without ctl. BUG here to ensure we never violate the HDMA1:0 transition timing and risk corruption. */ BUG(); } EXPORT_SYMBOL_GPL(ata_sff_dma_pause); static int ata_sff_check_ready(struct ata_link *link) { u8 status = link->ap->ops->sff_check_status(link->ap); return ata_check_ready(status); } /** * ata_sff_wait_ready - sleep until BSY clears, or timeout * @link: SFF link to wait ready status for * @deadline: deadline jiffies for the operation * * Sleep until ATA Status register bit BSY clears, or timeout * occurs. * * LOCKING: * Kernel thread context (may sleep). * * RETURNS: * 0 on success, -errno otherwise. */ int ata_sff_wait_ready(struct ata_link *link, unsigned long deadline) { return ata_wait_ready(link, deadline, ata_sff_check_ready); } EXPORT_SYMBOL_GPL(ata_sff_wait_ready); /** * ata_sff_set_devctl - Write device control reg * @ap: port where the device is * @ctl: value to write * * Writes ATA device control register. * * RETURN: * true if the register exists, false if not. * * LOCKING: * Inherited from caller. */ static bool ata_sff_set_devctl(struct ata_port *ap, u8 ctl) { if (ap->ops->sff_set_devctl) { ap->ops->sff_set_devctl(ap, ctl); return true; } if (ap->ioaddr.ctl_addr) { iowrite8(ctl, ap->ioaddr.ctl_addr); return true; } return false; } /** * ata_sff_dev_select - Select device 0/1 on ATA bus * @ap: ATA channel to manipulate * @device: ATA device (numbered from zero) to select * * Use the method defined in the ATA specification to * make either device 0, or device 1, active on the * ATA channel. Works with both PIO and MMIO. * * May be used as the dev_select() entry in ata_port_operations. * * LOCKING: * caller. */ void ata_sff_dev_select(struct ata_port *ap, unsigned int device) { u8 tmp; if (device == 0) tmp = ATA_DEVICE_OBS; else tmp = ATA_DEVICE_OBS | ATA_DEV1; iowrite8(tmp, ap->ioaddr.device_addr); ata_sff_pause(ap); /* needed; also flushes, for mmio */ } EXPORT_SYMBOL_GPL(ata_sff_dev_select); /** * ata_dev_select - Select device 0/1 on ATA bus * @ap: ATA channel to manipulate * @device: ATA device (numbered from zero) to select * @wait: non-zero to wait for Status register BSY bit to clear * @can_sleep: non-zero if context allows sleeping * * Use the method defined in the ATA specification to * make either device 0, or device 1, active on the * ATA channel. * * This is a high-level version of ata_sff_dev_select(), which * additionally provides the services of inserting the proper * pauses and status polling, where needed. * * LOCKING: * caller. */ static void ata_dev_select(struct ata_port *ap, unsigned int device, unsigned int wait, unsigned int can_sleep) { if (wait) ata_wait_idle(ap); ap->ops->sff_dev_select(ap, device); if (wait) { if (can_sleep && ap->link.device[device].class == ATA_DEV_ATAPI) ata_msleep(ap, 150); ata_wait_idle(ap); } } /** * ata_sff_irq_on - Enable interrupts on a port. * @ap: Port on which interrupts are enabled. * * Enable interrupts on a legacy IDE device using MMIO or PIO, * wait for idle, clear any pending interrupts. * * Note: may NOT be used as the sff_irq_on() entry in * ata_port_operations. * * LOCKING: * Inherited from caller. */ void ata_sff_irq_on(struct ata_port *ap) { if (ap->ops->sff_irq_on) { ap->ops->sff_irq_on(ap); return; } ap->ctl &= ~ATA_NIEN; ap->last_ctl = ap->ctl; ata_sff_set_devctl(ap, ap->ctl); ata_wait_idle(ap); if (ap->ops->sff_irq_clear) ap->ops->sff_irq_clear(ap); } EXPORT_SYMBOL_GPL(ata_sff_irq_on); /** * ata_sff_tf_load - send taskfile registers to host controller * @ap: Port to which output is sent * @tf: ATA taskfile register set * * Outputs ATA taskfile to standard ATA host controller. * * LOCKING: * Inherited from caller. */ void ata_sff_tf_load(struct ata_port *ap, const struct ata_taskfile *tf) { struct ata_ioports *ioaddr = &ap->ioaddr; unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR; if (tf->ctl != ap->last_ctl) { if (ioaddr->ctl_addr) iowrite8(tf->ctl, ioaddr->ctl_addr); ap->last_ctl = tf->ctl; ata_wait_idle(ap); } if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) { WARN_ON_ONCE(!ioaddr->ctl_addr); iowrite8(tf->hob_feature, ioaddr->feature_addr); iowrite8(tf->hob_nsect, ioaddr->nsect_addr); iowrite8(tf->hob_lbal, ioaddr->lbal_addr); iowrite8(tf->hob_lbam, ioaddr->lbam_addr); iowrite8(tf->hob_lbah, ioaddr->lbah_addr); } if (is_addr) { iowrite8(tf->feature, ioaddr->feature_addr); iowrite8(tf->nsect, ioaddr->nsect_addr); iowrite8(tf->lbal, ioaddr->lbal_addr); iowrite8(tf->lbam, ioaddr->lbam_addr); iowrite8(tf->lbah, ioaddr->lbah_addr); } if (tf->flags & ATA_TFLAG_DEVICE) iowrite8(tf->device, ioaddr->device_addr); ata_wait_idle(ap); } EXPORT_SYMBOL_GPL(ata_sff_tf_load); /** * ata_sff_tf_read - input device's ATA taskfile shadow registers * @ap: Port from which input is read * @tf: ATA taskfile register set for storing input * * Reads ATA taskfile registers for currently-selected device * into @tf. Assumes the device has a fully SFF compliant task file * layout and behaviour. If you device does not (eg has a different * status method) then you will need to provide a replacement tf_read * * LOCKING: * Inherited from caller. */ void ata_sff_tf_read(struct ata_port *ap, struct ata_taskfile *tf) { struct ata_ioports *ioaddr = &ap->ioaddr; tf->status = ata_sff_check_status(ap); tf->error = ioread8(ioaddr->error_addr); tf->nsect = ioread8(ioaddr->nsect_addr); tf->lbal = ioread8(ioaddr->lbal_addr); tf->lbam = ioread8(ioaddr->lbam_addr); tf->lbah = ioread8(ioaddr->lbah_addr); tf->device = ioread8(ioaddr->device_addr); if (tf->flags & ATA_TFLAG_LBA48) { if (likely(ioaddr->ctl_addr)) { iowrite8(tf->ctl | ATA_HOB, ioaddr->ctl_addr); tf->hob_feature = ioread8(ioaddr->error_addr); tf->hob_nsect = ioread8(ioaddr->nsect_addr); tf->hob_lbal = ioread8(ioaddr->lbal_addr); tf->hob_lbam = ioread8(ioaddr->lbam_addr); tf->hob_lbah = ioread8(ioaddr->lbah_addr); iowrite8(tf->ctl, ioaddr->ctl_addr); ap->last_ctl = tf->ctl; } else WARN_ON_ONCE(1); } } EXPORT_SYMBOL_GPL(ata_sff_tf_read); /** * ata_sff_exec_command - issue ATA command to host controller * @ap: port to which command is being issued * @tf: ATA taskfile register set * * Issues ATA command, with proper synchronization with interrupt * handler / other threads. * * LOCKING: * spin_lock_irqsave(host lock) */ void ata_sff_exec_command(struct ata_port *ap, const struct ata_taskfile *tf) { iowrite8(tf->command, ap->ioaddr.command_addr); ata_sff_pause(ap); } EXPORT_SYMBOL_GPL(ata_sff_exec_command); /** * ata_tf_to_host - issue ATA taskfile to host controller * @ap: port to which command is being issued * @tf: ATA taskfile register set * @tag: tag of the associated command * * Issues ATA taskfile register set to ATA host controller, * with proper synchronization with interrupt handler and * other threads. * * LOCKING: * spin_lock_irqsave(host lock) */ static inline void ata_tf_to_host(struct ata_port *ap, const struct ata_taskfile *tf, unsigned int tag) { trace_ata_tf_load(ap, tf); ap->ops->sff_tf_load(ap, tf); trace_ata_exec_command(ap, tf, tag); ap->ops->sff_exec_command(ap, tf); } /** * ata_sff_data_xfer - Transfer data by PIO * @qc: queued command * @buf: data buffer * @buflen: buffer length * @rw: read/write * * Transfer data from/to the device data register by PIO. * * LOCKING: * Inherited from caller. * * RETURNS: * Bytes consumed. */ unsigned int ata_sff_data_xfer(struct ata_queued_cmd *qc, unsigned char *buf, unsigned int buflen, int rw) { struct ata_port *ap = qc->dev->link->ap; void __iomem *data_addr = ap->ioaddr.data_addr; unsigned int words = buflen >> 1; /* Transfer multiple of 2 bytes */ if (rw == READ) ioread16_rep(data_addr, buf, words); else iowrite16_rep(data_addr, buf, words); /* Transfer trailing byte, if any. */ if (unlikely(buflen & 0x01)) { unsigned char pad[2] = { }; /* Point buf to the tail of buffer */ buf += buflen - 1; /* * Use io*16_rep() accessors here as well to avoid pointlessly * swapping bytes to and from on the big endian machines... */ if (rw == READ) { ioread16_rep(data_addr, pad, 1);