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