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