>From 072658e23208b4337f5d43c11244333e9798bdb2 Mon Sep 17 00:00:00 2001 From: Damien Zammit Date: Sun, 5 Jul 2020 11:15:44 +1000 Subject: [PATCH] irq: Refactor interrupts into mach device --- device/dev_hdr.h | 9 ++ device/ds_routines.c | 66 +++++------ device/ds_routines.h | 3 - device/intr.c | 183 +++++++++++++------------------ device/intr.h | 55 ++++++---- i386/Makefrag.am | 2 + i386/i386/irq.c | 37 +++++++ i386/i386/irq.h | 14 +++ i386/i386/pic.c | 54 +++++++++ i386/i386/pic.h | 2 + i386/i386at/conf.c | 8 ++ include/device/device.defs | 22 ++-- include/device/notify.defs | 2 +- include/device/notify.h | 2 +- linux/dev/arch/i386/kernel/irq.c | 51 +-------- 15 files changed, 284 insertions(+), 226 deletions(-) create mode 100644 i386/i386/irq.c create mode 100644 i386/i386/irq.h diff --git a/device/dev_hdr.h b/device/dev_hdr.h index ad98e0bb..4bd12c1c 100644 --- a/device/dev_hdr.h +++ b/device/dev_hdr.h @@ -146,4 +146,13 @@ extern void dev_set_indirection( dev_ops_t ops, int unit); +/* + * compare device name + */ +extern boolean_t __attribute__ ((pure)) +name_equal( + const char *src, + int len, + const char *target); + #endif /* _DEVICE_DEV_HDR_H_ */ diff --git a/device/ds_routines.c b/device/ds_routines.c index 13c9a63e..69e963bd 100644 --- a/device/ds_routines.c +++ b/device/ds_routines.c @@ -321,44 +321,35 @@ ds_device_map (device_t dev, vm_prot_t prot, vm_offset_t offset, /* TODO: missing deregister support */ io_return_t -ds_device_intr_register (ipc_port_t master_port, int line, - int id, int flags, ipc_port_t receive_port) +ds_device_intr_register (device_t dev, int id, + int flags, ipc_port_t receive_port) { -#ifdef MACH_XEN - return D_INVALID_OPERATION; -#else /* MACH_XEN */ - io_return_t ret; + kern_return_t err; + mach_device_t mdev = dev->emul_data; - /* Open must be called on the master device port. */ - if (master_port != master_device_port) - return D_INVALID_OPERATION; + /* Refuse if device is dead or not completely open. */ + if (dev == DEVICE_NULL) + return D_NO_SUCH_DEVICE; - /* XXX: move to arch-specific */ - if (line < 0 || line >= 16) + /* Must be called on the irq device only */ + if (! name_equal(mdev->dev_ops->d_name, 3, "irq")) return D_INVALID_OPERATION; - user_intr_t *user_intr = insert_intr_entry (line, receive_port); - if (!user_intr) + user_intr_t *e = insert_intr_entry (&irqtab, id, receive_port); + if (!e) return D_NO_MEMORY; + // TODO The original port should be replaced // when the same device driver calls it again, // in order to handle the case that the device driver crashes and restarts. - ret = install_user_intr_handler (line, flags, user_intr); - - if (ret == 0) - { - /* If the port is installed successfully, increase its reference by 1. - * Thus, the port won't be destroyed after its task is terminated. */ - ip_reference (receive_port); - - /* For now netdde calls device_intr_enable once after registration. Assume - * it does so for now. When we move to IRQ acknowledgment convention we will - * change this. */ - __disable_irq (line); - } - - return ret; -#endif /* MACH_XEN */ + err = install_user_intr_handler (&irqtab, id, flags, e); + if (err == D_SUCCESS) + { + /* If the port is installed successfully, increase its reference by 1. + * Thus, the port won't be destroyed after its task is terminated. */ + ip_reference (receive_port); + } + return err; } boolean_t @@ -1842,16 +1833,19 @@ device_writev_trap (mach_device_t device, dev_mode_t mode, } kern_return_t -ds_device_intr_enable(ipc_port_t master_port, int line, char status) +ds_device_intr_ack (device_t dev, ipc_port_t receive_port) { -#ifdef MACH_XEN - return D_INVALID_OPERATION; -#else /* MACH_XEN */ - if (master_port != master_device_port) + mach_device_t mdev = dev->emul_data; + + /* Refuse if device is dead or not completely open. */ + if (dev == DEVICE_NULL) + return D_NO_SUCH_DEVICE; + + /* Must be called on the irq device only */ + if (! name_equal(mdev->dev_ops->d_name, 3, "irq")) return D_INVALID_OPERATION; - return user_intr_enable(line, status); -#endif /* MACH_XEN */ + return irq_acknowledge(receive_port); } struct device_emulation_ops mach_device_emulation_ops = diff --git a/device/ds_routines.h b/device/ds_routines.h index e9f115fc..c0543cbc 100644 --- a/device/ds_routines.h +++ b/device/ds_routines.h @@ -83,7 +83,4 @@ io_return_t ds_device_writev_trap( io_buf_vec_t *iovec, vm_size_t count); -/* XXX arch-specific */ -extern ipc_port_t intr_rcv_ports[16]; - #endif /* DS_ROUTINES_H */ diff --git a/device/intr.c b/device/intr.c index 1e9ab898..eccc924f 100644 --- a/device/intr.c +++ b/device/intr.c @@ -1,119 +1,96 @@ #include -#include -#include +#include +#include +#include #include #include +#include +#include #ifndef MACH_XEN -static boolean_t deliver_intr (int line, ipc_port_t dest_port); +queue_head_t main_intr_queue; +static boolean_t deliver_intr (int id, ipc_port_t dst_port); -static queue_head_t intr_queue; -/* The total number of unprocessed interrupts. */ -static int tot_num_intr; - -static struct intr_entry * -search_intr (int line, ipc_port_t dest) +static user_intr_t * +search_intr (struct irqdev *dev, ipc_port_t dst_port) { - struct intr_entry *e; - queue_iterate (&intr_queue, e, struct intr_entry *, chain) + user_intr_t *e; + queue_iterate (dev->intr_queue, e, user_intr_t *, chain) { - if (e->dest == dest && e->line == line) + if (e->dst_port == dst_port) return e; } return NULL; } -static struct intr_entry * -search_intr_line (int line) +kern_return_t +irq_acknowledge (ipc_port_t receive_port) { - struct intr_entry *e; - queue_iterate (&intr_queue, e, struct intr_entry *, chain) - { - if (e->line == line && - (e->dest != MACH_PORT_NULL - && e->dest->ip_references != 1 - && e->unacked_interrupts)) - return e; - } - return NULL; -} - -kern_return_t user_intr_enable (int line, char status) -{ - struct intr_entry *e; - kern_return_t ret = D_SUCCESS; + user_intr_t *e; + kern_return_t ret; spl_t s = splhigh (); - /* FIXME: Use search_intr instead once we get the delivery port from ds_device_intr_enable, and get rid of search_intr_line */ - e = search_intr_line (line); + e = search_intr (&irqtab, receive_port); if (!e) - printf("didn't find user intr for interrupt %d!?\n", line); - else if (status) - { - if (!e->unacked_interrupts) - ret = D_INVALID_OPERATION; - else - e->unacked_interrupts--; - } + printf("didn't find user intr for interrupt !?\n"); else - { - e->unacked_interrupts++; - if (!e->unacked_interrupts) { - ret = D_INVALID_OPERATION; - e->unacked_interrupts--; + if (!e->n_unacked) + ret = D_INVALID_OPERATION; + else + e->n_unacked--; } - } splx (s); if (ret) return ret; - if (status) - /* TODO: better name for generic-to-arch-specific call */ - __enable_irq (line); - else - __disable_irq (line); + if (irqtab.irqdev_ack) + (*(irqtab.irqdev_ack)) (&irqtab, e->id); + + irq_enable (irqtab.irq[e->id]); + return D_SUCCESS; } /* This function can only be used in the interrupt handler. */ static void -queue_intr (int line, user_intr_t *e) +queue_intr (struct irqdev *dev, int id, user_intr_t *e) { /* Until userland has handled the IRQ in the driver, we have to keep it * disabled. Level-triggered interrupts would keep raising otherwise. */ - __disable_irq (line); + irq_disable (dev->irq[id]); spl_t s = splhigh (); - e->unacked_interrupts++; + e->n_unacked++; e->interrupts++; - tot_num_intr++; + dev->tot_num_intr++; splx (s); thread_wakeup ((event_t) &intr_thread); } -int deliver_user_intr (int line, user_intr_t *intr) +int +deliver_user_intr (struct irqdev *dev, int id, user_intr_t *e) { /* The reference of the port was increased * when the port was installed. * If the reference is 1, it means the port should * have been destroyed and I destroy it now. */ - if (intr->dest - && intr->dest->ip_references == 1) + if (e->dst_port + && e->dst_port->ip_references == 1) { - printf ("irq handler %d: release a dead delivery port %p entry %p\n", line, intr->dest, intr); - ipc_port_release (intr->dest); - intr->dest = MACH_PORT_NULL; + printf ("irq handler [%d]: release a dead delivery port %p entry %p\n", id, e->dst_port, e); + ipc_port_release (e->dst_port); + e->dst_port = MACH_PORT_NULL; thread_wakeup ((event_t) &intr_thread); return 0; } else { - queue_intr (line, intr); + queue_intr (dev, id, e); return 1; } } @@ -122,37 +99,32 @@ int deliver_user_intr (int line, user_intr_t *intr) * This entry exists in the queue until * the corresponding interrupt port is removed.*/ user_intr_t * -insert_intr_entry (int line, ipc_port_t dest) +insert_intr_entry (struct irqdev *dev, int id, ipc_port_t dst_port) { - struct intr_entry *e, *new, *ret; + user_intr_t *e, *new, *ret; int free = 0; - new = (struct intr_entry *) kalloc (sizeof (*new)); + new = (user_intr_t *) kalloc (sizeof (*new)); if (new == NULL) return NULL; /* check whether the intr entry has been in the queue. */ spl_t s = splhigh (); - e = search_intr (line, dest); + e = search_intr (dev, dst_port); if (e) { - printf ("the interrupt entry for line %d and port %p has already been inserted\n", line, dest); + printf ("the interrupt entry for irq[%d] and port %p has already been inserted\n", id, dst_port); free = 1; ret = NULL; goto out; } - printf("irq handler %d: new delivery port %p entry %p\n", line, dest, new); + printf("irq handler [%d]: new delivery port %p entry %p\n", id, dst_port, new); ret = new; - new->line = line; - new->dest = dest; + new->id = id; + new->dst_port = dst_port; new->interrupts = 0; - /* For now netdde calls device_intr_enable once after registration. Assume - * it does so for now. When we move to IRQ acknowledgment convention we will - * change this. */ - new->unacked_interrupts = 1; - - queue_enter (&intr_queue, new, struct intr_entry *, chain); + queue_enter (dev->intr_queue, new, user_intr_t *, chain); out: splx (s); if (free) @@ -163,10 +135,10 @@ out: void intr_thread (void) { - struct intr_entry *e; - int line; - ipc_port_t dest; - queue_init (&intr_queue); + user_intr_t *e; + int id; + ipc_port_t dst_port; + queue_init (&main_intr_queue); for (;;) { @@ -176,11 +148,11 @@ intr_thread (void) spl_t s = splhigh (); /* Check for aborted processes */ - queue_iterate (&intr_queue, e, struct intr_entry *, chain) + queue_iterate (&main_intr_queue, e, user_intr_t *, chain) { - if ((!e->dest || e->dest->ip_references == 1) && e->unacked_interrupts) + if ((!e->dst_port || e->dst_port->ip_references == 1) && e->n_unacked) { - printf ("irq handler %d: release dead delivery %d unacked irqs port %p entry %p\n", e->line, e->unacked_interrupts, e->dest, e); + printf ("irq handler [%d]: release dead delivery %d unacked irqs port %p entry %p\n", e->id, e->n_unacked, e->dst_port, e); /* The reference of the port was increased * when the port was installed. * If the reference is 1, it means the port should @@ -188,24 +160,24 @@ intr_thread (void) * handling can trigger, and we will cleanup later after the Linux * handler is cleared. */ /* TODO: rather immediately remove from Linux handler */ - while (e->unacked_interrupts) + while (e->n_unacked) { - __enable_irq(e->line); - e->unacked_interrupts--; + irq_enable (irqtab.irq[e->id]); + e->n_unacked--; } } } /* Now check for interrupts */ - while (tot_num_intr) + while (irqtab.tot_num_intr) { int del = 0; - queue_iterate (&intr_queue, e, struct intr_entry *, chain) + queue_iterate (&main_intr_queue, e, user_intr_t *, chain) { /* if an entry doesn't have dest port, * we should remove it. */ - if (e->dest == MACH_PORT_NULL) + if (e->dst_port == MACH_PORT_NULL) { clear_wait (current_thread (), 0, 0); del = 1; @@ -215,13 +187,13 @@ intr_thread (void) if (e->interrupts) { clear_wait (current_thread (), 0, 0); - line = e->line; - dest = e->dest; + id = e->id; + dst_port = e->dst_port; e->interrupts--; - tot_num_intr--; + irqtab.tot_num_intr--; splx (s); - deliver_intr (line, dest); + deliver_intr (id, dst_port); s = splhigh (); } } @@ -229,16 +201,16 @@ intr_thread (void) /* remove the entry without dest port from the queue and free it. */ if (del) { - assert (!queue_empty (&intr_queue)); - queue_remove (&intr_queue, e, struct intr_entry *, chain); - if (e->unacked_interrupts) - printf("irq handler %d: still %d unacked irqs in entry %p\n", e->line, e->unacked_interrupts, e); - while (e->unacked_interrupts) + assert (!queue_empty (&main_intr_queue)); + queue_remove (&main_intr_queue, e, user_intr_t *, chain); + if (e->n_unacked) + printf("irq handler [%d]: still %d unacked irqs in entry %p\n", e->id, e->n_unacked, e); + while (e->n_unacked) { - __enable_irq(e->line); - e->unacked_interrupts--; + irq_enable (irqtab.irq[e->id]); + e->n_unacked--; } - printf("irq handler %d: removed entry %p\n", e->line, e); + printf("irq handler [%d]: removed entry %p\n", e->id, e); splx (s); kfree ((vm_offset_t) e, sizeof (*e)); s = splhigh (); @@ -250,11 +222,11 @@ intr_thread (void) } static boolean_t -deliver_intr (int line, ipc_port_t dest_port) +deliver_intr (int id, ipc_port_t dst_port) { ipc_kmsg_t kmsg; device_intr_notification_t *n; - mach_port_t dest = (mach_port_t) dest_port; + mach_port_t dest = (mach_port_t) dst_port; if (dest == MACH_PORT_NULL) return FALSE; @@ -285,11 +257,12 @@ deliver_intr (int line, ipc_port_t dest_port) t->msgt_unused = 0; n->intr_header.msgh_remote_port = dest; - n->line = line; + n->id = id; - ipc_port_copy_send (dest_port); + ipc_port_copy_send (dst_port); ipc_mqueue_send_always(kmsg); return TRUE; } + #endif /* MACH_XEN */ diff --git a/device/intr.h b/device/intr.h index 48843cf0..f3adebde 100644 --- a/device/intr.h +++ b/device/intr.h @@ -1,37 +1,48 @@ -#ifndef __INTR_H__ +#ifndef _DEVICE_IRQ_H +#define _DEVICE_IRQ_H -#define __INTR_H__ +#ifndef MACH_XEN -#include +#include +#include #include -#include +#include +#include -typedef struct intr_entry -{ +#define DEVICE_NOTIFY_MSGH_SEQNO 0 + +#include + +struct irqdev; +#include + +typedef struct { queue_chain_t chain; - ipc_port_t dest; - int line; - int interrupts; /* The number of interrupts occur since last run of intr_thread. */ - int unacked_interrupts; /* Number of times irqs were disabled for this */ + int interrupts; /* Number of interrupts occurred since last run of intr_thread */ + int n_unacked; /* Number of times irqs were disabled for this */ + ipc_port_t dst_port; /* Notification port */ + int id; /* Mapping to machine dependent irq_t array elem */ } user_intr_t; -#define DEVICE_NOTIFY_MSGH_SEQNO 0 - -int install_user_intr_handler (unsigned int line, - unsigned long flags, - user_intr_t *user_intr); +struct irqdev { + char *name; + void (*irqdev_ack)(struct irqdev *dev, int id); -/* Returns 0 if action should be removed */ -int deliver_user_intr (int line, user_intr_t *intr); + queue_head_t *intr_queue; + int tot_num_intr; /* Total number of unprocessed interrupts */ -user_intr_t *insert_intr_entry (int line, ipc_port_t dest); + /* Machine dependent */ + irq_t irq[NINTR]; +}; -/* TODO: should rather take delivery port */ -kern_return_t user_intr_enable (int line, char status); +extern queue_head_t main_intr_queue; +extern int install_user_intr_handler (struct irqdev *dev, int id, unsigned long flags, user_intr_t *e); +extern int deliver_user_intr (struct irqdev *dev, int id, user_intr_t *e); +extern user_intr_t *insert_intr_entry (struct irqdev *dev, int id, ipc_port_t receive_port); void intr_thread (void); +kern_return_t irq_acknowledge (ipc_port_t receive_port); -void __disable_irq(unsigned int); -void __enable_irq(unsigned int); +#endif /* MACH_XEN */ #endif diff --git a/i386/Makefrag.am b/i386/Makefrag.am index f38c0785..59571416 100644 --- a/i386/Makefrag.am +++ b/i386/Makefrag.am @@ -102,6 +102,8 @@ libkernel_a_SOURCES += \ i386/i386/io_perm.c \ i386/i386/io_perm.h \ i386/i386/ipl.h \ + i386/i386/irq.c \ + i386/i386/irq.h \ i386/i386/ktss.c \ i386/i386/ktss.h \ i386/i386/kttd_interface.c \ diff --git a/i386/i386/irq.c b/i386/i386/irq.c new file mode 100644 index 00000000..11a2003d --- /dev/null +++ b/i386/i386/irq.c @@ -0,0 +1,37 @@ +#include +#include +#include +#include +#include + +extern queue_head_t main_intr_queue; + +static void +irq_eoi (struct irqdev *dev, int id) +{ + /* TODO EOI(dev->irq[id]) */ +} + +void +irq_enable (irq_t irq) +{ + spl_t s = splhigh(); + mach_cli (); + unmask_irq (irq); + splx(s); +} + +void +irq_disable (irq_t irq) +{ + spl_t s = splhigh(); + mach_cli (); + mask_irq (irq); + splx(s); +} + +struct irqdev irqtab = { + "irq", irq_eoi, &main_intr_queue, 0, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, +}; + diff --git a/i386/i386/irq.h b/i386/i386/irq.h new file mode 100644 index 00000000..eb03c9cc --- /dev/null +++ b/i386/i386/irq.h @@ -0,0 +1,14 @@ +#ifndef _I386_IRQ_H +#define _I386_IRQ_H + +#include +#define mach_cli() __asm__ __volatile__ ("cli": : :"memory") + +typedef unsigned int irq_t; + +void irq_enable (irq_t irq); +void irq_disable (irq_t irq); + +extern struct irqdev irqtab; + +#endif diff --git a/i386/i386/pic.c b/i386/i386/pic.c index 0feebc6f..3c0e7d91 100644 --- a/i386/i386/pic.c +++ b/i386/i386/pic.c @@ -185,3 +185,57 @@ intnull(int unit_dev) } } + +/* + * Mask a PIC IRQ. + */ +inline void +mask_irq (unsigned int irq_nr) +{ + int new_pic_mask = curr_pic_mask | 1 << irq_nr; + + if (curr_pic_mask != new_pic_mask) + { + curr_pic_mask = new_pic_mask; + if (irq_nr < 8) + { + outb (PIC_MASTER_OCW, curr_pic_mask & 0xff); + } + else + { + outb (PIC_SLAVE_OCW, curr_pic_mask >> 8); + } + } +} + +/* + * Unmask a PIC IRQ. + */ +inline void +unmask_irq (unsigned int irq_nr) +{ + int mask; + int new_pic_mask; + + mask = 1 << irq_nr; + if (irq_nr >= 8) + { + mask |= 1 << 2; + } + + new_pic_mask = curr_pic_mask & ~mask; + + if (curr_pic_mask != new_pic_mask) + { + curr_pic_mask = new_pic_mask; + if (irq_nr < 8) + { + outb (PIC_MASTER_OCW, curr_pic_mask & 0xff); + } + else + { + outb (PIC_SLAVE_OCW, curr_pic_mask >> 8); + } + } +} + diff --git a/i386/i386/pic.h b/i386/i386/pic.h index 553c4bcc..01fc5ccc 100644 --- a/i386/i386/pic.h +++ b/i386/i386/pic.h @@ -180,6 +180,8 @@ WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. extern void picinit (void); extern int curr_pic_mask; extern void intnull(int unit); +extern inline void mask_irq (unsigned int irq_nr); +extern inline void unmask_irq (unsigned int irq_nr); #endif /* __ASSEMBLER__ */ #endif /* _I386_PIC_H_ */ diff --git a/i386/i386at/conf.c b/i386/i386at/conf.c index fe7c7c09..ca5d0dfb 100644 --- a/i386/i386at/conf.c +++ b/i386/i386at/conf.c @@ -68,6 +68,9 @@ #define hypcnname "hyp" #endif /* MACH_HYP */ +#include +#define irqname "irq" + /* * List of devices - console must be at slot 0 */ @@ -149,6 +152,11 @@ struct dev_ops dev_name_list[] = nodev }, #endif /* MACH_HYP */ + { irqname, nulldev_open, nulldev_close, nulldev_read, + nulldev_write,nulldev_getstat,nulldev_setstat, nomap, + nodev, nulldev, nulldev_portdeath,0, + nodev }, + }; int dev_name_count = sizeof(dev_name_list)/sizeof(dev_name_list[0]); diff --git a/include/device/device.defs b/include/device/device.defs index dca1be4e..ec4b5bf8 100644 --- a/include/device/device.defs +++ b/include/device/device.defs @@ -143,22 +143,20 @@ routine device_set_filter( ); routine device_intr_register( - master_port : mach_port_t; - in line : int; + device : device_t; in id : int; in flags : int; in receive_port : mach_port_send_t ); /* - * enable/disable the specified line. + * Acknowledge the specified interrupt notification. */ -/* XXX: Naming a function taht can disable something "xxx_enable" is confusing. */ -/* Is the disable part actually used at all? AIUI, the kernel IRQ handler -should always disable the line; and the userspace driver only has to -reenable it, after acknowledging and handling the interrupt... -*/ -routine device_intr_enable( - master_port : mach_port_t; - line : int; - status : char); +/* + * When an IRQ happens and an intr notification is thus sent, the IRQ line + * is kept disabled until the notification is acknowledged with this RPC + */ +routine device_intr_ack( + device : device_t; + in receive_port : mach_port_send_t); + diff --git a/include/device/notify.defs b/include/device/notify.defs index ea374d26..7919b339 100644 --- a/include/device/notify.defs +++ b/include/device/notify.defs @@ -33,4 +33,4 @@ serverdemux device_intr_notify_server; simpleroutine device_intr_notify( notify : notify_port_t; - name : int); + id : int); diff --git a/include/device/notify.h b/include/device/notify.h index b6907b03..addf9114 100644 --- a/include/device/notify.h +++ b/include/device/notify.h @@ -26,7 +26,7 @@ typedef struct { mach_msg_header_t intr_header; mach_msg_type_t intr_type; - int line; + int id; } device_intr_notification_t; #define DEVICE_INTR_NOTIFY 100 diff --git a/linux/dev/arch/i386/kernel/irq.c b/linux/dev/arch/i386/kernel/irq.c index bc752013..e7f50342 100644 --- a/linux/dev/arch/i386/kernel/irq.c +++ b/linux/dev/arch/i386/kernel/irq.c @@ -89,49 +89,6 @@ static struct linux_action *irq_action[16] = NULL, NULL, NULL, NULL }; -/* - * Mask an IRQ. - */ -static inline void -mask_irq (unsigned int irq_nr) -{ - int new_pic_mask = curr_pic_mask | 1 << irq_nr; - - if (curr_pic_mask != new_pic_mask) - { - curr_pic_mask = new_pic_mask; - if (irq_nr < 8) - outb (curr_pic_mask & 0xff, PIC_MASTER_OCW); - else - outb (curr_pic_mask >> 8, PIC_SLAVE_OCW); - } -} - -/* - * Unmask an IRQ. - */ -static inline void -unmask_irq (unsigned int irq_nr) -{ - int mask; - int new_pic_mask; - - mask = 1 << irq_nr; - if (irq_nr >= 8) - mask |= 1 << 2; - - new_pic_mask = curr_pic_mask & ~mask; - - if (curr_pic_mask != new_pic_mask) - { - curr_pic_mask = new_pic_mask; - if (irq_nr < 8) - outb (curr_pic_mask & 0xff, PIC_MASTER_OCW); - else - outb (curr_pic_mask >> 8, PIC_SLAVE_OCW); - } -} - /* * Generic interrupt handler for Linux devices. * Set up a fake `struct pt_regs' then call the real handler. @@ -157,7 +114,7 @@ linux_intr (int irq) // the current device. But I don't do it for now. if (action->user_intr) { - if (!deliver_user_intr(irq, action->user_intr)) + if (!deliver_user_intr(&irqtab, irq, action->user_intr)) { *prev = action->next; linux_kfree(action); @@ -300,13 +257,15 @@ setup_x86_irq (int irq, struct linux_action *new) } int -install_user_intr_handler (unsigned int irq, unsigned long flags, +install_user_intr_handler (struct irqdev *dev, int id, unsigned long flags, user_intr_t *user_intr) { struct linux_action *action; struct linux_action *old; int retval; + unsigned int irq = dev->irq[id]; + assert (irq < 16); /* Test whether the irq handler has been set */ @@ -314,7 +273,7 @@ install_user_intr_handler (unsigned int irq, unsigned long flags, old = irq_action[irq]; while (old) { - if (old->user_intr && old->user_intr->dest == user_intr->dest) + if (old->user_intr && old->user_intr->dst_port == user_intr->dst_port) { printk ("The interrupt handler has already been installed on line %d", irq); return linux_to_mach_error (-EAGAIN); -- 2.25.1