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