diff options
-rw-r--r-- | ToDo | 1 | ||||
-rw-r--r-- | cli.c | 90 | ||||
-rw-r--r-- | common.mk | 3 | ||||
-rw-r--r-- | default.c | 12 | ||||
-rw-r--r-- | default.h | 4 | ||||
-rw-r--r-- | dma.c | 18 | ||||
-rw-r--r-- | dma/nwl.c | 75 | ||||
-rw-r--r-- | dma/nwl_register.h | 94 | ||||
-rw-r--r-- | event.c | 36 | ||||
-rw-r--r-- | ipecamera/model.c | 13 | ||||
-rw-r--r-- | ipecamera/model.h | 126 | ||||
-rw-r--r-- | pci.c | 21 | ||||
-rw-r--r-- | pci.h | 5 | ||||
-rw-r--r-- | pcilib.h | 14 | ||||
-rw-r--r-- | register.c | 151 | ||||
-rw-r--r-- | register.h | 7 |
16 files changed, 468 insertions, 202 deletions
@@ -1,4 +1,3 @@ -1. Support registers with bit shifts 2. Hint for register value representation in the bank (hex, decimal) 3. Implement software registers 4. Support FIFO reads/writes from/to registers @@ -172,7 +172,7 @@ void Error(const char *format, ...) { void Silence(const char *format, ...) { } -void List(pcilib_t *handle, pcilib_model_t model, const char *bank) { +void List(pcilib_t *handle, pcilib_model_description_t *model_info, const char *bank, int details) { int i; pcilib_register_bank_description_t *banks; pcilib_register_description_t *registers; @@ -180,7 +180,7 @@ void List(pcilib_t *handle, pcilib_model_t model, const char *bank) { const pcilib_board_info_t *board_info = pcilib_get_board_info(handle); const pcilib_dma_info_t *dma_info = pcilib_get_dma_info(handle); - + for (i = 0; i < PCILIB_MAX_BANKS; i++) { if (board_info->bar_length[i] > 0) { printf(" BAR %d - ", i); @@ -232,7 +232,7 @@ void List(pcilib_t *handle, pcilib_model_t model, const char *bank) { } if ((bank)&&(bank != (char*)-1)) banks = NULL; - else banks = pcilib_model[model].banks; + else banks = model_info->banks; if (banks) { printf("Banks: \n"); @@ -247,13 +247,13 @@ void List(pcilib_t *handle, pcilib_model_t model, const char *bank) { } if (bank == (char*)-1) registers = NULL; - else registers = pcilib_model[model].registers; + else registers = model_info->registers; if (registers) { pcilib_register_bank_addr_t bank_addr; if (bank) { pcilib_register_bank_t bank_id = pcilib_find_bank(handle, bank); - pcilib_register_bank_description_t *b = pcilib_model[model].banks + bank_id; + pcilib_register_bank_description_t *b = model_info->banks + bank_id; bank_addr = b->addr; if (b->description) printf("%s:\n", b->description); @@ -266,6 +266,17 @@ void List(pcilib_t *handle, pcilib_model_t model, const char *bank) { const char *mode; if ((bank)&&(registers[i].bank != bank_addr)) continue; + if (registers[i].type == PCILIB_REGISTER_BITS) { + if (!details) continue; + + if (registers[i].bits > 1) { + printf(" [%2u:%2u] - %s\n", registers[i].offset, registers[i].offset + registers[i].bits, registers[i].name); + } else { + printf(" [ %2u] - %s\n", registers[i].offset, registers[i].name); + } + + continue; + } if (registers[i].mode == PCILIB_REGISTER_RW) mode = "RW"; else if (registers[i].mode == PCILIB_REGISTER_R) mode = "R "; @@ -273,7 +284,7 @@ void List(pcilib_t *handle, pcilib_model_t model, const char *bank) { else mode = " "; printf(" 0x%02x (%2i %s) %s", registers[i].addr, registers[i].bits, mode, registers[i].name); - if ((registers[i].description)&&(registers[i].description[0])) { + if ((details > 0)&&(registers[i].description)&&(registers[i].description[0])) { printf(": %s", registers[i].description); } printf("\n"); @@ -283,7 +294,7 @@ void List(pcilib_t *handle, pcilib_model_t model, const char *bank) { } if (bank == (char*)-1) events = NULL; - else events = pcilib_model[model].events; + else events = model_info->events; if (events) { printf("Events: \n"); @@ -297,11 +308,11 @@ void List(pcilib_t *handle, pcilib_model_t model, const char *bank) { } } -void Info(pcilib_t *handle, pcilib_model_t model) { +void Info(pcilib_t *handle, pcilib_model_description_t *model_info) { const pcilib_board_info_t *board_info = pcilib_get_board_info(handle); printf("Vendor: %x, Device: %x, Interrupt Pin: %i, Interrupt Line: %i\n", board_info->vendor_id, board_info->device_id, board_info->interrupt_pin, board_info->interrupt_line); - List(handle, model, (char*)-1); + List(handle, model_info, (char*)-1, 0); } @@ -567,21 +578,20 @@ int ReadData(pcilib_t *handle, ACCESS_MODE mode, pcilib_dma_engine_addr_t dma, p -int ReadRegister(pcilib_t *handle, pcilib_model_t model, const char *bank, const char *reg) { +int ReadRegister(pcilib_t *handle, pcilib_model_description_t *model_info, const char *bank, const char *reg) { int i; int err; const char *format; pcilib_register_bank_t bank_id; pcilib_register_bank_addr_t bank_addr; - pcilib_register_description_t *registers = pcilib_model[model].registers; pcilib_register_value_t value; if (reg) { pcilib_register_t regid = pcilib_find_register(handle, bank, reg); - bank_id = pcilib_find_bank_by_addr(handle, registers[regid].bank); - format = pcilib_model[model].banks[bank_id].format; + bank_id = pcilib_find_bank_by_addr(handle, model_info->registers[regid].bank); + format = model_info->banks[bank_id].format; if (!format) format = "%lu"; err = pcilib_read_register_by_id(handle, regid, &value); @@ -593,32 +603,34 @@ int ReadRegister(pcilib_t *handle, pcilib_model_t model, const char *bank, const printf("\n"); } } else { - - if (registers) { + // Adding DMA registers + pcilib_get_dma_info(handle); + + if (model_info->registers) { if (bank) { bank_id = pcilib_find_bank(handle, bank); - bank_addr = pcilib_model[model].banks[bank_id].addr; + bank_addr = model_info->banks[bank_id].addr; } printf("Registers:\n"); - for (i = 0; registers[i].bits; i++) { - if ((registers[i].mode & PCILIB_REGISTER_R)&&((!bank)||(registers[i].bank == bank_addr))) { - bank_id = pcilib_find_bank_by_addr(handle, registers[i].bank); - format = pcilib_model[model].banks[bank_id].format; + for (i = 0; model_info->registers[i].bits; i++) { + if ((model_info->registers[i].mode & PCILIB_REGISTER_R)&&((!bank)||(model_info->registers[i].bank == bank_addr))&&(model_info->registers[i].type != PCILIB_REGISTER_BITS)) { + bank_id = pcilib_find_bank_by_addr(handle, model_info->registers[i].bank); + format = model_info->banks[bank_id].format; if (!format) format = "%lu"; err = pcilib_read_register_by_id(handle, i, &value); - if (err) printf(" %s = error reading value", registers[i].name); + if (err) printf(" %s = error reading value", model_info->registers[i].name); else { - printf(" %s = ", registers[i].name); + printf(" %s = ", model_info->registers[i].name); printf(format, value); } printf(" ["); - printf(format, registers[i].defvalue); + printf(format, model_info->registers[i].defvalue); printf("]"); + printf("\n"); } - printf("\n"); } } else { printf("No registers"); @@ -627,11 +639,11 @@ int ReadRegister(pcilib_t *handle, pcilib_model_t model, const char *bank, const } } -int ReadRegisterRange(pcilib_t *handle, pcilib_model_t model, const char *bank, uintptr_t addr, size_t n) { +int ReadRegisterRange(pcilib_t *handle, pcilib_model_description_t *model_info, const char *bank, uintptr_t addr, size_t n) { int err; int i; - pcilib_register_bank_description_t *banks = pcilib_model[model].banks; + pcilib_register_bank_description_t *banks = model_info->banks; pcilib_register_bank_t bank_id = pcilib_find_bank(handle, bank); if (bank_id == PCILIB_REGISTER_BANK_INVALID) { @@ -726,7 +738,7 @@ int WriteData(pcilib_t *handle, ACCESS_MODE mode, pcilib_dma_engine_addr_t dma, free(buf); } -int WriteRegisterRange(pcilib_t *handle, pcilib_model_t model, const char *bank, uintptr_t addr, size_t n, char ** data) { +int WriteRegisterRange(pcilib_t *handle, pcilib_model_description_t *model_info, const char *bank, uintptr_t addr, size_t n, char ** data) { pcilib_register_value_t *buf, *check; int res, i, err; unsigned long value; @@ -750,7 +762,7 @@ int WriteRegisterRange(pcilib_t *handle, pcilib_model_t model, const char *bank, if (memcmp(buf, check, size)) { printf("Write failed: the data written and read differ, the foolowing is read back:\n"); - ReadRegisterRange(handle, model, bank, addr, n); + ReadRegisterRange(handle, model_info, bank, addr, n); exit(-1); } @@ -759,7 +771,7 @@ int WriteRegisterRange(pcilib_t *handle, pcilib_model_t model, const char *bank, } -int WriteRegister(pcilib_t *handle, pcilib_model_t model, const char *bank, const char *reg, char ** data) { +int WriteRegister(pcilib_t *handle, pcilib_model_description_t *model_info, const char *bank, const char *reg, char ** data) { int err; int i; @@ -827,9 +839,11 @@ int main(int argc, char **argv) { long itmp; unsigned char c; + int details = 0; int quiete = 0; pcilib_model_t model = PCILIB_MODEL_DETECT; + pcilib_model_description_t *model_info; MODE mode = MODE_INVALID; const char *type = NULL; ACCESS_MODE amode = ACCESS_BAR; @@ -865,7 +879,8 @@ int main(int argc, char **argv) { mode = MODE_INFO; break; case OPT_LIST: - if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported"); + if (mode == MODE_LIST) details++; + else if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported"); mode = MODE_LIST; break; @@ -966,6 +981,7 @@ int main(int argc, char **argv) { if (handle < 0) Error("Failed to open FPGA device: %s", fpga_device); model = pcilib_get_model(handle); + model_info = pcilib_get_model_description(handle); switch (mode) { case MODE_WRITE: @@ -1027,7 +1043,7 @@ int main(int argc, char **argv) { amode = ACCESS_BAR; } else if ((isxnumber(addr))&&(sscanf(addr, "%lx", &start) == 1)) { // check if the address in the register range - pcilib_register_range_t *ranges = pcilib_model[model].ranges; + pcilib_register_range_t *ranges = model_info->ranges; if (ranges) { for (i = 0; ranges[i].start != ranges[i].end; i++) @@ -1069,10 +1085,10 @@ int main(int argc, char **argv) { switch (mode) { case MODE_INFO: - Info(handle, model); + Info(handle, model_info); break; case MODE_LIST: - List(handle, model, bank); + List(handle, model_info, bank, details); break; case MODE_BENCHMARK: Benchmark(handle, amode, dma, bar, start, size_set?size:0, access); @@ -1085,15 +1101,15 @@ int main(int argc, char **argv) { } break; case MODE_READ_REGISTER: - if ((reg)||(!addr)) ReadRegister(handle, model, bank, reg); - else ReadRegisterRange(handle, model, bank, start, size); + if ((reg)||(!addr)) ReadRegister(handle, model_info, bank, reg); + else ReadRegisterRange(handle, model_info, bank, start, size); break; case MODE_WRITE: WriteData(handle, amode, dma, bar, start, size, access, endianess, data); break; case MODE_WRITE_REGISTER: - if (reg) WriteRegister(handle, model, bank, reg, data); - else WriteRegisterRange(handle, model, bank, start, size, data); + if (reg) WriteRegister(handle, model_info, bank, reg, data); + else WriteRegisterRange(handle, model_info, bank, start, size, data); break; case MODE_RESET: pcilib_reset(handle); @@ -22,6 +22,9 @@ SRCC = $(wildcard *.c) SRC += $(wildcard ipecamera/*.cpp) SRCC += $(wildcard ipecamera/*.c) +SRC += $(wildcard dma/*.cpp) +SRCC += $(wildcard dma/*.c) + # Corresponding object files OBJ = $(addprefix $(OBJDIR)/,$(SRC:.cpp=.o)) OBJ += $(addprefix $(OBJDIR)/,$(SRCC:.c=.o)) @@ -8,30 +8,30 @@ #define default_datacpy(dst, src, access, bank) pcilib_datacpy(dst, src, access, 1, bank->raw_endianess) -int pcilib_default_read(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, uint8_t bits, pcilib_register_value_t *value) { +int pcilib_default_read(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, pcilib_register_value_t *value) { int err; char *ptr; pcilib_register_value_t val = 0; int access = bank->access / 8; - ptr = pcilib_resolve_register_address(ctx, bank->bar, bank->read_addr + addr * access); + ptr = pcilib_resolve_register_address(ctx, bank->bar, bank->read_addr + addr); default_datacpy(&val, ptr, access, bank); -// printf("%lx %lx\n",val, BIT_MASK(bits)); - *value = val&BIT_MASK(bits); +// *value = val&BIT_MASK(bits); + *value = val; return 0; } -int pcilib_default_write(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, uint8_t bits, pcilib_register_value_t value) { +int pcilib_default_write(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, pcilib_register_value_t value) { int err; char *ptr; int access = bank->access / 8; - ptr = pcilib_resolve_register_address(ctx, bank->bar, bank->write_addr + addr * access); + ptr = pcilib_resolve_register_address(ctx, bank->bar, bank->write_addr + addr); default_datacpy(ptr, &value, access, bank); return 0; @@ -3,7 +3,7 @@ #include "pcilib.h" -int pcilib_default_read(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, uint8_t bits, pcilib_register_value_t *value); -int pcilib_default_write(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, uint8_t bits, pcilib_register_value_t value); +int pcilib_default_read(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, pcilib_register_value_t *value); +int pcilib_default_write(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, pcilib_register_value_t value); #endif /* _PCILIB_DEFAULT_H */ @@ -88,12 +88,12 @@ size_t pcilib_stream_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, uintptr_t addr, return 0; } - if (!ctx->model_info->dma_api) { + if (!ctx->model_info.dma_api) { pcilib_error("DMA Engine is not configured in the current model"); return 0; } - if (!ctx->model_info->dma_api->stream) { + if (!ctx->model_info.dma_api->stream) { pcilib_error("The DMA read is not supported by configured DMA engine"); return 0; } @@ -108,7 +108,7 @@ size_t pcilib_stream_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, uintptr_t addr, return 0; } - return ctx->model_info->dma_api->stream(ctx->dma_ctx, dma, addr, size, flags, timeout, cb, cbattr); + return ctx->model_info.dma_api->stream(ctx->dma_ctx, dma, addr, size, flags, timeout, cb, cbattr); } size_t pcilib_read_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, void *buf) { @@ -141,12 +141,12 @@ size_t pcilib_push_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, uintptr_t addr, s return 0; } - if (!ctx->model_info->dma_api) { + if (!ctx->model_info.dma_api) { pcilib_error("DMA Engine is not configured in the current model"); return 0; } - if (!ctx->model_info->dma_api->push) { + if (!ctx->model_info.dma_api->push) { pcilib_error("The DMA write is not supported by configured DMA engine"); return 0; } @@ -161,7 +161,7 @@ size_t pcilib_push_dma(pcilib_t *ctx, pcilib_dma_engine_t dma, uintptr_t addr, s return 0; } - return ctx->model_info->dma_api->push(ctx->dma_ctx, dma, addr, size, flags, timeout, buf); + return ctx->model_info.dma_api->push(ctx->dma_ctx, dma, addr, size, flags, timeout, buf); } @@ -178,12 +178,12 @@ double pcilib_benchmark_dma(pcilib_t *ctx, pcilib_dma_engine_addr_t dma, uintptr return 0; } - if (!ctx->model_info->dma_api) { + if (!ctx->model_info.dma_api) { pcilib_error("DMA Engine is not configured in the current model"); return -1; } - if (!ctx->model_info->dma_api->benchmark) { + if (!ctx->model_info.dma_api->benchmark) { pcilib_error("The DMA benchmark is not supported by configured DMA engine"); return -1; } @@ -193,5 +193,5 @@ double pcilib_benchmark_dma(pcilib_t *ctx, pcilib_dma_engine_addr_t dma, uintptr return -1; } - return ctx->model_info->dma_api->benchmark(ctx->dma_ctx, dma, addr, size, iterations, direction); + return ctx->model_info.dma_api->benchmark(ctx->dma_ctx, dma, addr, size, iterations, direction); } @@ -15,20 +15,13 @@ #include "nwl.h" #include "nwl_defines.h" +#include "nwl_register.h" #define NWL_XAUI_ENGINE 0 #define NWL_XRAWDATA_ENGINE 1 #define NWL_FIX_EOP_FOR_BIG_PACKETS // requires precise sizes in read requests -/* -pcilib_register_bank_description_t ipecamera_register_banks[] = { - { PCILIB_REGISTER_DMABANK0, PCILIB_BAR0, 128, PCILIB_DEFAULT_PROTOCOL, DMA_NWL_OFFSET, DMA_NWL_OFFSET, PCILIB_LITTLE_ENDIAN, 32, PCILIB_LITTLE_ENDIAN, "%lx", "dma", "NorthWest Logick DMA Engine" }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } -}; -*/ - - typedef struct { pcilib_dma_engine_description_t desc; @@ -58,6 +51,63 @@ struct nwl_dma_s { #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) +static int nwl_add_registers(nwl_dma_t *ctx) { + int err; + size_t n, i, j; + int length; + const char *names[NWL_MAX_DMA_ENGINE_REGISTERS]; + uintptr_t addr[NWL_MAX_DMA_ENGINE_REGISTERS]; + + // We don't want DMA registers + if (pcilib_find_bank_by_addr(ctx->pcilib, PCILIB_REGISTER_BANK_DMA) == PCILIB_REGISTER_BANK_INVALID) return 0; + + err = pcilib_add_registers(ctx->pcilib, 0, nwl_dma_registers); + if (err) return err; + + err = pcilib_add_registers(ctx->pcilib, 0, nwl_xrawdata_registers); + if (err) return err; + + for (n = 0; nwl_dma_engine_registers[n].bits; n++) { + names[n] = nwl_dma_engine_registers[n].name; + addr[n] = nwl_dma_engine_registers[n].addr; + } + + if (ctx->n_engines > 9) length = 2; + else length = 1; + + for (i = 0; i < ctx->n_engines; i++) { + for (j = 0; nwl_dma_engine_registers[j].bits; j++) { + const char *direction; + nwl_dma_engine_registers[j].name = nwl_dma_engine_register_names[i * NWL_MAX_DMA_ENGINE_REGISTERS + j]; + nwl_dma_engine_registers[j].addr = addr[j] + (ctx->engines[i].base_addr - ctx->base_addr); +// printf("%lx %lx\n", (ctx->engines[i].base_addr - ctx->base_addr), nwl_dma_engine_registers[j].addr); + + switch (ctx->engines[i].desc.direction) { + case PCILIB_DMA_FROM_DEVICE: + direction = "r"; + break; + case PCILIB_DMA_TO_DEVICE: + direction = "w"; + break; + default: + direction = ""; + } + + sprintf((char*)nwl_dma_engine_registers[j].name, names[j], length, ctx->engines[i].desc.addr, direction); + } + + err = pcilib_add_registers(ctx->pcilib, n, nwl_dma_engine_registers); + if (err) return err; + } + + for (n = 0; nwl_dma_engine_registers[n].bits; n++) { + nwl_dma_engine_registers[n].name = names[n]; + nwl_dma_engine_registers[n].addr = addr[n]; + } + + return 0; +} + static int nwl_read_engine_config(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *info, char *base) { uint32_t val; @@ -101,6 +151,7 @@ static int nwl_stop_engine(nwl_dma_t *ctx, pcilib_dma_engine_t dma) { pcilib_nwl_engine_description_t *info = ctx->engines + dma; char *base = ctx->engines[dma].base_addr; + return 0; if (info->desc.addr == NWL_XRAWDATA_ENGINE) { // Stop Generators nwl_read_register(val, ctx, ctx->base_addr, TX_CONFIG_ADDRESS); @@ -182,6 +233,7 @@ pcilib_dma_context_t *dma_nwl_init(pcilib_t *pcilib) { 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; } @@ -210,6 +262,13 @@ pcilib_dma_context_t *dma_nwl_init(pcilib_t *pcilib) { pcilib_set_dma_engine_description(pcilib, n_engines, NULL); ctx->n_engines = n_engines; + + err = nwl_add_registers(ctx); + if (err) { + free(ctx); + pcilib_error("Failed to add DMA registers"); + return NULL; + } } return (pcilib_dma_context_t*)ctx; } diff --git a/dma/nwl_register.h b/dma/nwl_register.h new file mode 100644 index 0000000..86515cc --- /dev/null +++ b/dma/nwl_register.h @@ -0,0 +1,94 @@ +/* +pcilib_register_bank_description_t ipecamera_register_banks[] = { + { PCILIB_REGISTER_DMABANK0, PCILIB_BAR0, 128, PCILIB_DEFAULT_PROTOCOL, DMA_NWL_OFFSET, DMA_NWL_OFFSET, PCILIB_LITTLE_ENDIAN, 32, PCILIB_LITTLE_ENDIAN, "%lx", "dma", "NorthWest Logick DMA Engine" }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; +*/ + + // DMA +static pcilib_register_description_t nwl_dma_registers[] = { + {0x4000, 0, 32, 0, 0x00000011, PCILIB_REGISTER_RW , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma_control_and_status", ""}, + {0x4000, 0, 1, 0, 0x00000011, PCILIB_REGISTER_RW , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma_interrupt_enable", ""}, + {0x4000, 1, 1, 0, 0x00000011, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma_interrupt_active", ""}, + {0x4000, 2, 1, 0, 0x00000011, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma_interrupt_pending", ""}, + {0x4000, 3, 1, 0, 0x00000011, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma_interrupt_mode", ""}, + {0x4000, 4, 1, 0, 0x00000011, PCILIB_REGISTER_RW , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma_user_interrupt_enable", ""}, + {0x4000, 5, 1, 0, 0x00000011, PCILIB_REGISTER_RW1C, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma_user_interrupt_active", ""}, + {0x4000, 16, 8, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma_s2c_interrupt_status", ""}, + {0x4000, 24, 8, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma_c2s_interrupt_status", ""}, + {0x8000, 0, 32, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma_design_version", ""}, + {0x8000, 0, 4, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma_subversion_number", ""}, + {0x8000, 4, 8, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma_version_number", ""}, + {0x8000, 28, 4, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma_targeted_device", ""}, + {0x8200, 0, 32, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma_transmit_utilization", ""}, + {0x8200, 0, 2, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma_transmit_sample_count", ""}, + {0x8200, 2, 30, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma_transmit_dword_count", ""}, + {0x8204, 0, 32, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma_receive_utilization", ""}, + {0x8004, 0, 2, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma_receive_sample_count", ""}, + {0x8004, 2, 30, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma_receive_dword_count", ""}, + {0x8208, 0, 32, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma_mwr", ""}, + {0x8008, 0, 2, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma_mwr_sample_count", ""}, + {0x8008, 2, 30, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma_mwr_dword_count", ""}, + {0x820C, 0, 32, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma_cpld", ""}, + {0x820C, 0, 2, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma_cpld_sample_count", ""}, + {0x820C, 2, 30, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma_cpld_dword_count", ""}, + {0x8210, 0, 12, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma_init_fc_cpld", ""}, + {0x8214, 0, 8, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma_init_fc_cplh", ""}, + {0x8218, 0, 12, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma_init_fc_npd", ""}, + {0x821C, 0, 8, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma_init_fc_nph", ""}, + {0x8220, 0, 12, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma_init_fc_pd", ""}, + {0x8224, 0, 8, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma_init_fc_ph", ""}, + {0, 0, 0, 0, 0x00000000, 0, 0, 0, NULL, NULL} +}; + + // DMA Engine Registers +#define NWL_MAX_DMA_ENGINE_REGISTERS 64 +#define NWL_MAX_REGISTER_NAME 128 +static char nwl_dma_engine_register_names[PCILIB_MAX_DMA_ENGINES * NWL_MAX_DMA_ENGINE_REGISTERS][NWL_MAX_REGISTER_NAME]; +static pcilib_register_description_t nwl_dma_engine_registers[] = { + {0x0000, 0, 32, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_engine_capabilities", ""}, + {0x0000, 0, 1, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_present", ""}, + {0x0000, 1, 1, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_direction", ""}, + {0x0000, 4, 2, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_type", ""}, + {0x0000, 8, 8, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_number", ""}, + {0x0000, 24, 6, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_max_buffer_size", ""}, + {0x0004, 0, 32, 0, 0x0000C100, PCILIB_REGISTER_RW , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_engine_control", ""}, + {0x0004, 0, 1, 0, 0x0000C100, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_interrupt_enable", ""}, + {0x0004, 1, 1, 0, 0x0000C100, PCILIB_REGISTER_RW1C, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_interrupt_active", ""}, + {0x0004, 2, 1, 0, 0x0000C100, PCILIB_REGISTER_RW1C, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_descriptor_complete", ""}, + {0x0004, 3, 1, 0, 0x0000C100, PCILIB_REGISTER_RW1C, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_descriptor_alignment_error", ""}, + {0x0004, 4, 1, 0, 0x0000C100, PCILIB_REGISTER_RW1C, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_descriptor_fetch_error", ""}, + {0x0004, 5, 1, 0, 0x0000C100, PCILIB_REGISTER_RW1C, PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_sw_abort_error", ""}, + {0x0004, 8, 1, 0, 0x0000C100, PCILIB_REGISTER_RW , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_enable", ""}, + {0x0004, 9, 1, 0, 0x0000C100, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_running", ""}, + {0x0004, 10, 1, 0, 0x0000C100, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_waiting", ""}, + {0x0004, 14, 1, 0, 0x0000C100, PCILIB_REGISTER_RW , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_reset_request", ""}, + {0x0004, 15, 1, 0, 0x0000C100, PCILIB_REGISTER_RW , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_reset", ""}, + {0x0008, 0, 32, 0, 0x00000000, PCILIB_REGISTER_RW , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_next_descriptor", ""}, + {0x000C, 0, 32, 0, 0x00000000, PCILIB_REGISTER_RW , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_sw_descriptor", ""}, + {0x0010, 0, 32, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_last_descriptor", ""}, + {0x0014, 0, 32, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_active_time", ""}, + {0x0018, 0, 32, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_wait_time", ""}, + {0x001C, 0, 32, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_counter", ""}, + {0x001C, 0, 2, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_sample_count", ""}, + {0x001C, 2, 30, 0, 0x00000000, PCILIB_REGISTER_R , PCILIB_REGISTER_BITS, PCILIB_REGISTER_BANK_DMA, "dma%0*u%s_dword_count", ""}, + {0, 0, 0, 0, 0x00000000, 0, 0, 0, NULL, NULL} +}; + +/* + // XAUI registers +static pcilib_register_description_t nwl_xaui_registers[] = { + {0, 0, 0, 0, 0, 0, 0, NULL, NULL} +}; +*/ + + // XRAWDATA registers +static pcilib_register_description_t nwl_xrawdata_registers[] = { + {0x9100, 0, 1, 0, 0x00000000, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "xrawdata_enable_generator", ""}, + {0x9104, 0, 16, 0, 0x00000000, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "xrawdata_packet_length", ""}, + {0x9108, 0, 2, 0, 0x00000003, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK_DMA, "xrawdata_control", ""}, + {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", ""}, + {0, 0, 0, 0, 0x00000000, 0, 0, 0, NULL, NULL} +}; @@ -23,8 +23,8 @@ pcilib_event_t pcilib_find_event(pcilib_t *ctx, const char *event) { pcilib_register_bank_t res; unsigned long addr; - pcilib_model_t model = pcilib_get_model(ctx); - pcilib_event_description_t *events = pcilib_model[model].events; + pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); + pcilib_event_description_t *events = model_info->events; for (i = 0; events[i].name; i++) { if (!strcasecmp(events[i].name, event)) return (1<<i); @@ -37,9 +37,9 @@ pcilib_event_t pcilib_find_event(pcilib_t *ctx, const char *event) { int pcilib_reset(pcilib_t *ctx) { pcilib_event_api_description_t *api; - pcilib_model_t model = pcilib_get_model(ctx); + pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); - api = pcilib_model[model].event_api; + api = model_info->event_api; if (!api) { pcilib_error("Event API is not supported by the selected model"); return PCILIB_ERROR_NOTSUPPORTED; @@ -54,9 +54,9 @@ int pcilib_reset(pcilib_t *ctx) { int pcilib_start(pcilib_t *ctx, pcilib_event_t event_mask, void *callback, void *user) { pcilib_event_api_description_t *api; - pcilib_model_t model = pcilib_get_model(ctx); + pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); - api = pcilib_model[model].event_api; + api = model_info->event_api; if (!api) { pcilib_error("Event API is not supported by the selected model"); return PCILIB_ERROR_NOTSUPPORTED; @@ -71,9 +71,9 @@ int pcilib_start(pcilib_t *ctx, pcilib_event_t event_mask, void *callback, void int pcilib_stop(pcilib_t *ctx) { pcilib_event_api_description_t *api; - pcilib_model_t model = pcilib_get_model(ctx); + pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); - api = pcilib_model[model].event_api; + api = model_info->event_api; if (!api) { pcilib_error("Event API is not supported by the selected model"); return PCILIB_ERROR_NOTSUPPORTED; @@ -88,9 +88,9 @@ int pcilib_stop(pcilib_t *ctx) { pcilib_event_id_t pcilib_get_next_event(pcilib_t *ctx, pcilib_event_t event_mask, const struct timespec *timeout) { pcilib_event_api_description_t *api; - pcilib_model_t model = pcilib_get_model(ctx); + pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); - api = pcilib_model[model].event_api; + api = model_info->event_api; if (!api) { pcilib_error("Event API is not supported by the selected model"); return PCILIB_ERROR_NOTSUPPORTED; @@ -106,9 +106,9 @@ pcilib_event_id_t pcilib_get_next_event(pcilib_t *ctx, pcilib_event_t event_mask int pcilib_trigger(pcilib_t *ctx, pcilib_event_t event, size_t trigger_size, void *trigger_data) { pcilib_event_api_description_t *api; - pcilib_model_t model = pcilib_get_model(ctx); + pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); - api = pcilib_model[model].event_api; + api = model_info->event_api; if (!api) { pcilib_error("Event API is not supported by the selected model"); return PCILIB_ERROR_NOTSUPPORTED; @@ -123,7 +123,9 @@ int pcilib_trigger(pcilib_t *ctx, pcilib_event_t event, size_t trigger_size, voi void *pcilib_get_data_with_argument(pcilib_t *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t arg_size, void *arg, size_t *size) { - pcilib_event_api_description_t *api = pcilib_model[ctx->model].event_api; + pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); + + pcilib_event_api_description_t *api = model_info->event_api; if (!api) { pcilib_error("Event API is not supported by the selected model"); return NULL; @@ -136,7 +138,9 @@ void *pcilib_get_data_with_argument(pcilib_t *ctx, pcilib_event_id_t event_id, p } void *pcilib_get_data(pcilib_t *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t *size) { - pcilib_event_api_description_t *api = pcilib_model[ctx->model].event_api; + pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); + + pcilib_event_api_description_t *api = model_info->event_api; if (!api) { pcilib_error("Event API is not supported by the selected model"); return NULL; @@ -149,7 +153,9 @@ void *pcilib_get_data(pcilib_t *ctx, pcilib_event_id_t event_id, pcilib_event_da } int pcilib_return_data(pcilib_t *ctx, pcilib_event_id_t event_id) { - pcilib_event_api_description_t *api = pcilib_model[ctx->model].event_api; + pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); + + pcilib_event_api_description_t *api = model_info->event_api; if (!api) { pcilib_error("Event API is not supported by the selected model"); return PCILIB_ERROR_NOTSUPPORTED; diff --git a/ipecamera/model.c b/ipecamera/model.c index 23715e3..ddf9ee6 100644 --- a/ipecamera/model.c +++ b/ipecamera/model.c @@ -21,9 +21,9 @@ //#define IPECAMERA_SIMPLIFIED_READOUT #define IPECAMERA_MULTIREAD -static pcilib_register_value_t ipecamera_bit_mask[9] = { 0, 1, 3, 7, 15, 31, 63, 127, 255 }; +//static pcilib_register_value_t ipecamera_bit_mask[9] = { 0, 1, 3, 7, 15, 31, 63, 127, 255 }; -int ipecamera_read(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, uint8_t bits, pcilib_register_value_t *value) { +int ipecamera_read(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, pcilib_register_value_t *value) { uint32_t val, tmp[4]; char *wr, *rd; struct timeval start, cur; @@ -107,12 +107,13 @@ retry: return PCILIB_ERROR_VERIFY; } - *value = val&ipecamera_bit_mask[bits]; +// *value = val&ipecamera_bit_mask[bits]; + *value = val&0xFF; return 0; } -int ipecamera_write(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, uint8_t bits, pcilib_register_value_t value) { +int ipecamera_write(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, pcilib_register_value_t value) { uint32_t val, tmp[4]; char *wr, *rd; struct timeval start, cur; @@ -196,8 +197,8 @@ retry: return PCILIB_ERROR_VERIFY; } - if ((val&ipecamera_bit_mask[bits]) != value) { - pcilib_error("Value verification failed during register read (CMOSIS %lu, value: %lu != %lu)", addr, val&ipecamera_bit_mask[bits], value); + if ((val&0xFF/*&ipecamera_bit_mask[bits]*/) != value) { + pcilib_error("Value verification failed during register read (CMOSIS %lu, value: %lu != %lu)", addr, val/*&ipecamera_bit_mask[bits]*/, value); return PCILIB_ERROR_VERIFY; } diff --git a/ipecamera/model.h b/ipecamera/model.h index 197671f..da0ac12 100644 --- a/ipecamera/model.h +++ b/ipecamera/model.h @@ -13,72 +13,72 @@ #ifdef _IPECAMERA_MODEL_C pcilib_register_bank_description_t ipecamera_register_banks[] = { - { PCILIB_REGISTER_BANK0, PCILIB_BAR0, 128, IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, PCILIB_LITTLE_ENDIAN, 8, PCILIB_LITTLE_ENDIAN, "%lu", "cmosis", "CMOSIS CMV2000 Registers" }, - { PCILIB_REGISTER_BANK1, PCILIB_BAR0, 64, PCILIB_DEFAULT_PROTOCOL, IPECAMERA_REGISTER_SPACE, IPECAMERA_REGISTER_SPACE, PCILIB_LITTLE_ENDIAN, 32, PCILIB_LITTLE_ENDIAN, "0x%lx", "fpga", "IPECamera Registers" }, - { PCILIB_REGISTER_BANK_DMA, PCILIB_BAR0, 0x2000, PCILIB_DEFAULT_PROTOCOL, 0, 0, PCILIB_LITTLE_ENDIAN, 32, PCILIB_LITTLE_ENDIAN, "0x%lx", "dma", "DMA Registers"}, + { PCILIB_REGISTER_BANK0, PCILIB_BAR0, 128, IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ , IPECAMERA_REGISTER_WRITE, PCILIB_LITTLE_ENDIAN, 8 , PCILIB_LITTLE_ENDIAN, "%lu" , "cmosis", "CMOSIS CMV2000 Registers" }, + { PCILIB_REGISTER_BANK1, PCILIB_BAR0, 0x0200, PCILIB_DEFAULT_PROTOCOL , IPECAMERA_REGISTER_SPACE, IPECAMERA_REGISTER_SPACE, PCILIB_LITTLE_ENDIAN, 32, PCILIB_LITTLE_ENDIAN, "0x%lx", "fpga", "IPECamera Registers" }, + { PCILIB_REGISTER_BANK_DMA, PCILIB_BAR0, 0xA000, PCILIB_DEFAULT_PROTOCOL , 0, 0, PCILIB_LITTLE_ENDIAN, 32, PCILIB_LITTLE_ENDIAN, "0x%lx", "dma", "DMA Registers"}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } }; pcilib_register_description_t ipecamera_registers[] = { -{1, 0, 16, 1088, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "number_lines", ""}, -{3, 0, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "start1", ""}, -{5, 0, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "start2", ""}, -{7, 0, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "start3", ""}, -{9, 0, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "start4", ""}, -{11, 0, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "start5", ""}, -{13, 0, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "start6", ""}, -{15, 0, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "start7", ""}, -{17, 0, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "start8", ""}, -{19, 0, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "number_lines1", ""}, -{21, 0, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "number_lines2", ""}, -{23, 0, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "number_lines3", ""}, -{25, 0, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "number_lines4", ""}, -{27, 0, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "number_lines5", ""}, -{29, 0, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "number_lines6", ""}, -{31, 0, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "number_lines7", ""}, -{33, 0, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "number_lines8", ""}, -{35, 0, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "sub_s", ""}, -{37, 0, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "sub_a", ""}, -{39, 0, 1, 1, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "color", ""}, -{40, 0, 2, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "image_flipping", ""}, -{41, 0, 2, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "exp_flags", ""}, -{42, 0, 24, 1088, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "exp_time", ""}, -{45, 0, 24, 1088, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "exp_step", ""}, -{48, 0, 24, 1, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "exp_kp1", ""}, -{51, 0, 24, 1, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "exp_kp2", ""}, -{54, 0, 2, 1, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "nr_slopes", ""}, -{55, 0, 8, 1, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "exp_seq", ""}, -{56, 0, 24, 1088, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "exp_time2", ""}, -{59, 0, 24, 1088, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "exp_step2", ""}, -{68, 0, 2, 1, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "nr_slopes2", ""}, -{69, 0, 8, 1, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "exp_seq2", ""}, -{70, 0, 16, 1, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "number_frames", ""}, -{72, 0, 2, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "output_mode", ""}, -{78, 0, 12, 85, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "training_pattern", ""}, -{80, 0, 18, 0x3FFFF,PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "channel_en", ""}, -{82, 0, 3, 7, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "special_82", ""}, -{89, 0, 8, 96, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "vlow2", ""}, -{90, 0, 8, 96, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "vlow3", ""}, -{100, 0, 14, 16260, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "offset", ""}, -{102, 0, 2, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "pga", ""}, -{103, 0, 8, 32, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "adc_gain", ""}, -{111, 0, 1, 1, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "bit_mode", ""}, -{112, 0, 2, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "adc_resolution", ""}, -{115, 0, 1, 1, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "special_115", ""}, +{1, 0, 16, 1088, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "number_lines", ""}, +{3, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "start1", ""}, +{5, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "start2", ""}, +{7, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "start3", ""}, +{9, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "start4", ""}, +{11, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "start5", ""}, +{13, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "start6", ""}, +{15, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "start7", ""}, +{17, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "start8", ""}, +{19, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "number_lines1", ""}, +{21, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "number_lines2", ""}, +{23, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "number_lines3", ""}, +{25, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "number_lines4", ""}, +{27, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "number_lines5", ""}, +{29, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "number_lines6", ""}, +{31, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "number_lines7", ""}, +{33, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "number_lines8", ""}, +{35, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "sub_s", ""}, +{37, 0, 16, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "sub_a", ""}, +{39, 0, 1, 1, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "color", ""}, +{40, 0, 2, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "image_flipping", ""}, +{41, 0, 2, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "exp_flags", ""}, +{42, 0, 24, 1088, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "exp_time", ""}, +{45, 0, 24, 1088, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "exp_step", ""}, +{48, 0, 24, 1, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "exp_kp1", ""}, +{51, 0, 24, 1, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "exp_kp2", ""}, +{54, 0, 2, 1, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "nr_slopes", ""}, +{55, 0, 8, 1, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "exp_seq", ""}, +{56, 0, 24, 1088, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "exp_time2", ""}, +{59, 0, 24, 1088, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "exp_step2", ""}, +{68, 0, 2, 1, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "nr_slopes2", ""}, +{69, 0, 8, 1, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "exp_seq2", ""}, +{70, 0, 16, 1, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "number_frames", ""}, +{72, 0, 2, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "output_mode", ""}, +{78, 0, 12, 85, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "training_pattern", ""}, +{80, 0, 18, 0x3FFFF,0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "channel_en", ""}, +{82, 0, 3, 7, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "special_82", ""}, +{89, 0, 8, 96, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "vlow2", ""}, +{90, 0, 8, 96, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "vlow3", ""}, +{100, 0, 14, 16260, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "offset", ""}, +{102, 0, 2, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "pga", ""}, +{103, 0, 8, 32, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "adc_gain", ""}, +{111, 0, 1, 1, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "bit_mode", ""}, +{112, 0, 2, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "adc_resolution", ""}, +{115, 0, 1, 1, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "special_115", ""}, /*{126, 0, 16, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK0, "temp", ""},*/ -{0, 0, 32, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "spi_conf_input", ""}, -{4, 0, 32, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "spi_conf_output", ""}, -{8, 0, 32, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "spi_clk_speed", ""}, -{12, 0, 32, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "firmware_version", ""}, -{16, 0, 32, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "control", ""}, -{20, 0, 32, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "status", ""}, -{24, 0, 16, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "cmosis_temperature", ""}, -{28, 0, 32, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "temperature_sample_timing", ""}, -{32, 0, 32, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "start_address", ""}, -{36, 0, 32, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "end_address", ""}, -{40, 0, 32, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "last_write_address", ""}, -{44, 0, 32, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "last_write_value", ""}, -{0, 0, 0, 0, 0, 0, 0, NULL, NULL} +{0, 0, 32, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "spi_conf_input", ""}, +{0x10, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "spi_conf_output", ""}, +{0x20, 0, 32, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "spi_clk_speed", ""}, +{0x30, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "firmware_version", ""}, +{0x40, 0, 32, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "control", ""}, +{0x50, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "status", ""}, +{0x60, 0, 16, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "cmosis_temperature", ""}, +{0x70, 0, 32, 0, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "temperature_sample_timing", ""}, +{0x80, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "start_address", ""}, +{0x90, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "end_address", ""}, +{0x100, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "last_write_address", ""}, +{0x110, 0, 32, 0, 0, PCILIB_REGISTER_R, PCILIB_REGISTER_STANDARD, PCILIB_REGISTER_BANK1, "last_write_value", ""}, +{0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL} }; pcilib_register_range_t ipecamera_register_ranges[] = { @@ -115,7 +115,7 @@ pcilib_event_api_description_t ipecamera_image_api = { extern pcilib_event_api_description_t ipecamera_image_api; #endif -int ipecamera_read(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, uint8_t bits, pcilib_register_value_t *value); -int ipecamera_write(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, uint8_t bits, pcilib_register_value_t value); +int ipecamera_read(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, pcilib_register_value_t *value); +int ipecamera_write(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, pcilib_register_value_t value); #endif /* _IPECAMERA_MODEL_H */ @@ -63,8 +63,8 @@ pcilib_t *pcilib_open(const char *device, pcilib_model_t model) { if (!model) model = pcilib_get_model(ctx); - ctx->model_info = pcilib_model + model; - + memcpy(&ctx->model_info, pcilib_model + model, sizeof(pcilib_model_description_t)); + api = pcilib_model[model].event_api; if ((api)&&(api->init)) ctx->event_ctx = api->init(ctx); } @@ -73,7 +73,7 @@ pcilib_t *pcilib_open(const char *device, pcilib_model_t model) { } pcilib_model_description_t *pcilib_get_model_description(pcilib_t *ctx) { - return ctx->model_info; + return &ctx->model_info; } const pcilib_board_info_t *pcilib_get_board_info(pcilib_t *ctx) { @@ -221,8 +221,8 @@ int pcilib_map_register_space(pcilib_t *ctx) { pcilib_register_bank_t i; if (!ctx->reg_bar_mapped) { - pcilib_model_t model = pcilib_get_model(ctx); - pcilib_register_bank_description_t *banks = pcilib_model[model].banks; + pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); + pcilib_register_bank_description_t *banks = model_info->banks; for (i = 0; ((banks)&&(banks[i].access)); i++) { // uint32_t buf[2]; @@ -400,13 +400,18 @@ void pcilib_close(pcilib_t *ctx) { pcilib_bar_t i; if (ctx) { - pcilib_model_t model = pcilib_get_model(ctx); - pcilib_event_api_description_t *eapi = pcilib_model[model].event_api; - pcilib_dma_api_description_t *dapi = pcilib_model[model].dma_api; + pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); + pcilib_event_api_description_t *eapi = model_info->event_api; + pcilib_dma_api_description_t *dapi = model_info->dma_api; if ((eapi)&&(eapi->free)) eapi->free(ctx->event_ctx); if ((dapi)&&(dapi->free)) dapi->free(ctx->dma_ctx); + if (ctx->model_info.registers != model_info->registers) { + free(ctx->model_info.registers); + ctx->model_info.registers = pcilib_model[ctx->model].registers; + } + while (ctx->kmem_list) { pcilib_free_kernel_memory(ctx, ctx->kmem_list); } @@ -34,7 +34,8 @@ struct pcilib_s { pcilib_kmem_list_t *kmem_list; - pcilib_model_description_t *model_info; + size_t num_reg, alloc_reg; + pcilib_model_description_t model_info; pcilib_dma_context_t *dma_ctx; pcilib_context_t *event_ctx; @@ -61,6 +62,8 @@ pcilib_protocol_description_t pcilib_protocol[3] = { { NULL, NULL } }; #else +extern pcilib_model_description_t pcilib_model[]; + extern void (*pcilib_error)(const char *msg, ...); extern void (*pcilib_warning)(const char *msg, ...); @@ -28,7 +28,7 @@ typedef unsigned long pcilib_irq_source_t; typedef uint8_t pcilib_bar_t; /**< Type holding the PCI Bar number */ typedef uint8_t pcilib_register_t; /**< Type holding the register ID within the Bank */ -typedef uint8_t pcilib_register_addr_t; /**< Type holding the register ID within the Bank */ +typedef uint32_t pcilib_register_addr_t; /**< Type holding the register ID within the Bank */ typedef uint8_t pcilib_register_bank_t; /**< Type holding the register bank number */ typedef uint8_t pcilib_register_bank_addr_t; /**< Type holding the register bank number */ typedef uint8_t pcilib_register_size_t; /**< Type holding the size in bits of the register */ @@ -53,7 +53,9 @@ typedef enum { typedef enum { PCILIB_REGISTER_R = 1, PCILIB_REGISTER_W = 2, - PCILIB_REGISTER_RW = 3 + PCILIB_REGISTER_RW = 3, + PCILIB_REGISTER_W1C = 4, /**< writting 1 resets the flag */ + PCILIB_REGISTER_RW1C = 5 } pcilib_register_mode_t; typedef enum { @@ -72,7 +74,8 @@ typedef enum { typedef enum { PCILIB_REGISTER_STANDARD = 0, - PCILIB_REGISTER_FIFO + PCILIB_REGISTER_FIFO, + PCILIB_REGISTER_BITS } pcilib_register_type_t; #define PCILIB_BAR_DETECT ((pcilib_bar_t)-1) @@ -126,6 +129,7 @@ typedef struct { pcilib_register_size_t offset; pcilib_register_size_t bits; pcilib_register_value_t defvalue; + pcilib_register_value_t rwmask; /**< 1 - read before write bits, 0 - zero should be written to preserve value */ pcilib_register_mode_t mode; pcilib_register_type_t type; @@ -185,10 +189,6 @@ typedef struct { pcilib_event_api_description_t *event_api; } pcilib_model_description_t; -#ifndef _PCILIB_PCI_C -extern pcilib_model_description_t pcilib_model[]; -#endif /* ! _PCILIB_PCI_C */ - int pcilib_set_error_handler(void (*err)(const char *msg, ...), void (*warn)(const char *msg, ...)); pcilib_model_t pcilib_get_model(pcilib_t *ctx); @@ -17,10 +17,50 @@ #include "tools.h" #include "error.h" +int pcilib_add_registers(pcilib_t *ctx, size_t n, pcilib_register_description_t *registers) { + pcilib_register_description_t *regs; + size_t size, n_present, n_new; + + if (!n) { + for (n = 0; registers[n].bits; n++); + } + + + if (ctx->model_info.registers == pcilib_model[ctx->model].registers) { + for (n_present = 0; ctx->model_info.registers[n_present].bits; n_present++); + for (size = 1024; size < 2 * (n + n_present + 1); size<<=1); + regs = (pcilib_register_description_t*)malloc(size * sizeof(pcilib_register_description_t)); + if (!regs) return PCILIB_ERROR_MEMORY; + + ctx->model_info.registers = regs; + ctx->num_reg = n + n_present; + ctx->alloc_reg = size; + + memcpy(ctx->model_info.registers, pcilib_model[ctx->model].registers, (n_present + 1) * sizeof(pcilib_register_description_t)); + } else { + n_present = ctx->num_reg; + if ((n_present + n + 1) > ctx->alloc_reg) { + for (size = ctx->alloc_reg; size < 2 * (n + n_present + 1); size<<=1); + + regs = (pcilib_register_description_t*)realloc(ctx->model_info.registers, size * sizeof(pcilib_register_description_t)); + if (!regs) return PCILIB_ERROR_MEMORY; + + ctx->model_info.registers = regs; + ctx->alloc_reg = size; + } + ctx->num_reg += n; + } + + memcpy(ctx->model_info.registers + ctx->num_reg, ctx->model_info.registers + n_present, sizeof(pcilib_register_description_t)); + memcpy(ctx->model_info.registers + n_present, registers, n * sizeof(pcilib_register_description_t)); + + return 0; +} + pcilib_register_bank_t pcilib_find_bank_by_addr(pcilib_t *ctx, pcilib_register_bank_addr_t bank) { pcilib_register_bank_t i; - pcilib_model_t model = pcilib_get_model(ctx); - pcilib_register_bank_description_t *banks = pcilib_model[model].banks; + pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); + pcilib_register_bank_description_t *banks = model_info->banks; for (i = 0; banks[i].access; i++) if (banks[i].addr == bank) return i; @@ -30,7 +70,8 @@ pcilib_register_bank_t pcilib_find_bank_by_addr(pcilib_t *ctx, pcilib_register_b pcilib_register_bank_t pcilib_find_bank_by_name(pcilib_t *ctx, const char *bankname) { pcilib_register_bank_t i; - pcilib_register_bank_description_t *banks = pcilib_model[ctx->model].banks; + pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); + pcilib_register_bank_description_t *banks = model_info->banks; for (i = 0; banks[i].access; i++) if (!strcasecmp(banks[i].name, bankname)) return i; @@ -43,8 +84,8 @@ pcilib_register_bank_t pcilib_find_bank(pcilib_t *ctx, const char *bank) { unsigned long addr; if (!bank) { - pcilib_model_t model = pcilib_get_model(ctx); - pcilib_register_bank_description_t *banks = pcilib_model[model].banks; + pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); + pcilib_register_bank_description_t *banks = model_info->banks; if ((banks)&&(banks[0].access)) return (pcilib_register_bank_t)0; return -1; } @@ -62,10 +103,9 @@ pcilib_register_t pcilib_find_register(pcilib_t *ctx, const char *bank, const ch pcilib_register_t i; pcilib_register_bank_t bank_id; pcilib_register_bank_addr_t bank_addr; - - pcilib_model_t model = pcilib_get_model(ctx); - - pcilib_register_description_t *registers = pcilib_model[model].registers; + + pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); + pcilib_register_description_t *registers = model_info->registers; if (bank) { bank_id = pcilib_find_bank(ctx, bank); @@ -74,28 +114,36 @@ pcilib_register_t pcilib_find_register(pcilib_t *ctx, const char *bank, const ch return -1; } - bank_addr = pcilib_model[model].banks[bank_id].addr; + bank_addr = model_info->banks[bank_id].addr; } for (i = 0; registers[i].bits; i++) { if ((!strcasecmp(registers[i].name, reg))&&((!bank)||(registers[i].bank == bank_addr))) return i; } + if ((ctx->model_info.dma_api)&&(!ctx->dma_ctx)&&(pcilib_get_dma_info(ctx))) { + registers = model_info->registers; + + for (; registers[i].bits; i++) { + if ((!strcasecmp(registers[i].name, reg))&&((!bank)||(registers[i].bank == bank_addr))) return i; + } + } + return (pcilib_register_t)-1; }; -static int pcilib_read_register_space_internal(pcilib_t *ctx, pcilib_register_bank_t bank, pcilib_register_addr_t addr, size_t n, uint8_t bits, pcilib_register_value_t *buf) { +static int pcilib_read_register_space_internal(pcilib_t *ctx, pcilib_register_bank_t bank, pcilib_register_addr_t addr, size_t n, pcilib_register_size_t offset, pcilib_register_size_t bits, pcilib_register_value_t *buf) { int err; int rest; size_t i; - pcilib_model_t model = pcilib_get_model(ctx); - pcilib_register_bank_description_t *b = pcilib_model[model].banks + bank; + pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); + pcilib_register_bank_description_t *b = model_info->banks + bank; assert(bits < 8 * sizeof(pcilib_register_value_t)); if (((addr + n) > b->size)||(((addr + n) == b->size)&&(bits))) { - pcilib_error("Accessing sregister (%u regs at addr %u) out of register space (%u registers total)", bits?(n+1):n, addr, b->size); + pcilib_error("Accessing register (%u regs at addr %u) out of register space (%u registers total)", bits?(n+1):n, addr, b->size); return PCILIB_ERROR_OUTOFRANGE; } @@ -109,11 +157,17 @@ static int pcilib_read_register_space_internal(pcilib_t *ctx, pcilib_register_ba //bits %= b->access; for (i = 0; i < n; i++) { - err = pcilib_protocol[b->protocol].read(ctx, b, addr + i, b->access, buf + i); + err = pcilib_protocol[b->protocol].read(ctx, b, addr + i, buf + i); if (err) break; } - if ((bits > 0)&&(!err)) err = pcilib_protocol[b->protocol].read(ctx, b, addr + n, bits, buf + n); + if ((bits > 0)&&(!err)) { + pcilib_register_value_t val = 0; + err = pcilib_protocol[b->protocol].read(ctx, b, addr + n, &val); + + val = (val >> offset)&BIT_MASK(bits); + memcpy(buf + n, &val, sizeof(pcilib_register_value_t)); + } return err; } @@ -126,25 +180,31 @@ int pcilib_read_register_space(pcilib_t *ctx, const char *bank, pcilib_register_ return PCILIB_ERROR_INVALID_BANK; } - return pcilib_read_register_space_internal(ctx, bank_id, addr, n, 0, buf); + return pcilib_read_register_space_internal(ctx, bank_id, addr, n, 0, 0, buf); } int pcilib_read_register_by_id(pcilib_t *ctx, pcilib_register_t reg, pcilib_register_value_t *value) { int err; - size_t i, n, bits; + size_t i, n; + pcilib_register_size_t bits; pcilib_register_value_t res; + pcilib_register_bank_t bank; pcilib_register_description_t *r; pcilib_register_bank_description_t *b; - pcilib_model_t model = pcilib_get_model(ctx); + pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); - r = pcilib_model[model].registers + reg; - b = pcilib_model[model].banks + r->bank; + r = model_info->registers + reg; + + bank = pcilib_find_bank_by_addr(ctx, r->bank); + if (bank == PCILIB_REGISTER_BANK_INVALID) return PCILIB_ERROR_INVALID_BANK; + + b = model_info->banks + bank; n = r->bits / b->access; bits = r->bits % b->access; pcilib_register_value_t buf[n + 1]; - err = pcilib_read_register_space_internal(ctx, r->bank, r->addr, n, bits, buf); + err = pcilib_read_register_space_internal(ctx, bank, r->addr, n, r->offset, bits, buf); if ((b->endianess == PCILIB_BIG_ENDIAN)||((b->endianess == PCILIB_HOST_ENDIAN)&&(ntohs(1) == 1))) { pcilib_error("Big-endian byte order support is not implemented"); @@ -174,24 +234,21 @@ int pcilib_read_register(pcilib_t *ctx, const char *bank, const char *regname, p } return pcilib_read_register_by_id(ctx, reg, value); - -// registers[reg].bank -// printf("%li %li", sizeof(pcilib_model[model].banks), sizeof(pcilib_register_bank_description_t)); } -static int pcilib_write_register_space_internal(pcilib_t *ctx, pcilib_register_bank_t bank, pcilib_register_addr_t addr, size_t n, uint8_t bits, pcilib_register_value_t *buf) { +static int pcilib_write_register_space_internal(pcilib_t *ctx, pcilib_register_bank_t bank, pcilib_register_addr_t addr, size_t n, pcilib_register_size_t offset, pcilib_register_size_t bits, pcilib_register_value_t rwmask, pcilib_register_value_t *buf) { int err; int rest; size_t i; - pcilib_model_t model = pcilib_get_model(ctx); - pcilib_register_bank_description_t *b = pcilib_model[model].banks + bank; + pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); + pcilib_register_bank_description_t *b = model_info->banks + bank; assert(bits < 8 * sizeof(pcilib_register_value_t)); if (((addr + n) > b->size)||(((addr + n) == b->size)&&(bits))) { - pcilib_error("Accessing sregister (%u regs at addr %u) out of register space (%u registers total)", bits?(n+1):n, addr, b->size); + pcilib_error("Accessing register (%u regs at addr %u) out of register space (%u registers total)", bits?(n+1):n, addr, b->size); return PCILIB_ERROR_OUTOFRANGE; } @@ -205,11 +262,25 @@ static int pcilib_write_register_space_internal(pcilib_t *ctx, pcilib_register_b //bits %= b->access; for (i = 0; i < n; i++) { - err = pcilib_protocol[b->protocol].write(ctx, b, addr + i, b->access, buf[i]); + err = pcilib_protocol[b->protocol].write(ctx, b, addr + i, buf[i]); if (err) break; } - if ((bits > 0)&&(!err)) err = pcilib_protocol[b->protocol].write(ctx, b, addr + n, bits, buf[n]); + if ((bits > 0)&&(!err)) { + pcilib_register_value_t val = (buf[n]&BIT_MASK(bits))<<offset; + pcilib_register_value_t mask = BIT_MASK(bits)<<offset; + + if (~mask&rwmask) { + pcilib_register_value_t rval; + + err = pcilib_protocol[b->protocol].read(ctx, b, addr + n, &rval); + if (err) return err; + + val |= (rval & rwmask & ~mask); + } + + err = pcilib_protocol[b->protocol].write(ctx, b, addr + n, val); + } return err; } @@ -222,20 +293,26 @@ int pcilib_write_register_space(pcilib_t *ctx, const char *bank, pcilib_register return PCILIB_ERROR_INVALID_BANK; } - return pcilib_write_register_space_internal(ctx, bank_id, addr, n, 0, buf); + return pcilib_write_register_space_internal(ctx, bank_id, addr, n, 0, 0, 0, buf); } int pcilib_write_register_by_id(pcilib_t *ctx, pcilib_register_t reg, pcilib_register_value_t value) { int err; - size_t i, n, bits; + size_t i, n; + pcilib_register_size_t bits; + pcilib_register_bank_t bank; pcilib_register_value_t res; pcilib_register_description_t *r; pcilib_register_bank_description_t *b; - pcilib_model_t model = pcilib_get_model(ctx); + pcilib_model_description_t *model_info = pcilib_get_model_description(ctx); + + r = model_info->registers + reg; + + bank = pcilib_find_bank_by_addr(ctx, r->bank); + if (bank == PCILIB_REGISTER_BANK_INVALID) return PCILIB_ERROR_INVALID_BANK; - r = pcilib_model[model].registers + reg; - b = pcilib_model[model].banks + r->bank; + b = model_info->banks + bank; n = r->bits / b->access; bits = r->bits % b->access; @@ -262,7 +339,7 @@ int pcilib_write_register_by_id(pcilib_t *ctx, pcilib_register_t reg, pcilib_reg } } - err = pcilib_write_register_space_internal(ctx, r->bank, r->addr, n, bits, buf); + err = pcilib_write_register_space_internal(ctx, bank, r->addr, n, r->offset, bits, r->rwmask, buf); return err; } @@ -4,8 +4,11 @@ #include "pcilib.h" struct pcilib_protocol_description_s { - int (*read)(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, uint8_t bits, pcilib_register_value_t *value); - int (*write)(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, uint8_t bits, pcilib_register_value_t value); + int (*read)(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, pcilib_register_value_t *value); + int (*write)(pcilib_t *ctx, pcilib_register_bank_description_t *bank, pcilib_register_addr_t addr, pcilib_register_value_t value); }; + // we don't copy strings, they should be statically allocated +int pcilib_add_registers(pcilib_t *ctx, size_t n, pcilib_register_description_t *registers); + #endif /* _PCILIB_REGISTER_H */ |