Apply by doing:
cd /usr/src
patch -p0 < 009_atapi.patch
And then rebuild your kernel.
Index: sys/dev/ata/ata.c
===================================================================
RCS file: /cvs/src/sys/dev/ata/ata.c,v
retrieving revision 1.2
retrieving revision 1.4
diff -u -r1.2 -r1.4
--- sys/dev/ata/ata.c 1999/08/05 00:12:09 1.2
+++ sys/dev/ata/ata.c 1999/11/17 01:22:55 1.4
@@ -1,4 +1,4 @@
-/* $OpenBSD: ata.c,v 1.2 1999/08/05 00:12:09 niklas Exp $ */
+/* $OpenBSD: ata.c,v 1.4 1999/11/17 01:22:55 csapuntz Exp $ */
/* $NetBSD: ata.c,v 1.9 1999/04/15 09:41:09 bouyer Exp $ */
/*
* Copyright (c) 1998 Manuel Bouyer. All rights reserved.
@@ -29,10 +29,6 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef WDCDEBUG
-#define WDCDEBUG
-#endif /* WDCDEBUG */
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
@@ -57,6 +53,8 @@
#define WDCDEBUG_PRINT(args, level)
#endif
+#define ATAPARAMS_SIZE 512
+
/* Get the disk's parameters */
int
ata_get_params(drvp, flags, prms)
@@ -64,17 +62,15 @@
u_int8_t flags;
struct ataparams *prms;
{
- char tb[DEV_BSIZE];
+ char tb[ATAPARAMS_SIZE];
struct wdc_command wdc_c;
-#if BYTE_ORDER == LITTLE_ENDIAN
int i;
u_int16_t *p;
-#endif
WDCDEBUG_PRINT(("wdc_ata_get_parms\n"), DEBUG_FUNCS);
- bzero(tb, DEV_BSIZE);
+ bzero(tb, sizeof(tb));
bzero(prms, sizeof(struct ataparams));
bzero(&wdc_c, sizeof(struct wdc_command));
@@ -93,7 +89,7 @@
}
wdc_c.flags = AT_READ | flags;
wdc_c.data = tb;
- wdc_c.bcount = DEV_BSIZE;
+ wdc_c.bcount = ATAPARAMS_SIZE;
{
int ret;
@@ -106,9 +102,24 @@
if (wdc_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) {
return CMD_ERR;
} else {
+#if BYTE_ORDER == BIG_ENDIAN
+ /* All the fields in the params structure are 16-bit
+ integers except for the ID strings which are char
+ strings. The 16-bit integers are currently in
+ memory in little-endian, regardless of architecture.
+ So, they need to be swapped on big-endian architectures
+ before they are accessed through the ataparams structure.
+
+ The swaps below avoid touching the char strings.
+ */
+
+ swap16_multi((u_int16_t *)tb, 10);
+ swap16_multi((u_int16_t *)tb + 20, 3);
+ swap16_multi((u_int16_t *)tb + 47, ATAPARAMS_SIZE / 2 - 47);
+#endif
/* Read in parameter block. */
bcopy(tb, prms, sizeof(struct ataparams));
-#if BYTE_ORDER == LITTLE_ENDIAN
+
/*
* Shuffle string byte order.
* ATAPI Mitsumi and NEC drives don't need this.
@@ -122,17 +133,17 @@
return 0;
for (i = 0; i < sizeof(prms->atap_model); i += 2) {
p = (u_short *)(prms->atap_model + i);
- *p = ntohs(*p);
+ *p = swap16(*p);
}
for (i = 0; i < sizeof(prms->atap_serial); i += 2) {
p = (u_short *)(prms->atap_serial + i);
- *p = ntohs(*p);
+ *p = swap16(*p);
}
for (i = 0; i < sizeof(prms->atap_revision); i += 2) {
p = (u_short *)(prms->atap_revision + i);
- *p = ntohs(*p);
+ *p = swap16(*p);
}
-#endif
+
return CMD_OK;
}
}
Index: sys/dev/ata/ata_wdc.c
===================================================================
RCS file: /cvs/src/sys/dev/ata/ata_wdc.c,v
retrieving revision 1.1
retrieving revision 1.4
diff -u -r1.1 -r1.4
--- sys/dev/ata/ata_wdc.c 1999/07/18 21:25:17 1.1
+++ sys/dev/ata/ata_wdc.c 1999/11/17 01:22:55 1.4
@@ -1,5 +1,4 @@
-/* $OpenBSD: ata_wdc.c,v 1.1 1999/07/18 21:25:17 csapuntz Exp $ */
-/* $NetBSD: ata_wdc.c,v 1.19 1999/04/01 21:46:28 bouyer Exp $ */
+/* $NetBSD: ata_wdc.c,v 1.21 1999/08/09 09:43:11 bouyer Exp $ */
/*
* Copyright (c) 1998 Manuel Bouyer.
@@ -70,10 +69,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef WDCDEBUG
-#define WDCDEBUG
-#endif /* WDCDEBUG */
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
@@ -88,12 +83,6 @@
#include <machine/intr.h>
#include <machine/bus.h>
-#ifndef __BUS_SPACE_HAS_STREAM_METHODS
-#define bus_space_write_multi_stream_2 bus_space_write_multi_2
-#define bus_space_write_multi_stream_4 bus_space_write_multi_4
-#define bus_space_read_multi_stream_2 bus_space_read_multi_2
-#define bus_space_read_multi_stream_4 bus_space_read_multi_4
-#endif /* __BUS_SPACE_HAS_STREAM_METHODS */
#include <dev/ata/atareg.h>
#include <dev/ata/atavar.h>
@@ -124,6 +113,7 @@
#endif
void wdc_ata_bio_start __P((struct channel_softc *,struct wdc_xfer *));
+void _wdc_ata_bio_start __P((struct channel_softc *,struct wdc_xfer *));
int wdc_ata_bio_intr __P((struct channel_softc *, struct wdc_xfer *, int));
void wdc_ata_bio_done __P((struct channel_softc *, struct wdc_xfer *));
int wdc_ata_ctrl_intr __P((struct channel_softc *, struct wdc_xfer *, int));
@@ -168,6 +158,22 @@
struct wdc_xfer *xfer;
{
struct ata_bio *ata_bio = xfer->cmd;
+ WDCDEBUG_PRINT(("wdc_ata_bio_start %s:%d:%d\n",
+ chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive),
+ DEBUG_XFERS);
+
+ /* start timeout machinery */
+ if ((ata_bio->flags & ATA_POLL) == 0)
+ timeout(wdctimeout, chp, ATA_DELAY / 1000 * hz);
+ _wdc_ata_bio_start(chp, xfer);
+}
+
+void
+_wdc_ata_bio_start(chp, xfer)
+ struct channel_softc *chp;
+ struct wdc_xfer *xfer;
+{
+ struct ata_bio *ata_bio = xfer->cmd;
struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];
u_int16_t cyl;
u_int8_t head, sect, cmd = 0;
@@ -175,10 +181,9 @@
int ata_delay;
int dma_flags = 0;
- WDCDEBUG_PRINT(("wdc_ata_bio_start %s:%d:%d\n",
+ WDCDEBUG_PRINT(("_wdc_ata_bio_start %s:%d:%d\n",
chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive),
- DEBUG_XFERS);
-
+ DEBUG_INTR | DEBUG_XFERS);
/* Do control operations specially. */
if (drvp->state < READY) {
/*
@@ -188,22 +193,19 @@
*/
/* at this point, we should only be in RECAL state */
if (drvp->state != RECAL) {
- printf("%s:%d:%d: bad state %d in wdc_ata_bio_start\n",
+ printf("%s:%d:%d: bad state %d in _wdc_ata_bio_start\n",
chp->wdc->sc_dev.dv_xname, chp->channel,
xfer->drive, drvp->state);
- panic("wdc_ata_bio_start: bad state");
+ panic("_wdc_ata_bio_start: bad state");
}
xfer->c_intr = wdc_ata_ctrl_intr;
- bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
- WDSD_IBM | (xfer->drive << 4));
+ CHP_WRITE_REG(chp, wdr_sdh, WDSD_IBM | (xfer->drive << 4));
if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, ATA_DELAY) != 0)
goto timeout;
wdccommandshort(chp, xfer->drive, WDCC_RECAL);
drvp->state = RECAL_WAIT;
if ((ata_bio->flags & ATA_POLL) == 0) {
chp->ch_flags |= WDCF_IRQ_WAIT;
- timeout(wdctimeout, chp,
- ATA_DELAY / 1000 * hz);
} else {
/* Wait for at last 400ns for status bit to be valid */
DELAY(1);
@@ -287,7 +289,7 @@
return;
}
/* Initiate command */
- bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
+ CHP_WRITE_REG(chp, wdr_sdh,
WDSD_IBM | (xfer->drive << 4));
if (wait_for_ready(chp, ata_delay) < 0)
goto timeout;
@@ -309,8 +311,7 @@
WDCC_READ : WDCC_WRITE;
}
/* Initiate command! */
- bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
- WDSD_IBM | (xfer->drive << 4));
+ CHP_WRITE_REG(chp, wdr_sdh, WDSD_IBM | (xfer->drive << 4));
if (wait_for_ready(chp, ata_delay) < 0)
goto timeout;
wdccommand(chp, xfer->drive, cmd, cyl,
@@ -341,41 +342,13 @@
wdc_ata_bio_done(chp, xfer);
return;
}
- if ((chp->wdc->cap & WDC_CAPABILITY_ATA_NOSTREAM)) {
- if (drvp->drive_flags & DRIVE_CAP32) {
- bus_space_write_multi_4(chp->data32iot,
- chp->data32ioh, 0,
- (u_int32_t *)((char *)xfer->databuf +
- xfer->c_skip),
- ata_bio->nbytes >> 2);
- } else {
- bus_space_write_multi_2(chp->cmd_iot,
- chp->cmd_ioh, wd_data,
- (u_int16_t *)((char *)xfer->databuf +
- xfer->c_skip),
- ata_bio->nbytes >> 1);
- }
- } else {
- if (drvp->drive_flags & DRIVE_CAP32) {
- bus_space_write_multi_stream_4(chp->data32iot,
- chp->data32ioh, 0,
- (u_int32_t *)((char *)xfer->databuf +
- xfer->c_skip),
- ata_bio->nbytes >> 2);
- } else {
- bus_space_write_multi_stream_2(chp->cmd_iot,
- chp->cmd_ioh, wd_data,
- (u_int16_t *)((char *)xfer->databuf +
- xfer->c_skip),
- ata_bio->nbytes >> 1);
- }
- }
+ wdc_output_bytes(drvp, (char *)xfer->databuf + xfer->c_skip,
+ ata_bio->nbytes);
}
intr: /* Wait for IRQ (either real or polled) */
if ((ata_bio->flags & ATA_POLL) == 0) {
chp->ch_flags |= WDCF_IRQ_WAIT;
- timeout(wdctimeout, chp, ata_delay / 1000 * hz);
} else {
/* Wait for at last 400ns for status bit to be valid */
delay(1);
@@ -423,6 +396,16 @@
dma_flags |= (ata_bio->flags & ATA_POLL) ? WDC_DMA_POLL : 0;
}
+ /*
+ * if we missed an interrupt in a PIO transfer, reset and restart.
+ * Don't try to continue transfer, we may have missed cycles.
+ */
+ if ((xfer->c_flags & (C_TIMEOU | C_DMA)) == C_TIMEOU) {
+ ata_bio->error = TIMEOUT;
+ wdc_ata_bio_done(chp, xfer);
+ return 1;
+ }
+
/* Ack interrupt done by wait_for_unbusy */
if (wait_for_unbusy(chp,
(irq == 0) ? ATA_DELAY : 0) < 0) {
@@ -498,38 +481,10 @@
ata_bio->error = TIMEOUT;
wdc_ata_bio_done(chp, xfer);
return 1;
- }
- if ((chp->wdc->cap & WDC_CAPABILITY_ATA_NOSTREAM)) {
- if (drvp->drive_flags & DRIVE_CAP32) {
- bus_space_read_multi_4(chp->data32iot,
- chp->data32ioh, 0,
- (u_int32_t *)((char *)xfer->databuf +
- xfer->c_skip),
- ata_bio->nbytes >> 2);
- } else {
- bus_space_read_multi_2(chp->cmd_iot,
- chp->cmd_ioh, wd_data,
- (u_int16_t *)((char *)xfer->databuf +
- xfer->c_skip),
- ata_bio->nbytes >> 1);
- }
- } else {
- if (drvp->drive_flags & DRIVE_CAP32) {
- bus_space_read_multi_stream_4(chp->data32iot,
- chp->data32ioh, 0,
- (u_int32_t *)((char *)xfer->databuf +
- xfer->c_skip),
- ata_bio->nbytes >> 2);
- } else {
- bus_space_read_multi_stream_2(chp->cmd_iot,
- chp->cmd_ioh, wd_data,
- (u_int16_t *)((char *)xfer->databuf +
- xfer->c_skip),
- ata_bio->nbytes >> 1);
- }
}
+ wdc_input_bytes(drvp, (char *)xfer->databuf + xfer->c_skip,
+ ata_bio->nbytes);
}
-
end:
ata_bio->blkno += ata_bio->nblks;
ata_bio->blkdone += ata_bio->nblks;
@@ -539,9 +494,9 @@
if (xfer->c_bcount > 0) {
if ((ata_bio->flags & ATA_POLL) == 0) {
/* Start the next operation */
- wdc_ata_bio_start(chp, xfer);
+ _wdc_ata_bio_start(chp, xfer);
} else {
- /* Let wdc_ata_bio_start do the loop */
+ /* Let _wdc_ata_bio_start do the loop */
return 1;
}
} else { /* Done with this transfer */
@@ -557,7 +512,6 @@
struct wdc_xfer *xfer;
{
struct ata_bio *ata_bio = xfer->cmd;
- int need_done = xfer->c_flags & C_NEEDDONE;
int drive = xfer->drive;
struct ata_drive_datas *drvp = &chp->ch_drive[drive];
@@ -566,6 +520,7 @@
(u_int)xfer->c_flags),
DEBUG_XFERS);
+ untimeout(wdctimeout, chp);
if (ata_bio->error == NOERROR)
drvp->n_dmaerrs = 0;
else if (drvp->n_dmaerrs >= NERRS_MAX) {
@@ -579,7 +534,7 @@
wdc_free_xfer(chp, xfer);
ata_bio->flags |= ATA_ITSDONE;
- if (need_done) {
+ if ((ata_bio->flags & ATA_POLL) == 0) {
WDCDEBUG_PRINT(("wdc_ata_done: wddone\n"), DEBUG_XFERS);
wddone(chp->ch_drive[drive].drv_softc);
}
@@ -703,13 +658,12 @@
* The drive is usable now
*/
xfer->c_intr = wdc_ata_bio_intr;
- wdc_ata_bio_start(chp, xfer);
+ _wdc_ata_bio_start(chp, xfer);
return 1;
}
if ((ata_bio->flags & ATA_POLL) == 0) {
chp->ch_flags |= WDCF_IRQ_WAIT;
- timeout(wdctimeout, chp, ATA_DELAY / 1000 * hz);
} else {
goto again;
}
Index: sys/dev/ata/wd.c
===================================================================
RCS file: /cvs/src/sys/dev/ata/wd.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- sys/dev/ata/wd.c 1999/10/09 07:14:00 1.9
+++ sys/dev/ata/wd.c 1999/11/17 01:22:55 1.10
@@ -1,4 +1,4 @@
-/* $OpenBSD: wd.c,v 1.9 1999/10/09 07:14:00 csapuntz Exp $ */
+/* $OpenBSD: wd.c,v 1.10 1999/11/17 01:22:55 csapuntz Exp $ */
/* $NetBSD: wd.c,v 1.193 1999/02/28 17:15:27 explorer Exp $ */
/*
@@ -65,10 +65,6 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
-
-#ifndef WDCDEBUG
-#define WDCDEBUG
-#endif /* WDCDEBUG */
#if 0
#include "rnd.h"
Index: sys/dev/pci/pciide.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/pciide.c,v
retrieving revision 1.11
retrieving revision 1.15
diff -u -r1.11 -r1.15
--- sys/dev/pci/pciide.c 1999/10/09 03:42:04 1.11
+++ sys/dev/pci/pciide.c 1999/11/23 20:48:35 1.15
@@ -1,4 +1,4 @@
-/* $OpenBSD: pciide.c,v 1.11 1999/10/09 03:42:04 csapuntz Exp $ */
+/* $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 $ */
/*
@@ -43,10 +43,6 @@
*
*/
-#ifndef WDCDEBUG
-#define WDCDEBUG
-#endif
-
#define DEBUG_DMA 0x01
#define DEBUG_XFERS 0x02
#define DEBUG_FUNCS 0x08
@@ -230,11 +226,11 @@
0,
piix_chip_map
},
- { PCI_PRODUCT_INTEL_82801AA_IDE,
+ { PCI_PRODUCT_INTEL_82801AA_IDE, /* Intel 82801AA IDE (ICH) */
0,
piix_chip_map,
},
- { PCI_PRODUCT_INTEL_82801AB_IDE,
+ { PCI_PRODUCT_INTEL_82801AB_IDE, /* Intel 82801AB IDE (ICH0) */
0,
piix_chip_map,
},
@@ -274,7 +270,7 @@
};
const struct pciide_product_desc pciide_sis_products[] = {
- { PCI_PRODUCT_SIS_5597, /* SIS 5597/5598 IDE */
+ { PCI_PRODUCT_SIS_5513, /* SIS 5513 EIDE */
0,
sis_chip_map
}
@@ -1113,7 +1109,7 @@
} else {
pciide_mapreg_dma(sc, pa);
if (sc->sc_dma_ok != 0)
- printf(", (partial support) ");
+ printf(", (partial support)");
}
} else {
printf(": no DMA");
@@ -1297,7 +1293,7 @@
PIIX_IDETIM_IDE) == 0) {
printf("%s: %s ignored (disabled)\n",
sc->sc_wdcdev.sc_dev.dv_xname, cp->name);
- return;
+ continue;
}
/* PIIX are compat-only pciide devices */
pciide_mapchan(pa, cp, 0, &cmdsize, &ctlsize, pciide_pci_intr);
@@ -1689,7 +1685,7 @@
if ((ideconf & APO_IDECONF_EN(channel)) == 0) {
printf("%s: %s ignored (disabled)\n",
sc->sc_wdcdev.sc_dev.dv_xname, cp->name);
- return;
+ continue;
}
pciide_mapchan(pa, cp, interface, &cmdsize, &ctlsize,
pciide_pci_intr);
@@ -2192,7 +2188,7 @@
(channel == 1 && (sis_ctr0 & SIS_CTRL0_CHAN1_EN) == 0)) {
printf("%s: %s ignored (disabled)\n",
sc->sc_wdcdev.sc_dev.dv_xname, cp->name);
- return;
+ continue;
}
pciide_mapchan(pa, cp, interface, &cmdsize, &ctlsize,
pciide_pci_intr);
@@ -2574,7 +2570,7 @@
WDCDEBUG_PRINT(("pdc202xx_setup_chip: new controller state 0x%x\n", st),
DEBUG_PROBE);
pci_conf_write(sc->sc_pc, sc->sc_tag, PDC2xx_STATE, st);
-return;
+ return;
}
void
Index: sys/dev/atapiscsi/atapiscsi.c
===================================================================
RCS file: /cvs/src/sys/dev/atapiscsi/atapiscsi.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -r1.18 -r1.19
--- sys/dev/atapiscsi/atapiscsi.c 1999/11/02 01:43:40 1.18
+++ sys/dev/atapiscsi/atapiscsi.c 1999/11/17 01:22:55 1.19
@@ -1,4 +1,4 @@
-/* $OpenBSD: atapiscsi.c,v 1.18 1999/11/02 01:43:40 deraadt Exp $ */
+/* $OpenBSD: atapiscsi.c,v 1.19 1999/11/17 01:22:55 csapuntz Exp $ */
/*
* This code is derived from code with the copyright below.
@@ -68,7 +68,6 @@
#include <dev/atapiscsi/atapiconf.h>
-#define WDCDEBUG
#define DEBUG_INTR 0x01
#define DEBUG_XFERS 0x02
#define DEBUG_STATUS 0x04
@@ -124,6 +123,7 @@
struct channel_softc *chp;
enum atapi_state { as_none, as_cmdout, as_data } protocol_phase;
+ int retries;
int diagnostics_printed;
#define ATAPI_DIAG_UNEXP_CMD 0x01
#define ATAPI_DIAG_POLARITY 0x02
@@ -335,7 +335,7 @@
}
drvp->state = 0;
- bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_status);
+ CHP_READ_REG(chp, wdr_status);
/* Some ATAPI devices need a bit more time after software reset. */
delay(5000);
@@ -357,7 +357,6 @@
int drive = sc_xfer->sc_link->target;
struct channel_softc *chp = as->chp;
struct ata_drive_datas *drvp = &chp->ch_drive[drive];
- struct wdc_softc *wdc = chp->wdc;
struct wdc_xfer *xfer;
int flags = sc_xfer->flags;
int s, ret, saved_datalen;
@@ -367,7 +366,7 @@
saved_datalen = 0;
WDCDEBUG_PRINT(("wdc_atapi_send_cmd %s:%d:%d\n",
- wdc->sc_dev.dv_xname, chp->channel, drive), DEBUG_XFERS);
+ chp->wdc->sc_dev.dv_xname, chp->channel, drive), DEBUG_XFERS);
if (drive > 1 || !(drvp->drive_flags & DRIVE_ATAPI)) {
sc_xfer->error = XS_DRIVER_STUFFUP;
@@ -568,6 +567,7 @@
(xfer->c_flags & C_DMA) ? ATAPI_PKT_CMD_FTRE_DMA : 0);
as->protocol_phase = as_cmdout;
+ as->retries = 0;
/*
* If there is no interrupt for CMD input, busy-wait for it (done in
@@ -616,106 +616,105 @@
/* We should really wait_for_unbusy here too before
switching drives. */
- bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
- WDSD_IBM | (drvp->drive << 4));
+ CHP_WRITE_REG(chp, wdr_sdh, WDSD_IBM | (drvp->drive << 4));
return (wait_for_unbusy(chp, 0) == 0);
}
+
+int wdc_atapi_intr_command __P((struct channel_softc *, struct wdc_xfer *, int));
+int wdc_atapi_intr_data __P((struct channel_softc *, struct wdc_xfer *, int));
+int wdc_atapi_intr_complete __P((struct channel_softc *, struct wdc_xfer *, int));
-int wdc_atapi_intr_drq __P((struct channel_softc *, struct wdc_xfer *, int));
int
-wdc_atapi_intr_drq(chp, xfer, irq)
+wdc_atapi_intr_command(chp, xfer, dma_flags)
struct channel_softc *chp;
struct wdc_xfer *xfer;
- int irq;
-
+ int dma_flags;
{
struct scsi_xfer *sc_xfer = xfer->cmd;
struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];
struct atapiscsi_softc *as = sc_xfer->sc_link->adapter_softc;
- int len, phase, i;
- int ire;
- int dma_flags = 0;
+ int i;
u_int8_t cmd[16];
struct scsi_sense *cmd_reqsense;
int cmdlen = (drvp->atapi_cap & ACAP_LEN) ? 16 : 12;
- if (xfer->c_flags & C_DMA) {
- dma_flags = ((sc_xfer->flags & SCSI_DATA_IN) ||
- (xfer->c_flags & C_SENSE)) ? WDC_DMA_READ : 0;
- dma_flags |= ((sc_xfer->flags & SCSI_POLL) ||
- (drvp->atapi_cap & ACAP_DSC)) ? WDC_DMA_POLL : 0;
- }
+ bzero(cmd, sizeof(cmd));
-
- if (as->protocol_phase == as_cmdout) {
- bzero(cmd, sizeof(cmd));
+ if (xfer->c_flags & C_SENSE) {
+ cmd_reqsense = (struct scsi_sense *)&cmd[0];
+ cmd_reqsense->opcode = REQUEST_SENSE;
+ cmd_reqsense->length = xfer->c_bcount;
+ } else
+ bcopy(sc_xfer->cmd, cmd, sc_xfer->cmdlen);
+
+ for (i = 0; i < 12; i++)
+ WDCDEBUG_PRINT(("%02x ", cmd[i]), DEBUG_INTR);
+ WDCDEBUG_PRINT((": PHASE_CMDOUT\n"), DEBUG_INTR);
- if (xfer->c_flags & C_SENSE) {
- cmd_reqsense = (struct scsi_sense *)&cmd[0];
- cmd_reqsense->opcode = REQUEST_SENSE;
- cmd_reqsense->length = xfer->c_bcount;
- } else
- bcopy(sc_xfer->cmd, cmd, sc_xfer->cmdlen);
-
- for (i = 0; i < 12; i++)
- WDCDEBUG_PRINT(("%02x ", cmd[i]), DEBUG_INTR);
- WDCDEBUG_PRINT((": PHASE_CMDOUT\n"), DEBUG_INTR);
-
- /* Init the DMA channel if necessary */
- if (xfer->c_flags & C_DMA) {
- if ((*chp->wdc->dma_init)(chp->wdc->dma_arg,
- chp->channel, xfer->drive, xfer->databuf,
- xfer->c_bcount, dma_flags) != 0) {
- sc_xfer->error = XS_DRIVER_STUFFUP;
- wdc_atapi_done(chp, xfer);
- return (1);
- }
+ /* Init the DMA channel if necessary */
+ if (xfer->c_flags & C_DMA) {
+ if ((*chp->wdc->dma_init)(chp->wdc->dma_arg,
+ chp->channel, xfer->drive, xfer->databuf,
+ xfer->c_bcount, dma_flags) != 0) {
+ sc_xfer->error = XS_DRIVER_STUFFUP;
+ wdc_atapi_done(chp, xfer);
+ return (1);
}
-
+ }
- wdc_output_bytes(drvp, cmd, cmdlen);
+ wdc_output_bytes(drvp, cmd, cmdlen);
- as->protocol_phase = as_data;
+ as->protocol_phase = as_data;
- /* Start the DMA channel if necessary */
- if (xfer->c_flags & C_DMA) {
- (*chp->wdc->dma_start)(chp->wdc->dma_arg,
- chp->channel, xfer->drive,
- dma_flags);
- }
+ /* Start the DMA channel if necessary */
+ if (xfer->c_flags & C_DMA) {
+ (*chp->wdc->dma_start)(chp->wdc->dma_arg,
+ chp->channel, xfer->drive,
+ dma_flags);
+ }
- if ((sc_xfer->flags & SCSI_POLL) == 0 &&
- (drvp->atapi_cap & ACAP_DSC) == 0) {
- chp->ch_flags |= WDCF_IRQ_WAIT;
- timeout(wdctimeout, chp, sc_xfer->timeout * hz / 1000);
- }
+ if ((sc_xfer->flags & SCSI_POLL) == 0 &&
+ (drvp->atapi_cap & ACAP_DSC) == 0) {
+ chp->ch_flags |= WDCF_IRQ_WAIT;
+ timeout(wdctimeout, chp, sc_xfer->timeout * hz / 1000);
+ }
- /* If we read/write to a tape we will get into buffer
- availability mode. */
- if (drvp->atapi_cap & ACAP_DSC) {
- if (!(drvp->drive_flags & DRIVE_DSCBA) &&
- (sc_xfer->cmd->opcode == READ ||
- sc_xfer->cmd->opcode == WRITE)) {
- drvp->drive_flags |= DRIVE_DSCBA;
- WDCDEBUG_PRINT(("set DSCBA\n"), DEBUG_DSC);
- }
- if (sc_xfer->cmd->opcode == READ)
- drvp->drive_flags |= DRIVE_DSCWAIT;
+ /* If we read/write to a tape we will get into buffer
+ availability mode. */
+ if (drvp->atapi_cap & ACAP_DSC) {
+ if (!(drvp->drive_flags & DRIVE_DSCBA) &&
+ (sc_xfer->cmd->opcode == READ ||
+ sc_xfer->cmd->opcode == WRITE)) {
+ drvp->drive_flags |= DRIVE_DSCBA;
+ WDCDEBUG_PRINT(("set DSCBA\n"), DEBUG_DSC);
}
- return (1);
+ if (sc_xfer->cmd->opcode == READ)
+ drvp->drive_flags |= DRIVE_DSCWAIT;
}
+ return (1);
- if (as->protocol_phase != as_data) {
- panic ("wdc_atapi_intr_drq: bad protocol phase");
- }
+}
+
+int
+wdc_atapi_intr_data(chp, xfer, dma_flags)
+ struct channel_softc *chp;
+ struct wdc_xfer *xfer;
+ int dma_flags;
+
+{
+ struct scsi_xfer *sc_xfer = xfer->cmd;
+ struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];
+ struct atapiscsi_softc *as = sc_xfer->sc_link->adapter_softc;
+ int len, ire;
+ char *message = 0;
- len = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_cyl_lo) +
- 256 * bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_cyl_hi);
- ire = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_ireason);
- phase = (ire & (WDCI_CMD | WDCI_IN)) | (chp->ch_status & WDCS_DRQ);
+ len = (CHP_READ_REG(chp, wdr_cyl_hi) << 8) |
+ CHP_READ_REG(chp, wdr_cyl_lo);
+ ire = CHP_READ_REG(chp, wdr_ireason);
+
WDCDEBUG_PRINT(("wdc_atapi_intr: c_bcount %d len %d st 0x%x err 0x%x "
"ire 0x%x :", xfer->c_bcount,
len, chp->ch_status, chp->ch_error, ire), DEBUG_INTR);
@@ -723,42 +722,41 @@
/* Possibility to explore; what if we get an interrupt
during DMA ? */
if ((xfer->c_flags & C_DMA) != 0) {
- printf("wdc_atapi_intr_drq: Unexpected "
- "interrupt during DMA mode");
+ if ((xfer->c_flags & C_TIMEOU) == 0)
+ message = "unexpected interrupt during DMA mode";
- goto abort_data;
+ goto unexpected_state;
}
-
if (ire & WDCI_CMD) {
- /* Something messed up */
- if (!(as->diagnostics_printed & ATAPI_DIAG_UNEXP_CMD)) {
- printf ("wdc_atapi_intr_drq: Unexpectedly "
- "in the command phase. Please report this.\n");
- as->diagnostics_printed |= ATAPI_DIAG_UNEXP_CMD;
- }
- goto abort_data;
+ message = "unexpectedly in command phase";
+ goto unexpected_state;
}
+
+ if (!(xfer->c_flags & C_SENSE)) {
+ if (!(sc_xfer->flags & (SCSI_DATA_IN | SCSI_DATA_OUT))) {
+ message = "data phase where none expected";
+ goto unexpected_state;
+ }
- /* Make sure polarities match */
- if (((ire & WDCI_IN) == WDCI_IN) ==
- ((sc_xfer->flags & SCSI_DATA_OUT) == SCSI_DATA_OUT)) {
- if (!(as->diagnostics_printed & ATAPI_DIAG_POLARITY)) {
- printf ("wdc_atapi_intr_drq: Polarity problem "
- "in transfer. Please report this.\n");
- as->diagnostics_printed |= ATAPI_DIAG_POLARITY;
+ /* Make sure polarities match */
+ if (((ire & WDCI_IN) == WDCI_IN) ==
+ ((sc_xfer->flags & SCSI_DATA_OUT) == SCSI_DATA_OUT)) {
+ message = "data transfer direction disagreement";
+ goto unexpected_state;
}
- goto abort_data;
+ } else {
+ if (!(ire & WDCI_IN)) {
+ message = "data transfer direction disagreement during sense";
+ goto unexpected_state;
+ }
}
- WDCDEBUG_PRINT(("PHASE_DATA\n"), DEBUG_INTR);
-
if (len == 0) {
- printf("wdc_atapi_intr_drq: length 0 transfer in "
- "data phase\n");
- goto abort_data;
+ message = "zero length transfer requested in data phase";
+ goto unexpected_state;
}
-
+
if (xfer->c_bcount >= len) {
/* Common case */
if (sc_xfer->flags & SCSI_DATA_OUT)
@@ -779,9 +777,8 @@
wdc_output_bytes(drvp, (u_int8_t *)xfer->databuf +
xfer->c_skip, xfer->c_bcount);
- for (i = xfer->c_bcount; i < len; i += 2)
- bus_space_write_2(chp->cmd_iot, chp->cmd_ioh,
- wd_data, 0);
+ CHP_WRITE_RAW_MULTI_2(chp, NULL,
+ len - xfer->c_bcount);
} else {
printf("wdc_atapi_intr: warning: reading only "
"%d of %d bytes\n", xfer->c_bcount, len);
@@ -803,8 +800,29 @@
} else if (drvp->atapi_cap & ACAP_DSC)
drvp->drive_flags |= DRIVE_DSCWAIT;
return (1);
+
+ unexpected_state:
- abort_data:
+ /* If we're in polling mode, then it's possible we caught
+ a drive in some awkward, intermediate state. Of course,
+ the drive should have BSY set while it's transitioning
+ through awkward states, but this may not always
+ be the case. */
+
+ /* Spurious interrupts can cause us pain too and we don't deal
+ with those nearly as well. We assume the spurious
+ interrupts are random and won't affect us on retry */
+ if (xfer->c_flags & C_POLL) {
+ DELAY(1000);
+ as->retries++;
+ /* Give the drive up to 2 seconds to fix itself */
+ if (as->retries <= 2000)
+ return (1);
+ }
+
+ if (message)
+ printf ("wdc_atapi_intr_drq: %s\n", message);
+
if (xfer->c_flags & C_DMA) {
(*chp->wdc->dma_finish)(chp->wdc->dma_arg,
chp->channel, xfer->drive, dma_flags);
@@ -819,63 +837,16 @@
int
-wdc_atapi_intr(chp, xfer, irq)
+wdc_atapi_intr_complete(chp, xfer, dma_flags)
struct channel_softc *chp;
struct wdc_xfer *xfer;
- int irq;
+ int dma_flags;
+
{
struct scsi_xfer *sc_xfer = xfer->cmd;
struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];
struct atapiscsi_softc *as = sc_xfer->sc_link->adapter_softc;
int dma_err = 0;
- int dma_flags = 0;
-
- WDCDEBUG_PRINT(("wdc_atapi_intr %s:%d:%d\n",
- chp->wdc->sc_dev.dv_xname, chp->channel, drvp->drive),
- DEBUG_INTR);
-
- /* Is it not a transfer, but a control operation? */
- if (drvp->state < READY) {
- printf("%s:%d:%d: bad state %d in wdc_atapi_intr\n",
- chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,
- drvp->state);
- panic("wdc_atapi_intr: bad state\n");
- }
-
- /* We should really wait_for_unbusy here too before
- switching drives. */
- bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
- WDSD_IBM | (xfer->drive << 4));
-
- /* Ack interrupt done in wait_for_unbusy */
- if (wait_for_unbusy(chp,
- (irq == 0) ? sc_xfer->timeout : 0) != 0) {
- if (irq && (xfer->c_flags & C_TIMEOU) == 0)
- return (0); /* IRQ was not for us */
- printf("%s:%d:%d: device timeout, c_bcount=%d, c_skip=%d\n",
- chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,
- xfer->c_bcount, xfer->c_skip);
- if (xfer->c_flags & C_DMA)
- drvp->n_dmaerrs++;
- sc_xfer->error = XS_TIMEOUT;
- wdc_atapi_reset(chp, xfer);
- return (1);
- }
- /* If we missed an IRQ and were using DMA, flag it as a DMA error */
- if ((xfer->c_flags & C_TIMEOU) && (xfer->c_flags & C_DMA))
- drvp->n_dmaerrs++;
-
- if (chp->ch_status & WDCS_DRQ)
- return (wdc_atapi_intr_drq(chp, xfer, irq));
-
- /* DRQ was dropped. This means the command is over.
- Do cleanup, check for errors, etc. */
- if (xfer->c_flags & C_DMA) {
- dma_flags = ((sc_xfer->flags & SCSI_DATA_IN) ||
- (xfer->c_flags & C_SENSE)) ? WDC_DMA_READ : 0;
- dma_flags |= ((sc_xfer->flags & SCSI_POLL) ||
- (drvp->atapi_cap & ACAP_DSC)) ? WDC_DMA_POLL : 0;
- }
WDCDEBUG_PRINT(("PHASE_COMPLETED\n"), DEBUG_INTR);
@@ -885,7 +856,8 @@
dma_err = (*chp->wdc->dma_finish)(chp->wdc->dma_arg,
chp->channel, xfer->drive, dma_flags);
- /* Assume everything was transferred */
+ /* Assume everything was transferred
+ XXX - maybe we want to check the error register here */
if (xfer->c_flags & C_SENSE)
xfer->c_bcount -= sizeof(sc_xfer->sense);
else
@@ -972,6 +944,69 @@
}
int
+wdc_atapi_intr(chp, xfer, irq)
+ struct channel_softc *chp;
+ struct wdc_xfer *xfer;
+ int irq;
+{
+ struct scsi_xfer *sc_xfer = xfer->cmd;
+ struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];
+ struct atapiscsi_softc *as = sc_xfer->sc_link->adapter_softc;
+ int dma_flags = 0;
+
+ WDCDEBUG_PRINT(("wdc_atapi_intr %s:%d:%d\n",
+ chp->wdc->sc_dev.dv_xname, chp->channel, drvp->drive),
+ DEBUG_INTR);
+
+ /* Is it not a transfer, but a control operation? */
+ if (drvp->state < READY) {
+ printf("%s:%d:%d: bad state %d in wdc_atapi_intr\n",
+ chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,
+ drvp->state);
+ panic("wdc_atapi_intr: bad state\n");
+ }
+
+ /* We should really wait_for_unbusy here too before
+ switching drives. */
+ CHP_WRITE_REG(chp, wdr_sdh, WDSD_IBM | (xfer->drive << 4));
+
+ /* Ack interrupt done in wait_for_unbusy */
+ if (wait_for_unbusy(chp,
+ (irq == 0) ? sc_xfer->timeout : 0) != 0) {
+ if (irq && (xfer->c_flags & C_TIMEOU) == 0)
+ return (0); /* IRQ was not for us */
+ printf("%s:%d:%d: device timeout, c_bcount=%d, c_skip=%d\n",
+ chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,
+ xfer->c_bcount, xfer->c_skip);
+ if (xfer->c_flags & C_DMA)
+ drvp->n_dmaerrs++;
+ sc_xfer->error = XS_TIMEOUT;
+ wdc_atapi_reset(chp, xfer);
+ return (1);
+ }
+ /* If we missed an IRQ and were using DMA, flag it as a DMA error */
+ if ((xfer->c_flags & C_TIMEOU) && (xfer->c_flags & C_DMA))
+ drvp->n_dmaerrs++;
+
+ /* DRQ was dropped. This means the command is over.
+ Do cleanup, check for errors, etc. */
+ if (xfer->c_flags & C_DMA) {
+ dma_flags = ((sc_xfer->flags & SCSI_DATA_IN) ||
+ (xfer->c_flags & C_SENSE)) ? WDC_DMA_READ : 0;
+ dma_flags |= ((sc_xfer->flags & SCSI_POLL) ||
+ (drvp->atapi_cap & ACAP_DSC)) ? WDC_DMA_POLL : 0;
+ }
+
+ if (chp->ch_status & WDCS_DRQ) {
+ if (as->protocol_phase == as_cmdout)
+ return (wdc_atapi_intr_command(chp, xfer, dma_flags));
+ else
+ return (wdc_atapi_intr_data(chp, xfer, dma_flags));
+ } else
+ return (wdc_atapi_intr_complete(chp, xfer, dma_flags));
+}
+
+int
wdc_atapi_ctrl(chp, xfer, irq)
struct channel_softc *chp;
struct wdc_xfer *xfer;
@@ -1005,7 +1040,6 @@
is about the most innocuous thing you can do
that's guaranteed to be there */
case IDENTIFY:
-#if 1
wdccommandshort(chp, drvp->drive, ATAPI_IDENTIFY_DEVICE);
drvp->state = IDENTIFY_WAIT;
break;
@@ -1026,14 +1060,11 @@
errstring = "Post IDENTIFY";
- delay = ATAPI_DELAY;
+ if (wdcwait(chp, WDCS_DRQ, 0, 100))
+ goto timeout;
}
drvp->state = PIOMODE;
- goto again;
-#else
- drvp->state = PIOMODE;
-#endif
case PIOMODE:
piomode:
/* Don't try to set mode if controller can't be adjusted */
@@ -1182,8 +1213,7 @@
if (chp->ch_flags & WDCF_ACTIVE)
return (0);
wdc_select_drive(chp, drvp->drive, 0);
- chp->ch_status =
- bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_status);
+ chp->ch_status = CHP_READ_REG(chp, wdr_status);
return ((chp->ch_status & (WDCS_BSY | WDCS_DSC)) == WDCS_DSC);
}
Index: sys/dev/ic/wdc.c
===================================================================
RCS file: /cvs/src/sys/dev/ic/wdc.c,v
retrieving revision 1.12
retrieving revision 1.14
diff -u -r1.12 -r1.14
--- sys/dev/ic/wdc.c 1999/10/29 01:15:15 1.12
+++ sys/dev/ic/wdc.c 1999/11/17 01:22:56 1.14
@@ -1,4 +1,4 @@
-/* $OpenBSD: wdc.c,v 1.12 1999/10/29 01:15:15 deraadt Exp $ */
+/* $OpenBSD: wdc.c,v 1.14 1999/11/17 01:22:56 csapuntz Exp $ */
/* $NetBSD: wdc.c,v 1.68 1999/06/23 19:00:17 bouyer Exp $ */
@@ -72,10 +72,6 @@
*
*/
-#ifndef WDCDEBUG
-#define WDCDEBUG
-#endif /* WDCDEBUG */
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
@@ -91,13 +87,6 @@
#include <machine/intr.h>
#include <machine/bus.h>
-#ifndef __BUS_SPACE_HAS_STREAM_METHODS
-#define bus_space_write_multi_stream_2 bus_space_write_multi_2
-#define bus_space_write_multi_stream_4 bus_space_write_multi_4
-#define bus_space_read_multi_stream_2 bus_space_read_multi_2
-#define bus_space_read_multi_stream_4 bus_space_read_multi_4
-#endif /* __BUS_SPACE_HAS_STREAM_METHODS */
-
#include <dev/ata/atavar.h>
#include <dev/ata/atareg.h>
#include <dev/ic/wdcreg.h>
@@ -138,6 +127,155 @@
#define WDCDEBUG_PRINT(args, level)
#endif
+
+u_int8_t wdc_default_read_reg __P((struct channel_softc *, enum wdc_regs));
+void wdc_default_write_reg __P((struct channel_softc *, enum wdc_regs, u_int8_t));
+void wdc_default_read_raw_multi_2 __P((struct channel_softc *,
+ void *, unsigned int));
+void wdc_default_write_raw_multi_2 __P((struct channel_softc *,
+ void *, unsigned int));
+void wdc_default_read_raw_multi_4 __P((struct channel_softc *,
+ void *, unsigned int));
+void wdc_default_write_raw_multi_4 __P((struct channel_softc *,
+ void *, unsigned int));
+
+struct channel_softc_vtbl wdc_default_vtbl = {
+ wdc_default_read_reg,
+ wdc_default_write_reg,
+ wdc_default_read_raw_multi_2,
+ wdc_default_write_raw_multi_2,
+ wdc_default_read_raw_multi_4,
+ wdc_default_write_raw_multi_4
+};
+
+u_int8_t
+wdc_default_read_reg(chp, reg)
+ struct channel_softc *chp;
+ enum wdc_regs reg;
+{
+#ifdef DIAGNOSTIC
+ if (reg & _WDC_WRONLY) {
+ printf ("wdc_default_read_reg: reading from a write-only register %d\n", reg);
+ }
+#endif
+
+ if (reg & _WDC_AUX)
+ return (bus_space_read_1(chp->ctl_iot, chp->ctl_ioh,
+ reg & _WDC_REGMASK));
+ else
+ return (bus_space_read_1(chp->cmd_iot, chp->cmd_ioh,
+ reg & _WDC_REGMASK));
+}
+
+void
+wdc_default_write_reg(chp, reg, val)
+ struct channel_softc *chp;
+ enum wdc_regs reg;
+ u_int8_t val;
+{
+#ifdef DIAGNOSTIC
+ if (reg & _WDC_RDONLY) {
+ printf ("wdc_default_write_reg: writing to a read-only register %d\n", reg);
+ }
+#endif
+
+ if (reg & _WDC_AUX)
+ bus_space_write_1(chp->ctl_iot, chp->ctl_ioh,
+ reg & _WDC_REGMASK, val);
+ else
+ bus_space_write_1(chp->cmd_iot, chp->cmd_ioh,
+ reg & _WDC_REGMASK, val);
+}
+
+
+void
+wdc_default_read_raw_multi_2(chp, data, nbytes)
+ struct channel_softc *chp;
+ void *data;
+ unsigned int nbytes;
+{
+ if (data == NULL) {
+ int i;
+
+ for (i = 0; i < nbytes; i += 2) {
+ bus_space_read_2(chp->cmd_iot, chp->cmd_ioh, 0);
+ }
+
+ return;
+ }
+
+ bus_space_read_raw_multi_2(chp->cmd_iot, chp->cmd_ioh, 0,
+ data, nbytes);
+ return;
+}
+
+
+void
+wdc_default_write_raw_multi_2(chp, data, nbytes)
+ struct channel_softc *chp;
+ void *data;
+ unsigned int nbytes;
+{
+ if (data == NULL) {
+ int i;
+
+ for (i = 0; i < nbytes; i += 2) {
+ bus_space_write_2(chp->cmd_iot, chp->cmd_ioh, 0, 0);
+ }
+
+ return;
+ }
+
+ bus_space_write_raw_multi_2(chp->cmd_iot, chp->cmd_ioh, 0,
+ data, nbytes);
+ return;
+}
+
+
+void
+wdc_default_write_raw_multi_4(chp, data, nbytes)
+ struct channel_softc *chp;
+ void *data;
+ unsigned int nbytes;
+{
+ if (data == NULL) {
+ int i;
+
+ for (i = 0; i < nbytes; i += 4) {
+ bus_space_write_4(chp->cmd_iot, chp->cmd_ioh, 0, 0);
+ }
+
+ return;
+ }
+
+ bus_space_write_raw_multi_4(chp->cmd_iot, chp->cmd_ioh, 0,
+ data, nbytes);
+ return;
+}
+
+
+void
+wdc_default_read_raw_multi_4(chp, data, nbytes)
+ struct channel_softc *chp;
+ void *data;
+ unsigned int nbytes;
+{
+ if (data == NULL) {
+ int i;
+
+ for (i = 0; i < nbytes; i += 4) {
+ bus_space_read_4(chp->cmd_iot, chp->cmd_ioh, 0);
+ }
+
+ return;
+ }
+
+ bus_space_read_raw_multi_4(chp->cmd_iot, chp->cmd_ioh, 0,
+ data, nbytes);
+ return;
+}
+
+
int
wdprint(aux, pnp)
void *aux;
@@ -167,16 +305,14 @@
wdc_disable_intr(chp)
struct channel_softc *chp;
{
- bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr,
- WDCTL_IDS);
+ CHP_WRITE_REG(chp, wdr_ctlr, WDCTL_IDS);
}
void
wdc_enable_intr(chp)
struct channel_softc *chp;
{
- bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr,
- WDCTL_4BIT);
+ CHP_WRITE_REG(chp, wdr_ctlr, WDCTL_4BIT);
}
int
@@ -185,8 +321,7 @@
int drive;
int howlong;
{
- bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
- WDSD_IBM | (drive << 4));
+ CHP_WRITE_REG(chp, wdr_sdh, WDSD_IBM | (drive << 4));
delay(1);
@@ -225,20 +360,21 @@
u_int8_t ret_value = 0x03;
u_int8_t drive;
+ if (!chp->_vtbl)
+ chp->_vtbl = &wdc_default_vtbl;
+
/*
* Sanity check to see if the wdc channel responds at all.
*/
if (chp->wdc == NULL ||
(chp->wdc->cap & WDC_CAPABILITY_NO_EXTRA_RESETS) == 0) {
- bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
- WDSD_IBM);
+ CHP_WRITE_REG(chp, wdr_sdh, WDSD_IBM);
delay(10);
- st0 = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_status);
- bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
- WDSD_IBM | 0x10);
+ st0 = CHP_READ_REG(chp, wdr_status);
+ CHP_WRITE_REG(chp, wdr_sdh, WDSD_IBM | 0x10);
delay(10);
- st1 = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_status);
+ st1 = CHP_READ_REG(chp, wdr_status);
WDCDEBUG_PRINT(("%s:%d: before reset, st0=0x%x, st1=0x%x\n",
chp->wdc ? chp->wdc->sc_dev.dv_xname : "wdcprobe",
@@ -253,17 +389,14 @@
}
/* assert SRST, wait for reset to complete */
- bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
- WDSD_IBM);
+ CHP_WRITE_REG(chp, wdr_sdh, WDSD_IBM);
delay(10);
- bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr,
- WDCTL_RST | WDCTL_IDS);
+ CHP_WRITE_REG(chp,wdr_ctlr, WDCTL_RST | WDCTL_IDS);
DELAY(1000);
- bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr,
- WDCTL_IDS);
+ CHP_WRITE_REG(chp, wdr_ctlr, WDCTL_IDS);
delay(1000);
- (void) bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_error);
- bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr, WDCTL_4BIT);
+ (void) CHP_READ_REG(chp, wdr_error);
+ CHP_WRITE_REG(chp, wdr_ctlr, WDCTL_4BIT);
delay(10);
ret_value = __wdcwait_reset(chp, ret_value);
@@ -284,14 +417,13 @@
for (drive = 0; drive < 2; drive++) {
if ((ret_value & (0x01 << drive)) == 0)
continue;
- bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
- WDSD_IBM | (drive << 4));
+ CHP_WRITE_REG(chp, wdr_sdh, WDSD_IBM | (drive << 4));
delay(10);
/* Save registers contents */
- sc = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_seccnt);
- sn = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_sector);
- cl = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_cyl_lo);
- ch = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_cyl_hi);
+ sc = CHP_READ_REG(chp, wdr_seccnt);
+ sn = CHP_READ_REG(chp, wdr_sector);
+ cl = CHP_READ_REG(chp, wdr_cyl_lo);
+ ch = CHP_READ_REG(chp, wdr_cyl_hi);
WDCDEBUG_PRINT(("%s:%d:%d: after reset, sc=0x%x sn=0x%x "
"cl=0x%x ch=0x%x\n",
@@ -333,6 +465,8 @@
return;
}
#endif
+ if (!chp->_vtbl)
+ chp->_vtbl = &wdc_default_vtbl;
if (wdcprobe(chp) == 0) {
/* If no drives, abort attach here. */
@@ -382,25 +516,19 @@
* Test registers writability (Error register not
* writable, but cyllo is), then try an ATA command.
*/
- bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
- WDSD_IBM | (i << 4));
+ CHP_WRITE_REG(chp, wdr_sdh, WDSD_IBM | (i << 4));
delay(10);
- bus_space_write_1(chp->cmd_iot, chp->cmd_ioh,
- wd_error, 0x58);
- bus_space_write_1(chp->cmd_iot, chp->cmd_ioh,
- wd_cyl_lo, 0xa5);
- if (bus_space_read_1(chp->cmd_iot, chp->cmd_ioh,
- wd_error == 0x58) ||
- bus_space_read_1(chp->cmd_iot, chp->cmd_ioh,
- wd_cyl_lo) != 0xa5) {
+ CHP_WRITE_REG(chp, wdr_features, 0x58);
+ CHP_WRITE_REG(chp, wdr_cyl_lo, 0xa5);
+ if ((CHP_READ_REG(chp, wdr_error) == 0x58) ||
+ (CHP_READ_REG(chp, wdr_cyl_lo) != 0xa5)) {
WDCDEBUG_PRINT(("%s:%d:%d: register "
"writability failed\n",
chp->wdc->sc_dev.dv_xname,
chp->channel, i), DEBUG_PROBE);
chp->ch_drive[i].drive_flags &= ~DRIVE_OLD;
}
- bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
- WDSD_IBM | (i << 4));
+ CHP_WRITE_REG(chp, wdr_sdh, WDSD_IBM | (i << 4));
delay(100);
if (wait_for_ready(chp, 10000) != 0) {
WDCDEBUG_PRINT(("%s:%d:%d: not ready\n",
@@ -409,8 +537,7 @@
chp->ch_drive[i].drive_flags &= ~DRIVE_OLD;
continue;
}
- bus_space_write_1(chp->cmd_iot, chp->cmd_ioh,
- wd_command, WDCC_RECAL);
+ CHP_WRITE_REG(chp, wdr_command, WDCC_RECAL);
if (wait_for_ready(chp, 10000) != 0) {
WDCDEBUG_PRINT(("%s:%d:%d: WDCC_RECAL failed\n",
chp->wdc->sc_dev.dv_xname,
@@ -491,8 +618,8 @@
*/
for (i = 1; i >= 0; i--) {
if (chp->ch_drive[i].drive_flags & DRIVE) {
- bus_space_write_1(chp->cmd_iot, chp->cmd_ioh,
- wd_sdh, WDSD_IBM | (i << 4));
+ CHP_WRITE_REG(chp,
+ wdr_sdh, WDSD_IBM | (i << 4));
if (wait_for_unbusy(chp, 10000) < 0)
printf("%s:%d:%d: device busy\n",
chp->wdc->sc_dev.dv_xname,
@@ -545,7 +672,7 @@
panic("wdcstart: channel waiting for irq\n");
#endif
if (chp->wdc->cap & WDC_CAPABILITY_HWLOCK)
- if (!(*chp->wdc->claim_hw)(chp, 0))
+ if (!(chp->wdc->claim_hw)(chp, 0))
return;
WDCDEBUG_PRINT(("wdcstart: xfer %p channel %d drive %d\n", xfer,
@@ -619,17 +746,13 @@
{
int drv_mask1, drv_mask2;
- bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
- WDSD_IBM); /* master */
- bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr,
- WDCTL_RST | WDCTL_IDS);
+ CHP_WRITE_REG(chp, wdr_sdh, WDSD_IBM); /* master */
+ CHP_WRITE_REG(chp, wdr_ctlr, WDCTL_RST | WDCTL_IDS);
delay(1000);
- bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr,
- WDCTL_IDS);
+ CHP_WRITE_REG(chp, wdr_ctlr, WDCTL_IDS);
delay(2000);
- (void) bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_error);
- bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr,
- WDCTL_4BIT);
+ (void) CHP_READ_REG(chp,wdr_error);
+ CHP_WRITE_REG(chp, wdr_ctlr, WDCTL_4BIT);
drv_mask1 = (chp->ch_drive[0].drive_flags & DRIVE) ? 0x01:0x00;
drv_mask1 |= (chp->ch_drive[1].drive_flags & DRIVE) ? 0x02:0x00;
@@ -660,14 +783,12 @@
/* wait for BSY to deassert */
for (timeout = 0; timeout < WDCNDELAY_RST;timeout++) {
- bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
- WDSD_IBM); /* master */
+ CHP_WRITE_REG(chp, wdr_sdh, WDSD_IBM); /* master */
delay(10);
- st0 = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_status);
- bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
- WDSD_IBM | 0x10); /* slave */
+ st0 = CHP_READ_REG(chp, wdr_status);
+ CHP_WRITE_REG(chp, wdr_sdh, WDSD_IBM | 0x10); /* slave */
delay(10);
- st1 = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_status);
+ st1 = CHP_READ_REG(chp, wdr_status);
if ((drv_mask & 0x01) == 0) {
/* no master */
@@ -726,25 +847,18 @@
for (;;) {
#ifdef TEST_ALTSTS
- chp->ch_status = status =
- bus_space_read_1(chp->ctl_iot, chp->ctl_ioh,
- wd_aux_altsts);
+ chp->ch_status = status = CHP_READ_REG(chp, wdr_altsts);
#else
- chp->ch_status = status =
- bus_space_read_1(chp->cmd_iot, chp->cmd_ioh,
- wd_status);
+ chp->ch_status = status = CHP_READ_REG(chp, wdr_status);
#endif
if (status == 0xff && (chp->ch_flags & WDCF_ONESLAVE)) {
- bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
- WDSD_IBM | 0x10);
+ CHP_WRITE_REG(chp, wdr_sdh, WDSD_IBM | 0x10);
#ifdef TEST_ALTSTS
chp->ch_status = status =
- bus_space_read_1(chp->ctl_iot, chp->ctl_ioh,
- wd_aux_altsts);
+ CHP_READ_REG(chp, wdr_altsts);
#else
chp->ch_status = status =
- bus_space_read_1(chp->cmd_iot, chp->cmd_ioh,
- wd_status);
+ CHP_READ_REG(chp, wdr_status);
#endif
}
if ((status & WDCS_BSY) == 0 && (status & mask) == bits)
@@ -752,8 +866,7 @@
if (++time > timeout) {
WDCDEBUG_PRINT(("wdcwait: timeout, status %x "
"error %x\n", status,
- bus_space_read_1(chp->cmd_iot, chp->cmd_ioh,
- wd_error)),
+ CHP_READ_REG(chp, wdr_error)),
DEBUG_STATUSX | DEBUG_STATUS);
return -1;
}
@@ -761,11 +874,10 @@
}
#ifdef TEST_ALTSTS
/* Acknowledge any pending interrupts */
- bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_status);
+ CHP_READ_REG(chp, wdr_status);
#endif
if (status & WDCS_ERR) {
- chp->ch_error = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh,
- wd_error);
+ chp->ch_error = CHP_READ_REG(chp, wdr_error);
WDCDEBUG_PRINT(("wdcwait: error %x\n", chp->ch_error),
DEBUG_STATUSX | DEBUG_STATUS);
}
@@ -1010,23 +1122,23 @@
{
struct channel_softc *chp = drvp->chnl_softc;
unsigned int off = 0;
- unsigned int len = buflen;
+ unsigned int len = buflen, roundlen;
if (drvp->drive_flags & DRIVE_CAP32) {
- bus_space_write_multi_4(chp->data32iot,
- chp->data32ioh, wd_data,
- (void *)((u_int8_t *)bytes + off),
- len >> 2);
+ roundlen = len & ~3;
- off += ((len >> 2) << 2);
- len = len & 0x03;
+ CHP_WRITE_RAW_MULTI_4(chp,
+ (void *)((u_int8_t *)bytes + off), roundlen);
+
+ off += roundlen;
+ len -= roundlen;
}
if (len > 0) {
- bus_space_write_multi_2(chp->cmd_iot,
- chp->cmd_ioh, wd_data,
- (void *)((u_int8_t *)bytes + off),
- (len + 1) >> 1);
+ roundlen = (len + 1) & ~0x1;
+
+ CHP_WRITE_RAW_MULTI_2(chp,
+ (void *)((u_int8_t *)bytes + off), roundlen);
}
return;
@@ -1040,22 +1152,23 @@
{
struct channel_softc *chp = drvp->chnl_softc;
unsigned int off = 0;
- unsigned int len = buflen;
+ unsigned int len = buflen, roundlen;
if (drvp->drive_flags & DRIVE_CAP32) {
- bus_space_read_multi_4(chp->data32iot,
- chp->data32ioh, wd_data,
- (void *)((u_int8_t *)bytes + off),
- len >> 2);
- off += ((len >> 2) << 2);
- len = len & 0x03;
+ roundlen = len & ~3;
+
+ CHP_READ_RAW_MULTI_4(chp,
+ (void *)((u_int8_t *)bytes + off), roundlen);
+
+ off += roundlen;
+ len -= roundlen;
}
if (len > 0) {
- bus_space_read_multi_2(chp->cmd_iot,
- chp->cmd_ioh, wd_data,
- (void *)((u_int8_t *)bytes + off),
- (len + 1) >> 1);
+ roundlen = (len + 1) & ~0x1;
+
+ CHP_READ_RAW_MULTI_2(chp,
+ (void *)((u_int8_t *)bytes + off), roundlen);
}
return;
@@ -1236,8 +1349,7 @@
* For resets, we don't really care to make sure that
* the bus is free
*/
- bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
- WDSD_IBM | (drive << 4));
+ CHP_WRITE_REG(chp, wdr_sdh, WDSD_IBM | (drive << 4));
if (wdc_c->r_command != ATAPI_SOFT_RESET) {
if (wdcwait(chp, wdc_c->r_st_bmask, wdc_c->r_st_bmask,
@@ -1315,20 +1427,15 @@
wdc_c->flags |= AT_DONE;
if (wdc_c->flags & AT_READREG && (wdc_c->flags & (AT_ERROR | AT_DF))
== 0) {
- wdc_c->r_head = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh,
- wd_sdh);
- wdc_c->r_cyl = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh,
- wd_cyl_hi) << 8;
- wdc_c->r_cyl |= bus_space_read_1(chp->cmd_iot, chp->cmd_ioh,
- wd_cyl_lo);
- wdc_c->r_sector = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh,
- wd_sector);
- wdc_c->r_count = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh,
- wd_seccnt);
- wdc_c->r_error = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh,
- wd_error);
- wdc_c->r_precomp = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh,
- wd_precomp);
+ wdc_c->r_head = CHP_READ_REG(chp, wdr_sdh);
+ wdc_c->r_cyl = CHP_READ_REG(chp, wdr_cyl_hi) << 8;
+ wdc_c->r_cyl |= CHP_READ_REG(chp, wdr_cyl_lo);
+ wdc_c->r_sector = CHP_READ_REG(chp, wdr_sector);
+ wdc_c->r_count = CHP_READ_REG(chp, wdr_seccnt);
+ wdc_c->r_error = CHP_READ_REG(chp, wdr_error);
+ wdc_c->r_precomp = wdc_c->r_error;
+ /* XXX CHP_READ_REG(chp, wdr_precomp); - precomp
+ isn't a readable register */
}
if (xfer->c_flags & C_POLL) {
wdc_enable_intr(chp);
@@ -1364,19 +1471,17 @@
DEBUG_FUNCS);
/* Select drive, head, and addressing mode. */
- bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
- WDSD_IBM | (drive << 4) | head);
+ CHP_WRITE_REG(chp, wdr_sdh, WDSD_IBM | (drive << 4) | head);
- /* Load parameters. wd_features(ATA/ATAPI) = wd_precomp(ST506) */
- bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_precomp,
- precomp);
- bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_cyl_lo, cylin);
- bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_cyl_hi, cylin >> 8);
- bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sector, sector);
- bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_seccnt, count);
+ /* Load parameters. wdr_features(ATA/ATAPI) = wdr_precomp(ST506) */
+ CHP_WRITE_REG(chp, wdr_precomp, precomp);
+ CHP_WRITE_REG(chp, wdr_cyl_lo, cylin);
+ CHP_WRITE_REG(chp, wdr_cyl_hi, cylin >> 8);
+ CHP_WRITE_REG(chp, wdr_sector, sector);
+ CHP_WRITE_REG(chp, wdr_seccnt, count);
/* Send command. */
- bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_command, command);
+ CHP_WRITE_REG(chp, wdr_command, command);
return;
}
@@ -1396,10 +1501,8 @@
DEBUG_FUNCS);
/* Select drive. */
- bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
- WDSD_IBM | (drive << 4));
-
- bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_command, command);
+ CHP_WRITE_REG(chp, wdr_sdh, WDSD_IBM | (drive << 4));
+ CHP_WRITE_REG(chp, wdr_command, command);
}
/* Add a command to the queue and start controller. Must be called at splbio */
@@ -1519,11 +1622,7 @@
struct channel_softc *chp;
int size;
{
-
- for (; size >= 2; size -= 2)
- (void)bus_space_read_2(chp->cmd_iot, chp->cmd_ioh, wd_data);
- if (size)
- (void)bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_data);
+ CHP_READ_RAW_MULTI_2(chp, NULL, size);
}
#ifndef __OpenBSD__
Index: sys/dev/ic/wdcreg.h
===================================================================
RCS file: /cvs/src/sys/dev/ic/wdcreg.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- sys/dev/ic/wdcreg.h 1999/07/18 21:25:16 1.1
+++ sys/dev/ic/wdcreg.h 1999/11/17 01:22:56 1.2
@@ -1,4 +1,4 @@
-/* $OpenBSD: wdcreg.h,v 1.1 1999/07/18 21:25:16 csapuntz Exp $ */
+/* $OpenBSD: wdcreg.h,v 1.2 1999/11/17 01:22:56 csapuntz Exp $ */
/* $NetBSD: wdcreg.h,v 1.22 1999/03/07 14:02:54 bouyer Exp $ */
/*-
@@ -39,27 +39,9 @@
* @(#)wdreg.h 7.1 (Berkeley) 5/9/91
*/
-/*
- * Disk Controller register definitions.
- */
-
-/* offsets of registers in the 'regular' register region */
-#define wd_data 0 /* data register (R/W - 16 bits) */
-#define wd_error 1 /* error register (R) */
-#define wd_precomp 1 /* write precompensation (W) */
-#define wd_features 1 /* features (W), same as wd_precomp */
-#define wd_seccnt 2 /* sector count (R/W) */
-#define wd_ireason 2 /* interrupt reason (R/W) (for atapi) */
-#define wd_sector 3 /* first sector number (R/W) */
-#define wd_cyl_lo 4 /* cylinder address, low byte (R/W) */
-#define wd_cyl_hi 5 /* cylinder address, high byte (R/W) */
-#define wd_sdh 6 /* sector size/drive/head (R/W) */
-#define wd_command 7 /* command register (W) */
-#define wd_status 7 /* immediate status (R) */
-
-/* offsets of registers in the auxiliary register region */
-#define wd_aux_altsts 0 /* alternate fixed disk status (R) */
-#define wd_aux_ctlr 0 /* fixed disk controller control (W) */
+/*
+ * Controller register (wdr_ctlr)
+ */
#define WDCTL_4BIT 0x08 /* use four head bits (wd1003) */
#define WDCTL_RST 0x04 /* reset the controller */
#define WDCTL_IDS 0x02 /* disable controller interrupts */
@@ -178,4 +160,5 @@
#define PHASE_DATAOUT WDCS_DRQ
#define PHASE_COMPLETED (WDCI_IN | WDCI_CMD)
#define PHASE_ABORTED 0
+
Index: sys/dev/ic/wdcvar.h
===================================================================
RCS file: /cvs/src/sys/dev/ic/wdcvar.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- sys/dev/ic/wdcvar.h 1999/10/29 01:15:15 1.4
+++ sys/dev/ic/wdcvar.h 1999/11/17 01:22:56 1.5
@@ -1,4 +1,4 @@
-/* $OpenBSD: wdcvar.h,v 1.4 1999/10/29 01:15:15 deraadt Exp $ */
+/* $OpenBSD: wdcvar.h,v 1.5 1999/11/17 01:22:56 csapuntz Exp $ */
/* $NetBSD: wdcvar.h,v 1.17 1999/04/11 20:50:29 bouyer Exp $ */
/*-
@@ -44,7 +44,11 @@
TAILQ_HEAD(xferhead, wdc_xfer) sc_xfer;
};
+struct channel_softc_vtbl;
+
struct channel_softc { /* Per channel data */
+ struct channel_softc_vtbl *_vtbl;
+
/* Our location */
int channel;
/* Our controller's softc */
@@ -73,6 +77,57 @@
*/
struct channel_queue *ch_queue;
};
+
+/*
+ * Disk Controller register definitions.
+ */
+#define _WDC_REGMASK 7
+#define _WDC_AUX 8
+#define _WDC_RDONLY 16
+#define _WDC_WRONLY 32
+enum wdc_regs {
+ wdr_error = _WDC_RDONLY | 1,
+ wdr_precomp = _WDC_WRONLY | 1,
+ wdr_features = _WDC_WRONLY | 1,
+ wdr_seccnt = 2,
+ wdr_ireason = 2,
+ wdr_sector = 3,
+ wdr_cyl_lo = 4,
+ wdr_cyl_hi = 5,
+ wdr_sdh = 6,
+ wdr_status = _WDC_RDONLY | 7,
+ wdr_command = _WDC_WRONLY | 7,
+ wdr_altsts = _WDC_RDONLY | _WDC_AUX,
+ wdr_ctlr = _WDC_WRONLY | _WDC_AUX
+};
+
+struct channel_softc_vtbl {
+ u_int8_t (*read_reg)(struct channel_softc *, enum wdc_regs reg);
+ void (*write_reg)(struct channel_softc *, enum wdc_regs reg,
+ u_int8_t var);
+
+ void (*read_raw_multi_2)(struct channel_softc *,
+ void *data, unsigned int nbytes);
+ void (*write_raw_multi_2)(struct channel_softc *,
+ void *data, unsigned int nbytes);
+
+ void (*read_raw_multi_4)(struct channel_softc *,
+ void *data, unsigned int nbytes);
+ void (*write_raw_multi_4)(struct channel_softc *,
+ void *data, unsigned int nbytes);
+};
+
+
+#define CHP_READ_REG(chp, a) ((chp)->_vtbl->read_reg)(chp, a)
+#define CHP_WRITE_REG(chp, a, b) ((chp)->_vtbl->write_reg)(chp, a, b)
+#define CHP_READ_RAW_MULTI_2(chp, a, b) \
+ ((chp)->_vtbl->read_raw_multi_2)(chp, a, b)
+#define CHP_WRITE_RAW_MULTI_2(chp, a, b) \
+ ((chp)->_vtbl->write_raw_multi_2)(chp, a, b)
+#define CHP_READ_RAW_MULTI_4(chp, a, b) \
+ ((chp)->_vtbl->read_raw_multi_4)(chp, a, b)
+#define CHP_WRITE_RAW_MULTI_4(chp, a, b) \
+ ((chp)->_vtbl->write_raw_multi_4)(chp, a, b)
struct wdc_softc { /* Per controller state */
struct device sc_dev;