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