1 /* if_ace.c 1.4 86/01/20 */ 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 #ifdef notdef 290 if (len - sizeof (struct ether_header) < ETHERMIN) 291 len = ETHERMIN + sizeof (struct ether_header); 292 #else 293 if (len - 14 < ETHERMIN) 294 len = ETHERMIN + 14; 295 #endif 296 if (++is->is_txnext > SEG_MAX) 297 is->is_txnext = is->is_segboundry; 298 is->is_if.if_opackets++; 299 is->is_xcnt++; 300 len = (len & 0x7fff) | TCS_TBFULL; 301 movow(txs, len); 302 goto again; 303 } 304 305 /* 306 * Transmit done interrupt. 307 */ 308 acecint(unit) 309 int unit; 310 { 311 register struct ace_softc *is = &ace_softc[unit]; 312 register struct tx_segment *txseg; 313 short eostat; 314 315 if (is->is_xcnt <= 0) { 316 log(LOG_ERR, "ace%d: stray xmit interrupt, xcnt %d\n", 317 unit, is->is_xcnt); 318 is->is_xcnt = 0; 319 if (is->is_if.if_snd.ifq_head) 320 acestart(unit); 321 return; 322 } 323 is->is_xcnt--; 324 txseg = (struct tx_segment *)((is->is_eoctr << 11) + is->is_dpm); 325 eostat = txseg->tx_csr; 326 if ((eostat & TCS_TBFULL) == 0) { 327 is->is_stats.tx_retries += eostat & TCS_RTC; 328 if (eostat & TCS_RTFAIL) { 329 is->is_stats.tx_discarded++; 330 is->is_if.if_oerrors++; 331 } else 332 is->is_stats.tx_datagrams++; 333 if (++is->is_eoctr >= 16) 334 is->is_eoctr = is->is_segboundry; 335 } 336 if (is->is_if.if_snd.ifq_head) 337 acestart(unit); 338 } 339 340 /* 341 * Ethernet interface receiver interrupt. 342 * If input error just drop packet. 343 * Otherwise purge input buffered data path and examine 344 * packet to determine type. If can't determine length 345 * from type, then have to drop packet. Othewise decapsulate 346 * packet based on type and pass to type specific higher-level 347 * input routine. 348 */ 349 acerint(unit) 350 int unit; 351 { 352 register struct ace_softc *is = &ace_softc[unit]; 353 register struct ifqueue *inq; 354 register struct ether_header *ace; 355 register struct rx_segment *rxseg; 356 int len, s, off, resid; 357 struct mbuf *m; 358 short eistat; 359 360 if ((is->is_if.if_flags&IFF_RUNNING) == 0) 361 return; 362 again: 363 rxseg = (struct rx_segment *)((is->is_eictr << 11) + is->is_dpm); 364 eistat = rxseg->rx_csr; 365 if ((eistat & RCS_RBFULL) == 0) 366 return; 367 is->is_if.if_ipackets++; 368 if (++is->is_eictr >= is->is_segboundry) 369 is->is_eictr = 0; 370 len = eistat & RCS_RBC; 371 if ((eistat & (RCS_ROVRN | RCS_RCRC | RCS_RODD)) || 372 len < ET_MINLEN || len > ET_MAXLEN+CRC_SIZE) { 373 if (eistat & RCS_ROVRN) 374 is->is_stats.rx_overruns++; 375 if (eistat & RCS_RCRC) 376 is->is_stats.rx_crc_errors++; 377 if (eistat & RCS_RODD) 378 is->is_stats.rx_align_errors++; 379 if (len < ET_MINLEN) 380 is->is_stats.rx_underruns++; 381 if (len > ET_MAXLEN+CRC_SIZE) 382 is->is_stats.rx_overruns++; 383 is->is_if.if_ierrors++; 384 rxseg->rx_csr = 0; 385 return; 386 } else 387 is->is_stats.rx_datagrams++; 388 ace = (struct ether_header *)rxseg->rx_data; 389 #ifdef notdef 390 len -= sizeof (struct ether_header); 391 #else 392 len -= 14; 393 #endif 394 /* 395 * Deal with trailer protocol: if type is trailer 396 * get true type from first 16-bit word past data. 397 * Remember that type was trailer by setting off. 398 */ 399 ace->ether_type = ntohs((u_short)ace->ether_type); 400 #ifdef notdef 401 #define acedataaddr(ace, off, type) \ 402 ((type)(((caddr_t)(((char *)ace)+sizeof (struct ether_header))+(off)))) 403 #else 404 #define acedataaddr(ace, off, type) \ 405 ((type)(((caddr_t)(((char *)ace)+14)+(off)))) 406 #endif 407 if (ace->ether_type >= ETHERTYPE_TRAIL && 408 ace->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { 409 off = (ace->ether_type - ETHERTYPE_TRAIL) * 512; 410 if (off >= ETHERMTU) 411 goto setup; /* sanity */ 412 ace->ether_type = ntohs(*acedataaddr(ace, off, u_short *)); 413 resid = ntohs(*(acedataaddr(ace, off+2, u_short *))); 414 if (off + resid > len) 415 goto setup; /* sanity */ 416 len = off + resid; 417 } else 418 off = 0; 419 if (len == 0) 420 goto setup; 421 422 /* 423 * Pull packet off interface. Off is nonzero if packet 424 * has trailing header; aceget will then force this header 425 * information to be at the front, but we still have to drop 426 * the type and length which are at the front of any trailer data. 427 */ 428 m = aceget((u_char *)rxseg->rx_data, len, off, &is->is_if); 429 if (m == 0) 430 goto setup; 431 if (off) { 432 struct ifnet *ifp; 433 434 ifp = *(mtod(m, struct ifnet **)); 435 m->m_off += 2 * sizeof (u_short); 436 m->m_len -= 2 * sizeof (u_short); 437 *(mtod(m, struct ifnet **)) = ifp; 438 } 439 switch (ace->ether_type) { 440 441 #ifdef INET 442 case ETHERTYPE_IP: 443 schednetisr(NETISR_IP); 444 inq = &ipintrq; 445 break; 446 #endif 447 448 case ETHERTYPE_ARP: 449 arpinput(&is->is_ac, m); 450 goto setup; 451 #ifdef NS 452 case ETHERTYPE_NS: 453 schednetisr(NETISR_NS); 454 inq = &nsintrq; 455 break; 456 457 #endif 458 default: 459 m_freem(m); 460 goto setup; 461 } 462 if (IF_QFULL(inq)) { 463 IF_DROP(inq); 464 m_freem(m); 465 goto setup; 466 } 467 s = splimp(); 468 IF_ENQUEUE(inq, m); 469 splx(s); 470 setup: 471 rxseg->rx_csr = 0; 472 goto again; 473 } 474 475 /* 476 * Ethernet output routine. 477 * Encapsulate a packet of type family for the local net. 478 * Use trailer local net encapsulation if enough data in first 479 * packet leaves a multiple of 512 bytes of data in remainder. 480 */ 481 aceoutput(ifp, m0, dst) 482 struct ifnet *ifp; 483 struct mbuf *m0; 484 struct sockaddr *dst; 485 { 486 register struct ace_softc *is = &ace_softc[ifp->if_unit]; 487 register struct mbuf *m = m0; 488 register struct ether_header *ace; 489 register int off; 490 struct mbuf *mcopy = (struct mbuf *)0; 491 int type, s, error; 492 u_char edst[6]; 493 struct in_addr idst; 494 495 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { 496 error = ENETDOWN; 497 goto bad; 498 } 499 switch (dst->sa_family) { 500 501 #ifdef INET 502 case AF_INET: 503 idst = ((struct sockaddr_in *)dst)->sin_addr; 504 if (!arpresolve(&is->is_ac, m, &idst, edst)) 505 return (0); /* if not yet resolved */ 506 if (!bcmp((caddr_t)edst, (caddr_t)etherbroadcastaddr, 507 sizeof(edst))) 508 mcopy = m_copy(m, 0, (int)M_COPYALL); 509 off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; 510 /* need per host negotiation */ 511 if ((ifp->if_flags & IFF_NOTRAILERS) == 0 && off > 0 && 512 (off & 0x1ff) == 0 && 513 m->m_off >= MMINOFF + 2 * sizeof (u_short)) { 514 type = ETHERTYPE_TRAIL + (off>>9); 515 m->m_off -= 2 * sizeof (u_short); 516 m->m_len += 2 * sizeof (u_short); 517 *mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP); 518 *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len); 519 goto gottrailertype; 520 } 521 type = ETHERTYPE_IP; 522 off = 0; 523 goto gottype; 524 #endif 525 #ifdef NS 526 case AF_NS: 527 bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), 528 (caddr_t)edst, sizeof (edst)); 529 if (!bcmp((caddr_t)edst, (caddr_t)&ns_broadhost,sizeof(edst))) 530 mcopy = m_copy(m, 0, (int)M_COPYALL); 531 else if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, 532 sizeof(edst))) 533 return(looutput(&loif, m, dst)); 534 type = ETHERTYPE_NS; 535 off = 0; 536 goto gottype; 537 #endif 538 case AF_UNSPEC: 539 ace = (struct ether_header *)dst->sa_data; 540 bcopy((caddr_t)ace->ether_dhost, (caddr_t)edst, sizeof (edst)); 541 type = ace->ether_type; 542 goto gottype; 543 544 default: 545 log(LOG_ERR, "ace%d: can't handle af%d\n", 546 ifp->if_unit, dst->sa_family); 547 error = EAFNOSUPPORT; 548 goto bad; 549 } 550 551 gottrailertype: 552 /* 553 * Packet to be sent as trailer: move first packet 554 * (control information) to end of chain. 555 */ 556 while (m->m_next) 557 m = m->m_next; 558 m->m_next = m0; 559 m = m0->m_next; 560 m0->m_next = 0; 561 m0 = m; 562 563 gottype: 564 /* 565 * Add local net header. If no space in first mbuf, 566 * allocate another. 567 */ 568 if (m->m_off > MMAXOFF || 569 #ifdef notdef 570 MMINOFF + sizeof (struct ether_header) > m->m_off) { 571 #else 572 MMINOFF + 14 > m->m_off) { 573 #endif 574 m = m_get(M_DONTWAIT, MT_HEADER); 575 if (m == 0) { 576 error = ENOBUFS; 577 goto bad; 578 } 579 m->m_next = m0; 580 m->m_off = MMINOFF; 581 #ifdef notdef 582 m->m_len = sizeof (struct ether_header); 583 #else 584 m->m_len = 14; 585 #endif 586 } else { 587 #ifdef notdef 588 m->m_off -= sizeof (struct ether_header); 589 m->m_len += sizeof (struct ether_header); 590 #else 591 m->m_off -= 14; 592 m->m_len += 14; 593 #endif 594 } 595 ace = mtod(m, struct ether_header *); 596 bcopy((caddr_t)edst, (caddr_t)ace->ether_dhost, sizeof (edst)); 597 bcopy((caddr_t)is->is_addr, (caddr_t)ace->ether_shost, 598 sizeof (is->is_addr)); 599 ace->ether_type = htons((u_short)type); 600 601 /* 602 * Queue message on interface, and start output if interface 603 * not yet active. 604 */ 605 s = splimp(); 606 if (IF_QFULL(&ifp->if_snd)) { 607 IF_DROP(&ifp->if_snd); 608 error = ENOBUFS; 609 goto qfull; 610 } 611 IF_ENQUEUE(&ifp->if_snd, m); 612 splx(s); 613 acestart(ifp->if_unit); 614 return (mcopy ? looutput(&loif, mcopy, dst) : 0); 615 qfull: 616 m0 = m; 617 splx(s); 618 bad: 619 m_freem(m0); 620 if (mcopy) 621 m_freem(mcopy); 622 return (error); 623 } 624 625 /* 626 * Routine to copy from mbuf chain to transmit buffer on the VERSAbus 627 * If packet size is less than the minimum legal size, 628 * the buffer is expanded. We probably should zero out the extra 629 * bytes for security, but that would slow things down. 630 */ 631 /*ARGSUSED*/ 632 aceput(unit, txbuf, m) 633 int unit; 634 char *txbuf; 635 struct mbuf *m; 636 { 637 register u_char *bp, *mcp; 638 register short *s1, *s2; 639 register u_int len; 640 register struct mbuf *mp; 641 int total; 642 643 total = 0; 644 bp = (u_char *)txbuf; 645 for (mp = m; (mp); mp = mp->m_next) { 646 len = mp->m_len; 647 if (len == 0) 648 continue; 649 total += len; 650 mcp = mtod(mp, u_char *); 651 if (((int)mcp & 01) && ((int)bp & 01)) { 652 /* source & destination at odd addresses */ 653 movob(bp++, *mcp++); 654 --len; 655 } 656 if (len > 1 && (((int)mcp & 01)==0) && (((int)bp & 01)==0)) { 657 register u_int l; 658 659 s1 = (short *)bp; 660 s2 = (short *)mcp; 661 l = len >> 1; /* count # of shorts */ 662 while (l-- != 0) 663 movow(s1++, *s2++); 664 len &= 1; /* # remaining bytes */ 665 bp = (u_char *)s1; 666 mcp = (u_char *)s2; 667 } 668 while (len-- != 0) 669 movob(bp++, *mcp++); 670 } 671 m_freem(m); 672 return (total); 673 } 674 675 /* 676 * Routine to copy from VERSAbus memory into mbufs. 677 * 678 * Warning: This makes the fairly safe assumption that 679 * mbufs have even lengths. 680 */ 681 /*ARGSUSED*/ 682 struct mbuf * 683 aceget(rxbuf, totlen, off0, ifp) 684 u_char *rxbuf; 685 int totlen, off0; 686 struct ifnet *ifp; 687 { 688 register u_char *cp, *mcp; 689 register int tlen; 690 register struct mbuf *m; 691 struct mbuf *top = 0, **mp = ⊤ 692 int len, off = off0; 693 694 #ifdef notdef 695 cp = rxbuf + sizeof (struct ether_header); 696 #else 697 cp = rxbuf + 14; 698 #endif 699 while (totlen > 0) { 700 MGET(m, M_DONTWAIT, MT_DATA); 701 if (m == 0) 702 goto bad; 703 if (off) { 704 len = totlen - off; 705 #ifdef notdef 706 cp = rxbuf + sizeof (struct ether_header) + off; 707 #else 708 cp = rxbuf + 14 + off; 709 #endif 710 } else 711 len = totlen; 712 if (ifp) 713 len += sizeof(ifp); 714 if (len >= CLBYTES) { 715 struct mbuf *p; 716 717 MCLGET(p, 1); 718 if (p != 0) { 719 m->m_len = len = CLBYTES; 720 m->m_off = (int)p - (int)m; 721 } else { 722 m->m_len = len = MIN(MLEN, len); 723 m->m_off = MMINOFF; 724 } 725 } else { 726 m->m_len = len = MIN(MLEN, len); 727 m->m_off = MMINOFF; 728 } 729 mcp = mtod(m, u_char *); 730 if (ifp) { 731 /* 732 * Prepend interface pointer to first mbuf. 733 */ 734 *(mtod(m, struct ifnet **)) = ifp; 735 mcp += sizeof(ifp); 736 len -= sizeof(ifp); 737 ifp = (struct ifnet *)0; 738 } 739 /*bcopy((caddr_t)cp, (caddr_t)mcp, len);*/ 740 /*cp += len; mcp += len;*/ 741 tlen = len; 742 if (((int)mcp & 01) && ((int)cp & 01)) { 743 /* source & destination at odd addresses */ 744 *mcp++ = *cp++; 745 --tlen; 746 } 747 if (tlen > 1 && (((int)mcp&01) == 0) && (((int)cp&01) == 0)) { 748 register short *s1, *s2; 749 register int l; 750 751 s1 = (short *)mcp; 752 s2 = (short *)cp; 753 l = tlen >> 1; /* count # of shorts */ 754 while (l-- > 0) /* copy shorts */ 755 *s1++ = *s2++; 756 tlen &= 1; /* # remaining bytes */ 757 mcp = (u_char *)s1; 758 cp = (u_char *)s2; 759 } 760 while (tlen-- > 0) 761 *mcp++ = *cp++; 762 *mp = m; 763 mp = &m->m_next; 764 if (off == 0) { 765 totlen -= len; 766 continue; 767 } 768 off += len; 769 if (off == totlen) { 770 #ifdef notdef 771 cp = rxbuf + sizeof (struct ether_header); 772 #else 773 cp = rxbuf + 14; 774 #endif 775 off = 0; 776 totlen = off0; 777 } 778 } 779 return (top); 780 bad: 781 m_freem(top); 782 return (0); 783 } 784 785 acebakoff(is, txseg, retries) 786 struct ace_softc *is; 787 struct tx_segment *txseg; 788 register int retries; 789 { 790 register short *pBakNum, random_num; 791 short *pMask; 792 793 pMask = &random_mask_tbl[0]; 794 pBakNum = &txseg->tx_backoff[0]; 795 while (--retries >= 0) { 796 random_num = (is->is_currnd = (is->is_currnd * 18741)-13849); 797 random_num &= *pMask++; 798 *pBakNum++ = random_num ^ (short)(0xFF00 | 0x00FC); 799 } 800 } 801 802 /* 803 * Process an ioctl request. 804 */ 805 aceioctl(ifp, cmd, data) 806 register struct ifnet *ifp; 807 int cmd; 808 caddr_t data; 809 { 810 register struct ifaddr *ifa = (struct ifaddr *)data; 811 struct acedevice *addr; 812 int s = splimp(), error = 0; 813 814 switch (cmd) { 815 816 case SIOCSIFADDR: 817 ifp->if_flags |= IFF_UP; 818 switch (ifa->ifa_addr.sa_family) { 819 #ifdef INET 820 case AF_INET: 821 aceinit(ifp->if_unit); /* before arpwhohas */ 822 ((struct arpcom *)ifp)->ac_ipaddr = 823 IA_SIN(ifa)->sin_addr; 824 arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); 825 break; 826 #endif 827 #ifdef NS 828 case AF_NS: { 829 struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); 830 831 if (!ns_nullhost(*ina)) { 832 ifp->if_flags &= ~IFF_RUNNING; 833 sin = (struct sockaddr_in *)&ifr->ifr_addr; 834 addr = (struct acedevice *) 835 (aceinfo[ifp->if_unit]->ui_addr); 836 movow(&addr->csr, CSR_RESET); 837 DELAY(10000); 838 /* set station address & copy addr to arp */ 839 acesetetaddr(ifp->if_unit, addr, 840 ina->x_host.c_host); 841 } else 842 ina->x_host = *(union ns_host *)(es->es_addr); 843 aceinit(ifp->if_unit); 844 break; 845 } 846 #endif 847 default: 848 aceinit(ifp->if_unit); 849 break; 850 } 851 break; 852 853 case SIOCSIFFLAGS: 854 if ((ifp->if_flags&IFF_UP) == 0 && ifp->if_flags&IFF_RUNNING) { 855 addr = (struct acedevice *) 856 (aceinfo[ifp->if_unit]->ui_addr); 857 movow(&addr->csr, CSR_RESET); 858 ifp->if_flags &= ~IFF_RUNNING; 859 } else if (ifp->if_flags&IFF_UP && 860 (ifp->if_flags&IFF_RUNNING) == 0) 861 aceinit(ifp->if_unit); 862 break; 863 864 default: 865 error = EINVAL; 866 } 867 splx(s); 868 return (error); 869 } 870 871 acesetup(unit) 872 int unit; 873 { 874 register struct ace_softc *is = &ace_softc[unit]; 875 register char *pData1; 876 register short i; 877 struct acedevice *addr; 878 879 bzero(is->is_dpm, 16384*2); 880 is->is_currnd = 49123; 881 addr = (struct acedevice *)aceinfo[unit]->ui_addr; 882 is->is_segboundry = (addr->segb >> 11) & 0xf; 883 pData1 = is->is_dpm + (is->is_segboundry << 11); 884 for (i = SEG_MAX + 1 - is->is_segboundry; --i >= 0;) { 885 acebakoff(is, (struct tx_segment *)pData1, 15); 886 pData1 += sizeof (struct tx_segment); 887 } 888 is->is_eictr = 0; 889 is->is_eoctr = is->is_txnext = is->is_segboundry; 890 bzero((char *)&is->is_stats, sizeof (is->is_stats)); 891 } 892 #endif 893