2 * All Rights Reserved, Copyright (C) Fujitsu Limited 1995
4 * This software may be used, modified, copied, distributed, and sold, in
5 * both source and binary form provided that the above copyright, these
6 * terms and the following disclaimer are retained. The name of the author
7 * and/or the contributor may not be used to endorse or promote products
8 * derived from this software without specific prior written permission.
10 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND THE CONTRIBUTOR ``AS IS'' AND
11 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
12 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR THE CONTRIBUTOR BE LIABLE
14 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
15 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
16 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION.
17 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
18 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
19 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 #include <sys/cdefs.h>
25 __FBSDID("$FreeBSD$");
27 #include <sys/param.h>
28 #include <sys/systm.h>
29 #include <sys/kernel.h>
30 #include <sys/socket.h>
31 #include <sys/module.h>
34 #include <machine/bus.h>
37 #include <net/ethernet.h>
39 #include <net/if_mib.h>
40 #include <net/if_media.h>
42 #include <netinet/in.h>
43 #include <netinet/if_ether.h>
45 #include <dev/fe/mb86960.h>
46 #include <dev/fe/if_fereg.h>
47 #include <dev/fe/if_fevar.h>
49 #include <isa/isavar.h>
54 static int fe_isa_probe(device_t);
55 static int fe_isa_attach(device_t);
57 static struct isa_pnp_id fe_ids[] = {
58 { 0x101ee0d, NULL }, /* CON0101 - Contec C-NET(98)P2-T */
62 static device_method_t fe_isa_methods[] = {
63 /* Device interface */
64 DEVMETHOD(device_probe, fe_isa_probe),
65 DEVMETHOD(device_attach, fe_isa_attach),
70 static driver_t fe_isa_driver = {
73 sizeof (struct fe_softc)
76 DRIVER_MODULE(fe, isa, fe_isa_driver, fe_devclass, 0, 0);
79 static int fe98_alloc_port(device_t, int);
81 static int fe_probe_re1000(device_t);
82 static int fe_probe_cnet9ne(device_t);
83 static int fe_probe_rex(device_t);
84 static int fe_probe_ssi(device_t);
85 static int fe_probe_jli(device_t);
86 static int fe_probe_lnx(device_t);
87 static int fe_probe_gwy(device_t);
88 static int fe_probe_ubn(device_t);
91 * Determine if the device is present at a specified I/O address. The
92 * main entry to the driver.
95 fe_isa_probe(device_t dev)
100 /* Prepare for the softc struct. */
101 sc = device_get_softc(dev);
102 sc->sc_unit = device_get_unit(dev);
104 /* Check isapnp ids */
105 error = ISA_PNP_PROBE(device_get_parent(dev), dev, fe_ids);
107 /* If the card had a PnP ID that didn't match any we know about */
111 /* If we had some other problem. */
112 if (!(error == 0 || error == ENOENT))
115 /* Probe for supported boards. */
116 if ((error = fe_probe_re1000(dev)) == 0)
118 fe_release_resource(dev);
120 if ((error = fe_probe_cnet9ne(dev)) == 0)
122 fe_release_resource(dev);
124 if ((error = fe_probe_rex(dev)) == 0)
126 fe_release_resource(dev);
128 if ((error = fe_probe_ssi(dev)) == 0)
130 fe_release_resource(dev);
132 if ((error = fe_probe_jli(dev)) == 0)
134 fe_release_resource(dev);
136 if ((error = fe_probe_lnx(dev)) == 0)
138 fe_release_resource(dev);
140 if ((error = fe_probe_ubn(dev)) == 0)
142 fe_release_resource(dev);
144 if ((error = fe_probe_gwy(dev)) == 0)
146 fe_release_resource(dev);
150 error = fe_alloc_irq(dev, 0);
152 fe_release_resource(dev);
157 fe_isa_attach(device_t dev)
159 struct fe_softc *sc = device_get_softc(dev);
163 * Note: these routines aren't expected to fail since we also call
164 * them in the probe routine. But coverity complains, so we'll honor
165 * that complaint since the intention here was never to ignore them..
168 error = fe98_alloc_port(dev, sc->type);
172 error = fe_alloc_irq(dev, 0);
176 return fe_attach(dev);
180 /* Generic I/O address table */
181 static bus_addr_t ioaddr_generic[MAXREGISTERS] = {
182 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007,
183 0x008, 0x009, 0x00a, 0x00b, 0x00c, 0x00d, 0x00e, 0x00f,
184 0x010, 0x011, 0x012, 0x013, 0x014, 0x015, 0x016, 0x017,
185 0x018, 0x019, 0x01a, 0x01b, 0x01c, 0x01d, 0x01e, 0x01f,
188 /* I/O address table for RE1000/1000Plus */
189 static bus_addr_t ioaddr_re1000[MAXREGISTERS] = {
190 0x0000, 0x0001, 0x0200, 0x0201, 0x0400, 0x0401, 0x0600, 0x0601,
191 0x0800, 0x0801, 0x0a00, 0x0a01, 0x0c00, 0x0c01, 0x0e00, 0x0e01,
192 0x1000, 0x1200, 0x1400, 0x1600, 0x1800, 0x1a00, 0x1c00, 0x1e00,
193 0x1001, 0x1201, 0x1401, 0x1601, 0x1801, 0x1a01, 0x1c01, 0x1e01,
196 /* I/O address table for CNET9NE */
197 static bus_addr_t ioaddr_cnet9ne[MAXREGISTERS] = {
198 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007,
199 0x008, 0x009, 0x00a, 0x00b, 0x00c, 0x00d, 0x00e, 0x00f,
200 0x400, 0x402, 0x404, 0x406, 0x408, 0x40a, 0x40c, 0x40e,
201 0x401, 0x403, 0x405, 0x407, 0x409, 0x40b, 0x40d, 0x40f,
204 /* I/O address table for LAC-98 */
205 static bus_addr_t ioaddr_lnx[MAXREGISTERS] = {
206 0x000, 0x002, 0x004, 0x006, 0x008, 0x00a, 0x00c, 0x00e,
207 0x100, 0x102, 0x104, 0x106, 0x108, 0x10a, 0x10c, 0x10e,
208 0x200, 0x202, 0x204, 0x206, 0x208, 0x20a, 0x20c, 0x20e,
209 0x300, 0x302, 0x304, 0x306, 0x308, 0x30a, 0x30c, 0x30e,
212 /* I/O address table for Access/PC N98C+ */
213 static bus_addr_t ioaddr_ubn[MAXREGISTERS] = {
214 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007,
215 0x008, 0x009, 0x00a, 0x00b, 0x00c, 0x00d, 0x00e, 0x00f,
216 0x200, 0x201, 0x202, 0x203, 0x204, 0x205, 0x206, 0x207,
217 0x208, 0x209, 0x20a, 0x20b, 0x20c, 0x20d, 0x20e, 0x20f,
220 /* I/O address table for REX-9880 */
221 static bus_addr_t ioaddr_rex[MAXREGISTERS] = {
222 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007,
223 0x008, 0x009, 0x00a, 0x00b, 0x00c, 0x00d, 0x00e, 0x00f,
224 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107,
225 0x108, 0x109, 0x10a, 0x10b, 0x10c, 0x10d, 0x10e, 0x10f,
229 fe98_alloc_port(device_t dev, int type)
231 struct fe_softc *sc = device_get_softc(dev);
232 struct resource *res;
241 case FE_TYPE_CNET9NE:
242 iat = ioaddr_cnet9ne;
246 iat = ioaddr_generic;
254 iat = ioaddr_generic;
266 iat = ioaddr_generic;
272 res = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid,
273 iat, size, RF_ACTIVE);
277 isa_load_resourcev(res, iat, size);
280 sc->port_used = size;
287 * Probe and initialization for Allied-Telesis RE1000 series.
290 fe_init_re1000(struct fe_softc *sc)
292 /* Setup IRQ control register on the ASIC. */
293 fe_outb(sc, FE_RE1000_IRQCONF, sc->priv_info);
297 fe_probe_re1000(device_t dev)
299 struct fe_softc *sc = device_get_softc(dev);
301 rman_res_t iobase, irq;
304 static struct fe_simple_probe_struct probe_table [] = {
305 { FE_DLCR2, 0x58, 0x00 },
306 { FE_DLCR4, 0x08, 0x00 },
310 /* See if the specified I/O address is possible for RE1000. */
311 /* [01]D[02468ACE] are allowed. */
312 if (bus_get_resource(dev, SYS_RES_IOPORT, 0, &iobase, NULL) != 0)
314 if ((iobase & ~0x10E) != 0xD0)
317 if (fe98_alloc_port(dev, FE_TYPE_RE1000))
320 /* Fill the softc struct with default values. */
321 fe_softc_defaults(sc);
323 /* See if the card is on its address. */
324 if (!fe_simple_probe(sc, probe_table))
327 /* Get our station address from EEPROM. */
328 fe_inblk(sc, 0x18, sc->enaddr, ETHER_ADDR_LEN);
330 /* Make sure it is Allied-Telesis's. */
331 if (!fe_valid_Ether_p(sc->enaddr, 0x0000F4))
334 /* Calculate checksum. */
335 sum = fe_inb(sc, 0x1e);
336 for (i = 0; i < ETHER_ADDR_LEN; i++)
337 sum ^= sc->enaddr[i];
341 /* Setup the board type. */
342 sc->typestr = "RE1000";
344 /* This looks like an RE1000 board. It requires an
345 explicit IRQ setting in config. Make sure we have one,
346 determining an appropriate value for the IRQ control
349 bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, NULL);
351 case 3: n = 0x10; break;
352 case 5: n = 0x20; break;
353 case 6: n = 0x40; break;
354 case 12: n = 0x80; break;
356 fe_irq_failure(sc->typestr, sc->sc_unit, irq, "3/5/6/12");
359 sc->priv_info = (fe_inb(sc, FE_RE1000_IRQCONF) & 0x0f) | n;
361 /* Setup hooks. We need a special initialization procedure. */
362 sc->init = fe_init_re1000;
367 /* JLI sub-probe for Allied-Telesis RE1000Plus/ME1500 series. */
368 static u_short const *
369 fe_probe_jli_re1000p(struct fe_softc * sc, u_char const * eeprom)
372 static u_short const irqmaps_re1000p [4] = { 3, 5, 6, 12 };
374 /* Make sure the EEPROM contains Allied-Telesis bit pattern. */
375 if (eeprom[1] != 0xFF) return NULL;
376 for (i = 2; i < 8; i++) if (eeprom[i] != 0xFF) return NULL;
377 for (i = 14; i < 24; i++) if (eeprom[i] != 0xFF) return NULL;
379 /* Get our station address from EEPROM, and make sure the
380 EEPROM contains Allied-Telesis's address. */
381 bcopy(eeprom + 8, sc->enaddr, ETHER_ADDR_LEN);
382 if (!fe_valid_Ether_p(sc->enaddr, 0x0000F4))
385 /* I don't know any sub-model identification. */
386 sc->typestr = "RE1000Plus/ME1500";
388 /* Returns the IRQ table for the RE1000Plus. */
389 return irqmaps_re1000p;
394 * Probe for Allied-Telesis RE1000Plus/ME1500 series.
397 fe_probe_jli(device_t dev)
399 struct fe_softc *sc = device_get_softc(dev);
400 int i, n, xirq, error;
401 rman_res_t iobase, irq;
402 u_char eeprom [JLI_EEPROM_SIZE];
403 u_short const * irqmap;
405 static u_short const baseaddr [8] =
406 { 0x1D6, 0x1D8, 0x1DA, 0x1D4, 0x0D4, 0x0D2, 0x0D8, 0x0D0 };
407 static struct fe_simple_probe_struct const probe_table [] = {
408 /* { FE_DLCR1, 0x20, 0x00 }, Doesn't work. */
409 { FE_DLCR2, 0x50, 0x00 },
410 { FE_DLCR4, 0x08, 0x00 },
411 /* { FE_DLCR5, 0x80, 0x00 }, Doesn't work. */
413 { FE_BMPR16, 0x1B, 0x00 },
414 { FE_BMPR17, 0x7F, 0x00 },
420 * See if the specified address is possible for MB86965A JLI mode.
422 if (bus_get_resource(dev, SYS_RES_IOPORT, 0, &iobase, NULL) != 0)
424 for (i = 0; i < 8; i++) {
425 if (baseaddr[i] == iobase)
431 if (fe98_alloc_port(dev, FE_TYPE_RE1000))
434 /* Fill the softc struct with default values. */
435 fe_softc_defaults(sc);
438 * We should test if MB86965A is on the base address now.
439 * Unfortunately, it is very hard to probe it reliably, since
440 * we have no way to reset the chip under software control.
441 * On cold boot, we could check the "signature" bit patterns
442 * described in the Fujitsu document. On warm boot, however,
443 * we can predict almost nothing about register values.
445 if (!fe_simple_probe(sc, probe_table))
448 /* Check if our I/O address matches config info on 86965. */
449 n = (fe_inb(sc, FE_BMPR19) & FE_B19_ADDR) >> FE_B19_ADDR_SHIFT;
450 if (baseaddr[n] != iobase)
454 * We are now almost sure we have an MB86965 at the given
455 * address. So, read EEPROM through it. We have to write
456 * into LSI registers to read from EEPROM. I want to avoid it
457 * at this stage, but I cannot test the presence of the chip
458 * any further without reading EEPROM. FIXME.
460 fe_read_eeprom_jli(sc, eeprom);
462 /* Make sure that config info in EEPROM and 86965 agree. */
463 if (eeprom[FE_EEPROM_CONF] != fe_inb(sc, FE_BMPR19))
466 /* Use 86965 media selection scheme, unless othewise
467 specified. It is "AUTO always" and "select with BMPR13".
468 This behaviour covers most of the 86965 based board (as
469 minimum requirements.) It is backward compatible with
470 previous versions, also. */
472 sc->defmedia = MB_HA;
473 sc->msel = fe_msel_965;
475 /* Perform board-specific probe. */
476 if ((irqmap = fe_probe_jli_re1000p(sc, eeprom)) == NULL)
479 /* Find the IRQ read from EEPROM. */
480 n = (fe_inb(sc, FE_BMPR19) & FE_B19_IRQ) >> FE_B19_IRQ_SHIFT;
483 /* Try to determine IRQ setting. */
484 error = bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, NULL);
485 if (error && xirq == NO_IRQ) {
486 /* The device must be configured with an explicit IRQ. */
487 device_printf(dev, "IRQ auto-detection does not work\n");
489 } else if (error && xirq != NO_IRQ) {
490 /* Just use the probed IRQ value. */
491 bus_set_resource(dev, SYS_RES_IRQ, 0, xirq, 1);
492 } else if (!error && xirq == NO_IRQ) {
493 /* No problem. Go ahead. */
494 } else if (irq == xirq) {
495 /* Good. Go ahead. */
497 /* User must be warned in this case. */
498 sc->stability |= UNSTABLE_IRQ;
501 /* Setup a hook, which resets te 86965 when the driver is being
502 initialized. This may solve a nasty bug. FIXME. */
503 sc->init = fe_init_jli;
510 * Probe and initialization for Contec C-NET(9N)E series.
513 /* TODO: Should be in "if_fereg.h" */
514 #define FE_CNET9NE_INTR 0x10 /* Interrupt Mask? */
517 fe_init_cnet9ne(struct fe_softc *sc)
519 /* Enable interrupt? FIXME. */
520 fe_outb(sc, FE_CNET9NE_INTR, 0x10);
524 fe_probe_cnet9ne (device_t dev)
526 struct fe_softc *sc = device_get_softc(dev);
527 rman_res_t iobase, irq;
529 static struct fe_simple_probe_struct probe_table [] = {
530 { FE_DLCR2, 0x58, 0x00 },
531 { FE_DLCR4, 0x08, 0x00 },
535 /* See if the specified I/O address is possible for C-NET(9N)E. */
536 if (bus_get_resource(dev, SYS_RES_IOPORT, 0, &iobase, NULL) != 0)
538 if (iobase != 0x73D0)
541 if (fe98_alloc_port(dev, FE_TYPE_CNET9NE))
544 /* Fill the softc struct with default values. */
545 fe_softc_defaults(sc);
547 /* See if the card is on its address. */
548 if (!fe_simple_probe(sc, probe_table))
551 /* Get our station address from EEPROM. */
552 fe_inblk(sc, 0x18, sc->enaddr, ETHER_ADDR_LEN);
554 /* Make sure it is Contec's. */
555 if (!fe_valid_Ether_p(sc->enaddr, 0x00804C))
558 /* Determine the card type. */
559 if (sc->enaddr[3] == 0x06) {
560 sc->typestr = "C-NET(9N)C";
562 /* We seems to need our own IDENT bits... FIXME. */
563 sc->proto_dlcr7 = FE_D7_BYTSWP_LH | FE_D7_IDENT_NICE;
565 /* C-NET(9N)C requires an explicit IRQ to work. */
566 if (bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, NULL) != 0) {
567 fe_irq_failure(sc->typestr, sc->sc_unit, NO_IRQ, NULL);
571 sc->typestr = "C-NET(9N)E";
573 /* C-NET(9N)E works only IRQ5. */
574 if (bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, NULL) != 0)
577 fe_irq_failure(sc->typestr, sc->sc_unit, irq, "5");
581 /* We need an init hook to initialize ASIC before we start. */
582 sc->init = fe_init_cnet9ne;
585 /* C-NET(9N)E has 64KB SRAM. */
586 sc->proto_dlcr6 = FE_D6_BUFSIZ_64KB | FE_D6_TXBSIZ_2x4KB
587 | FE_D6_BBW_WORD | FE_D6_SBW_WORD | FE_D6_SRAM;
594 * Probe for Contec C-NET(98)P2 series.
595 * (Logitec LAN-98TP/LAN-98T25P - parhaps)
598 fe_probe_ssi(device_t dev)
600 struct fe_softc *sc = device_get_softc(dev);
601 rman_res_t iobase, irq;
603 u_char eeprom [SSI_EEPROM_SIZE];
604 static struct fe_simple_probe_struct probe_table [] = {
605 { FE_DLCR2, 0x08, 0x00 },
606 { FE_DLCR4, 0x08, 0x00 },
609 static u_short const irqmap[] = {
611 NO_IRQ, NO_IRQ, NO_IRQ, 3, NO_IRQ, 5, 6, NO_IRQ,
612 NO_IRQ, 9, 10, NO_IRQ, 12, 13, NO_IRQ, NO_IRQ,
613 /* INT3 INT41 INT5 INT6 */
616 /* See if the specified I/O address is possible for 78Q8377A. */
617 /* [0-D]3D0 are allowed. */
618 if (bus_get_resource(dev, SYS_RES_IOPORT, 0, &iobase, NULL) != 0)
620 if ((iobase & 0xFFF) != 0x3D0)
623 if (fe98_alloc_port(dev, FE_TYPE_SSI))
626 /* Fill the softc struct with default values. */
627 fe_softc_defaults(sc);
629 /* See if the card is on its address. */
630 if (!fe_simple_probe(sc, probe_table))
633 /* We now have to read the config EEPROM. We should be very
634 careful, since doing so destroys a register. (Remember, we
635 are not yet sure we have a C-NET(98)P2 board here.) Don't
636 remember to select BMPRs bofore reading EEPROM, since other
637 register bank may be selected before the probe() is called. */
638 fe_read_eeprom_ssi(sc, eeprom);
640 /* Make sure the Ethernet (MAC) station address is of Contec's. */
641 if (!fe_valid_Ether_p(eeprom + FE_SSI_EEP_ADDR, 0x00804C))
643 bcopy(eeprom + FE_SSI_EEP_ADDR, sc->enaddr, ETHER_ADDR_LEN);
645 /* Setup the board type. */
646 sc->typestr = "C-NET(98)P2";
648 /* Non-PnP mode, set static resource from eeprom. */
649 if (!isa_get_vendorid(dev)) {
650 /* Get IRQ configuration from EEPROM. */
651 irq = irqmap[eeprom[FE_SSI_EEP_IRQ]];
653 fe_irq_failure(sc->typestr, sc->sc_unit, irq,
657 bus_set_resource(dev, SYS_RES_IRQ, 0, irq, 1);
660 /* Get Duplex-mode configuration from EEPROM. */
661 sc->proto_dlcr4 |= (eeprom[FE_SSI_EEP_DUPLEX] & FE_D4_DSC);
663 /* Fill softc struct accordingly. */
665 sc->defmedia = MB_HT;
672 * Probe for TDK LAC-98012/013/025/9N011 - parhaps.
675 fe_probe_lnx(device_t dev)
677 struct fe_softc *sc = device_get_softc(dev);
679 rman_res_t iobase, irq;
680 u_char eeprom [LNX_EEPROM_SIZE];
682 static struct fe_simple_probe_struct probe_table [] = {
683 { FE_DLCR2, 0x58, 0x00 },
684 { FE_DLCR4, 0x08, 0x00 },
688 /* See if the specified I/O address is possible for TDK/LANX boards. */
689 /* 0D0, 4D0, 8D0, and CD0 are allowed. */
690 if (bus_get_resource(dev, SYS_RES_IOPORT, 0, &iobase, NULL) != 0)
692 if ((iobase & ~0xC00) != 0xD0)
695 if (fe98_alloc_port(dev, FE_TYPE_LNX))
698 /* Fill the softc struct with default values. */
699 fe_softc_defaults(sc);
701 /* See if the card is on its address. */
702 if (!fe_simple_probe(sc, probe_table))
705 /* We now have to read the config EEPROM. We should be very
706 careful, since doing so destroys a register. (Remember, we
707 are not yet sure we have a LAC-98012/98013 board here.) */
708 fe_read_eeprom_lnx(sc, eeprom);
710 /* Make sure the Ethernet (MAC) station address is of TDK/LANX's. */
711 if (!fe_valid_Ether_p(eeprom, 0x008098))
713 bcopy(eeprom, sc->enaddr, ETHER_ADDR_LEN);
715 /* Setup the board type. */
716 sc->typestr = "LAC-98012/98013";
718 /* This looks like a TDK/LANX board. It requires an
719 explicit IRQ setting in config. Make sure we have one,
720 determining an appropriate value for the IRQ control
723 if (bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, NULL) != 0)
726 case 3 : sc->priv_info = 0x10 | LNX_CLK_LO | LNX_SDA_HI; break;
727 case 5 : sc->priv_info = 0x20 | LNX_CLK_LO | LNX_SDA_HI; break;
728 case 6 : sc->priv_info = 0x40 | LNX_CLK_LO | LNX_SDA_HI; break;
729 case 12: sc->priv_info = 0x80 | LNX_CLK_LO | LNX_SDA_HI; break;
731 fe_irq_failure(sc->typestr, sc->sc_unit, irq, "3/5/6/12");
735 /* LAC-98's system bus width is 8-bit. */
736 sc->proto_dlcr6 = FE_D6_BUFSIZ_32KB | FE_D6_TXBSIZ_2x2KB
737 | FE_D6_BBW_BYTE | FE_D6_SBW_BYTE | FE_D6_SRAM_150ns;
739 /* Setup hooks. We need a special initialization procedure. */
740 sc->init = fe_init_lnx;
747 * Probe for Gateway Communications' old cards.
748 * (both as Generic MB86960 probe routine)
751 fe_probe_gwy(device_t dev)
753 struct fe_softc *sc = device_get_softc(dev);
755 static struct fe_simple_probe_struct probe_table [] = {
756 /* { FE_DLCR2, 0x70, 0x00 }, */
757 { FE_DLCR2, 0x58, 0x00 },
758 { FE_DLCR4, 0x08, 0x00 },
764 * I'm not sure which address is possible, so accepts any.
767 if (fe98_alloc_port(dev, FE_TYPE_GWY))
770 /* Fill the softc struct with default values. */
771 fe_softc_defaults(sc);
773 /* See if the card is on its address. */
774 if (!fe_simple_probe(sc, probe_table))
777 /* Get our station address from EEPROM. */
778 fe_inblk(sc, 0x18, sc->enaddr, ETHER_ADDR_LEN);
779 if (!fe_valid_Ether_p(sc->enaddr, 0x000000))
782 /* Determine the card type. */
783 sc->typestr = "Generic MB86960 Ethernet";
784 if (fe_valid_Ether_p(sc->enaddr, 0x000061))
785 sc->typestr = "Gateway Ethernet (Fujitsu chipset)";
787 /* Gateway's board requires an explicit IRQ to work, since it
788 is not possible to probe the setting of jumpers. */
789 if (bus_get_resource(dev, SYS_RES_IRQ, 0, NULL, NULL) != 0) {
790 fe_irq_failure(sc->typestr, sc->sc_unit, NO_IRQ, NULL);
799 * Probe for Ungermann-Bass Access/PC N98C+(Model 85152).
802 fe_probe_ubn(device_t dev)
804 struct fe_softc *sc = device_get_softc(dev);
807 rman_res_t iobase, irq;
809 static struct fe_simple_probe_struct const probe_table [] = {
810 { FE_DLCR2, 0x58, 0x00 },
811 { FE_DLCR4, 0x08, 0x00 },
815 /* See if the specified I/O address is possible for Access/PC. */
816 /* [01][048C]D0 are allowed. */
817 if (bus_get_resource(dev, SYS_RES_IOPORT, 0, &iobase, NULL) != 0)
819 if ((iobase & ~0x1C00) != 0xD0)
822 if (fe98_alloc_port(dev, FE_TYPE_UBN))
825 /* Fill the softc struct with default values. */
826 fe_softc_defaults(sc);
829 if (!fe_simple_probe(sc, probe_table))
832 /* NOTE: Access/NOTE N98 sometimes freeze when reading station
833 address. In case of using it togather with C-NET(9N)C,
834 this problem usually happens.
835 Writing DLCR7 prevents freezing, but I don't know why. FIXME. */
837 /* Save the current value for the DLCR7 register we are about
839 save7 = fe_inb(sc, FE_DLCR7);
840 fe_outb(sc, FE_DLCR7,
841 sc->proto_dlcr7 | FE_D7_RBS_BMPR | FE_D7_POWER_UP);
843 /* Get our station address form ID ROM and make sure it is UBN's. */
844 fe_inblk(sc, 0x18, sc->enaddr, ETHER_ADDR_LEN);
845 if (!fe_valid_Ether_p(sc->enaddr, 0x00DD01))
848 /* Calculate checksum. */
849 sum = fe_inb(sc, 0x1e);
850 for (i = 0; i < ETHER_ADDR_LEN; i++)
851 sum ^= sc->enaddr[i];
856 /* Setup the board type. */
857 sc->typestr = "Access/PC";
859 /* This looks like an AccessPC/N98C+ board. It requires an
860 explicit IRQ setting in config. Make sure we have one,
861 determining an appropriate value for the IRQ control
864 bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, NULL);
866 case 3: sc->priv_info = 0x01; break;
867 case 5: sc->priv_info = 0x02; break;
868 case 6: sc->priv_info = 0x04; break;
869 case 12: sc->priv_info = 0x08; break;
871 fe_irq_failure(sc->typestr, sc->sc_unit, irq, "3/5/6/12");
875 /* Setup hooks. We need a special initialization procedure. */
876 sc->init = fe_init_ubn;
881 fe_outb(sc, FE_DLCR7, save7);
887 * REX boards(non-JLI type) support routine.
890 #define REX_EEPROM_SIZE 32
894 fe_read_eeprom_rex(struct fe_softc *sc, u_char *data)
900 save16 = fe_inb(sc, 0x10);
902 /* Issue a start condition. */
903 val = fe_inb(sc, 0x10) & 0xf0;
904 fe_outb(sc, 0x10, val);
906 (void) fe_inb(sc, 0x10);
907 (void) fe_inb(sc, 0x10);
908 (void) fe_inb(sc, 0x10);
909 (void) fe_inb(sc, 0x10);
911 /* Read bytes from EEPROM. */
912 for (i = 0; i < REX_EEPROM_SIZE; i++) {
913 /* Read a byte and store it into the buffer. */
915 for (bit = 0x01; bit != 0x00; bit <<= 1)
916 if (fe_inb(sc, 0x10) & REX_DAT)
921 fe_outb(sc, 0x10, save16);
924 /* Report what we got. */
926 data -= REX_EEPROM_SIZE;
927 for (i = 0; i < REX_EEPROM_SIZE; i += 16) {
928 printf("fe%d: EEPROM(REX):%3x: %16D\n",
929 sc->sc_unit, i, data + i, " ");
937 fe_init_rex(struct fe_softc *sc)
939 /* Setup IRQ control register on the ASIC. */
940 fe_outb(sc, 0x10, sc->priv_info);
944 * Probe for RATOC REX-9880/81/82/83 series.
947 fe_probe_rex(device_t dev)
949 struct fe_softc *sc = device_get_softc(dev);
952 rman_res_t iobase, irq;
953 u_char eeprom [REX_EEPROM_SIZE];
955 static struct fe_simple_probe_struct probe_table [] = {
956 { FE_DLCR2, 0x58, 0x00 },
957 { FE_DLCR4, 0x08, 0x00 },
961 /* See if the specified I/O address is possible for REX-9880. */
962 /* 6[46CE]D0 are allowed. */
963 if (bus_get_resource(dev, SYS_RES_IOPORT, 0, &iobase, NULL) != 0)
965 if ((iobase & ~0xA00) != 0x64D0)
968 if (fe98_alloc_port(dev, FE_TYPE_REX))
971 /* Fill the softc struct with default values. */
972 fe_softc_defaults(sc);
974 /* See if the card is on its address. */
975 if (!fe_simple_probe(sc, probe_table))
978 /* We now have to read the config EEPROM. We should be very
979 careful, since doing so destroys a register. (Remember, we
980 are not yet sure we have a REX-9880 board here.) */
981 fe_read_eeprom_rex(sc, eeprom);
982 for (i = 0; i < ETHER_ADDR_LEN; i++)
983 sc->enaddr[i] = eeprom[7 - i];
985 /* Make sure it is RATOC's. */
986 if (!fe_valid_Ether_p(sc->enaddr, 0x00C0D0) &&
987 !fe_valid_Ether_p(sc->enaddr, 0x00803D))
990 /* Setup the board type. */
991 sc->typestr = "REX-9880/9883";
993 /* This looks like a REX-9880 board. It requires an
994 explicit IRQ setting in config. Make sure we have one,
995 determining an appropriate value for the IRQ control
998 bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, NULL);
1000 case 3: sc->priv_info = 0x10; break;
1001 case 5: sc->priv_info = 0x20; break;
1002 case 6: sc->priv_info = 0x40; break;
1003 case 12: sc->priv_info = 0x80; break;
1005 fe_irq_failure(sc->typestr, sc->sc_unit, irq, "3/5/6/12");
1009 /* Setup hooks. We need a special initialization procedure. */
1010 sc->init = fe_init_rex;
1012 /* REX-9880 has 64KB SRAM. */
1013 sc->proto_dlcr6 = FE_D6_BUFSIZ_64KB | FE_D6_TXBSIZ_2x4KB
1014 | FE_D6_BBW_WORD | FE_D6_SBW_WORD | FE_D6_SRAM;
1016 sc->proto_dlcr7 |= FE_D7_EOPPOL; /* XXX */