xref: /freebsd/sys/dev/pccbb/pccbb.c (revision 77a0943ded95b9e6438f7db70c4a28e4d93946d4)
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  * Much of the 16-bit PC Card compatibility code stolen from dev/pcic/i82365.c
38  * XXX and should be cleaned up to share as much as possible.
39  *
40  * Written by Jonathan Chen <jon@freebsd.org>
41  * The author would like to acknowledge:
42  *  * HAYAKAWA Koichi: Author of the NetBSD code for the same thing
43  *  * Warner Losh: Newbus/newcard guru and author of the pccard side of things
44  *  * YAMAMOTO Shigeru: Author of another FreeBSD cardbus driver
45  *  * David Cross: Author of the initial ugly hack for a specific cardbus card
46  */
47 
48 #define CBB_DEBUG
49 
50 #include <sys/param.h>
51 #include <sys/systm.h>
52 #include <sys/errno.h>
53 #include <sys/kernel.h>
54 #include <sys/kthread.h>
55 #include <sys/malloc.h>
56 
57 #include <sys/bus.h>
58 #include <machine/bus.h>
59 #include <sys/rman.h>
60 #include <machine/resource.h>
61 
62 #include <pci/pcireg.h>
63 #include <pci/pcivar.h>
64 #include <machine/clock.h>
65 
66 #include <dev/pccard/pccardreg.h>
67 #include <dev/pccard/pccardvar.h>
68 #include <dev/pcic/i82365reg.h>
69 
70 #include <dev/pccbb/pccbbreg.h>
71 #include <dev/pccbb/pccbbvar.h>
72 
73 #include "power_if.h"
74 #include "card_if.h"
75 #include "pccbb_if.h"
76 #include "pcib_if.h"
77 
78 #if defined CBB_DEBUG
79 #define	DPRINTF(x) printf x
80 #define	DEVPRINTF(x) device_printf x
81 #else
82 #define	DPRINTF(x)
83 #define	DEVPRINTF(x)
84 #endif
85 
86 #define	PCI_MASK_CONFIG(DEV,REG,MASK,SIZE) 				\
87 	pci_write_config(DEV, REG, pci_read_config(DEV, REG, SIZE) MASK, SIZE)
88 #define	PCI_MASK2_CONFIG(DEV,REG,MASK1,MASK2,SIZE)			\
89 	pci_write_config(DEV, REG, (					\
90 		pci_read_config(DEV, REG, SIZE) MASK1) MASK2, SIZE)
91 
92 #define	PCIC_READ(SC,REG)						\
93 	(((u_int8_t*)((SC)->sc_socketreg))[0x800+(REG)])
94 #define	PCIC_WRITE(SC,REG,val)						\
95 	(((u_int8_t*)((SC)->sc_socketreg))[0x800+(REG)]) = (val)
96 #define	PCIC_MASK(SC,REG,MASK)						\
97 	PCIC_WRITE(SC,REG,PCIC_READ(SC,REG) MASK)
98 #define	PCIC_MASK2(SC,REG,MASK,MASK2)					\
99 	PCIC_WRITE(SC,REG,(PCIC_READ(SC,REG) MASK) MASK2)
100 
101 #define DETACH_FORCE    0x1
102 
103 struct pccbb_sclist {
104 	struct pccbb_softc *sc;
105 	STAILQ_ENTRY(pccbb_sclist) entries;
106 };
107 
108 static STAILQ_HEAD(, pccbb_sclist) softcs;
109 static int softcs_init = 0;
110 
111 
112 struct yenta_chipinfo {
113 	u_int32_t yc_id;
114 	const char *yc_name;
115 	int yc_chiptype;
116 	int yc_flags;
117 } yc_chipsets[] = {
118 	/* Texas Instruments chips */
119 	{PCI_DEVICE_ID_PCIC_TI1130, "TI1130 PCI-CardBus Bridge", CB_TI113X,
120 		PCCBB_PCIC_IO_RELOC | PCCBB_PCIC_MEM_32},
121 	{PCI_DEVICE_ID_PCIC_TI1131, "TI1131 PCI-CardBus Bridge", CB_TI113X,
122 		PCCBB_PCIC_IO_RELOC | PCCBB_PCIC_MEM_32},
123 
124 	{PCI_DEVICE_ID_PCIC_TI1211, "TI1211 PCI-CardBus Bridge", CB_TI12XX,
125 		PCCBB_PCIC_IO_RELOC | PCCBB_PCIC_MEM_32},
126 	{PCI_DEVICE_ID_PCIC_TI1220, "TI1220 PCI-CardBus Bridge", CB_TI12XX,
127 		PCCBB_PCIC_IO_RELOC | PCCBB_PCIC_MEM_32},
128 	{PCI_DEVICE_ID_PCIC_TI1221, "TI1221 PCI-CardBus Bridge", CB_TI12XX,
129 		PCCBB_PCIC_IO_RELOC | PCCBB_PCIC_MEM_32},
130 	{PCI_DEVICE_ID_PCIC_TI1225, "TI1225 PCI-CardBus Bridge", CB_TI12XX,
131 		PCCBB_PCIC_IO_RELOC | PCCBB_PCIC_MEM_32},
132 	{PCI_DEVICE_ID_PCIC_TI1250, "TI1250 PCI-CardBus Bridge", CB_TI12XX,
133 		PCCBB_PCIC_IO_RELOC | PCCBB_PCIC_MEM_32},
134 	{PCI_DEVICE_ID_PCIC_TI1251, "TI1251 PCI-CardBus Bridge", CB_TI12XX,
135 		PCCBB_PCIC_IO_RELOC | PCCBB_PCIC_MEM_32},
136 	{PCI_DEVICE_ID_PCIC_TI1251B,"TI1251B PCI-CardBus Bridge",CB_TI12XX,
137 		PCCBB_PCIC_IO_RELOC | PCCBB_PCIC_MEM_32},
138 	{PCI_DEVICE_ID_PCIC_TI1410, "TI1410 PCI-CardBus Bridge", CB_TI12XX,
139 		PCCBB_PCIC_IO_RELOC | PCCBB_PCIC_MEM_32},
140 	{PCI_DEVICE_ID_PCIC_TI1420, "TI1420 PCI-CardBus Bridge", CB_TI12XX,
141 		PCCBB_PCIC_IO_RELOC | PCCBB_PCIC_MEM_32},
142 	{PCI_DEVICE_ID_PCIC_TI1450, "TI1450 PCI-CardBus Bridge", CB_TI12XX,
143 		PCCBB_PCIC_IO_RELOC | PCCBB_PCIC_MEM_32},
144 	{PCI_DEVICE_ID_PCIC_TI1451, "TI1451 PCI-CardBus Bridge", CB_TI12XX,
145 		PCCBB_PCIC_IO_RELOC | PCCBB_PCIC_MEM_32},
146 
147 	/* Ricoh chips */
148 	{PCI_DEVICE_ID_RICOH_RL5C465, "RF5C465 PCI-CardBus Bridge",
149 		CB_RF5C46X, PCCBB_PCIC_MEM_32},
150 	{PCI_DEVICE_ID_RICOH_RL5C466, "RF5C466 PCI-CardBus Bridge",
151 		CB_RF5C46X, PCCBB_PCIC_MEM_32},
152 	{PCI_DEVICE_ID_RICOH_RL5C475, "RF5C475 PCI-CardBus Bridge",
153 		CB_RF5C47X, PCCBB_PCIC_MEM_32},
154 	{PCI_DEVICE_ID_RICOH_RL5C476, "RF5C476 PCI-CardBus Bridge",
155 		CB_RF5C47X, PCCBB_PCIC_MEM_32},
156 	{PCI_DEVICE_ID_RICOH_RL5C478, "RF5C478 PCI-CardBus Bridge",
157 		CB_RF5C47X, PCCBB_PCIC_MEM_32},
158 
159 	/* Toshiba products */
160 	{PCI_DEVICE_ID_TOSHIBA_TOPIC95, "ToPIC95 PCI-CardBus Bridge",
161 		CB_TOPIC95, PCCBB_PCIC_MEM_32},
162 	{PCI_DEVICE_ID_TOSHIBA_TOPIC95B, "ToPIC95B PCI-CardBus Bridge",
163 		CB_TOPIC95B, PCCBB_PCIC_MEM_32},
164 	{PCI_DEVICE_ID_TOSHIBA_TOPIC97, "ToPIC97 PCI-CardBus Bridge",
165 		CB_TOPIC97, PCCBB_PCIC_MEM_32},
166 	{PCI_DEVICE_ID_TOSHIBA_TOPIC100, "ToPIC100 PCI-CardBus Bridge",
167 		CB_TOPIC97, PCCBB_PCIC_MEM_32},
168 
169 	/* Cirrus Logic */
170 	{PCI_DEVICE_ID_PCIC_CLPD6832, "CLPD6832 PCI-CardBus Bridge",
171 		CB_CIRRUS, PCCBB_PCIC_MEM_32},
172 	{PCI_DEVICE_ID_PCIC_CLPD6833, "CLPD6833 PCI-CardBus Bridge",
173 		CB_CIRRUS, PCCBB_PCIC_MEM_32},
174 
175 	/* sentinel */
176 	{0 /* null id */, "unknown",
177 		CB_UNKNOWN, 0},
178 };
179 
180 
181 static int cb_chipset(u_int32_t pci_id, const char** namep, int* flagp);
182 static int pccbb_probe(device_t dev);
183 static void pccbb_chipinit(struct pccbb_softc* sc);
184 static int pccbb_attach(device_t dev);
185 static void pccbb_event_thread (void *arg);
186 static void pccbb_create_event_thread (struct pccbb_softc *sc);
187 static void pccbb_start_threads(void *arg);
188 static void pccbb_insert (struct pccbb_softc *sc);
189 static void pccbb_removal (struct pccbb_softc *sc);
190 static void pccbb_intr(void* arg);
191 static int pccbb_detect_voltage(struct pccbb_softc *sc);
192 static int pccbb_power(device_t dev, int volts);
193 static int pccbb_cardbus_detect_card(device_t dev);
194 static int pccbb_cardbus_reset(device_t dev);
195 static int pccbb_cardbus_io_open(device_t dev, int win,
196 				 u_int32_t start, u_int32_t end);
197 static int pccbb_cardbus_mem_open(device_t dev, int win,
198 				  u_int32_t start, u_int32_t end);
199 static void pccbb_cardbus_auto_open(struct pccbb_softc *sc, int type);
200 static int pccbb_cardbus_activate_resource(device_t self, device_t child,
201 					   int type, int rid,
202 					   struct resource *r);
203 static int pccbb_cardbus_deactivate_resource(device_t self, device_t child,
204 					     int type, int rid,
205 					     struct resource *r);
206 static struct resource* pccbb_cardbus_alloc_resource(device_t self,
207 			     device_t child, int type, int* rid,
208 			     u_long start, u_long end, u_long count,
209 			     u_int flags);
210 static int pccbb_cardbus_release_resource(device_t self, device_t child,
211 					  int type,int rid,
212 					  struct resource *r);
213 static void pccbb_pcic_wait_ready(struct pccbb_softc *sc);
214 static void pccbb_pcic_do_mem_map(struct pccbb_softc *sc, int win);
215 static int pccbb_pcic_mem_map(struct pccbb_softc *sc, int kind,
216 			      struct resource *r, bus_addr_t card_addr,
217 			      int *win);
218 static void pccbb_pcic_mem_unmap(struct pccbb_softc *sc, int window);
219 static void pccbb_pcic_do_io_map(struct pccbb_softc *sc, int win);
220 static int pccbb_pcic_io_map(struct pccbb_softc *sc, int width,
221 			     struct resource *r, bus_addr_t card_addr,
222 			     int *win);
223 static void pccbb_pcic_io_unmap(struct pccbb_softc *sc, int window);
224 static int pccbb_pcic_activate_resource(device_t self, device_t child,
225 					int type, int rid, struct resource *r);
226 static int pccbb_pcic_deactivate_resource(device_t self, device_t child,
227 					 int type,int rid, struct resource *r);
228 static struct resource* pccbb_pcic_alloc_resource(device_t self,device_t child,
229 				int type, int* rid, u_long start,
230 				u_long end, u_long count, u_int flags);
231 static int pccbb_pcic_release_resource(device_t self, device_t child, int type,
232 				       int rid, struct resource *res);
233 static int pccbb_pcic_set_res_flags(device_t self, device_t child, int type,
234 				    int rid, u_int32_t flags);
235 static int pccbb_pcic_set_memory_offset(device_t self, device_t child, int rid,
236 					u_int32_t offset);
237 static int pccbb_pcic_enable_socket(device_t self, device_t child);
238 static void pccbb_pcic_disable_socket(device_t self, device_t child);
239 static int pccbb_activate_resource(device_t self, device_t child, int type,
240 				   int rid, struct resource *r);
241 static int pccbb_deactivate_resource(device_t self, device_t child, int type,
242 				     int rid, struct resource *r);
243 static struct resource* pccbb_alloc_resource(device_t self, device_t child,
244 					     int type, int* rid, u_long start,
245 					     u_long end, u_long count,
246 					     u_int flags);
247 static int pccbb_release_resource(device_t self, device_t child,
248 				  int type, int rid, struct resource *r);
249 
250 
251 /************************************************************************/
252 /* Probe/Attach								*/
253 /************************************************************************/
254 
255 static int
256 cb_chipset(u_int32_t pci_id, const char** namep, int* flagp)
257 {
258 	int loopend = sizeof(yc_chipsets)/sizeof(yc_chipsets[0]);
259 	struct yenta_chipinfo *ycp, *ycend;
260 	ycend = yc_chipsets + loopend;
261 
262 	for (ycp = yc_chipsets; ycp < ycend && pci_id != ycp->yc_id; ++ycp);
263 	if (ycp == ycend) {
264 		/* not found */
265 		ycp = yc_chipsets + loopend - 1; /* to point the sentinel */
266 	}
267 	if (namep != NULL) {
268 		*namep = ycp->yc_name;
269 	}
270 	if (flagp != NULL) {
271 		*flagp = ycp->yc_flags;
272 	}
273 	return ycp->yc_chiptype;
274 }
275 
276 static int
277 pccbb_probe(device_t dev)
278 {
279 	const char *name;
280 
281 	if (cb_chipset(pci_get_devid(dev), &name, NULL) == CB_UNKNOWN)
282 		return ENXIO;
283 	device_set_desc(dev, name);
284 	return 0;
285 }
286 
287 static void
288 pccbb_chipinit(struct pccbb_softc* sc)
289 {
290 	/* Set CardBus latency timer */
291 	if (pci_read_config(sc->sc_dev, PCIR_SECLAT_1, 1) < 0x20)
292 		pci_write_config(sc->sc_dev, PCIR_SECLAT_1, 0x20, 1);
293 
294 	/* Set PCI latency timer */
295 	if (pci_read_config(sc->sc_dev, PCIR_LATTIMER, 1) < 0x20)
296 		pci_write_config(sc->sc_dev, PCIR_LATTIMER, 0x20, 1);
297 
298 	/* Enable memory access */
299 	PCI_MASK_CONFIG(sc->sc_dev, PCIR_COMMAND,
300 			| PCIM_CMD_MEMEN
301 			| PCIM_CMD_PORTEN
302 			| PCIM_CMD_BUSMASTEREN, 2);
303 
304 	/* disable Legacy IO */
305 	switch (sc->sc_chipset) {
306 	case CB_RF5C46X:
307 	case CB_RF5C47X:
308 		PCI_MASK_CONFIG(sc->sc_dev, PCCBBR_BRIDGECTRL,
309 				& ~(PCCBBM_BRIDGECTRL_RL_3E0_EN|
310 				    PCCBBM_BRIDGECTRL_RL_3E2_EN), 2);
311 		break;
312 	default:
313 		pci_write_config(sc->sc_dev, PCCBBR_LEGACY, 0x0, 4);
314 		break;
315 	}
316 
317 	/* Use PCI interrupt for interrupt routing */
318 	PCI_MASK2_CONFIG(sc->sc_dev, PCCBBR_BRIDGECTRL,
319 			 & ~(PCCBBM_BRIDGECTRL_MASTER_ABORT |
320 			     PCCBBM_BRIDGECTRL_INTR_IREQ_EN),
321 			 | PCCBBM_BRIDGECTRL_WRITE_POST_EN,
322 			 2);
323 
324 	switch (sc->sc_chipset) {
325 	case CB_TI113X:
326 		PCI_MASK2_CONFIG(sc->sc_dev, PCCBBR_CBCTRL,
327 				 & ~PCCBBM_CBCTRL_113X_PCI_INTR,
328 				 | PCCBBM_CBCTRL_113X_PCI_CSC
329 				 | PCCBBM_CBCTRL_113X_PCI_IRQ_EN, 1);
330 		PCI_MASK_CONFIG(sc->sc_dev, PCCBBR_DEVCTRL,
331 				& ~(PCCBBM_DEVCTRL_INT_SERIAL|
332 				    PCCBBM_DEVCTRL_INT_PCI), 1);
333 		PCIC_WRITE(sc, PCIC_INTR, PCIC_INTR_ENABLE);
334 		PCIC_WRITE(sc, PCIC_CSC_INTR, 0);
335 		break;
336 	case CB_TI12XX:
337 		PCIC_WRITE(sc, PCIC_INTR, PCIC_INTR_ENABLE);
338 		PCIC_WRITE(sc, PCIC_CSC_INTR, 0);
339 		break;
340 	case CB_TOPIC95B:
341 		PCI_MASK_CONFIG(sc->sc_dev, PCCBBR_TOPIC_SOCKETCTRL,
342 				| PCCBBM_TOPIC_SOCKETCTRL_SCR_IRQSEL, 4);
343 		PCI_MASK2_CONFIG(sc->sc_dev, PCCBBR_TOPIC_SLOTCTRL,
344 				 | PCCBBM_TOPIC_SLOTCTRL_SLOTON
345 				 | PCCBBM_TOPIC_SLOTCTRL_SLOTEN
346 				 | PCCBBM_TOPIC_SLOTCTRL_ID_LOCK
347 				 | PCCBBM_TOPIC_SLOTCTRL_CARDBUS,
348 				 & ~PCCBBM_TOPIC_SLOTCTRL_SWDETECT, 4);
349 		break;
350 	}
351 
352 	/* close all memory and io windows */
353 	pci_write_config(sc->sc_dev, PCCBBR_MEMBASE0, 0xffffffff, 4);
354 	pci_write_config(sc->sc_dev, PCCBBR_MEMLIMIT0, 0, 4);
355 	pci_write_config(sc->sc_dev, PCCBBR_MEMBASE1, 0xffffffff, 4);
356 	pci_write_config(sc->sc_dev, PCCBBR_MEMLIMIT1, 0, 4);
357 	pci_write_config(sc->sc_dev, PCCBBR_IOBASE0, 0xffffffff, 4);
358 	pci_write_config(sc->sc_dev, PCCBBR_IOLIMIT0, 0, 4);
359 	pci_write_config(sc->sc_dev, PCCBBR_IOBASE1, 0xffffffff, 4);
360 	pci_write_config(sc->sc_dev, PCCBBR_IOLIMIT1, 0, 4);
361 }
362 
363 static int
364 pccbb_attach(device_t dev)
365 {
366 	struct pccbb_softc *sc = (struct pccbb_softc *)device_get_softc(dev);
367 	int flags;
368 	int rid;
369 	u_int32_t tmp;
370 
371 	if (!softcs_init) {
372 		softcs_init = 1;
373 		STAILQ_INIT(&softcs);
374 	}
375 	sc->sc_chipset = cb_chipset(pci_get_devid(dev), NULL, &flags);
376 	sc->sc_dev = dev;
377 	sc->sc_flags = 0;
378 	sc->sc_cbdev = NULL;
379 	sc->sc_pccarddev = NULL;
380 	sc->memalloc = 0;
381 	sc->ioalloc = 0;
382 	SLIST_INIT(&sc->rl);
383 
384 	/* Ths PCI bus should have given me memory... right? */
385 	rid=PCCBBR_SOCKBASE;
386 	sc->sc_base_res=bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
387 					   0,~0,1, RF_ACTIVE);
388 	if (!sc->sc_base_res) {
389 		/*
390 		 * XXX eVILE HACK BAD THING! XXX
391 		 * The pci bus device should do this for us.
392 		 * Some BIOSes doesn't assign a memory space properly.
393 		 * So we try to manually put one in...
394 		 */
395 		u_int32_t sockbase;
396 
397 		sockbase = pci_read_config(dev, rid, 4);
398 		if (sockbase < 0x100000 || sockbase >= 0xfffffff0) {
399 			pci_write_config(dev, rid, 0xffffffff, 4);
400 			sockbase = pci_read_config(dev, rid, 4);
401 			sockbase = (sockbase & 0xfffffff0) &
402 				-(sockbase & 0xfffffff0);
403 			sc->sc_base_res = bus_generic_alloc_resource(
404 				device_get_parent(dev), dev, SYS_RES_MEMORY,
405 				&rid, CARDBUS_SYS_RES_MEMORY_START,
406 				CARDBUS_SYS_RES_MEMORY_END, sockbase,
407 				RF_ACTIVE|rman_make_alignment_flags(sockbase));
408 			if (!sc->sc_base_res){
409 				device_printf(dev,
410 					"Could not grab register memory\n");
411 				return ENOMEM;
412 			}
413 			pci_write_config(dev, PCCBBR_SOCKBASE,
414 					 rman_get_start(sc->sc_base_res), 4);
415 			DEVPRINTF((dev, "PCI Memory allocated: %08lx\n",
416 				   rman_get_start(sc->sc_base_res)));
417 		} else {
418 			device_printf(dev, "Could not map register memory\n");
419 			return ENOMEM;
420 		}
421 	}
422 
423 	sc->sc_socketreg =
424 		(struct pccbb_socketreg *)rman_get_virtual(sc->sc_base_res);
425 	pccbb_chipinit(sc);
426 
427 	/* CSC Interrupt: Card detect interrupt on */
428 	sc->sc_socketreg->socket_mask |= PCCBB_SOCKET_MASK_CD;
429 
430 	/* reset interrupt */
431 	tmp = sc->sc_socketreg->socket_event;
432 	sc->sc_socketreg->socket_event = tmp;
433 
434 	/* Map and establish the interrupt. */
435 	rid=0;
436 	sc->sc_irq_res=bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
437 					  RF_SHAREABLE | RF_ACTIVE);
438 	if (sc->sc_irq_res == NULL)  {
439 		printf("pccbb: Unable to map IRQ...\n");
440 		return ENOMEM;
441 	}
442 
443 	if (bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_BIO, pccbb_intr, sc,
444 		     &(sc->sc_intrhand))) {
445 		device_printf(dev, "couldn't establish interrupt");
446 		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
447 		bus_release_resource(dev, SYS_RES_MEMORY, PCCBBR_SOCKBASE,
448 				     sc->sc_base_res);
449 		return ENOMEM;
450 	}
451 
452 	/* attach children */
453 	sc->sc_cbdev = device_add_child(dev, "cardbus", -1);
454 	if (sc->sc_cbdev == NULL)
455 		DEVPRINTF((dev, "Cannot add cardbus bus!\n"));
456 	else if (device_probe_and_attach(sc->sc_cbdev) != 0) {
457 		DEVPRINTF((dev, "Cannot attach cardbus bus!\n"));
458 		sc->sc_cbdev = NULL;
459 	}
460 
461 	sc->sc_pccarddev = device_add_child(dev, "pccard", -1);
462 	if (sc->sc_pccarddev == NULL)
463 		DEVPRINTF((dev, "Cannot add pccard bus!\n"));
464 	else if (device_probe_and_attach(sc->sc_pccarddev) != 0) {
465 		DEVPRINTF((dev, "Cannot attach pccard bus!\n"));
466 		sc->sc_pccarddev = NULL;
467 	}
468 
469 	if (sc->sc_cbdev == NULL && sc->sc_pccarddev == NULL) {
470 		device_printf(dev, "Failed to attach cardbus/pccard bus!\n");
471 		bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_intrhand);
472 		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
473 		bus_release_resource(dev, SYS_RES_MEMORY, PCCBBR_SOCKBASE,
474 				     sc->sc_base_res);
475 		return ENOMEM;
476 	}
477 
478 	{
479 		struct pccbb_sclist *sclist;
480 		sclist = malloc(sizeof(struct pccbb_sclist), M_DEVBUF,
481 				M_WAITOK);
482 		sclist->sc = sc;
483 		STAILQ_INSERT_TAIL(&softcs, sclist, entries);
484 	}
485 	return 0;
486 }
487 
488 /************************************************************************/
489 /* Kthreads								*/
490 /************************************************************************/
491 
492 static void
493 pccbb_event_thread (void *arg)
494 {
495 	struct pccbb_softc *sc = arg;
496 	int s;
497 	u_int32_t status;
498 
499 	s = splhigh();
500 	for(;;) {
501 		if (sc->sc_flags & PCCBB_INITIALCARD)
502 			sc->sc_flags &= ~PCCBB_INITIALCARD;
503 		else {
504 			splx (s);
505 			tsleep (sc, PWAIT, "pccbbev", 0);
506 			/*
507 			 * Delay some time, make sure the user is done with
508 			 * whatever he is doing.
509 			 */
510 			DELAY(1000*1000);
511 			s = splhigh();
512 		}
513 
514 		sc->sc_flags |= PCCBB_CARDSTATUS_BUSY;
515 		status = sc->sc_socketreg->socket_state;
516 		if ((status & PCCBB_SOCKET_STAT_CD) == 0) {
517 			if (!(sc->sc_flags & PCCBB_CARDATTACHED))
518 				pccbb_insert(sc);
519 			else
520 				device_printf(sc->sc_dev,
521 					      "duplicate card insert\n");
522 		} else {
523 			if (!(sc->sc_flags & PCCBB_CARDATTACHED))
524 				DEVPRINTF((sc->sc_dev,
525 					   "removal of nonexistant card!\n"));
526 			else
527 				pccbb_removal(sc);
528 		}
529 		sc->sc_flags &= ~PCCBB_CARDSTATUS_BUSY;
530 		splx (s);
531 	}
532 	/* NOTREACHED */
533 	kthread_exit(0);
534 }
535 
536 static void
537 pccbb_create_event_thread (struct pccbb_softc *sc)
538 {
539 	if (kthread_create(pccbb_event_thread, sc, &sc->event_thread,
540 			   0, "%s%d", device_get_name(sc->sc_dev),
541 			   device_get_unit(sc->sc_dev))) {
542 		device_printf (sc->sc_dev, "unable to create event thread.\n");
543 		panic ("pccbb_create_event_thread");
544 	}
545 }
546 
547 static void
548 pccbb_start_threads(void *arg)
549 {
550 	struct pccbb_sclist *sclist;
551 
552 	STAILQ_FOREACH(sclist, &softcs, entries) {
553 		if (0 == (sclist->sc->sc_socketreg->socket_state &
554 			  PCCBB_SOCKET_STAT_CD)) {
555 			sclist->sc->sc_flags |= PCCBB_INITIALCARD;
556 		}
557 		pccbb_create_event_thread(sclist->sc);
558 	}
559 }
560 
561 /************************************************************************/
562 /* Insert/removal							*/
563 /************************************************************************/
564 
565 static void
566 pccbb_insert (struct pccbb_softc *sc)
567 {
568 	u_int32_t sockevent, sockstate;
569 	int timeout = 30;
570 
571 	do {
572 		sockevent = sc->sc_socketreg->socket_event;
573 		sockstate = sc->sc_socketreg->socket_state;
574 	} while (sockstate & PCCBB_SOCKET_STAT_CD && --timeout > 0);
575 
576 	if (timeout < 0) {
577 		device_printf (sc->sc_dev, "insert timeout");
578 		return;
579 	}
580 
581 	DEVPRINTF((sc->sc_dev, "card inserted: event=0x%08x, state=%08x\n",
582 		   sockevent, sockstate));
583 
584 	if (sockstate & PCCBB_SOCKET_STAT_16BIT && sc->sc_pccarddev != NULL) {
585 		sc->sc_flags |= PCCBB_CARDATTACHED | PCCBB_16BIT_CARD;
586 		if (CARD_ATTACH_CARD(sc->sc_pccarddev) != 0) {
587 			device_printf(sc->sc_dev, "card activation failed\n");
588 			sc->sc_flags &= ~PCCBB_CARDATTACHED;
589 		}
590 	} else if (sockstate & PCCBB_SOCKET_STAT_CB && sc->sc_cbdev != NULL) {
591 		sc->sc_flags |= PCCBB_CARDATTACHED;
592 		sc->sc_flags &= ~PCCBB_16BIT_CARD;
593 		if (CARD_ATTACH_CARD(sc->sc_cbdev) != 0) {
594 			device_printf(sc->sc_dev, "card activation failed\n");
595 			sc->sc_flags &= ~PCCBB_CARDATTACHED;
596 		}
597 	} else {
598 		device_printf (sc->sc_dev, "Unsupported card type detected\n");
599 	}
600 }
601 
602 static void
603 pccbb_removal (struct pccbb_softc *sc)
604 {
605 	u_int32_t sockstate;
606 	struct pccbb_reslist *rle;
607 
608 	sockstate = sc->sc_socketreg->socket_state;
609 
610 	sc->sc_flags &= ~PCCBB_CARDATTACHED;
611 	if (sockstate & PCCBB_16BIT_CARD)
612 		CARD_DETACH_CARD(sc->sc_pccarddev, DETACH_FORCE);
613 	else
614 		CARD_DETACH_CARD(sc->sc_cbdev, DETACH_FORCE);
615 
616 	while (NULL != (rle = SLIST_FIRST(&sc->rl))) {
617 		device_printf(sc->sc_dev, "WARNING: Resource left allocated!  "
618 			      "This is a bug... (rid=%x, type=%d, addr=%x)\n",
619 			      rle->rid, rle->type, rle->start);
620 		SLIST_REMOVE_HEAD(&sc->rl, entries);
621 	}
622 }
623 
624 /************************************************************************/
625 /* Interrupt Handler							*/
626 /************************************************************************/
627 
628 static void
629 pccbb_intr(void* arg)
630 {
631 	struct pccbb_softc *sc = arg;
632 	u_int32_t sockevent;
633 	int tmp;
634 
635 	if (!(sockevent = sc->sc_socketreg->socket_event)) {
636 		/* not for me. */
637 		return;
638 	}
639 
640 	/* reset bit */
641 	sc->sc_socketreg->socket_event = sockevent | 0x01;
642 
643 	if (sockevent & PCCBB_SOCKET_EVENT_CD) {
644 		for (tmp = 0; tmp <= 100 &&
645 		     (sc->sc_flags & PCCBB_CARDSTATUS_BUSY); tmp++) {
646 			if (tmp == 0)
647 				DEVPRINTF((sc->sc_dev, "(pccbbintr): busy!"));
648 			else
649 				DPRINTF(("."));
650 			DELAY(1);
651 		}
652 		if (sc->sc_flags & PCCBB_CARDSTATUS_BUSY) {
653 			DPRINTF(("failed!  Going ahead anyway..."));
654 			sc->sc_flags &= ~PCCBB_CARDSTATUS_BUSY;
655 		}
656 		wakeup(sc);
657 	} else {
658 		if (sockevent & PCCBB_SOCKET_EVENT_CSTS) {
659 			DPRINTF((" cstsevent occures, 0x%08x\n",
660 				 sc->sc_socketreg->socket_state));
661 		}
662 		if (sockevent & PCCBB_SOCKET_EVENT_POWER) {
663 			DPRINTF((" pwrevent occures, 0x%08x\n",
664 				 sc->sc_socketreg->socket_state));
665 		}
666 	}
667 
668 	return;
669 }
670 
671 /************************************************************************/
672 /* Power functions							*/
673 /************************************************************************/
674 
675 static int
676 pccbb_detect_voltage(struct pccbb_softc *sc)
677 {
678 	u_int32_t psr;
679 	int vol = CARD_UKN_CARD;
680 
681 	psr = sc->sc_socketreg->socket_state;
682 
683 	if (psr & PCCBB_SOCKET_STAT_5VCARD) {
684 		vol |= CARD_5V_CARD;
685 	}
686 	if (psr & PCCBB_SOCKET_STAT_3VCARD) {
687 		vol |= CARD_3V_CARD;
688 	}
689 	if (psr & PCCBB_SOCKET_STAT_XVCARD) {
690 		vol |= CARD_XV_CARD;
691 	}
692 	if (psr & PCCBB_SOCKET_STAT_YVCARD) {
693 		vol |= CARD_YV_CARD;
694 	}
695 
696 	return vol;
697 }
698 
699 static int
700 pccbb_power(device_t dev, int volts)
701 {
702 	u_int32_t status, sock_ctrl;
703 	struct pccbb_softc *sc = device_get_softc(dev);
704 
705 	DEVPRINTF((sc->sc_dev, "pccbb_power: %s and %s [%x]\n",
706 		   (volts & CARD_VCCMASK) == CARD_VCC_UC ? "CARD_VCC_UC" :
707 		   (volts & CARD_VCCMASK) == CARD_VCC_5V ? "CARD_VCC_5V" :
708 		   (volts & CARD_VCCMASK) == CARD_VCC_3V ? "CARD_VCC_3V" :
709 		   (volts & CARD_VCCMASK) == CARD_VCC_XV ? "CARD_VCC_XV" :
710 		   (volts & CARD_VCCMASK) == CARD_VCC_YV ? "CARD_VCC_YV" :
711 		   (volts & CARD_VCCMASK) == CARD_VCC_0V ? "CARD_VCC_0V" :
712 		   "VCC-UNKNOWN",
713 		   (volts & CARD_VPPMASK) == CARD_VPP_UC ? "CARD_VPP_UC" :
714 		   (volts & CARD_VPPMASK) == CARD_VPP_12V ? "CARD_VPP_12V" :
715 		   (volts & CARD_VPPMASK) == CARD_VPP_VCC ? "CARD_VPP_VCC" :
716 		   (volts & CARD_VPPMASK) == CARD_VPP_0V ? "CARD_VPP_0V" :
717 		   "VPP-UNKNOWN",
718 		   volts));
719 
720 	status = sc->sc_socketreg->socket_state;
721 	sock_ctrl = sc->sc_socketreg->socket_control;
722 
723 	switch (volts & CARD_VCCMASK) {
724 	case CARD_VCC_UC:
725 		break;
726 	case CARD_VCC_5V:
727 		if (PCCBB_SOCKET_STAT_5VCARD & status) { /* check 5 V card */
728 			sock_ctrl &= ~PCCBB_SOCKET_CTRL_VCCMASK;
729 			sock_ctrl |= PCCBB_SOCKET_CTRL_VCC_5V;
730 		} else {
731 			device_printf(sc->sc_dev,
732 				      "BAD voltage request: no 5 V card\n");
733 		}
734 		break;
735 	case CARD_VCC_3V:
736 		if (PCCBB_SOCKET_STAT_3VCARD & status) {
737 			sock_ctrl &= ~PCCBB_SOCKET_CTRL_VCCMASK;
738 			sock_ctrl |= PCCBB_SOCKET_CTRL_VCC_3V;
739 		} else {
740 			device_printf(sc->sc_dev,
741 				      "BAD voltage request: no 3.3 V card\n");
742 		}
743 		break;
744 	case CARD_VCC_0V:
745 		sock_ctrl &= ~PCCBB_SOCKET_CTRL_VCCMASK;
746 		break;
747 	default:
748 		return 0;			/* power NEVER changed */
749 		break;
750 	}
751 
752 	switch (volts & CARD_VPPMASK) {
753 	case CARD_VPP_UC:
754 		break;
755 	case CARD_VPP_0V:
756 		sock_ctrl &= ~PCCBB_SOCKET_CTRL_VPPMASK;
757 		break;
758 	case CARD_VPP_VCC:
759 		sock_ctrl &= ~PCCBB_SOCKET_CTRL_VPPMASK;
760 		sock_ctrl |= ((sock_ctrl >> 4) & 0x07);
761 		break;
762 	case CARD_VPP_12V:
763 		sock_ctrl &= ~PCCBB_SOCKET_CTRL_VPPMASK;
764 		sock_ctrl |= PCCBB_SOCKET_CTRL_VPP_12V;
765 		break;
766 	}
767 
768 	sc->sc_socketreg->socket_control = sock_ctrl;
769 	status = sc->sc_socketreg->socket_state;
770 
771 	{
772 		int timeout = 20;
773 		u_int32_t sockevent;
774 		do {
775 			DELAY(20*1000);
776 			sockevent = sc->sc_socketreg->socket_event;
777 		} while (!(sockevent & PCCBB_SOCKET_EVENT_POWER) &&
778 			 --timeout > 0);
779 		/* reset event status */
780 		sc->sc_socketreg->socket_event = sockevent;
781 		if ( timeout < 0 ) {
782 			printf ("VCC supply failed.\n");
783 			return 0;
784 		}
785 	}
786 	/* XXX
787 	 * delay 400 ms: thgough the standard defines that the Vcc set-up time
788 	 * is 20 ms, some PC-Card bridge requires longer duration.
789 	 */
790 	DELAY(400*1000);
791 
792 	if (status & PCCBB_SOCKET_STAT_BADVCC) {
793 		device_printf(sc->sc_dev,
794 			      "bad Vcc request. ctrl=0x%x, status=0x%x\n",
795 			      sock_ctrl ,status);
796 		printf("pccbb_power: %s and %s [%x]\n",
797 		       (volts & CARD_VCCMASK) == CARD_VCC_UC ? "CARD_VCC_UC" :
798 		       (volts & CARD_VCCMASK) == CARD_VCC_5V ? "CARD_VCC_5V" :
799 		       (volts & CARD_VCCMASK) == CARD_VCC_3V ? "CARD_VCC_3V" :
800 		       (volts & CARD_VCCMASK) == CARD_VCC_XV ? "CARD_VCC_XV" :
801 		       (volts & CARD_VCCMASK) == CARD_VCC_YV ? "CARD_VCC_YV" :
802 		       (volts & CARD_VCCMASK) == CARD_VCC_0V ? "CARD_VCC_0V" :
803 		       "VCC-UNKNOWN",
804 		       (volts & CARD_VPPMASK) == CARD_VPP_UC ? "CARD_VPP_UC" :
805 		       (volts & CARD_VPPMASK) == CARD_VPP_12V ? "CARD_VPP_12V":
806 		       (volts & CARD_VPPMASK) == CARD_VPP_VCC ? "CARD_VPP_VCC":
807 		       (volts & CARD_VPPMASK) == CARD_VPP_0V ? "CARD_VPP_0V" :
808 		       "VPP-UNKNOWN",
809 		       volts);
810 		return 0;
811 	}
812 	return 1;		/* power changed correctly */
813 }
814 
815 /************************************************************************/
816 /* PCCBB methods							*/
817 /************************************************************************/
818 
819 static int
820 pccbb_cardbus_detect_card(device_t dev)
821 {
822 	struct pccbb_softc *sc = device_get_softc(dev);
823 	u_int32_t sockstat = sc->sc_socketreg->socket_state;
824 
825 	if (sockstat & PCCBB_SOCKET_STAT_CB)
826 		return pccbb_detect_voltage(sc);
827 	return 0;
828 }
829 
830 static int
831 pccbb_cardbus_reset(device_t dev)
832 {
833 	struct pccbb_softc *sc = device_get_softc(dev);
834 	u_int32_t bcr = pci_read_config(dev, PCCBBR_BRIDGECTRL, 2);
835 	int delay_us;
836 
837 	delay_us = sc->sc_chipset == CB_RF5C47X ? 400*1000 : 20*1000;
838 
839 	bcr |= PCCBBM_BRIDGECTRL_RESET;
840 	pci_write_config(dev, PCCBBR_BRIDGECTRL, bcr, 2);
841 
842 	DELAY(delay_us);
843 
844 	/* If a card exists, unreset it! */
845 	if (sc->sc_flags & PCCBB_CARDATTACHED) {
846 		bcr &= ~PCCBBM_BRIDGECTRL_RESET;
847 		pci_write_config(dev, PCCBBR_BRIDGECTRL, bcr, 2);
848 		DELAY(delay_us);
849 	}
850 	return 1;
851 }
852 
853 
854 /************************************************************************/
855 /* Cardbus Resource							*/
856 /************************************************************************/
857 
858 static int
859 pccbb_cardbus_io_open(device_t dev, int win, u_int32_t start, u_int32_t end)
860 {
861 	int basereg;
862 	int limitreg;
863 
864 	if ((win < 0) || (win > 1)) {
865 		DEVPRINTF((dev,
866 			   "pccbb_cardbus_io_open: window out of range %d\n",
867 			   win));
868 		return EINVAL;
869 	}
870 
871 	basereg = win*8 + PCCBBR_IOBASE0;
872 	limitreg = win*8 + PCCBBR_IOLIMIT0;
873 
874 	pci_write_config(dev, basereg, start, 4);
875 	pci_write_config(dev, limitreg, end, 4);
876 	return 0;
877 }
878 
879 static int
880 pccbb_cardbus_mem_open(device_t dev, int win, u_int32_t start, u_int32_t end)
881 {
882 	int basereg;
883 	int limitreg;
884 
885 	if ((win < 0) || (win > 1)) {
886 		DEVPRINTF((dev,
887 			   "pccbb_cardbus_mem_open: window out of range %d\n",
888 			   win));
889 		return EINVAL;
890 	}
891 
892 	basereg = win*8 + PCCBBR_MEMBASE0;
893 	limitreg = win*8 + PCCBBR_MEMLIMIT0;
894 
895 	pci_write_config(dev, basereg, start, 4);
896 	pci_write_config(dev, limitreg, end, 4);
897 	return 0;
898 }
899 
900 static void
901 pccbb_cardbus_auto_open(struct pccbb_softc *sc, int type)
902 {
903 	u_int32_t starts[2];
904 	u_int32_t ends[2];
905 	struct pccbb_reslist *rle;
906 	int align;
907 
908 	starts[0] = starts[1] = 0xffffffff;
909 	ends[0] = ends[1] = 0;
910 
911 	SLIST_FOREACH(rle, &sc->rl, entries) {
912 		if (rle->type != type)
913 			;
914 		else if (starts[0] == 0xffffffff) {
915 			starts[0] = rle->start;
916 			ends[0] = rle->end;
917 			rle->win = 0;
918 		} else if (rle->end > ends[0] &&
919 			   rle->start - ends[0] < PCCBB_AUTO_OPEN_SMALLHOLE) {
920 			ends[0] = rle->end;
921 			rle->win = 0;
922 		} else if (rle->start < starts[0] &&
923 			   starts[0] - rle->end < PCCBB_AUTO_OPEN_SMALLHOLE) {
924 			starts[0] = rle->start;
925 			rle->win = 0;
926 		} else if (starts[1] == 0xffffffff) {
927 			starts[1] = rle->start;
928 			ends[1] = rle->end;
929 			rle->win = 1;
930 		} else if (rle->end > ends[1] &&
931 			   rle->start - ends[1] < PCCBB_AUTO_OPEN_SMALLHOLE) {
932 			ends[1] = rle->end;
933 			rle->win = 1;
934 		} else if (rle->start < starts[1] &&
935 			   starts[1] - rle->end < PCCBB_AUTO_OPEN_SMALLHOLE) {
936 			starts[1] = rle->start;
937 			rle->win = 1;
938 		} else {
939 			u_int32_t diffs[2];
940 
941 			diffs[0] = diffs[1] = 0xffffffff;
942 			if (rle->start > ends[0])
943 				diffs[0] = rle->start - ends[0];
944 			else if (rle->end < starts[0])
945 				diffs[0] = starts[0] - rle->end;
946 			if (rle->start > ends[1])
947 				diffs[1] = rle->start - ends[1];
948 			else if (rle->end < starts[1])
949 				diffs[1] = starts[1] - rle->end;
950 
951 			rle->win = (diffs[0] <= diffs[1])?0:1;
952 			if (rle->start > ends[rle->win])
953 				ends[rle->win] = rle->end;
954 			else if (rle->end < starts[rle->win])
955 				starts[rle->win] = rle->start;
956 			else
957 				panic("pccbb_auto_open: Weird condition!\n");
958 		}
959 	}
960 
961 	if (type == SYS_RES_MEMORY)
962 		align = PCCBB_MEMALIGN;
963 	else if (type == SYS_RES_IOPORT)
964 		align = PCCBB_IOALIGN;
965 	else
966 		align = 1;
967 
968 	if (starts[0] != 0xffffffff)
969 		starts[0] -= starts[0] % align;
970 	if (starts[1] != 0xffffffff)
971 		starts[1] -= starts[1] % align;
972 	if (ends[0] % align != 0)
973 		ends[0] += align - ends[0]%align;
974 	if (ends[1] % align != 0)
975 		ends[1] += align - ends[1]%align;
976 
977 	if (type == SYS_RES_MEMORY) {
978 		pccbb_cardbus_mem_open(sc->sc_dev, 0, starts[0], ends[0]);
979 		pccbb_cardbus_mem_open(sc->sc_dev, 1, starts[1], ends[1]);
980 	} else if (type == SYS_RES_IOPORT) {
981 		pccbb_cardbus_io_open(sc->sc_dev, 0, starts[0], ends[0]);
982 		pccbb_cardbus_io_open(sc->sc_dev, 1, starts[1], ends[1]);
983 	}
984 }
985 
986 static int
987 pccbb_cardbus_activate_resource(device_t self, device_t child, int type,
988 				int rid, struct resource *r)
989 {
990 	struct pccbb_softc *sc = device_get_softc(self);
991 	struct pccbb_reslist *rle;
992 
993 	if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
994 		SLIST_FOREACH(rle, &sc->rl, entries) {
995 			if (type == rle->type && rid == rle->rid &&
996 			    child == rle->odev)
997 				return bus_generic_activate_resource(
998 					self, child, type, rid, r);
999 		}
1000 		rle = malloc(sizeof(struct pccbb_reslist), M_DEVBUF, M_WAITOK);
1001 		rle->type = type;
1002 		rle->rid = rid;
1003 		rle->start = rman_get_start(r);
1004 		rle->end = rman_get_end(r);
1005 		rle->odev = child;
1006 		rle->win = -1;
1007 		SLIST_INSERT_HEAD(&sc->rl, rle, entries);
1008 
1009 		pccbb_cardbus_auto_open(sc, type);
1010 	}
1011 
1012 	return bus_generic_activate_resource(self, child, type, rid, r);
1013 }
1014 
1015 static int
1016 pccbb_cardbus_deactivate_resource(device_t self, device_t child, int type,
1017 				  int rid, struct resource *r)
1018 {
1019 	struct pccbb_softc *sc = device_get_softc(self);
1020 	struct pccbb_reslist *rle;
1021 
1022 	SLIST_FOREACH(rle, &sc->rl, entries) {
1023 		if (type == rle->type && rid == rle->rid &&
1024 		    child == rle->odev) {
1025 			SLIST_REMOVE(&sc->rl, rle, pccbb_reslist, entries);
1026 			if (type == SYS_RES_IOPORT ||
1027 			    type == SYS_RES_MEMORY)
1028 				pccbb_cardbus_auto_open(sc, type);
1029 			free(rle, M_DEVBUF);
1030 			break;
1031 		}
1032 	}
1033 	return bus_generic_deactivate_resource(self, child, type, rid, r);
1034 }
1035 
1036 static struct resource*
1037 pccbb_cardbus_alloc_resource(device_t self, device_t child, int type, int* rid,
1038 			     u_long start, u_long end, u_long count,
1039 			     u_int flags)
1040 {
1041 	if (type == SYS_RES_IRQ) {
1042 		struct pccbb_softc *sc = device_get_softc(self);
1043 		if (start == 0) {
1044 			start = end = rman_get_start(sc->sc_irq_res);
1045 		}
1046 		return bus_generic_alloc_resource(self, child, type, rid,
1047 						  start, end, count, flags);
1048 	} else {
1049 		if (type == SYS_RES_MEMORY && start == 0 && end == ~0) {
1050 			start = CARDBUS_SYS_RES_MEMORY_START;
1051 			end = CARDBUS_SYS_RES_MEMORY_END;
1052 		} else if (type == SYS_RES_IOPORT && start == 0 && end == ~0) {
1053 			start = CARDBUS_SYS_RES_IOPORT_START;
1054 			end = CARDBUS_SYS_RES_IOPORT_END;
1055 		}
1056 		return bus_generic_alloc_resource(self, child, type, rid,
1057 						  start, end, count, flags);
1058 	}
1059 }
1060 
1061 static int
1062 pccbb_cardbus_release_resource(device_t self, device_t child, int type,
1063 			       int rid, struct resource *r)
1064 {
1065 	return bus_generic_release_resource(self, child, type, rid, r);
1066 }
1067 
1068 /************************************************************************/
1069 /* PC Card Resources							*/
1070 /************************************************************************/
1071 
1072 static void
1073 pccbb_pcic_wait_ready(struct pccbb_softc *sc)
1074 {
1075 	int i;
1076 	DEVPRINTF((sc->sc_dev, "pccbb_pcic_wait_ready: status 0x%02x\n",
1077 		   PCIC_READ(sc, PCIC_IF_STATUS)));
1078 	for (i = 0; i < 10000; i++) {
1079 		if (PCIC_READ(sc, PCIC_IF_STATUS) & PCIC_IF_STATUS_READY) {
1080 			return;
1081 		}
1082 		DELAY(500);
1083 	}
1084 	device_printf(sc->sc_dev, "ready never happened, status = %02x\n",
1085 		      PCIC_READ(sc, PCIC_IF_STATUS));
1086 }
1087 
1088 #define PCIC_MEMINFO(NUM) { \
1089 	PCIC_SYSMEM_ADDR ## NUM ## _START_LSB, \
1090 	PCIC_SYSMEM_ADDR ## NUM ## _START_MSB, \
1091 	PCIC_SYSMEM_ADDR ## NUM ## _STOP_LSB, \
1092 	PCIC_SYSMEM_ADDR ## NUM ## _STOP_MSB, \
1093 	PCIC_CARDMEM_ADDR ## NUM ## _LSB, \
1094 	PCIC_CARDMEM_ADDR ## NUM ## _MSB, \
1095 	PCIC_ADDRWIN_ENABLE_MEM ## NUM ## , \
1096 }
1097 
1098 static struct mem_map_index_st {
1099 	int sysmem_start_lsb;
1100 	int sysmem_start_msb;
1101 	int sysmem_stop_lsb;
1102 	int sysmem_stop_msb;
1103 	int cardmem_lsb;
1104 	int cardmem_msb;
1105 	int memenable;
1106 } mem_map_index[] = {
1107 	PCIC_MEMINFO(0),
1108 	PCIC_MEMINFO(1),
1109 	PCIC_MEMINFO(2),
1110 	PCIC_MEMINFO(3),
1111 	PCIC_MEMINFO(4),
1112 };
1113 #undef PCIC_MEMINFO
1114 
1115 static void
1116 pccbb_pcic_do_mem_map(struct pccbb_softc *sc, int win)
1117 {
1118 	PCIC_WRITE(sc, mem_map_index[win].sysmem_start_lsb,
1119 		   (sc->mem[win].addr >> PCIC_SYSMEM_ADDRX_SHIFT) & 0xff);
1120 	PCIC_WRITE(sc, mem_map_index[win].sysmem_start_msb,
1121 		   ((sc->mem[win].addr >> (PCIC_SYSMEM_ADDRX_SHIFT + 8)) &
1122 		    PCIC_SYSMEM_ADDRX_START_MSB_ADDR_MASK));
1123 
1124 	PCIC_WRITE(sc, mem_map_index[win].sysmem_stop_lsb,
1125 		   ((sc->mem[win].addr + sc->mem[win].realsize - 1) >>
1126 		    PCIC_SYSMEM_ADDRX_SHIFT) & 0xff);
1127 	PCIC_WRITE(sc, mem_map_index[win].sysmem_stop_msb,
1128 		   (((sc->mem[win].addr + sc->mem[win].realsize - 1) >>
1129 		     (PCIC_SYSMEM_ADDRX_SHIFT + 8)) &
1130 		    PCIC_SYSMEM_ADDRX_STOP_MSB_ADDR_MASK) |
1131 		   PCIC_SYSMEM_ADDRX_STOP_MSB_WAIT2);
1132 
1133 	PCIC_WRITE(sc, mem_map_index[win].cardmem_lsb,
1134 		   (sc->mem[win].offset >> PCIC_CARDMEM_ADDRX_SHIFT) & 0xff);
1135 	PCIC_WRITE(sc, mem_map_index[win].cardmem_msb,
1136 		   ((sc->mem[win].offset >> (PCIC_CARDMEM_ADDRX_SHIFT + 8)) &
1137 		    PCIC_CARDMEM_ADDRX_MSB_ADDR_MASK) |
1138 		   ((sc->mem[win].kind == PCCARD_MEM_ATTR) ?
1139 		    PCIC_CARDMEM_ADDRX_MSB_REGACTIVE_ATTR : 0));
1140 
1141 	PCIC_MASK(sc, PCIC_ADDRWIN_ENABLE, | PCIC_ADDRWIN_ENABLE_MEMCS16
1142 		  			   | mem_map_index[win].memenable);
1143 
1144 	DELAY(100);
1145 
1146 #ifdef CBB_DEBUG
1147 	{
1148 		int r1, r2, r3, r4, r5, r6;
1149 		r1 = PCIC_READ(sc, mem_map_index[win].sysmem_start_msb);
1150 		r2 = PCIC_READ(sc, mem_map_index[win].sysmem_start_lsb);
1151 		r3 = PCIC_READ(sc, mem_map_index[win].sysmem_stop_msb);
1152 		r4 = PCIC_READ(sc, mem_map_index[win].sysmem_stop_lsb);
1153 		r5 = PCIC_READ(sc, mem_map_index[win].cardmem_msb);
1154 		r6 = PCIC_READ(sc, mem_map_index[win].cardmem_lsb);
1155 		DPRINTF(("pccbb_pcic_do_mem_map window %d: %02x%02x %02x%02x "
1156 			 "%02x%02x\n", win, r1, r2, r3, r4, r5, r6));
1157 	}
1158 #endif
1159 }
1160 
1161 static int
1162 pccbb_pcic_mem_map(struct pccbb_softc *sc, int kind,
1163 		   struct resource *r, bus_addr_t card_addr, int *win)
1164 {
1165 	int i;
1166 
1167 	*win = -1;
1168 	for (i = 0; i < PCIC_MEM_WINS; i++) {
1169 		if ((sc->memalloc & (1 << i)) == 0) {
1170 			*win = i;
1171 			sc->memalloc |= (1 << i);
1172 			break;
1173 		}
1174 	}
1175 	if (*win == -1)
1176 		return (1);
1177 
1178 	card_addr = card_addr - card_addr % PCIC_MEM_PAGESIZE;
1179 
1180 	sc->mem[*win].memt = rman_get_bustag(r);
1181 	sc->mem[*win].memh = rman_get_bushandle(r);
1182 	sc->mem[*win].addr = rman_get_start(r);
1183 	sc->mem[*win].size = rman_get_end(r) - sc->mem[*win].addr + 1;
1184 	sc->mem[*win].realsize = sc->mem[*win].size + PCIC_MEM_PAGESIZE - 1;
1185 	sc->mem[*win].realsize = sc->mem[*win].realsize -
1186 				 (sc->mem[*win].realsize % PCIC_MEM_PAGESIZE);
1187 	sc->mem[*win].offset = ((long)card_addr) -
1188 			       ((long)(sc->mem[*win].addr));
1189 	sc->mem[*win].kind = kind;
1190 
1191 	DPRINTF(("pccbb_pcic_mem_map window %d bus %x+%x+%lx card addr %x\n",
1192 		 *win, sc->mem[*win].addr, sc->mem[*win].size,
1193 		 sc->mem[*win].offset, card_addr));
1194 
1195 	pccbb_pcic_do_mem_map(sc, *win);
1196 
1197 	return (0);
1198 }
1199 
1200 static void
1201 pccbb_pcic_mem_unmap(struct pccbb_softc *sc, int window)
1202 {
1203 	if (window >= PCIC_MEM_WINS)
1204 		panic("pccbb_pcic_mem_unmap: window out of range");
1205 
1206 	PCIC_MASK(sc, PCIC_ADDRWIN_ENABLE, & ~mem_map_index[window].memenable);
1207 
1208 	sc->memalloc &= ~(1 << window);
1209 }
1210 
1211 #define PCIC_IOINFO(NUM) { \
1212 	PCIC_IOADDR ## NUM ## _START_LSB, \
1213 	PCIC_IOADDR ## NUM ## _START_MSB, \
1214 	PCIC_IOADDR ## NUM ## _STOP_LSB, \
1215 	PCIC_IOADDR ## NUM ## _STOP_MSB, \
1216 	PCIC_ADDRWIN_ENABLE_IO ## NUM ## , \
1217 	PCIC_IOCTL_IO ## NUM ## _WAITSTATE \
1218 	| PCIC_IOCTL_IO ## NUM ## _ZEROWAIT \
1219 	| PCIC_IOCTL_IO ## NUM ## _IOCS16SRC_MASK \
1220 	| PCIC_IOCTL_IO ## NUM ## _DATASIZE_MASK, \
1221 	{ \
1222 		PCIC_IOCTL_IO ## NUM ## _IOCS16SRC_CARD, \
1223 		PCIC_IOCTL_IO ## NUM ## _IOCS16SRC_DATASIZE \
1224 		| PCIC_IOCTL_IO ## NUM ## _DATASIZE_8BIT, \
1225 		PCIC_IOCTL_IO ## NUM ## _IOCS16SRC_DATASIZE \
1226 		| PCIC_IOCTL_IO ## NUM ## _DATASIZE_16BIT, \
1227 	} \
1228 }
1229 
1230 static struct io_map_index_st {
1231 	int start_lsb;
1232 	int start_msb;
1233 	int stop_lsb;
1234 	int stop_msb;
1235 	int ioenable;
1236 	int ioctlmask;
1237 	int ioctlbits[3]; /* indexed by PCCARD_WIDTH_* */
1238 } io_map_index[] = {
1239 	PCIC_IOINFO(0),
1240 	PCIC_IOINFO(1),
1241 };
1242 #undef PCIC_IOINFO
1243 
1244 static void pccbb_pcic_do_io_map(struct pccbb_softc *sc, int win)
1245 {
1246 	PCIC_WRITE(sc, io_map_index[win].start_lsb, sc->io[win].addr & 0xff);
1247 	PCIC_WRITE(sc, io_map_index[win].start_msb,
1248 		   (sc->io[win].addr >> 8) & 0xff);
1249 
1250 	PCIC_WRITE(sc, io_map_index[win].stop_lsb,
1251 		   (sc->io[win].addr + sc->io[win].size - 1) & 0xff);
1252 	PCIC_WRITE(sc, io_map_index[win].stop_msb,
1253 		   ((sc->io[win].addr + sc->io[win].size - 1) >> 8) & 0xff);
1254 
1255 	PCIC_MASK2(sc, PCIC_IOCTL,
1256 		   & ~io_map_index[win].ioctlmask,
1257 		   | io_map_index[win].ioctlbits[sc->io[win].width]);
1258 
1259 	PCIC_MASK(sc, PCIC_ADDRWIN_ENABLE, | io_map_index[win].ioenable);
1260 }
1261 
1262 static int
1263 pccbb_pcic_io_map(struct pccbb_softc *sc, int width,
1264 		  struct resource *r, bus_addr_t card_addr, int *win)
1265 {
1266 	int i;
1267 #ifdef CBB_DEBUG
1268 	static char *width_names[] = { "auto", "io8", "io16"};
1269 #endif
1270 
1271 	*win = -1;
1272 	for (i=0; i < PCIC_IO_WINS; i++) {
1273 		if ((sc->ioalloc & (1 << i)) == 0) {
1274 			*win = i;
1275 			sc->ioalloc |= (1 << i);
1276 			break;
1277 		}
1278 	}
1279 	if (*win == -1)
1280 		return (1);
1281 
1282 	sc->io[*win].iot = rman_get_bustag(r);
1283 	sc->io[*win].ioh = rman_get_bushandle(r);
1284 	sc->io[*win].addr = rman_get_start(r);
1285 	sc->io[*win].size = rman_get_end(r) - sc->io[*win].addr + 1;
1286 	sc->io[*win].flags = 0;
1287 	sc->io[*win].width = width;
1288 
1289 	DPRINTF(("pccbb_pcic_io_map window %d %s port %x+%x\n",
1290 		 *win, width_names[width], sc->io[*win].addr,
1291 		 sc->io[*win].size));
1292 
1293 	pccbb_pcic_do_io_map(sc, *win);
1294 
1295 	return (0);
1296 }
1297 
1298 static void
1299 pccbb_pcic_io_unmap(struct pccbb_softc *sc, int window)
1300 {
1301 	if (window >= PCIC_IO_WINS)
1302 		panic("pccbb_pcic_io_unmap: window out of range");
1303 
1304 	PCIC_MASK(sc, PCIC_ADDRWIN_ENABLE, & ~io_map_index[window].ioenable);
1305 
1306 	sc->ioalloc &= ~(1 << window);
1307 
1308 	sc->io[window].iot = 0;
1309 	sc->io[window].ioh = 0;
1310 	sc->io[window].addr = 0;
1311 	sc->io[window].size = 0;
1312 	sc->io[window].flags = 0;
1313 	sc->io[window].width = 0;
1314 }
1315 
1316 static int
1317 pccbb_pcic_activate_resource(device_t self, device_t child, int type, int rid,
1318 			     struct resource *r)
1319 {
1320 	int err;
1321 	int win;
1322 	struct pccbb_reslist *rle;
1323 	struct pccbb_softc *sc = device_get_softc(self);
1324 
1325 	switch (type) {
1326 	case SYS_RES_IOPORT:
1327 		err = pccbb_pcic_io_map(sc, 0, r, 0, &win);
1328 		if (err)
1329 			return err;
1330 		break;
1331 	case SYS_RES_MEMORY:
1332 		err = pccbb_pcic_mem_map(sc, 0, r, 0, &win);
1333 		if (err)
1334 			return err;
1335 		break;
1336 	default:
1337 		break;
1338 	}
1339 	SLIST_FOREACH(rle, &sc->rl, entries) {
1340 		if (type == rle->type && rid == rle->rid &&
1341 		    child == rle->odev) {
1342 			rle->win = win;
1343 			break;
1344 		}
1345 	}
1346 	err = bus_generic_activate_resource(self, child, type, rid, r);
1347 	return (err);
1348 }
1349 
1350 static int
1351 pccbb_pcic_deactivate_resource(device_t self, device_t child, int type,
1352 			       int rid, struct resource *r)
1353 {
1354 	struct pccbb_softc *sc = device_get_softc(self);
1355 	int win;
1356 	struct pccbb_reslist *rle;
1357 
1358 	win = -1;
1359 	SLIST_FOREACH(rle, &sc->rl, entries) {
1360 		if (type == rle->type && rid == rle->rid &&
1361 		    child == rle->odev) {
1362 			win = rle->win;
1363 			break;
1364 		}
1365 	}
1366 	if (win == -1)
1367 		return 1;
1368 
1369 	switch (type) {
1370 	case SYS_RES_IOPORT:
1371 		pccbb_pcic_io_unmap(sc, win);
1372 		break;
1373 	case SYS_RES_MEMORY:
1374 		pccbb_pcic_mem_unmap(sc, win);
1375 		break;
1376 	default:
1377 		break;
1378 	}
1379 	return bus_generic_deactivate_resource(self, child, type, rid, r);
1380 }
1381 
1382 static struct resource*
1383 pccbb_pcic_alloc_resource(device_t self, device_t child, int type, int* rid,
1384 			  u_long start, u_long end, u_long count, u_int flags)
1385 {
1386 	struct resource *r = NULL;
1387 	struct pccbb_softc *sc = device_get_softc(self);
1388 	struct pccbb_reslist *rle;
1389 
1390 	switch (type) {
1391 	case SYS_RES_MEMORY:
1392 		/* Nearly default */
1393 		if (start == 0 && end == ~0 && count != 1) {
1394 			start = 0xd0000; /* XXX -- should be tweakable*/
1395 			end = 0xdffff;
1396 		}
1397 		flags = (flags & ~RF_ALIGNMENT_MASK)
1398 			| rman_make_alignment_flags(PCCBB_MEMALIGN);
1399 		break;
1400 	case SYS_RES_IOPORT:
1401 		if (start < 0x100)
1402 			start = 0x100;		/* XXX tweakable? */
1403 		if (end < start)
1404 			end = start;
1405 		break;
1406 	case SYS_RES_IRQ:
1407 		flags |= RF_SHAREABLE;
1408 		start = end = rman_get_start(sc->sc_irq_res);
1409 		break;
1410 	}
1411 	r = bus_generic_alloc_resource(self, child, type, rid, start, end,
1412 				       count, flags & ~RF_ACTIVE);
1413 	if (r == NULL)
1414 		return NULL;
1415 
1416 	rle = malloc(sizeof(struct pccbb_reslist), M_DEVBUF, M_WAITOK);
1417 	rle->type = type;
1418 	rle->rid = *rid;
1419 	rle->start = rman_get_start(r);
1420 	rle->end = rman_get_end(r);
1421 	rle->odev = child;
1422 	rle->win = -1;
1423 	SLIST_INSERT_HEAD(&sc->rl, rle, entries);
1424 
1425 	if (flags & RF_ACTIVE) {
1426 		if (bus_activate_resource(child, type, *rid, r) != 0) {
1427 			BUS_RELEASE_RESOURCE(self, child, type, *rid, r);
1428 			return NULL;
1429 		}
1430 	}
1431 
1432 	return r;
1433 }
1434 
1435 static int
1436 pccbb_pcic_release_resource(device_t self, device_t child, int type,
1437 			    int rid, struct resource *res)
1438 {
1439 	struct pccbb_softc *sc = device_get_softc(self);
1440 	struct pccbb_reslist *rle;
1441 
1442 	SLIST_FOREACH(rle, &sc->rl, entries) {
1443 		if (type == rle->type && rid == rle->rid &&
1444 		    child == rle->odev) {
1445 			SLIST_REMOVE(&sc->rl, rle, pccbb_reslist, entries);
1446 			free(rle, M_DEVBUF);
1447 			break;
1448 		}
1449 	}
1450 
1451 	return bus_generic_release_resource(self, child, type, rid, res);
1452 }
1453 
1454 /************************************************************************/
1455 /* PC Card methods							*/
1456 /************************************************************************/
1457 
1458 static int
1459 pccbb_pcic_set_res_flags(device_t self, device_t child, int type, int rid,
1460 			 u_int32_t flags)
1461 {
1462 	struct pccbb_softc *sc = device_get_softc(self);
1463 
1464 	if (type != SYS_RES_MEMORY)
1465 		return (EINVAL);
1466 	sc->mem[rid].kind = PCCARD_MEM_ATTR;
1467 	pccbb_pcic_do_mem_map(sc, rid);
1468 	return 0;
1469 }
1470 
1471 static int
1472 pccbb_pcic_set_memory_offset(device_t self, device_t child, int rid,
1473 			     u_int32_t offset)
1474 {
1475 	struct pccbb_softc *sc = device_get_softc(self);
1476 	int win;
1477 	struct pccbb_reslist *rle;
1478 
1479 	win = -1;
1480 	SLIST_FOREACH(rle, &sc->rl, entries) {
1481 		if (SYS_RES_MEMORY == rle->type && rid == rle->rid &&
1482 		    child == rle->odev) {
1483 			win = rle->win;
1484 			break;
1485 		}
1486 	}
1487 	if (win == -1)
1488 		return 1;
1489 
1490 	offset = offset - offset % PCIC_MEM_PAGESIZE;
1491 	sc->mem[win].offset = ((long)offset) -
1492 			      ((long)(sc->mem[win].addr));
1493 
1494 	pccbb_pcic_do_mem_map(sc, win);
1495 
1496 	return 0;
1497 }
1498 
1499 static int
1500 pccbb_pcic_enable_socket(device_t self, device_t child)
1501 {
1502 	struct pccbb_softc *sc = device_get_softc(self);
1503 
1504 	DPRINTF(("pccbb_pcic_socket_enable:\n"));
1505 
1506 	/* power down/up the socket to reset */
1507 	{
1508 		int voltage = pccbb_detect_voltage(sc);
1509 
1510 		pccbb_power(self, CARD_VCC_0V | CARD_VPP_0V);
1511 		if (voltage & CARD_5V_CARD)
1512 			pccbb_power(self, CARD_VCC_5V | CARD_VPP_VCC);
1513 		else if (voltage & CARD_3V_CARD)
1514 			pccbb_power(self, CARD_VCC_3V | CARD_VPP_VCC);
1515 		else {
1516 			device_printf(self, "Unknown card voltage\n");
1517 			return ENXIO;
1518 		}
1519 	}
1520 
1521 	/* enable socket i/o */
1522 	PCIC_MASK(sc, PCIC_PWRCTL, | PCIC_PWRCTL_OE);
1523 
1524 	PCIC_WRITE(sc, PCIC_INTR, PCIC_INTR_ENABLE);
1525 	/* hold reset for 30ms */
1526 	DELAY(30*1000);
1527 	/* clear the reset flag */
1528 	PCIC_MASK(sc, PCIC_INTR, | PCIC_INTR_RESET);
1529 	/* wait 20ms as per pc card standard (r2.01) section 4.3.6 */
1530 	DELAY(20*1000);
1531 
1532 	pccbb_pcic_wait_ready(sc);
1533 
1534 	/* disable all address windows */
1535 	PCIC_WRITE(sc, PCIC_ADDRWIN_ENABLE, 0);
1536 
1537 	{
1538 		int cardtype;
1539 		CARD_GET_TYPE(child, &cardtype);
1540 		PCIC_MASK(sc, PCIC_INTR, | ((cardtype == PCCARD_IFTYPE_IO) ?
1541 					    PCIC_INTR_CARDTYPE_IO :
1542 					    PCIC_INTR_CARDTYPE_MEM));
1543 		DEVPRINTF((sc->sc_dev, "card type is %s\n",
1544 			   (cardtype == PCCARD_IFTYPE_IO) ? "io" : "mem"));
1545 	}
1546 
1547 	/* reinstall all the memory and io mappings */
1548 	{
1549 		int win;
1550 
1551 		for (win = 0; win < PCIC_MEM_WINS; ++win) {
1552 			if (sc->memalloc & (1 << win)) {
1553 				pccbb_pcic_do_mem_map(sc, win);
1554 			}
1555 		}
1556 		for (win = 0; win < PCIC_IO_WINS; ++win) {
1557 			if (sc->ioalloc & (1 << win)) {
1558 				pccbb_pcic_do_io_map(sc, win);
1559 			}
1560 		}
1561 	}
1562 	return 0;
1563 }
1564 
1565 static void
1566 pccbb_pcic_disable_socket(device_t self, device_t child)
1567 {
1568 	struct pccbb_softc *sc = device_get_softc(self);
1569 
1570 	DPRINTF(("pccbb_pcic_socket_disable\n"));
1571 
1572 	/* reset signal asserting... */
1573 	PCIC_MASK(sc, PCIC_INTR, & ~PCIC_INTR_RESET);
1574 	DELAY(2*1000);
1575 
1576 	/* power down the socket */
1577 	PCIC_MASK(sc, PCIC_PWRCTL, &~PCIC_PWRCTL_OE);
1578 	pccbb_power(self, CARD_VCC_0V | CARD_VPP_0V);
1579 
1580 	/* wait 300ms until power fails (Tpf). */
1581 	DELAY(300 * 1000);
1582 }
1583 
1584 /************************************************************************/
1585 /* Methods								*/
1586 /************************************************************************/
1587 
1588 
1589 static int
1590 pccbb_activate_resource(device_t self, device_t child, int type, int rid,
1591 			struct resource *r)
1592 {
1593 	struct pccbb_softc *sc = device_get_softc(self);
1594 
1595 	if (sc->sc_flags & PCCBB_16BIT_CARD)
1596 		return pccbb_pcic_activate_resource(self, child, type, rid, r);
1597 	else
1598 		return pccbb_cardbus_activate_resource(self, child, type, rid,
1599 						       r);
1600 }
1601 
1602 static int
1603 pccbb_deactivate_resource(device_t self, device_t child, int type,
1604 			  int rid, struct resource *r)
1605 {
1606 	struct pccbb_softc *sc = device_get_softc(self);
1607 
1608 	if (sc->sc_flags & PCCBB_16BIT_CARD)
1609 		return pccbb_pcic_deactivate_resource(self, child, type,
1610 						      rid, r);
1611 	else
1612 		return pccbb_cardbus_deactivate_resource(self, child, type,
1613 						      rid, r);
1614 }
1615 
1616 static struct resource*
1617 pccbb_alloc_resource(device_t self, device_t child, int type, int* rid,
1618 		     u_long start, u_long end, u_long count, u_int flags)
1619 {
1620 	struct pccbb_softc *sc = device_get_softc(self);
1621 
1622 	if (sc->sc_flags & PCCBB_16BIT_CARD)
1623 		return pccbb_pcic_alloc_resource(self, child, type, rid,
1624 						 start, end, count, flags);
1625 	else
1626 		return pccbb_cardbus_alloc_resource(self, child, type, rid,
1627 						 start, end, count, flags);
1628 }
1629 
1630 static int
1631 pccbb_release_resource(device_t self, device_t child, int type, int rid,
1632 		       struct resource *r)
1633 {
1634 	struct pccbb_softc *sc = device_get_softc(self);
1635 
1636 	if (sc->sc_flags & PCCBB_16BIT_CARD)
1637 		return pccbb_pcic_release_resource(self, child, type,
1638 						   rid, r);
1639 	else
1640 		return pccbb_cardbus_release_resource(self, child, type,
1641 						      rid, r);
1642 }
1643 
1644 static int
1645 pccbb_maxslots(device_t dev)
1646 {
1647 	return 0;
1648 }
1649 
1650 static u_int32_t
1651 pccbb_read_config(device_t dev, int b, int s, int f,
1652 		 int reg, int width)
1653 {
1654 	/*
1655 	 * Pass through to the next ppb up the chain (i.e. our grandparent).
1656 	 */
1657 	return PCIB_READ_CONFIG(device_get_parent(device_get_parent(dev)),
1658 				b, s, f, reg, width);
1659 }
1660 
1661 static void
1662 pccbb_write_config(device_t dev, int b, int s, int f,
1663 		  int reg, u_int32_t val, int width)
1664 {
1665 	/*
1666 	 * Pass through to the next ppb up the chain (i.e. our grandparent).
1667 	 */
1668 	PCIB_WRITE_CONFIG(device_get_parent(device_get_parent(dev)),
1669 			  b, s, f, reg, val, width);
1670 }
1671 
1672 static device_method_t pccbb_methods[] = {
1673 	/* Device interface */
1674 	DEVMETHOD(device_probe,			pccbb_probe),
1675 	DEVMETHOD(device_attach,		pccbb_attach),
1676 	DEVMETHOD(device_detach,		bus_generic_detach),
1677 	DEVMETHOD(device_shutdown,		bus_generic_shutdown),
1678 	DEVMETHOD(device_suspend,		bus_generic_suspend),
1679 	DEVMETHOD(device_resume,		bus_generic_resume),
1680 
1681 	/* bus methods */
1682 	DEVMETHOD(bus_print_child,		bus_generic_print_child),
1683 	DEVMETHOD(bus_alloc_resource,		pccbb_alloc_resource),
1684 	DEVMETHOD(bus_release_resource,		pccbb_release_resource),
1685 	DEVMETHOD(bus_activate_resource,	pccbb_activate_resource),
1686 	DEVMETHOD(bus_deactivate_resource,	pccbb_deactivate_resource),
1687 	DEVMETHOD(bus_setup_intr,		bus_generic_setup_intr),
1688 	DEVMETHOD(bus_teardown_intr,		bus_generic_teardown_intr),
1689 
1690         /* pcib compatibility interface */
1691 	DEVMETHOD(pcib_maxslots,		pccbb_maxslots),
1692 	DEVMETHOD(pcib_read_config,		pccbb_read_config),
1693 	DEVMETHOD(pcib_write_config,		pccbb_write_config),
1694 
1695 	DEVMETHOD(pccbb_power_socket,		pccbb_power),
1696 	DEVMETHOD(pccbb_detect_card,		pccbb_cardbus_detect_card),
1697 	DEVMETHOD(pccbb_reset,			pccbb_cardbus_reset),
1698 
1699 	DEVMETHOD(card_set_res_flags,		pccbb_pcic_set_res_flags),
1700 	DEVMETHOD(card_set_memory_offset,	pccbb_pcic_set_memory_offset),
1701 
1702 	DEVMETHOD(power_enable_socket,		pccbb_pcic_enable_socket),
1703 	DEVMETHOD(power_disable_socket,		pccbb_pcic_disable_socket),
1704 
1705 	{0,0}
1706 };
1707 
1708 static driver_t pccbb_driver = {
1709 	"pccbb",
1710 	pccbb_methods,
1711 	sizeof(struct pccbb_softc)
1712 };
1713 static devclass_t pccbb_devclass = {
1714 };
1715 DRIVER_MODULE(pccbb, pci, pccbb_driver, pccbb_devclass, 0, 0);
1716 
1717 
1718 SYSINIT(pccbb, SI_SUB_KTHREAD_IDLE, SI_ORDER_ANY, pccbb_start_threads, 0);
1719