[ANNOUNCEMENT] Wiki for discussing P35/IHC9(R)/SATA issues set up

Andrey V. Elsukov bu7cher at yandex.ru
Wed Nov 7 03:54:25 PST 2007


Aryeh M. Friedman wrote:
>>
>> As i see from pciconf and dmesg output Aryeh's hardware not determined
>> as an AHCI and driver use legacy way for interact with controller.
>> In this case driver don't use any of SATA method's and can't determine
>> drives speed.
>>
> 
> Is this based on the dmesg I posted after appling the patch or the one I
> posted before?

You can set an AHCI mode in the BIOS and all will work good, IMHO.
If you want use IDE-compatible mode, you can test the attached patch.

-- 
WBR, Andrey V. Elsukov
-------------- next part --------------
diff -pruN ata.orig/ata-chipset.c ata/ata-chipset.c
--- ata.orig/ata-chipset.c	2007-10-26 13:01:06.000000000 +0400
+++ ata/ata-chipset.c	2007-11-07 14:08:23.000000000 +0300
@@ -94,6 +94,7 @@ static int ata_highpoint_check_80pin(dev
 static int ata_intel_chipinit(device_t dev);
 static int ata_intel_allocate(device_t dev);
 static void ata_intel_reset(device_t dev);
+static void ata_intel_setmode(device_t dev, int mode);
 static void ata_intel_old_setmode(device_t dev, int mode);
 static void ata_intel_new_setmode(device_t dev, int mode);
 static int ata_intel_31244_allocate(device_t dev);
@@ -1809,13 +1810,15 @@ ata_intel_chipinit(device_t dev)
 	 * if we have AHCI capability and BAR(5) as a memory resource
 	 * and AHCI or RAID mode enabled in BIOS we go for AHCI mode
 	 */ 
-	if ((ctlr->chip->cfg1 == AHCI) &&
-	    (pci_read_config(dev, 0x90, 1) & 0xc0)) {
-	    ctlr->r_type2 = SYS_RES_MEMORY;
+	if (ctlr->chip->cfg1 == AHCI) {
+	    if (pci_read_config(dev, 0x90, 1) & 0xc0)
+		ctlr->r_type2 = SYS_RES_MEMORY;
+	    else
+		ctlr->r_type2 = SYS_RES_IOPORT;
 	    ctlr->r_rid2 = PCIR_BAR(5);
-	    if ((ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2,
-						       &ctlr->r_rid2,
-						       RF_ACTIVE)))
+	    ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2, &ctlr->r_rid2,
+						       RF_ACTIVE);
+	    if (ctlr->r_res2 != NULL && ctlr->r_type2 == SYS_RES_MEMORY)
 		return ata_ahci_chipinit(dev);
 	}
 	ctlr->setmode = ata_sata_setmode;
@@ -1830,6 +1833,7 @@ ata_intel_chipinit(device_t dev)
 static int
 ata_intel_allocate(device_t dev)
 {
+    struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
     struct ata_channel *ch = device_get_softc(dev);
 
     /* setup the usual register normal pci style */
@@ -1837,6 +1841,14 @@ ata_intel_allocate(device_t dev)
 	return ENXIO;
 
     ch->flags |= ATA_ALWAYS_DMASTAT;
+
+    if (ctlr->r_res2 != NULL) {
+	ch->r_io[ATA_IDX_ADDR].res = ctlr->r_res2;
+	ch->r_io[ATA_IDX_ADDR].offset = 0;
+	ch->r_io[ATA_IDX_DATA].res = ctlr->r_res2;
+	ch->r_io[ATA_IDX_DATA].offset = 4;
+	ctlr->setmode = ata_intel_setmode;
+    }
     return 0;
 }
 
@@ -1877,6 +1889,45 @@ ata_intel_reset(device_t dev)
 }
 
 static void
+ata_intel_setmode(device_t dev, int mode)
+{
+    struct ata_device *atadev = device_get_softc(dev);
+
+    if (atadev->param.satacapabilities != 0x0000 &&
+	atadev->param.satacapabilities != 0xffff) {
+	struct ata_channel *ch = device_get_softc(device_get_parent(dev));
+	uint32_t port;
+
+	/* on some drives we need to set the transfer mode */
+	ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0,
+		       ata_limit_mode(dev, mode, ATA_UDMA6));
+
+	if (ch->unit == 1)
+	    port = 2 << 8;
+	else if (ch->unit == 2)
+	    port = 1 << 8;
+	else
+	    port = ch->unit << 8;
+
+	/* Select channel and ATA_SSTATUS register */
+	ATA_IDX_OUTL(ch, ATA_IDX_ADDR, port);
+	/* query SATA STATUS for the speed */
+        if ((ATA_IDX_INL(ch, ATA_IDX_DATA) & ATA_SS_CONWELL_MASK) ==
+	    ATA_SS_CONWELL_GEN2)
+	    atadev->mode = ATA_SA300;
+	else 
+	    atadev->mode = ATA_SA150;
+    }
+    else {
+	mode = ata_limit_mode(dev, mode, ATA_UDMA5);
+	if (!ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode))
+	    atadev->mode = mode;
+    }
+}
+
+
+
+static void
 ata_intel_old_setmode(device_t dev, int mode)
 {
     /* NOT YET */


More information about the freebsd-current mailing list