1 /*
2 * Copyright © 2015 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24 #include <errno.h>
25 #include <getopt.h>
26 #include <limits.h>
27 #include <stdbool.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <sys/stat.h>
32 #include <sys/types.h>
33 #include <unistd.h>
34
35 #include "igt.h"
36 #include "igt_gt.h"
37 #include "intel_io.h"
38 #include "intel_chipset.h"
39
40 #include "intel_reg_spec.h"
41
42
43 #ifdef HAVE_SYS_IO_H
44 #include <sys/io.h>
45 #else
46
_not_supported(void)47 static inline int _not_supported(void)
48 {
49 fprintf(stderr, "portio-vga not supported\n");
50 exit(EXIT_FAILURE);
51 }
52 #define inb(port) _not_supported()
53 #define outb(value, port) _not_supported()
54 #define iopl(level)
55
56 #endif /* HAVE_SYS_IO_H */
57
58 struct config {
59 struct pci_device *pci_dev;
60 char *mmiofile;
61 uint32_t devid;
62
63 /* read: number of registers to read */
64 uint32_t count;
65
66 /* write: do a posting read */
67 bool post;
68
69 /* decode register for all platforms */
70 bool all_platforms;
71
72 /* spread out bits for convenience */
73 bool binary;
74
75 /* register spec */
76 char *specfile;
77
78 /* fd for engine access avoiding reopens */
79 int fd;
80
81 struct reg *regs;
82 ssize_t regcount;
83
84 int verbosity;
85 };
86
87 /* port desc must have been set */
set_reg_by_addr(struct config * config,struct reg * reg,uint32_t addr)88 static int set_reg_by_addr(struct config *config, struct reg *reg,
89 uint32_t addr)
90 {
91 int i;
92
93 reg->addr = addr;
94 if (reg->name)
95 free(reg->name);
96 reg->name = NULL;
97
98 for (i = 0; i < config->regcount; i++) {
99 struct reg *r = &config->regs[i];
100
101 if (reg->port_desc.port != r->port_desc.port)
102 continue;
103
104 /* ->mmio_offset should be 0 for non-MMIO ports. */
105 if (addr + reg->mmio_offset == r->addr + r->mmio_offset) {
106 /* Always output the "normalized" offset+addr. */
107 reg->mmio_offset = r->mmio_offset;
108 reg->addr = r->addr;
109
110 reg->name = r->name ? strdup(r->name) : NULL;
111 break;
112 }
113 }
114
115 return 0;
116 }
117
118 /* port desc must have been set */
set_reg_by_name(struct config * config,struct reg * reg,const char * name)119 static int set_reg_by_name(struct config *config, struct reg *reg,
120 const char *name)
121 {
122 int i;
123
124 reg->name = strdup(name);
125 reg->addr = 0;
126
127 for (i = 0; i < config->regcount; i++) {
128 struct reg *r = &config->regs[i];
129
130 if (reg->port_desc.port != r->port_desc.port)
131 continue;
132
133 if (!r->name)
134 continue;
135
136 if (strcasecmp(name, r->name) == 0) {
137 reg->addr = r->addr;
138
139 /* Also get MMIO offset if not already specified. */
140 if (!reg->mmio_offset && r->mmio_offset)
141 reg->mmio_offset = r->mmio_offset;
142
143 return 0;
144 }
145 }
146
147 return -1;
148 }
149
to_binary(char * buf,size_t buflen,uint32_t val)150 static void to_binary(char *buf, size_t buflen, uint32_t val)
151 {
152 int i;
153
154 if (!buflen)
155 return;
156
157 *buf = '\0';
158
159 /* XXX: This quick and dirty implementation makes eyes hurt. */
160 for (i = 31; i >= 0; i--) {
161 if (i % 8 == 0)
162 snprintf(buf, buflen, " %2d", i);
163 else
164 snprintf(buf, buflen, " ");
165 buflen -= strlen(buf);
166 buf += strlen(buf);
167 }
168 snprintf(buf, buflen, "\n");
169 buflen -= strlen(buf);
170 buf += strlen(buf);
171
172 for (i = 31; i >= 0; i--) {
173 snprintf(buf, buflen, " %s%d", i % 8 == 7 ? " " : "",
174 !!(val & (1 << i)));
175 buflen -= strlen(buf);
176 buf += strlen(buf);
177 }
178 snprintf(buf, buflen, "\n");
179 }
180
dump_decode(struct config * config,struct reg * reg,uint32_t val)181 static void dump_decode(struct config *config, struct reg *reg, uint32_t val)
182 {
183 char decode[1300];
184 char tmp[1024];
185 char bin[200];
186
187 if (config->binary)
188 to_binary(bin, sizeof(bin), val);
189 else
190 *bin = '\0';
191
192 intel_reg_spec_decode(tmp, sizeof(tmp), reg, val,
193 config->all_platforms ? 0 : config->devid);
194
195 if (*tmp) {
196 /* We have a decode result, and maybe binary decode. */
197 if (config->all_platforms)
198 snprintf(decode, sizeof(decode), "\n%s%s", tmp, bin);
199 else
200 snprintf(decode, sizeof(decode), " (%s)\n%s", tmp, bin);
201 } else if (*bin) {
202 /* No decode result, but binary decode. */
203 snprintf(decode, sizeof(decode), "\n%s", bin);
204 } else {
205 /* No decode nor binary decode. */
206 snprintf(decode, sizeof(decode), "\n");
207 }
208
209 if (reg->port_desc.port == PORT_MMIO) {
210 /* Omit port name for MMIO, optionally include MMIO offset. */
211 if (reg->mmio_offset)
212 printf("%24s (0x%08x:0x%08x): 0x%08x%s",
213 reg->name ?: "",
214 reg->mmio_offset, reg->addr,
215 val, decode);
216 else
217 printf("%35s (0x%08x): 0x%08x%s",
218 reg->name ?: "",
219 reg->addr,
220 val, decode);
221 } else {
222 char name[100], addr[100];
223
224 /* If no name, use addr as name for easier copy pasting. */
225 if (reg->name)
226 snprintf(name, sizeof(name), "%s:%s",
227 reg->port_desc.name, reg->name);
228 else
229 snprintf(name, sizeof(name), "%s:0x%08x",
230 reg->port_desc.name, reg->addr);
231
232 /* Negative port numbers are not real sideband ports. */
233 if (reg->port_desc.port > PORT_NONE)
234 snprintf(addr, sizeof(addr), "0x%02x:0x%08x",
235 reg->port_desc.port, reg->addr);
236 else
237 snprintf(addr, sizeof(addr), "%s:0x%08x",
238 reg->port_desc.name, reg->addr);
239
240 printf("%24s (%s): 0x%08x%s", name, addr, val, decode);
241 }
242 }
243
find_engine(const char * name)244 static const struct intel_execution_engine2 *find_engine(const char *name)
245 {
246 const struct intel_execution_engine2 *e;
247
248 if (strlen(name) < 2)
249 return NULL;
250
251 if (name[0] == '-')
252 name++;
253
254 for (e = intel_execution_engines2; e->name; e++) {
255 if (!strcasecmp(e->name, name))
256 return e;
257 }
258
259 return NULL;
260 }
261
register_srm(struct config * config,struct reg * reg,uint32_t * val_in)262 static int register_srm(struct config *config, struct reg *reg,
263 uint32_t *val_in)
264 {
265 const int gen = intel_gen(config->devid);
266 const bool r64b = gen >= 8;
267 const uint32_t ctx = 0;
268 struct drm_i915_gem_exec_object2 obj[2];
269 struct drm_i915_gem_relocation_entry reloc[1];
270 struct drm_i915_gem_execbuffer2 execbuf;
271 uint32_t *batch, *r;
272 const struct intel_execution_engine2 *engine;
273 bool secure;
274 int fd, i;
275 uint32_t val;
276
277 if (config->fd == -1) {
278 config->fd = __drm_open_driver(DRIVER_INTEL);
279 if (config->fd == -1) {
280 fprintf(stderr, "Error opening driver: %s",
281 strerror(errno));
282 exit(EXIT_FAILURE);
283 }
284 }
285
286 fd = config->fd;
287 engine = find_engine(reg->engine);
288 if (engine == NULL)
289 exit(EXIT_FAILURE);
290
291 secure = reg->engine[0] != '-';
292
293 memset(obj, 0, sizeof(obj));
294 obj[0].handle = gem_create(fd, 4096);
295 obj[1].handle = gem_create(fd, 4096);
296 obj[1].relocs_ptr = to_user_pointer(reloc);
297 obj[1].relocation_count = 1;
298
299 batch = gem_mmap__cpu(fd, obj[1].handle, 0, 4096, PROT_WRITE);
300 gem_set_domain(fd, obj[1].handle,
301 I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
302
303 i = 0;
304 if (val_in) {
305 batch[i++] = MI_NOOP;
306 batch[i++] = MI_NOOP;
307
308 batch[i++] = MI_LOAD_REGISTER_IMM;
309 batch[i++] = reg->addr;
310 batch[i++] = *val_in;
311 batch[i++] = MI_NOOP;
312 }
313
314 batch[i++] = 0x24 << 23 | (1 + r64b); /* SRM */
315 batch[i++] = reg->addr;
316 reloc[0].target_handle = obj[0].handle;
317 reloc[0].presumed_offset = obj[0].offset;
318 reloc[0].offset = i * sizeof(uint32_t);
319 reloc[0].delta = 0;
320 reloc[0].read_domains = I915_GEM_DOMAIN_RENDER;
321 reloc[0].write_domain = I915_GEM_DOMAIN_RENDER;
322 batch[i++] = reloc[0].delta;
323 if (r64b)
324 batch[i++] = 0;
325
326 batch[i++] = MI_BATCH_BUFFER_END;
327 munmap(batch, 4096);
328
329 memset(&execbuf, 0, sizeof(execbuf));
330 execbuf.buffers_ptr = to_user_pointer(obj);
331 execbuf.buffer_count = 2;
332 execbuf.flags = engine->flags;
333 if (secure)
334 execbuf.flags |= I915_EXEC_SECURE;
335
336 if (config->verbosity > 0)
337 printf("%s: using %sprivileged batch\n",
338 engine->name,
339 secure ? "" : "non-");
340
341 execbuf.rsvd1 = ctx;
342 gem_execbuf(fd, &execbuf);
343 gem_close(fd, obj[1].handle);
344
345 r = gem_mmap__cpu(fd, obj[0].handle, 0, 4096, PROT_READ);
346 gem_set_domain(fd, obj[0].handle, I915_GEM_DOMAIN_CPU, 0);
347
348 val = r[0];
349 munmap(r, 4096);
350
351 gem_close(fd, obj[0].handle);
352
353 return val;
354 }
355
read_register(struct config * config,struct reg * reg,uint32_t * valp)356 static int read_register(struct config *config, struct reg *reg, uint32_t *valp)
357 {
358 uint32_t val = 0;
359
360 switch (reg->port_desc.port) {
361 case PORT_MMIO:
362 if (reg->engine)
363 val = register_srm(config, reg, NULL);
364 else
365 val = INREG(reg->mmio_offset + reg->addr);
366 break;
367 case PORT_PORTIO_VGA:
368 iopl(3);
369 val = inb(reg->addr);
370 iopl(0);
371 break;
372 case PORT_MMIO_VGA:
373 val = INREG8(reg->addr);
374 break;
375 case PORT_BUNIT:
376 case PORT_PUNIT:
377 case PORT_NC:
378 case PORT_DPIO:
379 case PORT_GPIO_NC:
380 case PORT_CCK:
381 case PORT_CCU:
382 case PORT_DPIO2:
383 case PORT_FLISDSI:
384 if (!IS_VALLEYVIEW(config->devid) &&
385 !IS_CHERRYVIEW(config->devid)) {
386 fprintf(stderr, "port %s only supported on vlv/chv\n",
387 reg->port_desc.name);
388 return -1;
389 }
390 val = intel_iosf_sb_read(reg->port_desc.port, reg->addr);
391 break;
392 default:
393 fprintf(stderr, "port %d not supported\n", reg->port_desc.port);
394 return -1;
395 }
396
397 if (valp)
398 *valp = val;
399
400 return 0;
401 }
402
dump_register(struct config * config,struct reg * reg)403 static void dump_register(struct config *config, struct reg *reg)
404 {
405 uint32_t val;
406
407 if (read_register(config, reg, &val) == 0)
408 dump_decode(config, reg, val);
409 }
410
write_register(struct config * config,struct reg * reg,uint32_t val)411 static int write_register(struct config *config, struct reg *reg, uint32_t val)
412 {
413 int ret = 0;
414
415 if (config->verbosity > 0) {
416 printf("Before:\n");
417 dump_register(config, reg);
418 }
419
420 switch (reg->port_desc.port) {
421 case PORT_MMIO:
422 if (reg->engine) {
423 register_srm(config, reg, &val);
424 } else {
425 OUTREG(reg->mmio_offset + reg->addr, val);
426 }
427 break;
428 case PORT_PORTIO_VGA:
429 if (val > 0xff) {
430 fprintf(stderr, "value 0x%08x out of range for port %s\n",
431 val, reg->port_desc.name);
432 return -1;
433 }
434 iopl(3);
435 outb(val, reg->addr);
436 iopl(0);
437 break;
438 case PORT_MMIO_VGA:
439 if (val > 0xff) {
440 fprintf(stderr, "value 0x%08x out of range for port %s\n",
441 val, reg->port_desc.name);
442 return -1;
443 }
444 OUTREG8(reg->addr, val);
445 break;
446 case PORT_BUNIT:
447 case PORT_PUNIT:
448 case PORT_NC:
449 case PORT_DPIO:
450 case PORT_GPIO_NC:
451 case PORT_CCK:
452 case PORT_CCU:
453 case PORT_DPIO2:
454 case PORT_FLISDSI:
455 if (!IS_VALLEYVIEW(config->devid) &&
456 !IS_CHERRYVIEW(config->devid)) {
457 fprintf(stderr, "port %s only supported on vlv/chv\n",
458 reg->port_desc.name);
459 return -1;
460 }
461 intel_iosf_sb_write(reg->port_desc.port, reg->addr, val);
462 break;
463 default:
464 fprintf(stderr, "port %d not supported\n", reg->port_desc.port);
465 ret = -1;
466 }
467
468 if (config->verbosity > 0) {
469 printf("After:\n");
470 dump_register(config, reg);
471 } else if (config->post) {
472 read_register(config, reg, NULL);
473 }
474
475 return ret;
476 }
477
parse_engine(struct reg * reg,const char * s)478 static int parse_engine(struct reg *reg, const char *s)
479 {
480 const struct intel_execution_engine2 *e;
481
482 e = find_engine(s);
483 if (e) {
484 reg->port_desc.port = PORT_MMIO;
485 reg->port_desc.name = strdup(s);
486 reg->port_desc.stride = 4;
487 reg->engine = strdup(s);
488 reg->mmio_offset = 0;
489 } else {
490 reg->engine = NULL;
491 }
492
493 return reg->engine == NULL;
494 }
495
496 /* s has [(PORTNAME|PORTNUM|ENGINE|MMIO-OFFSET):](REGNAME|REGADDR) */
parse_reg(struct config * config,struct reg * reg,const char * s)497 static int parse_reg(struct config *config, struct reg *reg, const char *s)
498 {
499 unsigned long addr;
500 char *endp;
501 const char *p;
502 int ret;
503
504 memset(reg, 0, sizeof(*reg));
505
506 p = strchr(s, ':');
507 if (p == s) {
508 ret = -1;
509 } else if (p) {
510 char *port_name = strndup(s, p - s);
511
512 ret = parse_engine(reg, port_name);
513 if (ret)
514 ret = parse_port_desc(reg, port_name);
515
516 free(port_name);
517 p++;
518 } else {
519 /*
520 * XXX: If port is not specified in input, see if the register
521 * matches by name, and initialize port desc based on that.
522 */
523 ret = parse_port_desc(reg, NULL);
524 p = s;
525 }
526
527 if (ret) {
528 fprintf(stderr, "invalid port in '%s'\n", s);
529 return ret;
530 }
531
532 addr = strtoul(p, &endp, 16);
533 if (endp > p && *endp == 0) {
534 /* It's a number. */
535 ret = set_reg_by_addr(config, reg, addr);
536 } else {
537 /* Not a number, it's a name. */
538 ret = set_reg_by_name(config, reg, p);
539 }
540
541 return ret;
542 }
543
544 /* XXX: add support for register ranges, maybe REGISTER..REGISTER */
intel_reg_read(struct config * config,int argc,char * argv[])545 static int intel_reg_read(struct config *config, int argc, char *argv[])
546 {
547 int i, j;
548
549 if (argc == 1) {
550 fprintf(stderr, "read: no registers specified\n");
551 return EXIT_FAILURE;
552 }
553
554 if (config->mmiofile)
555 intel_mmio_use_dump_file(config->mmiofile);
556 else
557 intel_register_access_init(config->pci_dev, 0, -1);
558
559 for (i = 1; i < argc; i++) {
560 struct reg reg;
561
562 if (parse_reg(config, ®, argv[i]))
563 continue;
564
565 for (j = 0; j < config->count; j++) {
566 dump_register(config, ®);
567 /* Update addr and name. */
568 set_reg_by_addr(config, ®,
569 reg.addr + reg.port_desc.stride);
570 }
571 }
572
573 intel_register_access_fini();
574
575 return EXIT_SUCCESS;
576 }
577
intel_reg_write(struct config * config,int argc,char * argv[])578 static int intel_reg_write(struct config *config, int argc, char *argv[])
579 {
580 int i;
581
582 if (argc == 1) {
583 fprintf(stderr, "write: no registers specified\n");
584 return EXIT_FAILURE;
585 }
586
587 intel_register_access_init(config->pci_dev, 0, -1);
588
589 for (i = 1; i < argc; i += 2) {
590 struct reg reg;
591 uint32_t val;
592 char *endp;
593
594 if (parse_reg(config, ®, argv[i]))
595 continue;
596
597 if (i + 1 == argc) {
598 fprintf(stderr, "write: no value\n");
599 break;
600 }
601
602 val = strtoul(argv[i + 1], &endp, 16);
603 if (endp == argv[i + 1] || *endp) {
604 fprintf(stderr, "write: invalid value '%s'\n",
605 argv[i + 1]);
606 continue;
607 }
608
609 write_register(config, ®, val);
610 }
611
612 intel_register_access_fini();
613
614 return EXIT_SUCCESS;
615 }
616
intel_reg_dump(struct config * config,int argc,char * argv[])617 static int intel_reg_dump(struct config *config, int argc, char *argv[])
618 {
619 struct reg *reg;
620 int i;
621
622 if (config->mmiofile)
623 intel_mmio_use_dump_file(config->mmiofile);
624 else
625 intel_register_access_init(config->pci_dev, 0, -1);
626
627 for (i = 0; i < config->regcount; i++) {
628 reg = &config->regs[i];
629
630 /* can't dump sideband with mmiofile */
631 if (config->mmiofile && reg->port_desc.port != PORT_MMIO)
632 continue;
633
634 dump_register(config, &config->regs[i]);
635 }
636
637 intel_register_access_fini();
638
639 return EXIT_SUCCESS;
640 }
641
intel_reg_snapshot(struct config * config,int argc,char * argv[])642 static int intel_reg_snapshot(struct config *config, int argc, char *argv[])
643 {
644 int mmio_bar = IS_GEN2(config->devid) ? 1 : 0;
645
646 if (config->mmiofile) {
647 fprintf(stderr, "specifying --mmio=FILE is not compatible\n");
648 return EXIT_FAILURE;
649 }
650
651 intel_mmio_use_pci_bar(config->pci_dev);
652
653 /* XXX: error handling */
654 if (write(1, igt_global_mmio, config->pci_dev->regions[mmio_bar].size) == -1)
655 fprintf(stderr, "Error writing snapshot: %s", strerror(errno));
656
657 if (config->verbosity > 0)
658 printf("use this with --mmio=FILE --devid=0x%04X\n",
659 config->devid);
660
661 return EXIT_SUCCESS;
662 }
663
664 /* XXX: add support for reading and re-decoding a previously done dump */
intel_reg_decode(struct config * config,int argc,char * argv[])665 static int intel_reg_decode(struct config *config, int argc, char *argv[])
666 {
667 int i;
668
669 if (argc == 1) {
670 fprintf(stderr, "decode: no registers specified\n");
671 return EXIT_FAILURE;
672 }
673
674 for (i = 1; i < argc; i += 2) {
675 struct reg reg;
676 uint32_t val;
677 char *endp;
678
679 if (parse_reg(config, ®, argv[i]))
680 continue;
681
682 if (i + 1 == argc) {
683 fprintf(stderr, "decode: no value\n");
684 break;
685 }
686
687 val = strtoul(argv[i + 1], &endp, 16);
688 if (endp == argv[i + 1] || *endp) {
689 fprintf(stderr, "decode: invalid value '%s'\n",
690 argv[i + 1]);
691 continue;
692 }
693
694 dump_decode(config, ®, val);
695 }
696
697 return EXIT_SUCCESS;
698 }
699
intel_reg_list(struct config * config,int argc,char * argv[])700 static int intel_reg_list(struct config *config, int argc, char *argv[])
701 {
702 int i;
703
704 for (i = 0; i < config->regcount; i++) {
705 printf("%s\n", config->regs[i].name);
706 }
707
708 return EXIT_SUCCESS;
709 }
710
711 static int intel_reg_help(struct config *config, int argc, char *argv[]);
712
713 struct command {
714 const char *name;
715 const char *description;
716 const char *synopsis;
717 int (*function)(struct config *config, int argc, char *argv[]);
718 };
719
720 static const struct command commands[] = {
721 {
722 .name = "read",
723 .function = intel_reg_read,
724 .synopsis = "[--count=N] REGISTER [...]",
725 .description = "read and decode specified register(s)",
726 },
727 {
728 .name = "write",
729 .function = intel_reg_write,
730 .synopsis = "[--post] REGISTER VALUE [REGISTER VALUE ...]",
731 .description = "write value(s) to specified register(s)",
732 },
733 {
734 .name = "dump",
735 .function = intel_reg_dump,
736 .description = "dump all known registers",
737 },
738 {
739 .name = "decode",
740 .function = intel_reg_decode,
741 .synopsis = "REGISTER VALUE [REGISTER VALUE ...]",
742 .description = "decode value(s) for specified register(s)",
743 },
744 {
745 .name = "snapshot",
746 .function = intel_reg_snapshot,
747 .description = "create a snapshot of the MMIO bar to stdout",
748 },
749 {
750 .name = "list",
751 .function = intel_reg_list,
752 .description = "list all known register names",
753 },
754 {
755 .name = "help",
756 .function = intel_reg_help,
757 .description = "show this help",
758 },
759 };
760
intel_reg_help(struct config * config,int argc,char * argv[])761 static int intel_reg_help(struct config *config, int argc, char *argv[])
762 {
763 const struct intel_execution_engine2 *e;
764 int i;
765
766 printf("Intel graphics register multitool\n\n");
767 printf("Usage: intel_reg [OPTION ...] COMMAND\n\n");
768 printf("COMMAND is one of:\n");
769 for (i = 0; i < ARRAY_SIZE(commands); i++) {
770 printf(" %-14s%s\n", commands[i].name,
771 commands[i].synopsis ?: "");
772 printf(" %-14s%s\n", "", commands[i].description);
773 }
774
775 printf("\n");
776 printf("REGISTER is defined as:\n");
777 printf(" [(PORTNAME|PORTNUM|ENGINE|MMIO-OFFSET):](REGNAME|REGADDR)\n");
778
779 printf("\n");
780 printf("PORTNAME is one of:\n");
781 intel_reg_spec_print_ports();
782 printf("\n\n");
783
784 printf("ENGINE is one of:\n");
785 for (e = intel_execution_engines2; e->name; e++)
786 printf("%s -%s ", e->name, e->name);
787 printf("\n\n");
788
789 printf("OPTIONS common to most COMMANDS:\n");
790 printf(" --spec=PATH Read register spec from directory or file\n");
791 printf(" --mmio=FILE Use an MMIO snapshot\n");
792 printf(" --devid=DEVID Specify PCI device ID for --mmio=FILE\n");
793 printf(" --all Decode registers for all known platforms\n");
794 printf(" --binary Binary dump registers\n");
795 printf(" --verbose Increase verbosity\n");
796 printf(" --quiet Reduce verbosity\n");
797
798 printf("\n");
799 printf("Environment variables:\n");
800 printf(" INTEL_REG_SPEC Read register spec from directory or file\n");
801
802 return EXIT_SUCCESS;
803 }
804
805 /*
806 * Get codename for a gen5+ platform to be used for finding register spec file.
807 */
get_codename(uint32_t devid)808 static const char *get_codename(uint32_t devid)
809 {
810 return intel_get_device_info(devid)->codename;
811 }
812
813 /*
814 * Get register definitions filename for devid in dir. Return 0 if found,
815 * negative error code otherwise.
816 */
get_reg_spec_file(char * buf,size_t buflen,const char * dir,uint32_t devid)817 static int get_reg_spec_file(char *buf, size_t buflen, const char *dir,
818 uint32_t devid)
819 {
820 const char *codename;
821
822 /* First, try file named after devid, e.g. "0412" for Haswell GT2. */
823 snprintf(buf, buflen, "%s/%04x", dir, devid);
824 if (!access(buf, F_OK))
825 return 0;
826
827 /*
828 * Second, for gen5+, try file named after codename, e.g. "haswell" for
829 * Haswell.
830 */
831 codename = get_codename(devid);
832 if (codename) {
833 snprintf(buf, buflen, "%s/%s", dir, codename);
834 if (!access(buf, F_OK))
835 return 0;
836 }
837
838 /*
839 * Third, try file named after gen, e.g. "gen7" for Haswell (which is
840 * technically 7.5 but this is how it works).
841 */
842 snprintf(buf, buflen, "%s/gen%d", dir, intel_gen(devid));
843 if (!access(buf, F_OK))
844 return 0;
845
846 return -ENOENT;
847 }
848
849 /*
850 * Read register spec.
851 */
read_reg_spec(struct config * config)852 static int read_reg_spec(struct config *config)
853 {
854 char buf[PATH_MAX];
855 const char *path;
856 struct stat st;
857 int r;
858
859 path = config->specfile;
860 if (!path)
861 path = getenv("INTEL_REG_SPEC");
862
863 if (!path)
864 path = IGT_DATADIR"/registers";
865
866 r = stat(path, &st);
867 if (r) {
868 fprintf(stderr, "Warning: stat '%s' failed: %s. "
869 "Using builtin register spec.\n",
870 path, strerror(errno));
871 goto builtin;
872 }
873
874 if (S_ISDIR(st.st_mode)) {
875 r = get_reg_spec_file(buf, sizeof(buf), path, config->devid);
876 if (r) {
877 fprintf(stderr, "Warning: register spec not found in "
878 "'%s'. Using builtin register spec.\n", path);
879 goto builtin;
880 }
881 path = buf;
882 }
883
884 config->regcount = intel_reg_spec_file(&config->regs, path);
885 if (config->regcount <= 0) {
886 fprintf(stderr, "Warning: reading '%s' failed. "
887 "Using builtin register spec.\n", path);
888 goto builtin;
889 }
890
891 return config->regcount;
892
893 builtin:
894 /* Fallback to builtin register spec. */
895 config->regcount = intel_reg_spec_builtin(&config->regs, config->devid);
896
897 return config->regcount;
898 }
899
900 enum opt {
901 OPT_UNKNOWN = '?',
902 OPT_END = -1,
903 OPT_MMIO,
904 OPT_DEVID,
905 OPT_COUNT,
906 OPT_POST,
907 OPT_ALL,
908 OPT_BINARY,
909 OPT_SPEC,
910 OPT_VERBOSE,
911 OPT_QUIET,
912 OPT_HELP,
913 };
914
main(int argc,char * argv[])915 int main(int argc, char *argv[])
916 {
917 int ret, i, index;
918 char *endp;
919 enum opt opt;
920 const struct command *command = NULL;
921 struct config config = {
922 .count = 1,
923 .fd = -1,
924 };
925 bool help = false;
926
927 static struct option options[] = {
928 /* global options */
929 { "spec", required_argument, NULL, OPT_SPEC },
930 { "verbose", no_argument, NULL, OPT_VERBOSE },
931 { "quiet", no_argument, NULL, OPT_QUIET },
932 { "help", no_argument, NULL, OPT_HELP },
933 /* options specific to read and dump */
934 { "mmio", required_argument, NULL, OPT_MMIO },
935 { "devid", required_argument, NULL, OPT_DEVID },
936 /* options specific to read */
937 { "count", required_argument, NULL, OPT_COUNT },
938 /* options specific to write */
939 { "post", no_argument, NULL, OPT_POST },
940 /* options specific to read, dump and decode */
941 { "all", no_argument, NULL, OPT_ALL },
942 { "binary", no_argument, NULL, OPT_BINARY },
943 { 0 }
944 };
945
946 for (opt = 0; opt != OPT_END; ) {
947 opt = getopt_long(argc, argv, "", options, &index);
948
949 switch (opt) {
950 case OPT_MMIO:
951 config.mmiofile = strdup(optarg);
952 if (!config.mmiofile) {
953 fprintf(stderr, "strdup: %s\n",
954 strerror(errno));
955 return EXIT_FAILURE;
956 }
957 break;
958 case OPT_DEVID:
959 config.devid = strtoul(optarg, &endp, 16);
960 if (*endp) {
961 fprintf(stderr, "invalid devid '%s'\n", optarg);
962 return EXIT_FAILURE;
963 }
964 break;
965 case OPT_COUNT:
966 config.count = strtol(optarg, &endp, 10);
967 if (*endp) {
968 fprintf(stderr, "invalid count '%s'\n", optarg);
969 return EXIT_FAILURE;
970 }
971 break;
972 case OPT_POST:
973 config.post = true;
974 break;
975 case OPT_SPEC:
976 config.specfile = strdup(optarg);
977 if (!config.specfile) {
978 fprintf(stderr, "strdup: %s\n",
979 strerror(errno));
980 return EXIT_FAILURE;
981 }
982 break;
983 case OPT_ALL:
984 config.all_platforms = true;
985 break;
986 case OPT_BINARY:
987 config.binary = true;
988 break;
989 case OPT_VERBOSE:
990 config.verbosity++;
991 break;
992 case OPT_QUIET:
993 config.verbosity--;
994 break;
995 case OPT_HELP:
996 help = true;
997 break;
998 case OPT_END:
999 break;
1000 case OPT_UNKNOWN:
1001 return EXIT_FAILURE;
1002 }
1003 }
1004
1005 argc -= optind;
1006 argv += optind;
1007
1008 if (help || (argc > 0 && strcmp(argv[0], "help") == 0))
1009 return intel_reg_help(&config, argc, argv);
1010
1011 if (argc == 0) {
1012 fprintf(stderr, "Command missing. Try intel_reg help.\n");
1013 return EXIT_FAILURE;
1014 }
1015
1016 if (config.mmiofile) {
1017 if (!config.devid) {
1018 fprintf(stderr, "--mmio requires --devid\n");
1019 return EXIT_FAILURE;
1020 }
1021 } else {
1022 /* XXX: devid without --mmio could be useful for decode. */
1023 if (config.devid) {
1024 fprintf(stderr, "--devid without --mmio\n");
1025 return EXIT_FAILURE;
1026 }
1027 config.pci_dev = intel_get_pci_device();
1028 config.devid = config.pci_dev->device_id;
1029 }
1030
1031 if (read_reg_spec(&config) < 0) {
1032 return EXIT_FAILURE;
1033 }
1034
1035 for (i = 0; i < ARRAY_SIZE(commands); i++) {
1036 if (strcmp(argv[0], commands[i].name) == 0) {
1037 command = &commands[i];
1038 break;
1039 }
1040 }
1041
1042 if (!command) {
1043 fprintf(stderr, "'%s' is not an intel-reg command\n", argv[0]);
1044 return EXIT_FAILURE;
1045 }
1046
1047 ret = command->function(&config, argc, argv);
1048
1049 free(config.mmiofile);
1050
1051 if (config.fd >= 0)
1052 close(config.fd);
1053
1054 return ret;
1055 }
1056