|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: *
6: * @(#)if_de.c 7.4 (Berkeley) 5/26/88
7: */
8: #include "de.h"
9: #if NDE > 0
10:
11: /*
12: * DEC DEUNA interface
13: *
14: * Lou Salkind
15: * New York University
16: *
17: * TODO:
18: * timeout routine (get statistics)
19: */
20: #include "../machine/pte.h"
21:
22: #include "param.h"
23: #include "systm.h"
24: #include "mbuf.h"
25: #include "buf.h"
26: #include "protosw.h"
27: #include "socket.h"
28: #include "vmmac.h"
29: #include "ioctl.h"
30: #include "errno.h"
31: #include "syslog.h"
32:
33: #include "../net/if.h"
34: #include "../net/netisr.h"
35: #include "../net/route.h"
36:
37: #ifdef INET
38: #include "../netinet/in.h"
39: #include "../netinet/in_systm.h"
40: #include "../netinet/in_var.h"
41: #include "../netinet/ip.h"
42: #include "../netinet/if_ether.h"
43: #endif
44:
45: #ifdef NS
46: #include "../netns/ns.h"
47: #include "../netns/ns_if.h"
48: #endif
49:
50: #include "../vax/cpu.h"
51: #include "../vax/mtpr.h"
52: #include "if_dereg.h"
53: #include "if_uba.h"
54: #include "../vaxuba/ubareg.h"
55: #include "../vaxuba/ubavar.h"
56:
57: #define NXMT 3 /* number of transmit buffers */
58: #define NRCV 7 /* number of receive buffers (must be > 1) */
59:
60: int dedebug = 0;
61:
62: int deprobe(), deattach(), deintr();
63: struct uba_device *deinfo[NDE];
64: u_short destd[] = { 0 };
65: struct uba_driver dedriver =
66: { deprobe, 0, deattach, 0, destd, "de", deinfo };
67: int deinit(),deoutput(),deioctl(),dereset();
68:
69:
70: /*
71: * Ethernet software status per interface.
72: *
73: * Each interface is referenced by a network interface structure,
74: * ds_if, which the routing code uses to locate the interface.
75: * This structure contains the output queue for the interface, its address, ...
76: * We also have, for each interface, a UBA interface structure, which
77: * contains information about the UNIBUS resources held by the interface:
78: * map registers, buffered data paths, etc. Information is cached in this
79: * structure for use by the if_uba.c routines in running the interface
80: * efficiently.
81: */
82: struct de_softc {
83: struct arpcom ds_ac; /* Ethernet common part */
84: #define ds_if ds_ac.ac_if /* network-visible interface */
85: #define ds_addr ds_ac.ac_enaddr /* hardware Ethernet address */
86: int ds_flags;
87: #define DSF_LOCK 1 /* lock out destart */
88: #define DSF_RUNNING 2 /* board is enabled */
89: #define DSF_SETADDR 4 /* physical address is changed */
90: int ds_ubaddr; /* map info for incore structs */
91: struct ifubinfo ds_deuba; /* unibus resource structure */
92: struct ifrw ds_ifr[NRCV]; /* unibus receive maps */
93: struct ifxmt ds_ifw[NXMT]; /* unibus xmt maps */
94: /* the following structures are always mapped in */
95: struct de_pcbb ds_pcbb; /* port control block */
96: struct de_ring ds_xrent[NXMT]; /* transmit ring entrys */
97: struct de_ring ds_rrent[NRCV]; /* receive ring entrys */
98: struct de_udbbuf ds_udbbuf; /* UNIBUS data buffer */
99: /* end mapped area */
100: #define INCORE_BASE(p) ((char *)&(p)->ds_pcbb)
101: #define RVAL_OFF(n) ((char *)&de_softc[0].n - INCORE_BASE(&de_softc[0]))
102: #define LVAL_OFF(n) ((char *)de_softc[0].n - INCORE_BASE(&de_softc[0]))
103: #define PCBB_OFFSET RVAL_OFF(ds_pcbb)
104: #define XRENT_OFFSET LVAL_OFF(ds_xrent)
105: #define RRENT_OFFSET LVAL_OFF(ds_rrent)
106: #define UDBBUF_OFFSET RVAL_OFF(ds_udbbuf)
107: #define INCORE_SIZE RVAL_OFF(ds_xindex)
108: int ds_xindex; /* UNA index into transmit chain */
109: int ds_rindex; /* UNA index into receive chain */
110: int ds_xfree; /* index for next transmit buffer */
111: int ds_nxmit; /* # of transmits in progress */
112: } de_softc[NDE];
113:
114: deprobe(reg)
115: caddr_t reg;
116: {
117: register int br, cvec; /* r11, r10 value-result */
118: register struct dedevice *addr = (struct dedevice *)reg;
119: register i;
120:
121: #ifdef lint
122: br = 0; cvec = br; br = cvec;
123: i = 0; derint(i); deintr(i);
124: #endif
125:
126: /*
127: * Make sure self-test is finished before we screw with the board.
128: * Self-test on a DELUA can take 15 seconds (argh).
129: */
130: for (i = 0;
131: i < 160 &&
132: (addr->pcsr0 & PCSR0_FATI) == 0 &&
133: (addr->pcsr1 & PCSR1_STMASK) == STAT_RESET;
134: ++i)
135: DELAY(100000);
136: if ((addr->pcsr0 & PCSR0_FATI) != 0 ||
137: (addr->pcsr1 & PCSR1_STMASK) != STAT_READY)
138: return(0);
139:
140: addr->pcsr0 = 0;
141: DELAY(100);
142: addr->pcsr0 = PCSR0_RSET;
143: while ((addr->pcsr0 & PCSR0_INTR) == 0)
144: ;
145: /* make board interrupt by executing a GETPCBB command */
146: addr->pcsr0 = PCSR0_INTE;
147: addr->pcsr2 = 0;
148: addr->pcsr3 = 0;
149: addr->pcsr0 = PCSR0_INTE|CMD_GETPCBB;
150: DELAY(100000);
151: return(1);
152: }
153:
154: /*
155: * Interface exists: make available by filling in network interface
156: * record. System will initialize the interface when it is ready
157: * to accept packets. We get the ethernet address here.
158: */
159: deattach(ui)
160: struct uba_device *ui;
161: {
162: register struct de_softc *ds = &de_softc[ui->ui_unit];
163: register struct ifnet *ifp = &ds->ds_if;
164: register struct dedevice *addr = (struct dedevice *)ui->ui_addr;
165: int csr1;
166:
167: ifp->if_unit = ui->ui_unit;
168: ifp->if_name = "de";
169: ifp->if_mtu = ETHERMTU;
170: ifp->if_flags = IFF_BROADCAST;
171:
172: /*
173: * What kind of a board is this?
174: * The error bits 4-6 in pcsr1 are a device id as long as
175: * the high byte is zero.
176: */
177: csr1 = addr->pcsr1;
178: if (csr1 & 0xff60)
179: printf("de%d: broken\n", ui->ui_unit);
180: else if (csr1 & 0x10)
181: printf("de%d: delua\n", ui->ui_unit);
182: else
183: printf("de%d: deuna\n", ui->ui_unit);
184:
185: /*
186: * Reset the board and temporarily map
187: * the pcbb buffer onto the Unibus.
188: */
189: addr->pcsr0 = 0; /* reset INTE */
190: DELAY(100);
191: addr->pcsr0 = PCSR0_RSET;
192: (void)dewait(ui, "reset");
193:
194: ds->ds_ubaddr = uballoc(ui->ui_ubanum, (char *)&ds->ds_pcbb,
195: sizeof (struct de_pcbb), 0);
196: addr->pcsr2 = ds->ds_ubaddr & 0xffff;
197: addr->pcsr3 = (ds->ds_ubaddr >> 16) & 0x3;
198: addr->pclow = CMD_GETPCBB;
199: (void)dewait(ui, "pcbb");
200:
201: ds->ds_pcbb.pcbb0 = FC_RDPHYAD;
202: addr->pclow = CMD_GETCMD;
203: (void)dewait(ui, "read addr ");
204:
205: ubarelse(ui->ui_ubanum, &ds->ds_ubaddr);
206: bcopy((caddr_t)&ds->ds_pcbb.pcbb2, (caddr_t)ds->ds_addr,
207: sizeof (ds->ds_addr));
208: printf("de%d: hardware address %s\n", ui->ui_unit,
209: ether_sprintf(ds->ds_addr));
210: ifp->if_init = deinit;
211: ifp->if_output = deoutput;
212: ifp->if_ioctl = deioctl;
213: ifp->if_reset = dereset;
214: ds->ds_deuba.iff_flags = UBA_CANTWAIT;
215: #ifdef notdef
216: /* CAN WE USE BDP's ??? */
217: ds->ds_deuba.iff_flags |= UBA_NEEDBDP;
218: #endif
219: if_attach(ifp);
220: }
221:
222: /*
223: * Reset of interface after UNIBUS reset.
224: * If interface is on specified uba, reset its state.
225: */
226: dereset(unit, uban)
227: int unit, uban;
228: {
229: register struct uba_device *ui;
230:
231: if (unit >= NDE || (ui = deinfo[unit]) == 0 || ui->ui_alive == 0 ||
232: ui->ui_ubanum != uban)
233: return;
234: printf(" de%d", unit);
235: de_softc[unit].ds_if.if_flags &= ~IFF_RUNNING;
236: de_softc[unit].ds_flags &= ~(DSF_LOCK | DSF_RUNNING);
237: ((struct dedevice *)ui->ui_addr)->pcsr0 = PCSR0_RSET;
238: (void)dewait(ui, "reset");
239: deinit(unit);
240: }
241:
242: /*
243: * Initialization of interface; clear recorded pending
244: * operations, and reinitialize UNIBUS usage.
245: */
246: deinit(unit)
247: int unit;
248: {
249: register struct de_softc *ds = &de_softc[unit];
250: register struct uba_device *ui = deinfo[unit];
251: register struct dedevice *addr;
252: register struct ifrw *ifrw;
253: register struct ifxmt *ifxp;
254: struct ifnet *ifp = &ds->ds_if;
255: int s;
256: struct de_ring *rp;
257: int incaddr;
258:
259: /* not yet, if address still unknown */
260: if (ifp->if_addrlist == (struct ifaddr *)0)
261: return;
262:
263: if (ds->ds_flags & DSF_RUNNING)
264: return;
265: if ((ifp->if_flags & IFF_RUNNING) == 0) {
266: if (if_ubaminit(&ds->ds_deuba, ui->ui_ubanum,
267: sizeof (struct ether_header), (int)btoc(ETHERMTU),
268: ds->ds_ifr, NRCV, ds->ds_ifw, NXMT) == 0) {
269: printf("de%d: can't initialize\n", unit);
270: ds->ds_if.if_flags &= ~IFF_UP;
271: return;
272: }
273: ds->ds_ubaddr = uballoc(ui->ui_ubanum, INCORE_BASE(ds),
274: INCORE_SIZE, 0);
275: }
276: addr = (struct dedevice *)ui->ui_addr;
277:
278: /* set the pcbb block address */
279: incaddr = ds->ds_ubaddr + PCBB_OFFSET;
280: addr->pcsr2 = incaddr & 0xffff;
281: addr->pcsr3 = (incaddr >> 16) & 0x3;
282: addr->pclow = 0; /* reset INTE */
283: DELAY(100);
284: addr->pclow = CMD_GETPCBB;
285: (void)dewait(ui, "pcbb");
286:
287: /* set the transmit and receive ring header addresses */
288: incaddr = ds->ds_ubaddr + UDBBUF_OFFSET;
289: ds->ds_pcbb.pcbb0 = FC_WTRING;
290: ds->ds_pcbb.pcbb2 = incaddr & 0xffff;
291: ds->ds_pcbb.pcbb4 = (incaddr >> 16) & 0x3;
292:
293: incaddr = ds->ds_ubaddr + XRENT_OFFSET;
294: ds->ds_udbbuf.b_tdrbl = incaddr & 0xffff;
295: ds->ds_udbbuf.b_tdrbh = (incaddr >> 16) & 0x3;
296: ds->ds_udbbuf.b_telen = sizeof (struct de_ring) / sizeof (short);
297: ds->ds_udbbuf.b_trlen = NXMT;
298: incaddr = ds->ds_ubaddr + RRENT_OFFSET;
299: ds->ds_udbbuf.b_rdrbl = incaddr & 0xffff;
300: ds->ds_udbbuf.b_rdrbh = (incaddr >> 16) & 0x3;
301: ds->ds_udbbuf.b_relen = sizeof (struct de_ring) / sizeof (short);
302: ds->ds_udbbuf.b_rrlen = NRCV;
303:
304: addr->pclow = CMD_GETCMD;
305: (void)dewait(ui, "wtring");
306:
307: /* initialize the mode - enable hardware padding */
308: ds->ds_pcbb.pcbb0 = FC_WTMODE;
309: /* let hardware do padding - set MTCH bit on broadcast */
310: ds->ds_pcbb.pcbb2 = MOD_TPAD|MOD_HDX;
311: addr->pclow = CMD_GETCMD;
312: (void)dewait(ui, "wtmode");
313:
314: /* set up the receive and transmit ring entries */
315: ifxp = &ds->ds_ifw[0];
316: for (rp = &ds->ds_xrent[0]; rp < &ds->ds_xrent[NXMT]; rp++) {
317: rp->r_segbl = ifxp->ifw_info & 0xffff;
318: rp->r_segbh = (ifxp->ifw_info >> 16) & 0x3;
319: rp->r_flags = 0;
320: ifxp++;
321: }
322: ifrw = &ds->ds_ifr[0];
323: for (rp = &ds->ds_rrent[0]; rp < &ds->ds_rrent[NRCV]; rp++) {
324: rp->r_slen = sizeof (struct de_buf);
325: rp->r_segbl = ifrw->ifrw_info & 0xffff;
326: rp->r_segbh = (ifrw->ifrw_info >> 16) & 0x3;
327: rp->r_flags = RFLG_OWN; /* hang receive */
328: ifrw++;
329: }
330:
331: /* start up the board (rah rah) */
332: s = splimp();
333: ds->ds_rindex = ds->ds_xindex = ds->ds_xfree = ds->ds_nxmit = 0;
334: ds->ds_if.if_flags |= IFF_RUNNING;
335: addr->pclow = PCSR0_INTE; /* avoid interlock */
336: destart(unit); /* queue output packets */
337: ds->ds_flags |= DSF_RUNNING; /* need before de_setaddr */
338: if (ds->ds_flags & DSF_SETADDR)
339: de_setaddr(ds->ds_addr, unit);
340: addr->pclow = CMD_START | PCSR0_INTE;
341: splx(s);
342: }
343:
344: /*
345: * Setup output on interface.
346: * Get another datagram to send off of the interface queue,
347: * and map it to the interface before starting the output.
348: */
349: destart(unit)
350: int unit;
351: {
352: int len;
353: struct uba_device *ui = deinfo[unit];
354: struct dedevice *addr = (struct dedevice *)ui->ui_addr;
355: register struct de_softc *ds = &de_softc[unit];
356: register struct de_ring *rp;
357: struct mbuf *m;
358: register int nxmit;
359:
360: /*
361: * the following test is necessary, since
362: * the code is not reentrant and we have
363: * multiple transmission buffers.
364: */
365: if (ds->ds_flags & DSF_LOCK)
366: return;
367: for (nxmit = ds->ds_nxmit; nxmit < NXMT; nxmit++) {
368: IF_DEQUEUE(&ds->ds_if.if_snd, m);
369: if (m == 0)
370: break;
371: rp = &ds->ds_xrent[ds->ds_xfree];
372: if (rp->r_flags & XFLG_OWN)
373: panic("deuna xmit in progress");
374: len = if_ubaput(&ds->ds_deuba, &ds->ds_ifw[ds->ds_xfree], m);
375: if (ds->ds_deuba.iff_flags & UBA_NEEDBDP)
376: UBAPURGE(ds->ds_deuba.iff_uba,
377: ds->ds_ifw[ds->ds_xfree].ifw_bdp);
378: rp->r_slen = len;
379: rp->r_tdrerr = 0;
380: rp->r_flags = XFLG_STP|XFLG_ENP|XFLG_OWN;
381:
382: ds->ds_xfree++;
383: if (ds->ds_xfree == NXMT)
384: ds->ds_xfree = 0;
385: }
386: if (ds->ds_nxmit != nxmit) {
387: ds->ds_nxmit = nxmit;
388: if (ds->ds_flags & DSF_RUNNING)
389: addr->pclow = PCSR0_INTE|CMD_PDMD;
390: }
391: }
392:
393: /*
394: * Command done interrupt.
395: */
396: deintr(unit)
397: int unit;
398: {
399: struct uba_device *ui = deinfo[unit];
400: register struct dedevice *addr = (struct dedevice *)ui->ui_addr;
401: register struct de_softc *ds = &de_softc[unit];
402: register struct de_ring *rp;
403: register struct ifxmt *ifxp;
404: short csr0;
405:
406: /* save flags right away - clear out interrupt bits */
407: csr0 = addr->pcsr0;
408: addr->pchigh = csr0 >> 8;
409:
410:
411: ds->ds_flags |= DSF_LOCK; /* prevent entering destart */
412: /*
413: * if receive, put receive buffer on mbuf
414: * and hang the request again
415: */
416: derecv(unit);
417:
418: /*
419: * Poll transmit ring and check status.
420: * Be careful about loopback requests.
421: * Then free buffer space and check for
422: * more transmit requests.
423: */
424: for ( ; ds->ds_nxmit > 0; ds->ds_nxmit--) {
425: rp = &ds->ds_xrent[ds->ds_xindex];
426: if (rp->r_flags & XFLG_OWN)
427: break;
428: ds->ds_if.if_opackets++;
429: ifxp = &ds->ds_ifw[ds->ds_xindex];
430: /* check for unusual conditions */
431: if (rp->r_flags & (XFLG_ERRS|XFLG_MTCH|XFLG_ONE|XFLG_MORE)) {
432: if (rp->r_flags & XFLG_ERRS) {
433: /* output error */
434: ds->ds_if.if_oerrors++;
435: if (dedebug)
436: printf("de%d: oerror, flags=%b tdrerr=%b (len=%d)\n",
437: unit, rp->r_flags, XFLG_BITS,
438: rp->r_tdrerr, XERR_BITS, rp->r_slen);
439: } else if (rp->r_flags & XFLG_ONE) {
440: /* one collision */
441: ds->ds_if.if_collisions++;
442: } else if (rp->r_flags & XFLG_MORE) {
443: /* more than one collision */
444: ds->ds_if.if_collisions += 2; /* guess */
445: } else if (rp->r_flags & XFLG_MTCH) {
446: /* received our own packet */
447: ds->ds_if.if_ipackets++;
448: deread(ds, &ifxp->ifrw,
449: rp->r_slen - sizeof (struct ether_header));
450: }
451: }
452: if (ifxp->ifw_xtofree) {
453: m_freem(ifxp->ifw_xtofree);
454: ifxp->ifw_xtofree = 0;
455: }
456: /* check if next transmit buffer also finished */
457: ds->ds_xindex++;
458: if (ds->ds_xindex == NXMT)
459: ds->ds_xindex = 0;
460: }
461: ds->ds_flags &= ~DSF_LOCK;
462: destart(unit);
463:
464: if (csr0 & PCSR0_RCBI) {
465: if (dedebug)
466: log(LOG_WARNING, "de%d: buffer unavailable\n", unit);
467: addr->pclow = PCSR0_INTE|CMD_PDMD;
468: }
469: }
470:
471: /*
472: * Ethernet interface receiver interface.
473: * If input error just drop packet.
474: * Otherwise purge input buffered data path and examine
475: * packet to determine type. If can't determine length
476: * from type, then have to drop packet. Othewise decapsulate
477: * packet based on type and pass to type specific higher-level
478: * input routine.
479: */
480: derecv(unit)
481: int unit;
482: {
483: register struct de_softc *ds = &de_softc[unit];
484: register struct de_ring *rp;
485: int len;
486:
487: rp = &ds->ds_rrent[ds->ds_rindex];
488: while ((rp->r_flags & RFLG_OWN) == 0) {
489: ds->ds_if.if_ipackets++;
490: if (ds->ds_deuba.iff_flags & UBA_NEEDBDP)
491: UBAPURGE(ds->ds_deuba.iff_uba,
492: ds->ds_ifr[ds->ds_rindex].ifrw_bdp);
493: len = (rp->r_lenerr&RERR_MLEN) - sizeof (struct ether_header)
494: - 4; /* don't forget checksum! */
495: /* check for errors */
496: if ((rp->r_flags & (RFLG_ERRS|RFLG_FRAM|RFLG_OFLO|RFLG_CRC)) ||
497: (rp->r_flags&(RFLG_STP|RFLG_ENP)) != (RFLG_STP|RFLG_ENP) ||
498: (rp->r_lenerr & (RERR_BUFL|RERR_UBTO|RERR_NCHN)) ||
499: len < ETHERMIN || len > ETHERMTU) {
500: ds->ds_if.if_ierrors++;
501: if (dedebug)
502: printf("de%d: ierror, flags=%b lenerr=%b (len=%d)\n",
503: unit, rp->r_flags, RFLG_BITS, rp->r_lenerr,
504: RERR_BITS, len);
505: } else
506: deread(ds, &ds->ds_ifr[ds->ds_rindex], len);
507:
508: /* hang the receive buffer again */
509: rp->r_lenerr = 0;
510: rp->r_flags = RFLG_OWN;
511:
512: /* check next receive buffer */
513: ds->ds_rindex++;
514: if (ds->ds_rindex == NRCV)
515: ds->ds_rindex = 0;
516: rp = &ds->ds_rrent[ds->ds_rindex];
517: }
518: }
519:
520: /*
521: * Pass a packet to the higher levels.
522: * We deal with the trailer protocol here.
523: */
524: deread(ds, ifrw, len)
525: register struct de_softc *ds;
526: struct ifrw *ifrw;
527: int len;
528: {
529: struct ether_header *eh;
530: struct mbuf *m;
531: int off, resid;
532: int s;
533: register struct ifqueue *inq;
534:
535: /*
536: * Deal with trailer protocol: if type is trailer type
537: * get true type from first 16-bit word past data.
538: * Remember that type was trailer by setting off.
539: */
540: eh = (struct ether_header *)ifrw->ifrw_addr;
541: eh->ether_type = ntohs((u_short)eh->ether_type);
542: #define dedataaddr(eh, off, type) ((type)(((caddr_t)((eh)+1)+(off))))
543: if (eh->ether_type >= ETHERTYPE_TRAIL &&
544: eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
545: off = (eh->ether_type - ETHERTYPE_TRAIL) * 512;
546: if (off >= ETHERMTU)
547: return; /* sanity */
548: eh->ether_type = ntohs(*dedataaddr(eh, off, u_short *));
549: resid = ntohs(*(dedataaddr(eh, off+2, u_short *)));
550: if (off + resid > len)
551: return; /* sanity */
552: len = off + resid;
553: } else
554: off = 0;
555: if (len == 0)
556: return;
557:
558: /*
559: * Pull packet off interface. Off is nonzero if packet
560: * has trailing header; if_ubaget will then force this header
561: * information to be at the front, but we still have to drop
562: * the type and length which are at the front of any trailer data.
563: */
564: m = if_ubaget(&ds->ds_deuba, ifrw, len, off, &ds->ds_if);
565: if (m == 0)
566: return;
567: if (off) {
568: struct ifnet *ifp;
569:
570: ifp = *(mtod(m, struct ifnet **));
571: m->m_off += 2 * sizeof (u_short);
572: m->m_len -= 2 * sizeof (u_short);
573: *(mtod(m, struct ifnet **)) = ifp;
574: }
575: switch (eh->ether_type) {
576:
577: #ifdef INET
578: case ETHERTYPE_IP:
579: schednetisr(NETISR_IP);
580: inq = &ipintrq;
581: break;
582:
583: case ETHERTYPE_ARP:
584: arpinput(&ds->ds_ac, m);
585: return;
586: #endif
587: #ifdef NS
588: case ETHERTYPE_NS:
589: schednetisr(NETISR_NS);
590: inq = &nsintrq;
591: break;
592:
593: #endif
594: default:
595: m_freem(m);
596: return;
597: }
598:
599: s = splimp();
600: if (IF_QFULL(inq)) {
601: IF_DROP(inq);
602: splx(s);
603: m_freem(m);
604: return;
605: }
606: IF_ENQUEUE(inq, m);
607: splx(s);
608: }
609:
610: /*
611: * Ethernet output routine.
612: * Encapsulate a packet of type family for the local net.
613: * Use trailer local net encapsulation if enough data in first
614: * packet leaves a multiple of 512 bytes of data in remainder.
615: */
616: deoutput(ifp, m0, dst)
617: struct ifnet *ifp;
618: struct mbuf *m0;
619: struct sockaddr *dst;
620: {
621: int type, s, error;
622: u_char edst[6];
623: struct in_addr idst;
624: register struct de_softc *ds = &de_softc[ifp->if_unit];
625: register struct mbuf *m = m0;
626: register struct ether_header *eh;
627: register int off;
628: int usetrailers;
629:
630: if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
631: error = ENETDOWN;
632: goto bad;
633: }
634: switch (dst->sa_family) {
635:
636: #ifdef INET
637: case AF_INET:
638: idst = ((struct sockaddr_in *)dst)->sin_addr;
639: if (!arpresolve(&ds->ds_ac, m, &idst, edst, &usetrailers))
640: return (0); /* if not yet resolved */
641: off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
642: if (usetrailers && off > 0 && (off & 0x1ff) == 0 &&
643: m->m_off >= MMINOFF + 2 * sizeof (u_short)) {
644: type = ETHERTYPE_TRAIL + (off>>9);
645: m->m_off -= 2 * sizeof (u_short);
646: m->m_len += 2 * sizeof (u_short);
647: *mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP);
648: *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len);
649: goto gottrailertype;
650: }
651: type = ETHERTYPE_IP;
652: off = 0;
653: goto gottype;
654: #endif
655: #ifdef NS
656: case AF_NS:
657: type = ETHERTYPE_NS;
658: bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
659: (caddr_t)edst, sizeof (edst));
660: off = 0;
661: goto gottype;
662: #endif
663:
664: case AF_UNSPEC:
665: eh = (struct ether_header *)dst->sa_data;
666: bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst));
667: type = eh->ether_type;
668: goto gottype;
669:
670: default:
671: printf("de%d: can't handle af%d\n", ifp->if_unit,
672: dst->sa_family);
673: error = EAFNOSUPPORT;
674: goto bad;
675: }
676:
677: gottrailertype:
678: /*
679: * Packet to be sent as trailer: move first packet
680: * (control information) to end of chain.
681: */
682: while (m->m_next)
683: m = m->m_next;
684: m->m_next = m0;
685: m = m0->m_next;
686: m0->m_next = 0;
687: m0 = m;
688:
689: gottype:
690: /*
691: * Add local net header. If no space in first mbuf,
692: * allocate another.
693: */
694: if (m->m_off > MMAXOFF ||
695: MMINOFF + sizeof (struct ether_header) > m->m_off) {
696: m = m_get(M_DONTWAIT, MT_HEADER);
697: if (m == 0) {
698: error = ENOBUFS;
699: goto bad;
700: }
701: m->m_next = m0;
702: m->m_off = MMINOFF;
703: m->m_len = sizeof (struct ether_header);
704: } else {
705: m->m_off -= sizeof (struct ether_header);
706: m->m_len += sizeof (struct ether_header);
707: }
708: eh = mtod(m, struct ether_header *);
709: eh->ether_type = htons((u_short)type);
710: bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst));
711: /* DEUNA fills in source address */
712:
713: /*
714: * Queue message on interface, and start output if interface
715: * not yet active.
716: */
717: s = splimp();
718: if (IF_QFULL(&ifp->if_snd)) {
719: IF_DROP(&ifp->if_snd);
720: splx(s);
721: m_freem(m);
722: return (ENOBUFS);
723: }
724: IF_ENQUEUE(&ifp->if_snd, m);
725: destart(ifp->if_unit);
726: splx(s);
727: return (0);
728:
729: bad:
730: m_freem(m0);
731: return (error);
732: }
733:
734: /*
735: * Process an ioctl request.
736: */
737: deioctl(ifp, cmd, data)
738: register struct ifnet *ifp;
739: int cmd;
740: caddr_t data;
741: {
742: register struct ifaddr *ifa = (struct ifaddr *)data;
743: register struct de_softc *ds = &de_softc[ifp->if_unit];
744: int s = splimp(), error = 0;
745:
746: switch (cmd) {
747:
748: case SIOCSIFADDR:
749: ifp->if_flags |= IFF_UP;
750: deinit(ifp->if_unit);
751:
752: switch (ifa->ifa_addr.sa_family) {
753: #ifdef INET
754: case AF_INET:
755: ((struct arpcom *)ifp)->ac_ipaddr =
756: IA_SIN(ifa)->sin_addr;
757: arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
758: break;
759: #endif
760: #ifdef NS
761: case AF_NS:
762: {
763: register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
764:
765: if (ns_nullhost(*ina))
766: ina->x_host = *(union ns_host *)(ds->ds_addr);
767: else
768: de_setaddr(ina->x_host.c_host,ifp->if_unit);
769: break;
770: }
771: #endif
772: }
773: break;
774:
775: case SIOCSIFFLAGS:
776: if ((ifp->if_flags & IFF_UP) == 0 &&
777: ds->ds_flags & DSF_RUNNING) {
778: ((struct dedevice *)
779: (deinfo[ifp->if_unit]->ui_addr))->pclow = 0;
780: DELAY(100);
781: ((struct dedevice *)
782: (deinfo[ifp->if_unit]->ui_addr))->pclow = PCSR0_RSET;
783: ds->ds_flags &= ~(DSF_LOCK | DSF_RUNNING);
784: } else if (ifp->if_flags & IFF_UP &&
785: (ds->ds_flags & DSF_RUNNING) == 0)
786: deinit(ifp->if_unit);
787: break;
788:
789: default:
790: error = EINVAL;
791: }
792: splx(s);
793: return (error);
794: }
795:
796: /*
797: * set ethernet address for unit
798: */
799: de_setaddr(physaddr, unit)
800: u_char *physaddr;
801: int unit;
802: {
803: register struct de_softc *ds = &de_softc[unit];
804: struct uba_device *ui = deinfo[unit];
805: register struct dedevice *addr= (struct dedevice *)ui->ui_addr;
806:
807: if (! (ds->ds_flags & DSF_RUNNING))
808: return;
809:
810: bcopy((caddr_t) physaddr, (caddr_t) &ds->ds_pcbb.pcbb2, 6);
811: ds->ds_pcbb.pcbb0 = FC_WTPHYAD;
812: addr->pclow = PCSR0_INTE|CMD_GETCMD;
813: if (dewait(ui, "address change") == 0) {
814: ds->ds_flags |= DSF_SETADDR;
815: bcopy((caddr_t) physaddr, (caddr_t) ds->ds_addr, 6);
816: }
817: }
818:
819: /*
820: * Await completion of the named function
821: * and check for errors.
822: */
823: dewait(ui, fn)
824: register struct uba_device *ui;
825: char *fn;
826: {
827: register struct dedevice *addr = (struct dedevice *)ui->ui_addr;
828: register csr0;
829:
830: while ((addr->pcsr0 & PCSR0_INTR) == 0)
831: ;
832: csr0 = addr->pcsr0;
833: addr->pchigh = csr0 >> 8;
834: if (csr0 & PCSR0_PCEI)
835: printf("de%d: %s failed, csr0=%b csr1=%b\n",
836: ui->ui_unit, fn, csr0, PCSR0_BITS,
837: addr->pcsr1, PCSR1_BITS);
838: return (csr0 & PCSR0_PCEI);
839: }
840: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.