summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Gray <jsg@cvs.openbsd.org>2009-01-04 10:37:41 +0000
committerJonathan Gray <jsg@cvs.openbsd.org>2009-01-04 10:37:41 +0000
commit826a606e9dd903d3cbcf9474470229ebc91fa4fe (patch)
treefe1ce3ffb2d28bc8f2c5000bb77174b5b7bade78
parentced536a82bb817960eb514a92297e6389ed80845 (diff)
Add support for CS5535 IDE adapted from the gcscide code in NetBSD
originally written by Juan Romero Pardines. Thanks to Lars Kotthoff for testing on a HeroLogic HL-463 system. Because the CS5535 doesn't provide SMM emulated PCI access to set DMA/PIO modes or a real PCI IDE controller we have to resort to making MSR calls. As this is very MD specific, hide most of uglyness away in i386 MD pciide code. ok grange@
-rw-r--r--sys/arch/i386/pci/pciide_gcsc_reg.h87
-rw-r--r--sys/arch/i386/pci/pciide_machdep.c132
-rw-r--r--sys/dev/pci/pciide.c12
-rw-r--r--sys/dev/pci/pciidevar.h6
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 *,