]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/ex/if_ex_isa.c
sys/dev: further adoption of SPDX licensing ID tags.
[FreeBSD/FreeBSD.git] / sys / dev / ex / if_ex_isa.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2000 Matthew N. Dodd
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
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.
15  *
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
26  * SUCH DAMAGE.
27  *
28  */
29
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/kernel.h>
36 #include <sys/socket.h>
37
38 #include <sys/module.h>
39 #include <sys/bus.h>
40
41 #include <machine/bus.h>
42 #include <machine/resource.h>
43 #include <sys/rman.h>
44
45 #include <net/if.h>
46 #include <net/if_arp.h>
47 #include <net/if_media.h> 
48
49
50 #include <isa/isavar.h>
51 #include <isa/pnpvar.h>
52
53 #include <dev/ex/if_exreg.h>
54 #include <dev/ex/if_exvar.h>
55
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);
60
61 static int      ex_look_for_card(struct ex_softc *);
62
63 #if 0
64 static  void    ex_pnp_wakeup(void *);
65
66 SYSINIT(ex_pnpwakeup, SI_SUB_CPU, SI_ORDER_ANY, ex_pnp_wakeup, NULL);
67 #endif
68
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),
75
76         { 0, 0 }
77 };
78
79 static driver_t ex_isa_driver = {
80         "ex",
81         ex_isa_methods,
82         sizeof(struct ex_softc),
83 };
84
85 DRIVER_MODULE(ex, isa, ex_isa_driver, ex_devclass, 0, 0);
86
87 static struct isa_pnp_id ex_ids[] = {
88         { 0x3110d425,   NULL }, /* INT1031 */
89         { 0x3010d425,   NULL }, /* INT1030 */
90         { 0,            NULL },
91 };
92
93 #if 0
94 #define EX_PNP_WAKE             0x279
95
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 };
101
102 static void
103 ex_pnp_wakeup (void * dummy)
104 {
105         int     tmp;
106
107         if (bootverbose)
108                 printf("ex_pnp_wakeup()\n");
109
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]);
114         }
115 }
116 #endif
117
118 /*
119  * Non-destructive identify.
120  */
121 static void
122 ex_isa_identify(driver_t *driver, device_t parent)
123 {
124         device_t        child;
125         bus_addr_t      ioport;
126         u_char          enaddr[6];
127         u_int           irq;
128         int             tmp;
129         const char *    desc;
130         struct ex_softc sc;
131         int             rid;
132
133         if (bootverbose)
134                 printf("ex_isa_identify()\n");
135
136         for (ioport = 0x200; ioport < 0x3a0; ioport += 0x10) {
137                 rid = 0;
138                 sc.ioport = bus_alloc_resource(parent, SYS_RES_IOPORT, &rid,
139                     ioport, ioport, 0x10, RF_ACTIVE);
140                 if (sc.ioport == NULL)
141                         continue;
142
143                 /* No board found at address */
144                 if (!ex_look_for_card(&sc)) {
145                         bus_release_resource(parent, SYS_RES_IOPORT, rid,
146                             sc.ioport);
147                         continue;
148                 }
149
150                 if (bootverbose)
151                         printf("ex: Found card at 0x%03lx!\n", (unsigned long)ioport);
152
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);
157                         DELAY(500);
158                         if (bootverbose)
159                                 printf("ex: card at 0x%03lx in PnP mode!\n", (unsigned long)ioport);
160                         bus_release_resource(parent, SYS_RES_IOPORT, rid,
161                             sc.ioport);
162                         continue;
163                 }
164
165                 bzero(enaddr, sizeof(enaddr));
166
167                 /* Reset the card. */
168                 CSR_WRITE_1(&sc, CMD_REG, Reset_CMD);
169                 DELAY(400);
170
171                 ex_get_address(&sc, enaddr);
172                 tmp = ex_eeprom_read(&sc, EE_W1) & EE_W1_INT_SEL;
173
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+";
178                 } else {
179                         irq = ee2irqmap[tmp];
180                         desc = "Intel Pro/10";
181                 }
182
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);
189                 if (bootverbose)
190                         printf("ex: Adding board at 0x%03lx, irq %d\n",
191                            (unsigned long)ioport, irq);
192         }
193
194         return;
195 }
196
197 static int
198 ex_isa_probe(device_t dev)
199 {
200         bus_addr_t      iobase;
201         u_int           irq;
202         char *          irq2ee;
203         u_char *        ee2irq;
204         u_char          enaddr[6];
205         int             tmp;
206         int             error;
207         struct ex_softc *sc = device_get_softc(dev);
208
209         /* Check isapnp ids */
210         error = ISA_PNP_PROBE(device_get_parent(dev), dev, ex_ids);
211
212         /* If the card had a PnP ID that didn't match any we know about */
213         if (error == ENXIO)
214                 return(error);
215
216         /* If we had some other problem. */
217         if (!(error == 0 || error == ENOENT))
218                 return(error);
219
220         error = ex_alloc_resources(dev);
221         if (error != 0)
222                 goto bad;
223         iobase = bus_get_resource_start(dev, SYS_RES_IOPORT, 0);
224         if (!ex_look_for_card(sc)) {
225                 if (bootverbose)
226                         printf("ex: no card found at 0x%03lx.\n", (unsigned long)iobase);
227                 error = ENXIO;
228                 goto bad;
229         }
230         if (bootverbose)
231                 printf("ex: ex_isa_probe() found card at 0x%03lx\n", (unsigned long)iobase);
232
233         /*
234          * Reset the card.
235          */
236         CSR_WRITE_1(sc, CMD_REG, Reset_CMD);
237         DELAY(800);
238
239         ex_get_address(sc, enaddr);
240
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;
245         } else {
246                 irq2ee = irq2eemap;
247                 ee2irq = ee2irqmap;
248         }
249
250         tmp = ex_eeprom_read(sc, EE_W1) & EE_W1_INT_SEL;
251         irq = bus_get_resource_start(dev, SYS_RES_IRQ, 0);
252         if (irq > 0) {
253                 /* This will happen if board is in PnP mode. */
254                 if (ee2irq[tmp] != irq) {
255                         device_printf(dev,
256                             "WARNING: IRQ mismatch: EEPROM %d, using %d\n",
257                                 ee2irq[tmp], irq);
258                 }
259         } else {
260                 irq = ee2irq[tmp];
261                 bus_set_resource(dev, SYS_RES_IRQ, 0, irq, 1);
262         }
263
264         if (irq == 0) {
265                 printf("ex: invalid IRQ.\n");
266                 error = ENXIO;
267         }
268
269 bad:;
270         ex_release_resources(dev);
271         return (error);
272 }
273
274 static int
275 ex_isa_attach(device_t dev)
276 {
277         struct ex_softc *       sc = device_get_softc(dev);
278         int                     error = 0;
279         uint16_t                temp;
280
281         sc->dev = dev;
282         sc->ioport_rid = 0;
283         sc->irq_rid = 0;
284         sc->flags |= HAS_INT_NO_REG;
285
286         if ((error = ex_alloc_resources(dev)) != 0) {
287                 device_printf(dev, "ex_alloc_resources() failed!\n");
288                 goto bad;
289         }
290
291         /*
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).
296          *      - Connector type.
297          */
298         sc->irq_no = rman_get_start(sc->irq);
299
300         ex_get_address(sc, sc->enaddr);
301
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");
306
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);
311
312         if ((error = ex_attach(dev)) != 0) {
313                 device_printf(dev, "ex_attach() failed!\n");
314                 goto bad;
315         }
316
317         return(0);
318 bad:
319         ex_release_resources(dev);
320         return (error);
321 }
322
323 static int
324 ex_look_for_card(struct ex_softc *sc)
325 {
326         int count1, count2;
327
328         /*
329          * Check for the i82595 signature, and check that the round robin
330          * counter actually advances.
331          */
332         if (((count1 = CSR_READ_1(sc, ID_REG)) & Id_Mask) != Id_Sig)
333                 return(0);
334         count2 = CSR_READ_1(sc, ID_REG);
335         count2 = CSR_READ_1(sc, ID_REG);
336         count2 = CSR_READ_1(sc, ID_REG);
337
338         return((count2 & Counter_bits) == ((count1 + 0xc0) & Counter_bits));
339 }