svn commit: r191568 - in head/sys/dev/ata: . chipsets

Jung-uk Kim jkim at FreeBSD.org
Mon Apr 27 17:29:53 UTC 2009


Author: jkim
Date: Mon Apr 27 17:29:51 2009
New Revision: 191568
URL: http://svn.freebsd.org/changeset/base/191568

Log:
  - 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.

Modified:
  head/sys/dev/ata/ata-pci.h
  head/sys/dev/ata/chipsets/ata-ahci.c
  head/sys/dev/ata/chipsets/ata-ati.c

Modified: head/sys/dev/ata/ata-pci.h
==============================================================================
--- head/sys/dev/ata/ata-pci.h	Mon Apr 27 17:24:47 2009	(r191567)
+++ head/sys/dev/ata/ata-pci.h	Mon Apr 27 17:29:51 2009	(r191568)
@@ -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);

Modified: head/sys/dev/ata/chipsets/ata-ahci.c
==============================================================================
--- head/sys/dev/ata/chipsets/ata-ahci.c	Mon Apr 27 17:24:47 2009	(r191567)
+++ head/sys/dev/ata/chipsets/ata-ahci.c	Mon Apr 27 17:29:51 2009	(r191568)
@@ -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);

Modified: head/sys/dev/ata/chipsets/ata-ati.c
==============================================================================
--- head/sys/dev/ata/chipsets/ata-ati.c	Mon Apr 27 17:24:47 2009	(r191567)
+++ head/sys/dev/ata/chipsets/ata-ati.c	Mon Apr 27 17:29:51 2009	(r191568)
@@ -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
 #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);


More information about the svn-src-head mailing list