From a9f41fe33b771520d3b9e8f1771988cc0a0bc7af Mon Sep 17 00:00:00 2001 From: bouyer Date: Sun, 16 Dec 2001 23:35:52 +0000 Subject: [PATCH] dd support for the Promise Ultra100TX2, Promise Ultra100TX2v2 and Ultra133 IDE controllers. In part from OpenBSD via ragge, in part from FreeBSD. --- sys/dev/pci/pciide.c | 210 +++++++++++++++++++++++++++++++------------ 1 file changed, 151 insertions(+), 59 deletions(-) diff --git a/sys/dev/pci/pciide.c b/sys/dev/pci/pciide.c index 36bd629cb93a..594133450868 100644 --- a/sys/dev/pci/pciide.c +++ b/sys/dev/pci/pciide.c @@ -1,4 +1,4 @@ -/* $NetBSD: pciide.c,v 1.137 2001/12/13 20:57:22 bouyer Exp $ */ +/* $NetBSD: pciide.c,v 1.138 2001/12/16 23:35:52 bouyer Exp $ */ /* @@ -77,7 +77,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: pciide.c,v 1.137 2001/12/13 20:57:22 bouyer Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pciide.c,v 1.138 2001/12/16 23:35:52 bouyer Exp $"); #ifndef WDCDEBUG #define WDCDEBUG @@ -192,6 +192,7 @@ static int acer_isabr_match __P(( struct pci_attach_args *)); void pdc202xx_chip_map __P((struct pciide_softc*, struct pci_attach_args*)); void pdc202xx_setup_channel __P((struct channel_softc*)); +void pdc20268_setup_channel __P((struct channel_softc*)); int pdc202xx_pci_intr __P((void *)); int pdc20265_pci_intr __P((void *)); @@ -420,6 +421,21 @@ const struct pciide_product_desc pciide_promise_products[] = { "Promise Ultra100/ATA Bus Master IDE Accelerator", pdc202xx_chip_map, }, + { PCI_PRODUCT_PROMISE_ULTRA100TX2, + IDE_PCI_CLASS_OVERRIDE, + "Promise Ultra100TX2/ATA Bus Master IDE Accelerator", + pdc202xx_chip_map, + }, + { PCI_PRODUCT_PROMISE_ULTRA100TX2v2, + IDE_PCI_CLASS_OVERRIDE, + "Promise Ultra100TX2v2/ATA Bus Master IDE Accelerator", + pdc202xx_chip_map, + }, + { PCI_PRODUCT_PROMISE_ULTRA133, + IDE_PCI_CLASS_OVERRIDE, + "Promise Ultra133/ATA Bus Master IDE Accelerator", + pdc202xx_chip_map, + }, { 0, 0, NULL, @@ -3390,10 +3406,20 @@ hpt_pci_intr(arg) #define PDC_IS_262(sc) \ ((sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_ULTRA66 || \ (sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_ULTRA100 || \ - (sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_ULTRA100X) + (sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_ULTRA100X || \ + (sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_ULTRA100TX2 || \ + (sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_ULTRA100TX2v2 || \ + (sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_ULTRA133) #define PDC_IS_265(sc) \ ((sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_ULTRA100 || \ - (sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_ULTRA100X) + (sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_ULTRA100X || \ + (sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_ULTRA100TX2 || \ + (sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_ULTRA100TX2v2 || \ + (sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_ULTRA133) +#define PDC_IS_268(sc) \ + ((sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_ULTRA100TX2 || \ + (sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_ULTRA100TX2v2 || \ + (sc)->sc_pp->ide_product == PCI_PRODUCT_PROMISE_ULTRA133) void pdc202xx_chip_map(sc, pa) @@ -3405,14 +3431,17 @@ pdc202xx_chip_map(sc, pa) pcireg_t interface, st, mode; bus_size_t cmdsize, ctlsize; - st = pci_conf_read(sc->sc_pc, sc->sc_tag, PDC2xx_STATE); - WDCDEBUG_PRINT(("pdc202xx_setup_chip: controller state 0x%x\n", st), - DEBUG_PROBE); + if (!PDC_IS_268(sc)) { + st = pci_conf_read(sc->sc_pc, sc->sc_tag, PDC2xx_STATE); + WDCDEBUG_PRINT(("pdc202xx_setup_chip: controller state 0x%x\n", + st), DEBUG_PROBE); + } if (pciide_chipen(sc, pa) == 0) return; /* turn off RAID mode */ - st &= ~PDC2xx_STATE_IDERAID; + if (!PDC_IS_268(sc)) + st &= ~PDC2xx_STATE_IDERAID; /* * can't rely on the PCI_CLASS_REG content if the chip was in raid @@ -3441,63 +3470,73 @@ pdc202xx_chip_map(sc, pa) sc->sc_wdcdev.UDMA_cap = 4; else sc->sc_wdcdev.UDMA_cap = 2; - sc->sc_wdcdev.set_modes = pdc202xx_setup_channel; + sc->sc_wdcdev.set_modes = PDC_IS_268(sc) ? + pdc20268_setup_channel : pdc202xx_setup_channel; sc->sc_wdcdev.channels = sc->wdc_chanarray; sc->sc_wdcdev.nchannels = PCIIDE_NUM_CHANNELS; - /* setup failsafe defaults */ - mode = 0; - mode = PDC2xx_TIM_SET_PA(mode, pdc2xx_pa[0]); - mode = PDC2xx_TIM_SET_PB(mode, pdc2xx_pb[0]); - mode = PDC2xx_TIM_SET_MB(mode, pdc2xx_dma_mb[0]); - mode = PDC2xx_TIM_SET_MC(mode, pdc2xx_dma_mc[0]); - for (channel = 0; channel < sc->sc_wdcdev.nchannels; channel++) { - WDCDEBUG_PRINT(("pdc202xx_setup_chip: channel %d drive 0 " - "initial timings 0x%x, now 0x%x\n", channel, - pci_conf_read(sc->sc_pc, sc->sc_tag, - PDC2xx_TIM(channel, 0)), mode | PDC2xx_TIM_IORDYp), + if (!PDC_IS_268(sc)) { + /* setup failsafe defaults */ + mode = 0; + mode = PDC2xx_TIM_SET_PA(mode, pdc2xx_pa[0]); + mode = PDC2xx_TIM_SET_PB(mode, pdc2xx_pb[0]); + mode = PDC2xx_TIM_SET_MB(mode, pdc2xx_dma_mb[0]); + mode = PDC2xx_TIM_SET_MC(mode, pdc2xx_dma_mc[0]); + for (channel = 0; + channel < sc->sc_wdcdev.nchannels; + channel++) { + WDCDEBUG_PRINT(("pdc202xx_setup_chip: channel %d " + "drive 0 initial timings 0x%x, now 0x%x\n", + channel, pci_conf_read(sc->sc_pc, sc->sc_tag, + PDC2xx_TIM(channel, 0)), mode | PDC2xx_TIM_IORDYp), + DEBUG_PROBE); + pci_conf_write(sc->sc_pc, sc->sc_tag, + PDC2xx_TIM(channel, 0), mode | PDC2xx_TIM_IORDYp); + WDCDEBUG_PRINT(("pdc202xx_setup_chip: channel %d " + "drive 1 initial timings 0x%x, now 0x%x\n", + channel, pci_conf_read(sc->sc_pc, sc->sc_tag, + PDC2xx_TIM(channel, 1)), mode), DEBUG_PROBE); + pci_conf_write(sc->sc_pc, sc->sc_tag, + PDC2xx_TIM(channel, 1), mode); + } + + mode = PDC2xx_SCR_DMA; + if (PDC_IS_262(sc)) { + mode = PDC2xx_SCR_SET_GEN(mode, PDC262_SCR_GEN_LAT); + } else { + /* the BIOS set it up this way */ + mode = PDC2xx_SCR_SET_GEN(mode, 0x1); + } + mode = PDC2xx_SCR_SET_I2C(mode, 0x3); /* ditto */ + mode = PDC2xx_SCR_SET_POLL(mode, 0x1); /* ditto */ + WDCDEBUG_PRINT(("pdc202xx_setup_chip: initial SCR 0x%x, " + "now 0x%x\n", + bus_space_read_4(sc->sc_dma_iot, sc->sc_dma_ioh, + PDC2xx_SCR), + mode), DEBUG_PROBE); + bus_space_write_4(sc->sc_dma_iot, sc->sc_dma_ioh, + PDC2xx_SCR, mode); + + /* controller initial state register is OK even without BIOS */ + /* Set DMA mode to IDE DMA compatibility */ + mode = + bus_space_read_1(sc->sc_dma_iot, sc->sc_dma_ioh, PDC2xx_PM); + WDCDEBUG_PRINT(("pdc202xx_setup_chip: primary mode 0x%x", mode), DEBUG_PROBE); - pci_conf_write(sc->sc_pc, sc->sc_tag, PDC2xx_TIM(channel, 0), - mode | PDC2xx_TIM_IORDYp); - WDCDEBUG_PRINT(("pdc202xx_setup_chip: channel %d drive 1 " - "initial timings 0x%x, now 0x%x\n", channel, - pci_conf_read(sc->sc_pc, sc->sc_tag, - PDC2xx_TIM(channel, 1)), mode), DEBUG_PROBE); - pci_conf_write(sc->sc_pc, sc->sc_tag, PDC2xx_TIM(channel, 1), - mode); + bus_space_write_1(sc->sc_dma_iot, sc->sc_dma_ioh, PDC2xx_PM, + mode | 0x1); + mode = + bus_space_read_1(sc->sc_dma_iot, sc->sc_dma_ioh, PDC2xx_SM); + WDCDEBUG_PRINT((", secondary mode 0x%x\n", mode ), DEBUG_PROBE); + bus_space_write_1(sc->sc_dma_iot, sc->sc_dma_ioh, PDC2xx_SM, + mode | 0x1); } - mode = PDC2xx_SCR_DMA; - if (PDC_IS_262(sc)) { - mode = PDC2xx_SCR_SET_GEN(mode, PDC262_SCR_GEN_LAT); - } else { - /* the BIOS set it up this way */ - mode = PDC2xx_SCR_SET_GEN(mode, 0x1); - } - mode = PDC2xx_SCR_SET_I2C(mode, 0x3); /* ditto */ - mode = PDC2xx_SCR_SET_POLL(mode, 0x1); /* ditto */ - WDCDEBUG_PRINT(("pdc202xx_setup_chip: initial SCR 0x%x, now 0x%x\n", - bus_space_read_4(sc->sc_dma_iot, sc->sc_dma_ioh, PDC2xx_SCR), mode), - DEBUG_PROBE); - bus_space_write_4(sc->sc_dma_iot, sc->sc_dma_ioh, PDC2xx_SCR, mode); - - /* controller initial state register is OK even without BIOS */ - /* Set DMA mode to IDE DMA compatibility */ - mode = bus_space_read_1(sc->sc_dma_iot, sc->sc_dma_ioh, PDC2xx_PM); - WDCDEBUG_PRINT(("pdc202xx_setup_chip: primary mode 0x%x", mode ), - DEBUG_PROBE); - bus_space_write_1(sc->sc_dma_iot, sc->sc_dma_ioh, PDC2xx_PM, - mode | 0x1); - mode = bus_space_read_1(sc->sc_dma_iot, sc->sc_dma_ioh, PDC2xx_SM); - WDCDEBUG_PRINT((", secondary mode 0x%x\n", mode ), DEBUG_PROBE); - bus_space_write_1(sc->sc_dma_iot, sc->sc_dma_ioh, PDC2xx_SM, - mode | 0x1); - for (channel = 0; channel < sc->sc_wdcdev.nchannels; channel++) { cp = &sc->pciide_channels[channel]; if (pciide_chansetup(sc, channel, interface) == 0) continue; - if ((st & (PDC_IS_262(sc) ? + if (!PDC_IS_268(sc) && (st & (PDC_IS_262(sc) ? PDC262_STATE_EN(channel):PDC246_STATE_EN(channel))) == 0) { printf("%s: %s channel ignored (disabled)\n", sc->sc_wdcdev.sc_dev.dv_xname, cp->name); @@ -3511,15 +3550,17 @@ pdc202xx_chip_map(sc, pa) pdc202xx_pci_intr); if (cp->hw_ok == 0) continue; - if (pciide_chan_candisable(cp)) + if (!PDC_IS_268(sc) && pciide_chan_candisable(cp)) st &= ~(PDC_IS_262(sc) ? PDC262_STATE_EN(channel):PDC246_STATE_EN(channel)); pciide_map_compat_intr(pa, cp, channel, interface); pdc202xx_setup_channel(&cp->wdc_channel); } - WDCDEBUG_PRINT(("pdc202xx_setup_chip: new controller state 0x%x\n", st), - DEBUG_PROBE); - pci_conf_write(sc->sc_pc, sc->sc_tag, PDC2xx_STATE, st); + if (!PDC_IS_268(sc)) { + WDCDEBUG_PRINT(("pdc202xx_setup_chip: new controller state " + "0x%x\n", st), DEBUG_PROBE); + pci_conf_write(sc->sc_pc, sc->sc_tag, PDC2xx_STATE, st); + } return; } @@ -3640,6 +3681,57 @@ pdc202xx_setup_channel(chp) pciide_print_modes(cp); } +void +pdc20268_setup_channel(chp) + struct channel_softc *chp; +{ + struct ata_drive_datas *drvp; + int drive; + u_int32_t idedma_ctl; + struct pciide_channel *cp = (struct pciide_channel*)chp; + struct pciide_softc *sc = (struct pciide_softc *)cp->wdc_channel.wdc; + int u100; + + /* setup DMA if needed */ + pciide_channel_dma_setup(cp); + + idedma_ctl = 0; + + /* I don't know what this is for, FreeBSD does it ... */ + bus_space_write_1(sc->sc_dma_iot, sc->sc_dma_ioh, + IDEDMA_CMD + 0x1, 0x0b); + + /* + * I don't know what this is for; FreeBSD checks this ... this is not + * cable type detect. + */ + u100 = (bus_space_read_1(sc->sc_dma_iot, sc->sc_dma_ioh, + IDEDMA_CMD + 0x3) & 0x04) ? 0 : 1; + + for (drive = 0; drive < 2; drive++) { + drvp = &chp->ch_drive[drive]; + /* If no drive, skip */ + if ((drvp->drive_flags & DRIVE) == 0) + continue; + if (drvp->drive_flags & DRIVE_UDMA) { + /* use Ultra/DMA */ + drvp->drive_flags &= ~DRIVE_DMA; + idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); + if (drvp->UDMA_mode > 2 && u100 == 0) + drvp->UDMA_mode = 2; + } else if (drvp->drive_flags & DRIVE_DMA) { + idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); + } + } + /* nothing to do to setup modes, the controller snoop SET_FEATURE cmd */ + if (idedma_ctl != 0) { + /* Add software bits in status register */ + bus_space_write_1(sc->sc_dma_iot, sc->sc_dma_ioh, + IDEDMA_CTL, idedma_ctl); + } + pciide_print_modes(cp); +} + int pdc202xx_pci_intr(arg) void *arg;