2 * Copyright (c) 2002 Takeshi Shibagaki
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
26 * xe pccard interface driver
28 * $FreeBSD: src/sys/dev/xe/if_xe_pccard.c,v 1.11 2003/10/14 22:51:35 rsm Exp $
29 * $DragonFly: src/sys/dev/netif/xe/if_xe_pccard.c,v 1.5 2007/08/14 15:32:32 sephe Exp $
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/kernel.h>
35 #include <sys/socket.h>
36 #include <sys/module.h>
40 #include <net/ethernet.h>
42 #include <net/if_arp.h>
43 #include <net/if_media.h>
44 #include <net/if_mib.h>
46 #include <bus/pccard/pccardvar.h>
47 #include <bus/pccard/pccarddevs.h>
56 #define DEVPRINTF(level, arg) if (xe_debug >= (level)) device_printf arg
58 #define DEVPRINTF(level, arg)
61 static const struct pccard_product xe_pccard_products
[] = {
62 PCMCIA_CARD(COMPAQ
, CPQ550
, 0),
63 PCMCIA_CARD(COMPAQ2
, CPQ_10_100
, 0),
64 PCMCIA_CARD(INTEL
, EEPRO100
, 0),
65 PCMCIA_CARD(RACORE
, ACCTON_EN2226
, 0),
66 PCMCIA_CARD(XIRCOM
, CE
, 0),
67 PCMCIA_CARD(XIRCOM
, CE2
, 0),
68 PCMCIA_CARD(XIRCOM
, CE3
, 0),
69 PCMCIA_CARD(XIRCOM
, CEM
, 0),
70 PCMCIA_CARD(XIRCOM
, CEM28
, 0),
71 PCMCIA_CARD(XIRCOM
, CEM33
, 0),
72 PCMCIA_CARD(XIRCOM
, CEM56
, 0),
73 PCMCIA_CARD(XIRCOM
, REM56
, 0),
74 PCMCIA_CARD(XIRCOM
, CNW_801
, 0),
75 PCMCIA_CARD(XIRCOM
, CNW_802
, 0),
81 const char *vendor_desc
;
83 { PCMCIA_VENDOR_XIRCOM
, "Xircom" },
84 { PCMCIA_VENDOR_COMPAQ
, "Compaq" },
85 { PCMCIA_VENDOR_COMPAQ2
, "Compaq" },
86 { PCMCIA_VENDOR_INTEL
, "Intel" },
90 #define XE_CARD_TYPE_FLAGS_NO 0x0
91 #define XE_CARD_TYPE_FLAGS_CE2 0x1
92 #define XE_CARD_TYPE_FLAGS_MOHAWK 0x2
93 #define XE_CARD_TYPE_FLAGS_DINGO 0x4
95 #define XE_PROD_UMASK 0x11000f
96 #define XE_PROD_ETHER_UMASK 0x010000
97 #define XE_PROD_MODEM_UMASK 0x100000
98 #define XE_PROD_SINGLE_ID1 0x010001
99 #define XE_PROD_SINGLE_ID2 0x010002
100 #define XE_PROD_SINGLE_ID3 0x010003
101 #define XE_PROD_MULTI_ID1 0x110001
102 #define XE_PROD_MULTI_ID2 0x110002
103 #define XE_PROD_MULTI_ID3 0x110003
104 #define XE_PROD_MULTI_ID4 0x110004
105 #define XE_PROD_MULTI_ID5 0x110005
106 #define XE_PROD_MULTI_ID6 0x110006
107 #define XE_PROD_MULTI_ID7 0x110007
109 struct xe_card_type
{
111 const char *card_type_desc
;
113 } xe_card_types
[] = {
114 { XE_PROD_MULTI_ID1
, "CEM", XE_CARD_TYPE_FLAGS_NO
},
115 { XE_PROD_MULTI_ID2
, "CEM2", XE_CARD_TYPE_FLAGS_CE2
},
116 { XE_PROD_MULTI_ID3
, "CEM3", XE_CARD_TYPE_FLAGS_CE2
},
117 { XE_PROD_MULTI_ID4
, "CEM33", XE_CARD_TYPE_FLAGS_CE2
},
118 { XE_PROD_MULTI_ID5
, "CEM56M", XE_CARD_TYPE_FLAGS_MOHAWK
},
119 { XE_PROD_MULTI_ID6
, "CEM56", XE_CARD_TYPE_FLAGS_MOHAWK
|
120 XE_CARD_TYPE_FLAGS_DINGO
},
121 { XE_PROD_MULTI_ID7
, "CEM56", XE_CARD_TYPE_FLAGS_MOHAWK
|
122 XE_CARD_TYPE_FLAGS_DINGO
},
123 { XE_PROD_SINGLE_ID1
, "CE", XE_CARD_TYPE_FLAGS_NO
},
124 { XE_PROD_SINGLE_ID2
, "CE2", XE_CARD_TYPE_FLAGS_CE2
},
125 { XE_PROD_SINGLE_ID3
, "CE3", XE_CARD_TYPE_FLAGS_MOHAWK
},
129 static struct xe_vendor
*xe_vendor_lookup (uint32_t);
130 static struct xe_card_type
*xe_card_type_lookup (uint32_t);
132 static int xe_cemfix (device_t
);
133 static int xe_pccard_probe (device_t
);
134 static int xe_pccard_match (device_t
);
135 static int xe_pccard_attach(device_t
);
137 static device_method_t xe_pccard_methods
[] = {
138 /* Device interface */
139 DEVMETHOD(device_probe
, pccard_compat_probe
),
140 DEVMETHOD(device_attach
, pccard_compat_attach
),
141 DEVMETHOD(device_detach
, xe_detach
),
144 DEVMETHOD(card_compat_match
, xe_pccard_match
),
145 DEVMETHOD(card_compat_probe
, xe_pccard_probe
),
146 DEVMETHOD(card_compat_attach
, xe_pccard_attach
),
151 static driver_t xe_pccard_driver
= {
154 sizeof(struct xe_softc
),
157 devclass_t xe_devclass
;
158 DRIVER_MODULE(xe
, pccard
, xe_pccard_driver
, xe_devclass
, 0, 0);
161 * Fixing for CEM2, CEM3 and CEM56/REM56 cards. These need some magic to
162 * enable the Ethernet function, which isn't mentioned anywhere in the CIS.
163 * Despite the register names, most of this isn't Dingo-specific.
166 xe_cemfix(device_t dev
)
168 struct xe_softc
*sc
= device_get_softc(dev
);
170 bus_space_handle_t bsh
;
175 device_printf(dev
, "CEM I/O port 0x%0lx, size 0x%0lx\n",
176 bus_get_resource_start(dev
, SYS_RES_IOPORT
, sc
->port_rid
),
177 bus_get_resource_count(dev
, SYS_RES_IOPORT
, sc
->port_rid
));
180 r
= bus_alloc_resource(dev
, SYS_RES_MEMORY
, &rid
, 0,
181 ~0, 4 << 10, RF_ACTIVE
);
183 device_printf(dev
, "Can't map in attribute memory\n");
187 bsh
= rman_get_bushandle(r
);
188 bst
= rman_get_bustag(r
);
190 CARD_SET_RES_FLAGS(device_get_parent(dev
), dev
, SYS_RES_MEMORY
, rid
,
193 bus_space_write_1(bst
, bsh
, DINGO_ECOR
, DINGO_ECOR_IRQ_LEVEL
|
194 DINGO_ECOR_INT_ENABLE
|
195 DINGO_ECOR_IOB_ENABLE
|
196 DINGO_ECOR_ETH_ENABLE
);
197 ioport
= bus_get_resource_start(dev
, SYS_RES_IOPORT
, sc
->port_rid
);
198 bus_space_write_1(bst
, bsh
, DINGO_EBAR0
, ioport
& 0xff);
199 bus_space_write_1(bst
, bsh
, DINGO_EBAR1
, (ioport
>> 8) & 0xff);
202 bus_space_write_1(bst
, bsh
, DINGO_DCOR0
, DINGO_DCOR0_SF_INT
);
203 bus_space_write_1(bst
, bsh
, DINGO_DCOR1
,
204 DINGO_DCOR1_INT_LEVEL
| DINGO_DCOR1_EEDIO
);
205 bus_space_write_1(bst
, bsh
, DINGO_DCOR2
, 0x00);
206 bus_space_write_1(bst
, bsh
, DINGO_DCOR3
, 0x00);
207 bus_space_write_1(bst
, bsh
, DINGO_DCOR4
, 0x00);
210 bus_release_resource(dev
, SYS_RES_MEMORY
, rid
, r
);
216 static struct xe_vendor
*
217 xe_vendor_lookup(uint32_t vendor_id
)
221 for (v
= xe_vendors
; v
->vendor_id
!= 0; ++v
) {
222 if(v
->vendor_id
== vendor_id
)
228 static struct xe_card_type
*
229 xe_card_type_lookup(uint32_t prod
)
231 struct xe_card_type
*ct
;
233 for (ct
= xe_card_types
; ct
->card_type_desc
!= NULL
; ++ct
) {
234 if(ct
->prod_type
== (prod
& XE_PROD_UMASK
))
241 * PCMCIA probe routine.
242 * Identify the device. Called from the bus driver when the card is
243 * inserted or otherwise powers up.
246 xe_pccard_probe(device_t dev
)
248 struct xe_softc
*scp
= device_get_softc(dev
);
249 uint32_t vendor
, product
, prod
;
251 const uint8_t *ether_addr
;
252 const char *cis3_str
=NULL
;
253 struct xe_vendor
*vendor_itm
;
254 struct xe_card_type
*card_itm
;
258 const char *vendor_str
= NULL
;
259 const char *product_str
= NULL
;
260 const char *cis4_str
= NULL
;
262 vendor
= pccard_get_vendor(dev
);
263 product
= pccard_get_product(dev
);
264 prodext
= pccard_get_prodext(dev
);
265 vendor_str
= pccard_get_vendor_str(dev
);
266 product_str
= pccard_get_product_str(dev
);
267 cis3_str
= pccard_get_cis3_str(dev
);
268 cis4_str
= pccard_get_cis4_str(dev
);
270 DEVPRINTF(1, (dev
, "pccard_probe\n"));
271 DEVPRINTF(1, (dev
, "vendor = 0x%04x\n", vendor
));
272 DEVPRINTF(1, (dev
, "product = 0x%04x\n", product
));
273 DEVPRINTF(1, (dev
, "prodext = 0x%02x\n", prodext
));
274 DEVPRINTF(1, (dev
, "vendor_str = %s\n",
275 vendor_str
== NULL
? "NULL" : vendor_str
));
276 DEVPRINTF(1, (dev
, "product_str = %s\n",
277 product_str
== NULL
? "NULL" : product_str
));
278 DEVPRINTF(1, (dev
, "cis3_str = %s\n",
279 cis3_str
== NULL
? "NULL" : cis3_str
));
280 DEVPRINTF(1, (dev
, "cis4_str = %s\n",
281 cis4_str
== NULL
? "NULL" : cis4_str
));
285 * PCCARD_CISTPL_MANFID = 0x20
287 vendor
= pccard_get_vendor(dev
);
288 vendor_itm
= xe_vendor_lookup(vendor
);
290 * We always have some vendor here, although
291 * vendor description may be "Unknown".
293 scp
->vendor
= vendor_itm
->vendor_desc
;
295 product
= pccard_get_product(dev
);
296 prodext
= pccard_get_prodext(dev
);
299 * prod(new) = rev, media, prod(old)
300 * prod(new) = (don't care), (care 0x10 bit), (care 0x0f bit)
302 prod
= (product
<< 8) | prodext
;
303 card_itm
= xe_card_type_lookup(prod
);
304 if (card_itm
== NULL
)
307 scp
->card_type
= card_itm
->card_type_desc
;
308 if (card_itm
->prod_type
& XE_PROD_MODEM_UMASK
)
311 for (i
= 1; i
!= XE_CARD_TYPE_FLAGS_DINGO
; i
= i
<< 1) {
312 switch(i
& card_itm
->flags
) {
313 case XE_CARD_TYPE_FLAGS_CE2
:
316 case XE_CARD_TYPE_FLAGS_MOHAWK
:
319 case XE_CARD_TYPE_FLAGS_DINGO
:
326 * PCCARD_CISTPL_VERS_1 = 0x15
328 * Check for certain strange CE2's that look like CE's:
329 * match 3rd version string against "CE2"
331 cis3_str
= pccard_get_cis3_str(dev
);
332 if (strcmp(scp
->card_type
, "CE") == 0)
333 if (cis3_str
!= NULL
&& strcmp(cis3_str
, "PS-CE2-10") == 0)
334 scp
->card_type
= "CE2";
337 * PCCARD_CISTPL_FUNCE = 0x22
339 ether_addr
= pccard_get_ether(dev
);
340 bcopy(ether_addr
, scp
->arpcom
.ac_enaddr
, ETHER_ADDR_LEN
);
342 /* Reject unsupported cards */
343 if (strcmp(scp
->card_type
, "CE") == 0 ||
344 strcmp(scp
->card_type
, "CEM") == 0) {
345 device_printf(dev
, "Sorry, your %s card is not supported :(\n",
355 xe_pccard_attach(device_t dev
)
357 struct xe_softc
*scp
= device_get_softc(dev
);
360 if ((err
= xe_activate(dev
)) != 0)
363 /* Hack RealPorts into submission */
364 if (scp
->modem
&& xe_cemfix(dev
) < 0) {
365 device_printf(dev
, "Unable to fix your %s combo card\n",
370 return xe_attach(dev
);
374 xe_pccard_match(device_t dev
)
376 const struct pccard_product
*pp
;
378 if ((pp
= pccard_product_lookup(dev
, xe_pccard_products
,
379 sizeof(xe_pccard_products
[0]), NULL
)) != NULL
) {
380 if (pp
->pp_name
!= NULL
)
381 device_set_desc(dev
, pp
->pp_name
);