--- /usr/src/sys/dev/ata/ata-chipset.c 2007-11-22 10:24:03.000000000 +0300 +++ ata-chipset.c 2007-11-23 11:22:05.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); @@ -1850,6 +1851,7 @@ ata_intel_chipinit(device_t dev) ctlr->allocate = ata_intel_allocate; ctlr->reset = ata_intel_reset; + ctlr->setmode = ata_sata_setmode; /* * if we have AHCI capability and AHCI or RAID mode enabled @@ -1859,8 +1861,14 @@ ata_intel_chipinit(device_t dev) (pci_read_config(dev, 0x90, 1) & 0xc0) && (ata_ahci_chipinit(dev) != ENXIO)) return 0; - - ctlr->setmode = ata_sata_setmode; + 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))) + return ENXIO; + ctlr->setmode = ata_intel_setmode; + } /* enable PCI interrupt */ pci_write_config(dev, PCIR_COMMAND, @@ -1872,6 +1880,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 */ @@ -1879,10 +1888,47 @@ 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; + } return 0; } 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 idx[] = {0x0000, 0x0200, 0x0100, 0x0300}; + + /* 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)); + + /* Select channel and ATA_SSTATUS register */ + ATA_IDX_OUTL(ch, ATA_IDX_ADDR, idx[ch->unit]); + + /* 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_reset(device_t dev) { device_t parent = device_get_parent(dev);