1 /* $NetBSD: pcmcia_cis_quirks.c,v 1.33 2008/09/06 22:07:11 rmind Exp $ */
4 * Copyright (c) 1998 Marc Horowitz. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Marc Horowitz.
17 * 4. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: pcmcia_cis_quirks.c,v 1.33 2008/09/06 22:07:11 rmind Exp $");
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/device.h>
38 #include <sys/kernel.h>
41 #include <dev/pcmcia/pcmciadevs.h>
42 #include <dev/pcmcia/pcmciareg.h>
43 #include <dev/pcmcia/pcmciachip.h>
44 #include <dev/pcmcia/pcmciavar.h>
46 /* There are cards out there whose CIS flat-out lies. This file
47 contains struct pcmcia_function chains for those devices. */
49 /* these structures are just static templates which are then copied
50 into "live" allocated structures */
52 static const struct pcmcia_function pcmcia_3cxem556_func0
= {
53 .number
= 0, /* function number */
54 .function
= PCMCIA_FUNCTION_NETWORK
,
55 .last_config_index
= 0x07, /* last cfe number */
56 .ccr_base
= 0x800, /* ccr_base */
57 .ccr_mask
= 0x63, /* ccr_mask */
60 static const struct pcmcia_config_entry pcmcia_3cxem556_func0_cfe0
= {
61 .number
= 0x07, /* cfe number */
62 .flags
= PCMCIA_CFE_IO8
| PCMCIA_CFE_IO16
| PCMCIA_CFE_IRQLEVEL
,
63 .iftype
= PCMCIA_IFTYPE_IO
,
64 .num_iospace
= 1, /* num_iospace */
65 .iomask
= 4, /* iomask */
66 .iospace
= { { .length
= 0x0010, .start
= 0 } }, /* iospace */
67 .irqmask
= 0xffff, /* irqmask */
70 static const struct pcmcia_function pcmcia_3cxem556_func1
= {
71 .number
= 1, /* function number */
72 .function
= PCMCIA_FUNCTION_SERIAL
,
73 .last_config_index
= 0x27, /* last cfe number */
74 .ccr_base
= 0x900, /* ccr_base */
75 .ccr_mask
= 0x63, /* ccr_mask */
78 static const struct pcmcia_config_entry pcmcia_3cxem556_func1_cfe0
= {
79 .number
= 0x27, /* cfe number */
80 .flags
= PCMCIA_CFE_IO8
| PCMCIA_CFE_IRQLEVEL
,
81 .iftype
= PCMCIA_IFTYPE_IO
,
82 .num_iospace
= 1, /* num_iospace */
83 .iomask
= 3, /* iomask */
84 .iospace
= { { .length
= 0x0008, .start
= 0 } }, /* iospace */
85 .irqmask
= 0xffff, /* irqmask */
88 static const struct pcmcia_function pcmcia_3ccfem556bi_func0
= {
89 .number
= 0, /* function number */
90 .function
= PCMCIA_FUNCTION_NETWORK
,
91 .last_config_index
= 0x07, /* last cfe number */
92 .ccr_base
= 0x1000, /* ccr_base */
93 .ccr_mask
= 0x267, /* ccr_mask */
96 static const struct pcmcia_config_entry pcmcia_3ccfem556bi_func0_cfe0
= {
97 .number
= 0x07, /* cfe number */
98 .flags
= PCMCIA_CFE_IO8
| PCMCIA_CFE_IO16
| PCMCIA_CFE_IRQLEVEL
,
99 .iftype
= PCMCIA_IFTYPE_IO
,
100 .num_iospace
= 1, /* num_iospace */
101 .iomask
= 5, /* iomask */
102 .iospace
= { { .length
= 0x0020, .start
= 0 } }, /* iospace */
105 static const struct pcmcia_function pcmcia_3ccfem556bi_func1
= {
106 .number
= 1, /* function number */
107 .function
= PCMCIA_FUNCTION_SERIAL
,
108 .last_config_index
= 0x27, /* last cfe number */
109 .ccr_base
= 0x1100, /* ccr_base */
110 .ccr_mask
= 0x277, /* ccr_mask */
113 static const struct pcmcia_config_entry pcmcia_3ccfem556bi_func1_cfe0
= {
114 .number
= 0x27, /* cfe number */
115 .flags
= PCMCIA_CFE_IO8
| PCMCIA_CFE_IRQLEVEL
,
116 .iftype
= PCMCIA_IFTYPE_IO
,
117 .num_iospace
= 1, /* num_iospace */
118 .iomask
= 3, /* iomask */
119 .iospace
= { { .length
= 0x0008, .start
= 0 } }, /* iospace */
120 .irqmask
= 0xffff, /* irqmask */
123 static const struct pcmcia_function pcmcia_sveclancard_func0
= {
124 .number
= 0, /* function number */
125 .function
= PCMCIA_FUNCTION_NETWORK
,
126 .last_config_index
= 0x1, /* last cfe number */
127 .ccr_base
= 0x100, /* ccr_base */
128 .ccr_mask
= 0x1, /* ccr_mask */
131 static const struct pcmcia_config_entry pcmcia_sveclancard_func0_cfe0
= {
132 .number
= 0x1, /* cfe number */
133 .flags
= PCMCIA_CFE_MWAIT_REQUIRED
| PCMCIA_CFE_RDYBSY_ACTIVE
|
134 PCMCIA_CFE_WP_ACTIVE
| PCMCIA_CFE_BVD_ACTIVE
| PCMCIA_CFE_IO16
,
135 .iftype
= PCMCIA_IFTYPE_IO
,
136 .num_iospace
= 1, /* num_iospace */
137 .iomask
= 5, /* iomask */
138 .iospace
= { { .length
= 0x20, .start
= 0x300 } }, /* iospace */
139 .irqmask
= 0xdeb8, /* irqmask */
142 static const struct pcmcia_function pcmcia_ndc_nd5100_func0
= {
143 .number
= 0, /* function number */
144 .function
= PCMCIA_FUNCTION_NETWORK
,
145 .last_config_index
= 0x23, /* last cfe number */
146 .ccr_base
= 0x3f8, /* ccr_base */
147 .ccr_mask
= 0x3, /* ccr_mask */
150 static const struct pcmcia_config_entry pcmcia_ndc_nd5100_func0_cfe0
= {
151 .number
= 0x20, /* cfe number */
152 .flags
= PCMCIA_CFE_MWAIT_REQUIRED
| PCMCIA_CFE_IO16
|
154 .iftype
= PCMCIA_IFTYPE_IO
,
155 .num_iospace
= 1, /* num_iospace */
156 .iomask
= 5, /* iomask */
157 .iospace
= { { .length
= 0x20, .start
= 0x300 } }, /* iospace */
158 .irqmask
= 0xdeb8, /* irqmask */
161 static const struct pcmcia_function pcmcia_emtac_a2424i_func0
= {
162 .number
= 0, /* function number */
163 .function
= PCMCIA_FUNCTION_NETWORK
,
164 .last_config_index
= 0x21, /* last cfe number */
165 .ccr_base
= 0x3e0, /* ccr_base */
166 .ccr_mask
= 0x1, /* ccr_mask */
169 static const struct pcmcia_config_entry pcmcia_emtac_a2424i_func0_cfe0
= {
170 .number
= 0x21, /* cfe number */
171 .flags
= PCMCIA_CFE_IO16
| PCMCIA_CFE_IRQLEVEL
| PCMCIA_CFE_IRQPULSE
,
172 .iftype
= PCMCIA_IFTYPE_IO
,
173 .num_iospace
= 1, /* num_iospace */
174 .iomask
= 6, /* iomask */
175 .iospace
= { { .length
= 0x40, .start
= 0x100 } }, /* iospace */
176 .irqmask
= 0xffff, /* irqmask */
179 static const struct pcmcia_function pcmcia_fujitsu_j181_func0
= {
180 .number
= 0, /* function number */
181 .function
= PCMCIA_FUNCTION_NETWORK
,
182 .last_config_index
= 0x21, /* last cfe number */
183 .ccr_base
= 0xfe0, /* ccr_base */
184 .ccr_mask
= 0xf, /* ccr_mask */
187 static const struct pcmcia_config_entry pcmcia_fujitsu_j181_func0_cfe0
= {
188 .number
= 0xc, /* cfe number */
189 .flags
= PCMCIA_CFE_MWAIT_REQUIRED
| PCMCIA_CFE_WP_ACTIVE
|
190 PCMCIA_CFE_IO8
| PCMCIA_CFE_IO16
| PCMCIA_CFE_IRQLEVEL
|
192 .iftype
= PCMCIA_IFTYPE_IO
,
193 .num_iospace
= 1, /* num_iospace */
194 .iomask
= 10, /* iomask */
195 .iospace
= { { .length
= 0x20, .start
= 0x140 } }, /* iospace */
196 .irqmask
= 0xffff, /* irqmask */
199 static const struct pcmcia_function pcmcia_necinfrontia_ax420n_func0
= {
200 .number
= 0, /* function number */
201 .function
= PCMCIA_FUNCTION_SERIAL
,
202 .last_config_index
= 0x38, /* last cfe number */
203 .ccr_base
= 0x200, /* ccr_base */
204 .ccr_mask
= 0x1f, /* ccr_mask */
207 static const struct pcmcia_config_entry pcmcia_necinfrontia_ax420n_func0_cfe0
= {
208 .number
= 0x25, /* cfe number */
209 .flags
= PCMCIA_CFE_RDYBSY_ACTIVE
| PCMCIA_CFE_IO8
|
210 PCMCIA_CFE_IRQLEVEL
| PCMCIA_CFE_POWERDOWN
|
212 .iftype
= PCMCIA_IFTYPE_IO
,
213 .num_iospace
= 1, /* num_iospace */
214 .iomask
= 10, /* iomask */
215 .iospace
= { { .length
= 0x8, .start
= 0x3f8 } }, /* iospace */
216 .irqmask
= 0x86bc, /* irqmask */
219 static const struct pcmcia_function pcmcia_sierra_ac850_func0
= {
220 .number
= 0, /* function number */
221 .function
= PCMCIA_FUNCTION_SERIAL
,
222 .last_config_index
= 0x24, /* last cfe number */
223 .ccr_base
= 0x700, /* ccr_base */
224 .ccr_mask
= 0x73, /* ccr_mask */
227 static const struct pcmcia_config_entry pcmcia_sierra_ac850_cfe0
= {
228 .number
= 0x22, /* cfe number */
229 .flags
= PCMCIA_CFE_IO8
| PCMCIA_CFE_IRQLEVEL
,
230 .iftype
= PCMCIA_IFTYPE_IO
,
231 .num_iospace
= 1, /* num_iospace */
232 .iomask
= 0, /* iomask */
233 .iospace
= { { .length
= 0x0008, .start
= 0x3e8 } }, /* iospace */
234 .irqmask
= 0x3fbc, /* irqmask */
237 static const struct pcmcia_cis_quirk pcmcia_cis_quirks
[] = {
238 { PCMCIA_VENDOR_3COM
, PCMCIA_PRODUCT_3COM_3CXEM556
,
240 &pcmcia_3cxem556_func0
, &pcmcia_3cxem556_func0_cfe0
},
241 { PCMCIA_VENDOR_3COM
, PCMCIA_PRODUCT_3COM_3CXEM556
,
243 &pcmcia_3cxem556_func1
, &pcmcia_3cxem556_func1_cfe0
},
244 { PCMCIA_VENDOR_3COM
, PCMCIA_PRODUCT_3COM_3CXEM556INT
,
246 &pcmcia_3cxem556_func0
, &pcmcia_3cxem556_func0_cfe0
},
247 { PCMCIA_VENDOR_3COM
, PCMCIA_PRODUCT_3COM_3CXEM556INT
,
249 &pcmcia_3cxem556_func1
, &pcmcia_3cxem556_func1_cfe0
},
250 { PCMCIA_VENDOR_3COM
, PCMCIA_PRODUCT_3COM_3CCFEM556BI
,
252 &pcmcia_3ccfem556bi_func0
, &pcmcia_3ccfem556bi_func0_cfe0
},
253 { PCMCIA_VENDOR_3COM
, PCMCIA_PRODUCT_3COM_3CCFEM556BI
,
255 &pcmcia_3ccfem556bi_func1
, &pcmcia_3ccfem556bi_func1_cfe0
},
256 { PCMCIA_VENDOR_INVALID
, PCMCIA_PRODUCT_INVALID
,
257 PCMCIA_CIS_SVEC_LANCARD
,
258 &pcmcia_sveclancard_func0
, &pcmcia_sveclancard_func0_cfe0
},
259 { PCMCIA_VENDOR_INVALID
, PCMCIA_PRODUCT_INVALID
,
260 PCMCIA_CIS_NDC_ND5100_E
,
261 &pcmcia_ndc_nd5100_func0
, &pcmcia_ndc_nd5100_func0_cfe0
},
262 { PCMCIA_VENDOR_EMTAC
, PCMCIA_PRODUCT_EMTAC_WLAN
,
264 &pcmcia_emtac_a2424i_func0
, &pcmcia_emtac_a2424i_func0_cfe0
},
265 { PCMCIA_VENDOR_INVALID
, PCMCIA_PRODUCT_INVALID
,
266 PCMCIA_CIS_FUJITSU_FMV_J181
,
267 &pcmcia_fujitsu_j181_func0
, &pcmcia_fujitsu_j181_func0_cfe0
},
268 { PCMCIA_VENDOR_NECINFRONTIA
, PCMCIA_PRODUCT_NECINFRONTIA_AX420N
,
270 &pcmcia_necinfrontia_ax420n_func0
,
271 &pcmcia_necinfrontia_ax420n_func0_cfe0
},
274 static const int pcmcia_cis_nquirks
=
275 sizeof(pcmcia_cis_quirks
) / sizeof(pcmcia_cis_quirks
[0]);
278 pcmcia_check_cis_quirks(struct pcmcia_softc
*sc
)
282 struct pcmcia_function
*pf
;
283 const struct pcmcia_function
*pf_last
;
284 struct pcmcia_config_entry
*cfe
;
285 struct pcmcia_card
*card
= &sc
->card
;
286 const struct pcmcia_cis_quirk
*quirk
;
291 for (i
= 0; i
< pcmcia_cis_nquirks
; i
++) {
292 quirk
= &pcmcia_cis_quirks
[i
];
294 if (card
->manufacturer
== quirk
->manufacturer
&&
295 card
->manufacturer
!= PCMCIA_VENDOR_INVALID
&&
296 card
->product
== quirk
->product
&&
297 card
->product
!= PCMCIA_PRODUCT_INVALID
)
300 for (j
= 0; j
< 2; j
++)
301 if (card
->cis1_info
[j
] == NULL
||
302 quirk
->cis1_info
[j
] == NULL
||
303 strcmp(card
->cis1_info
[j
],
304 quirk
->cis1_info
[j
]) != 0)
309 if (pcmcia_verbose
) {
310 printf("%s: using CIS quirks for ",
311 device_xname(sc
->dev
));
312 for (j
= 0; j
< 4; j
++) {
313 if (card
->cis1_info
[j
] == NULL
)
317 printf("%s", card
->cis1_info
[j
]);
321 pcmcia_free_pf(&card
->pf_head
);
325 if (pf_last
!= quirk
->pf
) {
327 * XXX: a driver which still calls pcmcia_card_attach
328 * very early attach stage should be fixed instead.
330 pf
= malloc(sizeof(*pf
), M_DEVBUF
,
331 cold
? M_NOWAIT
: M_WAITOK
);
333 panic("pcmcia_check_cis_quirks: malloc pf");
335 SIMPLEQ_INIT(&pf
->cfe_head
);
336 SIMPLEQ_INSERT_TAIL(&card
->pf_head
, pf
, pf_list
);
343 cfe
= malloc(sizeof(*cfe
), M_DEVBUF
,
344 cold
? M_NOWAIT
: M_WAITOK
);
346 panic("pcmcia_check_cis_quirks: malloc cfe");
349 SIMPLEQ_INSERT_TAIL(&pf
->cfe_head
, cfe
, cfe_list
);