1/*
2 * Copyright 2024, Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * 		J��r��me Duval <jerome.duval@gmail.com>
7 */
8
9
10#include <errno.h>
11#include <stdint.h>
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
15
16#include <OS.h>
17
18
19extern const char *__progname;
20static const char *kCommandName = __progname;
21
22
23// usage
24static const char *kUsage =
25"Usage: %s [ <options> ] [ command ] [ args ]\n"
26"\n"
27"Options:\n"
28"  --count <n>      - Read n registers.\n"
29;
30
31
32static void
33print_usage(bool error)
34{
35	// print usage
36	fprintf((error ? stderr : stdout), kUsage, kCommandName);
37}
38
39
40static void
41print_usage_and_exit(bool error)
42{
43	print_usage(error);
44	exit(error ? 1 : 0);
45}
46
47
48int
49main(int argc, const char *const *argv)
50{
51	const char *const *programArgs = NULL;
52	int32_t programArgCount = 0;
53	uint32_t count = 1;
54
55	// parse arguments
56	for (int argi = 1; argi < argc; argi++) {
57		const char *arg = argv[argi];
58		if (arg[0] == '-') {
59			if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0) {
60				print_usage_and_exit(false);
61			} else if (strcmp(arg, "--count") == 0) {
62				count = strtol(argv[++argi], (char **)NULL, 10);
63				if (count == 0 && errno != 0)
64					print_usage_and_exit(true);
65			} else {
66				print_usage_and_exit(true);
67			}
68		} else {
69			programArgs = argv + argi;
70			programArgCount = argc - argi;
71			break;
72		}
73	}
74
75	bool write = false;
76	uint32 value = 0;
77	if (programArgCount < 2) {
78		print_usage_and_exit(true);
79	}
80	if (strcmp(programArgs[0], "read") == 0) {
81		if (programArgCount >= 4) {
82			const char *arg = programArgs[1];
83			if (arg[0] == '-') {
84				if (strcmp(arg, "--count") == 0) {
85					count = strtol(programArgs[2], (char **)NULL, 10);
86					if (count == 0 && errno != 0)
87						print_usage_and_exit(true);
88					programArgCount -= 2;
89					programArgs += 2;
90				} else {
91					print_usage_and_exit(true);
92				}
93			}
94		}
95	} else if (strcmp(programArgs[0], "write") == 0) {
96		write = true;
97	} else
98		print_usage_and_exit(true);
99	programArgCount--;
100	programArgs++;
101
102	area_id area = find_area("intel extreme mmio");
103	if (area < 0) {
104		fprintf(stderr, "couldn't find intel extreme mmio area\n");
105		exit(1);
106	}
107
108	void* regs;
109	uint32 protection = B_READ_AREA | (write ? B_WRITE_AREA : 0);
110	area_id clone = clone_area("clone regs", &regs, B_ANY_ADDRESS, protection, area);
111	if (clone < B_OK) {
112		fprintf(stderr, "couldn't clone intel extreme mmio area\n");
113		exit(1);
114	}
115
116	while (programArgCount > 0) {
117		const char* arg = programArgs[0];
118		programArgCount--;
119		programArgs++;
120		if (write) {
121			if (programArgCount < 1)
122				print_usage_and_exit(true);
123			const char* val = programArgs[0];
124			if (val[0] == '0' && (val[1] == 'x' || val[1] == 'X'))
125				value = strtol(val + 2, (char **)NULL, 16);
126			else
127				value = strtol(val, (char **)NULL, 10);
128			if (value == 0 && errno != 0)
129				print_usage_and_exit(true);
130			programArgCount--;
131			programArgs++;
132		}
133		uint64_t address;
134		if (arg[0] == '0' && (arg[1] == 'x' || arg[1] == 'X')) {
135			address = strtol(arg + 2, (char **)NULL, 16);
136		} else
137			address = strtol(arg, (char **)NULL, 10);
138		if (address == 0 && errno != 0)
139			print_usage_and_exit(true);
140
141		for (uint32_t i = 0; i < count; i++) {
142			addr_t addr = (addr_t)regs + address + i * sizeof(uint32);
143			if (write) {
144				*(uint32*)addr = value;
145			} else {
146				printf("(0x%08" B_PRIxADDR "): 0x%08" B_PRIx32 "\n", address + i * sizeof(uint32), *(uint32*)addr);
147			}
148		}
149	}
150
151	delete_area(clone);
152	exit(0);
153}
154