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