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