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