1cddcb259SBaptiste Daroussin /*- 2cddcb259SBaptiste Daroussin * Copyright (c) 2015 Baptiste Daroussin <bapt@FreeBSD.org> 38729f5ecSAllan Jude * Copyright (c) 2015 Allan Jude <allanjude@FreeBSD.org> 48729f5ecSAllan Jude * Copyright (c) 2000 by Matthew Jacob 5cddcb259SBaptiste Daroussin * All rights reserved. 6cddcb259SBaptiste Daroussin * 7cddcb259SBaptiste Daroussin * Redistribution and use in source and binary forms, with or without 8cddcb259SBaptiste Daroussin * modification, are permitted provided that the following conditions 9cddcb259SBaptiste Daroussin * are met: 10cddcb259SBaptiste Daroussin * 1. Redistributions of source code must retain the above copyright 11cddcb259SBaptiste Daroussin * notice, this list of conditions and the following disclaimer 12cddcb259SBaptiste Daroussin * in this position and unchanged. 13cddcb259SBaptiste Daroussin * 2. Redistributions in binary form must reproduce the above copyright 14cddcb259SBaptiste Daroussin * notice, this list of conditions and the following disclaimer in the 15cddcb259SBaptiste Daroussin * documentation and/or other materials provided with the distribution. 16cddcb259SBaptiste Daroussin * 17cddcb259SBaptiste Daroussin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 18cddcb259SBaptiste Daroussin * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19cddcb259SBaptiste Daroussin * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20cddcb259SBaptiste Daroussin * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 21cddcb259SBaptiste Daroussin * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22cddcb259SBaptiste Daroussin * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23cddcb259SBaptiste Daroussin * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24cddcb259SBaptiste Daroussin * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25cddcb259SBaptiste Daroussin * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26cddcb259SBaptiste Daroussin * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27cddcb259SBaptiste Daroussin */ 28cddcb259SBaptiste Daroussin 29cddcb259SBaptiste Daroussin #include <sys/cdefs.h> 30cddcb259SBaptiste Daroussin __FBSDID("$FreeBSD$"); 31cddcb259SBaptiste Daroussin 3220a957e3SBaptiste Daroussin #include <sys/endian.h> 33cddcb259SBaptiste Daroussin #include <sys/param.h> 34cddcb259SBaptiste Daroussin #include <sys/ioctl.h> 35d7654478SBaptiste Daroussin #include <sys/types.h> 36cddcb259SBaptiste Daroussin 37cddcb259SBaptiste Daroussin #include <err.h> 38cddcb259SBaptiste Daroussin #include <errno.h> 39cddcb259SBaptiste Daroussin #include <fcntl.h> 408729f5ecSAllan Jude #include <getopt.h> 41cddcb259SBaptiste Daroussin #include <glob.h> 42cddcb259SBaptiste Daroussin #include <stdbool.h> 43cddcb259SBaptiste Daroussin #include <stddef.h> 44cddcb259SBaptiste Daroussin #include <stdint.h> 45cddcb259SBaptiste Daroussin #include <stdio.h> 46cddcb259SBaptiste Daroussin #include <stdlib.h> 47cddcb259SBaptiste Daroussin #include <string.h> 48cddcb259SBaptiste Daroussin #include <unistd.h> 49d25c1ff6SBaptiste Daroussin #include <libxo/xo.h> 50cddcb259SBaptiste Daroussin 51cddcb259SBaptiste Daroussin #include <cam/scsi/scsi_enc.h> 52cddcb259SBaptiste Daroussin 538729f5ecSAllan Jude #include "eltsub.h" 548729f5ecSAllan Jude 55d25c1ff6SBaptiste Daroussin #define SESUTIL_XO_VERSION "1" 56d25c1ff6SBaptiste Daroussin 578729f5ecSAllan Jude static int encstatus(int argc, char **argv); 588729f5ecSAllan Jude static int fault(int argc, char **argv); 59cddcb259SBaptiste Daroussin static int locate(int argc, char **argv); 608729f5ecSAllan Jude static int objmap(int argc, char **argv); 618729f5ecSAllan Jude static int sesled(int argc, char **argv, bool fault); 6220a957e3SBaptiste Daroussin static void sesutil_print(bool *title, const char *fmt, ...) __printflike(2,3); 63cddcb259SBaptiste Daroussin 64cddcb259SBaptiste Daroussin static struct command { 65cddcb259SBaptiste Daroussin const char *name; 668729f5ecSAllan Jude const char *param; 67cddcb259SBaptiste Daroussin const char *desc; 68cddcb259SBaptiste Daroussin int (*exec)(int argc, char **argv); 69cddcb259SBaptiste Daroussin } cmds[] = { 708729f5ecSAllan Jude { "fault", 718729f5ecSAllan Jude "(<disk>|<sesid>|all) (on|off)", 728729f5ecSAllan Jude "Change the state of the fault LED associated with a disk", 738729f5ecSAllan Jude fault }, 748729f5ecSAllan Jude { "locate", 758729f5ecSAllan Jude "(<disk>|<sesid>|all) (on|off)", 768729f5ecSAllan Jude "Change the state of the locate LED associated with a disk", 778729f5ecSAllan Jude locate }, 788729f5ecSAllan Jude { "map", "", 798729f5ecSAllan Jude "Print a map of the devices managed by the enclosure", objmap } , 808729f5ecSAllan Jude { "status", "", "Print the status of the enclosure", 818729f5ecSAllan Jude encstatus }, 82cddcb259SBaptiste Daroussin }; 83cddcb259SBaptiste Daroussin 84cddcb259SBaptiste Daroussin static const int nbcmds = nitems(cmds); 858729f5ecSAllan Jude static const char *uflag; 86cddcb259SBaptiste Daroussin 87cddcb259SBaptiste Daroussin static void 888729f5ecSAllan Jude usage(FILE *out, const char *subcmd) 898729f5ecSAllan Jude { 908729f5ecSAllan Jude int i; 918729f5ecSAllan Jude 928729f5ecSAllan Jude if (subcmd == NULL) { 938729f5ecSAllan Jude fprintf(out, "Usage: %s [-u /dev/ses<N>] <command> [options]\n", 948729f5ecSAllan Jude getprogname()); 958729f5ecSAllan Jude fprintf(out, "Commands supported:\n"); 968729f5ecSAllan Jude } 978729f5ecSAllan Jude for (i = 0; i < nbcmds; i++) { 988729f5ecSAllan Jude if (subcmd != NULL) { 998729f5ecSAllan Jude if (strcmp(subcmd, cmds[i].name) == 0) { 1008729f5ecSAllan Jude fprintf(out, "Usage: %s %s [-u /dev/ses<N>] " 1018729f5ecSAllan Jude "%s\n\t%s\n", getprogname(), subcmd, 1028729f5ecSAllan Jude cmds[i].param, cmds[i].desc); 1038729f5ecSAllan Jude break; 1048729f5ecSAllan Jude } 1058729f5ecSAllan Jude continue; 1068729f5ecSAllan Jude } 1078729f5ecSAllan Jude fprintf(out, " %-12s%s\n\t\t%s\n\n", cmds[i].name, 1088729f5ecSAllan Jude cmds[i].param, cmds[i].desc); 1098729f5ecSAllan Jude } 1108729f5ecSAllan Jude 1118729f5ecSAllan Jude exit(EXIT_FAILURE); 1128729f5ecSAllan Jude } 1138729f5ecSAllan Jude 1148729f5ecSAllan Jude static void 115fe74eaabSAlexander Motin do_led(int fd, unsigned int idx, elm_type_t type, bool onoff, bool setfault) 116cddcb259SBaptiste Daroussin { 117fe74eaabSAlexander Motin int state = onoff ? 1 : 0; 118cddcb259SBaptiste Daroussin encioc_elm_status_t o; 119fe74eaabSAlexander Motin struct ses_ctrl_dev_slot *slot; 120cddcb259SBaptiste Daroussin 121cddcb259SBaptiste Daroussin o.elm_idx = idx; 122cddcb259SBaptiste Daroussin if (ioctl(fd, ENCIOC_GETELMSTAT, (caddr_t) &o) < 0) { 123cddcb259SBaptiste Daroussin close(fd); 124d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "ENCIOC_GETELMSTAT"); 125cddcb259SBaptiste Daroussin } 126fe74eaabSAlexander Motin slot = (struct ses_ctrl_dev_slot *) &o.cstat[0]; 127fe74eaabSAlexander Motin switch (type) { 128fe74eaabSAlexander Motin case ELMTYP_DEVICE: 129fe74eaabSAlexander Motin case ELMTYP_ARRAY_DEV: 130fe74eaabSAlexander Motin ses_ctrl_common_set_select(&slot->common, 1); 131fe74eaabSAlexander Motin if (setfault) 132fe74eaabSAlexander Motin ses_ctrl_dev_slot_set_rqst_fault(slot, state); 133efab8bfdSAlexander Motin else 134fe74eaabSAlexander Motin ses_ctrl_dev_slot_set_rqst_ident(slot, state); 135fe74eaabSAlexander Motin break; 136fe74eaabSAlexander Motin default: 137fe74eaabSAlexander Motin return; 1388729f5ecSAllan Jude } 139cddcb259SBaptiste Daroussin if (ioctl(fd, ENCIOC_SETELMSTAT, (caddr_t) &o) < 0) { 140cddcb259SBaptiste Daroussin close(fd); 141d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "ENCIOC_SETELMSTAT"); 142cddcb259SBaptiste Daroussin } 143cddcb259SBaptiste Daroussin } 144cddcb259SBaptiste Daroussin 145cddcb259SBaptiste Daroussin static bool 146cddcb259SBaptiste Daroussin disk_match(const char *devnames, const char *disk, size_t len) 147cddcb259SBaptiste Daroussin { 1481bc54324SBaptiste Daroussin const char *dname; 149cddcb259SBaptiste Daroussin 1501bc54324SBaptiste Daroussin dname = devnames; 1511bc54324SBaptiste Daroussin while ((dname = strstr(dname, disk)) != NULL) { 1528729f5ecSAllan Jude if (dname[len] == '\0' || dname[len] == ',') { 153cddcb259SBaptiste Daroussin return (true); 1548729f5ecSAllan Jude } 1551bc54324SBaptiste Daroussin dname++; 156cddcb259SBaptiste Daroussin } 1578729f5ecSAllan Jude 158cddcb259SBaptiste Daroussin return (false); 159cddcb259SBaptiste Daroussin } 160cddcb259SBaptiste Daroussin 161cddcb259SBaptiste Daroussin static int 1626af5d161SAllan Jude sesled(int argc, char **argv, bool setfault) 163cddcb259SBaptiste Daroussin { 164cddcb259SBaptiste Daroussin encioc_elm_devnames_t objdn; 165cddcb259SBaptiste Daroussin encioc_element_t *objp; 166cddcb259SBaptiste Daroussin glob_t g; 1678729f5ecSAllan Jude char *disk, *endptr; 1688729f5ecSAllan Jude size_t len, i, ndisks; 1698729f5ecSAllan Jude int fd; 1708729f5ecSAllan Jude unsigned int nobj, j, sesid; 1718729f5ecSAllan Jude bool all, isses, onoff; 172cddcb259SBaptiste Daroussin 1738729f5ecSAllan Jude isses = false; 1748729f5ecSAllan Jude all = false; 1758729f5ecSAllan Jude onoff = false; 1768729f5ecSAllan Jude 1778729f5ecSAllan Jude if (argc != 3) { 1786af5d161SAllan Jude usage(stderr, (setfault ? "fault" : "locate")); 179cddcb259SBaptiste Daroussin } 180cddcb259SBaptiste Daroussin 1818729f5ecSAllan Jude disk = argv[1]; 182cddcb259SBaptiste Daroussin 1838729f5ecSAllan Jude sesid = strtoul(disk, &endptr, 10); 1848729f5ecSAllan Jude if (*endptr == '\0') { 1858729f5ecSAllan Jude endptr = strrchr(uflag, '*'); 18696e6c444SBaptiste Daroussin if (endptr != NULL && *endptr == '*') { 187d25c1ff6SBaptiste Daroussin xo_warnx("Must specifying a SES device (-u) to use a SES " 1888729f5ecSAllan Jude "id# to identify a disk"); 1896af5d161SAllan Jude usage(stderr, (setfault ? "fault" : "locate")); 1908729f5ecSAllan Jude } 1918729f5ecSAllan Jude isses = true; 1928729f5ecSAllan Jude } 1938729f5ecSAllan Jude 1948729f5ecSAllan Jude if (strcmp(argv[2], "on") == 0) { 1954569e7cfSBaptiste Daroussin onoff = true; 1968729f5ecSAllan Jude } else if (strcmp(argv[2], "off") == 0) { 1974569e7cfSBaptiste Daroussin onoff = false; 198cddcb259SBaptiste Daroussin } else { 1996af5d161SAllan Jude usage(stderr, (setfault ? "fault" : "locate")); 200cddcb259SBaptiste Daroussin } 201cddcb259SBaptiste Daroussin 202cddcb259SBaptiste Daroussin if (strcmp(disk, "all") == 0) { 203cddcb259SBaptiste Daroussin all = true; 204cddcb259SBaptiste Daroussin } 205cddcb259SBaptiste Daroussin len = strlen(disk); 206cddcb259SBaptiste Daroussin 207cddcb259SBaptiste Daroussin /* Get the list of ses devices */ 2088729f5ecSAllan Jude if (glob((uflag != NULL ? uflag : "/dev/ses[0-9]*"), 0, NULL, &g) == 2098729f5ecSAllan Jude GLOB_NOMATCH) { 2108729f5ecSAllan Jude globfree(&g); 211d25c1ff6SBaptiste Daroussin xo_errx(EXIT_FAILURE, "No SES devices found"); 2128729f5ecSAllan Jude } 2138729f5ecSAllan Jude 2148729f5ecSAllan Jude ndisks = 0; 2158729f5ecSAllan Jude for (i = 0; i < g.gl_pathc; i++) { 2168729f5ecSAllan Jude /* ensure we only got numbers after ses */ 2178729f5ecSAllan Jude if (strspn(g.gl_pathv[i] + 8, "0123456789") != 2188729f5ecSAllan Jude strlen(g.gl_pathv[i] + 8)) { 2198729f5ecSAllan Jude continue; 2208729f5ecSAllan Jude } 2218729f5ecSAllan Jude if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) { 2228729f5ecSAllan Jude /* 2238729f5ecSAllan Jude * Don't treat non-access errors as critical if we are 2248729f5ecSAllan Jude * accessing all devices 2258729f5ecSAllan Jude */ 2268729f5ecSAllan Jude if (errno == EACCES && g.gl_pathc > 1) { 227d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "unable to access SES device"); 2288729f5ecSAllan Jude } 229d25c1ff6SBaptiste Daroussin xo_warn("unable to access SES device: %s", g.gl_pathv[i]); 2308729f5ecSAllan Jude continue; 2318729f5ecSAllan Jude } 2328729f5ecSAllan Jude 2338729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj) < 0) { 2348729f5ecSAllan Jude close(fd); 235d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "ENCIOC_GETNELM"); 2368729f5ecSAllan Jude } 2378729f5ecSAllan Jude 2388729f5ecSAllan Jude objp = calloc(nobj, sizeof(encioc_element_t)); 2398729f5ecSAllan Jude if (objp == NULL) { 2408729f5ecSAllan Jude close(fd); 241d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "calloc()"); 2428729f5ecSAllan Jude } 2438729f5ecSAllan Jude 2448729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETELMMAP, (caddr_t) objp) < 0) { 245*a221b104SAlan Somers free(objp); 2468729f5ecSAllan Jude close(fd); 247d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "ENCIOC_GETELMMAP"); 2488729f5ecSAllan Jude } 2498729f5ecSAllan Jude 2508729f5ecSAllan Jude if (isses) { 251691a834cSAlan Somers if (sesid >= nobj) { 252*a221b104SAlan Somers free(objp); 2538729f5ecSAllan Jude close(fd); 254d25c1ff6SBaptiste Daroussin xo_errx(EXIT_FAILURE, 2558729f5ecSAllan Jude "Requested SES ID does not exist"); 2568729f5ecSAllan Jude } 257fe74eaabSAlexander Motin do_led(fd, sesid, objp[sesid].elm_type, onoff, setfault); 2588729f5ecSAllan Jude ndisks++; 259*a221b104SAlan Somers free(objp); 2608729f5ecSAllan Jude close(fd); 2618729f5ecSAllan Jude break; 2628729f5ecSAllan Jude } 2638729f5ecSAllan Jude for (j = 0; j < nobj; j++) { 26424ffc649SAllan Jude if (all) { 265fe74eaabSAlexander Motin do_led(fd, objp[j].elm_idx, objp[j].elm_type, 266fe74eaabSAlexander Motin onoff, setfault); 26724ffc649SAllan Jude continue; 26824ffc649SAllan Jude } 2698729f5ecSAllan Jude memset(&objdn, 0, sizeof(objdn)); 2708729f5ecSAllan Jude objdn.elm_idx = objp[j].elm_idx; 2718729f5ecSAllan Jude objdn.elm_names_size = 128; 2728729f5ecSAllan Jude objdn.elm_devnames = calloc(128, sizeof(char)); 2738729f5ecSAllan Jude if (objdn.elm_devnames == NULL) { 2748729f5ecSAllan Jude close(fd); 275d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "calloc()"); 2768729f5ecSAllan Jude } 2778729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETELMDEVNAMES, 2788729f5ecSAllan Jude (caddr_t) &objdn) <0) { 2798729f5ecSAllan Jude continue; 2808729f5ecSAllan Jude } 2818729f5ecSAllan Jude if (objdn.elm_names_len > 0) { 2828729f5ecSAllan Jude if (disk_match(objdn.elm_devnames, disk, len)) { 283fe74eaabSAlexander Motin do_led(fd, objdn.elm_idx, objp[j].elm_type, 2846af5d161SAllan Jude onoff, setfault); 2858729f5ecSAllan Jude ndisks++; 2868729f5ecSAllan Jude break; 2878729f5ecSAllan Jude } 2888729f5ecSAllan Jude } 2898729f5ecSAllan Jude } 290f734685eSBaptiste Daroussin free(objp); 2918729f5ecSAllan Jude close(fd); 2928729f5ecSAllan Jude } 2938729f5ecSAllan Jude globfree(&g); 2948729f5ecSAllan Jude if (ndisks == 0 && all == false) { 295d25c1ff6SBaptiste Daroussin xo_errx(EXIT_FAILURE, "Count not find the SES id of device '%s'", 2968729f5ecSAllan Jude disk); 2978729f5ecSAllan Jude } 2988729f5ecSAllan Jude 2998729f5ecSAllan Jude return (EXIT_SUCCESS); 3008729f5ecSAllan Jude } 3018729f5ecSAllan Jude 3028729f5ecSAllan Jude static int 3038729f5ecSAllan Jude locate(int argc, char **argv) 3048729f5ecSAllan Jude { 3058729f5ecSAllan Jude 3068729f5ecSAllan Jude return (sesled(argc, argv, false)); 3078729f5ecSAllan Jude } 3088729f5ecSAllan Jude 3098729f5ecSAllan Jude static int 3108729f5ecSAllan Jude fault(int argc, char **argv) 3118729f5ecSAllan Jude { 3128729f5ecSAllan Jude 3138729f5ecSAllan Jude return (sesled(argc, argv, true)); 3148729f5ecSAllan Jude } 3158729f5ecSAllan Jude 31620a957e3SBaptiste Daroussin #define TEMPERATURE_OFFSET 20 31720a957e3SBaptiste Daroussin static void 31820a957e3SBaptiste Daroussin sesutil_print(bool *title, const char *fmt, ...) 31920a957e3SBaptiste Daroussin { 32020a957e3SBaptiste Daroussin va_list args; 32120a957e3SBaptiste Daroussin 32220a957e3SBaptiste Daroussin if (!*title) { 323d25c1ff6SBaptiste Daroussin xo_open_container("extra_status"); 324d25c1ff6SBaptiste Daroussin xo_emit("\t\tExtra status:\n"); 32520a957e3SBaptiste Daroussin *title = true; 32620a957e3SBaptiste Daroussin } 32720a957e3SBaptiste Daroussin va_start(args, fmt); 328d25c1ff6SBaptiste Daroussin xo_emit_hv(NULL, fmt, args); 32920a957e3SBaptiste Daroussin va_end(args); 33020a957e3SBaptiste Daroussin } 33120a957e3SBaptiste Daroussin 33220a957e3SBaptiste Daroussin static void 33320a957e3SBaptiste Daroussin print_extra_status(int eletype, u_char *cstat) 33420a957e3SBaptiste Daroussin { 33520a957e3SBaptiste Daroussin bool title = false; 33620a957e3SBaptiste Daroussin 33720a957e3SBaptiste Daroussin if (cstat[0] & 0x40) { 338d25c1ff6SBaptiste Daroussin sesutil_print(&title, "\t\t-{e:predicted_failure/true} Predicted Failure\n"); 33920a957e3SBaptiste Daroussin } 34020a957e3SBaptiste Daroussin if (cstat[0] & 0x20) { 341d25c1ff6SBaptiste Daroussin sesutil_print(&title, "\t\t-{e:disabled/true} Disabled\n"); 34220a957e3SBaptiste Daroussin } 34320a957e3SBaptiste Daroussin if (cstat[0] & 0x10) { 344d25c1ff6SBaptiste Daroussin sesutil_print(&title, "\t\t-{e:swapped/true} Swapped\n"); 34520a957e3SBaptiste Daroussin } 34620a957e3SBaptiste Daroussin switch (eletype) { 34720a957e3SBaptiste Daroussin case ELMTYP_DEVICE: 34820a957e3SBaptiste Daroussin case ELMTYP_ARRAY_DEV: 34920a957e3SBaptiste Daroussin if (cstat[2] & 0x02) { 350d25c1ff6SBaptiste Daroussin sesutil_print(&title, "\t\t- LED={q:led/locate}\n"); 35120a957e3SBaptiste Daroussin } 35220a957e3SBaptiste Daroussin if (cstat[2] & 0x20) { 353d25c1ff6SBaptiste Daroussin sesutil_print(&title, "\t\t- LED={q:led/fault}\n"); 35420a957e3SBaptiste Daroussin } 35520a957e3SBaptiste Daroussin break; 35620a957e3SBaptiste Daroussin case ELMTYP_FAN: 357d25c1ff6SBaptiste Daroussin sesutil_print(&title, "\t\t- Speed: {:speed/%d}{Uw:rpm}\n", 35820a957e3SBaptiste Daroussin (((0x7 & cstat[1]) << 8) + cstat[2]) * 10); 35920a957e3SBaptiste Daroussin break; 36020a957e3SBaptiste Daroussin case ELMTYP_THERM: 36120a957e3SBaptiste Daroussin if (cstat[2]) { 362d25c1ff6SBaptiste Daroussin sesutil_print(&title, "\t\t- Temperature: {:temperature/%d}{Uw:C}\n", 36320a957e3SBaptiste Daroussin cstat[2] - TEMPERATURE_OFFSET); 36420a957e3SBaptiste Daroussin } else { 365d25c1ff6SBaptiste Daroussin sesutil_print(&title, "\t\t- Temperature: -{q:temperature/reserved}-\n"); 36620a957e3SBaptiste Daroussin } 36720a957e3SBaptiste Daroussin break; 36820a957e3SBaptiste Daroussin case ELMTYP_VOM: 369d25c1ff6SBaptiste Daroussin sesutil_print(&title, "\t\t- Voltage: {:voltage/%.2f}{Uw:V}\n", 37020a957e3SBaptiste Daroussin be16dec(cstat + 2) / 100.0); 37120a957e3SBaptiste Daroussin break; 37220a957e3SBaptiste Daroussin } 373d25c1ff6SBaptiste Daroussin if (title) { 374d25c1ff6SBaptiste Daroussin xo_close_container("extra_status"); 375d25c1ff6SBaptiste Daroussin } 37620a957e3SBaptiste Daroussin } 37720a957e3SBaptiste Daroussin 3788729f5ecSAllan Jude static int 3798729f5ecSAllan Jude objmap(int argc, char **argv __unused) 3808729f5ecSAllan Jude { 38160f46640SBaptiste Daroussin encioc_string_t stri; 3828729f5ecSAllan Jude encioc_elm_devnames_t e_devname; 3838729f5ecSAllan Jude encioc_elm_status_t e_status; 3848729f5ecSAllan Jude encioc_elm_desc_t e_desc; 3858729f5ecSAllan Jude encioc_element_t *e_ptr; 3868729f5ecSAllan Jude glob_t g; 3878729f5ecSAllan Jude int fd; 3888729f5ecSAllan Jude unsigned int j, nobj; 3898729f5ecSAllan Jude size_t i; 39060f46640SBaptiste Daroussin char str[32]; 3918729f5ecSAllan Jude 3928729f5ecSAllan Jude if (argc != 1) { 3938729f5ecSAllan Jude usage(stderr, "map"); 3948729f5ecSAllan Jude } 3958729f5ecSAllan Jude 3968729f5ecSAllan Jude /* Get the list of ses devices */ 3978729f5ecSAllan Jude if (glob(uflag, 0, NULL, &g) == GLOB_NOMATCH) { 398cddcb259SBaptiste Daroussin globfree(&g); 399d25c1ff6SBaptiste Daroussin xo_errx(EXIT_FAILURE, "No SES devices found"); 400cddcb259SBaptiste Daroussin } 401d25c1ff6SBaptiste Daroussin xo_set_version(SESUTIL_XO_VERSION); 402d25c1ff6SBaptiste Daroussin xo_open_container("sesutil"); 403d25c1ff6SBaptiste Daroussin xo_open_list("enclosures"); 404cddcb259SBaptiste Daroussin for (i = 0; i < g.gl_pathc; i++) { 405cddcb259SBaptiste Daroussin /* ensure we only got numbers after ses */ 406cddcb259SBaptiste Daroussin if (strspn(g.gl_pathv[i] + 8, "0123456789") != 4078729f5ecSAllan Jude strlen(g.gl_pathv[i] + 8)) { 408cddcb259SBaptiste Daroussin continue; 4098729f5ecSAllan Jude } 410cddcb259SBaptiste Daroussin if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) { 4118729f5ecSAllan Jude /* 4128729f5ecSAllan Jude * Don't treat non-access errors as critical if we are 4138729f5ecSAllan Jude * accessing all devices 4148729f5ecSAllan Jude */ 4158729f5ecSAllan Jude if (errno == EACCES && g.gl_pathc > 1) { 416d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "unable to access SES device"); 4178729f5ecSAllan Jude } 418d25c1ff6SBaptiste Daroussin xo_warn("unable to access SES device: %s", g.gl_pathv[i]); 4198729f5ecSAllan Jude continue; 420cddcb259SBaptiste Daroussin } 421cddcb259SBaptiste Daroussin 4228729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj) < 0) { 4238729f5ecSAllan Jude close(fd); 424d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "ENCIOC_GETNELM"); 4258729f5ecSAllan Jude } 426cddcb259SBaptiste Daroussin 4278729f5ecSAllan Jude e_ptr = calloc(nobj, sizeof(encioc_element_t)); 4288729f5ecSAllan Jude if (e_ptr == NULL) { 4298729f5ecSAllan Jude close(fd); 430d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "calloc()"); 4318729f5ecSAllan Jude } 432cddcb259SBaptiste Daroussin 4338729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETELMMAP, (caddr_t) e_ptr) < 0) { 4348729f5ecSAllan Jude close(fd); 435d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "ENCIOC_GETELMMAP"); 4368729f5ecSAllan Jude } 437cddcb259SBaptiste Daroussin 438d25c1ff6SBaptiste Daroussin xo_open_instance("enclosures"); 439d25c1ff6SBaptiste Daroussin xo_emit("{t:enc/%s}:\n", g.gl_pathv[i] + 5); 44060f46640SBaptiste Daroussin stri.bufsiz = sizeof(str); 44160f46640SBaptiste Daroussin stri.buf = &str[0]; 44260f46640SBaptiste Daroussin if (ioctl(fd, ENCIOC_GETENCNAME, (caddr_t) &stri) == 0) 443d25c1ff6SBaptiste Daroussin xo_emit("\tEnclosure Name: {t:name/%s}\n", stri.buf); 44460f46640SBaptiste Daroussin stri.bufsiz = sizeof(str); 44560f46640SBaptiste Daroussin stri.buf = &str[0]; 44660f46640SBaptiste Daroussin if (ioctl(fd, ENCIOC_GETENCID, (caddr_t) &stri) == 0) 447d25c1ff6SBaptiste Daroussin xo_emit("\tEnclosure ID: {t:id/%s}\n", stri.buf); 44860f46640SBaptiste Daroussin 449d25c1ff6SBaptiste Daroussin xo_open_list("elements"); 450cddcb259SBaptiste Daroussin for (j = 0; j < nobj; j++) { 4518729f5ecSAllan Jude /* Get the status of the element */ 4528729f5ecSAllan Jude memset(&e_status, 0, sizeof(e_status)); 4538729f5ecSAllan Jude e_status.elm_idx = e_ptr[j].elm_idx; 4548729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETELMSTAT, 4558729f5ecSAllan Jude (caddr_t) &e_status) < 0) { 4568729f5ecSAllan Jude close(fd); 457d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "ENCIOC_GETELMSTAT"); 4588729f5ecSAllan Jude } 4598729f5ecSAllan Jude /* Get the description of the element */ 4608729f5ecSAllan Jude memset(&e_desc, 0, sizeof(e_desc)); 4618729f5ecSAllan Jude e_desc.elm_idx = e_ptr[j].elm_idx; 4628729f5ecSAllan Jude e_desc.elm_desc_len = UINT16_MAX; 4638729f5ecSAllan Jude e_desc.elm_desc_str = calloc(UINT16_MAX, sizeof(char)); 4648729f5ecSAllan Jude if (e_desc.elm_desc_str == NULL) { 4658729f5ecSAllan Jude close(fd); 466d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "calloc()"); 4678729f5ecSAllan Jude } 4688729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETELMDESC, 4698729f5ecSAllan Jude (caddr_t) &e_desc) < 0) { 4708729f5ecSAllan Jude close(fd); 471d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "ENCIOC_GETELMDESC"); 4728729f5ecSAllan Jude } 4738729f5ecSAllan Jude /* Get the device name(s) of the element */ 4748729f5ecSAllan Jude memset(&e_devname, 0, sizeof(e_devname)); 4758729f5ecSAllan Jude e_devname.elm_idx = e_ptr[j].elm_idx; 4768729f5ecSAllan Jude e_devname.elm_names_size = 128; 4778729f5ecSAllan Jude e_devname.elm_devnames = calloc(128, sizeof(char)); 4788729f5ecSAllan Jude if (e_devname.elm_devnames == NULL) { 4798729f5ecSAllan Jude close(fd); 480d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "calloc()"); 4818729f5ecSAllan Jude } 482cddcb259SBaptiste Daroussin if (ioctl(fd, ENCIOC_GETELMDEVNAMES, 4838729f5ecSAllan Jude (caddr_t) &e_devname) <0) { 4848729f5ecSAllan Jude /* We don't care if this fails */ 4858729f5ecSAllan Jude e_devname.elm_devnames[0] = '\0'; 486cddcb259SBaptiste Daroussin } 487d25c1ff6SBaptiste Daroussin xo_open_instance("elements"); 488d25c1ff6SBaptiste Daroussin xo_emit("\tElement {:id/%u}, Type: {:type/%s}\n", e_ptr[j].elm_idx, 4898729f5ecSAllan Jude geteltnm(e_ptr[j].elm_type)); 490d25c1ff6SBaptiste Daroussin xo_emit("\t\tStatus: {:status/%s} ({q:status_code/0x%02x 0x%02x 0x%02x 0x%02x})\n", 491d7654478SBaptiste Daroussin scode2ascii(e_status.cstat[0]), e_status.cstat[0], 492d7654478SBaptiste Daroussin e_status.cstat[1], e_status.cstat[2], 493d7654478SBaptiste Daroussin e_status.cstat[3]); 4948729f5ecSAllan Jude if (e_desc.elm_desc_len > 0) { 495d25c1ff6SBaptiste Daroussin xo_emit("\t\tDescription: {:description/%s}\n", 4968729f5ecSAllan Jude e_desc.elm_desc_str); 497cddcb259SBaptiste Daroussin } 4988729f5ecSAllan Jude if (e_devname.elm_names_len > 0) { 499d25c1ff6SBaptiste Daroussin xo_emit("\t\tDevice Names: {:device_names/%s}\n", 5008729f5ecSAllan Jude e_devname.elm_devnames); 501cddcb259SBaptiste Daroussin } 50220a957e3SBaptiste Daroussin print_extra_status(e_ptr[j].elm_type, e_status.cstat); 503d25c1ff6SBaptiste Daroussin xo_close_instance("elements"); 5048729f5ecSAllan Jude free(e_devname.elm_devnames); 505cddcb259SBaptiste Daroussin } 506d25c1ff6SBaptiste Daroussin xo_close_list("elements"); 507f734685eSBaptiste Daroussin free(e_ptr); 508cddcb259SBaptiste Daroussin close(fd); 509cddcb259SBaptiste Daroussin } 510cddcb259SBaptiste Daroussin globfree(&g); 511d25c1ff6SBaptiste Daroussin xo_close_list("enclosures"); 512d25c1ff6SBaptiste Daroussin xo_close_container("sesutil"); 513d25c1ff6SBaptiste Daroussin xo_finish(); 514cddcb259SBaptiste Daroussin 515cddcb259SBaptiste Daroussin return (EXIT_SUCCESS); 516cddcb259SBaptiste Daroussin } 517cddcb259SBaptiste Daroussin 5188729f5ecSAllan Jude static int 5198729f5ecSAllan Jude encstatus(int argc, char **argv __unused) 520cddcb259SBaptiste Daroussin { 5218729f5ecSAllan Jude glob_t g; 5228729f5ecSAllan Jude int fd, status; 5238729f5ecSAllan Jude size_t i, e; 5248729f5ecSAllan Jude u_char estat; 525cddcb259SBaptiste Daroussin 5268729f5ecSAllan Jude status = 0; 5278729f5ecSAllan Jude if (argc != 1) { 5288729f5ecSAllan Jude usage(stderr, "status"); 5298729f5ecSAllan Jude } 5308729f5ecSAllan Jude 5318729f5ecSAllan Jude /* Get the list of ses devices */ 5328729f5ecSAllan Jude if (glob(uflag, 0, NULL, &g) == GLOB_NOMATCH) { 5338729f5ecSAllan Jude globfree(&g); 534d25c1ff6SBaptiste Daroussin xo_errx(EXIT_FAILURE, "No SES devices found"); 5358729f5ecSAllan Jude } 536d25c1ff6SBaptiste Daroussin 537d25c1ff6SBaptiste Daroussin xo_set_version(SESUTIL_XO_VERSION); 538d25c1ff6SBaptiste Daroussin xo_open_container("sesutil"); 539d25c1ff6SBaptiste Daroussin xo_open_list("enclosures"); 5408729f5ecSAllan Jude for (i = 0; i < g.gl_pathc; i++) { 5418729f5ecSAllan Jude /* ensure we only got numbers after ses */ 5428729f5ecSAllan Jude if (strspn(g.gl_pathv[i] + 8, "0123456789") != 5438729f5ecSAllan Jude strlen(g.gl_pathv[i] + 8)) { 5448729f5ecSAllan Jude continue; 5458729f5ecSAllan Jude } 5468729f5ecSAllan Jude if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) { 5478729f5ecSAllan Jude /* 5488729f5ecSAllan Jude * Don't treat non-access errors as critical if we are 5498729f5ecSAllan Jude * accessing all devices 5508729f5ecSAllan Jude */ 5518729f5ecSAllan Jude if (errno == EACCES && g.gl_pathc > 1) { 552d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "unable to access SES device"); 5538729f5ecSAllan Jude } 554d25c1ff6SBaptiste Daroussin xo_warn("unable to access SES device: %s", g.gl_pathv[i]); 5558729f5ecSAllan Jude continue; 5568729f5ecSAllan Jude } 5578729f5ecSAllan Jude 5588729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETENCSTAT, (caddr_t) &estat) < 0) { 559d25c1ff6SBaptiste Daroussin xo_err(EXIT_FAILURE, "ENCIOC_GETENCSTAT"); 5608729f5ecSAllan Jude close(fd); 5618729f5ecSAllan Jude } 5628729f5ecSAllan Jude 563d25c1ff6SBaptiste Daroussin xo_open_instance("enclosures"); 564d25c1ff6SBaptiste Daroussin xo_emit("{:enc/%s}: ", g.gl_pathv[i] + 5); 5658729f5ecSAllan Jude e = 0; 5668729f5ecSAllan Jude if (estat == 0) { 5678729f5ecSAllan Jude if (status == 0) { 5688729f5ecSAllan Jude status = 1; 5698729f5ecSAllan Jude } 570d25c1ff6SBaptiste Daroussin xo_emit("{q:status/OK}"); 5718729f5ecSAllan Jude } else { 5728729f5ecSAllan Jude if (estat & SES_ENCSTAT_INFO) { 573d25c1ff6SBaptiste Daroussin xo_emit("{lq:status/INFO}"); 5748729f5ecSAllan Jude e++; 5758729f5ecSAllan Jude } 5768729f5ecSAllan Jude if (estat & SES_ENCSTAT_NONCRITICAL) { 5778729f5ecSAllan Jude if (e) 578d25c1ff6SBaptiste Daroussin xo_emit(","); 579d25c1ff6SBaptiste Daroussin xo_emit("{lq:status/NONCRITICAL}"); 5808729f5ecSAllan Jude e++; 5818729f5ecSAllan Jude } 5828729f5ecSAllan Jude if (estat & SES_ENCSTAT_CRITICAL) { 5838729f5ecSAllan Jude if (e) 584d25c1ff6SBaptiste Daroussin xo_emit(","); 585d25c1ff6SBaptiste Daroussin xo_emit("{lq:status/CRITICAL}"); 5868729f5ecSAllan Jude e++; 5878729f5ecSAllan Jude status = -1; 5888729f5ecSAllan Jude } 5898729f5ecSAllan Jude if (estat & SES_ENCSTAT_UNRECOV) { 5908729f5ecSAllan Jude if (e) 591d25c1ff6SBaptiste Daroussin xo_emit(","); 592d25c1ff6SBaptiste Daroussin xo_emit("{lq:status/UNRECOV}"); 5938729f5ecSAllan Jude e++; 5948729f5ecSAllan Jude status = -1; 5958729f5ecSAllan Jude } 5968729f5ecSAllan Jude } 597d25c1ff6SBaptiste Daroussin xo_close_instance("enclosures"); 598d25c1ff6SBaptiste Daroussin xo_emit("\n"); 5998729f5ecSAllan Jude close(fd); 6008729f5ecSAllan Jude } 6018729f5ecSAllan Jude globfree(&g); 6028729f5ecSAllan Jude 603d25c1ff6SBaptiste Daroussin xo_close_list("enclosures"); 604d25c1ff6SBaptiste Daroussin xo_close_container("sesutil"); 605d25c1ff6SBaptiste Daroussin xo_finish(); 606d25c1ff6SBaptiste Daroussin 6078729f5ecSAllan Jude if (status == 1) { 6088729f5ecSAllan Jude return (EXIT_SUCCESS); 6098729f5ecSAllan Jude } else { 6108729f5ecSAllan Jude return (EXIT_FAILURE); 6118729f5ecSAllan Jude } 612cddcb259SBaptiste Daroussin } 613cddcb259SBaptiste Daroussin 614cddcb259SBaptiste Daroussin int 615cddcb259SBaptiste Daroussin main(int argc, char **argv) 616cddcb259SBaptiste Daroussin { 6178729f5ecSAllan Jude int i, ch; 618cddcb259SBaptiste Daroussin struct command *cmd = NULL; 619cddcb259SBaptiste Daroussin 620d25c1ff6SBaptiste Daroussin argc = xo_parse_args(argc, argv); 621d25c1ff6SBaptiste Daroussin if (argc < 0) 622d25c1ff6SBaptiste Daroussin exit(1); 623d25c1ff6SBaptiste Daroussin 6248729f5ecSAllan Jude uflag = "/dev/ses[0-9]*"; 6258729f5ecSAllan Jude while ((ch = getopt_long(argc, argv, "u:", NULL, NULL)) != -1) { 6268729f5ecSAllan Jude switch (ch) { 6278729f5ecSAllan Jude case 'u': 6288729f5ecSAllan Jude uflag = optarg; 6298729f5ecSAllan Jude break; 6308729f5ecSAllan Jude case '?': 6318729f5ecSAllan Jude default: 6328729f5ecSAllan Jude usage(stderr, NULL); 6338729f5ecSAllan Jude } 6348729f5ecSAllan Jude } 6358729f5ecSAllan Jude argc -= optind; 6368729f5ecSAllan Jude argv += optind; 6378729f5ecSAllan Jude 6388729f5ecSAllan Jude if (argc < 1) { 639cddcb259SBaptiste Daroussin warnx("Missing command"); 6408729f5ecSAllan Jude usage(stderr, NULL); 641cddcb259SBaptiste Daroussin } 642cddcb259SBaptiste Daroussin 643cddcb259SBaptiste Daroussin for (i = 0; i < nbcmds; i++) { 6448729f5ecSAllan Jude if (strcmp(argv[0], cmds[i].name) == 0) { 645cddcb259SBaptiste Daroussin cmd = &cmds[i]; 646cddcb259SBaptiste Daroussin break; 647cddcb259SBaptiste Daroussin } 648cddcb259SBaptiste Daroussin } 649cddcb259SBaptiste Daroussin 650cddcb259SBaptiste Daroussin if (cmd == NULL) { 6518729f5ecSAllan Jude warnx("unknown command %s", argv[0]); 6528729f5ecSAllan Jude usage(stderr, NULL); 653cddcb259SBaptiste Daroussin } 654cddcb259SBaptiste Daroussin 655cddcb259SBaptiste Daroussin return (cmd->exec(argc, argv)); 656cddcb259SBaptiste Daroussin } 657