|
|
1.1 root 1: /*-
2: * Copyright (c) 1990, 1991 William F. Jolitz.
3: * Copyright (c) 1990 The Regents of the University of California.
4: * All rights reserved.
5: *
6: * Redistribution and use in source and binary forms, with or without
7: * modification, are permitted provided that the following conditions
8: * are met:
9: * 1. Redistributions of source code must retain the above copyright
10: * notice, this list of conditions and the following disclaimer.
11: * 2. Redistributions in binary form must reproduce the above copyright
12: * notice, this list of conditions and the following disclaimer in the
13: * documentation and/or other materials provided with the distribution.
14: * 3. All advertising materials mentioning features or use of this software
15: * must display the following acknowledgement:
16: * This product includes software developed by the University of
17: * California, Berkeley and its contributors.
18: * 4. Neither the name of the University nor the names of its contributors
19: * may be used to endorse or promote products derived from this software
20: * without specific prior written permission.
21: *
22: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32: * SUCH DAMAGE.
33: *
1.1.1.4 ! root 34: * from: @(#)if_ne.c 7.4 (Berkeley) 5/21/91
! 35: * if_ne.c,v 1.9 1993/07/17 16:41:27 mycroft Exp
1.1 root 36: */
37:
38: /*
1.1.1.4 ! root 39: * NE2000/NE1000 Ethernet driver
1.1 root 40: *
41: * Parts inspired from Tim Tucker's if_wd driver for the wd8003,
42: * insight on the ne2000 gained from Robert Clements PC/FTP driver.
1.1.1.4 ! root 43: *
! 44: * Corrected for NE1000 by Andrew A. Chernov
1.1 root 45: */
46:
47: #include "ne.h"
48: #if NNE > 0
49:
50: #include "param.h"
51: #include "systm.h"
52: #include "mbuf.h"
53: #include "buf.h"
54: #include "protosw.h"
55: #include "socket.h"
56: #include "ioctl.h"
57: #include "errno.h"
58: #include "syslog.h"
59:
60: #include "net/if.h"
61: #include "net/netisr.h"
62: #include "net/route.h"
63:
64: #ifdef INET
65: #include "netinet/in.h"
66: #include "netinet/in_systm.h"
67: #include "netinet/in_var.h"
68: #include "netinet/ip.h"
69: #include "netinet/if_ether.h"
70: #endif
71:
72: #ifdef NS
73: #include "netns/ns.h"
74: #include "netns/ns_if.h"
75: #endif
76:
1.1.1.4 ! root 77: #include "bpfilter.h"
! 78: #if NBPFILTER > 0
! 79: #include "sys/select.h"
! 80: #include "net/bpf.h"
! 81: #include "net/bpfdesc.h"
! 82: #endif
! 83:
1.1 root 84: #include "i386/isa/isa_device.h"
85: #include "i386/isa/if_nereg.h"
86: #include "i386/isa/icu.h"
87:
88: int neprobe(), neattach(), neintr();
89: int nestart(),neinit(), ether_output(), neioctl();
90:
91: struct isa_driver nedriver = {
92: neprobe, neattach, "ne",
93: };
94:
95: struct mbuf *neget();
96:
97: #define ETHER_MIN_LEN 64
98: #define ETHER_MAX_LEN 1536
99:
100: /*
101: * Ethernet software status per interface.
102: *
103: * Each interface is referenced by a network interface structure,
104: * ns_if, which the routing code uses to locate the interface.
105: * This structure contains the output queue for the interface, its address, ...
106: */
107: struct ne_softc {
108: struct arpcom ns_ac; /* Ethernet common part */
109: #define ns_if ns_ac.ac_if /* network-visible interface */
1.1.1.3 root 110: #define ns_addrp ns_ac.ac_enaddr /* hardware Ethernet address */
1.1 root 111: int ns_flags;
112: #define DSF_LOCK 1 /* block re-entering enstart */
113: int ns_oactive ;
114: int ns_mask ;
115: int ns_ba; /* byte addr in buffer ram of inc pkt */
116: int ns_cur; /* current page being filled */
117: struct prhdr ns_ph; /* hardware header of incoming packet*/
118: struct ether_header ns_eh; /* header of incoming packet */
119: u_char ns_pb[2048 /*ETHERMTU+sizeof(long)*/];
1.1.1.2 root 120: short ns_txstart; /* transmitter buffer start */
1.1.1.4 ! root 121: u_short ns_rxend; /* recevier buffer end */
1.1.1.2 root 122: short ns_port; /* i/o port base */
123: short ns_mode; /* word/byte mode */
1.1.1.4 ! root 124: caddr_t ns_bpf; /* BPF frob */
1.1 root 125: } ne_softc[NNE] ;
126: #define ENBUFSIZE (sizeof(struct ether_header) + ETHERMTU + 2 + ETHER_MIN_LEN)
127:
1.1.1.2 root 128: #define PAT(n) (0xa55a + 37*(n))
1.1 root 129:
130: u_short boarddata[16];
131:
132: neprobe(dvp)
133: struct isa_device *dvp;
134: {
1.1.1.2 root 135: int val, i, s, sum, bytemode = 1, pat;
1.1 root 136: register struct ne_softc *ns = &ne_softc[0];
1.1.1.2 root 137: register nec;
1.1 root 138:
139: #ifdef lint
140: neintr(0);
141: #endif
142:
1.1.1.2 root 143: nec = ns->ns_port = dvp->id_iobase;
1.1 root 144: s = splimp();
145:
1.1.1.2 root 146: if (bytemode) {
147: /* Byte Transfers, Burst Mode Select, Fifo at 8 bytes */
148: ns->ns_mode = DSDC_BMS|DSDC_FT1;
149: ns->ns_txstart = TBUF8;
150: ns->ns_rxend = RBUFEND8;
151: } else {
152: word:
153: /* Word Transfers, Burst Mode Select, Fifo at 8 bytes */
154: ns->ns_mode = DSDC_WTS|DSDC_BMS|DSDC_FT1;
155: ns->ns_txstart = TBUF16;
156: ns->ns_rxend = RBUFEND16;
157: bytemode = 0;
158: }
159:
1.1 root 160: /* Reset the bastard */
1.1.1.2 root 161: val = inb(nec + ne_reset);
162: DELAY(200);
163: outb(nec + ne_reset, val);
164: DELAY(200);
1.1 root 165:
1.1.1.2 root 166: outb(nec + ds_cmd, DSCM_STOP|DSCM_NODMA);
1.1 root 167:
1.1.1.2 root 168: i = 10000;
169: while ((inb(nec + ds0_isr) & DSIS_RESET) == 0 && i-- > 0);
1.1 root 170: if (i < 0) return (0);
171:
1.1.1.2 root 172: outb(nec + ds0_isr, 0xff);
173: outb(nec + ds0_dcr, ns->ns_mode);
174: outb(nec + ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP);
175: DELAY(1000);
1.1 root 176:
177: /* Check cmd reg and fail if not right */
1.1.1.2 root 178: if ((i = inb(nec + ds_cmd)) != (DSCM_NODMA|DSCM_PG0|DSCM_STOP))
1.1 root 179: return(0);
180:
1.1.1.2 root 181: outb(nec + ds0_tcr, 0);
182: outb(nec + ds0_rcr, DSRC_MON);
183: outb(nec + ds0_pstart, (ns->ns_txstart+PKTSZ)/DS_PGSIZE);
184: outb(nec + ds0_pstop, ns->ns_rxend/DS_PGSIZE);
185: outb(nec + ds0_bnry, ns->ns_rxend/DS_PGSIZE);
186: outb(nec + ds0_imr, 0);
187: outb(nec + ds0_isr, 0);
188: outb(nec + ds_cmd, DSCM_NODMA|DSCM_PG1|DSCM_STOP);
189: outb(nec + ds1_curr, (ns->ns_txstart+PKTSZ)/DS_PGSIZE);
190: outb(nec + ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP);
191:
1.1 root 192:
193: #ifdef NEDEBUG
194: #define RCON 37
1.1.1.2 root 195: { int i, rom;
1.1 root 196:
197: rom=1;
198: printf("ne ram ");
199:
200: for (i = 0; i < 0xfff0; i+=4) {
201: pat = PAT(i);
1.1.1.2 root 202: neput(ns, &pat,i,4);
203: nefetch(ns, &pat,i,4);
1.1 root 204: if (pat == PAT(i)) {
205: if (rom) {
206: rom=0;
207: printf(" %x", i);
208: }
209: } else {
210: if (!rom) {
211: rom=1;
212: printf("..%x ", i);
213: }
214: }
215: pat=0;
1.1.1.2 root 216: neput(ns, &pat,i,4);
1.1 root 217: }
218: printf("\n");
219: }
220: #endif
221:
1.1.1.2 root 222: /*
223: * <groan> detect difference between units
224: * solely by where the RAM is decoded.
225: */
226: pat = PAT(0);
227: neput(ns, &pat, ns->ns_txstart, 4);
228: nefetch(ns, &pat, ns->ns_txstart, 4);
229: if (pat != PAT(0)) {
230: if (bytemode)
231: goto word;
232: else return (0);
233: }
234:
235:
1.1 root 236: /* Extract board address */
1.1.1.2 root 237: nefetch (ns, (caddr_t)boarddata, 0, sizeof(boarddata));
238:
239: for(i=0; i < 6; i++)
1.1.1.3 root 240: ns->ns_addrp[i] = boarddata[i];
1.1 root 241: splx(s);
1.1.1.4 ! root 242: return (16);
1.1 root 243: }
244:
245: /*
246: * Fetch from onboard ROM/RAM
247: */
1.1.1.2 root 248: nefetch (ns, up, ad, len) struct ne_softc *ns; caddr_t up; {
1.1 root 249: u_char cmd;
1.1.1.2 root 250: register nec = ns->ns_port;
251: int counter = 100000;
1.1 root 252:
1.1.1.2 root 253: cmd = inb (nec + ds_cmd);
254: outb (nec + ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START);
1.1 root 255:
256: /* Setup remote dma */
1.1.1.2 root 257: outb (nec + ds0_isr, DSIS_RDC);
258:
259: if ((ns->ns_mode & DSDC_WTS) && len&1)
260: len++; /* roundup to words */
261:
1.1 root 262: outb (nec+ds0_rbcr0, len);
263: outb (nec+ds0_rbcr1, len>>8);
264: outb (nec+ds0_rsar0, ad);
265: outb (nec+ds0_rsar1, ad>>8);
266:
267: /* Execute & extract from card */
268: outb (nec+ds_cmd, DSCM_RREAD|DSCM_PG0|DSCM_START);
1.1.1.2 root 269:
270: if (ns->ns_mode & DSDC_WTS)
271: insw (nec+ne_data, up, len/2);
272: else
273: insb (nec+ne_data, up, len);
1.1 root 274:
275: /* Wait till done, then shutdown feature */
1.1.1.2 root 276: while ((inb (nec+ds0_isr) & DSIS_RDC) == 0 && counter-- > 0)
277: ;
1.1 root 278: outb (nec+ds0_isr, DSIS_RDC);
279: outb (nec+ds_cmd, cmd);
280: }
281:
282: /*
283: * Put to onboard RAM
284: */
1.1.1.2 root 285: neput (ns, up, ad, len) struct ne_softc *ns; caddr_t up; {
1.1 root 286: u_char cmd;
1.1.1.2 root 287: register nec = ns->ns_port;
288: int counter = 100000;
1.1 root 289:
290: cmd = inb(nec+ds_cmd);
291: outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START);
292:
293: /* Setup for remote dma */
294: outb (nec+ds0_isr, DSIS_RDC);
1.1.1.2 root 295:
296: if ((ns->ns_mode & DSDC_WTS) && len&1)
297: len++; /* roundup to words */
298:
1.1 root 299: outb (nec+ds0_rbcr0, len);
300: outb (nec+ds0_rbcr1, len>>8);
301: outb (nec+ds0_rsar0, ad);
302: outb (nec+ds0_rsar1, ad>>8);
303:
304: /* Execute & stuff to card */
305: outb (nec+ds_cmd, DSCM_RWRITE|DSCM_PG0|DSCM_START);
1.1.1.2 root 306: if (ns->ns_mode & DSDC_WTS)
307: outsw (nec+ne_data, up, len/2);
308: else
309: outsb (nec+ne_data, up, len);
1.1 root 310:
311: /* Wait till done, then shutdown feature */
1.1.1.2 root 312: while ((inb (nec+ds0_isr) & DSIS_RDC) == 0 && counter-- > 0)
313: ;
1.1 root 314: outb (nec+ds0_isr, DSIS_RDC);
315: outb (nec+ds_cmd, cmd);
316: }
317:
318: /*
319: * Reset of interface.
320: */
321: nereset(unit, uban)
322: int unit, uban;
323: {
324: if (unit >= NNE)
325: return;
326: printf("ne%d: reset\n", unit);
327: ne_softc[unit].ns_flags &= ~DSF_LOCK;
328: neinit(unit);
329: }
330:
331: /*
332: * Interface exists: make available by filling in network interface
333: * record. System will initialize the interface when it is ready
334: * to accept packets. We get the ethernet address here.
335: */
336: neattach(dvp)
337: struct isa_device *dvp;
338: {
339: int unit = dvp->id_unit;
340: register struct ne_softc *ns = &ne_softc[unit];
341: register struct ifnet *ifp = &ns->ns_if;
342:
343: ifp->if_unit = unit;
344: ifp->if_name = nedriver.name ;
345: ifp->if_mtu = ETHERMTU;
1.1.1.4 ! root 346: printf ("ne%d: ne%s ethernet address %s\n", unit,
! 347: (ns->ns_mode & DSDC_WTS) ? "2000" : "1000",
! 348: ether_sprintf(ns->ns_addrp));
1.1 root 349: ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS;
350: ifp->if_init = neinit;
351: ifp->if_output = ether_output;
352: ifp->if_start = nestart;
353: ifp->if_ioctl = neioctl;
354: ifp->if_reset = nereset;
355: ifp->if_watchdog = 0;
356: if_attach(ifp);
1.1.1.4 ! root 357:
! 358: #if NBPFILTER > 0
! 359: bpfattach(&ns->ns_bpf, ifp, DLT_EN10MB,
! 360: sizeof(struct ether_header));
! 361: #endif
1.1 root 362: }
363:
364: /*
365: * Initialization of interface; set up initialization block
366: * and transmit/receive descriptor rings.
367: */
368: neinit(unit)
369: int unit;
370: {
371: register struct ne_softc *ns = &ne_softc[unit];
372: struct ifnet *ifp = &ns->ns_if;
373: int s;
1.1.1.2 root 374: int i; char *cp;
375: register nec = ns->ns_port;
1.1 root 376:
377: if (ifp->if_addrlist == (struct ifaddr *)0) return;
378: if (ifp->if_flags & IFF_RUNNING) return;
379:
380: s = splimp();
381:
382: /* set physical address on ethernet */
383: outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG1|DSCM_STOP);
1.1.1.3 root 384: for (i=0 ; i < 6 ; i++) outb(nec+ds1_par0+i,ns->ns_addrp[i]);
1.1 root 385:
386: /* clr logical address hash filter for now */
387: for (i=0 ; i < 8 ; i++) outb(nec+ds1_mar0+i,0xff);
388:
389: /* init regs */
390: outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP);
391: outb (nec+ds0_rbcr0, 0);
392: outb (nec+ds0_rbcr1, 0);
393: outb (nec+ds0_imr, 0);
394: outb (nec+ds0_isr, 0xff);
395:
1.1.1.2 root 396: /* Word Transfer select, Burst Mode Select, Fifo at 8 bytes */
397: outb(nec+ds0_dcr, ns->ns_mode);
398:
1.1 root 399: outb(nec+ds0_tcr, 0);
400: outb (nec+ds0_rcr, DSRC_MON);
401: outb (nec+ds0_tpsr, 0);
1.1.1.2 root 402: outb(nec+ds0_pstart, (ns->ns_txstart+PKTSZ)/DS_PGSIZE);
403: outb(nec+ds0_pstop, ns->ns_rxend/DS_PGSIZE);
404: outb(nec+ds0_bnry, (ns->ns_txstart+PKTSZ)/DS_PGSIZE);
1.1 root 405: outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG1|DSCM_STOP);
1.1.1.2 root 406: outb(nec+ds1_curr, (ns->ns_txstart+PKTSZ)/DS_PGSIZE);
407: ns->ns_cur = (ns->ns_txstart+PKTSZ)/DS_PGSIZE;
1.1 root 408: outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START);
1.1.1.4 ! root 409: #if NBPFILTER > 0
! 410: if (ns->ns_if.if_flags & IFF_PROMISC)
! 411: outb (nec+ds0_rcr, DSRC_AB | DSRC_PRO | DSRC_AR | DSRC_SEP);
! 412: else
! 413: #endif
! 414: outb (nec+ds0_rcr, DSRC_AB);
1.1.1.2 root 415: outb(nec+ds0_dcr, ns->ns_mode);
1.1 root 416: outb (nec+ds0_imr, 0xff);
417:
418: ns->ns_if.if_flags |= IFF_RUNNING;
1.1.1.2 root 419: ns->ns_flags &= ~DSF_LOCK;
1.1 root 420: ns->ns_oactive = 0; ns->ns_mask = ~0;
421: nestart(ifp);
422: splx(s);
423: }
424:
425: /*
426: * Setup output on interface.
427: * Get another datagram to send off of the interface queue,
428: * and map it to the interface before starting the output.
429: * called only at splimp or interrupt level.
1.1.1.4 ! root 430: * XXX: Needs BPF hook.
1.1 root 431: */
432: nestart(ifp)
433: struct ifnet *ifp;
434: {
435: register struct ne_softc *ns = &ne_softc[ifp->if_unit];
436: struct mbuf *m0, *m;
1.1.1.4 ! root 437: int len, i, total,t;
1.1.1.2 root 438: register nec = ns->ns_port;
1.1.1.4 ! root 439: u_char cmd;
! 440: u_short word;
! 441: int counter;
! 442:
! 443: if (ns->ns_flags & DSF_LOCK)
! 444: return;
! 445:
! 446: if ((ns->ns_if.if_flags & IFF_RUNNING) == 0)
! 447: return;
1.1 root 448:
449: /*
450: * The DS8390 has only one transmit buffer, if it is busy we
451: * must wait until the transmit interrupt completes.
452: */
453: outb(nec+ds_cmd,DSCM_NODMA|DSCM_START);
454:
455: if (inb(nec+ds_cmd) & DSCM_TRANS)
456: return;
457:
458: IF_DEQUEUE(&ns->ns_if.if_snd, m);
459:
460: if (m == 0)
461: return;
462:
1.1.1.4 ! root 463: ns->ns_flags |= DSF_LOCK; /* prevent entering nestart */
! 464:
1.1 root 465: /*
466: * Copy the mbuf chain into the transmit buffer
467: */
468:
1.1.1.4 ! root 469: len = i = 0;
1.1 root 470: t = 0;
471: for (m0 = m; m != 0; m = m->m_next)
472: t += m->m_len;
473:
1.1.1.4 ! root 474: /* next code derived from neput() */
1.1 root 475:
1.1.1.4 ! root 476: if ((ns->ns_mode & DSDC_WTS) && t&1)
! 477: t++; /* roundup to words */
! 478:
! 479: cmd = inb(nec+ds_cmd);
! 480: outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START);
! 481:
! 482: /* Setup for remote dma */
! 483: outb (nec+ds0_isr, DSIS_RDC);
! 484:
! 485: outb (nec+ds0_rbcr0, t);
! 486: outb (nec+ds0_rbcr1, t>>8);
! 487: outb (nec+ds0_rsar0, ns->ns_txstart);
! 488: outb (nec+ds0_rsar1, ns->ns_txstart>>8);
! 489:
! 490: /* Execute & stuff to card */
! 491: outb (nec+ds_cmd, DSCM_RWRITE|DSCM_PG0|DSCM_START);
! 492:
1.1 root 493: m = m0;
1.1.1.4 ! root 494: total = t;
! 495: if (ns->ns_mode & DSDC_WTS) { /* Word Mode */
! 496: while (m != 0) {
! 497: if (m->m_len > 1)
! 498: outsw(nec+ne_data, m->m_data, m->m_len / 2);
! 499: if (m->m_len & 1) {
! 500: word = (u_char) *(mtod(m, caddr_t) + m->m_len - 1);
! 501: if ((m = m->m_next) != 0) {
! 502: word |= *mtod(m, caddr_t) << 8;
! 503: m->m_len--;
! 504: m->m_data++;
! 505: }
! 506: outsw(nec+ne_data, (caddr_t)&word, 1);
! 507: } else
! 508: m = m->m_next;
! 509: }
! 510: }
! 511: else { /* Byte Mode */
! 512: while (m != 0) {
! 513: if (m->m_len > 0)
! 514: outsb(nec+ne_data, mtod(m, caddr_t), m->m_len);
! 515: m = m->m_next;
1.1 root 516: }
517: }
518:
1.1.1.4 ! root 519: m_freem(m0);
! 520:
! 521: counter = 100000;
! 522: /* Wait till done, then shutdown feature */
! 523: while ((inb (nec+ds0_isr) & DSIS_RDC) == 0 && counter-- > 0)
! 524: ;
! 525: outb (nec+ds0_isr, DSIS_RDC);
! 526: outb (nec+ds_cmd, cmd);
! 527:
1.1 root 528: /*
529: * Init transmit length registers, and set transmit start flag.
530: */
531:
532: len = total;
533: if (len < ETHER_MIN_LEN) len = ETHER_MIN_LEN;
534: outb(nec+ds0_tbcr0,len&0xff);
535: outb(nec+ds0_tbcr1,(len>>8)&0xff);
1.1.1.2 root 536: outb(nec+ds0_tpsr, ns->ns_txstart/DS_PGSIZE);
1.1 root 537: outb(nec+ds_cmd, DSCM_TRANS|DSCM_NODMA|DSCM_START);
538: }
539:
540: /* buffer successor/predecessor in ring? */
1.1.1.2 root 541: #define succ(n) (((n)+1 >= ns->ns_rxend/DS_PGSIZE) ? (ns->ns_txstart+PKTSZ)/DS_PGSIZE : (n)+1)
542: #define pred(n) (((n)-1 < (ns->ns_txstart+PKTSZ)/DS_PGSIZE) ? ns->ns_rxend/DS_PGSIZE-1 : (n)-1)
1.1 root 543:
544: /*
545: * Controller interrupt.
546: */
547: neintr(unit)
548: {
549: register struct ne_softc *ns = &ne_softc[unit];
550: u_char cmd,isr;
1.1.1.2 root 551: register nec = ns->ns_port;
1.1 root 552:
553: /* Save cmd, clear interrupt */
554: cmd = inb (nec+ds_cmd);
555: loop:
556: isr = inb (nec+ds0_isr);
557: outb(nec+ds_cmd,DSCM_NODMA|DSCM_START);
558: outb(nec+ds0_isr, isr);
559:
560: /* Receiver error */
561: if (isr & DSIS_RXE) {
562: /* need to read these registers to clear status */
563: (void) inb(nec+ ds0_rsr);
564: (void) inb(nec+ 0xD);
565: (void) inb(nec + 0xE);
566: (void) inb(nec + 0xF);
567: ns->ns_if.if_ierrors++;
568: }
569:
570: /* We received something; rummage thru tiny ring buffer */
571: if (isr & (DSIS_RX|DSIS_RXE|DSIS_ROVRN)) {
572: u_char pend,lastfree;
573:
574: outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG1);
575: pend = inb(nec+ds1_curr);
576: outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG0);
577: lastfree = inb(nec+ds0_bnry);
578:
579: /* Have we wrapped? */
1.1.1.2 root 580: if (lastfree >= ns->ns_rxend/DS_PGSIZE)
581: lastfree = (ns->ns_txstart+PKTSZ)/DS_PGSIZE;
1.1 root 582: if (pend < lastfree && ns->ns_cur < pend)
583: lastfree = ns->ns_cur;
584: else if (ns->ns_cur > lastfree)
585: lastfree = ns->ns_cur;
586:
587: /* Something in the buffer? */
588: while (pend != lastfree) {
589: u_char nxt;
590:
591: /* Extract header from microcephalic board */
1.1.1.2 root 592: nefetch(ns, &ns->ns_ph,lastfree*DS_PGSIZE,
1.1 root 593: sizeof(ns->ns_ph));
594: ns->ns_ba = lastfree*DS_PGSIZE+sizeof(ns->ns_ph);
595:
596: /* Incipient paranoia */
597: if (ns->ns_ph.pr_status == DSRS_RPC ||
598: /* for dequna's */
599: ns->ns_ph.pr_status == 0x21)
600: nerecv (ns);
601: #ifdef NEDEBUG
602: else {
603: printf("cur %x pnd %x lfr %x ",
604: ns->ns_cur, pend, lastfree);
605: printf("nxt %x len %x ", ns->ns_ph.pr_nxtpg,
606: (ns->ns_ph.pr_sz1<<8)+ ns->ns_ph.pr_sz0);
607: printf("Bogus Sts %x\n", ns->ns_ph.pr_status);
608: }
609: #endif
610:
611: nxt = ns->ns_ph.pr_nxtpg ;
612:
613: /* Sanity check */
1.1.1.2 root 614: if ( nxt >= (ns->ns_txstart+PKTSZ)/DS_PGSIZE
615: && nxt <= ns->ns_rxend/DS_PGSIZE && nxt <= pend)
1.1 root 616: ns->ns_cur = nxt;
617: else ns->ns_cur = nxt = pend;
618:
619: /* Set the boundaries */
620: lastfree = nxt;
621: outb(nec+ds0_bnry, pred(nxt));
622: outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG1);
623: pend = inb(nec+ds1_curr);
624: outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG0);
625: }
626: outb(nec+ds_cmd, DSCM_START|DSCM_NODMA);
627: }
628:
629: /* Transmit error */
630: if (isr & DSIS_TXE) {
631: ns->ns_flags &= ~DSF_LOCK;
632: /* Need to read these registers to clear status */
633: ns->ns_if.if_collisions += inb(nec+ds0_tbcr0);
634: ns->ns_if.if_oerrors++;
635: }
636:
637: /* Packet Transmitted */
638: if (isr & DSIS_TX) {
639: ns->ns_flags &= ~DSF_LOCK;
640: ++ns->ns_if.if_opackets;
641: ns->ns_if.if_collisions += inb(nec+ds0_tbcr0);
642: }
643:
644: /* Receiver ovverun? */
645: if (isr & DSIS_ROVRN) {
646: log(LOG_ERR, "ne%d: error: isr %x\n", ns-ne_softc, isr
647: /*, DSIS_BITS*/);
648: outb(nec+ds0_rbcr0, 0);
649: outb(nec+ds0_rbcr1, 0);
650: outb(nec+ds0_tcr, DSTC_LB0);
651: outb(nec+ds0_rcr, DSRC_MON);
652: outb(nec+ds_cmd, DSCM_START|DSCM_NODMA);
653: outb(nec+ds0_rcr, DSRC_AB);
654: outb(nec+ds0_tcr, 0);
655: }
656:
657: /* Any more to send? */
658: outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START);
659: nestart(&ns->ns_if);
660: outb (nec+ds_cmd, cmd);
661: outb (nec+ds0_imr, 0xff);
662:
663: /* Still more to do? */
664: isr = inb (nec+ds0_isr);
665: if(isr) goto loop;
666: }
667:
668: /*
669: * Ethernet interface receiver interface.
670: * If input error just drop packet.
671: * Otherwise examine packet to determine type. If can't determine length
672: * from type, then have to drop packet. Othewise decapsulate
673: * packet based on type and pass to type specific higher-level
674: * input routine.
675: */
676: nerecv(ns)
677: register struct ne_softc *ns;
678: {
679: int len,i;
680:
681: ns->ns_if.if_ipackets++;
682: len = ns->ns_ph.pr_sz0 + (ns->ns_ph.pr_sz1<<8);
683: if(len < ETHER_MIN_LEN || len > ETHER_MAX_LEN)
684: return;
685:
686: /* this need not be so torturous - one/two bcopys at most into mbufs */
1.1.1.2 root 687: nefetch(ns, ns->ns_pb, ns->ns_ba, min(len,DS_PGSIZE-sizeof(ns->ns_ph)));
1.1 root 688: if (len > DS_PGSIZE-sizeof(ns->ns_ph)) {
689: int l = len - (DS_PGSIZE-sizeof(ns->ns_ph)), b ;
690: u_char *p = ns->ns_pb + (DS_PGSIZE-sizeof(ns->ns_ph));
691:
1.1.1.4 ! root 692: if (++ns->ns_cur >= ns->ns_rxend/DS_PGSIZE)
! 693: ns->ns_cur = (ns->ns_txstart+PKTSZ)/DS_PGSIZE;
1.1 root 694: b = ns->ns_cur*DS_PGSIZE;
695:
696: while (l >= DS_PGSIZE) {
1.1.1.2 root 697: nefetch(ns, p, b, DS_PGSIZE);
1.1 root 698: p += DS_PGSIZE; l -= DS_PGSIZE;
1.1.1.4 ! root 699: if (++ns->ns_cur >= ns->ns_rxend/DS_PGSIZE)
! 700: ns->ns_cur = (ns->ns_txstart+PKTSZ)/DS_PGSIZE;
1.1 root 701: b = ns->ns_cur*DS_PGSIZE;
702: }
703: if (l > 0)
1.1.1.2 root 704: nefetch(ns, p, b, l);
1.1 root 705: }
706: /* don't forget checksum! */
1.1.1.4 ! root 707: len -= sizeof(long) + sizeof(struct ether_header);
1.1 root 708:
709: neread(ns,(caddr_t)(ns->ns_pb), len);
710: }
711:
712: /*
713: * Pass a packet to the higher levels.
714: * We deal with the trailer protocol here.
715: */
716: neread(ns, buf, len)
717: register struct ne_softc *ns;
718: char *buf;
719: int len;
720: {
721: register struct ether_header *eh;
722: struct mbuf *m;
723: int off, resid;
724: register struct ifqueue *inq;
1.1.1.4 ! root 725: u_short etype;
1.1 root 726:
727: /*
728: * Deal with trailer protocol: if type is trailer type
729: * get true type from first 16-bit word past data.
730: * Remember that type was trailer by setting off.
731: */
732: eh = (struct ether_header *)buf;
1.1.1.4 ! root 733: etype = ntohs((u_short)eh->ether_type);
1.1 root 734: #define nedataaddr(eh, off, type) ((type)(((caddr_t)((eh)+1)+(off))))
1.1.1.4 ! root 735: if (etype >= ETHERTYPE_TRAIL &&
! 736: etype < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
! 737: off = (etype - ETHERTYPE_TRAIL) * 512;
1.1 root 738: if (off >= ETHERMTU) return; /* sanity */
1.1.1.4 ! root 739: eh->ether_type = *nedataaddr(eh, off, u_short *);
! 740: resid = ntohs(*nedataaddr(eh, off+2, u_short *));
1.1 root 741: if (off + resid > len) return; /* sanity */
742: len = off + resid;
743: } else off = 0;
744:
1.1.1.4 ! root 745: if (len <= 0) return;
1.1 root 746:
747: /*
748: * Pull packet off interface. Off is nonzero if packet
749: * has trailing header; neget will then force this header
750: * information to be at the front, but we still have to drop
751: * the type and length which are at the front of any trailer data.
752: */
753: m = neget(buf, len, off, &ns->ns_if);
754: if (m == 0) return;
755:
1.1.1.4 ! root 756: #if NBPFILTER > 0
! 757: /*
! 758: * Check if there's a bpf filter listening on this interface.
! 759: * If so, hand off the raw packet to bpf.
! 760: */
! 761: if (ns->ns_bpf) {
! 762: bpf_mtap(ns->ns_bpf, m);
! 763: }
! 764:
! 765: /*
! 766: * Note that the interface cannot be in promiscuous mode if
! 767: * there are no bpf listeners. And if we are in promiscuous
! 768: * mode, we have to check if this packet is really ours.
! 769: *
! 770: * XXX This test does not support multicasts.
! 771: */
! 772: if ((ns->ns_if.if_flags & IFF_PROMISC) &&
! 773: bcmp(eh->ether_dhost, ns->ns_addrp,
! 774: sizeof(eh->ether_dhost)) != 0 &&
! 775: bcmp(eh->ether_dhost, etherbroadcastaddr,
! 776: sizeof(eh->ether_dhost)) != 0) {
! 777:
! 778: m_freem(m);
! 779: return;
! 780: }
! 781: #endif
! 782:
! 783: /*
! 784: * Drop packet header and save fixed up ether_type.
! 785: */
! 786: #if NBPFILTER > 0
! 787: m_adj(m, sizeof(struct ether_header));
! 788: #endif
! 789: eh->ether_type = ntohs(eh->ether_type);
! 790:
1.1 root 791: ether_input(&ns->ns_if, eh, m);
792: }
793:
794: /*
795: * Supporting routines
796: */
797:
798: /*
799: * Pull read data off a interface.
800: * Len is length of data, with local net header stripped.
801: * Off is non-zero if a trailer protocol was used, and
802: * gives the offset of the trailer information.
803: * We copy the trailer information and then all the normal
804: * data into mbufs. When full cluster sized units are present
805: * we copy into clusters.
806: */
807: struct mbuf *
1.1.1.4 ! root 808: neget(buf, totlen, off, ifp)
1.1 root 809: caddr_t buf;
1.1.1.4 ! root 810: int totlen, off;
1.1 root 811: struct ifnet *ifp;
812: {
1.1.1.4 ! root 813: struct mbuf *top, *last, *m;
! 814: int len;
! 815: register caddr_t cp;
! 816:
! 817: MGETHDR(m, M_DONTWAIT, MT_DATA);
! 818: if (m == 0)
! 819: return (0);
! 820: top = last = m;
! 821:
! 822: #if NBPFILTER > 0
! 823: /*
! 824: * Copy the ethernet header first.
! 825: * XXX: This assumes that ether_header fits inside the mbuf.
! 826: */
! 827: /*
! 828: * XXX: This line is to avoid `nfs_rcv odd length!' spewage.
! 829: */
! 830: m->m_data += (MHLEN - sizeof(struct ether_header)) & 3;
! 831: bcopy(buf, mtod(m, caddr_t), sizeof(struct ether_header));
! 832: m->m_len = sizeof(struct ether_header);
! 833: m->m_pkthdr.len = totlen + sizeof(struct ether_header);
! 834: #else
! 835: m->m_len = 0;
! 836: m->m_pkthdr.len = totlen;
! 837: #endif
! 838: m->m_pkthdr.rcvif = ifp;
1.1 root 839:
840: buf += sizeof(struct ether_header);
841: cp = buf;
842:
843: if (off) {
844: cp += off + 2 * sizeof(u_short);
1.1.1.4 ! root 845: totlen -= off + 2 * sizeof(u_short);
1.1 root 846: }
847:
1.1.1.4 ! root 848: copy:
1.1 root 849: while (totlen > 0) {
1.1.1.4 ! root 850: len = min(totlen, M_TRAILINGSPACE(m));
! 851: if (!len) {
1.1 root 852: MGET(m, M_DONTWAIT, MT_DATA);
853: if (m == 0) {
854: m_freem(top);
855: return (0);
856: }
1.1.1.4 ! root 857: if (totlen >= MINCLSIZE) {
! 858: MCLGET(m, M_DONTWAIT);
! 859: if (m == 0) {
! 860: m_freem(top);
! 861: return (0);
! 862: }
! 863: }
! 864: m->m_len = 0;
! 865: last->m_next = m;
! 866: last = m;
! 867: len = min(totlen, M_TRAILINGSPACE(m));
1.1 root 868: }
1.1.1.4 ! root 869:
! 870: bcopy(cp, mtod(m, caddr_t) + m->m_len, len);
! 871: m->m_len += len;
1.1 root 872: totlen -= len;
1.1.1.4 ! root 873: cp += len;
! 874: }
! 875:
! 876: if (off) {
! 877: totlen = off;
! 878: cp = buf;
! 879: off = 0;
! 880: goto copy;
1.1 root 881: }
1.1.1.4 ! root 882:
1.1 root 883: return (top);
884: }
885:
886: /*
887: * Process an ioctl request.
888: */
889: neioctl(ifp, cmd, data)
890: register struct ifnet *ifp;
891: int cmd;
892: caddr_t data;
893: {
894: register struct ifaddr *ifa = (struct ifaddr *)data;
895: struct ne_softc *ns = &ne_softc[ifp->if_unit];
896: struct ifreq *ifr = (struct ifreq *)data;
897: int s = splimp(), error = 0;
898:
899:
900: switch (cmd) {
901:
902: case SIOCSIFADDR:
903: ifp->if_flags |= IFF_UP;
904:
905: switch (ifa->ifa_addr->sa_family) {
906: #ifdef INET
907: case AF_INET:
908: neinit(ifp->if_unit); /* before arpwhohas */
909: ((struct arpcom *)ifp)->ac_ipaddr =
910: IA_SIN(ifa)->sin_addr;
911: arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
912: break;
913: #endif
914: #ifdef NS
915: case AF_NS:
916: {
917: register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
918:
919: if (ns_nullhost(*ina))
1.1.1.3 root 920: ina->x_host = *(union ns_host *)(ns->ns_addrp);
1.1 root 921: else {
922: /*
923: * The manual says we can't change the address
924: * while the receiver is armed,
925: * so reset everything
926: */
927: ifp->if_flags &= ~IFF_RUNNING;
928: bcopy((caddr_t)ina->x_host.c_host,
1.1.1.3 root 929: (caddr_t)ns->ns_addrp, sizeof(ns->ns_addrp));
1.1 root 930: }
931: neinit(ifp->if_unit); /* does ne_setaddr() */
932: break;
933: }
934: #endif
935: default:
936: neinit(ifp->if_unit);
937: break;
938: }
939: break;
940:
941: case SIOCSIFFLAGS:
942: if ((ifp->if_flags & IFF_UP) == 0 &&
943: ifp->if_flags & IFF_RUNNING) {
944: ifp->if_flags &= ~IFF_RUNNING;
1.1.1.2 root 945: outb(ns->ns_port + ds_cmd, DSCM_STOP|DSCM_NODMA);
1.1 root 946: } else if (ifp->if_flags & IFF_UP &&
1.1.1.4 ! root 947: (ifp->if_flags & IFF_RUNNING) == 0) {
1.1 root 948: neinit(ifp->if_unit);
1.1.1.4 ! root 949: break;
! 950: }
! 951: #if NBPFILTER > 0
! 952: if (ns->ns_if.if_flags & IFF_PROMISC)
! 953: outb (ns->ns_port+ds0_rcr, DSRC_AB | DSRC_PRO |
! 954: DSRC_AR | DSRC_SEP);
! 955: else
! 956: #endif
! 957: outb (ns->ns_port+ds0_rcr, DSRC_AB);
1.1 root 958: break;
959:
960: #ifdef notdef
961: case SIOCGHWADDR:
962: bcopy((caddr_t)ns->ns_addr, (caddr_t) &ifr->ifr_data,
963: sizeof(ns->ns_addr));
964: break;
965: #endif
966:
967: default:
968: error = EINVAL;
969: }
970: splx(s);
971: return (error);
972: }
973: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.