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, &reg, argv[i]))
563 			continue;
564 
565 		for (j = 0; j < config->count; j++) {
566 			dump_register(config, &reg);
567 			/* Update addr and name. */
568 			set_reg_by_addr(config, &reg,
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, &reg, 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, &reg, 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, &reg, 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, &reg, 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