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;