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