diff options
| -rw-r--r-- | dma/ipe.c | 71 | 
1 files changed, 41 insertions, 30 deletions
@@ -289,61 +289,72 @@ int dma_ipe_get_status(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, pcil      void *desc_va = (void*)pcilib_kmem_get_ua(ctx->pcilib, ctx->desc);      uint32_t *last_written_addr_ptr;      uint32_t last_written_addr; -          if (!status) return -1;      if (ctx->mode64) last_written_addr_ptr = desc_va + 3 * sizeof(uint32_t);      else last_written_addr_ptr = desc_va + 4 * sizeof(uint32_t); -    last_written_addr = ntohl(*last_written_addr_ptr); +    last_written_addr = *last_written_addr_ptr;      status->started = ctx->started;      status->ring_size = ctx->ring_size;      status->buffer_size = ctx->page_size; -    status->ring_tail = ctx->last_read + 1; -    if (status->ring_tail == status->ring_size) status->ring_tail = 0; +	// For simplicity, we keep last_read here, and fix in the end +    status->ring_tail = ctx->last_read;  	// Find where the ring head is actually are      for (i = 0; i < ctx->ring_size; i++) {  	uintptr_t bus_addr = pcilib_kmem_get_block_ba(ctx->pcilib, ctx->pages, i);  	if (bus_addr == last_written_addr) { -	    status->ring_head = bus_addr; +	    status->ring_head = i;  	    break;  	}      } -     +      if (i == ctx->ring_size) { -	// ERROR +	if (last_written_addr) { +	    pcilib_warning("DMA is in unknown state, last_written_addr does not correspond any of available buffers"); +	    return -1; +	} +	status->ring_head = 0; +	status->ring_tail = 0;      } -     -    if (n_buffers > ctx->ring_size) n_buffers = ctx->ring_size; -    memset(buffers, 0, n_buffers * sizeof(pcilib_dma_engine_status_t)); +    if (n_buffers > ctx->ring_size) n_buffers = ctx->ring_size; -    if (status->ring_head > status->ring_tail) { -	for (i = status->ring_tail; i <= status->ring_head; i++) { -	    buffers[i].used = 1; -	    buffers[i].size = ctx->page_size; -	    buffers[i].first = 1; -	    buffers[i].last = 1; +    if (buffers) { +	memset(buffers, 0, n_buffers * sizeof(pcilib_dma_buffer_status_t)); +	if (status->ring_head >= status->ring_tail) { +	    for (i = status->ring_tail + 1; (i <= status->ring_head)&&(i < n_buffers); i++) { +		buffers[i].used = 1; +		buffers[i].size = ctx->page_size; +		buffers[i].first = 1; +		buffers[i].last = 1; +	    } +	} else { +	    for (i = 0; (i <= status->ring_head)&&(i < n_buffers); i++) { +		buffers[i].used = 1; +		buffers[i].size = ctx->page_size; +		buffers[i].first = 1; +		buffers[i].last = 1; +	    }  + +	    for (i = status->ring_tail + 1; (i < status->ring_size)&&(i < n_buffers); i++) { +		buffers[i].used = 1; +		buffers[i].size = ctx->page_size; +		buffers[i].first = 1; +		buffers[i].last = 1; +	    }  	} -    } else { -	for (i = 0; i <= status->ring_tail; i++) { -	    buffers[i].used = 1; -	    buffers[i].size = ctx->page_size; -	    buffers[i].first = 1; -	    buffers[i].last = 1; -	}  -	 -	for (i = status->ring_head; i < status->ring_size; i++) { -	    buffers[i].used = 1; -	    buffers[i].size = ctx->page_size; -	    buffers[i].first = 1; -	    buffers[i].last = 1; -	}  +    } + +	// We actually keep last_read in the ring_tail, so need to increase +    if (status->ring_tail != status->ring_head) { +	status->ring_tail++; +	if (status->ring_tail == status->ring_size) status->ring_tail = 0;      }      return 0;  | 
