소스 검색

Initial support of IPECamera protocol

Suren A. Chilingaryan 13 년 전
부모
커밋
7f97ea0741
9개의 변경된 파일854개의 추가작업 그리고 246개의 파일을 삭제
  1. 118 80
      cli.c
  2. 1 1
      common.mk
  3. 16 0
      error.h
  4. 153 0
      ipecamera.c
  5. 63 52
      ipecamera.h
  6. 324 70
      pci.c
  7. 84 28
      pci.h
  8. 79 11
      tools.c
  9. 16 4
      tools.h

+ 118 - 80
cli.c

@@ -1,37 +1,25 @@
-/*******************************************************************
- * This is a test program for the IOctl interface of the 
- * pciDriver.
- * 
- * $Revision: 1.3 $
- * $Date: 2006-11-17 18:49:01 $
- * 
- *******************************************************************/
-
-/*******************************************************************
- * Change History:
- * 
- * $Log: not supported by cvs2svn $
- * Revision 1.2  2006/10/16 16:56:09  marcus
- * Added nice comment at the start.
- *
- *******************************************************************/
+#define _POSIX_C_SOURCE 200112L
 
 #include <stdio.h>
-#include <string.h>
 #include <stdlib.h>
+#include <string.h>
+#include <strings.h>
 #include <stdint.h>
 #include <stdarg.h>
 #include <fcntl.h>
 #include <unistd.h>
+#include <sys/time.h>
 #include <sys/ioctl.h>
 #include <sys/mman.h>
 #include <errno.h>
 #include <alloca.h>
+#include <arpa/inet.h>
 
 #include <getopt.h>
 
 #include "pci.h"
 #include "ipecamera.h"
+#include "tools.h"
 
 
 /* defines */
@@ -48,7 +36,9 @@
 #define BLOCK_SIZE 8
 #define BENCHMARK_ITERATIONS 128
 
