From 1c02564abe7cea7d2fc6df82aeecce5bb6b0d93a Mon Sep 17 00:00:00 2001 From: Damien Zammit Date: Tue, 30 Mar 2021 13:58:29 +1100 Subject: intr: Add user interrupt handling code for non-Linux case * device/intr.c: Include (struct intr_list): New structure. (user_intr_handlers): New array. (user_irq_handler): New function. (install_user_intr_handler): New function. Message-Id: <20210330025830.63528-2-damien@zamaudio.com> --- device/intr.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) (limited to 'device') diff --git a/device/intr.c b/device/intr.c index fbb9f495..ac213ecf 100644 --- a/device/intr.c +++ b/device/intr.c @@ -12,6 +12,7 @@ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. */ +#include #include #include #include @@ -26,6 +27,17 @@ queue_head_t main_intr_queue; static boolean_t deliver_intr (int id, ipc_port_t dst_port); +#ifndef LINUX_DEV +#define SA_SHIRQ 0x04000000 + +struct intr_list { + user_intr_t *user_intr; + unsigned long flags; + struct intr_list *next; +}; +static struct intr_list *user_intr_handlers[NINTR]; +#endif + static user_intr_t * search_intr (struct irqdev *dev, ipc_port_t dst_port) { @@ -147,6 +159,74 @@ out: return ret; } +#ifndef LINUX_DEV + +static void +user_irq_handler (int id) +{ + struct intr_list *handler; + struct intr_list **prev = &user_intr_handlers[id]; + user_intr_t *e; + spl_t s; + + s = splhigh(); + + for (handler = *prev; handler; handler = handler->next) + { + e = handler->user_intr; + if (!deliver_user_intr(&irqtab, id, e)) + { + /* We failed to deliver this interrupt, remove handler from list */ + *prev = handler->next; + } + prev = &handler->next; + } + splx(s); +} + +int +install_user_intr_handler (struct irqdev *dev, int id, unsigned long flags, + user_intr_t *user_intr) +{ + unsigned int irq = dev->irq[id]; + struct intr_list **head = &user_intr_handlers[id]; + struct intr_list *new, *old = *head; + spl_t s; + + assert (irq < NINTR); + + /* Don't allow overriding hardclock/kdintr etc */ + if ((ivect[irq] != user_irq_handler) && (ivect[irq] != intnull)) + { + mach_print("You can't have this interrupt\n"); + return D_ALREADY_OPEN; + } + + if (old) + { + if (!(old->flags & flags & SA_SHIRQ)) + { + mach_print ("Cannot share irq\n"); + return D_ALREADY_OPEN; + } + } + + new = (struct intr_list *)kalloc (sizeof (struct intr_list)); + new->user_intr = user_intr; + new->flags = flags; + + s = splhigh(); + new->next = *head; + *head = new; + ivect[irq] = user_irq_handler; + iunit[irq] = (int)irq; + unmask_irq (irq); + splx(s); + + return D_SUCCESS; +} +#endif + void intr_thread (void) { -- cgit v1.2.3