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