pccard.c revision 113242
1132451Sroberto/*	$NetBSD: pcmcia.c,v 1.23 2000/07/28 19:17:02 drochner Exp $	*/
2132451Sroberto/* $FreeBSD: head/sys/dev/pccard/pccard.c 113242 2003-04-08 07:02:03Z imp $ */
3132451Sroberto
4132451Sroberto/*
5132451Sroberto * Copyright (c) 1997 Marc Horowitz.  All rights reserved.
6132451Sroberto *
7132451Sroberto * Redistribution and use in source and binary forms, with or without
8132451Sroberto * modification, are permitted provided that the following conditions
9132451Sroberto * are met:
10132451Sroberto * 1. Redistributions of source code must retain the above copyright
11132451Sroberto *    notice, this list of conditions and the following disclaimer.
12132451Sroberto * 2. Redistributions in binary form must reproduce the above copyright
13132451Sroberto *    notice, this list of conditions and the following disclaimer in the
14132451Sroberto *    documentation and/or other materials provided with the distribution.
15132451Sroberto * 3. All advertising materials mentioning features or use of this software
16132451Sroberto *    must display the following acknowledgement:
17132451Sroberto *	This product includes software developed by Marc Horowitz.
18132451Sroberto * 4. The name of the author may not be used to endorse or promote products
19132451Sroberto *    derived from this software without specific prior written permission.
20132451Sroberto *
21132451Sroberto * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22132451Sroberto * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23132451Sroberto * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24132451Sroberto * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25132451Sroberto * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26132451Sroberto * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27132451Sroberto * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28132451Sroberto * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29132451Sroberto * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30132451Sroberto * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31132451Sroberto */
32132451Sroberto
33132451Sroberto#include <sys/param.h>
34132451Sroberto#include <sys/systm.h>
35132451Sroberto#include <sys/malloc.h>
36132451Sroberto#include <sys/module.h>
37132451Sroberto#include <sys/kernel.h>
38132451Sroberto#include <sys/queue.h>
39132451Sroberto#include <sys/sysctl.h>
40132451Sroberto#include <sys/types.h>
41132451Sroberto
42132451Sroberto#include <sys/bus.h>
43132451Sroberto#include <machine/bus.h>
44132451Sroberto#include <sys/rman.h>
45132451Sroberto#include <machine/resource.h>
46132451Sroberto
47132451Sroberto#include <net/ethernet.h>
48132451Sroberto
49132451Sroberto#include <dev/pccard/pccardreg.h>
50132451Sroberto#include <dev/pccard/pccardvar.h>
51132451Sroberto
52132451Sroberto#include "power_if.h"
53132451Sroberto#include "card_if.h"
54132451Sroberto
55132451Sroberto#define PCCARDDEBUG
56132451Sroberto
57132451Sroberto/* sysctl vars */
58132451SrobertoSYSCTL_NODE(_hw, OID_AUTO, pccard, CTLFLAG_RD, 0, "PCCARD parameters");
59132451Sroberto
60132451Srobertoint	pccard_debug = 0;
61132451SrobertoTUNABLE_INT("hw.pccard.debug", &pccard_debug);
62132451SrobertoSYSCTL_INT(_hw_pccard, OID_AUTO, debug, CTLFLAG_RW,
63132451Sroberto    &pccard_debug, 0,
64132451Sroberto  "pccard debug");
65132451Sroberto
66132451Srobertoint	pccard_cis_debug = 0;
67132451SrobertoTUNABLE_INT("hw.pccard.cis_debug", &pccard_cis_debug);
68132451SrobertoSYSCTL_INT(_hw_pccard, OID_AUTO, cis_debug, CTLFLAG_RW,
69132451Sroberto    &pccard_cis_debug, 0, "pccard CIS debug");
70132451Sroberto
71132451Sroberto#ifdef PCCARDDEBUG
72132451Sroberto#define	DPRINTF(arg) if (pccard_debug) printf arg
73132451Sroberto#define	DEVPRINTF(arg) if (pccard_debug) device_printf arg
74132451Sroberto#define PRVERBOSE(arg) printf arg
75132451Sroberto#define DEVPRVERBOSE(arg) device_printf arg
76132451Sroberto#else
77132451Sroberto#define	DPRINTF(arg)
78132451Sroberto#define	DEVPRINTF(arg)
79132451Sroberto#define PRVERBOSE(arg) if (bootverbose) printf arg
80132451Sroberto#define DEVPRVERBOSE(arg) if (bootverbose) device_printf arg
81132451Sroberto#endif
82132451Sroberto
83132451Srobertostatic int	pccard_ccr_read(struct pccard_function *pf, int ccr);
84132451Srobertostatic void	pccard_ccr_write(struct pccard_function *pf, int ccr, int val);
85132451Srobertostatic int	pccard_attach_card(device_t dev);
86132451Srobertostatic int	pccard_detach_card(device_t dev);
87132451Srobertostatic int	pccard_card_gettype(device_t dev, int *type);
88132451Srobertostatic void	pccard_function_init(struct pccard_function *pf);
89132451Srobertostatic void	pccard_function_free(struct pccard_function *pf);
90132451Srobertostatic int	pccard_function_enable(struct pccard_function *pf);
91132451Srobertostatic void	pccard_function_disable(struct pccard_function *pf);
92132451Srobertostatic int	pccard_compat_do_probe(device_t bus, device_t dev);
93132451Srobertostatic int	pccard_compat_do_attach(device_t bus, device_t dev);
94132451Srobertostatic int	pccard_add_children(device_t dev, int busno);
95132451Srobertostatic int	pccard_probe(device_t dev);
96132451Srobertostatic int	pccard_attach(device_t dev);
97280849Scystatic int	pccard_detach(device_t dev);
98280849Scystatic void	pccard_print_resources(struct resource_list *rl,
99132451Sroberto		    const char *name, int type, int count, const char *format);
100132451Srobertostatic int	pccard_print_child(device_t dev, device_t child);
101132451Srobertostatic int	pccard_set_resource(device_t dev, device_t child, int type,
102132451Sroberto		    int rid, u_long start, u_long count);
103132451Srobertostatic int	pccard_get_resource(device_t dev, device_t child, int type,
104132451Sroberto		    int rid, u_long *startp, u_long *countp);
105132451Srobertostatic void	pccard_delete_resource(device_t dev, device_t child, int type,
106132451Sroberto		    int rid);
107132451Srobertostatic int	pccard_set_res_flags(device_t dev, device_t child, int type,
108132451Sroberto		    int rid, u_int32_t flags);
109132451Srobertostatic int	pccard_set_memory_offset(device_t dev, device_t child, int rid,
110132451Sroberto		    u_int32_t offset, u_int32_t *deltap);
111132451Srobertostatic void	pccard_probe_nomatch(device_t cbdev, device_t child);
112132451Srobertostatic int	pccard_read_ivar(device_t bus, device_t child, int which,
113132451Sroberto		    u_char *result);
114132451Srobertostatic void	pccard_driver_added(device_t dev, driver_t *driver);
115132451Srobertostatic struct resource *pccard_alloc_resource(device_t dev,
116132451Sroberto		    device_t child, int type, int *rid, u_long start,
117132451Sroberto		    u_long end, u_long count, u_int flags);
118132451Srobertostatic int	pccard_release_resource(device_t dev, device_t child, int type,
119132451Sroberto		    int rid, struct resource *r);
120132451Srobertostatic void	pccard_child_detached(device_t parent, device_t dev);
121132451Srobertostatic void	pccard_intr(void *arg);
122132451Srobertostatic int	pccard_setup_intr(device_t dev, device_t child,
123132451Sroberto		    struct resource *irq, int flags, driver_intr_t *intr,
124132451Sroberto		    void *arg, void **cookiep);
125132451Srobertostatic int	pccard_teardown_intr(device_t dev, device_t child,
126132451Sroberto		    struct resource *r, void *cookie);
127132451Sroberto
128132451Srobertostatic const struct pccard_product *
129132451Srobertopccard_do_product_lookup(device_t bus, device_t dev,
130132451Sroberto			 const struct pccard_product *tab, size_t ent_size,
131132451Sroberto			 pccard_product_match_fn matchfn);
132132451Sroberto
133132451Sroberto
134132451Srobertostatic int
135132451Srobertopccard_ccr_read(struct pccard_function *pf, int ccr)
136132451Sroberto{
137132451Sroberto	return (bus_space_read_1(pf->pf_ccrt, pf->pf_ccrh,
138132451Sroberto	    pf->pf_ccr_offset + ccr));
139132451Sroberto}
140132451Sroberto
141132451Srobertostatic void
142132451Srobertopccard_ccr_write(struct pccard_function *pf, int ccr, int val)
143132451Sroberto{
144132451Sroberto	if ((pf->ccr_mask) & (1 << (ccr / 2))) {
145132451Sroberto		bus_space_write_1(pf->pf_ccrt, pf->pf_ccrh,
146132451Sroberto		    pf->pf_ccr_offset + ccr, val);
147132451Sroberto	}
148132451Sroberto}
149132451Sroberto
150132451Srobertostatic int
151132451Srobertopccard_set_default_descr(device_t dev)
152132451Sroberto{
153132451Sroberto	char *vendorstr, *prodstr, *str;
154132451Sroberto
155	if (pccard_get_vendor_str(dev, &vendorstr))
156		return (0);
157	if (pccard_get_product_str(dev, &prodstr))
158		return (0);
159	str = malloc(strlen(vendorstr) + strlen(prodstr) + 2, M_DEVBUF,
160	    M_WAITOK);
161	sprintf(str, "%s %s", vendorstr, prodstr);
162	device_set_desc_copy(dev, str);
163	free(str, M_DEVBUF);
164	return (0);
165}
166
167static int
168pccard_attach_card(device_t dev)
169{
170	struct pccard_softc *sc = PCCARD_SOFTC(dev);
171	struct pccard_function *pf;
172	struct pccard_ivar *ivar;
173	device_t child;
174	int i;
175
176	/*
177	 * this is here so that when socket_enable calls gettype, trt happens
178	 */
179	STAILQ_INIT(&sc->card.pf_head);
180
181	DEVPRINTF((dev, "chip_socket_enable\n"));
182	POWER_ENABLE_SOCKET(device_get_parent(dev), dev);
183
184	DEVPRINTF((dev, "read_cis\n"));
185	pccard_read_cis(sc);
186
187	DEVPRINTF((dev, "check_cis_quirks\n"));
188	pccard_check_cis_quirks(dev);
189
190	/*
191	 * bail now if the card has no functions, or if there was an error in
192	 * the cis.
193	 */
194
195	if (sc->card.error) {
196		device_printf(dev, "CARD ERROR!\n");
197		return (1);
198	}
199	if (STAILQ_EMPTY(&sc->card.pf_head)) {
200		device_printf(dev, "Card has no functions!\n");
201		return (1);
202	}
203
204	if (bootverbose || pccard_debug)
205		pccard_print_cis(dev);
206
207	DEVPRINTF((dev, "functions scanning\n"));
208	i = -1;
209	STAILQ_FOREACH(pf, &sc->card.pf_head, pf_list) {
210		i++;
211		if (STAILQ_EMPTY(&pf->cfe_head)) {
212			device_printf(dev,
213			    "Function %d has no config entries.!\n", i);
214			continue;
215		}
216		pf->sc = sc;
217		pf->cfe = NULL;
218		pf->dev = NULL;
219	}
220	DEVPRINTF((dev, "Card has %d functions. pccard_mfc is %d\n", i + 1,
221	    pccard_mfc(sc)));
222
223	STAILQ_FOREACH(pf, &sc->card.pf_head, pf_list) {
224		if (STAILQ_EMPTY(&pf->cfe_head))
225			continue;
226		/*
227		 * In NetBSD, the drivers are responsible for activating
228		 * each function of a card.  I think that in FreeBSD we
229		 * want to activate them enough for the usual bus_*_resource
230		 * routines will do the right thing.  This many mean a
231		 * departure from the current NetBSD model.
232		 *
233		 * This seems to work well in practice for most cards.
234		 * However, there are two cases that are problematic.
235		 * If a driver wishes to pick and chose which config
236		 * entry to use, then this method falls down.  These
237		 * are usually older cards.  In addition, there are
238		 * some cards that have multiple hardware units on the
239		 * cards, but presents only one CIS chain.  These cards
240		 * are combination cards, but only one of these units
241		 * can be on at a time.
242		 */
243		ivar = malloc(sizeof(struct pccard_ivar), M_DEVBUF,
244		    M_WAITOK | M_ZERO);
245		child = device_add_child(dev, NULL, -1);
246		device_set_ivars(child, ivar);
247		ivar->fcn = pf;
248		pf->dev = child;
249		/*
250		 * XXX We might want to move the next two lines into
251		 * XXX the pccard interface layer.  For the moment, this
252		 * XXX is OK, but some drivers want to pick the config
253		 * XXX entry to use as well as some address tweaks (mostly
254		 * XXX due to bugs in decode logic that makes some
255		 * XXX addresses illegal or broken).
256		 */
257		pccard_function_init(pf);
258		if (sc->sc_enabled_count == 0)
259			POWER_ENABLE_SOCKET(device_get_parent(dev), dev);
260		if (pccard_function_enable(pf) == 0 &&
261		    pccard_set_default_descr(child) == 0 &&
262		    device_probe_and_attach(child) == 0) {
263			DEVPRINTF((sc->dev, "function %d CCR at %d "
264			    "offset %x: %x %x %x %x, %x %x %x %x, %x\n",
265			    pf->number, pf->pf_ccr_window, pf->pf_ccr_offset,
266			    pccard_ccr_read(pf, 0x00),
267			pccard_ccr_read(pf, 0x02), pccard_ccr_read(pf, 0x04),
268			pccard_ccr_read(pf, 0x06), pccard_ccr_read(pf, 0x0A),
269			pccard_ccr_read(pf, 0x0C), pccard_ccr_read(pf, 0x0E),
270			pccard_ccr_read(pf, 0x10), pccard_ccr_read(pf, 0x12)));
271		} else {
272			if (pf->cfe != NULL)
273				pccard_function_disable(pf);
274		}
275	}
276	return (0);
277}
278
279static int
280pccard_detach_card(device_t dev)
281{
282	struct pccard_softc *sc = PCCARD_SOFTC(dev);
283	struct pccard_function *pf;
284	struct pccard_config_entry *cfe;
285
286	/*
287	 * We are running on either the PCCARD socket's event thread
288	 * or in user context detaching a device by user request.
289	 */
290	STAILQ_FOREACH(pf, &sc->card.pf_head, pf_list) {
291		int state = device_get_state(pf->dev);
292
293		if (state == DS_ATTACHED || state == DS_BUSY)
294			device_detach(pf->dev);
295		if (pf->cfe != NULL)
296			pccard_function_disable(pf);
297		pccard_function_free(pf);
298		device_delete_child(dev, pf->dev);
299	}
300	if (sc->sc_enabled_count == 0)
301		POWER_DISABLE_SOCKET(device_get_parent(dev), dev);
302
303	while (NULL != (pf = STAILQ_FIRST(&sc->card.pf_head))) {
304		while (NULL != (cfe = STAILQ_FIRST(&pf->cfe_head))) {
305			STAILQ_REMOVE_HEAD(&pf->cfe_head, cfe_list);
306			free(cfe, M_DEVBUF);
307		}
308		STAILQ_REMOVE_HEAD(&sc->card.pf_head, pf_list);
309		free(pf, M_DEVBUF);
310	}
311	return (0);
312}
313
314static const struct pccard_product *
315pccard_do_product_lookup(device_t bus, device_t dev,
316    const struct pccard_product *tab, size_t ent_size,
317    pccard_product_match_fn matchfn)
318{
319	const struct pccard_product *ent;
320	int matches;
321	u_int32_t fcn;
322	u_int32_t vendor;
323	u_int32_t prod;
324	char *vendorstr;
325	char *prodstr;
326
327#ifdef DIAGNOSTIC
328	if (sizeof *ent > ent_size)
329		panic("pccard_product_lookup: bogus ent_size %jd",
330		    (intmax_t) ent_size);
331#endif
332	if (pccard_get_vendor(dev, &vendor))
333		return (NULL);
334	if (pccard_get_product(dev, &prod))
335		return (NULL);
336	if (pccard_get_function_number(dev, &fcn))
337		return (NULL);
338	if (pccard_get_vendor_str(dev, &vendorstr))
339		return (NULL);
340	if (pccard_get_product_str(dev, &prodstr))
341		return (NULL);
342	for (ent = tab; ent->pp_name != NULL; ent =
343	    (const struct pccard_product *) ((const char *) ent + ent_size)) {
344		matches = 1;
345		if (ent->pp_vendor == PCCARD_VENDOR_ANY &&
346		    ent->pp_product == PCCARD_PRODUCT_ANY &&
347		    ent->pp_cis[0] == NULL &&
348		    ent->pp_cis[1] == NULL) {
349			device_printf(dev,
350			    "Total wildcard entry ignored for %s\n",
351			    ent->pp_name);
352			continue;
353		}
354		if (matches && ent->pp_vendor != PCCARD_VENDOR_ANY &&
355		    vendor != ent->pp_vendor)
356			matches = 0;
357		if (matches && ent->pp_product != PCCARD_PRODUCT_ANY &&
358		    prod != ent->pp_product)
359			matches = 0;
360		if (matches && fcn != ent->pp_expfunc)
361			matches = 0;
362		if (matches && ent->pp_cis[0] &&
363		    strcmp(ent->pp_cis[0], vendorstr) != 0)
364			matches = 0;
365		if (matches && ent->pp_cis[1] &&
366		    strcmp(ent->pp_cis[1], prodstr) != 0)
367			matches = 0;
368		/* XXX need to match cis[2] and cis[3] also XXX */
369		if (matchfn != NULL)
370			matches = (*matchfn)(dev, ent, matches);
371		if (matches)
372			return (ent);
373	}
374	return (NULL);
375}
376
377static int
378pccard_card_gettype(device_t dev, int *type)
379{
380	struct pccard_softc *sc = PCCARD_SOFTC(dev);
381	struct pccard_function *pf;
382
383	/*
384	 * set the iftype to memory if this card has no functions (not yet
385	 * probed), or only one function, and that is not initialized yet or
386	 * that is memory.
387	 */
388	pf = STAILQ_FIRST(&sc->card.pf_head);
389	if (pf == NULL ||
390	    (STAILQ_NEXT(pf, pf_list) == NULL &&
391	    (pf->cfe == NULL || pf->cfe->iftype == PCCARD_IFTYPE_MEMORY)))
392		*type = PCCARD_IFTYPE_MEMORY;
393	else
394		*type = PCCARD_IFTYPE_IO;
395	return (0);
396}
397
398/*
399 * Initialize a PCCARD function.  May be called as long as the function is
400 * disabled.
401 *
402 * Note: pccard_function_init should not keep resources allocated.  It should
403 * only set them up ala isa pnp, set the values in the rl lists, and return.
404 * Any resource held after pccard_function_init is called is a bug.  However,
405 * the bus routines to get the resources also assume that pccard_function_init
406 * does this, so they need to be fixed too.
407 */
408static void
409pccard_function_init(struct pccard_function *pf)
410{
411	struct pccard_config_entry *cfe;
412	int i;
413	struct pccard_ivar *devi = PCCARD_IVAR(pf->dev);
414	struct resource_list *rl = &devi->resources;
415	struct resource_list_entry *rle;
416	struct resource *r = 0;
417	device_t bus;
418	int start;
419	int end;
420	int spaces;
421
422	if (pf->pf_flags & PFF_ENABLED) {
423		printf("pccard_function_init: function is enabled");
424		return;
425	}
426	bus = device_get_parent(pf->dev);
427	/* Remember which configuration entry we are using. */
428	STAILQ_FOREACH(cfe, &pf->cfe_head, cfe_list) {
429		for (i = 0; i < cfe->num_iospace; i++)
430			cfe->iores[i] = NULL;
431		cfe->irqres = NULL;
432		spaces = 0;
433		for (i = 0; i < cfe->num_iospace; i++) {
434			start = cfe->iospace[i].start;
435			if (start)
436				end = start + cfe->iospace[i].length - 1;
437			else
438				end = ~0;
439			cfe->iorid[i] = i;
440			DEVPRINTF((bus, "I/O rid %d start %x end %x\n",
441			    i, start, end));
442			r = cfe->iores[i] = bus_alloc_resource(bus,
443			    SYS_RES_IOPORT, &cfe->iorid[i], start, end,
444			    cfe->iospace[i].length,
445			    rman_make_alignment_flags(cfe->iospace[i].length));
446			if (cfe->iores[i] == NULL)
447				goto not_this_one;
448			resource_list_add(rl, SYS_RES_IOPORT, cfe->iorid[i],
449			    rman_get_start(r), rman_get_end(r),
450			    cfe->iospace[i].length);
451			rle = resource_list_find(rl, SYS_RES_IOPORT,
452			    cfe->iorid[i]);
453			rle->res = r;
454			spaces++;
455		}
456		if (cfe->num_memspace > 0) {
457			/*
458			 * Not implement yet, Fix me.
459			 */
460			DEVPRINTF((bus, "Memory space not yet implemented.\n"));
461		}
462		if (spaces == 0) {
463			DEVPRINTF((bus, "Neither memory nor I/O mampped\n"));
464			goto not_this_one;
465		}
466		if (cfe->irqmask) {
467			cfe->irqrid = 0;
468			r = cfe->irqres = bus_alloc_resource(bus, SYS_RES_IRQ,
469			    &cfe->irqrid, 0, ~0, 1, 0);
470			if (cfe->irqres == NULL)
471				goto not_this_one;
472			resource_list_add(rl, SYS_RES_IRQ, cfe->irqrid,
473			    rman_get_start(r), rman_get_end(r), 1);
474			rle = resource_list_find(rl, SYS_RES_IRQ,
475			    cfe->irqrid);
476			rle->res = r;
477		}
478		/* If we get to here, we've allocated all we need */
479		pf->cfe = cfe;
480		break;
481	    not_this_one:;
482		DEVPRVERBOSE((bus, "Allocation failed for cfe %d\n",
483		    cfe->number));
484		/*
485		 * Release resources that we partially allocated
486		 * from this config entry.
487		 */
488		for (i = 0; i < cfe->num_iospace; i++) {
489			if (cfe->iores[i] != NULL) {
490				bus_release_resource(bus, SYS_RES_IOPORT,
491				    cfe->iorid[i], cfe->iores[i]);
492				rle = resource_list_find(rl, SYS_RES_IOPORT,
493				    cfe->iorid[i]);
494				rle->res = NULL;
495				resource_list_delete(rl, SYS_RES_IOPORT,
496				    cfe->iorid[i]);
497			}
498			cfe->iores[i] = NULL;
499		}
500		if (cfe->irqmask && cfe->irqres != NULL) {
501			bus_release_resource(bus, SYS_RES_IRQ,
502			    cfe->irqrid, cfe->irqres);
503			rle = resource_list_find(rl, SYS_RES_IRQ,
504			    cfe->irqrid);
505			rle->res = NULL;
506			resource_list_delete(rl, SYS_RES_IRQ, cfe->irqrid);
507			cfe->irqres = NULL;
508		}
509	}
510}
511
512/*
513 * Free resources allocated by pccard_function_init(), May be called as long
514 * as the function is disabled.
515 *
516 * NOTE: This function should be unnecessary.  pccard_function_init should
517 * never keep resources initialized.
518 */
519static void
520pccard_function_free(struct pccard_function *pf)
521{
522	struct pccard_ivar *devi = PCCARD_IVAR(pf->dev);
523	struct resource_list_entry *rle;
524
525	if (pf->pf_flags & PFF_ENABLED) {
526		printf("pccard_function_init: function is enabled");
527		return;
528	}
529
530	SLIST_FOREACH(rle, &devi->resources, link) {
531		if (rle->res) {
532			if (rman_get_device(rle->res) != pf->sc->dev)
533				device_printf(pf->sc->dev,
534				    "function_free: Resource still owned by "
535				    "child, oops. "
536				    "(type=%d, rid=%d, addr=%lx)\n",
537				    rle->type, rle->rid,
538				    rman_get_start(rle->res));
539			BUS_RELEASE_RESOURCE(device_get_parent(pf->sc->dev),
540			    pf->sc->dev, rle->type, rle->rid, rle->res);
541			rle->res = NULL;
542		}
543	}
544	resource_list_free(&devi->resources);
545}
546
547/* Enable a PCCARD function */
548static int
549pccard_function_enable(struct pccard_function *pf)
550{
551	struct pccard_function *tmp;
552	int reg;
553	device_t dev = pf->sc->dev;
554
555	if (pf->cfe == NULL) {
556		DEVPRVERBOSE((dev, "No config entry could be allocated.\n"));
557		return (ENOMEM);
558	}
559
560	/*
561	 * Increase the reference count on the socket, enabling power, if
562	 * necessary.
563	 */
564	pf->sc->sc_enabled_count++;
565
566	if (pf->pf_flags & PFF_ENABLED) {
567		/*
568		 * Don't do anything if we're already enabled.
569		 */
570		return (0);
571	}
572
573	/*
574	 * it's possible for different functions' CCRs to be in the same
575	 * underlying page.  Check for that.
576	 */
577	STAILQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) {
578		if ((tmp->pf_flags & PFF_ENABLED) &&
579		    (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) &&
580		    ((pf->ccr_base + PCCARD_CCR_SIZE) <=
581		    (tmp->ccr_base - tmp->pf_ccr_offset +
582		    tmp->pf_ccr_realsize))) {
583			pf->pf_ccrt = tmp->pf_ccrt;
584			pf->pf_ccrh = tmp->pf_ccrh;
585			pf->pf_ccr_realsize = tmp->pf_ccr_realsize;
586
587			/*
588			 * pf->pf_ccr_offset = (tmp->pf_ccr_offset -
589			 * tmp->ccr_base) + pf->ccr_base;
590			 */
591			/* pf->pf_ccr_offset =
592			    (tmp->pf_ccr_offset + pf->ccr_base) -
593			    tmp->ccr_base; */
594			pf->pf_ccr_window = tmp->pf_ccr_window;
595			break;
596		}
597	}
598	if (tmp == NULL) {
599		pf->ccr_rid = 0;
600		pf->ccr_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
601		    &pf->ccr_rid, 0, ~0, 1 << 10, RF_ACTIVE);
602		if (!pf->ccr_res)
603			goto bad;
604		DEVPRINTF((dev, "ccr_res == %lx-%lx, base=%x\n",
605		    rman_get_start(pf->ccr_res), rman_get_end(pf->ccr_res),
606		    pf->ccr_base));
607		CARD_SET_RES_FLAGS(device_get_parent(dev), dev, SYS_RES_MEMORY,
608		    pf->ccr_rid, PCCARD_A_MEM_ATTR);
609		CARD_SET_MEMORY_OFFSET(device_get_parent(dev), dev,
610		    pf->ccr_rid, pf->ccr_base, &pf->pf_ccr_offset);
611		pf->pf_ccrt = rman_get_bustag(pf->ccr_res);
612		pf->pf_ccrh = rman_get_bushandle(pf->ccr_res);
613		pf->pf_ccr_realsize = 1;
614	}
615
616	reg = (pf->cfe->number & PCCARD_CCR_OPTION_CFINDEX);
617	reg |= PCCARD_CCR_OPTION_LEVIREQ;
618	if (pccard_mfc(pf->sc)) {
619		reg |= (PCCARD_CCR_OPTION_FUNC_ENABLE |
620			PCCARD_CCR_OPTION_ADDR_DECODE);
621		/* PCCARD_CCR_OPTION_IRQ_ENABLE set elsewhere as needed */
622	}
623	pccard_ccr_write(pf, PCCARD_CCR_OPTION, reg);
624
625	reg = 0;
626	if ((pf->cfe->flags & PCCARD_CFE_IO16) == 0)
627		reg |= PCCARD_CCR_STATUS_IOIS8;
628	if (pf->cfe->flags & PCCARD_CFE_AUDIO)
629		reg |= PCCARD_CCR_STATUS_AUDIO;
630	pccard_ccr_write(pf, PCCARD_CCR_STATUS, reg);
631
632	pccard_ccr_write(pf, PCCARD_CCR_SOCKETCOPY, 0);
633
634	if (pccard_mfc(pf->sc)) {
635		long tmp, iosize;
636
637		tmp = pf->pf_mfc_iomax - pf->pf_mfc_iobase;
638		/* round up to nearest (2^n)-1 */
639		for (iosize = 1; iosize < tmp; iosize <<= 1)
640			;
641		iosize--;
642
643		pccard_ccr_write(pf, PCCARD_CCR_IOBASE0,
644				 pf->pf_mfc_iobase & 0xff);
645		pccard_ccr_write(pf, PCCARD_CCR_IOBASE1,
646				 (pf->pf_mfc_iobase >> 8) & 0xff);
647		pccard_ccr_write(pf, PCCARD_CCR_IOBASE2, 0);
648		pccard_ccr_write(pf, PCCARD_CCR_IOBASE3, 0);
649
650		pccard_ccr_write(pf, PCCARD_CCR_IOSIZE, iosize);
651	}
652
653#ifdef PCCARDDEBUG
654	if (pccard_debug) {
655		STAILQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) {
656			device_printf(tmp->sc->dev,
657			    "function %d CCR at %d offset %x: "
658			    "%x %x %x %x, %x %x %x %x, %x\n",
659			    tmp->number, tmp->pf_ccr_window,
660			    tmp->pf_ccr_offset,
661			    pccard_ccr_read(tmp, 0x00),
662			    pccard_ccr_read(tmp, 0x02),
663			    pccard_ccr_read(tmp, 0x04),
664			    pccard_ccr_read(tmp, 0x06),
665			    pccard_ccr_read(tmp, 0x0A),
666			    pccard_ccr_read(tmp, 0x0C),
667			    pccard_ccr_read(tmp, 0x0E),
668			    pccard_ccr_read(tmp, 0x10),
669			    pccard_ccr_read(tmp, 0x12));
670		}
671	}
672#endif
673	pf->pf_flags |= PFF_ENABLED;
674	return (0);
675
676 bad:
677	/*
678	 * Decrement the reference count, and power down the socket, if
679	 * necessary.
680	 */
681	pf->sc->sc_enabled_count--;
682	DEVPRINTF((dev, "bad --enabled_count = %d\n", pf->sc->sc_enabled_count));
683
684	return (1);
685}
686
687/* Disable PCCARD function. */
688static void
689pccard_function_disable(struct pccard_function *pf)
690{
691	struct pccard_function *tmp;
692	device_t dev = pf->sc->dev;
693
694	if (pf->cfe == NULL)
695		panic("pccard_function_disable: function not initialized");
696
697	if ((pf->pf_flags & PFF_ENABLED) == 0) {
698		/*
699		 * Don't do anything if we're already disabled.
700		 */
701		return;
702	}
703
704	if (pf->intr_handler != NULL) {
705		struct pccard_ivar *devi = PCCARD_IVAR(pf->dev);
706		struct resource_list_entry *rle =
707		    resource_list_find(&devi->resources, SYS_RES_IRQ, 0);
708		BUS_TEARDOWN_INTR(dev, pf->dev, rle->res,
709		    pf->intr_handler_cookie);
710	}
711
712	/*
713	 * it's possible for different functions' CCRs to be in the same
714	 * underlying page.  Check for that.  Note we mark us as disabled
715	 * first to avoid matching ourself.
716	 */
717
718	pf->pf_flags &= ~PFF_ENABLED;
719	STAILQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) {
720		if ((tmp->pf_flags & PFF_ENABLED) &&
721		    (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) &&
722		    ((pf->ccr_base + PCCARD_CCR_SIZE) <=
723		    (tmp->ccr_base - tmp->pf_ccr_offset +
724		    tmp->pf_ccr_realsize)))
725			break;
726	}
727
728	/* Not used by anyone else; unmap the CCR. */
729	if (tmp == NULL) {
730		bus_release_resource(dev, SYS_RES_MEMORY, pf->ccr_rid,
731		    pf->ccr_res);
732		pf->ccr_res = NULL;
733	}
734
735	/*
736	 * Decrement the reference count, and power down the socket, if
737	 * necessary.
738	 */
739	pf->sc->sc_enabled_count--;
740}
741
742/*
743 * simulate the old "probe" routine.  In the new world order, the driver
744 * needs to grab devices while in the old they were assigned to the device by
745 * the pccardd process.  These symbols are exported to the upper layers.
746 */
747static int
748pccard_compat_do_probe(device_t bus, device_t dev)
749{
750	return (CARD_COMPAT_MATCH(dev));
751}
752
753static int
754pccard_compat_do_attach(device_t bus, device_t dev)
755{
756	int err;
757
758	err = CARD_COMPAT_PROBE(dev);
759	if (err == 0)
760		err = CARD_COMPAT_ATTACH(dev);
761	return (err);
762}
763
764#define PCCARD_NPORT	2
765#define PCCARD_NMEM	5
766#define PCCARD_NIRQ	1
767#define PCCARD_NDRQ	0
768
769static int
770pccard_add_children(device_t dev, int busno)
771{
772	/* Call parent to scan for any current children */
773	return (0);
774}
775
776static int
777pccard_probe(device_t dev)
778{
779	device_set_desc(dev, "16-bit PCCard bus");
780	return (pccard_add_children(dev, device_get_unit(dev)));
781}
782
783static int
784pccard_attach(device_t dev)
785{
786	struct pccard_softc *sc = PCCARD_SOFTC(dev);
787
788	sc->dev = dev;
789	sc->sc_enabled_count = 0;
790	return (bus_generic_attach(dev));
791}
792
793static int
794pccard_detach(device_t dev)
795{
796	pccard_detach_card(dev);
797	return 0;
798}
799
800static int
801pccard_suspend(device_t self)
802{
803	pccard_detach_card(self);
804	return (0);
805}
806
807static
808int
809pccard_resume(device_t self)
810{
811	return (0);
812}
813
814static void
815pccard_print_resources(struct resource_list *rl, const char *name, int type,
816    int count, const char *format)
817{
818	struct resource_list_entry *rle;
819	int printed;
820	int i;
821
822	printed = 0;
823	for (i = 0; i < count; i++) {
824		rle = resource_list_find(rl, type, i);
825		if (rle != NULL) {
826			if (printed == 0)
827				printf(" %s ", name);
828			else if (printed > 0)
829				printf(",");
830			printed++;
831			printf(format, rle->start);
832			if (rle->count > 1) {
833				printf("-");
834				printf(format, rle->start + rle->count - 1);
835			}
836		} else if (i > 3) {
837			/* check the first few regardless */
838			break;
839		}
840	}
841}
842
843static int
844pccard_print_child(device_t dev, device_t child)
845{
846	struct pccard_ivar *devi = PCCARD_IVAR(child);
847	struct resource_list *rl = &devi->resources;
848	int retval = 0;
849
850	retval += bus_print_child_header(dev, child);
851	retval += printf(" at");
852
853	if (devi != NULL) {
854		pccard_print_resources(rl, "port", SYS_RES_IOPORT,
855		    PCCARD_NPORT, "%#lx");
856		pccard_print_resources(rl, "iomem", SYS_RES_MEMORY,
857		    PCCARD_NMEM, "%#lx");
858		pccard_print_resources(rl, "irq", SYS_RES_IRQ, PCCARD_NIRQ,
859		    "%ld");
860		pccard_print_resources(rl, "drq", SYS_RES_DRQ, PCCARD_NDRQ,
861		    "%ld");
862		retval += printf(" function %d config %d", devi->fcn->number,
863		    devi->fcn->cfe->number);
864	}
865
866	retval += bus_print_child_footer(dev, child);
867
868	return (retval);
869}
870
871static int
872pccard_set_resource(device_t dev, device_t child, int type, int rid,
873		 u_long start, u_long count)
874{
875	struct pccard_ivar *devi = PCCARD_IVAR(child);
876	struct resource_list *rl = &devi->resources;
877
878	if (type != SYS_RES_IOPORT && type != SYS_RES_MEMORY
879	    && type != SYS_RES_IRQ && type != SYS_RES_DRQ)
880		return (EINVAL);
881	if (rid < 0)
882		return (EINVAL);
883	if (type == SYS_RES_IOPORT && rid >= PCCARD_NPORT)
884		return (EINVAL);
885	if (type == SYS_RES_MEMORY && rid >= PCCARD_NMEM)
886		return (EINVAL);
887	if (type == SYS_RES_IRQ && rid >= PCCARD_NIRQ)
888		return (EINVAL);
889	if (type == SYS_RES_DRQ && rid >= PCCARD_NDRQ)
890		return (EINVAL);
891
892	resource_list_add(rl, type, rid, start, start + count - 1, count);
893	if (NULL != resource_list_alloc(rl, device_get_parent(dev), dev,
894	    type, &rid, start, start + count - 1, count, 0))
895		return 0;
896	else
897		return ENOMEM;
898}
899
900static int
901pccard_get_resource(device_t dev, device_t child, int type, int rid,
902    u_long *startp, u_long *countp)
903{
904	struct pccard_ivar *devi = PCCARD_IVAR(child);
905	struct resource_list *rl = &devi->resources;
906	struct resource_list_entry *rle;
907
908	rle = resource_list_find(rl, type, rid);
909	if (rle == NULL)
910		return (ENOENT);
911
912	if (startp != NULL)
913		*startp = rle->start;
914	if (countp != NULL)
915		*countp = rle->count;
916
917	return (0);
918}
919
920static void
921pccard_delete_resource(device_t dev, device_t child, int type, int rid)
922{
923	struct pccard_ivar *devi = PCCARD_IVAR(child);
924	struct resource_list *rl = &devi->resources;
925	resource_list_delete(rl, type, rid);
926}
927
928static int
929pccard_set_res_flags(device_t dev, device_t child, int type, int rid,
930    u_int32_t flags)
931{
932	return (CARD_SET_RES_FLAGS(device_get_parent(dev), child, type,
933	    rid, flags));
934}
935
936static int
937pccard_set_memory_offset(device_t dev, device_t child, int rid,
938    u_int32_t offset, u_int32_t *deltap)
939
940{
941	return (CARD_SET_MEMORY_OFFSET(device_get_parent(dev), child, rid,
942	    offset, deltap));
943}
944
945static void
946pccard_probe_nomatch(device_t bus, device_t child)
947{
948	struct pccard_ivar *devi = PCCARD_IVAR(child);
949	struct pccard_function *func = devi->fcn;
950	struct pccard_softc *sc = PCCARD_SOFTC(bus);
951
952	device_printf(bus, "<unknown card>");
953	printf(" (manufacturer=0x%04x, product=0x%04x) at function %d\n",
954	  sc->card.manufacturer, sc->card.product, func->number);
955	device_printf(bus, "   CIS info: %s, %s, %s\n", sc->card.cis1_info[0],
956	  sc->card.cis1_info[1], sc->card.cis1_info[2]);
957	return;
958}
959
960static int
961pccard_child_location_str(device_t bus, device_t child, char *buf,
962    size_t buflen)
963{
964	struct pccard_ivar *devi = PCCARD_IVAR(child);
965	struct pccard_function *func = devi->fcn;
966
967	snprintf(buf, buflen, "function=%d", func->number);
968	return (0);
969}
970
971static int
972pccard_child_pnpinfo_str(device_t bus, device_t child, char *buf,
973    size_t buflen)
974{
975	struct pccard_ivar *devi = PCCARD_IVAR(child);
976	struct pccard_function *func = devi->fcn;
977	struct pccard_softc *sc = PCCARD_SOFTC(bus);
978
979	snprintf(buf, buflen, "manufacturer=0x%04x product=0x%04x "
980	    "cisvendor=\"%s\" cisproduct=\"%s\" function_type=%d",
981	    sc->card.manufacturer, sc->card.product, sc->card.cis1_info[0],
982	    sc->card.cis1_info[1], func->function);
983	return (0);
984}
985
986static int
987pccard_read_ivar(device_t bus, device_t child, int which, u_char *result)
988{
989	struct pccard_ivar *devi = PCCARD_IVAR(child);
990	struct pccard_function *func = devi->fcn;
991	struct pccard_softc *sc = PCCARD_SOFTC(bus);
992
993	switch (which) {
994	default:
995	case PCCARD_IVAR_ETHADDR:
996		bcopy(func->pf_funce_lan_nid, result, ETHER_ADDR_LEN);
997		break;
998	case PCCARD_IVAR_VENDOR:
999		*(u_int32_t *) result = sc->card.manufacturer;
1000		break;
1001	case PCCARD_IVAR_PRODUCT:
1002		*(u_int32_t *) result = sc->card.product;
1003		break;
1004	case PCCARD_IVAR_PRODEXT:
1005		*(u_int16_t *) result = sc->card.prodext;
1006		break;
1007	case PCCARD_IVAR_FUNCTION:
1008		*(u_int32_t *) result = func->function;
1009		break;
1010	case PCCARD_IVAR_FUNCTION_NUMBER:
1011		if (!func) {
1012			device_printf(bus, "No function number, bug!\n");
1013			return (ENOENT);
1014		}
1015		*(u_int32_t *) result = func->number;
1016		break;
1017	case PCCARD_IVAR_VENDOR_STR:
1018		*(char **) result = sc->card.cis1_info[0];
1019		break;
1020	case PCCARD_IVAR_PRODUCT_STR:
1021		*(char **) result = sc->card.cis1_info[1];
1022		break;
1023	case PCCARD_IVAR_CIS3_STR:
1024		*(char **) result = sc->card.cis1_info[2];
1025		break;
1026	case PCCARD_IVAR_CIS4_STR:
1027		*(char **) result = sc->card.cis1_info[3];
1028		break;
1029	}
1030	return (0);
1031}
1032
1033static void
1034pccard_driver_added(device_t dev, driver_t *driver)
1035{
1036	struct pccard_softc *sc = PCCARD_SOFTC(dev);
1037	struct pccard_function *pf;
1038	device_t child;
1039
1040	STAILQ_FOREACH(pf, &sc->card.pf_head, pf_list) {
1041		if (STAILQ_EMPTY(&pf->cfe_head))
1042			continue;
1043		child = pf->dev;
1044		if (device_get_state(child) != DS_NOTPRESENT)
1045			continue;
1046		if (pccard_function_enable(pf) == 0 &&
1047		    device_probe_and_attach(child) == 0) {
1048			DEVPRINTF((sc->dev, "function %d CCR at %d "
1049			    "offset %x: %x %x %x %x, %x %x %x %x, %x\n",
1050			    pf->number, pf->pf_ccr_window, pf->pf_ccr_offset,
1051			    pccard_ccr_read(pf, 0x00),
1052			pccard_ccr_read(pf, 0x02), pccard_ccr_read(pf, 0x04),
1053			pccard_ccr_read(pf, 0x06), pccard_ccr_read(pf, 0x0A),
1054			pccard_ccr_read(pf, 0x0C), pccard_ccr_read(pf, 0x0E),
1055			pccard_ccr_read(pf, 0x10), pccard_ccr_read(pf, 0x12)));
1056		} else {
1057			if (pf->cfe != NULL)
1058				pccard_function_disable(pf);
1059		}
1060	}
1061	return;
1062}
1063
1064static struct resource *
1065pccard_alloc_resource(device_t dev, device_t child, int type, int *rid,
1066    u_long start, u_long end, u_long count, u_int flags)
1067{
1068	struct pccard_ivar *dinfo;
1069	struct resource_list_entry *rle = 0;
1070	int passthrough = (device_get_parent(child) != dev);
1071	struct resource *r = NULL;
1072
1073	if (passthrough) {
1074		return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
1075		    type, rid, start, end, count, flags));
1076	}
1077
1078	dinfo = device_get_ivars(child);
1079	rle = resource_list_find(&dinfo->resources, type, *rid);
1080
1081	if (rle == NULL)
1082		return (NULL);		/* no resource of that type/rid */
1083
1084	if (rle->res == NULL) {
1085		switch(type) {
1086		case SYS_RES_IOPORT:
1087			r = bus_alloc_resource(dev, type, rid, start, end,
1088			    count, rman_make_alignment_flags(count));
1089			if (r == NULL)
1090				goto bad;
1091			resource_list_add(&dinfo->resources, type, *rid,
1092			    rman_get_start(r), rman_get_end(r), count);
1093			rle = resource_list_find(&dinfo->resources, type, *rid);
1094			if (!rle)
1095				goto bad;
1096			rle->res = r;
1097			break;
1098		case SYS_RES_MEMORY:
1099			break;
1100		case SYS_RES_IRQ:
1101			break;
1102		}
1103		return (rle->res);
1104	}
1105	if (rman_get_device(rle->res) != dev)
1106		return (NULL);
1107	bus_release_resource(dev, type, *rid, rle->res);
1108	rle->res = NULL;
1109	switch(type) {
1110	case SYS_RES_IOPORT:
1111	case SYS_RES_MEMORY:
1112		if (!(flags & RF_ALIGNMENT_MASK))
1113			flags |= rman_make_alignment_flags(rle->count);
1114		break;
1115	case SYS_RES_IRQ:
1116		flags |= RF_SHAREABLE;
1117		break;
1118	}
1119	rle->res = resource_list_alloc(&dinfo->resources, dev, child,
1120	    type, rid, rle->start, rle->end, rle->count, flags);
1121	return (rle->res);
1122bad:;
1123	device_printf(dev, "WARNING: Resource not reserved by pccard\n");
1124	return (NULL);
1125}
1126
1127static int
1128pccard_release_resource(device_t dev, device_t child, int type, int rid,
1129    struct resource *r)
1130{
1131	struct pccard_ivar *dinfo;
1132	int passthrough = (device_get_parent(child) != dev);
1133	struct resource_list_entry *rle = 0;
1134	int ret;
1135	int flags;
1136
1137	if (passthrough)
1138		return BUS_RELEASE_RESOURCE(device_get_parent(dev), child,
1139		    type, rid, r);
1140
1141	dinfo = device_get_ivars(child);
1142
1143	rle = resource_list_find(&dinfo->resources, type, rid);
1144
1145	if (!rle) {
1146		device_printf(dev, "Allocated resource not found, "
1147		    "%d %x %lx %lx\n",
1148		    type, rid, rman_get_start(r), rman_get_size(r));
1149		return ENOENT;
1150	}
1151	if (!rle->res) {
1152		device_printf(dev, "Allocated resource not recorded\n");
1153		return ENOENT;
1154	}
1155
1156	ret = BUS_RELEASE_RESOURCE(device_get_parent(dev), child,
1157	    type, rid, r);
1158	switch(type) {
1159	case SYS_RES_IOPORT:
1160	case SYS_RES_MEMORY:
1161		flags = rman_make_alignment_flags(rle->count);
1162		break;
1163	case SYS_RES_IRQ:
1164		flags = RF_SHAREABLE;
1165		break;
1166	default:
1167		flags = 0;
1168	}
1169	rle->res = bus_alloc_resource(dev, type, &rid,
1170	    rle->start, rle->end, rle->count, flags);
1171	if (rle->res == NULL)
1172		device_printf(dev, "release_resource: "
1173		    "unable to reaquire resource\n");
1174	return ret;
1175}
1176
1177static void
1178pccard_child_detached(device_t parent, device_t dev)
1179{
1180	struct pccard_ivar *ivar = PCCARD_IVAR(dev);
1181	struct pccard_function *pf = ivar->fcn;
1182
1183	pccard_function_disable(pf);
1184}
1185
1186static void
1187pccard_intr(void *arg)
1188{
1189	struct pccard_function *pf = (struct pccard_function*) arg;
1190	int reg;
1191	int doisr = 1;
1192
1193	/*
1194	 * MFC cards know if they interrupted, so we have to ack the
1195	 * interrupt and call the ISR.  Non-MFC cards don't have these
1196	 * bits, so they always get called.  Many non-MFC cards have
1197	 * this bit set always upon read, but some do not.
1198	 *
1199	 * We always ack the interrupt, even if there's no ISR
1200	 * for the card.  This is done on the theory that acking
1201	 * the interrupt will pacify the card enough to keep an
1202	 * interrupt storm from happening.  Of course this won't
1203	 * help in the non-MFC case.
1204	 */
1205	if (pccard_mfc(pf->sc)) {
1206		reg = pccard_ccr_read(pf, PCCARD_CCR_STATUS);
1207		if (reg & PCCARD_CCR_STATUS_INTR)
1208			pccard_ccr_write(pf, PCCARD_CCR_STATUS,
1209			    reg & ~PCCARD_CCR_STATUS_INTR);
1210		else
1211			doisr = 0;
1212	}
1213	if (pf->intr_handler != NULL && doisr)
1214		pf->intr_handler(pf->intr_handler_arg);
1215}
1216
1217static int
1218pccard_setup_intr(device_t dev, device_t child, struct resource *irq,
1219    int flags, driver_intr_t *intr, void *arg, void **cookiep)
1220{
1221	struct pccard_softc *sc = PCCARD_SOFTC(dev);
1222	struct pccard_ivar *ivar = PCCARD_IVAR(child);
1223	struct pccard_function *func = ivar->fcn;
1224	int err;
1225
1226	if (func->intr_handler != NULL)
1227		panic("Only one interrupt handler per function allowed");
1228	err = bus_generic_setup_intr(dev, child, irq, flags, pccard_intr,
1229	    func, cookiep);
1230	if (err != 0)
1231		return (err);
1232	func->intr_handler = intr;
1233	func->intr_handler_arg = arg;
1234	func->intr_handler_cookie = *cookiep;
1235	if (pccard_mfc(sc)) {
1236		pccard_ccr_write(func, PCCARD_CCR_OPTION,
1237		    pccard_ccr_read(func, PCCARD_CCR_OPTION) |
1238		    PCCARD_CCR_OPTION_IREQ_ENABLE);
1239	}
1240	return (0);
1241}
1242
1243static int
1244pccard_teardown_intr(device_t dev, device_t child, struct resource *r,
1245    void *cookie)
1246{
1247	struct pccard_softc *sc = PCCARD_SOFTC(dev);
1248	struct pccard_ivar *ivar = PCCARD_IVAR(child);
1249	struct pccard_function *func = ivar->fcn;
1250	int ret;
1251
1252	if (pccard_mfc(sc)) {
1253		pccard_ccr_write(func, PCCARD_CCR_OPTION,
1254		    pccard_ccr_read(func, PCCARD_CCR_OPTION) &
1255		    ~PCCARD_CCR_OPTION_IREQ_ENABLE);
1256	}
1257	ret = bus_generic_teardown_intr(dev, child, r, cookie);
1258	if (ret == 0) {
1259		func->intr_handler = NULL;
1260		func->intr_handler_arg = NULL;
1261		func->intr_handler_cookie = NULL;
1262	}
1263
1264	return (ret);
1265}
1266
1267static device_method_t pccard_methods[] = {
1268	/* Device interface */
1269	DEVMETHOD(device_probe,		pccard_probe),
1270	DEVMETHOD(device_attach,	pccard_attach),
1271	DEVMETHOD(device_detach,	pccard_detach),
1272	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
1273	DEVMETHOD(device_suspend,	pccard_suspend),
1274	DEVMETHOD(device_resume,	pccard_resume),
1275
1276	/* Bus interface */
1277	DEVMETHOD(bus_print_child,	pccard_print_child),
1278	DEVMETHOD(bus_driver_added,	pccard_driver_added),
1279	DEVMETHOD(bus_child_detached,	pccard_child_detached),
1280	DEVMETHOD(bus_alloc_resource,	pccard_alloc_resource),
1281	DEVMETHOD(bus_release_resource,	pccard_release_resource),
1282	DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
1283	DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
1284	DEVMETHOD(bus_setup_intr,	pccard_setup_intr),
1285	DEVMETHOD(bus_teardown_intr,	pccard_teardown_intr),
1286	DEVMETHOD(bus_set_resource,	pccard_set_resource),
1287	DEVMETHOD(bus_get_resource,	pccard_get_resource),
1288	DEVMETHOD(bus_delete_resource,	pccard_delete_resource),
1289	DEVMETHOD(bus_probe_nomatch,	pccard_probe_nomatch),
1290	DEVMETHOD(bus_read_ivar,	pccard_read_ivar),
1291	DEVMETHOD(bus_child_pnpinfo_str, pccard_child_pnpinfo_str),
1292	DEVMETHOD(bus_child_location_str, pccard_child_location_str),
1293
1294	/* Card Interface */
1295	DEVMETHOD(card_set_res_flags,	pccard_set_res_flags),
1296	DEVMETHOD(card_set_memory_offset, pccard_set_memory_offset),
1297	DEVMETHOD(card_get_type,	pccard_card_gettype),
1298	DEVMETHOD(card_attach_card,	pccard_attach_card),
1299	DEVMETHOD(card_detach_card,	pccard_detach_card),
1300	DEVMETHOD(card_compat_do_probe, pccard_compat_do_probe),
1301	DEVMETHOD(card_compat_do_attach, pccard_compat_do_attach),
1302	DEVMETHOD(card_do_product_lookup, pccard_do_product_lookup),
1303
1304	{ 0, 0 }
1305};
1306
1307static driver_t pccard_driver = {
1308	"pccard",
1309	pccard_methods,
1310	sizeof(struct pccard_softc)
1311};
1312
1313devclass_t	pccard_devclass;
1314
1315/* Maybe we need to have a slot device? */
1316DRIVER_MODULE(pccard, pcic, pccard_driver, pccard_devclass, 0, 0);
1317DRIVER_MODULE(pccard, pc98pcic, pccard_driver, pccard_devclass, 0, 0);
1318DRIVER_MODULE(pccard, cbb, pccard_driver, pccard_devclass, 0, 0);
1319DRIVER_MODULE(pccard, tcic, pccard_driver, pccard_devclass, 0, 0);
1320MODULE_VERSION(pccard, 1);
1321/*MODULE_DEPEND(pccard, pcic, 1, 1, 1);*/
1322