diff options
-rw-r--r-- | sys/dev/pci/pciide.c | 123 | ||||
-rw-r--r-- | sys/dev/pci/pciide_cmd_reg.h | 62 |
2 files changed, 128 insertions, 57 deletions
diff --git a/sys/dev/pci/pciide.c b/sys/dev/pci/pciide.c index f5044b67ede..bfdebbef635 100644 --- a/sys/dev/pci/pciide.c +++ b/sys/dev/pci/pciide.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pciide.c,v 1.24 2000/06/13 03:56:41 chris Exp $ */ +/* $OpenBSD: pciide.c,v 1.25 2000/06/26 17:51:16 chris Exp $ */ /* $NetBSD: pciide.c,v 1.48 1999/11/28 20:05:18 bouyer Exp $ */ /* @@ -210,8 +210,8 @@ void apollo_chip_map __P((struct pciide_softc*, struct pci_attach_args*)); void apollo_setup_channel __P((struct channel_softc*)); void cmd_chip_map __P((struct pciide_softc*, struct pci_attach_args*)); -void cmd0643_6_chip_map __P((struct pciide_softc*, struct pci_attach_args*)); -void cmd0643_6_setup_channel __P((struct channel_softc*)); +void cmd0643_9_chip_map __P((struct pciide_softc*, struct pci_attach_args*)); +void cmd0643_9_setup_channel __P((struct channel_softc*)); void cmd_channel_map __P((struct pci_attach_args *, struct pciide_softc *, int)); int cmd_pci_intr __P((void *)); @@ -314,11 +314,19 @@ const struct pciide_product_desc pciide_cmd_products[] = { }, { PCI_PRODUCT_CMDTECH_643, /* CMD Technology PCI0643 */ 0, - cmd0643_6_chip_map + cmd0643_9_chip_map }, { PCI_PRODUCT_CMDTECH_646, /* CMD Technology PCI0646 */ 0, - cmd0643_6_chip_map + cmd0643_9_chip_map + }, + { PCI_PRODUCT_CMDTECH_648, /* CMD Technology PCI0648 */ + IDE_PCI_CLASS_OVERRIDE, + cmd0643_9_chip_map + }, + { PCI_PRODUCT_CMDTECH_649, /* CMD Technology PCI0649 */ + IDE_PCI_CLASS_OVERRIDE, + cmd0643_9_chip_map } }; @@ -2024,8 +2032,22 @@ cmd_channel_map(pa, sc, channel) struct pciide_channel *cp = &sc->pciide_channels[channel]; bus_size_t cmdsize, ctlsize; u_int8_t ctrl = pciide_pci_read(sc->sc_pc, sc->sc_tag, CMD_CTRL); - pcireg_t interface = - PCI_INTERFACE(pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_CLASS_REG)); + int interface; + + /* + * The 0648/0649 can be told to identify as a RAID controller. + * In this case, we have to fake interface + */ + if (PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_MASS_STORAGE_IDE) { + interface = PCIIDE_INTERFACE_SETTABLE(0) | + PCIIDE_INTERFACE_SETTABLE(1); + if (pciide_pci_read(pa->pa_pc, pa->pa_tag, CMD_CONF) & + CMD_CONF_DSA1) + interface |= PCIIDE_INTERFACE_PCI(0) | + PCIIDE_INTERFACE_PCI(1); + } else { + interface = PCI_INTERFACE(pa->pa_class); + } sc->wdc_chanarray[channel] = &cp->wdc_channel; cp->name = PCIIDE_CHANNEL_NAME(channel); @@ -2142,14 +2164,13 @@ cmd_chip_map(sc, pa) } void -cmd0643_6_chip_map(sc, pa) +cmd0643_9_chip_map(sc, pa) struct pciide_softc *sc; struct pci_attach_args *pa; { struct pciide_channel *cp; int channel; - pcireg_t interface = - PCI_INTERFACE(pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_CLASS_REG)); + pcireg_t interface = PCI_INTERFACE(pa->pa_class); /* * For a CMD PCI064x, the use of PCI_COMMAND_IO_ENABLE @@ -2167,20 +2188,27 @@ cmd0643_6_chip_map(sc, pa) #endif printf(": DMA"); pciide_mapreg_dma(sc, pa); - if (sc->sc_dma_ok) + sc->sc_wdcdev.cap = WDC_CAPABILITY_DATA16 | WDC_CAPABILITY_DATA32 | + WDC_CAPABILITY_MODE; + if (sc->sc_dma_ok) { sc->sc_wdcdev.cap |= WDC_CAPABILITY_DMA; + switch (sc->sc_pp->ide_product) { + case PCI_PRODUCT_CMDTECH_649: + case PCI_PRODUCT_CMDTECH_648: + sc->sc_wdcdev.cap |= WDC_CAPABILITY_UDMA; + sc->sc_wdcdev.UDMA_cap = 4; + } + } sc->sc_wdcdev.channels = sc->wdc_chanarray; sc->sc_wdcdev.nchannels = PCIIDE_NUM_CHANNELS; - sc->sc_wdcdev.cap |= WDC_CAPABILITY_DATA16 | WDC_CAPABILITY_DATA32 | - WDC_CAPABILITY_MODE; sc->sc_wdcdev.PIO_cap = 4; sc->sc_wdcdev.DMA_cap = 2; - sc->sc_wdcdev.set_modes = cmd0643_6_setup_channel; + sc->sc_wdcdev.set_modes = cmd0643_9_setup_channel; pciide_print_channels(sc->sc_wdcdev.nchannels, interface); - WDCDEBUG_PRINT(("cmd0643_6_chip_map: old timings reg 0x%x 0x%x\n", + WDCDEBUG_PRINT(("cmd0643_9_chip_map: old timings reg 0x%x 0x%x\n", pci_conf_read(sc->sc_pc, sc->sc_tag, 0x54), pci_conf_read(sc->sc_pc, sc->sc_tag, 0x58)), DEBUG_PROBE); @@ -2189,22 +2217,22 @@ cmd0643_6_chip_map(sc, pa) cmd_channel_map(pa, sc, channel); if (cp->hw_ok == 0) continue; - cmd0643_6_setup_channel(&cp->wdc_channel); + cmd0643_9_setup_channel(&cp->wdc_channel); } pciide_pci_write(sc->sc_pc, sc->sc_tag, CMD_DMA_MODE, CMD_DMA_MULTIPLE); - WDCDEBUG_PRINT(("cmd0643_6_chip_map: timings reg now 0x%x 0x%x\n", + WDCDEBUG_PRINT(("cmd0643_9_chip_map: timings reg now 0x%x 0x%x\n", pci_conf_read(sc->sc_pc, sc->sc_tag, 0x54), pci_conf_read(sc->sc_pc, sc->sc_tag, 0x58)), DEBUG_PROBE); } void -cmd0643_6_setup_channel(chp) +cmd0643_9_setup_channel(chp) struct channel_softc *chp; { struct ata_drive_datas *drvp; u_int8_t tim; - u_int32_t idedma_ctl; + u_int32_t idedma_ctl, udma_reg; int drive; struct pciide_channel *cp = (struct pciide_channel*)chp; struct pciide_softc *sc = (struct pciide_softc *)cp->wdc_channel.wdc; @@ -2219,18 +2247,51 @@ cmd0643_6_setup_channel(chp) if ((drvp->drive_flags & DRIVE) == 0) continue; /* add timing values, setup DMA if needed */ - tim = cmd0643_6_data_tim_pio[drvp->PIO_mode]; - if (drvp->drive_flags & DRIVE_DMA) { - /* - * use Multiword DMA. - * Timings will be used for both PIO and DMA, so adjust - * DMA mode if needed - */ - if (drvp->PIO_mode >= 3 && - (drvp->DMA_mode + 2) > drvp->PIO_mode) { - drvp->DMA_mode = drvp->PIO_mode - 2; + tim = cmd0643_9_data_tim_pio[drvp->PIO_mode]; + if (drvp->drive_flags & (DRIVE_DMA | DRIVE_UDMA)) { + if (drvp->drive_flags & DRIVE_UDMA) { + /* UltraDMA on a 0648 or 0649 */ + udma_reg = pciide_pci_read(sc->sc_pc, + sc->sc_tag, CMD_UDMATIM(chp->channel)); + if (drvp->UDMA_mode > 2 && + (pciide_pci_read(sc->sc_pc, sc->sc_tag, + CMD_BICSR) & + CMD_BICSR_80(chp->channel)) == 0) + drvp->UDMA_mode = 2; + if (drvp->UDMA_mode > 2) + udma_reg &= ~CMD_UDMATIM_UDMA33(drive); + else + udma_reg |= CMD_UDMATIM_UDMA33(drive); + udma_reg |= CMD_UDMATIM_UDMA(drive); + udma_reg &= ~(CMD_UDMATIM_TIM_MASK << + CMD_UDMATIM_TIM_OFF(drive)); + udma_reg |= + (cmd0648_9_tim_udma[drvp->UDMA_mode] << + CMD_UDMATIM_TIM_OFF(drive)); + pciide_pci_write(sc->sc_pc, sc->sc_tag, + CMD_UDMATIM(chp->channel), udma_reg); + } else { + /* + * use Multiword DMA. + * Timings will be used for both PIO and DMA, + * so adjust DMA mode if needed + * if we have a 0648/9, turn off UDMA + */ + if (sc->sc_wdcdev.cap & WDC_CAPABILITY_UDMA) { + udma_reg = pciide_pci_read(sc->sc_pc, + sc->sc_tag, + CMD_UDMATIM(chp->channel)); + udma_reg &= ~CMD_UDMATIM_UDMA(drive); + pciide_pci_write(sc->sc_pc, sc->sc_tag, + CMD_UDMATIM(chp->channel), + udma_reg); + } + if (drvp->PIO_mode >= 3 && + (drvp->DMA_mode + 2) > drvp->PIO_mode) { + drvp->DMA_mode = drvp->PIO_mode - 2; + } + tim = cmd0643_9_data_tim_dma[drvp->DMA_mode]; } - tim = cmd0643_6_data_tim_dma[drvp->DMA_mode]; idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); } pciide_pci_write(sc->sc_pc, sc->sc_tag, @@ -3079,7 +3140,7 @@ pdc202xx_setup_channel(chp) PDC262_U66); st = pci_conf_read(sc->sc_pc, sc->sc_tag, PDC2xx_STATE); /* Trim UDMA mode */ - if ((st & PDC262_STATE_80P(channel)) == 0 || + if ((st & PDC262_STATE_80P(channel)) != 0 || (chp->ch_drive[0].drive_flags & DRIVE_UDMA && chp->ch_drive[0].UDMA_mode <= 2) || (chp->ch_drive[1].drive_flags & DRIVE_UDMA && diff --git a/sys/dev/pci/pciide_cmd_reg.h b/sys/dev/pci/pciide_cmd_reg.h index e792e9f277f..62410cbeba3 100644 --- a/sys/dev/pci/pciide_cmd_reg.h +++ b/sys/dev/pci/pciide_cmd_reg.h @@ -1,5 +1,5 @@ -/* $OpenBSD: pciide_cmd_reg.h,v 1.2 1999/10/04 22:54:18 deraadt Exp $ */ -/* $NetBSD: pciide_cmd_reg.h,v 1.4 1998/12/02 10:52:25 bouyer Exp $ */ +/* $OpenBSD: pciide_cmd_reg.h,v 1.3 2000/06/26 17:51:17 chris Exp $ */ +/* $NetBSD: pciide_cmd_reg.h,v 1.7 2000/06/26 10:07:52 bouyer Exp $ */ /* * Copyright (c) 1998 Manuel Bouyer. @@ -20,17 +20,16 @@ * may be used to endorse or promote products derived from this software * without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ @@ -41,21 +40,21 @@ /* Configuration (RO) */ #define CMD_CONF 0x50 -#define CMD_CONF_REV_MASK 0x03 +#define CMD_CONF_REV_MASK 0x03 /* 0640/3/6 only */ #define CMD_CONF_DRV0_INTR 0x04 -#define CMD_CONF_DEVID 0x18 -#define CMD_CONF_VESAPRT 0x20 +#define CMD_CONF_DEVID 0x18 /* 0640/3/6 only */ +#define CMD_CONF_VESAPRT 0x20 /* 0640/3/6 only */ #define CMD_CONF_DSA1 0x40 -#define CMD_CONF_DSA0 0x80 +#define CMD_CONF_DSA0 0x80 /* 0640/3/6 only */ /* Control register (RW) */ #define CMD_CTRL 0x51 -#define CMD_CTRL_HR_FIFO 0x01 -#define CMD_CTRL_HW_FIFO 0x02 +#define CMD_CTRL_HR_FIFO 0x01 /* 0640/3/6 only */ +#define CMD_CTRL_HW_FIFO 0x02 /* 0640/3/6 only */ #define CMD_CTRL_DEVSEL 0x04 #define CMD_CTRL_2PORT 0x08 -#define CMD_CTRL_PAR 0x10 -#define CMD_CTRL_HW_HLD 0x20 +#define CMD_CTRL_PAR 0x10 /* 0640/3/6 only */ +#define CMD_CTRL_HW_HLD 0x20 /* 0640/3/6 only */ #define CMD_CTRL_DRV0_RAHEAD 0x40 #define CMD_CTRL_DRV1_RAHEAD 0x80 @@ -70,7 +69,7 @@ ((drive) == 0) ? 0x58 : 0x5b) /* secondary channel status and addr timings */ -#define CMD_ARTTIM23 0x57 +#define CMD_ARTTIM23 0x57 #define CMD_ARTTIM23_IRQ 0x10 #define CMD_ARTTIM23_RHAEAD(d) ((0x4) << (d)) @@ -79,12 +78,23 @@ #define CMD_DMA 0x00 #define CMD_DMA_MULTIPLE 0x01 #define CMD_DMA_LINE 0x10 - + +/* the followings are only for 0648/9 */ +/* busmaster control/status register */ +#define CMD_BICSR 0x79 +#define CMD_BICSR_80(chan) (0x01 << (chan)) +/* Ultra/DMA timings reg */ +#define CMD_UDMATIM(channel) (0x73 + (8 * (channel))) +#define CMD_UDMATIM_UDMA(drive) (0x01 << (drive)) +#define CMD_UDMATIM_UDMA33(drive) (0x04 << (drive)) +#define CMD_UDMATIM_TIM_MASK 0x3 +#define CMD_UDMATIM_TIM_OFF(drive) (4 + ((drive) * 2)) +static int8_t cmd0648_9_tim_udma[] = {0x03, 0x02, 0x01, 0x02, 0x01}; /* - * timings values for the 0643 and 0x646 + * timings values for the 0643/6/8/9 * for all dma_mode we have to have * DMA_timings(dma_mode) >= PIO_timings(dma_mode + 2) */ -static int8_t cmd0643_6_data_tim_pio[] = {0xA9, 0x57, 0x44, 0x32, 0x3F}; -static int8_t cmd0643_6_data_tim_dma[] = {0x87, 0x32, 0x3F}; +static int8_t cmd0643_9_data_tim_pio[] = {0xA9, 0x57, 0x44, 0x32, 0x3F}; +static int8_t cmd0643_9_data_tim_dma[] = {0x87, 0x32, 0x3F}; |