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