This commit was manufactured by cvs2svn to create tag 'FreeBSD-release/1.1'.
[unix-history] / sys / i386 / isa / wd.c
index 3a216ae..eb5a34b 100644 (file)
@@ -37,11 +37,10 @@ static int wdtest = 0;
  * SUCH DAMAGE.
  *
  *     from: @(#)wd.c  7.2 (Berkeley) 5/9/91
  * SUCH DAMAGE.
  *
  *     from: @(#)wd.c  7.2 (Berkeley) 5/9/91
- *     $Id: wd.c,v 1.23 1994/02/01 05:55:21 nate Exp $
+ *     $Id: wd.c,v 1.36 1994/03/06 03:10:58 jkh Exp $
  */
 
 /* TODO:
  */
 
 /* TODO:
- *     o Fix timeout from 2 to about 4 seconds.
  *     o Bump error count after timeout.
  *     o Satisfy ATA timing in all cases.
  *     o Finish merging berry/sos timeout code (bump error count...).
  *     o Bump error count after timeout.
  *     o Satisfy ATA timing in all cases.
  *     o Finish merging berry/sos timeout code (bump error count...).
@@ -84,9 +83,7 @@ static int wdtest = 0;
 #include "syslog.h"
 #include "vm/vm.h"
 
 #include "syslog.h"
 #include "vm/vm.h"
 
-#ifndef WDCTIMEOUT
-#define WDCTIMEOUT     10000000  /* arbitrary timeout for drive ready waits */
-#endif
+#define        TIMEOUT         10000   /* XXX? WDCC_DIAGNOSE can take > 1.1 sec */
 
 #define        RETRIES         5       /* number of retries before giving up */
 #define RECOVERYTIME   500000  /* usec for controller to recover after err */
 
 #define        RETRIES         5       /* number of retries before giving up */
 #define RECOVERYTIME   500000  /* usec for controller to recover after err */
@@ -176,9 +173,9 @@ static void wderror(struct buf *bp, struct disk *du, char *mesg);
 static void wdflushirq(struct disk *du, int old_ipl);
 static int wdreset(struct disk *du);
 static void wdsleep(int ctrlr, char *wmesg);
 static void wdflushirq(struct disk *du, int old_ipl);
 static int wdreset(struct disk *du);
 static void wdsleep(int ctrlr, char *wmesg);
-static int wdtimeout(caddr_t cdu, int ticks);
+static void wdtimeout(caddr_t cdu, int ticks);
 static int wdunwedge(struct disk *du);
 static int wdunwedge(struct disk *du);
-static int wdwait(struct disk *du, u_char bits_wanted);
+static int wdwait(struct disk *du, u_char bits_wanted, int timeout);
 
 struct isa_driver wdcdriver = {
        wdprobe, wdattach, "wdc",
 
 struct isa_driver wdcdriver = {
        wdprobe, wdattach, "wdc",
@@ -212,7 +209,7 @@ wdprobe(struct isa_device *dvp)
 
        /* execute a controller only command */
        if (wdcommand(du, 0, 0, 0, 0, WDCC_DIAGNOSE) != 0
 
        /* execute a controller only command */
        if (wdcommand(du, 0, 0, 0, 0, WDCC_DIAGNOSE) != 0
-           || wdwait(du, 0) != 0)
+           || wdwait(du, 0, TIMEOUT) != 0)
                goto nodevice;
 
        free(du, M_TEMP);
                goto nodevice;
 
        free(du, M_TEMP);
@@ -257,41 +254,29 @@ wdattach(struct isa_device *dvp)
                du->dk_port = dvp->id_iobase;
 
                /*
                du->dk_port = dvp->id_iobase;
 
                /*
-                * Print out description of drive, suppressing multiple
-                * blanks.
+                * Print out description of drive.
+                * wdp_model can be [0..40] bytes, thus \0 can be missing so
+                * so copy it and add a null before printing.
                 */
                if (wdgetctlr(du) == 0) {
                 */
                if (wdgetctlr(du) == 0) {
-                       int     i, blank;
-
-                       printf("wdc%d: unit %d (wd%d): ",
-                              dvp->id_unit, unit, lunit);
-                       if (du->dk_params.wdp_heads == 0)
-                               printf("size unknown");
-                       else
-                               printf("%luMB %lu cyl, %lu head, %lu sec",
-                                      du->dk_dd.d_secperunit
-                                      * du->dk_dd.d_secsize / (1024 * 1024),
-                                      du->dk_dd.d_ncylinders,
-                                      du->dk_dd.d_ntracks,
-                                      du->dk_dd.d_nsectors);
-                       printf(", type ");
-                       for (i = blank = 0; i < sizeof(du->dk_params.wdp_model); i++) {
-                               char    c = du->dk_params.wdp_model[i];
-
-                               if (blank && c == ' ')
-                                       continue;
-                               if (blank && c != ' ') {
-                                       printf(" %c", c);
-                                       blank = 0;
-                                       continue;
-                               }
-                               if (c == ' ')
-                                       blank = 1;
-                               else
-                                       printf("%c", c);
-                       }
-                       printf("\n");
-
+                   char buf[sizeof(du->dk_params.wdp_model) + 1];
+                   bcopy(du->dk_params.wdp_model, buf, sizeof(buf)-1);
+                   buf[sizeof(buf)-1] = '\0';
+                   printf("wdc%d: unit %d (wd%d): <%s>\n",
+                       dvp->id_unit, unit, lunit, buf);
+                   if (du->dk_params.wdp_heads == 0)
+                       printf("wd%d: size unknown\n", lunit);
+                   else
+                       printf("wd%d: %luMB (%lu total sec), ",
+                               lunit,
+                               du->dk_dd.d_secperunit
+                               * du->dk_dd.d_secsize / (1024 * 1024),
+                               du->dk_dd.d_secperunit);
+                       printf("%lu cyl, %lu head, %lu sec, bytes/sec %lu\n",
+                               du->dk_dd.d_ncylinders,
+                               du->dk_dd.d_ntracks,
+                               du->dk_dd.d_nsectors,
+                               du->dk_dd.d_secsize);
                        /*
                         * Start timeout routine for this drive.
                         * XXX timeout should be per controller.
                        /*
                         * Start timeout routine for this drive.
                         * XXX timeout should be per controller.
@@ -592,14 +577,14 @@ loop:
         * think).  Discarding them would be OK if the (special) file offset
         * was not advanced.
         */
         * think).  Discarding them would be OK if the (special) file offset
         * was not advanced.
         */
-       du->dk_timeout = 1 + 1;
+       du->dk_timeout = 1 + 3;
 
        /* If this is a read operation, just go away until it's done. */
        if (bp->b_flags & B_READ)
                return;
 
        /* Ready to send data? */
 
        /* If this is a read operation, just go away until it's done. */
        if (bp->b_flags & B_READ)
                return;
 
        /* Ready to send data? */
-       if (wdwait(du, WDCS_READY | WDCS_SEEKCMPLT | WDCS_DRQ) < 0) {
+       if (wdwait(du, WDCS_READY | WDCS_SEEKCMPLT | WDCS_DRQ, TIMEOUT) < 0) {
                wderror(bp, du, "wdstart: timeout waiting for DRQ");
                /*
                 * XXX what do we do now?  If we've just issued the command,
                wderror(bp, du, "wdstart: timeout waiting for DRQ");
                /*
                 * XXX what do we do now?  If we've just issued the command,
@@ -615,7 +600,7 @@ loop:
 
        /* then send it! */
        outsw(du->dk_port + wd_data,
 
        /* then send it! */
        outsw(du->dk_port + wd_data,
-             (int)bp->b_un.b_addr + du->dk_skip * DEV_BSIZE,
+             (void *)((int)bp->b_un.b_addr + du->dk_skip * DEV_BSIZE),
              DEV_BSIZE / sizeof(short));
        du->dk_bc -= DEV_BSIZE;
 }
              DEV_BSIZE / sizeof(short));
        du->dk_bc -= DEV_BSIZE;
 }
@@ -634,7 +619,9 @@ wdintr(int unit)
        if (wdtab[unit].b_active == 2)
                return;         /* intr in wdflushirq() */
        if (!wdtab[unit].b_active) {
        if (wdtab[unit].b_active == 2)
                return;         /* intr in wdflushirq() */
        if (!wdtab[unit].b_active) {
+#ifndef LAPTOP
                printf("wdc%d: extra interrupt\n", unit);
                printf("wdc%d: extra interrupt\n", unit);
+#endif
                return;
        }
 
                return;
        }
 
@@ -643,7 +630,7 @@ wdintr(int unit)
        du = wddrives[wdunit(bp->b_dev)];
        du->dk_timeout = 0;
 
        du = wddrives[wdunit(bp->b_dev)];
        du->dk_timeout = 0;
 
-       if (wdwait(du, 0) < 0) {
+       if (wdwait(du, 0, TIMEOUT) < 0) {
                wderror(bp, du, "wdintr: timeout waiting for status");
                du->dk_status |= WDCS_ERR;      /* XXX */
        }
                wderror(bp, du, "wdintr: timeout waiting for status");
                du->dk_status |= WDCS_ERR;      /* XXX */
        }
@@ -651,9 +638,15 @@ wdintr(int unit)
        /* is it not a transfer, but a control operation? */
        if (du->dk_state < OPEN) {
                wdtab[unit].b_active = 0;
        /* is it not a transfer, but a control operation? */
        if (du->dk_state < OPEN) {
                wdtab[unit].b_active = 0;
-               if (wdcontrol(bp))
+               switch (wdcontrol(bp)) {
+               case 0:
+                       return;
+               case 1:
                        wdstart(unit);
                return;
                        wdstart(unit);
                return;
+               case 2:
+                       goto done;
+               }
        }
 
        /* have we an error? */
        }
 
        /* have we an error? */
@@ -697,17 +690,15 @@ oops:
                chk = min(DEV_BSIZE / sizeof(short), du->dk_bc / sizeof(short));
 
                /* ready to receive data? */
                chk = min(DEV_BSIZE / sizeof(short), du->dk_bc / sizeof(short));
 
                /* ready to receive data? */
-               if ((du->dk_status & (WDCS_READY | WDCS_SEEKCMPLT | WDCS_DRQ))
-                   != (WDCS_READY | WDCS_SEEKCMPLT | WDCS_DRQ))
-                       wderror(bp, du, "wdintr: read intr arrived early");
-               if (wdwait(du, WDCS_READY | WDCS_SEEKCMPLT | WDCS_DRQ) != 0) {
+               if (wdwait(du, WDCS_READY | WDCS_SEEKCMPLT | WDCS_DRQ, TIMEOUT) != 0) {
                        wderror(bp, du, "wdintr: read error detected late");
                        goto oops;
                }
 
                /* suck in data */
                insw(du->dk_port + wd_data,
                        wderror(bp, du, "wdintr: read error detected late");
                        goto oops;
                }
 
                /* suck in data */
                insw(du->dk_port + wd_data,
-                    (int)bp->b_un.b_addr + du->dk_skip * DEV_BSIZE, chk);
+                    (void *)((int)bp->b_un.b_addr + du->dk_skip * DEV_BSIZE),
+                               chk);
                du->dk_bc -= chk * sizeof(short);
 
                /* XXX for obsolete fractional sector reads. */
                du->dk_bc -= chk * sizeof(short);
 
                /* XXX for obsolete fractional sector reads. */
@@ -739,9 +730,8 @@ outt:
                                return; /* redo xfer sector by sector */
                        }
                }
                                return; /* redo xfer sector by sector */
                        }
                }
-#ifdef B_FORMAT
+
 done: ;
 done: ;
-#endif
                /* done with this transfer, with or without error */
                du->dk_flags &= ~DKFL_SINGLE;
                wdtab[unit].b_actf = dp->b_forw;
                /* done with this transfer, with or without error */
                du->dk_flags &= ~DKFL_SINGLE;
                wdtab[unit].b_actf = dp->b_forw;
@@ -834,7 +824,7 @@ wdopen(dev_t dev, int flags, int fmt, struct proc *p)
                save_label = du->dk_dd;
 #define WDSTRATEGY     ((int (*)(struct buf *)) wdstrategy)    /* XXX */
                msg = readdisklabel(makewddev(major(dev), lunit, WDRAW),
                save_label = du->dk_dd;
 #define WDSTRATEGY     ((int (*)(struct buf *)) wdstrategy)    /* XXX */
                msg = readdisklabel(makewddev(major(dev), lunit, WDRAW),
-                                   WDSTRATEGY, &du->dk_dd,
+                                   (d_strategy_t *) WDSTRATEGY, &du->dk_dd,
                                    du->dk_dospartitions, &du->dk_bad,
                                    (struct buf **)NULL);
                du->dk_flags &= ~DKFL_LABELLING;
                                    du->dk_dospartitions, &du->dk_bad,
                                    (struct buf **)NULL);
                du->dk_flags &= ~DKFL_LABELLING;
@@ -939,7 +929,7 @@ wdopen(dev_t dev, int flags, int fmt, struct proc *p)
  * Implement operations other than read/write.
  * Called from wdstart or wdintr during opens and formats.
  * Uses finite-state-machine to track progress of operation in progress.
  * Implement operations other than read/write.
  * Called from wdstart or wdintr during opens and formats.
  * Uses finite-state-machine to track progress of operation in progress.
- * Returns 0 if operation still in progress, 1 if completed.
+ * Returns 0 if operation still in progress, 1 if completed, 2 if error.
  */
 static int
 wdcontrol(register struct buf *bp)
  */
 static int
 wdcontrol(register struct buf *bp)
@@ -971,7 +961,7 @@ maybe_retry:
                                goto tryagainrecal;
                        bp->b_error = ENXIO;    /* XXX needs translation */
                        bp->b_flags |= B_ERROR;
                                goto tryagainrecal;
                        bp->b_error = ENXIO;    /* XXX needs translation */
                        bp->b_flags |= B_ERROR;
-                       return (1);
+                       return (2);
                }
                wdtab[ctrlr].b_errcnt = 0;
                du->dk_state = OPEN;
                }
                wdtab[ctrlr].b_errcnt = 0;
                du->dk_state = OPEN;
