1 /*-
2 * Copyright (c) 1990, 1991 William F. Jolitz.
3 * Copyright (c) 1990, 1993
4 * The Regents of the University of California. All rights reserved.
5 *
6 * %sccs.include.redist.c%
7 *
8 * @(#)if_ne.c 8.1 (Berkeley) 06/11/93
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 */
nefetch(up,ad,len)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 */
neput(up,ad,len)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 */
nereset(unit,uban)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 */
neinit(unit)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 */
neintr(unit)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 */
nerecv(ns)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 */
neread(ns,buf,len)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 *
neget(buf,totlen,off0,ifp)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 = ⊤
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 */
neioctl(ifp,cmd,data)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