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