@@ -982,7 +972,7 @@ maybe_retry:
                return (1);
        }
        panic("wdcontrol");
                return (1);
        }
        panic("wdcontrol");
-       return (1);
+       return (2);
 }
 
 /*
 }
 
 /*
@@ -996,7 +986,7 @@ wdcommand(struct disk *du, u_int cylinder, u_int head, u_int sector,
 {
        u_int   wdc;
 
 {
        u_int   wdc;
 
-       if (wdwait(du, 0) < 0)
+       if (wdwait(du, 0, TIMEOUT) < 0)
                return (1);
        wdc = du->dk_port;
        outb(wdc + wd_precomp, du->dk_dd.d_precompcyl / 4);
                return (1);
        wdc = du->dk_port;
        outb(wdc + wd_precomp, du->dk_dd.d_precompcyl / 4);
@@ -1006,7 +996,7 @@ wdcommand(struct disk *du, u_int cylinder, u_int head, u_int sector,
        outb(wdc + wd_sector, sector + 1);
        outb(wdc + wd_seccnt, count);
        if (wdwait(du, command == WDCC_DIAGNOSE || command == WDCC_IDC
        outb(wdc + wd_sector, sector + 1);
        outb(wdc + wd_seccnt, count);
        if (wdwait(du, command == WDCC_DIAGNOSE || command == WDCC_IDC
-                      ? 0 : WDCS_READY) < 0)
+                      ? 0 : WDCS_READY, TIMEOUT) < 0)
                return (1);
        outb(wdc + wd_command, command);
        return (0);
                return (1);
        outb(wdc + wd_command, command);
        return (0);
@@ -1024,14 +1014,26 @@ wdsetctlr(struct disk *du)
               du->dk_dd.d_ncylinders, du->dk_dd.d_ntracks,
               du->dk_dd.d_nsectors);
 #endif
               du->dk_dd.d_ncylinders, du->dk_dd.d_ntracks,
               du->dk_dd.d_nsectors);
 #endif
-       if (du->dk_dd.d_ntracks > 16) {
-               printf("wd%d: cannot handle %lu heads (max 16)\n",
+       if (du->dk_dd.d_ntracks == 0 || du->dk_dd.d_ntracks > 16) {
+               struct wdparams *wp;
+
+               printf("wd%d: can't handle %lu heads from partition table ",
                       du->dk_lunit, du->dk_dd.d_ntracks);
                       du->dk_lunit, du->dk_dd.d_ntracks);
-               return (1);
+               /* obtain parameters */
+               wp = &du->dk_params;
+               if (wp->wdp_heads > 0 && wp->wdp_heads <= 16) {
+                       printf("(controller value %lu restored)\n",
+                               wp->wdp_heads);
+                       du->dk_dd.d_ntracks = wp->wdp_heads;
+               }
+               else {
+                       printf("(truncating to 16)\n");
+               du->dk_dd.d_ntracks = 16;
+       }
        }
        if (wdcommand(du, du->dk_dd.d_ncylinders, du->dk_dd.d_ntracks - 1, 0,
                      du->dk_dd.d_nsectors, WDCC_IDC) != 0
        }
        if (wdcommand(du, du->dk_dd.d_ncylinders, du->dk_dd.d_ntracks - 1, 0,
                      du->dk_dd.d_nsectors, WDCC_IDC) != 0
-           || wdwait(du, WDCS_READY) != 0) {
+           || wdwait(du, WDCS_READY, TIMEOUT) < 0) {
                wderror((struct buf *)NULL, du, "wdsetctlr failed");
                return (1);
        }
                wderror((struct buf *)NULL, du, "wdsetctlr failed");
                return (1);
        }
