From: Bill Joy Date: Thu, 26 Feb 1981 13:03:44 +0000 (-0800) Subject: almost working versions X-Git-Tag: BSD-4_1_snap-Snapshot-Development~2101 X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/commitdiff_plain/736772efddd677943a24c5f8ded448a1eba39fb9?hp=f6f4af0643cc2c2686845563bcff1b0bc8c20560 almost working versions SCCS-vsn: sys/vax/mba/hp.c 4.14 SCCS-vsn: sys/vax/mba/mba.c 4.9 SCCS-vsn: sys/vax/uba/up.c 4.22 SCCS-vsn: sys/vax/uba/tm.c 4.18 SCCS-vsn: sys/vax/uba/rk.c 4.11 --- diff --git a/usr/src/sys/vax/mba/hp.c b/usr/src/sys/vax/mba/hp.c index e69f6c7169..615462f86f 100644 --- a/usr/src/sys/vax/mba/hp.c +++ b/usr/src/sys/vax/mba/hp.c @@ -1,4 +1,4 @@ -/* hp.c 4.13 81/02/25 */ +/* hp.c 4.14 81/02/25 */ #include "hp.h" #if NHP > 0 @@ -217,16 +217,16 @@ hpstart(mi) hpaddr->hpda = (tn << 8) + sn; } -hpdtint(mi, mbastat) +hpdtint(mi, mbasr) register struct mba_info *mi; - int mbastat; + int mbasr; { register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; register struct buf *bp = mi->mi_tab.b_actf; while ((hpaddr->hpds & HP_DRY) == 0) /* shouldn't happen */ printf("hp dry not set\n"); - if (hpaddr->hpds & HP_ERR || mbastat & MBAEBITS) + if (hpaddr->hpds & HP_ERR || mbasr & MBAEBITS) if (++mi->mi_tab.b_errcnt < 28 && (hpaddr->hper1&HP_WLE) == 0) { if ((hpaddr->hper1&0xffff) != HP_DCK) { hpaddr->hpcs1 = HP_DCLR|HP_GO; @@ -243,7 +243,12 @@ hpdtint(mi, mbastat) if (hpaddr->hper1&HP_WLE) printf("hp%d is write locked\n", dkunit(bp)); else - deverror(bp, mbastat, hpaddr->hper1); + harderr(bp); + printf("hp%d mbasr %b er1 %b er2 %b\n", + dkunit(bp), mbasr, mbasr_bits, + hpaddr->hper1, HPER1_BITS, + hpaddr->hper2, HPER2_BITS); + hpaddr->hpcs1 = HP_DCLR|HP_GO; bp->b_flags |= B_ERROR; } bp->b_resid = -(mi->mi_mba->mba_bcr) & 0xffff; diff --git a/usr/src/sys/vax/mba/mba.c b/usr/src/sys/vax/mba/mba.c index 39df6efd07..bc64c1d60b 100644 --- a/usr/src/sys/vax/mba/mba.c +++ b/usr/src/sys/vax/mba/mba.c @@ -1,4 +1,4 @@ -/* mba.c 4.8 81/02/21 */ +/* mba.c 4.9 81/02/25 */ /* * Massbus driver; arbitrates massbusses through device driver routines @@ -21,6 +21,7 @@ int mbadebug = 0; #include "../h/mtpr.h" #include "../h/vm.h" +char mbasr_bits[] = MBASR_BITS; /* * Start activity on a massbus device. * We are given the device's mba_info structure and activate diff --git a/usr/src/sys/vax/uba/rk.c b/usr/src/sys/vax/uba/rk.c index 6f8bb13c0c..2a98e833c0 100644 --- a/usr/src/sys/vax/uba/rk.c +++ b/usr/src/sys/vax/uba/rk.c @@ -1,4 +1,4 @@ -/* rk.c 4.10 %G% */ +/* rk.c 4.11 %G% */ #include "rk.h" #if NHK > 0 @@ -327,12 +327,14 @@ hkintr(rk11) if (ds & RKDS_HARD) printf("rk%d is down\n", dkunit(bp)); if (++um->um_tab.b_errcnt > 28 || - ds&RKDS_HARD || er&RKER_HARD || cs2&RKCS2_HARD) + ds&RKDS_HARD || er&RKER_HARD || cs2&RKCS2_HARD) { bp->b_flags |= B_ERROR; - else + harderr(bp); + printf("rk%d cs2 %b ds %b er %b\n", + dkunit(bp), cs2, RKCS2_BITS, ds, + RKDS_BITS, er, RKER_BITS); + } else um->um_tab.b_active = 0; - if (um->um_tab.b_errcnt > 27) - deverror(bp, cs2, (ds<<16)|er); if (cs2&RK_MDS) { rkaddr->rkcs2 = RK_SCLR; goto retry; diff --git a/usr/src/sys/vax/uba/tm.c b/usr/src/sys/vax/uba/tm.c index 9311997831..50d6592b15 100644 --- a/usr/src/sys/vax/uba/tm.c +++ b/usr/src/sys/vax/uba/tm.c @@ -1,4 +1,4 @@ -/* tm.c 4.17 %G% */ +/* tm.c 4.18 %G% */ #include "tm.h" #if NTM > 0 @@ -518,7 +518,9 @@ tmintr(tm11) /* * Couldn't recover error */ - deverror(bp, sc->sc_erreg, sc->sc_dsreg); + harderr(bp); + printf("tm%d er %b\n", dkunit(bp), + sc->sc_erreg, TMEREG_BITS); bp->b_flags |= B_ERROR; goto opdone; } diff --git a/usr/src/sys/vax/uba/up.c b/usr/src/sys/vax/uba/up.c index 8d4c65826d..e25d94e70f 100644 --- a/usr/src/sys/vax/uba/up.c +++ b/usr/src/sys/vax/uba/up.c @@ -1,4 +1,4 @@ -/* up.c 4.21 81/02/23 */ +/* up.c 4.22 81/02/25 */ #include "up.h" #if NSC > 0 @@ -30,6 +30,7 @@ struct up_softc { int sc_softas; int sc_ndrive; int sc_wticks; + int sc_recal; } up_softc[NSC]; /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */ @@ -101,6 +102,7 @@ daddr_t dkblock(); int upwstart, upwatch(); /* Have started guardian */ int upseek; +int updrydel; /*ARGSUSED*/ upprobe(reg) @@ -198,40 +200,63 @@ bad: return; } +/* + * Unit start routine. + * Seek the drive to be where the data is + * and then generate another interrupt + * to actually start the transfer. + * If there is only one drive on the controller, + * or we are very close to the data, don't + * bother with the search. If called after + * searching once, don't bother to look where + * we are, just queue for transfer (to avoid + * positioning forever without transferrring.) + */ upustart(ui) register struct uba_dinfo *ui; { register struct buf *bp, *dp; - register struct uba_minfo *um; + register struct uba_minfo *um = ui->ui_mi; register struct updevice *upaddr; register struct upst *st; daddr_t bn; - int sn, cn, csn; - int didie = 0; - - if (ui == 0) - return (0); + int sn, csn; /* * The SC21 cancels commands if you just say * cs1 = UP_IE * so we are cautious about handling of cs1. * Also don't bother to clear as bits other than in upintr(). */ + int didie = 0; + + if (ui == 0) + return (0); dk_busy &= ~(1<ui_dk); dp = &uputab[ui->ui_unit]; if ((bp = dp->b_actf) == NULL) goto out; - /* dont confuse controller by giving SEARCH while dt in progress */ - um = ui->ui_mi; + /* + * If the controller is active, just remember + * that this device would like to be positioned... + * if we tried to position now we would confuse the SC21. + */ if (um->um_tab.b_active) { up_softc[um->um_ctlr].sc_softas |= 1<ui_slave; return (0); } + /* + * If we have already positioned this drive, + * then just put it on the ready queue. + */ if (dp->b_active) goto done; dp->b_active = 1; upaddr = (struct updevice *)um->um_addr; upaddr->upcs2 = ui->ui_slave; + /* + * If drive has just come up, + * setup the pack. + */ if ((upaddr->upds & UP_VV) == 0) { /* SHOULD WARN SYSTEM THAT THIS HAPPENED */ upaddr->upcs1 = UP_IE|UP_DCLR|UP_GO; @@ -239,16 +264,26 @@ upustart(ui) upaddr->upof = UP_FMT22; didie = 1; } + /* + * If drive is offline, forget about positioning. + */ if ((upaddr->upds & (UP_DPR|UP_MOL)) != (UP_DPR|UP_MOL)) goto done; + /* + * If there is only one drive, + * dont bother searching. + */ if (up_softc[um->um_ctlr].sc_ndrive == 1) goto done; + /* + * Figure out where this transfer is going to + * and see if we are close enough to justify not searching. + */ st = &upst[ui->ui_type]; bn = dkblock(bp); - cn = bp->b_cylin; sn = bn%st->nspc; sn = (sn + st->nsect - upSDIST) % st->nsect; - if (cn - upaddr->updc) + if (bp->b_cylin - upaddr->updc) goto search; /* Not on-cylinder */ else if (upseek) goto done; /* Ok just to be on-cylinder */ @@ -258,7 +293,11 @@ upustart(ui) if (csn > st->nsect - upRDIST) goto done; search: - upaddr->updc = cn; + upaddr->updc = bp->b_cylin; + /* + * Not on cylinder at correct position, + * seek/search. + */ if (upseek) upaddr->upcs1 = UP_IE|UP_SEEK|UP_GO; else { @@ -266,12 +305,20 @@ search: upaddr->upcs1 = UP_IE|UP_SEARCH|UP_GO; } didie = 1; + /* + * Mark unit busy for iostat. + */ if (ui->ui_dk >= 0) { dk_busy |= 1<ui_dk; dk_seek[ui->ui_dk]++; } goto out; done: + /* + * Device is ready to go. + * Put it on the ready queue for the controller + * (unless its already there.) + */ if (dp->b_active != 2) { dp->b_forw = NULL; if (um->um_tab.b_actf == NULL) @@ -285,6 +332,9 @@ out: return (didie); } +/* + * Start up a transfer on a drive. + */ upstart(um) register struct uba_minfo *um; { @@ -296,12 +346,19 @@ upstart(um) int dn, sn, tn, cmd; loop: + /* + * Pull a request off the controller queue + */ if ((dp = um->um_tab.b_actf) == NULL) return (0); if ((bp = dp->b_actf) == NULL) { um->um_tab.b_actf = dp->b_forw; goto loop; } + /* + * Mark controller busy, and + * determine destination of this request. + */ um->um_tab.b_active++; ui = updinfo[dkunit(bp)]; bn = dkblock(bp); @@ -311,7 +368,14 @@ loop: tn = sn/st->nsect; sn %= st->nsect; upaddr = (struct updevice *)ui->ui_addr; - upaddr->upcs2 = dn; + /* + * Select drive if not selected already. + */ + if ((upaddr->upcs2&07) != dn) + upaddr->upcs2 = dn; + /* + * Check that it is ready and online + */ if ((upaddr->upds & (UP_DPR|UP_MOL)) != (UP_DPR|UP_MOL)) { printf("up%d not ready", dkunit(bp)); if ((upaddr->upds & (UP_DPR|UP_MOL)) != (UP_DPR|UP_MOL)) { @@ -324,14 +388,25 @@ loop: iodone(bp); goto loop; } + /* + * Oh, well, sometimes this + * happens, for reasons unknown. + */ printf(" (flakey)\n"); } + /* + * After 16th retry, do offset positioning + */ if (um->um_tab.b_errcnt >= 16 && (bp->b_flags&B_READ) != 0) { upaddr->upof = up_offset[um->um_tab.b_errcnt & 017] | UP_FMT22; upaddr->upcs1 = UP_IE|UP_OFFSET|UP_GO; while (upaddr->upds & UP_PIP) DELAY(25); } + /* + * Setup for the transfer, and get in the + * UNIBUS adaptor queue. + */ upaddr->updc = bp->b_cylin; upaddr->upda = (tn << 8) + sn; upaddr->upwc = -bp->b_bcount / sizeof (short); @@ -344,6 +419,9 @@ loop: return (1); } +/* + * Now all ready to go, stuff the registers. + */ updgo(um) struct uba_minfo *um; { @@ -353,6 +431,9 @@ updgo(um) upaddr->upcs1 = um->um_cmd|((um->um_ubinfo>>8)&0x300); } +/* + * Handle a disk interrupt. + */ scintr(sc21) register sc21; { @@ -367,75 +448,144 @@ scintr(sc21) sc->sc_wticks = 0; sc->sc_softas = 0; - if (um->um_tab.b_active) { - if ((upaddr->upcs1 & UP_RDY) == 0) - printf("upintr !RDY\n"); - dp = um->um_tab.b_actf; - bp = dp->b_actf; - ui = updinfo[dkunit(bp)]; - dk_busy &= ~(1 << ui->ui_dk); + /* + * If controller wasn't transferring, then this is an + * interrupt for attention status on seeking drives. + * Just service them. + */ + if (um->um_tab.b_active == 0) { + if (upaddr->upcs1 & UP_TRE) + upaddr->upcs1 = UP_TRE; + goto doattn; + } + if ((upaddr->upcs1 & UP_RDY) == 0) + printf("upintr !RDY\n"); /* shouldn't happen */ + /* + * Get device and block structures, and a pointer + * to the uba_dinfo for the drive. Select the drive. + */ + dp = um->um_tab.b_actf; + bp = dp->b_actf; + ui = updinfo[dkunit(bp)]; + dk_busy &= ~(1 << ui->ui_dk); + if ((upaddr->upcs2&07) != ui->ui_slave) upaddr->upcs2 = ui->ui_slave; - if ((upaddr->upds&UP_ERR) || (upaddr->upcs1&UP_TRE)) { - int cs2; - while ((upaddr->upds & UP_DRY) == 0) - DELAY(25); - if (upaddr->uper1&UP_WLE) - printf("up%d is write locked\n", dkunit(bp)); - if (++um->um_tab.b_errcnt > 28 || upaddr->uper1&UP_WLE) - bp->b_flags |= B_ERROR; - else - um->um_tab.b_active = 0; /* force retry */ - if (um->um_tab.b_errcnt > 27) { - cs2 = (int)upaddr->upcs2; - deverror(bp, cs2, (int)upaddr->uper1); + /* + * Check for and process errors on + * either the drive or the controller. + */ + if ((upaddr->upds&UP_ERR) || (upaddr->upcs1&UP_TRE)) { + while ((upaddr->upds & UP_DRY) == 0) + updrydel++; + if (upaddr->uper1&UP_WLE) { + /* + * Give up on write locked devices + * immediately. + */ + printf("up%d is write locked\n", dkunit(bp)); + bp->b_flags |= B_ERROR; + } else if (++um->um_tab.b_errcnt > 27) { + /* + * After 28 retries (16 without offset, and + * 12 with offset positioning) give up. + */ + if (upaddr->upcs2&(UP_NEM|UP_MXF)) { + printf("FLAKEY UP "); + ubareset(um->um_ubanum); + return; } + harderr(bp); + printf("up%d cs2 %b er1 %b er2 %b\n", + dkunit(bp), upaddr->upcs2, UPCS2_BITS, upaddr->uper1, + UPER1_BITS, upaddr->uper2, UPER2_BITS); + bp->b_flags |= B_ERROR; + } else { + /* + * Retriable error. + * If a soft ecc, correct it (continuing + * by returning if necessary. + * Otherwise fall through and retry the transfer + */ + um->um_tab.b_active = 0; /* force retry */ if ((upaddr->uper1&(UP_DCK|UP_ECH))==UP_DCK) if (upecc(ui)) return; - upaddr->upcs1 = UP_TRE|UP_IE|UP_DCLR|UP_GO; + } + /* + * Clear drive error and, every eight attempts, + * (starting with the fourth) + * recalibrate to clear the slate. + */ + upaddr->upcs1 = UP_TRE|UP_IE|UP_DCLR|UP_GO; + needie = 0; + if ((um->um_tab.b_errcnt&07) == 4) { + upaddr->upcs1 = UP_RECAL|UP_IE|UP_GO; + um->um_tab.b_active = 1; + sc->sc_recal = 1; + return; + } + } + /* + * Done retrying transfer... release + * resources... if we were recalibrating, + * then retry the transfer. + * Mathematical note: 28%8 != 4. + */ + ubadone(um); + if (sc->sc_recal) { + sc->sc_recal = 0; + um->um_tab.b_active = 0; /* force retry */ + } + /* + * If still ``active'', then don't need any more retries. + */ + if (um->um_tab.b_active) { + /* + * If we were offset positioning, + * return to centerline. + */ + if (um->um_tab.b_errcnt >= 16) { + upaddr->upof = UP_FMT22; + upaddr->upcs1 = UP_RTC|UP_GO|UP_IE; + while (upaddr->upds & UP_PIP) + DELAY(25); needie = 0; - if ((um->um_tab.b_errcnt&07) == 4) { - upaddr->upcs1 = UP_RECAL|UP_IE|UP_GO; - while(upaddr->upds & UP_PIP) - DELAY(25); - } - if (um->um_tab.b_errcnt == 28 && cs2&(UP_NEM|UP_MXF)) { - printf("FLAKEY UP "); - ubareset(um->um_ubanum); - return; - } } - ubadone(um); - if (um->um_tab.b_active) { - if (um->um_tab.b_errcnt >= 16) { - upaddr->upcs1 = UP_RTC|UP_GO|UP_IE; - while (upaddr->upds & UP_PIP) - DELAY(25); + um->um_tab.b_active = 0; + um->um_tab.b_errcnt = 0; + um->um_tab.b_actf = dp->b_forw; + dp->b_active = 0; + dp->b_errcnt = 0; + dp->b_actf = bp->av_forw; + bp->b_resid = (-upaddr->upwc * sizeof(short)); + iodone(bp); + /* + * If this unit has more work to do, + * then start it up right away. + */ + if (dp->b_actf) + if (upustart(ui)) needie = 0; - } - um->um_tab.b_active = 0; - um->um_tab.b_errcnt = 0; - um->um_tab.b_actf = dp->b_forw; - dp->b_active = 0; - dp->b_errcnt = 0; - dp->b_actf = bp->av_forw; - bp->b_resid = (-upaddr->upwc * sizeof(short)); - iodone(bp); - if (dp->b_actf) - if (upustart(ui)) - needie = 0; - } - as &= ~(1<ui_slave); - } else { - if (upaddr->upcs1 & UP_TRE) - upaddr->upcs1 = UP_TRE; } + as &= ~(1<ui_slave); +doattn: + /* + * Process other units which need attention. + * For each unit which needs attention, call + * the unit start routine to place the slave + * on the controller device queue. + */ for (unit = 0; as; as >>= 1, unit++) if (as & 1) { upaddr->upas = 1<um_tab.b_actf && um->um_tab.b_active == 0) if (upstart(um)) needie = 0;