Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/netbsd-2-0]: src/sys/dev/pci Pull up revision 1.2 (requested by rumble i...



details:   https://anonhg.NetBSD.org/src/rev/5c9c0ad5a918
branches:  netbsd-2-0
changeset: 562243:5c9c0ad5a918
user:      tron <tron%NetBSD.org@localhost>
date:      Wed Jul 28 10:56:06 2004 +0000

description:
Pull up revision 1.2 (requested by rumble in ticket #718):
Add support for the controller found on the AMD (previously
NatSemi) Geode SC1100 controller (as found on the Soekris
NET4801). The chip has two bugs: the first requires dword
alignment, and the second cannot handle exact 64K transfers.
Also, fix a few typos while we're here.
Timings from FreeBSD. Reviewed by Manuel Bouyer.

diffstat:

 sys/dev/pci/geodeide.c         |  94 ++++++++++++++++++++++++++++++++++++-----
 sys/dev/pci/pciide_geode_reg.h |  32 +++++++++----
 2 files changed, 104 insertions(+), 22 deletions(-)

diffs (210 lines):

diff -r 878949338d37 -r 5c9c0ad5a918 sys/dev/pci/geodeide.c
--- a/sys/dev/pci/geodeide.c    Wed Jul 28 10:54:40 2004 +0000
+++ b/sys/dev/pci/geodeide.c    Wed Jul 28 10:56:06 2004 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: geodeide.c,v 1.1.2.2 2004/07/14 09:08:28 tron Exp $    */
+/*     $NetBSD: geodeide.c,v 1.1.2.3 2004/07/28 10:56:06 tron Exp $    */
 
 /*
  * Copyright (c) 2004 Manuel Bouyer.
@@ -31,16 +31,19 @@
  */
 
 /*
- * Driver for the IDE part of the AMD Geode CS5530A compagnion chip
+ * Driver for the IDE part of the AMD Geode CS5530A companion chip
+ * and AMD Geode SC1100.
  * Docs available from AMD's web site
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: geodeide.c,v 1.1.2.2 2004/07/14 09:08:28 tron Exp $");
+__KERNEL_RCSID(0, "$NetBSD: geodeide.c,v 1.1.2.3 2004/07/28 10:56:06 tron Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
 
+#include <uvm/uvm_extern.h>
+
 #include <dev/pci/pcivar.h>
 #include <dev/pci/pcidevs.h>
 #include <dev/pci/pciidereg.h>
@@ -64,6 +67,11 @@
          "AMD Geode CX5530 IDE controller",
          geodeide_chip_map,
        },
+       { PCI_PRODUCT_NS_SC1100_IDE,
+         0,
+         "AMD Geode SC1100 IDE controller",
+         geodeide_chip_map,
+       },
        { 0,
          0,
          NULL,
@@ -76,10 +84,11 @@
 {
        struct pci_attach_args *pa = aux;
 
-       if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_CYRIX &&
-           PCI_CLASS(pa->pa_class) == PCI_CLASS_MASS_STORAGE &&
-           PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_MASS_STORAGE_IDE &&
-           pciide_lookup_product(pa->pa_id, pciide_geode_products)) 
+       if ((PCI_VENDOR(pa->pa_id) == PCI_VENDOR_CYRIX ||
+            PCI_VENDOR(pa->pa_id) == PCI_VENDOR_NS) &&
+            PCI_CLASS(pa->pa_class) == PCI_CLASS_MASS_STORAGE &&
+            PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_MASS_STORAGE_IDE &&
+            pciide_lookup_product(pa->pa_id, pciide_geode_products)) 
                return(2);
        return (0);
 }
@@ -122,6 +131,21 @@
        sc->sc_wdcdev.cap |= WDC_CAPABILITY_DATA16 | WDC_CAPABILITY_DATA32 |
            WDC_CAPABILITY_MODE;
 
+       /*
+        * Soekris Engineering Issue #0003:
+        *      "The SC1100 built in busmaster IDE controller is pretty
+        *       standard, but have two bugs: data transfers need to be
+        *       dword aligned and it cannot do an exact 64Kbyte data
+        *       transfer."
+        */
+       if (sc->sc_pp->ide_product == PCI_PRODUCT_NS_SC1100_IDE) {
+               if (sc->sc_dma_boundary == 0x10000)
+                       sc->sc_dma_boundary -= PAGE_SIZE;
+
+               if (sc->sc_dma_maxsegsz == 0x10000)
+                       sc->sc_dma_maxsegsz -= PAGE_SIZE;
+       }
+
        for (channel = 0; channel < sc->sc_wdcdev.nchannels; channel++) {
                cp = &sc->pciide_channels[channel];
                /* controller is compat-only */
@@ -141,6 +165,25 @@
        int drive;
        u_int32_t dma_timing;
        u_int8_t idedma_ctl;
+       const int32_t *geode_pio;
+       const int32_t *geode_dma;
+       const int32_t *geode_udma;
+       bus_size_t dmaoff, piooff;
+
+       switch (sc->sc_pp->ide_product) {
+       case PCI_PRODUCT_CYRIX_CX5530_IDE:
+               geode_pio = geode_cs5530_pio;
+               geode_dma = geode_cs5530_dma;
+               geode_udma = geode_cs5530_udma;
+               break;
+
+       case PCI_PRODUCT_NS_SC1100_IDE:
+       default: /* XXX gcc */
+               geode_pio = geode_sc1100_pio;
+               geode_dma = geode_sc1100_dma;
+               geode_udma = geode_sc1100_udma;
+               break;
+       }
 
        /* setup DMA if needed */
        pciide_channel_dma_setup(cp);
@@ -153,7 +196,22 @@
                /* If no drive, skip */
                if ((drvp->drive_flags & DRIVE) == 0)
                        continue;
-               dma_timing = DMA_REG_PIO_FORMAT;
+
+               switch (sc->sc_pp->ide_product) {
+               case PCI_PRODUCT_CYRIX_CX5530_IDE:
+                       dmaoff = CS5530_DMA_REG(channel, drive);
+                       piooff = CS5530_PIO_REG(channel, drive);
+                       dma_timing = CS5530_DMA_REG_PIO_FORMAT;
+                       break;
+
+               case PCI_PRODUCT_NS_SC1100_IDE:
+               default: /* XXX gcc */
+                       dmaoff = SC1100_DMA_REG(channel, drive);
+                       piooff = SC1100_PIO_REG(channel, drive);
+                       dma_timing = 0;
+                       break;
+               }
+
                /* add timing values, setup DMA if needed */
                if (drvp->drive_flags & DRIVE_UDMA) {
                        /* Use Ultra-DMA */
@@ -167,10 +225,22 @@
                        /* PIO only */
                        drvp->drive_flags &= ~(DRIVE_UDMA | DRIVE_DMA);
                }
-               bus_space_write_4(sc->sc_dma_iot, sc->sc_dma_ioh,
-                   DMA_REG(channel, drive), dma_timing);
-               bus_space_write_4(sc->sc_dma_iot, sc->sc_dma_ioh,
-                   PIO_REG(channel, drive), geode_pio[drvp->PIO_mode]);
+
+               switch (sc->sc_pp->ide_product) {
+               case PCI_PRODUCT_CYRIX_CX5530_IDE:
+                       bus_space_write_4(sc->sc_dma_iot, sc->sc_dma_ioh,
+                           dmaoff, dma_timing);
+                       bus_space_write_4(sc->sc_dma_iot, sc->sc_dma_ioh,
+                           piooff, geode_pio[drvp->PIO_mode]);
+                       break;
+
+               case PCI_PRODUCT_NS_SC1100_IDE:
+                       pci_conf_write(sc->sc_pc, sc->sc_tag, dmaoff,
+                           dma_timing);
+                       pci_conf_write(sc->sc_pc, sc->sc_tag, piooff,
+                           geode_pio[drvp->PIO_mode]);
+                       break;
+               }
        }
 
        if (idedma_ctl != 0) {
diff -r 878949338d37 -r 5c9c0ad5a918 sys/dev/pci/pciide_geode_reg.h
--- a/sys/dev/pci/pciide_geode_reg.h    Wed Jul 28 10:54:40 2004 +0000
+++ b/sys/dev/pci/pciide_geode_reg.h    Wed Jul 28 10:56:06 2004 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: pciide_geode_reg.h,v 1.1.2.2 2004/07/14 09:08:28 tron Exp $    */
+/*     $NetBSD: pciide_geode_reg.h,v 1.1.2.3 2004/07/28 10:56:06 tron Exp $    */
 
 /*
  * Copyright (c) 2004 Manuel Bouyer.
@@ -30,21 +30,33 @@
  *
  */
 
-#define PIO_REG(chan, drv)     (0x20 + (chan) * 0x10 + (drv) * 0x8)
-#define DMA_REG(chan, drv)     (0x24 + (chan) * 0x10 + (drv) * 0x8)
-#define        DMA_REG_PIO_FORMAT      0x80000000 /* select PIO format 1 */
-#define                DMA_REG_UDMA            0x00100000 /* enable Ultra-DMA */
+#define CS5530_PIO_REG(chan, drv)      (0x20 + (chan) * 0x10 + (drv) * 0x8)
+#define CS5530_DMA_REG(chan, drv)      (0x24 + (chan) * 0x10 + (drv) * 0x8)
+#define CS5530_DMA_REG_PIO_FORMAT      0x80000000 /* select PIO format 1 */
+#define CS5530_DMA_REG_UDMA            0x00100000 /* enable Ultra-DMA */
 
 /*
- * Recommeded values from the cs5530 data sheet.
- * Note that the udma values include DMA_REG_UDMA.
+ * Recommended values from the cs5530 data sheet.
+ * Note that the udma values include CS5530_DMA_REG_UDMA.
  * However, from the datasheet bits 30-21 should be reserved, yet 
  * geode_udma sets bit 23 to 1. I don't know if it's the definition of
  * DMA_REG_UDMA which is wrong (bit 23 instead of 20) or these values.
  */
-static const int32_t geode_pio[] __attribute__((__unused__)) =
+static const int32_t geode_cs5530_pio[] __attribute__((__unused__)) =
     {0x9172d132, 0x21717121, 0x00803020, 0x20102010, 0x00100010};
-static const int32_t geode_dma[] __attribute__((__unused__)) =
+static const int32_t geode_cs5530_dma[] __attribute__((__unused__)) =
     {0x00077771, 0x00012121, 0x00002020};
-static const int32_t geode_udma[] __attribute__((__unused__)) =
+static const int32_t geode_cs5530_udma[] __attribute__((__unused__)) =
     {0x00921250, 0x00911140, 0x00911030};
+
+#define SC1100_PIO_REG(chan, drv)      (0x40 + (chan) * 0x10 + (drv) * 0x8)
+#define SC1100_DMA_REG(chan, drv)      (0x44 + (chan) * 0x10 + (drv) * 0x8)
+
+/* Timings from FreeBSD */
+static const int32_t geode_sc1100_pio[] __attribute__((__unused__)) =
+    {0x9172d132, 0x21717121, 0x00803020, 0x20102010, 0x00100010, 0x00803020,
+     0x20102010, 0x00100010, 0x00100010, 0x00100010, 0x00100010};
+static const int32_t geode_sc1100_dma[] __attribute__((__unused__)) =
+    {0x80077771, 0x80012121, 0x80002020};
+static const int32_t geode_sc1100_udma[] __attribute__((__unused__)) =
+    {0x80921250, 0x80911140, 0x80911030};



Home | Main Index | Thread Index | Old Index