1: /*
   2:  * Copyright (c) 1986 MICOM-Interlan, Inc., Boxborough Mass
   3:  * All rights reserved.  The Berkeley software License Agreement
   4:  * specifies the terms and conditions for redistribution.
   5:  *
   6:  *	@(#)np.c	7.1 (Berkeley) 6/5/86
   7:  */
   8: 
   9:         /******************************************
  10:  		*					  *
  11:  		*		NPDRIVER		  *
  12:  		*					  *
  13:  		******************************************/
  14: 
  15: /*
  16:  * The NP Driver is used to route requests, independent of protocol type,
  17:  * to the NP series Intelligent Board. The facilities it provides are
  18:  * used for board maintainance by the superuser and by protocol pseudo-drivers,
  19:  * such as WN, for sending requests to a board. The board maintainance and
  20:  * control functions are accessed via npioctl() by the NP support utilities.
  21:  */
  22: 
  23: 
  24: /*
  25:  * Include Files
  26:  */
  27: 
  28: #include "np.h"
  29: #if NNP > 0
  30: #include "param.h"
  31: #include "buf.h"
  32: #include "signal.h"
  33: #include "systm.h"
  34: #include "dir.h"
  35: #include "user.h"
  36: #include "proc.h"
  37: #include "uio.h"
  38: #include "errno.h"
  39: 
  40: #include "../vaxuba/ubavar.h"
  41: #include "../vaxuba/npreg.h"
  42: 
  43: /*
  44:  * Global variables for pseudo-drivers.
  45:  */
  46: 
  47: int WnInitFlag;
  48: int IsInitFlag;
  49: 
  50: /*
  51:  * Debugging level.
  52:  */
  53: 
  54: int NpDebug = 0;
  55: 
  56: /* Driver Wide State used by the ICP */
  57: 
  58: int NpState = NPCLEAR;
  59: 
  60: 
  61: /*
  62:  * Master structure, one per board, contains request queue header,
  63:  * shared memory address, and memory mapping information.
  64:  */
  65: 
  66: struct npmaster npmasters[NNP];
  67: 
  68: /* Structure of the shared memory area */
  69: 
  70: static struct npspace npspaces[NNP];
  71: 
  72: /* Panic Message data structures */
  73: 
  74: static int panicmap;            /* Mapping information */
  75: static char NpPbuf[PANLEN] = 0; /* Panic message buffer */
  76: static caddr_t pstring;         /* Panic string address on board, absolute */
  77: static unsign16 panaddr[2];     /* Panic string address on board (seg/offset) */
  78: 
  79: /* Driver Wide Connection Table */
  80: 
  81: static struct npconn npcnxtab[NNP][NNPCNN];
  82: 
  83: /* Head of the request queue, one per board */
  84: 
  85: static struct npreq reqhdr[NNP];
  86: 
  87: /* The request structures, one pool per board */
  88: 
  89: static struct npreq npreqs[NNP][NUMCQE];
  90: 
  91: 
  92: /*
  93:  * Data structures needed for BSD 4.2 Device Drivers
  94:  */
  95: 
  96: int npprobe(), npattach(), npintr();
  97: struct  uba_device *npdinfo[NNP];
  98: 
  99: /* UNIBUS address of Network Processors */
 100: 
 101: u_short npstd[] = { 0166000, 0166020, 0 };
 102: 
 103: /* Interrupt vectors used by the Network Processors */
 104: 
 105: static unsign16 npvectors[NNP];
 106: 
 107: struct  uba_driver npdriver =
 108:     { npprobe, 0, npattach, 0, npstd, "np", npdinfo };
 109: struct  buf np_tab[NNP];
 110: 
 111: 
 112: /*
 113:  * External function and data structure declarations.
 114:  */
 115: 
 116: struct npreq * NpGetReq();
 117: struct npmaster *NpBoardChange();
 118: int NpTimer();
 119: struct CQE * NpRemCQE();
 120: int (*IxAttach)();
 121: int (*IxReset)();
 122: 
 123: extern struct user u;
 124: 
 125: /*
 126:  * Np_init() is responsible for hardware initializiation and the software
 127:  * initialization of the connection table and driver software data structures.
 128:  */
 129: 
 130: npinit(unit)
 131: int unit;
 132: {
 133:     register int j;
 134: 
 135: 
 136:         /* Software Initialization */
 137: 
 138:     npmasters[unit].flags = NPCLEAR;
 139: 
 140:     NpSWinit(unit);
 141: 
 142:         /* Hardware Initialization */
 143: 
 144:     NpHWinit(unit);
 145: 
 146:         /* Connection Table Initialization */
 147: 
 148:     for(j=0;j<NNPCNN;j++) {
 149:         npcnxtab[unit][j].protocol = NPCLCONN;
 150:         npcnxtab[unit][j].unit = &npmasters[unit];
 151:     }
 152: }
 153: 
 154: /*
 155:  * Np_open establishes a connection to the NP Driver using the minor
 156:  * device number as an identifier. A default protocol, NPMAINT, is assigned
 157:  * with the specified unit. Protocol and unit may be changed using the
 158:  * NpProtChange and NpBoardChange functions.
 159:  * Since the maintainance protocol does not need a working I-Board, entries
 160:  * are always made in the Connection Table, npcnxtab, if the board exists.
 161:  */
 162: 
 163: /*ARGSUSED*/
 164: npopen(dev,flag)
 165: dev_t dev;
 166: int flag;
 167: {
 168:     int unit;
 169:     unsign16 conn;
 170:     struct npmaster *mp;
 171:     int error;
 172: 
 173:     if(NpDebug & DEBENTRY)
 174:         printf("npopen\n");
 175: 
 176:     /* Clear error */
 177: 
 178:     error = 0;
 179: 
 180:     /* Make sure it's the superuser */
 181: 
 182:     if(u.u_uid)
 183:         return(EPERM);
 184: 
 185:     /* Get the connection identifier */
 186: 
 187:     if(((conn = NPCONN(dev)) >= NNPCNN) ||
 188:         ((unit = NPUNIT(dev)) >= NNP))
 189:         return(ENODEV);
 190: 
 191: 
 192:     if(NpDebug  & DEBOPEN)
 193:         printf("conn = %x unit = %d\n",conn,unit);
 194: 
 195:     /* Get the board for the specified unit */
 196: 
 197:     mp = NpBoardChange(NPMAINT,unit);
 198: 
 199:     if(mp != (struct npmaster *) 0) {
 200:         npcnxtab[unit][conn].unit = mp;
 201:         npcnxtab[unit][conn].protocol = NPMAINT;
 202:     }
 203:     else error = ENXIO;
 204: 
 205:     if(NpDebug & DEBENTRY)
 206:         printf("npopen...\n");
 207: 
 208:     return(error);
 209: }
 210: 
 211: /*
 212:  * Np_close is responsible updating the connection table for
 213:  * that connection by marking it closed.
 214:  */
 215: 
 216: npclose(dev)
 217: dev_t dev;
 218: {
 219: 
 220:     if(NpDebug & DEBENTRY)
 221:         printf("npclose\n");
 222: 
 223:     /* Get the connection identifier */
 224: 
 225:     npcnxtab[NPUNIT(dev)][NPCONN(dev)].protocol = NPCLCONN;
 226: 
 227:     if(NpDebug & DEBENTRY)
 228:         printf("npclose...\n");
 229: 
 230:     return(0);
 231: 
 232: }
 233: 
 234: /*
 235:  * Npioctl is the main conduit of commands between the I-Board and the
 236:  * NP support utilities. Relevant information for the request is found in the
 237:  * cmd and addr parameters. Cmd specifies the function to perform, addr is
 238:  * command specific. Npioctl returns 0 if successful, or an error number
 239:  * (which winds up in errno).
 240:  */
 241: 
 242: /*ARGSUSED*/
 243: npioctl(dev,cmd,addr,flag)
 244: dev_t dev;
 245: int cmd;
 246: caddr_t *addr;
 247: int flag;
 248: {
 249:     unsign16 protocol;
 250:     unsign16 conn;
 251:     unsign16 unit;
 252:     int error;
 253: 
 254:     register struct npmaster *mp;
 255:     register struct npreq *rp;
 256:     unsigned usrarg;
 257: 
 258:     if(NpDebug & DEBENTRY)
 259:         printf("npioctl\n");
 260: 
 261:     /* Clear error */
 262: 
 263:     error = 0;
 264: 
 265:     /* Strip off IOC_VOID bit */
 266: 
 267:     cmd &= CMDMASK;
 268: 
 269:     /* Get connection identifier */
 270: 
 271:     conn = NPCONN(dev);
 272:     unit = NPUNIT(dev);
 273: 
 274:     /* Master pointer for this unit */
 275: 
 276:     mp = npcnxtab[unit][conn].unit;
 277: 
 278:     protocol = npcnxtab[unit][conn].protocol;
 279: 
 280:     /* Get a request structure from the pool and initialize it */
 281: 
 282:     while((rp = NpGetReq(mp->reqtab)) == NULL) {
 283:         mp->reqtab->flags |= WANTREQ;
 284:         sleep((caddr_t)(mp->reqtab),PZERO -1);
 285:     }
 286: 
 287:     if(NpDebug & DEBREQ)
 288:         printf("NP Reqp is %x\n",rp);
 289: 
 290:     /* Initializations of request structure */
 291: 
 292:     rp->intr = (int (*)())0;    /* Do not call interrupt routine */
 293:     rp->bufoffset = 0;      /* Offset into data buffer */
 294:     rp->flags = NPCLEAR;        /* Clear flags */
 295:     rp->procp = u.u_procp;  /* Process structure for this user */
 296: 
 297:     /* Copy in user's argument to ioctl() call */
 298: 
 299:     if(error = copyin(*addr,&usrarg,sizeof(usrarg)))
 300:         return(error);
 301: 
 302: 
 303:     if(NpDebug & DEBIOCTL)
 304:         printf("arg = %x\n",usrarg);
 305: 
 306:     /* Execute the specified command */
 307: 
 308:     switch(cmd) {
 309: 
 310:         case NPSETPROT:
 311:             if((error = NpProtChange(usrarg,mp->unit)) == 0)
 312:             npcnxtab[unit][conn].protocol = usrarg;
 313:         break;
 314:         case NPSETBOARD:
 315:         if(mp = NpBoardChange(protocol,usrarg))
 316:             npcnxtab[unit][conn].unit = mp;
 317:         else {
 318:             mp = npcnxtab[unit][conn].unit;
 319:             error = ENXIO;
 320:         }
 321:         break;
 322:         case NPRESET:
 323:         error = NpReset(mp,rp);
 324:         break;
 325:         case NPSETNPDEB:
 326:         NpDebug = usrarg;
 327:         break;
 328:         case NPINIT:
 329:         error = NpSWinit(mp->unit);
 330:         break;
 331:         case NPSTART:
 332: 
 333: #ifdef OLDROM
 334:         /*
 335: 		 * Kludge to work around I-Board boot from Host. Read two bytes
 336: 		 * from the board into the Device Configuration Word
 337: 		 * in Shared Memory.
 338: 		 */
 339: 
 340:         NPIO(mp,(paddr_t)0x500,(paddr_t)(&mp->shmemp->statblock.sb_dcw),2,B_READ);
 341: 
 342:         mp->shmemp->statblock.sb_drw = 0;
 343: #endif
 344: 
 345:         /* Set the Address at which to begin On-Board execution */
 346: 
 347:         error = NpSetXeqAddr(mp,(caddr_t)usrarg);
 348:         break;
 349:         case NPSTATS:
 350:         error = NpStats();
 351:         break;
 352:         case NPGPANIC:
 353:         error = copyout((caddr_t)NpPbuf,*addr,PANLEN);
 354: 
 355:         /* Clear panic request flag and leave */
 356: 
 357:         mp->flags &= ~PANICREQ;
 358:         break;
 359:         case NPPOLL:
 360:         error = NpPoll(mp,*addr);
 361:         break;
 362:         case NPKILL:
 363:         error = NpKill(mp,rp);
 364:         break;
 365:         case NPSETADDR:
 366:         error = NpSetMemAddr(mp,*addr);
 367:         break;
 368:         case NPRCSR0:
 369:         usrarg = RCSR0(mp->iobase);
 370:         error = copyout((caddr_t)&usrarg,*addr,sizeof(usrarg));
 371:         break;
 372:         case NPRCSR1:
 373:         usrarg = RCSR1(mp->iobase);
 374:         error = copyout((caddr_t)&usrarg,*addr,sizeof(usrarg));
 375:         break;
 376:         case NPRCSR2:
 377:         usrarg = RCSR2(mp->iobase);
 378:         error = copyout((caddr_t)&usrarg,*addr,sizeof(usrarg));
 379:         break;
 380:         case NPRCSR3:
 381:         usrarg = RCSR3(mp->iobase);
 382:         error = copyout((caddr_t)&usrarg,*addr,sizeof(usrarg));
 383:         break;
 384:         case NPWCSR0:
 385:         WCSR0(mp->iobase,usrarg);
 386:         break;
 387:         case NPWCSR1:
 388:         WCSR1(mp->iobase,usrarg);
 389:         break;
 390:         case NPWCSR2:
 391:         WCSR2(mp->iobase,usrarg);
 392:         break;
 393:         case NPWCSR3:
 394:         WCSR3(mp->iobase,usrarg);
 395:         break;
 396:         case NPNETBOOT:
 397:         error = NpSetIntLevel(mp,mp->vector);
 398:         if(error) break;
 399:         error = NpSetXeqAddr(mp,(caddr_t)INETBOOT);
 400:         break;
 401:         default:
 402:         printf("Bad Maintenance command: %d!\n",cmd);
 403:         error = EIO;
 404:         break;
 405: 
 406:     }
 407:     if((cmd != NPRESET) && (cmd != NPINIT))
 408:         NpFreeReq(mp->reqtab,rp);
 409: 
 410:     if(NpDebug & DEBENTRY)
 411:         printf("npioctl...\n");
 412: 
 413:     return(error);
 414: }
 415: 
 416: /*
 417:  * np_start - start io activity
 418:  */
 419: npstart(mp)
 420: register struct npmaster *mp;
 421: {
 422: 
 423:     register struct buf *bp;
 424:     register struct npreq   *rp;
 425: 
 426:     int error;          /* Return from NPIO call */
 427: 
 428:     if(NpDebug & DEBENTRY)
 429:         printf("npstart\n");
 430: 
 431:     if((bp = np_tab[mp->unit].b_actf) == (struct buf *)0) {
 432:         np_tab[mp->unit].b_active = 0;
 433:         return;
 434:     }
 435:     if((rp = (struct npreq *)(bp->av_back)) == (struct npreq *)0) {
 436:         bp->b_flags = B_ERROR;
 437:         iodone(bp);
 438:         return;
 439:     }
 440:     np_tab[mp->unit].b_active = 1;
 441: 
 442:     if(NpDebug & DEBIO)
 443:         printf("NP IO src %x dst = %x cnt = %x\n",bp->b_un.b_addr,bp->b_blkno << DEV_BSHIFT,bp->b_bcount);
 444: 
 445:     /* Send the request to the board via the CSR0 command interface */
 446: 
 447:     if(bp->b_flags & B_READ)
 448: 
 449:         error = NPIO(mp,(paddr_t)((long)bp->b_blkno << DEV_BSHIFT),(paddr_t)(rp->bufaddr),
 450:         bp->b_bcount,(bp->b_flags & B_READ));
 451: 
 452:     else
 453:         error = NPIO(mp,(paddr_t)(rp->bufaddr),(paddr_t)((long)bp->b_blkno << DEV_BSHIFT),
 454:         bp->b_bcount,(bp->b_flags & B_READ));
 455: 
 456: 
 457:     /* Check return from I/O */
 458: 
 459:     if(error) {
 460:         bp->b_flags |= B_ERROR;
 461:         np_tab[mp->unit].b_actf = bp->av_forw;
 462: 
 463:         if(NpDebug & DEBIO)
 464:             printf("NPIO return error: b_flags is %x \n",bp->b_flags);
 465:         iodone(bp);
 466:     }
 467: 
 468:     if(NpDebug & DEBENTRY)
 469:         printf("npstart...\n");
 470: 
 471: }
 472: /*
 473:  * npstratagey - the strategy routine
 474:  */
 475: 
 476: npstrategy(bp)
 477: register struct buf *bp;
 478: {
 479: 
 480:     register struct buf *ip;    /* quick pointer */
 481:     register struct npmaster *mp;   /* master structure for this device */
 482:     register struct npreq *rp;  /* reqest struct pointer */
 483:     int s;              /* priority to return to */
 484: 
 485:     if(NpDebug & DEBENTRY)
 486:         printf("npstrategy\n");
 487:     if(NpDebug & DEBIO)
 488:         printf("flag = %x count = %x paddr = %x %x blkno = %x %x\n",
 489:             bp->b_flags,bp->b_bcount,bp->b_un.b_addr,bp->b_un.b_addr,bp->b_blkno,bp->b_blkno);
 490: 
 491:     /* get master structure */
 492: 
 493:     mp = npcnxtab[NPUNIT(bp->b_dev)][NPCONN(bp->b_dev)].unit;
 494: 
 495:     /* make sure the boards ok */
 496: 
 497:     if (mp->flags & BADBOARD) {
 498:         bp->b_flags |= B_ERROR;
 499: 
 500:         if(NpDebug & DEBMEM)
 501:             printf("Bad Board %x bp %x\n",mp->flags,bp->b_flags);
 502: 
 503:         np_tab[mp->unit].b_actf = bp->av_forw;
 504:         iodone(bp);
 505:         return;
 506:     }
 507: 
 508:     /* Initializations of request structure */
 509: 
 510:     while((rp = NpGetReq(mp->reqtab)) == NULL) {
 511:         mp->reqtab->flags |= WANTREQ;
 512:         sleep((caddr_t)(mp->reqtab),PZERO -1);
 513:     }
 514: 
 515:     rp->bufoffset = 0;      /* This is the start of the buffer */
 516:     ip = &np_tab[mp->unit];
 517:     bp->av_forw = (struct buf *)0;
 518:     bp->av_back = (struct buf *)rp;
 519: 
 520:     rp->flags |= KERNREQ;       /* Mark it as kernel so not to map */
 521: 
 522:     rp->mapbase = ubasetup(mp->devp->ui_ubanum,bp,0);
 523:     rp->bufaddr = (caddr_t)((int)(rp->mapbase) & UBADDRMASK);
 524: 
 525:     s = spl5();
 526:     if(ip->b_actf ==(struct buf *)0)
 527:         ip->b_actf = bp;
 528:     else {
 529:         if(ip->b_actf->av_forw)
 530:             printf("Panic NP100 bad buffer chain\n");
 531:         ip->b_actf->av_forw = bp;
 532:     }
 533:     ip->b_actl = bp;
 534: 
 535:     NpAddReq(mp->reqtab,rp);        /* Queue onto active list */
 536: 
 537:     if(ip->b_active == 0) {
 538: 
 539:         if(NpDebug & DEBIO)
 540:             printf("calling npstart %x\n",mp);
 541: 
 542:         npstart(mp);
 543:     }
 544:     splx(s);
 545: 
 546:     if(NpDebug & DEBIO)
 547:         printf("back from npstart\n");
 548: 
 549:     /* Await completion of I/O */
 550: 
 551:     iowait(bp);
 552: 
 553:     if(NpDebug & DEBIO)
 554:         printf("after iowait in npstrategy\n");
 555: 
 556:     /* Remove request from queue */
 557: 
 558:     NpRemReq(rp);
 559: 
 560:     /* Release mapping registers */
 561: 
 562:     ubarelse(mp->devp->ui_ubanum,&rp->mapbase);
 563: 
 564:     /* Free up request structure */
 565: 
 566:     NpFreeReq(mp->reqtab,rp);
 567: 
 568:     if(NpDebug & DEBENTRY)
 569:         printf("Leaving npstrategy flags is %x\n",bp->b_flags);
 570: }
 571: 
 572: unsigned
 573: nptrim(bp)
 574: register struct buf *bp;
 575: {
 576: 
 577:     if(bp->b_bcount > NPMAXXFR)
 578:         bp->b_bcount = NPMAXXFR;
 579: }
 580: 
 581: /*
 582:  * Npread dumps data from the board to the user's buffer
 583:  */
 584: npread(dev,uio)
 585: dev_t dev;
 586: struct uio *uio;
 587: {
 588: 
 589:     if(NpDebug & DEBENTRY)
 590:         printf("in npread\n");
 591: 
 592:     return(physio(npstrategy,&npcnxtab[NPUNIT(dev)][NPCONN(dev)].np_rbuf,dev,B_READ ,nptrim,uio));
 593: 
 594: }
 595: 
 596: /*
 597:  * Npwrite loads the np100 board from the user's buffer
 598:  */
 599: 
 600: npwrite(dev,uio)
 601: dev_t dev;
 602: struct uio *uio;
 603: {
 604:     struct buf *bp;
 605:     bp = &npcnxtab[NPUNIT(dev)][NPCONN(dev)].np_wbuf;
 606: 
 607:     if(NpDebug & DEBENTRY)
 608:         printf("in npwrite \n");
 609: 
 610:     return(physio(npstrategy,bp,dev,B_WRITE ,nptrim,uio));
 611: }
 612: /*
 613: 
 614:  * npreset - called as result of a UNIBUS reset.
 615:  */
 616: 
 617: npreset(uban)
 618: int uban;
 619: {
 620: 
 621:     register struct npmaster *mp;
 622:     register struct npreq *rp;
 623:     register struct uba_device *ui;
 624:     int i;
 625: 
 626:     for(i = 0; i < NNP; i++) {
 627: 
 628:         if(((ui = npdinfo[i]) == (struct uba_device *)NULL) ||
 629:             (ui->ui_ubanum != uban))
 630:             continue;
 631: 
 632:         mp = &npmasters[i];
 633:         mp->iomapbase = 0;
 634:         NpReset(mp,0);
 635:     }
 636: }
 637: 
 638: /*
 639:  * Nppoll looks for work by polling each board. He goes to sleep if there are
 640:  * no outstanding requests for him but reminds the board that he's there when
 641:  * needed.
 642:  */
 643: 
 644: NpPoll(mp,addr)
 645: struct npmaster *mp;
 646: caddr_t addr;
 647: {
 648:     int error;
 649: 
 650:     struct {
 651:         unsign16 request;
 652:         unsign16 unit;
 653:     }icpreq;
 654: 
 655:     if(NpDebug & DEBMAINT)
 656:         printf("NpPoll: flags is %x.\n",mp->flags);
 657: 
 658:     while(TRUE) {
 659: 
 660:         for(mp = npmasters; mp; mp = mp->next) {
 661: 
 662:             if(mp->flags & BOARDREQ) {
 663: 
 664:                 /* Get request type from master structure */
 665: 
 666:                 if(mp->flags & BRDRESET) {
 667:                     icpreq.request = ICPPOLL;
 668:                     mp->reqtab->reqcnt--;
 669: 
 670:                     if(NpDebug & DEBMAINT)
 671:                         printf("Waking NpResetter!\n");
 672: 
 673:                     wakeup((caddr_t)(&mp->reqtab));
 674:                 }
 675:                 else if(mp->flags & PANICREQ)
 676:                     icpreq.request = ICPPANIC;
 677:                 else if(mp->flags & DUMPREQ)
 678:                     icpreq.request = ICPDUMP;
 679:                 else if(mp->flags & LOADREQ)
 680:                     icpreq.request = ICPLOAD;
 681:                 else {
 682:                     mp->flags &= ~BOARDREQ;
 683:                     continue;
 684:                 }
 685: 
 686:                 if(NpDebug & DEBMAINT)
 687:                     printf("ProcICP servicing %d \n",icpreq.request );
 688: 
 689:                 /* Request and unit number to be sent */
 690: 
 691:                 icpreq.unit = mp->unit;
 692: 
 693:                 /* Copy service request to calling process */
 694: 
 695:                 error = copyout(&icpreq,addr,sizeof(icpreq));
 696: 
 697:                 /* Mark Poller as being unavailable */
 698: 
 699:                 NpState &= ~ICPAVAIL;
 700: 
 701:                 return(error);
 702:             }
 703:         }
 704: 
 705:         /* Mark Poller as being available */
 706: 
 707:         NpState |= ICPAVAIL;
 708: 
 709:         sleep((caddr_t)&NpState, PZERO + 1);
 710: 
 711:         if(NpDebug & DEBMAINT)
 712:             printf("wakeup in NpPoll\n");
 713: 
 714:     }
 715: }
 716: 
 717: /*
 718:  * Software initialization of Driver data structures for the specified unit.
 719:  */
 720: 
 721: NpSWinit(unit)
 722: int unit;
 723: {
 724: 
 725:     register int j;
 726:     register struct npmaster *mp;
 727:     register struct npspace *npsp;
 728:     register struct CmdQue *cqp;
 729:     int offset;
 730: 
 731:     if(NpDebug & DEBINIT)
 732:         printf("SW reset on unit %d.\n",unit);
 733: 
 734:     /* Initialize master structure pointer for this unit */
 735: 
 736:     mp = &npmasters[unit];
 737: 
 738:     /* Initialize unit buffer headers */
 739: 
 740:     np_tab[unit].b_active = 0;
 741:     np_tab[unit].b_actf = 0;
 742: 
 743:     /* UBA device structure for this unit */
 744: 
 745:     mp->devp = npdinfo[unit];
 746: 
 747:     /* Interrupt vector for this unit */
 748: 
 749:     mp->vector = npvectors[unit];
 750: 
 751:     if(unit == (NNP -1))
 752:         mp->next = (struct npmaster *)NULL;
 753:     else mp->next = &npmasters[unit + 1];
 754: 
 755:     /*
 756: 	 * Guarantee alignment of shared memory area on a
 757:          * 16 byte boundary as required by I-Board
 758: 	 */
 759: 
 760:     mp->shmemp = &npspaces[unit];
 761:     mp->shmemp = (struct npspace *)ROUND16((int)(mp->shmemp));
 762: 
 763:     /* Base address of this controller */
 764: 
 765:     mp->iobase = (struct NPREG *)(mp->devp->ui_addr);
 766: 
 767:     if(NpDebug & DEBMEM) {
 768:         printf("Npspaces starts at %x.\n",npspaces);
 769:         printf("Shared memory starts at %x.\n",mp->shmemp);
 770:         printf("End of shared memory is %x.\n",&npspaces[unit + 1]);
 771:         printf("Iobase is %x.\n",mp->iobase);
 772:         printf("Npmasters start at %x\n",npmasters);
 773:         printf("Reqhdr start at %x\n",reqhdr);
 774:         printf("Npreqs start at %x\n",npreqs);
 775:     }
 776: 
 777:     /* Initialize the request header */
 778: 
 779:     mp->reqtab = &reqhdr[unit];
 780: 
 781:     /* Unit initialization */
 782: 
 783:     mp->unit = unit;
 784: 
 785:     /* Initialize Status Block */
 786: 
 787:     npsp = mp->shmemp;
 788:     offset = (int) (mp->shmemp);
 789: 
 790:     npsp->statblock.sb_drw = 0;
 791:     npsp->statblock.sb_hcw = HOSTCONF;
 792:     npsp->statblock.sb_dcw = 0;
 793:     npsp->statblock.sb_dpm = 0;
 794: 
 795:     npsp->statblock.sb_dcq = (unsign16)((int)(&npsp->devcq))-offset;
 796: 
 797:     npsp->statblock.sb_hcq = (unsign16)((int)(&npsp->hostcq))-offset;
 798: 
 799:     /* Initialize Device Command Queue */
 800: 
 801:     cqp = (struct CmdQue *) &npsp->devcq;
 802: 
 803:     if(NpDebug & DEBCQ)
 804:         printf("Device CQ at %x\n",cqp);
 805: 
 806:     cqp->scanflag = NPCLEAR;
 807:     cqp->chngflag = NPCLEAR;
 808: 
 809:     cqp->cq_add = (unsign16)(int)(&cqp->cq_cqe[0]) - offset;
 810:     cqp->cq_rem = cqp->cq_add;
 811: 
 812:     cqp->cq_wrap = (unsign16)(int)(&cqp->cq_cqe[NUMCQE]) - offset;
 813: 
 814:     for(j = 0; j < NUMCQE; j++)
 815:         cqp->cq_cqe[j] = (unsign16)NULL;
 816: 
 817:     /* Initialize Host Command Queue */
 818: 
 819:     cqp = (struct CmdQue *) &npsp->hostcq;
 820: 
 821:     if(NpDebug & DEBCQ)
 822:         printf("HOST CQ at %x\n",cqp);
 823: 
 824:     cqp->scanflag = NPCLEAR;
 825:     cqp->chngflag = NPCLEAR;
 826: 
 827:     cqp->cq_add = (unsign16)(int)(&cqp->cq_cqe[0]) - offset;
 828:     cqp->cq_rem = cqp->cq_add;
 829: 
 830:     cqp->cq_wrap = (unsign16)(int)(&cqp->cq_cqe[NUMCQE]) - offset;
 831: 
 832:     for(j = 0; j < NUMCQE; j++)
 833:         cqp->cq_cqe[j] = (unsign16)NULL;
 834: 
 835:     /*
 836: 	 * Initialize the reqid of the elements to the address
 837: 	 * of the corresponding Npreq structure. These don't change.
 838:  	 */
 839: 
 840:     for(j = 0; j < NUMCQE; j++)
 841:         npsp->elements[j].cqe_reqid = &npreqs[unit][j];
 842: 
 843:     /*
 844: 	 * Initialize the Request Header (reqhdr), free list of
 845:  	 * npreqs, and pointers to CQEs.
 846:  	 */
 847: 
 848:     reqhdr[unit].forw = reqhdr[unit].back = &reqhdr[unit];
 849:     reqhdr[unit].free = &npreqs[unit][0];
 850: 
 851:     for(j = 0; j < NUMCQE; j++) {
 852: 
 853:         npreqs[unit][j].free = &npreqs[unit][j + 1];
 854:         npreqs[unit][j].element = &npsp->elements[j];
 855:         npreqs[unit][j].forw = npreqs[unit][j].back = (struct npreq *)NULL;
 856:     }
 857:     npreqs[unit][--j].free = &reqhdr[unit];
 858: 
 859:     /*
 860: 	 * Set up the UNIBUS I/O Map Registers for the
 861: 	 * Shared memory area.
 862:  	 */
 863: 
 864:     mp->iomapbase = uballoc(mp->devp->ui_ubanum,(caddr_t)(mp->shmemp),sizeof(struct npspace),0);
 865: 
 866: 
 867:     if(NpDebug & DEBENTRY)
 868:         printf("SW_Init...\n");
 869: }
 870: 
 871: /*
 872:  * NpHWinit() issues a hardware reset to the specified board and waits
 873:  * for on-board diagnostics to complete. It returns 0 if the board is
 874:  * present and passed diagnostics, an error value otherwise.
 875:  */
 876: 
 877: NpHWinit(unit)
 878: int unit;
 879: {
 880:     register struct npmaster *mp;
 881:     struct NPREG *REG;
 882:     unsign16 status;
 883:     int dflag;
 884: 
 885:     if(unit >= NNP)
 886:         return(ENXIO);
 887: 
 888:     mp = &npmasters[unit];
 889: 
 890:     if(NpDebug & DEBENTRY)
 891:         printf("NpHWinit\n");
 892: 
 893:     /* See if the board is out there */
 894: 
 895:     REG = (struct NPREG *)mp->iobase;
 896: 
 897:     if(NpDebug & DEBINIT)
 898:         printf("REG in HWinit is %x.\n",mp->iobase);
 899: 
 900:     if(!(mp->flags & BRDRESET))
 901: 
 902:         if(badaddr(REG,2)) {
 903:             mp->flags |= BADBOARD;
 904:             printf("\nNP100 unit %d not found!\n",unit);
 905:             return(ENXIO);
 906:         }
 907: 
 908: 
 909: #ifdef mc500
 910:     if(setjmp(u.u_tsav) == 0) {
 911:         u.u_nofault = TRUE;
 912:         status = RCSR1(mp->iobase);
 913:         u.u_nofault = FALSE;
 914:     }
 915:     else {
 916:         np__addr[unit] = 0;
 917:         mp->flags |= BADBOARD;
 918:         u.u_error = ENXIO;
 919:         printf("\nNP100 Unit %x not here!\n",unit);
 920:         return(0);
 921:     }
 922: #endif
 923: 
 924:     if(NpDebug & DEBENTRY)
 925:         printf("Resetting the NP100 Board at %x\n",mp->iobase);
 926: 
 927:     /* Reset the Board */
 928: 
 929:     RESET(mp);
 930: 
 931:     dflag = NPCLEAR;
 932: 
 933:     timeout(NpTimer,&dflag,DIAGTIME);
 934: 
 935:     /* Wait for Enable and Read Data Ready to go high */
 936: 
 937:     while(! ((RCSR1(mp->iobase) & NPENB) && (RCSR1(mp->iobase) & NPRDR))) {
 938:         if(dflag)
 939:             break;
 940: 
 941:     }
 942: 
 943:     untimeout(NpTimer,&dflag);
 944: 
 945:     if(NpDebug & DEBINIT)
 946:         printf("np reset %d \n",dflag);
 947: 
 948:     if(dflag) {
 949:         mp->flags |= BADBOARD;
 950:         printf("NP100 Unit %d timed out!\n",unit);
 951:         return(EIO);
 952:     }
 953: 
 954:     status = RCSR0(mp->iobase);
 955: 
 956:     /* Check for Hardware OK */
 957: 
 958:     if(!(RCSR1(mp->iobase) & NPHOK)) {
 959:         mp->flags |= BADBOARD;
 960:         u.u_error = EIO;
 961:         printf("NP100 Unit %d Failed diagnostics!\n",unit);
 962:         printf("Status from CSR0: %x.\n",status);
 963:         return(EIO);
 964:     }
 965: 
 966:     if(NpDebug & DEBENTRY)
 967:         printf("HWinit...\n");
 968: 
 969:     return(0);
 970: }
 971: 
 972: /*
 973:  * NP Driver Interrupt Handler
 974:  */
 975: 
 976: npintr(unit)
 977: int unit;
 978: {
 979:     register struct npmaster *mp;
 980:     register struct buf *bp;
 981: 
 982:     if(NpDebug & DEBENTRY)
 983:         printf("npintr on unit %d!\n",unit);
 984: 
 985:     mp = &npmasters[unit];
 986: 
 987:     if(NpDebug & DEBINTR)
 988:         printf("npintr mp->flags = %x\n",mp->flags);
 989: 
 990:     /* Wake up anyone sleeping on a CSR0 Command */
 991: 
 992:     if(mp->flags & CSRPEND) {
 993: 
 994:         mp->flags &= ~CSRPEND;
 995:         if(np_tab[mp->unit].b_active) {
 996:             np_tab[mp->unit].b_active = 0;
 997:             bp = np_tab[mp->unit].b_actf;
 998:             np_tab[mp->unit].b_actf = bp->av_forw;
 999: 
1000:             if(NpDebug & DEBINTR)
1001:                 printf("bp = %x resid = %d forw = %x\n",bp,
1002:                     bp->b_resid,bp->av_forw);
1003: 
1004:             bp->b_resid = 0;
1005:             iodone(bp);
1006:         }
1007:         if(mp->flags & PANIC3) {
1008:             mp->flags &= ~PANIC3;
1009:             mp->flags = AVAILABLE;
1010:             ubarelse(mp->devp->ui_ubanum,&panicmap);
1011:         }
1012:         if(mp->flags & PANIC2) {
1013:             mp->flags &= ~PANIC2;
1014:             printf("Panic Message: %s",NpPbuf);
1015:             mp->flags |= PANIC3;
1016:             NpPbuf[0] = 0;
1017:             NPIO(mp,(paddr_t)((int) panicmap & UBADDRMASK),(paddr_t)pstring,sizeof(NpPbuf),B_WRITE);
1018:         }
1019:         if(mp->flags & PANIC1) {
1020:             mp->flags &= ~PANIC1;
1021:             mp->flags |= PANIC2;
1022:             ubarelse(mp->devp->ui_ubanum,&panicmap);
1023:             panicmap = uballoc(mp->devp->ui_ubanum,(caddr_t)NpPbuf,sizeof(NpPbuf),0);
1024:             pstring = (caddr_t)((panaddr[1] << 4) + panaddr[0]);
1025:             NPIO(mp,(paddr_t)pstring,(paddr_t)((int) panicmap & UBADDRMASK),sizeof(NpPbuf),B_READ);
1026:         }
1027: 
1028:         wakeup((caddr_t)mp);
1029:         goto out;
1030:     }
1031: 
1032:     /* Mark unit as being available if Device Protocol Mask set */
1033: 
1034:     if(!(mp->flags & AVAILABLE)) {
1035: 
1036:         if((mp->shmemp->statblock.sb_dpm) && (!(mp->flags & BRDRESET))){
1037: 
1038:             mp->flags = AVAILABLE;
1039:             printf("\nNP100 unit #%d available!\n",mp->unit);
1040:         }
1041:     }
1042: 
1043:     /* Honor service requests from the device */
1044: 
1045:     switch(mp->shmemp->statblock.sb_drw) {
1046: 
1047:         case NOREQ:
1048:         break;
1049: 
1050:         case NPPANIC:
1051: 
1052:         printf("\nPanic from NP100 unit %d!\n",mp->unit);
1053:         mp->flags &= ~AVAILABLE;
1054:         mp->flags |= PANIC1;
1055: 
1056:         /* Clear device request word */
1057: 
1058:         mp->shmemp->statblock.sb_drw = 0;
1059: 
1060:         panicmap = uballoc(mp->devp->ui_ubanum,(caddr_t)panaddr,sizeof(panaddr),0);
1061:         NPIO(mp,(paddr_t)NPPSADDR,(paddr_t)((int)panicmap & UBADDRMASK),sizeof(panaddr),B_READ);
1062:         goto out;
1063:         break;
1064: 
1065:         case NPDUMP:
1066:         mp->flags |= (DUMPREQ | BOARDREQ);
1067: 
1068:         /* Clear device request word */
1069: 
1070:         mp->shmemp->statblock.sb_drw = 0;
1071: 
1072:         if(NpState & ICPAVAIL)
1073:             wakeup((caddr_t)&NpState);
1074:         break;
1075: 
1076:         case NPLOAD:
1077:         mp->flags |= (LOADREQ | BOARDREQ);
1078: 
1079:         /* Clear device request word */
1080: 
1081:         mp->shmemp->statblock.sb_drw = 0;
1082: 
1083:         if(NpState & ICPAVAIL)
1084:             wakeup((caddr_t)&NpState);
1085:         break;
1086: 
1087:         default:
1088:         printf("Bad Req: %x.\n",mp->shmemp->statblock.sb_drw);
1089:         goto out;
1090: 
1091:     }
1092: 
1093:     /* Process the Host Command Queue for this device */
1094: 
1095:     NpProcQueue(mp);
1096: 
1097: out:
1098:     CLEARINT(mp);   /* Clear the interrupt */
1099: 
1100:     if(NpDebug & DEBENTRY)
1101:         printf("npintr...\n");
1102: 
1103:     return(1);  /* Interrupt serviced */
1104: 
1105: }
1106: 
1107: /*
1108:  * This routine, called from the interrupt handler, is used to process the
1109:  * Host Command Queue for the specified device.
1110:  */
1111: 
1112: NpProcQueue(mp)
1113: struct npmaster *mp;
1114: {
1115:     register struct CmdQue *cqp;
1116:     register struct CQE *ep;
1117:     register struct npreq *rp;
1118:     register int base;
1119: 
1120:     if(NpDebug & DEBENTRY)
1121:         printf("NpProcQueue\n");
1122: 
1123:     cqp = &mp->shmemp->hostcq;  /* Command Queue pointer */
1124: 
1125:     if(cqp->scanflag & ON)
1126:                 return;
1127: 
1128:     else cqp->scanflag | = ON;
1129: 
1130:     base = (int)mp->shmemp;     /* Shared memory base address */
1131: 
1132:     while(cqp->scanflag & ON) {
1133: 
1134:         while(ep = NpRemCQE(cqp,base)) {
1135: 
1136:             rp = ep->cqe_reqid;
1137: 
1138:             if(NpDebug & DEBCQE)
1139:                 printf("cqe_sts is %x ep = %x\n",ep->cqe_sts,ep);
1140: 
1141:             switch (ep->cqe_sts)  {
1142: 
1143:                 case NPDONE:
1144:                 rp->flags |= REQDONE;   /* Normal completion */
1145:                 break;
1146:                 case NPIFC:         /* IFC Request */
1147:                 rp->flags |= IOIFC;
1148:                 break;
1149:                 case NPPERR:        /* Protocol Error */
1150:                 rp->flags |= (NPPERR | REQDONE);
1151:                 break;
1152:                 case NPMERR:        /* Memory allocation */
1153:                 rp->flags |= (NPMERR | REQDONE);
1154:                 break;
1155:                 default:            /* Error on Board */
1156:                 rp->flags |= (IOERR | REQDONE);
1157:                 break;
1158: 
1159:             }
1160: 
1161:             if(NpDebug & DEBCQE) {
1162:                 printf("flag is %x reqid = %x\n",rp->flags,ep->cqe_reqid);
1163:                 printf("wakeup in procqueue\n");
1164:             }
1165: 
1166:             if(rp->intr) {
1167: 
1168:                 if(NpDebug & DEBINTR)
1169:                     printf("calling usr intr at %x\n",
1170:                         rp->intr);
1171: 
1172:                 /* Call interrupt routine */
1173: 
1174:                 (*rp->intr)(mp,rp);
1175: 
1176:             }
1177:             else {
1178: 
1179:             if(NpDebug & DEBINTR)
1180:                 printf("waking up %x\n",rp);
1181: 
1182:                 if(rp->flags & NPUIO)
1183:                     iodone(&rp->buf);
1184:                 else    wakeup((caddr_t) (rp)); /* Awaken */
1185: 
1186:             if(NpDebug & DEBINTR)
1187:                 printf("AWAKE\n");
1188:             }
1189: 
1190:         }
1191: 
1192:         if(!(cqp->chngflag & ON))
1193:             cqp->scanflag &= ~ON;
1194: 
1195:     }
1196: 
1197:     if(NpDebug & DEBENTRY)
1198:         printf("NpProcQueue...\n");
1199: }
1200: 
1201: /*
1202:  * NpIFC - processes an IFC (Internal Fuction Call) request
1203:  *		NOTE: this function must be called from the user context
1204:  *			on all virtual pageing systems
1205:  *
1206:  */
1207: NpIFC(mp,rp)
1208: register struct npmaster *mp;
1209: register struct npreq *rp;
1210: {
1211:     register struct CQE *ep;
1212: 
1213:     if(NpDebug & DEBENTRY)
1214:         printf("NpIFC\n");
1215: 
1216:     ep = rp->element;
1217:     rp->flags &= ~IOIFC;
1218:     switch(ep->cqe_func) {
1219: 
1220:         case NPUNLOCK:  /* Unlock process, free up mapping registers  */
1221: 
1222:         if(NpDebug & DEBIFC)
1223:             printf("NPUNLOCK\n");
1224: 
1225:         if(rp->mapbase)
1226:             NpUnMapMem(mp,rp);
1227:         break;
1228: 
1229:         case NPLOCK:    /* Lock process, get mapping registers */
1230: 
1231:         if(NpDebug & DEBIFC)
1232:             printf("NPLOCK\n");
1233:         NpMapMem(mp,rp,rp->virtmem,rp->bytecnt);
1234:         ep->cqe_dma[0] = LOWORD(rp->bufaddr);
1235:         ep->cqe_dma[1] = HIWORD(rp->bufaddr);
1236:         break;
1237: 
1238:         case NPREMAP:
1239: 
1240:         if(NpDebug & DEBIFC)
1241:             printf("NPREMAP\n");
1242: 
1243:         /* Remap user buffer and update buffer offset */
1244: #ifdef USG
1245:         np_remapmem(rp,rp->virtmem);
1246:         ep->cqe_dma[0] = LOWORD(rp->bufaddr);
1247:         ep->cqe_dma[1] = HIWORD(rp->bufaddr);
1248:         break;
1249: #endif
1250: 
1251:         default:
1252:         if(NpDebug & DEBIFC)
1253:             printf("Bad case %x in IFC\n", ep->cqe_func);
1254: 
1255:         rp->flags |= (REQDONE | IOERR);
1256:         break;
1257:     }
1258: }
1259: 
1260: /*
1261:  * The following contains various routines for allocating and deallocating
1262:  * structures used by the NP Driver. Routines are also here for addding
1263:  * and removing Command Queue Elements from a Command Queue.
1264:  */
1265: 
1266: /*
1267:  * Get a free NP Request structure from the list pointed to by head. Returns
1268:  * a pointer to a npreq or NULL if none left.
1269:  */
1270: 
1271: struct npreq *
1272: NpGetReq(head)
1273: struct npreq *head;
1274: {
1275: 
1276:     register struct npreq *p;
1277: 
1278:     p = head->free;
1279:     head->free = p->free;
1280:     return(p==head ? (struct npreq *)NULL : p);
1281: }
1282: 
1283: /*
1284:  * Return a NP Request structure to the free list pointed to by head.
1285:  */
1286: 
1287: NpFreeReq(head,nprp)
1288: register struct npreq *head, *nprp;
1289: {
1290: 
1291:     if(NpDebug & DEBREQ)
1292:         printf("NpFreeReq, head is %x rp is %x\n",head,nprp);
1293: 
1294:     nprp->forw = nprp->back = (struct npreq *)NULL;
1295:     nprp->free = head->free;
1296:     head->free = nprp;
1297: 
1298:     /* Wake up any processes waiting for a request structure */
1299: 
1300:     if(head->flags & WANTREQ) {
1301:         head->flags &= ~WANTREQ;
1302:         wakeup((caddr_t)head);
1303:     }
1304: 
1305:     if(NpDebug & DEBENTRY)
1306:         printf("NpFreeReq...\n");
1307: }
1308: 
1309: /*
1310:  * Add a Command Queue Element onto the specified Command Queue and
1311:  * update its Add offset.
1312:  */
1313: 
1314: NpAddCQE(ep,cqp,mp)
1315: struct CQE *ep;
1316: struct CmdQue *cqp;
1317: struct npmaster *mp;
1318: {
1319: 
1320:     register unsign16 *temp;
1321:     register unsign16 cqe_offset;
1322:     register int base;
1323: 
1324:     base = (int)mp->shmemp;     /* Shared memory base address */
1325: 
1326:     temp = (unsign16 *)(base + cqp->cq_add); /* Offset to add element */
1327: 
1328:     cqe_offset = (unsign16)((int)ep - base);
1329: 
1330:     if(*temp) {         /* Should never happen */
1331: 
1332:         printf("No more room on Command Queue!\n");
1333:         u.u_error = EIO;
1334:         return;
1335:     }
1336:     else *temp = cqe_offset;    /* Enter this request's offset */
1337: 
1338:     cqp->chngflag |= ON;        /* Set change flag unconditionally */
1339: 
1340:     /* Update cqe_add where next request is to be added */
1341: 
1342:     cqp->cq_add += sizeof(unsign16);
1343: 
1344:     if(cqp->cq_add == cqp->cq_wrap) /* Wrap if necessary */
1345:         cqp->cq_add = (unsign16)((int)cqp->cq_cqe - base);
1346: 
1347:     /* Interrupt the Board if his scan flag isn't on */
1348: 
1349:     if(!(cqp->scanflag & ON))
1350: 
1351:         INTNI(mp);      /* Interrupt the Board */
1352: 
1353: }
1354: 
1355: /*
1356:  * The NpRemCQE routine is used to remove the next CQE from the Command Queue
1357:  * specified by cqp. The common offset of shared memory used by the device
1358:  * is specified by base. NpRemCQE returns a pointer to the next CQE or
1359:  * NULL if there are none left. This routine will also update the cqe_rem
1360:  * offset which specifies where the next element to be removed from the
1361:  * queue is located.
1362:  */
1363: 
1364: struct CQE *
1365: NpRemCQE(cqp,base)
1366: struct CmdQue *cqp;
1367: int base;
1368: {
1369: 
1370:     register unsign16 *temp;
1371:     register unsign16 cqe_offset;
1372: 
1373:     cqp->chngflag &= ~ON;           /* Turn off unconditionally */
1374: 
1375:     /* Get address of element to remove */
1376: 
1377:     temp = (unsign16 *)(base +cqp->cq_rem);
1378: 
1379:     if(*temp == NULL)           /* If none left, go home */
1380:         return((struct CQE *) NULL);
1381: 
1382:     else cqe_offset = *temp;        /* Offset of CQE to remove */
1383: 
1384:     /* Update the Command Queue's cqe_rem offset */
1385: 
1386:     *temp = NULL;               /* Clear out this entry */
1387: 
1388:     cqp->cq_rem += sizeof(unsign16);    /* Bump offset */
1389: 
1390:     if(cqp->cq_rem == cqp->cq_wrap)     /* Wrap if necessary */
1391:         cqp->cq_rem = (unsign16)((int)cqp->cq_cqe - base);
1392: 
1393:     temp = (unsign16 *)(base + cqe_offset); /* CQE address */
1394:     return((struct CQE *)temp);     /* is returned */
1395: }
1396: 
1397: /*
1398:  * NpAddReq will add the specified npreq structure to the queue controlled
1399:  * by head.
1400:  */
1401: 
1402: NpAddReq(head,rp)
1403: register struct npreq *head, *rp;
1404: {
1405: 
1406:     if(NpDebug & DEBENTRY)
1407:         printf("NpAddReq\n");
1408: 
1409:     if(NpDebug & DEBREQ)
1410:         printf("NpAddReq: %x\n",rp);
1411: 
1412:     rp->forw = head->forw;
1413:     rp->forw->back = rp;
1414:     rp->back = head;
1415:     head->forw = rp;
1416: 
1417:     if(NpDebug & DEBENTRY)
1418:         printf("NpAddReq...\n");
1419: }
1420: 
1421: /*
1422:  * NpRemReq is used to remove a npreq structure from the queue specified by
1423:  * head.
1424:  */
1425: 
1426: NpRemReq(rp)
1427: register struct npreq *rp;
1428: {
1429: 
1430:     if(NpDebug & DEBENTRY)
1431:         printf("NpRemReq\n");
1432: 
1433:     if(NpDebug & DEBREQ)
1434:         printf("NpRemReq: %x\n",rp);
1435: 
1436:     rp->back->forw = rp->forw;
1437:     rp->forw->back = rp->back;
1438: 
1439:     if(NpDebug & DEBENTRY)
1440:         printf("NpRemReq...\n");
1441: }
1442: 
1443: 
1444: /*
1445:  * The following routines are used to communicate with the
1446:  * NI Hardware via the CSR0 commands. These commands are issued during
1447:  * the hardware initializtion process and may also be used subsequently
1448:  * by privileged processes who wish to communicate in this way. The
1449:  * convention for passing data as a Command Block is discussed in detail
1450:  * in the NI1510 UNIBUS Compatible Ethernet Communications Processor
1451:  * Hardware Specification.
1452:  */
1453: 
1454: NpSendCSR0(iobase,src,bcount)
1455: struct NPREG *iobase;
1456: register unsign16 *src;
1457: int bcount;
1458: {
1459:     register int wcount;
1460:     int i;
1461:     int csrflag;
1462:     unsign16 tmp;
1463: 
1464:     if(NpDebug & DEBENTRY)
1465:         printf("NpSendCSR0\n");
1466: 
1467:     /* Jolt the board into CSR0 command mode if necessary */
1468: 
1469:     if(!(RCSR1(iobase) & NPENB)){
1470:         tmp = NPCLEAR;      /* MC68000 clr reads before writing */
1471:         WCSR0(iobase,tmp);
1472:     }
1473: 
1474:     wcount = (bcount +1) >> 1;  /* Convert byte count to word count */
1475: 
1476:     /* Clear timer flag before beginning the timer */
1477: 
1478:     csrflag = NPCLEAR;
1479:     timeout(NpTimer,&csrflag,DIAGTIME);
1480: 
1481:     for(i = 0; (i < wcount) & (csrflag == NPCLEAR); i++) {
1482:         while(! ((RCSR1(iobase) & NPENB) && (RCSR1(iobase) & NPRDY)))
1483:             if(csrflag) break;
1484:         WCSR0(iobase,*src);
1485:         src++;          /* Better do this WCSR is a macro */
1486:     }
1487: 
1488:     /* Clear the timer entry */
1489: 
1490:     untimeout(NpTimer,&csrflag);
1491: 
1492:     /* Error if timer went off */
1493: 
1494:     if(csrflag)
1495:         return(EIO);
1496: 
1497:     if(NpDebug & DEBENTRY)
1498:         printf("NpSendCSR0...\n");
1499:     return(0);
1500: }
1501: 
1502: /*
1503:  * NpSetIntLev sets the UNIBUS interrupt vector to be used by the NP board when
1504:  * interupting the host. The board is specified by mp.
1505:  */
1506: 
1507: NpSetIntLevel(mp,level)
1508: struct npmaster *mp;
1509: int level;
1510: {
1511: 
1512:     struct {
1513:         unsign16 cmd_word;
1514:         unsign16 int_level;
1515:     }cmd_block;
1516: 
1517:     cmd_block.cmd_word = NPCBI | CBICNT;
1518:     cmd_block.int_level = level;
1519: 
1520:     return(NpSendCSR0(mp->iobase,(unsign16 *)&cmd_block,(int)sizeof(cmd_block)));
1521: }
1522: 
1523: /*
1524:  * NpSetMemAddr is used to declare the shared memory area address to be used
1525:  * for communication between the driver and the device. This address is used
1526:  * to access data structures by acting as a base from which defined offsets
1527:  * locate data. The board is specified by mp.
1528:  */
1529: 
1530: NpSetMemAddr(mp,addr)
1531: struct npmaster *mp;
1532: caddr_t addr;
1533: {
1534: 
1535:     caddr_t shmaddr;
1536:     int error;
1537: 
1538:     struct {
1539:         unsign16 cmd_word;
1540:         unsign16 hi_addr;
1541:         unsign16 lo_addr;
1542:     } cmd_block;
1543: 
1544:     if(NpDebug & DEBENTRY)
1545:         printf("NpSetMemAddr\n");
1546: 
1547:     shmaddr = addr;
1548: 
1549:     if(NpDebug & DEBMEM)
1550:         printf("NpSetMemAddr, addr is %x shmaddr is %x.\n",addr,shmaddr);
1551: 
1552:     cmd_block.cmd_word = NPCMD | CMDCNT;
1553:     cmd_block.hi_addr = HIWORD(shmaddr);
1554:     cmd_block.lo_addr = LOWORD(shmaddr);
1555: 
1556:     error = NpSendCSR0(mp->iobase,(unsign16 *)&cmd_block,(int)sizeof(cmd_block));
1557: 
1558:     if(NpDebug & DEBENTRY)
1559:         printf("NpSetMemAddr...\n");
1560: 
1561:     return(error);
1562: }
1563: 
1564: 
1565: /*
1566:  * NpSetXeqAddr specifies the address at which the board should begin
1567:  * execution of its on-board software. It also indicates the shared memory
1568:  * address to be used. The board is specified by mp.
1569:  */
1570: 
1571: NpSetXeqAddr(mp,addr)
1572: struct npmaster *mp;
1573: caddr_t addr;
1574: {
1575:     caddr_t shmaddr;
1576:     int error;
1577: 
1578:     struct {
1579:         unsign16 cmd_word;
1580:         unsign16 hi_addr;
1581:         unsign16 lo_addr;
1582:         unsign16 mhi_addr;
1583:         unsign16 mlo_addr;
1584:     } cmd_block;
1585: 
1586:     if(NpDebug & DEBENTRY)
1587:         printf("NpSetXeqAddr\n");
1588: 
1589:     shmaddr = (caddr_t)((int)mp->iomapbase & UBADDRMASK);
1590: 
1591:     cmd_block.cmd_word = NPBGN | NPCMD | NPLST | (BGNCNT + CMDCNT);
1592:     cmd_block.hi_addr = HIWORD(addr);
1593:     cmd_block.lo_addr = LOWORD(addr);
1594:     cmd_block.mhi_addr = HIWORD(shmaddr);
1595:     cmd_block.mlo_addr = LOWORD(shmaddr);
1596: 
1597:     if(NpDebug & DEBINIT) {
1598:         printf("NpSetXeqAdddr: hi: %x lo: %x\n",HIWORD(addr), LOWORD(addr));
1599:         printf("NpSetXeqAdddr: mhi: %x mlo: %x\n",HIWORD(shmaddr),LOWORD(shmaddr));
1600:     }
1601: 
1602:     error = NpSendCSR0(mp->iobase,(unsign16 *)&cmd_block,(int)sizeof(cmd_block));
1603: 
1604:     if(NpDebug & DEBENTRY)
1605:         printf("NpSetXeqAddr...\n");
1606: 
1607:     return(error);
1608: }
1609: 
1610: /*
1611:  * NPIO issues a CSR0 load or dump request to the I-Board after packaging a
1612:  * CSR0 Command Block.
1613:  */
1614: 
1615: NPIO(mp,src,dest,count,dir)
1616: struct npmaster *mp;
1617: paddr_t dest;
1618: paddr_t src;
1619: unsign16 count;
1620: int dir;        /* Direction  READ/WRITE */
1621: {
1622: 
1623:     int error;
1624: 
1625:     struct {
1626:         unsign16 cmd_word;  /* Command Word */
1627:         unsign16 shi_addr;  /* High word of Source Address */
1628:         unsign16 slo_addr;  /* Low word of Source Address */
1629:         unsign16 dhi_addr;  /* High word of Destination Address */
1630:         unsign16 dlo_addr;  /* Low word of Destination Address */
1631:         unsign16 count;     /* Byte count */
1632:         unsign16 intlevel;  /* Interrupt level to host */
1633:     } cmd_block;
1634: 
1635:     if(NpDebug & DEBENTRY)
1636:         printf("NPIO\n");
1637:     if(NpDebug & DEBMAINT) {
1638:         printf("I/O src addr = %x, dest addr = %x \n",src,dest);
1639:         printf("I/O count = %d \n",count);
1640:     }
1641: 
1642:     cmd_block.cmd_word = NPCBI | NPLST | (CBICNT + IOCNT);
1643:     cmd_block.intlevel = mp->vector;
1644:     cmd_block.shi_addr = HIWORD(src);
1645:     cmd_block.slo_addr = LOWORD(src);
1646:     cmd_block.dhi_addr = HIWORD(dest);
1647:     cmd_block.dlo_addr = LOWORD(dest);
1648:     cmd_block.count = count;
1649:     if(dir == B_READ)
1650:         cmd_block.cmd_word |= NPDMP;
1651:     else
1652:         cmd_block.cmd_word |= NPLD;
1653: 
1654: 
1655:     if(NpDebug & DEBIO) {
1656:         printf("cmd: %x int: %o shi: %x slo: %x dhi: %x dlo: %x cnt: %x\n",
1657:     cmd_block.cmd_word,cmd_block.intlevel,cmd_block.shi_addr,cmd_block.slo_addr,
1658:     cmd_block.dhi_addr,cmd_block.dlo_addr,cmd_block.count);
1659:     }
1660: 
1661:     mp->flags |= CSRPEND;       /* CSR0 command pending */
1662: 
1663:     error = NpSendCSR0(mp->iobase,(unsign16 *)&cmd_block,(int)sizeof(cmd_block));
1664:     if(NpDebug & DEBENTRY)
1665:         printf("NPIO...\n");
1666: 
1667:     return(error);
1668: }
1669: 
1670: 
1671: /*
1672:  * NpKill will terminate all outstanding requests for the specified board.
1673:  */
1674: 
1675: NpKill(mp,curr_rp)
1676: struct npmaster *mp;
1677: struct npreq *curr_rp;
1678: {
1679:     struct npreq *rp;
1680:     int s;
1681: 
1682:     if(NpDebug & DEBENTRY)
1683:         printf("NpKill\n");
1684: 
1685:     mp->reqtab->reqcnt = 0;     /* Init request count */
1686: 
1687:     s = spl4();         /* Disable interrupts */
1688: 
1689:     /* Mark each active request as having an error and wake him up */
1690: 
1691:     for(rp = mp->reqtab->forw;rp != mp->reqtab;rp = rp->forw) {
1692: 
1693:         if(rp == curr_rp) continue;
1694: 
1695:         rp->flags |= (IOABORT | REQDONE);
1696:         mp->reqtab->reqcnt++;
1697:         if(rp->flags & NPUIO)
1698:             iodone(&rp->buf);
1699:         else wakeup((caddr_t)rp);
1700:     }
1701: 
1702:     if(NpDebug & DEBMAINT)
1703:         printf("NpKill, req count is %d\n",mp->reqtab->reqcnt);
1704: 
1705:     splx(s);
1706: 
1707:     if(NpDebug & DEBENTRY)
1708:         printf("NpKill...\n");
1709: 
1710:     return(0);
1711: 
1712: }
1713: 
1714: /* Hardware and Software Initializations for the specified unit */
1715: 
1716: NpReset(mp,rp)
1717: register struct npmaster *mp;
1718: struct npreq *rp;
1719: {
1720:     int error;
1721: 
1722:     if(NpDebug & DEBENTRY)
1723:         printf("NpReset!\n");
1724: 
1725:     /* Mark board as being reset and make unavailable */
1726: 
1727:     mp->flags = BRDRESET;
1728: 
1729:     /* Abort outstanding requests for this board */
1730: 
1731:     mp->reqtab->reqcnt = 0;     /* Init request count */
1732: 
1733:     /* Wakeup Poller if available and wait until he's gone */
1734: 
1735:     if(NpState & ICPAVAIL) {
1736: 
1737:         mp->flags |= BOARDREQ;
1738:         mp->reqtab->reqcnt++;
1739: 
1740:         if(NpDebug & DEBMAINT)
1741:             printf("Waking ICP in reset!\n");
1742: 
1743:         wakeup((caddr_t)&NpState);
1744: 
1745:         while(mp->reqtab->reqcnt)
1746:             sleep((caddr_t)(&mp->reqtab),PZERO +1);
1747: 
1748:         if(NpDebug & DEBMAINT)
1749:             printf("Reset:awoken by ICP senior!\n");
1750: 
1751:     }
1752: 
1753:     /* Abort outstanding requests and wait till they're gone */
1754: 
1755:     NpKill(mp,rp);
1756: 
1757:     while(mp->reqtab->reqcnt) {
1758: 
1759:         if(NpDebug & DEBMAINT) {
1760:             printf("Sleeping in NpReset on reqtab!\n");
1761:             printf("Reqcnt is %d.\n",mp->reqtab->reqcnt);
1762:         }
1763: 
1764:         sleep((caddr_t)(&mp->reqtab),PZERO +1);
1765: 
1766:     }
1767: 
1768:     /* Free up I/O Map registers if any allocated */
1769: 
1770:     if(mp->iomapbase) {
1771: 
1772:         if(NpDebug & DEBMEM)
1773:             printf("freeing shared memory map.\n");
1774: 
1775:         ubarelse(mp->devp->ui_ubanum,&mp->iomapbase);
1776:         mp->iomapbase = 0;
1777:     }
1778: 
1779:     /* Initialize S/W data structures in NP Driver */
1780: 
1781:     NpSWinit(mp->unit);     /* Software initialization */
1782: 
1783:     /* Hardware initialization of the board */
1784: 
1785:     error = NpHWinit(mp->unit); /* Hardware initialization */
1786: 
1787:     mp->flags &= ~BRDRESET;     /* Initialization complete */
1788: 
1789:     /* Initialize Pseudo-Drivers */
1790: 
1791:     WnInitFlag = 0;         /* WN Pseudo-Driver */
1792:     IsInitFlag = 0;         /* IS Pseudo-Driver */
1793: 
1794:     if (IxReset)
1795:         (*IxReset)(mp->unit, mp->devp->ui_ubanum, rp);
1796: 
1797:     /* Clear Poller's State Flag */
1798: 
1799:     NpState = NPCLEAR;
1800: 
1801:     if(NpDebug & DEBENTRY)
1802:         printf("NpReset...\n");
1803: 
1804:     return(error);
1805: }
1806: 
1807: /*
1808:  * General purpose timeout function which sets the flag passed to it
1809:  * as argument.
1810:  */
1811: 
1812: NpTimer(flagp)
1813: int *flagp;
1814: {
1815:     *flagp = NPSET;
1816: }
1817: 
1818: NpStats()
1819: {
1820:     if(NpDebug & DEBENTRY)
1821:         printf("npstats\n");
1822:     return(0);
1823: }
1824: 
1825: /*
1826:  * NpCloseConn is called to issue a close connection command to the I-Board.
1827:  */
1828: 
1829: NpCloseConn(mp,protocol)
1830: struct npmaster *mp;
1831: unsign16 protocol;
1832: {
1833: 
1834:     register struct npreq *rp;
1835:     register struct CQE *ep;
1836:     int pri;
1837: 
1838:     if(NpDebug & DEBENTRY)
1839:         printf("NpCloseConn\n");
1840: 
1841:     /*
1842: 	 * Don't issue the Close Connection command if the Board
1843:          * isn't up.
1844:          */
1845: 
1846:     if(!((mp->shmemp->statblock.sb_dpm) & PROTOMASK(protocol))) {
1847:         return;
1848:     }
1849: 
1850:     /* Get a Request structure */
1851: 
1852:     while((rp = NpGetReq(mp->reqtab)) == NULL) {
1853:         mp->reqtab->flags |= WANTREQ;
1854:         sleep((caddr_t)(mp->reqtab),PZERO -1);
1855:     }
1856: 
1857:     rp->intr = (int (*)())0;    /* Do not call interrupt routine */
1858:     rp->flags = NPCLEAR;
1859:     rp->mapbase = 0;        /* Clear mapping information */
1860: 
1861:     ep = rp->element;       /* Handy pointer */
1862: 
1863:     /* Fill in CQE */
1864: 
1865:     ep->cqe_wind = 0;       /* Entire buffer mapped */
1866:     ep->cqe_nbuf = 1;       /* Must be 1, no buffer chaining */
1867:     ep->cqe_char = 0;       /* Set to 0 for now */
1868: 
1869:     ep->cqe_func = NPSTOP;      /* OS_STP to I-Board */
1870: 
1871:     ep->cqe_prot = protocol;    /* Protocol of this connection */
1872:     ep->cqe_lenrpb = 0;     /* Parameter block length */
1873: 
1874:     ep->cqe_ust0 = ep->cqe_ust1 = NPCLEAR;  /* Clear status flags */
1875: 
1876:     ep->cqe_famid = (unsign32)u.u_procp->p_pid;  /* Process ID */
1877: 
1878:     NpAddReq(mp->reqtab,rp);    /* Queue onto active list */
1879: 
1880:     pri = spl4();           /* Mask our interrupts */
1881: 
1882:     NpAddCQE(ep,&mp->shmemp->devcq,mp); /* Add CQE to device's queue */
1883: 
1884:     /* Wait for command to complete */
1885: 
1886:     while(!(rp->flags & REQDONE))
1887:         sleep((caddr_t)rp,PZERO - 1);
1888: 
1889:     splx(pri);
1890: 
1891:     NpRemReq(rp);           /* Remove request from active list */
1892: 
1893:     NpFreeReq(mp->reqtab,rp);   /* Deallocate request structure */
1894: 
1895:     if(NpDebug & DEBENTRY)
1896:         printf("NpCloseConn...\n");
1897: 
1898: }
1899: 
1900: /*
1901:  * This function allows the protocol to be changed for a given connection.
1902:  * It returns 0 for success, error code otherwise.
1903:  */
1904: 
1905: NpProtChange(protocol,unit)
1906: register unsign16 protocol;
1907: register int unit;
1908: {
1909: 
1910:     register struct npmaster *mp;
1911: 
1912:     /* Privileged users only for Maintenance Protocol */
1913: 
1914:     if((protocol == NPMAINT) && (u.u_uid != 0))
1915:         return(EPERM);
1916: 
1917:     if(NpDebug & DEBMAINT)
1918:         printf("NpProtChange = %x\n",protocol);
1919: 
1920:     if(protocol != NPMAINT) {
1921: 
1922:         /* Make sure the I-Board supports the protocol */
1923: 
1924:         mp = &npmasters[unit];
1925: 
1926:         if(!((mp->shmemp->statblock.sb_dpm) & PROTOMASK(protocol)))
1927:             return(ENXIO);
1928:     }
1929: 
1930:     return(0);
1931: }
1932: 
1933: /*
1934:  * This function allows for the changing of the unit for a given connection.
1935:  */
1936: 
1937: struct npmaster *
1938: NpBoardChange(protocol,unit)
1939: register unsign16 protocol;
1940: register int unit;          /* Unit number */
1941: {
1942:     register struct npmaster *mp;
1943: 
1944: 
1945:     if(unit > NNP)
1946:         return((struct npmaster *)0);
1947: 
1948:     if(protocol != NPMAINT) {
1949: 
1950:         /*
1951: 		 * Loop through the master structures finding a board which
1952: 		 * supports the requested protocol.
1953: 		 */
1954: 
1955:         for(mp = npmasters; mp ; mp = mp->next) {
1956: 
1957:             if(mp->flags & BADBOARD)
1958:                 continue;
1959: 
1960:             if(((mp->shmemp->statblock.sb_dpm) & PROTOMASK(protocol)))
1961:                 return(mp);
1962:         }
1963:         return((struct npmaster *)0);
1964:     }
1965:     return(&npmasters[unit]);
1966: }
1967: 
1968: /*
1969:  * NpMapMem - maps the user's memory updating the fields in the npreq
1970:  * structure and returning the mapped address in rp->buffaddr.
1971:  */
1972: NpMapMem(mp,rp,addr,count)
1973: register struct npmaster *mp;
1974: register struct npreq *rp;
1975: caddr_t addr;
1976: int count;
1977: {
1978: 
1979:     if(NpDebug & DEBENTRY)
1980:         printf("NpMapMem\n");
1981:     if(NpDebug & DEBIO)
1982:         printf("mp %x rp %x addr %x count %x\n",mp,rp,addr,count);
1983: 
1984:     rp->virtmem = addr;
1985:     rp->bytecnt = count;
1986: 
1987:     rp->buf.b_un.b_addr = addr;
1988:     rp->buf.b_flags = B_PHYS | B_BUSY;
1989:     rp->buf.b_bcount = count;
1990:     rp->buf.b_proc = rp->procp;
1991: 
1992:     rp->procp->p_flag |= SPHYSIO;
1993:     vslock(addr,count);
1994: 
1995:     rp->mapbase = ubasetup(mp->devp->ui_ubanum,&rp->buf,0);
1996: 
1997:     rp->bufaddr = (caddr_t)(rp->mapbase & UBADDRMASK);
1998: 
1999:     if(NpDebug & DEBENTRY)
2000:         printf("NpMapMem...\n");
2001: }
2002: 
2003: /*
2004:  * Unmap the user's memory and free up mapping registers
2005:  */
2006: 
2007: NpUnMapMem(mp,rp)
2008: struct npmaster *mp;
2009: struct npreq *rp;
2010: {
2011:     if(NpDebug & DEBENTRY)
2012:         printf("NpUnMapMem\n");
2013: 
2014:     ubarelse(mp->devp->ui_ubanum,&rp->mapbase);
2015:     rp->mapbase = 0;
2016:     vsunlock(rp->virtmem,rp->bytecnt,B_READ);
2017:     rp->procp->p_flag &= ~SPHYSIO;
2018: 
2019:     if(NpDebug & DEBENTRY)
2020:         printf("NpUnMapMem...\n");
2021: }
2022: 
2023: npprobe(reg, ui)
2024: caddr_t reg;
2025: struct uba_device *ui;
2026: {
2027: register int br,cvec;
2028: u_short csraddr;
2029: int i;
2030: 
2031: #ifdef lint
2032:     br = 0; cvec = br; br = cvec;
2033: #endif
2034: 
2035:     if(NpDebug & DEBINIT)
2036:         printf("In npprobe, regaddr is %x!\n",reg);
2037: 
2038:     cvec = (uba_hd[numuba].uh_lastiv -= 4);
2039: 
2040: #ifdef OLDBSD4_2
2041:     /* Find unit number from npstd[] by matching the csr address */
2042: 
2043:     csraddr = (u_short)((int)reg & 0x0FFFF);
2044: 
2045:     for(i = 0; i < NNP; i++) {
2046: 
2047:         if(csraddr == npstd[i]) {
2048:             npvectors[i] = cvec;
2049:             break;
2050:         }
2051:     }
2052:     if(i == NNP)
2053:         printf("Couldn't find device in npstd[]!\n");
2054: #else
2055:     npvectors[ui->ui_unit] = cvec;
2056: #endif
2057:     br = 0x15;
2058: 
2059:     if(NpDebug & DEBINIT)
2060:         printf("npprobe...\n");
2061: 
2062:     return(sizeof(struct NPREG));       /* CSR Registers */
2063: 
2064: }
2065: 
2066: npattach(ui)
2067: register struct uba_device *ui;
2068: {
2069: 
2070:     if(NpDebug & DEBINIT)
2071:         printf("In npattach, ui is %x.\n",ui);
2072: 
2073:     npinit(ui->ui_unit);
2074: 
2075:     if (IxAttach)
2076:         (*IxAttach)(ui);
2077: 
2078:     if(NpDebug & DEBINIT)
2079:         printf("npattach...\n");
2080: }
2081: 
2082: #endif

