Commit 819e712bfe40f0706689a98f9968f842e3aaccd1

Authored by bellard
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 }