pccard.c revision 82415
1/*	$NetBSD: pcmcia.c,v 1.23 2000/07/28 19:17:02 drochner Exp $	*/
2/* $FreeBSD: head/sys/dev/pccard/pccard.c 82415 2001-08-27 11:28:00Z jon $ */
3
4/*
5 * Copyright (c) 1997 Marc Horowitz.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 *    must display the following acknowledgement:
17 *	This product includes software developed by Marc Horowitz.
18 * 4. The name of the author may not be used to endorse or promote products
19 *    derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#include <sys/param.h>
34#include <sys/systm.h>
35#include <sys/malloc.h>
36#include <sys/module.h>
37#include <sys/kernel.h>
38#include <sys/queue.h>
39#include <sys/types.h>
40
41#include <sys/bus.h>
42#include <machine/bus.h>
43#include <sys/rman.h>
44#include <machine/resource.h>
45
46#include <dev/pccard/pccardreg.h>
47#include <dev/pccard/pccardvar.h>
48
49#include "power_if.h"
50#include "card_if.h"
51
52#define PCCARDDEBUG
53
54#ifdef PCCARDDEBUG
55int	pccard_debug = 1;
56#define	DPRINTF(arg) if (pccard_debug) printf arg
57#define	DEVPRINTF(arg) if (pccard_debug) device_printf arg
58#define PRVERBOSE(arg) printf arg
59#define DEVPRVERBOSE(arg) device_printf arg
60#else
61#define	DPRINTF(arg)
62#define	DEVPRINTF(arg)
63#define PRVERBOSE(arg) if (bootverbose) printf arg
64#define DEVPRVERBOSE(arg) if (bootverbose) device_printf arg
65#endif
66
67#ifdef PCCARDVERBOSE
68int	pccard_verbose = 1;
69#else
70int	pccard_verbose = 0;
71#endif
72
73static int	pccard_ccr_read(struct pccard_function *pf, int ccr);
74static void	pccard_ccr_write(struct pccard_function *pf, int ccr, int val);
75static int	pccard_attach_card(device_t dev);
76static int	pccard_detach_card(device_t dev, int flags);
77static int	pccard_card_gettype(device_t dev, int *type);
78static void	pccard_function_init(struct pccard_function *pf);
79static void	pccard_function_free(struct pccard_function *pf);
80static int	pccard_function_enable(struct pccard_function *pf);
81static void	pccard_function_disable(struct pccard_function *pf);
82static int	pccard_compat_do_probe(device_t bus, device_t dev);
83static int	pccard_compat_do_attach(device_t bus, device_t dev);
84static int	pccard_add_children(device_t dev, int busno);
85static int	pccard_probe(device_t dev);
86static int	pccard_attach(device_t dev);
87static int	pccard_detach(device_t dev);
88static void	pccard_print_resources(struct resource_list *rl,
89		    const char *name, int type, int count, const char *format);
90static int	pccard_print_child(device_t dev, device_t child);
91static int	pccard_set_resource(device_t dev, device_t child, int type,
92		    int rid, u_long start, u_long count);
93static int	pccard_get_resource(device_t dev, device_t child, int type,
94		    int rid, u_long *startp, u_long *countp);
95static void	pccard_delete_resource(device_t dev, device_t child, int type,
96		    int rid);
97static int	pccard_set_res_flags(device_t dev, device_t child, int type,
98		    int rid, u_int32_t flags);
99static int	pccard_set_memory_offset(device_t dev, device_t child, int rid,
100		    u_int32_t offset, u_int32_t *deltap);
101static int	pccard_read_ivar(device_t bus, device_t child, int which,
102		    u_char *result);
103static void	pccard_driver_added(device_t dev, driver_t *driver);
104static struct resource *pccard_alloc_resource(device_t dev,
105		    device_t child, int type, int *rid, u_long start,
106		    u_long end, u_long count, u_int flags);
107static int	pccard_release_resource(device_t dev, device_t child, int type,
108		    int rid, struct resource *r);
109static void	pccard_child_detached(device_t parent, device_t dev);
110static void	pccard_intr(void *arg);
111static int	pccard_setup_intr(device_t dev, device_t child,
112		    struct resource *irq, int flags, driver_intr_t *intr,
113		    void *arg, void **cookiep);
114static int	pccard_teardown_intr(device_t dev, device_t child,
115		    struct resource *r, void *cookie);
116
117static int
118pccard_ccr_read(struct pccard_function *pf, int ccr)
119{
120	return (bus_space_read_1(pf->pf_ccrt, pf->pf_ccrh,
121	    pf->pf_ccr_offset + ccr));
122}
123
124static void
125pccard_ccr_write(struct pccard_function *pf, int ccr, int val)
126{
127	if ((pf->ccr_mask) & (1 << (ccr / 2))) {
128		bus_space_write_1(pf->pf_ccrt, pf->pf_ccrh,
129		    pf->pf_ccr_offset + ccr, val);
130	}
131}
132
133static int
134pccard_attach_card(device_t dev)
135{
136	struct pccard_softc *sc = PCCARD_SOFTC(dev);
137	struct pccard_function *pf;
138	struct pccard_ivar *ivar;
139	device_t child;
140
141	/*
142	 * this is here so that when socket_enable calls gettype, trt happens
143	 */
144	STAILQ_INIT(&sc->card.pf_head);
145
146	DEVPRINTF((dev, "chip_socket_enable\n"));
147	POWER_ENABLE_SOCKET(device_get_parent(dev), dev);
148
149	DEVPRINTF((dev, "read_cis\n"));
150	pccard_read_cis(sc);
151
152	DEVPRINTF((dev, "check_cis_quirks\n"));
153	pccard_check_cis_quirks(dev);
154
155	/*
156	 * bail now if the card has no functions, or if there was an error in
157	 * the cis.
158	 */
159
160	if (sc->card.error) {
161		device_printf (dev, "CARD ERROR!\n");
162		return (1);
163	}
164	if (STAILQ_EMPTY(&sc->card.pf_head)) {
165		device_printf (dev, "Card has no functions!\n");
166		return (1);
167	}
168
169	if (1)
170		pccard_print_cis(dev);
171
172	DEVPRINTF((dev, "functions scanning\n"));
173	STAILQ_FOREACH(pf, &sc->card.pf_head, pf_list) {
174		if (STAILQ_EMPTY(&pf->cfe_head))
175			continue;
176
177		pf->sc = sc;
178		pf->cfe = NULL;
179		pf->dev = NULL;
180	}
181
182	STAILQ_FOREACH(pf, &sc->card.pf_head, pf_list) {
183		if (STAILQ_EMPTY(&pf->cfe_head))
184			continue;
185		/*
186		 * In NetBSD, the drivers are responsible for activating
187		 * each function of a card.  I think that in FreeBSD we
188		 * want to activate them enough for the usual bus_*_resource
189		 * routines will do the right thing.  This many mean a
190		 * departure from the current NetBSD model.
191		 *
192		 * This could get really ugly for multifunction cards.  But
193		 * it might also just fall out of the FreeBSD resource model.
194		 *
195		 */
196		ivar = malloc(sizeof(struct pccard_ivar), M_DEVBUF,
197		    M_WAITOK | M_ZERO);
198		child = device_add_child(dev, NULL, -1);
199		device_set_ivars(child, ivar);
200		ivar->fcn = pf;
201		pf->dev = child;
202		/*
203		 * XXX We might want to move the next two lines into
204		 * XXX the pccard interface layer.  For the moment, this
205		 * XXX is OK, but some drivers want to pick the config
206		 * XXX entry to use as well as some address tweaks (mostly
207		 * XXX due to bugs in decode logic that makes some
208		 * XXX addresses illegal or broken).
209		 */
210		pccard_function_init(pf);
211		if (sc->sc_enabled_count == 0)
212			POWER_ENABLE_SOCKET(device_get_parent(dev), dev);
213		if (pccard_function_enable(pf) == 0 &&
214		    device_probe_and_attach(child) == 0) {
215			DEVPRINTF((sc->dev, "function %d CCR at %d "
216			    "offset %x: %x %x %x %x, %x %x %x %x, %x\n",
217			    pf->number, pf->pf_ccr_window, pf->pf_ccr_offset,
218			    pccard_ccr_read(pf, 0x00),
219			pccard_ccr_read(pf, 0x02), pccard_ccr_read(pf, 0x04),
220			pccard_ccr_read(pf, 0x06), pccard_ccr_read(pf, 0x0A),
221			pccard_ccr_read(pf, 0x0C), pccard_ccr_read(pf, 0x0E),
222			pccard_ccr_read(pf, 0x10), pccard_ccr_read(pf, 0x12)));
223		} else {
224			pccard_function_disable(pf);
225		}
226	}
227	if (sc->sc_enabled_count == 0)
228		pccard_detach_card(dev, 0);
229	return (0);
230}
231
232static int
233pccard_detach_card(device_t dev, int flags)
234{
235	struct pccard_softc *sc = PCCARD_SOFTC(dev);
236	struct pccard_function *pf;
237	struct pccard_config_entry *cfe;
238
239	/*
240	 * We are running on either the PCCARD socket's event thread
241	 * or in user context detaching a device by user request.
242	 */
243	STAILQ_FOREACH(pf, &sc->card.pf_head, pf_list) {
244		int state = device_get_state(pf->dev);
245
246		if (state == DS_ATTACHED || state == DS_BUSY)
247			device_detach(pf->dev);
248		pccard_function_disable(pf);
249		pccard_function_free(pf);
250		if (pf->dev != NULL)
251			device_delete_child(dev, pf->dev);
252	}
253	if (sc->sc_enabled_count == 0)
254		POWER_DISABLE_SOCKET(device_get_parent(dev), dev);
255
256	while (NULL != (pf = STAILQ_FIRST(&sc->card.pf_head))) {
257		while (NULL != (cfe = STAILQ_FIRST(&pf->cfe_head))) {
258			STAILQ_REMOVE_HEAD(&pf->cfe_head, cfe_list);
259			free(cfe, M_DEVBUF);
260		}
261		STAILQ_REMOVE_HEAD(&sc->card.pf_head, pf_list);
262		free(pf, M_DEVBUF);
263	}
264	return (0);
265}
266
267const struct pccard_product *
268pccard_product_lookup(device_t dev, const struct pccard_product *tab,
269    size_t ent_size, pccard_product_match_fn matchfn)
270{
271	const struct pccard_product *ent;
272	int matches;
273	u_int32_t fcn;
274	u_int32_t vendor;
275	u_int32_t prod;
276	char *vendorstr;
277	char *prodstr;
278
279#ifdef DIAGNOSTIC
280	if (sizeof *ent > ent_size)
281		panic("pccard_product_lookup: bogus ent_size %ld",
282		    (long) ent_size);
283#endif
284	if (pccard_get_vendor(dev, &vendor))
285		return (NULL);
286	if (pccard_get_product(dev, &prod))
287		return (NULL);
288	if (pccard_get_function_number(dev, &fcn))
289		return (NULL);
290	if (pccard_get_vendor_str(dev, &vendorstr))
291		return (NULL);
292	if (pccard_get_product_str(dev, &prodstr))
293		return (NULL);
294	for (ent = tab; ent->pp_name != NULL; ent =
295	    (const struct pccard_product *) ((const char *) ent + ent_size)) {
296		matches = 1;
297		if (matches && ent->pp_vendor != PCCARD_VENDOR_ANY &&
298		    vendor != ent->pp_vendor)
299			matches = 0;
300		if (matches && ent->pp_product != PCCARD_PRODUCT_ANY &&
301		    prod != ent->pp_product)
302			matches = 0;
303		if (matches && fcn != ent->pp_expfunc)
304			matches = 0;
305		if (matches && ent->pp_cis[0] &&
306		    strcmp(ent->pp_cis[0], vendorstr) != 0)
307			matches = 0;
308		if (matches && ent->pp_cis[1] &&
309		    strcmp(ent->pp_cis[1], prodstr) != 0)
310			matches = 0;
311		/* XXX need to match cis[2] and cis[3] also XXX */
312		if (matchfn != NULL)
313			matches = (*matchfn)(dev, ent, matches);
314		if (matches)
315			return (ent);
316	}
317	return (NULL);
318}
319
320static int
321pccard_card_gettype(device_t dev, int *type)
322{
323	struct pccard_softc *sc = PCCARD_SOFTC(dev);
324	struct pccard_function *pf;
325
326	/*
327	 * set the iftype to memory if this card has no functions (not yet
328	 * probed), or only one function, and that is not initialized yet or
329	 * that is memory.
330	 */
331	pf = STAILQ_FIRST(&sc->card.pf_head);
332	if (pf == NULL ||
333	    (STAILQ_NEXT(pf, pf_list) == NULL &&
334	    (pf->cfe == NULL || pf->cfe->iftype == PCCARD_IFTYPE_MEMORY)))
335		*type = PCCARD_IFTYPE_MEMORY;
336	else
337		*type = PCCARD_IFTYPE_IO;
338	return (0);
339}
340
341/*
342 * Initialize a PCCARD function.  May be called as long as the function is
343 * disabled.
344 *
345 * Note: pccard_function_init should not keep resources allocated.  It should
346 * only set them up ala isa pnp, set the values in the rl lists, and return.
347 * Any resource held after pccard_function_init is called is a bug.  However,
348 * the bus routines to get the resources also assume that pccard_function_init
349 * does this, so they need to be fixed too.
350 */
351static void
352pccard_function_init(struct pccard_function *pf)
353{
354	struct pccard_config_entry *cfe;
355	int i;
356	struct pccard_ivar *devi = PCCARD_IVAR(pf->dev);
357	struct resource_list *rl = &devi->resources;
358	struct resource_list_entry *rle;
359	struct resource *r = 0;
360	device_t bus;
361	int start;
362	int end;
363
364	if (pf->pf_flags & PFF_ENABLED) {
365		printf("pccard_function_init: function is enabled");
366		return;
367	}
368	bus = device_get_parent(pf->dev);
369	/* Remember which configuration entry we are using. */
370	STAILQ_FOREACH(cfe, &pf->cfe_head, cfe_list) {
371		for (i = 0; i < cfe->num_iospace; i++)
372			cfe->iores[i] = NULL;
373		cfe->irqres = NULL;
374		for (i = 0; i < cfe->num_iospace; i++) {
375			start = cfe->iospace[i].start;
376			if (start)
377				end = start + cfe->iospace[i].length - 1;
378			else
379				end = ~0;
380			cfe->iorid[i] = i;
381			r = cfe->iores[i] = bus_alloc_resource(bus,
382			    SYS_RES_IOPORT, &cfe->iorid[i], start, end,
383			    cfe->iospace[i].length,
384			    rman_make_alignment_flags(cfe->iospace[i].length));
385			if (cfe->iores[i] == NULL)
386				goto not_this_one;
387			resource_list_add(rl, SYS_RES_IOPORT, cfe->iorid[i],
388			    rman_get_start(r), rman_get_end(r),
389			    cfe->iospace[i].length);
390			rle = resource_list_find(rl, SYS_RES_IOPORT,
391			    cfe->iorid[i]);
392			rle->res = r;
393		}
394		if (cfe->num_memspace > 0) {
395			goto not_this_one;
396		}
397		if (cfe->irqmask) {
398			cfe->irqrid = 0;
399			r = cfe->irqres = bus_alloc_resource(bus, SYS_RES_IRQ,
400			    &cfe->irqrid, 0, ~0, 1, 0);
401			if (cfe->irqres == NULL)
402				goto not_this_one;
403			resource_list_add(rl, SYS_RES_IRQ, cfe->irqrid,
404			    rman_get_start(r), rman_get_end(r), 1);
405			rle = resource_list_find(rl, SYS_RES_IRQ,
406			    cfe->irqrid);
407			rle->res = r;
408		}
409		/* If we get to here, we've allocated all we need */
410		pf->cfe = cfe;
411		break;
412	    not_this_one:;
413		DEVPRVERBOSE((bus, "Allocation failed for cfe %d\n",
414		    cfe->number));
415		/*
416		 * Release resources that we partially allocated
417		 * from this config entry.
418		 */
419		for (i = 0; i < cfe->num_iospace; i++) {
420			if (cfe->iores[i] != NULL) {
421				bus_release_resource(bus, SYS_RES_IOPORT,
422				    cfe->iorid[i], cfe->iores[i]);
423				rle = resource_list_find(rl, SYS_RES_IOPORT,
424				    cfe->iorid[i]);
425				rle->res = NULL;
426				resource_list_delete(rl, SYS_RES_IOPORT,
427				    cfe->iorid[i]);
428			}
429			cfe->iores[i] = NULL;
430		}
431		if (cfe->irqmask && cfe->irqres != NULL) {
432			bus_release_resource(bus, SYS_RES_IRQ,
433			    cfe->irqrid, cfe->irqres);
434			rle = resource_list_find(rl, SYS_RES_IRQ,
435			    cfe->irqrid);
436			rle->res = NULL;
437			resource_list_delete(rl, SYS_RES_IRQ, cfe->irqrid);
438			cfe->irqres = NULL;
439		}
440	}
441}
442
443/*
444 * Free resources allocated by pccard_function_init(), May be called as long
445 * as the function is disabled.
446 *
447 * NOTE: This function should be unnecessary.  pccard_function_init should
448 * never keep resources initialized.
449 */
450static void
451pccard_function_free(struct pccard_function *pf)
452{
453	struct pccard_ivar *devi = PCCARD_IVAR(pf->dev);
454	struct resource_list_entry *rle;
455
456	if (pf->pf_flags & PFF_ENABLED) {
457		printf("pccard_function_init: function is enabled");
458		return;
459	}
460
461	SLIST_FOREACH(rle, &devi->resources, link) {
462		if (rle->res) {
463			if (rle->res->r_dev != pf->sc->dev)
464				device_printf(pf->sc->dev,
465				    "function_free: Resource still owned by "
466				    "child, oops. "
467				    "(type=%d, rid=%d, addr=%lx)\n",
468				    rle->type, rle->rid,
469				    rman_get_start(rle->res));
470			BUS_RELEASE_RESOURCE(device_get_parent(pf->sc->dev),
471			    rle->res->r_dev, rle->type, rle->rid, rle->res);
472			rle->res = NULL;
473		}
474	}
475	resource_list_free(&devi->resources);
476}
477
478/* Enable a PCCARD function */
479static int
480pccard_function_enable(struct pccard_function *pf)
481{
482	struct pccard_function *tmp;
483	int reg;
484	device_t dev = pf->sc->dev;
485
486	if (pf->cfe == NULL) {
487		DEVPRVERBOSE((dev, "No config entry could be allocated.\n"));
488		return (ENOMEM);
489	}
490
491	/*
492	 * Increase the reference count on the socket, enabling power, if
493	 * necessary.
494	 */
495	pf->sc->sc_enabled_count++;
496
497	if (pf->pf_flags & PFF_ENABLED) {
498		/*
499		 * Don't do anything if we're already enabled.
500		 */
501		return (0);
502	}
503
504	/*
505	 * it's possible for different functions' CCRs to be in the same
506	 * underlying page.  Check for that.
507	 */
508	STAILQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) {
509		if ((tmp->pf_flags & PFF_ENABLED) &&
510		    (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) &&
511		    ((pf->ccr_base + PCCARD_CCR_SIZE) <=
512		    (tmp->ccr_base - tmp->pf_ccr_offset +
513		    tmp->pf_ccr_realsize))) {
514			pf->pf_ccrt = tmp->pf_ccrt;
515			pf->pf_ccrh = tmp->pf_ccrh;
516			pf->pf_ccr_realsize = tmp->pf_ccr_realsize;
517
518			/*
519			 * pf->pf_ccr_offset = (tmp->pf_ccr_offset -
520			 * tmp->ccr_base) + pf->ccr_base;
521			 */
522			/* pf->pf_ccr_offset =
523			    (tmp->pf_ccr_offset + pf->ccr_base) -
524			    tmp->ccr_base; */
525			pf->pf_ccr_window = tmp->pf_ccr_window;
526			break;
527		}
528	}
529	if (tmp == NULL) {
530		pf->ccr_rid = 0;
531		pf->ccr_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
532		    &pf->ccr_rid, 0, ~0, 1 << 10, RF_ACTIVE);
533		if (!pf->ccr_res)
534			goto bad;
535		DEVPRINTF((dev, "ccr_res == %lx-%lx, base=%lx\n",
536		    rman_get_start(pf->ccr_res), rman_get_end(pf->ccr_res),
537		    pf->ccr_base));
538		CARD_SET_RES_FLAGS(device_get_parent(dev), dev, SYS_RES_MEMORY,
539		    pf->ccr_rid, PCCARD_A_MEM_ATTR);
540		CARD_SET_MEMORY_OFFSET(device_get_parent(dev), dev,
541		    pf->ccr_rid, pf->ccr_base, &pf->pf_ccr_offset);
542		pf->pf_ccrt = rman_get_bustag(pf->ccr_res);
543		pf->pf_ccrh = rman_get_bushandle(pf->ccr_res);
544		pf->pf_ccr_realsize = 1;
545	}
546
547	reg = (pf->cfe->number & PCCARD_CCR_OPTION_CFINDEX);
548	reg |= PCCARD_CCR_OPTION_LEVIREQ;
549	if (pccard_mfc(pf->sc)) {
550		reg |= (PCCARD_CCR_OPTION_FUNC_ENABLE |
551			PCCARD_CCR_OPTION_ADDR_DECODE);
552		/* PCCARD_CCR_OPTION_IRQ_ENABLE set elsewhere as needed */
553	}
554	pccard_ccr_write(pf, PCCARD_CCR_OPTION, reg);
555
556	reg = 0;
557	if ((pf->cfe->flags & PCCARD_CFE_IO16) == 0)
558		reg |= PCCARD_CCR_STATUS_IOIS8;
559	if (pf->cfe->flags & PCCARD_CFE_AUDIO)
560		reg |= PCCARD_CCR_STATUS_AUDIO;
561	pccard_ccr_write(pf, PCCARD_CCR_STATUS, reg);
562
563	pccard_ccr_write(pf, PCCARD_CCR_SOCKETCOPY, 0);
564
565	if (pccard_mfc(pf->sc)) {
566		long tmp, iosize;
567
568		tmp = pf->pf_mfc_iomax - pf->pf_mfc_iobase;
569		/* round up to nearest (2^n)-1 */
570		for (iosize = 1; iosize < tmp; iosize <<= 1)
571			;
572		iosize--;
573
574		pccard_ccr_write(pf, PCCARD_CCR_IOBASE0,
575				 pf->pf_mfc_iobase & 0xff);
576		pccard_ccr_write(pf, PCCARD_CCR_IOBASE1,
577				 (pf->pf_mfc_iobase >> 8) & 0xff);
578		pccard_ccr_write(pf, PCCARD_CCR_IOBASE2, 0);
579		pccard_ccr_write(pf, PCCARD_CCR_IOBASE3, 0);
580
581		pccard_ccr_write(pf, PCCARD_CCR_IOSIZE, iosize);
582	}
583
584#ifdef PCCARDDEBUG
585	if (pccard_debug) {
586		STAILQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) {
587			device_printf(tmp->sc->dev,
588			    "function %d CCR at %d offset %x: "
589			    "%x %x %x %x, %x %x %x %x, %x\n",
590			    tmp->number, tmp->pf_ccr_window,
591			    tmp->pf_ccr_offset,
592			    pccard_ccr_read(tmp, 0x00),
593			    pccard_ccr_read(tmp, 0x02),
594			    pccard_ccr_read(tmp, 0x04),
595			    pccard_ccr_read(tmp, 0x06),
596			    pccard_ccr_read(tmp, 0x0A),
597			    pccard_ccr_read(tmp, 0x0C),
598			    pccard_ccr_read(tmp, 0x0E),
599			    pccard_ccr_read(tmp, 0x10),
600			    pccard_ccr_read(tmp, 0x12));
601		}
602	}
603#endif
604	pf->pf_flags |= PFF_ENABLED;
605	return (0);
606
607 bad:
608	/*
609	 * Decrement the reference count, and power down the socket, if
610	 * necessary.
611	 */
612	pf->sc->sc_enabled_count--;
613	DEVPRINTF((dev, "bad --enabled_count = %d\n", pf->sc->sc_enabled_count));
614
615	return (1);
616}
617
618/* Disable PCCARD function. */
619static void
620pccard_function_disable(struct pccard_function *pf)
621{
622	struct pccard_function *tmp;
623	device_t dev = pf->sc->dev;
624
625	if (pf->cfe == NULL)
626		panic("pccard_function_disable: function not initialized");
627
628	if ((pf->pf_flags & PFF_ENABLED) == 0) {
629		/*
630		 * Don't do anything if we're already disabled.
631		 */
632		return;
633	}
634
635	if (pf->intr_handler != NULL) {
636		struct pccard_ivar *devi = PCCARD_IVAR(pf->dev);
637		struct resource_list_entry *rle =
638		    resource_list_find(&devi->resources, SYS_RES_IRQ, 0);
639		BUS_TEARDOWN_INTR(dev, pf->dev, rle->res,
640		    pf->intr_handler_cookie);
641	}
642
643	/*
644	 * it's possible for different functions' CCRs to be in the same
645	 * underlying page.  Check for that.  Note we mark us as disabled
646	 * first to avoid matching ourself.
647	 */
648
649	pf->pf_flags &= ~PFF_ENABLED;
650	STAILQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) {
651		if ((tmp->pf_flags & PFF_ENABLED) &&
652		    (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) &&
653		    ((pf->ccr_base + PCCARD_CCR_SIZE) <=
654		    (tmp->ccr_base - tmp->pf_ccr_offset +
655		    tmp->pf_ccr_realsize)))
656			break;
657	}
658
659	/* Not used by anyone else; unmap the CCR. */
660	if (tmp == NULL) {
661		bus_release_resource(dev, SYS_RES_MEMORY, pf->ccr_rid,
662		    pf->ccr_res);
663		pf->ccr_res = NULL;
664	}
665
666	/*
667	 * Decrement the reference count, and power down the socket, if
668	 * necessary.
669	 */
670	pf->sc->sc_enabled_count--;
671}
672
673#if 0
674/* XXX These functions are needed, but not like this XXX */
675int
676pccard_io_map(struct pccard_function *pf, int width, bus_addr_t offset,
677    bus_size_t size, struct pccard_io_handle *pcihp, int *windowp)
678{
679	int reg;
680
681	if (pccard_chip_io_map(pf->sc->pct, pf->sc->pch, width, offset, size,
682	    pcihp, windowp))
683		return (1);
684
685	/*
686	 * XXX in the multifunction multi-iospace-per-function case, this
687	 * needs to cooperate with io_alloc to make sure that the spaces
688	 * don't overlap, and that the ccr's are set correctly
689	 */
690
691	if (pccard_mfc(pf->sc)) {
692		long tmp, iosize;
693
694		if (pf->pf_mfc_iomax == 0) {
695			pf->pf_mfc_iobase = pcihp->addr + offset;
696			pf->pf_mfc_iomax = pf->pf_mfc_iobase + size;
697		} else {
698			/* this makes the assumption that nothing overlaps */
699			if (pf->pf_mfc_iobase > pcihp->addr + offset)
700				pf->pf_mfc_iobase = pcihp->addr + offset;
701			if (pf->pf_mfc_iomax < pcihp->addr + offset + size)
702				pf->pf_mfc_iomax = pcihp->addr + offset + size;
703		}
704
705		tmp = pf->pf_mfc_iomax - pf->pf_mfc_iobase;
706		/* round up to nearest (2^n)-1 */
707		for (iosize = 1; iosize >= tmp; iosize <<= 1)
708			;
709		iosize--;
710
711		pccard_ccr_write(pf, PCCARD_CCR_IOBASE0,
712		    pf->pf_mfc_iobase & 0xff);
713		pccard_ccr_write(pf, PCCARD_CCR_IOBASE1,
714		    (pf->pf_mfc_iobase >> 8) & 0xff);
715		pccard_ccr_write(pf, PCCARD_CCR_IOBASE2, 0);
716		pccard_ccr_write(pf, PCCARD_CCR_IOBASE3, 0);
717
718		pccard_ccr_write(pf, PCCARD_CCR_IOSIZE, iosize);
719
720		reg = pccard_ccr_read(pf, PCCARD_CCR_OPTION);
721		reg |= PCCARD_CCR_OPTION_ADDR_DECODE;
722		pccard_ccr_write(pf, PCCARD_CCR_OPTION, reg);
723	}
724	return (0);
725}
726
727void
728pccard_io_unmap(struct pccard_function *pf, int window)
729{
730
731	pccard_chip_io_unmap(pf->sc->pct, pf->sc->pch, window);
732
733	/* XXX Anything for multi-function cards? */
734}
735#endif
736
737/*
738 * simulate the old "probe" routine.  In the new world order, the driver
739 * needs to grab devices while in the old they were assigned to the device by
740 * the pccardd process.  These symbols are exported to the upper layers.
741 */
742static int
743pccard_compat_do_probe(device_t bus, device_t dev)
744{
745	return (CARD_COMPAT_MATCH(dev));
746}
747
748static int
749pccard_compat_do_attach(device_t bus, device_t dev)
750{
751	int err;
752
753	err = CARD_COMPAT_PROBE(dev);
754	if (err == 0)
755		err = CARD_COMPAT_ATTACH(dev);
756	return (err);
757}
758
759#define PCCARD_NPORT	2
760#define PCCARD_NMEM	5
761#define PCCARD_NIRQ	1
762#define PCCARD_NDRQ	0
763
764static int
765pccard_add_children(device_t dev, int busno)
766{
767	/* Call parent to scan for any current children */
768	return (0);
769}
770
771static int
772pccard_probe(device_t dev)
773{
774	device_set_desc(dev, "16-bit PCCard bus");
775	return (pccard_add_children(dev, device_get_unit(dev)));
776}
777
778static int
779pccard_attach(device_t dev)
780{
781	struct pccard_softc *sc = PCCARD_SOFTC(dev);
782
783	sc->dev = dev;
784	sc->sc_enabled_count = 0;
785	return (bus_generic_attach(dev));
786}
787
788static int
789pccard_detach(device_t dev)
790{
791	pccard_detach_card(dev, 0);
792	return 0;
793}
794
795static void
796pccard_print_resources(struct resource_list *rl, const char *name, int type,
797    int count, const char *format)
798{
799	struct resource_list_entry *rle;
800	int printed;
801	int i;
802
803	printed = 0;
804	for (i = 0; i < count; i++) {
805		rle = resource_list_find(rl, type, i);
806		if (rle != NULL) {
807			if (printed == 0)
808				printf(" %s ", name);
809			else if (printed > 0)
810				printf(",");
811			printed++;
812			printf(format, rle->start);
813			if (rle->count > 1) {
814				printf("-");
815				printf(format, rle->start + rle->count - 1);
816			}
817		} else if (i > 3) {
818			/* check the first few regardless */
819			break;
820		}
821	}
822}
823
824static int
825pccard_print_child(device_t dev, device_t child)
826{
827	struct pccard_ivar *devi = PCCARD_IVAR(child);
828	struct resource_list *rl = &devi->resources;
829	int retval = 0;
830
831	retval += bus_print_child_header(dev, child);
832	retval += printf(" at");
833
834	if (devi != NULL) {
835		pccard_print_resources(rl, "port", SYS_RES_IOPORT,
836		    PCCARD_NPORT, "%#lx");
837		pccard_print_resources(rl, "iomem", SYS_RES_MEMORY,
838		    PCCARD_NMEM, "%#lx");
839		pccard_print_resources(rl, "irq", SYS_RES_IRQ, PCCARD_NIRQ,
840		    "%ld");
841		pccard_print_resources(rl, "drq", SYS_RES_DRQ, PCCARD_NDRQ,
842		    "%ld");
843		retval += printf(" function %d config %d", devi->fcn->number,
844		    devi->fcn->cfe->number);
845	}
846
847	retval += bus_print_child_footer(dev, child);
848
849	return (retval);
850}
851
852static int
853pccard_set_resource(device_t dev, device_t child, int type, int rid,
854		 u_long start, u_long count)
855{
856	struct pccard_ivar *devi = PCCARD_IVAR(child);
857	struct resource_list *rl = &devi->resources;
858
859	if (type != SYS_RES_IOPORT && type != SYS_RES_MEMORY
860	    && type != SYS_RES_IRQ && type != SYS_RES_DRQ)
861		return (EINVAL);
862	if (rid < 0)
863		return (EINVAL);
864	if (type == SYS_RES_IOPORT && rid >= PCCARD_NPORT)
865		return (EINVAL);
866	if (type == SYS_RES_MEMORY && rid >= PCCARD_NMEM)
867		return (EINVAL);
868	if (type == SYS_RES_IRQ && rid >= PCCARD_NIRQ)
869		return (EINVAL);
870	if (type == SYS_RES_DRQ && rid >= PCCARD_NDRQ)
871		return (EINVAL);
872
873	resource_list_add(rl, type, rid, start, start + count - 1, count);
874	if (NULL != resource_list_alloc(rl, device_get_parent(dev), dev,
875	    type, &rid, start, start + count - 1, count, 0))
876		return 0;
877	else
878		return ENOMEM;
879}
880
881static int
882pccard_get_resource(device_t dev, device_t child, int type, int rid,
883    u_long *startp, u_long *countp)
884{
885	struct pccard_ivar *devi = PCCARD_IVAR(child);
886	struct resource_list *rl = &devi->resources;
887	struct resource_list_entry *rle;
888
889	rle = resource_list_find(rl, type, rid);
890	if (rle == NULL)
891		return (ENOENT);
892
893	if (startp != NULL)
894		*startp = rle->start;
895	if (countp != NULL)
896		*countp = rle->count;
897
898	return (0);
899}
900
901static void
902pccard_delete_resource(device_t dev, device_t child, int type, int rid)
903{
904	struct pccard_ivar *devi = PCCARD_IVAR(child);
905	struct resource_list *rl = &devi->resources;
906	resource_list_delete(rl, type, rid);
907}
908
909static int
910pccard_set_res_flags(device_t dev, device_t child, int type, int rid,
911    u_int32_t flags)
912{
913	return (CARD_SET_RES_FLAGS(device_get_parent(dev), child, type,
914	    rid, flags));
915}
916
917static int
918pccard_set_memory_offset(device_t dev, device_t child, int rid,
919    u_int32_t offset, u_int32_t *deltap)
920
921{
922	return (CARD_SET_MEMORY_OFFSET(device_get_parent(dev), child, rid,
923	    offset, deltap));
924}
925
926static int
927pccard_read_ivar(device_t bus, device_t child, int which, u_char *result)
928{
929	struct pccard_ivar *devi = PCCARD_IVAR(child);
930	struct pccard_function *func = devi->fcn;
931	struct pccard_softc *sc = PCCARD_SOFTC(bus);
932
933	/* PCCARD_IVAR_ETHADDR unhandled from oldcard */
934	switch (which) {
935	default:
936	case PCCARD_IVAR_ETHADDR:
937		return (ENOENT);
938		break;
939	case PCCARD_IVAR_VENDOR:
940		*(u_int32_t *) result = sc->card.manufacturer;
941		break;
942	case PCCARD_IVAR_PRODUCT:
943		*(u_int32_t *) result = sc->card.product;
944		break;
945	case PCCARD_IVAR_FUNCTION:
946		*(u_int32_t *) result = func->function;
947		break;
948	case PCCARD_IVAR_FUNCTION_NUMBER:
949		if (!func) {
950			device_printf(bus, "No function number, bug!\n");
951			return (ENOENT);
952		}
953		*(u_int32_t *) result = func->number;
954		break;
955	case PCCARD_IVAR_VENDOR_STR:
956		*(char **) result = sc->card.cis1_info[0];
957		break;
958	case PCCARD_IVAR_PRODUCT_STR:
959		*(char **) result = sc->card.cis1_info[1];
960		break;
961	case PCCARD_IVAR_CIS3_STR:
962		*(char **) result = sc->card.cis1_info[2];
963		break;
964	case PCCARD_IVAR_CIS4_STR:
965		*(char **) result = sc->card.cis1_info[2];
966		break;
967	}
968	return (0);
969}
970
971static void
972pccard_driver_added(device_t dev, driver_t *driver)
973{
974	struct pccard_softc *sc = PCCARD_SOFTC(dev);
975	struct pccard_function *pf;
976	device_t child;
977
978	if (sc->sc_enabled_count == 0) {
979		CARD_REPROBE_CARD(device_get_parent(dev), dev);
980		return;
981	}
982
983	STAILQ_FOREACH(pf, &sc->card.pf_head, pf_list) {
984		if (STAILQ_EMPTY(&pf->cfe_head))
985			continue;
986		child = pf->dev;
987		if (device_get_state(child) != DS_NOTPRESENT)
988			continue;
989		if (pccard_function_enable(pf) == 0 &&
990		    device_probe_and_attach(child) == 0) {
991			DEVPRINTF((sc->dev, "function %d CCR at %d "
992			    "offset %x: %x %x %x %x, %x %x %x %x, %x\n",
993			    pf->number, pf->pf_ccr_window, pf->pf_ccr_offset,
994			    pccard_ccr_read(pf, 0x00),
995			pccard_ccr_read(pf, 0x02), pccard_ccr_read(pf, 0x04),
996			pccard_ccr_read(pf, 0x06), pccard_ccr_read(pf, 0x0A),
997			pccard_ccr_read(pf, 0x0C), pccard_ccr_read(pf, 0x0E),
998			pccard_ccr_read(pf, 0x10), pccard_ccr_read(pf, 0x12)));
999		} else {
1000			pccard_function_disable(pf);
1001		}
1002	}
1003	return;
1004}
1005
1006static struct resource *
1007pccard_alloc_resource(device_t dev, device_t child, int type, int *rid,
1008    u_long start, u_long end, u_long count, u_int flags)
1009{
1010	struct pccard_ivar *dinfo;
1011	struct resource_list_entry *rle = 0;
1012	int passthrough = (device_get_parent(child) != dev);
1013
1014	if (passthrough) {
1015		return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
1016		    type, rid, start, end, count, flags));
1017	}
1018
1019	dinfo = device_get_ivars(child);
1020	rle = resource_list_find(&dinfo->resources, type, *rid);
1021
1022	if (!rle)
1023		return NULL;		/* no resource of that type/rid */
1024
1025	if (!rle->res) {
1026		device_printf(dev, "WARNING: Resource not reserved by pccard bus\n");
1027		return NULL;
1028	} else {
1029		if (rle->res->r_dev != dev) return NULL;
1030		bus_release_resource(dev, type, *rid, rle->res);
1031		rle->res = NULL;
1032		switch(type) {
1033		case SYS_RES_IOPORT:
1034		case SYS_RES_MEMORY:
1035			if (!(flags & RF_ALIGNMENT_MASK))
1036				flags |= rman_make_alignment_flags(rle->count);
1037			break;
1038		case SYS_RES_IRQ:
1039			flags |= RF_SHAREABLE;
1040			break;
1041		}
1042		return resource_list_alloc(&dinfo->resources, dev, child, type,
1043		    rid, rle->start, rle->end, rle->count, flags);
1044	}
1045}
1046
1047static int
1048pccard_release_resource(device_t dev, device_t child, int type, int rid,
1049    struct resource *r)
1050{
1051	struct pccard_ivar *dinfo;
1052	int passthrough = (device_get_parent(child) != dev);
1053	struct resource_list_entry *rle = 0;
1054	int ret;
1055	int flags;
1056
1057	if (passthrough)
1058		return BUS_RELEASE_RESOURCE(device_get_parent(dev), child,
1059		    type, rid, r);
1060
1061	dinfo = device_get_ivars(child);
1062
1063	rle = resource_list_find(&dinfo->resources, type, rid);
1064
1065	if (!rle) {
1066		device_printf(dev, "Allocated resource not found, "
1067		    "%d %x %lx %lx\n",
1068		    type, rid, rman_get_start(r), rman_get_size(r));
1069		return ENOENT;
1070	}
1071	if (!rle->res) {
1072		device_printf(dev, "Allocated resource not recorded\n");
1073		return ENOENT;
1074	}
1075
1076	ret = BUS_RELEASE_RESOURCE(device_get_parent(dev), child,
1077	    type, rid, r);
1078	switch(type) {
1079	case SYS_RES_IOPORT:
1080	case SYS_RES_MEMORY:
1081		flags = rman_make_alignment_flags(rle->count);
1082		break;
1083	case SYS_RES_IRQ:
1084		flags = RF_SHAREABLE;
1085		break;
1086	default:
1087		flags = 0;
1088	}
1089	rle->res = bus_alloc_resource(dev, type, &rid,
1090	    rle->start, rle->end, rle->count, flags);
1091	if (rle->res == NULL)
1092		device_printf(dev, "release_resource: "
1093		    "unable to reaquire resource\n");
1094	return ret;
1095}
1096
1097static void
1098pccard_child_detached(device_t parent, device_t dev)
1099{
1100	struct pccard_ivar *ivar = PCCARD_IVAR(dev);
1101	struct pccard_function *pf = ivar->fcn;
1102
1103	pccard_function_disable(pf);
1104}
1105
1106static void
1107pccard_intr(void *arg)
1108{
1109	struct pccard_function *pf = (struct pccard_function*) arg;
1110	int reg;
1111
1112	/*
1113	 * If we go to resetting a card, we may need a null interrupt hanlder
1114	 * to work (since the system may call it before the device can
1115	 * establish an ISR) due to interrupt sharing at a higher level.
1116	 */
1117	if (pf->intr_handler == NULL)
1118		panic("Null interrupt handler?\n");
1119
1120	/*
1121	 * XXX The CCR_STATUS register bits used here are
1122	 * only valid for multi function cards.
1123	 */
1124	reg = pccard_ccr_read(pf, PCCARD_CCR_STATUS);
1125	if (reg & PCCARD_CCR_STATUS_INTR) {
1126		pccard_ccr_write(pf, PCCARD_CCR_STATUS,
1127				 reg & ~PCCARD_CCR_STATUS_INTR);
1128		pf->intr_handler(pf->intr_handler_arg);
1129	}
1130}
1131
1132static int
1133pccard_setup_intr(device_t dev, device_t child, struct resource *irq,
1134    int flags, driver_intr_t *intr, void *arg, void **cookiep)
1135{
1136	struct pccard_ivar *ivar = PCCARD_IVAR(child);
1137	struct pccard_function *func = ivar->fcn;
1138
1139	if (func->intr_handler != NULL)
1140		panic("Only one interrupt handler per function allowed\n");
1141
1142	func->intr_handler = intr;
1143	func->intr_handler_arg = arg;
1144	func->intr_handler_cookie = *cookiep;
1145	pccard_ccr_write(func, PCCARD_CCR_OPTION,
1146	    pccard_ccr_read(func, PCCARD_CCR_OPTION) |
1147	    PCCARD_CCR_OPTION_IREQ_ENABLE);
1148
1149	/*
1150	 * XXX Don't use TTY type for our interrupt handler.  It makes
1151	 * the spl masks wrong on -stable.  Instead, we should use the type
1152	 * that was requested of us.
1153	 */
1154	bus_setup_intr(dev, irq, INTR_TYPE_TTY/* | INTR_FAST*/,
1155	    pccard_intr, func, cookiep);
1156	return (0);
1157}
1158
1159static int
1160pccard_teardown_intr(device_t dev, device_t child, struct resource *r,
1161    void *cookie)
1162{
1163	struct pccard_ivar *ivar = PCCARD_IVAR(child);
1164	struct pccard_function *func = ivar->fcn;
1165	int ret;
1166
1167	pccard_ccr_write(func, PCCARD_CCR_OPTION,
1168	    pccard_ccr_read(func, PCCARD_CCR_OPTION) &
1169	    ~PCCARD_CCR_OPTION_IREQ_ENABLE);
1170
1171	ret = bus_teardown_intr(dev, r, cookie);
1172	if (ret == 0) {
1173		func->intr_handler = NULL;
1174		func->intr_handler_arg = NULL;
1175		func->intr_handler_cookie = NULL;
1176	}
1177
1178	return (ret);
1179}
1180
1181static device_method_t pccard_methods[] = {
1182	/* Device interface */
1183	DEVMETHOD(device_probe,		pccard_probe),
1184	DEVMETHOD(device_attach,	pccard_attach),
1185	DEVMETHOD(device_detach,	pccard_detach),
1186	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
1187	DEVMETHOD(device_suspend,	bus_generic_suspend),
1188	DEVMETHOD(device_resume,	bus_generic_resume),
1189
1190	/* Bus interface */
1191	DEVMETHOD(bus_print_child,	pccard_print_child),
1192	DEVMETHOD(bus_driver_added,	pccard_driver_added),
1193	DEVMETHOD(bus_child_detached,	pccard_child_detached),
1194	DEVMETHOD(bus_alloc_resource,	pccard_alloc_resource),
1195	DEVMETHOD(bus_release_resource,	pccard_release_resource),
1196	DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
1197	DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
1198	DEVMETHOD(bus_setup_intr,	pccard_setup_intr),
1199	DEVMETHOD(bus_teardown_intr,	pccard_teardown_intr),
1200	DEVMETHOD(bus_set_resource,	pccard_set_resource),
1201	DEVMETHOD(bus_get_resource,	pccard_get_resource),
1202	DEVMETHOD(bus_delete_resource,	pccard_delete_resource),
1203	DEVMETHOD(bus_read_ivar,	pccard_read_ivar),
1204
1205	/* Card Interface */
1206	DEVMETHOD(card_set_res_flags,	pccard_set_res_flags),
1207	DEVMETHOD(card_set_memory_offset, pccard_set_memory_offset),
1208	DEVMETHOD(card_get_type,	pccard_card_gettype),
1209	DEVMETHOD(card_attach_card,	pccard_attach_card),
1210	DEVMETHOD(card_detach_card,	pccard_detach_card),
1211	DEVMETHOD(card_compat_do_probe, pccard_compat_do_probe),
1212	DEVMETHOD(card_compat_do_attach, pccard_compat_do_attach),
1213
1214	{ 0, 0 }
1215};
1216
1217static driver_t pccard_driver = {
1218	"pccard",
1219	pccard_methods,
1220	sizeof(struct pccard_softc)
1221};
1222
1223devclass_t	pccard_devclass;
1224
1225DRIVER_MODULE(pccard, pcic, pccard_driver, pccard_devclass, 0, 0);
1226DRIVER_MODULE(pccard, pc98pcic, pccard_driver, pccard_devclass, 0, 0);
1227DRIVER_MODULE(pccard, pccbb, pccard_driver, pccard_devclass, 0, 0);
1228DRIVER_MODULE(pccard, tcic, pccard_driver, pccard_devclass, 0, 0);
1229MODULE_VERSION(pccard, 1);
1230/*MODULE_DEPEND(pccard, pcic, 1, 1, 1);*/
1231