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