diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c index fe87b766abf4..17fa2efa36e6 100644 --- a/sys/dev/ata/ata-all.c +++ b/sys/dev/ata/ata-all.c @@ -211,8 +211,8 @@ struct ata_pci_softc { int32_t irqcnt; }; -static int32_t -ata_find_dev(device_t dev, int32_t type) +int32_t +ata_find_dev(device_t dev, int32_t type, int32_t revid) { device_t *children, child; int nchildren, i; @@ -226,7 +226,8 @@ ata_find_dev(device_t dev, int32_t type) /* check that it's on the same silicon and the device we want */ if (pci_get_slot(dev) == pci_get_slot(child) && pci_get_vendor(child) == (type & 0xffff) && - pci_get_device(child) == ((type & 0xffff0000) >> 16)) { + pci_get_device(child) == ((type & 0xffff0000) >> 16) && + pci_get_revid(child) >= revid) { free(children, M_TEMP); return 1; } @@ -263,11 +264,13 @@ ata_pci_match(device_t dev) return "AcerLabs Aladdin ATA33 controller"; case 0x05711106: - if (ata_find_dev(dev, 0x05861106)) + if (ata_find_dev(dev, 0x05861106, 0)) return "VIA 82C586 ATA33 controller"; - if (ata_find_dev(dev, 0x05961106)) + if (ata_find_dev(dev, 0x05961106, 0x12)) + return "VIA 82C596B ATA66 controller"; + if (ata_find_dev(dev, 0x05961106, 0)) return "VIA 82C596 ATA33 controller"; - if (ata_find_dev(dev, 0x06861106)) + if (ata_find_dev(dev, 0x06861106, 0)) return "VIA 82C686 ATA66 controller"; return "VIA Apollo ATA controller"; @@ -428,8 +431,9 @@ ata_pci_attach(device_t dev) pci_write_config(dev, 0x60, DEV_BSIZE, 2); pci_write_config(dev, 0x68, DEV_BSIZE, 2); - /* prepare for ATA-66 on the 82C686 */ - if (ata_find_dev(dev, 0x06861106)) { + /* prepare for ATA-66 on the 82C686 and rev 0x12 and newer 82C596's */ + if (ata_find_dev(dev, 0x06861106, 0) || + ata_find_dev(dev, 0x05961106, 0x12)) { pci_write_config(dev, 0x50, pci_read_config(dev, 0x50, 4) | 0x070f070f, 4); } @@ -697,11 +701,11 @@ ata_pcisub_probe(device_t dev) scp->unit = (uintptr_t) device_get_ivars(dev); /* set the chiptype to the hostchip ID, makes life easier */ - if (ata_find_dev(device_get_parent(dev), 0x05861106)) + if (ata_find_dev(device_get_parent(dev), 0x05861106, 0)) scp->chiptype = 0x05861106; - else if (ata_find_dev(device_get_parent(dev), 0x05961106)) + else if (ata_find_dev(device_get_parent(dev), 0x05961106, 0)) scp->chiptype = 0x05961106; - else if (ata_find_dev(device_get_parent(dev), 0x06861106)) + else if (ata_find_dev(device_get_parent(dev), 0x06861106, 0)) scp->chiptype = 0x06861106; else scp->chiptype = pci_get_devid(device_get_parent(dev)); diff --git a/sys/dev/ata/ata-all.h b/sys/dev/ata/ata-all.h index 62a10b558b3d..14a3d971882e 100644 --- a/sys/dev/ata/ata-all.h +++ b/sys/dev/ata/ata-all.h @@ -326,6 +326,9 @@ int8_t ata_pio2mode(int32_t); int ata_pmode(struct ata_params *); int ata_wmode(struct ata_params *); int ata_umode(struct ata_params *); +#if NPCI > 0 +int32_t ata_find_dev(device_t, int32_t, int32_t); +#endif void ata_dmainit(struct ata_softc *, int32_t, int32_t, int32_t, int32_t); int32_t ata_dmasetup(struct ata_softc *, int32_t, int8_t *, int32_t, int32_t); diff --git a/sys/dev/ata/ata-dma.c b/sys/dev/ata/ata-dma.c index 0f430a53f7ab..dc96bde13a11 100644 --- a/sys/dev/ata/ata-dma.c +++ b/sys/dev/ata/ata-dma.c @@ -280,7 +280,24 @@ ata_dmainit(struct ata_softc *scp, int32_t device, /* we could set PIO mode timings, but we assume the BIOS did that */ break; + case 0x74091022: /* AMD 756 */ + if (udmamode >= 4) { + error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, + ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY); + if (bootverbose) + ata_printf(scp, device, + "%s setting up UDMA4 mode on AMD chip\n", + (error) ? "failed" : "success"); + if (!error) { + pci_write_config(parent, 0x53 - devno, 0xc3, 1); + scp->mode[ATA_DEV(device)] = ATA_UDMA4; + return; + } + } + goto via_82c586; + case 0x06861106: /* VIA 82C686 */ +via_82c686: if (udmamode >= 4) { error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY); @@ -309,25 +326,14 @@ ata_dmainit(struct ata_softc *scp, int32_t device, } goto via_generic; - case 0x74091022: /* AMD 756 */ - if (udmamode >= 4) { - error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, - ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_printf(scp, device, - "%s setting up UDMA4 mode on AMD chip\n", - (error) ? "failed" : "success"); - if (!error) { - pci_write_config(parent, 0x53 - devno, 0xc3, 1); - scp->mode[ATA_DEV(device)] = ATA_UDMA4; - return; - } - } + case 0x05961106: /* VIA 82C596 */ + /* 82c596 revision >= 0x12 is like the 82c686 */ + if (ata_find_dev(parent, 0x05961106, 0x12)) + goto via_82c686; /* FALLTHROUGH */ - case 0x05961106: /* VIA 82C596 */ case 0x05861106: /* VIA 82C586 */ - +via_82c586: /* UDMA2 mode only on 82C586 > rev1, 82C596, AMD 756 */ if ((udmamode >= 2 && scp->chiptype == 0x05861106 && pci_read_config(scp->dev, 0x08, 1) >= 0x01) ||