|
|
1.1 root 1: /*
2: * Mach Operating System
3: * Copyright (c) 1991,1990,1989 Carnegie Mellon University
4: * All Rights Reserved.
5: *
6: * Permission to use, copy, modify and distribute this software and its
7: * documentation is hereby granted, provided that both the copyright
8: * notice and this permission notice appear in all copies of the
9: * software, derivative works or modified versions, and any portions
10: * thereof, and that both notices appear in supporting documentation.
11: *
12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15: *
16: * Carnegie Mellon requests users of this software to return to
17: *
18: * Software Distribution Coordinator or [email protected]
19: * School of Computer Science
20: * Carnegie Mellon University
21: * Pittsburgh PA 15213-3890
22: *
23: * any improvements or extensions that they make and grant Carnegie Mellon
24: * the rights to redistribute these changes.
25: */
26: /* NOTE:
27: * There are three outstanding bug/features in this implementation.
28: * They may even be hardware misfeatures. The conditions are registered
29: * by counters maintained by the software.
30: * 1: over_write is a condition that means that the board wants to store
31: * packets, but there is no room. So new packets are lost. What seems to
32: * be happening is that we get an over_write condition, but there are no
33: * or just a few packets in the board's ram. Also it seems that we get
34: * several over_writes in a row.
35: * 2: Since there is only one transmit buffer, we need a lock to indicate
36: * whether it is in use. We clear this lock when we get a transmit interrupt.
37: * Sometimes we go to transmit and although there is no transmit in progress,
38: * the lock is set. (In this case, we just ignore the lock.) It would look
39: * like we can miss transmit interrupts?
40: * 3: We tried to clean up the unnecessary switches to bank 0.
41: * Unfortunately, when you do an ifconfig "down", the system tend to lock up
42: * a few seconds later (this was when DSF_RUNNING) was not being set before.
43: * But even with DSF_RUNNING, on an EISA bus machine we ALWAYS lock up after
44: * a few seconds.
45: */
46:
47: /*
48: * Western Digital 8003E Mach Ethernet driver (for intel 80386)
49: * Copyright (c) 1990 by Open Software Foundation (OSF).
50: */
51:
52: /*
53: Copyright 1990 by Open Software Foundation,
54: Cambridge, MA.
55:
56: All Rights Reserved
57:
58: Permission to use, copy, modify, and distribute this software and
59: its documentation for any purpose and without fee is hereby granted,
60: provided that the above copyright notice appears in all copies and
61: that both the copyright notice and this permission notice appear in
62: supporting documentation, and that the name of OSF or Open Software
63: Foundation not be used in advertising or publicity pertaining to
64: distribution of the software without specific, written prior
65: permission.
66:
67: OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
68: <INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
69: IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
70: CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
71: LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
72: NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
73: WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
74: */
75:
76: #define IF_CNTRS MACH
77:
78: #include <ns8390.h>
79: #if NNS8390 > 0
80:
81: #include <mach_ttd.h>
82: #include <kern/time_out.h>
83: #include <device/device_types.h>
84: #include <device/errno.h>
85: #include <device/io_req.h>
86: #include <device/if_hdr.h>
87: #include <device/if_ether.h>
88: #include <device/net_status.h>
89: #include <device/net_io.h>
90: #include "vm_param.h"
91: #include <i386/ipl.h>
92: #include <chips/busses.h>
93: #include <i386at/ds8390.h>
94: #include <i386at/if_wd8003.h>
95: #include <i386at/if_3c503.h>
96:
97: #if MACH_TTD
98: #include <ttd/ttd_stub.h>
99: #endif /* MACH_TTD */
100:
101:
102: #define SPLNET spl6
103:
104: int wd_debug = 0;
105:
106: int ns8390probe();
107: void ns8390attach();
108: int ns8390intr();
109: int ns8390init();
110: int ns8390output();
111: int ns8390ioctl();
112: int ns8390reset();
113: int ns8390rcv();
114: int ns8390watch();
115: int ns8390get_CURR();
116: int ns8390over_write();
117:
118: struct bus_device *ns8390info[NNS8390]; /* ???? */
119:
120: static vm_offset_t ns8390_std[NNS8390] = { 0 };
121: static struct bus_device *ns8390_info[NNS8390];
122: struct bus_driver ns8390driver =
123: {ns8390probe, 0, ns8390attach, 0, ns8390_std, "ns8390", ns8390_info, 0, 0, 0};
124:
125: int watchdog_id;
126:
127: char *wd8003_card = "wd";
128: char *elii_card = "el";
129: /* 2e0, 2a0, 280, 250, 350, 330, 310, 300*/
130: int elii_irq[8] = {5, 2, 2, 5, 5, 0x711, 0x711, 5};
131: int elii_bnc[8] = {1, 0, 1, 1, 0, 0x711, 0x711, 0};
132: /*int elii_bnc[8] = {0, 1, 1, 1, 1, 1, 0, 1}; */
133:
134: typedef struct {
135: #ifdef MACH_KERNEL
136: struct ifnet ds_if; /* generic interface header */
137: u_char ds_addr[6]; /* Ethernet hardware address */
138: #else MACH_KERNEL
139: struct arpcom ns8390_ac;
140: #define ds_if ns8390_ac.ac_if
141: #define ds_addr ns8390_ac.ac_enaddr
142: #endif MACH_KERNEL
143: int flags;
144: int timer;
145: int interrupt;
146: char *nic;
147: u_char address[ETHER_ADDR_SIZE];
148: short mode;
149: int tbusy;
150: char *sram; /* beginning of the shared memory RAM buffer */
151: int read_nxtpkt_ptr;/* pointer to next packet available */
152: int pstart; /* page start hold */
153: int pstop; /* page stop hold */
154: int tpsr; /* transmit page start hold */
155: int fifo_depth; /* NIC fifo threshold */
156: char *card;
157: int board_id;
158: }
159: ns8390_softc_t;
160:
161: ns8390_softc_t ns8390_softc[NNS8390];
162:
163: struct ns8390_cntrs {
164: u_int ovw,
165: jabber,
166: crc,
167: frame,
168: miss,
169: fifo,
170: rcv;
171: u_int xmt,
172: xmti,
173: busy,
174: heart;
175: } ns8390_cntrs[NNS8390];
176:
177: #if MACH_TTD
178: boolean_t ttd_poll_loop;
179:
180: int ns8390poll_receive();
181: int ns8390transmit_ttd();
182: #endif /* MACH_TTD */
183:
184: #ifdef IF_CNTRS
185: int ns_narp = 1, ns_arp = 0;
186: int ns_ein[32], ns_eout[32];
187: int ns_lin[128/8], ns_lout[128/8];
188: static
189: log_2(no)
190: unsigned long no;
191: {
192: return ({ unsigned long _temp__;
193: asm("bsr %1, %0; jne 0f; xorl %0, %0; 0:" :
194: "=r" (_temp__) : "a" (no));
195: _temp__;});
196: }
197: #endif IF_CNTRS
198:
199: /* Interrupts mask bits */
200: int imr_hold = DSIM_PRXE|DSIM_PTXE|DSIM_RXEE|DSIM_TXEE|DSIM_OVWE|DSIM_CNTE;
201:
202: /*
203: * ns8390probe:
204: *
205: * This function "probes" or checks for the wd8003 board on the bus to see
206: * if it is there. As far as I can tell, the best break between this
207: * routine and the attach code is to simply determine whether the board
208: * is configured in properly. Currently my approach to this is to test the
209: * base I/O special offset for the Western Digital unique byte sequence
210: * identifier. If the bytes match we assume board is there.
211: * The config code expects to see a successful return from the probe
212: * routine before attach will be called.
213: *
214: * input : address device is mapped to, and unit # being checked
215: * output : a '1' is returned if the board exists, and a 0 otherwise
216: *
217: */
218:
219: ns8390probe(port, dev)
220: struct bus_device *dev;
221: {
222: caddr_t hdwbase = (caddr_t)dev->address;
223: int unit = dev->unit;
224: ns8390_softc_t *sp = &ns8390_softc[unit];
225: int tmp;
226: int vendor_id;
227:
228: if ((unit < 0) || (unit > NNS8390)) {
229: printf("ns8390 ethernet unit %d out of range\n", unit);
230: return(0);
231: }
232: if (((u_char) inb(hdwbase+IFWD_LAR_0) == (u_char) WD_NODE_ADDR_0) &&
233: ((u_char) inb(hdwbase+IFWD_LAR_1) == (u_char) WD_NODE_ADDR_1) &&
234: ((u_char) inb(hdwbase+IFWD_LAR_2) == (u_char) WD_NODE_ADDR_2)) {
235: ns8390info[unit] = dev;
236: sp->card = wd8003_card;
237: dev->name = wd8003_card;
238: sp->nic = hdwbase + OFF_8390;
239: /* enable mem access to board */
240: sp->board_id = wd80xxget_board_id(dev);
241:
242: *(sp->address) = inb(hdwbase+IFWD_LAR_0);
243: *(sp->address + 1) = inb(hdwbase+IFWD_LAR_1);
244: *(sp->address + 2) = inb(hdwbase+IFWD_LAR_2);
245: *(sp->address + 3) = inb(hdwbase+IFWD_LAR_3);
246: *(sp->address + 4) = inb(hdwbase+IFWD_LAR_4);
247: *(sp->address + 5) = inb(hdwbase+IFWD_LAR_5);
248: return (1);
249: } /* checks the address of the board to verify that it is a WD */
250:
251: /* try to avoid any NE2000 pretending to be an el II */
252: if (inb(hdwbase + 0x408) == 0xff)
253: return 0;
254:
255: /* check vendor id */
256: tmp = inb(hdwbase + CTLR);
257:
258: outb(hdwbase + CTLR, CTLR_RST|CTLR_THIN); /* Reset it... */
259: outb(hdwbase + CTLR, CTLR_THIN);
260: /*
261: * Map the station addr PROM into the lower I/O ports. We now
262: * check for both the old and new 3Com prefix
263: */
264: outb(hdwbase + CTLR, CTLR_STA_ADDR|CTLR_THIN);
265: vendor_id = inb(hdwbase)*0x10000 + inb(hdwbase + 1)*0x100 +
266: inb(hdwbase + 2);
267: /* Restore the register we frobbed. */
268: outb(hdwbase + CTLR, tmp);
269: if ((vendor_id != OLD_3COM_ID) && (vendor_id != NEW_3COM_ID))
270: return 0;
271:
272: if ((tmp = inb(hdwbase+BCFR))) {
273: switch(tmp) {
274: case (1<<7): sp->board_id = 7; break; /*irq5 xvcr*/
275: #ifdef not_currently_possible
276: case (1<<6): sp->board_id = 6; break;
277: case (1<<5): sp->board_id = 5; break;
278: #endif not_currently_possible
279: case (1<<4): sp->board_id = 4; break;
280: case (1<<3): sp->board_id = 3; break;
281: case (1<<2): sp->board_id = 2; break; /*irq2 bnc*/
282: case (1<<1): sp->board_id = 1; break; /*irq2 xvcr*/
283: case (1<<0): sp->board_id = 0; break; /*irq5 bnc*/
284: default: return 0;
285: }
286: switch (inb(hdwbase+PCFR)) {
287: case (1<<7): dev->phys_address = 0xDC000; break;
288: case (1<<6): dev->phys_address = 0xD8000; break;
289: #ifdef not_currently_possible
290: case (1<<5): dev->phys_address = 0xCC000; break;
291: case (1<<4): dev->phys_address = 0xC8000; break;
292: #endif not_currently_possible
293: default:
294: printf("EtherLink II with NO memory configured\n");
295: return 0;
296: }
297: ns8390info[unit] = dev;
298: dev->sysdep1 = elii_irq[sp->board_id];
299: if (dev->sysdep1 == 2)
300: dev->sysdep1 = 9;
301: sp->card = elii_card;
302: dev->name = elii_card;
303: sp->nic = hdwbase;
304: return 1;
305: }
306:
307: return(0);
308: }
309:
310: /*
311: * ns8390attach:
312: *
313: * This function attaches a ns8390 board to the "system". The rest of
314: * runtime structures are initialized here (this routine is called after
315: * a successful probe of the board). Once the ethernet address is read
316: * and stored, the board's ifnet structure is attached and readied.
317: *
318: * input : bus_device structure setup in autoconfig
319: * output : board structs and ifnet is setup
320: *
321: */
322:
323: void ns8390attach(dev)
324: struct bus_device *dev;
325: {
326: ns8390_softc_t *sp;
327: struct ifnet *ifp;
328: u_char unit;
329: int temp;
330:
331: take_dev_irq(dev);
332: unit = (u_char)dev->unit;
333: sp = &ns8390_softc[unit];
334: printf(", port = %x, spl = %d, pic = %d. ",
335: dev->address, dev->sysdep, dev->sysdep1);
336:
337: if (sp->card == elii_card) {
338: if (elii_bnc[sp->board_id])
339: printf("cheapernet ");
340: else
341: printf("ethernet ");
342: } else
343: printf("ethernet ");
344:
345: (volatile char *)sp->sram =
346: (volatile char *) phystokv(dev->phys_address);
347: dev->address = (vm_offset_t) phystokv(dev->address);
348: sp->timer = -1;
349: sp->flags = 0;
350: sp->mode = 0;
351:
352: if (!ns8390hwrst(unit)) {
353: printf("%s%d: attach(): reset failed.\n",
354: sp->card, unit);
355: return;
356: }
357: /* N.B. sp->address is not determined till
358: * hwrst time. */
359: *(sp->ds_addr) = *(sp->address);
360: *(sp->ds_addr + 1) = *(sp->address + 1);
361: *(sp->ds_addr + 2) = *(sp->address + 2);
362: *(sp->ds_addr + 3) = *(sp->address + 3);
363: *(sp->ds_addr + 4) = *(sp->address + 4);
364: *(sp->ds_addr + 5) = *(sp->address + 5);
365:
366: printf("id [%x:%x:%x:%x:%x:%x]",
367: sp->address[0],sp->address[1],sp->address[2],
368: sp->address[3],sp->address[4],sp->address[5]);
369: ifp = &(sp->ds_if);
370: ifp->if_unit = unit;
371: ifp->if_mtu = ETHERMTU;
372: ifp->if_flags = IFF_BROADCAST;
373: #ifdef MACH_KERNEL
374: ifp->if_header_size = sizeof(struct ether_header);
375: ifp->if_header_format = HDR_ETHERNET;
376: ifp->if_address_size = 6;
377: ifp->if_address = (char *)&sp->address[0];
378: if_init_queues(ifp);
379: #else MACH_KERNEL
380: ifp->if_name = sp->card;
381: ifp->if_init = ns8390init;
382: ifp->if_output = ns8390output;
383: ifp->if_ioctl = ns8390ioctl;
384: ifp->if_reset = ns8390reset;
385: ifp->if_next = NULL;
386: if_attach(ifp);
387: #ifdef notdef
388: watchdog_id = timeout(ns8390watch, &(ifp->if_unit), 20*HZ);
389: #endif
390: #endif MACH_KERNEL
391:
392: #ifdef MACH_KERNEL
393: #if MACH_TTD
394: if (!ttd_get_packet) {
395: ttd_device_unit = unit;
396: ttd_get_packet = ns8390poll_receive;
397: ttd_send_packet = ns8390transmit_ttd;
398: ttd_host_ether_id.array[0] = *(sp->address);
399: ttd_host_ether_id.array[1] = *(sp->address + 1);
400: ttd_host_ether_id.array[2] = *(sp->address + 2);
401: ttd_host_ether_id.array[3] = *(sp->address + 3);
402: ttd_host_ether_id.array[4] = *(sp->address + 4);
403: ttd_host_ether_id.array[5] = *(sp->address + 5);
404: }
405: #endif /* MACH_TTD */
406: #endif /* MACH_KERNEL */
407: }
408:
409: /*
410: * ns8390watch():
411: *
412: */
413:
414: int
415: ns8390watch(b_ptr)
416: caddr_t b_ptr;
417: {
418: int x,
419: y,
420: opri,
421: unit;
422: int temp_cr;
423: caddr_t nic;
424:
425: unit = *b_ptr;
426: #ifdef MACH_KERNEL
427: timeout(ns8390watch,b_ptr,20*HZ);
428: #else MACH_KERNEL
429: watchdog_id = timeout(ns8390watch,b_ptr,20*HZ);
430: #endif MACH_KERNEL
431: nic = ns8390_softc[unit].nic;
432: temp_cr = inb(nic+ds_cmd);
433: outb(nic + ds_cmd, (temp_cr & 0x3f) | DSCM_PG0);
434: printf("<<< ISR=%x CURR=%x rdnxt=%x BNDY=%x>>> ",
435: inb(nic + ds0_isr),
436: ns8390get_CURR(unit), ns8390_softc[unit].read_nxtpkt_ptr,
437: inb(nic+ds0_bndy));
438: outb(nic+ds_cmd,temp_cr);
439: }
440:
441: #ifdef MACH_KERNEL
442: int ns8390start(); /* forward */
443:
444: /*ARGSUSED*/
445: wd8003open(dev, flag)
446: dev_t dev;
447: int flag;
448: {
449: register int unit = minor(dev);
450:
451: if (ns8390_softc[unit].card != wd8003_card)
452: return (ENXIO);
453: if (unit < 0 || unit >= NNS8390 ||
454: ns8390_softc[unit].nic == 0)
455: return (ENXIO);
456:
457: ns8390_softc[unit].ds_if.if_flags |= IFF_UP;
458: ns8390init(unit);
459: return(0);
460: }
461:
462: eliiopen(dev, flag)
463: dev_t dev;
464: int flag;
465: {
466: register int unit = minor(dev);
467:
468: if (ns8390_softc[unit].card != elii_card)
469: return (ENXIO);
470: if (unit < 0 || unit >= NNS8390 ||
471: ns8390_softc[unit].nic == 0)
472: return (ENXIO);
473:
474: ns8390_softc[unit].ds_if.if_flags |= IFF_UP;
475: ns8390init(unit);
476: return(0);
477: }
478:
479: ns8390output(dev, ior)
480: dev_t dev;
481: io_req_t ior;
482: {
483: register int unit = minor(dev);
484:
485: if (unit < 0 || unit >= NNS8390 ||
486: ns8390_softc[unit].nic == 0)
487: return (ENXIO);
488: return (net_write(&ns8390_softc[unit].ds_if, ns8390start, ior));
489: }
490:
491: ns8390setinput(dev, receive_port, priority, filter, filter_count)
492: dev_t dev;
493: mach_port_t receive_port;
494: int priority;
495: filter_t filter[];
496: unsigned int filter_count;
497: {
498: register int unit = minor(dev);
499:
500: if (unit < 0 || unit >= NNS8390 ||
501: ns8390_softc[unit].nic == 0)
502: return (ENXIO);
503:
504: return (net_set_filter(&ns8390_softc[unit].ds_if,
505: receive_port, priority,
506: filter, filter_count));
507: }
508:
509: #else MACH_KERNEL
510: /*
511: * ns8390output:
512: *
513: * This routine is called by the "if" layer to output a packet to
514: * the network. This code resolves the local ethernet address, and
515: * puts it into the mbuf if there is room. If not, then a new mbuf
516: * is allocated with the header information and precedes the data
517: * to be transmitted. The routine ns8390xmt() which actually
518: * transmits the data expects the ethernet header to precede the
519: * data in the mbuf.
520: *
521: * input: ifnet structure pointer, an mbuf with data, and address
522: * to be resolved
523: * output: mbuf is updated to hold enet address, or a new mbuf
524: * with the address is added
525: *
526: */
527:
528: ns8390output(ifp, m0, dst)
529: struct ifnet *ifp;
530: struct mbuf *m0;
531: struct sockaddr *dst;
532: {
533: register ns8390_softc_t *is = &ns8390_softc[ifp->if_unit];
534: u_char edst[6];
535: struct in_addr idst;
536: register struct mbuf *m = m0;
537: register struct ether_header *eh;
538: register int off;
539: int usetrailers;
540: int type, error;
541: spl_t opri;
542:
543: if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
544: printf("%s%d output(): Turning off board %d\n",
545: is->card, ifp->if_unit);
546: ns8390intoff(ifp->if_unit);
547: error = ENETDOWN;
548: goto bad;
549: }
550: switch (dst->sa_family) {
551: #ifdef INET
552: case AF_INET:
553: idst = ((struct sockaddr_in *)dst)->sin_addr;
554: if (!arpresolve(&is->ns8390_ac, m, &idst, edst, &usetrailers)){
555: return (0); /* if not yet resolved */
556: }
557: off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
558: if (usetrailers && off > 0 && (off & 0x1ff) == 0 &&
559: m->m_off >= MMINOFF + 2 * sizeof (u_short)) {
560: type = ETHERTYPE_TRAIL + (off>>9);
561: m->m_off -= 2 * sizeof (u_short);
562: m->m_len += 2 * sizeof (u_short);
563: *mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP);
564: *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len);
565: goto gottrailertype;
566: }
567: type = ETHERTYPE_IP;
568: off = 0;
569: goto gottype;
570: #endif
571: #ifdef NS
572: case AF_NS:
573: type = ETHERTYPE_NS;
574: bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
575: (caddr_t)edst,
576: sizeof (edst));
577: off = 0;
578: goto gottype;
579: #endif
580: case AF_UNSPEC:
581: eh = (struct ether_header *)dst->sa_data;
582: bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst));
583: type = eh->ether_type;
584: goto gottype;
585: default:
586: printf("%s%d output(): can't handle af%d\n",
587: is->card, ifp->if_unit,
588: dst->sa_family);
589: error = EAFNOSUPPORT;
590: goto bad;
591: }
592: gottrailertype:
593: /*
594: * Packet to be sent as trailer: move first packet
595: * (control information) to end of chain.
596: */
597: while (m->m_next)
598: m = m->m_next;
599: m->m_next = m0;
600: m = m0->m_next;
601: m0->m_next = 0;
602: m0 = m;
603: gottype:
604: /*
605: * Add local net header. If no space in first mbuf,
606: * allocate another.
607: */
608: if (m->m_off > MMAXOFF ||
609: MMINOFF + sizeof (struct ether_header) > m->m_off) {
610: m = m_get(M_DONTWAIT, MT_HEADER);
611: if (m == 0) {
612: error = ENOBUFS;
613: goto bad;
614: }
615: m->m_next = m0;
616: m->m_off = MMINOFF;
617: m->m_len = sizeof (struct ether_header);
618: } else {
619: m->m_off -= sizeof (struct ether_header);
620: m->m_len += sizeof (struct ether_header);
621: }
622: eh = mtod(m, struct ether_header *);
623: eh->ether_type = htons((u_short)type);
624: bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst));
625: bcopy((caddr_t)is->address,
626: (caddr_t)eh->ether_shost,
627: sizeof(edst));
628: /*
629: * Queue message on interface, and start output if interface
630: * not yet active.
631: */
632: opri = SPLNET();
633: if (IF_QFULL(&ifp->if_snd)) {
634: IF_DROP(&ifp->if_snd);
635: splx(opri);
636: m_freem(m);
637: return (ENOBUFS);
638: }
639: IF_ENQUEUE(&ifp->if_snd, m);
640: /*
641: * Some action needs to be added here for checking whether the
642: * board is already transmitting. If it is, we don't want to
643: * start it up (ie call ns8390start()). We will attempt to send
644: * packets that are queued up after an interrupt occurs. Some
645: * flag checking action has to happen here and/or in the start
646: * routine. This note is here to remind me that some thought
647: * is needed and there is a potential problem here.
648: *
649: */
650: ns8390start(ifp->if_unit);
651: splx(opri);
652: return (0);
653: bad:
654: m_freem(m0);
655: return (error);
656: }
657: #endif MACH_KERNEL
658:
659: /*
660: * ns8390reset:
661: *
662: * This routine is in part an entry point for the "if" code. Since most
663: * of the actual initialization has already (we hope already) been done
664: * by calling ns8390attach().
665: *
666: * input : unit number or board number to reset
667: * output : board is reset
668: *
669: */
670:
671: int
672: ns8390reset(unit)
673: int unit;
674: {
675:
676: ns8390_softc[unit].ds_if.if_flags &= ~IFF_RUNNING;
677: return(ns8390init(unit));
678: }
679:
680: /*
681: * ns8390init:
682: *
683: * Another routine that interfaces the "if" layer to this driver.
684: * Simply resets the structures that are used by "upper layers".
685: * As well as calling ns8390hwrst that does reset the ns8390 board.
686: *
687: * input : board number
688: * output : structures (if structs) and board are reset
689: *
690: */
691:
692: int
693: ns8390init(unit)
694: int unit;
695: {
696: struct ifnet *ifp;
697: int stat;
698: spl_t oldpri;
699:
700: ifp = &(ns8390_softc[unit].ds_if);
701: #ifdef MACH_KERNEL
702: #else MACH_KERNEL
703: if (ifp->if_addrlist == (struct ifaddr *)0) {
704: return;
705: }
706: #endif MACH_KERNEL
707: oldpri = SPLNET();
708: if ((stat = ns8390hwrst(unit)) == TRUE) {
709: ns8390_softc[unit].ds_if.if_flags |= IFF_RUNNING;
710: ns8390_softc[unit].flags |= DSF_RUNNING;
711: ns8390_softc[unit].tbusy = 0;
712: ns8390start(unit);
713: } else
714: printf("%s%d init(): trouble resetting board %d\n",
715: ns8390_softc[unit].card, unit);
716: ns8390_softc[unit].timer = 5;
717: splx(oldpri);
718: return(stat);
719: }
720:
721: /*
722: * ns8390start:
723: *
724: * This is yet another interface routine that simply tries to output a
725: * in an mbuf after a reset.
726: *
727: * input : board number
728: * output : stuff sent to board if any there
729: *
730: */
731:
732: ns8390start(unit)
733: int unit;
734: {
735: register ns8390_softc_t *is = &ns8390_softc[unit];
736: struct ifnet *ifp;
737: #ifdef MACH_KERNEL
738: io_req_t m;
739: #else MACH_KERNEL
740: struct mbuf *m;
741: #endif MACH_KERNEL
742:
743: if (is->tbusy) {
744: caddr_t nic = ns8390_softc[unit].nic;
745: if (!(inb(nic+ds_cmd) & DSCM_TRANS)) {
746: is->tbusy = 0;
747: ns8390_cntrs[unit].busy++;
748: } else
749: return;
750: }
751:
752: ifp = &(ns8390_softc[unit].ds_if);
753:
754: IF_DEQUEUE(&ifp->if_snd, m);
755: #ifdef MACH_KERNEL
756: if (m != 0)
757: #else MACH_KERNEL
758: if (m != (struct mbuf *)0)
759: #endif MACH_KERNEL
760: {
761: is->tbusy++;
762: ns8390_cntrs[unit].xmt++;
763: ns8390xmt(unit, m);
764: }
765: }
766:
767: #ifdef MACH_KERNEL
768: /*ARGSUSED*/
769: ns8390getstat(dev, flavor, status, count)
770: dev_t dev;
771: int flavor;
772: dev_status_t status; /* pointer to OUT array */
773: unsigned int *count; /* out */
774: {
775: register int unit = minor(dev);
776:
777: if (unit < 0 || unit >= NNS8390 ||
778: ns8390_softc[unit].nic == 0)
779: return (ENXIO);
780:
781: return (net_getstat(&ns8390_softc[unit].ds_if,
782: flavor,
783: status,
784: count));
785: }
786: ns8390setstat(dev, flavor, status, count)
787: dev_t dev;
788: int flavor;
789: dev_status_t status;
790: unsigned int count;
791: {
792: register int unit = minor(dev);
793: register ns8390_softc_t *sp;
794:
795: if (unit < 0 || unit >= NNS8390 ||
796: ns8390_softc[unit].nic == 0)
797: return (ENXIO);
798:
799: sp = &ns8390_softc[unit];
800:
801: switch (flavor) {
802: case NET_STATUS:
803: {
804: /*
805: * All we can change are flags, and not many of those.
806: */
807: register struct net_status *ns = (struct net_status *)status;
808: int mode = 0;
809:
810: if (count < NET_STATUS_COUNT)
811: return (D_INVALID_SIZE);
812:
813: if (ns->flags & IFF_ALLMULTI)
814: mode |= MOD_ENAL;
815: if (ns->flags & IFF_PROMISC)
816: mode |= MOD_PROM;
817:
818: /*
819: * Force a complete reset if the receive mode changes
820: * so that these take effect immediately.
821: */
822: if (sp->mode != mode) {
823: sp->mode = mode;
824: if (sp->flags & DSF_RUNNING) {
825: sp->flags &= ~(DSF_LOCK | DSF_RUNNING);
826: ns8390init(unit);
827: }
828: }
829: break;
830: }
831:
832: default:
833: return (D_INVALID_OPERATION);
834: }
835: return (D_SUCCESS);
836: }
837: #else MACH_KERNEL
838: /*
839: * ns8390ioctl:
840: *
841: * This routine processes an ioctl request from the "if" layer
842: * above.
843: *
844: * input : pointer the appropriate "if" struct, command, and data
845: * output : based on command appropriate action is taken on the
846: * ns8390 board(s) or related structures
847: * return : error is returned containing exit conditions
848: *
849: */
850:
851: int
852: ns8390ioctl(ifp, cmd, data)
853: struct ifnet *ifp;
854: int cmd;
855: caddr_t data;
856: {
857: register struct ifaddr *ifa = (struct ifaddr *)data;
858: register ns8390_softc_t *is;
859: int error;
860: spl_t opri;
861: short mode = 0;
862:
863: is = &ns8390_softc[ifp->if_unit];
864: opri = SPLNET();
865: error = 0;
866: switch (cmd) {
867: case SIOCSIFADDR:
868: ifp->if_flags |= IFF_UP;
869: ns8390init(ifp->if_unit);
870: switch (ifa->ifa_addr.sa_family) {
871: #ifdef INET
872: case AF_INET:
873: ((struct arpcom *)ifp)->ac_ipaddr =
874: IA_SIN(ifa)->sin_addr;
875: arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
876: break;
877: #endif
878: #ifdef NS
879: case AF_NS:
880: {
881: register struct ns_addr *ina =
882: &(IA_SNS(ifa)->sns_addr);
883: if (ns_nullhost(*ina))
884: ina->x_host =
885: *(union ns_host *)(ds->ds_addr);
886: else
887: ????
888: ns8390seteh(ina->x_host.c_host,
889: ns8390_softc[ifp->if_unit].base);
890: break;
891: }
892: #endif
893: }
894: break;
895: case SIOCSIFFLAGS:
896: if (ifp->if_flags & IFF_ALLMULTI)
897: mode |= MOD_ENAL;
898: if (ifp->if_flags & IFF_PROMISC)
899: mode |= MOD_PROM;
900: /*
901: * force a complete reset if the receive multicast/
902: * promiscuous mode changes so that these take
903: * effect immediately.
904: *
905: */
906: if (is->mode != mode) {
907: is->mode = mode;
908: if (is->flags & DSF_RUNNING) {
909: is->flags &=
910: ~(DSF_LOCK|DSF_RUNNING);
911: ns8390init(ifp->if_unit);
912: }
913: }
914: if ((ifp->if_flags & IFF_UP) == 0 &&
915: is->flags & DSF_RUNNING) {
916: printf("%s%d ioctl(): turning off board %d\n",
917: is->card, ifp->if_unit);
918: is->flags &= ~(DSF_LOCK | DSF_RUNNING);
919: is->timer = -1;
920: ns8390intoff(ifp->if_unit);
921: ns8390over_write(ifp->if_unit);
922: } else
923: if (ifp->if_flags & IFF_UP &&
924: (is->flags & DSF_RUNNING) == 0)
925: ns8390init(ifp->if_unit);
926: break;
927: #ifdef IF_CNTRS
928: case SIOCCIFCNTRS:
929: if (!suser()) {
930: error = EPERM;
931: break;
932: }
933: bzero((caddr_t)ns_ein, sizeof (ns_ein));
934: bzero((caddr_t)ns_eout, sizeof (ns_eout));
935: bzero((caddr_t)ns_lin, sizeof (ns_lin));
936: bzero((caddr_t)ns_lout, sizeof (ns_lout));
937: bzero((caddr_t)&ns_arp, sizeof (int));
938: bzero((caddr_t)&ns8390_cntrs, sizeof (ns8390_cntrs));
939: break;
940: #endif IF_CNTRS
941: default:
942: error = EINVAL;
943: }
944: splx(opri);
945: return (error);
946: }
947: #endif MACH_KERNEL
948:
949: /*
950: * ns8390hwrst:
951: *
952: * This routine resets the ns8390 board that corresponds to the
953: * board number passed in.
954: *
955: * input : board number to do a hardware reset
956: * output : board is reset
957: *
958: */
959:
960: int
961: ns8390hwrst(unit)
962: int unit;
963: {
964: caddr_t nic = ns8390_softc[unit].nic;
965: int count;
966: u_char stat;
967: spl_t spl = SPLNET();
968:
969: if (ns8390_softc[unit].card == wd8003_card &&
970: config_wd8003(unit) == FALSE) {
971: printf("%s%d hwrst(): config_wd8003 failed.\n",
972: ns8390_softc[unit].card, unit);
973: splx(spl);
974: return(FALSE);
975: }
976: if (ns8390_softc[unit].card == elii_card &&
977: config_3c503(unit) == FALSE) {
978: printf("%s%d hwrst(): config_3c503 failed.\n",
979: ns8390_softc[unit].card, unit);
980: splx(spl);
981: return(FALSE);
982: }
983: if (config_nic(unit) == FALSE) {
984: printf("%s%d hwrst(): config_nic failed.\n",
985: ns8390_softc[unit].card, unit);
986: splx(spl);
987: return(FALSE);
988: }
989: splx(spl);
990: return(TRUE);
991: }
992:
993: /*
994: * ns8390intr:
995: *
996: * This function is the interrupt handler for the ns8390 ethernet
997: * board. This routine will be called whenever either a packet
998: * is received, or a packet has successfully been transfered and
999: * the unit is ready to transmit another packet.
1000: *
1001: * input : board number that interrupted
1002: * output : either a packet is received, or a packet is transfered
1003: *
1004: */
1005: int
1006: ns8390intr(unit)
1007: {
1008: int opri, i;
1009: int isr_status;
1010: int temp_cr;
1011: caddr_t nic = ns8390_softc[unit].nic;
1012:
1013: temp_cr = inb(nic+ds_cmd);
1014: outb(nic+ds_cmd, (temp_cr & 0x3f) | DSCM_PG0);
1015: outb(nic+ds0_imr, 0); /* stop board interrupts */
1016: outb(nic+ds_cmd, temp_cr);
1017: while (isr_status = inb(nic+ds0_isr)) {
1018: outb(nic+ds0_isr, isr_status); /* clear interrupt status */
1019:
1020: if ((isr_status & (DSIS_ROVRN|DSIS_RXE)) == DSIS_RXE) {
1021: int rsr = inb(nic+ds0_rsr);
1022: if (rsr & DSRS_DFR) ns8390_cntrs[unit].jabber++;
1023: if (rsr & ~(DSRS_DFR|DSRS_PHY|DSRS_FAE|DSRS_CRC|DSIS_RX))
1024: printf("%s%d intr(): isr = %x, RSR = %x\n",
1025: ns8390_softc[unit].card, unit,
1026: isr_status, rsr);
1027: } else if (isr_status & DSIS_ROVRN) {
1028: ns8390_cntrs[unit].ovw++;
1029: ns8390over_write(unit);
1030: }
1031: if (isr_status & DSIS_RX) { /* DFR & PRX is possible */
1032: ns8390rcv(unit);
1033:
1034: #if MACH_TTD
1035: if (kttd_active)
1036: ttd_poll_loop = FALSE;
1037: #endif /* MACH_TTD */
1038: }
1039:
1040: if (isr_status & DSIS_TXE) {
1041: int tsr = inb(nic+ds0_tsr);
1042: tsr &= ~0x2; /* unadvertised special */
1043: #if MACH_TTD
1044: if (!kttd_active)
1045: #endif /* MACH_TTD */
1046: {
1047: if (tsr == (DSTS_CDH|DSTS_ABT))
1048: ns8390_cntrs[unit].heart++;
1049: else
1050: printf("%s%d intr(): isr = %x, TSR = %x\n",
1051: ns8390_softc[unit].card, unit,
1052: isr_status, tsr);
1053: ns8390_softc[unit].tbusy = 0;
1054: ns8390start(unit);
1055: }
1056: } else if (isr_status & DSIS_TX) {
1057: #if MACH_TTD
1058: if (!kttd_active)
1059: #endif /* MACH_TTD */
1060: {
1061: ns8390_cntrs[unit].xmti++;
1062: ns8390_softc[unit].tbusy = 0;
1063: ns8390start(unit);
1064: }
1065: }
1066:
1067: if (isr_status & DSIS_CTRS) {
1068: int c0 = inb(nic+ds0_cntr0);
1069: int c1 = inb(nic+ds0_cntr1);
1070: int c2 = inb(nic+ds0_cntr2);
1071: ns8390_cntrs[unit].frame += c0;
1072: ns8390_cntrs[unit].crc += c1;
1073: ns8390_cntrs[unit].miss += c2;
1074: #ifdef COUNTERS
1075: printf("%s%d intr(): isr = %x, FRAME %x, CRC %x, MISS %x\n",
1076: ns8390_softc[unit].card, unit,
1077: isr_status, c0, c1, c2);
1078: printf("%s%d intr(): TOTAL , FRAME %x, CRC %x, MISS %x\n",
1079: ns8390_softc[unit].card, unit,
1080: ns8390_cntrs[unit].frame,
1081: ns8390_cntrs[unit].crc,
1082: ns8390_cntrs[unit].miss);
1083: #endif COUNTERS
1084: outb(nic+ds0_isr, isr_status); /* clear interrupt status again */
1085: }
1086: }
1087: temp_cr=inb(nic+ds_cmd);
1088: outb(nic+ds_cmd, (temp_cr & 0x3f) | DSCM_PG0);
1089: outb(nic+ds0_imr, imr_hold);
1090: outb(nic+ds_cmd, temp_cr);
1091: return(0);
1092: }
1093:
1094: /*
1095: * Called if on board buffer has been completely filled by ns8390intr. It stops
1096: * the board, reads in all the buffers that are currently in the buffer, and
1097: * then restart board.
1098: */
1099: ns8390over_write(unit)
1100: int unit;
1101: {
1102: caddr_t nic = ns8390_softc[unit].nic;
1103: int no;
1104: int count = 0;
1105:
1106: outb(nic+ds_cmd, DSCM_NODMA|DSCM_STOP|DSCM_PG0); /* clear the receive buffer */
1107: outb(nic+ds0_rbcr0, 0);
1108: outb(nic+ds0_rbcr1, 0);
1109: while ((!(inb (nic + ds0_isr) & DSIS_RESET)) && (count < 10000))
1110: count++;
1111: if (count == 10000) {
1112: printf("%s%d: over_write(): would not reset.\n",
1113: ns8390_softc[unit].card, unit);
1114: }
1115: no = ns8390rcv(unit);
1116: #ifdef OVWBUG
1117: printf("%s%d over_write(): ns8390 OVW ... %d.\n",
1118: ns8390_softc[unit].card, unit, no);
1119: #endif OVWBUG
1120: outb(nic+ds0_tcr, DSTC_LB0); /* External loopback mode */
1121: outb(nic+ds_cmd, DSCM_NODMA|DSCM_START|DSCM_PG0);
1122: outb(nic+ds0_tcr, 0);
1123: return;
1124: }
1125:
1126: /*
1127: * ns8390rcv:
1128: *
1129: * This routine is called by the interrupt handler to initiate a
1130: * packet transfer from the board to the "if" layer above this
1131: * driver. This routine checks if a buffer has been successfully
1132: * received by the ns8390. If so, it does the actual transfer of the
1133: * board data (including the ethernet header) into a packet (consisting
1134: * of an mbuf chain) and enqueues it to a higher level.
1135: * Then check again whether there are any packets in the receive ring,
1136: * if so, read the next packet, until there are no more.
1137: *
1138: * input : number of the board to check
1139: * output : if a packet is available, it is "sent up"
1140: */
1141: ns8390rcv(unit)
1142: int unit;
1143: {
1144: register ns8390_softc_t *is = &ns8390_softc[unit];
1145: register struct ifnet *ifp = &is->ds_if;
1146: caddr_t nic = is->nic;
1147: int packets = 0;
1148: struct ether_header eh;
1149: u_short mlen, len, bytes_in_mbuf, bytes;
1150: u_short remaining;
1151: int temp_cr;
1152: u_char *mb_p;
1153: int board_id = is->board_id;
1154: vm_offset_t hdwbase = ns8390info[unit]->address;
1155: spl_t s;
1156:
1157: /* calculation of pkt size */
1158: int nic_overcount; /* NIC says 1 or 2 more than we need */
1159: int pkt_size; /* calculated size of received data */
1160: int wrap_size; /* size of data before wrapping it */
1161: int header_nxtpkt_ptr; /* NIC's next pkt ptr in rcv header */
1162: int low_byte_count; /* low byte count of read from rcv header */
1163: int high_byte_count; /* calculated high byte count */
1164:
1165:
1166: volatile char *sram_nxtpkt_ptr; /* mem location of next packet */
1167: volatile char *sram_getdata_ptr; /* next location to be read */
1168: #ifdef MACH_KERNEL
1169: ipc_kmsg_t new_kmsg;
1170: struct ether_header *ehp;
1171: struct packet_header *pkt;
1172: #else MACH_KERNEL
1173: struct mbuf *m, *tm; /* initial allocation of mem; temp */
1174: #endif MACH_KERNEL
1175:
1176:
1177: #if MACH_TTD
1178: if (((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) &&
1179: !kttd_active) {
1180: #else
1181: if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
1182: #endif /* MACH_TTD */
1183: temp_cr = inb(nic+ds_cmd); /* get current CR value */
1184: outb(nic+ds_cmd,((temp_cr & 0x3F)|DSCM_PG0|DSCM_STOP));
1185: outb(nic+ds0_imr, 0); /* Interrupt Mask Register */
1186: outb(nic+ds_cmd, temp_cr);
1187: return -1;
1188: }
1189:
1190: while(is->read_nxtpkt_ptr != ns8390get_CURR(unit)) {
1191:
1192: /* while there is a packet to read from the buffer */
1193:
1194: if ((is->read_nxtpkt_ptr < is->pstart) ||
1195: (is->read_nxtpkt_ptr >= is->pstop)) {
1196: ns8390hwrst(unit);
1197: return -1;
1198: } /* if next packet pointer is out of receive ring bounds */
1199:
1200: #if MACH_TTD
1201: if (!kttd_active)
1202: #endif /* MACH_TTD */
1203: {
1204: packets++;
1205: ns8390_cntrs[unit].rcv++;
1206: }
1207:
1208: sram_nxtpkt_ptr = (char *) (is->sram + (is->read_nxtpkt_ptr << 8));
1209:
1210: /* get packet size and location of next packet */
1211: header_nxtpkt_ptr = *(sram_nxtpkt_ptr + 1);
1212: header_nxtpkt_ptr &= 0xFF;
1213: low_byte_count = *(sram_nxtpkt_ptr + 2);
1214: low_byte_count &= 0xFF;
1215:
1216: if ((low_byte_count + NIC_HEADER_SIZE) > NIC_PAGE_SIZE)
1217: nic_overcount = 2;
1218: else
1219: nic_overcount = 1;
1220: if (header_nxtpkt_ptr > is->read_nxtpkt_ptr) {
1221: wrap_size = 0;
1222: high_byte_count = header_nxtpkt_ptr - is->read_nxtpkt_ptr -
1223: nic_overcount;
1224: } else {
1225: wrap_size = (int) (is->pstop - is->read_nxtpkt_ptr - nic_overcount);
1226: high_byte_count = is->pstop - is->read_nxtpkt_ptr +
1227: header_nxtpkt_ptr - is->pstart - nic_overcount;
1228: }
1229: pkt_size = (high_byte_count << 8) | (low_byte_count & 0xFF);
1230: /* does not seem to include NIC_HEADER_SIZE */
1231: if (!pkt_size) {
1232: printf("%s%d rcv(): zero length.\n",
1233: ns8390_softc[unit].card, unit);
1234: goto next_pkt;
1235: }
1236: len = pkt_size;
1237:
1238: sram_getdata_ptr = sram_nxtpkt_ptr + NIC_HEADER_SIZE;
1239: if (board_id & IFWD_SLOT_16BIT) {
1240: #if MACH_TTD
1241: if (!kttd_active)
1242: #endif /* MACH_TTD */
1243: { s = splhi(); }
1244:
1245: en_16bit_access(hdwbase, board_id);
1246: bcopy16 (sram_getdata_ptr,
1247: &eh,
1248: sizeof(struct ether_header));
1249: dis_16bit_access (hdwbase, board_id);
1250: #if MACH_TTD
1251: if (!kttd_active)
1252: #endif /* MACH_TTD */
1253: { splx(s); }
1254:
1255: } else {
1256: bcopy16 (sram_getdata_ptr,
1257: &eh,
1258: sizeof(struct ether_header));
1259: }
1260: sram_getdata_ptr += sizeof(struct ether_header);
1261: len -= (sizeof(struct ether_header) + 4); /* crc size */
1262: #ifdef MACH_KERNEL
1263: #if MACH_TTD
1264: if (kttd_active) {
1265: new_kmsg = (ipc_kmsg_t)ttd_request_msg;
1266: }else
1267: #endif /* MACH_TTD */
1268: {
1269: new_kmsg = net_kmsg_get();
1270: if (new_kmsg == IKM_NULL) {
1271: /*
1272: * Drop the packet.
1273: */
1274: is->ds_if.if_rcvdrops++;
1275: /*
1276: * not only do we want to return, we need to drop
1277: * the packet on the floor to clear the interrupt.
1278: */
1279: ns8390lost_frame(unit);
1280: return;/* packets;*/
1281: }
1282: }
1283:
1284: #if DEBUG_TTD
1285: dump_ether_header("ns8390wire",&eh);
1286: #endif /* DEBUG_TTD */
1287:
1288: ehp = (struct ether_header *) (&net_kmsg(new_kmsg)->header[0]);
1289: pkt = (struct packet_header *) (&net_kmsg(new_kmsg)->packet[0]);
1290:
1291: #if DEBUG_TTD
1292: printf("!ehp = 0x%x, pkt = 0x%x!",ehp, pkt);
1293: #endif /* DEBUG_TTD */
1294:
1295: *ehp = eh;
1296: if (len >
1297: (wrap_size = (is->sram + (is->pstop << 8) - sram_getdata_ptr))) {
1298: /* if needs to wrap */
1299: if (board_id & IFWD_SLOT_16BIT) {
1300: #if MACH_TTD
1301: if (!kttd_active)
1302: #endif /* MACH_TTD */
1303: { s = splhi(); }
1304:
1305: en_16bit_access(hdwbase, board_id);
1306: bcopy16 (sram_getdata_ptr, (char *) (pkt + 1),
1307: wrap_size);
1308: dis_16bit_access (hdwbase, board_id);
1309: #if MACH_TTD
1310: if (!kttd_active)
1311: #endif /* MACH_TTD */
1312: { splx(s); }
1313: } else {
1314: bcopy (sram_getdata_ptr, (char *) (pkt + 1),
1315: wrap_size);
1316: }
1317: sram_getdata_ptr = (volatile char *)
1318: (is->sram + (is->pstart << 8));
1319: } else { /* normal getting data from buffer */
1320: wrap_size = 0;
1321: }
1322: if (board_id & IFWD_SLOT_16BIT) {
1323: #if MACH_TTD
1324: if (!kttd_active)
1325: #endif /* MACH_TTD */
1326: { s = splhi(); }
1327: en_16bit_access(hdwbase, board_id);
1328: bcopy16 (sram_getdata_ptr,
1329: (char *) (pkt + 1) + wrap_size,
1330: len - wrap_size);
1331: dis_16bit_access (hdwbase, board_id);
1332: #if MACH_TTD
1333: if (!kttd_active)
1334: #endif /* MACH_TTD */
1335: { splx(s); }
1336: } else {
1337: bcopy (sram_getdata_ptr,
1338: (char *) (pkt + 1) + wrap_size,
1339: len - wrap_size);
1340: }
1341:
1342: pkt->type = ehp->ether_type;
1343: pkt->length = len + sizeof(struct packet_header);
1344:
1345: #if MACH_TTD
1346: /*
1347: * Don't want to call net_packet if we are polling
1348: * for a packet.
1349: */
1350: if (!kttd_active)
1351: #endif /* MACH_TTD */
1352: {
1353: /*
1354: * Hand the packet to the network module.
1355: */
1356: net_packet(ifp, new_kmsg, pkt->length,
1357: ethernet_priority(new_kmsg));
1358: }
1359:
1360: #else MACH_KERNEL
1361: #define NEW
1362: #ifdef NEW
1363: m = (struct mbuf *) 0;
1364: eh.ether_type = ntohs(eh.ether_type);
1365: MGET(m, M_DONTWAIT, MT_DATA);
1366: if (m == (struct mbuf *) 0) {
1367: printf("%s%d rcv(): Lost frame\n",
1368: ns8390_softc[unit].card, unit);
1369: ns8390lost_frame(unit); /* update NIC pointers and registers */
1370: return packets;
1371: }
1372: m->m_next = (struct mbuf *) 0;
1373: tm = m;
1374: m->m_len = MLEN;
1375: if (len > 2 * MLEN - sizeof (struct ifnet **)) {
1376: MCLGET(m);
1377: }
1378: *(mtod(tm, struct ifnet **)) = ifp;
1379: mlen = sizeof (struct ifnet **);
1380: bytes_in_mbuf = m->m_len - sizeof(struct ifnet **);
1381: mb_p = mtod(tm, u_char *) + sizeof (struct ifnet **);
1382: bytes = min(bytes_in_mbuf, len);
1383: remaining = (int) (is->sram + (is->pstop << 8) -
1384: sram_getdata_ptr);
1385: bytes = min(bytes, remaining);
1386: do {
1387: if (board_id & IFWD_SLOT_16BIT) {
1388: s = splhi();
1389: en_16bit_access(hdwbase, board_id);
1390: bcopy16 (sram_getdata_ptr, mb_p, bytes);
1391: dis_16bit_access (hdwbase, board_id);
1392: splx(s);
1393: } else {
1394: bcopy16 (sram_getdata_ptr, mb_p, bytes);
1395: }
1396:
1397: mlen += bytes;
1398:
1399: if (!(bytes_in_mbuf -= bytes)) {
1400: MGET(tm->m_next, M_DONTWAIT, MT_DATA);
1401: tm = tm->m_next;
1402: if (tm == (struct mbuf *)0) {
1403: printf("%s%d rcv(): No mbufs, lost frame\n",
1404: ns8390_softc[unit].card, unit);
1405: m_freem(m); /* free the mbuf chain */
1406: ns8390lost_frame(unit); /* update NIC pointers and registers */
1407: return;
1408: }
1409: mlen = 0;
1410: tm->m_len = MLEN;
1411: bytes_in_mbuf = MLEN;
1412: mb_p = mtod(tm, u_char *);
1413: } else
1414: mb_p += bytes;
1415:
1416: if (!(len -= bytes)) {
1417: tm->m_len = mlen;
1418: break;
1419: } else if (bytes == remaining) {
1420: sram_getdata_ptr = (volatile char *) (is->sram +
1421: (is->pstart << 8));
1422: bytes = len;
1423: remaining = ETHERMTU;
1424: } else {
1425: sram_getdata_ptr += bytes;
1426: remaining -= bytes;
1427: }
1428:
1429: bytes = min(bytes_in_mbuf, len);
1430: bytes = min(bytes, remaining);
1431: } while(1);
1432: #else NEW
1433: m = (struct mbuf *) 0;
1434: eh.ether_type = ntohs(eh.ether_type);
1435:
1436: while ( len ) {
1437: if (m == (struct mbuf *) 0) {
1438: m = m_get(M_DONTWAIT, MT_DATA);
1439: if (m == (struct mbuf *) 0) {
1440: printf("%s%d rcv(): Lost frame\n",
1441: ns8390_softc[unit].card, unit);
1442: ns8390lost_frame(unit); /* update NIC pointers and registers */
1443: return packets;
1444: }
1445: tm = m;
1446: tm->m_off = MMINOFF;
1447:
1448:
1449: /*
1450: * first mbuf in the packet must contain a pointer to the
1451: * ifnet structure. other mbufs that follow and make up
1452: * the packet do not need this pointer in the mbuf.
1453: *
1454: */
1455:
1456: *(mtod(tm, struct ifnet **)) = ifp;
1457: tm->m_len = sizeof(struct ifnet **);
1458:
1459: /* end of first buffer of packet */
1460: } else {
1461: tm->m_next = m_get(M_DONTWAIT, MT_DATA);
1462: tm = tm->m_next;
1463: if (tm == (struct mbuf *) 0) {
1464: printf("%s%d rcv(): No mbufs, lost frame\n",
1465: ns8390_softc[unit].card, unit);
1466: m_freem(m); /* free the mbuf chain */
1467: ns8390lost_frame(unit); /* update NIC pointers and registers */
1468: return packets;
1469: }
1470: tm->m_off = MMINOFF;
1471: tm->m_len = 0;
1472: }
1473:
1474: tlen = MIN( MLEN - tm->m_len, len);
1475: /* size of mbuf so you know how much you can copy from board */
1476: tm->m_next = (struct mbuf *) 0;
1477: if (sram_getdata_ptr + tlen >=
1478: (volatile char *) (is->sram + (is->pstop << 8))) {
1479: /* if needs to wrap */
1480: wrap_size = (int) (is->sram + (is->pstop << 8) -
1481: sram_getdata_ptr);
1482: if (board_id & IFWD_SLOT_16BIT) {
1483: s = splhi();
1484: en_16bit_access(hdwbase, board_id);
1485: bcopy16 (sram_getdata_ptr,
1486: mtod(tm, char*) + tm->m_len,
1487: wrap_size);
1488: dis_16bit_access (hdwbase, board_id);
1489: splx(s);
1490: } else {
1491: bcopy16 (sram_getdata_ptr,
1492: mtod(tm, char*) + tm->m_len,
1493: wrap_size);
1494: }
1495: tm->m_len += wrap_size;
1496: len -= wrap_size;
1497:
1498: sram_getdata_ptr = (volatile char *) (is->sram +
1499: (is->pstart << 8));
1500: } else { /* normal getting data from buffer */
1501: if (board_id & IFWD_SLOT_16BIT) {
1502: s = splhi();
1503: en_16bit_access(hdwbase, board_id);
1504: bcopy16 (sram_getdata_ptr,
1505: mtod(tm, char*) + tm->m_len,
1506: tlen);
1507: dis_16bit_access (hdwbase, board_id);
1508: splx(s);
1509: } else {
1510: bcopy16 (sram_getdata_ptr,
1511: mtod(tm, char*) + tm->m_len,
1512: tlen);
1513: }
1514: sram_getdata_ptr += tlen;
1515: tm->m_len += tlen;
1516: len -= tlen;
1517:
1518: }
1519: }
1520:
1521: #endif NEW
1522: if (!ns8390send_packet_up(m, &eh, is))
1523: m_freem(m);
1524: #ifdef IF_CNTRS
1525: ns_ein[log_2(pkt_size)]++;
1526: if (pkt_size < 128) ns_lin[(pkt_size)>>3]++;
1527:
1528: if (eh.ether_type == ETHERTYPE_ARP) {
1529: ns_arp++;
1530: if (ns_narp) {
1531: ns_ein[log_2(pkt_size)]--;
1532: if (pkt_size < 128) ns_lin[(pkt_size)>>3]--;
1533: }
1534: }
1535: #endif IF_CNTRS
1536: #endif MACH_KERNEL
1537:
1538: next_pkt:
1539: is->read_nxtpkt_ptr = *(sram_nxtpkt_ptr + 1);
1540: is->read_nxtpkt_ptr &= 0xFF;
1541:
1542: #if MACH_TTD
1543: if (!kttd_active)
1544: #endif /* MACH_TTD */
1545: {
1546: temp_cr = inb(nic+ds_cmd);
1547: outb(nic+ds_cmd, (temp_cr & 0x3f) | DSCM_PG0);
1548: }
1549:
1550: if (is->read_nxtpkt_ptr == ns8390get_CURR(unit))
1551: if (is->read_nxtpkt_ptr == is->pstart)
1552: outb(nic+ds0_bndy, is->pstop - 1);
1553: else
1554: outb(nic+ds0_bndy, is->read_nxtpkt_ptr - 1);
1555: else
1556: outb(nic+ds0_bndy, is->read_nxtpkt_ptr);
1557:
1558: #if MACH_TTD
1559: if (!kttd_active)
1560: #endif /* MACH_TTD */
1561: { outb(nic+ds_cmd, temp_cr); }
1562:
1563: #if MACH_TTD
1564: /*
1565: * Hand the packet back to the TTD server, if active.
1566: */
1567: if (kttd_active && pkt_size)
1568: return 1;
1569: #endif /* MACH_TTD */
1570:
1571:
1572: }
1573: return packets;
1574:
1575: }
1576:
1577: #ifdef MACH_KERNEL
1578: #if MACH_TTD
1579: /*
1580: * Polling routines for the TTD debugger.
1581: */
1582: int ns8390poll_receive(unit)
1583: int unit;
1584: {
1585: int s;
1586: int orig_cr;
1587: int orig_imr;
1588: int isr_status;
1589: int pkts;
1590:
1591: ttd_poll_loop = TRUE;
1592:
1593:
1594: /*
1595: * Should already in at splhigh. Is this necessary? XXX
1596: */
1597: s = splhigh();
1598:
1599: #if 0
1600: if (kttd_debug)
1601: printf("ns8390poll_receive: beginning polling loop\n");
1602: #endif /* DEBUG_TTD */
1603:
1604: /*
1605: * Loop until packet arrives.
1606: */
1607: while(ttd_poll_loop) {
1608:
1609: /*
1610: * Call intr routine
1611: */
1612:
1613: ns8390intr(unit);
1614: }
1615:
1616: #if 0
1617: if (kttd_debug)
1618: printf("ns8390poll_receive: got packet exiting loop\n");
1619: #endif /* DEBUG_TTD */
1620:
1621: splx(s);
1622: }
1623:
1624: int ns8390transmit_ttd(unit, packet, len)
1625: int unit;
1626: char * packet;
1627: int len;
1628: {
1629: ns8390_softc_t *is = &ns8390_softc[unit];
1630: caddr_t nic = is->nic;
1631: u_short count = 0; /* amount of data already copied */
1632: volatile char *sram_write_pkt;
1633: int board_id = is->board_id;
1634: caddr_t hdwbase = ns8390info[unit]->address;
1635: int s;
1636: int orig_cr;
1637: int orig_imr;
1638: int isr_status;
1639: boolean_t loop = TRUE;
1640:
1641: #if 0
1642: dump_ipudpbootp("Beg of xmit",packet);
1643: #endif
1644:
1645: s = splhigh();
1646:
1647: /* begining of physical address of transmition buffer */
1648:
1649: sram_write_pkt = is->sram + is->tpsr * 0x100;
1650:
1651: count = len;
1652: if (board_id & IFWD_SLOT_16BIT) {
1653: en_16bit_access(hdwbase, board_id);
1654: bcopy16 (packet, sram_write_pkt, count);
1655: dis_16bit_access (hdwbase, board_id);
1656: } else {
1657: bcopy (packet, sram_write_pkt, count);
1658: }
1659:
1660: while (count < ETHERMIN+sizeof(struct ether_header)) {
1661: *(sram_write_pkt + count) = 0;
1662: count++;
1663: }
1664: outb(nic+ds_cmd, DSCM_NODMA|DSCM_START|DSCM_PG0); /* select page 0 */
1665: outb(nic+ds0_tpsr, is->tpsr); /* xmt page start at 0 of RAM */
1666: outb(nic+ds0_tbcr1, count >> 8); /* upper byte of count */
1667: outb(nic+ds0_tbcr0, count & 0xFF); /* lower byte of count */
1668: outb(nic+ds_cmd, DSCM_TRANS|DSCM_NODMA|DSCM_START); /* start transmission */
1669:
1670: ns8390intr(unit);
1671:
1672: splx(s);
1673: }
1674: #endif /* MACH_TTD */
1675: #endif /* MACH_KERNEL */
1676:
1677: #ifdef MACH_KERNEL
1678: #else MACH_KERNEL
1679: /*
1680: * Send a packet composed of an mbuf chain to the higher levels
1681: *
1682: */
1683: ns8390send_packet_up(m, eh, is)
1684: struct mbuf *m;
1685: struct ether_header *eh;
1686: ns8390_softc_t *is;
1687: {
1688: register struct ifqueue *inq;
1689: spl_t opri;
1690:
1691: switch (eh->ether_type) {
1692: #ifdef INET
1693: case ETHERTYPE_IP:
1694: schednetisr(NETISR_IP);
1695: inq = &ipintrq;
1696: break;
1697: case ETHERTYPE_ARP:
1698: arpinput(&is->ns8390_ac, m);
1699: return(TRUE);
1700: #endif
1701: #ifdef NS
1702: case ETHERTYPE_NS:
1703: schednetisr(NETISR_NS);
1704: inq = &nsintrq;
1705: break;
1706: #endif
1707: default:
1708: return(FALSE);
1709: }
1710: opri = SPLNET();
1711: if (IF_QFULL(inq)) {
1712: IF_DROP(inq);
1713: splx(opri);
1714: return(FALSE);
1715: }
1716: IF_ENQUEUE(inq, m);
1717: splx(opri);
1718: return(TRUE);
1719: }
1720: #endif MACH_KERNEL
1721:
1722: /*
1723: * ns8390lost_frame:
1724: * this routine called by ns8390read after memory for mbufs could not be
1725: * allocated. It sets the boundary pointers and registers to the next
1726: * packet location.
1727: */
1728:
1729: ns8390lost_frame(unit)
1730: int unit;
1731: {
1732: ns8390_softc_t *is = &ns8390_softc[unit];
1733: caddr_t nic = is->nic;
1734: volatile char *sram_nxtpkt_ptr;
1735: int temp_cr;
1736:
1737:
1738:
1739: sram_nxtpkt_ptr = (volatile char *) (is->sram +
1740: (is->read_nxtpkt_ptr << 8));
1741:
1742: is->read_nxtpkt_ptr = *(sram_nxtpkt_ptr + 1);
1743: is->read_nxtpkt_ptr &= 0xFF;
1744:
1745: temp_cr = inb(nic+ds_cmd);
1746: outb(nic+ds_cmd, (temp_cr & 0x3f) | DSCM_PG0);
1747:
1748: /* update boundary register */
1749: if (is->read_nxtpkt_ptr == ns8390get_CURR(unit))
1750: if (is->read_nxtpkt_ptr == is->pstart)
1751: outb(nic+ds0_bndy, is->pstop - 1);
1752: else
1753: outb(nic+ds0_bndy, is->read_nxtpkt_ptr - 1);
1754: else
1755: outb(nic+ds0_bndy, is->read_nxtpkt_ptr);
1756:
1757: outb(nic+ds_cmd, temp_cr);
1758:
1759: return;
1760: }
1761:
1762: /*
1763: * ns8390get_CURR():
1764: *
1765: * Returns the value of the register CURR, which points to the next
1766: * available space for NIC to receive from network unto receive ring.
1767: *
1768: */
1769:
1770: int
1771: ns8390get_CURR(unit)
1772: int unit;
1773: {
1774: caddr_t nic = ns8390_softc[unit].nic;
1775: int temp_cr;
1776: int ret_val;
1777: spl_t s;
1778:
1779: s = SPLNET();
1780:
1781: temp_cr = inb(nic+ds_cmd); /* get current CR value */
1782: outb(nic+ds_cmd, ((temp_cr & 0x3F) | DSCM_PG1)); /* select page 1 registers */
1783: ret_val = inb(nic+ds1_curr); /* read CURR value */
1784: outb(nic+ds_cmd, temp_cr);
1785: splx(s);
1786: return (ret_val & 0xFF);
1787: }
1788:
1789: /*
1790: * ns8390xmt:
1791: *
1792: * This routine fills in the appropriate registers and memory
1793: * locations on the ns8390 board and starts the board off on
1794: * the transmit.
1795: *
1796: * input : board number of interest, and a pointer to the mbuf
1797: * output : board memory and registers are set for xfer and attention
1798: *
1799: */
1800:
1801: ns8390xmt(unit, m)
1802: int unit;
1803: #ifdef MACH_KERNEL
1804: io_req_t m;
1805: #else MACH_KERNEL
1806: struct mbuf *m;
1807: #endif MACH_KERNEL
1808: {
1809: ns8390_softc_t *is = &ns8390_softc[unit];
1810: caddr_t nic = is->nic;
1811: struct ether_header *eh;
1812: int i;
1813: int opri;
1814: u_short count = 0; /* amount of data already copied */
1815: volatile char *sram_write_pkt;
1816: int board_id = is->board_id;
1817: vm_offset_t hdwbase = ns8390info[unit]->address;
1818: spl_t s;
1819:
1820: #ifdef MACH_KERNEL
1821: #else MACH_KERNEL
1822: register struct mbuf *tm_p;
1823: #endif MACH_KERNEL
1824: /* begining of physical address of transmition buffer */
1825:
1826: sram_write_pkt = is->sram + is->tpsr * 0x100;
1827:
1828: #ifdef MACH_KERNEL
1829: count = m->io_count;
1830: if (board_id & IFWD_SLOT_16BIT) {
1831: s = splhi();
1832: en_16bit_access(hdwbase, board_id);
1833: bcopy16 (m->io_data, sram_write_pkt, count);
1834: dis_16bit_access (hdwbase, board_id);
1835: splx(s);
1836: } else {
1837: bcopy (m->io_data, sram_write_pkt, count);
1838: }
1839: #else MACH_KERNEL
1840: for(tm_p = m; tm_p != (struct mbuf *)0; tm_p = tm_p->m_next) {
1841: if (count + tm_p->m_len > ETHERMTU + sizeof (struct ether_header))
1842: break;
1843: if (tm_p->m_len == 0)
1844: continue;
1845: if (board_id & IFWD_SLOT_16BIT) {
1846: s = splhi();
1847: en_16bit_access(hdwbase, board_id);
1848: bcopy16 (mtod(tm_p, caddr_t),
1849: sram_write_pkt + count,
1850: tm_p->m_len);
1851: dis_16bit_access (hdwbase, board_id);
1852: splx(s);
1853: } else {
1854: bcopy16 (mtod(tm_p, caddr_t),
1855: sram_write_pkt + count,
1856: tm_p->m_len);
1857: }
1858: count += tm_p->m_len;
1859: }
1860: #ifdef IF_CNTRS
1861: ns_eout[log_2(count+4/*crc*/)]++;
1862: if (count < 128) ns_lout[(count+4/*crc*/)>>3]++;
1863: #endif IF_CNTRS
1864: #endif MACH_KERNEL
1865: while (count < ETHERMIN+sizeof(struct ether_header)) {
1866: *(sram_write_pkt + count) = 0;
1867: count++;
1868: }
1869:
1870: /* select page 0 */
1871: outb(nic+ds_cmd, DSCM_NODMA|DSCM_START|DSCM_PG0);
1872: outb(nic+ds0_tpsr, is->tpsr); /* xmt page start at 0 of RAM */
1873: outb(nic+ds0_tbcr1, count >> 8); /* upper byte of count */
1874: outb(nic+ds0_tbcr0, count & 0xFF); /* lower byte of count */
1875: /* start transmission */
1876: outb(nic+ds_cmd, DSCM_TRANS|DSCM_NODMA|DSCM_START);
1877:
1878: #ifdef MACH_KERNEL
1879: iodone(m);
1880: m=0;
1881: #else MACH_KERNEL
1882: /* If this is a broadcast packet, loop it back to rcv. */
1883: eh = mtod( m, struct ether_header *);
1884: for (i=0; ((i < 6) && (eh->ether_dhost[i] == 0xff)); i++) ;
1885: if (i == 6) {
1886: if (!ns8390send_packet_up(m, eh, is))
1887: m_freem(m);
1888: } else
1889: m_freem(m);
1890: #endif MACH_KERNEL
1891: return;
1892: }
1893:
1894: config_nic(unit)
1895: int unit;
1896: {
1897: ns8390_softc_t *is = &ns8390_softc[unit];
1898: caddr_t nic = is->nic;
1899: int i;
1900: int temp;
1901: int count = 0;
1902: spl_t s;
1903:
1904: /* soft reset and page 0 */
1905: outb (nic+ds_cmd, DSCM_PG0|DSCM_NODMA|DSCM_STOP);
1906:
1907: while ((!(inb (nic + ds0_isr) & DSIS_RESET)) && (count < 10000))
1908: count++;
1909: if (count == 10000) {
1910: printf("%s%d: config_nic(): would not reset.\n",
1911: ns8390_softc[unit].card, unit);
1912: }
1913:
1914: /* fifo depth | not loopback */
1915: temp = ((is->fifo_depth & 0x0c) << 3) | DSDC_BMS;
1916:
1917: /* word xfer select (16 bit cards ) */
1918: if (is->board_id & IFWD_SLOT_16BIT)
1919: temp |= DSDC_WTS;
1920:
1921: outb (nic+ds0_dcr, temp);
1922: outb (nic+ds0_tcr, 0);
1923: outb (nic+ds0_rcr, DSRC_MON); /* receive configuration register */
1924: /* recieve ring starts 2k into RAM */
1925: outb (nic+ds0_pstart, is->pstart);
1926: /* stop at last RAM buffer rcv location */
1927: outb (nic+ds0_pstop, is->pstop);
1928:
1929: /* boundary pointer for page 0 */
1930: outb (nic+ds0_bndy, is->pstart);
1931: s = SPLNET();
1932:
1933: /* maintain rst | sel page 1 */
1934: outb (nic+ds_cmd, DSCM_PG1|DSCM_NODMA|DSCM_STOP);
1935:
1936: /* internal next packet pointer */
1937: is->read_nxtpkt_ptr = is->pstart + 1;
1938:
1939: outb (nic+ds1_curr, is->read_nxtpkt_ptr); /* Current page register */
1940: for(i=0; i<ETHER_ADDR_SIZE; i++)
1941: outb (nic+ds1_par0+i, is->address[i]);
1942: for(i=0; i<8; i++)
1943: outb (nic+ds1_mar0+i, 0);
1944:
1945: outb (nic+ds_cmd, DSCM_PG0|DSCM_STOP|DSCM_NODMA);
1946: splx(s);
1947: outb (nic+ds0_isr, 0xff); /* clear all interrupt status bits */
1948: outb (nic+ds0_imr, imr_hold); /* Enable interrupts */
1949: outb (nic+ds0_rbcr0, 0); /* clear remote byte count */
1950: outb (nic+ds0_rbcr1, 0);
1951:
1952: /* start NIC | select page 0 */
1953: outb (nic+ds_cmd, DSCM_PG0|DSCM_START|DSCM_NODMA);
1954:
1955: outb (nic+ds0_rcr, DSRC_AB); /* receive configuration register */
1956:
1957: return TRUE;
1958: }
1959:
1960: /*
1961: * config_ns8390:
1962: *
1963: * This routine does a standard config of a wd8003 family board, with
1964: * the proper modifications to different boards within this family.
1965: *
1966: */
1967: config_wd8003(unit)
1968: int unit;
1969: {
1970: ns8390_softc_t *is = &ns8390_softc[unit];
1971: vm_offset_t hdwbase = ns8390info[unit]->address;
1972: int i;
1973: int RAMsize;
1974: volatile char *RAMbase;
1975: int addr_temp;
1976:
1977: is->tpsr = 0; /* transmit page start hold */
1978: is->pstart = 0x06; /* receive page start hold */
1979: is->read_nxtpkt_ptr = is->pstart + 1; /* internal next packet pointer */
1980: is->fifo_depth = 0x08; /* NIC fifo threshold */
1981: switch (is->board_id & IFWD_RAM_SIZE_MASK) {
1982: case IFWD_RAM_SIZE_8K:
1983: RAMsize = 0x2000; break;
1984: case IFWD_RAM_SIZE_16K:
1985: RAMsize = 0x4000; break;
1986: case IFWD_RAM_SIZE_32K:
1987: RAMsize = 0x8000; break;
1988: case IFWD_RAM_SIZE_64K:
1989: RAMsize = 0x10000; break;
1990: default:
1991: RAMsize = 0x2000; break;
1992: }
1993: is->pstop = (((int)RAMsize >> 8) & 0x0ff); /* rcv page stop hold */
1994: RAMbase = (volatile char *)ns8390info[unit]->phys_address;
1995: addr_temp = ((int)(RAMbase) >> 13) & 0x3f; /* convert to be written to MSR */
1996: outb(hdwbase+IFWD_MSR, addr_temp | IFWD_MENB); /* initialize MSR */
1997: /* enable 16 bit access from lan controller */
1998: if (is->board_id & IFWD_SLOT_16BIT) {
1999: if (is->board_id & IFWD_INTERFACE_CHIP) {
2000: outb(hdwbase+IFWD_REG_5,
2001: (inb(hdwbase + IFWD_REG_5) & IFWD_REG5_MEM_MASK) |
2002: IFWD_LAN16ENB);
2003: } else {
2004: outb(hdwbase+IFWD_REG_5, (IFWD_LAN16ENB | IFWD_LA19));
2005: }
2006: }
2007: /*
2008: outb(hdwbase+LAAR, LAN16ENB | LA19| MEM16ENB | SOFTINT);
2009: */
2010:
2011: return TRUE;
2012: }
2013:
2014: /*
2015: * config_ns8390:
2016: *
2017: * This routine does a standard config of a 3 com etherlink II board.
2018: *
2019: */
2020: int
2021: config_3c503(unit)
2022: int unit;
2023: {
2024: ns8390_softc_t *is = &ns8390_softc[unit];
2025: struct bus_device *dev = ns8390info[unit];
2026: vm_offset_t hdwbase = dev->address;
2027: int RAMsize = dev->am;
2028: int i;
2029:
2030: is->tpsr = 0x20; /* transmit page start hold */
2031: is->sram = (char *)phystokv(dev->phys_address) - is->tpsr * 0x100;
2032: /* When NIC says page 20, this means go to
2033: the beginning of the sram range */
2034: is->pstart = 0x26; /* receive page start hold */
2035: is->read_nxtpkt_ptr = is->pstart + 1; /* internal next packet pointer */
2036: is->fifo_depth = 0x08; /* NIC fifo threshold */
2037: is->pstop = is->tpsr + ((RAMsize >> 8) & 0x0ff); /* rcv page stop hold */
2038:
2039: outb(hdwbase+CTLR, CTLR_RST|CTLR_THIN);
2040: outb(hdwbase+CTLR, CTLR_THIN);
2041: outb(hdwbase+CTLR, CTLR_STA_ADDR|CTLR_THIN);
2042: for (i = 0; i < 6; i++)
2043: is->address[i] = inb(hdwbase+i);
2044: outb(hdwbase+CTLR, elii_bnc[is->board_id]?CTLR_THIN:CTLR_THICK);
2045: outb(hdwbase+PSTR, is->pstart);
2046: outb(hdwbase+PSPR, is->pstop);
2047: outb(hdwbase+IDCFR, IDCFR_IRQ2 << (elii_irq[is->board_id] - 2));
2048: outb(hdwbase+GACFR, GACFR_TCM|GACFR_8K);
2049: /* BCFR & PCRFR ro */
2050: /* STREG ro & dma */
2051: outb(hdwbase+DQTR, 0);
2052: outb(hdwbase+DAMSB, 0);
2053: outb(hdwbase+DALSB, 0);
2054: outb(hdwbase+VPTR2, 0);
2055: outb(hdwbase+VPTR1, 0);
2056: outb(hdwbase+VPTR0, 0);
2057: outb(hdwbase+RFMSB, 0);
2058: outb(hdwbase+RFLSB, 0);
2059: return TRUE;
2060: }
2061:
2062: /*
2063: * ns8390intoff:
2064: *
2065: * This function turns interrupts off for the ns8390 board indicated.
2066: *
2067: */
2068: void
2069: ns8390intoff(unit)
2070: int unit;
2071: {
2072: caddr_t nic = ns8390_softc[unit].nic;
2073: int temp_cr = inb(nic+ds_cmd); /* get current CR value */
2074:
2075: outb(nic+ds_cmd,((temp_cr & 0x3F)|DSCM_PG0|DSCM_STOP));
2076: outb(nic+ds0_imr, 0); /* Interrupt Mask Register */
2077: outb(nic+ds_cmd, temp_cr|DSCM_STOP);
2078:
2079: }
2080:
2081:
2082: /*
2083: * wd80xxget_board_id:
2084: *
2085: * determine which board is being used.
2086: * Currently supports:
2087: * wd8003E (tested)
2088: * wd8003EBT
2089: * wd8003EP (tested)
2090: * wd8013EP (tested)
2091: *
2092: */
2093: wd80xxget_board_id(dev)
2094: struct bus_device *dev;
2095: {
2096: vm_offset_t hdwbase = dev->address;
2097: long unit = dev->unit;
2098: long board_id = 0;
2099: int reg_temp;
2100: int rev_num; /* revision number */
2101: int ram_flag;
2102: int intr_temp;
2103: int i;
2104: boolean_t register_aliasing;
2105:
2106: rev_num = (inb(hdwbase + IFWD_BOARD_ID) & IFWD_BOARD_REV_MASK) >> 1;
2107: printf("%s%d: ", ns8390_softc[unit].card, unit);
2108:
2109: if (rev_num == 0) {
2110: printf("rev 0x00\n");
2111: /* It must be 8000 board */
2112: return 0;
2113: }
2114:
2115: /* Check if register aliasing is true, that is reading from register
2116: offsets 0-7 will return the contents of register offsets 8-f */
2117:
2118: register_aliasing = TRUE;
2119: for (i = 1; i < 5; i++) {
2120: if (inb(hdwbase + IFWD_REG_0 + i) !=
2121: inb(hdwbase + IFWD_LAR_0 + i))
2122: register_aliasing = FALSE;
2123: }
2124: if (inb(hdwbase + IFWD_REG_7) != inb(hdwbase + IFWD_CHKSUM))
2125: register_aliasing = FALSE;
2126:
2127:
2128: if (register_aliasing == FALSE) {
2129: /* Check if board has interface chip */
2130:
2131: reg_temp = inb(hdwbase + IFWD_REG_7); /* save old */
2132: outb(hdwbase + IFWD_REG_7, 0x35); /* write value */
2133: inb(hdwbase + IFWD_REG_0); /* dummy read */
2134: if ((inb(hdwbase + IFWD_REG_7) & 0xff) == 0x35) {
2135: outb(hdwbase + IFWD_REG_7, 0x3a);/* Try another value*/
2136: inb(hdwbase + IFWD_REG_0); /* dummy read */
2137: if ((inb(hdwbase + IFWD_REG_7) & 0xff) == 0x3a) {
2138: board_id |= IFWD_INTERFACE_CHIP;
2139: outb(hdwbase + IFWD_REG_7, reg_temp);
2140: /* restore old value */
2141: }
2142: }
2143:
2144: /* Check if board is 16 bit by testing if bit zero in
2145: register 1 is unchangeable by software. If so then
2146: card has 16 bit capability */
2147: reg_temp = inb(hdwbase + IFWD_REG_1);
2148: outb(hdwbase + IFWD_REG_1, reg_temp ^ IFWD_16BIT);
2149: inb(hdwbase + IFWD_REG_0); /* dummy read */
2150: if ((inb(hdwbase + IFWD_REG_1) & IFWD_16BIT) ==
2151: (reg_temp & IFWD_16BIT)) { /* Is bit unchanged */
2152: board_id |= IFWD_BOARD_16BIT; /* Yes == 16 bit */
2153: reg_temp &= 0xfe; /* For 16 bit board
2154: always reset bit 0 */
2155: }
2156: outb(hdwbase + IFWD_REG_1, reg_temp); /* write value back */
2157:
2158: /* Test if 16 bit card is in 16 bit slot by reading bit zero in
2159: register 1. */
2160: if (board_id & IFWD_BOARD_16BIT) {
2161: if (inb(hdwbase + IFWD_REG_1) & IFWD_16BIT) {
2162: board_id |= IFWD_SLOT_16BIT;
2163: }
2164: }
2165: }
2166:
2167: /* Get media type */
2168:
2169: if (inb(hdwbase + IFWD_BOARD_ID) & IFWD_MEDIA_TYPE) {
2170: board_id |= IFWD_ETHERNET_MEDIA;
2171: } else if (rev_num == 1) {
2172: board_id |= IFWD_STARLAN_MEDIA;
2173: } else {
2174: board_id |= IFWD_TWISTED_PAIR_MEDIA;
2175: }
2176:
2177: if (rev_num == 2) {
2178: if (inb(hdwbase + IFWD_BOARD_ID) & IFWD_SOFT_CONFIG) {
2179: if ((board_id & IFWD_STATIC_ID_MASK) == WD8003EB ||
2180: (board_id & IFWD_STATIC_ID_MASK) == WD8003W) {
2181: board_id |= IFWD_ALTERNATE_IRQ_BIT;
2182: }
2183: }
2184: /* Check for memory size */
2185:
2186: ram_flag = inb(hdwbase + IFWD_BOARD_ID) & IFWD_MEMSIZE;
2187:
2188: switch (board_id & IFWD_STATIC_ID_MASK) {
2189: case WD8003E: /* same as WD8003EBT */
2190: case WD8003S: /* same as WD8003SH */
2191: case WD8003WT:
2192: case WD8003W:
2193: case WD8003EB: /* same as WD8003EP */
2194: if (ram_flag)
2195: board_id |= IFWD_RAM_SIZE_32K;
2196: else
2197: board_id |= IFWD_RAM_SIZE_8K;
2198: break;
2199: case WD8003ETA:
2200: case WD8003STA:
2201: case WD8003EA:
2202: case WD8003SHA:
2203: case WD8003WA:
2204: board_id |= IFWD_RAM_SIZE_16K;
2205: break;
2206: case WD8013EBT:
2207: if (board_id & IFWD_SLOT_16BIT) {
2208: if (ram_flag)
2209: board_id |= IFWD_RAM_SIZE_64K;
2210: else
2211: board_id |= IFWD_RAM_SIZE_16K;
2212: } else {
2213: if (ram_flag)
2214: board_id |= IFWD_RAM_SIZE_32K;
2215: else
2216: board_id |= IFWD_RAM_SIZE_8K;
2217: }
2218: break;
2219: default:
2220: board_id |= IFWD_RAM_SIZE_UNKNOWN;
2221: break;
2222: }
2223: } else if (rev_num >= 3) {
2224: board_id &= (long) ~IFWD_MEDIA_MASK; /* remove media info */
2225: board_id |= IFWD_INTERFACE_584_CHIP;
2226: board_id |= wd80xxget_eeprom_info(hdwbase, board_id);
2227: } else {
2228: /* Check for memory size */
2229: if (board_id & IFWD_BOARD_16BIT) {
2230: if (board_id & IFWD_SLOT_16BIT)
2231: board_id |= IFWD_RAM_SIZE_16K;
2232: else
2233: board_id |= IFWD_RAM_SIZE_8K;
2234: } else if (board_id & IFWD_MICROCHANNEL)
2235: board_id |= IFWD_RAM_SIZE_16K;
2236: else if (board_id & IFWD_INTERFACE_CHIP) {
2237: if (inb(hdwbase + IFWD_REG_1) & IFWD_MEMSIZE)
2238: board_id |= IFWD_RAM_SIZE_32K;
2239: else
2240: board_id |= IFWD_RAM_SIZE_8K;
2241: } else
2242: board_id |= IFWD_RAM_SIZE_UNKNOWN;
2243:
2244: /* No support for 690 chip yet. It should be checked here */
2245: }
2246:
2247: switch (board_id & IFWD_STATIC_ID_MASK) {
2248: case WD8003E: printf("WD8003E or WD8003EBT"); break;
2249: case WD8003S: printf("WD8003S or WD8003SH"); break;
2250: case WD8003WT: printf("WD8003WT"); break;
2251: case WD8003W: printf("WD8003W"); break;
2252: case WD8003EB:
2253: if (board_id & IFWD_INTERFACE_584_CHIP)
2254: printf("WD8003EP");
2255: else
2256: printf("WD8003EB");
2257: break;
2258: case WD8003EW: printf("WD8003EW"); break;
2259: case WD8003ETA: printf("WD8003ETA"); break;
2260: case WD8003STA: printf("WD8003STA"); break;
2261: case WD8003EA: printf("WD8003EA"); break;
2262: case WD8003SHA: printf("WD8003SHA"); break;
2263: case WD8003WA: printf("WD8003WA"); break;
2264: case WD8013EBT: printf("WD8013EBT"); break;
2265: case WD8013EB:
2266: if (board_id & IFWD_INTERFACE_584_CHIP)
2267: printf("WD8013EP");
2268: else
2269: printf("WD8013EB");
2270: break;
2271: case WD8013W: printf("WD8013W"); break;
2272: case WD8013EW: printf("WD8013EW"); break;
2273: default: printf("unknown"); break;
2274: }
2275: printf(" rev 0x%02x", rev_num);
2276: switch(board_id & IFWD_RAM_SIZE_RES_7) {
2277: case IFWD_RAM_SIZE_UNKNOWN:
2278: break;
2279: case IFWD_RAM_SIZE_8K:
2280: printf(" 8 kB ram");
2281: break;
2282: case IFWD_RAM_SIZE_16K:
2283: printf(" 16 kB ram");
2284: break;
2285: case IFWD_RAM_SIZE_32K:
2286: printf(" 32 kB ram");
2287: break;
2288: case IFWD_RAM_SIZE_64K:
2289: printf(" 64 kB ram");
2290: break;
2291: default:
2292: printf("wd: Internal error ram size value invalid %d\n",
2293: (board_id & IFWD_RAM_SIZE_RES_7)>>16);
2294: }
2295:
2296: if (board_id & IFWD_BOARD_16BIT) {
2297: if (board_id & IFWD_SLOT_16BIT) {
2298: printf(", in 16 bit slot");
2299: } else {
2300: printf(", 16 bit board in 8 bit slot");
2301: }
2302: }
2303: if (board_id & IFWD_INTERFACE_CHIP) {
2304: if (board_id & IFWD_INTERFACE_584_CHIP) {
2305: printf(", 584 chip");
2306: } else {
2307: printf(", 583 chip");
2308: }
2309: }
2310: if ((board_id & IFWD_INTERFACE_CHIP) == IFWD_INTERFACE_CHIP) {
2311: /* program the WD83C583 EEPROM registers */
2312: int irr_temp, icr_temp;
2313:
2314: icr_temp = inb(hdwbase + IFWD_ICR);
2315: irr_temp = inb(hdwbase + IFWD_IRR);
2316:
2317: irr_temp &= ~(IFWD_IR0 | IFWD_IR1);
2318: irr_temp |= IFWD_IEN;
2319:
2320: icr_temp &= IFWD_WTS;
2321:
2322: if (!(board_id & IFWD_INTERFACE_584_CHIP)) {
2323: icr_temp |= IFWD_DMAE | IFWD_IOPE;
2324: if (ram_flag)
2325: icr_temp |= IFWD_MSZ;
2326: }
2327:
2328: if (board_id & IFWD_INTERFACE_584_CHIP) {
2329: switch(ns8390info[unit]->sysdep1) {
2330: case 10:
2331: icr_temp |= IFWD_DMAE;
2332: break;
2333: case 2:
2334: case 9: /* Same as 2 */
2335: break;
2336: case 11:
2337: icr_temp |= IFWD_DMAE;
2338: /*FALLTHROUGH*/
2339: case 3:
2340: irr_temp |= IFWD_IR0;
2341: break;
2342: case 15:
2343: icr_temp |= IFWD_DMAE;
2344: /*FALLTHROUGH*/
2345: case 5:
2346: irr_temp |= IFWD_IR1;
2347: break;
2348: case 4:
2349: icr_temp |= IFWD_DMAE;
2350: /*FALLTHROUGH*/
2351: case 7:
2352: irr_temp |= IFWD_IR0 | IFWD_IR1;
2353: break;
2354: default:
2355: printf("%s%d: wd80xx_get_board_id(): Could not set Interrupt Request Register according to pic(%d).\n",
2356: ns8390_softc[unit].card, unit,
2357: ns8390info[unit]->sysdep1);
2358: break;
2359: }
2360: } else {
2361: switch(ns8390info[unit]->sysdep1) {
2362: /* attempt to set interrupt according to assigned pic */
2363: case 2:
2364: case 9: /* Same as 2 */
2365: break;
2366: case 3:
2367: irr_temp |= IFWD_IR0;
2368: break;
2369: case 4:
2370: irr_temp |= IFWD_IR1;
2371: break;
2372: case 5:
2373: irr_temp |= IFWD_IR1 | IFWD_AINT;
2374: break;
2375: case 7:
2376: irr_temp |= IFWD_IR0 | IFWD_IR1;
2377: break;
2378: default:
2379: printf("%s%d: wd80xx_get_board_id(): Could not set Interrupt Request Register according to pic(%d).\n",
2380: ns8390_softc[unit].card, unit,
2381: ns8390info[unit]->sysdep1);
2382: }
2383: }
2384: outb(hdwbase + IFWD_IRR, irr_temp);
2385: outb(hdwbase + IFWD_ICR, icr_temp);
2386: }
2387: printf("\n");
2388: return (board_id);
2389: }
2390:
2391: wd80xxget_eeprom_info(hdwbase, board_id)
2392: caddr_t hdwbase;
2393: long board_id;
2394: {
2395: unsigned long new_bits = 0;
2396: int reg_temp;
2397:
2398: outb(hdwbase + IFWD_REG_1,
2399: ((inb(hdwbase + IFWD_REG_1) & IFWD_ICR_MASK) | IFWD_OTHER_BIT));
2400: outb(hdwbase + IFWD_REG_3,
2401: ((inb(hdwbase + IFWD_REG_3) & IFWD_EAR_MASK) | IFWD_ENGR_PAGE));
2402: outb(hdwbase + IFWD_REG_1,
2403: ((inb(hdwbase + IFWD_REG_1) & IFWD_ICR_MASK) |
2404: (IFWD_RLA | IFWD_OTHER_BIT)));
2405: while (inb(hdwbase + IFWD_REG_1) & IFWD_RECALL_DONE_MASK)
2406: ;
2407:
2408: reg_temp = inb(hdwbase + IFWD_EEPROM_1);
2409: switch (reg_temp & IFWD_EEPROM_BUS_TYPE_MASK) {
2410: case IFWD_EEPROM_BUS_TYPE_AT:
2411: if (wd_debug & 1) printf("wd: AT bus, ");
2412: break;
2413: case IFWD_EEPROM_BUS_TYPE_MCA:
2414: if (wd_debug & 1) printf("wd: MICROCHANNEL, ");
2415: new_bits |= IFWD_MICROCHANNEL;
2416: break;
2417: default:
2418: break;
2419: }
2420: switch (reg_temp & IFWD_EEPROM_BUS_SIZE_MASK) {
2421: case IFWD_EEPROM_BUS_SIZE_8BIT:
2422: if (wd_debug & 1) printf("8 bit bus size, ");
2423: break;
2424: case IFWD_EEPROM_BUS_SIZE_16BIT:
2425: if (wd_debug & 1) printf("16 bit bus size ");
2426: new_bits |= IFWD_BOARD_16BIT;
2427: if (inb(hdwbase + IFWD_REG_1) & IFWD_16BIT) {
2428: new_bits |= IFWD_SLOT_16BIT;
2429: if (wd_debug & 1)
2430: printf("in 16 bit slot, ");
2431: } else {
2432: if (wd_debug & 1)
2433: printf("in 8 bit slot (why?), ");
2434: }
2435: break;
2436: default:
2437: if (wd_debug & 1) printf("bus size other than 8 or 16 bit, ");
2438: break;
2439: }
2440: reg_temp = inb(hdwbase + IFWD_EEPROM_0);
2441: switch (reg_temp & IFWD_EEPROM_MEDIA_MASK) {
2442: case IFWD_STARLAN_TYPE:
2443: if (wd_debug & 1) printf("Starlan media, ");
2444: new_bits |= IFWD_STARLAN_MEDIA;
2445: break;
2446: case IFWD_TP_TYPE:
2447: if (wd_debug & 1) printf("Twisted pair media, ");
2448: new_bits |= IFWD_TWISTED_PAIR_MEDIA;
2449: break;
2450: case IFWD_EW_TYPE:
2451: if (wd_debug & 1) printf("Ethernet and twisted pair media, ");
2452: new_bits |= IFWD_EW_MEDIA;
2453: break;
2454: case IFWD_ETHERNET_TYPE: /*FALLTHROUGH*/
2455: default:
2456: if (wd_debug & 1) printf("ethernet media, ");
2457: new_bits |= IFWD_ETHERNET_MEDIA;
2458: break;
2459: }
2460: switch (reg_temp & IFWD_EEPROM_IRQ_MASK) {
2461: case IFWD_ALTERNATE_IRQ_1:
2462: if (wd_debug & 1) printf("Alternate irq 1\n");
2463: new_bits |= IFWD_ALTERNATE_IRQ_BIT;
2464: break;
2465: default:
2466: if (wd_debug & 1) printf("\n");
2467: break;
2468: }
2469: switch (reg_temp & IFWD_EEPROM_RAM_SIZE_MASK) {
2470: case IFWD_EEPROM_RAM_SIZE_8K:
2471: new_bits |= IFWD_RAM_SIZE_8K;
2472: break;
2473: case IFWD_EEPROM_RAM_SIZE_16K:
2474: if ((new_bits & IFWD_BOARD_16BIT) && (new_bits & IFWD_SLOT_16BIT))
2475: new_bits |= IFWD_RAM_SIZE_16K;
2476: else
2477: new_bits |= IFWD_RAM_SIZE_8K;
2478: break;
2479: case IFWD_EEPROM_RAM_SIZE_32K:
2480: new_bits |= IFWD_RAM_SIZE_32K;
2481: break;
2482: case IFWD_EEPROM_RAM_SIZE_64K:
2483: if ((new_bits & IFWD_BOARD_16BIT) && (new_bits & IFWD_SLOT_16BIT))
2484: new_bits |= IFWD_RAM_SIZE_64K;
2485: else
2486: new_bits |= IFWD_RAM_SIZE_32K;
2487: break;
2488: default:
2489: new_bits |= IFWD_RAM_SIZE_UNKNOWN;
2490: break;
2491: }
2492: outb(hdwbase + IFWD_REG_1,
2493: ((inb(hdwbase + IFWD_REG_1) & IFWD_ICR_MASK) | IFWD_OTHER_BIT));
2494: outb(hdwbase + IFWD_REG_3,
2495: ((inb(hdwbase + IFWD_REG_3) & IFWD_EAR_MASK) | IFWD_EA6));
2496: outb(hdwbase + IFWD_REG_1,
2497: ((inb(hdwbase + IFWD_REG_1) & IFWD_ICR_MASK) | IFWD_RLA));
2498: return (new_bits);
2499: }
2500:
2501: wdpr(unit)
2502: {
2503: caddr_t nic = ns8390_softc[unit].nic;
2504: spl_t s;
2505: int temp_cr;
2506:
2507: s = SPLNET();
2508: temp_cr = inb(nic+ds_cmd); /* get current CR value */
2509:
2510: printf("CR %x, BNDRY %x, TSR %x, NCR %x, FIFO %x, ISR %x, RSR %x\n",
2511: inb(nic+0x0), inb(nic+0x3), inb(nic+0x4), inb(nic+0x5),
2512: inb(nic+0x6), inb(nic+0x7), inb(nic+0xc));
2513: printf("CLD %x:%x, CRD %x:%x, FR %x, CRC %x, Miss %x\n",
2514: inb(nic+0x1), inb(nic+0x2),
2515: inb(nic+0x8), inb(nic+0x9),
2516: inb(nic+0xd), inb(nic+0xe), inb(nic+0xf));
2517:
2518:
2519: outb(nic, (temp_cr&0x3f)|DSCM_PG1); /* page 1 CR value */
2520: printf("PHYS %x:%x:%x:%x:%x CUR %x\n",
2521: inb(nic+0x1), inb(nic+0x2), inb(nic+0x3),
2522: inb(nic+0x4), inb(nic+0x5), inb(nic+0x6),
2523: inb(nic+0x7));
2524: printf("MAR %x:%x:%x:%x:%x:%x:%x:%x\n",
2525: inb(nic+0x8), inb(nic+0x9), inb(nic+0xa), inb(nic+0xb),
2526: inb(nic+0xc), inb(nic+0xd), inb(nic+0xe), inb(nic+0xf));
2527: outb(nic, temp_cr); /* restore current CR value */
2528: splx(s);
2529: }
2530:
2531:
2532: /*
2533: This sets bit 7 (0 justified) of register offset 0x05. It will enable
2534: the host to access shared RAM 16 bits at a time. It will also maintain
2535: the LAN16BIT bit high in addition, this routine maintains address bit 19
2536: (previous cards assumed this bit high...we must do it manually)
2537:
2538: note 1: this is a write only register
2539: note 2: this routine should be called only after interrupts are disabled
2540: and they should remain disabled until after the routine 'dis_16bit_access'
2541: is called
2542: */
2543:
2544: en_16bit_access (hdwbase, board_id)
2545: caddr_t hdwbase;
2546: long board_id;
2547: {
2548: if (board_id & IFWD_INTERFACE_CHIP)
2549: outb(hdwbase+IFWD_REG_5,
2550: (inb(hdwbase+IFWD_REG_5) & IFWD_REG5_MEM_MASK)
2551: | IFWD_MEM16ENB | IFWD_LAN16ENB);
2552: else
2553: outb(hdwbase+IFWD_REG_5, (IFWD_MEM16ENB | IFWD_LAN16ENB |
2554: IFWD_LA19));
2555: }
2556:
2557: /*
2558: This resets bit 7 (0 justified) of register offset 0x05. It will disable
2559: the host from accessing shared RAM 16 bits at a time. It will maintain the
2560: LAN16BIT bit high in addition, this routine maintains address bit 19
2561: (previous cards assumed this bit high...we must do it manually)
2562:
2563: note: this is a write only register
2564: */
2565:
2566: dis_16bit_access (hdwbase, board_id)
2567: caddr_t hdwbase;
2568: long board_id;
2569: {
2570: if (board_id & IFWD_INTERFACE_CHIP)
2571: outb(hdwbase+IFWD_REG_5,
2572: ((inb(hdwbase+IFWD_REG_5) & IFWD_REG5_MEM_MASK) |
2573: IFWD_LAN16ENB));
2574: else
2575: outb(hdwbase+IFWD_REG_5, (IFWD_LAN16ENB | IFWD_LA19));
2576: }
2577:
2578: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.