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.5 (Berkeley) 04/25/89 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 == 0) 411 goto setup; 412 switch (ace->ether_type) { 413 414 #ifdef INET 415 case ETHERTYPE_IP: 416 schednetisr(NETISR_IP); 417 inq = &ipintrq; 418 break; 419 #endif 420 421 case ETHERTYPE_ARP: 422 arpinput(&is->is_ac, m); 423 goto setup; 424 #ifdef NS 425 case ETHERTYPE_NS: 426 schednetisr(NETISR_NS); 427 inq = &nsintrq; 428 break; 429 430 #endif 431 default: 432 m_freem(m); 433 goto setup; 434 } 435 if (IF_QFULL(inq)) { 436 IF_DROP(inq); 437 m_freem(m); 438 goto setup; 439 } 440 s = splimp(); 441 IF_ENQUEUE(inq, m); 442 splx(s); 443 setup: 444 rxseg->rx_csr = 0; 445 goto again; 446 } 447 448 /* 449 * Routine to copy from mbuf chain to transmit buffer on the VERSAbus 450 * If packet size is less than the minimum legal size, 451 * the buffer is expanded. We probably should zero out the extra 452 * bytes for security, but that would slow things down. 453 */ 454 aceput(txbuf, m) 455 char *txbuf; 456 struct mbuf *m; 457 #ifdef notdef 458 { 459 register u_char *bp, *mcp; 460 register short *s1, *s2; 461 register u_int len; 462 register struct mbuf *mp; 463 int total; 464 465 total = mp->m_pkthdr.len; 466 bp = (u_char *)txbuf; 467 for (mp = m; mp; mp = mp->m_next) { 468 len = mp->m_len; 469 if (len == 0) 470 continue; 471 mcp = mtod(mp, u_char *); 472 if (((int)mcp & 01) && ((int)bp & 01)) { 473 /* source & destination at odd addresses */ 474 movob(bp++, *mcp++); 475 --len; 476 } 477 if (len > 1 && (((int)mcp & 01)==0) && (((int)bp & 01)==0)) { 478 int l = len & 1; 479 480 s1 = (short *)bp; 481 s2 = (short *)mcp; 482 len >>= 1; /* count # of shorts */ 483 while (len-- != 0) 484 movow(s1++, *s2++); 485 len = l; /* # remaining bytes */ 486 bp = (u_char *)s1; 487 mcp = (u_char *)s2; 488 } 489 while (len-- != 0) 490 movob(bp++, *mcp++); 491 } 492 m_freem(m); 493 return (total); 494 } 495 #else 496 { 497 register u_char *bp, *mcp; 498 register short *s1, *s2; 499 register u_int len; 500 register struct mbuf *mp; 501 int total; 502 503 total = 0; 504 bp = (u_char *)txbuf; 505 for (mp = m; (mp); mp = mp->m_next) { 506 len = mp->m_len; 507 if (len == 0) 508 continue; 509 total += len; 510 mcp = mtod(mp, u_char *); 511 if (((int)mcp & 01) && ((int)bp & 01)) { 512 /* source & destination at odd addresses */ 513 movob(bp++, *mcp++); 514 --len; 515 } 516 if (len > 1 && (((int)mcp & 01)==0) && (((int)bp & 01)==0)) { 517 register u_int l; 518 519 s1 = (short *)bp; 520 s2 = (short *)mcp; 521 l = len >> 1; /* count # of shorts */ 522 while (l-- != 0) 523 movow(s1++, *s2++); 524 len &= 1; /* # remaining bytes */ 525 bp = (u_char *)s1; 526 mcp = (u_char *)s2; 527 } 528 while (len-- != 0) 529 movob(bp++, *mcp++); 530 } 531 m_freem(m); 532 return (total); 533 } 534 #endif 535 536 /* 537 * Routine to copy from VERSAbus memory into mbufs. 538 * 539 * Warning: This makes the fairly safe assumption that 540 * mbufs have even lengths. 541 */ 542 struct mbuf * 543 aceget(rxbuf, totlen, off, ifp) 544 u_char *rxbuf; 545 int totlen, off; 546 struct ifnet *ifp; 547 { 548 register u_char *cp, *mcp; 549 register struct mbuf *m; 550 register int tlen; 551 struct mbuf *top = 0, **mp = ⊤ 552 int len; 553 u_char *packet_end; 554 555 rxbuf += sizeof (struct ether_header); 556 cp = rxbuf; 557 packet_end = cp + totlen; 558 if (off) { 559 off += 2 * sizeof(u_short); 560 totlen -= 2 *sizeof(u_short); 561 cp = rxbuf + off; 562 } 563 564 MGETHDR(m, M_DONTWAIT, MT_DATA); 565 if (m == 0) 566 return (0); 567 m->m_pkthdr.rcvif = ifp; 568 m->m_pkthdr.len = totlen; 569 m->m_len = MHLEN; 570 571 while (totlen > 0) { 572 if (top) { 573 MGET(m, M_DONTWAIT, MT_DATA); 574 if (m == 0) { 575 m_freem(top); 576 return (0); 577 } 578 m->m_len = MLEN; 579 } 580 len = min(totlen, (packet_end - cp)); 581 if (len >= MINCLSIZE) { 582 MCLGET(m, M_DONTWAIT); 583 if (m->m_flags & M_EXT) 584 m->m_len = len = min(len, MCLBYTES); 585 else 586 len = m->m_len; 587 } else { 588 /* 589 * Place initial small packet/header at end of mbuf. 590 */ 591 if (len < m->m_len) { 592 if (top == 0 && len + max_linkhdr <= m->m_len) 593 m->m_data += max_linkhdr; 594 m->m_len = len; 595 } else 596 len = m->m_len; 597 } 598 mcp = mtod(m, u_char *); 599 /*bcopy((caddr_t)cp, (caddr_t)mcp, len);*/ 600 /*cp += len; mcp += len;*/ 601 tlen = len; 602 if (((int)mcp & 01) && ((int)cp & 01)) { 603 /* source & destination at odd addresses */ 604 *mcp++ = *cp++; 605 --tlen; 606 } 607 if (tlen > 1 && (((int)mcp&01) == 0) && (((int)cp&01) == 0)) { 608 register short *s1, *s2; 609 register int l; 610 611 s1 = (short *)mcp; 612 s2 = (short *)cp; 613 l = tlen >> 1; /* count # of shorts */ 614 while (l-- > 0) /* copy shorts */ 615 *s1++ = *s2++; 616 tlen &= 1; /* # remaining bytes */ 617 mcp = (u_char *)s1; 618 cp = (u_char *)s2; 619 } 620 while (tlen-- > 0) 621 *mcp++ = *cp++; 622 *mp = m; 623 mp = &m->m_next; 624 totlen -= len; 625 if (cp == packet_end) 626 cp = rxbuf; 627 } 628 return (top); 629 } 630 631 /* backoff table masks */ 632 short random_mask_tbl[16] = { 633 0x0040, 0x00c0, 0x01c0, 0x03c0, 0x07c0, 0x0fc0, 0x1fc0, 0x3fc0, 634 0x7fc0, 0xffc0, 0xffc0, 0xffc0, 0xffc0, 0xffc0, 0xffc0, 0xffc0 635 }; 636 637 acebakoff(is, txseg, retries) 638 struct ace_softc *is; 639 struct tx_segment *txseg; 640 register int retries; 641 { 642 register short *pBakNum, random_num; 643 short *pMask; 644 645 pMask = &random_mask_tbl[0]; 646 pBakNum = &txseg->tx_backoff[0]; 647 while (--retries >= 0) { 648 random_num = (is->is_currnd = (is->is_currnd * 18741)-13849); 649 random_num &= *pMask++; 650 *pBakNum++ = random_num ^ (short)(0xff00 | 0x00fc); 651 } 652 } 653 654 /* 655 * Process an ioctl request. 656 */ 657 aceioctl(ifp, cmd, data) 658 register struct ifnet *ifp; 659 int cmd; 660 caddr_t data; 661 { 662 register struct ifaddr *ifa = (struct ifaddr *)data; 663 struct acedevice *addr; 664 int s = splimp(), error = 0; 665 666 switch (cmd) { 667 668 case SIOCSIFADDR: 669 ifp->if_flags |= IFF_UP; 670 switch (ifa->ifa_addr->sa_family) { 671 #ifdef INET 672 case AF_INET: 673 aceinit(ifp->if_unit); /* before arpwhohas */ 674 ((struct arpcom *)ifp)->ac_ipaddr = 675 IA_SIN(ifa)->sin_addr; 676 arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); 677 break; 678 #endif 679 #ifdef NS 680 case AF_NS: { 681 struct ns_addr *ina = &IA_SNS(ifa)->sns_addr; 682 struct ace_softc *is = &ace_softc[ifp->if_unit]; 683 684 if (!ns_nullhost(*ina)) { 685 ifp->if_flags &= ~IFF_RUNNING; 686 addr = (struct acedevice *) 687 aceinfo[ifp->if_unit]->ui_addr; 688 movow(&addr->csr, CSR_RESET); 689 DELAY(10000); 690 /* set station address & copy addr to arp */ 691 acesetaddr(ifp->if_unit, addr, 692 ina->x_host.c_host); 693 } else 694 ina->x_host = *(union ns_host *)is->is_addr; 695 aceinit(ifp->if_unit); 696 break; 697 } 698 #endif 699 default: 700 aceinit(ifp->if_unit); 701 break; 702 } 703 break; 704 705 case SIOCSIFFLAGS: 706 if ((ifp->if_flags&IFF_UP) == 0 && ifp->if_flags&IFF_RUNNING) { 707 addr = (struct acedevice *) 708 (aceinfo[ifp->if_unit]->ui_addr); 709 movow(&addr->csr, CSR_RESET); 710 ifp->if_flags &= ~IFF_RUNNING; 711 } else if (ifp->if_flags&IFF_UP && 712 (ifp->if_flags&IFF_RUNNING) == 0) 713 aceinit(ifp->if_unit); 714 break; 715 716 default: 717 error = EINVAL; 718 } 719 splx(s); 720 return (error); 721 } 722 723 /* 724 * Set the on-board station address, then read it back 725 * to initialize the address used by ARP (among others). 726 */ 727 acesetaddr(unit, addr, station) 728 short unit; 729 struct acedevice *addr; 730 u_char *station; 731 { 732 struct ace_softc *is = &ace_softc[unit]; 733 register short *wp, i; 734 735 for (wp = (short *)addr->station, i = 0; i < 6; i++) 736 movow(wp++, ~*station++); 737 for (wp = (short *)addr->station, i = 0; i < 6; i++) 738 is->is_addr[i] = ~*wp++; 739 printf("ace%d: hardware address %s\n", unit, 740 ether_sprintf(is->is_addr)); 741 } 742 743 /* 744 * Setup the device for use. Initialize dual-ported memory, 745 * backoff parameters, and various other software state. 746 */ 747 acesetup(unit) 748 int unit; 749 { 750 register struct ace_softc *is = &ace_softc[unit]; 751 register char *pData1; 752 register short i; 753 struct acedevice *addr; 754 755 bzero(is->is_dpm, 16384*2); 756 is->is_currnd = 49123; 757 addr = (struct acedevice *)aceinfo[unit]->ui_addr; 758 is->is_segboundry = (addr->segb >> 11) & 0xf; 759 pData1 = is->is_dpm + (is->is_segboundry << 11); 760 for (i = SEG_MAX + 1 - is->is_segboundry; --i >= 0;) { 761 acebakoff(is, (struct tx_segment *)pData1, 15); 762 pData1 += sizeof (struct tx_segment); 763 } 764 is->is_eictr = 0; 765 is->is_eoctr = is->is_txnext = is->is_segboundry; 766 bzero((char *)&is->is_stats, sizeof (is->is_stats)); 767 } 768 #endif 769