diff options
Diffstat (limited to 'dma')
| -rw-r--r-- | dma/CMakeLists.txt | 4 | ||||
| -rw-r--r-- | dma/ipe.c | 412 | ||||
| -rw-r--r-- | dma/ipe.h | 42 | ||||
| -rw-r--r-- | dma/ipe_private.h | 56 | ||||
| -rw-r--r-- | dma/ipe_registers.h | 44 | ||||
| -rw-r--r-- | dma/nwl.c | 2 | ||||
| -rw-r--r-- | dma/nwl.h | 89 | ||||
| -rw-r--r-- | dma/nwl_dma.h | 45 | ||||
| -rw-r--r-- | dma/nwl_engine.c | 2 | ||||
| -rw-r--r-- | dma/nwl_engine_buffers.h | 6 | ||||
| -rw-r--r-- | dma/nwl_irq.c | 2 | ||||
| -rw-r--r-- | dma/nwl_loopback.c | 2 | ||||
| -rw-r--r-- | dma/nwl_private.h | 67 | ||||
| -rw-r--r-- | dma/nwl_register.c | 2 | 
14 files changed, 665 insertions, 110 deletions
diff --git a/dma/CMakeLists.txt b/dma/CMakeLists.txt index 3d4226a..44bf18c 100644 --- a/dma/CMakeLists.txt +++ b/dma/CMakeLists.txt @@ -3,7 +3,7 @@ include_directories(  ) -set(HEADERS ${HEADERS} nwl.h nwl_dma.h nwl_engine.h nwl_irq.h nwl_loopback.h nwl_register.h) +set(HEADERS ${HEADERS} nwl.h nwl_private.h nwl_engine.h nwl_irq.h nwl_loopback.h nwl_register.h ipe.h ipe_private.h ipe_registers.h) -add_library(dma STATIC nwl.c nwl_engine.c nwl_irq.c nwl_loopback.c nwl_register.c) +add_library(dma STATIC nwl.c nwl_engine.c nwl_irq.c nwl_loopback.c nwl_register.c ipe.c) diff --git a/dma/ipe.c b/dma/ipe.c new file mode 100644 index 0000000..eb1ad6d --- /dev/null +++ b/dma/ipe.c @@ -0,0 +1,412 @@ +#define _PCILIB_DMA_IPE_C +#define _BSD_SOURCE + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/time.h> +#include <arpa/inet.h> + +#include "pci.h" +#include "pcilib.h" +#include "error.h" +#include "tools.h" + +#include "ipe.h" +#include "ipe_private.h" +#include "ipe_registers.h" + + +#define WR(addr, value) { *(uint32_t*)(ctx->base_addr + addr) = value; } +#define RD(addr, value) { value = *(uint32_t*)(ctx->base_addr + addr); } + + +pcilib_dma_context_t *dma_ipe_init(pcilib_t *pcilib, pcilib_dma_modification_t type, void *arg) { +    int err = 0; +     +    pcilib_model_description_t *model_info = pcilib_get_model_description(pcilib); + +    ipe_dma_t *ctx = malloc(sizeof(ipe_dma_t)); + +    if (ctx) { +	memset(ctx, 0, sizeof(ipe_dma_t)); +	ctx->pcilib = pcilib; +	 +	memset(ctx->engine, 0, 2 * sizeof(pcilib_dma_engine_description_t)); +	ctx->engine[0].addr = 0; +	ctx->engine[0].type = PCILIB_DMA_TYPE_PACKET; +	ctx->engine[0].direction = PCILIB_DMA_FROM_DEVICE; +	ctx->engine[0].addr_bits = 32; +	pcilib_set_dma_engine_description(pcilib, 0, &ctx->engine[0]); +	pcilib_set_dma_engine_description(pcilib, 1, NULL); + +	pcilib_register_bank_t dma_bank = pcilib_find_bank_by_addr(pcilib, PCILIB_REGISTER_BANK_DMA); +	if (dma_bank == PCILIB_REGISTER_BANK_INVALID) { +	    free(ctx); +	    pcilib_error("DMA Register Bank could not be found"); +	    return NULL; +	} + +	ctx->dma_bank = model_info->banks + dma_bank; +	ctx->base_addr = pcilib_resolve_register_address(pcilib, ctx->dma_bank->bar, ctx->dma_bank->read_addr); + +	err = pcilib_add_registers(ctx->pcilib, 0, ipe_dma_registers); +	if (err) { +	    free(ctx); +	    pcilib_error("Error adding DMA registers"); +	    return NULL; +	} +    } + +    return (pcilib_dma_context_t*)ctx; +} + +void  dma_ipe_free(pcilib_dma_context_t *vctx) { +    ipe_dma_t *ctx = (ipe_dma_t*)vctx; + +    if (ctx) { +	dma_ipe_stop(vctx, PCILIB_DMA_ENGINE_ALL, PCILIB_DMA_FLAGS_DEFAULT); +	free(ctx); +    } +} + + +int dma_ipe_start(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags) { +    size_t i; + +    ipe_dma_t *ctx = (ipe_dma_t*)vctx; + +    int preserve = 0; +    pcilib_kmem_flags_t kflags; +    pcilib_kmem_reuse_state_t reuse_desc, reuse_pages; + +    volatile void *desc_va; +    volatile uint32_t *last_written_addr_ptr; + +    pcilib_register_value_t value; + +    if (dma == PCILIB_DMA_ENGINE_INVALID) return 0; +    else if (dma > 1) return PCILIB_ERROR_INVALID_BANK; + +    if (!ctx->started) ctx->started = 1; + +    if (flags&PCILIB_DMA_FLAG_PERSISTENT) ctx->preserve = 1; + +    if (ctx->pages) return 0; +     +    kflags = PCILIB_KMEM_FLAG_REUSE|PCILIB_KMEM_FLAG_EXCLUSIVE|PCILIB_KMEM_FLAG_HARDWARE|(ctx->preserve?PCILIB_KMEM_FLAG_PERSISTENT:0); +    pcilib_kmem_handle_t *desc = pcilib_alloc_kernel_memory(ctx->pcilib, PCILIB_KMEM_TYPE_CONSISTENT, 1, IPEDMA_DESCRIPTOR_SIZE, IPEDMA_DESCRIPTOR_ALIGNMENT, PCILIB_KMEM_USE(PCILIB_KMEM_USE_DMA_RING, 0x00), kflags); +    pcilib_kmem_handle_t *pages = pcilib_alloc_kernel_memory(ctx->pcilib, PCILIB_KMEM_TYPE_DMA_C2S_PAGE, IPEDMA_DMA_PAGES, 0, 0, PCILIB_KMEM_USE(PCILIB_KMEM_USE_DMA_PAGES, 0x00), kflags); + +    if (!desc||!pages) { +	if (pages) pcilib_free_kernel_memory(ctx->pcilib, pages, 0); +	if (desc) pcilib_free_kernel_memory(ctx->pcilib, desc, 0); +	return PCILIB_ERROR_MEMORY; +    } +    reuse_desc = pcilib_kmem_is_reused(ctx->pcilib, desc); +    reuse_pages = pcilib_kmem_is_reused(ctx->pcilib, pages); + +    if (reuse_desc == reuse_pages) { +	if (reuse_desc & PCILIB_KMEM_REUSE_PARTIAL) pcilib_warning("Inconsistent DMA buffers are found (only part of required buffers is available), reinitializing..."); +	else if (reuse_desc & PCILIB_KMEM_REUSE_REUSED) { +	    if ((reuse_desc & PCILIB_KMEM_REUSE_PERSISTENT) == 0) pcilib_warning("Lost DMA buffers are found (non-persistent mode), reinitializing..."); +	    else if ((reuse_desc & PCILIB_KMEM_REUSE_HARDWARE) == 0) pcilib_warning("Lost DMA buffers are found (missing HW reference), reinitializing..."); +	    else { +#ifndef IPEDMA_BUG_DMARD +		RD(IPEDMA_REG_PAGE_COUNT, value); + +		if ((value + 1) != IPEDMA_DMA_PAGES) pcilib_warning("Inconsistent DMA buffers are found (Number of allocated buffers does not match current request), reinitializing..."); +		else +#endif /* IPEDMA_BUG_DMARD */ +		    preserve = 1; +	    } +	} +    } else pcilib_warning("Inconsistent DMA buffers (modes of ring and page buffers does not match), reinitializing...."); + +    desc_va = pcilib_kmem_get_ua(ctx->pcilib, desc); +    if (ctx->mode64) last_written_addr_ptr = desc_va + 3 * sizeof(uint32_t); +    else last_written_addr_ptr = desc_va + 4 * sizeof(uint32_t); + +    if (preserve) { +	ctx->reused = 1; +	ctx->preserve = 1; +	 + +//	usleep(100000); + +	    // Detect the current state of DMA engine +#ifdef IPEDMA_BUG_DMARD +	FILE *f = fopen("/tmp/pcitool_lastread", "r"); +	if (!f) pcilib_error("Can't read current status"); +	fread(&value, 1, sizeof(pcilib_register_value_t), f); +	fclose(f); +#else /* IPEDMA_BUG_DMARD */ +	RD(IPEDMA_REG_LAST_READ, value); +	if (value == IPEDMA_DMA_PAGES) value = 0; +#endif /* IPEDMA_BUG_DMARD */ + +	ctx->last_read = value; +    } else { +	ctx->reused = 0; + +	    // Disable DMA +	WR(IPEDMA_REG_CONTROL, 0x0); +	 +	    // Reset DMA engine +	WR(IPEDMA_REG_RESET, 0x1); +	usleep(100000); +	WR(IPEDMA_REG_RESET, 0x0); + +#ifndef IPEDMA_BUG_DMARD +	    // Verify PCIe link status +	RD(IPEDMA_REG_RESET, value); +	if (value != 0x14031700) pcilib_warning("PCIe is not ready"); +#endif /* IPEDMA_BUG_DMARD */ +  +	    // Configuring TLP and PACKET sizes (40 bit mode can be used with big pre-allocated buffers later) +        WR(IPEDMA_REG_TLP_SIZE, IPEDMA_TLP_SIZE); +        WR(IPEDMA_REG_TLP_COUNT, IPEDMA_PAGE_SIZE / (4 * IPEDMA_TLP_SIZE * IPEDMA_CORES)); + +	    // Setting progress register threshold +	WR(IPEDMA_REG_UPDATE_THRESHOLD, IPEDMA_DMA_PROGRESS_THRESHOLD); +         +	    // Reseting configured DMA pages +        WR(IPEDMA_REG_PAGE_COUNT, 0); +         +	    // Setting current read position and configuring progress register +	WR(IPEDMA_REG_LAST_READ, IPEDMA_DMA_PAGES - 2 + 1); +	WR(IPEDMA_REG_UPDATE_ADDR, pcilib_kmem_get_block_ba(ctx->pcilib, desc, 0)); + +	    // Instructing DMA engine that writting should start from the first DMA page +	*last_written_addr_ptr = 0;//htonl(pcilib_kmem_get_block_ba(ctx->pcilib, pages, IPEDMA_DMA_PAGES - 1)); + +	 +	for (i = 0; i < IPEDMA_DMA_PAGES; i++) { +	    uintptr_t bus_addr = pcilib_kmem_get_block_ba(ctx->pcilib, pages, i); +	    WR(IPEDMA_REG_PAGE_ADDR, bus_addr); +	    if (bus_addr%4096) printf("Bad address %lu: %lx\n", i, bus_addr); +	    usleep(1000); +	} +	 +	    // Enable DMA +	WR(IPEDMA_REG_CONTROL, 0x1); +	 +	ctx->last_read = IPEDMA_DMA_PAGES - 1; + +#ifdef IPEDMA_BUG_DMARD +	FILE *f = fopen("/tmp/pcitool_lastread", "w"); +	if (!f) pcilib_error("Can't write current status"); +	value = ctx->last_read; +	fwrite(&value, 1, sizeof(pcilib_register_value_t), f); +	fclose(f); +#endif /* IPEDMA_BUG_DMARD */ +    } + +    ctx->last_read_addr = htonl(pcilib_kmem_get_block_ba(ctx->pcilib, pages, ctx->last_read)); + + +    ctx->desc = desc; +    ctx->pages = pages; +    ctx->page_size = pcilib_kmem_get_block_size(ctx->pcilib, pages, 0);; +    ctx->ring_size = IPEDMA_DMA_PAGES; + +    return 0; +} + +int dma_ipe_stop(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags) { +    pcilib_kmem_flags_t kflags; + +    ipe_dma_t *ctx = (ipe_dma_t*)vctx; + +    if (!ctx->started) return 0; + +    if ((dma != PCILIB_DMA_ENGINE_INVALID)&&(dma > 1)) return PCILIB_ERROR_INVALID_BANK; + +	    // ignoring previous setting if flag specified +    if (flags&PCILIB_DMA_FLAG_PERSISTENT) { +	ctx->preserve = 0; +    } + +    if (ctx->preserve) { +	kflags = PCILIB_KMEM_FLAG_REUSE; +    } else { +        kflags = PCILIB_KMEM_FLAG_HARDWARE|PCILIB_KMEM_FLAG_PERSISTENT; + +	ctx->started  = 0; + +	    // Disable DMA +	WR(IPEDMA_REG_CONTROL, 0); +	 +	    // Reset DMA engine +	WR(IPEDMA_REG_RESET, 0x1); +	usleep(100000); +	WR(IPEDMA_REG_RESET, 0x0); + +	    // Reseting configured DMA pages +        WR(IPEDMA_REG_PAGE_COUNT, 0); +    } + +	// Clean buffers +    if (ctx->desc) { +	pcilib_free_kernel_memory(ctx->pcilib, ctx->desc, kflags); +	ctx->desc = NULL; +    } + +    if (ctx->pages) { +	pcilib_free_kernel_memory(ctx->pcilib, ctx->pages, kflags); +	ctx->pages = NULL; +    } + +    return 0; +} + + +int dma_ipe_get_status(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, pcilib_dma_engine_status_t *status, size_t n_buffers, pcilib_dma_buffer_status_t *buffers) { +    size_t i; +    ipe_dma_t *ctx = (ipe_dma_t*)vctx; + +    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); + +    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; + +	// 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; +	    break; +	} +    } +     +    if (i == ctx->ring_size) { +	// ERROR +    } +     +    if (n_buffers > ctx->ring_size) n_buffers = ctx->ring_size; + +    memset(buffers, 0, n_buffers * sizeof(pcilib_dma_engine_status_t)); + +    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; +	} +    } 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; +	}  +    } + +    return 0; +} + +int dma_ipe_stream_read(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, pcilib_dma_flags_t flags, pcilib_timeout_t timeout, pcilib_dma_callback_t cb, void *cbattr) { +    int err, ret = PCILIB_STREAMING_REQ_PACKET; + +    pcilib_register_value_t value; + +    pcilib_timeout_t wait = 0; +    struct timeval start, cur; + +    volatile void *desc_va; +    volatile uint32_t *last_written_addr_ptr; +     +    size_t cur_read; +     +    ipe_dma_t *ctx = (ipe_dma_t*)vctx; + +    err = dma_ipe_start(vctx, dma, PCILIB_DMA_FLAGS_DEFAULT); +    if (err) return err; + +    desc_va = (void*)pcilib_kmem_get_ua(ctx->pcilib, ctx->desc); + +    if (ctx->mode64) last_written_addr_ptr = desc_va + 3 * sizeof(uint32_t); +    else last_written_addr_ptr = desc_va + 4 * sizeof(uint32_t); + +    do { +	switch (ret&PCILIB_STREAMING_TIMEOUT_MASK) { +	    case PCILIB_STREAMING_CONTINUE: wait = PCILIB_DMA_TIMEOUT; break; +	    case PCILIB_STREAMING_WAIT: wait = timeout; break; +//	    case PCILIB_STREAMING_CHECK: wait = 0; break; +	} + +#ifdef IPEDMA_DEBUG +	printf("Waiting for data: %u (last read) 0x%x (last read addr) 0x%x (last_written)\n", ctx->last_read, ctx->last_read_addr, *last_written_addr_ptr); +#endif /* IPEDMA_DEBUG */ + +	gettimeofday(&start, NULL); +	while (((*last_written_addr_ptr == 0)||(ctx->last_read_addr == (*last_written_addr_ptr)))&&((wait == PCILIB_TIMEOUT_INFINITE)||(((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec)) < wait))) { +	    usleep(10); +	    gettimeofday(&cur, NULL); +	} +	 +	    // Failing out if we exited on timeout +	if ((ctx->last_read_addr == (*last_written_addr_ptr))||(*last_written_addr_ptr == 0)) +	    return (ret&PCILIB_STREAMING_FAIL)?PCILIB_ERROR_TIMEOUT:0; + +	    // Getting next page to read +	cur_read = ctx->last_read + 1; +	if (cur_read == ctx->ring_size) cur_read = 0; + +#ifdef IPEDMA_DEBUG +	printf("Reading: %u (last read) 0x%x (last read addr) 0x%x (last_written)\n", cur_read, ctx->last_read_addr, *last_written_addr_ptr); +#endif /* IPEDMA_DEBUG */ +	 +	pcilib_kmem_sync_block(ctx->pcilib, ctx->pages, PCILIB_KMEM_SYNC_FROMDEVICE, cur_read); +        void *buf = pcilib_kmem_get_block_ua(ctx->pcilib, ctx->pages, cur_read); +	ret = cb(cbattr, PCILIB_DMA_FLAG_EOP, ctx->page_size, buf); +	if (ret < 0) return -ret; +	 +//	DS: Fixme, it looks like we can avoid calling this for the sake of performance +//	pcilib_kmem_sync_block(ctx->pcilib, ctx->pages, PCILIB_KMEM_SYNC_TODEVICE, cur_read); + +	WR(IPEDMA_REG_LAST_READ, ctx->last_read + 1); + +	ctx->last_read = cur_read; +	ctx->last_read_addr = htonl(pcilib_kmem_get_block_ba(ctx->pcilib, ctx->pages, cur_read)); + +#ifdef IPEDMA_BUG_DMARD +	FILE *f = fopen("/tmp/pcitool_lastread", "w"); +	if (!f) pcilib_error("Can't write current status"); +	value = cur_read; +	fwrite(&value, 1, sizeof(pcilib_register_value_t), f); +	fclose(f); +#endif /* IPEDMA_BUG_DMARD */ + +    } while (ret); + +    return 0; +} + +double dma_ipe_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dma, uintptr_t addr, size_t size, size_t iterations, pcilib_dma_direction_t direction) { +    return 0; +} diff --git a/dma/ipe.h b/dma/ipe.h new file mode 100644 index 0000000..2c34ff1 --- /dev/null +++ b/dma/ipe.h @@ -0,0 +1,42 @@ +#ifndef _PCILIB_DMA_IPE_H +#define _PCILIB_DMA_IPE_H + +#include <stdio.h> +#include "../pcilib.h" + +//#define PCILIB_NWL_MODIFICATION_IPECAMERA 0x100 + +pcilib_dma_context_t *dma_ipe_init(pcilib_t *ctx, pcilib_dma_modification_t type, void *arg); +void  dma_ipe_free(pcilib_dma_context_t *vctx); + +int dma_ipe_get_status(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, pcilib_dma_engine_status_t *status, size_t n_buffers, pcilib_dma_buffer_status_t *buffers); + + +int dma_ipe_start(pcilib_dma_context_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags); +int dma_ipe_stop(pcilib_dma_context_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags); + +int dma_ipe_stream_read(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, pcilib_dma_flags_t flags, pcilib_timeout_t timeout, pcilib_dma_callback_t cb, void *cbattr); +double dma_ipe_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dma, uintptr_t addr, size_t size, size_t iterations, pcilib_dma_direction_t direction); + + +#ifdef _PCILIB_DMA_IPE_C +pcilib_dma_api_description_t ipe_dma_api = { +    "ipe_dma", +    dma_ipe_init, +    dma_ipe_free, +    dma_ipe_get_status, +    NULL, +    NULL, +    NULL, +    dma_ipe_start, +    dma_ipe_stop, +    NULL, +    dma_ipe_stream_read, +    dma_ipe_benchmark +}; +#else +extern pcilib_dma_api_description_t ipe_dma_api; +#endif + + +#endif /* _PCILIB_DMA_IPE_H */ diff --git a/dma/ipe_private.h b/dma/ipe_private.h new file mode 100644 index 0000000..e6e70c2 --- /dev/null +++ b/dma/ipe_private.h @@ -0,0 +1,56 @@ +#ifndef _PCILIB_DMA_IPE_PRIVATE_H +#define _PCILIB_DMA_IPE_PRIVATE_H + +#define IPEDMA_CORES			1 +#define IPEDMA_TLP_SIZE			32 +#define IPEDMA_PAGE_SIZE		4096 +#define IPEDMA_DMA_PAGES		16		/**< number of DMA pages in the ring buffer to allocate */ +#define IPEDMA_DMA_PROGRESS_THRESHOLD	1		/**< how many pages the DMA engine should fill before reporting progress */ +#define IPEDMA_DESCRIPTOR_SIZE		128 +#define IPEDMA_DESCRIPTOR_ALIGNMENT	64 + +//#define IPEDMA_DEBUG +#define IPEDMA_BUG_DMARD				/**< No register read during DMA transfer */ + +#define IPEDMA_REG_RESET		0x00 +#define IPEDMA_REG_CONTROL		0x04 +#define IPEDMA_REG_TLP_SIZE		0x0C +#define IPEDMA_REG_TLP_COUNT		0x10 +#define IPEDMA_REG_PAGE_ADDR		0x50 +#define IPEDMA_REG_UPDATE_ADDR		0x54 +#define IPEDMA_REG_LAST_READ		0x58 +#define IPEDMA_REG_PAGE_COUNT		0x5C +#define IPEDMA_REG_UPDATE_THRESHOLD	0x60 + + + +typedef struct ipe_dma_s ipe_dma_t; + +struct ipe_dma_s { +    struct pcilib_dma_context_s dmactx; +    pcilib_dma_engine_description_t engine[2]; + +    pcilib_t *pcilib; +     +    pcilib_register_bank_description_t *dma_bank; +    char *base_addr; + +    pcilib_irq_type_t irq_enabled;	/**< indicates that IRQs are enabled */ +    pcilib_irq_type_t irq_preserve;	/**< indicates that IRQs should not be disabled during clean-up */ +    int irq_started;			/**< indicates that IRQ subsystem is initialized (detecting which types should be preserverd) */     + +    int started;			/**< indicates that DMA buffers are initialized and reading is allowed */ +    int writting;			/**< indicates that we are in middle of writting packet */ +    int reused;				/**< indicates that DMA was found intialized, buffers were reused, and no additional initialization is needed */ +    int preserve;			/**< indicates that DMA should not be stopped during clean-up */ +    int mode64;				/**< indicates 64-bit operation mode */ + +    pcilib_kmem_handle_t *desc;		/**< in-memory status descriptor written by DMA engine upon operation progess */ +    pcilib_kmem_handle_t *pages;	/**< collection of memory-locked pages for DMA operation */ + +    size_t ring_size, page_size; +    size_t last_read, last_read_addr, last_written; + +}; + +#endif /* _PCILIB_DMA_IPE_PRIVATE_H */ diff --git a/dma/ipe_registers.h b/dma/ipe_registers.h new file mode 100644 index 0000000..17fc41a --- /dev/null +++ b/dma/ipe_registers.h @@ -0,0 +1,44 @@ +#ifndef _PCILIB_DMA_IPE_REGISTERS_H +#define _PCILIB_DMA_IPE_REGISTERS_H  + +#ifdef _PCILIB_DMA_IPE_C  +static pcilib_register_description_t ipe_dma_registers[] = { +    {0x0000, 	0, 	32, 	0, 	0x00000000,	PCILIB_REGISTER_RW  , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dcr",  			"Device Control Status Register"}, +    {0x0000, 	0, 	1, 	0, 	0x00000000,	PCILIB_REGISTER_RW  , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "reset_dma",  			""}, +    {0x0000, 	16, 	4, 	0, 	0x00000000,	PCILIB_REGISTER_R   , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "datapath_width",			""}, +    {0x0000, 	24, 	8, 	0, 	0x00000000,	PCILIB_REGISTER_R   , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "fpga_family",			""}, +    {0x0004, 	0, 	32, 	0, 	0x00000000,	PCILIB_REGISTER_RW  , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "ddmacr",  			"Device DMA Control Status Register"}, +    {0x0004, 	0, 	1, 	0, 	0xFFFFFFFF,	PCILIB_REGISTER_RW  , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "mwr_start",  			"Start writting memory"}, +    {0x0004, 	5, 	1, 	0, 	0x00000000,	PCILIB_REGISTER_R   , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "mwr_relxed_order",  		""}, +    {0x0004, 	6, 	1, 	0, 	0x00000000,	PCILIB_REGISTER_R   , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "mwr_nosnoop",  			""}, +    {0x0004, 	7, 	1, 	0, 	0x00000000,	PCILIB_REGISTER_R   , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "mwr_int_dis",  			""}, +    {0x0004, 	16, 	1, 	0, 	0x00000000,	PCILIB_REGISTER_R   , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "mrd_start",  			""}, +    {0x0004, 	21, 	1, 	0, 	0x00000000,	PCILIB_REGISTER_R   , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "mrd_relaxed_order",  		""}, +    {0x0004, 	22, 	1, 	0, 	0x00000000,	PCILIB_REGISTER_R   , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "mrd_nosnoop",  			""}, +    {0x0004, 	23, 	1, 	0, 	0x00000000,	PCILIB_REGISTER_R   , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "mrd_int_dis",  			""}, +    {0x000C, 	0, 	32, 	0, 	0x00000000,	PCILIB_REGISTER_RW  , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "mwr_size",  			"DMA TLP size"}, +    {0x000C, 	0, 	16, 	0x20, 	0xFFFFFFFF,	PCILIB_REGISTER_RW  , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "mwr_len",  			"Max TLP size"}, +    {0x000C, 	16, 	3, 	0, 	0x00000000,	PCILIB_REGISTER_R   , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "mwr_tlp_tc",  			"TC for TLP packets"}, +    {0x000C, 	19, 	1, 	0, 	0xFFFFFFFF,	PCILIB_REGISTER_RW  , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "mwr_64b_en",  			"Enable 64 bit memory addressing"}, +    {0x000C, 	20, 	1, 	0, 	0x00000000,	PCILIB_REGISTER_R   , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "mwr_phant_func_dis",		"Disable MWR phantom function"}, +    {0x000C, 	24, 	8, 	0, 	0xFFFFFFFF,	PCILIB_REGISTER_RW  , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "mwr_up_addr",  			"Upper address for 64 bit memory addressing"}, +    {0x0010, 	0, 	32, 	0, 	0x00000000,	PCILIB_REGISTER_RW  , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "mwr_count",  		"Write DMA TLP Count"}, +    {0x0014, 	0, 	32, 	0, 	0x00000000,	PCILIB_REGISTER_RW  , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "mwr_pattern",  		"DMA generator data pattern"}, +    {0x0028, 	0, 	32, 	0, 	0x00000000,	PCILIB_REGISTER_R   , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "mwr_perf",			"MWR Performance"}, +    {0x003C, 	0, 	32, 	0, 	0x00000000,	PCILIB_REGISTER_R   , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "cfg_lnk_width",		"Negotiated and max width of PCIe Link"}, +    {0x003C, 	0, 	6, 	0, 	0x00000000,	PCILIB_REGISTER_R   , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "cfg_cap_max_lnk_width", 		"Max link width"}, +    {0x003C, 	8, 	6, 	0, 	0x00000000,	PCILIB_REGISTER_R   , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "cfg_prg_max_lnk_width", 		"Negotiated link width"}, +    {0x0040, 	0, 	32, 	0, 	0x00000000,	PCILIB_REGISTER_R   , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "cfg_payload_size",  		""}, +    {0x0040, 	0, 	4, 	0, 	0x00000000,	PCILIB_REGISTER_R   , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "cfg_cap_max_payload_size",	"Max payload size"}, +    {0x0040, 	8, 	3, 	0, 	0x00000000,	PCILIB_REGISTER_R   , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "cfg_prg_max_payload_size",	"Prog max payload size"}, +    {0x0040, 	16, 	3, 	0, 	0x00000000,	PCILIB_REGISTER_R   , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "cfg_max_rd_req_size",		"Max read request size"}, +    {0x0050, 	0, 	32, 	0, 	0x00000000,	PCILIB_REGISTER_RW  , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "desc_mem_din",  		"Descriptor memory"}, +    {0x0054, 	0, 	32, 	0, 	0x00000000,	PCILIB_REGISTER_RW  , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "update_addr",  		"Address of progress register"}, +    {0x0058, 	0, 	32, 	0, 	0x00000000,	PCILIB_REGISTER_RW  , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "last_descriptor_read",	"Last descriptor read by the host"}, +    {0x005C, 	0, 	32, 	0, 	0x00000000,	PCILIB_REGISTER_RW  , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "desc_mem_addr", 		"Number of descriptors configured"}, +    {0x0060, 	0, 	32, 	0, 	0x00000000,	PCILIB_REGISTER_RW  , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "update_thresh",  		"Update threshold of progress register"}, +    {0,		0,	0,	0,	0x00000000,	0,                                           0,                        0, NULL, 			NULL} +}; +#endif /* _PCILIB_DMA_IPE_C */ + +#endif /* _PCILIB_DMA_IPE_REGISTERS_H */ @@ -11,7 +11,7 @@  #include "pcilib.h"  #include "error.h"  #include "tools.h" -#include "nwl.h" +#include "nwl_private.h"  #include "nwl_defines.h" @@ -1,67 +1,46 @@ -#ifndef _PCILIB_NWL_H -#define _PCILIB_NWL_H +#ifndef _PCILIB_DMA_NWL_H +#define _PCILIB_DMA_NWL_H -typedef struct nwl_dma_s nwl_dma_t; -typedef struct pcilib_nwl_engine_description_s pcilib_nwl_engine_description_t; +#include <stdio.h> +#include "../pcilib.h" -#define NWL_DMA_IRQ_SOURCE 0 +#define PCILIB_NWL_MODIFICATION_IPECAMERA 0x100 -#define NWL_XAUI_ENGINE 0 -#define NWL_XRAWDATA_ENGINE 1 -#define NWL_MAX_PACKET_SIZE 4096 //16384 -//#define NWL_GENERATE_DMA_IRQ +pcilib_dma_context_t *dma_nwl_init(pcilib_t *ctx, pcilib_dma_modification_t type, void *arg); +void  dma_nwl_free(pcilib_dma_context_t *vctx); -#define PCILIB_NWL_ALIGNMENT 			64  // in bytes -#define PCILIB_NWL_DMA_DESCRIPTOR_SIZE		64  // in bytes -#define PCILIB_NWL_DMA_PAGES			256 // 1024 +int dma_nwl_get_status(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, pcilib_dma_engine_status_t *status, size_t n_buffers, pcilib_dma_buffer_status_t *buffers); -//#define DEBUG_HARDWARE -//#define DEBUG_NWL +int dma_nwl_enable_irq(pcilib_dma_context_t *vctx, pcilib_irq_type_t type, pcilib_dma_flags_t flags); +int dma_nwl_disable_irq(pcilib_dma_context_t *vctx, pcilib_dma_flags_t flags); +int dma_nwl_acknowledge_irq(pcilib_dma_context_t *ctx, pcilib_irq_type_t irq_type, pcilib_irq_source_t irq_source); -#include "nwl_dma.h" -#include "nwl_irq.h" -#include "nwl_register.h" -#include "nwl_engine.h" -#include "nwl_loopback.h" +int dma_nwl_start(pcilib_dma_context_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags); +int dma_nwl_stop(pcilib_dma_context_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags); -#define nwl_read_register(var, ctx, base, reg) pcilib_datacpy(&var, base + reg, 4, 1, ctx->dma_bank->raw_endianess) -#define nwl_write_register(var, ctx, base, reg) pcilib_datacpy(base + reg, &var, 4, 1, ctx->dma_bank->raw_endianess) +int dma_nwl_write_fragment(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, pcilib_dma_flags_t flags, pcilib_timeout_t timeout, void *data, size_t *written); +int dma_nwl_stream_read(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, pcilib_dma_flags_t flags, pcilib_timeout_t timeout, pcilib_dma_callback_t cb, void *cbattr); +double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dma, uintptr_t addr, size_t size, size_t iterations, pcilib_dma_direction_t direction); -struct pcilib_nwl_engine_description_s { -    pcilib_dma_engine_description_t desc; -    char *base_addr; -     -    size_t ring_size, page_size; -    size_t head, tail; -    pcilib_kmem_handle_t *ring; -    pcilib_kmem_handle_t *pages; -     -    int started;			/**< indicates that DMA buffers are initialized and reading is allowed */ -    int writting;			/**< indicates that we are in middle of writting packet */ -    int reused;				/**< indicates that DMA was found intialized, buffers were reused, and no additional initialization is needed */ -    int preserve;			/**< indicates that DMA should not be stopped during clean-up */ -}; - - -struct nwl_dma_s { -    struct pcilib_dma_context_s dmactx; -     -    pcilib_t *pcilib; -     -    pcilib_dma_modification_t type; -     -    pcilib_register_bank_description_t *dma_bank; -    char *base_addr; - -    pcilib_irq_type_t irq_enabled;	/**< indicates that IRQs are enabled */ -    pcilib_irq_type_t irq_preserve;	/**< indicates that IRQs should not be disabled during clean-up */ -    int started;			/**< indicates that DMA subsystem is initialized and DMA engine can start */ -    int irq_started;			/**< indicates that IRQ subsystem is initialized (detecting which types should be preserverd) */     -    int loopback_started;		/**< indicates that benchmarking subsystem is initialized */ -    pcilib_dma_engine_t n_engines; -    pcilib_nwl_engine_description_t engines[PCILIB_MAX_DMA_ENGINES + 1]; +#ifdef _PCILIB_DMA_NWL_C +pcilib_dma_api_description_t nwl_dma_api = { +    "nwl_dma", +    dma_nwl_init, +    dma_nwl_free, +    dma_nwl_get_status, +    dma_nwl_enable_irq, +    dma_nwl_disable_irq, +    dma_nwl_acknowledge_irq, +    dma_nwl_start, +    dma_nwl_stop, +    dma_nwl_write_fragment, +    dma_nwl_stream_read, +    dma_nwl_benchmark  }; +#else +extern pcilib_dma_api_description_t nwl_dma_api; +#endif -#endif /* _PCILIB_NWL_H */ +#endif /* _PCILIB_DMA_NWL_H */ diff --git a/dma/nwl_dma.h b/dma/nwl_dma.h deleted file mode 100644 index cc9e379..0000000 --- a/dma/nwl_dma.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef _PCILIB_DMA_NWL_H -#define _PCILIB_DMA_NWL_H - -#include <stdio.h> -#include "../pcilib.h" - -#define PCILIB_NWL_MODIFICATION_IPECAMERA 0x100 - -pcilib_dma_context_t *dma_nwl_init(pcilib_t *ctx, pcilib_dma_modification_t type, void *arg); -void  dma_nwl_free(pcilib_dma_context_t *vctx); - -int dma_nwl_get_status(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, pcilib_dma_engine_status_t *status, size_t n_buffers, pcilib_dma_buffer_status_t *buffers); - -int dma_nwl_enable_irq(pcilib_dma_context_t *vctx, pcilib_irq_type_t type, pcilib_dma_flags_t flags); -int dma_nwl_disable_irq(pcilib_dma_context_t *vctx, pcilib_dma_flags_t flags); -int dma_nwl_acknowledge_irq(pcilib_dma_context_t *ctx, pcilib_irq_type_t irq_type, pcilib_irq_source_t irq_source); - -int dma_nwl_start(pcilib_dma_context_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags); -int dma_nwl_stop(pcilib_dma_context_t *ctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags); - -int dma_nwl_write_fragment(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, pcilib_dma_flags_t flags, pcilib_timeout_t timeout, void *data, size_t *written); -int dma_nwl_stream_read(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, pcilib_dma_flags_t flags, pcilib_timeout_t timeout, pcilib_dma_callback_t cb, void *cbattr); -double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dma, uintptr_t addr, size_t size, size_t iterations, pcilib_dma_direction_t direction); - - -#ifdef _PCILIB_DMA_NWL_C -pcilib_dma_api_description_t nwl_dma_api = { -    dma_nwl_init, -    dma_nwl_free, -    dma_nwl_get_status, -    dma_nwl_enable_irq, -    dma_nwl_disable_irq, -    dma_nwl_acknowledge_irq, -    dma_nwl_start, -    dma_nwl_stop, -    dma_nwl_write_fragment, -    dma_nwl_stream_read, -    dma_nwl_benchmark -}; -#else -extern pcilib_dma_api_description_t nwl_dma_api; -#endif - - -#endif /* _PCILIB_DMA_NWL_H */ diff --git a/dma/nwl_engine.c b/dma/nwl_engine.c index e4c102d..f541d0b 100644 --- a/dma/nwl_engine.c +++ b/dma/nwl_engine.c @@ -10,7 +10,7 @@  #include "pcilib.h"  #include "error.h"  #include "tools.h" -#include "nwl.h" +#include "nwl_private.h"  #include "nwl_defines.h" diff --git a/dma/nwl_engine_buffers.h b/dma/nwl_engine_buffers.h index 826a4d5..c45c3ca 100644 --- a/dma/nwl_engine_buffers.h +++ b/dma/nwl_engine_buffers.h @@ -94,10 +94,10 @@ static int dma_nwl_allocate_engine_buffers(nwl_dma_t *ctx, pcilib_nwl_engine_des      pcilib_kmem_handle_t *ring = pcilib_alloc_kernel_memory(ctx->pcilib, PCILIB_KMEM_TYPE_CONSISTENT, 1, PCILIB_NWL_DMA_PAGES * PCILIB_NWL_DMA_DESCRIPTOR_SIZE, PCILIB_NWL_ALIGNMENT, PCILIB_KMEM_USE(PCILIB_KMEM_USE_DMA_RING, sub_use), flags);      pcilib_kmem_handle_t *pages = pcilib_alloc_kernel_memory(ctx->pcilib, type, PCILIB_NWL_DMA_PAGES, 0, 0, PCILIB_KMEM_USE(PCILIB_KMEM_USE_DMA_PAGES, sub_use), flags); -    if (err) { +    if (!ring||!pages) {  	if (pages) pcilib_free_kernel_memory(ctx->pcilib, pages, 0); -	if (ring) pcilib_free_kernel_memory(ctx->pcilib, ring, 0);     -	return err; +	if (ring) pcilib_free_kernel_memory(ctx->pcilib, ring, 0); +	return PCILIB_ERROR_MEMORY;      }      reuse_ring = pcilib_kmem_is_reused(ctx->pcilib, ring); diff --git a/dma/nwl_irq.c b/dma/nwl_irq.c index ee5f520..e71c76a 100644 --- a/dma/nwl_irq.c +++ b/dma/nwl_irq.c @@ -10,7 +10,7 @@  #include "error.h"  #include "tools.h" -#include "nwl.h" +#include "nwl_private.h"  #include "nwl_defines.h"  int dma_nwl_init_irq(nwl_dma_t *ctx, uint32_t val) { diff --git a/dma/nwl_loopback.c b/dma/nwl_loopback.c index ce0844f..53e0d48 100644 --- a/dma/nwl_loopback.c +++ b/dma/nwl_loopback.c @@ -9,7 +9,7 @@  #include "pcilib.h"  #include "error.h"  #include "tools.h" -#include "nwl.h" +#include "nwl_private.h"  #include "nwl_defines.h" diff --git a/dma/nwl_private.h b/dma/nwl_private.h new file mode 100644 index 0000000..756e6ca --- /dev/null +++ b/dma/nwl_private.h @@ -0,0 +1,67 @@ +#ifndef _PCILIB_DMA_NWL_PRIVATE_H +#define _PCILIB_DMA_NWL_PRIVATE_H + +typedef struct nwl_dma_s nwl_dma_t; +typedef struct pcilib_nwl_engine_description_s pcilib_nwl_engine_description_t; + +#define NWL_DMA_IRQ_SOURCE 0 + +#define NWL_XAUI_ENGINE 0 +#define NWL_XRAWDATA_ENGINE 1 +#define NWL_MAX_PACKET_SIZE 4096 //16384 +//#define NWL_GENERATE_DMA_IRQ + +#define PCILIB_NWL_ALIGNMENT 			64  // in bytes +#define PCILIB_NWL_DMA_DESCRIPTOR_SIZE		64  // in bytes +#define PCILIB_NWL_DMA_PAGES			256 // 1024 + +//#define DEBUG_HARDWARE +//#define DEBUG_NWL + +#include "nwl.h" +#include "nwl_irq.h" +#include "nwl_register.h" +#include "nwl_engine.h" +#include "nwl_loopback.h" + +#define nwl_read_register(var, ctx, base, reg) pcilib_datacpy(&var, base + reg, 4, 1, ctx->dma_bank->raw_endianess) +#define nwl_write_register(var, ctx, base, reg) pcilib_datacpy(base + reg, &var, 4, 1, ctx->dma_bank->raw_endianess) + +struct pcilib_nwl_engine_description_s { +    pcilib_dma_engine_description_t desc; +    char *base_addr; +     +    size_t ring_size, page_size; +    size_t head, tail; +    pcilib_kmem_handle_t *ring; +    pcilib_kmem_handle_t *pages; +     +    int started;			/**< indicates that DMA buffers are initialized and reading is allowed */ +    int writting;			/**< indicates that we are in middle of writting packet */ +    int reused;				/**< indicates that DMA was found intialized, buffers were reused, and no additional initialization is needed */ +    int preserve;			/**< indicates that DMA should not be stopped during clean-up */ +}; + + +struct nwl_dma_s { +    struct pcilib_dma_context_s dmactx; +     +    pcilib_t *pcilib; +     +    pcilib_dma_modification_t type; +     +    pcilib_register_bank_description_t *dma_bank; +    char *base_addr; + +    pcilib_irq_type_t irq_enabled;	/**< indicates that IRQs are enabled */ +    pcilib_irq_type_t irq_preserve;	/**< indicates that IRQs should not be disabled during clean-up */ +    int started;			/**< indicates that DMA subsystem is initialized and DMA engine can start */ +    int irq_started;			/**< indicates that IRQ subsystem is initialized (detecting which types should be preserverd) */     +    int loopback_started;		/**< indicates that benchmarking subsystem is initialized */ + +    pcilib_dma_engine_t n_engines; +    pcilib_nwl_engine_description_t engines[PCILIB_MAX_DMA_ENGINES + 1]; +}; + + +#endif /* _PCILIB_DMA_NWL_PRIVATE_H */ diff --git a/dma/nwl_register.c b/dma/nwl_register.c index 5f94e4d..6a3771a 100644 --- a/dma/nwl_register.c +++ b/dma/nwl_register.c @@ -12,7 +12,7 @@  #include "error.h"  #include "tools.h" -#include "nwl.h" +#include "nwl_private.h"  #include "nwl_register.h"  int nwl_add_registers(nwl_dma_t *ctx) {  | 
