xref: /csrg-svn/sys/i386/isa/if_ne.c (revision 45537)
1 #include "ne.h"
2 #if NNE > 0
3 /*
4  * NE2000 Ethernet driver
5  * Copyright (C) 1990 W. Jolitz
6  * @(#)if_ne.c	1.1 (Berkeley) 11/08/90
7  *
8  * Parts inspired from Tim Tucker's if_wd driver for the wd8003,
9  * insight on the ne2000 gained from Robert Clements PC/FTP driver.
10  */
11 
12 #include "param.h"
13 #include "systm.h"
14 #include "mbuf.h"
15 #include "buf.h"
16 #include "protosw.h"
17 #include "socket.h"
18 #include "ioctl.h"
19 #include "errno.h"
20 #include "syslog.h"
21 
22 #include "../net/if.h"
23 #include "../net/netisr.h"
24 #include "../net/route.h"
25 
26 #ifdef INET
27 #include "../netinet/in.h"
28 #include "../netinet/in_systm.h"
29 #include "../netinet/in_var.h"
30 #include "../netinet/ip.h"
31 #include "../netinet/if_ether.h"
32 #endif
33 
34 #ifdef NS
35 #include "../netns/ns.h"
36 #include "../netns/ns_if.h"
37 #endif
38 
39 #include "../machine/device.h"
40 #include "if_nereg.h"
41 #include "icu.h"
42 
43 int	neprobe(), neattach(), neintr();
44 int	neinit(), neoutput(), neioctl();
45 
46 struct	driver nedriver = {
47 	neprobe, neattach, "ne",
48 };
49 
50 u_short	neaddr[NNE] = {
51 	0x360
52 };
53 
54 struct	mbuf *neget();
55 
56 /*
57  * Ethernet software status per interface.
58  *
59  * Each interface is referenced by a network interface structure,
60  * ns_if, which the routing code uses to locate the interface.
61  * This structure contains the output queue for the interface, its address, ...
62  */
63 struct	ne_softc {
64 	struct	arpcom ns_ac;		/* Ethernet common part */
65 #define	ns_if	ns_ac.ac_if		/* network-visible interface */
66 #define	ns_addr	ns_ac.ac_enaddr		/* hardware Ethernet address */
67 	int	ns_flags;
68 #define	DSF_LOCK	1		/* block re-entering enstart */
69 	int	ns_oactive ;
70 	int	ns_mask ;
71 	int	ns_ba;			/* byte addr in buffer ram of inc pkt */
72 	int	ns_cur;			/* current page being filled */
73 	struct	prhdr	ns_ph;		/* hardware header of incoming packet*/
74 	struct	ether_header ns_eh;	/* header of incoming packet */
75 	u_char	ns_pb[2048 /*ETHERMTU+sizeof(long)*/];
76 } ne_softc[NNE] ;
77 #define	ENBUFSIZE	(sizeof(struct ether_header) + ETHERMTU + 2 + 64)
78 
79 int nec;
80 
81 u_short boarddata[16];
82 
83 neprobe(dvp)
84 	struct device *dvp;
85 {
86 	int val,i,s;
87 	register struct ne_softc *ns = &ne_softc[0];
88 
89 #ifdef lint
90 	neintr(0);
91 #endif
92 
93 	nec = dvp->ioa;
94 	s = splimp();
95 
96 	/* reset the bastard */
97 	val = inb(nec+ne_reset);
98 	DELAY(2000000);
99 	outb(nec+ne_reset,val);
100 
101 	outb(nec+ds_cmd, DSCM_STOP|DSCM_NODMA);
102 /* install timeout and return 0 if error */
103 	while ((inb(nec+ds0_isr)&DSIS_RESET) == 0);
104 	outb(nec+ds0_isr, 0xff);
105 
106 	/* Word Transfers, Burst Mode Select, Fifo at 8 bytes */
107 	outb(nec+ds0_dcr, DSDC_WTS|DSDC_BMS|DSDC_FT1);
108 
109 	outb(nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP);
110 /* check cmd reg and fail if not right */
111 	outb(nec+ds0_tcr, 0);
112 	outb(nec+ds0_rcr, DSRC_MON);
113 	outb(nec+ds0_pstart, RBUF/DS_PGSIZE);
114 	outb(nec+ds0_pstop, RBUFEND/DS_PGSIZE);
115 	outb(nec+ds0_bnry, RBUFEND/DS_PGSIZE);
116 	outb(nec+ds0_imr, 0);
117 	outb(nec+ds0_isr, 0);
118 	outb(nec+ds_cmd, DSCM_NODMA|DSCM_PG1|DSCM_STOP);
119 	outb(nec+ds1_curr, RBUF/DS_PGSIZE);
120 	outb(nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP);
121 	fetchrom (boarddata, 0, sizeof(boarddata));
122 /*{ int i,rom;
123 	rom=1;
124 printf("ne ram ");
125 	for (i = 0; i < 0xfff0; i+=4) {
126 		int pat;
127 		pat = 0xa55a+i*37;
128 		putram(&pat,i,4);
129 		fetchram(&pat,i,4);
130 		if (pat == 0xa55a+i*37) {
131 			if (rom) { rom=0; printf(" %x", i); }
132 		} else {
133 			if (!rom) { rom=1; printf("..%x ", i); }
134 		}
135 		pat=0;
136 		putram(&pat,i,4);
137 	}
138 printf("\n");
139 }*/
140 /* checksum data? */
141 	/* extract board address */
142 	for(i=0; i < 6; i++)  ns->ns_addr[i] = boarddata[i];
143 	INTREN(IRQ9);
144 	INTREN(0x2);
145 	splx(s);
146 	return (1);
147 }
148 
149 fetchrom (up, ad, len) u_short *up; {
150 	u_char cmd;
151 
152 	cmd = inb(nec+ds_cmd);
153 	outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP);
154 	outb (nec+ds0_isr, DSIS_RDC);
155 	outb (nec+ds0_rbcr0, len&0xff);
156 	outb (nec+ds0_rbcr1, (len>>8)&0xff);
157 	outb (nec+ds0_rsar0, ad&0xff);
158 	outb (nec+ds0_rsar1, (ad>>8)&0xff);
159 	outb (nec+ds_cmd, DSCM_RREAD|DSCM_PG0|DSCM_START);
160 	insw (nec+ne_data, up, len/2);
161 	while ((inb (nec+ds0_isr) & DSIS_RDC) == 0) nulldev();
162 	outb (nec+ds0_isr, DSIS_RDC);
163 	outb (nec+ds_cmd, cmd);
164 }
165 
166 fetchram (up, ad, len) caddr_t up; {
167 	u_char cmd;
168 
169 	cmd = inb(nec+ds_cmd);
170 	outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START);
171 	outb (nec+ds0_isr, DSIS_RDC);
172 	outb (nec+ds0_rbcr0, len&0xff);
173 	outb (nec+ds0_rbcr1, (len>>8)&0xff);
174 	outb (nec+ds0_rsar0, ad&0xff);
175 	outb (nec+ds0_rsar1, (ad>>8)&0xff);
176 	outb (nec+ds_cmd, DSCM_RREAD|DSCM_PG0|DSCM_START);
177 	insw (nec+ne_data, up, len/2);
178 	while ((inb (nec+ds0_isr) & DSIS_RDC) == 0) nulldev();
179 	outb (nec+ds0_isr, DSIS_RDC);
180 	outb (nec+ds_cmd, cmd);
181 }
182 
183 putram (up, ad, len) caddr_t up; {
184 	u_char cmd;
185 
186 	cmd = inb(nec+ds_cmd);
187 	outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START);
188 	outb (nec+ds0_isr, DSIS_RDC);
189 	if(len&1) len++;
190 	outb (nec+ds0_rbcr0, len&0xff);
191 	outb (nec+ds0_rbcr1, (len>>8)&0xff);
192 	outb (nec+ds0_rsar0, ad&0xff);
193 	outb (nec+ds0_rsar1, (ad>>8)&0xff);
194 	outb (nec+ds_cmd, DSCM_RWRITE|DSCM_PG0|DSCM_START);
195 	outsw (nec+ne_data, up, len/2);
196 	while ((inb (nec+ds0_isr) & DSIS_RDC) == 0) nulldev();
197 	outb (nec+ds0_isr, DSIS_RDC);
198 	outb (nec+ds_cmd, cmd);
199 }
200 
201 /*
202  * Reset of interface.
203  */
204 nereset(unit, uban)
205 	int unit, uban;
206 {
207 	if (unit >= NNE)
208 		return;
209 	printf("ne%d: reset\n", unit);
210 	ne_softc[unit].ns_flags &= ~DSF_LOCK;
211 	neinit(unit);
212 }
213 
214 /*
215  * Interface exists: make available by filling in network interface
216  * record.  System will initialize the interface when it is ready
217  * to accept packets.  We get the ethernet address here.
218  */
219 neattach(dvp)
220 	struct device *dvp;
221 {
222 	int unit = dvp->unit;
223 	register struct ne_softc *ns = &ne_softc[unit];
224 	register struct ifnet *ifp = &ns->ns_if;
225 
226 	ifp->if_unit = unit;
227 	ifp->if_name = nedriver.name ;
228 	ifp->if_mtu = ETHERMTU;
229 	printf (" physical address %s", ether_sprintf(ns->ns_addr)) ;
230 	ifp->if_flags = IFF_BROADCAST|IFF_NOTRAILERS;
231 	ifp->if_init = neinit;
232 	ifp->if_output = neoutput;
233 	ifp->if_ioctl = neioctl;
234 	ifp->if_reset = nereset;
235 	ifp->if_watchdog = 0;
236 	if_attach(ifp);
237 }
238 
239 /*
240  * Initialization of interface; set up initialization block
241  * and transmit/receive descriptor rings.
242  */
243 neinit(unit)
244 	int unit;
245 {
246 	register struct ne_softc *ns = &ne_softc[unit];
247 	struct ifnet *ifp = &ns->ns_if;
248 	int s;
249 	register i; char *cp;
250 
251  	if (ifp->if_addrlist == (struct ifaddr *)0) return;
252 	if (ifp->if_flags & IFF_RUNNING) return;
253 
254 	s = splimp();
255 
256 	/* set physical address on ethernet */
257 	outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG1|DSCM_STOP);
258 	for (i=0 ; i < 6 ; i++) outb(nec+ds1_par0+i,ns->ns_addr[i]);
259 
260 	/* clr logical address hash filter for now */
261 	for (i=0 ; i < 8 ; i++) outb(nec+ds1_mar0+i,0xff);
262 
263 	/* init regs */
264 	outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP);
265 	outb (nec+ds0_rbcr0, 0);
266 	outb (nec+ds0_rbcr1, 0);
267 	outb (nec+ds0_imr, 0);
268 	outb (nec+ds0_isr, 0xff);
269 	/* Word Transfers, Burst Mode Select, Fifo at 8 bytes */
270 	outb(nec+ds0_dcr, DSDC_WTS|DSDC_BMS|DSDC_FT1);
271 	outb(nec+ds0_tcr, 0);
272 	outb (nec+ds0_rcr, DSRC_MON);
273 	outb (nec+ds0_tpsr, 0);
274 	outb(nec+ds0_pstart, RBUF/DS_PGSIZE);
275 	outb(nec+ds0_pstop, RBUFEND/DS_PGSIZE);
276 	outb(nec+ds0_bnry, RBUFEND/DS_PGSIZE);
277 	outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG1|DSCM_STOP);
278 	outb(nec+ds1_curr, RBUF/DS_PGSIZE);
279 	ns->ns_cur = RBUF/DS_PGSIZE;
280 	outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START);
281 	outb (nec+ds0_rcr, DSRC_AB);
282 	outb(nec+ds0_dcr, DSDC_WTS|DSDC_BMS|DSDC_FT1);
283 	outb (nec+ds0_imr, 0xff);
284 
285 	ns->ns_if.if_flags |= IFF_RUNNING;
286 	ns->ns_oactive = 0; ns->ns_mask = ~0;
287 	if (ns->ns_if.if_snd.ifq_head) nestart(ns);
288 	splx(s);
289 }
290 
291 /*
292  * Setup output on interface.
293  * Get another datagram to send off of the interface queue,
294  * and map it to the interface before starting the output.
295  * called only at splimp or interrupt level.
296  */
297 nestart(ns)
298 	register struct ne_softc *ns;
299 {
300 	struct mbuf *m0, *m;
301 	int buffer;
302 	int len = 0, i;
303 
304 	/*
305 	 * The DS8390 has only one transmit buffer, if it is busy we
306 	 * must wait until the transmit interrupt completes.
307 	 */
308 	outb(nec+ds_cmd,DSCM_NODMA|DSCM_START);
309 
310 	if (inb(nec+ds_cmd) & DSCM_TRANS)
311 		return;
312 
313 	if ((ns->ns_if.if_flags & IFF_RUNNING) == 0)
314 		return;
315 
316 	IF_DEQUEUE(&ns->ns_if.if_snd, m);
317 
318 	if (m == 0)
319 		return;
320 
321 	/*
322 	 * Copy the mbuf chain into the transmit buffer
323 	 */
324 
325 	buffer = TBUF; len = i = 0;
326 	for (m0 = m; m != 0; m = m->m_next) {
327 /*int j;*/
328 		putram(mtod(m, caddr_t), buffer, m->m_len);
329 		buffer += m->m_len;
330 		len += m->m_len;
331 /*for(j=0; i < len;i++,j++) puthex(mtod(m,u_char *)[j]);
332 printf("|"); */
333 	}
334 
335 	/*
336 	 * If this was a broadcast packet loop it
337 	 * back because the hardware can't hear its own
338 	 * transmits.
339 	 */
340 	/*if (bcmp((caddr_t)(mtod(m0, struct ether_header *)->ether_dhost),
341 	   (caddr_t)etherbroadcastaddr,
342 	   sizeof(etherbroadcastaddr)) == 0) {
343 		neread(ns, m0);
344 	} else {
345 */
346 		m_freem(m0);
347 	/*}*/
348 
349 	/*
350 	 * Init transmit length registers, and set transmit start flag.
351 	 */
352 
353 if (len < 60) len = 60;
354 	outb(nec+ds0_tbcr0,len&0xff);
355 	outb(nec+ds0_tbcr1,(len>>8)&0xff);
356 	outb(nec+ds0_tpsr, TBUF/DS_PGSIZE);
357 	outb(nec+ds_cmd, DSCM_TRANS|DSCM_NODMA|DSCM_START);
358 }
359 
360 #define succ(n) (((n)+1 > RBUFEND/DS_PGSIZE) ? RBUF/DS_PGSIZE : (n)+1)
361 #define pred(n) (((n)-1 < RBUF/DS_PGSIZE) ? RBUFEND/DS_PGSIZE : (n)-1)
362 /*
363  * Controller interrupt.
364  */
365 neintr(vec)
366 	int vec;
367 {
368 	register struct ne_softc *ns = &ne_softc[0];
369 	u_char cmd,isr;
370 
371 	/* check cmd, clear interrupt */
372 redo:
373 	cmd = inb (nec+ds_cmd);
374 	outb(nec+ds_cmd,DSCM_NODMA|DSCM_STOP);
375 	isr = inb (nec+ds0_isr);
376 	outb (nec+ds0_isr, isr);
377 
378 	ns->ns_flags |= DSF_LOCK;	/* prevent entering nestart */
379 
380 	if (isr & (/*DSIS_RXE|*/DSIS_TXE|DSIS_ROVRN))
381 		log(LOG_ERR, "ne%d: error: isr %x\n", ns-ne_softc, isr/*, DSIS_BITS*/);
382 
383 	/* receiver ovverun? */
384 	if (isr & DSIS_ROVRN) {
385 		u_char pend,lastfree;
386 
387 		outb(nec+ds_cmd, DSCM_STOP|DSCM_NODMA);
388 		outb(nec+ds_cmd, DSCM_STOP|DSCM_NODMA|DSCM_PG1);
389 		pend = inb(nec+ds1_curr);
390 		outb(nec+ds_cmd, DSCM_STOP|DSCM_NODMA|DSCM_PG0);
391 		lastfree = inb(nec+ds0_bnry);
392 printf("Cur %x pend %x lastfree %x ", ns->ns_cur, pend, lastfree);
393 		/* have we wrapped */
394 		if (lastfree > RBUFEND/DS_PGSIZE)
395 			lastfree = RBUF/DS_PGSIZE;
396 		/* something in the buffer? */
397 		if (pend != succ(lastfree)) {
398 			u_char nxt;
399 
400 			fetchram(&ns->ns_ph,ns->ns_cur*DS_PGSIZE, sizeof(ns->ns_ph));
401 			ns->ns_ba = ns->ns_cur*DS_PGSIZE+sizeof(ns->ns_ph);
402 
403 			if (ns->ns_ph.pr_status & DSRS_RPC)
404 				nerecv (ns);
405 
406 			nxt = ns->ns_ph.pr_nxtpg ;
407 printf("nxt %x ", nxt);
408 			/* sanity check */
409 			if ( nxt >= RBUF/DS_PGSIZE
410 			&& nxt <= RBUFEND/DS_PGSIZE && nxt <= pend)
411 				ns->ns_cur = nxt;
412 			else	ns->ns_cur = nxt = pend;
413 			lastfree = pred(nxt);
414 			outb(nec+ds0_bnry, lastfree);
415 		} else ns->ns_cur = pend;
416 
417 		outb(nec+ds0_rbcr0,0);
418 		outb(nec+ds0_rbcr1,0);
419 		outb(nec+ds0_tcr,DSTC_LB0);
420 		outb(nec+ds0_rcr, DSRC_MON);
421 		outb(nec+ds_cmd, DSCM_START|DSCM_NODMA);
422 		outb (nec+ds0_rcr, DSRC_AB);
423 		outb(nec+ds0_tcr,0);
424 printf("\n");
425 		goto redo;
426 	}
427 
428 	/* receiver error */
429 	if (isr & DSIS_RXE) {
430 		/* need to read these registers to clear status */
431 		(void) inb(nec+ ds0_rsr);
432 		(void) inb(nec+ 0xD);
433 		(void) inb(nec + 0xE);
434 		(void) inb(nec + 0xF);
435 		ns->ns_if.if_ierrors++;
436 	}
437 
438 	if (isr & (DSIS_RX|DSIS_RXE)) {
439 		u_char pend,lastfree;
440 
441 		outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG1);
442 		pend = inb(nec+ds1_curr);
443 		outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG0);
444 		lastfree = inb(nec+ds0_bnry);
445 #include "dbg.h"
446 dprintf(DEXPAND,"cur %x pend %x lastfree %x ", ns->ns_cur, pend, lastfree);
447 		/* have we wrapped */
448 		if (lastfree > RBUFEND/DS_PGSIZE)
449 			lastfree = RBUF/DS_PGSIZE;
450 		/* something in the buffer? */
451 		while (pend != succ(lastfree)) {
452 			u_char nxt;
453 
454 			fetchram(&ns->ns_ph,ns->ns_cur*DS_PGSIZE, sizeof(ns->ns_ph));
455 			ns->ns_ba = ns->ns_cur*DS_PGSIZE+sizeof(ns->ns_ph);
456 
457 			if (ns->ns_ph.pr_status & DSRS_RPC)
458 				nerecv (ns);
459 
460 			nxt = ns->ns_ph.pr_nxtpg ;
461 dprintf(DEXPAND,"nxt %x ", nxt);
462 			/* sanity check */
463 			if ( nxt >= RBUF/DS_PGSIZE
464 			&& nxt <= RBUFEND/DS_PGSIZE && nxt <= pend)
465 				ns->ns_cur = nxt;
466 			else	ns->ns_cur = nxt = pend;
467 			lastfree = pred(nxt);
468 			outb(nec+ds0_bnry, lastfree);
469 		}/* else ns->ns_cur = pend;*/
470 		outb(nec+ds_cmd, DSCM_START|DSCM_NODMA);
471 		goto redo;
472 	}
473 	if (isr & DSIS_TXE) {
474 		/* need to read these registers to clear status */
475 		ns->ns_if.if_collisions += inb(nec+ds0_tbcr0);
476 		ns->ns_if.if_oerrors++;
477 	}
478 	if (isr & (DSIS_TXE| DSIS_TX)) {
479 		++ns->ns_if.if_opackets;
480 		inb(nec+ds0_bnry);
481 		ns->ns_if.if_collisions +=
482 		    inb(nec+ds0_tbcr0);
483 	}
484 dprintf(DEXPAND,"\n");
485 	ns->ns_flags &= ~DSF_LOCK;
486 	outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START);
487 	nestart(ns);
488 	outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START);
489 	outb (nec+ds0_imr, 0xff);
490 }
491 
492 /*
493  * Ethernet interface receiver interface.
494  * If input error just drop packet.
495  * Otherwise examine packet to determine type.  If can't determine length
496  * from type, then have to drop packet.  Othewise decapsulate
497  * packet based on type and pass to type specific higher-level
498  * input routine.
499  */
500 nerecv(ns)
501 	register struct ne_softc *ns;
502 {
503 	int len,i;
504 
505 	ns->ns_if.if_ipackets++;
506 	len = ns->ns_ph.pr_sz0 + (ns->ns_ph.pr_sz1<<8);
507 	fetchram(ns->ns_pb,ns->ns_ba,min(len,DS_PGSIZE-sizeof(ns->ns_ph)));
508 if (!bcmp((caddr_t)ns->ns_pb, (caddr_t)ns->ns_addr, 6)
509 && !bcmp((caddr_t)ns->ns_pb, (caddr_t)etherbroadcastaddr, 6)) {
510 printf("G%x ", ns->ns_cur);
511 return;
512 }/* else
513 printf("P%x ", ns->ns_cur);*/
514 	if(len > DS_PGSIZE-sizeof(ns->ns_ph)) {
515 		int l = len - (DS_PGSIZE-sizeof(ns->ns_ph)), b ;
516 		u_char *p = ns->ns_pb + (DS_PGSIZE-sizeof(ns->ns_ph));
517 
518 dprintf(DEXPAND,"len %d( %d| ", len, p - ns->ns_pb);
519 		if(++ns->ns_cur > 0x7f) ns->ns_cur = 0x46;
520 		b = ns->ns_cur*DS_PGSIZE;
521 
522 		while (l >= DS_PGSIZE) {
523 			fetchram(p,b,DS_PGSIZE);
524 			p += DS_PGSIZE; l -= DS_PGSIZE;
525 		if(++ns->ns_cur > 0x7f) ns->ns_cur = 0x46;
526 		b = ns->ns_cur*DS_PGSIZE;
527 dprintf(DEXPAND,"%d| ", p - ns->ns_pb);
528 		}
529 dprintf(DEXPAND,". %d)\n", l);
530 		if (l > 0)
531 			fetchram(p,b,l);
532 	}
533 	len -=
534 		sizeof(struct ether_header)
535 		+ sizeof(long);	/* don't forget checksum! */
536 
537 
538 	neread(ns,(caddr_t)(ns->ns_pb), len);
539 }
540 
541 /*
542  * Pass a packet to the higher levels.
543  * We deal with the trailer protocol here.
544  */
545 neread(ns, buf, len)
546 	register struct ne_softc *ns;
547 	char *buf;
548 	int len;
549 {
550 	register struct ether_header *eh;
551     	struct mbuf *m;
552 	int off, resid;
553 	register struct ifqueue *inq;
554 
555 	/*
556 	 * Deal with trailer protocol: if type is trailer type
557 	 * get true type from first 16-bit word past data.
558 	 * Remember that type was trailer by setting off.
559 	 */
560 	eh = (struct ether_header *)buf;
561 	eh->ether_type = ntohs((u_short)eh->ether_type);
562 #define	nedataaddr(eh, off, type)	((type)(((caddr_t)((eh)+1)+(off))))
563 	if (eh->ether_type >= ETHERTYPE_TRAIL &&
564 	    eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
565 		off = (eh->ether_type - ETHERTYPE_TRAIL) * 512;
566 		if (off >= ETHERMTU) return;		/* sanity */
567 		eh->ether_type = ntohs(*nedataaddr(eh, off, u_short *));
568 		resid = ntohs(*(nedataaddr(eh, off+2, u_short *)));
569 		if (off + resid > len) return;		/* sanity */
570 		len = off + resid;
571 	} else	off = 0;
572 
573 	if (len == 0) return;
574 
575 	/*
576 	 * Pull packet off interface.  Off is nonzero if packet
577 	 * has trailing header; neget will then force this header
578 	 * information to be at the front, but we still have to drop
579 	 * the type and length which are at the front of any trailer data.
580 	 */
581 	m = neget(buf, len, off, &ns->ns_if);
582 	if (m == 0) return;
583 
584 	if (off) {
585 		struct ifnet *ifp;
586 
587 		ifp = *(mtod(m, struct ifnet **));
588 		m->m_off += 2 * sizeof (u_short);
589 		m->m_len -= 2 * sizeof (u_short);
590 		*(mtod(m, struct ifnet **)) = ifp;
591 	}
592 	switch (eh->ether_type) {
593 #ifdef INET
594 	case ETHERTYPE_IP:
595 		/*if (ns->ns_ac.ac_ipaddr == 0) goto raw;*/
596 		schednetisr(NETISR_IP);
597 		inq = &ipintrq;
598 		break;
599 
600 	case ETHERTYPE_ARP:
601 		arpinput(&ns->ns_ac, m);
602 		return;
603 #endif
604 #ifdef NS
605 	case ETHERTYPE_NS:
606 		schednetisr(NETISR_NS);
607 		inq = &nsintrq;
608 		break;
609 
610 #endif
611 	default:
612 		m_freem(m);
613 		return;
614 	}
615 
616 	if (IF_QFULL(inq)) {
617 		IF_DROP(inq);
618 		m_freem(m);
619 		return;
620 	}
621 	IF_ENQUEUE(inq, m);
622 }
623 
624 /*
625  * Ethernet output routine.
626  * Encapsulate a packet of type family for the local net.
627  * Use trailer local net encapsulation if enough data in first
628  * packet leaves a multiple of 512 bytes of data in remainder.
629  */
630 neoutput(ifp, m0, dst)
631 	struct ifnet *ifp;
632 	struct mbuf *m0;
633 	struct sockaddr *dst;
634 {
635 	int type, s, error;
636 	u_char edst[6];
637 	struct in_addr idst;
638 	register struct ne_softc *ns = &ne_softc[ifp->if_unit];
639 	register struct mbuf *m = m0;
640 	register struct ether_header *eh;
641 	register int off;
642 	extern struct ifnet loif;
643         struct mbuf *mcopy = (struct mbuf *)0;
644 	int usetrailers;
645 
646 	if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
647 		error = ENETDOWN;
648 		goto bad;
649 	}
650 
651 	switch (dst->sa_family) {
652 #ifdef INET
653 	case AF_INET:
654 		idst = ((struct sockaddr_in *)dst)->sin_addr;
655 		if (!arpresolve(&ns->ns_ac, m, &idst, edst, &usetrailers))
656 			return (0);	/* if not yet resolved */
657 		if (!bcmp((caddr_t)edst, (caddr_t)etherbroadcastaddr,
658 		    sizeof(edst)))
659                         mcopy = m_copy(m, 0, (int)M_COPYALL);
660 		off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
661 
662 		/* need per host negotiation */
663 		if (usetrailers && off > 0 && (off & 0x1ff) == 0 &&
664 		    m->m_off >= MMINOFF + 2 * sizeof (u_short)) {
665 			type = ETHERTYPE_TRAIL + (off>>9);
666 			m->m_off -= 2 * sizeof (u_short);
667 			m->m_len += 2 * sizeof (u_short);
668 			*mtod(m, u_short *) = ntohs((u_short)ETHERTYPE_IP);
669 			*(mtod(m, u_short *) + 1) = ntohs((u_short)m->m_len);
670 			goto gottrailertype;
671 		}
672 		type = ETHERTYPE_IP;
673 		off = 0;
674 		goto gottype;
675 #endif
676 #ifdef NS
677 	case AF_NS:
678  		bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
679 		    (caddr_t)edst, sizeof (edst));
680 
681 		if (!bcmp((caddr_t)edst, (caddr_t)&ns_broadhost,
682 			sizeof(edst))) {
683 
684 				mcopy = m_copy(m, 0, (int)M_COPYALL);
685 		} else if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost,
686 			sizeof(edst))) {
687 
688 				return(looutput(&loif, m, dst));
689 		}
690 		type = ETHERTYPE_NS;
691 		off = 0;
692 		goto gottype;
693 #endif
694 
695 	case AF_UNSPEC:
696 		eh = (struct ether_header *)dst->sa_data;
697 		bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst));
698 		type = eh->ether_type;
699 		goto gottype;
700 
701 	default:
702 		printf("ne%d: can't handle af%d\n", ifp->if_unit,
703 			dst->sa_family);
704 		error = EAFNOSUPPORT;
705 		goto bad;
706 	}
707 
708 gottrailertype:
709 	/*
710 	 * Packet to be sent as trailer: move first packet
711 	 * (control information) to end of chain.
712 	 */
713 	while (m->m_next)
714 		m = m->m_next;
715 	m->m_next = m0;
716 	m = m0->m_next;
717 	m0->m_next = 0;
718 	m0 = m;
719 
720 gottype:
721 	/*
722 	 * Add local net header.  If no space in first mbuf,
723 	 * allocate another.
724 	 */
725 	if (m->m_off > MMAXOFF ||
726 	    MMINOFF + sizeof (struct ether_header) > m->m_off) {
727 		m = m_get(M_DONTWAIT, MT_HEADER);
728 		if (m == 0) {
729 			error = ENOBUFS;
730 			goto bad;
731 		}
732 		m->m_next = m0;
733 		m->m_off = MMINOFF;
734 		m->m_len = sizeof (struct ether_header);
735 	} else {
736 		m->m_off -= sizeof (struct ether_header);
737 		m->m_len += sizeof (struct ether_header);
738 	}
739 	eh = mtod(m, struct ether_header *);
740 	bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst));
741 	bcopy((caddr_t)ns->ns_addr, (caddr_t)eh->ether_shost,
742 		sizeof (eh->ether_shost));
743 	eh->ether_type = htons((u_short)type);
744 
745 	/*
746 	 * Queue message on interface, and start output if interface
747 	 * not yet active.
748 	 */
749 	s = splimp();
750 	if (IF_QFULL(&ifp->if_snd)) {
751 		IF_DROP(&ifp->if_snd);
752 		splx(s);
753 		m_freem(m);
754 		return (ENOBUFS);
755 	}
756 	IF_ENQUEUE(&ifp->if_snd, m);
757 	nestart(ns);
758 	splx(s);
759         return (mcopy ? looutput(&loif, mcopy, dst) : 0);
760 
761 bad:
762 	m_freem(m0);
763 	if (mcopy)
764 		m_freem(mcopy);
765 	return (error);
766 }
767 
768 /*
769  * Supporting routines
770  */
771 
772 /*
773  * Pull read data off a interface.
774  * Len is length of data, with local net header stripped.
775  * Off is non-zero if a trailer protocol was used, and
776  * gives the offset of the trailer information.
777  * We copy the trailer information and then all the normal
778  * data into mbufs.  When full cluster sized units are present
779  * we copy into clusters.
780  */
781 struct mbuf *
782 neget(buf, totlen, off0, ifp)
783 	caddr_t buf;
784 	int totlen, off0;
785 	struct ifnet *ifp;
786 {
787 	struct mbuf *top, **mp, *m, *p;
788 	int off = off0, len;
789 	register caddr_t cp = buf;
790 
791 	cp = buf + sizeof(struct ether_header);
792 	top = 0;
793 	mp = &top;
794 	while (totlen > 0) {
795 		u_char *mcp;
796 
797 		MGET(m, M_DONTWAIT, MT_DATA);
798 		if (m == 0)
799 			goto bad;
800 		if (off) {
801 			len = totlen - off;
802 			cp = buf + off + sizeof (struct ether_header);
803 		} else
804 			len = totlen;
805 		if (ifp)
806 			len += sizeof(ifp);
807 		if (len >= NBPG) {
808 			MCLGET(m);
809 			if (m->m_len == CLBYTES)
810 				m->m_len = len = MIN(len, CLBYTES);
811 			else
812 				m->m_len = len = MIN(MLEN, len);
813 		} else {
814 			m->m_len = len = MIN(MLEN, len);
815 			m->m_off = MMINOFF;
816 		}
817 		mcp = mtod(m, u_char *);
818 		if (ifp) {
819 			/*
820 			 * Prepend interface pointer to first mbuf.
821 			 */
822 			*(mtod(m, struct ifnet **)) = ifp;
823 			mcp += sizeof(ifp);
824 			len -= sizeof(ifp);
825 			ifp = (struct ifnet *)0;
826 		}
827 		bcopy(cp, mcp, len);
828 		cp += len ; mcp += len ;
829 		*mp = m;
830 		mp = &m->m_next;
831 		if (off == 0) {
832 			totlen -= len;
833 			continue;
834 		}
835 		off += len;
836 		if (off == totlen) {
837 			cp = buf + sizeof (struct ether_header);
838 			off = 0;
839 			totlen = off0;
840 		}
841 	}
842 	return (top);
843 bad:
844 	m_freem(top);
845 	return (0);
846 }
847 
848 /*
849  * Map a chain of mbufs onto a network interface
850  * in preparation for an i/o operation.
851  * The argument chain of mbufs includes the local network
852  * header which is copied to be in the mapped, aligned
853  * i/o space.
854  */
855 neput(cp, m)
856 	register caddr_t cp;
857 	register struct mbuf *m;
858 {
859 	register struct mbuf *mp;
860 	register int i;
861 	int x, cc = 0, t;
862 	caddr_t dp;
863 
864 	while (m) {
865 		dp = mtod(m, char *);
866 		bcopy(mtod(m, caddr_t), cp, (unsigned)m->m_len);
867 		cp += m->m_len;
868 		cc += m->m_len;
869 		MFREE(m, mp);
870 		m = mp;
871 	}
872 	return (max(cc, ETHERMIN + sizeof(struct ether_header)));
873 }
874 
875 /*
876  * Process an ioctl request.
877  */
878 neioctl(ifp, cmd, data)
879 	register struct ifnet *ifp;
880 	int cmd;
881 	caddr_t data;
882 {
883 	register struct ifaddr *ifa = (struct ifaddr *)data;
884 	struct ne_softc *ns = &ne_softc[ifp->if_unit];
885 	struct ifreq *ifr = (struct ifreq *)data;
886 	int s = splimp(), error = 0;
887 
888 
889 	switch (cmd) {
890 
891 	case SIOCSIFADDR:
892 		ifp->if_flags |= IFF_UP;
893 
894 		switch (ifa->ifa_addr.sa_family) {
895 #ifdef INET
896 		case AF_INET:
897 			neinit(ifp->if_unit);	/* before arpwhohas */
898 			((struct arpcom *)ifp)->ac_ipaddr =
899 				IA_SIN(ifa)->sin_addr;
900 			arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
901 			break;
902 #endif
903 #ifdef NS
904 		case AF_NS:
905 		    {
906 			register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
907 
908 			if (ns_nullhost(*ina))
909 				ina->x_host = *(union ns_host *)(ns->ns_addr);
910 			else {
911 				/*
912 				 * The manual says we can't change the address
913 				 * while the receiver is armed,
914 				 * so reset everything
915 				 */
916 				ifp->if_flags &= ~IFF_RUNNING;
917 				bcopy((caddr_t)ina->x_host.c_host,
918 				    (caddr_t)ns->ns_addr, sizeof(ns->ns_addr));
919 			}
920 			neinit(ifp->if_unit); /* does ne_setaddr() */
921 			break;
922 		    }
923 #endif
924 		default:
925 			neinit(ifp->if_unit);
926 			break;
927 		}
928 		break;
929 
930 	case SIOCSIFFLAGS:
931 		if ((ifp->if_flags & IFF_UP) == 0 &&
932 		    ifp->if_flags & IFF_RUNNING) {
933 			ifp->if_flags &= ~IFF_RUNNING;
934 			outb(nec+ds_cmd,DSCM_STOP|DSCM_NODMA);
935 		} else if (ifp->if_flags & IFF_UP &&
936 		    (ifp->if_flags & IFF_RUNNING) == 0)
937 			neinit(ifp->if_unit);
938 		break;
939 
940 #ifdef notdef
941 	case SIOCGHWADDR:
942 		bcopy((caddr_t)ns->ns_addr, (caddr_t) &ifr->ifr_data,
943 			sizeof(ns->ns_addr));
944 		break;
945 #endif
946 
947 	default:
948 		error = EINVAL;
949 	}
950 	splx(s);
951 	return (error);
952 }
953 
954 nesetaddr(ifp, sin)
955 	register struct ifnet *ifp;
956 	register struct sockaddr_in *sin;
957 {
958 #ifdef notdef
959 	ifp->if_addr = *(struct sockaddr *)sin;
960 	ifp->if_net = in_netof(sin->sin_addr);
961 	ifp->if_host[0] = in_lnaof(sin->sin_addr);
962 	if (nepaddr[ifp->if_unit][0] == '3')
963 		nepaddr[ifp->if_unit][0] = ifp->if_host[0] << 1;
964 	sin = (struct sockaddr_in *)&ifp->if_broadaddr;
965 	sin->sin_family = AF_INET;
966 	sin->sin_addr = in_makeaddr(ifp->if_net, INADDR_ANY);
967 	ifp->if_flags |= IFF_BROADCAST;
968 #endif
969 }
970 #endif
971