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;