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