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