cb0d2d4e1518dad13eb343d2ead9ec298b6f626f
[dragonfly.git] / sys / dev / pccard / pccbb / pccbb.c
1 /*-
2  * Copyright (c) 2002-2004 M. Warner Losh.
3  * Copyright (c) 2000-2001 Jonathan Chen.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  * $FreeBSD: src/sys/dev/pccbb/pccbb.c,v 1.126 2005/07/17 19:40:05 imp Exp $
28  * $DragonFly: src/sys/dev/pccard/pccbb/pccbb.c,v 1.21 2007/07/05 12:08:54 sephe Exp $
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  * and PCI to PCMCIA Bridge chips
64  * and ISA to PCMCIA host adapters
65  * and C Bus to PCMCIA host adapters
66  *
67  * References:
68  *  TI Datasheets:
69  *   http://www-s.ti.com/cgi-bin/sc/generic2.cgi?family=PCI+CARDBUS+CONTROLLERS
70  *
71  * Written by Jonathan Chen <jon@freebsd.org>
72  * The author would like to acknowledge:
73  *  * HAYAKAWA Koichi: Author of the NetBSD code for the same thing
74  *  * Warner Losh: Newbus/newcard guru and author of the pccard side of things
75  *  * YAMAMOTO Shigeru: Author of another FreeBSD cardbus driver
76  *  * David Cross: Author of the initial ugly hack for a specific cardbus card
77  */
78
79 #include <sys/param.h>
80 #include <sys/bus.h>
81 #include <sys/errno.h>
82 #include <sys/interrupt.h>
83 #include <sys/kernel.h>
84 #include <sys/module.h>
85 #include <sys/kthread.h>
86 #include <sys/lock.h>
87 #include <sys/malloc.h>
88 #include <sys/proc.h>
89 #include <sys/rman.h>
90 #include <sys/sysctl.h>
91 #include <sys/systm.h>
92
93 #include <sys/thread2.h>
94 #include <sys/mplock2.h>
95
96 #include <bus/pci/pcireg.h>
97 #include <bus/pci/pcivar.h>
98 #include <machine/clock.h>
99
100 #include <bus/pccard/pccardreg.h>
101 #include <bus/pccard/pccardvar.h>
102
103 #include <dev/pccard/exca/excareg.h>
104 #include <dev/pccard/exca/excavar.h>
105
106 #include <dev/pccard/pccbb/pccbbreg.h>
107 #include <dev/pccard/pccbb/pccbbvar.h>
108
109 #include "power_if.h"
110 #include "card_if.h"
111 #include "pcib_if.h"
112
113 #define DPRINTF(x) do { if (cbb_debug) kprintf x; } while (0)
114 #define DEVPRINTF(x) do { if (cbb_debug) device_printf x; } while (0)
115
116 #define PCI_MASK_CONFIG(DEV,REG,MASK,SIZE)                              \
117         pci_write_config(DEV, REG, pci_read_config(DEV, REG, SIZE) MASK, SIZE)
118 #define PCI_MASK2_CONFIG(DEV,REG,MASK1,MASK2,SIZE)                      \
119         pci_write_config(DEV, REG, (                                    \
120                 pci_read_config(DEV, REG, SIZE) MASK1) MASK2, SIZE)
121
122 #define CBB_CARD_PRESENT(s) ((s & CBB_STATE_CD) == 0)
123
124 #define CBB_START_MEM   0x88000000
125 #define CBB_START_32_IO 0x1000
126 #define CBB_START_16_IO 0x100
127
128 devclass_t cbb_devclass;
129
130 /* sysctl vars */
131 SYSCTL_NODE(_hw, OID_AUTO, cbb, CTLFLAG_RD, 0, "CBB parameters");
132
133 /* There's no way to say TUNEABLE_LONG to get the right types */
134 u_long cbb_start_mem = CBB_START_MEM;
135 TUNABLE_INT("hw.cbb.start_memory", (int *)&cbb_start_mem);
136 SYSCTL_ULONG(_hw_cbb, OID_AUTO, start_memory, CTLFLAG_RW,
137     &cbb_start_mem, CBB_START_MEM,
138     "Starting address for memory allocations");
139
140 u_long cbb_start_16_io = CBB_START_16_IO;
141 TUNABLE_INT("hw.cbb.start_16_io", (int *)&cbb_start_16_io);
142 SYSCTL_ULONG(_hw_cbb, OID_AUTO, start_16_io, CTLFLAG_RW,
143     &cbb_start_16_io, CBB_START_16_IO,
144     "Starting ioport for 16-bit cards");
145
146 u_long cbb_start_32_io = CBB_START_32_IO;
147 TUNABLE_INT("hw.cbb.start_32_io", (int *)&cbb_start_32_io);
148 SYSCTL_ULONG(_hw_cbb, OID_AUTO, start_32_io, CTLFLAG_RW,
149     &cbb_start_32_io, CBB_START_32_IO,
150     "Starting ioport for 32-bit cards");
151
152 int cbb_debug = 0;
153 TUNABLE_INT("hw.cbb.debug", &cbb_debug);
154 SYSCTL_ULONG(_hw_cbb, OID_AUTO, debug, CTLFLAG_RW, &cbb_debug, 0,
155     "Verbose cardbus bridge debugging");
156
157 static void     cbb_insert(struct cbb_softc *sc);
158 static void     cbb_removal(struct cbb_softc *sc);
159 static uint32_t cbb_detect_voltage(device_t brdev);
160 static void     cbb_cardbus_reset(device_t brdev);
161 static int      cbb_cardbus_io_open(device_t brdev, int win, uint32_t start,
162                     uint32_t end);
163 static int      cbb_cardbus_mem_open(device_t brdev, int win,
164                     uint32_t start, uint32_t end);
165 static void     cbb_cardbus_auto_open(struct cbb_softc *sc, int type);
166 static int      cbb_cardbus_activate_resource(device_t brdev, device_t child,
167                     int type, int rid, struct resource *res);
168 static int      cbb_cardbus_deactivate_resource(device_t brdev,
169                     device_t child, int type, int rid, struct resource *res);
170 static struct resource  *cbb_cardbus_alloc_resource(device_t brdev,
171                     device_t child, int type, int *rid, u_long start,
172                     u_long end, u_long count, u_int flags);
173 static int      cbb_cardbus_release_resource(device_t brdev, device_t child,
174                     int type, int rid, struct resource *res);
175 static int      cbb_cardbus_power_enable_socket(device_t brdev,
176                     device_t child);
177 static void     cbb_cardbus_power_disable_socket(device_t brdev,
178                     device_t child);
179 static void     cbb_func_intr(void *arg);
180
181 static void
182 cbb_remove_res(struct cbb_softc *sc, struct resource *res)
183 {
184         struct cbb_reslist *rle;
185
186         SLIST_FOREACH(rle, &sc->rl, link) {
187                 if (rle->res == res) {
188                         SLIST_REMOVE(&sc->rl, rle, cbb_reslist, link);
189                         kfree(rle, M_DEVBUF);
190                         return;
191                 }
192         }
193 }
194
195 static struct resource *
196 cbb_find_res(struct cbb_softc *sc, int type, int rid)
197 {
198         struct cbb_reslist *rle;
199         
200         SLIST_FOREACH(rle, &sc->rl, link)
201                 if (SYS_RES_MEMORY == rle->type && rid == rle->rid)
202                         return (rle->res);
203         return (NULL);
204 }
205
206 static void
207 cbb_insert_res(struct cbb_softc *sc, struct resource *res, int type,
208     int rid)
209 {
210         struct cbb_reslist *rle;
211
212         /*
213          * Need to record allocated resource so we can iterate through
214          * it later.
215          */
216         rle = kmalloc(sizeof(struct cbb_reslist), M_DEVBUF, M_NOWAIT);
217         if (rle == NULL)
218                 panic("cbb_cardbus_alloc_resource: can't record entry!");
219         rle->res = res;
220         rle->type = type;
221         rle->rid = rid;
222         SLIST_INSERT_HEAD(&sc->rl, rle, link);
223 }
224
225 static void
226 cbb_destroy_res(struct cbb_softc *sc)
227 {
228         struct cbb_reslist *rle;
229
230         while ((rle = SLIST_FIRST(&sc->rl)) != NULL) {
231                 device_printf(sc->dev, "Danger Will Robinson: Resource "
232                     "left allocated!  This is a bug... "
233                     "(rid=%x, type=%d, addr=%lx)\n", rle->rid, rle->type,
234                     rman_get_start(rle->res));
235                 SLIST_REMOVE_HEAD(&sc->rl, link);
236                 kfree(rle, M_DEVBUF);
237         }
238 }
239
240 /*
241  * Disable function interrupts by telling the bridge to generate IRQ1
242  * interrupts.  These interrupts aren't really generated by the chip, since
243  * IRQ1 is reserved.  Some chipsets assert INTA# inappropriately during
244  * initialization, so this helps to work around the problem.
245  *
246  * XXX We can't do this workaround for all chipsets, because this
247  * XXX causes interference with the keyboard because somechipsets will
248  * XXX actually signal IRQ1 over their serial interrupt connections to
249  * XXX the south bridge.  Disable it it for now.
250  */
251 void
252 cbb_disable_func_intr(struct cbb_softc *sc)
253 {
254 #if 0
255         uint8_t reg;
256         reg = (exca_getb(&sc->exca[0], EXCA_INTR) & ~EXCA_INTR_IRQ_MASK) | 
257             EXCA_INTR_IRQ_RESERVED1;
258         exca_putb(&sc->exca[0], EXCA_INTR, reg);
259 #endif
260 }
261
262 /*
263  * Enable function interrupts.  We turn on function interrupts when the card
264  * requests an interrupt.  The PCMCIA standard says that we should set
265  * the lower 4 bits to 0 to route via PCI.  Note: we call this for both
266  * CardBus and R2 (PC Card) cases, but it should have no effect on CardBus
267  * cards.
268  */
269 static void
270 cbb_enable_func_intr(struct cbb_softc *sc)
271 {
272         uint8_t reg;
273
274         reg = (exca_getb(&sc->exca[0], EXCA_INTR) & ~EXCA_INTR_IRQ_MASK) | 
275             EXCA_INTR_IRQ_NONE;
276         exca_putb(&sc->exca[0], EXCA_INTR, reg);
277 }
278
279 int
280 cbb_detach(device_t brdev)
281 {
282         struct cbb_softc *sc = device_get_softc(brdev);
283         int numdevs;
284         device_t *devlist;
285         int tmp;
286         int error;
287
288         device_get_children(brdev, &devlist, &numdevs);
289
290         error = 0;
291         for (tmp = 0; tmp < numdevs; tmp++) {
292                 if (device_detach(devlist[tmp]) == 0)
293                         device_delete_child(brdev, devlist[tmp]);
294                 else
295                         error++;
296         }
297         kfree(devlist, M_TEMP);
298         if (error > 0)
299                 return (ENXIO);
300
301         /* 
302          * XXX do we teardown all the ones still registered to guard against
303          * XXX buggy client drivers?
304          */
305         bus_teardown_intr(brdev, sc->irq_res, sc->intrhand);
306         sc->flags |= CBB_KTHREAD_DONE;
307         if (sc->flags & CBB_KTHREAD_RUNNING) {
308                 crit_enter();
309                 wakeup(&sc->generic_cv);
310                 tsleep(sc->event_thread, 0, "cbbun", 0);
311                 crit_exit();
312         }
313
314         bus_release_resource(brdev, SYS_RES_IRQ, 0, sc->irq_res);
315         bus_release_resource(brdev, SYS_RES_MEMORY, CBBR_SOCKBASE,
316             sc->base_res);
317         return (0);
318 }
319
320 int
321 cbb_shutdown(device_t brdev)
322 {
323         struct cbb_softc *sc = (struct cbb_softc *)device_get_softc(brdev);
324         /* properly reset everything at shutdown */
325
326         PCI_MASK_CONFIG(brdev, CBBR_BRIDGECTRL, |CBBM_BRIDGECTRL_RESET, 2);
327         exca_clrb(&sc->exca[0], EXCA_INTR, EXCA_INTR_RESET);
328
329         cbb_set(sc, CBB_SOCKET_MASK, 0);
330
331         cbb_power(brdev, CARD_OFF);
332
333         exca_putb(&sc->exca[0], EXCA_ADDRWIN_ENABLE, 0);
334         pci_write_config(brdev, CBBR_MEMBASE0, 0, 4);
335         pci_write_config(brdev, CBBR_MEMLIMIT0, 0, 4);
336         pci_write_config(brdev, CBBR_MEMBASE1, 0, 4);
337         pci_write_config(brdev, CBBR_MEMLIMIT1, 0, 4);
338         pci_write_config(brdev, CBBR_IOBASE0, 0, 4);
339         pci_write_config(brdev, CBBR_IOLIMIT0, 0, 4);
340         pci_write_config(brdev, CBBR_IOBASE1, 0, 4);
341         pci_write_config(brdev, CBBR_IOLIMIT1, 0, 4);
342         pci_write_config(brdev, PCIR_COMMAND, 0, 2);
343         return (0);
344 }
345
346 int
347 cbb_setup_intr(device_t dev, device_t child, struct resource *irq,
348                int flags, driver_intr_t *intr, void *arg,
349                void **cookiep, lwkt_serialize_t serializer)
350 {
351         struct cbb_intrhand *ih;
352         struct cbb_softc *sc = device_get_softc(dev);
353         int err;
354
355         ih = kmalloc(sizeof(struct cbb_intrhand), M_DEVBUF, M_NOWAIT);
356         if (ih == NULL)
357                 return (ENOMEM);
358         *cookiep = ih;
359         ih->intr = intr;
360         ih->arg = arg;
361         ih->sc = sc;
362         ih->serializer = serializer;
363         /*
364          * XXX need to turn on ISA interrupts, if we ever support them, but
365          * XXX for now that's all we need to do.
366          */
367         err = BUS_SETUP_INTR(device_get_parent(dev), child, irq, flags,
368             cbb_func_intr, ih, &ih->cookie, NULL);
369         if (err != 0) {
370                 kfree(ih, M_DEVBUF);
371                 return (err);
372         }
373         cbb_enable_func_intr(sc);
374         sc->flags |= CBB_CARD_OK;
375         return 0;
376 }
377
378 int
379 cbb_teardown_intr(device_t dev, device_t child, struct resource *irq,
380     void *cookie)
381 {
382         struct cbb_intrhand *ih;
383         int err;
384
385         /* XXX Need to do different things for ISA interrupts. */
386         ih = (struct cbb_intrhand *) cookie;
387         err = BUS_TEARDOWN_INTR(device_get_parent(dev), child, irq,
388             ih->cookie);
389         if (err != 0)
390                 return (err);
391         kfree(ih, M_DEVBUF);
392         return (0);
393 }
394
395
396 void
397 cbb_driver_added(device_t brdev, driver_t *driver)
398 {
399         struct cbb_softc *sc = device_get_softc(brdev);
400         device_t *devlist;
401         device_t dev;
402         int tmp;
403         int numdevs;
404         int wake = 0;
405
406         DEVICE_IDENTIFY(driver, brdev);
407         device_get_children(brdev, &devlist, &numdevs);
408         for (tmp = 0; tmp < numdevs; tmp++) {
409                 dev = devlist[tmp];
410                 if (device_get_state(dev) == DS_NOTPRESENT &&
411                     device_probe_and_attach(dev) == 0)
412                         wake++;
413         }
414         kfree(devlist, M_TEMP);
415
416         if (wake > 0)
417                 wakeup_one(&sc->generic_cv);
418 }
419
420 void
421 cbb_child_detached(device_t brdev, device_t child)
422 {
423         struct cbb_softc *sc = device_get_softc(brdev);
424
425         if (child != sc->cbdev && child != sc->exca[0].pccarddev)
426                 device_printf(brdev, "Unknown child detached: %s\n",
427                     device_get_nameunit(child));
428 }
429
430 /************************************************************************/
431 /* Kthreads                                                             */
432 /************************************************************************/
433
434 void
435 cbb_event_thread(void *arg)
436 {
437         struct cbb_softc *sc = arg;
438         uint32_t status;
439         int err;
440         int not_a_card = 0;
441
442         get_mplock();
443         sc->flags |= CBB_KTHREAD_RUNNING;
444         while ((sc->flags & CBB_KTHREAD_DONE) == 0) {
445                 /*
446                  * We take out Giant here because we need it deep,
447                  * down in the bowels of the vm system for mapping the
448                  * memory we need to read the CIS.  In addition, since
449                  * we are adding/deleting devices from the dev tree,
450                  * and that code isn't MP safe, we have to hold Giant.
451                  */
452                 status = cbb_get(sc, CBB_SOCKET_STATE);
453                 DPRINTF(("Status is 0x%x\n", status));
454                 if (!CBB_CARD_PRESENT(status)) {
455                         not_a_card = 0;         /* We know card type */
456                         cbb_removal(sc);
457                 } else if (status & CBB_STATE_NOT_A_CARD) {
458                         /*
459                          * Up to 20 times, try to rescan the card when we
460                          * see NOT_A_CARD.
461                          */
462                         if (not_a_card++ < 20) {
463                                 DEVPRINTF((sc->dev,
464                                     "Not a card bit set, rescanning\n"));
465                                 cbb_setb(sc, CBB_SOCKET_FORCE, CBB_FORCE_CV_TEST);
466                         } else {
467                                 device_printf(sc->dev,
468                                     "Can't determine card type\n");
469                         }
470                 } else {
471                         not_a_card = 0;         /* We know card type */
472                         cbb_insert(sc);
473                 }
474
475                 /*
476                  * Wait until it has been 1s since the last time we
477                  * get an interrupt.  We handle the rest of the interrupt
478                  * at the top of the loop.  Although we clear the bit in the
479                  * ISR, we signal sc->generic_cv from the detach path after
480                  * we've set the CBB_KTHREAD_DONE bit, so we can't do a simple
481                  * 1s sleep here.
482                  *
483                  * In our ISR, we turn off the card changed interrupt.  Turn
484                  * them back on here before we wait for them to happen.  We
485                  * turn them on/off so that we can tolerate a large latency
486                  * between the time we signal cbb_event_thread and it gets
487                  * a chance to run.
488                  */
489                 crit_enter();
490                 cbb_setb(sc, CBB_SOCKET_MASK, CBB_SOCKET_MASK_CD);
491                 tsleep(&sc->generic_cv, 0, "cbbgcv", 0);
492                 err = 0;
493                 while (err != EWOULDBLOCK &&
494                     (sc->flags & CBB_KTHREAD_DONE) == 0)
495                         err = tsleep(&sc->generic_cv, 0, "cbbgcv", hz);
496                 crit_exit();
497         }
498         sc->flags &= ~CBB_KTHREAD_RUNNING;
499         wakeup(sc->event_thread);
500         rel_mplock();
501 }
502
503 /************************************************************************/
504 /* Insert/removal                                                       */
505 /************************************************************************/
506
507 static void
508 cbb_insert(struct cbb_softc *sc)
509 {
510         uint32_t sockevent, sockstate;
511
512         sockevent = cbb_get(sc, CBB_SOCKET_EVENT);
513         sockstate = cbb_get(sc, CBB_SOCKET_STATE);
514
515         DEVPRINTF((sc->dev, "card inserted: event=0x%08x, state=%08x\n",
516             sockevent, sockstate));
517
518         if (sockstate & CBB_STATE_R2_CARD) {
519                 if (sc->exca[0].pccarddev) {
520                         sc->flags |= CBB_16BIT_CARD;
521                         exca_insert(&sc->exca[0]);
522                 } else {
523                         device_printf(sc->dev,
524                             "16-bit card inserted, but no pccard bus.\n");
525                 }
526         } else if (sockstate & CBB_STATE_CB_CARD) {
527                 if (sc->cbdev != NULL) {
528                         sc->flags &= ~CBB_16BIT_CARD;
529                         CARD_ATTACH_CARD(sc->cbdev);
530                 } else {
531                         device_printf(sc->dev,
532                             "CardBus card inserted, but no cardbus bus.\n");
533                 }
534         } else {
535                 /*
536                  * We should power the card down, and try again a couple of
537                  * times if this happens. XXX
538                  */
539                 device_printf(sc->dev, "Unsupported card type detected\n");
540         }
541 }
542
543 static void
544 cbb_removal(struct cbb_softc *sc)
545 {
546         sc->flags &= ~CBB_CARD_OK;
547         if (sc->flags & CBB_16BIT_CARD) {
548                 exca_removal(&sc->exca[0]);
549         } else {
550                 if (sc->cbdev != NULL)
551                         CARD_DETACH_CARD(sc->cbdev);
552         }
553         cbb_destroy_res(sc);
554 }
555
556 /************************************************************************/
557 /* Interrupt Handler                                                    */
558 /************************************************************************/
559
560 /*
561  * Since we touch hardware in the worst case, we don't need to use atomic
562  * ops on the CARD_OK tests.  They would save us a trip to the hardware
563  * if CARD_OK was recently cleared and the caches haven't updated yet.
564  * However, an atomic op costs between 100-200 CPU cycles.  On a 3GHz
565  * machine, this is about 33-66ns, whereas a trip the the hardware
566  * is about that.  On slower machines, the cost is even higher, so the
567  * trip to the hardware is cheaper and achieves the same ends that
568  * a fully locked operation would give us.
569  *
570  * This is a separate routine because we'd have to use locking and/or
571  * other synchronization in cbb_intr to do this there.  That would be
572  * even more expensive.
573  *
574  * I need to investigate what this means for a SMP machine with multiple
575  * CPUs servicing the ISR when an eject happens.  In the case of a dirty
576  * eject, CD glitches and we might read 'card present' from the hardware
577  * due to this jitter.  If we assumed that cbb_intr() ran before
578  * cbb_func_intr(), we could just check the SOCKET_MASK register and if
579  * CD changes were clear there, then we'd know the card was gone.
580  */
581 static void
582 cbb_func_intr(void *arg)
583 {
584         struct cbb_intrhand *ih = arg;
585         struct cbb_softc *sc = ih->sc;
586
587         /*
588          * Make sure that the card is really there.
589          */
590         if ((sc->flags & CBB_CARD_OK) == 0)
591                 return;
592         if (!CBB_CARD_PRESENT(cbb_get(sc, CBB_SOCKET_STATE))) {
593                 sc->flags &= ~CBB_CARD_OK;
594                 return;
595         }
596
597         /*
598          * nb: don't have to check for giant or not, since that's done
599          * in the ISR dispatch
600          */
601         if (ih->serializer) {
602                 lwkt_serialize_handler_call(ih->serializer,
603                         (inthand2_t *)ih->intr, ih->arg, NULL);
604         } else {
605                 (*ih->intr)(ih->arg);
606         }
607 }
608
609 void
610 cbb_intr(void *arg)
611 {
612         struct cbb_softc *sc = arg;
613         uint32_t sockevent;
614
615         sockevent = cbb_get(sc, CBB_SOCKET_EVENT);
616         if (sockevent != 0) {
617                 /* ack the interrupt */
618                 cbb_set(sc, CBB_SOCKET_EVENT, sockevent);
619
620                 /*
621                  * If anything has happened to the socket, we assume that
622                  * the card is no longer OK, and we shouldn't call its
623                  * ISR.  We set CARD_OK as soon as we've attached the
624                  * card.  This helps in a noisy eject, which happens
625                  * all too often when users are ejecting their PC Cards.
626                  *
627                  * We use this method in preference to checking to see if
628                  * the card is still there because the check suffers from
629                  * a race condition in the bouncing case.  Prior versions
630                  * of the pccard software used a similar trick and achieved
631                  * excellent results.
632                  */
633                 if (sockevent & CBB_SOCKET_EVENT_CD) {
634                         crit_enter();
635                         cbb_clrb(sc, CBB_SOCKET_MASK, CBB_SOCKET_MASK_CD);
636                         sc->flags &= ~CBB_CARD_OK;
637                         cbb_disable_func_intr(sc);
638                         wakeup_one(&sc->generic_cv);
639                         crit_exit();
640                 }
641                 /*
642                  * If we get a power interrupt, wakeup anybody that might
643                  * be waiting for one.
644                  */
645                 if (sockevent & CBB_SOCKET_EVENT_POWER) {
646                         crit_enter();
647                         sc->powerintr++;
648                         wakeup(&sc->power_cv);
649                         crit_exit();
650                 }
651         }
652         /*
653          * Some chips also require us to read the old ExCA registe for
654          * card status change when we route CSC vis PCI.  This isn't supposed
655          * to be required, but it clears the interrupt state on some chipsets.
656          * Maybe there's a setting that would obviate its need.  Maybe we
657          * should test the status bits and deal with them, but so far we've
658          * not found any machines that don't also give us the socket status
659          * indication above.
660          *
661          * We have to call this unconditionally because some bridges deliver
662          * the even independent of the CBB_SOCKET_EVENT_CD above.
663          */
664         exca_getb(&sc->exca[0], EXCA_CSC);
665 }
666
667 /************************************************************************/
668 /* Generic Power functions                                              */
669 /************************************************************************/
670
671 static uint32_t
672 cbb_detect_voltage(device_t brdev)
673 {
674         struct cbb_softc *sc = device_get_softc(brdev);
675         uint32_t psr;
676         uint32_t vol = CARD_UKN_CARD;
677
678         psr = cbb_get(sc, CBB_SOCKET_STATE);
679
680         if (psr & CBB_STATE_5VCARD)
681                 vol |= CARD_5V_CARD;
682         if (psr & CBB_STATE_3VCARD)
683                 vol |= CARD_3V_CARD;
684         if (psr & CBB_STATE_XVCARD)
685                 vol |= CARD_XV_CARD;
686         if (psr & CBB_STATE_YVCARD)
687                 vol |= CARD_YV_CARD;
688
689         return (vol);
690 }
691
692 static uint8_t
693 cbb_o2micro_power_hack(struct cbb_softc *sc)
694 {
695         uint8_t reg;
696
697         /*
698          * Issue #2: INT# not qualified with IRQ Routing Bit.  An
699          * unexpected PCI INT# may be generated during PC-Card
700          * initialization even with the IRQ Routing Bit Set with some
701          * PC-Cards.
702          *
703          * This is a two part issue.  The first part is that some of
704          * our older controllers have an issue in which the slot's PCI
705          * INT# is NOT qualified by the IRQ routing bit (PCI reg. 3Eh
706          * bit 7).  Regardless of the IRQ routing bit, if NO ISA IRQ
707          * is selected (ExCA register 03h bits 3:0, of the slot, are
708          * cleared) we will generate INT# if IREQ# is asserted.  The
709          * second part is because some PC-Cards prematurally assert
710          * IREQ# before the ExCA registers are fully programmed.  This
711          * in turn asserts INT# because ExCA register 03h bits 3:0
712          * (ISA IRQ Select) are not yet programmed.
713          *
714          * The fix for this issue, which will work for any controller
715          * (old or new), is to set ExCA register 03h bits 3:0 = 0001b
716          * (select IRQ1), of the slot, before turning on slot power.
717          * Selecting IRQ1 will result in INT# NOT being asserted
718          * (because IRQ1 is selected), and IRQ1 won't be asserted
719          * because our controllers don't generate IRQ1.
720          *
721          * Other, non O2Micro controllers will generate irq 1 in some
722          * situations, so we can't do this hack for everybody.  Reports of
723          * keyboard controller's interrupts being suppressed occurred when
724          * we did this.
725          */
726         reg = exca_getb(&sc->exca[0], EXCA_INTR);
727         exca_putb(&sc->exca[0], EXCA_INTR, (reg & 0xf0) | 1);
728         return (reg);
729 }
730
731 /*
732  * Restore the damage that cbb_o2micro_power_hack does to EXCA_INTR so
733  * we don't have an interrupt storm on power on.  This has the efect of
734  * disabling card status change interrupts for the duration of poweron.
735  */
736 static void
737 cbb_o2micro_power_hack2(struct cbb_softc *sc, uint8_t reg)
738 {
739         exca_putb(&sc->exca[0], EXCA_INTR, reg);
740 }
741
742 int
743 cbb_power(device_t brdev, int volts)
744 {
745         uint32_t status, sock_ctrl, mask;
746         struct cbb_softc *sc = device_get_softc(brdev);
747         int cnt, sane;
748         int retval = 0;
749         int on = 0;
750         uint8_t reg = 0;
751
752         sock_ctrl = cbb_get(sc, CBB_SOCKET_CONTROL);
753
754         sock_ctrl &= ~CBB_SOCKET_CTRL_VCCMASK;
755         switch (volts & CARD_VCCMASK) {
756         case 5:
757                 sock_ctrl |= CBB_SOCKET_CTRL_VCC_5V;
758                 on++;
759                 break;
760         case 3:
761                 sock_ctrl |= CBB_SOCKET_CTRL_VCC_3V;
762                 on++;
763                 break;
764         case XV:
765                 sock_ctrl |= CBB_SOCKET_CTRL_VCC_XV;
766                 on++;
767                 break;
768         case YV:
769                 sock_ctrl |= CBB_SOCKET_CTRL_VCC_YV;
770                 on++;
771                 break;
772         case 0:
773                 break;
774         default:
775                 return (0);                     /* power NEVER changed */
776         }
777
778         /* VPP == VCC */
779         sock_ctrl &= ~CBB_SOCKET_CTRL_VPPMASK;
780         sock_ctrl |= ((sock_ctrl >> 4) & 0x07);
781
782         if (cbb_get(sc, CBB_SOCKET_CONTROL) == sock_ctrl)
783                 return (1); /* no change necessary */
784         DEVPRINTF((sc->dev, "cbb_power: %dV\n", volts));
785         if (volts != 0 && sc->chipset == CB_O2MICRO)
786                 reg = cbb_o2micro_power_hack(sc);
787
788         /*
789          * We have to mask the card change detect interrupt while we're
790          * messing with the power.  It is allowed to bounce while we're
791          * messing with power as things settle down.  In addition, we mask off
792          * the card's function interrupt by routing it via the ISA bus.  This
793          * bit generally only affects 16bit cards.  Some bridges allow one to
794          * set another bit to have it also affect 32bit cards.  Since 32bit
795          * cards are required to be better behaved, we don't bother to get
796          * into those bridge specific features.
797          */
798         mask = cbb_get(sc, CBB_SOCKET_MASK);
799         mask |= CBB_SOCKET_MASK_POWER;
800         mask &= ~CBB_SOCKET_MASK_CD;
801         cbb_set(sc, CBB_SOCKET_MASK, mask);
802         PCI_MASK_CONFIG(brdev, CBBR_BRIDGECTRL,
803             |CBBM_BRIDGECTRL_INTR_IREQ_ISA_EN, 2);
804         cbb_set(sc, CBB_SOCKET_CONTROL, sock_ctrl);
805         if (on) {
806                 crit_enter();
807                 cnt = sc->powerintr;
808                 sane = 200;
809                 while (!(cbb_get(sc, CBB_SOCKET_STATE) & CBB_STATE_POWER_CYCLE) &&
810                     cnt == sc->powerintr && sane-- > 0)
811                         tsleep(&sc->power_cv, 0, "cbbpcv", hz / 10);
812                 crit_exit();
813                 if (sane <= 0)
814                         device_printf(sc->dev, "power timeout, doom?\n");
815         }
816
817         /*
818          * After the power is good, we can turn off the power interrupt.
819          * However, the PC Card standard says that we must delay turning the
820          * CD bit back on for a bit to allow for bouncyness on power down
821          * (recall that we don't wait above for a power down, since we don't
822          * get an interrupt for that).  We're called either from the suspend
823          * code in which case we don't want to turn card change on again, or
824          * we're called from the card insertion code, in which case the cbb
825          * thread will turn it on for us before it waits to be woken by a
826          * change event.
827          */
828         cbb_clrb(sc, CBB_SOCKET_MASK, CBB_SOCKET_MASK_POWER);
829         status = cbb_get(sc, CBB_SOCKET_STATE);
830         if (on) {
831                 if ((status & CBB_STATE_POWER_CYCLE) == 0)
832                         device_printf(sc->dev, "Power not on?\n");
833         }
834         if (status & CBB_STATE_BAD_VCC_REQ) {
835                 device_printf(sc->dev, "Bad Vcc requested\n");  
836                 /* XXX Do we want to do something to mitigate things here? */
837                 goto done;
838         }
839         PCI_MASK_CONFIG(brdev, CBBR_BRIDGECTRL,
840             & ~CBBM_BRIDGECTRL_INTR_IREQ_ISA_EN, 2);
841         retval = 1;
842 done:;
843         if (volts != 0 && sc->chipset == CB_O2MICRO)
844                 cbb_o2micro_power_hack2(sc, reg);
845         return (retval);
846 }
847
848 static int
849 cbb_current_voltage(device_t brdev)
850 {
851         struct cbb_softc *sc = device_get_softc(brdev);
852         uint32_t ctrl;
853         
854         ctrl = cbb_get(sc, CBB_SOCKET_CONTROL);
855         switch (ctrl & CBB_SOCKET_CTRL_VCCMASK) {
856         case CBB_SOCKET_CTRL_VCC_5V:
857                 return CARD_5V_CARD;
858         case CBB_SOCKET_CTRL_VCC_3V:
859                 return CARD_3V_CARD;
860         case CBB_SOCKET_CTRL_VCC_XV:
861                 return CARD_XV_CARD;
862         case CBB_SOCKET_CTRL_VCC_YV:
863                 return CARD_YV_CARD;
864         }
865         return 0;
866 }
867
868 /*
869  * detect the voltage for the card, and set it.  Since the power
870  * used is the square of the voltage, lower voltages is a big win
871  * and what Windows does (and what Microsoft prefers).  The MS paper
872  * also talks about preferring the CIS entry as well, but that has
873  * to be done elsewhere.  We also optimize power sequencing here
874  * and don't change things if we're already powered up at a supported
875  * voltage.
876  *
877  * In addition, we power up with OE disabled.  We'll set it later
878  * in the power up sequence.
879  */
880 static int
881 cbb_do_power(device_t brdev)
882 {
883         struct cbb_softc *sc = device_get_softc(brdev);
884         uint32_t voltage, curpwr;
885         uint32_t status;
886
887         /* Don't enable OE (output enable) until power stable */
888         exca_clrb(&sc->exca[0], EXCA_PWRCTL, EXCA_PWRCTL_OE);
889
890         voltage = cbb_detect_voltage(brdev);
891         curpwr = cbb_current_voltage(brdev);
892         status = cbb_get(sc, CBB_SOCKET_STATE);
893         if ((status & CBB_STATE_POWER_CYCLE) && (voltage & curpwr))
894                 return 0;
895         /* Prefer lowest voltage supported */
896         cbb_power(brdev, CARD_OFF);
897         if (voltage & CARD_YV_CARD)
898                 cbb_power(brdev, CARD_VCC(YV));
899         else if (voltage & CARD_XV_CARD)
900                 cbb_power(brdev, CARD_VCC(XV));
901         else if (voltage & CARD_3V_CARD)
902                 cbb_power(brdev, CARD_VCC(3));
903         else if (voltage & CARD_5V_CARD)
904                 cbb_power(brdev, CARD_VCC(5));
905         else {
906                 device_printf(brdev, "Unknown card voltage\n");
907                 return (ENXIO);
908         }
909         return (0);
910 }
911
912 /************************************************************************/
913 /* CardBus power functions                                              */
914 /************************************************************************/
915
916 static void
917 cbb_cardbus_reset(device_t brdev)
918 {
919         struct cbb_softc *sc = device_get_softc(brdev);
920         int delay;
921
922         /*
923          * 20ms is necessary for most bridges.  For some reason, the Ricoh
924          * RF5C47x bridges need 400ms.
925          */
926         delay = sc->chipset == CB_RF5C47X ? 400 : 20;
927
928         PCI_MASK_CONFIG(brdev, CBBR_BRIDGECTRL, |CBBM_BRIDGECTRL_RESET, 2);
929
930         tsleep(sc, 0, "cbbP3", hz * delay / 1000);
931
932         /* If a card exists, unreset it! */
933         if (CBB_CARD_PRESENT(cbb_get(sc, CBB_SOCKET_STATE))) {
934                 PCI_MASK_CONFIG(brdev, CBBR_BRIDGECTRL,
935                     &~CBBM_BRIDGECTRL_RESET, 2);
936                 tsleep(sc, 0, "cbbP3", hz * delay / 1000);
937         }
938 }
939
940 static int
941 cbb_cardbus_power_enable_socket(device_t brdev, device_t child)
942 {
943         struct cbb_softc *sc = device_get_softc(brdev);
944         int err;
945
946         if (!CBB_CARD_PRESENT(cbb_get(sc, CBB_SOCKET_STATE)))
947                 return (ENODEV);
948
949         err = cbb_do_power(brdev);
950         if (err)
951                 return (err);
952         cbb_cardbus_reset(brdev);
953         return (0);
954 }
955
956 static void
957 cbb_cardbus_power_disable_socket(device_t brdev, device_t child)
958 {
959         cbb_power(brdev, CARD_OFF);
960         cbb_cardbus_reset(brdev);
961 }
962
963 /************************************************************************/
964 /* CardBus Resource                                                     */
965 /************************************************************************/
966
967 static int
968 cbb_cardbus_io_open(device_t brdev, int win, uint32_t start, uint32_t end)
969 {
970         int basereg;
971         int limitreg;
972
973         if ((win < 0) || (win > 1)) {
974                 DEVPRINTF((brdev,
975                     "cbb_cardbus_io_open: window out of range %d\n", win));
976                 return (EINVAL);
977         }
978
979         basereg = win * 8 + CBBR_IOBASE0;
980         limitreg = win * 8 + CBBR_IOLIMIT0;
981
982         pci_write_config(brdev, basereg, start, 4);
983         pci_write_config(brdev, limitreg, end, 4);
984         return (0);
985 }
986
987 static int
988 cbb_cardbus_mem_open(device_t brdev, int win, uint32_t start, uint32_t end)
989 {
990         int basereg;
991         int limitreg;
992
993         if ((win < 0) || (win > 1)) {
994                 DEVPRINTF((brdev,
995                     "cbb_cardbus_mem_open: window out of range %d\n", win));
996                 return (EINVAL);
997         }
998
999         basereg = win*8 + CBBR_MEMBASE0;
1000         limitreg = win*8 + CBBR_MEMLIMIT0;
1001
1002         pci_write_config(brdev, basereg, start, 4);
1003         pci_write_config(brdev, limitreg, end, 4);
1004         return (0);
1005 }
1006
1007 /*
1008  * XXX The following function belongs in the pci bus layer.
1009  */
1010 static void
1011 cbb_cardbus_auto_open(struct cbb_softc *sc, int type)
1012 {
1013         uint32_t starts[2];
1014         uint32_t ends[2];
1015         struct cbb_reslist *rle;
1016         int align;
1017         int prefetchable[2];
1018         uint32_t reg;
1019
1020         starts[0] = starts[1] = 0xffffffff;
1021         ends[0] = ends[1] = 0;
1022
1023         if (type == SYS_RES_MEMORY)
1024                 align = CBB_MEMALIGN;
1025         else if (type == SYS_RES_IOPORT)
1026                 align = CBB_IOALIGN;
1027         else
1028                 align = 1;
1029
1030         /*
1031          * This looks somewhat bogus, and doesn't seem to really respect
1032          * alignment.  The alignment stuff is happening too late (it
1033          * should happen at allocation time, not activation time) and
1034          * this code looks generally to be too complex for the purpose
1035          * it surves.
1036          */
1037         SLIST_FOREACH(rle, &sc->rl, link) {
1038                 if (rle->type != type)
1039                         ;
1040                 else if (rle->res == NULL) {
1041                         device_printf(sc->dev, "WARNING: Resource not reserved?  "
1042                             "(type=%d, addr=%lx)\n",
1043                             rle->type, rman_get_start(rle->res));
1044                 } else if (!(rman_get_flags(rle->res) & RF_ACTIVE)) {
1045                         /* XXX */
1046                 } else if (starts[0] == 0xffffffff) {
1047                         starts[0] = rman_get_start(rle->res);
1048                         ends[0] = rman_get_end(rle->res);
1049                         prefetchable[0] =
1050                             rman_get_flags(rle->res) & RF_PREFETCHABLE;
1051                 } else if (rman_get_end(rle->res) > ends[0] &&
1052                     rman_get_start(rle->res) - ends[0] <
1053                     CBB_AUTO_OPEN_SMALLHOLE && prefetchable[0] ==
1054                     (rman_get_flags(rle->res) & RF_PREFETCHABLE)) {
1055                         ends[0] = rman_get_end(rle->res);
1056                 } else if (rman_get_start(rle->res) < starts[0] &&
1057                     starts[0] - rman_get_end(rle->res) <
1058                     CBB_AUTO_OPEN_SMALLHOLE && prefetchable[0] ==
1059                     (rman_get_flags(rle->res) & RF_PREFETCHABLE)) {
1060                         starts[0] = rman_get_start(rle->res);
1061                 } else if (starts[1] == 0xffffffff) {
1062                         starts[1] = rman_get_start(rle->res);
1063                         ends[1] = rman_get_end(rle->res);
1064                         prefetchable[1] =
1065                             rman_get_flags(rle->res) & RF_PREFETCHABLE;
1066                 } else if (rman_get_end(rle->res) > ends[1] &&
1067                     rman_get_start(rle->res) - ends[1] <
1068                     CBB_AUTO_OPEN_SMALLHOLE && prefetchable[1] ==
1069                     (rman_get_flags(rle->res) & RF_PREFETCHABLE)) {
1070                         ends[1] = rman_get_end(rle->res);
1071                 } else if (rman_get_start(rle->res) < starts[1] &&
1072                     starts[1] - rman_get_end(rle->res) <
1073                     CBB_AUTO_OPEN_SMALLHOLE && prefetchable[1] ==
1074                     (rman_get_flags(rle->res) & RF_PREFETCHABLE)) {
1075                         starts[1] = rman_get_start(rle->res);
1076                 } else {
1077                         uint32_t diffs[2];
1078                         int win;
1079
1080                         diffs[0] = diffs[1] = 0xffffffff;
1081                         if (rman_get_start(rle->res) > ends[0])
1082                                 diffs[0] = rman_get_start(rle->res) - ends[0];
1083                         else if (rman_get_end(rle->res) < starts[0])
1084                                 diffs[0] = starts[0] - rman_get_end(rle->res);
1085                         if (rman_get_start(rle->res) > ends[1])
1086                                 diffs[1] = rman_get_start(rle->res) - ends[1];
1087                         else if (rman_get_end(rle->res) < starts[1])
1088                                 diffs[1] = starts[1] - rman_get_end(rle->res);
1089
1090                         win = (diffs[0] <= diffs[1])?0:1;
1091                         if (rman_get_start(rle->res) > ends[win])
1092                                 ends[win] = rman_get_end(rle->res);
1093                         else if (rman_get_end(rle->res) < starts[win])
1094                                 starts[win] = rman_get_start(rle->res);
1095                         if (!(rman_get_flags(rle->res) & RF_PREFETCHABLE))
1096                                 prefetchable[win] = 0;
1097                 }
1098
1099                 if (starts[0] != 0xffffffff)
1100                         starts[0] -= starts[0] % align;
1101                 if (starts[1] != 0xffffffff)
1102                         starts[1] -= starts[1] % align;
1103                 if (ends[0] % align != 0)
1104                         ends[0] += align - ends[0] % align - 1;
1105                 if (ends[1] % align != 0)
1106                         ends[1] += align - ends[1] % align - 1;
1107         }
1108
1109         if (type == SYS_RES_MEMORY) {
1110                 cbb_cardbus_mem_open(sc->dev, 0, starts[0], ends[0]);
1111                 cbb_cardbus_mem_open(sc->dev, 1, starts[1], ends[1]);
1112                 reg = pci_read_config(sc->dev, CBBR_BRIDGECTRL, 2);
1113                 reg &= ~(CBBM_BRIDGECTRL_PREFETCH_0|
1114                     CBBM_BRIDGECTRL_PREFETCH_1);
1115                 reg |= (prefetchable[0]?CBBM_BRIDGECTRL_PREFETCH_0:0)|
1116                     (prefetchable[1]?CBBM_BRIDGECTRL_PREFETCH_1:0);
1117                 pci_write_config(sc->dev, CBBR_BRIDGECTRL, reg, 2);
1118         } else if (type == SYS_RES_IOPORT) {
1119                 cbb_cardbus_io_open(sc->dev, 0, starts[0], ends[0]);
1120                 cbb_cardbus_io_open(sc->dev, 1, starts[1], ends[1]);
1121         }
1122 }
1123
1124 static int
1125 cbb_cardbus_activate_resource(device_t brdev, device_t child, int type,
1126     int rid, struct resource *res)
1127 {
1128         int ret;
1129
1130         ret = BUS_ACTIVATE_RESOURCE(device_get_parent(brdev), child,
1131             type, rid, res);
1132         if (ret != 0)
1133                 return (ret);
1134         cbb_cardbus_auto_open(device_get_softc(brdev), type);
1135         return (0);
1136 }
1137
1138 static int
1139 cbb_cardbus_deactivate_resource(device_t brdev, device_t child, int type,
1140     int rid, struct resource *res)
1141 {
1142         int ret;
1143
1144         ret = BUS_DEACTIVATE_RESOURCE(device_get_parent(brdev), child,
1145             type, rid, res);
1146         if (ret != 0)
1147                 return (ret);
1148         cbb_cardbus_auto_open(device_get_softc(brdev), type);
1149         return (0);
1150 }
1151
1152 static struct resource *
1153 cbb_cardbus_alloc_resource(device_t brdev, device_t child, int type,
1154     int *rid, u_long start, u_long end, u_long count, u_int flags)
1155 {
1156         struct cbb_softc *sc = device_get_softc(brdev);
1157         int tmp;
1158         struct resource *res;
1159         u_long align;
1160
1161         switch (type) {
1162         case SYS_RES_IRQ:
1163                 tmp = rman_get_start(sc->irq_res);
1164                 if (start > tmp || end < tmp || count != 1) {
1165                         device_printf(child, "requested interrupt %ld-%ld,"
1166                             "count = %ld not supported by cbb\n",
1167                             start, end, count);
1168                         return (NULL);
1169                 }
1170                 start = end = tmp;
1171                 flags |= RF_SHAREABLE;
1172                 break;
1173         case SYS_RES_IOPORT:
1174                 if (start <= cbb_start_32_io)
1175                         start = cbb_start_32_io;
1176                 if (end < start)
1177                         end = start;
1178                 break;
1179         case SYS_RES_MEMORY:
1180                 if (start <= cbb_start_mem)
1181                         start = cbb_start_mem;
1182                 if (end < start)
1183                         end = start;
1184                 if (count < CBB_MEMALIGN)
1185                         align = CBB_MEMALIGN;
1186                 else
1187                         align = count;
1188                 if (align > (1 << RF_ALIGNMENT(flags)))
1189                         flags = (flags & ~RF_ALIGNMENT_MASK) | 
1190                             rman_make_alignment_flags(align);
1191                 break;
1192         }
1193
1194         res = BUS_ALLOC_RESOURCE(device_get_parent(brdev), child, type, rid,
1195             start, end, count, flags & ~RF_ACTIVE);
1196         if (res == NULL) {
1197                 kprintf("cbb alloc res fail\n");
1198                 return (NULL);
1199         }
1200         cbb_insert_res(sc, res, type, *rid);
1201         if (flags & RF_ACTIVE)
1202                 if (bus_activate_resource(child, type, *rid, res) != 0) {
1203                         bus_release_resource(child, type, *rid, res);
1204                         return (NULL);
1205                 }
1206
1207         return (res);
1208 }
1209
1210 static int
1211 cbb_cardbus_release_resource(device_t brdev, device_t child, int type,
1212     int rid, struct resource *res)
1213 {
1214         struct cbb_softc *sc = device_get_softc(brdev);
1215         int error;
1216
1217         if (rman_get_flags(res) & RF_ACTIVE) {
1218                 error = bus_deactivate_resource(child, type, rid, res);
1219                 if (error != 0)
1220                         return (error);
1221         }
1222         cbb_remove_res(sc, res);
1223         return (BUS_RELEASE_RESOURCE(device_get_parent(brdev), child,
1224             type, rid, res));
1225 }
1226
1227 /************************************************************************/
1228 /* PC Card Power Functions                                              */
1229 /************************************************************************/
1230
1231 static int
1232 cbb_pcic_power_enable_socket(device_t brdev, device_t child)
1233 {
1234         struct cbb_softc *sc = device_get_softc(brdev);
1235         int err;
1236
1237         DPRINTF(("cbb_pcic_socket_enable:\n"));
1238
1239         /* power down/up the socket to reset */
1240         err = cbb_do_power(brdev);
1241         if (err)
1242                 return (err);
1243         exca_reset(&sc->exca[0], child);
1244
1245         return (0);
1246 }
1247
1248 static void
1249 cbb_pcic_power_disable_socket(device_t brdev, device_t child)
1250 {
1251         struct cbb_softc *sc = device_get_softc(brdev);
1252
1253         DPRINTF(("cbb_pcic_socket_disable\n"));
1254
1255         /* reset signal asserting... */
1256         exca_clrb(&sc->exca[0], EXCA_INTR, EXCA_INTR_RESET);
1257         tsleep(sc, 0, "cbbP1", hz / 100);
1258
1259         /* power down the socket */
1260         exca_clrb(&sc->exca[0], EXCA_PWRCTL, EXCA_PWRCTL_OE);
1261         cbb_power(brdev, CARD_OFF);
1262
1263         /* wait 300ms until power fails (Tpf). */
1264         tsleep(sc, 0, "cbbP1", hz * 300 / 1000);
1265 }
1266
1267 /************************************************************************/
1268 /* POWER methods                                                        */
1269 /************************************************************************/
1270
1271 int
1272 cbb_power_enable_socket(device_t brdev, device_t child)
1273 {
1274         struct cbb_softc *sc = device_get_softc(brdev);
1275
1276         if (sc->flags & CBB_16BIT_CARD)
1277                 return (cbb_pcic_power_enable_socket(brdev, child));
1278         else
1279                 return (cbb_cardbus_power_enable_socket(brdev, child));
1280 }
1281
1282 void
1283 cbb_power_disable_socket(device_t brdev, device_t child)
1284 {
1285         struct cbb_softc *sc = device_get_softc(brdev);
1286         if (sc->flags & CBB_16BIT_CARD)
1287                 cbb_pcic_power_disable_socket(brdev, child);
1288         else
1289                 cbb_cardbus_power_disable_socket(brdev, child);
1290 }
1291
1292 static int
1293 cbb_pcic_activate_resource(device_t brdev, device_t child, int type, int rid,
1294     struct resource *res)
1295 {
1296         struct cbb_softc *sc = device_get_softc(brdev);
1297         return (exca_activate_resource(&sc->exca[0], child, type, rid, res));
1298 }
1299
1300 static int
1301 cbb_pcic_deactivate_resource(device_t brdev, device_t child, int type,
1302     int rid, struct resource *res)
1303 {
1304         struct cbb_softc *sc = device_get_softc(brdev);
1305         return (exca_deactivate_resource(&sc->exca[0], child, type, rid, res));
1306 }
1307
1308 static struct resource *
1309 cbb_pcic_alloc_resource(device_t brdev, device_t child, int type, int *rid,
1310     u_long start, u_long end, u_long count, u_int flags)
1311 {
1312         struct resource *res = NULL;
1313         struct cbb_softc *sc = device_get_softc(brdev);
1314         int align;
1315         int tmp;
1316
1317         switch (type) {
1318         case SYS_RES_MEMORY:
1319                 if (start < cbb_start_mem)
1320                         start = cbb_start_mem;
1321                 if (end < start)
1322                         end = start;
1323                 if (count < CBB_MEMALIGN)
1324                         align = CBB_MEMALIGN;
1325                 else
1326                         align = count;
1327                 if (align > (1 << RF_ALIGNMENT(flags)))
1328                         flags = (flags & ~RF_ALIGNMENT_MASK) | 
1329                             rman_make_alignment_flags(align);
1330                 break;
1331         case SYS_RES_IOPORT:
1332                 if (start < cbb_start_16_io)
1333                         start = cbb_start_16_io;
1334                 if (end < start)
1335                         end = start;
1336                 break;
1337         case SYS_RES_IRQ:
1338                 tmp = rman_get_start(sc->irq_res);
1339                 if (start > tmp || end < tmp || count != 1) {
1340                         device_printf(child, "requested interrupt %ld-%ld,"
1341                             "count = %ld not supported by cbb\n",
1342                             start, end, count);
1343                         return (NULL);
1344                 }
1345                 flags |= RF_SHAREABLE;
1346                 start = end = rman_get_start(sc->irq_res);
1347                 break;
1348         }
1349         res = BUS_ALLOC_RESOURCE(device_get_parent(brdev), child, type, rid,
1350             start, end, count, flags & ~RF_ACTIVE);
1351         if (res == NULL)
1352                 return (NULL);
1353         cbb_insert_res(sc, res, type, *rid);
1354         if (flags & RF_ACTIVE) {
1355                 if (bus_activate_resource(child, type, *rid, res) != 0) {
1356                         bus_release_resource(child, type, *rid, res);
1357                         return (NULL);
1358                 }
1359         }
1360
1361         return (res);
1362 }
1363
1364 static int
1365 cbb_pcic_release_resource(device_t brdev, device_t child, int type,
1366     int rid, struct resource *res)
1367 {
1368         struct cbb_softc *sc = device_get_softc(brdev);
1369         int error;
1370
1371         if (rman_get_flags(res) & RF_ACTIVE) {
1372                 error = bus_deactivate_resource(child, type, rid, res);
1373                 if (error != 0)
1374                         return (error);
1375         }
1376         cbb_remove_res(sc, res);
1377         return (BUS_RELEASE_RESOURCE(device_get_parent(brdev), child,
1378             type, rid, res));
1379 }
1380
1381 /************************************************************************/
1382 /* PC Card methods                                                      */
1383 /************************************************************************/
1384
1385 int
1386 cbb_pcic_set_res_flags(device_t brdev, device_t child, int type, int rid,
1387     uint32_t flags)
1388 {
1389         struct cbb_softc *sc = device_get_softc(brdev);
1390         struct resource *res;
1391
1392         if (type != SYS_RES_MEMORY)
1393                 return (EINVAL);
1394         res = cbb_find_res(sc, type, rid);
1395         if (res == NULL) {
1396                 device_printf(brdev,
1397                     "set_res_flags: specified rid not found\n");
1398                 return (ENOENT);
1399         }
1400         return (exca_mem_set_flags(&sc->exca[0], res, flags));
1401 }
1402
1403 int
1404 cbb_pcic_set_memory_offset(device_t brdev, device_t child, int rid,
1405     uint32_t cardaddr, uint32_t *deltap)
1406 {
1407         struct cbb_softc *sc = device_get_softc(brdev);
1408         struct resource *res;
1409
1410         res = cbb_find_res(sc, SYS_RES_MEMORY, rid);
1411         if (res == NULL) {
1412                 device_printf(brdev,
1413                     "set_memory_offset: specified rid not found\n");
1414                 return (ENOENT);
1415         }
1416         return (exca_mem_set_offset(&sc->exca[0], res, cardaddr, deltap));
1417 }
1418
1419 /************************************************************************/
1420 /* BUS Methods                                                          */
1421 /************************************************************************/
1422
1423
1424 int
1425 cbb_activate_resource(device_t brdev, device_t child, int type, int rid,
1426     struct resource *r)
1427 {
1428         struct cbb_softc *sc = device_get_softc(brdev);
1429
1430         if (sc->flags & CBB_16BIT_CARD)
1431                 return (cbb_pcic_activate_resource(brdev, child, type, rid, r));
1432         else
1433                 return (cbb_cardbus_activate_resource(brdev, child, type, rid,
1434                     r));
1435 }
1436
1437 int
1438 cbb_deactivate_resource(device_t brdev, device_t child, int type,
1439     int rid, struct resource *r)
1440 {
1441         struct cbb_softc *sc = device_get_softc(brdev);
1442
1443         if (sc->flags & CBB_16BIT_CARD)
1444                 return (cbb_pcic_deactivate_resource(brdev, child, type,
1445                     rid, r));
1446         else
1447                 return (cbb_cardbus_deactivate_resource(brdev, child, type,
1448                     rid, r));
1449 }
1450
1451 struct resource *
1452 cbb_alloc_resource(device_t brdev, device_t child, int type, int *rid,
1453     u_long start, u_long end, u_long count, u_int flags)
1454 {
1455         struct cbb_softc *sc = device_get_softc(brdev);
1456
1457         if (sc->flags & CBB_16BIT_CARD)
1458                 return (cbb_pcic_alloc_resource(brdev, child, type, rid,
1459                     start, end, count, flags));
1460         else
1461                 return (cbb_cardbus_alloc_resource(brdev, child, type, rid,
1462                     start, end, count, flags));
1463 }
1464
1465 int
1466 cbb_release_resource(device_t brdev, device_t child, int type, int rid,
1467     struct resource *r)
1468 {
1469         struct cbb_softc *sc = device_get_softc(brdev);
1470
1471         if (sc->flags & CBB_16BIT_CARD)
1472                 return (cbb_pcic_release_resource(brdev, child, type,
1473                     rid, r));
1474         else
1475                 return (cbb_cardbus_release_resource(brdev, child, type,
1476                     rid, r));
1477 }
1478
1479 int
1480 cbb_read_ivar(device_t brdev, device_t child, int which, uintptr_t *result)
1481 {
1482         struct cbb_softc *sc = device_get_softc(brdev);
1483
1484         switch (which) {
1485         case PCIB_IVAR_DOMAIN:
1486                 *result = sc->domain;
1487                 return (0);
1488         case PCIB_IVAR_BUS:
1489                 *result = sc->secbus;
1490                 return (0);
1491         }
1492         return (ENOENT);
1493 }
1494
1495 int
1496 cbb_write_ivar(device_t brdev, device_t child, int which, uintptr_t value)
1497 {
1498         struct cbb_softc *sc = device_get_softc(brdev);
1499
1500         switch (which) {
1501         case PCIB_IVAR_DOMAIN:
1502                 return (EINVAL);
1503         case PCIB_IVAR_BUS:
1504                 sc->secbus = value;
1505                 break;
1506         }
1507         return (ENOENT);
1508 }
1509
1510 /************************************************************************/
1511 /* PCI compat methods                                                   */
1512 /************************************************************************/
1513
1514 int
1515 cbb_maxslots(device_t brdev)
1516 {
1517         return (0);
1518 }
1519
1520 uint32_t
1521 cbb_read_config(device_t brdev, int b, int s, int f, int reg, int width)
1522 {
1523         uint32_t rv;
1524
1525         /*
1526          * Pass through to the next ppb up the chain (i.e. our grandparent).
1527          */
1528         rv = PCIB_READ_CONFIG(device_get_parent(device_get_parent(brdev)),
1529             b, s, f, reg, width);
1530         return (rv);
1531 }
1532
1533 void
1534 cbb_write_config(device_t brdev, int b, int s, int f, int reg, uint32_t val,
1535     int width)
1536 {
1537         /*
1538          * Pass through to the next ppb up the chain (i.e. our grandparent).
1539          */
1540         PCIB_WRITE_CONFIG(device_get_parent(device_get_parent(brdev)),
1541             b, s, f, reg, val, width);
1542 }
1543
1544 int
1545 cbb_suspend(device_t self)
1546 {
1547         int                     error = 0;
1548         struct cbb_softc        *sc = device_get_softc(self);
1549
1550         cbb_set(sc, CBB_SOCKET_MASK, 0);        /* Quiet hardware */
1551         bus_teardown_intr(self, sc->irq_res, sc->intrhand);
1552         sc->flags &= ~CBB_CARD_OK;              /* Card is bogus now */
1553         error = bus_generic_suspend(self);
1554         return (error);
1555 }
1556
1557 int
1558 cbb_resume(device_t self)
1559 {
1560         int     error = 0;
1561         struct cbb_softc *sc = (struct cbb_softc *)device_get_softc(self);
1562         uint32_t tmp;
1563
1564         /*
1565          * Some BIOSes will not save the BARs for the pci chips, so we
1566          * must do it ourselves.  If the BAR is reset to 0 for an I/O
1567          * device, it will read back as 0x1, so no explicit test for
1568          * memory devices are needed.
1569          *
1570          * Note: The PCI bus code should do this automatically for us on
1571          * suspend/resume, but until it does, we have to cope.
1572          */
1573         pci_write_config(self, CBBR_SOCKBASE, rman_get_start(sc->base_res), 4);
1574         DEVPRINTF((self, "PCI Memory allocated: %08lx\n",
1575             rman_get_start(sc->base_res)));
1576
1577         sc->chipinit(sc);
1578
1579         /* reset interrupt -- Do we really need to do this? */
1580         tmp = cbb_get(sc, CBB_SOCKET_EVENT);
1581         cbb_set(sc, CBB_SOCKET_EVENT, tmp);
1582
1583         /* re-establish the interrupt. */
1584         if (bus_setup_intr(self, sc->irq_res, INTR_MPSAFE, cbb_intr, sc,
1585                            &sc->intrhand, NULL)) {
1586                 device_printf(self, "couldn't re-establish interrupt");
1587                 bus_release_resource(self, SYS_RES_IRQ, 0, sc->irq_res);
1588                 bus_release_resource(self, SYS_RES_MEMORY, CBBR_SOCKBASE,
1589                     sc->base_res);
1590                 sc->irq_res = NULL;
1591                 sc->base_res = NULL;
1592                 return (ENOMEM);
1593         }
1594
1595         /* CSC Interrupt: Card detect interrupt on */
1596         cbb_setb(sc, CBB_SOCKET_MASK, CBB_SOCKET_MASK_CD);
1597
1598         /* Signal the thread to wakeup. */
1599         wakeup_one(&sc->generic_cv);
1600
1601         error = bus_generic_resume(self);
1602
1603         return (error);
1604 }
1605
1606 int
1607 cbb_child_present(device_t self)
1608 {
1609         struct cbb_softc *sc = (struct cbb_softc *)device_get_softc(self);
1610         uint32_t sockstate;
1611
1612         sockstate = cbb_get(sc, CBB_SOCKET_STATE);
1613         return (CBB_CARD_PRESENT(sockstate) &&
1614           (sc->flags & CBB_CARD_OK) == CBB_CARD_OK);
1615 }