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