Browse Source

Merge branch 'upstream' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev

Linus Torvalds 19 years ago
parent
commit
5fadd053d9

+ 1072 - 0
Documentation/DocBook/libata.tmpl

@@ -415,6 +415,362 @@ and other resources, etc.
      </sect1>
   </chapter>
 
+  <chapter id="libataEH">
+        <title>Error handling</title>
+
+	<para>
+	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.
+	</para>
+
+	<sect1><title>Origins of commands</title>
+	<para>
+	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.
+	</para>
+	<para>
+	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.
+	</para>
+	</sect1>
+
+	<sect1><title>How commands are issued</title>
+
+	<variablelist>
+
+	<varlistentry><term>Internal commands</term>
+	<listitem>
+	<para>
+	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.
+	</para>
+	<para>
+	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.
+	</para>
+	<para>
+	Once initialization is complete, host_set lock is acquired
+	and the qc is issued.
+	</para>
+	</listitem>
+	</varlistentry>
+
+	<varlistentry><term>SCSI commands</term>
+	<listitem>
+	<para>
+	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.
+	</para>
+	<para>
+	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.
+	</para>
+	<para>
+	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().
+	</para>
+	<para>
+	Note that SCSI midlayer invokes hostt->queuecommand while
+	holding host_set lock, so all above occur while holding
+	host_set lock.
+	</para>
+	</listitem>
+	</varlistentry>
+
+	</variablelist>
+	</sect1>
+
+	<sect1><title>How commands are processed</title>
+	<para>
+	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.
+	</para>
+	<para>
+	Currently 6 ATA command protocols are used.  They can be
+	sorted into the following four categories according to how
+	they are processed.
+	</para>
+
+	<variablelist>
+	   <varlistentry><term>ATA NO DATA or DMA</term>
+	   <listitem>
+	   <para>
+	   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.
+	   </para>
+	   </listitem>
+	   </varlistentry>
+
+	   <varlistentry><term>ATA PIO</term>
+	   <listitem>
+	   <para>
+	   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.
+	   </para>
+	   </listitem>
+	   </varlistentry>
+
+	   <varlistentry><term>ATAPI NODATA or DMA</term>
+	   <listitem>
+	   <para>
+	   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.
+	   </para>
+	   </listitem>
+	   </varlistentry>
+
+	   <varlistentry><term>ATAPI PIO</term>
+	   <listitem>
+	   <para>
+	   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.
+	   </para>
+	   </listitem>
+	   </varlistentry>
+	</variablelist>
+        </sect1>
+
+	<sect1><title>How commands are completed</title>
+	<para>
+	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.
+	</para>
+	<para>
+	ata_qc_complete() does the following.
+	</para>
+
+	<orderedlist>
+
+	<listitem>
+	<para>
+	DMA memory is unmapped.
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	ATA_QCFLAG_ACTIVE is clared from qc->flags.
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	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.
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	__ata_qc_complete() is called, which does
+	   <orderedlist>
+
+	   <listitem>
+	   <para>
+	   qc->flags is cleared to zero.
+	   </para>
+	   </listitem>
+
+	   <listitem>
+	   <para>
+	   ap->active_tag and qc->tag are poisoned.
+	   </para>
+	   </listitem>
+
+	   <listitem>
+	   <para>
+	   qc->waiting is claread &amp; completed (in that order).
+	   </para>
+	   </listitem>
+
+	   <listitem>
+	   <para>
+	   qc is deallocated by clearing appropriate bit in ap->qactive.
+	   </para>
+	   </listitem>
+
+	   </orderedlist>
+	</para>
+	</listitem>
+
+	</orderedlist>
+
+	<para>
+	So, it basically notifies upper layer and deallocates qc.  One
+	exception is short-circuit path in #3 which is used by
+	atapi_qc_complete().
+	</para>
+	<para>
+	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.
+	</para>
+	<para>
+	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.
+	</para>
+	<para>
+	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.
+	</para>
+
+	</sect1>
+
+	<sect1><title>ata_scsi_error()</title>
+	<para>
+	ata_scsi_error() is the current hostt->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().
+	</para>
+	<para>
+	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().
+	</para>
+	<para>
+	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.
+	</para>
+	<para>
+	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.
+	</para>
+
+	</sect1>
+
+	<sect1><title>Problems with the current EH</title>
+
+	<itemizedlist>
+
+	<listitem>
+	<para>
+	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.
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	When handling timeouts, no action is taken to make device
+	forget about the timed out command and ready for new commands.
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	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.
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	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.
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	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.
+	</para>
+	<para>
+	First, advanced error handling often requires context and
+	internal qc execution.
+	</para>
+	<para>
+	Second, even a simple failure (say, CRC error) needs
+	information gathering and could trigger complex error handling
+	(say, resetting &amp; reconfiguring).  Having multiple code
+	paths to gather information, enter EH and trigger actions
+	makes life painful.
+	</para>
+	<para>
+	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.
+	</para>
+	</listitem>
+
+	</itemizedlist>
+	</sect1>
+  </chapter>
+
   <chapter id="libataExt">
      <title>libata Library</title>
 !Edrivers/scsi/libata-core.c
@@ -431,6 +787,722 @@ and other resources, etc.
 !Idrivers/scsi/libata-scsi.c
   </chapter>
 
+  <chapter id="ataExceptions">
+     <title>ATA errors &amp; exceptions</title>
+
+  <para>
+  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.
+  </para>
+
+  <para>
+  The term 'error' is used to describe conditions where either an
+  explicit error condition is reported from device or a command has
+  timed out.
+  </para>
+
+  <para>
+  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.
+  </para>
+
+  <sect1 id="excat">
+     <title>Exception categories</title>
+     <para>
+     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.
+     </para>
+
+     <para>
+     In the following sections, two recovery actions - reset and
+     reconfiguring transport - are mentioned.  These are described
+     further in <xref linkend="exrec"/>.
+     </para>
+
+     <sect2 id="excatHSMviolation">
+        <title>HSM violation</title>
+        <para>
+        This error is indicated when STATUS value doesn't match HSM
+        requirement during issuing or excution any ATA/ATAPI command.
+        </para>
+
+	<itemizedlist>
+	<title>Examples</title>
+
+        <listitem>
+	<para>
+	ATA_STATUS doesn't contain !BSY &amp;&amp; DRDY &amp;&amp; !DRQ while trying
+	to issue a command.
+        </para>
+	</listitem>
+
+        <listitem>
+	<para>
+	!BSY &amp;&amp; !DRQ during PIO data transfer.
+        </para>
+	</listitem>
+
+        <listitem>
+	<para>
+	DRQ on command completion.
+        </para>
+	</listitem>
+
+        <listitem>
+	<para>
+	!BSY &amp;&amp; ERR after CDB tranfer starts but before the
+        last byte of CDB is transferred.  ATA/ATAPI standard states
+        that &quot;The device shall not terminate the PACKET command
+        with an error before the last byte of the command packet has
+        been written&quot; in the error outputs description of PACKET
+        command and the state diagram doesn't include such
+        transitions.
+	</para>
+	</listitem>
+
+	</itemizedlist>
+
+	<para>
+	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.
+	</para>
+
+	<para>
+	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.
+	</para>
+     </sect2>
+     
+     <sect2 id="excatDevErr">
+        <title>ATA/ATAPI device error (non-NCQ / non-CHECK CONDITION)</title>
+
+	<para>
+	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.
+	</para>
+
+	<para>
+	For ATA commands, this type of errors are indicated by !BSY
+	&amp;&amp; ERR during command execution and on completion.
+	</para>
+
+	<para>For ATAPI commands,</para>
+
+	<itemizedlist>
+
+	<listitem>
+	<para>
+	!BSY &amp;&amp; ERR &amp;&amp; ABRT right after issuing PACKET
+	indicates that PACKET command is not supported and falls in
+	this category.
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	!BSY &amp;&amp; ERR(==CHK) &amp;&amp; !ABRT after the last
+	byte of CDB is transferred indicates CHECK CONDITION and
+	doesn't fall in this category.
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	!BSY &amp;&amp; ERR(==CHK) &amp;&amp; ABRT after the last byte
+        of CDB is transferred *probably* indicates CHECK CONDITION and
+        doesn't fall in this category.
+	</para>
+	</listitem>
+
+	</itemizedlist>
+
+	<para>
+	Of errors detected as above, the followings are not ATA/ATAPI
+	device errors but ATA bus errors and should be handled
+	according to <xref linkend="excatATAbusErr"/>.
+	</para>
+
+	<variablelist>
+
+	   <varlistentry>
+	   <term>CRC error during data transfer</term>
+	   <listitem>
+	   <para>
+	   This is indicated by ICRC bit in the ERROR register and
+	   means that corruption occurred during data transfer.  Upto
+	   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.
+	   </para>
+	   </listitem>
+	   </varlistentry>
+
+	   <varlistentry>
+	   <term>ABRT error during data transfer or on completion</term>
+	   <listitem>
+	   <para>
+	   Upto 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 upto
+	   ATA/ATAPI-7, it seems to imply that ABRT bit alone could
+	   indicate tranfer errors.
+	   </para>
+	   <para>
+	   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.
+	   </para>
+	   </listitem>
+	   </varlistentry>
+
+	</variablelist>
+
+	<para>
+	ATA/ATAPI device errors can be further categorized as follows.
+	</para>
+
+	<variablelist>
+
+	   <varlistentry>
+	   <term>Media errors</term>
+	   <listitem>
+	   <para>
+	   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.
+	   </para>
+	   <para>
+	   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.
+	   </para>
+	   </listitem>
+	   </varlistentry>
+
+	   <varlistentry>
+	   <term>Media changed / media change requested error</term>
+	   <listitem>
+	   <para>
+	   &lt;&lt;TODO: fill here&gt;&gt;
+	   </para>
+	   </listitem>
+	   </varlistentry>
+
+	   <varlistentry><term>Address error</term>
+	   <listitem>
+	   <para>
+	   This is indicated by IDNF bit in the ERROR register.
+	   Report to upper layer.
+	   </para>
+	   </listitem>
+	   </varlistentry>
+
+	   <varlistentry><term>Other errors</term>
+	   <listitem>
+	   <para>
+	   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.
+	   </para>
+	   </listitem>
+	   </varlistentry>
+
+	</variablelist>
+
+	<para>
+	Depending on commands, not all STATUS/ERROR bits are
+	applicable.  These non-applicable bits are marked with
+	&quot;na&quot; in the output descriptions but upto ATA/ATAPI-7
+	no definition of &quot;na&quot; can be found.  However,
+	ATA/ATAPI-8 draft revision 1f describes &quot;N/A&quot; as
+	follows.
+	</para>
+
+	<blockquote>
+	<variablelist>
+	   <varlistentry><term>3.2.3.3a N/A</term>
+	   <listitem>
+	   <para>
+	   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.
+	   </para>
+	   </listitem>
+	   </varlistentry>
+	</variablelist>
+	</blockquote>
+
+	<para>
+	So, it seems reasonable to assume that &quot;na&quot; bits are
+	cleared to zero by devices and thus need no explicit masking.
+	</para>
+
+     </sect2>
+
+     <sect2 id="excatATAPIcc">
+        <title>ATAPI device CHECK CONDITION</title>
+
+	<para>
+	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.
+	</para>
+
+	<para>
+	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
+	&amp;&amp; ASC/ASCQ 47h/00h SCSI PARITY ERROR).  In such
+	cases, the error should be considered as an ATA bus error and
+	handled according to <xref linkend="excatATAbusErr"/>.
+	</para>
+
+     </sect2>
+
+     <sect2 id="excatNCQerr">
+        <title>ATA device error (NCQ)</title>
+
+	<para>
+	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.
+	</para>
+
+	<para>
+	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 <xref linkend="excatDevErr"/> 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.
+	</para>
+
+	<para>
+	Note that ATA bus errors can be reported as ATA device NCQ
+	errors.  This should be handled as described in <xref
+	linkend="excatATAbusErr"/>.
+	</para>
+
+	<para>
+	If READ LOG EXT Log Page 10h fails or reports NQ, we're
+	thoroughly screwed.  This condition should be treated
+	according to <xref linkend="excatHSMviolation"/>.
+	</para>
+
+     </sect2>
+
+     <sect2 id="excatATAbusErr">
+        <title>ATA bus error</title>
+
+	<para>
+	ATA bus error means that data corruption occurred during
+	transmission over ATA bus (SATA or PATA).  This type of errors
+	can be indicated by
+	</para>
+
+	<itemizedlist>
+
+	<listitem>
+	<para>
+	ICRC or ABRT error as described in <xref linkend="excatDevErr"/>.
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	Controller-specific error completion with error information
+	indicating transmission error.
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	On some controllers, command timeout.  In this case, there may
+	be a mechanism to determine that the timeout is due to
+	transmission error.
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	Unknown/random errors, timeouts and all sorts of weirdities.
+	</para>
+	</listitem>
+
+	</itemizedlist>
+
+	<para>
+	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.
+	</para>
+
+	<para>
+	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 <xref
+	linkend="exrecReconf"/> for more information.
+	</para>
+
+     </sect2>
+
+     <sect2 id="excatPCIbusErr">
+        <title>PCI bus error</title>
+
+	<para>
+	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.
+	</para>
+
+     </sect2>
+
+     <sect2 id="excatLateCompletion">
+        <title>Late completion</title>
+
+	<para>
+	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.
+	</para>
+
+     </sect2>
+
+     <sect2 id="excatUnknown">
+        <title>Unknown error (timeout)</title>
+
+	<para>
+	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.
+	</para>
+
+	<para>
+	Timeouts can also be caused by transmission errors.  Refer to
+	<xref linkend="excatATAbusErr"/> for more details.
+	</para>
+
+     </sect2>
+
+     <sect2 id="excatHoplugPM">
+        <title>Hotplug and power management exceptions</title>
+
+	<para>
+	&lt;&lt;TODO: fill here&gt;&gt;
+	</para>
+
+     </sect2>
+
+  </sect1>
+
+  <sect1 id="exrec">
+     <title>EH recovery actions</title>
+
+     <para>
+     This section discusses several important recovery actions.
+     </para>
+
+     <sect2 id="exrecClr">
+        <title>Clearing error condition</title>
+
+	<para>
+	Many controllers require its error registers to be cleared by
+	error handler.  Different controllers may have different
+	requirements.
+	</para>
+
+	<para>
+	For SATA, it's strongly recommended to clear at least SError
+	register during error handling.
+	</para>
+     </sect2>
+
+     <sect2 id="exrecRst">
+        <title>Reset</title>
+
+	<para>
+	During EH, resetting is necessary in the following cases.
+	</para>
+
+	<itemizedlist>
+
+	<listitem>
+	<para>
+	HSM is in unknown or invalid state
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	HBA is in unknown or invalid state
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	EH needs to make HBA/device forget about in-flight commands
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	HBA/device behaves weirdly
+	</para>
+	</listitem>
+
+	</itemizedlist>
+
+	<para>
+	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.
+	</para>
+
+	<itemizedlist>
+
+	<listitem>
+	<para>
+	When it's known that HBA is in ready state but ATA/ATAPI
+	device in in unknown state, reset only device.
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	If HBA is in unknown state, reset both HBA and device.
+	</para>
+	</listitem>
+
+	</itemizedlist>
+
+	<para>
+	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.
+	</para>
+
+	<para>
+	OTOH, ATA/ATAPI standard describes in detail ways to reset
+	ATA/ATAPI devices.
+	</para>
+
+	<variablelist>
+
+	   <varlistentry><term>PATA hardware reset</term>
+	   <listitem>
+	   <para>
+	   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.
+	   </para>
+	   </listitem>
+	   </varlistentry>
+
+	   <varlistentry><term>Software reset</term>
+	   <listitem>
+	   <para>
+	   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.
+	   </para>
+	   </listitem>
+	   </varlistentry>
+
+	   <varlistentry><term>EXECUTE DEVICE DIAGNOSTIC command</term>
+	   <listitem>
+	   <para>
+	   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.
+	   </para>
+	   <para>
+	   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.
+	   </para>
+	   </listitem>
+	   </varlistentry>
+
+	   <varlistentry><term>ATAPI DEVICE RESET command</term>
+	   <listitem>
+	   <para>
+	   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.
+	   </para>
+	   </listitem>
+	   </varlistentry>
+
+	   <varlistentry><term>SATA phy reset</term>
+	   <listitem>
+	   <para>
+	   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.
+	   </para>
+	   </listitem>
+	   </varlistentry>
+
+	</variablelist>
+
+	<para>
+	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.
+	</para>
+
+	<para>
+	Parameters affected are.
+	</para>
+
+	<itemizedlist>
+
+	<listitem>
+	<para>
+	CHS set up with INITIALIZE DEVICE PARAMETERS (seldomly used)
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	Parameters set with SET FEATURES including transfer mode setting
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	Block count set with SET MULTIPLE MODE
+	</para>
+	</listitem>
+
+	<listitem>
+	<para>
+	Other parameters (SET MAX, MEDIA LOCK...)
+	</para>
+	</listitem>
+
+	</itemizedlist>
+
+	<para>
+	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).
+	</para>
+
+	<para>
+	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.
+	</para>
+
+     </sect2>
+
+     <sect2 id="exrecReconf">
+        <title>Reconfigure transport</title>
+
+	<para>
+	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.
+	</para>
+
+	<para>
+	The following is a possible scheme Jeff Garzik suggested.
+	</para>
+
+	<blockquote>
+	<para>
+	If more than $N (3?) transmission errors happen in 15 minutes,
+	</para>	
+	<itemizedlist>
+	<listitem>
+	<para>
+	if SATA, decrease SATA PHY speed.  if speed cannot be decreased,
+	</para>
+	</listitem>
+	<listitem>
+	<para>
+	decrease UDMA xfer speed.  if at UDMA0, switch to PIO4,
+	</para>
+	</listitem>
+	<listitem>
+	<para>
+	decrease PIO xfer speed.  if at PIO3, complain, but continue
+	</para>
+	</listitem>
+	</itemizedlist>
+	</blockquote>
+
+     </sect2>
+
+  </sect1>
+
+  </chapter>
+
   <chapter id="PiixInt">
      <title>ata_piix Internals</title>
 !Idrivers/scsi/ata_piix.c

