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