Revision 70ea255d
b/hw/etraxfs_pic.c | ||
---|---|---|
41 | 41 |
uint32_t r_guru; |
42 | 42 |
}; |
43 | 43 |
|
44 |
static uint32_t pic_readb (void *opaque, target_phys_addr_t addr) |
|
45 |
{ |
|
46 |
return 0; |
|
47 |
} |
|
48 |
static uint32_t pic_readw (void *opaque, target_phys_addr_t addr) |
|
49 |
{ |
|
50 |
return 0; |
|
44 |
static 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 |
/* The ETRAX interrupt controller signals interrupts to teh core |
|
53 |
through an interrupt request wire and an irq vector bus. If |
|
54 |
multiple interrupts are simultaneously active it chooses vector |
|
55 |
0x30 and lets the sw choose the priorities. */ |
|
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 |
/* Check for multiple interrupts. */ |
|
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 |
} |
|
51 | 78 |
} |
52 | 79 |
|
53 | 80 |
static uint32_t pic_readl (void *opaque, target_phys_addr_t addr) |
... | ... | |
82 | 109 |
} |
83 | 110 |
|
84 | 111 |
static void |
85 |
pic_writeb (void *opaque, target_phys_addr_t addr, uint32_t value) |
|
86 |
{ |
|
87 |
} |
|
88 |
|
|
89 |
static void |
|
90 |
pic_writew (void *opaque, target_phys_addr_t addr, uint32_t value) |
|
91 |
{ |
|
92 |
} |
|
93 |
|
|
94 |
static void |
|
95 | 112 |
pic_writel (void *opaque, target_phys_addr_t addr, uint32_t value) |
96 | 113 |
{ |
97 | 114 |
struct fs_pic_state_t *fs = opaque; |
... | ... | |
100 | 117 |
{ |
101 | 118 |
case 0x0: |
102 | 119 |
fs->rw_mask = value; |
103 |
break; |
|
104 |
case 0x4: |
|
105 |
fs->r_vect = value; |
|
106 |
break; |
|
107 |
case 0x8: |
|
108 |
fs->r_masked_vect = value; |
|
109 |
break; |
|
110 |
case 0xc: |
|
111 |
fs->r_nmi = value; |
|
112 |
break; |
|
113 |
case 0x10: |
|
114 |
fs->r_guru = value; |
|
120 |
pic_update(fs); |
|
115 | 121 |
break; |
116 | 122 |
default: |
117 | 123 |
cpu_abort(fs->env, "invalid PIC register.\n"); |
... | ... | |
120 | 126 |
} |
121 | 127 |
|
122 | 128 |
static CPUReadMemoryFunc *pic_read[] = { |
123 |
&pic_readb, |
|
124 |
&pic_readw, |
|
129 |
NULL, NULL, |
|
125 | 130 |
&pic_readl, |
126 | 131 |
}; |
127 | 132 |
|
128 | 133 |
static CPUWriteMemoryFunc *pic_write[] = { |
129 |
&pic_writeb, |
|
130 |
&pic_writew, |
|
134 |
NULL, NULL, |
|
131 | 135 |
&pic_writel, |
132 | 136 |
}; |
133 | 137 |
|
... | ... | |
142 | 146 |
static void irq_handler(void *opaque, int irq, int level) |
143 | 147 |
{ |
144 | 148 |
struct fs_pic_state_t *fs = (void *)opaque; |
145 |
CPUState *env = fs->env; |
|
146 |
int i; |
|
147 |
uint32_t vector = 0; |
|
148 | 149 |
|
149 | 150 |
D(printf("%s irq=%d level=%d mask=%x v=%x mv=%x\n", |
150 | 151 |
__func__, irq, level, |
... | ... | |
153 | 154 |
irq -= 1; |
154 | 155 |
fs->r_vect &= ~(1 << irq); |
155 | 156 |
fs->r_vect |= (!!level << irq); |
156 |
fs->r_masked_vect = fs->r_vect & fs->rw_mask; |
|
157 | 157 |
|
158 |
/* The ETRAX interrupt controller signals interrupts to teh core |
|
159 |
through an interrupt request wire and an irq vector bus. If |
|
160 |
multiple interrupts are simultaneously active it chooses vector |
|
161 |
0x30 and lets the sw choose the priorities. */ |
|
162 |
if (fs->r_masked_vect) { |
|
163 |
uint32_t mv = fs->r_masked_vect; |
|
164 |
for (i = 0; i < 31; i++) { |
|
165 |
if (mv & 1) { |
|
166 |
vector = 0x31 + i; |
|
167 |
/* Check for multiple interrupts. */ |
|
168 |
if (mv > 1) |
|
169 |
vector = 0x30; |
|
170 |
break; |
|
171 |
} |
|
172 |
mv >>= 1; |
|
173 |
} |
|
174 |
if (vector) { |
|
175 |
env->interrupt_vector = vector; |
|
176 |
D(printf("%s vector=%x\n", __func__, vector)); |
|
177 |
cpu_interrupt(env, CPU_INTERRUPT_HARD); |
|
178 |
} |
|
179 |
} else { |
|
180 |
env->interrupt_vector = 0; |
|
181 |
cpu_reset_interrupt(env, CPU_INTERRUPT_HARD); |
|
182 |
D(printf("%s reset irqs\n", __func__)); |
|
183 |
} |
|
158 |
pic_update(fs); |
|
184 | 159 |
} |
185 | 160 |
|
186 | 161 |
static void nmi_handler(void *opaque, int irq, int level) |
... | ... | |
209 | 184 |
|
210 | 185 |
} |
211 | 186 |
|
212 |
|
|
213 | 187 |
struct etraxfs_pic *etraxfs_pic_init(CPUState *env, target_phys_addr_t base) |
214 | 188 |
{ |
215 | 189 |
struct fs_pic_state_t *fs = NULL; |
Also available in: Unified diff