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