diff options
author | Marco Peereboom <marco@cvs.openbsd.org> | 2006-04-16 16:34:36 +0000 |
---|---|---|
committer | Marco Peereboom <marco@cvs.openbsd.org> | 2006-04-16 16:34:36 +0000 |
commit | 4178ec7446512122df25fcd8639e3a7fa9de3b3a (patch) | |
tree | b9eb6b4e960c33870657145c67574602c2dcebe7 /sys/dev | |
parent | 13211293b56c5a2ce7ee7cc76d22039420a3e6fa (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.c | 45 | ||||
-rw-r--r-- | sys/dev/ic/mfireg.h | 7 | ||||
-rw-r--r-- | sys/dev/ic/mfivar.h | 12 |
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 { |