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