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