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

Defined functions

hpattach defined in line 72; used 1 times
  • in line 69
hpdump defined in line 655; never used
hpecc defined in line 499; used 3 times
hpintr defined in line 346; used 4 times
hpread defined in line 460; never used
hproot defined in line 66; never used
hpstart defined in line 258; used 2 times
hpstrategy defined in line 89; used 5 times
hpustart defined in line 139; used 3 times
hpwrite defined in line 475; never used

Defined variables

bhpbuf defined in line 58; used 1 times
hp_init defined in line 59; used 2 times
hp_offset defined in line 41; used 1 times
hpbad defined in line 57; used 2 times
hptab defined in line 49; used 32 times
hputab defined in line 55; used 2 times
rhpbuf defined in line 53; used 4 times

Defined macros

DBSIZE defined in line 652; used 3 times
HP_NCYL defined in line 32; used 3 times
HP_NSECT defined in line 33; used 27 times
HP_NTRAC defined in line 34; used 13 times
HP_RDIST defined in line 36; used 1 times
HP_SDIST defined in line 35; used 2 times
exadr defined in line 491; used 2 times
Last modified: 1983-09-02
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1994
Valid CSS Valid XHTML 1.0 Strict