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