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