1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25#include <stdio.h>
26#include "hw.h"
27#include "etraxfs.h"
28
29#define D(x)
30
31struct fs_pic_state_t
32{
33 CPUState *env;
34
35 uint32_t rw_mask;
36
37 uint32_t r_vect;
38
39 uint32_t r_masked_vect;
40 uint32_t r_nmi;
41 uint32_t r_guru;
42};
43
44static void pic_update(struct fs_pic_state_t *fs)
45{
46 CPUState *env = fs->env;
47 int i;
48 uint32_t vector = 0;
49
50 fs->r_masked_vect = fs->r_vect & fs->rw_mask;
51
52
53
54
55
56 if (fs->r_masked_vect) {
57 uint32_t mv = fs->r_masked_vect;
58 for (i = 0; i < 31; i++) {
59 if (mv & 1) {
60 vector = 0x31 + i;
61
62 if (mv > 1)
63 vector = 0x30;
64 break;
65 }
66 mv >>= 1;
67 }
68 if (vector) {
69 env->interrupt_vector = vector;
70 D(printf("%s vector=%x\n", __func__, vector));
71 cpu_interrupt(env, CPU_INTERRUPT_HARD);
72 }
73 } else {
74 env->interrupt_vector = 0;
75 cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
76 D(printf("%s reset irqs\n", __func__));
77 }
78}
79
80static uint32_t pic_readl (void *opaque, target_phys_addr_t addr)
81{
82 struct fs_pic_state_t *fs = opaque;
83 uint32_t rval;
84
85 switch (addr)
86 {
87 case 0x0:
88 rval = fs->rw_mask;
89 break;
90 case 0x4:
91 rval = fs->r_vect;
92 break;
93 case 0x8:
94 rval = fs->r_masked_vect;
95 break;
96 case 0xc:
97 rval = fs->r_nmi;
98 break;
99 case 0x10:
100 rval = fs->r_guru;
101 break;
102 default:
103 cpu_abort(fs->env, "invalid PIC register.\n");
104 break;
105
106 }
107 D(printf("%s %x=%x\n", __func__, addr, rval));
108 return rval;
109}
110
111static void
112pic_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
113{
114 struct fs_pic_state_t *fs = opaque;
115 D(printf("%s addr=%x val=%x\n", __func__, addr, value));
116 switch (addr)
117 {
118 case 0x0:
119 fs->rw_mask = value;
120 pic_update(fs);
121 break;
122 default:
123 cpu_abort(fs->env, "invalid PIC register.\n");
124 break;
125 }
126}
127
128static CPUReadMemoryFunc *pic_read[] = {
129 NULL, NULL,
130 &pic_readl,
131};
132
133static CPUWriteMemoryFunc *pic_write[] = {
134 NULL, NULL,
135 &pic_writel,
136};
137
138void pic_info(void)
139{
140}
141
142void irq_info(void)
143{
144}
145
146static void irq_handler(void *opaque, int irq, int level)
147{
148 struct fs_pic_state_t *fs = (void *)opaque;
149
150 D(printf("%s irq=%d level=%d mask=%x v=%x mv=%x\n",
151 __func__, irq, level,
152 fs->rw_mask, fs->r_vect, fs->r_masked_vect));
153
154 irq -= 1;
155 fs->r_vect &= ~(1 << irq);
156 fs->r_vect |= (!!level << irq);
157
158 pic_update(fs);
159}
160
161static void nmi_handler(void *opaque, int irq, int level)
162{
163 struct fs_pic_state_t *fs = (void *)opaque;
164 CPUState *env = fs->env;
165 uint32_t mask;
166
167 mask = 1 << irq;
168 if (level)
169 fs->r_nmi |= mask;
170 else
171 fs->r_nmi &= ~mask;
172
173 if (fs->r_nmi)
174 cpu_interrupt(env, CPU_INTERRUPT_NMI);
175 else
176 cpu_reset_interrupt(env, CPU_INTERRUPT_NMI);
177}
178
179static void guru_handler(void *opaque, int irq, int level)
180{
181 struct fs_pic_state_t *fs = (void *)opaque;
182 CPUState *env = fs->env;
183 cpu_abort(env, "%s unsupported exception\n", __func__);
184
185}
186
187struct etraxfs_pic *etraxfs_pic_init(CPUState *env, target_phys_addr_t base)
188{
189 struct fs_pic_state_t *fs = NULL;
190 struct etraxfs_pic *pic = NULL;
191 int intr_vect_regs;
192
193 pic = qemu_mallocz(sizeof *pic);
194 pic->internal = fs = qemu_mallocz(sizeof *fs);
195
196 fs->env = env;
197 pic->irq = qemu_allocate_irqs(irq_handler, fs, 30);
198 pic->nmi = qemu_allocate_irqs(nmi_handler, fs, 2);
199 pic->guru = qemu_allocate_irqs(guru_handler, fs, 1);
200
201 intr_vect_regs = cpu_register_io_memory(0, pic_read, pic_write, fs);
202 cpu_register_physical_memory(base, 0x14, intr_vect_regs);
203
204 return pic;
205}
206