126199Ssklower /* 2*26266Ssklower * Copyright (c) 1986 MICOM-Interlan, Inc., Boxborough Mass 3*26266Ssklower * All rights reserved. The Berkeley software License Agreement 4*26266Ssklower * specifies the terms and conditions for redistribution. 526199Ssklower * 6*26266Ssklower * @(#)np.c 6.2 (Berkeley) 02/20/86 726199Ssklower */ 826199Ssklower 926199Ssklower /****************************************** 1026199Ssklower * * 1126199Ssklower * NPDRIVER * 1226199Ssklower * * 1326199Ssklower ******************************************/ 1426199Ssklower 1526199Ssklower /* 1626199Ssklower * The NP Driver is used to route requests, independent of protocol type, 1726199Ssklower * to the NP series Intelligent Board. The facilities it provides are 1826199Ssklower * used for board maintainance by the superuser and by protocol pseudo-drivers, 1926199Ssklower * such as WN, for sending requests to a board. The board maintainance and 2026199Ssklower * control functions are accessed via npioctl() by the NP support utilities. 2126199Ssklower */ 2226199Ssklower 2326199Ssklower 2426199Ssklower /* 2526199Ssklower * Include Files 2626199Ssklower */ 2726199Ssklower 2826199Ssklower #include "np.h" 2926199Ssklower #if NNP > 0 3026199Ssklower #include "param.h" 3126199Ssklower #include "buf.h" 3226199Ssklower #include "signal.h" 3326199Ssklower #include "systm.h" 3426199Ssklower #include "dir.h" 3526199Ssklower #include "user.h" 3626199Ssklower #include "proc.h" 3726199Ssklower #include "uio.h" 3826199Ssklower #include "errno.h" 3926199Ssklower 4026199Ssklower #include "../vaxuba/ubavar.h" 4126199Ssklower #include "../vaxuba/npreg.h" 4226199Ssklower 4326199Ssklower /* 4426199Ssklower * Global variables for pseudo-drivers. 4526199Ssklower */ 4626199Ssklower 4726199Ssklower int WnInitFlag; 4826199Ssklower int IsInitFlag; 4926199Ssklower 5026199Ssklower /* 5126199Ssklower * Debugging level. 5226199Ssklower */ 5326199Ssklower 5426199Ssklower int NpDebug = 0; 5526199Ssklower 5626199Ssklower /* Driver Wide State used by the ICP */ 5726199Ssklower 5826199Ssklower int NpState = NPCLEAR; 5926199Ssklower 6026199Ssklower 6126199Ssklower /* 6226199Ssklower * Master structure, one per board, contains request queue header, 6326199Ssklower * shared memory address, and memory mapping information. 6426199Ssklower */ 6526199Ssklower 6626199Ssklower struct npmaster npmasters[NNP]; 6726199Ssklower 6826199Ssklower /* Structure of the shared memory area */ 6926199Ssklower 7026199Ssklower static struct npspace npspaces[NNP]; 7126199Ssklower 7226199Ssklower /* Panic Message data structures */ 7326199Ssklower 7426199Ssklower static int panicmap; /* Mapping information */ 7526199Ssklower static char NpPbuf[PANLEN] = 0; /* Panic message buffer */ 7626199Ssklower static caddr_t pstring; /* Panic string address on board, absolute */ 7726199Ssklower static unsign16 panaddr[2]; /* Panic string address on board (seg/offset) */ 7826199Ssklower 7926199Ssklower /* Driver Wide Connection Table */ 8026199Ssklower 8126199Ssklower static struct npconn npcnxtab[NNP][NNPCNN]; 8226199Ssklower 8326199Ssklower /* Head of the request queue, one per board */ 8426199Ssklower 8526199Ssklower static struct npreq reqhdr[NNP]; 8626199Ssklower 8726199Ssklower /* The request structures, one pool per board */ 8826199Ssklower 8926199Ssklower static struct npreq npreqs[NNP][NUMCQE]; 9026199Ssklower 9126199Ssklower 9226199Ssklower /* 9326199Ssklower * Data structures needed for BSD 4.2 Device Drivers 9426199Ssklower */ 9526199Ssklower 9626199Ssklower int npprobe(), npattach(), npintr(); 9726199Ssklower struct uba_device *npdinfo[NNP]; 9826199Ssklower 9926199Ssklower /* UNIBUS address of Network Processors */ 10026199Ssklower 10126199Ssklower u_short npstd[] = { 0166000, 0166020, 0 }; 10226199Ssklower 10326199Ssklower /* Interrupt vectors used by the Network Processors */ 10426199Ssklower 10526199Ssklower static unsign16 npvectors[NNP]; 10626199Ssklower 10726199Ssklower struct uba_driver npdriver = 10826199Ssklower { npprobe, 0, npattach, 0, npstd, "np", npdinfo }; 10926199Ssklower struct buf np_tab[NNP]; 11026199Ssklower 11126199Ssklower 11226199Ssklower /* 11326199Ssklower * External function and data structure declarations. 11426199Ssklower */ 11526199Ssklower 11626199Ssklower struct npreq * NpGetReq(); 11726199Ssklower struct npmaster *NpBoardChange(); 11826199Ssklower int NpTimer(); 11926199Ssklower struct CQE * NpRemCQE(); 12026199Ssklower int (*IxAttach)(); 12126199Ssklower int (*IxReset)(); 12226199Ssklower 12326199Ssklower extern struct user u; 12426199Ssklower 12526199Ssklower /* 12626199Ssklower * Np_init() is responsible for hardware initializiation and the software 12726199Ssklower * initialization of the connection table and driver software data structures. 12826199Ssklower */ 12926199Ssklower 13026199Ssklower npinit(unit) 13126199Ssklower int unit; 13226199Ssklower { 13326199Ssklower register int j; 13426199Ssklower 13526199Ssklower 13626199Ssklower /* Software Initialization */ 13726199Ssklower 13826199Ssklower npmasters[unit].flags = NPCLEAR; 13926199Ssklower 14026199Ssklower NpSWinit(unit); 14126199Ssklower 14226199Ssklower /* Hardware Initialization */ 14326199Ssklower 14426199Ssklower NpHWinit(unit); 14526199Ssklower 14626199Ssklower /* Connection Table Initialization */ 14726199Ssklower 14826199Ssklower for(j=0;j<NNPCNN;j++) { 14926199Ssklower npcnxtab[unit][j].protocol = NPCLCONN; 15026199Ssklower npcnxtab[unit][j].unit = &npmasters[unit]; 15126199Ssklower } 15226199Ssklower } 15326199Ssklower 15426199Ssklower /* 15526199Ssklower * Np_open establishes a connection to the NP Driver using the minor 15626199Ssklower * device number as an identifier. A default protocol, NPMAINT, is assigned 15726199Ssklower * with the specified unit. Protocol and unit may be changed using the 15826199Ssklower * NpProtChange and NpBoardChange functions. 15926199Ssklower * Since the maintainance protocol does not need a working I-Board, entries 16026199Ssklower * are always made in the Connection Table, npcnxtab, if the board exists. 16126199Ssklower */ 16226199Ssklower 16326199Ssklower /*ARGSUSED*/ 16426199Ssklower npopen(dev,flag) 16526199Ssklower dev_t dev; 16626199Ssklower int flag; 16726199Ssklower { 16826199Ssklower int unit; 16926199Ssklower unsign16 conn; 17026199Ssklower struct npmaster *mp; 17126199Ssklower int error; 17226199Ssklower 17326199Ssklower if(NpDebug & DEBENTRY) 17426199Ssklower printf("npopen\n"); 17526199Ssklower 17626199Ssklower /* Clear error */ 17726199Ssklower 17826199Ssklower error = 0; 17926199Ssklower 18026199Ssklower /* Make sure it's the superuser */ 18126199Ssklower 18226199Ssklower if(u.u_uid) 18326199Ssklower return(EPERM); 18426199Ssklower 18526199Ssklower /* Get the connection identifier */ 18626199Ssklower 18726199Ssklower if(((conn = NPCONN(dev)) >= NNPCNN) || 18826199Ssklower ((unit = NPUNIT(dev)) >= NNP)) 18926199Ssklower return(ENODEV); 19026199Ssklower 19126199Ssklower 19226199Ssklower if(NpDebug & DEBOPEN) 19326199Ssklower printf("conn = %x unit = %d\n",conn,unit); 19426199Ssklower 19526199Ssklower /* Get the board for the specified unit */ 19626199Ssklower 19726199Ssklower mp = NpBoardChange(NPMAINT,unit); 19826199Ssklower 19926199Ssklower if(mp != (struct npmaster *) 0) { 20026199Ssklower npcnxtab[unit][conn].unit = mp; 20126199Ssklower npcnxtab[unit][conn].protocol = NPMAINT; 20226199Ssklower } 20326199Ssklower else error = ENXIO; 20426199Ssklower 20526199Ssklower if(NpDebug & DEBENTRY) 20626199Ssklower printf("npopen...\n"); 20726199Ssklower 20826199Ssklower return(error); 20926199Ssklower } 21026199Ssklower 21126199Ssklower /* 21226199Ssklower * Np_close is responsible updating the connection table for 21326199Ssklower * that connection by marking it closed. 21426199Ssklower */ 21526199Ssklower 21626199Ssklower npclose(dev) 21726199Ssklower dev_t dev; 21826199Ssklower { 21926199Ssklower 22026199Ssklower if(NpDebug & DEBENTRY) 22126199Ssklower printf("npclose\n"); 22226199Ssklower 22326199Ssklower /* Get the connection identifier */ 22426199Ssklower 22526199Ssklower npcnxtab[NPUNIT(dev)][NPCONN(dev)].protocol = NPCLCONN; 22626199Ssklower 22726199Ssklower if(NpDebug & DEBENTRY) 22826199Ssklower printf("npclose...\n"); 22926199Ssklower 23026199Ssklower return(0); 23126199Ssklower 23226199Ssklower } 23326199Ssklower 23426199Ssklower /* 23526199Ssklower * Npioctl is the main conduit of commands between the I-Board and the 23626199Ssklower * NP support utilities. Relevant information for the request is found in the 23726199Ssklower * cmd and addr parameters. Cmd specifies the function to perform, addr is 23826199Ssklower * command specific. Npioctl returns 0 if successful, or an error number 23926199Ssklower * (which winds up in errno). 24026199Ssklower */ 24126199Ssklower 24226199Ssklower /*ARGSUSED*/ 24326199Ssklower npioctl(dev,cmd,addr,flag) 24426199Ssklower dev_t dev; 24526199Ssklower int cmd; 24626199Ssklower caddr_t *addr; 24726199Ssklower int flag; 24826199Ssklower { 24926199Ssklower unsign16 protocol; 25026199Ssklower unsign16 conn; 25126199Ssklower unsign16 unit; 25226199Ssklower int error; 25326199Ssklower 25426199Ssklower register struct npmaster *mp; 25526199Ssklower register struct npreq *rp; 25626199Ssklower unsigned usrarg; 25726199Ssklower 25826199Ssklower if(NpDebug & DEBENTRY) 25926199Ssklower printf("npioctl\n"); 26026199Ssklower 26126199Ssklower /* Clear error */ 26226199Ssklower 26326199Ssklower error = 0; 26426199Ssklower 26526199Ssklower /* Strip off IOC_VOID bit */ 26626199Ssklower 26726199Ssklower cmd &= CMDMASK; 26826199Ssklower 26926199Ssklower /* Get connection identifier */ 27026199Ssklower 27126199Ssklower conn = NPCONN(dev); 27226199Ssklower unit = NPUNIT(dev); 27326199Ssklower 27426199Ssklower /* Master pointer for this unit */ 27526199Ssklower 27626199Ssklower mp = npcnxtab[unit][conn].unit; 27726199Ssklower 27826199Ssklower protocol = npcnxtab[unit][conn].protocol; 27926199Ssklower 28026199Ssklower /* Get a request structure from the pool and initialize it */ 28126199Ssklower 28226199Ssklower while((rp = NpGetReq(mp->reqtab)) == NULL) { 28326199Ssklower mp->reqtab->flags |= WANTREQ; 28426199Ssklower sleep((caddr_t)(mp->reqtab),PZERO -1); 28526199Ssklower } 28626199Ssklower 28726199Ssklower if(NpDebug & DEBREQ) 28826199Ssklower printf("NP Reqp is %x\n",rp); 28926199Ssklower 29026199Ssklower /* Initializations of request structure */ 29126199Ssklower 29226199Ssklower rp->intr = (int (*)())0; /* Do not call interrupt routine */ 29326199Ssklower rp->bufoffset = 0; /* Offset into data buffer */ 29426199Ssklower rp->flags = NPCLEAR; /* Clear flags */ 29526199Ssklower rp->procp = u.u_procp; /* Process structure for this user */ 29626199Ssklower 29726199Ssklower /* Copy in user's argument to ioctl() call */ 29826199Ssklower 29926199Ssklower if(error = copyin(*addr,&usrarg,sizeof(usrarg))) 30026199Ssklower return(error); 30126199Ssklower 30226199Ssklower 30326199Ssklower if(NpDebug & DEBIOCTL) 30426199Ssklower printf("arg = %x\n",usrarg); 30526199Ssklower 30626199Ssklower /* Execute the specified command */ 30726199Ssklower 30826199Ssklower switch(cmd) { 30926199Ssklower 31026199Ssklower case NPSETPROT: 31126199Ssklower if((error = NpProtChange(usrarg,mp->unit)) == 0) 31226199Ssklower npcnxtab[unit][conn].protocol = usrarg; 31326199Ssklower break; 31426199Ssklower case NPSETBOARD: 31526199Ssklower if(mp = NpBoardChange(protocol,usrarg)) 31626199Ssklower npcnxtab[unit][conn].unit = mp; 31726199Ssklower else { 31826199Ssklower mp = npcnxtab[unit][conn].unit; 31926199Ssklower error = ENXIO; 32026199Ssklower } 32126199Ssklower break; 32226199Ssklower case NPRESET: 32326199Ssklower error = NpReset(mp,rp); 32426199Ssklower break; 32526199Ssklower case NPSETNPDEB: 32626199Ssklower NpDebug = usrarg; 32726199Ssklower break; 32826199Ssklower case NPINIT: 32926199Ssklower error = NpSWinit(mp->unit); 33026199Ssklower break; 33126199Ssklower case NPSTART: 33226199Ssklower 33326199Ssklower #ifdef OLDROM 33426199Ssklower /* 33526199Ssklower * Kludge to work around I-Board boot from Host. Read two bytes 33626199Ssklower * from the board into the Device Configuration Word 33726199Ssklower * in Shared Memory. 33826199Ssklower */ 33926199Ssklower 34026199Ssklower NPIO(mp,(paddr_t)0x500,(paddr_t)(&mp->shmemp->statblock.sb_dcw),2,B_READ); 34126199Ssklower 34226199Ssklower mp->shmemp->statblock.sb_drw = 0; 34326199Ssklower #endif 34426199Ssklower 34526199Ssklower /* Set the Address at which to begin On-Board execution */ 34626199Ssklower 34726199Ssklower error = NpSetXeqAddr(mp,(caddr_t)usrarg); 34826199Ssklower break; 34926199Ssklower case NPSTATS: 35026199Ssklower error = NpStats(); 35126199Ssklower break; 35226199Ssklower case NPGPANIC: 35326199Ssklower error = copyout((caddr_t)NpPbuf,*addr,PANLEN); 35426199Ssklower 35526199Ssklower /* Clear panic request flag and leave */ 35626199Ssklower 35726199Ssklower mp->flags &= ~PANICREQ; 35826199Ssklower break; 35926199Ssklower case NPPOLL: 36026199Ssklower error = NpPoll(mp,*addr); 36126199Ssklower break; 36226199Ssklower case NPKILL: 36326199Ssklower error = NpKill(mp,rp); 36426199Ssklower break; 36526199Ssklower case NPSETADDR: 36626199Ssklower error = NpSetMemAddr(mp,*addr); 36726199Ssklower break; 36826199Ssklower case NPRCSR0: 36926199Ssklower usrarg = RCSR0(mp->iobase); 37026199Ssklower error = copyout((caddr_t)&usrarg,*addr,sizeof(usrarg)); 37126199Ssklower break; 37226199Ssklower case NPRCSR1: 37326199Ssklower usrarg = RCSR1(mp->iobase); 37426199Ssklower error = copyout((caddr_t)&usrarg,*addr,sizeof(usrarg)); 37526199Ssklower break; 37626199Ssklower case NPRCSR2: 37726199Ssklower usrarg = RCSR2(mp->iobase); 37826199Ssklower error = copyout((caddr_t)&usrarg,*addr,sizeof(usrarg)); 37926199Ssklower break; 38026199Ssklower case NPRCSR3: 38126199Ssklower usrarg = RCSR3(mp->iobase); 38226199Ssklower error = copyout((caddr_t)&usrarg,*addr,sizeof(usrarg)); 38326199Ssklower break; 38426199Ssklower case NPWCSR0: 38526199Ssklower WCSR0(mp->iobase,usrarg); 38626199Ssklower break; 38726199Ssklower case NPWCSR1: 38826199Ssklower WCSR1(mp->iobase,usrarg); 38926199Ssklower break; 39026199Ssklower case NPWCSR2: 39126199Ssklower WCSR2(mp->iobase,usrarg); 39226199Ssklower break; 39326199Ssklower case NPWCSR3: 39426199Ssklower WCSR3(mp->iobase,usrarg); 39526199Ssklower break; 39626199Ssklower case NPNETBOOT: 39726199Ssklower error = NpSetIntLevel(mp,mp->vector); 39826199Ssklower if(error) break; 39926199Ssklower error = NpSetXeqAddr(mp,(caddr_t)INETBOOT); 40026199Ssklower break; 40126199Ssklower default: 40226199Ssklower printf("Bad Maintenance command: %d!\n",cmd); 40326199Ssklower error = EIO; 40426199Ssklower break; 40526199Ssklower 40626199Ssklower } 40726199Ssklower if((cmd != NPRESET) && (cmd != NPINIT)) 40826199Ssklower NpFreeReq(mp->reqtab,rp); 40926199Ssklower 41026199Ssklower if(NpDebug & DEBENTRY) 41126199Ssklower printf("npioctl...\n"); 41226199Ssklower 41326199Ssklower return(error); 41426199Ssklower } 41526199Ssklower 41626199Ssklower /* 41726199Ssklower * np_start - start io activity 41826199Ssklower */ 41926199Ssklower npstart(mp) 42026199Ssklower register struct npmaster *mp; 42126199Ssklower { 42226199Ssklower 42326199Ssklower register struct buf *bp; 42426199Ssklower register struct npreq *rp; 42526199Ssklower 42626199Ssklower int error; /* Return from NPIO call */ 42726199Ssklower 42826199Ssklower if(NpDebug & DEBENTRY) 42926199Ssklower printf("npstart\n"); 43026199Ssklower 43126199Ssklower if((bp = np_tab[mp->unit].b_actf) == (struct buf *)0) { 43226199Ssklower np_tab[mp->unit].b_active = 0; 43326199Ssklower return; 43426199Ssklower } 43526199Ssklower if((rp = (struct npreq *)(bp->av_back)) == (struct npreq *)0) { 43626199Ssklower bp->b_flags = B_ERROR; 43726199Ssklower iodone(bp); 43826199Ssklower return; 43926199Ssklower } 44026199Ssklower np_tab[mp->unit].b_active = 1; 44126199Ssklower 44226199Ssklower if(NpDebug & DEBIO) 44326199Ssklower printf("NP IO src %x dst = %x cnt = %x\n",bp->b_un.b_addr,bp->b_blkno << DEV_BSHIFT,bp->b_bcount); 44426199Ssklower 44526199Ssklower /* Send the request to the board via the CSR0 command interface */ 44626199Ssklower 44726199Ssklower if(bp->b_flags & B_READ) 44826199Ssklower 44926199Ssklower error = NPIO(mp,(paddr_t)((long)bp->b_blkno << DEV_BSHIFT),(paddr_t)(rp->bufaddr), 45026199Ssklower bp->b_bcount,(bp->b_flags & B_READ)); 45126199Ssklower 45226199Ssklower else 45326199Ssklower error = NPIO(mp,(paddr_t)(rp->bufaddr),(paddr_t)((long)bp->b_blkno << DEV_BSHIFT), 45426199Ssklower bp->b_bcount,(bp->b_flags & B_READ)); 45526199Ssklower 45626199Ssklower 45726199Ssklower /* Check return from I/O */ 45826199Ssklower 45926199Ssklower if(error) { 46026199Ssklower bp->b_flags |= B_ERROR; 46126199Ssklower np_tab[mp->unit].b_actf = bp->av_forw; 46226199Ssklower 46326199Ssklower if(NpDebug & DEBIO) 46426199Ssklower printf("NPIO return error: b_flags is %x \n",bp->b_flags); 46526199Ssklower iodone(bp); 46626199Ssklower } 46726199Ssklower 46826199Ssklower if(NpDebug & DEBENTRY) 46926199Ssklower printf("npstart...\n"); 47026199Ssklower 47126199Ssklower } 47226199Ssklower /* 47326199Ssklower * npstratagey - the strategy routine 47426199Ssklower */ 47526199Ssklower 47626199Ssklower npstrategy(bp) 47726199Ssklower register struct buf *bp; 47826199Ssklower { 47926199Ssklower 48026199Ssklower register struct buf *ip; /* quick pointer */ 48126199Ssklower register struct npmaster *mp; /* master structure for this device */ 48226199Ssklower register struct npreq *rp; /* reqest struct pointer */ 48326199Ssklower int s; /* priority to return to */ 48426199Ssklower 48526199Ssklower if(NpDebug & DEBENTRY) 48626199Ssklower printf("npstrategy\n"); 48726199Ssklower if(NpDebug & DEBIO) 48826199Ssklower printf("flag = %x count = %x paddr = %x %x blkno = %x %x\n", 48926199Ssklower bp->b_flags,bp->b_bcount,bp->b_un.b_addr,bp->b_un.b_addr,bp->b_blkno,bp->b_blkno); 49026199Ssklower 49126199Ssklower /* get master structure */ 49226199Ssklower 49326199Ssklower mp = npcnxtab[NPUNIT(bp->b_dev)][NPCONN(bp->b_dev)].unit; 49426199Ssklower 49526199Ssklower /* make sure the boards ok */ 49626199Ssklower 49726199Ssklower if (mp->flags & BADBOARD) { 49826199Ssklower bp->b_flags |= B_ERROR; 49926199Ssklower 50026199Ssklower if(NpDebug & DEBMEM) 50126199Ssklower printf("Bad Board %x bp %x\n",mp->flags,bp->b_flags); 50226199Ssklower 50326199Ssklower np_tab[mp->unit].b_actf = bp->av_forw; 50426199Ssklower iodone(bp); 50526199Ssklower return; 50626199Ssklower } 50726199Ssklower 50826199Ssklower /* Initializations of request structure */ 50926199Ssklower 51026199Ssklower while((rp = NpGetReq(mp->reqtab)) == NULL) { 51126199Ssklower mp->reqtab->flags |= WANTREQ; 51226199Ssklower sleep((caddr_t)(mp->reqtab),PZERO -1); 51326199Ssklower } 51426199Ssklower 51526199Ssklower rp->bufoffset = 0; /* This is the start of the buffer */ 51626199Ssklower ip = &np_tab[mp->unit]; 51726199Ssklower bp->av_forw = (struct buf *)0; 51826199Ssklower bp->av_back = (struct buf *)rp; 51926199Ssklower 52026199Ssklower rp->flags |= KERNREQ; /* Mark it as kernel so not to map */ 52126199Ssklower 52226199Ssklower rp->mapbase = ubasetup(mp->devp->ui_ubanum,bp,0); 52326199Ssklower rp->bufaddr = (caddr_t)((int)(rp->mapbase) & UBADDRMASK); 52426199Ssklower 52526199Ssklower s = spl5(); 52626199Ssklower if(ip->b_actf ==(struct buf *)0) 52726199Ssklower ip->b_actf = bp; 52826199Ssklower else { 52926199Ssklower if(ip->b_actf->av_forw) 53026199Ssklower printf("Panic NP100 bad buffer chain\n"); 53126199Ssklower ip->b_actf->av_forw = bp; 53226199Ssklower } 53326199Ssklower ip->b_actl = bp; 53426199Ssklower 53526199Ssklower NpAddReq(mp->reqtab,rp); /* Queue onto active list */ 53626199Ssklower 53726199Ssklower if(ip->b_active == 0) { 53826199Ssklower 53926199Ssklower if(NpDebug & DEBIO) 54026199Ssklower printf("calling npstart %x\n",mp); 54126199Ssklower 54226199Ssklower npstart(mp); 54326199Ssklower } 54426199Ssklower splx(s); 54526199Ssklower 54626199Ssklower if(NpDebug & DEBIO) 54726199Ssklower printf("back from npstart\n"); 54826199Ssklower 54926199Ssklower /* Await completion of I/O */ 55026199Ssklower 55126199Ssklower iowait(bp); 55226199Ssklower 55326199Ssklower if(NpDebug & DEBIO) 55426199Ssklower printf("after iowait in npstrategy\n"); 55526199Ssklower 55626199Ssklower /* Remove request from queue */ 55726199Ssklower 55826199Ssklower NpRemReq(rp); 55926199Ssklower 56026199Ssklower /* Release mapping registers */ 56126199Ssklower 56226199Ssklower ubarelse(mp->devp->ui_ubanum,&rp->mapbase); 56326199Ssklower 56426199Ssklower /* Free up request structure */ 56526199Ssklower 56626199Ssklower NpFreeReq(mp->reqtab,rp); 56726199Ssklower 56826199Ssklower if(NpDebug & DEBENTRY) 56926199Ssklower printf("Leaving npstrategy flags is %x\n",bp->b_flags); 57026199Ssklower } 57126199Ssklower 57226199Ssklower unsigned 57326199Ssklower nptrim(bp) 57426199Ssklower register struct buf *bp; 57526199Ssklower { 57626199Ssklower 57726199Ssklower if(bp->b_bcount > NPMAXXFR) 57826199Ssklower bp->b_bcount = NPMAXXFR; 57926199Ssklower } 58026199Ssklower 58126199Ssklower /* 58226199Ssklower * Npread dumps data from the board to the user's buffer 58326199Ssklower */ 58426199Ssklower npread(dev,uio) 58526199Ssklower dev_t dev; 58626199Ssklower struct uio *uio; 58726199Ssklower { 58826199Ssklower 58926199Ssklower if(NpDebug & DEBENTRY) 59026199Ssklower printf("in npread\n"); 59126199Ssklower 59226199Ssklower return(physio(npstrategy,&npcnxtab[NPUNIT(dev)][NPCONN(dev)].np_rbuf,dev,B_READ ,nptrim,uio)); 59326199Ssklower 59426199Ssklower } 59526199Ssklower 59626199Ssklower /* 59726199Ssklower * Npwrite loads the np100 board from the user's buffer 59826199Ssklower */ 59926199Ssklower 60026199Ssklower npwrite(dev,uio) 60126199Ssklower dev_t dev; 60226199Ssklower struct uio *uio; 60326199Ssklower { 60426199Ssklower struct buf *bp; 60526199Ssklower bp = &npcnxtab[NPUNIT(dev)][NPCONN(dev)].np_wbuf; 60626199Ssklower 60726199Ssklower if(NpDebug & DEBENTRY) 60826199Ssklower printf("in npwrite \n"); 60926199Ssklower 61026199Ssklower return(physio(npstrategy,bp,dev,B_WRITE ,nptrim,uio)); 61126199Ssklower } 61226199Ssklower /* 61326199Ssklower 61426199Ssklower * npreset - called as result of a UNIBUS reset. 61526199Ssklower */ 61626199Ssklower 61726199Ssklower npreset(uban) 61826199Ssklower int uban; 61926199Ssklower { 62026199Ssklower 62126199Ssklower register struct npmaster *mp; 62226199Ssklower register struct npreq *rp; 62326199Ssklower register struct uba_device *ui; 62426199Ssklower int i; 62526199Ssklower 62626199Ssklower for(i = 0; i < NNP; i++) { 62726199Ssklower 62826199Ssklower if(((ui = npdinfo[i]) == (struct uba_device *)NULL) || 62926199Ssklower (ui->ui_ubanum != uban)) 63026199Ssklower continue; 63126199Ssklower 63226199Ssklower mp = &npmasters[i]; 63326199Ssklower mp->iomapbase = 0; 63426199Ssklower NpReset(mp,0); 63526199Ssklower } 63626199Ssklower } 63726199Ssklower 63826199Ssklower /* 63926199Ssklower * Nppoll looks for work by polling each board. He goes to sleep if there are 64026199Ssklower * no outstanding requests for him but reminds the board that he's there when 64126199Ssklower * needed. 64226199Ssklower */ 64326199Ssklower 64426199Ssklower NpPoll(mp,addr) 64526199Ssklower struct npmaster *mp; 64626199Ssklower caddr_t addr; 64726199Ssklower { 64826199Ssklower int error; 64926199Ssklower 65026199Ssklower struct { 65126199Ssklower unsign16 request; 65226199Ssklower unsign16 unit; 65326199Ssklower }icpreq; 65426199Ssklower 65526199Ssklower if(NpDebug & DEBMAINT) 65626199Ssklower printf("NpPoll: flags is %x.\n",mp->flags); 65726199Ssklower 65826199Ssklower while(TRUE) { 65926199Ssklower 66026199Ssklower for(mp = npmasters; mp; mp = mp->next) { 66126199Ssklower 66226199Ssklower if(mp->flags & BOARDREQ) { 66326199Ssklower 66426199Ssklower /* Get request type from master structure */ 66526199Ssklower 66626199Ssklower if(mp->flags & BRDRESET) { 66726199Ssklower icpreq.request = ICPPOLL; 66826199Ssklower mp->reqtab->reqcnt--; 66926199Ssklower 67026199Ssklower if(NpDebug & DEBMAINT) 67126199Ssklower printf("Waking NpResetter!\n"); 67226199Ssklower 67326199Ssklower wakeup((caddr_t)(&mp->reqtab)); 67426199Ssklower } 67526199Ssklower else if(mp->flags & PANICREQ) 67626199Ssklower icpreq.request = ICPPANIC; 67726199Ssklower else if(mp->flags & DUMPREQ) 67826199Ssklower icpreq.request = ICPDUMP; 67926199Ssklower else if(mp->flags & LOADREQ) 68026199Ssklower icpreq.request = ICPLOAD; 68126199Ssklower else { 68226199Ssklower mp->flags &= ~BOARDREQ; 68326199Ssklower continue; 68426199Ssklower } 68526199Ssklower 68626199Ssklower if(NpDebug & DEBMAINT) 68726199Ssklower printf("ProcICP servicing %d \n",icpreq.request ); 68826199Ssklower 68926199Ssklower /* Request and unit number to be sent */ 69026199Ssklower 69126199Ssklower icpreq.unit = mp->unit; 69226199Ssklower 69326199Ssklower /* Copy service request to calling process */ 69426199Ssklower 69526199Ssklower error = copyout(&icpreq,addr,sizeof(icpreq)); 69626199Ssklower 69726199Ssklower /* Mark Poller as being unavailable */ 69826199Ssklower 69926199Ssklower NpState &= ~ICPAVAIL; 70026199Ssklower 70126199Ssklower return(error); 70226199Ssklower } 70326199Ssklower } 70426199Ssklower 70526199Ssklower /* Mark Poller as being available */ 70626199Ssklower 70726199Ssklower NpState |= ICPAVAIL; 70826199Ssklower 70926199Ssklower sleep((caddr_t)&NpState, PZERO + 1); 71026199Ssklower 71126199Ssklower if(NpDebug & DEBMAINT) 71226199Ssklower printf("wakeup in NpPoll\n"); 71326199Ssklower 71426199Ssklower } 71526199Ssklower } 71626199Ssklower 71726199Ssklower /* 71826199Ssklower * Software initialization of Driver data structures for the specified unit. 71926199Ssklower */ 72026199Ssklower 72126199Ssklower NpSWinit(unit) 72226199Ssklower int unit; 72326199Ssklower { 72426199Ssklower 72526199Ssklower register int j; 72626199Ssklower register struct npmaster *mp; 72726199Ssklower register struct npspace *npsp; 72826199Ssklower register struct CmdQue *cqp; 72926199Ssklower int offset; 73026199Ssklower 73126199Ssklower if(NpDebug & DEBINIT) 73226199Ssklower printf("SW reset on unit %d.\n",unit); 73326199Ssklower 73426199Ssklower /* Initialize master structure pointer for this unit */ 73526199Ssklower 73626199Ssklower mp = &npmasters[unit]; 73726199Ssklower 73826199Ssklower /* Initialize unit buffer headers */ 73926199Ssklower 74026199Ssklower np_tab[unit].b_active = 0; 74126199Ssklower np_tab[unit].b_actf = 0; 74226199Ssklower 74326199Ssklower /* UBA device structure for this unit */ 74426199Ssklower 74526199Ssklower mp->devp = npdinfo[unit]; 74626199Ssklower 74726199Ssklower /* Interrupt vector for this unit */ 74826199Ssklower 74926199Ssklower mp->vector = npvectors[unit]; 75026199Ssklower 75126199Ssklower if(unit == (NNP -1)) 75226199Ssklower mp->next = (struct npmaster *)NULL; 75326199Ssklower else mp->next = &npmasters[unit + 1]; 75426199Ssklower 75526199Ssklower /* 75626199Ssklower * Guarantee alignment of shared memory area on a 75726199Ssklower * 16 byte boundary as required by I-Board 75826199Ssklower */ 75926199Ssklower 76026199Ssklower mp->shmemp = &npspaces[unit]; 76126199Ssklower mp->shmemp = (struct npspace *)ROUND16((int)(mp->shmemp)); 76226199Ssklower 76326199Ssklower /* Base address of this controller */ 76426199Ssklower 76526199Ssklower mp->iobase = (struct NPREG *)(mp->devp->ui_addr); 76626199Ssklower 76726199Ssklower if(NpDebug & DEBMEM) { 76826199Ssklower printf("Npspaces starts at %x.\n",npspaces); 76926199Ssklower printf("Shared memory starts at %x.\n",mp->shmemp); 77026199Ssklower printf("End of shared memory is %x.\n",&npspaces[unit + 1]); 77126199Ssklower printf("Iobase is %x.\n",mp->iobase); 77226199Ssklower printf("Npmasters start at %x\n",npmasters); 77326199Ssklower printf("Reqhdr start at %x\n",reqhdr); 77426199Ssklower printf("Npreqs start at %x\n",npreqs); 77526199Ssklower } 77626199Ssklower 77726199Ssklower /* Initialize the request header */ 77826199Ssklower 77926199Ssklower mp->reqtab = &reqhdr[unit]; 78026199Ssklower 78126199Ssklower /* Unit initialization */ 78226199Ssklower 78326199Ssklower mp->unit = unit; 78426199Ssklower 78526199Ssklower /* Initialize Status Block */ 78626199Ssklower 78726199Ssklower npsp = mp->shmemp; 78826199Ssklower offset = (int) (mp->shmemp); 78926199Ssklower 79026199Ssklower npsp->statblock.sb_drw = 0; 79126199Ssklower npsp->statblock.sb_hcw = HOSTCONF; 79226199Ssklower npsp->statblock.sb_dcw = 0; 79326199Ssklower npsp->statblock.sb_dpm = 0; 79426199Ssklower 79526199Ssklower npsp->statblock.sb_dcq = (unsign16)((int)(&npsp->devcq))-offset; 79626199Ssklower 79726199Ssklower npsp->statblock.sb_hcq = (unsign16)((int)(&npsp->hostcq))-offset; 79826199Ssklower 79926199Ssklower /* Initialize Device Command Queue */ 80026199Ssklower 80126199Ssklower cqp = (struct CmdQue *) &npsp->devcq; 80226199Ssklower 80326199Ssklower if(NpDebug & DEBCQ) 80426199Ssklower printf("Device CQ at %x\n",cqp); 80526199Ssklower 80626199Ssklower cqp->scanflag = NPCLEAR; 80726199Ssklower cqp->chngflag = NPCLEAR; 80826199Ssklower 80926199Ssklower cqp->cq_add = (unsign16)(int)(&cqp->cq_cqe[0]) - offset; 81026199Ssklower cqp->cq_rem = cqp->cq_add; 81126199Ssklower 81226199Ssklower cqp->cq_wrap = (unsign16)(int)(&cqp->cq_cqe[NUMCQE]) - offset; 81326199Ssklower 81426199Ssklower for(j = 0; j < NUMCQE; j++) 81526199Ssklower cqp->cq_cqe[j] = (unsign16)NULL; 81626199Ssklower 81726199Ssklower /* Initialize Host Command Queue */ 81826199Ssklower 81926199Ssklower cqp = (struct CmdQue *) &npsp->hostcq; 82026199Ssklower 82126199Ssklower if(NpDebug & DEBCQ) 82226199Ssklower printf("HOST CQ at %x\n",cqp); 82326199Ssklower 82426199Ssklower cqp->scanflag = NPCLEAR; 82526199Ssklower cqp->chngflag = NPCLEAR; 82626199Ssklower 82726199Ssklower cqp->cq_add = (unsign16)(int)(&cqp->cq_cqe[0]) - offset; 82826199Ssklower cqp->cq_rem = cqp->cq_add; 82926199Ssklower 83026199Ssklower cqp->cq_wrap = (unsign16)(int)(&cqp->cq_cqe[NUMCQE]) - offset; 83126199Ssklower 83226199Ssklower for(j = 0; j < NUMCQE; j++) 83326199Ssklower cqp->cq_cqe[j] = (unsign16)NULL; 83426199Ssklower 83526199Ssklower /* 83626199Ssklower * Initialize the reqid of the elements to the address 83726199Ssklower * of the corresponding Npreq structure. These don't change. 83826199Ssklower */ 83926199Ssklower 84026199Ssklower for(j = 0; j < NUMCQE; j++) 84126199Ssklower npsp->elements[j].cqe_reqid = &npreqs[unit][j]; 84226199Ssklower 84326199Ssklower /* 84426199Ssklower * Initialize the Request Header (reqhdr), free list of 84526199Ssklower * npreqs, and pointers to CQEs. 84626199Ssklower */ 84726199Ssklower 84826199Ssklower reqhdr[unit].forw = reqhdr[unit].back = &reqhdr[unit]; 84926199Ssklower reqhdr[unit].free = &npreqs[unit][0]; 85026199Ssklower 85126199Ssklower for(j = 0; j < NUMCQE; j++) { 85226199Ssklower 85326199Ssklower npreqs[unit][j].free = &npreqs[unit][j + 1]; 85426199Ssklower npreqs[unit][j].element = &npsp->elements[j]; 85526199Ssklower npreqs[unit][j].forw = npreqs[unit][j].back = (struct npreq *)NULL; 85626199Ssklower } 85726199Ssklower npreqs[unit][--j].free = &reqhdr[unit]; 85826199Ssklower 85926199Ssklower /* 86026199Ssklower * Set up the UNIBUS I/O Map Registers for the 86126199Ssklower * Shared memory area. 86226199Ssklower */ 86326199Ssklower 86426199Ssklower mp->iomapbase = uballoc(mp->devp->ui_ubanum,(caddr_t)(mp->shmemp),sizeof(struct npspace),0); 86526199Ssklower 86626199Ssklower 86726199Ssklower if(NpDebug & DEBENTRY) 86826199Ssklower printf("SW_Init...\n"); 86926199Ssklower } 87026199Ssklower 87126199Ssklower /* 87226199Ssklower * NpHWinit() issues a hardware reset to the specified board and waits 87326199Ssklower * for on-board diagnostics to complete. It returns 0 if the board is 87426199Ssklower * present and passed diagnostics, an error value otherwise. 87526199Ssklower */ 87626199Ssklower 87726199Ssklower NpHWinit(unit) 87826199Ssklower int unit; 87926199Ssklower { 88026199Ssklower register struct npmaster *mp; 88126199Ssklower struct NPREG *REG; 88226199Ssklower unsign16 status; 88326199Ssklower int dflag; 88426199Ssklower 88526199Ssklower if(unit >= NNP) 88626199Ssklower return(ENXIO); 88726199Ssklower 88826199Ssklower mp = &npmasters[unit]; 88926199Ssklower 89026199Ssklower if(NpDebug & DEBENTRY) 89126199Ssklower printf("NpHWinit\n"); 89226199Ssklower 89326199Ssklower /* See if the board is out there */ 89426199Ssklower 89526199Ssklower REG = (struct NPREG *)mp->iobase; 89626199Ssklower 89726199Ssklower if(NpDebug & DEBINIT) 89826199Ssklower printf("REG in HWinit is %x.\n",mp->iobase); 89926199Ssklower 90026199Ssklower if(!(mp->flags & BRDRESET)) 90126199Ssklower 90226199Ssklower if(badaddr(REG,2)) { 90326199Ssklower mp->flags |= BADBOARD; 90426199Ssklower printf("\nNP100 unit %d not found!\n",unit); 90526199Ssklower return(ENXIO); 90626199Ssklower } 90726199Ssklower 90826199Ssklower 90926199Ssklower #ifdef mc500 91026199Ssklower if(setjmp(u.u_tsav) == 0) { 91126199Ssklower u.u_nofault = TRUE; 91226199Ssklower status = RCSR1(mp->iobase); 91326199Ssklower u.u_nofault = FALSE; 91426199Ssklower } 91526199Ssklower else { 91626199Ssklower np__addr[unit] = 0; 91726199Ssklower mp->flags |= BADBOARD; 91826199Ssklower u.u_error = ENXIO; 91926199Ssklower printf("\nNP100 Unit %x not here!\n",unit); 92026199Ssklower return(0); 92126199Ssklower } 92226199Ssklower #endif 92326199Ssklower 92426199Ssklower if(NpDebug & DEBENTRY) 92526199Ssklower printf("Resetting the NP100 Board at %x\n",mp->iobase); 92626199Ssklower 92726199Ssklower /* Reset the Board */ 92826199Ssklower 92926199Ssklower RESET(mp); 93026199Ssklower 93126199Ssklower dflag = NPCLEAR; 93226199Ssklower 93326199Ssklower timeout(NpTimer,&dflag,DIAGTIME); 93426199Ssklower 93526199Ssklower /* Wait for Enable and Read Data Ready to go high */ 93626199Ssklower 93726199Ssklower while(! ((RCSR1(mp->iobase) & NPENB) && (RCSR1(mp->iobase) & NPRDR))) { 93826199Ssklower if(dflag) 93926199Ssklower break; 94026199Ssklower 94126199Ssklower } 94226199Ssklower 94326199Ssklower untimeout(NpTimer,&dflag); 94426199Ssklower 94526199Ssklower if(NpDebug & DEBINIT) 94626199Ssklower printf("np reset %d \n",dflag); 94726199Ssklower 94826199Ssklower if(dflag) { 94926199Ssklower mp->flags |= BADBOARD; 95026199Ssklower printf("NP100 Unit %d timed out!\n",unit); 95126199Ssklower return(EIO); 95226199Ssklower } 95326199Ssklower 95426199Ssklower status = RCSR0(mp->iobase); 95526199Ssklower 95626199Ssklower /* Check for Hardware OK */ 95726199Ssklower 95826199Ssklower if(!(RCSR1(mp->iobase) & NPHOK)) { 95926199Ssklower mp->flags |= BADBOARD; 96026199Ssklower u.u_error = EIO; 96126199Ssklower printf("NP100 Unit %d Failed diagnostics!\n",unit); 96226199Ssklower printf("Status from CSR0: %x.\n",status); 96326199Ssklower return(EIO); 96426199Ssklower } 96526199Ssklower 96626199Ssklower if(NpDebug & DEBENTRY) 96726199Ssklower printf("HWinit...\n"); 96826199Ssklower 96926199Ssklower return(0); 97026199Ssklower } 97126199Ssklower 97226199Ssklower /* 97326199Ssklower * NP Driver Interrupt Handler 97426199Ssklower */ 97526199Ssklower 97626199Ssklower npintr(unit) 97726199Ssklower int unit; 97826199Ssklower { 97926199Ssklower register struct npmaster *mp; 98026199Ssklower register struct buf *bp; 98126199Ssklower 98226199Ssklower if(NpDebug & DEBENTRY) 98326199Ssklower printf("npintr on unit %d!\n",unit); 98426199Ssklower 98526199Ssklower mp = &npmasters[unit]; 98626199Ssklower 98726199Ssklower if(NpDebug & DEBINTR) 98826199Ssklower printf("npintr mp->flags = %x\n",mp->flags); 98926199Ssklower 99026199Ssklower /* Wake up anyone sleeping on a CSR0 Command */ 99126199Ssklower 99226199Ssklower if(mp->flags & CSRPEND) { 99326199Ssklower 99426199Ssklower mp->flags &= ~CSRPEND; 99526199Ssklower if(np_tab[mp->unit].b_active) { 99626199Ssklower np_tab[mp->unit].b_active = 0; 99726199Ssklower bp = np_tab[mp->unit].b_actf; 99826199Ssklower np_tab[mp->unit].b_actf = bp->av_forw; 99926199Ssklower 100026199Ssklower if(NpDebug & DEBINTR) 100126199Ssklower printf("bp = %x resid = %d forw = %x\n",bp, 100226199Ssklower bp->b_resid,bp->av_forw); 100326199Ssklower 100426199Ssklower bp->b_resid = 0; 100526199Ssklower iodone(bp); 100626199Ssklower } 100726199Ssklower if(mp->flags & PANIC3) { 100826199Ssklower mp->flags &= ~PANIC3; 100926199Ssklower mp->flags = AVAILABLE; 101026199Ssklower ubarelse(mp->devp->ui_ubanum,&panicmap); 101126199Ssklower } 101226199Ssklower if(mp->flags & PANIC2) { 101326199Ssklower mp->flags &= ~PANIC2; 101426199Ssklower printf("Panic Message: %s",NpPbuf); 101526199Ssklower mp->flags |= PANIC3; 101626199Ssklower NpPbuf[0] = 0; 101726199Ssklower NPIO(mp,(paddr_t)((int) panicmap & UBADDRMASK),(paddr_t)pstring,sizeof(NpPbuf),B_WRITE); 101826199Ssklower } 101926199Ssklower if(mp->flags & PANIC1) { 102026199Ssklower mp->flags &= ~PANIC1; 102126199Ssklower mp->flags |= PANIC2; 102226199Ssklower ubarelse(mp->devp->ui_ubanum,&panicmap); 102326199Ssklower panicmap = uballoc(mp->devp->ui_ubanum,(caddr_t)NpPbuf,sizeof(NpPbuf),0); 102426199Ssklower pstring = (caddr_t)((panaddr[1] << 4) + panaddr[0]); 102526199Ssklower NPIO(mp,(paddr_t)pstring,(paddr_t)((int) panicmap & UBADDRMASK),sizeof(NpPbuf),B_READ); 102626199Ssklower } 102726199Ssklower 102826199Ssklower wakeup((caddr_t)mp); 102926199Ssklower goto out; 103026199Ssklower } 103126199Ssklower 103226199Ssklower /* Mark unit as being available if Device Protocol Mask set */ 103326199Ssklower 103426199Ssklower if(!(mp->flags & AVAILABLE)) { 103526199Ssklower 103626199Ssklower if((mp->shmemp->statblock.sb_dpm) && (!(mp->flags & BRDRESET))){ 103726199Ssklower 103826199Ssklower mp->flags = AVAILABLE; 103926199Ssklower printf("\nNP100 unit #%d available!\n",mp->unit); 104026199Ssklower } 104126199Ssklower } 104226199Ssklower 104326199Ssklower /* Honor service requests from the device */ 104426199Ssklower 104526199Ssklower switch(mp->shmemp->statblock.sb_drw) { 104626199Ssklower 104726199Ssklower case NOREQ: 104826199Ssklower break; 104926199Ssklower 105026199Ssklower case NPPANIC: 105126199Ssklower 105226199Ssklower printf("\nPanic from NP100 unit %d!\n",mp->unit); 105326199Ssklower mp->flags &= ~AVAILABLE; 105426199Ssklower mp->flags |= PANIC1; 105526199Ssklower 105626199Ssklower /* Clear device request word */ 105726199Ssklower 105826199Ssklower mp->shmemp->statblock.sb_drw = 0; 105926199Ssklower 106026199Ssklower panicmap = uballoc(mp->devp->ui_ubanum,(caddr_t)panaddr,sizeof(panaddr),0); 106126199Ssklower NPIO(mp,(paddr_t)NPPSADDR,(paddr_t)((int)panicmap & UBADDRMASK),sizeof(panaddr),B_READ); 106226199Ssklower goto out; 106326199Ssklower break; 106426199Ssklower 106526199Ssklower case NPDUMP: 106626199Ssklower mp->flags |= (DUMPREQ | BOARDREQ); 106726199Ssklower 106826199Ssklower /* Clear device request word */ 106926199Ssklower 107026199Ssklower mp->shmemp->statblock.sb_drw = 0; 107126199Ssklower 107226199Ssklower if(NpState & ICPAVAIL) 107326199Ssklower wakeup((caddr_t)&NpState); 107426199Ssklower break; 107526199Ssklower 107626199Ssklower case NPLOAD: 107726199Ssklower mp->flags |= (LOADREQ | BOARDREQ); 107826199Ssklower 107926199Ssklower /* Clear device request word */ 108026199Ssklower 108126199Ssklower mp->shmemp->statblock.sb_drw = 0; 108226199Ssklower 108326199Ssklower if(NpState & ICPAVAIL) 108426199Ssklower wakeup((caddr_t)&NpState); 108526199Ssklower break; 108626199Ssklower 108726199Ssklower default: 108826199Ssklower printf("Bad Req: %x.\n",mp->shmemp->statblock.sb_drw); 108926199Ssklower goto out; 109026199Ssklower 109126199Ssklower } 109226199Ssklower 109326199Ssklower /* Process the Host Command Queue for this device */ 109426199Ssklower 109526199Ssklower NpProcQueue(mp); 109626199Ssklower 109726199Ssklower out: 109826199Ssklower CLEARINT(mp); /* Clear the interrupt */ 109926199Ssklower 110026199Ssklower if(NpDebug & DEBENTRY) 110126199Ssklower printf("npintr...\n"); 110226199Ssklower 110326199Ssklower return(1); /* Interrupt serviced */ 110426199Ssklower 110526199Ssklower } 110626199Ssklower 110726199Ssklower /* 110826199Ssklower * This routine, called from the interrupt handler, is used to process the 110926199Ssklower * Host Command Queue for the specified device. 111026199Ssklower */ 111126199Ssklower 111226199Ssklower NpProcQueue(mp) 111326199Ssklower struct npmaster *mp; 111426199Ssklower { 111526199Ssklower register struct CmdQue *cqp; 111626199Ssklower register struct CQE *ep; 111726199Ssklower register struct npreq *rp; 111826199Ssklower register int base; 111926199Ssklower 112026199Ssklower if(NpDebug & DEBENTRY) 112126199Ssklower printf("NpProcQueue\n"); 112226199Ssklower 112326199Ssklower cqp = &mp->shmemp->hostcq; /* Command Queue pointer */ 112426199Ssklower 112526199Ssklower if(cqp->scanflag & ON) 112626199Ssklower return; 112726199Ssklower 112826199Ssklower else cqp->scanflag | = ON; 112926199Ssklower 113026199Ssklower base = (int)mp->shmemp; /* Shared memory base address */ 113126199Ssklower 113226199Ssklower while(cqp->scanflag & ON) { 113326199Ssklower 113426199Ssklower while(ep = NpRemCQE(cqp,base)) { 113526199Ssklower 113626199Ssklower rp = ep->cqe_reqid; 113726199Ssklower 113826199Ssklower if(NpDebug & DEBCQE) 113926199Ssklower printf("cqe_sts is %x ep = %x\n",ep->cqe_sts,ep); 114026199Ssklower 114126199Ssklower switch (ep->cqe_sts) { 114226199Ssklower 114326199Ssklower case NPDONE: 114426199Ssklower rp->flags |= REQDONE; /* Normal completion */ 114526199Ssklower break; 114626199Ssklower case NPIFC: /* IFC Request */ 114726199Ssklower rp->flags |= IOIFC; 114826199Ssklower break; 114926199Ssklower case NPPERR: /* Protocol Error */ 115026199Ssklower rp->flags |= (NPPERR | REQDONE); 115126199Ssklower break; 115226199Ssklower case NPMERR: /* Memory allocation */ 115326199Ssklower rp->flags |= (NPMERR | REQDONE); 115426199Ssklower break; 115526199Ssklower default: /* Error on Board */ 115626199Ssklower rp->flags |= (IOERR | REQDONE); 115726199Ssklower break; 115826199Ssklower 115926199Ssklower } 116026199Ssklower 116126199Ssklower if(NpDebug & DEBCQE) { 116226199Ssklower printf("flag is %x reqid = %x\n",rp->flags,ep->cqe_reqid); 116326199Ssklower printf("wakeup in procqueue\n"); 116426199Ssklower } 116526199Ssklower 116626199Ssklower if(rp->intr) { 116726199Ssklower 116826199Ssklower if(NpDebug & DEBINTR) 116926199Ssklower printf("calling usr intr at %x\n", 117026199Ssklower rp->intr); 117126199Ssklower 117226199Ssklower /* Call interrupt routine */ 117326199Ssklower 117426199Ssklower (*rp->intr)(mp,rp); 117526199Ssklower 117626199Ssklower } 117726199Ssklower else { 117826199Ssklower 117926199Ssklower if(NpDebug & DEBINTR) 118026199Ssklower printf("waking up %x\n",rp); 118126199Ssklower 118226199Ssklower if(rp->flags & NPUIO) 118326199Ssklower iodone(&rp->buf); 118426199Ssklower else wakeup((caddr_t) (rp)); /* Awaken */ 118526199Ssklower 118626199Ssklower if(NpDebug & DEBINTR) 118726199Ssklower printf("AWAKE\n"); 118826199Ssklower } 118926199Ssklower 119026199Ssklower } 119126199Ssklower 119226199Ssklower if(!(cqp->chngflag & ON)) 119326199Ssklower cqp->scanflag &= ~ON; 119426199Ssklower 119526199Ssklower } 119626199Ssklower 119726199Ssklower if(NpDebug & DEBENTRY) 119826199Ssklower printf("NpProcQueue...\n"); 119926199Ssklower } 120026199Ssklower 120126199Ssklower /* 120226199Ssklower * NpIFC - processes an IFC (Internal Fuction Call) request 120326199Ssklower * NOTE: this function must be called from the user context 120426199Ssklower * on all virtual pageing systems 120526199Ssklower * 120626199Ssklower */ 120726199Ssklower NpIFC(mp,rp) 120826199Ssklower register struct npmaster *mp; 120926199Ssklower register struct npreq *rp; 121026199Ssklower { 121126199Ssklower register struct CQE *ep; 121226199Ssklower 121326199Ssklower if(NpDebug & DEBENTRY) 121426199Ssklower printf("NpIFC\n"); 121526199Ssklower 121626199Ssklower ep = rp->element; 121726199Ssklower rp->flags &= ~IOIFC; 121826199Ssklower switch(ep->cqe_func) { 121926199Ssklower 122026199Ssklower case NPUNLOCK: /* Unlock process, free up mapping registers */ 122126199Ssklower 122226199Ssklower if(NpDebug & DEBIFC) 122326199Ssklower printf("NPUNLOCK\n"); 122426199Ssklower 122526199Ssklower if(rp->mapbase) 122626199Ssklower NpUnMapMem(mp,rp); 122726199Ssklower break; 122826199Ssklower 122926199Ssklower case NPLOCK: /* Lock process, get mapping registers */ 123026199Ssklower 123126199Ssklower if(NpDebug & DEBIFC) 123226199Ssklower printf("NPLOCK\n"); 123326199Ssklower NpMapMem(mp,rp,rp->virtmem,rp->bytecnt); 123426199Ssklower ep->cqe_dma[0] = LOWORD(rp->bufaddr); 123526199Ssklower ep->cqe_dma[1] = HIWORD(rp->bufaddr); 123626199Ssklower break; 123726199Ssklower 123826199Ssklower case NPREMAP: 123926199Ssklower 124026199Ssklower if(NpDebug & DEBIFC) 124126199Ssklower printf("NPREMAP\n"); 124226199Ssklower 124326199Ssklower /* Remap user buffer and update buffer offset */ 124426199Ssklower #ifdef USG 124526199Ssklower np_remapmem(rp,rp->virtmem); 124626199Ssklower ep->cqe_dma[0] = LOWORD(rp->bufaddr); 124726199Ssklower ep->cqe_dma[1] = HIWORD(rp->bufaddr); 124826199Ssklower break; 124926199Ssklower #endif 125026199Ssklower 125126199Ssklower default: 125226199Ssklower if(NpDebug & DEBIFC) 125326199Ssklower printf("Bad case %x in IFC\n", ep->cqe_func); 125426199Ssklower 125526199Ssklower rp->flags |= (REQDONE | IOERR); 125626199Ssklower break; 125726199Ssklower } 125826199Ssklower } 125926199Ssklower 126026199Ssklower /* 126126199Ssklower * The following contains various routines for allocating and deallocating 126226199Ssklower * structures used by the NP Driver. Routines are also here for addding 126326199Ssklower * and removing Command Queue Elements from a Command Queue. 126426199Ssklower */ 126526199Ssklower 126626199Ssklower /* 126726199Ssklower * Get a free NP Request structure from the list pointed to by head. Returns 126826199Ssklower * a pointer to a npreq or NULL if none left. 126926199Ssklower */ 127026199Ssklower 127126199Ssklower struct npreq * 127226199Ssklower NpGetReq(head) 127326199Ssklower struct npreq *head; 127426199Ssklower { 127526199Ssklower 127626199Ssklower register struct npreq *p; 127726199Ssklower 127826199Ssklower p = head->free; 127926199Ssklower head->free = p->free; 128026199Ssklower return(p==head ? (struct npreq *)NULL : p); 128126199Ssklower } 128226199Ssklower 128326199Ssklower /* 128426199Ssklower * Return a NP Request structure to the free list pointed to by head. 128526199Ssklower */ 128626199Ssklower 128726199Ssklower NpFreeReq(head,nprp) 128826199Ssklower register struct npreq *head, *nprp; 128926199Ssklower { 129026199Ssklower 129126199Ssklower if(NpDebug & DEBREQ) 129226199Ssklower printf("NpFreeReq, head is %x rp is %x\n",head,nprp); 129326199Ssklower 129426199Ssklower nprp->forw = nprp->back = (struct npreq *)NULL; 129526199Ssklower nprp->free = head->free; 129626199Ssklower head->free = nprp; 129726199Ssklower 129826199Ssklower /* Wake up any processes waiting for a request structure */ 129926199Ssklower 130026199Ssklower if(head->flags & WANTREQ) { 130126199Ssklower head->flags &= ~WANTREQ; 130226199Ssklower wakeup((caddr_t)head); 130326199Ssklower } 130426199Ssklower 130526199Ssklower if(NpDebug & DEBENTRY) 130626199Ssklower printf("NpFreeReq...\n"); 130726199Ssklower } 130826199Ssklower 130926199Ssklower /* 131026199Ssklower * Add a Command Queue Element onto the specified Command Queue and 131126199Ssklower * update its Add offset. 131226199Ssklower */ 131326199Ssklower 131426199Ssklower NpAddCQE(ep,cqp,mp) 131526199Ssklower struct CQE *ep; 131626199Ssklower struct CmdQue *cqp; 131726199Ssklower struct npmaster *mp; 131826199Ssklower { 131926199Ssklower 132026199Ssklower register unsign16 *temp; 132126199Ssklower register unsign16 cqe_offset; 132226199Ssklower register int base; 132326199Ssklower 132426199Ssklower base = (int)mp->shmemp; /* Shared memory base address */ 132526199Ssklower 132626199Ssklower temp = (unsign16 *)(base + cqp->cq_add); /* Offset to add element */ 132726199Ssklower 132826199Ssklower cqe_offset = (unsign16)((int)ep - base); 132926199Ssklower 133026199Ssklower if(*temp) { /* Should never happen */ 133126199Ssklower 133226199Ssklower printf("No more room on Command Queue!\n"); 133326199Ssklower u.u_error = EIO; 133426199Ssklower return; 133526199Ssklower } 133626199Ssklower else *temp = cqe_offset; /* Enter this request's offset */ 133726199Ssklower 133826199Ssklower cqp->chngflag |= ON; /* Set change flag unconditionally */ 133926199Ssklower 134026199Ssklower /* Update cqe_add where next request is to be added */ 134126199Ssklower 134226199Ssklower cqp->cq_add += sizeof(unsign16); 134326199Ssklower 134426199Ssklower if(cqp->cq_add == cqp->cq_wrap) /* Wrap if necessary */ 134526199Ssklower cqp->cq_add = (unsign16)((int)cqp->cq_cqe - base); 134626199Ssklower 134726199Ssklower /* Interrupt the Board if his scan flag isn't on */ 134826199Ssklower 134926199Ssklower if(!(cqp->scanflag & ON)) 135026199Ssklower 135126199Ssklower INTNI(mp); /* Interrupt the Board */ 135226199Ssklower 135326199Ssklower } 135426199Ssklower 135526199Ssklower /* 135626199Ssklower * The NpRemCQE routine is used to remove the next CQE from the Command Queue 135726199Ssklower * specified by cqp. The common offset of shared memory used by the device 135826199Ssklower * is specified by base. NpRemCQE returns a pointer to the next CQE or 135926199Ssklower * NULL if there are none left. This routine will also update the cqe_rem 136026199Ssklower * offset which specifies where the next element to be removed from the 136126199Ssklower * queue is located. 136226199Ssklower */ 136326199Ssklower 136426199Ssklower struct CQE * 136526199Ssklower NpRemCQE(cqp,base) 136626199Ssklower struct CmdQue *cqp; 136726199Ssklower int base; 136826199Ssklower { 136926199Ssklower 137026199Ssklower register unsign16 *temp; 137126199Ssklower register unsign16 cqe_offset; 137226199Ssklower 137326199Ssklower cqp->chngflag &= ~ON; /* Turn off unconditionally */ 137426199Ssklower 137526199Ssklower /* Get address of element to remove */ 137626199Ssklower 137726199Ssklower temp = (unsign16 *)(base +cqp->cq_rem); 137826199Ssklower 137926199Ssklower if(*temp == NULL) /* If none left, go home */ 138026199Ssklower return((struct CQE *) NULL); 138126199Ssklower 138226199Ssklower else cqe_offset = *temp; /* Offset of CQE to remove */ 138326199Ssklower 138426199Ssklower /* Update the Command Queue's cqe_rem offset */ 138526199Ssklower 138626199Ssklower *temp = NULL; /* Clear out this entry */ 138726199Ssklower 138826199Ssklower cqp->cq_rem += sizeof(unsign16); /* Bump offset */ 138926199Ssklower 139026199Ssklower if(cqp->cq_rem == cqp->cq_wrap) /* Wrap if necessary */ 139126199Ssklower cqp->cq_rem = (unsign16)((int)cqp->cq_cqe - base); 139226199Ssklower 139326199Ssklower temp = (unsign16 *)(base + cqe_offset); /* CQE address */ 139426199Ssklower return((struct CQE *)temp); /* is returned */ 139526199Ssklower } 139626199Ssklower 139726199Ssklower /* 139826199Ssklower * NpAddReq will add the specified npreq structure to the queue controlled 139926199Ssklower * by head. 140026199Ssklower */ 140126199Ssklower 140226199Ssklower NpAddReq(head,rp) 140326199Ssklower register struct npreq *head, *rp; 140426199Ssklower { 140526199Ssklower 140626199Ssklower if(NpDebug & DEBENTRY) 140726199Ssklower printf("NpAddReq\n"); 140826199Ssklower 140926199Ssklower if(NpDebug & DEBREQ) 141026199Ssklower printf("NpAddReq: %x\n",rp); 141126199Ssklower 141226199Ssklower rp->forw = head->forw; 141326199Ssklower rp->forw->back = rp; 141426199Ssklower rp->back = head; 141526199Ssklower head->forw = rp; 141626199Ssklower 141726199Ssklower if(NpDebug & DEBENTRY) 141826199Ssklower printf("NpAddReq...\n"); 141926199Ssklower } 142026199Ssklower 142126199Ssklower /* 142226199Ssklower * NpRemReq is used to remove a npreq structure from the queue specified by 142326199Ssklower * head. 142426199Ssklower */ 142526199Ssklower 142626199Ssklower NpRemReq(rp) 142726199Ssklower register struct npreq *rp; 142826199Ssklower { 142926199Ssklower 143026199Ssklower if(NpDebug & DEBENTRY) 143126199Ssklower printf("NpRemReq\n"); 143226199Ssklower 143326199Ssklower if(NpDebug & DEBREQ) 143426199Ssklower printf("NpRemReq: %x\n",rp); 143526199Ssklower 143626199Ssklower rp->back->forw = rp->forw; 143726199Ssklower rp->forw->back = rp->back; 143826199Ssklower 143926199Ssklower if(NpDebug & DEBENTRY) 144026199Ssklower printf("NpRemReq...\n"); 144126199Ssklower } 144226199Ssklower 144326199Ssklower 144426199Ssklower /* 144526199Ssklower * The following routines are used to communicate with the 144626199Ssklower * NI Hardware via the CSR0 commands. These commands are issued during 144726199Ssklower * the hardware initializtion process and may also be used subsequently 144826199Ssklower * by privileged processes who wish to communicate in this way. The 144926199Ssklower * convention for passing data as a Command Block is discussed in detail 145026199Ssklower * in the NI1510 UNIBUS Compatible Ethernet Communications Processor 145126199Ssklower * Hardware Specification. 145226199Ssklower */ 145326199Ssklower 145426199Ssklower NpSendCSR0(iobase,src,bcount) 145526199Ssklower struct NPREG *iobase; 145626199Ssklower register unsign16 *src; 145726199Ssklower int bcount; 145826199Ssklower { 145926199Ssklower register int wcount; 146026199Ssklower int i; 146126199Ssklower int csrflag; 146226199Ssklower unsign16 tmp; 146326199Ssklower 146426199Ssklower if(NpDebug & DEBENTRY) 146526199Ssklower printf("NpSendCSR0\n"); 146626199Ssklower 146726199Ssklower /* Jolt the board into CSR0 command mode if necessary */ 146826199Ssklower 146926199Ssklower if(!(RCSR1(iobase) & NPENB)){ 147026199Ssklower tmp = NPCLEAR; /* MC68000 clr reads before writing */ 147126199Ssklower WCSR0(iobase,tmp); 147226199Ssklower } 147326199Ssklower 147426199Ssklower wcount = (bcount +1) >> 1; /* Convert byte count to word count */ 147526199Ssklower 147626199Ssklower /* Clear timer flag before beginning the timer */ 147726199Ssklower 147826199Ssklower csrflag = NPCLEAR; 147926199Ssklower timeout(NpTimer,&csrflag,DIAGTIME); 148026199Ssklower 148126199Ssklower for(i = 0; (i < wcount) & (csrflag == NPCLEAR); i++) { 148226199Ssklower while(! ((RCSR1(iobase) & NPENB) && (RCSR1(iobase) & NPRDY))) 148326199Ssklower if(csrflag) break; 148426199Ssklower WCSR0(iobase,*src); 148526199Ssklower src++; /* Better do this WCSR is a macro */ 148626199Ssklower } 148726199Ssklower 148826199Ssklower /* Clear the timer entry */ 148926199Ssklower 149026199Ssklower untimeout(NpTimer,&csrflag); 149126199Ssklower 149226199Ssklower /* Error if timer went off */ 149326199Ssklower 149426199Ssklower if(csrflag) 149526199Ssklower return(EIO); 149626199Ssklower 149726199Ssklower if(NpDebug & DEBENTRY) 149826199Ssklower printf("NpSendCSR0...\n"); 149926199Ssklower return(0); 150026199Ssklower } 150126199Ssklower 150226199Ssklower /* 150326199Ssklower * NpSetIntLev sets the UNIBUS interrupt vector to be used by the NP board when 150426199Ssklower * interupting the host. The board is specified by mp. 150526199Ssklower */ 150626199Ssklower 150726199Ssklower NpSetIntLevel(mp,level) 150826199Ssklower struct npmaster *mp; 150926199Ssklower int level; 151026199Ssklower { 151126199Ssklower 151226199Ssklower struct { 151326199Ssklower unsign16 cmd_word; 151426199Ssklower unsign16 int_level; 151526199Ssklower }cmd_block; 151626199Ssklower 151726199Ssklower cmd_block.cmd_word = NPCBI | CBICNT; 151826199Ssklower cmd_block.int_level = level; 151926199Ssklower 152026199Ssklower return(NpSendCSR0(mp->iobase,(unsign16 *)&cmd_block,(int)sizeof(cmd_block))); 152126199Ssklower } 152226199Ssklower 152326199Ssklower /* 152426199Ssklower * NpSetMemAddr is used to declare the shared memory area address to be used 152526199Ssklower * for communication between the driver and the device. This address is used 152626199Ssklower * to access data structures by acting as a base from which defined offsets 152726199Ssklower * locate data. The board is specified by mp. 152826199Ssklower */ 152926199Ssklower 153026199Ssklower NpSetMemAddr(mp,addr) 153126199Ssklower struct npmaster *mp; 153226199Ssklower caddr_t addr; 153326199Ssklower { 153426199Ssklower 153526199Ssklower caddr_t shmaddr; 153626199Ssklower int error; 153726199Ssklower 153826199Ssklower struct { 153926199Ssklower unsign16 cmd_word; 154026199Ssklower unsign16 hi_addr; 154126199Ssklower unsign16 lo_addr; 154226199Ssklower } cmd_block; 154326199Ssklower 154426199Ssklower if(NpDebug & DEBENTRY) 154526199Ssklower printf("NpSetMemAddr\n"); 154626199Ssklower 154726199Ssklower shmaddr = addr; 154826199Ssklower 154926199Ssklower if(NpDebug & DEBMEM) 155026199Ssklower printf("NpSetMemAddr, addr is %x shmaddr is %x.\n",addr,shmaddr); 155126199Ssklower 155226199Ssklower cmd_block.cmd_word = NPCMD | CMDCNT; 155326199Ssklower cmd_block.hi_addr = HIWORD(shmaddr); 155426199Ssklower cmd_block.lo_addr = LOWORD(shmaddr); 155526199Ssklower 155626199Ssklower error = NpSendCSR0(mp->iobase,(unsign16 *)&cmd_block,(int)sizeof(cmd_block)); 155726199Ssklower 155826199Ssklower if(NpDebug & DEBENTRY) 155926199Ssklower printf("NpSetMemAddr...\n"); 156026199Ssklower 156126199Ssklower return(error); 156226199Ssklower } 156326199Ssklower 156426199Ssklower 156526199Ssklower /* 156626199Ssklower * NpSetXeqAddr specifies the address at which the board should begin 156726199Ssklower * execution of its on-board software. It also indicates the shared memory 156826199Ssklower * address to be used. The board is specified by mp. 156926199Ssklower */ 157026199Ssklower 157126199Ssklower NpSetXeqAddr(mp,addr) 157226199Ssklower struct npmaster *mp; 157326199Ssklower caddr_t addr; 157426199Ssklower { 157526199Ssklower caddr_t shmaddr; 157626199Ssklower int error; 157726199Ssklower 157826199Ssklower struct { 157926199Ssklower unsign16 cmd_word; 158026199Ssklower unsign16 hi_addr; 158126199Ssklower unsign16 lo_addr; 158226199Ssklower unsign16 mhi_addr; 158326199Ssklower unsign16 mlo_addr; 158426199Ssklower } cmd_block; 158526199Ssklower 158626199Ssklower if(NpDebug & DEBENTRY) 158726199Ssklower printf("NpSetXeqAddr\n"); 158826199Ssklower 158926199Ssklower shmaddr = (caddr_t)((int)mp->iomapbase & UBADDRMASK); 159026199Ssklower 159126199Ssklower cmd_block.cmd_word = NPBGN | NPCMD | NPLST | (BGNCNT + CMDCNT); 159226199Ssklower cmd_block.hi_addr = HIWORD(addr); 159326199Ssklower cmd_block.lo_addr = LOWORD(addr); 159426199Ssklower cmd_block.mhi_addr = HIWORD(shmaddr); 159526199Ssklower cmd_block.mlo_addr = LOWORD(shmaddr); 159626199Ssklower 159726199Ssklower if(NpDebug & DEBINIT) { 159826199Ssklower printf("NpSetXeqAdddr: hi: %x lo: %x\n",HIWORD(addr), LOWORD(addr)); 159926199Ssklower printf("NpSetXeqAdddr: mhi: %x mlo: %x\n",HIWORD(shmaddr),LOWORD(shmaddr)); 160026199Ssklower } 160126199Ssklower 160226199Ssklower error = NpSendCSR0(mp->iobase,(unsign16 *)&cmd_block,(int)sizeof(cmd_block)); 160326199Ssklower 160426199Ssklower if(NpDebug & DEBENTRY) 160526199Ssklower printf("NpSetXeqAddr...\n"); 160626199Ssklower 160726199Ssklower return(error); 160826199Ssklower } 160926199Ssklower 161026199Ssklower /* 161126199Ssklower * NPIO issues a CSR0 load or dump request to the I-Board after packaging a 161226199Ssklower * CSR0 Command Block. 161326199Ssklower */ 161426199Ssklower 161526199Ssklower NPIO(mp,src,dest,count,dir) 161626199Ssklower struct npmaster *mp; 161726199Ssklower paddr_t dest; 161826199Ssklower paddr_t src; 161926199Ssklower unsign16 count; 162026199Ssklower int dir; /* Direction READ/WRITE */ 162126199Ssklower { 162226199Ssklower 162326199Ssklower int error; 162426199Ssklower 162526199Ssklower struct { 162626199Ssklower unsign16 cmd_word; /* Command Word */ 162726199Ssklower unsign16 shi_addr; /* High word of Source Address */ 162826199Ssklower unsign16 slo_addr; /* Low word of Source Address */ 162926199Ssklower unsign16 dhi_addr; /* High word of Destination Address */ 163026199Ssklower unsign16 dlo_addr; /* Low word of Destination Address */ 163126199Ssklower unsign16 count; /* Byte count */ 163226199Ssklower unsign16 intlevel; /* Interrupt level to host */ 163326199Ssklower } cmd_block; 163426199Ssklower 163526199Ssklower if(NpDebug & DEBENTRY) 163626199Ssklower printf("NPIO\n"); 163726199Ssklower if(NpDebug & DEBMAINT) { 163826199Ssklower printf("I/O src addr = %x, dest addr = %x \n",src,dest); 163926199Ssklower printf("I/O count = %d \n",count); 164026199Ssklower } 164126199Ssklower 164226199Ssklower cmd_block.cmd_word = NPCBI | NPLST | (CBICNT + IOCNT); 164326199Ssklower cmd_block.intlevel = mp->vector; 164426199Ssklower cmd_block.shi_addr = HIWORD(src); 164526199Ssklower cmd_block.slo_addr = LOWORD(src); 164626199Ssklower cmd_block.dhi_addr = HIWORD(dest); 164726199Ssklower cmd_block.dlo_addr = LOWORD(dest); 164826199Ssklower cmd_block.count = count; 164926199Ssklower if(dir == B_READ) 165026199Ssklower cmd_block.cmd_word |= NPDMP; 165126199Ssklower else 165226199Ssklower cmd_block.cmd_word |= NPLD; 165326199Ssklower 165426199Ssklower 165526199Ssklower if(NpDebug & DEBIO) { 165626199Ssklower printf("cmd: %x int: %o shi: %x slo: %x dhi: %x dlo: %x cnt: %x\n", 165726199Ssklower cmd_block.cmd_word,cmd_block.intlevel,cmd_block.shi_addr,cmd_block.slo_addr, 165826199Ssklower cmd_block.dhi_addr,cmd_block.dlo_addr,cmd_block.count); 165926199Ssklower } 166026199Ssklower 166126199Ssklower mp->flags |= CSRPEND; /* CSR0 command pending */ 166226199Ssklower 166326199Ssklower error = NpSendCSR0(mp->iobase,(unsign16 *)&cmd_block,(int)sizeof(cmd_block)); 166426199Ssklower if(NpDebug & DEBENTRY) 166526199Ssklower printf("NPIO...\n"); 166626199Ssklower 166726199Ssklower return(error); 166826199Ssklower } 166926199Ssklower 167026199Ssklower 167126199Ssklower /* 167226199Ssklower * NpKill will terminate all outstanding requests for the specified board. 167326199Ssklower */ 167426199Ssklower 167526199Ssklower NpKill(mp,curr_rp) 167626199Ssklower struct npmaster *mp; 167726199Ssklower struct npreq *curr_rp; 167826199Ssklower { 167926199Ssklower struct npreq *rp; 168026199Ssklower int s; 168126199Ssklower 168226199Ssklower if(NpDebug & DEBENTRY) 168326199Ssklower printf("NpKill\n"); 168426199Ssklower 168526199Ssklower mp->reqtab->reqcnt = 0; /* Init request count */ 168626199Ssklower 168726199Ssklower s = spl4(); /* Disable interrupts */ 168826199Ssklower 168926199Ssklower /* Mark each active request as having an error and wake him up */ 169026199Ssklower 169126199Ssklower for(rp = mp->reqtab->forw;rp != mp->reqtab;rp = rp->forw) { 169226199Ssklower 169326199Ssklower if(rp == curr_rp) continue; 169426199Ssklower 169526199Ssklower rp->flags |= (IOABORT | REQDONE); 169626199Ssklower mp->reqtab->reqcnt++; 169726199Ssklower if(rp->flags & NPUIO) 169826199Ssklower iodone(&rp->buf); 169926199Ssklower else wakeup((caddr_t)rp); 170026199Ssklower } 170126199Ssklower 170226199Ssklower if(NpDebug & DEBMAINT) 170326199Ssklower printf("NpKill, req count is %d\n",mp->reqtab->reqcnt); 170426199Ssklower 170526199Ssklower splx(s); 170626199Ssklower 170726199Ssklower if(NpDebug & DEBENTRY) 170826199Ssklower printf("NpKill...\n"); 170926199Ssklower 171026199Ssklower return(0); 171126199Ssklower 171226199Ssklower } 171326199Ssklower 171426199Ssklower /* Hardware and Software Initializations for the specified unit */ 171526199Ssklower 171626199Ssklower NpReset(mp,rp) 171726199Ssklower register struct npmaster *mp; 171826199Ssklower struct npreq *rp; 171926199Ssklower { 172026199Ssklower int error; 172126199Ssklower 172226199Ssklower if(NpDebug & DEBENTRY) 172326199Ssklower printf("NpReset!\n"); 172426199Ssklower 172526199Ssklower /* Mark board as being reset and make unavailable */ 172626199Ssklower 172726199Ssklower mp->flags = BRDRESET; 172826199Ssklower 172926199Ssklower /* Abort outstanding requests for this board */ 173026199Ssklower 173126199Ssklower mp->reqtab->reqcnt = 0; /* Init request count */ 173226199Ssklower 173326199Ssklower /* Wakeup Poller if available and wait until he's gone */ 173426199Ssklower 173526199Ssklower if(NpState & ICPAVAIL) { 173626199Ssklower 173726199Ssklower mp->flags |= BOARDREQ; 173826199Ssklower mp->reqtab->reqcnt++; 173926199Ssklower 174026199Ssklower if(NpDebug & DEBMAINT) 174126199Ssklower printf("Waking ICP in reset!\n"); 174226199Ssklower 174326199Ssklower wakeup((caddr_t)&NpState); 174426199Ssklower 174526199Ssklower while(mp->reqtab->reqcnt) 174626199Ssklower sleep((caddr_t)(&mp->reqtab),PZERO +1); 174726199Ssklower 174826199Ssklower if(NpDebug & DEBMAINT) 174926199Ssklower printf("Reset:awoken by ICP senior!\n"); 175026199Ssklower 175126199Ssklower } 175226199Ssklower 175326199Ssklower /* Abort outstanding requests and wait till they're gone */ 175426199Ssklower 175526199Ssklower NpKill(mp,rp); 175626199Ssklower 175726199Ssklower while(mp->reqtab->reqcnt) { 175826199Ssklower 175926199Ssklower if(NpDebug & DEBMAINT) { 176026199Ssklower printf("Sleeping in NpReset on reqtab!\n"); 176126199Ssklower printf("Reqcnt is %d.\n",mp->reqtab->reqcnt); 176226199Ssklower } 176326199Ssklower 176426199Ssklower sleep((caddr_t)(&mp->reqtab),PZERO +1); 176526199Ssklower 176626199Ssklower } 176726199Ssklower 176826199Ssklower /* Free up I/O Map registers if any allocated */ 176926199Ssklower 177026199Ssklower if(mp->iomapbase) { 177126199Ssklower 177226199Ssklower if(NpDebug & DEBMEM) 177326199Ssklower printf("freeing shared memory map.\n"); 177426199Ssklower 177526199Ssklower ubarelse(mp->devp->ui_ubanum,&mp->iomapbase); 177626199Ssklower mp->iomapbase = 0; 177726199Ssklower } 177826199Ssklower 177926199Ssklower /* Initialize S/W data structures in NP Driver */ 178026199Ssklower 178126199Ssklower NpSWinit(mp->unit); /* Software initialization */ 178226199Ssklower 178326199Ssklower /* Hardware initialization of the board */ 178426199Ssklower 178526199Ssklower error = NpHWinit(mp->unit); /* Hardware initialization */ 178626199Ssklower 178726199Ssklower mp->flags &= ~BRDRESET; /* Initialization complete */ 178826199Ssklower 178926199Ssklower /* Initialize Pseudo-Drivers */ 179026199Ssklower 179126199Ssklower WnInitFlag = 0; /* WN Pseudo-Driver */ 179226199Ssklower IsInitFlag = 0; /* IS Pseudo-Driver */ 179326199Ssklower 179426199Ssklower if (IxReset) 179526199Ssklower (*IxReset)(mp->unit, mp->devp->ui_ubanum, rp); 179626199Ssklower 179726199Ssklower /* Clear Poller's State Flag */ 179826199Ssklower 179926199Ssklower NpState = NPCLEAR; 180026199Ssklower 180126199Ssklower if(NpDebug & DEBENTRY) 180226199Ssklower printf("NpReset...\n"); 180326199Ssklower 180426199Ssklower return(error); 180526199Ssklower } 180626199Ssklower 180726199Ssklower /* 180826199Ssklower * General purpose timeout function which sets the flag passed to it 180926199Ssklower * as argument. 181026199Ssklower */ 181126199Ssklower 181226199Ssklower NpTimer(flagp) 181326199Ssklower int *flagp; 181426199Ssklower { 181526199Ssklower *flagp = NPSET; 181626199Ssklower } 181726199Ssklower 181826199Ssklower NpStats() 181926199Ssklower { 182026199Ssklower if(NpDebug & DEBENTRY) 182126199Ssklower printf("npstats\n"); 182226199Ssklower return(0); 182326199Ssklower } 182426199Ssklower 182526199Ssklower /* 182626199Ssklower * NpCloseConn is called to issue a close connection command to the I-Board. 182726199Ssklower */ 182826199Ssklower 182926199Ssklower NpCloseConn(mp,protocol) 183026199Ssklower struct npmaster *mp; 183126199Ssklower unsign16 protocol; 183226199Ssklower { 183326199Ssklower 183426199Ssklower register struct npreq *rp; 183526199Ssklower register struct CQE *ep; 183626199Ssklower int pri; 183726199Ssklower 183826199Ssklower if(NpDebug & DEBENTRY) 183926199Ssklower printf("NpCloseConn\n"); 184026199Ssklower 184126199Ssklower /* 184226199Ssklower * Don't issue the Close Connection command if the Board 184326199Ssklower * isn't up. 184426199Ssklower */ 184526199Ssklower 184626199Ssklower if(!((mp->shmemp->statblock.sb_dpm) & PROTOMASK(protocol))) { 184726199Ssklower return; 184826199Ssklower } 184926199Ssklower 185026199Ssklower /* Get a Request structure */ 185126199Ssklower 185226199Ssklower while((rp = NpGetReq(mp->reqtab)) == NULL) { 185326199Ssklower mp->reqtab->flags |= WANTREQ; 185426199Ssklower sleep((caddr_t)(mp->reqtab),PZERO -1); 185526199Ssklower } 185626199Ssklower 185726199Ssklower rp->intr = (int (*)())0; /* Do not call interrupt routine */ 185826199Ssklower rp->flags = NPCLEAR; 185926199Ssklower rp->mapbase = 0; /* Clear mapping information */ 186026199Ssklower 186126199Ssklower ep = rp->element; /* Handy pointer */ 186226199Ssklower 186326199Ssklower /* Fill in CQE */ 186426199Ssklower 186526199Ssklower ep->cqe_wind = 0; /* Entire buffer mapped */ 186626199Ssklower ep->cqe_nbuf = 1; /* Must be 1, no buffer chaining */ 186726199Ssklower ep->cqe_char = 0; /* Set to 0 for now */ 186826199Ssklower 186926199Ssklower ep->cqe_func = NPSTOP; /* OS_STP to I-Board */ 187026199Ssklower 187126199Ssklower ep->cqe_prot = protocol; /* Protocol of this connection */ 187226199Ssklower ep->cqe_lenrpb = 0; /* Parameter block length */ 187326199Ssklower 187426199Ssklower ep->cqe_ust0 = ep->cqe_ust1 = NPCLEAR; /* Clear status flags */ 187526199Ssklower 187626199Ssklower ep->cqe_famid = (unsign32)u.u_procp->p_pid; /* Process ID */ 187726199Ssklower 187826199Ssklower NpAddReq(mp->reqtab,rp); /* Queue onto active list */ 187926199Ssklower 188026199Ssklower pri = spl4(); /* Mask our interrupts */ 188126199Ssklower 188226199Ssklower NpAddCQE(ep,&mp->shmemp->devcq,mp); /* Add CQE to device's queue */ 188326199Ssklower 188426199Ssklower /* Wait for command to complete */ 188526199Ssklower 188626199Ssklower while(!(rp->flags & REQDONE)) 188726199Ssklower sleep((caddr_t)rp,PZERO - 1); 188826199Ssklower 188926199Ssklower splx(pri); 189026199Ssklower 189126199Ssklower NpRemReq(rp); /* Remove request from active list */ 189226199Ssklower 189326199Ssklower NpFreeReq(mp->reqtab,rp); /* Deallocate request structure */ 189426199Ssklower 189526199Ssklower if(NpDebug & DEBENTRY) 189626199Ssklower printf("NpCloseConn...\n"); 189726199Ssklower 189826199Ssklower } 189926199Ssklower 190026199Ssklower /* 190126199Ssklower * This function allows the protocol to be changed for a given connection. 190226199Ssklower * It returns 0 for success, error code otherwise. 190326199Ssklower */ 190426199Ssklower 190526199Ssklower NpProtChange(protocol,unit) 190626199Ssklower register unsign16 protocol; 190726199Ssklower register int unit; 190826199Ssklower { 190926199Ssklower 191026199Ssklower register struct npmaster *mp; 191126199Ssklower 191226199Ssklower /* Privileged users only for Maintenance Protocol */ 191326199Ssklower 191426199Ssklower if((protocol == NPMAINT) && (u.u_uid != 0)) 191526199Ssklower return(EPERM); 191626199Ssklower 191726199Ssklower if(NpDebug & DEBMAINT) 191826199Ssklower printf("NpProtChange = %x\n",protocol); 191926199Ssklower 192026199Ssklower if(protocol != NPMAINT) { 192126199Ssklower 192226199Ssklower /* Make sure the I-Board supports the protocol */ 192326199Ssklower 192426199Ssklower mp = &npmasters[unit]; 192526199Ssklower 192626199Ssklower if(!((mp->shmemp->statblock.sb_dpm) & PROTOMASK(protocol))) 192726199Ssklower return(ENXIO); 192826199Ssklower } 192926199Ssklower 193026199Ssklower return(0); 193126199Ssklower } 193226199Ssklower 193326199Ssklower /* 193426199Ssklower * This function allows for the changing of the unit for a given connection. 193526199Ssklower */ 193626199Ssklower 193726199Ssklower struct npmaster * 193826199Ssklower NpBoardChange(protocol,unit) 193926199Ssklower register unsign16 protocol; 194026199Ssklower register int unit; /* Unit number */ 194126199Ssklower { 194226199Ssklower register struct npmaster *mp; 194326199Ssklower 194426199Ssklower 194526199Ssklower if(unit > NNP) 194626199Ssklower return((struct npmaster *)0); 194726199Ssklower 194826199Ssklower if(protocol != NPMAINT) { 194926199Ssklower 195026199Ssklower /* 195126199Ssklower * Loop through the master structures finding a board which 195226199Ssklower * supports the requested protocol. 195326199Ssklower */ 195426199Ssklower 195526199Ssklower for(mp = npmasters; mp ; mp = mp->next) { 195626199Ssklower 195726199Ssklower if(mp->flags & BADBOARD) 195826199Ssklower continue; 195926199Ssklower 196026199Ssklower if(((mp->shmemp->statblock.sb_dpm) & PROTOMASK(protocol))) 196126199Ssklower return(mp); 196226199Ssklower } 196326199Ssklower return((struct npmaster *)0); 196426199Ssklower } 196526199Ssklower return(&npmasters[unit]); 196626199Ssklower } 196726199Ssklower 196826199Ssklower /* 196926199Ssklower * NpMapMem - maps the user's memory updating the fields in the npreq 197026199Ssklower * structure and returning the mapped address in rp->buffaddr. 197126199Ssklower */ 197226199Ssklower NpMapMem(mp,rp,addr,count) 197326199Ssklower register struct npmaster *mp; 197426199Ssklower register struct npreq *rp; 197526199Ssklower caddr_t addr; 197626199Ssklower int count; 197726199Ssklower { 197826199Ssklower 197926199Ssklower if(NpDebug & DEBENTRY) 198026199Ssklower printf("NpMapMem\n"); 198126199Ssklower if(NpDebug & DEBIO) 198226199Ssklower printf("mp %x rp %x addr %x count %x\n",mp,rp,addr,count); 198326199Ssklower 198426199Ssklower rp->virtmem = addr; 198526199Ssklower rp->bytecnt = count; 198626199Ssklower 198726199Ssklower rp->buf.b_un.b_addr = addr; 198826199Ssklower rp->buf.b_flags = B_PHYS | B_BUSY; 198926199Ssklower rp->buf.b_bcount = count; 199026199Ssklower rp->buf.b_proc = rp->procp; 199126199Ssklower 199226199Ssklower rp->procp->p_flag |= SPHYSIO; 199326199Ssklower vslock(addr,count); 199426199Ssklower 199526199Ssklower rp->mapbase = ubasetup(mp->devp->ui_ubanum,&rp->buf,0); 199626199Ssklower 199726199Ssklower rp->bufaddr = (caddr_t)(rp->mapbase & UBADDRMASK); 199826199Ssklower 199926199Ssklower if(NpDebug & DEBENTRY) 200026199Ssklower printf("NpMapMem...\n"); 200126199Ssklower } 200226199Ssklower 200326199Ssklower /* 200426199Ssklower * Unmap the user's memory and free up mapping registers 200526199Ssklower */ 200626199Ssklower 200726199Ssklower NpUnMapMem(mp,rp) 200826199Ssklower struct npmaster *mp; 200926199Ssklower struct npreq *rp; 201026199Ssklower { 201126199Ssklower if(NpDebug & DEBENTRY) 201226199Ssklower printf("NpUnMapMem\n"); 201326199Ssklower 201426199Ssklower ubarelse(mp->devp->ui_ubanum,&rp->mapbase); 201526199Ssklower rp->mapbase = 0; 201626199Ssklower vsunlock(rp->virtmem,rp->bytecnt,B_READ); 201726199Ssklower rp->procp->p_flag &= ~SPHYSIO; 201826199Ssklower 201926199Ssklower if(NpDebug & DEBENTRY) 202026199Ssklower printf("NpUnMapMem...\n"); 202126199Ssklower } 202226199Ssklower 202326199Ssklower npprobe(reg, ui) 202426199Ssklower caddr_t reg; 202526199Ssklower struct uba_device *ui; 202626199Ssklower { 202726199Ssklower register int br,cvec; 202826199Ssklower u_short csraddr; 202926199Ssklower int i; 203026199Ssklower 203126199Ssklower #ifdef lint 203226199Ssklower br = 0; cvec = br; br = cvec; 203326199Ssklower #endif 203426199Ssklower 203526199Ssklower if(NpDebug & DEBINIT) 203626199Ssklower printf("In npprobe, regaddr is %x!\n",reg); 203726199Ssklower 203826199Ssklower cvec = (uba_hd[numuba].uh_lastiv -= 4); 203926199Ssklower 204026199Ssklower #ifdef OLDBSD4_2 204126199Ssklower /* Find unit number from npstd[] by matching the csr address */ 204226199Ssklower 204326199Ssklower csraddr = (u_short)((int)reg & 0x0FFFF); 204426199Ssklower 204526199Ssklower for(i = 0; i < NNP; i++) { 204626199Ssklower 204726199Ssklower if(csraddr == npstd[i]) { 204826199Ssklower npvectors[i] = cvec; 204926199Ssklower break; 205026199Ssklower } 205126199Ssklower } 205226199Ssklower if(i == NNP) 205326199Ssklower printf("Couldn't find device in npstd[]!\n"); 205426199Ssklower #else 205526199Ssklower npvectors[ui->ui_unit] = cvec; 205626199Ssklower #endif 205726199Ssklower br = 0x15; 205826199Ssklower 205926199Ssklower if(NpDebug & DEBINIT) 206026199Ssklower printf("npprobe...\n"); 206126199Ssklower 206226199Ssklower return(sizeof(struct NPREG)); /* CSR Registers */ 206326199Ssklower 206426199Ssklower } 206526199Ssklower 206626199Ssklower npattach(ui) 206726199Ssklower register struct uba_device *ui; 206826199Ssklower { 206926199Ssklower 207026199Ssklower if(NpDebug & DEBINIT) 207126199Ssklower printf("In npattach, ui is %x.\n",ui); 207226199Ssklower 207326199Ssklower npinit(ui->ui_unit); 207426199Ssklower 207526199Ssklower if (IxAttach) 207626199Ssklower (*IxAttach)(ui); 207726199Ssklower 207826199Ssklower if(NpDebug & DEBINIT) 207926199Ssklower printf("npattach...\n"); 208026199Ssklower } 208126199Ssklower 208226199Ssklower #endif 2083