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