|
|
1.1 root 1: /*-
2: * Copyright (c) 1990 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * This code is derived from software contributed to Berkeley by
6: * Tim L. Tucker.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed by the University of
19: * California, Berkeley and its contributors.
20: * 4. Neither the name of the University nor the names of its contributors
21: * may be used to endorse or promote products derived from this software
22: * without specific prior written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34: * SUCH DAMAGE.
35: *
36: * @(#)if_we.c 7.3 (Berkeley) 5/21/91
37: */
38:
39: /*
40: * Modification history
41: *
42: * 8/28/89 - Initial version(if_wd.c), Tim L Tucker
43: */
44:
45: #include "we.h"
46: #if NWE > 0
47: /*
48: * Western Digital 8003 ethernet/starlan adapter
49: *
50: * Supports the following interface cards:
51: * WD8003E, WD8003EBT, WD8003S, WD8003SBT, WD8013EBT
52: *
53: * The Western Digital card is one of many AT/MCA ethernet interfaces
54: * based on the National DS8390 Network Interface chip set.
55: */
56: #include "param.h"
57: #include "mbuf.h"
58: #include "socket.h"
59: #include "ioctl.h"
60: #include "errno.h"
61: #include "syslog.h"
62:
63: #include "net/if.h"
64: #include "net/netisr.h"
65:
66: #ifdef INET
67: #include "netinet/in.h"
68: #include "netinet/in_systm.h"
69: #include "netinet/in_var.h"
70: #include "netinet/ip.h"
71: #include "netinet/if_ether.h"
72: #endif
73:
74: #ifdef NS
75: #include "netns/ns.h"
76: #include "netns/ns_if.h"
77: #endif
78:
1.1.1.2 ! root 79: #include "i386/isa/isa.h"
1.1 root 80: #include "i386/isa/if_wereg.h"
81: #include "i386/isa/isa_device.h"
1.1.1.2 ! root 82: #include "i386/isa/icu.h"
1.1 root 83:
84: /*
85: * This constant should really be 60 because the we adds 4 bytes of crc.
1.1.1.2 ! root 86: * However when set to 60 our packets are ignored by deunas , 3coms are
1.1 root 87: * okay ??????????????????????????????????????????
88: */
89: #define ETHER_MIN_LEN 64
90: #define ETHER_ADDR_LEN 6
91: #define ETHER_HDR_SIZE 14
92:
93: /*
94: * Ethernet software status per interface.
95: *
96: * Each interface is referenced by a network interface structure,
97: * qe_if, which the routing code uses to locate the interface.
98: * This structure contains the output queue for the interface, its address, ...
99: */
100: struct we_softc {
101: struct arpcom we_ac; /* Ethernet common part */
102: #define we_if we_ac.ac_if /* network-visible interface */
103: #define we_addr we_ac.ac_enaddr /* hardware Ethernet address */
104:
105: u_char we_flags; /* software state */
106: #define WDF_RUNNING 0x01
107: #define WDF_TXBUSY 0x02
108:
109: u_char we_type; /* interface type code */
110: u_short we_vector; /* interrupt vector */
111: short we_io_ctl_addr; /* i/o bus address, control */
112: short we_io_nic_addr; /* i/o bus address, DS8390 */
113:
114: caddr_t we_vmem_addr; /* card RAM virtual memory base */
115: u_long we_vmem_size; /* card RAM bytes */
116: caddr_t we_vmem_ring; /* receive ring RAM vaddress */
117: caddr_t we_vmem_end; /* receive ring RAM end */
118: } we_softc[NWE];
119:
120: int weprobe(), weattach(), weintr(), westart();
121: int weinit(), ether_output(), weioctl(), wereset(), wewatchdog();
122:
123: struct isa_driver wedriver = {
124: weprobe, weattach, "we",
125: };
126:
1.1.1.2 ! root 127: static unsigned short wemask[] =
! 128: { IRQ9, IRQ3, IRQ5, IRQ7, IRQ10, IRQ11, IRQ15, IRQ4 };
! 129:
1.1 root 130: /*
1.1.1.2 ! root 131: * Probe the WD8003 to see if its there
1.1 root 132: */
133: weprobe(is)
134: struct isa_device *is;
135: {
136: register int i;
137: register struct we_softc *sc = &we_softc[is->id_unit];
138: union we_mem_sel wem;
139: u_char sum;
140:
1.1.1.2 ! root 141: /* reset card to force it into a known state. */
! 142: outb(is->id_iobase, 0x80);
! 143: DELAY(100);
! 144: outb(is->id_iobase, 0x00);
! 145: /* wait in the case this card is reading it's EEROM */
! 146: DELAY(5000);
! 147:
1.1 root 148: /*
149: * Here we check the card ROM, if the checksum passes, and the
150: * type code and ethernet address check out, then we know we have
151: * a wd8003 card.
152: *
153: * Autoconfiguration: No warning message is printed on error.
154: */
155: for (sum = 0, i = 0; i < 8; ++i)
156: sum += inb(is->id_iobase + WD_ROM_OFFSET + i);
157: if (sum != WD_CHECKSUM)
158: return (0);
159: sc->we_type = inb(is->id_iobase + WD_ROM_OFFSET + 6);
1.1.1.2 ! root 160: #ifdef nope
! 161: if ((sc->we_type & WD_REVMASK) != 2 /* WD8003E or WD8003S */
! 162: && (sc->we_type & WD_REVMASK) != 4 /* WD8003EBT */
! 163: && (sc->we_type & WD_REVMASK) != 6) /* WD8003ELB? */
1.1 root 164: return (0);
1.1.1.2 ! root 165: #endif
! 166: /*printf("type %x ", sc->we_type);*/
! 167: if (sc->we_type & WD_SOFTCONFIG) {
! 168: int iv = inb(is->id_iobase + 1) & 4 |
! 169: ((inb(is->id_iobase+4) & 0x60) >> 5);
! 170: /*printf("iv %d ", iv);*/
! 171: if (wemask[iv] != is->id_irq)
! 172: return(0);
! 173: outb(is->id_iobase+4, inb(is->id_iobase+4) | 0x80);
! 174: }
1.1 root 175:
176: /*
177: * Setup card RAM area and i/o addresses
178: * Kernel Virtual to segment C0000-DFFFF?????
179: */
180: sc->we_io_ctl_addr = is->id_iobase;
181: sc->we_io_nic_addr = sc->we_io_ctl_addr + WD_NIC_OFFSET;
182: sc->we_vector = is->id_irq;
183: sc->we_vmem_addr = (caddr_t)is->id_maddr;
184: sc->we_vmem_size = is->id_msize;
185: sc->we_vmem_ring = sc->we_vmem_addr + (WD_PAGE_SIZE * WD_TXBUF_SIZE);
186: sc->we_vmem_end = sc->we_vmem_addr + is->id_msize;
187:
188: /*
189: * Save board ROM station address
190: */
191: for (i = 0; i < ETHER_ADDR_LEN; ++i)
192: sc->we_addr[i] = inb(sc->we_io_ctl_addr + WD_ROM_OFFSET + i);
193:
194: /*
195: * Mapin interface memory, setup memory select register
196: */
1.1.1.2 ! root 197: wem.ms_addr = kvtop(sc->we_vmem_addr) >> 13;
1.1 root 198: wem.ms_enable = 1;
199: wem.ms_reset = 0;
200: outb(sc->we_io_ctl_addr, wem.ms_byte);
201:
202: /*
203: * clear interface memory, then sum to make sure its valid
204: */
205: for (i = 0; i < sc->we_vmem_size; ++i)
206: sc->we_vmem_addr[i] = 0x0;
207: for (sum = 0, i = 0; i < sc->we_vmem_size; ++i)
208: sum += sc->we_vmem_addr[i];
209: if (sum != 0x0) {
210: printf("we%d: wd8003 dual port RAM address error\n", is->id_unit);
211: return (0);
212: }
213:
214: return (WD_IO_PORTS);
215: }
216:
217: /*
218: * Interface exists: make available by filling in network interface
219: * record. System will initialize the interface when it is ready
220: * to accept packets.
221: */
222: weattach(is)
223: struct isa_device *is;
224: {
225: register struct we_softc *sc = &we_softc[is->id_unit];
226: register struct ifnet *ifp = &sc->we_if;
227: union we_command wecmd;
228:
229: wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND);
230: wecmd.cs_stp = 1;
231: wecmd.cs_sta = 0;
232: wecmd.cs_ps = 0;
233: outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
234: /*
235: * Initialize ifnet structure
236: */
237: ifp->if_unit = is->id_unit;
238: ifp->if_name = "we" ;
239: ifp->if_mtu = ETHERMTU;
240: ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS ;
241: ifp->if_init = weinit;
242: ifp->if_output = ether_output;
243: ifp->if_start = westart;
244: ifp->if_ioctl = weioctl;
245: ifp->if_reset = wereset;
246: ifp->if_watchdog = wewatchdog;
247: if_attach(ifp);
248:
249: /*
250: * Banner...
251: */
252: printf(" %s address %s",
1.1.1.2 ! root 253: (sc->we_type & WD_ETHERNET) ? "ethernet" : "starlan",
1.1 root 254: ether_sprintf(sc->we_addr));
255: }
256:
257: /*
258: * Reset of interface.
259: */
260: wereset(unit, uban)
261: int unit, uban;
262: {
263: if (unit >= NWE)
264: return;
265: printf("we%d: reset\n", unit);
266: /* we_softc[unit].we_flags &= ~WDF_RUNNING; */
267: weinit(unit);
268: }
269:
270: /*
271: * Take interface offline.
272: */
273: westop(unit)
274: int unit;
275: {
276: register struct we_softc *sc = &we_softc[unit];
277: union we_command wecmd;
278: int s;
279:
280: /*
281: * Shutdown DS8390
282: */
283: s = splimp();
284: wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND);
285: wecmd.cs_stp = 1;
286: wecmd.cs_sta = 0;
287: wecmd.cs_ps = 0;
288: outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
289: (void) splx(s);
290: }
291:
292: wewatchdog(unit) {
293:
294: log(LOG_WARNING,"we%d: soft reset\n", unit);
295: westop(unit);
296: weinit(unit);
297: }
298:
299: static Bdry;
300: /*
301: * Initialization of interface (really just DS8390).
302: */
303: weinit(unit)
304: int unit;
305: {
306: register struct we_softc *sc = &we_softc[unit];
307: register struct ifnet *ifp = &sc->we_if;
308: union we_command wecmd;
309: int i, s;
310:
311: /* address not known */
312: if (ifp->if_addrlist == (struct ifaddr *)0)
313: return;
314:
315: /* already running */
316: /*if (ifp->if_flags & IFF_RUNNING) return; */
317:
318: /*
319: * Initialize DS8390 in order given in NSC NIC manual.
320: * this is stock code...please see the National manual for details.
321: */
322: s = splhigh();
323: Bdry = 0;
324: wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND);
325: wecmd.cs_stp = 1;
326: wecmd.cs_sta = 0;
327: wecmd.cs_ps = 0;
328: outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
329: outb(sc->we_io_nic_addr + WD_P0_DCR, WD_D_CONFIG);
330: outb(sc->we_io_nic_addr + WD_P0_RBCR0, 0);
331: outb(sc->we_io_nic_addr + WD_P0_RBCR1, 0);
332: outb(sc->we_io_nic_addr + WD_P0_RCR, WD_R_MON);
333: outb(sc->we_io_nic_addr + WD_P0_TCR, WD_T_CONFIG);
334: outb(sc->we_io_nic_addr + WD_P0_TPSR, 0);
335: outb(sc->we_io_nic_addr + WD_P0_PSTART, WD_TXBUF_SIZE);
336: outb(sc->we_io_nic_addr + WD_P0_PSTOP,
337: sc->we_vmem_size / WD_PAGE_SIZE);
338: outb(sc->we_io_nic_addr + WD_P0_BNRY, WD_TXBUF_SIZE);
339: outb(sc->we_io_nic_addr + WD_P0_ISR, 0xff);
340: outb(sc->we_io_nic_addr + WD_P0_IMR, WD_I_CONFIG);
341: wecmd.cs_ps = 1;
342: outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
343: for (i = 0; i < ETHER_ADDR_LEN; ++i)
344: outb(sc->we_io_nic_addr + WD_P1_PAR0 + i, sc->we_addr[i]);
345: for (i = 0; i < ETHER_ADDR_LEN; ++i) /* == broadcast addr */
346: outb(sc->we_io_nic_addr + WD_P1_MAR0 + i, 0xff);
347: outb(sc->we_io_nic_addr + WD_P1_CURR, WD_TXBUF_SIZE);
348: wecmd.cs_ps = 0;
349: wecmd.cs_stp = 0;
350: wecmd.cs_sta = 1;
351: wecmd.cs_rd = 0x4;
352: outb(sc->we_io_nic_addr + WD_P1_COMMAND, wecmd.cs_byte);
353: outb(sc->we_io_nic_addr + WD_P0_RCR, WD_R_CONFIG);
354:
355: /*
356: * Take the interface out of reset, program the vector,
357: * enable interrupts, and tell the world we are up.
358: */
359: ifp->if_flags |= IFF_RUNNING;
360: sc->we_flags &= ~WDF_TXBUSY;
361: (void) splx(s);
362: westart(ifp);
363: }
364:
365: /*
366: * Start output on interface.
367: */
368: westart(ifp)
369: struct ifnet *ifp;
370: {
371: register struct we_softc *sc = &we_softc[ifp->if_unit];
372: struct mbuf *m0, *m;
373: register caddr_t buffer;
374: int len, s;
375: union we_command wecmd;
376:
377: /*
378: * The DS8390 has only one transmit buffer, if it is busy we
379: * must wait until the transmit interrupt completes.
380: */
381: s = splhigh();
382: if (sc->we_flags & WDF_TXBUSY) {
383: (void) splx(s);
384: return;
385: }
386: IF_DEQUEUE(&sc->we_if.if_snd, m);
387: if (m == 0) {
388: (void) splx(s);
389: return;
390: }
391: sc->we_flags |= WDF_TXBUSY;
392: (void) splx(s);
393:
394: /*
395: * Copy the mbuf chain into the transmit buffer
396: */
397: buffer = sc->we_vmem_addr;
398: len = 0;
399: for (m0 = m; m != 0; m = m->m_next) {
400: bcopy(mtod(m, caddr_t), buffer, m->m_len);
401: buffer += m->m_len;
402: len += m->m_len;
403: }
404:
405: m_freem(m0);
406:
407: /*
408: * Init transmit length registers, and set transmit start flag.
409: */
410: s = splhigh();
411: len = MAX(len, ETHER_MIN_LEN);
412: wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND);
413: wecmd.cs_ps = 0;
414: outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
415: outb(sc->we_io_nic_addr + WD_P0_TBCR0, len & 0xff);
416: outb(sc->we_io_nic_addr + WD_P0_TBCR1, len >> 8);
417: wecmd.cs_txp = 1;
418: outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
419: (void) splx(s);
420: }
421:
422: /*
423: * Ethernet interface interrupt processor
424: */
425: weintr(unit)
426: int unit;
427: {
428: register struct we_softc *sc = &we_softc[unit];
429: union we_command wecmd;
430: union we_interrupt weisr;
431:
432: unit =0;
433:
434: /* disable onboard interrupts, then get interrupt status */
435: wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND);
436: wecmd.cs_ps = 0;
437: outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
438: weisr.is_byte = inb(sc->we_io_nic_addr + WD_P0_ISR);
439: loop:
440: outb(sc->we_io_nic_addr + WD_P0_ISR, weisr.is_byte);
441:
442: /* transmit error */
443: if (weisr.is_txe) {
444: /* need to read these registers to clear status */
445: sc->we_if.if_collisions +=
446: inb(sc->we_io_nic_addr + WD_P0_TBCR0);
447: ++sc->we_if.if_oerrors;
448: }
449:
450: /* receiver error */
451: if (weisr.is_rxe) {
452: /* need to read these registers to clear status */
453: (void) inb(sc->we_io_nic_addr + 0xD);
454: (void) inb(sc->we_io_nic_addr + 0xE);
455: (void) inb(sc->we_io_nic_addr + 0xF);
456: ++sc->we_if.if_ierrors;
457: }
458:
459: /* normal transmit complete */
460: if (weisr.is_ptx || weisr.is_txe)
461: wetint (unit);
462:
463: /* normal receive notification */
464: if (weisr.is_prx || weisr.is_rxe)
465: werint (unit);
466:
467: /* try to start transmit */
468: westart(&sc->we_if);
469:
470: /* re-enable onboard interrupts */
471: wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND);
472: wecmd.cs_ps = 0;
473: outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
474: outb(sc->we_io_nic_addr + WD_P0_IMR, 0xff/*WD_I_CONFIG*/);
475: weisr.is_byte = inb(sc->we_io_nic_addr + WD_P0_ISR);
476: if (weisr.is_byte) goto loop;
477: }
478:
479: /*
480: * Ethernet interface transmit interrupt.
481: */
482: wetint(unit)
483: int unit;
484: {
485: register struct we_softc *sc = &we_softc[unit];
486:
487: /*
488: * Do some statistics (assume page zero of NIC mapped in)
489: */
490: sc->we_flags &= ~WDF_TXBUSY;
491: sc->we_if.if_timer = 0;
492: ++sc->we_if.if_opackets;
493: sc->we_if.if_collisions += inb(sc->we_io_nic_addr + WD_P0_TBCR0);
494: }
495:
496: /*
497: * Ethernet interface receiver interrupt.
498: */
499: werint(unit)
500: int unit;
501: {
502: register struct we_softc *sc = &we_softc[unit];
503: u_char bnry, curr;
504: long len;
505: union we_command wecmd;
506: struct we_ring *wer;
507:
508: /*
509: * Traverse the receive ring looking for packets to pass back.
510: * The search is complete when we find a descriptor not in use.
511: */
512: wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND);
513: wecmd.cs_ps = 0;
514: outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
515: bnry = inb(sc->we_io_nic_addr + WD_P0_BNRY);
516: wecmd.cs_ps = 1;
517: outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
518: curr = inb(sc->we_io_nic_addr + WD_P1_CURR);
519: if(Bdry)
520: bnry =Bdry;
521:
522: while (bnry != curr)
523: {
524: /* get pointer to this buffer header structure */
525: wer = (struct we_ring *)(sc->we_vmem_addr + (bnry << 8));
526:
527: /* count includes CRC */
528: len = wer->we_count - 4;
529: if (len > 30 && len <= ETHERMTU+100
530: /*&& (*(char *)wer == 1 || *(char *) wer == 0x21)*/)
531: weread(sc, (caddr_t)(wer + 1), len);
532: else printf("reject %d", len);
533:
534: outofbufs:
535: wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND);
536: wecmd.cs_ps = 0;
537: outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
538:
539: /* advance on chip Boundry register */
540: if((caddr_t) wer + WD_PAGE_SIZE - 1 > sc->we_vmem_end) {
541: bnry = WD_TXBUF_SIZE;
542: outb(sc->we_io_nic_addr + WD_P0_BNRY,
543: sc->we_vmem_size / WD_PAGE_SIZE-1);
544:
545: } else {
546: if (len > 30 && len <= ETHERMTU+100)
547: bnry = wer->we_next_packet;
548: else bnry = curr;
549:
550: /* watch out for NIC overflow, reset Boundry if invalid */
551: if ((bnry - 1) < WD_TXBUF_SIZE) {
552: outb(sc->we_io_nic_addr + WD_P0_BNRY,
553: (sc->we_vmem_size / WD_PAGE_SIZE) - 1);
554: bnry = WD_TXBUF_SIZE;
555: } else
556: outb(sc->we_io_nic_addr + WD_P0_BNRY, bnry-1);
557: }
558:
559: /* refresh our copy of CURR */
560: wecmd.cs_ps = 1;
561: outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
562: curr = inb(sc->we_io_nic_addr + WD_P1_CURR);
563: }
564: Bdry = bnry;
565: }
566:
567: /*
568: * Process an ioctl request.
569: */
570: weioctl(ifp, cmd, data)
571: register struct ifnet *ifp;
572: int cmd;
573: caddr_t data;
574: {
575: register struct ifaddr *ifa = (struct ifaddr *)data;
576: struct we_softc *sc = &we_softc[ifp->if_unit];
577: struct ifreq *ifr = (struct ifreq *)data;
578: int s = splimp(), error = 0;
579:
580:
581: switch (cmd) {
582:
583: case SIOCSIFADDR:
584: ifp->if_flags |= IFF_UP;
585:
586: switch (ifa->ifa_addr->sa_family) {
587: #ifdef INET
588: case AF_INET:
589: weinit(ifp->if_unit); /* before arpwhohas */
590: ((struct arpcom *)ifp)->ac_ipaddr =
591: IA_SIN(ifa)->sin_addr;
592: arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
593: break;
594: #endif
595: #ifdef NS
596: case AF_NS:
597: {
598: register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
599:
600: if (ns_nullhost(*ina))
601: ina->x_host = *(union ns_host *)(sc->ns_addr);
602: else {
603: /*
1.1.1.2 ! root 604: * The manual says we cant change the address
1.1 root 605: * while the receiver is armed,
606: * so reset everything
607: */
608: ifp->if_flags &= ~IFF_RUNNING;
609: bcopy((caddr_t)ina->x_host.c_host,
610: (caddr_t)sc->ns_addr, sizeof(sc->ns_addr));
611: }
612: weinit(ifp->if_unit); /* does ne_setaddr() */
613: break;
614: }
615: #endif
616: default:
617: weinit(ifp->if_unit);
618: break;
619: }
620: break;
621:
622: case SIOCSIFFLAGS:
623: if ((ifp->if_flags & IFF_UP) == 0 &&
624: ifp->if_flags & IFF_RUNNING) {
625: ifp->if_flags &= ~IFF_RUNNING;
626: westop(ifp->if_unit);
627: } else if (ifp->if_flags & IFF_UP &&
628: (ifp->if_flags & IFF_RUNNING) == 0)
629: weinit(ifp->if_unit);
630: break;
631:
632: #ifdef notdef
633: case SIOCGHWADDR:
634: bcopy((caddr_t)sc->sc_addr, (caddr_t) &ifr->ifr_data,
635: sizeof(sc->sc_addr));
636: break;
637: #endif
638:
639: default:
640: error = EINVAL;
641: }
642: splx(s);
643: return (error);
644: }
645: /*
646: * set ethernet address for unit
647: */
648: wesetaddr(physaddr, unit)
649: u_char *physaddr;
650: int unit;
651: {
652: register struct we_softc *sc = &we_softc[unit];
653: register int i;
654:
655: /*
656: * Rewrite ethernet address, and then force restart of NIC
657: */
658: for (i = 0; i < ETHER_ADDR_LEN; i++)
659: sc->we_addr[i] = physaddr[i];
660: sc->we_flags &= ~WDF_RUNNING;
661: weinit(unit);
662: }
663:
664: #define wedataaddr(sc, eh, off, type) \
665: ((type) ((caddr_t)((eh)+1)+(off) >= (sc)->we_vmem_end) ? \
666: (((caddr_t)((eh)+1)+(off))) - (sc)->we_vmem_end \
667: + (sc)->we_vmem_ring: \
668: ((caddr_t)((eh)+1)+(off)))
669: /*
670: * Pass a packet to the higher levels.
671: * We deal with the trailer protocol here.
672: */
673: weread(sc, buf, len)
674: register struct we_softc *sc;
675: char *buf;
676: int len;
677: {
678: register struct ether_header *eh;
679: struct mbuf *m, *weget();
680: int off, resid;
681:
682: /*
683: * Deal with trailer protocol: if type is trailer type
684: * get true type from first 16-bit word past data.
685: * Remember that type was trailer by setting off.
686: */
687: eh = (struct ether_header *)buf;
688: eh->ether_type = ntohs((u_short)eh->ether_type);
689: if (eh->ether_type >= ETHERTYPE_TRAIL &&
690: eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
691: off = (eh->ether_type - ETHERTYPE_TRAIL) * 512;
692: if (off >= ETHERMTU) return; /* sanity */
693: eh->ether_type = ntohs(*wedataaddr(sc, eh, off, u_short *));
694: resid = ntohs(*(wedataaddr(sc, eh, off+2, u_short *)));
695: if (off + resid > len) return; /* sanity */
696: len = off + resid;
697: } else off = 0;
698:
699: len -= sizeof(struct ether_header);
700: if (len <= 0) return;
701:
702: /*
703: * Pull packet off interface. Off is nonzero if packet
704: * has trailing header; neget will then force this header
705: * information to be at the front, but we still have to drop
706: * the type and length which are at the front of any trailer data.
707: */
708: m = weget(buf, len, off, &sc->we_if, sc);
709: if (m == 0) return;
710: ether_input(&sc->we_if, eh, m);
711: }
712:
713: /*
714: * Supporting routines
715: */
716:
717: /*
718: * Pull read data off a interface.
719: * Len is length of data, with local net header stripped.
720: * Off is non-zero if a trailer protocol was used, and
721: * gives the offset of the trailer information.
722: * We copy the trailer information and then all the normal
723: * data into mbufs. When full cluster sized units are present
724: * we copy into clusters.
725: */
726: struct mbuf *
727: weget(buf, totlen, off0, ifp, sc)
728: caddr_t buf;
729: int totlen, off0;
730: struct ifnet *ifp;
731: struct we_softc *sc;
732: {
733: struct mbuf *top, **mp, *m, *p;
734: int off = off0, len;
735: register caddr_t cp = buf;
736: char *epkt;
737: int tc =totlen;
738:
739: buf += sizeof(struct ether_header);
740: cp = buf;
741: epkt = cp + totlen;
742:
743: if (off) {
744: cp += off + 2 * sizeof(u_short);
745: totlen -= 2 * sizeof(u_short);
746: }
747:
748: MGETHDR(m, M_DONTWAIT, MT_DATA);
749: if (m == 0)
750: return (0);
751: m->m_pkthdr.rcvif = ifp;
752: m->m_pkthdr.len = totlen;
753: m->m_len = MHLEN;
754:
755: top = 0;
756: mp = ⊤
757: while (totlen > 0) {
758: if (top) {
759: MGET(m, M_DONTWAIT, MT_DATA);
760: if (m == 0) {
761: m_freem(top);
762: return (0);
763: }
764: m->m_len = MLEN;
765: }
766: len = min(totlen, epkt - cp);
767: if (len >= MINCLSIZE) {
768: MCLGET(m, M_DONTWAIT);
769: if (m->m_flags & M_EXT)
770: m->m_len = len = min(len, MCLBYTES);
771: else
772: len = m->m_len;
773: } else {
774: /*
775: * Place initial small packet/header at end of mbuf.
776: */
777: if (len < m->m_len) {
778: if (top == 0 && len + max_linkhdr <= m->m_len)
779: m->m_data += max_linkhdr;
780: m->m_len = len;
781: } else
782: len = m->m_len;
783: }
784:
785: totlen -= len;
786: /* only do up to end of buffer */
787: if (cp+len > sc->we_vmem_end) {
788: unsigned toend = sc->we_vmem_end - cp;
789:
790: bcopy(cp, mtod(m, caddr_t), toend);
791: cp = sc->we_vmem_ring;
792: bcopy(cp, mtod(m, caddr_t)+toend, len - toend);
793: cp += len - toend;
794: epkt = cp + totlen;
795: } else {
796: bcopy(cp, mtod(m, caddr_t), (unsigned)len);
797: cp += len;
798: }
799: *mp = m;
800: mp = &m->m_next;
801: if (cp == epkt) {
802: cp = buf;
803: epkt = cp + tc;
804: }
805: }
806: return (top);
807: }
808: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.