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