func: static void stream_process_mem2s(struct Stream *s,
  
                                   StreamSlave *tx_dev)
  
  {
  
      uint32_t prev_d;
  
      unsigned char txbuf[16 * 1024];
  
      unsigned int txlen;
  
      uint32_t app[6];
  
  
  
      if (!stream_running(s) || stream_idle(s)) {
  
          return;
  
      }
  
  
  
      while (1) {
  
          stream_desc_load(s, s->regs[R_CURDESC]);
  
  
  
          if (s->desc.status & SDESC_STATUS_COMPLETE) {
  
              s->regs[R_DMASR] |= DMASR_HALTED;
  
              break;
  
          }
  
  
  
          if (stream_desc_sof(&s->desc)) {
  
              s->pos = 0;
  
              memcpy(app, s->desc.app, sizeof app);
  
          }
  
  
  
          txlen = s->desc.control & SDESC_CTRL_LEN_MASK;
  
          if ((txlen + s->pos) > sizeof txbuf) {
  
              hw_error("%s: too small internal txbuf! %d\n", __func__,
  
                       txlen + s->pos);
  
          }
  
  
  
          cpu_physical_memory_read(s->desc.buffer_address,
  
                                   txbuf + s->pos, txlen);
  
          s->pos += txlen;
  
  
  
          if (stream_desc_eof(&s->desc)) {
  
              stream_push(tx_dev, txbuf, s->pos, app);
  
              s->pos = 0;
  
              stream_complete(s);
  
          }
  
  
  
          /* Update the descriptor.  */
  
          s->desc.status = txlen | SDESC_STATUS_COMPLETE;
  
          stream_desc_store(s, s->regs[R_CURDESC]);
  
  
  
          /* Advance.  */
  
          prev_d = s->regs[R_CURDESC];
  
          s->regs[R_CURDESC] = s->desc.nxtdesc;
  
          if (prev_d == s->regs[R_TAILDESC]) {
  
              s->regs[R_DMASR] |= DMASR_IDLE;
  
              break;
  
          }
  
      }
  
  }
  