Initial import from FreeBSD RELENG_4:
[games.git] / sys / dev / misc / pccard / pccard_cis_quirks.c
1 /*      $NetBSD: pcmcia_cis_quirks.c,v 1.5 1999/10/11 17:50:21 thorpej Exp $    */
2 /* $FreeBSD: src/sys/dev/pccard/pccard_cis_quirks.c,v 1.2.2.1 2000/05/23 03:57:00 imp Exp $ */
3
4 #define PCCARDDEBUG
5
6 /*
7  * Copyright (c) 1998 Marc Horowitz.  All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *      This product includes software developed by Marc Horowitz.
20  * 4. The name of the author may not be used to endorse or promote products
21  *    derived from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/malloc.h>
38 #include <sys/module.h>
39 #include <sys/kernel.h>
40 #include <sys/queue.h>
41 #include <sys/types.h>
42
43 #include <sys/bus.h>
44 #include <machine/bus.h>
45 #include <sys/rman.h>
46 #include <machine/resource.h>
47
48 #include <dev/pccard/pccarddevs.h>
49 #include <dev/pccard/pccardreg.h>
50 #include <dev/pccard/pccardvar.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_sveclancard_func0 = {
143         0,                      /* function number */
144         PCCARD_FUNCTION_NETWORK,
145         0x1,                    /* last cfe number */
146         0x100,                  /* ccr_base */
147         0x1,                    /* ccr_mask */
148 };
149
150 static struct pccard_config_entry pccard_sveclancard_func0_cfe0 = {
151         0x1,                    /* cfe number */
152         PCCARD_CFE_MWAIT_REQUIRED | PCCARD_CFE_RDYBSY_ACTIVE |
153         PCCARD_CFE_WP_ACTIVE | PCCARD_CFE_BVD_ACTIVE | PCCARD_CFE_IO16,
154         PCCARD_IFTYPE_IO,
155         1,                      /* num_iospace */
156         5,                      /* iomask */
157         { { 0x20, 0x300 } },    /* iospace */
158         0xdeb8,                 /* irqmask */
159         0,                      /* num_memspace */
160         { },                    /* memspace */
161         0,                      /* maxtwins */
162 };
163
164 static struct pccard_cis_quirk pccard_cis_quirks[] = {
165         { PCCARD_VENDOR_3COM, PCCARD_PRODUCT_3COM_3CXEM556, PCCARD_CIS_INVALID, 
166           &pccard_3cxem556_func0, &pccard_3cxem556_func0_cfe0 },
167         { PCCARD_VENDOR_3COM, PCCARD_PRODUCT_3COM_3CXEM556, PCCARD_CIS_INVALID,
168           &pccard_3cxem556_func1, &pccard_3cxem556_func1_cfe0 },
169         { PCCARD_VENDOR_3COM, PCCARD_PRODUCT_3COM_3CXEM556INT, PCCARD_CIS_INVALID, 
170           &pccard_3cxem556_func0, &pccard_3cxem556_func0_cfe0 },
171         { PCCARD_VENDOR_3COM, PCCARD_PRODUCT_3COM_3CXEM556INT, PCCARD_CIS_INVALID,
172           &pccard_3cxem556_func1, &pccard_3cxem556_func1_cfe0 },
173         { PCCARD_VENDOR_3COM, PCCARD_PRODUCT_3COM_3CCFEM556BI,
174           PCCARD_CIS_INVALID,
175           &pccard_3ccfem556bi_func0, &pccard_3ccfem556bi_func0_cfe0 },
176         { PCCARD_VENDOR_3COM, PCCARD_PRODUCT_3COM_3CCFEM556BI,
177           PCCARD_CIS_INVALID,
178           &pccard_3ccfem556bi_func1, &pccard_3ccfem556bi_func1_cfe0 },
179         { PCCARD_VENDOR_INVALID, PCCARD_PRODUCT_INVALID, PCCARD_CIS_SVEC_LANCARD,
180           &pccard_sveclancard_func0, &pccard_sveclancard_func0_cfe0 },
181 };
182         
183 static int n_pccard_cis_quirks =
184         sizeof(pccard_cis_quirks)/sizeof(pccard_cis_quirks[0]);
185
186 void pccard_check_cis_quirks(device_t dev)
187 {
188         struct pccard_softc *sc = (struct pccard_softc *)
189             device_get_softc(dev);
190         int wiped = 0;
191         int i, j;
192         struct pccard_function *pf, *pf_next, *pf_last;
193         struct pccard_config_entry *cfe, *cfe_next;
194
195         pf = NULL;
196         pf_last = NULL;
197
198         for (i=0; i<n_pccard_cis_quirks; i++) {
199                 if ((sc->card.manufacturer == pccard_cis_quirks[i].manufacturer) &&
200                         (sc->card.product == pccard_cis_quirks[i].product) &&
201                         (((sc->card.manufacturer != PCCARD_VENDOR_INVALID) &&
202                           (sc->card.product != PCCARD_PRODUCT_INVALID)) ||
203                          ((sc->card.manufacturer == PCCARD_VENDOR_INVALID) &&
204                           (sc->card.product == PCCARD_PRODUCT_INVALID) &&
205                           sc->card.cis1_info[0] &&
206                           (strcmp(sc->card.cis1_info[0],
207                                           pccard_cis_quirks[i].cis1_info[0]) == 0) &&
208                           sc->card.cis1_info[1] &&
209                           (strcmp(sc->card.cis1_info[1],
210                                           pccard_cis_quirks[i].cis1_info[1]) == 0)))) {
211                         if (!wiped) {
212                                 if (pccard_verbose) {
213                                         device_printf(dev, "using CIS quirks for ");
214                                         for (j = 0; j < 4; j++) {
215                                                 if (sc->card.cis1_info[j] == NULL)
216                                                         break;
217                                                 if (j)
218                                                         printf(", ");
219                                                 printf("%s", sc->card.cis1_info[j]);
220                                         }
221                                         printf("\n");
222                                 }
223
224                                 for (pf = STAILQ_FIRST(&sc->card.pf_head); pf != NULL;
225                                      pf = pf_next) {
226                                         for (cfe = STAILQ_FIRST(&pf->cfe_head); cfe != NULL;
227                                              cfe = cfe_next) {
228                                                 cfe_next = STAILQ_NEXT(cfe, cfe_list);
229                                                 free(cfe, M_DEVBUF);
230                                         }
231                                         pf_next = STAILQ_NEXT(pf, pf_list);
232                                         free(pf, M_DEVBUF);
233                                 }
234
235                                 STAILQ_INIT(&sc->card.pf_head);
236                                 wiped = 1;
237                         }
238
239                         if (pf_last == pccard_cis_quirks[i].pf) {
240                                 cfe = malloc(sizeof(*cfe), M_DEVBUF, M_NOWAIT);
241                                 *cfe = *pccard_cis_quirks[i].cfe;
242
243                                 STAILQ_INSERT_TAIL(&pf->cfe_head, cfe, cfe_list);
244                         } else {
245                                 pf = malloc(sizeof(*pf), M_DEVBUF, M_NOWAIT);
246                                 *pf = *pccard_cis_quirks[i].pf;
247                                 STAILQ_INIT(&pf->cfe_head);
248
249                                 cfe = malloc(sizeof(*cfe), M_DEVBUF, M_NOWAIT);
250                                 *cfe = *pccard_cis_quirks[i].cfe;
251
252                                 STAILQ_INSERT_TAIL(&pf->cfe_head, cfe, cfe_list);
253                                 STAILQ_INSERT_TAIL(&sc->card.pf_head, pf, pf_list);
254
255                                 pf_last = pccard_cis_quirks[i].pf;
256                         }
257                 }
258         }
259 }