Revision 8d13fcc0 hw/etraxfs_pic.c
b/hw/etraxfs_pic.c | ||
---|---|---|
29 | 29 |
|
30 | 30 |
#define D(x) |
31 | 31 |
|
32 |
#define R_RW_MASK 0 |
|
33 |
#define R_R_VECT 1 |
|
34 |
#define R_R_MASKED_VECT 2 |
|
35 |
#define R_R_NMI 3 |
|
36 |
#define R_R_GURU 4 |
|
37 |
#define R_MAX 5 |
|
38 |
|
|
32 | 39 |
struct fs_pic_state_t |
33 | 40 |
{ |
34 | 41 |
CPUState *env; |
35 |
|
|
36 |
uint32_t rw_mask; |
|
37 |
/* Active interrupt lines. */ |
|
38 |
uint32_t r_vect; |
|
39 |
/* Active lines, gated through the mask. */ |
|
40 |
uint32_t r_masked_vect; |
|
41 |
uint32_t r_nmi; |
|
42 |
uint32_t r_guru; |
|
42 |
uint32_t regs[R_MAX]; |
|
43 | 43 |
}; |
44 | 44 |
|
45 | 45 |
static void pic_update(struct fs_pic_state_t *fs) |
46 | 46 |
{ |
47 | 47 |
CPUState *env = fs->env; |
48 |
int i; |
|
49 | 48 |
uint32_t vector = 0; |
49 |
int i; |
|
50 | 50 |
|
51 |
fs->r_masked_vect = fs->r_vect & fs->rw_mask;
|
|
51 |
fs->regs[R_R_MASKED_VECT] = fs->regs[R_R_VECT] & fs->regs[R_RW_MASK];
|
|
52 | 52 |
|
53 | 53 |
/* The ETRAX interrupt controller signals interrupts to teh core |
54 | 54 |
through an interrupt request wire and an irq vector bus. If |
55 | 55 |
multiple interrupts are simultaneously active it chooses vector |
56 | 56 |
0x30 and lets the sw choose the priorities. */ |
57 |
if (fs->r_masked_vect) {
|
|
58 |
uint32_t mv = fs->r_masked_vect;
|
|
57 |
if (fs->regs[R_R_MASKED_VECT]) {
|
|
58 |
uint32_t mv = fs->regs[R_R_MASKED_VECT];
|
|
59 | 59 |
for (i = 0; i < 31; i++) { |
60 | 60 |
if (mv & 1) { |
61 | 61 |
vector = 0x31 + i; |
... | ... | |
83 | 83 |
struct fs_pic_state_t *fs = opaque; |
84 | 84 |
uint32_t rval; |
85 | 85 |
|
86 |
switch (addr) |
|
87 |
{ |
|
88 |
case 0x0: |
|
89 |
rval = fs->rw_mask; |
|
90 |
break; |
|
91 |
case 0x4: |
|
92 |
rval = fs->r_vect; |
|
93 |
break; |
|
94 |
case 0x8: |
|
95 |
rval = fs->r_masked_vect; |
|
96 |
break; |
|
97 |
case 0xc: |
|
98 |
rval = fs->r_nmi; |
|
99 |
break; |
|
100 |
case 0x10: |
|
101 |
rval = fs->r_guru; |
|
102 |
break; |
|
103 |
default: |
|
104 |
cpu_abort(fs->env, "invalid PIC register.\n"); |
|
105 |
break; |
|
106 |
|
|
107 |
} |
|
86 |
rval = fs->regs[addr >> 2]; |
|
108 | 87 |
D(printf("%s %x=%x\n", __func__, addr, rval)); |
109 | 88 |
return rval; |
110 | 89 |
} |
... | ... | |
114 | 93 |
{ |
115 | 94 |
struct fs_pic_state_t *fs = opaque; |
116 | 95 |
D(printf("%s addr=%x val=%x\n", __func__, addr, value)); |
117 |
switch (addr) |
|
118 |
{ |
|
119 |
case 0x0: |
|
120 |
fs->rw_mask = value; |
|
121 |
pic_update(fs); |
|
122 |
break; |
|
123 |
default: |
|
124 |
cpu_abort(fs->env, "invalid PIC register.\n"); |
|
125 |
break; |
|
96 |
|
|
97 |
if (addr == R_RW_MASK) { |
|
98 |
fs->regs[R_RW_MASK] = value; |
|
99 |
pic_update(fs); |
|
126 | 100 |
} |
127 | 101 |
} |
128 | 102 |
|
... | ... | |
147 | 121 |
static void irq_handler(void *opaque, int irq, int level) |
148 | 122 |
{ |
149 | 123 |
struct fs_pic_state_t *fs = (void *)opaque; |
150 |
|
|
151 |
D(printf("%s irq=%d level=%d mask=%x v=%x mv=%x\n", |
|
152 |
__func__, irq, level, |
|
153 |
fs->rw_mask, fs->r_vect, fs->r_masked_vect)); |
|
154 |
|
|
155 | 124 |
irq -= 1; |
156 |
fs->r_vect &= ~(1 << irq);
|
|
157 |
fs->r_vect |= (!!level << irq);
|
|
125 |
fs->regs[R_R_VECT] &= ~(1 << irq);
|
|
126 |
fs->regs[R_R_VECT] |= (!!level << irq);
|
|
158 | 127 |
|
159 | 128 |
pic_update(fs); |
160 | 129 |
} |
... | ... | |
167 | 136 |
|
168 | 137 |
mask = 1 << irq; |
169 | 138 |
if (level) |
170 |
fs->r_nmi |= mask;
|
|
139 |
fs->regs[R_R_NMI] |= mask;
|
|
171 | 140 |
else |
172 |
fs->r_nmi &= ~mask;
|
|
141 |
fs->regs[R_R_NMI] &= ~mask;
|
|
173 | 142 |
|
174 |
if (fs->r_nmi)
|
|
143 |
if (fs->regs[R_R_NMI])
|
|
175 | 144 |
cpu_interrupt(env, CPU_INTERRUPT_NMI); |
176 | 145 |
else |
177 | 146 |
cpu_reset_interrupt(env, CPU_INTERRUPT_NMI); |
... | ... | |
180 | 149 |
static void guru_handler(void *opaque, int irq, int level) |
181 | 150 |
{ |
182 | 151 |
struct fs_pic_state_t *fs = (void *)opaque; |
183 |
CPUState *env = fs->env; |
|
184 |
cpu_abort(env, "%s unsupported exception\n", __func__); |
|
185 |
|
|
152 |
cpu_abort(fs->env, "%s unsupported exception\n", __func__); |
|
186 | 153 |
} |
187 | 154 |
|
188 | 155 |
struct etraxfs_pic *etraxfs_pic_init(CPUState *env, target_phys_addr_t base) |
... | ... | |
200 | 167 |
pic->guru = qemu_allocate_irqs(guru_handler, fs, 1); |
201 | 168 |
|
202 | 169 |
intr_vect_regs = cpu_register_io_memory(0, pic_read, pic_write, fs); |
203 |
cpu_register_physical_memory(base, 0x14, intr_vect_regs);
|
|
170 |
cpu_register_physical_memory(base, R_MAX * 4, intr_vect_regs);
|
|
204 | 171 |
|
205 | 172 |
return pic; |
206 | 173 |
} |
Also available in: Unified diff