// 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 = …; EXPORT_SYMBOL_GPL(…); /** * 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) { … } EXPORT_SYMBOL_GPL(…); /** * 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) { … } /** * 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) { … } /** * 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_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) { … } EXPORT_SYMBOL_GPL(…); /** * 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) { … } EXPORT_SYMBOL_GPL(…); static int ata_sff_check_ready(struct ata_link *link) { … } /** * 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) { … } EXPORT_SYMBOL_GPL(…); /** * 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) { … } /** * 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) { … } EXPORT_SYMBOL_GPL(…); /** * 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) { … } /** * 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) { … } EXPORT_SYMBOL_GPL(…); /** * 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) { … } EXPORT_SYMBOL_GPL(…); /** * 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) { … } EXPORT_SYMBOL_GPL(…); /** * 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) { … } EXPORT_SYMBOL_GPL(…); /** * 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) { … } /** * 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) { … } EXPORT_SYMBOL_GPL(…); /** * ata_sff_data_xfer32 - 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 using 32bit * I/O operations. * * LOCKING: * Inherited from caller. * * RETURNS: * Bytes consumed. */ unsigned int ata_sff_data_xfer32(struct ata_queued_cmd *qc, unsigned char *buf, unsigned int buflen, int rw) { … } EXPORT_SYMBOL_GPL(…); static void ata_pio_xfer(struct ata_queued_cmd *qc, struct page *page, unsigned int offset, size_t xfer_size) { … } /** * ata_pio_sector - Transfer a sector of data. * @qc: Command on going * * Transfer qc->sect_size bytes of data from/to the ATA device. * * LOCKING: * Inherited from caller. */ static void ata_pio_sector(struct ata_queued_cmd *qc) { … } /** * ata_pio_sectors - Transfer one or many sectors. * @qc: Command on going * * Transfer one or many sectors of data from/to the * ATA device for the DRQ request. * * LOCKING: * Inherited from caller. */ static void ata_pio_sectors(struct ata_queued_cmd *qc) { … } /** * atapi_send_cdb - Write CDB bytes to hardware * @ap: Port to which ATAPI device is attached. * @qc: Taskfile currently active * * When device has indicated its readiness to accept * a CDB, this function is called. Send the CDB. * * LOCKING: * caller. */ static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc) { … } /** * __atapi_pio_bytes - Transfer data from/to the ATAPI device. * @qc: Command on going * @bytes: number of bytes * * Transfer data from/to the ATAPI device. * * LOCKING: * Inherited from caller. * */ static int __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes) { … } /** * atapi_pio_bytes - Transfer data from/to the ATAPI device. * @qc: Command on going * * Transfer Transfer data from/to the ATAPI device. * * LOCKING: * Inherited from caller. */ static void atapi_pio_bytes(struct ata_queued_cmd *qc) { … } /** * ata_hsm_ok_in_wq - Check if the qc can be handled in the workqueue. * @ap: the target ata_port * @qc: qc on going * * RETURNS: * 1 if ok in workqueue, 0 otherwise. */ static inline int ata_hsm_ok_in_wq(struct ata_port *ap, struct ata_queued_cmd *qc) { … } /** * ata_hsm_qc_complete - finish a qc running on standard HSM * @qc: Command to complete * @in_wq: 1 if called from workqueue, 0 otherwise * * Finish @qc which is running on standard HSM. * * LOCKING: * If @in_wq is zero, spin_lock_irqsave(host lock). * Otherwise, none on entry and grabs host lock. */ static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq) { … } /** * ata_sff_hsm_move - move the HSM to the next state. * @ap: the target ata_port * @qc: qc on going * @status: current device status * @in_wq: 1 if called from workqueue, 0 otherwise * * RETURNS: * 1 when poll next status needed, 0 otherwise. */ int ata_sff_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc, u8 status, int in_wq) { … } EXPORT_SYMBOL_GPL(…); void ata_sff_queue_work(struct work_struct *work) { … } EXPORT_SYMBOL_GPL(…); void ata_sff_queue_delayed_work(struct delayed_work *dwork, unsigned long delay) { … } EXPORT_SYMBOL_GPL(…); void ata_sff_queue_pio_task(struct ata_link *link, unsigned long delay) { … } EXPORT_SYMBOL_GPL(…); void ata_sff_flush_pio_task(struct ata_port *ap) { … } static void ata_sff_pio_task(struct work_struct *work) { … } /** * ata_sff_qc_issue - issue taskfile to a SFF controller * @qc: command to issue to device * * This function issues a PIO or NODATA command to a SFF * controller. * * LOCKING: * spin_lock_irqsave(host lock) * * RETURNS: * Zero on success, AC_ERR_* mask on failure */ unsigned int ata_sff_qc_issue(struct ata_queued_cmd *qc) { … } EXPORT_SYMBOL_GPL(…); /** * ata_sff_qc_fill_rtf - fill result TF using ->sff_tf_read * @qc: qc to fill result TF for * * @qc is finished and result TF needs to be filled. Fill it * using ->sff_tf_read. * * LOCKING: * spin_lock_irqsave(host lock) */ void ata_sff_qc_fill_rtf(struct ata_queued_cmd *qc) { … } EXPORT_SYMBOL_GPL(…); static unsigned int ata_sff_idle_irq(struct ata_port *ap) { … } static unsigned int __ata_sff_port_intr(struct ata_port *ap, struct ata_queued_cmd *qc, bool hsmv_on_idle) { … } /** * ata_sff_port_intr - Handle SFF port interrupt * @ap: Port on which interrupt arrived (possibly...) * @qc: Taskfile currently active in engine * * Handle port interrupt for given queued command. * * LOCKING: * spin_lock_irqsave(host lock) * * RETURNS: * One if interrupt was handled, zero if not (shared irq). */ unsigned int ata_sff_port_intr(struct ata_port *ap, struct ata_queued_cmd *qc) { … } EXPORT_SYMBOL_GPL(…); static inline irqreturn_t __ata_sff_interrupt(int irq, void *dev_instance, unsigned int (*port_intr)(struct ata_port *, struct ata_queued_cmd *)) { … } /** * ata_sff_interrupt - Default SFF ATA host interrupt handler * @irq: irq line (unused) * @dev_instance: pointer to our ata_host information structure * * Default interrupt handler for PCI IDE devices. Calls * ata_sff_port_intr() for each port that is not disabled. * * LOCKING: * Obtains host lock during operation. * * RETURNS: * IRQ_NONE or IRQ_HANDLED. */ irqreturn_t ata_sff_interrupt(int irq, void *dev_instance) { … } EXPORT_SYMBOL_GPL(…); /** * ata_sff_lost_interrupt - Check for an apparent lost interrupt * @ap: port that appears to have timed out * * Called from the libata error handlers when the core code suspects * an interrupt has been lost. If it has complete anything we can and * then return. Interface must support altstatus for this faster * recovery to occur. * * Locking: * Caller holds host lock */ void ata_sff_lost_interrupt(struct ata_port *ap) { … } EXPORT_SYMBOL_GPL(…); /** * ata_sff_freeze - Freeze SFF controller port * @ap: port to freeze * * Freeze SFF controller port. * * LOCKING: * Inherited from caller. */ void ata_sff_freeze(struct ata_port *ap) { … } EXPORT_SYMBOL_GPL(…); /** * ata_sff_thaw - Thaw SFF controller port * @ap: port to thaw * * Thaw SFF controller port. * * LOCKING: * Inherited from caller. */ void ata_sff_thaw(struct ata_port *ap) { … } EXPORT_SYMBOL_GPL(…); /** * ata_sff_prereset - prepare SFF link for reset * @link: SFF link to be reset * @deadline: deadline jiffies for the operation * * SFF link @link is about to be reset. Initialize it. It first * calls ata_std_prereset() and wait for !BSY if the port is * being softreset. * * LOCKING: * Kernel thread context (may sleep) * * RETURNS: * Always 0. */ int ata_sff_prereset(struct ata_link *link, unsigned long deadline) { … } EXPORT_SYMBOL_GPL(…); /** * ata_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. * * RETURN: * true if device is present, false if not. * * LOCKING: * caller. */ static bool ata_devchk(struct ata_port *ap, unsigned int device) { … } /** * ata_sff_dev_classify - Parse returned ATA device signature * @dev: ATA device to classify (starting at zero) * @present: device seems present * @r_err: Value of error register on completion * * After an event -- SRST, E.D.D., or SATA COMRESET -- occurs, * an ATA/ATAPI-defined set of values is placed in the ATA * shadow registers, indicating the results of device detection * and diagnostics. * * Select the ATA device, and read the values from the ATA shadow * registers. Then parse according to the Error register value, * and the spec-defined values examined by ata_dev_classify(). * * LOCKING: * caller. * * RETURNS: * Device type - %ATA_DEV_ATA, %ATA_DEV_ATAPI or %ATA_DEV_NONE. */ unsigned int ata_sff_dev_classify(struct ata_device *dev, int present, u8 *r_err) { … } EXPORT_SYMBOL_GPL(…); /** * ata_sff_wait_after_reset - wait for devices to become ready after reset * @link: SFF link which is just reset * @devmask: mask of present devices * @deadline: deadline jiffies for the operation * * Wait devices attached to SFF @link to become ready after * reset. It contains preceding 150ms wait to avoid accessing TF * status register too early. * * LOCKING: * Kernel thread context (may sleep). * * RETURNS: * 0 on success, -ENODEV if some or all of devices in @devmask * don't seem to exist. -errno on other errors. */ int ata_sff_wait_after_reset(struct ata_link *link, unsigned int devmask, unsigned long deadline) { … } EXPORT_SYMBOL_GPL(…); static int ata_bus_softreset(struct ata_port *ap, unsigned int devmask, unsigned long deadline) { … } /** * ata_sff_softreset - reset host port via ATA SRST * @link: ATA link to reset * @classes: resulting classes of attached devices * @deadline: deadline jiffies for the operation * * Reset host port using ATA SRST. * * LOCKING: * Kernel thread context (may sleep) * * RETURNS: * 0 on success, -errno otherwise. */ int ata_sff_softreset(struct ata_link *link, unsigned int *classes, unsigned long deadline) { … } EXPORT_SYMBOL_GPL(…); /** * sata_sff_hardreset - reset host port via SATA phy reset * @link: link to reset * @class: resulting class of attached device * @deadline: deadline jiffies for the operation * * SATA phy-reset host port using DET bits of SControl register, * wait for !BSY and classify the attached device. * * LOCKING: * Kernel thread context (may sleep) * * RETURNS: * 0 on success, -errno otherwise. */ int sata_sff_hardreset(struct ata_link *link, unsigned int *class, unsigned long deadline) { … } EXPORT_SYMBOL_GPL(…); /** * ata_sff_postreset - SFF postreset callback * @link: the target SFF ata_link * @classes: classes of attached devices * * This function is invoked after a successful reset. It first * calls ata_std_postreset() and performs SFF specific postreset * processing. * * LOCKING: * Kernel thread context (may sleep) */ void ata_sff_postreset(struct ata_link *link, unsigned int *classes) { … } EXPORT_SYMBOL_GPL(…); /** * ata_sff_drain_fifo - Stock FIFO drain logic for SFF controllers * @qc: command * * Drain the FIFO and device of any stuck data following a command * failing to complete. In some cases this is necessary before a * reset will recover the device. * */ void ata_sff_drain_fifo(struct ata_queued_cmd *qc) { … } EXPORT_SYMBOL_GPL(…); /** * ata_sff_error_handler - Stock error handler for SFF controller * @ap: port to handle error for * * Stock error handler for SFF controller. It can handle both * PATA and SATA controllers. Many controllers should be able to * use this EH as-is or with some added handling before and * after. * * LOCKING: * Kernel thread context (may sleep) */ void ata_sff_error_handler(struct ata_port *ap) { … } EXPORT_SYMBOL_GPL(…); /** * ata_sff_std_ports - initialize ioaddr with standard port offsets. * @ioaddr: IO address structure to be initialized * * Utility function which initializes data_addr, error_addr, * feature_addr, nsect_addr, lbal_addr, lbam_addr, lbah_addr, * device_addr, status_addr, and command_addr to standard offsets * relative to cmd_addr. * * Does not set ctl_addr, altstatus_addr, bmdma_addr, or scr_addr. */ void ata_sff_std_ports(struct ata_ioports *ioaddr) { … } EXPORT_SYMBOL_GPL(…); #ifdef CONFIG_PCI static bool ata_resources_present(struct pci_dev *pdev, int port) { … } /** * ata_pci_sff_init_host - acquire native PCI ATA resources and init host * @host: target ATA host * * Acquire native PCI ATA resources for @host and initialize the * first two ports of @host accordingly. Ports marked dummy are * skipped and allocation failure makes the port dummy. * * Note that native PCI resources are valid even for legacy hosts * as we fix up pdev resources array early in boot, so this * function can be used for both native and legacy SFF hosts. * * LOCKING: * Inherited from calling layer (may sleep). * * RETURNS: * 0 if at least one port is initialized, -ENODEV if no port is * available. */ int ata_pci_sff_init_host(struct ata_host *host) { … } EXPORT_SYMBOL_GPL(…); /** * ata_pci_sff_prepare_host - helper to prepare PCI PIO-only SFF ATA host * @pdev: target PCI device * @ppi: array of port_info, must be enough for two ports * @r_host: out argument for the initialized ATA host * * Helper to allocate PIO-only SFF ATA host for @pdev, acquire * all PCI resources and initialize it accordingly in one go. * * LOCKING: * Inherited from calling layer (may sleep). * * RETURNS: * 0 on success, -errno otherwise. */ int ata_pci_sff_prepare_host(struct pci_dev *pdev, const struct ata_port_info * const *ppi, struct ata_host **r_host) { … } EXPORT_SYMBOL_GPL(…); /** * ata_pci_sff_activate_host - start SFF host, request IRQ and register it * @host: target SFF ATA host * @irq_handler: irq_handler used when requesting IRQ(s) * @sht: scsi_host_template to use when registering the host * * This is the counterpart of ata_host_activate() for SFF ATA * hosts. This separate helper is necessary because SFF hosts * use two separate interrupts in legacy mode. * * LOCKING: * Inherited from calling layer (may sleep). * * RETURNS: * 0 on success, -errno otherwise. */ int ata_pci_sff_activate_host(struct ata_host *host, irq_handler_t irq_handler, const struct scsi_host_template *sht) { … } EXPORT_SYMBOL_GPL(…); static const struct ata_port_info *ata_sff_find_valid_pi( const struct ata_port_info * const *ppi) { … } static int ata_pci_init_one(struct pci_dev *pdev, const struct ata_port_info * const *ppi, const struct scsi_host_template *sht, void *host_priv, int hflags, bool bmdma) { … } /** * ata_pci_sff_init_one - Initialize/register PIO-only PCI IDE controller * @pdev: Controller to be initialized * @ppi: array of port_info, must be enough for two ports * @sht: scsi_host_template to use when registering the host * @host_priv: host private_data * @hflag: host flags * * This is a helper function which can be called from a driver's * xxx_init_one() probe function if the hardware uses traditional * IDE taskfile registers and is PIO only. * * ASSUMPTION: * Nobody makes a single channel controller that appears solely as * the secondary legacy port on PCI. * * LOCKING: * Inherited from PCI layer (may sleep). * * RETURNS: * Zero on success, negative on errno-based value on error. */ int ata_pci_sff_init_one(struct pci_dev *pdev, const struct ata_port_info * const *ppi, const struct scsi_host_template *sht, void *host_priv, int hflag) { … } EXPORT_SYMBOL_GPL(…); #endif /* CONFIG_PCI */ /* * BMDMA support */ #ifdef CONFIG_ATA_BMDMA const struct ata_port_operations ata_bmdma_port_ops = …; EXPORT_SYMBOL_GPL(…); const struct ata_port_operations ata_bmdma32_port_ops = …; EXPORT_SYMBOL_GPL(…); /** * ata_bmdma_fill_sg - Fill PCI IDE PRD table * @qc: Metadata associated with taskfile to be transferred * * Fill PCI IDE PRD (scatter-gather) table with segments * associated with the current disk command. * * LOCKING: * spin_lock_irqsave(host lock) * */ static void ata_bmdma_fill_sg(struct ata_queued_cmd *qc) { … } /** * ata_bmdma_fill_sg_dumb - Fill PCI IDE PRD table * @qc: Metadata associated with taskfile to be transferred * * Fill PCI IDE PRD (scatter-gather) table with segments * associated with the current disk command. Perform the fill * so that we avoid writing any length 64K records for * controllers that don't follow the spec. * * LOCKING: * spin_lock_irqsave(host lock) * */ static void ata_bmdma_fill_sg_dumb(struct ata_queued_cmd *qc) { … } /** * ata_bmdma_qc_prep - Prepare taskfile for submission * @qc: Metadata associated with taskfile to be prepared * * Prepare ATA taskfile for submission. * * LOCKING: * spin_lock_irqsave(host lock) */ enum ata_completion_errors ata_bmdma_qc_prep(struct ata_queued_cmd *qc) { … } EXPORT_SYMBOL_GPL(…); /** * ata_bmdma_dumb_qc_prep - Prepare taskfile for submission * @qc: Metadata associated with taskfile to be prepared * * Prepare ATA taskfile for submission. * * LOCKING: * spin_lock_irqsave(host lock) */ enum ata_completion_errors ata_bmdma_dumb_qc_prep(struct ata_queued_cmd *qc) { … } EXPORT_SYMBOL_GPL(…); /** * ata_bmdma_qc_issue - issue taskfile to a BMDMA controller * @qc: command to issue to device * * This function issues a PIO, NODATA or DMA command to a * SFF/BMDMA controller. PIO and NODATA are handled by * ata_sff_qc_issue(). * * LOCKING: * spin_lock_irqsave(host lock) * * RETURNS: * Zero on success, AC_ERR_* mask on failure */ unsigned int ata_bmdma_qc_issue(struct ata_queued_cmd *qc) { … } EXPORT_SYMBOL_GPL(…); /** * ata_bmdma_port_intr - Handle BMDMA port interrupt * @ap: Port on which interrupt arrived (possibly...) * @qc: Taskfile currently active in engine * * Handle port interrupt for given queued command. * * LOCKING: * spin_lock_irqsave(host lock) * * RETURNS: * One if interrupt was handled, zero if not (shared irq). */ unsigned int ata_bmdma_port_intr(struct ata_port *ap, struct ata_queued_cmd *qc) { … } EXPORT_SYMBOL_GPL(…); /** * ata_bmdma_interrupt - Default BMDMA ATA host interrupt handler * @irq: irq line (unused) * @dev_instance: pointer to our ata_host information structure * * Default interrupt handler for PCI IDE devices. Calls * ata_bmdma_port_intr() for each port that is not disabled. * * LOCKING: * Obtains host lock during operation. * * RETURNS: * IRQ_NONE or IRQ_HANDLED. */ irqreturn_t ata_bmdma_interrupt(int irq, void *dev_instance) { … } EXPORT_SYMBOL_GPL(…); /** * ata_bmdma_error_handler - Stock error handler for BMDMA controller * @ap: port to handle error for * * Stock error handler for BMDMA controller. It can handle both * PATA and SATA controllers. Most BMDMA controllers should be * able to use this EH as-is or with some added handling before * and after. * * LOCKING: * Kernel thread context (may sleep) */ void ata_bmdma_error_handler(struct ata_port *ap) { … } EXPORT_SYMBOL_GPL(…); /** * ata_bmdma_post_internal_cmd - Stock post_internal_cmd for BMDMA * @qc: internal command to clean up * * LOCKING: * Kernel thread context (may sleep) */ void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc) { … } EXPORT_SYMBOL_GPL(…); /** * 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 lock) */ void ata_bmdma_irq_clear(struct ata_port *ap) { … } EXPORT_SYMBOL_GPL(…); /** * ata_bmdma_setup - Set up PCI IDE BMDMA transaction * @qc: Info associated with this ATA transaction. * * LOCKING: * spin_lock_irqsave(host lock) */ void ata_bmdma_setup(struct ata_queued_cmd *qc) { … } EXPORT_SYMBOL_GPL(…); /** * ata_bmdma_start - Start a PCI IDE BMDMA transaction * @qc: Info associated with this ATA transaction. * * LOCKING: * spin_lock_irqsave(host lock) */ void ata_bmdma_start(struct ata_queued_cmd *qc) { … } EXPORT_SYMBOL_GPL(…); /** * 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 lock) */ void ata_bmdma_stop(struct ata_queued_cmd *qc) { … } EXPORT_SYMBOL_GPL(…); /** * 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 lock) */ u8 ata_bmdma_status(struct ata_port *ap) { … } EXPORT_SYMBOL_GPL(…); /** * ata_bmdma_port_start - Set port up for bmdma. * @ap: Port to initialize * * Called just after data structures for each port are * initialized. Allocates space for PRD table. * * May be used as the port_start() entry in ata_port_operations. * * LOCKING: * Inherited from caller. */ int ata_bmdma_port_start(struct ata_port *ap) { … } EXPORT_SYMBOL_GPL(…); /** * ata_bmdma_port_start32 - Set port up for dma. * @ap: Port to initialize * * Called just after data structures for each port are * initialized. Enables 32bit PIO and allocates space for PRD * table. * * May be used as the port_start() entry in ata_port_operations for * devices that are capable of 32bit PIO. * * LOCKING: * Inherited from caller. */ int ata_bmdma_port_start32(struct ata_port *ap) { … } EXPORT_SYMBOL_GPL(…); #ifdef CONFIG_PCI /** * ata_pci_bmdma_clear_simplex - attempt to kick device out of simplex * @pdev: PCI device * * Some PCI ATA devices report simplex mode but in fact can be told to * enter non simplex mode. This implements the necessary logic to * perform the task on such devices. Calling it on other devices will * have -undefined- behaviour. */ int ata_pci_bmdma_clear_simplex(struct pci_dev *pdev) { … } EXPORT_SYMBOL_GPL(…); static void ata_bmdma_nodma(struct ata_host *host, const char *reason) { … } /** * ata_pci_bmdma_init - acquire PCI BMDMA resources and init ATA host * @host: target ATA host * * Acquire PCI BMDMA resources and initialize @host accordingly. * * LOCKING: * Inherited from calling layer (may sleep). */ void ata_pci_bmdma_init(struct ata_host *host) { … } EXPORT_SYMBOL_GPL(…); /** * ata_pci_bmdma_prepare_host - helper to prepare PCI BMDMA ATA host * @pdev: target PCI device * @ppi: array of port_info, must be enough for two ports * @r_host: out argument for the initialized ATA host * * Helper to allocate BMDMA ATA host for @pdev, acquire all PCI * resources and initialize it accordingly in one go. * * LOCKING: * Inherited from calling layer (may sleep). * * RETURNS: * 0 on success, -errno otherwise. */ int ata_pci_bmdma_prepare_host(struct pci_dev *pdev, const struct ata_port_info * const * ppi, struct ata_host **r_host) { … } EXPORT_SYMBOL_GPL(…); /** * ata_pci_bmdma_init_one - Initialize/register BMDMA PCI IDE controller * @pdev: Controller to be initialized * @ppi: array of port_info, must be enough for two ports * @sht: scsi_host_template to use when registering the host * @host_priv: host private_data * @hflags: host flags * * This function is similar to ata_pci_sff_init_one() but also * takes care of BMDMA initialization. * * LOCKING: * Inherited from PCI layer (may sleep). * * RETURNS: * Zero on success, negative on errno-based value on error. */ int ata_pci_bmdma_init_one(struct pci_dev *pdev, const struct ata_port_info * const * ppi, const struct scsi_host_template *sht, void *host_priv, int hflags) { … } EXPORT_SYMBOL_GPL(…); #endif /* CONFIG_PCI */ #endif /* CONFIG_ATA_BMDMA */ /** * ata_sff_port_init - Initialize SFF/BMDMA ATA port * @ap: Port to initialize * * Called on port allocation to initialize SFF/BMDMA specific * fields. * * LOCKING: * None. */ void ata_sff_port_init(struct ata_port *ap) { … } int __init ata_sff_init(void) { … } void ata_sff_exit(void) { … }