1 /*- 2 * Copyright (c) 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Tim L. Tucker 7 * 8 * %sccs.include.noredist.c% 9 * 10 * @(#)if_we.c 5.4 (Berkeley) 11/18/90 11 */ 12 13 /* 14 * Modification history 15 * 16 * 8/28/89 - Initial version(if_wd.c), Tim L Tucker 17 */ 18 19 #include "we.h" 20 #if NWE > 0 21 /* 22 * Western Digital 8003 ethernet/starlan adapter 23 * 24 * Supports the following interface cards: 25 * WD8003E, WD8003EBT, WD8003S, WD8003SBT, WD8013EBT 26 * 27 * The Western Digital card is one of many AT/MCA ethernet interfaces 28 * based on the National DS8390 Network Interface chip set. 29 */ 30 #include "param.h" 31 #include "mbuf.h" 32 #include "socket.h" 33 #include "ioctl.h" 34 #include "errno.h" 35 #include "syslog.h" 36 37 #include "../net/if.h" 38 #include "../net/netisr.h" 39 40 #ifdef INET 41 #include "../netinet/in.h" 42 #include "../netinet/in_systm.h" 43 #include "../netinet/in_var.h" 44 #include "../netinet/ip.h" 45 #include "../netinet/if_ether.h" 46 #endif 47 48 #ifdef NS 49 #include "../netns/ns.h" 50 #include "../netns/ns_if.h" 51 #endif 52 53 #include "machine/isa/if_wereg.h" 54 #include "machine/isa/isa_device.h" 55 56 /* 57 * This constant should really be 60 because the we adds 4 bytes of crc. 58 * However when set to 60 our packets are ignored by deuna's , 3coms are 59 * okay ?????????????????????????????????????????? 60 */ 61 #define ETHER_MIN_LEN 64 62 #define ETHER_ADDR_LEN 6 63 #define ETHER_HDR_SIZE 14 64 65 /* 66 * Ethernet software status per interface. 67 * 68 * Each interface is referenced by a network interface structure, 69 * qe_if, which the routing code uses to locate the interface. 70 * This structure contains the output queue for the interface, its address, ... 71 */ 72 struct we_softc { 73 struct arpcom we_ac; /* Ethernet common part */ 74 #define we_if we_ac.ac_if /* network-visible interface */ 75 #define we_addr we_ac.ac_enaddr /* hardware Ethernet address */ 76 77 u_char we_flags; /* software state */ 78 #define WDF_RUNNING 0x01 79 #define WDF_TXBUSY 0x02 80 81 u_char we_type; /* interface type code */ 82 u_short we_vector; /* interrupt vector */ 83 caddr_t we_io_ctl_addr; /* i/o bus address, control */ 84 caddr_t we_io_nic_addr; /* i/o bus address, DS8390 */ 85 86 caddr_t we_vmem_addr; /* card RAM virtual memory base */ 87 u_long we_vmem_size; /* card RAM bytes */ 88 caddr_t we_vmem_ring; /* receive ring RAM vaddress */ 89 } we_softc[NWE]; 90 91 int weprobe(), weattach(), weintr(); 92 int weinit(), weoutput(), weioctl(), wereset(); 93 94 struct isa_driver wedriver = { 95 weprobe, weattach, "we", 96 }; 97 98 /* 99 * Probe the WD8003 to see if it's there 100 */ 101 weprobe(is) 102 struct isa_device *is; 103 { 104 register int i; 105 register struct we_softc *sc = &we_softc[is->id_unit]; 106 union we_mem_sel wem; 107 u_char sum; 108 109 /* 110 * Here we check the card ROM, if the checksum passes, and the 111 * type code and ethernet address check out, then we know we have 112 * a wd8003 card. 113 * 114 * Autoconfiguration: No warning message is printed on error. 115 */ 116 for (sum = 0, i = 0; i < 8; ++i) 117 sum += inb(is->id_iobase + WD_ROM_OFFSET + i); 118 if (sum != WD_CHECKSUM) 119 return (0); 120 sc->we_type = inb(is->id_iobase + WD_ROM_OFFSET + 6); 121 if ((sc->we_type != WD_ETHER) && (sc->we_type != WD_STARLAN) 122 && (sc->we_type != WD_ETHER2)) 123 return (0); 124 125 /* 126 * Setup card RAM area and i/o addresses 127 * Kernel Virtual to segment C0000-DFFFF????? 128 */ 129 sc->we_io_ctl_addr = is->id_iobase; 130 sc->we_io_nic_addr = sc->we_io_ctl_addr + WD_NIC_OFFSET; 131 sc->we_vector = is->id_irq; 132 sc->we_vmem_addr = (caddr_t)is->id_maddr; 133 sc->we_vmem_size = is->id_msize; 134 sc->we_vmem_ring = sc->we_vmem_addr + (WD_PAGE_SIZE * WD_TXBUF_SIZE); 135 136 /* 137 * Save board ROM station address 138 */ 139 for (i = 0; i < ETHER_ADDR_LEN; ++i) 140 sc->we_addr[i] = inb(sc->we_io_ctl_addr + WD_ROM_OFFSET + i); 141 142 /* 143 * Mapin interface memory, setup memory select register 144 */ 145 /* wem.ms_addr = (u_long)sc->we_vmem_addr >> 13; */ 146 wem.ms_addr = (u_long)(0xd0000)>> 13; 147 wem.ms_enable = 1; 148 wem.ms_reset = 0; 149 outb(sc->we_io_ctl_addr, wem.ms_byte); 150 151 /* 152 * clear interface memory, then sum to make sure its valid 153 */ 154 for (i = 0; i < sc->we_vmem_size; ++i) 155 sc->we_vmem_addr[i] = 0x0; 156 for (sum = 0, i = 0; i < sc->we_vmem_size; ++i) 157 sum += sc->we_vmem_addr[i]; 158 if (sum != 0x0) { 159 printf("we%d: wd8003 dual port RAM address error\n", is->id_unit); 160 return (0); 161 } 162 163 return (WD_IO_PORTS); 164 } 165 166 /* 167 * Interface exists: make available by filling in network interface 168 * record. System will initialize the interface when it is ready 169 * to accept packets. 170 */ 171 weattach(is) 172 struct isa_device *is; 173 { 174 register struct we_softc *sc = &we_softc[is->id_unit]; 175 register struct ifnet *ifp = &sc->we_if; 176 177 /* 178 * Initialize ifnet structure 179 */ 180 ifp->if_unit = is->id_unit; 181 ifp->if_name = "we"; 182 ifp->if_mtu = ETHERMTU; 183 ifp->if_flags = IFF_BROADCAST|IFF_NOTRAILERS; 184 ifp->if_init = weinit; 185 ifp->if_output = weoutput; 186 ifp->if_ioctl = weioctl; 187 ifp->if_reset = wereset; 188 ifp->if_watchdog = 0; 189 if_attach(ifp); 190 191 /* 192 * Banner... 193 */ 194 printf(" %s address %s", 195 ((sc->we_type != WD_STARLAN) ? "ethernet" : "starlan"), 196 ether_sprintf(sc->we_addr)); 197 } 198 199 /* 200 * Reset of interface. 201 */ 202 wereset(unit, uban) 203 int unit, uban; 204 { 205 if (unit >= NWE) 206 return; 207 printf("we%d: reset\n", unit); 208 we_softc[unit].we_flags &= ~WDF_RUNNING; 209 weinit(unit); 210 } 211 212 /* 213 * Take interface offline. 214 */ 215 westop(unit) 216 int unit; 217 { 218 register struct we_softc *sc = &we_softc[unit]; 219 union we_command wecmd; 220 int s; 221 222 /* 223 * Shutdown DS8390 224 */ 225 s = splimp(); 226 wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND); 227 wecmd.cs_stp = 1; 228 wecmd.cs_sta = 0; 229 wecmd.cs_ps = 0; 230 outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte); 231 (void) splx(s); 232 } 233 234 /* 235 * Initialization of interface (really just DS8390). 236 */ 237 weinit(unit) 238 int unit; 239 { 240 register struct we_softc *sc = &we_softc[unit]; 241 register struct ifnet *ifp = &sc->we_if; 242 union we_command wecmd; 243 int i, s; 244 245 /* address not known */ 246 if (ifp->if_addrlist == (struct ifaddr *)0) 247 return; 248 249 /* already running */ 250 if (sc->we_flags & WDF_RUNNING) 251 return; 252 253 /* 254 * Initialize DS8390 in order given in NSC NIC manual. 255 * this is stock code...please see the National manual for details. 256 */ 257 s = splhigh(); 258 wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND); 259 wecmd.cs_stp = 1; 260 wecmd.cs_sta = 0; 261 wecmd.cs_ps = 0; 262 outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte); 263 outb(sc->we_io_nic_addr + WD_P0_DCR, WD_D_CONFIG); 264 outb(sc->we_io_nic_addr + WD_P0_RBCR0, 0); 265 outb(sc->we_io_nic_addr + WD_P0_RBCR1, 0); 266 outb(sc->we_io_nic_addr + WD_P0_RCR, WD_R_MON); 267 outb(sc->we_io_nic_addr + WD_P0_TCR, WD_T_CONFIG); 268 outb(sc->we_io_nic_addr + WD_P0_TPSR, 0); 269 outb(sc->we_io_nic_addr + WD_P0_PSTART, WD_TXBUF_SIZE); 270 outb(sc->we_io_nic_addr + WD_P0_PSTOP, 271 sc->we_vmem_size / WD_PAGE_SIZE); 272 outb(sc->we_io_nic_addr + WD_P0_BNRY, WD_TXBUF_SIZE); 273 outb(sc->we_io_nic_addr + WD_P0_ISR, 0xff); 274 outb(sc->we_io_nic_addr + WD_P0_IMR, WD_I_CONFIG); 275 wecmd.cs_ps = 1; 276 outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte); 277 for (i = 0; i < ETHER_ADDR_LEN; ++i) 278 outb(sc->we_io_nic_addr + WD_P1_PAR0 + i, sc->we_addr[i]); 279 for (i = 0; i < ETHER_ADDR_LEN; ++i) /* == broadcast addr */ 280 outb(sc->we_io_nic_addr + WD_P1_MAR0 + i, 0xff); 281 outb(sc->we_io_nic_addr + WD_P1_CURR, WD_TXBUF_SIZE); 282 wecmd.cs_ps = 0; 283 wecmd.cs_stp = 0; 284 wecmd.cs_sta = 1; 285 wecmd.cs_rd = 0x4; 286 outb(sc->we_io_nic_addr + WD_P1_COMMAND, wecmd.cs_byte); 287 outb(sc->we_io_nic_addr + WD_P0_RCR, WD_R_CONFIG); 288 289 /* 290 * Take the interface out of reset, program the vector, 291 * enable interrupts, and tell the world we are up. 292 */ 293 ifp->if_flags |= IFF_UP | IFF_RUNNING; 294 sc->we_flags |= WDF_RUNNING; 295 sc->we_flags &= ~WDF_TXBUSY; 296 (void) splx(s); 297 westart(unit); 298 } 299 300 /* 301 * Start output on interface. 302 */ 303 westart(unit) 304 int unit; 305 { 306 register struct we_softc *sc = &we_softc[unit]; 307 struct mbuf *m0, *m; 308 register caddr_t buffer; 309 int len = 0, s; 310 union we_command wecmd; 311 312 /* 313 * The DS8390 has only one transmit buffer, if it is busy we 314 * must wait until the transmit interrupt completes. 315 */ 316 s = splhigh(); 317 if (sc->we_flags & WDF_TXBUSY) { 318 (void) splx(s); 319 return; 320 } 321 IF_DEQUEUE(&sc->we_if.if_snd, m); 322 if (m == 0) { 323 (void) splx(s); 324 return; 325 } 326 sc->we_flags |= WDF_TXBUSY; 327 (void) splx(s); 328 329 /* 330 * Copy the mbuf chain into the transmit buffer 331 */ 332 buffer = sc->we_vmem_addr; 333 for (m0 = m; m != 0; m = m->m_next) { 334 bcopy(mtod(m, caddr_t), buffer, m->m_len); 335 buffer += m->m_len; 336 len += m->m_len; 337 } 338 339 /* 340 * If this was a broadcast packet loop it 341 * back because the hardware can't hear its own 342 * transmits. 343 */ 344 if (bcmp((caddr_t)(mtod(m0, struct ether_header *)->ether_dhost), 345 (caddr_t)etherbroadcastaddr, 346 sizeof(etherbroadcastaddr)) == 0) { 347 weread(sc, m0); 348 } else { 349 m_freem(m0); 350 } 351 352 /* 353 * Init transmit length registers, and set transmit start flag. 354 */ 355 s = splhigh(); 356 len = MAX(len, ETHER_MIN_LEN); 357 wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND); 358 wecmd.cs_ps = 0; 359 outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte); 360 outb(sc->we_io_nic_addr + WD_P0_TBCR0, len & 0xff); 361 outb(sc->we_io_nic_addr + WD_P0_TBCR1, len >> 8); 362 wecmd.cs_txp = 1; 363 outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte); 364 (void) splx(s); 365 } 366 367 /* 368 * Ethernet interface interrupt processor 369 */ 370 weintr(unit) 371 int unit; 372 { 373 register struct we_softc *sc = &we_softc[0]; 374 union we_command wecmd; 375 union we_interrupt weisr; 376 int s; 377 unit =0; 378 379 /* disable onboard interrupts, then get interrupt status */ 380 s = splhigh(); 381 wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND); 382 wecmd.cs_ps = 0; 383 outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte); 384 outb(sc->we_io_nic_addr + WD_P0_IMR, 0); 385 weisr.is_byte = inb(sc->we_io_nic_addr + WD_P0_ISR); 386 outb(sc->we_io_nic_addr + WD_P0_ISR, 0xff); 387 (void) splx(s); 388 389 /* transmit error */ 390 if (weisr.is_txe) { 391 /* need to read these registers to clear status */ 392 sc->we_if.if_collisions += 393 inb(sc->we_io_nic_addr + WD_P0_TBCR0); 394 ++sc->we_if.if_oerrors; 395 } 396 397 /* receiver error */ 398 if (weisr.is_rxe) { 399 /* need to read these registers to clear status */ 400 (void) inb(sc->we_io_nic_addr + 0xD); 401 (void) inb(sc->we_io_nic_addr + 0xE); 402 (void) inb(sc->we_io_nic_addr + 0xF); 403 ++sc->we_if.if_ierrors; 404 } 405 406 /* normal transmit complete */ 407 if (weisr.is_ptx) 408 wetint (unit); 409 410 /* normal receive notification */ 411 if (weisr.is_prx) 412 werint (unit); 413 414 /* try to start transmit */ 415 westart(unit); 416 417 /* re-enable onboard interrupts */ 418 wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND); 419 wecmd.cs_ps = 0; 420 outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte); 421 outb(sc->we_io_nic_addr + WD_P0_IMR, WD_I_CONFIG); 422 } 423 424 /* 425 * Ethernet interface transmit interrupt. 426 */ 427 wetint(unit) 428 int unit; 429 { 430 register struct we_softc *sc = &we_softc[unit]; 431 432 /* 433 * Do some statistics (assume page zero of NIC mapped in) 434 */ 435 sc->we_flags &= ~WDF_TXBUSY; 436 sc->we_if.if_timer = 0; 437 ++sc->we_if.if_opackets; 438 sc->we_if.if_collisions += inb(sc->we_io_nic_addr + WD_P0_TBCR0); 439 } 440 441 /* 442 * Ethernet interface receiver interrupt. 443 */ 444 werint(unit) 445 int unit; 446 { 447 register struct we_softc *sc = &we_softc[unit]; 448 register struct mbuf **m; 449 int mlen, len, count; 450 u_char bnry, curr; 451 union we_command wecmd; 452 struct we_ring *wer; 453 struct mbuf *m0; 454 caddr_t pkt, endp; 455 static Bdry; 456 457 /* 458 * Traverse the receive ring looking for packets to pass back. 459 * The search is complete when we find a descriptor not in use. 460 */ 461 wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND); 462 wecmd.cs_ps = 0; 463 outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte); 464 bnry = inb(sc->we_io_nic_addr + WD_P0_BNRY); 465 wecmd.cs_ps = 1; 466 outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte); 467 curr = inb(sc->we_io_nic_addr + WD_P1_CURR); 468 if(Bdry && Bdry > bnry) 469 bnry =Bdry; 470 while (bnry != curr) 471 { 472 /* get pointer to this buffer header structure */ 473 wer = (struct we_ring *)(sc->we_vmem_addr + (bnry << 8)); 474 len = wer->we_count - 4; /* count includes CRC */ 475 pkt = (caddr_t)(wer + 1) /*- 2*/; /* 2 - word align pkt data */ 476 count = len /*+ 2*/; /* copy two extra bytes */ 477 endp = (caddr_t)(sc->we_vmem_addr + sc->we_vmem_size); 478 ++sc->we_if.if_ipackets; 479 480 /* pull packet out of dual ported RAM */ 481 m = &m0; m0 = 0; 482 while (count > 0) 483 { 484 /* drop chain if can't get another buffer */ 485 MGET(*m, M_DONTWAIT, MT_DATA); 486 if (*m == 0) 487 { 488 m_freem(m0); 489 goto outofbufs; 490 } 491 492 /* fill mbuf and attach to packet list */ 493 mlen = MIN(MLEN, count); 494 mlen = MIN(mlen, endp - pkt); 495 bcopy(pkt, mtod(*m, caddr_t), mlen); 496 (*m)->m_len = mlen; 497 m = &((*m)->m_next); 498 pkt += mlen; 499 count -= mlen; 500 501 /* wrap memory pointer around circ buffer */ 502 if (pkt == endp) 503 pkt = (caddr_t)sc->we_vmem_ring; 504 } 505 506 /* skip aligment bytes, send packet up to higher levels */ 507 if (m0 != 0) 508 { 509 /* m0->m_off += 2*/; 510 weread(sc, m0); 511 } 512 513 outofbufs: 514 /* advance on chip Boundry register */ 515 bnry = wer->we_next_packet; 516 wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND); 517 wecmd.cs_ps = 0; 518 outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte); 519 520 /* watch out for NIC overflow, reset Boundry if invalid */ 521 if ((bnry - 1) < WD_TXBUF_SIZE) { 522 #ifdef notdef 523 wereset(unit, 0); 524 break; 525 #else 526 outb(sc->we_io_nic_addr + WD_P0_BNRY, 527 (sc->we_vmem_size / WD_PAGE_SIZE) - 1); 528 #endif 529 } 530 outb(sc->we_io_nic_addr + WD_P0_BNRY, bnry-1); 531 532 /* refresh our copy of CURR */ 533 wecmd.cs_ps = 1; 534 outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte); 535 curr = inb(sc->we_io_nic_addr + WD_P1_CURR); 536 } 537 Bdry = bnry; 538 } 539 540 /* 541 * Ethernet output routine. 542 * Encapsulate a packet of type family for the local net. 543 */ 544 weoutput(ifp, m0, dst) 545 struct ifnet *ifp; 546 struct mbuf *m0; 547 struct sockaddr *dst; 548 { 549 int type, s, error; 550 u_char edst[6]; 551 struct in_addr idst; 552 register struct we_softc *sc = &we_softc[ifp->if_unit]; 553 register struct mbuf *m = m0; 554 register struct ether_header *eh; 555 int usetrailers; 556 557 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { 558 error = ENETDOWN; 559 goto bad; 560 } 561 562 switch (dst->sa_family) { 563 564 #ifdef INET 565 case AF_INET: 566 /* Note: we ignore usetrailers */ 567 idst = ((struct sockaddr_in *)dst)->sin_addr; 568 if (!arpresolve(&sc->we_ac, m, &idst, edst, &usetrailers)) 569 return (0); /* if not yet resolved */ 570 type = ETHERTYPE_IP; 571 break; 572 #endif 573 #ifdef NS 574 case AF_NS: 575 type = ETHERTYPE_NS; 576 bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), 577 (caddr_t)edst, sizeof (edst)); 578 break; 579 #endif 580 581 582 case AF_UNSPEC: 583 eh = (struct ether_header *)dst->sa_data; 584 bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst)); 585 type = eh->ether_type; 586 break; 587 588 default: 589 printf("we%d: can't handle af%d\n", ifp->if_unit, 590 dst->sa_family); 591 error = EAFNOSUPPORT; 592 goto bad; 593 } 594 595 /* 596 * Add local net header. If no space in first mbuf, 597 * allocate another. 598 */ 599 if (m->m_off > MMAXOFF || MMINOFF + ETHER_HDR_SIZE > m->m_off) { 600 m = m_get(M_DONTWAIT, MT_HEADER); 601 if (m == 0) { 602 error = ENOBUFS; 603 goto bad; 604 } 605 m->m_next = m0; 606 m->m_off = MMINOFF; 607 m->m_len = ETHER_HDR_SIZE; 608 } else { 609 m->m_off -= ETHER_HDR_SIZE; 610 m->m_len += ETHER_HDR_SIZE; 611 } 612 eh = mtod(m, struct ether_header *); 613 eh->ether_type = htons((u_short)type); 614 bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst)); 615 bcopy((caddr_t)sc->we_addr, (caddr_t)eh->ether_shost, 616 sizeof (sc->we_addr)); 617 618 /* 619 * Queue message on interface, and start output if interface 620 * not yet active. 621 */ 622 s = splimp(); 623 if (IF_QFULL(&ifp->if_snd)) { 624 IF_DROP(&ifp->if_snd); 625 (void) splx(s); 626 m_freem(m); 627 return (ENOBUFS); 628 } 629 IF_ENQUEUE(&ifp->if_snd, m); 630 (void) splx(s); 631 westart(ifp->if_unit); 632 return (0); 633 634 bad: 635 m_freem(m0); 636 return (error); 637 } 638 639 /* 640 * Process an ioctl request. 641 */ 642 weioctl(ifp, cmd, data) 643 register struct ifnet *ifp; 644 int cmd; 645 caddr_t data; 646 { 647 struct we_softc *sc = &we_softc[ifp->if_unit]; 648 struct ifaddr *ifa = (struct ifaddr *)data; 649 int s = splimp(), error = 0; 650 651 switch (cmd) { 652 653 case SIOCSIFADDR: 654 ifp->if_flags |= IFF_UP; 655 weinit(ifp->if_unit); 656 switch(ifa->ifa_addr.sa_family) { 657 #ifdef INET 658 case AF_INET: 659 ((struct arpcom *)ifp)->ac_ipaddr = 660 IA_SIN(ifa)->sin_addr; 661 arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); 662 break; 663 #endif 664 #ifdef NS 665 case AF_NS: 666 { 667 register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); 668 669 if (ns_nullhost(*ina)) 670 ina->x_host = *(union ns_host *)(sc->we_addr); 671 else 672 wesetaddr(ina->x_host.c_host, ifp->if_unit); 673 break; 674 } 675 #endif 676 } 677 break; 678 679 case SIOCSIFFLAGS: 680 if (((ifp->if_flags & IFF_UP) == 0) && 681 (sc->we_flags & WDF_RUNNING)) { 682 westop(ifp->if_unit); 683 } else if (((ifp->if_flags & IFF_UP) == IFF_UP) && 684 ((sc->we_flags & WDF_RUNNING) == 0)) 685 weinit(ifp->if_unit); 686 break; 687 688 default: 689 error = EINVAL; 690 691 } 692 (void) splx(s); 693 return (error); 694 } 695 696 /* 697 * set ethernet address for unit 698 */ 699 wesetaddr(physaddr, unit) 700 u_char *physaddr; 701 int unit; 702 { 703 register struct we_softc *sc = &we_softc[unit]; 704 register int i; 705 706 /* 707 * Rewrite ethernet address, and then force restart of NIC 708 */ 709 for (i = 0; i < ETHER_ADDR_LEN; i++) 710 sc->we_addr[i] = physaddr[i]; 711 sc->we_flags &= ~WDF_RUNNING; 712 weinit(unit); 713 } 714 715 /* 716 * Pass a packet to the higher levels. 717 * NO TRAILER PROTOCOL! 718 */ 719 weread(sc, m) 720 register struct we_softc *sc; 721 struct mbuf *m; 722 { 723 struct ether_header *eh; 724 int scn, type, s; 725 struct ifqueue *inq; 726 727 /* 728 * Get ethernet protocol type out of ether header 729 */ 730 eh = mtod(m, struct ether_header *); 731 type = ntohs((u_short)eh->ether_type); 732 733 /* 734 * Drop ethernet header 735 */ 736 m->m_off += ETHER_HDR_SIZE; 737 m->m_len -= ETHER_HDR_SIZE; 738 739 /* 740 * Insert ifp pointer at start of packet 741 */ 742 m->m_off -= sizeof (struct ifnet *); 743 m->m_len += sizeof (struct ifnet *); 744 *(mtod(m, struct ifnet **)) = &sc->we_if; 745 746 switch (type) { 747 748 #ifdef INET 749 case ETHERTYPE_IP: 750 scn = NETISR_IP; 751 inq = &ipintrq; 752 break; 753 754 case ETHERTYPE_ARP: 755 arpinput(&sc->we_ac, m); 756 return; 757 #endif 758 #ifdef NS 759 case ETHERTYPE_NS: 760 scn = NETISR_NS; 761 inq = &nsintrq; 762 break; 763 764 #endif 765 766 default: 767 m_freem(m); 768 return; 769 } 770 771 s = splimp(); 772 if (IF_QFULL(inq)) { 773 IF_DROP(inq); 774 m_freem(m); 775 } else 776 IF_ENQUEUE(inq, m); 777 schednetisr(scn); 778 (void) splx(s); 779 } 780 781 #endif 782