Commit 819e712bfe40f0706689a98f9968f842e3aaccd1
1 parent
28b9b5af
cuda fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@950 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
138 additions
and
66 deletions
hw/adb.c
@@ -63,8 +63,8 @@ void adb_receive_packet(ADBBusState *s, const uint8_t *buf, int len) | @@ -63,8 +63,8 @@ void adb_receive_packet(ADBBusState *s, const uint8_t *buf, int len) | ||
63 | int devaddr, cmd, i; | 63 | int devaddr, cmd, i; |
64 | uint8_t obuf[4]; | 64 | uint8_t obuf[4]; |
65 | 65 | ||
66 | - cmd = buf[1] & 0xf; | ||
67 | - devaddr = buf[1] >> 4; | 66 | + cmd = buf[0] & 0xf; |
67 | + devaddr = buf[0] >> 4; | ||
68 | if (buf[1] == ADB_BUSRESET) { | 68 | if (buf[1] == ADB_BUSRESET) { |
69 | obuf[0] = 0x00; | 69 | obuf[0] = 0x00; |
70 | obuf[1] = 0x00; | 70 | obuf[1] = 0x00; |
hw/cuda.c
@@ -23,6 +23,9 @@ | @@ -23,6 +23,9 @@ | ||
23 | */ | 23 | */ |
24 | #include "vl.h" | 24 | #include "vl.h" |
25 | 25 | ||
26 | +//#define DEBUG_CUDA | ||
27 | +//#define DEBUG_CUDA_PACKET | ||
28 | + | ||
26 | /* Bits in B data register: all active low */ | 29 | /* Bits in B data register: all active low */ |
27 | #define TREQ 0x08 /* Transfer request (input) */ | 30 | #define TREQ 0x08 /* Transfer request (input) */ |
28 | #define TACK 0x10 /* Transfer acknowledge (output) */ | 31 | #define TACK 0x10 /* Transfer acknowledge (output) */ |
@@ -114,6 +117,7 @@ typedef struct CUDAState { | @@ -114,6 +117,7 @@ typedef struct CUDAState { | ||
114 | int data_out_index; | 117 | int data_out_index; |
115 | 118 | ||
116 | int irq; | 119 | int irq; |
120 | + openpic_t *openpic; | ||
117 | uint8_t autopoll; | 121 | uint8_t autopoll; |
118 | uint8_t data_in[128]; | 122 | uint8_t data_in[128]; |
119 | uint8_t data_out[16]; | 123 | uint8_t data_out[16]; |
@@ -125,13 +129,15 @@ ADBBusState adb_bus; | @@ -125,13 +129,15 @@ ADBBusState adb_bus; | ||
125 | static void cuda_update(CUDAState *s); | 129 | static void cuda_update(CUDAState *s); |
126 | static void cuda_receive_packet_from_host(CUDAState *s, | 130 | static void cuda_receive_packet_from_host(CUDAState *s, |
127 | const uint8_t *data, int len); | 131 | const uint8_t *data, int len); |
132 | +static void cuda_timer_update(CUDAState *s, CUDATimer *ti, | ||
133 | + int64_t current_time); | ||
128 | 134 | ||
129 | static void cuda_update_irq(CUDAState *s) | 135 | static void cuda_update_irq(CUDAState *s) |
130 | { | 136 | { |
131 | - if (s->ifr & s->ier & SR_INT) { | ||
132 | - pic_set_irq(s->irq, 1); | 137 | + if (s->ifr & s->ier & (SR_INT | T1_INT)) { |
138 | + openpic_set_irq(s->openpic, s->irq, 1); | ||
133 | } else { | 139 | } else { |
134 | - pic_set_irq(s->irq, 0); | 140 | + openpic_set_irq(s->openpic, s->irq, 0); |
135 | } | 141 | } |
136 | } | 142 | } |
137 | 143 | ||
@@ -150,10 +156,15 @@ static unsigned int get_counter(CUDATimer *s) | @@ -150,10 +156,15 @@ static unsigned int get_counter(CUDATimer *s) | ||
150 | return counter; | 156 | return counter; |
151 | } | 157 | } |
152 | 158 | ||
153 | -static void set_counter(CUDATimer *s, unsigned int val) | 159 | +static void set_counter(CUDAState *s, CUDATimer *ti, unsigned int val) |
154 | { | 160 | { |
155 | - s->load_time = qemu_get_clock(vm_clock); | ||
156 | - s->counter_value = val; | 161 | +#ifdef DEBUG_CUDA |
162 | + printf("cuda: T%d.counter=%d\n", | ||
163 | + 1 + (ti->timer == NULL), val); | ||
164 | +#endif | ||
165 | + ti->load_time = qemu_get_clock(vm_clock); | ||
166 | + ti->counter_value = val; | ||
167 | + cuda_timer_update(s, ti, ti->load_time); | ||
157 | } | 168 | } |
158 | 169 | ||
159 | static int64_t get_next_irq_time(CUDATimer *s, int64_t current_time) | 170 | static int64_t get_next_irq_time(CUDATimer *s, int64_t current_time) |
@@ -165,10 +176,14 @@ static int64_t get_next_irq_time(CUDATimer *s, int64_t current_time) | @@ -165,10 +176,14 @@ static int64_t get_next_irq_time(CUDATimer *s, int64_t current_time) | ||
165 | if (d <= s->counter_value) { | 176 | if (d <= s->counter_value) { |
166 | next_time = s->counter_value + 1; | 177 | next_time = s->counter_value + 1; |
167 | } else { | 178 | } else { |
168 | - base = ((d - s->counter_value) % s->latch); | 179 | + base = ((d - s->counter_value) / s->latch); |
169 | base = (base * s->latch) + s->counter_value; | 180 | base = (base * s->latch) + s->counter_value; |
170 | next_time = base + s->latch; | 181 | next_time = base + s->latch; |
171 | } | 182 | } |
183 | +#ifdef DEBUG_CUDA | ||
184 | + printf("latch=%d counter=%lld delta_next=%lld\n", | ||
185 | + s->latch, d, next_time - d); | ||
186 | +#endif | ||
172 | next_time = muldiv64(next_time, ticks_per_sec, CUDA_TIMER_FREQ) + | 187 | next_time = muldiv64(next_time, ticks_per_sec, CUDA_TIMER_FREQ) + |
173 | s->load_time; | 188 | s->load_time; |
174 | if (next_time <= current_time) | 189 | if (next_time <= current_time) |
@@ -176,13 +191,25 @@ static int64_t get_next_irq_time(CUDATimer *s, int64_t current_time) | @@ -176,13 +191,25 @@ static int64_t get_next_irq_time(CUDATimer *s, int64_t current_time) | ||
176 | return next_time; | 191 | return next_time; |
177 | } | 192 | } |
178 | 193 | ||
194 | +static void cuda_timer_update(CUDAState *s, CUDATimer *ti, | ||
195 | + int64_t current_time) | ||
196 | +{ | ||
197 | + if (!ti->timer) | ||
198 | + return; | ||
199 | + if ((s->acr & T1MODE) != T1MODE_CONT) { | ||
200 | + qemu_del_timer(ti->timer); | ||
201 | + } else { | ||
202 | + ti->next_irq_time = get_next_irq_time(ti, current_time); | ||
203 | + qemu_mod_timer(ti->timer, ti->next_irq_time); | ||
204 | + } | ||
205 | +} | ||
206 | + | ||
179 | static void cuda_timer1(void *opaque) | 207 | static void cuda_timer1(void *opaque) |
180 | { | 208 | { |
181 | CUDAState *s = opaque; | 209 | CUDAState *s = opaque; |
182 | CUDATimer *ti = &s->timers[0]; | 210 | CUDATimer *ti = &s->timers[0]; |
183 | 211 | ||
184 | - ti->next_irq_time = get_next_irq_time(ti, ti->next_irq_time); | ||
185 | - qemu_mod_timer(ti->timer, ti->next_irq_time); | 212 | + cuda_timer_update(s, ti, ti->next_irq_time); |
186 | s->ifr |= T1_INT; | 213 | s->ifr |= T1_INT; |
187 | cuda_update_irq(s); | 214 | cuda_update_irq(s); |
188 | } | 215 | } |
@@ -229,11 +256,9 @@ static uint32_t cuda_readb(void *opaque, target_phys_addr_t addr) | @@ -229,11 +256,9 @@ static uint32_t cuda_readb(void *opaque, target_phys_addr_t addr) | ||
229 | val = get_counter(&s->timers[1]) >> 8; | 256 | val = get_counter(&s->timers[1]) >> 8; |
230 | break; | 257 | break; |
231 | case 10: | 258 | case 10: |
232 | - if (s->data_in_index < s->data_in_size) { | ||
233 | - val = s->data_in[s->data_in_index]; | ||
234 | - } else { | ||
235 | - val = 0; | ||
236 | - } | 259 | + val = s->sr; |
260 | + s->ifr &= ~SR_INT; | ||
261 | + cuda_update_irq(s); | ||
237 | break; | 262 | break; |
238 | case 11: | 263 | case 11: |
239 | val = s->acr; | 264 | val = s->acr; |
@@ -253,7 +278,8 @@ static uint32_t cuda_readb(void *opaque, target_phys_addr_t addr) | @@ -253,7 +278,8 @@ static uint32_t cuda_readb(void *opaque, target_phys_addr_t addr) | ||
253 | break; | 278 | break; |
254 | } | 279 | } |
255 | #ifdef DEBUG_CUDA | 280 | #ifdef DEBUG_CUDA |
256 | - printf("cuda: read: reg=0x%x val=%02x\n", addr, val); | 281 | + if (addr != 13 || val != 0) |
282 | + printf("cuda: read: reg=0x%x val=%02x\n", addr, val); | ||
257 | #endif | 283 | #endif |
258 | return val; | 284 | return val; |
259 | } | 285 | } |
@@ -283,44 +309,34 @@ static void cuda_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) | @@ -283,44 +309,34 @@ static void cuda_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) | ||
283 | break; | 309 | break; |
284 | case 4: | 310 | case 4: |
285 | val = val | (get_counter(&s->timers[0]) & 0xff00); | 311 | val = val | (get_counter(&s->timers[0]) & 0xff00); |
286 | - set_counter(&s->timers[0], val); | 312 | + set_counter(s, &s->timers[0], val); |
287 | break; | 313 | break; |
288 | case 5: | 314 | case 5: |
289 | val = (val << 8) | (get_counter(&s->timers[0]) & 0xff); | 315 | val = (val << 8) | (get_counter(&s->timers[0]) & 0xff); |
290 | - set_counter(&s->timers[0], val); | 316 | + set_counter(s, &s->timers[0], val); |
291 | break; | 317 | break; |
292 | case 6: | 318 | case 6: |
293 | s->timers[0].latch = (s->timers[0].latch & 0xff00) | val; | 319 | s->timers[0].latch = (s->timers[0].latch & 0xff00) | val; |
320 | + cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock)); | ||
294 | break; | 321 | break; |
295 | case 7: | 322 | case 7: |
296 | s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8); | 323 | s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8); |
324 | + cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock)); | ||
297 | break; | 325 | break; |
298 | case 8: | 326 | case 8: |
299 | val = val | (get_counter(&s->timers[1]) & 0xff00); | 327 | val = val | (get_counter(&s->timers[1]) & 0xff00); |
300 | - set_counter(&s->timers[1], val); | 328 | + set_counter(s, &s->timers[1], val); |
301 | break; | 329 | break; |
302 | case 9: | 330 | case 9: |
303 | val = (val << 8) | (get_counter(&s->timers[1]) & 0xff); | 331 | val = (val << 8) | (get_counter(&s->timers[1]) & 0xff); |
304 | - set_counter(&s->timers[1], val); | 332 | + set_counter(s, &s->timers[1], val); |
305 | break; | 333 | break; |
306 | case 10: | 334 | case 10: |
307 | s->sr = val; | 335 | s->sr = val; |
308 | break; | 336 | break; |
309 | case 11: | 337 | case 11: |
310 | s->acr = val; | 338 | s->acr = val; |
311 | - if ((s->acr & T1MODE) == T1MODE_CONT) { | ||
312 | - if ((s->last_acr & T1MODE) != T1MODE_CONT) { | ||
313 | - CUDATimer *ti = &s->timers[0]; | ||
314 | - /* activate timer interrupt */ | ||
315 | - ti->next_irq_time = get_next_irq_time(ti, qemu_get_clock(vm_clock)); | ||
316 | - qemu_mod_timer(ti->timer, ti->next_irq_time); | ||
317 | - } | ||
318 | - } else { | ||
319 | - if ((s->last_acr & T1MODE) == T1MODE_CONT) { | ||
320 | - CUDATimer *ti = &s->timers[0]; | ||
321 | - qemu_del_timer(ti->timer); | ||
322 | - } | ||
323 | - } | 339 | + cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock)); |
324 | cuda_update(s); | 340 | cuda_update(s); |
325 | break; | 341 | break; |
326 | case 12: | 342 | case 12: |
@@ -351,47 +367,90 @@ static void cuda_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) | @@ -351,47 +367,90 @@ static void cuda_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) | ||
351 | /* NOTE: TIP and TREQ are negated */ | 367 | /* NOTE: TIP and TREQ are negated */ |
352 | static void cuda_update(CUDAState *s) | 368 | static void cuda_update(CUDAState *s) |
353 | { | 369 | { |
354 | - if (s->data_in_index < s->data_in_size) { | ||
355 | - /* data input */ | ||
356 | - if (!(s->b & TIP) && | ||
357 | - (s->b & (TACK | TIP)) != (s->last_b & (TACK | TIP))) { | ||
358 | - s->sr = s->data_in[s->data_in_index++]; | ||
359 | - s->ifr |= SR_INT; | ||
360 | - cuda_update_irq(s); | ||
361 | - } | ||
362 | - } | ||
363 | - if (s->data_in_index < s->data_in_size) { | ||
364 | - /* there is some data to read */ | ||
365 | - s->b = (s->b & ~TREQ); | ||
366 | - } else { | ||
367 | - s->b = (s->b | TREQ); | ||
368 | - } | 370 | + int packet_received, len; |
371 | + | ||
372 | + packet_received = 0; | ||
373 | + if (!(s->b & TIP)) { | ||
374 | + /* transfer requested from host */ | ||
369 | 375 | ||
370 | - if (s->acr & SR_OUT) { | ||
371 | - /* data output */ | ||
372 | - if (!(s->b & TIP) && | ||
373 | - (s->b & (TACK | TIP)) != (s->last_b & (TACK | TIP))) { | ||
374 | - if (s->data_out_index < sizeof(s->data_out)) { | ||
375 | - s->data_out[s->data_out_index++] = s->sr; | 376 | + if (s->acr & SR_OUT) { |
377 | + /* data output */ | ||
378 | + if ((s->b & (TACK | TIP)) != (s->last_b & (TACK | TIP))) { | ||
379 | + if (s->data_out_index < sizeof(s->data_out)) { | ||
380 | +#ifdef DEBUG_CUDA | ||
381 | + printf("cuda: send: %02x\n", s->sr); | ||
382 | +#endif | ||
383 | + s->data_out[s->data_out_index++] = s->sr; | ||
384 | + s->ifr |= SR_INT; | ||
385 | + cuda_update_irq(s); | ||
386 | + } | ||
387 | + } | ||
388 | + } else { | ||
389 | + if (s->data_in_index < s->data_in_size) { | ||
390 | + /* data input */ | ||
391 | + if ((s->b & (TACK | TIP)) != (s->last_b & (TACK | TIP))) { | ||
392 | + s->sr = s->data_in[s->data_in_index++]; | ||
393 | +#ifdef DEBUG_CUDA | ||
394 | + printf("cuda: recv: %02x\n", s->sr); | ||
395 | +#endif | ||
396 | + /* indicate end of transfer */ | ||
397 | + if (s->data_in_index >= s->data_in_size) { | ||
398 | + s->b = (s->b | TREQ); | ||
399 | + } | ||
400 | + s->ifr |= SR_INT; | ||
401 | + cuda_update_irq(s); | ||
402 | + } | ||
376 | } | 403 | } |
404 | + } | ||
405 | + } else { | ||
406 | + /* no transfer requested: handle sync case */ | ||
407 | + if ((s->last_b & TIP) && (s->b & TACK) != (s->last_b & TACK)) { | ||
408 | + /* update TREQ state each time TACK change state */ | ||
409 | + if (s->b & TACK) | ||
410 | + s->b = (s->b | TREQ); | ||
411 | + else | ||
412 | + s->b = (s->b & ~TREQ); | ||
377 | s->ifr |= SR_INT; | 413 | s->ifr |= SR_INT; |
378 | cuda_update_irq(s); | 414 | cuda_update_irq(s); |
415 | + } else { | ||
416 | + if (!(s->last_b & TIP)) { | ||
417 | + /* handle end of host to cuda transfert */ | ||
418 | + packet_received = (s->data_out_index > 0); | ||
419 | + /* always an IRQ at the end of transfert */ | ||
420 | + s->ifr |= SR_INT; | ||
421 | + cuda_update_irq(s); | ||
422 | + } | ||
423 | + /* signal if there is data to read */ | ||
424 | + if (s->data_in_index < s->data_in_size) { | ||
425 | + s->b = (s->b & ~TREQ); | ||
426 | + } | ||
379 | } | 427 | } |
380 | } | 428 | } |
381 | 429 | ||
382 | - /* check end of data output */ | ||
383 | - if (!(s->acr & SR_OUT) && (s->last_acr & SR_OUT)) { | ||
384 | - if (s->data_out_index > 0) | ||
385 | - cuda_receive_packet_from_host(s, s->data_out, s->data_out_index); | ||
386 | - s->data_out_index = 0; | ||
387 | - } | ||
388 | s->last_acr = s->acr; | 430 | s->last_acr = s->acr; |
389 | s->last_b = s->b; | 431 | s->last_b = s->b; |
432 | + | ||
433 | + /* NOTE: cuda_receive_packet_from_host() can call cuda_update() | ||
434 | + recursively */ | ||
435 | + if (packet_received) { | ||
436 | + len = s->data_out_index; | ||
437 | + s->data_out_index = 0; | ||
438 | + cuda_receive_packet_from_host(s, s->data_out, len); | ||
439 | + } | ||
390 | } | 440 | } |
391 | 441 | ||
392 | static void cuda_send_packet_to_host(CUDAState *s, | 442 | static void cuda_send_packet_to_host(CUDAState *s, |
393 | const uint8_t *data, int len) | 443 | const uint8_t *data, int len) |
394 | { | 444 | { |
445 | +#ifdef DEBUG_CUDA_PACKET | ||
446 | + { | ||
447 | + int i; | ||
448 | + printf("cuda_send_packet_to_host:\n"); | ||
449 | + for(i = 0; i < len; i++) | ||
450 | + printf(" %02x", data[i]); | ||
451 | + printf("\n"); | ||
452 | + } | ||
453 | +#endif | ||
395 | memcpy(s->data_in, data, len); | 454 | memcpy(s->data_in, data, len); |
396 | s->data_in_size = len; | 455 | s->data_in_size = len; |
397 | s->data_in_index = 0; | 456 | s->data_in_index = 0; |
@@ -425,7 +484,7 @@ static void cuda_receive_packet(CUDAState *s, | @@ -425,7 +484,7 @@ static void cuda_receive_packet(CUDAState *s, | ||
425 | break; | 484 | break; |
426 | case CUDA_GET_TIME: | 485 | case CUDA_GET_TIME: |
427 | /* XXX: add time support ? */ | 486 | /* XXX: add time support ? */ |
428 | - ti = 0; | 487 | + ti = time(NULL); |
429 | obuf[0] = CUDA_PACKET; | 488 | obuf[0] = CUDA_PACKET; |
430 | obuf[1] = 0; | 489 | obuf[1] = 0; |
431 | obuf[2] = 0; | 490 | obuf[2] = 0; |
@@ -452,6 +511,15 @@ static void cuda_receive_packet(CUDAState *s, | @@ -452,6 +511,15 @@ static void cuda_receive_packet(CUDAState *s, | ||
452 | static void cuda_receive_packet_from_host(CUDAState *s, | 511 | static void cuda_receive_packet_from_host(CUDAState *s, |
453 | const uint8_t *data, int len) | 512 | const uint8_t *data, int len) |
454 | { | 513 | { |
514 | +#ifdef DEBUG_CUDA_PACKET | ||
515 | + { | ||
516 | + int i; | ||
517 | + printf("cuda_receive_packet_to_host:\n"); | ||
518 | + for(i = 0; i < len; i++) | ||
519 | + printf(" %02x", data[i]); | ||
520 | + printf("\n"); | ||
521 | + } | ||
522 | +#endif | ||
455 | switch(data[0]) { | 523 | switch(data[0]) { |
456 | case ADB_PACKET: | 524 | case ADB_PACKET: |
457 | adb_receive_packet(&adb_bus, data + 1, len - 1); | 525 | adb_receive_packet(&adb_bus, data + 1, len - 1); |
@@ -492,16 +560,20 @@ static CPUReadMemoryFunc *cuda_read[] = { | @@ -492,16 +560,20 @@ static CPUReadMemoryFunc *cuda_read[] = { | ||
492 | &cuda_readl, | 560 | &cuda_readl, |
493 | }; | 561 | }; |
494 | 562 | ||
495 | -int cuda_init(void) | 563 | +int cuda_init(openpic_t *openpic, int irq) |
496 | { | 564 | { |
497 | CUDAState *s = &cuda_state; | 565 | CUDAState *s = &cuda_state; |
498 | int cuda_mem_index; | 566 | int cuda_mem_index; |
499 | 567 | ||
500 | - s->timers[0].latch = 0x10000; | ||
501 | - set_counter(&s->timers[0], 0xffff); | 568 | + s->openpic = openpic; |
569 | + s->irq = irq; | ||
570 | + | ||
502 | s->timers[0].timer = qemu_new_timer(vm_clock, cuda_timer1, s); | 571 | s->timers[0].timer = qemu_new_timer(vm_clock, cuda_timer1, s); |
572 | + s->timers[0].latch = 0x10000; | ||
573 | + set_counter(s, &s->timers[0], 0xffff); | ||
503 | s->timers[1].latch = 0x10000; | 574 | s->timers[1].latch = 0x10000; |
504 | - set_counter(&s->timers[1], 0xffff); | 575 | + s->ier = T1_INT | SR_INT; |
576 | + set_counter(s, &s->timers[1], 0xffff); | ||
505 | cuda_mem_index = cpu_register_io_memory(0, cuda_read, cuda_write, s); | 577 | cuda_mem_index = cpu_register_io_memory(0, cuda_read, cuda_write, s); |
506 | return cuda_mem_index; | 578 | return cuda_mem_index; |
507 | } | 579 | } |