aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/ata/chipsets/ata-siliconimage.c
diff options
context:
space:
mode:
authorAlexander Motin <mav@FreeBSD.org>2010-10-18 11:30:13 +0000
committerAlexander Motin <mav@FreeBSD.org>2010-10-18 11:30:13 +0000
commitbda55b6adb5c21095e00ffd8b87f8950cf737314 (patch)
treefd926a601552c1bcf585c33dddb137654dc80a3f /sys/dev/ata/chipsets/ata-siliconimage.c
parent7672cbaaf981d91efb4cdcc90fa5f88bbc5c29b1 (diff)
downloadsrc-bda55b6adb5c21095e00ffd8b87f8950cf737314.tar.gz
src-bda55b6adb5c21095e00ffd8b87f8950cf737314.zip
Set of legacy mode SATA enchancements:
- Implement proper combined mode decoding for Intel controllers to properly identify SATA and PATA channels and associate ATA channels with SATA ports. This fixes wrong reporting and in some cases hard resets to wrong SATA ports. - Improve SATA registers support to handle hot-plug events and potentially interface errors. For ICH5/6300ESB chipsets these registers accessible via PCI config space. For later ones they may be accessible via PCI BAR(5). - For controllers not generating interrupts on hot-plug events, implement periodic status polling. Use it to detect hot-plug on Intel and VIA controllers. Same probably could also be used for Serverworks and SIS.
Notes
Notes: svn path=/head/; revision=214016
Diffstat (limited to 'sys/dev/ata/chipsets/ata-siliconimage.c')
-rw-r--r--sys/dev/ata/chipsets/ata-siliconimage.c42
1 files changed, 40 insertions, 2 deletions
diff --git a/sys/dev/ata/chipsets/ata-siliconimage.c b/sys/dev/ata/chipsets/ata-siliconimage.c
index f9b90f6753d2..fa7619c75b32 100644
--- a/sys/dev/ata/chipsets/ata-siliconimage.c
+++ b/sys/dev/ata/chipsets/ata-siliconimage.c
@@ -354,7 +354,7 @@ ata_sii_status(device_t dev)
/* do we have any PHY events ? */
if (ctlr->chip->max_dma >= ATA_SA150 &&
(ATA_INL(ctlr->r_res2, 0x10 + offset0) & 0x00000010))
- ata_sata_phy_check_events(dev);
+ ata_sata_phy_check_events(dev, -1);
if (ATA_INL(ctlr->r_res2, 0xa0 + offset1) & 0x00000800)
return ata_pci_status(dev);
@@ -510,7 +510,7 @@ ata_siiprb_status(device_t dev)
u_int32_t istatus = ATA_INL(ctlr->r_res2, 0x1008 + offset);
/* do we have any PHY events ? */
- ata_sata_phy_check_events(dev);
+ ata_sata_phy_check_events(dev, -1);
/* clear interrupt(s) */
ATA_OUTL(ctlr->r_res2, 0x1008 + offset, istatus);
@@ -700,6 +700,25 @@ ata_siiprb_pm_read(device_t dev, int port, int reg, u_int32_t *result)
struct ata_siiprb_command *prb = (struct ata_siiprb_command *)ch->dma.work;
int offset = ch->unit * 0x2000;
+ if (port < 0) {
+ *result = ATA_IDX_INL(ch, reg);
+ return (0);
+ }
+ if (port < ATA_PM) {
+ switch (reg) {
+ case ATA_SSTATUS:
+ reg = 0;
+ break;
+ case ATA_SERROR:
+ reg = 1;
+ break;
+ case ATA_SCONTROL:
+ reg = 2;
+ break;
+ default:
+ return (EINVAL);
+ }
+ }
bzero(prb, sizeof(struct ata_siiprb_command));
prb->fis[0] = 0x27; /* host to device */
prb->fis[1] = 0x8f; /* command FIS to PM port */
@@ -724,6 +743,25 @@ ata_siiprb_pm_write(device_t dev, int port, int reg, u_int32_t value)
struct ata_siiprb_command *prb = (struct ata_siiprb_command *)ch->dma.work;
int offset = ch->unit * 0x2000;
+ if (port < 0) {
+ ATA_IDX_OUTL(ch, reg, value);
+ return (0);
+ }
+ if (port < ATA_PM) {
+ switch (reg) {
+ case ATA_SSTATUS:
+ reg = 0;
+ break;
+ case ATA_SERROR:
+ reg = 1;
+ break;
+ case ATA_SCONTROL:
+ reg = 2;
+ break;
+ default:
+ return (EINVAL);
+ }
+ }
bzero(prb, sizeof(struct ata_siiprb_command));
prb->fis[0] = 0x27; /* host to device */
prb->fis[1] = 0x8f; /* command FIS to PM port */