1 /* if_ec.c 6.5 84/08/29 */ 2 3 #include "ec.h" 4 5 /* 6 * 3Com Ethernet Controller interface 7 */ 8 #include "../machine/pte.h" 9 10 #include "param.h" 11 #include "systm.h" 12 #include "mbuf.h" 13 #include "buf.h" 14 #include "protosw.h" 15 #include "socket.h" 16 #include "vmmac.h" 17 #include "ioctl.h" 18 #include "errno.h" 19 20 #include "../net/if.h" 21 #include "../net/netisr.h" 22 #include "../net/route.h" 23 #include "../netinet/in.h" 24 #include "../netinet/in_systm.h" 25 #include "../netinet/ip.h" 26 #include "../netinet/ip_var.h" 27 #include "../netinet/if_ether.h" 28 #include "../netpup/pup.h" 29 30 #include "../vax/cpu.h" 31 #include "../vax/mtpr.h" 32 #include "if_ecreg.h" 33 #include "if_uba.h" 34 #include "../vaxuba/ubareg.h" 35 #include "../vaxuba/ubavar.h" 36 37 /* 38 * The memory address must be consecutive. Any allocations 39 * not in order will cause problems on a VAX 780. 40 */ 41 42 int ecmem[] = { 43 #if NEC > 0 44 0000000, 45 #endif 46 #if NEC > 1 47 0100000, 48 #endif 49 #if NEC > 2 50 0200000, 51 #endif 52 #if NEC > 3 53 0300000, 54 #endif 55 #if NEC > 4 56 0400000, 57 #endif 58 #if NEC > 5 59 0500000, 60 #endif 61 #if NEC > 6 62 0600000, 63 #endif 64 #if NEC > 7 65 0700000, 66 #endif 67 }; 68 69 int necmem = 0; /* count of current memory number for ecprobe */ 70 71 int ecprobe(), ecattach(), ecrint(), ecxint(), eccollide(); 72 struct uba_device *ecinfo[NEC]; 73 u_short ecstd[] = { 0 }; 74 struct uba_driver ecdriver = 75 { ecprobe, 0, ecattach, 0, ecstd, "ec", ecinfo }; 76 #define ECUNIT(x) minor(x) 77 78 int ecinit(),ecioctl(),ecoutput(),ecreset(); 79 struct mbuf *ecget(); 80 81 extern struct ifnet loif; 82 83 /* 84 * Ethernet software status per interface. 85 * 86 * Each interface is referenced by a network interface structure, 87 * es_if, which the routing code uses to locate the interface. 88 * This structure contains the output queue for the interface, its address, ... 89 * We also have, for each interface, a UBA interface structure, which 90 * contains information about the UNIBUS resources held by the interface: 91 * map registers, buffered data paths, etc. Information is cached in this 92 * structure for use by the if_uba.c routines in running the interface 93 * efficiently. 94 */ 95 struct ec_softc { 96 struct arpcom es_ac; /* common Ethernet structures */ 97 #define es_if es_ac.ac_if /* network-visible interface */ 98 #define es_addr es_ac.ac_enaddr /* hardware Ethernet address */ 99 struct ifuba es_ifuba; /* UNIBUS resources */ 100 short es_mask; /* mask for current output delay */ 101 short es_oactive; /* is output active? */ 102 u_char *es_buf[16]; /* virtual addresses of buffers */ 103 } ec_softc[NEC]; 104 105 /* 106 * Do output DMA to determine interface presence and 107 * interrupt vector. DMA is too short to disturb other hosts. 108 */ 109 ecprobe(reg) 110 caddr_t reg; 111 { 112 register int br, cvec; /* r11, r10 value-result */ 113 register struct ecdevice *addr = (struct ecdevice *)reg; 114 register caddr_t ecbuf = (caddr_t) &umem[numuba][ecmem[necmem]]; 115 116 #ifdef lint 117 br = 0; cvec = br; br = cvec; 118 ecrint(0); ecxint(0); eccollide(0); 119 #endif 120 /* 121 * Make sure memory is turned on 122 */ 123 addr->ec_rcr = EC_AROM; 124 /* 125 * Disable map registers for ec unibus space, 126 * but don't allocate yet. 127 */ 128 (void) ubamem(numuba, ecmem[necmem], 32*2, 0); 129 /* 130 * Check for existence of buffers on Unibus. 131 */ 132 if (badaddr((caddr_t)ecbuf, 2)) { 133 bad1: 134 printf("ec: buffer mem not found\n"); 135 bad2: 136 (void) ubamem(numuba, 0, 0, 0); /* reenable map (780 only) */ 137 addr->ec_rcr = EC_MDISAB; /* disable memory */ 138 necmem++; 139 return (0); 140 } 141 #if VAX780 142 if (cpu == VAX_780 && uba_hd[numuba].uh_uba->uba_sr) { 143 uba_hd[numuba].uh_uba->uba_sr = uba_hd[numuba].uh_uba->uba_sr; 144 goto bad1; 145 } 146 #endif 147 148 /* 149 * Tell the system that the board has memory here, so it won't 150 * attempt to allocate the addresses later. 151 */ 152 if (ubamem(numuba, ecmem[necmem], 32*2, 1) == 0) { 153 printf("ecprobe: cannot reserve uba addresses\n"); 154 goto bad2; 155 } 156 157 /* 158 * Make a one byte packet in what should be buffer #0. 159 * Submit it for sending. This whould cause an xmit interrupt. 160 * The xmit interrupt vector is 8 bytes after the receive vector, 161 * so adjust for this before returning. 162 */ 163 *(u_short *)ecbuf = (u_short) 03777; 164 ecbuf[03777] = '\0'; 165 addr->ec_xcr = EC_XINTEN|EC_XWBN; 166 DELAY(100000); 167 addr->ec_xcr = EC_XCLR; 168 if (cvec > 0 && cvec != 0x200) { 169 if (cvec & 04) { /* collision interrupt */ 170 cvec -= 04; 171 br += 1; /* rcv is collision + 1 */ 172 } else { /* xmit interrupt */ 173 cvec -= 010; 174 br += 2; /* rcv is xmit + 2 */ 175 } 176 } 177 necmem++; 178 return (1); 179 } 180 181 /* 182 * Interface exists: make available by filling in network interface 183 * record. System will initialize the interface when it is ready 184 * to accept packets. 185 */ 186 ecattach(ui) 187 struct uba_device *ui; 188 { 189 struct ec_softc *es = &ec_softc[ui->ui_unit]; 190 register struct ifnet *ifp = &es->es_if; 191 register struct ecdevice *addr = (struct ecdevice *)ui->ui_addr; 192 struct sockaddr_in *sin; 193 int i, j; 194 u_char *cp; 195 196 ifp->if_unit = ui->ui_unit; 197 ifp->if_name = "ec"; 198 ifp->if_mtu = ETHERMTU; 199 200 /* 201 * Read the ethernet address off the board, one nibble at a time. 202 */ 203 addr->ec_xcr = EC_UECLR; 204 addr->ec_rcr = EC_AROM; 205 cp = (u_char *) &es->es_addr; 206 #define NEXTBIT addr->ec_rcr = EC_AROM|EC_ASTEP; addr->ec_rcr = EC_AROM 207 for (i=0; i < sizeof (es->es_addr); i++) { 208 *cp = 0; 209 for (j=0; j<=4; j+=4) { 210 *cp |= ((addr->ec_rcr >> 8) & 0xf) << j; 211 NEXTBIT; NEXTBIT; NEXTBIT; NEXTBIT; 212 } 213 cp++; 214 } 215 sin = (struct sockaddr_in *)&es->es_if.if_addr; 216 sin->sin_family = AF_INET; 217 ifp->if_init = ecinit; 218 ifp->if_ioctl = ecioctl; 219 ifp->if_output = ecoutput; 220 ifp->if_reset = ecreset; 221 for (i=0; i<16; i++) 222 es->es_buf[i] 223 = (u_char *)&umem[ui->ui_ubanum][ecmem[ifp->if_unit]+2048*i]; 224 if_attach(ifp); 225 } 226 227 /* 228 * Reset of interface after UNIBUS reset. 229 * If interface is on specified uba, reset its state. 230 */ 231 ecreset(unit, uban) 232 int unit, uban; 233 { 234 register struct uba_device *ui; 235 236 if (unit >= NEC || (ui = ecinfo[unit]) == 0 || ui->ui_alive == 0 || 237 ui->ui_ubanum != uban) 238 return; 239 printf(" ec%d", unit); 240 (void) ubamem(uban, ecmem[unit], 32*2, 0); /* mr disable (no alloc) */ 241 ec_softc[unit].es_if.if_flags &= ~IFF_RUNNING; 242 ecinit(unit); 243 } 244 245 /* 246 * Initialization of interface; clear recorded pending 247 * operations, and reinitialize UNIBUS usage. 248 */ 249 ecinit(unit) 250 int unit; 251 { 252 struct ec_softc *es = &ec_softc[unit]; 253 struct ecdevice *addr; 254 register struct ifnet *ifp = &es->es_if; 255 register struct sockaddr_in *sin; 256 int i, s; 257 258 sin = (struct sockaddr_in *)&ifp->if_addr; 259 if (sin->sin_addr.s_addr == 0) /* address still unknown */ 260 return; 261 262 /* 263 * Hang receive buffers and start any pending writes. 264 * Writing into the rcr also makes sure the memory 265 * is turned on. 266 */ 267 if ((es->es_if.if_flags & IFF_RUNNING) == 0) { 268 addr = (struct ecdevice *)ecinfo[unit]->ui_addr; 269 s = splimp(); 270 for (i = ECRHBF; i >= ECRLBF; i--) 271 addr->ec_rcr = EC_READ | i; 272 es->es_oactive = 0; 273 es->es_mask = ~0; 274 es->es_if.if_flags |= IFF_UP|IFF_RUNNING; 275 if (es->es_if.if_snd.ifq_head) 276 ecstart(unit); 277 splx(s); 278 } 279 if_rtinit(&es->es_if, RTF_UP); 280 arpwhohas(&es->es_ac, &sin->sin_addr); 281 } 282 283 /* 284 * Start or restart output on interface. 285 * If interface is already active, then this is a retransmit 286 * after a collision, and just restuff registers. 287 * If interface is not already active, get another datagram 288 * to send off of the interface queue, and map it to the interface 289 * before starting the output. 290 */ 291 ecstart(dev) 292 dev_t dev; 293 { 294 int unit = ECUNIT(dev); 295 struct ec_softc *es = &ec_softc[unit]; 296 struct ecdevice *addr; 297 struct mbuf *m; 298 299 if (es->es_oactive) 300 goto restart; 301 302 IF_DEQUEUE(&es->es_if.if_snd, m); 303 if (m == 0) { 304 es->es_oactive = 0; 305 return; 306 } 307 ecput(es->es_buf[ECTBF], m); 308 309 restart: 310 addr = (struct ecdevice *)ecinfo[unit]->ui_addr; 311 addr->ec_xcr = EC_WRITE|ECTBF; 312 es->es_oactive = 1; 313 } 314 315 /* 316 * Ethernet interface transmitter interrupt. 317 * Start another output if more data to send. 318 */ 319 ecxint(unit) 320 int unit; 321 { 322 register struct ec_softc *es = &ec_softc[unit]; 323 register struct ecdevice *addr = 324 (struct ecdevice *)ecinfo[unit]->ui_addr; 325 326 if (es->es_oactive == 0) 327 return; 328 if ((addr->ec_xcr&EC_XDONE) == 0 || (addr->ec_xcr&EC_XBN) != ECTBF) { 329 printf("ec%d: stray xmit interrupt, xcr=%b\n", unit, 330 addr->ec_xcr, EC_XBITS); 331 es->es_oactive = 0; 332 addr->ec_xcr = EC_XCLR; 333 return; 334 } 335 es->es_if.if_opackets++; 336 es->es_oactive = 0; 337 es->es_mask = ~0; 338 addr->ec_xcr = EC_XCLR; 339 if (es->es_if.if_snd.ifq_head) 340 ecstart(unit); 341 } 342 343 /* 344 * Collision on ethernet interface. Do exponential 345 * backoff, and retransmit. If have backed off all 346 * the way print warning diagnostic, and drop packet. 347 */ 348 eccollide(unit) 349 int unit; 350 { 351 struct ec_softc *es = &ec_softc[unit]; 352 353 es->es_if.if_collisions++; 354 if (es->es_oactive) 355 ecdocoll(unit); 356 } 357 358 ecdocoll(unit) 359 int unit; 360 { 361 register struct ec_softc *es = &ec_softc[unit]; 362 register struct ecdevice *addr = 363 (struct ecdevice *)ecinfo[unit]->ui_addr; 364 register i; 365 int delay; 366 367 /* 368 * Es_mask is a 16 bit number with n low zero bits, with 369 * n the number of backoffs. When es_mask is 0 we have 370 * backed off 16 times, and give up. 371 */ 372 if (es->es_mask == 0) { 373 es->es_if.if_oerrors++; 374 printf("ec%d: send error\n", unit); 375 /* 376 * Reset interface, then requeue rcv buffers. 377 * Some incoming packets may be lost, but that 378 * can't be helped. 379 */ 380 addr->ec_xcr = EC_UECLR; 381 for (i=ECRHBF; i>=ECRLBF; i--) 382 addr->ec_rcr = EC_READ|i; 383 /* 384 * Reset and transmit next packet (if any). 385 */ 386 es->es_oactive = 0; 387 es->es_mask = ~0; 388 if (es->es_if.if_snd.ifq_head) 389 ecstart(unit); 390 return; 391 } 392 /* 393 * Do exponential backoff. Compute delay based on low bits 394 * of the interval timer. Then delay for that number of 395 * slot times. A slot time is 51.2 microseconds (rounded to 51). 396 * This does not take into account the time already used to 397 * process the interrupt. 398 */ 399 es->es_mask <<= 1; 400 delay = mfpr(ICR) &~ es->es_mask; 401 DELAY(delay * 51); 402 /* 403 * Clear the controller's collision flag, thus enabling retransmit. 404 */ 405 addr->ec_xcr = EC_CLEAR; 406 } 407 408 /* 409 * Ethernet interface receiver interrupt. 410 * If input error just drop packet. 411 * Otherwise purge input buffered data path and examine 412 * packet to determine type. If can't determine length 413 * from type, then have to drop packet. Othewise decapsulate 414 * packet based on type and pass to type specific higher-level 415 * input routine. 416 */ 417 ecrint(unit) 418 int unit; 419 { 420 struct ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr; 421 422 while (addr->ec_rcr & EC_RDONE) 423 ecread(unit); 424 } 425 426 ecread(unit) 427 int unit; 428 { 429 register struct ec_softc *es = &ec_softc[unit]; 430 struct ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr; 431 register struct ether_header *ec; 432 struct mbuf *m; 433 int len, off, resid, ecoff, rbuf; 434 register struct ifqueue *inq; 435 u_char *ecbuf; 436 437 es->es_if.if_ipackets++; 438 rbuf = addr->ec_rcr & EC_RBN; 439 if (rbuf < ECRLBF || rbuf > ECRHBF) 440 panic("ecrint"); 441 ecbuf = es->es_buf[rbuf]; 442 ecoff = *(short *)ecbuf; 443 if (ecoff <= ECRDOFF || ecoff > 2046) { 444 es->es_if.if_ierrors++; 445 #ifdef notdef 446 if (es->es_if.if_ierrors % 100 == 0) 447 printf("ec%d: += 100 input errors\n", unit); 448 #endif 449 goto setup; 450 } 451 452 /* 453 * Get input data length. 454 * Get pointer to ethernet header (in input buffer). 455 * Deal with trailer protocol: if type is PUP trailer 456 * get true type from first 16-bit word past data. 457 * Remember that type was trailer by setting off. 458 */ 459 len = ecoff - ECRDOFF - sizeof (struct ether_header); 460 ec = (struct ether_header *)(ecbuf + ECRDOFF); 461 ec->ether_type = ntohs((u_short)ec->ether_type); 462 #define ecdataaddr(ec, off, type) ((type)(((caddr_t)((ec)+1)+(off)))) 463 if (ec->ether_type >= ETHERPUP_TRAIL && 464 ec->ether_type < ETHERPUP_TRAIL+ETHERPUP_NTRAILER) { 465 off = (ec->ether_type - ETHERPUP_TRAIL) * 512; 466 if (off >= ETHERMTU) 467 goto setup; /* sanity */ 468 ec->ether_type = ntohs(*ecdataaddr(ec, off, u_short *)); 469 resid = ntohs(*(ecdataaddr(ec, off+2, u_short *))); 470 if (off + resid > len) 471 goto setup; /* sanity */ 472 len = off + resid; 473 } else 474 off = 0; 475 if (len == 0) 476 goto setup; 477 478 /* 479 * Pull packet off interface. Off is nonzero if packet 480 * has trailing header; ecget will then force this header 481 * information to be at the front, but we still have to drop 482 * the type and length which are at the front of any trailer data. 483 */ 484 m = ecget(ecbuf, len, off); 485 if (m == 0) 486 goto setup; 487 if (off) { 488 m->m_off += 2 * sizeof (u_short); 489 m->m_len -= 2 * sizeof (u_short); 490 } 491 switch (ec->ether_type) { 492 493 #ifdef INET 494 case ETHERPUP_IPTYPE: 495 schednetisr(NETISR_IP); 496 inq = &ipintrq; 497 break; 498 499 case ETHERPUP_ARPTYPE: 500 arpinput(&es->es_ac, m); 501 goto setup; 502 #endif 503 default: 504 m_freem(m); 505 goto setup; 506 } 507 508 if (IF_QFULL(inq)) { 509 IF_DROP(inq); 510 m_freem(m); 511 goto setup; 512 } 513 IF_ENQUEUE(inq, m); 514 515 setup: 516 /* 517 * Reset for next packet. 518 */ 519 addr->ec_rcr = EC_READ|EC_RCLR|rbuf; 520 } 521 522 /* 523 * Ethernet output routine. 524 * Encapsulate a packet of type family for the local net. 525 * Use trailer local net encapsulation if enough data in first 526 * packet leaves a multiple of 512 bytes of data in remainder. 527 * If destination is this address or broadcast, send packet to 528 * loop device to kludge around the fact that 3com interfaces can't 529 * talk to themselves. 530 */ 531 ecoutput(ifp, m0, dst) 532 struct ifnet *ifp; 533 struct mbuf *m0; 534 struct sockaddr *dst; 535 { 536 int type, s, error; 537 struct ether_addr edst; 538 struct in_addr idst; 539 register struct ec_softc *es = &ec_softc[ifp->if_unit]; 540 register struct mbuf *m = m0; 541 register struct ether_header *ec; 542 register int off; 543 struct mbuf *mcopy = (struct mbuf *)0; 544 545 switch (dst->sa_family) { 546 547 #ifdef INET 548 case AF_INET: 549 idst = ((struct sockaddr_in *)dst)->sin_addr; 550 if (!arpresolve(&es->es_ac, m, &idst, &edst)) 551 return (0); /* if not yet resolved */ 552 if (in_lnaof(idst) == INADDR_ANY) 553 mcopy = m_copy(m, 0, (int)M_COPYALL); 554 off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; 555 /* need per host negotiation */ 556 if ((ifp->if_flags & IFF_NOTRAILERS) == 0) 557 if (off > 0 && (off & 0x1ff) == 0 && 558 m->m_off >= MMINOFF + 2 * sizeof (u_short)) { 559 type = ETHERPUP_TRAIL + (off>>9); 560 m->m_off -= 2 * sizeof (u_short); 561 m->m_len += 2 * sizeof (u_short); 562 *mtod(m, u_short *) = ntohs((u_short)ETHERPUP_IPTYPE); 563 *(mtod(m, u_short *) + 1) = ntohs((u_short)m->m_len); 564 goto gottrailertype; 565 } 566 type = ETHERPUP_IPTYPE; 567 off = 0; 568 goto gottype; 569 #endif 570 571 case AF_UNSPEC: 572 ec = (struct ether_header *)dst->sa_data; 573 edst = ec->ether_dhost; 574 type = ec->ether_type; 575 goto gottype; 576 577 default: 578 printf("ec%d: can't handle af%d\n", ifp->if_unit, 579 dst->sa_family); 580 error = EAFNOSUPPORT; 581 goto bad; 582 } 583 584 gottrailertype: 585 /* 586 * Packet to be sent as trailer: move first packet 587 * (control information) to end of chain. 588 */ 589 while (m->m_next) 590 m = m->m_next; 591 m->m_next = m0; 592 m = m0->m_next; 593 m0->m_next = 0; 594 m0 = m; 595 596 gottype: 597 /* 598 * Add local net header. If no space in first mbuf, 599 * allocate another. 600 */ 601 if (m->m_off > MMAXOFF || 602 MMINOFF + sizeof (struct ether_header) > m->m_off) { 603 m = m_get(M_DONTWAIT, MT_HEADER); 604 if (m == 0) { 605 error = ENOBUFS; 606 goto bad; 607 } 608 m->m_next = m0; 609 m->m_off = MMINOFF; 610 m->m_len = sizeof (struct ether_header); 611 } else { 612 m->m_off -= sizeof (struct ether_header); 613 m->m_len += sizeof (struct ether_header); 614 } 615 ec = mtod(m, struct ether_header *); 616 ec->ether_dhost = edst; 617 ec->ether_shost = es->es_addr; 618 ec->ether_type = htons((u_short)type); 619 620 /* 621 * Queue message on interface, and start output if interface 622 * not yet active. 623 */ 624 s = splimp(); 625 if (IF_QFULL(&ifp->if_snd)) { 626 IF_DROP(&ifp->if_snd); 627 error = ENOBUFS; 628 goto qfull; 629 } 630 IF_ENQUEUE(&ifp->if_snd, m); 631 if (es->es_oactive == 0) 632 ecstart(ifp->if_unit); 633 splx(s); 634 return (mcopy ? looutput(&loif, mcopy, dst) : 0); 635 636 qfull: 637 m0 = m; 638 splx(s); 639 bad: 640 m_freem(m0); 641 if (mcopy) 642 m_freem(mcopy); 643 return (error); 644 } 645 646 /* 647 * Routine to copy from mbuf chain to transmit 648 * buffer in UNIBUS memory. 649 * If packet size is less than the minimum legal size, 650 * the buffer is expanded. We probably should zero out the extra 651 * bytes for security, but that would slow things down. 652 */ 653 ecput(ecbuf, m) 654 u_char *ecbuf; 655 struct mbuf *m; 656 { 657 register struct mbuf *mp; 658 register int off; 659 u_char *bp; 660 661 for (off = 2048, mp = m; mp; mp = mp->m_next) 662 off -= mp->m_len; 663 if (2048 - off < ETHERMIN + sizeof (struct ether_header)) 664 off = 2048 - ETHERMIN - sizeof (struct ether_header); 665 *(u_short *)ecbuf = off; 666 bp = (u_char *)(ecbuf + off); 667 for (mp = m; mp; mp = mp->m_next) { 668 register unsigned len = mp->m_len; 669 u_char *mcp; 670 671 if (len == 0) 672 continue; 673 mcp = mtod(mp, u_char *); 674 if ((unsigned)bp & 01) { 675 *bp++ = *mcp++; 676 len--; 677 } 678 if (off = (len >> 1)) { 679 register u_short *to, *from; 680 681 to = (u_short *)bp; 682 from = (u_short *)mcp; 683 do 684 *to++ = *from++; 685 while (--off > 0); 686 bp = (u_char *)to, 687 mcp = (u_char *)from; 688 } 689 if (len & 01) 690 *bp++ = *mcp++; 691 } 692 m_freem(m); 693 } 694 695 /* 696 * Routine to copy from UNIBUS memory into mbufs. 697 * Similar in spirit to if_rubaget. 698 * 699 * Warning: This makes the fairly safe assumption that 700 * mbufs have even lengths. 701 */ 702 struct mbuf * 703 ecget(ecbuf, totlen, off0) 704 u_char *ecbuf; 705 int totlen, off0; 706 { 707 register struct mbuf *m; 708 struct mbuf *top = 0, **mp = ⊤ 709 register int off = off0, len; 710 u_char *cp; 711 712 cp = ecbuf + ECRDOFF + sizeof (struct ether_header); 713 while (totlen > 0) { 714 register int words; 715 u_char *mcp; 716 717 MGET(m, M_DONTWAIT, MT_DATA); 718 if (m == 0) 719 goto bad; 720 if (off) { 721 len = totlen - off; 722 cp = ecbuf + ECRDOFF + 723 sizeof (struct ether_header) + off; 724 } else 725 len = totlen; 726 if (len >= CLBYTES) { 727 struct mbuf *p; 728 729 MCLGET(p, 1); 730 if (p != 0) { 731 m->m_len = len = CLBYTES; 732 m->m_off = (int)p - (int)m; 733 } else { 734 m->m_len = len = MIN(MLEN, len); 735 m->m_off = MMINOFF; 736 } 737 } else { 738 m->m_len = len = MIN(MLEN, len); 739 m->m_off = MMINOFF; 740 } 741 mcp = mtod(m, u_char *); 742 if (words = (len >> 1)) { 743 register u_short *to, *from; 744 745 to = (u_short *)mcp; 746 from = (u_short *)cp; 747 do 748 *to++ = *from++; 749 while (--words > 0); 750 mcp = (u_char *)to; 751 cp = (u_char *)from; 752 } 753 if (len & 01) 754 *mcp++ = *cp++; 755 *mp = m; 756 mp = &m->m_next; 757 if (off == 0) { 758 totlen -= len; 759 continue; 760 } 761 off += len; 762 if (off == totlen) { 763 cp = ecbuf + ECRDOFF + sizeof (struct ether_header); 764 off = 0; 765 totlen = off0; 766 } 767 } 768 return (top); 769 bad: 770 m_freem(top); 771 return (0); 772 } 773 774 /* 775 * Process an ioctl request. 776 */ 777 ecioctl(ifp, cmd, data) 778 register struct ifnet *ifp; 779 int cmd; 780 caddr_t data; 781 { 782 register struct ifreq *ifr = (struct ifreq *)data; 783 int s = splimp(), error = 0; 784 785 switch (cmd) { 786 787 case SIOCSIFADDR: 788 if (ifp->if_flags & IFF_RUNNING) 789 if_rtinit(ifp, -1); /* delete previous route */ 790 ecsetaddr(ifp, (struct sockaddr_in *)&ifr->ifr_addr); 791 ecinit(ifp->if_unit); 792 break; 793 794 default: 795 error = EINVAL; 796 } 797 splx(s); 798 return (error); 799 } 800 801 ecsetaddr(ifp, sin) 802 register struct ifnet *ifp; 803 register struct sockaddr_in *sin; 804 { 805 806 ifp->if_addr = *(struct sockaddr *)sin; 807 ifp->if_net = in_netof(sin->sin_addr); 808 ifp->if_host[0] = in_lnaof(sin->sin_addr); 809 sin = (struct sockaddr_in *)&ifp->if_broadaddr; 810 sin->sin_family = AF_INET; 811 sin->sin_addr = if_makeaddr(ifp->if_net, INADDR_ANY); 812 ifp->if_flags |= IFF_BROADCAST; 813 } 814