+ 19 - 3
drivers/scsi/Kconfig

@@ -489,11 +489,11 @@ config SCSI_SATA_NV
 
 	  If unsure, say N.
 
-config SCSI_SATA_PROMISE
-	tristate "Promise SATA TX2/TX4 support"
+config SCSI_PDC_ADMA
+	tristate "Pacific Digital ADMA support"
 	depends on SCSI_SATA && PCI
 	help
-	  This option enables support for Promise Serial ATA TX2/TX4.
+	  This option enables support for Pacific Digital ADMA controllers
 
 	  If unsure, say N.
 
@@ -505,6 +505,14 @@ config SCSI_SATA_QSTOR
 
 	  If unsure, say N.
 
+config SCSI_SATA_PROMISE
+	tristate "Promise SATA TX2/TX4 support"
+	depends on SCSI_SATA && PCI
+	help
+	  This option enables support for Promise Serial ATA TX2/TX4.
+
+	  If unsure, say N.
+
 config SCSI_SATA_SX4
 	tristate "Promise SATA SX4 support"
 	depends on SCSI_SATA && PCI && EXPERIMENTAL
@@ -521,6 +529,14 @@ config SCSI_SATA_SIL
 
 	  If unsure, say N.
 
+config SCSI_SATA_SIL24
+	tristate "Silicon Image 3124/3132 SATA support"
+	depends on SCSI_SATA && PCI && EXPERIMENTAL
+	help
+	  This option enables support for Silicon Image 3124/3132 Serial ATA.
+
+	  If unsure, say N.
+
 config SCSI_SATA_SIS
 	tristate "SiS 964/180 SATA support"
 	depends on SCSI_SATA && PCI && EXPERIMENTAL

+ 2 - 0
drivers/scsi/Makefile

@@ -130,6 +130,7 @@ obj-$(CONFIG_SCSI_ATA_PIIX)	+= libata.o ata_piix.o
 obj-$(CONFIG_SCSI_SATA_PROMISE)	+= libata.o sata_promise.o
 obj-$(CONFIG_SCSI_SATA_QSTOR)	+= libata.o sata_qstor.o
 obj-$(CONFIG_SCSI_SATA_SIL)	+= libata.o sata_sil.o
+obj-$(CONFIG_SCSI_SATA_SIL24)	+= libata.o sata_sil24.o
 obj-$(CONFIG_SCSI_SATA_VIA)	+= libata.o sata_via.o
 obj-$(CONFIG_SCSI_SATA_VITESSE)	+= libata.o sata_vsc.o
 obj-$(CONFIG_SCSI_SATA_SIS)	+= libata.o sata_sis.o
@@ -137,6 +138,7 @@ obj-$(CONFIG_SCSI_SATA_SX4)	+= libata.o sata_sx4.o
 obj-$(CONFIG_SCSI_SATA_NV)	+= libata.o sata_nv.o
 obj-$(CONFIG_SCSI_SATA_ULI)	+= libata.o sata_uli.o
 obj-$(CONFIG_SCSI_SATA_MV)	+= libata.o sata_mv.o
+obj-$(CONFIG_SCSI_PDC_ADMA)	+= libata.o pdc_adma.o
 
 obj-$(CONFIG_ARM)		+= arm/
 

+ 30 - 11
drivers/scsi/ahci.c

@@ -216,7 +216,7 @@ static Scsi_Host_Template ahci_sht = {
 	.ordered_flush		= 1,
 };
 
-static struct ata_port_operations ahci_ops = {
+static const struct ata_port_operations ahci_ops = {
 	.port_disable		= ata_port_disable,
 
 	.check_status		= ahci_check_status,
@@ -407,7 +407,7 @@ static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg_in)
 		return 0xffffffffU;
 	}
 
-	return readl((void *) ap->ioaddr.scr_addr + (sc_reg * 4));
+	return readl((void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
 }
 
 
@@ -425,7 +425,7 @@ static void ahci_scr_write (struct ata_port *ap, unsigned int sc_reg_in,
 		return;
 	}
 
-	writel(val, (void *) ap->ioaddr.scr_addr + (sc_reg * 4));
+	writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
 }
 
 static void ahci_phy_reset(struct ata_port *ap)
@@ -453,14 +453,14 @@ static void ahci_phy_reset(struct ata_port *ap)
 
 static u8 ahci_check_status(struct ata_port *ap)
 {
-	void *mmio = (void *) ap->ioaddr.cmd_addr;
+	void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr;
 
 	return readl(mmio + PORT_TFDATA) & 0xFF;
 }
 
 static u8 ahci_check_err(struct ata_port *ap)
 {
-	void *mmio = (void *) ap->ioaddr.cmd_addr;
+	void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr;
 
 	return (readl(mmio + PORT_TFDATA) >> 8) & 0xFF;
 }
