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