瀏覽代碼

Support dynamic registers, support register offsets and multiregisters (bitmasks), list NWL DMA registers

Suren A. Chilingaryan 13 年之前
父節點
當前提交
02924fc496
共有 16 個文件被更改,包括 468 次插入202 次删除
  1. 0 1
      ToDo
  2. 53 37
      cli.c
  3. 3 0
      common.mk
  4. 6 6
      default.c
  5. 2 2
      default.h
  6. 9 9
      dma.c
  7. 67 8
      dma/nwl.c
  8. 94 0
      dma/nwl_register.h
  9. 21 15
      event.c
  10. 7 6
      ipecamera/model.c
  11. 63 63
      ipecamera/model.h
  12. 13 8
      pci.c
  13. 4 1
      pci.h
  14. 7 7
      pcilib.h
  15. 114 37
      register.c
  16. 5 2
      register.h

+ 0 - 1
ToDo

@@ -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

+ 53 - 37
cli.c

@@ -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);

+ 3 - 0
common.mk

@@ -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))

+ 6 - 6
default.c

@@ -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;

+ 2 - 2
default.h

@@ -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 */

+ 9 - 9
dma.c

@@ -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);
 }

+ 67 - 8
dma/nwl.c

@@ -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;
 }

+ 94 - 0
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}
+};

+ 21 - 15
event.c

@@ -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;

+ 7 - 6
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;
     }
 

+ 63 - 63
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 */

+ 13 - 8
pci.c

@@ -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);
 	}

+ 4 - 1
pci.h

@@ -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, ...);
 

+ 7 - 7
pcilib.h

@@ -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);

+ 114 - 37
register.c

@@ -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;
 }
 

+ 5 - 2
register.h

@@ -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 */