xref: /freebsd/sys/dev/pccbb/pccbb.c (revision 70fe064ad7cab6c0444b91622f60ec6a462f308a)
1 /*
2  * Copyright (c) 2000,2001 Jonathan Chen.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions, and the following disclaimer,
10  *    without modification, immediately at the beginning of the file.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in
13  *    the documentation and/or other materials provided with the
14  *    distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
20  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  * $FreeBSD$
29  */
30 
31 /*
32  * Driver for PCI to Cardbus Bridge chips
33  *
34  * References:
35  *  TI Datasheets:
36  *   http://www-s.ti.com/cgi-bin/sc/generic2.cgi?family=PCI+CARDBUS+CONTROLLERS
37  *
38  * Written by Jonathan Chen <jon@freebsd.org>
39  * The author would like to acknowledge:
40  *  * HAYAKAWA Koichi: Author of the NetBSD code for the same thing
41  *  * Warner Losh: Newbus/newcard guru and author of the pccard side of things
42  *  * YAMAMOTO Shigeru: Author of another FreeBSD cardbus driver
43  *  * David Cross: Author of the initial ugly hack for a specific cardbus card
44  */
45 
46 #define	CBB_DEBUG
47 
48 #include <sys/param.h>
49 #include <sys/systm.h>
50 #include <sys/errno.h>
51 #include <sys/kernel.h>
52 #include <sys/kthread.h>
53 #include <sys/lock.h>
54 #include <sys/malloc.h>
55 #include <sys/mutex.h>
56 #include <sys/sysctl.h>
57 
58 #include <sys/bus.h>
59 #include <machine/bus.h>
60 #include <sys/rman.h>
61 #include <machine/resource.h>
62 
63 #include <pci/pcireg.h>
64 #include <pci/pcivar.h>
65 #include <machine/clock.h>
66 
67 #include <dev/pccard/pccardreg.h>
68 #include <dev/pccard/pccardvar.h>
69 
70 #include <dev/exca/excareg.h>
71 #include <dev/exca/excavar.h>
72 
73 #include <dev/pccbb/pccbbreg.h>
74 #include <dev/pccbb/pccbbvar.h>
75 
76 #include "power_if.h"
77 #include "card_if.h"
78 #include "pcib_if.h"
79 
80 #if defined CBB_DEBUG
81 #define	DPRINTF(x) printf x
82 #define	DEVPRINTF(x) device_printf x
83 #else
84 #define	DPRINTF(x)
85 #define	DEVPRINTF(x)
86 #endif
87 
88 #define	PCI_MASK_CONFIG(DEV,REG,MASK,SIZE)				\
89 	pci_write_config(DEV, REG, pci_read_config(DEV, REG, SIZE) MASK, SIZE)
90 #define	PCI_MASK2_CONFIG(DEV,REG,MASK1,MASK2,SIZE)			\
91 	pci_write_config(DEV, REG, (					\
92 		pci_read_config(DEV, REG, SIZE) MASK1) MASK2, SIZE)
93 
94 #define PCCBB_START_MEM	0x84000000
95 #define PCCBB_START_IO 0x1000
96 
97 struct pccbb_sclist {
98 	struct	pccbb_softc *sc;
99 	STAILQ_ENTRY(pccbb_sclist) entries;
100 };
101 
102 static STAILQ_HEAD(, pccbb_sclist) softcs;
103 static int softcs_init = 0;
104 
105 struct yenta_chipinfo {
106 	uint32_t yc_id;
107 	const	char *yc_name;
108 	int	yc_chiptype;
109 	int	yc_flags;
110 } yc_chipsets[] = {
111 	/* Texas Instruments chips */
112 	{PCI_DEVICE_ID_PCIC_TI1031, "TI1031 PCI-PCCard Bridge", CB_TI113X, 0},
113 	{PCI_DEVICE_ID_PCIC_TI1130, "TI1130 PCI-CardBus Bridge", CB_TI113X, 0},
114 	{PCI_DEVICE_ID_PCIC_TI1131, "TI1131 PCI-CardBus Bridge", CB_TI113X, 0},
115 
116 	{PCI_DEVICE_ID_PCIC_TI1210, "TI1210 PCI-CardBus Bridge", CB_TI12XX, 0},
117 	{PCI_DEVICE_ID_PCIC_TI1211, "TI1211 PCI-CardBus Bridge", CB_TI12XX, 0},
118 	{PCI_DEVICE_ID_PCIC_TI1220, "TI1220 PCI-CardBus Bridge", CB_TI12XX, 0},
119 	{PCI_DEVICE_ID_PCIC_TI1221, "TI1221 PCI-CardBus Bridge", CB_TI12XX, 0},
120 	{PCI_DEVICE_ID_PCIC_TI1225, "TI1225 PCI-CardBus Bridge", CB_TI12XX, 0},
121 	{PCI_DEVICE_ID_PCIC_TI1250, "TI1250 PCI-CardBus Bridge", CB_TI12XX, 0},
122 	{PCI_DEVICE_ID_PCIC_TI1251, "TI1251 PCI-CardBus Bridge", CB_TI12XX, 0},
123 	{PCI_DEVICE_ID_PCIC_TI1251B,"TI1251B PCI-CardBus Bridge",CB_TI12XX, 0},
124 	{PCI_DEVICE_ID_PCIC_TI1260, "TI1260 PCI-CardBus Bridge", CB_TI12XX, 0},
125 	{PCI_DEVICE_ID_PCIC_TI1260B, "TI1260B PCI-CardBus Bridge", CB_TI12XX,
126 	    0},
127 	{PCI_DEVICE_ID_PCIC_TI1410, "TI1410 PCI-CardBus Bridge", CB_TI12XX, 0},
128 	{PCI_DEVICE_ID_PCIC_TI1420, "TI1420 PCI-CardBus Bridge", CB_TI12XX, 0},
129 	{PCI_DEVICE_ID_PCIC_TI1421, "TI1421 PCI-CardBus Bridge", CB_TI12XX, 0},
130 	{PCI_DEVICE_ID_PCIC_TI1450, "TI1450 PCI-CardBus Bridge", CB_TI12XX, 0},
131 	{PCI_DEVICE_ID_PCIC_TI1451, "TI1451 PCI-CardBus Bridge", CB_TI12XX, 0},
132 	{PCI_DEVICE_ID_PCIC_TI4410, "TI4410 PCI-CardBus Bridge", CB_TI12XX, 0},
133 	{PCI_DEVICE_ID_PCIC_TI4450, "TI4450 PCI-CardBus Bridge", CB_TI12XX, 0},
134 	{PCI_DEVICE_ID_PCIC_TI4451, "TI4451 PCI-CardBus Bridge", CB_TI12XX, 0},
135 
136 	/* Ricoh chips */
137 	{PCI_DEVICE_ID_RICOH_RL5C465, "RF5C465 PCI-CardBus Bridge",
138 	    CB_RF5C46X, 0},
139 	{PCI_DEVICE_ID_RICOH_RL5C466, "RF5C466 PCI-CardBus Bridge",
140 	    CB_RF5C46X, 0},
141 	{PCI_DEVICE_ID_RICOH_RL5C475, "RF5C475 PCI-CardBus Bridge",
142 	    CB_RF5C47X, 0},
143 	{PCI_DEVICE_ID_RICOH_RL5C476, "RF5C476 PCI-CardBus Bridge",
144 	    CB_RF5C47X, 0},
145 	{PCI_DEVICE_ID_RICOH_RL5C478, "RF5C478 PCI-CardBus Bridge",
146 	    CB_RF5C47X, 0},
147 
148 	/* Toshiba products */
149 	{PCI_DEVICE_ID_TOSHIBA_TOPIC95, "ToPIC95 PCI-CardBus Bridge",
150 	    CB_TOPIC95, 0},
151 	{PCI_DEVICE_ID_TOSHIBA_TOPIC95B, "ToPIC95B PCI-CardBus Bridge",
152 	    CB_TOPIC95B, 0},
153 	{PCI_DEVICE_ID_TOSHIBA_TOPIC97, "ToPIC97 PCI-CardBus Bridge",
154 	    CB_TOPIC97, 0},
155 	{PCI_DEVICE_ID_TOSHIBA_TOPIC100, "ToPIC100 PCI-CardBus Bridge",
156 	    CB_TOPIC97, 0},
157 
158 	/* Cirrus Logic */
159 	{PCI_DEVICE_ID_PCIC_CLPD6832, "CLPD6832 PCI-CardBus Bridge",
160 	    CB_CIRRUS, 0},
161 	{PCI_DEVICE_ID_PCIC_CLPD6833, "CLPD6833 PCI-CardBus Bridge",
162 	    CB_CIRRUS, 0},
163 	{PCI_DEVICE_ID_PCIC_CLPD6834, "CLPD6834 PCI-CardBus Bridge",
164 	    CB_CIRRUS, 0},
165 
166 	/* 02Micro */
167 	{PCI_DEVICE_ID_PCIC_OZ6832, "O2Mirco OZ6832/6833 PCI-CardBus Bridge",
168 	    CB_CIRRUS, 0},
169 	{PCI_DEVICE_ID_PCIC_OZ6860, "O2Mirco OZ6836/6860 PCI-CardBus Bridge",
170 	    CB_CIRRUS, 0},
171 	{PCI_DEVICE_ID_PCIC_OZ6872, "O2Mirco OZ6812/6872 PCI-CardBus Bridge",
172 	    CB_CIRRUS, 0},
173 	{PCI_DEVICE_ID_PCIC_OZ6912, "O2Mirco OZ6912/6972 PCI-CardBus Bridge",
174 	    CB_CIRRUS, 0},
175 	{PCI_DEVICE_ID_PCIC_OZ6922, "O2Mirco OZ6822 PCI-CardBus Bridge",
176 	    CB_CIRRUS, 0},
177 	{PCI_DEVICE_ID_PCIC_OZ6933, "O2Mirco OZ6833 PCI-CardBus Bridge",
178 	    CB_CIRRUS, 0},
179 
180 	/* sentinel */
181 	{0 /* null id */, "unknown",
182 	    CB_UNKNOWN, 0},
183 };
184 
185 /* sysctl vars */
186 SYSCTL_NODE(_hw, OID_AUTO, pccbb, CTLFLAG_RD, 0, "PCCBB parameters");
187 
188 /* There's no way to say TUNEABLE_LONG to get the right types */
189 u_long pccbb_start_mem = PCCBB_START_MEM;
190 TUNABLE_INT("hw.pccbb.start_memory", (int *)&pccbb_start_mem);
191 SYSCTL_ULONG(_hw_pccbb, OID_AUTO, start_mem, CTLFLAG_RD,
192     &pccbb_start_mem, PCCBB_START_MEM,
193     "Starting address for memory allocations");
194 
195 static int	pccbb_chipset(uint32_t pci_id, const char **namep, int *flagp);
196 static int	pccbb_probe(device_t brdev);
197 static void	pccbb_chipinit(struct pccbb_softc *sc);
198 static int	pccbb_attach(device_t brdev);
199 static int	pccbb_detach(device_t brdev);
200 static int	pccbb_shutdown(device_t brdev);
201 static void	pccbb_driver_added(device_t brdev, driver_t *driver);
202 static void	pccbb_child_detached(device_t brdev, device_t child);
203 static int	pccbb_card_reprobe(device_t brdev, device_t busdev);
204 static void	pccbb_event_thread(void *arg);
205 static void	pccbb_create_event_thread(struct pccbb_softc *sc);
206 static void	pccbb_start_threads(void *arg);
207 static void	pccbb_insert(struct pccbb_softc *sc);
208 static void	pccbb_removal(struct pccbb_softc *sc);
209 static void	pccbb_intr(void *arg);
210 static int	pccbb_detect_voltage(device_t brdev);
211 static int	pccbb_power(device_t brdev, int volts);
212 static void	pccbb_cardbus_reset(device_t brdev);
213 static int	pccbb_cardbus_power_enable_socket(device_t brdev,
214 		    device_t child);
215 static void	pccbb_cardbus_power_disable_socket(device_t brdev,
216 		    device_t child);
217 static int	pccbb_cardbus_io_open(device_t brdev, int win, uint32_t start,
218 		    uint32_t end);
219 static int	pccbb_cardbus_mem_open(device_t brdev, int win,
220 		    uint32_t start, uint32_t end);
221 static void	pccbb_cardbus_auto_open(struct pccbb_softc *sc, int type);
222 static int	pccbb_cardbus_activate_resource(device_t brdev, device_t child,
223 		    int type, int rid, struct resource *res);
224 static int	pccbb_cardbus_deactivate_resource(device_t brdev,
225 		    device_t child, int type, int rid, struct resource *res);
226 static struct resource	*pccbb_cardbus_alloc_resource(device_t brdev,
227 		    device_t child, int type, int *rid, u_long start,
228 		    u_long end, u_long count, uint flags);
229 static int	pccbb_cardbus_release_resource(device_t brdev, device_t child,
230 		    int type, int rid, struct resource *res);
231 static int	pccbb_power_enable_socket(device_t brdev, device_t child);
232 static void	pccbb_power_disable_socket(device_t brdev, device_t child);
233 static int	pccbb_activate_resource(device_t brdev, device_t child,
234 		    int type, int rid, struct resource *r);
235 static int	pccbb_deactivate_resource(device_t brdev, device_t child,
236 		    int type, int rid, struct resource *r);
237 static struct resource	*pccbb_alloc_resource(device_t brdev, device_t child,
238 		    int type, int *rid, u_long start, u_long end, u_long count,
239 		    uint flags);
240 static int	pccbb_release_resource(device_t brdev, device_t child,
241 		    int type, int rid, struct resource *r);
242 static int	pccbb_read_ivar(device_t brdev, device_t child, int which,
243 		    uintptr_t *result);
244 static int	pccbb_write_ivar(device_t brdev, device_t child, int which,
245 		    uintptr_t value);
246 static int	pccbb_maxslots(device_t brdev);
247 static uint32_t pccbb_read_config(device_t brdev, int b, int s, int f,
248 		    int reg, int width);
249 static void	pccbb_write_config(device_t brdev, int b, int s, int f,
250 		    int reg, uint32_t val, int width);
251 
252 /*
253  */
254 static __inline void
255 pccbb_set(struct pccbb_softc *sc, uint32_t reg, uint32_t val)
256 {
257 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, reg, val);
258 }
259 
260 static __inline uint32_t
261 pccbb_get(struct pccbb_softc *sc, uint32_t reg)
262 {
263 	return (bus_space_read_4(sc->sc_bst, sc->sc_bsh, reg));
264 }
265 
266 static __inline void
267 pccbb_setb(struct pccbb_softc *sc, uint32_t reg, uint32_t bits)
268 {
269 	pccbb_set(sc, reg, pccbb_get(sc, reg) | bits);
270 }
271 
272 static __inline void
273 pccbb_clrb(struct pccbb_softc *sc, uint32_t reg, uint32_t bits)
274 {
275 	pccbb_set(sc, reg, pccbb_get(sc, reg) & ~bits);
276 }
277 
278 static __inline uint8_t
279 pccbb_pcic_read(struct exca_softc *sc, int reg)
280 {
281 	return (bus_space_read_1(sc->bst, sc->bsh, sc->offset + reg));
282 }
283 
284 static __inline void
285 pccbb_pcic_write(struct exca_softc *sc, int reg, uint8_t val)
286 {
287 	return (bus_space_write_1(sc->bst, sc->bsh, sc->offset + reg, val));
288 }
289 
290 static void
291 pccbb_remove_res(struct pccbb_softc *sc, struct resource *res)
292 {
293 	struct pccbb_reslist *rle;
294 
295 	SLIST_FOREACH(rle, &sc->rl, link) {
296 		if (rle->res == res) {
297 			SLIST_REMOVE(&sc->rl, rle, pccbb_reslist, link);
298 			free(rle, M_DEVBUF);
299 			return;
300 		}
301 	}
302 }
303 
304 static struct resource *
305 pccbb_find_res(struct pccbb_softc *sc, int type, int rid)
306 {
307 	struct pccbb_reslist *rle;
308 
309 	SLIST_FOREACH(rle, &sc->rl, link)
310 		if (SYS_RES_MEMORY == rle->type && rid == rle->rid)
311 			return (rle->res);
312 	return (NULL);
313 }
314 
315 static void
316 pccbb_insert_res(struct pccbb_softc *sc, struct resource *res, int type,
317     int rid)
318 {
319 	struct pccbb_reslist *rle;
320 
321 	/*
322 	 * Need to record allocated resource so we can iterate through
323 	 * it later.
324 	 */
325 	rle = malloc(sizeof(struct pccbb_reslist), M_DEVBUF, M_NOWAIT);
326 	if (!res)
327 		panic("pccbb_cardbus_alloc_resource: can't record entry!");
328 	rle->res = res;
329 	rle->type = type;
330 	rle->rid = rid;
331 	SLIST_INSERT_HEAD(&sc->rl, rle, link);
332 }
333 
334 static void
335 pccbb_destroy_res(struct pccbb_softc *sc)
336 {
337 	struct pccbb_reslist *rle;
338 
339 	while ((rle = SLIST_FIRST(&sc->rl)) != NULL) {
340 		device_printf(sc->sc_dev, "Danger Will Robinson: Resource "
341 		    "left allocated!  This is a bug... "
342 		    "(rid=%x, type=%d, addr=%lx)\n", rle->rid, rle->type,
343 		    rman_get_start(rle->res));
344 		SLIST_REMOVE_HEAD(&sc->rl, link);
345 		free(rle, M_DEVBUF);
346 	}
347 }
348 
349 /************************************************************************/
350 /* Probe/Attach								*/
351 /************************************************************************/
352 
353 static int
354 pccbb_chipset(uint32_t pci_id, const char **namep, int *flagp)
355 {
356 	int loopend = sizeof(yc_chipsets)/sizeof(yc_chipsets[0]);
357 	struct yenta_chipinfo *ycp, *ycend;
358 	ycend = yc_chipsets + loopend;
359 
360 	for (ycp = yc_chipsets; ycp < ycend && pci_id != ycp->yc_id; ++ycp)
361 	    continue;
362 	if (ycp == ycend)
363 		/* not found */
364 		ycp = yc_chipsets + loopend - 1; /* to point the sentinel */
365 	if (namep != NULL)
366 		*namep = ycp->yc_name;
367 	if (flagp != NULL)
368 		*flagp = ycp->yc_flags;
369 	return (ycp->yc_chiptype);
370 }
371 
372 static int
373 pccbb_probe(device_t brdev)
374 {
375 	const char *name;
376 
377 	if (pccbb_chipset(pci_get_devid(brdev), &name, NULL) == CB_UNKNOWN)
378 		return (ENXIO);
379 	device_set_desc(brdev, name);
380 	return (0);
381 }
382 
383 static void
384 pccbb_chipinit(struct pccbb_softc *sc)
385 {
386 	/* Set CardBus latency timer */
387 	if (pci_read_config(sc->sc_dev, PCIR_SECLAT_1, 1) < 0x20)
388 		pci_write_config(sc->sc_dev, PCIR_SECLAT_1, 0x20, 1);
389 
390 	/* Set PCI latency timer */
391 	if (pci_read_config(sc->sc_dev, PCIR_LATTIMER, 1) < 0x20)
392 		pci_write_config(sc->sc_dev, PCIR_LATTIMER, 0x20, 1);
393 
394 	/* Enable memory access */
395 	PCI_MASK_CONFIG(sc->sc_dev, PCIR_COMMAND,
396 	    | PCIM_CMD_MEMEN
397 	    | PCIM_CMD_PORTEN
398 	    | PCIM_CMD_BUSMASTEREN, 2);
399 
400 	/* disable Legacy IO */
401 	switch (sc->sc_chipset) {
402 	case CB_RF5C46X:
403 		PCI_MASK_CONFIG(sc->sc_dev, PCCBBR_BRIDGECTRL,
404 		    & ~(PCCBBM_BRIDGECTRL_RL_3E0_EN |
405 		    PCCBBM_BRIDGECTRL_RL_3E2_EN), 2);
406 		break;
407 	default:
408 		pci_write_config(sc->sc_dev, PCCBBR_LEGACY, 0x0, 4);
409 		break;
410 	}
411 
412 	/* Use PCI interrupt for interrupt routing */
413 	PCI_MASK2_CONFIG(sc->sc_dev, PCCBBR_BRIDGECTRL,
414 	    & ~(PCCBBM_BRIDGECTRL_MASTER_ABORT |
415 	    PCCBBM_BRIDGECTRL_INTR_IREQ_EN),
416 	    | PCCBBM_BRIDGECTRL_WRITE_POST_EN,
417 	    2);
418 
419 	/* XXX this should be a function table, ala OLDCARD. */
420 	switch (sc->sc_chipset) {
421 	case CB_TI113X:
422 		/*
423 		 * The TI 1031, TI 1130 and TI 1131 all require another bit
424 		 * be set to enable PCI routing of interrupts, and then
425 		 * a bit for each of the CSC and Function interrupts we
426 		 * want routed.
427 		 */
428 		PCI_MASK_CONFIG(sc->sc_dev, PCCBBR_CBCTRL,
429 		    | PCCBBM_CBCTRL_113X_PCI_INTR |
430 		    PCCBBM_CBCTRL_113X_PCI_CSC | PCCBBM_CBCTRL_113X_PCI_IRQ_EN,
431 		    1);
432 		PCI_MASK_CONFIG(sc->sc_dev, PCCBBR_DEVCTRL,
433 		    & ~(PCCBBM_DEVCTRL_INT_SERIAL |
434 		    PCCBBM_DEVCTRL_INT_PCI), 1);
435 		exca_write(&sc->exca, EXCA_INTR, EXCA_INTR_ENABLE);
436 		exca_write(&sc->exca, EXCA_CSC_INTR, 0);
437 		break;
438 	case CB_TI12XX:
439 		exca_write(&sc->exca, EXCA_INTR, EXCA_INTR_ENABLE);
440 		exca_write(&sc->exca, EXCA_CSC_INTR, 0);
441 		break;
442 	case CB_TOPIC95B:
443 		PCI_MASK_CONFIG(sc->sc_dev, PCCBBR_TOPIC_SOCKETCTRL,
444 		    | PCCBBM_TOPIC_SOCKETCTRL_SCR_IRQSEL, 4);
445 		PCI_MASK2_CONFIG(sc->sc_dev, PCCBBR_TOPIC_SLOTCTRL,
446 		    | PCCBBM_TOPIC_SLOTCTRL_SLOTON |
447 		    PCCBBM_TOPIC_SLOTCTRL_SLOTEN |
448 		    PCCBBM_TOPIC_SLOTCTRL_ID_LOCK |
449 		    PCCBBM_TOPIC_SLOTCTRL_CARDBUS,
450 		    & ~PCCBBM_TOPIC_SLOTCTRL_SWDETECT, 4);
451 		break;
452 	}
453 
454 	/* close all memory and io windows */
455 	pci_write_config(sc->sc_dev, PCCBBR_MEMBASE0, 0xffffffff, 4);
456 	pci_write_config(sc->sc_dev, PCCBBR_MEMLIMIT0, 0, 4);
457 	pci_write_config(sc->sc_dev, PCCBBR_MEMBASE1, 0xffffffff, 4);
458 	pci_write_config(sc->sc_dev, PCCBBR_MEMLIMIT1, 0, 4);
459 	pci_write_config(sc->sc_dev, PCCBBR_IOBASE0, 0xffffffff, 4);
460 	pci_write_config(sc->sc_dev, PCCBBR_IOLIMIT0, 0, 4);
461 	pci_write_config(sc->sc_dev, PCCBBR_IOBASE1, 0xffffffff, 4);
462 	pci_write_config(sc->sc_dev, PCCBBR_IOLIMIT1, 0, 4);
463 }
464 
465 static int
466 pccbb_attach(device_t brdev)
467 {
468 	struct pccbb_softc *sc = (struct pccbb_softc *)device_get_softc(brdev);
469 	int rid;
470 	uint32_t sockbase;
471 	struct pccbb_sclist *sclist;
472 
473 	if (!softcs_init) {
474 		softcs_init = 1;
475 		STAILQ_INIT(&softcs);
476 	}
477 	mtx_init(&sc->sc_mtx, device_get_nameunit(brdev), MTX_DEF);
478 	sc->sc_chipset = pccbb_chipset(pci_get_devid(brdev), NULL, &sc->sc_flags);
479 	sc->sc_dev = brdev;
480 	sc->sc_cbdev = NULL;
481 	sc->sc_pccarddev = NULL;
482 	sc->sc_secbus = pci_read_config(brdev, PCIR_SECBUS_2, 1);
483 	sc->sc_subbus = pci_read_config(brdev, PCIR_SUBBUS_2, 1);
484 	SLIST_INIT(&sc->rl);
485 
486 	/*
487 	 * The PCI bus code should assign us memory in the absense
488 	 * of the BIOS doing so.  However, 'should' isn't 'is,' so we hack
489 	 * up something here until the PCI code is up to snuff.
490 	 */
491 	rid = PCCBBR_SOCKBASE;
492 	sc->sc_base_res = bus_alloc_resource(brdev, SYS_RES_MEMORY, &rid,
493 	    0, ~0, 1, RF_ACTIVE);
494 	if (!sc->sc_base_res) {
495 		/*
496 		 * XXX EVILE HACK BAD THING! XXX
497 		 * The pci bus device should do this for us.
498 		 * Some BIOSes doesn't assign a memory space properly.
499 		 * So we try to manually put one in...
500 		 */
501 		sockbase = pci_read_config(brdev, rid, 4);
502 		if (sockbase < 0x100000 || sockbase >= 0xfffffff0) {
503 			pci_write_config(brdev, rid, 0xffffffff, 4);
504 			sockbase = pci_read_config(brdev, rid, 4);
505 			sockbase = (sockbase & 0xfffffff0) &
506 			    -(sockbase & 0xfffffff0);
507 			sc->sc_base_res = bus_generic_alloc_resource(
508 			    device_get_parent(brdev), brdev, SYS_RES_MEMORY,
509 			    &rid, pccbb_start_mem, ~0, sockbase,
510 			    RF_ACTIVE|rman_make_alignment_flags(sockbase));
511 			if (!sc->sc_base_res){
512 				device_printf(brdev,
513 				    "Could not grab register memory\n");
514 				mtx_destroy(&sc->sc_mtx);
515 				return (ENOMEM);
516 			}
517 			pci_write_config(brdev, PCCBBR_SOCKBASE,
518 			    rman_get_start(sc->sc_base_res), 4);
519 			DEVPRINTF((brdev, "PCI Memory allocated: %08lx\n",
520 			    rman_get_start(sc->sc_base_res)));
521 		} else {
522 			device_printf(brdev, "Could not map register memory\n");
523 			mtx_destroy(&sc->sc_mtx);
524 			return (ENOMEM);
525 		}
526 	}
527 
528 	sc->sc_bst = rman_get_bustag(sc->sc_base_res);
529 	sc->sc_bsh = rman_get_bushandle(sc->sc_base_res);
530 	exca_init(&sc->exca, brdev, &pccbb_pcic_write, &pccbb_pcic_read,
531 	  sc->sc_bst, sc->sc_bsh, 0x800);
532 	pccbb_chipinit(sc);
533 
534 	/* CSC Interrupt: Card detect interrupt on */
535 	pccbb_setb(sc, PCCBB_SOCKET_MASK, PCCBB_SOCKET_MASK_CD);
536 
537 	/* reset interrupt */
538 	pccbb_set(sc, PCCBB_SOCKET_EVENT, pccbb_get(sc, PCCBB_SOCKET_EVENT));
539 
540 	/* Map and establish the interrupt. */
541 	rid = 0;
542 	sc->sc_irq_res = bus_alloc_resource(brdev, SYS_RES_IRQ, &rid, 0, ~0, 1,
543 	    RF_SHAREABLE | RF_ACTIVE);
544 	if (sc->sc_irq_res == NULL) {
545 		printf("pccbb: Unable to map IRQ...\n");
546 		bus_release_resource(brdev, SYS_RES_MEMORY, PCCBBR_SOCKBASE,
547 		    sc->sc_base_res);
548 		mtx_destroy(&sc->sc_mtx);
549 		return (ENOMEM);
550 	}
551 
552 	/* XXX INTR_TYPE_BIO IS WRONG here */
553 	if (bus_setup_intr(brdev, sc->sc_irq_res, INTR_TYPE_BIO, pccbb_intr, sc,
554 	    &sc->sc_intrhand)) {
555 		device_printf(brdev, "couldn't establish interrupt");
556 		bus_release_resource(brdev, SYS_RES_IRQ, 0, sc->sc_irq_res);
557 		bus_release_resource(brdev, SYS_RES_MEMORY, PCCBBR_SOCKBASE,
558 		    sc->sc_base_res);
559 		mtx_destroy(&sc->sc_mtx);
560 		return (ENOMEM);
561 	}
562 
563 	/* attach children */
564 	sc->sc_cbdev = device_add_child(brdev, "cardbus", -1);
565 	if (sc->sc_cbdev == NULL)
566 		DEVPRINTF((brdev, "WARNING: cannot add cardbus bus.\n"));
567 	else if (device_probe_and_attach(sc->sc_cbdev) != 0) {
568 		DEVPRINTF((brdev, "WARNING: cannot attach cardbus bus!\n"));
569 		sc->sc_cbdev = NULL;
570 	}
571 
572 	sc->sc_pccarddev = device_add_child(brdev, "pccard", -1);
573 	if (sc->sc_pccarddev == NULL)
574 		DEVPRINTF((brdev, "WARNING: cannot add pccard bus.\n"));
575 	else if (device_probe_and_attach(sc->sc_pccarddev) != 0) {
576 		DEVPRINTF((brdev, "WARNING: cannot attach pccard bus.\n"));
577 		sc->sc_pccarddev = NULL;
578 	}
579 
580 	sclist = malloc(sizeof(struct pccbb_sclist), M_DEVBUF, M_WAITOK);
581 	sclist->sc = sc;
582 	STAILQ_INSERT_TAIL(&softcs, sclist, entries);
583 	return (0);
584 }
585 
586 static int
587 pccbb_detach(device_t brdev)
588 {
589 	struct pccbb_softc *sc = device_get_softc(brdev);
590 	int numdevs;
591 	device_t *devlist;
592 	int tmp;
593 	int error;
594 
595 	device_get_children(brdev, &devlist, &numdevs);
596 
597 	error = 0;
598 	for (tmp = 0; tmp < numdevs; tmp++) {
599 		if (device_detach(devlist[tmp]) == 0)
600 			device_delete_child(brdev, devlist[tmp]);
601 		else
602 			error++;
603 	}
604 	free(devlist, M_TEMP);
605 	if (error > 0)
606 		return (ENXIO);
607 
608 	mtx_lock(&sc->sc_mtx);
609 	bus_teardown_intr(brdev, sc->sc_irq_res, sc->sc_intrhand);
610 
611 	sc->sc_flags |= PCCBB_KTHREAD_DONE;
612 	if (sc->sc_flags & PCCBB_KTHREAD_RUNNING) {
613 		wakeup(sc);
614 		mtx_unlock(&sc->sc_mtx);
615 		DEVPRINTF((brdev, "waiting for kthread exit..."));
616 		error = tsleep(sc, PWAIT, "pccbb-detach-wait", 60 * hz);
617 		if (error)
618 			DPRINTF(("timeout\n"));
619 		else
620 			DPRINTF(("done\n"));
621 	} else {
622 		mtx_unlock(&sc->sc_mtx);
623 	}
624 
625 	bus_release_resource(brdev, SYS_RES_IRQ, 0, sc->sc_irq_res);
626 	bus_release_resource(brdev, SYS_RES_MEMORY, PCCBBR_SOCKBASE,
627 	    sc->sc_base_res);
628 	mtx_destroy(&sc->sc_mtx);
629 	return (0);
630 }
631 
632 static int
633 pccbb_shutdown(device_t brdev)
634 {
635 	struct pccbb_softc *sc = (struct pccbb_softc *)device_get_softc(brdev);
636 	/* properly reset everything at shutdown */
637 
638 	PCI_MASK_CONFIG(brdev, PCCBBR_BRIDGECTRL, |PCCBBM_BRIDGECTRL_RESET, 2);
639 	exca_clrb(&sc->exca, EXCA_INTR, EXCA_INTR_RESET);
640 
641 	pccbb_set(sc, PCCBB_SOCKET_MASK, 0);
642 
643 	pccbb_power(brdev, CARD_VCC_0V | CARD_VPP_0V);
644 
645 	exca_write(&sc->exca, EXCA_ADDRWIN_ENABLE, 0);
646 	pci_write_config(brdev, PCCBBR_MEMBASE0, 0, 4);
647 	pci_write_config(brdev, PCCBBR_MEMLIMIT0, 0, 4);
648 	pci_write_config(brdev, PCCBBR_MEMBASE1, 0, 4);
649 	pci_write_config(brdev, PCCBBR_MEMLIMIT1, 0, 4);
650 	pci_write_config(brdev, PCCBBR_IOBASE0, 0, 4);
651 	pci_write_config(brdev, PCCBBR_IOLIMIT0, 0, 4);
652 	pci_write_config(brdev, PCCBBR_IOBASE1, 0, 4);
653 	pci_write_config(brdev, PCCBBR_IOLIMIT1, 0, 4);
654 	pci_write_config(brdev, PCIR_COMMAND, 0, 2);
655 	return (0);
656 }
657 
658 static void
659 pccbb_driver_added(device_t brdev, driver_t *driver)
660 {
661 	struct pccbb_softc *sc = device_get_softc(brdev);
662 	device_t *devlist;
663 	int tmp;
664 	int numdevs;
665 	int wake;
666 	uint32_t sockstate;
667 
668 	DEVICE_IDENTIFY(driver, brdev);
669 	device_get_children(brdev, &devlist, &numdevs);
670 	wake = 0;
671 	sockstate = pccbb_get(sc, PCCBB_SOCKET_STATE);
672 	for (tmp = 0; tmp < numdevs; tmp++) {
673 		if (device_get_state(devlist[tmp]) == DS_NOTPRESENT &&
674 		    device_probe_and_attach(devlist[tmp]) == 0) {
675 			if (devlist[tmp] == NULL)
676 				/* NOTHING */;
677 			else if (strcmp(driver->name, "cardbus") == 0) {
678 				sc->sc_cbdev = devlist[tmp];
679 				if (((sockstate & PCCBB_SOCKET_STAT_CD) == 0) &&
680 				    (sockstate & PCCBB_SOCKET_STAT_CB))
681 					wake++;
682 			} else if (strcmp(driver->name, "pccard") == 0) {
683 				sc->sc_pccarddev = devlist[tmp];
684 				if (((sockstate & PCCBB_SOCKET_STAT_CD) == 0) &&
685 				    (sockstate & PCCBB_SOCKET_STAT_16BIT))
686 					wake++;
687 			} else
688 				device_printf(brdev,
689 				    "Unsupported child bus: %s\n",
690 				    driver->name);
691 		}
692 	}
693 	free(devlist, M_TEMP);
694 
695 	if (wake > 0) {
696 		if ((pccbb_get(sc, PCCBB_SOCKET_STATE) & PCCBB_SOCKET_STAT_CD)
697 		    == 0) {
698 			mtx_lock(&sc->sc_mtx);
699 			wakeup(sc);
700 			mtx_unlock(&sc->sc_mtx);
701 		}
702 	}
703 }
704 
705 static void
706 pccbb_child_detached(device_t brdev, device_t child)
707 {
708 	struct pccbb_softc *sc = device_get_softc(brdev);
709 
710 	if (child == sc->sc_cbdev)
711 		sc->sc_cbdev = NULL;
712 	else if (child == sc->sc_pccarddev)
713 		sc->sc_pccarddev = NULL;
714 	else
715 		device_printf(brdev, "Unknown child detached: %s %p/%p\n",
716 		    device_get_nameunit(child), sc->sc_cbdev, sc->sc_pccarddev);
717 }
718 
719 static int
720 pccbb_card_reprobe(device_t brdev, device_t busdev)
721 {
722 	struct pccbb_softc *sc = device_get_softc(brdev);
723 	int wake = 0;
724 	uint32_t sockstate;
725 
726 	sockstate = pccbb_get(sc, PCCBB_SOCKET_STATE);
727 
728 	if ((sockstate & PCCBB_SOCKET_STAT_CD) == 0) {
729 		if (busdev == sc->sc_cbdev &&
730 		    (sockstate & PCCBB_SOCKET_STAT_CB))
731 			wake++;
732 		else if (busdev == sc->sc_pccarddev &&
733 		    (sockstate & PCCBB_SOCKET_STAT_16BIT))
734 			wake++;
735 
736 		if (wake > 0) {
737 			mtx_lock(&sc->sc_mtx);
738 			wakeup(sc);
739 			mtx_unlock(&sc->sc_mtx);
740 			return (0);
741 		}
742 		return (EBUSY);
743 	}
744 	return (ENOENT);
745 }
746 
747 /************************************************************************/
748 /* Kthreads								*/
749 /************************************************************************/
750 
751 static void
752 pccbb_event_thread(void *arg)
753 {
754 	struct pccbb_softc *sc = arg;
755 	uint32_t status;
756 
757 	mtx_lock(&Giant);
758 	for(;;) {
759 		if (!(sc->sc_flags & PCCBB_KTHREAD_RUNNING)) {
760 			sc->sc_flags |= PCCBB_KTHREAD_RUNNING;
761 		} else {
762 			tsleep (sc, PWAIT, "pccbbev", 0);
763 			/*
764 			 * Delay 1 second, make sure the user is done with
765 			 * whatever he is doing.  We tsleep on sc->sc_flags,
766 			 * which should never be woken up.
767 			 *
768 			 * XXX Note: This can cause problems on card
769 			 * removal.  See OLDCARD's ISR for how you may
770 			 * have to deal with the debouncing problem.  The
771 			 * crux of the issue is interrupts delivered to
772 			 * the card after eject are unstable.
773 			 */
774 			tsleep (&sc->sc_flags, PWAIT, "pccbbev", 1*hz);
775 		}
776 		mtx_lock(&sc->sc_mtx);
777 		if (sc->sc_flags & PCCBB_KTHREAD_DONE)
778 			break;
779 
780 		status = pccbb_get(sc, PCCBB_SOCKET_STATE);
781 		if ((status & PCCBB_SOCKET_STAT_CD) == 0) {
782 			pccbb_insert(sc);
783 		} else {
784 			pccbb_removal(sc);
785 		}
786 		mtx_unlock(&sc->sc_mtx);
787 	}
788 	mtx_unlock(&sc->sc_mtx);
789 	sc->sc_flags &= ~PCCBB_KTHREAD_RUNNING;
790 	wakeup(sc);
791 	kthread_exit(0);
792 }
793 
794 static void
795 pccbb_create_event_thread(struct pccbb_softc *sc)
796 {
797 	if (kthread_create(pccbb_event_thread, sc, &sc->event_thread,
798 	    0, "%s%d", device_get_name(sc->sc_dev),
799 	    device_get_unit(sc->sc_dev))) {
800 		device_printf (sc->sc_dev, "unable to create event thread.\n");
801 		panic ("pccbb_create_event_thread");
802 	}
803 }
804 
805 static void
806 pccbb_start_threads(void *arg)
807 {
808 	struct pccbb_sclist *sclist;
809 
810 	STAILQ_FOREACH(sclist, &softcs, entries) {
811 		pccbb_create_event_thread(sclist->sc);
812 	}
813 }
814 
815 /************************************************************************/
816 /* Insert/removal							*/
817 /************************************************************************/
818 
819 static void
820 pccbb_insert(struct pccbb_softc *sc)
821 {
822 	uint32_t sockevent, sockstate;
823 	int timeout = 30;
824 
825 	do {
826 		sockevent = pccbb_get(sc, PCCBB_SOCKET_EVENT);
827 		sockstate = pccbb_get(sc, PCCBB_SOCKET_STATE);
828 	} while (sockstate & PCCBB_SOCKET_STAT_CD && --timeout > 0);
829 
830 	if (timeout < 0) {
831 		device_printf (sc->sc_dev, "insert timeout");
832 		return;
833 	}
834 
835 	DEVPRINTF((sc->sc_dev, "card inserted: event=0x%08x, state=%08x\n",
836 	    sockevent, sockstate));
837 
838 	if (sockstate & PCCBB_SOCKET_STAT_16BIT && sc->sc_pccarddev != NULL) {
839 		sc->sc_flags |= PCCBB_16BIT_CARD;
840 		if (CARD_ATTACH_CARD(sc->sc_pccarddev) != 0)
841 			device_printf(sc->sc_dev, "card activation failed\n");
842 	} else if (sockstate & PCCBB_SOCKET_STAT_CB && sc->sc_cbdev != NULL) {
843 		sc->sc_flags &= ~PCCBB_16BIT_CARD;
844 		if (CARD_ATTACH_CARD(sc->sc_cbdev) != 0)
845 			device_printf(sc->sc_dev, "card activation failed\n");
846 	} else {
847 		device_printf (sc->sc_dev, "Unsupported card type detected\n");
848 	}
849 }
850 
851 static void
852 pccbb_removal(struct pccbb_softc *sc)
853 {
854 	if (sc->sc_flags & PCCBB_16BIT_CARD && sc->sc_pccarddev != NULL)
855 		CARD_DETACH_CARD(sc->sc_pccarddev, DETACH_FORCE);
856 	else if ((!(sc->sc_flags & PCCBB_16BIT_CARD)) && sc->sc_cbdev != NULL)
857 		CARD_DETACH_CARD(sc->sc_cbdev, DETACH_FORCE);
858 	pccbb_destroy_res(sc);
859 }
860 
861 /************************************************************************/
862 /* Interrupt Handler							*/
863 /************************************************************************/
864 
865 static void
866 pccbb_intr(void *arg)
867 {
868 	struct pccbb_softc *sc = arg;
869 	uint32_t sockevent;
870 
871 	if (!(sockevent = pccbb_get(sc, PCCBB_SOCKET_EVENT))) {
872 		/* not for me. */
873 		return;
874 	}
875 
876 	/* reset bit */
877 	pccbb_setb(sc, PCCBB_SOCKET_EVENT, 0x01);	/* XXXmagic */
878 
879 	if (sockevent & PCCBB_SOCKET_EVENT_CD) {
880 		mtx_lock(&sc->sc_mtx);
881 		wakeup(sc);
882 		mtx_unlock(&sc->sc_mtx);
883 	} else {
884 		if (sockevent & PCCBB_SOCKET_EVENT_CSTS) {
885 			DPRINTF((" cstsevent occures, 0x%08x\n",
886 			    pccbb_get(sc, PCCBB_SOCKET_STATE)));
887 		}
888 		if (sockevent & PCCBB_SOCKET_EVENT_POWER) {
889 			DPRINTF((" pwrevent occures, 0x%08x\n",
890 			    pccbb_get(sc, PCCBB_SOCKET_STATE)));
891 		}
892 	}
893 }
894 
895 /************************************************************************/
896 /* Generic Power functions						*/
897 /************************************************************************/
898 
899 static int
900 pccbb_detect_voltage(device_t brdev)
901 {
902 	struct pccbb_softc *sc = device_get_softc(brdev);
903 	uint32_t psr;
904 	int vol = CARD_UKN_CARD;
905 
906 	psr = pccbb_get(sc, PCCBB_SOCKET_STATE);
907 
908 	if (psr & PCCBB_SOCKET_STAT_5VCARD)
909 		vol |= CARD_5V_CARD;
910 	if (psr & PCCBB_SOCKET_STAT_3VCARD)
911 		vol |= CARD_3V_CARD;
912 	if (psr & PCCBB_SOCKET_STAT_XVCARD)
913 		vol |= CARD_XV_CARD;
914 	if (psr & PCCBB_SOCKET_STAT_YVCARD)
915 		vol |= CARD_YV_CARD;
916 
917 	return (vol);
918 }
919 
920 static int
921 pccbb_power(device_t brdev, int volts)
922 {
923 	uint32_t status, sock_ctrl;
924 	struct pccbb_softc *sc = device_get_softc(brdev);
925 	int timeout;
926 	uint32_t sockevent;
927 
928 	DEVPRINTF((sc->sc_dev, "pccbb_power: %s and %s [%x]\n",
929 	    (volts & CARD_VCCMASK) == CARD_VCC_UC ? "CARD_VCC_UC" :
930 	    (volts & CARD_VCCMASK) == CARD_VCC_5V ? "CARD_VCC_5V" :
931 	    (volts & CARD_VCCMASK) == CARD_VCC_3V ? "CARD_VCC_3V" :
932 	    (volts & CARD_VCCMASK) == CARD_VCC_XV ? "CARD_VCC_XV" :
933 	    (volts & CARD_VCCMASK) == CARD_VCC_YV ? "CARD_VCC_YV" :
934 	    (volts & CARD_VCCMASK) == CARD_VCC_0V ? "CARD_VCC_0V" :
935 	    "VCC-UNKNOWN",
936 	    (volts & CARD_VPPMASK) == CARD_VPP_UC ? "CARD_VPP_UC" :
937 	    (volts & CARD_VPPMASK) == CARD_VPP_12V ? "CARD_VPP_12V" :
938 	    (volts & CARD_VPPMASK) == CARD_VPP_VCC ? "CARD_VPP_VCC" :
939 	    (volts & CARD_VPPMASK) == CARD_VPP_0V ? "CARD_VPP_0V" :
940 	    "VPP-UNKNOWN",
941 	    volts));
942 
943 	status = pccbb_get(sc, PCCBB_SOCKET_STATE);
944 	sock_ctrl = pccbb_get(sc, PCCBB_SOCKET_CONTROL);
945 
946 	switch (volts & CARD_VCCMASK) {
947 	case CARD_VCC_UC:
948 		break;
949 	case CARD_VCC_5V:
950 		if (PCCBB_SOCKET_STAT_5VCARD & status) { /* check 5 V card */
951 			sock_ctrl &= ~PCCBB_SOCKET_CTRL_VCCMASK;
952 			sock_ctrl |= PCCBB_SOCKET_CTRL_VCC_5V;
953 		} else {
954 			device_printf(sc->sc_dev,
955 			    "BAD voltage request: no 5 V card\n");
956 		}
957 		break;
958 	case CARD_VCC_3V:
959 		if (PCCBB_SOCKET_STAT_3VCARD & status) {
960 			sock_ctrl &= ~PCCBB_SOCKET_CTRL_VCCMASK;
961 			sock_ctrl |= PCCBB_SOCKET_CTRL_VCC_3V;
962 		} else {
963 			device_printf(sc->sc_dev,
964 			    "BAD voltage request: no 3.3 V card\n");
965 		}
966 		break;
967 	case CARD_VCC_0V:
968 		sock_ctrl &= ~PCCBB_SOCKET_CTRL_VCCMASK;
969 		break;
970 	default:
971 		return (0);			/* power NEVER changed */
972 		break;
973 	}
974 
975 	switch (volts & CARD_VPPMASK) {
976 	case CARD_VPP_UC:
977 		break;
978 	case CARD_VPP_0V:
979 		sock_ctrl &= ~PCCBB_SOCKET_CTRL_VPPMASK;
980 		break;
981 	case CARD_VPP_VCC:
982 		sock_ctrl &= ~PCCBB_SOCKET_CTRL_VPPMASK;
983 		sock_ctrl |= ((sock_ctrl >> 4) & 0x07);
984 		break;
985 	case CARD_VPP_12V:
986 		sock_ctrl &= ~PCCBB_SOCKET_CTRL_VPPMASK;
987 		sock_ctrl |= PCCBB_SOCKET_CTRL_VPP_12V;
988 		break;
989 	}
990 
991 	if (pccbb_get(sc, PCCBB_SOCKET_CONTROL) == sock_ctrl)
992 		return (1); /* no change necessary */
993 
994 	pccbb_set(sc, PCCBB_SOCKET_CONTROL, sock_ctrl);
995 	status = pccbb_get(sc, PCCBB_SOCKET_STATE);
996 
997 	/*
998 	 * XXX This busy wait is bogus.  We should wait for a power
999 	 * interrupt and then whine if the status is bad.  If we're
1000 	 * worried about the card not coming up, then we should also
1001 	 * schedule a timeout which we can cacel in the power interrupt.
1002 	 */
1003 	timeout = 20;
1004 	do {
1005 		DELAY(20*1000);
1006 		sockevent = pccbb_get(sc, PCCBB_SOCKET_EVENT);
1007 	} while (!(sockevent & PCCBB_SOCKET_EVENT_POWER) && --timeout > 0);
1008 	/* reset event status */
1009 	/* XXX should only reset EVENT_POWER */
1010 	pccbb_set(sc, PCCBB_SOCKET_EVENT, sockevent);
1011 	if (timeout < 0) {
1012 		printf ("VCC supply failed.\n");
1013 		return (0);
1014 	}
1015 
1016 	/* XXX
1017 	 * delay 400 ms: thgough the standard defines that the Vcc set-up time
1018 	 * is 20 ms, some PC-Card bridge requires longer duration.
1019 	 * XXX Note: We should check the stutus AFTER the delay to give time
1020 	 * for things to stabilize.
1021 	 */
1022 	DELAY(400*1000);
1023 
1024 	if (status & PCCBB_SOCKET_STAT_BADVCC) {
1025 		device_printf(sc->sc_dev,
1026 		    "bad Vcc request. ctrl=0x%x, status=0x%x\n",
1027 		    sock_ctrl ,status);
1028 		printf("pccbb_power: %s and %s [%x]\n",
1029 		    (volts & CARD_VCCMASK) == CARD_VCC_UC ? "CARD_VCC_UC" :
1030 		    (volts & CARD_VCCMASK) == CARD_VCC_5V ? "CARD_VCC_5V" :
1031 		    (volts & CARD_VCCMASK) == CARD_VCC_3V ? "CARD_VCC_3V" :
1032 		    (volts & CARD_VCCMASK) == CARD_VCC_XV ? "CARD_VCC_XV" :
1033 		    (volts & CARD_VCCMASK) == CARD_VCC_YV ? "CARD_VCC_YV" :
1034 		    (volts & CARD_VCCMASK) == CARD_VCC_0V ? "CARD_VCC_0V" :
1035 		    "VCC-UNKNOWN",
1036 		    (volts & CARD_VPPMASK) == CARD_VPP_UC ? "CARD_VPP_UC" :
1037 		    (volts & CARD_VPPMASK) == CARD_VPP_12V ? "CARD_VPP_12V":
1038 		    (volts & CARD_VPPMASK) == CARD_VPP_VCC ? "CARD_VPP_VCC":
1039 		    (volts & CARD_VPPMASK) == CARD_VPP_0V ? "CARD_VPP_0V" :
1040 		    "VPP-UNKNOWN",
1041 		    volts);
1042 		return (0);
1043 	}
1044 	return (1);		/* power changed correctly */
1045 }
1046 
1047 /************************************************************************/
1048 /* Cardbus power functions						*/
1049 /************************************************************************/
1050 
1051 static void
1052 pccbb_cardbus_reset(device_t brdev)
1053 {
1054 	struct pccbb_softc *sc = device_get_softc(brdev);
1055 	int delay_us;
1056 
1057 	delay_us = sc->sc_chipset == CB_RF5C47X ? 400*1000 : 20*1000;
1058 
1059 	PCI_MASK_CONFIG(brdev, PCCBBR_BRIDGECTRL, |PCCBBM_BRIDGECTRL_RESET, 2);
1060 
1061 	DELAY(delay_us);
1062 
1063 	/* If a card exists, unreset it! */
1064 	if ((pccbb_get(sc, PCCBB_SOCKET_STATE) & PCCBB_SOCKET_STAT_CD) == 0) {
1065 		PCI_MASK_CONFIG(brdev, PCCBBR_BRIDGECTRL,
1066 		    &~PCCBBM_BRIDGECTRL_RESET, 2);
1067 		DELAY(delay_us);
1068 	}
1069 }
1070 
1071 static int
1072 pccbb_cardbus_power_enable_socket(device_t brdev, device_t child)
1073 {
1074 	struct pccbb_softc *sc = device_get_softc(brdev);
1075 	int voltage;
1076 
1077 	if ((pccbb_get(sc, PCCBB_SOCKET_STATE) & PCCBB_SOCKET_STAT_CD) ==
1078 	    PCCBB_SOCKET_STAT_CD)
1079 		return (ENODEV);
1080 
1081 	voltage = pccbb_detect_voltage(brdev);
1082 
1083 	pccbb_power(brdev, CARD_VCC_0V | CARD_VPP_0V);
1084 	if (voltage & CARD_5V_CARD)
1085 		pccbb_power(brdev, CARD_VCC_5V | CARD_VPP_VCC);
1086 	else if (voltage & CARD_3V_CARD)
1087 		pccbb_power(brdev, CARD_VCC_3V | CARD_VPP_VCC);
1088 	else {
1089 		device_printf(brdev, "Unknown card voltage\n");
1090 		return (ENXIO);
1091 	}
1092 
1093 	pccbb_cardbus_reset(brdev);
1094 	return (0);
1095 }
1096 
1097 static void
1098 pccbb_cardbus_power_disable_socket(device_t brdev, device_t child)
1099 {
1100 	pccbb_power(brdev, CARD_VCC_0V | CARD_VPP_0V);
1101 	pccbb_cardbus_reset(brdev);
1102 }
1103 
1104 /************************************************************************/
1105 /* Cardbus Resource							*/
1106 /************************************************************************/
1107 
1108 static int
1109 pccbb_cardbus_io_open(device_t brdev, int win, uint32_t start, uint32_t end)
1110 {
1111 	int basereg;
1112 	int limitreg;
1113 
1114 	if ((win < 0) || (win > 1)) {
1115 		DEVPRINTF((brdev,
1116 		    "pccbb_cardbus_io_open: window out of range %d\n", win));
1117 		return (EINVAL);
1118 	}
1119 
1120 	basereg = win*8 + PCCBBR_IOBASE0;
1121 	limitreg = win*8 + PCCBBR_IOLIMIT0;
1122 
1123 	pci_write_config(brdev, basereg, start, 4);
1124 	pci_write_config(brdev, limitreg, end, 4);
1125 	return (0);
1126 }
1127 
1128 static int
1129 pccbb_cardbus_mem_open(device_t brdev, int win, uint32_t start, uint32_t end)
1130 {
1131 	int basereg;
1132 	int limitreg;
1133 
1134 	if ((win < 0) || (win > 1)) {
1135 		DEVPRINTF((brdev,
1136 		    "pccbb_cardbus_mem_open: window out of range %d\n", win));
1137 		return (EINVAL);
1138 	}
1139 
1140 	basereg = win*8 + PCCBBR_MEMBASE0;
1141 	limitreg = win*8 + PCCBBR_MEMLIMIT0;
1142 
1143 	pci_write_config(brdev, basereg, start, 4);
1144 	pci_write_config(brdev, limitreg, end, 4);
1145 	return (0);
1146 }
1147 
1148 /*
1149  * XXX The following function belongs in the pci bus layer.
1150  */
1151 static void
1152 pccbb_cardbus_auto_open(struct pccbb_softc *sc, int type)
1153 {
1154 	uint32_t starts[2];
1155 	uint32_t ends[2];
1156 	struct pccbb_reslist *rle;
1157 	int align;
1158 	int prefetchable[2];
1159 	uint32_t reg;
1160 
1161 	starts[0] = starts[1] = 0xffffffff;
1162 	ends[0] = ends[1] = 0;
1163 
1164 	if (type == SYS_RES_MEMORY)
1165 		align = PCCBB_MEMALIGN;
1166 	else if (type == SYS_RES_IOPORT)
1167 		align = PCCBB_IOALIGN;
1168 	else
1169 		align = 1;
1170 
1171 	SLIST_FOREACH(rle, &sc->rl, link) {
1172 		if (rle->type != type)
1173 			;
1174 		else if (rle->res == NULL) {
1175 			device_printf(sc->sc_dev, "WARNING: Resource not reserved?  "
1176 			    "(type=%d, addr=%lx)\n",
1177 			    rle->type, rman_get_start(rle->res));
1178 		} else if (!(rman_get_flags(rle->res) & RF_ACTIVE)) {
1179 			/* XXX */
1180 		} else if (starts[0] == 0xffffffff) {
1181 			starts[0] = rman_get_start(rle->res);
1182 			ends[0] = rman_get_end(rle->res);
1183 			prefetchable[0] =
1184 			    rman_get_flags(rle->res) & RF_PREFETCHABLE;
1185 		} else if (rman_get_end(rle->res) > ends[0] &&
1186 		    rman_get_start(rle->res) - ends[0] <
1187 		    PCCBB_AUTO_OPEN_SMALLHOLE && prefetchable[0] ==
1188 		    (rman_get_flags(rle->res) & RF_PREFETCHABLE)) {
1189 			ends[0] = rman_get_end(rle->res);
1190 		} else if (rman_get_start(rle->res) < starts[0] &&
1191 		    starts[0] - rman_get_end(rle->res) <
1192 		    PCCBB_AUTO_OPEN_SMALLHOLE && prefetchable[0] ==
1193 		    (rman_get_flags(rle->res) & RF_PREFETCHABLE)) {
1194 			starts[0] = rman_get_start(rle->res);
1195 		} else if (starts[1] == 0xffffffff) {
1196 			starts[1] = rman_get_start(rle->res);
1197 			ends[1] = rman_get_end(rle->res);
1198 			prefetchable[1] =
1199 			    rman_get_flags(rle->res) & RF_PREFETCHABLE;
1200 		} else if (rman_get_end(rle->res) > ends[1] &&
1201 		    rman_get_start(rle->res) - ends[1] <
1202 		    PCCBB_AUTO_OPEN_SMALLHOLE && prefetchable[1] ==
1203 		    (rman_get_flags(rle->res) & RF_PREFETCHABLE)) {
1204 			ends[1] = rman_get_end(rle->res);
1205 		} else if (rman_get_start(rle->res) < starts[1] &&
1206 		    starts[1] - rman_get_end(rle->res) <
1207 		    PCCBB_AUTO_OPEN_SMALLHOLE && prefetchable[1] ==
1208 		    (rman_get_flags(rle->res) & RF_PREFETCHABLE)) {
1209 			starts[1] = rman_get_start(rle->res);
1210 		} else {
1211 			uint32_t diffs[2];
1212 			int win;
1213 
1214 			diffs[0] = diffs[1] = 0xffffffff;
1215 			if (rman_get_start(rle->res) > ends[0])
1216 				diffs[0] = rman_get_start(rle->res) - ends[0];
1217 			else if (rman_get_end(rle->res) < starts[0])
1218 				diffs[0] = starts[0] - rman_get_end(rle->res);
1219 			if (rman_get_start(rle->res) > ends[1])
1220 				diffs[1] = rman_get_start(rle->res) - ends[1];
1221 			else if (rman_get_end(rle->res) < starts[1])
1222 				diffs[1] = starts[1] - rman_get_end(rle->res);
1223 
1224 			win = (diffs[0] <= diffs[1])?0:1;
1225 			if (rman_get_start(rle->res) > ends[win])
1226 				ends[win] = rman_get_end(rle->res);
1227 			else if (rman_get_end(rle->res) < starts[win])
1228 				starts[win] = rman_get_start(rle->res);
1229 			if (!(rman_get_flags(rle->res) & RF_PREFETCHABLE))
1230 				prefetchable[win] = 0;
1231 		}
1232 
1233 		if (starts[0] != 0xffffffff)
1234 			starts[0] -= starts[0] % align;
1235 		if (starts[1] != 0xffffffff)
1236 			starts[1] -= starts[1] % align;
1237 		if (ends[0] % align != 0)
1238 			ends[0] += align - ends[0]%align - 1;
1239 		if (ends[1] % align != 0)
1240 			ends[1] += align - ends[1]%align - 1;
1241 	}
1242 
1243 	if (type == SYS_RES_MEMORY) {
1244 		pccbb_cardbus_mem_open(sc->sc_dev, 0, starts[0], ends[0]);
1245 		pccbb_cardbus_mem_open(sc->sc_dev, 1, starts[1], ends[1]);
1246 		reg = pci_read_config(sc->sc_dev, PCCBBR_BRIDGECTRL, 2);
1247 		reg &= ~(PCCBBM_BRIDGECTRL_PREFETCH_0|
1248 		    PCCBBM_BRIDGECTRL_PREFETCH_1);
1249 		reg |= (prefetchable[0]?PCCBBM_BRIDGECTRL_PREFETCH_0:0)|
1250 		    (prefetchable[1]?PCCBBM_BRIDGECTRL_PREFETCH_1:0);
1251 		pci_write_config(sc->sc_dev, PCCBBR_BRIDGECTRL, reg, 2);
1252 	} else if (type == SYS_RES_IOPORT) {
1253 		pccbb_cardbus_io_open(sc->sc_dev, 0, starts[0], ends[0]);
1254 		pccbb_cardbus_io_open(sc->sc_dev, 1, starts[1], ends[1]);
1255 	}
1256 }
1257 
1258 static int
1259 pccbb_cardbus_activate_resource(device_t brdev, device_t child, int type,
1260     int rid, struct resource *res)
1261 {
1262 	int ret;
1263 
1264 	ret = BUS_ACTIVATE_RESOURCE(device_get_parent(brdev), child,
1265 	    type, rid, res);
1266 	if (ret != 0)
1267 		return (ret);
1268 	pccbb_cardbus_auto_open(device_get_softc(brdev), type);
1269 	return (0);
1270 }
1271 
1272 static int
1273 pccbb_cardbus_deactivate_resource(device_t brdev, device_t child, int type,
1274     int rid, struct resource *res)
1275 {
1276 	int ret;
1277 
1278 	ret = BUS_DEACTIVATE_RESOURCE(device_get_parent(brdev), child,
1279 	    type, rid, res);
1280 	if (ret != 0)
1281 		return (ret);
1282 	pccbb_cardbus_auto_open(device_get_softc(brdev), type);
1283 	return (0);
1284 }
1285 
1286 static struct resource *
1287 pccbb_cardbus_alloc_resource(device_t brdev, device_t child, int type, int *rid,
1288     u_long start, u_long end, u_long count, uint flags)
1289 {
1290 	struct pccbb_softc *sc = device_get_softc(brdev);
1291 	int tmp;
1292 	struct resource *res;
1293 
1294 	switch (type) {
1295 	case SYS_RES_IRQ:
1296 		tmp = rman_get_start(sc->sc_irq_res);
1297 		if (start > tmp || end < tmp || count != 1) {
1298 			device_printf(child, "requested interrupt %ld-%ld,"
1299 			    "count = %ld not supported by pccbb\n",
1300 			    start, end, count);
1301 			return (NULL);
1302 		}
1303 		start = end = tmp;
1304 		break;
1305 	case SYS_RES_IOPORT:
1306 		if (start <= PCCBB_START_IO)
1307 			start = PCCBB_START_IO;
1308 		if (end < start)
1309 			end = start;
1310 		break;
1311 	case SYS_RES_MEMORY:
1312 		if (start <= pccbb_start_mem)
1313 			start = pccbb_start_mem;
1314 		if (end < start)
1315 			end = start;
1316 		break;
1317 	}
1318 
1319 	res = BUS_ALLOC_RESOURCE(device_get_parent(brdev), child, type, rid,
1320 	    start, end, count, flags & ~RF_ACTIVE);
1321 	if (res == NULL) {
1322 		printf("pccbb alloc res fail\n");
1323 		return (NULL);
1324 	}
1325 	pccbb_insert_res(sc, res, type, *rid);
1326 	if (flags & RF_ACTIVE)
1327 		if (bus_activate_resource(child, type, *rid, res) != 0) {
1328 			bus_release_resource(child, type, *rid, res);
1329 			return (NULL);
1330 		}
1331 
1332 	return (res);
1333 }
1334 
1335 static int
1336 pccbb_cardbus_release_resource(device_t brdev, device_t child, int type,
1337     int rid, struct resource *res)
1338 {
1339 	struct pccbb_softc *sc = device_get_softc(brdev);
1340 	int error;
1341 
1342 	if (rman_get_flags(res) & RF_ACTIVE) {
1343 		error = bus_deactivate_resource(child, type, rid, res);
1344 		if (error != 0)
1345 			return (error);
1346 	}
1347 	pccbb_remove_res(sc, res);
1348 	return (BUS_RELEASE_RESOURCE(device_get_parent(brdev), child,
1349 	    type, rid, res));
1350 }
1351 
1352 /************************************************************************/
1353 /* PC Card Power Functions						*/
1354 /************************************************************************/
1355 
1356 static int
1357 pccbb_pcic_power_enable_socket(device_t brdev, device_t child)
1358 {
1359 	struct pccbb_softc *sc = device_get_softc(brdev);
1360 	int voltage;
1361 
1362 	DPRINTF(("pccbb_pcic_socket_enable:\n"));
1363 
1364 	/* power down/up the socket to reset */
1365 	voltage = pccbb_detect_voltage(brdev);
1366 	pccbb_power(brdev, CARD_VCC_0V | CARD_VPP_0V);
1367 	if (voltage & CARD_5V_CARD)
1368 		pccbb_power(brdev, CARD_VCC_5V | CARD_VPP_VCC);
1369 	else if (voltage & CARD_3V_CARD)
1370 		pccbb_power(brdev, CARD_VCC_3V | CARD_VPP_VCC);
1371 	else {
1372 		device_printf(brdev, "Unknown card voltage\n");
1373 		return (ENXIO);
1374 	}
1375 	exca_reset(&sc->exca, child);
1376 
1377 	return (0);
1378 }
1379 
1380 static void
1381 pccbb_pcic_power_disable_socket(device_t brdev, device_t child)
1382 {
1383 	struct pccbb_softc *sc = device_get_softc(brdev);
1384 
1385 	DPRINTF(("pccbb_pcic_socket_disable\n"));
1386 
1387 	/* reset signal asserting... */
1388 	exca_clrb(&sc->exca, EXCA_INTR, EXCA_INTR_RESET);
1389 	DELAY(2*1000);
1390 
1391 	/* power down the socket */
1392 	pccbb_power(brdev, CARD_VCC_0V | CARD_VPP_0V);
1393 	exca_clrb(&sc->exca, EXCA_PWRCTL, EXCA_PWRCTL_OE);
1394 
1395 	/* wait 300ms until power fails (Tpf). */
1396 	DELAY(300 * 1000);
1397 }
1398 
1399 /************************************************************************/
1400 /* POWER methods							*/
1401 /************************************************************************/
1402 
1403 static int
1404 pccbb_power_enable_socket(device_t brdev, device_t child)
1405 {
1406 	struct pccbb_softc *sc = device_get_softc(brdev);
1407 
1408 	if (sc->sc_flags & PCCBB_16BIT_CARD)
1409 		return (pccbb_pcic_power_enable_socket(brdev, child));
1410 	else
1411 		return (pccbb_cardbus_power_enable_socket(brdev, child));
1412 }
1413 
1414 static void
1415 pccbb_power_disable_socket(device_t brdev, device_t child)
1416 {
1417 	struct pccbb_softc *sc = device_get_softc(brdev);
1418 	if (sc->sc_flags & PCCBB_16BIT_CARD)
1419 		pccbb_pcic_power_disable_socket(brdev, child);
1420 	else
1421 		pccbb_cardbus_power_disable_socket(brdev, child);
1422 }
1423 static int
1424 pccbb_pcic_activate_resource(device_t brdev, device_t child, int type, int rid,
1425     struct resource *res)
1426 {
1427 	int err;
1428 	struct pccbb_softc *sc = device_get_softc(brdev);
1429 	if (!(rman_get_flags(res) & RF_ACTIVE)) { /* not already activated */
1430 		switch (type) {
1431 		case SYS_RES_IOPORT:
1432 			err = exca_io_map(&sc->exca, 0, res);
1433 			break;
1434 		case SYS_RES_MEMORY:
1435 			err = exca_mem_map(&sc->exca, 0, res);
1436 			break;
1437 		default:
1438 			err = 0;
1439 			break;
1440 		}
1441 		if (err)
1442 			return (err);
1443 
1444 	}
1445 	return (BUS_ACTIVATE_RESOURCE(device_get_parent(brdev), child,
1446 	    type, rid, res));
1447 }
1448 
1449 static int
1450 pccbb_pcic_deactivate_resource(device_t brdev, device_t child, int type,
1451     int rid, struct resource *res)
1452 {
1453 	struct pccbb_softc *sc = device_get_softc(brdev);
1454 
1455 	if (rman_get_flags(res) & RF_ACTIVE) { /* if activated */
1456 		switch (type) {
1457 		case SYS_RES_IOPORT:
1458 			if (exca_io_unmap_res(&sc->exca, res))
1459 				return (ENOENT);
1460 			break;
1461 		case SYS_RES_MEMORY:
1462 			if (exca_mem_unmap_res(&sc->exca, res))
1463 				return (ENOENT);
1464 			break;
1465 		}
1466 	}
1467 	return (BUS_DEACTIVATE_RESOURCE(device_get_parent(brdev), child,
1468 	    type, rid, res));
1469 }
1470 
1471 static struct resource *
1472 pccbb_pcic_alloc_resource(device_t brdev, device_t child, int type, int *rid,
1473     u_long start, u_long end, u_long count, uint flags)
1474 {
1475 	struct resource *res = NULL;
1476 	struct pccbb_softc *sc = device_get_softc(brdev);
1477 	int tmp;
1478 
1479 	switch (type) {
1480 	case SYS_RES_MEMORY:
1481 		if (start < pccbb_start_mem)
1482 			start = pccbb_start_mem;
1483 		if (end < start)
1484 			end = start;
1485 		flags = (flags & ~RF_ALIGNMENT_MASK) |
1486 		    rman_make_alignment_flags(PCCBB_MEMALIGN);
1487 		break;
1488 	case SYS_RES_IOPORT:
1489 		if (start < 0x100)
1490 			start = 0x100;		/* XXX tweakable? */
1491 		if (end < start)
1492 			end = start;
1493 		break;
1494 	case SYS_RES_IRQ:
1495 		tmp = rman_get_start(sc->sc_irq_res);
1496 		if (start > tmp || end < tmp || count != 1) {
1497 			device_printf(child, "requested interrupt %ld-%ld,"
1498 			    "count = %ld not supported by pccbb\n",
1499 			    start, end, count);
1500 			return (NULL);
1501 		}
1502 		flags |= RF_SHAREABLE;
1503 		start = end = rman_get_start(sc->sc_irq_res);
1504 		break;
1505 	}
1506 	res = BUS_ALLOC_RESOURCE(device_get_parent(brdev), child, type, rid,
1507 	    start, end, count, flags & ~RF_ACTIVE);
1508 	if (res == NULL)
1509 		return (NULL);
1510 	pccbb_insert_res(sc, res, type, *rid);
1511 	if (flags & RF_ACTIVE) {
1512 		if (bus_activate_resource(child, type, *rid, res) != 0) {
1513 			bus_release_resource(child, type, *rid, res);
1514 			return (NULL);
1515 		}
1516 	}
1517 
1518 	return (res);
1519 }
1520 
1521 static int
1522 pccbb_pcic_release_resource(device_t brdev, device_t child, int type,
1523     int rid, struct resource *res)
1524 {
1525 	struct pccbb_softc *sc = device_get_softc(brdev);
1526 	int error;
1527 
1528 	if (rman_get_flags(res) & RF_ACTIVE) {
1529 		error = bus_deactivate_resource(child, type, rid, res);
1530 		if (error != 0)
1531 			return (error);
1532 	}
1533 	pccbb_remove_res(sc, res);
1534 	return (BUS_RELEASE_RESOURCE(device_get_parent(brdev), child,
1535 	    type, rid, res));
1536 }
1537 
1538 /************************************************************************/
1539 /* PC Card methods							*/
1540 /************************************************************************/
1541 
1542 static int
1543 pccbb_pcic_set_res_flags(device_t brdev, device_t child, int type, int rid,
1544     uint32_t flags)
1545 {
1546 	struct pccbb_softc *sc = device_get_softc(brdev);
1547 	struct resource *res;
1548 
1549 	if (type != SYS_RES_MEMORY)
1550 		return (EINVAL);
1551 	res = pccbb_find_res(sc, type, rid);
1552 	if (res == NULL) {
1553 		device_printf(brdev,
1554 		    "set_res_flags: specified rid not found\n");
1555 		return (ENOENT);
1556 	}
1557 	return (exca_mem_set_flags(&sc->exca, res, flags));
1558 }
1559 
1560 static int
1561 pccbb_pcic_set_memory_offset(device_t brdev, device_t child, int rid,
1562     uint32_t cardaddr, uint32_t *deltap)
1563 {
1564 	struct pccbb_softc *sc = device_get_softc(brdev);
1565 	struct resource *res;
1566 
1567 	res = pccbb_find_res(sc, SYS_RES_MEMORY, rid);
1568 	if (res == NULL) {
1569 		device_printf(brdev,
1570 		    "set_memory_offset: specified rid not found\n");
1571 		return (ENOENT);
1572 	}
1573 	return (exca_mem_set_offset(&sc->exca, res, cardaddr, deltap));
1574 }
1575 
1576 /************************************************************************/
1577 /* BUS Methods								*/
1578 /************************************************************************/
1579 
1580 
1581 static int
1582 pccbb_activate_resource(device_t brdev, device_t child, int type, int rid,
1583     struct resource *r)
1584 {
1585 	struct pccbb_softc *sc = device_get_softc(brdev);
1586 
1587 	if (sc->sc_flags & PCCBB_16BIT_CARD)
1588 		return (pccbb_pcic_activate_resource(brdev, child, type, rid, r));
1589 	else
1590 		return (pccbb_cardbus_activate_resource(brdev, child, type, rid,
1591 		    r));
1592 }
1593 
1594 static int
1595 pccbb_deactivate_resource(device_t brdev, device_t child, int type,
1596     int rid, struct resource *r)
1597 {
1598 	struct pccbb_softc *sc = device_get_softc(brdev);
1599 
1600 	if (sc->sc_flags & PCCBB_16BIT_CARD)
1601 		return (pccbb_pcic_deactivate_resource(brdev, child, type,
1602 		    rid, r));
1603 	else
1604 		return (pccbb_cardbus_deactivate_resource(brdev, child, type,
1605 		    rid, r));
1606 }
1607 
1608 static struct resource *
1609 pccbb_alloc_resource(device_t brdev, device_t child, int type, int *rid,
1610     u_long start, u_long end, u_long count, uint flags)
1611 {
1612 	struct pccbb_softc *sc = device_get_softc(brdev);
1613 
1614 	if (sc->sc_flags & PCCBB_16BIT_CARD)
1615 		return (pccbb_pcic_alloc_resource(brdev, child, type, rid,
1616 		    start, end, count, flags));
1617 	else
1618 		return (pccbb_cardbus_alloc_resource(brdev, child, type, rid,
1619 		    start, end, count, flags));
1620 }
1621 
1622 static int
1623 pccbb_release_resource(device_t brdev, device_t child, int type, int rid,
1624     struct resource *r)
1625 {
1626 	struct pccbb_softc *sc = device_get_softc(brdev);
1627 
1628 	if (sc->sc_flags & PCCBB_16BIT_CARD)
1629 		return (pccbb_pcic_release_resource(brdev, child, type,
1630 		    rid, r));
1631 	else
1632 		return (pccbb_cardbus_release_resource(brdev, child, type,
1633 		    rid, r));
1634 }
1635 
1636 static int
1637 pccbb_read_ivar(device_t brdev, device_t child, int which, uintptr_t *result)
1638 {
1639 	struct pccbb_softc *sc = device_get_softc(brdev);
1640 
1641 	switch (which) {
1642 	case PCIB_IVAR_BUS:
1643 		*result = sc->sc_secbus;
1644 		return (0);
1645 	}
1646 	return (ENOENT);
1647 }
1648 
1649 static int
1650 pccbb_write_ivar(device_t brdev, device_t child, int which, uintptr_t value)
1651 {
1652 	struct pccbb_softc *sc = device_get_softc(brdev);
1653 
1654 	switch (which) {
1655 	case PCIB_IVAR_BUS:
1656 		sc->sc_secbus = value;
1657 		break;
1658 	}
1659 	return (ENOENT);
1660 }
1661 
1662 /************************************************************************/
1663 /* PCI compat methods							*/
1664 /************************************************************************/
1665 
1666 static int
1667 pccbb_maxslots(device_t brdev)
1668 {
1669 	return (0);
1670 }
1671 
1672 static uint32_t
1673 pccbb_read_config(device_t brdev, int b, int s, int f, int reg, int width)
1674 {
1675 	/*
1676 	 * Pass through to the next ppb up the chain (i.e. our grandparent).
1677 	 */
1678 	return (PCIB_READ_CONFIG(device_get_parent(device_get_parent(brdev)),
1679 	    b, s, f, reg, width));
1680 }
1681 
1682 static void
1683 pccbb_write_config(device_t brdev, int b, int s, int f, int reg, uint32_t val,
1684     int width)
1685 {
1686 	/*
1687 	 * Pass through to the next ppb up the chain (i.e. our grandparent).
1688 	 */
1689 	PCIB_WRITE_CONFIG(device_get_parent(device_get_parent(brdev)),
1690 	    b, s, f, reg, val, width);
1691 }
1692 
1693 static int
1694 pccbb_suspend(device_t self)
1695 {
1696 	int			error = 0;
1697 	struct pccbb_softc*	sc = device_get_softc(self);
1698 
1699 	bus_teardown_intr(self, sc->sc_irq_res, sc->sc_intrhand);
1700 	error = bus_generic_suspend(self);
1701 	return (error);
1702 }
1703 
1704 static int
1705 pccbb_resume(device_t self)
1706 {
1707 	int	error = 0;
1708 	struct pccbb_softc *sc = (struct pccbb_softc *)device_get_softc(self);
1709 	uint32_t tmp;
1710 
1711 	pci_write_config(self, PCCBBR_SOCKBASE,
1712 	    rman_get_start(sc->sc_base_res), 4);
1713 	DEVPRINTF((self, "PCI Memory allocated: %08lx\n",
1714 	    rman_get_start(sc->sc_base_res)));
1715 
1716 	pccbb_chipinit(sc);
1717 
1718 	/* CSC Interrupt: Card detect interrupt on */
1719 	pccbb_setb(sc, PCCBB_SOCKET_MASK, PCCBB_SOCKET_MASK_CD);
1720 
1721 	/* reset interrupt */
1722 	tmp = pccbb_get(sc, PCCBB_SOCKET_EVENT);
1723 	pccbb_set(sc, PCCBB_SOCKET_EVENT, tmp);
1724 
1725 	/* re-establish the interrupt. */
1726 	/* XXX INTR_TYPE_BIOS IS WRONG here */
1727 	if (bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO, pccbb_intr, sc,
1728 	    &sc->sc_intrhand)) {
1729 		device_printf(self, "couldn't re-establish interrupt");
1730 		bus_release_resource(self, SYS_RES_IRQ, 0, sc->sc_irq_res);
1731 		bus_release_resource(self, SYS_RES_MEMORY, PCCBBR_SOCKBASE,
1732 		    sc->sc_base_res);
1733 		mtx_destroy(&sc->sc_mtx);
1734 		error = ENOMEM;
1735 	}
1736 	bus_generic_resume(self);
1737 
1738 	/* wakeup thread */
1739 	if (!error) {
1740 		mtx_lock(&sc->sc_mtx);
1741 		wakeup(sc);
1742 		mtx_unlock(&sc->sc_mtx);
1743 	}
1744 	return (error);
1745 }
1746 
1747 static device_method_t pccbb_methods[] = {
1748 	/* Device interface */
1749 	DEVMETHOD(device_probe,			pccbb_probe),
1750 	DEVMETHOD(device_attach,		pccbb_attach),
1751 	DEVMETHOD(device_detach,		pccbb_detach),
1752 	DEVMETHOD(device_shutdown,		pccbb_shutdown),
1753 	DEVMETHOD(device_suspend,		pccbb_suspend),
1754 	DEVMETHOD(device_resume,		pccbb_resume),
1755 
1756 	/* bus methods */
1757 	DEVMETHOD(bus_print_child,		bus_generic_print_child),
1758 	DEVMETHOD(bus_read_ivar,		pccbb_read_ivar),
1759 	DEVMETHOD(bus_write_ivar,		pccbb_write_ivar),
1760 	DEVMETHOD(bus_alloc_resource,		pccbb_alloc_resource),
1761 	DEVMETHOD(bus_release_resource,		pccbb_release_resource),
1762 	DEVMETHOD(bus_activate_resource,	pccbb_activate_resource),
1763 	DEVMETHOD(bus_deactivate_resource,	pccbb_deactivate_resource),
1764 	DEVMETHOD(bus_driver_added,		pccbb_driver_added),
1765 	DEVMETHOD(bus_child_detached,		pccbb_child_detached),
1766 	DEVMETHOD(bus_setup_intr,		bus_generic_setup_intr),
1767 	DEVMETHOD(bus_teardown_intr,		bus_generic_teardown_intr),
1768 
1769 	/* 16-bit card interface */
1770 	DEVMETHOD(card_set_res_flags,		pccbb_pcic_set_res_flags),
1771 	DEVMETHOD(card_set_memory_offset,	pccbb_pcic_set_memory_offset),
1772 	DEVMETHOD(card_reprobe_card,		pccbb_card_reprobe),
1773 
1774 	/* power interface */
1775 	DEVMETHOD(power_enable_socket,		pccbb_power_enable_socket),
1776 	DEVMETHOD(power_disable_socket,		pccbb_power_disable_socket),
1777 
1778 	/* pcib compatibility interface */
1779 	DEVMETHOD(pcib_maxslots,		pccbb_maxslots),
1780 	DEVMETHOD(pcib_read_config,		pccbb_read_config),
1781 	DEVMETHOD(pcib_write_config,		pccbb_write_config),
1782 	{0,0}
1783 };
1784 
1785 static driver_t pccbb_driver = {
1786 	"pccbb",
1787 	pccbb_methods,
1788 	sizeof(struct pccbb_softc)
1789 };
1790 
1791 static devclass_t pccbb_devclass;
1792 
1793 DRIVER_MODULE(pccbb, pci, pccbb_driver, pccbb_devclass, 0, 0);
1794 
1795 SYSINIT(pccbb, SI_SUB_KTHREAD_IDLE, SI_ORDER_ANY, pccbb_start_threads, 0);
1796