1 /* if_ace.c 1.8 86/01/26 */ 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[] = { 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, usetrailers; 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, &usetrailers)) 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 (usetrailers && off > 0 && (off & 0x1ff) == 0 && 498 m->m_off >= MMINOFF + 2 * sizeof (u_short)) { 499 type = ETHERTYPE_TRAIL + (off>>9); 500 m->m_off -= 2 * sizeof (u_short); 501 m->m_len += 2 * sizeof (u_short); 502 *mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP); 503 *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len); 504 goto gottrailertype; 505 } 506 type = ETHERTYPE_IP; 507 off = 0; 508 goto gottype; 509 #endif 510 #ifdef NS 511 case AF_NS: 512 bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), 513 (caddr_t)edst, sizeof (edst)); 514 if (!bcmp((caddr_t)edst, (caddr_t)&ns_broadhost,sizeof(edst))) 515 mcopy = m_copy(m, 0, (int)M_COPYALL); 516 else if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, 517 sizeof(edst))) 518 return(looutput(&loif, m, dst)); 519 type = ETHERTYPE_NS; 520 off = 0; 521 goto gottype; 522 #endif 523 case AF_UNSPEC: 524 ace = (struct ether_header *)dst->sa_data; 525 bcopy((caddr_t)ace->ether_dhost, (caddr_t)edst, sizeof (edst)); 526 type = ace->ether_type; 527 goto gottype; 528 529 default: 530 log(LOG_ERR, "ace%d: can't handle af%d\n", 531 ifp->if_unit, dst->sa_family); 532 error = EAFNOSUPPORT; 533 goto bad; 534 } 535 536 gottrailertype: 537 /* 538 * Packet to be sent as trailer: move first packet 539 * (control information) to end of chain. 540 */ 541 while (m->m_next) 542 m = m->m_next; 543 m->m_next = m0; 544 m = m0->m_next; 545 m0->m_next = 0; 546 m0 = m; 547 548 gottype: 549 /* 550 * Add local net header. If no space in first mbuf, 551 * allocate another. 552 */ 553 if (m->m_off > MMAXOFF || 554 MMINOFF + sizeof (struct ether_header) > m->m_off) { 555 m = m_get(M_DONTWAIT, MT_HEADER); 556 if (m == 0) { 557 error = ENOBUFS; 558 goto bad; 559 } 560 m->m_next = m0; 561 m->m_off = MMINOFF; 562 m->m_len = sizeof (struct ether_header); 563 } else { 564 m->m_off -= sizeof (struct ether_header); 565 m->m_len += sizeof (struct ether_header); 566 } 567 ace = mtod(m, struct ether_header *); 568 bcopy((caddr_t)edst, (caddr_t)ace->ether_dhost, sizeof (edst)); 569 bcopy((caddr_t)is->is_addr, (caddr_t)ace->ether_shost, 570 sizeof (is->is_addr)); 571 ace->ether_type = htons((u_short)type); 572 573 /* 574 * Queue message on interface, and start output if interface 575 * not yet active. 576 */ 577 s = splimp(); 578 if (IF_QFULL(&ifp->if_snd)) { 579 IF_DROP(&ifp->if_snd); 580 error = ENOBUFS; 581 goto qfull; 582 } 583 IF_ENQUEUE(&ifp->if_snd, m); 584 splx(s); 585 acestart(ifp->if_unit); 586 return (mcopy ? looutput(&loif, mcopy, dst) : 0); 587 qfull: 588 m0 = m; 589 splx(s); 590 bad: 591 m_freem(m0); 592 if (mcopy) 593 m_freem(mcopy); 594 return (error); 595 } 596 597 /* 598 * Routine to copy from mbuf chain to transmit buffer on the VERSAbus 599 * If packet size is less than the minimum legal size, 600 * the buffer is expanded. We probably should zero out the extra 601 * bytes for security, but that would slow things down. 602 */ 603 /*ARGSUSED*/ 604 aceput(unit, txbuf, m) 605 int unit; 606 char *txbuf; 607 struct mbuf *m; 608 { 609 register u_char *bp, *mcp; 610 register short *s1, *s2; 611 register u_int len; 612 register struct mbuf *mp; 613 int total; 614 615 total = 0; 616 bp = (u_char *)txbuf; 617 for (mp = m; (mp); mp = mp->m_next) { 618 len = mp->m_len; 619 if (len == 0) 620 continue; 621 total += len; 622 mcp = mtod(mp, u_char *); 623 if (((int)mcp & 01) && ((int)bp & 01)) { 624 /* source & destination at odd addresses */ 625 movob(bp++, *mcp++); 626 --len; 627 } 628 if (len > 1 && (((int)mcp & 01)==0) && (((int)bp & 01)==0)) { 629 register u_int l; 630 631 s1 = (short *)bp; 632 s2 = (short *)mcp; 633 l = len >> 1; /* count # of shorts */ 634 while (l-- != 0) 635 movow(s1++, *s2++); 636 len &= 1; /* # remaining bytes */ 637 bp = (u_char *)s1; 638 mcp = (u_char *)s2; 639 } 640 while (len-- != 0) 641 movob(bp++, *mcp++); 642 } 643 m_freem(m); 644 return (total); 645 } 646 647 /* 648 * Routine to copy from VERSAbus memory into mbufs. 649 * 650 * Warning: This makes the fairly safe assumption that 651 * mbufs have even lengths. 652 */ 653 /*ARGSUSED*/ 654 struct mbuf * 655 aceget(rxbuf, totlen, off0, ifp) 656 u_char *rxbuf; 657 int totlen, off0; 658 struct ifnet *ifp; 659 { 660 register u_char *cp, *mcp; 661 register int tlen; 662 register struct mbuf *m; 663 struct mbuf *top = 0, **mp = ⊤ 664 int len, off = off0; 665 666 cp = rxbuf + sizeof (struct ether_header); 667 while (totlen > 0) { 668 MGET(m, M_DONTWAIT, MT_DATA); 669 if (m == 0) 670 goto bad; 671 if (off) { 672 len = totlen - off; 673 cp = rxbuf + sizeof (struct ether_header) + off; 674 } else 675 len = totlen; 676 if (ifp) 677 len += sizeof(ifp); 678 if (len >= CLBYTES) { 679 struct mbuf *p; 680 681 MCLGET(p, 1); 682 if (p != 0) { 683 m->m_len = len = CLBYTES; 684 m->m_off = (int)p - (int)m; 685 } else { 686 m->m_len = len = MIN(MLEN, len); 687 m->m_off = MMINOFF; 688 } 689 } else { 690 m->m_len = len = MIN(MLEN, len); 691 m->m_off = MMINOFF; 692 } 693 mcp = mtod(m, u_char *); 694 if (ifp) { 695 /* 696 * Prepend interface pointer to first mbuf. 697 */ 698 *(mtod(m, struct ifnet **)) = ifp; 699 mcp += sizeof(ifp); 700 len -= sizeof(ifp); 701 ifp = (struct ifnet *)0; 702 } 703 /*bcopy((caddr_t)cp, (caddr_t)mcp, len);*/ 704 /*cp += len; mcp += len;*/ 705 tlen = len; 706 if (((int)mcp & 01) && ((int)cp & 01)) { 707 /* source & destination at odd addresses */ 708 *mcp++ = *cp++; 709 --tlen; 710 } 711 if (tlen > 1 && (((int)mcp&01) == 0) && (((int)cp&01) == 0)) { 712 register short *s1, *s2; 713 register int l; 714 715 s1 = (short *)mcp; 716 s2 = (short *)cp; 717 l = tlen >> 1; /* count # of shorts */ 718 while (l-- > 0) /* copy shorts */ 719 *s1++ = *s2++; 720 tlen &= 1; /* # remaining bytes */ 721 mcp = (u_char *)s1; 722 cp = (u_char *)s2; 723 } 724 while (tlen-- > 0) 725 *mcp++ = *cp++; 726 *mp = m; 727 mp = &m->m_next; 728 if (off == 0) { 729 totlen -= len; 730 continue; 731 } 732 off += len; 733 if (off == totlen) { 734 cp = rxbuf + sizeof (struct ether_header); 735 off = 0; 736 totlen = off0; 737 } 738 } 739 return (top); 740 bad: 741 m_freem(top); 742 return (0); 743 } 744 745 acebakoff(is, txseg, retries) 746 struct ace_softc *is; 747 struct tx_segment *txseg; 748 register int retries; 749 { 750 register short *pBakNum, random_num; 751 short *pMask; 752 753 pMask = &random_mask_tbl[0]; 754 pBakNum = &txseg->tx_backoff[0]; 755 while (--retries >= 0) { 756 random_num = (is->is_currnd = (is->is_currnd * 18741)-13849); 757 random_num &= *pMask++; 758 *pBakNum++ = random_num ^ (short)(0xFF00 | 0x00FC); 759 } 760 } 761 762 /* 763 * Process an ioctl request. 764 */ 765 aceioctl(ifp, cmd, data) 766 register struct ifnet *ifp; 767 int cmd; 768 caddr_t data; 769 { 770 register struct ifaddr *ifa = (struct ifaddr *)data; 771 struct acedevice *addr; 772 int s = splimp(), error = 0; 773 774 switch (cmd) { 775 776 case SIOCSIFADDR: 777 ifp->if_flags |= IFF_UP; 778 switch (ifa->ifa_addr.sa_family) { 779 #ifdef INET 780 case AF_INET: 781 aceinit(ifp->if_unit); /* before arpwhohas */ 782 ((struct arpcom *)ifp)->ac_ipaddr = 783 IA_SIN(ifa)->sin_addr; 784 arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); 785 break; 786 #endif 787 #ifdef NS 788 case AF_NS: { 789 struct ns_addr *ina = &IA_SNS(ifa)->sns_addr; 790 struct ace_softc *is = &ace_softc[ifp->if_unit]; 791 792 if (!ns_nullhost(*ina)) { 793 ifp->if_flags &= ~IFF_RUNNING; 794 addr = (struct acedevice *) 795 aceinfo[ifp->if_unit]->ui_addr; 796 movow(&addr->csr, CSR_RESET); 797 DELAY(10000); 798 /* set station address & copy addr to arp */ 799 acesetetaddr(ifp->if_unit, addr, 800 ina->x_host.c_host); 801 } else 802 ina->x_host = *(union ns_host *)is->is_addr; 803 aceinit(ifp->if_unit); 804 break; 805 } 806 #endif 807 default: 808 aceinit(ifp->if_unit); 809 break; 810 } 811 break; 812 813 case SIOCSIFFLAGS: 814 if ((ifp->if_flags&IFF_UP) == 0 && ifp->if_flags&IFF_RUNNING) { 815 addr = (struct acedevice *) 816 (aceinfo[ifp->if_unit]->ui_addr); 817 movow(&addr->csr, CSR_RESET); 818 ifp->if_flags &= ~IFF_RUNNING; 819 } else if (ifp->if_flags&IFF_UP && 820 (ifp->if_flags&IFF_RUNNING) == 0) 821 aceinit(ifp->if_unit); 822 break; 823 824 default: 825 error = EINVAL; 826 } 827 splx(s); 828 return (error); 829 } 830 831 acesetup(unit) 832 int unit; 833 { 834 register struct ace_softc *is = &ace_softc[unit]; 835 register char *pData1; 836 register short i; 837 struct acedevice *addr; 838 839 bzero(is->is_dpm, 16384*2); 840 is->is_currnd = 49123; 841 addr = (struct acedevice *)aceinfo[unit]->ui_addr; 842 is->is_segboundry = (addr->segb >> 11) & 0xf; 843 pData1 = is->is_dpm + (is->is_segboundry << 11); 844 for (i = SEG_MAX + 1 - is->is_segboundry; --i >= 0;) { 845 acebakoff(is, (struct tx_segment *)pData1, 15); 846 pData1 += sizeof (struct tx_segment); 847 } 848 is->is_eictr = 0; 849 is->is_eoctr = is->is_txnext = is->is_segboundry; 850 bzero((char *)&is->is_stats, sizeof (is->is_stats)); 851 } 852 #endif 853