[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