diff options
-rw-r--r-- | sys/arch/i386/pci/pciide_gcsc_reg.h | 87 | ||||
-rw-r--r-- | sys/arch/i386/pci/pciide_machdep.c | 132 | ||||
-rw-r--r-- | sys/dev/pci/pciide.c | 12 | ||||
-rw-r--r-- | sys/dev/pci/pciidevar.h | 6 |
4 files changed, 234 insertions, 3 deletions
diff --git a/sys/arch/i386/pci/pciide_gcsc_reg.h b/sys/arch/i386/pci/pciide_gcsc_reg.h new file mode 100644 index 00000000000..1e9a5148505 --- /dev/null +++ b/sys/arch/i386/pci/pciide_gcsc_reg.h @@ -0,0 +1,87 @@ +/* $OpenBSD: pciide_gcsc_reg.h,v 1.1 2009/01/04 10:37:40 jsg Exp $ */ +/* $NetBSD: gcscide.c,v 1.6 2007/10/06 07:21:03 xtraeme Exp $ */ + +/*- + * Copyright (c) 2007 Juan Romero Pardines. + * All rights reserved. + * + * 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. + * + * 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. + */ + + +/* + * 6.4 - ATA-5 Controller Register Definitions. + */ +#define GCSC_MSR_ATAC_BASE 0x51300000 +#define GCSC_ATAC_GLD_MSR_CAP (GCSC_MSR_ATAC_BASE + 0) +#define GCSC_ATAC_GLD_MSR_CONFIG (GCSC_MSR_ATAC_BASE + 0x01) +#define GCSC_ATAC_GLD_MSR_SMI (GCSC_MSR_ATAC_BASE + 0x02) +#define GCSC_ATAC_GLD_MSR_ERROR (GCSC_MSR_ATAC_BASE + 0x03) +#define GCSC_ATAC_GLD_MSR_PM (GCSC_MSR_ATAC_BASE + 0x04) +#define GCSC_ATAC_GLD_MSR_DIAG (GCSC_MSR_ATAC_BASE + 0x05) +#define GCSC_ATAC_IO_BAR (GCSC_MSR_ATAC_BASE + 0x08) +#define GCSC_ATAC_RESET (GCSC_MSR_ATAC_BASE + 0x10) +#define GCSC_ATAC_CH0D0_PIO (GCSC_MSR_ATAC_BASE + 0x20) +#define GCSC_ATAC_CH0D0_DMA (GCSC_MSR_ATAC_BASE + 0x21) +#define GCSC_ATAC_CH0D1_PIO (GCSC_MSR_ATAC_BASE + 0x22) +#define GCSC_ATAC_CH0D1_DMA (GCSC_MSR_ATAC_BASE + 0x23) +#define GCSC_ATAC_PCI_ABRTERR (GCSC_MSR_ATAC_BASE + 0x24) +#define GCSC_ATAC_BM0_CMD_PRIM 0x00 +#define GCSC_ATAC_BM0_STS_PRIM 0x02 +#define GCSC_ATAC_BM0_PRD 0x04 + +/* + * ATAC_CH0D0_DMA registers: + * + * PIO Format (bit 31): Format 1 allows independent control of command + * and data per drive, while Format 0 selects the slowest speed + * of the two drives. + */ +#define GCSC_ATAC_PIO_FORMAT (1 << 31) /* PIO Mode Format 1 */ +/* + * DMA_SEL (bit 20): sets Ultra DMA mode (if enabled) or Multi-word + * DMA mode (if disabled). + */ +#define GCSC_ATAC_DMA_SEL (1 << 20) + +/* PIO Format 1 settings */ +static const uint32_t gcsc_pio_timings[] = { + 0xf7f4f7f4, /* PIO Mode 0 */ + 0x53f3f173, /* PIO Mode 1 */ + 0x13f18141, /* PIO Mode 2 */ + 0x51315131, /* PIO Mode 3 */ + 0x11311131 /* PIO Mode 4 */ +}; + +static const uint32_t gcsc_mdma_timings[] = { + 0x7f0ffff3, /* MDMA Mode 0 */ + 0x7f035352, /* MDMA Mode 1 */ + 0x7f024241 /* MDMA Mode 2 */ +}; + +static const uint32_t gcsc_udma_timings[] = { + 0x7f7436a1, /* Ultra DMA Mode 0 */ + 0x7f733481, /* Ultra DMA Mode 1 */ + 0x7f723261, /* Ultra DMA Mode 2 */ + 0x7f713161, /* Ultra DMA Mode 3 */ + 0x7f703061 /* Ultra DMA Mode 4 */ +}; + diff --git a/sys/arch/i386/pci/pciide_machdep.c b/sys/arch/i386/pci/pciide_machdep.c index 6efa9eae90b..180267ad684 100644 --- a/sys/arch/i386/pci/pciide_machdep.c +++ b/sys/arch/i386/pci/pciide_machdep.c @@ -1,6 +1,31 @@ -/* $OpenBSD: pciide_machdep.c,v 1.6 2006/09/19 11:06:34 jsg Exp $ */ +/* $OpenBSD: pciide_machdep.c,v 1.7 2009/01/04 10:37:40 jsg Exp $ */ /* $NetBSD: pciide_machdep.c,v 1.2 1999/02/19 18:01:27 mycroft Exp $ */ +/*- + * Copyright (c) 2007 Juan Romero Pardines. + * All rights reserved. + * + * 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. + * + * 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. + */ + /* * Copyright (c) 1998 Christopher G. Demetriou. All rights reserved. * @@ -52,6 +77,11 @@ #include <dev/isa/isavar.h> +#include <machine/cpufunc.h> +#include <i386/pci/pciide_gcsc_reg.h> + +void gcsc_setup_channel(struct channel_softc *); + void * pciide_machdep_compat_intr_establish(struct device *dev, struct pci_attach_args *pa, int chan, int (*func)(void *), void *arg) @@ -70,3 +100,103 @@ pciide_machdep_compat_intr_disestablish(pci_chipset_tag_t pc, void *cookie) { isa_intr_disestablish(NULL, cookie); } + +void +gcsc_chip_map(struct pciide_softc *sc, struct pci_attach_args *pa) +{ + struct pciide_channel *cp; + pcireg_t interface; + bus_size_t cmdsize, ctlsize; + + printf(": DMA"); + pciide_mapreg_dma(sc, pa); + + 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 | WDC_CAPABILITY_UDMA; + sc->sc_wdcdev.cap |= WDC_CAPABILITY_IRQACK; + sc->sc_wdcdev.irqack = pciide_irqack; + } + + sc->sc_wdcdev.PIO_cap = 4; + sc->sc_wdcdev.DMA_cap = 2; + sc->sc_wdcdev.UDMA_cap = 4; + sc->sc_wdcdev.set_modes = gcsc_setup_channel; + sc->sc_wdcdev.channels = sc->wdc_chanarray; + sc->sc_wdcdev.nchannels = 1; + + interface = PCI_INTERFACE(pa->pa_class); + + pciide_print_channels(sc->sc_wdcdev.nchannels, interface); + + cp = &sc->pciide_channels[0]; + + if (pciide_chansetup(sc, 0, interface) == 0) + return; + + pciide_map_compat_intr(pa, cp, 0, interface); + if (cp->hw_ok == 0) + return; + + pciide_mapchan(pa, cp, interface, + &cmdsize, &ctlsize, pciide_pci_intr); + if (cp->hw_ok == 0) { + pciide_unmap_compat_intr(pa, cp, 0, interface); + return; + } + + gcsc_setup_channel(&cp->wdc_channel); +} + +void +gcsc_setup_channel(struct channel_softc *chp) +{ + struct pciide_channel *cp = (struct pciide_channel *)chp; + struct ata_drive_datas *drvp; + uint64_t reg = 0; + int drive, s; + + pciide_channel_dma_setup(cp); + + for (drive = 0; drive < 2; drive++) { + drvp = &chp->ch_drive[drive]; + if ((drvp->drive_flags & DRIVE) == 0) + continue; + + reg = rdmsr(drive ? GCSC_ATAC_CH0D1_DMA : + GCSC_ATAC_CH0D0_DMA); + + if (drvp->drive_flags & DRIVE_UDMA) { + s = splbio(); + drvp->drive_flags &= ~DRIVE_DMA; + splx(s); + /* Enable the Ultra DMA mode bit */ + reg |= GCSC_ATAC_DMA_SEL; + /* set the Ultra DMA mode */ + reg |= gcsc_udma_timings[drvp->UDMA_mode]; + + wrmsr(drive ? GCSC_ATAC_CH0D1_DMA : + GCSC_ATAC_CH0D0_DMA, reg); + + } else if (drvp->drive_flags & DRIVE_DMA) { + /* Enable the Multi-word DMA bit */ + reg &= ~GCSC_ATAC_DMA_SEL; + /* set the Multi-word DMA mode */ + reg |= gcsc_mdma_timings[drvp->DMA_mode]; + + wrmsr(drive ? GCSC_ATAC_CH0D1_DMA : + GCSC_ATAC_CH0D0_DMA, reg); + } + + /* Always use PIO Format 1. */ + wrmsr(drive ? GCSC_ATAC_CH0D1_DMA : + GCSC_ATAC_CH0D0_DMA, reg | GCSC_ATAC_PIO_FORMAT); + + /* Set PIO mode */ + wrmsr(drive ? GCSC_ATAC_CH0D1_PIO : GCSC_ATAC_CH0D0_PIO, + gcsc_pio_timings[drvp->PIO_mode]); + } + + pciide_print_modes(cp); +} diff --git a/sys/dev/pci/pciide.c b/sys/dev/pci/pciide.c index e03135a53b0..2e2acf4a134 100644 --- a/sys/dev/pci/pciide.c +++ b/sys/dev/pci/pciide.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pciide.c,v 1.291 2009/01/04 10:22:01 jsg Exp $ */ +/* $OpenBSD: pciide.c,v 1.292 2009/01/04 10:37:40 jsg Exp $ */ /* $NetBSD: pciide.c,v 1.127 2001/08/03 01:31:08 tsutsui Exp $ */ /* @@ -671,7 +671,17 @@ const struct pciide_product_desc pciide_sis_products[] = { } }; +/* + * The National/AMD CS5535 requires MSRs to set DMA/PIO modes so it + * has been banished to the MD i386 pciide_machdep + */ const struct pciide_product_desc pciide_natsemi_products[] = { +#ifdef __i386__ + { PCI_PRODUCT_NS_CS5535_IDE, /* National/AMD CS5535 IDE */ + 0, + gcsc_chip_map + }, +#endif { PCI_PRODUCT_NS_PC87415, /* National Semi PC87415 IDE */ 0, natsemi_chip_map diff --git a/sys/dev/pci/pciidevar.h b/sys/dev/pci/pciidevar.h index c957ba9db2d..fb7d3591388 100644 --- a/sys/dev/pci/pciidevar.h +++ b/sys/dev/pci/pciidevar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pciidevar.h,v 1.17 2009/01/04 10:22:01 jsg Exp $ */ +/* $OpenBSD: pciidevar.h,v 1.18 2009/01/04 10:37:40 jsg Exp $ */ /* $NetBSD: pciidevar.h,v 1.6 2001/01/12 16:04:00 bouyer Exp $ */ /* @@ -161,6 +161,10 @@ void pciide_print_channels(int, pcireg_t); * Functions defined by machine-dependent code. */ +#ifdef __i386__ +void gcsc_chip_map(struct pciide_softc *, struct pci_attach_args *); +#endif + /* Attach compat interrupt handler, returning handle or NULL if failed. */ #if !defined(pciide_machdep_compat_intr_establish) void *pciide_machdep_compat_intr_establish(struct device *, |