summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSuren A. Chilingaryan <csa@dside.dyndns.org>2011-03-09 01:45:29 +0100
committerSuren A. Chilingaryan <csa@dside.dyndns.org>2011-03-09 01:45:29 +0100
commit1f39476f289cd6ac1f45da7f0d9b528b4bc9a978 (patch)
tree295c7283a6e665afb01d882dba950d99ee31209b
parent7f97ea07417de4c2ea260e2860e589011c732e04 (diff)
downloadpcitool-1f39476f289cd6ac1f45da7f0d9b528b4bc9a978.tar.gz
pcitool-1f39476f289cd6ac1f45da7f0d9b528b4bc9a978.tar.bz2
pcitool-1f39476f289cd6ac1f45da7f0d9b528b4bc9a978.tar.xz
pcitool-1f39476f289cd6ac1f45da7f0d9b528b4bc9a978.zip
Better handling of register banks
-rw-r--r--cli.c106
-rw-r--r--error.h3
-rw-r--r--ipecamera.h4
-rw-r--r--pci.c82
-rw-r--r--pci.h15
5 files changed, 162 insertions, 48 deletions
diff --git a/cli.c b/cli.c
index 2215c55..3540239 100644
--- a/cli.c
+++ b/cli.c
@@ -139,8 +139,9 @@ void Error(const char *format, ...) {
}
-void List(pcilib_t *handle, pcilib_model_t model) {
+void List(pcilib_t *handle, pcilib_model_t model, const char *bank) {
int i;
+ pcilib_register_bank_description_t *banks;
pcilib_register_description_t *registers;
const pci_board_info *board_info = pcilib_get_board_info(handle);
@@ -163,13 +164,43 @@ void List(pcilib_t *handle, pcilib_model_t model) {
}
}
printf("\n");
+
+ if ((bank)&&(bank != (char*)-1)) banks = NULL;
+ else banks = pcilib_model[model].banks;
+
+ if (banks) {
+ printf("Banks: \n");
+ for (i = 0; banks[i].access; i++) {
+ printf(" 0x%02x %s", banks[i].addr, banks[i].name);
+ if ((banks[i].description)&&(banks[i].description[0])) {
+ printf(": %s", banks[i].description);
+ }
+ printf("\n");
+ }
+ printf("\n");
+ }
- registers = pcilib_model[model].registers;
+ if (bank == (char*)-1) registers = NULL;
+ else registers = pcilib_model[model].registers;
if (registers) {
- printf("Registers: \n");
+ pcilib_register_bank_addr_t bank_addr;
+ if (bank) {
+ pcilib_register_bank_t bank_id = pcilib_find_bank(handle, bank);
+ pcilib_register_bank_description_t *b = pcilib_model[model].banks + bank_id;
+
+ bank_addr = b->addr;
+ if (b->description) printf("%s:\n", b->description);
+ else if (b->name) printf("Registers of bank %s:\n", b->name);
+ else printf("Registers of bank 0x%x:\n", b->addr);
+ } else {
+ printf("Registers: \n");
+ }
for (i = 0; registers[i].bits; i++) {
const char *mode;
+
+ if ((bank)&&(registers[i].bank != bank_addr)) continue;
+
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";
@@ -190,7 +221,7 @@ 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);
- List(handle, model);
+ List(handle, model, (char*)-1);
}
@@ -341,23 +372,31 @@ int ReadData(pcilib_t *handle, pcilib_bar_t bar, uintptr_t addr, size_t n, acces
free(buf);
}
-int ReadRegister(pcilib_t *handle, pcilib_model_t model, const char *reg) {
+int ReadRegister(pcilib_t *handle, pcilib_model_t model, const char *bank, const char *reg) {
int err;
int i;
pcilib_register_value_t value;
if (reg) {
- err = pcilib_read_register(handle, reg, &value);
+ err = pcilib_read_register(handle, bank, 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;
+ pcilib_register_bank_t bank_id;
+ pcilib_register_bank_addr_t bank_addr;
+
+ pcilib_register_description_t *registers = pcilib_model[model].registers;
if (registers) {
+ if (bank) {
+ bank_id = pcilib_find_bank(handle, bank);
+ bank_addr = pcilib_model[model].banks[bank_id].addr;
+ }
+
printf("Registers:\n");
for (i = 0; registers[i].bits; i++) {
- if (registers[i].mode & PCILIB_REGISTER_R) {
+ if ((registers[i].mode & PCILIB_REGISTER_R)&&((!bank)||(registers[i].bank == bank_addr))) {
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);
@@ -371,7 +410,13 @@ int ReadRegister(pcilib_t *handle, pcilib_model_t model, const char *reg) {
}
}
-int ReadRegisterRange(pcilib_t *handle, pcilib_model_t model, uintptr_t addr, size_t n) {
+int ReadRegisterRange(pcilib_t *handle, pcilib_model_t model, const char *bank, uintptr_t addr, size_t n) {
+/* int err;
+
+ pcilib_register_bank_t bank = pcilib_find_bank(handle, bank_addr);
+ pcilib_register_value_t buf[n];
+
+ err = pcilib_read_register_space(handle, bank, addr, n, buf);*/
}
int WriteData(pcilib_t *handle, pcilib_bar_t bar, uintptr_t addr, size_t n, access_t access, int endianess, char ** data) {
@@ -409,10 +454,10 @@ int WriteData(pcilib_t *handle, pcilib_bar_t bar, uintptr_t addr, size_t n, acce
free(buf);
}
-int WriteRegisterRange(pcilib_t *handle, pcilib_model_t model, uintptr_t addr, size_t n, char ** data) {
+int WriteRegisterRange(pcilib_t *handle, pcilib_model_t model, const char *bank, uintptr_t addr, size_t n, char ** data) {
}
-int WriteRegister(pcilib_t *handle, pcilib_model_t model, const char *reg, char ** data) {
+int WriteRegister(pcilib_t *handle, pcilib_model_t model, const char *bank, const char *reg, char ** data) {
int err;
int i;
@@ -425,10 +470,10 @@ int WriteRegister(pcilib_t *handle, pcilib_model_t model, const char *reg, char
value = val;
- err = pcilib_write_register(handle, reg, value);
+ err = pcilib_write_register(handle, bank, reg, value);
if (err) Error("Error writting register %s\n", reg);
- err = pcilib_read_register(handle, reg, &value);
+ err = pcilib_read_register(handle, bank, reg, &value);
if (err) Error("Error reading back register %s for verification\n", reg);
if (val != value) {
@@ -452,6 +497,7 @@ int main(int argc, char **argv) {
pcilib_bar_t bar = PCILIB_BAR_DETECT;
const char *addr = NULL;
const char *reg = NULL;
+ const char *bank = NULL;
uintptr_t start = -1;
size_t size = 1;
access_t access = 4;
@@ -504,8 +550,9 @@ int main(int argc, char **argv) {
else Usage(argc, argv, "Invalid memory model (%s) is specified", optarg);\
break;
case OPT_BAR:
- 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;
+ bank = 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, "%li", &itmp) != 1) access = 0;
@@ -563,7 +610,6 @@ int main(int argc, char **argv) {
default:
if (argc > optind) Usage(argc, argv, "Invalid non-option parameters are supplied");
}
-
if (addr) {
if (sscanf(addr, "%lx", &start) == 1) {
@@ -576,7 +622,7 @@ int main(int argc, char **argv) {
// register access in plain mode
if (ranges[i].start != ranges[i].end) ++mode;
} else {
- if (pcilib_find_register(handle, addr) == PCILIB_REGISTER_INVALID) {
+ if (pcilib_find_register(handle, bank, addr) == PCILIB_REGISTER_INVALID) {
Usage(argc, argv, "Invalid address (%s) is specified", addr);
} else {
reg = addr;
@@ -584,14 +630,28 @@ int main(int argc, char **argv) {
}
}
}
-
+ if (bank) {
+ switch (mode) {
+ case MODE_BENCHMARK:
+ case MODE_READ:
+ case MODE_WRITE:
+ if ((sscanf(bank,"%li", &itmp) != 1)||(itmp < 0)||(itmp >= PCILIB_MAX_BANKS))
+ Usage(argc, argv, "Invalid data bank (%s) is specified", bank);
+ else bar = itmp;
+ break;
+ default:
+ if (pcilib_find_bank(handle, bank) == PCILIB_REGISTER_BANK_INVALID)
+ Usage(argc, argv, "Invalid data bank (%s) is specified", bank);
+ }
+ }
+
switch (mode) {
case MODE_INFO:
Info(handle, model);
break;
case MODE_LIST:
- List(handle, model);
+ List(handle, model, bank);
break;
case MODE_BENCHMARK:
Benchmark(handle, bar);
@@ -604,15 +664,15 @@ int main(int argc, char **argv) {
}
break;
case MODE_READ_REGISTER:
- if ((reg)||(!addr)) ReadRegister(handle, model, reg);
- else ReadRegisterRange(handle, model, start, size);
+ if ((reg)||(!addr)) ReadRegister(handle, model, bank, reg);
+ else ReadRegisterRange(handle, model, bank, start, size);
break;
case MODE_WRITE:
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, start, size, argv + optind);
+ if (reg) WriteRegister(handle, model, bank, reg, argv + optind);
+ else WriteRegisterRange(handle, model, bank, start, size, argv + optind);
break;
}
diff --git a/error.h b/error.h
index 59cedef..715b6eb 100644
--- a/error.h
+++ b/error.h
@@ -4,12 +4,13 @@
enum {
PCILIB_ERROR_SUCCESS = 0,
PCILIB_ERROR_INVALID_ADDRESS,
+ PCILIB_ERROR_INVALID_BANK,
PCILIB_ERROR_TIMEOUT,
PCILIB_ERROR_FAILED,
PCILIB_ERROR_VERIFY,
PCILIB_ERROR_NOTSUPPORTED,
PCILIB_ERROR_NOTFOUND,
- PCILIB_ERROR_OUTOFRANGE
+ PCILIB_ERROR_OUTOFRANGE,
} pcilib_errot_t;
diff --git a/ipecamera.h b/ipecamera.h
index 0c5b518..d3657e0 100644
--- a/ipecamera.h
+++ b/ipecamera.h
@@ -12,8 +12,8 @@
#ifdef _IPECAMERA_C
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_BANK0, 128, IPECAMERA_REGISTER_PROTOCOL, IPECAMERA_REGISTER_READ, IPECAMERA_REGISTER_WRITE, PCILIB_BIG_ENDIAN, 8, PCILIB_LITTLE_ENDIAN, "cmosis", "CMOSIS CMV2000 Registers" },
+ { 0, 0, 0, 0, 0, 0, NULL, NULL }
};
pcilib_register_description_t ipecamera_registers[] = {
diff --git a/pci.c b/pci.c
index af3fc72..48cc318 100644
--- a/pci.c
+++ b/pci.c
@@ -202,30 +202,65 @@ int pcilib_write(pcilib_t *ctx, pcilib_bar_t bar, uintptr_t addr, size_t size, v
}
+static pcilib_register_bank_t pcilib_find_bank_by_addr(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 pcilib_register_bank_t pcilib_find_bank_by_name(pcilib_t *ctx, const char *bankname) {
+ pcilib_register_bank_t i;
+ pcilib_register_bank_description_t *banks = pcilib_model[ctx->model].banks;
+
+ for (i = 0; banks[i].access; i++)
+ if (!strcasecmp(banks[i].name, bankname)) return i;
+
+ return -1;
+}
+
+pcilib_register_bank_t pcilib_find_bank(pcilib_t *ctx, const char *bank) {
+ pcilib_register_bank_t res;
+ unsigned long addr;
+
+ if (sscanf(bank,"%lx", &addr) == 1) {
+ res = pcilib_find_bank_by_addr(ctx, addr);
+ if (res != PCILIB_REGISTER_BANK_INVALID) return res;
+ }
+
+ return pcilib_find_bank_by_name(ctx, bank);
+}
+
// FIXME create hash during map_register space
-pcilib_register_t pcilib_find_register(pcilib_t *ctx, const char *reg) {
+pcilib_register_t pcilib_find_register(pcilib_t *ctx, const char *bank, const char *reg) {
pcilib_register_t i;
+ pcilib_register_bank_t bank_id;
+ pcilib_register_bank_addr_t bank_addr;
pcilib_model_t model = pcilib_get_model(ctx);
pcilib_register_description_t *registers = pcilib_model[model].registers;
+ if (bank) {
+ bank_id = pcilib_find_bank(ctx, bank);
+ if (bank_id == PCILIB_REGISTER_BANK_INVALID) {
+ pcilib_error("Invalid bank (%s) is specified", bank);
+ return -1;
+ }
+
+ bank_addr = pcilib_model[ctx->model].banks[bank_id].addr;
+ }
+
for (i = 0; registers[i].bits; i++) {
- if (!strcasecmp(registers[i].name, reg)) return i;
+ if ((!strcasecmp(registers[i].name, reg))&&((!bank)||(registers[i].bank == bank_addr))) 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) {
@@ -283,9 +318,6 @@ void pcilib_close(pcilib_t *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;
@@ -294,6 +326,11 @@ static int pcilib_read_register_space_internal(pcilib_t *ctx, pcilib_register_ba
pcilib_register_bank_description_t *b = pcilib_model[ctx->model].banks + bank;
assert(bits < 8 * sizeof(pcilib_register_value_t));
+
+ if (((addr + n) > b->size)||(((addr + n) == b->size)&&(bits))) {
+ pcilib_error("Accessing sregister (%u regs at addr %u) out of register space (%u registers total)", bits?(n+1):n, addr, b->size);
+ return PCILIB_ERROR_OUTOFRANGE;
+ }
err = pcilib_map_register_space(ctx);
if (err) {
@@ -314,8 +351,8 @@ static int pcilib_read_register_space_internal(pcilib_t *ctx, pcilib_register_ba
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);
+int pcilib_read_register_space(pcilib_t *ctx, pcilib_register_bank_t bank, 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);
}
@@ -352,11 +389,11 @@ int pcilib_read_register_by_id(pcilib_t *ctx, pcilib_register_t reg, pcilib_regi
}
-int pcilib_read_register(pcilib_t *ctx, const char *regname, pcilib_register_value_t *value) {
+int pcilib_read_register(pcilib_t *ctx, const char *bank, const char *regname, pcilib_register_value_t *value) {
int err;
int reg;
- reg = pcilib_find_register(ctx, regname);
+ reg = pcilib_find_register(ctx, bank, regname);
if (reg < 0) {
pcilib_error("Register (%s) is not found", regname);
return PCILIB_ERROR_NOTFOUND;
@@ -378,6 +415,11 @@ static int pcilib_write_register_space_internal(pcilib_t *ctx, pcilib_register_b
assert(bits < 8 * sizeof(pcilib_register_value_t));
+ if (((addr + n) > b->size)||(((addr + n) == b->size)&&(bits))) {
+ pcilib_error("Accessing sregister (%u regs at addr %u) out of register space (%u registers total)", bits?(n+1):n, addr, b->size);
+ return PCILIB_ERROR_OUTOFRANGE;
+ }
+
err = pcilib_map_register_space(ctx);
if (err) {
pcilib_error("Failed to map the register space");
@@ -432,11 +474,11 @@ int pcilib_write_register_by_id(pcilib_t *ctx, pcilib_register_t reg, pcilib_reg
return err;
}
-int pcilib_write_register(pcilib_t *ctx, const char *regname, pcilib_register_value_t value) {
+int pcilib_write_register(pcilib_t *ctx, const char *bank, const char *regname, pcilib_register_value_t value) {
int err;
int reg;
- reg = pcilib_find_register(ctx, regname);
+ reg = pcilib_find_register(ctx, bank, 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 cda7628..c4b2298 100644
--- a/pci.h
+++ b/pci.h
@@ -47,10 +47,12 @@ typedef enum {
#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_BANK_INVALID ((pcilib_register_bank_t)-1)
#define PCILIB_REGISTER_BANK0 0
typedef struct {
pcilib_register_bank_addr_t addr;
+ size_t size;
pcilib_register_protocol_t protocol;
@@ -60,6 +62,9 @@ typedef struct {
uint8_t access;
uint8_t endianess;
+
+ const char *name;
+ const char *description;
} pcilib_register_bank_description_t;
typedef struct {
@@ -126,12 +131,18 @@ 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);
-
-pcilib_register_t pcilib_find_register(pcilib_t *ctx, const char *reg);
char *pcilib_resolve_register_address(pcilib_t *ctx, uintptr_t addr);
+pcilib_register_bank_t pcilib_find_bank(pcilib_t *ctx, const char *bank);
+pcilib_register_t pcilib_find_register(pcilib_t *ctx, const char *bank, const char *reg);
+
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_read_register_by_id(pcilib_t *ctx, pcilib_register_t reg, pcilib_register_value_t *value);
+int pcilib_write_register_by_id(pcilib_t *ctx, pcilib_register_t reg, pcilib_register_value_t value);
+
+int pcilib_read_register(pcilib_t *ctx, const char *bank, const char *regname, pcilib_register_value_t *value);
+int pcilib_write_register(pcilib_t *ctx, const char *bank, const char *regname, pcilib_register_value_t value);
#endif /* _PCITOOL_PCI_H */