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 2025 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 static void 32 udf_readone(int fd, uint8_t inst, uint8_t func, uint16_t reg, 33 zen_udf_flags_t flags) 34 { 35 int ret; 36 zen_udf_io_t zui; 37 38 bzero(&zui, sizeof (zui)); 39 zui.zui_flags = flags; 40 zui.zui_inst = inst; 41 zui.zui_func = func; 42 zui.zui_reg = reg; 43 44 ret = ioctl(fd, ZEN_UDF_READ, &zui); 45 if (ret != 0) { 46 err(EXIT_FAILURE, "failed to issue read ioctl"); 47 } 48 49 if ((flags & ZEN_UDF_F_BCAST) == 0) { 50 (void) printf("ifr %x/%x/%x: 0x%" PRIx64 "\n", 51 inst, func, reg, zui.zui_data); 52 } else { 53 (void) printf("ifr bcast/%x/%x: 0x%" PRIx64 "\n", 54 func, reg, zui.zui_data); 55 } 56 } 57 58 int 59 main(int argc, char *argv[]) 60 { 61 int c, fd; 62 const char *device = NULL; 63 const char *funcstr = NULL; 64 const char *inststr = NULL; 65 const char *regstr = NULL; 66 zen_udf_flags_t flags = 0; 67 uint8_t func, inst = UINT8_MAX; 68 uint16_t reg; 69 unsigned long lval; 70 char *eptr; 71 72 while ((c = getopt(argc, argv, "d:f:bi:r:l")) != -1) { 73 switch (c) { 74 case 'd': 75 device = optarg; 76 break; 77 case 'f': 78 funcstr = optarg; 79 break; 80 case 'b': 81 flags |= ZEN_UDF_F_BCAST; 82 break; 83 case 'i': 84 inststr = optarg; 85 break; 86 case 'l': 87 flags |= ZEN_UDF_F_64; 88 break; 89 case 'r': 90 regstr = optarg; 91 break; 92 } 93 } 94 95 if (device == NULL || funcstr == NULL || regstr == NULL || 96 (inststr == NULL && (flags & ZEN_UDF_F_BCAST) == 0)) { 97 warnx("missing required arguments"); 98 (void) fprintf(stderr, "Usage: " 99 "\tudf \t[-l] -d device -f func -b -r reg\n" 100 "\t\t[-l] -d device -f func -i inst -r reg\n"); 101 exit(2); 102 } 103 104 errno = 0; 105 lval = strtoul(funcstr, &eptr, 0); 106 if (errno != 0 || lval > UINT8_MAX || *eptr != '\0') { 107 errx(EXIT_FAILURE, "failed to parse -f: %s", funcstr); 108 } 109 func = (uint8_t)lval; 110 111 if ((flags & ZEN_UDF_F_BCAST) == 0) { 112 lval = strtoul(inststr, &eptr, 0); 113 if (errno != 0 || lval > UINT8_MAX || *eptr != '\0') { 114 errx(EXIT_FAILURE, "failed to parse -i: %s", inststr); 115 } 116 inst = (uint8_t)lval; 117 } else if (inststr != NULL) { 118 errx(EXIT_FAILURE, "pass just one of -b or -i inst"); 119 } 120 121 lval = strtoul(regstr, &eptr, 0); 122 if (errno != 0 || lval > UINT16_MAX || *eptr != '\0') { 123 errx(EXIT_FAILURE, "failed to parse -r: %s", regstr); 124 } 125 reg = (uint16_t)lval; 126 127 if ((fd = open(device, O_RDONLY)) < 0) { 128 err(EXIT_FAILURE, "failed to open %s", device); 129 } 130 131 udf_readone(fd, inst, func, reg, flags); 132 (void) close(fd); 133 return (0); 134 } 135