From: Damien Lespiau <damien.lespiau at intel.com> >From time to time, one would like to decode a register value that have been captured at a certain point in time (and say printed out with a printk). intel_reg_dumper has all the knowledge to do that and this patch adds a -r option to use the tool in that mode. Example usage: $ ./tools/intel_reg_dumper -r PCH_PP_CONTROL 0xabcd0002 PCH_PP_CONTROL: 0xabcd0002 (blacklight disabled, power... Signed-off-by: Damien Lespiau <damien.lespiau at intel.com> --- tools/intel_reg_dumper.c | 102 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 88 insertions(+), 14 deletions(-) diff --git a/tools/intel_reg_dumper.c b/tools/intel_reg_dumper.c index b49d967..88d7216 100644 --- a/tools/intel_reg_dumper.c +++ b/tools/intel_reg_dumper.c @@ -1911,26 +1911,33 @@ static struct reg_debug i945gm_mi_regs[] = { DEFINEREG(ECOSKPD), }; +static void +_intel_dump_reg(struct reg_debug *reg, uint32_t val) +{ + char debug[1024]; + + if (reg->debug_output != NULL) { + reg->debug_output(debug, sizeof(debug), reg->reg, val); + printf("%30.30s: 0x%08x (%s)\n", + reg->name, + (unsigned int)val, debug); + } else { + printf("%30.30s: 0x%08x\n", reg->name, + (unsigned int)val); + } +} + #define intel_dump_regs(regs) _intel_dump_regs(regs, ARRAY_SIZE(regs)) static void _intel_dump_regs(struct reg_debug *regs, int count) { - char debug[1024]; int i; for (i = 0; i < count; i++) { uint32_t val = INREG(regs[i].reg); - if (regs[i].debug_output != NULL) { - regs[i].debug_output(debug, sizeof(debug), regs[i].reg, val); - printf("%30.30s: 0x%08x (%s)\n", - regs[i].name, - (unsigned int)val, debug); - } else { - printf("%30.30s: 0x%08x\n", regs[i].name, - (unsigned int)val); - } + _intel_dump_reg(®s[i], val); } } @@ -1964,6 +1971,54 @@ static struct reg_debug gen6_rp_debug_regs[] = { DEFINEREG(GEN6_PMINTRMSK), }; +#define DECLARE_REGS(r) { .regs = r, .count = ARRAY_SIZE(r) } +static struct { + struct reg_debug *regs; + int count; +}known_registers[] = { + DECLARE_REGS(ironlake_debug_regs), + DECLARE_REGS(i945gm_mi_regs), + DECLARE_REGS(intel_debug_regs), + DECLARE_REGS(gen6_rp_debug_regs), + DECLARE_REGS(haswell_debug_regs) +}; +#undef DECLARE_REGS + +static struct reg_debug * +find_register_by_name(struct reg_debug *regs, int count, + const char *name) +{ + int i; + + for (i = 0; i < count; i++) + if (strcmp(name, regs[i].name) == 0) + return ®s[i]; + + return NULL; +} + +static void +decode_register(const char *name, uint32_t val) +{ + int i; + struct reg_debug *reg = NULL; + + for (i = 0; i < ARRAY_SIZE(known_registers); i++) { + reg = find_register_by_name(known_registers[i].regs, + known_registers[i].count, + name); + if (reg) + break; + } + + if (!reg) { + fprintf(stderr, "Unknown register: %s\n", name); + return; + } + + _intel_dump_reg(reg, val); +} + static void intel_dump_other_regs(void) { @@ -2171,10 +2226,11 @@ intel_dump_other_regs(void) static void print_usage(void) { - printf("Usage: intel_reg_dumper [options] [file]\n" + printf("Usage: intel_reg_dumper [options] [file|value]\n" "Options:\n" " -d id when a dump file is used, use 'id' as device id (in " "hex)\n" + " -r name name of the register to decode\n" " -h prints this help\n"); } @@ -2182,13 +2238,17 @@ int main(int argc, char** argv) { struct pci_device *pci_dev; int opt; - char *file = NULL; + char *reg_name = NULL; + char *arg = NULL, *file = NULL; - while ((opt = getopt(argc, argv, "d:h")) != -1) { + while ((opt = getopt(argc, argv, "d:r:h")) != -1) { switch (opt) { case 'd': devid = strtol(optarg, NULL, 16); break; + case 'r': + reg_name = optarg; + break; case 'h': print_usage(); return 0; @@ -2198,8 +2258,22 @@ int main(int argc, char** argv) } } if (optind < argc) - file = argv[optind]; + arg = argv[optind]; + + if (reg_name && !arg) { + fprintf (stderr, "-r needs a value to decode\n"); + return 2; + } + + /* the tool operates in "single" mode, decode a single register given + * on the command line: -r PCH_PP_CONTROL 0xabcd0002 */ + if (reg_name) { + uint32_t reg_val = strtoul(arg, NULL, 0); + decode_register(reg_name, reg_val); + return 0; + } + file = arg; if (file) { intel_map_file(file); if (devid) { -- 1.7.11.4