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