[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 2/8] hw/char/escc2: Handle interrupt generation
From: |
Jasper Lowell |
Subject: |
[PATCH 2/8] hw/char/escc2: Handle interrupt generation |
Date: |
Wed, 17 Jun 2020 18:23:56 +1000 |
Signed-off-by: Jasper Lowell <jasper.lowell@bt.com>
---
hw/char/escc2.c | 88 ++++++++++++++++++++++++++++++++++++++++++++
hw/char/trace-events | 1 +
2 files changed, 89 insertions(+)
diff --git a/hw/char/escc2.c b/hw/char/escc2.c
index 94528b8a4c..926346482f 100644
--- a/hw/char/escc2.c
+++ b/hw/char/escc2.c
@@ -8,6 +8,7 @@
#include "qemu/osdep.h"
#include "hw/char/escc2.h"
+#include "hw/irq.h"
#include "hw/isa/isa.h"
#include "hw/qdev-properties.h"
#include "qapi/error.h"
@@ -55,6 +56,13 @@
/* CCR0. */
#define REGISTER_CCR0_OFFSET 0x2c
+#define REGISTER_CCR0_PU 0x80
+#define REGISTER_CCR0_MCE 0x40
+#define REGISTER_CCR0_SC2 0x10
+#define REGISTER_CCR0_SC1 0x8
+#define REGISTER_CCR0_SC0 0x4
+#define REGISTER_CCR0_SM1 0x2
+#define REGISTER_CCR0_SM0 0x1
/* CCR1. */
#define REGISTER_CCR1_OFFSET 0x2d
@@ -94,12 +102,23 @@
/* GIS. */
#define REGISTER_GIS_OFFSET 0x38
+#define REGISTER_GIS_PI 0x80
+#define REGISTER_GIS_ISA1 0x8
+#define REGISTER_GIS_ISA0 0x4
+#define REGISTER_GIS_ISB1 0x2
+#define REGISTER_GIS_ISB0 0x1
/* IVA. */
#define REGISTER_IVA_OFFSET 0x38
/* IPC. */
#define REGISTER_IPC_OFFSET 0x39
+#define REGISTER_IPC_VIS 0x80
+#define REGISTER_IPC_SLA1 0x10
+#define REGISTER_IPC_SLA0 0x8
+#define REGISTER_IPC_CASM 0x4
+#define REGISTER_IPC_IC1 0x2
+#define REGISTER_IPC_IC0 0x1
/* ISR0. */
#define REGISTER_ISR0_OFFSET 0x3a
@@ -207,6 +226,7 @@ struct ESCC2State {
DeviceState parent;
MemoryRegion io;
+ qemu_irq irq;
ESCC2ChannelState channel[CHANNEL_COUNT];
};
@@ -218,9 +238,62 @@ struct ESCC2State {
typedef struct ESCC2ISAState {
ISADevice parent;
uint32_t iobase;
+ uint32_t irq;
struct ESCC2State controller;
} ESCC2ISAState;
+static void escc2_irq_update(ESCC2State *controller)
+{
+ bool power;
+ uint8_t gis;
+ ESCC2ChannelState *a, *b;
+
+ gis = 0;
+ a = CONTROLLER_CHANNEL_A(controller);
+ b = CONTROLLER_CHANNEL_B(controller);
+
+ /*
+ * Interrupts are not propagated to the CPU when in power-down mode. There
+ * is an exception for interrupts from the universal port.
+ */
+ power = REGISTER_READ(a, REGISTER_CCR0) & REGISTER_CCR0_PU;
+
+ if (REGISTER_READ(a, REGISTER_ISR0) & ~(REGISTER_READ(a, REGISTER_IMR0))) {
+ gis |= REGISTER_GIS_ISA0;
+ }
+ if (REGISTER_READ(a, REGISTER_ISR1) & ~(REGISTER_READ(a, REGISTER_IMR1))) {
+ gis |= REGISTER_GIS_ISA1;
+ }
+
+ if (REGISTER_READ(b, REGISTER_ISR0) & ~(REGISTER_READ(b, REGISTER_IMR0))) {
+ gis |= REGISTER_GIS_ISB0;
+ }
+ if (REGISTER_READ(b, REGISTER_ISR1) & ~(REGISTER_READ(b, REGISTER_IMR1))) {
+ gis |= REGISTER_GIS_ISB1;
+ }
+
+ if (REGISTER_READ(a, REGISTER_PIS) & ~(REGISTER_READ(a, REGISTER_PIM))) {
+ gis |= REGISTER_GIS_PI;
+ /*
+ * Ensure that interrupts are propagated even if the controller is in
+ * power-down mode.
+ */
+ power = true;
+ }
+
+ /* GIS is accessible from either channel and must be synchronised. */
+ REGISTER_WRITE(a, REGISTER_GIS, gis);
+ REGISTER_WRITE(b, REGISTER_GIS, gis);
+
+ if (gis && power) {
+ qemu_irq_raise(controller->irq);
+ } else {
+ qemu_irq_lower(controller->irq);
+ }
+
+ trace_escc2_irq_update(gis);
+}
+
static void escc2_channel_reset(ESCC2ChannelState *channel)
{
unsigned int i;
@@ -320,15 +393,22 @@ static uint64_t escc2_mem_read(void *opaque, hwaddr addr,
unsigned size)
break;
case REGISTER_ISR0_OFFSET:
value = REGISTER_READ(channel, REGISTER_ISR0);
+ REGISTER_WRITE(channel, REGISTER_ISR0, 0);
+ escc2_irq_update(controller);
break;
case REGISTER_ISR1_OFFSET:
value = REGISTER_READ(channel, REGISTER_ISR1);
+ REGISTER_WRITE(channel, REGISTER_ISR1, 0);
+ escc2_irq_update(controller);
break;
case REGISTER_PVR_OFFSET:
value = REGISTER_READ(channel, REGISTER_PVR);
break;
case REGISTER_PIS_OFFSET:
value = REGISTER_READ(channel, REGISTER_PIS);
+ REGISTER_WRITE(CONTROLLER_CHANNEL_A(controller), REGISTER_PIS, 0);
+ REGISTER_WRITE(CONTROLLER_CHANNEL_B(controller), REGISTER_PIS, 0);
+ escc2_irq_update(controller);
break;
case REGISTER_PCR_OFFSET:
value = REGISTER_READ(channel, REGISTER_PCR);
@@ -506,6 +586,13 @@ static void escc2_isa_realize(DeviceState *dev, Error
**errp)
return;
}
+ if (isa->irq == -1) {
+ error_setg(errp, "IRQ must be provided.");
+ return;
+ }
+
+ isa_init_irq(ISA_DEVICE(dev), &controller->irq, isa->irq);
+
object_property_set_bool(OBJECT(controller), true, "realized", errp);
if (*errp) {
return;
@@ -536,6 +623,7 @@ static Property escc2_properties[] = {
static Property escc2_isa_properties[] = {
DEFINE_PROP_UINT32("iobase", ESCC2ISAState, iobase, -1),
+ DEFINE_PROP_UINT32("irq", ESCC2ISAState, irq, -1),
DEFINE_PROP_END_OF_LIST()
};
diff --git a/hw/char/trace-events b/hw/char/trace-events
index 65c176f582..b4f4f30815 100644
--- a/hw/char/trace-events
+++ b/hw/char/trace-events
@@ -57,6 +57,7 @@ escc_kbd_command(int val) "Command %d"
escc_sunmouse_event(int dx, int dy, int buttons_state) "dx=%d dy=%d
buttons=0x%01x"
# escc2.c
+escc2_irq_update(uint8_t gis) "value 0x%x"
escc2_mem_read(char channel, uint32_t addr, uint8_t value) "channel %c addr
0x%x value 0x%x"
escc2_mem_write(char channel, uint32_t addr, uint8_t value) "channel %c addr
0x%x value 0x%x"
--
2.26.2
- [PATCH 0/8] ESCC2, Jasper Lowell, 2020/06/17
- [PATCH 1/8] hw/char/escc2: Add device, Jasper Lowell, 2020/06/17
- [PATCH 2/8] hw/char/escc2: Handle interrupt generation,
Jasper Lowell <=
- [PATCH 3/8] hw/char/escc2: Add character device backend, Jasper Lowell, 2020/06/17
- [PATCH 5/8] hw/char/escc2: Add Receiver Reset (RRES) command, Jasper Lowell, 2020/06/17
- [PATCH 4/8] hw/char/escc2: Add clock generation, Jasper Lowell, 2020/06/17
- [PATCH 6/8] hw/char/escc2: Add RFRD command, Jasper Lowell, 2020/06/17
- [PATCH 7/8] hw/char/escc2: Add Transmit Frame (XF) command, Jasper Lowell, 2020/06/17
- [PATCH 8/8] hw/char/escc2: Add XRES command, Jasper Lowell, 2020/06/17
- Re: [PATCH 0/8] ESCC2, no-reply, 2020/06/17
- Re: [PATCH 0/8] ESCC2, Philippe Mathieu-Daudé, 2020/06/17
- Re: [PATCH 0/8] ESCC2, Artyom Tarasenko, 2020/06/17