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