Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/pci Add support for the OPTi 82c621 PCIIDE controlle...



details:   https://anonhg.NetBSD.org/src/rev/50dcdc252ce8
branches:  trunk
changeset: 486707:50dcdc252ce8
user:      scw <scw%NetBSD.org@localhost>
date:      Sat May 27 17:18:41 2000 +0000

description:
Add support for the OPTi 82c621 PCIIDE controller and its derivatives.
I only have a Compaq laptop on which to test this, so reports of
success/failure in other systems would be welcomed.

diffstat:

 sys/dev/pci/pciide.c          |  182 +++++++++++++++++++++++++++++++++++++++++-
 sys/dev/pci/pciide_opti_reg.h |  167 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 348 insertions(+), 1 deletions(-)

diffs (truncated from 392 to 300 lines):

diff -r 59f65e8ef654 -r 50dcdc252ce8 sys/dev/pci/pciide.c
--- a/sys/dev/pci/pciide.c      Sat May 27 17:12:36 2000 +0000
+++ b/sys/dev/pci/pciide.c      Sat May 27 17:18:41 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: pciide.c,v 1.58 2000/05/15 08:46:00 bouyer Exp $       */
+/*     $NetBSD: pciide.c,v 1.59 2000/05/27 17:18:41 scw Exp $  */
 
 
 /*
@@ -115,6 +115,7 @@
 #include <dev/pci/pciide_sis_reg.h>
 #include <dev/pci/pciide_acer_reg.h>
 #include <dev/pci/pciide_pdc202xx_reg.h>
+#include <dev/pci/pciide_opti_reg.h>
 
 /* inlines for reading/writing 8-bit PCI registers */
 static __inline u_int8_t pciide_pci_read __P((pci_chipset_tag_t, pcitag_t,
@@ -184,6 +185,9 @@
 void pdc202xx_setup_channel __P((struct channel_softc*));
 int  pdc202xx_pci_intr __P((void *));
 
+void opti_chip_map __P((struct pciide_softc*, struct pci_attach_args*));
+void opti_setup_channel __P((struct channel_softc*));
+
 void pciide_channel_dma_setup __P((struct pciide_channel *));
 int  pciide_dma_table_setup __P((struct pciide_softc*, int, int));
 int  pciide_dma_init __P((void*, int, int, void *, size_t, int));
@@ -351,6 +355,28 @@
        }
 };
 
+const struct pciide_product_desc pciide_opti_products[] =  {
+       { PCI_PRODUCT_OPTI_82C621,
+         0,
+         "OPTi 82c621 PCI IDE controller",
+         opti_chip_map,
+       },
+       { PCI_PRODUCT_OPTI_82C568,
+         0,
+         "OPTi 82c568 (82c621 compatible) PCI IDE controller",
+         opti_chip_map,
+       },
+       { PCI_PRODUCT_OPTI_82D568,
+         0,
+         "OPTi 82d568 (82c621 compatible) PCI IDE controller",
+         opti_chip_map,
+       },
+       { 0,
+         0,
+         NULL,
+       }
+};
+
 struct pciide_vendor_desc {
        u_int32_t ide_vendor;
        const struct pciide_product_desc *ide_products;
@@ -365,6 +391,7 @@
        { PCI_VENDOR_ALI, pciide_acer_products },
        { PCI_VENDOR_PROMISE, pciide_promise_products },
        { PCI_VENDOR_AMD, pciide_amd_products },
+       { PCI_VENDOR_OPTI, pciide_opti_products },
        { 0, NULL }
 };
 
@@ -2861,3 +2888,156 @@
        }
        return rv;
 }
