X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/060afaf6fc835fde62dca6e0035ff72c7497e012..de59ccc2375aad4c9f0ff41f3291584ead755f15:/usr/src/sys/vax/uba/up.c diff --git a/usr/src/sys/vax/uba/up.c b/usr/src/sys/vax/uba/up.c index 0fa50d89f7..44e1bdbeb2 100644 --- a/usr/src/sys/vax/uba/up.c +++ b/usr/src/sys/vax/uba/up.c @@ -1,11 +1,14 @@ -/* up.c 4.25 81/02/26 */ +/* up.c 4.53 82/05/27 */ #include "up.h" #if NSC > 0 /* * UNIBUS disk driver with overlapped seeks and ECC recovery. + * + * TODO: + * Add bad sector forwarding code + * Check that offset recovery code works */ -#define DELAY(N) { register int d; d = N; while (--d > 0); } #include "../h/param.h" #include "../h/systm.h" @@ -20,7 +23,8 @@ #include "../h/pte.h" #include "../h/mtpr.h" #include "../h/vm.h" -#include "../h/uba.h" +#include "../h/ubavar.h" +#include "../h/ubareg.h" #include "../h/cmap.h" #include "../h/upreg.h" @@ -38,13 +42,22 @@ struct size daddr_t nblocks; int cyloff; } up_sizes[8] = { +#ifdef ERNIE + 49324, 0, /* A=cyl 0 thru 26 */ +#else 15884, 0, /* A=cyl 0 thru 26 */ +#endif 33440, 27, /* B=cyl 27 thru 81 */ 495520, 0, /* C=cyl 0 thru 814 */ 15884, 562, /* D=cyl 562 thru 588 */ 55936, 589, /* E=cyl 589 thru 680 */ - 81472, 681, /* F=cyl 681 thru 814 */ - 153824, 562, /* G=cyl 562 thru 814 */ +#ifndef NOBADSECT + 81376, 681, /* F=cyl 681 thru 814 */ + 153728, 562, /* G=cyl 562 thru 814 */ +#else + 81472, 681, + 153824, 562, +#endif 291346, 82, /* H=cyl 82 thru 561 */ }, fj_sizes[8] = { 15884, 0, /* A=cyl 0 thru 49 */ @@ -54,20 +67,38 @@ struct size 0, 0, 0, 0, 0, 0, - 213760, 155, /* H=cyl 155 thru 822 */ +#ifndef NOBADSECT + 213664, 155, /* H=cyl 155 thru 822 */ +#else + 213760, 155, +#endif +}, upam_sizes[8] = { + 15884, 0, /* A=cyl 0 thru 31 */ + 33440, 32, /* B=cyl 32 thru 97 */ + 524288, 0, /* C=cyl 0 thru 1023 */ + 27786, 668, + 27786, 723, + 125440, 778, + 181760, 668, /* G=cyl 668 thru 1022 */ + 291346, 98, /* H=cyl 98 thru 667 */ }; /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */ -#define _upSDIST 2 /* 1.0 msec */ +/* + * On a 780 upSDIST could be 2, but + * in the interest of 750's... + */ +#define _upSDIST 3 /* 1.5 msec */ #define _upRDIST 4 /* 2.0 msec */ int upSDIST = _upSDIST; int upRDIST = _upRDIST; int upprobe(), upslave(), upattach(), updgo(), upintr(); -struct uba_minfo *upminfo[NSC]; -struct uba_dinfo *updinfo[NUP]; -struct uba_dinfo *upip[NSC][4]; +struct uba_ctlr *upminfo[NSC]; +struct uba_device *updinfo[NUP]; +#define UPIPUNITS 8 +struct uba_device *upip[NSC][UPIPUNITS]; /* fuji w/fixed head gives n,n+4 */ u_short upstd[] = { 0776700, 0774400, 0776300, 0 }; struct uba_driver scdriver = @@ -84,11 +115,14 @@ struct upst { 32, 19, 32*19, 823, up_sizes, /* 9300/cdc */ /* 9300 actually has 815 cylinders... */ 32, 10, 32*10, 823, fj_sizes, /* fujitsu 160m */ + 32, 16, 32*16, 1024, upam_sizes, /* ampex capricorn */ }; u_char up_offset[16] = { - UP_P400, UP_M400, UP_P400, UP_M400, UP_P800, UP_M800, UP_P800, UP_M800, - UP_P1200, UP_M1200, UP_P1200, UP_M1200, 0, 0, 0, 0 + UPOF_P400, UPOF_M400, UPOF_P400, UPOF_M400, + UPOF_P800, UPOF_M800, UPOF_P800, UPOF_M800, + UPOF_P1200, UPOF_M1200, UPOF_P1200, UPOF_M1200, + 0, 0, 0, 0 }; struct buf rupbuf[NUP]; @@ -119,14 +153,15 @@ upprobe(reg) } upslave(ui, reg) - struct uba_dinfo *ui; + struct uba_device *ui; caddr_t reg; { register struct updevice *upaddr = (struct updevice *)reg; upaddr->upcs1 = 0; /* conservative */ upaddr->upcs2 = ui->ui_slave; - if (upaddr->upcs2&UP_NED) { + upaddr->upcs1 = UP_NOP|UP_GO; + if (upaddr->upcs2&UPCS2_NED) { upaddr->upcs1 = UP_DCLR|UP_GO; return (0); } @@ -134,35 +169,41 @@ upslave(ui, reg) } upattach(ui) - register struct uba_dinfo *ui; + register struct uba_device *ui; { -#ifdef notdef register struct updevice *upaddr; -#endif if (upwstart == 0) { - timeout(upwatch, (caddr_t)0, HZ); + timeout(upwatch, (caddr_t)0, hz); upwstart++; } if (ui->ui_dk >= 0) dk_mspw[ui->ui_dk] = .0000020345; upip[ui->ui_ctlr][ui->ui_slave] = ui; up_softc[ui->ui_ctlr].sc_ndrive++; -#ifdef notdef upaddr = (struct updevice *)ui->ui_addr; upaddr->upcs1 = 0; upaddr->upcs2 = ui->ui_slave; - upaddr->uphr = -1; - /* ... */ - if (upaddr-> ... == 10) - ui->ui_type = 1; -#endif + upaddr->uphr = UPHR_MAXTRAK; + if (upaddr->uphr == 9) + ui->ui_type = 1; /* fujitsu hack */ + else if (upaddr->uphr == 15) + ui->ui_type = 2; /* ampex hack */ + upaddr->upcs2 = UPCS2_CLR; +/* + upaddr->uphr = UPHR_MAXCYL; + printf("maxcyl %d\n", upaddr->uphr); + upaddr->uphr = UPHR_MAXTRAK; + printf("maxtrak %d\n", upaddr->uphr); + upaddr->uphr = UPHR_MAXSECT; + printf("maxsect %d\n", upaddr->uphr); +*/ } upstrategy(bp) register struct buf *bp; { - register struct uba_dinfo *ui; + register struct uba_device *ui; register struct upst *st; register int unit; register struct buf *dp; @@ -212,10 +253,10 @@ bad: * positioning forever without transferrring.) */ upustart(ui) - register struct uba_dinfo *ui; + register struct uba_device *ui; { register struct buf *bp, *dp; - register struct uba_minfo *um = ui->ui_mi; + register struct uba_ctlr *um; register struct updevice *upaddr; register struct upst *st; daddr_t bn; @@ -230,6 +271,7 @@ upustart(ui) if (ui == 0) return (0); + um = ui->ui_mi; dk_busy &= ~(1<ui_dk); dp = &uputab[ui->ui_unit]; if ((bp = dp->b_actf) == NULL) @@ -256,17 +298,17 @@ upustart(ui) * If drive has just come up, * setup the pack. */ - if ((upaddr->upds & UP_VV) == 0) { + if ((upaddr->upds & UPDS_VV) == 0) { /* SHOULD WARN SYSTEM THAT THIS HAPPENED */ upaddr->upcs1 = UP_IE|UP_DCLR|UP_GO; upaddr->upcs1 = UP_IE|UP_PRESET|UP_GO; - upaddr->upof = UP_FMT22; + upaddr->upof = UPOF_FMT22; didie = 1; } /* * If drive is offline, forget about positioning. */ - if ((upaddr->upds & (UP_DPR|UP_MOL)) != (UP_DPR|UP_MOL)) + if ((upaddr->upds & (UPDS_DPR|UPDS_MOL)) != (UPDS_DPR|UPDS_MOL)) goto done; /* * If there is only one drive, @@ -335,10 +377,10 @@ out: * Start up a transfer on a drive. */ upstart(um) - register struct uba_minfo *um; + register struct uba_ctlr *um; { register struct buf *bp, *dp; - register struct uba_dinfo *ui; + register struct uba_device *ui; register struct updevice *upaddr; struct upst *st; daddr_t bn; @@ -376,14 +418,14 @@ loop: * Check that it is ready and online */ waitdry = 0; - while ((upaddr->upds&UP_DRY) == 0) { + while ((upaddr->upds&UPDS_DRY) == 0) { if (++waitdry > 512) break; upwaitdry++; } - if ((upaddr->upds & UP_DREADY) != UP_DREADY) { - printf("up%d not ready", dkunit(bp)); - if ((upaddr->upds & UP_DREADY) != UP_DREADY) { + if ((upaddr->upds & UPDS_DREADY) != UPDS_DREADY) { + printf("up%d: not ready", dkunit(bp)); + if ((upaddr->upds & UPDS_DREADY) != UPDS_DREADY) { printf("\n"); um->um_tab.b_active = 0; um->um_tab.b_errcnt = 0; @@ -399,15 +441,6 @@ loop: */ 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. @@ -420,7 +453,7 @@ loop: else cmd = UP_IE|UP_WCOM|UP_GO; um->um_cmd = cmd; - ubago(ui); + (void) ubago(ui); return (1); } @@ -428,10 +461,11 @@ loop: * Now all ready to go, stuff the registers. */ updgo(um) - struct uba_minfo *um; + struct uba_ctlr *um; { register struct updevice *upaddr = (struct updevice *)um->um_addr; + um->um_tab.b_active = 2; /* should now be 2 */ upaddr->upba = um->um_ubinfo; upaddr->upcs1 = um->um_cmd|((um->um_ubinfo>>8)&0x300); } @@ -443,8 +477,8 @@ upintr(sc21) register sc21; { register struct buf *bp, *dp; - register struct uba_minfo *um = upminfo[sc21]; - register struct uba_dinfo *ui; + register struct uba_ctlr *um = upminfo[sc21]; + register struct uba_device *ui; register struct updevice *upaddr = (struct updevice *)um->um_addr; register unit; struct up_softc *sc = &up_softc[um->um_ctlr]; @@ -458,16 +492,15 @@ upintr(sc21) * interrupt for attention status on seeking drives. * Just service them. */ - if (um->um_tab.b_active == 0) { + if (um->um_tab.b_active != 2 && !sc->sc_recal) { if (upaddr->upcs1 & UP_TRE) upaddr->upcs1 = UP_TRE; goto doattn; } - if ((upaddr->upcs1 & UP_RDY) == 0) - printf("upintr !RDY\n"); /* shouldn't happen */ + um->um_tab.b_active = 1; /* * Get device and block structures, and a pointer - * to the uba_dinfo for the drive. Select the drive. + * to the uba_device for the drive. Select the drive. */ dp = um->um_tab.b_actf; bp = dp->b_actf; @@ -479,37 +512,30 @@ upintr(sc21) * Check for and process errors on * either the drive or the controller. */ - if ((upaddr->upds&UP_ERR) || (upaddr->upcs1&UP_TRE)) { + if ((upaddr->upds&UPDS_ERR) || (upaddr->upcs1&UP_TRE)) { waitdry = 0; - while ((upaddr->upds & UP_DRY) == 0) { + while ((upaddr->upds & UPDS_DRY) == 0) { if (++waitdry > 512) break; upwaitdry++; } - if ((upaddr->upds&UP_DREADY) != UP_DREADY) { - printf("up%d not ready", dkunit(bp)); - bp->b_flags |= B_ERROR; - } else if (upaddr->uper1&UP_WLE) { + if (upaddr->uper1&UPER1_WLE) { /* * Give up on write locked devices * immediately. */ - printf("up%d is write locked\n", dkunit(bp)); + printf("up%d: 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); + harderr(bp, "up"); + printf("cs2=%b er1=%b er2=%b\n", + upaddr->upcs2, UPCS2_BITS, + upaddr->uper1, UPER1_BITS, + upaddr->uper2, UPER2_BITS); bp->b_flags |= B_ERROR; } else { /* @@ -519,7 +545,7 @@ upintr(sc21) * 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 ((upaddr->uper1&(UPER1_DCK|UPER1_ECH))==UPER1_DCK) if (upecc(ui)) return; } @@ -530,23 +556,41 @@ upintr(sc21) */ upaddr->upcs1 = UP_TRE|UP_IE|UP_DCLR|UP_GO; needie = 0; - if ((um->um_tab.b_errcnt&07) == 4) { + if ((um->um_tab.b_errcnt&07) == 4 && um->um_tab.b_active == 0) { upaddr->upcs1 = UP_RECAL|UP_IE|UP_GO; - um->um_tab.b_active = 1; - sc->sc_recal = 1; - return; + sc->sc_recal = 0; + goto nextrecal; } } /* - * Done retrying transfer... release - * resources... if we were recalibrating, - * then retry the transfer. - * Mathematical note: 28%8 != 4. + * Advance recalibration finite state machine + * if recalibrate in progress, through + * RECAL + * SEEK + * OFFSET (optional) + * RETRY */ - ubadone(um); - if (sc->sc_recal) { + switch (sc->sc_recal) { + + case 1: + upaddr->updc = bp->b_cylin; + upaddr->upcs1 = UP_SEEK|UP_IE|UP_GO; + goto nextrecal; + case 2: + if (um->um_tab.b_errcnt < 16 || (bp->b_flags&B_READ) == 0) + goto donerecal; + upaddr->upof = up_offset[um->um_tab.b_errcnt & 017] | UPOF_FMT22; + upaddr->upcs1 = UP_IE|UP_OFFSET|UP_GO; + goto nextrecal; + nextrecal: + sc->sc_recal++; + um->um_tab.b_active = 1; + return; + donerecal: + case 3: sc->sc_recal = 0; - um->um_tab.b_active = 0; /* force retry */ + um->um_tab.b_active = 0; + break; } /* * If still ``active'', then don't need any more retries. @@ -557,9 +601,9 @@ upintr(sc21) * return to centerline. */ if (um->um_tab.b_errcnt >= 16) { - upaddr->upof = UP_FMT22; + upaddr->upof = UPOF_FMT22; upaddr->upcs1 = UP_RTC|UP_GO|UP_IE; - while (upaddr->upds & UP_PIP) + while (upaddr->upds & UPDS_PIP) DELAY(25); needie = 0; } @@ -580,6 +624,10 @@ upintr(sc21) needie = 0; } as &= ~(1<ui_slave); + /* + * Release unibus resources and flush data paths. + */ + ubadone(um); doattn: /* * Process other units which need attention. @@ -587,12 +635,13 @@ doattn: * 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<upas = 1<ui_addr; register struct buf *bp = uputab[ui->ui_unit].b_actf; - register struct uba_minfo *um = ui->ui_mi; + register struct uba_ctlr *um = ui->ui_mi; register struct upst *st; struct uba_regs *ubp = ui->ui_hd->uh_uba; register int i; @@ -655,13 +704,13 @@ upecc(ui) npf = btop((up->upwc * sizeof(short)) + bp->b_bcount) - 1; reg = btop(um->um_ubinfo&0x3ffff) + npf; o = (int)bp->b_un.b_addr & PGOFSET; - printf("%D ", bp->b_blkno+npf); - prdev("ECC", bp->b_dev); + printf("up%d%c: soft ecc sn%d\n", dkunit(bp), + 'a'+(minor(bp->b_dev)&07), bp->b_blkno + npf); mask = up->upec2; - if (mask == 0) { - up->upof = UP_FMT22; /* == RTC ???? */ - return (0); - } +#ifdef UPECCDEBUG + printf("npf %d reg %x o %d mask %o pos %d\n", npf, reg, o, mask, + up->upec1); +#endif /* * Flush the buffered data path, and compute the * byte and bit position of the error. The variable i @@ -682,12 +731,19 @@ upecc(ui) while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) { addr = ptob(ubp->uba_map[reg+btop(byte)].pg_pfnum)+ (byte & PGOFSET); +#ifdef UPECCDEBUG + printf("addr %x map reg %x\n", + addr, *(int *)(&ubp->uba_map[reg+btop(byte)])); + printf("old: %x, ", getmemc(addr)); +#endif putmemc(addr, getmemc(addr)^(mask<um_tab.b_active++; /* Either complete or continuing... */ if (up->upwc == 0) return (0); /* @@ -715,6 +771,7 @@ upecc(ui) up->upba = ubaddr; cmd = (ubaddr >> 8) & 0x300; cmd |= UP_IE|UP_GO|UP_RCOM; + um->um_tab.b_active = 2; /* continuing transfer ... */ up->upcs1 = cmd; #endif return (1); @@ -726,32 +783,30 @@ upecc(ui) * and restart all units and the controller. */ upreset(uban) + int uban; { - register struct uba_minfo *um; - register struct uba_dinfo *ui; + register struct uba_ctlr *um; + register struct uba_device *ui; register sc21, unit; - int any = 0; for (sc21 = 0; sc21 < NSC; sc21++) { if ((um = upminfo[sc21]) == 0 || um->um_ubanum != uban || um->um_alive == 0) continue; - if (any == 0) { - printf(" up"); - DELAY(10000000); /* give it time to self-test */ - any++; - } + printf(" sc%d", sc21); um->um_tab.b_active = 0; um->um_tab.b_actf = um->um_tab.b_actl = 0; + up_softc[sc21].sc_recal = 0; + up_softc[sc21].sc_wticks = 0; if (um->um_ubinfo) { printf("<%d>", (um->um_ubinfo>>28)&0xf); ubadone(um); } - ((struct updevice *)(um->um_addr))->upcs2 = UP_CLR; + ((struct updevice *)(um->um_addr))->upcs2 = UPCS2_CLR; for (unit = 0; unit < NUP; unit++) { if ((ui = updinfo[unit]) == 0) continue; - if (ui->ui_alive == 0) + if (ui->ui_alive == 0 || ui->ui_mi != um) continue; uputab[unit].b_active = 0; (void) upustart(ui); @@ -763,16 +818,16 @@ upreset(uban) /* * Wake up every second and if an interrupt is pending * but nothing has happened increment a counter. - * If nothing happens for 20 seconds, reset the controller + * If nothing happens for 20 seconds, reset the UNIBUS * and begin anew. */ upwatch() { - register struct uba_minfo *um; + register struct uba_ctlr *um; register sc21, unit; register struct up_softc *sc; - timeout(upwatch, (caddr_t)0, HZ); + timeout(upwatch, (caddr_t)0, hz); for (sc21 = 0; sc21 < NSC; sc21++) { um = upminfo[sc21]; if (um == 0 || um->um_alive == 0) @@ -786,11 +841,11 @@ upwatch() sc->sc_wticks = 0; continue; } - active: +active: sc->sc_wticks++; if (sc->sc_wticks >= 20) { sc->sc_wticks = 0; - printf("LOST upintr "); + printf("sc%d: lost interrupt\n", sc21); ubareset(um->um_ubanum); } } @@ -806,48 +861,41 @@ updump(dev) int num, blk, unit; struct size *sizes; register struct uba_regs *uba; - register struct uba_dinfo *ui; + register struct uba_device *ui; register short *rp; struct upst *st; + register int retry; unit = minor(dev) >> 3; - if (unit >= NUP) { - printf("bad unit\n"); - return (-1); - } + if (unit >= NUP) + return (ENXIO); #define phys(cast, addr) ((cast)((int)addr & 0x7fffffff)) - ui = phys(struct uba_dinfo *, updinfo[unit]); - if (ui->ui_alive == 0) { - printf("dna\n"); - return(-1); - } + ui = phys(struct uba_device *, updinfo[unit]); + if (ui->ui_alive == 0) + return (ENXIO); uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba; -#if VAX780 - if (cpu == VAX_780) - ubainit(uba); -#endif - DELAY(1000000); + ubainit(uba); upaddr = (struct updevice *)ui->ui_physaddr; - while ((upaddr->upcs1&UP_DVA) == 0) - ; + DELAY(5000000); num = maxfree; - start = 0; upaddr->upcs2 = unit; - if ((upaddr->upds & UP_VV) == 0) { - upaddr->upcs1 = UP_DCLR|UP_GO; - upaddr->upcs1 = UP_PRESET|UP_GO; - upaddr->upof = UP_FMT22; - } - if ((upaddr->upds & (UP_DPR|UP_MOL)) != (UP_DPR|UP_MOL)) { - printf("dna\n"); - return (-1); - } + DELAY(100); + upaddr->upcs1 = UP_DCLR|UP_GO; + upaddr->upcs1 = UP_PRESET|UP_GO; + upaddr->upof = UPOF_FMT22; + retry = 0; + do { + DELAY(25); + if (++retry > 527) + break; + } while ((upaddr->upds & UP_RDY) == 0); + if ((upaddr->upds & UPDS_DREADY) != UPDS_DREADY) + return (EFAULT); + start = 0; st = &upst[ui->ui_type]; sizes = phys(struct size *, st->sizes); - if (dumplo < 0 || dumplo + num >= sizes[minor(dev)&07].nblocks) { - printf("oor\n"); - return (-1); - } + if (dumplo < 0 || dumplo + num >= sizes[minor(dev)&07].nblocks) + return (EINVAL); while (num > 0) { register struct pte *io; register int i; @@ -857,7 +905,7 @@ updump(dev) blk = num > DBSIZE ? DBSIZE : num; io = uba->uba_map; for (i = 0; i < blk; i++) - *(int *)io++ = (btop(start)+i) | (1<<21) | UBA_MRV; + *(int *)io++ = (btop(start)+i) | (1<<21) | UBAMR_MRV; *(int *)io = 0; bn = dumplo + btop(start); cn = bn/st->nspc + sizes[minor(dev)&07].cyloff; @@ -870,14 +918,22 @@ updump(dev) *--rp = 0; *--rp = -blk*NBPG / sizeof (short); *--rp = UP_GO|UP_WCOM; + retry = 0; do { DELAY(25); + if (++retry > 527) + break; } while ((upaddr->upcs1 & UP_RDY) == 0); - if (upaddr->upcs1&UP_ERR) { - printf("up dump dsk err: (%d,%d,%d) cs1=%x, er1=%x\n", - cn, tn, sn, upaddr->upcs1, upaddr->uper1); - return (-1); + if ((upaddr->upds & UPDS_DREADY) != UPDS_DREADY) { + printf("up%d: not ready", unit); + if ((upaddr->upds & UPDS_DREADY) != UPDS_DREADY) { + printf("\n"); + return (EIO); + } + printf(" (flakey)\n"); } + if (upaddr->upds&UPDS_ERR) + return (EIO); start += blk*NBPG; num -= blk; }