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.2 (Berkeley) 11/08/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 26 * 27 * The Western Digital card is one of many AT/MCA ethernet interfaces 28 * based on the National N8390/NS32490 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/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, NS32490 */ 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 NS32490 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 NS32490). 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 NS32490 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 #define WD_I_CONFIG 0xff 275 outb(sc->we_io_nic_addr + WD_P0_IMR, WD_I_CONFIG); 276 wecmd.cs_ps = 1; 277 outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte); 278 for (i = 0; i < ETHER_ADDR_LEN; ++i) 279 outb(sc->we_io_nic_addr + WD_P1_PAR0 + i, sc->we_addr[i]); 280 for (i = 0; i < ETHER_ADDR_LEN; ++i) /* == broadcast addr */ 281 outb(sc->we_io_nic_addr + WD_P1_MAR0 + i, 0xff); 282 outb(sc->we_io_nic_addr + WD_P1_CURR, WD_TXBUF_SIZE); 283 wecmd.cs_ps = 0; 284 wecmd.cs_stp = 0; 285 wecmd.cs_sta = 1; 286 wecmd.cs_rd = 0x4; 287 outb(sc->we_io_nic_addr + WD_P1_COMMAND, wecmd.cs_byte); 288 outb(sc->we_io_nic_addr + WD_P0_RCR, WD_R_CONFIG); 289 290 /* 291 * Take the interface out of reset, program the vector, 292 * enable interrupts, and tell the world we are up. 293 */ 294 ifp->if_flags |= IFF_UP | IFF_RUNNING; 295 sc->we_flags |= WDF_RUNNING; 296 sc->we_flags &= ~WDF_TXBUSY; 297 (void) splx(s); 298 westart(unit); 299 } 300 301 /* 302 * Start output on interface. 303 */ 304 westart(unit) 305 int unit; 306 { 307 register struct we_softc *sc = &we_softc[unit]; 308 struct mbuf *m0, *m; 309 register caddr_t buffer; 310 int len = 0, s; 311 union we_command wecmd; 312 313 /* 314 * The NS32490 has only one transmit buffer, if it is busy we 315 * must wait until the transmit interrupt completes. 316 */ 317 s = splhigh(); 318 if (sc->we_flags & WDF_TXBUSY) { 319 (void) splx(s); 320 return; 321 } 322 IF_DEQUEUE(&sc->we_if.if_snd, m); 323 if (m == 0) { 324 (void) splx(s); 325 return; 326 } 327 sc->we_flags |= WDF_TXBUSY; 328 (void) splx(s); 329 330 /* 331 * Copy the mbuf chain into the transmit buffer 332 */ 333 buffer = sc->we_vmem_addr; 334 for (m0 = m; m != 0; m = m->m_next) { 335 bcopy(mtod(m, caddr_t), buffer, m->m_len); 336 buffer += m->m_len; 337 len += m->m_len; 338 } 339 340 /* 341 * If this was a broadcast packet loop it 342 * back because the hardware can't hear its own 343 * transmits. 344 */ 345 #ifdef notyet 346 if (bcmp((caddr_t)(mtod(m0, struct ether_header *)->ether_dhost), 347 (caddr_t)etherbroadcastaddr, 348 sizeof(etherbroadcastaddr)) == 0) { 349 weread(sc, m0); 350 } else { 351 #endif 352 m_freem(m0); 353 #ifdef notyet 354 } 355 #endif 356 357 /* 358 * Init transmit length registers, and set transmit start flag. 359 */ 360 s = splhigh(); 361 len = MAX(len, ETHER_MIN_LEN); 362 wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND); 363 wecmd.cs_ps = 0; 364 outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte); 365 outb(sc->we_io_nic_addr + WD_P0_TBCR0, len & 0xff); 366 outb(sc->we_io_nic_addr + WD_P0_TBCR1, len >> 8); 367 wecmd.cs_txp = 1; 368 outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte); 369 (void) splx(s); 370 } 371 372 /* 373 * Ethernet interface interrupt processor 374 */ 375 weintr(unit) 376 int unit; 377 { 378 register struct we_softc *sc = &we_softc[0]; 379 union we_command wecmd; 380 union we_interrupt weisr; 381 int s; 382 unit =0; 383 384 /* disable onboard interrupts, then get interrupt status */ 385 s = splhigh(); 386 wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND); 387 wecmd.cs_ps = 0; 388 outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte); 389 /* outb(sc->we_io_nic_addr + WD_P0_IMR, 0); */ 390 weisr.is_byte = inb(sc->we_io_nic_addr + WD_P0_ISR); 391 #ifdef notdef 392 printf("weintr %x ", inb(sc->we_io_nic_addr + WD_P0_ISR)); 393 outb(sc->we_io_nic_addr+WD_P0_IMR,0xff); 394 #endif 395 outb(sc->we_io_nic_addr + WD_P0_ISR, 0xff); 396 (void) splx(s); 397 398 /* transmit error */ 399 if (weisr.is_txe) { 400 printf("txe\n"); 401 /* need to read these registers to clear status */ 402 sc->we_if.if_collisions += 403 inb(sc->we_io_nic_addr + WD_P0_TBCR0); 404 ++sc->we_if.if_oerrors; 405 } 406 407 /* receiver error */ 408 if (weisr.is_rxe) { 409 printf("rxe\n"); 410 /* need to read these registers to clear status */ 411 (void) inb(sc->we_io_nic_addr + 0xD); 412 (void) inb(sc->we_io_nic_addr + 0xE); 413 (void) inb(sc->we_io_nic_addr + 0xF); 414 ++sc->we_if.if_ierrors; 415 } 416 417 /* normal transmit complete */ 418 if (weisr.is_ptx) 419 wetint (unit); 420 421 /* normal receive notification */ 422 if (weisr.is_prx) 423 werint (unit); 424 425 /* try to start transmit */ 426 westart(unit); 427 428 /* re-enable onboard interrupts */ 429 wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND); 430 wecmd.cs_ps = 0; 431 outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte); 432 outb(sc->we_io_nic_addr + WD_P0_IMR, WD_I_CONFIG); 433 } 434 435 /* 436 * Ethernet interface transmit interrupt. 437 */ 438 wetint(unit) 439 int unit; 440 { 441 register struct we_softc *sc = &we_softc[unit]; 442 443 /* 444 * Do some statistics (assume page zero of NIC mapped in) 445 */ 446 sc->we_flags &= ~WDF_TXBUSY; 447 sc->we_if.if_timer = 0; 448 ++sc->we_if.if_opackets; 449 sc->we_if.if_collisions += inb(sc->we_io_nic_addr + WD_P0_TBCR0); 450 } 451 452 /* 453 * Ethernet interface receiver interrupt. 454 */ 455 werint(unit) 456 int unit; 457 { 458 register struct we_softc *sc = &we_softc[unit]; 459 register struct mbuf **m; 460 int mlen, len, count; 461 u_char bnry, curr; 462 union we_command wecmd; 463 struct we_ring *wer; 464 struct mbuf *m0; 465 caddr_t pkt, endp; 466 static Bdry; 467 468 /* 469 * Traverse the receive ring looking for packets to pass back. 470 * The search is complete when we find a descriptor not in use. 471 */ 472 wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND); 473 wecmd.cs_ps = 0; 474 outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte); 475 bnry = inb(sc->we_io_nic_addr + WD_P0_BNRY); 476 wecmd.cs_ps = 1; 477 outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte); 478 curr = inb(sc->we_io_nic_addr + WD_P1_CURR); 479 printf("Bd %x cur %x ", bnry, curr); 480 if(Bdry && Bdry > bnry){ 481 bnry =Bdry; 482 printf("bd %x! ", bnry); 483 } 484 while (bnry != curr) 485 { 486 /* get pointer to this buffer header structure */ 487 wer = (struct we_ring *)(sc->we_vmem_addr + (bnry << 8)); 488 len = wer->we_count - 4; /* count includes CRC */ 489 printf("l %d", len); 490 pkt = (caddr_t)(wer + 1) /*- 2*/; /* 2 - word align pkt data */ 491 count = len /*+ 2*/; /* copy two extra bytes */ 492 endp = (caddr_t)(sc->we_vmem_addr + sc->we_vmem_size); 493 ++sc->we_if.if_ipackets; 494 495 /* pull packet out of dual ported RAM */ 496 m = &m0; m0 = 0; 497 while (count > 0) 498 { 499 /* drop chain if can't get another buffer */ 500 MGET(*m, M_DONTWAIT, MT_DATA); 501 if (*m == 0) 502 { 503 m_freem(m0); 504 goto outofbufs; 505 } 506 507 /* fill mbuf and attach to packet list */ 508 mlen = MIN(MLEN, count); 509 mlen = MIN(mlen, endp - pkt); 510 bcopy(pkt, mtod(*m, caddr_t), mlen); 511 (*m)->m_len = mlen; 512 m = &((*m)->m_next); 513 pkt += mlen; 514 count -= mlen; 515 516 /* wrap memory pointer around circ buffer */ 517 if (pkt == endp) 518 pkt = (caddr_t)sc->we_vmem_ring; 519 } 520 521 /* skip aligment bytes, send packet up to higher levels */ 522 if (m0 != 0) 523 { 524 /* m0->m_off += 2*/; 525 weread(sc, m0); 526 } 527 528 outofbufs: 529 /* advance on chip Boundry register */ 530 printf("nx %x ", wer->we_next_packet); 531 bnry = wer->we_next_packet; 532 wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND); 533 wecmd.cs_ps = 0; 534 outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte); 535 536 /* watch out for NIC overflow, reset Boundry if invalid */ 537 if ((bnry - 1) < WD_TXBUF_SIZE) { 538 #ifdef notdef 539 wereset(unit, 0); 540 break; 541 #else 542 outb(sc->we_io_nic_addr + WD_P0_BNRY, 543 (sc->we_vmem_size / WD_PAGE_SIZE) - 1); 544 #endif 545 } 546 outb(sc->we_io_nic_addr + WD_P0_BNRY, bnry-1); 547 548 /* refresh our copy of CURR */ 549 wecmd.cs_ps = 1; 550 outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte); 551 curr = inb(sc->we_io_nic_addr + WD_P1_CURR); 552 printf("bd %x cur %x ", bnry-1, curr); 553 } 554 printf("bD %x\n", bnry); 555 Bdry = bnry; 556 } 557 558 /* 559 * Ethernet output routine. 560 * Encapsulate a packet of type family for the local net. 561 */ 562 weoutput(ifp, m0, dst) 563 struct ifnet *ifp; 564 struct mbuf *m0; 565 struct sockaddr *dst; 566 { 567 int type, s, error; 568 u_char edst[6]; 569 struct in_addr idst; 570 register struct we_softc *sc = &we_softc[ifp->if_unit]; 571 register struct mbuf *m = m0; 572 register struct ether_header *eh; 573 int usetrailers; 574 575 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { 576 error = ENETDOWN; 577 goto bad; 578 } 579 580 switch (dst->sa_family) { 581 582 #ifdef INET 583 case AF_INET: 584 /* Note: we ignore usetrailers */ 585 idst = ((struct sockaddr_in *)dst)->sin_addr; 586 if (!arpresolve(&sc->we_ac, m, &idst, edst, &usetrailers)) 587 return (0); /* if not yet resolved */ 588 type = ETHERTYPE_IP; 589 break; 590 #endif 591 #ifdef NS 592 case AF_NS: 593 type = ETHERTYPE_NS; 594 bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), 595 (caddr_t)edst, sizeof (edst)); 596 break; 597 #endif 598 599 600 case AF_UNSPEC: 601 eh = (struct ether_header *)dst->sa_data; 602 bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst)); 603 type = eh->ether_type; 604 break; 605 606 default: 607 printf("we%d: can't handle af%d\n", ifp->if_unit, 608 dst->sa_family); 609 error = EAFNOSUPPORT; 610 goto bad; 611 } 612 613 /* 614 * Add local net header. If no space in first mbuf, 615 * allocate another. 616 */ 617 if (m->m_off > MMAXOFF || MMINOFF + ETHER_HDR_SIZE > m->m_off) { 618 m = m_get(M_DONTWAIT, MT_HEADER); 619 if (m == 0) { 620 error = ENOBUFS; 621 goto bad; 622 } 623 m->m_next = m0; 624 m->m_off = MMINOFF; 625 m->m_len = ETHER_HDR_SIZE; 626 } else { 627 m->m_off -= ETHER_HDR_SIZE; 628 m->m_len += ETHER_HDR_SIZE; 629 } 630 eh = mtod(m, struct ether_header *); 631 eh->ether_type = htons((u_short)type); 632 bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst)); 633 bcopy((caddr_t)sc->we_addr, (caddr_t)eh->ether_shost, 634 sizeof (sc->we_addr)); 635 636 /* 637 * Queue message on interface, and start output if interface 638 * not yet active. 639 */ 640 s = splimp(); 641 if (IF_QFULL(&ifp->if_snd)) { 642 IF_DROP(&ifp->if_snd); 643 (void) splx(s); 644 m_freem(m); 645 return (ENOBUFS); 646 } 647 IF_ENQUEUE(&ifp->if_snd, m); 648 (void) splx(s); 649 westart(ifp->if_unit); 650 return (0); 651 652 bad: 653 m_freem(m0); 654 return (error); 655 } 656 657 /* 658 * Process an ioctl request. 659 */ 660 weioctl(ifp, cmd, data) 661 register struct ifnet *ifp; 662 int cmd; 663 caddr_t data; 664 { 665 struct we_softc *sc = &we_softc[ifp->if_unit]; 666 struct ifaddr *ifa = (struct ifaddr *)data; 667 int s = splimp(), error = 0; 668 669 switch (cmd) { 670 671 case SIOCSIFADDR: 672 ifp->if_flags |= IFF_UP; 673 weinit(ifp->if_unit); 674 switch(ifa->ifa_addr.sa_family) { 675 #ifdef INET 676 case AF_INET: 677 ((struct arpcom *)ifp)->ac_ipaddr = 678 IA_SIN(ifa)->sin_addr; 679 arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); 680 break; 681 #endif 682 #ifdef NS 683 case AF_NS: 684 { 685 register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); 686 687 if (ns_nullhost(*ina)) 688 ina->x_host = *(union ns_host *)(sc->we_addr); 689 else 690 wesetaddr(ina->x_host.c_host, ifp->if_unit); 691 break; 692 } 693 #endif 694 } 695 break; 696 697 case SIOCSIFFLAGS: 698 if (((ifp->if_flags & IFF_UP) == 0) && 699 (sc->we_flags & WDF_RUNNING)) { 700 westop(ifp->if_unit); 701 } else if (((ifp->if_flags & IFF_UP) == IFF_UP) && 702 ((sc->we_flags & WDF_RUNNING) == 0)) 703 weinit(ifp->if_unit); 704 break; 705 706 default: 707 error = EINVAL; 708 709 } 710 (void) splx(s); 711 return (error); 712 } 713 714 /* 715 * set ethernet address for unit 716 */ 717 wesetaddr(physaddr, unit) 718 u_char *physaddr; 719 int unit; 720 { 721 register struct we_softc *sc = &we_softc[unit]; 722 register int i; 723 724 /* 725 * Rewrite ethernet address, and then force restart of NIC 726 */ 727 for (i = 0; i < ETHER_ADDR_LEN; i++) 728 sc->we_addr[i] = physaddr[i]; 729 sc->we_flags &= ~WDF_RUNNING; 730 weinit(unit); 731 } 732 733 /* 734 * Pass a packet to the higher levels. 735 * NO TRAILER PROTOCOL! 736 */ 737 weread(sc, m) 738 register struct we_softc *sc; 739 struct mbuf *m; 740 { 741 struct ether_header *eh; 742 int scn, type, s; 743 struct ifqueue *inq; 744 745 /* 746 * Get ethernet protocol type out of ether header 747 */ 748 eh = mtod(m, struct ether_header *); 749 type = ntohs((u_short)eh->ether_type); 750 751 /* 752 * Drop ethernet header 753 */ 754 m->m_off += ETHER_HDR_SIZE; 755 m->m_len -= ETHER_HDR_SIZE; 756 757 /* 758 * Insert ifp pointer at start of packet 759 */ 760 m->m_off -= sizeof (struct ifnet *); 761 m->m_len += sizeof (struct ifnet *); 762 *(mtod(m, struct ifnet **)) = &sc->we_if; 763 764 printf("ty %x ", type); 765 switch (type) { 766 767 #ifdef INET 768 case ETHERTYPE_IP: 769 printf("ip "); 770 scn = NETISR_IP; 771 inq = &ipintrq; 772 break; 773 774 case ETHERTYPE_ARP: 775 printf("arp "); 776 arpinput(&sc->we_ac, m); 777 return; 778 #endif 779 #ifdef NS 780 case ETHERTYPE_NS: 781 scn = NETISR_NS; 782 inq = &nsintrq; 783 break; 784 785 #endif 786 787 default: 788 m_freem(m); 789 return; 790 } 791 792 s = splimp(); 793 if (IF_QFULL(inq)) { 794 IF_DROP(inq); 795 m_freem(m); 796 } else 797 IF_ENQUEUE(inq, m); 798 schednetisr(scn); 799 (void) splx(s); 800 } 801 802 #endif 803