xref: /illumos-gate/usr/src/cmd/amdzen/udf.c (revision f87c0a68ef64fc0c0effda47ee88951e83bb693c)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2026 Oxide Computer Company
14  */
15 
16 /*
17  * Facilitate access to the AMD Zen data fabric
18  */
19 
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23 #include <err.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <fcntl.h>
27 #include <errno.h>
28 #include <strings.h>
29 #include <zen_udf.h>
30 
31 #include "amdzen_common.h"
32 
33 static void
34 udf_readone(int fd, uint8_t inst, uint8_t func, uint16_t reg,
35     zen_udf_flags_t flags)
36 {
37 	int ret;
38 	zen_udf_io_t zui;
39 
40 	bzero(&zui, sizeof (zui));
41 	zui.zui_flags = flags;
42 	zui.zui_inst = inst;
43 	zui.zui_func = func;
44 	zui.zui_reg = reg;
45 
46 	ret = ioctl(fd, ZEN_UDF_READ, &zui);
47 	if (ret != 0) {
48 		err(EXIT_FAILURE, "failed to issue read ioctl");
49 	}
50 
51 	if ((flags & ZEN_UDF_F_BCAST) == 0) {
52 		(void) printf("ifr %x/%x/%x: 0x%" PRIx64 "\n",
53 		    inst, func, reg, zui.zui_data);
54 	} else {
55 		(void) printf("ifr bcast/%x/%x: 0x%" PRIx64 "\n",
56 		    func, reg, zui.zui_data);
57 	}
58 }
59 
60 int
61 main(int argc, char *argv[])
62 {
63 	int c, fd;
64 	const char *device = NULL;
65 	const char *funcstr = NULL;
66 	const char *inststr = NULL;
67 	const char *regstr = NULL;
68 	zen_udf_flags_t flags = 0;
69 	uint8_t func, inst = UINT8_MAX;
70 	uint16_t reg;
71 	unsigned long lval;
72 	char *eptr;
73 
74 	while ((c = getopt(argc, argv, "d:f:bi:r:l")) != -1) {
75 		switch (c) {
76 		case 'd':
77 			device = optarg;
78 			break;
79 		case 'f':
80 			funcstr = optarg;
81 			break;
82 		case 'b':
83 			flags |= ZEN_UDF_F_BCAST;
84 			break;
85 		case 'i':
86 			inststr = optarg;
87 			break;
88 		case 'l':
89 			flags |= ZEN_UDF_F_64;
90 			break;
91 		case 'r':
92 			regstr = optarg;
93 			break;
94 		}
95 	}
96 
97 	if (device == NULL || funcstr == NULL || regstr == NULL ||
98 	    (inststr == NULL && (flags & ZEN_UDF_F_BCAST) == 0)) {
99 		warnx("missing required arguments");
100 		(void) fprintf(stderr, "Usage: "
101 		    "\tudf \t[-l] -d device -f func -b -r reg\n"
102 		    "\t\t[-l] -d device -f func -i inst -r reg\n");
103 		exit(EXIT_USAGE);
104 	}
105 
106 	errno = 0;
107 	lval = strtoul(funcstr, &eptr, 0);
108 	if (errno != 0 || lval > UINT8_MAX || *eptr != '\0') {
109 		errx(EXIT_FAILURE, "failed to parse -f: %s", funcstr);
110 	}
111 	func = (uint8_t)lval;
112 
113 	if ((flags & ZEN_UDF_F_BCAST) == 0) {
114 		lval = strtoul(inststr, &eptr, 0);
115 		if (errno != 0 || lval > UINT8_MAX || *eptr != '\0') {
116 			errx(EXIT_FAILURE, "failed to parse -i: %s", inststr);
117 		}
118 		inst = (uint8_t)lval;
119 	} else if (inststr != NULL) {
120 		errx(EXIT_FAILURE, "pass just one of -b or -i inst");
121 	}
122 
123 	lval = strtoul(regstr, &eptr, 0);
124 	if (errno != 0 || lval > UINT16_MAX || *eptr != '\0') {
125 		errx(EXIT_FAILURE, "failed to parse -r: %s", regstr);
126 	}
127 	reg = (uint16_t)lval;
128 
129 	if ((fd = amdzen_open_device("udf", device, O_RDONLY)) < 0)
130 		return (EXIT_FAILURE);
131 
132 	udf_readone(fd, inst, func, reg, flags);
133 	(void) close(fd);
134 	return (0);
135 }
136