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