diff options
| author | mycroft <mycroft@NetBSD.org> | 1994-03-07 05:54:44 +0000 |
|---|---|---|
| committer | mycroft <mycroft@NetBSD.org> | 1994-03-07 05:54:44 +0000 |
| commit | 5a17003403d3d1d2ac43dd7e258f8af8bd8b7658 (patch) | |
| tree | 2ef8939b73d66646d5bc662e88aa85b0d48c5d3d /sys/dev | |
| parent | 1675d4304303cc9ffbfa1bd129eb574628e43b3e (diff) | |
Some changes inspired by Bruce Evans's driver:
Consolidate error reporting in one function. Actually use the dk_status and
dk_error fields, and pass around only the error bit to avoid lots of unneeded
assignments and tests. No functional differences.
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/ata/wd.c | 192 | ||||
| -rw-r--r-- | sys/dev/isa/wd.c | 192 |
2 files changed, 182 insertions, 202 deletions
diff --git a/sys/dev/ata/wd.c b/sys/dev/ata/wd.c index 303290c0991..50068924530 100644 --- a/sys/dev/ata/wd.c +++ b/sys/dev/ata/wd.c @@ -35,7 +35,7 @@ * SUCH DAMAGE. * * from: @(#)wd.c 7.2 (Berkeley) 5/9/91 - * $Id: wd.c,v 1.62 1994/03/07 03:18:35 mycroft Exp $ + * $Id: wd.c,v 1.63 1994/03/07 05:54:44 mycroft Exp $ */ #define INSTRUMENT /* instrumentation stuff by Brad Parker */ @@ -156,11 +156,12 @@ static int wdgetctlr __P((struct disk *)); static void bad144intern __P((struct disk *)); static int wdreset __P((struct disk *, int)); static void wdtimeout __P((caddr_t)); -void wddisksort __P((struct buf *dp, struct buf *bp)); -int wdc_wait __P((struct disk *, int)); -#define wait_for_drq(d) wdc_wait(d, WDCS_DRQ) -#define wait_for_ready(d) wdc_wait(d, WDCS_READY | WDCS_SEEKCMPLT) -#define wait_for_unbusy(d) wdc_wait(d, 0) +void wddisksort __P((struct buf *, struct buf *)); +static void wderror __P((struct disk *, struct buf *, char *)); +int wdwait __P((struct disk *, int)); +#define wait_for_drq(d) wdwait(d, WDCS_DRQ) +#define wait_for_ready(d) wdwait(d, WDCS_READY | WDCS_SEEKCMPLT) +#define wait_for_unbusy(d) wdwait(d, 0) /* * Probe for controller. @@ -194,7 +195,7 @@ wdprobe(isa_dev) wdreset(du, 0); /* execute a controller only command */ - if (wdcommand(du, 0, 0, 0, 0, WDCC_DIAGNOSE) < 0) + if (wdcommand(du, 0, 0, 0, 0, WDCC_DIAGNOSE) != 0) goto nodevice; free(du, M_TEMP); @@ -405,7 +406,6 @@ wdstart(ctrlr) long secpertrk, secpercyl; int xfrblknum; int lunit; - u_short wdc; loop: /* is there a drive for the controller to do a transfer with? */ @@ -520,7 +520,6 @@ loop: sector++; /* sectors begin with 1, not 0 */ wdtab[ctrlr].b_active = 1; /* mark controller active */ - wdc = du->dk_port; #ifdef INSTRUMENT /* instrumentation */ @@ -566,13 +565,14 @@ retry: #endif /* initiate command! */ - if (wdcommand(du, cylin, head, sector, count, command) < 0) { + while (wdcommand(du, cylin, head, sector, count, command) < 0) { + wderror(du, NULL, + "wdstart: timeout waiting for unbusy"); wdreset(du, 1); - goto retry; } #ifdef WDDEBUG printf("sector %d cylin %d head %d addr %x sts %x\n", sector, - cylin, head, bp->b_un.b_addr, inb(wdc+wd_altsts)); + cylin, head, bp->b_un.b_addr, inb(du->dk_port+wd_altsts)); #endif } @@ -583,12 +583,13 @@ retry: return; if (wait_for_drq(du) < 0) { + /* XXX seems wrong */ wdreset(du, 1); goto retry; } /* then send it! */ - outsw(wdc+wd_data, bp->b_un.b_addr + du->dk_skip * DEV_BSIZE, + outsw(du->dk_port+wd_data, bp->b_un.b_addr + du->dk_skip * DEV_BSIZE, DEV_BSIZE / sizeof(short)); du->dk_bc -= DEV_BSIZE; @@ -606,8 +607,6 @@ wdintr(ctrlr) { register struct disk *du; register struct buf *bp, *dp; - int stat; - u_short wdc; /* clear the pending interrupt */ (void) inb(wdcontroller[ctrlr].dkc_port+wd_status); @@ -620,17 +619,15 @@ wdintr(ctrlr) dp = wdtab[ctrlr].b_forw; bp = dp->b_actf; du = wddrives[WDUNIT(bp->b_dev)]; - wdc = du->dk_port; du->dk_timeout = 0; #ifdef WDDEBUG printf("I%d ", ctrlr); #endif - stat = wait_for_unbusy(du); - if (stat < 0) { - printf("wdc%d: timeout waiting for unbusy\n", ctrlr); - stat |= WDCS_ERR; /* XXX */ + if (wait_for_unbusy(du) < 0) { + wderror(du, NULL, "wdintr: timeout waiting for unbusy"); + du->dk_status |= WDCS_ERR; /* XXX */ } /* is it not a transfer, but a control operation? */ @@ -647,12 +644,10 @@ wdintr(ctrlr) } /* have we an error? */ - if (stat & (WDCS_ERR | WDCS_ECCCOR)) { + if (du->dk_status & (WDCS_ERR | WDCS_ECCCOR)) { lose: - du->dk_status = stat; - du->dk_error = inb(wdc+wd_error); #ifdef WDDEBUG - printf("stat %x error %x\n", stat, du->dk_error); + wderror(du, NULL, "wdintr"); #endif if ((du->dk_flags & DKFL_SINGLE) == 0) { du->dk_flags |= DKFL_ERROR; @@ -667,23 +662,16 @@ wdintr(ctrlr) #endif /* error or error correction? */ - if (stat & WDCS_ERR) { + if (du->dk_status & WDCS_ERR) { if (++wdtab[ctrlr].b_errcnt < WDIORETRIES) wdtab[ctrlr].b_active = 0; else { - diskerr(bp, "wd", "hard error", LOG_PRINTF, - du->dk_skip, &du->dk_dd); -#ifdef WDDEBUG - printf("wd%d: stat %b error %b\n", du->dk_lunit, - stat, WDCS_BITS, inb(wdc+wd_error), - WDERR_BITS); -#endif + wderror(du, bp, "hard error"); bp->b_error = EIO; bp->b_flags |= B_ERROR; /* flag the error */ } } else - diskerr(bp, "wd", "soft error", 0, du->dk_skip, - &du->dk_dd); + wderror(du, bp, "soft ecc"); } /* @@ -696,20 +684,20 @@ wdintr(ctrlr) chk = min(DEV_BSIZE / sizeof(short), du->dk_bc / sizeof(short)); /* ready to receive data? */ - if (wait_for_drq(du) < 0) { - printf("wdc%d: timeout waiting for drq\n", ctrlr); + if (wait_for_drq(du) != 0) { + wderror(du, NULL, "wdintr: read error detected late"); goto lose; } /* suck in data */ - insw(wdc+wd_data, + insw(du->dk_port+wd_data, bp->b_un.b_addr + du->dk_skip * DEV_BSIZE, chk); du->dk_bc -= chk * sizeof(short); du->dk_bct -= chk * sizeof(short); /* for obselete fractional sector reads */ while (chk++ < (DEV_BSIZE / sizeof(short))) - (void) inw(wdc+wd_data); + (void) inw(du->dk_port+wd_data); } wdxfer[du->dk_lunit]++; @@ -723,8 +711,7 @@ outt: du->dk_skip++; /* Add to succ. sect */ du->dk_skipm++; /* Add to succ. sect for multitransfer */ if (wdtab[ctrlr].b_errcnt) - diskerr(bp, "wd", "soft error", 0, du->dk_skip, - &du->dk_dd); + wderror(du, bp, "soft error"); wdtab[ctrlr].b_errcnt = 0; /* see if more to transfer */ @@ -891,35 +878,29 @@ wdcontrol(bp) struct buf *bp; { struct disk *du; - int stat; - int s, ctrlr; - u_short wdc; + int ctrlr; du = wddrives[WDUNIT(bp->b_dev)]; ctrlr = du->dk_ctrlr; - wdc = du->dk_port; switch (du->dk_state) { case WANTOPEN: /* set SDH, step rate, do restore */ tryagainrecal: - s = splbio(); /* not called from intr level ... */ wdgetctlr(du); /* XXX Is this necessary? */ wdtab[ctrlr].b_active = 1; - if (wdcommand(du, 0, 0, 0, 0, WDCC_RESTORE | WD_STEP) < 0) { - wdreset(du, 1); - splx(s); - goto tryagainrecal; + if (wdcommand(du, 0, 0, 0, 0, WDCC_RESTORE | WD_STEP) != 0) { + wderror(du, 0, "wdcontrol: wdcommand failed"); + goto lose; } du->dk_state = RECAL; - splx(s); return 0; case RECAL: - stat = inb(wdc+wd_altsts); - if (stat & WDCS_ERR || wdsetctlr(du) < 0) { - printf("wd%d: recal failed: stat %b error %b\n", - du->dk_lunit, stat, WDCS_BITS, inb(wdc+wd_error), - WDERR_BITS); + if (du->dk_status & WDCS_ERR || wdsetctlr(du) != 0) { + wderror(du, NULL, "wdcontrol: recal failed"); + lose: + if (du->dk_status & WDCS_ERR) + wdreset(du, 1); du->dk_state = WANTOPEN; if (++wdtab[ctrlr].b_errcnt < WDIORETRIES) goto tryagainrecal; @@ -930,8 +911,7 @@ wdcontrol(bp) wdtab[ctrlr].b_errcnt = 0; du->dk_state = OPEN; /* - * The rest of the initialization can be done - * by normal means. + * The rest of the initialization can be done by normal means. */ return 1; } @@ -966,7 +946,7 @@ wdcommand(du, cylin, head, sector, count, cmd) if (cmd == WDCC_DIAGNOSE || cmd == WDCC_IDC) stat = wait_for_unbusy(du); else - stat = wdc_wait(du, WDCS_READY); + stat = wdwait(du, WDCS_READY); if (stat < 0) return -1; @@ -992,7 +972,7 @@ wdcommand(du, cylin, head, sector, count, cmd) case WDCC_WRITE: return 0; case WDCC_IDC: - return wdc_wait(du, WDCS_READY); + return wdwait(du, WDCS_READY); case WDCC_READP: return wait_for_drq(du); } @@ -1005,22 +985,17 @@ static int wdsetctlr(du) struct disk *du; { - int stat, s; - + #ifdef WDDEBUG printf("wd(%d,%d) C%dH%dS%d\n", du->dk_ctrlr, du->dk_unit, du->dk_dd.d_ncylinders, du->dk_dd.d_ntracks, du->dk_dd.d_nsectors); #endif - s = splbio(); - stat = wdcommand(du, du->dk_dd.d_ncylinders, du->dk_dd.d_ntracks - 1, 0, - du->dk_dd.d_nsectors, WDCC_IDC); - if (stat < 0 || stat & WDCS_ERR) { - printf("wd%d: wdsetctlr: stat %b error %b\n", du->dk_lunit, - stat, WDCS_BITS, inb(du->dk_port+wd_error), WDERR_BITS); + if (wdcommand(du, du->dk_dd.d_ncylinders, du->dk_dd.d_ntracks - 1, 0, + du->dk_dd.d_nsectors, WDCC_IDC) != 0) { + wderror(du, NULL, "wdsetctlr: failed"); return -1; } - splx(s); return 0; } @@ -1031,24 +1006,18 @@ static int wdgetctlr(du) struct disk *du; { - int stat, s, i; + int i; char tb[DEV_BSIZE]; struct wdparams *wp; - s = splbio(); /* not called from intr level ... */ - - stat = wdcommand(du, 0, 0, 0, 0, WDCC_READP); - if (stat < 0 || stat & WDCS_ERR) { + if (wdcommand(du, 0, 0, 0, 0, WDCC_READP) != 0) { /* * If WDCC_READP fails then we might have an old drive * so we try a seek to 0; if that passes then the * drive is there but it's OLD AND KRUSTY. */ - stat = wdcommand(du, 0, 0, 0, 0, WDCC_RESTORE | WD_STEP); - if (stat < 0 || stat & WDCS_ERR) { - splx(s); + if (wdcommand(du, 0, 0, 0, 0, WDCC_RESTORE | WD_STEP) != 0) return -1; - } strncpy(du->dk_dd.d_typename, "ST506", sizeof du->dk_dd.d_typename); @@ -1096,7 +1065,7 @@ wdgetctlr(du) /* XXX sometimes possibly needed */ (void) inb(du->dk_port+wd_status); - splx(s); + return 0; } @@ -1283,9 +1252,8 @@ wddump(dev) register struct disk *du; /* disk unit to do the IO */ long num; /* number of sectors to write */ int ctrlr, lunit, part; - u_short wdc; long blkoff, blknum; - long cylin, head, sector, stat; + long cylin, head, sector; long secpertrk, secpercyl, nblocks; char *addr; static wddoingadump = 0; @@ -1311,7 +1279,6 @@ wddump(dev) if (du == 0 || du->dk_state < OPEN || du->dk_flags & DKFL_WRITEPROT) return ENXIO; - wdc = du->dk_port; ctrlr = du->dk_ctrlr; /* Convert to disk sectors */ @@ -1340,9 +1307,11 @@ wddump(dev) wddoingadump = 1; /* Recalibrate. */ - if (wdcommand(du, 0, 0, 0, 0, WDCC_RESTORE | WD_STEP) < 0 || - wdsetctlr(du) < 0) + if (wdcommand(du, 0, 0, 0, 0, WDCC_RESTORE | WD_STEP) != 0 || + wdsetctlr(du) != 0) { + wderror(du, NULL, "wddump: recal failed"); return EIO; + } blknum = dumplo + blkoff; while (num > 0) { @@ -1377,9 +1346,14 @@ wddump(dev) printf("cylin %d, head %d, sector %d, addr 0x%x", cylin, head, sector, addr); #endif - stat = wdcommand(du, cylin, head, sector, 1, WDCC_WRITE); - if (stat < 0 || stat & WDCS_ERR || wait_for_drq(du) < 0) + if (wdcommand(du, cylin, head, sector, 1, WDCC_WRITE) != 0) { + wderror(du, NULL, "wddump: wdcommand failed"); + return EIO; + } + if (wait_for_drq(du) != 0) { + wderror(du, NULL, "wddump: timeout waiting for drq"); return EIO; + } #ifdef notdef /* cannot use this since this address was mapped differently */ pmap_enter(kernel_pmap, CADDR1, trunc_page(addr), VM_PROT_READ, TRUE); @@ -1388,13 +1362,18 @@ wddump(dev) tlbflush(); #endif - outsw(wdc+wd_data, CADDR1 + ((int)addr & PGOFSET), + outsw(du->dk_port+wd_data, CADDR1 + ((int)addr & PGOFSET), DEV_BSIZE / sizeof(short)); /* Check data request (should be done). */ - stat = wait_for_ready(du); - if (stat < 0 || stat & (WDCS_ERR | WDCS_DRQ)) + if (wait_for_ready(du) != 0) { + wderror(du, NULL, "wddump: timeout waiting for ready"); + return EIO; + } + if (du->dk_status & WDCS_DRQ) { + wderror(du, NULL, "wddump: extra drq"); return EIO; + } if ((unsigned)addr % 1048576 == 0) printf("%d ", num / (1048576 / DEV_BSIZE)); @@ -1443,8 +1422,7 @@ wdreset(du, err) struct disk *du; int err; { - int wdc = du->dk_port; - int stat; + u_short wdc = du->dk_port; if (err) printf("wdc%d: busy too long, resetting\n", du->dk_ctrlr); @@ -1462,28 +1440,30 @@ wdreset(du, err) } int -wdc_wait(du, mask) +wdwait(du, mask) struct disk *du; int mask; { - int wdc = du->dk_port; + u_short wdc = du->dk_port; int timeout = 0; - int stat; + u_char status; for (;;) { - stat = inb(wdc+wd_altsts); - if ((stat & WDCS_BUSY) == 0 && (stat & mask) == mask) + du->dk_status = status = inb(wdc+wd_altsts); + if ((status & WDCS_BUSY) == 0 && (status & mask) == mask) break; if (++timeout > WDCNDELAY) return -1; delay(WDCDELAY); } + if (status & WDCS_ERR) + du->dk_error = inb(wdc+wd_error); #ifdef WDCNDELAY_DEBUG if (timeout > WDCNDELAY_DEBUG) - printf("wdc%d: timeout took %dus\n", du->dk_ctrlr, + printf("wdc%d: busy-wait took %dus\n", du->dk_ctrlr, WDCDELAY * timeout); #endif - return stat; + return status & WDCS_ERR; } static void @@ -1494,10 +1474,7 @@ wdtimeout(arg) struct disk *du = (void *)arg; if (du->dk_timeout && --du->dk_timeout == 0) { - int wdc = du->dk_port; - - printf("wd%d: lost interrupt: stat %x error %x\n", - du->dk_lunit, inb(wdc+wd_status), inb(wdc+wd_error)); + wderror(du, NULL, "lost interrupt"); wdreset(du, 0); /* XXX Need to recalibrate and upload geometry. */ du->dk_skip = 0; @@ -1508,4 +1485,17 @@ wdtimeout(arg) splx(s); } +static void +wderror(du, bp, msg) + struct disk *du; + struct buf *bp; + char *msg; +{ + if (bp) + diskerr(bp, "wd", msg, LOG_PRINTF, du->dk_skip, &du->dk_dd); + else + printf("wd%d: %s: status %b error %b\n", du->dk_lunit, msg, + du->dk_status, WDCS_BITS, du->dk_error, WDERR_BITS); +} + #endif /* NWDC > 0 */ diff --git a/sys/dev/isa/wd.c b/sys/dev/isa/wd.c index 303290c0991..50068924530 100644 --- a/sys/dev/isa/wd.c +++ b/sys/dev/isa/wd.c @@ -35,7 +35,7 @@ * SUCH DAMAGE. * * from: @(#)wd.c 7.2 (Berkeley) 5/9/91 - * $Id: wd.c,v 1.62 1994/03/07 03:18:35 mycroft Exp $ + * $Id: wd.c,v 1.63 1994/03/07 05:54:44 mycroft Exp $ */ #define INSTRUMENT /* instrumentation stuff by Brad Parker */ @@ -156,11 +156,12 @@ static int wdgetctlr __P((struct disk *)); static void bad144intern __P((struct disk *)); static int wdreset __P((struct disk *, int)); static void wdtimeout __P((caddr_t)); -void wddisksort __P((struct buf *dp, struct buf *bp)); -int wdc_wait __P((struct disk *, int)); -#define wait_for_drq(d) wdc_wait(d, WDCS_DRQ) -#define wait_for_ready(d) wdc_wait(d, WDCS_READY | WDCS_SEEKCMPLT) -#define wait_for_unbusy(d) wdc_wait(d, 0) +void wddisksort __P((struct buf *, struct buf *)); +static void wderror __P((struct disk *, struct buf *, char *)); +int wdwait __P((struct disk *, int)); +#define wait_for_drq(d) wdwait(d, WDCS_DRQ) +#define wait_for_ready(d) wdwait(d, WDCS_READY | WDCS_SEEKCMPLT) +#define wait_for_unbusy(d) wdwait(d, 0) /* * Probe for controller. @@ -194,7 +195,7 @@ wdprobe(isa_dev) wdreset(du, 0); /* execute a controller only command */ - if (wdcommand(du, 0, 0, 0, 0, WDCC_DIAGNOSE) < 0) + if (wdcommand(du, 0, 0, 0, 0, WDCC_DIAGNOSE) != 0) goto nodevice; free(du, M_TEMP); @@ -405,7 +406,6 @@ wdstart(ctrlr) long secpertrk, secpercyl; int xfrblknum; int lunit; - u_short wdc; loop: /* is there a drive for the controller to do a transfer with? */ @@ -520,7 +520,6 @@ loop: sector++; /* sectors begin with 1, not 0 */ wdtab[ctrlr].b_active = 1; /* mark controller active */ - wdc = du->dk_port; #ifdef INSTRUMENT /* instrumentation */ @@ -566,13 +565,14 @@ retry: #endif /* initiate command! */ - if (wdcommand(du, cylin, head, sector, count, command) < 0) { + while (wdcommand(du, cylin, head, sector, count, command) < 0) { + wderror(du, NULL, + "wdstart: timeout waiting for unbusy"); wdreset(du, 1); - goto retry; } #ifdef WDDEBUG printf("sector %d cylin %d head %d addr %x sts %x\n", sector, - cylin, head, bp->b_un.b_addr, inb(wdc+wd_altsts)); + cylin, head, bp->b_un.b_addr, inb(du->dk_port+wd_altsts)); #endif } @@ -583,12 +583,13 @@ retry: return; if (wait_for_drq(du) < 0) { + /* XXX seems wrong */ wdreset(du, 1); goto retry; } /* then send it! */ - outsw(wdc+wd_data, bp->b_un.b_addr + du->dk_skip * DEV_BSIZE, + outsw(du->dk_port+wd_data, bp->b_un.b_addr + du->dk_skip * DEV_BSIZE, DEV_BSIZE / sizeof(short)); du->dk_bc -= DEV_BSIZE; @@ -606,8 +607,6 @@ wdintr(ctrlr) { register struct disk *du; register struct buf *bp, *dp; - int stat; - u_short wdc; /* clear the pending interrupt */ (void) inb(wdcontroller[ctrlr].dkc_port+wd_status); @@ -620,17 +619,15 @@ wdintr(ctrlr) dp = wdtab[ctrlr].b_forw; bp = dp->b_actf; du = wddrives[WDUNIT(bp->b_dev)]; - wdc = du->dk_port; du->dk_timeout = 0; #ifdef WDDEBUG printf("I%d ", ctrlr); #endif - stat = wait_for_unbusy(du); - if (stat < 0) { - printf("wdc%d: timeout waiting for unbusy\n", ctrlr); - stat |= WDCS_ERR; /* XXX */ + if (wait_for_unbusy(du) < 0) { + wderror(du, NULL, "wdintr: timeout waiting for unbusy"); + du->dk_status |= WDCS_ERR; /* XXX */ } /* is it not a transfer, but a control operation? */ @@ -647,12 +644,10 @@ wdintr(ctrlr) } /* have we an error? */ - if (stat & (WDCS_ERR | WDCS_ECCCOR)) { + if (du->dk_status & (WDCS_ERR | WDCS_ECCCOR)) { lose: - du->dk_status = stat; - du->dk_error = inb(wdc+wd_error); #ifdef WDDEBUG - printf("stat %x error %x\n", stat, du->dk_error); + wderror(du, NULL, "wdintr"); #endif if ((du->dk_flags & DKFL_SINGLE) == 0) { du->dk_flags |= DKFL_ERROR; @@ -667,23 +662,16 @@ wdintr(ctrlr) #endif /* error or error correction? */ - if (stat & WDCS_ERR) { + if (du->dk_status & WDCS_ERR) { if (++wdtab[ctrlr].b_errcnt < WDIORETRIES) wdtab[ctrlr].b_active = 0; else { - diskerr(bp, "wd", "hard error", LOG_PRINTF, - du->dk_skip, &du->dk_dd); -#ifdef WDDEBUG - printf("wd%d: stat %b error %b\n", du->dk_lunit, - stat, WDCS_BITS, inb(wdc+wd_error), - WDERR_BITS); -#endif + wderror(du, bp, "hard error"); bp->b_error = EIO; bp->b_flags |= B_ERROR; /* flag the error */ } } else - diskerr(bp, "wd", "soft error", 0, du->dk_skip, - &du->dk_dd); + wderror(du, bp, "soft ecc"); } /* @@ -696,20 +684,20 @@ wdintr(ctrlr) chk = min(DEV_BSIZE / sizeof(short), du->dk_bc / sizeof(short)); /* ready to receive data? */ - if (wait_for_drq(du) < 0) { - printf("wdc%d: timeout waiting for drq\n", ctrlr); + if (wait_for_drq(du) != 0) { + wderror(du, NULL, "wdintr: read error detected late"); goto lose; } /* suck in data */ - insw(wdc+wd_data, + insw(du->dk_port+wd_data, bp->b_un.b_addr + du->dk_skip * DEV_BSIZE, chk); du->dk_bc -= chk * sizeof(short); du->dk_bct -= chk * sizeof(short); /* for obselete fractional sector reads */ while (chk++ < (DEV_BSIZE / sizeof(short))) - (void) inw(wdc+wd_data); + (void) inw(du->dk_port+wd_data); } wdxfer[du->dk_lunit]++; @@ -723,8 +711,7 @@ outt: du->dk_skip++; /* Add to succ. sect */ du->dk_skipm++; /* Add to succ. sect for multitransfer */ if (wdtab[ctrlr].b_errcnt) - diskerr(bp, "wd", "soft error", 0, du->dk_skip, - &du->dk_dd); + wderror(du, bp, "soft error"); wdtab[ctrlr].b_errcnt = 0; /* see if more to transfer */ @@ -891,35 +878,29 @@ wdcontrol(bp) struct buf *bp; { struct disk *du; - int stat; - int s, ctrlr; - u_short wdc; + int ctrlr; du = wddrives[WDUNIT(bp->b_dev)]; ctrlr = du->dk_ctrlr; - wdc = du->dk_port; switch (du->dk_state) { case WANTOPEN: /* set SDH, step rate, do restore */ tryagainrecal: - s = splbio(); /* not called from intr level ... */ wdgetctlr(du); /* XXX Is this necessary? */ wdtab[ctrlr].b_active = 1; - if (wdcommand(du, 0, 0, 0, 0, WDCC_RESTORE | WD_STEP) < 0) { - wdreset(du, 1); - splx(s); - goto tryagainrecal; + if (wdcommand(du, 0, 0, 0, 0, WDCC_RESTORE | WD_STEP) != 0) { + wderror(du, 0, "wdcontrol: wdcommand failed"); + goto lose; } du->dk_state = RECAL; - splx(s); return 0; case RECAL: - stat = inb(wdc+wd_altsts); - if (stat & WDCS_ERR || wdsetctlr(du) < 0) { - printf("wd%d: recal failed: stat %b error %b\n", - du->dk_lunit, stat, WDCS_BITS, inb(wdc+wd_error), - WDERR_BITS); + if (du->dk_status & WDCS_ERR || wdsetctlr(du) != 0) { + wderror(du, NULL, "wdcontrol: recal failed"); + lose: + if (du->dk_status & WDCS_ERR) + wdreset(du, 1); du->dk_state = WANTOPEN; if (++wdtab[ctrlr].b_errcnt < WDIORETRIES) goto tryagainrecal; @@ -930,8 +911,7 @@ wdcontrol(bp) wdtab[ctrlr].b_errcnt = 0; du->dk_state = OPEN; /* - * The rest of the initialization can be done - * by normal means. + * The rest of the initialization can be done by normal means. */ return 1; } @@ -966,7 +946,7 @@ wdcommand(du, cylin, head, sector, count, cmd) if (cmd == WDCC_DIAGNOSE || cmd == WDCC_IDC) stat = wait_for_unbusy(du); else - stat = wdc_wait(du, WDCS_READY); + stat = wdwait(du, WDCS_READY); if (stat < 0) return -1; @@ -992,7 +972,7 @@ wdcommand(du, cylin, head, sector, count, cmd) case WDCC_WRITE: return 0; case WDCC_IDC: - return wdc_wait(du, WDCS_READY); + return wdwait(du, WDCS_READY); case WDCC_READP: return wait_for_drq(du); } @@ -1005,22 +985,17 @@ static int wdsetctlr(du) struct disk *du; { - int stat, s; - + #ifdef WDDEBUG printf("wd(%d,%d) C%dH%dS%d\n", du->dk_ctrlr, du->dk_unit, du->dk_dd.d_ncylinders, du->dk_dd.d_ntracks, du->dk_dd.d_nsectors); #endif - s = splbio(); - stat = wdcommand(du, du->dk_dd.d_ncylinders, du->dk_dd.d_ntracks - 1, 0, - du->dk_dd.d_nsectors, WDCC_IDC); - if (stat < 0 || stat & WDCS_ERR) { - printf("wd%d: wdsetctlr: stat %b error %b\n", du->dk_lunit, - stat, WDCS_BITS, inb(du->dk_port+wd_error), WDERR_BITS); + if (wdcommand(du, du->dk_dd.d_ncylinders, du->dk_dd.d_ntracks - 1, 0, + du->dk_dd.d_nsectors, WDCC_IDC) != 0) { + wderror(du, NULL, "wdsetctlr: failed"); return -1; } - splx(s); return 0; } @@ -1031,24 +1006,18 @@ static int wdgetctlr(du) struct disk *du; { - int stat, s, i; + int i; char tb[DEV_BSIZE]; struct wdparams *wp; - s = splbio(); /* not called from intr level ... */ - - stat = wdcommand(du, 0, 0, 0, 0, WDCC_READP); - if (stat < 0 || stat & WDCS_ERR) { + if (wdcommand(du, 0, 0, 0, 0, WDCC_READP) != 0) { /* * If WDCC_READP fails then we might have an old drive * so we try a seek to 0; if that passes then the * drive is there but it's OLD AND KRUSTY. */ - stat = wdcommand(du, 0, 0, 0, 0, WDCC_RESTORE | WD_STEP); - if (stat < 0 || stat & WDCS_ERR) { - splx(s); + if (wdcommand(du, 0, 0, 0, 0, WDCC_RESTORE | WD_STEP) != 0) return -1; - } strncpy(du->dk_dd.d_typename, "ST506", sizeof du->dk_dd.d_typename); @@ -1096,7 +1065,7 @@ wdgetctlr(du) /* XXX sometimes possibly needed */ (void) inb(du->dk_port+wd_status); - splx(s); + return 0; } @@ -1283,9 +1252,8 @@ wddump(dev) register struct disk *du; /* disk unit to do the IO */ long num; /* number of sectors to write */ int ctrlr, lunit, part; - u_short wdc; long blkoff, blknum; - long cylin, head, sector, stat; + long cylin, head, sector; long secpertrk, secpercyl, nblocks; char *addr; static wddoingadump = 0; @@ -1311,7 +1279,6 @@ wddump(dev) if (du == 0 || du->dk_state < OPEN || du->dk_flags & DKFL_WRITEPROT) return ENXIO; - wdc = du->dk_port; ctrlr = du->dk_ctrlr; /* Convert to disk sectors */ @@ -1340,9 +1307,11 @@ wddump(dev) wddoingadump = 1; /* Recalibrate. */ - if (wdcommand(du, 0, 0, 0, 0, WDCC_RESTORE | WD_STEP) < 0 || - wdsetctlr(du) < 0) + if (wdcommand(du, 0, 0, 0, 0, WDCC_RESTORE | WD_STEP) != 0 || + wdsetctlr(du) != 0) { + wderror(du, NULL, "wddump: recal failed"); return EIO; + } blknum = dumplo + blkoff; while (num > 0) { @@ -1377,9 +1346,14 @@ wddump(dev) printf("cylin %d, head %d, sector %d, addr 0x%x", cylin, head, sector, addr); #endif - stat = wdcommand(du, cylin, head, sector, 1, WDCC_WRITE); - if (stat < 0 || stat & WDCS_ERR || wait_for_drq(du) < 0) + if (wdcommand(du, cylin, head, sector, 1, WDCC_WRITE) != 0) { + wderror(du, NULL, "wddump: wdcommand failed"); + return EIO; + } + if (wait_for_drq(du) != 0) { + wderror(du, NULL, "wddump: timeout waiting for drq"); return EIO; + } #ifdef notdef /* cannot use this since this address was mapped differently */ pmap_enter(kernel_pmap, CADDR1, trunc_page(addr), VM_PROT_READ, TRUE); @@ -1388,13 +1362,18 @@ wddump(dev) tlbflush(); #endif - outsw(wdc+wd_data, CADDR1 + ((int)addr & PGOFSET), + outsw(du->dk_port+wd_data, CADDR1 + ((int)addr & PGOFSET), DEV_BSIZE / sizeof(short)); /* Check data request (should be done). */ - stat = wait_for_ready(du); - if (stat < 0 || stat & (WDCS_ERR | WDCS_DRQ)) + if (wait_for_ready(du) != 0) { + wderror(du, NULL, "wddump: timeout waiting for ready"); + return EIO; + } + if (du->dk_status & WDCS_DRQ) { + wderror(du, NULL, "wddump: extra drq"); return EIO; + } if ((unsigned)addr % 1048576 == 0) printf("%d ", num / (1048576 / DEV_BSIZE)); @@ -1443,8 +1422,7 @@ wdreset(du, err) struct disk *du; int err; { - int wdc = du->dk_port; - int stat; + u_short wdc = du->dk_port; if (err) printf("wdc%d: busy too long, resetting\n", du->dk_ctrlr); @@ -1462,28 +1440,30 @@ wdreset(du, err) } int -wdc_wait(du, mask) +wdwait(du, mask) struct disk *du; int mask; { - int wdc = du->dk_port; + u_short wdc = du->dk_port; int timeout = 0; - int stat; + u_char status; for (;;) { - stat = inb(wdc+wd_altsts); - if ((stat & WDCS_BUSY) == 0 && (stat & mask) == mask) + du->dk_status = status = inb(wdc+wd_altsts); + if ((status & WDCS_BUSY) == 0 && (status & mask) == mask) break; if (++timeout > WDCNDELAY) return -1; delay(WDCDELAY); } + if (status & WDCS_ERR) + du->dk_error = inb(wdc+wd_error); #ifdef WDCNDELAY_DEBUG if (timeout > WDCNDELAY_DEBUG) - printf("wdc%d: timeout took %dus\n", du->dk_ctrlr, + printf("wdc%d: busy-wait took %dus\n", du->dk_ctrlr, WDCDELAY * timeout); #endif - return stat; + return status & WDCS_ERR; } static void @@ -1494,10 +1474,7 @@ wdtimeout(arg) struct disk *du = (void *)arg; if (du->dk_timeout && --du->dk_timeout == 0) { - int wdc = du->dk_port; - - printf("wd%d: lost interrupt: stat %x error %x\n", - du->dk_lunit, inb(wdc+wd_status), inb(wdc+wd_error)); + wderror(du, NULL, "lost interrupt"); wdreset(du, 0); /* XXX Need to recalibrate and upload geometry. */ du->dk_skip = 0; @@ -1508,4 +1485,17 @@ wdtimeout(arg) splx(s); } +static void +wderror(du, bp, msg) + struct disk *du; + struct buf *bp; + char *msg; +{ + if (bp) + diskerr(bp, "wd", msg, LOG_PRINTF, du->dk_skip, &du->dk_dd); + else + printf("wd%d: %s: status %b error %b\n", du->dk_lunit, msg, + du->dk_status, WDCS_BITS, du->dk_error, WDERR_BITS); +} + #endif /* NWDC > 0 */ |
