1 /* if_ace.c 1.1 85/07/21 */ 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 "../h/param.h" 12 #include "../h/systm.h" 13 #include "../h/mbuf.h" 14 #include "../h/buf.h" 15 #include "../h/protosw.h" 16 #include "../h/socket.h" 17 #include "../h/vmmac.h" 18 #include "../h/ioctl.h" 19 #include "../h/errno.h" 20 #include "../h/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/ip.h" 28 #include "../netinet/ip_var.h" 29 #include "../netinet/if_ether.h" 30 #include "../netpup/pup.h" 31 32 #include "../tahoe/mtpr.h" 33 #include "../tahoeif/if_acereg.h" 34 #include "../vba/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 long ACE0map[], ACE1map[]; 47 long *ACEmap[] = { ACE0map, ACE1map }; 48 long ACEmapa[] = { 0xfff80000, 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 movew((short)CSR_RESET, &addr->csr); 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 struct sockaddr_in *sin; 126 127 ifp->if_unit = unit; 128 ifp->if_name = "ace"; 129 ifp->if_mtu = ETHERMTU; 130 /* 131 * Set station's addresses, multicast 132 * hash table, and initialize dual ported memory. 133 */ 134 ace_station[5] = ~(unit + 1); 135 acesetetaddr(unit, addr, ace_station); 136 is->is_promiscuous = 0; 137 wp = (short *)addr->hash; 138 for (i = 0; i < 8; i++) 139 movew((short)ace_hash[i], wp++); 140 movew((short)~0xffff, &addr->bcastena[0]); 141 movew((short)~0xffff, &addr->bcastena[1]); 142 aceclean(unit); 143 sin = (struct sockaddr_in *)&ifp->if_addr; 144 sin->sin_family = AF_INET; 145 ifp->if_init = aceinit; 146 ifp->if_output = aceoutput; 147 ifp->if_ioctl = aceioctl; 148 ifp->if_reset = acereset; 149 if_attach(ifp); 150 } 151 152 acesetetaddr(unit, addr, station_addr) 153 short unit; 154 struct acedevice *addr; 155 char *station_addr; 156 { 157 register short *wp, i; 158 register char *cp; 159 struct ace_softc *is = &ace_softc[unit]; 160 161 wp = (short *)addr->station; 162 cp = station_addr; 163 for (i = 0; i < 6; i++) 164 movew((short)*cp++, wp++); 165 wp = (short *)addr->station; 166 cp = (char *)&is->is_addr; 167 for (i = 0; i < 6; i++) 168 *cp++ = ~(*wp++); 169 } 170 171 /* 172 * Reset of interface after "system" reset. 173 */ 174 acereset(unit, vban) 175 int unit, vban; 176 { 177 register struct vba_device *ui; 178 179 if (unit >= NACE || (ui = aceinfo[unit]) == 0 || ui->ui_alive == 0 || 180 ui->ui_vbanum != vban) 181 return; 182 printf(" ace%d", unit); 183 aceinit(unit); 184 } 185 186 /* 187 * Initialization of interface; clear recorded pending operations 188 */ 189 aceinit(unit) 190 int unit; 191 { 192 register struct ace_softc *is = &ace_softc[unit]; 193 register struct vba_device *ui = aceinfo[unit]; 194 register struct acedevice *addr; 195 register struct ifnet *ifp = &is->is_if; 196 register struct sockaddr_in *sin; 197 register short Csr; 198 register int i, s; 199 200 sin = (struct sockaddr_in *)&ifp->if_addr; 201 if (sin->sin_addr.s_addr == 0) /* address still unknown */ 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 movew((short)CSR_RESET, &addr->csr); 211 DELAY(10000); 212 213 /* 214 * clean up dpm since the controller might 215 * jumble dpm after reset 216 */ 217 aceclean(unit); 218 movew((short)CSR_GO, &addr->csr); 219 Csr = addr->csr; 220 if (Csr & CSR_ACTIVE) { 221 movew((short)(ACEVECTOR + unit*8), &addr->ivct); 222 Csr |= CSR_IENA | is->is_promiscuous; 223 if (ifp->if_net == LONET) 224 Csr |= CSR_LOOP3; 225 movew(Csr, &addr->csr); 226 is->is_flags = 0; 227 is->is_xcnt = 0; 228 is->is_if.if_flags |= IFF_UP|IFF_RUNNING; 229 } 230 splx(s); 231 } 232 233 if (is->is_if.if_flags & IFF_UP) { 234 if_rtinit(&is->is_if, RTF_UP); 235 aceStart(unit); 236 } 237 arpwhohas(&is->is_ac, &sin->sin_addr); 238 } 239 240 /* 241 * Start output on interface. 242 * Get another datagram to send off of the interface queue, 243 * and map it to the interface before starting the output. 244 * 245 */ 246 acestart(dev) 247 dev_t dev; 248 { 249 register struct tx_segment *txs; 250 register long len, x; 251 int unit = ACEUNIT(dev); 252 struct vba_device *ui = aceinfo[unit]; 253 register struct acedevice *addr = (struct acedevice *)ui->ui_addr; 254 register struct ace_softc *is = &ace_softc[unit]; 255 struct mbuf *m; 256 short retries, idx; 257 258 again: 259 txs = (struct tx_segment*)(is->is_dpm + (is->is_txnext << 11)); 260 if (txs->tx_csr & TCS_TBFULL) { 261 is->is_stats.tx_busy++; 262 return; 263 } 264 x = splimp(); 265 IF_DEQUEUE(&is->is_if.if_snd, m); 266 splx(x); 267 if (m == 0) 268 return; 269 len = aceput(unit, txs->tx_data, m); 270 retries = txs->tx_csr & TCS_RTC; 271 if (retries > 0) 272 acebakoff(is, txs, retries); 273 274 /* 275 * Ensure minimum packet length. 276 * This makes the safe assumtion that there are no virtual holes 277 * after the data. 278 * For security, it might be wise to zero out the added bytes, 279 * but we're mainly interested in speed at the moment. 280 */ 281 #ifdef notdef 282 if (len - sizeof (struct ether_header) < ETHERMIN) 283 len = ETHERMIN + sizeof (struct ether_header); 284 #else 285 if (len - 14 < ETHERMIN) 286 len = ETHERMIN + 14; 287 #endif 288 if (++is->is_txnext > SEG_MAX) 289 is->is_txnext = is->is_segboundry; 290 is->is_if.if_opackets++; 291 is->is_xcnt++; 292 len = (len & 0x7fff) | TCS_TBFULL; 293 movew((short)len, txs); 294 goto again; 295 } 296 297 /* 298 * Transmit done interrupt. 299 */ 300 acecint(unit) 301 int unit; 302 { 303 register struct ace_softc *is = &ace_softc[unit]; 304 struct vba_device *ui = aceinfo[unit]; 305 register struct acedevice *addr = (struct acedevice *)ui->ui_addr; 306 register struct tx_segment *txseg; 307 short txidx, eostat; 308 309 if (is->is_xcnt <= 0) { 310 txidx = (addr->tseg >> 11) & 0xf; 311 printf("ace%d: stray xmit interrupt, xcnt %d\n", 312 unit, is->is_xcnt); 313 is->is_xcnt = 0; 314 aceStart(unit); 315 return; 316 } 317 is->is_xcnt--; 318 txseg = (struct tx_segment *)((is->is_eoctr << 11) + is->is_dpm); 319 eostat = txseg->tx_csr; 320 if ((eostat & TCS_TBFULL) == 0) { 321 is->is_stats.tx_retries += eostat & TCS_RTC; 322 if (eostat & TCS_RTFAIL) { 323 is->is_stats.tx_discarded++; 324 is->is_if.if_oerrors++; 325 } else 326 is->is_stats.tx_datagrams++; 327 if (++is->is_eoctr >= 16) 328 is->is_eoctr = is->is_segboundry; 329 } 330 aceStart(unit); 331 } 332 333 /* 334 * Ethernet interface receiver interrupt. 335 * If input error just drop packet. 336 * Otherwise purge input buffered data path and examine 337 * packet to determine type. If can't determine length 338 * from type, then have to drop packet. Othewise decapsulate 339 * packet based on type and pass to type specific higher-level 340 * input routine. 341 */ 342 acerint(unit) 343 int unit; 344 { 345 register struct ace_softc *is = &ace_softc[unit]; 346 register struct ifqueue *inq; 347 register struct ether_header *ace; 348 register struct rx_segment *rxseg; 349 struct acedevice *addr = (struct acedevice *)aceinfo[unit]->ui_addr; 350 int len, s, off, resid; 351 struct mbuf *m; 352 short eistat; 353 354 again: 355 rxseg = (struct rx_segment *)((is->is_eictr << 11) + is->is_dpm); 356 eistat = rxseg->rx_csr; 357 if ((eistat & RCS_RBFULL) == 0) 358 return; 359 is->is_if.if_ipackets++; 360 if (++is->is_eictr >= is->is_segboundry) 361 is->is_eictr = 0; 362 len = eistat & RCS_RBC; 363 if ((eistat & (RCS_ROVRN | RCS_RCRC | RCS_RODD)) || 364 len < ET_MINLEN || len > ET_MAXLEN+CRC_SIZE) { 365 if (eistat & RCS_ROVRN) 366 is->is_stats.rx_overruns++; 367 if (eistat & RCS_RCRC) 368 is->is_stats.rx_crc_errors++; 369 if (eistat & RCS_RODD) 370 is->is_stats.rx_align_errors++; 371 if (len < ET_MINLEN) 372 is->is_stats.rx_underruns++; 373 if (len > ET_MAXLEN+CRC_SIZE) 374 is->is_stats.rx_overruns++; 375 is->is_if.if_ierrors++; 376 rxseg->rx_csr = 0; 377 return; 378 } else 379 is->is_stats.rx_datagrams++; 380 ace = (struct ether_header *)rxseg->rx_data; 381 #ifdef notdef 382 len -= sizeof (struct ether_header); 383 #else 384 len -= 14; 385 #endif 386 /* 387 * Deal with trailer protocol: if type is PUP trailer 388 * get true type from first 16-bit word past data. 389 * Remember that type was trailer by setting off. 390 */ 391 ace->ether_type = ntohs((u_short)ace->ether_type); 392 #ifdef notdef 393 #define acedataaddr(ace, off, type) \ 394 ((type)(((caddr_t)(((char *)ace)+sizeof (struct ether_header))+(off)))) 395 #else 396 #define acedataaddr(ace, off, type) \ 397 ((type)(((caddr_t)(((char *)ace)+14)+(off)))) 398 #endif 399 if (ace->ether_type >= ETHERPUP_TRAIL && 400 ace->ether_type < ETHERPUP_TRAIL+ETHERPUP_NTRAILER) { 401 off = (ace->ether_type - ETHERPUP_TRAIL) * 512; 402 if (off >= ETHERMTU) 403 goto setup; /* sanity */ 404 ace->ether_type = ntohs(*acedataaddr(ace, off, u_short *)); 405 resid = ntohs(*(acedataaddr(ace, off+2, u_short *))); 406 if (off + resid > len) 407 goto setup; /* sanity */ 408 len = off + resid; 409 } else 410 off = 0; 411 if (len == 0) 412 goto setup; 413 414 /* 415 * Pull packet off interface. Off is nonzero if packet 416 * has trailing header; aceget will then force this header 417 * information to be at the front, but we still have to drop 418 * the type and length which are at the front of any trailer data. 419 */ 420 m = aceget(unit, rxseg->rx_data, len, off); 421 if (m == 0) 422 goto setup; 423 if (off) { 424 m->m_off += 2 * sizeof (u_short); 425 m->m_len -= 2 * sizeof (u_short); 426 } 427 switch (ace->ether_type) { 428 429 #ifdef INET 430 case ETHERPUP_IPTYPE: 431 schednetisr(NETISR_IP); 432 inq = &ipintrq; 433 break; 434 435 case ETHERPUP_ARPTYPE: 436 arpinput(&is->is_ac, m); 437 goto setup; 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 struct ether_addr edst; 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 (in_lnaof(idst) == INADDR_ANY) 484 mcopy = m_copy(m, 0, (int)M_COPYALL); 485 off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; 486 /* need per host negotiation */ 487 if ((ifp->if_flags & IFF_NOTRAILERS) == 0 && off > 0 && 488 (off & 0x1ff) == 0 && 489 m->m_off >= MMINOFF + 2 * sizeof (u_short)) { 490 type = ETHERPUP_TRAIL + (off>>9); 491 m->m_off -= 2 * sizeof (u_short); 492 m->m_len += 2 * sizeof (u_short); 493 *mtod(m, u_short *) = htons((u_short)ETHERPUP_IPTYPE); 494 *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len); 495 goto gottrailertype; 496 } 497 type = ETHERPUP_IPTYPE; 498 off = 0; 499 goto gottype; 500 #endif 501 502 case AF_UNSPEC: 503 ace = (struct ether_header *)dst->sa_data; 504 #ifdef notdef 505 edst = ace->ether_dhost; 506 #else 507 bcopy((caddr_t)ace->ether_dhost, (caddr_t)&edst, 6); 508 #endif 509 type = ace->ether_type; 510 goto gottype; 511 512 default: 513 printf("ace%d: can't handle af%d\n", 514 ifp->if_unit, dst->sa_family); 515 error = EAFNOSUPPORT; 516 goto bad; 517 } 518 519 gottrailertype: 520 /* 521 * Packet to be sent as trailer: move first packet 522 * (control information) to end of chain. 523 */ 524 while (m->m_next) 525 m = m->m_next; 526 m->m_next = m0; 527 m = m0->m_next; 528 m0->m_next = 0; 529 m0 = m; 530 531 gottype: 532 /* 533 * Add local net header. If no space in first mbuf, 534 * allocate another. 535 */ 536 if (m->m_off > MMAXOFF || 537 #ifdef notdef 538 MMINOFF + sizeof (struct ether_header) > m->m_off) { 539 #else 540 MMINOFF + 14 > m->m_off) { 541 #endif 542 m = m_get(M_DONTWAIT, MT_HEADER); 543 if (m == 0) { 544 error = ENOBUFS; 545 goto bad; 546 } 547 m->m_next = m0; 548 m->m_off = MMINOFF; 549 #ifdef notdef 550 m->m_len = sizeof (struct ether_header); 551 #else 552 m->m_len = 14; 553 #endif 554 } else { 555 #ifdef notdef 556 m->m_off -= sizeof (struct ether_header); 557 m->m_len += sizeof (struct ether_header); 558 #else 559 m->m_off -= 14; 560 m->m_len += 14; 561 #endif 562 } 563 ace = mtod(m, struct ether_header *); 564 #ifdef notdef 565 ace->ether_dhost = edst; 566 ace->ether_shost = is->is_addr; 567 #else 568 bcopy((caddr_t)&edst, (caddr_t)ace->ether_dhost, 6); 569 bcopy((caddr_t)&is->is_addr, (caddr_t)ace->ether_shost, 6); 570 #endif 571 ace->ether_type = htons((u_short)type); 572 573 /* 574 * Queue message on interface, and start output if interface 575 * not yet active. 576 */ 577 s = splimp(); 578 if (IF_QFULL(&ifp->if_snd)) { 579 IF_DROP(&ifp->if_snd); 580 error = ENOBUFS; 581 goto qfull; 582 } 583 IF_ENQUEUE(&ifp->if_snd, m); 584 splx(s); 585 aceStart(ifp->if_unit); 586 return (mcopy ? looutput(&loif, mcopy, dst) : 0); 587 qfull: 588 m0 = m; 589 splx(s); 590 bad: 591 m_freem(m0); 592 if (mcopy) 593 m_freem(mcopy); 594 return (error); 595 } 596 597 aceStart(unit) 598 int unit; 599 { 600 register struct ace_softc *is = &ace_softc[unit]; 601 602 if (is->is_flags & ACEF_OACTIVE) 603 return; 604 is->is_flags |= ACEF_OACTIVE; 605 acestart((dev_t)unit); 606 is->is_flags &= ~ACEF_OACTIVE; 607 } 608 609 /* 610 * Routine to copy from mbuf chain to transmit buffer on the VERSAbus 611 * If packet size is less than the minimum legal size, 612 * the buffer is expanded. We probably should zero out the extra 613 * bytes for security, but that would slow things down. 614 */ 615 aceput(unit, txbuf, m) 616 int unit; /* for statistics collection */ 617 u_char *txbuf; 618 struct mbuf *m; 619 { 620 register u_char *bp, *mcp; /* known to be r12, r11 */ 621 register short *s1, *s2; /* known to be r10, r9 */ 622 register unsigned len; 623 register struct mbuf *mp; 624 int total, idx; 625 626 total = 0; 627 bp = txbuf; 628 for (mp = m;(mp); mp = mp->m_next) { 629 len = mp->m_len; 630 if (len == 0) 631 continue; 632 total += len; 633 mcp = mtod(mp, u_char *); 634 if (((int)mcp & 01) && ((int)bp & 01)) { 635 /* source & destination at odd addresses */ 636 /* *bp++ = *mcp++; */ 637 asm("movob (r11),(r12)"); 638 bp++, mcp++; 639 --len; 640 } 641 if (len > 1 && (((int)mcp & 01)==0) && (((int)bp & 01)==0)) { 642 register int l; 643 644 s1 = (short *)bp; 645 s2 = (short *)mcp; 646 l = len >> 1; /* count # of shorts */ 647 while (l-- > 0) { 648 /* *s1++ = *s2++; */ 649 asm("movow (r9),(r10)"); 650 s1++, s2++; 651 } 652 len &= 1; /* # remaining bytes */ 653 bp = (u_char *)s1; 654 mcp = (u_char *)s2; 655 } 656 while (len-- > 0) { 657 /* *bp++ = *mcp++; */ 658 asm("movob (r11),(r12)"); 659 bp++, mcp++; 660 } 661 } 662 m_freem(m); 663 return (total); 664 } 665 666 movew(data, to) 667 short data, *to; 668 { 669 670 asm("movow 6(fp),*8(fp)"); 671 } 672 673 /* 674 * Routine to copy from VERSAbus memory into mbufs. 675 * 676 * Warning: This makes the fairly safe assumption that 677 * mbufs have even lengths. 678 */ 679 struct mbuf * 680 aceget(unit, rxbuf, totlen, off0) 681 int unit; /* for statistics collection */ 682 u_char *rxbuf; 683 int totlen, off0; 684 { 685 register u_char *cp, *mcp; /* known to be r12, r11 */ 686 register int tlen; 687 register struct mbuf *m; 688 struct mbuf *top = 0, **mp = ⊤ 689 int len, off = off0; 690 691 #ifdef notdef 692 cp = rxbuf + sizeof (struct ether_header); 693 #else 694 cp = rxbuf + 14; 695 #endif 696 while (totlen > 0) { 697 register int words; 698 699 MGET(m, M_DONTWAIT, MT_DATA); 700 if (m == 0) 701 goto bad; 702 if (off) { 703 len = totlen - off; 704 #ifdef notdef 705 cp = rxbuf + sizeof (struct ether_header) + off; 706 #else 707 cp = rxbuf + 14 + off; 708 #endif 709 } else 710 len = totlen; 711 if (len >= CLBYTES) { 712 struct mbuf *p; 713 714 MCLGET(p, 1); 715 if (p != 0) { 716 m->m_len = len = CLBYTES; 717 m->m_off = (int)p - (int)m; 718 } else { 719 m->m_len = len = MIN(MLEN, len); 720 m->m_off = MMINOFF; 721 } 722 } else { 723 m->m_len = len = MIN(MLEN, len); 724 m->m_off = MMINOFF; 725 } 726 mcp = mtod(m, u_char *); 727 /*bcopy((caddr_t)cp, (caddr_t)mcp, len);*/ 728 /*cp += len; mcp += len;*/ 729 tlen = len; 730 if (((int)mcp & 01) && ((int)cp & 01)) { 731 /* source & destination at odd addresses */ 732 *mcp++ = *cp++; 733 --tlen; 734 } 735 if (tlen > 1 && (((int)mcp&01) == 0) && (((int)cp&01) == 0)) { 736 register short *s1, *s2; 737 register int l; 738 739 s1 = (short *)mcp; 740 s2 = (short *)cp; 741 l = tlen >> 1; /* count # of shorts */ 742 while (l-- > 0) /* copy shorts */ 743 *s1++ = *s2++; 744 tlen &= 1; /* # remaining bytes */ 745 mcp = (u_char *)s1; 746 cp = (u_char *)s2; 747 } 748 while (tlen-- > 0) 749 *mcp++ = *cp++; 750 *mp = m; 751 mp = &m->m_next; 752 if (off == 0) { 753 totlen -= len; 754 continue; 755 } 756 off += len; 757 if (off == totlen) { 758 #ifdef notdef 759 cp = rxbuf + sizeof (struct ether_header); 760 #else 761 cp = rxbuf + 14; 762 #endif 763 off = 0; 764 totlen = off0; 765 } 766 } 767 return (top); 768 bad: 769 m_freem(top); 770 return (0); 771 } 772 773 acebakoff(is, txseg, retries) 774 struct ace_softc *is; 775 struct tx_segment *txseg; 776 register int retries; 777 { 778 register short *pBakNum, random_num; 779 short *pMask; 780 781 pMask = &random_mask_tbl[0]; 782 pBakNum = &txseg->tx_backoff[0]; 783 while (--retries >= 0) { 784 random_num = (is->is_currnd = (is->is_currnd * 18741)-13849); 785 random_num &= *pMask++; 786 *pBakNum++ = random_num ^ (short)(0xFF00 | 0x00FC); 787 } 788 } 789 790 /* 791 * Process an ioctl request. 792 */ 793 aceioctl(ifp, cmd, data) 794 register struct ifnet *ifp; 795 int cmd; 796 caddr_t data; 797 { 798 register struct ifreq *ifr = (struct ifreq *)data; 799 int s, error = 0; 800 801 s = splimp(); 802 switch (cmd) { 803 804 case SIOCSIFADDR: 805 if (ifp->if_flags & IFF_RUNNING) 806 if_rtinit(ifp, -1); /* delete previous route */ 807 acesetaddr(ifp, (struct sockaddr_in *)&ifr->ifr_addr); 808 aceinit(ifp->if_unit); 809 break; 810 811 #ifdef notdef 812 case SIOCSETETADDR: { /* set Ethernet station address */ 813 struct vba_device *ui; 814 struct acedevice *addr; 815 struct sockaddr_in *sin; 816 817 ifp->if_flags &= ~IFF_RUNNING | IFF_UP; 818 sin = (struct sockaddr_in *)&ifr->ifr_addr; 819 ui = aceinfo[ifp->if_unit]; 820 addr = (struct acedevice *)ui->ui_addr; 821 movew((short)CSR_RESET, &addr->csr); 822 DELAY(10000); 823 /* set station address and copy addr to arp struct */ 824 acesetetaddr(ifp->if_unit, addr, &sin->sin_zero[2]); 825 aceinit(ifp->if_unit); /* Re-initialize */ 826 break; 827 } 828 #endif 829 830 default: 831 error = EINVAL; 832 } 833 splx(s); 834 return (error); 835 } 836 837 acesetaddr(ifp, sin) 838 register struct ifnet *ifp; 839 register struct sockaddr_in *sin; 840 { 841 842 ifp->if_addr = *(struct sockaddr *)sin; 843 ifp->if_net = in_netof(sin->sin_addr); 844 ifp->if_host[0] = in_lnaof(sin->sin_addr); 845 sin = (struct sockaddr_in *)&ifp->if_broadaddr; 846 sin->sin_family = AF_INET; 847 sin->sin_addr = if_makeaddr(ifp->if_net, INADDR_ANY); 848 ifp->if_flags |= IFF_BROADCAST; 849 } 850 851 aceclean(unit) 852 int unit; 853 { 854 register struct ace_softc *is = &ace_softc[unit]; 855 register struct ifnet *ifp = &is->is_if; 856 register struct vba_device *ui = aceinfo[unit]; 857 register struct acedevice *addr = (struct acedevice *)ui->ui_addr; 858 register short i, data; 859 register char *pData1; 860 861 ioaccess(ACEmap[unit], ACEmapa[unit], ACEBPTE); 862 is->is_dpm = acemap[unit]; /* init dpm */ 863 bzero((char *)is->is_dpm, 16384*2); 864 865 is->is_currnd = 49123; 866 is->is_segboundry = (addr->segb >> 11) & 0xf; 867 pData1 = (char*)((int)is->is_dpm + (is->is_segboundry << 11)); 868 for (i = SEG_MAX + 1 - is->is_segboundry; --i >= 0;) { 869 acebakoff(is, (struct tx_segment *)pData1, 15); 870 pData1 += sizeof (struct tx_segment); 871 } 872 is->is_eictr = 0; 873 is->is_eoctr = is->is_txnext = is->is_segboundry; 874 bzero((char *)&is->is_stats, sizeof (is->is_stats)); 875 } 876 #endif 877