diff options
author | blueswir1 <blueswir1@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-01-26 09:13:46 +0000 |
---|---|---|
committer | blueswir1 <blueswir1@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-01-26 09:13:46 +0000 |
commit | 67e42751dc4956509f5665bc64d883aaff9f771f (patch) | |
tree | f797af3ea99a49a9ee7c7afb68dd1ab0218b9538 | |
parent | e5e38121576e57ea4f1f4acae01f58f0386ff0ba (diff) |
Fix user timer mode change (Robert Reif)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3933 c046a42c-6fe2-441c-8c8c-71466251a162
-rw-r--r-- | hw/slavio_timer.c | 53 |
1 files changed, 33 insertions, 20 deletions
diff --git a/hw/slavio_timer.c b/hw/slavio_timer.c index 412f331369..f129a5f0b0 100644 --- a/hw/slavio_timer.c +++ b/hw/slavio_timer.c @@ -199,10 +199,8 @@ static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr, count = ((uint64_t)s->counthigh << 32) | s->count; DPRINTF("processor %d user timer set to %016llx\n", s->slave_index, count); - if (s->timer) { + if (s->timer) ptimer_set_count(s->timer, LIMIT_TO_PERIODS(s->limit - count)); - ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(s->limit), 0); - } } else { // set limit, reset counter qemu_irq_lower(s->irq); @@ -227,10 +225,8 @@ static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr, count = ((uint64_t)s->counthigh) << 32 | s->count; DPRINTF("processor %d user timer set to %016llx\n", s->slave_index, count); - if (s->timer) { + if (s->timer) ptimer_set_count(s->timer, LIMIT_TO_PERIODS(s->limit - count)); - ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(s->limit), 0); - } } else DPRINTF("not user timer\n"); break; @@ -265,22 +261,39 @@ static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr, unsigned int i; for (i = 0; i < s->num_slaves; i++) { - if (val & (1 << i)) { - qemu_irq_lower(s->slave[i]->irq); - s->slave[i]->limit = -1ULL; - } else { - ptimer_stop(s->slave[i]->timer); - } - if ((val & (1 << i)) != (s->slave_mode & (1 << i))) { - ptimer_stop(s->slave[i]->timer); - ptimer_set_limit(s->slave[i]->timer, - LIMIT_TO_PERIODS(s->slave[i]->limit), 1); - DPRINTF("processor %d timer changed\n", - s->slave[i]->slave_index); - ptimer_run(s->slave[i]->timer, 0); + unsigned int processor = 1 << i; + + // check for a change in timer mode for this processor + if ((val & processor) != (s->slave_mode & processor)) { + if (val & processor) { // counter -> user timer + qemu_irq_lower(s->slave[i]->irq); + // counters are always running + ptimer_stop(s->slave[i]->timer); + s->slave[i]->running = 0; + // user timer limit is always the same + s->slave[i]->limit = TIMER_MAX_COUNT64; + ptimer_set_limit(s->slave[i]->timer, + LIMIT_TO_PERIODS(s->slave[i]->limit), 1); + // set this processors user timer bit in config + // register + s->slave_mode |= processor; + DPRINTF("processor %d changed from counter to user " + "timer\n", s->slave[i]->slave_index); + } else { // user timer -> counter + // stop the user timer if it is running + if (s->slave[i]->running) + ptimer_stop(s->slave[i]->timer); + // start the counter + ptimer_run(s->slave[i]->timer, 0); + s->slave[i]->running = 1; + // clear this processors user timer bit in config + // register + s->slave_mode &= ~processor; + DPRINTF("processor %d changed from user timer to " + "counter\n", s->slave[i]->slave_index); + } } } - s->slave_mode = val & ((1 << s->num_slaves) - 1); } else DPRINTF("not system timer\n"); break; |