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