diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/pci/pccbb.c | 92 | ||||
-rw-r--r-- | sys/dev/pci/pccbbreg.h | 5 | ||||
-rw-r--r-- | sys/dev/pci/pccbbvar.h | 5 |
3 files changed, 89 insertions, 13 deletions
diff --git a/sys/dev/pci/pccbb.c b/sys/dev/pci/pccbb.c index c337b770608..46671634288 100644 --- a/sys/dev/pci/pccbb.c +++ b/sys/dev/pci/pccbb.c @@ -1,5 +1,5 @@ -/* $OpenBSD: pccbb.c,v 1.4 2000/07/06 06:03:01 aaron Exp $ */ -/* $NetBSD: pccbb.c,v 1.37 2000/03/23 07:01:40 thorpej Exp $ */ +/* $OpenBSD: pccbb.c,v 1.5 2000/07/06 19:49:10 aaron Exp $ */ +/* $NetBSD: pccbb.c,v 1.42 2000/06/16 23:41:35 cgd Exp $ */ /* * Copyright (c) 1998, 1999 and 2000 @@ -345,7 +345,7 @@ cb_chipset(pci_id, flagp) /* Loop over except the last default entry. */ for (yc = yc_chipsets; yc < yc_chipsets + sizeof(yc_chipsets) / sizeof(yc_chipsets[0]) - 1; yc++) - if (pci_id != yc->yc_id) + if (pci_id == yc->yc_id) break; if (flagp != NULL) @@ -562,6 +562,10 @@ pccbb_pci_callback(self) base_memt = sc->sc_base_memt; /* socket regs memory tag */ base_memh = sc->sc_base_memh; /* socket regs memory handle */ + /* clear data structure for child device interrupt handlers */ + sc->sc_pil = NULL; + sc->sc_pil_intr_enable = 1; + /* Map and establish the interrupt. */ if (pci_intr_map(pc, sc->sc_intrtag, sc->sc_intrpin, sc->sc_intrline, &ih)) { @@ -569,6 +573,11 @@ pccbb_pci_callback(self) return; } intrstr = pci_intr_string(pc, ih); + + /* + * XXX pccbbintr should be called under the priority lower + * than any other hard interrputs. + */ sc->sc_ih = pci_intr_establish(pc, ih, IPL_BIO, pccbbintr, sc, sc->sc_dev.dv_xname); @@ -893,7 +902,11 @@ pccbbintr(arg) if (sockevent == 0) { /* This intr is not for me: it may be for my child devices. */ - return (pccbbintr_function(sc)); + if (sc->sc_pil_intr_enable) { + return pccbbintr_function(sc); + } else { + return 0; + } } if (sockevent & CB_SOCKET_EVENT_CD) { @@ -955,9 +968,49 @@ pccbbintr_function(sc) { int retval = 0, val; struct pccbb_intrhand_list *pil; - + int s, splchanged; + for (pil = sc->sc_pil; pil != NULL; pil = pil->pil_next) { - val = (*pil->pil_func) (pil->pil_arg); + /* + * XXX priority change. gross. I use if-else + * sentense instead of switch-case sentense because of + * avoiding duplicate case value error. More than one + * IPL_XXX use same value. It depends on + * implimentation. + */ + splchanged = 1; +#if 0 + if (pil->pil_level == IPL_SERIAL) { + s = splserial(); + } else if (pil->pil_level == IPL_HIGH) { +#endif + if (pil->pil_level == IPL_HIGH) { + s = splhigh(); + } else if (pil->pil_level == IPL_CLOCK) { + s = splclock(); + } else if (pil->pil_level == IPL_AUDIO) { + s = splaudio(); + } else if (pil->pil_level == IPL_IMP) { + s = splimp(); + } else if (pil->pil_level == IPL_TTY) { + s = spltty(); +#if 0 + } else if (pil->pil_level == IPL_SOFTSERIAL) { + s = splsoftserial(); +#endif + } else if (pil->pil_level == IPL_NET) { + s = splnet(); + } else { + splchanged = 0; + /* XXX: ih lower than IPL_BIO runs w/ IPL_BIO. */ + } + + val = (*pil->pil_func)(pil->pil_arg); + + if (splchanged != 0) { + splx(s); + } + retval = retval == 1 ? 1 : retval == 0 ? val : val != 0 ? val : retval; } @@ -1310,12 +1363,14 @@ cb_reset(sc) (sc->sc_chipset == CB_RX5C47X ? 400 * 1000 : 40 * 1000); u_int32_t bcr = pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_BCR_INTR); - bcr |= (0x40 << 16); /* Reset bit Assert (bit 6 at 0x3E) */ + /* Reset bit Assert (bit 6 at 0x3E) */ + bcr |= CB_BCR_RESET_ENABLE; pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_BCR_INTR, bcr); delay(reset_duration); if (CBB_CARDEXIST & sc->sc_flags) { /* A card exists. Reset it! */ - bcr &= ~(0x40 << 16); /* Reset bit Deassert (bit 6 at 0x3E) */ + /* Reset bit Deassert (bit 6 at 0x3E) */ + bcr &= ~CB_BCR_RESET_ENABLE; pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_BCR_INTR, bcr); delay(reset_duration); } @@ -1530,7 +1585,7 @@ pccbb_mem_close(ct, win) * order not to call the interrupt handlers of child devices when * a card-deletion interrupt occurs. * - * The arguments irq and level are not used. + * The arguments irq is not used because pccbb selects intr vector. */ void * pccbb_cb_intr_establish(ct, irq, level, func, arg) @@ -1617,6 +1672,7 @@ pccbb_intr_establish(sc, irq, level, func, arg) newpil->pil_func = func; newpil->pil_arg = arg; + newpil->pil_level = level; newpil->pil_next = NULL; if (sc->sc_pil == NULL) { @@ -3073,6 +3129,18 @@ pccbb_powerhook(why, arg) DPRINTF(("%s: power: why %d\n", sc->sc_dev.dv_xname, why)); + if (why == PWR_SUSPEND || why == PWR_STANDBY) { + DPRINTF(("%s: power: why %d stopping intr\n", + sc->sc_dev.dv_xname, why)); + if (sc->sc_pil_intr_enable) { + (void)pccbbintr_function(sc); + } + sc->sc_pil_intr_enable = 0; + + /* ToDo: deactivate or suspend child devices */ + + } + if (why == PWR_RESUME) { /* CSC Interrupt: Card detect interrupt on */ reg = bus_space_read_4(base_memt, base_memh, CB_SOCKET_MASK); @@ -3089,5 +3157,11 @@ pccbb_powerhook(why, arg) * insert). how can we detect such situation? */ (void)pccbbintr(sc); + + sc->sc_pil_intr_enable = 1; + DPRINTF(("%s: power: RESUME enabling intr\n", + sc->sc_dev.dv_xname)); + + /* ToDo: activate or wakeup child devices */ } } diff --git a/sys/dev/pci/pccbbreg.h b/sys/dev/pci/pccbbreg.h index d027482a875..fc2855e3c49 100644 --- a/sys/dev/pci/pccbbreg.h +++ b/sys/dev/pci/pccbbreg.h @@ -1,5 +1,5 @@ -/* $OpenBSD: pccbbreg.h,v 1.1 2000/04/08 05:50:51 aaron Exp $ */ -/* $NetBSD: pccbbreg.h,v 1.4 2000/01/13 08:46:46 joda Exp $ */ +/* $OpenBSD: pccbbreg.h,v 1.2 2000/07/06 19:49:11 aaron Exp $ */ +/* $NetBSD: pccbbreg.h,v 1.5 2000/06/07 09:02:47 haya Exp $ */ /* * Copyright (c) 1999 HAYAKAWA Koichi. All rights reserved. * @@ -76,6 +76,7 @@ /* PCI_BCR_INTR bits for generic PCI-CardBus bridge */ +#define CB_BCR_RESET_ENABLE 0x00400000 #define CB_BCR_INTR_IREQ_ENABLE 0x00800000 #define CB_BCR_PREFETCH_MEMWIN0 0x01000000 #define CB_BCR_PREFETCH_MEMWIN1 0x02000000 diff --git a/sys/dev/pci/pccbbvar.h b/sys/dev/pci/pccbbvar.h index 089f1f5b11c..e582eab3a93 100644 --- a/sys/dev/pci/pccbbvar.h +++ b/sys/dev/pci/pccbbvar.h @@ -1,5 +1,5 @@ -/* $OpenBSD: pccbbvar.h,v 1.1 2000/04/08 05:50:51 aaron Exp $ */ -/* $NetBSD: pccbbvar.h,v 1.12 2000/03/23 07:01:40 thorpej Exp $ */ +/* $OpenBSD: pccbbvar.h,v 1.2 2000/07/06 19:49:11 aaron Exp $ */ +/* $NetBSD: pccbbvar.h,v 1.13 2000/06/08 10:28:29 haya Exp $ */ /* * Copyright (c) 1999 HAYAKAWA Koichi. All rights reserved. * @@ -168,6 +168,7 @@ struct pccbb_softc { struct pccbb_intrhand_list { int (*pil_func) __P((void *)); void *pil_arg; + int pil_level; struct pccbb_intrhand_list *pil_next; }; |