Commit 67e42751dc4956509f5665bc64d883aaff9f771f

Authored by blueswir1
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;