aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2018-10-29 23:34:26 -0700
committerH. Peter Anvin <hpa@zytor.com>2018-10-29 23:34:26 -0700
commit64e32a88a18c3ff6790578a62249b40411c829d9 (patch)
treed1cb6f6f70650ad39d2f454ef4912d7433cb8067
parent667f4f71e8a875e199ab61ed15d4da45d8402249 (diff)
downloadabc80sim-64e32a88a18c3ff6790578a62249b40411c829d9.tar.gz
abc80sim-64e32a88a18c3ff6790578a62249b40411c829d9.tar.xz
abc80sim-64e32a88a18c3ff6790578a62249b40411c829d9.zip
irq: change the IRQ interface to use struct z80_irq consistently
It is better than to futz with numeric priority levels, even though it otherwise would be theoretically possible to use a shared z80_irq structure for more than one interrupt: it is simply not worth it. Using struct z80_irq * consistently makes for a more flexible API in the future.
-rw-r--r--abcio.c8
-rw-r--r--cas.c16
-rw-r--r--clock.c2
-rw-r--r--z80irq.c32
-rw-r--r--z80irq.h8
5 files changed, 27 insertions, 39 deletions
diff --git a/abcio.c b/abcio.c
index 21ee564..dd1fde3 100644
--- a/abcio.c
+++ b/abcio.c
@@ -21,7 +21,7 @@ static uint8_t keyb_fakedata;
/* Fake minimal-touch input */
bool faketype;
-static int keyb_intack_fake(unsigned int prio, struct z80_irq *irq);
+static int keyb_intack_fake(struct z80_irq *irq);
static struct z80_irq *keyb_irq;
static struct z80_irq keyb_irq_80 =
@@ -186,12 +186,10 @@ static unsigned int get_key(void)
return rv;
}
-static int keyb_intack_fake(unsigned int prio, struct z80_irq *irq)
+static int keyb_intack_fake(struct z80_irq *irq)
{
unsigned int data = get_key();
- (void)prio;
-
keyb_fakedata = (data & 0x7f) | ((data & KEYB_NEW) ? 0x80 : 0x00);
return irq->vector;
@@ -454,7 +452,7 @@ void keyboard_down(int sym)
}
keyb_data = sym | KEYB_NEW | KEYB_DOWN;
- z80_interrupt(keyb_irq->prio);
+ z80_interrupt(keyb_irq);
}
unsigned int keyboard_up(void)
diff --git a/cas.c b/cas.c
index 38d3ca2..6c4dae4 100644
--- a/cas.c
+++ b/cas.c
@@ -170,7 +170,7 @@ static bool cas_edge(void)
/*
* ABC80 PIO interfacing
*/
-static inline int pio_eoi(unsigned int, struct z80_irq *);
+static inline int pio_eoi(struct z80_irq *);
enum pioctl_state {
pcs_init,
@@ -213,14 +213,13 @@ static void pio_check_interrupt(struct pio *pio)
(pio->irqctl & 0x40) ? (masked == pio->irqmask) : (masked != 0);
if (trigger)
- z80_interrupt(pio->irq.prio);
+ z80_interrupt(&pio->irq);
else
- z80_clear_interrupt(pio->irq.prio);
+ z80_clear_interrupt(&pio->irq);
}
-static int pio_eoi(unsigned int prio, struct z80_irq *irq)
+static int pio_eoi(struct z80_irq *irq)
{
- (void)prio;
pio_check_interrupt((struct pio *)(irq->pvt));
return 0;
}
@@ -329,7 +328,7 @@ void abc80_cas_init(void)
* - At end of block either hardware or software go back to need sync
*/
-static int sio_cas_eoi(unsigned int prio, struct z80_irq *irq);
+static int sio_cas_eoi(struct z80_irq *irq);
static uint8_t sio_cas_ctl[8];
static bool cas_first_rx_armed = true;
@@ -354,9 +353,8 @@ static inline bool cas_rx_interrupt(bool huntok)
static void cas_poll_interrupt(void);
-static int sio_cas_eoi(unsigned int prio, struct z80_irq *irq)
+static int sio_cas_eoi(struct z80_irq *irq)
{
- (void)prio;
(void)irq;
cas_poll_interrupt();
@@ -372,7 +370,7 @@ static void cas_poll_interrupt(void)
sio_cas_ctl[3] &= ~0x10; /* Not hunting anymore */
cas_first_rx_armed = false;
sio_cas_irq.vector = (sio_cas_ctl[2] & ~0x0f) | 0x04;
- z80_interrupt(sio_cas_irq.prio);
+ z80_interrupt(&sio_cas_irq);
}
void abc800_sio_cas_out(uint8_t port, uint8_t v)
diff --git a/clock.c b/clock.c
index 14eaa0e..2ba1c6a 100644
--- a/clock.c
+++ b/clock.c
@@ -197,7 +197,7 @@ static struct z80_irq ctc_irq[4] =
static void abc800_clock_tick(void)
{
if ((ctc_ctl[3] & 0xc0) == 0x80)
- z80_interrupt(IRQ800_CTC3);
+ z80_interrupt(&ctc_irq[3]);
}
/*
diff --git a/z80irq.c b/z80irq.c
index 2919db3..61cbb24 100644
--- a/z80irq.c
+++ b/z80irq.c
@@ -5,7 +5,6 @@
volatile unsigned int irq_pending; /* Quick way to poll */
static struct z80_irq *irqs[MAX_IRQ];
static struct z80_irq *current_irq;
-static unsigned int current_prio;
void z80_register_irq(struct z80_irq *irq)
{
@@ -36,13 +35,12 @@ int z80_intack(void)
irq = irqs[prio];
if (unlikely(irq->intack))
- vector = irq->intack(prio, irq);
+ vector = irq->intack(irq);
else
vector = irq->vector;
} while (vector < 0);
current_irq = irq;
- current_prio = prio;
return vector;
}
@@ -58,10 +56,10 @@ void z80_eoi(void)
if (!irq)
return; /* No known interrupt to EOI */
- if (irq->eoi)
- irq->eoi(current_prio, irq);
-
current_irq = NULL;
+
+ if (irq->eoi)
+ irq->eoi(irq);
}
/*
@@ -71,38 +69,35 @@ void z80_eoi(void)
*/
#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
-bool z80_interrupt(unsigned int prio)
+bool z80_interrupt(struct z80_irq *irq)
{
bool raised;
asm volatile("lock btsl %2,%0"
: "+m" (irq_pending), "=@ccnc" (raised)
- : "ri" (prio));
+ : "rN" (irq->prio));
return raised;
}
-bool z80_clear_interrupt(unsigned int prio)
+bool z80_clear_interrupt(struct z80_irq *irq)
{
bool cleared;
asm volatile("lock btrl %2,%0"
: "+m" (irq_pending), "=@ccc" (cleared)
- : "ri" (prio));
+ : "rN" (irq->prio));
return cleared;
}
#else
-bool z80_interrupt(unsigned int prio)
+bool z80_interrupt(struct z80_irq *irq)
{
unsigned int irqmask, irqpend;
- if (prio >= MAX_IRQ)
- return false;
-
- irqmask = 1U << prio;
+ irqmask = 1U << irq->prio;
irqpend = irq_pending;
do {
if (irqpend & irqmask)
@@ -112,14 +107,11 @@ bool z80_interrupt(unsigned int prio)
return true;
}
-bool z80_clear_interrupt(unsigned int prio)
+bool z80_clear_interrupt(struct z80_irq *irq)
{
unsigned int irqmask, irqpend;
- if (prio >= MAX_IRQ)
- return false;
-
- irqmask = 1U << prio;
+ irqmask = 1U << irq->prio;
irqpend = irq_pending;
do {
if (!(irqpend & irqmask))
diff --git a/z80irq.h b/z80irq.h
index 9e2c1dc..f4f8c1e 100644
--- a/z80irq.h
+++ b/z80irq.h
@@ -4,14 +4,14 @@
#include "compiler.h"
#include "z80.h"
-typedef int (*irq_func)(unsigned int prio, struct z80_irq *irq);
+typedef int (*irq_func)(struct z80_irq *irq);
struct z80_irq {
irq_func intack;
irq_func eoi;
void *pvt; /* Available for user */
int vector; /* Available for user if intack defined */
- unsigned int prio; /* Available for user after register_irq */
+ unsigned int prio; /* Priority level */
};
#define MAX_IRQ 32
@@ -25,7 +25,7 @@ static inline bool poll_irq(void)
void z80_register_irq(struct z80_irq *irq);
int z80_intack(void);
void z80_eoi(void);
-bool z80_interrupt(unsigned int prio);
-bool z80_clear_interrupt(unsigned int prio);
+bool z80_interrupt(struct z80_irq *irq);
+bool z80_clear_interrupt(struct z80_irq *irq);
#endif /* Z80IRQ_H */