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