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
22 * $FreeBSD: src/sys/dev/fe/if_fe_cbus.c,v 1.2.2.5 2002/02/09 03:12:27 nyan Exp $
23 * $DragonFly: src/sys/dev/netif/fe/Attic/if_fe_cbus.c,v 1.2 2003/06/17 04:28:25 dillon Exp $
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/kernel.h>
33 #include <sys/socket.h>
34 #include <sys/module.h>
35 #include <machine/clock.h>
38 #include <machine/bus.h>
40 #include <machine/resource.h>
42 #include <net/ethernet.h>
44 #include <net/if_mib.h>
45 #include <net/if_media.h>
47 #include <netinet/in.h>
48 #include <netinet/if_ether.h>
50 #include <i386/isa/ic/mb86960.h>
51 #include <dev/fe/if_fereg.h>
52 #include <dev/fe/if_fevar.h>
54 #include <isa/isavar.h>
59 static int fe_isa_probe(device_t);
60 static int fe_isa_attach(device_t);
62 static struct isa_pnp_id fe_ids[] = {
63 { 0x101ee0d, NULL }, /* CON0101 - Contec C-NET(98)P2-T */
67 static device_method_t fe_isa_methods[] = {
68 /* Device interface */
69 DEVMETHOD(device_probe, fe_isa_probe),
70 DEVMETHOD(device_attach, fe_isa_attach),
75 static driver_t fe_isa_driver = {
78 sizeof (struct fe_softc)
81 DRIVER_MODULE(fe, isa, fe_isa_driver, fe_devclass, 0, 0);
84 static int fe98_alloc_port(device_t, int);
86 static int fe_probe_re1000(device_t);
87 static int fe_probe_cnet9ne(device_t);
88 static int fe_probe_rex(device_t);
89 static int fe_probe_ssi(device_t);
90 static int fe_probe_jli(device_t);
91 static int fe_probe_lnx(device_t);
92 static int fe_probe_gwy(device_t);
93 static int fe_probe_ubn(device_t);
96 * Determine if the device is present at a specified I/O address. The
97 * main entry to the driver.
100 fe_isa_probe(device_t dev)
105 /* Prepare for the softc struct. */
106 sc = device_get_softc(dev);
107 sc->sc_unit = device_get_unit(dev);
109 /* Check isapnp ids */
110 error = ISA_PNP_PROBE(device_get_parent(dev), dev, fe_ids);
112 /* If the card had a PnP ID that didn't match any we know about */
116 /* If we had some other problem. */
117 if (!(error == 0 || error == ENOENT))
120 /* Probe for supported boards. */
121 if ((error = fe_probe_re1000(dev)) == 0)
123 fe_release_resource(dev);
125 if ((error = fe_probe_cnet9ne(dev)) == 0)
127 fe_release_resource(dev);
129 if ((error = fe_probe_rex(dev)) == 0)
131 fe_release_resource(dev);
133 if ((error = fe_probe_ssi(dev)) == 0)
135 fe_release_resource(dev);
137 if ((error = fe_probe_jli(dev)) == 0)
139 fe_release_resource(dev);
141 if ((error = fe_probe_lnx(dev)) == 0)
143 fe_release_resource(dev);
145 if ((error = fe_probe_ubn(dev)) == 0)
147 fe_release_resource(dev);
149 if ((error = fe_probe_gwy(dev)) == 0)
151 fe_release_resource(dev);
155 error = fe_alloc_irq(dev, 0);
157 fe_release_resource(dev);
162 fe_isa_attach(device_t dev)
164 struct fe_softc *sc = device_get_softc(dev);
167 fe98_alloc_port(dev, sc->type);
168 fe_alloc_irq(dev, 0);
170 return fe_attach(dev);
174 /* Generic I/O address table */
175 static bus_addr_t ioaddr_generic[MAXREGISTERS] = {
176 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007,
177 0x008, 0x009, 0x00a, 0x00b, 0x00c, 0x00d, 0x00e, 0x00f,
178 0x010, 0x011, 0x012, 0x013, 0x014, 0x015, 0x016, 0x017,
179 0x018, 0x019, 0x01a, 0x01b, 0x01c, 0x01d, 0x01e, 0x01f,
182 /* I/O address table for RE1000/1000Plus */
183 static bus_addr_t ioaddr_re1000[MAXREGISTERS] = {
184 0x0000, 0x0001, 0x0200, 0x0201, 0x0400, 0x0401, 0x0600, 0x0601,
185 0x0800, 0x0801, 0x0a00, 0x0a01, 0x0c00, 0x0c01, 0x0e00, 0x0e01,
186 0x1000, 0x1200, 0x1400, 0x1600, 0x1800, 0x1a00, 0x1c00, 0x1e00,
187 0x1001, 0x1201, 0x1401, 0x1601, 0x1801, 0x1a01, 0x1c01, 0x1e01,
190 /* I/O address table for CNET9NE */
191 static bus_addr_t ioaddr_cnet9ne[MAXREGISTERS] = {
192 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007,
193 0x008, 0x009, 0x00a, 0x00b, 0x00c, 0x00d, 0x00e, 0x00f,
194 0x400, 0x402, 0x404, 0x406, 0x408, 0x40a, 0x40c, 0x40e,
195 0x401, 0x403, 0x405, 0x407, 0x409, 0x40b, 0x40d, 0x40f,
198 /* I/O address table for LAC-98 */
199 static bus_addr_t ioaddr_lnx[MAXREGISTERS] = {
200 0x000, 0x002, 0x004, 0x006, 0x008, 0x00a, 0x00c, 0x00e,
201 0x100, 0x102, 0x104, 0x106, 0x108, 0x10a, 0x10c, 0x10e,
202 0x200, 0x202, 0x204, 0x206, 0x208, 0x20a, 0x20c, 0x20e,
203 0x300, 0x302, 0x304, 0x306, 0x308, 0x30a, 0x30c, 0x30e,
206 /* I/O address table for Access/PC N98C+ */
207 static bus_addr_t ioaddr_ubn[MAXREGISTERS] = {
208 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007,
209 0x008, 0x009, 0x00a, 0x00b, 0x00c, 0x00d, 0x00e, 0x00f,
210 0x200, 0x201, 0x202, 0x203, 0x204, 0x205, 0x206, 0x207,
211 0x208, 0x209, 0x20a, 0x20b, 0x20c, 0x20d, 0x20e, 0x20f,
214 /* I/O address table for REX-9880 */
215 static bus_addr_t ioaddr_rex[MAXREGISTERS] = {
216 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007,
217 0x008, 0x009, 0x00a, 0x00b, 0x00c, 0x00d, 0x00e, 0x00f,
218 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107,
219 0x108, 0x109, 0x10a, 0x10b, 0x10c, 0x10d, 0x10e, 0x10f,
223 fe98_alloc_port(device_t dev, int type)
225 struct fe_softc *sc = device_get_softc(dev);
226 struct resource *res;
235 case FE_TYPE_CNET9NE:
236 iat = ioaddr_cnet9ne;
240 iat = ioaddr_generic;
248 iat = ioaddr_generic;
260 iat = ioaddr_generic;
266 res = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid,
267 iat, size, RF_ACTIVE);
271 isa_load_resourcev(res, iat, size);
274 sc->port_used = size;
276 sc->iot = rman_get_bustag(res);
277 sc->ioh = rman_get_bushandle(res);
283 * Probe and initialization for Allied-Telesis RE1000 series.
286 fe_init_re1000(struct fe_softc *sc)
288 /* Setup IRQ control register on the ASIC. */
289 fe_outb(sc, FE_RE1000_IRQCONF, sc->priv_info);
293 fe_probe_re1000(device_t dev)
295 struct fe_softc *sc = device_get_softc(dev);
300 static struct fe_simple_probe_struct probe_table [] = {
301 { FE_DLCR2, 0x58, 0x00 },
302 { FE_DLCR4, 0x08, 0x00 },
306 /* See if the specified I/O address is possible for RE1000. */
307 /* [01]D[02468ACE] are allowed. */
308 if (bus_get_resource(dev, SYS_RES_IOPORT, 0, &iobase, NULL) != 0)
310 if ((iobase & ~0x10E) != 0xD0)
313 if (fe98_alloc_port(dev, FE_TYPE_RE1000))
316 /* Fill the softc struct with default values. */
317 fe_softc_defaults(sc);
319 /* See if the card is on its address. */
320 if (!fe_simple_probe(sc, probe_table))
323 /* Get our station address from EEPROM. */
324 fe_inblk(sc, 0x18, sc->sc_enaddr, ETHER_ADDR_LEN);
326 /* Make sure it is Allied-Telesis's. */
327 if (!valid_Ether_p(sc->sc_enaddr, 0x0000F4))
330 /* Calculate checksum. */
331 sum = fe_inb(sc, 0x1e);
332 for (i = 0; i < ETHER_ADDR_LEN; i++)
333 sum ^= sc->sc_enaddr[i];
337 /* Setup the board type. */
338 sc->typestr = "RE1000";
340 /* This looks like an RE1000 board. It requires an
341 explicit IRQ setting in config. Make sure we have one,
342 determining an appropriate value for the IRQ control
345 bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, NULL);
347 case 3: n = 0x10; break;
348 case 5: n = 0x20; break;
349 case 6: n = 0x40; break;
350 case 12: n = 0x80; break;
352 fe_irq_failure(sc->typestr, sc->sc_unit, irq, "3/5/6/12");
355 sc->priv_info = (fe_inb(sc, FE_RE1000_IRQCONF) & 0x0f) | n;
357 /* Setup hooks. We need a special initialization procedure. */
358 sc->init = fe_init_re1000;
363 /* JLI sub-probe for Allied-Telesis RE1000Plus/ME1500 series. */
364 static u_short const *
365 fe_probe_jli_re1000p(struct fe_softc * sc, u_char const * eeprom)
368 static u_short const irqmaps_re1000p [4] = { 3, 5, 6, 12 };
370 /* Make sure the EEPROM contains Allied-Telesis bit pattern. */
371 if (eeprom[1] != 0xFF) return NULL;
372 for (i = 2; i < 8; i++) if (eeprom[i] != 0xFF) return NULL;
373 for (i = 14; i < 24; i++) if (eeprom[i] != 0xFF) return NULL;
375 /* Get our station address from EEPROM, and make sure the
376 EEPROM contains Allied-Telesis's address. */
377 bcopy(eeprom + 8, sc->sc_enaddr, ETHER_ADDR_LEN);
378 if (!valid_Ether_p(sc->sc_enaddr, 0x0000F4))
381 /* I don't know any sub-model identification. */
382 sc->typestr = "RE1000Plus/ME1500";
384 /* Returns the IRQ table for the RE1000Plus. */
385 return irqmaps_re1000p;
390 * Probe for Allied-Telesis RE1000Plus/ME1500 series.
393 fe_probe_jli(device_t dev)
395 struct fe_softc *sc = device_get_softc(dev);
396 int i, n, xirq, error;
398 u_char eeprom [JLI_EEPROM_SIZE];
399 u_short const * irqmap;
401 static u_short const baseaddr [8] =
402 { 0x1D6, 0x1D8, 0x1DA, 0x1D4, 0x0D4, 0x0D2, 0x0D8, 0x0D0 };
403 static struct fe_simple_probe_struct const probe_table [] = {
404 /* { FE_DLCR1, 0x20, 0x00 }, Doesn't work. */
405 { FE_DLCR2, 0x50, 0x00 },
406 { FE_DLCR4, 0x08, 0x00 },
407 /* { FE_DLCR5, 0x80, 0x00 }, Doesn't work. */
409 { FE_BMPR16, 0x1B, 0x00 },
410 { FE_BMPR17, 0x7F, 0x00 },
416 * See if the specified address is possible for MB86965A JLI mode.
418 if (bus_get_resource(dev, SYS_RES_IOPORT, 0, &iobase, NULL) != 0)
420 for (i = 0; i < 8; i++) {
421 if (baseaddr[i] == iobase)
427 if (fe98_alloc_port(dev, FE_TYPE_RE1000))
430 /* Fill the softc struct with default values. */
431 fe_softc_defaults(sc);
434 * We should test if MB86965A is on the base address now.
435 * Unfortunately, it is very hard to probe it reliably, since
436 * we have no way to reset the chip under software control.
437 * On cold boot, we could check the "signature" bit patterns
438 * described in the Fujitsu document. On warm boot, however,
439 * we can predict almost nothing about register values.
441 if (!fe_simple_probe(sc, probe_table))
444 /* Check if our I/O address matches config info on 86965. */
445 n = (fe_inb(sc, FE_BMPR19) & FE_B19_ADDR) >> FE_B19_ADDR_SHIFT;
446 if (baseaddr[n] != iobase)
450 * We are now almost sure we have an MB86965 at the given
451 * address. So, read EEPROM through it. We have to write
452 * into LSI registers to read from EEPROM. I want to avoid it
453 * at this stage, but I cannot test the presence of the chip
454 * any further without reading EEPROM. FIXME.
456 fe_read_eeprom_jli(sc, eeprom);
458 /* Make sure that config info in EEPROM and 86965 agree. */
459 if (eeprom[FE_EEPROM_CONF] != fe_inb(sc, FE_BMPR19))
462 /* Use 86965 media selection scheme, unless othewise
463 specified. It is "AUTO always" and "select with BMPR13".
464 This behaviour covers most of the 86965 based board (as
465 minimum requirements.) It is backward compatible with
466 previous versions, also. */
468 sc->defmedia = MB_HA;
469 sc->msel = fe_msel_965;
471 /* Perform board-specific probe. */
472 if ((irqmap = fe_probe_jli_re1000p(sc, eeprom)) == NULL)
475 /* Find the IRQ read from EEPROM. */
476 n = (fe_inb(sc, FE_BMPR19) & FE_B19_IRQ) >> FE_B19_IRQ_SHIFT;
479 /* Try to determine IRQ setting. */
480 error = bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, NULL);
481 if (error && xirq == NO_IRQ) {
482 /* The device must be configured with an explicit IRQ. */
483 device_printf(dev, "IRQ auto-detection does not work\n");
485 } else if (error && xirq != NO_IRQ) {
486 /* Just use the probed IRQ value. */
487 bus_set_resource(dev, SYS_RES_IRQ, 0, xirq, 1);
488 } else if (!error && xirq == NO_IRQ) {
489 /* No problem. Go ahead. */
490 } else if (irq == xirq) {
491 /* Good. Go ahead. */
493 /* User must be warned in this case. */
494 sc->stability |= UNSTABLE_IRQ;
497 /* Setup a hook, which resets te 86965 when the driver is being
498 initialized. This may solve a nasty bug. FIXME. */
499 sc->init = fe_init_jli;
506 * Probe and initialization for Contec C-NET(9N)E series.
509 /* TODO: Should be in "if_fereg.h" */
510 #define FE_CNET9NE_INTR 0x10 /* Interrupt Mask? */
513 fe_init_cnet9ne(struct fe_softc *sc)
515 /* Enable interrupt? FIXME. */
516 fe_outb(sc, FE_CNET9NE_INTR, 0x10);
520 fe_probe_cnet9ne (device_t dev)
522 struct fe_softc *sc = device_get_softc(dev);
525 static struct fe_simple_probe_struct probe_table [] = {
526 { FE_DLCR2, 0x58, 0x00 },
527 { FE_DLCR4, 0x08, 0x00 },
531 /* See if the specified I/O address is possible for C-NET(9N)E. */
532 if (bus_get_resource(dev, SYS_RES_IOPORT, 0, &iobase, NULL) != 0)
534 if (iobase != 0x73D0)
537 if (fe98_alloc_port(dev, FE_TYPE_CNET9NE))
540 /* Fill the softc struct with default values. */
541 fe_softc_defaults(sc);
543 /* See if the card is on its address. */
544 if (!fe_simple_probe(sc, probe_table))
547 /* Get our station address from EEPROM. */
548 fe_inblk(sc, 0x18, sc->sc_enaddr, ETHER_ADDR_LEN);
550 /* Make sure it is Contec's. */
551 if (!valid_Ether_p(sc->sc_enaddr, 0x00804C))
554 /* Determine the card type. */
555 if (sc->sc_enaddr[3] == 0x06) {
556 sc->typestr = "C-NET(9N)C";
558 /* We seems to need our own IDENT bits... FIXME. */
559 sc->proto_dlcr7 = FE_D7_BYTSWP_LH | FE_D7_IDENT_NICE;
561 /* C-NET(9N)C requires an explicit IRQ to work. */
562 if (bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, NULL) != 0) {
563 fe_irq_failure(sc->typestr, sc->sc_unit, NO_IRQ, NULL);
567 sc->typestr = "C-NET(9N)E";
569 /* C-NET(9N)E works only IRQ5. */
570 if (bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, NULL) != 0)
573 fe_irq_failure(sc->typestr, sc->sc_unit, irq, "5");
577 /* We need an init hook to initialize ASIC before we start. */
578 sc->init = fe_init_cnet9ne;
581 /* C-NET(9N)E has 64KB SRAM. */
582 sc->proto_dlcr6 = FE_D6_BUFSIZ_64KB | FE_D6_TXBSIZ_2x4KB
583 | FE_D6_BBW_WORD | FE_D6_SBW_WORD | FE_D6_SRAM;
590 * Probe for Contec C-NET(98)P2 series.
591 * (Logitec LAN-98TP/LAN-98T25P - parhaps)
594 fe_probe_ssi(device_t dev)
596 struct fe_softc *sc = device_get_softc(dev);
599 u_char eeprom [SSI_EEPROM_SIZE];
600 static struct fe_simple_probe_struct probe_table [] = {
601 { FE_DLCR2, 0x08, 0x00 },
602 { FE_DLCR4, 0x08, 0x00 },
605 static u_short const irqmap[] = {
607 NO_IRQ, NO_IRQ, NO_IRQ, 3, NO_IRQ, 5, 6, NO_IRQ,
608 NO_IRQ, 9, 10, NO_IRQ, 12, 13, NO_IRQ, NO_IRQ,
609 /* INT3 INT41 INT5 INT6 */
612 /* See if the specified I/O address is possible for 78Q8377A. */
613 /* [0-D]3D0 are allowed. */
614 if (bus_get_resource(dev, SYS_RES_IOPORT, 0, &iobase, NULL) != 0)
616 if ((iobase & 0xFFF) != 0x3D0)
619 if (fe98_alloc_port(dev, FE_TYPE_SSI))
622 /* Fill the softc struct with default values. */
623 fe_softc_defaults(sc);
625 /* See if the card is on its address. */
626 if (!fe_simple_probe(sc, probe_table))
629 /* We now have to read the config EEPROM. We should be very
630 careful, since doing so destroys a register. (Remember, we
631 are not yet sure we have a C-NET(98)P2 board here.) Don't
632 remember to select BMPRs bofore reading EEPROM, since other
633 register bank may be selected before the probe() is called. */
634 fe_read_eeprom_ssi(sc, eeprom);
636 /* Make sure the Ethernet (MAC) station address is of Contec's. */
637 if (!valid_Ether_p(eeprom + FE_SSI_EEP_ADDR, 0x00804C))
639 bcopy(eeprom + FE_SSI_EEP_ADDR, sc->sc_enaddr, ETHER_ADDR_LEN);
641 /* Setup the board type. */
642 sc->typestr = "C-NET(98)P2";
644 /* Non-PnP mode, set static resource from eeprom. */
645 if (!isa_get_vendorid(dev)) {
646 /* Get IRQ configuration from EEPROM. */
647 irq = irqmap[eeprom[FE_SSI_EEP_IRQ]];
649 fe_irq_failure(sc->typestr, sc->sc_unit, irq,
653 bus_set_resource(dev, SYS_RES_IRQ, 0, irq, 1);
656 /* Get Duplex-mode configuration from EEPROM. */
657 sc->proto_dlcr4 |= (eeprom[FE_SSI_EEP_DUPLEX] & FE_D4_DSC);
659 /* Fill softc struct accordingly. */
661 sc->defmedia = MB_HT;
668 * Probe for TDK LAC-98012/013/025/9N011 - parhaps.
671 fe_probe_lnx(device_t dev)
673 #ifndef FE_8BIT_SUPPORT
675 "skip LAC-98012/013(only 16-bit cards are supported)\n");
678 struct fe_softc *sc = device_get_softc(dev);
681 u_char eeprom [LNX_EEPROM_SIZE];
683 static struct fe_simple_probe_struct probe_table [] = {
684 { FE_DLCR2, 0x58, 0x00 },
685 { FE_DLCR4, 0x08, 0x00 },
689 /* See if the specified I/O address is possible for TDK/LANX boards. */
690 /* 0D0, 4D0, 8D0, and CD0 are allowed. */
691 if (bus_get_resource(dev, SYS_RES_IOPORT, 0, &iobase, NULL) != 0)
693 if ((iobase & ~0xC00) != 0xD0)
696 if (fe98_alloc_port(dev, FE_TYPE_LNX))
699 /* Fill the softc struct with default values. */
700 fe_softc_defaults(sc);
702 /* See if the card is on its address. */
703 if (!fe_simple_probe(sc, probe_table))
706 /* We now have to read the config EEPROM. We should be very
707 careful, since doing so destroys a register. (Remember, we
708 are not yet sure we have a LAC-98012/98013 board here.) */
709 fe_read_eeprom_lnx(sc, eeprom);
711 /* Make sure the Ethernet (MAC) station address is of TDK/LANX's. */
712 if (!valid_Ether_p(eeprom, 0x008098))
714 bcopy(eeprom, sc->sc_enaddr, ETHER_ADDR_LEN);
716 /* Setup the board type. */
717 sc->typestr = "LAC-98012/98013";
719 /* This looks like a TDK/LANX board. It requires an
720 explicit IRQ setting in config. Make sure we have one,
721 determining an appropriate value for the IRQ control
724 if (bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, NULL) != 0)
727 case 3 : sc->priv_info = 0x10 | LNX_CLK_LO | LNX_SDA_HI; break;
728 case 5 : sc->priv_info = 0x20 | LNX_CLK_LO | LNX_SDA_HI; break;
729 case 6 : sc->priv_info = 0x40 | LNX_CLK_LO | LNX_SDA_HI; break;
730 case 12: sc->priv_info = 0x80 | LNX_CLK_LO | LNX_SDA_HI; break;
732 fe_irq_failure(sc->typestr, sc->sc_unit, irq, "3/5/6/12");
736 /* LAC-98's system bus width is 8-bit. */
737 sc->proto_dlcr6 = FE_D6_BUFSIZ_32KB | FE_D6_TXBSIZ_2x2KB
738 | FE_D6_BBW_BYTE | FE_D6_SBW_BYTE | FE_D6_SRAM_150ns;
740 /* Setup hooks. We need a special initialization procedure. */
741 sc->init = fe_init_lnx;
744 #endif /* FE_8BIT_SUPPORT */
749 * Probe for Gateway Communications' old cards.
750 * (both as Generic MB86960 probe routine)
753 fe_probe_gwy(device_t dev)
755 struct fe_softc *sc = device_get_softc(dev);
757 static struct fe_simple_probe_struct probe_table [] = {
758 /* { FE_DLCR2, 0x70, 0x00 }, */
759 { FE_DLCR2, 0x58, 0x00 },
760 { FE_DLCR4, 0x08, 0x00 },
766 * I'm not sure which address is possible, so accepts any.
769 if (fe98_alloc_port(dev, FE_TYPE_GWY))
772 /* Fill the softc struct with default values. */
773 fe_softc_defaults(sc);
775 /* See if the card is on its address. */
776 if (!fe_simple_probe(sc, probe_table))
779 /* Get our station address from EEPROM. */
780 fe_inblk(sc, 0x18, sc->sc_enaddr, ETHER_ADDR_LEN);
781 if (!valid_Ether_p(sc->sc_enaddr, 0x000000))
784 /* Determine the card type. */
785 sc->typestr = "Generic MB86960 Ethernet";
786 if (valid_Ether_p(sc->sc_enaddr, 0x000061))
787 sc->typestr = "Gateway Ethernet (Fujitsu chipset)";
789 /* Gateway's board requires an explicit IRQ to work, since it
790 is not possible to probe the setting of jumpers. */
791 if (bus_get_resource(dev, SYS_RES_IRQ, 0, NULL, NULL) != 0) {
792 fe_irq_failure(sc->typestr, sc->sc_unit, NO_IRQ, NULL);
801 * Probe for Ungermann-Bass Access/PC N98C+(Model 85152).
804 fe_probe_ubn(device_t dev)
806 struct fe_softc *sc = device_get_softc(dev);
811 static struct fe_simple_probe_struct const probe_table [] = {
812 { FE_DLCR2, 0x58, 0x00 },
813 { FE_DLCR4, 0x08, 0x00 },
817 /* See if the specified I/O address is possible for Access/PC. */
818 /* [01][048C]D0 are allowed. */
819 if (bus_get_resource(dev, SYS_RES_IOPORT, 0, &iobase, NULL) != 0)
821 if ((iobase & ~0x1C00) != 0xD0)
824 if (fe98_alloc_port(dev, FE_TYPE_UBN))
827 /* Fill the softc struct with default values. */
828 fe_softc_defaults(sc);
831 if (!fe_simple_probe(sc, probe_table))
834 /* NOTE: Access/NOTE N98 sometimes freeze when reading station
835 address. In case of using it togather with C-NET(9N)C,
836 this problem usually happens.
837 Writing DLCR7 prevents freezing, but I don't know why. FIXME. */
839 /* Save the current value for the DLCR7 register we are about
841 save7 = fe_inb(sc, FE_DLCR7);
842 fe_outb(sc, FE_DLCR7,
843 sc->proto_dlcr7 | FE_D7_RBS_BMPR | FE_D7_POWER_UP);
845 /* Get our station address form ID ROM and make sure it is UBN's. */
846 fe_inblk(sc, 0x18, sc->sc_enaddr, ETHER_ADDR_LEN);
847 if (!valid_Ether_p(sc->sc_enaddr, 0x00DD01))
850 /* Calculate checksum. */
851 sum = fe_inb(sc, 0x1e);
852 for (i = 0; i < ETHER_ADDR_LEN; i++)
853 sum ^= sc->sc_enaddr[i];
858 /* Setup the board type. */
859 sc->typestr = "Access/PC";
861 /* This looks like an AccessPC/N98C+ board. It requires an
862 explicit IRQ setting in config. Make sure we have one,
863 determining an appropriate value for the IRQ control
866 bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, NULL);
868 case 3: sc->priv_info = 0x01; break;
869 case 5: sc->priv_info = 0x02; break;
870 case 6: sc->priv_info = 0x04; break;
871 case 12: sc->priv_info = 0x08; break;
873 fe_irq_failure(sc->typestr, sc->sc_unit, irq, "3/5/6/12");
877 /* Setup hooks. We need a special initialization procedure. */
878 sc->init = fe_init_ubn;
883 fe_outb(sc, FE_DLCR7, save7);
889 * REX boards(non-JLI type) support routine.
892 #define REX_EEPROM_SIZE 32
896 fe_read_eeprom_rex(struct fe_softc *sc, u_char *data)
902 save16 = fe_inb(sc, 0x10);
904 /* Issue a start condition. */
905 val = fe_inb(sc, 0x10) & 0xf0;
906 fe_outb(sc, 0x10, val);
908 (void) fe_inb(sc, 0x10);
909 (void) fe_inb(sc, 0x10);
910 (void) fe_inb(sc, 0x10);
911 (void) fe_inb(sc, 0x10);
913 /* Read bytes from EEPROM. */
914 for (i = 0; i < REX_EEPROM_SIZE; i++) {
915 /* Read a byte and store it into the buffer. */
917 for (bit = 0x01; bit != 0x00; bit <<= 1)
918 if (fe_inb(sc, 0x10) & REX_DAT)
923 fe_outb(sc, 0x10, save16);
926 /* Report what we got. */
928 data -= REX_EEPROM_SIZE;
929 for (i = 0; i < REX_EEPROM_SIZE; i += 16) {
930 printf("fe%d: EEPROM(REX):%3x: %16D\n",
931 sc->sc_unit, i, data + i, " ");
939 fe_init_rex(struct fe_softc *sc)
941 /* Setup IRQ control register on the ASIC. */
942 fe_outb(sc, 0x10, sc->priv_info);
946 * Probe for RATOC REX-9880/81/82/83 series.
949 fe_probe_rex(device_t dev)
951 struct fe_softc *sc = device_get_softc(dev);
955 u_char eeprom [REX_EEPROM_SIZE];
957 static struct fe_simple_probe_struct probe_table [] = {
958 { FE_DLCR2, 0x58, 0x00 },
959 { FE_DLCR4, 0x08, 0x00 },
963 /* See if the specified I/O address is possible for REX-9880. */
964 /* 6[46CE]D0 are allowed. */
965 if (bus_get_resource(dev, SYS_RES_IOPORT, 0, &iobase, NULL) != 0)
967 if ((iobase & ~0xA00) != 0x64D0)
970 if (fe98_alloc_port(dev, FE_TYPE_REX))
973 /* Fill the softc struct with default values. */
974 fe_softc_defaults(sc);
976 /* See if the card is on its address. */
977 if (!fe_simple_probe(sc, probe_table))
980 /* We now have to read the config EEPROM. We should be very
981 careful, since doing so destroys a register. (Remember, we
982 are not yet sure we have a REX-9880 board here.) */
983 fe_read_eeprom_rex(sc, eeprom);
984 for (i = 0; i < ETHER_ADDR_LEN; i++)
985 sc->sc_enaddr[i] = eeprom[7 - i];
987 /* Make sure it is RATOC's. */
988 if (!valid_Ether_p(sc->sc_enaddr, 0x00C0D0) &&
989 !valid_Ether_p(sc->sc_enaddr, 0x00803D))
992 /* Setup the board type. */
993 sc->typestr = "REX-9880/9883";
995 /* This looks like a REX-9880 board. It requires an
996 explicit IRQ setting in config. Make sure we have one,
997 determining an appropriate value for the IRQ control
1000 bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, NULL);
1002 case 3: sc->priv_info = 0x10; break;
1003 case 5: sc->priv_info = 0x20; break;
1004 case 6: sc->priv_info = 0x40; break;
1005 case 12: sc->priv_info = 0x80; break;
1007 fe_irq_failure(sc->typestr, sc->sc_unit, irq, "3/5/6/12");
1011 /* Setup hooks. We need a special initialization procedure. */
1012 sc->init = fe_init_rex;
1014 /* REX-9880 has 64KB SRAM. */
1015 sc->proto_dlcr6 = FE_D6_BUFSIZ_64KB | FE_D6_TXBSIZ_2x4KB
1016 | FE_D6_BBW_WORD | FE_D6_SBW_WORD | FE_D6_SRAM;
1018 sc->proto_dlcr7 |= FE_D7_EOPPOL; /* XXX */