FreeBSD/Linux Kernel Cross Reference
sys/i386/isa/if_ep.c
1 /*
2 * Copyright (c) 1994 Herb Peyerl <hpeyerl@novatel.ca>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Herb Peyerl.
16 * 4. The name of Herb Peyerl may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * if_ep.c,v 1.19 1995/01/24 20:53:45 davidg Exp
31 */
32
33 /*
34 * Modified from the FreeBSD 1.1.5.1 version by:
35 * Andres Vega Garcia
36 * INRIA - Sophia Antipolis, France
37 * avega@sophia.inria.fr
38 */
39
40 /*
41 * $FreeBSD: src/sys/i386/isa/if_ep.c,v 1.53.2.7 1999/09/05 08:12:49 peter Exp $
42 *
43 * Promiscuous mode added and interrupt logic slightly changed
44 * to reduce the number of adapter failures. Transceiver select
45 * logic changed to use value from EEPROM. Autoconfiguration
46 * features added.
47 * Done by:
48 * Serge Babkin
49 * Chelindbank (Chelyabinsk, Russia)
50 * babkin@hq.icb.chel.su
51 */
52
53 /*
54 * Pccard support for 3C589 by:
55 * HAMADA Naoki
56 * nao@tom-yam.or.jp
57 */
58
59 #include "ep.h"
60 #if NEP > 0
61
62 #include "bpfilter.h"
63
64 #include <sys/param.h>
65 #if defined(__FreeBSD__)
66 #include <sys/systm.h>
67 #include <sys/kernel.h>
68 #include <sys/conf.h>
69 #endif
70 #include <sys/mbuf.h>
71 #include <sys/socket.h>
72 #include <sys/ioctl.h>
73 #include <sys/errno.h>
74 #include <sys/syslog.h>
75 #if defined(__NetBSD__)
76 #include <sys/select.h>
77 #endif
78
79 #include <net/if.h>
80 #include <net/if_dl.h>
81 #include <net/if_types.h>
82
83 #ifdef INET
84 #include <netinet/in.h>
85 #include <netinet/in_systm.h>
86 #include <netinet/in_var.h>
87 #include <netinet/ip.h>
88 #include <netinet/if_ether.h>
89 #endif
90
91 #ifdef IPX
92 #include <netipx/ipx.h>
93 #include <netipx/ipx_if.h>
94 #endif
95
96 #ifdef NS
97 #include <netns/ns.h>
98 #include <netns/ns_if.h>
99 #endif
100
101 #if NBPFILTER > 0
102 #include <net/bpf.h>
103 #include <net/bpfdesc.h>
104 #endif
105
106 #ifdef BRIDGE
107 #include <net/bridge.h>
108 #endif
109
110 #if defined(__FreeBSD__)
111 #include <machine/clock.h>
112 #endif
113
114 #include <i386/isa/isa_device.h>
115 #include <i386/isa/if_epreg.h>
116 #include <i386/isa/elink.h>
117
118 /* Exported variables */
119 u_long ep_unit;
120 int ep_boards;
121 struct ep_board ep_board[EP_MAX_BOARDS + 1];
122
123 static int eeprom_rdy __P((struct ep_softc *sc));
124
125 static int ep_isa_probe __P((struct isa_device *));
126 static struct ep_board * ep_look_for_board_at __P((struct isa_device *is));
127 static int ep_isa_attach __P((struct isa_device *));
128 static int epioctl __P((struct ifnet * ifp, int, caddr_t));
129
130 static void epinit __P((struct ep_softc *));
131 static void epread __P((struct ep_softc *));
132 void epreset __P((int));
133 static void epstart __P((struct ifnet *));
134 static void epstop __P((struct ep_softc *));
135 static void epwatchdog __P((struct ifnet *));
136
137 #if 0
138 static int send_ID_sequence __P((int));
139 #endif
140 static int get_eeprom_data __P((int, int));
141
142 static struct ep_softc* ep_softc[NEP];
143 static int ep_current_tag = EP_LAST_TAG + 1;
144 static char *ep_conn_type[] = {"UTP", "AUI", "???", "BNC"};
145
146 #define ep_ftst(f) (sc->stat&(f))
147 #define ep_fset(f) (sc->stat|=(f))
148 #define ep_frst(f) (sc->stat&=~(f))
149
150 struct isa_driver epdriver = {
151 ep_isa_probe,
152 ep_isa_attach,
153 "ep",
154 0
155 };
156
157 #include "card.h"
158
159 #if NCARD > 0
160 #include "apm.h"
161 #include <sys/select.h>
162 #include <pccard/cardinfo.h>
163 #include <pccard/driver.h>
164 #include <pccard/slot.h>
165
166 /*
167 * PC-Card (PCMCIA) specific code.
168 */
169 static int ep_pccard_init __P((struct pccard_devinfo *));
170 static int ep_pccard_attach __P((struct pccard_devinfo *));
171 static void ep_unload __P((struct pccard_devinfo *));
172 static int card_intr __P((struct pccard_devinfo *));
173
174 static struct pccard_device ep_info = {
175 "ep",
176 ep_pccard_init,
177 ep_unload,
178 card_intr,
179 0, /* Attributes - presently unused */
180 &net_imask
181 };
182
183 DATA_SET(pccarddrv_set, ep_info);
184
185 /*
186 * Initialize the device - called from Slot manager.
187 */
188 static int
189 ep_pccard_init(devi)
190 struct pccard_devinfo *devi;
191 {
192 struct isa_device *is = &devi->isahd;
193 struct ep_softc *sc = ep_softc[is->id_unit];
194 struct ep_board *epb;
195 int i;
196
197 epb = &ep_board[is->id_unit];
198
199 if (sc == 0) {
200 if ((sc = ep_alloc(is->id_unit, epb)) == 0) {
201 return (ENXIO);
202 }
203 ep_unit++;
204 }
205
206 /* get_e() requires these. */
207 sc->ep_io_addr = is->id_iobase;
208 sc->unit = is->id_unit;
209
210 epb->epb_addr = is->id_iobase;
211 epb->epb_used = 1;
212 epb->prod_id = get_e(sc, EEPROM_PROD_ID);
213
214 /* 3C589's product id? */
215 if (epb->prod_id != 0x9058) {
216 printf("ep%d: failed to come ready.\n", is->id_unit);
217 return (ENXIO);
218 }
219
220 epb->res_cfg = get_e(sc, EEPROM_RESOURCE_CFG);
221 for (i = 0; i < 3; i++)
222 sc->epb->eth_addr[i] = get_e(sc, EEPROM_NODE_ADDR_0 + i);
223
224 if (ep_pccard_attach(devi) == 0)
225 return (ENXIO);
226
227 sc->arpcom.ac_if.if_snd.ifq_maxlen = ifqmaxlen;
228 return (0);
229 }
230
231 static int
232 ep_pccard_attach(devi)
233 struct pccard_devinfo *devi;
234 {
235 struct isa_device *is = &devi->isahd;
236 struct ep_softc *sc = ep_softc[is->id_unit];
237 u_short config;
238
239 sc->ep_connectors = 0;
240 config = inw(IS_BASE + EP_W0_CONFIG_CTRL);
241 if (config & IS_BNC) {
242 sc->ep_connectors |= BNC;
243 }
244 if (config & IS_UTP) {
245 sc->ep_connectors |= UTP;
246 }
247 if (!(sc->ep_connectors & 7))
248 printf("no connectors!");
249 sc->ep_connector = inw(BASE + EP_W0_ADDRESS_CFG) >> ACF_CONNECTOR_BITS;
250
251 /* ROM size = 0, ROM base = 0 */
252 /* For now, ignore AUTO SELECT feature of 3C589B and later. */
253 outw(BASE + EP_W0_ADDRESS_CFG, get_e(sc, EEPROM_ADDR_CFG) & 0xc000);
254
255 /* Fake IRQ must be 3 */
256 outw(BASE + EP_W0_RESOURCE_CFG, (sc->epb->res_cfg & 0x0fff) | 0x3000);
257
258 outw(BASE + EP_W0_PRODUCT_ID, sc->epb->prod_id);
259
260 ep_attach(sc);
261
262 return 1;
263 }
264
265 static void
266 ep_unload(devi)
267 struct pccard_devinfo *devi;
268 {
269 struct ep_softc *sc = ep_softc[devi->isahd.id_unit];
270
271 if (sc->gone) {
272 printf("ep%d: already unloaded\n", devi->isahd.id_unit);
273 return;
274 }
275 sc->arpcom.ac_if.if_flags &= ~IFF_RUNNING;
276 sc->gone = 1;
277 printf("ep%d: unload\n", devi->isahd.id_unit);
278 }
279
280 /*
281 * card_intr - Shared interrupt called from
282 * front end of PC-Card handler.
283 */
284 static int
285 card_intr(devi)
286 struct pccard_devinfo *devi;
287 {
288 epintr(devi->isahd.id_unit);
289 return(1);
290 }
291 #endif /* NCARD > 0 */
292
293 static int
294 eeprom_rdy(sc)
295 struct ep_softc *sc;
296 {
297 int i;
298
299 for (i = 0; is_eeprom_busy(BASE) && i < MAX_EEPROMBUSY; i++)
300 continue;
301 if (i >= MAX_EEPROMBUSY) {
302 printf("ep%d: eeprom failed to come ready.\n", sc->unit);
303 return (0);
304 }
305 return (1);
306 }
307
308 static struct ep_board *
309 ep_look_for_board_at(is)
310 struct isa_device *is;
311 {
312 int data, i, j, id_port = ELINK_ID_PORT;
313 int count = 0;
314
315 if (ep_current_tag == (EP_LAST_TAG + 1)) {
316 /* Come here just one time */
317
318 ep_current_tag--;
319
320 /* Look for the ISA boards. Init and leave them actived */
321 outb(id_port, 0);
322 outb(id_port, 0);
323
324 elink_idseq(0xCF);
325
326 elink_reset();
327 DELAY(10000);
328 for (i = 0; i < EP_MAX_BOARDS; i++) {
329 outb(id_port, 0);
330 outb(id_port, 0);
331 elink_idseq(0xCF);
332
333 data = get_eeprom_data(id_port, EEPROM_MFG_ID);
334 if (data != MFG_ID)
335 break;
336
337 /* resolve contention using the Ethernet address */
338
339 for (j = 0; j < 3; j++)
340 get_eeprom_data(id_port, j);
341
342 /* and save this address for later use */
343
344 for (j = 0; j < 3; j++)
345 ep_board[ep_boards].eth_addr[j] = get_eeprom_data(id_port, j);
346
347 ep_board[ep_boards].res_cfg =
348 get_eeprom_data(id_port, EEPROM_RESOURCE_CFG);
349
350 ep_board[ep_boards].prod_id =
351 get_eeprom_data(id_port, EEPROM_PROD_ID);
352
353 ep_board[ep_boards].epb_used = 0;
354 #ifdef PC98
355 ep_board[ep_boards].epb_addr =
356 (get_eeprom_data(id_port, EEPROM_ADDR_CFG) & 0x1f) * 0x100 + 0x40d0;
357 #else
358 ep_board[ep_boards].epb_addr =
359 (get_eeprom_data(id_port, EEPROM_ADDR_CFG) & 0x1f) * 0x10 + 0x200;
360
361 if (ep_board[ep_boards].epb_addr > 0x3E0)
362 /* Board in EISA configuration mode */
363 continue;
364 #endif /* PC98 */
365
366 outb(id_port, ep_current_tag); /* tags board */
367 outb(id_port, ACTIVATE_ADAPTER_TO_CONFIG);
368 ep_boards++;
369 count++;
370 ep_current_tag--;
371 }
372
373 ep_board[ep_boards].epb_addr = 0;
374 if (count) {
375 printf("%d 3C5x9 board(s) on ISA found at", count);
376 for (j = 0; ep_board[j].epb_addr; j++)
377 if (ep_board[j].epb_addr <= 0x3E0)
378 printf(" 0x%x", ep_board[j].epb_addr);
379 printf("\n");
380 }
381 }
382
383 /* we have two cases:
384 *
385 * 1. Device was configured with 'port ?'
386 * In this case we search for the first unused card in list
387 *
388 * 2. Device was configured with 'port xxx'
389 * In this case we search for the unused card with that address
390 *
391 */
392
393 if (IS_BASE == -1) { /* port? */
394 for (i = 0; ep_board[i].epb_addr && ep_board[i].epb_used; i++)
395 ;
396 if (ep_board[i].epb_addr == 0)
397 return 0;
398
399 IS_BASE = ep_board[i].epb_addr;
400 ep_board[i].epb_used = 1;
401
402 return &ep_board[i];
403 } else {
404 for (i = 0;
405 ep_board[i].epb_addr && ep_board[i].epb_addr != IS_BASE;
406 i++)
407 ;
408
409 if (ep_board[i].epb_used || ep_board[i].epb_addr != IS_BASE)
410 return 0;
411
412 if (inw(IS_BASE + EP_W0_EEPROM_COMMAND) & EEPROM_TST_MODE) {
413 printf("ep%d: 3c5x9 at 0x%x in PnP mode. Disable PnP mode!\n",
414 is->id_unit, IS_BASE);
415 }
416 ep_board[i].epb_used = 1;
417
418 return &ep_board[i];
419 }
420 }
421
422 /*
423 * get_e: gets a 16 bits word from the EEPROM. we must have set the window
424 * before
425 */
426 u_int16_t
427 get_e(sc, offset)
428 struct ep_softc *sc;
429 int offset;
430 {
431 if (!eeprom_rdy(sc))
432 return (0xffff);
433 outw(BASE + EP_W0_EEPROM_COMMAND, EEPROM_CMD_RD | offset);
434 if (!eeprom_rdy(sc))
435 return (0xffff);
436 return (inw(BASE + EP_W0_EEPROM_DATA));
437 }
438
439 struct ep_softc *
440 ep_alloc(unit, epb)
441 int unit;
442 struct ep_board *epb;
443 {
444 struct ep_softc *sc;
445
446 if (unit >= NEP) {
447 printf("ep: unit number (%d) too high\n", unit);
448 return NULL;
449 }
450
451 /*
452 * Allocate a storage area for us
453 */
454 if (ep_softc[unit]) {
455 printf("ep%d: unit number already allocated to another "
456 "adaptor\n", unit);
457 return NULL;
458 }
459
460 sc = malloc(sizeof(struct ep_softc), M_DEVBUF, M_NOWAIT);
461 if (!sc) {
462 printf("ep%d: cannot malloc!\n", unit);
463 return NULL;
464 }
465 bzero(sc, sizeof(struct ep_softc));
466 ep_softc[unit] = sc;
467 sc->unit = unit;
468 sc->ep_io_addr = epb->epb_addr;
469 sc->epb = epb;
470
471 return(sc);
472 }
473
474 void
475 ep_free(sc)
476 struct ep_softc *sc;
477 {
478 ep_softc[sc->unit] = NULL;
479 free(sc, M_DEVBUF);
480 return;
481 }
482
483 int
484 ep_isa_probe(is)
485 struct isa_device *is;
486 {
487 struct ep_softc *sc;
488 struct ep_board *epb;
489 u_short k;
490
491 if ((epb = ep_look_for_board_at(is)) == 0)
492 return (0);
493
494 /*
495 * Allocate a storage area for us
496 */
497 sc = ep_alloc(ep_unit, epb);
498 if (!sc)
499 return (0);
500
501 is->id_unit = ep_unit++;
502
503 /*
504 * The iobase was found and MFG_ID was 0x6d50. PROD_ID should be
505 * 0x9[0-f]50 (IBM-PC)
506 * 0x9[0-f]5[0-f] (PC-98)
507 */
508 GO_WINDOW(0);
509 k = sc->epb->prod_id;
510 #ifdef PC98
511 if ((k & 0xf0f0) != (PROD_ID & 0xf0f0)) {
512 #else
513 if ((k & 0xf0ff) != (PROD_ID & 0xf0ff)) {
514 #endif
515 printf("ep_isa_probe: ignoring model %04x\n", k);
516 ep_free(sc);
517 return (0);
518 }
519
520 k = sc->epb->res_cfg;
521
522 k >>= 12;
523
524 /* Now we have two cases again:
525 *
526 * 1. Device was configured with 'irq?'
527 * In this case we use irq read from the board
528 *
529 * 2. Device was configured with 'irq xxx'
530 * In this case we set up the board to use specified interrupt
531 *
532 */
533
534 if (is->id_irq == 0) { /* irq? */
535 is->id_irq = 1 << ((k == 2) ? 9 : k);
536 }
537
538 sc->stat = 0; /* 16 bit access */
539
540 /* By now, the adapter is already activated */
541
542 return (EP_IOSIZE); /* 16 bytes of I/O space used. */
543 }
544
545 static int
546 ep_isa_attach(is)
547 struct isa_device *is;
548 {
549 struct ep_softc *sc = ep_softc[is->id_unit];
550 u_short config;
551 int irq;
552
553 sc->ep_connectors = 0;
554 config = inw(IS_BASE + EP_W0_CONFIG_CTRL);
555 if (config & IS_AUI) {
556 sc->ep_connectors |= AUI;
557 }
558 if (config & IS_BNC) {
559 sc->ep_connectors |= BNC;
560 }
561 if (config & IS_UTP) {
562 sc->ep_connectors |= UTP;
563 }
564 if (!(sc->ep_connectors & 7))
565 printf("no connectors!");
566 sc->ep_connector = inw(BASE + EP_W0_ADDRESS_CFG) >> ACF_CONNECTOR_BITS;
567 /*
568 * Write IRQ value to board
569 */
570
571 irq = ffs(is->id_irq) - 1;
572 if (irq == -1) {
573 printf(" invalid irq... cannot attach\n");
574 return 0;
575 }
576
577 GO_WINDOW(0);
578 SET_IRQ(BASE, irq);
579
580 ep_attach(sc);
581 return 1;
582 }
583
584 int
585 ep_attach(sc)
586 struct ep_softc *sc;
587 {
588 struct ifaddr *ifa;
589 struct ifnet *ifp = &sc->arpcom.ac_if;
590 struct sockaddr_dl *sdl;
591 u_short *p;
592 int i;
593 int attached;
594
595 sc->gone = 0;
596 attached = (ifp->if_softc != 0);
597
598 printf("ep%d: ", sc->unit);
599 /*
600 * Current media type
601 */
602 if (sc->ep_connectors & AUI) {
603 printf("aui");
604 if (sc->ep_connectors & ~AUI)
605 printf("/");
606 }
607 if (sc->ep_connectors & UTP) {
608 printf("utp");
609 if (sc->ep_connectors & BNC)
610 printf("/");
611 }
612 if (sc->ep_connectors & BNC) {
613 printf("bnc");
614 }
615
616 printf("[*%s*]", ep_conn_type[sc->ep_connector]);
617
618 /*
619 * Setup the station address
620 */
621 p = (u_short *) & sc->arpcom.ac_enaddr;
622 GO_WINDOW(2);
623 for (i = 0; i < 3; i++) {
624 p[i] = htons(sc->epb->eth_addr[i]);
625 outw(BASE + EP_W2_ADDR_0 + (i * 2), ntohs(p[i]));
626 }
627 printf(" address %6D\n", sc->arpcom.ac_enaddr, ":");
628
629 ifp->if_softc = sc;
630 ifp->if_unit = sc->unit;
631 ifp->if_name = "ep";
632 ifp->if_mtu = ETHERMTU;
633 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
634 ifp->if_output = ether_output;
635 ifp->if_start = epstart;
636 ifp->if_ioctl = epioctl;
637 ifp->if_watchdog = epwatchdog;
638
639 if (!attached) {
640 if_attach(ifp);
641 ether_ifattach(ifp);
642 }
643
644 /* device attach does transition from UNCONFIGURED to IDLE state */
645
646 /*
647 * Fill the hardware address into ifa_addr if we find an AF_LINK entry.
648 * We need to do this so bpf's can get the hardware addr of this card.
649 * netstat likes this too!
650 */
651 ifa = ifp->if_addrlist;
652 while ((ifa != 0) && (ifa->ifa_addr != 0) &&
653 (ifa->ifa_addr->sa_family != AF_LINK))
654 ifa = ifa->ifa_next;
655
656 if ((ifa != 0) && (ifa->ifa_addr != 0)) {
657 sdl = (struct sockaddr_dl *) ifa->ifa_addr;
658 sdl->sdl_type = IFT_ETHER;
659 sdl->sdl_alen = ETHER_ADDR_LEN;
660 sdl->sdl_slen = 0;
661 bcopy(sc->arpcom.ac_enaddr, LLADDR(sdl), ETHER_ADDR_LEN);
662 }
663
664 #ifdef EP_LOCAL_STATS
665 sc->rx_no_first = sc->rx_no_mbuf =
666 sc->rx_bpf_disc = sc->rx_overrunf = sc->rx_overrunl =
667 sc->tx_underrun = 0;
668 #endif
669 ep_fset(F_RX_FIRST);
670 sc->top = sc->mcur = 0;
671
672 #if NBPFILTER > 0
673 if (!attached) {
674 bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header));
675 }
676 #endif
677 return 0;
678 }
679
680
681 /*
682 * The order in here seems important. Otherwise we may not receive
683 * interrupts. ?!
684 */
685 static void
686 epinit(sc)
687 struct ep_softc *sc;
688 {
689 register struct ifnet *ifp = &sc->arpcom.ac_if;
690 int s, i, j;
691
692 if (sc->gone)
693 return;
694
695 /*
696 if (ifp->if_addrlist == (struct ifaddr *) 0)
697 return;
698 */
699
700 s = splimp();
701 while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
702
703 GO_WINDOW(0);
704 outw(BASE + EP_COMMAND, STOP_TRANSCEIVER);
705 GO_WINDOW(4);
706 outw(BASE + EP_W4_MEDIA_TYPE, DISABLE_UTP);
707 GO_WINDOW(0);
708
709 /* Disable the card */
710 outw(BASE + EP_W0_CONFIG_CTRL, 0);
711
712 /* Enable the card */
713 outw(BASE + EP_W0_CONFIG_CTRL, ENABLE_DRQ_IRQ);
714
715 GO_WINDOW(2);
716
717 /* Reload the ether_addr. */
718 for (i = 0; i < 6; i++)
719 outb(BASE + EP_W2_ADDR_0 + i, sc->arpcom.ac_enaddr[i]);
720
721 outw(BASE + EP_COMMAND, RX_RESET);
722 outw(BASE + EP_COMMAND, TX_RESET);
723 while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
724
725 /* Window 1 is operating window */
726 GO_WINDOW(1);
727 for (i = 0; i < 31; i++)
728 inb(BASE + EP_W1_TX_STATUS);
729
730 /* get rid of stray intr's */
731 outw(BASE + EP_COMMAND, ACK_INTR | 0xff);
732
733 outw(BASE + EP_COMMAND, SET_RD_0_MASK | S_5_INTS);
734
735 outw(BASE + EP_COMMAND, SET_INTR_MASK | S_5_INTS);
736
737 if (ifp->if_flags & IFF_PROMISC)
738 outw(BASE + EP_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL |
739 FIL_GROUP | FIL_BRDCST | FIL_ALL);
740 else
741 outw(BASE + EP_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL |
742 FIL_GROUP | FIL_BRDCST);
743
744 /*
745 * S.B.
746 *
747 * Now behavior was slightly changed:
748 *
749 * if any of flags link[0-2] is used and its connector is
750 * physically present the following connectors are used:
751 *
752 * link0 - AUI * highest precedence
753 * link1 - BNC
754 * link2 - UTP * lowest precedence
755 *
756 * If none of them is specified then
757 * connector specified in the EEPROM is used
758 * (if present on card or AUI if not).
759 *
760 */
761
762 /* Set the xcvr. */
763 if (ifp->if_flags & IFF_LINK0 && sc->ep_connectors & AUI) {
764 i = ACF_CONNECTOR_AUI;
765 } else if (ifp->if_flags & IFF_LINK1 && sc->ep_connectors & BNC) {
766 i = ACF_CONNECTOR_BNC;
767 } else if (ifp->if_flags & IFF_LINK2 && sc->ep_connectors & UTP) {
768 i = ACF_CONNECTOR_UTP;
769 } else {
770 i = sc->ep_connector;
771 }
772 GO_WINDOW(0);
773 j = inw(BASE + EP_W0_ADDRESS_CFG) & 0x3fff;
774 outw(BASE + EP_W0_ADDRESS_CFG, j | (i << ACF_CONNECTOR_BITS));
775
776 switch(i) {
777 case ACF_CONNECTOR_UTP:
778 if (sc->ep_connectors & UTP) {
779 GO_WINDOW(4);
780 outw(BASE + EP_W4_MEDIA_TYPE, ENABLE_UTP);
781 }
782 break;
783 case ACF_CONNECTOR_BNC:
784 if (sc->ep_connectors & BNC) {
785 outw(BASE + EP_COMMAND, START_TRANSCEIVER);
786 DELAY(1000);
787 }
788 break;
789 case ACF_CONNECTOR_AUI:
790 /* nothing to do */
791 break;
792 default:
793 printf("ep%d: strange connector type in EEPROM: assuming AUI\n",
794 sc->unit);
795 break;
796 }
797
798 outw(BASE + EP_COMMAND, RX_ENABLE);
799 outw(BASE + EP_COMMAND, TX_ENABLE);
800
801 ifp->if_flags |= IFF_RUNNING;
802 ifp->if_flags &= ~IFF_OACTIVE; /* just in case */
803
804 #ifdef EP_LOCAL_STATS
805 sc->rx_no_first = sc->rx_no_mbuf =
806 sc->rx_bpf_disc = sc->rx_overrunf = sc->rx_overrunl =
807 sc->tx_underrun = 0;
808 #endif
809 ep_fset(F_RX_FIRST);
810 if (sc->top) {
811 m_freem(sc->top);
812 sc->top = sc->mcur = 0;
813 }
814 outw(BASE + EP_COMMAND, SET_RX_EARLY_THRESH | RX_INIT_EARLY_THRESH);
815 outw(BASE + EP_COMMAND, SET_TX_START_THRESH | 16);
816
817 /*
818 * Store up a bunch of mbuf's for use later. (MAX_MBS). First we free up
819 * any that we had in case we're being called from intr or somewhere
820 * else.
821 */
822
823 GO_WINDOW(1);
824 epstart(ifp);
825
826 splx(s);
827 }
828
829 static const char padmap[] = {0, 3, 2, 1};
830
831 static void
832 epstart(ifp)
833 struct ifnet *ifp;
834 {
835 register struct ep_softc *sc = ifp->if_softc;
836 register u_int len;
837 register struct mbuf *m;
838 struct mbuf *top;
839 int s, pad;
840
841 if (sc->gone) {
842 return;
843 }
844
845 s = splimp();
846 while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
847 if (ifp->if_flags & IFF_OACTIVE) {
848 splx(s);
849 return;
850 }
851 startagain:
852 /* Sneak a peek at the next packet */
853 m = ifp->if_snd.ifq_head;
854 if (m == 0) {
855 splx(s);
856 return;
857 }
858 for (len = 0, top = m; m; m = m->m_next)
859 len += m->m_len;
860
861 pad = padmap[len & 3];
862
863 /*
864 * The 3c509 automatically pads short packets to minimum ethernet length,
865 * but we drop packets that are too large. Perhaps we should truncate
866 * them instead?
867 */
868 if (len + pad > ETHER_MAX_LEN) {
869 /* packet is obviously too large: toss it */
870 ++ifp->if_oerrors;
871 IF_DEQUEUE(&ifp->if_snd, m);
872 m_freem(m);
873 goto readcheck;
874 }
875 if (inw(BASE + EP_W1_FREE_TX) < len + pad + 4) {
876 /* no room in FIFO */
877 outw(BASE + EP_COMMAND, SET_TX_AVAIL_THRESH | (len + pad + 4));
878 /* make sure */
879 if (inw(BASE + EP_W1_FREE_TX) < len + pad + 4) {
880 ifp->if_flags |= IFF_OACTIVE;
881 splx(s);
882 return;
883 }
884 }
885 IF_DEQUEUE(&ifp->if_snd, m);
886
887 outw(BASE + EP_W1_TX_PIO_WR_1, len);
888 outw(BASE + EP_W1_TX_PIO_WR_1, 0x0); /* Second dword meaningless */
889
890 for (top = m; m != 0; m = m->m_next)
891 if (ep_ftst(F_ACCESS_32_BITS)) {
892 outsl(BASE + EP_W1_TX_PIO_WR_1, mtod(m, caddr_t),
893 m->m_len / 4);
894 if (m->m_len & 3)
895 outsb(BASE + EP_W1_TX_PIO_WR_1,
896 mtod(m, caddr_t) + (m->m_len & (~3)),
897 m->m_len & 3);
898 } else {
899 outsw(BASE + EP_W1_TX_PIO_WR_1, mtod(m, caddr_t), m->m_len / 2);
900 if (m->m_len & 1)
901 outb(BASE + EP_W1_TX_PIO_WR_1,
902 *(mtod(m, caddr_t) + m->m_len - 1));
903 }
904
905 while (pad--)
906 outb(BASE + EP_W1_TX_PIO_WR_1, 0); /* Padding */
907
908 #if NBPFILTER > 0
909 if (ifp->if_bpf) {
910 bpf_mtap(ifp, top);
911 }
912 #endif
913
914 ifp->if_timer = 2;
915 ifp->if_opackets++;
916 m_freem(top);
917
918 /*
919 * Is another packet coming in? We don't want to overflow the tiny RX
920 * fifo.
921 */
922 readcheck:
923 if (inw(BASE + EP_W1_RX_STATUS) & RX_BYTES_MASK) {
924 /*
925 * we check if we have packets left, in that case we prepare to come
926 * back later
927 */
928 if (ifp->if_snd.ifq_head) {
929 outw(BASE + EP_COMMAND, SET_TX_AVAIL_THRESH | 8);
930 }
931 splx(s);
932 return;
933 }
934 goto startagain;
935 }
936
937 void
938 epintr(unit)
939 int unit;
940 {
941 register struct ep_softc *sc = ep_softc[unit];
942
943 if (sc->gone) {
944 return;
945 }
946
947 ep_intr(sc);
948 }
949
950 void
951 ep_intr(arg)
952 void *arg;
953 {
954 struct ep_softc *sc;
955 register int status;
956 struct ifnet *ifp;
957 int x;
958
959 x = splbio();
960
961 sc = (struct ep_softc *)arg;
962
963 ifp = &sc->arpcom.ac_if;
964
965 outw(BASE + EP_COMMAND, SET_INTR_MASK); /* disable all Ints */
966
967 rescan:
968
969 while ((status = inw(BASE + EP_STATUS)) & S_5_INTS) {
970
971 /* first acknowledge all interrupt sources */
972 outw(BASE + EP_COMMAND, ACK_INTR | (status & S_MASK));
973
974 if (status & (S_RX_COMPLETE | S_RX_EARLY)) {
975 epread(sc);
976 continue;
977 }
978 if (status & S_TX_AVAIL) {
979 /* we need ACK */
980 ifp->if_timer = 0;
981 ifp->if_flags &= ~IFF_OACTIVE;
982 GO_WINDOW(1);
983 inw(BASE + EP_W1_FREE_TX);
984 epstart(ifp);
985 }
986 if (status & S_CARD_FAILURE) {
987 ifp->if_timer = 0;
988 #ifdef EP_LOCAL_STATS
989 printf("\nep%d:\n\tStatus: %x\n", sc->unit, status);
990 GO_WINDOW(4);
991 printf("\tFIFO Diagnostic: %x\n", inw(BASE + EP_W4_FIFO_DIAG));
992 printf("\tStat: %x\n", sc->stat);
993 printf("\tIpackets=%d, Opackets=%d\n",
994 ifp->if_ipackets, ifp->if_opackets);
995 printf("\tNOF=%d, NOMB=%d, BPFD=%d, RXOF=%d, RXOL=%d, TXU=%d\n",
996 sc->rx_no_first, sc->rx_no_mbuf, sc->rx_bpf_disc, sc->rx_overrunf,
997 sc->rx_overrunl, sc->tx_underrun);
998 #else
999
1000 #ifdef DIAGNOSTIC
1001 printf("ep%d: Status: %x (input buffer overflow)\n", sc->unit, status);
1002 #else
1003 ++ifp->if_ierrors;
1004 #endif
1005
1006 #endif
1007 epinit(sc);
1008 splx(x);
1009 return;
1010 }
1011 if (status & S_TX_COMPLETE) {
1012 ifp->if_timer = 0;
1013 /* we need ACK. we do it at the end */
1014 /*
1015 * We need to read TX_STATUS until we get a 0 status in order to
1016 * turn off the interrupt flag.
1017 */
1018 while ((status = inb(BASE + EP_W1_TX_STATUS)) & TXS_COMPLETE) {
1019 if (status & TXS_SUCCES_INTR_REQ);
1020 else if (status & (TXS_UNDERRUN | TXS_JABBER | TXS_MAX_COLLISION)) {
1021 outw(BASE + EP_COMMAND, TX_RESET);
1022 if (status & TXS_UNDERRUN) {
1023 #ifdef EP_LOCAL_STATS
1024 sc->tx_underrun++;
1025 #endif
1026 } else {
1027 if (status & TXS_JABBER);
1028 else /* TXS_MAX_COLLISION - we shouldn't get here */
1029 ++ifp->if_collisions;
1030 }
1031 ++ifp->if_oerrors;
1032 outw(BASE + EP_COMMAND, TX_ENABLE);
1033 /*
1034 * To have a tx_avail_int but giving the chance to the
1035 * Reception
1036 */
1037 if (ifp->if_snd.ifq_head) {
1038 outw(BASE + EP_COMMAND, SET_TX_AVAIL_THRESH | 8);
1039 }
1040 }
1041 outb(BASE + EP_W1_TX_STATUS, 0x0); /* pops up the next
1042 * status */
1043 } /* while */
1044 ifp->if_flags &= ~IFF_OACTIVE;
1045 GO_WINDOW(1);
1046 inw(BASE + EP_W1_FREE_TX);
1047 epstart(ifp);
1048 } /* end TX_COMPLETE */
1049 }
1050
1051 outw(BASE + EP_COMMAND, C_INTR_LATCH); /* ACK int Latch */
1052
1053 if ((status = inw(BASE + EP_STATUS)) & S_5_INTS)
1054 goto rescan;
1055
1056 /* re-enable Ints */
1057 outw(BASE + EP_COMMAND, SET_INTR_MASK | S_5_INTS);
1058
1059 splx(x);
1060 }
1061
1062 static void
1063 epread(sc)
1064 register struct ep_softc *sc;
1065 {
1066 struct ether_header *eh;
1067 struct mbuf *top, *mcur, *m;
1068 struct ifnet *ifp;
1069 int lenthisone;
1070
1071 short rx_fifo2, status;
1072 register short delta;
1073 register short rx_fifo;
1074
1075 ifp = &sc->arpcom.ac_if;
1076 status = inw(BASE + EP_W1_RX_STATUS);
1077
1078 read_again:
1079
1080 if (status & ERR_RX) {
1081 ++ifp->if_ierrors;
1082 if (status & ERR_RX_OVERRUN) {
1083 /*
1084 * we can think the rx latency is actually greather than we
1085 * expect
1086 */
1087 #ifdef EP_LOCAL_STATS
1088 if (ep_ftst(F_RX_FIRST))
1089 sc->rx_overrunf++;
1090 else
1091 sc->rx_overrunl++;
1092 #endif
1093 }
1094 goto out;
1095 }
1096 rx_fifo = rx_fifo2 = status & RX_BYTES_MASK;
1097
1098 if (ep_ftst(F_RX_FIRST)) {
1099 MGETHDR(m, M_DONTWAIT, MT_DATA);
1100 if (!m)
1101 goto out;
1102 if (rx_fifo >= MINCLSIZE)
1103 MCLGET(m, M_DONTWAIT);
1104 sc->top = sc->mcur = top = m;
1105 #define EROUND ((sizeof(struct ether_header) + 3) & ~3)
1106 #define EOFF (EROUND - sizeof(struct ether_header))
1107 top->m_data += EOFF;
1108
1109 /* Read what should be the header. */
1110 insw(BASE + EP_W1_RX_PIO_RD_1,
1111 mtod(top, caddr_t), sizeof(struct ether_header) / 2);
1112 top->m_len = sizeof(struct ether_header);
1113 rx_fifo -= sizeof(struct ether_header);
1114 sc->cur_len = rx_fifo2;
1115 } else {
1116 /* come here if we didn't have a complete packet last time */
1117 top = sc->top;
1118 m = sc->mcur;
1119 sc->cur_len += rx_fifo2;
1120 }
1121
1122 /* Reads what is left in the RX FIFO */
1123 while (rx_fifo > 0) {
1124 lenthisone = min(rx_fifo, M_TRAILINGSPACE(m));
1125 if (lenthisone == 0) { /* no room in this one */
1126 mcur = m;
1127 MGET(m, M_DONTWAIT, MT_DATA);
1128 if (!m)
1129 goto out;
1130 if (rx_fifo >= MINCLSIZE)
1131 MCLGET(m, M_DONTWAIT);
1132 m->m_len = 0;
1133 mcur->m_next = m;
1134 lenthisone = min(rx_fifo, M_TRAILINGSPACE(m));
1135 }
1136 if (ep_ftst(F_ACCESS_32_BITS)) { /* default for EISA configured cards*/
1137 insl(BASE + EP_W1_RX_PIO_RD_1, mtod(m, caddr_t) + m->m_len,
1138 lenthisone / 4);
1139 m->m_len += (lenthisone & ~3);
1140 if (lenthisone & 3)
1141 insb(BASE + EP_W1_RX_PIO_RD_1,
1142 mtod(m, caddr_t) + m->m_len,
1143 lenthisone & 3);
1144 m->m_len += (lenthisone & 3);
1145 } else {
1146 insw(BASE + EP_W1_RX_PIO_RD_1, mtod(m, caddr_t) + m->m_len,
1147 lenthisone / 2);
1148 m->m_len += lenthisone;
1149 if (lenthisone & 1)
1150 *(mtod(m, caddr_t) + m->m_len - 1) = inb(BASE + EP_W1_RX_PIO_RD_1);
1151 }
1152 rx_fifo -= lenthisone;
1153 }
1154
1155 if (status & ERR_RX_INCOMPLETE) { /* we haven't received the complete
1156 * packet */
1157 sc->mcur = m;
1158 #ifdef EP_LOCAL_STATS
1159 sc->rx_no_first++; /* to know how often we come here */
1160 #endif
1161 ep_frst(F_RX_FIRST);
1162 if (!((status = inw(BASE + EP_W1_RX_STATUS)) & ERR_RX_INCOMPLETE)) {
1163 /* we see if by now, the packet has completly arrived */
1164 goto read_again;
1165 }
1166 outw(BASE + EP_COMMAND, SET_RX_EARLY_THRESH | RX_NEXT_EARLY_THRESH);
1167 return;
1168 }
1169 all_pkt:
1170 outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK);
1171 ++ifp->if_ipackets;
1172 ep_fset(F_RX_FIRST);
1173 top->m_pkthdr.rcvif = &sc->arpcom.ac_if;
1174 top->m_pkthdr.len = sc->cur_len;
1175
1176 #if NBPFILTER > 0
1177 if (ifp->if_bpf)
1178 bpf_mtap(ifp, top);
1179 #endif
1180 #ifdef BRIDGE
1181 if (do_bridge) {
1182 struct ifnet * bdg_ifp ;
1183
1184 bdg_ifp = bridge_in(top);
1185 if (bdg_ifp == BDG_DROP)
1186 goto dropit ;
1187 if (bdg_ifp != BDG_LOCAL)
1188 bdg_forward(&(sc->top), bdg_ifp);
1189 if (bdg_ifp !=BDG_LOCAL && bdg_ifp !=BDG_BCAST && bdg_ifp !=BDG_MCAST)
1190 goto dropit ;
1191 /* all others accepted locally */
1192 goto getit ;
1193 }
1194 #endif
1195
1196 /*
1197 * If we are in promiscuous mode, we have to
1198 * check if this packet is really ours.
1199 */
1200 eh = mtod(top, struct ether_header *);
1201 if ((ifp->if_flags & IFF_PROMISC) &&
1202 (eh->ether_dhost[0] & 1) == 0 &&
1203 bcmp(eh->ether_dhost, sc->arpcom.ac_enaddr,
1204 sizeof(eh->ether_dhost)) != 0 &&
1205 bcmp(eh->ether_dhost, etherbroadcastaddr,
1206 sizeof(eh->ether_dhost)) != 0) {
1207 dropit:
1208 if (sc->top) {
1209 m_freem(sc->top);
1210 sc->top = 0;
1211 }
1212 ep_fset(F_RX_FIRST);
1213 #ifdef EP_LOCAL_STATS
1214 sc->rx_bpf_disc++;
1215 #endif
1216 while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
1217 outw(BASE + EP_COMMAND, SET_RX_EARLY_THRESH | RX_INIT_EARLY_THRESH);
1218 return;
1219 }
1220 getit:
1221 eh = mtod(top, struct ether_header *);
1222 m_adj(top, sizeof(struct ether_header));
1223 ether_input(ifp, eh, top);
1224 sc->top = 0;
1225 while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
1226 outw(BASE + EP_COMMAND, SET_RX_EARLY_THRESH | RX_INIT_EARLY_THRESH);
1227 return;
1228
1229 out:
1230 outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK);
1231 if (sc->top) {
1232 m_freem(sc->top);
1233 sc->top = 0;
1234 #ifdef EP_LOCAL_STATS
1235 sc->rx_no_mbuf++;
1236 #endif
1237 }
1238 ep_fset(F_RX_FIRST);
1239 while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
1240 outw(BASE + EP_COMMAND, SET_RX_EARLY_THRESH | RX_INIT_EARLY_THRESH);
1241 }
1242
1243 /*
1244 * Look familiar?
1245 */
1246 static int
1247 epioctl(ifp, cmd, data)
1248 register struct ifnet *ifp;
1249 int cmd;
1250 caddr_t data;
1251 {
1252 register struct ifaddr *ifa = (struct ifaddr *) data;
1253 struct ep_softc *sc = ifp->if_softc;
1254 struct ifreq *ifr = (struct ifreq *) data;
1255 int s, error = 0;
1256
1257 s = splimp();
1258
1259 switch (cmd) {
1260 case SIOCSIFADDR:
1261 ifp->if_flags |= IFF_UP;
1262
1263 /* netifs are BUSY when UP */
1264
1265 switch (ifa->ifa_addr->sa_family) {
1266 #ifdef INET
1267 case AF_INET:
1268 epinit(sc); /* before arpwhohas */
1269 arp_ifinit((struct arpcom *)ifp, ifa);
1270 break;
1271 #endif
1272 #ifdef IPX
1273 case AF_IPX:
1274 {
1275 register struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr);
1276
1277 if (ipx_nullhost(*ina))
1278 ina->x_host =
1279 *(union ipx_host *) (sc->arpcom.ac_enaddr);
1280 else {
1281 ifp->if_flags &= ~IFF_RUNNING;
1282 bcopy((caddr_t) ina->x_host.c_host,
1283 (caddr_t) sc->arpcom.ac_enaddr,
1284 sizeof(sc->arpcom.ac_enaddr));
1285 }
1286 epinit(sc);
1287 break;
1288 }
1289 #endif
1290 #ifdef NS
1291 case AF_NS:
1292 {
1293 register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
1294
1295 if (ns_nullhost(*ina))
1296 ina->x_host =
1297 *(union ns_host *) (sc->arpcom.ac_enaddr);
1298 else {
1299 ifp->if_flags &= ~IFF_RUNNING;
1300 bcopy((caddr_t) ina->x_host.c_host,
1301 (caddr_t) sc->arpcom.ac_enaddr,
1302 sizeof(sc->arpcom.ac_enaddr));
1303 }
1304 epinit(sc);
1305 break;
1306 }
1307 #endif
1308 default:
1309 epinit(sc);
1310 break;
1311 }
1312 break;
1313 case SIOCGIFADDR:
1314 {
1315 struct sockaddr *sa;
1316
1317 sa = (struct sockaddr *) & ifr->ifr_data;
1318 bcopy((caddr_t) sc->arpcom.ac_enaddr,
1319 (caddr_t) sa->sa_data, ETHER_ADDR_LEN);
1320 }
1321 break;
1322 case SIOCSIFFLAGS:
1323
1324 if ((ifp->if_flags & IFF_UP) == 0 && ifp->if_flags & IFF_RUNNING) {
1325 ifp->if_flags &= ~IFF_RUNNING;
1326 epstop(sc);
1327 break;
1328 } else {
1329 /* reinitialize card on any parameter change */
1330 epinit(sc);
1331 break;
1332 }
1333
1334 /* NOTREACHED */
1335 break;
1336 #ifdef notdef
1337 case SIOCGHWADDR:
1338 bcopy((caddr_t) sc->sc_addr, (caddr_t) & ifr->ifr_data,
1339 sizeof(sc->sc_addr));
1340 break;
1341 #endif
1342 case SIOCSIFMTU:
1343
1344 /*
1345 * Set the interface MTU.
1346 */
1347 if (ifr->ifr_mtu > ETHERMTU) {
1348 error = EINVAL;
1349 } else {
1350 ifp->if_mtu = ifr->ifr_mtu;
1351 }
1352 break;
1353 case SIOCADDMULTI:
1354 case SIOCDELMULTI:
1355 /* Now this driver has no support for programmable
1356 * multicast filters. If some day it will gain this
1357 * support this part of code must be extended.
1358 */
1359 error = 0;
1360 break;
1361 default:
1362 error = EINVAL;
1363 }
1364
1365 splx(s);
1366
1367 return (error);
1368 }
1369
1370 static void
1371 epwatchdog(ifp)
1372 struct ifnet *ifp;
1373 {
1374 struct ep_softc *sc = ifp->if_softc;
1375
1376 /*
1377 printf("ep: watchdog\n");
1378
1379 log(LOG_ERR, "ep%d: watchdog\n", ifp->if_unit);
1380 ifp->if_oerrors++;
1381 */
1382
1383 if (sc->gone) {
1384 return;
1385 }
1386
1387 ifp->if_flags &= ~IFF_OACTIVE;
1388 epstart(ifp);
1389 ep_intr(ifp->if_softc);
1390 }
1391
1392 static void
1393 epstop(sc)
1394 struct ep_softc *sc;
1395 {
1396 if (sc->gone) {
1397 return;
1398 }
1399
1400 outw(BASE + EP_COMMAND, RX_DISABLE);
1401 outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK);
1402 while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
1403 outw(BASE + EP_COMMAND, TX_DISABLE);
1404 outw(BASE + EP_COMMAND, STOP_TRANSCEIVER);
1405 outw(BASE + EP_COMMAND, RX_RESET);
1406 outw(BASE + EP_COMMAND, TX_RESET);
1407 while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
1408 outw(BASE + EP_COMMAND, C_INTR_LATCH);
1409 outw(BASE + EP_COMMAND, SET_RD_0_MASK);
1410 outw(BASE + EP_COMMAND, SET_INTR_MASK);
1411 outw(BASE + EP_COMMAND, SET_RX_FILTER);
1412 }
1413
1414
1415 #if 0
1416 static int
1417 send_ID_sequence(port)
1418 int port;
1419 {
1420 int cx, al;
1421
1422 for (al = 0xff, cx = 0; cx < 255; cx++) {
1423 outb(port, al);
1424 al <<= 1;
1425 if (al & 0x100)
1426 al ^= 0xcf;
1427 }
1428 return (1);
1429 }
1430 #endif
1431
1432
1433 /*
1434 * We get eeprom data from the id_port given an offset into the eeprom.
1435 * Basically; after the ID_sequence is sent to all of the cards; they enter
1436 * the ID_CMD state where they will accept command requests. 0x80-0xbf loads
1437 * the eeprom data. We then read the port 16 times and with every read; the
1438 * cards check for contention (ie: if one card writes a 0 bit and another
1439 * writes a 1 bit then the host sees a 0. At the end of the cycle; each card
1440 * compares the data on the bus; if there is a difference then that card goes
1441 * into ID_WAIT state again). In the meantime; one bit of data is returned in
1442 * the AX register which is conveniently returned to us by inb(). Hence; we
1443 * read 16 times getting one bit of data with each read.
1444 */
1445 static int
1446 get_eeprom_data(id_port, offset)
1447 int id_port;
1448 int offset;
1449 {
1450 int i, data = 0;
1451 outb(id_port, 0x80 + offset);
1452 DELAY(1000);
1453 for (i = 0; i < 16; i++)
1454 data = (data << 1) | (inw(id_port) & 1);
1455 return (data);
1456 }
1457
1458 #endif /* NEP > 0 */
Cache object: 726813b57d7f39587c4843b6f749fb52
|