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