Revision 61271e5c

b/hw/cuda.c
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 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 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 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 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 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 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 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 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);

Also available in: Unified diff