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 32*20a957e3SBaptiste 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> 49cddcb259SBaptiste Daroussin 50cddcb259SBaptiste Daroussin #include <cam/scsi/scsi_enc.h> 51cddcb259SBaptiste Daroussin 528729f5ecSAllan Jude #include "eltsub.h" 538729f5ecSAllan Jude 548729f5ecSAllan Jude static int encstatus(int argc, char **argv); 558729f5ecSAllan Jude static int fault(int argc, char **argv); 56cddcb259SBaptiste Daroussin static int locate(int argc, char **argv); 578729f5ecSAllan Jude static int objmap(int argc, char **argv); 588729f5ecSAllan Jude static int sesled(int argc, char **argv, bool fault); 59*20a957e3SBaptiste Daroussin static void sesutil_print(bool *title, const char *fmt, ...) __printflike(2,3); 60cddcb259SBaptiste Daroussin 61cddcb259SBaptiste Daroussin static struct command { 62cddcb259SBaptiste Daroussin const char *name; 638729f5ecSAllan Jude const char *param; 64cddcb259SBaptiste Daroussin const char *desc; 65cddcb259SBaptiste Daroussin int (*exec)(int argc, char **argv); 66cddcb259SBaptiste Daroussin } cmds[] = { 678729f5ecSAllan Jude { "fault", 688729f5ecSAllan Jude "(<disk>|<sesid>|all) (on|off)", 698729f5ecSAllan Jude "Change the state of the fault LED associated with a disk", 708729f5ecSAllan Jude fault }, 718729f5ecSAllan Jude { "locate", 728729f5ecSAllan Jude "(<disk>|<sesid>|all) (on|off)", 738729f5ecSAllan Jude "Change the state of the locate LED associated with a disk", 748729f5ecSAllan Jude locate }, 758729f5ecSAllan Jude { "map", "", 768729f5ecSAllan Jude "Print a map of the devices managed by the enclosure", objmap } , 778729f5ecSAllan Jude { "status", "", "Print the status of the enclosure", 788729f5ecSAllan Jude encstatus }, 79cddcb259SBaptiste Daroussin }; 80cddcb259SBaptiste Daroussin 81cddcb259SBaptiste Daroussin static const int nbcmds = nitems(cmds); 828729f5ecSAllan Jude static const char *uflag; 83cddcb259SBaptiste Daroussin 84cddcb259SBaptiste Daroussin static void 858729f5ecSAllan Jude usage(FILE *out, const char *subcmd) 868729f5ecSAllan Jude { 878729f5ecSAllan Jude int i; 888729f5ecSAllan Jude 898729f5ecSAllan Jude if (subcmd == NULL) { 908729f5ecSAllan Jude fprintf(out, "Usage: %s [-u /dev/ses<N>] <command> [options]\n", 918729f5ecSAllan Jude getprogname()); 928729f5ecSAllan Jude fprintf(out, "Commands supported:\n"); 938729f5ecSAllan Jude } 948729f5ecSAllan Jude for (i = 0; i < nbcmds; i++) { 958729f5ecSAllan Jude if (subcmd != NULL) { 968729f5ecSAllan Jude if (strcmp(subcmd, cmds[i].name) == 0) { 978729f5ecSAllan Jude fprintf(out, "Usage: %s %s [-u /dev/ses<N>] " 988729f5ecSAllan Jude "%s\n\t%s\n", getprogname(), subcmd, 998729f5ecSAllan Jude cmds[i].param, cmds[i].desc); 1008729f5ecSAllan Jude break; 1018729f5ecSAllan Jude } 1028729f5ecSAllan Jude continue; 1038729f5ecSAllan Jude } 1048729f5ecSAllan Jude fprintf(out, " %-12s%s\n\t\t%s\n\n", cmds[i].name, 1058729f5ecSAllan Jude cmds[i].param, cmds[i].desc); 1068729f5ecSAllan Jude } 1078729f5ecSAllan Jude 1088729f5ecSAllan Jude exit(EXIT_FAILURE); 1098729f5ecSAllan Jude } 1108729f5ecSAllan Jude 1118729f5ecSAllan Jude static void 1126af5d161SAllan Jude do_led(int fd, unsigned int idx, bool onoff, bool setfault) 113cddcb259SBaptiste Daroussin { 114cddcb259SBaptiste Daroussin encioc_elm_status_t o; 115cddcb259SBaptiste Daroussin 116cddcb259SBaptiste Daroussin o.elm_idx = idx; 117cddcb259SBaptiste Daroussin if (ioctl(fd, ENCIOC_GETELMSTAT, (caddr_t) &o) < 0) { 118cddcb259SBaptiste Daroussin close(fd); 119cddcb259SBaptiste Daroussin err(EXIT_FAILURE, "ENCIOC_GETELMSTAT"); 120cddcb259SBaptiste Daroussin } 121cddcb259SBaptiste Daroussin o.cstat[0] |= 0x80; 122efab8bfdSAlexander Motin if (setfault) { 123efab8bfdSAlexander Motin if (onoff) 124efab8bfdSAlexander Motin o.cstat[3] |= 0x20; 125efab8bfdSAlexander Motin else 126efab8bfdSAlexander Motin o.cstat[3] &= 0xdf; 1278729f5ecSAllan Jude } else { 128efab8bfdSAlexander Motin if (onoff) 129efab8bfdSAlexander Motin o.cstat[2] |= 0x02; 130efab8bfdSAlexander Motin else 131efab8bfdSAlexander Motin o.cstat[2] &= 0xfd; 1328729f5ecSAllan Jude } 133cddcb259SBaptiste Daroussin 134cddcb259SBaptiste Daroussin if (ioctl(fd, ENCIOC_SETELMSTAT, (caddr_t) &o) < 0) { 135cddcb259SBaptiste Daroussin close(fd); 136cddcb259SBaptiste Daroussin err(EXIT_FAILURE, "ENCIOC_SETELMSTAT"); 137cddcb259SBaptiste Daroussin } 138cddcb259SBaptiste Daroussin } 139cddcb259SBaptiste Daroussin 140cddcb259SBaptiste Daroussin static bool 141cddcb259SBaptiste Daroussin disk_match(const char *devnames, const char *disk, size_t len) 142cddcb259SBaptiste Daroussin { 1431bc54324SBaptiste Daroussin const char *dname; 144cddcb259SBaptiste Daroussin 1451bc54324SBaptiste Daroussin dname = devnames; 1461bc54324SBaptiste Daroussin while ((dname = strstr(dname, disk)) != NULL) { 1478729f5ecSAllan Jude if (dname[len] == '\0' || dname[len] == ',') { 148cddcb259SBaptiste Daroussin return (true); 1498729f5ecSAllan Jude } 1501bc54324SBaptiste Daroussin dname++; 151cddcb259SBaptiste Daroussin } 1528729f5ecSAllan Jude 153cddcb259SBaptiste Daroussin return (false); 154cddcb259SBaptiste Daroussin } 155cddcb259SBaptiste Daroussin 156cddcb259SBaptiste Daroussin static int 1576af5d161SAllan Jude sesled(int argc, char **argv, bool setfault) 158cddcb259SBaptiste Daroussin { 159cddcb259SBaptiste Daroussin encioc_elm_devnames_t objdn; 160cddcb259SBaptiste Daroussin encioc_element_t *objp; 161cddcb259SBaptiste Daroussin glob_t g; 1628729f5ecSAllan Jude char *disk, *endptr; 1638729f5ecSAllan Jude size_t len, i, ndisks; 1648729f5ecSAllan Jude int fd; 1658729f5ecSAllan Jude unsigned int nobj, j, sesid; 1668729f5ecSAllan Jude bool all, isses, onoff; 167cddcb259SBaptiste Daroussin 1688729f5ecSAllan Jude isses = false; 1698729f5ecSAllan Jude all = false; 1708729f5ecSAllan Jude onoff = false; 1718729f5ecSAllan Jude 1728729f5ecSAllan Jude if (argc != 3) { 1736af5d161SAllan Jude usage(stderr, (setfault ? "fault" : "locate")); 174cddcb259SBaptiste Daroussin } 175cddcb259SBaptiste Daroussin 1768729f5ecSAllan Jude disk = argv[1]; 177cddcb259SBaptiste Daroussin 1788729f5ecSAllan Jude sesid = strtoul(disk, &endptr, 10); 1798729f5ecSAllan Jude if (*endptr == '\0') { 1808729f5ecSAllan Jude endptr = strrchr(uflag, '*'); 18196e6c444SBaptiste Daroussin if (endptr != NULL && *endptr == '*') { 1828729f5ecSAllan Jude warnx("Must specifying a SES device (-u) to use a SES " 1838729f5ecSAllan Jude "id# to identify a disk"); 1846af5d161SAllan Jude usage(stderr, (setfault ? "fault" : "locate")); 1858729f5ecSAllan Jude } 1868729f5ecSAllan Jude isses = true; 1878729f5ecSAllan Jude } 1888729f5ecSAllan Jude 1898729f5ecSAllan Jude if (strcmp(argv[2], "on") == 0) { 1904569e7cfSBaptiste Daroussin onoff = true; 1918729f5ecSAllan Jude } else if (strcmp(argv[2], "off") == 0) { 1924569e7cfSBaptiste Daroussin onoff = false; 193cddcb259SBaptiste Daroussin } else { 1946af5d161SAllan Jude usage(stderr, (setfault ? "fault" : "locate")); 195cddcb259SBaptiste Daroussin } 196cddcb259SBaptiste Daroussin 197cddcb259SBaptiste Daroussin if (strcmp(disk, "all") == 0) { 198cddcb259SBaptiste Daroussin all = true; 199cddcb259SBaptiste Daroussin } 200cddcb259SBaptiste Daroussin len = strlen(disk); 201cddcb259SBaptiste Daroussin 202cddcb259SBaptiste Daroussin /* Get the list of ses devices */ 2038729f5ecSAllan Jude if (glob((uflag != NULL ? uflag : "/dev/ses[0-9]*"), 0, NULL, &g) == 2048729f5ecSAllan Jude GLOB_NOMATCH) { 2058729f5ecSAllan Jude globfree(&g); 2068729f5ecSAllan Jude errx(EXIT_FAILURE, "No SES devices found"); 2078729f5ecSAllan Jude } 2088729f5ecSAllan Jude 2098729f5ecSAllan Jude ndisks = 0; 2108729f5ecSAllan Jude for (i = 0; i < g.gl_pathc; i++) { 2118729f5ecSAllan Jude /* ensure we only got numbers after ses */ 2128729f5ecSAllan Jude if (strspn(g.gl_pathv[i] + 8, "0123456789") != 2138729f5ecSAllan Jude strlen(g.gl_pathv[i] + 8)) { 2148729f5ecSAllan Jude continue; 2158729f5ecSAllan Jude } 2168729f5ecSAllan Jude if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) { 2178729f5ecSAllan Jude /* 2188729f5ecSAllan Jude * Don't treat non-access errors as critical if we are 2198729f5ecSAllan Jude * accessing all devices 2208729f5ecSAllan Jude */ 2218729f5ecSAllan Jude if (errno == EACCES && g.gl_pathc > 1) { 2228729f5ecSAllan Jude err(EXIT_FAILURE, "unable to access SES device"); 2238729f5ecSAllan Jude } 2248729f5ecSAllan Jude warn("unable to access SES device: %s", g.gl_pathv[i]); 2258729f5ecSAllan Jude continue; 2268729f5ecSAllan Jude } 2278729f5ecSAllan Jude 2288729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj) < 0) { 2298729f5ecSAllan Jude close(fd); 2308729f5ecSAllan Jude err(EXIT_FAILURE, "ENCIOC_GETNELM"); 2318729f5ecSAllan Jude } 2328729f5ecSAllan Jude 2338729f5ecSAllan Jude objp = calloc(nobj, sizeof(encioc_element_t)); 2348729f5ecSAllan Jude if (objp == NULL) { 2358729f5ecSAllan Jude close(fd); 2368729f5ecSAllan Jude err(EXIT_FAILURE, "calloc()"); 2378729f5ecSAllan Jude } 2388729f5ecSAllan Jude 2398729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETELMMAP, (caddr_t) objp) < 0) { 2408729f5ecSAllan Jude close(fd); 2418729f5ecSAllan Jude err(EXIT_FAILURE, "ENCIOC_GETELMMAP"); 2428729f5ecSAllan Jude } 2438729f5ecSAllan Jude 2448729f5ecSAllan Jude if (isses) { 2458729f5ecSAllan Jude if (sesid > nobj) { 2468729f5ecSAllan Jude close(fd); 2478729f5ecSAllan Jude errx(EXIT_FAILURE, 2488729f5ecSAllan Jude "Requested SES ID does not exist"); 2498729f5ecSAllan Jude } 2506af5d161SAllan Jude do_led(fd, sesid, onoff, setfault); 2518729f5ecSAllan Jude ndisks++; 2528729f5ecSAllan Jude close(fd); 2538729f5ecSAllan Jude break; 2548729f5ecSAllan Jude } 2558729f5ecSAllan Jude for (j = 0; j < nobj; j++) { 25624ffc649SAllan Jude if (all) { 25724ffc649SAllan Jude do_led(fd, objp[j].elm_idx, onoff, setfault); 25824ffc649SAllan Jude continue; 25924ffc649SAllan Jude } 2608729f5ecSAllan Jude memset(&objdn, 0, sizeof(objdn)); 2618729f5ecSAllan Jude objdn.elm_idx = objp[j].elm_idx; 2628729f5ecSAllan Jude objdn.elm_names_size = 128; 2638729f5ecSAllan Jude objdn.elm_devnames = calloc(128, sizeof(char)); 2648729f5ecSAllan Jude if (objdn.elm_devnames == NULL) { 2658729f5ecSAllan Jude close(fd); 2668729f5ecSAllan Jude err(EXIT_FAILURE, "calloc()"); 2678729f5ecSAllan Jude } 2688729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETELMDEVNAMES, 2698729f5ecSAllan Jude (caddr_t) &objdn) <0) { 2708729f5ecSAllan Jude continue; 2718729f5ecSAllan Jude } 2728729f5ecSAllan Jude if (objdn.elm_names_len > 0) { 2738729f5ecSAllan Jude if (disk_match(objdn.elm_devnames, disk, len)) { 2748729f5ecSAllan Jude do_led(fd, objdn.elm_idx, 2756af5d161SAllan Jude onoff, setfault); 2768729f5ecSAllan Jude ndisks++; 2778729f5ecSAllan Jude break; 2788729f5ecSAllan Jude } 2798729f5ecSAllan Jude } 2808729f5ecSAllan Jude } 281f734685eSBaptiste Daroussin free(objp); 2828729f5ecSAllan Jude close(fd); 2838729f5ecSAllan Jude } 2848729f5ecSAllan Jude globfree(&g); 2858729f5ecSAllan Jude if (ndisks == 0 && all == false) { 2868729f5ecSAllan Jude errx(EXIT_FAILURE, "Count not find the SES id of device '%s'", 2878729f5ecSAllan Jude disk); 2888729f5ecSAllan Jude } 2898729f5ecSAllan Jude 2908729f5ecSAllan Jude return (EXIT_SUCCESS); 2918729f5ecSAllan Jude } 2928729f5ecSAllan Jude 2938729f5ecSAllan Jude static int 2948729f5ecSAllan Jude locate(int argc, char **argv) 2958729f5ecSAllan Jude { 2968729f5ecSAllan Jude 2978729f5ecSAllan Jude return (sesled(argc, argv, false)); 2988729f5ecSAllan Jude } 2998729f5ecSAllan Jude 3008729f5ecSAllan Jude static int 3018729f5ecSAllan Jude fault(int argc, char **argv) 3028729f5ecSAllan Jude { 3038729f5ecSAllan Jude 3048729f5ecSAllan Jude return (sesled(argc, argv, true)); 3058729f5ecSAllan Jude } 3068729f5ecSAllan Jude 307*20a957e3SBaptiste Daroussin #define TEMPERATURE_OFFSET 20 308*20a957e3SBaptiste Daroussin static void 309*20a957e3SBaptiste Daroussin sesutil_print(bool *title, const char *fmt, ...) 310*20a957e3SBaptiste Daroussin { 311*20a957e3SBaptiste Daroussin va_list args; 312*20a957e3SBaptiste Daroussin 313*20a957e3SBaptiste Daroussin if (!*title) { 314*20a957e3SBaptiste Daroussin printf("\t\tExtra status:\n"); 315*20a957e3SBaptiste Daroussin *title = true; 316*20a957e3SBaptiste Daroussin } 317*20a957e3SBaptiste Daroussin va_start(args, fmt); 318*20a957e3SBaptiste Daroussin vprintf(fmt, args); 319*20a957e3SBaptiste Daroussin va_end(args); 320*20a957e3SBaptiste Daroussin } 321*20a957e3SBaptiste Daroussin 322*20a957e3SBaptiste Daroussin static void 323*20a957e3SBaptiste Daroussin print_extra_status(int eletype, u_char *cstat) 324*20a957e3SBaptiste Daroussin { 325*20a957e3SBaptiste Daroussin bool title = false; 326*20a957e3SBaptiste Daroussin 327*20a957e3SBaptiste Daroussin if (cstat[0] & 0x40) { 328*20a957e3SBaptiste Daroussin sesutil_print(&title, "\t\t- Predicted Failure\n"); 329*20a957e3SBaptiste Daroussin } 330*20a957e3SBaptiste Daroussin if (cstat[0] & 0x20) { 331*20a957e3SBaptiste Daroussin sesutil_print(&title, "\t\t- Disabled\n"); 332*20a957e3SBaptiste Daroussin } 333*20a957e3SBaptiste Daroussin if (cstat[0] & 0x10) { 334*20a957e3SBaptiste Daroussin sesutil_print(&title, "\t\t- Swapped\n"); 335*20a957e3SBaptiste Daroussin } 336*20a957e3SBaptiste Daroussin switch (eletype) { 337*20a957e3SBaptiste Daroussin case ELMTYP_DEVICE: 338*20a957e3SBaptiste Daroussin if (cstat[2] & 0x02) { 339*20a957e3SBaptiste Daroussin sesutil_print(&title, "\t\t- LED=locate\n"); 340*20a957e3SBaptiste Daroussin } 341*20a957e3SBaptiste Daroussin if (cstat[2] & 0x20) { 342*20a957e3SBaptiste Daroussin sesutil_print(&title, "\t\t- LED=fault\n"); 343*20a957e3SBaptiste Daroussin } 344*20a957e3SBaptiste Daroussin break; 345*20a957e3SBaptiste Daroussin case ELMTYP_ARRAY_DEV: 346*20a957e3SBaptiste Daroussin if (cstat[2] & 0x02) { 347*20a957e3SBaptiste Daroussin sesutil_print(&title, "\t\t- LED=locate\n"); 348*20a957e3SBaptiste Daroussin } 349*20a957e3SBaptiste Daroussin if (cstat[2] & 0x20) { 350*20a957e3SBaptiste Daroussin sesutil_print(&title, "\t\t- LED=fault\n"); 351*20a957e3SBaptiste Daroussin } 352*20a957e3SBaptiste Daroussin break; 353*20a957e3SBaptiste Daroussin case ELMTYP_FAN: 354*20a957e3SBaptiste Daroussin sesutil_print(&title, "\t\t- Speed: %d rpm\n", 355*20a957e3SBaptiste Daroussin (((0x7 & cstat[1]) << 8) + cstat[2]) * 10); 356*20a957e3SBaptiste Daroussin break; 357*20a957e3SBaptiste Daroussin case ELMTYP_THERM: 358*20a957e3SBaptiste Daroussin if (cstat[2]) { 359*20a957e3SBaptiste Daroussin sesutil_print(&title, "\t\t- Temperature: %d C\n", 360*20a957e3SBaptiste Daroussin cstat[2] - TEMPERATURE_OFFSET); 361*20a957e3SBaptiste Daroussin } else { 362*20a957e3SBaptiste Daroussin sesutil_print(&title, "\t\t- Temperature: -reserved-\n"); 363*20a957e3SBaptiste Daroussin } 364*20a957e3SBaptiste Daroussin break; 365*20a957e3SBaptiste Daroussin case ELMTYP_VOM: 366*20a957e3SBaptiste Daroussin sesutil_print(&title, "\t\t- Voltage: %.2f V\n", 367*20a957e3SBaptiste Daroussin be16dec(cstat + 2) / 100.0); 368*20a957e3SBaptiste Daroussin break; 369*20a957e3SBaptiste Daroussin } 370*20a957e3SBaptiste Daroussin } 371*20a957e3SBaptiste Daroussin 3728729f5ecSAllan Jude static int 3738729f5ecSAllan Jude objmap(int argc, char **argv __unused) 3748729f5ecSAllan Jude { 37560f46640SBaptiste Daroussin encioc_string_t stri; 3768729f5ecSAllan Jude encioc_elm_devnames_t e_devname; 3778729f5ecSAllan Jude encioc_elm_status_t e_status; 3788729f5ecSAllan Jude encioc_elm_desc_t e_desc; 3798729f5ecSAllan Jude encioc_element_t *e_ptr; 3808729f5ecSAllan Jude glob_t g; 3818729f5ecSAllan Jude int fd; 3828729f5ecSAllan Jude unsigned int j, nobj; 3838729f5ecSAllan Jude size_t i; 38460f46640SBaptiste Daroussin char str[32]; 3858729f5ecSAllan Jude 3868729f5ecSAllan Jude if (argc != 1) { 3878729f5ecSAllan Jude usage(stderr, "map"); 3888729f5ecSAllan Jude } 3898729f5ecSAllan Jude 3908729f5ecSAllan Jude /* Get the list of ses devices */ 3918729f5ecSAllan Jude if (glob(uflag, 0, NULL, &g) == GLOB_NOMATCH) { 392cddcb259SBaptiste Daroussin globfree(&g); 393cddcb259SBaptiste Daroussin errx(EXIT_FAILURE, "No SES devices found"); 394cddcb259SBaptiste Daroussin } 395cddcb259SBaptiste Daroussin for (i = 0; i < g.gl_pathc; i++) { 396cddcb259SBaptiste Daroussin /* ensure we only got numbers after ses */ 397cddcb259SBaptiste Daroussin if (strspn(g.gl_pathv[i] + 8, "0123456789") != 3988729f5ecSAllan Jude strlen(g.gl_pathv[i] + 8)) { 399cddcb259SBaptiste Daroussin continue; 4008729f5ecSAllan Jude } 401cddcb259SBaptiste Daroussin if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) { 4028729f5ecSAllan Jude /* 4038729f5ecSAllan Jude * Don't treat non-access errors as critical if we are 4048729f5ecSAllan Jude * accessing all devices 4058729f5ecSAllan Jude */ 4068729f5ecSAllan Jude if (errno == EACCES && g.gl_pathc > 1) { 4078729f5ecSAllan Jude err(EXIT_FAILURE, "unable to access SES device"); 4088729f5ecSAllan Jude } 4098729f5ecSAllan Jude warn("unable to access SES device: %s", g.gl_pathv[i]); 4108729f5ecSAllan Jude continue; 411cddcb259SBaptiste Daroussin } 412cddcb259SBaptiste Daroussin 4138729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj) < 0) { 4148729f5ecSAllan Jude close(fd); 415cddcb259SBaptiste Daroussin err(EXIT_FAILURE, "ENCIOC_GETNELM"); 4168729f5ecSAllan Jude } 417cddcb259SBaptiste Daroussin 4188729f5ecSAllan Jude e_ptr = calloc(nobj, sizeof(encioc_element_t)); 4198729f5ecSAllan Jude if (e_ptr == NULL) { 4208729f5ecSAllan Jude close(fd); 421cddcb259SBaptiste Daroussin err(EXIT_FAILURE, "calloc()"); 4228729f5ecSAllan Jude } 423cddcb259SBaptiste Daroussin 4248729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETELMMAP, (caddr_t) e_ptr) < 0) { 4258729f5ecSAllan Jude close(fd); 426cddcb259SBaptiste Daroussin err(EXIT_FAILURE, "ENCIOC_GETELMMAP"); 4278729f5ecSAllan Jude } 428cddcb259SBaptiste Daroussin 4298729f5ecSAllan Jude printf("%s:\n", g.gl_pathv[i] + 5); 43060f46640SBaptiste Daroussin stri.bufsiz = sizeof(str); 43160f46640SBaptiste Daroussin stri.buf = &str[0]; 43260f46640SBaptiste Daroussin if (ioctl(fd, ENCIOC_GETENCNAME, (caddr_t) &stri) == 0) 43360f46640SBaptiste Daroussin printf("\tEnclosure Name: %s\n", stri.buf); 43460f46640SBaptiste Daroussin stri.bufsiz = sizeof(str); 43560f46640SBaptiste Daroussin stri.buf = &str[0]; 43660f46640SBaptiste Daroussin if (ioctl(fd, ENCIOC_GETENCID, (caddr_t) &stri) == 0) 43760f46640SBaptiste Daroussin printf("\tEnclosure ID: %s\n", stri.buf); 43860f46640SBaptiste Daroussin 439cddcb259SBaptiste Daroussin for (j = 0; j < nobj; j++) { 4408729f5ecSAllan Jude /* Get the status of the element */ 4418729f5ecSAllan Jude memset(&e_status, 0, sizeof(e_status)); 4428729f5ecSAllan Jude e_status.elm_idx = e_ptr[j].elm_idx; 4438729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETELMSTAT, 4448729f5ecSAllan Jude (caddr_t) &e_status) < 0) { 4458729f5ecSAllan Jude close(fd); 4468729f5ecSAllan Jude err(EXIT_FAILURE, "ENCIOC_GETELMSTAT"); 4478729f5ecSAllan Jude } 4488729f5ecSAllan Jude /* Get the description of the element */ 4498729f5ecSAllan Jude memset(&e_desc, 0, sizeof(e_desc)); 4508729f5ecSAllan Jude e_desc.elm_idx = e_ptr[j].elm_idx; 4518729f5ecSAllan Jude e_desc.elm_desc_len = UINT16_MAX; 4528729f5ecSAllan Jude e_desc.elm_desc_str = calloc(UINT16_MAX, sizeof(char)); 4538729f5ecSAllan Jude if (e_desc.elm_desc_str == NULL) { 4548729f5ecSAllan Jude close(fd); 455cddcb259SBaptiste Daroussin err(EXIT_FAILURE, "calloc()"); 4568729f5ecSAllan Jude } 4578729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETELMDESC, 4588729f5ecSAllan Jude (caddr_t) &e_desc) < 0) { 4598729f5ecSAllan Jude close(fd); 4608729f5ecSAllan Jude err(EXIT_FAILURE, "ENCIOC_GETELMDESC"); 4618729f5ecSAllan Jude } 4628729f5ecSAllan Jude /* Get the device name(s) of the element */ 4638729f5ecSAllan Jude memset(&e_devname, 0, sizeof(e_devname)); 4648729f5ecSAllan Jude e_devname.elm_idx = e_ptr[j].elm_idx; 4658729f5ecSAllan Jude e_devname.elm_names_size = 128; 4668729f5ecSAllan Jude e_devname.elm_devnames = calloc(128, sizeof(char)); 4678729f5ecSAllan Jude if (e_devname.elm_devnames == NULL) { 4688729f5ecSAllan Jude close(fd); 4698729f5ecSAllan Jude err(EXIT_FAILURE, "calloc()"); 4708729f5ecSAllan Jude } 471cddcb259SBaptiste Daroussin if (ioctl(fd, ENCIOC_GETELMDEVNAMES, 4728729f5ecSAllan Jude (caddr_t) &e_devname) <0) { 4738729f5ecSAllan Jude /* We don't care if this fails */ 4748729f5ecSAllan Jude e_devname.elm_devnames[0] = '\0'; 475cddcb259SBaptiste Daroussin } 4768729f5ecSAllan Jude printf("\tElement %u, Type: %s\n", e_ptr[j].elm_idx, 4778729f5ecSAllan Jude geteltnm(e_ptr[j].elm_type)); 478d7654478SBaptiste Daroussin printf("\t\tStatus: %s (0x%02x 0x%02x 0x%02x 0x%02x)\n", 479d7654478SBaptiste Daroussin scode2ascii(e_status.cstat[0]), e_status.cstat[0], 480d7654478SBaptiste Daroussin e_status.cstat[1], e_status.cstat[2], 481d7654478SBaptiste Daroussin e_status.cstat[3]); 4828729f5ecSAllan Jude if (e_desc.elm_desc_len > 0) { 4838729f5ecSAllan Jude printf("\t\tDescription: %s\n", 4848729f5ecSAllan Jude e_desc.elm_desc_str); 485cddcb259SBaptiste Daroussin } 4868729f5ecSAllan Jude if (e_devname.elm_names_len > 0) { 4878729f5ecSAllan Jude printf("\t\tDevice Names: %s\n", 4888729f5ecSAllan Jude e_devname.elm_devnames); 489cddcb259SBaptiste Daroussin } 490*20a957e3SBaptiste Daroussin print_extra_status(e_ptr[j].elm_type, e_status.cstat); 4918729f5ecSAllan Jude free(e_devname.elm_devnames); 492cddcb259SBaptiste Daroussin } 493f734685eSBaptiste Daroussin free(e_ptr); 494cddcb259SBaptiste Daroussin close(fd); 495cddcb259SBaptiste Daroussin } 496cddcb259SBaptiste Daroussin globfree(&g); 497cddcb259SBaptiste Daroussin 498cddcb259SBaptiste Daroussin return (EXIT_SUCCESS); 499cddcb259SBaptiste Daroussin } 500cddcb259SBaptiste Daroussin 5018729f5ecSAllan Jude static int 5028729f5ecSAllan Jude encstatus(int argc, char **argv __unused) 503cddcb259SBaptiste Daroussin { 5048729f5ecSAllan Jude glob_t g; 5058729f5ecSAllan Jude int fd, status; 5068729f5ecSAllan Jude size_t i, e; 5078729f5ecSAllan Jude u_char estat; 508cddcb259SBaptiste Daroussin 5098729f5ecSAllan Jude status = 0; 5108729f5ecSAllan Jude if (argc != 1) { 5118729f5ecSAllan Jude usage(stderr, "status"); 5128729f5ecSAllan Jude } 5138729f5ecSAllan Jude 5148729f5ecSAllan Jude /* Get the list of ses devices */ 5158729f5ecSAllan Jude if (glob(uflag, 0, NULL, &g) == GLOB_NOMATCH) { 5168729f5ecSAllan Jude globfree(&g); 5178729f5ecSAllan Jude errx(EXIT_FAILURE, "No SES devices found"); 5188729f5ecSAllan Jude } 5198729f5ecSAllan Jude for (i = 0; i < g.gl_pathc; i++) { 5208729f5ecSAllan Jude /* ensure we only got numbers after ses */ 5218729f5ecSAllan Jude if (strspn(g.gl_pathv[i] + 8, "0123456789") != 5228729f5ecSAllan Jude strlen(g.gl_pathv[i] + 8)) { 5238729f5ecSAllan Jude continue; 5248729f5ecSAllan Jude } 5258729f5ecSAllan Jude if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) { 5268729f5ecSAllan Jude /* 5278729f5ecSAllan Jude * Don't treat non-access errors as critical if we are 5288729f5ecSAllan Jude * accessing all devices 5298729f5ecSAllan Jude */ 5308729f5ecSAllan Jude if (errno == EACCES && g.gl_pathc > 1) { 5318729f5ecSAllan Jude err(EXIT_FAILURE, "unable to access SES device"); 5328729f5ecSAllan Jude } 5338729f5ecSAllan Jude warn("unable to access SES device: %s", g.gl_pathv[i]); 5348729f5ecSAllan Jude continue; 5358729f5ecSAllan Jude } 5368729f5ecSAllan Jude 5378729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETENCSTAT, (caddr_t) &estat) < 0) { 5388729f5ecSAllan Jude close(fd); 5398729f5ecSAllan Jude err(EXIT_FAILURE, "ENCIOC_GETENCSTAT"); 5408729f5ecSAllan Jude } 5418729f5ecSAllan Jude 5428729f5ecSAllan Jude printf("%s: ", g.gl_pathv[i] + 5); 5438729f5ecSAllan Jude e = 0; 5448729f5ecSAllan Jude if (estat == 0) { 5458729f5ecSAllan Jude if (status == 0) { 5468729f5ecSAllan Jude status = 1; 5478729f5ecSAllan Jude } 5488729f5ecSAllan Jude printf("OK"); 5498729f5ecSAllan Jude } else { 5508729f5ecSAllan Jude if (estat & SES_ENCSTAT_INFO) { 5518729f5ecSAllan Jude printf("INFO"); 5528729f5ecSAllan Jude e++; 5538729f5ecSAllan Jude } 5548729f5ecSAllan Jude if (estat & SES_ENCSTAT_NONCRITICAL) { 5558729f5ecSAllan Jude if (e) 5568729f5ecSAllan Jude printf(","); 5578729f5ecSAllan Jude printf("NONCRITICAL"); 5588729f5ecSAllan Jude e++; 5598729f5ecSAllan Jude } 5608729f5ecSAllan Jude if (estat & SES_ENCSTAT_CRITICAL) { 5618729f5ecSAllan Jude if (e) 5628729f5ecSAllan Jude printf(","); 5638729f5ecSAllan Jude printf("CRITICAL"); 5648729f5ecSAllan Jude e++; 5658729f5ecSAllan Jude status = -1; 5668729f5ecSAllan Jude } 5678729f5ecSAllan Jude if (estat & SES_ENCSTAT_UNRECOV) { 5688729f5ecSAllan Jude if (e) 5698729f5ecSAllan Jude printf(","); 5708729f5ecSAllan Jude printf("UNRECOV"); 5718729f5ecSAllan Jude e++; 5728729f5ecSAllan Jude status = -1; 5738729f5ecSAllan Jude } 5748729f5ecSAllan Jude } 5758729f5ecSAllan Jude printf("\n"); 5768729f5ecSAllan Jude 5778729f5ecSAllan Jude close(fd); 5788729f5ecSAllan Jude } 5798729f5ecSAllan Jude globfree(&g); 5808729f5ecSAllan Jude 5818729f5ecSAllan Jude if (status == 1) { 5828729f5ecSAllan Jude return (EXIT_SUCCESS); 5838729f5ecSAllan Jude } else { 5848729f5ecSAllan Jude return (EXIT_FAILURE); 5858729f5ecSAllan Jude } 586cddcb259SBaptiste Daroussin } 587cddcb259SBaptiste Daroussin 588cddcb259SBaptiste Daroussin int 589cddcb259SBaptiste Daroussin main(int argc, char **argv) 590cddcb259SBaptiste Daroussin { 5918729f5ecSAllan Jude int i, ch; 592cddcb259SBaptiste Daroussin struct command *cmd = NULL; 593cddcb259SBaptiste Daroussin 5948729f5ecSAllan Jude uflag = "/dev/ses[0-9]*"; 5958729f5ecSAllan Jude while ((ch = getopt_long(argc, argv, "u:", NULL, NULL)) != -1) { 5968729f5ecSAllan Jude switch (ch) { 5978729f5ecSAllan Jude case 'u': 5988729f5ecSAllan Jude uflag = optarg; 5998729f5ecSAllan Jude break; 6008729f5ecSAllan Jude case '?': 6018729f5ecSAllan Jude default: 6028729f5ecSAllan Jude usage(stderr, NULL); 6038729f5ecSAllan Jude } 6048729f5ecSAllan Jude } 6058729f5ecSAllan Jude argc -= optind; 6068729f5ecSAllan Jude argv += optind; 6078729f5ecSAllan Jude 6088729f5ecSAllan Jude if (argc < 1) { 609cddcb259SBaptiste Daroussin warnx("Missing command"); 6108729f5ecSAllan Jude usage(stderr, NULL); 611cddcb259SBaptiste Daroussin } 612cddcb259SBaptiste Daroussin 613cddcb259SBaptiste Daroussin for (i = 0; i < nbcmds; i++) { 6148729f5ecSAllan Jude if (strcmp(argv[0], cmds[i].name) == 0) { 615cddcb259SBaptiste Daroussin cmd = &cmds[i]; 616cddcb259SBaptiste Daroussin break; 617cddcb259SBaptiste Daroussin } 618cddcb259SBaptiste Daroussin } 619cddcb259SBaptiste Daroussin 620cddcb259SBaptiste Daroussin if (cmd == NULL) { 6218729f5ecSAllan Jude warnx("unknown command %s", argv[0]); 6228729f5ecSAllan Jude usage(stderr, NULL); 623cddcb259SBaptiste Daroussin } 624cddcb259SBaptiste Daroussin 625cddcb259SBaptiste Daroussin return (cmd->exec(argc, argv)); 626cddcb259SBaptiste Daroussin } 627