|
|
1.1 ! root 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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.