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