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