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