From 1f39476f289cd6ac1f45da7f0d9b528b4bc9a978 Mon Sep 17 00:00:00 2001 From: "Suren A. Chilingaryan" Date: Wed, 9 Mar 2011 01:45:29 +0100 Subject: Better handling of register banks --- cli.c | 106 +++++++++++++++++++++++++++++++++++++++++++++++------------- error.h | 3 +- ipecamera.h | 4 +-- pci.c | 82 ++++++++++++++++++++++++++++++++++------------ pci.h | 15 +++++++-- 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 */ -- cgit v1.2.3