summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorMarco Peereboom <marco@cvs.openbsd.org>2006-04-16 16:34:36 +0000
committerMarco Peereboom <marco@cvs.openbsd.org>2006-04-16 16:34:36 +0000
commit4178ec7446512122df25fcd8639e3a7fa9de3b3a (patch)
treeb9eb6b4e960c33870657145c67574602c2dcebe7 /sys/dev
parent13211293b56c5a2ce7ee7cc76d22039420a3e6fa (diff)
Add interrupt handler. Idea borrowed from FreeBSD since it is much nicer
than the Linux one.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ic/mfi.c45
-rw-r--r--sys/dev/ic/mfireg.h7
-rw-r--r--sys/dev/ic/mfivar.h12
3 files changed, 54 insertions, 10 deletions
diff --git a/sys/dev/ic/mfi.c b/sys/dev/ic/mfi.c
index 41b691e636b..d6194583f4b 100644
--- a/sys/dev/ic/mfi.c
+++ b/sys/dev/ic/mfi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mfi.c,v 1.7 2006/04/07 20:27:51 marco Exp $ */
+/* $OpenBSD: mfi.c,v 1.8 2006/04/16 16:34:35 marco Exp $ */
/*
* Copyright (c) 2006 Marco Peereboom <marco@peereboom.us>
*
@@ -233,9 +233,9 @@ mfi_attach(struct mfi_softc *sc)
DEVNAME(sc), sc->sc_max_cmds, sc->sc_max_sgl);
/* reply queue memory */
- sc->sc_reply_q = mfi_allocmem(sc,
- sizeof(uint32_t) * (sc->sc_max_cmds + 1));
- if (sc->sc_reply_q == NULL) {
+ sc->sc_pcq = mfi_allocmem(sc, (sizeof(uint32_t) * sc->sc_max_cmds) +
+ sizeof(struct mfi_prod_cons));
+ if (sc->sc_pcq == NULL) {
printf("%s: unable to allocate reply queue memory\n",
DEVNAME(sc));
return (1);
@@ -248,9 +248,42 @@ mfi_attach(struct mfi_softc *sc)
}
int
-mfi_intr(void *v)
+mfi_intr(void *arg)
{
- return (0); /* XXX unclaimed */
+ struct mfi_softc *sc = arg;
+ struct mfi_prod_cons *pcq;
+ uint32_t status, producer, consumer, ctx;
+ int s, claimed = 0;
+
+ status = mfi_read(sc, MFI_OSTS);
+ if ((status & MFI_OSTS_INTR_VALID) == 0)
+ return (claimed);
+ /* write status back to acknowledge interrupt */
+ mfi_write(sc, MFI_OSTS, status);
+
+ pcq = (struct mfi_prod_cons *)sc->sc_pcq->am_kva;
+ producer = pcq->mpc_producer;
+ consumer = pcq->mpc_consumer;
+
+ s = splbio();
+ while (consumer != producer) {
+ ctx = pcq->mpc_reply_q[consumer];
+ pcq->mpc_reply_q[consumer] = MFI_INVALID_CTX;
+ if (ctx == MFI_INVALID_CTX)
+ printf("%s: invalid context\n", DEVNAME(sc));
+ else {
+ /* remove from queue and call scsi_done */
+ claimed = 1;
+ }
+ consumer++;
+ if (consumer == sc->sc_max_cmds)
+ consumer = 0;
+ }
+ splx(s);
+
+ pcq->mpc_consumer = consumer;
+
+ return (claimed);
}
int
diff --git a/sys/dev/ic/mfireg.h b/sys/dev/ic/mfireg.h
index 13a8e42bbae..7f6e34e00b5 100644
--- a/sys/dev/ic/mfireg.h
+++ b/sys/dev/ic/mfireg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: mfireg.h,v 1.3 2006/04/07 16:10:14 marco Exp $ */
+/* $OpenBSD: mfireg.h,v 1.4 2006/04/16 16:34:35 marco Exp $ */
/*
* Copyright (c) 2006 Marco Peereboom <marco@peereboom.us>
*
@@ -32,6 +32,11 @@
#define MFI_IQP 0x40 /* inbound queue port */
#define MFI_OQP 0x44 /* outbound queue port */
+/* valid interrupt */
+#define MFI_OSTS_INTR_VALID 0x00000002
+
+#define MFI_INVALID_CTX 0xffffffff
+
/* * firmware states */
#define MFI_STATE_MASK 0xf0000000
#define MFI_STATE_UNDEFINED 0x00000000
diff --git a/sys/dev/ic/mfivar.h b/sys/dev/ic/mfivar.h
index a98dd8a5506..01cbee0e3ae 100644
--- a/sys/dev/ic/mfivar.h
+++ b/sys/dev/ic/mfivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: mfivar.h,v 1.6 2006/04/16 14:40:00 marco Exp $ */
+/* $OpenBSD: mfivar.h,v 1.7 2006/04/16 16:34:35 marco Exp $ */
/*
* Copyright (c) 2006 Marco Peereboom <marco@peereboom.us>
*
@@ -44,6 +44,12 @@ struct mfi_mem {
#define MFIMEM_DVA(_am) ((_am)->am_map->dm_segs[0].ds_addr)
#define MFIMEM_KVA(_am) ((void *)(_am)->am_kva)
+struct mfi_prod_cons {
+ uint32_t mpc_producer;
+ uint32_t mpc_consumer;
+ uint32_t mpc_reply_q[1]; /* compensate for 1 extra reply per spec */
+};
+
struct mfi_softc {
struct device sc_dev;
void *sc_ih;
@@ -59,8 +65,8 @@ struct mfi_softc {
uint32_t sc_max_cmds;
uint32_t sc_max_sgl;
- /* reply queue */
- struct mfi_mem *sc_reply_q;
+ /* producer/consumer pointers and reply queue */
+ struct mfi_mem *sc_pcq;
};
struct mfi_ccb {