kernel: Use DEVMETHOD_END in the drivers.
[dragonfly.git] / sys / dev / netif / xe / if_xe_pccard.c
1 /*
2  * Copyright (c) 2002 Takeshi Shibagaki
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  * xe pccard interface driver
27  *
28  * $FreeBSD: src/sys/dev/xe/if_xe_pccard.c,v 1.11 2003/10/14 22:51:35 rsm Exp $
29  */
30
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/kernel.h>
34 #include <sys/socket.h>
35 #include <sys/module.h>
36 #include <sys/bus.h>
37 #include <sys/rman.h>
38  
39 #include <net/ethernet.h>
40 #include <net/if.h> 
41 #include <net/if_arp.h>
42 #include <net/if_media.h>
43 #include <net/if_mib.h>
44
45 #include <bus/pccard/pccardvar.h>
46 #include <bus/pccard/pccarddevs.h>
47 #include "card_if.h"
48
49 #include "if_xereg.h"
50 #include "if_xevar.h"
51
52 #define XE_DEBUG
53
54 #ifdef XE_DEBUG
55 #define DEVPRINTF(level, arg)   if (xe_debug >= (level)) device_printf arg
56 #else
57 #define DEVPRINTF(level, arg)
58 #endif
59
60 static const struct pccard_product xe_pccard_products[] = {
61         PCMCIA_CARD(COMPAQ, CPQ550, 0),
62         PCMCIA_CARD(COMPAQ2, CPQ_10_100, 0),
63         PCMCIA_CARD(INTEL, EEPRO100, 0),
64         PCMCIA_CARD(RACORE, ACCTON_EN2226, 0),
65         PCMCIA_CARD(XIRCOM, CE, 0),
66         PCMCIA_CARD(XIRCOM, CE2, 0),
67         PCMCIA_CARD(XIRCOM, CE3, 0),
68         PCMCIA_CARD(XIRCOM, CEM, 0),
69         PCMCIA_CARD(XIRCOM, CEM28, 0),
70         PCMCIA_CARD(XIRCOM, CEM33, 0),
71         PCMCIA_CARD(XIRCOM, CEM56, 0),
72         PCMCIA_CARD(XIRCOM, REM56, 0),
73         PCMCIA_CARD(XIRCOM, CNW_801, 0),
74         PCMCIA_CARD(XIRCOM, CNW_802, 0),
75         { NULL }
76 };
77
78 struct xe_vendor {
79         uint32_t         vendor_id;
80         const char      *vendor_desc;
81 } xe_vendors[] = {
82         { PCMCIA_VENDOR_XIRCOM,         "Xircom" },
83         { PCMCIA_VENDOR_COMPAQ,         "Compaq" },
84         { PCMCIA_VENDOR_COMPAQ2,        "Compaq" },
85         { PCMCIA_VENDOR_INTEL,          "Intel" },
86         { 0,                            "Unknown" }
87 };
88
89 #define XE_CARD_TYPE_FLAGS_NO           0x0
90 #define XE_CARD_TYPE_FLAGS_CE2          0x1
91 #define XE_CARD_TYPE_FLAGS_MOHAWK       0x2
92 #define XE_CARD_TYPE_FLAGS_DINGO        0x4
93
94 #define XE_PROD_UMASK           0x11000f
95 #define XE_PROD_ETHER_UMASK     0x010000
96 #define XE_PROD_MODEM_UMASK     0x100000
97 #define XE_PROD_SINGLE_ID1      0x010001
98 #define XE_PROD_SINGLE_ID2      0x010002
99 #define XE_PROD_SINGLE_ID3      0x010003
100 #define XE_PROD_MULTI_ID1       0x110001
101 #define XE_PROD_MULTI_ID2       0x110002
102 #define XE_PROD_MULTI_ID3       0x110003
103 #define XE_PROD_MULTI_ID4       0x110004
104 #define XE_PROD_MULTI_ID5       0x110005
105 #define XE_PROD_MULTI_ID6       0x110006 
106 #define XE_PROD_MULTI_ID7       0x110007  
107
108 struct xe_card_type {
109         uint32_t         prod_type;
110         const char      *card_type_desc;
111         uint32_t         flags;
112 } xe_card_types[] = {
113         { XE_PROD_MULTI_ID1,    "CEM",          XE_CARD_TYPE_FLAGS_NO },
114         { XE_PROD_MULTI_ID2,    "CEM2",         XE_CARD_TYPE_FLAGS_CE2 },
115         { XE_PROD_MULTI_ID3,    "CEM3",         XE_CARD_TYPE_FLAGS_CE2 },
116         { XE_PROD_MULTI_ID4,    "CEM33",        XE_CARD_TYPE_FLAGS_CE2 },
117         { XE_PROD_MULTI_ID5,    "CEM56M",       XE_CARD_TYPE_FLAGS_MOHAWK },
118         { XE_PROD_MULTI_ID6,    "CEM56",        XE_CARD_TYPE_FLAGS_MOHAWK |
119                                                 XE_CARD_TYPE_FLAGS_DINGO },
120         { XE_PROD_MULTI_ID7,    "CEM56",        XE_CARD_TYPE_FLAGS_MOHAWK |
121                                                 XE_CARD_TYPE_FLAGS_DINGO },
122         { XE_PROD_SINGLE_ID1,   "CE",           XE_CARD_TYPE_FLAGS_NO },
123         { XE_PROD_SINGLE_ID2,   "CE2",          XE_CARD_TYPE_FLAGS_CE2 },
124         { XE_PROD_SINGLE_ID3,   "CE3",          XE_CARD_TYPE_FLAGS_MOHAWK },
125         { 0, NULL, -1 }
126 };
127
128 static struct xe_vendor         *xe_vendor_lookup       (uint32_t);
129 static struct xe_card_type      *xe_card_type_lookup    (uint32_t);
130
131 static int      xe_cemfix       (device_t);
132 static int      xe_pccard_probe (device_t);
133 static int      xe_pccard_match (device_t);
134 static int      xe_pccard_attach(device_t);
135
136 static device_method_t xe_pccard_methods[] = {
137         /* Device interface */
138         DEVMETHOD(device_probe,         pccard_compat_probe),
139         DEVMETHOD(device_attach,        pccard_compat_attach),
140         DEVMETHOD(device_detach,        xe_detach),
141
142         /* Card interface */
143         DEVMETHOD(card_compat_match,    xe_pccard_match),
144         DEVMETHOD(card_compat_probe,    xe_pccard_probe),
145         DEVMETHOD(card_compat_attach,   xe_pccard_attach),
146
147         DEVMETHOD_END
148 };
149
150 static driver_t xe_pccard_driver = {
151         "xe",
152         xe_pccard_methods,
153         sizeof(struct xe_softc),
154 };
155
156 devclass_t xe_devclass;
157 DRIVER_MODULE(xe, pccard, xe_pccard_driver, xe_devclass, NULL, NULL);
158
159 /*
160  * Fixing for CEM2, CEM3 and CEM56/REM56 cards.  These need some magic to
161  * enable the Ethernet function, which isn't mentioned anywhere in the CIS.
162  * Despite the register names, most of this isn't Dingo-specific.
163  */
164 static int
165 xe_cemfix(device_t dev)
166 {
167         struct xe_softc *sc = device_get_softc(dev);
168         bus_space_tag_t bst;
169         bus_space_handle_t bsh;
170         struct resource *r;
171         int rid;
172         int ioport;
173
174         device_printf(dev, "CEM I/O port 0x%0lx, size 0x%0lx\n",
175             bus_get_resource_start(dev, SYS_RES_IOPORT, sc->port_rid),
176             bus_get_resource_count(dev, SYS_RES_IOPORT, sc->port_rid));
177
178         rid = 0;
179         r = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0,
180                                ~0, 4 << 10, RF_ACTIVE);
181         if (r == NULL) {
182                 device_printf(dev, "Can't map in attribute memory\n");
183                 return -1;
184         }
185
186         bsh = rman_get_bushandle(r);
187         bst = rman_get_bustag(r);
188
189         CARD_SET_RES_FLAGS(device_get_parent(dev), dev, SYS_RES_MEMORY, rid,
190                            PCCARD_A_MEM_ATTR);
191
192         bus_space_write_1(bst, bsh, DINGO_ECOR, DINGO_ECOR_IRQ_LEVEL |
193                                                 DINGO_ECOR_INT_ENABLE |
194                                                 DINGO_ECOR_IOB_ENABLE |
195                                                 DINGO_ECOR_ETH_ENABLE);
196         ioport = bus_get_resource_start(dev, SYS_RES_IOPORT, sc->port_rid);
197         bus_space_write_1(bst, bsh, DINGO_EBAR0, ioport & 0xff);
198         bus_space_write_1(bst, bsh, DINGO_EBAR1, (ioport >> 8) & 0xff);
199
200         if (sc->dingo) {
201                 bus_space_write_1(bst, bsh, DINGO_DCOR0, DINGO_DCOR0_SF_INT);
202                 bus_space_write_1(bst, bsh, DINGO_DCOR1,
203                                   DINGO_DCOR1_INT_LEVEL | DINGO_DCOR1_EEDIO);
204                 bus_space_write_1(bst, bsh, DINGO_DCOR2, 0x00);
205                 bus_space_write_1(bst, bsh, DINGO_DCOR3, 0x00);
206                 bus_space_write_1(bst, bsh, DINGO_DCOR4, 0x00);
207         }
208
209         bus_release_resource(dev, SYS_RES_MEMORY, rid, r);
210
211         /* success! */
212         return 0;
213 }
214
215 static struct xe_vendor *
216 xe_vendor_lookup(uint32_t vendor_id)
217 {
218         struct xe_vendor *v;
219
220         for (v = xe_vendors; v->vendor_id != 0; ++v) {
221                 if(v->vendor_id == vendor_id)
222                         break;
223         }
224         return v;
225 }
226       
227 static struct xe_card_type *
228 xe_card_type_lookup(uint32_t prod)
229 {
230         struct xe_card_type *ct;
231
232         for (ct = xe_card_types; ct->card_type_desc != NULL; ++ct) {
233                 if(ct->prod_type == (prod & XE_PROD_UMASK))
234                         return ct;
235         }
236         return NULL;
237 }
238
239 /*
240  * PCMCIA probe routine.
241  * Identify the device.  Called from the bus driver when the card is
242  * inserted or otherwise powers up.
243  */
244 static int
245 xe_pccard_probe(device_t dev)
246 {
247         struct xe_softc *scp = device_get_softc(dev);
248         uint32_t vendor, product, prod;
249         uint16_t prodext;
250         const uint8_t *ether_addr;
251         const char *cis3_str=NULL;
252         struct xe_vendor *vendor_itm;
253         struct xe_card_type *card_itm;
254         int i;
255
256 #ifdef XE_DEBUG
257         const char *vendor_str = NULL;
258         const char *product_str = NULL;
259         const char *cis4_str = NULL;
260
261         vendor = pccard_get_vendor(dev);
262         product = pccard_get_product(dev);
263         prodext = pccard_get_prodext(dev);
264         vendor_str = pccard_get_vendor_str(dev);
265         product_str = pccard_get_product_str(dev);
266         cis3_str = pccard_get_cis3_str(dev);
267         cis4_str = pccard_get_cis4_str(dev);
268
269         DEVPRINTF(1, (dev, "pccard_probe\n"));
270         DEVPRINTF(1, (dev, "vendor = 0x%04x\n", vendor));
271         DEVPRINTF(1, (dev, "product = 0x%04x\n", product));
272         DEVPRINTF(1, (dev, "prodext = 0x%02x\n", prodext));
273         DEVPRINTF(1, (dev, "vendor_str = %s\n",
274                       vendor_str == NULL ? "NULL" : vendor_str));
275         DEVPRINTF(1, (dev, "product_str = %s\n",
276                       product_str == NULL ? "NULL" : product_str));
277         DEVPRINTF(1, (dev, "cis3_str = %s\n",
278                       cis3_str == NULL ? "NULL" : cis3_str));
279         DEVPRINTF(1, (dev, "cis4_str = %s\n",
280                       cis4_str == NULL ? "NULL" : cis4_str));
281 #endif
282
283         /*
284          * PCCARD_CISTPL_MANFID = 0x20
285          */
286         vendor = pccard_get_vendor(dev);
287         vendor_itm = xe_vendor_lookup(vendor);
288         /*
289          * We always have some vendor here, although
290          * vendor description may be "Unknown".
291          */
292         scp->vendor = vendor_itm->vendor_desc;
293
294         product = pccard_get_product(dev);
295         prodext = pccard_get_prodext(dev);
296
297         /*
298          * prod(new) =  rev, media, prod(old)
299          * prod(new) =  (don't care), (care 0x10 bit), (care 0x0f bit)
300          */
301         prod = (product << 8) | prodext;
302         card_itm = xe_card_type_lookup(prod);
303         if (card_itm == NULL)
304                 return ENODEV;
305
306         scp->card_type = card_itm->card_type_desc;
307         if (card_itm->prod_type & XE_PROD_MODEM_UMASK)
308                 scp->modem = 1;
309
310         for (i = 1; i != XE_CARD_TYPE_FLAGS_DINGO; i = i << 1) {
311                 switch(i & card_itm->flags) {
312                 case XE_CARD_TYPE_FLAGS_CE2:
313                         scp->ce2 = 1;
314                         break;
315                 case XE_CARD_TYPE_FLAGS_MOHAWK:
316                         scp->mohawk = 1;
317                         break;
318                 case XE_CARD_TYPE_FLAGS_DINGO:
319                         scp->dingo = 1;
320                         break;
321                 }
322         }
323
324         /*
325          * PCCARD_CISTPL_VERS_1 = 0x15
326          *
327          * Check for certain strange CE2's that look like CE's:
328          * match 3rd version string against "CE2"
329          */
330         cis3_str = pccard_get_cis3_str(dev);
331         if (strcmp(scp->card_type, "CE") == 0)
332                 if (cis3_str != NULL && strcmp(cis3_str, "PS-CE2-10") == 0)
333                         scp->card_type = "CE2";
334
335         /*
336          * PCCARD_CISTPL_FUNCE = 0x22
337          */
338         ether_addr = pccard_get_ether(dev);
339         bcopy(ether_addr, scp->arpcom.ac_enaddr, ETHER_ADDR_LEN);
340
341         /* Reject unsupported cards */
342         if (strcmp(scp->card_type, "CE") == 0 ||
343             strcmp(scp->card_type, "CEM") == 0) {
344                 device_printf(dev, "Sorry, your %s card is not supported :(\n",
345                               scp->card_type);
346                 return ENODEV;
347         }
348
349         /* Success */
350         return 0;
351 }
352
353 static int
354 xe_pccard_attach(device_t dev)
355 {
356         struct xe_softc *scp = device_get_softc(dev);
357         int err;
358
359         if ((err = xe_activate(dev)) != 0)
360                 return err;
361          
362         /* Hack RealPorts into submission */
363         if (scp->modem && xe_cemfix(dev) < 0) {
364                 device_printf(dev, "Unable to fix your %s combo card\n",
365                               scp->card_type);
366                 xe_deactivate(dev);
367                 return ENODEV;
368         }
369         return xe_attach(dev);
370 }
371
372 static int
373 xe_pccard_match(device_t dev)
374 {
375         const struct pccard_product *pp;
376
377         if ((pp = pccard_product_lookup(dev, xe_pccard_products,
378              sizeof(xe_pccard_products[0]), NULL)) != NULL) {
379                 if (pp->pp_name != NULL)
380                         device_set_desc(dev, pp->pp_name);
381                 return 0;
382         }
383         return EIO;
384 }