summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorChris Cappuccio <chris@cvs.openbsd.org>2000-01-10 22:54:47 +0000
committerChris Cappuccio <chris@cvs.openbsd.org>2000-01-10 22:54:47 +0000
commit6066316e407d370dd62fa9c9158435213039c4a1 (patch)
treedbc9320ce04664181e3df796c0e9cdf8eafbd76e /sys
parenta29a78b5274d3d5066afd6263632abe5434eef38 (diff)
Sync w/NetBSD regarding Promise PDC20262 support (the Promise Ultra/66
controller actually works now!) and Manuel Bouyer's copyright.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/pci/pciide.c120
-rw-r--r--sys/dev/pci/pciide_pdc202xx_reg.h52
2 files changed, 136 insertions, 36 deletions
diff --git a/sys/dev/pci/pciide.c b/sys/dev/pci/pciide.c
index ed93953541c..03c839a880c 100644
--- a/sys/dev/pci/pciide.c
+++ b/sys/dev/pci/pciide.c
@@ -1,5 +1,38 @@
-/* $OpenBSD: pciide.c,v 1.15 1999/11/23 20:48:35 chris Exp $ */
-/* $NetBSD: pciide.c,v 1.40 1999/07/12 13:49:38 bouyer Exp $ */
+/* $OpenBSD: pciide.c,v 1.16 2000/01/10 22:54:45 chris Exp $ */
+/* $NetBSD: pciide.c,v 1.48 1999/11/28 20:05:18 bouyer Exp $ */
+
+/*
+ * Copyright (c) 1999 Manuel Bouyer.
+ *
+ * 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.
+ *
+ */
/*
* Copyright (c) 1996, 1998 Christopher G. Demetriou. All rights reserved.
@@ -2458,6 +2491,8 @@ acer_pci_intr(arg)
return rv;
}
+/* A macro to test product */
+#define PDC_IS_262(sc) (sc->sc_pp->ide_product == PCI_PRODUCT_PROMISE_ULTRA66)
void
pdc202xx_chip_map(sc, pa)
@@ -2495,7 +2530,7 @@ pdc202xx_chip_map(sc, pa)
sc->sc_wdcdev.cap |= WDC_CAPABILITY_DMA | WDC_CAPABILITY_UDMA;
sc->sc_wdcdev.PIO_cap = 4;
sc->sc_wdcdev.DMA_cap = 2;
- if (sc->sc_pp->ide_product == PCI_PRODUCT_PROMISE_ULTRA66)
+ if (PDC_IS_262(sc))
sc->sc_wdcdev.UDMA_cap = 4;
else
sc->sc_wdcdev.UDMA_cap = 2;
@@ -2529,7 +2564,12 @@ pdc202xx_chip_map(sc, pa)
}
mode = PDC2xx_SCR_DMA;
- mode = PDC2xx_SCR_SET_GEN(mode, 0x1); /* the BIOS set it up this way */
+ if (PDC_IS_262(sc)) {
+ mode = PDC2xx_SCR_SET_GEN(mode, PDC262_SCR_GEN_LAT);
+ } else {
+ /* the BIOS set it up this way */
+ mode = PDC2xx_SCR_SET_GEN(mode, 0x1);
+ }
mode = PDC2xx_SCR_SET_I2C(mode, 0x3); /* ditto */
mode = PDC2xx_SCR_SET_POLL(mode, 0x1); /* ditto */
WDCDEBUG_PRINT(("pdc202xx_setup_chip: initial SCR 0x%x, now 0x%x\n",
@@ -2538,7 +2578,7 @@ pdc202xx_chip_map(sc, pa)
bus_space_write_4(sc->sc_dma_iot, sc->sc_dma_ioh, PDC2xx_SCR, mode);
/* controller initial state register is OK even without BIOS */
- /* The Linux driver does this */
+ /* Set DMA mode to IDE DMA compatibility */
mode = bus_space_read_1(sc->sc_dma_iot, sc->sc_dma_ioh, PDC2xx_PM);
WDCDEBUG_PRINT(("pdc202xx_setup_chip: primary mode 0x%x", mode ),
DEBUG_PROBE);
@@ -2553,7 +2593,8 @@ pdc202xx_chip_map(sc, pa)
cp = &sc->pciide_channels[channel];
if (pciide_chansetup(sc, channel, interface) == 0)
continue;
- if ((st & PDC2xx_STATE_EN(channel)) == 0) {
+ if ((st & (PDC_IS_262(sc) ?
+ PDC262_STATE_EN(channel):PDC246_STATE_EN(channel))) == 0) {
printf("%s: %s ignored (disabled)\n",
sc->sc_wdcdev.sc_dev.dv_xname, cp->name);
continue;
@@ -2563,7 +2604,8 @@ pdc202xx_chip_map(sc, pa)
if (cp->hw_ok == 0)
continue;
if (pciiide_chan_candisable(cp))
- st &= ~PDC2xx_STATE_EN(channel);
+ st &= ~(PDC_IS_262(sc) ?
+ PDC262_STATE_EN(channel):PDC246_STATE_EN(channel));
pciide_map_compat_intr(pa, cp, channel, interface);
pdc202xx_setup_channel(&cp->wdc_channel);
}
@@ -2579,23 +2621,64 @@ pdc202xx_setup_channel(chp)
{
struct ata_drive_datas *drvp;
int drive;
- pcireg_t mode;
- u_int32_t idedma_ctl;
+ pcireg_t mode, st;
+ u_int32_t idedma_ctl, scr, atapi;
struct pciide_channel *cp = (struct pciide_channel*)chp;
struct pciide_softc *sc = (struct pciide_softc *)cp->wdc_channel.wdc;
+ int channel = chp->channel;
/* setup DMA if needed */
pciide_channel_dma_setup(cp);
idedma_ctl = 0;
+
+ /* Per channel settings */
+ if (PDC_IS_262(sc)) {
+ scr = bus_space_read_1(sc->sc_dma_iot, sc->sc_dma_ioh,
+ PDC262_U66);
+ st = pci_conf_read(sc->sc_pc, sc->sc_tag, PDC2xx_STATE);
+ /* Trim UDMA mode */
+ if ((st & PDC262_STATE_80P(channel)) == 0 ||
+ (chp->ch_drive[0].drive_flags & DRIVE_UDMA &&
+ chp->ch_drive[0].UDMA_mode <= 2) ||
+ (chp->ch_drive[1].drive_flags & DRIVE_UDMA &&
+ chp->ch_drive[1].UDMA_mode <= 2)) {
+ if (chp->ch_drive[0].UDMA_mode > 2)
+ chp->ch_drive[0].UDMA_mode = 2;
+ if (chp->ch_drive[1].UDMA_mode > 2)
+ chp->ch_drive[1].UDMA_mode = 2;
+ }
+ /* Set U66 if needed */
+ if ((chp->ch_drive[0].drive_flags & DRIVE_UDMA &&
+ chp->ch_drive[0].UDMA_mode > 2) ||
+ (chp->ch_drive[1].drive_flags & DRIVE_UDMA &&
+ chp->ch_drive[1].UDMA_mode > 2))
+ scr |= PDC262_U66_EN(channel);
+ else
+ scr &= ~PDC262_U66_EN(channel);
+ bus_space_write_1(sc->sc_dma_iot, sc->sc_dma_ioh,
+ PDC262_U66, scr);
+ if (chp->ch_drive[0].drive_flags & DRIVE_ATAPI ||
+ chp->ch_drive[1].drive_flags & DRIVE_ATAPI) {
+ if (((chp->ch_drive[0].drive_flags & DRIVE_UDMA) &&
+ !(chp->ch_drive[1].drive_flags & DRIVE_UDMA) &&
+ (chp->ch_drive[1].drive_flags & DRIVE_DMA)) ||
+ ((chp->ch_drive[1].drive_flags & DRIVE_UDMA) &&
+ !(chp->ch_drive[0].drive_flags & DRIVE_UDMA) &&
+ (chp->ch_drive[0].drive_flags & DRIVE_DMA)))
+ atapi = 0;
+ else
+ atapi = PDC262_ATAPI_UDMA;
+ bus_space_write_4(sc->sc_dma_iot, sc->sc_dma_ioh,
+ PDC262_ATAPI(channel), atapi);
+ }
+ }
for (drive = 0; drive < 2; drive++) {
drvp = &chp->ch_drive[drive];
/* If no drive, skip */
if ((drvp->drive_flags & DRIVE) == 0)
continue;
- mode = PDC2xx_TIM_IORDY;
- if (drvp->drive_flags & DRIVE_ATA)
- mode |= PDC2xx_TIM_PRE;
+ mode = 0;
if (drvp->drive_flags & DRIVE_UDMA) {
mode = PDC2xx_TIM_SET_MB(mode,
pdc2xx_udma_mb[drvp->UDMA_mode]);
@@ -2617,11 +2700,14 @@ pdc202xx_setup_channel(chp)
}
mode = PDC2xx_TIM_SET_PA(mode, pdc2xx_pa[drvp->PIO_mode]);
mode = PDC2xx_TIM_SET_PB(mode, pdc2xx_pb[drvp->PIO_mode]);
- mode |= PDC2xx_TIM_SYNC;
- if (drvp->PIO_mode >= 3 &&(drvp->drive_flags & DRIVE_ATA))
- mode |= PDC2xx_TIM_ERRDY;
- if (drive == 0)
- mode |= PDC2xx_TIM_IORDYp;
+ if (drvp->drive_flags & DRIVE_ATA)
+ mode |= PDC2xx_TIM_PRE;
+ mode |= PDC2xx_TIM_SYNC | PDC2xx_TIM_ERRDY;
+ if (drvp->PIO_mode >= 3) {
+ mode |= PDC2xx_TIM_IORDY;
+ if (drive == 0)
+ mode |= PDC2xx_TIM_IORDYp;
+ }
WDCDEBUG_PRINT(("pdc202xx_setup_channel: %s:%d:%d "
"timings 0x%x\n",
sc->sc_wdcdev.sc_dev.dv_xname,
diff --git a/sys/dev/pci/pciide_pdc202xx_reg.h b/sys/dev/pci/pciide_pdc202xx_reg.h
index 8e8d1751e45..8bae46615a4 100644
--- a/sys/dev/pci/pciide_pdc202xx_reg.h
+++ b/sys/dev/pci/pciide_pdc202xx_reg.h
@@ -1,3 +1,4 @@
+/* $OpenBSD: pciide_pdc202xx_reg.h,v 1.2 2000/01/10 22:54:46 chris Exp $ */
/* $NetBSD: pciide_pdc202xx_reg.h,v 1.1 1999/08/29 17:20:10 bouyer Exp $ */
/*
@@ -34,21 +35,24 @@
*/
/*
- * Registers definitions for PROMISE PDC20246 PCI IDE controller.
- * Unfortunably the HW docs available don't provide much informations
- * Most of the values set in registers comes from the FreeBSD and linux
- * drivers, and from experiments with the BIOS of a Promise Ultra/33 board.
+ * Registers definitions for PROMISE PDC20246/PDC20262 PCI IDE controller.
+ * Unfortunably the HW docs are not publically available. I've been able
+ * to get a partial one for the PDC20246, and a better one for the PDC20262
+ * from Promise.
*/
-/* controller initial state */
#define PDC2xx_STATE 0x50
-#define PDC2xx_STATE_SHIPID 0x8000
-#define PDC2xx_STATE_IOCHRDY 0x0400
-#define PDC2xx_STATE_LBA(channel) (0x0100 << (channel))
-#define PDC2xx_STATE_NATIVE 0x0080
-#define PDC2xx_STATE_ISAIRQ 0x0008
-#define PDC2xx_STATE_EN(channel) (0x0002 << (channel))
#define PDC2xx_STATE_IDERAID 0x0001
+#define PDC2xx_STATE_NATIVE 0x0080
+/* controller initial state values(PDC20246 only) */
+#define PDC246_STATE_SHIPID 0x8000
+#define PDC246_STATE_IOCHRDY 0x0400
+#define PDC246_STATE_LBA(channel) (0x0100 << (channel))
+#define PDC246_STATE_ISAIRQ 0x0008
+#define PDC246_STATE_EN(channel) (0x0002 << (channel))
+/* controller initial state values(PDC20262 only) */
+#define PDC262_STATE_EN(chan) (0x1000 << (chan))
+#define PDC262_STATE_80P(chan) (0x0400 << (chan))
/* per-drive timings */
#define PDC2xx_TIM(channel, drive) (0x60 + 4 * (drive) + 8 * (channel))
@@ -67,13 +71,16 @@
/* The following are extentions of the DMA registers */
+/* Ultra-DMA mode 3/4 control (PDC20262 only, 1 byte) */
+#define PDC262_U66 0x11
+#define PDC262_U66_EN(chan) (0x1 << ((chan) *2))
/* primary mode (1 byte) */
#define PDC2xx_PM 0x1a
/* secondary mode (1 byte) */
#define PDC2xx_SM 0x1b
/* System control register (4 bytes) */
#define PDC2xx_SCR 0x1c
-#define PDC2xx_SCR_SET_GEN(r,x) (((r) & 0xfffffff0) | ((x) & 0xf))
+#define PDC2xx_SCR_SET_GEN(r,x) (((r) & 0xffffff00) | ((x) & 0xff))
#define PDC2xx_SCR_EMPTY(channel) (0x00000100 << (4 * channel))
#define PDC2xx_SCR_FULL(channel) (0x00000200 << (4 * channel))
#define PDC2xx_SCR_INT(channel) (0x00000400 << (4 * channel))
@@ -86,17 +93,24 @@
#define PDC2xx_SCR_FLOAT 0x08000000
#define PDC2xx_SCR_RSET 0x10000000
#define PDC2xx_SCR_TST 0x20000000
+/* Values for "General Purpose Register" (PDC20262 only) */
+#define PDC262_SCR_GEN_LAT 0x20
+
+/* ATAPI port ((PDC20262 only) (4 bytes) */
+#define PDC262_ATAPI(chan) (0x20 + (4 * (chan)))
+#define PDC262_ATAPI_WC_MASK 0x00000fff
+#define PDC262_ATAPI_DMA_READ 0x00001000
+#define PDC262_ATAPI_DMA_WRITE 0x00002000
+#define PDC262_ATAPI_UDMA 0x00004000
/*
- * The timings provided here results from things gathered from the FreeBSD
- * driver and experimentations with the BIOS of a promise board.
- * Unfortunably I didn't have enouth HW to test all the modes.
- * They may be suboptimal.
+ * The timings provided here cmoes from the PDC20262 docs. I hope they are
+ * rigth for the PDC20246 too ...
*/
-static int8_t pdc2xx_pa[] = {0x4, 0x4, 0x4, 0x7, 0x3};
-static int8_t pdc2xx_pb[] = {0x13, 0x13, 0x13, 0xf, 0x7};
+static int8_t pdc2xx_pa[] = {0x9, 0x5, 0x3, 0x2, 0x1};
+static int8_t pdc2xx_pb[] = {0x13, 0xc, 0x8, 0x6, 0x4};
static int8_t pdc2xx_dma_mb[] = {0x7, 0x3, 0x3};
static int8_t pdc2xx_dma_mc[] = {0xf, 0x4, 0x3};
static int8_t pdc2xx_udma_mb[] = {0x3, 0x2, 0x1, 0x2, 0x1};
-static int8_t pdc2xx_udma_mc[] = {0x1, 0x1, 0x1, 0x1, 0x1};
+static int8_t pdc2xx_udma_mc[] = {0x3, 0x2, 0x1, 0x2, 0x1};