Commit a8303d18e044b9c808c27a9c48888c6e639a321d

Authored by edgar_igl
1 parent 77b73de6

ETRAX: More DMA context level related fixes.

* When hitting EOL (end of list) at the data descriptor level, the DMA should mark the current context-descriptor as disabled and perform a context-store so software can see whats goin on.
* Context loads update RW_SAVED_DATA_BUF, data loads dont. This fixes an issue with ethernet bootstrapping.
* Reorder the logic for processing out channels to be more like the one for input channels.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4723 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 70 additions and 40 deletions
hw/etraxfs_dma.c
@@ -267,23 +267,33 @@ static void channel_load_d(struct fs_dma_ctrl *ctrl, int c) @@ -267,23 +267,33 @@ static void channel_load_d(struct fs_dma_ctrl *ctrl, int c)
267 target_phys_addr_t addr = channel_reg(ctrl, c, RW_SAVED_DATA); 267 target_phys_addr_t addr = channel_reg(ctrl, c, RW_SAVED_DATA);
268 268
269 /* Load and decode. FIXME: handle endianness. */ 269 /* Load and decode. FIXME: handle endianness. */
270 - D(printf("%s addr=%x\n", __func__, addr)); 270 + D(printf("%s ch=%d addr=%x\n", __func__, c, addr));
271 cpu_physical_memory_read (addr, 271 cpu_physical_memory_read (addr,
272 (void *) &ctrl->channels[c].current_d, 272 (void *) &ctrl->channels[c].current_d,
273 sizeof ctrl->channels[c].current_d); 273 sizeof ctrl->channels[c].current_d);
274 274
275 D(dump_d(c, &ctrl->channels[c].current_d)); 275 D(dump_d(c, &ctrl->channels[c].current_d));
276 ctrl->channels[c].regs[RW_DATA] = addr; 276 ctrl->channels[c].regs[RW_DATA] = addr;
277 - ctrl->channels[c].regs[RW_SAVED_DATA_BUF] =  
278 - (uint32_t)ctrl->channels[c].current_d.buf; 277 +}
  278 +
  279 +static void channel_store_c(struct fs_dma_ctrl *ctrl, int c)
  280 +{
  281 + target_phys_addr_t addr = channel_reg(ctrl, c, RW_GROUP_DOWN);
  282 +
  283 + /* Encode and store. FIXME: handle endianness. */
  284 + D(printf("%s ch=%d addr=%x\n", __func__, c, addr));
  285 + D(dump_d(c, &ctrl->channels[c].current_d));
  286 + cpu_physical_memory_write (addr,
  287 + (void *) &ctrl->channels[c].current_c,
  288 + sizeof ctrl->channels[c].current_c);
279 } 289 }
280 290
281 static void channel_store_d(struct fs_dma_ctrl *ctrl, int c) 291 static void channel_store_d(struct fs_dma_ctrl *ctrl, int c)
282 { 292 {
283 target_phys_addr_t addr = channel_reg(ctrl, c, RW_SAVED_DATA); 293 target_phys_addr_t addr = channel_reg(ctrl, c, RW_SAVED_DATA);
284 294
285 - /* Load and decode. FIXME: handle endianness. */  
286 - D(printf("%s addr=%x\n", __func__, addr)); 295 + /* Encode and store. FIXME: handle endianness. */
  296 + D(printf("%s ch=%d addr=%x\n", __func__, c, addr));
287 cpu_physical_memory_write (addr, 297 cpu_physical_memory_write (addr,
288 (void *) &ctrl->channels[c].current_d, 298 (void *) &ctrl->channels[c].current_d,
289 sizeof ctrl->channels[c].current_d); 299 sizeof ctrl->channels[c].current_d);
@@ -326,20 +336,23 @@ static void channel_continue(struct fs_dma_ctrl *ctrl, int c) @@ -326,20 +336,23 @@ static void channel_continue(struct fs_dma_ctrl *ctrl, int c)
326 /* If the current descriptor cleared the eol flag and we had already 336 /* If the current descriptor cleared the eol flag and we had already
327 reached eol state, do the continue. */ 337 reached eol state, do the continue. */
328 if (!ctrl->channels[c].current_d.eol && ctrl->channels[c].eol) { 338 if (!ctrl->channels[c].current_d.eol && ctrl->channels[c].eol) {
329 - D(printf("continue %d ok %x\n", c, 339 + D(printf("continue %d ok %p\n", c,
330 ctrl->channels[c].current_d.next)); 340 ctrl->channels[c].current_d.next));
331 ctrl->channels[c].regs[RW_SAVED_DATA] = 341 ctrl->channels[c].regs[RW_SAVED_DATA] =
332 (uint32_t) ctrl->channels[c].current_d.next; 342 (uint32_t) ctrl->channels[c].current_d.next;
333 channel_load_d(ctrl, c); 343 channel_load_d(ctrl, c);
334 channel_start(ctrl, c); 344 channel_start(ctrl, c);
335 } 345 }
  346 + ctrl->channels[c].regs[RW_SAVED_DATA_BUF] =
  347 + (uint32_t) ctrl->channels[c].current_d.buf;
336 } 348 }
337 349
338 static void channel_stream_cmd(struct fs_dma_ctrl *ctrl, int c, uint32_t v) 350 static void channel_stream_cmd(struct fs_dma_ctrl *ctrl, int c, uint32_t v)
339 { 351 {
340 unsigned int cmd = v & ((1 << 10) - 1); 352 unsigned int cmd = v & ((1 << 10) - 1);
341 353
342 - D(printf("%s cmd=%x\n", __func__, cmd)); 354 + D(printf("%s ch=%d cmd=%x pc=%x\n",
  355 + __func__, c, cmd, ctrl->env->pc));
343 if (cmd & regk_dma_load_d) { 356 if (cmd & regk_dma_load_d) {
344 channel_load_d(ctrl, c); 357 channel_load_d(ctrl, c);
345 if (cmd & regk_dma_burst) 358 if (cmd & regk_dma_burst)
@@ -348,6 +361,7 @@ static void channel_stream_cmd(struct fs_dma_ctrl *ctrl, int c, uint32_t v) @@ -348,6 +361,7 @@ static void channel_stream_cmd(struct fs_dma_ctrl *ctrl, int c, uint32_t v)
348 361
349 if (cmd & regk_dma_load_c) { 362 if (cmd & regk_dma_load_c) {
350 channel_load_c(ctrl, c); 363 channel_load_c(ctrl, c);
  364 + channel_start(ctrl, c);
351 } 365 }
352 } 366 }
353 367
@@ -382,11 +396,30 @@ static void channel_out_run(struct fs_dma_ctrl *ctrl, int c) @@ -382,11 +396,30 @@ static void channel_out_run(struct fs_dma_ctrl *ctrl, int c)
382 396
383 saved_data_buf = channel_reg(ctrl, c, RW_SAVED_DATA_BUF); 397 saved_data_buf = channel_reg(ctrl, c, RW_SAVED_DATA_BUF);
384 398
385 - D(printf("buf=%x after=%x saved_data_buf=%x\n", 399 + D(fprintf(logfile, "ch=%d buf=%x after=%x saved_data_buf=%x\n",
  400 + c,
386 (uint32_t)ctrl->channels[c].current_d.buf, 401 (uint32_t)ctrl->channels[c].current_d.buf,
387 (uint32_t)ctrl->channels[c].current_d.after, 402 (uint32_t)ctrl->channels[c].current_d.after,
388 saved_data_buf)); 403 saved_data_buf));
389 404
  405 + len = (uint32_t) ctrl->channels[c].current_d.after;
  406 + len -= saved_data_buf;
  407 +
  408 + if (len > sizeof buf)
  409 + len = sizeof buf;
  410 + cpu_physical_memory_read (saved_data_buf, buf, len);
  411 +
  412 + D(printf("channel %d pushes %x %u bytes\n", c,
  413 + saved_data_buf, len));
  414 +
  415 + if (ctrl->channels[c].client->client.push)
  416 + ctrl->channels[c].client->client.push(
  417 + ctrl->channels[c].client->client.opaque, buf, len);
  418 + else
  419 + printf("WARNING: DMA ch%d dataloss, no attached client.\n", c);
  420 +
  421 + saved_data_buf += len;
  422 +
390 if (saved_data_buf == (uint32_t)ctrl->channels[c].current_d.after) { 423 if (saved_data_buf == (uint32_t)ctrl->channels[c].current_d.after) {
391 /* Done. Step to next. */ 424 /* Done. Step to next. */
392 if (ctrl->channels[c].current_d.out_eop) { 425 if (ctrl->channels[c].current_d.out_eop) {
@@ -403,36 +436,26 @@ static void channel_out_run(struct fs_dma_ctrl *ctrl, int c) @@ -403,36 +436,26 @@ static void channel_out_run(struct fs_dma_ctrl *ctrl, int c)
403 if (ctrl->channels[c].current_d.eol) { 436 if (ctrl->channels[c].current_d.eol) {
404 D(printf("channel %d EOL\n", c)); 437 D(printf("channel %d EOL\n", c));
405 ctrl->channels[c].eol = 1; 438 ctrl->channels[c].eol = 1;
  439 +
  440 + /* Mark the context as disabled. */
  441 + ctrl->channels[c].current_c.dis = 1;
  442 + channel_store_c(ctrl, c);
  443 +
406 channel_stop(ctrl, c); 444 channel_stop(ctrl, c);
407 } else { 445 } else {
408 ctrl->channels[c].regs[RW_SAVED_DATA] = 446 ctrl->channels[c].regs[RW_SAVED_DATA] =
409 (uint32_t) ctrl->channels[c].current_d.next; 447 (uint32_t) ctrl->channels[c].current_d.next;
410 /* Load new descriptor. */ 448 /* Load new descriptor. */
411 channel_load_d(ctrl, c); 449 channel_load_d(ctrl, c);
  450 + saved_data_buf = (uint32_t)
  451 + ctrl->channels[c].current_d.buf;
412 } 452 }
413 453
414 channel_store_d(ctrl, c); 454 channel_store_d(ctrl, c);
  455 + ctrl->channels[c].regs[RW_SAVED_DATA_BUF] = saved_data_buf;
415 D(dump_d(c, &ctrl->channels[c].current_d)); 456 D(dump_d(c, &ctrl->channels[c].current_d));
416 - return;  
417 } 457 }
418 -  
419 - len = (uint32_t) ctrl->channels[c].current_d.after;  
420 - len -= saved_data_buf;  
421 -  
422 - if (len > sizeof buf)  
423 - len = sizeof buf;  
424 - cpu_physical_memory_read (saved_data_buf, buf, len);  
425 -  
426 - D(printf("channel %d pushes %x %u bytes\n", c,  
427 - saved_data_buf, len));  
428 - /* TODO: Push content. */  
429 - if (ctrl->channels[c].client->client.push)  
430 - ctrl->channels[c].client->client.push(  
431 - ctrl->channels[c].client->client.opaque, buf, len);  
432 - else  
433 - printf("WARNING: DMA ch%d dataloss, no attached client.\n", c);  
434 -  
435 - ctrl->channels[c].regs[RW_SAVED_DATA_BUF] += len; 458 + ctrl->channels[c].regs[RW_SAVED_DATA_BUF] = saved_data_buf;
436 } 459 }
437 460
438 static int channel_in_process(struct fs_dma_ctrl *ctrl, int c, 461 static int channel_in_process(struct fs_dma_ctrl *ctrl, int c,
@@ -483,14 +506,19 @@ static int channel_in_process(struct fs_dma_ctrl *ctrl, int c, @@ -483,14 +506,19 @@ static int channel_in_process(struct fs_dma_ctrl *ctrl, int c,
483 if (ctrl->channels[c].current_d.eol) { 506 if (ctrl->channels[c].current_d.eol) {
484 D(printf("channel %d EOL\n", c)); 507 D(printf("channel %d EOL\n", c));
485 ctrl->channels[c].eol = 1; 508 ctrl->channels[c].eol = 1;
  509 +
  510 + /* Mark the context as disabled. */
  511 + ctrl->channels[c].current_c.dis = 1;
  512 + channel_store_c(ctrl, c);
  513 +
486 channel_stop(ctrl, c); 514 channel_stop(ctrl, c);
487 } else { 515 } else {
488 ctrl->channels[c].regs[RW_SAVED_DATA] = 516 ctrl->channels[c].regs[RW_SAVED_DATA] =
489 (uint32_t) ctrl->channels[c].current_d.next; 517 (uint32_t) ctrl->channels[c].current_d.next;
490 /* Load new descriptor. */ 518 /* Load new descriptor. */
491 channel_load_d(ctrl, c); 519 channel_load_d(ctrl, c);
492 - saved_data_buf =  
493 - ctrl->channels[c].regs[RW_SAVED_DATA_BUF]; 520 + saved_data_buf = (uint32_t)
  521 + ctrl->channels[c].current_d.buf;
494 } 522 }
495 } 523 }
496 524
@@ -523,21 +551,21 @@ dma_readl (void *opaque, target_phys_addr_t addr) @@ -523,21 +551,21 @@ dma_readl (void *opaque, target_phys_addr_t addr)
523 551
524 /* Make addr relative to this instances base. */ 552 /* Make addr relative to this instances base. */
525 c = fs_channel(ctrl->base, addr); 553 c = fs_channel(ctrl->base, addr);
526 - addr &= 0x1fff; 554 + addr &= 0x1fff;
527 switch (addr) 555 switch (addr)
528 - { 556 + {
529 case RW_STAT: 557 case RW_STAT:
530 r = ctrl->channels[c].state & 7; 558 r = ctrl->channels[c].state & 7;
531 r |= ctrl->channels[c].eol << 5; 559 r |= ctrl->channels[c].eol << 5;
532 r |= ctrl->channels[c].stream_cmd_src << 8; 560 r |= ctrl->channels[c].stream_cmd_src << 8;
533 break; 561 break;
534 562
535 - default: 563 + default:
536 r = ctrl->channels[c].regs[addr]; 564 r = ctrl->channels[c].regs[addr];
537 D(printf ("%s c=%d addr=%x pc=%x\n", 565 D(printf ("%s c=%d addr=%x pc=%x\n",
538 - __func__, c, addr, env->pc));  
539 - break;  
540 - } 566 + __func__, c, addr, ctrl->env->pc));
  567 + break;
  568 + }
541 return r; 569 return r;
542 } 570 }
543 571
@@ -560,7 +588,7 @@ dma_writel (void *opaque, target_phys_addr_t addr, uint32_t value) @@ -560,7 +588,7 @@ dma_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
560 c = fs_channel(ctrl->base, addr); 588 c = fs_channel(ctrl->base, addr);
561 addr &= 0x1fff; 589 addr &= 0x1fff;
562 switch (addr) 590 switch (addr)
563 - { 591 + {
564 case RW_DATA: 592 case RW_DATA:
565 ctrl->channels[c].regs[addr] = value; 593 ctrl->channels[c].regs[addr] = value;
566 break; 594 break;
@@ -591,13 +619,15 @@ dma_writel (void *opaque, target_phys_addr_t addr, uint32_t value) @@ -591,13 +619,15 @@ dma_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
591 619
592 case RW_STREAM_CMD: 620 case RW_STREAM_CMD:
593 ctrl->channels[c].regs[addr] = value; 621 ctrl->channels[c].regs[addr] = value;
  622 + D(printf("stream_cmd ch=%d pc=%x\n",
  623 + c, ctrl->env->pc));
594 channel_stream_cmd(ctrl, c, value); 624 channel_stream_cmd(ctrl, c, value);
595 break; 625 break;
596 626
597 - default:  
598 - D(printf ("%s c=%d %x %x pc=%x\n",  
599 - __func__, c, addr, value, env->pc));  
600 - break; 627 + default:
  628 + D(printf ("%s c=%d %x %x pc=%x\n",
  629 + __func__, c, addr, value, ctrl->env->pc));
  630 + break;
601 } 631 }
602 } 632 }
603 633