]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/pccard/pccard_cis_quirks.c
cxgbe(4): Make sure bundled_fw is always initialized before use.
[FreeBSD/FreeBSD.git] / sys / dev / pccard / pccard_cis_quirks.c
1 /*      $NetBSD: pcmcia_cis_quirks.c,v 1.6 2000/04/12 21:07:55 scw Exp $ */
2
3 #include <sys/cdefs.h>
4 __FBSDID("$FreeBSD$");
5
6 #define PCCARDDEBUG
7
8 /*-
9  * SPDX-License-Identifier: BSD-4-Clause
10  *
11  * Copyright (c) 1998 Marc Horowitz.  All rights reserved.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the
20  *    documentation and/or other materials provided with the distribution.
21  * 3. All advertising materials mentioning features or use of this software
22  *    must display the following acknowledgement:
23  *      This product includes software developed by Marc Horowitz.
24  * 4. The name of the author may not be used to endorse or promote products
25  *    derived from this software without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
28  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
29  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
30  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
31  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
32  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
36  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37  */
38
39 #include <sys/param.h>
40 #include <sys/bus.h>
41 #include <sys/malloc.h>
42 #include <sys/systm.h>
43
44 #include <machine/bus.h>
45
46 #include <dev/pccard/pccard_cis.h>
47 #include <dev/pccard/pccardvar.h>
48 #include <dev/pccard/pccardvarp.h>
49
50 #include "pccarddevs.h"
51
52 /* There are cards out there whose CIS flat-out lies.  This file
53    contains struct pccard_function chains for those devices. */
54
55 /* these structures are just static templates which are then copied
56    into "live" allocated structures */
57
58 struct pccard_function pccard_3cxem556_func0 = {
59         0,                      /* function number */
60         PCCARD_FUNCTION_NETWORK,
61         0x07,                   /* last cfe number */
62         0x800,                  /* ccr_base */
63         0x63,                   /* ccr_mask */
64 };
65
66 struct pccard_config_entry pccard_3cxem556_func0_cfe0 = {
67         0x07,                   /* cfe number */
68         PCCARD_CFE_IO8 | PCCARD_CFE_IO16 | PCCARD_CFE_IRQLEVEL,
69         PCCARD_IFTYPE_IO,
70         1,                      /* num_iospace */
71         4,                      /* iomask */
72         { { 0x0010, 0 } },      /* iospace */
73         0xffff,                 /* irqmask */
74         0,                      /* num_memspace */
75         { },                    /* memspace */
76         0,                      /* maxtwins */
77 };
78
79 static struct pccard_function pccard_3cxem556_func1 = {
80         1,                      /* function number */
81         PCCARD_FUNCTION_SERIAL,
82         0x27,                   /* last cfe number */
83         0x900,                  /* ccr_base */
84         0x63,                   /* ccr_mask */
85 };
86
87 static struct pccard_config_entry pccard_3cxem556_func1_cfe0 = {
88         0x27,                   /* cfe number */
89         PCCARD_CFE_IO8 | PCCARD_CFE_IRQLEVEL,
90         PCCARD_IFTYPE_IO,
91         1,                      /* num_iospace */
92         3,                      /* iomask */
93         { { 0x0008, 0 } },      /* iospace */
94         0xffff,                 /* irqmask */
95         0,                      /* num_memspace */
96         { },                    /* memspace */
97         0,                      /* maxtwins */
98 };
99
100 static struct pccard_function pccard_3ccfem556bi_func0 = {
101         0,                      /* function number */
102         PCCARD_FUNCTION_NETWORK,
103         0x07,                   /* last cfe number */
104         0x1000,                 /* ccr_base */
105         0x267,                  /* ccr_mask */
106 };
107
108 static struct pccard_config_entry pccard_3ccfem556bi_func0_cfe0 = {
109         0x07,                   /* cfe number */
110         PCCARD_CFE_IO8 | PCCARD_CFE_IO16 | PCCARD_CFE_IRQLEVEL,
111         PCCARD_IFTYPE_IO,
112         1,                      /* num_iospace */
113         5,                      /* iomask */
114         { { 0x0020, 0 } },      /* iospace */
115         0xffff,                 /* irqmask */
116         0,                      /* num_memspace */
117         { },                    /* memspace */
118         0,                      /* maxtwins */
119 };
120
121 static struct pccard_function pccard_3ccfem556bi_func1 = {
122         1,                      /* function number */
123         PCCARD_FUNCTION_SERIAL,
124         0x27,                   /* last cfe number */
125         0x1100,                 /* ccr_base */
126         0x277,                  /* ccr_mask */
127 };
128
129 static struct pccard_config_entry pccard_3ccfem556bi_func1_cfe0 = {
130         0x27,                   /* cfe number */
131         PCCARD_CFE_IO8 | PCCARD_CFE_IRQLEVEL,
132         PCCARD_IFTYPE_IO,
133         1,                      /* num_iospace */
134         3,                      /* iomask */
135         { { 0x0008, 0 } },      /* iospace */
136         0xffff,                 /* irqmask */
137         0,                      /* num_memspace */
138         { },                    /* memspace */
139         0,                      /* maxtwins */
140 };
141
142 static struct pccard_function pccard_3c1_func0 = {
143         0,                      /* function number */
144         PCCARD_FUNCTION_NETWORK,
145         0x05,                   /* last cfe number */
146         0x400,                  /* ccr_base */
147         0x267,                  /* ccr_mask */
148 };
149
150 static struct pccard_config_entry pccard_3c1_func0_cfe0 = {
151         0x05,                   /* cfe number */
152         PCCARD_CFE_IO8 | PCCARD_CFE_IO16 | PCCARD_CFE_IRQLEVEL,
153         PCCARD_IFTYPE_IO,
154         1,                      /* num_iospace */
155         5,                      /* iomask */
156         { { 0x0010, 0 } },      /* iospace */
157         0xffff,                 /* irqmask */
158         0,                      /* num_memspace */
159         { },                    /* memspace */
160         0,                      /* maxtwins */
161 };
162
163 static struct pccard_function pccard_sveclancard_func0 = {
164         0,                      /* function number */
165         PCCARD_FUNCTION_NETWORK,
166         0x1,                    /* last cfe number */
167         0x100,                  /* ccr_base */
168         0x1,                    /* ccr_mask */
169 };
170
171 static struct pccard_config_entry pccard_sveclancard_func0_cfe0 = {
172         0x1,                    /* cfe number */
173         PCCARD_CFE_MWAIT_REQUIRED | PCCARD_CFE_RDYBSY_ACTIVE |
174         PCCARD_CFE_WP_ACTIVE | PCCARD_CFE_BVD_ACTIVE | PCCARD_CFE_IO16,
175         PCCARD_IFTYPE_IO,
176         1,                      /* num_iospace */
177         5,                      /* iomask */
178         { { 0x20, 0x300 } },    /* iospace */
179         0xdeb8,                 /* irqmask */
180         0,                      /* num_memspace */
181         { },                    /* memspace */
182         0,                      /* maxtwins */
183 };
184
185 static struct pccard_function pccard_ndc_nd5100_func0 = {
186         0,                      /* function number */
187         PCCARD_FUNCTION_NETWORK,
188         0x23,                   /* last cfe number */
189         0x3f8,                  /* ccr_base */
190         0x3,                    /* ccr_mask */
191 };
192
193 static struct pccard_config_entry pccard_ndc_nd5100_func0_cfe0 = {
194         0x20,                   /* cfe number */
195         PCCARD_CFE_MWAIT_REQUIRED | PCCARD_CFE_IO16 | PCCARD_CFE_IRQLEVEL,
196         PCCARD_IFTYPE_IO,
197         1,                      /* num_iospace */
198         5,                      /* iomask */
199         { { 0x20, 0x300 } },    /* iospace */
200         0xdeb8,                 /* irqmask */
201         0,                      /* num_memspace */
202         { },                    /* memspace */
203         0,                      /* maxtwins */
204 };
205
206 static struct pccard_function pccard_sierra_a555_func1 = {
207         1,                      /* function number */
208         PCCARD_FUNCTION_SERIAL,
209         0x24,                   /* last cfe number */
210         0x700,                  /* ccr_base */
211         0x73,                   /* ccr_mask */
212 };
213
214 static struct pccard_config_entry pccard_sierra_a555_func1_cfe0 = {
215         0x22,                   /* cfe number */
216         PCCARD_CFE_IO8 | PCCARD_CFE_IRQLEVEL, 
217         PCCARD_IFTYPE_IO,
218         1,                      /* num_iospace */
219         0,                      /* iomask */
220         { { 0x0008, 0x3e8 } },  /* iospace */
221         0x3fbc,                 /* irqmask */
222         0,                      /* num_memspace */
223         { },                    /* memspace */
224         0,                      /* maxtwins */
225 };
226
227 static struct pccard_cis_quirk pccard_cis_quirks[] = {
228         { PCMCIA_VENDOR_3COM, PCMCIA_PRODUCT_3COM_3CXEM556, PCMCIA_CIS_INVALID, 
229           &pccard_3cxem556_func0, &pccard_3cxem556_func0_cfe0 },
230         { PCMCIA_VENDOR_3COM, PCMCIA_PRODUCT_3COM_3CXEM556, PCMCIA_CIS_INVALID,
231           &pccard_3cxem556_func1, &pccard_3cxem556_func1_cfe0 },
232         { PCMCIA_VENDOR_3COM, PCMCIA_PRODUCT_3COM_3CXEM556INT, PCMCIA_CIS_INVALID, 
233           &pccard_3cxem556_func0, &pccard_3cxem556_func0_cfe0 },
234         { PCMCIA_VENDOR_3COM, PCMCIA_PRODUCT_3COM_3CXEM556INT, PCMCIA_CIS_INVALID,
235           &pccard_3cxem556_func1, &pccard_3cxem556_func1_cfe0 },
236         { PCMCIA_VENDOR_3COM, PCMCIA_PRODUCT_3COM_3CCFEM556BI,
237           PCMCIA_CIS_INVALID,
238           &pccard_3ccfem556bi_func0, &pccard_3ccfem556bi_func0_cfe0 },
239         { PCMCIA_VENDOR_3COM, PCMCIA_PRODUCT_3COM_3CCFEM556BI,
240           PCMCIA_CIS_INVALID,
241           &pccard_3ccfem556bi_func1, &pccard_3ccfem556bi_func1_cfe0 },
242         { PCMCIA_VENDOR_SIERRA, PCMCIA_PRODUCT_SIERRA_A550,
243           PCMCIA_CIS_INVALID,
244           &pccard_sierra_a555_func1, &pccard_sierra_a555_func1_cfe0 },
245         { PCMCIA_VENDOR_SIERRA, PCMCIA_PRODUCT_SIERRA_A555,
246           PCMCIA_CIS_INVALID,
247           &pccard_sierra_a555_func1, &pccard_sierra_a555_func1_cfe0 },
248         { PCMCIA_VENDOR_SIERRA, PCMCIA_PRODUCT_SIERRA_A710,
249           PCMCIA_CIS_INVALID,
250           &pccard_sierra_a555_func1, &pccard_sierra_a555_func1_cfe0 },
251         { PCMCIA_VENDOR_SIERRA, PCMCIA_PRODUCT_SIERRA_AC710,
252           PCMCIA_CIS_INVALID,
253           &pccard_sierra_a555_func1, &pccard_sierra_a555_func1_cfe0 },
254         { PCMCIA_VENDOR_3COM, PCMCIA_PRODUCT_3COM_3C1, PCMCIA_CIS_INVALID,
255           &pccard_3c1_func0, &pccard_3c1_func0_cfe0 },
256         { PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID, PCMCIA_CIS_SVEC_LANCARD,
257           &pccard_sveclancard_func0, &pccard_sveclancard_func0_cfe0 },
258         { PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID, PCMCIA_CIS_NDC_ND5100_E,
259           &pccard_ndc_nd5100_func0, &pccard_ndc_nd5100_func0_cfe0 },
260 };
261         
262 static int
263 pccard_cis_quirk_match(struct pccard_softc *sc, struct pccard_cis_quirk *q)
264 {
265         if ((sc->card.manufacturer == q->manufacturer) &&
266                 (sc->card.product == q->product) &&
267                 (((sc->card.manufacturer != PCMCIA_VENDOR_INVALID) &&
268                   (sc->card.product != PCMCIA_PRODUCT_INVALID)) ||
269                  ((sc->card.manufacturer == PCMCIA_VENDOR_INVALID) &&
270                   (sc->card.product == PCMCIA_PRODUCT_INVALID) &&
271                   sc->card.cis1_info[0] &&
272                   (strcmp(sc->card.cis1_info[0], q->cis1_info[0]) == 0) &&
273                   sc->card.cis1_info[1] &&
274                   (strcmp(sc->card.cis1_info[1], q->cis1_info[1]) == 0))))
275                 return (1);
276         return (0);
277 }
278
279 void pccard_check_cis_quirks(device_t dev)
280 {
281         struct pccard_softc *sc = PCCARD_SOFTC(dev);
282         int wiped = 0;
283         int i, j;
284         struct pccard_function *pf, *pf_next, *pf_last;
285         struct pccard_config_entry *cfe, *cfe_next;
286         struct pccard_cis_quirk *q;
287
288         pf = NULL;
289         pf_last = NULL;
290
291         for (i = 0; i < nitems(pccard_cis_quirks); i++) {
292                 q = &pccard_cis_quirks[i];
293                 if (!pccard_cis_quirk_match(sc, q))
294                         continue;
295                 if (!wiped) {
296                         if (bootverbose) {
297                                 device_printf(dev, "using CIS quirks for ");
298                                 for (j = 0; j < 4; j++) {
299                                         if (sc->card.cis1_info[j] == NULL)
300                                                 break;
301                                         if (j)
302                                                 printf(", ");
303                                         printf("%s", sc->card.cis1_info[j]);
304                                 }
305                                 printf("\n");
306                         }
307
308                         for (pf = STAILQ_FIRST(&sc->card.pf_head); pf != NULL;
309                              pf = pf_next) {
310                                 for (cfe = STAILQ_FIRST(&pf->cfe_head); cfe != NULL;
311                                      cfe = cfe_next) {
312                                         cfe_next = STAILQ_NEXT(cfe, cfe_list);
313                                         free(cfe, M_DEVBUF);
314                                 }
315                                 pf_next = STAILQ_NEXT(pf, pf_list);
316                                 free(pf, M_DEVBUF);
317                         }
318
319                         STAILQ_INIT(&sc->card.pf_head);
320                         wiped = 1;
321                 }
322
323                 if (pf_last == q->pf) {
324                         cfe = malloc(sizeof(*cfe), M_DEVBUF, M_NOWAIT);
325                         if (cfe == NULL) {
326                                 device_printf(dev, "no memory for quirk (1)\n");
327                                 continue;
328                         }
329                         *cfe = *q->cfe;
330                         STAILQ_INSERT_TAIL(&pf->cfe_head, cfe, cfe_list);
331                 } else {
332                         pf = malloc(sizeof(*pf), M_DEVBUF, M_NOWAIT);
333                         if (pf == NULL) {
334                                 device_printf(dev,
335                                         "no memory for pccard function\n");
336                                 continue;
337                         }
338                         *pf = *q->pf;
339                         STAILQ_INIT(&pf->cfe_head);
340                         cfe = malloc(sizeof(*cfe), M_DEVBUF, M_NOWAIT);
341                         if (cfe == NULL) {
342                                 free(pf, M_DEVBUF);
343                                 device_printf(dev, "no memory for quirk (2)\n");
344                                 continue;
345                         }
346                         *cfe = *q->cfe;
347                         STAILQ_INSERT_TAIL(&pf->cfe_head, cfe, cfe_list);
348                         STAILQ_INSERT_TAIL(&sc->card.pf_head, pf, pf_list);
349                         pf_last = q->pf;
350                 }
351         }
352 }