-//#define FILE_IO
+
+
+typedef uint8_t access_t;
 
 typedef enum {
     MODE_INVALID,
@@ -66,6 +56,7 @@ typedef enum {
     OPT_MODEL = 'm',
     OPT_BAR = 'b',
     OPT_ACCESS = 'a',
+    OPT_ENDIANESS = 'e',
     OPT_SIZE = 's',
     OPT_INFO = 'i',
     OPT_BENCHMARK = 'p',
@@ -80,6 +71,7 @@ static struct option long_options[] = {
     {"model",			required_argument, 0, OPT_MODEL },
     {"bar",			required_argument, 0, OPT_BAR },
     {"access",			required_argument, 0, OPT_ACCESS },
+    {"endianess",		required_argument, 0, OPT_ENDIANESS },
     {"size",			required_argument, 0, OPT_SIZE },
     {"info",			no_argument, 0, OPT_INFO },
     {"list",			no_argument, 0, OPT_LIST },
@@ -118,14 +110,15 @@ void Usage(int argc, char *argv[], const char *format, ...) {
 "\n"
 "  Addressing:\n"
 "	-d <device>	- FPGA device (/dev/fpga0)\n"
-"	-m <model>	- Memory model\n"
-"	   pci		- Plain (default)\n"
+"	-m <model>	- Memory model (autodetected)\n"
+"	   pci		- Plain\n"
 "	   ipecamera	- IPE Camera\n"
-"	-b <bank>	- Data bank (autodetected)\n"
+"	-b <bank>	- Data/Register bank (autodetected)\n"
 "\n"
 "  Options:\n"
 "	-s <size>	- Number of words (default: 1)\n"
 "	-a <bitness>	- Bits per word (default: 32)\n"
+"	-e <l|b>	- Endianess Little/Big (default: host)\n"
 "\n\n",
 argv[0]);
 
@@ -146,9 +139,9 @@ void Error(const char *format, ...) {
 }
 
 
-void List(int handle, pcilib_model_t model) {
+void List(pcilib_t *handle, pcilib_model_t model) {
     int i;
-    pcilib_register_t *registers;
+    pcilib_register_description_t *registers;
 
     const pci_board_info *board_info = pcilib_get_board_info(handle);
 
@@ -171,18 +164,18 @@ void List(int handle, pcilib_model_t model) {
     }
     printf("\n");
     
-    registers = pcilib_model_description[model].registers;
+    registers = pcilib_model[model].registers;
     
     if (registers) {
 	printf("Registers: \n");
-	for (i = 0; registers[i].size; i++) {
+	for (i = 0; registers[i].bits; i++) {
 	    const char *mode;
 	    if (registers[i].mode == PCILIB_REGISTER_RW) mode = "RW";
 	    else if (registers[i].mode == PCILIB_REGISTER_R) mode = "R ";
 	    else if (registers[i].mode == PCILIB_REGISTER_W) mode = " W";
 	    else mode = "  ";
 	    
-	    printf(" 0x%02x (%2i %s) %s", registers[i].id, registers[i].size, mode, registers[i].name);
+	    printf(" 0x%02x (%2i %s) %s", registers[i].addr, registers[i].bits, mode, registers[i].name);
 	    if ((registers[i].description)&&(registers[i].description[0])) {
 		printf(": %s", registers[i].description);
 	    }
@@ -193,7 +186,7 @@ void List(int handle, pcilib_model_t model) {
     }
 }
 
-void Info(int handle, pcilib_model_t model) {
+void Info(pcilib_t *handle, pcilib_model_t model) {
     const pci_board_info *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);
@@ -201,7 +194,7 @@ void Info(int handle, pcilib_model_t model) {
 }
 
 
-int Benchmark(int handle, int bar) {
+int Benchmark(pcilib_t *handle, pcilib_bar_t bar) {
     int err;
     int i, errors;
     void *data, *buf, *check;
@@ -262,7 +255,7 @@ int Benchmark(int handle, int bar) {
     for (size = 4 ; size < max_size; size *= 8) {
 	gettimeofday(&start,NULL);
 	for (i = 0; i < BENCHMARK_ITERATIONS; i++) {
-	    pcilib_read(buf, handle, bar, 0, size);
+	    pcilib_read(handle, bar, 0, size, buf);
 	}
 	gettimeofday(&end,NULL);
 
@@ -273,7 +266,7 @@ int Benchmark(int handle, int bar) {
 
 	gettimeofday(&start,NULL);
 	for (i = 0; i < BENCHMARK_ITERATIONS; i++) {
-	    pcilib_write(buf, handle, bar, 0, size);
+	    pcilib_write(handle, bar, 0, size, buf);
 	}
 	gettimeofday(&end,NULL);
 
@@ -282,8 +275,8 @@ int Benchmark(int handle, int bar) {
 
 	gettimeofday(&start,NULL);
 	for (i = 0, errors = 0; i < BENCHMARK_ITERATIONS; i++) {
-	    pcilib_write(buf, handle, bar, 0, size);
-	    pcilib_read(check, handle, bar, 0, size);
+	    pcilib_write(handle, bar, 0, size, buf);
+	    pcilib_read(handle, bar, 0, size, check);
 	    if (memcmp(buf, check, size)) ++errors;
 	}
 	gettimeofday(&end,NULL);
@@ -300,8 +293,10 @@ int Benchmark(int handle, int bar) {
     free(buf);
 }
 
+#define pci2host16(endianess, value) endianess?
+
 
-int ReadData(int handle, int bar, unsigned long addr, int n, int access) {
+int ReadData(pcilib_t *handle, pcilib_bar_t bar, uintptr_t addr, size_t n, access_t access, int endianess) {
     void *buf;
     int i, err;
     int size = n * abs(access);
@@ -317,10 +312,10 @@ int ReadData(int handle, int bar, unsigned long addr, int n, int access) {
 
 //    buf = alloca(size);
     err = posix_memalign( (void**)&buf, 256, size );
-
     if ((err)||(!buf)) Error("Allocation of %i bytes of memory have failed", size);
     
-    pcilib_read(buf, handle, bar, addr, size);
+    pcilib_read(handle, bar, addr, size, buf);
+    if (endianess) pcilib_swap(buf, buf, abs(access), n);
 
     for (i = 0; i < n; i++) {
 	if (i) {
@@ -346,17 +341,26 @@ int ReadData(int handle, int bar, unsigned long addr, int n, int access) {
     free(buf);
 }
 
-int ReadRegister(int handle, pcilib_model_t model, const char *reg) {
+int ReadRegister(pcilib_t *handle, pcilib_model_t model, const char *reg) {
+    int err;
     int i;
+
+    pcilib_register_value_t value;
     
-    if (!reg) {
-        pcilib_register_t *registers = pcilib_model_description[model].registers;
+    if (reg) {
+        err = pcilib_read_register(handle, reg, &value);
+        if (err) printf("Error reading register %s\n", reg);
+        else printf("%s = %i\n", reg, value);
+    } else {
+        pcilib_register_description_t *registers = pcilib_model[model].registers;
 	
 	if (registers) {
 	    printf("Registers:\n");
-	    for (i = 0; registers[i].size; i++) {
+	    for (i = 0; registers[i].bits; i++) {
 		if (registers[i].mode & PCILIB_REGISTER_R) {
-	    	    printf(" %s = %i [%i]", registers[i].name, 0, registers[i].defvalue);
+		    err = pcilib_read_register_by_id(handle, i, &value);
+		    if (err) printf(" %s = error reading value [%i]", registers[i].name, registers[i].defvalue);
+	    	    else printf(" %s = %i [%i]", registers[i].name, value, registers[i].defvalue);
 		}
 		printf("\n");
 	    }
@@ -367,20 +371,17 @@ int ReadRegister(int handle, pcilib_model_t model, const char *reg) {
     }
 }
 
-int ReadRegisterRange(int handle, pcilib_model_t model, int bar, unsigned long addr, int n, int access) {
+int ReadRegisterRange(pcilib_t *handle, pcilib_model_t model, uintptr_t addr, size_t n) {
 }
 
-int WriteData(int handle, int bar, unsigned long addr, int n, int access, char ** data) {
+int WriteData(pcilib_t *handle, pcilib_bar_t bar, uintptr_t addr, size_t n, access_t access, int endianess, char ** data) {
     void *buf, *check;
     int res, i, err;
     int size = n * abs(access);
-    
+
     err = posix_memalign( (void**)&buf, 256, size );
-    if (!err) {
-        err = posix_memalign( (void**)&check, 256, size );
-    }
-    if ((err)||(!buf)||(!check)) 
-        Error("Allocation of %i bytes of memory have failed", size);
+    if (!err) err = posix_memalign( (void**)&check, 256, size );
+    if ((err)||(!buf)||(!check)) Error("Allocation of %i bytes of memory have failed", size);
 
     for (i = 0; i < n; i++) {
 	switch (access) {
@@ -393,12 +394,14 @@ int WriteData(int handle, int bar, unsigned long addr, int n, int access, char *
 	if (res != 1) Error("Can't parse data value at poition %i, (%s) is not valid hex number", i, data[i]);
     }
 
-    pcilib_write(buf, handle, bar, addr, size);
-    pcilib_read(check, handle, bar, addr, size);
+    if (endianess) pcilib_swap(buf, buf, abs(access), n);
+    pcilib_write(handle, bar, addr, size, buf);
+    pcilib_read(handle, bar, addr, size, check);
+    if (endianess) pcilib_swap(check, check, abs(access), n);
     
     if (memcmp(buf, check, size)) {
 	printf("Write failed: the data written and read differ, the foolowing is read back:\n");
-	ReadData(handle, bar, addr, n, access);
+	ReadData(handle, bar, addr, n, access, endianess);
 	exit(-1);
     }
 
@@ -406,32 +409,58 @@ int WriteData(int handle, int bar, unsigned long addr, int n, int access, char *
     free(buf);
 }
 
-int WriteRegisterRange(int handle, pcilib_model_t model, int bar, unsigned long addr, int n, int access, char ** data) {
+int WriteRegisterRange(pcilib_t *handle, pcilib_model_t model, uintptr_t addr, size_t n, char ** data) {
 }
 
-int WriteRegister(int handle, pcilib_model_t model, const char *reg, char ** data) {
+int WriteRegister(pcilib_t *handle, pcilib_model_t model, const char *reg, char ** data) {
+    int err;
+    int i;
+
+    unsigned long val;
+    pcilib_register_value_t value;
+    
+    if (sscanf(*data, "%li", &val) != 1) {
+	Error("Can't parse data value (%s) is not valid decimal number", data[i]);
+    }
+
+    value = val;
+    
+    err = pcilib_write_register(handle, reg, value);
+    if (err) Error("Error writting register %s\n", reg);
+
+    err = pcilib_read_register(handle, reg, &value);
+    if (err) Error("Error reading back register %s for verification\n", reg);
+
+    if (val != value) {
+	Error("Failed to write register %s: %lu is written and %lu is read back", reg, val, value);
+    } else {
+	printf("%s = %i\n", reg, value);
+    }
+    
+    return 0;
 }
 
 
 int main(int argc, char **argv) {
+    int i;
+    long itmp;
     unsigned char c;
 
-    pcilib_model_t model = (pcilib_model_t)-1;
+    pcilib_model_t model = PCILIB_MODEL_DETECT;
     MODE mode = MODE_INVALID;
     const char *fpga_device = DEFAULT_FPGA_DEVICE;
-    int bar = -1;
+    pcilib_bar_t bar = PCILIB_BAR_DETECT;
     const char *addr = NULL;
-    unsigned long start = -1;
-    int size = 1;
-    int access = 4;
+    const char *reg = NULL;
+    uintptr_t start = -1;
+    size_t size = 1;
+    access_t access = 4;
     int skip = 0;
+    int endianess = 0;
 
-    int i;
-    int handle;
+    pcilib_t *handle;
     
-    const char *reg = NULL;
-    
-    while ((c = getopt_long(argc, argv, "hilpr::w::d:b:a:s:", long_options, NULL)) != (unsigned char)-1) {
+    while ((c = getopt_long(argc, argv, "hilpr::w::d:m:b:a:s:e:", long_options, NULL)) != (unsigned char)-1) {
 	extern int optind;
 	switch (c) {
 	    case OPT_HELP:
@@ -475,11 +504,12 @@ int main(int argc, char **argv) {
 		else Usage(argc, argv, "Invalid memory model (%s) is specified", optarg);\
 	    break;
 	    case OPT_BAR:
-		if ((sscanf(optarg,"%u", &bar) != 1)||(bar < 0)||(bar >= PCILIB_MAX_BANKS)) Usage(argc, argv, "Invalid data bank (%s) is specified", optarg);
+		if ((sscanf(optarg,"%li", &itmp) != 1)||(itmp < 0)||(itmp >= PCILIB_MAX_BANKS)) Usage(argc, argv, "Invalid data bank (%s) is specified", optarg);
+		else bar = itmp;
 	    break;
 	    case OPT_ACCESS:
-		if (sscanf(optarg, "%i", &access) != 1) access = 0;
-		switch (access) {
+		if (sscanf(optarg, "%li", &itmp) != 1) access = 0;
+		switch (itmp) {
 		    case 8: access = 1; break;
 		    case 16: access = 2; break;
 		    case 32: access = 4; break;
@@ -488,9 +518,19 @@ int main(int argc, char **argv) {
 		}	
 	    break;
 	    case OPT_SIZE:
-		if (sscanf(optarg, "%u", &size) != 1)
+		if (sscanf(optarg, "%zu", &size) != 1)
 		    Usage(argc, argv, "Invalid size is specified (%s)", optarg);
 	    break;
+	    case OPT_ENDIANESS:
+		if ((*optarg == 'b')||(*optarg == 'B')) {
+		    if (ntohs(1) == 1) endianess = 0;
+		    else endianess = 1;
+		} else if ((*optarg == 'l')||(*optarg == 'L')) {
+		    if (ntohs(1) == 1) endianess = 1;
+		    else endianess = 0;
+		} else Usage(argc, argv, "Invalid endianess is specified (%s)", optarg);
+		
+	    break;
 	    default:
 		Usage(argc, argv, "Unknown option (%s)", argv[optind]);
 	}
@@ -503,12 +543,10 @@ int main(int argc, char **argv) {
 
     pcilib_set_error_handler(&Error);
 
-    handle = pcilib_open(fpga_device);
+    handle = pcilib_open(fpga_device, model);
     if (handle < 0) Error("Failed to open FPGA device: %s", fpga_device);
 
-    if (model == (pcilib_model_t)-1) {
-	model = pcilib_detect_model(handle);
-    }
+    model = pcilib_get_model(handle);
 
     switch (mode) {
      case MODE_WRITE:
@@ -530,7 +568,7 @@ int main(int argc, char **argv) {
     if (addr) {
 	if (sscanf(addr, "%lx", &start) == 1) {
 		// check if the address in the register range
-	    pcilib_register_range_t *ranges =  pcilib_model_description[model].ranges;
+	    pcilib_register_range_t *ranges =  pcilib_model[model].ranges;
 
 	    for (i = 0; ranges[i].start != ranges[i].end; i++) 
 		if ((start >= ranges[i].start)&&(start <= ranges[i].end)) break;
@@ -538,11 +576,11 @@ int main(int argc, char **argv) {
 		// register access in plain mode
 	    if (ranges[i].start != ranges[i].end) ++mode;
 	} else {
-	    if (pcilib_find_register(model, addr) >= 0) {
+	    if (pcilib_find_register(handle, addr) == PCILIB_REGISTER_INVALID) {
+	        Usage(argc, argv, "Invalid address (%s) is specified", addr);
+	    } else {
 	        reg = addr;
 		++mode;
-	    } else {
-	        Usage(argc, argv, "Invalid address (%s) is specified", addr);
 	    }
 	} 
     }
@@ -560,21 +598,21 @@ int main(int argc, char **argv) {
      break;
      case MODE_READ:
         if (addr) {
-	    ReadData(handle, bar, start, size, access);
+	    ReadData(handle, bar, start, size, access, endianess);
 	} else {
 	    Error("Address to read is not specified");
 	}
      break;
      case MODE_READ_REGISTER:
         if ((reg)||(!addr)) ReadRegister(handle, model, reg);
-	else ReadRegisterRange(handle, model, bar, start, size, access);
+	else ReadRegisterRange(handle, model, start, size);
      break;
      case MODE_WRITE:
-	WriteData(handle, bar, start, size, access, argv + optind);
+	WriteData(handle, bar, start, size, access, endianess, argv + optind);
      break;
      case MODE_WRITE_REGISTER:
         if (reg) WriteRegister(handle, model, reg, argv + optind);
-	else WriteRegisterRange(handle, model, bar, start, size, access, argv + optind);
+	else WriteRegisterRange(handle, model, start, size, argv + optind);
      break;
     }
 

+ 1 - 1
common.mk

@@ -13,7 +13,7 @@ OBJDIR ?= $(ROOTDIR)
 DEPENDDIR ?= $(ROOTDIR)
 
 CXXFLAGS += $(addprefix -I ,$(INCDIR)) -fPIC
-CFLAGS += $(addprefix -I ,$(INCDIR)) -fPIC
+CFLAGS += $(addprefix -I ,$(INCDIR)) -fPIC -std=c99
 
 # Source files in this directory
 SRC = $(wildcard *.cpp)

+ 16 - 0
error.h

@@ -0,0 +1,16 @@
+#ifndef _PCILIB_ERROR_H
+#define _PCILIB_ERROR_H
+ 
+enum {
+    PCILIB_ERROR_SUCCESS = 0,
+    PCILIB_ERROR_INVALID_ADDRESS,
+    PCILIB_ERROR_TIMEOUT,
+    PCILIB_ERROR_FAILED,
+    PCILIB_ERROR_VERIFY,
+    PCILIB_ERROR_NOTSUPPORTED,
+    PCILIB_ERROR_NOTFOUND,
+    PCILIB_ERROR_OUTOFRANGE
+} pcilib_errot_t;
+
+
+#endif /* _PCILIB_ERROR_H */

+ 153 - 0
ipecamera.c

@@ -1,4 +1,157 @@
 #define _IPECAMERA_C
+#include <sys/time.h>
+#include <assert.h>
+
+#include "tools.h"
 #include "ipecamera.h"
+#include "error.h"
+
+#define ADDR_MASK 0x7F00
+#define WRITE_BIT 0x8000
+#define RETRIES 10
+
+#define READ_READY_BIT 0x20000
+#define READ_ERROR_BIT 0x40000
+
+#define ipecamera_datacpy(dst, src, bank)   pcilib_datacpy(dst, src, 4, 1, bank->raw_endianess)
+
+/*
+int ipecamera_read_register_space(int handle, pcilib_model_t model, pcilib_register_t addr, pcilib_register_value_t *value) {
+    //ipelib_write_
+    //(void *buf, int handle, pcilib_bar_t bar, uintptr_t addr, size_t size);
+    
+}
+
+int ipecamera_write_register_space(int handle, pcilib_model_t model, pcilib_register_t addr, pcilib_register_value_t value) {
+}
+
+
+static int ipecamera_read_byte(int handle, int reg, int bits, uint8_t *value) {
+}
+
+static int ipecamera_write_byte(int handle, int reg, int bits, uint8_t value) {
+}
+*/
+
+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) {
+    uint32_t val;
+    char *wr, *rd;
+    struct timeval start, cur;
+    int retries = RETRIES;
+    
+    assert(addr < 128);
+    
+    wr =  pcilib_resolve_register_address(ctx, bank->write_addr);
+    rd =  pcilib_resolve_register_address(ctx, bank->read_addr);
+    if ((!rd)||(!wr)) {
+	pcilib_error("Error resolving addresses of read & write registers");
+	return PCILIB_ERROR_INVALID_ADDRESS;
+    }
+
+retry:
+    val = (addr << 8);
+    
+    //printf("%i %x %p %p\n", addr,  val, wr, rd);
+    
+    ipecamera_datacpy(wr, &val, bank);
+    
+    gettimeofday(&start, NULL);
+
+    ipecamera_datacpy(&val, rd, bank);
+    while ((val & READ_READY_BIT) == 0) {
+        gettimeofday(&cur, NULL);
+	if (((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec)) > PCILIB_REGISTER_TIMEOUT) break;
+	
+	ipecamera_datacpy(&val, rd, bank);
+    }
+
+    if ((val & READ_READY_BIT) == 0) {
+	pcilib_error("Timeout reading register value");
+	return PCILIB_ERROR_TIMEOUT;
+    }
+    
+    if (val & READ_ERROR_BIT) {
+	pcilib_error("Error reading register value");
+	return PCILIB_ERROR_FAILED;
+    }
+
+    if (((val&ADDR_MASK) >> 8) != addr) {
+	if (--retries > 0) {
+	    pcilib_warning("Address verification failed during register read, retrying (try %i of %i)...", RETRIES - retries, RETRIES);
+	    goto retry;
+	}
+	pcilib_error("Address verification failed during register read");
+	return PCILIB_ERROR_VERIFY;
+    }
+
+    
+//    printf("%i\n", val&ipecamera_bit_mask[bits]);
+
+    *value = val&ipecamera_bit_mask[bits];
+
+    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) {
+    uint32_t val;
+    char *wr, *rd;
+    struct timeval start, cur;
+    int retries = RETRIES;
+    
+    assert(addr < 128);
+    assert(value < 256);
+    
+    wr =  pcilib_resolve_register_address(ctx, bank->write_addr);
+    rd =  pcilib_resolve_register_address(ctx, bank->read_addr);
+    if ((!rd)||(!wr)) {
+	pcilib_error("Error resolving addresses of read & write registers");
+	return PCILIB_ERROR_INVALID_ADDRESS;
+    }
+
+retry:
+    val = WRITE_BIT|(addr << 8)|(value&0xFF);
+    
+    //printf("%i %x %p %p\n", addr,  val, wr, rd);
+    
+    ipecamera_datacpy(wr, &val, bank);
+    
+    gettimeofday(&start, NULL);
+
+    ipecamera_datacpy(&val, rd, bank);
+    while ((val & READ_READY_BIT) == 0) {
+        gettimeofday(&cur, NULL);
+	if (((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec)) > PCILIB_REGISTER_TIMEOUT) break;
+	
+	ipecamera_datacpy(&val, rd, bank);
+    }
+
+    if ((val & READ_READY_BIT) == 0) {
+	pcilib_error("Timeout writting register value");
+	return PCILIB_ERROR_TIMEOUT;
+    }
+    
+    if (val & READ_ERROR_BIT) {
+	pcilib_error("Error writting register value");
+	return PCILIB_ERROR_FAILED;
+    }
+
+    if (((val&ADDR_MASK) >> 8) != addr) {
+	if (--retries > 0) {
+	    pcilib_warning("Address verification failed during register read, retrying (try %i of %i)...", RETRIES - retries, RETRIES);
+	    goto retry;
+	}
+	pcilib_error("Address verification failed during register write");
+	return PCILIB_ERROR_VERIFY;
+    }
+    
+    if ((val&ipecamera_bit_mask[bits]) != value) {
+	pcilib_error("Value verification failed during register read (%lu != %lu)", val&ipecamera_bit_mask[bits], value);
+	return PCILIB_ERROR_VERIFY;
+    }
 
+    //printf("%i\n", val&ipecamera_bit_mask[bits]);
 
+    return 0;
+}

+ 63 - 52
ipecamera.h

@@ -6,65 +6,76 @@
 #include "pci.h"
 
 #define IPECAMERA_REGISTER_SPACE 0xfeaffc00
-#define IPECAMERA_REGISTER_WRITE (IPECAMERA_REGISTER_SPACE)
-#define IPECAMERA_REGISTER_READ (IPECAMERA_REGISTER_SPACE + 4)
+#define IPECAMERA_REGISTER_WRITE (IPECAMERA_REGISTER_SPACE + 0)
+#define IPECAMERA_REGISTER_READ (IPECAMERA_REGISTER_WRITE + 4)
+
 
 #ifdef _IPECAMERA_C
-pcilib_register_t ipecamera_registers[] = {
-{1, 	16, 	1088, 	PCILIB_REGISTER_RW, "number_lines", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{3, 	16, 	0, 	PCILIB_REGISTER_RW, "start1", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{5, 	16, 	0, 	PCILIB_REGISTER_RW, "start2", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{7, 	16, 	0, 	PCILIB_REGISTER_RW, "start3", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{9, 	16, 	0, 	PCILIB_REGISTER_RW, "start4", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{11,	16, 	0, 	PCILIB_REGISTER_RW, "start5", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{13, 	16, 	0, 	PCILIB_REGISTER_RW, "start6", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{15, 	16, 	0, 	PCILIB_REGISTER_RW, "start7", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{17, 	16, 	0, 	PCILIB_REGISTER_RW, "start8", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{19, 	16, 	0, 	PCILIB_REGISTER_RW, "number_lines1", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{21, 	16, 	0, 	PCILIB_REGISTER_RW, "number_lines2", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{23, 	16, 	0, 	PCILIB_REGISTER_RW, "number_lines3", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{25, 	16, 	0, 	PCILIB_REGISTER_RW, "number_lines4", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{27, 	16, 	0, 	PCILIB_REGISTER_RW, "number_lines5", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{29, 	16, 	0, 	PCILIB_REGISTER_RW, "number_lines6", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{31, 	16, 	0, 	PCILIB_REGISTER_RW, "number_lines7", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{33, 	16, 	0, 	PCILIB_REGISTER_RW, "number_lines8", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{35, 	16, 	0, 	PCILIB_REGISTER_RW, "sub_s", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{37, 	16, 	0, 	PCILIB_REGISTER_RW, "sub_a", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{39, 	1, 	1, 	PCILIB_REGISTER_RW, "color", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{40, 	2, 	0, 	PCILIB_REGISTER_RW, "image_flipping", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{41, 	2, 	0, 	PCILIB_REGISTER_RW, "exp_flags", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{42, 	24, 	1088, 	PCILIB_REGISTER_RW, "exp_time", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{45, 	24, 	1088, 	PCILIB_REGISTER_RW, "exp_step", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{48, 	24, 	1, 	PCILIB_REGISTER_RW, "exp_kp1", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{51, 	24, 	1, 	PCILIB_REGISTER_RW, "exp_kp2", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{54, 	2, 	1, 	PCILIB_REGISTER_RW, "nr_slopes", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{55, 	8, 	1, 	PCILIB_REGISTER_RW, "exp_seq", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{56, 	24, 	1088, 	PCILIB_REGISTER_RW, "exp_time2", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{59, 	24, 	1088, 	PCILIB_REGISTER_RW, "exp_step2", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{68, 	2, 	1, 	PCILIB_REGISTER_RW, "nr_slopes2", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{69, 	8, 	1, 	PCILIB_REGISTER_RW, "exp_seq2", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{70, 	16, 	1, 	PCILIB_REGISTER_RW, "number_frames", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{72, 	2, 	0, 	PCILIB_REGISTER_RW, "output_mode", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{78, 	12, 	85, 	PCILIB_REGISTER_RW, "training_pattern", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{80, 	18, 	0x3FFFF,PCILIB_REGISTER_RW, "channel_en", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{89, 	8, 	96, 	PCILIB_REGISTER_RW, "vlow2", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{90, 	8, 	96, 	PCILIB_REGISTER_RW, "vlow3", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{100, 	14, 	16260, 	PCILIB_REGISTER_RW, "offset", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{102, 	2, 	0, 	PCILIB_REGISTER_RW, "pga", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{103, 	8, 	32, 	PCILIB_REGISTER_RW, "adc_gain", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{111, 	1, 	1, 	PCILIB_REGISTER_RW, "bit_mode", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{112, 	2, 	0, 	PCILIB_REGISTER_RW, "adc_resolution", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{126, 	16, 	0, 	PCILIB_REGISTER_RW, "temp", IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, ""},
-{0,	0,	0,	0, NULL, 0, 0, 0, NULL}
+pcilib_register_bank_description_t ipecamera_register_banks[] = {
+    { PCILIB_REGISTER_BANK0, IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE,  PCILIB_BIG_ENDIAN, 8, PCILIB_LITTLE_ENDIAN },
+    { 0, 0, 0, 0, 0 }
+};
+
+pcilib_register_description_t ipecamera_registers[] = {
+{1, 	16, 	1088, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines",  ""},
+{3, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "start1", ""},
+{5, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "start2", ""},
+{7, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "start3", ""},
+{9, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "start4", ""},
+{11,	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "start5", ""},
+{13, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "start6", ""},
+{15, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "start7", ""},
+{17, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "start8", ""},
+{19, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines1", ""},
+{21, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines2", ""},
+{23, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines3", ""},
+{25, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines4", ""},
+{27, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines5", ""},
+{29, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines6", ""},
+{31, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines7", ""},
+{33, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_lines8", ""},
+{35, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "sub_s", ""},
+{37, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "sub_a", ""},
+{39, 	1, 	1, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "color", ""},
+{40, 	2, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "image_flipping", ""},
+{41, 	2, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_flags", ""},
+{42, 	24, 	1088, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_time", ""},
+{45, 	24, 	1088, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_step", ""},
+{48, 	24, 	1, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_kp1", ""},
+{51, 	24, 	1, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_kp2", ""},
+{54, 	2, 	1, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "nr_slopes", ""},
+{55, 	8, 	1, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_seq", ""},
+{56, 	24, 	1088, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_time2", ""},
+{59, 	24, 	1088, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_step2", ""},
+{68, 	2, 	1, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "nr_slopes2", ""},
+{69, 	8, 	1, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "exp_seq2", ""},
+{70, 	16, 	1, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "number_frames", ""},
+{72, 	2, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "output_mode", ""},
+{78, 	12, 	85, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "training_pattern", ""},
+{80, 	18, 	0x3FFFF,PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "channel_en", ""},
+{89, 	8, 	96, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "vlow2", ""},
+{90, 	8, 	96, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "vlow3", ""},
+{100, 	14, 	16260, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "offset", ""},
+{102, 	2, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "pga", ""},
+{103, 	8, 	32, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "adc_gain", ""},
+{111, 	1, 	1, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "bit_mode", ""},
+{112, 	2, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "adc_resolution", ""},
+{126, 	16, 	0, 	PCILIB_REGISTER_RW, PCILIB_REGISTER_BANK0, "temp", ""},
+{0,	0,	0,	0,                  0,                     NULL, NULL}
 };
 
-pcilib_register_range_t ipecamera_register_range[] = {
-    {0, 128}, {0,0}
+pcilib_register_range_t ipecamera_register_ranges[] = {
+    {0, 128, PCILIB_REGISTER_BANK0}, {0, 0, 0}
 };
 
 #else
-extern pcilib_register_t ipecamera_registers[];
-extern pcilib_register_range_t ipecamera_register_range[];
+extern pcilib_register_description_t ipecamera_registers[];
+extern pcilib_register_bank_description_t ipecamera_register_banks[];
+extern pcilib_register_range_t ipecamera_register_ranges[];
 #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);
+
 #endif /* _IPECAMERA_H */

+ 324 - 70
pci.c

@@ -2,6 +2,7 @@
 
 #include <stdio.h>
 #include <string.h>
+#include <strings.h>
 #include <stdlib.h>
 #include <stdint.h>
 #include <stdarg.h>
@@ -10,6 +11,7 @@
 #include <sys/ioctl.h>
 #include <sys/mman.h>
 #include <errno.h>
+#include <assert.h>
 
 #include "driver/pciDriver.h"
 
@@ -18,135 +20,160 @@
 
 #include "pci.h"
 #include "ipecamera.h"
+#include "error.h"
 
-static pci_board_info board_info;
-static page_mask = -1;
+#define BIT_MASK(bits) ((1 << (bits)) - 1)
 
 
+//#define PCILIB_FILE_IO
+
+struct pcilib_s {
+    int handle;
+    
+    uintptr_t page_mask;
+    pci_board_info board_info;
+    pcilib_model_t model;
+
+    pcilib_bar_t reg_bar;
+    char *reg_space;
+    
+#ifdef PCILIB_FILE_IO
+    int file_io_handle;
+#endif /* PCILIB_FILE_IO */
+};
+
 static void pcilib_print_error(const char *msg, ...) {
     va_list va;
     
     va_start(va, msg);
     vprintf(msg, va);
     va_end(va);
+    printf("\n");
 }
 
-static void (*Error)(const char *msg, ...) = pcilib_print_error;
+void (*pcilib_error)(const char *msg, ...) = pcilib_print_error;
+void (*pcilib_warning)(const char *msg, ...) = pcilib_print_error;
 
-int pcilib_open(const char *device) {
-    int handle = open(device, O_RDWR);
-    return handle;
+int pcilib_set_error_handler(void (*err)(const char *msg, ...)) {
+    pcilib_error = err;
 }
 
-void pcilib_close(int handle) {
-    close(handle);
-}
+pcilib_t *pcilib_open(const char *device, pcilib_model_t model) {
+    pcilib_t *ctx = malloc(sizeof(pcilib_t));
 
-int pcilib_set_error_handler(void (*err)(const char *msg, ...)) {
-    Error = err;
+    if (ctx) {
+	ctx->handle = open(device, O_RDWR);
+	ctx->page_mask = (uintptr_t)-1;
+	ctx->model = model;
+	ctx->reg_space = NULL;
+    }
+
+    return ctx;
 }
 
-const pci_board_info *pcilib_get_board_info(int handle) {
+const pci_board_info *pcilib_get_board_info(pcilib_t *ctx) {
     int ret;
     
-    if (page_mask < 0) {
-	ret = ioctl( handle, PCIDRIVER_IOC_PCI_INFO, &board_info );
-	if (ret) Error("PCIDRIVER_IOC_PCI_INFO ioctl have failed");
+    if (ctx->page_mask ==  (uintptr_t)-1) {
+	ret = ioctl( ctx->handle, PCIDRIVER_IOC_PCI_INFO, &ctx->board_info );
+	if (ret) pcilib_error("PCIDRIVER_IOC_PCI_INFO ioctl have failed");
 	
-	page_mask = get_page_mask();
+	ctx->page_mask = pcilib_get_page_mask();
     }
     
-    return &board_info;
+    return &ctx->board_info;
 }
 
 
-pcilib_model_t pcilib_detect_model(int handle) {
+pcilib_model_t pcilib_get_model(pcilib_t *ctx) {
+    if (ctx->model == PCILIB_MODEL_DETECT) {
 	unsigned short vendor_id;
 	unsigned short device_id;
 
-    pcilib_get_board_info(handle);
+	const pci_board_info *board_info = pcilib_get_board_info(ctx);
 
-    if ((board_info.vendor_id == PCIE_XILINX_VENDOR_ID)&&(board_info.device_id ==  PCIE_IPECAMERA_DEVICE_ID)) return PCILIB_MODEL_IPECAMERA;
-    return PCILIB_MODEL_PCI;
+	if ((board_info->vendor_id == PCIE_XILINX_VENDOR_ID)&&(board_info->device_id == PCIE_IPECAMERA_DEVICE_ID))
+	    ctx->model = PCILIB_MODEL_IPECAMERA;
+	else
+	    ctx->model = PCILIB_MODEL_PCI;
+    }
+    
+    return ctx->model;
 }
 
-static int pcilib_detect_bar(int handle, unsigned long addr, int size) {
+static int pcilib_detect_bar(pcilib_t *ctx, uintptr_t addr, size_t size) {
     int ret,i;
 	
-    pcilib_get_board_info(handle);
+    const pci_board_info *board_info = pcilib_get_board_info(ctx);
 		
     for (i = 0; i < PCILIB_MAX_BANKS; i++) {
-	if ((addr >= board_info.bar_start[i])&&((board_info.bar_start[i] + board_info.bar_length[i]) >= (addr + size))) return i;
+	if ((addr >= board_info->bar_start[i])&&((board_info->bar_start[i] + board_info->bar_length[i]) >= (addr + size))) return i;
     }
 	
     return -1;
 }
 
-static void *pcilib_detect_address(int handle, int *bar, unsigned long *addr, int size) {
-    if (*bar < 0) {
-	*bar = pcilib_detect_bar(handle, *addr, size);
-	if (*bar < 0) Error("The requested data block at address 0x%x with size 0x%x does not belongs to any available memory bank", *addr, size);
+static void pcilib_detect_address(pcilib_t *ctx, pcilib_bar_t *bar, uintptr_t *addr, size_t size) {
+    const pci_board_info *board_info = pcilib_get_board_info(ctx);
+    
+    if (*bar == PCILIB_BAR_DETECT) {
+	*bar = pcilib_detect_bar(ctx, *addr, size);
+	if (*bar < 0) pcilib_error("The requested data block at address 0x%x with size 0x%x does not belongs to any available memory bank", *addr, size);
     } else {
-	pcilib_get_board_info(handle);
-	
-	if ((*addr < board_info.bar_start[*bar])||((board_info.bar_start[*bar] + board_info.bar_length[*bar]) < (((uintptr_t)*addr) + size))) {
-	    if ((board_info.bar_length[*bar]) >= (((uintptr_t)*addr) + size)) 
-		*addr += board_info.bar_start[*bar];
+	if ((*addr < board_info->bar_start[*bar])||((board_info->bar_start[*bar] + board_info->bar_length[*bar]) < (((uintptr_t)*addr) + size))) {
+	    if ((board_info->bar_length[*bar]) >= (((uintptr_t)*addr) + size)) 
+		*addr += board_info->bar_start[*bar];
 	    else
-		Error("The requested data block at address 0x%x with size 0x%x does not belong the specified memory bank (Bar %i: starting at 0x%x with size 0x%x)", *addr, size, *bar, board_info.bar_start[*bar], board_info.bar_length[*bar]);
+		pcilib_error("The requested data block at address 0x%x with size 0x%x does not belong the specified memory bank (Bar %i: starting at 0x%x with size 0x%x)", *addr, size, *bar, board_info->bar_start[*bar], board_info->bar_length[*bar]);
 	}
     }
     
-    *addr -= board_info.bar_start[*bar];
-    *addr += board_info.bar_start[*bar] & page_mask;
+    *addr -= board_info->bar_start[*bar];
+    *addr += board_info->bar_start[*bar] & ctx->page_mask;
 }
 
-
-#ifdef FILE_IO
-int file_io_handle;
-#endif /* FILE_IO */
-
-void *pcilib_map_bar(int handle, int bar) {
+void *pcilib_map_bar(pcilib_t *ctx, pcilib_bar_t bar) {
     void *res;
     int ret; 
 
-    pcilib_get_board_info(handle);
+    const pci_board_info *board_info = pcilib_get_board_info(ctx);
     
-    ret = ioctl( handle, PCIDRIVER_IOC_MMAP_MODE, PCIDRIVER_MMAP_PCI );
-    if (ret) Error("PCIDRIVER_IOC_MMAP_MODE ioctl have failed", bar);
+    ret = ioctl( ctx->handle, PCIDRIVER_IOC_MMAP_MODE, PCIDRIVER_MMAP_PCI );
+    if (ret) pcilib_error("PCIDRIVER_IOC_MMAP_MODE ioctl have failed", bar);
 
-    ret = ioctl( handle, PCIDRIVER_IOC_MMAP_AREA, PCIDRIVER_BAR0 + bar );
-    if (ret) Error("PCIDRIVER_IOC_MMAP_AREA ioctl have failed for bank %i", bar);
+    ret = ioctl( ctx->handle, PCIDRIVER_IOC_MMAP_AREA, PCIDRIVER_BAR0 + bar );
+    if (ret) pcilib_error("PCIDRIVER_IOC_MMAP_AREA ioctl have failed for bank %i", bar);
 
-#ifdef FILE_IO
-    file_io_handle = open("/root/drivers/pciDriver/data", O_RDWR);
-    res = mmap( 0, board_info.bar_length[bar], PROT_WRITE | PROT_READ, MAP_SHARED, file_io_handle, 0 );
+#ifdef PCILIB_FILE_IO
+    file_io_handle = open("/root/data", O_RDWR);
+    res = mmap( 0, board_info->bar_length[bar], PROT_WRITE | PROT_READ, MAP_SHARED, ctx->file_io_handle, 0 );
 #else
-    res = mmap( 0, board_info.bar_length[bar], PROT_WRITE | PROT_READ, MAP_SHARED, handle, 0 );
+    res = mmap( 0, board_info->bar_length[bar], PROT_WRITE | PROT_READ, MAP_SHARED, ctx->handle, 0 );
 #endif
-    if ((!res)||(res == MAP_FAILED)) Error("Failed to mmap data bank %i", bar);
+    if ((!res)||(res == MAP_FAILED)) pcilib_error("Failed to mmap data bank %i", bar);
 
     
     return res;
 }
 
-void pcilib_unmap_bar(int handle, int bar, void *data) {
-    munmap(data, board_info.bar_length[bar]);
-#ifdef FILE_IO
-    close(file_io_handle);
+void pcilib_unmap_bar(pcilib_t *ctx, pcilib_bar_t bar, void *data) {
+    const pci_board_info *board_info = pcilib_get_board_info(ctx);
+
+    munmap(data, board_info->bar_length[bar]);
+#ifdef PCILIB_FILE_IO
+    close(ctx->file_io_handle);
 #endif
 }
 
-int pcilib_read(void *buf, int handle, int bar, unsigned long addr, int size) {
+int pcilib_read(pcilib_t *ctx, pcilib_bar_t bar, uintptr_t addr, size_t size, void *buf) {
     int i;
     void *data;
     unsigned int offset;
     char local_buf[size];
     
 
-
-    pcilib_detect_address(handle, &bar, &addr, size);
-    data = pcilib_map_bar(handle, bar);
+    pcilib_detect_address(ctx, &bar, &addr, size);
+    data = pcilib_map_bar(ctx, bar);
 
 /*
     for (i = 0; i < size/4; i++)  {
@@ -156,35 +183,262 @@ int pcilib_read(void *buf, int handle, int bar, unsigned long addr, int size) {
 
     pcilib_memcpy(buf, data + addr, size);
     
-    pcilib_unmap_bar(handle, bar, data);    
+    pcilib_unmap_bar(ctx, bar, data);    
 }
 
-int pcilib_write(void *buf, int handle, int bar, unsigned long addr, int size) {
+int pcilib_write(pcilib_t *ctx, pcilib_bar_t bar, uintptr_t addr, size_t size, void *buf) {
     int i;
     void *data;
     unsigned int offset;
     char local_buf[size];
     
 
-    pcilib_detect_address(handle, &bar, &addr, size);
-    data = pcilib_map_bar(handle, bar);
+    pcilib_detect_address(ctx, &bar, &addr, size);
+    data = pcilib_map_bar(ctx, bar);
 
     pcilib_memcpy(data + addr, buf, size);
     
-    pcilib_unmap_bar(handle, bar, data);    
+    pcilib_unmap_bar(ctx, bar, data);    
 }
 
 
-int pcilib_find_register(pcilib_model_t model, const char *reg) {
-    int i;
-
-    pcilib_register_t *registers =  pcilib_model_description[model].registers;
+    // FIXME create hash during map_register space
+pcilib_register_t pcilib_find_register(pcilib_t *ctx, const char *reg) {
+    pcilib_register_t i;
     
-    for (i = 0; registers[i].size; i++) {
+    pcilib_model_t model = pcilib_get_model(ctx);
+    
+    pcilib_register_description_t *registers =  pcilib_model[model].registers;
+    
+    for (i = 0; registers[i].bits; i++) {
 	if (!strcasecmp(registers[i].name, reg)) return i;
     }
     
     return -1;
 };
 
+static pcilib_register_bank_t pcilib_find_bank(pcilib_t *ctx, pcilib_register_bank_addr_t bank) {
+    pcilib_register_bank_t i;
+    pcilib_register_bank_description_t *banks = pcilib_model[ctx->model].banks;
+
+    for (i = 0; banks[i].access; i++)
+	if (banks[i].addr == bank) return i;
+	
+    return -1;
+}
+
+
+static int pcilib_map_register_space(pcilib_t *ctx) {
+    if (!ctx->reg_space)  {
+	pcilib_register_bank_description_t *banks = pcilib_model[ctx->model].banks;
+
+	if ((banks)&&(banks[0].access)) {
+	    void *reg_space;
+	    
+	    uintptr_t addr = banks[0].read_addr;
+	    pcilib_bar_t bar = PCILIB_BAR_DETECT;
+	    
+	    pcilib_detect_address(ctx, &bar, &addr, 1);
+	    reg_space = pcilib_map_bar(ctx, bar);
+
+	    uint32_t buf[2];
+	    pcilib_memcpy(&buf, reg_space, 8);
+	    
+	    if (reg_space) {
+	        ctx->reg_bar = bar;
+		ctx->reg_space = reg_space;
+
+		return 0;
+	    }
+	}
+	
+	return -1;
+    }
+    
+    return 0;
+}
+	    
+	
+static void pcilib_unmap_register_space(pcilib_t *ctx) {
+    if (ctx->reg_space) {
+	pcilib_unmap_bar(ctx, ctx->reg_bar, ctx->reg_space);
+	ctx->reg_space = NULL;
+    }
+}
+
+char  *pcilib_resolve_register_address(pcilib_t *ctx, uintptr_t addr) {
+    size_t offset = addr - ctx->board_info.bar_start[ctx->reg_bar];
+    if (offset < ctx->board_info.bar_length[ctx->reg_bar]) {
+	return ctx->reg_space + offset + (ctx->board_info.bar_start[ctx->reg_bar] & ctx->page_mask);
+    }
+    return NULL;
+}
+
+
+void pcilib_close(pcilib_t *ctx) {
+    if (ctx) {
+	if (ctx->reg_space) pcilib_unmap_register_space(ctx);
+	close(ctx->handle);
+	free(ctx);
+    }
+}
+
+
+
+
+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) {
+    int err;
+    int rest;
+    size_t i;
+    
+    pcilib_register_bank_description_t *b = pcilib_model[ctx->model].banks + bank;
+
+    assert(bits < 8 * sizeof(pcilib_register_value_t));
+
+    err = pcilib_map_register_space(ctx);
+    if (err) {
+	pcilib_error("Failed to map the register space");
+	return err;
+    }
+    
+    //n += bits / b->access;
+    //bits %= b->access; 
+    
+    for (i = 0; i < n; i++) {
+	err = pcilib_protocol[b->protocol].read(ctx, b, addr + i, b->access, buf + i);
+	if (err) break;
+    }
+    
+    if ((bits > 0)&&(!err)) err = pcilib_protocol[b->protocol].read(ctx, b, addr + n, bits, buf + n);
+    
+    return err;
+}
+
+int pcilib_read_register_space(pcilib_t *ctx, pcilib_register_bank_addr_t bank_addr, pcilib_register_addr_t addr, size_t n, pcilib_register_value_t *buf) {
+    pcilib_register_bank_t bank = pcilib_find_bank(ctx, bank_addr);
+    return pcilib_read_register_space_internal(ctx, bank, addr, n, 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;
+    pcilib_register_value_t res;
+    pcilib_register_description_t *r;
+    pcilib_register_bank_description_t *b;
+
+    r = pcilib_model[ctx->model].registers + reg;
+    b = pcilib_model[ctx->model].banks + r->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);
+
+    if (b->endianess) {
+	pcilib_error("Big-endian byte order support is not implemented");
+	return PCILIB_ERROR_NOTSUPPORTED;
+    } else {
+	res = 0;
+	if (bits) ++n;
+	for (i = 0; i < n; i++) {
+	    res |= buf[i] << (i * b->access);
+	}
+    }
+    
+    *value = res;
+    
+    return err;
+}
+
+
+int pcilib_read_register(pcilib_t *ctx, const char *regname, pcilib_register_value_t *value) {
+    int err;
+    int reg;
+    
+    reg = pcilib_find_register(ctx, regname);
+    if (reg < 0) {
+	pcilib_error("Register (%s) is not found", regname);
+	return PCILIB_ERROR_NOTFOUND;
+    }
+    
+    return pcilib_read_register_by_id(ctx, reg, value);
+
+//    registers[reg].bank
+//    printf("%li %li", sizeof(pcilib_model[ctx->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) {
+    int err;
+    int rest;
+    size_t i;
+    
+    pcilib_register_bank_description_t *b = pcilib_model[ctx->model].banks + bank;
+
+    assert(bits < 8 * sizeof(pcilib_register_value_t));
+
+    err = pcilib_map_register_space(ctx);
+    if (err) {
+	pcilib_error("Failed to map the register space");
+	return err;
+    }
+    
+    //n += bits / b->access;
+    //bits %= b->access; 
+    
+    for (i = 0; i < n; i++) {
+	err = pcilib_protocol[b->protocol].write(ctx, b, addr + i, b->access, buf[i]);
+	if (err) break;
+    }
+    
+    if ((bits > 0)&&(!err)) err = pcilib_protocol[b->protocol].write(ctx, b, addr + n, bits, buf[n]);
+    
+    return err;
+}
+
+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;
+    pcilib_register_value_t res;
+    pcilib_register_description_t *r;
+    pcilib_register_bank_description_t *b;
+
+    r = pcilib_model[ctx->model].registers + reg;
+    b = pcilib_model[ctx->model].banks + r->bank;
+    
+    n = r->bits / b->access;
+    bits = r->bits % b->access; 
+
+    pcilib_register_value_t buf[n + 1];
+    memset(buf, 0, (n + 1) * sizeof(pcilib_register_value_t));
+    
+    if (b->endianess) {
+	pcilib_error("Big-endian byte order support is not implemented");
+	return PCILIB_ERROR_NOTSUPPORTED;
+    } else {
+	for (i = 0, res = value; (res > 0)&&(i <= n); ++i) {
+	    buf[i] = res & BIT_MASK(b->access);
+	    res >>= b->access;
+	}
+	
+	if (res) {
+	    pcilib_error("Value %i is to big to fit in the register %s", value, r->name);
+	    return PCILIB_ERROR_OUTOFRANGE;
+	}
+    }
+    
+    err = pcilib_write_register_space_internal(ctx, r->bank, r->addr, n, bits, buf);
+    return err;
+}
+
+int pcilib_write_register(pcilib_t *ctx, const char *regname, pcilib_register_value_t value) {
+    int err;
+    int reg;
+    
+    reg = pcilib_find_register(ctx, regname);
+    if (reg < 0) pcilib_error("Register (%s) is not found", regname);
+
+    return pcilib_write_register_by_id(ctx, reg, value);
+}
 

+ 84 - 28
pci.h

@@ -2,80 +2,136 @@
 #define _PCITOOL_PCI_H
 
 #define PCILIB_MAX_BANKS 6
+#define PCILIB_REGISTER_TIMEOUT 10000		/**< us */
 
 #include <stdint.h>
 
 #include "driver/pciDriver.h"
 #include "kernel.h"
 
-#define pcilib_memcpy memcpy32
+#define pcilib_memcpy pcilib_memcpy32
+#define pcilib_datacpy pcilib_datacpy32
+
+typedef struct pcilib_s pcilib_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 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 */
+typedef uint32_t pcilib_register_value_t;	/**< Type holding the register value */
+
+typedef enum {
+    PCILIB_LITTLE_ENDIAN = 0,
+    PCILIB_BIG_ENDIAN
+} pcilib_endianess_t;
 
 typedef enum {
+    PCILIB_MODEL_DETECT,
     PCILIB_MODEL_PCI,
     PCILIB_MODEL_IPECAMERA
 } pcilib_model_t;
 
-
 typedef enum {
     PCILIB_REGISTER_R = 1,
     PCILIB_REGISTER_W = 2,
     PCILIB_REGISTER_RW = 3
 } pcilib_register_mode_t;
 
+
 typedef enum {
     IPECAMERA_REGISTER_PROTOCOL
 } pcilib_register_protocol_t;
 
-typedef struct {
-    uint8_t id;
-    uint8_t size;
-    uint32_t defvalue;
-    pcilib_register_mode_t mode;
+#define PCILIB_BAR_DETECT 		((pcilib_bar_t)-1)
+#define PCILIB_REGISTER_INVALID		((pcilib_register_t)-1)
+#define PCILIB_ADDRESS_INVALID		((uintptr_t)-1)
+#define PCILIB_REGISTER_BANK0 		0
 
-    const char *name;
+typedef struct {
+    pcilib_register_bank_addr_t addr;
     
     pcilib_register_protocol_t protocol;
-    uint64_t read_addr;
-    uint64_t write_addr;
 
+    uintptr_t read_addr;
+    uintptr_t write_addr;
+    uint8_t raw_endianess;
+
+    uint8_t access;
+    uint8_t endianess;
+} pcilib_register_bank_description_t;
+
+typedef struct {
+    pcilib_register_addr_t addr;
+    pcilib_register_size_t bits;
+    pcilib_register_value_t defvalue;
+    pcilib_register_mode_t mode;
+
+    pcilib_register_bank_t bank;
+    
+    const char *name;
     const char *description;
-} pcilib_register_t;
+} pcilib_register_description_t;
 
+/**
+  * Default mappings
+  */
 typedef struct {
-    uint32_t start;
-    uint32_t end;
+    uintptr_t start;
+    uintptr_t end;
+    pcilib_register_bank_t bank;
 } pcilib_register_range_t;
 
+typedef struct {
+    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);
+} pcilib_protocol_description_t;
+
 #include "ipecamera.h"
 
 typedef struct {
-    pcilib_register_t *registers;
+    pcilib_register_description_t *registers;
+    pcilib_register_bank_description_t *banks;
     pcilib_register_range_t *ranges;
 } pcilib_model_description_t;
 
 #ifdef _PCILIB_PCI_C
-pcilib_model_description_t pcilib_model_description[2] = {
-    { NULL, NULL },
-    { ipecamera_registers, ipecamera_register_range }
+pcilib_model_description_t pcilib_model[3] = {
+    { NULL, NULL, NULL },
+    { NULL, NULL, NULL },
+    { ipecamera_registers, ipecamera_register_banks, ipecamera_register_ranges }
+};
+
+pcilib_protocol_description_t pcilib_protocol[2] = {
+    { ipecamera_read, ipecamera_write },
+    { NULL, NULL }
 };
 #else
-extern pcilib_model_description_t pcilib_model_description[];
+extern void (*pcilib_error)(const char *msg, ...);
+extern void (*pcilib_warning)(const char *msg, ...);
+
+extern pcilib_model_description_t pcilib_model[];
+extern pcilib_protocol_description_t pcilib_protocol[];
 #endif /* _PCILIB_PCI_C */
 
+int pcilib_set_error_handler(void (*err)(const char *msg, ...));
+
 
-int pcilib_open(const char *device);
-void pcilib_close(int handle);
+pcilib_t *pcilib_open(const char *device, pcilib_model_t model);
+void pcilib_close(pcilib_t *ctx);
 
-int pcilib_set_error_handler(void (*err)(const char *msg, ...));
+const pci_board_info *pcilib_get_board_info(pcilib_t *ctx);
+pcilib_model_t pcilib_get_model(pcilib_t *ctx);
+
+void *pcilib_map_bar(pcilib_t *ctx, pcilib_bar_t bar);
+void pcilib_unmap_bar(pcilib_t *ctx, pcilib_bar_t bar, void *data);
 
-const pci_board_info *pcilib_get_board_info(int handle);
-pcilib_model_t pcilib_detect_model(int handle);
-void *pcilib_map_bar(int handle, int bar);
-void pcilib_unmap_bar(int handle, int bar, void *data);
+pcilib_register_t pcilib_find_register(pcilib_t *ctx, const char *reg);
+char  *pcilib_resolve_register_address(pcilib_t *ctx, uintptr_t addr);
 
-int pcilib_read(void *buf, int handle, int bar, unsigned long addr, int size);
-int pcilib_write(void *buf, int handle, int bar, unsigned long addr, int size);
+int pcilib_read(pcilib_t *ctx, pcilib_bar_t bar, uintptr_t addr, size_t size, void *buf);
+int pcilib_write(pcilib_t *ctx, pcilib_bar_t bar, uintptr_t addr, size_t size, void *buf);
 
-int pcilib_find_register(pcilib_model_t model, const char *reg);
 
 #endif /* _PCITOOL_PCI_H */

+ 79 - 11
tools.c

@@ -2,24 +2,72 @@
 #include <string.h>
 #include <unistd.h>
 #include <stdint.h>
+#include <assert.h>
+#include <arpa/inet.h>
 
-void *memcpy8(void * dst, void const * src, size_t len) {
+#include "tools.h"
+
+uint16_t pcilib_swap16(uint16_t x) {
+    return (((x<<8)&0xFFFF) | ((x>>8)&0xFFFF));
+}
+
+uint32_t pcilib_swap32(uint32_t x) {
+    return ((x & 0xFF) << 24) | \
+	((x & 0xFF00) << 8) | \
+	((x & 0xFF0000) >> 8) | \
+        ((x & 0xFF000000) >> 24); 
+}
+ 
+uint64_t pcilib_swap64(uint64_t x) {
+    return (((uint64_t)(x) << 56) | \
+        (((uint64_t)(x) << 40) & 0xff000000000000ULL) | \
+        (((uint64_t)(x) << 24) & 0xff0000000000ULL) | \
+        (((uint64_t)(x) << 8)  & 0xff00000000ULL) | \
+        (((uint64_t)(x) >> 8)  & 0xff000000ULL) | \
+        (((uint64_t)(x) >> 24) & 0xff0000ULL) | \
+        (((uint64_t)(x) >> 40) & 0xff00ULL) | \
+        ((uint64_t)(x)  >> 56));
+}
+
+void pcilib_swap(void *dst, void *src, size_t size, size_t n) {
+    int i;
+    switch (size) {
+	case 1:
+	    if (src != dst) memcpy(dst, src, n);
+	break;
+	case 2:
+	    for (i = 0; i < n; i++) {
+		((uint16_t*)dst)[i] = pcilib_swap16(((uint16_t*)src)[i]);
+	    }    
+	break;
+	case 4:
+	    for (i = 0; i < n; i++) {
+		((uint32_t*)dst)[i] = pcilib_swap32(((uint32_t*)src)[i]);
+	    }    
+	break;
+	case 8:
+	    for (i = 0; i < n; i++) {
+		((uint64_t*)dst)[i] = pcilib_swap64(((uint64_t*)src)[i]);
+	    }    
+	break;
+	default:
+	    pcilib_error("Invalid word size: %i", size);
+    }
+}
+
+void *pcilib_memcpy8(void * dst, void const * src, size_t len) {
     int i;
     for (i = 0; i < len; i++) ((char*)dst)[i] = ((char*)src)[i];
     return dst;
 }
 
-
-void *memcpy32(void * dst, void const * src, size_t len) {
+void *pcilib_memcpy32(void * dst, void const * src, size_t len) {
     uint32_t * plDst = (uint32_t *) dst;
     uint32_t const * plSrc = (uint32_t const *) src;
 
     while (len >= 4) {
-        uint32_t a = (*plSrc & 0xFF) << 24;
-        a |= (*plSrc & 0xFF00) << 8;
-        a |= (*plSrc & 0xFF0000) >> 8;
-        a |= (*plSrc & 0xFF000000) >> 24;
-        *plDst = a;
+//        *plDst = ntohl(*plSrc);
+	*plDst = *plSrc;
         plSrc++;
         plDst++;
         len -= 4;
@@ -35,7 +83,8 @@ void *memcpy32(void * dst, void const * src, size_t len) {
     return (dst);
 } 
 
-void *memcpy64(void * dst, void const * src, size_t len) {
+
+void *pcilib_memcpy64(void * dst, void const * src, size_t len) {
     uint64_t * plDst = (uint64_t *) dst;
     uint64_t const * plSrc = (uint64_t const *) src;
 
@@ -123,11 +172,30 @@ void *memcpy128(void * dst, void const * src, size_t len) {
 } 
 */
 
+void *pcilib_datacpy32(void * dst, void const * src, uint8_t size, size_t n, pcilib_endianess_t endianess) {
+    uint32_t * plDst = (uint32_t *) dst;
+    uint32_t const * plSrc = (uint32_t const *) src;
+
+    int swap = (endianess == PCILIB_BIG_ENDIAN)?(ntohs(1)!=1):(ntohs(1)==1);
+
+    assert(size == 4);	// only 32 bit at the moment
+
+    while (n > 0) {
+	if (swap) *plDst = ntohl(*plSrc);
+	else *plDst = *plSrc;
+
+        ++plSrc;
+        ++plDst;
+
+        --n;
+    }
+} 
+
 
-int get_page_mask() {
+int pcilib_get_page_mask() {
     int pagesize,pagemask,temp;
 
-    pagesize = getpagesize();
+    pagesize = sysconf(_SC_PAGESIZE);
 
     for( pagemask=0, temp = pagesize; temp != 1; ) {
 	temp = (temp >> 1);

+ 16 - 4
tools.h

@@ -1,9 +1,21 @@
 #ifndef _PCITOOL_TOOLS_H
 #define _PCITOOL_TOOLS_H
 
-void * memcpy8(void * dst, void const * src, size_t len);
-void * memcpy32(void * dst, void const * src, size_t len);
-void * memcpy64(void * dst, void const * src, size_t len);
-int get_page_mask();
+#include <stdio.h>
+#include <stdint.h>
+
+#include "pci.h"
+
+uint16_t pcilib_swap16(uint16_t x);
+uint32_t pcilib_swap32(uint32_t x);
+uint64_t pcilib_swap64(uint64_t x);
+void pcilib_swap(void *dst, void *src, size_t size, size_t n);
+
+void * pcilib_memcpy8(void * dst, void const * src, size_t len);
+void * pcilib_memcpy32(void * dst, void const * src, size_t len);
+void * pcilib_memcpy64(void * dst, void const * src, size_t len);
+void * pcilib_datacpy32(void * dst, void const * src, uint8_t size, size_t n, pcilib_endianess_t big_endian);
+
+int pcilib_get_page_mask();
 
 #endif /* _PCITOOL_TOOS_H */