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