summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSuren A. Chilingaryan <csa@dside.dyndns.org>2011-03-08 22:46:14 +0100
committerSuren A. Chilingaryan <csa@dside.dyndns.org>2011-03-08 22:46:14 +0100
commit7f97ea07417de4c2ea260e2860e589011c732e04 (patch)
tree5e5dd32f4615a40990f8daf10a96f82f39ca3b83
parent8a33c993a5771b041b67c365378ac40f76365da7 (diff)
downloadipecamera-7f97ea07417de4c2ea260e2860e589011c732e04.tar.gz
ipecamera-7f97ea07417de4c2ea260e2860e589011c732e04.tar.bz2
ipecamera-7f97ea07417de4c2ea260e2860e589011c732e04.tar.xz
ipecamera-7f97ea07417de4c2ea260e2860e589011c732e04.zip
Initial support of IPECamera protocol
-rw-r--r--cli.c198
-rw-r--r--common.mk2
-rw-r--r--error.h16
-rw-r--r--ipecamera.c153
-rw-r--r--ipecamera.h115
-rw-r--r--pci.c394
-rw-r--r--pci.h112
-rw-r--r--tools.c90
-rw-r--r--tools.h20
9 files changed, 854 insertions, 246 deletions
diff --git a/cli.c b/cli.c
index adf0f4b..2215c55 100644
--- a/cli.c
+++ b/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;
}
diff --git a/common.mk b/common.mk
index ee58558..f8dae8b 100644
--- a/common.mk
+++ b/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)
diff --git a/error.h b/error.h
new file mode 100644
index 0000000..59cedef
--- /dev/null
+++ b/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 */
diff --git a/ipecamera.c b/ipecamera.c
index b51a2f8..81cf7d7 100644
--- a/ipecamera.c
+++ b/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;
+}
diff --git a/ipecamera.h b/ipecamera.h
index 51c99d9..0c5b518 100644
--- a/ipecamera.h
+++ b/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 */
diff --git a/pci.c b/pci.c
index dfcdaf7..af3fc72 100644
--- a/pci.c
+++ b/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);
+}
diff --git a/pci.h b/pci.h
index 306892f..cda7628 100644
--- a/pci.h
+++ b/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 */
diff --git a/tools.c b/tools.c
index 4ca3730..838172d 100644
--- a/tools.c
+++ b/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);
diff --git a/tools.h b/tools.h
index 718d8df..059675a 100644
--- a/tools.h
+++ b/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 */