dd support for the Promise Ultra100TX2, Promise Ultra100TX2v2 and Ultra133

IDE controllers. In part from OpenBSD via ragge, in part from FreeBSD.
This commit is contained in:
bouyer 2001-12-16 23:35:52 +00:00
parent 3b488c3f27
commit a9f41fe33b
1 changed files with 151 additions and 59 deletions

View File

@ -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 <sys/cdefs.h>
__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;