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