diff options
-rw-r--r-- | sys/dev/pccbb/pccbb.c | 57 |
1 files changed, 47 insertions, 10 deletions
diff --git a/sys/dev/pccbb/pccbb.c b/sys/dev/pccbb/pccbb.c index f0178e7..81f848a 100644 --- a/sys/dev/pccbb/pccbb.c +++ b/sys/dev/pccbb/pccbb.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002 M. Warner Losh. + * Copyright (c) 2002-2003 M. Warner Losh. * Copyright (c) 2000,2001 Jonathan Chen. * All rights reserved. * @@ -399,6 +399,39 @@ cbb_probe(device_t brdev) } +/* + * Disable function interrupts by telling the bridge to generate IRQ1 + * interrupts. These interrupts aren't really generated by the chip, since + * IRQ1 is reserved. Some chipsets assert INTA# inappropriately during + * initialization, so this helps to work around the problem. + */ +static void +cbb_disable_func_intr(struct cbb_softc *sc) +{ + uint8_t reg; + + reg = (exca_getb(&sc->exca, EXCA_INTR) & ~EXCA_INTR_IRQ_MASK) | + EXCA_INTR_IRQ_RESERVED1; + exca_putb(&sc->exca, EXCA_INTR, reg); +} + +/* + * Enable function interrupts. We turn on function interrupts when the card + * requests an interrupt. The PCMCIA standard says that we should set + * the lower 4 bits to 0 to route via PCI. Note: we call this for both + * CardBus and R2 (PC Card) cases, but it should have no effect on CardBus + * cards. + */ +static void +cbb_enable_func_intr(struct cbb_softc *sc) +{ + uint8_t reg; + + reg = (exca_getb(&sc->exca, EXCA_INTR) & ~EXCA_INTR_IRQ_MASK) | + EXCA_INTR_IRQ_NONE; + exca_putb(&sc->exca, EXCA_INTR, reg); +} + static void cbb_chipinit(struct cbb_softc *sc) { @@ -566,14 +599,16 @@ cbb_chipinit(struct cbb_softc *sc) } /* - * Need to tell ExCA registers to route via PCI interrupts. There - * are two ways to do this. Once is to set INTR_ENABLE and the - * other is to set CSC to 0. Since both methods are mutually - * compatible, we do both. + * Need to tell ExCA registers to CSC interrupts route via PCI + * interrupts. There are two ways to do this. Once is to set + * INTR_ENABLE and the other is to set CSC to 0. Since both + * methods are mutually compatible, we do both. */ exca_putb(&sc->exca, EXCA_INTR, EXCA_INTR_ENABLE); exca_putb(&sc->exca, EXCA_CSC_INTR, 0); + cbb_disable_func_intr(sc); + /* close all memory and io windows */ pci_write_config(sc->dev, CBBR_MEMBASE0, 0xffffffff, 4); pci_write_config(sc->dev, CBBR_MEMLIMIT0, 0, 4); @@ -869,6 +904,7 @@ cbb_setup_intr(device_t dev, device_t child, struct resource *irq, ih->arg = arg; ih->flags = flags & INTR_MPSAFE; STAILQ_INSERT_TAIL(&sc->intr_handlers, ih, entries); + cbb_enable_func_intr(sc); /* * XXX need to turn on ISA interrupts, if we ever support them, but * XXX for now that's all we need to do. @@ -952,7 +988,10 @@ cbb_event_thread(void *arg) mtx_lock(&Giant); status = cbb_get(sc, CBB_SOCKET_STATE); DPRINTF(("Status is 0x%x\n", status)); - if (status & CBB_STATE_NOT_A_CARD) { + if ((status & CBB_STATE_CD) != 0) { + not_a_card = 0; /* We know card type */ + cbb_removal(sc); + } else if (status & CBB_STATE_NOT_A_CARD) { /* * Up to 20 times, try to rescan the card when we * see NOT_A_CARD. @@ -967,10 +1006,7 @@ cbb_event_thread(void *arg) } } else { not_a_card = 0; /* We know card type */ - if ((status & CBB_STATE_CD) == 0) - cbb_insert(sc); - else - cbb_removal(sc); + cbb_insert(sc); } mtx_unlock(&Giant); @@ -1092,6 +1128,7 @@ cbb_intr(void *arg) cbb_clrb(sc, CBB_SOCKET_MASK, CBB_SOCKET_MASK_CD); mtx_lock(&sc->mtx); sc->flags &= ~CBB_CARD_OK; + cbb_disable_func_intr(sc); DPRINTF(("Waking up thread\n")); cv_signal(&sc->cv); mtx_unlock(&sc->mtx); |