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,10 +199,8 @@ static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr, | ||
199 | count = ((uint64_t)s->counthigh << 32) | s->count; | 199 | count = ((uint64_t)s->counthigh << 32) | s->count; |
200 | DPRINTF("processor %d user timer set to %016llx\n", s->slave_index, | 200 | DPRINTF("processor %d user timer set to %016llx\n", s->slave_index, |
201 | count); | 201 | count); |
202 | - if (s->timer) { | 202 | + if (s->timer) |
203 | ptimer_set_count(s->timer, LIMIT_TO_PERIODS(s->limit - count)); | 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 | } else { | 204 | } else { |
207 | // set limit, reset counter | 205 | // set limit, reset counter |
208 | qemu_irq_lower(s->irq); | 206 | qemu_irq_lower(s->irq); |
@@ -227,10 +225,8 @@ static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr, | @@ -227,10 +225,8 @@ static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr, | ||
227 | count = ((uint64_t)s->counthigh) << 32 | s->count; | 225 | count = ((uint64_t)s->counthigh) << 32 | s->count; |
228 | DPRINTF("processor %d user timer set to %016llx\n", s->slave_index, | 226 | DPRINTF("processor %d user timer set to %016llx\n", s->slave_index, |
229 | count); | 227 | count); |
230 | - if (s->timer) { | 228 | + if (s->timer) |
231 | ptimer_set_count(s->timer, LIMIT_TO_PERIODS(s->limit - count)); | 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 | } else | 230 | } else |
235 | DPRINTF("not user timer\n"); | 231 | DPRINTF("not user timer\n"); |
236 | break; | 232 | break; |
@@ -265,22 +261,39 @@ static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr, | @@ -265,22 +261,39 @@ static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr, | ||
265 | unsigned int i; | 261 | unsigned int i; |
266 | 262 | ||
267 | for (i = 0; i < s->num_slaves; i++) { | 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 | } else | 297 | } else |
285 | DPRINTF("not system timer\n"); | 298 | DPRINTF("not system timer\n"); |
286 | break; | 299 | break; |