|
|
1.1.1.3 ! root 1: /* ! 2: * Isolan AT 4141-0 Ethernet driver ! 3: * Isolink 4110 1.1 root 4: * 1.1.1.3 ! root 5: * By Paul Richards 1.1 root 6: * 1.1.1.3 ! root 7: * Copyright (C) 1993, Paul Richards. This software may be used, modified, ! 8: * copied, distributed, and sold, in both source and binary form provided ! 9: * that the above copyright and these terms are retained. Under no ! 10: * circumstances is the author responsible for the proper functioning ! 11: * of this software, nor does the author assume any responsibility ! 12: * for damages incurred with its use. 1.1 root 13: * 1.1.1.3 ! root 14: */ 1.1 root 15: 1.1.1.3 ! root 16: /* TODO ! 17: ! 18: 1) Add working multicast support ! 19: 2) Use better allocation of memory to card ! 20: 3) Advertise for more packets until all transmit buffers are full ! 21: 4) Add more of the timers/counters e.g. arpcom.opackets etc. ! 22: */ 1.1 root 23: 24: #include "is.h" 25: #if NIS > 0 26: 1.1.1.3 ! root 27: #include "bpfilter.h" ! 28: 1.1 root 29: #include "param.h" 1.1.1.3 ! root 30: #include "errno.h" ! 31: #include "ioctl.h" 1.1 root 32: #include "mbuf.h" 33: #include "socket.h" 34: #include "syslog.h" 35: 36: #include "net/if.h" 1.1.1.3 ! root 37: #include "net/if_dl.h" ! 38: #include "net/if_types.h" 1.1 root 39: #include "net/netisr.h" 40: 41: #ifdef INET 42: #include "netinet/in.h" 43: #include "netinet/in_systm.h" 44: #include "netinet/in_var.h" 45: #include "netinet/ip.h" 46: #include "netinet/if_ether.h" 47: #endif 48: 49: #ifdef NS 50: #include "netns/ns.h" 51: #include "netns/ns_if.h" 52: #endif 53: 1.1.1.3 ! root 54: #if NBPFILTER > 0 ! 55: #include "net/bpf.h" ! 56: #include "net/bpfdesc.h" ! 57: #endif ! 58: 1.1 root 59: #include "i386/isa/isa_device.h" 60: #include "i386/isa/if_isreg.h" 61: #include "i386/isa/icu.h" 62: 63: #include "vm/vm.h" 64: 65: 66: 67: #define ETHER_MIN_LEN 64 1.1.1.3 ! root 68: #define ETHER_MAX_LEN 1518 ! 69: #define ETHER_ADDR_LEN 6 ! 70: 1.1 root 71: 72: /* 73: * Ethernet software status per interface. 74: * 75: * Each interface is referenced by a network interface structure, 1.1.1.3 ! root 76: * arpcom.ac_if, which the routing code uses to locate the interface. 1.1 root 77: * This structure contains the output queue for the interface, its address, ... 78: */ 79: struct is_softc { 1.1.1.3 ! root 80: struct arpcom arpcom; /* Ethernet common part */ ! 81: int iobase; /* IO base address of card */ ! 82: struct mds *rd; ! 83: struct mds *td; ! 84: unsigned char *rbuf; ! 85: unsigned char *tbuf; 1.1 root 86: int last_rd; 87: int last_td; 88: int no_td; 1.1.1.3 ! root 89: caddr_t bpf; /* BPF "magic cookie" */ ! 90: 1.1 root 91: } is_softc[NIS] ; 92: 1.1.1.3 ! root 93: struct init_block init_block[NIS]; ! 94: ! 95: /* Function prototypes */ ! 96: int is_probe(),is_attach(),is_watchdog(); ! 97: int is_ioctl(),is_init(),is_start(); ! 98: ! 99: static inline void is_rint(int unit); ! 100: static inline void isread(struct is_softc*, unsigned char*, int); 1.1 root 101: 1.1.1.3 ! root 102: struct mbuf *isget(); 1.1 root 103: 1.1.1.3 ! root 104: struct isa_driver isdriver = { ! 105: is_probe, ! 106: is_attach, ! 107: "is" ! 108: }; ! 109: ! 110: iswrcsr(unit,port,val) ! 111: int unit; 1.1 root 112: u_short port; 113: u_short val; 114: { 1.1.1.3 ! root 115: int iobase; ! 116: ! 117: iobase = is_softc[unit].iobase; ! 118: outw(iobase+RAP,port); ! 119: outw(iobase+RDP,val); 1.1 root 120: } 121: 1.1.1.3 ! root 122: u_short isrdcsr(unit,port) ! 123: int unit; 1.1 root 124: u_short port; 125: { 1.1.1.3 ! root 126: int iobase; ! 127: ! 128: iobase = is_softc[unit].iobase; ! 129: outw(iobase+RAP,port); ! 130: return(inw(iobase+RDP)); 1.1 root 131: } 132: 1.1.1.3 ! root 133: is_probe(isa_dev) ! 134: struct isa_device *isa_dev; 1.1 root 135: { 136: int val,i,s; 1.1.1.3 ! root 137: int unit = isa_dev->id_unit ; ! 138: register struct is_softc *is = &is_softc[unit]; 1.1 root 139: 1.1.1.3 ! root 140: is->iobase = isa_dev->id_iobase; 1.1 root 141: 142: /* Stop the lance chip, put it known state */ 1.1.1.3 ! root 143: iswrcsr(unit,0,STOP); 1.1 root 144: DELAY(100); 145: 146: /* is there a lance? */ 1.1.1.3 ! root 147: iswrcsr(unit,3, 0xffff); ! 148: if (isrdcsr(unit,3) != 7) { ! 149: is->iobase = 0; 1.1 root 150: return (0); 151: } 1.1.1.3 ! root 152: iswrcsr(unit,3, 0); 1.1 root 153: 154: /* Extract board address */ 1.1.1.3 ! root 155: for(i=0;i<ETHER_ADDR_LEN;i++) ! 156: is->arpcom.ac_enaddr[i]=inb(is->iobase+(i*2)); 1.1 root 157: 158: return (1); 159: } 160: 161: 162: 163: /* 164: * Reset of interface. 165: */ 1.1.1.3 ! root 166: int is_reset(int unit) 1.1 root 167: { 1.1.1.3 ! root 168: int s; 1.1 root 169: if (unit >= NIS) 170: return; 1.1.1.3 ! root 171: s = splnet(); 1.1 root 172: printf("is%d: reset\n", unit); 1.1.1.3 ! root 173: is_init(unit); ! 174: s = splx(); 1.1 root 175: } 176: 177: /* 178: * Interface exists: make available by filling in network interface 179: * record. System will initialize the interface when it is ready 180: * to accept packets. We get the ethernet address here. 181: */ 1.1.1.3 ! root 182: int is_attach(isa_dev) ! 183: struct isa_device *isa_dev; 1.1 root 184: { 1.1.1.3 ! root 185: int unit = isa_dev->id_unit; ! 186: struct is_softc *is = &is_softc[unit]; ! 187: struct ifnet *ifp = &is->arpcom.ac_if; ! 188: struct ifaddr *ifa; ! 189: struct sockaddr_dl *sdl; ! 190: 1.1 root 191: 192: 193: ifp->if_unit = unit; 194: ifp->if_name = isdriver.name ; 195: ifp->if_mtu = ETHERMTU; 196: ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS; 1.1.1.3 ! root 197: ifp->if_init = is_init; 1.1 root 198: ifp->if_output = ether_output; 1.1.1.3 ! root 199: ifp->if_start = is_start; ! 200: ifp->if_ioctl = is_ioctl; ! 201: ifp->if_reset = is_reset; ! 202: ifp->if_watchdog = is_watchdog; ! 203: ! 204: /* Set up DMA */ ! 205: isa_dmacascade(isa_dev->id_drq); ! 206: 1.1 root 207: if_attach(ifp); 1.1.1.2 root 208: 1.1.1.3 ! root 209: /* ! 210: * Search down the ifa address list looking for the AF_LINK type ! 211: entry ! 212: */ ! 213: ifa = ifp->if_addrlist; ! 214: while ((ifa != 0) && (ifa->ifa_addr != 0) && ! 215: (ifa->ifa_addr->sa_family != AF_LINK)) ! 216: ifa = ifa->ifa_next; ! 217: ! 218: /* ! 219: * If we find an AF_LINK type entry, we will fill ! 220: * in the hardware address for this interface. ! 221: */ ! 222: if ((ifa != 0) && (ifa->ifa_addr != 0)) { ! 223: /* ! 224: * Fill in the link level address for this interface ! 225: */ ! 226: sdl = (struct sockaddr_dl *)ifa->ifa_addr; ! 227: sdl->sdl_type = IFT_ETHER; ! 228: sdl->sdl_alen = ETHER_ADDR_LEN; ! 229: sdl->sdl_slen = 0; ! 230: bcopy(is->arpcom.ac_enaddr, LLADDR(sdl), ETHER_ADDR_LEN); ! 231: } ! 232: ! 233: printf ("is%d: address %s\n", unit, ! 234: ether_sprintf(is->arpcom.ac_enaddr)) ; ! 235: ! 236: #if NBPFILTER > 0 ! 237: bpfattach(&is->bpf, ifp, DLT_EN10MB, sizeof(struct ether_header)); ! 238: #endif ! 239: } ! 240: ! 241: int ! 242: is_watchdog(unit) ! 243: int unit; ! 244: { ! 245: log(LOG_ERR, "is%d: device timeout\n", unit); ! 246: ! 247: is_reset(unit); 1.1 root 248: } 249: 250: 251: /* Lance initialisation block set up */ 1.1.1.3 ! root 252: init_mem(unit) ! 253: int unit; 1.1 root 254: { 255: int i; 256: u_long temp; 1.1.1.3 ! root 257: struct is_softc *is = &is_softc[unit]; 1.1 root 258: 259: /* Allocate memory */ 260: /* Temporary hack, will use kmem_alloc in future */ 261: #define MAXMEM ((NRBUF+NTBUF)*(BUFSIZE) + (NRBUF+NTBUF)*sizeof(struct mds) + 8) 1.1.1.3 ! root 262: static u_char lance_mem[NIS][MAXMEM]; 1.1 root 263: 264: 265: /* Align message descriptors on quad word boundary 266: (this is essential) */ 267: 1.1.1.3 ! root 268: temp = (u_long) &lance_mem[unit]; 1.1 root 269: temp = (temp+8) - (temp%8); 1.1.1.3 ! root 270: is->rd = (struct mds *) temp; ! 271: is->td = (struct mds *) (temp + (NRBUF*sizeof(struct mds))); 1.1 root 272: temp += (NRBUF+NTBUF) * sizeof(struct mds); 273: 1.1.1.3 ! root 274: init_block[unit].mode = 0; 1.1 root 275: 276: 1.1.1.3 ! root 277: ! 278: init_block[unit].rdra = kvtop(is->rd); ! 279: init_block[unit].rlen = ((kvtop(is->rd) >> 16) & 0xff) | (RLEN<<13); ! 280: init_block[unit].tdra = kvtop(is->td); ! 281: init_block[unit].tlen = ((kvtop(is->td) >> 16) & 0xff) | (TLEN<<13); 1.1 root 282: 283: /* Set up receive ring descriptors */ 1.1.1.3 ! root 284: is->rbuf = (unsigned char *)temp; 1.1 root 285: for (i=0; i<NRBUF; i++) { 1.1.1.3 ! root 286: (is->rd+i)->addr = kvtop(temp); ! 287: (is->rd+i)->flags= ((kvtop(temp) >> 16) & 0xff) | OWN; ! 288: (is->rd+i)->bcnt = -BUFSIZE; ! 289: (is->rd+i)->mcnt = 0; 1.1 root 290: temp += BUFSIZE; 291: } 292: 293: /* Set up transmit ring descriptors */ 1.1.1.3 ! root 294: is->tbuf = (unsigned char *)temp; ! 295: #if ISDEBUG > 4 ! 296: printf("rd = %x,td = %x, rbuf = %x, tbuf = %x,td+1=%x\n",is->rd,is->td,is->rbuf,is->tbuf,is->td+1); 1.1 root 297: #endif 298: for (i=0; i<NTBUF; i++) { 1.1.1.3 ! root 299: (is->td+i)->addr = kvtop(temp); ! 300: (is->td+i)->flags= ((kvtop(temp) >> 16) & 0xff); ! 301: (is->td+i)->bcnt = 0; ! 302: (is->td+i)->mcnt = 0; 1.1 root 303: temp += BUFSIZE; 304: } 305: 306: } 307: 308: /* 309: * Initialization of interface; set up initialization block 310: * and transmit/receive descriptor rings. 311: */ 1.1.1.3 ! root 312: is_init(unit) 1.1 root 313: int unit; 314: { 1.1.1.3 ! root 315: register struct is_softc *is = &is_softc[unit]; ! 316: struct ifnet *ifp = &is->arpcom.ac_if; 1.1 root 317: int s; 318: register i; 319: 1.1.1.3 ! root 320: /* Address not known */ 1.1 root 321: if (ifp->if_addrlist == (struct ifaddr *)0) return; 322: 1.1.1.3 ! root 323: s = splnet(); ! 324: is->last_rd = is->last_td = is->no_td = 0; 1.1 root 325: 326: /* Set up lance's memory area */ 1.1.1.3 ! root 327: init_mem(unit); 1.1 root 328: 329: /* Stop Lance to get access to other registers */ 1.1.1.3 ! root 330: iswrcsr(unit,0,STOP); ! 331: ! 332: /* Get ethernet address */ ! 333: for (i=0; i<ETHER_ADDR_LEN; i++) ! 334: init_block[unit].padr[i] = is->arpcom.ac_enaddr[i]; ! 335: ! 336: #if NBPFILTER > 0 ! 337: /* ! 338: * Initialize multicast address hashing registers to accept ! 339: * all multicasts (only used when in promiscuous mode) ! 340: */ ! 341: for (i = 0; i < 8; ++i) ! 342: init_block[unit].ladrf[i] = 0xff; ! 343: #endif ! 344: 1.1 root 345: 346: /* I wish I knew what this was */ 1.1.1.3 ! root 347: iswrcsr(unit,3,0); 1.1 root 348: 349: /* Give lance the physical address of its memory area */ 1.1.1.3 ! root 350: iswrcsr(unit,1,kvtop(&init_block[unit])); ! 351: iswrcsr(unit,2,(kvtop(&init_block[unit]) >> 16) & 0xff); 1.1 root 352: 353: /* OK, let's try and initialise the Lance */ 1.1.1.3 ! root 354: iswrcsr(unit,0,INIT); 1.1 root 355: 356: /* Wait for initialisation to finish */ 357: for(i=0; i<1000; i++){ 1.1.1.3 ! root 358: if (isrdcsr(unit,0)&IDON) 1.1 root 359: break; 360: } 1.1.1.3 ! root 361: if (isrdcsr(unit,0)&IDON) { 1.1 root 362: /* Start lance */ 1.1.1.3 ! root 363: iswrcsr(unit,0,STRT|IDON|INEA); ! 364: ifp->if_flags |= IFF_RUNNING; ! 365: ifp->if_flags &= ~IFF_OACTIVE; ! 366: ! 367: is_start(ifp); 1.1 root 368: } 369: else 1.1.1.3 ! root 370: printf("is%d: card failed to initialise\n", unit); 1.1 root 371: 1.1.1.3 ! root 372: (void) splx(s); 1.1 root 373: } 374: 375: /* 376: * Setup output on interface. 377: * Get another datagram to send off of the interface queue, 378: * and map it to the interface before starting the output. 379: * called only at splimp or interrupt level. 380: */ 1.1.1.3 ! root 381: is_start(ifp) 1.1 root 382: struct ifnet *ifp; 383: { 1.1.1.3 ! root 384: int unit = ifp->if_unit; ! 385: register struct is_softc *is = &is_softc[unit]; 1.1 root 386: struct mbuf *m0, *m; 387: unsigned char *buffer; 388: u_short len; 389: int i; 390: struct mds *cdm; 391: 392: 1.1.1.3 ! root 393: if ((is->arpcom.ac_if.if_flags & IFF_RUNNING) == 0) 1.1 root 394: return; 395: 396: do { 1.1.1.3 ! root 397: cdm = (is->td + is->last_td); 1.1 root 398: if (cdm->flags&OWN) 399: return; 400: 1.1.1.3 ! root 401: IF_DEQUEUE(&is->arpcom.ac_if.if_snd, m); 1.1 root 402: 403: if (m == 0) 404: return; 405: 406: /* 407: * Copy the mbuf chain into the transmit buffer 408: */ 409: 1.1.1.3 ! root 410: buffer = is->tbuf+(BUFSIZE*is->last_td); 1.1 root 411: len=0; 412: for (m0=m; m != 0; m=m->m_next) { 413: bcopy(mtod(m,caddr_t),buffer,m->m_len); 414: buffer += m->m_len; 415: len += m->m_len; 416: } 1.1.1.3 ! root 417: #if NBPFILTER > 0 ! 418: if (is->bpf) { ! 419: u_short etype; ! 420: int off, datasize, resid; ! 421: struct ether_header *eh; ! 422: struct trailer_header { ! 423: u_short ether_type; ! 424: u_short ether_residual; ! 425: } trailer_header; ! 426: char ether_packet[ETHER_MAX_LEN]; ! 427: char *ep; ! 428: ! 429: ep = ether_packet; ! 430: ! 431: /* ! 432: * We handle trailers below: ! 433: * Copy ether header first, then residual data, ! 434: * then data. Put all this in a temporary buffer ! 435: * 'ether_packet' and send off to bpf. Since the ! 436: * system has generated this packet, we assume ! 437: * that all of the offsets in the packet are ! 438: * correct; if they're not, the system will almost ! 439: * certainly crash in m_copydata. ! 440: * We make no assumptions about how the data is ! 441: * arranged in the mbuf chain (i.e. how much ! 442: * data is in each mbuf, if mbuf clusters are ! 443: * used, etc.), which is why we use m_copydata ! 444: * to get the ether header rather than assume ! 445: * that this is located in the first mbuf. ! 446: */ ! 447: /* copy ether header */ ! 448: m_copydata(m0, 0, sizeof(struct ether_header), ep); ! 449: eh = (struct ether_header *) ep; ! 450: ep += sizeof(struct ether_header); ! 451: etype = ntohs(eh->ether_type); ! 452: if (etype >= ETHERTYPE_TRAIL && ! 453: etype < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { ! 454: datasize = ((etype - ETHERTYPE_TRAIL) << 9); ! 455: off = datasize + sizeof(struct ether_header); ! 456: ! 457: /* copy trailer_header into a data structure */ ! 458: m_copydata(m0, off, sizeof(struct trailer_header), ! 459: &trailer_header.ether_type); ! 460: ! 461: /* copy residual data */ ! 462: resid = trailer_header.ether_residual - ! 463: sizeof(struct trailer_header); ! 464: resid = ntohs(resid); ! 465: m_copydata(m0, off+sizeof(struct trailer_header), ! 466: resid, ep); ! 467: ep += resid; ! 468: ! 469: /* copy data */ ! 470: m_copydata(m0, sizeof(struct ether_header), ! 471: datasize, ep); ! 472: ep += datasize; ! 473: ! 474: /* restore original ether packet type */ ! 475: eh->ether_type = trailer_header.ether_type; ! 476: ! 477: bpf_tap(is->bpf, ether_packet, ep - ether_packet); ! 478: } else ! 479: bpf_mtap(is->bpf, m0); ! 480: } ! 481: #endif ! 482: 1.1 root 483: 484: m_freem(m0); 485: len = MAX(len,ETHER_MIN_LEN); 486: 487: /* 488: * Init transmit registers, and set transmit start flag. 489: */ 490: 491: cdm->flags |= (OWN|STP|ENP); 492: cdm->bcnt = -len; 493: cdm->mcnt = 0; 1.1.1.3 ! root 494: #if ISDEBUG > 3 ! 495: xmit_print(unit,is->last_td); 1.1 root 496: #endif 497: 1.1.1.3 ! root 498: iswrcsr(unit,0,TDMD|INEA); ! 499: if (++is->last_td >= NTBUF) ! 500: is->last_td=0; ! 501: }while(++is->no_td < NTBUF); ! 502: is->no_td = NTBUF; ! 503: is->arpcom.ac_if.if_flags |= IFF_OACTIVE; ! 504: #if ISDEBUG >4 ! 505: printf("no_td = %x, last_td = %x\n",is->no_td, is->last_td); 1.1 root 506: #endif 507: return(0); 508: } 509: 510: 511: /* 512: * Controller interrupt. 513: */ 514: isintr(unit) 515: { 1.1.1.3 ! root 516: register struct is_softc *is = &is_softc[unit]; 1.1 root 517: u_short isr; 518: 1.1.1.3 ! root 519: while((isr=isrdcsr(unit,0))&INTR) { 1.1 root 520: if (isr&ERR) { 1.1.1.3 ! root 521: if (isr&BABL){ ! 522: printf("is%d: BABL\n",unit); ! 523: is->arpcom.ac_if.if_oerrors++; ! 524: } ! 525: if (isr&CERR) { ! 526: printf("is%d: CERR\n",unit); ! 527: is->arpcom.ac_if.if_collisions++; ! 528: } ! 529: if (isr&MISS) { ! 530: printf("is%d: MISS\n",unit); ! 531: is->arpcom.ac_if.if_ierrors++; ! 532: } 1.1 root 533: if (isr&MERR) 1.1.1.3 ! root 534: printf("is%d: MERR\n",unit); ! 535: iswrcsr(unit,0,BABL|CERR|MISS|MERR|INEA); 1.1 root 536: } 1.1.1.3 ! root 537: if (!(isr&RXON)) { ! 538: printf("is%d: !(isr&RXON)\n", unit); ! 539: is->arpcom.ac_if.if_ierrors++; ! 540: is_reset(unit); 1.1 root 541: return(1); 542: } 1.1.1.3 ! root 543: if (!(isr&TXON)) { ! 544: printf("is%d: !(isr&TXON)\n", unit); ! 545: is->arpcom.ac_if.if_oerrors++; ! 546: is_reset(unit); 1.1 root 547: return(1); 548: } 1.1.1.3 ! root 549: 1.1 root 550: if (isr&RINT) { 1.1.1.3 ! root 551: /* reset watchdog timer */ ! 552: is->arpcom.ac_if.if_timer = 0; ! 553: is_rint(unit); 1.1 root 554: } 555: if (isr&TINT) { 1.1.1.3 ! root 556: /* reset watchdog timer */ ! 557: is->arpcom.ac_if.if_timer = 0; ! 558: iswrcsr(unit,0,TINT|INEA); 1.1 root 559: istint(unit); 560: } 561: } 562: } 563: 564: istint(unit) 565: int unit; 566: { 567: struct is_softc *is = &is_softc[unit]; 1.1.1.3 ! root 568: register struct ifnet *ifp = &is->arpcom.ac_if; 1.1 root 569: int i,loopcount=0; 570: struct mds *cdm; 571: 1.1.1.3 ! root 572: is->arpcom.ac_if.if_opackets++; 1.1 root 573: do { 574: if ((i=is->last_td - is->no_td) < 0) 575: i+=NTBUF; 1.1.1.3 ! root 576: cdm = (is->td+i); ! 577: #if ISDEBUG >4 1.1 root 578: printf("Trans cdm = %x\n",cdm); 579: #endif 580: if (cdm->flags&OWN) { 581: if (loopcount) 582: break; 583: return; 584: } 585: loopcount++; 1.1.1.3 ! root 586: is->arpcom.ac_if.if_flags &= ~IFF_OACTIVE; 1.1 root 587: }while(--is->no_td > 0); 1.1.1.3 ! root 588: is_start(ifp); 1.1 root 589: 590: } 591: 592: #define NEXTRDS \ 1.1.1.3 ! root 593: if (++rmd == NRBUF) rmd=0, cdm=is->rd; else ++cdm 1.1 root 594: 1.1.1.3 ! root 595: /* only called from one place, so may as well integrate */ ! 596: static inline void is_rint(int unit) 1.1 root 597: { 598: register struct is_softc *is=&is_softc[unit]; 599: register int rmd = is->last_rd; 1.1.1.3 ! root 600: struct mds *cdm = (is->rd + rmd); 1.1 root 601: 602: /* Out of sync with hardware, should never happen */ 603: 604: if (cdm->flags & OWN) { 1.1.1.3 ! root 605: printf("is%d: error: out of sync\n",unit); ! 606: iswrcsr(unit,0,RINT|INEA); 1.1 root 607: return; 608: } 609: 610: /* Process all buffers with valid data */ 611: while (!(cdm->flags&OWN)) { 612: /* Clear interrupt to avoid race condition */ 1.1.1.3 ! root 613: iswrcsr(unit,0,RINT|INEA); 1.1 root 614: if (cdm->flags&ERR) { 615: if (cdm->flags&FRAM) 1.1.1.3 ! root 616: printf("is%d: FRAM\n",unit); 1.1 root 617: if (cdm->flags&OFLO) 1.1.1.3 ! root 618: printf("is%d: OFLO\n",unit); 1.1 root 619: if (cdm->flags&CRC) 1.1.1.3 ! root 620: printf("is%d: CRC\n",unit); 1.1 root 621: if (cdm->flags&RBUFF) 1.1.1.3 ! root 622: printf("is%d: RBUFF\n",unit); 1.1 root 623: }else 624: if (cdm->flags&(STP|ENP) != (STP|ENP)) { 625: do { 1.1.1.3 ! root 626: iswrcsr(unit,0,RINT|INEA); 1.1 root 627: cdm->mcnt = 0; 628: cdm->flags |= OWN; 629: NEXTRDS; 630: }while (!(cdm->flags&(OWN|ERR|STP|ENP))); 631: is->last_rd = rmd; 1.1.1.3 ! root 632: printf("is%d: Chained buffer\n",unit); 1.1 root 633: if ((cdm->flags & (OWN|ERR|STP|ENP)) != ENP) { 1.1.1.3 ! root 634: is_reset(unit); 1.1 root 635: return; 636: } 637: }else 638: { 1.1.1.3 ! root 639: #if ISDEBUG >2 ! 640: recv_print(unit,is->last_rd); 1.1 root 641: #endif 1.1.1.3 ! root 642: isread(is,is->rbuf+(BUFSIZE*rmd),(int)cdm->mcnt); ! 643: is->arpcom.ac_if.if_ipackets++; 1.1 root 644: } 645: 646: cdm->flags |= OWN; 647: cdm->mcnt = 0; 648: NEXTRDS; 1.1.1.3 ! root 649: #if ISDEBUG >4 1.1 root 650: printf("is->last_rd = %x, cdm = %x\n",is->last_rd,cdm); 651: #endif 652: } /* while */ 653: is->last_rd = rmd; 1.1.1.3 ! root 654: } /* is_rint */ ! 655: 1.1 root 656: 657: /* 658: * Pass a packet to the higher levels. 659: * We deal with the trailer protocol here. 660: */ 1.1.1.3 ! root 661: static inline void ! 662: isread(struct is_softc *is, unsigned char *buf, int len) ! 663: { ! 664: register struct ether_header *eh; ! 665: struct mbuf *m; ! 666: int off, resid; ! 667: register struct ifqueue *inq; ! 668: ! 669: /* ! 670: * Deal with trailer protocol: if type is trailer type ! 671: * get true type from first 16-bit word past data. ! 672: * Remember that type was trailer by setting off. ! 673: */ ! 674: eh = (struct ether_header *)buf; ! 675: eh->ether_type = ntohs((u_short)eh->ether_type); ! 676: len = len - sizeof(struct ether_header) - 4; ! 677: #define nedataaddr(eh, off, type) ((type)(((caddr_t)((eh)+1)+(off)))) ! 678: if (eh->ether_type >= ETHERTYPE_TRAIL && ! 679: eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { ! 680: off = (eh->ether_type - ETHERTYPE_TRAIL) * 512; ! 681: if (off >= ETHERMTU) return; /* sanity */ ! 682: eh->ether_type = ntohs(*nedataaddr(eh, off, u_short *)); ! 683: resid = ntohs(*(nedataaddr(eh, off+2, u_short *))); ! 684: if (off + resid > len) return; /* sanity */ ! 685: len = off + resid; ! 686: } else off = 0; ! 687: ! 688: if (len == 0) return; ! 689: ! 690: /* ! 691: * Pull packet off interface. Off is nonzero if packet ! 692: * has trailing header; neget will then force this header ! 693: * information to be at the front, but we still have to drop ! 694: * the type and length which are at the front of any trailer data. ! 695: */ ! 696: is->arpcom.ac_if.if_ipackets++; ! 697: m = isget(buf, len, off, &is->arpcom.ac_if); ! 698: if (m == 0) return; ! 699: #if NBPFILTER > 0 ! 700: /* ! 701: * Check if there's a BPF listener on this interface. ! 702: * If so, hand off the raw packet to bpf. ! 703: */ ! 704: if (is->bpf) { ! 705: bpf_mtap(is->bpf, m); ! 706: ! 707: /* ! 708: * Note that the interface cannot be in promiscuous mode if ! 709: * there are no BPF listeners. And if we are in promiscuous ! 710: * mode, we have to check if this packet is really ours. ! 711: * ! 712: * XXX This test does not support multicasts. ! 713: */ ! 714: if ((is->arpcom.ac_if.if_flags & IFF_PROMISC) && ! 715: bcmp(eh->ether_dhost, is->arpcom.ac_enaddr, ! 716: sizeof(eh->ether_dhost)) != 0 && ! 717: bcmp(eh->ether_dhost, etherbroadcastaddr, ! 718: sizeof(eh->ether_dhost)) != 0) { ! 719: ! 720: m_freem(m); ! 721: return; ! 722: } ! 723: } ! 724: #endif 1.1 root 725: 1.1.1.3 ! root 726: ! 727: ether_input(&is->arpcom.ac_if, eh, m); 1.1 root 728: } 729: 730: /* 731: * Supporting routines 732: */ 733: 734: /* 735: * Pull read data off a interface. 736: * Len is length of data, with local net header stripped. 737: * Off is non-zero if a trailer protocol was used, and 738: * gives the offset of the trailer information. 739: * We copy the trailer information and then all the normal 740: * data into mbufs. When full cluster sized units are present 741: * we copy into clusters. 742: */ 743: struct mbuf * 744: isget(buf, totlen, off0, ifp) 1.1.1.3 ! root 745: caddr_t buf; ! 746: int totlen, off0; ! 747: struct ifnet *ifp; ! 748: { ! 749: struct mbuf *top, **mp, *m, *p; ! 750: int off = off0, len; ! 751: register caddr_t cp = buf; ! 752: char *epkt; ! 753: ! 754: buf += sizeof(struct ether_header); ! 755: cp = buf; ! 756: epkt = cp + totlen; ! 757: ! 758: ! 759: if (off) { ! 760: cp += off + 2 * sizeof(u_short); ! 761: totlen -= 2 * sizeof(u_short); ! 762: } ! 763: ! 764: MGETHDR(m, M_DONTWAIT, MT_DATA); ! 765: if (m == 0) ! 766: return (0); ! 767: m->m_pkthdr.rcvif = ifp; ! 768: m->m_pkthdr.len = totlen; ! 769: m->m_len = MHLEN; ! 770: top = 0; ! 771: mp = ⊤ ! 772: while (totlen > 0) { ! 773: if (top) { ! 774: MGET(m, M_DONTWAIT, MT_DATA); ! 775: if (m == 0) { ! 776: m_freem(top); ! 777: return (0); ! 778: } ! 779: m->m_len = MLEN; ! 780: } ! 781: len = min(totlen, epkt - cp); ! 782: if (len >= MINCLSIZE) { ! 783: MCLGET(m, M_DONTWAIT); ! 784: if (m->m_flags & M_EXT) ! 785: m->m_len = len = min(len, MCLBYTES); ! 786: else ! 787: len = m->m_len; ! 788: } else { ! 789: /* ! 790: * Place initial small packet/header at end of mbuf. ! 791: */ ! 792: if (len < m->m_len) { ! 793: if (top == 0 && len + max_linkhdr <= m->m_len) ! 794: m->m_data += max_linkhdr; ! 795: m->m_len = len; ! 796: } else ! 797: len = m->m_len; ! 798: } ! 799: bcopy(cp, mtod(m, caddr_t), (unsigned)len); ! 800: cp += len; ! 801: *mp = m; ! 802: mp = &m->m_next; ! 803: totlen -= len; ! 804: if (cp == epkt) ! 805: cp = buf; ! 806: } ! 807: return (top); 1.1 root 808: } 809: 1.1.1.3 ! root 810: 1.1 root 811: /* 812: * Process an ioctl request. 813: */ 1.1.1.3 ! root 814: is_ioctl(ifp, cmd, data) 1.1 root 815: register struct ifnet *ifp; 816: int cmd; 817: caddr_t data; 818: { 819: register struct ifaddr *ifa = (struct ifaddr *)data; 1.1.1.3 ! root 820: int unit = ifp->if_unit; ! 821: struct is_softc *is = &is_softc[unit]; 1.1 root 822: struct ifreq *ifr = (struct ifreq *)data; 1.1.1.3 ! root 823: int s, error = 0; 1.1 root 824: 1.1.1.3 ! root 825: s = splnet(); 1.1 root 826: 827: switch (cmd) { 828: 829: case SIOCSIFADDR: 830: ifp->if_flags |= IFF_UP; 831: 832: switch (ifa->ifa_addr->sa_family) { 833: #ifdef INET 834: case AF_INET: 1.1.1.3 ! root 835: is_init(ifp->if_unit); /* before arpwhohas */ ! 836: /* ! 837: * See if another station has *our* IP address. ! 838: * i.e.: There is an address conflict! If a ! 839: * conflict exists, a message is sent to the ! 840: * console. ! 841: */ 1.1 root 842: ((struct arpcom *)ifp)->ac_ipaddr = 843: IA_SIN(ifa)->sin_addr; 844: arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); 845: break; 846: #endif 847: #ifdef NS 1.1.1.3 ! root 848: /* ! 849: * XXX - This code is probably wrong ! 850: */ 1.1 root 851: case AF_NS: 852: { 1.1.1.3 ! root 853: register struct arpcom.ac_enaddr *ina = &(IA_SNS(ifa)->sns_addr); 1.1 root 854: 855: if (ns_nullhost(*ina)) 1.1.1.3 ! root 856: ina->x_host = *(union ns_host *)(is->arpcom.ac_enaddr); 1.1 root 857: else { 858: /* 859: */ 860: bcopy((caddr_t)ina->x_host.c_host, 1.1.1.3 ! root 861: (caddr_t)is->arpcom.ac_enaddr, sizeof(is->arpcom.ac_enaddr)); 1.1 root 862: } 1.1.1.3 ! root 863: /* ! 864: * Set new address ! 865: */ ! 866: is_init(ifp->if_unit); 1.1 root 867: break; 868: } 869: #endif 870: default: 1.1.1.3 ! root 871: is_init(ifp->if_unit); 1.1 root 872: break; 873: } 874: break; 875: 876: case SIOCSIFFLAGS: 1.1.1.3 ! root 877: /* ! 878: * If interface is marked down and it is running, then stop it ! 879: */ 1.1 root 880: if ((ifp->if_flags & IFF_UP) == 0 && 881: ifp->if_flags & IFF_RUNNING) { 1.1.1.3 ! root 882: iswrcsr(unit,0,STOP); 1.1 root 883: ifp->if_flags &= ~IFF_RUNNING; 1.1.1.3 ! root 884: } else { ! 885: /* ! 886: * If interface is marked up and it is stopped, then start it ! 887: */ ! 888: if ((ifp->if_flags & IFF_UP) && ! 889: (ifp->if_flags & IFF_RUNNING) == 0) ! 890: is_init(ifp->if_unit); ! 891: } ! 892: #if NBPFILTER > 0 ! 893: if (ifp->if_flags & IFF_PROMISC) { ! 894: /* ! 895: * Set promiscuous mode on interface. ! 896: * XXX - for multicasts to work, we would need to ! 897: * write 1's in all bits of multicast ! 898: * hashing array. For now we assume that ! 899: * this was done in is_init(). ! 900: */ ! 901: init_block[unit].mode = PROM; ! 902: } else ! 903: /* ! 904: * XXX - for multicasts to work, we would need to ! 905: * rewrite the multicast hashing array with the ! 906: * proper hash (would have been destroyed above). ! 907: */ ! 908: { /* Don't know about this */}; ! 909: #endif 1.1 root 910: break; 911: 912: #ifdef notdef 913: case SIOCGHWADDR: 1.1.1.3 ! root 914: bcopy((caddr_t)is->arpcom.ac_enaddr, (caddr_t) &ifr->ifr_data, ! 915: sizeof(is->arpcom.ac_enaddr)); 1.1 root 916: break; 917: #endif 918: 919: default: 920: error = EINVAL; 921: } 1.1.1.3 ! root 922: (void) splx(s); 1.1 root 923: return (error); 924: } 925: 1.1.1.3 ! root 926: recv_print(unit,no) ! 927: int unit,no; 1.1 root 928: { 1.1.1.3 ! root 929: register struct is_softc *is=&is_softc[unit]; 1.1 root 930: struct mds *rmd; 1.1.1.3 ! root 931: int len,i,printed=0; 1.1 root 932: 1.1.1.3 ! root 933: rmd = (is->rd+no); 1.1 root 934: len = rmd->mcnt; 1.1.1.3 ! root 935: printf("is%d: Receive buffer %d, len = %d\n",unit,no,len); ! 936: printf("is%d: Status %x\n",unit,isrdcsr(unit,0)); ! 937: for (i=0; i<len; i++) { ! 938: if (!printed) { ! 939: printed=1; ! 940: printf("is%d: data: ", unit); ! 941: } ! 942: printf("%x ",*(is->rbuf+(BUFSIZE*no)+i)); ! 943: } ! 944: if (printed) ! 945: printf("\n"); 1.1 root 946: } 947: 1.1.1.3 ! root 948: xmit_print(unit,no) ! 949: int unit,no; 1.1 root 950: { 1.1.1.3 ! root 951: register struct is_softc *is=&is_softc[unit]; 1.1 root 952: struct mds *rmd; 1.1.1.3 ! root 953: int i, printed=0; 1.1 root 954: u_short len; 955: 1.1.1.3 ! root 956: rmd = (is->td+no); 1.1 root 957: len = -(rmd->bcnt); 1.1.1.3 ! root 958: printf("is%d: Transmit buffer %d, len = %d\n",unit,no,len); ! 959: printf("is%d: Status %x\n",unit,isrdcsr(unit,0)); ! 960: printf("is%d: addr %x, flags %x, bcnt %x, mcnt %x\n", ! 961: unit,rmd->addr,rmd->flags,rmd->bcnt,rmd->mcnt); ! 962: for (i=0; i<len; i++) { ! 963: if (!printed) { ! 964: printed = 1; ! 965: printf("is%d: data: ", unit); ! 966: } ! 967: printf("%x ",*(is->tbuf+(BUFSIZE*no)+i)); ! 968: } ! 969: if (printed) ! 970: printf("\n"); 1.1 root 971: } 972: 973: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.