|
|
1.1 ! root 1: #define DEBUG 1 ! 2: /* ! 3: * Mach Operating System ! 4: * Copyright (c) 1994,1993,1992 Carnegie Mellon University ! 5: * All Rights Reserved. ! 6: * ! 7: * Permission to use, copy, modify and distribute this software and its ! 8: * documentation is hereby granted, provided that both the copyright ! 9: * notice and this permission notice appear in all copies of the ! 10: * software, derivative works or modified versions, and any portions ! 11: * thereof, and that both notices appear in supporting documentation. ! 12: * ! 13: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 14: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 15: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 16: * ! 17: * Carnegie Mellon requests users of this software to return to ! 18: * ! 19: * Software Distribution Coordinator or [email protected] ! 20: * School of Computer Science ! 21: * Carnegie Mellon University ! 22: * Pittsburgh PA 15213-3890 ! 23: * ! 24: * any improvements or extensions that they make and grant Carnegie Mellon ! 25: * the rights to redistribute these changes. ! 26: */ ! 27: ! 28: /* ! 29: * HISTORY ! 30: * 17-Feb-94 David Golub (dbg) at Carnegie-Mellon University ! 31: * Fix from Bob Baron to fix transmitter problems. ! 32: * ! 33: * $Log: if_de6c.c,v $ ! 34: * Revision 1.1.1.1 1997/02/25 21:27:16 thomas ! 35: * Initial source ! 36: * ! 37: * Revision 1.1.1.1 1996/10/30 01:39:26 thomas ! 38: * Imported from UK22 ! 39: * ! 40: * Revision 1.1 1994/11/08 20:47:24 baford ! 41: * merged in CMU's MK83-MK83a diffs ! 42: * ! 43: * Revision 2.2 93/11/17 18:29:25 dbg ! 44: * Moved source into kernel/i386at/DLINK/if_de6c.c, since we ! 45: * can't release it but don't want to lose it. ! 46: * [93/11/17 dbg] ! 47: * ! 48: * Removed u_long. ! 49: * [93/03/25 dbg] ! 50: * ! 51: * Created. ! 52: * I have used if_3c501.c as a typical driver template and ! 53: * spliced in the appropriate particulars for the ! 54: * d-link 600. ! 55: * [92/08/13 rvb] ! 56: * ! 57: * ! 58: * File: if_de6c.c ! 59: * Author: Robert V. Baron ! 60: */ ! 61: ! 62: /* ! 63: * File: if_3c501.c ! 64: * Author: Philippe Bernadat ! 65: * Date: 1989 ! 66: * Copyright (c) 1989 OSF Research Institute ! 67: * ! 68: * 3COM Etherlink d-link "600" Mach Ethernet drvier ! 69: */ ! 70: /* ! 71: Copyright 1990 by Open Software Foundation, ! 72: Cambridge, MA. ! 73: ! 74: All Rights Reserved ! 75: ! 76: Permission to use, copy, modify, and distribute this software and ! 77: its documentation for any purpose and without fee is hereby granted, ! 78: provided that the above copyright notice appears in all copies and ! 79: that both the copyright notice and this permission notice appear in ! 80: supporting documentation, and that the name of OSF or Open Software ! 81: Foundation not be used in advertising or publicity pertaining to ! 82: distribution of the software without specific, written prior ! 83: permission. ! 84: ! 85: OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE ! 86: INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, ! 87: IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR ! 88: CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM ! 89: LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, ! 90: NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION ! 91: WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ! 92: */ ! 93: ! 94: /* ! 95: * I have tried to make it clear what is device specific code ! 96: * and what code supports the general BSD ethernet interface. d-link ! 97: * specific code is preceded by a line or two of ! 98: * "d-link 600 ON; d-link 600 ON; d-link 600 ON; d-link 600 ON" ! 99: * and followed by a line or two of ! 100: * "d-link 600 OFF; d-link 600 OFF; d-link 600 OFF; d-link 600 OFF" ! 101: * ! 102: * The main routines that do device specific processing are: ! 103: * de6cintr - interrupt dispatcher ! 104: * de6crcv - rcv packets and switch to new buffers ! 105: * de6cxmt - xmt packet and wait for xmtbusy to clear ! 106: * de6calive - probe for device ! 107: * de6cinit - device initialization ! 108: * de6cintoff - turn it off. ! 109: * There are a couple of interesting macros at the head of this ! 110: * file and some support subroutines at the end. ! 111: * ! 112: * Lastly, to get decent performance on i386SX class machines, it ! 113: * was necessary to recode the read and write d-link memory routines in ! 114: * assembler. The deread and dewrite routines that are used are in ! 115: * if_de6s.s ! 116: * ! 117: */ ! 118: ! 119: /* Questions: ! 120: ! 121: Make sure that iopl maps 378, 278 and 3bc. ! 122: ! 123: If you set command w/o MODE and page bit, what happens? ! 124: ! 125: Could I get xmt interrupts; currently I spin - this is not an issue? ! 126: ! 127: enable promiscuous? ! 128: ! 129: Can you assert TXEN and RXen simulatneously? ! 130: */ ! 131: ! 132: #include <de6c.h> ! 133: #include <par.h> ! 134: ! 135: #ifdef MACH_KERNEL ! 136: #include <kern/time_out.h> ! 137: #include <device/device_types.h> ! 138: #include <device/errno.h> ! 139: #include <device/io_req.h> ! 140: #include <device/if_hdr.h> ! 141: #include <device/if_ether.h> ! 142: #include <device/net_status.h> ! 143: #include <device/net_io.h> ! 144: #include <chips/busses.h> ! 145: #else MACH_KERNEL ! 146: #include <sys/param.h> ! 147: #include <mach/machine/vm_param.h> ! 148: #include <sys/systm.h> ! 149: #include <sys/mbuf.h> ! 150: #include <sys/buf.h> ! 151: #include <sys/protosw.h> ! 152: #include <sys/socket.h> ! 153: #include <sys/vmmac.h> ! 154: #include <sys/ioctl.h> ! 155: #include <sys/errno.h> ! 156: #include <sys/syslog.h> ! 157: ! 158: #include <net/if.h> ! 159: #include <net/netisr.h> ! 160: #include <net/route.h> ! 161: #include <i386at/atbus.h> ! 162: ! 163: #ifdef INET ! 164: #include <netinet/in.h> ! 165: #include <netinet/in_systm.h> ! 166: #include <netinet/in_var.h> ! 167: #include <netinet/ip.h> ! 168: #include <netinet/if_ether.h> ! 169: #endif ! 170: ! 171: #ifdef NS ! 172: #include <netns/ns.h> ! 173: #include <netns/ns_if.h> ! 174: #endif ! 175: #endif MACH_KERNEL ! 176: ! 177: #include <vm/vm_kern.h> ! 178: #include <i386/ipl.h> ! 179: #include <i386/pio.h> ! 180: #include <i386at/if_de6c.h> ! 181: ! 182: #define SPLNET spl6 ! 183: ! 184: /* d-link 600 ON; d-link 600 ON; d-link 600 ON; d-link 600 ON */ ! 185: /* d-link 600 ON; d-link 600 ON; d-link 600 ON; d-link 600 ON */ ! 186: #define de6cwrite(sp, addr, buf, len) \ ! 187: de6cwriteasm(addr, buf, len, DATA(sp->port), sp->latency) ! 188: ! 189: #define de6cread(sp, addr, buf, len) \ ! 190: de6creadasm(addr, buf, len, DATA(sp->port), sp->latency) ! 191: ! 192: #define DATA_OUT(sp, p, f, z) \ ! 193: de6coutb(sp, DATA(p), ((z)<<4) | f);\ ! 194: de6coutb(sp, DATA(p), ((z)&0xf0)| f | STROBE) ! 195: ! 196: #define STAT_IN(sp, p, in) \ ! 197: de6coutb(sp, DATA(p), STATUS); \ ! 198: in = inb(STAT(port)); \ ! 199: de6coutb(sp, DATA(p), NUL_CMD | STROBE) ! 200: ! 201: #define XMTidx 3 ! 202: #define XMT_BSY_WAIT 10000 ! 203: /* d-link 600 OFF; d-link 600 OFF; d-link 600 OFF; d-link 600 OFF */ ! 204: /* d-link 600 OFF; d-link 600 OFF; d-link 600 OFF; d-link 600 OFF */ ! 205: ! 206: int de6cprobe(); ! 207: void de6cattach(); ! 208: int de6cintr(); ! 209: int de6cinit(); ! 210: int de6coutput(); ! 211: int de6cioctl(); ! 212: int de6creset(); ! 213: void de6cwatch(); ! 214: ! 215: static vm_offset_t de6c_std[NDE6C] = { 0 }; ! 216: static struct bus_device *de6c_info[NDE6C]; ! 217: ! 218: #ifdef MACH_KERNEL ! 219: struct bus_driver de6cdriver = ! 220: {de6cprobe, 0, de6cattach, 0, de6c_std, "de", de6c_info, }; ! 221: extern struct bus_device *lprinfo[]; ! 222: ! 223: #define MM io_req_t ! 224: #define PIC sysdep1 ! 225: #define DEV bus_device ! 226: #else MACH_KERNEL ! 227: int (*de6cintrs[])() = { de6cintr, 0}; ! 228: struct isa_driver de6cdriver = ! 229: {de6cprobe, 0, de6cattach, "de", 0, 0, 0}; ! 230: extern struct isa_dev *lprinfo[]; ! 231: ! 232: #define MM struct mbuf * ! 233: #define PIC dev_pic ! 234: #define DEV isa_dev ! 235: #endif MACH_KERNEL ! 236: ! 237: int watchdog_id; ! 238: ! 239: typedef struct { ! 240: #ifdef MACH_KERNEL ! 241: struct ifnet ds_if; /* generic interface header */ ! 242: u_char ds_addr[6]; /* Ethernet hardware address */ ! 243: #else MACH_KERNEL ! 244: struct arpcom de6c_ac; ! 245: #define ds_if de6c_ac.ac_if ! 246: #define ds_addr de6c_ac.ac_enaddr ! 247: #endif MACH_KERNEL ! 248: int flags; ! 249: int timer; ! 250: u_char address[6]; ! 251: short mode; ! 252: int port; ! 253: int latency; ! 254: int xmt; ! 255: int rcv; ! 256: int rcvoff; ! 257: int rcvspin; ! 258: /* d-link 600 ON; d-link 600 ON; d-link 600 ON; d-link 600 ON */ ! 259: /* d-link 600 ON; d-link 600 ON; d-link 600 ON; d-link 600 ON */ ! 260: int produce; ! 261: int consume; ! 262: int rcvlen[XMTidx]; ! 263: int alive; ! 264: /* d-link 600 OFF; d-link 600 OFF; d-link 600 OFF; d-link 600 OFF */ ! 265: /* d-link 600 OFF; d-link 600 OFF; d-link 600 OFF; d-link 600 OFF */ ! 266: int (*oldvect)(); ! 267: int oldunit; ! 268: } de6c_softc_t; ! 269: ! 270: de6c_softc_t de6c_softc[NDE6C]; ! 271: ! 272: int de6cactive[NDE6C]; ! 273: ! 274: /* ! 275: * Patch to change latency value ! 276: */ ! 277: int de6c_latency = 30; /* works on NEC Versa (pottsylvania.mach) */ ! 278: ! 279: #ifdef DEBUG ! 280: int de6crcv0, de6crcv1, de6crcv2, de6crcv3; ! 281: int de6cdo_rcvintr = 0, de6cdo_watch = 0; ! 282: int de6cdo_xmt = 0; ! 283: #define D(X) X ! 284: #else /* DEBUG */ ! 285: #define D(X) ! 286: #endif /* DEBUG */ ! 287: ! 288: /* ! 289: * de6cprobe: ! 290: * We are not directly probed. The lprattach will call de6cattach. ! 291: * But what we have is plausible for a probe. ! 292: */ ! 293: de6cprobe(port, dev) ! 294: struct DEV *dev; ! 295: { ! 296: #ifdef MACH_KERNEL ! 297: int unit = dev->unit; ! 298: #else MACH_KERNEL ! 299: int unit = dev->dev_unit; ! 300: #endif MACH_KERNEL ! 301: ! 302: if ((unit < 0) || (unit >= NDE6C)) { ! 303: return(0); ! 304: } ! 305: return(1); ! 306: } ! 307: ! 308: /* ! 309: * de6cattach: ! 310: * ! 311: * Called from lprattach ! 312: * ! 313: */ ! 314: void de6cattach(dev) ! 315: #ifdef MACH_KERNEL ! 316: struct bus_device *dev; ! 317: #else MACH_KERNEL ! 318: struct isa_dev *dev; ! 319: #endif MACH_KERNEL ! 320: { ! 321: de6c_softc_t *sp; ! 322: struct ifnet *ifp; ! 323: #ifdef MACH_KERNEL ! 324: int unit = dev->unit; ! 325: int port = (int)dev->address; ! 326: #else MACH_KERNEL ! 327: int unit = dev->dev_unit; ! 328: int port = (int)dev->dev_addr; ! 329: #endif MACH_KERNEL ! 330: ! 331: sp = &de6c_softc[unit]; ! 332: sp->port = port; ! 333: sp->timer = -1; ! 334: sp->flags = 0; ! 335: sp->mode = 0; ! 336: ! 337: ifp = &(sp->ds_if); ! 338: ifp->if_unit = unit; ! 339: ifp->if_mtu = ETHERMTU; ! 340: ifp->if_flags = IFF_BROADCAST; ! 341: ! 342: #ifdef MACH_KERNEL ! 343: ifp->if_header_size = sizeof(struct ether_header); ! 344: ifp->if_header_format = HDR_ETHERNET; ! 345: ifp->if_address_size = 6; ! 346: ifp->if_address = (char *)&sp->address[0]; ! 347: if_init_queues(ifp); ! 348: #else MACH_KERNEL ! 349: ifp->if_name = "de"; ! 350: ifp->if_init = de6cinit; ! 351: ifp->if_output = de6coutput; ! 352: ifp->if_ioctl = de6cioctl; ! 353: ifp->if_reset = de6creset; ! 354: ifp->if_next = NULL; ! 355: if_attach(ifp); ! 356: #endif MACH_KERNEL ! 357: ! 358: sp->alive = de6calive(sp); ! 359: } ! 360: ! 361: de6calive(sp) ! 362: de6c_softc_t *sp; ! 363: { ! 364: int port = sp->port; ! 365: int unit = sp->ds_if.if_unit; ! 366: struct DEV *dev = lprinfo[unit]; ! 367: int i; ! 368: ! 369: #ifdef MACH_KERNEL ! 370: #else /* MACH_KERNEL */ ! 371: extern int tcp_recvspace; /* empircal messure */ ! 372: #endif /* MACH_KERNEL */ ! 373: ! 374: /* d-link 600 ON; d-link 600 ON; d-link 600 ON; d-link 600 ON */ ! 375: /* d-link 600 ON; d-link 600 ON; d-link 600 ON; d-link 600 ON */ ! 376: de6coutb(sp, CMD(port), SLT_NIC); ! 377: DATA_OUT(sp, port, COMMAND, RESET); ! 378: DATA_OUT(sp, port, COMMAND, STOP_RESET); ! 379: sp->latency = 101; ! 380: if (!de6cgetid(sp, sp->ds_addr)) { ! 381: de6coutb(sp, CMD(port), SLT_PRN); ! 382: return 0; ! 383: } ! 384: ! 385: #ifdef MACH_KERNEL ! 386: #else /* MACH_KERNEL */ ! 387: tcp_recvspace = 0x300; /* empircal messure */ ! 388: #endif /* MACH_KERNEL */ ! 389: ! 390: #ifdef de6cwrite ! 391: sp->latency = de6c_latency; ! 392: #else /* de6cwrite */ ! 393: sp->latency = 0; ! 394: #endif /* de6cwrite */ ! 395: ! 396: for (i = 0; i++ < 10;) { ! 397: if (de6cmemcheck(sp)) ! 398: break; ! 399: sp->latency += 10; ! 400: } ! 401: ! 402: de6cgetid(sp, sp->ds_addr); ! 403: de6cgetid(sp, sp->address); ! 404: de6csetid(sp, sp->address); ! 405: de6coutb(sp, CMD(port), SLT_PRN); ! 406: /* d-link 600 OFF; d-link 600 OFF; d-link 600 OFF; d-link 600 OFF */ ! 407: /* d-link 600 OFF; d-link 600 OFF; d-link 600 OFF; d-link 600 OFF */ ! 408: ! 409: #ifdef MACH_KERNEL ! 410: #if NPAR > 0 ! 411: printf("\n"); ! 412: #endif /* NPAR > 0 */ ! 413: printf(" de%d: at lpr%d, port = %x, spl = %d, pic = %d. ", ! 414: unit, unit, dev->address, dev->sysdep, dev->sysdep1); ! 415: ! 416: printf("ethernet id [%x:%x:%x:%x:%x:%x]", ! 417: sp->address[0],sp->address[1],sp->address[2], ! 418: sp->address[3],sp->address[4],sp->address[5]); ! 419: ! 420: if (sp->latency > 1) { ! 421: printf("\n"); ! 422: printf(" LATENCY = %d", sp->latency); ! 423: printf(" LATENCY = %d", sp->latency); ! 424: printf(" LATENCY = %d", sp->latency); ! 425: printf(" LATENCY = %d", sp->latency); ! 426: } ! 427: #else MACH_KERNEL ! 428: printf("de%d: port = %x, spl = %d, pic = %d. ", ! 429: unit, dev->dev_addr, dev->dev_spl, dev->dev_pic); ! 430: ! 431: printf("ethernet id [%x:%x:%x:%x:%x:%x]\n", ! 432: sp->address[0],sp->address[1],sp->address[2], ! 433: sp->address[3],sp->address[4],sp->address[5]); ! 434: ! 435: if (sp->latency > 1) { ! 436: printf("de%d:", unit); ! 437: printf(" LATENCY = %d", sp->latency); ! 438: printf(" LATENCY = %d", sp->latency); ! 439: printf(" LATENCY = %d", sp->latency); ! 440: printf(" LATENCY = %d", sp->latency); ! 441: printf("\n"); ! 442: } ! 443: #endif MACH_KERNEL ! 444: ! 445: return 1; ! 446: } ! 447: ! 448: /* ! 449: * de6cwatch(): ! 450: * ! 451: */ ! 452: void de6cwatch(b_ptr) ! 453: short *b_ptr; ! 454: { ! 455: #ifdef DEBUG_MORE ! 456: int unit = *b_ptr; ! 457: de6c_softc_t *sp = &de6c_softc[unit]; ! 458: ! 459: if(!de6cdo_watch) return; ! 460: de6cintr(unit); ! 461: if (sp->ds_if.if_flags & IFF_RUNNING) ! 462: timeout(de6cwatch, b_ptr, de6cdo_watch); ! 463: #endif /* DEBUG_MORE */ ! 464: } ! 465: ! 466: #ifdef MACH_KERNEL ! 467: void de6cstart(int); /* forward */ ! 468: ! 469: de6coutput(dev, ior) ! 470: dev_t dev; ! 471: io_req_t ior; ! 472: { ! 473: register int unit = minor(dev); ! 474: ! 475: if (unit < 0 || unit >= NDE6C || ! 476: de6c_softc[unit].port == 0) ! 477: return (ENXIO); ! 478: ! 479: return (net_write(&de6c_softc[unit].ds_if, de6cstart, ior)); ! 480: } ! 481: ! 482: io_return_t ! 483: de6csetinput( ! 484: dev_t dev, ! 485: mach_port_t receive_port, ! 486: int priority, ! 487: filter_t filter[], ! 488: natural_t filter_count) ! 489: { ! 490: register int unit = minor(dev); ! 491: ! 492: if (unit < 0 || unit >= NDE6C || ! 493: de6c_softc[unit].port == 0) ! 494: return ENXIO; ! 495: ! 496: return net_set_filter(&de6c_softc[unit].ds_if, ! 497: receive_port, priority, ! 498: filter, filter_count); ! 499: } ! 500: ! 501: #else MACH_KERNEL ! 502: /* ! 503: * de6coutput: ! 504: * ! 505: * This routine is called by the "if" layer to output a packet to ! 506: * the network. This code resolves the local ethernet address, and ! 507: * puts it into the mbuf if there is room. If not, then a new mbuf ! 508: * is allocated with the header information and precedes the data ! 509: * to be transmitted. ! 510: * ! 511: * input: ifnet structure pointer, an mbuf with data, and address ! 512: * to be resolved ! 513: * output: mbuf is updated to hold enet address, or a new mbuf ! 514: * with the address is added ! 515: * ! 516: */ ! 517: de6coutput(ifp, m0, dst) ! 518: struct ifnet *ifp; ! 519: struct mbuf *m0; ! 520: struct sockaddr *dst; ! 521: { ! 522: register de6c_softc_t *sp = &de6c_softc[ifp->if_unit]; ! 523: int type, opri, error; ! 524: u_char edst[6]; ! 525: struct in_addr idst; ! 526: register struct mbuf *m = m0; ! 527: register struct ether_header *eh; ! 528: register int off; ! 529: int usetrailers; ! 530: ! 531: if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { ! 532: de6cintoff(ifp->if_unit); ! 533: error = ENETDOWN; ! 534: goto bad; ! 535: } ! 536: switch (dst->sa_family) { ! 537: ! 538: #ifdef INET ! 539: case AF_INET: ! 540: idst = ((struct sockaddr_in *)dst)->sin_addr; ! 541: if (!arpresolve(&sp->de6c_ac, m, &idst, edst, &usetrailers)){ ! 542: return (0); /* if not yet resolved */ ! 543: } ! 544: off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; ! 545: ! 546: if (usetrailers && off > 0 && (off & 0x1ff) == 0 && ! 547: m->m_off >= MMINOFF + 2 * sizeof (u_short)) { ! 548: type = ETHERTYPE_TRAIL + (off>>9); ! 549: m->m_off -= 2 * sizeof (u_short); ! 550: m->m_len += 2 * sizeof (u_short); ! 551: *mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP); ! 552: *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len); ! 553: goto gottrailertype; ! 554: } ! 555: type = ETHERTYPE_IP; ! 556: off = 0; ! 557: goto gottype; ! 558: #endif ! 559: #ifdef NS ! 560: case AF_NS: ! 561: type = ETHERTYPE_NS; ! 562: bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), ! 563: (caddr_t)edst, sizeof (edst)); ! 564: off = 0; ! 565: goto gottype; ! 566: #endif ! 567: ! 568: case AF_UNSPEC: ! 569: eh = (struct ether_header *)dst->sa_data; ! 570: bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst)); ! 571: type = eh->ether_type; ! 572: goto gottype; ! 573: ! 574: default: ! 575: printf("de6c%d: can't handle af%d\n", ifp->if_unit, ! 576: dst->sa_family); ! 577: error = EAFNOSUPPORT; ! 578: goto bad; ! 579: } ! 580: ! 581: gottrailertype: ! 582: /* ! 583: * Packet to be sent as trailer: move first packet ! 584: * (control information) to end of chain. ! 585: */ ! 586: while (m->m_next) ! 587: m = m->m_next; ! 588: m->m_next = m0; ! 589: m = m0->m_next; ! 590: m0->m_next = 0; ! 591: m0 = m; ! 592: ! 593: gottype: ! 594: /* ! 595: * Add local net header. If no space in first mbuf, ! 596: * allocate another. ! 597: */ ! 598: if (m->m_off > MMAXOFF || ! 599: MMINOFF + sizeof (struct ether_header) > m->m_off) { ! 600: m = m_get(M_DONTWAIT, MT_HEADER); ! 601: if (m == 0) { ! 602: error = ENOBUFS; ! 603: goto bad; ! 604: } ! 605: m->m_next = m0; ! 606: m->m_off = MMINOFF; ! 607: m->m_len = sizeof (struct ether_header); ! 608: } else { ! 609: m->m_off -= sizeof (struct ether_header); ! 610: m->m_len += sizeof (struct ether_header); ! 611: } ! 612: eh = mtod(m, struct ether_header *); ! 613: eh->ether_type = htons((u_short)type); ! 614: bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst)); ! 615: bcopy((caddr_t)sp->address,(caddr_t)eh->ether_shost, sizeof(edst)); ! 616: /* ! 617: * Queue message on interface, and start output if interface ! 618: * not yet active. ! 619: */ ! 620: opri = SPLNET(); ! 621: if (IF_QFULL(&ifp->if_snd)) { ! 622: IF_DROP(&ifp->if_snd); ! 623: splx(opri); ! 624: m_freem(m); ! 625: return (ENOBUFS); ! 626: } ! 627: IF_ENQUEUE(&ifp->if_snd, m); ! 628: de6cstart(ifp->if_unit); ! 629: splx(opri); ! 630: return (0); ! 631: ! 632: bad: ! 633: m_freem(m0); ! 634: return (error); ! 635: } ! 636: #endif MACH_KERNEL ! 637: ! 638: /* ! 639: * de6creset: ! 640: * ! 641: * This routine is in part an entry point for the "if" code. Since most ! 642: * of the actual initialization has already (we hope already) been done ! 643: * by calling de6cattach(). ! 644: * ! 645: * input : unit number or board number to reset ! 646: * output : board is reset ! 647: * ! 648: */ ! 649: de6creset(unit) ! 650: int unit; ! 651: { ! 652: de6c_softc[unit].ds_if.if_flags &= ~IFF_RUNNING; ! 653: return(de6cinit(unit)); ! 654: } ! 655: ! 656: ! 657: ! 658: /* ! 659: * de6cinit: ! 660: * ! 661: * Another routine that interfaces the "if" layer to this driver. ! 662: * Simply resets the structures that are used by "upper layers". ! 663: * ! 664: * input : board number ! 665: * output : structures (if structs) and board are reset ! 666: * ! 667: */ ! 668: de6cinit(unit) ! 669: int unit; ! 670: { ! 671: de6c_softc_t *sp = &de6c_softc[unit]; ! 672: struct ifnet *ifp = &(sp->ds_if); ! 673: int port = sp->port; ! 674: int pic = lprinfo[unit]->PIC; ! 675: spl_t oldpri; ! 676: ! 677: #ifdef MACH_KERNEL ! 678: #else MACH_KERNEL ! 679: if (ifp->if_addrlist == (struct ifaddr *)0) { ! 680: return; ! 681: } ! 682: #endif MACH_KERNEL ! 683: oldpri = SPLNET(); ! 684: ! 685: if (ivect[pic] != de6cintr) { ! 686: sp->oldvect = ivect[pic]; ! 687: ivect[pic] = de6cintr; ! 688: sp->oldunit = iunit[pic]; ! 689: iunit[pic] = unit; ! 690: } ! 691: ! 692: /* d-link 600 ON; d-link 600 ON; d-link 600 ON; d-link 600 ON */ ! 693: /* d-link 600 ON; d-link 600 ON; d-link 600 ON; d-link 600 ON */ ! 694: sp->consume = 0; ! 695: sp->produce = 0; ! 696: de6coutb(sp, CMD(port), SLT_NIC); ! 697: DATA_OUT(sp, port, COMMAND, RESET); ! 698: DATA_OUT(sp, port, COMMAND, STOP_RESET); ! 699: de6coutb(sp, CMD(port), IRQEN); ! 700: DATA_OUT(sp, port, COMMAND, RX_BP|(sp->produce<<4)); ! 701: DATA_OUT(sp, port, COMMAND, RX_BP|(sp->produce<<4)|RXEN); ! 702: de6coutb(sp, CMD(port), SLT_PRN); ! 703: #if 0 ! 704: if (sp->mode & IFF_PROMISC) { ! 705: /* handle promiscuous case */; ! 706: } ! 707: #endif 0 ! 708: /* d-link 600 OFF; d-link 600 OFF; d-link 600 OFF; d-link 600 OFF */ ! 709: /* d-link 600 OFF; d-link 600 OFF; d-link 600 OFF; d-link 600 OFF */ ! 710: sp->ds_if.if_flags |= IFF_RUNNING; ! 711: sp->flags |= DSF_RUNNING; ! 712: sp->timer = 5; ! 713: timeout(de6cwatch, &(ifp->if_unit), 3); ! 714: de6cstart(unit); ! 715: splx(oldpri); ! 716: } ! 717: ! 718: #ifdef MACH_KERNEL ! 719: /*ARGSUSED*/ ! 720: de6copen(dev, flag) ! 721: dev_t dev; ! 722: int flag; ! 723: { ! 724: register int unit = minor(dev); ! 725: ! 726: if (unit < 0 || unit >= NDE6C || ! 727: de6c_softc[unit].port == 0) ! 728: return (ENXIO); ! 729: ! 730: de6c_softc[unit].ds_if.if_flags |= IFF_UP; ! 731: de6cinit(unit); ! 732: return(0); ! 733: } ! 734: #endif MACH_KERNEL ! 735: ! 736: /* ! 737: * de6cstart: ! 738: * ! 739: * This is yet another interface routine that simply tries to output a ! 740: * in an mbuf after a reset. ! 741: * ! 742: * input : board number ! 743: * output : stuff sent to board if any there ! 744: * ! 745: */ ! 746: ! 747: /* NOTE: called at SPLNET */ ! 748: void de6cstart( ! 749: int unit) ! 750: { ! 751: struct ifnet *ifp = &(de6c_softc[unit].ds_if); ! 752: MM m; ! 753: ! 754: for(;;) { ! 755: IF_DEQUEUE(&ifp->if_snd, m); ! 756: if (m != (MM) 0) ! 757: de6cxmt(unit, m); ! 758: else ! 759: return; ! 760: } ! 761: } ! 762: ! 763: #ifdef MACH_KERNEL ! 764: /*ARGSUSED*/ ! 765: io_return_t ! 766: de6cgetstat( ! 767: dev_t dev, ! 768: int flavor, ! 769: dev_status_t status, /* pointer to OUT array */ ! 770: natural_t *count) /* out */ ! 771: { ! 772: register int unit = minor(dev); ! 773: register de6c_softc_t *sp; ! 774: ! 775: if (unit < 0 || unit >= NDE6C || ! 776: de6c_softc[unit].port == 0) ! 777: return (ENXIO); ! 778: ! 779: sp = &de6c_softc[unit]; ! 780: if (! sp->alive) ! 781: if (! (sp->alive = de6calive(sp))) ! 782: return ENXIO; ! 783: ! 784: return (net_getstat(&de6c_softc[unit].ds_if, ! 785: flavor, ! 786: status, ! 787: count)); ! 788: } ! 789: ! 790: io_return_t ! 791: de6csetstat( ! 792: dev_t dev, ! 793: int flavor, ! 794: dev_status_t status, ! 795: natural_t count) ! 796: { ! 797: register int unit = minor(dev); ! 798: register de6c_softc_t *sp; ! 799: ! 800: if (unit < 0 || unit >= NDE6C || ! 801: de6c_softc[unit].port == 0) ! 802: return (ENXIO); ! 803: ! 804: sp = &de6c_softc[unit]; ! 805: if (! sp->alive) ! 806: if (! (sp->alive = de6calive(sp))) ! 807: return ENXIO; ! 808: ! 809: ! 810: switch (flavor) { ! 811: case NET_STATUS: ! 812: { ! 813: /* ! 814: * All we can change are flags, and not many of those. ! 815: */ ! 816: register struct net_status *ns = (struct net_status *)status; ! 817: int mode = 0; ! 818: ! 819: if (count < NET_STATUS_COUNT) ! 820: return (D_INVALID_SIZE); ! 821: ! 822: if (ns->flags & IFF_ALLMULTI) ! 823: mode |= MOD_ENAL; ! 824: if (ns->flags & IFF_PROMISC) ! 825: mode |= MOD_PROM; ! 826: ! 827: /* ! 828: * Force a compilete reset if the receive mode changes ! 829: * so that these take effect immediately. ! 830: */ ! 831: if (sp->mode != mode) { ! 832: sp->mode = mode; ! 833: if (sp->flags & DSF_RUNNING) { ! 834: sp->flags &= ~(DSF_LOCK | DSF_RUNNING); ! 835: de6cinit(unit); ! 836: } ! 837: } ! 838: break; ! 839: } ! 840: case NET_ADDRESS: ! 841: { ! 842: register union ether_cvt { ! 843: char addr[6]; ! 844: int lwd[2]; ! 845: } *ec = (union ether_cvt *)status; ! 846: ! 847: if (count < sizeof(*ec)/sizeof(int)) ! 848: return (D_INVALID_SIZE); ! 849: ! 850: ec->lwd[0] = ntohl(ec->lwd[0]); ! 851: ec->lwd[1] = ntohl(ec->lwd[1]); ! 852: de6csetid(sp->port, ec->addr); ! 853: break; ! 854: } ! 855: ! 856: default: ! 857: return (D_INVALID_OPERATION); ! 858: } ! 859: return (D_SUCCESS); ! 860: } ! 861: #else MACH_KERNEL ! 862: ! 863: /* ! 864: * de6cioctl: ! 865: * ! 866: * This routine processes an ioctl request from the "if" layer ! 867: * above. ! 868: * ! 869: * input : pointer the appropriate "if" struct, command, and data ! 870: * output : based on command appropriate action is taken on the ! 871: * de6c board(s) or related structures ! 872: * return : error is returned containing exit conditions ! 873: * ! 874: */ ! 875: de6cioctl(ifp, cmd, data) ! 876: struct ifnet *ifp; ! 877: int cmd; ! 878: caddr_t data; ! 879: { ! 880: register struct ifaddr *ifa = (struct ifaddr *)data; ! 881: register de6c_softc_t *sp = &de6c_softc[ifp->if_unit]; ! 882: int opri, error; ! 883: short mode = 0; ! 884: ! 885: if (! sp->alive) ! 886: if (! (sp->alive = de6calive(sp))) ! 887: return ENXIO; ! 888: ! 889: opri = SPLNET(); ! 890: error = 0; ! 891: switch (cmd) { ! 892: case SIOCSIFADDR: ! 893: ifp->if_flags |= IFF_UP; ! 894: de6cinit(ifp->if_unit); ! 895: switch (ifa->ifa_addr.sa_family) { ! 896: #ifdef INET ! 897: case AF_INET: ! 898: ((struct arpcom *)ifp)->ac_ipaddr = ! 899: IA_SIN(ifa)->sin_addr; ! 900: arpwhohas((struct arpcom *)ifp, ! 901: &IA_SIN(ifa)->sin_addr); ! 902: break; ! 903: #endif ! 904: #ifdef NS ! 905: case AF_NS: ! 906: { ! 907: register struct ns_addr *ina = ! 908: &(IA_SNS(ifa)->sns_addr); ! 909: if (ns_nullhost(*ina)) ! 910: ina->x_host = ! 911: *(union ns_host *)(ds->ds_addr); ! 912: else ! 913: de6cseteh(ina->x_host.c_host, ! 914: de6c_softc[ifp->if_unit].port); ! 915: break; ! 916: } ! 917: #endif ! 918: } ! 919: break; ! 920: case SIOCSIFFLAGS: ! 921: if (ifp->if_flags & IFF_ALLMULTI) ! 922: mode |= MOD_ENAL; ! 923: if (ifp->if_flags & IFF_PROMISC) ! 924: mode |= MOD_PROM; ! 925: /* ! 926: * force a complete reset if the receive multicast/ ! 927: * promiscuous mode changes so that these take ! 928: * effect immediately. ! 929: * ! 930: */ ! 931: if (sp->mode != mode) { ! 932: sp->mode = mode; ! 933: if (sp->flags & DSF_RUNNING) { ! 934: sp->flags &= ! 935: ~(DSF_LOCK|DSF_RUNNING); ! 936: de6cinit(ifp->if_unit); ! 937: } ! 938: } ! 939: if ((ifp->if_flags & IFF_UP) == 0 && ! 940: sp->flags & DSF_RUNNING) { ! 941: sp->timer = -1; ! 942: de6cintoff(ifp->if_unit); ! 943: } else ! 944: if (ifp->if_flags & IFF_UP && ! 945: (sp->flags & DSF_RUNNING) == 0) ! 946: de6cinit(ifp->if_unit); ! 947: break; ! 948: default: ! 949: error = EINVAL; ! 950: } ! 951: splx(opri); ! 952: return (error); ! 953: } ! 954: #endif MACH_KERNEL ! 955: ! 956: /* ! 957: * de6cintr: ! 958: * ! 959: * This function is the interrupt handler for the de6c ethernet ! 960: * board. This routine will be called whenever either a packet ! 961: * is received, or a packet has successfully been transfered and ! 962: * the unit is ready to transmit another packet. ! 963: * ! 964: * input : board number that interrupted ! 965: * output : either a packet is received, or a packet is transfered ! 966: * ! 967: */ ! 968: /* d-link 600 ON; d-link 600 ON; d-link 600 ON; d-link 600 ON */ ! 969: /* d-link 600 ON; d-link 600 ON; d-link 600 ON; d-link 600 ON */ ! 970: #ifdef DEBUG_MORE ! 971: de6crcvintr(unit) ! 972: int unit; ! 973: { ! 974: if(!de6cdo_rcvintr) ! 975: return; ! 976: de6cintr(unit); ! 977: } ! 978: #endif /* DEBUG_MORE */ ! 979: ! 980: de6cintr(unit) ! 981: int unit; ! 982: { ! 983: register de6c_softc_t *sp = &de6c_softc[unit]; ! 984: int port = sp->port; ! 985: int in; ! 986: ! 987: if (de6cactive[unit] || !(sp->flags & DSF_RUNNING)) ! 988: return; ! 989: de6cactive[unit]++; ! 990: de6coutb(sp, CMD(port), SLT_NIC); ! 991: STAT_IN(sp, port, in); ! 992: ! 993: if ((in & (GOOD|TXBUSY)) == (GOOD|TXBUSY)) { ! 994: /* on L40's means that we are disconnected */ ! 995: printf("de6intr%d: Card was disconnected; turning off network.\n", unit); ! 996: de6cintoff(unit); ! 997: de6cactive[unit]--; ! 998: return; ! 999: } ! 1000: ! 1001: if (in & GOOD) ! 1002: de6crcv(unit, in); ! 1003: else ! 1004: /*rvb:tmp printf("intr: %x\n", in)*/; ! 1005: ! 1006: ! 1007: de6coutb(sp, CMD(port), SLT_PRN); ! 1008: de6cactive[unit]--; ! 1009: } ! 1010: /* d-link 600 OFF; d-link 600 OFF; d-link 600 OFF; d-link 600 OFF */ ! 1011: /* d-link 600 OFF; d-link 600 OFF; d-link 600 OFF; d-link 600 OFF */ ! 1012: ! 1013: /* ! 1014: * de6crcv: ! 1015: * ! 1016: * This routine is called by the interrupt handler to initiate a ! 1017: * packet transfer from the board to the "if" layer above this ! 1018: * driver. This routine checks if a buffer has been successfully ! 1019: * received by the de6c. If so, the routine de6cread is called ! 1020: * to do the actual transfer of the board data (including the ! 1021: * ethernet header) into a packet (consisting of an mbuf chain). ! 1022: * ! 1023: * input : number of the board to check ! 1024: * output : if a packet is available, it is "sent up" ! 1025: * ! 1026: */ ! 1027: de6crcv(unit, in) ! 1028: int unit, in; ! 1029: { ! 1030: register de6c_softc_t *sp = &de6c_softc[unit]; ! 1031: register struct ifnet *ifp = &sp->ds_if; ! 1032: int port = sp->port; ! 1033: int bo; ! 1034: int collision = 0; ! 1035: int spins = 0; ! 1036: u_short len; ! 1037: struct ether_header header; ! 1038: int tlen; ! 1039: register struct ifqueue *inq; ! 1040: int opri; ! 1041: struct ether_header eh; ! 1042: #ifdef MACH_KERNEL ! 1043: ipc_kmsg_t new_kmsg; ! 1044: struct ether_header *ehp; ! 1045: struct packet_header *pkt; ! 1046: #else MACH_KERNEL ! 1047: struct mbuf *m, *tm; ! 1048: #endif MACH_KERNEL ! 1049: ! 1050: sp->rcv++; ! 1051: ! 1052: /* d-link 600 ON; d-link 600 ON; d-link 600 ON; d-link 600 ON */ ! 1053: /* d-link 600 ON; d-link 600 ON; d-link 600 ON; d-link 600 ON */ ! 1054: D(de6crcv0++); ! 1055: #define MT (sp->consume == sp->produce) ! 1056: while (in & GOOD || !MT) { ! 1057: spins++; ! 1058: D(de6crcv1++); ! 1059: if (in & GOOD) { ! 1060: sp->rcvlen[sp->produce] = de6clen(sp); ! 1061: if ( ((sp->produce + 1) % XMTidx) != sp->consume) { ! 1062: if (++sp->produce == XMTidx) ! 1063: sp->produce = 0; ! 1064: DATA_OUT(sp, port, COMMAND, RX_BP|(sp->produce<<4)); ! 1065: DATA_OUT(sp, port, COMMAND, RX_BP|(sp->produce<<4)|RXEN); ! 1066: } else collision = 1; ! 1067: } ! 1068: len = sp->rcvlen[sp->consume]; ! 1069: bo = sp->consume*BFRSIZ; ! 1070: if (len < 60) { ! 1071: printf("de%d: len(%d) < 60\n", unit, len); ! 1072: goto out; ! 1073: return; ! 1074: } ! 1075: de6cread(sp, bo, &eh, sizeof(struct ether_header)); ! 1076: bo += sizeof(struct ether_header); ! 1077: len -= 18; ! 1078: /* d-link 600 OFF; d-link 600 OFF; d-link 600 OFF; d-link 600 OFF */ ! 1079: /* d-link 600 OFF; d-link 600 OFF; d-link 600 OFF; d-link 600 OFF */ ! 1080: ! 1081: #ifdef MACH_KERNEL ! 1082: new_kmsg = net_kmsg_get(); ! 1083: if (new_kmsg == IKM_NULL) { ! 1084: /* ! 1085: * Drop the packet. ! 1086: */ ! 1087: sp->ds_if.if_rcvdrops++; ! 1088: goto out; ! 1089: return; ! 1090: } ! 1091: ! 1092: ehp = (struct ether_header *) ! 1093: (&net_kmsg(new_kmsg)->header[0]); ! 1094: pkt = (struct packet_header *) ! 1095: (&net_kmsg(new_kmsg)->packet[0]); ! 1096: ! 1097: /* ! 1098: * Get header. ! 1099: */ ! 1100: *ehp = eh; ! 1101: ! 1102: /* ! 1103: * Get body ! 1104: */ ! 1105: /* d-link 600 ON; d-link 600 ON; d-link 600 ON; d-link 600 ON */ ! 1106: de6cread(sp, bo, (char *)(pkt + 1), len); ! 1107: /* d-link 600 OFF; d-link 600 OFF; d-link 600 OFF; d-link 600 OFF */ ! 1108: pkt->type = ehp->ether_type; ! 1109: pkt->length = len + sizeof(struct packet_header); ! 1110: ! 1111: /* ! 1112: * Hand the packet to the network module. ! 1113: */ ! 1114: net_packet(ifp, new_kmsg, pkt->length, ! 1115: ethernet_priority(new_kmsg)); ! 1116: ! 1117: #else MACH_KERNEL ! 1118: eh.ether_type = htons(eh.ether_type); ! 1119: m =(struct mbuf *)0; ! 1120: while ( len ) { ! 1121: if (m == (struct mbuf *)0) { ! 1122: m = m_get(M_DONTWAIT, MT_DATA); ! 1123: if (m == (struct mbuf *)0) { ! 1124: printf("de6crcv: Lost frame\n"); ! 1125: goto out; ! 1126: return; ! 1127: } ! 1128: tm = m; ! 1129: tm->m_off = MMINOFF; ! 1130: /* ! 1131: * first mbuf in the packet must contain a pointer to the ! 1132: * ifnet structure. other mbufs that follow and make up ! 1133: * the packet do not need this pointer in the mbuf. ! 1134: * ! 1135: */ ! 1136: *(mtod(tm, struct ifnet **)) = ifp; ! 1137: tm->m_len = sizeof(struct ifnet **); ! 1138: } ! 1139: else { ! 1140: tm->m_next = m_get(M_DONTWAIT, MT_DATA); ! 1141: tm = tm->m_next; ! 1142: tm->m_off = MMINOFF; ! 1143: tm->m_len = 0; ! 1144: if (tm == (struct mbuf *)0) { ! 1145: m_freem(m); ! 1146: printf("de6crcv: No mbufs, lost frame\n"); ! 1147: goto out; ! 1148: return; ! 1149: } ! 1150: } ! 1151: tlen = MIN( MLEN - tm->m_len, len ); ! 1152: tm->m_next = (struct mbuf *)0; ! 1153: /* d-link 600 ON; d-link 600 ON; d-link 600 ON; d-link 600 ON */ ! 1154: de6cread(sp, bo, mtod(tm, char *)+tm->m_len, tlen); ! 1155: bo += tlen; ! 1156: /* d-link 600 OFF; d-link 600 OFF; d-link 600 OFF; d-link 600 OFF */ ! 1157: tm->m_len += tlen; ! 1158: len -= tlen; ! 1159: } ! 1160: /* d-link 600 ON; d-link 600 ON; d-link 600 ON; d-link 600 ON */ ! 1161: /* d-link 600 ON; d-link 600 ON; d-link 600 ON; d-link 600 ON */ ! 1162: STAT_IN(sp, port, in); ! 1163: if (in & GOOD) { /* got another */ ! 1164: D(de6crcv2++); ! 1165: sp->rcvlen[sp->produce] = de6clen(sp); ! 1166: if ( ((sp->produce + 1) % XMTidx) != sp->consume) { ! 1167: if (++sp->produce == XMTidx) ! 1168: sp->produce = 0; ! 1169: DATA_OUT(sp, port, COMMAND, RX_BP|(sp->produce<<4)); ! 1170: DATA_OUT(sp, port, COMMAND, RX_BP|(sp->produce<<4)|RXEN); ! 1171: } else collision = 1; ! 1172: } ! 1173: /* d-link 600 OFF; d-link 600 OFF; d-link 600 OFF; d-link 600 OFF */ ! 1174: /* d-link 600 OFF; d-link 600 OFF; d-link 600 OFF; d-link 600 OFF */ ! 1175: ! 1176: /* ! 1177: * received packet is now in a chain of mbuf's. next step is ! 1178: * to pass the packet upwards. ! 1179: * ! 1180: */ ! 1181: switch (eh.ether_type) { ! 1182: ! 1183: #ifdef INET ! 1184: case ETHERTYPE_IP: ! 1185: schednetisr(NETISR_IP); ! 1186: inq = &ipintrq; ! 1187: break; ! 1188: case ETHERTYPE_ARP: ! 1189: arpinput(&sp->de6c_ac, m); ! 1190: goto out; ! 1191: return; ! 1192: #endif ! 1193: #ifdef NS ! 1194: case ETHERTYPE_NS: ! 1195: schednetisr(NETISR_NS); ! 1196: inq = &nsintrq; ! 1197: break; ! 1198: #endif ! 1199: default: ! 1200: m_freem(m); ! 1201: goto out; ! 1202: return; ! 1203: } ! 1204: opri = SPLNET(); ! 1205: if (IF_QFULL(inq)) { ! 1206: IF_DROP(inq); ! 1207: splx(opri); ! 1208: m_freem(m); ! 1209: goto out; ! 1210: return; ! 1211: } ! 1212: IF_ENQUEUE(inq, m); ! 1213: splx(opri); ! 1214: #endif MACH_KERNEL ! 1215: out: ! 1216: /* d-link 600 ON; d-link 600 ON; d-link 600 ON; d-link 600 ON */ ! 1217: /* d-link 600 ON; d-link 600 ON; d-link 600 ON; d-link 600 ON */ ! 1218: STAT_IN(sp, port, in); ! 1219: if (in & GOOD) { /* got another */ ! 1220: D(de6crcv3++); ! 1221: } ! 1222: /*2*/ /* implies wrap and pause */ ! 1223: if (collision) { ! 1224: collision = 0; ! 1225: D(printf("*C* ")); ! 1226: sp->rcvoff++; ! 1227: if (++sp->produce == XMTidx) ! 1228: sp->produce = 0; ! 1229: DATA_OUT(sp, port, COMMAND, RX_BP|(sp->produce<<4)); ! 1230: DATA_OUT(sp, port, COMMAND, RX_BP|(sp->produce<<4)|RXEN); ! 1231: } ! 1232: /*2*/ /* implies wrap and pause */ ! 1233: if (++sp->consume == XMTidx) ! 1234: sp->consume = 0; ! 1235: if (spins > 10) { ! 1236: spins = 0; ! 1237: D(printf("*R* ")); ! 1238: sp->rcvspin++; ! 1239: /* how should we recover here ??? */; ! 1240: /* return does not work */; ! 1241: /* de6cinit(unit) gets ugly if we are called from ! 1242: de6cxmt */; ! 1243: } ! 1244: /* d-link 600 OFF; d-link 600 OFF; d-link 600 OFF; d-link 600 OFF */ ! 1245: /* d-link 600 OFF; d-link 600 OFF; d-link 600 OFF; d-link 600 OFF */ ! 1246: } ! 1247: } ! 1248: ! 1249: ! 1250: /* ! 1251: * de6cxmt: ! 1252: * ! 1253: * This routine fills in the appropriate registers and memory ! 1254: * locations on the d-link "600" board and starts the board off on ! 1255: * the transmit. ! 1256: * ! 1257: * input : board number of interest, and a pointer to the mbuf ! 1258: * output : board memory and registers are set for xfer and attention ! 1259: * ! 1260: */ ! 1261: /* NOTE: called at SPLNET */ ! 1262: /* ! 1263: * This implies that rcv interrupts will be blocked. ! 1264: */ ! 1265: #define max(a,b) (((a) > (b)) ? (a) : (b)) ! 1266: ! 1267: char de6mt[ETHERMIN]; ! 1268: de6cxmt(unit, m) ! 1269: int unit; ! 1270: MM m; ! 1271: { ! 1272: #ifdef MACH_KERNEL ! 1273: #else MACH_KERNEL ! 1274: register struct mbuf *tm_p; ! 1275: #endif MACH_KERNEL ! 1276: int i; ! 1277: int in; ! 1278: int bo, boo; ! 1279: de6c_softc_t *sp = &de6c_softc[unit]; ! 1280: int port = sp->port; ! 1281: u_short count = 0; ! 1282: u_short bytes_in_msg; ! 1283: static int m_length(); ! 1284: ! 1285: /* d-link 600 ON; d-link 600 ON; d-link 600 ON; d-link 600 ON */ ! 1286: /* d-link 600 ON; d-link 600 ON; d-link 600 ON; d-link 600 ON */ ! 1287: if (de6cactive[unit] >= 2) /* a funny loop caused by */ ! 1288: return; /* a flood of arps */ ! 1289: if (de6cactive[unit]++ == 0) ! 1290: de6coutb(sp, CMD(port), SLT_NIC); ! 1291: STAT_IN(sp, port, in); ! 1292: ! 1293: D(if (de6cdo_xmt) printf("xmt: stat[-] = %x\n", in)); ! 1294: if (in & GOOD) { ! 1295: de6crcv(unit, in); ! 1296: } ! 1297: sp->xmt++; ! 1298: /* d-link 600 OFF; d-link 600 OFF; d-link 600 OFF; d-link 600 OFF */ ! 1299: /* d-link 600 OFF; d-link 600 OFF; d-link 600 OFF; d-link 600 OFF */ ! 1300: ! 1301: #ifdef MACH_KERNEL ! 1302: count = m->io_count; ! 1303: bytes_in_msg = max(count, ETHERMIN + sizeof(struct ether_header)); ! 1304: /* d-link 600 ON; d-link 600 ON; d-link 600 ON; d-link 600 ON */ ! 1305: boo = bo = XMTidx*BFRSIZ+(BFRSIZ-bytes_in_msg); ! 1306: de6cwrite(sp, bo, m->io_data, count); ! 1307: /* d-link 600 OFF; d-link 600 OFF; d-link 600 OFF; d-link 600 OFF */ ! 1308: bo += count; ! 1309: iodone(m); ! 1310: #else MACH_KERNEL ! 1311: bytes_in_msg = max(m_length(m), ETHERMIN + sizeof(struct ether_header)); ! 1312: /* d-link 600 ON; d-link 600 ON; d-link 600 ON; d-link 600 ON */ ! 1313: boo = bo = XMTidx*BFRSIZ+(BFRSIZ-bytes_in_msg); ! 1314: /* d-link 600 OFF; d-link 600 OFF; d-link 600 OFF; d-link 600 OFF */ ! 1315: ! 1316: for (tm_p = m; tm_p != (struct mbuf *)0; tm_p = tm_p->m_next) { ! 1317: if (count + tm_p->m_len > ETHERMTU + sizeof(struct ether_header)) ! 1318: break; ! 1319: if (tm_p->m_len == 0) ! 1320: continue; ! 1321: /* d-link 600 ON; d-link 600 ON; d-link 600 ON; d-link 600 ON */ ! 1322: de6cwrite(sp, bo, mtod(tm_p, caddr_t), tm_p->m_len); ! 1323: bo += tm_p->m_len; ! 1324: /* d-link 600 OFF; d-link 600 OFF; d-link 600 OFF; d-link 600 OFF */ ! 1325: count += tm_p->m_len; ! 1326: } ! 1327: m_freem(m); ! 1328: #endif MACH_KERNEL ! 1329: ! 1330: /* d-link 600 ON; d-link 600 ON; d-link 600 ON; d-link 600 ON */ ! 1331: /* d-link 600 ON; d-link 600 ON; d-link 600 ON; d-link 600 ON */ ! 1332: if (bytes_in_msg - count > 0) ! 1333: de6cwrite(sp, bo, de6mt, bytes_in_msg - count); ! 1334: ! 1335: DATA_OUT(sp, port, TX_ADR, boo & 0xff); ! 1336: DATA_OUT(sp, port, TX_ADR, (boo >> 8) & 0xff); ! 1337: DATA_OUT(sp, port, COMMAND, RX_BP|(sp->produce<<4)); ! 1338: DATA_OUT(sp, port, COMMAND, RX_BP|(sp->produce<<4)|TXEN); ! 1339: ! 1340: for (i = 0; i < XMT_BSY_WAIT; i++) { ! 1341: STAT_IN(sp, port, in); ! 1342: D(if (de6cdo_xmt) printf("xmt: stat[%d] = %x\n", i, in)); ! 1343: if (in & GOOD) { ! 1344: /* ! 1345: * this does indeed happen ! 1346: * printf("!#"); ! 1347: */ ! 1348: de6crcv(unit, in); ! 1349: } ! 1350: if (!(in & TXBUSY)) { ! 1351: goto out; ! 1352: return; ! 1353: } ! 1354: } ! 1355: printf("dexmt: stat[??] = %x\n", i, in); ! 1356: out: ! 1357: DATA_OUT(sp, port, COMMAND, RX_BP|(sp->produce<<4)); ! 1358: DATA_OUT(sp, port, COMMAND, RX_BP|(sp->produce<<4)|RXEN); ! 1359: ! 1360: if (--de6cactive[unit] == 0) ! 1361: de6coutb(sp, CMD(port), SLT_PRN); ! 1362: /* d-link 600 OFF; d-link 600 OFF; d-link 600 OFF; d-link 600 OFF */ ! 1363: /* d-link 600 OFF; d-link 600 OFF; d-link 600 OFF; d-link 600 OFF */ ! 1364: } ! 1365: ! 1366: /* ! 1367: * de6cintoff: ! 1368: * ! 1369: * This function turns interrupts off for the de6c board indicated. ! 1370: * ! 1371: */ ! 1372: de6cintoff(unit) ! 1373: int unit; ! 1374: { ! 1375: de6c_softc_t *sp = &de6c_softc[unit]; ! 1376: int port = sp->port; ! 1377: int pic = lprinfo[unit]->PIC; ! 1378: ! 1379: printf("de%d: Turning off d-link \"600\"\n", unit); ! 1380: sp->ds_if.if_flags &= ~(IFF_UP|IFF_RUNNING); ! 1381: sp->flags &= ~(DSF_LOCK | DSF_RUNNING); ! 1382: ! 1383: /* d-link 600 ON; d-link 600 ON; d-link 600 ON; d-link 600 ON */ ! 1384: /* d-link 600 ON; d-link 600 ON; d-link 600 ON; d-link 600 ON */ ! 1385: de6coutb(sp, CMD(port), SLT_NIC); ! 1386: DATA_OUT(sp, port, COMMAND, RESET); ! 1387: DATA_OUT(sp, port, COMMAND, STOP_RESET); ! 1388: de6coutb(sp, CMD(port), SLT_PRN); ! 1389: /* d-link 600 OFF; d-link 600 OFF; d-link 600 OFF; d-link 600 OFF */ ! 1390: /* d-link 600 OFF; d-link 600 OFF; d-link 600 OFF; d-link 600 OFF */ ! 1391: ! 1392: outb(CMD(sp->port), 0x07); ! 1393: ivect[pic] = sp->oldvect; ! 1394: iunit[pic] = sp->oldunit; ! 1395: } ! 1396: ! 1397: #ifdef MACH_KERNEL ! 1398: #else MACH_KERNEL ! 1399: /* ! 1400: * The length of an mbuf chain ! 1401: */ ! 1402: static ! 1403: m_length(m) ! 1404: register struct mbuf *m; ! 1405: { ! 1406: register int len = 0; ! 1407: ! 1408: while (m) { ! 1409: len += m->m_len; ! 1410: m = m->m_next; ! 1411: } ! 1412: return len; ! 1413: } ! 1414: #endif MACH_KERNEL ! 1415: ! 1416: ! 1417: /* d-link 600 ON; d-link 600 ON; d-link 600 ON; d-link 600 ON */ ! 1418: /* d-link 600 ON; d-link 600 ON; d-link 600 ON; d-link 600 ON */ ! 1419: de6cgetid(sp, buf) ! 1420: de6c_softc_t *sp; ! 1421: u_char *buf; ! 1422: { ! 1423: de6cread(sp, EADDR, buf, 6); ! 1424: if ((buf[0] != 0x00) || (buf[1] != 0xde) || (buf[2] != 0x15)) ! 1425: return 0; ! 1426: buf[0] = 0x80; ! 1427: buf[1] = 0x00; ! 1428: buf[2] = 0xc8; ! 1429: /* for this model d-link we assert 0x70 as the high mfr's nibble. */ ! 1430: buf[3] = 0x70 | (buf[3] & 0xf); ! 1431: return 1; ! 1432: } ! 1433: ! 1434: de6csetid(sp, buf) ! 1435: de6c_softc_t *sp; ! 1436: char *buf; ! 1437: { ! 1438: de6cwrite(sp, EADDR, buf, 6); ! 1439: } ! 1440: ! 1441: /* ! 1442: * get length of packet just rcv'd. ! 1443: * includes ether header and crc ! 1444: */ ! 1445: de6clen(sp) ! 1446: de6c_softc_t *sp; ! 1447: { ! 1448: int port = sp->port; ! 1449: int in; ! 1450: int i; ! 1451: ! 1452: de6coutb(sp, DATA(port), RX_LEN); ! 1453: in = inb(STAT(port)); ! 1454: de6coutb(sp, DATA(port), RX_LEN|STROBE); ! 1455: i = ((in>>4) | (inb(STAT(port)) & 0xf0)); ! 1456: ! 1457: de6coutb(sp, DATA(port), RX_LEN); ! 1458: in = inb(STAT(port)); ! 1459: de6coutb(sp, DATA(port), RX_LEN|STROBE); ! 1460: i |= ((in>>4) | (inb(STAT(port)) & 0xf0)) << 8; ! 1461: ! 1462: return i; ! 1463: } ! 1464: ! 1465: #if 0 ! 1466: de6cread(sp, address, buf, len) ! 1467: de6c_softc_t *sp; ! 1468: unsigned char *buf; ! 1469: { ! 1470: int port = sp->port; ! 1471: u_char in; ! 1472: ! 1473: DATA_OUT(sp, port, RW_ADR, address & 0xff); ! 1474: DATA_OUT(sp, port, RW_ADR, (address >> 8) & 0xff); ! 1475: ! 1476: while (len--) { ! 1477: de6coutb(sp, DATA(port), READ); ! 1478: in = inb(STAT(port)); ! 1479: de6coutb(sp, DATA(port), READ|STROBE); ! 1480: *buf++ = ((in>>4) | (inb(STAT(port)) & 0xf0)); ! 1481: } ! 1482: } ! 1483: ! 1484: de6cwrite(sp, address, buf, len) ! 1485: de6c_softc_t *sp; ! 1486: unsigned char *buf; ! 1487: { ! 1488: int port = sp->port; ! 1489: int out; ! 1490: ! 1491: DATA_OUT(sp, port, RW_ADR, address & 0xff); ! 1492: DATA_OUT(sp, port, RW_ADR, (address >> 8) & 0xff); ! 1493: ! 1494: while (len--) { ! 1495: out = *buf++; ! 1496: DATA_OUT(sp, port, WRITE, out); ! 1497: ! 1498: } ! 1499: } ! 1500: #endif 0 ! 1501: ! 1502: #ifndef de6cread ! 1503: de6cread(sp, address, buf, len) ! 1504: de6c_softc_t *sp; ! 1505: unsigned char *buf; ! 1506: { ! 1507: int port = sp->port; ! 1508: register volatile int i; ! 1509: unsigned char in; ! 1510: ! 1511: outb(port, ((address)<<4) | RW_ADR); ! 1512: i = sp->latency; while (i-- > 0); ! 1513: outb(port, ((address)&0xf0)| RW_ADR | 0x8); ! 1514: i = sp->latency; while (i-- > 0); ! 1515: ! 1516: outb(port, ((address>>8)<<4) | RW_ADR); ! 1517: i = sp->latency; while (i-- > 0); ! 1518: outb(port, ((address>>8)&0xf0)| RW_ADR | 0x8); ! 1519: i = sp->latency; while (i-- > 0); ! 1520: ! 1521: while (len--) { ! 1522: outb(port, READ); ! 1523: i = sp->latency; while (i-- > 0); ! 1524: in = inb(STAT(port)); ! 1525: outb(port, READ|0x08); ! 1526: i = sp->latency; while (i-- > 0); ! 1527: *buf++ = ((in>>4) | (inb(STAT(port)) & 0xf0)); ! 1528: } ! 1529: } ! 1530: #endif /* de6cread */ ! 1531: ! 1532: #ifndef de6cwrite ! 1533: de6cwrite(sp, address, buf, len) ! 1534: de6c_softc_t *sp; ! 1535: unsigned char *buf; ! 1536: { ! 1537: int port = sp->port; ! 1538: register volatile int i; ! 1539: unsigned char out; ! 1540: ! 1541: outb(port, ((address)<<4) | RW_ADR); ! 1542: i = sp->latency; while (i-- > 0); ! 1543: outb(port, ((address)&0xf0)| RW_ADR | 0x8); ! 1544: i = sp->latency; while (i-- > 0); ! 1545: ! 1546: outb(port, ((address>>8)<<4) | RW_ADR); ! 1547: i = sp->latency; while (i-- > 0); ! 1548: outb(port, ((address>>8)&0xf0)| RW_ADR | 0x8); ! 1549: i = sp->latency; while (i-- > 0); ! 1550: ! 1551: while (len--) { ! 1552: out = *buf++; ! 1553: outb(port, ((out)<<4) | WRITE); ! 1554: i = sp->latency; while (i-- > 0); ! 1555: outb(port, ((out)&0xf0)| WRITE | 0x8); ! 1556: i = sp->latency; while (i-- > 0); ! 1557: } ! 1558: } ! 1559: #endif /* de6cwrite */ ! 1560: ! 1561: de6coutb(sp, p, v) ! 1562: de6c_softc_t *sp; ! 1563: { ! 1564: register volatile int i = sp->latency; ! 1565: ! 1566: outb(p, v); ! 1567: while (i-- > 0); ! 1568: } ! 1569: ! 1570: de6cmemcheck(sp) ! 1571: de6c_softc_t *sp; ! 1572: { ! 1573: int i; ! 1574: int off = 0; ! 1575: int ret = 1; ! 1576: #ifdef MACH_KERNEL ! 1577: unsigned short *memchk; ! 1578: unsigned short *chkmem; ! 1579: if (kmem_alloc(kernel_map, (vm_offset_t *)&memchk, BFRS * BFRSIZ) != ! 1580: KERN_SUCCESS || ! 1581: kmem_alloc(kernel_map, (vm_offset_t *)&chkmem, BFRS * BFRSIZ) != ! 1582: KERN_SUCCESS) { ! 1583: printf("de6c: memory allocation failure!!\n"); ! 1584: return 0; ! 1585: } ! 1586: #else /* MACH_KERNEL */ ! 1587: unsigned short *memchk = (unsigned short *) kmem_alloc(kernel_map, BFRS * BFRSIZ); ! 1588: unsigned short *chkmem = (unsigned short *) kmem_alloc(kernel_map, BFRS * BFRSIZ); ! 1589: if ( ! ((int) memchk) || ! ((int) chkmem)) { ! 1590: printf("de6c: memory allocation failure!!\n"); ! 1591: return 0; ! 1592: } ! 1593: #endif /* MACH_KERNEL */ ! 1594: ! 1595: for (i = 0; i < BFRS * BFRSIZ/sizeof (short); i++) ! 1596: memchk[i] = i; ! 1597: bzero(chkmem, BFRS * BFRSIZ); ! 1598: ! 1599: ! 1600: for (off = 0; off < BFRS * BFRSIZ; off += BFRSIZ/2) { ! 1601: de6cwrite(sp, off, memchk+(off/sizeof (short)), BFRSIZ/2); ! 1602: de6cread (sp, off, chkmem+(off/sizeof (short)), BFRSIZ/2); ! 1603: } ! 1604: ! 1605: for (i = 0; i < BFRS * (BFRSIZ/sizeof (short)); i++) ! 1606: if (memchk[i] != chkmem[i]) { ! 1607: printf("de: tilt:seq [%x:%d] %x != %x\n", ! 1608: i, i, memchk[i], chkmem[i]); ! 1609: ret = 0; ! 1610: break; ! 1611: } ! 1612: ! 1613: kmem_free(kernel_map, (vm_offset_t) memchk, BFRS * BFRSIZ); ! 1614: kmem_free(kernel_map, (vm_offset_t) chkmem, BFRS * BFRSIZ); ! 1615: ! 1616: return ret; ! 1617: } ! 1618: /* d-link 600 OFF; d-link 600 OFF; d-link 600 OFF; d-link 600 OFF */ ! 1619: /* d-link 600 OFF; d-link 600 OFF; d-link 600 OFF; d-link 600 OFF */ ! 1620: ! 1621: #ifdef DEBUG ! 1622: #define STATIC ! 1623: STATIC int print_pkt(), print_bdy(); ! 1624: STATIC int print_e_hdr(), print_ip_hdr(), print_ip(); ! 1625: STATIC int print_ipa(), print_arp(), print_e(), print_chars(); ! 1626: ! 1627: STATIC ! 1628: print_pkt(p, len) ! 1629: unsigned char *p; ! 1630: { ! 1631: int j, k; ! 1632: int type; ! 1633: ! 1634: if (len < 18) ! 1635: printf("print_pkt: too small %d\n", len); ! 1636: ! 1637: type = print_e_hdr(p); ! 1638: ! 1639: switch (type) { ! 1640: case 0x806: ! 1641: print_arp(p+14); ! 1642: break; ! 1643: case 0x800: ! 1644: print_ip(p+14, len - 18); ! 1645: break; ! 1646: default: ! 1647: for (j = 14; j < len; j +=20) { ! 1648: for (k = 0; k < 20; k++) ! 1649: printf("%2x ", p[j+k]); ! 1650: printf("\n"); ! 1651: } ! 1652: } ! 1653: } ! 1654: ! 1655: STATIC ! 1656: print_bdy(p, len, type) ! 1657: unsigned char *p; ! 1658: { ! 1659: int j, k; ! 1660: ! 1661: if (len < 18) ! 1662: printf("print_pkt: too small %d|n", len); ! 1663: ! 1664: switch (type) { ! 1665: case 0x806: ! 1666: print_arp(p); ! 1667: break; ! 1668: case 0x800: ! 1669: print_ip(p, len); ! 1670: break; ! 1671: default: ! 1672: for (j = 0; j < len; j +=20) { ! 1673: for (k = 0; k < 20; k++) ! 1674: printf("%2x ", p[j+k]); ! 1675: printf("\n"); ! 1676: } ! 1677: } ! 1678: } ! 1679: ! 1680: STATIC ! 1681: print_e_hdr(p) ! 1682: unsigned char *p; ! 1683: { ! 1684: int type = ntohs(((unsigned short *)p)[6]); ! 1685: ! 1686: printf("S=%x:%x:%x:%x:%x:%x, ", p[6], p[7], p[8], p[9], p[10], p[11]); ! 1687: printf("D=%x:%x:%x:%x:%x:%x, ", p[0], p[1], p[2], p[3], p[4], p[5]); ! 1688: printf("T=%x\n", type); ! 1689: ! 1690: return type; ! 1691: } ! 1692: ! 1693: STATIC ! 1694: print_ip_hdr(u) ! 1695: u_char *u; ! 1696: { ! 1697: ! 1698: int l = ntohs(*(u_short *)(u+2)); ! 1699: ! 1700: print_ipa(u+12); ! 1701: printf(" -> "); ! 1702: print_ipa(u+12+4); ! 1703: printf(" L%d(0x%x)\n", l, l); ! 1704: } ! 1705: ! 1706: STATIC ! 1707: print_ip(p, len) ! 1708: unsigned char *p; ! 1709: { ! 1710: int j,k; ! 1711: ! 1712: print_ip_hdr(p); ! 1713: for (k =0; k < 12; k++) ! 1714: printf("%2x ", p[k]); ! 1715: print_ipa(p+12); ! 1716: printf(" "); ! 1717: print_ipa(p+12+4); ! 1718: printf("\n"); ! 1719: for (j = 20; j < len; j +=16) { ! 1720: for (k = 0; k < 16; k++) ! 1721: printf("%2x ", p[j+k]); ! 1722: print_chars(&p[j], 16); ! 1723: printf("\n"); ! 1724: } ! 1725: } ! 1726: ! 1727: STATIC ! 1728: print_ipa(u) ! 1729: u_char *u; ! 1730: { ! 1731: printf("%d.%d.%d.%d", u[0], u[1], u[2], u[3]); ! 1732: } ! 1733: ! 1734: STATIC ! 1735: print_arp(p) ! 1736: #ifdef MACH_KERNEL ! 1737: {} ! 1738: #else MACH_KERNEL ! 1739: struct arphdr *p; ! 1740: { ! 1741: u_char *u = (u_char *)(p+1); ! 1742: ! 1743: printf("op = %x, pro = %x, hln = %x, pln = %x\n", ! 1744: ntohs(p->ar_op), ntohs(p->ar_pro), p->ar_hln, p->ar_pln); ! 1745: ! 1746: print_e(u); ! 1747: print_ipa(u+p->ar_hln); ! 1748: printf(" seeks\n"); ! 1749: ! 1750: print_e(u+p->ar_hln+p->ar_pln); ! 1751: print_ipa(u+p->ar_hln+p->ar_pln+p->ar_hln); ! 1752: printf("\n"); ! 1753: ! 1754: } ! 1755: #endif MACH_KERNEL ! 1756: ! 1757: STATIC ! 1758: print_e(u) ! 1759: u_char *u; ! 1760: { ! 1761: printf("%x:%x:%x:%x:%x:%x ", u[0], u[1], u[2], u[3], u[4], u[5]); ! 1762: } ! 1763: ! 1764: STATIC ! 1765: print_chars(u, len) ! 1766: u_char *u; ! 1767: { ! 1768: int c; ! 1769: ! 1770: printf("|>"); ! 1771: while (len--) { ! 1772: c = *u++; ! 1773: if (c < 0x7f && c > 0x1f) ! 1774: printf("%c", c); ! 1775: else ! 1776: printf(" "); ! 1777: } ! 1778: printf("<|"); ! 1779: } ! 1780: #endif DEBUG
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.