1 /* if_ace.c 1.6 86/01/21 */ 2 3 /* 4 * ACC VERSAbus Ethernet controller 5 */ 6 #include "ace.h" 7 #if NACE > 0 8 9 #include "../machine/pte.h" 10 11 #include "param.h" 12 #include "systm.h" 13 #include "mbuf.h" 14 #include "buf.h" 15 #include "protosw.h" 16 #include "socket.h" 17 #include "vmmac.h" 18 #include "ioctl.h" 19 #include "errno.h" 20 #include "vmparam.h" 21 #include "syslog.h" 22 23 #include "../net/if.h" 24 #include "../net/netisr.h" 25 #include "../net/route.h" 26 #ifdef INET 27 #include "../netinet/in.h" 28 #include "../netinet/in_systm.h" 29 #include "../netinet/in_var.h" 30 #include "../netinet/ip.h" 31 #include "../netinet/ip_var.h" 32 #include "../netinet/if_ether.h" 33 #endif 34 #ifdef NS 35 #include "../netns/ns.h" 36 #include "../netns/ns_if.h" 37 #endif 38 39 #include "../tahoe/mtpr.h" 40 #include "../tahoeif/if_acereg.h" 41 #include "../tahoevba/vbavar.h" 42 43 /* station address */ 44 char ace_station[6] = { ~0x8, ~0x0, ~0x3, ~0x0, ~0x0, ~0x1 }; 45 /* multicast hash table initializer */ 46 char ace_hash[8] = { ~0xF,~0xF,~0xF,~0xF,~0xF,~0xF,~0xF,~0xF }; 47 /* backoff table masks */ 48 short random_mask_tbl[16] = { 49 0x0040, 0x00C0, 0x01C0, 0x03C0, 0x07C0, 0x0FC0, 0x1FC0, 0x3FC0, 50 0x7FC0, 0xFFC0, 0xFFC0, 0xFFC0, 0xFFC0, 0xFFC0, 0xFFC0, 0xFFC0 51 }; 52 53 int aceprobe(), aceattach(), acerint(), acecint(); 54 struct vba_device *aceinfo[NACE]; 55 long acestd[] = { 0x0ff0000, 0xff0100, 0 }; 56 struct vba_driver acedriver = 57 { aceprobe, 0, aceattach, 0, acestd, "ace", aceinfo, "v/eiu", 0 }; 58 59 int aceinit(), aceoutput(), aceioctl(), acereset(); 60 struct mbuf *aceget(); 61 62 /* 63 * Ethernet software status per interface. 64 * 65 * Each interface is referenced by a network interface structure, 66 * is_if, which the routing code uses to locate the interface. 67 * This structure contains the output queue for the interface, its address, ... 68 */ 69 struct ace_softc { 70 struct arpcom is_ac; /* Ethernet common part */ 71 #define is_if is_ac.ac_if /* network-visible interface */ 72 #define is_addr is_ac.ac_enaddr /* hardware Ethernet address */ 73 short is_flags; 74 #define ACEF_OACTIVE 0x1 /* output is active */ 75 #define ACEF_RCVPENDING 0x2 /* start rcv in acecint */ 76 short is_promiscuous; /* true is enabled */ 77 short is_segboundry; /* first TX Seg in dpm */ 78 short is_eictr; /* Rx segment tracking ctr */ 79 short is_eoctr; /* Tx segment tracking ctr */ 80 short is_txnext; /* Next available Tx segment */ 81 short is_currnd; /* current random backoff */ 82 struct ace_stats is_stats; /* holds board statistics */ 83 short is_xcnt; /* count xmitted segments to be acked 84 by the controller */ 85 long is_ivec; /* autoconfig interrupt vector base */ 86 struct pte *is_map; /* pte map for dual ported memory */ 87 caddr_t is_dpm; /* address of mapped memory */ 88 } ace_softc[NACE]; 89 extern struct ifnet loif; 90 91 aceprobe(reg, vi) 92 caddr_t reg; 93 struct vba_device *vi; 94 { 95 register br, cvec; /* must be r12, r11 */ 96 struct acedevice *ap = (struct acedevice *)reg; 97 struct ace_softc *is = &ace_softc[vi->ui_unit]; 98 99 #ifdef lint 100 acerint(0); acecint(0); 101 #endif 102 if (badaddr(reg, 2)) 103 return (0); 104 movow(&ap->csr, CSR_RESET); 105 DELAY(10000); 106 #ifdef notdef 107 /* 108 * Select two spaces for the interrupts aligned to an 109 * eight vector boundary and fitting in 8 bits (as 110 * required by the controller) -- YECH. The controller 111 * will be notified later at initialization time. 112 */ 113 if ((vi->ui_hd->vh_lastiv -= 2) > 0xff) 114 vi->ui_hd->vh_lastiv = 0x200; 115 is->is_ivec = vi->ui_hd->vh_lastiv = vi->ui_hd->vh_lastiv &~ 0x7; 116 #else 117 is->is_ivec = 0x90+vi->ui_unit*8; 118 #endif 119 br = 0x14, cvec = is->is_ivec; /* XXX */ 120 return (sizeof (*ap)); 121 } 122 123 /* 124 * Interface exists: make available by filling in network interface 125 * record. System will initialize the interface when it is ready 126 * to accept packets. 127 */ 128 aceattach(ui) 129 struct vba_device *ui; 130 { 131 register short unit = ui->ui_unit; 132 register struct ace_softc *is = &ace_softc[unit]; 133 register struct ifnet *ifp = &is->is_if; 134 register struct acedevice *addr = (struct acedevice *)ui->ui_addr; 135 register short *wp, i; 136 137 ifp->if_unit = unit; 138 ifp->if_name = "ace"; 139 ifp->if_mtu = ETHERMTU; 140 /* 141 * Set station's addresses and multicast hash table. 142 */ 143 ace_station[5] = ~(unit + 1); 144 acesetetaddr(unit, addr, ace_station); 145 is->is_promiscuous = 0; 146 wp = (short *)addr->hash; 147 for (i = 0; i < 8; i++) 148 movow(wp++, ace_hash[i]); 149 movow(&addr->bcastena[0], ~0xffff); 150 movow(&addr->bcastena[1], ~0xffff); 151 /* 152 * Allocate and map dual ported VERSAbus memory. 153 */ 154 vbmemalloc(32, (caddr_t)ui->ui_flags, &is->is_map, &is->is_dpm); 155 156 ifp->if_init = aceinit; 157 ifp->if_output = aceoutput; 158 ifp->if_ioctl = aceioctl; 159 ifp->if_reset = acereset; 160 ifp->if_flags = IFF_BROADCAST; 161 if_attach(ifp); 162 } 163 164 acesetetaddr(unit, addr, station_addr) 165 short unit; 166 struct acedevice *addr; 167 char *station_addr; 168 { 169 register short *wp, i; 170 register char *cp; 171 struct ace_softc *is = &ace_softc[unit]; 172 173 wp = (short *)addr->station; 174 cp = station_addr; 175 for (i = 0; i < 6; i++) 176 movow(wp++, *cp++); 177 wp = (short *)addr->station; 178 cp = (char *)is->is_addr; 179 for (i = 0; i < 6; i++) 180 *cp++ = ~(*wp++); 181 } 182 183 /* 184 * Reset of interface after "system" reset. 185 */ 186 acereset(unit, vban) 187 int unit, vban; 188 { 189 register struct vba_device *ui; 190 191 if (unit >= NACE || (ui = aceinfo[unit]) == 0 || ui->ui_alive == 0 || 192 ui->ui_vbanum != vban) 193 return; 194 printf(" ace%d", unit); 195 aceinit(unit); 196 } 197 198 /* 199 * Initialization of interface; clear recorded pending operations 200 */ 201 aceinit(unit) 202 int unit; 203 { 204 register struct ace_softc *is = &ace_softc[unit]; 205 register struct vba_device *ui = aceinfo[unit]; 206 register struct acedevice *addr; 207 register struct ifnet *ifp = &is->is_if; 208 register short Csr; 209 register int s; 210 211 if (ifp->if_addrlist == (struct ifaddr *)0) 212 return; 213 if ((ifp->if_flags & IFF_RUNNING) == 0) { 214 /* 215 * Reset the controller, initialize the recieve buffers, 216 * and turn the controller on again and set board online. 217 */ 218 addr = (struct acedevice *)ui->ui_addr; 219 s = splimp(); 220 movow(&addr->csr, CSR_RESET); 221 DELAY(10000); 222 223 /* 224 * Clean up dpm since the controller might 225 * jumble dpm after reset. 226 */ 227 acesetup(unit); 228 movow(&addr->csr, CSR_GO); 229 Csr = addr->csr; 230 if (Csr & CSR_ACTIVE) { 231 movow(&addr->ivct, is->is_ivec); 232 Csr |= CSR_IENA | is->is_promiscuous; 233 movow(&addr->csr, Csr); 234 is->is_flags = 0; 235 is->is_xcnt = 0; 236 is->is_if.if_flags |= IFF_RUNNING; 237 } 238 splx(s); 239 } 240 if (is->is_if.if_snd.ifq_head) 241 acestart(unit); 242 } 243 244 /* 245 * Start output on interface. 246 * Get another datagram to send off of the interface queue, 247 * and map it to the interface before starting the output. 248 * 249 */ 250 acestart(unit) 251 int unit; 252 { 253 register struct tx_segment *txs; 254 register long len; 255 register int s; 256 register struct ace_softc *is = &ace_softc[unit]; 257 struct mbuf *m; 258 short retries; 259 260 if (is->is_flags & ACEF_OACTIVE) 261 return; 262 is->is_flags |= ACEF_OACTIVE; 263 again: 264 txs = (struct tx_segment*)(is->is_dpm + (is->is_txnext << 11)); 265 if (txs->tx_csr & TCS_TBFULL) { 266 is->is_stats.tx_busy++; 267 is->is_flags &= ~ACEF_OACTIVE; 268 return; 269 } 270 s = splimp(); 271 IF_DEQUEUE(&is->is_if.if_snd, m); 272 splx(s); 273 if (m == 0) { 274 is->is_flags &= ~ACEF_OACTIVE; 275 return; 276 } 277 len = aceput(unit, txs->tx_data, m); 278 retries = txs->tx_csr & TCS_RTC; 279 if (retries > 0) 280 acebakoff(is, txs, retries); 281 282 /* 283 * Ensure minimum packet length. 284 * This makes the safe assumtion that there are no virtual holes 285 * after the data. 286 * For security, it might be wise to zero out the added bytes, 287 * but we're mainly interested in speed at the moment. 288 */ 289 if (len - sizeof (struct ether_header) < ETHERMIN) 290 len = ETHERMIN + sizeof (struct ether_header); 291 if (++is->is_txnext > SEG_MAX) 292 is->is_txnext = is->is_segboundry; 293 is->is_if.if_opackets++; 294 is->is_xcnt++; 295 len = (len & 0x7fff) | TCS_TBFULL; 296 movow(txs, len); 297 goto again; 298 } 299 300 /* 301 * Transmit done interrupt. 302 */ 303 acecint(unit) 304 int unit; 305 { 306 register struct ace_softc *is = &ace_softc[unit]; 307 register struct tx_segment *txseg; 308 short eostat; 309 310 if (is->is_xcnt <= 0) { 311 log(LOG_ERR, "ace%d: stray xmit interrupt, xcnt %d\n", 312 unit, is->is_xcnt); 313 is->is_xcnt = 0; 314 if (is->is_if.if_snd.ifq_head) 315 acestart(unit); 316 return; 317 } 318 is->is_xcnt--; 319 txseg = (struct tx_segment *)((is->is_eoctr << 11) + is->is_dpm); 320 eostat = txseg->tx_csr; 321 if ((eostat & TCS_TBFULL) == 0) { 322 is->is_stats.tx_retries += eostat & TCS_RTC; 323 if (eostat & TCS_RTFAIL) { 324 is->is_stats.tx_discarded++; 325 is->is_if.if_oerrors++; 326 } else 327 is->is_stats.tx_datagrams++; 328 if (++is->is_eoctr >= 16) 329 is->is_eoctr = is->is_segboundry; 330 } 331 if (is->is_if.if_snd.ifq_head) 332 acestart(unit); 333 } 334 335 /* 336 * Ethernet interface receiver interrupt. 337 * If input error just drop packet. 338 * Otherwise purge input buffered data path and examine 339 * packet to determine type. If can't determine length 340 * from type, then have to drop packet. Othewise decapsulate 341 * packet based on type and pass to type specific higher-level 342 * input routine. 343 */ 344 acerint(unit) 345 int unit; 346 { 347 register struct ace_softc *is = &ace_softc[unit]; 348 register struct ifqueue *inq; 349 register struct ether_header *ace; 350 register struct rx_segment *rxseg; 351 int len, s, off, resid; 352 struct mbuf *m; 353 short eistat; 354 355 if ((is->is_if.if_flags&IFF_RUNNING) == 0) 356 return; 357 again: 358 rxseg = (struct rx_segment *)((is->is_eictr << 11) + is->is_dpm); 359 eistat = rxseg->rx_csr; 360 if ((eistat & RCS_RBFULL) == 0) 361 return; 362 is->is_if.if_ipackets++; 363 if (++is->is_eictr >= is->is_segboundry) 364 is->is_eictr = 0; 365 len = eistat & RCS_RBC; 366 if ((eistat & (RCS_ROVRN | RCS_RCRC | RCS_RODD)) || 367 len < ET_MINLEN || len > ET_MAXLEN+CRC_SIZE) { 368 if (eistat & RCS_ROVRN) 369 is->is_stats.rx_overruns++; 370 if (eistat & RCS_RCRC) 371 is->is_stats.rx_crc_errors++; 372 if (eistat & RCS_RODD) 373 is->is_stats.rx_align_errors++; 374 if (len < ET_MINLEN) 375 is->is_stats.rx_underruns++; 376 if (len > ET_MAXLEN+CRC_SIZE) 377 is->is_stats.rx_overruns++; 378 is->is_if.if_ierrors++; 379 rxseg->rx_csr = 0; 380 return; 381 } else 382 is->is_stats.rx_datagrams++; 383 ace = (struct ether_header *)rxseg->rx_data; 384 len -= sizeof (struct ether_header); 385 /* 386 * Deal with trailer protocol: if type is trailer 387 * get true type from first 16-bit word past data. 388 * Remember that type was trailer by setting off. 389 */ 390 ace->ether_type = ntohs((u_short)ace->ether_type); 391 #define acedataaddr(ace, off, type) \ 392 ((type)(((caddr_t)(((char *)ace)+sizeof (struct ether_header))+(off)))) 393 if (ace->ether_type >= ETHERTYPE_TRAIL && 394 ace->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { 395 off = (ace->ether_type - ETHERTYPE_TRAIL) * 512; 396 if (off >= ETHERMTU) 397 goto setup; /* sanity */ 398 ace->ether_type = ntohs(*acedataaddr(ace, off, u_short *)); 399 resid = ntohs(*(acedataaddr(ace, off+2, u_short *))); 400 if (off + resid > len) 401 goto setup; /* sanity */ 402 len = off + resid; 403 } else 404 off = 0; 405 if (len == 0) 406 goto setup; 407 408 /* 409 * Pull packet off interface. Off is nonzero if packet 410 * has trailing header; aceget will then force this header 411 * information to be at the front, but we still have to drop 412 * the type and length which are at the front of any trailer data. 413 */ 414 m = aceget((u_char *)rxseg->rx_data, len, off, &is->is_if); 415 if (m == 0) 416 goto setup; 417 if (off) { 418 struct ifnet *ifp; 419 420 ifp = *(mtod(m, struct ifnet **)); 421 m->m_off += 2 * sizeof (u_short); 422 m->m_len -= 2 * sizeof (u_short); 423 *(mtod(m, struct ifnet **)) = ifp; 424 } 425 switch (ace->ether_type) { 426 427 #ifdef INET 428 case ETHERTYPE_IP: 429 schednetisr(NETISR_IP); 430 inq = &ipintrq; 431 break; 432 #endif 433 434 case ETHERTYPE_ARP: 435 arpinput(&is->is_ac, m); 436 goto setup; 437 #ifdef NS 438 case ETHERTYPE_NS: 439 schednetisr(NETISR_NS); 440 inq = &nsintrq; 441 break; 442 443 #endif 444 default: 445 m_freem(m); 446 goto setup; 447 } 448 if (IF_QFULL(inq)) { 449 IF_DROP(inq); 450 m_freem(m); 451 goto setup; 452 } 453 s = splimp(); 454 IF_ENQUEUE(inq, m); 455 splx(s); 456 setup: 457 rxseg->rx_csr = 0; 458 goto again; 459 } 460 461 /* 462 * Ethernet output routine. 463 * Encapsulate a packet of type family for the local net. 464 * Use trailer local net encapsulation if enough data in first 465 * packet leaves a multiple of 512 bytes of data in remainder. 466 */ 467 aceoutput(ifp, m0, dst) 468 struct ifnet *ifp; 469 struct mbuf *m0; 470 struct sockaddr *dst; 471 { 472 register struct ace_softc *is = &ace_softc[ifp->if_unit]; 473 register struct mbuf *m = m0; 474 register struct ether_header *ace; 475 register int off; 476 struct mbuf *mcopy = (struct mbuf *)0; 477 int type, s, error; 478 u_char edst[6]; 479 struct in_addr idst; 480 481 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { 482 error = ENETDOWN; 483 goto bad; 484 } 485 switch (dst->sa_family) { 486 487 #ifdef INET 488 case AF_INET: 489 idst = ((struct sockaddr_in *)dst)->sin_addr; 490 if (!arpresolve(&is->is_ac, m, &idst, edst)) 491 return (0); /* if not yet resolved */ 492 if (!bcmp((caddr_t)edst, (caddr_t)etherbroadcastaddr, 493 sizeof (edst))) 494 mcopy = m_copy(m, 0, (int)M_COPYALL); 495 off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; 496 /* need per host negotiation */ 497 if ((ifp->if_flags & IFF_NOTRAILERS) == 0 && off > 0 && 498 (off & 0x1ff) == 0 && 499 m->m_off >= MMINOFF + 2 * sizeof (u_short)) { 500 type = ETHERTYPE_TRAIL + (off>>9); 501 m->m_off -= 2 * sizeof (u_short); 502 m->m_len += 2 * sizeof (u_short); 503 *mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP); 504 *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len); 505 goto gottrailertype; 506 } 507 type = ETHERTYPE_IP; 508 off = 0; 509 goto gottype; 510 #endif 511 #ifdef NS 512 case AF_NS: 513 bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), 514 (caddr_t)edst, sizeof (edst)); 515 if (!bcmp((caddr_t)edst, (caddr_t)&ns_broadhost,sizeof(edst))) 516 mcopy = m_copy(m, 0, (int)M_COPYALL); 517 else if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, 518 sizeof(edst))) 519 return(looutput(&loif, m, dst)); 520 type = ETHERTYPE_NS; 521 off = 0; 522 goto gottype; 523 #endif 524 case AF_UNSPEC: 525 ace = (struct ether_header *)dst->sa_data; 526 bcopy((caddr_t)ace->ether_dhost, (caddr_t)edst, sizeof (edst)); 527 type = ace->ether_type; 528 goto gottype; 529 530 default: 531 log(LOG_ERR, "ace%d: can't handle af%d\n", 532 ifp->if_unit, dst->sa_family); 533 error = EAFNOSUPPORT; 534 goto bad; 535 } 536 537 gottrailertype: 538 /* 539 * Packet to be sent as trailer: move first packet 540 * (control information) to end of chain. 541 */ 542 while (m->m_next) 543 m = m->m_next; 544 m->m_next = m0; 545 m = m0->m_next; 546 m0->m_next = 0; 547 m0 = m; 548 549 gottype: 550 /* 551 * Add local net header. If no space in first mbuf, 552 * allocate another. 553 */ 554 if (m->m_off > MMAXOFF || 555 MMINOFF + sizeof (struct ether_header) > m->m_off) { 556 m = m_get(M_DONTWAIT, MT_HEADER); 557 if (m == 0) { 558 error = ENOBUFS; 559 goto bad; 560 } 561 m->m_next = m0; 562 m->m_off = MMINOFF; 563 m->m_len = sizeof (struct ether_header); 564 } else { 565 m->m_off -= sizeof (struct ether_header); 566 m->m_len += sizeof (struct ether_header); 567 } 568 ace = mtod(m, struct ether_header *); 569 bcopy((caddr_t)edst, (caddr_t)ace->ether_dhost, sizeof (edst)); 570 bcopy((caddr_t)is->is_addr, (caddr_t)ace->ether_shost, 571 sizeof (is->is_addr)); 572 ace->ether_type = htons((u_short)type); 573 574 /* 575 * Queue message on interface, and start output if interface 576 * not yet active. 577 */ 578 s = splimp(); 579 if (IF_QFULL(&ifp->if_snd)) { 580 IF_DROP(&ifp->if_snd); 581 error = ENOBUFS; 582 goto qfull; 583 } 584 IF_ENQUEUE(&ifp->if_snd, m); 585 splx(s); 586 acestart(ifp->if_unit); 587 return (mcopy ? looutput(&loif, mcopy, dst) : 0); 588 qfull: 589 m0 = m; 590 splx(s); 591 bad: 592 m_freem(m0); 593 if (mcopy) 594 m_freem(mcopy); 595 return (error); 596 } 597 598 /* 599 * Routine to copy from mbuf chain to transmit buffer on the VERSAbus 600 * If packet size is less than the minimum legal size, 601 * the buffer is expanded. We probably should zero out the extra 602 * bytes for security, but that would slow things down. 603 */ 604 /*ARGSUSED*/ 605 aceput(unit, txbuf, m) 606 int unit; 607 char *txbuf; 608 struct mbuf *m; 609 { 610 register u_char *bp, *mcp; 611 register short *s1, *s2; 612 register u_int len; 613 register struct mbuf *mp; 614 int total; 615 616 total = 0; 617 bp = (u_char *)txbuf; 618 for (mp = m; (mp); mp = mp->m_next) { 619 len = mp->m_len; 620 if (len == 0) 621 continue; 622 total += len; 623 mcp = mtod(mp, u_char *); 624 if (((int)mcp & 01) && ((int)bp & 01)) { 625 /* source & destination at odd addresses */ 626 movob(bp++, *mcp++); 627 --len; 628 } 629 if (len > 1 && (((int)mcp & 01)==0) && (((int)bp & 01)==0)) { 630 register u_int l; 631 632 s1 = (short *)bp; 633 s2 = (short *)mcp; 634 l = len >> 1; /* count # of shorts */ 635 while (l-- != 0) 636 movow(s1++, *s2++); 637 len &= 1; /* # remaining bytes */ 638 bp = (u_char *)s1; 639 mcp = (u_char *)s2; 640 } 641 while (len-- != 0) 642 movob(bp++, *mcp++); 643 } 644 m_freem(m); 645 return (total); 646 } 647 648 /* 649 * Routine to copy from VERSAbus memory into mbufs. 650 * 651 * Warning: This makes the fairly safe assumption that 652 * mbufs have even lengths. 653 */ 654 /*ARGSUSED*/ 655 struct mbuf * 656 aceget(rxbuf, totlen, off0, ifp) 657 u_char *rxbuf; 658 int totlen, off0; 659 struct ifnet *ifp; 660 { 661 register u_char *cp, *mcp; 662 register int tlen; 663 register struct mbuf *m; 664 struct mbuf *top = 0, **mp = ⊤ 665 int len, off = off0; 666 667 cp = rxbuf + sizeof (struct ether_header); 668 while (totlen > 0) { 669 MGET(m, M_DONTWAIT, MT_DATA); 670 if (m == 0) 671 goto bad; 672 if (off) { 673 len = totlen - off; 674 cp = rxbuf + sizeof (struct ether_header) + off; 675 } else 676 len = totlen; 677 if (ifp) 678 len += sizeof(ifp); 679 if (len >= CLBYTES) { 680 struct mbuf *p; 681 682 MCLGET(p, 1); 683 if (p != 0) { 684 m->m_len = len = CLBYTES; 685 m->m_off = (int)p - (int)m; 686 } else { 687 m->m_len = len = MIN(MLEN, len); 688 m->m_off = MMINOFF; 689 } 690 } else { 691 m->m_len = len = MIN(MLEN, len); 692 m->m_off = MMINOFF; 693 } 694 mcp = mtod(m, u_char *); 695 if (ifp) { 696 /* 697 * Prepend interface pointer to first mbuf. 698 */ 699 *(mtod(m, struct ifnet **)) = ifp; 700 mcp += sizeof(ifp); 701 len -= sizeof(ifp); 702 ifp = (struct ifnet *)0; 703 } 704 /*bcopy((caddr_t)cp, (caddr_t)mcp, len);*/ 705 /*cp += len; mcp += len;*/ 706 tlen = len; 707 if (((int)mcp & 01) && ((int)cp & 01)) { 708 /* source & destination at odd addresses */ 709 *mcp++ = *cp++; 710 --tlen; 711 } 712 if (tlen > 1 && (((int)mcp&01) == 0) && (((int)cp&01) == 0)) { 713 register short *s1, *s2; 714 register int l; 715 716 s1 = (short *)mcp; 717 s2 = (short *)cp; 718 l = tlen >> 1; /* count # of shorts */ 719 while (l-- > 0) /* copy shorts */ 720 *s1++ = *s2++; 721 tlen &= 1; /* # remaining bytes */ 722 mcp = (u_char *)s1; 723 cp = (u_char *)s2; 724 } 725 while (tlen-- > 0) 726 *mcp++ = *cp++; 727 *mp = m; 728 mp = &m->m_next; 729 if (off == 0) { 730 totlen -= len; 731 continue; 732 } 733 off += len; 734 if (off == totlen) { 735 cp = rxbuf + sizeof (struct ether_header); 736 off = 0; 737 totlen = off0; 738 } 739 } 740 return (top); 741 bad: 742 m_freem(top); 743 return (0); 744 } 745 746 acebakoff(is, txseg, retries) 747 struct ace_softc *is; 748 struct tx_segment *txseg; 749 register int retries; 750 { 751 register short *pBakNum, random_num; 752 short *pMask; 753 754 pMask = &random_mask_tbl[0]; 755 pBakNum = &txseg->tx_backoff[0]; 756 while (--retries >= 0) { 757 random_num = (is->is_currnd = (is->is_currnd * 18741)-13849); 758 random_num &= *pMask++; 759 *pBakNum++ = random_num ^ (short)(0xFF00 | 0x00FC); 760 } 761 } 762 763 /* 764 * Process an ioctl request. 765 */ 766 aceioctl(ifp, cmd, data) 767 register struct ifnet *ifp; 768 int cmd; 769 caddr_t data; 770 { 771 register struct ifaddr *ifa = (struct ifaddr *)data; 772 struct acedevice *addr; 773 int s = splimp(), error = 0; 774 775 switch (cmd) { 776 777 case SIOCSIFADDR: 778 ifp->if_flags |= IFF_UP; 779 switch (ifa->ifa_addr.sa_family) { 780 #ifdef INET 781 case AF_INET: 782 aceinit(ifp->if_unit); /* before arpwhohas */ 783 ((struct arpcom *)ifp)->ac_ipaddr = 784 IA_SIN(ifa)->sin_addr; 785 arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); 786 break; 787 #endif 788 #ifdef NS 789 case AF_NS: { 790 struct ns_addr *ina = &IA_SNS(ifa)->sns_addr; 791 struct ace_softc *is = &ace_softc[ifp->if_unit]; 792 793 if (!ns_nullhost(*ina)) { 794 ifp->if_flags &= ~IFF_RUNNING; 795 addr = (struct acedevice *) 796 aceinfo[ifp->if_unit]->ui_addr; 797 movow(&addr->csr, CSR_RESET); 798 DELAY(10000); 799 /* set station address & copy addr to arp */ 800 acesetetaddr(ifp->if_unit, addr, 801 ina->x_host.c_host); 802 } else 803 ina->x_host = *(union ns_host *)is->is_addr; 804 aceinit(ifp->if_unit); 805 break; 806 } 807 #endif 808 default: 809 aceinit(ifp->if_unit); 810 break; 811 } 812 break; 813 814 case SIOCSIFFLAGS: 815 if ((ifp->if_flags&IFF_UP) == 0 && ifp->if_flags&IFF_RUNNING) { 816 addr = (struct acedevice *) 817 (aceinfo[ifp->if_unit]->ui_addr); 818 movow(&addr->csr, CSR_RESET); 819 ifp->if_flags &= ~IFF_RUNNING; 820 } else if (ifp->if_flags&IFF_UP && 821 (ifp->if_flags&IFF_RUNNING) == 0) 822 aceinit(ifp->if_unit); 823 break; 824 825 default: 826 error = EINVAL; 827 } 828 splx(s); 829 return (error); 830 } 831 832 acesetup(unit) 833 int unit; 834 { 835 register struct ace_softc *is = &ace_softc[unit]; 836 register char *pData1; 837 register short i; 838 struct acedevice *addr; 839 840 bzero(is->is_dpm, 16384*2); 841 is->is_currnd = 49123; 842 addr = (struct acedevice *)aceinfo[unit]->ui_addr; 843 is->is_segboundry = (addr->segb >> 11) & 0xf; 844 pData1 = is->is_dpm + (is->is_segboundry << 11); 845 for (i = SEG_MAX + 1 - is->is_segboundry; --i >= 0;) { 846 acebakoff(is, (struct tx_segment *)pData1, 15); 847 pData1 += sizeof (struct tx_segment); 848 } 849 is->is_eictr = 0; 850 is->is_eoctr = is->is_txnext = is->is_segboundry; 851 bzero((char *)&is->is_stats, sizeof (is->is_stats)); 852 } 853 #endif 854