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