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