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