diff options
author | Suren A. Chilingaryan <csa@suren.me> | 2015-10-18 03:47:47 +0200 |
---|---|---|
committer | Suren A. Chilingaryan <csa@suren.me> | 2015-10-18 03:47:47 +0200 |
commit | c8628b2a715a7cfaaccbd7e403cd1c6c76b918cd (patch) | |
tree | 53971a137e5d0e32ad7219f1d2fd01559c0a6ff3 /pcitool | |
parent | 2e9457b666a303fab83aa17e33624f39de9a1dd7 (diff) | |
download | pcitool-c8628b2a715a7cfaaccbd7e403cd1c6c76b918cd.tar.gz pcitool-c8628b2a715a7cfaaccbd7e403cd1c6c76b918cd.tar.bz2 pcitool-c8628b2a715a7cfaaccbd7e403cd1c6c76b918cd.tar.xz pcitool-c8628b2a715a7cfaaccbd7e403cd1c6c76b918cd.zip |
Support properties of arbitrary type
Diffstat (limited to 'pcitool')
-rw-r--r-- | pcitool/cli.c | 210 |
1 files changed, 172 insertions, 38 deletions
diff --git a/pcitool/cli.c b/pcitool/cli.c index 867b65e..2956306 100644 --- a/pcitool/cli.c +++ b/pcitool/cli.c @@ -77,8 +77,10 @@ typedef enum { MODE_BENCHMARK, MODE_READ, MODE_READ_REGISTER, + MODE_READ_PROPERTY, MODE_WRITE, MODE_WRITE_REGISTER, + MODE_WRITE_PROPERTY, MODE_RESET, MODE_GRAB, MODE_START_DMA, @@ -193,7 +195,7 @@ static struct option long_options[] = { {"timeout", required_argument, 0, OPT_TIMEOUT }, {"iterations", required_argument, 0, OPT_ITERATIONS }, {"info", optional_argument, 0, OPT_INFO }, - {"list", no_argument, 0, OPT_LIST }, + {"list", optional_argument, 0, OPT_LIST }, {"reset", no_argument, 0, OPT_RESET }, {"benchmark", optional_argument, 0, OPT_BENCHMARK }, {"read", optional_argument, 0, OPT_READ }, @@ -258,7 +260,7 @@ void Usage(int argc, char *argv[], const char *format, ...) { " %s <mode> [options] [hex data]\n" " Modes:\n" " -i [target] - Device or Register (target) Info\n" -" -l[l] - List (detailed) Data Banks & Registers\n" +" -l[l] [bank|/branch] - List (detailed) Data Banks & Registers\n" " -r <addr|dmaX|reg[/unit]> - Read Data/Register\n" " -w <addr|dmaX|reg[/unit]> - Write Data/Register\n" " --benchmark <barX|dmaX> - Performance Evaluation\n" @@ -406,6 +408,79 @@ int RegisterCompare(const void *aptr, const void *bptr, void *registers) { return 0; } +void ListProperties(pcilib_t *handle, const char *branch, int details) { + int i; + pcilib_property_info_t *props; + + props = pcilib_get_property_list(handle, branch, 0); + if (!props) Error("Error getting properties"); + + if (props[0].path) { + printf("Properties: \n"); + + for (i = 0; props[i].path; i++) { + const char *mode; + const char *type; + + switch (props[i].type) { + case PCILIB_TYPE_LONG: + type = "int "; + break; + case PCILIB_TYPE_DOUBLE: + type = "float "; + break; + case PCILIB_TYPE_STRING: + type = "string "; + break; + case PCILIB_TYPE_INVALID: + type = NULL; + break; + default: + type = "unknown"; + } + + switch (props[i].mode) { + case PCILIB_ACCESS_RW: + mode = "RW"; + break; + case PCILIB_ACCESS_R: + mode = "R "; + break; + case PCILIB_ACCESS_W: + mode = "W "; + break; + default: + mode = " "; + } + + if (type) + printf(" (%s %s) ", type, mode); + else + printf(" %12s", ""); + + if (props[i].flags&PCILIB_LIST_FLAG_CHILDS) + printf(" + "); + else + printf(" "); + + if (details > 0) { + printf("%s", props[i].name); + if ((props[i].description)&&(props[i].description[0])) { + printf(": %s", props[i].description); + } + } else { + printf("%s", props[i].path); + } + printf("\n"); + } + + printf("\n"); + + pcilib_free_property_info(handle, props); + } + +} + void List(pcilib_t *handle, const pcilib_model_description_t *model_info, const char *bank, int details) { int i, j, k; const pcilib_register_bank_description_t *banks; @@ -415,7 +490,7 @@ void List(pcilib_t *handle, const pcilib_model_description_t *model_info, const const pcilib_board_info_t *board_info = pcilib_get_board_info(handle); const pcilib_dma_description_t *dma_info = pcilib_get_dma_description(handle); - + for (i = 0; i < PCILIB_MAX_BARS; i++) { if (board_info->bar_length[i] > 0) { printf(" BAR %d - ", i); @@ -470,7 +545,7 @@ void List(pcilib_t *handle, const pcilib_model_description_t *model_info, const if ((bank)&&(bank != (char*)-1)) banks = NULL; else banks = model_info->banks; - + if (banks) { printf("Banks: \n"); for (i = 0; banks[i].access; i++) { @@ -543,6 +618,8 @@ void List(pcilib_t *handle, const pcilib_model_description_t *model_info, const printf("\n"); } + ListProperties(handle, "/", details); + if (bank == (char*)-1) events = NULL; else { events = model_info->events; @@ -1126,7 +1203,7 @@ int ReadData(pcilib_t *handle, ACCESS_MODE mode, FLAGS flags, pcilib_dma_engine_ -int ReadRegister(pcilib_t *handle, const pcilib_model_description_t *model_info, const char *bank, const char *reg, const char *unit) { +int ReadRegister(pcilib_t *handle, const pcilib_model_description_t *model_info, const char *bank, const char *reg, const char *view, const char *unit) { int i; int err; const char *format; @@ -1139,19 +1216,37 @@ int ReadRegister(pcilib_t *handle, const pcilib_model_description_t *model_info, // Adding DMA registers pcilib_get_dma_description(handle); - if (reg) { - pcilib_register_t regid = pcilib_find_register(handle, bank, reg); - - if (unit) { + if (reg||view) { + if (view) { pcilib_value_t val = {0}; - err = pcilib_read_register_view(handle, bank, reg, unit, &val); - if (err) Error("Error reading view %s of register %s", unit, reg); + if (reg) { + err = pcilib_read_register_view(handle, bank, reg, view, &val); + if (err) Error("Error reading view %s of register %s", view, reg); + } else { + err = pcilib_get_property(handle, view, &val); + if (err) Error("Error reading property %s", view); + } + if (unit) { + err = pcilib_convert_value_unit(handle, &val, unit); + if (err) { + if (reg) Error("Error converting view %s of register %s to unit %s", view, reg, unit); + else Error("Error converting property %s to unit %s", view, unit); + } + } + err = pcilib_convert_value_type(handle, &val, PCILIB_TYPE_STRING); - if (err) Error("Error converting view %s of register %s to string", unit, reg); + if (err) { + if (reg) Error("Error converting view %s of register %s to string", view); + else Error("Error converting property %s to string", view); + } - printf("%s = %s\n", reg, val.sval); + printf("%s = %s", (reg?reg:view), val.sval); + if ((val.unit)&&(strcasecmp(val.unit, "name"))) + printf(" %s", val.unit); + printf("\n"); } else { + pcilib_register_t regid = pcilib_find_register(handle, bank, reg); bank_id = pcilib_find_register_bank_by_addr(handle, model_info->registers[regid].bank); format = model_info->banks[bank_id].format; if (!format) format = "%lu"; @@ -1362,14 +1457,12 @@ int WriteRegisterRange(pcilib_t *handle, const pcilib_model_description_t *model } -int WriteRegister(pcilib_t *handle, const pcilib_model_description_t *model_info, const char *bank, const char *reg, const char *unit, char **data) { +int WriteRegister(pcilib_t *handle, const pcilib_model_description_t *model_info, const char *bank, const char *reg, const char *view, const char *unit, char **data) { int err = 0; pcilib_value_t val = {0}; pcilib_register_value_t value, verify; - pcilib_register_t regid = pcilib_find_register(handle, bank, reg); - if (regid == PCILIB_REGISTER_INVALID) Error("Can't find register (%s) from bank (%s)", reg, bank?bank:"autodetected"); /* pcilib_register_bank_t bank_id; @@ -1384,11 +1477,23 @@ int WriteRegister(pcilib_t *handle, const pcilib_model_description_t *model_info err = pcilib_set_value_from_static_string(handle, &val, *data); if (err) Error("Error (%i) setting value", err); - if (unit) { - err = pcilib_write_register_view(handle, bank, reg, unit, &val); - if (err) Error("Error writting view %s of register %s", unit, reg); - printf("%s is written\n ", reg); + if (view) { + if (unit) + val.unit = unit; + + if (reg) { + err = pcilib_write_register_view(handle, bank, reg, view, &val); + if (err) Error("Error writting view %s of register %s", view, reg); + printf("%s is written\n ", reg); + } else { + err = pcilib_set_property(handle, view, &val); + if (err) Error("Error setting property %s", view); + printf("%s is written\n ", view); + } } else { + pcilib_register_t regid = pcilib_find_register(handle, bank, reg); + if (regid == PCILIB_REGISTER_INVALID) Error("Can't find register (%s) from bank (%s)", reg, bank?bank:"autodetected"); + value = pcilib_get_value_as_register_value(handle, &val, &err); if (err) Error("Error (%i) parsing data value (%s)", *data); @@ -2758,6 +2863,7 @@ int main(int argc, char **argv) { pcilib_bar_t bar = PCILIB_BAR_DETECT; const char *addr = NULL; const char *reg = NULL; + const char *view = NULL; const char *unit = NULL; const char *bank = NULL; char **data = NULL; @@ -2767,6 +2873,7 @@ int main(int argc, char **argv) { const char *use = NULL; const char *lock = NULL; const char *info_target = NULL; + const char *list_target = NULL; size_t block = (size_t)-1; pcilib_irq_type_t irq_type = PCILIB_IRQ_TYPE_ALL; pcilib_irq_hw_source_t irq_source = PCILIB_IRQ_SOURCE_DEFAULT; @@ -2813,6 +2920,9 @@ int main(int argc, char **argv) { if (mode == MODE_LIST) details++; else if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported"); + if (optarg) list_target = optarg; + else if ((optind < argc)&&(argv[optind][0] != '-')) list_target = argv[optind++]; + mode = MODE_LIST; break; case OPT_RESET: @@ -3302,17 +3412,25 @@ int main(int argc, char **argv) { num_offset = dma_channel + 3; itmp -= 3; } - + if (bank) { if (strncmp(num_offset, bank, itmp)) Usage(argc, argv, "Conflicting DMA channels are specified in mode parameter (%s) and bank parameter (%s)", dma_channel, bank); } - + if (!isnumber_n(num_offset, itmp)) Usage(argc, argv, "Invalid DMA channel (%s) is specified", dma_channel); dma = atoi(num_offset); } break; + case MODE_LIST: + if (bank&&list_target) { + if (strcmp(list_target, bank)) + Usage(argc, argv, "Conflicting banks are specified in list parameter (%s) and bank parameter (%s)", list_target, bank); + } else if (bank) { + list_target = bank; + } + break; default: if (argc > optind) Usage(argc, argv, "Invalid non-option parameters are supplied"); } @@ -3359,24 +3477,35 @@ int main(int argc, char **argv) { } } } else { - unit = strchr(addr, '/'); - if (!unit) unit = strchr(addr, ':'); - if (unit) { - char *reg_name; - size_t reg_size = strlen(addr) - strlen(unit); - reg_name = alloca(reg_size + 1); - memcpy(reg_name, addr, reg_size); - reg_name[reg_size] = 0; - reg = reg_name; - unit++; + view = strchr(addr, '/'); + unit = strchr((view?view:addr), ':'); + + if (view||unit) { + size_t reg_size = strlen(addr) - strlen(view?view:unit); + if (reg_size) reg = strndupa(addr, reg_size); + else reg = NULL; + + if ((reg)&&(view)) view++; + if (unit) unit++; + + if (view&&unit) { + view = strndupa(view, strlen(view) - strlen(unit) - 1); + } else if ((reg)&&(unit)) { + view = unit; + unit = NULL; + } } else { reg = addr; } - if (pcilib_find_register(handle, bank, reg) == PCILIB_REGISTER_INVALID) { - Usage(argc, argv, "Invalid address (%s) is specified", addr); + if (reg) { + if (pcilib_find_register(handle, bank, reg) == PCILIB_REGISTER_INVALID) { + Usage(argc, argv, "Invalid address (%s) is specified", addr); + } else { + ++mode; + } } else { - ++mode; + mode += 2; } } } @@ -3458,7 +3587,10 @@ int main(int argc, char **argv) { Info(handle, model_info, info_target); break; case MODE_LIST: - List(handle, model_info, bank, details); + if ((list_target)&&(*list_target == '/')) + ListProperties(handle, list_target, details); + else + List(handle, model_info, list_target, details); break; case MODE_BENCHMARK: Benchmark(handle, amode, dma, bar, start, size_set?size:0, access, iterations); @@ -3475,14 +3607,16 @@ int main(int argc, char **argv) { } break; case MODE_READ_REGISTER: - if ((reg)||(!addr)) ReadRegister(handle, model_info, bank, reg, unit); + case MODE_READ_PROPERTY: + if ((reg)||(view)||(!addr)) ReadRegister(handle, model_info, bank, reg, view, unit); else ReadRegisterRange(handle, model_info, bank, start, addr_shift, size, ofile); break; case MODE_WRITE: WriteData(handle, amode, dma, bar, start, size, access, endianess, data, verify); break; case MODE_WRITE_REGISTER: - if (reg) WriteRegister(handle, model_info, bank, reg, unit, data); + case MODE_WRITE_PROPERTY: + if (reg||view) WriteRegister(handle, model_info, bank, reg, view, unit, data); else WriteRegisterRange(handle, model_info, bank, start, addr_shift, size, data); break; case MODE_RESET: |