Browse Source

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

Suren A. Chilingaryan 12 years ago
parent
commit
02924fc496
16 changed files with 468 additions and 202 deletions
  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 */