Copyright © 2003-2006 Jeff Garzik
The contents of this file are subject to the Open Software License version 1.1 that can be found at http://fedoraproject.org/wiki/Licensing:OSL1.1 and is included herein by reference.
Alternatively, the contents of this file may be used under the terms of the GNU General Public License version 2 (the "GPL") as distributed in the kernel source COPYING file, in which case the provisions of the GPL are applicable instead of the above. If you wish to allow the use of your version of this file only under the terms of the GPL and not to allow others to use your version of this file under the OSL, indicate your decision by deleting the provisions above and replace them with the notice and other provisions required by the GPL. If you do not delete the provisions above, a recipient may use your version of this file under either the OSL or the GPL.
Table of Contents
ata_sas_port_start
scsi_rescan_device
libATA is a library used inside the Linux kernel to support ATA host controllers and devices. libATA provides an ATA driver API, class transports for ATA and ATAPI devices, and SCSI<->ATA translation for ATA devices according to the T10 SAT specification.
This Guide documents the libATA driver API, library functions, library internals, and a couple sample ATA low-level drivers.
Table of Contents
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.
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.
void (*port_disable) (struct ata_port *);
Called from ata_bus_probe() error path, as well as when unregistering from the SCSI module (rmmod, hot unplug). This function should do whatever needs to be done to take the port out of use. In most cases, ata_port_disable() can be used as this hook.
Called from ata_bus_probe() on a failed probe. Called from ata_scsi_release().
void (*dev_config) (struct ata_port *, struct ata_device *);
Called after IDENTIFY [PACKET] DEVICE is issued to each device found. Typically used to apply device-specific fixups prior to issue of SET FEATURES - XFER MODE, and prior to operation.
This entry may be specified as NULL in ata_port_operations.
void (*set_piomode) (struct ata_port *, struct ata_device *); void (*set_dmamode) (struct ata_port *, struct ata_device *); void (*post_set_mode) (struct ata_port *); unsigned int (*mode_filter) (struct ata_port *, struct ata_device *, unsigned int);
Hooks called prior to the issue of SET FEATURES - XFER MODE command. The optional ->mode_filter() hook is called when libata has built a mask of the possible modes. This is passed to the ->mode_filter() function which should return a mask of valid modes after filtering those unsuitable due to hardware limits. It is not valid to use this interface to add modes.
dev->pio_mode and dev->dma_mode are guaranteed to be valid when ->set_piomode() and when ->set_dmamode() is called. The timings for any other drive sharing the cable will also be valid at this point. That is the library records the decisions for the modes of each drive on a channel before it attempts to set any of them.
->post_set_mode() is called unconditionally, after the SET FEATURES - XFER MODE command completes successfully.
->set_piomode() is always called (if present), but ->set_dma_mode() is only called if DMA is possible.
void (*sff_tf_load) (struct ata_port *ap, struct ata_taskfile *tf); void (*sff_tf_read) (struct ata_port *ap, struct ata_taskfile *tf);
->tf_load() is called to load the given taskfile into hardware registers / DMA buffers. ->tf_read() is called to read the hardware registers / DMA buffers, to obtain the current set of taskfile register values. Most drivers for taskfile-based hardware (PIO or MMIO) use ata_sff_tf_load() and ata_sff_tf_read() for these hooks.
void (*sff_data_xfer) (struct ata_device *, unsigned char *, unsigned int, int);
All bmdma-style drivers must implement this hook. This is the low-level operation that actually copies the data bytes during a PIO data transfer. Typically the driver will choose one of ata_sff_data_xfer_noirq(), ata_sff_data_xfer(), or ata_sff_data_xfer32().
void (*sff_exec_command)(struct ata_port *ap, struct ata_taskfile *tf);
causes an ATA command, previously loaded with ->tf_load(), to be initiated in hardware. Most drivers for taskfile-based hardware use ata_sff_exec_command() for this hook.
int (*check_atapi_dma) (struct ata_queued_cmd *qc);
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.
This hook may be specified as NULL, in which case libata will assume that atapi dma can be supported.
u8 (*sff_check_status)(struct ata_port *ap); u8 (*sff_check_altstatus)(struct ata_port *ap);
Reads the Status/AltStatus ATA shadow register from hardware. On some hardware, reading the Status register has the side effect of clearing the interrupt condition. Most drivers for taskfile-based hardware use ata_sff_check_status() for this hook.
void (*sff_set_devctl)(struct ata_port *ap, u8 ctl);
Write the device control ATA shadow register to the hardware. Most drivers don't need to define this.
void (*sff_dev_select)(struct ata_port *ap, unsigned int device);
Issues the low-level hardware command(s) that causes one of N hardware devices to be considered 'selected' (active and available for use) on the ATA bus. This generally has no meaning on FIS-based devices.
Most drivers for taskfile-based hardware use ata_sff_dev_select() for this hook.
void (*set_mode) (struct ata_port *ap);
By default libata performs drive and controller tuning in accordance with the ATA timing rules and also applies blacklists and cable limits. Some controllers need special handling and have custom tuning rules, typically raid controllers that use ATA commands but do not actually do drive timing.
This hook should not be used to replace the standard controller tuning logic when a controller has quirks. Replacing the default tuning logic in that case would bypass handling for drive and bridge quirks that may be important to data reliability. If a controller needs to filter the mode selection it should use the mode_filter hook instead.
void (*bmdma_setup) (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);
When setting up an IDE BMDMA transaction, these hooks arm (->bmdma_setup), fire (->bmdma_start), and halt (->bmdma_stop) the hardware's DMA engine. ->bmdma_status is used to read the standard PCI IDE DMA Status register.
These hooks are typically either no-ops, or simply not implemented, in FIS-based drivers.
Most legacy IDE drivers use ata_bmdma_setup() for the bmdma_setup() hook. ata_bmdma_setup() will write the pointer to the PRD table to the IDE PRD Table Address register, enable DMA in the DMA Command register, and call exec_command() to begin the transfer.
Most legacy IDE drivers use ata_bmdma_start() for the bmdma_start() hook. ata_bmdma_start() will write the ATA_DMA_START flag to the DMA Command register.
Many legacy IDE drivers use ata_bmdma_stop() for the bmdma_stop() hook. ata_bmdma_stop() clears the ATA_DMA_START flag in the DMA command register.
Many legacy IDE drivers use ata_bmdma_status() as the bmdma_status() hook.
void (*qc_prep) (struct ata_queued_cmd *qc); int (*qc_issue) (struct ata_queued_cmd *qc);
Higher-level hooks, these two hooks can potentially supercede several of the above taskfile/DMA engine hooks. ->qc_prep is called after the buffers have been DMA-mapped, and is typically used to populate the hardware's DMA scatter-gather table. Most drivers use the standard ata_qc_prep() helper function, but more advanced drivers roll their own.
->qc_issue is used to make a command active, once the hardware and S/G tables have been prepared. IDE BMDMA drivers use the helper function ata_qc_issue_prot() for taskfile protocol-based dispatch. More advanced drivers implement their own ->qc_issue.
ata_qc_issue_prot() calls ->tf_load(), ->bmdma_setup(), and ->bmdma_start() as necessary to initiate a transfer.
void (*eng_timeout) (struct ata_port *ap); void (*phy_reset) (struct ata_port *ap);
Deprecated. Use ->error_handler() instead.
void (*freeze) (struct ata_port *ap); void (*thaw) (struct ata_port *ap);
ata_port_freeze() is called when HSM violations or some other condition disrupts normal operation of the port. A frozen port is not allowed to perform any operation until the port is thawed, which usually follows a successful reset.
The optional ->freeze() callback can be used for freezing the port hardware-wise (e.g. mask interrupt and stop DMA engine). If a port cannot be frozen hardware-wise, the interrupt handler must ack and clear interrupts unconditionally while the port is frozen.
The optional ->thaw() callback is called to perform the opposite of ->freeze(): prepare the port for normal operation once again. Unmask interrupts, start DMA engine, etc.
void (*error_handler) (struct ata_port *ap);
->error_handler() is a driver's hook into probe, hotplug, and recovery and other exceptional conditions. The primary responsibility of an implementation is to call ata_do_eh() or ata_bmdma_drive_eh() with a set of EH hooks as arguments:
'prereset' hook (may be NULL) is called during an EH reset, before any other actions are taken.
'postreset' hook (may be NULL) is called after the EH reset is performed. Based on existing conditions, severity of the problem, and hardware capabilities,
Either 'softreset' (may be NULL) or 'hardreset' (may be NULL) will be called to perform the low-level EH reset.
void (*post_internal_cmd) (struct ata_queued_cmd *qc);
Perform any hardware-specific actions necessary to finish processing after executing a probe-time or EH-time command via ata_exec_internal().
irqreturn_t (*irq_handler)(int, void *, struct pt_regs *); void (*irq_clear) (struct ata_port *);
->irq_handler is the interrupt handling routine registered with the system, by libata. ->irq_clear is called during probe just before the interrupt handler is registered, to be sure hardware is quiet.
The second argument, dev_instance, should be cast to a pointer to struct ata_host_set.
Most legacy IDE drivers use ata_sff_interrupt() for the irq_handler hook, which scans all ports in the host_set, determines which queued command was active (if any), and calls ata_sff_host_intr(ap,qc).
Most legacy IDE drivers use ata_sff_irq_clear() for the irq_clear() hook, which simply clears the interrupt and error flags in the DMA status register.
int (*scr_read) (struct ata_port *ap, unsigned int sc_reg, u32 *val); int (*scr_write) (struct ata_port *ap, unsigned int sc_reg, u32 val);
Read and write standard SATA phy registers. Currently only used if ->phy_reset hook called the sata_phy_reset() helper function. sc_reg is one of SCR_STATUS, SCR_CONTROL, SCR_ERROR, or SCR_ACTIVE.
int (*port_start) (struct ata_port *ap); void (*port_stop) (struct ata_port *ap); void (*host_stop) (struct ata_host_set *host_set);
->port_start() is called just after the data structures for each port are initialized. Typically this is used to alloc per-port DMA buffers / tables / rings, enable DMA engines, and similar tasks. Some drivers also use this entry point as a chance to allocate driver-private memory for ap->private_data.
Many drivers use ata_port_start() as this hook or call it from their own port_start() hooks. ata_port_start() allocates space for a legacy IDE PRD table and returns.
->port_stop() is called after ->host_stop(). Its sole function is to release DMA/memory resources, now that they are no longer actively being used. Many drivers also free driver-private data from port at this time.
->host_stop() is called after all ->port_stop() calls have completed. The hook must finalize hardware shutdown, release DMA and other resources, etc. This hook may be specified as NULL, in which case it is not called.
Table of Contents
This chapter describes how errors are handled under libata. Readers are advised to read SCSI EH (Documentation/scsi/scsi_eh.txt) and ATA exceptions doc first.
In libata, a command is represented with struct ata_queued_cmd or qc. qc's are preallocated during port initialization and repetitively used for command executions. Currently only one qc is allocated per port but yet-to-be-merged NCQ branch allocates one for each tag and maps each qc to NCQ tag 1-to-1.
libata commands can originate from two sources - libata itself and SCSI midlayer. libata internal commands are used for initialization and error handling. All normal blk requests and commands for SCSI emulation are passed as SCSI commands through queuecommand callback of SCSI host template.
First, qc is allocated and initialized using ata_qc_new_init(). Although ata_qc_new_init() doesn't implement any wait or retry mechanism when qc is not available, internal commands are currently issued only during initialization and error recovery, so no other command is active and allocation is guaranteed to succeed.
Once allocated qc's taskfile is initialized for the command to be executed. qc currently has two mechanisms to notify completion. One is via qc->complete_fn() callback and the other is completion qc->waiting. qc->complete_fn() callback is the asynchronous path used by normal SCSI translated commands and qc->waiting is the synchronous (issuer sleeps in process context) path used by internal commands.
Once initialization is complete, host_set lock is acquired and the qc is issued.
All libata drivers use ata_scsi_queuecmd() as hostt->queuecommand callback. scmds can either be simulated or translated. No qc is involved in processing a simulated scmd. The result is computed right away and the scmd is completed.
For a translated scmd, ata_qc_new_init() is invoked to allocate a qc and the scmd is translated into the qc. SCSI midlayer's completion notification function pointer is stored into qc->scsidone.
qc->complete_fn() callback is used for completion notification. ATA commands use ata_scsi_qc_complete() while ATAPI commands use atapi_qc_complete(). Both functions end up calling qc->scsidone to notify upper layer when the qc is finished. After translation is completed, the qc is issued with ata_qc_issue().
Note that SCSI midlayer invokes hostt->queuecommand while holding host_set lock, so all above occur while holding host_set lock.
Depending on which protocol and which controller are used, commands are processed differently. For the purpose of discussion, a controller which uses taskfile interface and all standard callbacks is assumed.
Currently 6 ATA command protocols are used. They can be sorted into the following four categories according to how they are processed.
ATA_PROT_NODATA and ATA_PROT_DMA fall into this category. These types of commands don't require any software intervention once issued. Device will raise interrupt on completion.
ATA_PROT_PIO is in this category. libata currently implements PIO with polling. ATA_NIEN bit is set to turn off interrupt and pio_task on ata_wq performs polling and IO.
ATA_PROT_ATAPI_NODATA and ATA_PROT_ATAPI_DMA are in this category. packet_task is used to poll BSY bit after issuing PACKET command. Once BSY is turned off by the device, packet_task transfers CDB and hands off processing to interrupt handler.
ATA_PROT_ATAPI is in this category. ATA_NIEN bit is set and, as in ATAPI NODATA or DMA, packet_task submits cdb. However, after submitting cdb, further processing (data transfer) is handed off to pio_task.
Once issued, all qc's are either completed with ata_qc_complete() or time out. For commands which are handled by interrupts, ata_host_intr() invokes ata_qc_complete(), and, for PIO tasks, pio_task invokes ata_qc_complete(). In error cases, packet_task may also complete commands.
ata_qc_complete() does the following.
DMA memory is unmapped.
ATA_QCFLAG_ACTIVE is clared from qc->flags.
qc->complete_fn() callback is invoked. If the return value of the callback is not zero. Completion is short circuited and ata_qc_complete() returns.
__ata_qc_complete() is called, which does
qc->flags is cleared to zero.
ap->active_tag and qc->tag are poisoned.
qc->waiting is claread & completed (in that order).
qc is deallocated by clearing appropriate bit in ap->qactive.
So, it basically notifies upper layer and deallocates qc. One exception is short-circuit path in #3 which is used by atapi_qc_complete().
For all non-ATAPI commands, whether it fails or not, almost the same code path is taken and very little error handling takes place. A qc is completed with success status if it succeeded, with failed status otherwise.
However, failed ATAPI commands require more handling as REQUEST SENSE is needed to acquire sense data. If an ATAPI command fails, ata_qc_complete() is invoked with error status, which in turn invokes atapi_qc_complete() via qc->complete_fn() callback.
This makes atapi_qc_complete() set scmd->result to SAM_STAT_CHECK_CONDITION, complete the scmd and return 1. As the sense data is empty but scmd->result is CHECK CONDITION, SCSI midlayer will invoke EH for the scmd, and returning 1 makes ata_qc_complete() to return without deallocating the qc. This leads us to ata_scsi_error() with partially completed qc.
ata_scsi_error() is the current transportt->eh_strategy_handler() for libata. As discussed above, this will be entered in two cases - timeout and ATAPI error completion. This function calls low level libata driver's eng_timeout() callback, the standard callback for which is ata_eng_timeout(). It checks if a qc is active and calls ata_qc_timeout() on the qc if so. Actual error handling occurs in ata_qc_timeout().
If EH is invoked for timeout, ata_qc_timeout() stops BMDMA and completes the qc. Note that as we're currently in EH, we cannot call scsi_done. As described in SCSI EH doc, a recovered scmd should be either retried with scsi_queue_insert() or finished with scsi_finish_command(). Here, we override qc->scsidone with scsi_finish_command() and calls ata_qc_complete().
If EH is invoked due to a failed ATAPI qc, the qc here is completed but not deallocated. The purpose of this half-completion is to use the qc as place holder to make EH code reach this place. This is a bit hackish, but it works.
Once control reaches here, the qc is deallocated by invoking __ata_qc_complete() explicitly. Then, internal qc for REQUEST SENSE is issued. Once sense data is acquired, scmd is finished by directly invoking scsi_finish_command() on the scmd. Note that as we already have completed and deallocated the qc which was associated with the scmd, we don't need to/cannot call ata_qc_complete() again.
Error representation is too crude. Currently any and all error conditions are represented with ATA STATUS and ERROR registers. Errors which aren't ATA device errors are treated as ATA device errors by setting ATA_ERR bit. Better error descriptor which can properly represent ATA and other errors/exceptions is needed.
When handling timeouts, no action is taken to make device forget about the timed out command and ready for new commands.
EH handling via ata_scsi_error() is not properly protected from usual command processing. On EH entrance, the device is not in quiescent state. Timed out commands may succeed or fail any time. pio_task and atapi_task may still be running.
Too weak error recovery. Devices / controllers causing HSM mismatch errors and other errors quite often require reset to return to known state. Also, advanced error handling is necessary to support features like NCQ and hotplug.
ATA errors are directly handled in the interrupt handler and PIO errors in pio_task. This is problematic for advanced error handling for the following reasons.
First, advanced error handling often requires context and internal qc execution.
Second, even a simple failure (say, CRC error) needs information gathering and could trigger complex error handling (say, resetting & reconfiguring). Having multiple code paths to gather information, enter EH and trigger actions makes life painful.
Third, scattered EH code makes implementing low level drivers difficult. Low level drivers override libata callbacks. If EH is scattered over several places, each affected callbacks should perform its part of error handling. This can be error prone and painful.
Table of Contents
ata_link_next — link iteration helper
struct ata_link * fsfuncata_link_next ( | link, | |
ap, | ||
mode) ; |
struct ata_link * link
;struct ata_port * ap
;enum ata_link_iter_mode mode
;ata_dev_next — device iteration helper
struct ata_device * fsfuncata_dev_next ( | dev, | |
link, | ||
mode) ; |
struct ata_device * dev
;struct ata_link * link
;enum ata_dev_iter_mode mode
;atapi_cmd_type — Determine ATAPI command type from SCSI opcode
int fsfuncatapi_cmd_type ( | opcode) ; |
u8 opcode
;ata_tf_to_fis — Convert ATA taskfile to SATA FIS structure
void fsfuncata_tf_to_fis ( | tf, | |
pmp, | ||
is_cmd, | ||
fis) ; |
const struct ata_taskfile * tf
;u8 pmp
;int is_cmd
;u8 * fis
;tf
Taskfile to convert
pmp
Port multiplier port
is_cmd
This FIS is for command
fis
Buffer into which data will output
ata_tf_from_fis — Convert SATA FIS to ATA taskfile
void fsfuncata_tf_from_fis ( | fis, | |
tf) ; |
const u8 * fis
;struct ata_taskfile * tf
;ata_pack_xfermask — Pack pio, mwdma and udma masks into xfer_mask
unsigned long fsfuncata_pack_xfermask ( | pio_mask, | |
mwdma_mask, | ||
udma_mask) ; |
unsigned long pio_mask
;unsigned long mwdma_mask
;unsigned long udma_mask
;ata_unpack_xfermask — Unpack xfer_mask into pio, mwdma and udma masks
void fsfuncata_unpack_xfermask ( | xfer_mask, | |
pio_mask, | ||
mwdma_mask, | ||
udma_mask) ; |
unsigned long xfer_mask
;unsigned long * pio_mask
;unsigned long * mwdma_mask
;unsigned long * udma_mask
;ata_xfer_mask2mode — Find matching XFER_* for the given xfer_mask
u8 fsfuncata_xfer_mask2mode ( | xfer_mask) ; |
unsigned long xfer_mask
;ata_xfer_mode2mask — Find matching xfer_mask for XFER_*
unsigned long fsfuncata_xfer_mode2mask ( | xfer_mode) ; |
u8 xfer_mode
;ata_xfer_mode2shift — Find matching xfer_shift for XFER_*
int fsfuncata_xfer_mode2shift ( | xfer_mode) ; |
unsigned long xfer_mode
;ata_mode_string — convert xfer_mask to string
const char * fsfuncata_mode_string ( | xfer_mask) ; |
unsigned long xfer_mask
;ata_dev_classify — determine device type based on ATA-spec signature
unsigned int fsfuncata_dev_classify ( | tf) ; |
const struct ata_taskfile * tf
;ata_id_string — Convert IDENTIFY DEVICE page into string
void fsfuncata_id_string ( | id, | |
s, | ||
ofs, | ||
len) ; |
const u16 * id
;unsigned char * s
;unsigned int ofs
;unsigned int len
;id
IDENTIFY DEVICE results we will examine
s
string into which data is output
ofs
offset into identify device page
len
length of string to return. must be an even number.
ata_id_c_string — Convert IDENTIFY DEVICE page into C string
void fsfuncata_id_c_string ( | id, | |
s, | ||
ofs, | ||
len) ; |
const u16 * id
;unsigned char * s
;unsigned int ofs
;unsigned int len
;id
IDENTIFY DEVICE results we will examine
s
string into which data is output
ofs
offset into identify device page
len
length of string to return. must be an odd number.
ata_id_xfermask — Compute xfermask from the given IDENTIFY data
unsigned long fsfuncata_id_xfermask ( | id) ; |
const u16 * id
;ata_pio_need_iordy — check if iordy needed
unsigned int fsfuncata_pio_need_iordy ( | adev) ; |
const struct ata_device * adev
;ata_do_dev_read_id — default ID read method
unsigned int fsfuncata_do_dev_read_id ( | dev, | |
tf, | ||
id) ; |
struct ata_device * dev
;struct ata_taskfile * tf
;u16 * id
;ata_cable_40wire — return 40 wire cable type
int fsfuncata_cable_40wire ( | ap) ; |
struct ata_port * ap
;ata_cable_80wire — return 80 wire cable type
int fsfuncata_cable_80wire ( | ap) ; |
struct ata_port * ap
;ata_cable_unknown — return unknown PATA cable.
int fsfuncata_cable_unknown ( | ap) ; |
struct ata_port * ap
;ata_cable_ignore — return ignored PATA cable.
int fsfuncata_cable_ignore ( | ap) ; |
struct ata_port * ap
;ata_cable_sata — return SATA cable type
int fsfuncata_cable_sata ( | ap) ; |
struct ata_port * ap
;ata_dev_pair — return other device on cable
struct ata_device * fsfuncata_dev_pair ( | adev) ; |
struct ata_device * adev
;sata_set_spd — set SATA spd according to spd limit
int fsfuncsata_set_spd ( | link) ; |
struct ata_link * link
;ata_timing_cycle2mode — find xfer mode for the specified cycle duration
u8 fsfuncata_timing_cycle2mode ( | xfer_shift, | |
cycle) ; |
unsigned int xfer_shift
;int cycle
;ata_do_set_mode — Program timings and issue SET FEATURES - XFER
int fsfuncata_do_set_mode ( | link, | |
r_failed_dev) ; |
struct ata_link * link
;struct ata_device ** r_failed_dev
;ata_wait_after_reset — wait for link to become ready after reset
int fsfuncata_wait_after_reset ( | link, | |
deadline, | ||
check_ready) ; |
struct ata_link * link
;unsigned long deadline
;int (*check_ready)
(
struct ata_link *link)
;sata_link_debounce — debounce SATA phy status
int fsfuncsata_link_debounce ( | link, | |
params, | ||
deadline) ; |
struct ata_link * link
;const unsigned long * params
;unsigned long deadline
;link
ATA link to debounce SATA phy status for
params
timing parameters { interval, duratinon, timeout } in msec
deadline
deadline jiffies for the operation
Make sure SStatus of link
reaches stable state, determined by
holding the same value where DET is not 1 for duration
polled
every interval
, before timeout
. Timeout constraints the
beginning of the stable state. Because DET gets stuck at 1 on
some controllers after hot unplugging, this functions waits
until timeout then returns 0 if DET is stable at 1.
timeout
is further limited by deadline
. The sooner of the
two is used.
sata_link_resume — resume SATA link
int fsfuncsata_link_resume ( | link, | |
params, | ||
deadline) ; |
struct ata_link * link
;const unsigned long * params
;unsigned long deadline
;sata_link_scr_lpm — manipulate SControl IPM and SPM fields
int fsfuncsata_link_scr_lpm ( | link, | |
policy, | ||
spm_wakeup) ; |
struct ata_link * link
;enum ata_lpm_policy policy
;bool spm_wakeup
;link
ATA link to manipulate SControl for
policy
LPM policy to configure
spm_wakeup
initiate LPM transition to active state
ata_std_prereset — prepare for reset
int fsfuncata_std_prereset ( | link, | |
deadline) ; |
struct ata_link * link
;unsigned long deadline
;sata_link_hardreset — reset link via SATA phy reset
int fsfuncsata_link_hardreset ( | link, | |
timing, | ||
deadline, | ||
online, | ||
check_ready) ; |
struct ata_link * link
;const unsigned long * timing
;unsigned long deadline
;bool * online
;int (*check_ready)
(
struct ata_link *)
;link
link to reset
timing
timing parameters { interval, duratinon, timeout } in msec
deadline
deadline jiffies for the operation
online
optional out parameter indicating link onlineness
check_ready
optional callback to check link readiness
SATA phy-reset link
using DET bits of SControl register.
After hardreset, link readiness is waited upon using
ata_wait_ready
if check_ready
is specified. LLDs are
allowed to not specify check_ready
and wait itself after this
function returns. Device classification is LLD's
responsibility.
*online
is set to one iff reset succeeded and link
is online
after reset.
sata_std_hardreset — COMRESET w/o waiting or classification
int fsfuncsata_std_hardreset ( | link, | |
class, | ||
deadline) ; |
struct ata_link * link
;unsigned int * class
;unsigned long deadline
;ata_std_postreset — standard postreset callback
void fsfuncata_std_postreset ( | link, | |
classes) ; |
struct ata_link * link
;unsigned int * classes
;ata_dev_set_feature — Issue SET FEATURES - SATA FEATURES
unsigned int fsfuncata_dev_set_feature ( | dev, | |
enable, | ||
feature) ; |
struct ata_device * dev
;u8 enable
;u8 feature
;ata_std_qc_defer — Check whether a qc needs to be deferred
int fsfuncata_std_qc_defer ( | qc) ; |
struct ata_queued_cmd * qc
;ata_sg_init — Associate command with scatter-gather table.
void fsfuncata_sg_init ( | qc, | |
sg, | ||
n_elem) ; |
struct ata_queued_cmd * qc
;struct scatterlist * sg
;unsigned int n_elem
;qc
Command to be associated
sg
Scatter-gather table.
n_elem
Number of elements in s/g table.
ata_qc_complete — Complete an active ATA command
void fsfuncata_qc_complete ( | qc) ; |
struct ata_queued_cmd * qc
;Indicate to the mid and upper layers that an ATA command has completed, with either an ok or not-ok status.
Refrain from calling this function multiple times when
successfully completing multiple NCQ commands.
ata_qc_complete_multiple
should be used instead, which will
properly update IRQ expect state.
ata_qc_complete_multiple — Complete multiple qcs successfully
int fsfuncata_qc_complete_multiple ( | ap, | |
qc_active) ; |
struct ata_port * ap
;u32 qc_active
;
Complete in-flight commands. This functions is meant to be
called from low-level driver's interrupt routine to complete
requests normally. ap->qc_active and qc_active
is compared
and commands are completed accordingly.
Always use this function when completing multiple NCQ commands
from IRQ handlers instead of calling ata_qc_complete
multiple times to keep IRQ expect status properly in sync.
sata_scr_valid — test whether SCRs are accessible
int fsfuncsata_scr_valid ( | link) ; |
struct ata_link * link
;sata_scr_read — read SCR register of the specified port
int fsfuncsata_scr_read ( | link, | |
reg, | ||
val) ; |
struct ata_link * link
;int reg
;u32 * val
;sata_scr_write — write SCR register of the specified port
int fsfuncsata_scr_write ( | link, | |
reg, | ||
val) ; |
struct ata_link * link
;int reg
;u32 val
;sata_scr_write_flush — write SCR register of the specified port and flush
int fsfuncsata_scr_write_flush ( | link, | |
reg, | ||
val) ; |
struct ata_link * link
;int reg
;u32 val
;ata_link_online — test whether the given link is online
bool fsfuncata_link_online ( | link) ; |
struct ata_link * link
;ata_link_offline — test whether the given link is offline
bool fsfuncata_link_offline ( | link) ; |
struct ata_link * link
;ata_host_suspend — suspend host
int fsfuncata_host_suspend ( | host, | |
mesg) ; |
struct ata_host * host
;pm_message_t mesg
;ata_host_resume — resume host
void fsfuncata_host_resume ( | host) ; |
struct ata_host * host
;ata_host_alloc — allocate and init basic ATA host resources
struct ata_host * fsfuncata_host_alloc ( | dev, | |
max_ports) ; |
struct device * dev
;int max_ports
;dev
generic device this host is associated with
max_ports
maximum number of ATA ports associated with this host
Allocate and initialize basic ATA host resources. LLD calls
this function to allocate a host, initializes it fully and
attaches it using ata_host_register
.
max_ports
ports are allocated and host->n_ports is
initialized to max_ports
. The caller is allowed to decrease
host->n_ports before calling ata_host_register
. The unused
ports will be automatically freed on registration.
ata_host_alloc_pinfo — alloc host and init with port_info array
struct ata_host * fsfuncata_host_alloc_pinfo ( | dev, | |
ppi, | ||
n_ports) ; |
struct device * dev
;const struct ata_port_info *const * ppi
;int n_ports
;dev
generic device this host is associated with
ppi
array of ATA port_info to initialize host with
n_ports
number of ATA ports attached to this host
ata_slave_link_init — initialize slave link
int fsfuncata_slave_link_init ( | ap) ; |
struct ata_port * ap
;
Create and initialize slave link for ap
. This enables slave
link handling on the port.
In libata, a port contains links and a link contains devices. There is single host link but if a PMP is attached to it, there can be multiple fan-out links. On SATA, there's usually a single device connected to a link but PATA and SATA controllers emulating TF based interface can have two - master and slave.
However, there are a few controllers which don't fit into this abstraction too well - SATA controllers which emulate TF interface with both master and slave devices but also have separate SCR register sets for each device. These controllers need separate links for physical link handling (e.g. onlineness, link speed) but should be treated like a traditional M/S controller for everything else (e.g. command issue, softreset).
slave_link is libata's way of handling this class of
controllers without impacting core layer too much. For
anything other than physical link handling, the default host
link is used for both master and slave. For physical link
handling, separate ap
->slave_link is used. All dirty details
are implemented inside libata core layer. From LLD's POV, the
only difference is that prereset, hardreset and postreset are
called once more for the slave link, so the reset sequence
looks like the following.
prereset(M) -> prereset(S) -> hardreset(M) -> hardreset(S) -> softreset(M) -> postreset(M) -> postreset(S)
Note that softreset is called only for the master. Softreset resets both M/S by definition, so SRST on master should handle both (the standard method will work just fine).
ata_host_start — start and freeze ports of an ATA host
int fsfuncata_host_start ( | host) ; |
struct ata_host * host
;ata_host_init — Initialize a host struct for sas (ipr, libsas)
void fsfuncata_host_init ( | host, | |
dev, | ||
ops) ; |
struct ata_host * host
;struct device * dev
;struct ata_port_operations * ops
;ata_host_register — register initialized ATA host
int fsfuncata_host_register ( | host, | |
sht) ; |
struct ata_host * host
;struct scsi_host_template * sht
;ata_host_activate — start host, request IRQ and register it
int fsfuncata_host_activate ( | host, | |
irq, | ||
irq_handler, | ||
irq_flags, | ||
sht) ; |
struct ata_host * host
;int irq
;irq_handler_t irq_handler
;unsigned long irq_flags
;struct scsi_host_template * sht
;host
target ATA host
irq
IRQ to request
irq_handler
irq_handler used when requesting IRQ
irq_flags
irq_flags used when requesting IRQ
sht
scsi_host_template to use when registering the host
After allocating an ATA host and initializing it, most libata LLDs perform three steps to activate the host - start host, request IRQ and register it. This helper takes necessasry arguments and performs the three steps in one go.
An invalid IRQ skips the IRQ registration and expects the host to
have set polling mode on the port. In this case, irq_handler
should be NULL.
ata_host_detach — Detach all ports of an ATA host
void fsfuncata_host_detach ( | host) ; |
struct ata_host * host
;ata_pci_remove_one — PCI layer callback for device removal
void fsfuncata_pci_remove_one ( | pdev) ; |
struct pci_dev * pdev
;ata_platform_remove_one — Platform layer callback for device removal
int fsfuncata_platform_remove_one ( | pdev) ; |
struct platform_device * pdev
;ata_msleep — ATA EH owner aware msleep
void fsfuncata_msleep ( | ap, | |
msecs) ; |
struct ata_port * ap
;unsigned int msecs
;ata_wait_register — wait until register value changes
u32 fsfuncata_wait_register ( | ap, | |
reg, | ||
mask, | ||
val, | ||
interval, | ||
timeout) ; |
struct ata_port * ap
;void __iomem * reg
;u32 mask
;u32 val
;unsigned long interval
;unsigned long timeout
;ap
ATA port to wait register for, can be NULL
reg
IO-mapped register
mask
Mask to apply to read register value
val
Wait condition
interval
polling interval in milliseconds
timeout
timeout in milliseconds
Waiting for some bits of register to change is a common
operation for ATA controllers. This function reads 32bit LE
IO-mapped register reg
and tests for the following condition.
(*reg
& mask) != val
If the condition is met, it returns; otherwise, the process is
repeated after interval_msec
until timeout.
Table of Contents
ata_dev_phys_link — find physical link for a device
struct ata_link * fsfuncata_dev_phys_link ( | dev) ; |
struct ata_device * dev
;ata_force_cbl — force cable type according to libata.force
void fsfuncata_force_cbl ( | ap) ; |
struct ata_port * ap
;ata_force_link_limits — force link limits according to libata.force
void fsfuncata_force_link_limits ( | link) ; |
struct ata_link * link
;Force link flags and SATA spd limit according to libata.force and whine about it. When only the port part is specified (e.g. 1:), the limit applies to all links connected to both the host link and all fan-out ports connected via PMP. If the device part is specified as 0 (e.g. 1.00:), it specifies the first fan-out link not the host link. Device number 15 always points to the host link whether PMP is attached or not. If the controller has slave link, device number 16 points to it.
ata_force_xfermask — force xfermask according to libata.force
void fsfuncata_force_xfermask ( | dev) ; |
struct ata_device * dev
;ata_force_horkage — force horkage according to libata.force
void fsfuncata_force_horkage ( | dev) ; |
struct ata_device * dev
;ata_rwcmd_protocol — set taskfile r/w commands and protocol
int fsfuncata_rwcmd_protocol ( | tf, | |
dev) ; |
struct ata_taskfile * tf
;struct ata_device * dev
;ata_tf_read_block — Read block address from ATA taskfile
u64 fsfuncata_tf_read_block ( | tf, | |
dev) ; |
struct ata_taskfile * tf
;struct ata_device * dev
;ata_build_rw_tf — Build ATA taskfile for given read/write request
int fsfuncata_build_rw_tf ( | tf, | |
dev, | ||
block, | ||
n_block, | ||
tf_flags, | ||
tag) ; |
struct ata_taskfile * tf
;struct ata_device * dev
;u64 block
;u32 n_block
;unsigned int tf_flags
;unsigned int tag
;tf
Target ATA taskfile
dev
ATA device tf
belongs to
block
Block address
n_block
Number of blocks
tf_flags
RW/FUA etc...
tag
tag
ata_read_native_max_address — Read native max address
int fsfuncata_read_native_max_address ( | dev, | |
max_sectors) ; |
struct ata_device * dev
;u64 * max_sectors
;ata_set_max_sectors — Set max sectors
int fsfuncata_set_max_sectors ( | dev, | |
new_sectors) ; |
struct ata_device * dev
;u64 new_sectors
;ata_hpa_resize — Resize a device with an HPA set
int fsfuncata_hpa_resize ( | dev) ; |
struct ata_device * dev
;ata_dump_id — IDENTIFY DEVICE info debugging output
void fsfuncata_dump_id ( | id) ; |
const u16 * id
;ata_exec_internal_sg — execute libata internal command
unsigned fsfuncata_exec_internal_sg ( | dev, | |
tf, | ||
cdb, | ||
dma_dir, | ||
sgl, | ||
n_elem, | ||
timeout) ; |
struct ata_device * dev
;struct ata_taskfile * tf
;const u8 * cdb
;int dma_dir
;struct scatterlist * sgl
;unsigned int n_elem
;unsigned long timeout
;dev
Device to which the command is sent
tf
Taskfile registers for the command and the result
cdb
CDB for packet command
dma_dir
Data tranfer direction of the command
sgl
sg list for the data buffer of the command
n_elem
Number of sg entries
timeout
Timeout in msecs (0 for default)
ata_exec_internal — execute libata internal command
unsigned fsfuncata_exec_internal ( | dev, | |
tf, | ||
cdb, | ||
dma_dir, | ||
buf, | ||
buflen, | ||
timeout) ; |
struct ata_device * dev
;struct ata_taskfile * tf
;const u8 * cdb
;int dma_dir
;void * buf
;unsigned int buflen
;unsigned long timeout
;ata_do_simple_cmd — execute simple internal command
unsigned int fsfuncata_do_simple_cmd ( | dev, | |
cmd) ; |
struct ata_device * dev
;u8 cmd
;ata_pio_mask_no_iordy — Return the non IORDY mask
u32 fsfuncata_pio_mask_no_iordy ( | adev) ; |
const struct ata_device * adev
;ata_dev_read_id — Read ID data from the specified device
int fsfuncata_dev_read_id ( | dev, | |
p_class, | ||
flags, | ||
id) ; |
struct ata_device * dev
;unsigned int * p_class
;unsigned int flags
;u16 * id
;dev
target device
p_class
pointer to class of the target device (may be changed)
flags
ATA_READID_* flags
id
buffer to read IDENTIFY data into
ata_dev_configure — Configure the specified ATA/ATAPI device
int fsfuncata_dev_configure ( | dev) ; |
struct ata_device * dev
;ata_bus_probe — Reset and probe ATA bus
int fsfuncata_bus_probe ( | ap) ; |
struct ata_port * ap
;sata_print_link_status — Print SATA link status
void fsfuncsata_print_link_status ( | link) ; |
struct ata_link * link
;sata_down_spd_limit — adjust SATA spd limit downward
int fsfuncsata_down_spd_limit ( | link, | |
spd_limit) ; |
struct ata_link * link
;u32 spd_limit
;
Adjust SATA spd limit of link
downward. Note that this
function only adjusts the limit. The change must be applied
using sata_set_spd
.
If spd_limit
is non-zero, the speed is limited to equal to or
lower than spd_limit
if such speed is supported. If
spd_limit
is slower than any supported speed, only the lowest
supported speed is allowed.
sata_set_spd_needed — is SATA spd configuration needed
int fsfuncsata_set_spd_needed ( | link) ; |
struct ata_link * link
;ata_down_xfermask_limit — adjust dev xfer masks downward
int fsfuncata_down_xfermask_limit ( | dev, | |
sel) ; |
struct ata_device * dev
;unsigned int sel
;ata_wait_ready — wait for link to become ready
int fsfuncata_wait_ready ( | link, | |
deadline, | ||
check_ready) ; |
struct ata_link * link
;unsigned long deadline
;int (*check_ready)
(
struct ata_link *link)
;link
link to be waited on
deadline
deadline jiffies for the operation
check_ready
callback to check link readiness
ata_dev_same_device — Determine whether new ID matches configured device
int fsfuncata_dev_same_device ( | dev, | |
new_class, | ||
new_id) ; |
struct ata_device * dev
;unsigned int new_class
;const u16 * new_id
;dev
device to compare against
new_class
class of the new device
new_id
IDENTIFY page of the new device
ata_dev_reread_id — Re-read IDENTIFY data
int fsfuncata_dev_reread_id ( | dev, | |
readid_flags) ; |
struct ata_device * dev
;unsigned int readid_flags
;ata_dev_revalidate — Revalidate ATA device
int fsfuncata_dev_revalidate ( | dev, | |
new_class, | ||
readid_flags) ; |
struct ata_device * dev
;unsigned int new_class
;unsigned int readid_flags
;glob_match — match a text string against a glob-style pattern
int fsfuncglob_match ( | text, | |
pattern) ; |
const char * text
;const char * pattern
;Either/both of text and pattern can be empty strings.
Match text against a glob-style pattern, with wildcards and simple sets:
? matches any single character. * matches any run of characters. [xyz] matches a single character from the set: x, y, or z. [a-d] matches a single character from the range: a, b, c, or d. [a-d0-9] matches a single character from either range.
The special characters ?, [, -, or *, can be matched using a set, eg. [*] Behaviour with malformed patterns is undefined, though generally reasonable.
ata_is_40wire — check drive side detection
int fsfuncata_is_40wire ( | dev) ; |
struct ata_device * dev
;cable_is_40wire — 40/80/SATA decider
int fsfunccable_is_40wire ( | ap) ; |
struct ata_port * ap
;This function encapsulates the policy for speed management in one place. At the moment we don't cache the result but there is a good case for setting ap->cbl to the result when we are called with unknown cables (and figuring out if it impacts hotplug at all).
Return 1 if the cable appears to be 40 wire.
ata_dev_xfermask — Compute supported xfermask of the given device
void fsfuncata_dev_xfermask ( | dev) ; |
struct ata_device * dev
;ata_dev_set_xfermode — Issue SET FEATURES - XFER MODE command
unsigned int fsfuncata_dev_set_xfermode ( | dev) ; |
struct ata_device * dev
;ata_dev_init_params — Issue INIT DEV PARAMS command
unsigned int fsfuncata_dev_init_params ( | dev, | |
heads, | ||
sectors) ; |
struct ata_device * dev
;u16 heads
;u16 sectors
;ata_sg_clean — Unmap DMA memory associated with command
void fsfuncata_sg_clean ( | qc) ; |
struct ata_queued_cmd * qc
;atapi_check_dma — Check whether ATAPI DMA can be supported
int fsfuncatapi_check_dma ( | qc) ; |
struct ata_queued_cmd * qc
;ata_sg_setup — DMA-map the scatter-gather table associated with a command.
int fsfuncata_sg_setup ( | qc) ; |
struct ata_queued_cmd * qc
;swap_buf_le16 — swap halves of 16-bit words in place
void fsfuncswap_buf_le16 ( | buf, | |
buf_words) ; |
u16 * buf
;unsigned int buf_words
;ata_qc_new — Request an available ATA command, for queueing
struct ata_queued_cmd * fsfuncata_qc_new ( | ap) ; |
struct ata_port * ap
;ata_qc_new_init — Request an available ATA command, and initialize it
struct ata_queued_cmd * fsfuncata_qc_new_init ( | dev) ; |
struct ata_device * dev
;ata_qc_free — free unused ata_queued_cmd
void fsfuncata_qc_free ( | qc) ; |
struct ata_queued_cmd * qc
;ata_qc_issue — issue taskfile to device
void fsfuncata_qc_issue ( | qc) ; |
struct ata_queued_cmd * qc
;ata_phys_link_online — test whether the given link is online
bool fsfuncata_phys_link_online ( | link) ; |
struct ata_link * link
;ata_phys_link_offline — test whether the given link is offline
bool fsfuncata_phys_link_offline ( | link) ; |
struct ata_link * link
;ata_dev_init — Initialize an ata_device structure
void fsfuncata_dev_init ( | dev) ; |
struct ata_device * dev
;ata_link_init — Initialize an ata_link structure
void fsfuncata_link_init ( | ap, | |
link, | ||
pmp) ; |
struct ata_port * ap
;struct ata_link * link
;int pmp
;sata_link_init_spd — Initialize link->sata_spd_limit
int fsfuncsata_link_init_spd ( | link) ; |
struct ata_link * link
;ata_port_alloc — allocate and initialize basic ATA port resources
struct ata_port * fsfuncata_port_alloc ( | host) ; |
struct ata_host * host
;ata_finalize_port_ops — finalize ata_port_operations
void fsfuncata_finalize_port_ops ( | ops) ; |
struct ata_port_operations * ops
;An ata_port_operations can inherit from another ops and that ops can again inherit from another. This can go on as many times as necessary as long as there is no loop in the inheritance chain.
Ops tables are finalized when the host is started. NULL or unspecified entries are inherited from the closet ancestor which has the method and the entry is populated with it. After finalization, the ops table directly points to all the methods and ->inherits is no longer necessary and cleared.
Using ATA_OP_NULL, inheriting ops can force a method to NULL.
ata_port_detach — Detach ATA port in prepration of device removal
void fsfuncata_port_detach ( | ap) ; |
struct ata_port * ap
;Table of Contents
ata_sas_port_start
scsi_rescan_device
ata_std_bios_param — generic bios head/sector/cylinder calculator used by sd.
int fsfuncata_std_bios_param ( | sdev, | |
bdev, | ||
capacity, | ||
geom[]) ; |
struct scsi_device * sdev
;struct block_device * bdev
;sector_t capacity
;int geom[]
;sdev
SCSI device for which BIOS geometry is to be determined
bdev
block device associated with sdev
capacity
capacity of SCSI device
geom[]
location to which geometry will be output
ata_scsi_unlock_native_capacity — unlock native capacity
void fsfuncata_scsi_unlock_native_capacity ( | sdev) ; |
struct scsi_device * sdev
;ata_scsi_slave_config — Set SCSI device attributes
int fsfuncata_scsi_slave_config ( | sdev) ; |
struct scsi_device * sdev
;ata_scsi_slave_destroy — SCSI device is about to be destroyed
void fsfuncata_scsi_slave_destroy ( | sdev) ; |
struct scsi_device * sdev
;
sdev
is about to be destroyed for hot/warm unplugging. If
this unplugging was initiated by libata as indicated by NULL
dev->sdev, this function doesn't have to do anything.
Otherwise, SCSI layer initiated warm-unplug is in progress.
Clear dev->sdev, schedule the device for ATA detach and invoke
EH.
__ata_change_queue_depth — helper for ata_scsi_change_queue_depth
int fsfunc__ata_change_queue_depth ( | ap, | |
sdev, | ||
queue_depth, | ||
reason) ; |
struct ata_port * ap
;struct scsi_device * sdev
;int queue_depth
;int reason
;ata_scsi_change_queue_depth — SCSI callback for queue depth config
int fsfuncata_scsi_change_queue_depth ( | sdev, | |
queue_depth, | ||
reason) ; |
struct scsi_device * sdev
;int queue_depth
;int reason
;sdev
SCSI device to configure queue depth for
queue_depth
new queue depth
reason
calling context
ata_scsi_queuecmd — Issue SCSI cdb to libata-managed device
int fsfuncata_scsi_queuecmd ( | shost, | |
cmd) ; |
struct Scsi_Host * shost
;struct scsi_cmnd * cmd
;In some cases, this function translates SCSI commands into ATA taskfiles, and queues the taskfiles to be sent to hardware. In other cases, this function simulates a SCSI device by evaluating and responding to certain SCSI commands. This creates the overall effect of ATA and ATAPI devices appearing as SCSI devices.
ata_scsi_simulate — simulate SCSI command on ATA device
void fsfuncata_scsi_simulate ( | dev, | |
cmd) ; |
struct ata_device * dev
;struct scsi_cmnd * cmd
;ata_sas_port_alloc — Allocate port for a SAS attached SATA device
struct ata_port * fsfuncata_sas_port_alloc ( | host, | |
port_info, | ||
shost) ; |
struct ata_host * host
;struct ata_port_info * port_info
;struct Scsi_Host * shost
;ata_sas_port_start — Set port up for dma.
int fsfuncata_sas_port_start ( | ap) ; |
struct ata_port * ap
;ata_sas_port_stop —
Undo ata_sas_port_start
void fsfuncata_sas_port_stop ( | ap) ; |
struct ata_port * ap
;ata_sas_async_probe — simply schedule probing and return
void fsfuncata_sas_async_probe ( | ap) ; |
struct ata_port * ap
;ata_sas_port_init — Initialize a SATA device
int fsfuncata_sas_port_init ( | ap) ; |
struct ata_port * ap
;ata_sas_port_destroy — Destroy a SATA port allocated by ata_sas_port_alloc
void fsfuncata_sas_port_destroy ( | ap) ; |
struct ata_port * ap
;ata_sas_slave_configure — Default slave_config routine for libata devices
int fsfuncata_sas_slave_configure ( | sdev, | |
ap) ; |
struct scsi_device * sdev
;struct ata_port * ap
;ata_sas_queuecmd — Issue SCSI cdb to libata-managed device
int fsfuncata_sas_queuecmd ( | cmd, | |
ap) ; |
struct scsi_cmnd * cmd
;struct ata_port * ap
;ata_get_identity — Handler for HDIO_GET_IDENTITY ioctl
int fsfuncata_get_identity ( | ap, | |
sdev, | ||
arg) ; |
struct ata_port * ap
;struct scsi_device * sdev
;void __user * arg
;ata_cmd_ioctl — Handler for HDIO_DRIVE_CMD ioctl
int fsfuncata_cmd_ioctl ( | scsidev, | |
arg) ; |
struct scsi_device * scsidev
;void __user * arg
;ata_task_ioctl — Handler for HDIO_DRIVE_TASK ioctl
int fsfuncata_task_ioctl ( | scsidev, | |
arg) ; |
struct scsi_device * scsidev
;void __user * arg
;ata_scsi_qc_new — acquire new ata_queued_cmd reference
struct ata_queued_cmd * fsfuncata_scsi_qc_new ( | dev, | |
cmd) ; |
struct ata_device * dev
;struct scsi_cmnd * cmd
;dev
ATA device to which the new command is attached
cmd
SCSI command that originated this ATA command
ata_dump_status — user friendly display of error info
void fsfuncata_dump_status ( | id, | |
tf) ; |
unsigned id
;struct ata_taskfile * tf
;ata_to_sense_error — convert ATA error to SCSI error
void fsfuncata_to_sense_error ( | id, | |
drv_stat, | ||
drv_err, | ||
sk, | ||
asc, | ||
ascq, | ||
verbose) ; |
unsigned id
;u8 drv_stat
;u8 drv_err
;u8 * sk
;u8 * asc
;u8 * ascq
;int verbose
;id
ATA device number
drv_stat
value contained in ATA status register
drv_err
value contained in ATA error register
sk
the sense key we'll fill out
asc
the additional sense code we'll fill out
ascq
the additional sense code qualifier we'll fill out
verbose
be verbose
ata_gen_ata_sense — generate a SCSI fixed sense block
void fsfuncata_gen_ata_sense ( | qc) ; |
struct ata_queued_cmd * qc
;atapi_drain_needed — Check whether data transfer may overflow
int fsfuncatapi_drain_needed ( | rq) ; |
struct request * rq
;ata_scsi_start_stop_xlat — Translate SCSI START STOP UNIT command
unsigned int fsfuncata_scsi_start_stop_xlat ( | qc) ; |
struct ata_queued_cmd * qc
;ata_scsi_flush_xlat — Translate SCSI SYNCHRONIZE CACHE command
unsigned int fsfuncata_scsi_flush_xlat ( | qc) ; |
struct ata_queued_cmd * qc
;scsi_6_lba_len — Get LBA and transfer length
void fsfuncscsi_6_lba_len ( | cdb, | |
plba, | ||
plen) ; |
const u8 * cdb
;u64 * plba
;u32 * plen
;scsi_10_lba_len — Get LBA and transfer length
void fsfuncscsi_10_lba_len ( | cdb, | |
plba, | ||
plen) ; |
const u8 * cdb
;u64 * plba
;u32 * plen
;scsi_16_lba_len — Get LBA and transfer length
void fsfuncscsi_16_lba_len ( | cdb, | |
plba, | ||
plen) ; |
const u8 * cdb
;u64 * plba
;u32 * plen
;ata_scsi_verify_xlat — Translate SCSI VERIFY command into an ATA one
unsigned int fsfuncata_scsi_verify_xlat ( | qc) ; |
struct ata_queued_cmd * qc
;ata_scsi_rw_xlat — Translate SCSI r/w command into an ATA one
unsigned int fsfuncata_scsi_rw_xlat ( | qc) ; |
struct ata_queued_cmd * qc
;ata_scsi_translate — Translate then issue SCSI command to ATA device
int fsfuncata_scsi_translate ( | dev, | |
cmd, | ||
xlat_func) ; |
struct ata_device * dev
;struct scsi_cmnd * cmd
;ata_xlat_func_t xlat_func
;dev
ATA device to which the command is addressed
cmd
SCSI command to execute
xlat_func
Actor which translates cmd
to an ATA taskfile
Our ->queuecommand
function has decided that the SCSI
command issued can be directly translated into an ATA
command, rather than handled internally.
This function sets up an ata_queued_cmd structure for the SCSI command, and sends that ata_queued_cmd to the hardware.
The xlat_func argument (actor) returns 0 if ready to execute ATA command, else 1 to finish translation. If 1 is returned then cmd->result (and possibly cmd->sense_buffer) are assumed to be set reflecting an error condition or clean (early) termination.
ata_scsi_rbuf_get — Map response buffer.
void * fsfuncata_scsi_rbuf_get ( | cmd, | |
copy_in, | ||
flags) ; |
struct scsi_cmnd * cmd
;bool copy_in
;unsigned long * flags
;ata_scsi_rbuf_put — Unmap response buffer.
void fsfuncata_scsi_rbuf_put ( | cmd, | |
copy_out, | ||
flags) ; |
struct scsi_cmnd * cmd
;bool copy_out
;unsigned long * flags
;ata_scsi_rbuf_fill — wrapper for SCSI command simulators
void fsfuncata_scsi_rbuf_fill ( | args, | |
actor) ; |
struct ata_scsi_args * args
;unsigned int (*actor)
(
struct ata_scsi_args *args, u8 *rbuf)
;args
device IDENTIFY data / SCSI command of interest.
actor
Callback hook for desired SCSI command simulator
Takes care of the hard work of simulating a SCSI command... Mapping the response buffer, calling the command's handler, and handling the handler's return value. This return value indicates whether the handler wishes the SCSI command to be completed successfully (0), or not (in which case cmd->result and sense buffer are assumed to be set).
ata_scsiop_inq_std — Simulate INQUIRY command
unsigned int fsfuncata_scsiop_inq_std ( | args, | |
rbuf) ; |
struct ata_scsi_args * args
;u8 * rbuf
;args
device IDENTIFY data / SCSI command of interest.
rbuf
Response buffer, to which simulated SCSI cmd output is sent.
ata_scsiop_inq_00 — Simulate INQUIRY VPD page 0, list of pages
unsigned int fsfuncata_scsiop_inq_00 ( | args, | |
rbuf) ; |
struct ata_scsi_args * args
;u8 * rbuf
;ata_scsiop_inq_80 — Simulate INQUIRY VPD page 80, device serial number
unsigned int fsfuncata_scsiop_inq_80 ( | args, | |
rbuf) ; |
struct ata_scsi_args * args
;u8 * rbuf
;ata_scsiop_inq_83 — Simulate INQUIRY VPD page 83, device identity
unsigned int fsfuncata_scsiop_inq_83 ( | args, | |
rbuf) ; |
struct ata_scsi_args * args
;u8 * rbuf
;args
device IDENTIFY data / SCSI command of interest.
rbuf
Response buffer, to which simulated SCSI cmd output is sent.
ata_scsiop_inq_89 — Simulate INQUIRY VPD page 89, ATA info
unsigned int fsfuncata_scsiop_inq_89 ( | args, | |
rbuf) ; |
struct ata_scsi_args * args
;u8 * rbuf
;ata_scsiop_noop — Command handler that simply returns success.
unsigned int fsfuncata_scsiop_noop ( | args, | |
rbuf) ; |
struct ata_scsi_args * args
;u8 * rbuf
;args
device IDENTIFY data / SCSI command of interest.
rbuf
Response buffer, to which simulated SCSI cmd output is sent.
modecpy — Prepare response for MODE SENSE
void fsfuncmodecpy ( | dest, | |
src, | ||
n, | ||
changeable) ; |
u8 * dest
;const u8 * src
;int n
;bool changeable
;ata_msense_caching — Simulate MODE SENSE caching info page
unsigned int fsfuncata_msense_caching ( | id, | |
buf, | ||
changeable) ; |
u16 * id
;u8 * buf
;bool changeable
;id
device IDENTIFY data
buf
output buffer
changeable
whether changeable parameters are requested
ata_msense_ctl_mode — Simulate MODE SENSE control mode page
unsigned int fsfuncata_msense_ctl_mode ( | buf, | |
changeable) ; |
u8 * buf
;bool changeable
;ata_msense_rw_recovery — Simulate MODE SENSE r/w error recovery page
unsigned int fsfuncata_msense_rw_recovery ( | buf, | |
changeable) ; |
u8 * buf
;bool changeable
;ata_scsiop_mode_sense — Simulate MODE SENSE 6, 10 commands
unsigned int fsfuncata_scsiop_mode_sense ( | args, | |
rbuf) ; |
struct ata_scsi_args * args
;u8 * rbuf
;args
device IDENTIFY data / SCSI command of interest.
rbuf
Response buffer, to which simulated SCSI cmd output is sent.
ata_scsiop_read_cap — Simulate READ CAPACITY[ 16] commands
unsigned int fsfuncata_scsiop_read_cap ( | args, | |
rbuf) ; |
struct ata_scsi_args * args
;u8 * rbuf
;ata_scsiop_report_luns — Simulate REPORT LUNS command
unsigned int fsfuncata_scsiop_report_luns ( | args, | |
rbuf) ; |
struct ata_scsi_args * args
;u8 * rbuf
;atapi_xlat — Initialize PACKET taskfile
unsigned int fsfuncatapi_xlat ( | qc) ; |
struct ata_queued_cmd * qc
;ata_scsi_find_dev — lookup ata_device from scsi_cmnd
struct ata_device * fsfuncata_scsi_find_dev ( | ap, | |
scsidev) ; |
struct ata_port * ap
;const struct scsi_device * scsidev
;ap
ATA port to which the device is attached
scsidev
SCSI device from which we derive the ATA device
ata_scsi_pass_thru — convert ATA pass-thru CDB to taskfile
unsigned int fsfuncata_scsi_pass_thru ( | qc) ; |
struct ata_queued_cmd * qc
;ata_mselect_caching — Simulate MODE SELECT for caching info page
int fsfuncata_mselect_caching ( | qc, | |
buf, | ||
len) ; |
struct ata_queued_cmd * qc
;const u8 * buf
;int len
;ata_scsi_mode_select_xlat — Simulate MODE SELECT 6, 10 commands
unsigned int fsfuncata_scsi_mode_select_xlat ( | qc) ; |
struct ata_queued_cmd * qc
;ata_get_xlat_func — check if SCSI to ATA translation is possible
ata_xlat_func_t fsfuncata_get_xlat_func ( | dev, | |
cmd) ; |
struct ata_device * dev
;u8 cmd
;ata_scsi_dump_cdb — dump SCSI command contents to dmesg
void fsfuncata_scsi_dump_cdb ( | ap, | |
cmd) ; |
struct ata_port * ap
;struct scsi_cmnd * cmd
;ata_scsi_offline_dev — offline attached SCSI device
int fsfuncata_scsi_offline_dev ( | dev) ; |
struct ata_device * dev
;ata_scsi_remove_dev — remove attached SCSI device
void fsfuncata_scsi_remove_dev ( | dev) ; |
struct ata_device * dev
;ata_scsi_media_change_notify — send media change event
void fsfuncata_scsi_media_change_notify ( | dev) ; |
struct ata_device * dev
;ata_scsi_hotplug — SCSI part of hotplug
void fsfuncata_scsi_hotplug ( | work) ; |
struct work_struct * work
;ata_scsi_user_scan — indication for user-initiated bus scan
int fsfuncata_scsi_user_scan ( | shost, | |
channel, | ||
id, | ||
lun) ; |
struct Scsi_Host * shost
;unsigned int channel
;unsigned int id
;unsigned int lun
;Table of Contents
This chapter tries to identify what error/exception conditions exist for ATA/ATAPI devices and describe how they should be handled in implementation-neutral way.
The term 'error' is used to describe conditions where either an explicit error condition is reported from device or a command has timed out.
The term 'exception' is either used to describe exceptional conditions which are not errors (say, power or hotplug events), or to describe both errors and non-error exceptional conditions. Where explicit distinction between error and exception is necessary, the term 'non-error exception' is used.
Exceptions are described primarily with respect to legacy taskfile + bus master IDE interface. If a controller provides other better mechanism for error reporting, mapping those into categories described below shouldn't be difficult.
In the following sections, two recovery actions - reset and reconfiguring transport - are mentioned. These are described further in the section called “EH recovery actions”.
This error is indicated when STATUS value doesn't match HSM requirement during issuing or execution any ATA/ATAPI command.
Examples
ATA_STATUS doesn't contain !BSY && DRDY && !DRQ while trying to issue a command.
!BSY && !DRQ during PIO data transfer.
DRQ on command completion.
!BSY && ERR after CDB transfer starts but before the last byte of CDB is transferred. ATA/ATAPI standard states that "The device shall not terminate the PACKET command with an error before the last byte of the command packet has been written" in the error outputs description of PACKET command and the state diagram doesn't include such transitions.
In these cases, HSM is violated and not much information regarding the error can be acquired from STATUS or ERROR register. IOW, this error can be anything - driver bug, faulty device, controller and/or cable.
As HSM is violated, reset is necessary to restore known state. Reconfiguring transport for lower speed might be helpful too as transmission errors sometimes cause this kind of errors.
These are errors detected and reported by ATA/ATAPI devices indicating device problems. For this type of errors, STATUS and ERROR register values are valid and describe error condition. Note that some of ATA bus errors are detected by ATA/ATAPI devices and reported using the same mechanism as device errors. Those cases are described later in this section.
For ATA commands, this type of errors are indicated by !BSY && ERR during command execution and on completion.
For ATAPI commands,
!BSY && ERR && ABRT right after issuing PACKET indicates that PACKET command is not supported and falls in this category.
!BSY && ERR(==CHK) && !ABRT after the last byte of CDB is transferred indicates CHECK CONDITION and doesn't fall in this category.
!BSY && ERR(==CHK) && ABRT after the last byte of CDB is transferred *probably* indicates CHECK CONDITION and doesn't fall in this category.
Of errors detected as above, the followings are not ATA/ATAPI device errors but ATA bus errors and should be handled according to the section called “ATA bus error”.
This is indicated by ICRC bit in the ERROR register and means that corruption occurred during data transfer. Up to ATA/ATAPI-7, the standard specifies that this bit is only applicable to UDMA transfers but ATA/ATAPI-8 draft revision 1f says that the bit may be applicable to multiword DMA and PIO.
Up to ATA/ATAPI-7, the standard specifies that ABRT could be set on ICRC errors and on cases where a device is not able to complete a command. Combined with the fact that MWDMA and PIO transfer errors aren't allowed to use ICRC bit up to ATA/ATAPI-7, it seems to imply that ABRT bit alone could indicate transfer errors.
However, ATA/ATAPI-8 draft revision 1f removes the part that ICRC errors can turn on ABRT. So, this is kind of gray area. Some heuristics are needed here.
ATA/ATAPI device errors can be further categorized as follows.
This is indicated by UNC bit in the ERROR register. ATA devices reports UNC error only after certain number of retries cannot recover the data, so there's nothing much else to do other than notifying upper layer.
READ and WRITE commands report CHS or LBA of the first failed sector but ATA/ATAPI standard specifies that the amount of transferred data on error completion is indeterminate, so we cannot assume that sectors preceding the failed sector have been transferred and thus cannot complete those sectors successfully as SCSI does.
<<TODO: fill here>>
This is indicated by IDNF bit in the ERROR register. Report to upper layer.
This can be invalid command or parameter indicated by ABRT ERROR bit or some other error condition. Note that ABRT bit can indicate a lot of things including ICRC and Address errors. Heuristics needed.
Depending on commands, not all STATUS/ERROR bits are applicable. These non-applicable bits are marked with "na" in the output descriptions but up to ATA/ATAPI-7 no definition of "na" can be found. However, ATA/ATAPI-8 draft revision 1f describes "N/A" as follows.
- 3.2.3.3a N/A
A keyword the indicates a field has no defined value in this standard and should not be checked by the host or device. N/A fields should be cleared to zero.
So, it seems reasonable to assume that "na" bits are cleared to zero by devices and thus need no explicit masking.
ATAPI device CHECK CONDITION error is indicated by set CHK bit (ERR bit) in the STATUS register after the last byte of CDB is transferred for a PACKET command. For this kind of errors, sense data should be acquired to gather information regarding the errors. REQUEST SENSE packet command should be used to acquire sense data.
Once sense data is acquired, this type of errors can be handled similary to other SCSI errors. Note that sense data may indicate ATA bus error (e.g. Sense Key 04h HARDWARE ERROR && ASC/ASCQ 47h/00h SCSI PARITY ERROR). In such cases, the error should be considered as an ATA bus error and handled according to the section called “ATA bus error”.
NCQ command error is indicated by cleared BSY and set ERR bit during NCQ command phase (one or more NCQ commands outstanding). Although STATUS and ERROR registers will contain valid values describing the error, READ LOG EXT is required to clear the error condition, determine which command has failed and acquire more information.
READ LOG EXT Log Page 10h reports which tag has failed and taskfile register values describing the error. With this information the failed command can be handled as a normal ATA command error as in the section called “ATA/ATAPI device error (non-NCQ / non-CHECK CONDITION)” and all other in-flight commands must be retried. Note that this retry should not be counted - it's likely that commands retried this way would have completed normally if it were not for the failed command.
Note that ATA bus errors can be reported as ATA device NCQ errors. This should be handled as described in the section called “ATA bus error”.
If READ LOG EXT Log Page 10h fails or reports NQ, we're thoroughly screwed. This condition should be treated according to the section called “HSM violation”.
ATA bus error means that data corruption occurred during transmission over ATA bus (SATA or PATA). This type of errors can be indicated by
ICRC or ABRT error as described in the section called “ATA/ATAPI device error (non-NCQ / non-CHECK CONDITION)”.
Controller-specific error completion with error information indicating transmission error.
On some controllers, command timeout. In this case, there may be a mechanism to determine that the timeout is due to transmission error.
Unknown/random errors, timeouts and all sorts of weirdities.
As described above, transmission errors can cause wide variety of symptoms ranging from device ICRC error to random device lockup, and, for many cases, there is no way to tell if an error condition is due to transmission error or not; therefore, it's necessary to employ some kind of heuristic when dealing with errors and timeouts. For example, encountering repetitive ABRT errors for known supported command is likely to indicate ATA bus error.
Once it's determined that ATA bus errors have possibly occurred, lowering ATA bus transmission speed is one of actions which may alleviate the problem. See the section called “Reconfigure transport” for more information.
Data corruption or other failures during transmission over PCI (or other system bus). For standard BMDMA, this is indicated by Error bit in the BMDMA Status register. This type of errors must be logged as it indicates something is very wrong with the system. Resetting host controller is recommended.
This occurs when timeout occurs and the timeout handler finds out that the timed out command has completed successfully or with error. This is usually caused by lost interrupts. This type of errors must be logged. Resetting host controller is recommended.
This is when timeout occurs and the command is still processing or the host and device are in unknown state. When this occurs, HSM could be in any valid or invalid state. To bring the device to known state and make it forget about the timed out command, resetting is necessary. The timed out command may be retried.
Timeouts can also be caused by transmission errors. Refer to the section called “ATA bus error” for more details.
This section discusses several important recovery actions.
Many controllers require its error registers to be cleared by error handler. Different controllers may have different requirements.
For SATA, it's strongly recommended to clear at least SError register during error handling.
During EH, resetting is necessary in the following cases.
HSM is in unknown or invalid state
HBA is in unknown or invalid state
EH needs to make HBA/device forget about in-flight commands
HBA/device behaves weirdly
Resetting during EH might be a good idea regardless of error condition to improve EH robustness. Whether to reset both or either one of HBA and device depends on situation but the following scheme is recommended.
When it's known that HBA is in ready state but ATA/ATAPI device is in unknown state, reset only device.
If HBA is in unknown state, reset both HBA and device.
HBA resetting is implementation specific. For a controller complying to taskfile/BMDMA PCI IDE, stopping active DMA transaction may be sufficient iff BMDMA state is the only HBA context. But even mostly taskfile/BMDMA PCI IDE complying controllers may have implementation specific requirements and mechanism to reset themselves. This must be addressed by specific drivers.
OTOH, ATA/ATAPI standard describes in detail ways to reset ATA/ATAPI devices.
This is hardware initiated device reset signalled with asserted PATA RESET- signal. There is no standard way to initiate hardware reset from software although some hardware provides registers that allow driver to directly tweak the RESET- signal.
This is achieved by turning CONTROL SRST bit on for at least 5us. Both PATA and SATA support it but, in case of SATA, this may require controller-specific support as the second Register FIS to clear SRST should be transmitted while BSY bit is still set. Note that on PATA, this resets both master and slave devices on a channel.
Although ATA/ATAPI standard doesn't describe exactly, EDD implies some level of resetting, possibly similar level with software reset. Host-side EDD protocol can be handled with normal command processing and most SATA controllers should be able to handle EDD's just like other commands. As in software reset, EDD affects both devices on a PATA bus.
Although EDD does reset devices, this doesn't suit error handling as EDD cannot be issued while BSY is set and it's unclear how it will act when device is in unknown/weird state.
This is very similar to software reset except that reset can be restricted to the selected device without affecting the other device sharing the cable.
This is the preferred way of resetting a SATA device. In effect, it's identical to PATA hardware reset. Note that this can be done with the standard SCR Control register. As such, it's usually easier to implement than software reset.
One more thing to consider when resetting devices is that resetting clears certain configuration parameters and they need to be set to their previous or newly adjusted values after reset.
Parameters affected are.
CHS set up with INITIALIZE DEVICE PARAMETERS (seldom used)
Parameters set with SET FEATURES including transfer mode setting
Block count set with SET MULTIPLE MODE
Other parameters (SET MAX, MEDIA LOCK...)
ATA/ATAPI standard specifies that some parameters must be maintained across hardware or software reset, but doesn't strictly specify all of them. Always reconfiguring needed parameters after reset is required for robustness. Note that this also applies when resuming from deep sleep (power-off).
Also, ATA/ATAPI standard requires that IDENTIFY DEVICE / IDENTIFY PACKET DEVICE is issued after any configuration parameter is updated or a hardware reset and the result used for further operation. OS driver is required to implement revalidation mechanism to support this.
For both PATA and SATA, a lot of corners are cut for cheap connectors, cables or controllers and it's quite common to see high transmission error rate. This can be mitigated by lowering transmission speed.
The following is a possible scheme Jeff Garzik suggested.
If more than $N (3?) transmission errors happen in 15 minutes,
if SATA, decrease SATA PHY speed. if speed cannot be decreased,
decrease UDMA xfer speed. if at UDMA0, switch to PIO4,
decrease PIO xfer speed. if at PIO3, complain, but continue
Table of Contents
ich_pata_cable_detect — Probe host controller cable detect info
int fsfuncich_pata_cable_detect ( | ap) ; |
struct ata_port * ap
;piix_pata_prereset — prereset for PATA host controller
int fsfuncpiix_pata_prereset ( | link, | |
deadline) ; |
struct ata_link * link
;unsigned long deadline
;piix_set_piomode — Initialize host controller PATA PIO timings
void fsfuncpiix_set_piomode ( | ap, | |
adev) ; |
struct ata_port * ap
;struct ata_device * adev
;do_pata_set_dmamode — Initialize host controller PATA PIO timings
void fsfuncdo_pata_set_dmamode ( | ap, | |
adev, | ||
isich) ; |
struct ata_port * ap
;struct ata_device * adev
;int isich
;piix_set_dmamode — Initialize host controller PATA DMA timings
void fsfuncpiix_set_dmamode ( | ap, | |
adev) ; |
struct ata_port * ap
;struct ata_device * adev
;ich_set_dmamode — Initialize host controller PATA DMA timings
void fsfuncich_set_dmamode ( | ap, | |
adev) ; |
struct ata_port * ap
;struct ata_device * adev
;piix_check_450nx_errata — Check for problem 450NX setup
int fsfuncpiix_check_450nx_errata ( | ata_dev) ; |
struct pci_dev * ata_dev
;piix_init_one — Register PIIX ATA PCI device with kernel services
int fsfuncpiix_init_one ( | pdev, | |
ent) ; |
struct pci_dev * pdev
;const struct pci_device_id * ent
;Table of Contents
sil_set_mode — wrap set_mode functions
int fsfuncsil_set_mode ( | link, | |
r_failed) ; |
struct ata_link * link
;struct ata_device ** r_failed
;sil_dev_config — Apply device/host-specific errata fixups
void fsfuncsil_dev_config ( | dev) ; |
struct ata_device * dev
;After the IDENTIFY [PACKET] DEVICE step is complete, and a device is known to be present, this function is called. We apply two errata fixups which are specific to Silicon Image, a Seagate and a Maxtor fixup.
For certain Seagate devices, we must limit the maximum sectors to under 8K.
For certain Maxtor devices, we must not program the drive beyond udma5.
Both fixups are unfairly pessimistic. As soon as I get more information on these errata, I will create a more exhaustive list, and apply the fixups to only the specific devices/hosts/firmwares that need it.
20040111 - Seagate drives affected by the Mod15Write bug are blacklisted The Maxtor quirk is in the blacklist, but I'm keeping the original pessimistic fix for the following reasons... - There seems to be less info on it, only one device gleaned off the Windows driver, maybe only one is affected. More info would be greatly appreciated. - But then again UDMA5 is hardly anything to complain about
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.
Thanks to Alan Cox for pointing out similarities between SATA and SCSI, and in general for motivation to hack on libata.
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).