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