2 * Copyright (c) 2002-2004 M. Warner Losh.
3 * Copyright (c) 2000-2001 Jonathan Chen.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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
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 $
32 * Copyright (c) 1998, 1999 and 2000
33 * HAYAKAWA Koichi. All rights reserved.
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
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.
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.
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
69 * http://www-s.ti.com/cgi-bin/sc/generic2.cgi?family=PCI+CARDBUS+CONTROLLERS
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
79 #include <sys/param.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>
87 #include <sys/malloc.h>
90 #include <sys/sysctl.h>
91 #include <sys/systm.h>
92 #include <sys/thread2.h>
94 #include <bus/pci/pcireg.h>
95 #include <bus/pci/pcivar.h>
96 #include <machine/clock.h>
98 #include <bus/pccard/pccardreg.h>
99 #include <bus/pccard/pccardvar.h>
101 #include <dev/pccard/exca/excareg.h>
102 #include <dev/pccard/exca/excavar.h>
104 #include <dev/pccard/pccbb/pccbbreg.h>
105 #include <dev/pccard/pccbb/pccbbvar.h>
107 #include "power_if.h"
111 #define DPRINTF(x) do { if (cbb_debug) kprintf x; } while (0)
112 #define DEVPRINTF(x) do { if (cbb_debug) device_printf x; } while (0)
114 #define PCI_MASK_CONFIG(DEV,REG,MASK,SIZE) \
115 pci_write_config(DEV, REG, pci_read_config(DEV, REG, SIZE) MASK, SIZE)
116 #define PCI_MASK2_CONFIG(DEV,REG,MASK1,MASK2,SIZE) \
117 pci_write_config(DEV, REG, ( \
118 pci_read_config(DEV, REG, SIZE) MASK1) MASK2, SIZE)
120 #define CBB_CARD_PRESENT(s) ((s & CBB_STATE_CD) == 0)
122 #define CBB_START_MEM 0x88000000
123 #define CBB_START_32_IO 0x1000
124 #define CBB_START_16_IO 0x100
126 devclass_t cbb_devclass;
129 SYSCTL_NODE(_hw, OID_AUTO, cbb, CTLFLAG_RD, 0, "CBB parameters");
131 /* There's no way to say TUNEABLE_LONG to get the right types */
132 u_long cbb_start_mem = CBB_START_MEM;
133 TUNABLE_INT("hw.cbb.start_memory", (int *)&cbb_start_mem);
134 SYSCTL_ULONG(_hw_cbb, OID_AUTO, start_memory, CTLFLAG_RW,
135 &cbb_start_mem, CBB_START_MEM,
136 "Starting address for memory allocations");
138 u_long cbb_start_16_io = CBB_START_16_IO;
139 TUNABLE_INT("hw.cbb.start_16_io", (int *)&cbb_start_16_io);
140 SYSCTL_ULONG(_hw_cbb, OID_AUTO, start_16_io, CTLFLAG_RW,
141 &cbb_start_16_io, CBB_START_16_IO,
142 "Starting ioport for 16-bit cards");
144 u_long cbb_start_32_io = CBB_START_32_IO;
145 TUNABLE_INT("hw.cbb.start_32_io", (int *)&cbb_start_32_io);
146 SYSCTL_ULONG(_hw_cbb, OID_AUTO, start_32_io, CTLFLAG_RW,
147 &cbb_start_32_io, CBB_START_32_IO,
148 "Starting ioport for 32-bit cards");
151 TUNABLE_INT("hw.cbb.debug", &cbb_debug);
152 SYSCTL_ULONG(_hw_cbb, OID_AUTO, debug, CTLFLAG_RW, &cbb_debug, 0,
153 "Verbose cardbus bridge debugging");
155 static void cbb_insert(struct cbb_softc *sc);
156 static void cbb_removal(struct cbb_softc *sc);
157 static uint32_t cbb_detect_voltage(device_t brdev);
158 static void cbb_cardbus_reset(device_t brdev);
159 static int cbb_cardbus_io_open(device_t brdev, int win, uint32_t start,
161 static int cbb_cardbus_mem_open(device_t brdev, int win,
162 uint32_t start, uint32_t end);
163 static void cbb_cardbus_auto_open(struct cbb_softc *sc, int type);
164 static int cbb_cardbus_activate_resource(device_t brdev, device_t child,
165 int type, int rid, struct resource *res);
166 static int cbb_cardbus_deactivate_resource(device_t brdev,
167 device_t child, int type, int rid, struct resource *res);
168 static struct resource *cbb_cardbus_alloc_resource(device_t brdev,
169 device_t child, int type, int *rid, u_long start,
170 u_long end, u_long count, u_int flags);
171 static int cbb_cardbus_release_resource(device_t brdev, device_t child,
172 int type, int rid, struct resource *res);
173 static int cbb_cardbus_power_enable_socket(device_t brdev,
175 static void cbb_cardbus_power_disable_socket(device_t brdev,
177 static void cbb_func_intr(void *arg);
180 cbb_remove_res(struct cbb_softc *sc, struct resource *res)
182 struct cbb_reslist *rle;
184 SLIST_FOREACH(rle, &sc->rl, link) {
185 if (rle->res == res) {
186 SLIST_REMOVE(&sc->rl, rle, cbb_reslist, link);
187 kfree(rle, M_DEVBUF);
193 static struct resource *
194 cbb_find_res(struct cbb_softc *sc, int type, int rid)
196 struct cbb_reslist *rle;
198 SLIST_FOREACH(rle, &sc->rl, link)
199 if (SYS_RES_MEMORY == rle->type && rid == rle->rid)
205 cbb_insert_res(struct cbb_softc *sc, struct resource *res, int type,
208 struct cbb_reslist *rle;
211 * Need to record allocated resource so we can iterate through
214 rle = kmalloc(sizeof(struct cbb_reslist), M_DEVBUF, M_NOWAIT);
216 panic("cbb_cardbus_alloc_resource: can't record entry!");
220 SLIST_INSERT_HEAD(&sc->rl, rle, link);
224 cbb_destroy_res(struct cbb_softc *sc)
226 struct cbb_reslist *rle;
228 while ((rle = SLIST_FIRST(&sc->rl)) != NULL) {
229 device_printf(sc->dev, "Danger Will Robinson: Resource "
230 "left allocated! This is a bug... "
231 "(rid=%x, type=%d, addr=%lx)\n", rle->rid, rle->type,
232 rman_get_start(rle->res));
233 SLIST_REMOVE_HEAD(&sc->rl, link);
234 kfree(rle, M_DEVBUF);
239 * Disable function interrupts by telling the bridge to generate IRQ1
240 * interrupts. These interrupts aren't really generated by the chip, since
241 * IRQ1 is reserved. Some chipsets assert INTA# inappropriately during
242 * initialization, so this helps to work around the problem.
244 * XXX We can't do this workaround for all chipsets, because this
245 * XXX causes interference with the keyboard because somechipsets will
246 * XXX actually signal IRQ1 over their serial interrupt connections to
247 * XXX the south bridge. Disable it it for now.
250 cbb_disable_func_intr(struct cbb_softc *sc)
254 reg = (exca_getb(&sc->exca[0], EXCA_INTR) & ~EXCA_INTR_IRQ_MASK) |
255 EXCA_INTR_IRQ_RESERVED1;
256 exca_putb(&sc->exca[0], EXCA_INTR, reg);
261 * Enable function interrupts. We turn on function interrupts when the card
262 * requests an interrupt. The PCMCIA standard says that we should set
263 * the lower 4 bits to 0 to route via PCI. Note: we call this for both
264 * CardBus and R2 (PC Card) cases, but it should have no effect on CardBus
268 cbb_enable_func_intr(struct cbb_softc *sc)
272 reg = (exca_getb(&sc->exca[0], EXCA_INTR) & ~EXCA_INTR_IRQ_MASK) |
274 exca_putb(&sc->exca[0], EXCA_INTR, reg);
278 cbb_detach(device_t brdev)
280 struct cbb_softc *sc = device_get_softc(brdev);
286 device_get_children(brdev, &devlist, &numdevs);
289 for (tmp = 0; tmp < numdevs; tmp++) {
290 if (device_detach(devlist[tmp]) == 0)
291 device_delete_child(brdev, devlist[tmp]);
295 kfree(devlist, M_TEMP);
300 * XXX do we teardown all the ones still registered to guard against
301 * XXX buggy client drivers?
303 bus_teardown_intr(brdev, sc->irq_res, sc->intrhand);
304 sc->flags |= CBB_KTHREAD_DONE;
305 if (sc->flags & CBB_KTHREAD_RUNNING) {
307 wakeup(&sc->generic_cv);
308 tsleep(sc->event_thread, 0, "cbbun", 0);
312 bus_release_resource(brdev, SYS_RES_IRQ, 0, sc->irq_res);
313 bus_release_resource(brdev, SYS_RES_MEMORY, CBBR_SOCKBASE,
319 cbb_shutdown(device_t brdev)
321 struct cbb_softc *sc = (struct cbb_softc *)device_get_softc(brdev);
322 /* properly reset everything at shutdown */
324 PCI_MASK_CONFIG(brdev, CBBR_BRIDGECTRL, |CBBM_BRIDGECTRL_RESET, 2);
325 exca_clrb(&sc->exca[0], EXCA_INTR, EXCA_INTR_RESET);
327 cbb_set(sc, CBB_SOCKET_MASK, 0);
329 cbb_power(brdev, CARD_OFF);
331 exca_putb(&sc->exca[0], EXCA_ADDRWIN_ENABLE, 0);
332 pci_write_config(brdev, CBBR_MEMBASE0, 0, 4);
333 pci_write_config(brdev, CBBR_MEMLIMIT0, 0, 4);
334 pci_write_config(brdev, CBBR_MEMBASE1, 0, 4);
335 pci_write_config(brdev, CBBR_MEMLIMIT1, 0, 4);
336 pci_write_config(brdev, CBBR_IOBASE0, 0, 4);
337 pci_write_config(brdev, CBBR_IOLIMIT0, 0, 4);
338 pci_write_config(brdev, CBBR_IOBASE1, 0, 4);
339 pci_write_config(brdev, CBBR_IOLIMIT1, 0, 4);
340 pci_write_config(brdev, PCIR_COMMAND, 0, 2);
345 cbb_setup_intr(device_t dev, device_t child, struct resource *irq,
346 int flags, driver_intr_t *intr, void *arg,
347 void **cookiep, lwkt_serialize_t serializer)
349 struct cbb_intrhand *ih;
350 struct cbb_softc *sc = device_get_softc(dev);
353 ih = kmalloc(sizeof(struct cbb_intrhand), M_DEVBUF, M_NOWAIT);
360 ih->serializer = serializer;
362 * XXX need to turn on ISA interrupts, if we ever support them, but
363 * XXX for now that's all we need to do.
365 err = BUS_SETUP_INTR(device_get_parent(dev), child, irq, flags,
366 cbb_func_intr, ih, &ih->cookie, NULL);
371 cbb_enable_func_intr(sc);
372 sc->flags |= CBB_CARD_OK;
377 cbb_teardown_intr(device_t dev, device_t child, struct resource *irq,
380 struct cbb_intrhand *ih;
383 /* XXX Need to do different things for ISA interrupts. */
384 ih = (struct cbb_intrhand *) cookie;
385 err = BUS_TEARDOWN_INTR(device_get_parent(dev), child, irq,
395 cbb_driver_added(device_t brdev, driver_t *driver)
397 struct cbb_softc *sc = device_get_softc(brdev);
404 DEVICE_IDENTIFY(driver, brdev);
405 device_get_children(brdev, &devlist, &numdevs);
406 for (tmp = 0; tmp < numdevs; tmp++) {
408 if (device_get_state(dev) == DS_NOTPRESENT &&
409 device_probe_and_attach(dev) == 0)
412 kfree(devlist, M_TEMP);
415 wakeup_one(&sc->generic_cv);
419 cbb_child_detached(device_t brdev, device_t child)
421 struct cbb_softc *sc = device_get_softc(brdev);
423 if (child != sc->cbdev && child != sc->exca[0].pccarddev)
424 device_printf(brdev, "Unknown child detached: %s\n",
425 device_get_nameunit(child));
428 /************************************************************************/
430 /************************************************************************/
433 cbb_event_thread(void *arg)
435 struct cbb_softc *sc = arg;
440 sc->flags |= CBB_KTHREAD_RUNNING;
441 while ((sc->flags & CBB_KTHREAD_DONE) == 0) {
443 * We take out Giant here because we need it deep,
444 * down in the bowels of the vm system for mapping the
445 * memory we need to read the CIS. In addition, since
446 * we are adding/deleting devices from the dev tree,
447 * and that code isn't MP safe, we have to hold Giant.
449 status = cbb_get(sc, CBB_SOCKET_STATE);
450 DPRINTF(("Status is 0x%x\n", status));
451 if (!CBB_CARD_PRESENT(status)) {
452 not_a_card = 0; /* We know card type */
454 } else if (status & CBB_STATE_NOT_A_CARD) {
456 * Up to 20 times, try to rescan the card when we
459 if (not_a_card++ < 20) {
461 "Not a card bit set, rescanning\n"));
462 cbb_setb(sc, CBB_SOCKET_FORCE, CBB_FORCE_CV_TEST);
464 device_printf(sc->dev,
465 "Can't determine card type\n");
468 not_a_card = 0; /* We know card type */
473 * Wait until it has been 1s since the last time we
474 * get an interrupt. We handle the rest of the interrupt
475 * at the top of the loop. Although we clear the bit in the
476 * ISR, we signal sc->generic_cv from the detach path after
477 * we've set the CBB_KTHREAD_DONE bit, so we can't do a simple
480 * In our ISR, we turn off the card changed interrupt. Turn
481 * them back on here before we wait for them to happen. We
482 * turn them on/off so that we can tolerate a large latency
483 * between the time we signal cbb_event_thread and it gets
487 cbb_setb(sc, CBB_SOCKET_MASK, CBB_SOCKET_MASK_CD);
488 tsleep(&sc->generic_cv, 0, "cbbgcv", 0);
490 while (err != EWOULDBLOCK &&
491 (sc->flags & CBB_KTHREAD_DONE) == 0)
492 err = tsleep(&sc->generic_cv, 0, "cbbgcv", hz);
495 sc->flags &= ~CBB_KTHREAD_RUNNING;
496 wakeup(sc->event_thread);
500 /************************************************************************/
502 /************************************************************************/
505 cbb_insert(struct cbb_softc *sc)
507 uint32_t sockevent, sockstate;
509 sockevent = cbb_get(sc, CBB_SOCKET_EVENT);
510 sockstate = cbb_get(sc, CBB_SOCKET_STATE);
512 DEVPRINTF((sc->dev, "card inserted: event=0x%08x, state=%08x\n",
513 sockevent, sockstate));
515 if (sockstate & CBB_STATE_R2_CARD) {
516 if (sc->exca[0].pccarddev) {
517 sc->flags |= CBB_16BIT_CARD;
518 exca_insert(&sc->exca[0]);
520 device_printf(sc->dev,
521 "16-bit card inserted, but no pccard bus.\n");
523 } else if (sockstate & CBB_STATE_CB_CARD) {
524 if (sc->cbdev != NULL) {
525 sc->flags &= ~CBB_16BIT_CARD;
526 CARD_ATTACH_CARD(sc->cbdev);
528 device_printf(sc->dev,
529 "CardBus card inserted, but no cardbus bus.\n");
533 * We should power the card down, and try again a couple of
534 * times if this happens. XXX
536 device_printf(sc->dev, "Unsupported card type detected\n");
541 cbb_removal(struct cbb_softc *sc)
543 sc->flags &= ~CBB_CARD_OK;
544 if (sc->flags & CBB_16BIT_CARD) {
545 exca_removal(&sc->exca[0]);
547 if (sc->cbdev != NULL)
548 CARD_DETACH_CARD(sc->cbdev);
553 /************************************************************************/
554 /* Interrupt Handler */
555 /************************************************************************/
558 * Since we touch hardware in the worst case, we don't need to use atomic
559 * ops on the CARD_OK tests. They would save us a trip to the hardware
560 * if CARD_OK was recently cleared and the caches haven't updated yet.
561 * However, an atomic op costs between 100-200 CPU cycles. On a 3GHz
562 * machine, this is about 33-66ns, whereas a trip the the hardware
563 * is about that. On slower machines, the cost is even higher, so the
564 * trip to the hardware is cheaper and achieves the same ends that
565 * a fully locked operation would give us.
567 * This is a separate routine because we'd have to use locking and/or
568 * other synchronization in cbb_intr to do this there. That would be
569 * even more expensive.
571 * I need to investigate what this means for a SMP machine with multiple
572 * CPUs servicing the ISR when an eject happens. In the case of a dirty
573 * eject, CD glitches and we might read 'card present' from the hardware
574 * due to this jitter. If we assumed that cbb_intr() ran before
575 * cbb_func_intr(), we could just check the SOCKET_MASK register and if
576 * CD changes were clear there, then we'd know the card was gone.
579 cbb_func_intr(void *arg)
581 struct cbb_intrhand *ih = arg;
582 struct cbb_softc *sc = ih->sc;
585 * Make sure that the card is really there.
587 if ((sc->flags & CBB_CARD_OK) == 0)
589 if (!CBB_CARD_PRESENT(cbb_get(sc, CBB_SOCKET_STATE))) {
590 sc->flags &= ~CBB_CARD_OK;
595 * nb: don't have to check for giant or not, since that's done
596 * in the ISR dispatch
598 if (ih->serializer) {
599 lwkt_serialize_handler_call(ih->serializer,
600 (inthand2_t *)ih->intr, ih->arg, NULL);
602 (*ih->intr)(ih->arg);
609 struct cbb_softc *sc = arg;
612 sockevent = cbb_get(sc, CBB_SOCKET_EVENT);
613 if (sockevent != 0) {
614 /* ack the interrupt */
615 cbb_set(sc, CBB_SOCKET_EVENT, sockevent);
618 * If anything has happened to the socket, we assume that
619 * the card is no longer OK, and we shouldn't call its
620 * ISR. We set CARD_OK as soon as we've attached the
621 * card. This helps in a noisy eject, which happens
622 * all too often when users are ejecting their PC Cards.
624 * We use this method in preference to checking to see if
625 * the card is still there because the check suffers from
626 * a race condition in the bouncing case. Prior versions
627 * of the pccard software used a similar trick and achieved
630 if (sockevent & CBB_SOCKET_EVENT_CD) {
632 cbb_clrb(sc, CBB_SOCKET_MASK, CBB_SOCKET_MASK_CD);
633 sc->flags &= ~CBB_CARD_OK;
634 cbb_disable_func_intr(sc);
635 wakeup_one(&sc->generic_cv);
639 * If we get a power interrupt, wakeup anybody that might
640 * be waiting for one.
642 if (sockevent & CBB_SOCKET_EVENT_POWER) {
645 wakeup(&sc->power_cv);
650 * Some chips also require us to read the old ExCA registe for
651 * card status change when we route CSC vis PCI. This isn't supposed
652 * to be required, but it clears the interrupt state on some chipsets.
653 * Maybe there's a setting that would obviate its need. Maybe we
654 * should test the status bits and deal with them, but so far we've
655 * not found any machines that don't also give us the socket status
658 * We have to call this unconditionally because some bridges deliver
659 * the even independent of the CBB_SOCKET_EVENT_CD above.
661 exca_getb(&sc->exca[0], EXCA_CSC);
664 /************************************************************************/
665 /* Generic Power functions */
666 /************************************************************************/
669 cbb_detect_voltage(device_t brdev)
671 struct cbb_softc *sc = device_get_softc(brdev);
673 uint32_t vol = CARD_UKN_CARD;
675 psr = cbb_get(sc, CBB_SOCKET_STATE);
677 if (psr & CBB_STATE_5VCARD)
679 if (psr & CBB_STATE_3VCARD)
681 if (psr & CBB_STATE_XVCARD)
683 if (psr & CBB_STATE_YVCARD)
690 cbb_o2micro_power_hack(struct cbb_softc *sc)
695 * Issue #2: INT# not qualified with IRQ Routing Bit. An
696 * unexpected PCI INT# may be generated during PC-Card
697 * initialization even with the IRQ Routing Bit Set with some
700 * This is a two part issue. The first part is that some of
701 * our older controllers have an issue in which the slot's PCI
702 * INT# is NOT qualified by the IRQ routing bit (PCI reg. 3Eh
703 * bit 7). Regardless of the IRQ routing bit, if NO ISA IRQ
704 * is selected (ExCA register 03h bits 3:0, of the slot, are
705 * cleared) we will generate INT# if IREQ# is asserted. The
706 * second part is because some PC-Cards prematurally assert
707 * IREQ# before the ExCA registers are fully programmed. This
708 * in turn asserts INT# because ExCA register 03h bits 3:0
709 * (ISA IRQ Select) are not yet programmed.
711 * The fix for this issue, which will work for any controller
712 * (old or new), is to set ExCA register 03h bits 3:0 = 0001b
713 * (select IRQ1), of the slot, before turning on slot power.
714 * Selecting IRQ1 will result in INT# NOT being asserted
715 * (because IRQ1 is selected), and IRQ1 won't be asserted
716 * because our controllers don't generate IRQ1.
718 * Other, non O2Micro controllers will generate irq 1 in some
719 * situations, so we can't do this hack for everybody. Reports of
720 * keyboard controller's interrupts being suppressed occurred when
723 reg = exca_getb(&sc->exca[0], EXCA_INTR);
724 exca_putb(&sc->exca[0], EXCA_INTR, (reg & 0xf0) | 1);
729 * Restore the damage that cbb_o2micro_power_hack does to EXCA_INTR so
730 * we don't have an interrupt storm on power on. This has the efect of
731 * disabling card status change interrupts for the duration of poweron.
734 cbb_o2micro_power_hack2(struct cbb_softc *sc, uint8_t reg)
736 exca_putb(&sc->exca[0], EXCA_INTR, reg);
740 cbb_power(device_t brdev, int volts)
742 uint32_t status, sock_ctrl, mask;
743 struct cbb_softc *sc = device_get_softc(brdev);
749 sock_ctrl = cbb_get(sc, CBB_SOCKET_CONTROL);
751 sock_ctrl &= ~CBB_SOCKET_CTRL_VCCMASK;
752 switch (volts & CARD_VCCMASK) {
754 sock_ctrl |= CBB_SOCKET_CTRL_VCC_5V;
758 sock_ctrl |= CBB_SOCKET_CTRL_VCC_3V;
762 sock_ctrl |= CBB_SOCKET_CTRL_VCC_XV;
766 sock_ctrl |= CBB_SOCKET_CTRL_VCC_YV;
772 return (0); /* power NEVER changed */
776 sock_ctrl &= ~CBB_SOCKET_CTRL_VPPMASK;
777 sock_ctrl |= ((sock_ctrl >> 4) & 0x07);
779 if (cbb_get(sc, CBB_SOCKET_CONTROL) == sock_ctrl)
780 return (1); /* no change necessary */
781 DEVPRINTF((sc->dev, "cbb_power: %dV\n", volts));
782 if (volts != 0 && sc->chipset == CB_O2MICRO)
783 reg = cbb_o2micro_power_hack(sc);
786 * We have to mask the card change detect interrupt while we're
787 * messing with the power. It is allowed to bounce while we're
788 * messing with power as things settle down. In addition, we mask off
789 * the card's function interrupt by routing it via the ISA bus. This
790 * bit generally only affects 16bit cards. Some bridges allow one to
791 * set another bit to have it also affect 32bit cards. Since 32bit
792 * cards are required to be better behaved, we don't bother to get
793 * into those bridge specific features.
795 mask = cbb_get(sc, CBB_SOCKET_MASK);
796 mask |= CBB_SOCKET_MASK_POWER;
797 mask &= ~CBB_SOCKET_MASK_CD;
798 cbb_set(sc, CBB_SOCKET_MASK, mask);
799 PCI_MASK_CONFIG(brdev, CBBR_BRIDGECTRL,
800 |CBBM_BRIDGECTRL_INTR_IREQ_ISA_EN, 2);
801 cbb_set(sc, CBB_SOCKET_CONTROL, sock_ctrl);
806 while (!(cbb_get(sc, CBB_SOCKET_STATE) & CBB_STATE_POWER_CYCLE) &&
807 cnt == sc->powerintr && sane-- > 0)
808 tsleep(&sc->power_cv, 0, "cbbpcv", hz / 10);
811 device_printf(sc->dev, "power timeout, doom?\n");
815 * After the power is good, we can turn off the power interrupt.
816 * However, the PC Card standard says that we must delay turning the
817 * CD bit back on for a bit to allow for bouncyness on power down
818 * (recall that we don't wait above for a power down, since we don't
819 * get an interrupt for that). We're called either from the suspend
820 * code in which case we don't want to turn card change on again, or
821 * we're called from the card insertion code, in which case the cbb
822 * thread will turn it on for us before it waits to be woken by a
825 cbb_clrb(sc, CBB_SOCKET_MASK, CBB_SOCKET_MASK_POWER);
826 status = cbb_get(sc, CBB_SOCKET_STATE);
828 if ((status & CBB_STATE_POWER_CYCLE) == 0)
829 device_printf(sc->dev, "Power not on?\n");
831 if (status & CBB_STATE_BAD_VCC_REQ) {
832 device_printf(sc->dev, "Bad Vcc requested\n");
833 /* XXX Do we want to do something to mitigate things here? */
836 PCI_MASK_CONFIG(brdev, CBBR_BRIDGECTRL,
837 & ~CBBM_BRIDGECTRL_INTR_IREQ_ISA_EN, 2);
840 if (volts != 0 && sc->chipset == CB_O2MICRO)
841 cbb_o2micro_power_hack2(sc, reg);
846 cbb_current_voltage(device_t brdev)
848 struct cbb_softc *sc = device_get_softc(brdev);
851 ctrl = cbb_get(sc, CBB_SOCKET_CONTROL);
852 switch (ctrl & CBB_SOCKET_CTRL_VCCMASK) {
853 case CBB_SOCKET_CTRL_VCC_5V:
855 case CBB_SOCKET_CTRL_VCC_3V:
857 case CBB_SOCKET_CTRL_VCC_XV:
859 case CBB_SOCKET_CTRL_VCC_YV:
866 * detect the voltage for the card, and set it. Since the power
867 * used is the square of the voltage, lower voltages is a big win
868 * and what Windows does (and what Microsoft prefers). The MS paper
869 * also talks about preferring the CIS entry as well, but that has
870 * to be done elsewhere. We also optimize power sequencing here
871 * and don't change things if we're already powered up at a supported
874 * In addition, we power up with OE disabled. We'll set it later
875 * in the power up sequence.
878 cbb_do_power(device_t brdev)
880 struct cbb_softc *sc = device_get_softc(brdev);
881 uint32_t voltage, curpwr;
884 /* Don't enable OE (output enable) until power stable */
885 exca_clrb(&sc->exca[0], EXCA_PWRCTL, EXCA_PWRCTL_OE);
887 voltage = cbb_detect_voltage(brdev);
888 curpwr = cbb_current_voltage(brdev);
889 status = cbb_get(sc, CBB_SOCKET_STATE);
890 if ((status & CBB_STATE_POWER_CYCLE) && (voltage & curpwr))
892 /* Prefer lowest voltage supported */
893 cbb_power(brdev, CARD_OFF);
894 if (voltage & CARD_YV_CARD)
895 cbb_power(brdev, CARD_VCC(YV));
896 else if (voltage & CARD_XV_CARD)
897 cbb_power(brdev, CARD_VCC(XV));
898 else if (voltage & CARD_3V_CARD)
899 cbb_power(brdev, CARD_VCC(3));
900 else if (voltage & CARD_5V_CARD)
901 cbb_power(brdev, CARD_VCC(5));
903 device_printf(brdev, "Unknown card voltage\n");
909 /************************************************************************/
910 /* CardBus power functions */
911 /************************************************************************/
914 cbb_cardbus_reset(device_t brdev)
916 struct cbb_softc *sc = device_get_softc(brdev);
920 * 20ms is necessary for most bridges. For some reason, the Ricoh
921 * RF5C47x bridges need 400ms.
923 delay = sc->chipset == CB_RF5C47X ? 400 : 20;
925 PCI_MASK_CONFIG(brdev, CBBR_BRIDGECTRL, |CBBM_BRIDGECTRL_RESET, 2);
927 tsleep(sc, 0, "cbbP3", hz * delay / 1000);
929 /* If a card exists, unreset it! */
930 if (CBB_CARD_PRESENT(cbb_get(sc, CBB_SOCKET_STATE))) {
931 PCI_MASK_CONFIG(brdev, CBBR_BRIDGECTRL,
932 &~CBBM_BRIDGECTRL_RESET, 2);
933 tsleep(sc, 0, "cbbP3", hz * delay / 1000);
938 cbb_cardbus_power_enable_socket(device_t brdev, device_t child)
940 struct cbb_softc *sc = device_get_softc(brdev);
943 if (!CBB_CARD_PRESENT(cbb_get(sc, CBB_SOCKET_STATE)))
946 err = cbb_do_power(brdev);
949 cbb_cardbus_reset(brdev);
954 cbb_cardbus_power_disable_socket(device_t brdev, device_t child)
956 cbb_power(brdev, CARD_OFF);
957 cbb_cardbus_reset(brdev);
960 /************************************************************************/
961 /* CardBus Resource */
962 /************************************************************************/
965 cbb_cardbus_io_open(device_t brdev, int win, uint32_t start, uint32_t end)
970 if ((win < 0) || (win > 1)) {
972 "cbb_cardbus_io_open: window out of range %d\n", win));
976 basereg = win * 8 + CBBR_IOBASE0;
977 limitreg = win * 8 + CBBR_IOLIMIT0;
979 pci_write_config(brdev, basereg, start, 4);
980 pci_write_config(brdev, limitreg, end, 4);
985 cbb_cardbus_mem_open(device_t brdev, int win, uint32_t start, uint32_t end)
990 if ((win < 0) || (win > 1)) {
992 "cbb_cardbus_mem_open: window out of range %d\n", win));
996 basereg = win*8 + CBBR_MEMBASE0;
997 limitreg = win*8 + CBBR_MEMLIMIT0;
999 pci_write_config(brdev, basereg, start, 4);
1000 pci_write_config(brdev, limitreg, end, 4);
1005 * XXX The following function belongs in the pci bus layer.
1008 cbb_cardbus_auto_open(struct cbb_softc *sc, int type)
1012 struct cbb_reslist *rle;
1014 int prefetchable[2];
1017 starts[0] = starts[1] = 0xffffffff;
1018 ends[0] = ends[1] = 0;
1020 if (type == SYS_RES_MEMORY)
1021 align = CBB_MEMALIGN;
1022 else if (type == SYS_RES_IOPORT)
1023 align = CBB_IOALIGN;
1028 * This looks somewhat bogus, and doesn't seem to really respect
1029 * alignment. The alignment stuff is happening too late (it
1030 * should happen at allocation time, not activation time) and
1031 * this code looks generally to be too complex for the purpose
1034 SLIST_FOREACH(rle, &sc->rl, link) {
1035 if (rle->type != type)
1037 else if (rle->res == NULL) {
1038 device_printf(sc->dev, "WARNING: Resource not reserved? "
1039 "(type=%d, addr=%lx)\n",
1040 rle->type, rman_get_start(rle->res));
1041 } else if (!(rman_get_flags(rle->res) & RF_ACTIVE)) {
1043 } else if (starts[0] == 0xffffffff) {
1044 starts[0] = rman_get_start(rle->res);
1045 ends[0] = rman_get_end(rle->res);
1047 rman_get_flags(rle->res) & RF_PREFETCHABLE;
1048 } else if (rman_get_end(rle->res) > ends[0] &&
1049 rman_get_start(rle->res) - ends[0] <
1050 CBB_AUTO_OPEN_SMALLHOLE && prefetchable[0] ==
1051 (rman_get_flags(rle->res) & RF_PREFETCHABLE)) {
1052 ends[0] = rman_get_end(rle->res);
1053 } else if (rman_get_start(rle->res) < starts[0] &&
1054 starts[0] - rman_get_end(rle->res) <
1055 CBB_AUTO_OPEN_SMALLHOLE && prefetchable[0] ==
1056 (rman_get_flags(rle->res) & RF_PREFETCHABLE)) {
1057 starts[0] = rman_get_start(rle->res);
1058 } else if (starts[1] == 0xffffffff) {
1059 starts[1] = rman_get_start(rle->res);
1060 ends[1] = rman_get_end(rle->res);
1062 rman_get_flags(rle->res) & RF_PREFETCHABLE;
1063 } else if (rman_get_end(rle->res) > ends[1] &&
1064 rman_get_start(rle->res) - ends[1] <
1065 CBB_AUTO_OPEN_SMALLHOLE && prefetchable[1] ==
1066 (rman_get_flags(rle->res) & RF_PREFETCHABLE)) {
1067 ends[1] = rman_get_end(rle->res);
1068 } else if (rman_get_start(rle->res) < starts[1] &&
1069 starts[1] - rman_get_end(rle->res) <
1070 CBB_AUTO_OPEN_SMALLHOLE && prefetchable[1] ==
1071 (rman_get_flags(rle->res) & RF_PREFETCHABLE)) {
1072 starts[1] = rman_get_start(rle->res);
1077 diffs[0] = diffs[1] = 0xffffffff;
1078 if (rman_get_start(rle->res) > ends[0])
1079 diffs[0] = rman_get_start(rle->res) - ends[0];
1080 else if (rman_get_end(rle->res) < starts[0])
1081 diffs[0] = starts[0] - rman_get_end(rle->res);
1082 if (rman_get_start(rle->res) > ends[1])
1083 diffs[1] = rman_get_start(rle->res) - ends[1];
1084 else if (rman_get_end(rle->res) < starts[1])
1085 diffs[1] = starts[1] - rman_get_end(rle->res);
1087 win = (diffs[0] <= diffs[1])?0:1;
1088 if (rman_get_start(rle->res) > ends[win])
1089 ends[win] = rman_get_end(rle->res);
1090 else if (rman_get_end(rle->res) < starts[win])
1091 starts[win] = rman_get_start(rle->res);
1092 if (!(rman_get_flags(rle->res) & RF_PREFETCHABLE))
1093 prefetchable[win] = 0;
1096 if (starts[0] != 0xffffffff)
1097 starts[0] -= starts[0] % align;
1098 if (starts[1] != 0xffffffff)
1099 starts[1] -= starts[1] % align;
1100 if (ends[0] % align != 0)
1101 ends[0] += align - ends[0] % align - 1;
1102 if (ends[1] % align != 0)
1103 ends[1] += align - ends[1] % align - 1;
1106 if (type == SYS_RES_MEMORY) {
1107 cbb_cardbus_mem_open(sc->dev, 0, starts[0], ends[0]);
1108 cbb_cardbus_mem_open(sc->dev, 1, starts[1], ends[1]);
1109 reg = pci_read_config(sc->dev, CBBR_BRIDGECTRL, 2);
1110 reg &= ~(CBBM_BRIDGECTRL_PREFETCH_0|
1111 CBBM_BRIDGECTRL_PREFETCH_1);
1112 reg |= (prefetchable[0]?CBBM_BRIDGECTRL_PREFETCH_0:0)|
1113 (prefetchable[1]?CBBM_BRIDGECTRL_PREFETCH_1:0);
1114 pci_write_config(sc->dev, CBBR_BRIDGECTRL, reg, 2);
1115 } else if (type == SYS_RES_IOPORT) {
1116 cbb_cardbus_io_open(sc->dev, 0, starts[0], ends[0]);
1117 cbb_cardbus_io_open(sc->dev, 1, starts[1], ends[1]);
1122 cbb_cardbus_activate_resource(device_t brdev, device_t child, int type,
1123 int rid, struct resource *res)
1127 ret = BUS_ACTIVATE_RESOURCE(device_get_parent(brdev), child,
1131 cbb_cardbus_auto_open(device_get_softc(brdev), type);
1136 cbb_cardbus_deactivate_resource(device_t brdev, device_t child, int type,
1137 int rid, struct resource *res)
1141 ret = BUS_DEACTIVATE_RESOURCE(device_get_parent(brdev), child,
1145 cbb_cardbus_auto_open(device_get_softc(brdev), type);
1149 static struct resource *
1150 cbb_cardbus_alloc_resource(device_t brdev, device_t child, int type,
1151 int *rid, u_long start, u_long end, u_long count, u_int flags)
1153 struct cbb_softc *sc = device_get_softc(brdev);
1155 struct resource *res;
1160 tmp = rman_get_start(sc->irq_res);
1161 if (start > tmp || end < tmp || count != 1) {
1162 device_printf(child, "requested interrupt %ld-%ld,"
1163 "count = %ld not supported by cbb\n",
1168 flags |= RF_SHAREABLE;
1170 case SYS_RES_IOPORT:
1171 if (start <= cbb_start_32_io)
1172 start = cbb_start_32_io;
1176 case SYS_RES_MEMORY:
1177 if (start <= cbb_start_mem)
1178 start = cbb_start_mem;
1181 if (count < CBB_MEMALIGN)
1182 align = CBB_MEMALIGN;
1185 if (align > (1 << RF_ALIGNMENT(flags)))
1186 flags = (flags & ~RF_ALIGNMENT_MASK) |
1187 rman_make_alignment_flags(align);
1191 res = BUS_ALLOC_RESOURCE(device_get_parent(brdev), child, type, rid,
1192 start, end, count, flags & ~RF_ACTIVE);
1194 kprintf("cbb alloc res fail\n");
1197 cbb_insert_res(sc, res, type, *rid);
1198 if (flags & RF_ACTIVE)
1199 if (bus_activate_resource(child, type, *rid, res) != 0) {
1200 bus_release_resource(child, type, *rid, res);
1208 cbb_cardbus_release_resource(device_t brdev, device_t child, int type,
1209 int rid, struct resource *res)
1211 struct cbb_softc *sc = device_get_softc(brdev);
1214 if (rman_get_flags(res) & RF_ACTIVE) {
1215 error = bus_deactivate_resource(child, type, rid, res);
1219 cbb_remove_res(sc, res);
1220 return (BUS_RELEASE_RESOURCE(device_get_parent(brdev), child,
1224 /************************************************************************/
1225 /* PC Card Power Functions */
1226 /************************************************************************/
1229 cbb_pcic_power_enable_socket(device_t brdev, device_t child)
1231 struct cbb_softc *sc = device_get_softc(brdev);
1234 DPRINTF(("cbb_pcic_socket_enable:\n"));
1236 /* power down/up the socket to reset */
1237 err = cbb_do_power(brdev);
1240 exca_reset(&sc->exca[0], child);
1246 cbb_pcic_power_disable_socket(device_t brdev, device_t child)
1248 struct cbb_softc *sc = device_get_softc(brdev);
1250 DPRINTF(("cbb_pcic_socket_disable\n"));
1252 /* reset signal asserting... */
1253 exca_clrb(&sc->exca[0], EXCA_INTR, EXCA_INTR_RESET);
1254 tsleep(sc, 0, "cbbP1", hz / 100);
1256 /* power down the socket */
1257 exca_clrb(&sc->exca[0], EXCA_PWRCTL, EXCA_PWRCTL_OE);
1258 cbb_power(brdev, CARD_OFF);
1260 /* wait 300ms until power fails (Tpf). */
1261 tsleep(sc, 0, "cbbP1", hz * 300 / 1000);
1264 /************************************************************************/
1266 /************************************************************************/
1269 cbb_power_enable_socket(device_t brdev, device_t child)
1271 struct cbb_softc *sc = device_get_softc(brdev);
1273 if (sc->flags & CBB_16BIT_CARD)
1274 return (cbb_pcic_power_enable_socket(brdev, child));
1276 return (cbb_cardbus_power_enable_socket(brdev, child));
1280 cbb_power_disable_socket(device_t brdev, device_t child)
1282 struct cbb_softc *sc = device_get_softc(brdev);
1283 if (sc->flags & CBB_16BIT_CARD)
1284 cbb_pcic_power_disable_socket(brdev, child);
1286 cbb_cardbus_power_disable_socket(brdev, child);
1290 cbb_pcic_activate_resource(device_t brdev, device_t child, int type, int rid,
1291 struct resource *res)
1293 struct cbb_softc *sc = device_get_softc(brdev);
1294 return (exca_activate_resource(&sc->exca[0], child, type, rid, res));
1298 cbb_pcic_deactivate_resource(device_t brdev, device_t child, int type,
1299 int rid, struct resource *res)
1301 struct cbb_softc *sc = device_get_softc(brdev);
1302 return (exca_deactivate_resource(&sc->exca[0], child, type, rid, res));
1305 static struct resource *
1306 cbb_pcic_alloc_resource(device_t brdev, device_t child, int type, int *rid,
1307 u_long start, u_long end, u_long count, u_int flags)
1309 struct resource *res = NULL;
1310 struct cbb_softc *sc = device_get_softc(brdev);
1315 case SYS_RES_MEMORY:
1316 if (start < cbb_start_mem)
1317 start = cbb_start_mem;
1320 if (count < CBB_MEMALIGN)
1321 align = CBB_MEMALIGN;
1324 if (align > (1 << RF_ALIGNMENT(flags)))
1325 flags = (flags & ~RF_ALIGNMENT_MASK) |
1326 rman_make_alignment_flags(align);
1328 case SYS_RES_IOPORT:
1329 if (start < cbb_start_16_io)
1330 start = cbb_start_16_io;
1335 tmp = rman_get_start(sc->irq_res);
1336 if (start > tmp || end < tmp || count != 1) {
1337 device_printf(child, "requested interrupt %ld-%ld,"
1338 "count = %ld not supported by cbb\n",
1342 flags |= RF_SHAREABLE;
1343 start = end = rman_get_start(sc->irq_res);
1346 res = BUS_ALLOC_RESOURCE(device_get_parent(brdev), child, type, rid,
1347 start, end, count, flags & ~RF_ACTIVE);
1350 cbb_insert_res(sc, res, type, *rid);
1351 if (flags & RF_ACTIVE) {
1352 if (bus_activate_resource(child, type, *rid, res) != 0) {
1353 bus_release_resource(child, type, *rid, res);
1362 cbb_pcic_release_resource(device_t brdev, device_t child, int type,
1363 int rid, struct resource *res)
1365 struct cbb_softc *sc = device_get_softc(brdev);
1368 if (rman_get_flags(res) & RF_ACTIVE) {
1369 error = bus_deactivate_resource(child, type, rid, res);
1373 cbb_remove_res(sc, res);
1374 return (BUS_RELEASE_RESOURCE(device_get_parent(brdev), child,
1378 /************************************************************************/
1379 /* PC Card methods */
1380 /************************************************************************/
1383 cbb_pcic_set_res_flags(device_t brdev, device_t child, int type, int rid,
1386 struct cbb_softc *sc = device_get_softc(brdev);
1387 struct resource *res;
1389 if (type != SYS_RES_MEMORY)
1391 res = cbb_find_res(sc, type, rid);
1393 device_printf(brdev,
1394 "set_res_flags: specified rid not found\n");
1397 return (exca_mem_set_flags(&sc->exca[0], res, flags));
1401 cbb_pcic_set_memory_offset(device_t brdev, device_t child, int rid,
1402 uint32_t cardaddr, uint32_t *deltap)
1404 struct cbb_softc *sc = device_get_softc(brdev);
1405 struct resource *res;
1407 res = cbb_find_res(sc, SYS_RES_MEMORY, rid);
1409 device_printf(brdev,
1410 "set_memory_offset: specified rid not found\n");
1413 return (exca_mem_set_offset(&sc->exca[0], res, cardaddr, deltap));
1416 /************************************************************************/
1418 /************************************************************************/
1422 cbb_activate_resource(device_t brdev, device_t child, int type, int rid,
1425 struct cbb_softc *sc = device_get_softc(brdev);
1427 if (sc->flags & CBB_16BIT_CARD)
1428 return (cbb_pcic_activate_resource(brdev, child, type, rid, r));
1430 return (cbb_cardbus_activate_resource(brdev, child, type, rid,
1435 cbb_deactivate_resource(device_t brdev, device_t child, int type,
1436 int rid, struct resource *r)
1438 struct cbb_softc *sc = device_get_softc(brdev);
1440 if (sc->flags & CBB_16BIT_CARD)
1441 return (cbb_pcic_deactivate_resource(brdev, child, type,
1444 return (cbb_cardbus_deactivate_resource(brdev, child, type,
1449 cbb_alloc_resource(device_t brdev, device_t child, int type, int *rid,
1450 u_long start, u_long end, u_long count, u_int flags)
1452 struct cbb_softc *sc = device_get_softc(brdev);
1454 if (sc->flags & CBB_16BIT_CARD)
1455 return (cbb_pcic_alloc_resource(brdev, child, type, rid,
1456 start, end, count, flags));
1458 return (cbb_cardbus_alloc_resource(brdev, child, type, rid,
1459 start, end, count, flags));
1463 cbb_release_resource(device_t brdev, device_t child, int type, int rid,
1466 struct cbb_softc *sc = device_get_softc(brdev);
1468 if (sc->flags & CBB_16BIT_CARD)
1469 return (cbb_pcic_release_resource(brdev, child, type,
1472 return (cbb_cardbus_release_resource(brdev, child, type,
1477 cbb_read_ivar(device_t brdev, device_t child, int which, uintptr_t *result)
1479 struct cbb_softc *sc = device_get_softc(brdev);
1482 case PCIB_IVAR_DOMAIN:
1483 *result = sc->domain;
1486 *result = sc->secbus;
1493 cbb_write_ivar(device_t brdev, device_t child, int which, uintptr_t value)
1495 struct cbb_softc *sc = device_get_softc(brdev);
1498 case PCIB_IVAR_DOMAIN:
1507 /************************************************************************/
1508 /* PCI compat methods */
1509 /************************************************************************/
1512 cbb_maxslots(device_t brdev)
1518 cbb_read_config(device_t brdev, int b, int s, int f, int reg, int width)
1523 * Pass through to the next ppb up the chain (i.e. our grandparent).
1525 rv = PCIB_READ_CONFIG(device_get_parent(device_get_parent(brdev)),
1526 b, s, f, reg, width);
1531 cbb_write_config(device_t brdev, int b, int s, int f, int reg, uint32_t val,
1535 * Pass through to the next ppb up the chain (i.e. our grandparent).
1537 PCIB_WRITE_CONFIG(device_get_parent(device_get_parent(brdev)),
1538 b, s, f, reg, val, width);
1542 cbb_suspend(device_t self)
1545 struct cbb_softc *sc = device_get_softc(self);
1547 cbb_set(sc, CBB_SOCKET_MASK, 0); /* Quiet hardware */
1548 bus_teardown_intr(self, sc->irq_res, sc->intrhand);
1549 sc->flags &= ~CBB_CARD_OK; /* Card is bogus now */
1550 error = bus_generic_suspend(self);
1555 cbb_resume(device_t self)
1558 struct cbb_softc *sc = (struct cbb_softc *)device_get_softc(self);
1562 * Some BIOSes will not save the BARs for the pci chips, so we
1563 * must do it ourselves. If the BAR is reset to 0 for an I/O
1564 * device, it will read back as 0x1, so no explicit test for
1565 * memory devices are needed.
1567 * Note: The PCI bus code should do this automatically for us on
1568 * suspend/resume, but until it does, we have to cope.
1570 pci_write_config(self, CBBR_SOCKBASE, rman_get_start(sc->base_res), 4);
1571 DEVPRINTF((self, "PCI Memory allocated: %08lx\n",
1572 rman_get_start(sc->base_res)));
1576 /* reset interrupt -- Do we really need to do this? */
1577 tmp = cbb_get(sc, CBB_SOCKET_EVENT);
1578 cbb_set(sc, CBB_SOCKET_EVENT, tmp);
1580 /* re-establish the interrupt. */
1581 if (bus_setup_intr(self, sc->irq_res, INTR_MPSAFE, cbb_intr, sc,
1582 &sc->intrhand, NULL)) {
1583 device_printf(self, "couldn't re-establish interrupt");
1584 bus_release_resource(self, SYS_RES_IRQ, 0, sc->irq_res);
1585 bus_release_resource(self, SYS_RES_MEMORY, CBBR_SOCKBASE,
1588 sc->base_res = NULL;
1592 /* CSC Interrupt: Card detect interrupt on */
1593 cbb_setb(sc, CBB_SOCKET_MASK, CBB_SOCKET_MASK_CD);
1595 /* Signal the thread to wakeup. */
1596 wakeup_one(&sc->generic_cv);
1598 error = bus_generic_resume(self);
1604 cbb_child_present(device_t self)
1606 struct cbb_softc *sc = (struct cbb_softc *)device_get_softc(self);
1609 sockstate = cbb_get(sc, CBB_SOCKET_STATE);
1610 return (CBB_CARD_PRESENT(sockstate) &&
1611 (sc->flags & CBB_CARD_OK) == CBB_CARD_OK);