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