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