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 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