1 /*
2 * Mach Operating System
3 * Copyright (c) 1993,1992,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.23 93/11/17 16:47:47 dbg
30 * Changed HZ to hz. Removed non-MACH_KERNEL code.
31 * [93/05/24 dbg]
32 *
33 * Revision 2.22 93/05/10 23:24:07 rvb
34 * Added TTD teledebug code to use the ns8390 as a remote ethernet
35 * debugging device.
36 * [93/03/01 grm]
37 *
38 * Revision 2.21 93/05/10 21:19:20 rvb
39 * Lint.
40 * [93/05/08 11:20:50 af]
41 *
42 * Revision 2.20 93/01/24 13:17:18 danner
43 * Sigh! Sometimes the reported length of the packet is zero. But
44 * the rest of the chain looked OK. So we'll just skip the packet.
45 * [92/10/27 rvb]
46 *
47 * Revision 2.19 93/01/14 17:30:37 danner
48 * Proper spl typing.
49 * [92/11/30 af]
50 *
51 * Revision 2.18 92/08/03 17:17:43 jfriedl
52 * Fixed bug in wd80xxget_board_id, that made the machine hang on
53 * reboot when using wd8013EP boards.
54 * [92/07/13 kivinen]
55 *
56 * Revision 2.17 92/07/09 22:54:18 rvb
57 * Say whether EtherLink II is thick or thin.
58 * [92/06/18 rvb]
59 *
60 * Revision 2.16 92/04/03 12:15:19 rpd
61 * Use port 0x250, 0x350 for irq 5 bnc, thick respectively.
62 * [92/04/02 rvb]
63 *
64 * Revision 2.15 92/02/19 15:08:22 elf
65 * Made wd driver work with 16 bit cards. Better recognize different
66 * cards. Print card name when probing. Tested on wd8003, wd8013EP,
67 * wd8003EP.
68 * Add IFWD_ prefix to defines.
69 * [92/01/20 kivinen]
70 *
71 * Revision 2.14 91/11/12 11:09:39 rvb
72 * Undo "strict" wrong change to probe()
73 * [91/10/25 rvb]
74 *
75 * Revision 2.13 91/10/09 16:07:43 af
76 * Fixes from 2.5 (from rvb), made sure two WD boards work (with
77 * help from jeffreyh).
78 *
79 * Revision 2.12 91/08/24 11:58:01 af
80 * New MI autoconf.
81 * [91/08/02 02:55:17 af]
82 *
83 * Revision 2.11 91/05/14 16:24:56 mrt
84 * Correcting copyright
85 *
86 * Revision 2.10 91/05/13 06:02:41 af
87 * Made code under CMUCS standard.
88 * [91/05/12 15:50:35 af]
89 *
90 * Revision 2.9 91/03/16 14:46:23 rpd
91 * Changed net_filter to net_packet.
92 * [91/01/15 rpd]
93 *
94 * Revision 2.8 91/02/14 14:42:44 mrt
95 * Distinguish EtherLinkII vs WD8003 on open. Get packet
96 * size right for statistics. Fix 3.0 buf that sometimes
97 * reported packets too large.
98 * [91/01/28 15:31:22 rvb]
99 *
100 * Revision 2.7 91/02/05 17:17:52 mrt
101 * Changed to new Mach copyright
102 * [91/02/01 17:44:04 mrt]
103 *
104 * Revision 2.6 91/01/09 16:07:19 rpd
105 * Fixed typo in ns8390probe.
106 * [91/01/09 rpd]
107 *
108 * Revision 2.5 91/01/08 17:35:46 rpd
109 * Changed NET_KMSG_GET to net_kmsg_get.
110 * [91/01/08 rpd]
111 *
112 * Revision 2.4 91/01/08 17:33:05 rpd
113 * A few bug fixes.
114 * [91/01/08 16:41:04 rvb]
115 *
116 * Make this a generic driver for ns8390 from wd8003 because
117 * we now will also support etherlink ii.
118 * [91/01/04 12:25:21 rvb]
119 *
120 * Revision 2.1.1.7 90/11/27 13:43:18 rvb
121 * Synched 2.5 & 3.0 at I386q (r2.1.1.7) & XMK35 (r2.3)
122 * [90/11/15 rvb]
123 *
124 * Revision 2.2 90/10/01 14:23:09 jeffreyh
125 * Changes for MACH_KERNEL.
126 * initial checkin.
127 * [90/09/27 18:22:09 jeffreyh]
128 *
129 * Revision 2.1.1.6 90/09/18 08:38:39 rvb
130 * Unfortunately, the switches to bank 0 seem necessary so are back
131 * in.
132 * [90/09/08 rvb]
133 *
134 * Revision 2.1.1.5 90/08/25 15:42:58 rvb
135 * Use take_<>_irq() vs direct manipulations of ivect and friends.
136 * [90/08/20 rvb]
137 *
138 * Flush unnecessary switches to bank 0. Use error counters
139 * vs printouts. Fix DSF_RUNNING. Some more cleanup.
140 * [90/08/14 rvb]
141 *
142 * Revision 2.1.1.4 90/07/28 10:00:40 rvb
143 * Get correct counter offsets
144 *
145 * Revision 2.1.1.3 90/07/27 17:16:05 rvb
146 * No multicast for now.
147 *
148 * Revision 2.1.1.2 90/07/27 11:25:11 rvb
149 * Add boardID support for wd80xxyyy family of boards. [rweiss]
150 * Bunch of cleanup and ... [rweiss&rvb]
151 *
152 * Revision 2.1.1.1 90/07/10 11:44:46 rvb
153 * Added to system.
154 * [90/07/06 rvb]
155 *
156 *
157 * Author: Ron Weiss (rweiss)
158 *
159 */
160
161 /* NOTE:
162 * There are three outstanding bug/features in this implementation.
163 * They may even be hardware misfeatures. The conditions are registered
164 * by counters maintained by the software.
165 * 1: over_write is a condition that means that the board wants to store
166 * packets, but there is no room. So new packets are lost. What seems to
167 * be happening is that we get an over_write condition, but there are no
168 * or just a few packets in the board's ram. Also it seems that we get
169 * several over_writes in a row.
170 * 2: Since there is only one transmit buffer, we need a lock to indicate
171 * whether it is in use. We clear this lock when we get a transmit interrupt.
172 * Sometimes we go to transmit and although there is no transmit in progress,
173 * the lock is set. (In this case, we just ignore the lock.) It would look
174 * like we can miss transmit interrupts?
175 * 3: We tried to clean up the unnecessary switches to bank 0.
176 * Unfortunately, when you do an ifconfig "down", the system tend to lock up
177 * a few seconds later (this was when DSF_RUNNING) was not being set before.
178 * But even with DSF_RUNNING, on an EISA bus machine we ALWAYS lock up after
179 * a few seconds.
180 */
181
182 /*
183 * Western Digital 8003E Mach Ethernet driver (for intel 80386)
184 * Copyright (c) 1990 by Open Software Foundation (OSF).
185 */
186
187 /*
188 Copyright 1990 by Open Software Foundation,
189 Cambridge, MA.
190
191 All Rights Reserved
192
193 Permission to use, copy, modify, and distribute this software and
194 its documentation for any purpose and without fee is hereby granted,
195 provided that the above copyright notice appears in all copies and
196 that both the copyright notice and this permission notice appear in
197 supporting documentation, and that the name of OSF or Open Software
198 Foundation not be used in advertising or publicity pertaining to
199 distribution of the software without specific, written prior
200 permission.
201
202 OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
203 <INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
204 IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
205 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
206 LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
207 NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
208 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
209 */
210
211 #define IF_CNTRS MACH
212 #include <ns8390.h>
213
214 #include <mach_ttd.h>
215 #include <kern/kern_io.h>
216 #include <kern/memory.h>
217 #include <kern/time_out.h>
218 #include <device/device_types.h>
219 #include <device/errno.h>
220 #include <device/io_req.h>
221 #include <device/if_hdr.h>
222 #include <device/if_ether.h>
223 #include <device/net_status.h>
224 #include <device/net_io.h>
225
226 #include <i386/ipl.h>
227 #include <i386/pio.h>
228 #include <chips/busses.h>
229 #include <i386at/if_ns8390.h>
230 #include <i386at/if_wd8003.h>
231 #include <i386at/if_3c503.h>
232
233 #if MACH_TTD
234 #include <ttd/ttd_stub.h>
235 #endif /* MACH_TTD */
236
237
238 #define SPLNET spl6
239
240 int wd_debug = 0;
241
242 boolean_t ns8390probe(
243 vm_offset_t port,
244 struct bus_device *dev);
245 void ns8390attach();
246 int ns8390intr();
247 int ns8390init();
248 int ns8390output();
249 int ns8390ioctl();
250 int ns8390reset();
251 int ns8390rcv(int unit);
252 void ns8390watch(void *b_ptr);
253 int ns8390get_CURR();
254 int ns8390over_write();
255
256 struct bus_device *ns8390info[NNS8390]; /* ???? */
257
258 static vm_offset_t ns8390_std[NNS8390] = { 0 };
259 static struct bus_device *ns8390_info[NNS8390];
260 struct bus_driver ns8390driver =
261 {ns8390probe, 0, ns8390attach, 0, ns8390_std, "ns8390", ns8390_info, 0, 0, 0};
262
263 int watchdog_id;
264
265 char *wd8003_card = "wd";
266 char *elii_card = "el";
267 /* 2e0, 2a0, 280, 250, 350, 330, 310, 300*/
268 int elii_irq[8] = {5, 2, 2, 5, 5, 0x711, 0x711, 5};
269 int elii_bnc[8] = {1, 0, 1, 1, 0, 0x711, 0x711, 0};
270 /*int elii_bnc[8] = {0, 1, 1, 1, 1, 1, 0, 1}; */
271
272 typedef struct {
273 struct ifnet ds_if; /* generic interface header */
274 u_char ds_addr[6]; /* Ethernet hardware address */
275 int flags;
276 int timer;
277 int interrupt;
278 vm_offset_t nic; /* address of IO ports */
279 u_char address[ETHER_ADDR_SIZE];
280 short mode;
281 int tbusy;
282 char *sram; /* beginning of the shared memory RAM buffer */
283 int read_nxtpkt_ptr;/* pointer to next packet available */
284 int pstart; /* page start hold */
285 int pstop; /* page stop hold */
286 int tpsr; /* transmit page start hold */
287 int fifo_depth; /* NIC fifo threshold */
288 char *card;
289 int board_id;
290 }
291 ns8390_softc_t;
292
293 ns8390_softc_t ns8390_softc[NNS8390];
294
295 struct ns8390_cntrs {
296 u_int ovw,
297 jabber,
298 crc,
299 frame,
300 miss,
301 fifo,
302 rcv;
303 u_int xmt,
304 xmti,
305 busy,
306 heart;
307 } ns8390_cntrs[NNS8390];
308
309 #if MACH_TTD
310 boolean_t ttd_poll_loop;
311
312 int ns8390poll_receive();
313 int ns8390transmit_ttd();
314 #endif /* MACH_TTD */
315
316 #ifdef IF_CNTRS
317 int ns_narp = 1, ns_arp = 0;
318 int ns_ein[32], ns_eout[32];
319 int ns_lin[128/8], ns_lout[128/8];
320 static
321 log_2(no)
322 unsigned long no;
323 {
324 return ({ unsigned long _temp__;
325 asm("bsr %1, %0; jne 0f; xorl %0, %0; 0:" :
326 "=r" (_temp__) : "a" (no));
327 _temp__;});
328 }
329 #endif /* IF_CNTRS */
330
331 int imr_hold = PRXE|PTXE|RXEE|TXEE|OVWE|CNTE; /* Interrupts mask bits */
332
333 /*
334 * ns8390probe:
335 *
336 * This function "probes" or checks for the wd8003 board on the bus to see
337 * if it is there. As far as I can tell, the best break between this
338 * routine and the attach code is to simply determine whether the board
339 * is configured in properly. Currently my approach to this is to test the
340 * base I/O special offset for the Western Digital unique byte sequence
341 * identifier. If the bytes match we assume board is there.
342 * The config code expects to see a successful return from the probe
343 * routine before attach will be called.
344 *
345 * input : address device is mapped to, and unit # being checked
346 * output : a '1' is returned if the board exists, and a 0 otherwise
347 *
348 */
349
350 boolean_t ns8390probe(
351 vm_offset_t port,
352 struct bus_device *dev)
353 {
354 vm_offset_t hdwbase = dev->address;
355 int unit = dev->unit;
356 ns8390_softc_t *sp = &ns8390_softc[unit];
357 int tmp;
358
359 if ((unit < 0) || (unit > NNS8390)) {
360 printf("ns8390 ethernet unit %d out of range\n", unit);
361 return(0);
362 }
363 if (((u_char) inb(hdwbase+IFWD_LAR_0) == (u_char) WD_NODE_ADDR_0) &&
364 ((u_char) inb(hdwbase+IFWD_LAR_1) == (u_char) WD_NODE_ADDR_1) &&
365 ((u_char) inb(hdwbase+IFWD_LAR_2) == (u_char) WD_NODE_ADDR_2)) {
366 ns8390info[unit] = dev;
367 sp->card = wd8003_card;
368 dev->name = wd8003_card;
369 sp->nic = hdwbase + OFF_8390;
370 /* enable mem access to board */
371 sp->board_id = wd80xxget_board_id(dev);
372
373 *(sp->address) = inb(hdwbase+IFWD_LAR_0);
374 *(sp->address + 1) = inb(hdwbase+IFWD_LAR_1);
375 *(sp->address + 2) = inb(hdwbase+IFWD_LAR_2);
376 *(sp->address + 3) = inb(hdwbase+IFWD_LAR_3);
377 *(sp->address + 4) = inb(hdwbase+IFWD_LAR_4);
378 *(sp->address + 5) = inb(hdwbase+IFWD_LAR_5);
379 return (1);
380 } /* checks the address of the board to verify that it is a WD */
381 if (tmp = inb(hdwbase+BCFR)) {
382 switch(tmp) {
383 case (1<<7): sp->board_id = 7; break; /*irq5 xvcr*/
384 #ifdef not_currently_possible
385 case (1<<6): sp->board_id = 6; break;
386 case (1<<5): sp->board_id = 5; break;
387 #endif /* not_currently_possible */
388 case (1<<4): sp->board_id = 4; break;
389 case (1<<3): sp->board_id = 3; break;
390 case (1<<2): sp->board_id = 2; break; /*irq2 bnc*/
391 case (1<<1): sp->board_id = 1; break; /*irq2 xvcr*/
392 case (1<<0): sp->board_id = 0; break; /*irq5 bnc*/
393 default: return 0;
394 }
395 switch (inb(hdwbase+PCFR)) {
396 case (1<<7): dev->phys_address = 0xDC000; break;
397 case (1<<6): dev->phys_address = 0xD8000; break;
398 #ifdef not_currently_possible
399 case (1<<5): dev->phys_address = 0xCC000; break;
400 case (1<<4): dev->phys_address = 0xC8000; break;
401 #endif /* not_currently_possible */
402 default:
403 printf("EtherLink II with NO memory configured\n");
404 return 0;
405 }
406 ns8390info[unit] = dev;
407 dev->sysdep1 = elii_irq[sp->board_id];
408 if (dev->sysdep1 == 2)
409 dev->sysdep1 = 9;
410 sp->card = elii_card;
411 dev->name = elii_card;
412 sp->nic = hdwbase;
413 return 1;
414 }
415 return(0);
416 }
417
418 /*
419 * ns8390attach:
420 *
421 * This function attaches a ns8390 board to the "system". The rest of
422 * runtime structures are initialized here (this routine is called after
423 * a successful probe of the board). Once the ethernet address is read
424 * and stored, the board's ifnet structure is attached and readied.
425 *
426 * input : bus_device structure setup in autoconfig
427 * output : board structs and ifnet is setup
428 *
429 */
430
431 void ns8390attach(dev)
432 struct bus_device *dev;
433 {
434 ns8390_softc_t *sp;
435 struct ifnet *ifp;
436 u_char unit;
437
438 take_dev_irq(dev);
439 unit = (u_char)dev->unit;
440 sp = &ns8390_softc[unit];
441 printf(", port = %x, spl = %d, pic = %d. ",
442 dev->address, dev->sysdep, dev->sysdep1);
443
444 if (sp->card == elii_card) {
445 if (elii_bnc[sp->board_id])
446 printf("cheapernet ");
447 else
448 printf("ethernet ");
449 } else
450 printf("ethernet ");
451
452 (volatile char *)sp->sram =
453 (volatile char *) phystokv(dev->phys_address);
454 dev->address = (vm_offset_t) phystokv(dev->address);
455 sp->timer = -1;
456 sp->flags = 0;
457 sp->mode = 0;
458
459 if (!ns8390hwrst(unit)) {
460 printf("%s%d: attach(): reset failed.\n",
461 sp->card, unit);
462 return;
463 }
464 /* N.B. sp->address is not determined till
465 * hwrst time. */
466 *(sp->ds_addr) = *(sp->address);
467 *(sp->ds_addr + 1) = *(sp->address + 1);
468 *(sp->ds_addr + 2) = *(sp->address + 2);
469 *(sp->ds_addr + 3) = *(sp->address + 3);
470 *(sp->ds_addr + 4) = *(sp->address + 4);
471 *(sp->ds_addr + 5) = *(sp->address + 5);
472
473 printf("id [%x:%x:%x:%x:%x:%x]",
474 sp->address[0],sp->address[1],sp->address[2],
475 sp->address[3],sp->address[4],sp->address[5]);
476 ifp = &(sp->ds_if);
477 ifp->if_unit = unit;
478 ifp->if_mtu = ETHERMTU;
479 ifp->if_flags = IFF_BROADCAST;
480 ifp->if_header_size = sizeof(struct ether_header);
481 ifp->if_header_format = HDR_ETHERNET;
482 ifp->if_address_size = 6;
483 ifp->if_address = (char *)&sp->address[0];
484 if_init_queues(ifp);
485
486 #if MACH_TTD
487 if (!ttd_get_packet) {
488 ttd_device_unit = unit;
489 ttd_get_packet = ns8390poll_receive;
490 ttd_send_packet = ns8390transmit_ttd;
491 ttd_host_ether_id.array[0] = *(sp->address);
492 ttd_host_ether_id.array[1] = *(sp->address + 1);
493 ttd_host_ether_id.array[2] = *(sp->address + 2);
494 ttd_host_ether_id.array[3] = *(sp->address + 3);
495 ttd_host_ether_id.array[4] = *(sp->address + 4);
496 ttd_host_ether_id.array[5] = *(sp->address + 5);
497 }
498 #endif /* MACH_TTD */
499 }
500
501 /*
502 * ns8390watch():
503 *
504 */
505
506 void
507 ns8390watch(void *b_ptr)
508 {
509 int unit;
510 int temp_cr;
511 vm_offset_t nic;
512
513 unit = *(char *)b_ptr;
514 timeout(ns8390watch,b_ptr,20*hz);
515 nic = ns8390_softc[unit].nic;
516 temp_cr = inb(nic+CR);
517 outb(nic + CR, (temp_cr & 0x3f) | PS0);
518 printf("<<< ISR=%x CURR=%x rdnxt=%x BNDY=%x>>> ",
519 inb(nic + ISR),
520 ns8390get_CURR(unit), ns8390_softc[unit].read_nxtpkt_ptr,
521 inb(nic+BNDY));
522 outb(nic+CR,temp_cr);
523 }
524
525 void ns8390start(
526 int unit); /* forward */
527
528 /*ARGSUSED*/
529 wd8003open(dev, flag)
530 dev_t dev;
531 int flag;
532 {
533 register int unit = minor(dev);
534
535 if (ns8390_softc[unit].card != wd8003_card)
536 return (ENXIO);
537 if (unit < 0 || unit >= NNS8390 ||
538 ns8390_softc[unit].nic == 0)
539 return (ENXIO);
540
541 ns8390_softc[unit].ds_if.if_flags |= IFF_UP;
542 ns8390init(unit);
543 return(0);
544 }
545
546 eliiopen(dev, flag)
547 dev_t dev;
548 int flag;
549 {
550 register int unit = minor(dev);
551
552 if (ns8390_softc[unit].card != elii_card)
553 return (ENXIO);
554 if (unit < 0 || unit >= NNS8390 ||
555 ns8390_softc[unit].nic == 0)
556 return (ENXIO);
557
558 ns8390_softc[unit].ds_if.if_flags |= IFF_UP;
559 ns8390init(unit);
560 return(0);
561 }
562
563 ns8390output(dev, ior)
564 dev_t dev;
565 io_req_t ior;
566 {
567 register int unit = minor(dev);
568
569 if (unit < 0 || unit >= NNS8390 ||
570 ns8390_softc[unit].nic == 0)
571 return (ENXIO);
572 return (net_write(&ns8390_softc[unit].ds_if, ns8390start, ior));
573 }
574
575 ns8390setinput(dev, receive_port, priority, filter, filter_count)
576 dev_t dev;
577 mach_port_t receive_port;
578 int priority;
579 filter_t filter[];
580 unsigned int filter_count;
581 {
582 register int unit = minor(dev);
583
584 if (unit < 0 || unit >= NNS8390 ||
585 ns8390_softc[unit].nic == 0)
586 return (ENXIO);
587
588 return (net_set_filter(&ns8390_softc[unit].ds_if,
589 receive_port, priority,
590 filter, filter_count));
591 }
592
593
594 /*
595 * ns8390reset:
596 *
597 * This routine is in part an entry point for the "if" code. Since most
598 * of the actual initialization has already (we hope already) been done
599 * by calling ns8390attach().
600 *
601 * input : unit number or board number to reset
602 * output : board is reset
603 *
604 */
605
606 int
607 ns8390reset(unit)
608 int unit;
609 {
610
611 ns8390_softc[unit].ds_if.if_flags &= ~IFF_RUNNING;
612 return(ns8390init(unit));
613 }
614
615 /*
616 * ns8390init:
617 *
618 * Another routine that interfaces the "if" layer to this driver.
619 * Simply resets the structures that are used by "upper layers".
620 * As well as calling ns8390hwrst that does reset the ns8390 board.
621 *
622 * input : board number
623 * output : structures (if structs) and board are reset
624 *
625 */
626
627 int
628 ns8390init(unit)
629 int unit;
630 {
631 struct ifnet *ifp;
632 int stat;
633 spl_t oldpri;
634
635 ifp = &(ns8390_softc[unit].ds_if);
636 oldpri = SPLNET();
637 if ((stat = ns8390hwrst(unit)) == TRUE) {
638 ns8390_softc[unit].ds_if.if_flags |= IFF_RUNNING;
639 ns8390_softc[unit].flags |= DSF_RUNNING;
640 ns8390_softc[unit].tbusy = 0;
641 ns8390start(unit);
642 } else
643 printf("%s%d init(): trouble resetting board %d\n",
644 ns8390_softc[unit].card, unit);
645 ns8390_softc[unit].timer = 5;
646 splx(oldpri);
647 return(stat);
648 }
649
650 /*
651 * ns8390start:
652 *
653 * This is yet another interface routine that simply tries to output a
654 * in an mbuf after a reset.
655 *
656 * input : board number
657 * output : stuff sent to board if any there
658 *
659 */
660
661 void ns8390start(
662 int unit)
663 {
664 register ns8390_softc_t *is = &ns8390_softc[unit];
665 struct ifnet *ifp;
666 io_req_t m;
667
668 if (is->tbusy) {
669 vm_offset_t nic = ns8390_softc[unit].nic;
670 if (!(inb(nic+CR) & TXP)) {
671 is->tbusy = 0;
672 ns8390_cntrs[unit].busy++;
673 } else
674 return;
675 }
676
677 ifp = &(ns8390_softc[unit].ds_if);
678
679 IF_DEQUEUE(&ifp->if_snd, m);
680 if (m != 0) {
681 is->tbusy++;
682 ns8390_cntrs[unit].xmt++;
683 ns8390xmt(unit, m);
684 }
685 }
686
687 /*ARGSUSED*/
688 ns8390getstat(dev, flavor, status, count)
689 dev_t dev;
690 int flavor;
691 dev_status_t status; /* pointer to OUT array */
692 unsigned int *count; /* out */
693 {
694 register int unit = minor(dev);
695
696 if (unit < 0 || unit >= NNS8390 ||
697 ns8390_softc[unit].nic == 0)
698 return (ENXIO);
699
700 return (net_getstat(&ns8390_softc[unit].ds_if,
701 flavor,
702 status,
703 count));
704 }
705 ns8390setstat(dev, flavor, status, count)
706 dev_t dev;
707 int flavor;
708 dev_status_t status;
709 unsigned int count;
710 {
711 register int unit = minor(dev);
712 register ns8390_softc_t *sp;
713
714 if (unit < 0 || unit >= NNS8390 ||
715 ns8390_softc[unit].nic == 0)
716 return (ENXIO);
717
718 sp = &ns8390_softc[unit];
719
720 switch (flavor) {
721 case NET_STATUS:
722 {
723 /*
724 * All we can change are flags, and not many of those.
725 */
726 register struct net_status *ns = (struct net_status *)status;
727 int mode = 0;
728
729 if (count < NET_STATUS_COUNT)
730 return (D_INVALID_SIZE);
731
732 if (ns->flags & IFF_ALLMULTI)
733 mode |= MOD_ENAL;
734 if (ns->flags & IFF_PROMISC)
735 mode |= MOD_PROM;
736
737 /*
738 * Force a complete reset if the receive mode changes
739 * so that these take effect immediately.
740 */
741 if (sp->mode != mode) {
742 sp->mode = mode;
743 if (sp->flags & DSF_RUNNING) {
744 sp->flags &= ~(DSF_LOCK | DSF_RUNNING);
745 ns8390init(unit);
746 }
747 }
748 break;
749 }
750
751 default:
752 return (D_INVALID_OPERATION);
753 }
754 return (D_SUCCESS);
755 }
756
757 /*
758 * ns8390hwrst:
759 *
760 * This routine resets the ns8390 board that corresponds to the
761 * board number passed in.
762 *
763 * input : board number to do a hardware reset
764 * output : board is reset
765 *
766 */
767
768 int
769 ns8390hwrst(unit)
770 int unit;
771 {
772 spl_t spl = SPLNET();
773
774 if (ns8390_softc[unit].card == wd8003_card &&
775 config_wd8003(unit) == FALSE) {
776 printf("%s%d hwrst(): config_wd8003 failed.\n",
777 ns8390_softc[unit].card, unit);
778 splx(spl);
779 return(FALSE);
780 }
781 if (ns8390_softc[unit].card == elii_card &&
782 config_3c503(unit) == FALSE) {
783 printf("%s%d hwrst(): config_3c503 failed.\n",
784 ns8390_softc[unit].card, unit);
785 splx(spl);
786 return(FALSE);
787 }
788 if (config_nic(unit) == FALSE) {
789 printf("%s%d hwrst(): config_nic failed.\n",
790 ns8390_softc[unit].card, unit);
791 splx(spl);
792 return(FALSE);
793 }
794 splx(spl);
795 return(TRUE);
796 }
797
798 /*
799 * ns8390intr:
800 *
801 * This function is the interrupt handler for the ns8390 ethernet
802 * board. This routine will be called whenever either a packet
803 * is received, or a packet has successfully been transfered and
804 * the unit is ready to transmit another packet.
805 *
806 * input : board number that interrupted
807 * output : either a packet is received, or a packet is transfered
808 *
809 */
810 int
811 ns8390intr(unit)
812 {
813 int isr_status;
814 int temp_cr;
815 vm_offset_t nic = ns8390_softc[unit].nic;
816
817 temp_cr = inb(nic+CR);
818 outb(nic+CR, (temp_cr & 0x3f) | PS0);
819 outb(nic+IMR, 0); /* stop board interrupts */
820 outb(nic+CR, temp_cr);
821 while (isr_status = inb(nic+ISR)) {
822 outb(nic+ISR, isr_status); /* clear interrupt status */
823
824 if ((isr_status & (OVW|RXE)) == RXE) {
825 int rsr = inb(nic+RSR);
826 if (rsr & DFR) ns8390_cntrs[unit].jabber++;
827 if (rsr & ~(DFR|PHY|FAE|CRC|PRX))
828 printf("%s%d intr(): isr = %x, RSR = %x\n",
829 ns8390_softc[unit].card, unit,
830 isr_status, rsr);
831 } else if (isr_status & OVW) {
832 ns8390_cntrs[unit].ovw++;
833 ns8390over_write(unit);
834 }
835 if (isr_status & PRX) { /* DFR & PRX is possible */
836 (void) ns8390rcv(unit);
837
838 #if MACH_TTD
839 if (kttd_active)
840 ttd_poll_loop = FALSE;
841 #endif /* MACH_TTD */
842 }
843
844 if (isr_status & TXE) {
845 int tsr = inb(nic+TSR);
846 tsr &= ~0x2; /* unadvertised special */
847 #if MACH_TTD
848 if (!kttd_active)
849 #endif /* MACH_TTD */
850 {
851 if (tsr == (CDH|ABT))
852 ns8390_cntrs[unit].heart++;
853 else
854 printf("%s%d intr(): isr = %x, TSR = %x\n",
855 ns8390_softc[unit].card, unit,
856 isr_status, tsr);
857 ns8390_softc[unit].tbusy = 0;
858 ns8390start(unit);
859 }
860 } else if (isr_status & PTX) {
861 #if MACH_TTD
862 if (!kttd_active)
863 #endif /* MACH_TTD */
864 {
865 ns8390_cntrs[unit].xmti++;
866 ns8390_softc[unit].tbusy = 0;
867 ns8390start(unit);
868 }
869 }
870
871 if (isr_status & CNT) {
872 int c0 = inb(nic+CNTR0);
873 int c1 = inb(nic+CNTR1);
874 int c2 = inb(nic+CNTR2);
875 ns8390_cntrs[unit].frame += c0;
876 ns8390_cntrs[unit].crc += c1;
877 ns8390_cntrs[unit].miss += c2;
878 #ifdef COUNTERS
879 printf("%s%d intr(): isr = %x, FRAME %x, CRC %x, MISS %x\n",
880 ns8390_softc[unit].card, unit,
881 isr_status, c0, c1, c2);
882 printf("%s%d intr(): TOTAL , FRAME %x, CRC %x, MISS %x\n",
883 ns8390_softc[unit].card, unit,
884 ns8390_cntrs[unit].frame,
885 ns8390_cntrs[unit].crc,
886 ns8390_cntrs[unit].miss);
887 #endif /* COUNTERS */
888 outb(nic+ISR, isr_status); /* clear interrupt status again */
889 }
890 }
891 temp_cr=inb(nic+CR);
892 outb(nic+CR, (temp_cr & 0x3f) | PS0);
893 outb(nic+IMR, imr_hold);
894 outb(nic+CR, temp_cr);
895 return(0);
896 }
897
898 /*
899 * Called if on board buffer has been completely filled by ns8390intr. It stops
900 * the board, reads in all the buffers that are currently in the buffer, and
901 * then restart board.
902 */
903 ns8390over_write(unit)
904 int unit;
905 {
906 vm_offset_t nic = ns8390_softc[unit].nic;
907 int no;
908 int count = 0;
909
910 outb(nic+CR, ABR|STP|PS0); /* clear the receive buffer */
911 outb(nic+RBCR0, 0);
912 outb(nic+RBCR1, 0);
913 while ((!(inb (nic + ISR) & RST)) && (count < 10000))
914 count++;
915 if (count == 10000) {
916 printf("%s%d: over_write(): would not reset.\n",
917 ns8390_softc[unit].card, unit);
918 }
919 no = ns8390rcv(unit);
920 #ifdef OVWBUG
921 printf("%s%d over_write(): ns8390 OVW ... %d.\n",
922 ns8390_softc[unit].card, unit, no);
923 #endif /* OVWBUG */
924 outb(nic+TCR, LB1); /* External loopback mode */
925 outb(nic+CR, ABR|STA|PS0);
926 outb(nic+TCR, 0);
927 return;
928 }
929
930 /*
931 * ns8390rcv:
932 *
933 * This routine is called by the interrupt handler to initiate a
934 * packet transfer from the board to the "if" layer above this
935 * driver. This routine checks if a buffer has been successfully
936 * received by the ns8390. If so, it does the actual transfer of the
937 * board data (including the ethernet header) into a packet (consisting
938 * of an mbuf chain) and enqueues it to a higher level.
939 * Then check again whether there are any packets in the receive ring,
940 * if so, read the next packet, until there are no more.
941 *
942 * input : number of the board to check
943 * output : if a packet is available, it is "sent up"
944 */
945 int ns8390rcv(
946 int unit)
947 {
948 register ns8390_softc_t *is = &ns8390_softc[unit];
949 register struct ifnet *ifp = &is->ds_if;
950 vm_offset_t nic = is->nic;
951 int packets = 0;
952 struct ether_header eh;
953 u_short len;
954 int temp_cr;
955 int board_id = is->board_id;
956 vm_offset_t hdwbase = ns8390info[unit]->address;
957 spl_t s;
958
959 /* calculation of pkt size */
960 int nic_overcount; /* NIC says 1 or 2 more than we need */
961 int pkt_size; /* calculated size of received data */
962 int wrap_size; /* size of data before wrapping it */
963 int header_nxtpkt_ptr; /* NIC's next pkt ptr in rcv header */
964 int low_byte_count; /* low byte count of read from rcv header */
965 int high_byte_count; /* calculated high byte count */
966
967
968 volatile char *sram_nxtpkt_ptr; /* mem location of next packet */
969 volatile char *sram_getdata_ptr; /* next location to be read */
970 ipc_kmsg_t new_kmsg;
971 struct ether_header *ehp;
972 struct packet_header *pkt;
973
974
975 #if MACH_TTD
976 if (((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) &&
977 !kttd_active) {
978 #else
979 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
980 #endif /* MACH_TTD */
981 temp_cr = inb(nic+CR); /* get current CR value */
982 outb(nic+CR,((temp_cr & 0x3F)|PS0|STP));
983 outb(nic+IMR, 0); /* Interrupt Mask Register */
984 outb(nic+CR, temp_cr);
985 return -1;
986 }
987
988 while(is->read_nxtpkt_ptr != ns8390get_CURR(unit)) {
989
990 /* while there is a packet to read from the buffer */
991
992 if ((is->read_nxtpkt_ptr < is->pstart) ||
993 (is->read_nxtpkt_ptr >= is->pstop)) {
994 ns8390hwrst(unit);
995 return -1;
996 } /* if next packet pointer is out of receive ring bounds */
997
998 #if MACH_TTD
999 if (!kttd_active)
1000 #endif /* MACH_TTD */
1001 {
1002 packets++;
1003 ns8390_cntrs[unit].rcv++;
1004 }
1005
1006 sram_nxtpkt_ptr = (char *) (is->sram + (is->read_nxtpkt_ptr << 8));
1007
1008 /* get packet size and location of next packet */
1009 header_nxtpkt_ptr = *(sram_nxtpkt_ptr + 1);
1010 header_nxtpkt_ptr &= 0xFF;
1011 low_byte_count = *(sram_nxtpkt_ptr + 2);
1012 low_byte_count &= 0xFF;
1013
1014 if ((low_byte_count + NIC_HEADER_SIZE) > NIC_PAGE_SIZE)
1015 nic_overcount = 2;
1016 else
1017 nic_overcount = 1;
1018 if (header_nxtpkt_ptr > is->read_nxtpkt_ptr) {
1019 wrap_size = 0;
1020 high_byte_count = header_nxtpkt_ptr - is->read_nxtpkt_ptr -
1021 nic_overcount;
1022 } else {
1023 wrap_size = (int) (is->pstop - is->read_nxtpkt_ptr - nic_overcount);
1024 high_byte_count = is->pstop - is->read_nxtpkt_ptr +
1025 header_nxtpkt_ptr - is->pstart - nic_overcount;
1026 }
1027 pkt_size = (high_byte_count << 8) | (low_byte_count & 0xFF);
1028 /* does not seem to include NIC_HEADER_SIZE */
1029 if (!pkt_size) {
1030 printf("%s%d rcv(): zero length.\n",
1031 ns8390_softc[unit].card, unit);
1032 goto next_pkt;
1033 }
1034 len = pkt_size;
1035
1036 sram_getdata_ptr = sram_nxtpkt_ptr + NIC_HEADER_SIZE;
1037 if (board_id & IFWD_SLOT_16BIT) {
1038 #if MACH_TTD
1039 if (!kttd_active)
1040 #endif /* MACH_TTD */
1041 { s = splhi(); }
1042
1043 en_16bit_access(hdwbase, board_id);
1044 bcopy16 (sram_getdata_ptr,
1045 &eh,
1046 sizeof(struct ether_header));
1047 dis_16bit_access (hdwbase, board_id);
1048 #if MACH_TTD
1049 if (!kttd_active)
1050 #endif /* MACH_TTD */
1051 { splx(s); }
1052
1053 } else {
1054 bcopy16 (sram_getdata_ptr,
1055 &eh,
1056 sizeof(struct ether_header));
1057 }
1058 sram_getdata_ptr += sizeof(struct ether_header);
1059 len -= (sizeof(struct ether_header) + 4); /* crc size */
1060 #if MACH_TTD
1061 if (kttd_active) {
1062 new_kmsg = (ipc_kmsg_t)ttd_request_msg;
1063 }else
1064 #endif /* MACH_TTD */
1065 {
1066 new_kmsg = net_kmsg_get();
1067 if (new_kmsg == IKM_NULL) {
1068 /*
1069 * Drop the packet.
1070 */
1071 is->ds_if.if_rcvdrops++;
1072 /*
1073 * not only do we want to return, we need to drop
1074 * the packet on the floor to clear the interrupt.
1075 */
1076 ns8390lost_frame(unit);
1077 return packets;
1078 }
1079 }
1080
1081 #if DEBUG_TTD
1082 dump_ether_header("ns8390wire",&eh);
1083 #endif /* DEBUG_TTD */
1084
1085 ehp = (struct ether_header *) (&net_kmsg(new_kmsg)->header[0]);
1086 pkt = (struct packet_header *) (&net_kmsg(new_kmsg)->packet[0]);
1087
1088 #if DEBUG_TTD
1089 printf("!ehp = 0x%x, pkt = 0x%x!",ehp, pkt);
1090 #endif /* DEBUG_TTD */
1091
1092 *ehp = eh;
1093 if (len >
1094 (wrap_size = (is->sram + (is->pstop << 8) - sram_getdata_ptr))) {
1095 /* if needs to wrap */
1096 if (board_id & IFWD_SLOT_16BIT) {
1097 #if MACH_TTD
1098 if (!kttd_active)
1099 #endif /* MACH_TTD */
1100 { s = splhi(); }
1101
1102 en_16bit_access(hdwbase, board_id);
1103 bcopy16 (sram_getdata_ptr, (char *) (pkt + 1),
1104 wrap_size);
1105 dis_16bit_access (hdwbase, board_id);
1106 #if MACH_TTD
1107 if (!kttd_active)
1108 #endif /* MACH_TTD */
1109 { splx(s); }
1110 } else {
1111 bcopy (sram_getdata_ptr, (char *) (pkt + 1),
1112 wrap_size);
1113 }
1114 sram_getdata_ptr = (volatile char *)
1115 (is->sram + (is->pstart << 8));
1116 } else { /* normal getting data from buffer */
1117 wrap_size = 0;
1118 }
1119 if (board_id & IFWD_SLOT_16BIT) {
1120 #if MACH_TTD
1121 if (!kttd_active)
1122 #endif /* MACH_TTD */
1123 { s = splhi(); }
1124 en_16bit_access(hdwbase, board_id);
1125 bcopy16 (sram_getdata_ptr,
1126 (char *) (pkt + 1) + wrap_size,
1127 len - wrap_size);
1128 dis_16bit_access (hdwbase, board_id);
1129 #if MACH_TTD
1130 if (!kttd_active)
1131 #endif /* MACH_TTD */
1132 { splx(s); }
1133 } else {
1134 bcopy (sram_getdata_ptr,
1135 (char *) (pkt + 1) + wrap_size,
1136 len - wrap_size);
1137 }
1138
1139 pkt->type = ehp->ether_type;
1140 pkt->length = len + sizeof(struct packet_header);
1141
1142 #if MACH_TTD
1143 /*
1144 * Don't want to call net_packet if we are polling
1145 * for a packet.
1146 */
1147 if (!kttd_active)
1148 #endif /* MACH_TTD */
1149 {
1150 /*
1151 * Hand the packet to the network module.
1152 */
1153 net_packet(ifp, new_kmsg, pkt->length,
1154 ethernet_priority(new_kmsg));
1155 }
1156
1157
1158 next_pkt:
1159 is->read_nxtpkt_ptr = *(sram_nxtpkt_ptr + 1);
1160 is->read_nxtpkt_ptr &= 0xFF;
1161
1162 #if MACH_TTD
1163 if (!kttd_active)
1164 #endif /* MACH_TTD */
1165 {
1166 temp_cr = inb(nic+CR);
1167 outb(nic+CR, (temp_cr & 0x3f) | PS0);
1168 }
1169
1170 if (is->read_nxtpkt_ptr == ns8390get_CURR(unit))
1171 if (is->read_nxtpkt_ptr == is->pstart)
1172 outb(nic+BNDY, is->pstop - 1);
1173 else
1174 outb(nic+BNDY, is->read_nxtpkt_ptr - 1);
1175 else
1176 outb(nic+BNDY, is->read_nxtpkt_ptr);
1177
1178 #if MACH_TTD
1179 if (!kttd_active)
1180 #endif /* MACH_TTD */
1181 { outb(nic+CR, temp_cr); }
1182
1183 #if MACH_TTD
1184 /*
1185 * Hand the packet back to the TTD server, if active.
1186 */
1187 if (kttd_active && pkt_size)
1188 return 1;
1189 #endif /* MACH_TTD */
1190
1191
1192 }
1193 return packets;
1194
1195 }
1196
1197 #if MACH_TTD
1198 /*
1199 * Polling routines for the TTD debugger.
1200 */
1201 int ns8390poll_receive(unit)
1202 int unit;
1203 {
1204 int s;
1205 int orig_cr;
1206 int orig_imr;
1207 int isr_status;
1208 int pkts;
1209
1210 ttd_poll_loop = TRUE;
1211
1212
1213 /*
1214 * Should already in at splhigh. Is this necessary? XXX
1215 */
1216 s = splhigh();
1217
1218 #if 0
1219 if (kttd_debug)
1220 printf("ns8390poll_receive: beginning polling loop\n");
1221 #endif /* DEBUG_TTD */
1222
1223 /*
1224 * Loop until packet arrives.
1225 */
1226 while(ttd_poll_loop) {
1227
1228 /*
1229 * Call intr routine
1230 */
1231
1232 ns8390intr(unit);
1233 }
1234
1235 #if 0
1236 if (kttd_debug)
1237 printf("ns8390poll_receive: got packet exiting loop\n");
1238 #endif /* DEBUG_TTD */
1239
1240 splx(s);
1241 }
1242
1243 int ns8390transmit_ttd(unit, packet, len)
1244 int unit;
1245 char * packet;
1246 int len;
1247 {
1248 ns8390_softc_t *is = &ns8390_softc[unit];
1249 vm_offset_t nic = is->nic;
1250 u_short count = 0; /* amount of data already copied */
1251 volatile char *sram_write_pkt;
1252 int board_id = is->board_id;
1253 caddr_t hdwbase = ns8390info[unit]->address;
1254 int s;
1255 int orig_cr;
1256 int orig_imr;
1257 int isr_status;
1258 boolean_t loop = TRUE;
1259
1260 #if 0
1261 dump_ipudpbootp("Beg of xmit",packet);
1262 #endif
1263
1264 s = splhigh();
1265
1266 /* begining of physical address of transmition buffer */
1267
1268 sram_write_pkt = is->sram + is->tpsr * 0x100;
1269
1270 count = len;
1271 if (board_id & IFWD_SLOT_16BIT) {
1272 en_16bit_access(hdwbase, board_id);
1273 bcopy16 (packet, sram_write_pkt, count);
1274 dis_16bit_access (hdwbase, board_id);
1275 } else {
1276 bcopy (packet, sram_write_pkt, count);
1277 }
1278
1279 while (count < ETHERMIN+sizeof(struct ether_header)) {
1280 *(sram_write_pkt + count) = 0;
1281 count++;
1282 }
1283 outb(nic+CR, ABR|STA|PS0); /* select page 0 */
1284 outb(nic+TPSR, is->tpsr); /* xmt page start at 0 of RAM */
1285 outb(nic+TBCR1, count >> 8); /* upper byte of count */
1286 outb(nic+TBCR0, count & 0xFF); /* lower byte of count */
1287 outb(nic+CR, TXP|ABR|STA); /* start transmission */
1288
1289 ns8390intr(unit);
1290
1291 splx(s);
1292 }
1293 #endif /* MACH_TTD */
1294
1295
1296 /*
1297 * ns8390lost_frame:
1298 * this routine called by ns8390read after memory for mbufs could not be
1299 * allocated. It sets the boundary pointers and registers to the next
1300 * packet location.
1301 */
1302
1303 ns8390lost_frame(unit)
1304 int unit;
1305 {
1306 ns8390_softc_t *is = &ns8390_softc[unit];
1307 vm_offset_t nic = is->nic;
1308 volatile char *sram_nxtpkt_ptr;
1309 int temp_cr;
1310
1311 sram_nxtpkt_ptr = (volatile char *) (is->sram +
1312 (is->read_nxtpkt_ptr << 8));
1313
1314 is->read_nxtpkt_ptr = *(sram_nxtpkt_ptr + 1);
1315 is->read_nxtpkt_ptr &= 0xFF;
1316
1317 temp_cr = inb(nic+CR);
1318 outb(nic+CR, (temp_cr & 0x3f) | PS0);
1319
1320 /* update boundary register */
1321 if (is->read_nxtpkt_ptr == ns8390get_CURR(unit))
1322 if (is->read_nxtpkt_ptr == is->pstart)
1323 outb(nic+BNDY, is->pstop - 1);
1324 else
1325 outb(nic+BNDY, is->read_nxtpkt_ptr - 1);
1326 else
1327 outb(nic+BNDY, is->read_nxtpkt_ptr);
1328
1329 outb(nic+CR, temp_cr);
1330
1331 return;
1332 }
1333
1334 /*
1335 * ns8390get_CURR():
1336 *
1337 * Returns the value of the register CURR, which points to the next
1338 * available space for NIC to receive from network unto receive ring.
1339 *
1340 */
1341
1342 int
1343 ns8390get_CURR(unit)
1344 int unit;
1345 {
1346 vm_offset_t nic = ns8390_softc[unit].nic;
1347 int temp_cr;
1348 int ret_val;
1349 spl_t s;
1350
1351 s = SPLNET();
1352
1353 temp_cr = inb(nic+CR); /* get current CR value */
1354 outb(nic+CR, ((temp_cr & 0x3F) | PS1)); /* select page 1 registers */
1355 ret_val = inb(nic+CURR); /* read CURR value */
1356 outb(nic+CR, temp_cr);
1357 splx(s);
1358 return (ret_val & 0xFF);
1359 }
1360
1361 /*
1362 * ns8390xmt:
1363 *
1364 * This routine fills in the appropriate registers and memory
1365 * locations on the ns8390 board and starts the board off on
1366 * the transmit.
1367 *
1368 * input : board number of interest, and a pointer to the mbuf
1369 * output : board memory and registers are set for xfer and attention
1370 *
1371 */
1372
1373 ns8390xmt(unit, m)
1374 int unit;
1375 io_req_t m;
1376 {
1377 ns8390_softc_t *is = &ns8390_softc[unit];
1378 vm_offset_t nic = is->nic;
1379 u_short count = 0; /* amount of data already copied */
1380 volatile char *sram_write_pkt;
1381 int board_id = is->board_id;
1382 vm_offset_t hdwbase = ns8390info[unit]->address;
1383 spl_t s;
1384
1385 /* begining of physical address of transmition buffer */
1386
1387 sram_write_pkt = is->sram + is->tpsr * 0x100;
1388
1389 count = m->io_count;
1390 if (board_id & IFWD_SLOT_16BIT) {
1391 s = splhi();
1392 en_16bit_access(hdwbase, board_id);
1393 bcopy16 (m->io_data, sram_write_pkt, count);
1394 dis_16bit_access (hdwbase, board_id);
1395 splx(s);
1396 } else {
1397 bcopy (m->io_data, sram_write_pkt, count);
1398 }
1399 while (count < ETHERMIN+sizeof(struct ether_header)) {
1400 *(sram_write_pkt + count) = 0;
1401 count++;
1402 }
1403 outb(nic+CR, ABR|STA|PS0); /* select page 0 */
1404 outb(nic+TPSR, is->tpsr); /* xmt page start at 0 of RAM */
1405 outb(nic+TBCR1, count >> 8); /* upper byte of count */
1406 outb(nic+TBCR0, count & 0xFF); /* lower byte of count */
1407 outb(nic+CR, TXP|ABR|STA); /* start transmission */
1408
1409 iodone(m);
1410 }
1411
1412 config_nic(unit)
1413 int unit;
1414 {
1415 ns8390_softc_t *is = &ns8390_softc[unit];
1416 vm_offset_t nic = is->nic;
1417 int i;
1418 int temp;
1419 int count = 0;
1420 spl_t s;
1421
1422 outb (nic+CR, PS0|ABR|STP); /* soft reset and page 0 */
1423 while ((!(inb (nic + ISR) & RST)) && (count < 10000))
1424 count++;
1425 if (count == 10000) {
1426 printf("%s%d: config_nic(): would not reset.\n",
1427 ns8390_softc[unit].card, unit);
1428 }
1429
1430 temp = ((is->fifo_depth & 0x0c) << 3) | BMS; /* fifo depth | not loopback */
1431 if (is->board_id & IFWD_SLOT_16BIT)
1432 temp |= WTS; /* word xfer select (16 bit cards ) */
1433 outb (nic+DCR, temp);
1434 outb (nic+TCR, 0);
1435 outb (nic+RCR, MON); /* receive configuration register */
1436 outb (nic+PSTART, is->pstart); /* recieve ring starts 2k into RAM */
1437 outb (nic+PSTOP, is->pstop); /* stop at last RAM buffer rcv location */
1438 outb (nic+BNDY, is->pstart); /* boundary pointer for page 0 */
1439 s = SPLNET();
1440
1441 outb (nic+CR, PS1|ABR|STP); /* maintain rst | sel page 1 */
1442 is->read_nxtpkt_ptr = is->pstart + 1; /* internal next packet pointer */
1443 outb (nic+CURR, is->read_nxtpkt_ptr); /* Current page register */
1444 for(i=0; i<ETHER_ADDR_SIZE; i++)
1445 outb (nic+PAR0+i, is->address[i]);
1446 for(i=0; i<8; i++)
1447 outb (nic+MAR0+i, 0);
1448
1449 outb (nic+CR, PS0|STP|ABR);
1450 splx(s);
1451 outb (nic+ISR, 0xff); /* clear all interrupt status bits */
1452 outb (nic+IMR, imr_hold); /* Enable interrupts */
1453 outb (nic+RBCR0, 0); /* clear remote byte count */
1454 outb (nic+RBCR1, 0);
1455
1456 outb (nic+CR, PS0|STA|ABR); /* start NIC | select page 0 */
1457 outb (nic+RCR, AB); /* receive configuration register */
1458
1459 return TRUE;
1460 }
1461
1462 /*
1463 * config_ns8390:
1464 *
1465 * This routine does a standard config of a wd8003 family board, with
1466 * the proper modifications to different boards within this family.
1467 *
1468 */
1469 config_wd8003(unit)
1470 int unit;
1471 {
1472 ns8390_softc_t *is = &ns8390_softc[unit];
1473 vm_offset_t hdwbase = ns8390info[unit]->address;
1474 int RAMsize;
1475 volatile char *RAMbase;
1476 int addr_temp;
1477
1478 is->tpsr = 0; /* transmit page start hold */
1479 is->pstart = 0x06; /* receive page start hold */
1480 is->read_nxtpkt_ptr = is->pstart + 1; /* internal next packet pointer */
1481 is->fifo_depth = 0x08; /* NIC fifo threshold */
1482 switch (is->board_id & IFWD_RAM_SIZE_MASK) {
1483 case IFWD_RAM_SIZE_8K:
1484 RAMsize = 0x2000; break;
1485 case IFWD_RAM_SIZE_16K:
1486 RAMsize = 0x4000; break;
1487 case IFWD_RAM_SIZE_32K:
1488 RAMsize = 0x8000; break;
1489 case IFWD_RAM_SIZE_64K:
1490 RAMsize = 0x10000; break;
1491 default:
1492 RAMsize = 0x2000; break;
1493 }
1494 is->pstop = (((int)RAMsize >> 8) & 0x0ff); /* rcv page stop hold */
1495 RAMbase = (volatile char *)ns8390info[unit]->phys_address;
1496 addr_temp = ((int)(RAMbase) >> 13) & 0x3f; /* convert to be written to MSR */
1497 outb(hdwbase+IFWD_MSR, addr_temp | IFWD_MENB); /* initialize MSR */
1498 /* enable 16 bit access from lan controller */
1499 if (is->board_id & IFWD_SLOT_16BIT) {
1500 if (is->board_id & IFWD_INTERFACE_CHIP) {
1501 outb(hdwbase+IFWD_REG_5,
1502 (inb(hdwbase + IFWD_REG_5) & IFWD_REG5_MEM_MASK) |
1503 IFWD_LAN16ENB);
1504 } else {
1505 outb(hdwbase+IFWD_REG_5, (IFWD_LAN16ENB | IFWD_LA19));
1506 }
1507 }
1508 /*
1509 outb(hdwbase+LAAR, LAN16ENB | LA19| MEM16ENB | SOFTINT);
1510 */
1511
1512 return TRUE;
1513 }
1514
1515 /*
1516 * config_ns8390:
1517 *
1518 * This routine does a standard config of a 3 com etherlink II board.
1519 *
1520 */
1521 config_3c503(unit)
1522 int unit;
1523 {
1524 ns8390_softc_t *is = &ns8390_softc[unit];
1525 struct bus_device *dev = ns8390info[unit];
1526 vm_offset_t hdwbase = dev->address;
1527 int RAMsize = dev->am;
1528 int i;
1529
1530 is->tpsr = 0x20; /* transmit page start hold */
1531 is->sram = (char *)phystokv(dev->phys_address) - is->tpsr * 0x100;
1532 /* When NIC says page 20, this means go to
1533 the beginning of the sram range */
1534 is->pstart = 0x26; /* receive page start hold */
1535 is->read_nxtpkt_ptr = is->pstart + 1; /* internal next packet pointer */
1536 is->fifo_depth = 0x08; /* NIC fifo threshold */
1537 is->pstop = is->tpsr + ((RAMsize >> 8) & 0x0ff); /* rcv page stop hold */
1538
1539 outb(hdwbase+CTLR, CTLR_RST|CTLR_THIN);
1540 outb(hdwbase+CTLR, CTLR_THIN);
1541 outb(hdwbase+CTLR, CTLR_STA_ADDR|CTLR_THIN);
1542 for (i = 0; i < 6; i++)
1543 is->address[i] = inb(hdwbase+i);
1544 outb(hdwbase+CTLR, elii_bnc[is->board_id]?CTLR_THIN:CTLR_THICK);
1545 outb(hdwbase+PSTR, is->pstart);
1546 outb(hdwbase+PSPR, is->pstop);
1547 outb(hdwbase+IDCFR, IDCFR_IRQ2 << (elii_irq[is->board_id] - 2));
1548 outb(hdwbase+GACFR, GACFR_TCM|GACFR_8K);
1549 /* BCFR & PCRFR ro */
1550 /* STREG ro & dma */
1551 outb(hdwbase+DQTR, 0);
1552 outb(hdwbase+DAMSB, 0);
1553 outb(hdwbase+DALSB, 0);
1554 outb(hdwbase+VPTR2, 0);
1555 outb(hdwbase+VPTR1, 0);
1556 outb(hdwbase+VPTR0, 0);
1557 outb(hdwbase+RFMSB, 0);
1558 outb(hdwbase+RFLSB, 0);
1559 return TRUE;
1560 }
1561
1562 /*
1563 * ns8390intoff:
1564 *
1565 * This function turns interrupts off for the ns8390 board indicated.
1566 *
1567 */
1568
1569 ns8390intoff(unit)
1570 int unit;
1571 {
1572 vm_offset_t nic = ns8390_softc[unit].nic;
1573 int temp_cr = inb(nic+CR); /* get current CR value */
1574
1575 outb(nic+CR,((temp_cr & 0x3F)|PS0|STP));
1576 outb(nic+IMR, 0); /* Interrupt Mask Register */
1577 outb(nic+CR, temp_cr|STP);
1578
1579 }
1580
1581 /*
1582 * wd80xxget_board_id:
1583 *
1584 * determine which board is being used.
1585 * Currently supports:
1586 * wd8003E (tested)
1587 * wd8003EBT
1588 * wd8003EP (tested)
1589 * wd8013EP (tested)
1590 *
1591 */
1592 wd80xxget_board_id(dev)
1593 struct bus_device *dev;
1594 {
1595 vm_offset_t hdwbase = dev->address;
1596 long unit = dev->unit;
1597 long board_id = 0;
1598 int reg_temp;
1599 int rev_num; /* revision number */
1600 int ram_flag;
1601 int i;
1602 boolean_t register_aliasing;
1603
1604 rev_num = (inb(hdwbase + IFWD_BOARD_ID) & IFWD_BOARD_REV_MASK) >> 1;
1605 printf("%s%d: ", ns8390_softc[unit].card, unit);
1606
1607 if (rev_num == 0) {
1608 printf("rev 0x00\n");
1609 /* It must be 8000 board */
1610 return 0;
1611 }
1612
1613 /* Check if register aliasing is true, that is reading from register
1614 offsets 0-7 will return the contents of register offsets 8-f */
1615
1616 register_aliasing = TRUE;
1617 for (i = 1; i < 5; i++) {
1618 if (inb(hdwbase + IFWD_REG_0 + i) !=
1619 inb(hdwbase + IFWD_LAR_0 + i))
1620 register_aliasing = FALSE;
1621 }
1622 if (inb(hdwbase + IFWD_REG_7) != inb(hdwbase + IFWD_CHKSUM))
1623 register_aliasing = FALSE;
1624
1625
1626 if (register_aliasing == FALSE) {
1627 /* Check if board has interface chip */
1628
1629 reg_temp = inb(hdwbase + IFWD_REG_7); /* save old */
1630 outb(hdwbase + IFWD_REG_7, 0x35); /* write value */
1631 inb(hdwbase + IFWD_REG_0); /* dummy read */
1632 if ((inb(hdwbase + IFWD_REG_7) & 0xff) == 0x35) {
1633 outb(hdwbase + IFWD_REG_7, 0x3a);/* Try another value*/
1634 inb(hdwbase + IFWD_REG_0); /* dummy read */
1635 if ((inb(hdwbase + IFWD_REG_7) & 0xff) == 0x3a) {
1636 board_id |= IFWD_INTERFACE_CHIP;
1637 outb(hdwbase + IFWD_REG_7, reg_temp);
1638 /* restore old value */
1639 }
1640 }
1641
1642 /* Check if board is 16 bit by testing if bit zero in
1643 register 1 is unchangeable by software. If so then
1644 card has 16 bit capability */
1645 reg_temp = inb(hdwbase + IFWD_REG_1);
1646 outb(hdwbase + IFWD_REG_1, reg_temp ^ IFWD_16BIT);
1647 inb(hdwbase + IFWD_REG_0); /* dummy read */
1648 if ((inb(hdwbase + IFWD_REG_1) & IFWD_16BIT) ==
1649 (reg_temp & IFWD_16BIT)) { /* Is bit unchanged */
1650 board_id |= IFWD_BOARD_16BIT; /* Yes == 16 bit */
1651 reg_temp &= 0xfe; /* For 16 bit board
1652 always reset bit 0 */
1653 }
1654 outb(hdwbase + IFWD_REG_1, reg_temp); /* write value back */
1655
1656 /* Test if 16 bit card is in 16 bit slot by reading bit zero in
1657 register 1. */
1658 if (board_id & IFWD_BOARD_16BIT) {
1659 if (inb(hdwbase + IFWD_REG_1) & IFWD_16BIT) {
1660 board_id |= IFWD_SLOT_16BIT;
1661 }
1662 }
1663 }
1664
1665 /* Get media type */
1666
1667 if (inb(hdwbase + IFWD_BOARD_ID) & IFWD_MEDIA_TYPE) {
1668 board_id |= IFWD_ETHERNET_MEDIA;
1669 } else if (rev_num == 1) {
1670 board_id |= IFWD_STARLAN_MEDIA;
1671 } else {
1672 board_id |= IFWD_TWISTED_PAIR_MEDIA;
1673 }
1674
1675 if (rev_num == 2) {
1676 if (inb(hdwbase + IFWD_BOARD_ID) & IFWD_SOFT_CONFIG) {
1677 if ((board_id & IFWD_STATIC_ID_MASK) == WD8003EB ||
1678 (board_id & IFWD_STATIC_ID_MASK) == WD8003W) {
1679 board_id |= IFWD_ALTERNATE_IRQ_BIT;
1680 }
1681 }
1682 /* Check for memory size */
1683
1684 ram_flag = inb(hdwbase + IFWD_BOARD_ID) & IFWD_MEMSIZE;
1685
1686 switch (board_id & IFWD_STATIC_ID_MASK) {
1687 case WD8003E: /* same as WD8003EBT */
1688 case WD8003S: /* same as WD8003SH */
1689 case WD8003WT:
1690 case WD8003W:
1691 case WD8003EB: /* same as WD8003EP */
1692 if (ram_flag)
1693 board_id |= IFWD_RAM_SIZE_32K;
1694 else
1695 board_id |= IFWD_RAM_SIZE_8K;
1696 break;
1697 case WD8003ETA:
1698 case WD8003STA:
1699 case WD8003EA:
1700 case WD8003SHA:
1701 case WD8003WA:
1702 board_id |= IFWD_RAM_SIZE_16K;
1703 break;
1704 case WD8013EBT:
1705 if (board_id & IFWD_SLOT_16BIT) {
1706 if (ram_flag)
1707 board_id |= IFWD_RAM_SIZE_64K;
1708 else
1709 board_id |= IFWD_RAM_SIZE_16K;
1710 } else {
1711 if (ram_flag)
1712 board_id |= IFWD_RAM_SIZE_32K;
1713 else
1714 board_id |= IFWD_RAM_SIZE_8K;
1715 }
1716 break;
1717 default:
1718 board_id |= IFWD_RAM_SIZE_UNKNOWN;
1719 break;
1720 }
1721 } else if (rev_num >= 3) {
1722 board_id &= (long) ~IFWD_MEDIA_MASK; /* remove media info */
1723 board_id |= IFWD_INTERFACE_584_CHIP;
1724 board_id |= wd80xxget_eeprom_info(hdwbase, board_id);
1725 } else {
1726 /* Check for memory size */
1727 if (board_id & IFWD_BOARD_16BIT) {
1728 if (board_id & IFWD_SLOT_16BIT)
1729 board_id |= IFWD_RAM_SIZE_16K;
1730 else
1731 board_id |= IFWD_RAM_SIZE_8K;
1732 } else if (board_id & IFWD_MICROCHANNEL)
1733 board_id |= IFWD_RAM_SIZE_16K;
1734 else if (board_id & IFWD_INTERFACE_CHIP) {
1735 if (inb(hdwbase + IFWD_REG_1) & IFWD_MEMSIZE)
1736 board_id |= IFWD_RAM_SIZE_32K;
1737 else
1738 board_id |= IFWD_RAM_SIZE_8K;
1739 } else
1740 board_id |= IFWD_RAM_SIZE_UNKNOWN;
1741
1742 /* No support for 690 chip yet. It should be checked here */
1743 }
1744
1745 switch (board_id & IFWD_STATIC_ID_MASK) {
1746 case WD8003E: printf("WD8003E or WD8003EBT"); break;
1747 case WD8003S: printf("WD8003S or WD8003SH"); break;
1748 case WD8003WT: printf("WD8003WT"); break;
1749 case WD8003W: printf("WD8003W"); break;
1750 case WD8003EB:
1751 if (board_id & IFWD_INTERFACE_584_CHIP)
1752 printf("WD8003EP");
1753 else
1754 printf("WD8003EB");
1755 break;
1756 case WD8003EW: printf("WD8003EW"); break;
1757 case WD8003ETA: printf("WD8003ETA"); break;
1758 case WD8003STA: printf("WD8003STA"); break;
1759 case WD8003EA: printf("WD8003EA"); break;
1760 case WD8003SHA: printf("WD8003SHA"); break;
1761 case WD8003WA: printf("WD8003WA"); break;
1762 case WD8013EBT: printf("WD8013EBT"); break;
1763 case WD8013EB:
1764 if (board_id & IFWD_INTERFACE_584_CHIP)
1765 printf("WD8013EP");
1766 else
1767 printf("WD8013EB");
1768 break;
1769 case WD8013W: printf("WD8013W"); break;
1770 case WD8013EW: printf("WD8013EW"); break;
1771 default: printf("unknown"); break;
1772 }
1773 printf(" rev 0x%02x", rev_num);
1774 switch(board_id & IFWD_RAM_SIZE_RES_7) {
1775 case IFWD_RAM_SIZE_UNKNOWN:
1776 break;
1777 case IFWD_RAM_SIZE_8K:
1778 printf(" 8 kB ram");
1779 break;
1780 case IFWD_RAM_SIZE_16K:
1781 printf(" 16 kB ram");
1782 break;
1783 case IFWD_RAM_SIZE_32K:
1784 printf(" 32 kB ram");
1785 break;
1786 case IFWD_RAM_SIZE_64K:
1787 printf(" 64 kB ram");
1788 break;
1789 default:
1790 printf("wd: Internal error ram size value invalid %d\n",
1791 (board_id & IFWD_RAM_SIZE_RES_7)>>16);
1792 }
1793
1794 if (board_id & IFWD_BOARD_16BIT) {
1795 if (board_id & IFWD_SLOT_16BIT) {
1796 printf(", in 16 bit slot");
1797 } else {
1798 printf(", 16 bit board in 8 bit slot");
1799 }
1800 }
1801 if (board_id & IFWD_INTERFACE_CHIP) {
1802 if (board_id & IFWD_INTERFACE_584_CHIP) {
1803 printf(", 584 chip");
1804 } else {
1805 printf(", 583 chip");
1806 }
1807 }
1808 if ((board_id & IFWD_INTERFACE_CHIP) == IFWD_INTERFACE_CHIP) {
1809 /* program the WD83C583 EEPROM registers */
1810 int irr_temp, icr_temp;
1811
1812 icr_temp = inb(hdwbase + IFWD_ICR);
1813 irr_temp = inb(hdwbase + IFWD_IRR);
1814
1815 irr_temp &= ~(IFWD_IR0 | IFWD_IR1);
1816 irr_temp |= IFWD_IEN;
1817
1818 icr_temp &= IFWD_WTS;
1819
1820 if (!(board_id & IFWD_INTERFACE_584_CHIP)) {
1821 icr_temp |= IFWD_DMAE | IFWD_IOPE;
1822 if (ram_flag)
1823 icr_temp |= IFWD_MSZ;
1824 }
1825
1826 if (board_id & IFWD_INTERFACE_584_CHIP) {
1827 switch(ns8390info[unit]->sysdep1) {
1828 case 10:
1829 icr_temp |= IFWD_DMAE;
1830 break;
1831 case 2:
1832 case 9: /* Same as 2 */
1833 break;
1834 case 11:
1835 icr_temp |= IFWD_DMAE;
1836 /*FALLTHROUGH*/
1837 case 3:
1838 irr_temp |= IFWD_IR0;
1839 break;
1840 case 15:
1841 icr_temp |= IFWD_DMAE;
1842 /*FALLTHROUGH*/
1843 case 5:
1844 irr_temp |= IFWD_IR1;
1845 break;
1846 case 4:
1847 icr_temp |= IFWD_DMAE;
1848 /*FALLTHROUGH*/
1849 case 7:
1850 irr_temp |= IFWD_IR0 | IFWD_IR1;
1851 break;
1852 default:
1853 printf("%s%d: wd80xx_get_board_id(): Could not set Interrupt Request Register according to pic(%d).\n",
1854 ns8390_softc[unit].card, unit,
1855 ns8390info[unit]->sysdep1);
1856 break;
1857 }
1858 } else {
1859 switch(ns8390info[unit]->sysdep1) {
1860 /* attempt to set interrupt according to assigned pic */
1861 case 2:
1862 case 9: /* Same as 2 */
1863 break;
1864 case 3:
1865 irr_temp |= IFWD_IR0;
1866 break;
1867 case 4:
1868 irr_temp |= IFWD_IR1;
1869 break;
1870 case 5:
1871 irr_temp |= IFWD_IR1 | IFWD_AINT;
1872 break;
1873 case 7:
1874 irr_temp |= IFWD_IR0 | IFWD_IR1;
1875 break;
1876 default:
1877 printf("%s%d: wd80xx_get_board_id(): Could not set Interrupt Request Register according to pic(%d).\n",
1878 ns8390_softc[unit].card, unit,
1879 ns8390info[unit]->sysdep1);
1880 }
1881 }
1882 outb(hdwbase + IFWD_IRR, irr_temp);
1883 outb(hdwbase + IFWD_ICR, icr_temp);
1884 }
1885 printf("\n");
1886 return (board_id);
1887 }
1888
1889 wd80xxget_eeprom_info(hdwbase, board_id)
1890 caddr_t hdwbase;
1891 long board_id;
1892 {
1893 unsigned long new_bits = 0;
1894 int reg_temp;
1895
1896 outb(hdwbase + IFWD_REG_1,
1897 ((inb(hdwbase + IFWD_REG_1) & IFWD_ICR_MASK) | IFWD_OTHER_BIT));
1898 outb(hdwbase + IFWD_REG_3,
1899 ((inb(hdwbase + IFWD_REG_3) & IFWD_EAR_MASK) | IFWD_ENGR_PAGE));
1900 outb(hdwbase + IFWD_REG_1,
1901 ((inb(hdwbase + IFWD_REG_1) & IFWD_ICR_MASK) |
1902 (IFWD_RLA | IFWD_OTHER_BIT)));
1903 while (inb(hdwbase + IFWD_REG_1) & IFWD_RECALL_DONE_MASK)
1904 ;
1905
1906 reg_temp = inb(hdwbase + IFWD_EEPROM_1);
1907 switch (reg_temp & IFWD_EEPROM_BUS_TYPE_MASK) {
1908 case IFWD_EEPROM_BUS_TYPE_AT:
1909 if (wd_debug & 1) printf("wd: AT bus, ");
1910 break;
1911 case IFWD_EEPROM_BUS_TYPE_MCA:
1912 if (wd_debug & 1) printf("wd: MICROCHANNEL, ");
1913 new_bits |= IFWD_MICROCHANNEL;
1914 break;
1915 default:
1916 break;
1917 }
1918 switch (reg_temp & IFWD_EEPROM_BUS_SIZE_MASK) {
1919 case IFWD_EEPROM_BUS_SIZE_8BIT:
1920 if (wd_debug & 1) printf("8 bit bus size, ");
1921 break;
1922 case IFWD_EEPROM_BUS_SIZE_16BIT:
1923 if (wd_debug & 1) printf("16 bit bus size ");
1924 new_bits |= IFWD_BOARD_16BIT;
1925 if (inb(hdwbase + IFWD_REG_1) & IFWD_16BIT) {
1926 new_bits |= IFWD_SLOT_16BIT;
1927 if (wd_debug & 1)
1928 printf("in 16 bit slot, ");
1929 } else {
1930 if (wd_debug & 1)
1931 printf("in 8 bit slot (why?), ");
1932 }
1933 break;
1934 default:
1935 if (wd_debug & 1) printf("bus size other than 8 or 16 bit, ");
1936 break;
1937 }
1938 reg_temp = inb(hdwbase + IFWD_EEPROM_0);
1939 switch (reg_temp & IFWD_EEPROM_MEDIA_MASK) {
1940 case IFWD_STARLAN_TYPE:
1941 if (wd_debug & 1) printf("Starlan media, ");
1942 new_bits |= IFWD_STARLAN_MEDIA;
1943 break;
1944 case IFWD_TP_TYPE:
1945 if (wd_debug & 1) printf("Twisted pair media, ");
1946 new_bits |= IFWD_TWISTED_PAIR_MEDIA;
1947 break;
1948 case IFWD_EW_TYPE:
1949 if (wd_debug & 1) printf("Ethernet and twisted pair media, ");
1950 new_bits |= IFWD_EW_MEDIA;
1951 break;
1952 case IFWD_ETHERNET_TYPE: /*FALLTHROUGH*/
1953 default:
1954 if (wd_debug & 1) printf("ethernet media, ");
1955 new_bits |= IFWD_ETHERNET_MEDIA;
1956 break;
1957 }
1958 switch (reg_temp & IFWD_EEPROM_IRQ_MASK) {
1959 case IFWD_ALTERNATE_IRQ_1:
1960 if (wd_debug & 1) printf("Alternate irq 1\n");
1961 new_bits |= IFWD_ALTERNATE_IRQ_BIT;
1962 break;
1963 default:
1964 if (wd_debug & 1) printf("\n");
1965 break;
1966 }
1967 switch (reg_temp & IFWD_EEPROM_RAM_SIZE_MASK) {
1968 case IFWD_EEPROM_RAM_SIZE_8K:
1969 new_bits |= IFWD_RAM_SIZE_8K;
1970 break;
1971 case IFWD_EEPROM_RAM_SIZE_16K:
1972 if ((new_bits & IFWD_BOARD_16BIT) && (new_bits & IFWD_SLOT_16BIT))
1973 new_bits |= IFWD_RAM_SIZE_16K;
1974 else
1975 new_bits |= IFWD_RAM_SIZE_8K;
1976 break;
1977 case IFWD_EEPROM_RAM_SIZE_32K:
1978 new_bits |= IFWD_RAM_SIZE_32K;
1979 break;
1980 case IFWD_EEPROM_RAM_SIZE_64K:
1981 if ((new_bits & IFWD_BOARD_16BIT) && (new_bits & IFWD_SLOT_16BIT))
1982 new_bits |= IFWD_RAM_SIZE_64K;
1983 else
1984 new_bits |= IFWD_RAM_SIZE_32K;
1985 break;
1986 default:
1987 new_bits |= IFWD_RAM_SIZE_UNKNOWN;
1988 break;
1989 }
1990 outb(hdwbase + IFWD_REG_1,
1991 ((inb(hdwbase + IFWD_REG_1) & IFWD_ICR_MASK) | IFWD_OTHER_BIT));
1992 outb(hdwbase + IFWD_REG_3,
1993 ((inb(hdwbase + IFWD_REG_3) & IFWD_EAR_MASK) | IFWD_EA6));
1994 outb(hdwbase + IFWD_REG_1,
1995 ((inb(hdwbase + IFWD_REG_1) & IFWD_ICR_MASK) | IFWD_RLA));
1996 return (new_bits);
1997 }
1998
1999 wdpr(unit)
2000 {
2001 vm_offset_t nic = ns8390_softc[unit].nic;
2002 spl_t s;
2003 int temp_cr;
2004
2005 s = SPLNET();
2006 temp_cr = inb(nic); /* get current CR value */
2007
2008 printf("CR %x, BNDRY %x, TSR %x, NCR %x, FIFO %x, ISR %x, RSR %x\n",
2009 inb(nic+0x0), inb(nic+0x3), inb(nic+0x4), inb(nic+0x5),
2010 inb(nic+0x6), inb(nic+0x7), inb(nic+0xc));
2011 printf("CLD %x:%x, CRD %x:%x, FR %x, CRC %x, Miss %x\n",
2012 inb(nic+0x1), inb(nic+0x2),
2013 inb(nic+0x8), inb(nic+0x9),
2014 inb(nic+0xd), inb(nic+0xe), inb(nic+0xf));
2015
2016
2017 outb(nic, (temp_cr&0x3f)|PS1); /* page 1 CR value */
2018 printf("PHYS %x:%x:%x:%x:%x CUR %x\n",
2019 inb(nic+0x1), inb(nic+0x2), inb(nic+0x3),
2020 inb(nic+0x4), inb(nic+0x5), inb(nic+0x6),
2021 inb(nic+0x7));
2022 printf("MAR %x:%x:%x:%x:%x:%x:%x:%x\n",
2023 inb(nic+0x8), inb(nic+0x9), inb(nic+0xa), inb(nic+0xb),
2024 inb(nic+0xc), inb(nic+0xd), inb(nic+0xe), inb(nic+0xf));
2025 outb(nic, temp_cr); /* restore current CR value */
2026 splx(s);
2027 }
2028
2029
2030 /*
2031 This sets bit 7 (0 justified) of register offset 0x05. It will enable
2032 the host to access shared RAM 16 bits at a time. It will also maintain
2033 the LAN16BIT bit high in addition, this routine maintains address bit 19
2034 (previous cards assumed this bit high...we must do it manually)
2035
2036 note 1: this is a write only register
2037 note 2: this routine should be called only after interrupts are disabled
2038 and they should remain disabled until after the routine 'dis_16bit_access'
2039 is called
2040 */
2041
2042 en_16bit_access (hdwbase, board_id)
2043 caddr_t hdwbase;
2044 long board_id;
2045 {
2046 if (board_id & IFWD_INTERFACE_CHIP)
2047 outb(hdwbase+IFWD_REG_5,
2048 (inb(hdwbase+IFWD_REG_5) & IFWD_REG5_MEM_MASK)
2049 | IFWD_MEM16ENB | IFWD_LAN16ENB);
2050 else
2051 outb(hdwbase+IFWD_REG_5, (IFWD_MEM16ENB | IFWD_LAN16ENB |
2052 IFWD_LA19));
2053 }
2054
2055 /*
2056 This resets bit 7 (0 justified) of register offset 0x05. It will disable
2057 the host from accessing shared RAM 16 bits at a time. It will maintain the
2058 LAN16BIT bit high in addition, this routine maintains address bit 19
2059 (previous cards assumed this bit high...we must do it manually)
2060
2061 note: this is a write only register
2062 */
2063
2064 dis_16bit_access (hdwbase, board_id)
2065 caddr_t hdwbase;
2066 long board_id;
2067 {
2068 if (board_id & IFWD_INTERFACE_CHIP)
2069 outb(hdwbase+IFWD_REG_5,
2070 ((inb(hdwbase+IFWD_REG_5) & IFWD_REG5_MEM_MASK) |
2071 IFWD_LAN16ENB));
2072 else
2073 outb(hdwbase+IFWD_REG_5, (IFWD_LAN16ENB | IFWD_LA19));
2074 }
2075
Cache object: 338c6e9ddb7d83f3a2627f93da32a4ab
|