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