Commit 67e42751dc4956509f5665bc64d883aaff9f771f
1 parent
e5e38121
Fix user timer mode change (Robert Reif)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3933 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
33 additions
and
20 deletions
hw/slavio_timer.c
... | ... | @@ -199,10 +199,8 @@ static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr, |
199 | 199 | count = ((uint64_t)s->counthigh << 32) | s->count; |
200 | 200 | DPRINTF("processor %d user timer set to %016llx\n", s->slave_index, |
201 | 201 | count); |
202 | - if (s->timer) { | |
202 | + if (s->timer) | |
203 | 203 | ptimer_set_count(s->timer, LIMIT_TO_PERIODS(s->limit - count)); |
204 | - ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(s->limit), 0); | |
205 | - } | |
206 | 204 | } else { |
207 | 205 | // set limit, reset counter |
208 | 206 | qemu_irq_lower(s->irq); |
... | ... | @@ -227,10 +225,8 @@ static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr, |
227 | 225 | count = ((uint64_t)s->counthigh) << 32 | s->count; |
228 | 226 | DPRINTF("processor %d user timer set to %016llx\n", s->slave_index, |
229 | 227 | count); |
230 | - if (s->timer) { | |
228 | + if (s->timer) | |
231 | 229 | ptimer_set_count(s->timer, LIMIT_TO_PERIODS(s->limit - count)); |
232 | - ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(s->limit), 0); | |
233 | - } | |
234 | 230 | } else |
235 | 231 | DPRINTF("not user timer\n"); |
236 | 232 | break; |
... | ... | @@ -265,22 +261,39 @@ static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr, |
265 | 261 | unsigned int i; |
266 | 262 | |
267 | 263 | for (i = 0; i < s->num_slaves; i++) { |
268 | - if (val & (1 << i)) { | |
269 | - qemu_irq_lower(s->slave[i]->irq); | |
270 | - s->slave[i]->limit = -1ULL; | |
271 | - } else { | |
272 | - ptimer_stop(s->slave[i]->timer); | |
273 | - } | |
274 | - if ((val & (1 << i)) != (s->slave_mode & (1 << i))) { | |
275 | - ptimer_stop(s->slave[i]->timer); | |
276 | - ptimer_set_limit(s->slave[i]->timer, | |
277 | - LIMIT_TO_PERIODS(s->slave[i]->limit), 1); | |
278 | - DPRINTF("processor %d timer changed\n", | |
279 | - s->slave[i]->slave_index); | |
280 | - ptimer_run(s->slave[i]->timer, 0); | |
264 | + unsigned int processor = 1 << i; | |
265 | + | |
266 | + // check for a change in timer mode for this processor | |
267 | + if ((val & processor) != (s->slave_mode & processor)) { | |
268 | + if (val & processor) { // counter -> user timer | |
269 | + qemu_irq_lower(s->slave[i]->irq); | |
270 | + // counters are always running | |
271 | + ptimer_stop(s->slave[i]->timer); | |
272 | + s->slave[i]->running = 0; | |
273 | + // user timer limit is always the same | |
274 | + s->slave[i]->limit = TIMER_MAX_COUNT64; | |
275 | + ptimer_set_limit(s->slave[i]->timer, | |
276 | + LIMIT_TO_PERIODS(s->slave[i]->limit), 1); | |
277 | + // set this processors user timer bit in config | |
278 | + // register | |
279 | + s->slave_mode |= processor; | |
280 | + DPRINTF("processor %d changed from counter to user " | |
281 | + "timer\n", s->slave[i]->slave_index); | |
282 | + } else { // user timer -> counter | |
283 | + // stop the user timer if it is running | |
284 | + if (s->slave[i]->running) | |
285 | + ptimer_stop(s->slave[i]->timer); | |
286 | + // start the counter | |
287 | + ptimer_run(s->slave[i]->timer, 0); | |
288 | + s->slave[i]->running = 1; | |
289 | + // clear this processors user timer bit in config | |
290 | + // register | |
291 | + s->slave_mode &= ~processor; | |
292 | + DPRINTF("processor %d changed from user timer to " | |
293 | + "counter\n", s->slave[i]->slave_index); | |
294 | + } | |
281 | 295 | } |
282 | 296 | } |
283 | - s->slave_mode = val & ((1 << s->num_slaves) - 1); | |
284 | 297 | } else |
285 | 298 | DPRINTF("not system timer\n"); |
286 | 299 | break; | ... | ... |