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