1 /* $OpenBSD: pcmcia_cis_quirks.c,v 1.15 2021/03/07 06:20:09 jsg Exp $ */
2 /* $NetBSD: pcmcia_cis_quirks.c,v 1.3 1998/12/29 09:00:28 marc Exp $ */
3
4 /*
5 * Copyright (c) 1998 Marc Horowitz. 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 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Marc Horowitz.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/malloc.h>
36 #include <sys/device.h>
37
38 #include <dev/pcmcia/pcmciadevs.h>
39 #include <dev/pcmcia/pcmciareg.h>
40 #include <dev/pcmcia/pcmciavar.h>
41
42 /* There are cards out there whose CIS flat-out lies. This file
43 contains struct pcmcia_function chains for those devices. */
44
45 /* these structures are just static templates which are then copied
46 into "live" allocated structures */
47
48 struct pcmcia_function pcmcia_3cxem556_func0 = {
49 0, /* function number */
50 PCMCIA_FUNCTION_NETWORK,
51 0x07, /* last cfe number */
52 0x800, /* ccr_base */
53 0x63, /* ccr_mask */
54 };
55
56 struct pcmcia_config_entry pcmcia_3cxem556_func0_cfe0 = {
57 0x07, /* cfe number */
58 PCMCIA_CFE_IO8 | PCMCIA_CFE_IO16 | PCMCIA_CFE_IRQLEVEL,
59 PCMCIA_IFTYPE_IO,
60 1, /* num_iospace */
61 4, /* iomask */
62 { { 0x0010, 0 } }, /* iospace */
63 0xffff, /* irqmask */
64 0, /* num_memspace */
65 { }, /* memspace */
66 0, /* maxtwins */
67 };
68
69 static struct pcmcia_function pcmcia_3cxem556_func1 = {
70 1, /* function number */
71 PCMCIA_FUNCTION_SERIAL,
72 0x27, /* last cfe number */
73 0x900, /* ccr_base */
74 0x63, /* ccr_mask */
75 };
76
77 static struct pcmcia_config_entry pcmcia_3cxem556_func1_cfe0 = {
78 0x27, /* cfe number */
79 PCMCIA_CFE_IO8 | PCMCIA_CFE_IRQLEVEL,
80 PCMCIA_IFTYPE_IO,
81 1, /* num_iospace */
82 3, /* iomask */
83 { { 0x0008, 0 } }, /* iospace */
84 0xffff, /* irqmask */
85 0, /* num_memspace */
86 { }, /* memspace */
87 0, /* maxtwins */
88 };
89
90 struct pcmcia_function pcmcia_megahertz_xjem1144_func0 = {
91 0, /* function number */
92 PCMCIA_FUNCTION_NETWORK,
93 0x07, /* last cfe number */
94 0x200, /* ccr_base */
95 0x63, /* ccr_mask */
96 };
97
98 struct pcmcia_config_entry pcmcia_megahertz_xjem1144_func0_cfe0 = {
99 0x07, /* cfe number */
100 PCMCIA_CFE_IO8 | PCMCIA_CFE_IO16 | PCMCIA_CFE_IRQLEVEL,
101 PCMCIA_IFTYPE_IO,
102 1, /* num_iospace */
103 4, /* iomask */
104 { { 0x0010, 0 } }, /* iospace */
105 0xffff, /* irqmask */
106 0, /* num_memspace */
107 { }, /* memspace */
108 0, /* maxtwins */
109 };
110
111 static struct pcmcia_function pcmcia_megahertz_xjem1144_func1 = {
112 1, /* function number */
113 PCMCIA_FUNCTION_SERIAL,
114 0x35, /* last cfe number */
115 0x300, /* ccr_base */
116 0x3, /* ccr_mask */
117 };
118
119 static struct pcmcia_config_entry pcmcia_megahertz_xjem1144_func1_cfe0 = {
120 0x35, /* cfe number */
121 PCMCIA_CFE_IO8 | PCMCIA_CFE_IRQLEVEL, PCMCIA_IFTYPE_IO,
122 1, /* num_iospace */
123 0, /* iomask */
124 { { 0x0008, 0x2f8 } }, /* iospace */
125 0xffff, /* irqmask */
126 0, /* num_memspace */
127 { }, /* memspace */
128 0, /* maxtwins */
129 };
130
131 static struct pcmcia_function pcmcia_sierra_a555_func1 = {
132 1, /* function number */
133 PCMCIA_FUNCTION_SERIAL,
134 0x24, /* last cfe number */
135 0x700, /* ccr_base */
136 0x73, /* ccr_mask */
137 };
138
139 static struct pcmcia_config_entry pcmcia_sierra_a555_func1_cfe0 = {
140 0x20, /* cfe number */
141 PCMCIA_CFE_IO8 | PCMCIA_CFE_IRQLEVEL, PCMCIA_IFTYPE_IO,
142 1, /* num_iospace */
143 0, /* iomask */
144 { { 0x0008, 0x3f8 } }, /* iospace */
145 0x3fbc, /* irqmask */
146 0, /* num_memspace */
147 { }, /* memspace */
148 0, /* maxtwins */
149 };
150
151 static struct pcmcia_function pcmcia_sveclancard_func0 = {
152 0, /* function number */
153 PCMCIA_FUNCTION_NETWORK,
154 0x1, /* last cfe number */
155 0x100, /* ccr_base */
156 0x1, /* ccr_mask */
157 };
158
159 static struct pcmcia_config_entry pcmcia_sveclancard_func0_cfe0 = {
160 0x1, /* cfe number */
161 PCMCIA_CFE_MWAIT_REQUIRED | PCMCIA_CFE_RDYBSY_ACTIVE |
162 PCMCIA_CFE_WP_ACTIVE | PCMCIA_CFE_BVD_ACTIVE | PCMCIA_CFE_IO16,
163 PCMCIA_IFTYPE_IO,
164 1, /* num_iospace */
165 5, /* iomask */
166 { { 0x20, 0x300 } }, /* iospace */
167 0xdeb8, /* irqmask */
168 0, /* num_memspace */
169 { }, /* memspace */
170 0, /* maxtwins */
171 };
172
173 static struct pcmcia_cis_quirk pcmcia_cis_quirks[] = {
174 { PCMCIA_VENDOR_3COM, PCMCIA_PRODUCT_3COM_3CXEM556, PCMCIA_CIS_INVALID,
175 &pcmcia_3cxem556_func0, &pcmcia_3cxem556_func0_cfe0 },
176 { PCMCIA_VENDOR_3COM, PCMCIA_PRODUCT_3COM_3CXEM556, PCMCIA_CIS_INVALID,
177 &pcmcia_3cxem556_func1, &pcmcia_3cxem556_func1_cfe0 },
178 { PCMCIA_VENDOR_3COM, PCMCIA_PRODUCT_3COM_3CXEM556B,
179 PCMCIA_CIS_INVALID,
180 &pcmcia_3cxem556_func0, &pcmcia_3cxem556_func0_cfe0 },
181 { PCMCIA_VENDOR_3COM, PCMCIA_PRODUCT_3COM_3CXEM556B,
182 PCMCIA_CIS_INVALID,
183 &pcmcia_3cxem556_func1, &pcmcia_3cxem556_func1_cfe0 },
184 { PCMCIA_VENDOR_MEGAHERTZ2, PCMCIA_PRODUCT_MEGAHERTZ2_XJEM1144,
185 PCMCIA_CIS_INVALID,
186 &pcmcia_megahertz_xjem1144_func0,
187 &pcmcia_megahertz_xjem1144_func0_cfe0 },
188 { PCMCIA_VENDOR_MEGAHERTZ2, PCMCIA_PRODUCT_MEGAHERTZ2_XJEM1144,
189 PCMCIA_CIS_INVALID,
190 &pcmcia_megahertz_xjem1144_func1,
191 &pcmcia_megahertz_xjem1144_func1_cfe0 },
192 { PCMCIA_VENDOR_SIERRA, PCMCIA_PRODUCT_SIERRA_A550,
193 PCMCIA_CIS_INVALID,
194 &pcmcia_sierra_a555_func1, &pcmcia_sierra_a555_func1_cfe0 },
195 { PCMCIA_VENDOR_SIERRA, PCMCIA_PRODUCT_SIERRA_A555,
196 PCMCIA_CIS_INVALID,
197 &pcmcia_sierra_a555_func1, &pcmcia_sierra_a555_func1_cfe0 },
198 { PCMCIA_VENDOR_SIERRA, PCMCIA_PRODUCT_SIERRA_A710,
199 PCMCIA_CIS_INVALID,
200 &pcmcia_sierra_a555_func1, &pcmcia_sierra_a555_func1_cfe0 },
201 { PCMCIA_VENDOR_SIERRA, PCMCIA_PRODUCT_SIERRA_AC710,
202 PCMCIA_CIS_INVALID,
203 &pcmcia_sierra_a555_func1, &pcmcia_sierra_a555_func1_cfe0 },
204 { PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID,
205 PCMCIA_CIS_SVEC_LANCARD,
206 &pcmcia_sveclancard_func0, &pcmcia_sveclancard_func0_cfe0 },
207 };
208
209 void
pcmcia_check_cis_quirks(struct pcmcia_softc * sc)210 pcmcia_check_cis_quirks(struct pcmcia_softc *sc)
211 {
212 int wiped = 0;
213 int i, j;
214 struct pcmcia_function *pf, *pf_next, *pf_last;
215 struct pcmcia_config_entry *cfe, *cfe_next;
216
217 pf = NULL;
218 pf_last = NULL;
219
220
221 for (i = 0; i < nitems(pcmcia_cis_quirks);
222 i++) {
223 if ((sc->card.manufacturer == pcmcia_cis_quirks[i].manufacturer) &&
224 (sc->card.product == pcmcia_cis_quirks[i].product) &&
225 (((sc->card.manufacturer != PCMCIA_VENDOR_INVALID) &&
226 (sc->card.product != PCMCIA_PRODUCT_INVALID)) ||
227 ((sc->card.manufacturer == PCMCIA_VENDOR_INVALID) &&
228 (sc->card.product == PCMCIA_PRODUCT_INVALID) &&
229 sc->card.cis1_info[0] &&
230 (strcmp(sc->card.cis1_info[0],
231 pcmcia_cis_quirks[i].cis1_info[0]) == 0) &&
232 sc->card.cis1_info[1] &&
233 (strcmp(sc->card.cis1_info[1],
234 pcmcia_cis_quirks[i].cis1_info[1]) == 0)))) {
235 if (!wiped) {
236 if (pcmcia_verbose) {
237 printf("%s: using CIS quirks for ", sc->dev.dv_xname);
238 for (j = 0; j < 4; j++) {
239 if (sc->card.cis1_info[j] == NULL)
240 break;
241 if (j)
242 printf(", ");
243 printf("%s", sc->card.cis1_info[j]);
244 }
245 printf("\n");
246 }
247
248 for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL;
249 pf = pf_next) {
250 for (cfe = SIMPLEQ_FIRST(&pf->cfe_head); cfe != NULL;
251 cfe = cfe_next) {
252 cfe_next = SIMPLEQ_NEXT(cfe, cfe_list);
253 free(cfe, M_DEVBUF, 0);
254 }
255 pf_next = SIMPLEQ_NEXT(pf, pf_list);
256 free(pf, M_DEVBUF, 0);
257 }
258
259 SIMPLEQ_INIT(&sc->card.pf_head);
260 wiped = 1;
261 }
262
263 if (pf_last == pcmcia_cis_quirks[i].pf) {
264 cfe = malloc(sizeof(*cfe), M_DEVBUF, M_NOWAIT);
265 if (cfe == NULL)
266 return;
267 *cfe = *pcmcia_cis_quirks[i].cfe;
268
269 SIMPLEQ_INSERT_TAIL(&pf->cfe_head, cfe, cfe_list);
270 } else {
271 pf = malloc(sizeof(*pf), M_DEVBUF, M_NOWAIT);
272 if (pf == NULL)
273 return;
274 *pf = *pcmcia_cis_quirks[i].pf;
275 SIMPLEQ_INIT(&pf->cfe_head);
276
277 cfe = malloc(sizeof(*cfe), M_DEVBUF, M_NOWAIT);
278 if (cfe == NULL) {
279 free(pf, M_DEVBUF, sizeof(*pf));
280 return;
281 }
282 *cfe = *pcmcia_cis_quirks[i].cfe;
283
284 SIMPLEQ_INSERT_TAIL(&pf->cfe_head, cfe, cfe_list);
285 SIMPLEQ_INSERT_TAIL(&sc->card.pf_head, pf, pf_list);
286
287 pf_last = pcmcia_cis_quirks[i].pf;
288 }
289 }
290 }
291 }
292