+
+void
+opti_chip_map(sc, pa)
+       struct pciide_softc *sc;
+       struct pci_attach_args *pa;
+{
+       struct pciide_channel *cp;
+       bus_size_t cmdsize, ctlsize;
+       pcireg_t interface;
+       u_int8_t init_ctrl;
+       int channel;
+
+       if (pciide_chipen(sc, pa) == 0)
+               return;
+       printf("%s: bus-master DMA support present",
+           sc->sc_wdcdev.sc_dev.dv_xname);
+       pciide_mapreg_dma(sc, pa);
+       printf("\n");
+
+       sc->sc_wdcdev.cap |= WDC_CAPABILITY_DATA16 | WDC_CAPABILITY_MODE;
+       sc->sc_wdcdev.PIO_cap = 4;
+       if (sc->sc_dma_ok) {
+               sc->sc_wdcdev.cap |= WDC_CAPABILITY_DMA;
+               sc->sc_wdcdev.DMA_cap = 2;
+       }
+       sc->sc_wdcdev.set_modes = opti_setup_channel;
+
+       sc->sc_wdcdev.channels = sc->wdc_chanarray;
+       sc->sc_wdcdev.nchannels = PCIIDE_NUM_CHANNELS;
+
+       init_ctrl = pciide_pci_read(sc->sc_pc, sc->sc_tag,
+           OPTI_REG_INIT_CONTROL);
+
+       interface = PCI_INTERFACE(pci_conf_read(sc->sc_pc,
+           sc->sc_tag, PCI_CLASS_REG));
+
+       for (channel = 0; channel < sc->sc_wdcdev.nchannels; channel++) {
+               cp = &sc->pciide_channels[channel];
+               if (pciide_chansetup(sc, channel, interface) == 0)
+                       continue;
+               if (channel == 1 &&
+                   (init_ctrl & OPTI_INIT_CONTROL_CH2_DISABLE) != 0) {
+                       printf("%s: %s channel ignored (disabled)\n",
+                           sc->sc_wdcdev.sc_dev.dv_xname, cp->name);
+                       continue;
+               }
+               pciide_mapchan(pa, cp, interface, &cmdsize, &ctlsize,
+                   pciide_pci_intr);
+               if (cp->hw_ok == 0)
+                       continue;
+               pciide_map_compat_intr(pa, cp, channel, interface);
+               if (cp->hw_ok == 0)
+                       continue;
+               opti_setup_channel(&cp->wdc_channel);
+       }
+}
+
+void
+opti_setup_channel(chp)
+       struct channel_softc *chp;
+{
+       struct ata_drive_datas *drvp;
+       struct pciide_channel *cp = (struct pciide_channel*)chp;
+       struct pciide_softc *sc = (struct pciide_softc *)cp->wdc_channel.wdc;
+       int drive;
+       int mode[2];
+       u_int8_t rv, mr;
+
+       /*
+        * The `Delay' and `Address Setup Time' fields of the
+        * Miscellaneous Register are always zero initially.
+        */
+       mr = opti_read_config(chp, OPTI_REG_MISC) & ~OPTI_MISC_INDEX_MASK;
+       mr &= ~(OPTI_MISC_DELAY_MASK |
+               OPTI_MISC_ADDR_SETUP_MASK |
+               OPTI_MISC_INDEX_MASK);
+
+       /* Prime the control register before setting timing values */
+       opti_write_config(chp, OPTI_REG_CONTROL, OPTI_CONTROL_DISABLE);
+
+       /* 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) {
+                       mode[drive] = -1;
+                       continue;
+               }
+
+               if ((drvp->drive_flags & DRIVE_DMA)) {
+                       /*
+                        * Timings will be used for both PIO and DMA,
+                        * so adjust DMA mode if needed
+                        */
+                       if (drvp->PIO_mode > (drvp->DMA_mode + 2))
+                               drvp->PIO_mode = drvp->DMA_mode + 2;
+                       if (drvp->DMA_mode + 2 > (drvp->PIO_mode))
+                               drvp->DMA_mode = (drvp->PIO_mode > 2) ?
+                                   drvp->PIO_mode - 2 : 0;
+                       if (drvp->DMA_mode == 0)
+                               drvp->PIO_mode = 0;
+
+                       mode[drive] = drvp->DMA_mode + 5;
+               } else
+                       mode[drive] = drvp->PIO_mode;
+
+               if (drive && mode[0] >= 0 &&
+                   (opti_tim_as[mode[0]] != opti_tim_as[mode[1]])) {
+                       /*
+                        * Can't have two drives using different values
+                        * for `Address Setup Time'.
+                        * Slow down the faster drive to compensate.
+                        */
+                       int d;
+                       d = (opti_tim_as[mode[0]] > opti_tim_as[mode[1]])?0:1;
+
+                       mode[d] = mode[1-d];
+                       chp->ch_drive[d].PIO_mode = chp->ch_drive[1-d].PIO_mode;
+                       chp->ch_drive[d].DMA_mode = 0;
+                       chp->ch_drive[d].drive_flags &= DRIVE_DMA;
+               }
+       }
+
+       for (drive = 0; drive < 2; drive++) {
+               int m;
+               if ((m = mode[drive]) < 0)
+                       continue;
+
+               /* Set the Address Setup Time and select appropriate index */
+               rv = opti_tim_as[m] << OPTI_MISC_ADDR_SETUP_SHIFT;
+               rv |= OPTI_MISC_INDEX(drive);
+               opti_write_config(chp, OPTI_REG_MISC, mr | rv);
+
+               /* Set the pulse width and recovery timing parameters */
+               rv  = opti_tim_cp[m] << OPTI_PULSE_WIDTH_SHIFT;
+               rv |= opti_tim_rt[m] << OPTI_RECOVERY_TIME_SHIFT;
+               opti_write_config(chp, OPTI_REG_READ_CYCLE_TIMING, rv);
+               opti_write_config(chp, OPTI_REG_WRITE_CYCLE_TIMING, rv);
+
+               /* Set the Enhanced Mode register appropriately */
+               rv = pciide_pci_read(sc->sc_pc, sc->sc_tag, OPTI_REG_ENH_MODE);
+               rv &= ~OPTI_ENH_MODE_MASK(chp->channel, drive);
+               rv |= OPTI_ENH_MODE(chp->channel, drive, opti_tim_em[m]);
+               pciide_pci_write(sc->sc_pc, sc->sc_tag, OPTI_REG_ENH_MODE, rv);
+       }
+
+       /* Finally, enable the timings */
+       opti_write_config(chp, OPTI_REG_CONTROL, OPTI_CONTROL_ENABLE);
+
+       pciide_print_modes(cp);
+}
diff -r 59f65e8ef654 -r 50dcdc252ce8 sys/dev/pci/pciide_opti_reg.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/pci/pciide_opti_reg.h     Sat May 27 17:18:41 2000 +0000
@@ -0,0 +1,167 @@
+/*     $NetBSD: pciide_opti_reg.h,v 1.1 2000/05/27 17:18:41 scw Exp $  */
+
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Steve C. Woodford.
+ *
+ * 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 NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+/*
+ * Register definitions for OPTi PCIIDE controllers based on
+ * their 82c621 chip.
+ */
+
+/* IDE Initialization Control Register */
+#define OPTI_REG_INIT_CONTROL          0x40
+#define  OPTI_INIT_CONTROL_MODE_PIO_0  0
+#define  OPTI_INIT_CONTROL_MODE_PIO_1  2
+#define  OPTI_INIT_CONTROL_MODE_PIO_2  1
+#define  OPTI_INIT_CONTROL_MODE_PIO_3  3
+#define  OPTI_INIT_CONTROL_ADDR_RELOC  (1u << 2)
+#define  OPTI_INIT_CONTROL_CH2_ENABLE  0
+#define  OPTI_INIT_CONTROL_CH2_DISABLE (1u << 3)
+#define  OPTI_INIT_CONTROL_FIFO_16     0
+#define  OPTI_INIT_CONTROL_FIFO_32     (1u << 5)
+#define  OPTI_INIT_CONTROL_FIFO_REQ_32 0
+#define  OPTI_INIT_CONTROL_FIFO_REQ_30 (1u << 6)
+#define  OPTI_INIT_CONTROL_FIFO_REQ_28 (2u << 6)
+#define  OPTI_INIT_CONTROL_FIFO_REQ_26 (3u << 6)
+
+/* IDE Enhanced Features Register */
+#define OPTI_REG_ENH_FEAT              0x42
+#define  OPTI_ENH_FEAT_X111_ENABLE     (1u << 1)
+#define  OPTI_ENH_FEAT_CONCURRENT_MAST (1u << 2)
+#define  OPTI_ENH_FEAT_PCI_INVALIDATE  (1u << 3)
+#define  OPTI_ENH_FEAT_IDE_CONCUR      (1u << 4)
+#define  OPTI_ENH_FEAT_SLAVE_FIFO_ISA  (1u << 5)
+
+/* IDE Enhanced Mode Register */
+#define OPTI_REG_ENH_MODE              0x43
+#define  OPTI_ENH_MODE_MASK(c,d)       (3u << (((c) * 4) + ((d) * 2)))
+#define  OPTI_ENH_MODE_USE_TIMING(c,d) 0
+#define  OPTI_ENH_MODE(c,d,m)          ((m) << (((c) * 4) + ((d) * 2)))
+
+/* Timing registers */
+#define OPTI_REG_READ_CYCLE_TIMING     0x00



Home | Main Index | Thread Index | Old Index