Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys Changes to the wdc(4) mi driver that add the WDC_CAPABIL...
details: https://anonhg.NetBSD.org/src/rev/5afb566782c0
branches: trunk
changeset: 520338:5afb566782c0
user: dbj <dbj%NetBSD.org@localhost>
date: Mon Jan 07 22:11:17 2002 +0000
description:
Changes to the wdc(4) mi driver that add the WDC_CAPABILITY_SELECT
flag and a callback function which gets called whenever a target is
selected on a channel.
The macppc wdc driver needs to reprogram its timing register
differently for each target on a channel each time that target is
selected. I also changed the ATA4_TIME_TO_TICK to use a divisor of
15, which brings our timing calculations consistent with darwin.
These patches fix problems on my dual usb ibook with combo dvd/cdrw
drive because the hard drive supports udma and the combo drive does
not. Without turning off the udma timings in the configuration
register, I cannot access the non-udma combo drive.
diffstat:
sys/arch/macppc/dev/wdc_obio.c | 225 ++++++++++++++++++++--------------------
sys/dev/ic/wdc.c | 37 ++++++-
sys/dev/ic/wdcvar.h | 6 +-
3 files changed, 155 insertions(+), 113 deletions(-)
diffs (truncated from 453 to 300 lines):
diff -r 97fac036cb1b -r 5afb566782c0 sys/arch/macppc/dev/wdc_obio.c
--- a/sys/arch/macppc/dev/wdc_obio.c Mon Jan 07 22:07:37 2002 +0000
+++ b/sys/arch/macppc/dev/wdc_obio.c Mon Jan 07 22:11:17 2002 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: wdc_obio.c,v 1.17 2001/09/09 16:08:49 bouyer Exp $ */
+/* $NetBSD: wdc_obio.c,v 1.18 2002/01/07 22:11:19 dbj Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -71,6 +71,7 @@
struct channel_softc wdc_channel;
dbdma_regmap_t *sc_dmareg;
dbdma_command_t *sc_dmacmd;
+ u_int sc_dmaconf[2]; /* per target value of CONFIG_REG */
void *sc_ih;
};
@@ -80,6 +81,8 @@
int wdc_obio_dma_init __P((void *, int, int, void *, size_t, int));
void wdc_obio_dma_start __P((void *, int, int));
int wdc_obio_dma_finish __P((void *, int, int, int));
+
+static void wdc_obio_select __P((struct channel_softc *, int));
static void adjust_timing __P((struct channel_softc *));
static void ata4_adjust_timing __P((struct channel_softc *));
@@ -260,75 +263,83 @@
#define DMA_REC_MIN 1
#define DMA_ACT_MIN 1
-#define ATA4_TIME_TO_TICK(time) howmany((time) * 1000, 7500)
-
+#define ATA4_TIME_TO_TICK(time) howmany((time), 15) /* 15 ns clock */
#define CONFIG_REG (0x200 >> 4) /* IDE access timing register */
void
+wdc_obio_select(chp, drive)
+ struct channel_softc *chp;
+ int drive;
+{
+ struct wdc_obio_softc *sc = (struct wdc_obio_softc *)chp->wdc;
+ bus_space_write_4(chp->cmd_iot, chp->cmd_ioh,
+ CONFIG_REG, sc->sc_dmaconf[drive]);
+}
+
+void
adjust_timing(chp)
struct channel_softc *chp;
{
- struct ata_drive_datas *drvp;
- u_int conf;
+ struct wdc_obio_softc *sc = (struct wdc_obio_softc *)chp->wdc;
int drive;
- int piomode = -1, dmamode = -1;
int min_cycle, min_active;
int cycle_tick, act_tick, inact_tick, half_tick;
-
for (drive = 0; drive < 2; drive++) {
+ u_int conf = 0;
+ struct ata_drive_datas *drvp;
+
drvp = &chp->ch_drive[drive];
- if ((drvp->drive_flags & DRIVE) == 0)
- continue;
- if (piomode == -1 || piomode > drvp->PIO_mode)
- piomode = drvp->PIO_mode;
- if (drvp->drive_flags & DRIVE_DMA) {
- if (dmamode == -1 || dmamode > drvp->DMA_mode)
- dmamode = drvp->DMA_mode;
+ /* set up pio mode timings */
+ if (drvp->drive_flags & DRIVE) {
+ int piomode = drvp->PIO_mode;
+ min_cycle = pio_timing[piomode].cycle;
+ min_active = pio_timing[piomode].active;
+
+ cycle_tick = TIME_TO_TICK(min_cycle);
+ act_tick = TIME_TO_TICK(min_active);
+ if (act_tick < PIO_ACT_MIN)
+ act_tick = PIO_ACT_MIN;
+ inact_tick = cycle_tick - act_tick - PIO_REC_OFFSET;
+ if (inact_tick < PIO_REC_MIN)
+ inact_tick = PIO_REC_MIN;
+ /* mask: 0x000007ff */
+ conf |= (inact_tick << 5) | act_tick;
}
- }
- if (piomode == -1)
- return; /* No drive */
- for (drive = 0; drive < 2; drive++) {
- drvp = &chp->ch_drive[drive];
- if (drvp->drive_flags & DRIVE) {
- drvp->PIO_mode = piomode;
- if (drvp->drive_flags & DRIVE_DMA)
- drvp->DMA_mode = dmamode;
+ /* Set up dma mode timings */
+ if (drvp->drive_flags & DRIVE_DMA) {
+ int dmamode = drvp->DMA_mode;
+ min_cycle = dma_timing[dmamode].cycle;
+ min_active = dma_timing[dmamode].active;
+ cycle_tick = TIME_TO_TICK(min_cycle);
+ act_tick = TIME_TO_TICK(min_active);
+ inact_tick = cycle_tick - act_tick - DMA_REC_OFFSET;
+ if (inact_tick < DMA_REC_MIN)
+ inact_tick = DMA_REC_MIN;
+ half_tick = 0; /* XXX */
+ /* mask: 0xfffff800 */
+ conf |=
+ (half_tick << 21) |
+ (inact_tick << 16) | (act_tick << 11);
}
+ if (conf) {
+ printf("conf[%d] = 0x%x, cyc = %d (%d ns), act = %d (%d ns), inact = %d\n",
+ drive, conf, cycle_tick, min_cycle, act_tick, min_active, inact_tick);
+ }
+ sc->sc_dmaconf[drive] = conf;
}
- min_cycle = pio_timing[piomode].cycle;
- min_active = pio_timing[piomode].active;
-
- cycle_tick = TIME_TO_TICK(min_cycle);
- act_tick = TIME_TO_TICK(min_active);
- if (act_tick < PIO_ACT_MIN)
- act_tick = PIO_ACT_MIN;
- inact_tick = cycle_tick - act_tick - PIO_REC_OFFSET;
- if (inact_tick < PIO_REC_MIN)
- inact_tick = PIO_REC_MIN;
- /* mask: 0x000007ff */
- conf = (inact_tick << 5) | act_tick;
- if (dmamode != -1) {
- /* there are active DMA mode */
-
- min_cycle = dma_timing[dmamode].cycle;
- min_active = dma_timing[dmamode].active;
- cycle_tick = TIME_TO_TICK(min_cycle);
- act_tick = TIME_TO_TICK(min_active);
- inact_tick = cycle_tick - act_tick - DMA_REC_OFFSET;
- if (inact_tick < DMA_REC_MIN)
- inact_tick = DMA_REC_MIN;
- half_tick = 0; /* XXX */
- /* mask: 0xfffff800 */
- conf |=
- (half_tick << 21) |
- (inact_tick << 16) | (act_tick << 11);
+ sc->sc_wdcdev.cap &= ~WDC_CAPABILITY_SELECT;
+ sc->sc_wdcdev.select = 0;
+ if (sc->sc_dmaconf[0]) {
+ wdc_obio_select(chp,0);
+ if (sc->sc_dmaconf[1] && (sc->sc_dmaconf[0] != sc->sc_dmaconf[1])) {
+ sc->sc_wdcdev.select = wdc_obio_select;
+ sc->sc_wdcdev.cap |= WDC_CAPABILITY_SELECT;
+ }
+ } else if (sc->sc_dmaconf[1]) {
+ wdc_obio_select(chp,1);
}
- bus_space_write_4(chp->cmd_iot, chp->cmd_ioh, CONFIG_REG, conf);
- printf("conf = 0x%x, cyc = %d (%d ns), act = %d (%d ns), inact = %d\n",
- conf, cycle_tick, min_cycle, act_tick, min_active, inact_tick);
wdc_print_modes(chp);
}
@@ -336,73 +347,67 @@
ata4_adjust_timing(chp)
struct channel_softc *chp;
{
- struct ata_drive_datas *drvp;
- u_int conf;
+ struct wdc_obio_softc *sc = (struct wdc_obio_softc *)chp->wdc;
int drive;
- int piomode = -1, dmamode = -1;
int min_cycle, min_active;
int cycle_tick, act_tick, inact_tick;
- int udmamode = -1;
-
for (drive = 0; drive < 2; drive++) {
+ u_int conf = 0;
+ struct ata_drive_datas *drvp;
+
drvp = &chp->ch_drive[drive];
- if ((drvp->drive_flags & DRIVE) == 0)
- continue;
- if (piomode == -1 || piomode > drvp->PIO_mode)
- piomode = drvp->PIO_mode;
- if (drvp->drive_flags & DRIVE_DMA) {
- if (dmamode == -1 || dmamode > drvp->DMA_mode)
- dmamode = drvp->DMA_mode;
- }
- if (drvp->drive_flags & DRIVE_UDMA) {
- if (udmamode == -1 || udmamode > drvp->UDMA_mode)
- udmamode = drvp->UDMA_mode;
- }
- }
- if (piomode == -1)
- return; /* No drive */
- for (drive = 0; drive < 2; drive++) {
- drvp = &chp->ch_drive[drive];
+ /* set up pio mode timings */
+
if (drvp->drive_flags & DRIVE) {
- drvp->PIO_mode = piomode;
- if (drvp->drive_flags & DRIVE_DMA)
- drvp->DMA_mode = dmamode;
- if (drvp->drive_flags & DRIVE_UDMA)
- drvp->UDMA_mode = udmamode;
- }
- }
- min_cycle = pio_timing[piomode].cycle;
- min_active = pio_timing[piomode].active;
+ int piomode = drvp->PIO_mode;
+ min_cycle = pio_timing[piomode].cycle;
+ min_active = pio_timing[piomode].active;
- cycle_tick = ATA4_TIME_TO_TICK(min_cycle);
- act_tick = ATA4_TIME_TO_TICK(min_active);
- inact_tick = cycle_tick - act_tick;
- /* mask: 0x000003ff */
- conf = (inact_tick << 5) | act_tick;
- if (dmamode != -1) {
- /* there are active DMA mode */
-
- min_cycle = dma_timing[dmamode].cycle;
- min_active = dma_timing[dmamode].active;
- cycle_tick = ATA4_TIME_TO_TICK(min_cycle);
- act_tick = ATA4_TIME_TO_TICK(min_active);
- inact_tick = cycle_tick - act_tick;
- /* mask: 0x001ffc00 */
- conf |= (act_tick << 10) | (inact_tick << 15);
+ cycle_tick = ATA4_TIME_TO_TICK(min_cycle);
+ act_tick = ATA4_TIME_TO_TICK(min_active);
+ inact_tick = cycle_tick - act_tick;
+ /* mask: 0x000003ff */
+ conf |= (inact_tick << 5) | act_tick;
+ }
+ /* set up dma mode timings */
+ if (drvp->drive_flags & DRIVE_DMA) {
+ int dmamode = drvp->DMA_mode;
+ min_cycle = dma_timing[dmamode].cycle;
+ min_active = dma_timing[dmamode].active;
+ cycle_tick = ATA4_TIME_TO_TICK(min_cycle);
+ act_tick = ATA4_TIME_TO_TICK(min_active);
+ inact_tick = cycle_tick - act_tick;
+ /* mask: 0x001ffc00 */
+ conf |= (act_tick << 10) | (inact_tick << 15);
+ }
+ /* set up udma mode timings */
+ if (drvp->drive_flags & DRIVE_UDMA) {
+ int udmamode = drvp->UDMA_mode;
+ min_cycle = udma_timing[udmamode].cycle;
+ min_active = udma_timing[udmamode].active;
+ act_tick = ATA4_TIME_TO_TICK(min_active);
+ cycle_tick = ATA4_TIME_TO_TICK(min_cycle);
+ /* mask: 0x1ff00000 */
+ conf |= (cycle_tick << 21) | (act_tick << 25) | 0x100000;
+ }
+ if (conf) {
+ printf("ata4 conf[%d] = 0x%x, cyc = %d (%d ns), act = %d (%d ns), inact = %d\n",
+ drive, conf, cycle_tick, min_cycle, act_tick, min_active, inact_tick);
+ }
+ sc->sc_dmaconf[drive] = conf;
}
- if (udmamode != -1) {
- min_cycle = udma_timing[udmamode].cycle;
- min_active = udma_timing[udmamode].active;
- act_tick = ATA4_TIME_TO_TICK(min_active);
- cycle_tick = ATA4_TIME_TO_TICK(min_cycle);
- /* mask: 0x1ff00000 */
- conf |= (cycle_tick << 21) | (act_tick << 25) | 0x100000;
+ sc->sc_wdcdev.cap &= ~WDC_CAPABILITY_SELECT;
+ sc->sc_wdcdev.select = 0;
+ if (sc->sc_dmaconf[0]) {
+ wdc_obio_select(chp,0);
+ if (sc->sc_dmaconf[1] && (sc->sc_dmaconf[0] != sc->sc_dmaconf[1])) {
+ sc->sc_wdcdev.select = wdc_obio_select;
+ sc->sc_wdcdev.cap |= WDC_CAPABILITY_SELECT;
+ }
+ } else if (sc->sc_dmaconf[1]) {
+ wdc_obio_select(chp,1);
}
-
- bus_space_write_4(chp->cmd_iot, chp->cmd_ioh, CONFIG_REG, conf);
- printf("ata4 conf = 0x%x, cyc = %d (%d ns), act = %d (%d ns), inact = %d\n",
- conf, cycle_tick, min_cycle, act_tick, min_active, inact_tick);
wdc_print_modes(chp);
}
diff -r 97fac036cb1b -r 5afb566782c0 sys/dev/ic/wdc.c
--- a/sys/dev/ic/wdc.c Mon Jan 07 22:07:37 2002 +0000
+++ b/sys/dev/ic/wdc.c Mon Jan 07 22:11:17 2002 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: wdc.c,v 1.106 2001/12/05 20:43:00 bouyer Exp $ */
+/* $NetBSD: wdc.c,v 1.107 2002/01/07 22:11:17 dbj Exp $ */
/*
@@ -72,7 +72,7 @@
*/
#include <sys/cdefs.h>
Home |
Main Index |
Thread Index |
Old Index