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