From 357cf0961c2baa332e4ad14a3a7d55b0d7986870 Mon Sep 17 00:00:00 2001 From: chris Date: Fri, 24 Mar 2000 17:47:41 +0000 Subject: [PATCH] From NetBSD: Don't reset cp->hw_ok ro 0 when cp isn't initialised in cy693_chip_map() Support for AMD 756 IDE controller --- sys/dev/pci/pciide.c | 156 ++++++++++++++++++++++++++++++++++- sys/dev/pci/pciide_amd_reg.h | 66 +++++++++++++++ 2 files changed, 218 insertions(+), 4 deletions(-) create mode 100644 sys/dev/pci/pciide_amd_reg.h diff --git a/sys/dev/pci/pciide.c b/sys/dev/pci/pciide.c index 66c57717bea..55b07125c97 100644 --- a/sys/dev/pci/pciide.c +++ b/sys/dev/pci/pciide.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pciide.c,v 1.20 2000/01/17 17:12:34 chris Exp $ */ +/* $OpenBSD: pciide.c,v 1.21 2000/03/24 17:47:41 chris Exp $ */ /* $NetBSD: pciide.c,v 1.48 1999/11/28 20:05:18 bouyer Exp $ */ /* @@ -103,6 +103,7 @@ int wdcdebug_pciide_mask = 0; #include #include #include +#include #include #include #include @@ -193,6 +194,9 @@ static u_int32_t piix_setup_idetim_timings __P((u_int8_t, u_int8_t, u_int8_t)); static u_int32_t piix_setup_idetim_drvs __P((struct ata_drive_datas*)); static u_int32_t piix_setup_sidetim_timings __P((u_int8_t, u_int8_t, u_int8_t)); +void amd756_chip_map __P((struct pciide_softc*, struct pci_attach_args*)); +void amd756_setup_channel __P((struct channel_softc*)); + void apollo_chip_map __P((struct pciide_softc*, struct pci_attach_args*)); void apollo_setup_channel __P((struct channel_softc*)); @@ -261,11 +265,18 @@ const struct pciide_product_desc pciide_intel_products[] = { }, { PCI_PRODUCT_INTEL_82801AA_IDE, /* Intel 82801AA IDE (ICH) */ 0, - piix_chip_map, + piix_chip_map }, { PCI_PRODUCT_INTEL_82801AB_IDE, /* Intel 82801AB IDE (ICH0) */ 0, - piix_chip_map, + piix_chip_map + }, +}; + +const struct pciide_product_desc pciide_amd_products[] = { + { PCI_PRODUCT_AMD_PBC756_IDE, /* AMD 756 */ + 0, + amd756_chip_map }, }; @@ -338,6 +349,8 @@ struct pciide_vendor_desc { const struct pciide_vendor_desc pciide_vendors[] = { { PCI_VENDOR_INTEL, pciide_intel_products, sizeof(pciide_intel_products)/sizeof(pciide_intel_products[0]) }, + { PCI_VENDOR_AMD, pciide_amd_products, + sizeof(pciide_amd_products)/sizeof(pciide_amd_products[0]) }, { PCI_VENDOR_CMDTECH, pciide_cmd_products, sizeof(pciide_cmd_products)/sizeof(pciide_cmd_products[0]) }, { PCI_VENDOR_VIATECH, pciide_via_products, @@ -1669,6 +1682,142 @@ piix_setup_sidetim_timings(mode, dma, channel) PIIX_SIDETIM_RTC_SET(piix_rtc_pio[mode], channel); } +void +amd756_chip_map(sc, pa) + struct pciide_softc *sc; + struct pci_attach_args *pa; +{ + struct pciide_channel *cp; + pcireg_t interface = PCI_INTERFACE(pci_conf_read(sc->sc_pc, + sc->sc_tag, PCI_CLASS_REG)); + int channel; + pcireg_t chanenable; + bus_size_t cmdsize, ctlsize; + + if (pciide_chipen(sc, pa) == 0) + return; + + printf(": DMA"); + pciide_mapreg_dma(sc, pa); + + if (sc->sc_dma_ok) + sc->sc_wdcdev.cap |= WDC_CAPABILITY_DMA | WDC_CAPABILITY_UDMA; + 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.UDMA_cap = 4; + sc->sc_wdcdev.set_modes = amd756_setup_channel; + sc->sc_wdcdev.channels = sc->wdc_chanarray; + sc->sc_wdcdev.nchannels = PCIIDE_NUM_CHANNELS; + chanenable = pci_conf_read(sc->sc_pc, sc->sc_tag, AMD756_CHANSTATUS_EN); + + pciide_print_channels(sc->sc_wdcdev.nchannels, interface); + + for (channel = 0; channel < sc->sc_wdcdev.nchannels; channel++) { + cp = &sc->pciide_channels[channel]; + if (pciide_chansetup(sc, channel, interface) == 0) + continue; + + if ((chanenable & AMD756_CHAN_EN(channel)) == 0) { + printf("%s: %s ignored (disabled)\n", + sc->sc_wdcdev.sc_dev.dv_xname, cp->name); + continue; + } + pciide_mapchan(pa, cp, interface, &cmdsize, &ctlsize, + pciide_pci_intr); + + if (pciiide_chan_candisable(cp)) + chanenable &= ~AMD756_CHAN_EN(channel); + pciide_map_compat_intr(pa, cp, channel, interface); + if (cp->hw_ok == 0) + continue; + + amd756_setup_channel(&cp->wdc_channel); + } + pci_conf_write(sc->sc_pc, sc->sc_tag, AMD756_CHANSTATUS_EN, + chanenable); + return; +} + +void +amd756_setup_channel(chp) + struct channel_softc *chp; +{ + u_int32_t udmatim_reg, datatim_reg; + u_int8_t idedma_ctl; + int mode, drive; + struct ata_drive_datas *drvp; + struct pciide_channel *cp = (struct pciide_channel*)chp; + struct pciide_softc *sc = (struct pciide_softc *)cp->wdc_channel.wdc; + + idedma_ctl = 0; + datatim_reg = pci_conf_read(sc->sc_pc, sc->sc_tag, AMD756_DATATIM); + udmatim_reg = pci_conf_read(sc->sc_pc, sc->sc_tag, AMD756_UDMA); + datatim_reg &= ~AMD756_DATATIM_MASK(chp->channel); + udmatim_reg &= ~AMD756_UDMA_MASK(chp->channel); + + /* setup DMA if needed */ + pciide_channel_dma_setup(cp); + + for (drive = 0; drive < 2; drive++) { + drvp = &chp->ch_drive[drive]; + /* If no drive, skip */ + if ((drvp->drive_flags & DRIVE) == 0) + continue; + /* add timing values, setup DMA if needed */ + if (((drvp->drive_flags & DRIVE_DMA) == 0 && + (drvp->drive_flags & DRIVE_UDMA) == 0)) { + mode = drvp->PIO_mode; + goto pio; + } + if ((chp->wdc->cap & WDC_CAPABILITY_UDMA) && + (drvp->drive_flags & DRIVE_UDMA)) { + /* use Ultra/DMA */ + drvp->drive_flags &= ~DRIVE_DMA; + udmatim_reg |= AMD756_UDMA_EN(chp->channel, drive) | + AMD756_UDMA_EN_MTH(chp->channel, drive) | + AMD756_UDMA_TIME(chp->channel, drive, + amd756_udma_tim[drvp->UDMA_mode]); + /* can use PIO timings, MW DMA unused */ + mode = drvp->PIO_mode; + } else { + /* use Multiword DMA */ + drvp->drive_flags &= ~DRIVE_UDMA; + /* mode = min(pio, dma+2) */ + if (drvp->PIO_mode <= (drvp->DMA_mode +2)) + mode = drvp->PIO_mode; + else + mode = drvp->DMA_mode + 2; + } + idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); + +pio: /* setup PIO mode */ + if (mode <= 2) { + drvp->DMA_mode = 0; + drvp->PIO_mode = 0; + mode = 0; + } else { + drvp->PIO_mode = mode; + drvp->DMA_mode = mode - 2; + } + datatim_reg |= + AMD756_DATATIM_PULSE(chp->channel, drive, + amd756_pio_set[mode]) | + AMD756_DATATIM_RECOV(chp->channel, drive, + amd756_pio_rec[mode]); + } + 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_SCH_OFFSET * chp->channel), + idedma_ctl); + } + pciide_print_modes(cp); + pci_conf_write(sc->sc_pc, sc->sc_tag, AMD756_DATATIM, datatim_reg); + pci_conf_write(sc->sc_pc, sc->sc_tag, AMD756_UDMA, udmatim_reg); +} + void apollo_chip_map(sc, pa) struct pciide_softc *sc; @@ -2072,7 +2221,6 @@ cy693_chip_map(sc, pa) } else { printf("%s: unexpected PCI function %d\n", sc->sc_wdcdev.sc_dev.dv_xname, pa->pa_function); - cp->hw_ok = 0; return; } if (interface & PCIIDE_INTERFACE_BUS_MASTER_DMA) { diff --git a/sys/dev/pci/pciide_amd_reg.h b/sys/dev/pci/pciide_amd_reg.h new file mode 100644 index 00000000000..f683e173bd7 --- /dev/null +++ b/sys/dev/pci/pciide_amd_reg.h @@ -0,0 +1,66 @@ +/* $OpenBSD: pciide_amd_reg.h,v 1.1 2000/03/24 17:47:41 chris Exp $ */ + +/* + * Copyright (c) 2000 David Sainty. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * 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. + * + */ + +/* + * Registers definitions for AMD 756 PCI IDE controller. Documentation + * available at: http://www.amd.com/products/cpg/athlon/techdocs/pdf/22548.pdf + */ + +/* Channel enable */ +#define AMD756_CHANSTATUS_EN 0x40 +#define AMD756_CHAN_EN(chan) (0x01 << (1 - (chan))) + +/* Data port timing controls */ +#define AMD756_DATATIM 0x48 +#define AMD756_DATATIM_MASK(channel) (0xffff << ((1 - (channel)) << 4)) +#define AMD756_DATATIM_RECOV(channel, drive, x) (((x) & 0xf) << \ + (((1 - (channel)) << 4) + ((1 - (drive)) << 3))) +#define AMD756_DATATIM_PULSE(channel, drive, x) (((x) & 0xf) << \ + (((1 - (channel)) << 4) + ((1 - (drive)) << 3) + 4)) + +static const int8_t amd756_pio_set[] = {0x0a, 0x0a, 0x0a, 0x02, 0x02}; +static const int8_t amd756_pio_rec[] = {0x08, 0x08, 0x08, 0x02, 0x00}; + +/* Ultra-DMA/33 control */ +#define AMD756_UDMA 0x50 +#define AMD756_UDMA_MASK(channel) (0xffff << ((1 - (channel)) << 4)) +#define AMD756_UDMA_TIME(channel, drive, x) (((x) & 0x7) << \ + (((1 - (channel)) << 4) + ((1 - (drive)) << 3))) +#define AMD756_UDMA_EN(channel, drive) (0x40 << \ + (((1 - (channel)) << 4) + ((1 - (drive)) << 3))) +#define AMD756_UDMA_EN_MTH(channel, drive) (0x80 << \ + (((1 - (channel)) << 4) + ((1 - (drive)) << 3))) + +static const int8_t amd756_udma_tim[] = {0x02, 0x01, 0x00, 0x04, 0x05}; -- 2.20.1