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