Defined functions

NPIO defined in line 1615; used 6 times
NpAddCQE defined in line 1314; used 4 times
NpAddReq defined in line 1402; used 3 times
NpBoardChange defined in line 1937; used 3 times
NpCloseConn defined in line 1829; never used
NpFreeReq defined in line 1287; used 3 times
NpGetReq defined in line 1271; used 6 times
NpHWinit defined in line 877; used 2 times
NpIFC defined in line 1207; never used
NpKill defined in line 1675; used 3 times
NpMapMem defined in line 1972; used 1 times
NpPoll defined in line 644; used 1 times
NpProcQueue defined in line 1112; used 1 times
NpProtChange defined in line 1905; used 1 times
NpRemCQE defined in line 1364; used 2 times
NpRemReq defined in line 1426; used 3 times
NpReset defined in line 1716; used 3 times
NpSWinit defined in line 721; used 3 times
NpSendCSR0 defined in line 1454; used 4 times
NpSetIntLevel defined in line 1507; used 1 times
NpSetMemAddr defined in line 1530; used 1 times
NpSetXeqAddr defined in line 1571; used 2 times
NpStats defined in line 1818; used 1 times
NpTimer defined in line 1812; used 5 times
NpUnMapMem defined in line 2007; used 1 times
npattach defined in line 2066; used 2 times
npclose defined in line 216; never used
npinit defined in line 130; used 1 times
npintr defined in line 976; used 1 times
  • in line 96
npioctl defined in line 243; never used
npopen defined in line 164; never used
npprobe defined in line 2023; used 2 times
npread defined in line 584; never used
npreset defined in line 617; never used
npstart defined in line 419; used 1 times
npstrategy defined in line 476; used 2 times
nptrim defined in line 572; used 2 times
npwrite defined in line 600; never used

Defined variables

IsInitFlag defined in line 48; used 1 times
NpDebug defined in line 54; used 95 times
NpPbuf defined in line 75; used 7 times
NpState defined in line 58; used 10 times
WnInitFlag defined in line 47; used 1 times
np_tab defined in line 109; used 12 times
npcnxtab defined in line 81; used 13 times
npdinfo defined in line 97; used 5 times
npdriver defined in line 107; never used
npmasters defined in line 66; used 12 times
npreqs defined in line 89; used 9 times
npspaces defined in line 70; used 3 times
panicmap defined in line 74; used 7 times
reqhdr defined in line 85; used 7 times
Last modified: 1986-06-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2184
Valid CSS Valid XHTML 1.0 Strict