summaryrefslogtreecommitdiffstats
path: root/sys/dev/ata
diff options
context:
space:
mode:
authorjkim <jkim@FreeBSD.org>2009-04-27 17:29:51 +0000
committerjkim <jkim@FreeBSD.org>2009-04-27 17:29:51 +0000
commit3c49b58ce468aab699bcef9841ddfc8072bd5c12 (patch)
tree64c5c8bf60966200d0d392e41c8922c367605a21 /sys/dev/ata
parentca804bea3e4b9f7bbdf116d9869376542187b1a3 (diff)
downloadFreeBSD-src-3c49b58ce468aab699bcef9841ddfc8072bd5c12.zip
FreeBSD-src-3c49b58ce468aab699bcef9841ddfc8072bd5c12.tar.gz
- Always force AHCI mode on a ATI/AMD SB600/700/800 SATA controller. These
controllers may be configured as legacy IDE mode by modifying subclass and progif without actually changing PCI device IDs. Instead of complicating code, we always force AHCI mode while probing. Also we restore AHCI mode while resuming per ATI/AMD register programming/requirement guides. - Fix SB700/800 "combined" mode. Unlike SB600, this PATA controller can combine two SATA ports and emulate one PATA channel as primary or secondary depending on BIOS configuration. When the combined mode is disabled, this channel disappears and it works just like SB600 PATA controller, however. - Add more PCI device IDs for SB700/800 and adjust device descriptions. SB800 shares the same PCI device IDs and added two more SATA IDs.
Diffstat (limited to 'sys/dev/ata')
-rw-r--r--sys/dev/ata/ata-pci.h6
-rw-r--r--sys/dev/ata/chipsets/ata-ahci.c3
-rw-r--r--sys/dev/ata/chipsets/ata-ati.c76
3 files changed, 77 insertions, 8 deletions
diff --git a/sys/dev/ata/ata-pci.h b/sys/dev/ata/ata-pci.h
index 9e31bc7..42f478e 100644
--- a/sys/dev/ata/ata-pci.h
+++ b/sys/dev/ata/ata-pci.h
@@ -108,6 +108,11 @@ struct ata_pci_controller {
#define ATA_ATI_IXP600_S1 0x43801002
#define ATA_ATI_IXP700 0x439c1002
#define ATA_ATI_IXP700_S1 0x43901002
+#define ATA_ATI_IXP700_S2 0x43911002
+#define ATA_ATI_IXP700_S3 0x43921002
+#define ATA_ATI_IXP700_S4 0x43931002
+#define ATA_ATI_IXP800_S1 0x43941002
+#define ATA_ATI_IXP800_S2 0x43951002
#define ATA_CENATEK_ID 0x16ca
#define ATA_CENATEK_ROCKET 0x000116ca
@@ -458,6 +463,7 @@ int ata_ahci_ch_attach(device_t dev);
int ata_ahci_ch_detach(device_t dev);
int ata_ahci_ch_suspend(device_t dev);
int ata_ahci_ch_resume(device_t dev);
+int ata_ahci_ctlr_reset(device_t dev);
void ata_ahci_reset(device_t dev);
int ata_marvell_edma_chipinit(device_t);
int ata_sii_chipinit(device_t);
diff --git a/sys/dev/ata/chipsets/ata-ahci.c b/sys/dev/ata/chipsets/ata-ahci.c
index 9e78132..d48ec26 100644
--- a/sys/dev/ata/chipsets/ata-ahci.c
+++ b/sys/dev/ata/chipsets/ata-ahci.c
@@ -52,7 +52,6 @@ __FBSDID("$FreeBSD$");
#include <ata_if.h>
/* local prototypes */
-static int ata_ahci_ctlr_reset(device_t dev);
static int ata_ahci_suspend(device_t dev);
static int ata_ahci_status(device_t dev);
static int ata_ahci_begin_transaction(struct ata_request *request);
@@ -155,7 +154,7 @@ ata_ahci_chipinit(device_t dev)
return 0;
}
-static int
+int
ata_ahci_ctlr_reset(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(dev);
diff --git a/sys/dev/ata/chipsets/ata-ati.c b/sys/dev/ata/chipsets/ata-ati.c
index a777241..7a5d992 100644
--- a/sys/dev/ata/chipsets/ata-ati.c
+++ b/sys/dev/ata/chipsets/ata-ati.c
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
#include <machine/stdarg.h>
#include <machine/resource.h>
#include <machine/bus.h>
+#include <sys/pciio.h>
#include <sys/rman.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
@@ -54,6 +55,9 @@ __FBSDID("$FreeBSD$");
/* local prototypes */
static int ata_ati_chipinit(device_t dev);
static void ata_ati_setmode(device_t dev, int mode);
+static void ata_ati_ahci_enable(device_t dev);
+static int ata_ati_ahci_chipinit(device_t dev);
+static int ata_ati_ahci_resume(device_t dev);
/* misc defines */
#define ATI_PATA 0x01
@@ -62,6 +66,13 @@ static void ata_ati_setmode(device_t dev, int mode);
#define SII_MEMIO 1
#define SII_BUG 0x04
+/* Misc Control Register */
+#define ATI_PCI_MISC_CTRL 0x40
+#define ATI_PCI_MISCCTRL_ENABLE_WR 0x00000001
+
+/* Watchdog Control/Status Register */
+#define ATI_PCI_WD_CTRL 0x44
+#define ATI_PCI_WDCTRL_ENABLE 0x0001
/*
* ATI chipset support functions
@@ -79,8 +90,13 @@ ata_ati_probe(device_t dev)
{ ATA_ATI_IXP400_S2, 0x00, ATI_SATA, 0, ATA_SA150, "IXP400" },
{ ATA_ATI_IXP600, 0x00, ATI_PATA, 0, ATA_UDMA6, "IXP600" },
{ ATA_ATI_IXP600_S1, 0x00, ATI_AHCI, 0, ATA_SA300, "IXP600" },
- { ATA_ATI_IXP700, 0x00, ATI_PATA, 0, ATA_UDMA6, "IXP700" },
- { ATA_ATI_IXP700_S1, 0x00, ATI_AHCI, 0, ATA_SA300, "IXP700" },
+ { ATA_ATI_IXP700, 0x00, ATI_PATA, 0, ATA_UDMA6, "IXP700/800" },
+ { ATA_ATI_IXP700_S1, 0x00, ATI_AHCI, 0, ATA_SA300, "IXP700/800" },
+ { ATA_ATI_IXP700_S2, 0x00, ATI_AHCI, 0, ATA_SA300, "IXP700/800" },
+ { ATA_ATI_IXP700_S3, 0x00, ATI_AHCI, 0, ATA_SA300, "IXP700/800" },
+ { ATA_ATI_IXP700_S4, 0x00, ATI_AHCI, 0, ATA_SA300, "IXP700/800" },
+ { ATA_ATI_IXP800_S1, 0x00, ATI_AHCI, 0, ATA_SA300, "IXP800" },
+ { ATA_ATI_IXP800_S2, 0x00, ATI_AHCI, 0, ATA_SA300, "IXP800" },
{ 0, 0, 0, 0, 0, 0}};
if (pci_get_vendor(dev) != ATA_ATI_ID)
@@ -105,7 +121,19 @@ ata_ati_probe(device_t dev)
ctlr->chipinit = ata_sii_chipinit;
break;
case ATI_AHCI:
- ctlr->chipinit = ata_ahci_chipinit;
+ /*
+ * Force AHCI mode if IDE mode is set from BIOS.
+ */
+ if ((ctlr->chip->chipid == ATA_ATI_IXP600_S1 ||
+ ctlr->chip->chipid == ATA_ATI_IXP700_S1) &&
+ pci_get_subclass(dev) == PCIS_STORAGE_IDE) {
+ struct pci_devinfo *dinfo = device_get_ivars(dev);
+ pcicfgregs *cfg = &dinfo->cfg;
+ cfg->subclass = PCIS_STORAGE_SATA;
+ cfg->progif = PCIP_STORAGE_SATA_AHCI_1_0;
+ ata_ati_ahci_enable(dev);
+ }
+ ctlr->chipinit = ata_ati_ahci_chipinit;
break;
}
return 0;
@@ -119,9 +147,8 @@ ata_ati_chipinit(device_t dev)
if (ata_setup_interrupt(dev, ata_generic_intr))
return ENXIO;
- /* IXP600 & IXP700 only have 1 PATA channel */
- if ((ctlr->chip->chipid == ATA_ATI_IXP600) ||
- (ctlr->chip->chipid == ATA_ATI_IXP700))
+ /* IXP600 only has 1 PATA channel */
+ if (ctlr->chip->chipid == ATA_ATI_IXP600)
ctlr->channels = 1;
ctlr->setmode = ata_ati_setmode;
@@ -192,6 +219,43 @@ ata_ati_setmode(device_t dev, int mode)
}
}
+static void
+ata_ati_ahci_enable(device_t dev)
+{
+ struct pci_devinfo *dinfo = device_get_ivars(dev);
+ pcicfgregs *cfg = &dinfo->cfg;
+ uint32_t ctrl;
+
+ ctrl = pci_read_config(dev, ATI_PCI_MISC_CTRL, 4);
+ pci_write_config(dev, ATI_PCI_MISC_CTRL,
+ ctrl | ATI_PCI_MISCCTRL_ENABLE_WR, 4);
+ pci_write_config(dev, PCIR_SUBCLASS, cfg->subclass, 1);
+ pci_write_config(dev, PCIR_PROGIF, cfg->progif, 1);
+ pci_write_config(dev, ATI_PCI_WD_CTRL,
+ pci_read_config(dev, ATI_PCI_WD_CTRL, 2) | ATI_PCI_WDCTRL_ENABLE, 2);
+ pci_write_config(dev, ATI_PCI_MISC_CTRL,
+ ctrl & ~ATI_PCI_MISCCTRL_ENABLE_WR, 4);
+}
+
+static int
+ata_ati_ahci_chipinit(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+ int error;
+
+ error = ata_ahci_chipinit(dev);
+ ctlr->resume = ata_ati_ahci_resume;
+ return (error);
+}
+
+static int
+ata_ati_ahci_resume(device_t dev)
+{
+
+ ata_ati_ahci_enable(dev);
+ return (ata_ahci_ctlr_reset(dev));
+}
+
ATA_DECLARE_DRIVER(ata_ati);
MODULE_DEPEND(ata_ati, ata_ahci, 1, 1, 1);
MODULE_DEPEND(ata_ati, ata_sii, 1, 1, 1);
OpenPOWER on IntegriCloud