|
|
1.1 ! root 1: static char *sccsid = "@(#)hk.c 1.1 (Berkeley) 10/10/80"; ! 2: ! 3: /* ! 4: * RK07 disk driver with bad-sector forwarding ! 5: * ! 6: * This driver, revised from a UCSB RK07 driver, is modeled ! 7: * after the Stanford SI 9500 driver with bad-sector forwarding. ! 8: * The bad-sector information on the last track of each pack is ! 9: * used to patch up transfers by forwarding accesses to bad sectors ! 10: * to spares on the last cylinder. The last cylinder is otherwise ! 11: * write-protected. ! 12: * The bad-sector table is read when a minor device is first ! 13: * opened after a close. No Volume-Valid checking is done; ! 14: * hamfists beware. To be correct, the open routine needs a ! 15: * mechanism for reading drive status and for doing a PACKACK. ! 16: * A pack is 1 minor device; there is no pack mapping. ! 17: * No attempt at ECC logic is included. Be my guest. ! 18: * ! 19: * BUGS: The same bomb is planted here as in most UBA DMA drivers, ! 20: * to wit, ubasetup is called from the interrupt level. Ubasetup ! 21: * will sleep if it cannot allocate; ka-boom! ! 22: * ! 23: * Author: Rob Mathews, EE Information Systems Lab, Stanford 4/80 ! 24: */ ! 25: ! 26: /* ! 27: * Debug control ! 28: * ! 29: * 1 - open/close ! 30: * 2 - strategy ! 31: * 4 - intr entry/exit ! 32: * 8 - intr detail ! 33: * 16 - intr sector mapping ! 34: * 32 - strat errors/lock-opens ! 35: * 64 - bst reading ! 36: *1024 - loop after errors ! 37: */ ! 38: ! 39: #define debug(bit) if (rk7debug & (bit)) printf ! 40: int rk7debug = (0); ! 41: ! 42: #include "../h/param.h" ! 43: #include "../h/systm.h" ! 44: #include "../h/buf.h" ! 45: #include "../h/conf.h" ! 46: #include "../h/dir.h" ! 47: #include "../h/user.h" ! 48: #include "../h/map.h" ! 49: #include "../h/pte.h" ! 50: #include "../h/uba.h" ! 51: ! 52: /* ! 53: * Disk parameters ! 54: */ ! 55: ! 56: #define NRK7 8 ! 57: #define NCYLS 815 ! 58: #define NTRKS 3 ! 59: #define NSECTS 22 ! 60: #define NBYTES 512 ! 61: #define NBLKS (NCYLS*NTRKS*NSECTS) ! 62: #define BSCYL (NCYLS-1) /* bad-sector repair cylinder */ ! 63: #define BSBASE (BSCYL*NTRKS*NSECTS) /* track 0,1 - repair pool */ ! 64: #define BSTBLK (BSBASE + 2*NSECTS) /* track 2 - bad-sector table */ ! 65: #define MAXBB 10 /* max tolerable bad sectors */ ! 66: ! 67: /* ! 68: * Register definitions ! 69: */ ! 70: ! 71: #define RK7ADDR ((struct rk7_regs *)(UBA0_DEV + 0177440)) ! 72: ! 73: struct rk7_regs ! 74: { ! 75: short rkcs1, rkwc; ! 76: unsigned short rkba; ! 77: short rkda, rkcs2, rkds, rker, rkasof, rkdc, rknull, rkdb, rkmr1; ! 78: short rkecps, rkecpt, rkmr2, rkmr3; ! 79: }; ! 80: ! 81: /* ! 82: * Register bits, per RK07 manual ! 83: */ ! 84: ! 85: #define GO 01 /* cs1 */ ! 86: #define DRCLR 04 ! 87: #define READ 020 ! 88: #define WRITE 022 ! 89: #define PACKACK 02 ! 90: #define IE 0100 ! 91: #define RDY 0200 ! 92: #define BA1617 01400 ! 93: #define CDT 02000 ! 94: #define CERR 0100000 ! 95: #define CCLR 0100000 ! 96: #define SCLR 040 /* cs2 */ ! 97: #define SVAL 0100000 /* ds */ ! 98: #define DRDY 0200 ! 99: #define VV 0100 ! 100: #define DRA 01 ! 101: #define DCK 0100000 /* er */ ! 102: #define BSE 0200 ! 103: #define NXF 04 ! 104: ! 105: #define Error ((RK7ADDR->rkcs1 & CERR) != 0) ! 106: ! 107: /* ! 108: * Driver parameters, data, and definitions ! 109: */ ! 110: ! 111: #define RETRIES 10 ! 112: ! 113: #define IDLE 0 ! 114: #define NORMAL 1 ! 115: #define MAPPED 2 ! 116: #define RESTART 3 ! 117: ! 118: struct buf rk7tab, rk7bsbuf, rrk7buf; ! 119: ! 120: struct rk7 ! 121: { ! 122: long access; ! 123: short retries, errors, mapped, spurious; ! 124: int ubinfo, rwcommand; ! 125: short unsigned errer, errcs2, errds; ! 126: short cylnow, trksecnow; ! 127: unsigned short wcnow; ! 128: long manow; ! 129: } ! 130: rk7; ! 131: ! 132: struct bb ! 133: { ! 134: short serial, zeros[2], alignpack; ! 135: struct bbtbl ! 136: { ! 137: short bbtcyl, bbtts; ! 138: } ! 139: bbt[MAXBB]; ! 140: } ! 141: rk7bb[NRK7]; ! 142: #define OPENF bbt[MAXBB-1].bbtcyl ! 143: #define LOCKF zeros[0] ! 144: ! 145: #define b_trksec av_back ! 146: #define b_cylin b_resid ! 147: #define nsects(x) x/NBYTES ! 148: ! 149: /* ! 150: */ ! 151: ! 152: rk7open (dev, flag) ! 153: { ! 154: register struct bb *bbp; ! 155: register m; ! 156: ! 157: if ((m = minor (dev)) >= NRK7) ! 158: { ! 159: u.u_error = ENXIO; ! 160: return; ! 161: } ! 162: bbp = &rk7bb[m]; ! 163: debug (1) ("open\n"); ! 164: if (bbp->OPENF != -1) ! 165: { ! 166: bbp->OPENF = 1; ! 167: debug (1|64) ("bs read\n"); ! 168: ! 169: rk7bsbuf.b_flags = B_BUSY | B_READ; ! 170: rk7bsbuf.b_dev = minor (dev); /* major better not matter ! */ ! 171: rk7bsbuf.b_bcount = sizeof (struct bb); ! 172: rk7bsbuf.b_un.b_addr = (caddr_t) bbp; ! 173: rk7bsbuf.b_blkno = BSTBLK; ! 174: rk7bsbuf.b_error = 0; ! 175: rk7strategy (&rk7bsbuf); ! 176: iowait (&rk7bsbuf); ! 177: ! 178: if (rk7bsbuf.b_flags & B_ERROR) ! 179: { ! 180: printf ("rk7: error reading bad sector table!\n"); ! 181: } ! 182: else if (bbp->OPENF != -1) ! 183: { ! 184: printf ("rk7: too many bad sectors, drive %d\n", m); ! 185: bbp->OPENF = -1; ! 186: } ! 187: wakeup (&bbp->OPENF); ! 188: debug (1|64) ("bs read done\n"); ! 189: } ! 190: else ! 191: while (bbp->OPENF != -1) ! 192: sleep (&bbp->OPENF, PSWP); ! 193: } ! 194: ! 195: rk7close (dev, flag) ! 196: { ! 197: debug (1) ("close\n"); ! 198: if (!rk7bb[minor (dev)].LOCKF) ! 199: rk7bb[minor (dev)].OPENF = 0; ! 200: } ! 201: ! 202: rk7strategy (bp) ! 203: register struct buf *bp; ! 204: { ! 205: debug (2) ("strat %s ", bp->b_flags & B_READ ? "r" : "w"); ! 206: if (rk7bb[minor (bp->b_dev)].OPENF == 0) ! 207: { ! 208: rk7open (bp->b_dev, 0); /* in case root or swap is here */ ! 209: rk7bb[minor (bp->b_dev)].LOCKF++; ! 210: debug (32) ("lock-open\n"); ! 211: } ! 212: ! 213: if (bp->b_blkno + nsects (bp->b_bcount) ! 214: > (bp->b_flags & B_READ ? NBLKS : BSBASE)) ! 215: { ! 216: debug (2|32) ("error, blk %d, dev %d\n", ! 217: bp->b_blkno, minor (bp->b_dev)); ! 218: bp->b_flags |= B_ERROR; ! 219: iodone(bp); ! 220: return; ! 221: } ! 222: ! 223: debug (2) ("queue "); ! 224: bp->b_cylin = bp->b_blkno / (NTRKS*NSECTS); ! 225: bp->b_trksec = (struct buf *) ((((bp->b_blkno / NSECTS) % NTRKS) << 8) ! 226: + (bp->b_blkno % NSECTS)); ! 227: ! 228: spl5(); ! 229: disksort (&rk7tab, bp); ! 230: ! 231: if(rk7tab.b_active == IDLE) ! 232: rk7intr(); ! 233: spl0(); ! 234: debug (2) ("end\n"); ! 235: } ! 236: ! 237: /* ! 238: disksort (tabp, bp) ! 239: register struct buf *tabp, bp; ! 240: { ! 241: bp->av_forw = (struct buf *)NULL; ! 242: if(tabp->b_actf == NULL) ! 243: tabp->b_actf = bp; ! 244: else ! 245: tabp->b_actl->av_forw = bp; ! 246: tabp->b_actl = bp; ! 247: } ! 248: */ ! 249: ! 250: /* ! 251: * Interrupt (co)routine ! 252: */ ! 253: ! 254: #define iwait(x) rk7tab.b_active = x; return; case x: ! 255: rk7intr() ! 256: { ! 257: register struct buf *bp; ! 258: ! 259: bp = rk7tab.b_actf; ! 260: switch (rk7tab.b_active) ! 261: { ! 262: case IDLE: ! 263: debug (4) ("intr "); ! 264: if (bp == NULL) ! 265: { ! 266: rk7.spurious++; ! 267: return; ! 268: } ! 269: ! 270: do { /* empty the queue */ ! 271: ! 272: rk7.access++; ! 273: rk7tab.b_errcnt = 0; ! 274: ! 275: do { /* transfer */ ! 276: register short s; ! 277: short rk7map (), ms; ! 278: ! 279: rk7.rwcommand = bp->b_flags & B_READ ! 280: ? (READ|IE|CDT|GO) ! 281: : (WRITE|IE|CDT|GO); ! 282: if (Error) ! 283: { ! 284: debug (8) ("clear "); ! 285: rk7clear (); ! 286: } ! 287: ! 288: RK7ADDR->rkcs2 = minor (bp->b_dev); ! 289: RK7ADDR->rkcs1 = PACKACK|CDT|GO; ! 290: while (RK7ADDR->rkcs1 & GO); ! 291: ! 292: debug (8) ("setup "); ! 293: rk7.ubinfo = ubasetup (bp, 1); ! 294: rk7start ( rk7.rwcommand, ! 295: (short) bp->b_cylin, (short)(long) bp->b_trksec, ! 296: (long) rk7.ubinfo, ! 297: (short) (-(bp->b_bcount>>1))); ! 298: debug (8) ("started "); ! 299: iwait (NORMAL); ! 300: ! 301: debug (8) ("NORMAL "); ! 302: while (RK7ADDR->rker == BSE && (ms = rk7map ()) != -1) ! 303: { /* forwarding */ ! 304: rk7.mapped++; ! 305: debug (8|16) ("mapping "); ! 306: ! 307: rk7clear (); ! 308: ! 309: rk7start (rk7.rwcommand, ! 310: (short) BSCYL, (short) ms, (long) rk7.manow, ! 311: (short) (-(rk7.wcnow > NBYTES/2 ! 312: ? NBYTES/2 : rk7.wcnow))); ! 313: iwait (MAPPED); ! 314: ! 315: debug (8|16) ("mapped\n"); ! 316: if (!Error && rk7.wcnow > NBYTES/2) ! 317: { ! 318: debug (8|16) ("restarting "); ! 319: rk7restart (); ! 320: iwait (RESTART); ! 321: debug (8|16) ("restarted\n"); ! 322: } ! 323: } /* forwarding */ ! 324: ! 325: if (Error) ! 326: { ! 327: rk7.errer = RK7ADDR->rker; ! 328: rk7.errcs2 = RK7ADDR->rkcs2; ! 329: rk7.errds = RK7ADDR->rkds; ! 330: } ! 331: debug (8) (Error ? "error\n" : "free "); ! 332: ubafree (rk7.ubinfo); ! 333: } /* transfer */ ! 334: while (Error && ++rk7tab.b_errcnt != RETRIES); ! 335: ! 336: if (rk7tab.b_errcnt != 0) ! 337: rk7errs (bp); ! 338: ! 339: debug (8) ("next\n"); ! 340: bp->b_resid = 0; ! 341: rk7tab.b_actf = bp->av_forw; ! 342: iodone (bp); ! 343: ! 344: } /* empty the queue */ ! 345: while ((bp = rk7tab.b_actf) != NULL); ! 346: ! 347: rk7tab.b_active = IDLE; ! 348: debug (4) ("exit\n"); ! 349: return; ! 350: } ! 351: } ! 352: ! 353: rk7clear () ! 354: { ! 355: register drive; ! 356: ! 357: drive = RK7ADDR->rkcs2 & 07; ! 358: RK7ADDR->rkcs1 = CCLR; ! 359: RK7ADDR->rkcs2 = drive; ! 360: RK7ADDR->rkcs1 = DRCLR|CDT|GO; ! 361: while ((RK7ADDR->rkcs1 & RDY) == 0); ! 362: } ! 363: ! 364: rk7start (rwcommand, cyl, tsect, mem, wc) ! 365: short cyl, tsect, wc; ! 366: long mem; ! 367: { ! 368: RK7ADDR->rkdc = cyl; ! 369: RK7ADDR->rkda = tsect; ! 370: RK7ADDR->rkba = mem; ! 371: RK7ADDR->rkwc = wc; ! 372: RK7ADDR->rkcs1 = ((mem >> 8) & BA1617) | rwcommand; ! 373: } ! 374: ! 375: short rk7map () ! 376: { ! 377: register struct bbtbl *bbp; ! 378: register i; ! 379: ! 380: rk7.wcnow = -RK7ADDR->rkwc; ! 381: rk7.cylnow = RK7ADDR->rkdc; ! 382: rk7.trksecnow = RK7ADDR->rkda; ! 383: rk7.manow = (((long)(RK7ADDR->rkcs1 & BA1617)) << 8) + RK7ADDR->rkba; ! 384: ! 385: for (bbp = rk7bb[RK7ADDR->rkcs2 & 07].bbt, i = 0; ! 386: bbp->bbtcyl != -1 && ! 387: (bbp->bbtcyl != rk7.cylnow || bbp->bbtts != rk7.trksecnow); ! 388: bbp++, i++); ! 389: return (bbp->bbtcyl == -1 ? -1 : i /* trk & sec */); ! 390: } ! 391: ! 392: rk7restart () ! 393: { ! 394: register short ts; ! 395: ! 396: ts = rk7.trksecnow; ! 397: if ((++ts & 0377) == NSECTS) ! 398: if (((ts += (1<<8) - NSECTS) >> 8) == NTRKS) ! 399: { ! 400: ts = 0; ! 401: rk7.cylnow++; ! 402: } ! 403: rk7start (rk7.rwcommand, (short) rk7.cylnow, (short) ts, ! 404: (long) rk7.manow + NBYTES, (short) (-(rk7.wcnow - NBYTES/2))); ! 405: } ! 406: ! 407: rk7errs (bp) ! 408: register struct buf *bp; ! 409: { ! 410: register nerr; ! 411: ! 412: nerr = rk7tab.b_errcnt; ! 413: rk7.retries += nerr; ! 414: if (nerr == RETRIES) ! 415: { ! 416: bp->b_flags |= B_ERROR; ! 417: rk7.errors++; ! 418: printf ("Hard rk7 "); ! 419: } ! 420: else ! 421: printf ("%d * rk7 ", nerr); ! 422: deverror (bp, rk7.errer, rk7.errcs2); ! 423: printf ("ds %X\n", rk7.errds); ! 424: while (nerr == RETRIES && (rk7debug & 1024)); ! 425: } ! 426: ! 427: rk7read(dev) ! 428: dev_t dev; ! 429: { ! 430: ! 431: physio(rk7strategy, &rrk7buf, dev, B_READ, minphys); ! 432: } ! 433: ! 434: rk7write(dev) ! 435: dev_t dev; ! 436: { ! 437: ! 438: physio(rk7strategy, &rrk7buf, dev, B_WRITE, minphys); ! 439: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.