|
|
1.1 root 1: #include "il.h"
2:
3: #if NIL > 0
4:
5: #include "../h/param.h"
6: #include "../h/systm.h"
7: #include "../h/dir.h"
8: #include "../h/user.h"
9: #include "../h/map.h"
10: #include "../h/pte.h"
11: #include "../h/buf.h"
12: #include "../h/ubareg.h"
13: #include "../h/ubavar.h"
14: #include "../h/proc.h"
15: #include "../h/tty.h"
16: /*#include "../h/queue.h"*/
17: #include "../h/ilreg.h"
18: #include "../h/conf.h"
19:
20: #define PRINET 26 /* sleep priority: interruptible */
21:
22: struct ilcb ilcb[NIL];
23: extern int ilprobe(), ilattach(), ilrint(), ilcint();
24: struct uba_device *ildinfo[NIL];
25: u_short ilstd[] = {0164040};
26: struct uba_driver ildriver =
27: { ilprobe, 0, ilattach, 0, ilstd, "il", ildinfo };
28:
29:
30: /*++*
31: * Macro: NM10command
32: * Abstract: pass the NM10 board an inline command
33: * Parameters:
34: * command: command to process
35: * size: size of data buffer
36: * buf: data buffer
37: * addr: NM10 device addr
38: * Returns: nothing
39: * Affects: nothing
40: * Errors: none
41: * Design: trivial
42: *
43: *--*/
44: #define NM10command(command, size, buf) \
45: { \
46: register unsigned int map = ((unsigned int) buf); \
47: reg->bcr = size; \
48: reg->bar = map & 0xffff; \
49: reg->csr = ((map & 0x30000) >> 2) | command; \
50: while ((reg->csr & IL_CMD_DONE) == 0); \
51: }
52:
53:
54: /*++*
55: * Routine: ilinit
56: * Abstract: Initialize the Interlan ethernet driver.
57: * Parameters:
58: * dev: number device to initialize;
59: * Returns: nothing
60: * Affects: nothing
61: * Errors:
62: * Design: trivial
63: *
64: *--*/
65: ilinit (dev)
66: {
67: register struct ilcb *ib = &ilcb[dev];
68: register struct uba_device *ui = ildinfo[dev];
69: register struct ilreg *reg = (struct ilreg *)ui->ui_addr;
70:
71: if (ib->avail)
72: {
73: u.u_error = EBUSY;
74: return;
75: }
76:
77: ib->in_map = uballoc(ui->ui_ubanum, (caddr_t) 0x80000000,
78: ILUBASIZE, UBA_NEEDBDP|UBA_CANTWAIT);
79: ib->cmd_map = uballoc(ui->ui_ubanum, (caddr_t) 0x80000000,
80: ILUBASIZE, UBA_NEEDBDP|UBA_CANTWAIT);
81:
82: if ((ib->in_map == 0) || (ib->cmd_map == 0))
83: {
84: if (ib->in_map)
85: ubarelse (ui->ui_ubanum, &ib->in_map);
86: if (ib->cmd_map)
87: ubarelse (ui->ui_ubanum, &ib->cmd_map);
88: u.u_error = ENOMEM;
89: return;
90: }
91:
92: /*++*
93: * initialize cummulative statistics
94: *
95: *--*/
96: {
97: struct ilstats stats;
98: register unsigned short *st = (unsigned short *) &stats.rframes;
99: register unsigned int *in = (unsigned int *) &ib->info.rframes;
100:
101: NM10command (IL_RPT_STATS, 66,
102: ubaremap(ui->ui_ubanum, ib->in_map, stats));
103:
104: /* we do this remap to cause a ubapurge */
105: ubaremap(ui->ui_ubanum, ib->in_map, stats);
106:
107: while (st > (unsigned short *) &stats.modid)
108: *in++ = *st++;
109:
110: ib->info.iladdr = stats.iladdr;
111: ib->info.modid = stats.modid;
112: ib->info.firmid = stats.firmid;
113: }
114:
115: ib->in_ptr = 0;
116: ib->in_packet = NULL;
117: ib->cmd_packet = NULL;
118: ib->in_next = NULL;
119:
120: initqueue((struct Queue *)&ib->cmd_q);
121:
122: ilrstart (ui);
123: NM10command (IL_ON_LINE, 0, 0);
124: }
125:
126: ilopen (dev, flag)
127: {
128: register struct ilcb *ib = &ilcb[dev];
129:
130: if (ib > &ilcb[NIL] || !ib->attached)
131: {
132: u.u_error = ENXIO;
133: return;
134: }
135:
136: }
137:
138: ilclose (dev)
139: {
140: return;
141: }
142:
143:
144: /*++*
145: * Procedure: ilcommand
146: * Abstract:
147: * send command to net.
148: * Parameters:
149: * dev = device number
150: * p = pointer to packet that is to be given to Interland device.
151: * Design:
152: *
153: *--*/
154: ilcommand(dev, p)
155: register struct ilpacket *p;
156: {
157: register struct uba_device *ui = ildinfo [dev];
158: register struct ilcb *ib = &ilcb [dev];
159: int ipl;
160: extern ilcmdstart();
161:
162: ipl = spl6();
163:
164: if (ib->cmd_packet == NULL)
165: {
166: ib->cmd_packet = p;
167: ilcmdstart (ui);
168: }
169: else enqueue (&ib->cmd_q, p);
170:
171: splx(ipl);
172: }
173:
174:
175:
176: ilioctl (dev, cmd, arg) int *arg;
177: {
178: switch (cmd)
179: {
180: case IL_INIT:
181: {
182: if (suser())
183: ilinit (dev);
184: else
185: {
186: u.u_error = EPERM;
187: return;
188: }
189: }
190: break;
191:
192: case IL_DISABLE:
193: {
194: /* ildisable (dev); */
195: }
196: break;
197:
198: case IL_STATS:
199: {
200: register struct ilcb *ib = &ilcb[dev];
201: unsigned short buf[ILPHEAD + 66];
202: register struct ilpacket *p = (struct ilpacket *)buf;
203: extern ilstats ();
204:
205: p->command = IL_RPT_STATS;
206: p->function = ilstats;
207: p->count = 66;
208: ilcommand (dev, p);
209:
210: while (p->command == IL_RPT_STATS)
211: sleep((caddr_t) p, PRINET);
212: copyout(&ib->info, arg, sizeof ib->info);
213: }
214: break;
215:
216: default:
217: {
218: u.u_error = EINVAL;
219: }
220: break;
221: }
222: }
223:
224:
225: /*++*
226: * Routine: ilfind
227: * Abstract: find a type filter that matched a specified type.
228: * Parameters:
229: * ib = pointer to the ethernet device ilcb.
230: * type = type that filter will match.
231: * Returns:
232: * SUCCESS: a descriptor with the matched type.
233: * FAILURE: NULL
234: * Affects: nothing
235: * Errors: none
236: * Design: trivial
237: *
238: *--*/
239: struct iltype *ilfind(ib, type) register unsigned short type;
240: register struct ilcb *ib;
241: {
242: register struct iltype *d;
243: for ( d = (struct iltype *)ib->type_q.F;
244: d != (struct iltype *)&ib->type_q;
245: d = (struct iltype *) d->head.F )
246: if (d->type == type)
247: return (d);
248: return (NULL);
249: }
250:
251:
252: /*++*
253: * Routine: ilconnect
254: * Abstract: create and ethernet type filter entry
255: * Parameters:
256: * unit = ethernet device unit number.
257: * type = ethernet type
258: * funct = function to call if we find a match
259: * Returns:
260: * SUCCESS: 1
261: * FAILURE: 0
262: * Affects:
263: * ilcb[unit].type_q: entry placed in queue
264: * ilcb[unit].free_q: entry removed from queue
265: * Errors: none
266: * Design: ...
267: *
268: *--*/
269: ilconnect (unit, type, function) register funct *function;
270: {
271: register struct iltype *d;
272: register struct ilcb *ib = &ilcb[unit];
273: register int ipl;
274:
275: ipl = spl6();
276: if (ilfind (ib, type) == NULL)
277: if (d = (struct iltype *) dequeue (&ib->free_q))
278: {
279: ib->num_free--;
280: d->type = type;
281: d->funct = function;
282: enqueue (&ib->type_q, d);
283: ib->num_types++;
284: splx (ipl);
285: return (1);
286: }
287: splx (ipl);
288: return (0);
289: }
290:
291:
292:
293: /*++*
294: * Routine: ildisconnect
295: * Abstract: remove an ethernet type filter match entry
296: * Parameters:
297: * unit = ethernet device unit number
298: * type = ethernet type
299: * Returns:
300: * SUCCESS: 1
301: * FAILURE: 0
302: * Affects:
303: * ilcb[unit].type_q: entry removed
304: * ilcb[unit].free_q: entry entered
305: * Errors: none
306: * Design: ...
307: *
308: *--*/
309: ildisconnect (unit, type) register int type;
310: {
311: struct iltype *d;
312: register struct ilcb *ib = &ilcb[unit];
313: register int ipl;
314:
315: if (d = ilfind (ib, type))
316: {
317: ipl = spl6 ();
318: enqueue (&ib->free_q, dequeue (&d));
319: ib->num_types--;
320: ib->num_free++;
321: splx(ipl);
322: }
323: }
324:
325:
326:
327: /*++*
328: * Routine: iladdress
329: * Abstract: return (by reference) the device net address
330: * Parameters:
331: * addr = the network address.
332: * Returns: nothing
333: * Affects: nothing
334: * Errors: none
335: * Design: trivial
336: *
337: *--*/
338: iladdress (dev, addr) register struct iladdr *addr;
339: {
340: register struct ilcb *ib = &ilcb[dev];
341: *addr = ib->info.iladdr;
342: }
343:
344:
345: /*++*
346: * Procedure: ilrstart
347: * Abstract: Start read operation on net.
348: * Parameters:
349: * 'ui' type "uba_device *": pointer to ethernet device to be started.
350: *
351: *--*/
352:
353: ilrstart(ui)
354: register struct uba_device *ui;
355: {
356: register struct ilreg *reg = (struct ilreg *)ui->ui_addr;
357: register struct ilcb *ib = &ilcb[ui->ui_unit];
358: register struct ilpacket *p;
359: int ipl;
360:
361: if (ib->in_packet == NULL)
362: {
363: ipl = spl6();
364: ib->in_packet = &ib->in_pool[ib->in_ptr];
365: ib->in_ptr ^= 1;
366: ib->in_next = ubaremap (ui->ui_ubanum, ib->in_map,
367: ib->in_packet->data);
368: if (ib->cmd_packet == NULL)
369: {
370: NM10command (IL_RCVR_BUFFER | IL_RCV_INTR,
371: ILPACKETSIZE,
372: ib->in_next);
373: ib->in_next = NULL;
374: }
375: splx (ipl);
376: }
377: }
378:
379:
380:
381: /*++*
382: * Procedure: ilcmdstart
383: * Abstract: Start packet transmission on net.
384: * Parameters:
385: * ui pointer to ethernet device structure.
386: * Design:
387: * We give the Interland device the correct command
388: *
389: * The UNIBUS address is derived by calculating the offset of the
390: * packet from the packet pool buffer base address and adding it to the
391: * allocated unibus buffer base address.
392: *
393: * We must do a purge to make sure the uba device has no data words
394: * lying around that might get sent on the next DMA.
395: *
396: *--*/
397: ilcmdstart(ui)
398: register struct uba_device *ui;
399: {
400:
401: register struct ilcb *ib = &ilcb[ui->ui_unit];
402: register struct ilreg *ilreg = (struct ilreg *)ui->ui_addr;
403: register struct ilpacket *p;
404: register unsigned int buffer;
405:
406: if (ib->cmd_packet == NULL)
407: if ((ib->cmd_packet = (struct ilpacket *)dequeue(&ib->cmd_q)) == NULL)
408: return;
409:
410: /* we dont use NM10command here since we are not interested
411: in waiting for the command to complete synchronously */
412:
413: p = ib->cmd_packet;
414: buffer = (unsigned int) ubaremap (ui->ui_ubanum, ib->cmd_map,
415: p->data);
416: ilreg->bcr = p->count;
417: ilreg->bar = buffer & 0xffff;
418: ilreg->csr = ((buffer & 0x30000) >> 2)
419: | p->command | IL_CMD_INTR | IL_RCV_INTR;
420:
421: }
422:
423:
424: /*++*
425: * Procedure: ilrint
426: * Abstract: Net read interrupt handler.
427: * Parameters:
428: * dev = number of ethernet device.
429: *
430: *--*/
431: ilrint(dev)
432: {
433:
434: register struct ilcb *ib = &ilcb[dev];
435: register struct uba_device *ui = ildinfo[dev];
436: register struct il_rheader *l;
437: register struct iltype *d;
438:
439: l = (struct il_rheader *)ib->in_packet;
440: ilrstart(ui);
441: if (l->status & IL_RCV_STATUS)
442: printf ("il%d: received bad packet; status %x\n", dev, l);
443: else if (d = ilfind(ib, l->type))
444: (*d->funct)(dev, l);
445: }
446:
447:
448: /*++*
449: * Procedure: ilcint
450: * Abstract: Net transmit interrupt handler.
451: * Parameters:
452: * 'en' number of device we interrupted on.
453: *
454: *--*/
455:
456: ilcint(dev)
457: {
458: register struct ilcb *ib = &ilcb[dev];
459: register struct uba_device *ui = ildinfo[dev];
460: register unsigned short status;
461: register struct ilpacket *p = ib->cmd_packet;
462: register struct ilreg *reg = (struct ilreg *) ui->ui_addr;
463:
464: if (p == NULL)
465: {
466: printf ("il%d: spurious transmit interrupt\n", dev);
467: return;
468: }
469:
470: status = reg->csr & IL_CMD_STATUS;
471: if (p->command == IL_XMIT_SEND)
472: {
473: if ((status) > 1)
474: printf ("il%d: dropped xmit packet\n", dev);
475: }
476: else if (status)
477: printf ("il%d: command %x bad status packet: %x\n",
478: dev, p->command, p);
479:
480: if (p->function != NULL)
481: (*(p->function)) (p, dev);
482:
483: if (ib->in_next)
484: {
485: NM10command (IL_RCVR_BUFFER | IL_RCV_INTR,
486: ILPACKETSIZE,
487: ib->in_next);
488: }
489:
490: ib->in_next = NULL;
491: ib->cmd_packet = NULL;
492: ilcmdstart (ui);
493: }
494:
495:
496: /*++*
497: * Procedure: ilstats
498: * Abstract:
499: * Merge currently collected data into the device statistics
500: * table. This routine assumes HIGH PRIORITY.
501: *
502: *--*/
503: ilstats (p, dev) struct ilpacket *p;
504: {
505: register struct ilcb *ib = &ilcb[dev];
506: register struct ilstats *stats = (struct ilstats *)p->data;
507: register unsigned int *in = (unsigned int *) &ib->info.rframes;
508: register unsigned short *st = (unsigned short *) &stats->rframes;
509:
510: while (st < (unsigned short *) stats)
511: *in++ += *st++;
512: ib->info.rfifo = stats->rfifo;
513: p->command = IL_NULL_CMD;
514: wakeup((caddr_t) p);
515: }
516:
517:
518:
519: /*++*
520: * Procedure: ilattach
521: * Abstract:
522: * This routine is called at system startup and initializes
523: * the device information structures.
524: * Parameters:
525: * 'ui' type "uba_device *": pointer to the device information
526: * structure.
527: *--*/
528: ilattach(ui)
529: register struct uba_device *ui;
530: {
531: register struct ilreg *reg = (struct ilreg *) ui->ui_addr;
532: register struct ilcb *ib = &ilcb[ui->ui_unit];
533: register unsigned short status;
534: register int i;
535:
536: if (&ilcb[ui->ui_unit] > &ilcb[NIL])
537: {
538: printf ("il%d: unit number to large. Max = %d\n",
539: ui->ui_unit, NIL);
540: return;
541: }
542:
543: if (status = (reg->csr & IL_CMD_STATUS))
544: {
545: printf ("il%d: bad reset status %x\n");
546: return;
547: }
548:
549: ib->attached = 1;
550:
551: initqueue((struct Queue *)&ib->type_q);
552: initqueue((struct Queue *)&ib->free_q);
553: ib->num_types = 0;
554: ib->num_free = ILMAXTYPES;
555:
556: for (i = 0; i < ILMAXTYPES; i++)
557: enqueue (&ib->free_q, ib->type[i]);
558:
559: #ifdef TCP_IP
560: #if NBBNNET > 0
561: il_attach();
562: #endif NBBNNET
563: #endif TCP_IP
564: }
565:
566:
567:
568: /*++*
569: * Procedure: ilprobe
570: * Abstract:
571: * This routine is called by the system auto configurer
572: * at boot time. It locates the interrupt vectors of the device
573: * by doing FM (f___ing Magic). Cvec is used as a global register
574: * in which the interrupt routine places the interrupt vector
575: * that it found when the device interrupted.
576: * We can use this routine to do some boot time testing if
577: * we want.
578: * Parameters:
579: * 'reg' the base address of the ethernet device.
580: *
581: *--*/
582: ilprobe(reg)
583: struct ilreg *reg;
584: {
585: register int br,cvec;
586:
587: #ifdef lint
588: br = 0; cvec = br; br = cvec;
589: #endif
590:
591: reg->bcr = 0;
592: reg->bar = 0;
593: reg->csr = IL_OFF_LINE | IL_CMD_INTR;
594: DELAY(10000);
595:
596: br = reg->csr; /* clear off status from il board */
597: cvec &= ~0xf; /* make sure we have the first intr vector */
598: return(1);
599: }
600:
601:
602:
603:
604: /*++*
605: * Procedure: ilreset
606: * Abstract:
607: * reset the interlan ethernet device
608: * Called on UBA reset to restart pending I/O.
609: * Just prints the device name and restarts the receiver and
610: * transmitter. No other state that we care about is lost by
611: * the reset.
612: * Parameters:
613: * 'uban' number of the uba that was reset.
614: *
615: *--*/
616: ilreset(uban)
617: {
618:
619: register int dev;
620: register struct uba_device *ui;
621: register struct ilreg *reg = (struct ilreg *) ui->ui_addr;
622: register struct ilcb *ib;
623:
624: for (dev = 0; dev < NIL; dev++)
625: {
626: if ((ui = ildinfo[dev]) ||
627: ui->ui_alive == 0 ||
628: ui->ui_ubanum != uban)
629: continue;
630:
631:
632: ib = &ilcb[dev];
633: /*++*
634: * do a reset command so we are sure of the state
635: *
636: *--*/
637: NM10command (IL_RESET, 0, 0);
638: printf("[reset] ");
639:
640: /*++*
641: * put us back on line if we are active
642: * and start the command and receive processes.
643: *
644: *--*/
645: if (ib->avail)
646: {
647: NM10command (IL_ON_LINE, 0, 0);
648: printf ("[on line]");
649: }
650: else printf ("[off line]");
651: }
652:
653: if (ib->cmd_packet)
654: (*ib->cmd_packet->function) (ib->cmd_packet, dev);
655:
656: ib->in_ptr = 0;
657: ib->in_packet = NULL;
658: ib->in_next = NULL;
659: ib->cmd_packet = NULL;
660: ilcmdstart(ui);
661: ilrstart (ui);
662: }
663:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.