23 |
*/ |
*/ |
24 |
#include "vl.h" |
#include "vl.h" |
25 |
|
|
26 |
|
/* XXX: implement all timer modes */ |
27 |
|
|
28 |
//#define DEBUG_CUDA |
//#define DEBUG_CUDA |
29 |
//#define DEBUG_CUDA_PACKET |
//#define DEBUG_CUDA_PACKET |
30 |
|
|
43 |
#define IER_CLR 0 /* clear bits in IER */ |
#define IER_CLR 0 /* clear bits in IER */ |
44 |
#define SR_INT 0x04 /* Shift register full/empty */ |
#define SR_INT 0x04 /* Shift register full/empty */ |
45 |
#define T1_INT 0x40 /* Timer 1 interrupt */ |
#define T1_INT 0x40 /* Timer 1 interrupt */ |
46 |
|
#define T2_INT 0x20 /* Timer 2 interrupt */ |
47 |
|
|
48 |
/* Bits in ACR */ |
/* Bits in ACR */ |
49 |
#define T1MODE 0xc0 /* Timer 1 mode */ |
#define T1MODE 0xc0 /* Timer 1 mode */ |
94 |
#define RTC_OFFSET 2082844800 |
#define RTC_OFFSET 2082844800 |
95 |
|
|
96 |
typedef struct CUDATimer { |
typedef struct CUDATimer { |
97 |
unsigned int latch; |
int index; |
98 |
|
uint16_t latch; |
99 |
uint16_t counter_value; /* counter value at load time */ |
uint16_t counter_value; /* counter value at load time */ |
100 |
int64_t load_time; |
int64_t load_time; |
101 |
int64_t next_irq_time; |
int64_t next_irq_time; |
158 |
|
|
159 |
d = muldiv64(qemu_get_clock(vm_clock) - s->load_time, |
d = muldiv64(qemu_get_clock(vm_clock) - s->load_time, |
160 |
CUDA_TIMER_FREQ, ticks_per_sec); |
CUDA_TIMER_FREQ, ticks_per_sec); |
161 |
if (d <= s->counter_value) { |
if (s->index == 0) { |
162 |
counter = d; |
/* 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 |
|
} |
169 |
} else { |
} else { |
170 |
counter = s->latch - 1 - ((d - s->counter_value) % s->latch); |
counter = (s->counter_value - d) & 0xffff; |
171 |
} |
} |
172 |
return counter; |
return counter; |
173 |
} |
} |
185 |
|
|
186 |
static int64_t get_next_irq_time(CUDATimer *s, int64_t current_time) |
static int64_t get_next_irq_time(CUDATimer *s, int64_t current_time) |
187 |
{ |
{ |
188 |
int64_t d, next_time, base; |
int64_t d, next_time; |
189 |
|
unsigned int counter; |
190 |
|
|
191 |
/* current counter value */ |
/* current counter value */ |
192 |
d = muldiv64(current_time - s->load_time, |
d = muldiv64(current_time - s->load_time, |
193 |
CUDA_TIMER_FREQ, ticks_per_sec); |
CUDA_TIMER_FREQ, ticks_per_sec); |
194 |
if (d < s->counter_value) { |
/* the timer goes down from latch to -1 (period of latch + 2) */ |
195 |
next_time = s->counter_value + 1; |
if (d <= (s->counter_value + 1)) { |
196 |
} else |
counter = (s->counter_value - d) & 0xffff; |
197 |
{ |
} else { |
198 |
base = ((d - s->counter_value + 1) / s->latch); |
counter = (d - (s->counter_value + 1)) % (s->latch + 2); |
199 |
base = (base * s->latch) + s->counter_value; |
counter = (s->latch - counter) & 0xffff; |
200 |
next_time = base + s->latch; |
} |
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; |
209 |
} |
} |
210 |
#if 0 |
#if 0 |
211 |
#ifdef DEBUG_CUDA |
#ifdef DEBUG_CUDA |
269 |
break; |
break; |
270 |
case 5: |
case 5: |
271 |
val = get_counter(&s->timers[0]) >> 8; |
val = get_counter(&s->timers[0]) >> 8; |
|
s->ifr &= ~T1_INT; |
|
272 |
cuda_update_irq(s); |
cuda_update_irq(s); |
273 |
break; |
break; |
274 |
case 6: |
case 6: |
275 |
val = s->timers[0].latch & 0xff; |
val = s->timers[0].latch & 0xff; |
276 |
break; |
break; |
277 |
case 7: |
case 7: |
278 |
|
/* XXX: check this */ |
279 |
val = (s->timers[0].latch >> 8) & 0xff; |
val = (s->timers[0].latch >> 8) & 0xff; |
280 |
break; |
break; |
281 |
case 8: |
case 8: |
282 |
val = get_counter(&s->timers[1]) & 0xff; |
val = get_counter(&s->timers[1]) & 0xff; |
283 |
|
s->ifr &= ~T2_INT; |
284 |
break; |
break; |
285 |
case 9: |
case 9: |
286 |
val = get_counter(&s->timers[1]) >> 8; |
val = get_counter(&s->timers[1]) >> 8; |
338 |
s->dira = val; |
s->dira = val; |
339 |
break; |
break; |
340 |
case 4: |
case 4: |
341 |
val = val | (get_counter(&s->timers[0]) & 0xff00); |
s->timers[0].latch = (s->timers[0].latch & 0xff00) | val; |
342 |
set_counter(s, &s->timers[0], val); |
cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock)); |
343 |
break; |
break; |
344 |
case 5: |
case 5: |
345 |
val = (val << 8) | (get_counter(&s->timers[0]) & 0xff); |
s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8); |
346 |
set_counter(s, &s->timers[0], val); |
s->ifr &= ~T1_INT; |
347 |
|
set_counter(s, &s->timers[0], s->timers[0].latch); |
348 |
break; |
break; |
349 |
case 6: |
case 6: |
350 |
s->timers[0].latch = (s->timers[0].latch & 0xff00) | val; |
s->timers[0].latch = (s->timers[0].latch & 0xff00) | val; |
352 |
break; |
break; |
353 |
case 7: |
case 7: |
354 |
s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8); |
s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8); |
355 |
|
s->ifr &= ~T1_INT; |
356 |
cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock)); |
cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock)); |
357 |
break; |
break; |
358 |
case 8: |
case 8: |
359 |
val = val | (get_counter(&s->timers[1]) & 0xff00); |
s->timers[1].latch = val; |
360 |
set_counter(s, &s->timers[1], val); |
set_counter(s, &s->timers[1], val); |
361 |
break; |
break; |
362 |
case 9: |
case 9: |
363 |
val = (val << 8) | (get_counter(&s->timers[1]) & 0xff); |
set_counter(s, &s->timers[1], (val << 8) | s->timers[1].latch); |
|
set_counter(s, &s->timers[1], val); |
|
364 |
break; |
break; |
365 |
case 10: |
case 10: |
366 |
s->sr = val; |
s->sr = val; |
642 |
s->irq_opaque = irq_opaque; |
s->irq_opaque = irq_opaque; |
643 |
s->irq = irq; |
s->irq = irq; |
644 |
|
|
645 |
|
s->timers[0].index = 0; |
646 |
s->timers[0].timer = qemu_new_timer(vm_clock, cuda_timer1, s); |
s->timers[0].timer = qemu_new_timer(vm_clock, cuda_timer1, s); |
647 |
s->timers[0].latch = 0x10000; |
s->timers[0].latch = 0xffff; |
648 |
set_counter(s, &s->timers[0], 0xffff); |
set_counter(s, &s->timers[0], 0xffff); |
649 |
s->timers[1].latch = 0x10000; |
|
650 |
|
s->timers[1].index = 1; |
651 |
|
s->timers[1].latch = 0; |
652 |
// s->ier = T1_INT | SR_INT; |
// s->ier = T1_INT | SR_INT; |
653 |
s->ier = 0; |
s->ier = 0; |
654 |
set_counter(s, &s->timers[1], 0xffff); |
set_counter(s, &s->timers[1], 0xffff); |