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 = ⊤ 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