X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/41888f1633c1339d2f01b12ee2799c96530262dd..4e3eed49bf5eed0d943cfb968e399c3f3e011a3c:/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 53bf7359f2..06325dfb6a 100644 --- a/usr/src/sys/vax/uba/up.c +++ b/usr/src/sys/vax/uba/up.c @@ -1,16 +1,18 @@ -/* %H% 3.14 %G% */ +/* up.c 3.23 %G% */ -#define spl5 spl6 /* block clock, for delay loop's sake */ /* - * Emulex UNIBUS disk driver with overlapped seeks and ECC recovery. + * UNIBUS disk driver with overlapped seeks and ECC recovery. * - * NB: This device is very sensitive: be aware that the code is the way - * it is for good reason and that there are delay loops here which may - * have to be lengthened if your processor is faster and which should - * probably be shortened if your processor is slower. + * This driver works marginally on an Emulex SC-11B controller with rev + * level J microcode, defining: + * int olducode = 1; + * to force CPU stalling delays. * - * This driver has been tested on a SC-11B Controller, configured - * with the following internal switch settings: + * It has worked with no delays and no problems on a prototype + * SC-21 controller. Emulex intends to upgrade all SC-11s on VAXes to SC-21s. + * You should get a SC-21 to replace any SC-11 on a VAX. + * + * SC-11B Controller switch settings: * SW1-1 5/19 surfaces (off, 19 surfaces on Ampex 9300) * SW1-2 chksum enable (off, checksum disabled) * SW1-3 volume select (off, 815 cylinders) @@ -22,16 +24,8 @@ * and top mounted switches: * SW2-1 extend opcodes (off=open, disable) * SW2-2 extend diag (off=open, disable) - * SW2-3 4 wd dma burst (off=open, disable) + * SW2-3 4 wd dma burst (on=closed, enable) * SW2-4 unused (off=open) - * - * The controller transfers data much more rapidly with SW2-3 set, - * but we have previously experienced problems with it set this way. - * We intend to try this again in the near future. - * - * NB: OUR SYSTEM CURRENTLY GETS UBA ERRORS WHEN RUNNING THIS DRIVER - * AND THE BUS OCCASIONALLY HANGS, NECESSITATING THE DEVIE RESET - * CODE WHICH RE-INITS THE UNIBUS. YECHHH. */ #include "../h/param.h" @@ -42,9 +36,9 @@ #include "../h/dir.h" #include "../h/user.h" #include "../h/map.h" +#include "../h/pte.h" #include "../h/mba.h" #include "../h/mtpr.h" -#include "../h/pte.h" #include "../h/uba.h" #include "../h/vm.h" @@ -91,7 +85,7 @@ struct device * postpone starting SEARCH commands until the controller * is not transferring. */ -int softas; +int upsoftas; /* * If upseek then we don't issue SEARCH commands but rather just @@ -138,7 +132,7 @@ struct size } up_sizes[8] = { 15884, 0, /* A=cyl 0 thru 26 */ 33440, 27, /* B=cyl 27 thru 81 */ - 494912, 0, /* C=cyl 0 thru 814 */ + 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 */ @@ -154,7 +148,7 @@ struct size * +/- microinches. Note that header compare inhibit (HCI) is not * tried (this makes sense only during read, in any case.) * - * ARE ALL THESE IMPLEMENTED ON 9300? + * NOT ALL OF THESE ARE IMPLEMENTED ON 9300!?! */ #define P400 020 #define M400 0220 @@ -202,7 +196,7 @@ struct buf rupbuf; /* Buffer for raw i/o */ /* Other bits of upcs1 */ #define IE 0100 /* Controller wide interrupt enable */ #define TRE 040000 /* Transfer error */ -#define RDY 020 /* Transfer terminated */ +#define RDY 0200 /* Transfer terminated */ /* Drive status bits of upds */ #define PIP 020000 /* Positioning in progress */ @@ -212,6 +206,8 @@ struct buf rupbuf; /* Buffer for raw i/o */ #define MOL 010000 /* Drive is online, heads loaded, etc */ #define DRY 0200 /* Drive ready */ +/* Bits of upcs2 */ +#define CLR 040 /* Controller clear */ /* Bits of uper1 */ #define DCK 0100000 /* Ecc error occurred */ #define ECH 0100 /* Ecc error was unrecoverable */ @@ -225,24 +221,27 @@ struct buf rupbuf; /* Buffer for raw i/o */ int up_ubinfo; /* Information about UBA usage saved here */ /* * The EMULEX controller balks if accessed quickly after - * certain operations. The exact timing has not yet been - * determined, but delays are known to be needed when changing - * the selected drive (by writing in upcs2), and thought to be - * needed after operations like PRESET and DCLR. The following - * variables control the delay, DELAY(n) is approximately n usec. + * certain operations. With rev J delays seem to be needed only + * when selecting a new unit, and in drive initialization type + * like PRESET and DCLR. The following variables control the delay + * DELAY(n) is approximately n usec. */ +int olducode = 1; int idelay = 500; /* Delay after PRESET or DCLR */ -int sdelay = 150; /* Delay after selecting drive in upcs2 */ -int rdelay = 100; /* Delay after SEARCH */ -int asdel = 100; /* Delay after clearing bit in upas */ - -int csdel2 = 0; /* ??? Delay in upstart ??? */ +int osdelay = 150; /* Old delay after selecting drive in upcs2 */ +int ordelay = 100; /* Old delay after SEARCH */ +int oasdel = 100; /* Old delay after clearing bit in upas */ +int nsdelay = 25; #define DELAY(N) { register int d; d = N; while (--d > 0); } int nwaitcs2; /* How many sdelay loops ? */ int neasycs2; /* How many sdelay loops not needed ? */ +int up_wticks; /* Ticks waiting for interrupt */ +int upwstart; /* Have started guardian */ +int upwatch(); + #ifdef INTRLVE daddr_t dkblock(); #endif @@ -262,6 +261,10 @@ register struct buf *bp; register unit, xunit; long sz, bn; + if (upwstart == 0) { + timeout((caddr_t)upwatch, 0, HZ); + upwstart++; + } xunit = minor(bp->b_dev) & 077; sz = bp->b_bcount; sz = (sz+511) >> 9; /* transfer size in 512 byte sectors */ @@ -331,7 +334,7 @@ register unit; * until an interrupt when a transfer is pending. */ if (uptab.b_active) { - softas |= 1<b_active) @@ -339,7 +342,7 @@ register unit; dp->b_active = 1; if ((upaddr->upcs2 & 07) != unit) { upaddr->upcs2 = unit; - DELAY(sdelay); + DELAY(olducode ? osdelay : nsdelay); nwaitcs2++; } else neasycs2++; @@ -354,7 +357,6 @@ register unit; upaddr->upcs1 = IE|PRESET|GO; DELAY(idelay); upaddr->upof = FMT22; - printf("VV done ds %o, er? %o %o %o\n", upaddr->upds, upaddr->uper1, upaddr->uper2, upaddr->uper3); didie = 1; } if ((upaddr->upds & (DPR|MOL)) != (DPR|MOL)) @@ -395,11 +397,12 @@ search: * Mark this unit busy. */ unit += DK_N; - if (unit <= DK_NMAX) { + if (unit <= DK_NMAX && DK_N+NUP <= DK_NMAX) { dk_busy |= 1<upds & (DPR|MOL)) != (DPR|MOL)) { - printf("!DPR || !MOL, unit %d, ds %o\n", dn, upaddr->upds); - uptab.b_active = 0; - uptab.b_errcnt = 0; - dp->b_actf = bp->av_forw; - dp->b_active = 0; - bp->b_flags |= B_ERROR; - iodone(bp); - ubafree(up_ubinfo), up_ubinfo = 0; /* A funny place ... */ - goto loop; + printf("!DPR || !MOL, unit %d, ds %o", dn, upaddr->upds); + if ((upaddr->upds & (DPR|MOL)) != (DPR|MOL)) { + printf("-- hard\n"); + uptab.b_active = 0; + uptab.b_errcnt = 0; + dp->b_actf = bp->av_forw; + dp->b_active = 0; + bp->b_flags |= B_ERROR; + iodone(bp); + /* A funny place to do this ... */ + ubafree(up_ubinfo), up_ubinfo = 0; + goto loop; + } + printf("-- came back\n"); } /* * If this is a retry, then with the 16'th retry we * begin to try offsetting the heads to recover the data. */ - if (uptab.b_errcnt >= 16) { + if (uptab.b_errcnt >= 16 && (bp->b_flags&B_WRITE)) { upaddr->upof = up_offset[uptab.b_errcnt & 017] | FMT22; upaddr->upcs1 = IE|OFFSET|GO; DELAY(idelay); @@ -542,10 +549,11 @@ upintr() register unit; register struct device *upaddr = UPADDR; int as = upaddr->upas & 0377; - int osoftas; + int oupsoftas; int needie = 1; (void) spl6(); + up_wticks = 0; if (uptab.b_active) { /* * The drive is transferring, thus the hardware @@ -555,7 +563,8 @@ upintr() if ((upaddr->upcs1 & RDY) == 0) { printf("!RDY: cs1 %o, ds %o, wc %d\n", upaddr->upcs1, upaddr->upds, upaddr->upwc); -printf("as=%d act %d %d %d\n", as, uptab.b_active, uputab[0].b_active, uputab[1].b_active); + printf("as=%d act %d %d %d\n", as, uptab.b_active, + uputab[0].b_active, uputab[1].b_active); } /* * Mark controller or drive not busy, and check for an @@ -570,11 +579,11 @@ printf("as=%d act %d %d %d\n", as, uptab.b_active, uputab[0].b_active, uputab[1] dk_busy &= ~(1<<(DK_N+unit)); if ((upaddr->upcs2 & 07) != unit) { upaddr->upcs2 = unit; - DELAY(sdelay); + DELAY(olducode ? osdelay : nsdelay); nwaitcs2++; } else neasycs2++; - if (upaddr->upds & ERR) { + if ((upaddr->upds&ERR) || (upaddr->upcs1&TRE)) { /* * An error occurred, indeed. Select this unit * to get at the drive status (a SEARCH may have @@ -646,7 +655,8 @@ printf("as=%d act %d %d %d\n", as, uptab.b_active, uputab[0].b_active, uputab[1] dp->b_actf = bp->av_forw; bp->b_resid = (-upaddr->upwc * sizeof(short)); if (bp->b_resid) - printf("resid %d ds %o er? %o %o %o\n", bp->b_resid, upaddr->upds, + printf("resid %d ds %o er? %o %o %o\n", + bp->b_resid, upaddr->upds, upaddr->uper1, upaddr->uper2, upaddr->uper3); iodone(bp); if(dp->b_actf) @@ -654,7 +664,7 @@ printf("as=%d act %d %d %d\n", as, uptab.b_active, uputab[0].b_active, uputab[1] needie = 0; } as &= ~(1<upcs1 & TRE) { @@ -669,14 +679,15 @@ printf("as=%d act %d %d %d\n", as, uptab.b_active, uputab[0].b_active, uputab[1] * Finally, if the controller is not transferring * start it if any drives are now ready to transfer. */ - as |= softas; - osoftas = softas; - softas = 0; + as |= upsoftas; + oupsoftas = upsoftas; + upsoftas = 0; for (unit = 0; unit < NUP; unit++) - if ((as|osoftas) & (1<upas = 1<", (up_ubinfo>>28)&0xf); ubafree(up_ubinfo), up_ubinfo = 0; } + UPADDR->upcs2 = CLR; /* clear controller */ + DELAY(idelay); for (unit = 0; unit < NUP; unit++) { uputab[unit].b_active = 0; (void) upustart(unit); } (void) upstart(); } + +/* + * 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 + * and begin anew. + */ +upwatch() +{ + int i; + + timeout((caddr_t)upwatch, 0, HZ); + if (uptab.b_active == 0) { + for (i = 0; i < NUP; i++) + if (uputab[i].b_active) + goto active; + up_wticks = 0; /* idling */ + return; + } +active: + up_wticks++; + if (up_wticks >= 20) { + up_wticks = 0; + printf("LOST INTERRUPT RESET"); + upreset(); + printf("\n"); + } +}