|
|
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.