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

Defined functions

hpattach defined in line 57; used 1 times
  • in line 54
hpdump defined in line 550; never used
hpecc defined in line 435; used 1 times
hpintr defined in line 299; never used
hpread defined in line 396; never used
hproot defined in line 51; never used
hpstart defined in line 218; used 2 times
hpstrategy defined in line 74; used 5 times
hpustart defined in line 124; used 3 times
hpwrite defined in line 411; never used

Defined variables

hp_offset defined in line 31; used 1 times
hptab defined in line 39; used 29 times
hputab defined in line 45; used 2 times
rhpbuf defined in line 43; used 4 times

Defined macros

DBSIZE defined in line 547; used 3 times
HP_NSECT defined in line 23; used 19 times
HP_NTRAC defined in line 24; used 9 times
HP_RDIST defined in line 26; used 1 times
HP_SDIST defined in line 25; used 2 times
exadr defined in line 427; used 2 times
Last modified: 1983-09-01
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1763
Valid CSS Valid XHTML 1.0 Strict