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