AHCI - Initial Port Multiplier support + misc fixes, and major reorg.
authorMatthew Dillon <dillon@apollo.backplane.com>
Thu, 11 Jun 2009 06:24:06 +0000 (23:24 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Thu, 11 Jun 2009 06:24:06 +0000 (23:24 -0700)
commit1980eff35123fa96fd373c68fdff6de63e80a30d
tree4330a2db19277e236a3e2da475bdc93ab91a40e6
parent5074bd7674945d08e97f154df18f823147583f98
AHCI - Initial Port Multiplier support + misc fixes, and major reorg.

* Add nearly all of the core port multiplier support code.  Add a
  new module, ahci_pm.c, which has most of the PM support.  Note
  that the PM probe code (ahci_port_pmprobe()) was placed in ahci.c.

  Note that we have to reduce the number of commands in the queue to 1
  even though we are in command switched mode, which is contrary to the
  AHCI spec which says we can queue more then 1 (the HBA still serializes
  it).  However, when I try to queue more then one to different devices
  the SATA port gets fatal PHY errors.

* Significantly reorganize the hard and soft reset code and create
  additional procedures in ahci_pm.c for hard and soft resets of
  targets through the PM.

  The softreset code now does the reset sequence twice to try to work
  around an issue where a previous signature prevents the new signature
  from being properly latched.

  The hard and soft reset code and the CAM code now has a simple probe
  sequencer using ap->ap_probe (and at->at_probe for the PM ata_port
  structures).

* The hardreset code now interfaces with the PM probe code, which itself
  is a bit complex.  Ports with port multipliers on them can either busy
  out on the initial probe or return information related to the device
  at target 0 instead of information related to the PM itself, so we
  have to probe the PM by putting the port into PMA mode and doing a
  softreset of target 15 even if a PM does not appear to be attached.

* The hard and soft reset code for a target behind a PM (in ahci_pm.c)
  tries to be careful not to break the entire port (and thus all the
  targets) when one target misbehaves.

* Get a large chunk of the error handling code working with the PM,
  including hopefully partial cancelation on target failure to fail
  just that target instead of the entire SATA port.

* Modify the probe code to check for the presence of a PHY with a short
  polling interval and skip the port if nothing appears to be connected
  to it.

* Fix re-initialization recursions which can occur from the port interrupt
  handler when called during a software or hardware reset.

* ATA_PORT vs AHCI_PORT

  AHCI_PORT represents a physical port on the AHCI device.  ATA_PORT
  reprewents a logical port of which (if a PM is present) there can be
  up to 16 per physical port.  In most cases in the code we only pass
  ATA_PORT (variable name 'atx') for targets behind a port multiplier
  and we pass NULL for atx for directly connected targets.  The variable
  'at' is similar to 'atx' except it is always non-NULL and is a
  pointer to target 0 on non-PM SATA ports (and the same as atx on
  PM SATA ports).

* Reorganize tracking of ap->ap_active_cnt, tying it more directly to
  the manipulation of ap->ap_active.  This also fixed a few bugs in
  the tracking of ap->ap_active_cnt.

* Implement the DHRS (Device-to-Host FIS) interrupt and properly
  copy the rfis to the ccb.  It is unclear whether command processing
  stops when we receive DHRS but if it does we restart it.  Without
  this the PM register read and write functions do not work.

* Add interrupt code to track notification (SSNTF capability) via
  the SDBS interrupt and AHCI_PREG_SNTF.  Not tied into anything yet.

* Put all the bits for the AHCI_PREG_SERR register on the same plane,
  combining the DIAG and ERR bits.  Get rid of the shift-by-16 macros.

* Pray.
sys/dev/disk/ahci/Makefile
sys/dev/disk/ahci/TODO
sys/dev/disk/ahci/ahci.c
sys/dev/disk/ahci/ahci.h
sys/dev/disk/ahci/ahci_cam.c
sys/dev/disk/ahci/ahci_pm.c [new file with mode: 0644]
sys/dev/disk/ahci/atascsi.h