1cddcb259SBaptiste Daroussin /*- 28ad16e55SEdward Tomasz Napierala * Copyright (c) 2019 Klara Inc. 3cddcb259SBaptiste Daroussin * Copyright (c) 2015 Baptiste Daroussin <bapt@FreeBSD.org> 48729f5ecSAllan Jude * Copyright (c) 2015 Allan Jude <allanjude@FreeBSD.org> 58729f5ecSAllan Jude * Copyright (c) 2000 by Matthew Jacob 6cddcb259SBaptiste Daroussin * All rights reserved. 7cddcb259SBaptiste Daroussin * 88ad16e55SEdward Tomasz Napierala * Portions of this software were developed by Edward Tomasz Napierala 98ad16e55SEdward Tomasz Napierala * under sponsorship from Klara Inc. 108ad16e55SEdward Tomasz Napierala * 11cddcb259SBaptiste Daroussin * Redistribution and use in source and binary forms, with or without 12cddcb259SBaptiste Daroussin * modification, are permitted provided that the following conditions 13cddcb259SBaptiste Daroussin * are met: 14cddcb259SBaptiste Daroussin * 1. Redistributions of source code must retain the above copyright 15cddcb259SBaptiste Daroussin * notice, this list of conditions and the following disclaimer 16cddcb259SBaptiste Daroussin * in this position and unchanged. 17cddcb259SBaptiste Daroussin * 2. Redistributions in binary form must reproduce the above copyright 18cddcb259SBaptiste Daroussin * notice, this list of conditions and the following disclaimer in the 19cddcb259SBaptiste Daroussin * documentation and/or other materials provided with the distribution. 20cddcb259SBaptiste Daroussin * 21cddcb259SBaptiste Daroussin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 22cddcb259SBaptiste Daroussin * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23cddcb259SBaptiste Daroussin * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24cddcb259SBaptiste Daroussin * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 25cddcb259SBaptiste Daroussin * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26cddcb259SBaptiste Daroussin * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27cddcb259SBaptiste Daroussin * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28cddcb259SBaptiste Daroussin * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29cddcb259SBaptiste Daroussin * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30cddcb259SBaptiste Daroussin * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31cddcb259SBaptiste Daroussin */ 32cddcb259SBaptiste Daroussin 33cddcb259SBaptiste Daroussin #include <sys/cdefs.h> 34cddcb259SBaptiste Daroussin __FBSDID("$FreeBSD$"); 35cddcb259SBaptiste Daroussin 3620a957e3SBaptiste Daroussin #include <sys/endian.h> 37cddcb259SBaptiste Daroussin #include <sys/param.h> 388ad16e55SEdward Tomasz Napierala #include <sys/disk.h> 39cddcb259SBaptiste Daroussin #include <sys/ioctl.h> 40d7654478SBaptiste Daroussin #include <sys/types.h> 41cddcb259SBaptiste Daroussin 42cddcb259SBaptiste Daroussin #include <err.h> 43cddcb259SBaptiste Daroussin #include <errno.h> 44cddcb259SBaptiste Daroussin #include <fcntl.h> 458729f5ecSAllan Jude #include <getopt.h> 46cddcb259SBaptiste Daroussin #include <glob.h> 47cddcb259SBaptiste Daroussin #include <stdbool.h> 48cddcb259SBaptiste Daroussin #include <stddef.h> 49cddcb259SBaptiste Daroussin #include <stdint.h> 50cddcb259SBaptiste Daroussin #include <stdio.h> 51cddcb259SBaptiste Daroussin #include <stdlib.h> 52cddcb259SBaptiste Daroussin #include <string.h> 53cddcb259SBaptiste Daroussin #include <unistd.h> 54d25c1ff6SBaptiste Daroussin #include <libxo/xo.h> 55cddcb259SBaptiste Daroussin 56cddcb259SBaptiste Daroussin #include <cam/scsi/scsi_enc.h> 57cddcb259SBaptiste Daroussin 588729f5ecSAllan Jude #include "eltsub.h" 598729f5ecSAllan Jude 60d25c1ff6SBaptiste Daroussin #define SESUTIL_XO_VERSION "1" 61d25c1ff6SBaptiste Daroussin 628ad16e55SEdward Tomasz Napierala #define TEMPERATURE_OFFSET 20 638ad16e55SEdward Tomasz Napierala 648ad16e55SEdward Tomasz Napierala #define PRINT_STYLE_DASHED 0 658ad16e55SEdward Tomasz Napierala #define PRINT_STYLE_DASHED_2 1 668ad16e55SEdward Tomasz Napierala #define PRINT_STYLE_CSV 2 678ad16e55SEdward Tomasz Napierala #define PRINT_STYLE_CSV_2 3 688ad16e55SEdward Tomasz Napierala 698729f5ecSAllan Jude static int encstatus(int argc, char **argv); 708729f5ecSAllan Jude static int fault(int argc, char **argv); 71cddcb259SBaptiste Daroussin static int locate(int argc, char **argv); 728729f5ecSAllan Jude static int objmap(int argc, char **argv); 738729f5ecSAllan Jude static int sesled(int argc, char **argv, bool fault); 748ad16e55SEdward Tomasz Napierala static int show(int argc, char **argv); 758ad16e55SEdward Tomasz Napierala static void sesutil_print(int *style, const char *fmt, ...) __printflike(2,3); 76cddcb259SBaptiste Daroussin 77cddcb259SBaptiste Daroussin static struct command { 78cddcb259SBaptiste Daroussin const char *name; 798729f5ecSAllan Jude const char *param; 80cddcb259SBaptiste Daroussin const char *desc; 81cddcb259SBaptiste Daroussin int (*exec)(int argc, char **argv); 82cddcb259SBaptiste Daroussin } cmds[] = { 838729f5ecSAllan Jude { "fault", 848729f5ecSAllan Jude "(<disk>|<sesid>|all) (on|off)", 858729f5ecSAllan Jude "Change the state of the fault LED associated with a disk", 868729f5ecSAllan Jude fault }, 878729f5ecSAllan Jude { "locate", 888729f5ecSAllan Jude "(<disk>|<sesid>|all) (on|off)", 898729f5ecSAllan Jude "Change the state of the locate LED associated with a disk", 908729f5ecSAllan Jude locate }, 918729f5ecSAllan Jude { "map", "", 928729f5ecSAllan Jude "Print a map of the devices managed by the enclosure", objmap } , 938ad16e55SEdward Tomasz Napierala { "show", "", 948ad16e55SEdward Tomasz Napierala "Print a human-friendly summary of the enclosure", show } , 958729f5ecSAllan Jude { "status", "", "Print the status of the enclosure", 968729f5ecSAllan Jude encstatus }, 97cddcb259SBaptiste Daroussin }; 98cddcb259SBaptiste Daroussin 99cddcb259SBaptiste Daroussin static const int nbcmds = nitems(cmds); 1008729f5ecSAllan Jude static const char *uflag; 101cddcb259SBaptiste Daroussin 102cddcb259SBaptiste Daroussin static void 1038729f5ecSAllan Jude usage(FILE *out, const char *subcmd) 1048729f5ecSAllan Jude { 1058729f5ecSAllan Jude int i; 1068729f5ecSAllan Jude 1078729f5ecSAllan Jude if (subcmd == NULL) { 1088729f5ecSAllan Jude fprintf(out, "Usage: %s [-u /dev/ses<N>] <command> [options]\n", 1098729f5ecSAllan Jude getprogname()); 1108729f5ecSAllan Jude fprintf(out, "Commands supported:\n"); 1118729f5ecSAllan Jude } 1128729f5ecSAllan Jude for (i = 0; i < nbcmds; i++) { 1138729f5ecSAllan Jude if (subcmd != NULL) { 1148729f5ecSAllan Jude if (strcmp(subcmd, cmds[i].name) == 0) { 1158729f5ecSAllan Jude fprintf(out, "Usage: %s %s [-u /dev/ses<N>] " 1168729f5ecSAllan Jude "%s\n\t%s\n", getprogname(), subcmd, 1178729f5ecSAllan Jude cmds[i].param, cmds[i].desc); 1188729f5ecSAllan Jude break; 1198729f5ecSAllan Jude } 1208729f5ecSAllan Jude continue; 1218729f5ecSAllan Jude } 1228729f5ecSAllan Jude fprintf(out, " %-12s%s\n\t\t%s\n\n", cmds[i].name, 1238729f5ecSAllan Jude cmds[i].param, cmds[i].desc); 1248729f5ecSAllan Jude } 1258729f5ecSAllan Jude 1268729f5ecSAllan Jude exit(EXIT_FAILURE); 1278729f5ecSAllan Jude } 1288729f5ecSAllan Jude 1298729f5ecSAllan Jude static void 130fe74eaabSAlexander Motin do_led(int fd, unsigned int idx, elm_type_t type, bool onoff, bool setfault) 131cddcb259SBaptiste Daroussin { 132fe74eaabSAlexander Motin int state = onoff ? 1 : 0; 133cddcb259SBaptiste Daroussin encioc_elm_status_t o; 134fe74eaabSAlexander Motin struct ses_ctrl_dev_slot *slot; 135cddcb259SBaptiste Daroussin 136cddcb259SBaptiste Daroussin o.elm_idx = idx; 137cddcb259SBaptiste Daroussin if (ioctl(fd, ENCIOC_GETELMSTAT, (caddr_t) &o) < 0) { 138cddcb259SBaptiste Daroussin close(fd); 139d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "ENCIOC_GETELMSTAT"); 140cddcb259SBaptiste Daroussin } 141fe74eaabSAlexander Motin slot = (struct ses_ctrl_dev_slot *) &o.cstat[0]; 142fe74eaabSAlexander Motin switch (type) { 143fe74eaabSAlexander Motin case ELMTYP_DEVICE: 144fe74eaabSAlexander Motin case ELMTYP_ARRAY_DEV: 145fe74eaabSAlexander Motin ses_ctrl_common_set_select(&slot->common, 1); 146fe74eaabSAlexander Motin if (setfault) 147fe74eaabSAlexander Motin ses_ctrl_dev_slot_set_rqst_fault(slot, state); 148efab8bfdSAlexander Motin else 149fe74eaabSAlexander Motin ses_ctrl_dev_slot_set_rqst_ident(slot, state); 150fe74eaabSAlexander Motin break; 151fe74eaabSAlexander Motin default: 152fe74eaabSAlexander Motin return; 1538729f5ecSAllan Jude } 154cddcb259SBaptiste Daroussin if (ioctl(fd, ENCIOC_SETELMSTAT, (caddr_t) &o) < 0) { 155cddcb259SBaptiste Daroussin close(fd); 156d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "ENCIOC_SETELMSTAT"); 157cddcb259SBaptiste Daroussin } 158cddcb259SBaptiste Daroussin } 159cddcb259SBaptiste Daroussin 160cddcb259SBaptiste Daroussin static bool 161cddcb259SBaptiste Daroussin disk_match(const char *devnames, const char *disk, size_t len) 162cddcb259SBaptiste Daroussin { 1631bc54324SBaptiste Daroussin const char *dname; 164cddcb259SBaptiste Daroussin 1651bc54324SBaptiste Daroussin dname = devnames; 1661bc54324SBaptiste Daroussin while ((dname = strstr(dname, disk)) != NULL) { 1678729f5ecSAllan Jude if (dname[len] == '\0' || dname[len] == ',') { 168cddcb259SBaptiste Daroussin return (true); 1698729f5ecSAllan Jude } 1701bc54324SBaptiste Daroussin dname++; 171cddcb259SBaptiste Daroussin } 1728729f5ecSAllan Jude 173cddcb259SBaptiste Daroussin return (false); 174cddcb259SBaptiste Daroussin } 175cddcb259SBaptiste Daroussin 176cddcb259SBaptiste Daroussin static int 1776af5d161SAllan Jude sesled(int argc, char **argv, bool setfault) 178cddcb259SBaptiste Daroussin { 179cddcb259SBaptiste Daroussin encioc_elm_devnames_t objdn; 180cddcb259SBaptiste Daroussin encioc_element_t *objp; 181cddcb259SBaptiste Daroussin glob_t g; 1828729f5ecSAllan Jude char *disk, *endptr; 1838729f5ecSAllan Jude size_t len, i, ndisks; 1848729f5ecSAllan Jude int fd; 1858729f5ecSAllan Jude unsigned int nobj, j, sesid; 1868729f5ecSAllan Jude bool all, isses, onoff; 187cddcb259SBaptiste Daroussin 1888729f5ecSAllan Jude isses = false; 1898729f5ecSAllan Jude all = false; 1908729f5ecSAllan Jude onoff = false; 1918729f5ecSAllan Jude 1928729f5ecSAllan Jude if (argc != 3) { 1936af5d161SAllan Jude usage(stderr, (setfault ? "fault" : "locate")); 194cddcb259SBaptiste Daroussin } 195cddcb259SBaptiste Daroussin 1968729f5ecSAllan Jude disk = argv[1]; 197cddcb259SBaptiste Daroussin 1988729f5ecSAllan Jude sesid = strtoul(disk, &endptr, 10); 1998729f5ecSAllan Jude if (*endptr == '\0') { 2008729f5ecSAllan Jude endptr = strrchr(uflag, '*'); 20196e6c444SBaptiste Daroussin if (endptr != NULL && *endptr == '*') { 202d25c1ff6SBaptiste Daroussin xo_warnx("Must specifying a SES device (-u) to use a SES " 2038729f5ecSAllan Jude "id# to identify a disk"); 2046af5d161SAllan Jude usage(stderr, (setfault ? "fault" : "locate")); 2058729f5ecSAllan Jude } 2068729f5ecSAllan Jude isses = true; 2078729f5ecSAllan Jude } 2088729f5ecSAllan Jude 2098729f5ecSAllan Jude if (strcmp(argv[2], "on") == 0) { 2104569e7cfSBaptiste Daroussin onoff = true; 2118729f5ecSAllan Jude } else if (strcmp(argv[2], "off") == 0) { 2124569e7cfSBaptiste Daroussin onoff = false; 213cddcb259SBaptiste Daroussin } else { 2146af5d161SAllan Jude usage(stderr, (setfault ? "fault" : "locate")); 215cddcb259SBaptiste Daroussin } 216cddcb259SBaptiste Daroussin 217cddcb259SBaptiste Daroussin if (strcmp(disk, "all") == 0) { 218cddcb259SBaptiste Daroussin all = true; 219cddcb259SBaptiste Daroussin } 220cddcb259SBaptiste Daroussin len = strlen(disk); 221cddcb259SBaptiste Daroussin 222cddcb259SBaptiste Daroussin /* Get the list of ses devices */ 2238729f5ecSAllan Jude if (glob((uflag != NULL ? uflag : "/dev/ses[0-9]*"), 0, NULL, &g) == 2248729f5ecSAllan Jude GLOB_NOMATCH) { 2258729f5ecSAllan Jude globfree(&g); 226d25c1ff6SBaptiste Daroussin xo_errx(EXIT_FAILURE, "No SES devices found"); 2278729f5ecSAllan Jude } 2288729f5ecSAllan Jude 2298729f5ecSAllan Jude ndisks = 0; 2308729f5ecSAllan Jude for (i = 0; i < g.gl_pathc; i++) { 2318729f5ecSAllan Jude /* ensure we only got numbers after ses */ 2328729f5ecSAllan Jude if (strspn(g.gl_pathv[i] + 8, "0123456789") != 2338729f5ecSAllan Jude strlen(g.gl_pathv[i] + 8)) { 2348729f5ecSAllan Jude continue; 2358729f5ecSAllan Jude } 2368729f5ecSAllan Jude if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) { 2378729f5ecSAllan Jude /* 2388729f5ecSAllan Jude * Don't treat non-access errors as critical if we are 2398729f5ecSAllan Jude * accessing all devices 2408729f5ecSAllan Jude */ 2418729f5ecSAllan Jude if (errno == EACCES && g.gl_pathc > 1) { 242d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "unable to access SES device"); 2438729f5ecSAllan Jude } 244d25c1ff6SBaptiste Daroussin xo_warn("unable to access SES device: %s", g.gl_pathv[i]); 2458729f5ecSAllan Jude continue; 2468729f5ecSAllan Jude } 2478729f5ecSAllan Jude 2488729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj) < 0) { 2498729f5ecSAllan Jude close(fd); 250d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "ENCIOC_GETNELM"); 2518729f5ecSAllan Jude } 2528729f5ecSAllan Jude 2538729f5ecSAllan Jude objp = calloc(nobj, sizeof(encioc_element_t)); 2548729f5ecSAllan Jude if (objp == NULL) { 2558729f5ecSAllan Jude close(fd); 256d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "calloc()"); 2578729f5ecSAllan Jude } 2588729f5ecSAllan Jude 2598729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETELMMAP, (caddr_t) objp) < 0) { 260a221b104SAlan Somers free(objp); 2618729f5ecSAllan Jude close(fd); 262d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "ENCIOC_GETELMMAP"); 2638729f5ecSAllan Jude } 2648729f5ecSAllan Jude 2658729f5ecSAllan Jude if (isses) { 266691a834cSAlan Somers if (sesid >= nobj) { 267a221b104SAlan Somers free(objp); 2688729f5ecSAllan Jude close(fd); 269d25c1ff6SBaptiste Daroussin xo_errx(EXIT_FAILURE, 2708729f5ecSAllan Jude "Requested SES ID does not exist"); 2718729f5ecSAllan Jude } 272fe74eaabSAlexander Motin do_led(fd, sesid, objp[sesid].elm_type, onoff, setfault); 2738729f5ecSAllan Jude ndisks++; 274a221b104SAlan Somers free(objp); 2758729f5ecSAllan Jude close(fd); 2768729f5ecSAllan Jude break; 2778729f5ecSAllan Jude } 2788729f5ecSAllan Jude for (j = 0; j < nobj; j++) { 2799f96f106SAlan Somers const int devnames_size = 128; 2809f96f106SAlan Somers char devnames[devnames_size]; 2819f96f106SAlan Somers 28224ffc649SAllan Jude if (all) { 283fe74eaabSAlexander Motin do_led(fd, objp[j].elm_idx, objp[j].elm_type, 284fe74eaabSAlexander Motin onoff, setfault); 28524ffc649SAllan Jude continue; 28624ffc649SAllan Jude } 2878729f5ecSAllan Jude memset(&objdn, 0, sizeof(objdn)); 2889f96f106SAlan Somers memset(devnames, 0, devnames_size); 2898729f5ecSAllan Jude objdn.elm_idx = objp[j].elm_idx; 2909f96f106SAlan Somers objdn.elm_names_size = devnames_size; 2919f96f106SAlan Somers objdn.elm_devnames = devnames; 2928729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETELMDEVNAMES, 2938729f5ecSAllan Jude (caddr_t) &objdn) <0) { 2948729f5ecSAllan Jude continue; 2958729f5ecSAllan Jude } 2968729f5ecSAllan Jude if (objdn.elm_names_len > 0) { 2978729f5ecSAllan Jude if (disk_match(objdn.elm_devnames, disk, len)) { 298fe74eaabSAlexander Motin do_led(fd, objdn.elm_idx, objp[j].elm_type, 2996af5d161SAllan Jude onoff, setfault); 3008729f5ecSAllan Jude ndisks++; 3018729f5ecSAllan Jude break; 3028729f5ecSAllan Jude } 3038729f5ecSAllan Jude } 3048729f5ecSAllan Jude } 305f734685eSBaptiste Daroussin free(objp); 3068729f5ecSAllan Jude close(fd); 3078729f5ecSAllan Jude } 3088729f5ecSAllan Jude globfree(&g); 3098729f5ecSAllan Jude if (ndisks == 0 && all == false) { 310d25c1ff6SBaptiste Daroussin xo_errx(EXIT_FAILURE, "Count not find the SES id of device '%s'", 3118729f5ecSAllan Jude disk); 3128729f5ecSAllan Jude } 3138729f5ecSAllan Jude 3148729f5ecSAllan Jude return (EXIT_SUCCESS); 3158729f5ecSAllan Jude } 3168729f5ecSAllan Jude 3178729f5ecSAllan Jude static int 3188729f5ecSAllan Jude locate(int argc, char **argv) 3198729f5ecSAllan Jude { 3208729f5ecSAllan Jude 3218729f5ecSAllan Jude return (sesled(argc, argv, false)); 3228729f5ecSAllan Jude } 3238729f5ecSAllan Jude 3248729f5ecSAllan Jude static int 3258729f5ecSAllan Jude fault(int argc, char **argv) 3268729f5ecSAllan Jude { 3278729f5ecSAllan Jude 3288729f5ecSAllan Jude return (sesled(argc, argv, true)); 3298729f5ecSAllan Jude } 3308729f5ecSAllan Jude 33120a957e3SBaptiste Daroussin static void 3328ad16e55SEdward Tomasz Napierala sesutil_print(int *style, const char *fmt, ...) 33320a957e3SBaptiste Daroussin { 33420a957e3SBaptiste Daroussin va_list args; 33520a957e3SBaptiste Daroussin 3368ad16e55SEdward Tomasz Napierala if (*style == PRINT_STYLE_DASHED) { 337d25c1ff6SBaptiste Daroussin xo_open_container("extra_status"); 338d25c1ff6SBaptiste Daroussin xo_emit("\t\tExtra status:\n"); 3398ad16e55SEdward Tomasz Napierala *style = PRINT_STYLE_DASHED_2; 3408ad16e55SEdward Tomasz Napierala } else if (*style == PRINT_STYLE_CSV) { 3418ad16e55SEdward Tomasz Napierala xo_open_container("extra_status"); 3428ad16e55SEdward Tomasz Napierala *style = PRINT_STYLE_CSV_2; 34320a957e3SBaptiste Daroussin } 3448ad16e55SEdward Tomasz Napierala 3458ad16e55SEdward Tomasz Napierala if (*style == PRINT_STYLE_DASHED_2) 3468ad16e55SEdward Tomasz Napierala xo_emit("\t\t- "); 3478ad16e55SEdward Tomasz Napierala else if (*style == PRINT_STYLE_CSV_2) 3488ad16e55SEdward Tomasz Napierala xo_emit(", "); 34920a957e3SBaptiste Daroussin va_start(args, fmt); 350d25c1ff6SBaptiste Daroussin xo_emit_hv(NULL, fmt, args); 35120a957e3SBaptiste Daroussin va_end(args); 3528ad16e55SEdward Tomasz Napierala if (*style == PRINT_STYLE_DASHED_2) 3538ad16e55SEdward Tomasz Napierala xo_emit("\n"); 35420a957e3SBaptiste Daroussin } 35520a957e3SBaptiste Daroussin 35620a957e3SBaptiste Daroussin static void 3578ad16e55SEdward Tomasz Napierala print_extra_status(int eletype, u_char *cstat, int style) 35820a957e3SBaptiste Daroussin { 35920a957e3SBaptiste Daroussin 36020a957e3SBaptiste Daroussin if (cstat[0] & 0x40) { 3618ad16e55SEdward Tomasz Napierala sesutil_print(&style, "{e:predicted_failure/true} Predicted Failure"); 36220a957e3SBaptiste Daroussin } 36320a957e3SBaptiste Daroussin if (cstat[0] & 0x20) { 3648ad16e55SEdward Tomasz Napierala sesutil_print(&style, "{e:disabled/true} Disabled"); 36520a957e3SBaptiste Daroussin } 36620a957e3SBaptiste Daroussin if (cstat[0] & 0x10) { 3678ad16e55SEdward Tomasz Napierala sesutil_print(&style, "{e:swapped/true} Swapped"); 36820a957e3SBaptiste Daroussin } 36920a957e3SBaptiste Daroussin switch (eletype) { 37020a957e3SBaptiste Daroussin case ELMTYP_DEVICE: 37120a957e3SBaptiste Daroussin case ELMTYP_ARRAY_DEV: 37220a957e3SBaptiste Daroussin if (cstat[2] & 0x02) { 3738ad16e55SEdward Tomasz Napierala sesutil_print(&style, "LED={q:led/locate}"); 37420a957e3SBaptiste Daroussin } 37520a957e3SBaptiste Daroussin if (cstat[2] & 0x20) { 3768ad16e55SEdward Tomasz Napierala sesutil_print(&style, "LED={q:led/fault}"); 37720a957e3SBaptiste Daroussin } 37820a957e3SBaptiste Daroussin break; 37920a957e3SBaptiste Daroussin case ELMTYP_FAN: 3808ad16e55SEdward Tomasz Napierala sesutil_print(&style, "Speed: {:speed/%d}{Uw:rpm}", 38120a957e3SBaptiste Daroussin (((0x7 & cstat[1]) << 8) + cstat[2]) * 10); 38220a957e3SBaptiste Daroussin break; 38320a957e3SBaptiste Daroussin case ELMTYP_THERM: 38420a957e3SBaptiste Daroussin if (cstat[2]) { 3858ad16e55SEdward Tomasz Napierala sesutil_print(&style, "Temperature: {:temperature/%d}{Uw:C}", 38620a957e3SBaptiste Daroussin cstat[2] - TEMPERATURE_OFFSET); 38720a957e3SBaptiste Daroussin } else { 3888ad16e55SEdward Tomasz Napierala sesutil_print(&style, "Temperature: -{q:temperature/reserved}"); 38920a957e3SBaptiste Daroussin } 39020a957e3SBaptiste Daroussin break; 39120a957e3SBaptiste Daroussin case ELMTYP_VOM: 3928ad16e55SEdward Tomasz Napierala sesutil_print(&style, "Voltage: {:voltage/%.2f}{Uw:V}", 39320a957e3SBaptiste Daroussin be16dec(cstat + 2) / 100.0); 39420a957e3SBaptiste Daroussin break; 39520a957e3SBaptiste Daroussin } 3968ad16e55SEdward Tomasz Napierala if (style) { 397d25c1ff6SBaptiste Daroussin xo_close_container("extra_status"); 398d25c1ff6SBaptiste Daroussin } 39920a957e3SBaptiste Daroussin } 40020a957e3SBaptiste Daroussin 4018729f5ecSAllan Jude static int 4028729f5ecSAllan Jude objmap(int argc, char **argv __unused) 4038729f5ecSAllan Jude { 40460f46640SBaptiste Daroussin encioc_string_t stri; 4058729f5ecSAllan Jude encioc_elm_devnames_t e_devname; 4068729f5ecSAllan Jude encioc_elm_status_t e_status; 4078729f5ecSAllan Jude encioc_elm_desc_t e_desc; 4088729f5ecSAllan Jude encioc_element_t *e_ptr; 4098729f5ecSAllan Jude glob_t g; 4108729f5ecSAllan Jude int fd; 4118729f5ecSAllan Jude unsigned int j, nobj; 4128729f5ecSAllan Jude size_t i; 41360f46640SBaptiste Daroussin char str[32]; 4148729f5ecSAllan Jude 4158729f5ecSAllan Jude if (argc != 1) { 4168729f5ecSAllan Jude usage(stderr, "map"); 4178729f5ecSAllan Jude } 4188729f5ecSAllan Jude 4198729f5ecSAllan Jude /* Get the list of ses devices */ 4208729f5ecSAllan Jude if (glob(uflag, 0, NULL, &g) == GLOB_NOMATCH) { 421cddcb259SBaptiste Daroussin globfree(&g); 422d25c1ff6SBaptiste Daroussin xo_errx(EXIT_FAILURE, "No SES devices found"); 423cddcb259SBaptiste Daroussin } 424d25c1ff6SBaptiste Daroussin xo_set_version(SESUTIL_XO_VERSION); 425d25c1ff6SBaptiste Daroussin xo_open_container("sesutil"); 426d25c1ff6SBaptiste Daroussin xo_open_list("enclosures"); 427cddcb259SBaptiste Daroussin for (i = 0; i < g.gl_pathc; i++) { 428cddcb259SBaptiste Daroussin /* ensure we only got numbers after ses */ 429cddcb259SBaptiste Daroussin if (strspn(g.gl_pathv[i] + 8, "0123456789") != 4308729f5ecSAllan Jude strlen(g.gl_pathv[i] + 8)) { 431cddcb259SBaptiste Daroussin continue; 4328729f5ecSAllan Jude } 433cddcb259SBaptiste Daroussin if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) { 4348729f5ecSAllan Jude /* 4358729f5ecSAllan Jude * Don't treat non-access errors as critical if we are 4368729f5ecSAllan Jude * accessing all devices 4378729f5ecSAllan Jude */ 4388729f5ecSAllan Jude if (errno == EACCES && g.gl_pathc > 1) { 439d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "unable to access SES device"); 4408729f5ecSAllan Jude } 441d25c1ff6SBaptiste Daroussin xo_warn("unable to access SES device: %s", g.gl_pathv[i]); 4428729f5ecSAllan Jude continue; 443cddcb259SBaptiste Daroussin } 444cddcb259SBaptiste Daroussin 4458729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj) < 0) { 4468729f5ecSAllan Jude close(fd); 447d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "ENCIOC_GETNELM"); 4488729f5ecSAllan Jude } 449cddcb259SBaptiste Daroussin 4508729f5ecSAllan Jude e_ptr = calloc(nobj, sizeof(encioc_element_t)); 4518729f5ecSAllan Jude if (e_ptr == NULL) { 4528729f5ecSAllan Jude close(fd); 453d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "calloc()"); 4548729f5ecSAllan Jude } 455cddcb259SBaptiste Daroussin 4568729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETELMMAP, (caddr_t) e_ptr) < 0) { 4578729f5ecSAllan Jude close(fd); 458d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "ENCIOC_GETELMMAP"); 4598729f5ecSAllan Jude } 460cddcb259SBaptiste Daroussin 461d25c1ff6SBaptiste Daroussin xo_open_instance("enclosures"); 462d25c1ff6SBaptiste Daroussin xo_emit("{t:enc/%s}:\n", g.gl_pathv[i] + 5); 46360f46640SBaptiste Daroussin stri.bufsiz = sizeof(str); 46460f46640SBaptiste Daroussin stri.buf = &str[0]; 46560f46640SBaptiste Daroussin if (ioctl(fd, ENCIOC_GETENCNAME, (caddr_t) &stri) == 0) 466d25c1ff6SBaptiste Daroussin xo_emit("\tEnclosure Name: {t:name/%s}\n", stri.buf); 46760f46640SBaptiste Daroussin stri.bufsiz = sizeof(str); 46860f46640SBaptiste Daroussin stri.buf = &str[0]; 46960f46640SBaptiste Daroussin if (ioctl(fd, ENCIOC_GETENCID, (caddr_t) &stri) == 0) 470d25c1ff6SBaptiste Daroussin xo_emit("\tEnclosure ID: {t:id/%s}\n", stri.buf); 47160f46640SBaptiste Daroussin 472d25c1ff6SBaptiste Daroussin xo_open_list("elements"); 473cddcb259SBaptiste Daroussin for (j = 0; j < nobj; j++) { 4748729f5ecSAllan Jude /* Get the status of the element */ 4758729f5ecSAllan Jude memset(&e_status, 0, sizeof(e_status)); 4768729f5ecSAllan Jude e_status.elm_idx = e_ptr[j].elm_idx; 4778729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETELMSTAT, 4788729f5ecSAllan Jude (caddr_t) &e_status) < 0) { 4798729f5ecSAllan Jude close(fd); 480d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "ENCIOC_GETELMSTAT"); 4818729f5ecSAllan Jude } 4828729f5ecSAllan Jude /* Get the description of the element */ 4838729f5ecSAllan Jude memset(&e_desc, 0, sizeof(e_desc)); 4848729f5ecSAllan Jude e_desc.elm_idx = e_ptr[j].elm_idx; 4858729f5ecSAllan Jude e_desc.elm_desc_len = UINT16_MAX; 4868729f5ecSAllan Jude e_desc.elm_desc_str = calloc(UINT16_MAX, sizeof(char)); 4878729f5ecSAllan Jude if (e_desc.elm_desc_str == NULL) { 4888729f5ecSAllan Jude close(fd); 489d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "calloc()"); 4908729f5ecSAllan Jude } 4918729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETELMDESC, 4928729f5ecSAllan Jude (caddr_t) &e_desc) < 0) { 4938729f5ecSAllan Jude close(fd); 494d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "ENCIOC_GETELMDESC"); 4958729f5ecSAllan Jude } 4968729f5ecSAllan Jude /* Get the device name(s) of the element */ 4978729f5ecSAllan Jude memset(&e_devname, 0, sizeof(e_devname)); 4988729f5ecSAllan Jude e_devname.elm_idx = e_ptr[j].elm_idx; 4998729f5ecSAllan Jude e_devname.elm_names_size = 128; 5008729f5ecSAllan Jude e_devname.elm_devnames = calloc(128, sizeof(char)); 5018729f5ecSAllan Jude if (e_devname.elm_devnames == NULL) { 5028729f5ecSAllan Jude close(fd); 503d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "calloc()"); 5048729f5ecSAllan Jude } 505cddcb259SBaptiste Daroussin if (ioctl(fd, ENCIOC_GETELMDEVNAMES, 5068729f5ecSAllan Jude (caddr_t) &e_devname) <0) { 5078729f5ecSAllan Jude /* We don't care if this fails */ 5088729f5ecSAllan Jude e_devname.elm_devnames[0] = '\0'; 509cddcb259SBaptiste Daroussin } 510d25c1ff6SBaptiste Daroussin xo_open_instance("elements"); 511d25c1ff6SBaptiste Daroussin xo_emit("\tElement {:id/%u}, Type: {:type/%s}\n", e_ptr[j].elm_idx, 5128729f5ecSAllan Jude geteltnm(e_ptr[j].elm_type)); 513d25c1ff6SBaptiste Daroussin xo_emit("\t\tStatus: {:status/%s} ({q:status_code/0x%02x 0x%02x 0x%02x 0x%02x})\n", 514d7654478SBaptiste Daroussin scode2ascii(e_status.cstat[0]), e_status.cstat[0], 515d7654478SBaptiste Daroussin e_status.cstat[1], e_status.cstat[2], 516d7654478SBaptiste Daroussin e_status.cstat[3]); 5178729f5ecSAllan Jude if (e_desc.elm_desc_len > 0) { 518d25c1ff6SBaptiste Daroussin xo_emit("\t\tDescription: {:description/%s}\n", 5198729f5ecSAllan Jude e_desc.elm_desc_str); 520cddcb259SBaptiste Daroussin } 5218729f5ecSAllan Jude if (e_devname.elm_names_len > 0) { 522d25c1ff6SBaptiste Daroussin xo_emit("\t\tDevice Names: {:device_names/%s}\n", 5238729f5ecSAllan Jude e_devname.elm_devnames); 524cddcb259SBaptiste Daroussin } 5258ad16e55SEdward Tomasz Napierala print_extra_status(e_ptr[j].elm_type, e_status.cstat, PRINT_STYLE_DASHED); 526d25c1ff6SBaptiste Daroussin xo_close_instance("elements"); 5278729f5ecSAllan Jude free(e_devname.elm_devnames); 528cddcb259SBaptiste Daroussin } 529d25c1ff6SBaptiste Daroussin xo_close_list("elements"); 530f734685eSBaptiste Daroussin free(e_ptr); 531cddcb259SBaptiste Daroussin close(fd); 532cddcb259SBaptiste Daroussin } 533cddcb259SBaptiste Daroussin globfree(&g); 534d25c1ff6SBaptiste Daroussin xo_close_list("enclosures"); 535d25c1ff6SBaptiste Daroussin xo_close_container("sesutil"); 536d25c1ff6SBaptiste Daroussin xo_finish(); 537cddcb259SBaptiste Daroussin 538cddcb259SBaptiste Daroussin return (EXIT_SUCCESS); 539cddcb259SBaptiste Daroussin } 540cddcb259SBaptiste Daroussin 5418ad16e55SEdward Tomasz Napierala /* 5428ad16e55SEdward Tomasz Napierala * Get rid of the 'passN' devices, unless there's nothing else to show. 5438ad16e55SEdward Tomasz Napierala */ 5448ad16e55SEdward Tomasz Napierala static void 5458ad16e55SEdward Tomasz Napierala skip_pass_devices(char *devnames, size_t devnameslen) 5468ad16e55SEdward Tomasz Napierala { 5478ad16e55SEdward Tomasz Napierala char *dev, devs[128], passes[128], *tmp; 5488ad16e55SEdward Tomasz Napierala 5498ad16e55SEdward Tomasz Napierala devs[0] = passes[0] = '\0'; 5508ad16e55SEdward Tomasz Napierala tmp = devnames; 5518ad16e55SEdward Tomasz Napierala 5528ad16e55SEdward Tomasz Napierala while ((dev = strsep(&tmp, ",")) != NULL) { 5538ad16e55SEdward Tomasz Napierala if (strncmp(dev, "pass", 4) == 0) { 5548ad16e55SEdward Tomasz Napierala if (passes[0] != '\0') 5558ad16e55SEdward Tomasz Napierala strlcat(passes, ",", sizeof(passes)); 5568ad16e55SEdward Tomasz Napierala strlcat(passes, dev, sizeof(passes)); 5578ad16e55SEdward Tomasz Napierala } else { 5588ad16e55SEdward Tomasz Napierala if (devs[0] != '\0') 5598ad16e55SEdward Tomasz Napierala strlcat(devs, ",", sizeof(devs)); 5608ad16e55SEdward Tomasz Napierala strlcat(devs, dev, sizeof(devs)); 5618ad16e55SEdward Tomasz Napierala } 5628ad16e55SEdward Tomasz Napierala } 5638ad16e55SEdward Tomasz Napierala strlcpy(devnames, devs, devnameslen); 5648ad16e55SEdward Tomasz Napierala if (devnames[0] == '\0') 5658ad16e55SEdward Tomasz Napierala strlcpy(devnames, passes, devnameslen); 5668ad16e55SEdward Tomasz Napierala } 5678ad16e55SEdward Tomasz Napierala 5688ad16e55SEdward Tomasz Napierala static void 5698ad16e55SEdward Tomasz Napierala fetch_device_details(char *devnames, char **model, char **serial, off_t *size) 5708ad16e55SEdward Tomasz Napierala { 5718ad16e55SEdward Tomasz Napierala char ident[DISK_IDENT_SIZE]; 5728ad16e55SEdward Tomasz Napierala struct diocgattr_arg arg; 573f05cc0f1SAlan Somers char *tmp; 5748ad16e55SEdward Tomasz Napierala off_t mediasize; 575f05cc0f1SAlan Somers int comma; 5768ad16e55SEdward Tomasz Napierala int fd; 5778ad16e55SEdward Tomasz Napierala 578f05cc0f1SAlan Somers comma = (int)strcspn(devnames, ","); 579f05cc0f1SAlan Somers asprintf(&tmp, "/dev/%.*s", comma, devnames); 5808ad16e55SEdward Tomasz Napierala if (tmp == NULL) 581f05cc0f1SAlan Somers err(1, "asprintf"); 5828ad16e55SEdward Tomasz Napierala fd = open(tmp, O_RDONLY); 583f05cc0f1SAlan Somers free(tmp); 5848ad16e55SEdward Tomasz Napierala if (fd < 0) { 5858ad16e55SEdward Tomasz Napierala /* 5868ad16e55SEdward Tomasz Napierala * This can happen with a disk so broken it cannot 5878ad16e55SEdward Tomasz Napierala * be probed by GEOM. 5888ad16e55SEdward Tomasz Napierala */ 5898ad16e55SEdward Tomasz Napierala *model = strdup("?"); 5908ad16e55SEdward Tomasz Napierala *serial = strdup("?"); 5918ad16e55SEdward Tomasz Napierala *size = -1; 592f05cc0f1SAlan Somers close(fd); 5938ad16e55SEdward Tomasz Napierala return; 5948ad16e55SEdward Tomasz Napierala } 5958ad16e55SEdward Tomasz Napierala 5968ad16e55SEdward Tomasz Napierala strlcpy(arg.name, "GEOM::descr", sizeof(arg.name)); 5978ad16e55SEdward Tomasz Napierala arg.len = sizeof(arg.value.str); 5988ad16e55SEdward Tomasz Napierala if (ioctl(fd, DIOCGATTR, &arg) == 0) 5998ad16e55SEdward Tomasz Napierala *model = strdup(arg.value.str); 6008ad16e55SEdward Tomasz Napierala else 6018ad16e55SEdward Tomasz Napierala *model = NULL; 6028ad16e55SEdward Tomasz Napierala 6038ad16e55SEdward Tomasz Napierala if (ioctl(fd, DIOCGIDENT, ident) == 0) 6048ad16e55SEdward Tomasz Napierala *serial = strdup(ident); 6058ad16e55SEdward Tomasz Napierala else 6068ad16e55SEdward Tomasz Napierala *serial = NULL; 6078ad16e55SEdward Tomasz Napierala 6088ad16e55SEdward Tomasz Napierala if (ioctl(fd, DIOCGMEDIASIZE, &mediasize) == 0) 6098ad16e55SEdward Tomasz Napierala *size = mediasize; 6108ad16e55SEdward Tomasz Napierala else 6118ad16e55SEdward Tomasz Napierala *size = -1; 612f05cc0f1SAlan Somers close(fd); 6138ad16e55SEdward Tomasz Napierala } 6148ad16e55SEdward Tomasz Napierala 6158ad16e55SEdward Tomasz Napierala static void 6168ad16e55SEdward Tomasz Napierala show_device(int fd, int elm_idx, encioc_elm_status_t e_status, encioc_elm_desc_t e_desc) 6178ad16e55SEdward Tomasz Napierala { 6188ad16e55SEdward Tomasz Napierala encioc_elm_devnames_t e_devname; 6198ad16e55SEdward Tomasz Napierala char *model, *serial; 6208ad16e55SEdward Tomasz Napierala off_t size; 6218ad16e55SEdward Tomasz Napierala 6228ad16e55SEdward Tomasz Napierala /* Get the device name(s) of the element */ 6238ad16e55SEdward Tomasz Napierala memset(&e_devname, 0, sizeof(e_devname)); 6248ad16e55SEdward Tomasz Napierala e_devname.elm_idx = elm_idx; 6258ad16e55SEdward Tomasz Napierala e_devname.elm_names_size = 128; 6268ad16e55SEdward Tomasz Napierala e_devname.elm_devnames = calloc(128, sizeof(char)); 6278ad16e55SEdward Tomasz Napierala if (e_devname.elm_devnames == NULL) { 6288ad16e55SEdward Tomasz Napierala close(fd); 6298ad16e55SEdward Tomasz Napierala xo_err(EXIT_FAILURE, "calloc()"); 6308ad16e55SEdward Tomasz Napierala } 6318ad16e55SEdward Tomasz Napierala 6328ad16e55SEdward Tomasz Napierala if (ioctl(fd, ENCIOC_GETELMDEVNAMES, 6338ad16e55SEdward Tomasz Napierala (caddr_t) &e_devname) < 0) { 6348ad16e55SEdward Tomasz Napierala /* We don't care if this fails */ 6358ad16e55SEdward Tomasz Napierala e_devname.elm_devnames[0] = '\0'; 6368ad16e55SEdward Tomasz Napierala model = NULL; 6378ad16e55SEdward Tomasz Napierala serial = NULL; 6388ad16e55SEdward Tomasz Napierala size = -1; 6398ad16e55SEdward Tomasz Napierala } else { 6408ad16e55SEdward Tomasz Napierala skip_pass_devices(e_devname.elm_devnames, 128); 6418ad16e55SEdward Tomasz Napierala fetch_device_details(e_devname.elm_devnames, &model, &serial, &size); 6428ad16e55SEdward Tomasz Napierala } 6438ad16e55SEdward Tomasz Napierala xo_open_instance("elements"); 6448ad16e55SEdward Tomasz Napierala xo_emit("{e:type/device_slot}"); 6458ad16e55SEdward Tomasz Napierala xo_emit("{d:description/%-8s} ", e_desc.elm_desc_len > 0 ? e_desc.elm_desc_str : "-"); 6468ad16e55SEdward Tomasz Napierala xo_emit("{e:description/%-8s}", e_desc.elm_desc_len > 0 ? e_desc.elm_desc_str : ""); 6478ad16e55SEdward Tomasz Napierala xo_emit("{d:device_names/%-7s} ", e_devname.elm_names_len > 0 ? e_devname.elm_devnames : "-"); 6488ad16e55SEdward Tomasz Napierala xo_emit("{e:device_names/%s}", e_devname.elm_names_len > 0 ? e_devname.elm_devnames : ""); 6498ad16e55SEdward Tomasz Napierala xo_emit("{d:model/%-25s} ", model ? model : "-"); 6508ad16e55SEdward Tomasz Napierala xo_emit("{e:model/%s}", model ? model : ""); 6518ad16e55SEdward Tomasz Napierala xo_emit("{d:serial/%-20s} ", serial != NULL ? serial : "-"); 6528ad16e55SEdward Tomasz Napierala xo_emit("{e:serial/%s}", serial != NULL ? serial : ""); 653*a1571967SEdward Tomasz Napierala if ((e_status.cstat[0] & 0xf) == SES_OBJSTAT_OK && size >= 0) { 6548ad16e55SEdward Tomasz Napierala xo_emit("{h,hn-1000:size/%ld}{e:status/%s}", 6558ad16e55SEdward Tomasz Napierala size, scode2ascii(e_status.cstat[0])); 6568ad16e55SEdward Tomasz Napierala } else { 6578ad16e55SEdward Tomasz Napierala xo_emit("{:status/%s}", scode2ascii(e_status.cstat[0])); 6588ad16e55SEdward Tomasz Napierala } 6598ad16e55SEdward Tomasz Napierala print_extra_status(ELMTYP_ARRAY_DEV, e_status.cstat, PRINT_STYLE_CSV); 6608ad16e55SEdward Tomasz Napierala xo_emit("\n"); 6618ad16e55SEdward Tomasz Napierala xo_close_instance("elements"); 6628ad16e55SEdward Tomasz Napierala free(e_devname.elm_devnames); 6638ad16e55SEdward Tomasz Napierala } 6648ad16e55SEdward Tomasz Napierala 6658ad16e55SEdward Tomasz Napierala static void 6668ad16e55SEdward Tomasz Napierala show_therm(encioc_elm_status_t e_status, encioc_elm_desc_t e_desc) 6678ad16e55SEdward Tomasz Napierala { 6688ad16e55SEdward Tomasz Napierala 6698ad16e55SEdward Tomasz Napierala if (e_desc.elm_desc_len <= 0) { 6708ad16e55SEdward Tomasz Napierala /* We don't have a label to display; might as well skip it. */ 6718ad16e55SEdward Tomasz Napierala return; 6728ad16e55SEdward Tomasz Napierala } 6738ad16e55SEdward Tomasz Napierala 6748ad16e55SEdward Tomasz Napierala if (e_status.cstat[2] == 0) { 6758ad16e55SEdward Tomasz Napierala /* No temperature to show. */ 6768ad16e55SEdward Tomasz Napierala return; 6778ad16e55SEdward Tomasz Napierala } 6788ad16e55SEdward Tomasz Napierala 6798ad16e55SEdward Tomasz Napierala xo_open_instance("elements"); 6808ad16e55SEdward Tomasz Napierala xo_emit("{e:type/temperature_sensor}"); 6818ad16e55SEdward Tomasz Napierala xo_emit("{:description/%s}: {:temperature/%d}{Uw:C}", 6828ad16e55SEdward Tomasz Napierala e_desc.elm_desc_str, e_status.cstat[2] - TEMPERATURE_OFFSET); 6838ad16e55SEdward Tomasz Napierala xo_close_instance("elements"); 6848ad16e55SEdward Tomasz Napierala } 6858ad16e55SEdward Tomasz Napierala 6868ad16e55SEdward Tomasz Napierala static void 6878ad16e55SEdward Tomasz Napierala show_vom(encioc_elm_status_t e_status, encioc_elm_desc_t e_desc) 6888ad16e55SEdward Tomasz Napierala { 6898ad16e55SEdward Tomasz Napierala 6908ad16e55SEdward Tomasz Napierala if (e_desc.elm_desc_len <= 0) { 6918ad16e55SEdward Tomasz Napierala /* We don't have a label to display; might as well skip it. */ 6928ad16e55SEdward Tomasz Napierala return; 6938ad16e55SEdward Tomasz Napierala } 6948ad16e55SEdward Tomasz Napierala 6958ad16e55SEdward Tomasz Napierala if (e_status.cstat[2] == 0) { 6968ad16e55SEdward Tomasz Napierala /* No voltage to show. */ 6978ad16e55SEdward Tomasz Napierala return; 6988ad16e55SEdward Tomasz Napierala } 6998ad16e55SEdward Tomasz Napierala 7008ad16e55SEdward Tomasz Napierala xo_open_instance("elements"); 7018ad16e55SEdward Tomasz Napierala xo_emit("{e:type/voltage_sensor}"); 7028ad16e55SEdward Tomasz Napierala xo_emit("{:description/%s}: {:voltage/%.2f}{Uw:V}", 7038ad16e55SEdward Tomasz Napierala e_desc.elm_desc_str, be16dec(e_status.cstat + 2) / 100.0); 7048ad16e55SEdward Tomasz Napierala xo_close_instance("elements"); 7058ad16e55SEdward Tomasz Napierala } 7068ad16e55SEdward Tomasz Napierala 7078ad16e55SEdward Tomasz Napierala static int 7088ad16e55SEdward Tomasz Napierala show(int argc, char **argv __unused) 7098ad16e55SEdward Tomasz Napierala { 7108ad16e55SEdward Tomasz Napierala encioc_string_t stri; 7118ad16e55SEdward Tomasz Napierala encioc_elm_status_t e_status; 7128ad16e55SEdward Tomasz Napierala encioc_elm_desc_t e_desc; 7138ad16e55SEdward Tomasz Napierala encioc_element_t *e_ptr; 7148ad16e55SEdward Tomasz Napierala glob_t g; 7158ad16e55SEdward Tomasz Napierala elm_type_t prev_type; 7168ad16e55SEdward Tomasz Napierala int fd; 7178ad16e55SEdward Tomasz Napierala unsigned int j, nobj; 7188ad16e55SEdward Tomasz Napierala size_t i; 7198ad16e55SEdward Tomasz Napierala bool first_ses; 7208ad16e55SEdward Tomasz Napierala char str[32]; 7218ad16e55SEdward Tomasz Napierala 7228ad16e55SEdward Tomasz Napierala if (argc != 1) { 7238ad16e55SEdward Tomasz Napierala usage(stderr, "map"); 7248ad16e55SEdward Tomasz Napierala } 7258ad16e55SEdward Tomasz Napierala 7268ad16e55SEdward Tomasz Napierala first_ses = true; 7278ad16e55SEdward Tomasz Napierala 7288ad16e55SEdward Tomasz Napierala /* Get the list of ses devices */ 7298ad16e55SEdward Tomasz Napierala if (glob(uflag, 0, NULL, &g) == GLOB_NOMATCH) { 7308ad16e55SEdward Tomasz Napierala globfree(&g); 7318ad16e55SEdward Tomasz Napierala xo_errx(EXIT_FAILURE, "No SES devices found"); 7328ad16e55SEdward Tomasz Napierala } 7338ad16e55SEdward Tomasz Napierala xo_set_version(SESUTIL_XO_VERSION); 7348ad16e55SEdward Tomasz Napierala xo_open_container("sesutil"); 7358ad16e55SEdward Tomasz Napierala xo_open_list("enclosures"); 7368ad16e55SEdward Tomasz Napierala for (i = 0; i < g.gl_pathc; i++) { 7378ad16e55SEdward Tomasz Napierala /* ensure we only got numbers after ses */ 7388ad16e55SEdward Tomasz Napierala if (strspn(g.gl_pathv[i] + 8, "0123456789") != 7398ad16e55SEdward Tomasz Napierala strlen(g.gl_pathv[i] + 8)) { 7408ad16e55SEdward Tomasz Napierala continue; 7418ad16e55SEdward Tomasz Napierala } 7428ad16e55SEdward Tomasz Napierala if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) { 7438ad16e55SEdward Tomasz Napierala /* 7448ad16e55SEdward Tomasz Napierala * Don't treat non-access errors as critical if we are 7458ad16e55SEdward Tomasz Napierala * accessing all devices 7468ad16e55SEdward Tomasz Napierala */ 7478ad16e55SEdward Tomasz Napierala if (errno == EACCES && g.gl_pathc > 1) { 7488ad16e55SEdward Tomasz Napierala xo_err(EXIT_FAILURE, "unable to access SES device"); 7498ad16e55SEdward Tomasz Napierala } 7508ad16e55SEdward Tomasz Napierala xo_warn("unable to access SES device: %s", g.gl_pathv[i]); 7518ad16e55SEdward Tomasz Napierala continue; 7528ad16e55SEdward Tomasz Napierala } 7538ad16e55SEdward Tomasz Napierala 7548ad16e55SEdward Tomasz Napierala if (ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj) < 0) { 7558ad16e55SEdward Tomasz Napierala close(fd); 7568ad16e55SEdward Tomasz Napierala xo_err(EXIT_FAILURE, "ENCIOC_GETNELM"); 7578ad16e55SEdward Tomasz Napierala } 7588ad16e55SEdward Tomasz Napierala 7598ad16e55SEdward Tomasz Napierala e_ptr = calloc(nobj, sizeof(encioc_element_t)); 7608ad16e55SEdward Tomasz Napierala if (e_ptr == NULL) { 7618ad16e55SEdward Tomasz Napierala close(fd); 7628ad16e55SEdward Tomasz Napierala xo_err(EXIT_FAILURE, "calloc()"); 7638ad16e55SEdward Tomasz Napierala } 7648ad16e55SEdward Tomasz Napierala 7658ad16e55SEdward Tomasz Napierala if (ioctl(fd, ENCIOC_GETELMMAP, (caddr_t) e_ptr) < 0) { 7668ad16e55SEdward Tomasz Napierala close(fd); 7678ad16e55SEdward Tomasz Napierala xo_err(EXIT_FAILURE, "ENCIOC_GETELMMAP"); 7688ad16e55SEdward Tomasz Napierala } 7698ad16e55SEdward Tomasz Napierala 7708ad16e55SEdward Tomasz Napierala xo_open_instance("enclosures"); 7718ad16e55SEdward Tomasz Napierala 7728ad16e55SEdward Tomasz Napierala if (first_ses) 7738ad16e55SEdward Tomasz Napierala first_ses = false; 7748ad16e55SEdward Tomasz Napierala else 7758ad16e55SEdward Tomasz Napierala xo_emit("\n"); 7768ad16e55SEdward Tomasz Napierala 7778ad16e55SEdward Tomasz Napierala xo_emit("{t:enc/%s}: ", g.gl_pathv[i] + 5); 7788ad16e55SEdward Tomasz Napierala stri.bufsiz = sizeof(str); 7798ad16e55SEdward Tomasz Napierala stri.buf = &str[0]; 7808ad16e55SEdward Tomasz Napierala if (ioctl(fd, ENCIOC_GETENCNAME, (caddr_t) &stri) == 0) 7818ad16e55SEdward Tomasz Napierala xo_emit("<{t:name/%s}>; ", stri.buf); 7828ad16e55SEdward Tomasz Napierala stri.bufsiz = sizeof(str); 7838ad16e55SEdward Tomasz Napierala stri.buf = &str[0]; 7848ad16e55SEdward Tomasz Napierala if (ioctl(fd, ENCIOC_GETENCID, (caddr_t) &stri) == 0) 7858ad16e55SEdward Tomasz Napierala xo_emit("ID: {t:id/%s}", stri.buf); 7868ad16e55SEdward Tomasz Napierala xo_emit("\n"); 7878ad16e55SEdward Tomasz Napierala 7888ad16e55SEdward Tomasz Napierala xo_open_list("elements"); 7898ad16e55SEdward Tomasz Napierala prev_type = -1; 7908ad16e55SEdward Tomasz Napierala for (j = 0; j < nobj; j++) { 7918ad16e55SEdward Tomasz Napierala /* Get the status of the element */ 7928ad16e55SEdward Tomasz Napierala memset(&e_status, 0, sizeof(e_status)); 7938ad16e55SEdward Tomasz Napierala e_status.elm_idx = e_ptr[j].elm_idx; 7948ad16e55SEdward Tomasz Napierala if (ioctl(fd, ENCIOC_GETELMSTAT, 7958ad16e55SEdward Tomasz Napierala (caddr_t) &e_status) < 0) { 7968ad16e55SEdward Tomasz Napierala close(fd); 7978ad16e55SEdward Tomasz Napierala xo_err(EXIT_FAILURE, "ENCIOC_GETELMSTAT"); 7988ad16e55SEdward Tomasz Napierala } 7998ad16e55SEdward Tomasz Napierala 8008ad16e55SEdward Tomasz Napierala /* 8018ad16e55SEdward Tomasz Napierala * Skip "Unsupported" elements; those usually precede 8028ad16e55SEdward Tomasz Napierala * the actual device entries and are not particularly 8038ad16e55SEdward Tomasz Napierala * interesting. 8048ad16e55SEdward Tomasz Napierala */ 8058ad16e55SEdward Tomasz Napierala if (e_status.cstat[0] == SES_OBJSTAT_UNSUPPORTED) 8068ad16e55SEdward Tomasz Napierala continue; 8078ad16e55SEdward Tomasz Napierala 8088ad16e55SEdward Tomasz Napierala /* Get the description of the element */ 8098ad16e55SEdward Tomasz Napierala memset(&e_desc, 0, sizeof(e_desc)); 8108ad16e55SEdward Tomasz Napierala e_desc.elm_idx = e_ptr[j].elm_idx; 8118ad16e55SEdward Tomasz Napierala e_desc.elm_desc_len = UINT16_MAX; 8128ad16e55SEdward Tomasz Napierala e_desc.elm_desc_str = calloc(UINT16_MAX, sizeof(char)); 8138ad16e55SEdward Tomasz Napierala if (e_desc.elm_desc_str == NULL) { 8148ad16e55SEdward Tomasz Napierala close(fd); 8158ad16e55SEdward Tomasz Napierala xo_err(EXIT_FAILURE, "calloc()"); 8168ad16e55SEdward Tomasz Napierala } 8178ad16e55SEdward Tomasz Napierala if (ioctl(fd, ENCIOC_GETELMDESC, 8188ad16e55SEdward Tomasz Napierala (caddr_t) &e_desc) < 0) { 8198ad16e55SEdward Tomasz Napierala close(fd); 8208ad16e55SEdward Tomasz Napierala xo_err(EXIT_FAILURE, "ENCIOC_GETELMDESC"); 8218ad16e55SEdward Tomasz Napierala } 8228ad16e55SEdward Tomasz Napierala 8238ad16e55SEdward Tomasz Napierala switch (e_ptr[j].elm_type) { 8248ad16e55SEdward Tomasz Napierala case ELMTYP_DEVICE: 8258ad16e55SEdward Tomasz Napierala case ELMTYP_ARRAY_DEV: 8268ad16e55SEdward Tomasz Napierala if (e_ptr[j].elm_type != prev_type) 8278ad16e55SEdward Tomasz Napierala xo_emit("Desc Dev Model Ident Size/Status\n"); 8288ad16e55SEdward Tomasz Napierala 8298ad16e55SEdward Tomasz Napierala show_device(fd, e_ptr[j].elm_idx, e_status, e_desc); 8308ad16e55SEdward Tomasz Napierala prev_type = e_ptr[j].elm_type; 8318ad16e55SEdward Tomasz Napierala break; 8328ad16e55SEdward Tomasz Napierala case ELMTYP_THERM: 8338ad16e55SEdward Tomasz Napierala if (e_ptr[j].elm_type != prev_type) 8343d10bf72SEdward Tomasz Napierala xo_emit("\nTemperatures: "); 8358ad16e55SEdward Tomasz Napierala else 8368ad16e55SEdward Tomasz Napierala xo_emit(", "); 8378ad16e55SEdward Tomasz Napierala prev_type = e_ptr[j].elm_type; 8388ad16e55SEdward Tomasz Napierala show_therm(e_status, e_desc); 8398ad16e55SEdward Tomasz Napierala break; 8408ad16e55SEdward Tomasz Napierala case ELMTYP_VOM: 8418ad16e55SEdward Tomasz Napierala if (e_ptr[j].elm_type != prev_type) 8423d10bf72SEdward Tomasz Napierala xo_emit("\nVoltages: "); 8438ad16e55SEdward Tomasz Napierala else 8448ad16e55SEdward Tomasz Napierala xo_emit(", "); 8458ad16e55SEdward Tomasz Napierala prev_type = e_ptr[j].elm_type; 8468ad16e55SEdward Tomasz Napierala show_vom(e_status, e_desc); 8478ad16e55SEdward Tomasz Napierala break; 8488ad16e55SEdward Tomasz Napierala default: 8498ad16e55SEdward Tomasz Napierala /* 8508ad16e55SEdward Tomasz Napierala * Ignore stuff not interesting to the user. 8518ad16e55SEdward Tomasz Napierala */ 8528ad16e55SEdward Tomasz Napierala break; 8538ad16e55SEdward Tomasz Napierala } 8548ad16e55SEdward Tomasz Napierala } 8558ad16e55SEdward Tomasz Napierala if (prev_type != (elm_type_t)-1 && 8568ad16e55SEdward Tomasz Napierala prev_type != ELMTYP_DEVICE && prev_type != ELMTYP_ARRAY_DEV) 8578ad16e55SEdward Tomasz Napierala xo_emit("\n"); 8588ad16e55SEdward Tomasz Napierala xo_close_list("elements"); 8598ad16e55SEdward Tomasz Napierala free(e_ptr); 8608ad16e55SEdward Tomasz Napierala close(fd); 8618ad16e55SEdward Tomasz Napierala } 8628ad16e55SEdward Tomasz Napierala globfree(&g); 8638ad16e55SEdward Tomasz Napierala xo_close_list("enclosures"); 8648ad16e55SEdward Tomasz Napierala xo_close_container("sesutil"); 8658ad16e55SEdward Tomasz Napierala xo_finish(); 8668ad16e55SEdward Tomasz Napierala 8678ad16e55SEdward Tomasz Napierala return (EXIT_SUCCESS); 8688ad16e55SEdward Tomasz Napierala } 8698ad16e55SEdward Tomasz Napierala 8708729f5ecSAllan Jude static int 8718729f5ecSAllan Jude encstatus(int argc, char **argv __unused) 872cddcb259SBaptiste Daroussin { 8738729f5ecSAllan Jude glob_t g; 8748729f5ecSAllan Jude int fd, status; 8758729f5ecSAllan Jude size_t i, e; 8768729f5ecSAllan Jude u_char estat; 877cddcb259SBaptiste Daroussin 8788729f5ecSAllan Jude status = 0; 8798729f5ecSAllan Jude if (argc != 1) { 8808729f5ecSAllan Jude usage(stderr, "status"); 8818729f5ecSAllan Jude } 8828729f5ecSAllan Jude 8838729f5ecSAllan Jude /* Get the list of ses devices */ 8848729f5ecSAllan Jude if (glob(uflag, 0, NULL, &g) == GLOB_NOMATCH) { 8858729f5ecSAllan Jude globfree(&g); 886d25c1ff6SBaptiste Daroussin xo_errx(EXIT_FAILURE, "No SES devices found"); 8878729f5ecSAllan Jude } 888d25c1ff6SBaptiste Daroussin 889d25c1ff6SBaptiste Daroussin xo_set_version(SESUTIL_XO_VERSION); 890d25c1ff6SBaptiste Daroussin xo_open_container("sesutil"); 891d25c1ff6SBaptiste Daroussin xo_open_list("enclosures"); 8928729f5ecSAllan Jude for (i = 0; i < g.gl_pathc; i++) { 8938729f5ecSAllan Jude /* ensure we only got numbers after ses */ 8948729f5ecSAllan Jude if (strspn(g.gl_pathv[i] + 8, "0123456789") != 8958729f5ecSAllan Jude strlen(g.gl_pathv[i] + 8)) { 8968729f5ecSAllan Jude continue; 8978729f5ecSAllan Jude } 8988729f5ecSAllan Jude if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) { 8998729f5ecSAllan Jude /* 9008729f5ecSAllan Jude * Don't treat non-access errors as critical if we are 9018729f5ecSAllan Jude * accessing all devices 9028729f5ecSAllan Jude */ 9038729f5ecSAllan Jude if (errno == EACCES && g.gl_pathc > 1) { 904d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "unable to access SES device"); 9058729f5ecSAllan Jude } 906d25c1ff6SBaptiste Daroussin xo_warn("unable to access SES device: %s", g.gl_pathv[i]); 9078729f5ecSAllan Jude continue; 9088729f5ecSAllan Jude } 9098729f5ecSAllan Jude 9108729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETENCSTAT, (caddr_t) &estat) < 0) { 911d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "ENCIOC_GETENCSTAT"); 9128729f5ecSAllan Jude close(fd); 9138729f5ecSAllan Jude } 9148729f5ecSAllan Jude 915d25c1ff6SBaptiste Daroussin xo_open_instance("enclosures"); 916d25c1ff6SBaptiste Daroussin xo_emit("{:enc/%s}: ", g.gl_pathv[i] + 5); 9178729f5ecSAllan Jude e = 0; 9188729f5ecSAllan Jude if (estat == 0) { 9198729f5ecSAllan Jude if (status == 0) { 9208729f5ecSAllan Jude status = 1; 9218729f5ecSAllan Jude } 922d25c1ff6SBaptiste Daroussin xo_emit("{q:status/OK}"); 9238729f5ecSAllan Jude } else { 9248729f5ecSAllan Jude if (estat & SES_ENCSTAT_INFO) { 925d25c1ff6SBaptiste Daroussin xo_emit("{lq:status/INFO}"); 9268729f5ecSAllan Jude e++; 9278729f5ecSAllan Jude } 9288729f5ecSAllan Jude if (estat & SES_ENCSTAT_NONCRITICAL) { 9298729f5ecSAllan Jude if (e) 930d25c1ff6SBaptiste Daroussin xo_emit(","); 931d25c1ff6SBaptiste Daroussin xo_emit("{lq:status/NONCRITICAL}"); 9328729f5ecSAllan Jude e++; 9338729f5ecSAllan Jude } 9348729f5ecSAllan Jude if (estat & SES_ENCSTAT_CRITICAL) { 9358729f5ecSAllan Jude if (e) 936d25c1ff6SBaptiste Daroussin xo_emit(","); 937d25c1ff6SBaptiste Daroussin xo_emit("{lq:status/CRITICAL}"); 9388729f5ecSAllan Jude e++; 9398729f5ecSAllan Jude status = -1; 9408729f5ecSAllan Jude } 9418729f5ecSAllan Jude if (estat & SES_ENCSTAT_UNRECOV) { 9428729f5ecSAllan Jude if (e) 943d25c1ff6SBaptiste Daroussin xo_emit(","); 944d25c1ff6SBaptiste Daroussin xo_emit("{lq:status/UNRECOV}"); 9458729f5ecSAllan Jude e++; 9468729f5ecSAllan Jude status = -1; 9478729f5ecSAllan Jude } 9488729f5ecSAllan Jude } 949d25c1ff6SBaptiste Daroussin xo_close_instance("enclosures"); 950d25c1ff6SBaptiste Daroussin xo_emit("\n"); 9518729f5ecSAllan Jude close(fd); 9528729f5ecSAllan Jude } 9538729f5ecSAllan Jude globfree(&g); 9548729f5ecSAllan Jude 955d25c1ff6SBaptiste Daroussin xo_close_list("enclosures"); 956d25c1ff6SBaptiste Daroussin xo_close_container("sesutil"); 957d25c1ff6SBaptiste Daroussin xo_finish(); 958d25c1ff6SBaptiste Daroussin 9598729f5ecSAllan Jude if (status == 1) { 9608729f5ecSAllan Jude return (EXIT_SUCCESS); 9618729f5ecSAllan Jude } else { 9628729f5ecSAllan Jude return (EXIT_FAILURE); 9638729f5ecSAllan Jude } 964cddcb259SBaptiste Daroussin } 965cddcb259SBaptiste Daroussin 966cddcb259SBaptiste Daroussin int 967cddcb259SBaptiste Daroussin main(int argc, char **argv) 968cddcb259SBaptiste Daroussin { 9698729f5ecSAllan Jude int i, ch; 970cddcb259SBaptiste Daroussin struct command *cmd = NULL; 971cddcb259SBaptiste Daroussin 972d25c1ff6SBaptiste Daroussin argc = xo_parse_args(argc, argv); 973d25c1ff6SBaptiste Daroussin if (argc < 0) 974d25c1ff6SBaptiste Daroussin exit(1); 975d25c1ff6SBaptiste Daroussin 9768729f5ecSAllan Jude uflag = "/dev/ses[0-9]*"; 9778729f5ecSAllan Jude while ((ch = getopt_long(argc, argv, "u:", NULL, NULL)) != -1) { 9788729f5ecSAllan Jude switch (ch) { 9798729f5ecSAllan Jude case 'u': 9808729f5ecSAllan Jude uflag = optarg; 9818729f5ecSAllan Jude break; 9828729f5ecSAllan Jude case '?': 9838729f5ecSAllan Jude default: 9848729f5ecSAllan Jude usage(stderr, NULL); 9858729f5ecSAllan Jude } 9868729f5ecSAllan Jude } 9878729f5ecSAllan Jude argc -= optind; 9888729f5ecSAllan Jude argv += optind; 9898729f5ecSAllan Jude 9908729f5ecSAllan Jude if (argc < 1) { 991cddcb259SBaptiste Daroussin warnx("Missing command"); 9928729f5ecSAllan Jude usage(stderr, NULL); 993cddcb259SBaptiste Daroussin } 994cddcb259SBaptiste Daroussin 995cddcb259SBaptiste Daroussin for (i = 0; i < nbcmds; i++) { 9968729f5ecSAllan Jude if (strcmp(argv[0], cmds[i].name) == 0) { 997cddcb259SBaptiste Daroussin cmd = &cmds[i]; 998cddcb259SBaptiste Daroussin break; 999cddcb259SBaptiste Daroussin } 1000cddcb259SBaptiste Daroussin } 1001cddcb259SBaptiste Daroussin 1002cddcb259SBaptiste Daroussin if (cmd == NULL) { 10038729f5ecSAllan Jude warnx("unknown command %s", argv[0]); 10048729f5ecSAllan Jude usage(stderr, NULL); 1005cddcb259SBaptiste Daroussin } 1006cddcb259SBaptiste Daroussin 1007cddcb259SBaptiste Daroussin return (cmd->exec(argc, argv)); 1008cddcb259SBaptiste Daroussin } 1009