diff options
author | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2020-07-10 00:23:32 +0200 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2020-07-10 00:31:38 +0200 |
commit | 6054cda4de2341b9a77ec4421411725f3684006b (patch) | |
tree | 02622e721dffe9fdb73e35805de2fbf8a2a5aea8 /i386 | |
parent | 2dbf108457d0a0057cc63d5b3b89fd4da48d2a72 (diff) | |
download | gnumach-6054cda4de2341b9a77ec4421411725f3684006b.tar.gz gnumach-6054cda4de2341b9a77ec4421411725f3684006b.tar.bz2 gnumach-6054cda4de2341b9a77ec4421411725f3684006b.zip |
Add hardware interrupt notification mechanism
This allows privileged userland drivers to get notifications of hardware
interrupts.
Initial work by Zheng Da, reworked by Damien Zammit and myself.
* Makefrag.am (libkernel_a_SOURCES): Add device/intr.c and
device/intr.h.
(include_device_HEADERS): Add include/device/notify.defs and
include/device/notify.h.
* device/dev_hdr.h (name_equal): Add declaration.
* device/ds_routines.c: Include <device/intr.h>
(ds_device_intr_register, ds_device_intr_ack): New functions.
* device/intr.c, device/intr.h: New files.
* doc/mach.texi (Device Interrupt): New section.
* i386/Makefrag.am (libkernel_a_SOURCES): Add i386/i386/irq.c and
i386/i386/irq.h.
* i386/i386/irq.c, i386/i386/irq.h: New files.
* i386/i386at/conf.c: Include <device/intr.h>.
(irqname): New macro.
(dev_name_list): Add irq device.
* include/device/device.defs (device_intr_register, device_intr_ack):
New RPCs.
* include/device/notify.defs, include/device/notify.h: New files.
* kern/startup.c: Include <device/intr.h>
(start_kernel_threads): Start intr_thread thread.
* linux/dev/arch/i386/kernel/irq.c: Include <device/intr.h>
(linux_action): Add user_intr field.
(linux_intr): Call user_intr action if any.
(mask_irq, unmask_irq): Move functions to i386/i386/pic.c
(__disable_irq, __enable_irq): Move functions to i386/i386/irq.c.
(install_user_intr_handler): New function.
(request_irq): Initialize user_intr field.
* linux/src/include/asm-i386/irq.h (__disable_irq, __enable_irq): Remove
prototypes.
* i386/i386/pic.c (mask_irq, unmask_irq): New functions.
* i386/i386/pic.h (mask_irq, unmask_irq): New prototypes.
Diffstat (limited to 'i386')
-rw-r--r-- | i386/Makefrag.am | 2 | ||||
-rw-r--r-- | i386/i386/irq.c | 66 | ||||
-rw-r--r-- | i386/i386/irq.h | 27 | ||||
-rw-r--r-- | i386/i386/pic.c | 72 | ||||
-rw-r--r-- | i386/i386/pic.h | 2 | ||||
-rw-r--r-- | i386/i386at/conf.c | 8 |
6 files changed, 177 insertions, 0 deletions
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..c65d2ea2 --- /dev/null +++ b/i386/i386/irq.c @@ -0,0 +1,66 @@ +/* + * Copyright (C) 1995 Shantanu Goel + * Copyright (C) 2020 Free Software Foundation, Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <i386/irq.h> +#include <device/intr.h> +#include <mach/kern_return.h> +#include <kern/queue.h> +#include <machine/machspl.h> + +extern queue_head_t main_intr_queue; + +static void +irq_eoi (struct irqdev *dev, int id) +{ + /* TODO EOI(dev->irq[id]) */ +} + +static unsigned int ndisabled_irq[NINTR]; + +void +__disable_irq (irq_t irq_nr) +{ + assert (irq_nr < NINTR); + + spl_t s = splhigh(); + ndisabled_irq[irq_nr]++; + assert (ndisabled_irq[irq_nr] > 0); + if (ndisabled_irq[irq_nr] == 1) + mask_irq (irq_nr); + splx(s); +} + +void +__enable_irq (irq_t irq_nr) +{ + assert (irq_nr < NINTR); + + spl_t s = splhigh(); + assert (ndisabled_irq[irq_nr] > 0); + ndisabled_irq[irq_nr]--; + if (ndisabled_irq[irq_nr] == 0) + unmask_irq (irq_nr); + 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..d48a8e92 --- /dev/null +++ b/i386/i386/irq.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2020 Free Software Foundation, Inc. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * THE FREE SOFTWARE FOUNDATION ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. THE FREE SOFTWARE FOUNDATION DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + */ + +#ifndef _I386_IRQ_H +#define _I386_IRQ_H + +#include <i386/pic.h> + +typedef unsigned int irq_t; + +void __enable_irq (irq_t irq); +void __disable_irq (irq_t irq); + +extern struct irqdev irqtab; + +#endif diff --git a/i386/i386/pic.c b/i386/i386/pic.c index 0feebc6f..62ed9ed1 100644 --- a/i386/i386/pic.c +++ b/i386/i386/pic.c @@ -49,6 +49,24 @@ OTHER TORTIOUS ACTION, ARISING OUR OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +/* + * Copyright (C) 1995 Shantanu Goel. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + #include <sys/types.h> #include <kern/printf.h> #include <i386/ipl.h> @@ -185,3 +203,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 f492de5e..6434bf08 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 <device/intr.h> +#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]); |