Merge from vendor branch GCC:
[dragonfly.git] / sys / dev / netif / ex / if_ex_isa.c
1 /*-
2  * Copyright (c) 2000 Matthew N. Dodd
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  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  *      $FreeBSD: src/sys/dev/ex/if_ex_isa.c,v 1.3.2.1 2001/03/05 05:33:20 imp Exp $
27  *      $DragonFly: src/sys/dev/netif/ex/if_ex_isa.c,v 1.7 2005/05/24 20:59:01 dillon Exp $
28  */
29
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/kernel.h>
33 #include <sys/socket.h>
34
35 #include <sys/module.h>
36 #include <sys/bus.h>
37
38 #include <machine/bus.h>
39 #include <machine/resource.h>
40 #include <machine/clock.h>
41 #include <sys/rman.h>
42
43 #include <net/if.h>
44 #include <net/if_arp.h>
45 #include <net/if_media.h> 
46
47
48 #include <bus/isa/isavar.h>
49 #include <bus/isa/pnpvar.h>
50
51 #include "if_exreg.h"
52 #include "if_exvar.h"
53
54 /* Bus Front End Functions */
55 static void     ex_isa_identify (driver_t *, device_t);
56 static int      ex_isa_probe    (device_t);
57 static int      ex_isa_attach   (device_t);
58
59 #if 0
60 static  void    ex_pnp_wakeup   (void *);
61
62 SYSINIT(ex_pnpwakeup, SI_SUB_CPU, SI_ORDER_ANY, ex_pnp_wakeup, NULL);
63 #endif
64
65 static device_method_t ex_methods[] = {
66         /* Device interface */
67         DEVMETHOD(device_identify,      ex_isa_identify),
68         DEVMETHOD(device_probe,         ex_isa_probe),
69         DEVMETHOD(device_attach,        ex_isa_attach),
70
71         { 0, 0 }
72 };
73
74 static driver_t ex_driver = {
75         "ex",
76         ex_methods,
77         sizeof(struct ex_softc),
78 };
79
80 devclass_t ex_devclass;
81
82 DRIVER_MODULE(if_ex, isa, ex_driver, ex_devclass, 0, 0);
83
84 static struct isa_pnp_id ex_ids[] = {
85         { 0x3110d425,   NULL }, /* INT1031 */
86         { 0x3010d425,   NULL }, /* INT1030 */
87         { 0,            NULL },
88 };
89
90 #if 0
91 #define EX_PNP_WAKE             0x279
92
93 static u_int8_t ex_pnp_wake_seq[] =
94                         { 0x6A, 0xB5, 0xDA, 0xED, 0xF6, 0xFB, 0x7D, 0xBE,
95                           0xDF, 0x6F, 0x37, 0x1B, 0x0D, 0x86, 0xC3, 0x61,
96                           0xB0, 0x58, 0x2C, 0x16, 0x8B, 0x45, 0xA2, 0xD1,
97                           0xE8, 0x74, 0x3A, 0x9D, 0xCE, 0xE7, 0x73, 0x43 };
98
99 static void
100 ex_pnp_wakeup (void * dummy)
101 {
102         int     tmp;
103
104         if (bootverbose)
105                 printf("ex_pnp_wakeup()\n");
106
107         outb(EX_PNP_WAKE, 0);
108         outb(EX_PNP_WAKE, 0);
109         for (tmp = 0; tmp < 32; tmp++) {
110                 outb(EX_PNP_WAKE, ex_pnp_wake_seq[tmp]);
111         }
112 }
113 #endif
114
115 /*
116  * Non-destructive identify.
117  */
118 static void
119 ex_isa_identify (driver_t *driver, device_t parent)
120 {
121         device_t        child;
122         u_int32_t       ioport;
123         u_char          enaddr[6];
124         u_int           irq;
125         int             tmp;
126         const char *    desc;
127
128         if (bootverbose)
129                 printf("ex_isa_identify()\n");
130
131         for (ioport = 0x200; ioport < 0x3a0; ioport += 0x10) {
132
133                 /* No board found at address */
134                 if (!look_for_card(ioport)) {
135                         continue;
136                 }
137
138                 if (bootverbose)
139                         printf("ex: Found card at 0x%03x!\n", ioport);
140
141                 /* Board in PnP mode */
142                 if (eeprom_read(ioport, EE_W0) & EE_W0_PNP) {
143                         /* Reset the card. */
144                         outb(ioport + CMD_REG, Reset_CMD);
145                         DELAY(500);
146                         if (bootverbose)
147                                 printf("ex: card at 0x%03x in PnP mode!\n", ioport);
148                         continue;
149                 }
150
151                 bzero(enaddr, sizeof(enaddr));
152
153                 /* Reset the card. */
154                 outb(ioport + CMD_REG, Reset_CMD);
155                 DELAY(400);
156
157                 ex_get_address(ioport, enaddr);
158                 tmp = eeprom_read(ioport, EE_W1) & EE_W1_INT_SEL;
159
160                 /* work out which set of irq <-> internal tables to use */
161                 if (ex_card_type(enaddr) == CARD_TYPE_EX_10_PLUS) {
162                         irq  = plus_ee2irqmap[tmp];
163                         desc = "Intel Pro/10+";
164                 } else {
165                         irq = ee2irqmap[tmp];
166                         desc = "Intel Pro/10";
167                 }
168
169                 child = BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "ex", -1);
170                 device_set_desc_copy(child, desc);
171                 device_set_driver(child, driver);
172                 bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1);
173                 bus_set_resource(child, SYS_RES_IOPORT, 0, ioport, EX_IOSIZE);
174
175                 if (bootverbose)
176                         printf("ex: Adding board at 0x%03x, irq %d\n", ioport, irq);
177         }
178
179         return;
180 }
181
182 static int
183 ex_isa_probe(device_t dev)
184 {
185         u_int           iobase;
186         u_int           irq;
187         char *          irq2ee;
188         u_char *        ee2irq;
189         u_char          enaddr[6];
190         int             tmp;
191         int             error;
192
193         /* Check isapnp ids */
194         error = ISA_PNP_PROBE(device_get_parent(dev), dev, ex_ids);
195
196         /* If the card had a PnP ID that didn't match any we know about */
197         if (error == ENXIO) {
198                 return(error);
199         }
200
201         /* If we had some other problem. */
202         if (!(error == 0 || error == ENOENT)) {
203                 return(error);
204         }
205
206         iobase = bus_get_resource_start(dev, SYS_RES_IOPORT, 0);
207         if (!iobase) {
208                 printf("ex: no iobase?\n");
209                 return(ENXIO);
210         }
211
212         if (!look_for_card(iobase)) {
213                 printf("ex: no card found at 0x%03x\n", iobase);
214                 return(ENXIO);
215         }
216
217         if (bootverbose)
218                 printf("ex: ex_isa_probe() found card at 0x%03x\n", iobase);
219
220         /*
221          * Reset the card.
222          */
223         outb(iobase + CMD_REG, Reset_CMD);
224         DELAY(800);
225
226         ex_get_address(iobase, enaddr);
227
228         /* work out which set of irq <-> internal tables to use */
229         if (ex_card_type(enaddr) == CARD_TYPE_EX_10_PLUS) {
230                 irq2ee = plus_irq2eemap;
231                 ee2irq = plus_ee2irqmap;
232         } else {
233                 irq2ee = irq2eemap;
234                 ee2irq = ee2irqmap;
235         }
236
237         tmp = eeprom_read(iobase, EE_W1) & EE_W1_INT_SEL;
238         irq = bus_get_resource_start(dev, SYS_RES_IRQ, 0);
239
240         if (irq > 0) {
241                 /* This will happen if board is in PnP mode. */
242                 if (ee2irq[tmp] != irq) {
243                         printf("ex: WARNING: board's EEPROM is configured"
244                                 " for IRQ %d, using %d\n",
245                                 ee2irq[tmp], irq);
246                 }
247         } else {
248                 irq = ee2irq[tmp];
249                 bus_set_resource(dev, SYS_RES_IRQ, 0, irq, 1);
250         }
251
252         if (irq == 0) {
253                 printf("ex: invalid IRQ.\n");
254                 return(ENXIO);
255         }
256
257         return(0);
258 }
259
260 static int
261 ex_isa_attach(device_t dev)
262 {
263         struct ex_softc *       sc = device_get_softc(dev);
264         int                     error = 0;
265         u_int16_t               temp;
266
267         sc->dev = dev;
268         sc->ioport_rid = 0;
269         sc->irq_rid = 0;
270
271         if ((error = ex_alloc_resources(dev)) != 0) {
272                 device_printf(dev, "ex_alloc_resources() failed!\n");
273                 goto bad;
274         }
275
276         /*
277          * Fill in several fields of the softc structure:
278          *      - I/O base address.
279          *      - Hardware Ethernet address.
280          *      - IRQ number (if not supplied in config file, read it from EEPROM).
281          *      - Connector type.
282          */
283         sc->iobase = rman_get_start(sc->ioport);
284         sc->irq_no = rman_get_start(sc->irq);
285
286         ex_get_address(sc->iobase, sc->arpcom.ac_enaddr);
287
288         temp = eeprom_read(sc->iobase, EE_W0);
289         device_printf(sc->dev, "%s config, %s bus, ",
290                 (temp & EE_W0_PNP) ? "PnP" : "Manual",
291                 (temp & EE_W0_BUS16) ? "16-bit" : "8-bit");
292
293         temp = eeprom_read(sc->iobase, EE_W6);
294         printf("board id 0x%03x, stepping 0x%01x\n",
295                 (temp & EE_W6_BOARD_MASK) >> EE_W6_BOARD_SHIFT,
296                 temp & EE_W6_STEP_MASK);
297
298         if ((error = ex_attach(dev)) != 0) {
299                 device_printf(dev, "ex_attach() failed!\n");
300                 goto bad;
301         }
302
303         error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET,
304                                 ex_intr, (void *)sc,
305                                 &sc->ih, NULL);
306         if (error) {
307                 device_printf(dev, "bus_setup_intr() failed!\n");
308                 goto bad;
309         }
310
311         return(0);
312 bad:
313         ex_release_resources(dev);
314         return (error);
315 }