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 } 1412e19fae4SAlexander Motin ses_status_to_ctrl(type, &o.cstat[0]); 142fe74eaabSAlexander Motin switch (type) { 143fe74eaabSAlexander Motin case ELMTYP_DEVICE: 144fe74eaabSAlexander Motin case ELMTYP_ARRAY_DEV: 1452e19fae4SAlexander Motin slot = (struct ses_ctrl_dev_slot *) &o.cstat[0]; 146fe74eaabSAlexander Motin ses_ctrl_common_set_select(&slot->common, 1); 147fe74eaabSAlexander Motin if (setfault) 148fe74eaabSAlexander Motin ses_ctrl_dev_slot_set_rqst_fault(slot, state); 149efab8bfdSAlexander Motin else 150fe74eaabSAlexander Motin ses_ctrl_dev_slot_set_rqst_ident(slot, state); 151fe74eaabSAlexander Motin break; 152fe74eaabSAlexander Motin default: 153fe74eaabSAlexander Motin return; 1548729f5ecSAllan Jude } 155cddcb259SBaptiste Daroussin if (ioctl(fd, ENCIOC_SETELMSTAT, (caddr_t) &o) < 0) { 156cddcb259SBaptiste Daroussin close(fd); 157d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "ENCIOC_SETELMSTAT"); 158cddcb259SBaptiste Daroussin } 159cddcb259SBaptiste Daroussin } 160cddcb259SBaptiste Daroussin 161cddcb259SBaptiste Daroussin static bool 162cddcb259SBaptiste Daroussin disk_match(const char *devnames, const char *disk, size_t len) 163cddcb259SBaptiste Daroussin { 1641bc54324SBaptiste Daroussin const char *dname; 165cddcb259SBaptiste Daroussin 1661bc54324SBaptiste Daroussin dname = devnames; 1671bc54324SBaptiste Daroussin while ((dname = strstr(dname, disk)) != NULL) { 1688729f5ecSAllan Jude if (dname[len] == '\0' || dname[len] == ',') { 169cddcb259SBaptiste Daroussin return (true); 1708729f5ecSAllan Jude } 1711bc54324SBaptiste Daroussin dname++; 172cddcb259SBaptiste Daroussin } 1738729f5ecSAllan Jude 174cddcb259SBaptiste Daroussin return (false); 175cddcb259SBaptiste Daroussin } 176cddcb259SBaptiste Daroussin 177cddcb259SBaptiste Daroussin static int 1786af5d161SAllan Jude sesled(int argc, char **argv, bool setfault) 179cddcb259SBaptiste Daroussin { 180cddcb259SBaptiste Daroussin encioc_elm_devnames_t objdn; 181cddcb259SBaptiste Daroussin encioc_element_t *objp; 182cddcb259SBaptiste Daroussin glob_t g; 1838729f5ecSAllan Jude char *disk, *endptr; 1848729f5ecSAllan Jude size_t len, i, ndisks; 1858729f5ecSAllan Jude int fd; 1868729f5ecSAllan Jude unsigned int nobj, j, sesid; 1878729f5ecSAllan Jude bool all, isses, onoff; 188cddcb259SBaptiste Daroussin 1898729f5ecSAllan Jude isses = false; 1908729f5ecSAllan Jude all = false; 1918729f5ecSAllan Jude onoff = false; 1928729f5ecSAllan Jude 1938729f5ecSAllan Jude if (argc != 3) { 1946af5d161SAllan Jude usage(stderr, (setfault ? "fault" : "locate")); 195cddcb259SBaptiste Daroussin } 196cddcb259SBaptiste Daroussin 1978729f5ecSAllan Jude disk = argv[1]; 198cddcb259SBaptiste Daroussin 1998729f5ecSAllan Jude sesid = strtoul(disk, &endptr, 10); 2008729f5ecSAllan Jude if (*endptr == '\0') { 2018729f5ecSAllan Jude endptr = strrchr(uflag, '*'); 20296e6c444SBaptiste Daroussin if (endptr != NULL && *endptr == '*') { 203d25c1ff6SBaptiste Daroussin xo_warnx("Must specifying a SES device (-u) to use a SES " 2048729f5ecSAllan Jude "id# to identify a disk"); 2056af5d161SAllan Jude usage(stderr, (setfault ? "fault" : "locate")); 2068729f5ecSAllan Jude } 2078729f5ecSAllan Jude isses = true; 2088729f5ecSAllan Jude } 2098729f5ecSAllan Jude 2108729f5ecSAllan Jude if (strcmp(argv[2], "on") == 0) { 2114569e7cfSBaptiste Daroussin onoff = true; 2128729f5ecSAllan Jude } else if (strcmp(argv[2], "off") == 0) { 2134569e7cfSBaptiste Daroussin onoff = false; 214cddcb259SBaptiste Daroussin } else { 2156af5d161SAllan Jude usage(stderr, (setfault ? "fault" : "locate")); 216cddcb259SBaptiste Daroussin } 217cddcb259SBaptiste Daroussin 218cddcb259SBaptiste Daroussin if (strcmp(disk, "all") == 0) { 219cddcb259SBaptiste Daroussin all = true; 220cddcb259SBaptiste Daroussin } 221cddcb259SBaptiste Daroussin len = strlen(disk); 222cddcb259SBaptiste Daroussin 223cddcb259SBaptiste Daroussin /* Get the list of ses devices */ 2248729f5ecSAllan Jude if (glob((uflag != NULL ? uflag : "/dev/ses[0-9]*"), 0, NULL, &g) == 2258729f5ecSAllan Jude GLOB_NOMATCH) { 2268729f5ecSAllan Jude globfree(&g); 227d25c1ff6SBaptiste Daroussin xo_errx(EXIT_FAILURE, "No SES devices found"); 2288729f5ecSAllan Jude } 2298729f5ecSAllan Jude 2308729f5ecSAllan Jude ndisks = 0; 2318729f5ecSAllan Jude for (i = 0; i < g.gl_pathc; i++) { 2328729f5ecSAllan Jude /* ensure we only got numbers after ses */ 2338729f5ecSAllan Jude if (strspn(g.gl_pathv[i] + 8, "0123456789") != 2348729f5ecSAllan Jude strlen(g.gl_pathv[i] + 8)) { 2358729f5ecSAllan Jude continue; 2368729f5ecSAllan Jude } 2378729f5ecSAllan Jude if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) { 2388729f5ecSAllan Jude /* 2398729f5ecSAllan Jude * Don't treat non-access errors as critical if we are 2408729f5ecSAllan Jude * accessing all devices 2418729f5ecSAllan Jude */ 2428729f5ecSAllan Jude if (errno == EACCES && g.gl_pathc > 1) { 243d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "unable to access SES device"); 2448729f5ecSAllan Jude } 245d25c1ff6SBaptiste Daroussin xo_warn("unable to access SES device: %s", g.gl_pathv[i]); 2468729f5ecSAllan Jude continue; 2478729f5ecSAllan Jude } 2488729f5ecSAllan Jude 2498729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj) < 0) { 2508729f5ecSAllan Jude close(fd); 251d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "ENCIOC_GETNELM"); 2528729f5ecSAllan Jude } 2538729f5ecSAllan Jude 2548729f5ecSAllan Jude objp = calloc(nobj, sizeof(encioc_element_t)); 2558729f5ecSAllan Jude if (objp == NULL) { 2568729f5ecSAllan Jude close(fd); 257d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "calloc()"); 2588729f5ecSAllan Jude } 2598729f5ecSAllan Jude 2608729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETELMMAP, (caddr_t) objp) < 0) { 261a221b104SAlan Somers free(objp); 2628729f5ecSAllan Jude close(fd); 263d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "ENCIOC_GETELMMAP"); 2648729f5ecSAllan Jude } 2658729f5ecSAllan Jude 2668729f5ecSAllan Jude if (isses) { 267691a834cSAlan Somers if (sesid >= nobj) { 268a221b104SAlan Somers free(objp); 2698729f5ecSAllan Jude close(fd); 270d25c1ff6SBaptiste Daroussin xo_errx(EXIT_FAILURE, 2718729f5ecSAllan Jude "Requested SES ID does not exist"); 2728729f5ecSAllan Jude } 273fe74eaabSAlexander Motin do_led(fd, sesid, objp[sesid].elm_type, onoff, setfault); 2748729f5ecSAllan Jude ndisks++; 275a221b104SAlan Somers free(objp); 2768729f5ecSAllan Jude close(fd); 2778729f5ecSAllan Jude break; 2788729f5ecSAllan Jude } 2798729f5ecSAllan Jude for (j = 0; j < nobj; j++) { 2809f96f106SAlan Somers const int devnames_size = 128; 2819f96f106SAlan Somers char devnames[devnames_size]; 2829f96f106SAlan Somers 28324ffc649SAllan Jude if (all) { 284fe74eaabSAlexander Motin do_led(fd, objp[j].elm_idx, objp[j].elm_type, 285fe74eaabSAlexander Motin onoff, setfault); 28624ffc649SAllan Jude continue; 28724ffc649SAllan Jude } 2888729f5ecSAllan Jude memset(&objdn, 0, sizeof(objdn)); 2899f96f106SAlan Somers memset(devnames, 0, devnames_size); 2908729f5ecSAllan Jude objdn.elm_idx = objp[j].elm_idx; 2919f96f106SAlan Somers objdn.elm_names_size = devnames_size; 2929f96f106SAlan Somers objdn.elm_devnames = devnames; 2938729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETELMDEVNAMES, 2948729f5ecSAllan Jude (caddr_t) &objdn) <0) { 2958729f5ecSAllan Jude continue; 2968729f5ecSAllan Jude } 2978729f5ecSAllan Jude if (objdn.elm_names_len > 0) { 2988729f5ecSAllan Jude if (disk_match(objdn.elm_devnames, disk, len)) { 299fe74eaabSAlexander Motin do_led(fd, objdn.elm_idx, objp[j].elm_type, 3006af5d161SAllan Jude onoff, setfault); 3018729f5ecSAllan Jude ndisks++; 3028729f5ecSAllan Jude break; 3038729f5ecSAllan Jude } 3048729f5ecSAllan Jude } 3058729f5ecSAllan Jude } 306f734685eSBaptiste Daroussin free(objp); 3078729f5ecSAllan Jude close(fd); 3088729f5ecSAllan Jude } 3098729f5ecSAllan Jude globfree(&g); 3108729f5ecSAllan Jude if (ndisks == 0 && all == false) { 311d25c1ff6SBaptiste Daroussin xo_errx(EXIT_FAILURE, "Count not find the SES id of device '%s'", 3128729f5ecSAllan Jude disk); 3138729f5ecSAllan Jude } 3148729f5ecSAllan Jude 3158729f5ecSAllan Jude return (EXIT_SUCCESS); 3168729f5ecSAllan Jude } 3178729f5ecSAllan Jude 3188729f5ecSAllan Jude static int 3198729f5ecSAllan Jude locate(int argc, char **argv) 3208729f5ecSAllan Jude { 3218729f5ecSAllan Jude 3228729f5ecSAllan Jude return (sesled(argc, argv, false)); 3238729f5ecSAllan Jude } 3248729f5ecSAllan Jude 3258729f5ecSAllan Jude static int 3268729f5ecSAllan Jude fault(int argc, char **argv) 3278729f5ecSAllan Jude { 3288729f5ecSAllan Jude 3298729f5ecSAllan Jude return (sesled(argc, argv, true)); 3308729f5ecSAllan Jude } 3318729f5ecSAllan Jude 33220a957e3SBaptiste Daroussin static void 3338ad16e55SEdward Tomasz Napierala sesutil_print(int *style, const char *fmt, ...) 33420a957e3SBaptiste Daroussin { 33520a957e3SBaptiste Daroussin va_list args; 33620a957e3SBaptiste Daroussin 3378ad16e55SEdward Tomasz Napierala if (*style == PRINT_STYLE_DASHED) { 338d25c1ff6SBaptiste Daroussin xo_open_container("extra_status"); 339d25c1ff6SBaptiste Daroussin xo_emit("\t\tExtra status:\n"); 3408ad16e55SEdward Tomasz Napierala *style = PRINT_STYLE_DASHED_2; 3418ad16e55SEdward Tomasz Napierala } else if (*style == PRINT_STYLE_CSV) { 3428ad16e55SEdward Tomasz Napierala xo_open_container("extra_status"); 3438ad16e55SEdward Tomasz Napierala *style = PRINT_STYLE_CSV_2; 34420a957e3SBaptiste Daroussin } 3458ad16e55SEdward Tomasz Napierala 3468ad16e55SEdward Tomasz Napierala if (*style == PRINT_STYLE_DASHED_2) 3478ad16e55SEdward Tomasz Napierala xo_emit("\t\t- "); 3488ad16e55SEdward Tomasz Napierala else if (*style == PRINT_STYLE_CSV_2) 3498ad16e55SEdward Tomasz Napierala xo_emit(", "); 35020a957e3SBaptiste Daroussin va_start(args, fmt); 351d25c1ff6SBaptiste Daroussin xo_emit_hv(NULL, fmt, args); 35220a957e3SBaptiste Daroussin va_end(args); 3538ad16e55SEdward Tomasz Napierala if (*style == PRINT_STYLE_DASHED_2) 3548ad16e55SEdward Tomasz Napierala xo_emit("\n"); 35520a957e3SBaptiste Daroussin } 35620a957e3SBaptiste Daroussin 35720a957e3SBaptiste Daroussin static void 3588ad16e55SEdward Tomasz Napierala print_extra_status(int eletype, u_char *cstat, int style) 35920a957e3SBaptiste Daroussin { 36020a957e3SBaptiste Daroussin 36120a957e3SBaptiste Daroussin if (cstat[0] & 0x40) { 3628ad16e55SEdward Tomasz Napierala sesutil_print(&style, "{e:predicted_failure/true} Predicted Failure"); 36320a957e3SBaptiste Daroussin } 36420a957e3SBaptiste Daroussin if (cstat[0] & 0x20) { 3658ad16e55SEdward Tomasz Napierala sesutil_print(&style, "{e:disabled/true} Disabled"); 36620a957e3SBaptiste Daroussin } 36720a957e3SBaptiste Daroussin if (cstat[0] & 0x10) { 3688ad16e55SEdward Tomasz Napierala sesutil_print(&style, "{e:swapped/true} Swapped"); 36920a957e3SBaptiste Daroussin } 37020a957e3SBaptiste Daroussin switch (eletype) { 37120a957e3SBaptiste Daroussin case ELMTYP_DEVICE: 37220a957e3SBaptiste Daroussin case ELMTYP_ARRAY_DEV: 37320a957e3SBaptiste Daroussin if (cstat[2] & 0x02) { 3748ad16e55SEdward Tomasz Napierala sesutil_print(&style, "LED={q:led/locate}"); 37520a957e3SBaptiste Daroussin } 37620a957e3SBaptiste Daroussin if (cstat[2] & 0x20) { 3778ad16e55SEdward Tomasz Napierala sesutil_print(&style, "LED={q:led/fault}"); 37820a957e3SBaptiste Daroussin } 37920a957e3SBaptiste Daroussin break; 38020a957e3SBaptiste Daroussin case ELMTYP_FAN: 3818ad16e55SEdward Tomasz Napierala sesutil_print(&style, "Speed: {:speed/%d}{Uw:rpm}", 38220a957e3SBaptiste Daroussin (((0x7 & cstat[1]) << 8) + cstat[2]) * 10); 38320a957e3SBaptiste Daroussin break; 38420a957e3SBaptiste Daroussin case ELMTYP_THERM: 38520a957e3SBaptiste Daroussin if (cstat[2]) { 3868ad16e55SEdward Tomasz Napierala sesutil_print(&style, "Temperature: {:temperature/%d}{Uw:C}", 38720a957e3SBaptiste Daroussin cstat[2] - TEMPERATURE_OFFSET); 38820a957e3SBaptiste Daroussin } else { 3898ad16e55SEdward Tomasz Napierala sesutil_print(&style, "Temperature: -{q:temperature/reserved}"); 39020a957e3SBaptiste Daroussin } 39120a957e3SBaptiste Daroussin break; 39220a957e3SBaptiste Daroussin case ELMTYP_VOM: 3938ad16e55SEdward Tomasz Napierala sesutil_print(&style, "Voltage: {:voltage/%.2f}{Uw:V}", 39420a957e3SBaptiste Daroussin be16dec(cstat + 2) / 100.0); 39520a957e3SBaptiste Daroussin break; 39620a957e3SBaptiste Daroussin } 3978ad16e55SEdward Tomasz Napierala if (style) { 398d25c1ff6SBaptiste Daroussin xo_close_container("extra_status"); 399d25c1ff6SBaptiste Daroussin } 40020a957e3SBaptiste Daroussin } 40120a957e3SBaptiste Daroussin 4028729f5ecSAllan Jude static int 4038729f5ecSAllan Jude objmap(int argc, char **argv __unused) 4048729f5ecSAllan Jude { 40560f46640SBaptiste Daroussin encioc_string_t stri; 4068729f5ecSAllan Jude encioc_elm_devnames_t e_devname; 4078729f5ecSAllan Jude encioc_elm_status_t e_status; 4088729f5ecSAllan Jude encioc_elm_desc_t e_desc; 4098729f5ecSAllan Jude encioc_element_t *e_ptr; 4108729f5ecSAllan Jude glob_t g; 4118729f5ecSAllan Jude int fd; 4128729f5ecSAllan Jude unsigned int j, nobj; 4138729f5ecSAllan Jude size_t i; 41460f46640SBaptiste Daroussin char str[32]; 4158729f5ecSAllan Jude 4168729f5ecSAllan Jude if (argc != 1) { 4178729f5ecSAllan Jude usage(stderr, "map"); 4188729f5ecSAllan Jude } 4198729f5ecSAllan Jude 4208729f5ecSAllan Jude /* Get the list of ses devices */ 4218729f5ecSAllan Jude if (glob(uflag, 0, NULL, &g) == GLOB_NOMATCH) { 422cddcb259SBaptiste Daroussin globfree(&g); 423d25c1ff6SBaptiste Daroussin xo_errx(EXIT_FAILURE, "No SES devices found"); 424cddcb259SBaptiste Daroussin } 425d25c1ff6SBaptiste Daroussin xo_set_version(SESUTIL_XO_VERSION); 426d25c1ff6SBaptiste Daroussin xo_open_container("sesutil"); 427d25c1ff6SBaptiste Daroussin xo_open_list("enclosures"); 428cddcb259SBaptiste Daroussin for (i = 0; i < g.gl_pathc; i++) { 429cddcb259SBaptiste Daroussin /* ensure we only got numbers after ses */ 430cddcb259SBaptiste Daroussin if (strspn(g.gl_pathv[i] + 8, "0123456789") != 4318729f5ecSAllan Jude strlen(g.gl_pathv[i] + 8)) { 432cddcb259SBaptiste Daroussin continue; 4338729f5ecSAllan Jude } 434cddcb259SBaptiste Daroussin if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) { 4358729f5ecSAllan Jude /* 4368729f5ecSAllan Jude * Don't treat non-access errors as critical if we are 4378729f5ecSAllan Jude * accessing all devices 4388729f5ecSAllan Jude */ 4398729f5ecSAllan Jude if (errno == EACCES && g.gl_pathc > 1) { 440d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "unable to access SES device"); 4418729f5ecSAllan Jude } 442d25c1ff6SBaptiste Daroussin xo_warn("unable to access SES device: %s", g.gl_pathv[i]); 4438729f5ecSAllan Jude continue; 444cddcb259SBaptiste Daroussin } 445cddcb259SBaptiste Daroussin 4468729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj) < 0) { 4478729f5ecSAllan Jude close(fd); 448d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "ENCIOC_GETNELM"); 4498729f5ecSAllan Jude } 450cddcb259SBaptiste Daroussin 4518729f5ecSAllan Jude e_ptr = calloc(nobj, sizeof(encioc_element_t)); 4528729f5ecSAllan Jude if (e_ptr == NULL) { 4538729f5ecSAllan Jude close(fd); 454d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "calloc()"); 4558729f5ecSAllan Jude } 456cddcb259SBaptiste Daroussin 4578729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETELMMAP, (caddr_t) e_ptr) < 0) { 4588729f5ecSAllan Jude close(fd); 459d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "ENCIOC_GETELMMAP"); 4608729f5ecSAllan Jude } 461cddcb259SBaptiste Daroussin 462d25c1ff6SBaptiste Daroussin xo_open_instance("enclosures"); 463d25c1ff6SBaptiste Daroussin xo_emit("{t:enc/%s}:\n", g.gl_pathv[i] + 5); 46460f46640SBaptiste Daroussin stri.bufsiz = sizeof(str); 46560f46640SBaptiste Daroussin stri.buf = &str[0]; 46660f46640SBaptiste Daroussin if (ioctl(fd, ENCIOC_GETENCNAME, (caddr_t) &stri) == 0) 467d25c1ff6SBaptiste Daroussin xo_emit("\tEnclosure Name: {t:name/%s}\n", stri.buf); 46860f46640SBaptiste Daroussin stri.bufsiz = sizeof(str); 46960f46640SBaptiste Daroussin stri.buf = &str[0]; 47060f46640SBaptiste Daroussin if (ioctl(fd, ENCIOC_GETENCID, (caddr_t) &stri) == 0) 471d25c1ff6SBaptiste Daroussin xo_emit("\tEnclosure ID: {t:id/%s}\n", stri.buf); 47260f46640SBaptiste Daroussin 473d25c1ff6SBaptiste Daroussin xo_open_list("elements"); 474cddcb259SBaptiste Daroussin for (j = 0; j < nobj; j++) { 4758729f5ecSAllan Jude /* Get the status of the element */ 4768729f5ecSAllan Jude memset(&e_status, 0, sizeof(e_status)); 4778729f5ecSAllan Jude e_status.elm_idx = e_ptr[j].elm_idx; 4788729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETELMSTAT, 4798729f5ecSAllan Jude (caddr_t) &e_status) < 0) { 4808729f5ecSAllan Jude close(fd); 481d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "ENCIOC_GETELMSTAT"); 4828729f5ecSAllan Jude } 4838729f5ecSAllan Jude /* Get the description of the element */ 4848729f5ecSAllan Jude memset(&e_desc, 0, sizeof(e_desc)); 4858729f5ecSAllan Jude e_desc.elm_idx = e_ptr[j].elm_idx; 4868729f5ecSAllan Jude e_desc.elm_desc_len = UINT16_MAX; 4878729f5ecSAllan Jude e_desc.elm_desc_str = calloc(UINT16_MAX, sizeof(char)); 4888729f5ecSAllan Jude if (e_desc.elm_desc_str == NULL) { 4898729f5ecSAllan Jude close(fd); 490d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "calloc()"); 4918729f5ecSAllan Jude } 4928729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETELMDESC, 4938729f5ecSAllan Jude (caddr_t) &e_desc) < 0) { 4948729f5ecSAllan Jude close(fd); 495d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "ENCIOC_GETELMDESC"); 4968729f5ecSAllan Jude } 4978729f5ecSAllan Jude /* Get the device name(s) of the element */ 4988729f5ecSAllan Jude memset(&e_devname, 0, sizeof(e_devname)); 4998729f5ecSAllan Jude e_devname.elm_idx = e_ptr[j].elm_idx; 5008729f5ecSAllan Jude e_devname.elm_names_size = 128; 5018729f5ecSAllan Jude e_devname.elm_devnames = calloc(128, sizeof(char)); 5028729f5ecSAllan Jude if (e_devname.elm_devnames == NULL) { 5038729f5ecSAllan Jude close(fd); 504d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "calloc()"); 5058729f5ecSAllan Jude } 506cddcb259SBaptiste Daroussin if (ioctl(fd, ENCIOC_GETELMDEVNAMES, 5078729f5ecSAllan Jude (caddr_t) &e_devname) <0) { 50818acbeb3SAlan Somers /* Continue even if we can't look up devnames */ 5098729f5ecSAllan Jude e_devname.elm_devnames[0] = '\0'; 510cddcb259SBaptiste Daroussin } 511d25c1ff6SBaptiste Daroussin xo_open_instance("elements"); 512d25c1ff6SBaptiste Daroussin xo_emit("\tElement {:id/%u}, Type: {:type/%s}\n", e_ptr[j].elm_idx, 5138729f5ecSAllan Jude geteltnm(e_ptr[j].elm_type)); 514d25c1ff6SBaptiste Daroussin xo_emit("\t\tStatus: {:status/%s} ({q:status_code/0x%02x 0x%02x 0x%02x 0x%02x})\n", 515d7654478SBaptiste Daroussin scode2ascii(e_status.cstat[0]), e_status.cstat[0], 516d7654478SBaptiste Daroussin e_status.cstat[1], e_status.cstat[2], 517d7654478SBaptiste Daroussin e_status.cstat[3]); 5188729f5ecSAllan Jude if (e_desc.elm_desc_len > 0) { 519d25c1ff6SBaptiste Daroussin xo_emit("\t\tDescription: {:description/%s}\n", 5208729f5ecSAllan Jude e_desc.elm_desc_str); 521cddcb259SBaptiste Daroussin } 5228729f5ecSAllan Jude if (e_devname.elm_names_len > 0) { 523d25c1ff6SBaptiste Daroussin xo_emit("\t\tDevice Names: {:device_names/%s}\n", 5248729f5ecSAllan Jude e_devname.elm_devnames); 525cddcb259SBaptiste Daroussin } 5268ad16e55SEdward Tomasz Napierala print_extra_status(e_ptr[j].elm_type, e_status.cstat, PRINT_STYLE_DASHED); 527d25c1ff6SBaptiste Daroussin xo_close_instance("elements"); 528*09f29b03SAlan Somers free(e_desc.elm_desc_str); 5298729f5ecSAllan Jude free(e_devname.elm_devnames); 530cddcb259SBaptiste Daroussin } 531d25c1ff6SBaptiste Daroussin xo_close_list("elements"); 532f734685eSBaptiste Daroussin free(e_ptr); 533cddcb259SBaptiste Daroussin close(fd); 534cddcb259SBaptiste Daroussin } 535cddcb259SBaptiste Daroussin globfree(&g); 536d25c1ff6SBaptiste Daroussin xo_close_list("enclosures"); 537d25c1ff6SBaptiste Daroussin xo_close_container("sesutil"); 538d25c1ff6SBaptiste Daroussin xo_finish(); 539cddcb259SBaptiste Daroussin 540cddcb259SBaptiste Daroussin return (EXIT_SUCCESS); 541cddcb259SBaptiste Daroussin } 542cddcb259SBaptiste Daroussin 5438ad16e55SEdward Tomasz Napierala /* 5448ad16e55SEdward Tomasz Napierala * Get rid of the 'passN' devices, unless there's nothing else to show. 5458ad16e55SEdward Tomasz Napierala */ 5468ad16e55SEdward Tomasz Napierala static void 5478ad16e55SEdward Tomasz Napierala skip_pass_devices(char *devnames, size_t devnameslen) 5488ad16e55SEdward Tomasz Napierala { 5498ad16e55SEdward Tomasz Napierala char *dev, devs[128], passes[128], *tmp; 5508ad16e55SEdward Tomasz Napierala 5518ad16e55SEdward Tomasz Napierala devs[0] = passes[0] = '\0'; 5528ad16e55SEdward Tomasz Napierala tmp = devnames; 5538ad16e55SEdward Tomasz Napierala 5548ad16e55SEdward Tomasz Napierala while ((dev = strsep(&tmp, ",")) != NULL) { 5558ad16e55SEdward Tomasz Napierala if (strncmp(dev, "pass", 4) == 0) { 5568ad16e55SEdward Tomasz Napierala if (passes[0] != '\0') 5578ad16e55SEdward Tomasz Napierala strlcat(passes, ",", sizeof(passes)); 5588ad16e55SEdward Tomasz Napierala strlcat(passes, dev, sizeof(passes)); 5598ad16e55SEdward Tomasz Napierala } else { 5608ad16e55SEdward Tomasz Napierala if (devs[0] != '\0') 5618ad16e55SEdward Tomasz Napierala strlcat(devs, ",", sizeof(devs)); 5628ad16e55SEdward Tomasz Napierala strlcat(devs, dev, sizeof(devs)); 5638ad16e55SEdward Tomasz Napierala } 5648ad16e55SEdward Tomasz Napierala } 5658ad16e55SEdward Tomasz Napierala strlcpy(devnames, devs, devnameslen); 5668ad16e55SEdward Tomasz Napierala if (devnames[0] == '\0') 5678ad16e55SEdward Tomasz Napierala strlcpy(devnames, passes, devnameslen); 5688ad16e55SEdward Tomasz Napierala } 5698ad16e55SEdward Tomasz Napierala 5708ad16e55SEdward Tomasz Napierala static void 5718ad16e55SEdward Tomasz Napierala fetch_device_details(char *devnames, char **model, char **serial, off_t *size) 5728ad16e55SEdward Tomasz Napierala { 5738ad16e55SEdward Tomasz Napierala char ident[DISK_IDENT_SIZE]; 5748ad16e55SEdward Tomasz Napierala struct diocgattr_arg arg; 575f05cc0f1SAlan Somers char *tmp; 5768ad16e55SEdward Tomasz Napierala off_t mediasize; 577f05cc0f1SAlan Somers int comma; 5788ad16e55SEdward Tomasz Napierala int fd; 5798ad16e55SEdward Tomasz Napierala 580f05cc0f1SAlan Somers comma = (int)strcspn(devnames, ","); 581f05cc0f1SAlan Somers asprintf(&tmp, "/dev/%.*s", comma, devnames); 5828ad16e55SEdward Tomasz Napierala if (tmp == NULL) 583f05cc0f1SAlan Somers err(1, "asprintf"); 5848ad16e55SEdward Tomasz Napierala fd = open(tmp, O_RDONLY); 585f05cc0f1SAlan Somers free(tmp); 5868ad16e55SEdward Tomasz Napierala if (fd < 0) { 5878ad16e55SEdward Tomasz Napierala /* 5888ad16e55SEdward Tomasz Napierala * This can happen with a disk so broken it cannot 5898ad16e55SEdward Tomasz Napierala * be probed by GEOM. 5908ad16e55SEdward Tomasz Napierala */ 5918ad16e55SEdward Tomasz Napierala *model = strdup("?"); 5928ad16e55SEdward Tomasz Napierala *serial = strdup("?"); 5938ad16e55SEdward Tomasz Napierala *size = -1; 594f05cc0f1SAlan Somers close(fd); 5958ad16e55SEdward Tomasz Napierala return; 5968ad16e55SEdward Tomasz Napierala } 5978ad16e55SEdward Tomasz Napierala 5988ad16e55SEdward Tomasz Napierala strlcpy(arg.name, "GEOM::descr", sizeof(arg.name)); 5998ad16e55SEdward Tomasz Napierala arg.len = sizeof(arg.value.str); 6008ad16e55SEdward Tomasz Napierala if (ioctl(fd, DIOCGATTR, &arg) == 0) 6018ad16e55SEdward Tomasz Napierala *model = strdup(arg.value.str); 6028ad16e55SEdward Tomasz Napierala else 6038ad16e55SEdward Tomasz Napierala *model = NULL; 6048ad16e55SEdward Tomasz Napierala 6058ad16e55SEdward Tomasz Napierala if (ioctl(fd, DIOCGIDENT, ident) == 0) 6068ad16e55SEdward Tomasz Napierala *serial = strdup(ident); 6078ad16e55SEdward Tomasz Napierala else 6088ad16e55SEdward Tomasz Napierala *serial = NULL; 6098ad16e55SEdward Tomasz Napierala 6108ad16e55SEdward Tomasz Napierala if (ioctl(fd, DIOCGMEDIASIZE, &mediasize) == 0) 6118ad16e55SEdward Tomasz Napierala *size = mediasize; 6128ad16e55SEdward Tomasz Napierala else 6138ad16e55SEdward Tomasz Napierala *size = -1; 614f05cc0f1SAlan Somers close(fd); 6158ad16e55SEdward Tomasz Napierala } 6168ad16e55SEdward Tomasz Napierala 6178ad16e55SEdward Tomasz Napierala static void 6188ad16e55SEdward Tomasz Napierala show_device(int fd, int elm_idx, encioc_elm_status_t e_status, encioc_elm_desc_t e_desc) 6198ad16e55SEdward Tomasz Napierala { 6208ad16e55SEdward Tomasz Napierala encioc_elm_devnames_t e_devname; 621*09f29b03SAlan Somers char *model = NULL, *serial = NULL; 6228ad16e55SEdward Tomasz Napierala off_t size; 6238ad16e55SEdward Tomasz Napierala 6248ad16e55SEdward Tomasz Napierala /* Get the device name(s) of the element */ 6258ad16e55SEdward Tomasz Napierala memset(&e_devname, 0, sizeof(e_devname)); 6268ad16e55SEdward Tomasz Napierala e_devname.elm_idx = elm_idx; 6278ad16e55SEdward Tomasz Napierala e_devname.elm_names_size = 128; 6288ad16e55SEdward Tomasz Napierala e_devname.elm_devnames = calloc(128, sizeof(char)); 6298ad16e55SEdward Tomasz Napierala if (e_devname.elm_devnames == NULL) { 6308ad16e55SEdward Tomasz Napierala close(fd); 6318ad16e55SEdward Tomasz Napierala xo_err(EXIT_FAILURE, "calloc()"); 6328ad16e55SEdward Tomasz Napierala } 6338ad16e55SEdward Tomasz Napierala 6348ad16e55SEdward Tomasz Napierala if (ioctl(fd, ENCIOC_GETELMDEVNAMES, 6358ad16e55SEdward Tomasz Napierala (caddr_t) &e_devname) < 0) { 6368ad16e55SEdward Tomasz Napierala /* We don't care if this fails */ 6378ad16e55SEdward Tomasz Napierala e_devname.elm_devnames[0] = '\0'; 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}"); 64579f38143SPoul-Henning Kamp xo_emit("{d:description/%-15s} ", e_desc.elm_desc_len > 0 ? e_desc.elm_desc_str : "-"); 64679f38143SPoul-Henning Kamp xo_emit("{e:description/%-15s}", 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 : ""); 653a1571967SEdward 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"); 662*09f29b03SAlan Somers free(serial); 663*09f29b03SAlan Somers free(model); 6648ad16e55SEdward Tomasz Napierala free(e_devname.elm_devnames); 6658ad16e55SEdward Tomasz Napierala } 6668ad16e55SEdward Tomasz Napierala 6678ad16e55SEdward Tomasz Napierala static void 6688ad16e55SEdward Tomasz Napierala show_therm(encioc_elm_status_t e_status, encioc_elm_desc_t e_desc) 6698ad16e55SEdward Tomasz Napierala { 6708ad16e55SEdward Tomasz Napierala 6718ad16e55SEdward Tomasz Napierala if (e_desc.elm_desc_len <= 0) { 6728ad16e55SEdward Tomasz Napierala /* We don't have a label to display; might as well skip it. */ 6738ad16e55SEdward Tomasz Napierala return; 6748ad16e55SEdward Tomasz Napierala } 6758ad16e55SEdward Tomasz Napierala 6768ad16e55SEdward Tomasz Napierala if (e_status.cstat[2] == 0) { 6778ad16e55SEdward Tomasz Napierala /* No temperature to show. */ 6788ad16e55SEdward Tomasz Napierala return; 6798ad16e55SEdward Tomasz Napierala } 6808ad16e55SEdward Tomasz Napierala 6818ad16e55SEdward Tomasz Napierala xo_open_instance("elements"); 6828ad16e55SEdward Tomasz Napierala xo_emit("{e:type/temperature_sensor}"); 6838ad16e55SEdward Tomasz Napierala xo_emit("{:description/%s}: {:temperature/%d}{Uw:C}", 6848ad16e55SEdward Tomasz Napierala e_desc.elm_desc_str, e_status.cstat[2] - TEMPERATURE_OFFSET); 6858ad16e55SEdward Tomasz Napierala xo_close_instance("elements"); 6868ad16e55SEdward Tomasz Napierala } 6878ad16e55SEdward Tomasz Napierala 6888ad16e55SEdward Tomasz Napierala static void 6898ad16e55SEdward Tomasz Napierala show_vom(encioc_elm_status_t e_status, encioc_elm_desc_t e_desc) 6908ad16e55SEdward Tomasz Napierala { 6918ad16e55SEdward Tomasz Napierala 6928ad16e55SEdward Tomasz Napierala if (e_desc.elm_desc_len <= 0) { 6938ad16e55SEdward Tomasz Napierala /* We don't have a label to display; might as well skip it. */ 6948ad16e55SEdward Tomasz Napierala return; 6958ad16e55SEdward Tomasz Napierala } 6968ad16e55SEdward Tomasz Napierala 6978ad16e55SEdward Tomasz Napierala if (e_status.cstat[2] == 0) { 6988ad16e55SEdward Tomasz Napierala /* No voltage to show. */ 6998ad16e55SEdward Tomasz Napierala return; 7008ad16e55SEdward Tomasz Napierala } 7018ad16e55SEdward Tomasz Napierala 7028ad16e55SEdward Tomasz Napierala xo_open_instance("elements"); 7038ad16e55SEdward Tomasz Napierala xo_emit("{e:type/voltage_sensor}"); 7048ad16e55SEdward Tomasz Napierala xo_emit("{:description/%s}: {:voltage/%.2f}{Uw:V}", 7058ad16e55SEdward Tomasz Napierala e_desc.elm_desc_str, be16dec(e_status.cstat + 2) / 100.0); 7068ad16e55SEdward Tomasz Napierala xo_close_instance("elements"); 7078ad16e55SEdward Tomasz Napierala } 7088ad16e55SEdward Tomasz Napierala 7098ad16e55SEdward Tomasz Napierala static int 7108ad16e55SEdward Tomasz Napierala show(int argc, char **argv __unused) 7118ad16e55SEdward Tomasz Napierala { 7128ad16e55SEdward Tomasz Napierala encioc_string_t stri; 7138ad16e55SEdward Tomasz Napierala encioc_elm_status_t e_status; 7148ad16e55SEdward Tomasz Napierala encioc_elm_desc_t e_desc; 7158ad16e55SEdward Tomasz Napierala encioc_element_t *e_ptr; 7168ad16e55SEdward Tomasz Napierala glob_t g; 7178ad16e55SEdward Tomasz Napierala elm_type_t prev_type; 7188ad16e55SEdward Tomasz Napierala int fd; 7198ad16e55SEdward Tomasz Napierala unsigned int j, nobj; 7208ad16e55SEdward Tomasz Napierala size_t i; 7218ad16e55SEdward Tomasz Napierala bool first_ses; 7228ad16e55SEdward Tomasz Napierala char str[32]; 7238ad16e55SEdward Tomasz Napierala 7248ad16e55SEdward Tomasz Napierala if (argc != 1) { 7258ad16e55SEdward Tomasz Napierala usage(stderr, "map"); 7268ad16e55SEdward Tomasz Napierala } 7278ad16e55SEdward Tomasz Napierala 7288ad16e55SEdward Tomasz Napierala first_ses = true; 7298ad16e55SEdward Tomasz Napierala 7308ad16e55SEdward Tomasz Napierala /* Get the list of ses devices */ 7318ad16e55SEdward Tomasz Napierala if (glob(uflag, 0, NULL, &g) == GLOB_NOMATCH) { 7328ad16e55SEdward Tomasz Napierala globfree(&g); 7338ad16e55SEdward Tomasz Napierala xo_errx(EXIT_FAILURE, "No SES devices found"); 7348ad16e55SEdward Tomasz Napierala } 7358ad16e55SEdward Tomasz Napierala xo_set_version(SESUTIL_XO_VERSION); 7368ad16e55SEdward Tomasz Napierala xo_open_container("sesutil"); 7378ad16e55SEdward Tomasz Napierala xo_open_list("enclosures"); 7388ad16e55SEdward Tomasz Napierala for (i = 0; i < g.gl_pathc; i++) { 7398ad16e55SEdward Tomasz Napierala /* ensure we only got numbers after ses */ 7408ad16e55SEdward Tomasz Napierala if (strspn(g.gl_pathv[i] + 8, "0123456789") != 7418ad16e55SEdward Tomasz Napierala strlen(g.gl_pathv[i] + 8)) { 7428ad16e55SEdward Tomasz Napierala continue; 7438ad16e55SEdward Tomasz Napierala } 7448ad16e55SEdward Tomasz Napierala if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) { 7458ad16e55SEdward Tomasz Napierala /* 7468ad16e55SEdward Tomasz Napierala * Don't treat non-access errors as critical if we are 7478ad16e55SEdward Tomasz Napierala * accessing all devices 7488ad16e55SEdward Tomasz Napierala */ 7498ad16e55SEdward Tomasz Napierala if (errno == EACCES && g.gl_pathc > 1) { 7508ad16e55SEdward Tomasz Napierala xo_err(EXIT_FAILURE, "unable to access SES device"); 7518ad16e55SEdward Tomasz Napierala } 7528ad16e55SEdward Tomasz Napierala xo_warn("unable to access SES device: %s", g.gl_pathv[i]); 7538ad16e55SEdward Tomasz Napierala continue; 7548ad16e55SEdward Tomasz Napierala } 7558ad16e55SEdward Tomasz Napierala 7568ad16e55SEdward Tomasz Napierala if (ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj) < 0) { 7578ad16e55SEdward Tomasz Napierala close(fd); 7588ad16e55SEdward Tomasz Napierala xo_err(EXIT_FAILURE, "ENCIOC_GETNELM"); 7598ad16e55SEdward Tomasz Napierala } 7608ad16e55SEdward Tomasz Napierala 7618ad16e55SEdward Tomasz Napierala e_ptr = calloc(nobj, sizeof(encioc_element_t)); 7628ad16e55SEdward Tomasz Napierala if (e_ptr == NULL) { 7638ad16e55SEdward Tomasz Napierala close(fd); 7648ad16e55SEdward Tomasz Napierala xo_err(EXIT_FAILURE, "calloc()"); 7658ad16e55SEdward Tomasz Napierala } 7668ad16e55SEdward Tomasz Napierala 7678ad16e55SEdward Tomasz Napierala if (ioctl(fd, ENCIOC_GETELMMAP, (caddr_t) e_ptr) < 0) { 7688ad16e55SEdward Tomasz Napierala close(fd); 7698ad16e55SEdward Tomasz Napierala xo_err(EXIT_FAILURE, "ENCIOC_GETELMMAP"); 7708ad16e55SEdward Tomasz Napierala } 7718ad16e55SEdward Tomasz Napierala 7728ad16e55SEdward Tomasz Napierala xo_open_instance("enclosures"); 7738ad16e55SEdward Tomasz Napierala 7748ad16e55SEdward Tomasz Napierala if (first_ses) 7758ad16e55SEdward Tomasz Napierala first_ses = false; 7768ad16e55SEdward Tomasz Napierala else 7778ad16e55SEdward Tomasz Napierala xo_emit("\n"); 7788ad16e55SEdward Tomasz Napierala 7798ad16e55SEdward Tomasz Napierala xo_emit("{t:enc/%s}: ", g.gl_pathv[i] + 5); 7808ad16e55SEdward Tomasz Napierala stri.bufsiz = sizeof(str); 7818ad16e55SEdward Tomasz Napierala stri.buf = &str[0]; 7828ad16e55SEdward Tomasz Napierala if (ioctl(fd, ENCIOC_GETENCNAME, (caddr_t) &stri) == 0) 7838ad16e55SEdward Tomasz Napierala xo_emit("<{t:name/%s}>; ", stri.buf); 7848ad16e55SEdward Tomasz Napierala stri.bufsiz = sizeof(str); 7858ad16e55SEdward Tomasz Napierala stri.buf = &str[0]; 7868ad16e55SEdward Tomasz Napierala if (ioctl(fd, ENCIOC_GETENCID, (caddr_t) &stri) == 0) 7878ad16e55SEdward Tomasz Napierala xo_emit("ID: {t:id/%s}", stri.buf); 7888ad16e55SEdward Tomasz Napierala xo_emit("\n"); 7898ad16e55SEdward Tomasz Napierala 7908ad16e55SEdward Tomasz Napierala xo_open_list("elements"); 7918ad16e55SEdward Tomasz Napierala prev_type = -1; 7928ad16e55SEdward Tomasz Napierala for (j = 0; j < nobj; j++) { 7938ad16e55SEdward Tomasz Napierala /* Get the status of the element */ 7948ad16e55SEdward Tomasz Napierala memset(&e_status, 0, sizeof(e_status)); 7958ad16e55SEdward Tomasz Napierala e_status.elm_idx = e_ptr[j].elm_idx; 7968ad16e55SEdward Tomasz Napierala if (ioctl(fd, ENCIOC_GETELMSTAT, 7978ad16e55SEdward Tomasz Napierala (caddr_t) &e_status) < 0) { 7988ad16e55SEdward Tomasz Napierala close(fd); 7998ad16e55SEdward Tomasz Napierala xo_err(EXIT_FAILURE, "ENCIOC_GETELMSTAT"); 8008ad16e55SEdward Tomasz Napierala } 8018ad16e55SEdward Tomasz Napierala 8028ad16e55SEdward Tomasz Napierala /* 8038ad16e55SEdward Tomasz Napierala * Skip "Unsupported" elements; those usually precede 8048ad16e55SEdward Tomasz Napierala * the actual device entries and are not particularly 8058ad16e55SEdward Tomasz Napierala * interesting. 8068ad16e55SEdward Tomasz Napierala */ 8078ad16e55SEdward Tomasz Napierala if (e_status.cstat[0] == SES_OBJSTAT_UNSUPPORTED) 8088ad16e55SEdward Tomasz Napierala continue; 8098ad16e55SEdward Tomasz Napierala 8108ad16e55SEdward Tomasz Napierala /* Get the description of the element */ 8118ad16e55SEdward Tomasz Napierala memset(&e_desc, 0, sizeof(e_desc)); 8128ad16e55SEdward Tomasz Napierala e_desc.elm_idx = e_ptr[j].elm_idx; 8138ad16e55SEdward Tomasz Napierala e_desc.elm_desc_len = UINT16_MAX; 8148ad16e55SEdward Tomasz Napierala e_desc.elm_desc_str = calloc(UINT16_MAX, sizeof(char)); 8158ad16e55SEdward Tomasz Napierala if (e_desc.elm_desc_str == NULL) { 8168ad16e55SEdward Tomasz Napierala close(fd); 8178ad16e55SEdward Tomasz Napierala xo_err(EXIT_FAILURE, "calloc()"); 8188ad16e55SEdward Tomasz Napierala } 8198ad16e55SEdward Tomasz Napierala if (ioctl(fd, ENCIOC_GETELMDESC, 8208ad16e55SEdward Tomasz Napierala (caddr_t) &e_desc) < 0) { 8218ad16e55SEdward Tomasz Napierala close(fd); 8228ad16e55SEdward Tomasz Napierala xo_err(EXIT_FAILURE, "ENCIOC_GETELMDESC"); 8238ad16e55SEdward Tomasz Napierala } 8248ad16e55SEdward Tomasz Napierala 8258ad16e55SEdward Tomasz Napierala switch (e_ptr[j].elm_type) { 8268ad16e55SEdward Tomasz Napierala case ELMTYP_DEVICE: 8278ad16e55SEdward Tomasz Napierala case ELMTYP_ARRAY_DEV: 8288ad16e55SEdward Tomasz Napierala if (e_ptr[j].elm_type != prev_type) 8298ad16e55SEdward Tomasz Napierala xo_emit("Desc Dev Model Ident Size/Status\n"); 8308ad16e55SEdward Tomasz Napierala 8318ad16e55SEdward Tomasz Napierala show_device(fd, e_ptr[j].elm_idx, e_status, e_desc); 8328ad16e55SEdward Tomasz Napierala prev_type = e_ptr[j].elm_type; 8338ad16e55SEdward Tomasz Napierala break; 8348ad16e55SEdward Tomasz Napierala case ELMTYP_THERM: 8358ad16e55SEdward Tomasz Napierala if (e_ptr[j].elm_type != prev_type) 8363d10bf72SEdward Tomasz Napierala xo_emit("\nTemperatures: "); 8378ad16e55SEdward Tomasz Napierala else 8388ad16e55SEdward Tomasz Napierala xo_emit(", "); 8398ad16e55SEdward Tomasz Napierala prev_type = e_ptr[j].elm_type; 8408ad16e55SEdward Tomasz Napierala show_therm(e_status, e_desc); 8418ad16e55SEdward Tomasz Napierala break; 8428ad16e55SEdward Tomasz Napierala case ELMTYP_VOM: 8438ad16e55SEdward Tomasz Napierala if (e_ptr[j].elm_type != prev_type) 8443d10bf72SEdward Tomasz Napierala xo_emit("\nVoltages: "); 8458ad16e55SEdward Tomasz Napierala else 8468ad16e55SEdward Tomasz Napierala xo_emit(", "); 8478ad16e55SEdward Tomasz Napierala prev_type = e_ptr[j].elm_type; 8488ad16e55SEdward Tomasz Napierala show_vom(e_status, e_desc); 8498ad16e55SEdward Tomasz Napierala break; 8508ad16e55SEdward Tomasz Napierala default: 8518ad16e55SEdward Tomasz Napierala /* 8528ad16e55SEdward Tomasz Napierala * Ignore stuff not interesting to the user. 8538ad16e55SEdward Tomasz Napierala */ 8548ad16e55SEdward Tomasz Napierala break; 8558ad16e55SEdward Tomasz Napierala } 856*09f29b03SAlan Somers free(e_desc.elm_desc_str); 8578ad16e55SEdward Tomasz Napierala } 8588ad16e55SEdward Tomasz Napierala if (prev_type != (elm_type_t)-1 && 8598ad16e55SEdward Tomasz Napierala prev_type != ELMTYP_DEVICE && prev_type != ELMTYP_ARRAY_DEV) 8608ad16e55SEdward Tomasz Napierala xo_emit("\n"); 8618ad16e55SEdward Tomasz Napierala xo_close_list("elements"); 8628ad16e55SEdward Tomasz Napierala free(e_ptr); 8638ad16e55SEdward Tomasz Napierala close(fd); 8648ad16e55SEdward Tomasz Napierala } 8658ad16e55SEdward Tomasz Napierala globfree(&g); 8668ad16e55SEdward Tomasz Napierala xo_close_list("enclosures"); 8678ad16e55SEdward Tomasz Napierala xo_close_container("sesutil"); 8688ad16e55SEdward Tomasz Napierala xo_finish(); 8698ad16e55SEdward Tomasz Napierala 8708ad16e55SEdward Tomasz Napierala return (EXIT_SUCCESS); 8718ad16e55SEdward Tomasz Napierala } 8728ad16e55SEdward Tomasz Napierala 8738729f5ecSAllan Jude static int 8748729f5ecSAllan Jude encstatus(int argc, char **argv __unused) 875cddcb259SBaptiste Daroussin { 8768729f5ecSAllan Jude glob_t g; 8778729f5ecSAllan Jude int fd, status; 8788729f5ecSAllan Jude size_t i, e; 8798729f5ecSAllan Jude u_char estat; 880cddcb259SBaptiste Daroussin 8818729f5ecSAllan Jude status = 0; 8828729f5ecSAllan Jude if (argc != 1) { 8838729f5ecSAllan Jude usage(stderr, "status"); 8848729f5ecSAllan Jude } 8858729f5ecSAllan Jude 8868729f5ecSAllan Jude /* Get the list of ses devices */ 8878729f5ecSAllan Jude if (glob(uflag, 0, NULL, &g) == GLOB_NOMATCH) { 8888729f5ecSAllan Jude globfree(&g); 889d25c1ff6SBaptiste Daroussin xo_errx(EXIT_FAILURE, "No SES devices found"); 8908729f5ecSAllan Jude } 891d25c1ff6SBaptiste Daroussin 892d25c1ff6SBaptiste Daroussin xo_set_version(SESUTIL_XO_VERSION); 893d25c1ff6SBaptiste Daroussin xo_open_container("sesutil"); 894d25c1ff6SBaptiste Daroussin xo_open_list("enclosures"); 8958729f5ecSAllan Jude for (i = 0; i < g.gl_pathc; i++) { 8968729f5ecSAllan Jude /* ensure we only got numbers after ses */ 8978729f5ecSAllan Jude if (strspn(g.gl_pathv[i] + 8, "0123456789") != 8988729f5ecSAllan Jude strlen(g.gl_pathv[i] + 8)) { 8998729f5ecSAllan Jude continue; 9008729f5ecSAllan Jude } 9018729f5ecSAllan Jude if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) { 9028729f5ecSAllan Jude /* 9038729f5ecSAllan Jude * Don't treat non-access errors as critical if we are 9048729f5ecSAllan Jude * accessing all devices 9058729f5ecSAllan Jude */ 9068729f5ecSAllan Jude if (errno == EACCES && g.gl_pathc > 1) { 907d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "unable to access SES device"); 9088729f5ecSAllan Jude } 909d25c1ff6SBaptiste Daroussin xo_warn("unable to access SES device: %s", g.gl_pathv[i]); 9108729f5ecSAllan Jude continue; 9118729f5ecSAllan Jude } 9128729f5ecSAllan Jude 9138729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETENCSTAT, (caddr_t) &estat) < 0) { 914d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "ENCIOC_GETENCSTAT"); 9158729f5ecSAllan Jude close(fd); 9168729f5ecSAllan Jude } 9178729f5ecSAllan Jude 918d25c1ff6SBaptiste Daroussin xo_open_instance("enclosures"); 919d25c1ff6SBaptiste Daroussin xo_emit("{:enc/%s}: ", g.gl_pathv[i] + 5); 9208729f5ecSAllan Jude e = 0; 9218729f5ecSAllan Jude if (estat == 0) { 9228729f5ecSAllan Jude if (status == 0) { 9238729f5ecSAllan Jude status = 1; 9248729f5ecSAllan Jude } 925d25c1ff6SBaptiste Daroussin xo_emit("{q:status/OK}"); 9268729f5ecSAllan Jude } else { 9278729f5ecSAllan Jude if (estat & SES_ENCSTAT_INFO) { 928d25c1ff6SBaptiste Daroussin xo_emit("{lq:status/INFO}"); 9298729f5ecSAllan Jude e++; 9308729f5ecSAllan Jude } 9318729f5ecSAllan Jude if (estat & SES_ENCSTAT_NONCRITICAL) { 9328729f5ecSAllan Jude if (e) 933d25c1ff6SBaptiste Daroussin xo_emit(","); 934d25c1ff6SBaptiste Daroussin xo_emit("{lq:status/NONCRITICAL}"); 9358729f5ecSAllan Jude e++; 9368729f5ecSAllan Jude } 9378729f5ecSAllan Jude if (estat & SES_ENCSTAT_CRITICAL) { 9388729f5ecSAllan Jude if (e) 939d25c1ff6SBaptiste Daroussin xo_emit(","); 940d25c1ff6SBaptiste Daroussin xo_emit("{lq:status/CRITICAL}"); 9418729f5ecSAllan Jude e++; 9428729f5ecSAllan Jude status = -1; 9438729f5ecSAllan Jude } 9448729f5ecSAllan Jude if (estat & SES_ENCSTAT_UNRECOV) { 9458729f5ecSAllan Jude if (e) 946d25c1ff6SBaptiste Daroussin xo_emit(","); 947d25c1ff6SBaptiste Daroussin xo_emit("{lq:status/UNRECOV}"); 9488729f5ecSAllan Jude e++; 9498729f5ecSAllan Jude status = -1; 9508729f5ecSAllan Jude } 9518729f5ecSAllan Jude } 952d25c1ff6SBaptiste Daroussin xo_close_instance("enclosures"); 953d25c1ff6SBaptiste Daroussin xo_emit("\n"); 9548729f5ecSAllan Jude close(fd); 9558729f5ecSAllan Jude } 9568729f5ecSAllan Jude globfree(&g); 9578729f5ecSAllan Jude 958d25c1ff6SBaptiste Daroussin xo_close_list("enclosures"); 959d25c1ff6SBaptiste Daroussin xo_close_container("sesutil"); 960d25c1ff6SBaptiste Daroussin xo_finish(); 961d25c1ff6SBaptiste Daroussin 9628729f5ecSAllan Jude if (status == 1) { 9638729f5ecSAllan Jude return (EXIT_SUCCESS); 9648729f5ecSAllan Jude } else { 9658729f5ecSAllan Jude return (EXIT_FAILURE); 9668729f5ecSAllan Jude } 967cddcb259SBaptiste Daroussin } 968cddcb259SBaptiste Daroussin 969cddcb259SBaptiste Daroussin int 970cddcb259SBaptiste Daroussin main(int argc, char **argv) 971cddcb259SBaptiste Daroussin { 9728729f5ecSAllan Jude int i, ch; 973cddcb259SBaptiste Daroussin struct command *cmd = NULL; 974cddcb259SBaptiste Daroussin 975d25c1ff6SBaptiste Daroussin argc = xo_parse_args(argc, argv); 976d25c1ff6SBaptiste Daroussin if (argc < 0) 977d25c1ff6SBaptiste Daroussin exit(1); 978d25c1ff6SBaptiste Daroussin 9798729f5ecSAllan Jude uflag = "/dev/ses[0-9]*"; 9808729f5ecSAllan Jude while ((ch = getopt_long(argc, argv, "u:", NULL, NULL)) != -1) { 9818729f5ecSAllan Jude switch (ch) { 9828729f5ecSAllan Jude case 'u': 9838729f5ecSAllan Jude uflag = optarg; 9848729f5ecSAllan Jude break; 9858729f5ecSAllan Jude case '?': 9868729f5ecSAllan Jude default: 9878729f5ecSAllan Jude usage(stderr, NULL); 9888729f5ecSAllan Jude } 9898729f5ecSAllan Jude } 9908729f5ecSAllan Jude argc -= optind; 9918729f5ecSAllan Jude argv += optind; 9928729f5ecSAllan Jude 9938729f5ecSAllan Jude if (argc < 1) { 994cddcb259SBaptiste Daroussin warnx("Missing command"); 9958729f5ecSAllan Jude usage(stderr, NULL); 996cddcb259SBaptiste Daroussin } 997cddcb259SBaptiste Daroussin 998cddcb259SBaptiste Daroussin for (i = 0; i < nbcmds; i++) { 9998729f5ecSAllan Jude if (strcmp(argv[0], cmds[i].name) == 0) { 1000cddcb259SBaptiste Daroussin cmd = &cmds[i]; 1001cddcb259SBaptiste Daroussin break; 1002cddcb259SBaptiste Daroussin } 1003cddcb259SBaptiste Daroussin } 1004cddcb259SBaptiste Daroussin 1005cddcb259SBaptiste Daroussin if (cmd == NULL) { 10068729f5ecSAllan Jude warnx("unknown command %s", argv[0]); 10078729f5ecSAllan Jude usage(stderr, NULL); 1008cddcb259SBaptiste Daroussin } 1009cddcb259SBaptiste Daroussin 1010cddcb259SBaptiste Daroussin return (cmd->exec(argc, argv)); 1011cddcb259SBaptiste Daroussin } 1012