2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2000 Matthew N. Dodd
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/kernel.h>
36 #include <sys/socket.h>
38 #include <sys/module.h>
41 #include <machine/bus.h>
42 #include <machine/resource.h>
46 #include <net/if_arp.h>
47 #include <net/if_media.h>
50 #include <isa/isavar.h>
51 #include <isa/pnpvar.h>
53 #include <dev/ex/if_exreg.h>
54 #include <dev/ex/if_exvar.h>
56 /* Bus Front End Functions */
57 static void ex_isa_identify(driver_t *, device_t);
58 static int ex_isa_probe(device_t);
59 static int ex_isa_attach(device_t);
61 static int ex_look_for_card(struct ex_softc *);
64 static void ex_pnp_wakeup(void *);
66 SYSINIT(ex_pnpwakeup, SI_SUB_CPU, SI_ORDER_ANY, ex_pnp_wakeup, NULL);
69 static device_method_t ex_isa_methods[] = {
70 /* Device interface */
71 DEVMETHOD(device_identify, ex_isa_identify),
72 DEVMETHOD(device_probe, ex_isa_probe),
73 DEVMETHOD(device_attach, ex_isa_attach),
74 DEVMETHOD(device_detach, ex_detach),
79 static driver_t ex_isa_driver = {
82 sizeof(struct ex_softc),
85 DRIVER_MODULE(ex, isa, ex_isa_driver, ex_devclass, 0, 0);
87 static struct isa_pnp_id ex_ids[] = {
88 { 0x3110d425, NULL }, /* INT1031 */
89 { 0x3010d425, NULL }, /* INT1030 */
94 #define EX_PNP_WAKE 0x279
96 static uint8_t ex_pnp_wake_seq[] =
97 { 0x6A, 0xB5, 0xDA, 0xED, 0xF6, 0xFB, 0x7D, 0xBE,
98 0xDF, 0x6F, 0x37, 0x1B, 0x0D, 0x86, 0xC3, 0x61,
99 0xB0, 0x58, 0x2C, 0x16, 0x8B, 0x45, 0xA2, 0xD1,
100 0xE8, 0x74, 0x3A, 0x9D, 0xCE, 0xE7, 0x73, 0x43 };
103 ex_pnp_wakeup (void * dummy)
108 printf("ex_pnp_wakeup()\n");
110 outb(EX_PNP_WAKE, 0);
111 outb(EX_PNP_WAKE, 0);
112 for (tmp = 0; tmp < 32; tmp++) {
113 outb(EX_PNP_WAKE, ex_pnp_wake_seq[tmp]);
119 * Non-destructive identify.
122 ex_isa_identify(driver_t *driver, device_t parent)
134 printf("ex_isa_identify()\n");
136 for (ioport = 0x200; ioport < 0x3a0; ioport += 0x10) {
138 sc.ioport = bus_alloc_resource(parent, SYS_RES_IOPORT, &rid,
139 ioport, ioport, 0x10, RF_ACTIVE);
140 if (sc.ioport == NULL)
143 /* No board found at address */
144 if (!ex_look_for_card(&sc)) {
145 bus_release_resource(parent, SYS_RES_IOPORT, rid,
151 printf("ex: Found card at 0x%03lx!\n", (unsigned long)ioport);
153 /* Board in PnP mode */
154 if (ex_eeprom_read(&sc, EE_W0) & EE_W0_PNP) {
155 /* Reset the card. */
156 CSR_WRITE_1(&sc, CMD_REG, Reset_CMD);
159 printf("ex: card at 0x%03lx in PnP mode!\n", (unsigned long)ioport);
160 bus_release_resource(parent, SYS_RES_IOPORT, rid,
165 bzero(enaddr, sizeof(enaddr));
167 /* Reset the card. */
168 CSR_WRITE_1(&sc, CMD_REG, Reset_CMD);
171 ex_get_address(&sc, enaddr);
172 tmp = ex_eeprom_read(&sc, EE_W1) & EE_W1_INT_SEL;
174 /* work out which set of irq <-> internal tables to use */
175 if (ex_card_type(enaddr) == CARD_TYPE_EX_10_PLUS) {
176 irq = plus_ee2irqmap[tmp];
177 desc = "Intel Pro/10+";
179 irq = ee2irqmap[tmp];
180 desc = "Intel Pro/10";
183 bus_release_resource(parent, SYS_RES_IOPORT, rid, sc.ioport);
184 child = BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "ex", -1);
185 device_set_desc_copy(child, desc);
186 device_set_driver(child, driver);
187 bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1);
188 bus_set_resource(child, SYS_RES_IOPORT, 0, ioport, EX_IOSIZE);
190 printf("ex: Adding board at 0x%03lx, irq %d\n",
191 (unsigned long)ioport, irq);
198 ex_isa_probe(device_t dev)
207 struct ex_softc *sc = device_get_softc(dev);
209 /* Check isapnp ids */
210 error = ISA_PNP_PROBE(device_get_parent(dev), dev, ex_ids);
212 /* If the card had a PnP ID that didn't match any we know about */
216 /* If we had some other problem. */
217 if (!(error == 0 || error == ENOENT))
220 error = ex_alloc_resources(dev);
223 iobase = bus_get_resource_start(dev, SYS_RES_IOPORT, 0);
224 if (!ex_look_for_card(sc)) {
226 printf("ex: no card found at 0x%03lx.\n", (unsigned long)iobase);
231 printf("ex: ex_isa_probe() found card at 0x%03lx\n", (unsigned long)iobase);
236 CSR_WRITE_1(sc, CMD_REG, Reset_CMD);
239 ex_get_address(sc, enaddr);
241 /* work out which set of irq <-> internal tables to use */
242 if (ex_card_type(enaddr) == CARD_TYPE_EX_10_PLUS) {
243 irq2ee = plus_irq2eemap;
244 ee2irq = plus_ee2irqmap;
250 tmp = ex_eeprom_read(sc, EE_W1) & EE_W1_INT_SEL;
251 irq = bus_get_resource_start(dev, SYS_RES_IRQ, 0);
253 /* This will happen if board is in PnP mode. */
254 if (ee2irq[tmp] != irq) {
256 "WARNING: IRQ mismatch: EEPROM %d, using %d\n",
261 bus_set_resource(dev, SYS_RES_IRQ, 0, irq, 1);
265 printf("ex: invalid IRQ.\n");
270 ex_release_resources(dev);
275 ex_isa_attach(device_t dev)
277 struct ex_softc * sc = device_get_softc(dev);
284 sc->flags |= HAS_INT_NO_REG;
286 if ((error = ex_alloc_resources(dev)) != 0) {
287 device_printf(dev, "ex_alloc_resources() failed!\n");
292 * Fill in several fields of the softc structure:
293 * - I/O base address.
294 * - Hardware Ethernet address.
295 * - IRQ number (if not supplied in config file, read it from EEPROM).
298 sc->irq_no = rman_get_start(sc->irq);
300 ex_get_address(sc, sc->enaddr);
302 temp = ex_eeprom_read(sc, EE_W0);
303 device_printf(sc->dev, "%s config, %s bus, ",
304 (temp & EE_W0_PNP) ? "PnP" : "Manual",
305 (temp & EE_W0_BUS16) ? "16-bit" : "8-bit");
307 temp = ex_eeprom_read(sc, EE_W6);
308 printf("board id 0x%03x, stepping 0x%01x\n",
309 (temp & EE_W6_BOARD_MASK) >> EE_W6_BOARD_SHIFT,
310 temp & EE_W6_STEP_MASK);
312 if ((error = ex_attach(dev)) != 0) {
313 device_printf(dev, "ex_attach() failed!\n");
319 ex_release_resources(dev);
324 ex_look_for_card(struct ex_softc *sc)
329 * Check for the i82595 signature, and check that the round robin
330 * counter actually advances.
332 if (((count1 = CSR_READ_1(sc, ID_REG)) & Id_Mask) != Id_Sig)
334 count2 = CSR_READ_1(sc, ID_REG);
335 count2 = CSR_READ_1(sc, ID_REG);
336 count2 = CSR_READ_1(sc, ID_REG);
338 return((count2 & Counter_bits) == ((count1 + 0xc0) & Counter_bits));