1 /*
2 * Copyright (c) 1982, 1986 Regents of the University of California.
3 * All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 *
7 * @(#)if_en.c 7.7 (Berkeley) 12/16/90
8 */
9
10 #include "en.h"
11 #if NEN > 0
12
13 /*
14 * Xerox prototype (3 Mb) Ethernet interface driver.
15 */
16 #include "../include/pte.h"
17
18 #include "sys/param.h"
19 #include "sys/systm.h"
20 #include "sys/mbuf.h"
21 #include "sys/buf.h"
22 #include "sys/protosw.h"
23 #include "sys/socket.h"
24 #include "sys/vmmac.h"
25 #include "sys/errno.h"
26 #include "sys/ioctl.h"
27
28 #include "net/if.h"
29 #include "net/netisr.h"
30 #include "net/route.h"
31
32 #ifdef INET
33 #include "netinet/in.h"
34 #include "netinet/in_systm.h"
35 #include "netinet/in_var.h"
36 #include "netinet/ip.h"
37 #endif
38
39 #ifdef PUP
40 #include "netpup/pup.h"
41 #include "netpup/ether.h"
42 #endif
43
44 #ifdef NS
45 #include "netns/ns.h"
46 #include "netns/ns_if.h"
47 #endif
48
49 #include "../include/cpu.h"
50 #include "../include/mtpr.h"
51 #include "if_en.h"
52 #include "if_enreg.h"
53 #include "if_uba.h"
54 #include "../uba/ubareg.h"
55 #include "../uba/ubavar.h"
56
57 #define ENMTU (1024+512)
58 #define ENMRU (1024+512+16) /* 16 is enough to receive trailer */
59
60 int enprobe(), enattach(), enrint(), enxint(), encollide();
61 struct uba_device *eninfo[NEN];
62 u_short enstd[] = { 0 };
63 struct uba_driver endriver =
64 { enprobe, 0, enattach, 0, enstd, "en", eninfo };
65 #define ENUNIT(x) minor(x)
66
67 int eninit(),oldenoutput(),enreset(),enioctl(), enstart();
68
69 #ifdef notdef
70 /*
71 * If you need to byte swap IP's in the system, define
72 * this and do a SIOCSIFFLAGS at boot time.
73 */
74 #define ENF_SWABIPS 0x1000
75 #endif
76
77 /*
78 * Ethernet software status per interface.
79 *
80 * Each interface is referenced by a network interface structure,
81 * es_if, which the routing code uses to locate the interface.
82 * This structure contains the output queue for the interface, its address, ...
83 * We also have, for each interface, a UBA interface structure, which
84 * contains information about the UNIBUS resources held by the interface:
85 * map registers, buffered data paths, etc. Information is cached in this
86 * structure for use by the if_uba.c routines in running the interface
87 * efficiently.
88 */
89 struct en_softc {
90 struct ifnet es_if; /* network-visible interface */
91 struct ifuba es_ifuba; /* UNIBUS resources */
92 short es_host; /* hardware host number */
93 short es_delay; /* current output delay */
94 short es_mask; /* mask for current output delay */
95 short es_lastx; /* host last transmitted to */
96 short es_oactive; /* is output active? */
97 short es_olen; /* length of last output */
98 short es_nsactive; /* is interface enabled for ns? */
99 } en_softc[NEN];
100
101 /*
102 * Do output DMA to determine interface presence and
103 * interrupt vector. DMA is too short to disturb other hosts.
104 */
enprobe(reg)105 enprobe(reg)
106 caddr_t reg;
107 {
108 register int br, cvec; /* r11, r10 value-result */
109 register struct endevice *addr = (struct endevice *)reg;
110
111 #ifdef lint
112 br = 0; cvec = br; br = cvec;
113 enrint(0); enxint(0); encollide(0);
114 #endif
115 addr->en_istat = 0;
116 addr->en_owc = -1;
117 addr->en_oba = 0;
118 addr->en_ostat = EN_IEN|EN_GO;
119 DELAY(100000);
120 addr->en_ostat = 0;
121 return (1);
122 }
123
124 /*
125 * Interface exists: make available by filling in network interface
126 * record. System will initialize the interface when it is ready
127 * to accept packets.
128 */
129 enattach(ui)
130 struct uba_device *ui;
131 {
132 register struct en_softc *es = &en_softc[ui->ui_unit];
133
134 es->es_if.if_unit = ui->ui_unit;
135 es->es_if.if_name = "en";
136 es->es_if.if_mtu = ENMTU;
137 es->es_if.if_flags = IFF_BROADCAST;
138 es->es_if.if_init = eninit;
139 es->es_if.if_output = oldenoutput;
140 es->es_if.if_start = enstart;
141 es->es_if.if_ioctl = enioctl;
142 es->es_if.if_reset = enreset;
143 es->es_ifuba.ifu_flags = UBA_NEEDBDP | UBA_NEED16 | UBA_CANTWAIT;
144 #if defined(VAX750)
145 /* don't chew up 750 bdp's */
146 if (cpu == VAX_750 && ui->ui_unit > 0)
147 es->es_ifuba.ifu_flags &= ~UBA_NEEDBDP;
148 #endif
149 if_attach(&es->es_if);
150 }
151
152 /*
153 * Reset of interface after UNIBUS reset.
154 * If interface is on specified uba, reset its state.
155 */
enreset(unit,uban)156 enreset(unit, uban)
157 int unit, uban;
158 {
159 register struct uba_device *ui;
160
161 if (unit >= NEN || (ui = eninfo[unit]) == 0 || ui->ui_alive == 0 ||
162 ui->ui_ubanum != uban)
163 return;
164 printf(" en%d", unit);
165 eninit(unit);
166 }
167
168 /*
169 * Initialization of interface; clear recorded pending
170 * operations, and reinitialize UNIBUS usage.
171 */
eninit(unit)172 eninit(unit)
173 int unit;
174 {
175 register struct en_softc *es = &en_softc[unit];
176 register struct uba_device *ui = eninfo[unit];
177 register struct endevice *addr;
178 int s;
179
180 if (es->es_if.if_addrlist == (struct ifaddr *)0)
181 return;
182 if (if_ubainit(&es->es_ifuba, ui->ui_ubanum,
183 sizeof (struct en_header), (int)btoc(ENMRU)) == 0) {
184 printf("en%d: can't initialize\n", unit);
185 es->es_if.if_flags &= ~IFF_UP;
186 return;
187 }
188 addr = (struct endevice *)ui->ui_addr;
189 addr->en_istat = addr->en_ostat = 0;
190
191 /*
192 * Hang a receive and start any
193 * pending writes by faking a transmit complete.
194 */
195 s = splimp();
196 addr->en_iba = es->es_ifuba.ifu_r.ifrw_info;
197 addr->en_iwc = -(sizeof (struct en_header) + ENMRU) >> 1;
198 addr->en_istat = EN_IEN|EN_GO;
199 es->es_oactive = 1;
200 es->es_if.if_flags |= IFF_RUNNING;
201 enxint(unit);
202 splx(s);
203 }
204
205 int enalldelay = 0;
206 int enlastdel = 50;
207 int enlastmask = (~0) << 5;
208
209 /*
210 * Start or restart output on interface.
211 * If interface is already active, then this is a retransmit
212 * after a collision, and just restuff registers and delay.
213 * If interface is not already active, get another datagram
214 * to send off of the interface queue, and map it to the interface
215 * before starting the output.
216 */
enstart(dev)217 enstart(dev)
218 dev_t dev;
219 {
220 int unit = ENUNIT(dev);
221 struct uba_device *ui = eninfo[unit];
222 register struct en_softc *es = &en_softc[unit];
223 register struct endevice *addr;
224 register struct en_header *en;
225 struct mbuf *m;
226 int dest;
227
228 if (es->es_oactive)
229 goto restart;
230
231 /*
232 * Not already active: dequeue another request
233 * and map it to the UNIBUS. If no more requests,
234 * just return.
235 */
236 IF_DEQUEUE(&es->es_if.if_snd, m);
237 if (m == 0) {
238 es->es_oactive = 0;
239 return;
240 }
241 en = mtod(m, struct en_header *);
242 dest = en->en_dhost;
243 en->en_shost = es->es_host;
244 es->es_olen = if_wubaput(&es->es_ifuba, m);
245 #ifdef ENF_SWABIPS
246 /*
247 * The Xerox interface does word at a time DMA, so
248 * someone must do byte swapping of user data if high
249 * and low ender machines are to communicate. It doesn't
250 * belong here, but certain people depend on it, so...
251 *
252 * Should swab everybody, but this is a kludge anyway.
253 */
254 if (es->es_if.if_flags & ENF_SWABIPS) {
255 en = (struct en_header *)es->es_ifuba.ifu_w.ifrw_addr;
256 if (en->en_type == ENTYPE_IP)
257 enswab((caddr_t)(en + 1), (caddr_t)(en + 1),
258 es->es_olen - sizeof (struct en_header) + 1);
259 }
260 #endif
261
262 /*
263 * Ethernet cannot take back-to-back packets (no
264 * buffering in interface. To help avoid overrunning
265 * receivers, enforce a small delay (about 1ms) in interface:
266 * * between all packets when enalldelay
267 * * whenever last packet was broadcast
268 * * whenever this packet is to same host as last packet
269 */
270 if (enalldelay || es->es_lastx == 0 || es->es_lastx == dest) {
271 es->es_delay = enlastdel;
272 es->es_mask = enlastmask;
273 }
274 es->es_lastx = dest;
275
276 restart:
277 /*
278 * Have request mapped to UNIBUS for transmission.
279 * Purge any stale data from this BDP, and start the otput.
280 */
281 if (es->es_ifuba.ifu_flags & UBA_NEEDBDP)
282 UBAPURGE(es->es_ifuba.ifu_uba, es->es_ifuba.ifu_w.ifrw_bdp);
283 addr = (struct endevice *)ui->ui_addr;
284 addr->en_oba = (int)es->es_ifuba.ifu_w.ifrw_info;
285 addr->en_odelay = es->es_delay;
286 addr->en_owc = -((es->es_olen + 1) >> 1);
287 addr->en_ostat = EN_IEN|EN_GO;
288 es->es_oactive = 1;
289 }
290
291 /*
292 * Ethernet interface transmitter interrupt.
293 * Start another output if more data to send.
294 */
enxint(unit)295 enxint(unit)
296 int unit;
297 {
298 register struct uba_device *ui = eninfo[unit];
299 register struct en_softc *es = &en_softc[unit];
300 register struct endevice *addr = (struct endevice *)ui->ui_addr;
301
302 if (es->es_oactive == 0)
303 return;
304 if (es->es_mask && (addr->en_ostat&EN_OERROR)) {
305 es->es_if.if_oerrors++;
306 endocoll(unit);
307 return;
308 }
309 es->es_if.if_opackets++;
310 es->es_oactive = 0;
311 es->es_delay = 0;
312 es->es_mask = ~0;
313 if (es->es_ifuba.ifu_xtofree) {
314 m_freem(es->es_ifuba.ifu_xtofree);
315 es->es_ifuba.ifu_xtofree = 0;
316 }
317 if (es->es_if.if_snd.ifq_head == 0) {
318 es->es_lastx = 256; /* putatively illegal */
319 return;
320 }
321 enstart(unit);
322 }
323
324 /*
325 * Collision on ethernet interface. Do exponential
326 * backoff, and retransmit. If have backed off all
327 * the way print warning diagnostic, and drop packet.
328 */
encollide(unit)329 encollide(unit)
330 int unit;
331 {
332 struct en_softc *es = &en_softc[unit];
333
334 es->es_if.if_collisions++;
335 if (es->es_oactive == 0)
336 return;
337 endocoll(unit);
338 }
339
endocoll(unit)340 endocoll(unit)
341 int unit;
342 {
343 register struct en_softc *es = &en_softc[unit];
344
345 /*
346 * Es_mask is a 16 bit number with n low zero bits, with
347 * n the number of backoffs. When es_mask is 0 we have
348 * backed off 16 times, and give up.
349 */
350 if (es->es_mask == 0) {
351 printf("en%d: send error\n", unit);
352 enxint(unit);
353 return;
354 }
355 /*
356 * Another backoff. Restart with delay based on n low bits
357 * of the interval timer.
358 */
359 es->es_mask <<= 1;
360 es->es_delay = mfpr(ICR) &~ es->es_mask;
361 enstart(unit);
362 }
363
364 #ifdef notdef
365 struct sockproto enproto = { AF_ETHERLINK };
366 struct sockaddr_en endst = { sizeof(endst), AF_ETHERLINK };
367 struct sockaddr_en ensrc = { sizeof(ensrc), AF_ETHERLINK };
368 #endif
369 /*
370 * Ethernet interface receiver interrupt.
371 * If input error just drop packet.
372 * Otherwise purge input buffered data path and examine
373 * packet to determine type. If can't determine length
374 * from type, then have to drop packet. Othewise decapsulate
375 * packet based on type and pass to type specific higher-level
376 * input routine.
377 */
enrint(unit)378 enrint(unit)
379 int unit;
380 {
381 register struct en_softc *es = &en_softc[unit];
382 struct endevice *addr = (struct endevice *)eninfo[unit]->ui_addr;
383 register struct en_header *en;
384 struct mbuf *m;
385 int len; short resid;
386 register struct ifqueue *inq;
387 int off, s;
388
389 es->es_if.if_ipackets++;
390
391 /*
392 * Purge BDP; drop if input error indicated.
393 */
394 if (es->es_ifuba.ifu_flags & UBA_NEEDBDP)
395 UBAPURGE(es->es_ifuba.ifu_uba, es->es_ifuba.ifu_r.ifrw_bdp);
396 if (addr->en_istat&EN_IERROR) {
397 es->es_if.if_ierrors++;
398 goto setup;
399 }
400
401 /*
402 * Calculate input data length.
403 * Get pointer to ethernet header (in input buffer).
404 * Deal with trailer protocol: if type is PUP trailer
405 * get true type from first 16-bit word past data.
406 * Remember that type was trailer by setting off.
407 */
408 resid = addr->en_iwc;
409 if (resid)
410 resid |= 0176000;
411 len = (((sizeof (struct en_header) + ENMRU) >> 1) + resid) << 1;
412 len -= sizeof (struct en_header);
413 if (len > ENMRU)
414 goto setup; /* sanity */
415 en = (struct en_header *)(es->es_ifuba.ifu_r.ifrw_addr);
416 en->en_type = ntohs(en->en_type);
417 #define endataaddr(en, off, type) ((type)(((caddr_t)((en)+1)+(off))))
418 if (en->en_type >= ENTYPE_TRAIL &&
419 en->en_type < ENTYPE_TRAIL+ENTYPE_NTRAILER) {
420 off = (en->en_type - ENTYPE_TRAIL) * 512;
421 if (off > ENMTU)
422 goto setup; /* sanity */
423 en->en_type = ntohs(*endataaddr(en, off, u_short *));
424 resid = ntohs(*(endataaddr(en, off+2, u_short *)));
425 if (off + resid > len)
426 goto setup; /* sanity */
427 len = off + resid;
428 } else
429 off = 0;
430 if (len == 0)
431 goto setup;
432 #ifdef ENF_SWABIPS
433 if (es->es_if.if_flags & ENF_SWABIPS && en->en_type == ENTYPE_IP)
434 enswab((caddr_t)(en + 1), (caddr_t)(en + 1), len);
435 #endif
436 /*
437 * Pull packet off interface. Off is nonzero if packet
438 * has trailing header; if_rubaget will then force this header
439 * information to be at the front, but we still have to drop
440 * the type and length which are at the front of any trailer data.
441 */
442 m = if_rubaget(&es->es_ifuba, len, off, &es->es_if);
443 if (m == 0)
444 goto setup;
445 switch (en->en_type) {
446
447 #ifdef INET
448 case ENTYPE_IP:
449 schednetisr(NETISR_IP);
450 inq = &ipintrq;
451 break;
452 #endif
453 #ifdef PUP
454 case ENTYPE_PUP:
455 rpup_input(m);
456 goto setup;
457 #endif
458 #ifdef NS
459 case ETHERTYPE_NS:
460 if (es->es_nsactive) {
461 schednetisr(NETISR_NS);
462 inq = &nsintrq;
463 } else {
464 m_freem(m);
465 goto setup;
466 }
467 break;
468 #endif
469
470 default:
471 #ifdef notdef
472 enproto.sp_protocol = en->en_type;
473 endst.sen_host = en->en_dhost;
474 endst.sen_net = ensrc.sen_net = es->es_if.if_net;
475 ensrc.sen_host = en->en_shost;
476 raw_input(m, &enproto,
477 (struct sockaddr *)&ensrc, (struct sockaddr *)&endst);
478 #else
479 m_freem(m);
480 #endif
481 goto setup;
482 }
483
484 s = splimp();
485 if (IF_QFULL(inq)) {
486 IF_DROP(inq);
487 m_freem(m);
488 } else
489 IF_ENQUEUE(inq, m);
490 splx(s);
491
492 setup:
493 /*
494 * Reset for next packet.
495 */
496 addr->en_iba = es->es_ifuba.ifu_r.ifrw_info;
497 addr->en_iwc = -(sizeof (struct en_header) + ENMRU) >> 1;
498 addr->en_istat = EN_IEN|EN_GO;
499 }
500
501 /*
502 * Ethernet output routine.
503 * Encapsulate a packet of type family for the local net.
504 * Use trailer local net encapsulation if enough data in first
505 * packet leaves a multiple of 512 bytes of data in remainder.
506 */
507 oldenoutput(ifp, m0, dst)
508 struct ifnet *ifp;
509 struct mbuf *m0;
510 struct sockaddr *dst;
511 {
512 int type, dest, s, error;
513 register struct mbuf *m = m0;
514 register struct en_header *en;
515 register int off;
516
517 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
518 error = ENETDOWN;
519 goto bad;
520 }
521 switch (dst->sa_family) {
522
523 #ifdef INET
524 case AF_INET:
525 {
526 struct in_addr in;
527
528 in = ((struct sockaddr_in *)dst)->sin_addr;
529 if (in_broadcast(in))
530 dest = EN_BROADCAST;
531 else
532 dest = in_lnaof(in);
533 }
534 if (dest >= 0x100) {
535 error = EPERM; /* ??? */
536 goto bad;
537 }
538 off = m->m_pkthdr.len - m->m_len;
539 /* need per host negotiation */
540 if ((ifp->if_flags & IFF_NOTRAILERS) == 0)
541 if (off > 0 && (off & 0x1ff) == 0 &&
542 (m->m_flags & M_EXT) == 0 &&
543 m->m_data >= m->m_pktdat + 2 * sizeof (u_short)) {
544 type = ENTYPE_TRAIL + (off>>9);
545 m->m_data -= 2 * sizeof (u_short);
546 m->m_len += 2 * sizeof (u_short);
547 *mtod(m, u_short *) = htons((u_short)ENTYPE_IP);
548 *(mtod(m, u_short *) + 1) = ntohs((u_short)m->m_len);
549 goto gottrailertype;
550 }
551 type = ENTYPE_IP;
552 off = 0;
553 goto gottype;
554 #endif
555 #ifdef NS
556 case AF_NS:
557 {
558 u_char *up;
559
560 type = ETHERTYPE_NS;
561 up = ((struct sockaddr_ns *)dst)->sns_addr.x_host.c_host;
562 if (*up & 1)
563 dest = EN_BROADCAST;
564 else
565 dest = up[5];
566
567 off = 0;
568 goto gottype;
569 }
570 #endif
571 #ifdef PUP
572 case AF_PUP:
573 dest = ((struct sockaddr_pup *)dst)->spup_host;
574 type = ENTYPE_PUP;
575 off = 0;
576 goto gottype;
577 #endif
578
579 #ifdef notdef
580 case AF_ETHERLINK:
581 goto gotheader;
582 #endif
583
584 default:
585 printf("en%d: can't handle af%d\n", ifp->if_unit,
586 dst->sa_family);
587 error = EAFNOSUPPORT;
588 goto bad;
589 }
590
591 gottrailertype:
592 /*
593 * Packet to be sent as trailer: move first packet
594 * (control information) to end of chain.
595 */
596 while (m->m_next)
597 m = m->m_next;
598 m->m_next = m0;
599 m = m0->m_next;
600 m0->m_next = 0;
601 m0 = m;
602
603 gottype:
604 /*
605 * Add local net header. If no space in first mbuf,
606 * allocate another.
607 */
608 M_PREPEND(m, sizeof (struct en_header), M_DONTWAIT);
609 if (m == NULL)
610 return (ENOBUFS);
611 en = mtod(m, struct en_header *);
612 /* add en_shost later */
613 en->en_dhost = dest;
614 en->en_type = htons((u_short)type);
615
616 #ifdef notdef
617 gotheader:
618 #endif
619 /*
620 * Queue message on interface, and start output if interface
621 * not yet active.
622 */
623 s = splimp();
624 if (IF_QFULL(&ifp->if_snd)) {
625 IF_DROP(&ifp->if_snd);
626 error = ENOBUFS;
627 goto qfull;
628 }
629 IF_ENQUEUE(&ifp->if_snd, m);
630 if (en_softc[ifp->if_unit].es_oactive == 0)
631 enstart(ifp->if_unit);
632 splx(s);
633 return (0);
634 qfull:
635 m0 = m;
636 splx(s);
637 bad:
638 m_freem(m0);
639 return (error);
640 }
641
642 /*
643 * Process an ioctl request.
644 */
enioctl(ifp,cmd,data)645 enioctl(ifp, cmd, data)
646 register struct ifnet *ifp;
647 int cmd;
648 caddr_t data;
649 {
650 register struct en_softc *es = ((struct en_softc *)ifp);
651 struct ifaddr *ifa = (struct ifaddr *) data;
652 int s = splimp(), error = 0;
653 struct endevice *enaddr;
654
655 switch (cmd) {
656
657 case SIOCSIFADDR:
658 enaddr = (struct endevice *)eninfo[ifp->if_unit]->ui_addr;
659 es->es_host = (~enaddr->en_addr) & 0xff;
660 /*
661 * Attempt to check agreement of protocol address
662 * and board address.
663 */
664 switch (ifa->ifa_addr->sa_family) {
665 case AF_INET:
666 if (in_lnaof(IA_SIN(ifa)->sin_addr) != es->es_host)
667 return (EADDRNOTAVAIL);
668 break;
669 #ifdef NS
670 case AF_NS:
671 if (IA_SNS(ifa)->sns_addr.x_host.c_host[5]
672 != es->es_host)
673 return (EADDRNOTAVAIL);
674 es->es_nsactive = 1;
675 break;
676 #endif
677 }
678 ifp->if_flags |= IFF_UP;
679 if ((ifp->if_flags & IFF_RUNNING) == 0)
680 eninit(ifp->if_unit);
681 break;
682
683 default:
684 error = EINVAL;
685 break;
686 }
687 splx(s);
688 return (error);
689 }
690
691 #ifdef ENF_SWABIPS
692 /*
693 * Swab bytes
694 * Jeffrey Mogul, Stanford
695 */
enswab(from,to,n)696 enswab(from, to, n)
697 register unsigned char *from, *to;
698 register int n;
699 {
700 register unsigned long temp;
701
702 if ((n <= 0) || (n > 0xFFFF)) {
703 printf("enswab: bad len %d\n", n);
704 return;
705 }
706
707 n >>= 1; n++;
708 #define STEP {temp = *from++;*to++ = *from++;*to++ = temp;}
709 /* round to multiple of 8 */
710 while ((--n) & 07)
711 STEP;
712 n >>= 3;
713 while (--n >= 0) {
714 STEP; STEP; STEP; STEP;
715 STEP; STEP; STEP; STEP;
716 }
717 }
718 #endif
719 #endif
720