This allows reading irq device status 0 for the mode of the interrupt
controller, pic or apic.
TESTED using:
```
\#include <stdio.h>
\#include <device/device.h>
\#include <hurd.h>
\#include <mach.h>
int main()
{
mach_port_t devices, irq;
int pic_mode, cnt = 1;
int err;
err = get_privileged_ports(NULL, &devices);
if (err)
return 1;
err = device_open(devices, D_READ, "irq", &irq);
if (err)
return 2;
err = device_get_status(irq, 0, &pic_mode, &cnt);
if (err)
return 3;
printf("pic_mode = %d\n", pic_mode);
return 0;
}
amd64-apic $ sudo ./test
pic_mode = 1
i386-pic $ sudo ./test
pic_mode = 0
i386-apic $ sudo ./test
pic_mode = 1
```
---
device/intr.c | 24 ++++++++++++++++++++++++
device/intr.h | 1 +
i386/i386/irq.h | 6 ++++++
i386/i386/pic.c | 2 ++
i386/i386at/conf.c | 2 +-
i386/i386at/ioapic.c | 3 +++
6 files changed, 37 insertions(+), 1 deletion(-)
diff --git a/device/intr.c b/device/intr.c
index 07d8acd8..b4c69508 100644
--- a/device/intr.c
+++ b/device/intr.c
@@ -22,6 +22,30 @@
#include <machine/irq.h>
#include <ipc/ipc_space.h>
+/*ARGSUSED*/
+io_return_t irqgetstat(
+ dev_t dev,
+ dev_flavor_t flavor,
+ dev_status_t data, /* pointer to OUT array */
+ mach_msg_type_number_t *count) /* OUT */
+{
+ io_return_t result;
+
+ switch (flavor)
+ {
+ case IRQGETPICMODE:
+ *data = pic_mode;
+ *count = 1;
+ result = D_SUCCESS;
+ break;
+ default:
+ result = D_INVALID_OPERATION;
+ break;
+ }
+
+ return (result);
+}
+
#ifndef MACH_XEN
def_simple_lock_irq_data(static, intr_lock)
diff --git a/device/intr.h b/device/intr.h
index cd3e0bce..2988e49c 100644
--- a/device/intr.h
+++ b/device/intr.h
@@ -53,6 +53,7 @@ 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);
+extern io_return_t irqgetstat(dev_t dev, dev_flavor_t flavor, dev_status_t
data, mach_msg_type_number_t *count);
void intr_thread (void);
kern_return_t irq_acknowledge (ipc_port_t receive_port);
diff --git a/i386/i386/irq.h b/i386/i386/irq.h
index e1f41045..bb5adaa9 100644
--- a/i386/i386/irq.h
+++ b/i386/i386/irq.h
@@ -15,6 +15,11 @@
#ifndef _I386_IRQ_H
#define _I386_IRQ_H
+#define IRQGETPICMODE 0
+# define ACPI_PICMODE_PIC 0
+# define ACPI_PICMODE_APIC 1
+# define ACPI_PICMODE_SAPIC 2
+
#ifdef APIC
# include <i386/apic.h>
#else
@@ -28,5 +33,6 @@ void __enable_irq (irq_t irq);
void __disable_irq (irq_t irq);
extern struct irqdev irqtab;
+extern int pic_mode;
#endif
diff --git a/i386/i386/pic.c b/i386/i386/pic.c
index b51bf3ad..019cdd8b 100644
--- a/i386/i386/pic.c
+++ b/i386/i386/pic.c
@@ -74,6 +74,8 @@ WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <i386/spl.h>
#include <i386/pio.h>
+int pic_mode = 0;
+
spl_t curr_ipl[NCPUS] = {0};
int curr_pic_mask;
int spl_init = 0;
diff --git a/i386/i386at/conf.c b/i386/i386at/conf.c
index 84b97c42..9bdd8379 100644
--- a/i386/i386at/conf.c
+++ b/i386/i386at/conf.c
@@ -156,7 +156,7 @@ struct dev_ops dev_name_list[] =
#endif /* MACH_HYP */
{ irqname, nulldev_open, nulldev_close, nulldev_read,
- nulldev_write,nulldev_getstat,nulldev_setstat, nomap,
+ nulldev_write,irqgetstat, nulldev_setstat, nomap,
nodev_async_in, nulldev_reset, nulldev_portdeath,0,
nodev_info },
diff --git a/i386/i386at/ioapic.c b/i386/i386at/ioapic.c
index e38e4d6b..09d62d23 100644
--- a/i386/i386at/ioapic.c
+++ b/i386/i386at/ioapic.c
@@ -36,6 +36,7 @@
static int has_irq_specific_eoi = 0;
int timer_pin;
+int pic_mode;
uint32_t lapic_timer_val = 0;
uint32_t calibrated_ticks = 0;
@@ -484,6 +485,8 @@ ioapic_configure(void)
printf("IOAPIC 1 configured with GSI %d-%d\n", ngsis, ngsis + ngsis2 -
1);
}
+ pic_mode = ACPI_PICMODE_APIC;
+
/* Start the IO APIC receiving interrupts */
lapic_setup();
lapic_enable();
--
2.45.2