pccard.c revision 166901
1229997Sken/*	$NetBSD: pcmcia.c,v 1.23 2000/07/28 19:17:02 drochner Exp $	*/
2229997Sken
3229997Sken/*-
4229997Sken * Copyright (c) 1997 Marc Horowitz.  All rights reserved.
5229997Sken *
6229997Sken * Redistribution and use in source and binary forms, with or without
7229997Sken * modification, are permitted provided that the following conditions
8229997Sken * are met:
9229997Sken * 1. Redistributions of source code must retain the above copyright
10229997Sken *    notice, this list of conditions and the following disclaimer.
11229997Sken * 2. Redistributions in binary form must reproduce the above copyright
12229997Sken *    notice, this list of conditions and the following disclaimer in the
13229997Sken *    documentation and/or other materials provided with the distribution.
14229997Sken * 3. All advertising materials mentioning features or use of this software
15229997Sken *    must display the following acknowledgement:
16229997Sken *	This product includes software developed by Marc Horowitz.
17229997Sken * 4. The name of the author may not be used to endorse or promote products
18229997Sken *    derived from this software without specific prior written permission.
19229997Sken *
20229997Sken * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21229997Sken * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22229997Sken * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23229997Sken * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24229997Sken * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25229997Sken * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26229997Sken * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27229997Sken * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28229997Sken * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29229997Sken * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30229997Sken */
31229997Sken
32229997Sken#include <sys/cdefs.h>
33229997Sken__FBSDID("$FreeBSD: head/sys/dev/pccard/pccard.c 166901 2007-02-23 12:19:07Z piso $");
34229997Sken
35229997Sken#include <sys/param.h>
36229997Sken#include <sys/systm.h>
37229997Sken#include <sys/malloc.h>
38229997Sken#include <sys/module.h>
39229997Sken#include <sys/kernel.h>
40229997Sken#include <sys/queue.h>
41229997Sken#include <sys/sysctl.h>
42229997Sken#include <sys/types.h>
43229997Sken
44229997Sken#include <sys/bus.h>
45229997Sken#include <machine/bus.h>
46229997Sken#include <sys/rman.h>
47229997Sken#include <machine/resource.h>
48229997Sken
49229997Sken#include <net/ethernet.h>
50229997Sken
51229997Sken#include <dev/pccard/pccardreg.h>
52229997Sken#include <dev/pccard/pccardvar.h>
53229997Sken#include <dev/pccard/pccardvarp.h>
54229997Sken#include <dev/pccard/pccard_cis.h>
55229997Sken
56229997Sken#include "power_if.h"
57229997Sken#include "card_if.h"
58229997Sken
59229997Sken#define PCCARDDEBUG
60229997Sken
61229997Sken/* sysctl vars */
62229997SkenSYSCTL_NODE(_hw, OID_AUTO, pccard, CTLFLAG_RD, 0, "PCCARD parameters");
63229997Sken
64229997Skenint	pccard_debug = 0;
65229997SkenTUNABLE_INT("hw.pccard.debug", &pccard_debug);
66229997SkenSYSCTL_INT(_hw_pccard, OID_AUTO, debug, CTLFLAG_RW,
67229997Sken    &pccard_debug, 0,
68229997Sken  "pccard debug");
69229997Sken
70229997Skenint	pccard_cis_debug = 0;
71229997SkenTUNABLE_INT("hw.pccard.cis_debug", &pccard_cis_debug);
72229997SkenSYSCTL_INT(_hw_pccard, OID_AUTO, cis_debug, CTLFLAG_RW,
73229997Sken    &pccard_cis_debug, 0, "pccard CIS debug");
74229997Sken
75229997Sken#ifdef PCCARDDEBUG
76229997Sken#define	DPRINTF(arg) if (pccard_debug) printf arg
77229997Sken#define	DEVPRINTF(arg) if (pccard_debug) device_printf arg
78229997Sken#define PRVERBOSE(arg) printf arg
79229997Sken#define DEVPRVERBOSE(arg) device_printf arg
80229997Sken#else
81229997Sken#define	DPRINTF(arg)
82229997Sken#define	DEVPRINTF(arg)
83229997Sken#define PRVERBOSE(arg) if (bootverbose) printf arg
84229997Sken#define DEVPRVERBOSE(arg) if (bootverbose) device_printf arg
85229997Sken#endif
86229997Sken
87229997Skenstatic int	pccard_ccr_read(struct pccard_function *pf, int ccr);
88229997Skenstatic void	pccard_ccr_write(struct pccard_function *pf, int ccr, int val);
89229997Skenstatic int	pccard_attach_card(device_t dev);
90229997Skenstatic int	pccard_detach_card(device_t dev);
91229997Skenstatic void	pccard_function_init(struct pccard_function *pf);
92229997Skenstatic void	pccard_function_free(struct pccard_function *pf);
93229997Skenstatic int	pccard_function_enable(struct pccard_function *pf);
94229997Skenstatic void	pccard_function_disable(struct pccard_function *pf);
95229997Skenstatic int	pccard_probe(device_t dev);
96229997Skenstatic int	pccard_attach(device_t dev);
97229997Skenstatic int	pccard_detach(device_t dev);
98229997Skenstatic void	pccard_print_resources(struct resource_list *rl,
99229997Sken		    const char *name, int type, int count, const char *format);
100229997Skenstatic int	pccard_print_child(device_t dev, device_t child);
101229997Skenstatic int	pccard_set_resource(device_t dev, device_t child, int type,
102229997Sken		    int rid, u_long start, u_long count);
103229997Skenstatic int	pccard_get_resource(device_t dev, device_t child, int type,
104229997Sken		    int rid, u_long *startp, u_long *countp);
105229997Skenstatic void	pccard_delete_resource(device_t dev, device_t child, int type,
106229997Sken		    int rid);
107229997Skenstatic int	pccard_set_res_flags(device_t dev, device_t child, int type,
108229997Sken		    int rid, uint32_t flags);
109229997Skenstatic int	pccard_set_memory_offset(device_t dev, device_t child, int rid,
110229997Sken		    uint32_t offset, uint32_t *deltap);
111229997Skenstatic void	pccard_probe_nomatch(device_t cbdev, device_t child);
112229997Skenstatic int	pccard_read_ivar(device_t bus, device_t child, int which,
113229997Sken		    u_char *result);
114229997Skenstatic void	pccard_driver_added(device_t dev, driver_t *driver);
115229997Skenstatic struct resource *pccard_alloc_resource(device_t dev,
116229997Sken		    device_t child, int type, int *rid, u_long start,
117229997Sken		    u_long end, u_long count, u_int flags);
118229997Skenstatic int	pccard_release_resource(device_t dev, device_t child, int type,
119229997Sken		    int rid, struct resource *r);
120229997Skenstatic void	pccard_child_detached(device_t parent, device_t dev);
121229997Skenstatic int	pccard_intr(void *arg);
122229997Skenstatic int	pccard_setup_intr(device_t dev, device_t child,
123229997Sken		    struct resource *irq, int flags, driver_filter_t *filt,
124229997Sken		    driver_intr_t *intr, void *arg, void **cookiep);
125229997Skenstatic int	pccard_teardown_intr(device_t dev, device_t child,
126229997Sken		    struct resource *r, void *cookie);
127229997Sken
128229997Skenstatic const struct pccard_product *
129229997Skenpccard_do_product_lookup(device_t bus, device_t dev,
130229997Sken			 const struct pccard_product *tab, size_t ent_size,
131229997Sken			 pccard_product_match_fn matchfn);
132229997Sken
133229997Sken
134229997Skenstatic int
135229997Skenpccard_ccr_read(struct pccard_function *pf, int ccr)
136229997Sken{
137229997Sken	return (bus_space_read_1(pf->pf_ccrt, pf->pf_ccrh,
138229997Sken	    pf->pf_ccr_offset + ccr));
139229997Sken}
140229997Sken
141229997Skenstatic void
142229997Skenpccard_ccr_write(struct pccard_function *pf, int ccr, int val)
143229997Sken{
144229997Sken	if ((pf->ccr_mask) & (1 << (ccr / 2))) {
145229997Sken		bus_space_write_1(pf->pf_ccrt, pf->pf_ccrh,
146229997Sken		    pf->pf_ccr_offset + ccr, val);
147229997Sken	}
148229997Sken}
149229997Sken
150229997Skenstatic int
151229997Skenpccard_set_default_descr(device_t dev)
152229997Sken{
153229997Sken	const char *vendorstr, *prodstr;
154229997Sken	uint32_t vendor, prod;
155229997Sken	char *str;
156229997Sken
157229997Sken	if (pccard_get_vendor_str(dev, &vendorstr))
158229997Sken		return (0);
159229997Sken	if (pccard_get_product_str(dev, &prodstr))
160229997Sken		return (0);
161229997Sken	if (vendorstr != NULL && prodstr != NULL) {
162229997Sken		str = malloc(strlen(vendorstr) + strlen(prodstr) + 2, M_DEVBUF,
163229997Sken		    M_WAITOK);
164229997Sken		sprintf(str, "%s %s", vendorstr, prodstr);
165229997Sken		device_set_desc_copy(dev, str);
166229997Sken		free(str, M_DEVBUF);
167229997Sken	} else {
168229997Sken		if (pccard_get_vendor(dev, &vendor))
169229997Sken			return (0);
170229997Sken		if (pccard_get_product(dev, &prod))
171229997Sken			return (0);
172229997Sken		str = malloc(100, M_DEVBUF, M_WAITOK);
173229997Sken		snprintf(str, 100, "vendor=0x%x product=0x%x", vendor, prod);
174229997Sken		device_set_desc_copy(dev, str);
175229997Sken		free(str, M_DEVBUF);
176229997Sken	}
177229997Sken	return (0);
178229997Sken}
179229997Sken
180229997Skenstatic int
181229997Skenpccard_attach_card(device_t dev)
182229997Sken{
183229997Sken	struct pccard_softc *sc = PCCARD_SOFTC(dev);
184229997Sken	struct pccard_function *pf;
185229997Sken	struct pccard_ivar *ivar;
186229997Sken	device_t child;
187229997Sken	int i;
188229997Sken
189229997Sken	if (!STAILQ_EMPTY(&sc->card.pf_head)) {
190229997Sken		if (bootverbose || pccard_debug)
191229997Sken			device_printf(dev, "Card already inserted.\n");
192229997Sken	}
193229997Sken
194229997Sken	DEVPRINTF((dev, "chip_socket_enable\n"));
195229997Sken	POWER_ENABLE_SOCKET(device_get_parent(dev), dev);
196229997Sken
197229997Sken	DEVPRINTF((dev, "read_cis\n"));
198229997Sken	pccard_read_cis(sc);
199229997Sken
200229997Sken	DEVPRINTF((dev, "check_cis_quirks\n"));
201229997Sken	pccard_check_cis_quirks(dev);
202229997Sken
203229997Sken	/*
204229997Sken	 * bail now if the card has no functions, or if there was an error in
205229997Sken	 * the cis.
206229997Sken	 */
207229997Sken
208229997Sken	if (sc->card.error) {
209229997Sken		device_printf(dev, "CARD ERROR!\n");
210229997Sken		return (1);
211229997Sken	}
212229997Sken	if (STAILQ_EMPTY(&sc->card.pf_head)) {
213229997Sken		device_printf(dev, "Card has no functions!\n");
214229997Sken		return (1);
215229997Sken	}
216229997Sken
217229997Sken	if (bootverbose || pccard_debug)
218229997Sken		pccard_print_cis(dev);
219229997Sken
220229997Sken	DEVPRINTF((dev, "functions scanning\n"));
221229997Sken	i = -1;
222229997Sken	STAILQ_FOREACH(pf, &sc->card.pf_head, pf_list) {
223229997Sken		i++;
224229997Sken		if (STAILQ_EMPTY(&pf->cfe_head)) {
225229997Sken			device_printf(dev,
226229997Sken			    "Function %d has no config entries.!\n", i);
227229997Sken			continue;
228229997Sken		}
229229997Sken		pf->sc = sc;
230229997Sken		pf->cfe = NULL;
231229997Sken		pf->dev = NULL;
232229997Sken	}
233229997Sken	DEVPRINTF((dev, "Card has %d functions. pccard_mfc is %d\n", i + 1,
234229997Sken	    pccard_mfc(sc)));
235229997Sken
236229997Sken	STAILQ_FOREACH(pf, &sc->card.pf_head, pf_list) {
237229997Sken		if (STAILQ_EMPTY(&pf->cfe_head))
238229997Sken			continue;
239229997Sken		/*
240229997Sken		 * In NetBSD, the drivers are responsible for activating
241229997Sken		 * each function of a card.  I think that in FreeBSD we
242229997Sken		 * want to activate them enough for the usual bus_*_resource
243229997Sken		 * routines will do the right thing.  This many mean a
244229997Sken		 * departure from the current NetBSD model.
245229997Sken		 *
246229997Sken		 * This seems to work well in practice for most cards.
247229997Sken		 * However, there are two cases that are problematic.
248229997Sken		 * If a driver wishes to pick and chose which config
249229997Sken		 * entry to use, then this method falls down.  These
250229997Sken		 * are usually older cards.  In addition, there are
251229997Sken		 * some cards that have multiple hardware units on the
252229997Sken		 * cards, but presents only one CIS chain.  These cards
253229997Sken		 * are combination cards, but only one of these units
254229997Sken		 * can be on at a time.
255229997Sken		 */
256229997Sken		ivar = malloc(sizeof(struct pccard_ivar), M_DEVBUF,
257229997Sken		    M_WAITOK | M_ZERO);
258229997Sken		resource_list_init(&ivar->resources);
259229997Sken		child = device_add_child(dev, NULL, -1);
260229997Sken		device_set_ivars(child, ivar);
261229997Sken		ivar->pf = pf;
262229997Sken		pf->dev = child;
263229997Sken		/*
264229997Sken		 * XXX We might want to move the next three lines into
265229997Sken		 * XXX the pccard interface layer.  For the moment, this
266229997Sken		 * XXX is OK, but some drivers want to pick the config
267229997Sken		 * XXX entry to use as well as some address tweaks (mostly
268229997Sken		 * XXX due to bugs in decode logic that makes some
269229997Sken		 * XXX addresses illegal or broken).
270229997Sken		 */
271229997Sken		pccard_function_init(pf);
272229997Sken		if (sc->sc_enabled_count == 0)
273229997Sken			POWER_ENABLE_SOCKET(device_get_parent(dev), dev);
274229997Sken		if (pccard_function_enable(pf) == 0 &&
275229997Sken		    pccard_set_default_descr(child) == 0 &&
276229997Sken		    device_probe_and_attach(child) == 0) {
277229997Sken			DEVPRINTF((sc->dev, "function %d CCR at %d "
278229997Sken			    "offset %x mask %x: "
279229997Sken			    "%x %x %x %x, %x %x %x %x, %x\n",
280229997Sken			    pf->number, pf->pf_ccr_window, pf->pf_ccr_offset,
281229997Sken			    pf->ccr_mask, pccard_ccr_read(pf, 0x00),
282229997Sken			pccard_ccr_read(pf, 0x02), pccard_ccr_read(pf, 0x04),
283229997Sken			pccard_ccr_read(pf, 0x06), pccard_ccr_read(pf, 0x0A),
284229997Sken			pccard_ccr_read(pf, 0x0C), pccard_ccr_read(pf, 0x0E),
285229997Sken			pccard_ccr_read(pf, 0x10), pccard_ccr_read(pf, 0x12)));
286229997Sken		} else {
287229997Sken			if (pf->cfe != NULL)
288229997Sken				pccard_function_disable(pf);
289229997Sken		}
290229997Sken	}
291229997Sken	return (0);
292229997Sken}
293229997Sken
294229997Skenstatic int
295229997Skenpccard_detach_card(device_t dev)
296229997Sken{
297229997Sken	struct pccard_softc *sc = PCCARD_SOFTC(dev);
298229997Sken	struct pccard_function *pf;
299229997Sken	struct pccard_config_entry *cfe;
300229997Sken	struct pccard_ivar *devi;
301229997Sken	int state;
302229997Sken
303229997Sken	/*
304229997Sken	 * We are running on either the PCCARD socket's event thread
305229997Sken	 * or in user context detaching a device by user request.
306229997Sken	 */
307229997Sken	STAILQ_FOREACH(pf, &sc->card.pf_head, pf_list) {
308230033Sken		if (pf->dev == NULL)
309229997Sken			continue;
310229997Sken		state = device_get_state(pf->dev);
311230033Sken		if (state == DS_ATTACHED || state == DS_BUSY)
312229997Sken			device_detach(pf->dev);
313229997Sken		if (pf->cfe != NULL)
314229997Sken			pccard_function_disable(pf);
315229997Sken		pccard_function_free(pf);
316229997Sken		devi = PCCARD_IVAR(pf->dev);
317229997Sken		device_delete_child(dev, pf->dev);
318229997Sken		free(devi, M_DEVBUF);
319229997Sken	}
320229997Sken	if (sc->sc_enabled_count == 0)
321229997Sken		POWER_DISABLE_SOCKET(device_get_parent(dev), dev);
322229997Sken
323229997Sken	while (NULL != (pf = STAILQ_FIRST(&sc->card.pf_head))) {
324229997Sken		while (NULL != (cfe = STAILQ_FIRST(&pf->cfe_head))) {
325229997Sken			STAILQ_REMOVE_HEAD(&pf->cfe_head, cfe_list);
326229997Sken			free(cfe, M_DEVBUF);
327229997Sken		}
328229997Sken		STAILQ_REMOVE_HEAD(&sc->card.pf_head, pf_list);
329229997Sken		free(pf, M_DEVBUF);
330229997Sken	}
331229997Sken	STAILQ_INIT(&sc->card.pf_head);
332229997Sken	return (0);
333229997Sken}
334229997Sken
335229997Skenstatic const struct pccard_product *
336229997Skenpccard_do_product_lookup(device_t bus, device_t dev,
337229997Sken    const struct pccard_product *tab, size_t ent_size,
338229997Sken    pccard_product_match_fn matchfn)
339229997Sken{
340229997Sken	const struct pccard_product *ent;
341229997Sken	int matches;
342229997Sken	uint32_t vendor;
343229997Sken	uint32_t prod;
344229997Sken	const char *vendorstr;
345229997Sken	const char *prodstr;
346229997Sken	const char *cis3str;
347229997Sken	const char *cis4str;
348229997Sken
349229997Sken#ifdef DIAGNOSTIC
350229997Sken	if (sizeof *ent > ent_size)
351229997Sken		panic("pccard_product_lookup: bogus ent_size %jd",
352229997Sken		    (intmax_t) ent_size);
353229997Sken#endif
354229997Sken	if (pccard_get_vendor(dev, &vendor))
355229997Sken		return (NULL);
356229997Sken	if (pccard_get_product(dev, &prod))
357229997Sken		return (NULL);
358229997Sken	if (pccard_get_vendor_str(dev, &vendorstr))
359229997Sken		return (NULL);
360229997Sken	if (pccard_get_product_str(dev, &prodstr))
361229997Sken		return (NULL);
362229997Sken	if (pccard_get_cis3_str(dev, &cis3str))
363229997Sken		return (NULL);
364229997Sken	if (pccard_get_cis4_str(dev, &cis4str))
365229997Sken		return (NULL);
366229997Sken	for (ent = tab; ent->pp_vendor != 0; ent =
367229997Sken	    (const struct pccard_product *) ((const char *) ent + ent_size)) {
368229997Sken		matches = 1;
369229997Sken		if (ent->pp_vendor == PCCARD_VENDOR_ANY &&
370229997Sken		    ent->pp_product == PCCARD_PRODUCT_ANY &&
371229997Sken		    ent->pp_cis[0] == NULL &&
372229997Sken		    ent->pp_cis[1] == NULL) {
373229997Sken			if (ent->pp_name)
374229997Sken				device_printf(dev,
375229997Sken				    "Total wildcard entry ignored for %s\n",
376229997Sken				    ent->pp_name);
377229997Sken			continue;
378229997Sken		}
379229997Sken		if (matches && ent->pp_vendor != PCCARD_VENDOR_ANY &&
380229997Sken		    vendor != ent->pp_vendor)
381229997Sken			matches = 0;
382229997Sken		if (matches && ent->pp_product != PCCARD_PRODUCT_ANY &&
383229997Sken		    prod != ent->pp_product)
384229997Sken			matches = 0;
385229997Sken		if (matches && ent->pp_cis[0] &&
386229997Sken		    (vendorstr == NULL ||
387229997Sken		    strcmp(ent->pp_cis[0], vendorstr) != 0))
388229997Sken			matches = 0;
389229997Sken		if (matches && ent->pp_cis[1] &&
390229997Sken		    (prodstr == NULL ||
391229997Sken		    strcmp(ent->pp_cis[1], prodstr) != 0))
392229997Sken			matches = 0;
393229997Sken		if (matches && ent->pp_cis[2] &&
394229997Sken		    (cis3str == NULL ||
395229997Sken		    strcmp(ent->pp_cis[2], cis3str) != 0))
396229997Sken			matches = 0;
397229997Sken		if (matches && ent->pp_cis[3] &&
398229997Sken		    (cis4str == NULL ||
399229997Sken		    strcmp(ent->pp_cis[3], cis4str) != 0))
400229997Sken			matches = 0;
401229997Sken		if (matchfn != NULL)
402229997Sken			matches = (*matchfn)(dev, ent, matches);
403229997Sken		if (matches)
404229997Sken			return (ent);
405229997Sken	}
406229997Sken	return (NULL);
407229997Sken}
408229997Sken
409229997Sken/*
410229997Sken * Initialize a PCCARD function.  May be called as long as the function is
411229997Sken * disabled.
412229997Sken *
413229997Sken * Note: pccard_function_init should not keep resources allocated.  It should
414229997Sken * only set them up ala isa pnp, set the values in the rl lists, and return.
415229997Sken * Any resource held after pccard_function_init is called is a bug.  However,
416229997Sken * the bus routines to get the resources also assume that pccard_function_init
417229997Sken * does this, so they need to be fixed too.
418229997Sken */
419229997Skenstatic void
420229997Skenpccard_function_init(struct pccard_function *pf)
421229997Sken{
422229997Sken	struct pccard_config_entry *cfe;
423229997Sken	struct pccard_ivar *devi = PCCARD_IVAR(pf->dev);
424229997Sken	struct resource_list *rl = &devi->resources;
425229997Sken	struct resource_list_entry *rle;
426230033Sken	struct resource *r = 0;
427229997Sken	device_t bus;
428229997Sken	u_long start, end, len;
429230033Sken	int i, rid, spaces;
430229997Sken
431229997Sken	if (pf->pf_flags & PFF_ENABLED) {
432229997Sken		printf("pccard_function_init: function is enabled");
433229997Sken		return;
434229997Sken	}
435229997Sken	bus = device_get_parent(pf->dev);
436229997Sken	/* Remember which configuration entry we are using. */
437229997Sken	STAILQ_FOREACH(cfe, &pf->cfe_head, cfe_list) {
438229997Sken		if (cfe->iftype != PCCARD_IFTYPE_IO)
439229997Sken			continue;
440229997Sken		spaces = 0;
441229997Sken		for (i = 0; i < cfe->num_iospace; i++) {
442229997Sken			start = cfe->iospace[i].start;
443229997Sken			if (start)
444229997Sken				end = start + cfe->iospace[i].length - 1;
445229997Sken			else
446229997Sken				end = ~0UL;
447229997Sken			DEVPRINTF((bus, "I/O rid %d start %lx end %lx\n",
448229997Sken			    i, start, end));
449229997Sken			rid = i;
450229997Sken			len = cfe->iospace[i].length;
451229997Sken			r = bus_alloc_resource(bus, SYS_RES_IOPORT, &rid,
452229997Sken			    start, end, len, rman_make_alignment_flags(len));
453229997Sken			if (r == NULL)
454229997Sken				goto not_this_one;
455229997Sken			rle = resource_list_add(rl, SYS_RES_IOPORT,
456229997Sken			    rid, rman_get_start(r), rman_get_end(r),
457229997Sken			    cfe->iospace[i].length);
458229997Sken			if (rle == NULL)
459229997Sken				panic("Cannot add resource rid %d IOPORT", rid);
460229997Sken			rle->res = r;
461229997Sken			spaces++;
462229997Sken		}
463229997Sken		for (i = 0; i < cfe->num_memspace; i++) {
464229997Sken			start = cfe->memspace[i].hostaddr;
465229997Sken			if (start)
466229997Sken				end = start + cfe->memspace[i].length - 1;
467229997Sken			else
468229997Sken				end = ~0UL;
469229997Sken			DEVPRINTF((bus, "Memory rid %d start %lx end %lx\n",
470229997Sken			    i, start, end));
471229997Sken			rid = i;
472229997Sken			len = cfe->memspace[i].length;
473229997Sken			r = bus_alloc_resource(bus, SYS_RES_MEMORY, &rid,
474229997Sken			    start, end, len, rman_make_alignment_flags(len));
475229997Sken			if (r == NULL)
476229997Sken				goto not_this_one;
477229997Sken			rle = resource_list_add(rl, SYS_RES_MEMORY,
478229997Sken			    rid, rman_get_start(r), rman_get_end(r),
479229997Sken			    cfe->memspace[i].length);
480229997Sken			if (rle == NULL)
481229997Sken				panic("Cannot add resource rid %d MEM", rid);
482229997Sken			rle->res = r;
483229997Sken			spaces++;
484229997Sken		}
485229997Sken		if (spaces == 0) {
486229997Sken			DEVPRINTF((bus, "Neither memory nor I/O mapped\n"));
487229997Sken			goto not_this_one;
488229997Sken		}
489229997Sken		if (cfe->irqmask) {
490229997Sken			rid = 0;
491229997Sken			r = bus_alloc_resource_any(bus, SYS_RES_IRQ, &rid,
492229997Sken			    RF_SHAREABLE);
493236426Smjacob			if (r == NULL)
494229997Sken				goto not_this_one;
495229997Sken			rle = resource_list_add(rl, SYS_RES_IRQ, rid,
496229997Sken			    rman_get_start(r), rman_get_end(r), 1);
497229997Sken			if (rle == NULL)
498229997Sken				panic("Cannot add resource rid %d IRQ", rid);
499229997Sken			rle->res = r;
500229997Sken		}
501229997Sken		/* If we get to here, we've allocated all we need */
502229997Sken		pf->cfe = cfe;
503229997Sken		break;
504229997Sken	    not_this_one:;
505229997Sken		DEVPRVERBOSE((bus, "Allocation failed for cfe %d\n",
506229997Sken		    cfe->number));
507229997Sken		resource_list_purge(rl);
508229997Sken	}
509229997Sken}
510229997Sken
511229997Sken/*
512229997Sken * Free resources allocated by pccard_function_init(), May be called as long
513229997Sken * as the function is disabled.
514229997Sken *
515229997Sken * NOTE: This function should be unnecessary.  pccard_function_init should
516229997Sken * never keep resources initialized.
517229997Sken */
518229997Skenstatic void
519229997Skenpccard_function_free(struct pccard_function *pf)
520229997Sken{
521229997Sken	struct pccard_ivar *devi = PCCARD_IVAR(pf->dev);
522229997Sken	struct resource_list_entry *rle;
523229997Sken
524229997Sken	if (pf->pf_flags & PFF_ENABLED) {
525229997Sken		printf("pccard_function_init: function is enabled");
526229997Sken		return;
527229997Sken	}
528229997Sken
529229997Sken	STAILQ_FOREACH(rle, &devi->resources, link) {
530229997Sken		if (rle->res) {
531229997Sken			if (rman_get_device(rle->res) != pf->sc->dev)
532229997Sken				device_printf(pf->sc->dev,
533229997Sken				    "function_free: Resource still owned by "
534229997Sken				    "child, oops. "
535229997Sken				    "(type=%d, rid=%d, addr=%lx)\n",
536229997Sken				    rle->type, rle->rid,
537229997Sken				    rman_get_start(rle->res));
538229997Sken			BUS_RELEASE_RESOURCE(device_get_parent(pf->sc->dev),
539229997Sken			    pf->sc->dev, rle->type, rle->rid, rle->res);
540229997Sken			rle->res = NULL;
541229997Sken		}
542229997Sken	}
543229997Sken	resource_list_free(&devi->resources);
544229997Sken}
545229997Sken
546229997Skenstatic void
547229997Skenpccard_mfc_adjust_iobase(struct pccard_function *pf, bus_addr_t addr,
548229997Sken    bus_addr_t offset, bus_size_t size)
549229997Sken{
550229997Sken	bus_size_t iosize, tmp;
551229997Sken
552229997Sken	if (addr != 0) {
553229997Sken		if (pf->pf_mfc_iomax == 0) {
554229997Sken			pf->pf_mfc_iobase = addr + offset;
555229997Sken			pf->pf_mfc_iomax = pf->pf_mfc_iobase + size;
556229997Sken		} else {
557229997Sken			/* this makes the assumption that nothing overlaps */
558229997Sken			if (pf->pf_mfc_iobase > addr + offset)
559229997Sken				pf->pf_mfc_iobase = addr + offset;
560229997Sken			if (pf->pf_mfc_iomax < addr + offset + size)
561229997Sken				pf->pf_mfc_iomax = addr + offset + size;
562229997Sken		}
563229997Sken	}
564229997Sken
565229997Sken	tmp = pf->pf_mfc_iomax - pf->pf_mfc_iobase;
566229997Sken	/* round up to nearest (2^n)-1 */
567229997Sken	for (iosize = 1; iosize < tmp; iosize <<= 1)
568229997Sken		;
569229997Sken	iosize--;
570229997Sken
571229997Sken	DEVPRINTF((pf->dev, "MFC: I/O base %#jx IOSIZE %#jx\n",
572229997Sken	    (uintmax_t)pf->pf_mfc_iobase, (uintmax_t)(iosize + 1)));
573229997Sken	pccard_ccr_write(pf, PCCARD_CCR_IOBASE0,
574229997Sken	    pf->pf_mfc_iobase & 0xff);
575229997Sken	pccard_ccr_write(pf, PCCARD_CCR_IOBASE1,
576229997Sken	    (pf->pf_mfc_iobase >> 8) & 0xff);
577229997Sken	pccard_ccr_write(pf, PCCARD_CCR_IOBASE2, 0);
578229997Sken	pccard_ccr_write(pf, PCCARD_CCR_IOBASE3, 0);
579229997Sken	pccard_ccr_write(pf, PCCARD_CCR_IOSIZE, iosize);
580229997Sken}
581229997Sken
582229997Sken/* Enable a PCCARD function */
583229997Skenstatic int
584229997Skenpccard_function_enable(struct pccard_function *pf)
585236426Smjacob{
586229997Sken	struct pccard_function *tmp;
587229997Sken	int reg;
588229997Sken	device_t dev = pf->sc->dev;
589229997Sken
590229997Sken	if (pf->cfe == NULL) {
591229997Sken		DEVPRVERBOSE((dev, "No config entry could be allocated.\n"));
592229997Sken		return (ENOMEM);
593229997Sken	}
594229997Sken
595229997Sken	/*
596229997Sken	 * Increase the reference count on the socket, enabling power, if
597229997Sken	 * necessary.
598229997Sken	 */
599229997Sken	pf->sc->sc_enabled_count++;
600229997Sken
601229997Sken	if (pf->pf_flags & PFF_ENABLED) {
602229997Sken		/*
603229997Sken		 * Don't do anything if we're already enabled.
604229997Sken		 */
605229997Sken		return (0);
606229997Sken	}
607229997Sken
608229997Sken	/*
609229997Sken	 * it's possible for different functions' CCRs to be in the same
610229997Sken	 * underlying page.  Check for that.
611229997Sken	 */
612229997Sken	STAILQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) {
613229997Sken		if ((tmp->pf_flags & PFF_ENABLED) &&
614229997Sken		    (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) &&
615229997Sken		    ((pf->ccr_base + PCCARD_CCR_SIZE) <=
616229997Sken		    (tmp->ccr_base - tmp->pf_ccr_offset +
617229997Sken		    tmp->pf_ccr_realsize))) {
618229997Sken			pf->pf_ccrt = tmp->pf_ccrt;
619236426Smjacob			pf->pf_ccrh = tmp->pf_ccrh;
620229997Sken			pf->pf_ccr_realsize = tmp->pf_ccr_realsize;
621229997Sken
622229997Sken			/*
623229997Sken			 * pf->pf_ccr_offset = (tmp->pf_ccr_offset -
624229997Sken			 * tmp->ccr_base) + pf->ccr_base;
625229997Sken			 */
626229997Sken			/* pf->pf_ccr_offset =
627229997Sken			    (tmp->pf_ccr_offset + pf->ccr_base) -
628229997Sken			    tmp->ccr_base; */
629229997Sken			pf->pf_ccr_window = tmp->pf_ccr_window;
630229997Sken			break;
631229997Sken		}
632229997Sken	}
633229997Sken	if (tmp == NULL) {
634229997Sken		pf->ccr_rid = 0;
635229997Sken		pf->ccr_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
636229997Sken		    &pf->ccr_rid, 0, ~0, PCCARD_MEM_PAGE_SIZE, RF_ACTIVE);
637229997Sken		if (!pf->ccr_res)
638229997Sken			goto bad;
639229997Sken		DEVPRINTF((dev, "ccr_res == %lx-%lx, base=%x\n",
640229997Sken		    rman_get_start(pf->ccr_res), rman_get_end(pf->ccr_res),
641229997Sken		    pf->ccr_base));
642229997Sken		CARD_SET_RES_FLAGS(device_get_parent(dev), dev, SYS_RES_MEMORY,
643229997Sken		    pf->ccr_rid, PCCARD_A_MEM_ATTR);
644229997Sken		CARD_SET_MEMORY_OFFSET(device_get_parent(dev), dev,
645229997Sken		    pf->ccr_rid, pf->ccr_base, &pf->pf_ccr_offset);
646229997Sken		pf->pf_ccrt = rman_get_bustag(pf->ccr_res);
647229997Sken		pf->pf_ccrh = rman_get_bushandle(pf->ccr_res);
648229997Sken		pf->pf_ccr_realsize = 1;
649229997Sken	}
650229997Sken
651229997Sken	reg = (pf->cfe->number & PCCARD_CCR_OPTION_CFINDEX);
652229997Sken	reg |= PCCARD_CCR_OPTION_LEVIREQ;
653229997Sken	if (pccard_mfc(pf->sc)) {
654229997Sken		reg |= (PCCARD_CCR_OPTION_FUNC_ENABLE |
655229997Sken			PCCARD_CCR_OPTION_ADDR_DECODE);
656229997Sken		/* PCCARD_CCR_OPTION_IRQ_ENABLE set elsewhere as needed */
657229997Sken	}
658229997Sken	pccard_ccr_write(pf, PCCARD_CCR_OPTION, reg);
659229997Sken
660229997Sken	reg = 0;
661229997Sken	if ((pf->cfe->flags & PCCARD_CFE_IO16) == 0)
662229997Sken		reg |= PCCARD_CCR_STATUS_IOIS8;
663229997Sken	if (pf->cfe->flags & PCCARD_CFE_AUDIO)
664229997Sken		reg |= PCCARD_CCR_STATUS_AUDIO;
665229997Sken	pccard_ccr_write(pf, PCCARD_CCR_STATUS, reg);
666229997Sken
667229997Sken	pccard_ccr_write(pf, PCCARD_CCR_SOCKETCOPY, 0);
668229997Sken
669229997Sken	if (pccard_mfc(pf->sc))
670229997Sken		pccard_mfc_adjust_iobase(pf, 0, 0, 0);
671229997Sken
672229997Sken#ifdef PCCARDDEBUG
673229997Sken	if (pccard_debug) {
674229997Sken		STAILQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) {
675229997Sken			device_printf(tmp->sc->dev,
676229997Sken			    "function %d CCR at %d offset %x: "
677229997Sken			    "%x %x %x %x, %x %x %x %x, %x\n",
678229997Sken			    tmp->number, tmp->pf_ccr_window,
679229997Sken			    tmp->pf_ccr_offset,
680229997Sken			    pccard_ccr_read(tmp, 0x00),
681229997Sken			    pccard_ccr_read(tmp, 0x02),
682229997Sken			    pccard_ccr_read(tmp, 0x04),
683229997Sken			    pccard_ccr_read(tmp, 0x06),
684229997Sken			    pccard_ccr_read(tmp, 0x0A),
685229997Sken			    pccard_ccr_read(tmp, 0x0C),
686229997Sken			    pccard_ccr_read(tmp, 0x0E),
687229997Sken			    pccard_ccr_read(tmp, 0x10),
688229997Sken			    pccard_ccr_read(tmp, 0x12));
689229997Sken		}
690229997Sken	}
691229997Sken#endif
692229997Sken	pf->pf_flags |= PFF_ENABLED;
693229997Sken	return (0);
694229997Sken
695229997Sken bad:
696229997Sken	/*
697229997Sken	 * Decrement the reference count, and power down the socket, if
698229997Sken	 * necessary.
699229997Sken	 */
700229997Sken	pf->sc->sc_enabled_count--;
701229997Sken	DEVPRINTF((dev, "bad --enabled_count = %d\n", pf->sc->sc_enabled_count));
702229997Sken
703229997Sken	return (1);
704229997Sken}
705229997Sken
706229997Sken/* Disable PCCARD function. */
707229997Skenstatic void
708229997Skenpccard_function_disable(struct pccard_function *pf)
709229997Sken{
710229997Sken	struct pccard_function *tmp;
711229997Sken	device_t dev = pf->sc->dev;
712229997Sken
713229997Sken	if (pf->cfe == NULL)
714229997Sken		panic("pccard_function_disable: function not initialized");
715229997Sken
716229997Sken	if ((pf->pf_flags & PFF_ENABLED) == 0) {
717229997Sken		/*
718229997Sken		 * Don't do anything if we're already disabled.
719229997Sken		 */
720229997Sken		return;
721229997Sken	}
722229997Sken
723229997Sken	if (pf->intr_handler != NULL) {
724229997Sken		struct pccard_ivar *devi = PCCARD_IVAR(pf->dev);
725229997Sken		struct resource_list_entry *rle =
726229997Sken		    resource_list_find(&devi->resources, SYS_RES_IRQ, 0);
727229997Sken		if (rle == NULL)
728229997Sken			panic("Can't disable an interrupt with no IRQ res\n");
729229997Sken		BUS_TEARDOWN_INTR(dev, pf->dev, rle->res,
730229997Sken		    pf->intr_handler_cookie);
731229997Sken	}
732229997Sken
733229997Sken	/*
734229997Sken	 * it's possible for different functions' CCRs to be in the same
735229997Sken	 * underlying page.  Check for that.  Note we mark us as disabled
736229997Sken	 * first to avoid matching ourself.
737229997Sken	 */
738229997Sken
739229997Sken	pf->pf_flags &= ~PFF_ENABLED;
740229997Sken	STAILQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) {
741229997Sken		if ((tmp->pf_flags & PFF_ENABLED) &&
742229997Sken		    (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) &&
743229997Sken		    ((pf->ccr_base + PCCARD_CCR_SIZE) <=
744229997Sken		    (tmp->ccr_base - tmp->pf_ccr_offset +
745229997Sken		    tmp->pf_ccr_realsize)))
746229997Sken			break;
747229997Sken	}
748229997Sken
749229997Sken	/* Not used by anyone else; unmap the CCR. */
750229997Sken	if (tmp == NULL) {
751229997Sken		bus_release_resource(dev, SYS_RES_MEMORY, pf->ccr_rid,
752229997Sken		    pf->ccr_res);
753229997Sken		pf->ccr_res = NULL;
754229997Sken	}
755229997Sken
756229997Sken	/*
757229997Sken	 * Decrement the reference count, and power down the socket, if
758229997Sken	 * necessary.
759229997Sken	 */
760229997Sken	pf->sc->sc_enabled_count--;
761229997Sken}
762229997Sken
763229997Sken#define PCCARD_NPORT	2
764229997Sken#define PCCARD_NMEM	5
765229997Sken#define PCCARD_NIRQ	1
766229997Sken#define PCCARD_NDRQ	0
767229997Sken
768229997Skenstatic int
769229997Skenpccard_probe(device_t dev)
770229997Sken{
771229997Sken	device_set_desc(dev, "16-bit PCCard bus");
772229997Sken	return (0);
773229997Sken}
774229997Sken
775229997Skenstatic int
776229997Skenpccard_attach(device_t dev)
777229997Sken{
778229997Sken	struct pccard_softc *sc = PCCARD_SOFTC(dev);
779229997Sken	int err;
780229997Sken
781229997Sken	sc->dev = dev;
782229997Sken	sc->sc_enabled_count = 0;
783229997Sken	if ((err = pccard_device_create(sc)) != 0)
784229997Sken		return  (err);
785229997Sken	STAILQ_INIT(&sc->card.pf_head);
786229997Sken	return (bus_generic_attach(dev));
787229997Sken}
788229997Sken
789229997Skenstatic int
790229997Skenpccard_detach(device_t dev)
791229997Sken{
792229997Sken	pccard_detach_card(dev);
793229997Sken	pccard_device_destroy(device_get_softc(dev));
794229997Sken	return (0);
795229997Sken}
796229997Sken
797229997Skenstatic int
798229997Skenpccard_suspend(device_t self)
799229997Sken{
800229997Sken	pccard_detach_card(self);
801229997Sken	return (0);
802229997Sken}
803229997Sken
804229997Skenstatic
805229997Skenint
806229997Skenpccard_resume(device_t self)
807229997Sken{
808229997Sken	return (0);
809229997Sken}
810229997Sken
811229997Skenstatic void
812229997Skenpccard_print_resources(struct resource_list *rl, const char *name, int type,
813229997Sken    int count, const char *format)
814229997Sken{
815229997Sken	struct resource_list_entry *rle;
816229997Sken	int printed;
817229997Sken	int i;
818229997Sken
819229997Sken	printed = 0;
820229997Sken	for (i = 0; i < count; i++) {
821229997Sken		rle = resource_list_find(rl, type, i);
822229997Sken		if (rle != NULL) {
823229997Sken			if (printed == 0)
824229997Sken				printf(" %s ", name);
825229997Sken			else if (printed > 0)
826229997Sken				printf(",");
827229997Sken			printed++;
828229997Sken			printf(format, rle->start);
829229997Sken			if (rle->count > 1) {
830229997Sken				printf("-");
831229997Sken				printf(format, rle->start + rle->count - 1);
832229997Sken			}
833229997Sken		} else if (i > 3) {
834229997Sken			/* check the first few regardless */
835229997Sken			break;
836229997Sken		}
837229997Sken	}
838229997Sken}
839229997Sken
840229997Skenstatic int
841229997Skenpccard_print_child(device_t dev, device_t child)
842229997Sken{
843229997Sken	struct pccard_ivar *devi = PCCARD_IVAR(child);
844229997Sken	struct resource_list *rl = &devi->resources;
845229997Sken	int retval = 0;
846229997Sken
847229997Sken	retval += bus_print_child_header(dev, child);
848229997Sken	retval += printf(" at");
849229997Sken
850229997Sken	if (devi != NULL) {
851229997Sken		pccard_print_resources(rl, "port", SYS_RES_IOPORT,
852229997Sken		    PCCARD_NPORT, "%#lx");
853229997Sken		pccard_print_resources(rl, "iomem", SYS_RES_MEMORY,
854229997Sken		    PCCARD_NMEM, "%#lx");
855229997Sken		pccard_print_resources(rl, "irq", SYS_RES_IRQ, PCCARD_NIRQ,
856229997Sken		    "%ld");
857229997Sken		pccard_print_resources(rl, "drq", SYS_RES_DRQ, PCCARD_NDRQ,
858229997Sken		    "%ld");
859229997Sken		retval += printf(" function %d config %d", devi->pf->number,
860229997Sken		    devi->pf->cfe->number);
861229997Sken	}
862229997Sken
863229997Sken	retval += bus_print_child_footer(dev, child);
864229997Sken
865229997Sken	return (retval);
866229997Sken}
867229997Sken
868229997Skenstatic int
869229997Skenpccard_set_resource(device_t dev, device_t child, int type, int rid,
870229997Sken    u_long start, u_long count)
871229997Sken{
872229997Sken	struct pccard_ivar *devi = PCCARD_IVAR(child);
873229997Sken	struct resource_list *rl = &devi->resources;
874229997Sken
875229997Sken	if (type != SYS_RES_IOPORT && type != SYS_RES_MEMORY
876229997Sken	    && type != SYS_RES_IRQ && type != SYS_RES_DRQ)
877229997Sken		return (EINVAL);
878229997Sken	if (rid < 0)
879229997Sken		return (EINVAL);
880229997Sken	if (type == SYS_RES_IOPORT && rid >= PCCARD_NPORT)
881229997Sken		return (EINVAL);
882229997Sken	if (type == SYS_RES_MEMORY && rid >= PCCARD_NMEM)
883229997Sken		return (EINVAL);
884229997Sken	if (type == SYS_RES_IRQ && rid >= PCCARD_NIRQ)
885229997Sken		return (EINVAL);
886229997Sken	if (type == SYS_RES_DRQ && rid >= PCCARD_NDRQ)
887229997Sken		return (EINVAL);
888229997Sken
889229997Sken	resource_list_add(rl, type, rid, start, start + count - 1, count);
890229997Sken	if (NULL != resource_list_alloc(rl, device_get_parent(dev), dev,
891229997Sken	    type, &rid, start, start + count - 1, count, 0))
892229997Sken		return 0;
893229997Sken	else
894229997Sken		return ENOMEM;
895229997Sken}
896229997Sken
897229997Skenstatic int
898229997Skenpccard_get_resource(device_t dev, device_t child, int type, int rid,
899229997Sken    u_long *startp, u_long *countp)
900229997Sken{
901229997Sken	struct pccard_ivar *devi = PCCARD_IVAR(child);
902229997Sken	struct resource_list *rl = &devi->resources;
903229997Sken	struct resource_list_entry *rle;
904229997Sken
905229997Sken	rle = resource_list_find(rl, type, rid);
906229997Sken	if (rle == NULL)
907229997Sken		return (ENOENT);
908229997Sken
909229997Sken	if (startp != NULL)
910229997Sken		*startp = rle->start;
911229997Sken	if (countp != NULL)
912229997Sken		*countp = rle->count;
913229997Sken
914229997Sken	return (0);
915229997Sken}
916229997Sken
917229997Skenstatic void
918229997Skenpccard_delete_resource(device_t dev, device_t child, int type, int rid)
919229997Sken{
920229997Sken	struct pccard_ivar *devi = PCCARD_IVAR(child);
921229997Sken	struct resource_list *rl = &devi->resources;
922229997Sken	resource_list_delete(rl, type, rid);
923229997Sken}
924229997Sken
925229997Skenstatic int
926229997Skenpccard_set_res_flags(device_t dev, device_t child, int type, int rid,
927229997Sken    uint32_t flags)
928229997Sken{
929229997Sken	return (CARD_SET_RES_FLAGS(device_get_parent(dev), child, type,
930229997Sken	    rid, flags));
931229997Sken}
932229997Sken
933229997Skenstatic int
934229997Skenpccard_set_memory_offset(device_t dev, device_t child, int rid,
935229997Sken    uint32_t offset, uint32_t *deltap)
936229997Sken
937229997Sken{
938229997Sken	return (CARD_SET_MEMORY_OFFSET(device_get_parent(dev), child, rid,
939229997Sken	    offset, deltap));
940229997Sken}
941229997Sken
942229997Skenstatic void
943229997Skenpccard_probe_nomatch(device_t bus, device_t child)
944229997Sken{
945229997Sken	struct pccard_ivar *devi = PCCARD_IVAR(child);
946229997Sken	struct pccard_function *pf = devi->pf;
947229997Sken	struct pccard_softc *sc = PCCARD_SOFTC(bus);
948229997Sken	int i;
949229997Sken
950229997Sken	device_printf(bus, "<unknown card>");
951229997Sken	printf(" (manufacturer=0x%04x, product=0x%04x, function_type=%d) "
952229997Sken	    "at function %d\n", sc->card.manufacturer, sc->card.product,
953229997Sken	    pf->function, pf->number);
954229997Sken	device_printf(bus, "   CIS info: ");
955229997Sken	for (i = 0; sc->card.cis1_info[i] != NULL && i < 4; i++)
956229997Sken		printf("%s%s", i > 0 ? ", " : "", sc->card.cis1_info[i]);
957229997Sken	printf("\n");
958229997Sken	return;
959229997Sken}
960229997Sken
961229997Skenstatic int
962229997Skenpccard_child_location_str(device_t bus, device_t child, char *buf,
963229997Sken    size_t buflen)
964229997Sken{
965229997Sken	struct pccard_ivar *devi = PCCARD_IVAR(child);
966229997Sken	struct pccard_function *pf = devi->pf;
967229997Sken
968229997Sken	snprintf(buf, buflen, "function=%d", pf->number);
969229997Sken	return (0);
970229997Sken}
971229997Sken
972229997Sken/* XXX Maybe this should be in subr_bus? */
973229997Skenstatic void
974229997Skenpccard_safe_quote(char *dst, const char *src, size_t len)
975229997Sken{
976229997Sken	char *walker = dst, *ep = dst + len - 1;
977229997Sken
978229997Sken	if (len == 0)
979229997Sken		return;
980229997Sken	while (src != NULL && walker < ep)
981229997Sken	{
982229997Sken		if (*src == '"') {
983229997Sken			if (ep - walker < 2)
984229997Sken				break;
985229997Sken			*walker++ = '\\';
986229997Sken		}
987229997Sken		*walker++ = *src++;
988229997Sken	}
989229997Sken	*walker = '\0';
990229997Sken}
991229997Sken
992229997Skenstatic int
993229997Skenpccard_child_pnpinfo_str(device_t bus, device_t child, char *buf,
994229997Sken    size_t buflen)
995229997Sken{
996229997Sken	struct pccard_ivar *devi = PCCARD_IVAR(child);
997229997Sken	struct pccard_function *pf = devi->pf;
998229997Sken	struct pccard_softc *sc = PCCARD_SOFTC(bus);
999229997Sken	char cis0[128], cis1[128];
1000229997Sken
1001229997Sken	pccard_safe_quote(cis0, sc->card.cis1_info[0], sizeof(cis0));
1002229997Sken	pccard_safe_quote(cis1, sc->card.cis1_info[1], sizeof(cis1));
1003229997Sken	snprintf(buf, buflen, "manufacturer=0x%04x product=0x%04x "
1004229997Sken	    "cisvendor=\"%s\" cisproduct=\"%s\" function_type=%d",
1005229997Sken	    sc->card.manufacturer, sc->card.product, cis0, cis1, pf->function);
1006229997Sken	return (0);
1007229997Sken}
1008229997Sken
1009229997Skenstatic int
1010229997Skenpccard_read_ivar(device_t bus, device_t child, int which, u_char *result)
1011229997Sken{
1012229997Sken	struct pccard_ivar *devi = PCCARD_IVAR(child);
1013229997Sken	struct pccard_function *pf = devi->pf;
1014229997Sken	struct pccard_softc *sc = PCCARD_SOFTC(bus);
1015229997Sken
1016229997Sken	if (!pf)
1017229997Sken		panic("No pccard function pointer");
1018229997Sken	switch (which) {
1019229997Sken	default:
1020229997Sken		return (EINVAL);
1021229997Sken	case PCCARD_IVAR_ETHADDR:
1022229997Sken		bcopy(pf->pf_funce_lan_nid, result, ETHER_ADDR_LEN);
1023229997Sken		break;
1024229997Sken	case PCCARD_IVAR_VENDOR:
1025229997Sken		*(uint32_t *)result = sc->card.manufacturer;
1026229997Sken		break;
1027229997Sken	case PCCARD_IVAR_PRODUCT:
1028229997Sken		*(uint32_t *)result = sc->card.product;
1029229997Sken		break;
1030229997Sken	case PCCARD_IVAR_PRODEXT:
1031229997Sken		*(uint16_t *)result = sc->card.prodext;
1032229997Sken		break;
1033229997Sken	case PCCARD_IVAR_FUNCTION:
1034229997Sken		*(uint32_t *)result = pf->function;
1035229997Sken		break;
1036229997Sken	case PCCARD_IVAR_FUNCTION_NUMBER:
1037229997Sken		*(uint32_t *)result = pf->number;
1038229997Sken		break;
1039229997Sken	case PCCARD_IVAR_VENDOR_STR:
1040229997Sken		*(const char **)result = sc->card.cis1_info[0];
1041229997Sken		break;
1042229997Sken	case PCCARD_IVAR_PRODUCT_STR:
1043229997Sken		*(const char **)result = sc->card.cis1_info[1];
1044229997Sken		break;
1045229997Sken	case PCCARD_IVAR_CIS3_STR:
1046229997Sken		*(const char **)result = sc->card.cis1_info[2];
1047229997Sken		break;
1048229997Sken	case PCCARD_IVAR_CIS4_STR:
1049229997Sken		*(const char **)result = sc->card.cis1_info[3];
1050229997Sken		break;
1051229997Sken	}
1052229997Sken	return (0);
1053229997Sken}
1054229997Sken
1055229997Skenstatic void
1056229997Skenpccard_driver_added(device_t dev, driver_t *driver)
1057229997Sken{
1058229997Sken	struct pccard_softc *sc = PCCARD_SOFTC(dev);
1059229997Sken	struct pccard_function *pf;
1060229997Sken	device_t child;
1061229997Sken
1062229997Sken	STAILQ_FOREACH(pf, &sc->card.pf_head, pf_list) {
1063229997Sken		if (STAILQ_EMPTY(&pf->cfe_head))
1064229997Sken			continue;
1065229997Sken		child = pf->dev;
1066229997Sken		if (device_get_state(child) != DS_NOTPRESENT)
1067229997Sken			continue;
1068229997Sken		if (pccard_function_enable(pf) == 0 &&
1069229997Sken		    device_probe_and_attach(child) == 0) {
1070229997Sken			DEVPRINTF((sc->dev, "function %d CCR at %d "
1071229997Sken			    "offset %x: %x %x %x %x, %x %x %x %x, %x\n",
1072229997Sken			    pf->number, pf->pf_ccr_window, pf->pf_ccr_offset,
1073229997Sken			    pccard_ccr_read(pf, 0x00),
1074229997Sken			pccard_ccr_read(pf, 0x02), pccard_ccr_read(pf, 0x04),
1075229997Sken			pccard_ccr_read(pf, 0x06), pccard_ccr_read(pf, 0x0A),
1076229997Sken			pccard_ccr_read(pf, 0x0C), pccard_ccr_read(pf, 0x0E),
1077229997Sken			pccard_ccr_read(pf, 0x10), pccard_ccr_read(pf, 0x12)));
1078229997Sken		} else {
1079229997Sken			if (pf->cfe != NULL)
1080229997Sken				pccard_function_disable(pf);
1081229997Sken		}
1082229997Sken	}
1083229997Sken	return;
1084229997Sken}
1085229997Sken
1086229997Skenstatic struct resource *
1087229997Skenpccard_alloc_resource(device_t dev, device_t child, int type, int *rid,
1088229997Sken    u_long start, u_long end, u_long count, u_int flags)
1089229997Sken{
1090229997Sken	struct pccard_ivar *dinfo;
1091229997Sken	struct resource_list_entry *rle = 0;
1092229997Sken	int passthrough = (device_get_parent(child) != dev);
1093229997Sken	int isdefault = (start == 0 && end == ~0UL && count == 1);
1094229997Sken	struct resource *r = NULL;
1095229997Sken
1096229997Sken	/* XXX I'm no longer sure this is right */
1097229997Sken	if (passthrough) {
1098229997Sken		return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
1099229997Sken		    type, rid, start, end, count, flags));
1100229997Sken	}
1101229997Sken
1102229997Sken	dinfo = device_get_ivars(child);
1103229997Sken	rle = resource_list_find(&dinfo->resources, type, *rid);
1104229997Sken
1105229997Sken	if (rle == NULL && isdefault)
1106229997Sken		return (NULL);	/* no resource of that type/rid */
1107229997Sken	if (rle == NULL || rle->res == NULL) {
1108229997Sken		/* XXX Need to adjust flags */
1109229997Sken		r = bus_alloc_resource(dev, type, rid, start, end,
1110229997Sken		  count, flags);
1111229997Sken		if (r == NULL)
1112229997Sken		    goto bad;
1113229997Sken		resource_list_add(&dinfo->resources, type, *rid,
1114229997Sken		  rman_get_start(r), rman_get_end(r), count);
1115229997Sken		rle = resource_list_find(&dinfo->resources, type, *rid);
1116229997Sken		if (!rle)
1117229997Sken		    goto bad;
1118229997Sken		rle->res = r;
1119229997Sken	}
1120229997Sken	/*
1121229997Sken	 * If dev doesn't own the device, then we can't give this device
1122229997Sken	 * out.
1123229997Sken	 */
1124229997Sken	if (rman_get_device(rle->res) != dev)
1125229997Sken		return (NULL);
1126229997Sken	rman_set_device(rle->res, child);
1127229997Sken	if (flags & RF_ACTIVE)
1128229997Sken		BUS_ACTIVATE_RESOURCE(dev, child, type, *rid, rle->res);
1129229997Sken	return (rle->res);
1130229997Skenbad:;
1131229997Sken	device_printf(dev, "WARNING: Resource not reserved by pccard\n");
1132229997Sken	return (NULL);
1133229997Sken}
1134229997Sken
1135229997Skenstatic int
1136229997Skenpccard_release_resource(device_t dev, device_t child, int type, int rid,
1137229997Sken    struct resource *r)
1138229997Sken{
1139229997Sken	struct pccard_ivar *dinfo;
1140229997Sken	int passthrough = (device_get_parent(child) != dev);
1141229997Sken	struct resource_list_entry *rle = 0;
1142229997Sken
1143229997Sken	if (passthrough)
1144229997Sken		return BUS_RELEASE_RESOURCE(device_get_parent(dev), child,
1145229997Sken		    type, rid, r);
1146229997Sken
1147229997Sken	dinfo = device_get_ivars(child);
1148229997Sken
1149229997Sken	rle = resource_list_find(&dinfo->resources, type, rid);
1150229997Sken
1151229997Sken	if (!rle) {
1152229997Sken		device_printf(dev, "Allocated resource not found, "
1153229997Sken		    "%d %x %lx %lx\n",
1154229997Sken		    type, rid, rman_get_start(r), rman_get_size(r));
1155229997Sken		return ENOENT;
1156229997Sken	}
1157229997Sken	if (!rle->res) {
1158229997Sken		device_printf(dev, "Allocated resource not recorded\n");
1159229997Sken		return ENOENT;
1160229997Sken	}
1161229997Sken	/*
1162229997Sken	 * Deactivate the resource (since it is being released), and
1163229997Sken	 * assign it to the bus.
1164229997Sken	 */
1165229997Sken	BUS_DEACTIVATE_RESOURCE(dev, child, type, rid, rle->res);
1166229997Sken	rman_set_device(rle->res, dev);
1167229997Sken	return (0);
1168229997Sken}
1169229997Sken
1170229997Skenstatic void
1171229997Skenpccard_child_detached(device_t parent, device_t dev)
1172229997Sken{
1173229997Sken	struct pccard_ivar *ivar = PCCARD_IVAR(dev);
1174229997Sken	struct pccard_function *pf = ivar->pf;
1175229997Sken
1176229997Sken	pccard_function_disable(pf);
1177229997Sken}
1178229997Sken
1179229997Skenstatic int
1180229997Skenpccard_intr(void *arg)
1181229997Sken{
1182229997Sken	struct pccard_function *pf = (struct pccard_function*) arg;
1183229997Sken	int reg;
1184229997Sken	int doisr = 1;
1185229997Sken
1186229997Sken	/*
1187229997Sken	 * MFC cards know if they interrupted, so we have to ack the
1188229997Sken	 * interrupt and call the ISR.  Non-MFC cards don't have these
1189229997Sken	 * bits, so they always get called.  Many non-MFC cards have
1190229997Sken	 * this bit set always upon read, but some do not.
1191229997Sken	 *
1192229997Sken	 * We always ack the interrupt, even if there's no ISR
1193229997Sken	 * for the card.  This is done on the theory that acking
1194229997Sken	 * the interrupt will pacify the card enough to keep an
1195229997Sken	 * interrupt storm from happening.  Of course this won't
1196229997Sken	 * help in the non-MFC case.
1197229997Sken	 *
1198229997Sken	 * This has no impact for MPSAFEness of the client drivers.
1199229997Sken	 * We register this with whatever flags the intr_handler
1200229997Sken	 * was registered with.  All these functions are MPSAFE.
1201229997Sken	 */
1202229997Sken	if (pccard_mfc(pf->sc)) {
1203229997Sken		reg = pccard_ccr_read(pf, PCCARD_CCR_STATUS);
1204229997Sken		if (reg & PCCARD_CCR_STATUS_INTR)
1205229997Sken			pccard_ccr_write(pf, PCCARD_CCR_STATUS,
1206229997Sken			    reg & ~PCCARD_CCR_STATUS_INTR);
1207229997Sken		else
1208229997Sken			doisr = 0;
1209229997Sken	}
1210229997Sken	if (doisr) {
1211229997Sken		if (pf->filt_handler != NULL)
1212229997Sken			pf->filt_handler(pf->intr_handler_arg);
1213229997Sken		else
1214229997Sken			pf->intr_handler(pf->intr_handler_arg);
1215229997Sken	}
1216229997Sken	return (FILTER_HANDLED);
1217229997Sken}
1218229997Sken
1219229997Skenstatic int
1220229997Skenpccard_setup_intr(device_t dev, device_t child, struct resource *irq,
1221229997Sken    int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg,
1222229997Sken    void **cookiep)
1223229997Sken{
1224229997Sken	struct pccard_softc *sc = PCCARD_SOFTC(dev);
1225229997Sken	struct pccard_ivar *ivar = PCCARD_IVAR(child);
1226229997Sken	struct pccard_function *pf = ivar->pf;
1227229997Sken	int err;
1228229997Sken
1229229997Sken	if (pf->intr_handler != NULL)
1230229997Sken		panic("Only one interrupt handler per function allowed");
1231229997Sken	if (filt != NULL && intr != NULL)
1232229997Sken		return (EINVAL);
1233229997Sken	if (filt != NULL)
1234229997Sken		err = bus_generic_setup_intr(dev, child, irq, flags,
1235229997Sken		    pccard_intr, NULL, pf, cookiep);
1236229997Sken	else
1237229997Sken		err = bus_generic_setup_intr(dev, child, irq, flags,
1238229997Sken		    NULL, (driver_intr_t *)pccard_intr, pf, cookiep);
1239229997Sken	if (err != 0)
1240229997Sken		return (err);
1241229997Sken	pf->filt_handler = filt;
1242229997Sken	pf->intr_handler = intr;
1243229997Sken	pf->intr_handler_arg = arg;
1244229997Sken	pf->intr_handler_cookie = *cookiep;
1245229997Sken	if (pccard_mfc(sc)) {
1246229997Sken		pccard_ccr_write(pf, PCCARD_CCR_OPTION,
1247229997Sken		    pccard_ccr_read(pf, PCCARD_CCR_OPTION) |
1248229997Sken		    PCCARD_CCR_OPTION_IREQ_ENABLE);
1249229997Sken	}
1250229997Sken	return (0);
1251229997Sken}
1252229997Sken
1253229997Skenstatic int
1254229997Skenpccard_teardown_intr(device_t dev, device_t child, struct resource *r,
1255229997Sken    void *cookie)
1256229997Sken{
1257229997Sken	struct pccard_softc *sc = PCCARD_SOFTC(dev);
1258229997Sken	struct pccard_ivar *ivar = PCCARD_IVAR(child);
1259229997Sken	struct pccard_function *pf = ivar->pf;
1260229997Sken	int ret;
1261229997Sken
1262229997Sken	if (pccard_mfc(sc)) {
1263229997Sken		pccard_ccr_write(pf, PCCARD_CCR_OPTION,
1264229997Sken		    pccard_ccr_read(pf, PCCARD_CCR_OPTION) &
1265229997Sken		    ~PCCARD_CCR_OPTION_IREQ_ENABLE);
1266229997Sken	}
1267229997Sken	ret = bus_generic_teardown_intr(dev, child, r, cookie);
1268229997Sken	if (ret == 0) {
1269229997Sken		pf->intr_handler = NULL;
1270229997Sken		pf->intr_handler_arg = NULL;
1271229997Sken		pf->intr_handler_cookie = NULL;
1272229997Sken	}
1273229997Sken
1274229997Sken	return (ret);
1275229997Sken}
1276229997Sken
1277229997Skenstatic int
1278229997Skenpccard_activate_resource(device_t brdev, device_t child, int type, int rid,
1279229997Sken    struct resource *r)
1280229997Sken{
1281229997Sken	struct pccard_ivar *ivar = PCCARD_IVAR(child);
1282229997Sken	struct pccard_function *pf = ivar->pf;
1283229997Sken
1284229997Sken	switch(type) {
1285229997Sken	case SYS_RES_IOPORT:
1286229997Sken		/*
1287229997Sken		 * We need to adjust IOBASE[01] and IOSIZE if we're an MFC
1288229997Sken		 * card.
1289229997Sken		 */
1290229997Sken		if (pccard_mfc(pf->sc))
1291229997Sken			pccard_mfc_adjust_iobase(pf, rman_get_start(r), 0,
1292229997Sken			    rman_get_size(r));
1293229997Sken		break;
1294229997Sken	default:
1295229997Sken		break;
1296229997Sken	}
1297229997Sken	return (bus_generic_activate_resource(brdev, child, type, rid, r));
1298229997Sken}
1299229997Sken
1300229997Skenstatic int
1301229997Skenpccard_deactivate_resource(device_t brdev, device_t child, int type,
1302229997Sken    int rid, struct resource *r)
1303229997Sken{
1304229997Sken	/* XXX undo pccard_activate_resource? XXX */
1305229997Sken	return (bus_generic_deactivate_resource(brdev, child, type, rid, r));
1306229997Sken}
1307229997Sken
1308229997Skenstatic int
1309229997Skenpccard_attr_read_impl(device_t brdev, device_t child, uint32_t offset,
1310229997Sken    uint8_t *val)
1311229997Sken{
1312229997Sken	struct pccard_ivar *devi = PCCARD_IVAR(child);
1313229997Sken	struct pccard_function *pf = devi->pf;
1314229997Sken
1315229997Sken	/*
1316229997Sken	 * Optimization.  Most of the time, devices want to access
1317229997Sken	 * the same page of the attribute memory that the CCR is in.
1318229997Sken	 * We take advantage of this fact here.
1319229997Sken	 */
1320229997Sken	if (offset / PCCARD_MEM_PAGE_SIZE ==
1321229997Sken	    pf->ccr_base / PCCARD_MEM_PAGE_SIZE)
1322229997Sken		*val = bus_space_read_1(pf->pf_ccrt, pf->pf_ccrh,
1323229997Sken		    offset % PCCARD_MEM_PAGE_SIZE);
1324229997Sken	else {
1325229997Sken		CARD_SET_MEMORY_OFFSET(brdev, child, pf->ccr_rid, offset,
1326229997Sken		    &offset);
1327229997Sken		*val = bus_space_read_1(pf->pf_ccrt, pf->pf_ccrh, offset);
1328229997Sken		CARD_SET_MEMORY_OFFSET(brdev, child, pf->ccr_rid, pf->ccr_base,
1329229997Sken		    &offset);
1330229997Sken	}
1331229997Sken	return 0;
1332229997Sken}
1333229997Sken
1334229997Skenstatic int
1335229997Skenpccard_attr_write_impl(device_t brdev, device_t child, uint32_t offset,
1336229997Sken    uint8_t val)
1337229997Sken{
1338229997Sken	struct pccard_ivar *devi = PCCARD_IVAR(child);
1339229997Sken	struct pccard_function *pf = devi->pf;
1340229997Sken
1341229997Sken	/*
1342229997Sken	 * Optimization.  Most of the time, devices want to access
1343229997Sken	 * the same page of the attribute memory that the CCR is in.
1344229997Sken	 * We take advantage of this fact here.
1345229997Sken	 */
1346229997Sken	if (offset / PCCARD_MEM_PAGE_SIZE ==
1347229997Sken	    pf->ccr_base / PCCARD_MEM_PAGE_SIZE)
1348229997Sken		bus_space_write_1(pf->pf_ccrt, pf->pf_ccrh,
1349229997Sken		    offset % PCCARD_MEM_PAGE_SIZE, val);
1350229997Sken	else {
1351229997Sken		CARD_SET_MEMORY_OFFSET(brdev, child, pf->ccr_rid, offset,
1352229997Sken		    &offset);
1353229997Sken		bus_space_write_1(pf->pf_ccrt, pf->pf_ccrh, offset, val);
1354229997Sken		CARD_SET_MEMORY_OFFSET(brdev, child, pf->ccr_rid, pf->ccr_base,
1355229997Sken		    &offset);
1356229997Sken	}
1357229997Sken
1358229997Sken	return 0;
1359229997Sken}
1360229997Sken
1361229997Skenstatic int
1362229997Skenpccard_ccr_read_impl(device_t brdev, device_t child, uint32_t offset,
1363229997Sken    uint8_t *val)
1364229997Sken{
1365229997Sken	struct pccard_ivar *devi = PCCARD_IVAR(child);
1366229997Sken
1367229997Sken	*val = pccard_ccr_read(devi->pf, offset);
1368229997Sken	device_printf(child, "ccr_read of %#x (%#x) is %#x\n", offset,
1369229997Sken	  devi->pf->pf_ccr_offset, *val);
1370229997Sken	return 0;
1371229997Sken}
1372229997Sken
1373229997Skenstatic int
1374229997Skenpccard_ccr_write_impl(device_t brdev, device_t child, uint32_t offset,
1375229997Sken    uint8_t val)
1376229997Sken{
1377229997Sken	struct pccard_ivar *devi = PCCARD_IVAR(child);
1378229997Sken	struct pccard_function *pf = devi->pf;
1379229997Sken
1380229997Sken	/*
1381229997Sken	 * Can't use pccard_ccr_write since client drivers may access
1382229997Sken	 * registers not contained in the 'mask' if they are non-standard.
1383229997Sken	 */
1384229997Sken	device_printf(child, "ccr_write of %#x to %#x (%#x)\n", val, offset,
1385229997Sken	  devi->pf->pf_ccr_offset);
1386229997Sken	bus_space_write_1(pf->pf_ccrt, pf->pf_ccrh, pf->pf_ccr_offset + offset,
1387229997Sken	    val);
1388229997Sken	return 0;
1389229997Sken}
1390229997Sken
1391229997Sken
1392229997Skenstatic device_method_t pccard_methods[] = {
1393229997Sken	/* Device interface */
1394229997Sken	DEVMETHOD(device_probe,		pccard_probe),
1395229997Sken	DEVMETHOD(device_attach,	pccard_attach),
1396229997Sken	DEVMETHOD(device_detach,	pccard_detach),
1397229997Sken	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
1398229997Sken	DEVMETHOD(device_suspend,	pccard_suspend),
1399229997Sken	DEVMETHOD(device_resume,	pccard_resume),
1400229997Sken
1401229997Sken	/* Bus interface */
1402229997Sken	DEVMETHOD(bus_print_child,	pccard_print_child),
1403229997Sken	DEVMETHOD(bus_driver_added,	pccard_driver_added),
1404229997Sken	DEVMETHOD(bus_child_detached,	pccard_child_detached),
1405229997Sken	DEVMETHOD(bus_alloc_resource,	pccard_alloc_resource),
1406229997Sken	DEVMETHOD(bus_release_resource,	pccard_release_resource),
1407229997Sken	DEVMETHOD(bus_activate_resource, pccard_activate_resource),
1408229997Sken	DEVMETHOD(bus_deactivate_resource, pccard_deactivate_resource),
1409229997Sken	DEVMETHOD(bus_setup_intr,	pccard_setup_intr),
1410229997Sken	DEVMETHOD(bus_teardown_intr,	pccard_teardown_intr),
1411229997Sken	DEVMETHOD(bus_set_resource,	pccard_set_resource),
1412229997Sken	DEVMETHOD(bus_get_resource,	pccard_get_resource),
1413229997Sken	DEVMETHOD(bus_delete_resource,	pccard_delete_resource),
1414229997Sken	DEVMETHOD(bus_probe_nomatch,	pccard_probe_nomatch),
1415229997Sken	DEVMETHOD(bus_read_ivar,	pccard_read_ivar),
1416229997Sken	DEVMETHOD(bus_child_pnpinfo_str, pccard_child_pnpinfo_str),
1417229997Sken	DEVMETHOD(bus_child_location_str, pccard_child_location_str),
1418229997Sken
1419229997Sken	/* Card Interface */
1420229997Sken	DEVMETHOD(card_set_res_flags,	pccard_set_res_flags),
1421229997Sken	DEVMETHOD(card_set_memory_offset, pccard_set_memory_offset),
1422229997Sken	DEVMETHOD(card_attach_card,	pccard_attach_card),
1423229997Sken	DEVMETHOD(card_detach_card,	pccard_detach_card),
1424229997Sken	DEVMETHOD(card_do_product_lookup, pccard_do_product_lookup),
1425229997Sken	DEVMETHOD(card_cis_scan,	pccard_scan_cis),
1426229997Sken	DEVMETHOD(card_attr_read,	pccard_attr_read_impl),
1427229997Sken	DEVMETHOD(card_attr_write,	pccard_attr_write_impl),
1428229997Sken	DEVMETHOD(card_ccr_read,	pccard_ccr_read_impl),
1429229997Sken	DEVMETHOD(card_ccr_write,	pccard_ccr_write_impl),
1430229997Sken
1431229997Sken	{ 0, 0 }
1432229997Sken};
1433229997Sken
1434229997Skenstatic driver_t pccard_driver = {
1435229997Sken	"pccard",
1436229997Sken	pccard_methods,
1437229997Sken	sizeof(struct pccard_softc)
1438229997Sken};
1439229997Sken
1440229997Skendevclass_t	pccard_devclass;
1441229997Sken
1442229997Sken/* Maybe we need to have a slot device? */
1443229997SkenDRIVER_MODULE(pccard, pcic, pccard_driver, pccard_devclass, 0, 0);
1444229997SkenDRIVER_MODULE(pccard, cbb, pccard_driver, pccard_devclass, 0, 0);
1445229997SkenMODULE_VERSION(pccard, 1);
1446229997Sken