@@ -672,17 +672,36 @@ static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *
 
         for (i = 0; i < host_set->n_ports; i++) {
 		struct ata_port *ap;
-		u32 tmp;
 
-		VPRINTK("port %u\n", i);
+		if (!(irq_stat & (1 << i)))
+			continue;
+
 		ap = host_set->ports[i];
-		tmp = irq_stat & (1 << i);
-		if (tmp && ap) {
+		if (ap) {
 			struct ata_queued_cmd *qc;
 			qc = ata_qc_from_tag(ap, ap->active_tag);
-			if (ahci_host_intr(ap, qc))
-				irq_ack |= (1 << i);
+			if (!ahci_host_intr(ap, qc))
+				if (ata_ratelimit()) {
+					struct pci_dev *pdev =
+					  to_pci_dev(ap->host_set->dev);
+					printk(KERN_WARNING
+					  "ahci(%s): unhandled interrupt on port %u\n",
+					  pci_name(pdev), i);
+				}
+
+			VPRINTK("port %u\n", i);
+		} else {
+			VPRINTK("port %u (no irq)\n", i);
+			if (ata_ratelimit()) {
+				struct pci_dev *pdev =
+				  to_pci_dev(ap->host_set->dev);
+				printk(KERN_WARNING
+				  "ahci(%s): interrupt on disabled port %u\n",
+				  pci_name(pdev), i);
+			}
 		}
+
+		irq_ack |= (1 << i);
 	}
 
 	if (irq_ack) {

+ 2 - 2
drivers/scsi/ata_piix.c

@@ -147,7 +147,7 @@ static Scsi_Host_Template piix_sht = {
 	.ordered_flush		= 1,
 };
 
-static struct ata_port_operations piix_pata_ops = {
+static const struct ata_port_operations piix_pata_ops = {
 	.port_disable		= ata_port_disable,
 	.set_piomode		= piix_set_piomode,
 	.set_dmamode		= piix_set_dmamode,
@@ -177,7 +177,7 @@ static struct ata_port_operations piix_pata_ops = {
 	.host_stop		= ata_host_stop,
 };
 
-static struct ata_port_operations piix_sata_ops = {
+static const struct ata_port_operations piix_sata_ops = {
 	.port_disable		= ata_port_disable,
 
 	.tf_load		= ata_tf_load,

File diff suppressed because it is too large
+ 443 - 158
drivers/scsi/libata-core.c


File diff suppressed because it is too large
+ 504 - 200
drivers/scsi/libata-scsi.c


+ 8 - 11
drivers/scsi/libata.h

@@ -39,18 +39,23 @@ struct ata_scsi_args {
 
 /* libata-core.c */
 extern int atapi_enabled;
+extern int ata_qc_complete_noop(struct ata_queued_cmd *qc, u8 drv_stat);
 extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
 				      struct ata_device *dev);
+extern void ata_rwcmd_protocol(struct ata_queued_cmd *qc);
 extern void ata_qc_free(struct ata_queued_cmd *qc);
 extern int ata_qc_issue(struct ata_queued_cmd *qc);
 extern int ata_check_atapi_dma(struct ata_queued_cmd *qc);
 extern void ata_dev_select(struct ata_port *ap, unsigned int device,
                            unsigned int wait, unsigned int can_sleep);
-extern void ata_tf_to_host_nolock(struct ata_port *ap, struct ata_taskfile *tf);
+extern void ata_tf_to_host_nolock(struct ata_port *ap, const struct ata_taskfile *tf);
 extern void swap_buf_le16(u16 *buf, unsigned int buf_words);
 
 
 /* libata-scsi.c */
+extern void atapi_request_sense(struct ata_port *ap, struct ata_device *dev,
+			 struct scsi_cmnd *cmd);
+extern void ata_scsi_scan_host(struct ata_port *ap);
 extern void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat);
 extern int ata_scsi_error(struct Scsi_Host *host);
 extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
@@ -76,18 +81,10 @@ extern unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf,
 extern void ata_scsi_badcmd(struct scsi_cmnd *cmd,
 			    void (*done)(struct scsi_cmnd *),
 			    u8 asc, u8 ascq);
+extern void ata_scsi_set_sense(struct scsi_cmnd *cmd,
+			       u8 sk, u8 asc, u8 ascq);
 extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
                         unsigned int (*actor) (struct ata_scsi_args *args,
                                            u8 *rbuf, unsigned int buflen));
 
-static inline void ata_bad_scsiop(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
-{
-	ata_scsi_badcmd(cmd, done, 0x20, 0x00);
-}
-
-static inline void ata_bad_cdb(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
-{
-	ata_scsi_badcmd(cmd, done, 0x24, 0x00);
-}
-
 #endif /* __LIBATA_H__ */

+ 739 - 0
drivers/scsi/pdc_adma.c

@@ -0,0 +1,739 @@
+/*
+ *  pdc_adma.c - Pacific Digital Corporation ADMA
+ *
+ *  Maintained by:  Mark Lord <mlord@pobox.com>
+ *
+ *  Copyright 2005 Mark Lord
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ *  libata documentation is available via 'make {ps|pdf}docs',
+ *  as Documentation/DocBook/libata.*
+ *
+ *
+ *  Supports ATA disks in single-packet ADMA mode.
+ *  Uses PIO for everything else.
+ *
+ *  TODO:  Use ADMA transfers for ATAPI devices, when possible.
+ *  This requires careful attention to a number of quirks of the chip.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include "scsi.h"
+#include <scsi/scsi_host.h>
+#include <asm/io.h>
+#include <linux/libata.h>
+
+#define DRV_NAME	"pdc_adma"
+#define DRV_VERSION	"0.01"
+
+/* macro to calculate base address for ATA regs */
+#define ADMA_ATA_REGS(base,port_no)	((base) + ((port_no) * 0x40))
+
+/* macro to calculate base address for ADMA regs */
+#define ADMA_REGS(base,port_no)	((base) + 0x80 + ((port_no) * 0x20))
+
+enum {
+	ADMA_PORTS		= 2,
+	ADMA_CPB_BYTES		= 40,
+	ADMA_PRD_BYTES		= LIBATA_MAX_PRD * 16,
+	ADMA_PKT_BYTES		= ADMA_CPB_BYTES + ADMA_PRD_BYTES,
+
+	ADMA_DMA_BOUNDARY	= 0xffffffff,
+
+	/* global register offsets */
+	ADMA_MODE_LOCK		= 0x00c7,
+
+	/* per-channel register offsets */
+	ADMA_CONTROL		= 0x0000, /* ADMA control */
+	ADMA_STATUS		= 0x0002, /* ADMA status */
+	ADMA_CPB_COUNT		= 0x0004, /* CPB count */
+	ADMA_CPB_CURRENT	= 0x000c, /* current CPB address */
+	ADMA_CPB_NEXT		= 0x000c, /* next CPB address */
+	ADMA_CPB_LOOKUP		= 0x0010, /* CPB lookup table */
+	ADMA_FIFO_IN		= 0x0014, /* input FIFO threshold */
+	ADMA_FIFO_OUT		= 0x0016, /* output FIFO threshold */
+
+	/* ADMA_CONTROL register bits */
+	aNIEN			= (1 << 8), /* irq mask: 1==masked */
+	aGO			= (1 << 7), /* packet trigger ("Go!") */
+	aRSTADM			= (1 << 5), /* ADMA logic reset */
+	aRSTA			= (1 << 2), /* ATA hard reset */
+	aPIOMD4			= 0x0003,   /* PIO mode 4 */
+
+	/* ADMA_STATUS register bits */
+	aPSD			= (1 << 6),
+	aUIRQ			= (1 << 4),
+	aPERR			= (1 << 0),
+
+	/* CPB bits */
+	cDONE			= (1 << 0),
+	cVLD			= (1 << 0),
+	cDAT			= (1 << 2),
+	cIEN			= (1 << 3),
+
+	/* PRD bits */
+	pORD			= (1 << 4),
+	pDIRO			= (1 << 5),
+	pEND			= (1 << 7),
+
+	/* ATA register flags */
+	rIGN			= (1 << 5),
+	rEND			= (1 << 7),
+
+	/* ATA register addresses */
+	ADMA_REGS_CONTROL	= 0x0e,
+	ADMA_REGS_SECTOR_COUNT	= 0x12,
+	ADMA_REGS_LBA_LOW	= 0x13,
+	ADMA_REGS_LBA_MID	= 0x14,
+	ADMA_REGS_LBA_HIGH	= 0x15,
+	ADMA_REGS_DEVICE	= 0x16,
+	ADMA_REGS_COMMAND	= 0x17,
+
+	/* PCI device IDs */
+	board_1841_idx		= 0,	/* ADMA 2-port controller */
+};
+
+typedef enum { adma_state_idle, adma_state_pkt, adma_state_mmio } adma_state_t;
+
+struct adma_port_priv {
+	u8			*pkt;
+	dma_addr_t		pkt_dma;
+	adma_state_t		state;
+};
+
+static int adma_ata_init_one (struct pci_dev *pdev,
+				const struct pci_device_id *ent);
+static irqreturn_t adma_intr (int irq, void *dev_instance,
+				struct pt_regs *regs);
+static int adma_port_start(struct ata_port *ap);
+static void adma_host_stop(struct ata_host_set *host_set);
+static void adma_port_stop(struct ata_port *ap);
+static void adma_phy_reset(struct ata_port *ap);
+static void adma_qc_prep(struct ata_queued_cmd *qc);
+static int adma_qc_issue(struct ata_queued_cmd *qc);
+static int adma_check_atapi_dma(struct ata_queued_cmd *qc);
+static void adma_bmdma_stop(struct ata_queued_cmd *qc);
+static u8 adma_bmdma_status(struct ata_port *ap);
+static void adma_irq_clear(struct ata_port *ap);
+static void adma_eng_timeout(struct ata_port *ap);
+
+static Scsi_Host_Template adma_ata_sht = {
+	.module			= THIS_MODULE,
+	.name			= DRV_NAME,
+	.ioctl			= ata_scsi_ioctl,
+	.queuecommand		= ata_scsi_queuecmd,
+	.eh_strategy_handler	= ata_scsi_error,
+	.can_queue		= ATA_DEF_QUEUE,
+	.this_id		= ATA_SHT_THIS_ID,
+	.sg_tablesize		= LIBATA_MAX_PRD,
+	.max_sectors		= ATA_MAX_SECTORS,
+	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+	.emulated		= ATA_SHT_EMULATED,
+	.use_clustering		= ENABLE_CLUSTERING,
+	.proc_name		= DRV_NAME,
+	.dma_boundary		= ADMA_DMA_BOUNDARY,
+	.slave_configure	= ata_scsi_slave_config,
+	.bios_param		= ata_std_bios_param,
+};
+
+static const struct ata_port_operations adma_ata_ops = {
+	.port_disable		= ata_port_disable,
+	.tf_load		= ata_tf_load,
+	.tf_read		= ata_tf_read,
+	.check_status		= ata_check_status,
+	.check_atapi_dma	= adma_check_atapi_dma,
+	.exec_command		= ata_exec_command,
+	.dev_select		= ata_std_dev_select,
+	.phy_reset		= adma_phy_reset,
+	.qc_prep		= adma_qc_prep,
+	.qc_issue		= adma_qc_issue,
+	.eng_timeout		= adma_eng_timeout,
+	.irq_handler		= adma_intr,
+	.irq_clear		= adma_irq_clear,
+	.port_start		= adma_port_start,
+	.port_stop		= adma_port_stop,
+	.host_stop		= adma_host_stop,
+	.bmdma_stop		= adma_bmdma_stop,
+	.bmdma_status		= adma_bmdma_status,
+};
+
+static struct ata_port_info adma_port_info[] = {
+	/* board_1841_idx */
+	{
+		.sht		= &adma_ata_sht,
+		.host_flags	= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST |
+				  ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO,
+		.pio_mask	= 0x10, /* pio4 */
+		.udma_mask	= 0x1f, /* udma0-4 */
+		.port_ops	= &adma_ata_ops,
+	},
+};
+
+static struct pci_device_id adma_ata_pci_tbl[] = {
+	{ PCI_VENDOR_ID_PDC, 0x1841, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_1841_idx },
+
+	{ }	/* terminate list */
+};
+
+static struct pci_driver adma_ata_pci_driver = {
+	.name			= DRV_NAME,
+	.id_table		= adma_ata_pci_tbl,
+	.probe			= adma_ata_init_one,
+	.remove			= ata_pci_remove_one,
+};
+
+static int adma_check_atapi_dma(struct ata_queued_cmd *qc)
+{
+	return 1;	/* ATAPI DMA not yet supported */
+}
+
+static void adma_bmdma_stop(struct ata_queued_cmd *qc)
+{
+	/* nothing */
+}
+
+static u8 adma_bmdma_status(struct ata_port *ap)
+{
+	return 0;
+}
+
+static void adma_irq_clear(struct ata_port *ap)
+{
+	/* nothing */
+}
+
+static void adma_reset_engine(void __iomem *chan)
+{
+	/* reset ADMA to idle state */
+	writew(aPIOMD4 | aNIEN | aRSTADM, chan + ADMA_CONTROL);
+	udelay(2);
+	writew(aPIOMD4, chan + ADMA_CONTROL);
+	udelay(2);
+}
+
+static void adma_reinit_engine(struct ata_port *ap)
+{
+	struct adma_port_priv *pp = ap->private_data;
+	void __iomem *mmio_base = ap->host_set->mmio_base;
+	void __iomem *chan = ADMA_REGS(mmio_base, ap->port_no);
+
+	/* mask/clear ATA interrupts */
+	writeb(ATA_NIEN, (void __iomem *)ap->ioaddr.ctl_addr);
+	ata_check_status(ap);
+
+	/* reset the ADMA engine */
+	adma_reset_engine(chan);
+
+	/* set in-FIFO threshold to 0x100 */
+	writew(0x100, chan + ADMA_FIFO_IN);
+
+	/* set CPB pointer */
+	writel((u32)pp->pkt_dma, chan + ADMA_CPB_NEXT);
+
+	/* set out-FIFO threshold to 0x100 */
+	writew(0x100, chan + ADMA_FIFO_OUT);
+
+	/* set CPB count */
+	writew(1, chan + ADMA_CPB_COUNT);
+
+	/* read/discard ADMA status */
+	readb(chan + ADMA_STATUS);
+}
+
+static inline void adma_enter_reg_mode(struct ata_port *ap)
+{
+	void __iomem *chan = ADMA_REGS(ap->host_set->mmio_base, ap->port_no);
+
+	writew(aPIOMD4, chan + ADMA_CONTROL);
+	readb(chan + ADMA_STATUS);	/* flush */
+}
+
+static void adma_phy_reset(struct ata_port *ap)
+{
+	struct adma_port_priv *pp = ap->private_data;
+
+	pp->state = adma_state_idle;
+	adma_reinit_engine(ap);
+	ata_port_probe(ap);
+	ata_bus_reset(ap);
+}
+
+static void adma_eng_timeout(struct ata_port *ap)
+{
+	struct adma_port_priv *pp = ap->private_data;
+
+	if (pp->state != adma_state_idle) /* healthy paranoia */
+		pp->state = adma_state_mmio;
+	adma_reinit_engine(ap);
+	ata_eng_timeout(ap);
+}
+
+static int adma_fill_sg(struct ata_queued_cmd *qc)
+{
+	struct scatterlist *sg = qc->sg;
+	struct ata_port *ap = qc->ap;
+	struct adma_port_priv *pp = ap->private_data;
+	u8  *buf = pp->pkt;
+	int nelem, i = (2 + buf[3]) * 8;
+	u8 pFLAGS = pORD | ((qc->tf.flags & ATA_TFLAG_WRITE) ? pDIRO : 0);
+
+	for (nelem = 0; nelem < qc->n_elem; nelem++,sg++) {
+		u32 addr;
+		u32 len;
+
+		addr = (u32)sg_dma_address(sg);
+		*(__le32 *)(buf + i) = cpu_to_le32(addr);
+		i += 4;
+
+		len = sg_dma_len(sg) >> 3;
+		*(__le32 *)(buf + i) = cpu_to_le32(len);
+		i += 4;
+
+		if ((nelem + 1) == qc->n_elem)
+			pFLAGS |= pEND;
+		buf[i++] = pFLAGS;
+		buf[i++] = qc->dev->dma_mode & 0xf;
+		buf[i++] = 0;	/* pPKLW */
+		buf[i++] = 0;	/* reserved */
+
+		*(__le32 *)(buf + i)
+			= (pFLAGS & pEND) ? 0 : cpu_to_le32(pp->pkt_dma + i + 4);
+		i += 4;
+
+		VPRINTK("PRD[%u] = (0x%lX, 0x%X)\n", nelem,
+					(unsigned long)addr, len);
+	}
+	return i;
+}
+
+static void adma_qc_prep(struct ata_queued_cmd *qc)
+{
+	struct adma_port_priv *pp = qc->ap->private_data;
+	u8  *buf = pp->pkt;
+	u32 pkt_dma = (u32)pp->pkt_dma;
+	int i = 0;
+
+	VPRINTK("ENTER\n");
+
+	adma_enter_reg_mode(qc->ap);
+	if (qc->tf.protocol != ATA_PROT_DMA) {
+		ata_qc_prep(qc);
+		return;
+	}
+
+	buf[i++] = 0;	/* Response flags */
+	buf[i++] = 0;	/* reserved */
+	buf[i++] = cVLD | cDAT | cIEN;
+	i++;		/* cLEN, gets filled in below */
+
+	*(__le32 *)(buf+i) = cpu_to_le32(pkt_dma);	/* cNCPB */
+	i += 4;		/* cNCPB */
+	i += 4;		/* cPRD, gets filled in below */
+
+	buf[i++] = 0;	/* reserved */
+	buf[i++] = 0;	/* reserved */
+	buf[i++] = 0;	/* reserved */
+	buf[i++] = 0;	/* reserved */
+
+	/* ATA registers; must be a multiple of 4 */
+	buf[i++] = qc->tf.device;
+	buf[i++] = ADMA_REGS_DEVICE;
+	if ((qc->tf.flags & ATA_TFLAG_LBA48)) {
+		buf[i++] = qc->tf.hob_nsect;
+		buf[i++] = ADMA_REGS_SECTOR_COUNT;
+		buf[i++] = qc->tf.hob_lbal;
+		buf[i++] = ADMA_REGS_LBA_LOW;
+		buf[i++] = qc->tf.hob_lbam;
+		buf[i++] = ADMA_REGS_LBA_MID;
+		buf[i++] = qc->tf.hob_lbah;
+		buf[i++] = ADMA_REGS_LBA_HIGH;
+	}
+	buf[i++] = qc->tf.nsect;
+	buf[i++] = ADMA_REGS_SECTOR_COUNT;
+	buf[i++] = qc->tf.lbal;
+	buf[i++] = ADMA_REGS_LBA_LOW;
+	buf[i++] = qc->tf.lbam;
+	buf[i++] = ADMA_REGS_LBA_MID;
+	buf[i++] = qc->tf.lbah;
+	buf[i++] = ADMA_REGS_LBA_HIGH;
+	buf[i++] = 0;
+	buf[i++] = ADMA_REGS_CONTROL;
+	buf[i++] = rIGN;
+	buf[i++] = 0;
+	buf[i++] = qc->tf.command;
+	buf[i++] = ADMA_REGS_COMMAND | rEND;
+
+	buf[3] = (i >> 3) - 2;				/* cLEN */
+	*(__le32 *)(buf+8) = cpu_to_le32(pkt_dma + i);	/* cPRD */
+
+	i = adma_fill_sg(qc);
+	wmb();	/* flush PRDs and pkt to memory */
+#if 0
+	/* dump out CPB + PRDs for debug */
+	{
+		int j, len = 0;
+		static char obuf[2048];
+		for (j = 0; j < i; ++j) {
+			len += sprintf(obuf+len, "%02x ", buf[j]);
+			if ((j & 7) == 7) {
+				printk("%s\n", obuf);
+				len = 0;
+			}
+		}
+		if (len)
+			printk("%s\n", obuf);
+	}
+#endif
+}
+
+static inline void adma_packet_start(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	void __iomem *chan = ADMA_REGS(ap->host_set->mmio_base, ap->port_no);
+
+	VPRINTK("ENTER, ap %p\n", ap);
+
+	/* fire up the ADMA engine */
+	writew(aPIOMD4 | aGO, chan + ADMA_CONTROL);
+}
+
+static int adma_qc_issue(struct ata_queued_cmd *qc)
+{
+	struct adma_port_priv *pp = qc->ap->private_data;
+
+	switch (qc->tf.protocol) {
+	case ATA_PROT_DMA:
+		pp->state = adma_state_pkt;
+		adma_packet_start(qc);
+		return 0;
+
+	case ATA_PROT_ATAPI_DMA:
+		BUG();
+		break;
+
+	default:
+		break;
+	}
+
+	pp->state = adma_state_mmio;
+	return ata_qc_issue_prot(qc);
+}
+
+static inline unsigned int adma_intr_pkt(struct ata_host_set *host_set)
+{
+	unsigned int handled = 0, port_no;
+	u8 __iomem *mmio_base = host_set->mmio_base;
+
+	for (port_no = 0; port_no < host_set->n_ports; ++port_no) {
+		struct ata_port *ap = host_set->ports[port_no];
+		struct adma_port_priv *pp;
+		struct ata_queued_cmd *qc;
+		void __iomem *chan = ADMA_REGS(mmio_base, port_no);
+		u8 drv_stat, status = readb(chan + ADMA_STATUS);
+
+		if (status == 0)
+			continue;
+		handled = 1;
+		adma_enter_reg_mode(ap);
+		if ((ap->flags & ATA_FLAG_PORT_DISABLED))
+			continue;
+		pp = ap->private_data;
+		if (!pp || pp->state != adma_state_pkt)
+			continue;
+		qc = ata_qc_from_tag(ap, ap->active_tag);
+		drv_stat = 0;
+		if ((status & (aPERR | aPSD | aUIRQ)))
+			drv_stat = ATA_ERR;
+		else if (pp->pkt[0] != cDONE)
+			drv_stat = ATA_ERR;
+		ata_qc_complete(qc, drv_stat);
+	}
+	return handled;
+}
+
+static inline unsigned int adma_intr_mmio(struct ata_host_set *host_set)
+{
+	unsigned int handled = 0, port_no;
+
+	for (port_no = 0; port_no < host_set->n_ports; ++port_no) {
+		struct ata_port *ap;
+		ap = host_set->ports[port_no];
+		if (ap && (!(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR)))) {
+			struct ata_queued_cmd *qc;
+			struct adma_port_priv *pp = ap->private_data;
+			if (!pp || pp->state != adma_state_mmio)
+				continue;
+			qc = ata_qc_from_tag(ap, ap->active_tag);
+			if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
+
+				/* check main status, clearing INTRQ */
+				u8 status = ata_chk_status(ap);
+				if ((status & ATA_BUSY))
+					continue;
+				DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n",
+					ap->id, qc->tf.protocol, status);
+		
+				/* complete taskfile transaction */
+				pp->state = adma_state_idle;
+				ata_qc_complete(qc, status);
+				handled = 1;
+			}
+		}
+	}
+	return handled;
+}
+
+static irqreturn_t adma_intr(int irq, void *dev_instance, struct pt_regs *regs)
+{
+	struct ata_host_set *host_set = dev_instance;
+	unsigned int handled = 0;
+
+	VPRINTK("ENTER\n");
+
+	spin_lock(&host_set->lock);
+	handled  = adma_intr_pkt(host_set) | adma_intr_mmio(host_set);
+	spin_unlock(&host_set->lock);
+
+	VPRINTK("EXIT\n");
+
+	return IRQ_RETVAL(handled);
+}
+
+static void adma_ata_setup_port(struct ata_ioports *port, unsigned long base)
+{
+	port->cmd_addr		=
+	port->data_addr		= base + 0x000;
+	port->error_addr	=
+	port->feature_addr	= base + 0x004;
+	port->nsect_addr	= base + 0x008;
+	port->lbal_addr		= base + 0x00c;
+	port->lbam_addr		= base + 0x010;
+	port->lbah_addr		= base + 0x014;
+	port->device_addr	= base + 0x018;
+	port->status_addr	=
+	port->command_addr	= base + 0x01c;
+	port->altstatus_addr	=
+	port->ctl_addr		= base + 0x038;
+}
+
+static int adma_port_start(struct ata_port *ap)
+{
+	struct device *dev = ap->host_set->dev;
+	struct adma_port_priv *pp;
+	int rc;
+
+	rc = ata_port_start(ap);
+	if (rc)
+		return rc;
+	adma_enter_reg_mode(ap);
+	rc = -ENOMEM;
+	pp = kcalloc(1, sizeof(*pp), GFP_KERNEL);
+	if (!pp)
+		goto err_out;
+	pp->pkt = dma_alloc_coherent(dev, ADMA_PKT_BYTES, &pp->pkt_dma,
+								GFP_KERNEL);
+	if (!pp->pkt)
+		goto err_out_kfree;
+	/* paranoia? */
+	if ((pp->pkt_dma & 7) != 0) {
+		printk("bad alignment for pp->pkt_dma: %08x\n",
+						(u32)pp->pkt_dma);
+		goto err_out_kfree2;
+	}
+	memset(pp->pkt, 0, ADMA_PKT_BYTES);
+	ap->private_data = pp;
+	adma_reinit_engine(ap);
+	return 0;
+
+err_out_kfree2:
+	kfree(pp);
+err_out_kfree:
+	kfree(pp);
+err_out:
+	ata_port_stop(ap);
+	return rc;
+}
+
+static void adma_port_stop(struct ata_port *ap)
+{
+	struct device *dev = ap->host_set->dev;
+	struct adma_port_priv *pp = ap->private_data;
+
+	adma_reset_engine(ADMA_REGS(ap->host_set->mmio_base, ap->port_no));
+	if (pp != NULL) {
+		ap->private_data = NULL;
+		if (pp->pkt != NULL)
+			dma_free_coherent(dev, ADMA_PKT_BYTES,
+					pp->pkt, pp->pkt_dma);
+		kfree(pp);
+	}
+	ata_port_stop(ap);
+}
+
+static void adma_host_stop(struct ata_host_set *host_set)
+{
+	unsigned int port_no;
+
+	for (port_no = 0; port_no < ADMA_PORTS; ++port_no)
+		adma_reset_engine(ADMA_REGS(host_set->mmio_base, port_no));
+
+	ata_pci_host_stop(host_set);
+}
+
+static void adma_host_init(unsigned int chip_id,
+				struct ata_probe_ent *probe_ent)
+{
+	unsigned int port_no;
+	void __iomem *mmio_base = probe_ent->mmio_base;
+
+	/* enable/lock aGO operation */
+	writeb(7, mmio_base + ADMA_MODE_LOCK);
+
+	/* reset the ADMA logic */
+	for (port_no = 0; port_no < ADMA_PORTS; ++port_no)
+		adma_reset_engine(ADMA_REGS(mmio_base, port_no));
+}
+
+static int adma_set_dma_masks(struct pci_dev *pdev, void __iomem *mmio_base)
+{
+	int rc;
+
+	rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+	if (rc) {
+		printk(KERN_ERR DRV_NAME
+			"(%s): 32-bit DMA enable failed\n",
+			pci_name(pdev));
+		return rc;
+	}
+	rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+	if (rc) {
+		printk(KERN_ERR DRV_NAME
+			"(%s): 32-bit consistent DMA enable failed\n",
+			pci_name(pdev));
+		return rc;
+	}
+	return 0;
+}
+
+static int adma_ata_init_one(struct pci_dev *pdev,
+				const struct pci_device_id *ent)
+{
+	static int printed_version;
+	struct ata_probe_ent *probe_ent = NULL;
+	void __iomem *mmio_base;
+	unsigned int board_idx = (unsigned int) ent->driver_data;
+	int rc, port_no;
+
+	if (!printed_version++)
+		printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+
+	rc = pci_enable_device(pdev);
+	if (rc)
+		return rc;
+
+	rc = pci_request_regions(pdev, DRV_NAME);
+	if (rc)
+		goto err_out;
+
+	if ((pci_resource_flags(pdev, 4) & IORESOURCE_MEM) == 0) {
+		rc = -ENODEV;
+		goto err_out_regions;
+	}
+
+	mmio_base = pci_iomap(pdev, 4, 0);
+	if (mmio_base == NULL) {
+		rc = -ENOMEM;
+		goto err_out_regions;
+	}
+
+	rc = adma_set_dma_masks(pdev, mmio_base);
+	if (rc)
+		goto err_out_iounmap;
+
+	probe_ent = kcalloc(1, sizeof(*probe_ent), GFP_KERNEL);
+	if (probe_ent == NULL) {
+		rc = -ENOMEM;
+		goto err_out_iounmap;
+	}
+
+	probe_ent->dev = pci_dev_to_dev(pdev);
+	INIT_LIST_HEAD(&probe_ent->node);
+
+	probe_ent->sht		= adma_port_info[board_idx].sht;
+	probe_ent->host_flags	= adma_port_info[board_idx].host_flags;
+	probe_ent->pio_mask	= adma_port_info[board_idx].pio_mask;
+	probe_ent->mwdma_mask	= adma_port_info[board_idx].mwdma_mask;
+	probe_ent->udma_mask	= adma_port_info[board_idx].udma_mask;
+	probe_ent->port_ops	= adma_port_info[board_idx].port_ops;
+
+	probe_ent->irq		= pdev->irq;
+	probe_ent->irq_flags	= SA_SHIRQ;
+	probe_ent->mmio_base	= mmio_base;
+	probe_ent->n_ports	= ADMA_PORTS;
+
+	for (port_no = 0; port_no < probe_ent->n_ports; ++port_no) {
+		adma_ata_setup_port(&probe_ent->port[port_no],
+			ADMA_ATA_REGS((unsigned long)mmio_base, port_no));
+	}
+
+	pci_set_master(pdev);
+
+	/* initialize adapter */
+	adma_host_init(board_idx, probe_ent);
+
+	rc = ata_device_add(probe_ent);
+	kfree(probe_ent);
+	if (rc != ADMA_PORTS)
+		goto err_out_iounmap;
+	return 0;
+
+err_out_iounmap:
+	pci_iounmap(pdev, mmio_base);
+err_out_regions:
+	pci_release_regions(pdev);
+err_out:
+	pci_disable_device(pdev);
+	return rc;
+}
+
+static int __init adma_ata_init(void)
+{
+	return pci_module_init(&adma_ata_pci_driver);
+}
+
+static void __exit adma_ata_exit(void)
+{
+	pci_unregister_driver(&adma_ata_pci_driver);
+}
+
+MODULE_AUTHOR("Mark Lord");
+MODULE_DESCRIPTION("Pacific Digital Corporation ADMA low-level driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, adma_ata_pci_tbl);
+MODULE_VERSION(DRV_VERSION);
+
+module_init(adma_ata_init);
+module_exit(adma_ata_exit);

File diff suppressed because it is too large
+ 676 - 97
drivers/scsi/sata_mv.c


+ 4 - 4
drivers/scsi/sata_nv.c

@@ -238,7 +238,7 @@ static Scsi_Host_Template nv_sht = {
 	.ordered_flush		= 1,
 };
 
-static struct ata_port_operations nv_ops = {
+static const struct ata_port_operations nv_ops = {
 	.port_disable		= ata_port_disable,
 	.tf_load		= ata_tf_load,
 	.tf_read		= ata_tf_read,
@@ -331,7 +331,7 @@ static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg)
 		return 0xffffffffU;
 
 	if (host->host_flags & NV_HOST_FLAGS_SCR_MMIO)
-		return readl((void*)ap->ioaddr.scr_addr + (sc_reg * 4));
+		return readl((void __iomem *)ap->ioaddr.scr_addr + (sc_reg * 4));
 	else
 		return inl(ap->ioaddr.scr_addr + (sc_reg * 4));
 }
@@ -345,7 +345,7 @@ static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
 		return;
 
 	if (host->host_flags & NV_HOST_FLAGS_SCR_MMIO)
-		writel(val, (void*)ap->ioaddr.scr_addr + (sc_reg * 4));
+		writel(val, (void __iomem *)ap->ioaddr.scr_addr + (sc_reg * 4));
 	else
 		outl(val, ap->ioaddr.scr_addr + (sc_reg * 4));
 }
@@ -405,7 +405,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 	rc = -ENOMEM;
 
 	ppi = &nv_port_info;
-	probe_ent = ata_pci_init_native_mode(pdev, &ppi);
+	probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
 	if (!probe_ent)
 		goto err_out_regions;
 

+ 13 - 13
drivers/scsi/sata_promise.c

@@ -87,8 +87,8 @@ static void pdc_port_stop(struct ata_port *ap);
 static void pdc_pata_phy_reset(struct ata_port *ap);
 static void pdc_sata_phy_reset(struct ata_port *ap);
 static void pdc_qc_prep(struct ata_queued_cmd *qc);
-static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf);
-static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf);
+static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
+static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
 static void pdc_irq_clear(struct ata_port *ap);
 static int pdc_qc_issue_prot(struct ata_queued_cmd *qc);
 
@@ -113,7 +113,7 @@ static Scsi_Host_Template pdc_ata_sht = {
 	.ordered_flush		= 1,
 };
 
-static struct ata_port_operations pdc_sata_ops = {
+static const struct ata_port_operations pdc_sata_ops = {
 	.port_disable		= ata_port_disable,
 	.tf_load		= pdc_tf_load_mmio,
 	.tf_read		= ata_tf_read,
@@ -136,7 +136,7 @@ static struct ata_port_operations pdc_sata_ops = {
 	.host_stop		= ata_pci_host_stop,
 };
 
-static struct ata_port_operations pdc_pata_ops = {
+static const struct ata_port_operations pdc_pata_ops = {
 	.port_disable		= ata_port_disable,
 	.tf_load		= pdc_tf_load_mmio,
 	.tf_read		= ata_tf_read,
@@ -324,7 +324,7 @@ static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
 {
 	if (sc_reg > SCR_CONTROL)
 		return 0xffffffffU;
-	return readl((void *) ap->ioaddr.scr_addr + (sc_reg * 4));
+	return readl((void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
 }
 
 
@@ -333,7 +333,7 @@ static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg,
 {
 	if (sc_reg > SCR_CONTROL)
 		return;
-	writel(val, (void *) ap->ioaddr.scr_addr + (sc_reg * 4));
+	writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
 }
 
 static void pdc_qc_prep(struct ata_queued_cmd *qc)
@@ -438,11 +438,11 @@ static inline unsigned int pdc_host_intr( struct ata_port *ap,
 		break;
 
         default:
-                ap->stats.idle_irq++;
-                break;
+		ap->stats.idle_irq++;
+		break;
         }
 
-        return handled;
+	return handled;
 }
 
 static void pdc_irq_clear(struct ata_port *ap)
@@ -523,8 +523,8 @@ static inline void pdc_packet_start(struct ata_queued_cmd *qc)
 
 	pp->pkt[2] = seq;
 	wmb();			/* flush PRD, pkt writes */
-	writel(pp->pkt_dma, (void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
-	readl((void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); /* flush */
+	writel(pp->pkt_dma, (void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
+	readl((void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); /* flush */
 }
 
 static int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
@@ -546,7 +546,7 @@ static int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
 	return ata_qc_issue_prot(qc);
 }
 
-static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
+static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
 {
 	WARN_ON (tf->protocol == ATA_PROT_DMA ||
 		 tf->protocol == ATA_PROT_NODATA);
@@ -554,7 +554,7 @@ static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
 }
 
 
-static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
+static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
 {
 	WARN_ON (tf->protocol == ATA_PROT_DMA ||
 		 tf->protocol == ATA_PROT_NODATA);

+ 5 - 3
drivers/scsi/sata_qstor.c

@@ -51,8 +51,6 @@ enum {
 	QS_PRD_BYTES		= QS_MAX_PRD * 16,
 	QS_PKT_BYTES		= QS_CPB_BYTES + QS_PRD_BYTES,
 
-	QS_DMA_BOUNDARY		= ~0UL,
-
 	/* global register offsets */
 	QS_HCF_CNFG3		= 0x0003, /* host configuration offset */
 	QS_HID_HPHY		= 0x0004, /* host physical interface info */
@@ -101,6 +99,10 @@ enum {
 	board_2068_idx		= 0,	/* QStor 4-port SATA/RAID */
 };
 
+enum {
+	QS_DMA_BOUNDARY		= ~0UL
+};
+
 typedef enum { qs_state_idle, qs_state_pkt, qs_state_mmio } qs_state_t;
 
 struct qs_port_priv {
@@ -145,7 +147,7 @@ static Scsi_Host_Template qs_ata_sht = {
 	.bios_param		= ata_std_bios_param,
 };
 
-static struct ata_port_operations qs_ata_ops = {
+static const struct ata_port_operations qs_ata_ops = {
 	.port_disable		= ata_port_disable,
 	.tf_load		= ata_tf_load,
 	.tf_read		= ata_tf_read,

+ 3 - 3
drivers/scsi/sata_sil.c

@@ -150,7 +150,7 @@ static Scsi_Host_Template sil_sht = {
 	.ordered_flush		= 1,
 };
 
-static struct ata_port_operations sil_ops = {
+static const struct ata_port_operations sil_ops = {
 	.port_disable		= ata_port_disable,
 	.dev_config		= sil_dev_config,
 	.tf_load		= ata_tf_load,
@@ -289,7 +289,7 @@ static inline unsigned long sil_scr_addr(struct ata_port *ap, unsigned int sc_re
 
 static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg)
 {
-	void *mmio = (void *) sil_scr_addr(ap, sc_reg);
+	void __iomem *mmio = (void __iomem *) sil_scr_addr(ap, sc_reg);
 	if (mmio)
 		return readl(mmio);
 	return 0xffffffffU;
@@ -297,7 +297,7 @@ static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg)
 
 static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
 {
-	void *mmio = (void *) sil_scr_addr(ap, sc_reg);
+	void *mmio = (void __iomem *) sil_scr_addr(ap, sc_reg);
 	if (mmio)
 		writel(val, mmio);
 }

+ 875 - 0
drivers/scsi/sata_sil24.c

@@ -0,0 +1,875 @@
+/*
+ * sata_sil24.c - Driver for Silicon Image 3124/3132 SATA-2 controllers
+ *
+ * Copyright 2005  Tejun Heo
+ *
+ * Based on preview driver from Silicon Image.
+ *
+ * NOTE: No NCQ/ATAPI support yet.  The preview driver didn't support
+ * NCQ nor ATAPI, and, unfortunately, I couldn't find out how to make
+ * those work.  Enabling those shouldn't be difficult.  Basic
+ * structure is all there (in libata-dev tree).  If you have any
+ * information about this hardware, please contact me or linux-ide.
+ * Info is needed on...
+ *
+ * - How to issue tagged commands and turn on sactive on issue accordingly.
+ * - Where to put an ATAPI command and how to tell the device to send it.
+ * - How to enable/use 64bit.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <scsi/scsi_host.h>
+#include "scsi.h"
+#include <linux/libata.h>
+#include <asm/io.h>
+
+#define DRV_NAME	"sata_sil24"
+#define DRV_VERSION	"0.22"	/* Silicon Image's preview driver was 0.10 */
+
+/*
+ * Port request block (PRB) 32 bytes
+ */
+struct sil24_prb {
+	u16	ctrl;
+	u16	prot;
+	u32	rx_cnt;
+	u8	fis[6 * 4];
+};
+
+/*
+ * Scatter gather entry (SGE) 16 bytes
+ */
+struct sil24_sge {
+	u64	addr;
+	u32	cnt;
+	u32	flags;
+};
+
+/*
+ * Port multiplier
+ */
+struct sil24_port_multiplier {
+	u32	diag;
+	u32	sactive;
+};
+
+enum {
+	/*
+	 * Global controller registers (128 bytes @ BAR0)
+	 */
+		/* 32 bit regs */
+	HOST_SLOT_STAT		= 0x00, /* 32 bit slot stat * 4 */
+	HOST_CTRL		= 0x40,
+	HOST_IRQ_STAT		= 0x44,
+	HOST_PHY_CFG		= 0x48,
+	HOST_BIST_CTRL		= 0x50,
+	HOST_BIST_PTRN		= 0x54,
+	HOST_BIST_STAT		= 0x58,
+	HOST_MEM_BIST_STAT	= 0x5c,
+	HOST_FLASH_CMD		= 0x70,
+		/* 8 bit regs */
+	HOST_FLASH_DATA		= 0x74,
+	HOST_TRANSITION_DETECT	= 0x75,
+	HOST_GPIO_CTRL		= 0x76,
+	HOST_I2C_ADDR		= 0x78, /* 32 bit */
+	HOST_I2C_DATA		= 0x7c,
+	HOST_I2C_XFER_CNT	= 0x7e,
+	HOST_I2C_CTRL		= 0x7f,
+
+	/* HOST_SLOT_STAT bits */
+	HOST_SSTAT_ATTN		= (1 << 31),
+
+	/*
+	 * Port registers
+	 * (8192 bytes @ +0x0000, +0x2000, +0x4000 and +0x6000 @ BAR2)
+	 */
+	PORT_REGS_SIZE		= 0x2000,
+	PORT_PRB		= 0x0000, /* (32 bytes PRB + 16 bytes SGEs * 6) * 31 (3968 bytes) */
+
+	PORT_PM			= 0x0f80, /* 8 bytes PM * 16 (128 bytes) */
+		/* 32 bit regs */
+	PORT_CTRL_STAT		= 0x1000, /* write: ctrl-set, read: stat */
+	PORT_CTRL_CLR		= 0x1004, /* write: ctrl-clear */
+	PORT_IRQ_STAT		= 0x1008, /* high: status, low: interrupt */
+	PORT_IRQ_ENABLE_SET	= 0x1010, /* write: enable-set */
+	PORT_IRQ_ENABLE_CLR	= 0x1014, /* write: enable-clear */
+	PORT_ACTIVATE_UPPER_ADDR= 0x101c,
+	PORT_EXEC_FIFO		= 0x1020, /* command execution fifo */
+	PORT_CMD_ERR		= 0x1024, /* command error number */
+	PORT_FIS_CFG		= 0x1028,
+	PORT_FIFO_THRES		= 0x102c,
+		/* 16 bit regs */
+	PORT_DECODE_ERR_CNT	= 0x1040,
+	PORT_DECODE_ERR_THRESH	= 0x1042,
+	PORT_CRC_ERR_CNT	= 0x1044,
+	PORT_CRC_ERR_THRESH	= 0x1046,
+	PORT_HSHK_ERR_CNT	= 0x1048,
+	PORT_HSHK_ERR_THRESH	= 0x104a,
+		/* 32 bit regs */
+	PORT_PHY_CFG		= 0x1050,
+	PORT_SLOT_STAT		= 0x1800,
+	PORT_CMD_ACTIVATE	= 0x1c00, /* 64 bit cmd activate * 31 (248 bytes) */
+	PORT_EXEC_DIAG		= 0x1e00, /* 32bit exec diag * 16 (64 bytes, 0-10 used on 3124) */
+	PORT_PSD_DIAG		= 0x1e40, /* 32bit psd diag * 16 (64 bytes, 0-8 used on 3124) */
+	PORT_SCONTROL		= 0x1f00,
+	PORT_SSTATUS		= 0x1f04,
+	PORT_SERROR		= 0x1f08,
+	PORT_SACTIVE		= 0x1f0c,
+
+	/* PORT_CTRL_STAT bits */
+	PORT_CS_PORT_RST	= (1 << 0), /* port reset */
+	PORT_CS_DEV_RST		= (1 << 1), /* device reset */
+	PORT_CS_INIT		= (1 << 2), /* port initialize */
+	PORT_CS_IRQ_WOC		= (1 << 3), /* interrupt write one to clear */
+	PORT_CS_RESUME		= (1 << 6), /* port resume */
+	PORT_CS_32BIT_ACTV	= (1 << 10), /* 32-bit activation */
+	PORT_CS_PM_EN		= (1 << 13), /* port multiplier enable */
+	PORT_CS_RDY		= (1 << 31), /* port ready to accept commands */
+
+	/* PORT_IRQ_STAT/ENABLE_SET/CLR */
+	/* bits[11:0] are masked */
+	PORT_IRQ_COMPLETE	= (1 << 0), /* command(s) completed */
+	PORT_IRQ_ERROR		= (1 << 1), /* command execution error */
+	PORT_IRQ_PORTRDY_CHG	= (1 << 2), /* port ready change */
+	PORT_IRQ_PWR_CHG	= (1 << 3), /* power management change */
+	PORT_IRQ_PHYRDY_CHG	= (1 << 4), /* PHY ready change */
+	PORT_IRQ_COMWAKE	= (1 << 5), /* COMWAKE received */
+	PORT_IRQ_UNK_FIS	= (1 << 6), /* Unknown FIS received */
+	PORT_IRQ_SDB_FIS	= (1 << 11), /* SDB FIS received */
+
+	/* bits[27:16] are unmasked (raw) */
+	PORT_IRQ_RAW_SHIFT	= 16,
+	PORT_IRQ_MASKED_MASK	= 0x7ff,
+	PORT_IRQ_RAW_MASK	= (0x7ff << PORT_IRQ_RAW_SHIFT),
+
+	/* ENABLE_SET/CLR specific, intr steering - 2 bit field */
+	PORT_IRQ_STEER_SHIFT	= 30,
+	PORT_IRQ_STEER_MASK	= (3 << PORT_IRQ_STEER_SHIFT),
+
+	/* PORT_CMD_ERR constants */
+	PORT_CERR_DEV		= 1, /* Error bit in D2H Register FIS */
+	PORT_CERR_SDB		= 2, /* Error bit in SDB FIS */
+	PORT_CERR_DATA		= 3, /* Error in data FIS not detected by dev */
+	PORT_CERR_SEND		= 4, /* Initial cmd FIS transmission failure */
+	PORT_CERR_INCONSISTENT	= 5, /* Protocol mismatch */
+	PORT_CERR_DIRECTION	= 6, /* Data direction mismatch */
+	PORT_CERR_UNDERRUN	= 7, /* Ran out of SGEs while writing */
+	PORT_CERR_OVERRUN	= 8, /* Ran out of SGEs while reading */
+	PORT_CERR_PKT_PROT	= 11, /* DIR invalid in 1st PIO setup of ATAPI */
+	PORT_CERR_SGT_BOUNDARY	= 16, /* PLD ecode 00 - SGT not on qword boundary */
+	PORT_CERR_SGT_TGTABRT	= 17, /* PLD ecode 01 - target abort */
+	PORT_CERR_SGT_MSTABRT	= 18, /* PLD ecode 10 - master abort */
+	PORT_CERR_SGT_PCIPERR	= 19, /* PLD ecode 11 - PCI parity err while fetching SGT */
+	PORT_CERR_CMD_BOUNDARY	= 24, /* ctrl[15:13] 001 - PRB not on qword boundary */
+	PORT_CERR_CMD_TGTABRT	= 25, /* ctrl[15:13] 010 - target abort */
+	PORT_CERR_CMD_MSTABRT	= 26, /* ctrl[15:13] 100 - master abort */
+	PORT_CERR_CMD_PCIPERR	= 27, /* ctrl[15:13] 110 - PCI parity err while fetching PRB */
+	PORT_CERR_XFR_UNDEF	= 32, /* PSD ecode 00 - undefined */
+	PORT_CERR_XFR_TGTABRT	= 33, /* PSD ecode 01 - target abort */
+	PORT_CERR_XFR_MSGABRT	= 34, /* PSD ecode 10 - master abort */
+	PORT_CERR_XFR_PCIPERR	= 35, /* PSD ecode 11 - PCI prity err during transfer */
+	PORT_CERR_SENDSERVICE	= 36, /* FIS received while sending service */
+
+	/*
+	 * Other constants
+	 */
+	SGE_TRM			= (1 << 31), /* Last SGE in chain */
+	PRB_SOFT_RST		= (1 << 7),  /* Soft reset request (ign BSY?) */
+
+	/* board id */
+	BID_SIL3124		= 0,
+	BID_SIL3132		= 1,
+	BID_SIL3131		= 2,
+
+	IRQ_STAT_4PORTS		= 0xf,
+};
+
+struct sil24_cmd_block {
+	struct sil24_prb prb;
+	struct sil24_sge sge[LIBATA_MAX_PRD];
+};
+
+/*
+ * ap->private_data
+ *
+ * The preview driver always returned 0 for status.  We emulate it
+ * here from the previous interrupt.
+ */
+struct sil24_port_priv {
+	struct sil24_cmd_block *cmd_block;	/* 32 cmd blocks */
+	dma_addr_t cmd_block_dma;		/* DMA base addr for them */
+	struct ata_taskfile tf;			/* Cached taskfile registers */
+};
+
+/* ap->host_set->private_data */
+struct sil24_host_priv {
+	void *host_base;	/* global controller control (128 bytes @BAR0) */
+	void *port_base;	/* port registers (4 * 8192 bytes @BAR2) */
+};
+
+static u8 sil24_check_status(struct ata_port *ap);
+static u8 sil24_check_err(struct ata_port *ap);
+static u32 sil24_scr_read(struct ata_port *ap, unsigned sc_reg);
+static void sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val);
+static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
+static void sil24_phy_reset(struct ata_port *ap);
+static void sil24_qc_prep(struct ata_queued_cmd *qc);
+static int sil24_qc_issue(struct ata_queued_cmd *qc);
+static void sil24_irq_clear(struct ata_port *ap);
+static void sil24_eng_timeout(struct ata_port *ap);
+static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+static int sil24_port_start(struct ata_port *ap);
+static void sil24_port_stop(struct ata_port *ap);
+static void sil24_host_stop(struct ata_host_set *host_set);
+static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
+
+static struct pci_device_id sil24_pci_tbl[] = {
+	{ 0x1095, 0x3124, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3124 },
+	{ 0x1095, 0x3132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3132 },
+	{ 0x1095, 0x3131, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3131 },
+	{ 0x1095, 0x3531, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3131 },
+	{ } /* terminate list */
+};
+
+static struct pci_driver sil24_pci_driver = {
+	.name			= DRV_NAME,
+	.id_table		= sil24_pci_tbl,
+	.probe			= sil24_init_one,
+	.remove			= ata_pci_remove_one, /* safe? */
+};
+
+static Scsi_Host_Template sil24_sht = {
+	.module			= THIS_MODULE,
+	.name			= DRV_NAME,
+	.ioctl			= ata_scsi_ioctl,
+	.queuecommand		= ata_scsi_queuecmd,
+	.eh_strategy_handler	= ata_scsi_error,
+	.can_queue		= ATA_DEF_QUEUE,
+	.this_id		= ATA_SHT_THIS_ID,
+	.sg_tablesize		= LIBATA_MAX_PRD,
+	.max_sectors		= ATA_MAX_SECTORS,
+	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+	.emulated		= ATA_SHT_EMULATED,
+	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+	.proc_name		= DRV_NAME,
+	.dma_boundary		= ATA_DMA_BOUNDARY,
+	.slave_configure	= ata_scsi_slave_config,
+	.bios_param		= ata_std_bios_param,
+	.ordered_flush		= 1, /* NCQ not supported yet */
+};
+
+static const struct ata_port_operations sil24_ops = {
+	.port_disable		= ata_port_disable,
+
+	.check_status		= sil24_check_status,
+	.check_altstatus	= sil24_check_status,
+	.check_err		= sil24_check_err,
+	.dev_select		= ata_noop_dev_select,
+
+	.tf_read		= sil24_tf_read,
+
+	.phy_reset		= sil24_phy_reset,
+
+	.qc_prep		= sil24_qc_prep,
+	.qc_issue		= sil24_qc_issue,
+
+	.eng_timeout		= sil24_eng_timeout,
+
+	.irq_handler		= sil24_interrupt,
+	.irq_clear		= sil24_irq_clear,
+
+	.scr_read		= sil24_scr_read,
+	.scr_write		= sil24_scr_write,
+
+	.port_start		= sil24_port_start,
+	.port_stop		= sil24_port_stop,
+	.host_stop		= sil24_host_stop,
+};
+
+/*
+ * Use bits 30-31 of host_flags to encode available port numbers.
+ * Current maxium is 4.
+ */
+#define SIL24_NPORTS2FLAG(nports)	((((unsigned)(nports) - 1) & 0x3) << 30)
+#define SIL24_FLAG2NPORTS(flag)		((((flag) >> 30) & 0x3) + 1)
+
+static struct ata_port_info sil24_port_info[] = {
+	/* sil_3124 */
+	{
+		.sht		= &sil24_sht,
+		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+				  ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO |
+				  ATA_FLAG_PIO_DMA | SIL24_NPORTS2FLAG(4),
+		.pio_mask	= 0x1f,			/* pio0-4 */
+		.mwdma_mask	= 0x07,			/* mwdma0-2 */
+		.udma_mask	= 0x3f,			/* udma0-5 */
+		.port_ops	= &sil24_ops,
+	},
+	/* sil_3132 */ 
+	{
+		.sht		= &sil24_sht,
+		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+				  ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO |
+				  ATA_FLAG_PIO_DMA | SIL24_NPORTS2FLAG(2),
+		.pio_mask	= 0x1f,			/* pio0-4 */
+		.mwdma_mask	= 0x07,			/* mwdma0-2 */
+		.udma_mask	= 0x3f,			/* udma0-5 */
+		.port_ops	= &sil24_ops,
+	},
+	/* sil_3131/sil_3531 */
+	{
+		.sht		= &sil24_sht,
+		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+				  ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO |
+				  ATA_FLAG_PIO_DMA | SIL24_NPORTS2FLAG(1),
+		.pio_mask	= 0x1f,			/* pio0-4 */
+		.mwdma_mask	= 0x07,			/* mwdma0-2 */
+		.udma_mask	= 0x3f,			/* udma0-5 */
+		.port_ops	= &sil24_ops,
+	},
+};
+
+static inline void sil24_update_tf(struct ata_port *ap)
+{
+	struct sil24_port_priv *pp = ap->private_data;
+	void *port = (void *)ap->ioaddr.cmd_addr;
+	struct sil24_prb *prb = port;
+
+	ata_tf_from_fis(prb->fis, &pp->tf);
+}
+
+static u8 sil24_check_status(struct ata_port *ap)
+{
+	struct sil24_port_priv *pp = ap->private_data;
+	return pp->tf.command;
+}
+
+static u8 sil24_check_err(struct ata_port *ap)
+{
+	struct sil24_port_priv *pp = ap->private_data;
+	return pp->tf.feature;
+}
+
+static int sil24_scr_map[] = {
+	[SCR_CONTROL]	= 0,
+	[SCR_STATUS]	= 1,
+	[SCR_ERROR]	= 2,
+	[SCR_ACTIVE]	= 3,
+};
+
+static u32 sil24_scr_read(struct ata_port *ap, unsigned sc_reg)
+{
+	void *scr_addr = (void *)ap->ioaddr.scr_addr;
+	if (sc_reg < ARRAY_SIZE(sil24_scr_map)) {
+		void *addr;
+		addr = scr_addr + sil24_scr_map[sc_reg] * 4;
+		return readl(scr_addr + sil24_scr_map[sc_reg] * 4);
+	}
+	return 0xffffffffU;
+}
+
+static void sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val)
+{
+	void *scr_addr = (void *)ap->ioaddr.scr_addr;
+	if (sc_reg < ARRAY_SIZE(sil24_scr_map)) {
+		void *addr;
+		addr = scr_addr + sil24_scr_map[sc_reg] * 4;
+		writel(val, scr_addr + sil24_scr_map[sc_reg] * 4);
+	}
+}
+
+static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+{
+	struct sil24_port_priv *pp = ap->private_data;
+	*tf = pp->tf;
+}
+
+static void sil24_phy_reset(struct ata_port *ap)
+{
+	__sata_phy_reset(ap);
+	/*
+	 * No ATAPI yet.  Just unconditionally indicate ATA device.
+	 * If ATAPI device is attached, it will fail ATA_CMD_ID_ATA
+	 * and libata core will ignore the device.
+	 */
+	if (!(ap->flags & ATA_FLAG_PORT_DISABLED))
+		ap->device[0].class = ATA_DEV_ATA;
+}
+
+static inline void sil24_fill_sg(struct ata_queued_cmd *qc,
+				 struct sil24_cmd_block *cb)
+{
+	struct scatterlist *sg = qc->sg;
+	struct sil24_sge *sge = cb->sge;
+	unsigned i;
+
+	for (i = 0; i < qc->n_elem; i++, sg++, sge++) {
+		sge->addr = cpu_to_le64(sg_dma_address(sg));
+		sge->cnt = cpu_to_le32(sg_dma_len(sg));
+		sge->flags = 0;
+		sge->flags = i < qc->n_elem - 1 ? 0 : cpu_to_le32(SGE_TRM);
+	}
+}
+
+static void sil24_qc_prep(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct sil24_port_priv *pp = ap->private_data;
+	struct sil24_cmd_block *cb = pp->cmd_block + qc->tag;
+	struct sil24_prb *prb = &cb->prb;
+
+	switch (qc->tf.protocol) {
+	case ATA_PROT_PIO:
+	case ATA_PROT_DMA:
+	case ATA_PROT_NODATA:
+		break;
+	default:
+		/* ATAPI isn't supported yet */
+		BUG();
+	}
+
+	ata_tf_to_fis(&qc->tf, prb->fis, 0);
+
+	if (qc->flags & ATA_QCFLAG_DMAMAP)
+		sil24_fill_sg(qc, cb);
+}
+
+static int sil24_qc_issue(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	void *port = (void *)ap->ioaddr.cmd_addr;
+	struct sil24_port_priv *pp = ap->private_data;
+	dma_addr_t paddr = pp->cmd_block_dma + qc->tag * sizeof(*pp->cmd_block);
+
+	writel((u32)paddr, port + PORT_CMD_ACTIVATE);
+	return 0;
+}
+
+static void sil24_irq_clear(struct ata_port *ap)
+{
+	/* unused */
+}
+
+static int __sil24_reset_controller(void *port)
+{
+	int cnt;
+	u32 tmp;
+
+	/* Reset controller state.  Is this correct? */
+	writel(PORT_CS_DEV_RST, port + PORT_CTRL_STAT);
+	readl(port + PORT_CTRL_STAT);	/* sync */
+
+	/* Max ~100ms */
+	for (cnt = 0; cnt < 1000; cnt++) {
+		udelay(100);
+		tmp = readl(port + PORT_CTRL_STAT);
+		if (!(tmp & PORT_CS_DEV_RST))
+			break;
+	}
+
+	if (tmp & PORT_CS_DEV_RST)
+		return -1;
+	return 0;
+}
+
+static void sil24_reset_controller(struct ata_port *ap)
+{
+	printk(KERN_NOTICE DRV_NAME
+	       " ata%u: resetting controller...\n", ap->id);
+	if (__sil24_reset_controller((void *)ap->ioaddr.cmd_addr))
+                printk(KERN_ERR DRV_NAME
+                       " ata%u: failed to reset controller\n", ap->id);
+}
+
+static void sil24_eng_timeout(struct ata_port *ap)
+{
+	struct ata_queued_cmd *qc;
+
+	qc = ata_qc_from_tag(ap, ap->active_tag);
+	if (!qc) {
+		printk(KERN_ERR "ata%u: BUG: tiemout without command\n",
+		       ap->id);
+		return;
+	}
+
+	/*
+	 * hack alert!  We cannot use the supplied completion
+	 * function from inside the ->eh_strategy_handler() thread.
+	 * libata is the only user of ->eh_strategy_handler() in
+	 * any kernel, so the default scsi_done() assumes it is
+	 * not being called from the SCSI EH.
+	 */
+	printk(KERN_ERR "ata%u: command timeout\n", ap->id);
+	qc->scsidone = scsi_finish_command;
+	ata_qc_complete(qc, ATA_ERR);
+
+	sil24_reset_controller(ap);
+}
+
+static void sil24_error_intr(struct ata_port *ap, u32 slot_stat)
+{
+	struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
+	struct sil24_port_priv *pp = ap->private_data;
+	void *port = (void *)ap->ioaddr.cmd_addr;
+	u32 irq_stat, cmd_err, sstatus, serror;
+
+	irq_stat = readl(port + PORT_IRQ_STAT);
+	writel(irq_stat, port + PORT_IRQ_STAT);		/* clear irq */
+
+	if (!(irq_stat & PORT_IRQ_ERROR)) {
+		/* ignore non-completion, non-error irqs for now */
+		printk(KERN_WARNING DRV_NAME
+		       "ata%u: non-error exception irq (irq_stat %x)\n",
+		       ap->id, irq_stat);
+		return;
+	}
+
+	cmd_err = readl(port + PORT_CMD_ERR);
+	sstatus = readl(port + PORT_SSTATUS);
+	serror = readl(port + PORT_SERROR);
+	if (serror)
+		writel(serror, port + PORT_SERROR);
+
+	printk(KERN_ERR DRV_NAME " ata%u: error interrupt on port%d\n"
+	       "  stat=0x%x irq=0x%x cmd_err=%d sstatus=0x%x serror=0x%x\n",
+	       ap->id, ap->port_no, slot_stat, irq_stat, cmd_err, sstatus, serror);
+
+	if (cmd_err == PORT_CERR_DEV || cmd_err == PORT_CERR_SDB) {
+		/*
+		 * Device is reporting error, tf registers are valid.
+		 */
+		sil24_update_tf(ap);
+	} else {
+		/*
+		 * Other errors.  libata currently doesn't have any
+		 * mechanism to report these errors.  Just turn on
+		 * ATA_ERR.
+		 */
+		pp->tf.command = ATA_ERR;
+	}
+
+	if (qc)
+		ata_qc_complete(qc, pp->tf.command);
+
+	sil24_reset_controller(ap);
+}
+
+static inline void sil24_host_intr(struct ata_port *ap)
+{
+	struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
+	void *port = (void *)ap->ioaddr.cmd_addr;
+	u32 slot_stat;
+
+	slot_stat = readl(port + PORT_SLOT_STAT);
+	if (!(slot_stat & HOST_SSTAT_ATTN)) {
+		struct sil24_port_priv *pp = ap->private_data;
+		/*
+		 * !HOST_SSAT_ATTN guarantees successful completion,
+		 * so reading back tf registers is unnecessary for
+		 * most commands.  TODO: read tf registers for
+		 * commands which require these values on successful
+		 * completion (EXECUTE DEVICE DIAGNOSTIC, CHECK POWER,
+		 * DEVICE RESET and READ PORT MULTIPLIER (any more?).
+		 */
+		sil24_update_tf(ap);
+
+		if (qc)
+			ata_qc_complete(qc, pp->tf.command);
+	} else
+		sil24_error_intr(ap, slot_stat);
+}
+
+static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
+{
+	struct ata_host_set *host_set = dev_instance;
+	struct sil24_host_priv *hpriv = host_set->private_data;
+	unsigned handled = 0;
+	u32 status;
+	int i;
+
+	status = readl(hpriv->host_base + HOST_IRQ_STAT);
+
+	if (status == 0xffffffff) {
+		printk(KERN_ERR DRV_NAME ": IRQ status == 0xffffffff, "
+		       "PCI fault or device removal?\n");
+		goto out;
+	}
+
+	if (!(status & IRQ_STAT_4PORTS))
+		goto out;
+
+	spin_lock(&host_set->lock);
+
+	for (i = 0; i < host_set->n_ports; i++)
+		if (status & (1 << i)) {
+			struct ata_port *ap = host_set->ports[i];
+			if (ap && !(ap->flags & ATA_FLAG_PORT_DISABLED)) {
+				sil24_host_intr(host_set->ports[i]);
+				handled++;
+			} else
+				printk(KERN_ERR DRV_NAME
+				       ": interrupt from disabled port %d\n", i);
+		}
+
+	spin_unlock(&host_set->lock);
+ out:
+	return IRQ_RETVAL(handled);
+}
+
+static int sil24_port_start(struct ata_port *ap)
+{
+	struct device *dev = ap->host_set->dev;
+	struct sil24_port_priv *pp;
+	struct sil24_cmd_block *cb;
+	size_t cb_size = sizeof(*cb);
+	dma_addr_t cb_dma;
+
+	pp = kmalloc(sizeof(*pp), GFP_KERNEL);
+	if (!pp)
+		return -ENOMEM;
+	memset(pp, 0, sizeof(*pp));
+
+	pp->tf.command = ATA_DRDY;
+
+	cb = dma_alloc_coherent(dev, cb_size, &cb_dma, GFP_KERNEL);
+	if (!cb) {
+		kfree(pp);
+		return -ENOMEM;
+	}
+	memset(cb, 0, cb_size);
+
+	pp->cmd_block = cb;
+	pp->cmd_block_dma = cb_dma;
+
+	ap->private_data = pp;
+
+	return 0;
+}
+
+static void sil24_port_stop(struct ata_port *ap)
+{
+	struct device *dev = ap->host_set->dev;
+	struct sil24_port_priv *pp = ap->private_data;
+	size_t cb_size = sizeof(*pp->cmd_block);
+
+	dma_free_coherent(dev, cb_size, pp->cmd_block, pp->cmd_block_dma);
+	kfree(pp);
+}
+
+static void sil24_host_stop(struct ata_host_set *host_set)
+{
+	struct sil24_host_priv *hpriv = host_set->private_data;
+
+	iounmap(hpriv->host_base);
+	iounmap(hpriv->port_base);
+	kfree(hpriv);
+}
+
+static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	static int printed_version = 0;
+	unsigned int board_id = (unsigned int)ent->driver_data;
+	struct ata_port_info *pinfo = &sil24_port_info[board_id];
+	struct ata_probe_ent *probe_ent = NULL;
+	struct sil24_host_priv *hpriv = NULL;
+	void *host_base = NULL, *port_base = NULL;
+	int i, rc;
+
+	if (!printed_version++)
+		printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+
+	rc = pci_enable_device(pdev);
+	if (rc)
+		return rc;
+
+	rc = pci_request_regions(pdev, DRV_NAME);
+	if (rc)
+		goto out_disable;
+
+	rc = -ENOMEM;
+	/* ioremap mmio registers */
+	host_base = ioremap(pci_resource_start(pdev, 0),
+			    pci_resource_len(pdev, 0));
+	if (!host_base)
+		goto out_free;
+	port_base = ioremap(pci_resource_start(pdev, 2),
+			    pci_resource_len(pdev, 2));
+	if (!port_base)
+		goto out_free;
+
+	/* allocate & init probe_ent and hpriv */
+	probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+	if (!probe_ent)
+		goto out_free;
+
+	hpriv = kmalloc(sizeof(*hpriv), GFP_KERNEL);
+	if (!hpriv)
+		goto out_free;
+
+	memset(probe_ent, 0, sizeof(*probe_ent));
+	probe_ent->dev = pci_dev_to_dev(pdev);
+	INIT_LIST_HEAD(&probe_ent->node);
+
+	probe_ent->sht		= pinfo->sht;
+	probe_ent->host_flags	= pinfo->host_flags;
+	probe_ent->pio_mask	= pinfo->pio_mask;
+	probe_ent->udma_mask	= pinfo->udma_mask;
+	probe_ent->port_ops	= pinfo->port_ops;
+	probe_ent->n_ports	= SIL24_FLAG2NPORTS(pinfo->host_flags);
+
+	probe_ent->irq = pdev->irq;
+	probe_ent->irq_flags = SA_SHIRQ;
+	probe_ent->mmio_base = port_base;
+	probe_ent->private_data = hpriv;
+
+	memset(hpriv, 0, sizeof(*hpriv));
+	hpriv->host_base = host_base;
+	hpriv->port_base = port_base;
+
+	/*
+	 * Configure the device
+	 */
+	/*
+	 * FIXME: This device is certainly 64-bit capable.  We just
+	 * don't know how to use it.  After fixing 32bit activation in
+	 * this function, enable 64bit masks here.
+	 */
+	rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+	if (rc) {
+		printk(KERN_ERR DRV_NAME "(%s): 32-bit DMA enable failed\n",
+		       pci_name(pdev));
+		goto out_free;
+	}
+	rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+	if (rc) {
+		printk(KERN_ERR DRV_NAME "(%s): 32-bit consistent DMA enable failed\n",
+		       pci_name(pdev));
+		goto out_free;
+	}
+
+	/* GPIO off */
+	writel(0, host_base + HOST_FLASH_CMD);
+
+	/* Mask interrupts during initialization */
+	writel(0, host_base + HOST_CTRL);
+
+	for (i = 0; i < probe_ent->n_ports; i++) {
+		void *port = port_base + i * PORT_REGS_SIZE;
+		unsigned long portu = (unsigned long)port;
+		u32 tmp;
+		int cnt;
+
+		probe_ent->port[i].cmd_addr = portu + PORT_PRB;
+		probe_ent->port[i].scr_addr = portu + PORT_SCONTROL;
+
+		ata_std_ports(&probe_ent->port[i]);
+
+		/* Initial PHY setting */
+		writel(0x20c, port + PORT_PHY_CFG);
+
+		/* Clear port RST */
+		tmp = readl(port + PORT_CTRL_STAT);
+		if (tmp & PORT_CS_PORT_RST) {
+			writel(PORT_CS_PORT_RST, port + PORT_CTRL_CLR);
+			readl(port + PORT_CTRL_STAT);	/* sync */
+			for (cnt = 0; cnt < 10; cnt++) {
+				msleep(10);
+				tmp = readl(port + PORT_CTRL_STAT);
+				if (!(tmp & PORT_CS_PORT_RST))
+					break;
+			}
+			if (tmp & PORT_CS_PORT_RST)
+				printk(KERN_ERR DRV_NAME
+				       "(%s): failed to clear port RST\n",
+				       pci_name(pdev));
+		}
+
+		/* Zero error counters. */
+		writel(0x8000, port + PORT_DECODE_ERR_THRESH);
+		writel(0x8000, port + PORT_CRC_ERR_THRESH);
+		writel(0x8000, port + PORT_HSHK_ERR_THRESH);
+		writel(0x0000, port + PORT_DECODE_ERR_CNT);
+		writel(0x0000, port + PORT_CRC_ERR_CNT);
+		writel(0x0000, port + PORT_HSHK_ERR_CNT);
+
+		/* FIXME: 32bit activation? */
+		writel(0, port + PORT_ACTIVATE_UPPER_ADDR);
+		writel(PORT_CS_32BIT_ACTV, port + PORT_CTRL_STAT);
+
+		/* Configure interrupts */
+		writel(0xffff, port + PORT_IRQ_ENABLE_CLR);
+		writel(PORT_IRQ_COMPLETE | PORT_IRQ_ERROR | PORT_IRQ_SDB_FIS,
+		       port + PORT_IRQ_ENABLE_SET);
+
+		/* Clear interrupts */
+		writel(0x0fff0fff, port + PORT_IRQ_STAT);
+		writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_CLR);
+
+		/* Clear port multiplier enable and resume bits */
+		writel(PORT_CS_PM_EN | PORT_CS_RESUME, port + PORT_CTRL_CLR);
+
+		/* Reset itself */
+		if (__sil24_reset_controller(port))
+			printk(KERN_ERR DRV_NAME
+			       "(%s): failed to reset controller\n",
+			       pci_name(pdev));
+	}
+
+	/* Turn on interrupts */
+	writel(IRQ_STAT_4PORTS, host_base + HOST_CTRL);
+
+	pci_set_master(pdev);
+
+	/* FIXME: check ata_device_add return value */
+	ata_device_add(probe_ent);
+
+	kfree(probe_ent);
+	return 0;
+
+ out_free:
+	if (host_base)
+		iounmap(host_base);
+	if (port_base)
+		iounmap(port_base);
+	kfree(probe_ent);
+	kfree(hpriv);
+	pci_release_regions(pdev);
+ out_disable:
+	pci_disable_device(pdev);
+	return rc;
+}
+
+static int __init sil24_init(void)
+{
+	return pci_module_init(&sil24_pci_driver);
+}
+
+static void __exit sil24_exit(void)
+{
+	pci_unregister_driver(&sil24_pci_driver);
+}
+
+MODULE_AUTHOR("Tejun Heo");
+MODULE_DESCRIPTION("Silicon Image 3124/3132 SATA low-level driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, sil24_pci_tbl);
+
+module_init(sil24_init);
+module_exit(sil24_exit);

+ 2 - 2
drivers/scsi/sata_sis.c

@@ -102,7 +102,7 @@ static Scsi_Host_Template sis_sht = {
 	.ordered_flush		= 1,
 };
 
-static struct ata_port_operations sis_ops = {
+static const struct ata_port_operations sis_ops = {
 	.port_disable		= ata_port_disable,
 	.tf_load		= ata_tf_load,
 	.tf_read		= ata_tf_read,
@@ -263,7 +263,7 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 		goto err_out_regions;
 
 	ppi = &sis_port_info;
-	probe_ent = ata_pci_init_native_mode(pdev, &ppi);
+	probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
 	if (!probe_ent) {
 		rc = -ENOMEM;
 		goto err_out_regions;

+ 2 - 2
drivers/scsi/sata_svw.c

@@ -102,7 +102,7 @@ static void k2_sata_scr_write (struct ata_port *ap, unsigned int sc_reg,
 }
 
 
-static void k2_sata_tf_load(struct ata_port *ap, struct ata_taskfile *tf)
+static void k2_sata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
 {
 	struct ata_ioports *ioaddr = &ap->ioaddr;
 	unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
@@ -297,7 +297,7 @@ static Scsi_Host_Template k2_sata_sht = {
 };
 
 
-static struct ata_port_operations k2_sata_ops = {
+static const struct ata_port_operations k2_sata_ops = {
 	.port_disable		= ata_port_disable,
 	.tf_load		= k2_sata_tf_load,
 	.tf_read		= k2_sata_tf_read,

+ 14 - 15
drivers/scsi/sata_sx4.c

@@ -137,7 +137,7 @@ struct pdc_port_priv {
 };
 
 struct pdc_host_priv {
-	void			*dimm_mmio;
+	void			__iomem *dimm_mmio;
 
 	unsigned int		doing_hdma;
 	unsigned int		hdma_prod;
@@ -157,8 +157,8 @@ static void pdc_20621_phy_reset (struct ata_port *ap);
 static int pdc_port_start(struct ata_port *ap);
 static void pdc_port_stop(struct ata_port *ap);
 static void pdc20621_qc_prep(struct ata_queued_cmd *qc);
-static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf);
-static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf);
+static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
+static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
 static void pdc20621_host_stop(struct ata_host_set *host_set);
 static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe);
 static int pdc20621_detect_dimm(struct ata_probe_ent *pe);
@@ -196,7 +196,7 @@ static Scsi_Host_Template pdc_sata_sht = {
 	.ordered_flush		= 1,
 };
 
-static struct ata_port_operations pdc_20621_ops = {
+static const struct ata_port_operations pdc_20621_ops = {
 	.port_disable		= ata_port_disable,
 	.tf_load		= pdc_tf_load_mmio,
 	.tf_read		= ata_tf_read,
@@ -247,7 +247,7 @@ static void pdc20621_host_stop(struct ata_host_set *host_set)
 {
 	struct pci_dev *pdev = to_pci_dev(host_set->dev);
 	struct pdc_host_priv *hpriv = host_set->private_data;
-	void *dimm_mmio = hpriv->dimm_mmio;
+	void __iomem *dimm_mmio = hpriv->dimm_mmio;
 
 	pci_iounmap(pdev, dimm_mmio);
 	kfree(hpriv);
@@ -669,8 +669,8 @@ static void pdc20621_packet_start(struct ata_queued_cmd *qc)
 		readl(mmio + PDC_20621_SEQCTL + (seq * 4));	/* flush */
 
 		writel(port_ofs + PDC_DIMM_ATA_PKT,
-		       (void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
-		readl((void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
+		       (void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
+		readl((void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
 		VPRINTK("submitted ofs 0x%x (%u), seq %u\n",
 			port_ofs + PDC_DIMM_ATA_PKT,
 			port_ofs + PDC_DIMM_ATA_PKT,
@@ -747,8 +747,8 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
 			writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4));
 			readl(mmio + PDC_20621_SEQCTL + (seq * 4));
 			writel(port_ofs + PDC_DIMM_ATA_PKT,
-			       (void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
-			readl((void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
+			       (void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
+			readl((void __iomem *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
 		}
 
 		/* step two - execute ATA command */
@@ -899,7 +899,7 @@ out:
 	DPRINTK("EXIT\n");
 }
 
-static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
+static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
 {
 	WARN_ON (tf->protocol == ATA_PROT_DMA ||
 		 tf->protocol == ATA_PROT_NODATA);
@@ -907,7 +907,7 @@ static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
 }
 
 
-static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
+static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
 {
 	WARN_ON (tf->protocol == ATA_PROT_DMA ||
 		 tf->protocol == ATA_PROT_NODATA);
@@ -1014,7 +1014,7 @@ static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource,
 	idx++;
 	dist = ((long)(s32)(window_size - (offset + size))) >= 0 ? size :
 		(long) (window_size - offset);
-	memcpy_toio((char *) (dimm_mmio + offset / 4), (char *) psource, dist);
+	memcpy_toio(dimm_mmio + offset / 4, psource, dist);
 	writel(0x01, mmio + PDC_GENERAL_CTLR);
 	readl(mmio + PDC_GENERAL_CTLR);
 
@@ -1023,8 +1023,7 @@ static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource,
 	for (; (long) size >= (long) window_size ;) {
 		writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
 		readl(mmio + PDC_DIMM_WINDOW_CTLR);
-		memcpy_toio((char *) (dimm_mmio), (char *) psource,
-			    window_size / 4);
+		memcpy_toio(dimm_mmio, psource, window_size / 4);
 		writel(0x01, mmio + PDC_GENERAL_CTLR);
 		readl(mmio + PDC_GENERAL_CTLR);
 		psource += window_size;
@@ -1035,7 +1034,7 @@ static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource,
 	if (size) {
 		writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
 		readl(mmio + PDC_DIMM_WINDOW_CTLR);
-		memcpy_toio((char *) (dimm_mmio), (char *) psource, size / 4);
+		memcpy_toio(dimm_mmio, psource, size / 4);
 		writel(0x01, mmio + PDC_GENERAL_CTLR);
 		readl(mmio + PDC_GENERAL_CTLR);
 	}

+ 2 - 2
drivers/scsi/sata_uli.c

@@ -90,7 +90,7 @@ static Scsi_Host_Template uli_sht = {
 	.ordered_flush		= 1,
 };
 
-static struct ata_port_operations uli_ops = {
+static const struct ata_port_operations uli_ops = {
 	.port_disable		= ata_port_disable,
 
 	.tf_load		= ata_tf_load,
@@ -202,7 +202,7 @@ static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 		goto err_out_regions;
 
 	ppi = &uli_port_info;
-	probe_ent = ata_pci_init_native_mode(pdev, &ppi);
+	probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
 	if (!probe_ent) {
 		rc = -ENOMEM;
 		goto err_out_regions;

+ 2 - 2
drivers/scsi/sata_via.c

@@ -109,7 +109,7 @@ static Scsi_Host_Template svia_sht = {
 	.ordered_flush		= 1,
 };
 
-static struct ata_port_operations svia_sata_ops = {
+static const struct ata_port_operations svia_sata_ops = {
 	.port_disable		= ata_port_disable,
 
 	.tf_load		= ata_tf_load,
@@ -212,7 +212,7 @@ static struct ata_probe_ent *vt6420_init_probe_ent(struct pci_dev *pdev)
 	struct ata_probe_ent *probe_ent;
 	struct ata_port_info *ppi = &svia_port_info;
 
-	probe_ent = ata_pci_init_native_mode(pdev, &ppi);
+	probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
 	if (!probe_ent)
 		return NULL;
 

+ 7 - 7
drivers/scsi/sata_vsc.c

@@ -86,7 +86,7 @@ static u32 vsc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
 {
 	if (sc_reg > SCR_CONTROL)
 		return 0xffffffffU;
-	return readl((void *) ap->ioaddr.scr_addr + (sc_reg * 4));
+	return readl((void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
 }
 
 
@@ -95,16 +95,16 @@ static void vsc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg,
 {
 	if (sc_reg > SCR_CONTROL)
 		return;
-	writel(val, (void *) ap->ioaddr.scr_addr + (sc_reg * 4));
+	writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
 }
 
 
 static void vsc_intr_mask_update(struct ata_port *ap, u8 ctl)
 {
-	unsigned long mask_addr;
+	void __iomem *mask_addr;
 	u8 mask;
 
-	mask_addr = (unsigned long) ap->host_set->mmio_base +
+	mask_addr = ap->host_set->mmio_base +
 		VSC_SATA_INT_MASK_OFFSET + ap->port_no;
 	mask = readb(mask_addr);
 	if (ctl & ATA_NIEN)
@@ -115,7 +115,7 @@ static void vsc_intr_mask_update(struct ata_port *ap, u8 ctl)
 }
 
 
-static void vsc_sata_tf_load(struct ata_port *ap, struct ata_taskfile *tf)
+static void vsc_sata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
 {
 	struct ata_ioports *ioaddr = &ap->ioaddr;
 	unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
@@ -231,7 +231,7 @@ static Scsi_Host_Template vsc_sata_sht = {
 };
 
 
-static struct ata_port_operations vsc_sata_ops = {
+static const struct ata_port_operations vsc_sata_ops = {
 	.port_disable		= ata_port_disable,
 	.tf_load		= vsc_sata_tf_load,
 	.tf_read		= vsc_sata_tf_read,
@@ -283,7 +283,7 @@ static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_d
 	struct ata_probe_ent *probe_ent = NULL;
 	unsigned long base;
 	int pci_dev_busy = 0;
-	void *mmio_base;
+	void __iomem *mmio_base;
 	int rc;
 
 	if (!printed_version++)

+ 32 - 9
include/linux/ata.h

@@ -42,13 +42,18 @@ enum {
 	ATA_SECT_SIZE		= 512,
 
 	ATA_ID_WORDS		= 256,
-	ATA_ID_PROD_OFS		= 27,
-	ATA_ID_FW_REV_OFS	= 23,
 	ATA_ID_SERNO_OFS	= 10,
-	ATA_ID_MAJOR_VER	= 80,
-	ATA_ID_PIO_MODES	= 64,
+	ATA_ID_FW_REV_OFS	= 23,
+	ATA_ID_PROD_OFS		= 27,
+	ATA_ID_OLD_PIO_MODES	= 51,
+	ATA_ID_FIELD_VALID	= 53,
 	ATA_ID_MWDMA_MODES	= 63,
+	ATA_ID_PIO_MODES	= 64,
+	ATA_ID_EIDE_DMA_MIN	= 65,
+	ATA_ID_EIDE_PIO		= 67,
+	ATA_ID_EIDE_PIO_IORDY	= 68,
 	ATA_ID_UDMA_MODES	= 88,
+	ATA_ID_MAJOR_VER	= 80,
 	ATA_ID_PIO4		= (1 << 1),
 
 	ATA_PCI_CTL_OFS		= 2,
@@ -128,10 +133,15 @@ enum {
 	ATA_CMD_PIO_READ_EXT	= 0x24,
 	ATA_CMD_PIO_WRITE	= 0x30,
 	ATA_CMD_PIO_WRITE_EXT	= 0x34,
+	ATA_CMD_READ_MULTI	= 0xC4,
+	ATA_CMD_READ_MULTI_EXT	= 0x29,
+	ATA_CMD_WRITE_MULTI	= 0xC5,
+	ATA_CMD_WRITE_MULTI_EXT	= 0x39,
 	ATA_CMD_SET_FEATURES	= 0xEF,
 	ATA_CMD_PACKET		= 0xA0,
 	ATA_CMD_VERIFY		= 0x40,
 	ATA_CMD_VERIFY_EXT	= 0x42,
+	ATA_CMD_INIT_DEV_PARAMS	= 0x91,
 
 	/* SETFEATURES stuff */
 	SETFEATURES_XFER	= 0x03,
@@ -146,14 +156,14 @@ enum {
 	XFER_MW_DMA_2		= 0x22,
 	XFER_MW_DMA_1		= 0x21,
 	XFER_MW_DMA_0		= 0x20,
+	XFER_SW_DMA_2		= 0x12,
+	XFER_SW_DMA_1		= 0x11,
+	XFER_SW_DMA_0		= 0x10,
 	XFER_PIO_4		= 0x0C,
 	XFER_PIO_3		= 0x0B,
 	XFER_PIO_2		= 0x0A,
 	XFER_PIO_1		= 0x09,
 	XFER_PIO_0		= 0x08,
-	XFER_SW_DMA_2		= 0x12,
-	XFER_SW_DMA_1		= 0x11,
-	XFER_SW_DMA_0		= 0x10,
 	XFER_PIO_SLOW		= 0x00,
 
 	/* ATAPI stuff */
@@ -181,6 +191,7 @@ enum {
 	ATA_TFLAG_ISADDR	= (1 << 1), /* enable r/w to nsect/lba regs */
 	ATA_TFLAG_DEVICE	= (1 << 2), /* enable r/w to device reg */
 	ATA_TFLAG_WRITE		= (1 << 3), /* data dir: host->dev==1 (write) */
+	ATA_TFLAG_LBA		= (1 << 4), /* enable LBA */
 };
 
 enum ata_tf_protocols {
@@ -250,7 +261,19 @@ struct ata_taskfile {
 	  ((u64) (id)[(n) + 1] << 16) |	\
 	  ((u64) (id)[(n) + 0]) )
 
-static inline int atapi_cdb_len(u16 *dev_id)
+static inline int ata_id_current_chs_valid(const u16 *id)
+{
+	/* For ATA-1 devices, if the INITIALIZE DEVICE PARAMETERS command 
+	   has not been issued to the device then the values of 
+	   id[54] to id[56] are vendor specific. */
+	return (id[53] & 0x01) && /* Current translation valid */
+		id[54] &&  /* cylinders in current translation */
+		id[55] &&  /* heads in current translation */
+		id[55] <= 16 &&
+		id[56];    /* sectors in current translation */
+}
+
+static inline int atapi_cdb_len(const u16 *dev_id)
 {
 	u16 tmp = dev_id[0] & 0x3;
 	switch (tmp) {
@@ -260,7 +283,7 @@ static inline int atapi_cdb_len(u16 *dev_id)
 	}
 }
 
-static inline int is_atapi_taskfile(struct ata_taskfile *tf)
+static inline int is_atapi_taskfile(const struct ata_taskfile *tf)
 {
 	return (tf->protocol == ATA_PROT_ATAPI) ||
 	       (tf->protocol == ATA_PROT_ATAPI_NODATA) ||

+ 81 - 32
include/linux/libata.h

@@ -91,12 +91,13 @@ enum {
 	ATA_SHT_EMULATED	= 1,
 	ATA_SHT_CMD_PER_LUN	= 1,
 	ATA_SHT_THIS_ID		= -1,
-	ATA_SHT_USE_CLUSTERING	= 0,
+	ATA_SHT_USE_CLUSTERING	= 1,
 
 	/* struct ata_device stuff */
 	ATA_DFLAG_LBA48		= (1 << 0), /* device supports LBA48 */
 	ATA_DFLAG_PIO		= (1 << 1), /* device currently in PIO mode */
 	ATA_DFLAG_LOCK_SECTORS	= (1 << 2), /* don't adjust max_sectors */
+	ATA_DFLAG_LBA		= (1 << 3), /* device supports LBA */
 
 	ATA_DEV_UNKNOWN		= 0,	/* unknown device */
 	ATA_DEV_ATA		= 1,	/* ATA device */
@@ -154,17 +155,21 @@ enum {
 	ATA_SHIFT_UDMA		= 0,
 	ATA_SHIFT_MWDMA		= 8,
 	ATA_SHIFT_PIO		= 11,
+	
+	/* Masks for port functions */
+	ATA_PORT_PRIMARY	= (1 << 0),
+	ATA_PORT_SECONDARY	= (1 << 1),
 };
 
-enum pio_task_states {
-	PIO_ST_UNKNOWN,
-	PIO_ST_IDLE,
-	PIO_ST_POLL,
-	PIO_ST_TMOUT,
-	PIO_ST,
-	PIO_ST_LAST,
-	PIO_ST_LAST_POLL,
-	PIO_ST_ERR,
+enum hsm_task_states {
+	HSM_ST_UNKNOWN,
+	HSM_ST_IDLE,
+	HSM_ST_POLL,
+	HSM_ST_TMOUT,
+	HSM_ST,
+	HSM_ST_LAST,
+	HSM_ST_LAST_POLL,
+	HSM_ST_ERR,
 };
 
 /* forward declarations */
@@ -197,7 +202,7 @@ struct ata_ioports {
 struct ata_probe_ent {
 	struct list_head	node;
 	struct device 		*dev;
-	struct ata_port_operations	*port_ops;
+	const struct ata_port_operations *port_ops;
 	Scsi_Host_Template	*sht;
 	struct ata_ioports	port[ATA_MAX_PORTS];
 	unsigned int		n_ports;
@@ -220,7 +225,7 @@ struct ata_host_set {
 	void __iomem		*mmio_base;
 	unsigned int		n_ports;
 	void			*private_data;
-	struct ata_port_operations *ops;
+	const struct ata_port_operations *ops;
 	struct ata_port *	ports[0];
 };
 
@@ -278,15 +283,18 @@ struct ata_device {
 	u8			xfer_mode;
 	unsigned int		xfer_shift;	/* ATA_SHIFT_xxx */
 
-	/* cache info about current transfer mode */
-	u8			xfer_protocol;	/* taskfile xfer protocol */
-	u8			read_cmd;	/* opcode to use on read */
-	u8			write_cmd;	/* opcode to use on write */
+	unsigned int		multi_count;	/* sectors count for
+						   READ/WRITE MULTIPLE */
+
+	/* for CHS addressing */
+	u16			cylinders;	/* Number of cylinders */
+	u16			heads;		/* Number of heads */
+	u16			sectors;	/* Number of sectors per track */
 };
 
 struct ata_port {
 	struct Scsi_Host	*host;	/* our co-allocated scsi host */
-	struct ata_port_operations	*ops;
+	const struct ata_port_operations *ops;
 	unsigned long		flags;	/* ATA_FLAG_xxx */
 	unsigned int		id;	/* unique id req'd by scsi midlyr */
 	unsigned int		port_no; /* unique port #; from zero */
@@ -319,7 +327,7 @@ struct ata_port {
 	struct work_struct	packet_task;
 
 	struct work_struct	pio_task;
-	unsigned int		pio_task_state;
+	unsigned int		hsm_task_state;
 	unsigned long		pio_task_timeout;
 
 	void			*private_data;
@@ -333,10 +341,10 @@ struct ata_port_operations {
 	void (*set_piomode) (struct ata_port *, struct ata_device *);
 	void (*set_dmamode) (struct ata_port *, struct ata_device *);
 
-	void (*tf_load) (struct ata_port *ap, struct ata_taskfile *tf);
+	void (*tf_load) (struct ata_port *ap, const struct ata_taskfile *tf);
 	void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf);
 
-	void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf);
+	void (*exec_command)(struct ata_port *ap, const struct ata_taskfile *tf);
 	u8   (*check_status)(struct ata_port *ap);
 	u8   (*check_altstatus)(struct ata_port *ap);
 	u8   (*check_err)(struct ata_port *ap);
@@ -377,9 +385,22 @@ struct ata_port_info {
 	unsigned long		pio_mask;
 	unsigned long		mwdma_mask;
 	unsigned long		udma_mask;
-	struct ata_port_operations	*port_ops;
+	const struct ata_port_operations *port_ops;
+};
+
+struct ata_timing {
+	unsigned short mode;		/* ATA mode */
+	unsigned short setup;		/* t1 */
+	unsigned short act8b;		/* t2 for 8-bit I/O */
+	unsigned short rec8b;		/* t2i for 8-bit I/O */
+	unsigned short cyc8b;		/* t0 for 8-bit I/O */
+	unsigned short active;		/* t2 or tD */
+	unsigned short recover;		/* t2i or tK */
+	unsigned short cycle;		/* t0 */
+	unsigned short udma;		/* t2CYCTYP/2 */
 };
 
+#define FIT(v,vmin,vmax)	max_t(short,min_t(short,v,vmax),vmin)
 
 extern void ata_port_probe(struct ata_port *);
 extern void __sata_phy_reset(struct ata_port *ap);
@@ -392,7 +413,7 @@ extern int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_i
 			     unsigned int n_ports);
 extern void ata_pci_remove_one (struct pci_dev *pdev);
 #endif /* CONFIG_PCI */
-extern int ata_device_add(struct ata_probe_ent *ent);
+extern int ata_device_add(const struct ata_probe_ent *ent);
 extern void ata_host_set_remove(struct ata_host_set *host_set);
 extern int ata_scsi_detect(Scsi_Host_Template *sht);
 extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg);
@@ -400,19 +421,21 @@ extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmn
 extern int ata_scsi_error(struct Scsi_Host *host);
 extern int ata_scsi_release(struct Scsi_Host *host);
 extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc);
+extern int ata_ratelimit(void);
+
 /*
  * Default driver ops implementations
  */
-extern void ata_tf_load(struct ata_port *ap, struct ata_taskfile *tf);
+extern void ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf);
 extern void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
-extern void ata_tf_to_fis(struct ata_taskfile *tf, u8 *fis, u8 pmp);
-extern void ata_tf_from_fis(u8 *fis, struct ata_taskfile *tf);
+extern void ata_tf_to_fis(const struct ata_taskfile *tf, u8 *fis, u8 pmp);
+extern void ata_tf_from_fis(const u8 *fis, struct ata_taskfile *tf);
 extern void ata_noop_dev_select (struct ata_port *ap, unsigned int device);
 extern void ata_std_dev_select (struct ata_port *ap, unsigned int device);
 extern u8 ata_check_status(struct ata_port *ap);
 extern u8 ata_altstatus(struct ata_port *ap);
 extern u8 ata_chk_err(struct ata_port *ap);
-extern void ata_exec_command(struct ata_port *ap, struct ata_taskfile *tf);
+extern void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf);
 extern int ata_port_start (struct ata_port *ap);
 extern void ata_port_stop (struct ata_port *ap);
 extern void ata_host_stop (struct ata_host_set *host_set);
@@ -423,8 +446,8 @@ extern void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf,
 		unsigned int buflen);
 extern void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg,
 		 unsigned int n_elem);
-extern unsigned int ata_dev_classify(struct ata_taskfile *tf);
-extern void ata_dev_id_string(u16 *id, unsigned char *s,
+extern unsigned int ata_dev_classify(const struct ata_taskfile *tf);
+extern void ata_dev_id_string(const u16 *id, unsigned char *s,
 			      unsigned int ofs, unsigned int len);
 extern void ata_dev_config(struct ata_port *ap, unsigned int i);
 extern void ata_bmdma_setup (struct ata_queued_cmd *qc);
@@ -441,6 +464,32 @@ extern int ata_std_bios_param(struct scsi_device *sdev,
 			      sector_t capacity, int geom[]);
 extern int ata_scsi_slave_config(struct scsi_device *sdev);
 
+/*
+ * Timing helpers
+ */
+extern int ata_timing_compute(struct ata_device *, unsigned short,
+			      struct ata_timing *, int, int);
+extern void ata_timing_merge(const struct ata_timing *,
+			     const struct ata_timing *, struct ata_timing *,
+			     unsigned int);
+
+enum {
+	ATA_TIMING_SETUP	= (1 << 0),
+	ATA_TIMING_ACT8B	= (1 << 1),
+	ATA_TIMING_REC8B	= (1 << 2),
+	ATA_TIMING_CYC8B	= (1 << 3),
+	ATA_TIMING_8BIT		= ATA_TIMING_ACT8B | ATA_TIMING_REC8B |
+				  ATA_TIMING_CYC8B,
+	ATA_TIMING_ACTIVE	= (1 << 4),
+	ATA_TIMING_RECOVER	= (1 << 5),
+	ATA_TIMING_CYCLE	= (1 << 6),
+	ATA_TIMING_UDMA		= (1 << 7),
+	ATA_TIMING_ALL		= ATA_TIMING_SETUP | ATA_TIMING_ACT8B |
+				  ATA_TIMING_REC8B | ATA_TIMING_CYC8B |
+				  ATA_TIMING_ACTIVE | ATA_TIMING_RECOVER |
+				  ATA_TIMING_CYCLE | ATA_TIMING_UDMA,
+};
+
 
 #ifdef CONFIG_PCI
 struct pci_bits {
@@ -452,8 +501,8 @@ struct pci_bits {
 
 extern void ata_pci_host_stop (struct ata_host_set *host_set);
 extern struct ata_probe_ent *
-ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port);
-extern int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits);
+ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int portmask);
+extern int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits);
 
 #endif /* CONFIG_PCI */
 
@@ -463,7 +512,7 @@ static inline unsigned int ata_tag_valid(unsigned int tag)
 	return (tag < ATA_MAX_QUEUE) ? 1 : 0;
 }
 
-static inline unsigned int ata_dev_present(struct ata_device *dev)
+static inline unsigned int ata_dev_present(const struct ata_device *dev)
 {
 	return ((dev->class == ATA_DEV_ATA) ||
 		(dev->class == ATA_DEV_ATAPI));
@@ -662,7 +711,7 @@ static inline unsigned int sata_dev_present(struct ata_port *ap)
 	return ((scr_read(ap, SCR_STATUS) & 0xf) == 0x3) ? 1 : 0;
 }
 
-static inline int ata_try_flush_cache(struct ata_device *dev)
+static inline int ata_try_flush_cache(const struct ata_device *dev)
 {
 	return ata_id_wcache_enabled(dev->id) ||
 	       ata_id_has_flush(dev->id) ||

Some files were not shown because too many files changed in this diff