Commit 61271e5c2d3eff4cc0c4845be291172c2015b6f1

Authored by bellard
1 parent aefce9af

more precise cuda timers


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1508 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 47 additions and 22 deletions
hw/cuda.c
... ... @@ -23,6 +23,8 @@
23 23 */
24 24 #include "vl.h"
25 25  
  26 +/* XXX: implement all timer modes */
  27 +
26 28 //#define DEBUG_CUDA
27 29 //#define DEBUG_CUDA_PACKET
28 30  
... ... @@ -41,6 +43,7 @@
41 43 #define IER_CLR 0 /* clear bits in IER */
42 44 #define SR_INT 0x04 /* Shift register full/empty */
43 45 #define T1_INT 0x40 /* Timer 1 interrupt */
  46 +#define T2_INT 0x20 /* Timer 2 interrupt */
44 47  
45 48 /* Bits in ACR */
46 49 #define T1MODE 0xc0 /* Timer 1 mode */
... ... @@ -91,7 +94,8 @@
91 94 #define RTC_OFFSET 2082844800
92 95  
93 96 typedef struct CUDATimer {
94   - unsigned int latch;
  97 + int index;
  98 + uint16_t latch;
95 99 uint16_t counter_value; /* counter value at load time */
96 100 int64_t load_time;
97 101 int64_t next_irq_time;
... ... @@ -154,10 +158,16 @@ static unsigned int get_counter(CUDATimer *s)
154 158  
155 159 d = muldiv64(qemu_get_clock(vm_clock) - s->load_time,
156 160 CUDA_TIMER_FREQ, ticks_per_sec);
157   - if (d <= s->counter_value) {
158   - counter = d;
  161 + if (s->index == 0) {
  162 + /* the timer goes down from latch to -1 (period of latch + 2) */
  163 + if (d <= (s->counter_value + 1)) {
  164 + counter = (s->counter_value - d) & 0xffff;
  165 + } else {
  166 + counter = (d - (s->counter_value + 1)) % (s->latch + 2);
  167 + counter = (s->latch - counter) & 0xffff;
  168 + }
159 169 } else {
160   - counter = s->latch - 1 - ((d - s->counter_value) % s->latch);
  170 + counter = (s->counter_value - d) & 0xffff;
161 171 }
162 172 return counter;
163 173 }
... ... @@ -175,17 +185,27 @@ static void set_counter(CUDAState *s, CUDATimer *ti, unsigned int val)
175 185  
176 186 static int64_t get_next_irq_time(CUDATimer *s, int64_t current_time)
177 187 {
178   - int64_t d, next_time, base;
  188 + int64_t d, next_time;
  189 + unsigned int counter;
  190 +
179 191 /* current counter value */
180 192 d = muldiv64(current_time - s->load_time,
181 193 CUDA_TIMER_FREQ, ticks_per_sec);
182   - if (d < s->counter_value) {
183   - next_time = s->counter_value + 1;
184   - } else
185   - {
186   - base = ((d - s->counter_value + 1) / s->latch);
187   - base = (base * s->latch) + s->counter_value;
188   - next_time = base + s->latch;
  194 + /* the timer goes down from latch to -1 (period of latch + 2) */
  195 + if (d <= (s->counter_value + 1)) {
  196 + counter = (s->counter_value - d) & 0xffff;
  197 + } else {
  198 + counter = (d - (s->counter_value + 1)) % (s->latch + 2);
  199 + counter = (s->latch - counter) & 0xffff;
  200 + }
  201 +
  202 + /* Note: we consider the irq is raised on 0 */
  203 + if (counter == 0xffff) {
  204 + next_time = d + s->latch + 1;
  205 + } else if (counter == 0) {
  206 + next_time = d + s->latch + 2;
  207 + } else {
  208 + next_time = d + counter;
189 209 }
190 210 #if 0
191 211 #ifdef DEBUG_CUDA
... ... @@ -249,17 +269,18 @@ static uint32_t cuda_readb(void *opaque, target_phys_addr_t addr)
249 269 break;
250 270 case 5:
251 271 val = get_counter(&s->timers[0]) >> 8;
252   - s->ifr &= ~T1_INT;
253 272 cuda_update_irq(s);
254 273 break;
255 274 case 6:
256 275 val = s->timers[0].latch & 0xff;
257 276 break;
258 277 case 7:
  278 + /* XXX: check this */
259 279 val = (s->timers[0].latch >> 8) & 0xff;
260 280 break;
261 281 case 8:
262 282 val = get_counter(&s->timers[1]) & 0xff;
  283 + s->ifr &= ~T2_INT;
263 284 break;
264 285 case 9:
265 286 val = get_counter(&s->timers[1]) >> 8;
... ... @@ -317,12 +338,13 @@ static void cuda_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
317 338 s->dira = val;
318 339 break;
319 340 case 4:
320   - val = val | (get_counter(&s->timers[0]) & 0xff00);
321   - set_counter(s, &s->timers[0], val);
  341 + s->timers[0].latch = (s->timers[0].latch & 0xff00) | val;
  342 + cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock));
322 343 break;
323 344 case 5:
324   - val = (val << 8) | (get_counter(&s->timers[0]) & 0xff);
325   - set_counter(s, &s->timers[0], val);
  345 + s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8);
  346 + s->ifr &= ~T1_INT;
  347 + set_counter(s, &s->timers[0], s->timers[0].latch);
326 348 break;
327 349 case 6:
328 350 s->timers[0].latch = (s->timers[0].latch & 0xff00) | val;
... ... @@ -330,15 +352,15 @@ static void cuda_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
330 352 break;
331 353 case 7:
332 354 s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8);
  355 + s->ifr &= ~T1_INT;
333 356 cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock));
334 357 break;
335 358 case 8:
336   - val = val | (get_counter(&s->timers[1]) & 0xff00);
  359 + s->timers[1].latch = val;
337 360 set_counter(s, &s->timers[1], val);
338 361 break;
339 362 case 9:
340   - val = (val << 8) | (get_counter(&s->timers[1]) & 0xff);
341   - set_counter(s, &s->timers[1], val);
  363 + set_counter(s, &s->timers[1], (val << 8) | s->timers[1].latch);
342 364 break;
343 365 case 10:
344 366 s->sr = val;
... ... @@ -620,10 +642,13 @@ int cuda_init(SetIRQFunc *set_irq, void *irq_opaque, int irq)
620 642 s->irq_opaque = irq_opaque;
621 643 s->irq = irq;
622 644  
  645 + s->timers[0].index = 0;
623 646 s->timers[0].timer = qemu_new_timer(vm_clock, cuda_timer1, s);
624   - s->timers[0].latch = 0x10000;
  647 + s->timers[0].latch = 0xffff;
625 648 set_counter(s, &s->timers[0], 0xffff);
626   - s->timers[1].latch = 0x10000;
  649 +
  650 + s->timers[1].index = 1;
  651 + s->timers[1].latch = 0;
627 652 // s->ier = T1_INT | SR_INT;
628 653 s->ier = 0;
629 654 set_counter(s, &s->timers[1], 0xffff);
... ...