1: /*
   2:  *	SCCS id	@(#)rm.c	2.1 (Berkeley)	9/1/83
   3:  */
   4: 
   5: /*
   6:  *	RJM02/RWM03 disk driver
   7:  *
   8:  *	For simplicity we use hpreg.h instead of an rmreg.h.  The bits
   9:  *	are the same.  Only the register names have been changed to
  10:  *	protect the innocent.
  11:  */
  12: 
  13: #include "rm.h"
  14: #if NRM > 0
  15: #include "param.h"
  16: #include <sys/systm.h>
  17: #include <sys/buf.h>
  18: #include <sys/conf.h>
  19: #include <sys/dir.h>
  20: #include <sys/user.h>
  21: #include <sys/hpreg.h>
  22: #ifndef INTRLVE
  23: #include <sys/inline.h>
  24: #endif
  25: #ifdef  RM_DUMP
  26: #include <sys/seg.h>
  27: #endif
  28: #include <sys/uba.h>
  29: 
  30: extern  struct  hpdevice *RMADDR;
  31: extern  struct  size rm_sizes[];
  32: 
  33: int rm_offset[] =
  34: {
  35:     HPOF_P400,  HPOF_M400,  HPOF_P400,  HPOF_M400,
  36:     HPOF_P800,  HPOF_M800,  HPOF_P800,  HPOF_M800,
  37:     HPOF_P1200, HPOF_M1200, HPOF_P1200, HPOF_M1200,
  38:     0,      0,      0,      0
  39: };
  40: 
  41: #define RM_NSECT    32
  42: #define RM_NTRAC    5
  43: #define RM_SDIST    2
  44: #define RM_RDIST    6
  45: 
  46: struct  buf rmtab;
  47: #ifdef  UCB_DBUFS
  48: struct  buf rrmbuf[NRM];
  49: #else
  50: struct  buf rrmbuf;
  51: #endif
  52: #if NRM > 1
  53: struct  buf rmutab[NRM];
  54: #endif
  55: 
  56: #ifdef  INTRLVE
  57: extern  daddr_t dkblock();
  58: #endif
  59: #if NRM > 1
  60: int rmcc[NRM];  /* Current cylinder */
  61: #endif
  62: 
  63: void
  64: rmroot()
  65: {
  66:     rmattach(RMADDR, 0);
  67: }
  68: 
  69: rmattach(addr, unit)
  70: register struct hpdevice *addr;
  71: {
  72:     if (unit != 0)
  73:         return(0);
  74:     if ((addr != (struct hpdevice *) NULL) && (fioword(addr) != -1)) {
  75:         RMADDR = addr;
  76: #if PDP11 == 70 || PDP11 == GENERIC
  77:         if (fioword(&(addr->hpbae)) != -1)
  78:             rmtab.b_flags |= B_RH70;
  79: #endif
  80:         return(1);
  81:     }
  82:     RMADDR = (struct hpdevice *) NULL;
  83:     return(0);
  84: }
  85: 
  86: rmstrategy(bp)
  87: register struct buf *bp;
  88: {
  89:     register struct buf *dp;
  90:     register unit;
  91:     long    bn;
  92: 
  93:     unit = minor(bp->b_dev) & 077;
  94:     if (unit >= (NRM << 3) || (RMADDR == (struct hpdevice *) NULL)) {
  95:         bp->b_error = ENXIO;
  96:         goto errexit;
  97:     }
  98:     if (bp->b_blkno < 0 ||
  99:         (bn = dkblock(bp)) + (long) ((bp->b_bcount + 511) >> 9)
 100:         > rm_sizes[unit & 07].nblocks) {
 101:         bp->b_error = EINVAL;
 102: errexit:
 103:         bp->b_flags |= B_ERROR;
 104:         iodone(bp);
 105:         return;
 106:     }
 107: #ifdef  UNIBUS_MAP
 108:     if ((rmtab.b_flags & B_RH70) == 0)
 109:         mapalloc(bp);
 110: #endif
 111:     bp->b_cylin = bn / (RM_NSECT * RM_NTRAC) + rm_sizes[unit & 07].cyloff;
 112:     unit = dkunit(bp);
 113: #if NRM > 1
 114:     dp = &rmutab[unit];
 115: #else
 116:     dp = &rmtab;
 117: #endif
 118:     (void) _spl5();
 119:     disksort(dp, bp);
 120:     if (dp->b_active == 0) {
 121: #if NRM > 1
 122:         rmustart(unit);
 123:         if (rmtab.b_active == 0)
 124:             rmstart();
 125: #else
 126:         rmstart();
 127: #endif
 128:     }
 129:     (void) _spl0();
 130: }
 131: 
 132: #if NRM > 1
 133: rmustart(unit)
 134: register unit;
 135: {
 136:     register struct hpdevice *rmaddr = RMADDR;
 137:     register struct buf *dp;
 138:     struct  buf *bp;
 139:     daddr_t bn;
 140:     int sn, cn, csn;
 141: 
 142:     rmaddr->hpcs2.w = unit;
 143:     rmaddr->hpcs1.c[0] = HP_IE;
 144:     rmaddr->hpas = 1 << unit;
 145: 
 146:     if (unit >= NRM)
 147:         return;
 148: #ifdef  RM_DKN
 149:     dk_busy &= ~(1 << (unit + RM_DKN));
 150: #endif
 151:     dp = &rmutab[unit];
 152:     if ((bp=dp->b_actf) == NULL)
 153:         return;
 154:     /*
 155: 	 * If we have already positioned this drive,
 156: 	 * then just put it on the ready queue.
 157: 	 */
 158:     if (dp->b_active)
 159:         goto done;
 160:     dp->b_active++;
 161:     /*
 162: 	 * If drive has just come up,
 163: 	 * set up the pack.
 164: 	 */
 165:     if ((rmaddr->hpds & HPDS_VV) == 0) {
 166:         /* SHOULD WARN SYSTEM THAT THIS HAPPENED */
 167:         rmaddr->hpcs1.c[0] = HP_IE | HP_PRESET | HP_GO;
 168:         rmaddr->hpof = HPOF_FMT22;
 169:     }
 170:     /*
 171: 	 * If drive is offline, forget about positioning.
 172: 	 */
 173:     if ((rmaddr->hpds & (HPDS_DPR | HPDS_MOL)) != (HPDS_DPR | HPDS_MOL))
 174:         goto done;
 175: 
 176:     bn = dkblock(bp);
 177:     cn = bp->b_cylin;
 178:     sn = bn % (RM_NSECT * RM_NTRAC);
 179:     sn = (sn + RM_NSECT - RM_SDIST) % RM_NSECT;
 180: 
 181:     if (rmcc[unit] != cn)
 182:         goto search;
 183:     csn = (rmaddr->hpla >> 6) - sn + RM_SDIST - 1;
 184:     if (csn < 0)
 185:         csn += RM_NSECT;
 186:     if (csn > RM_NSECT - RM_RDIST)
 187:         goto done;
 188: 
 189: search:
 190:     rmaddr->hpdc = cn;
 191:     rmaddr->hpda = sn;
 192:     rmaddr->hpcs1.c[0] = HP_IE | HP_SEARCH | HP_GO;
 193:     rmcc[unit] = cn;
 194:     /*
 195: 	 * Mark unit busy for iostat.
 196: 	 */
 197: #ifdef  RM_DKN
 198:     unit += RM_DKN;
 199:     dk_busy |= 1 << unit;
 200:     dk_numb[unit]++;
 201: #endif
 202:     return;
 203: 
 204: done:
 205:     /*
 206: 	 * Device is ready to go.
 207: 	 * Put it on the ready queue for the controller.
 208: 	 */
 209:     dp->b_forw = NULL;
 210:     if (rmtab.b_actf == NULL)
 211:         rmtab.b_actf = dp;
 212:     else
 213:         rmtab.b_actl->b_forw = dp;
 214:     rmtab.b_actl = dp;
 215: }
 216: #endif
 217: 
 218: /*
 219:  * Start up a transfer on a drive.
 220:  */
 221: rmstart()
 222: {
 223:     register struct hpdevice *rmaddr = RMADDR;
 224:     register struct buf *bp;
 225:     struct buf *dp;
 226:     register unit;
 227:     daddr_t bn;
 228:     int dn, sn, tn, cn;
 229: 
 230: loop:
 231:     /*
 232: 	 * Pull a request off the controller queue.
 233: 	 */
 234: #if NRM == 1
 235:     dp = &rmtab;
 236:     if ((bp = dp->b_actf) == NULL)
 237:         return;
 238: #else
 239:     if ((dp = rmtab.b_actf) == NULL)
 240:         return;
 241:     if ((bp = dp->b_actf) == NULL) {
 242:         rmtab.b_actf = dp->b_forw;
 243:         goto loop;
 244:     }
 245: #endif
 246:     /*
 247: 	 * Mark controller busy and
 248: 	 * determine destination of this request.
 249: 	 */
 250:     rmtab.b_active++;
 251:     unit = minor(bp->b_dev) & 077;
 252:     dn = dkunit(bp);
 253:     bn = dkblock(bp);
 254:     cn = bn / (RM_NSECT * RM_NTRAC) + rm_sizes[unit & 07].cyloff;
 255:     sn = bn % (RM_NSECT * RM_NTRAC);
 256:     tn = sn / RM_NSECT;
 257:     sn = sn % RM_NSECT;
 258: 
 259:     /*
 260: 	 * Select drive.
 261: 	 */
 262:     rmaddr->hpcs2.w = dn;
 263: #if NRM == 1
 264:     /*
 265: 	 * If drive has just come up,
 266: 	 * set up the pack.
 267: 	 */
 268:     if ((rmaddr->hpds & HPDS_VV) == 0) {
 269:         /* SHOULD WARN SYSTEM THAT THIS HAPPENED */
 270:         rmaddr->hpcs1.c[0] = HP_IE | HP_PRESET | HP_GO;
 271:         rmaddr->hpof = HPOF_FMT22;
 272:     }
 273: #endif
 274:     /*
 275: 	 * Check that it is ready and online.
 276: 	 */
 277:     if ((rmaddr->hpds & (HPDS_DPR | HPDS_MOL)) != (HPDS_DPR | HPDS_MOL)) {
 278:         rmtab.b_active = 0;
 279:         rmtab.b_errcnt = 0;
 280:         dp->b_actf = bp->av_forw;
 281:         bp->b_flags |= B_ERROR;
 282:         iodone(bp);
 283:         goto loop;
 284:     }
 285:     if (rmtab.b_errcnt >= 16 && (bp->b_flags & B_READ)) {
 286:         rmaddr->hpof = rm_offset[rmtab.b_errcnt & 017] | HPOF_FMT22;
 287:         rmaddr->hpcs1.w = HP_OFFSET | HP_GO;
 288:         while ((rmaddr->hpds & (HPDS_PIP | HPDS_DRY)) != HPDS_DRY)
 289:             ;
 290:     }
 291:     rmaddr->hpdc = cn;
 292:     rmaddr->hpda = (tn << 8) + sn;
 293:     rmaddr->hpba = bp->b_un.b_addr;
 294: #if PDP11 == 70 || PDP11 == GENERIC
 295:     if (rmtab.b_flags & B_RH70)
 296:         rmaddr->hpbae = bp->b_xmem;
 297: #endif
 298:     rmaddr->hpwc = -(bp->b_bcount >> 1);
 299:     /*
 300: 	 * Warning:  unit is being used as a temporary.
 301: 	 */
 302:     unit = ((bp->b_xmem & 3) << 8) | HP_IE | HP_GO;
 303:     if (bp->b_flags & B_READ)
 304:         unit |= HP_RCOM;
 305:     else
 306:         unit |= HP_WCOM;
 307:     rmaddr->hpcs1.w = unit;
 308: 
 309: #ifdef  RM_DKN
 310:     dk_busy |= 1 << (RM_DKN + NRM);
 311:     dk_numb[RM_DKN + NRM]++;
 312:     dk_wds[RM_DKN + NRM] += bp->b_bcount >> 6;
 313: #endif
 314: }
 315: 
 316: /*
 317:  * Handle a disk interrupt.
 318:  */
 319: rmintr()
 320: {
 321:     register struct hpdevice *rmaddr = RMADDR;
 322:     register struct buf *bp, *dp;
 323:     short   unit;
 324:     int as, i, j;
 325: 
 326:     as = rmaddr->hpas & 0377;
 327:     if (rmtab.b_active) {
 328: #ifdef  RM_DKN
 329:         dk_busy &= ~(1 << (RM_DKN + NRM));
 330: #endif
 331:         /*
 332: 		 * Get device and block structures.  Select the drive.
 333: 		 */
 334: #if NRM > 1
 335:         dp = rmtab.b_actf;
 336: #else
 337:         dp = &rmtab;
 338: #endif
 339:         bp = dp->b_actf;
 340:         unit = dkunit(bp);
 341:         rmaddr->hpcs2.c[0] = unit;
 342:         /*
 343: 		 * Check for and process errors.
 344: 		 */
 345:         if (rmaddr->hpcs1.w & HP_TRE) {     /* error bit */
 346:             while ((rmaddr->hpds & HPDS_DRY) == 0)
 347:                 ;
 348:             if (rmaddr->hper1 & HPER1_WLE) {
 349:                 /*
 350: 				 *	Give up on write locked devices
 351: 				 *	immediately.
 352: 				 */
 353:                 printf("rm%d: write locked\n", unit);
 354:                 bp->b_flags |= B_ERROR;
 355:             } else {
 356:                 /*
 357: 				 * After 28 retries (16 without offset and
 358: 				 * 12 with offset positioning), give up.
 359: 				 */
 360:                 if (++rmtab.b_errcnt > 28) {
 361:                     bp->b_flags |= B_ERROR;
 362: #ifdef  UCB_DEVERR
 363:                     harderr(bp, "rm");
 364:                     printf("cs2=%b er1=%b\n", rmaddr->hpcs2.w,
 365:                     HPCS2_BITS, rmaddr->hper1, HPER1_BITS);
 366: #else
 367:                     deverror(bp, rmaddr->hpcs2.w, rmaddr->hper1);
 368: #endif
 369:                 } else
 370:                     rmtab.b_active = 0;
 371:             }
 372: #ifdef  UCB_ECC
 373:             /*
 374: 			 * If soft ecc, correct it (continuing
 375: 			 * by returning if necessary).
 376: 			 * Otherwise, fall through and retry the transfer.
 377: 			 */
 378:             if((rmaddr->hper1 & (HPER1_DCK|HPER1_ECH)) == HPER1_DCK)
 379:                 if (rmecc(bp))
 380:                     return;
 381: #endif
 382:             rmaddr->hpcs1.w = HP_TRE | HP_IE | HP_DCLR | HP_GO;
 383:             if ((rmtab.b_errcnt & 07) == 4) {
 384:                 rmaddr->hpcs1.w = HP_RECAL | HP_IE | HP_GO;
 385:                 while ((rmaddr->hpds & (HPDS_PIP | HPDS_DRY)) != HPDS_DRY)
 386:                     ;
 387:             }
 388: #if NRM > 1
 389:             rmcc[unit] = -1;
 390: #endif
 391:         }
 392:         if (rmtab.b_active) {
 393:             if (rmtab.b_errcnt) {
 394:                 rmaddr->hpcs1.w = HP_RTC | HP_GO;
 395:                 while ((rmaddr->hpds & (HPDS_PIP | HPDS_DRY)) != HPDS_DRY)
 396:                     ;
 397:             }
 398:             rmtab.b_errcnt = 0;
 399: #if NRM > 1
 400:             rmtab.b_active = 0;
 401:             rmtab.b_actf = dp->b_forw;
 402:             rmcc[unit] = bp->b_cylin;
 403: #endif
 404:             dp->b_active = 0;
 405:             dp->b_actf = bp->b_actf;
 406:             bp->b_resid = - (rmaddr->hpwc << 1);
 407:             iodone(bp);
 408:             rmaddr->hpcs1.w = HP_IE;
 409: #if NRM > 1
 410:             if (dp->b_actf)
 411:                 rmustart(unit);
 412: #endif
 413:         }
 414: #if NRM > 1
 415:         as &= ~(1 << unit);
 416: #endif
 417:     } else {
 418:         if (as == 0)
 419:             rmaddr->hpcs1.w = HP_IE;
 420:         rmaddr->hpcs1.c[1] = HP_TRE >> 8;
 421:     }
 422: #if NRM > 1
 423:     for(unit = 0; unit < NRM; unit++)
 424:         if (as & (1 << unit))
 425:             rmustart(unit);
 426: #endif
 427:     rmstart();
 428: }
 429: 
 430: rmread(dev)
 431: dev_t   dev;
 432: {
 433: #ifdef  UCB_DBUFS
 434:     register int unit = (minor(dev) >> 3) & 07;
 435: 
 436:     if (unit >= NRM)
 437:         u.u_error = ENXIO;
 438:     else
 439:         physio(rmstrategy, &rrmbuf[unit], dev, B_READ);
 440: #else
 441:     physio(rmstrategy, &rrmbuf, dev, B_READ);
 442: #endif
 443: }
 444: 
 445: rmwrite(dev)
 446: dev_t   dev;
 447: {
 448: #ifdef  UCB_DBUFS
 449:     register int unit = (minor(dev) >> 3) & 07;
 450: 
 451:     if (unit >= NRM)
 452:         u.u_error = ENXIO;
 453:     else
 454:         physio(rmstrategy, &rrmbuf[unit], dev, B_WRITE);
 455: #else
 456:     physio(rmstrategy, &rrmbuf, dev, B_WRITE);
 457: #endif
 458: }
 459: 
 460: #ifdef  UCB_ECC
 461: #define exadr(x,y)  (((long)(x) << 16) | (unsigned)(y))
 462: 
 463: /*
 464:  * Correct an ECC error and restart the i/o to complete
 465:  * the transfer if necessary.  This is quite complicated because
 466:  * the correction may be going to an odd memory address base
 467:  * and the transfer may cross a sector boundary.
 468:  */
 469: rmecc(bp)
 470: register struct buf *bp;
 471: {
 472:     register struct hpdevice *rmaddr = RMADDR;
 473:     register unsigned byte;
 474:     ubadr_t bb, addr;
 475:     long    wrong;
 476:     int bit, wc;
 477:     unsigned ndone, npx;
 478:     int ocmd;
 479:     int cn, tn, sn;
 480:     daddr_t bn;
 481: #ifdef  UNIBUS_MAP
 482:     struct  ubmap *ubp;
 483: #endif
 484: 
 485:     /*
 486: 	 *	ndone is #bytes including the error
 487: 	 *	which is assumed to be in the last disk page transferred.
 488: 	 */
 489:     wc = rmaddr->hpwc;
 490:     ndone = (wc * NBPW) + bp->b_bcount;
 491:     npx = ndone / PGSIZE;
 492:     printf("rm%d%c:  soft ecc bn %D\n",
 493:         dkunit(bp), 'a' + (minor(bp->b_dev) & 07),
 494:         bp->b_blkno + (npx - 1));
 495:     wrong = rmaddr->hpec2;
 496:     if (wrong == 0) {
 497:         rmaddr->hpof = HPOF_FMT22;
 498:         rmaddr->hpcs1.w |= HP_IE;
 499:         return (0);
 500:     }
 501: 
 502:     /*
 503: 	 *	Compute the byte/bit position of the err
 504: 	 *	within the last disk page transferred.
 505: 	 *	Hpec1 is origin-1.
 506: 	 */
 507:     byte = rmaddr->hpec1 - 1;
 508:     bit = byte & 07;
 509:     byte >>= 3;
 510:     byte += ndone - PGSIZE;
 511:     bb = exadr(bp->b_xmem, bp->b_un.b_addr);
 512:     wrong <<= bit;
 513: 
 514:     /*
 515: 	 *	Correct until mask is zero or until end of transfer,
 516: 	 *	whichever comes first.
 517: 	 */
 518:     while (byte < bp->b_bcount && wrong != 0) {
 519:         addr = bb + byte;
 520: #ifdef  UNIBUS_MAP
 521:         if (bp->b_flags & (B_MAP|B_UBAREMAP)) {
 522:             /*
 523: 			 * Simulate UNIBUS map if UNIBUS transfer
 524: 			 */
 525:             ubp = UBMAP + ((addr >> 13) & 037);
 526:             addr = exadr(ubp->ub_hi, ubp->ub_lo) + (addr & 017777);
 527:         }
 528: #endif
 529:         putmemc(addr, getmemc(addr) ^ (int) wrong);
 530:         byte++;
 531:         wrong >>= 8;
 532:     }
 533: 
 534:     rmtab.b_active++;
 535:     if (wc == 0)
 536:         return (0);
 537: 
 538:     /*
 539: 	 * Have to continue the transfer.  Clear the drive
 540: 	 * and compute the position where the transfer is to continue.
 541: 	 * We have completed npx sectors of the transfer already.
 542: 	 */
 543:     ocmd = (rmaddr->hpcs1.w & ~HP_RDY) | HP_IE | HP_GO;
 544:     rmaddr->hpcs2.w = dkunit(bp);
 545:     rmaddr->hpcs1.w = HP_TRE | HP_DCLR | HP_GO;
 546: 
 547:     bn = dkblock(bp);
 548:     cn = bp->b_cylin - bn / (RM_NSECT * RM_NTRAC);
 549:     bn += npx;
 550:     addr = bb + ndone;
 551: 
 552:     cn += bn / (RM_NSECT * RM_NTRAC);
 553:     sn = bn % (RM_NSECT * RM_NTRAC);
 554:     tn = sn / RM_NSECT;
 555:     sn %= RM_NSECT;
 556: 
 557:     rmaddr->hpdc = cn;
 558:     rmaddr->hpda = (tn << 8) + sn;
 559:     rmaddr->hpwc = ((int)(ndone - bp->b_bcount)) / NBPW;
 560:     rmaddr->hpba = (int) addr;
 561: #if PDP11 == 70 || PDP11 == GENERIC
 562:     if (rmtab.b_flags & B_RH70)
 563:         rmaddr->hpbae = (int) (addr >> 16);
 564: #endif
 565:     rmaddr->hpcs1.w = ocmd;
 566:     return (1);
 567: }
 568: #endif	UCB_ECC
 569: 
 570: #if defined(RM_DUMP) && defined(UCB_AUTOBOOT)
 571: /*
 572:  *  Dump routine for RM02/RM03.
 573:  *  Dumps from dumplo to end of memory/end of disk section for minor(dev).
 574:  *  It uses the UNIBUS map to dump all of memory if there is a UNIBUS map
 575:  *  and this isn't an RM03.  This depends on UNIBUS_MAP being defined.
 576:  *  If there is no UNIBUS map, it will work with any definitions.
 577:  */
 578: 
 579: #ifdef  UNIBUS_MAP
 580: #define DBSIZE  (UBPAGE/PGSIZE)     /* unit of transfer, one UBPAGE */
 581: #else
 582: #define DBSIZE  16          /* unit of transfer, same number */
 583: #endif
 584: 
 585: rmdump(dev)
 586: dev_t   dev;
 587: {
 588:     register struct hpdevice *rmaddr = RMADDR;
 589:     daddr_t bn, dumpsize;
 590:     long    paddr;
 591:     register sn;
 592:     register count;
 593: #ifdef  UNIBUS_MAP
 594:     extern  bool_t ubmap;
 595:     register struct ubmap *ubp;
 596: #endif
 597: 
 598:     if ((bdevsw[major(dev)].d_strategy != rmstrategy)   /* paranoia */
 599:         || ((dev=minor(dev)) > (NRM << 3)))
 600:         return(EINVAL);
 601:     dumpsize = rm_sizes[dev & 07].nblocks;
 602:     if ((dumplo < 0) || (dumplo >= dumpsize))
 603:         return(EINVAL);
 604:     dumpsize -= dumplo;
 605: 
 606:     rmaddr->hpcs2.w = dev >> 3;
 607:     if ((rmaddr->hpds & HPDS_VV) == 0) {
 608:         rmaddr->hpcs1.w = HP_DCLR | HP_GO;
 609:         rmaddr->hpcs1.w = HP_PRESET | HP_GO;
 610:         rmaddr->hpof = HPOF_FMT22;
 611:     }
 612:     if ((rmaddr->hpds & (HPDS_DPR | HPDS_MOL)) != (HPDS_DPR | HPDS_MOL))
 613:         return(EFAULT);
 614:     dev &= 07;
 615: #ifdef  UNIBUS_MAP
 616:     ubp = &UBMAP[0];
 617: #endif
 618:     for (paddr = 0L; dumpsize > 0; dumpsize -= count) {
 619:         count = dumpsize>DBSIZE? DBSIZE: dumpsize;
 620:         bn = dumplo + (paddr >> PGSHIFT);
 621:         rmaddr->hpdc = bn / (RM_NSECT*RM_NTRAC) + rm_sizes[dev].cyloff;
 622:         sn = bn % (RM_NSECT * RM_NTRAC);
 623:         rmaddr->hpda = ((sn / RM_NSECT) << 8) | (sn % RM_NSECT);
 624:         rmaddr->hpwc = -(count << (PGSHIFT - 1));
 625:         /*
 626: 		 *  If UNIBUS_MAP exists, use
 627: 		 *  the map, unless on an 11/70 with RM03.
 628: 		 */
 629: #ifdef  UNIBUS_MAP
 630:         if (ubmap && ((rmtab.b_flags & B_RH70) == 0)) {
 631:             ubp->ub_lo = loint(paddr);
 632:             ubp->ub_hi = hiint(paddr);
 633:             rmaddr->hpba = 0;
 634:             rmaddr->hpcs1.w = HP_WCOM | HP_GO;
 635:         }
 636:         else
 637: #endif
 638:             {
 639:             /*
 640: 			 *  Non-UNIBUS map, or 11/70 RM03 (MASSBUS)
 641: 			 */
 642:             rmaddr->hpba = loint(paddr);
 643: #if PDP11 == 70 || PDP11 == GENERIC
 644:             if (rmtab.b_flags & B_RH70)
 645:                 rmaddr->hpbae = hiint(paddr);
 646: #endif
 647:             rmaddr->hpcs1.w = HP_WCOM | HP_GO | ((paddr >> 8) & (03 << 8));
 648:         }
 649:         while (rmaddr->hpcs1.w & HP_GO)
 650:             ;
 651:         if (rmaddr->hpcs1.w & HP_TRE) {
 652:             if (rmaddr->hpcs2.w & HPCS2_NEM)
 653:                 return(0);  /* made it to end of memory */
 654:             return(EIO);
 655:         }
 656:         paddr += (DBSIZE << PGSHIFT);
 657:     }
 658:     return(0);      /* filled disk minor dev */
 659: }
 660: #endif	RM_DUMP
 661: #endif	NRM

Defined functions

rmattach defined in line 69; used 1 times
  • in line 66
rmdump defined in line 585; never used
rmecc defined in line 469; used 1 times
rmintr defined in line 319; used 4 times
rmread defined in line 430; never used
rmroot defined in line 63; never used
rmstart defined in line 221; used 3 times
rmstrategy defined in line 86; used 5 times
rmustart defined in line 133; used 3 times
rmwrite defined in line 445; never used

Defined variables

rm_offset defined in line 33; used 1 times
rmcc defined in line 60; used 4 times
rmtab defined in line 46; used 34 times
rmutab defined in line 53; used 2 times
rrmbuf defined in line 50; used 4 times

Defined macros

DBSIZE defined in line 582; used 3 times
RM_NSECT defined in line 41; used 19 times
RM_NTRAC defined in line 42; used 9 times
RM_RDIST defined in line 44; used 1 times
RM_SDIST defined in line 43; used 2 times
exadr defined in line 461; used 2 times
Last modified: 1983-09-02
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1677
Valid CSS Valid XHTML 1.0 Strict