From NetBSD:
authorchris <chris@openbsd.org>
Fri, 24 Mar 2000 17:47:41 +0000 (17:47 +0000)
committerchris <chris@openbsd.org>
Fri, 24 Mar 2000 17:47:41 +0000 (17:47 +0000)
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
sys/dev/pci/pciide_amd_reg.h [new file with mode: 0644]

index 66c5771..55b0712 100644 (file)
@@ -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 <dev/pci/pciidereg.h>
 #include <dev/pci/pciidevar.h>
 #include <dev/pci/pciide_piix_reg.h>
+#include <dev/pci/pciide_amd_reg.h>
 #include <dev/pci/pciide_apollo_reg.h>
 #include <dev/pci/pciide_cmd_reg.h>
 #include <dev/pci/pciide_cy693_reg.h>
@@ -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 (file)
index 0000000..f683e17
--- /dev/null
@@ -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};