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