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