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 63 int devaddr, cmd, i;
64 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 68 if (buf[1] == ADB_BUSRESET) {
69 69 obuf[0] = 0x00;
70 70 obuf[1] = 0x00;
... ...
hw/cuda.c
... ... @@ -23,6 +23,9 @@
23 23 */
24 24 #include "vl.h"
25 25  
  26 +//#define DEBUG_CUDA
  27 +//#define DEBUG_CUDA_PACKET
  28 +
26 29 /* Bits in B data register: all active low */
27 30 #define TREQ 0x08 /* Transfer request (input) */
28 31 #define TACK 0x10 /* Transfer acknowledge (output) */
... ... @@ -114,6 +117,7 @@ typedef struct CUDAState {
114 117 int data_out_index;
115 118  
116 119 int irq;
  120 + openpic_t *openpic;
117 121 uint8_t autopoll;
118 122 uint8_t data_in[128];
119 123 uint8_t data_out[16];
... ... @@ -125,13 +129,15 @@ ADBBusState adb_bus;
125 129 static void cuda_update(CUDAState *s);
126 130 static void cuda_receive_packet_from_host(CUDAState *s,
127 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 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 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 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 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 176 if (d <= s->counter_value) {
166 177 next_time = s->counter_value + 1;
167 178 } else {
168   - base = ((d - s->counter_value) % s->latch);
  179 + base = ((d - s->counter_value) / s->latch);
169 180 base = (base * s->latch) + s->counter_value;
170 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 187 next_time = muldiv64(next_time, ticks_per_sec, CUDA_TIMER_FREQ) +
173 188 s->load_time;
174 189 if (next_time <= current_time)
... ... @@ -176,13 +191,25 @@ static int64_t get_next_irq_time(CUDATimer *s, int64_t current_time)
176 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 207 static void cuda_timer1(void *opaque)
180 208 {
181 209 CUDAState *s = opaque;
182 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 213 s->ifr |= T1_INT;
187 214 cuda_update_irq(s);
188 215 }
... ... @@ -229,11 +256,9 @@ static uint32_t cuda_readb(void *opaque, target_phys_addr_t addr)
229 256 val = get_counter(&s->timers[1]) >> 8;
230 257 break;
231 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 262 break;
238 263 case 11:
239 264 val = s->acr;
... ... @@ -253,7 +278,8 @@ static uint32_t cuda_readb(void *opaque, target_phys_addr_t addr)
253 278 break;
254 279 }
255 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 283 #endif
258 284 return val;
259 285 }
... ... @@ -283,44 +309,34 @@ static void cuda_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
283 309 break;
284 310 case 4:
285 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 313 break;
288 314 case 5:
289 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 317 break;
292 318 case 6:
293 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 321 break;
295 322 case 7:
296 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 325 break;
298 326 case 8:
299 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 329 break;
302 330 case 9:
303 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 333 break;
306 334 case 10:
307 335 s->sr = val;
308 336 break;
309 337 case 11:
310 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 340 cuda_update(s);
325 341 break;
326 342 case 12:
... ... @@ -351,47 +367,90 @@ static void cuda_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
351 367 /* NOTE: TIP and TREQ are negated */
352 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 413 s->ifr |= SR_INT;
378 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 430 s->last_acr = s->acr;
389 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 442 static void cuda_send_packet_to_host(CUDAState *s,
393 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 454 memcpy(s->data_in, data, len);
396 455 s->data_in_size = len;
397 456 s->data_in_index = 0;
... ... @@ -425,7 +484,7 @@ static void cuda_receive_packet(CUDAState *s,
425 484 break;
426 485 case CUDA_GET_TIME:
427 486 /* XXX: add time support ? */
428   - ti = 0;
  487 + ti = time(NULL);
429 488 obuf[0] = CUDA_PACKET;
430 489 obuf[1] = 0;
431 490 obuf[2] = 0;
... ... @@ -452,6 +511,15 @@ static void cuda_receive_packet(CUDAState *s,
452 511 static void cuda_receive_packet_from_host(CUDAState *s,
453 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 523 switch(data[0]) {
456 524 case ADB_PACKET:
457 525 adb_receive_packet(&adb_bus, data + 1, len - 1);
... ... @@ -492,16 +560,20 @@ static CPUReadMemoryFunc *cuda_read[] = {
492 560 &cuda_readl,
493 561 };
494 562  
495   -int cuda_init(void)
  563 +int cuda_init(openpic_t *openpic, int irq)
496 564 {
497 565 CUDAState *s = &cuda_state;
498 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 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 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 577 cuda_mem_index = cpu_register_io_memory(0, cuda_read, cuda_write, s);
506 578 return cuda_mem_index;
507 579 }
... ...