|
|
1.1 ! root 1: /* rl.c 6.1 83/07/29 */ ! 2: ! 3: #include "rl.h" ! 4: #if NRL > 0 ! 5: /* ! 6: * UNIBUS RL02 disk driver ! 7: */ ! 8: #include "../machine/pte.h" ! 9: ! 10: #include "../h/param.h" ! 11: #include "../h/systm.h" ! 12: #include "../h/dk.h" ! 13: #include "../h/dkbad.h" ! 14: #include "../h/buf.h" ! 15: #include "../h/conf.h" ! 16: #include "../h/dir.h" ! 17: #include "../h/user.h" ! 18: #include "../h/map.h" ! 19: #include "../h/vm.h" ! 20: #include "../h/cmap.h" ! 21: #include "../h/uio.h" ! 22: #include "../h/kernel.h" ! 23: ! 24: #include "../vax/cpu.h" ! 25: #include "../vax/nexus.h" ! 26: #include "../vaxuba/ubavar.h" ! 27: #include "../vaxuba/ubareg.h" ! 28: #include "../vaxuba/rlreg.h" ! 29: ! 30: /* Pending Controller items and statistics */ ! 31: struct rl_softc { ! 32: int rl_softas; /* Attention sumary, (seeks pending) */ ! 33: int rl_ndrive; /* Number of drives on controller */ ! 34: int rl_wticks; /* Monitor time for function */ ! 35: } rl_softc[NHL]; ! 36: ! 37: /* ! 38: * State of controller from last transfer. ! 39: * Since only one transfer can be done at a time per ! 40: * controller, only allocate one for each controller. ! 41: */ ! 42: struct rl_stat { ! 43: short rl_cyl[4]; /* Current cylinder for each drive */ ! 44: short rl_dn; /* drive number currently transferring */ ! 45: short rl_cylnhd; /* current cylinder and head of transfer */ ! 46: u_short rl_bleft; /* bytes left to transfer */ ! 47: u_short rl_bpart; /* bytes transferred */ ! 48: } rl_stat[NHL]; ! 49: ! 50: /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */ ! 51: /* Last cylinder not used. Saved for Bad Sector File */ ! 52: struct size { ! 53: daddr_t nblocks; ! 54: int cyloff; ! 55: } rl02_sizes[8] = { ! 56: 15884, 0, /* A=cyl 0 thru 397 */ ! 57: 4520, 398, /* B=cyl 398 thru 510 */ ! 58: -1, 0, /* C=cyl 0 thru 511 */ ! 59: 4520, 398, /* D=cyl 398 thru 510 */ ! 60: 0, 0, /* F= Not Defined */ ! 61: 20440, 0, /* G=cyl 0 thru 510 */ ! 62: 0, 0, /* H= Not Defined */ ! 63: }; ! 64: /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */ ! 65: ! 66: int rlprobe(), rlslave(), rlattach(), rldgo(), rlintr(); ! 67: struct uba_ctlr *rlminfo[NHL]; ! 68: struct uba_device *rldinfo[NRL]; ! 69: struct uba_device *rlip[NHL][4]; ! 70: ! 71: /* RL02 driver structure */ ! 72: u_short rlstd[] = { 0174400 }; ! 73: struct uba_driver hldriver = ! 74: { rlprobe, rlslave, rlattach, rldgo, rlstd, "rl", rldinfo, "hl", rlminfo }; ! 75: ! 76: /* User table per controller */ ! 77: struct buf rlutab[NRL]; ! 78: ! 79: /* RL02 drive structure */ ! 80: struct RL02 { ! 81: short nbpt; /* Number of 512 byte blocks/track */ ! 82: short ntrak; ! 83: short nbpc; /* Number of 512 byte blocks/cylinder */ ! 84: short ncyl; ! 85: short btrak; /* Number of bytes/track */ ! 86: struct size *sizes; ! 87: } rl02 = { ! 88: 20, 2, 40, 512, 20*512, rl02_sizes /* rl02/DEC*/ ! 89: }; ! 90: ! 91: struct buf rrlbuf[NRL]; ! 92: ! 93: #define b_cylin b_resid /* Last seek as CYL<<1 | HD */ ! 94: ! 95: #ifdef INTRLVE ! 96: daddr_t dkblock(); ! 97: #endif ! 98: ! 99: int rlwstart, rlwatch(); /* Have started guardian */ ! 100: ! 101: /* Check that controller exists */ ! 102: /*ARGSUSED*/ ! 103: rlprobe(reg) ! 104: caddr_t reg; ! 105: { ! 106: register int br, cvec; ! 107: ! 108: #ifdef lint ! 109: br = 0; cvec = br; br = cvec; ! 110: rlintr(0); ! 111: #endif ! 112: ((struct rldevice *)reg)->rlcs = RL_IE | RL_NOOP; ! 113: DELAY(10); ! 114: ((struct rldevice *)reg)->rlcs &= ~RL_IE; ! 115: return (sizeof (struct rldevice)); ! 116: } ! 117: ! 118: rlslave(ui, reg) ! 119: struct uba_device *ui; ! 120: caddr_t reg; ! 121: { ! 122: register struct rldevice *rladdr = (struct rldevice *)reg; ! 123: short ctr = 0; ! 124: ! 125: /* ! 126: * DEC reports that: ! 127: * For some unknown reason the RL02 (seems to be only drive 1) ! 128: * does not return a valid drive status the first time that a ! 129: * GET STATUS request is issued for the drive, in fact it can ! 130: * take up to three or more GET STATUS requests to obtain the ! 131: * correct status. ! 132: * In order to overcome this, the driver has been modified to ! 133: * issue a GET STATUS request and validate the drive status ! 134: * returned. If a valid status is not returned after eight ! 135: * attempts, then an error message is printed. ! 136: */ ! 137: do { ! 138: rladdr->rlda.getstat = RL_RESET; ! 139: rladdr->rlcs = (ui->ui_slave <<8) | RL_GETSTAT; /* Get status*/ ! 140: rlwait(rladdr); ! 141: } while ((rladdr->rlmp.getstat&RLMP_STATUS) != RLMP_STATOK && ++ctr<8); ! 142: if ((rladdr->rlcs & RL_DE) || (ctr >= 8)) ! 143: return (0); ! 144: if ((rladdr->rlmp.getstat & RLMP_DT) == 0 ) { ! 145: printf("rl%d: rl01's not supported\n", ui->ui_slave); ! 146: return(0); ! 147: } ! 148: return (1); ! 149: } ! 150: ! 151: rlattach(ui) ! 152: register struct uba_device *ui; ! 153: { ! 154: register struct rldevice *rladdr; ! 155: ! 156: if (rlwstart == 0) { ! 157: timeout(rlwatch, (caddr_t)0, hz); ! 158: rlwstart++; ! 159: } ! 160: /* Initialize iostat values */ ! 161: if (ui->ui_dk >= 0) ! 162: dk_mspw[ui->ui_dk] = .000003906; /* 16bit transfer time? */ ! 163: rlip[ui->ui_ctlr][ui->ui_slave] = ui; ! 164: rl_softc[ui->ui_ctlr].rl_ndrive++; ! 165: rladdr = (struct rldevice *)ui->ui_addr; ! 166: /* reset controller */ ! 167: rladdr->rlda.getstat = RL_RESET; /* SHOULD BE REPEATED? */ ! 168: rladdr->rlcs = (ui->ui_slave << 8) | RL_GETSTAT; /* Reset DE bit */ ! 169: rlwait(rladdr); ! 170: /* determine disk posistion */ ! 171: rladdr->rlcs = (ui->ui_slave << 8) | RL_RHDR; ! 172: rlwait(rladdr); ! 173: /* save disk drive posistion */ ! 174: rl_stat[ui->ui_ctlr].rl_cyl[ui->ui_slave] = ! 175: (rladdr->rlmp.readhdr & 0177700) >> 6; ! 176: rl_stat[ui->ui_ctlr].rl_dn = -1; ! 177: } ! 178: ! 179: rlopen(dev) ! 180: dev_t dev; ! 181: { ! 182: register int unit = minor(dev) >> 3; ! 183: register struct uba_device *ui; ! 184: ! 185: if (unit >= NRL || (ui = rldinfo[unit]) == 0 || ui->ui_alive == 0) ! 186: return (ENXIO); ! 187: return (0); ! 188: } ! 189: ! 190: rlstrategy(bp) ! 191: register struct buf *bp; ! 192: { ! 193: register struct uba_device *ui; ! 194: register int drive; ! 195: register struct buf *dp; ! 196: int partition = minor(bp->b_dev) & 07, s; ! 197: long bn, sz; ! 198: ! 199: sz = (bp->b_bcount+511) >> 9; ! 200: drive = dkunit(bp); ! 201: if (drive >= NRL) ! 202: goto bad; ! 203: ui = rldinfo[drive]; ! 204: if (ui == 0 || ui->ui_alive == 0) ! 205: goto bad; ! 206: if (bp->b_blkno < 0 || ! 207: (bn = dkblock(bp))+sz > rl02.sizes[partition].nblocks) ! 208: goto bad; ! 209: /* bn is in 512 byte block size */ ! 210: bp->b_cylin = bn/rl02.nbpc + rl02.sizes[partition].cyloff; ! 211: s = spl5(); ! 212: dp = &rlutab[ui->ui_unit]; ! 213: disksort(dp, bp); ! 214: if (dp->b_active == 0) { ! 215: rlustart(ui); ! 216: bp = &ui->ui_mi->um_tab; ! 217: if (bp->b_actf && bp->b_active == 0) ! 218: rlstart(ui->ui_mi); ! 219: } ! 220: splx(s); ! 221: return; ! 222: ! 223: bad: ! 224: bp->b_flags |= B_ERROR; ! 225: iodone(bp); ! 226: return; ! 227: } ! 228: ! 229: /* ! 230: * Unit start routine. ! 231: * Seek the drive to be where the data is ! 232: * and then generate another interrupt ! 233: * to actually start the transfer. ! 234: */ ! 235: rlustart(ui) ! 236: register struct uba_device *ui; ! 237: { ! 238: register struct buf *bp, *dp; ! 239: register struct uba_ctlr *um; ! 240: register struct rldevice *rladdr; ! 241: daddr_t bn; ! 242: short hd, diff; ! 243: ! 244: if (ui == 0) ! 245: return; ! 246: um = ui->ui_mi; ! 247: dk_busy &= ~(1 << ui->ui_dk); ! 248: dp = &rlutab[ui->ui_unit]; ! 249: if ((bp = dp->b_actf) == NULL) ! 250: return; ! 251: /* ! 252: * If the controller is active, just remember ! 253: * that this device has to be positioned... ! 254: */ ! 255: if (um->um_tab.b_active) { ! 256: rl_softc[um->um_ctlr].rl_softas |= 1<<ui->ui_slave; ! 257: return; ! 258: } ! 259: /* ! 260: * If we have already positioned this drive, ! 261: * then just put it on the ready queue. ! 262: */ ! 263: if (dp->b_active) ! 264: goto done; ! 265: dp->b_active = 1; /* positioning drive */ ! 266: rladdr = (struct rldevice *)um->um_addr; ! 267: ! 268: /* ! 269: * Figure out where this transfer is going to ! 270: * and see if we are seeked correctly. ! 271: */ ! 272: bn = dkblock(bp); /* Block # desired */ ! 273: /* ! 274: * Map 512 byte logical disk blocks ! 275: * to 256 byte sectors (rl02's are stupid). ! 276: */ ! 277: hd = (bn / rl02.nbpt) & 1; /* Get head required */ ! 278: diff = (rl_stat[um->um_ctlr].rl_cyl[ui->ui_slave] >> 1) - bp->b_cylin; ! 279: if ( diff == 0 && (rl_stat[um->um_ctlr].rl_cyl[ui->ui_slave] & 1) == hd) ! 280: goto done; /* on cylinder and head */ ! 281: /* ! 282: * Not at correct position. ! 283: */ ! 284: rl_stat[um->um_ctlr].rl_cyl[ui->ui_slave] = (bp->b_cylin << 1) | hd; ! 285: if (diff < 0) ! 286: rladdr->rlda.seek = -diff << 7 | RLDA_HGH | hd << 4; ! 287: else ! 288: rladdr->rlda.seek = diff << 7 | RLDA_LOW | hd << 4; ! 289: rladdr->rlcs = (ui->ui_slave << 8) | RL_SEEK; ! 290: ! 291: /* ! 292: * Mark unit busy for iostat. ! 293: */ ! 294: if (ui->ui_dk >= 0) { ! 295: dk_busy |= 1<<ui->ui_dk; ! 296: dk_seek[ui->ui_dk]++; ! 297: } ! 298: rlwait(rladdr); ! 299: done: ! 300: /* ! 301: * Device is ready to go. ! 302: * Put it on the ready queue for the controller ! 303: * (unless its already there.) ! 304: */ ! 305: if (dp->b_active != 2) { ! 306: dp->b_forw = NULL; ! 307: if (um->um_tab.b_actf == NULL) ! 308: um->um_tab.b_actf = dp; ! 309: else ! 310: um->um_tab.b_actl->b_forw = dp; ! 311: um->um_tab.b_actl = dp; ! 312: dp->b_active = 2; /* Request on ready queue */ ! 313: } ! 314: } ! 315: ! 316: /* ! 317: * Start up a transfer on a drive. ! 318: */ ! 319: rlstart(um) ! 320: register struct uba_ctlr *um; ! 321: { ! 322: register struct buf *bp, *dp; ! 323: register struct uba_device *ui; ! 324: register struct rldevice *rladdr; ! 325: register struct rl_stat *st = &rl_stat[um->um_ctlr]; ! 326: daddr_t bn; ! 327: short sn, cyl, cmd; ! 328: ! 329: loop: ! 330: if ((dp = um->um_tab.b_actf) == NULL) { ! 331: st->rl_dn = -1; ! 332: st->rl_cylnhd = 0; ! 333: st->rl_bleft = 0; ! 334: st->rl_bpart = 0; ! 335: return; ! 336: } ! 337: if ((bp = dp->b_actf) == NULL) { ! 338: um->um_tab.b_actf = dp->b_forw; ! 339: goto loop; ! 340: } ! 341: /* ! 342: * Mark controller busy, and ! 343: * determine destination. ! 344: */ ! 345: um->um_tab.b_active++; ! 346: ui = rldinfo[dkunit(bp)]; /* Controller */ ! 347: bn = dkblock(bp); /* 512 byte Block number */ ! 348: cyl = bp->b_cylin << 1; /* Cylinder */ ! 349: cyl |= (bn / rl02.nbpt) & 1; /* Get head required */ ! 350: sn = (bn % rl02.nbpt) << 1; /* Sector number */ ! 351: rladdr = (struct rldevice *)ui->ui_addr; ! 352: rlwait(rladdr); ! 353: rladdr->rlda.rw = cyl<<6 | sn; ! 354: /* save away current transfers drive status */ ! 355: st->rl_dn = ui->ui_slave; ! 356: st->rl_cylnhd = cyl; ! 357: st->rl_bleft = bp->b_bcount; ! 358: st->rl_bpart = rl02.btrak - (sn * NRLBPSC); ! 359: /* ! 360: * RL02 must seek between cylinders and between tracks, ! 361: * determine maximum data transfer at this time. ! 362: */ ! 363: if (st->rl_bleft < st->rl_bpart) ! 364: st->rl_bpart = st->rl_bleft; ! 365: rladdr->rlmp.rw = -(st->rl_bpart >> 1); ! 366: if (bp->b_flags & B_READ) ! 367: cmd = RL_IE | RL_READ | (ui->ui_slave << 8); ! 368: else ! 369: cmd = RL_IE | RL_WRITE | (ui->ui_slave << 8); ! 370: um->um_cmd = cmd; ! 371: (void) ubago(ui); ! 372: } ! 373: ! 374: rldgo(um) ! 375: register struct uba_ctlr *um; ! 376: { ! 377: register struct rldevice *rladdr = (struct rldevice *)um->um_addr; ! 378: ! 379: rladdr->rlba = um->um_ubinfo; ! 380: rladdr->rlcs = um->um_cmd|((um->um_ubinfo>>12)&RL_BAE); ! 381: } ! 382: ! 383: /* ! 384: * Handle a disk interrupt. ! 385: */ ! 386: rlintr(rl21) ! 387: register rl21; ! 388: { ! 389: register struct buf *bp, *dp; ! 390: register struct uba_ctlr *um = rlminfo[rl21]; ! 391: register struct uba_device *ui; ! 392: register struct rldevice *rladdr = (struct rldevice *)um->um_addr; ! 393: register unit; ! 394: struct rl_softc *rl = &rl_softc[um->um_ctlr]; ! 395: struct rl_stat *st = &rl_stat[um->um_ctlr]; ! 396: int as = rl->rl_softas, status; ! 397: ! 398: rl->rl_wticks = 0; ! 399: rl->rl_softas = 0; ! 400: dp = um->um_tab.b_actf; ! 401: bp = dp->b_actf; ! 402: ui = rldinfo[dkunit(bp)]; ! 403: dk_busy &= ~(1 << ui->ui_dk); ! 404: ! 405: /* ! 406: * Check for and process errors on ! 407: * either the drive or the controller. ! 408: */ ! 409: if (rladdr->rlcs & RL_ERR) { ! 410: u_short err; ! 411: rlwait(rladdr); ! 412: err = rladdr->rlcs; ! 413: /* get staus and reset controller */ ! 414: rladdr->rlda.getstat = RL_GSTAT; ! 415: rladdr->rlcs = (ui->ui_slave << 8) | RL_GETSTAT; ! 416: rlwait(rladdr); ! 417: status = rladdr->rlmp.getstat; ! 418: /* reset drive */ ! 419: rladdr->rlda.getstat = RL_RESET; ! 420: rladdr->rlcs = (ui->ui_slave <<8) | RL_GETSTAT; /* Get status*/ ! 421: rlwait(rladdr); ! 422: if ((status & RLMP_WL) == RLMP_WL) { ! 423: /* ! 424: * Give up on write protected devices ! 425: * immediately. ! 426: */ ! 427: printf("rl%d: write protected\n", dkunit(bp)); ! 428: bp->b_flags |= B_ERROR; ! 429: } else if (++um->um_tab.b_errcnt > 10) { ! 430: /* ! 431: * After 10 retries give up. ! 432: */ ! 433: harderr(bp, "rl"); ! 434: printf("cs=%b mp=%b\n", err, RLCS_BITS, ! 435: status, RLER_BITS); ! 436: bp->b_flags |= B_ERROR; ! 437: } else ! 438: um->um_tab.b_active = 0; /* force retry */ ! 439: /* determine disk position */ ! 440: rladdr->rlcs = (ui->ui_slave << 8) | RL_RHDR; ! 441: rlwait(rladdr); ! 442: /* save disk drive position */ ! 443: st->rl_cyl[ui->ui_slave] = ! 444: (rladdr->rlmp.readhdr & 0177700) >> 6; ! 445: } ! 446: /* ! 447: * If still ``active'', then don't need any more retries. ! 448: */ ! 449: if (um->um_tab.b_active) { ! 450: /* RL02 check if more data from previous request */ ! 451: if ((bp->b_flags & B_ERROR) == 0 && ! 452: (int)(st->rl_bleft -= st->rl_bpart) > 0) { ! 453: /* ! 454: * The following code was modeled from the rk07 ! 455: * driver when an ECC error occured. It has to ! 456: * fix the bits then restart the transfer which is ! 457: * what we have to do (restart transfer). ! 458: */ ! 459: int reg, npf, o, cmd, ubaddr, diff, head; ! 460: ! 461: /* seek to next head/track */ ! 462: /* increment head and/or cylinder */ ! 463: st->rl_cylnhd++; ! 464: diff = (st->rl_cyl[ui->ui_slave] >> 1) - ! 465: (st->rl_cylnhd >> 1); ! 466: st->rl_cyl[ui->ui_slave] = st->rl_cylnhd; ! 467: head = st->rl_cylnhd & 1; ! 468: rlwait(rladdr); ! 469: if (diff < 0) ! 470: rladdr->rlda.seek = ! 471: -diff << 7 | RLDA_HGH | head << 4; ! 472: else ! 473: rladdr->rlda.seek = ! 474: diff << 7 | RLDA_LOW | head << 4; ! 475: rladdr->rlcs = (ui->ui_slave << 8) | RL_SEEK; ! 476: npf = btop( bp->b_bcount - st->rl_bleft ); ! 477: reg = btop(um->um_ubinfo&0x3ffff) + npf; ! 478: o = (int)bp->b_un.b_addr & PGOFSET; ! 479: ubapurge(um); ! 480: um->um_tab.b_active++; ! 481: rlwait(rladdr); ! 482: rladdr->rlda.rw = st->rl_cylnhd << 6; ! 483: if (st->rl_bleft < (st->rl_bpart = rl02.btrak)) ! 484: st->rl_bpart = st->rl_bleft; ! 485: rladdr->rlmp.rw = -(st->rl_bpart >> 1); ! 486: cmd = (bp->b_flags&B_READ ? RL_READ : RL_WRITE) | ! 487: RL_IE | (ui->ui_slave << 8); ! 488: ubaddr = (int)ptob(reg) + o; ! 489: cmd |= ((ubaddr >> 12) & RL_BAE); ! 490: rladdr->rlba = ubaddr; ! 491: rladdr->rlcs = cmd; ! 492: return; ! 493: } ! 494: um->um_tab.b_active = 0; ! 495: um->um_tab.b_errcnt = 0; ! 496: dp->b_active = 0; ! 497: dp->b_errcnt = 0; ! 498: /* "b_resid" words remaining after error */ ! 499: bp->b_resid = st->rl_bleft; ! 500: um->um_tab.b_actf = dp->b_forw; ! 501: dp->b_actf = bp->av_forw; ! 502: st->rl_dn = -1; ! 503: st->rl_bpart = st->rl_bleft = 0; ! 504: iodone(bp); ! 505: /* ! 506: * If this unit has more work to do, ! 507: * then start it up right away. ! 508: */ ! 509: if (dp->b_actf) ! 510: rlustart(ui); ! 511: as &= ~(1<<ui->ui_slave); ! 512: } else ! 513: as |= (1<<ui->ui_slave); ! 514: ubadone(um); ! 515: /* reset state info */ ! 516: st->rl_dn = -1; ! 517: st->rl_cylnhd = st->rl_bpart = st->rl_bleft = 0; ! 518: /* ! 519: * Process other units which need attention. ! 520: * For each unit which needs attention, call ! 521: * the unit start routine to place the slave ! 522: * on the controller device queue. ! 523: */ ! 524: while (unit = ffs(as)) { ! 525: unit--; /* was 1 origin */ ! 526: as &= ~(1<<unit); ! 527: rlustart(rlip[rl21][unit]); ! 528: } ! 529: /* ! 530: * If the controller is not transferring, but ! 531: * there are devices ready to transfer, start ! 532: * the controller. ! 533: */ ! 534: if (um->um_tab.b_actf && um->um_tab.b_active == 0) ! 535: rlstart(um); ! 536: } ! 537: ! 538: rlwait(rladdr) ! 539: register struct rldevice *rladdr; ! 540: { ! 541: ! 542: while ((rladdr->rlcs & RL_CRDY) == 0) ! 543: ; ! 544: } ! 545: ! 546: rlread(dev, uio) ! 547: dev_t dev; ! 548: struct uio *uio; ! 549: { ! 550: register int unit = minor(dev) >> 3; ! 551: ! 552: if (unit >= NRL) ! 553: return (ENXIO); ! 554: return (physio(rlstrategy, &rrlbuf[unit], dev, B_READ, minphys, uio)); ! 555: } ! 556: ! 557: rlwrite(dev, uio) ! 558: dev_t dev; ! 559: struct uio *uio; ! 560: { ! 561: register int unit = minor(dev) >> 3; ! 562: ! 563: if (unit >= NRL) ! 564: return (ENXIO); ! 565: return (physio(rlstrategy, &rrlbuf[unit], dev, B_WRITE, minphys, uio)); ! 566: } ! 567: ! 568: /* ! 569: * Reset driver after UBA init. ! 570: * Cancel software state of all pending transfers ! 571: * and restart all units and the controller. ! 572: */ ! 573: rlreset(uban) ! 574: int uban; ! 575: { ! 576: register struct uba_ctlr *um; ! 577: register struct uba_device *ui; ! 578: register struct rldevice *rladdr; ! 579: register struct rl_stat *st; ! 580: register int rl21, unit; ! 581: ! 582: for (rl21 = 0; rl21 < NHL; rl21++) { ! 583: if ((um = rlminfo[rl21]) == 0 || um->um_ubanum != uban || ! 584: um->um_alive == 0) ! 585: continue; ! 586: printf(" hl%d", rl21); ! 587: rladdr = (struct rldevice *)um->um_addr; ! 588: st = &rl_stat[rl21]; ! 589: um->um_tab.b_active = 0; ! 590: um->um_tab.b_actf = um->um_tab.b_actl = 0; ! 591: if (um->um_ubinfo) { ! 592: printf("<%d>", (um->um_ubinfo>>28)&0xf); ! 593: um->um_ubinfo = 0; ! 594: } ! 595: /* reset controller */ ! 596: st->rl_dn = -1; ! 597: st->rl_cylnhd = 0; ! 598: st->rl_bleft = 0; ! 599: st->rl_bpart = 0; ! 600: rlwait(rladdr); ! 601: for (unit = 0; unit < NRL; unit++) { ! 602: rladdr->rlcs = (unit << 8) | RL_GETSTAT; ! 603: rlwait(rladdr); ! 604: /* Determine disk posistion */ ! 605: rladdr->rlcs = (unit << 8) | RL_RHDR; ! 606: rlwait(rladdr); ! 607: /* save disk drive posistion */ ! 608: st->rl_cyl[unit] = ! 609: (rladdr->rlmp.readhdr & 0177700) >> 6; ! 610: if ((ui = rldinfo[unit]) == 0) ! 611: continue; ! 612: if (ui->ui_alive == 0 || ui->ui_mi != um) ! 613: continue; ! 614: rlutab[unit].b_active = 0; ! 615: rlustart(ui); ! 616: } ! 617: rlstart(um); ! 618: } ! 619: } ! 620: ! 621: /* ! 622: * Wake up every second and if an interrupt is pending ! 623: * but nothing has happened increment a counter. ! 624: * If nothing happens for 20 seconds, reset the UNIBUS ! 625: * and begin anew. ! 626: */ ! 627: rlwatch() ! 628: { ! 629: register struct uba_ctlr *um; ! 630: register rl21, unit; ! 631: register struct rl_softc *rl; ! 632: ! 633: timeout(rlwatch, (caddr_t)0, hz); ! 634: for (rl21 = 0; rl21 < NHL; rl21++) { ! 635: um = rlminfo[rl21]; ! 636: if (um == 0 || um->um_alive == 0) ! 637: continue; ! 638: rl = &rl_softc[rl21]; ! 639: if (um->um_tab.b_active == 0) { ! 640: for (unit = 0; unit < NRL; unit++) ! 641: if (rlutab[unit].b_active && ! 642: rldinfo[unit]->ui_mi == um) ! 643: goto active; ! 644: rl->rl_wticks = 0; ! 645: continue; ! 646: } ! 647: active: ! 648: rl->rl_wticks++; ! 649: if (rl->rl_wticks >= 20) { ! 650: rl->rl_wticks = 0; ! 651: printf("hl%d: lost interrupt\n", rl21); ! 652: ubareset(um->um_ubanum); ! 653: } ! 654: } ! 655: } ! 656: ! 657: /*ARGSUSED*/ ! 658: rldump(dev) ! 659: dev_t dev; ! 660: { ! 661: ! 662: /* don't think there is room on swap for it anyway. */ ! 663: } ! 664: ! 665: rlsize(dev) ! 666: dev_t dev; ! 667: { ! 668: register int unit = minor(dev) >> 3; ! 669: register struct uba_device *ui; ! 670: ! 671: if (unit >= NRL || (ui = rldinfo[unit]) == 0 || ui->ui_alive == 0) ! 672: return (-1); ! 673: return (rl02.sizes[minor(dev) & 07].nblocks); ! 674: } ! 675: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.