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