|
|
1.1 root 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) 4/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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.