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