Message ID | 1346420719-5532-1-git-send-email-damien.lespiau@gmail.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
On 2012-08-31 06:45, Damien Lespiau wrote: > From: Damien Lespiau <damien.lespiau@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 way to ask it to decode a value. > > Example usage: > > $ ./tools/intel_reg_dumper PCH_PP_CONTROL 0xabcd0002 > PCH_PP_CONTROL: 0xabcd0002 (blacklight disabled, power... > > v2: friendlier invocation (Chris Wilson) > > Signed-off-by: Damien Lespiau <damien.lespiau@intel.com> Back to my earlier complaint from the other patch... If the names don't match the docs then you forced to memorize our historically awful naming scheme. More useful to me would be to decode a register at an offset for a given generation. > --- > tools/intel_reg_dumper.c | 99 > +++++++++++++++++++++++++++++++++++++++++------- > 1 file changed, 86 insertions(+), 13 deletions(-) > > diff --git a/tools/intel_reg_dumper.c b/tools/intel_reg_dumper.c > index b49d967..098affa 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) > { > @@ -2172,6 +2227,7 @@ intel_dump_other_regs(void) > static void print_usage(void) > { > printf("Usage: intel_reg_dumper [options] [file]\n" > + " intel_reg_dumper [options] register value\n" > "Options:\n" > " -d id when a dump file is used, use 'id' as device id > (in " > "hex)\n" > @@ -2181,8 +2237,9 @@ static void print_usage(void) > int main(int argc, char** argv) > { > struct pci_device *pci_dev; > - int opt; > - char *file = NULL; > + int opt, n_args; > + char *file = NULL, *reg_name = NULL; > + uint32_t reg_val; > > while ((opt = getopt(argc, argv, "d:h")) != -1) { > switch (opt) { > @@ -2197,8 +2254,24 @@ int main(int argc, char** argv) > return 1; > } > } > - if (optind < argc) > + > + n_args = argc - optind; > + if (n_args == 1) { > file = argv[optind]; > + } else if (n_args == 2) { > + reg_name = argv[optind]; > + reg_val = strtoul(argv[optind + 1], NULL, 0); > + } else if (n_args) { > + print_usage(); > + return 1; > + } > + > + /* the tool operates in "single" mode, decode a single register > given > + * on the command line: intel_reg_dumper PCH_PP_CONTROL 0xabcd0002 > */ > + if (reg_name) { > + decode_register(reg_name, reg_val); > + return 0; > + } > > if (file) { > intel_map_file(file);
On Sun, 02 Sep 2012, Ben Widawsky <ben@bwidawsk.net> wrote: > On 2012-08-31 06:45, Damien Lespiau wrote: >> From: Damien Lespiau <damien.lespiau@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 way to ask it to decode a value. >> >> Example usage: >> >> $ ./tools/intel_reg_dumper PCH_PP_CONTROL 0xabcd0002 >> PCH_PP_CONTROL: 0xabcd0002 (blacklight disabled, power... >> >> v2: friendlier invocation (Chris Wilson) >> >> Signed-off-by: Damien Lespiau <damien.lespiau@intel.com> > > Back to my earlier complaint from the other patch... If the names don't > match the docs then you forced to memorize our historically awful naming > scheme. More useful to me would be to decode a register at an offset for > a given generation. I think both would be useful. So how about supporting both? Concrete suggestion: 1) If strtoul eats whole of register name, it's register offset. Print *all* matches across *all* generations. 2) If it's a register name, print *all* partial matches (from beginning of string) across *all* generations. 3) Include generation and register offset in the output: Gen5: PCH_PP_CONTROL (0xc7204): 0xabcd0002 (blacklight disabled, power... This would help in cross checking historically awful naming against register offsets, and help in checking for differences between registers and their values across generations. These patches could also go in first, and the above added later. BR, Jani.
On Fri, 31 Aug 2012, Damien Lespiau <damien.lespiau@gmail.com> wrote: > From: Damien Lespiau <damien.lespiau@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 way to ask it to decode a value. > > Example usage: > > $ ./tools/intel_reg_dumper PCH_PP_CONTROL 0xabcd0002 > PCH_PP_CONTROL: 0xabcd0002 (blacklight disabled, power... > > v2: friendlier invocation (Chris Wilson) > > Signed-off-by: Damien Lespiau <damien.lespiau@intel.com> > --- > tools/intel_reg_dumper.c | 99 +++++++++++++++++++++++++++++++++++++++++------- > 1 file changed, 86 insertions(+), 13 deletions(-) > > diff --git a/tools/intel_reg_dumper.c b/tools/intel_reg_dumper.c > index b49d967..098affa 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); Is the cast really required? val is already unsigned. Ditto below in a few places. > + } 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]; strcasecmp for ease of use? BR, Jani. > + > + 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) > { > @@ -2172,6 +2227,7 @@ intel_dump_other_regs(void) > static void print_usage(void) > { > printf("Usage: intel_reg_dumper [options] [file]\n" > + " intel_reg_dumper [options] register value\n" > "Options:\n" > " -d id when a dump file is used, use 'id' as device id (in " > "hex)\n" > @@ -2181,8 +2237,9 @@ static void print_usage(void) > int main(int argc, char** argv) > { > struct pci_device *pci_dev; > - int opt; > - char *file = NULL; > + int opt, n_args; > + char *file = NULL, *reg_name = NULL; > + uint32_t reg_val; > > while ((opt = getopt(argc, argv, "d:h")) != -1) { > switch (opt) { > @@ -2197,8 +2254,24 @@ int main(int argc, char** argv) > return 1; > } > } > - if (optind < argc) > + > + n_args = argc - optind; > + if (n_args == 1) { > file = argv[optind]; > + } else if (n_args == 2) { > + reg_name = argv[optind]; > + reg_val = strtoul(argv[optind + 1], NULL, 0); > + } else if (n_args) { > + print_usage(); > + return 1; > + } > + > + /* the tool operates in "single" mode, decode a single register given > + * on the command line: intel_reg_dumper PCH_PP_CONTROL 0xabcd0002 */ > + if (reg_name) { > + decode_register(reg_name, reg_val); > + return 0; > + } > > if (file) { > intel_map_file(file); > -- > 1.7.11.4 > > _______________________________________________ > Intel-gfx mailing list > Intel-gfx@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
On Sun, Sep 2, 2012 at 2:48 AM, Ben Widawsky <ben@bwidawsk.net> wrote: > On 2012-08-31 06:45, Damien Lespiau wrote: > Back to my earlier complaint from the other patch... If the names don't > match the docs then you forced to memorize our historically awful naming > scheme. More useful to me would be to decode a register at an offset for a > given generation. Well, renaming the registers sounds a bit tedious and will break the diffs between two dumps across the change (don't know if it's a big deal). Hopefully the new little features suggested by Jani make the single register decode more useful for you.
diff --git a/tools/intel_reg_dumper.c b/tools/intel_reg_dumper.c index b49d967..098affa 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) { @@ -2172,6 +2227,7 @@ intel_dump_other_regs(void) static void print_usage(void) { printf("Usage: intel_reg_dumper [options] [file]\n" + " intel_reg_dumper [options] register value\n" "Options:\n" " -d id when a dump file is used, use 'id' as device id (in " "hex)\n" @@ -2181,8 +2237,9 @@ static void print_usage(void) int main(int argc, char** argv) { struct pci_device *pci_dev; - int opt; - char *file = NULL; + int opt, n_args; + char *file = NULL, *reg_name = NULL; + uint32_t reg_val; while ((opt = getopt(argc, argv, "d:h")) != -1) { switch (opt) { @@ -2197,8 +2254,24 @@ int main(int argc, char** argv) return 1; } } - if (optind < argc) + + n_args = argc - optind; + if (n_args == 1) { file = argv[optind]; + } else if (n_args == 2) { + reg_name = argv[optind]; + reg_val = strtoul(argv[optind + 1], NULL, 0); + } else if (n_args) { + print_usage(); + return 1; + } + + /* the tool operates in "single" mode, decode a single register given + * on the command line: intel_reg_dumper PCH_PP_CONTROL 0xabcd0002 */ + if (reg_name) { + decode_register(reg_name, reg_val); + return 0; + } if (file) { intel_map_file(file);