|
|
1.1 root 1: /*-
2: * Copyright (c) 1990, 1991 William F. Jolitz.
3: * Copyright (c) 1990 The Regents of the University of California.
4: * All rights reserved.
5: *
6: * Redistribution and use in source and binary forms, with or without
7: * modification, are permitted provided that the following conditions
8: * are met:
9: * 1. Redistributions of source code must retain the above copyright
10: * notice, this list of conditions and the following disclaimer.
11: * 2. Redistributions in binary form must reproduce the above copyright
12: * notice, this list of conditions and the following disclaimer in the
13: * documentation and/or other materials provided with the distribution.
14: * 3. All advertising materials mentioning features or use of this software
15: * must display the following acknowledgement:
16: * This product includes software developed by the University of
17: * California, Berkeley and its contributors.
18: * 4. Neither the name of the University nor the names of its contributors
19: * may be used to endorse or promote products derived from this software
20: * without specific prior written permission.
21: *
22: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32: * SUCH DAMAGE.
33: *
34: * @(#)if_ne.c 7.4 (Berkeley) 5/21/91
35: */
36:
37: /*
38: * NE2000 Ethernet driver
39: *
40: * Parts inspired from Tim Tucker's if_wd driver for the wd8003,
41: * insight on the ne2000 gained from Robert Clements PC/FTP driver.
42: */
43:
44: #include <ne.h>
45:
46:
47: #if NNE > 0
48: #ifdef MACH_KERNEL
49:
50: #include <kern/time_out.h>
51: #include <device/device_types.h>
52: #include <device/errno.h>
53: #include <device/io_req.h>
54: #include <device/if_hdr.h>
55: #include <device/if_ether.h>
56: #include <device/net_status.h>
57: #include <device/net_io.h>
58: #include <i386at/ds8390.h>
59: #include <i386at/if_nereg.h>
60: #include <i386/ipl.h>
61: #include <chips/busses.h>
62: #ifdef FIPC
63: #include <ipc/fipc.h>
64: #endif /* FIPC */
65:
66: #else MACH_KERNEL
67:
68: #include <sys/param.h>
69: #include <mach/vm_param.h>
70: #include <sys/systm.h>
71: #include <sys/mbuf.h>
72: #include <sys/table.h>
73: #include <sys/buf.h>
74: #include <sys/protosw.h>
75: #include <sys/socket.h>
76: #include <sys/vmmac.h>
77: #include <sys/ioctl.h>
78: #include <sys/errno.h>
79: #include <sys/syslog.h>
80: #include <vm/vm_kern.h>
81:
82: #include <net/if.h>
83: #include <net/if_types.h>
84: #include <net/route.h>
85:
86: #include <netinet/in.h>
87: #include <netinet/in_systm.h>
88: #include <netinet/in_var.h>
89: #include <netinet/ip.h>
90: #include <netinet/if_ether.h>
91:
92: #include <netns/ns.h>
93: #include <netns/ns_if.h>
94:
95:
96: #include <i386/ipl.h>
97: #include <i386at/atbus.h>
98: #include <i386at/ds8390.h>
99: #include <i386at/if_nereg.h>
100: #include <i386/handler.h>
101: #include <i386/dispatcher.h>
102: int ether_output();
103: int neioctl();
104:
105: #endif
106:
107:
108: int neprobe();
109: void neattach();
110: int neintr();
111: int nestart();
112: int neinit();
113:
114: static vm_offset_t ne_std[NNE] = {0};
115: static struct bus_device *ne_info[NNE];
116: struct bus_driver nedriver =
117: { neprobe, 0, neattach, 0, ne_std, "ne", ne_info, 0, 0, 0 };
118:
119: #define ETHER_MIN_LEN 64
120: #define ETHER_MAX_LEN 1536
121: #define SPLNET spl6
122: /*
123: * Ethernet software status per interface.
124: *
125: * Each interface is referenced by a network interface structure,
126: * ns_if, which the routing code uses to locate the interface.
127: * This structure contains the output queue for the interface, its address, ...
128: */
129: typedef struct {
130:
131: #ifdef MACH_KERNEL
132: struct ifnet ds_if;
133: u_char ds_addr[6];
134: #else MACH_KERNEL
135: struct arpcom ns_ac; /* Ethernet common part */
136: #define ds_if ns_ac.ac_if /* network-visible interface */
137: #define ds_addr ns_ac.ac_enaddr /* hardware Ethernet address */
138: #endif MACH_KERNEL
139:
140: int ns_flags;
141: #define DSF_LOCK 1 /* block re-entering enstart */
142: #define DSF_RUNNING 2
143: int ns_oactive ;
144: int ns_mask ;
145: int ns_ba; /* byte addr in buffer ram of inc pkt */
146: int ns_cur; /* current page being filled */
147: struct prhdr ns_ph; /* hardware header of incoming packet*/
148: struct ether_header ns_eh; /* header of incoming packet */
149: u_char ns_pb[2048 /*ETHERMTU+sizeof(long)*/];
150: short ns_txstart; /* transmitter buffer start */
151: short ns_rxend; /* recevier buffer end */
152: short ns_rxbndry; /* recevier buffer boundary */
153: caddr_t ns_port; /* i/o port base */
154: short ns_mode; /* word/byte mode */
155: int mode;
156: short card_present;
157: #ifndef MACH_KERNEL
158: ihandler_t handler;
159: ihandler_id_t *handler_id;
160: #endif MACH_KERNEL
161:
162: } ne_softc_t;
163: ne_softc_t ne_softc[NNE];
164:
165: #define PAT(n) (0xa55a + 37*(n))
166:
167: u_short boarddata[16];
168:
169: /*
170: * Fetch from onboard ROM/RAM
171: */
172: nefetch (ns, up, ad, len) ne_softc_t *ns; caddr_t up; {
173: u_char cmd;
174: caddr_t nec = ns->ns_port;
175: int counter = 10000;
176: int t_len;
177: unsigned char last_word[2];
178: char odd;
179:
180: cmd = inb (nec + ds_cmd);
181: outb (nec + ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START);
182:
183: /* Setup remote dma */
184: outb (nec + ds0_isr, DSIS_RDC);
185:
186: t_len = len;
187: if ((ns->ns_mode & DSDC_WTS) && len&1) {
188: odd=1;
189: t_len++; /* roundup to words */
190: } else odd=0;
191:
192: outb (nec+ds0_rbcr0, t_len);
193: outb (nec+ds0_rbcr1, t_len>>8);
194: outb (nec+ds0_rsar0, ad);
195: outb (nec+ds0_rsar1, ad>>8);
196:
197: /* Execute & extract from card */
198: outb (nec+ds_cmd, DSCM_RREAD|DSCM_PG0|DSCM_START);
199:
200: if (ns->ns_mode & DSDC_WTS)
201: if (odd) {
202: linw (nec+ne_data, up, len/2);
203: *(last_word) = inw(nec+ne_data); /* get last word */
204: *(up+len-1) = last_word[0]; /* last byte */
205: } else {
206: linw (nec+ne_data, up, len/2);
207: }
208: else
209: linb (nec+ne_data, up, len);
210:
211:
212: /* Wait till done, then shutdown feature */
213: while ((inb (nec+ds0_isr) & DSIS_RDC) == 0 && counter-- > 0)
214: ;
215:
216: outb (nec+ds0_isr, DSIS_RDC);
217: outb (nec+ds_cmd, cmd);
218: }
219:
220: /*
221: * Put to onboard RAM
222: */
223: neput (ns, up, ad, len) ne_softc_t *ns; caddr_t up; {
224: u_char cmd;
225: caddr_t nec = ns->ns_port;
226: int counter = 10000;
227: int t_len;
228: int odd;
229: unsigned char last_word[2];
230:
231: cmd = inb(nec+ds_cmd);
232: outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START);
233:
234: /* Setup for remote dma */
235: outb (nec+ds0_isr, DSIS_RDC);
236:
237: t_len = len;
238: if ((ns->ns_mode & DSDC_WTS) && len&1) {
239: odd = 1;
240: t_len++; /* roundup to words */
241: } else odd = 0;
242:
243: outb (nec+ds0_rbcr0, t_len);
244: outb (nec+ds0_rbcr1, t_len>>8);
245: outb (nec+ds0_rsar0, ad);
246: outb (nec+ds0_rsar1, ad>>8);
247:
248: /* Execute & stuff to card */
249: outb (nec+ds_cmd, DSCM_RWRITE|DSCM_PG0|DSCM_START);
250: if (ns->ns_mode & DSDC_WTS) {
251: if (odd) {
252: loutw (nec+ne_data, up, len/2);
253: last_word[0] = *(up+len-1);
254: outw (nec+ne_data, (unsigned short) *(last_word));
255: }
256: else {
257: loutw (nec+ne_data, up, len/2);
258: }
259: }
260: else
261: loutb (nec+ne_data, up, len);
262:
263:
264: /* Wait till done, then shutdown feature */
265: while ((inb (nec+ds0_isr) & DSIS_RDC) == 0 && counter-- > 0)
266: ;
267:
268: outb (nec+ds0_isr, DSIS_RDC);
269: outb (nec+ds_cmd, cmd);
270: }
271:
272: int
273: neprobe(port, dev)
274: struct bus_device *dev;
275: {
276: int val, i, sum, bytemode = 1, pat;
277: int unit = dev->unit;
278: ne_softc_t *ns = &ne_softc[unit];
279: caddr_t nec;
280:
281: if ((unsigned) unit >= NNE)
282: return(0);
283:
284: nec = (caddr_t) ns->ns_port = dev->address;
285:
286: if (ns->card_present) {
287: printf("ne%s : card already present in port %x\n",
288: unit, nec);
289: return(0);
290: }
291:
292: if (bytemode) {
293: /* Byte Transfers, Burst Mode Select, Fifo at 8 bytes */
294: ns->ns_mode = DSDC_BMS|DSDC_FT1;
295: ns->ns_txstart = TBUF8;
296: ns->ns_rxend = RBUFEND8;
297: } else {
298: word:
299: /* Word Transfers, Burst Mode Select, Fifo at 8 bytes */
300: ns->ns_mode = DSDC_WTS|DSDC_BMS|DSDC_FT1;
301: ns->ns_txstart = TBUF16;
302: ns->ns_rxend = RBUFEND16;
303: bytemode = 0;
304: }
305:
306: /* Reset the bastard */
307: val = inb(nec + ne_reset);
308: delay(200);
309: outb(nec + ne_reset, val);
310: delay(200);
311:
312: outb(nec + ds_cmd, DSCM_STOP|DSCM_NODMA);
313:
314: i = 10000;
315: while ((inb(nec + ds0_isr) & DSIS_RESET) == 0 && i-- > 0);
316: if (i < 0) return (0);
317:
318: outb(nec + ds0_isr, 0xff);
319: outb(nec + ds0_dcr, ns->ns_mode);
320: outb(nec + ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP);
321: delay(1000);
322:
323: /* Check cmd reg and fail if not right */
324: if ((i = inb(nec + ds_cmd)) != (DSCM_NODMA|DSCM_PG0|DSCM_STOP))
325: return(0);
326:
327: outb(nec + ds0_tcr, DSTC_LB0);
328: outb(nec + ds0_rcr, DSRC_MON);
329: outb(nec + ds0_pstart, ns->ns_txstart+PKTSZ);
330: outb(nec + ds0_pstop, ns->ns_rxend);
331: outb(nec + ds0_bnry, ns->ns_rxend);
332: outb(nec + ds0_imr, 0);
333: outb(nec + ds0_isr, 0);
334: outb(nec + ds_cmd, DSCM_NODMA|DSCM_PG1|DSCM_STOP);
335: outb(nec + ds1_curr, ns->ns_txstart+PKTSZ);
336: outb(nec + ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP);
337:
338: #ifdef NEDEBUG
339: #define RCON 37
340: { int i, rom;
341:
342: rom=1;
343: printf("ne ram ");
344:
345: for (i = 0; i < 0xfff0; i+=4) {
346: pat = PAT(i);
347: neput(ns, &pat,i,4);
348: nefetch(ns, &pat,i,4);
349: if (pat == PAT(i)) {
350: if (rom) {
351: rom=0;
352: printf(" %x", i);
353: }
354: } else {
355: if (!rom) {
356: rom=1;
357: printf("..%x ", i);
358: }
359: }
360: pat=0;
361: neput(ns, &pat,i,4);
362: }
363: printf("\n");
364: }
365: #endif
366:
367: /*
368: * <groan> detect difference between units
369: * solely by where the RAM is decoded.
370: */
371: pat = PAT(0);
372: neput (ns, &pat, ns->ns_txstart*DS_PGSIZE, 4);
373: nefetch(ns, &pat, ns->ns_txstart*DS_PGSIZE, 4);
374: if (pat != PAT(0)) {
375: if (bytemode)
376: goto word;
377: else return (0);
378: }
379:
380:
381: /* Extract board address */
382: nefetch (ns, (caddr_t)boarddata, 0, sizeof(boarddata));
383:
384: for(i=0; i < 6; i++)
385: ns->ds_addr[i] = boarddata[i];
386: ns->card_present = 1;
387: return (1);
388: }
389:
390: /*
391: * Interface exists: make available by filling in network interface
392: * record. System will initialize the interface when it is ready
393: * to accept packets. We get the ethernet address here.
394: */
395: void
396: neattach(dev)
397: struct bus_device *dev;
398: {
399: short unit = dev->unit;
400: ne_softc_t *ns = &ne_softc[unit];
401: register struct ifnet *ifp = &(ns->ds_if);
402:
403: if ((unsigned) unit >= NNE)
404: return;
405:
406: #ifdef MACH_KERNEL
407: take_dev_irq(dev);
408: #else MACH_KERNEL
409: /* setup intr handler */
410: ns->handler.ih_level = dev->dev_pic;
411: ns->handler.ih_handler = dev->dev_intr[0];
412: ns->handler.ih_resolver = i386_resolver;
413: ns->handler.ih_rdev = dev;
414: ns->handler.ih_stats.intr_type = INTR_DEVICE;
415: ns->handler.ih_stats.intr_cnt = 0;
416: ns->handler.ih_hparam[0].intparam = unit;
417: if ((ns->handler_id = handler_add(&ns->handler)) != NULL)
418: handler_enable(ns->handler_id);
419: else
420: panic("Unable to add NEx000 interrupt handler");
421: #endif MACH_KERNEL
422: printf (", port = %x, spl = %d, pic = %d, [%s].",
423: dev->address, dev->sysdep, dev->sysdep1,
424: ether_sprintf(ns->ds_addr));
425: #ifndef MACH_KERNEL
426: ns->ns_ac.ac_bcastaddr = (u_char *)etherbroadcastaddr;
427: ns->ns_ac.ac_arphrd = ARPHRD_ETHER;
428: #endif MACH_KERNEL
429: ns->ns_flags = 0;
430: ns->mode = 0;
431: ifp->if_unit = unit;
432: ifp->if_mtu = ETHERMTU;
433: ifp->if_flags = IFF_BROADCAST;
434: #ifdef MACH_KERNEL
435: ifp->if_header_size = sizeof(struct ether_header);
436: ifp->if_header_format = HDR_ETHERNET;
437: ifp->if_address_size = 6;
438: ifp->if_address = (char *)&ns->ds_addr[0];
439: if_init_queues(ifp);
440: #else MACH_KERNEL
441: ifp->if_name = nedriver.driver_dname;
442: ifp->if_init = neinit;
443: ifp->if_output = ether_output;
444: ifp->if_start = nestart;
445: ifp->if_ioctl = neioctl;
446: ifp->if_reset = nereset;
447: ifp->if_watchdog= 0;
448: if_attach(ifp);
449: #endif MACH_KERNEL
450: }
451:
452: /*
453: * Initialization of interface; set up initialization block
454: * and transmit/receive descriptor rings.
455: */
456: neinit(unit)
457: int unit;
458: {
459: ne_softc_t *ns = &ne_softc[unit];
460: struct ifnet *ifp = &ns->ds_if;
461: int i; char *cp;
462: int oldpri;
463: caddr_t nec = ns->ns_port;
464:
465: #ifndef MACH_KERNEL
466: if (ifp->if_addrlist == (struct ifaddr *)0) return;
467: #endif MACH_KERNEL
468:
469: oldpri = SPLNET();
470:
471: outb(nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP);
472:
473: /* Word Transfer select, Burst Mode Select, Fifo at 8 bytes */
474: outb(nec+ds0_dcr, ns->ns_mode);
475:
476: /* clear remote byte count resigters */
477: outb (nec+ds0_rbcr0, 0);
478: outb (nec+ds0_rbcr1, 0);
479:
480: /* don't store incoming packets into memory for now */
481: outb (nec+ds0_rcr, DSRC_MON);
482:
483: /* place NIC in internal loopback mode */
484: outb(nec+ds0_tcr, DSTC_LB0);
485:
486: /* initialize transmit/recieve (ring-buffer) Page Start */
487: outb (nec+ds0_tpsr, 0);
488: outb (nec+ds0_pstart, ns->ns_txstart+PKTSZ);
489:
490: /* initialize reciever (ring-buffer) Page Stop and Boundary */
491: outb (nec+ds0_pstop, ns->ns_rxend);
492: outb (nec+ds0_bnry, ns->ns_txstart+PKTSZ);
493:
494: /* clear all interrupts */
495: outb (nec+ds0_isr, 0xff);
496:
497: /* enable the interrupts that we care about */
498: outb (nec+ds0_imr, IMR_ENABLE);
499:
500: /* set physical address on ethernet */
501: outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG1|DSCM_STOP);
502: for (i=0 ; i < 6 ; i++) outb(nec+ds1_par0+i,ns->ds_addr[i]);
503:
504: ns->ns_cur = ns->ns_txstart+PKTSZ + 1;
505: outb (nec+ds1_curr, ns->ns_cur);
506:
507: /* XXX deal with Reciever Configuration Register */
508: /* clr logical address hash filter for now */
509: for (i=0 ; i < 8 ; i++) outb(nec+ds1_mar0+i,0xff);
510:
511: /* set page 0 registers */
512: outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP);
513: outb (nec+ds0_rcr, DSRC_AB);
514:
515: /* take unit out of loopback mode */
516: outb (nec+ds0_tcr, 0);
517:
518: ns->ds_if.if_flags |= IFF_RUNNING;
519: ns->ns_flags &= ~(DSF_LOCK|DSF_RUNNING);
520: ns->ns_oactive = 0; ns->ns_mask = ~0;
521: splx(oldpri);
522: nestart(unit);
523: return(1);
524: }
525:
526: /*
527: * Setup output on interface.
528: * Get another datagram to send off of the interface queue,
529: * and map it to the interface before starting the output.
530: * called only at splimp or interrupt level.
531: */
532: nestart(unit)
533: int unit;
534: {
535: ne_softc_t *ns = &ne_softc[unit];
536: struct ifnet *ifp = &ns->ds_if;
537: int buffer;
538: int len, i, total,t;
539: caddr_t nec = ns->ns_port;
540: #ifdef MACH_KERNEL
541: io_req_t m;
542:
543: #else MACH_KERNEL
544: struct mbuf *m0, *m;
545: #endif MACH_KERNEL
546:
547: /*
548: * The DS8390 has only one transmit buffer, if it is busy we
549: * must wait until the transmit interrupt completes.
550: */
551: outb(nec+ds_cmd,DSCM_NODMA|DSCM_START);
552:
553: if (ns->ns_flags & DSF_LOCK)
554: goto done;
555:
556: if (inb(nec+ds_cmd) & DSCM_TRANS)
557: goto done;
558:
559: if ((ns->ds_if.if_flags & IFF_RUNNING) == 0)
560: goto done;
561:
562: IF_DEQUEUE(&ns->ds_if.if_snd, m);
563: if (m == 0)
564: goto done;
565:
566: /*
567: * Copy the mbuf chain into the transmit buffer
568: */
569:
570: ns->ns_flags |= DSF_LOCK; /* prevent entering nestart */
571: buffer = ns->ns_txstart*DS_PGSIZE;
572: #ifdef MACH_KERNEL
573: total = m->io_count;
574: neput(ns, m->io_data, buffer, total);
575: #else MACH_KERNEL
576: t = 0; len = i = 0;
577: for (m0 = m; m != 0; m = m->m_next)
578: t += m->m_len;
579:
580: m = m0;
581: total = t;
582: for (m0 = m; m != 0; ) {
583:
584: if (m->m_len&1 && t > m->m_len) {
585: neput(ns, mtod(m, caddr_t), buffer, m->m_len - 1);
586: t -= m->m_len - 1;
587: buffer += m->m_len - 1;
588: m->m_data += m->m_len - 1;
589: m->m_len = 1;
590: m = m_pullup(m, 2);
591: } else {
592: neput(ns, mtod(m, caddr_t), buffer, m->m_len);
593: buffer += m->m_len;
594: t -= m->m_len;
595: MFREE(m, m0);
596: m = m0;
597: }
598: }
599: #endif MACH_KERNEL
600: /*
601: * Init transmit length registers, and set transmit start flag.
602: */
603:
604: len = total;
605: if (len < ETHER_MIN_LEN) len = ETHER_MIN_LEN;
606: outb(nec+ds0_tbcr0,len&0xff);
607: outb(nec+ds0_tbcr1,(len>>8)&0xff);
608: outb(nec+ds0_tpsr, ns->ns_txstart);
609: outb(nec+ds_cmd, DSCM_TRANS|DSCM_NODMA|DSCM_START);
610:
611: #ifdef MACH_KERNEL
612: iodone(m);
613: m = 0;
614: done:
615: #endif MACH_KERNEL
616: }
617:
618: /* buffer successor/predecessor in ring? */
619: #define succ(n) (((n)+1 >= ns->ns_rxend) ? (ns->ns_txstart+PKTSZ) : (n)+1)
620: #define pred(n) (((n)-1 < (ns->ns_txstart+PKTSZ)) ? ns->ns_rxend-1 : (n)-1)
621:
622: /*
623: * Controller interrupt.
624: */
625: neintr(unit)
626: {
627: ne_softc_t *ns = &ne_softc[unit];
628: u_char cmd,isr;
629: caddr_t nec = ns->ns_port;
630:
631: /* Save cmd, clear interrupt */
632: cmd = inb (nec+ds_cmd);
633: isr = inb (nec+ds0_isr);
634: loop:
635: outb(nec+ds_cmd,DSCM_NODMA|DSCM_START);
636: outb(nec+ds0_isr, isr);
637:
638: /* Receiver error */
639: if (isr & DSIS_RXE) {
640: (void) inb(nec+ds0_rsr);
641: /* need to read these registers to clear status */
642: ns->ds_if.if_ierrors++;
643: }
644:
645: /* Counters overflowed, reading the registers resets them */
646: if (isr & DSIS_CTRS) {
647: (void) inb(nec+ds0_cntr0);
648: (void) inb(nec+ds0_cntr1);
649: (void) inb(nec+ds0_cntr2);
650: }
651:
652:
653: /* We received something; rummage thru tiny ring buffer */
654: if (isr & (DSIS_RX|DSIS_RXE|DSIS_ROVRN)) {
655: u_char pend,lastfree;
656:
657: outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG1);
658: pend = inb(nec+ds1_curr);
659: outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG0);
660:
661: /* Something in the buffer? */
662: while (pend != ns->ns_cur) {
663: /* Extract header from microcephalic board */
664: nefetch(ns, &ns->ns_ph,ns->ns_cur*DS_PGSIZE,
665: sizeof(ns->ns_ph));
666: ns->ns_ba = ns->ns_cur*DS_PGSIZE+sizeof(ns->ns_ph);
667:
668: /* Incipient paranoia */
669: if (ns->ns_ph.pr_status == DSRS_RPC ||
670: /* for dequna's */
671: ns->ns_ph.pr_status == 0x21) {
672: if (nerecv(ns))
673: ns->ns_cur = ns->ns_ph.pr_nxtpg ;
674: else {
675: outb(nec+ds0_bnry, pred(ns->ns_cur));
676: goto short_load;
677: }
678: }
679: #ifdef NEDEBUG
680: else {
681: printf("cur %x pnd %x lfr %x ",
682: ns->ns_cur, pend, lastfree);
683: printf("nxt %x len %x ", ns->ns_ph.pr_nxtpg,
684: (ns->ns_ph.pr_sz1<<8)+ ns->ns_ph.pr_sz0);
685: printf("Bogus Sts %x\n", ns->ns_ph.pr_status);
686: ns->ns_cur = pend;
687: }
688: #endif
689: outb(nec+ds0_bnry, pred(ns->ns_cur));
690: outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG1);
691: pend = inb(nec+ds1_curr);
692: outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG0);
693: }
694: short_load:
695: outb(nec+ds_cmd, DSCM_START|DSCM_NODMA);
696: }
697:
698: /* Transmit error */
699: if (isr & DSIS_TXE) {
700: ns->ns_flags &= ~DSF_LOCK;
701: /* Need to read these registers to clear status */
702: ns->ds_if.if_collisions += inb(nec+ds0_tbcr0);
703: ns->ds_if.if_oerrors++;
704: }
705:
706: /* Packet Transmitted */
707: if (isr & DSIS_TX) {
708: ns->ns_flags &= ~DSF_LOCK;
709: ++ns->ds_if.if_opackets;
710: ns->ds_if.if_collisions += inb(nec+ds0_tbcr0);
711: }
712:
713: /* Receiver ovverun? */
714: if (isr & DSIS_ROVRN) {
715: outb(nec+ds0_rbcr0, 0);
716: outb(nec+ds0_rbcr1, 0);
717: outb(nec+ds0_tcr, DSTC_LB0);
718: outb(nec+ds0_rcr, DSRC_MON);
719: outb(nec+ds_cmd, DSCM_START|DSCM_NODMA);
720: outb(nec+ds0_rcr, DSRC_AB);
721: outb(nec+ds0_tcr, 0);
722: }
723:
724: /* Any more to send? */
725: outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START);
726: nestart(unit);
727: outb (nec+ds_cmd, cmd);
728: outb (nec+ds0_imr, IMR_ENABLE);
729:
730: /* Still more to do? */
731: isr = inb (nec+ds0_isr);
732: if(isr) goto loop;
733:
734: return 0;
735: }
736:
737: /*
738: * Ethernet interface receiver interface.
739: * If input error just drop packet.
740: * Otherwise examine packet to determine type. If can't determine length
741: * from type, then have to drop packet. Othewise decapsulate
742: * packet based on type and pass to type specific higher-level
743: * input routine.
744: */
745: nerecv(ns)
746: ne_softc_t *ns;
747: {
748: #ifdef MACH_KERNEL
749: ipc_kmsg_t new_kmsg;
750: struct ether_header *ehp;
751: struct packet_header *pkt;
752: register struct ifnet *ifp = &ns->ds_if;
753: #ifdef FIPC
754: char *fipc_buf;
755: #endif
756: #else MACH_KERNEL
757: struct mbuf *top, **mp, *m, *p;
758: #endif MACH_KERNEL
759: int len, l;
760: int epkt;
761:
762: ns->ds_if.if_ipackets++;
763: len = ns->ns_ph.pr_sz0 + (ns->ns_ph.pr_sz1<<8);
764: if(len < ETHER_MIN_LEN || len > ETHER_MAX_LEN)
765: return 0;
766:
767: nefetch(ns, &ns->ns_eh, ns->ns_ba, sizeof(struct ether_header));
768:
769: #ifndef MACH_KERNEL
770: ns->ns_eh.ether_type = ntohs((u_short)ns->ns_eh.ether_type);
771: #endif MACH_KERNEL
772: ns->ns_ba += sizeof(struct ether_header);
773:
774: /* don't forget checksum! */
775: len -= (sizeof(struct ether_header) + sizeof(long));
776: #ifdef MACH_KERNEL
777: #ifdef FIPC
778: if (ns->ns_eh.ether_type == FIPC_MSG_TYPE) /* fipc packet */
779: {
780: /* We need to hand the whole packet to the handler. */
781:
782: fipc_recvs++;
783:
784: fipc_buf = get_fipc_buffer (len, TRUE, TRUE);
785:
786: if (fipc_buf == NULL)
787: {
788: ns->ds_if.if_rcvdrops++;
789: return(0);
790: }
791: nefetch (ns, fipc_buf, ns->ns_ba, len);
792:
793: fipc_packet (fipc_buf, ns->ns_eh);
794: }
795: else /* net_kmsg */
796: {
797: #endif /* FIPC */
798: new_kmsg = net_kmsg_get();
799:
800: if (new_kmsg == IKM_NULL) {
801: ns->ds_if.if_rcvdrops++;
802: return(0);
803: }
804:
805: ehp = (struct ether_header *) (&net_kmsg(new_kmsg)->header[0]);
806: pkt = (struct packet_header *)(&net_kmsg(new_kmsg)->packet[0]);
807: *ehp = ns->ns_eh;
808:
809: nefetch(ns, (char *) (pkt + 1), ns->ns_ba, len);
810:
811: pkt->type = ehp->ether_type;
812:
813: pkt->length = len + sizeof(struct packet_header);
814: net_packet(ifp, new_kmsg, pkt->length, ethernet_priority(new_kmsg));
815: #ifdef FIPC
816: }
817: #endif
818:
819: #else MACH_KERNEL
820: /**/
821: epkt = ns->ns_ba + len;
822:
823: MGETHDR(m, M_DONTWAIT, MT_DATA);
824: if (m == 0)
825: return (0);
826:
827: m->m_pkthdr.rcvif = &ns->ds_if;
828: m->m_pkthdr.len = len;
829: m->m_len = MHLEN;
830:
831: top = 0;
832: mp = ⊤
833: while (len > 0) {
834: if (top) {
835: MGET(m, M_DONTWAIT, MT_DATA);
836: if (m == 0) {
837: m_freem(top);
838: return (0);
839: }
840: m->m_len = MLEN;
841: }
842: l = min(len, epkt - ns->ns_ba);
843: if (l >= MINCLSIZE) {
844: MCLGET(m, M_DONTWAIT);
845: if (m->m_flags & M_EXT)
846: m->m_len = l = min(len, MCLBYTES);
847: else
848: l = m->m_len;
849: } else {
850: /*
851: * Place initial small packet/header at end of mbuf.
852: */
853: if (l < m->m_len) {
854: if (top == 0 && len + max_linkhdr <= m->m_len)
855: m->m_data += max_linkhdr;
856: m->m_len = l;
857: } else
858: l = m->m_len;
859: }
860: nefetch(ns, mtod(m, caddr_t), ns->ns_ba, l);
861: ns->ns_ba += l;
862: *mp = m;
863: mp = &m->m_next;
864: len -= l;
865: }
866: /**/
867: if (top == 0) return 0; /* NEED MODIFY HERE !!! */
868:
869: ether_input(&ns->ds_if, &ns->ns_eh, top);
870: #endif MACH_KERNEL
871: return 1;
872: }
873:
874: #ifdef MACH_KERNEL
875: neopen(dev, flag)
876: dev_t dev;
877: int flag;
878: {
879: register int unit = minor(dev);
880:
881: if (!ne_softc[unit].card_present || unit < 0 || unit >= NNE)
882: return (ENXIO);
883:
884: ne_softc[unit].ds_if.if_flags |= IFF_UP;
885: neinit(unit);
886: return(0);
887: }
888:
889: #ifdef FIPC
890: nefoutput(dev, ior)
891: dev_t dev;
892: io_req_t ior;
893: {
894: register int unit = minor(dev);
895:
896: if (!ne_softc[unit].card_present || unit < 0 || unit >= NNE)
897: return (ENXIO);
898:
899: return (net_fwrite(&ne_softc[unit].ds_if, nestart, ior));
900: }
901: #endif
902:
903: neoutput(dev, ior)
904: dev_t dev;
905: io_req_t ior;
906: {
907: register int unit = minor(dev);
908:
909: if (!ne_softc[unit].card_present || unit < 0 || unit >= NNE)
910: return (ENXIO);
911:
912: return (net_write(&ne_softc[unit].ds_if, nestart, ior));
913: }
914:
915: nesetinput(dev, receive_port, priority, filter, filter_count)
916: dev_t dev;
917: mach_port_t receive_port;
918: int priority;
919: filter_t filter[];
920: unsigned int filter_count;
921: {
922: register int unit = minor(dev);
923:
924: if (!ne_softc[unit].card_present || unit < 0 || unit >= NNE)
925: return (ENXIO);
926:
927: return (net_set_filter(&ne_softc[unit].ds_if,
928: receive_port, priority,
929: filter, filter_count));
930: }
931:
932: negetstat(dev, flavor, status, count)
933: dev_t dev;
934: int flavor;
935: dev_status_t status;
936: unsigned int *count;
937: {
938: register int unit = minor(dev);
939:
940: if (!ne_softc[unit].card_present || unit < 0 || unit >= NNE)
941: return (ENXIO);
942:
943: return (net_getstat(&ne_softc[unit].ds_if,
944: flavor,
945: status,
946: count));
947: }
948:
949: nesetstat(dev, flavor, status, count)
950: dev_t dev;
951: int flavor;
952: dev_status_t status;
953: unsigned int count;
954: {
955: register int unit = minor(dev);
956: register ne_softc_t *ns;
957:
958: if (!ne_softc[unit].card_present || unit < 0 || unit >= NNE)
959: return (ENXIO);
960:
961: ns = &ne_softc[unit];
962:
963: switch(flavor) {
964: case NET_STATUS: {
965: register struct net_status *s = (struct net_status *)status;
966: int mode = 0;
967: if (count < NET_STATUS_COUNT)
968: return(D_INVALID_SIZE);
969: #define MOD_ENAL 1
970: #define MOD_PROM 2
971: if (s->flags & IFF_ALLMULTI)
972: mode |= MOD_ENAL;
973: if (s->flags & IFF_PROMISC)
974: mode |= MOD_PROM;
975:
976: if (ns->mode != mode) {
977: ns->mode = mode;
978: if (ns->ns_flags & DSF_RUNNING) {
979: ns->ns_flags &= ~(DSF_LOCK | DSF_RUNNING);
980: neinit(unit);
981: }
982: }
983: break;
984: }
985: default :
986: return (D_INVALID_OPERATION);
987: }
988: return (D_SUCCESS);
989: }
990:
991: #else MACH_KERNEL
992:
993: /*
994: * Process an ioctl request.
995: */
996: neioctl(ifp, cmd, data)
997: register struct ifnet *ifp;
998: int cmd;
999: caddr_t data;
1000: {
1001: register struct ifaddr *ifa = (struct ifaddr *)data;
1002: ne_softc_t *ns = &ne_softc[ifp->if_unit];
1003: struct ifreq *ifr = (struct ifreq *)data;
1004: int s = splimp(), error = 0;
1005:
1006:
1007: switch (cmd) {
1008:
1009: case SIOCSIFADDR:
1010: ifp->if_flags |= IFF_UP;
1011:
1012: switch (ifa->ifa_addr->sa_family) {
1013: case AF_INET:
1014: neinit(ifp->if_unit); /* before arpwhohas */
1015: ((struct arpcom *)ifp)->ac_ipaddr =
1016: IA_SIN(ifa)->sin_addr;
1017: arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
1018: break;
1019: case AF_NS:
1020: {
1021: register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
1022:
1023: if (ns_nullhost(*ina))
1024: ina->x_host = *(union ns_host *)(ns->ds_addr);
1025: else {
1026: /*
1027: * The manual says we can't change the address
1028: * while the receiver is armed,
1029: * so reset everything
1030: */
1031: ifp->if_flags &= ~IFF_RUNNING;
1032: bcopy((caddr_t)ina->x_host.c_host,
1033: (caddr_t)ns->ds_addr, sizeof(ns->ds_addr));
1034: }
1035: neinit(ifp->if_unit); /* does ne_setaddr() */
1036: break;
1037: }
1038: default:
1039: neinit(ifp->if_unit);
1040: break;
1041: }
1042: break;
1043:
1044: case SIOCSIFFLAGS:
1045: if ((ifp->if_flags & IFF_UP) == 0 &&
1046: ifp->if_flags & IFF_RUNNING) {
1047: ifp->if_flags &= ~IFF_RUNNING;
1048: outb(ns->ns_port + ds_cmd, DSCM_STOP|DSCM_NODMA);
1049: } else if (ifp->if_flags & IFF_UP &&
1050: (ifp->if_flags & IFF_RUNNING) == 0)
1051: neinit(ifp->if_unit);
1052: break;
1053:
1054: #ifdef notdef
1055: case SIOCGHWADDR:
1056: bcopy((caddr_t)ns->ds_addr, (caddr_t) &ifr->ifr_data,
1057: sizeof(ns->ds_addr));
1058: break;
1059: #endif
1060:
1061: default:
1062: error = EINVAL;
1063: }
1064: splx(s);
1065: return (error);
1066: }
1067:
1068: /*
1069: * Reset of interface.
1070: */
1071: nereset(unit, uban)
1072: int unit, uban;
1073: {
1074: if (unit >= NNE)
1075: return;
1076: printf("ne%d: reset\n", unit);
1077: ne_softc[unit].ns_flags &= ~DSF_LOCK;
1078: neinit(unit);
1079: }
1080: #endif MACH_KERNEL
1081: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.