summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2003-02-17 23:06:32 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2003-02-17 23:06:32 +0000
commit137a0f31e269263744dfab2e91fc44774923a5bf (patch)
tree7ffdfe312fb6ab3498f4519757d9ae01fdf846e6
parentbecfa62f65c6f332b9a1a2c794cee39d310b7458 (diff)
Since the ps/2 input ports show up as two different devices, with the same
irq, but hppa has no generic shared interrupt code, we need to make sure that gsckbc devices using the same irq know each other, and will pass the interrupt notification to each other. This allow a mouse and a keyboard to work together...
-rw-r--r--sys/arch/hppa/gsc/gsckbc.c62
1 files changed, 56 insertions, 6 deletions
diff --git a/sys/arch/hppa/gsc/gsckbc.c b/sys/arch/hppa/gsc/gsckbc.c
index 1e145b2760c..d814c8e3897 100644
--- a/sys/arch/hppa/gsc/gsckbc.c
+++ b/sys/arch/hppa/gsc/gsckbc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: gsckbc.c,v 1.2 2003/02/15 23:42:45 miod Exp $ */
+/* $OpenBSD: gsckbc.c,v 1.3 2003/02/17 23:06:31 miod Exp $ */
/*
* Copyright (c) 2003, Miodrag Vallat.
* All rights reserved.
@@ -99,6 +99,8 @@ struct gsckbc_softc {
int sc_irq;
void *sc_ih;
int sc_type;
+
+ struct device *sc_sibling;
};
struct cfattach gsckbc_ca = {
@@ -156,6 +158,7 @@ void pckbc_cleanqueue(struct pckbc_slotdata *);
void pckbc_cleanup(void *);
int pckbc_cmdresponse(struct pckbc_internal *, pckbc_slot_t, u_char);
void pckbc_start(struct pckbc_internal *, pckbc_slot_t);
+int gsckbcintr(struct gsckbc_softc *);
const char *pckbc_slot_names[] = { "kbd", "mouse" };
@@ -360,9 +363,10 @@ gsckbc_attach(struct device *parent, struct device *self, void *aux)
struct gsckbc_softc *gsc = (void *)self;
struct pckbc_softc *sc = &gsc->sc_pckbc;
struct pckbc_internal *t;
+ struct device *tdev;
bus_space_tag_t iot;
bus_space_handle_t ioh;
- int ident;
+ int ident, dev;
iot = ga->ga_ca.ca_iot;
gsc->sc_irq = ga->ga_ca.ca_irq;
@@ -395,6 +399,35 @@ gsckbc_attach(struct device *parent, struct device *self, void *aux)
timeout_set(&t->t_cleanup, pckbc_cleanup, t);
sc->id = t;
+ /*
+ * Several gsckbc attachments might share the same interrupt.
+ * Try to find existing gsckbc devices, and associate them
+ * together. We do not expect more than two gsckbc devices to
+ * share an interrupt.
+ */
+ for (dev = 0; dev < gsckbc_cd.cd_ndevs; dev++) {
+ tdev = gsckbc_cd.cd_devs[dev];
+ if (tdev != NULL && tdev != self &&
+ tdev->dv_parent == parent &&
+ strcmp(tdev->dv_cfdata->cf_driver->cd_name,
+ gsckbc_cd.cd_name) == 0) {
+ struct gsckbc_softc *alter = (void *)tdev;
+ if (alter->sc_irq == gsc->sc_irq) {
+#ifdef PCKBCDEBUG
+ if (alter->sc_sibling != NULL) {
+ printf(": more than two ps/2 ports"
+ " sharing the same interrupt???\n");
+ bus_space_unmap(iot, ioh, KBMAPSIZE);
+ return;
+ }
+#endif
+ gsc->sc_sibling = (void *)alter;
+ alter->sc_sibling = self;
+ printf(" (shared with %s)", tdev->dv_xname);
+ }
+ }
+ }
+
printf("\n");
/*
@@ -975,11 +1008,9 @@ pckbc_set_inputhandler(self, slot, func, arg, name)
}
int
-pckbcintr(vsc)
- void *vsc;
+gsckbcintr(struct gsckbc_softc *gsc)
{
- struct pckbc_softc *sc = (struct pckbc_softc *)vsc;
- struct gsckbc_softc *gsc = (void *)sc;
+ struct pckbc_softc *sc = (struct pckbc_softc *)gsc;
struct pckbc_internal *t = sc->id;
pckbc_slot_t slot;
struct pckbc_slotdata *q;
@@ -1020,3 +1051,22 @@ pckbcintr(vsc)
return (served);
}
+
+int
+pckbcintr(void *vsc)
+{
+ struct gsckbc_softc *gsc = vsc;
+ int claimed;
+
+ claimed = gsckbcintr(gsc);
+
+ /*
+ * We also need to handle interrupts for the associated slot device,
+ * if any
+ */
+ gsc = (struct gsckbc_softc *)gsc->sc_sibling;
+ if (gsc != NULL)
+ claimed |= gsckbcintr(gsc);
+
+ return (claimed);
+}