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