Re: Problems Installing to PowerEdge 850 with SATA Drive

From: Doug Ambrisko <ambrisko_at_ambrisko.com>
Date: Mon, 7 Nov 2005 10:35:17 -0800 (PST)
Doug Ambrisko writes:
| Doug Ambrisko writes:
| | Lynn A. Roth writes:
| | | I have two new Dell Poweredge 850 machines.  They have an Intel ICH7 
| | | chipset.  When I boot FreeBSD 6 RC1, the controller is identified, but 
| | | any drives connected to the SATA ports are not detected.  The drive that 
| | | is included with the system is a Seagate 7200.7 drive.  I also tried a 
| | | Maxtor.
| | 
| | I can confirm the problem on the PE850.  I have it working with my
| | latest 4.X SATA patches (which I haven't published yet).  I might
| | be able to look into this.
| | 
| | FWIW, I my code these SATA registers in 4.X before the become alive:
| |    ata2: Intel SATA P0 status 0 error 4050000 scontrol 0 0 1
| |    ata2: Intel SATA P0 status 113 error 4050000 scontrol 0 0 1
| |    ata2: Intel SATA P0 status 113 error 0 scontrol 0 0 1
| |    ata3: Intel SATA P1 status 0 error 4050000 scontrol 0 1 1
| |    ata3: Intel SATA P1 status 113 error 4050000 scontrol 0 1 1
| |    ata3: Intel SATA P1 status 113 error 0 scontrol 0 1 1
| | On other Intel controllers they I don't have to acknowledge the 
| | errors off the bat.
| 
| This is sort-of the clue indirectly.  The issue is that the ICH7 and
| maybe ICH6 have a hybrid AHCI mode in which the SATA status, error, control
| registers are present in AHCI for compatibility but that's all.  The
| reset of the AHCI registers are not there so then you have to 
| wack the registers in PCI space 0x92 to reset the controller.  Doing
| an AHCI reset won't work since it isn't running full AHCI mode.
| 
| I don't have a fix but this is the problem that I see.  If we don't
| do the channel reset via PCI space then it can never get out of that
| state so no drives are found.

Here's a hack to make it work on PE850:

Index: ata-chipset.c
===================================================================
RCS file: /usr/local/cvsroot/freebsd/src/sys/dev/ata/ata-chipset.c,v
retrieving revision 1.136
diff -u -p -r1.136 ata-chipset.c
--- ata-chipset.c	12 Oct 2005 20:00:26 -0000	1.136
+++ ata-chipset.c	7 Nov 2005 18:30:22 -0000
_at__at_ -236,15 +236,35 _at__at_ ata_sata_setmode(device_t dev, int mode)
 static int
 ata_sata_connect(struct ata_channel *ch)
 {
-    u_int32_t status;
-    int timeout;
+    u_int32_t status, error;
+    int timeout, device;
+    struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(ch->dev));
+    int something_there = 0;
+
+    if (ctlr->chip->chipid == ATA_I82801GB_S1) {
+	status = ATA_IDX_INL(ch, ATA_SSTATUS);
+	error = ATA_IDX_INL(ch, ATA_SERROR);
+	if (status == (ATA_SS_DET_DEV_PRESENT | ATA_SS_DET_PHY_OFFLINE) ||
+	    status == (ATA_SS_DET_PHY_ONLINE | ATA_SS_SPD_GEN1 | ATA_SS_IPM_ACTIVE)) {
+	    /* reset port */
+	    device = 1 << (ch->unit + 1);
+	    pci_write_config(ch->dev, 0x92,
+		pci_read_config(ch->dev, 0x92, 2) & ~device, 2);
+	    pci_write_config(ch->dev, 0x92,
+	        pci_read_config(ch->dev, 0x92, 2) & ~device, 2);
+	}
+    }
 
     /* wait up to 1 second for "connect well" */
     for (timeout = 0; timeout < 100 ; timeout++) {
 	status = ATA_IDX_INL(ch, ATA_SSTATUS);
+	error = ATA_IDX_INL(ch, ATA_SERROR);
+	ATA_IDX_OUTL(ch, ATA_SERROR, error);
 	if ((status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN1 ||
-	    (status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN2)
-	    break;
+	    (status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN2) {
+		something_there = 1;
+		break;
+	}
 	ata_udelay(10000);
     }
     if (timeout >= 100) {
_at__at_ -267,7 +287,7 _at__at_ ata_sata_connect(struct ata_channel *ch)
     }
     if (bootverbose)
 	device_printf(ch->dev, "SATA connect ready time=%dms\n", timeout * 10);
-    if (timeout < 1000) {
+    if (something_there || timeout < 1000) {
 	if ((ATA_IDX_INB(ch, ATA_CYL_LSB) == ATAPI_MAGIC_LSB) &&
 	    (ATA_IDX_INB(ch, ATA_CYL_MSB) == ATAPI_MAGIC_MSB))
 	    ch->devices = ATA_ATAPI_MASTER;
_at__at_ -1657,6 +1677,12 _at__at_ ata_intel_chipinit(device_t dev)
 	    /* force all ports active "the legacy way" */
 	    pci_write_config(dev, 0x92, pci_read_config(dev, 0x92, 2) | 0x0f,2);
 
+	    if (ctlr->chip->chipid == ATA_I82801GB_S1) {
+		/* enable AHCI register compat mode */
+		pci_write_config(dev, 0x94, pci_read_config(dev, 0x94, 4) | 1 << 9, 4);
+		ATA_OUTL(ctlr->r_res2, 0x0C, ATA_INL(ctlr->r_res2, 0x0C) | 0xf);
+	    }
+
 	    /* enable AHCI mode */
 	    ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC, ATA_AHCI_GHC_AE);
 
_at__at_ -1845,10 +1871,13 _at__at_ ata_intel_reset(device_t dev)
     struct ata_channel *ch = device_get_softc(dev);
     int mask, timeout;
 
-    /* ICH6 has 4 SATA ports as master/slave on 2 channels so deal with pairs */
+    /* ICH6/7 has 4 SATA ports as master/slave on 2 channels so deal with pairs */
     if (ctlr->chip->chipid == ATA_I82801FB_S1 ||
 	ctlr->chip->chipid == ATA_I82801FB_R1 ||
-	ctlr->chip->chipid == ATA_I82801FB_M) {
+	ctlr->chip->chipid == ATA_I82801FB_M  ||
+	ctlr->chip->chipid == ATA_I82801GB_S1 ||
+	ctlr->chip->chipid == ATA_I82801GB_R1 ||
+	ctlr->chip->chipid == ATA_I82801GB_M) {
 	mask = (0x0005 << ch->unit);
     }
     else {

This works for me on my PE850.  It shouldn't break other stuff etc.
I assume the ICH6 will need the same type of change.

Doug A.
Received on Mon Nov 07 2005 - 17:35:20 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:38:47 UTC