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

Defined functions

rmattach defined in line 80; used 1 times
  • in line 77
rmdump defined in line 715; never used
rmecc defined in line 558; used 3 times
rmintr defined in line 387; never used
rmread defined in line 519; never used
rmroot defined in line 74; never used
rmstart defined in line 257; used 3 times
rmstrategy defined in line 97; used 5 times
rmustart defined in line 144; used 3 times
rmwrite defined in line 534; never used

Defined variables

brmbuf defined in line 63; used 2 times
rm_init defined in line 64; used 4 times
rm_offset defined in line 38; used 1 times
rmbad defined in line 62; used 3 times
rmcc defined in line 71; used 4 times
rmtab defined in line 52; used 34 times
rmutab defined in line 59; used 2 times
rrmbuf defined in line 56; used 4 times

Defined macros

DBSIZE defined in line 712; used 3 times
RM_NCYL defined in line 48; used 5 times
RM_NSECT defined in line 46; used 28 times
RM_NTRAC defined in line 47; used 13 times
RM_RDIST defined in line 50; used 1 times
RM_SDIST defined in line 49; used 2 times
exadr defined in line 550; used 2 times
Last modified: 1983-09-02
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2497
Valid CSS Valid XHTML 1.0 Strict