Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/pci Pccbb manages interrupt handlers by itself for i...
details: https://anonhg.NetBSD.org/src/rev/7f703bfa4751
branches: trunk
changeset: 481333:7f703bfa4751
user: haya <haya%NetBSD.org@localhost>
date: Wed Jan 26 09:02:41 2000 +0000
description:
Pccbb manages interrupt handlers by itself for its child device.
diffstat:
sys/dev/pci/pccbb.c | 158 +++++++++++++++++++++++++++++++++++++-----------
sys/dev/pci/pccbbvar.h | 18 +++++-
2 files changed, 139 insertions(+), 37 deletions(-)
diffs (248 lines):
diff -r 5ee586e16fa4 -r 7f703bfa4751 sys/dev/pci/pccbb.c
--- a/sys/dev/pci/pccbb.c Wed Jan 26 07:50:33 2000 +0000
+++ b/sys/dev/pci/pccbb.c Wed Jan 26 09:02:41 2000 +0000
@@ -1,7 +1,8 @@
-/* $NetBSD: pccbb.c,v 1.20 2000/01/25 14:34:24 joda Exp $ */
+/* $NetBSD: pccbb.c,v 1.21 2000/01/26 09:02:41 haya Exp $ */
/*
- * Copyright (c) 1998 and 1999 HAYAKAWA Koichi. All rights reserved.
+ * Copyright (c) 1998, 1999 and 2000
+ * HAYAKAWA Koichi. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -98,6 +99,7 @@
void pccbbattach __P((struct device *, struct device *, void *));
int pccbbintr __P((void *));
static void pci113x_insert __P((void *));
+static int pccbbintr_function __P((struct pccbb_softc *));
static int pccbb_detect_card __P((struct pccbb_softc *));
@@ -920,7 +922,8 @@
sockevent = bus_space_read_4(memt, memh, CB_SOCKET_EVENT);
if (0 == sockevent) { /* not for me */
- return 0;
+ /* This interrupt is not for me: it may be for my child devices. */
+ return pccbbintr_function(sc);
} else {
bus_space_write_4(memt, memh, CB_SOCKET_EVENT, sockevent); /* reset bit */
}
@@ -967,6 +970,33 @@
+/*
+ * static int pccbbintr_function(struct pccbb_softc *sc)
+ *
+ * This function calls each interrupt handler registered at the
+ * bridge. The interrupt handlers are called in registerd order.
+ */
+static int
+pccbbintr_function(sc)
+ struct pccbb_softc *sc;
+{
+ int retval = 0, val;
+ struct pccbb_intrhand_list *pil;
+
+ for (pil = sc->sc_pil; pil != NULL; pil = pil->pil_next) {
+ val = (*pil->pil_func)(pil->pil_arg);
+ retval = retval == 1 ? 1 :
+ retval == 0 ? val :
+ val != 0 ? val : retval;
+ }
+
+ return retval;
+}
+
+
+
+
+
static void
pci113x_insert(arg)
void *arg;
@@ -1538,53 +1568,109 @@
+/*
+ * static void *pccbb_intr_establish(cardbus_chipset_tag_t ct,
+ * int irq,
+ * int level,
+ * int (* func) __P((void *)),
+ * void *arg)
+ *
+ * This function registers an interrupt handler at the bridge, in
+ * order not to call the interrput handlers of child devices when
+ * a card-deletion interrput occurs.
+ *
+ * The arguments irq and level are not used.
+ */
static void *
pccbb_intr_establish(ct, irq, level, func, arg)
- cardbus_chipset_tag_t ct;
- int irq, level;
- int (* func) __P((void *));
- void *arg;
+ cardbus_chipset_tag_t ct;
+ int irq, level;
+ int (* func) __P((void *));
+ void *arg;
{
- struct pccbb_softc *sc = (struct pccbb_softc *)ct;
-
- switch (sc->sc_chipset) {
- case CB_TI113X:
- {
- pcireg_t cbctrl = pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_CBCTRL);
- cbctrl |= PCI113X_CBCTRL_PCI_INTR; /* functional intr enabled */
- pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_CBCTRL, cbctrl);
+ struct pccbb_softc *sc = (struct pccbb_softc *)ct;
+ struct pccbb_intrhand_list *pil, *newpil;
+
+ if (sc->sc_pil == NULL) {
+ /* initialise bridge intr routing */
+
+ switch (sc->sc_chipset) {
+ case CB_TI113X:
+ {
+ pcireg_t cbctrl = pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_CBCTRL);
+ cbctrl |= PCI113X_CBCTRL_PCI_INTR; /* functional intr enabled */
+ pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_CBCTRL, cbctrl);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ /*
+ * Allocate a room for interrut handler structure.
+ */
+ if (NULL == (newpil = (struct pccbb_intrhand_list *)malloc(sizeof(struct pccbb_intrhand_list), M_DEVBUF, M_WAITOK))) {
+ return NULL;
}
- break;
- default:
- break;
- }
-
- return pci_intr_establish(sc->sc_pc, irq, level, func, arg);
+
+ newpil->pil_func = func;
+ newpil->pil_arg = arg;
+ newpil->pil_next = NULL;
+
+ if (sc->sc_pil == NULL) {
+ sc->sc_pil = newpil;
+ } else {
+ for (pil = sc->sc_pil; pil->pil_next != NULL; pil = pil->pil_next);
+ pil->pil_next = newpil;
+ }
+
+ return newpil;
}
+/*
+ * static void *pccbb_intr_disestablish(cardbus_chipset_tag_t ct,
+ * void *ih)
+ *
+ * This function removes an interrupt handler pointed by ih.
+ */
static void
pccbb_intr_disestablish(ct, ih)
- cardbus_chipset_tag_t ct;
- void *ih;
+ cardbus_chipset_tag_t ct;
+ void *ih;
{
- struct pccbb_softc *sc = (struct pccbb_softc *)ct;
+ struct pccbb_softc *sc = (struct pccbb_softc *)ct;
+ struct pccbb_intrhand_list *pil, **pil_prev;
+
+ pil_prev = &sc->sc_pil;
- switch (sc->sc_chipset) {
- case CB_TI113X:
- {
- pcireg_t cbctrl = pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_CBCTRL);
- cbctrl &= ~PCI113X_CBCTRL_PCI_INTR; /* functional intr disabled */
- pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_CBCTRL, cbctrl);
+ for (pil = sc->sc_pil; pil != NULL; pil = pil->pil_next) {
+ if (pil == ih) {
+ *pil_prev = pil->pil_next;
+ free(pil, M_DEVBUF);
+ break;
+ }
+ pil_prev = &pil->pil_next;
}
- break;
- default:
- break;
- }
-
- pci_intr_disestablish(sc->sc_pc, ih);
+
+ if (sc->sc_pil == NULL) {
+ /* No interrupt handlers */
+
+ switch (sc->sc_chipset) {
+ case CB_TI113X:
+ {
+ pcireg_t cbctrl = pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_CBCTRL);
+ cbctrl &= ~PCI113X_CBCTRL_PCI_INTR; /* functional intr disabled */
+ pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_CBCTRL, cbctrl);
+ break;
+ }
+ default:
+ break;
+ }
+ }
}
diff -r 5ee586e16fa4 -r 7f703bfa4751 sys/dev/pci/pccbbvar.h
--- a/sys/dev/pci/pccbbvar.h Wed Jan 26 07:50:33 2000 +0000
+++ b/sys/dev/pci/pccbbvar.h Wed Jan 26 09:02:41 2000 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: pccbbvar.h,v 1.4 1999/11/01 08:58:45 haya Exp $ */
+/* $NetBSD: pccbbvar.h,v 1.5 2000/01/26 09:02:41 haya Exp $ */
/*
* Copyright (c) 1999 HAYAKAWA Koichi. All rights reserved.
*
@@ -63,6 +63,7 @@
#endif
struct pccbb_softc;
+struct pccbb_intrhand_list;
#if pccard
struct cbb_pcmcia_softc {
@@ -170,6 +171,21 @@
struct proc *sc_event_thread;
SIMPLEQ_HEAD(, pcic_event) sc_events;
+
+ /* interrupt handler list on the bridge */
+ struct pccbb_intrhand_list *sc_pil;
+};
+
+
+/*
+ * struct pccbb_intrhand_list holds interrupt handler and argument for
+ * child devices.
+ */
+
+struct pccbb_intrhand_list {
+ int (*pil_func) __P((void *));
+ void *pil_arg;
+ struct pccbb_intrhand_list *pil_next;
};
#endif /* _DEV_PCI_PCCBBREG_H_ */
Home |
Main Index |
Thread Index |
Old Index