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

Defined functions

rlattach defined in line 157; used 2 times
rldgo defined in line 391; used 2 times
rldump defined in line 675; never used
rlintr defined in line 403; used 3 times
rlopen defined in line 185; never used
rlprobe defined in line 108; used 2 times
rlread defined in line 563; never used
rlreset defined in line 590; never used
rlsize defined in line 682; never used
rlslave defined in line 123; used 2 times
rlstart defined in line 336; used 3 times
rlstrategy defined in line 196; used 2 times
rlustart defined in line 252; used 4 times
rlwait defined in line 555; used 14 times
rlwatch defined in line 644; used 3 times
rlwrite defined in line 574; never used

Defined variables

hldriver defined in line 82; used 4 times
rl02 defined in line 96; used 10 times
rl02_sizes defined in line 63; used 1 times
  • in line 97
rl_softc defined in line 41; used 4 times
rl_stat defined in line 54; used 8 times
rldinfo defined in line 77; used 8 times
rlip defined in line 78; used 2 times
rlminfo defined in line 76; used 4 times
rlstd defined in line 81; used 1 times
  • in line 83
rlutab defined in line 86; used 4 times
rlwstart defined in line 104; used 2 times
rrlbuf defined in line 100; used 2 times

Defined struct's

RL02 defined in line 89; never used
rl_softc defined in line 37; used 4 times
rl_stat defined in line 48; used 6 times
size defined in line 60; used 2 times
  • in line 95(2)

Defined macros

b_cylin defined in line 102; used 4 times
rlunit defined in line 56; used 8 times
Last modified: 1986-06-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2399
Valid CSS Valid XHTML 1.0 Strict