Merge of 'docs' branch from

rsync://rsync.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev
This commit is contained in:
Linus Torvalds 2005-06-02 16:07:03 -07:00
commit 317604633e
5 changed files with 611 additions and 93 deletions

View File

@ -14,7 +14,7 @@
</authorgroup> </authorgroup>
<copyright> <copyright>
<year>2003</year> <year>2003-2005</year>
<holder>Jeff Garzik</holder> <holder>Jeff Garzik</holder>
</copyright> </copyright>
@ -44,30 +44,38 @@
<toc></toc> <toc></toc>
<chapter id="libataThanks"> <chapter id="libataIntroduction">
<title>Thanks</title> <title>Introduction</title>
<para> <para>
The bulk of the ATA knowledge comes thanks to long conversations with libATA is a library used inside the Linux kernel to support ATA host
Andre Hedrick (www.linux-ide.org). controllers and devices. libATA provides an ATA driver API, class
transports for ATA and ATAPI devices, and SCSI&lt;-&gt;ATA translation
for ATA devices according to the T10 SAT specification.
</para> </para>
<para> <para>
Thanks to Alan Cox for pointing out similarities This Guide documents the libATA driver API, library functions, library
between SATA and SCSI, and in general for motivation to hack on internals, and a couple sample ATA low-level drivers.
libata.
</para>
<para>
libata's device detection
method, ata_pio_devchk, and in general all the early probing was
based on extensive study of Hale Landis's probe/reset code in his
ATADRVR driver (www.ata-atapi.com).
</para> </para>
</chapter> </chapter>
<chapter id="libataDriverApi"> <chapter id="libataDriverApi">
<title>libata Driver API</title> <title>libata Driver API</title>
<para>
struct ata_port_operations is defined for every low-level libata
hardware driver, and it controls how the low-level driver
interfaces with the ATA and SCSI layers.
</para>
<para>
FIS-based drivers will hook into the system with ->qc_prep() and
->qc_issue() high-level hooks. Hardware which behaves in a manner
similar to PCI IDE hardware may utilize several generic helpers,
defining at a bare minimum the bus I/O addresses of the ATA shadow
register blocks.
</para>
<sect1> <sect1>
<title>struct ata_port_operations</title> <title>struct ata_port_operations</title>
<sect2><title>Disable ATA port</title>
<programlisting> <programlisting>
void (*port_disable) (struct ata_port *); void (*port_disable) (struct ata_port *);
</programlisting> </programlisting>
@ -78,6 +86,9 @@ void (*port_disable) (struct ata_port *);
unplug). unplug).
</para> </para>
</sect2>
<sect2><title>Post-IDENTIFY device configuration</title>
<programlisting> <programlisting>
void (*dev_config) (struct ata_port *, struct ata_device *); void (*dev_config) (struct ata_port *, struct ata_device *);
</programlisting> </programlisting>
@ -88,6 +99,9 @@ void (*dev_config) (struct ata_port *, struct ata_device *);
issue of SET FEATURES - XFER MODE, and prior to operation. issue of SET FEATURES - XFER MODE, and prior to operation.
</para> </para>
</sect2>
<sect2><title>Set PIO/DMA mode</title>
<programlisting> <programlisting>
void (*set_piomode) (struct ata_port *, struct ata_device *); void (*set_piomode) (struct ata_port *, struct ata_device *);
void (*set_dmamode) (struct ata_port *, struct ata_device *); void (*set_dmamode) (struct ata_port *, struct ata_device *);
@ -108,6 +122,9 @@ void (*post_set_mode) (struct ata_port *ap);
->set_dma_mode() is only called if DMA is possible. ->set_dma_mode() is only called if DMA is possible.
</para> </para>
</sect2>
<sect2><title>Taskfile read/write</title>
<programlisting> <programlisting>
void (*tf_load) (struct ata_port *ap, struct ata_taskfile *tf); void (*tf_load) (struct ata_port *ap, struct ata_taskfile *tf);
void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf); void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf);
@ -120,6 +137,9 @@ void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf);
taskfile register values. taskfile register values.
</para> </para>
</sect2>
<sect2><title>ATA command execute</title>
<programlisting> <programlisting>
void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf); void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf);
</programlisting> </programlisting>
@ -129,17 +149,37 @@ void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf);
->tf_load(), to be initiated in hardware. ->tf_load(), to be initiated in hardware.
</para> </para>
</sect2>
<sect2><title>Per-cmd ATAPI DMA capabilities filter</title>
<programlisting> <programlisting>
u8 (*check_status)(struct ata_port *ap); int (*check_atapi_dma) (struct ata_queued_cmd *qc);
void (*dev_select)(struct ata_port *ap, unsigned int device);
</programlisting> </programlisting>
<para> <para>
Reads the Status ATA shadow register from hardware. On some Allow low-level driver to filter ATA PACKET commands, returning a status
hardware, this has the side effect of clearing the interrupt indicating whether or not it is OK to use DMA for the supplied PACKET
condition. command.
</para> </para>
</sect2>
<sect2><title>Read specific ATA shadow registers</title>
<programlisting>
u8 (*check_status)(struct ata_port *ap);
u8 (*check_altstatus)(struct ata_port *ap);
u8 (*check_err)(struct ata_port *ap);
</programlisting>
<para>
Reads the Status/AltStatus/Error ATA shadow register from
hardware. On some hardware, reading the Status register has
the side effect of clearing the interrupt condition.
</para>
</sect2>
<sect2><title>Select ATA device on bus</title>
<programlisting> <programlisting>
void (*dev_select)(struct ata_port *ap, unsigned int device); void (*dev_select)(struct ata_port *ap, unsigned int device);
</programlisting> </programlisting>
@ -147,9 +187,13 @@ void (*dev_select)(struct ata_port *ap, unsigned int device);
<para> <para>
Issues the low-level hardware command(s) that causes one of N Issues the low-level hardware command(s) that causes one of N
hardware devices to be considered 'selected' (active and hardware devices to be considered 'selected' (active and
available for use) on the ATA bus. available for use) on the ATA bus. This generally has no
meaning on FIS-based devices.
</para> </para>
</sect2>
<sect2><title>Reset ATA bus</title>
<programlisting> <programlisting>
void (*phy_reset) (struct ata_port *ap); void (*phy_reset) (struct ata_port *ap);
</programlisting> </programlisting>
@ -162,17 +206,31 @@ void (*phy_reset) (struct ata_port *ap);
functions ata_bus_reset() or sata_phy_reset() for this hook. functions ata_bus_reset() or sata_phy_reset() for this hook.
</para> </para>
</sect2>
<sect2><title>Control PCI IDE BMDMA engine</title>
<programlisting> <programlisting>
void (*bmdma_setup) (struct ata_queued_cmd *qc); void (*bmdma_setup) (struct ata_queued_cmd *qc);
void (*bmdma_start) (struct ata_queued_cmd *qc); void (*bmdma_start) (struct ata_queued_cmd *qc);
void (*bmdma_stop) (struct ata_port *ap);
u8 (*bmdma_status) (struct ata_port *ap);
</programlisting> </programlisting>
<para> <para>
When setting up an IDE BMDMA transaction, these hooks arm When setting up an IDE BMDMA transaction, these hooks arm
(->bmdma_setup) and fire (->bmdma_start) the hardware's DMA (->bmdma_setup), fire (->bmdma_start), and halt (->bmdma_stop)
engine. the hardware's DMA engine. ->bmdma_status is used to read the standard
PCI IDE DMA Status register.
</para> </para>
<para>
These hooks are typically either no-ops, or simply not implemented, in
FIS-based drivers.
</para>
</sect2>
<sect2><title>High-level taskfile hooks</title>
<programlisting> <programlisting>
void (*qc_prep) (struct ata_queued_cmd *qc); void (*qc_prep) (struct ata_queued_cmd *qc);
int (*qc_issue) (struct ata_queued_cmd *qc); int (*qc_issue) (struct ata_queued_cmd *qc);
@ -190,20 +248,26 @@ int (*qc_issue) (struct ata_queued_cmd *qc);
->qc_issue is used to make a command active, once the hardware ->qc_issue is used to make a command active, once the hardware
and S/G tables have been prepared. IDE BMDMA drivers use the and S/G tables have been prepared. IDE BMDMA drivers use the
helper function ata_qc_issue_prot() for taskfile protocol-based helper function ata_qc_issue_prot() for taskfile protocol-based
dispatch. More advanced drivers roll their own ->qc_issue dispatch. More advanced drivers implement their own ->qc_issue.
implementation, using this as the "issue new ATA command to
hardware" hook.
</para> </para>
</sect2>
<sect2><title>Timeout (error) handling</title>
<programlisting> <programlisting>
void (*eng_timeout) (struct ata_port *ap); void (*eng_timeout) (struct ata_port *ap);
</programlisting> </programlisting>
<para> <para>
This is a high level error handling function, called from the This is a high level error handling function, called from the
error handling thread, when a command times out. error handling thread, when a command times out. Most newer
hardware will implement its own error handling code here. IDE BMDMA
drivers may use the helper function ata_eng_timeout().
</para> </para>
</sect2>
<sect2><title>Hardware interrupt handling</title>
<programlisting> <programlisting>
irqreturn_t (*irq_handler)(int, void *, struct pt_regs *); irqreturn_t (*irq_handler)(int, void *, struct pt_regs *);
void (*irq_clear) (struct ata_port *); void (*irq_clear) (struct ata_port *);
@ -216,6 +280,9 @@ void (*irq_clear) (struct ata_port *);
is quiet. is quiet.
</para> </para>
</sect2>
<sect2><title>SATA phy read/write</title>
<programlisting> <programlisting>
u32 (*scr_read) (struct ata_port *ap, unsigned int sc_reg); u32 (*scr_read) (struct ata_port *ap, unsigned int sc_reg);
void (*scr_write) (struct ata_port *ap, unsigned int sc_reg, void (*scr_write) (struct ata_port *ap, unsigned int sc_reg,
@ -227,6 +294,9 @@ void (*scr_write) (struct ata_port *ap, unsigned int sc_reg,
if ->phy_reset hook called the sata_phy_reset() helper function. if ->phy_reset hook called the sata_phy_reset() helper function.
</para> </para>
</sect2>
<sect2><title>Init and shutdown</title>
<programlisting> <programlisting>
int (*port_start) (struct ata_port *ap); int (*port_start) (struct ata_port *ap);
void (*port_stop) (struct ata_port *ap); void (*port_stop) (struct ata_port *ap);
@ -240,15 +310,17 @@ void (*host_stop) (struct ata_host_set *host_set);
tasks. tasks.
</para> </para>
<para> <para>
->host_stop() is called when the rmmod or hot unplug process
begins. The hook must stop all hardware interrupts, DMA
engines, etc.
</para>
<para>
->port_stop() is called after ->host_stop(). It's sole function ->port_stop() is called after ->host_stop(). It's sole function
is to release DMA/memory resources, now that they are no longer is to release DMA/memory resources, now that they are no longer
actively being used. actively being used.
</para> </para>
<para>
->host_stop() is called after all ->port_stop() calls
have completed. The hook must finalize hardware shutdown, release DMA
and other resources, etc.
</para>
</sect2>
</sect1> </sect1>
</chapter> </chapter>
@ -279,4 +351,24 @@ void (*host_stop) (struct ata_host_set *host_set);
!Idrivers/scsi/sata_sil.c !Idrivers/scsi/sata_sil.c
</chapter> </chapter>
<chapter id="libataThanks">
<title>Thanks</title>
<para>
The bulk of the ATA knowledge comes thanks to long conversations with
Andre Hedrick (www.linux-ide.org), and long hours pondering the ATA
and SCSI specifications.
</para>
<para>
Thanks to Alan Cox for pointing out similarities
between SATA and SCSI, and in general for motivation to hack on
libata.
</para>
<para>
libata's device detection
method, ata_pio_devchk, and in general all the early probing was
based on extensive study of Hale Landis's probe/reset code in his
ATADRVR driver (www.ata-atapi.com).
</para>
</chapter>
</book> </book>

View File

@ -665,15 +665,6 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
return ata_pci_init_one(pdev, port_info, n_ports); return ata_pci_init_one(pdev, port_info, n_ports);
} }
/**
* piix_init -
*
* LOCKING:
*
* RETURNS:
*
*/
static int __init piix_init(void) static int __init piix_init(void)
{ {
int rc; int rc;
@ -689,13 +680,6 @@ static int __init piix_init(void)
return 0; return 0;
} }
/**
* piix_exit -
*
* LOCKING:
*
*/
static void __exit piix_exit(void) static void __exit piix_exit(void)
{ {
pci_unregister_driver(&piix_pci_driver); pci_unregister_driver(&piix_pci_driver);

View File

@ -186,6 +186,28 @@ static void ata_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
ata_wait_idle(ap); ata_wait_idle(ap);
} }
/**
* ata_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 using MMIO
* or PIO as indicated by the ATA_FLAG_MMIO flag.
* Writes the control, feature, nsect, lbal, lbam, and lbah registers.
* Optionally (ATA_TFLAG_LBA48) writes hob_feature, hob_nsect,
* hob_lbal, hob_lbam, and hob_lbah.
*
* This function waits for idle (!BUSY and !DRQ) after writing
* registers. If the control register has a new value, this
* function also waits for idle after writing control and before
* writing the remaining registers.
*
* May be used as the tf_load() entry in ata_port_operations.
*
* LOCKING:
* Inherited from caller.
*/
void ata_tf_load(struct ata_port *ap, struct ata_taskfile *tf) void ata_tf_load(struct ata_port *ap, struct ata_taskfile *tf)
{ {
if (ap->flags & ATA_FLAG_MMIO) if (ap->flags & ATA_FLAG_MMIO)
@ -195,11 +217,11 @@ void ata_tf_load(struct ata_port *ap, struct ata_taskfile *tf)
} }
/** /**
* ata_exec_command - issue ATA command to host controller * ata_exec_command_pio - issue ATA command to host controller
* @ap: port to which command is being issued * @ap: port to which command is being issued
* @tf: ATA taskfile register set * @tf: ATA taskfile register set
* *
* Issues PIO/MMIO write to ATA command register, with proper * Issues PIO write to ATA command register, with proper
* synchronization with interrupt handler / other threads. * synchronization with interrupt handler / other threads.
* *
* LOCKING: * LOCKING:
@ -235,6 +257,18 @@ static void ata_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
ata_pause(ap); ata_pause(ap);
} }
/**
* ata_exec_command - issue ATA command to host controller
* @ap: port to which command is being issued
* @tf: ATA taskfile register set
*
* Issues PIO/MMIO write to ATA command register, with proper
* synchronization with interrupt handler / other threads.
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
*/
void ata_exec_command(struct ata_port *ap, struct ata_taskfile *tf) void ata_exec_command(struct ata_port *ap, struct ata_taskfile *tf)
{ {
if (ap->flags & ATA_FLAG_MMIO) if (ap->flags & ATA_FLAG_MMIO)
@ -305,7 +339,7 @@ void ata_tf_to_host_nolock(struct ata_port *ap, struct ata_taskfile *tf)
} }
/** /**
* ata_tf_read - input device's ATA taskfile shadow registers * ata_tf_read_pio - input device's ATA taskfile shadow registers
* @ap: Port from which input is read * @ap: Port from which input is read
* @tf: ATA taskfile register set for storing input * @tf: ATA taskfile register set for storing input
* *
@ -368,6 +402,23 @@ static void ata_tf_read_mmio(struct ata_port *ap, struct ata_taskfile *tf)
} }
} }
/**
* ata_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.
*
* Reads nsect, lbal, lbam, lbah, and device. If ATA_TFLAG_LBA48
* is set, also reads the hob registers.
*
* May be used as the tf_read() entry in ata_port_operations.
*
* LOCKING:
* Inherited from caller.
*/
void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf) void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
{ {
if (ap->flags & ATA_FLAG_MMIO) if (ap->flags & ATA_FLAG_MMIO)
@ -381,7 +432,7 @@ void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
* @ap: port where the device is * @ap: port where the device is
* *
* Reads ATA taskfile status register for currently-selected device * Reads ATA taskfile status register for currently-selected device
* and return it's value. This also clears pending interrupts * and return its value. This also clears pending interrupts
* from this device * from this device
* *
* LOCKING: * LOCKING:
@ -397,7 +448,7 @@ static u8 ata_check_status_pio(struct ata_port *ap)
* @ap: port where the device is * @ap: port where the device is
* *
* Reads ATA taskfile status register for currently-selected device * Reads ATA taskfile status register for currently-selected device
* via MMIO and return it's value. This also clears pending interrupts * via MMIO and return its value. This also clears pending interrupts
* from this device * from this device
* *
* LOCKING: * LOCKING:
@ -408,6 +459,20 @@ static u8 ata_check_status_mmio(struct ata_port *ap)
return readb((void __iomem *) ap->ioaddr.status_addr); return readb((void __iomem *) ap->ioaddr.status_addr);
} }
/**
* ata_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
*
* May be used as the check_status() entry in ata_port_operations.
*
* LOCKING:
* Inherited from caller.
*/
u8 ata_check_status(struct ata_port *ap) u8 ata_check_status(struct ata_port *ap)
{ {
if (ap->flags & ATA_FLAG_MMIO) if (ap->flags & ATA_FLAG_MMIO)
@ -415,6 +480,20 @@ u8 ata_check_status(struct ata_port *ap)
return ata_check_status_pio(ap); return ata_check_status_pio(ap);
} }
/**
* ata_altstatus - Read device alternate status reg
* @ap: port where the device is
*
* Reads ATA taskfile alternate status register for
* currently-selected device and return its value.
*
* Note: may NOT be used as the check_altstatus() entry in
* ata_port_operations.
*
* LOCKING:
* Inherited from caller.
*/
u8 ata_altstatus(struct ata_port *ap) u8 ata_altstatus(struct ata_port *ap)
{ {
if (ap->ops->check_altstatus) if (ap->ops->check_altstatus)
@ -425,6 +504,20 @@ u8 ata_altstatus(struct ata_port *ap)
return inb(ap->ioaddr.altstatus_addr); return inb(ap->ioaddr.altstatus_addr);
} }
/**
* ata_chk_err - Read device error reg
* @ap: port where the device is
*
* Reads ATA taskfile error register for
* currently-selected device and return its value.
*
* Note: may NOT be used as the check_err() entry in
* ata_port_operations.
*
* LOCKING:
* Inherited from caller.
*/
u8 ata_chk_err(struct ata_port *ap) u8 ata_chk_err(struct ata_port *ap)
{ {
if (ap->ops->check_err) if (ap->ops->check_err)
@ -873,10 +966,24 @@ void ata_dev_id_string(u16 *id, unsigned char *s,
} }
} }
/**
* ata_noop_dev_select - Select device 0/1 on ATA bus
* @ap: ATA channel to manipulate
* @device: ATA device (numbered from zero) to select
*
* This function performs no actual function.
*
* May be used as the dev_select() entry in ata_port_operations.
*
* LOCKING:
* caller.
*/
void ata_noop_dev_select (struct ata_port *ap, unsigned int device) void ata_noop_dev_select (struct ata_port *ap, unsigned int device)
{ {
} }
/** /**
* ata_std_dev_select - Select device 0/1 on ATA bus * ata_std_dev_select - Select device 0/1 on ATA bus
* @ap: ATA channel to manipulate * @ap: ATA channel to manipulate
@ -884,7 +991,9 @@ void ata_noop_dev_select (struct ata_port *ap, unsigned int device)
* *
* Use the method defined in the ATA specification to * Use the method defined in the ATA specification to
* make either device 0, or device 1, active on the * make either device 0, or device 1, active on the
* ATA channel. * ATA channel. Works with both PIO and MMIO.
*
* May be used as the dev_select() entry in ata_port_operations.
* *
* LOCKING: * LOCKING:
* caller. * caller.
@ -1190,7 +1299,12 @@ err_out:
* ata_bus_probe - Reset and probe ATA bus * ata_bus_probe - Reset and probe ATA bus
* @ap: Bus to probe * @ap: Bus to probe
* *
* Master ATA bus probing function. Initiates a hardware-dependent
* bus reset, then attempts to identify any devices found on
* the bus.
*
* LOCKING: * LOCKING:
* PCI/etc. bus probe sem.
* *
* RETURNS: * RETURNS:
* Zero on success, non-zero on error. * Zero on success, non-zero on error.
@ -1229,10 +1343,14 @@ err_out:
} }
/** /**
* ata_port_probe - * ata_port_probe - Mark port as enabled
* @ap: * @ap: Port for which we indicate enablement
* *
* LOCKING: * Modify @ap data structure such that the system
* thinks that the entire port is enabled.
*
* LOCKING: host_set lock, or some other form of
* serialization.
*/ */
void ata_port_probe(struct ata_port *ap) void ata_port_probe(struct ata_port *ap)
@ -1241,10 +1359,15 @@ void ata_port_probe(struct ata_port *ap)
} }
/** /**
* __sata_phy_reset - * __sata_phy_reset - Wake/reset a low-level SATA PHY
* @ap: * @ap: SATA port associated with target SATA PHY.
*
* This function issues commands to standard SATA Sxxx
* PHY registers, to wake up the phy (and device), and
* clear any reset condition.
* *
* LOCKING: * LOCKING:
* PCI/etc. bus probe sem.
* *
*/ */
void __sata_phy_reset(struct ata_port *ap) void __sata_phy_reset(struct ata_port *ap)
@ -1289,10 +1412,14 @@ void __sata_phy_reset(struct ata_port *ap)
} }
/** /**
* __sata_phy_reset - * sata_phy_reset - Reset SATA bus.
* @ap: * @ap: SATA port associated with target SATA PHY.
*
* This function resets the SATA bus, and then probes
* the bus for devices.
* *
* LOCKING: * LOCKING:
* PCI/etc. bus probe sem.
* *
*/ */
void sata_phy_reset(struct ata_port *ap) void sata_phy_reset(struct ata_port *ap)
@ -1304,10 +1431,16 @@ void sata_phy_reset(struct ata_port *ap)
} }
/** /**
* ata_port_disable - * ata_port_disable - Disable port.
* @ap: * @ap: Port to be disabled.
* *
* LOCKING: * Modify @ap data structure such that the system
* thinks that the entire port is disabled, and should
* never attempt to probe or communicate with devices
* on this port.
*
* LOCKING: host_set lock, or some other form of
* serialization.
*/ */
void ata_port_disable(struct ata_port *ap) void ata_port_disable(struct ata_port *ap)
@ -1416,7 +1549,10 @@ static void ata_host_set_dma(struct ata_port *ap, u8 xfer_mode,
* ata_set_mode - Program timings and issue SET FEATURES - XFER * ata_set_mode - Program timings and issue SET FEATURES - XFER
* @ap: port on which timings will be programmed * @ap: port on which timings will be programmed
* *
* Set ATA device disk transfer mode (PIO3, UDMA6, etc.).
*
* LOCKING: * LOCKING:
* PCI/etc. bus probe sem.
* *
*/ */
static void ata_set_mode(struct ata_port *ap) static void ata_set_mode(struct ata_port *ap)
@ -1467,7 +1603,10 @@ err_out:
* @tmout_pat: impatience timeout * @tmout_pat: impatience timeout
* @tmout: overall timeout * @tmout: overall timeout
* *
* LOCKING: * Sleep until ATA Status register bit BSY clears,
* or a timeout occurs.
*
* LOCKING: None.
* *
*/ */
@ -1553,10 +1692,14 @@ static void ata_bus_post_reset(struct ata_port *ap, unsigned int devmask)
} }
/** /**
* ata_bus_edd - * ata_bus_edd - Issue EXECUTE DEVICE DIAGNOSTIC command.
* @ap: * @ap: Port to reset and probe
*
* Use the EXECUTE DEVICE DIAGNOSTIC command to reset and
* probe the bus. Not often used these days.
* *
* LOCKING: * LOCKING:
* PCI/etc. bus probe sem.
* *
*/ */
@ -1633,8 +1776,8 @@ static unsigned int ata_bus_softreset(struct ata_port *ap,
* the device is ATA or ATAPI. * the device is ATA or ATAPI.
* *
* LOCKING: * LOCKING:
* Inherited from caller. Some functions called by this function * PCI/etc. bus probe sem.
* obtain the host_set lock. * Obtains host_set lock.
* *
* SIDE EFFECTS: * SIDE EFFECTS:
* Sets ATA_FLAG_PORT_DISABLED if bus reset fails. * Sets ATA_FLAG_PORT_DISABLED if bus reset fails.
@ -1876,7 +2019,11 @@ static int fgb(u32 bitmap)
* @xfer_mode_out: (output) SET FEATURES - XFER MODE code * @xfer_mode_out: (output) SET FEATURES - XFER MODE code
* @xfer_shift_out: (output) bit shift that selects this mode * @xfer_shift_out: (output) bit shift that selects this mode
* *
* Based on host and device capabilities, determine the
* maximum transfer mode that is amenable to all.
*
* LOCKING: * LOCKING:
* PCI/etc. bus probe sem.
* *
* RETURNS: * RETURNS:
* Zero on success, negative on error. * Zero on success, negative on error.
@ -1909,7 +2056,11 @@ static int ata_choose_xfer_mode(struct ata_port *ap,
* @ap: Port associated with device @dev * @ap: Port associated with device @dev
* @dev: Device to which command will be sent * @dev: Device to which command will be sent
* *
* Issue SET FEATURES - XFER MODE command to device @dev
* on port @ap.
*
* LOCKING: * LOCKING:
* PCI/etc. bus probe sem.
*/ */
static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev) static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev)
@ -1947,10 +2098,13 @@ static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev)
} }
/** /**
* ata_sg_clean - * ata_sg_clean - Unmap DMA memory associated with command
* @qc: * @qc: Command containing DMA memory to be released
*
* Unmap all mapped DMA memory associated with this command.
* *
* LOCKING: * LOCKING:
* spin_lock_irqsave(host_set lock)
*/ */
static void ata_sg_clean(struct ata_queued_cmd *qc) static void ata_sg_clean(struct ata_queued_cmd *qc)
@ -1981,7 +2135,11 @@ static void ata_sg_clean(struct ata_queued_cmd *qc)
* ata_fill_sg - Fill PCI IDE PRD table * ata_fill_sg - Fill PCI IDE PRD table
* @qc: Metadata associated with taskfile to be transferred * @qc: Metadata associated with taskfile to be transferred
* *
* Fill PCI IDE PRD (scatter-gather) table with segments
* associated with the current disk command.
*
* LOCKING: * LOCKING:
* spin_lock_irqsave(host_set lock)
* *
*/ */
static void ata_fill_sg(struct ata_queued_cmd *qc) static void ata_fill_sg(struct ata_queued_cmd *qc)
@ -2028,7 +2186,13 @@ static void ata_fill_sg(struct ata_queued_cmd *qc)
* ata_check_atapi_dma - Check whether ATAPI DMA can be supported * ata_check_atapi_dma - Check whether ATAPI DMA can be supported
* @qc: Metadata associated with taskfile to check * @qc: Metadata associated with taskfile to check
* *
* Allow low-level driver to filter ATA PACKET commands, returning
* a status indicating whether or not it is OK to use DMA for the
* supplied PACKET command.
*
* LOCKING: * LOCKING:
* spin_lock_irqsave(host_set lock)
*
* RETURNS: 0 when ATAPI DMA can be used * RETURNS: 0 when ATAPI DMA can be used
* nonzero otherwise * nonzero otherwise
*/ */
@ -2046,6 +2210,8 @@ int ata_check_atapi_dma(struct ata_queued_cmd *qc)
* ata_qc_prep - Prepare taskfile for submission * ata_qc_prep - Prepare taskfile for submission
* @qc: Metadata associated with taskfile to be prepared * @qc: Metadata associated with taskfile to be prepared
* *
* Prepare ATA taskfile for submission.
*
* LOCKING: * LOCKING:
* spin_lock_irqsave(host_set lock) * spin_lock_irqsave(host_set lock)
*/ */
@ -2057,6 +2223,32 @@ void ata_qc_prep(struct ata_queued_cmd *qc)
ata_fill_sg(qc); ata_fill_sg(qc);
} }
/**
* ata_sg_init_one - Associate command with memory buffer
* @qc: Command to be associated
* @buf: Memory buffer
* @buflen: Length of memory buffer, in bytes.
*
* Initialize the data-related elements of queued_cmd @qc
* to point to a single memory buffer, @buf of byte length @buflen.
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
*/
/**
* ata_sg_init_one - Prepare a one-entry scatter-gather list.
* @qc: Queued command
* @buf: transfer buffer
* @buflen: length of buf
*
* Builds a single-entry scatter-gather list to initiate a
* transfer utilizing the specified buffer.
*
* LOCKING:
*/
void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen) void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen)
{ {
struct scatterlist *sg; struct scatterlist *sg;
@ -2074,6 +2266,32 @@ void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen)
sg->length = buflen; sg->length = buflen;
} }
/**
* ata_sg_init - Associate command with scatter-gather table.
* @qc: Command to be associated
* @sg: Scatter-gather table.
* @n_elem: Number of elements in s/g table.
*
* Initialize the data-related elements of queued_cmd @qc
* to point to a scatter-gather table @sg, containing @n_elem
* elements.
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
*/
/**
* ata_sg_init - Assign a scatter gather list to a queued command
* @qc: Queued command
* @sg: Scatter-gather list
* @n_elem: length of sg list
*
* Attaches a scatter-gather list to a queued command.
*
* LOCKING:
*/
void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg, void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg,
unsigned int n_elem) unsigned int n_elem)
{ {
@ -2083,14 +2301,16 @@ void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg,
} }
/** /**
* ata_sg_setup_one - * ata_sg_setup_one - DMA-map the memory buffer associated with a command.
* @qc: * @qc: Command with memory buffer to be mapped.
*
* DMA-map the memory buffer associated with queued_cmd @qc.
* *
* LOCKING: * LOCKING:
* spin_lock_irqsave(host_set lock) * spin_lock_irqsave(host_set lock)
* *
* RETURNS: * RETURNS:
* * Zero on success, negative on error.
*/ */
static int ata_sg_setup_one(struct ata_queued_cmd *qc) static int ata_sg_setup_one(struct ata_queued_cmd *qc)
@ -2115,13 +2335,16 @@ static int ata_sg_setup_one(struct ata_queued_cmd *qc)
} }
/** /**
* ata_sg_setup - * ata_sg_setup - DMA-map the scatter-gather table associated with a command.
* @qc: * @qc: Command with scatter-gather table to be mapped.
*
* DMA-map the scatter-gather table associated with queued_cmd @qc.
* *
* LOCKING: * LOCKING:
* spin_lock_irqsave(host_set lock) * spin_lock_irqsave(host_set lock)
* *
* RETURNS: * RETURNS:
* Zero on success, negative on error.
* *
*/ */
@ -2151,6 +2374,7 @@ static int ata_sg_setup(struct ata_queued_cmd *qc)
* @ap: * @ap:
* *
* LOCKING: * LOCKING:
* None. (executing in kernel thread context)
* *
* RETURNS: * RETURNS:
* *
@ -2198,6 +2422,7 @@ static unsigned long ata_pio_poll(struct ata_port *ap)
* @ap: * @ap:
* *
* LOCKING: * LOCKING:
* None. (executing in kernel thread context)
*/ */
static void ata_pio_complete (struct ata_port *ap) static void ata_pio_complete (struct ata_port *ap)
@ -2240,6 +2465,18 @@ static void ata_pio_complete (struct ata_port *ap)
ata_qc_complete(qc, drv_stat); ata_qc_complete(qc, drv_stat);
} }
/**
* swap_buf_le16 -
* @buf: Buffer to swap
* @buf_words: Number of 16-bit words in buffer.
*
* Swap halves of 16-bit words if needed to convert from
* little-endian byte order to native cpu byte order, or
* vice-versa.
*
* LOCKING:
*/
void swap_buf_le16(u16 *buf, unsigned int buf_words) void swap_buf_le16(u16 *buf, unsigned int buf_words)
{ {
#ifdef __BIG_ENDIAN #ifdef __BIG_ENDIAN
@ -2415,6 +2652,7 @@ err_out:
* @ap: * @ap:
* *
* LOCKING: * LOCKING:
* None. (executing in kernel thread context)
*/ */
static void ata_pio_block(struct ata_port *ap) static void ata_pio_block(struct ata_port *ap)
@ -2583,6 +2821,7 @@ static void atapi_request_sense(struct ata_port *ap, struct ata_device *dev,
* transaction completed successfully. * transaction completed successfully.
* *
* LOCKING: * LOCKING:
* Inherited from SCSI layer (none, can sleep)
*/ */
static void ata_qc_timeout(struct ata_queued_cmd *qc) static void ata_qc_timeout(struct ata_queued_cmd *qc)
@ -2692,6 +2931,7 @@ out:
* @dev: Device from whom we request an available command structure * @dev: Device from whom we request an available command structure
* *
* LOCKING: * LOCKING:
* None.
*/ */
static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap) static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap)
@ -2717,6 +2957,7 @@ static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap)
* @dev: Device from whom we request an available command structure * @dev: Device from whom we request an available command structure
* *
* LOCKING: * LOCKING:
* None.
*/ */
struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
@ -2781,6 +3022,7 @@ static void __ata_qc_complete(struct ata_queued_cmd *qc)
* in case something prevents using it. * in case something prevents using it.
* *
* LOCKING: * LOCKING:
* spin_lock_irqsave(host_set lock)
* *
*/ */
void ata_qc_free(struct ata_queued_cmd *qc) void ata_qc_free(struct ata_queued_cmd *qc)
@ -2794,9 +3036,13 @@ void ata_qc_free(struct ata_queued_cmd *qc)
/** /**
* ata_qc_complete - Complete an active ATA command * ata_qc_complete - Complete an active ATA command
* @qc: Command to complete * @qc: Command to complete
* @drv_stat: ATA status register contents * @drv_stat: ATA Status register contents
*
* Indicate to the mid and upper layers that an ATA
* command has completed, with either an ok or not-ok status.
* *
* LOCKING: * LOCKING:
* spin_lock_irqsave(host_set lock)
* *
*/ */
@ -2892,6 +3138,7 @@ err_out:
return -1; return -1;
} }
/** /**
* ata_qc_issue_prot - issue taskfile to device in proto-dependent manner * ata_qc_issue_prot - issue taskfile to device in proto-dependent manner
* @qc: command to issue to device * @qc: command to issue to device
@ -2901,6 +3148,8 @@ err_out:
* classes called "protocols", and issuing each type of protocol * classes called "protocols", and issuing each type of protocol
* is slightly different. * is slightly different.
* *
* May be used as the qc_issue() entry in ata_port_operations.
*
* LOCKING: * LOCKING:
* spin_lock_irqsave(host_set lock) * spin_lock_irqsave(host_set lock)
* *
@ -2958,7 +3207,7 @@ int ata_qc_issue_prot(struct ata_queued_cmd *qc)
} }
/** /**
* ata_bmdma_setup - Set up PCI IDE BMDMA transaction * ata_bmdma_setup_mmio - Set up PCI IDE BMDMA transaction
* @qc: Info associated with this ATA transaction. * @qc: Info associated with this ATA transaction.
* *
* LOCKING: * LOCKING:
@ -3065,6 +3314,18 @@ static void ata_bmdma_start_pio (struct ata_queued_cmd *qc)
ap->ioaddr.bmdma_addr + ATA_DMA_CMD); 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) void ata_bmdma_start(struct ata_queued_cmd *qc)
{ {
if (qc->ap->flags & ATA_FLAG_MMIO) if (qc->ap->flags & ATA_FLAG_MMIO)
@ -3073,6 +3334,20 @@ void ata_bmdma_start(struct ata_queued_cmd *qc)
ata_bmdma_start_pio(qc); 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) void ata_bmdma_setup(struct ata_queued_cmd *qc)
{ {
if (qc->ap->flags & ATA_FLAG_MMIO) if (qc->ap->flags & ATA_FLAG_MMIO)
@ -3081,6 +3356,19 @@ void ata_bmdma_setup(struct ata_queued_cmd *qc)
ata_bmdma_setup_pio(qc); 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) void ata_bmdma_irq_clear(struct ata_port *ap)
{ {
if (ap->flags & ATA_FLAG_MMIO) { if (ap->flags & ATA_FLAG_MMIO) {
@ -3093,6 +3381,19 @@ void ata_bmdma_irq_clear(struct ata_port *ap)
} }
/**
* 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 ata_bmdma_status(struct ata_port *ap)
{ {
u8 host_stat; u8 host_stat;
@ -3104,6 +3405,19 @@ u8 ata_bmdma_status(struct ata_port *ap)
return host_stat; return host_stat;
} }
/**
* ata_bmdma_stop - Stop PCI IDE BMDMA transfer
* @ap: Port associated with this ATA transaction.
*
* 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_port *ap) void ata_bmdma_stop(struct ata_port *ap)
{ {
if (ap->flags & ATA_FLAG_MMIO) { if (ap->flags & ATA_FLAG_MMIO) {
@ -3203,13 +3517,18 @@ idle_irq:
/** /**
* ata_interrupt - Default ATA host interrupt handler * ata_interrupt - Default ATA host interrupt handler
* @irq: irq line * @irq: irq line (unused)
* @dev_instance: pointer to our host information structure * @dev_instance: pointer to our ata_host_set information structure
* @regs: unused * @regs: unused
* *
* Default interrupt handler for PCI IDE devices. Calls
* ata_host_intr() for each port that is not disabled.
*
* LOCKING: * LOCKING:
* Obtains host_set lock during operation.
* *
* RETURNS: * RETURNS:
* IRQ_NONE or IRQ_HANDLED.
* *
*/ */
@ -3302,6 +3621,19 @@ err_out:
ata_qc_complete(qc, ATA_ERR); ata_qc_complete(qc, ATA_ERR);
} }
/**
* ata_port_start - Set port up for dma.
* @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:
*/
int ata_port_start (struct ata_port *ap) int ata_port_start (struct ata_port *ap)
{ {
struct device *dev = ap->host_set->dev; struct device *dev = ap->host_set->dev;
@ -3315,6 +3647,18 @@ int ata_port_start (struct ata_port *ap)
return 0; return 0;
} }
/**
* ata_port_stop - Undo ata_port_start()
* @ap: Port to shut down
*
* Frees the PRD table.
*
* May be used as the port_stop() entry in ata_port_operations.
*
* LOCKING:
*/
void ata_port_stop (struct ata_port *ap) void ata_port_stop (struct ata_port *ap)
{ {
struct device *dev = ap->host_set->dev; struct device *dev = ap->host_set->dev;
@ -3357,7 +3701,11 @@ static void ata_host_remove(struct ata_port *ap, unsigned int do_unregister)
* @ent: Probe information provided by low-level driver * @ent: Probe information provided by low-level driver
* @port_no: Port number associated with this ata_port * @port_no: Port number associated with this ata_port
* *
* Initialize a new ata_port structure, and its associated
* scsi_host.
*
* LOCKING: * LOCKING:
* Inherited from caller.
* *
*/ */
@ -3412,9 +3760,13 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host,
* @host_set: Collections of ports to which we add * @host_set: Collections of ports to which we add
* @port_no: Port number associated with this host * @port_no: Port number associated with this host
* *
* Attach low-level ATA driver to system.
*
* LOCKING: * LOCKING:
* PCI/etc. bus probe sem.
* *
* RETURNS: * RETURNS:
* New ata_port on success, for NULL on error.
* *
*/ */
@ -3447,12 +3799,22 @@ err_out:
} }
/** /**
* ata_device_add - * ata_device_add - Register hardware device with ATA and SCSI layers
* @ent: * @ent: Probe information describing hardware device to be registered
*
* This function processes the information provided in the probe
* information struct @ent, allocates the necessary ATA and SCSI
* host information structures, initializes them, and registers
* everything with requisite kernel subsystems.
*
* This function requests irqs, probes the ATA bus, and probes
* the SCSI bus.
* *
* LOCKING: * LOCKING:
* PCI/etc. bus probe sem.
* *
* RETURNS: * RETURNS:
* Number of ports registered. Zero on error (no ports registered).
* *
*/ */
@ -3604,7 +3966,15 @@ int ata_scsi_release(struct Scsi_Host *host)
/** /**
* ata_std_ports - initialize ioaddr with standard port offsets. * ata_std_ports - initialize ioaddr with standard port offsets.
* @ioaddr: IO address structure to be initialized * @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_std_ports(struct ata_ioports *ioaddr) void ata_std_ports(struct ata_ioports *ioaddr)
{ {
ioaddr->data_addr = ioaddr->cmd_addr + ATA_REG_DATA; ioaddr->data_addr = ioaddr->cmd_addr + ATA_REG_DATA;
@ -3646,6 +4016,20 @@ ata_probe_ent_alloc(struct device *dev, struct ata_port_info *port)
return probe_ent; return probe_ent;
} }
/**
* ata_pci_init_native_mode - Initialize native-mode driver
* @pdev: pci device to be initialized
* @port: array[2] of pointers to port info structures.
*
* Utility function which allocates and initializes an
* ata_probe_ent structure for a standard dual-port
* PIO-based IDE controller. The returned ata_probe_ent
* structure can be passed to ata_device_add(). The returned
* ata_probe_ent structure should then be freed with kfree().
*/
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
struct ata_probe_ent * struct ata_probe_ent *
ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port) ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port)
@ -3727,10 +4111,19 @@ ata_pci_init_legacy_mode(struct pci_dev *pdev, struct ata_port_info **port,
* @port_info: Information from low-level host driver * @port_info: Information from low-level host driver
* @n_ports: Number of ports attached to host controller * @n_ports: Number of ports attached to host controller
* *
* 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.
*
* This function calls pci_enable_device(), reserves its register
* regions, sets the dma mask, enables bus master mode, and calls
* ata_device_add()
*
* LOCKING: * LOCKING:
* Inherited from PCI layer (may sleep). * Inherited from PCI layer (may sleep).
* *
* RETURNS: * RETURNS:
* Zero on success, negative on errno-based value on error.
* *
*/ */
@ -3949,15 +4342,6 @@ int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits)
#endif /* CONFIG_PCI */ #endif /* CONFIG_PCI */
/**
* ata_init -
*
* LOCKING:
*
* RETURNS:
*
*/
static int __init ata_init(void) static int __init ata_init(void)
{ {
ata_wq = create_workqueue("ata"); ata_wq = create_workqueue("ata");

View File

@ -947,7 +947,7 @@ unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf,
} }
/** /**
* ata_scsiop_noop - * ata_scsiop_noop - Command handler that simply returns success.
* @args: device IDENTIFY data / SCSI command of interest. * @args: device IDENTIFY data / SCSI command of interest.
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent. * @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
* @buflen: Response buffer length. * @buflen: Response buffer length.

View File

@ -467,12 +467,34 @@ static inline u8 ata_chk_status(struct ata_port *ap)
return ap->ops->check_status(ap); return ap->ops->check_status(ap);
} }
/**
* ata_pause - Flush writes and pause 400 nanoseconds.
* @ap: Port to wait for.
*
* LOCKING:
* Inherited from caller.
*/
static inline void ata_pause(struct ata_port *ap) static inline void ata_pause(struct ata_port *ap)
{ {
ata_altstatus(ap); ata_altstatus(ap);
ndelay(400); ndelay(400);
} }
/**
* ata_busy_wait - Wait for a port status register
* @ap: Port to wait for.
*
* Waits up to max*10 microseconds for the selected bits in the port's
* status register to be cleared.
* Returns final value of status register.
*
* LOCKING:
* Inherited from caller.
*/
static inline u8 ata_busy_wait(struct ata_port *ap, unsigned int bits, static inline u8 ata_busy_wait(struct ata_port *ap, unsigned int bits,
unsigned int max) unsigned int max)
{ {
@ -487,6 +509,18 @@ static inline u8 ata_busy_wait(struct ata_port *ap, unsigned int bits,
return status; return status;
} }
/**
* ata_wait_idle - Wait for a port to be idle.
* @ap: Port to wait for.
*
* Waits up to 10ms for port's BUSY and DRQ signals to clear.
* Returns final value of status register.
*
* LOCKING:
* Inherited from caller.
*/
static inline u8 ata_wait_idle(struct ata_port *ap) static inline u8 ata_wait_idle(struct ata_port *ap)
{ {
u8 status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); u8 status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
@ -525,6 +559,18 @@ static inline void ata_tf_init(struct ata_port *ap, struct ata_taskfile *tf, uns
tf->device = ATA_DEVICE_OBS | ATA_DEV1; tf->device = ATA_DEVICE_OBS | ATA_DEV1;
} }
/**
* ata_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.
*
* LOCKING:
* Inherited from caller.
*/
static inline u8 ata_irq_on(struct ata_port *ap) static inline u8 ata_irq_on(struct ata_port *ap)
{ {
struct ata_ioports *ioaddr = &ap->ioaddr; struct ata_ioports *ioaddr = &ap->ioaddr;
@ -544,6 +590,18 @@ static inline u8 ata_irq_on(struct ata_port *ap)
return tmp; return tmp;
} }
/**
* ata_irq_ack - Acknowledge a device interrupt.
* @ap: Port on which interrupts are enabled.
*
* Wait up to 10 ms for legacy IDE device to become idle (BUSY
* or BUSY+DRQ clear). Obtain dma status and port status from
* device. Clear the interrupt. Return port status.
*
* LOCKING:
*/
static inline u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq) static inline u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq)
{ {
unsigned int bits = chk_drq ? ATA_BUSY | ATA_DRQ : ATA_BUSY; unsigned int bits = chk_drq ? ATA_BUSY | ATA_DRQ : ATA_BUSY;