xref: /dflybsd-src/sys/bus/pccard/pccard_cis_quirks.c (revision dcb4b80df71308df08858318df7f148fde3b3e1b)
1666d2603SJoerg Sonnenberger /*	$NetBSD: pcmcia_cis_quirks.c,v 1.6 2000/04/12 21:07:55 scw Exp $ */
23aef8050SSepherosa Ziehau /*	$FreeBSD: src/sys/dev/pccard/pccard_cis_quirks.c,v 1.15 2005/03/26 21:30:49 sam Exp $ */
3666d2603SJoerg Sonnenberger 
4666d2603SJoerg Sonnenberger #define	PCCARDDEBUG
5666d2603SJoerg Sonnenberger 
63aef8050SSepherosa Ziehau /*-
7666d2603SJoerg Sonnenberger  * Copyright (c) 1998 Marc Horowitz.  All rights reserved.
8666d2603SJoerg Sonnenberger  *
9666d2603SJoerg Sonnenberger  * Redistribution and use in source and binary forms, with or without
10666d2603SJoerg Sonnenberger  * modification, are permitted provided that the following conditions
11666d2603SJoerg Sonnenberger  * are met:
12666d2603SJoerg Sonnenberger  * 1. Redistributions of source code must retain the above copyright
13666d2603SJoerg Sonnenberger  *    notice, this list of conditions and the following disclaimer.
14666d2603SJoerg Sonnenberger  * 2. Redistributions in binary form must reproduce the above copyright
15666d2603SJoerg Sonnenberger  *    notice, this list of conditions and the following disclaimer in the
16666d2603SJoerg Sonnenberger  *    documentation and/or other materials provided with the distribution.
17666d2603SJoerg Sonnenberger  * 3. All advertising materials mentioning features or use of this software
18666d2603SJoerg Sonnenberger  *    must display the following acknowledgement:
19666d2603SJoerg Sonnenberger  *	This product includes software developed by Marc Horowitz.
20666d2603SJoerg Sonnenberger  * 4. The name of the author may not be used to endorse or promote products
21666d2603SJoerg Sonnenberger  *    derived from this software without specific prior written permission.
22666d2603SJoerg Sonnenberger  *
23666d2603SJoerg Sonnenberger  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24666d2603SJoerg Sonnenberger  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25666d2603SJoerg Sonnenberger  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26666d2603SJoerg Sonnenberger  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27666d2603SJoerg Sonnenberger  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28666d2603SJoerg Sonnenberger  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29666d2603SJoerg Sonnenberger  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30666d2603SJoerg Sonnenberger  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31666d2603SJoerg Sonnenberger  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32666d2603SJoerg Sonnenberger  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33666d2603SJoerg Sonnenberger  */
34666d2603SJoerg Sonnenberger 
35666d2603SJoerg Sonnenberger #include <sys/param.h>
36666d2603SJoerg Sonnenberger #include <sys/bus.h>
373aef8050SSepherosa Ziehau #include <sys/malloc.h>
383aef8050SSepherosa Ziehau #include <sys/systm.h>
39666d2603SJoerg Sonnenberger 
403aef8050SSepherosa Ziehau #include <bus/pccard/pccard_cis.h>
41666d2603SJoerg Sonnenberger #include <bus/pccard/pccardvar.h>
42*dcb4b80dSSascha Wildner 
43*dcb4b80dSSascha Wildner #include "pccarddevs.h"
44666d2603SJoerg Sonnenberger 
45666d2603SJoerg Sonnenberger /* There are cards out there whose CIS flat-out lies.  This file
46666d2603SJoerg Sonnenberger    contains struct pccard_function chains for those devices. */
47666d2603SJoerg Sonnenberger 
48666d2603SJoerg Sonnenberger /* these structures are just static templates which are then copied
49666d2603SJoerg Sonnenberger    into "live" allocated structures */
50666d2603SJoerg Sonnenberger 
51666d2603SJoerg Sonnenberger struct pccard_function pccard_3cxem556_func0 = {
52666d2603SJoerg Sonnenberger 	0,			/* function number */
53666d2603SJoerg Sonnenberger 	PCCARD_FUNCTION_NETWORK,
54666d2603SJoerg Sonnenberger 	0x07,			/* last cfe number */
55666d2603SJoerg Sonnenberger 	0x800,			/* ccr_base */
56666d2603SJoerg Sonnenberger 	0x63,			/* ccr_mask */
57666d2603SJoerg Sonnenberger };
58666d2603SJoerg Sonnenberger 
59666d2603SJoerg Sonnenberger struct pccard_config_entry pccard_3cxem556_func0_cfe0 = {
60666d2603SJoerg Sonnenberger 	0x07,			/* cfe number */
61666d2603SJoerg Sonnenberger 	PCCARD_CFE_IO8 | PCCARD_CFE_IO16 | PCCARD_CFE_IRQLEVEL,
62666d2603SJoerg Sonnenberger 	PCCARD_IFTYPE_IO,
63666d2603SJoerg Sonnenberger 	1,			/* num_iospace */
64666d2603SJoerg Sonnenberger 	4,			/* iomask */
65666d2603SJoerg Sonnenberger 	{ { 0x0010, 0 } },	/* iospace */
66666d2603SJoerg Sonnenberger 	0xffff,			/* irqmask */
67666d2603SJoerg Sonnenberger 	0,			/* num_memspace */
68666d2603SJoerg Sonnenberger 	{ },			/* memspace */
69666d2603SJoerg Sonnenberger 	0,			/* maxtwins */
70666d2603SJoerg Sonnenberger };
71666d2603SJoerg Sonnenberger 
72666d2603SJoerg Sonnenberger static struct pccard_function pccard_3cxem556_func1 = {
73666d2603SJoerg Sonnenberger 	1,			/* function number */
74666d2603SJoerg Sonnenberger 	PCCARD_FUNCTION_SERIAL,
75666d2603SJoerg Sonnenberger 	0x27,			/* last cfe number */
76666d2603SJoerg Sonnenberger 	0x900,			/* ccr_base */
77666d2603SJoerg Sonnenberger 	0x63,			/* ccr_mask */
78666d2603SJoerg Sonnenberger };
79666d2603SJoerg Sonnenberger 
80666d2603SJoerg Sonnenberger static struct pccard_config_entry pccard_3cxem556_func1_cfe0 = {
81666d2603SJoerg Sonnenberger 	0x27,			/* cfe number */
82666d2603SJoerg Sonnenberger 	PCCARD_CFE_IO8 | PCCARD_CFE_IRQLEVEL,
83666d2603SJoerg Sonnenberger 	PCCARD_IFTYPE_IO,
84666d2603SJoerg Sonnenberger 	1,			/* num_iospace */
85666d2603SJoerg Sonnenberger 	3,			/* iomask */
86666d2603SJoerg Sonnenberger 	{ { 0x0008, 0 } },	/* iospace */
87666d2603SJoerg Sonnenberger 	0xffff,			/* irqmask */
88666d2603SJoerg Sonnenberger 	0,			/* num_memspace */
89666d2603SJoerg Sonnenberger 	{ },			/* memspace */
90666d2603SJoerg Sonnenberger 	0,			/* maxtwins */
91666d2603SJoerg Sonnenberger };
92666d2603SJoerg Sonnenberger 
93666d2603SJoerg Sonnenberger static struct pccard_function pccard_3ccfem556bi_func0 = {
94666d2603SJoerg Sonnenberger 	0,			/* function number */
95666d2603SJoerg Sonnenberger 	PCCARD_FUNCTION_NETWORK,
96666d2603SJoerg Sonnenberger 	0x07,			/* last cfe number */
97666d2603SJoerg Sonnenberger 	0x1000,			/* ccr_base */
98666d2603SJoerg Sonnenberger 	0x267,			/* ccr_mask */
99666d2603SJoerg Sonnenberger };
100666d2603SJoerg Sonnenberger 
101666d2603SJoerg Sonnenberger static struct pccard_config_entry pccard_3ccfem556bi_func0_cfe0 = {
102666d2603SJoerg Sonnenberger 	0x07,			/* cfe number */
103666d2603SJoerg Sonnenberger 	PCCARD_CFE_IO8 | PCCARD_CFE_IO16 | PCCARD_CFE_IRQLEVEL,
104666d2603SJoerg Sonnenberger 	PCCARD_IFTYPE_IO,
105666d2603SJoerg Sonnenberger 	1,			/* num_iospace */
106666d2603SJoerg Sonnenberger 	5,			/* iomask */
107666d2603SJoerg Sonnenberger 	{ { 0x0020, 0 } },	/* iospace */
108666d2603SJoerg Sonnenberger 	0xffff,			/* irqmask */
109666d2603SJoerg Sonnenberger 	0,			/* num_memspace */
110666d2603SJoerg Sonnenberger 	{ },			/* memspace */
111666d2603SJoerg Sonnenberger 	0,			/* maxtwins */
112666d2603SJoerg Sonnenberger };
113666d2603SJoerg Sonnenberger 
114666d2603SJoerg Sonnenberger static struct pccard_function pccard_3ccfem556bi_func1 = {
115666d2603SJoerg Sonnenberger 	1,			/* function number */
116666d2603SJoerg Sonnenberger 	PCCARD_FUNCTION_SERIAL,
117666d2603SJoerg Sonnenberger 	0x27,			/* last cfe number */
118666d2603SJoerg Sonnenberger 	0x1100,			/* ccr_base */
119666d2603SJoerg Sonnenberger 	0x277,			/* ccr_mask */
120666d2603SJoerg Sonnenberger };
121666d2603SJoerg Sonnenberger 
122666d2603SJoerg Sonnenberger static struct pccard_config_entry pccard_3ccfem556bi_func1_cfe0 = {
123666d2603SJoerg Sonnenberger 	0x27,			/* cfe number */
124666d2603SJoerg Sonnenberger 	PCCARD_CFE_IO8 | PCCARD_CFE_IRQLEVEL,
125666d2603SJoerg Sonnenberger 	PCCARD_IFTYPE_IO,
126666d2603SJoerg Sonnenberger 	1,			/* num_iospace */
127666d2603SJoerg Sonnenberger 	3,			/* iomask */
128666d2603SJoerg Sonnenberger 	{ { 0x0008, 0 } },	/* iospace */
129666d2603SJoerg Sonnenberger 	0xffff,			/* irqmask */
130666d2603SJoerg Sonnenberger 	0,			/* num_memspace */
131666d2603SJoerg Sonnenberger 	{ },			/* memspace */
132666d2603SJoerg Sonnenberger 	0,			/* maxtwins */
133666d2603SJoerg Sonnenberger };
134666d2603SJoerg Sonnenberger 
135666d2603SJoerg Sonnenberger static struct pccard_function pccard_sveclancard_func0 = {
136666d2603SJoerg Sonnenberger 	0,			/* function number */
137666d2603SJoerg Sonnenberger 	PCCARD_FUNCTION_NETWORK,
138666d2603SJoerg Sonnenberger 	0x1,			/* last cfe number */
139666d2603SJoerg Sonnenberger 	0x100,			/* ccr_base */
140666d2603SJoerg Sonnenberger 	0x1,			/* ccr_mask */
141666d2603SJoerg Sonnenberger };
142666d2603SJoerg Sonnenberger 
143666d2603SJoerg Sonnenberger static struct pccard_config_entry pccard_sveclancard_func0_cfe0 = {
144666d2603SJoerg Sonnenberger 	0x1,			/* cfe number */
145666d2603SJoerg Sonnenberger 	PCCARD_CFE_MWAIT_REQUIRED | PCCARD_CFE_RDYBSY_ACTIVE |
146666d2603SJoerg Sonnenberger 	PCCARD_CFE_WP_ACTIVE | PCCARD_CFE_BVD_ACTIVE | PCCARD_CFE_IO16,
147666d2603SJoerg Sonnenberger 	PCCARD_IFTYPE_IO,
148666d2603SJoerg Sonnenberger 	1,			/* num_iospace */
149666d2603SJoerg Sonnenberger 	5,			/* iomask */
150666d2603SJoerg Sonnenberger 	{ { 0x20, 0x300 } },	/* iospace */
151666d2603SJoerg Sonnenberger 	0xdeb8,			/* irqmask */
152666d2603SJoerg Sonnenberger 	0,			/* num_memspace */
153666d2603SJoerg Sonnenberger 	{ },			/* memspace */
154666d2603SJoerg Sonnenberger 	0,			/* maxtwins */
155666d2603SJoerg Sonnenberger };
156666d2603SJoerg Sonnenberger 
157666d2603SJoerg Sonnenberger static struct pccard_function pccard_ndc_nd5100_func0 = {
158666d2603SJoerg Sonnenberger 	0,			/* function number */
159666d2603SJoerg Sonnenberger 	PCCARD_FUNCTION_NETWORK,
160666d2603SJoerg Sonnenberger 	0x23,			/* last cfe number */
161666d2603SJoerg Sonnenberger 	0x3f8,			/* ccr_base */
162666d2603SJoerg Sonnenberger 	0x3,			/* ccr_mask */
163666d2603SJoerg Sonnenberger };
164666d2603SJoerg Sonnenberger 
165666d2603SJoerg Sonnenberger static struct pccard_config_entry pccard_ndc_nd5100_func0_cfe0 = {
166666d2603SJoerg Sonnenberger 	0x20,			/* cfe number */
167666d2603SJoerg Sonnenberger 	PCCARD_CFE_MWAIT_REQUIRED | PCCARD_CFE_IO16 | PCCARD_CFE_IRQLEVEL,
168666d2603SJoerg Sonnenberger 	PCCARD_IFTYPE_IO,
169666d2603SJoerg Sonnenberger 	1,			/* num_iospace */
170666d2603SJoerg Sonnenberger 	5,			/* iomask */
171666d2603SJoerg Sonnenberger 	{ { 0x20, 0x300 } },	/* iospace */
172666d2603SJoerg Sonnenberger 	0xdeb8,			/* irqmask */
173666d2603SJoerg Sonnenberger 	0,			/* num_memspace */
174666d2603SJoerg Sonnenberger 	{ },			/* memspace */
175666d2603SJoerg Sonnenberger 	0,			/* maxtwins */
176666d2603SJoerg Sonnenberger };
177666d2603SJoerg Sonnenberger 
178666d2603SJoerg Sonnenberger static struct pccard_cis_quirk pccard_cis_quirks[] = {
179666d2603SJoerg Sonnenberger 	{ PCMCIA_VENDOR_3COM, PCMCIA_PRODUCT_3COM_3CXEM556, PCMCIA_CIS_INVALID,
180666d2603SJoerg Sonnenberger 	  &pccard_3cxem556_func0, &pccard_3cxem556_func0_cfe0 },
181666d2603SJoerg Sonnenberger 	{ PCMCIA_VENDOR_3COM, PCMCIA_PRODUCT_3COM_3CXEM556, PCMCIA_CIS_INVALID,
182666d2603SJoerg Sonnenberger 	  &pccard_3cxem556_func1, &pccard_3cxem556_func1_cfe0 },
183666d2603SJoerg Sonnenberger 	{ PCMCIA_VENDOR_3COM, PCMCIA_PRODUCT_3COM_3CXEM556INT, PCMCIA_CIS_INVALID,
184666d2603SJoerg Sonnenberger 	  &pccard_3cxem556_func0, &pccard_3cxem556_func0_cfe0 },
185666d2603SJoerg Sonnenberger 	{ PCMCIA_VENDOR_3COM, PCMCIA_PRODUCT_3COM_3CXEM556INT, PCMCIA_CIS_INVALID,
186666d2603SJoerg Sonnenberger 	  &pccard_3cxem556_func1, &pccard_3cxem556_func1_cfe0 },
187666d2603SJoerg Sonnenberger 	{ PCMCIA_VENDOR_3COM, PCMCIA_PRODUCT_3COM_3CCFEM556BI,
188666d2603SJoerg Sonnenberger 	  PCMCIA_CIS_INVALID,
189666d2603SJoerg Sonnenberger 	  &pccard_3ccfem556bi_func0, &pccard_3ccfem556bi_func0_cfe0 },
190666d2603SJoerg Sonnenberger 	{ PCMCIA_VENDOR_3COM, PCMCIA_PRODUCT_3COM_3CCFEM556BI,
191666d2603SJoerg Sonnenberger 	  PCMCIA_CIS_INVALID,
192666d2603SJoerg Sonnenberger 	  &pccard_3ccfem556bi_func1, &pccard_3ccfem556bi_func1_cfe0 },
193666d2603SJoerg Sonnenberger 	{ PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID, PCMCIA_CIS_SVEC_LANCARD,
194666d2603SJoerg Sonnenberger 	  &pccard_sveclancard_func0, &pccard_sveclancard_func0_cfe0 },
195666d2603SJoerg Sonnenberger 	{ PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID, PCMCIA_CIS_NDC_ND5100_E,
196666d2603SJoerg Sonnenberger 	  &pccard_ndc_nd5100_func0, &pccard_ndc_nd5100_func0_cfe0 },
197666d2603SJoerg Sonnenberger };
198666d2603SJoerg Sonnenberger 
199c157ff7aSSascha Wildner static int n_pccard_cis_quirks = NELEM(pccard_cis_quirks);
200666d2603SJoerg Sonnenberger 
2013aef8050SSepherosa Ziehau static int
pccard_cis_quirk_match(struct pccard_softc * sc,struct pccard_cis_quirk * q)2023aef8050SSepherosa Ziehau pccard_cis_quirk_match(struct pccard_softc *sc, struct pccard_cis_quirk *q)
2033aef8050SSepherosa Ziehau {
2043aef8050SSepherosa Ziehau 	if ((sc->card.manufacturer == q->manufacturer) &&
2053aef8050SSepherosa Ziehau 		(sc->card.product == q->product) &&
2063aef8050SSepherosa Ziehau 		(((sc->card.manufacturer != PCMCIA_VENDOR_INVALID) &&
2073aef8050SSepherosa Ziehau 		  (sc->card.product != PCMCIA_PRODUCT_INVALID)) ||
2083aef8050SSepherosa Ziehau 		 ((sc->card.manufacturer == PCMCIA_VENDOR_INVALID) &&
2093aef8050SSepherosa Ziehau 		  (sc->card.product == PCMCIA_PRODUCT_INVALID) &&
2103aef8050SSepherosa Ziehau 		  sc->card.cis1_info[0] &&
2113aef8050SSepherosa Ziehau 		  (strcmp(sc->card.cis1_info[0], q->cis1_info[0]) == 0) &&
2123aef8050SSepherosa Ziehau 		  sc->card.cis1_info[1] &&
2133aef8050SSepherosa Ziehau 		  (strcmp(sc->card.cis1_info[1], q->cis1_info[1]) == 0))))
2143aef8050SSepherosa Ziehau 		return (1);
2153aef8050SSepherosa Ziehau 	return (0);
2163aef8050SSepherosa Ziehau }
2173aef8050SSepherosa Ziehau 
2180e224b5dSSascha Wildner void
pccard_check_cis_quirks(device_t dev)2190e224b5dSSascha Wildner pccard_check_cis_quirks(device_t dev)
220666d2603SJoerg Sonnenberger {
221666d2603SJoerg Sonnenberger 	struct pccard_softc *sc = PCCARD_SOFTC(dev);
222666d2603SJoerg Sonnenberger 	int wiped = 0;
223666d2603SJoerg Sonnenberger 	int i, j;
224666d2603SJoerg Sonnenberger 	struct pccard_function *pf, *pf_next, *pf_last;
225666d2603SJoerg Sonnenberger 	struct pccard_config_entry *cfe, *cfe_next;
2263aef8050SSepherosa Ziehau 	struct pccard_cis_quirk *q;
227666d2603SJoerg Sonnenberger 
228666d2603SJoerg Sonnenberger 	pf = NULL;
229666d2603SJoerg Sonnenberger 	pf_last = NULL;
230666d2603SJoerg Sonnenberger 
231666d2603SJoerg Sonnenberger 	for (i=0; i<n_pccard_cis_quirks; i++) {
2323aef8050SSepherosa Ziehau 		q = &pccard_cis_quirks[i];
2333aef8050SSepherosa Ziehau 		if (!pccard_cis_quirk_match(sc, q))
2343aef8050SSepherosa Ziehau 			continue;
235666d2603SJoerg Sonnenberger 		if (!wiped) {
236666d2603SJoerg Sonnenberger 			if (bootverbose) {
237666d2603SJoerg Sonnenberger 				device_printf(dev, "using CIS quirks for ");
238666d2603SJoerg Sonnenberger 				for (j = 0; j < 4; j++) {
239666d2603SJoerg Sonnenberger 					if (sc->card.cis1_info[j] == NULL)
240666d2603SJoerg Sonnenberger 						break;
241666d2603SJoerg Sonnenberger 					if (j)
24285f8e2eaSSascha Wildner 						kprintf(", ");
24385f8e2eaSSascha Wildner 					kprintf("%s", sc->card.cis1_info[j]);
244666d2603SJoerg Sonnenberger 				}
24585f8e2eaSSascha Wildner 				kprintf("\n");
246666d2603SJoerg Sonnenberger 			}
247666d2603SJoerg Sonnenberger 
248666d2603SJoerg Sonnenberger 			for (pf = STAILQ_FIRST(&sc->card.pf_head); pf != NULL;
249666d2603SJoerg Sonnenberger 			     pf = pf_next) {
250666d2603SJoerg Sonnenberger 				for (cfe = STAILQ_FIRST(&pf->cfe_head); cfe != NULL;
251666d2603SJoerg Sonnenberger 				     cfe = cfe_next) {
252666d2603SJoerg Sonnenberger 					cfe_next = STAILQ_NEXT(cfe, cfe_list);
253efda3bd0SMatthew Dillon 					kfree(cfe, M_DEVBUF);
254666d2603SJoerg Sonnenberger 				}
255666d2603SJoerg Sonnenberger 				pf_next = STAILQ_NEXT(pf, pf_list);
256efda3bd0SMatthew Dillon 				kfree(pf, M_DEVBUF);
257666d2603SJoerg Sonnenberger 			}
258666d2603SJoerg Sonnenberger 
259666d2603SJoerg Sonnenberger 			STAILQ_INIT(&sc->card.pf_head);
260666d2603SJoerg Sonnenberger 			wiped = 1;
261666d2603SJoerg Sonnenberger 		}
262666d2603SJoerg Sonnenberger 
2633aef8050SSepherosa Ziehau 		if (pf_last == q->pf) {
2643aef8050SSepherosa Ziehau 			cfe = kmalloc(sizeof(*cfe), M_DEVBUF, M_NOWAIT);
2653aef8050SSepherosa Ziehau 			if (cfe == NULL) {
2663aef8050SSepherosa Ziehau 				device_printf(dev, "no memory for quirk (1)\n");
2673aef8050SSepherosa Ziehau 				continue;
2683aef8050SSepherosa Ziehau 			}
2693aef8050SSepherosa Ziehau 			*cfe = *q->cfe;
270666d2603SJoerg Sonnenberger 			STAILQ_INSERT_TAIL(&pf->cfe_head, cfe, cfe_list);
271666d2603SJoerg Sonnenberger 		} else {
2723aef8050SSepherosa Ziehau 			pf = kmalloc(sizeof(*pf), M_DEVBUF, M_NOWAIT);
2733aef8050SSepherosa Ziehau 			if (pf == NULL) {
2743aef8050SSepherosa Ziehau 				device_printf(dev,
2753aef8050SSepherosa Ziehau 					"no memory for pccard function\n");
2763aef8050SSepherosa Ziehau 				continue;
2773aef8050SSepherosa Ziehau 			}
2783aef8050SSepherosa Ziehau 			*pf = *q->pf;
279666d2603SJoerg Sonnenberger 			STAILQ_INIT(&pf->cfe_head);
2803aef8050SSepherosa Ziehau 			cfe = kmalloc(sizeof(*cfe), M_DEVBUF, M_NOWAIT);
2813aef8050SSepherosa Ziehau 			if (cfe == NULL) {
2823aef8050SSepherosa Ziehau 				kfree(pf, M_DEVBUF);
2833aef8050SSepherosa Ziehau 				device_printf(dev, "no memory for quirk (2)\n");
2843aef8050SSepherosa Ziehau 				continue;
2853aef8050SSepherosa Ziehau 			}
2863aef8050SSepherosa Ziehau 			*cfe = *q->cfe;
287666d2603SJoerg Sonnenberger 			STAILQ_INSERT_TAIL(&pf->cfe_head, cfe, cfe_list);
288666d2603SJoerg Sonnenberger 			STAILQ_INSERT_TAIL(&sc->card.pf_head, pf, pf_list);
2893aef8050SSepherosa Ziehau 			pf_last = q->pf;
290666d2603SJoerg Sonnenberger 		}
291666d2603SJoerg Sonnenberger 	}
292666d2603SJoerg Sonnenberger }
293