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