svn commit: r217936 - stable/8/sys/dev/ata/chipsets
Alexander Motin
mav at FreeBSD.org
Thu Jan 27 13:37:45 UTC 2011
Author: mav
Date: Thu Jan 27 13:37:45 2011
New Revision: 217936
URL: http://svn.freebsd.org/changeset/base/217936
Log:
MFC r215449:
Some VIA SATA controllers provide access to non-standard SATA registers via
PCI config space. Use them to implement hot-plug and link speed reporting.
Tested on ASRock PV530 board with VX900 chipset.
Modified:
stable/8/sys/dev/ata/chipsets/ata-via.c
Directory Properties:
stable/8/sys/ (props changed)
stable/8/sys/amd64/include/xen/ (props changed)
stable/8/sys/cddl/contrib/opensolaris/ (props changed)
stable/8/sys/contrib/dev/acpica/ (props changed)
stable/8/sys/contrib/pf/ (props changed)
Modified: stable/8/sys/dev/ata/chipsets/ata-via.c
==============================================================================
--- stable/8/sys/dev/ata/chipsets/ata-via.c Thu Jan 27 13:16:08 2011 (r217935)
+++ stable/8/sys/dev/ata/chipsets/ata-via.c Thu Jan 27 13:37:45 2011 (r217936)
@@ -63,6 +63,12 @@ static int ata_via_new_setmode(device_t
static int ata_via_sata_ch_attach(device_t dev);
static int ata_via_sata_getrev(device_t dev, int target);
static int ata_via_sata_setmode(device_t dev, int target, int mode);
+static void ata_via_sata_reset(device_t dev);
+static int ata_via_sata_scr_read(device_t dev, int port, int reg,
+ u_int32_t *result);
+static int ata_via_sata_scr_write(device_t dev, int port, int reg,
+ u_int32_t value);
+static int ata_via_sata_status(device_t dev);
/* misc defines */
#define VIA33 0
@@ -153,11 +159,12 @@ ata_via_chipinit(device_t dev)
if (ata_ahci_chipinit(dev) != ENXIO)
return (0);
}
- /* 2 SATA without SATA registers on first channel + 1 PATA on second */
+ /* 2 SATA with "SATA registers" at PCI config space + PATA on secondary */
if (ctlr->chip->cfg2 & VIASATA) {
ctlr->ch_attach = ata_via_sata_ch_attach;
ctlr->setmode = ata_via_sata_setmode;
ctlr->getrev = ata_via_sata_getrev;
+ ctlr->reset = ata_via_sata_reset;
return 0;
}
/* Legacy SATA/SATA+PATA with SATA registers in BAR(5). */
@@ -405,18 +412,30 @@ ata_via_sata_ch_attach(device_t dev)
if (ata_pci_ch_attach(dev))
return ENXIO;
- if (ch->unit == 0)
+ if (ch->unit == 0) {
+ ch->hw.status = ata_via_sata_status;
+ ch->hw.pm_read = ata_via_sata_scr_read;
+ ch->hw.pm_write = ata_via_sata_scr_write;
+ ch->flags |= ATA_PERIODIC_POLL;
ch->flags |= ATA_SATA;
+ ata_sata_scr_write(ch, 0, ATA_SERROR, 0xffffffff);
+ ata_sata_scr_write(ch, 1, ATA_SERROR, 0xffffffff);
+ }
return (0);
}
static int
ata_via_sata_getrev(device_t dev, int target)
{
+ device_t parent = device_get_parent(dev);
struct ata_channel *ch = device_get_softc(dev);
- if (ch->unit == 0)
- return (1);
+ if (ch->unit == 0) {
+ if (pci_read_config(parent, 0xa0 + target, 1) & 0x10)
+ return (2);
+ else
+ return (1);
+ }
return (0);
}
@@ -430,5 +449,110 @@ ata_via_sata_setmode(device_t dev, int t
return (ata_via_old_setmode(dev, target, mode));
}
+static void
+ata_via_sata_reset(device_t dev)
+{
+ struct ata_channel *ch = device_get_softc(dev);
+ int devs;
+
+ if (ch->unit == 0) {
+ devs = ata_sata_phy_reset(dev, 0, 0);
+ DELAY(10000);
+ devs += ata_sata_phy_reset(dev, 1, 0);
+ } else
+ devs = 1;
+ if (devs)
+ ata_generic_reset(dev);
+}
+
+static int
+ata_via_sata_scr_read(device_t dev, int port, int reg, u_int32_t *result)
+{
+ struct ata_channel *ch;
+ device_t parent;
+ uint32_t val;
+
+ parent = device_get_parent(dev);
+ ch = device_get_softc(dev);
+ port = (port == 1) ? 1 : 0;
+ switch (reg) {
+ case ATA_SSTATUS:
+ val = pci_read_config(parent, 0xa0 + port, 1);
+ *result = val & 0x03;
+ if (*result != ATA_SS_DET_NO_DEVICE) {
+ if (val & 0x04)
+ *result |= ATA_SS_IPM_PARTIAL;
+ else if (val & 0x08)
+ *result |= ATA_SS_IPM_SLUMBER;
+ else
+ *result |= ATA_SS_IPM_ACTIVE;
+ if (val & 0x10)
+ *result |= ATA_SS_SPD_GEN2;
+ else
+ *result |= ATA_SS_SPD_GEN1;
+ }
+ break;
+ case ATA_SERROR:
+ *result = pci_read_config(parent, 0xa8 + port * 4, 4);
+ break;
+ case ATA_SCONTROL:
+ val = pci_read_config(parent, 0xa4 + port, 1);
+ *result = 0;
+ if (val & 0x01)
+ *result |= ATA_SC_DET_RESET;
+ if (val & 0x02)
+ *result |= ATA_SC_DET_DISABLE;
+ if (val & 0x04)
+ *result |= ATA_SC_IPM_DIS_PARTIAL;
+ if (val & 0x08)
+ *result |= ATA_SC_IPM_DIS_SLUMBER;
+ break;
+ default:
+ return (EINVAL);
+ }
+ return (0);
+}
+
+static int
+ata_via_sata_scr_write(device_t dev, int port, int reg, u_int32_t value)
+{
+ struct ata_channel *ch;
+ device_t parent;
+ uint32_t val;
+
+ parent = device_get_parent(dev);
+ ch = device_get_softc(dev);
+ port = (port == 1) ? 1 : 0;
+ switch (reg) {
+ case ATA_SERROR:
+ pci_write_config(parent, 0xa8 + port * 4, value, 4);
+ break;
+ case ATA_SCONTROL:
+ val = 0;
+ if (value & ATA_SC_DET_RESET)
+ val |= 0x01;
+ if (value & ATA_SC_DET_DISABLE)
+ val |= 0x02;
+ if (value & ATA_SC_IPM_DIS_PARTIAL)
+ val |= 0x04;
+ if (value & ATA_SC_IPM_DIS_SLUMBER)
+ val |= 0x08;
+ pci_write_config(parent, 0xa4 + port, val, 1);
+ break;
+ default:
+ return (EINVAL);
+ }
+ return (0);
+}
+
+static int
+ata_via_sata_status(device_t dev)
+{
+
+ ata_sata_phy_check_events(dev, 0);
+ ata_sata_phy_check_events(dev, 1);
+ return (ata_pci_status(dev));
+}
+
ATA_DECLARE_DRIVER(ata_via);
MODULE_DEPEND(ata_via, ata_ahci, 1, 1, 1);
More information about the svn-src-all
mailing list