Revision 22a9fe38 hw/hpet.c
b/hw/hpet.c | ||
---|---|---|
159 | 159 |
} |
160 | 160 |
} |
161 | 161 |
|
162 |
static void update_irq(struct HPETTimer *timer) |
|
162 |
static void update_irq(struct HPETTimer *timer, int set)
|
|
163 | 163 |
{ |
164 |
uint64_t mask; |
|
165 |
HPETState *s; |
|
164 | 166 |
int route; |
165 | 167 |
|
166 | 168 |
if (timer->tn <= 1 && hpet_in_legacy_mode(timer->state)) { |
... | ... | |
172 | 174 |
} else { |
173 | 175 |
route = timer_int_route(timer); |
174 | 176 |
} |
175 |
if (!timer_enabled(timer) || !hpet_enabled(timer->state)) { |
|
176 |
return; |
|
177 |
s = timer->state; |
|
178 |
mask = 1 << timer->tn; |
|
179 |
if (!set || !timer_enabled(timer) || !hpet_enabled(timer->state)) { |
|
180 |
s->isr &= ~mask; |
|
181 |
qemu_irq_lower(s->irqs[route]); |
|
182 |
} else if (timer->config & HPET_TN_TYPE_LEVEL) { |
|
183 |
s->isr |= mask; |
|
184 |
qemu_irq_raise(s->irqs[route]); |
|
185 |
} else { |
|
186 |
s->isr &= ~mask; |
|
187 |
qemu_irq_pulse(s->irqs[route]); |
|
177 | 188 |
} |
178 |
qemu_irq_pulse(timer->state->irqs[route]); |
|
179 | 189 |
} |
180 | 190 |
|
181 | 191 |
static void hpet_pre_save(void *opaque) |
... | ... | |
261 | 271 |
t->wrap_flag = 0; |
262 | 272 |
} |
263 | 273 |
} |
264 |
update_irq(t); |
|
274 |
update_irq(t, 1);
|
|
265 | 275 |
} |
266 | 276 |
|
267 | 277 |
static void hpet_set_timer(HPETTimer *t) |
... | ... | |
291 | 301 |
static void hpet_del_timer(HPETTimer *t) |
292 | 302 |
{ |
293 | 303 |
qemu_del_timer(t->qemu_timer); |
304 |
update_irq(t, 0); |
|
294 | 305 |
} |
295 | 306 |
|
296 | 307 |
#ifdef HPET_DEBUG |
... | ... | |
423 | 434 |
timer->cmp = (uint32_t)timer->cmp; |
424 | 435 |
timer->period = (uint32_t)timer->period; |
425 | 436 |
} |
426 |
if (new_val & HPET_TN_TYPE_LEVEL) { |
|
427 |
printf("qemu: level-triggered hpet not supported\n"); |
|
428 |
exit (-1); |
|
429 |
} |
|
430 | 437 |
if (activating_bit(old_val, new_val, HPET_TN_ENABLE)) { |
431 | 438 |
hpet_set_timer(timer); |
432 | 439 |
} else if (deactivating_bit(old_val, new_val, HPET_TN_ENABLE)) { |
... | ... | |
522 | 529 |
DPRINTF("qemu: invalid HPET_CFG+4 write \n"); |
523 | 530 |
break; |
524 | 531 |
case HPET_STATUS: |
525 |
/* FIXME: need to handle level-triggered interrupts */ |
|
532 |
val = new_val & s->isr; |
|
533 |
for (i = 0; i < HPET_NUM_TIMERS; i++) { |
|
534 |
if (val & (1 << i)) { |
|
535 |
update_irq(&s->timer[i], 0); |
|
536 |
} |
|
537 |
} |
|
526 | 538 |
break; |
527 | 539 |
case HPET_COUNTER: |
528 | 540 |
if (hpet_enabled(s)) { |
Also available in: Unified diff