|
|
1.1 ! root 1: /* ! 2: * Copyright IBM Corporation 1987,1990 ! 3: * ! 4: * All Rights Reserved ! 5: * ! 6: * Permission to use, copy, modify, and distribute this software and its ! 7: * documentation for any purpose and without fee is hereby granted, ! 8: * provided that the above copyright notice appear in all copies and that ! 9: * both that copyright notice and this permission notice appear in ! 10: * supporting documentation, and that the name of IBM not be ! 11: * used in advertising or publicity pertaining to distribution of the ! 12: * software without specific, written prior permission. ! 13: * ! 14: * IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ! 15: * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR USE. ! 16: * IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL ! 17: * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR ! 18: * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ! 19: * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF ! 20: * THIS SOFTWARE. ! 21: * ! 22: * @(#)if_un.eg 7.1 (Berkeley) 10/29/90 ! 23: */ ! 24: ! 25: /* ! 26: * Ungermann-Bass PC-NIC (Ethernet) Adapter (4.3 driver) ! 27: */ ! 28: ! 29: #include "un.h" ! 30: #if NUN > 0 ! 31: ! 32: #include "../machine/pte.h" ! 33: ! 34: #include "param.h" ! 35: #include "systm.h" ! 36: #include "mbuf.h" ! 37: #include "buf.h" ! 38: #include "protosw.h" ! 39: #include "socket.h" ! 40: #include "vmmac.h" ! 41: #include "ioctl.h" ! 42: #include "errno.h" ! 43: ! 44: #include "../net/if.h" ! 45: #include "../net/netisr.h" ! 46: #include "../net/route.h" ! 47: ! 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/if_ether.h" ! 54: #endif INET ! 55: ! 56: #ifdef NS ! 57: #include "../netns/ns.h" ! 58: #include "../netns/ns_if.h" ! 59: #endif NS ! 60: ! 61: #ifdef ISO ! 62: #include "../netargo/if_clnp.h" ! 63: #include "../netargo/iso.h" ! 64: #include "../netargo/iso_var.h" ! 65: #include "../netargo/argo_debug.h" ! 66: #endif ISO ! 67: ! 68: #include "../machine/io.h" ! 69: #include "if_unreg.h" ! 70: #ifdef IEEELLC ! 71: #include "if_llc.h" ! 72: #endif IEEELLC ! 73: #include "../machineio/ioccvar.h" ! 74: #include "../machine/debug.h" ! 75: ! 76: int unprobe(), unattach(); ! 77: ! 78: #ifdef AT ! 79: caddr_t unstd[] = { (caddr_t) 0xa0000, (caddr_t) 0xa8000, ! 80: (caddr_t) 0xb0000, (caddr_t) 0xb8000, 0 }; ! 81: #else ! 82: caddr_t unstd[] = { (caddr_t) 0xf4080000, (caddr_t) 0xf4088000, ! 83: (caddr_t) 0xf4090000, (caddr_t) 0xf4098000, 0 }; ! 84: #endif AT ! 85: ! 86: struct iocc_device *uninfo[NUN]; ! 87: ! 88: int unint(), uninit(), unioctl(), unoutput(), unreset(); ! 89: ! 90: struct iocc_driver undriver = ! 91: { unprobe, 0, unattach, 0, unstd, "un", uninfo, ! 92: 0, 0, unint, UN_EADDROFF }; ! 93: ! 94: struct mbuf *unget(); ! 95: ! 96: /* ! 97: * Ethernet software status per adapter. ! 98: */ ! 99: struct un_softc { ! 100: struct arpcom us_ac; /* generic network interface stuff */ ! 101: #define us_if us_ac.ac_if /* ifnet struct */ ! 102: #define us_addr us_ac.ac_enaddr /* hardware (i.e. ethernet) address */ ! 103: short us_oactive; /* 1 => output active */ ! 104: short us_nextpage; /* next receive buffer page */ ! 105: short us_xbuf; /* in-use xmt buf (if output active) */ ! 106: short us_xfull[2]; /* 1 => a full xmt buf */ ! 107: short us_xstart[2]; /* start address used in unstart */ ! 108: } un_softc[NUN]; ! 109: ! 110: #ifdef DEBUG ! 111: char undebug = 0; ! 112: #endif DEBUG ! 113: ! 114: #ifdef ATR ! 115: #define move_window(window, addr) {\ ! 116: int real_addr;\ ! 117: int new_window;\ ! 118: \ ! 119: window = get_128_window();\ ! 120: real_addr = 0xfffff & (int) addr;\ ! 121: new_window = real_addr & 0xe0000;\ ! 122: set_128_window(new_window);\ ! 123: addr = (struct undevice *) (real_addr - new_window);\ ! 124: } ! 125: ! 126: #define restore_window(window) set_128_window(window) ! 127: #define bcopyin(from,to,len) bcopy((from)+pcif_128_fw,to,len) ! 128: #define bcopyout(from,to,len) bcopy(from,(to)+pcif_128_fw,len) ! 129: #endif ATR ! 130: ! 131: #ifdef IBMRTPC ! 132: #define bcopyin bcopy ! 133: #define bcopyout bcopy ! 134: #endif IBMRTPC ! 135: /* ! 136: * unprobe - try to generate an interrupt (to see if the board is there) ! 137: */ ! 138: unprobe(p) ! 139: register caddr_t p; ! 140: { ! 141: register struct undevice *addr = (struct undevice *) p; ! 142: #ifdef ATR ! 143: register int old_window; ! 144: move_window(old_window, addr); ! 145: #endif ATR ! 146: (void) unzap(addr); ! 147: UN_GLOBIENB(0); /* global interrrupt enable */ ! 148: MM_OUT(&addr->un_csr, UN_GSFTINT); /* generate software interrupt */ ! 149: PROBE_DELAY(100000); ! 150: MM_OUT(&addr->un_csr, 0); ! 151: #ifdef ATR ! 152: restore_window(old_window); ! 153: #endif ATR ! 154: return(PROBE_OK); ! 155: } ! 156: ! 157: /* ! 158: * unattach - make the interface available to the network software ! 159: * (if the auto-configuration software determines that the interface ! 160: * exists). The system will initialize the interface when it is ! 161: * ready to accept packets. ! 162: */ ! 163: unattach(iod) ! 164: register struct iocc_device *iod; ! 165: { ! 166: register struct un_softc *us = &un_softc[iod->iod_unit]; ! 167: register struct ifnet *ifp = &us->us_if; ! 168: register struct undevice *addr = (struct undevice *) iod->iod_addr; ! 169: register int i; ! 170: #ifdef ATR ! 171: register int old_window; ! 172: ! 173: move_window(old_window, addr); ! 174: #endif ATR ! 175: ifp->if_unit = iod->iod_unit; ! 176: ifp->if_name = "un"; ! 177: ! 178: #ifdef IEEELLC ! 179: ifp->if_mtu = ETHERMTU - 3; /* 3 bytes for UI LLC frame */ ! 180: #else ! 181: ifp->if_mtu = ETHERMTU; ! 182: #endif IEEELCC ! 183: ! 184: /* ! 185: * Read the ethernet address off the board. ! 186: * Save it and also write it to the edlc chip. ! 187: */ ! 188: for (i = 0; i < ETH_ADDR_SIZE; i++){ ! 189: us->us_addr[i] = MM_IN(&addr->un_eprom[UN_EADDROFF+i]); ! 190: MM_OUT(&addr->un_edlc.nodeID[i], us->us_addr[i]); ! 191: } ! 192: printf("un%d: ethernet address ", ifp->if_unit); ! 193: unprintethaddr(us->us_addr); ! 194: printf("\n"); ! 195: ifp->if_init = uninit; ! 196: ifp->if_ioctl = unioctl; ! 197: ifp->if_output = unoutput; ! 198: ifp->if_reset = unreset; ! 199: ifp->if_flags = IFF_BROADCAST; ! 200: #ifdef ISO ! 201: ifp->if_flags |= IFF_EAVESDROP; ! 202: #endif ISO ! 203: if_attach(ifp); ! 204: DEBUGF(undebug, printf("un%d: attached\n", iod->iod_unit);) ! 205: #ifdef ATR ! 206: restore_window(old_window); ! 207: #endif ATR ! 208: } ! 209: ! 210: /* ! 211: * unreset - reset interface ! 212: */ ! 213: unreset(unit) ! 214: register unsigned int unit; ! 215: { ! 216: register struct iocc_device *iod; ! 217: ! 218: if (unit < NUN && (iod = uninfo[unit]) != 0 && iod->iod_alive != 0){ ! 219: un_softc[unit].us_if.if_flags &= ~IFF_RUNNING; ! 220: DEBUGF(undebug, printf("un%d: reset\n", unit);) ! 221: uninit(unit); ! 222: } ! 223: } ! 224: ! 225: /* ! 226: * uninit - initialize interface, enable packet reception, start any ! 227: * pending writes ! 228: */ ! 229: uninit(unit) ! 230: register int unit; ! 231: { ! 232: register struct un_softc *us = &un_softc[unit]; ! 233: register struct ifnet *ifp = &us->us_if; ! 234: register int s; ! 235: register struct undevice *addr; ! 236: register int i; ! 237: ! 238: if (ifp->if_addrlist == (struct ifaddr *) 0){ ! 239: /* no address */ ! 240: return; ! 241: } ! 242: if ((ifp->if_flags & IFF_RUNNING) == 0){ ! 243: int old_window; ! 244: ! 245: addr = (struct undevice *) (uninfo[unit]->iod_addr); ! 246: #ifdef ATR ! 247: move_window(old_window, addr); ! 248: #endif ATR ! 249: s = splimp(); ! 250: us->us_nextpage = unzap(addr); /* initialize hardware */ ! 251: /* unzap returns next receive page to be used */ ! 252: for (i = 0; i < ETH_ADDR_SIZE; i++){ ! 253: MM_OUT(&addr->un_edlc.nodeID[i], us->us_addr[i]); ! 254: } ! 255: us->us_oactive = 0; /* output not active */ ! 256: /* turn adapter on */ ! 257: ifp->if_flags |= IFF_RUNNING; ! 258: MM_OUT(&addr->un_csr, UN_PAVIENB); ! 259: /* Allow packet available interrupts */ ! 260: UN_GLOBIENB(us->us_nextpage); /* global interrrupt enable */ ! 261: if (ifp->if_snd.ifq_head){ /* anything on send queue */ ! 262: struct mbuf *m; ! 263: ! 264: IF_DEQUEUE(&ifp->if_snd, m); ! 265: unput(us, addr, m, 0); ! 266: unstart(us, addr, 0); ! 267: if (ifp->if_snd.ifq_head){ ! 268: IF_DEQUEUE(&ifp->if_snd, m); ! 269: unput(us, addr, m, 1); ! 270: } ! 271: } ! 272: splx(s); ! 273: #ifdef ATR ! 274: restore_window(old_window); ! 275: #endif ATR ! 276: } ! 277: DEBUGF(undebug, printf("un%d: init'ed\n", unit);) ! 278: } ! 279: ! 280: /* ! 281: * unstart - start output from one of the adapter's 2 transmit buffers ! 282: */ ! 283: unstart(us, addr, xbuf) ! 284: register struct un_softc *us; ! 285: register struct undevice *addr; ! 286: register int xbuf; ! 287: { ! 288: us->us_oactive = 1; ! 289: us->us_xbuf = xbuf; ! 290: UN_XMIT(addr, us->us_xstart[xbuf]); ! 291: MM_OUT(&addr->un_csr, UN_IENABLE); /* enable transmit done interrupt */ ! 292: } ! 293: ! 294: /* ! 295: * unint - interrupt handler. find the cause of the interrupt and ! 296: * dispatch an appropriate handler routine. ! 297: */ ! 298: unint(unit) ! 299: register int unit; ! 300: { ! 301: register struct un_softc *us = &un_softc[unit]; ! 302: register struct undevice *addr = ! 303: (struct undevice *) uninfo[unit]->iod_addr; ! 304: register char status; ! 305: register int rc = 1; ! 306: #ifdef ATR ! 307: register int old_window; ! 308: ! 309: move_window(old_window, addr); ! 310: #endif ATR ! 311: ! 312: UN_DISABLE(us->us_nextpage); ! 313: while ((status = ~MM_IN(&addr->un_csr)) & UN_PAVINT){ ! 314: DEBUGF(undebug & 0x2, printf("unint: unit = %d, csr = %b", ! 315: unit, status & 0xff, UN_CSRBITS);) ! 316: unrint(unit, us, addr); ! 317: rc = 0; ! 318: } ! 319: if (status & UN_TXRINT){ ! 320: DEBUGF(undebug & 0x2, printf("unint: unit = %d, csr = %b", ! 321: unit, status & 0xff, UN_CSRBITS);) ! 322: unxint(unit, us, addr); ! 323: rc = 0; ! 324: } ! 325: UN_ENABLE(us->us_nextpage); ! 326: #ifdef ATR ! 327: restore_window(old_window); ! 328: #endif ATR ! 329: return(rc); ! 330: } ! 331: ! 332: /* ! 333: * unrint - interrupt handler for packet reception. ! 334: * ! 335: * log error if error bits are latched, examine packet to determine ! 336: * type, if can't determine packet length from type, drop packet. ! 337: * otherwise decapsulate packet based on type and pass to an appropriate ! 338: * higher-level input routine. ! 339: */ ! 340: unrint(unit, us, addr) ! 341: int unit; ! 342: register struct un_softc *us; ! 343: register struct undevice *addr; ! 344: { ! 345: register struct ether_header *eh; ! 346: register struct mbuf *m; ! 347: register int len; ! 348: register int off; ! 349: int resid; ! 350: struct ifqueue *inq; ! 351: char status = MM_IN(&addr->un_edlc.rstat); ! 352: u_short type; ! 353: u_short ungetushortatoff(); ! 354: #ifdef IEEELLC ! 355: struct ether_header ehbuf; ! 356: #endif IEEELLC ! 357: ! 358: MM_OUT(&addr->un_edlc.rstat, status); /* clear status */ ! 359: /* (the hardware xor's in the value of status setting rstat to 0) */ ! 360: DEBUGF(undebug & 0x2, printf(" rstat = %b", status, RS_BITS);) ! 361: /* ! 362: * Latch errors. (Errors found correspond to packets ! 363: * that were received prior to the current packet ! 364: * since packet available interrupts are generated ! 365: * for good packets only.) ! 366: */ ! 367: if (status & RS_ERR){ ! 368: DEBUGF(undebug, printf("unrint: input error\n");) ! 369: us->us_if.if_ierrors++; ! 370: } ! 371: us->us_if.if_ipackets++; ! 372: ! 373: /* ! 374: * determine the length of the received packet. ! 375: */ ! 376: len = 0; ! 377: off = us->us_nextpage; ! 378: ! 379: #define BUMP(page) if (++(page) == UN_NUMRBUFS) page = 0 ! 380: while ((MM_IN(&addr->un_pram[us->us_nextpage]) & UN_LAST_PAGE) == 0){ ! 381: len += UN_RBUFSIZE; ! 382: BUMP(us->us_nextpage); ! 383: } ! 384: len += (MM_IN(&addr->un_pram[us->us_nextpage]) & ! 385: UN_PAGE_LENGTH_MASK) + 1; ! 386: BUMP(us->us_nextpage); ! 387: #undef BUMP ! 388: DEBUGF(undebug & 0x2, printf(" len = %d ", len);) ! 389: if (len > UN_XBSIZE){ ! 390: printf("un%d: huge packet!\n",unit); ! 391: goto chuckit; ! 392: } ! 393: /* ! 394: * Process the packet ! 395: */ ! 396: eh = (struct ether_header *) &addr->un_rcvbuf[off][0]; ! 397: DEBUGF(undebug & 0x2, ! 398: { char cbuf[6]; ! 399: printf(" from = "); ! 400: bcopyin(eh->ether_shost, cbuf, sizeof(cbuf)); ! 401: unprintethaddr(cbuf); ! 402: printf(" to = "); ! 403: bcopyin(eh->ether_dhost, cbuf, sizeof(cbuf)); ! 404: unprintethaddr(cbuf); ! 405: printf(" "); } ! 406: ) ! 407: len -= sizeof(struct ether_header); ! 408: type = ntohs((u_short) MM_INW(&eh->ether_type)); ! 409: /* ! 410: * The ETHERTYPE_NTRAILER packet types starting at ETHERTYPE_TRAIL ! 411: * have (type - ETHERTYPE_TRAIL) * 512 bytes of data followed by ! 412: * a type field and then a (variable length) header ! 413: */ ! 414: if (type >= ETHERTYPE_TRAIL && ! 415: type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER){ ! 416: off = (type - ETHERTYPE_TRAIL) * 512; ! 417: if (off >= ETHERMTU){ ! 418: goto chuckit; ! 419: } ! 420: type = ungetushortatoff(addr, eh, off); ! 421: resid = ungetushortatoff(addr, eh, off + 2); ! 422: if (off + resid > len){ ! 423: goto chuckit; ! 424: } ! 425: len = off + resid; ! 426: } else { ! 427: off = 0; ! 428: } ! 429: if (len == 0){ ! 430: goto chuckit; ! 431: } ! 432: ! 433: #ifdef IEEELLC ! 434: if (type <= ETHERMTU) { ! 435: /* may need ether_header for XID, TEST LLC functions */ ! 436: ehbuf = *eh; ! 437: } ! 438: #endif IEEELLC ! 439: ! 440: /* ! 441: * pull packet off interface. if off is non-zero, the ! 442: * packet has a trailing "header". unget will move this ! 443: * header to the front, but we still have to remove the ! 444: * type and length fields from the front of the data. ! 445: */ ! 446: m = unget(addr, (char *) eh, len, off, &us->us_if); ! 447: /* ! 448: * update the full page pointer and clear the packet available ! 449: * flag if necessary. update the fpp here to free the on-board ! 450: * receive pages as soon as possible. ! 451: */ ! 452: unupdatefpp(addr, us->us_nextpage); ! 453: if (m != 0){ ! 454: if (off){ ! 455: #ifdef ISO ! 456: /* ! 457: * Move snpa header over by 4 bytes to skip ! 458: * the trailer Type and Header length fields. ! 459: */ ! 460: struct snpa_hdr sh; ! 461: ! 462: bcopy(mtod(m, char *), (caddr_t)&sh, sizeof(struct snpa_hdr)); ! 463: m->m_off += 2 * sizeof(u_short); ! 464: m->m_len -= 2 * sizeof(u_short); ! 465: bcopy((caddr_t)&sh, mtod(m, char *), sizeof(struct snpa_hdr)); ! 466: #else ISO ! 467: struct ifnet *ifp; ! 468: /* ! 469: * bcopy is used since word moves must be on 4 byte ! 470: * boundaries on the RT PC ! 471: */ ! 472: bcopy(mtod(m, char *), (char *) &ifp, sizeof(ifp)); ! 473: m->m_off += 2 * sizeof(u_short); ! 474: m->m_len -= 2 * sizeof(u_short); ! 475: bcopy((char *) &ifp, mtod(m, char *), sizeof(ifp)); ! 476: #endif ISO ! 477: } ! 478: switch (type){ ! 479: #ifdef INET ! 480: case ETHERTYPE_IP: ! 481: { ! 482: int s; ! 483: ! 484: DEBUGF(undebug & 0x2, printf("ip packet\n");) ! 485: schednetisr(NETISR_IP); ! 486: s = splimp(); ! 487: inq = &ipintrq; ! 488: if (IF_QFULL(inq)){ ! 489: DEBUGF(undebug & 0x2, printf(" qfull\n");) ! 490: IF_DROP(inq); ! 491: m_freem(m); ! 492: } else { ! 493: IF_ENQUEUE(inq, m); ! 494: DEBUGF(undebug & 0x2, printf(" queued\n");) ! 495: } ! 496: splx(s); ! 497: break; ! 498: } ! 499: ! 500: case ETHERTYPE_ARP: ! 501: DEBUGF(undebug & 0x2, printf("arp packet\n");) ! 502: arpinput(&us->us_ac, m); /* arpinput frees m */ ! 503: break; ! 504: #endif INET ! 505: #ifdef NS ! 506: case ETHERTYPE_NS: ! 507: DEBUGF(undebug & 0x2, printf("ns packet\n");) ! 508: schednetisr(NETISR_NS); ! 509: inq = &nsintrq; ! 510: break; ! 511: #endif NS ! 512: #ifndef IEEELLC ! 513: #ifdef ISO ! 514: case ETHERTYPE_CLNP: /* should be CLNL */ ! 515: DEBUGF(undebug & 0x2, printf("clnl packet\n");) ! 516: ! 517: /* IFF_EAVESDROP can not be turned off for Ethernet */ ! 518: ! 519: schednetisr(NETISR_CLNP); ! 520: inq = &clnlintrq; ! 521: if (IF_QFULL(inq)){ ! 522: DEBUGF(undebug & 0x2, printf(" qfull\n");) ! 523: IF_DROP(inq); ! 524: m_freem(m); ! 525: } else { ! 526: IF_ENQUEUE(inq, m); ! 527: DEBUGF(undebug & 0x2, printf(" queued\n");) ! 528: } ! 529: break; ! 530: #endif ISO ! 531: default: ! 532: DEBUGF(undebug & 0x2, printf("unknown packet\n");) ! 533: m_freem(m); ! 534: break; ! 535: #else ! 536: default: { ! 537: struct llc *l; ! 538: caddr_t pkt_start; ! 539: #ifdef ISO ! 540: #define PREPENDED_SIZE sizeof(struct snpa_hdr) ! 541: #else ! 542: #define PREPENDED_SIZE sizeof(struct ifnet *) ! 543: #endif ISO ! 544: if (type > ETHERMTU) ! 545: goto not802; ! 546: ! 547: /* ! 548: * This assumes that the snpa header is in the same mbuf ! 549: * as the llc header. Currently this is ok, but if ! 550: * unget allocates a cluster, this will not be the case ! 551: */ ! 552: pkt_start = mtod(m, caddr_t); ! 553: l = (struct llc *) (pkt_start + PREPENDED_SIZE); ! 554: ! 555: IFDEBUG(D_ETHER) ! 556: printf("unrint: llc: length %d, control x%x:\n", type, ! 557: l->llc_control); ! 558: ENDDEBUG ! 559: ! 560: switch (l->llc_control) { ! 561: case LLC_UI: ! 562: /* LLC_UI_P forbidden in class 1 service */ ! 563: #ifdef ISO ! 564: if (l->llc_dsap == LLC_ISO_LSAP) { ! 565: if ((IS_MULTICAST(ehbuf.ether_dhost)) && ! 566: ((us->us_if.if_flags & IFF_EAVESDROP) == 0) && ! 567: (!snpac_ownmulti(ehbuf.ether_dhost, 6))) { ! 568: m_freem(m); ! 569: return; ! 570: } ! 571: ! 572: /* move struct snpa_header over the llc header */ ! 573: clnp_ypocb(pkt_start, pkt_start + 3, ! 574: PREPENDED_SIZE); ! 575: m->m_off += 3; ! 576: m->m_len -= 3; ! 577: ! 578: DEBUGF(undebug & 0x2, printf("clnp packet\n");) ! 579: schednetisr(NETISR_CLNP); ! 580: inq = &clnlintrq; ! 581: if (IF_QFULL(inq)){ ! 582: DEBUGF(undebug & 0x2, printf(" qfull\n");) ! 583: IF_DROP(inq); ! 584: m_freem(m); ! 585: } else { ! 586: IF_ENQUEUE(inq, m); ! 587: DEBUGF(undebug & 0x2, printf(" queued\n");) ! 588: } ! 589: return; ! 590: } else { ! 591: IFDEBUG(D_ETHER) ! 592: printf("unrint: unknown llc sap\n"); ! 593: ENDDEBUG ! 594: m_freem(m); ! 595: return; ! 596: } ! 597: #endif ISO ! 598: break; ! 599: /* LLC_XID, LLC_XID_P, LLC_TEST, and LLC_TEST_P are untested */ ! 600: case LLC_XID: ! 601: case LLC_XID_P: /* control field is untouched for resp */ ! 602: if(m->m_len < 6) ! 603: goto not802; ! 604: l->llc_fid = LLC_IEEE_basic_format; ! 605: l->llc_class = LLC_CLASS1; ! 606: l->llc_window = 0; ! 607: l->llc_dsap = l->llc_ssap = 0; ! 608: /* FALL THROUGH */ ! 609: case LLC_TEST: ! 610: case LLC_TEST_P: { ! 611: struct ifnet *ifp = &us->us_if; ! 612: struct sockaddr_iso siso; ! 613: u_char c = l->llc_dsap; ! 614: l->llc_dsap = l->llc_ssap; ! 615: l->llc_ssap = c; ! 616: ! 617: /* Do not TEST or XID to multicasts */ ! 618: if (IS_MULTICAST(ehbuf.ether_dhost)) { ! 619: m_freem(m); ! 620: break; ! 621: } ! 622: ! 623: siso.siso_family = AF_ISO; ! 624: bcopy(ehbuf.ether_shost, siso.siso_addr.sna_idi, 6); ! 625: siso.siso_addr.isoa_afi = AFI_SNA; ! 626: siso.siso_addr.isoa_len = 7; ! 627: ! 628: /* trim off prepended snpa_hdr or ifp */ ! 629: m->m_off += PREPENDED_SIZE; ! 630: m->m_len -= PREPENDED_SIZE; ! 631: ! 632: unoutput(ifp, m, &siso); ! 633: return; ! 634: } ! 635: not802: ! 636: default: ! 637: DEBUGF(undebug & 0x2, printf("unknown packet\n");) ! 638: m_freem(m); ! 639: break; ! 640: } ! 641: } ! 642: #endif IEEELLC ! 643: } ! 644: } ! 645: return; ! 646: chuckit: ! 647: DEBUGF(undebug, printf("unrint: packet dropped\n");) ! 648: unupdatefpp(addr, us->us_nextpage); ! 649: } ! 650: ! 651: /* ! 652: * unxint - interrupt handler for transmit ready ! 653: */ ! 654: unxint(unit, us, addr) ! 655: register int unit; ! 656: register struct un_softc *us; ! 657: register struct undevice *addr; ! 658: { ! 659: register char status; ! 660: register int next_buf; ! 661: ! 662: /* ! 663: * collect stats on last packet ! 664: */ ! 665: status = MM_IN(&addr->un_edlc.xstat); ! 666: MM_OUT(&addr->un_edlc.xstat, status); /* clear status bits */ ! 667: DEBUGF(undebug & 0x2, printf(" unxint: xstat = %b\n", ! 668: status & 0xff, XS_BITS);) ! 669: if (status & XS_16CL){ ! 670: us->us_if.if_collisions += 16; ! 671: us->us_if.if_oerrors++; ! 672: printf("un%d: ethernet jammed\n", unit); ! 673: } ! 674: else if (status & XS_SHRT){ ! 675: us->us_if.if_oerrors++; ! 676: printf( "un%d: ethernet not responding (is it connected?)\n", ! 677: unit); ! 678: } ! 679: else { ! 680: us->us_if.if_opackets++; ! 681: us->us_if.if_collisions += UN_NCOLL(addr); ! 682: } ! 683: DEBUGF(undebug & 0x2, ! 684: printf(" ipkt = %d ierr = %d okt = %d oerr = %d coll = %d\n", ! 685: us->us_if.if_ipackets, us->us_if.if_ierrors, ! 686: us->us_if.if_opackets, us->us_if.if_oerrors, ! 687: us->us_if.if_collisions);) ! 688: /* mark the current transmit buffer empty */ ! 689: us->us_xfull[us->us_xbuf] = 0; ! 690: /* switch to the other transmit buffer */ ! 691: next_buf = 1 - us->us_xbuf; ! 692: if (us->us_xfull[next_buf]){ /* if it's full */ ! 693: unstart(us, addr, next_buf); /* start output from it */ ! 694: if (us->us_if.if_snd.ifq_head){ /* if more on out queue */ ! 695: struct mbuf *m; ! 696: ! 697: IF_DEQUEUE(&us->us_if.if_snd, m); /* fill empty buf */ ! 698: unput(us, addr, m, 1 - next_buf); ! 699: } ! 700: } ! 701: else { /* the other transmit buffer is empty */ ! 702: us->us_oactive = 0; ! 703: MM_OUT(&addr->un_csr, UN_PAVIENB); /* Turn off TxRIENB */ ! 704: } ! 705: } ! 706: ! 707: /* ! 708: * unoutput - ethernet output routine. encapsulate a packet of type ! 709: * family for the local net. use trailer local net encapsulation if ! 710: * the number of bytes in the mbufs after the first is a multiple of ! 711: * 512. ! 712: */ ! 713: unoutput(ifp, m0, dst) ! 714: register struct ifnet *ifp; ! 715: register struct mbuf *m0; ! 716: register struct sockaddr *dst; ! 717: { ! 718: u_short type; ! 719: int s; ! 720: int error; ! 721: char edst[ETH_ADDR_SIZE]; ! 722: struct in_addr idst; ! 723: register struct un_softc *us = &un_softc[ifp->if_unit]; ! 724: register struct mbuf *m = m0; ! 725: register struct ether_header *eh; ! 726: int off; ! 727: struct mbuf *m_get(); ! 728: int usetrailers; ! 729: ! 730: if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)){ ! 731: error = ENETDOWN; ! 732: goto bad; ! 733: } ! 734: switch (dst->sa_family){ ! 735: ! 736: #ifdef INET ! 737: case AF_INET: ! 738: idst = ((struct sockaddr_in *)dst)->sin_addr; ! 739: if (!arpresolve(&us->us_ac, m, &idst, edst, &usetrailers)){ ! 740: /* not resolved */ ! 741: return(0); ! 742: } ! 743: off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; ! 744: if (usetrailers && off > 0 && (off & 0x1ff) == 0 && ! 745: m->m_off >= MMINOFF + 2 * sizeof(u_short)){ ! 746: type = ETHERTYPE_TRAIL + (off>>9); ! 747: m->m_off -= 2 * sizeof(u_short); ! 748: m->m_len += 2 * sizeof(u_short); ! 749: *mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP); ! 750: *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len); ! 751: /* ! 752: * Packet to be sent with trailer, move first packet ! 753: * (control information) to end of chain. ! 754: */ ! 755: while (m->m_next) ! 756: m = m->m_next; ! 757: m->m_next = m0; ! 758: m = m0->m_next; ! 759: m0->m_next = 0; ! 760: m0 = m; ! 761: } ! 762: else { ! 763: type = ETHERTYPE_IP; ! 764: } ! 765: break; ! 766: #endif INET ! 767: #ifdef NS ! 768: case AF_NS: ! 769: bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), ! 770: (caddr_t)edst, sizeof(edst)); ! 771: type = ETHERTYPE_NS; ! 772: off = 0; ! 773: break; ! 774: #endif NS ! 775: #ifdef ISO ! 776: case AF_ISO: { ! 777: int ret; ! 778: int len; ! 779: struct iso_addr *dst_nsap = &((struct sockaddr_iso *)dst)->siso_addr; ! 780: ! 781: if ((ret = iso_tryloopback(m, dst)) >= 0) ! 782: return (ret); ! 783: else if (ret = iso_snparesolve(&us->us_ac.ac_if, dst_nsap, edst, &len)){ ! 784: /* not resolved */ ! 785: IFDEBUG(D_ETHER) ! 786: printf("unoutput: clnp packet dropped\n"); ! 787: ENDDEBUG ! 788: m_freem(m); ! 789: return(ret); ! 790: } else if (len != 6) { ! 791: printf("unoutput: snpa len is not 6 (%d)\n", len); ! 792: m_freem(m); ! 793: return(ENETUNREACH); ! 794: } ! 795: ! 796: #ifndef IEEELLC ! 797: type = ETHERTYPE_CLNP; ! 798: #else ! 799: /* check for enough space for LLC header */ ! 800: { ! 801: struct mbuf *llcm; ! 802: char *cp; ! 803: if (m->m_off >= MMAXOFF || m->m_off < MMINOFF + 3) { ! 804: MGET(llcm, M_DONTWAIT, MT_DATA); ! 805: if (llcm == NULL) { ! 806: m_freem(m); ! 807: return(0); ! 808: } ! 809: llcm->m_off = MMAXOFF - 3; ! 810: llcm->m_len = 3; ! 811: llcm->m_next = m; ! 812: m = llcm; ! 813: } else { ! 814: m->m_off -= 3; ! 815: m->m_len += 3; ! 816: } ! 817: type = m_datalen(m); ! 818: ! 819: cp = mtod(m, u_char *); ! 820: cp[0] = cp[1] = LLC_ISO_LSAP; cp[2] = LLC_UI; ! 821: off = 0; ! 822: } ! 823: #endif IEEELLC ! 824: off = 0; ! 825: IFDEBUG(D_ETHER) ! 826: int i; ! 827: printf("unoutput: sending pkt to: "); ! 828: for (i=0; i<6; i++) ! 829: printf("%x ", edst[i] & 0xff); ! 830: #ifdef IEEELLC ! 831: printf(" llc len %d", type); ! 832: #endif IEEELLC ! 833: printf("\n"); ! 834: ENDDEBUG ! 835: } break; ! 836: #endif ISO ! 837: case AF_UNSPEC: ! 838: eh = (struct ether_header *)dst->sa_data; ! 839: bcopy((char *)eh->ether_dhost, (caddr_t)edst, sizeof(edst)); ! 840: type = eh->ether_type; ! 841: break; ! 842: default: ! 843: printf("un%d: can't handle af%d\n", ifp->if_unit, ! 844: dst->sa_family); ! 845: error = EAFNOSUPPORT; ! 846: goto bad; ! 847: } ! 848: /* ! 849: * Add local net header. If no space in first mbuf, ! 850: * allocate another. ! 851: */ ! 852: if (m->m_off > MMAXOFF || ! 853: MMINOFF + sizeof(struct ether_header) > m->m_off){ ! 854: m = m_get(M_DONTWAIT, MT_HEADER); ! 855: /* ! 856: * Note: m_get, m_freem etc. guard against concurrent ! 857: * updates to the list of free mbufs. ! 858: */ ! 859: if (m == 0){ ! 860: error = ENOBUFS; ! 861: goto bad; ! 862: } ! 863: m->m_next = m0; ! 864: m->m_off = MMINOFF; ! 865: m->m_len = sizeof(struct ether_header); ! 866: } else { ! 867: m->m_off -= sizeof(struct ether_header); ! 868: m->m_len += sizeof(struct ether_header); ! 869: } ! 870: eh = mtod(m, struct ether_header *); ! 871: bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof(edst)); ! 872: bcopy((caddr_t)us->us_addr, (caddr_t)eh->ether_shost, ! 873: sizeof(eh->ether_shost)); ! 874: bcopy((caddr_t)&type, (caddr_t)&eh->ether_type, sizeof(u_short)); ! 875: ! 876: /* ! 877: * queue packet for transmission. if there is an empty ! 878: * transmit buffer on the adapter, use it. ! 879: */ ! 880: s = splimp(); ! 881: if (IF_QFULL(&ifp->if_snd)){ ! 882: IF_DROP(&ifp->if_snd); ! 883: error = ENOBUFS; ! 884: goto qfull; ! 885: } ! 886: if (us->us_xfull[0] == 0 || us->us_xfull[1] == 0){ /* empty xmt buf */ ! 887: struct undevice *addr = (struct undevice *) ! 888: uninfo[ifp->if_unit]->iod_addr; ! 889: int next_buf; ! 890: #ifdef ATR ! 891: int old_window; ! 892: move_window(old_window, addr); ! 893: #endif ATR ! 894: if (us->us_xfull[0] == 0){ ! 895: next_buf = 0; ! 896: } ! 897: else { ! 898: next_buf = 1; ! 899: } ! 900: unput(us, addr, m, next_buf); ! 901: if (us->us_oactive == 0){ ! 902: unstart(us, addr, next_buf); ! 903: } ! 904: #ifdef ATR ! 905: restore_window(old_window); ! 906: #endif ATR ! 907: } ! 908: else { ! 909: IF_ENQUEUE(&ifp->if_snd, m); ! 910: } ! 911: splx(s); ! 912: return(0); ! 913: qfull: ! 914: m0 = m; ! 915: splx(s); ! 916: bad: ! 917: m_freem(m0); ! 918: return(error); ! 919: } ! 920: ! 921: /* ! 922: * unput - copy packet from an mbuf chain to one of the adapter's ! 923: * transmit buffers. the packet is extended to the minimum legal ! 924: * size if necessary. the extra bytes could be zeroed out to improve ! 925: * security but are not to maximize performance. ! 926: */ ! 927: unput(us, addr, m, xbuf) ! 928: struct un_softc *us; ! 929: struct undevice *addr; ! 930: register struct mbuf *m; ! 931: register int xbuf; ! 932: { ! 933: register unsigned off; ! 934: register struct mbuf *mp; ! 935: register char *bp; ! 936: ! 937: /* ! 938: * compute starting address in transmit buffer. packets must be ! 939: * "end_aligned". ! 940: */ ! 941: for (off = UN_XBSIZE, mp = m; mp; mp = mp->m_next){ ! 942: off -= mp->m_len; ! 943: } ! 944: if (UN_XBSIZE - off < ETHERMIN + sizeof(struct ether_header)){ ! 945: /* packet too short => extend it */ ! 946: off = UN_XBSIZE - ETHERMIN - sizeof(struct ether_header); ! 947: } ! 948: if (xbuf == 1){ /* use the second buffer */ ! 949: off += UN_XBSIZE; /* the 2 buffers are adjacent */ ! 950: } ! 951: bp = ((char *)(addr->un_xmtbuf)) + off; ! 952: for (mp = m; mp; mp = mp->m_next){ ! 953: register unsigned len = mp->m_len; ! 954: ! 955: bcopyout(mtod(mp, char *), bp, len); ! 956: bp += len; ! 957: } ! 958: /* save starting address so interrupt handler can find it */ ! 959: us->us_xstart[xbuf] = off; /* start address to be passed to adapter */ ! 960: us->us_xfull[xbuf] = 1; /* mark buffer full */ ! 961: m_freem(m); ! 962: } ! 963: ! 964: /* ! 965: * unget - copy packet from adapter's receive buffers into a chain of mbufs ! 966: * ! 967: */ ! 968: struct mbuf * ! 969: unget(addr, unbuf, totlen, off0, ifp) ! 970: struct undevice *addr; ! 971: char *unbuf; ! 972: register int totlen; ! 973: int off0; ! 974: struct ifnet *ifp; ! 975: { ! 976: register struct mbuf *m; ! 977: struct mbuf *top = 0; ! 978: register struct mbuf **mp = ⊤ ! 979: register int off = off0; ! 980: register int len; ! 981: register char *cp; ! 982: #ifdef ISO ! 983: int copied_snpa = 0; ! 984: #endif ISO ! 985: ! 986: cp = unbuf + sizeof(struct ether_header); ! 987: while (totlen > 0){ ! 988: char *mcp; ! 989: ! 990: MGET(m, M_DONTWAIT, MT_DATA); ! 991: if (m == 0) ! 992: goto bad; ! 993: if (off){ /* trailer exists */ ! 994: len = totlen - off; ! 995: cp = unbuf + sizeof(struct ether_header) + off; ! 996: } else ! 997: len = totlen; ! 998: #ifdef ISO ! 999: if (!copied_snpa) ! 1000: len += sizeof(struct snpa_hdr); ! 1001: #else ISO ! 1002: if (ifp) ! 1003: len += sizeof(ifp); ! 1004: #endif ISO ! 1005: if (len >= NBPG){ ! 1006: MCLGET(m); ! 1007: if (m->m_len == CLBYTES) ! 1008: m->m_len = len = MIN(len, CLBYTES); ! 1009: else ! 1010: m->m_len = len = MIN(MLEN, len); ! 1011: } else { ! 1012: m->m_len = len = MIN(MLEN, len); ! 1013: m->m_off = MMINOFF; ! 1014: } ! 1015: mcp = mtod(m, char *); ! 1016: #ifdef ISO ! 1017: if (!copied_snpa) { ! 1018: /* ! 1019: * Prepend snpa_hdr to first mbuf ! 1020: * The hardcoded 12 below refers to the length of the dhost ! 1021: * and shost fields. We recklessly assume ! 1022: * the order of dhost,shost in the snpa_hdr is the same ! 1023: * as the order in the ether_header. ! 1024: */ ! 1025: struct snpa_hdr *sh = (struct snpa_hdr *)mcp; ! 1026: struct ether_header *eh = (struct ether_header *)unbuf; ! 1027: ! 1028: bcopy((char *) &ifp, (caddr_t)&sh->snh_ifp, sizeof(ifp)); ! 1029: bcopy((caddr_t)eh, (caddr_t)sh->snh_dhost, 12); ! 1030: mcp += sizeof(struct snpa_hdr); ! 1031: len -= sizeof(struct snpa_hdr); ! 1032: copied_snpa = 1; ! 1033: } ! 1034: #else ISO ! 1035: if (ifp){ ! 1036: /* prepend ifp to first mbuf */ ! 1037: /* ! 1038: * bcopy is used since since word moves must ! 1039: * be on 4 byte boundaries on the RT PC ! 1040: */ ! 1041: bcopy((char *) &ifp, mcp, sizeof(ifp)); ! 1042: mcp += sizeof(ifp); ! 1043: len -= sizeof(ifp); ! 1044: ifp = (struct ifnet *) 0; ! 1045: } ! 1046: #endif ISO ! 1047: unbcopy(addr, cp, mcp, len); ! 1048: cp += len; ! 1049: *mp = m; ! 1050: mp = &m->m_next; ! 1051: if (off == 0){ ! 1052: totlen -= len; ! 1053: continue; ! 1054: } ! 1055: off += len; ! 1056: if (off == totlen){ ! 1057: cp = unbuf + sizeof(struct ether_header); ! 1058: off = 0; ! 1059: totlen = off0; ! 1060: } ! 1061: } ! 1062: return(top); ! 1063: bad: ! 1064: m_freem(top); ! 1065: return(0); ! 1066: } ! 1067: ! 1068: ! 1069: /* ! 1070: * ioctl - process an ioctl request. ! 1071: */ ! 1072: unioctl(ifp, cmd, data) ! 1073: register struct ifnet *ifp; ! 1074: register int cmd; ! 1075: register caddr_t data; ! 1076: { ! 1077: register struct ifaddr *ifa = (struct ifaddr *)data; ! 1078: register int s = splimp(); ! 1079: register int error = 0; ! 1080: ! 1081: switch (cmd){ ! 1082: case SIOCSIFADDR: ! 1083: ifp->if_flags |= IFF_UP; ! 1084: ! 1085: switch (ifa->ifa_addr.sa_family){ ! 1086: #ifdef INET ! 1087: case AF_INET: ! 1088: uninit(ifp->if_unit); /* before arpwhohas */ ! 1089: ((struct arpcom *) ifp)->ac_ipaddr = ! 1090: IA_SIN(ifa)->sin_addr; ! 1091: arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); ! 1092: break; ! 1093: #endif INET ! 1094: #ifdef NS ! 1095: case AF_NS: ! 1096: { ! 1097: struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); ! 1098: struct un_softc *us = &un_softc[ifp->if_unit]; ! 1099: ! 1100: if (ns_nullhost(*ina)) ! 1101: ina->x_host = *(union ns_host *)(us->us_addr); ! 1102: else { ! 1103: ifp->if_flags &= ~IFF_RUNNING; ! 1104: bcopy((caddr_t) ina->x_host.c_host, ! 1105: (caddr_t) us->us_addr, sizeof(us->us_addr)); ! 1106: /* ! 1107: * the uninit will set the hardware address ! 1108: * since the IFF_RUNNING flag is off ! 1109: */ ! 1110: } ! 1111: uninit(ifp->if_unit); ! 1112: break; ! 1113: } ! 1114: #endif NS ! 1115: default: ! 1116: uninit(ifp->if_unit); ! 1117: break; ! 1118: } ! 1119: break; ! 1120: case SIOCSIFFLAGS: ! 1121: if ((ifp->if_flags & IFF_UP) == 0 && ifp->if_flags & ! 1122: IFF_RUNNING){ ! 1123: #ifdef ATR ! 1124: int old_window; ! 1125: #endif ATR ! 1126: struct undevice *addr; ! 1127: ! 1128: addr = (struct undevice *) uninfo[ifp->if_unit]-> ! 1129: iod_addr; ! 1130: #ifdef ATR ! 1131: move_window(old_window, addr); ! 1132: #endif ATR ! 1133: (void) unzap((struct undevice *) addr); ! 1134: ifp->if_flags &= ~IFF_RUNNING; ! 1135: #ifdef ATR ! 1136: restore_window(old_window); ! 1137: #endif ATR ! 1138: } else if (ifp->if_flags & IFF_UP && (ifp->if_flags & ! 1139: IFF_RUNNING) == 0) ! 1140: uninit(ifp->if_unit); ! 1141: break; ! 1142: default: ! 1143: error = EINVAL; ! 1144: } ! 1145: splx(s); ! 1146: return(error); ! 1147: } ! 1148: ! 1149: /* ! 1150: * unzap - initialize adapter but don't enable it. ! 1151: * returns page number of next receive page to be used. ! 1152: */ ! 1153: unzap(addr) ! 1154: register struct undevice *addr; ! 1155: { ! 1156: register int next; ! 1157: ! 1158: MM_OUT(&addr->un_csr, 0); /* disable interrupts */ ! 1159: MM_OUT(&addr->un_edlc.reset, RESET_ON); ! 1160: /* set reset bit while init'ing */ ! 1161: MM_OUT(&addr->un_edlc.rstat, RS_CLEAR); ! 1162: MM_OUT(&addr->un_edlc.xstat, XS_CLEAR); ! 1163: MM_OUT(&addr->un_edlc.rmask, 0); ! 1164: MM_OUT(&addr->un_edlc.xmask, 0); ! 1165: MM_OUT(&addr->un_edlc.rmode, RM_NORMAL); ! 1166: /* ! 1167: * the next line puts the transmitter in loopback mode so ! 1168: * that a spurious packet is not sent when the reset bit is ! 1169: * cleared. ! 1170: */ ! 1171: MM_OUT(&addr->un_edlc.tmode, TM_NORMAL - TM_LBC); ! 1172: MM_OUT(&addr->un_edlc.reset, RESET_OFF); /* clear reset bit */ ! 1173: /* ! 1174: * clear the receive buffers. assign the value in the empty ! 1175: * page pointer to the full page pointer and clear the packet ! 1176: * available flag. ! 1177: */ ! 1178: next = MM_IN(&addr->un_fppepp) & UN_PAGE_MASK; ! 1179: /* clears the IKSYDK flag */ ! 1180: MM_OUT(&addr->un_fppepp, next); /* fpp = epp */ ! 1181: UN_CLRPAV(addr); /* clear the PAV flag */ ! 1182: MM_OUT(&addr->un_edlc.tmode, TM_NORMAL); ! 1183: /* put transmitter in normal mode */ ! 1184: DEBUGF(undebug & 0x2, printf("unzap: zzzzapped!\n");) ! 1185: return(next); ! 1186: } ! 1187: ! 1188: /* ! 1189: * unupdatefpp - update adapter's full page pointer and clear packet available ! 1190: * flag if appropriate ! 1191: */ ! 1192: unupdatefpp(addr, nextpage) ! 1193: register struct undevice *addr; ! 1194: register int nextpage; ! 1195: { ! 1196: if (nextpage == /* EPP */ (MM_IN(&addr->un_fppepp) & UN_PAGE_MASK)) ! 1197: UN_CLRPAV(addr); ! 1198: MM_OUT(&addr->un_fppepp, nextpage); /* set FPP */ ! 1199: } ! 1200: ! 1201: /* ! 1202: * unbcopy - similar to bcopy but can deal with packets that wrap ! 1203: * around from the high end of the adapter's receive buffer to the ! 1204: * low end ! 1205: */ ! 1206: unbcopy(addr, from, to, len) ! 1207: register struct undevice *addr; ! 1208: register char *from; ! 1209: register char *to; ! 1210: register int len; ! 1211: { ! 1212: register char *high_end = &addr->un_rcvbuf[UN_LASTRBUF][UN_RBUFSIZE]; ! 1213: register int n; ! 1214: ! 1215: if (from + len <= high_end){ ! 1216: bcopyin(from, to, len); ! 1217: } ! 1218: else if (from >= high_end){ ! 1219: from -= sizeof(addr->un_rcvbuf); ! 1220: bcopyin(from, to, len); ! 1221: } else { ! 1222: n = high_end - from; ! 1223: bcopyin(from, to, n); ! 1224: to += n; ! 1225: bcopyin((char *)addr->un_rcvbuf, to, len - n); ! 1226: } ! 1227: } ! 1228: ! 1229: /* ! 1230: * ungetushortatoff - return the u_short at offset in the received packet, ! 1231: * handling wrap-around in the receive buffer and conversion between network ! 1232: * and host formats as necessary. ! 1233: */ ! 1234: u_short ungetushortatoff(addr, eh, off) ! 1235: register struct undevice *addr; ! 1236: register struct ether_header *eh; ! 1237: register int off; ! 1238: { ! 1239: register char *high_end = &addr->un_rcvbuf[UN_LASTRBUF][UN_RBUFSIZE]; ! 1240: register char *p; ! 1241: ! 1242: p = (caddr_t)(eh + 1) + off; ! 1243: if (p >= high_end){ ! 1244: p -= sizeof(addr->un_rcvbuf); ! 1245: } ! 1246: return(ntohs((u_short) MM_INW(p))); ! 1247: } ! 1248: ! 1249: /* ! 1250: * unprintethaddr - print an ethernet address ! 1251: */ ! 1252: unprintethaddr(p) ! 1253: register char *p; ! 1254: { ! 1255: register int i; ! 1256: ! 1257: for (i = 0; i < ETH_ADDR_SIZE; i++){ ! 1258: if (i != 0) printf(":"); ! 1259: printf("%x", *p++); ! 1260: } ! 1261: } ! 1262: ! 1263: #endif NUN > 0
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.