@@ -1066,7 +1068,7 @@ wdgetctlr(struct disk *du)
        struct wdparams *wp;
 
        if (wdcommand(du, 0, 0, 0, 0, WDCC_READP) != 0
        struct wdparams *wp;
 
        if (wdcommand(du, 0, 0, 0, 0, WDCC_READP) != 0
-           || wdwait(du, WDCS_READY | WDCS_SEEKCMPLT | WDCS_DRQ) < 0) {
+           || wdwait(du, WDCS_READY | WDCS_SEEKCMPLT | WDCS_DRQ, TIMEOUT) != 0) {
                /* XXX need to check error status after final transfer. */
                /*
                 * Old drives don't support WDCC_READP.  Try a seek to 0.
                /* XXX need to check error status after final transfer. */
                /*
                 * Old drives don't support WDCC_READP.  Try a seek to 0.
@@ -1074,14 +1076,14 @@ wdgetctlr(struct disk *du)
                 * attached, so first test that the drive can be selected.
                 * This also avoids long waits for nonexistent drives.
                 */
                 * attached, so first test that the drive can be selected.
                 * This also avoids long waits for nonexistent drives.
                 */
-               if (wdwait(du, 0) < 0)
+               if (wdwait(du, 0, TIMEOUT) < 0)
                        return (1);
                outb(du->dk_port + wd_sdh, WDSD_IBM | (du->dk_unit << 4));
                DELAY(5000);    /* usually unnecessary; drive select is fast */
                if ((inb(du->dk_port + wd_status) & (WDCS_BUSY | WDCS_READY))
                    != WDCS_READY
                    || wdcommand(du, 0, 0, 0, 0, WDCC_RESTORE | WD_STEP) != 0
                        return (1);
                outb(du->dk_port + wd_sdh, WDSD_IBM | (du->dk_unit << 4));
                DELAY(5000);    /* usually unnecessary; drive select is fast */
                if ((inb(du->dk_port + wd_status) & (WDCS_BUSY | WDCS_READY))
                    != WDCS_READY
                    || wdcommand(du, 0, 0, 0, 0, WDCC_RESTORE | WD_STEP) != 0
-                   || wdwait(du, WDCS_READY | WDCS_SEEKCMPLT) != 0)
+                   || wdwait(du, WDCS_READY | WDCS_SEEKCMPLT, TIMEOUT) != 0)
                        return (1);
 
                /*
                        return (1);
 
                /*
@@ -1129,6 +1131,19 @@ wdgetctlr(struct disk *du)
                p = (u_short *) (wp->wdp_model + i);
                *p = ntohs(*p);
        }
                p = (u_short *) (wp->wdp_model + i);
                *p = ntohs(*p);
        }
+       /*
+        * Clean up the wdp_model by converting nulls to spaces, and
+        * then removing the trailing spaces.
+        */
+       for (i=0; i < sizeof(wp->wdp_model); i++) {
+               if (wp->wdp_model[i] == '\0') {
+                       wp->wdp_model[i] = ' ';
+               }
+       }
+       for (i=sizeof(wp->wdp_model)-1; i>=0 && wp->wdp_model[i]==' '; i--) {
+               wp->wdp_model[i] = '\0';
+       }
+
 #ifdef WDDEBUG
        printf(
 "\nwd(%d,%d): wdgetctlr: gc %x cyl %d trk %d sec %d type %d sz %d model %s\n",
 #ifdef WDDEBUG
        printf(
 "\nwd(%d,%d): wdgetctlr: gc %x cyl %d trk %d sec %d type %d sz %d model %s\n",
@@ -1270,8 +1285,8 @@ wdioctl(dev_t dev, int cmd, caddr_t addr, int flag)
                        du->dk_openpart |= (1 << 0);    /* XXX */
                        wlab = du->dk_wlabel;
                        du->dk_wlabel = 1;
                        du->dk_openpart |= (1 << 0);    /* XXX */
                        wlab = du->dk_wlabel;
                        du->dk_wlabel = 1;
-                       error = writedisklabel(dev, WDSTRATEGY, &du->dk_dd,
-                                              du->dk_dospartitions);
+                       error = writedisklabel(dev, (d_strategy_t *) WDSTRATEGY,
+                                       &du->dk_dd, du->dk_dospartitions);
                        du->dk_openpart = du->dk_copenpart | du->dk_bopenpart;
                        du->dk_wlabel = wlab;
                }
                        du->dk_openpart = du->dk_copenpart | du->dk_bopenpart;
                        du->dk_wlabel = wlab;
                }
@@ -1405,7 +1420,7 @@ wddump(dev_t dev)
        /* Recalibrate the drive. */
        DELAY(5);               /* ATA spec XXX NOT */
        if (wdcommand(du, 0, 0, 0, 0, WDCC_RESTORE | WD_STEP) != 0
        /* Recalibrate the drive. */
        DELAY(5);               /* ATA spec XXX NOT */
        if (wdcommand(du, 0, 0, 0, 0, WDCC_RESTORE | WD_STEP) != 0
-           || wdwait(du, WDCS_READY | WDCS_SEEKCMPLT) != 0
+           || wdwait(du, WDCS_READY | WDCS_SEEKCMPLT, TIMEOUT) != 0
            || wdsetctlr(du) != 0) {
                wderror((struct buf *)NULL, du, "wddump: recalibrate failed");
                return (EIO);
            || wdsetctlr(du) != 0) {
                wderror((struct buf *)NULL, du, "wddump: recalibrate failed");
                return (EIO);
@@ -1508,7 +1523,7 @@ out:
 
                        /* Ready to send data? */
                        DELAY(5);       /* ATA spec */
 
                        /* Ready to send data? */
                        DELAY(5);       /* ATA spec */
-                       if (wdwait(du, WDCS_READY | WDCS_SEEKCMPLT | WDCS_DRQ)
+                       if (wdwait(du, WDCS_READY | WDCS_SEEKCMPLT | WDCS_DRQ, TIMEOUT)
                            < 0) {
                                wderror((struct buf *)NULL, du,
                                        "wddump: timeout waiting for DRQ");
                            < 0) {
                                wderror((struct buf *)NULL, du,
                                        "wddump: timeout waiting for DRQ");
@@ -1526,7 +1541,7 @@ out:
 
                /* Wait for completion. */
                DELAY(5);       /* ATA spec XXX NOT */
 
                /* Wait for completion. */
                DELAY(5);       /* ATA spec XXX NOT */
-               if (wdwait(du, WDCS_READY | WDCS_SEEKCMPLT) < 0) {
+               if (wdwait(du, WDCS_READY | WDCS_SEEKCMPLT, TIMEOUT) < 0) {
                        wderror((struct buf *)NULL, du,
                                "wddump: timeout waiting for status");
                        return (EIO);
                        wderror((struct buf *)NULL, du,
                                "wddump: timeout waiting for status");
                        return (EIO);
@@ -1555,10 +1570,10 @@ static void
 wderror(struct buf *bp, struct disk *du, char *mesg)
 {
        if (bp == NULL)
 wderror(struct buf *bp, struct disk *du, char *mesg)
 {
        if (bp == NULL)
-               printf("wd%d: %s:", du->dk_lunit, mesg);
+               printf("wd%d: %s:\n", du->dk_lunit, mesg);
        else
                diskerr(bp, "wd", mesg, LOG_PRINTF, du->dk_skip, &du->dk_dd);
        else
                diskerr(bp, "wd", mesg, LOG_PRINTF, du->dk_skip, &du->dk_dd);
-       printf(" status %b error %b\n",
+       printf("wd%d: status %b error %b\n", du->dk_lunit,
               du->dk_status, WDCS_BITS, du->dk_error, WDERR_BITS);
 }
 
               du->dk_status, WDCS_BITS, du->dk_error, WDERR_BITS);
 }
 
@@ -1584,11 +1599,11 @@ wdreset(struct disk *du)
        int     wdc;
 
        wdc = du->dk_port;
        int     wdc;
 
        wdc = du->dk_port;
-       (void)wdwait(du, 0);
+       (void)wdwait(du, 0, TIMEOUT);
        outb(wdc + wd_ctlr, WDCTL_IDS | WDCTL_RST);
        DELAY(10 * 1000);
        outb(wdc + wd_ctlr, WDCTL_IDS);
        outb(wdc + wd_ctlr, WDCTL_IDS | WDCTL_RST);
        DELAY(10 * 1000);
        outb(wdc + wd_ctlr, WDCTL_IDS);
-       if (wdwait(du, WDCS_READY | WDCS_SEEKCMPLT) != 0
+       if (wdwait(du, WDCS_READY | WDCS_SEEKCMPLT, TIMEOUT) != 0
            || (du->dk_error = inb(wdc + wd_error)) != 0x01)
                return (1);
        outb(wdc + wd_ctlr, WDCTL_4BIT);
            || (du->dk_error = inb(wdc + wd_error)) != 0x01)
                return (1);
        outb(wdc + wd_ctlr, WDCTL_4BIT);
@@ -1607,8 +1622,7 @@ wdsleep(int ctrlr, char *wmesg)
                tsleep((caddr_t)&wdtab[ctrlr].b_active, PZERO - 1, wmesg, 1);
 }
 
                tsleep((caddr_t)&wdtab[ctrlr].b_active, PZERO - 1, wmesg, 1);
 }
 
-/* XXX void */
-static int
+static void
 wdtimeout(caddr_t cdu, int ticks)
 {
        struct disk *du;
 wdtimeout(caddr_t cdu, int ticks)
 {
        struct disk *du;
@@ -1626,7 +1640,6 @@ wdtimeout(caddr_t cdu, int ticks)
        }
        timeout(wdtimeout, cdu, hz);
        splx(x);
        }
        timeout(wdtimeout, cdu, hz);
        splx(x);
-       return (0);
 }
 
 /*
 }
 
 /*
@@ -1654,7 +1667,7 @@ wdunwedge(struct disk *du)
                 * aren't prepared to have its state change.
                 */
                if (wdcommand(du, 0, 0, 0, 0, WDCC_RESTORE | WD_STEP) == 0
                 * aren't prepared to have its state change.
                 */
                if (wdcommand(du, 0, 0, 0, 0, WDCC_RESTORE | WD_STEP) == 0
-                   && wdwait(du, WDCS_READY | WDCS_SEEKCMPLT) == 0
+                   && wdwait(du, WDCS_READY | WDCS_SEEKCMPLT, TIMEOUT) == 0
                    && wdsetctlr(du) == 0)
                        return (0);
        }
                    && wdsetctlr(du) == 0)
                        return (0);
        }
@@ -1677,22 +1690,20 @@ static int min_retries[NWDC];
 #endif
 
 static int
 #endif
 
 static int
-wdwait(struct disk *du, u_char bits_wanted)
+wdwait(struct disk *du, u_char bits_wanted, int timeout)
 {
 {
-       int     retries;
        int     wdc;
        u_char  status;
 
 #define        POLLING         1000
        int     wdc;
        u_char  status;
 
 #define        POLLING         1000
-#define        TIMEOUT         2000    /* WDCC_DIAGNOSE can take > 300 msec */
 
        wdc = du->dk_port;
 
        wdc = du->dk_port;
-       retries = POLLING + TIMEOUT;
+       timeout += POLLING;
        do {
 #ifdef WD_COUNT_RETRIES
        do {
 #ifdef WD_COUNT_RETRIES
-               if (min_retries[du->dk_ctrlr] > retries
+               if (min_retries[du->dk_ctrlr] > timeout
                    || min_retries[du->dk_ctrlr] == 0)
                    || min_retries[du->dk_ctrlr] == 0)
-                       min_retries[du->dk_ctrlr] = retries;
+                       min_retries[du->dk_ctrlr] = timeout;
 #endif
                DELAY(5);       /* ATA spec XXX NOT */
                du->dk_status = status = inb(wdc + wd_status);
 #endif
                DELAY(5);       /* ATA spec XXX NOT */
                du->dk_status = status = inb(wdc + wd_status);
@@ -1712,7 +1723,7 @@ wdwait(struct disk *du, u_char bits_wanted)
                        if ((status & bits_wanted) == bits_wanted)
                                return (status & WDCS_ERR);
                }
                        if ((status & bits_wanted) == bits_wanted)
                                return (status & WDCS_ERR);
                }
-               if (retries < TIMEOUT)
+               if (timeout < TIMEOUT)
                        /*
                         * Switch to a polling rate of about 1 KHz so that
                         * the timeout is almost machine-independent.  The
                        /*
                         * Switch to a polling rate of about 1 KHz so that
                         * the timeout is almost machine-independent.  The
@@ -1720,7 +1731,7 @@ wdwait(struct disk *du, u_char bits_wanted)
                         * an extra msec won't matter.
                         */
                        DELAY(1000);
                         * an extra msec won't matter.
                         */
                        DELAY(1000);
-       } while (--retries != 0);
+       } while (--timeout != 0);
        return (-1);
 }
 
        return (-1);
 }