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 267 target_phys_addr_t addr = channel_reg(ctrl, c, RW_SAVED_DATA);
268 268  
269 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 271 cpu_physical_memory_read (addr,
272 272 (void *) &ctrl->channels[c].current_d,
273 273 sizeof ctrl->channels[c].current_d);
274 274  
275 275 D(dump_d(c, &ctrl->channels[c].current_d));
276 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 291 static void channel_store_d(struct fs_dma_ctrl *ctrl, int c)
282 292 {
283 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 297 cpu_physical_memory_write (addr,
288 298 (void *) &ctrl->channels[c].current_d,
289 299 sizeof ctrl->channels[c].current_d);
... ... @@ -326,20 +336,23 @@ static void channel_continue(struct fs_dma_ctrl *ctrl, int c)
326 336 /* If the current descriptor cleared the eol flag and we had already
327 337 reached eol state, do the continue. */
328 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 340 ctrl->channels[c].current_d.next));
331 341 ctrl->channels[c].regs[RW_SAVED_DATA] =
332 342 (uint32_t) ctrl->channels[c].current_d.next;
333 343 channel_load_d(ctrl, c);
334 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 350 static void channel_stream_cmd(struct fs_dma_ctrl *ctrl, int c, uint32_t v)
339 351 {
340 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 356 if (cmd & regk_dma_load_d) {
344 357 channel_load_d(ctrl, c);
345 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 361  
349 362 if (cmd & regk_dma_load_c) {
350 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 396  
383 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 401 (uint32_t)ctrl->channels[c].current_d.buf,
387 402 (uint32_t)ctrl->channels[c].current_d.after,
388 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 423 if (saved_data_buf == (uint32_t)ctrl->channels[c].current_d.after) {
391 424 /* Done. Step to next. */
392 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 436 if (ctrl->channels[c].current_d.eol) {
404 437 D(printf("channel %d EOL\n", c));
405 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 444 channel_stop(ctrl, c);
407 445 } else {
408 446 ctrl->channels[c].regs[RW_SAVED_DATA] =
409 447 (uint32_t) ctrl->channels[c].current_d.next;
410 448 /* Load new descriptor. */
411 449 channel_load_d(ctrl, c);
  450 + saved_data_buf = (uint32_t)
  451 + ctrl->channels[c].current_d.buf;
412 452 }
413 453  
414 454 channel_store_d(ctrl, c);
  455 + ctrl->channels[c].regs[RW_SAVED_DATA_BUF] = saved_data_buf;
415 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 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 506 if (ctrl->channels[c].current_d.eol) {
484 507 D(printf("channel %d EOL\n", c));
485 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 514 channel_stop(ctrl, c);
487 515 } else {
488 516 ctrl->channels[c].regs[RW_SAVED_DATA] =
489 517 (uint32_t) ctrl->channels[c].current_d.next;
490 518 /* Load new descriptor. */
491 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 551  
524 552 /* Make addr relative to this instances base. */
525 553 c = fs_channel(ctrl->base, addr);
526   - addr &= 0x1fff;
  554 + addr &= 0x1fff;
527 555 switch (addr)
528   - {
  556 + {
529 557 case RW_STAT:
530 558 r = ctrl->channels[c].state & 7;
531 559 r |= ctrl->channels[c].eol << 5;
532 560 r |= ctrl->channels[c].stream_cmd_src << 8;
533 561 break;
534 562  
535   - default:
  563 + default:
536 564 r = ctrl->channels[c].regs[addr];
537 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 569 return r;
542 570 }
543 571  
... ... @@ -560,7 +588,7 @@ dma_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
560 588 c = fs_channel(ctrl->base, addr);
561 589 addr &= 0x1fff;
562 590 switch (addr)
563   - {
  591 + {
564 592 case RW_DATA:
565 593 ctrl->channels[c].regs[addr] = value;
566 594 break;
... ... @@ -591,13 +619,15 @@ dma_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
591 619  
592 620 case RW_STREAM_CMD:
593 621 ctrl->channels[c].regs[addr] = value;
  622 + D(printf("stream_cmd ch=%d pc=%x\n",
  623 + c, ctrl->env->pc));
594 624 channel_stream_cmd(ctrl, c, value);
595 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  
... ...