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.6 (Berkeley) 04/03/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 #ifdef mc500 975 if(setjmp(u.u_tsav) == 0) { 976 u.u_nofault = TRUE; 977 status = RCSR1(mp->iobase); 978 u.u_nofault = FALSE; 979 } 980 else { 981 np__addr[unit] = 0; 982 mp->flags |= BADBOARD; 983 u.u_error = ENXIO; 984 printf("\nNP100 Unit %x not here!\n",unit); 985 return(0); 986 } 987 #endif 988 989 if(NpDebug & DEBENTRY) 990 printf("Resetting the NP100 Board at %x\n",mp->iobase); 991 992 /* Reset the Board */ 993 994 RESET(mp); 995 996 dflag = NPCLEAR; 997 998 timeout(NpTimer,&dflag,DIAGTIME); 999 1000 /* Wait for Enable and Read Data Ready to go high */ 1001 1002 while(! ((RCSR1(mp->iobase) & NPENB) && (RCSR1(mp->iobase) & NPRDR))) { 1003 if(dflag) 1004 break; 1005 1006 } 1007 1008 untimeout(NpTimer,&dflag); 1009 1010 if(NpDebug & DEBINIT) 1011 printf("np reset %d \n",dflag); 1012 1013 if(dflag) { 1014 mp->flags |= BADBOARD; 1015 printf("NP100 Unit %d timed out!\n",unit); 1016 return(EIO); 1017 } 1018 1019 status = RCSR0(mp->iobase); 1020 1021 /* Check for Hardware OK */ 1022 1023 if(!(RCSR1(mp->iobase) & NPHOK)) { 1024 mp->flags |= BADBOARD; 1025 u.u_error = EIO; 1026 printf("NP100 Unit %d Failed diagnostics!\n",unit); 1027 printf("Status from CSR0: %x.\n",status); 1028 return(EIO); 1029 } 1030 1031 if(NpDebug & DEBENTRY) 1032 printf("HWinit...\n"); 1033 1034 return(0); 1035 } 1036 1037 /* 1038 * NP Driver Interrupt Handler 1039 */ 1040 1041 npintr(unit) 1042 int unit; 1043 { 1044 register struct npmaster *mp; 1045 register struct buf *bp; 1046 1047 if(NpDebug & DEBENTRY) 1048 printf("npintr on unit %d!\n",unit); 1049 1050 mp = &npmasters[unit]; 1051 np_icount[unit]++; 1052 1053 if(NpDebug & DEBINTR) 1054 printf("npintr mp->flags = %x interupt count = %x\n", 1055 mp->flags, np_icount[unit]); 1056 1057 /* Wake up anyone sleeping on a CSR0 Command */ 1058 1059 if(mp->flags & CSRPEND) { 1060 1061 mp->flags &= ~CSRPEND; 1062 if(np_tab[mp->unit].b_active) { 1063 np_tab[mp->unit].b_active = 0; 1064 bp = np_tab[mp->unit].b_actf; 1065 np_tab[mp->unit].b_actf = bp->av_forw; 1066 1067 if(NpDebug & DEBINTR) 1068 printf("bp = %x resid = %d forw = %x\n",bp, 1069 bp->b_resid,bp->av_forw); 1070 1071 bp->b_resid = 0; 1072 iodone(bp); 1073 } 1074 if(mp->flags & PANIC3) { 1075 mp->flags &= ~PANIC3; 1076 mp->flags = AVAILABLE; 1077 ubarelse(mp->devp->ui_ubanum,&panicmap); 1078 } 1079 if(mp->flags & PANIC2) { 1080 mp->flags &= ~PANIC2; 1081 printf("Panic Message: %s",NpPbuf); 1082 mp->flags |= PANIC3; 1083 NpPbuf[0] = 0; 1084 NPIO(mp,(paddr_t)((int) panicmap & UBADDRMASK),(paddr_t)pstring,sizeof(NpPbuf),B_WRITE); 1085 } 1086 if(mp->flags & PANIC1) { 1087 mp->flags &= ~PANIC1; 1088 mp->flags |= PANIC2; 1089 ubarelse(mp->devp->ui_ubanum,&panicmap); 1090 panicmap = uballoc(mp->devp->ui_ubanum,(caddr_t)NpPbuf,sizeof(NpPbuf),0); 1091 pstring = (caddr_t)((panaddr[1] << 4) + panaddr[0]); 1092 NPIO(mp,(paddr_t)pstring,(paddr_t)((int) panicmap & UBADDRMASK),sizeof(NpPbuf),B_READ); 1093 } 1094 1095 wakeup((caddr_t)mp); 1096 goto out; 1097 } 1098 1099 /* Mark unit as being available if Device Protocol Mask set */ 1100 1101 if(!(mp->flags & AVAILABLE)) { 1102 1103 if((mp->shmemp->statblock.sb_dpm) && (!(mp->flags & BRDRESET))){ 1104 1105 mp->flags = AVAILABLE; 1106 printf("\nNP100 unit #%d available!\n",mp->unit); 1107 } 1108 } 1109 1110 /* Honor service requests from the device */ 1111 1112 switch(mp->shmemp->statblock.sb_drw) { 1113 1114 case NOREQ: 1115 break; 1116 1117 case NPPANIC: 1118 1119 printf("\nPanic from NP100 unit %d!\n",mp->unit); 1120 mp->flags &= ~AVAILABLE; 1121 mp->flags |= PANIC1; 1122 1123 /* Clear device request word */ 1124 1125 mp->shmemp->statblock.sb_drw = 0; 1126 1127 panicmap = uballoc(mp->devp->ui_ubanum,(caddr_t)panaddr,sizeof(panaddr),0); 1128 NPIO(mp,(paddr_t)NPPSADDR,(paddr_t)((int)panicmap & UBADDRMASK),sizeof(panaddr),B_READ); 1129 goto out; 1130 break; 1131 1132 case NPDUMP: 1133 mp->flags |= (DUMPREQ | BOARDREQ); 1134 1135 /* Clear device request word */ 1136 1137 mp->shmemp->statblock.sb_drw = 0; 1138 1139 if(NpState & ICPAVAIL) 1140 wakeup((caddr_t)&NpState); 1141 break; 1142 1143 case NPLOAD: 1144 mp->flags |= (LOADREQ | BOARDREQ); 1145 1146 /* Clear device request word */ 1147 1148 mp->shmemp->statblock.sb_drw = 0; 1149 1150 if(NpState & ICPAVAIL) 1151 wakeup((caddr_t)&NpState); 1152 break; 1153 1154 default: 1155 printf("Bad Req: %x.\n",mp->shmemp->statblock.sb_drw); 1156 goto out; 1157 1158 } 1159 1160 /* Process the Host Command Queue for this device */ 1161 1162 NpProcQueue(mp); 1163 1164 out: 1165 CLEARINT(mp); /* Clear the interrupt */ 1166 1167 if(NpDebug & DEBENTRY) 1168 printf("npintr...\n"); 1169 1170 return(1); /* Interrupt serviced */ 1171 1172 } 1173 1174 /* 1175 * This routine, called from the interrupt handler, is used to process the 1176 * Host Command Queue for the specified device. 1177 */ 1178 1179 NpProcQueue(mp) 1180 struct npmaster *mp; 1181 { 1182 register struct CmdQue *cqp; 1183 register struct CQE *ep; 1184 register struct npreq *rp; 1185 register int base; 1186 int s; 1187 1188 if(NpDebug & DEBENTRY) 1189 printf("NpProcQueue\n"); 1190 1191 cqp = &mp->shmemp->hostcq; /* Command Queue pointer */ 1192 1193 s = spl5(); 1194 if(mp->flags & SCANNING) { 1195 splx(s); 1196 return; 1197 } 1198 mp->flags |= SCANNING; 1199 splx(s); 1200 1201 cqp->scanflag | = ON; 1202 1203 base = (int)mp->shmemp; /* Shared memory base address */ 1204 1205 while(1) { 1206 1207 cqp->scanflag |= ON; 1208 cqp->chngflag &= ~ON; 1209 while(ep = NpRemCQE(cqp,base)) { 1210 1211 rp = ep->cqe_reqid; 1212 1213 if(NpDebug & DEBCQE) 1214 printf("cqe_sts is %x ep = %x\n",ep->cqe_sts,ep); 1215 1216 switch (ep->cqe_sts) { 1217 1218 case NPDONE: 1219 rp->flags |= REQDONE; /* Normal completion */ 1220 break; 1221 case NPIFC: /* IFC Request */ 1222 rp->flags |= IOIFC; 1223 break; 1224 case NPPERR: /* Protocol Error */ 1225 rp->flags |= (NPPERR | REQDONE); 1226 break; 1227 case NPMERR: /* Memory allocation */ 1228 rp->flags |= (NPMERR | REQDONE); 1229 break; 1230 default: /* Error on Board */ 1231 rp->flags |= (IOERR | REQDONE); 1232 break; 1233 1234 } 1235 1236 if(NpDebug & DEBCQE) { 1237 printf("flag is %x reqid = %x\n",rp->flags,ep->cqe_reqid); 1238 printf("wakeup in procqueue\n"); 1239 } 1240 1241 if(rp->intr) { 1242 1243 if(NpDebug & DEBINTR) 1244 printf("calling usr intr at %x\n", 1245 rp->intr); 1246 1247 /* Call interrupt routine */ 1248 1249 (*rp->intr)(mp,rp); 1250 } 1251 else { 1252 1253 if(NpDebug & DEBINTR) 1254 printf("waking up %x\n",rp); 1255 1256 /* if(rp->flags & NPUIO) 1257 iodone(&rp->buf); 1258 else wakeup((caddr_t) (rp)); /* Awaken */ 1259 1260 wakeup((caddr_t)(rp)); /* Awaken */ 1261 if(NpDebug & DEBINTR) 1262 printf("AWAKE\n"); 1263 } 1264 } 1265 1266 cqp->scanflag &= ~ON; 1267 if(!(cqp->chngflag & ON)) 1268 break; 1269 1270 } 1271 1272 mp->flags &= ~SCANNING; 1273 if(NpDebug & DEBENTRY) 1274 printf("NpProcQueue...\n"); 1275 } 1276 1277 /* 1278 * NpIFC - processes an IFC (Internal Fuction Call) request 1279 * NOTE: this function must be called from the user context 1280 * on all virtual pageing systems 1281 * 1282 */ 1283 NpIFC(mp,rp) 1284 register struct npmaster *mp; 1285 register struct npreq *rp; 1286 { 1287 register struct CQE *ep; 1288 1289 if(NpDebug & DEBENTRY) 1290 printf("NpIFC\n"); 1291 1292 ep = rp->element; 1293 rp->flags &= ~IOIFC; 1294 switch(ep->cqe_func) { 1295 1296 case NPUNLOCK: /* Unlock process, free up mapping registers */ 1297 1298 if(NpDebug & DEBIFC) 1299 printf("NPUNLOCK\n"); 1300 1301 if(rp->mapbase) 1302 NpUnMapMem(mp,rp); 1303 break; 1304 1305 case NPLOCK: /* Lock process, get mapping registers */ 1306 1307 if(NpDebug & DEBIFC) 1308 printf("NPLOCK\n"); 1309 NpMapMem(mp,rp,rp->virtmem,rp->bytecnt); 1310 ep->cqe_dma[0] = LOWORD(rp->bufaddr); 1311 ep->cqe_dma[1] = HIWORD(rp->bufaddr); 1312 break; 1313 1314 case NPREMAP: 1315 1316 if(NpDebug & DEBIFC) 1317 printf("NPREMAP\n"); 1318 1319 /* Remap user buffer and update buffer offset */ 1320 #ifdef USG 1321 np_remapmem(rp,rp->virtmem); 1322 ep->cqe_dma[0] = LOWORD(rp->bufaddr); 1323 ep->cqe_dma[1] = HIWORD(rp->bufaddr); 1324 break; 1325 #endif 1326 1327 default: 1328 if(NpDebug & DEBIFC) 1329 printf("Bad case %x in IFC\n", ep->cqe_func); 1330 1331 rp->flags |= (REQDONE | IOERR); 1332 break; 1333 } 1334 } 1335 1336 /* 1337 * The following contains various routines for allocating and deallocating 1338 * structures used by the NP Driver. Routines are also here for addding 1339 * and removing Command Queue Elements from a Command Queue. 1340 */ 1341 1342 /* 1343 * Get a free NP Request structure from the list pointed to by head. Returns 1344 * a pointer to a npreq or NULL if none left. 1345 */ 1346 1347 struct npreq * 1348 NpGetReq(head) 1349 struct npreq *head; 1350 { 1351 1352 register struct npreq *p; 1353 1354 p = head->free; 1355 head->free = p->free; 1356 if (p->flags & REQALOC) 1357 printf("GetReq: Req %x already allocated\n", p); 1358 p->flags &= WANTREQ; 1359 if (p != head) 1360 p->flags |= REQALOC; 1361 return(p==head ? (struct npreq *)NULL : p); 1362 } 1363 1364 /* 1365 * Return a NP Request structure to the free list pointed to by head. 1366 */ 1367 1368 NpFreeReq(head,nprp) 1369 register struct npreq *head, *nprp; 1370 { 1371 int s; 1372 1373 if(NpDebug & DEBREQ) 1374 printf("NpFreeReq, head is %x rp is %x\n",head,nprp); 1375 1376 if (nprp == NULL) { 1377 printf("FREEREQ: attempt to free null pointer\n"); 1378 return; 1379 } 1380 if (!(nprp->flags & REQALOC)) { 1381 printf("FREEREQ: attempt to free unallocated request %x\n", 1382 nprp); 1383 return; 1384 } 1385 if (nprp->flags & REQUSE) 1386 printf("FREEREQ: freeing unremoved request %x\n", nprp); 1387 1388 s = spl5(); 1389 nprp->forw = nprp->back = (struct npreq *)NULL; 1390 nprp->free = head->free; 1391 head->free = nprp; 1392 nprp->flags &= ~REQALOC; 1393 splx(s); 1394 1395 /* Wake up any processes waiting for a request structure */ 1396 1397 if(head->flags & WANTREQ) { 1398 head->flags &= ~WANTREQ; 1399 wakeup((caddr_t)head); 1400 } 1401 1402 if(NpDebug & DEBENTRY) 1403 printf("NpFreeReq...\n"); 1404 } 1405 1406 /* 1407 * Add a Command Queue Element onto the specified Command Queue and 1408 * update its Add offset. 1409 */ 1410 1411 NpAddCQE(ep,cqp,mp) 1412 struct CQE *ep; 1413 struct CmdQue *cqp; 1414 struct npmaster *mp; 1415 { 1416 1417 register unsign16 *temp; 1418 register unsign16 cqe_offset; 1419 register int base; 1420 1421 base = (int)mp->shmemp; /* Shared memory base address */ 1422 1423 temp = (unsign16 *)(base + cqp->cq_add); /* Offset to add element */ 1424 1425 cqe_offset = (unsign16)((int)ep - base); 1426 1427 if(*temp) { /* Should never happen */ 1428 1429 printf("No more room on Command Queue!\n"); 1430 u.u_error = EIO; 1431 return; 1432 } 1433 else *temp = cqe_offset; /* Enter this request's offset */ 1434 1435 /* Update cqe_add where next request is to be added */ 1436 1437 cqp->cq_add += sizeof(unsign16); 1438 1439 if(cqp->cq_add == cqp->cq_wrap) /* Wrap if necessary */ 1440 cqp->cq_add = (unsign16)((int)cqp->cq_cqe - base); 1441 1442 cqp->chngflag |= ON; /* Set change flag unconditionally */ 1443 1444 /* Interrupt the Board if his scan flag isn't on */ 1445 1446 if(!(cqp->scanflag & ON)) 1447 1448 INTNI(mp); /* Interrupt the Board */ 1449 1450 } 1451 1452 /* 1453 * The NpRemCQE routine is used to remove the next CQE from the Command Queue 1454 * specified by cqp. The common offset of shared memory used by the device 1455 * is specified by base. NpRemCQE returns a pointer to the next CQE or 1456 * NULL if there are none left. This routine will also update the cqe_rem 1457 * offset which specifies where the next element to be removed from the 1458 * queue is located. 1459 */ 1460 1461 struct CQE * 1462 NpRemCQE(cqp,base) 1463 struct CmdQue *cqp; 1464 int base; 1465 { 1466 1467 register unsign16 *temp; 1468 register unsign16 cqe_offset; 1469 1470 cqp->chngflag &= ~ON; /* Turn off unconditionally */ 1471 1472 /* Get address of element to remove */ 1473 1474 temp = (unsign16 *)(base +cqp->cq_rem); 1475 1476 if(*temp == NULL) /* If none left, go home */ 1477 return((struct CQE *) NULL); 1478 1479 else cqe_offset = *temp; /* Offset of CQE to remove */ 1480 1481 /* Update the Command Queue's cqe_rem offset */ 1482 1483 *temp = NULL; /* Clear out this entry */ 1484 1485 cqp->cq_rem += sizeof(unsign16); /* Bump offset */ 1486 1487 if(cqp->cq_rem == cqp->cq_wrap) /* Wrap if necessary */ 1488 cqp->cq_rem = (unsign16)((int)cqp->cq_cqe - base); 1489 1490 temp = (unsign16 *)(base + cqe_offset); /* CQE address */ 1491 return((struct CQE *)temp); /* is returned */ 1492 } 1493 1494 /* 1495 * NpAddReq will add the specified npreq structure to the queue controlled 1496 * by head. 1497 */ 1498 1499 NpAddReq(head,rp) 1500 register struct npreq *head, *rp; 1501 { 1502 int s; 1503 1504 if (NpDebug & (DEBENTRY|DEBREQ)) 1505 printf("NpAddReq: %x\n",rp); 1506 1507 if (rp->flags & REQUSE) 1508 printf("ADDREQ: Request %x allready in use\n", rp); 1509 1510 s = spl7(); 1511 rp->forw = head->forw; 1512 rp->forw->back = rp; 1513 rp->back = head; 1514 head->forw = rp; 1515 rp->flags |= REQUSE; 1516 splx(s); 1517 1518 if(NpDebug & DEBENTRY) 1519 printf("NpAddReq...\n"); 1520 } 1521 1522 /* 1523 * NpRemReq is used to remove a npreq structure from the queue specified by 1524 * head. 1525 */ 1526 1527 NpRemReq(rp) 1528 register struct npreq *rp; 1529 { 1530 int s; 1531 1532 if (NpDebug & (DEBENTRY|DEBREQ)) 1533 printf("NpRemReq: %x\n",rp); 1534 1535 if (rp == NULL) { 1536 printf("REMREQ: null pointer removal requested\n"); 1537 return; 1538 } 1539 if (!(rp->flags & REQUSE)) { 1540 printf("REMREQ: trying to rem unused req %x\n", rp); 1541 return; 1542 } 1543 if (!(rp->flags & REQALOC)) { 1544 printf("REMREQ: trying to rem unallocated req %x\n", rp); 1545 return; 1546 } 1547 1548 s = spl7(); 1549 rp->back->forw = rp->forw; 1550 rp->forw->back = rp->back; 1551 rp->flags &= ~REQUSE; 1552 splx(s); 1553 1554 if(NpDebug & DEBENTRY) 1555 printf("NpRemReq...\n"); 1556 } 1557 1558 1559 /* 1560 * The following routines are used to communicate with the 1561 * NI Hardware via the CSR0 commands. These commands are issued during 1562 * the hardware initializtion process and may also be used subsequently 1563 * by privileged processes who wish to communicate in this way. The 1564 * convention for passing data as a Command Block is discussed in detail 1565 * in the NI1510 UNIBUS Compatible Ethernet Communications Processor 1566 * Hardware Specification. 1567 */ 1568 1569 NpSendCSR0(iobase,src,bcount) 1570 struct NPREG *iobase; 1571 register unsign16 *src; 1572 int bcount; 1573 { 1574 register int wcount; 1575 int i; 1576 int csrflag; 1577 unsign16 tmp; 1578 1579 if(NpDebug & DEBENTRY) 1580 printf("NpSendCSR0\n"); 1581 1582 /* Jolt the board into CSR0 command mode if necessary */ 1583 1584 if(!(RCSR1(iobase) & NPENB)){ 1585 tmp = NPCLEAR; /* MC68000 clr reads before writing */ 1586 WCSR0(iobase,tmp); 1587 } 1588 1589 wcount = (bcount +1) >> 1; /* Convert byte count to word count */ 1590 1591 /* Clear timer flag before beginning the timer */ 1592 1593 csrflag = NPCLEAR; 1594 timeout(NpTimer,&csrflag,DIAGTIME); 1595 1596 for(i = 0; (i < wcount) & (csrflag == NPCLEAR); i++) { 1597 while(! ((RCSR1(iobase) & NPENB) && (RCSR1(iobase) & NPRDY))) 1598 if(csrflag) break; 1599 WCSR0(iobase,*src); 1600 src++; /* Better do this WCSR is a macro */ 1601 } 1602 1603 /* Clear the timer entry */ 1604 1605 untimeout(NpTimer,&csrflag); 1606 1607 /* Error if timer went off */ 1608 1609 if(csrflag) 1610 return(EIO); 1611 1612 if(NpDebug & DEBENTRY) 1613 printf("NpSendCSR0...\n"); 1614 return(0); 1615 } 1616 1617 /* 1618 * NpSetIntLev sets the UNIBUS interrupt vector to be used by the NP board when 1619 * interupting the host. The board is specified by mp. 1620 */ 1621 1622 NpSetIntLevel(mp,level) 1623 struct npmaster *mp; 1624 int level; 1625 { 1626 1627 struct { 1628 unsign16 cmd_word; 1629 unsign16 int_level; 1630 }cmd_block; 1631 1632 cmd_block.cmd_word = NPCBI | CBICNT; 1633 cmd_block.int_level = level; 1634 1635 return(NpSendCSR0(mp->iobase,(unsign16 *)&cmd_block,(int)sizeof(cmd_block))); 1636 } 1637 1638 /* 1639 * NpSetMemAddr is used to declare the shared memory area address to be used 1640 * for communication between the driver and the device. This address is used 1641 * to access data structures by acting as a base from which defined offsets 1642 * locate data. The board is specified by mp. 1643 */ 1644 1645 NpSetMemAddr(mp,addr) 1646 struct npmaster *mp; 1647 caddr_t addr; 1648 { 1649 1650 caddr_t shmaddr; 1651 int error; 1652 1653 struct { 1654 unsign16 cmd_word; 1655 unsign16 hi_addr; 1656 unsign16 lo_addr; 1657 } cmd_block; 1658 1659 if(NpDebug & DEBENTRY) 1660 printf("NpSetMemAddr\n"); 1661 1662 shmaddr = addr; 1663 1664 if(NpDebug & DEBMEM) 1665 printf("NpSetMemAddr, addr is %x shmaddr is %x.\n",addr,shmaddr); 1666 1667 cmd_block.cmd_word = NPCMD | CMDCNT; 1668 cmd_block.hi_addr = HIWORD(shmaddr); 1669 cmd_block.lo_addr = LOWORD(shmaddr); 1670 1671 error = NpSendCSR0(mp->iobase,(unsign16 *)&cmd_block,(int)sizeof(cmd_block)); 1672 1673 if(NpDebug & DEBENTRY) 1674 printf("NpSetMemAddr...\n"); 1675 1676 return(error); 1677 } 1678 1679 1680 /* 1681 * NpSetXeqAddr specifies the address at which the board should begin 1682 * execution of its on-board software. It also indicates the shared memory 1683 * address to be used. The board is specified by mp. 1684 */ 1685 1686 NpSetXeqAddr(mp,addr) 1687 struct npmaster *mp; 1688 caddr_t addr; 1689 { 1690 caddr_t shmaddr; 1691 int error; 1692 1693 struct { 1694 unsign16 cmd_word; 1695 unsign16 hi_addr; 1696 unsign16 lo_addr; 1697 unsign16 mhi_addr; 1698 unsign16 mlo_addr; 1699 } cmd_block; 1700 1701 if(NpDebug & DEBENTRY) 1702 printf("NpSetXeqAddr\n"); 1703 1704 shmaddr = (caddr_t)((int)mp->iomapbase & UBADDRMASK); 1705 1706 cmd_block.cmd_word = NPBGN | NPCMD | NPLST | (BGNCNT + CMDCNT); 1707 cmd_block.hi_addr = HIWORD(addr); 1708 cmd_block.lo_addr = LOWORD(addr); 1709 cmd_block.mhi_addr = HIWORD(shmaddr); 1710 cmd_block.mlo_addr = LOWORD(shmaddr); 1711 1712 if(NpDebug & DEBINIT) { 1713 printf("NpSetXeqAdddr: hi: %x lo: %x\n",HIWORD(addr), LOWORD(addr)); 1714 printf("NpSetXeqAdddr: mhi: %x mlo: %x\n",HIWORD(shmaddr),LOWORD(shmaddr)); 1715 } 1716 1717 error = NpSendCSR0(mp->iobase,(unsign16 *)&cmd_block,(int)sizeof(cmd_block)); 1718 1719 if(NpDebug & DEBENTRY) 1720 printf("NpSetXeqAddr...\n"); 1721 1722 return(error); 1723 } 1724 1725 /* 1726 * NPIO issues a CSR0 load or dump request to the I-Board after packaging a 1727 * CSR0 Command Block. 1728 */ 1729 1730 NPIO(mp,src,dest,count,dir) 1731 struct npmaster *mp; 1732 paddr_t dest; 1733 paddr_t src; 1734 unsign16 count; 1735 int dir; /* Direction READ/WRITE */ 1736 { 1737 1738 int error; 1739 1740 struct { 1741 unsign16 cmd_word; /* Command Word */ 1742 unsign16 shi_addr; /* High word of Source Address */ 1743 unsign16 slo_addr; /* Low word of Source Address */ 1744 unsign16 dhi_addr; /* High word of Destination Address */ 1745 unsign16 dlo_addr; /* Low word of Destination Address */ 1746 unsign16 count; /* Byte count */ 1747 unsign16 intlevel; /* Interrupt level to host */ 1748 } cmd_block; 1749 1750 if(NpDebug & DEBENTRY) 1751 printf("NPIO\n"); 1752 if(NpDebug & DEBMAINT) { 1753 printf("I/O src addr = %x, dest addr = %x \n",src,dest); 1754 printf("I/O count = %d \n",count); 1755 } 1756 1757 cmd_block.cmd_word = NPCBI | (CBICNT + IOCNT); 1758 cmd_block.intlevel = mp->vector; 1759 cmd_block.shi_addr = HIWORD(src); 1760 cmd_block.slo_addr = LOWORD(src); 1761 cmd_block.dhi_addr = HIWORD(dest); 1762 cmd_block.dlo_addr = LOWORD(dest); 1763 cmd_block.count = count; 1764 if ((mp->flags & LSTCMD) == 0) 1765 cmd_block.cmd_word |= NPLST; 1766 if(dir == B_READ) 1767 cmd_block.cmd_word |= NPDMP; 1768 else 1769 cmd_block.cmd_word |= NPLD; 1770 1771 1772 if(NpDebug & DEBIO) { 1773 printf("cmd: %x int: %o shi: %x slo: %x dhi: %x dlo: %x cnt: %x\n", 1774 cmd_block.cmd_word,cmd_block.intlevel,cmd_block.shi_addr,cmd_block.slo_addr, 1775 cmd_block.dhi_addr,cmd_block.dlo_addr,cmd_block.count); 1776 } 1777 1778 mp->flags |= CSRPEND; /* CSR0 command pending */ 1779 1780 error = NpSendCSR0(mp->iobase,(unsign16 *)&cmd_block,(int)sizeof(cmd_block)); 1781 if(NpDebug & DEBENTRY) 1782 printf("NPIO...\n"); 1783 1784 return(error); 1785 } 1786 1787 1788 /* 1789 * NpKill will terminate all outstanding requests for the specified board. 1790 */ 1791 1792 NpKill(mp,curr_rp) 1793 struct npmaster *mp; 1794 struct npreq *curr_rp; 1795 { 1796 struct npreq *rp; 1797 int s; 1798 1799 if(NpDebug & DEBENTRY) 1800 printf("NpKill\n"); 1801 1802 mp->reqtab->reqcnt = 0; /* Init request count */ 1803 1804 s = spl5(); /* Disable interrupts */ 1805 1806 /* Mark each active request as having an error and wake him up */ 1807 1808 for(rp = mp->reqtab->forw;rp != mp->reqtab;rp = rp->forw) { 1809 1810 if(rp == curr_rp) continue; 1811 1812 rp->flags |= (IOABORT | REQDONE); 1813 mp->reqtab->reqcnt++; 1814 /* if(rp->flags & NPUIO) 1815 iodone(&rp->buf); 1816 else */ 1817 wakeup((caddr_t)rp); 1818 } 1819 1820 if(NpDebug & DEBMAINT) 1821 printf("NpKill, req count is %d\n",mp->reqtab->reqcnt); 1822 1823 splx(s); 1824 1825 if(NpDebug & DEBENTRY) 1826 printf("NpKill...\n"); 1827 1828 return(0); 1829 1830 } 1831 1832 /* Hardware and Software Initializations for the specified unit */ 1833 1834 NpReset(mp,rp) 1835 register struct npmaster *mp; 1836 struct npreq *rp; 1837 { 1838 int error; 1839 1840 if(NpDebug & DEBENTRY) 1841 printf("NpReset!\n"); 1842 1843 /* Mark board as being reset and make unavailable */ 1844 1845 mp->flags = BRDRESET; 1846 1847 /* Abort outstanding requests for this board */ 1848 1849 mp->reqtab->reqcnt = 0; /* Init request count */ 1850 1851 /* Wakeup Poller if available and wait until he's gone */ 1852 1853 if(NpState & ICPAVAIL) { 1854 1855 mp->flags |= BOARDREQ; 1856 mp->reqtab->reqcnt++; 1857 1858 if(NpDebug & DEBMAINT) 1859 printf("Waking ICP in reset!\n"); 1860 1861 wakeup((caddr_t)&NpState); 1862 1863 while(mp->reqtab->reqcnt) 1864 if (error = tsleep((caddr_t)(&mp->reqtab), 1865 (PZERO + 1) | PCATCH, devio, 0)) 1866 return (error); 1867 1868 if(NpDebug & DEBMAINT) 1869 printf("Reset:awoken by ICP senior!\n"); 1870 1871 } 1872 1873 /* Abort outstanding requests and wait till they're gone */ 1874 1875 NpKill(mp,rp); 1876 1877 while(mp->reqtab->reqcnt) { 1878 1879 if(NpDebug & DEBMAINT) { 1880 printf("Sleeping in NpReset on reqtab!\n"); 1881 printf("Reqcnt is %d.\n",mp->reqtab->reqcnt); 1882 } 1883 1884 if (error = tsleep((caddr_t)(&mp->reqtab), 1885 (PZERO + 1) | PCATCH, devio, 0)) 1886 return (error); 1887 } 1888 1889 /* Free up I/O Map registers if any allocated */ 1890 1891 if(mp->iomapbase) { 1892 1893 if(NpDebug & DEBMEM) 1894 printf("freeing shared memory map.\n"); 1895 1896 ubarelse(mp->devp->ui_ubanum,&mp->iomapbase); 1897 mp->iomapbase = 0; 1898 } 1899 1900 /* Initialize S/W data structures in NP Driver */ 1901 1902 NpSWinit(mp->unit); /* Software initialization */ 1903 1904 /* Hardware initialization of the board */ 1905 1906 error = NpHWinit(mp->unit); /* Hardware initialization */ 1907 1908 mp->flags &= ~BRDRESET; /* Initialization complete */ 1909 1910 /* Initialize Pseudo-Drivers */ 1911 1912 if (IxReset) 1913 (*IxReset)(mp->unit, mp->devp->ui_ubanum, rp); 1914 1915 /* Clear Poller's State Flag */ 1916 1917 NpState = NPCLEAR; 1918 1919 if(NpDebug & DEBENTRY) 1920 printf("NpReset...\n"); 1921 1922 return(error); 1923 } 1924 1925 /* 1926 * General purpose timeout function which sets the flag passed to it 1927 * as argument. 1928 */ 1929 1930 NpTimer(flagp) 1931 int *flagp; 1932 { 1933 *flagp = NPSET; 1934 } 1935 1936 NpStats() 1937 { 1938 if(NpDebug & DEBENTRY) 1939 printf("npstats\n"); 1940 return(0); 1941 } 1942 1943 /* 1944 * NpCloseConn is called to issue a close connection command to the I-Board. 1945 */ 1946 1947 NpCloseConn(mp,protocol) 1948 struct npmaster *mp; 1949 unsign16 protocol; 1950 { 1951 1952 register struct npreq *rp; 1953 register struct CQE *ep; 1954 int pri; 1955 1956 if(NpDebug & DEBENTRY) 1957 printf("NpCloseConn\n"); 1958 1959 /* 1960 * Don't issue the Close Connection command if the Board 1961 * isn't up. 1962 */ 1963 1964 if(!((mp->shmemp->statblock.sb_dpm) & PROTOMASK(protocol))) { 1965 return; 1966 } 1967 1968 /* Get a Request structure */ 1969 1970 while((rp = NpGetReq(mp->reqtab)) == NULL) { 1971 mp->reqtab->flags |= WANTREQ; 1972 sleep((caddr_t)(mp->reqtab),PZERO -1); 1973 } 1974 1975 rp->intr = (int (*)())0; /* Do not call interrupt routine */ 1976 rp->mapbase = 0; /* Clear mapping information */ 1977 1978 ep = rp->element; /* Handy pointer */ 1979 1980 /* Fill in CQE */ 1981 1982 ep->cqe_wind = 0; /* Entire buffer mapped */ 1983 ep->cqe_nbuf = 1; /* Must be 1, no buffer chaining */ 1984 ep->cqe_char = 0; /* Set to 0 for now */ 1985 1986 ep->cqe_func = NPSTOP; /* OS_STP to I-Board */ 1987 1988 ep->cqe_prot = protocol; /* Protocol of this connection */ 1989 ep->cqe_lenrpb = 0; /* Parameter block length */ 1990 1991 ep->cqe_ust0 = ep->cqe_ust1 = NPCLEAR; /* Clear status flags */ 1992 1993 ep->cqe_famid = (unsign32)u.u_procp->p_pid; /* Process ID */ 1994 1995 NpAddReq(mp->reqtab,rp); /* Queue onto active list */ 1996 1997 pri = spl5(); /* Mask our interrupts */ 1998 1999 NpAddCQE(ep,&mp->shmemp->devcq,mp); /* Add CQE to device's queue */ 2000 2001 /* Wait for command to complete */ 2002 2003 while(!(rp->flags & REQDONE)) 2004 sleep((caddr_t)rp,PZERO - 1); 2005 2006 splx(pri); 2007 2008 NpRemReq(rp); /* Remove request from active list */ 2009 2010 NpFreeReq(mp->reqtab,rp); /* Deallocate request structure */ 2011 2012 if(NpDebug & DEBENTRY) 2013 printf("NpCloseConn...\n"); 2014 2015 } 2016 2017 /* 2018 * This function allows the protocol to be changed for a given connection. 2019 * It returns 0 for success, error code otherwise. 2020 */ 2021 2022 NpProtChange(protocol,unit) 2023 register unsign16 protocol; 2024 register int unit; 2025 { 2026 2027 register struct npmaster *mp; 2028 2029 /* Privileged users only for Maintenance Protocol */ 2030 2031 if((protocol == NPMAINT) && (u.u_uid != 0)) 2032 return(EPERM); 2033 2034 if(NpDebug & DEBMAINT) 2035 printf("NpProtChange = %x\n",protocol); 2036 2037 if(protocol != NPMAINT) { 2038 2039 /* Make sure the I-Board supports the protocol */ 2040 2041 mp = &npmasters[unit]; 2042 2043 if(!((mp->shmemp->statblock.sb_dpm) & PROTOMASK(protocol))) 2044 return(ENXIO); 2045 } 2046 2047 return(0); 2048 } 2049 2050 /* 2051 * This function allows for the changing of the unit for a given connection. 2052 */ 2053 2054 struct npmaster * 2055 NpBoardChange(protocol,unit) 2056 register unsign16 protocol; 2057 register int unit; /* Unit number */ 2058 { 2059 register struct npmaster *mp; 2060 2061 2062 if(unit > NNP) 2063 return((struct npmaster *)0); 2064 2065 if(protocol != NPMAINT) { 2066 2067 /* 2068 * Loop through the master structures finding a board which 2069 * supports the requested protocol. 2070 */ 2071 2072 for(mp = npmasters; mp ; mp = mp->next) { 2073 2074 if(mp->flags & BADBOARD) 2075 continue; 2076 2077 if(((mp->shmemp->statblock.sb_dpm) & PROTOMASK(protocol))) 2078 return(mp); 2079 } 2080 return((struct npmaster *)0); 2081 } 2082 return(&npmasters[unit]); 2083 } 2084 2085 /* 2086 * NpMapMem - maps the user's memory updating the fields in the npreq 2087 * structure and returning the mapped address in rp->buffaddr. 2088 */ 2089 NpMapMem(mp,rp,addr,count) 2090 register struct npmaster *mp; 2091 register struct npreq *rp; 2092 caddr_t addr; 2093 int count; 2094 { 2095 2096 if(NpDebug & DEBENTRY) 2097 printf("NpMapMem\n"); 2098 if(NpDebug & DEBIO) 2099 printf("mp %x rp %x addr %x count %x\n",mp,rp,addr,count); 2100 2101 rp->virtmem = addr; 2102 rp->bytecnt = count; 2103 2104 rp->buf.b_un.b_addr = addr; 2105 rp->buf.b_flags = B_PHYS | B_BUSY; 2106 rp->buf.b_bcount = count; 2107 rp->buf.b_proc = rp->procp; 2108 2109 rp->procp->p_flag |= SPHYSIO; 2110 if(NpDebug & DEBENTRY) 2111 printf("vslock\n"); 2112 vslock(addr,count); 2113 if(NpDebug & DEBENTRY) 2114 printf("vslock...\n"); 2115 2116 rp->mapbase = ubasetup(mp->devp->ui_ubanum,&rp->buf,0); 2117 2118 rp->bufaddr = (caddr_t)(rp->mapbase & UBADDRMASK); 2119 2120 if(NpDebug & DEBENTRY) 2121 printf("NpMapMem...\n"); 2122 } 2123 2124 /* 2125 * Unmap the user's memory and free up mapping registers 2126 */ 2127 2128 NpUnMapMem(mp,rp) 2129 struct npmaster *mp; 2130 struct npreq *rp; 2131 { 2132 if(NpDebug & DEBENTRY) 2133 printf("NpUnMapMem\n"); 2134 2135 ubarelse(mp->devp->ui_ubanum,&rp->mapbase); 2136 rp->mapbase = 0; 2137 vsunlock(rp->virtmem,rp->bytecnt,B_READ); 2138 rp->procp->p_flag &= ~SPHYSIO; 2139 2140 if(NpDebug & DEBENTRY) 2141 printf("NpUnMapMem...\n"); 2142 } 2143 2144 npprobe(reg, ui) 2145 caddr_t reg; 2146 struct uba_device *ui; 2147 { 2148 register int br,cvec; 2149 u_short csraddr; 2150 int i; 2151 2152 #ifdef lint 2153 br = 0; cvec = br; br = cvec; 2154 #endif 2155 2156 if(NpDebug & DEBINIT) 2157 printf("In npprobe, regaddr is %x!\n",reg); 2158 2159 cvec = (uba_hd[numuba].uh_lastiv -= 4); 2160 2161 #ifdef OLDBSD 2162 /* Find unit number from npstd[] by matching the csr address */ 2163 2164 csraddr = (u_short)((int)reg & 0x0FFFF); 2165 2166 for(i = 0; i < NNP; i++) { 2167 2168 if(csraddr == npstd[i]) { 2169 npvectors[i] = cvec; 2170 break; 2171 } 2172 } 2173 if(i == NNP) 2174 printf("Couldn't find device in npstd[]!\n"); 2175 2176 #else 2177 npvectors[ui->ui_unit] = cvec; 2178 #endif 2179 br = 0x15; 2180 2181 if(NpDebug & DEBINIT) 2182 printf("npprobe...\n"); 2183 2184 return(sizeof(struct NPREG)); /* CSR Registers */ 2185 2186 } 2187 2188 npattach(ui) 2189 register struct uba_device *ui; 2190 { 2191 2192 if(NpDebug & DEBINIT) 2193 printf("In npattach, ui is %x.\n",ui); 2194 2195 npinit(ui->ui_unit); 2196 if (IxAttach) 2197 (*IxAttach)(ui); 2198 2199 if(NpDebug & DEBINIT) 2200 printf("npattach...\n"); 2201 } 2202 2203 2204 NpMem(mp, rp, uaddr) 2205 struct npmaster *mp; 2206 struct npreq *rp; 2207 unsigned long uaddr; 2208 { 2209 struct np_mem mem; 2210 register int error = 0; 2211 2212 if(NpDebug & DEBENTRY) 2213 printf("npmem\n"); 2214 2215 if (error = copyin(uaddr, &mem, sizeof(mem))) 2216 return (error); 2217 2218 if (mem.mem_type == NP_SET) { 2219 if (np_mapreq[mp->unit] != (struct npreq *)NPCLEAR) 2220 error = EBUSY; 2221 else { 2222 error = NpMapMem(mp, rp, mem.mem_addr, mem.mem_count); 2223 if (error != 0) { 2224 np_mapreq[mp->unit] = rp; 2225 mem.mem_addr = rp->bufaddr; 2226 } 2227 } 2228 } else if (mem.mem_type == NP_USET) { 2229 error = NpUnMapMem(mp, np_mapreq[mp->unit]); 2230 NpFreeReq(mp->reqtab, rp); 2231 NpFreeReq(mp->reqtab, np_mapreq[mp->unit]); 2232 np_mapreq[mp->unit] = (struct npreq *)NPCLEAR; 2233 } else 2234 error = EIO; 2235 2236 if (error != 0) 2237 error = copyout(&mem, uaddr, sizeof(mem)); 2238 2239 if(NpDebug & DEBENTRY) 2240 printf("npmem...\n"); 2241 return (error); 2242 } 2243 #endif 2244