diff options
-rw-r--r-- | dma.c | 12 | ||||
-rw-r--r-- | dma.h | 6 | ||||
-rw-r--r-- | dma/nwl.c | 153 | ||||
-rw-r--r-- | dma/nwl.h | 2 | ||||
-rw-r--r-- | dma/nwl_dma.h | 4 | ||||
-rw-r--r-- | dma/nwl_loopback.c | 11 | ||||
-rw-r--r-- | dma/nwl_register.h | 8 | ||||
-rw-r--r-- | event.h | 3 | ||||
-rw-r--r-- | ipecamera/image.c | 15 | ||||
-rw-r--r-- | ipecamera/image.h | 1 | ||||
-rw-r--r-- | ipecamera/model.h | 3 | ||||
-rw-r--r-- | pci.h | 1 |
12 files changed, 123 insertions, 96 deletions
@@ -20,12 +20,14 @@ const pcilib_dma_info_t *pcilib_get_dma_info(pcilib_t *ctx) { if (!ctx->dma_ctx) { - pcilib_model_t model = pcilib_get_model(ctx); - pcilib_dma_api_description_t *api = pcilib_model[model].dma_api; - - if ((api)&&(api->init)) { + pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); + + if ((ctx->event_ctx)&&(model_info->event_api->init_dma)) { + pcilib_map_register_space(ctx); + ctx->dma_ctx = model_info->event_api->init_dma(ctx->event_ctx); + } else if ((model_info->dma_api)&&(model_info->dma_api->init)) { pcilib_map_register_space(ctx); - ctx->dma_ctx = api->init(ctx); + ctx->dma_ctx = model_info->dma_api->init(ctx, PCILIB_DMA_MODIFICATION_DEFAULT, NULL); } if (!ctx->dma_ctx) return NULL; @@ -2,9 +2,13 @@ #define _PCILIB_DMA_H #define PCILIB_DMA_BUFFER_INVALID ((size_t)-1) +#define PCILIB_DMA_MODIFICATION_DEFAULT 0 /**< first 0x100 are reserved */ + +typedef uint32_t pcilib_dma_modification_t; + struct pcilib_dma_api_description_s { - pcilib_dma_context_t *(*init)(pcilib_t *ctx); + pcilib_dma_context_t *(*init)(pcilib_t *ctx, pcilib_dma_modification_t type, void *arg); void (*free)(pcilib_dma_context_t *ctx); int (*enable_irq)(pcilib_dma_context_t *ctx, pcilib_irq_type_t irq_type, pcilib_dma_flags_t flags); @@ -1,5 +1,6 @@ #define _PCILIB_DMA_NWL_C #define _BSD_SOURCE +//#define DEBUG_HARDWARE #include <stdio.h> #include <stdlib.h> @@ -74,7 +75,7 @@ int dma_nwl_stop(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, pcilib_dma } -pcilib_dma_context_t *dma_nwl_init(pcilib_t *pcilib) { +pcilib_dma_context_t *dma_nwl_init(pcilib_t *pcilib, pcilib_dma_modification_t type, void *arg) { int i; int err; uint32_t val; @@ -86,6 +87,7 @@ pcilib_dma_context_t *dma_nwl_init(pcilib_t *pcilib) { if (ctx) { memset(ctx, 0, sizeof(nwl_dma_t)); ctx->pcilib = pcilib; + ctx->type = type; pcilib_register_bank_t dma_bank = pcilib_find_bank_by_addr(pcilib, PCILIB_REGISTER_BANK_DMA); if (dma_bank == PCILIB_REGISTER_BANK_INVALID) { @@ -129,7 +131,7 @@ void dma_nwl_free(pcilib_dma_context_t *vctx) { nwl_dma_t *ctx = (nwl_dma_t*)vctx; if (ctx) { - dma_nwl_stop_loopback(ctx); + if (ctx->type == PCILIB_DMA_MODIFICATION_DEFAULT) dma_nwl_stop_loopback(ctx); dma_nwl_free_irq(ctx); dma_nwl_stop(ctx, PCILIB_DMA_ENGINE_ALL, PCILIB_DMA_FLAGS_DEFAULT); @@ -164,14 +166,19 @@ double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dm // Not supported if (direction == PCILIB_DMA_TO_DEVICE) return -1.; + else if ((direction == PCILIB_DMA_FROM_DEVICE)&&(ctx->type != PCILIB_DMA_MODIFICATION_DEFAULT)) return -1.; // Stop Generators and drain old data - dma_nwl_stop_loopback(ctx); + if (ctx->type == PCILIB_DMA_MODIFICATION_DEFAULT) dma_nwl_stop_loopback(ctx); // dma_nwl_stop_engine(ctx, readid); // DS: replace with something better __sync_synchronize(); - pcilib_skip_dma(ctx->pcilib, readid); + err = pcilib_skip_dma(ctx->pcilib, readid); + if (err) { + pcilib_error("Can't start benchmark, devices continuously writes unexpected data using DMA engine"); + return err; + } #ifdef NWL_GENERATE_DMA_IRQ dma_nwl_enable_engine_irq(ctx, readid); @@ -179,23 +186,9 @@ double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dm #endif /* NWL_GENERATE_DMA_IRQ */ - dma_nwl_start_loopback(ctx, direction, size * sizeof(uint32_t)); - -/* - printf("Packet size: %li\n", size * sizeof(uint32_t)); - pcilib_read_register(ctx->pcilib, NULL, "dma1w_counter", ®val); - printf("Count write: %lx\n", regval); - - nwl_read_register(val, ctx, read_base, REG_DMA_ENG_CTRL_STATUS); - printf("Read DMA control: %lx\n", val); - nwl_read_register(val, ctx, write_base, REG_DMA_ENG_CTRL_STATUS); - printf("Write DMA control: %lx\n", val); - - nwl_read_register(val, ctx, write_base, REG_DMA_ENG_NEXT_BD); - printf("Pointer1: %lx\n", val); - nwl_read_register(val, ctx, write_base, REG_SW_NEXT_BD); - printf("Pointer2: %lx\n", val); -*/ + if (ctx->type == PCILIB_DMA_MODIFICATION_DEFAULT) { + dma_nwl_start_loopback(ctx, direction, size * sizeof(uint32_t)); + } // Allocate memory and prepare data buf = malloc(size * sizeof(uint32_t)); @@ -208,12 +201,22 @@ double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dm memset(cmp, 0x13, size * sizeof(uint32_t)); + +#ifdef DEBUG_HARDWARE + if (ctx->type == PCILIB_NWL_MODIFICATION_IPECAMERA) { + pcilib_write_register(ctx->pcilib, NULL, "control", 0x1e5); + usleep(100000); + pcilib_write_register(ctx->pcilib, NULL, "control", 0x1e1); + } +#endif /* DEBUG_HARDWARE */ + // Benchmark for (i = 0; i < iterations; i++) { -// puts("===================================="); - pcilib_write_register(ctx->pcilib, NULL, "control", 0x1e1); -// pcilib_read_register(ctx->pcilib, NULL, "control", ®val); -// printf("Control: %lx\n", regval); +#ifdef DEBUG_HARDWARE + if (ctx->type == PCILIB_NWL_MODIFICATION_IPECAMERA) { + pcilib_write_register(ctx->pcilib, NULL, "control", 0x1e1); + } +#endif /* DEBUG_HARDWARE */ gettimeofday(&start, NULL); if (direction&PCILIB_DMA_TO_DEVICE) { @@ -225,57 +228,21 @@ double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dm break; } } -/* - printf("RegRead: %i\n",pcilib_read_register(ctx->pcilib, NULL, "dma1w_counter", ®val)); - printf("Count write (%i of %i): %lx\n", i, iterations, regval); - printf("RegRead: %i\n",pcilib_read_register(ctx->pcilib, NULL, "dma1r_counter", ®val)); - printf("Count read (%i of %i): %lx\n", i, iterations, regval); - - - nwl_read_register(val, ctx, read_base, REG_DMA_ENG_COMP_BYTES); - printf("Compl Bytes (read): %lx\n", val); - - nwl_read_register(val, ctx, write_base, REG_DMA_ENG_COMP_BYTES); - printf("Compl Bytes (write): %lx\n", val); - - nwl_read_register(val, ctx, read_base, REG_DMA_ENG_CTRL_STATUS); - printf("Read DMA control (after write): %lx\n", val); -*/ -/* - nwl_read_register(val, ctx, read_base, REG_DMA_ENG_CTRL_STATUS); - printf("Read DMA control (after write): %lx\n", val); - nwl_read_register(val, ctx, write_base, REG_DMA_ENG_CTRL_STATUS); - printf("Write DMA control (after write): %lx\n", val); -*/ - pcilib_write_register(ctx->pcilib, NULL, "control", 0x3e1); -// pcilib_read_register(ctx->pcilib, NULL, "control", ®val); -// printf("Control: %lx\n", regval); +#ifdef DEBUG_HARDWARE + if (ctx->type == PCILIB_NWL_MODIFICATION_IPECAMERA) { + //usleep(1000000); + pcilib_write_register(ctx->pcilib, NULL, "control", 0x3e1); + } memset(buf, 0, size * sizeof(uint32_t)); +#endif /* DEBUG_HARDWARE */ err = pcilib_read_dma(ctx->pcilib, readid, addr, size * sizeof(uint32_t), buf, &bytes); gettimeofday(&cur, NULL); us += ((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec)); if ((err)||(bytes != size * sizeof(uint32_t))) { -/* - nwl_read_register(val, ctx, read_base, REG_DMA_ENG_CTRL_STATUS); - printf("Read DMA control: %lx\n", val); - nwl_read_register(val, ctx, write_base, REG_DMA_ENG_CTRL_STATUS); - printf("Write DMA control: %lx\n", val); - nwl_read_register(val, ctx, write_base, REG_DMA_ENG_NEXT_BD); - printf("After Pointer wr1: %lx\n", val); - nwl_read_register(val, ctx, write_base, REG_SW_NEXT_BD); - printf("After Pointer wr2: %lx\n", val); - pcilib_read_register(ctx->pcilib, NULL, "end_address", ®val); - printf("End address: %lx\n", regval); - - nwl_read_register(val, ctx, read_base, REG_DMA_ENG_NEXT_BD); - printf("After Pointer read1: %lx\n", val); - nwl_read_register(val, ctx, read_base, REG_SW_NEXT_BD); - printf("After Pointer read2: %lx\n", val); -*/ error = "Read failed"; break; } @@ -287,32 +254,52 @@ double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dm break; } } - + +#ifdef DEBUG_HARDWARE + puts("===================================="); + + err = pcilib_read_register(ctx->pcilib, NULL, "reg9050", ®val); + printf("Status1: %i 0x%lx\n", err, regval); + err = pcilib_read_register(ctx->pcilib, NULL, "reg9080", ®val); + printf("Start address: %i 0x%lx\n", err, regval); + err = pcilib_read_register(ctx->pcilib, NULL, "reg9090", ®val); + printf("End address: %i 0x%lx\n", err, regval); + err = pcilib_read_register(ctx->pcilib, NULL, "reg9100", ®val); + printf("Status2: %i 0x%lx\n", err, regval); + err = pcilib_read_register(ctx->pcilib, NULL, "reg9110", ®val); + printf("Status3: %i 0x%lx\n", err, regval); + err = pcilib_read_register(ctx->pcilib, NULL, "reg9160", ®val); + printf("Add_rd_ddr: %i 0x%lx\n", err, regval); +#endif /* DEBUG_HARDWARE */ + } - + +#ifdef DEBUG_HARDWARE + puts("------------------------------------------------"); + err = pcilib_read_register(ctx->pcilib, NULL, "reg9050", ®val); + printf("Status1: %i 0x%lx\n", err, regval); + err = pcilib_read_register(ctx->pcilib, NULL, "reg9080", ®val); + printf("Start address: %i 0x%lx\n", err, regval); + err = pcilib_read_register(ctx->pcilib, NULL, "reg9090", ®val); + printf("End address: %i 0x%lx\n", err, regval); + err = pcilib_read_register(ctx->pcilib, NULL, "reg9100", ®val); + printf("Status2: %i 0x%lx\n", err, regval); + err = pcilib_read_register(ctx->pcilib, NULL, "reg9110", ®val); + printf("Status3: %i 0x%lx\n", err, regval); + err = pcilib_read_register(ctx->pcilib, NULL, "reg9160", ®val); + printf("Add_rd_ddr: %i 0x%lx\n", err, regval); +#endif /* DEBUG_HARDWARE */ + if (error) { pcilib_warning("%s at iteration %i, error: %i, bytes: %zu", error, i, err, bytes); } -/* - puts("Finished..."); - nwl_read_register(val, ctx, read_base, REG_DMA_ENG_NEXT_BD); - printf("After Pointer read1: %lx\n", val); - nwl_read_register(val, ctx, read_base, REG_SW_NEXT_BD); - printf("After Pointer read2: %lx\n", val); - - nwl_read_register(val, ctx, write_base, REG_DMA_ENG_NEXT_BD); - printf("After Pointer wr1: %lx\n", val); - nwl_read_register(val, ctx, write_base, REG_SW_NEXT_BD); - printf("After Pointer wr2: %lx\n", val); -*/ - #ifdef NWL_GENERATE_DMA_IRQ dma_nwl_disable_engine_irq(ctx, writeid); dma_nwl_disable_engine_irq(ctx, readid); #endif /* NWL_GENERATE_DMA_IRQ */ - dma_nwl_stop_loopback(ctx); + if (ctx->type == PCILIB_DMA_MODIFICATION_DEFAULT) dma_nwl_stop_loopback(ctx); __sync_synchronize(); @@ -42,6 +42,8 @@ struct pcilib_nwl_engine_description_s { struct nwl_dma_s { pcilib_t *pcilib; + pcilib_dma_modification_t type; + pcilib_register_bank_description_t *dma_bank; char *base_addr; diff --git a/dma/nwl_dma.h b/dma/nwl_dma.h index 883dc29..bdb3df0 100644 --- a/dma/nwl_dma.h +++ b/dma/nwl_dma.h @@ -4,7 +4,9 @@ #include <stdio.h> #include "pcilib.h" -pcilib_dma_context_t *dma_nwl_init(pcilib_t *ctx); +#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_enable_irq(pcilib_dma_context_t *vctx, pcilib_irq_type_t type, pcilib_dma_flags_t flags); diff --git a/dma/nwl_loopback.c b/dma/nwl_loopback.c index 9c74b14..a31bd08 100644 --- a/dma/nwl_loopback.c +++ b/dma/nwl_loopback.c @@ -43,11 +43,12 @@ int dma_nwl_start_loopback(nwl_dma_t *ctx, pcilib_dma_direction_t direction, si int dma_nwl_stop_loopback(nwl_dma_t *ctx) { uint32_t val = 0; - if (ctx->loopback_started) { - nwl_write_register(val, ctx, ctx->base_addr, TX_CONFIG_ADDRESS); - nwl_write_register(val, ctx, ctx->base_addr, RX_CONFIG_ADDRESS); - ctx->loopback_started = 0; - } + /* Stop in any case, otherwise we can have problems in benchmark due to + engine initialized in previous run, and benchmark is only actual usage. + Otherwise, we should detect current loopback status during initialization */ + nwl_write_register(val, ctx, ctx->base_addr, TX_CONFIG_ADDRESS); + nwl_write_register(val, ctx, ctx->base_addr, RX_CONFIG_ADDRESS); + ctx->loopback_started = 0; return 0; } diff --git a/dma/nwl_register.h b/dma/nwl_register.h index bffc1bf..df479e9 100644 --- a/dma/nwl_register.h +++ b/dma/nwl_register.h @@ -86,6 +86,14 @@ static pcilib_register_description_t nwl_xrawdata_registers[] = { {0x9108, 0, 1, 0, 0x00000003, PCILIB_REGISTER_RW, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "xrawdata_enable_checker", ""}, {0x9108, 1, 1, 0, 0x00000003, PCILIB_REGISTER_RW, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "xrawdata_enable_loopback", ""}, {0x910C, 0, 1, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "xrawdata_data_mistmatch", ""}, +#ifdef DEBUG_HARDWARE + {0x9050, 0, 32, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "reg9050", ""}, + {0x9080, 0, 32, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "reg9080", ""}, + {0x9090, 0, 32, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "reg9090", ""}, + {0x9100, 0, 32, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "reg9100", ""}, + {0x9110, 0, 32, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "reg9110", ""}, + {0x9160, 0, 32, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "reg9160", ""}, +#endif /* DEBUG_HARDWARE */ {0, 0, 0, 0, 0x00000000, 0, 0, 0, NULL, NULL} }; @@ -16,6 +16,9 @@ struct pcilib_event_api_description_s { pcilib_event_id_t (*next_event)(pcilib_context_t *ctx, pcilib_event_t event_mask, const struct timespec *timeout); void* (*get_data)(pcilib_context_t *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t arg_size, void *arg, size_t *size); int (*return_data)(pcilib_context_t *ctx, pcilib_event_id_t event_id); + + pcilib_dma_context_t *(*init_dma)(pcilib_context_t *ctx); + }; diff --git a/ipecamera/image.c b/ipecamera/image.c index bf5faf9..3d1056d 100644 --- a/ipecamera/image.c +++ b/ipecamera/image.c @@ -16,6 +16,8 @@ #include "model.h" #include "image.h" +#include "dma/nwl_dma.h" + #define IPECAMERA_SLEEP_TIME 250000 #define IPECAMERA_MAX_LINES 1088 #define IPECAMERA_DEFAULT_BUFFER_SIZE 10 @@ -171,6 +173,19 @@ void ipecamera_free(pcilib_context_t *vctx) { } } +pcilib_dma_context_t *ipecamera_init_dma(pcilib_context_t *vctx) { + ipecamera_t *ctx = (ipecamera_t*)vctx; + + pcilib_model_description_t *model_info = pcilib_get_model_description(ctx->pcilib); + if ((!model_info->dma_api)||(!model_info->dma_api->init)) { + pcilib_error("The DMA engine is not configured in model"); + return NULL; + } + + return model_info->dma_api->init(ctx->pcilib, PCILIB_DMA_MODIFICATION_DEFAULT, NULL); +} + + int ipecamera_set_buffer_size(ipecamera_t *ctx, int size) { if (ctx->started) { pcilib_error("Can't change buffer size while grabbing"); diff --git a/ipecamera/image.h b/ipecamera/image.h index 6863d09..4bac673 100644 --- a/ipecamera/image.h +++ b/ipecamera/image.h @@ -18,6 +18,7 @@ pcilib_event_id_t ipecamera_next_event(pcilib_context_t *ctx, pcilib_event_t eve void* ipecamera_get(pcilib_context_t *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t arg_size, void *arg, size_t *size); int ipecamera_return(pcilib_context_t *ctx, pcilib_event_id_t event_id); +pcilib_dma_context_t *ipecamera_init_dma(pcilib_context_t *ctx); #endif /* _IPECAMERA_IMAGE_H */ diff --git a/ipecamera/model.h b/ipecamera/model.h index da0ac12..a460dde 100644 --- a/ipecamera/model.h +++ b/ipecamera/model.h @@ -109,7 +109,8 @@ pcilib_event_api_description_t ipecamera_image_api = { ipecamera_next_event, ipecamera_get, - ipecamera_return + ipecamera_return, + ipecamera_init_dma }; #else extern pcilib_event_api_description_t ipecamera_image_api; @@ -2,6 +2,7 @@ #define _PCITOOL_PCI_H #define PCILIB_DMA_TIMEOUT 10000 /**< us */ +#define PCILIB_DMA_SKIP_TIMEOUT 1000000 /**< us */ #define PCILIB_REGISTER_TIMEOUT 10000 /**< us */ #include "driver/pciDriver.h" |