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 32cddcb259SBaptiste Daroussin #include <sys/param.h> 33cddcb259SBaptiste Daroussin #include <sys/ioctl.h> 34d7654478SBaptiste Daroussin #include <sys/types.h> 35d7654478SBaptiste Daroussin #include <sys/sbuf.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); 59cddcb259SBaptiste Daroussin 60cddcb259SBaptiste Daroussin static struct command { 61cddcb259SBaptiste Daroussin const char *name; 628729f5ecSAllan Jude const char *param; 63cddcb259SBaptiste Daroussin const char *desc; 64cddcb259SBaptiste Daroussin int (*exec)(int argc, char **argv); 65cddcb259SBaptiste Daroussin } cmds[] = { 668729f5ecSAllan Jude { "fault", 678729f5ecSAllan Jude "(<disk>|<sesid>|all) (on|off)", 688729f5ecSAllan Jude "Change the state of the fault LED associated with a disk", 698729f5ecSAllan Jude fault }, 708729f5ecSAllan Jude { "locate", 718729f5ecSAllan Jude "(<disk>|<sesid>|all) (on|off)", 728729f5ecSAllan Jude "Change the state of the locate LED associated with a disk", 738729f5ecSAllan Jude locate }, 748729f5ecSAllan Jude { "map", "", 758729f5ecSAllan Jude "Print a map of the devices managed by the enclosure", objmap } , 768729f5ecSAllan Jude { "status", "", "Print the status of the enclosure", 778729f5ecSAllan Jude encstatus }, 78cddcb259SBaptiste Daroussin }; 79cddcb259SBaptiste Daroussin 80cddcb259SBaptiste Daroussin static const int nbcmds = nitems(cmds); 818729f5ecSAllan Jude static const char *uflag; 82cddcb259SBaptiste Daroussin 83cddcb259SBaptiste Daroussin static void 848729f5ecSAllan Jude usage(FILE *out, const char *subcmd) 858729f5ecSAllan Jude { 868729f5ecSAllan Jude int i; 878729f5ecSAllan Jude 888729f5ecSAllan Jude if (subcmd == NULL) { 898729f5ecSAllan Jude fprintf(out, "Usage: %s [-u /dev/ses<N>] <command> [options]\n", 908729f5ecSAllan Jude getprogname()); 918729f5ecSAllan Jude fprintf(out, "Commands supported:\n"); 928729f5ecSAllan Jude } 938729f5ecSAllan Jude for (i = 0; i < nbcmds; i++) { 948729f5ecSAllan Jude if (subcmd != NULL) { 958729f5ecSAllan Jude if (strcmp(subcmd, cmds[i].name) == 0) { 968729f5ecSAllan Jude fprintf(out, "Usage: %s %s [-u /dev/ses<N>] " 978729f5ecSAllan Jude "%s\n\t%s\n", getprogname(), subcmd, 988729f5ecSAllan Jude cmds[i].param, cmds[i].desc); 998729f5ecSAllan Jude break; 1008729f5ecSAllan Jude } 1018729f5ecSAllan Jude continue; 1028729f5ecSAllan Jude } 1038729f5ecSAllan Jude fprintf(out, " %-12s%s\n\t\t%s\n\n", cmds[i].name, 1048729f5ecSAllan Jude cmds[i].param, cmds[i].desc); 1058729f5ecSAllan Jude } 1068729f5ecSAllan Jude 1078729f5ecSAllan Jude exit(EXIT_FAILURE); 1088729f5ecSAllan Jude } 1098729f5ecSAllan Jude 1108729f5ecSAllan Jude static void 1116af5d161SAllan Jude do_led(int fd, unsigned int idx, bool onoff, bool setfault) 112cddcb259SBaptiste Daroussin { 113cddcb259SBaptiste Daroussin encioc_elm_status_t o; 114cddcb259SBaptiste Daroussin 115cddcb259SBaptiste Daroussin o.elm_idx = idx; 116cddcb259SBaptiste Daroussin if (ioctl(fd, ENCIOC_GETELMSTAT, (caddr_t) &o) < 0) { 117cddcb259SBaptiste Daroussin close(fd); 118cddcb259SBaptiste Daroussin err(EXIT_FAILURE, "ENCIOC_GETELMSTAT"); 119cddcb259SBaptiste Daroussin } 120cddcb259SBaptiste Daroussin o.cstat[0] |= 0x80; 121*efab8bfdSAlexander Motin if (setfault) { 122*efab8bfdSAlexander Motin if (onoff) 123*efab8bfdSAlexander Motin o.cstat[3] |= 0x20; 124*efab8bfdSAlexander Motin else 125*efab8bfdSAlexander Motin o.cstat[3] &= 0xdf; 1268729f5ecSAllan Jude } else { 127*efab8bfdSAlexander Motin if (onoff) 128*efab8bfdSAlexander Motin o.cstat[2] |= 0x02; 129*efab8bfdSAlexander Motin else 130*efab8bfdSAlexander Motin o.cstat[2] &= 0xfd; 1318729f5ecSAllan Jude } 132cddcb259SBaptiste Daroussin 133cddcb259SBaptiste Daroussin if (ioctl(fd, ENCIOC_SETELMSTAT, (caddr_t) &o) < 0) { 134cddcb259SBaptiste Daroussin close(fd); 135cddcb259SBaptiste Daroussin err(EXIT_FAILURE, "ENCIOC_SETELMSTAT"); 136cddcb259SBaptiste Daroussin } 137cddcb259SBaptiste Daroussin } 138cddcb259SBaptiste Daroussin 139cddcb259SBaptiste Daroussin static bool 140cddcb259SBaptiste Daroussin disk_match(const char *devnames, const char *disk, size_t len) 141cddcb259SBaptiste Daroussin { 1421bc54324SBaptiste Daroussin const char *dname; 143cddcb259SBaptiste Daroussin 1441bc54324SBaptiste Daroussin dname = devnames; 1451bc54324SBaptiste Daroussin while ((dname = strstr(dname, disk)) != NULL) { 1468729f5ecSAllan Jude if (dname[len] == '\0' || dname[len] == ',') { 147cddcb259SBaptiste Daroussin return (true); 1488729f5ecSAllan Jude } 1491bc54324SBaptiste Daroussin dname++; 150cddcb259SBaptiste Daroussin } 1518729f5ecSAllan Jude 152cddcb259SBaptiste Daroussin return (false); 153cddcb259SBaptiste Daroussin } 154cddcb259SBaptiste Daroussin 155cddcb259SBaptiste Daroussin static int 1566af5d161SAllan Jude sesled(int argc, char **argv, bool setfault) 157cddcb259SBaptiste Daroussin { 158cddcb259SBaptiste Daroussin encioc_elm_devnames_t objdn; 159cddcb259SBaptiste Daroussin encioc_element_t *objp; 160cddcb259SBaptiste Daroussin glob_t g; 1618729f5ecSAllan Jude char *disk, *endptr; 1628729f5ecSAllan Jude size_t len, i, ndisks; 1638729f5ecSAllan Jude int fd; 1648729f5ecSAllan Jude unsigned int nobj, j, sesid; 1658729f5ecSAllan Jude bool all, isses, onoff; 166cddcb259SBaptiste Daroussin 1678729f5ecSAllan Jude isses = false; 1688729f5ecSAllan Jude all = false; 1698729f5ecSAllan Jude onoff = false; 1708729f5ecSAllan Jude 1718729f5ecSAllan Jude if (argc != 3) { 1726af5d161SAllan Jude usage(stderr, (setfault ? "fault" : "locate")); 173cddcb259SBaptiste Daroussin } 174cddcb259SBaptiste Daroussin 1758729f5ecSAllan Jude disk = argv[1]; 176cddcb259SBaptiste Daroussin 1778729f5ecSAllan Jude sesid = strtoul(disk, &endptr, 10); 1788729f5ecSAllan Jude if (*endptr == '\0') { 1798729f5ecSAllan Jude endptr = strrchr(uflag, '*'); 18096e6c444SBaptiste Daroussin if (endptr != NULL && *endptr == '*') { 1818729f5ecSAllan Jude warnx("Must specifying a SES device (-u) to use a SES " 1828729f5ecSAllan Jude "id# to identify a disk"); 1836af5d161SAllan Jude usage(stderr, (setfault ? "fault" : "locate")); 1848729f5ecSAllan Jude } 1858729f5ecSAllan Jude isses = true; 1868729f5ecSAllan Jude } 1878729f5ecSAllan Jude 1888729f5ecSAllan Jude if (strcmp(argv[2], "on") == 0) { 1894569e7cfSBaptiste Daroussin onoff = true; 1908729f5ecSAllan Jude } else if (strcmp(argv[2], "off") == 0) { 1914569e7cfSBaptiste Daroussin onoff = false; 192cddcb259SBaptiste Daroussin } else { 1936af5d161SAllan Jude usage(stderr, (setfault ? "fault" : "locate")); 194cddcb259SBaptiste Daroussin } 195cddcb259SBaptiste Daroussin 196cddcb259SBaptiste Daroussin if (strcmp(disk, "all") == 0) { 197cddcb259SBaptiste Daroussin all = true; 198cddcb259SBaptiste Daroussin } 199cddcb259SBaptiste Daroussin len = strlen(disk); 200cddcb259SBaptiste Daroussin 201cddcb259SBaptiste Daroussin /* Get the list of ses devices */ 2028729f5ecSAllan Jude if (glob((uflag != NULL ? uflag : "/dev/ses[0-9]*"), 0, NULL, &g) == 2038729f5ecSAllan Jude GLOB_NOMATCH) { 2048729f5ecSAllan Jude globfree(&g); 2058729f5ecSAllan Jude errx(EXIT_FAILURE, "No SES devices found"); 2068729f5ecSAllan Jude } 2078729f5ecSAllan Jude 2088729f5ecSAllan Jude ndisks = 0; 2098729f5ecSAllan Jude for (i = 0; i < g.gl_pathc; i++) { 2108729f5ecSAllan Jude /* ensure we only got numbers after ses */ 2118729f5ecSAllan Jude if (strspn(g.gl_pathv[i] + 8, "0123456789") != 2128729f5ecSAllan Jude strlen(g.gl_pathv[i] + 8)) { 2138729f5ecSAllan Jude continue; 2148729f5ecSAllan Jude } 2158729f5ecSAllan Jude if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) { 2168729f5ecSAllan Jude /* 2178729f5ecSAllan Jude * Don't treat non-access errors as critical if we are 2188729f5ecSAllan Jude * accessing all devices 2198729f5ecSAllan Jude */ 2208729f5ecSAllan Jude if (errno == EACCES && g.gl_pathc > 1) { 2218729f5ecSAllan Jude err(EXIT_FAILURE, "unable to access SES device"); 2228729f5ecSAllan Jude } 2238729f5ecSAllan Jude warn("unable to access SES device: %s", g.gl_pathv[i]); 2248729f5ecSAllan Jude continue; 2258729f5ecSAllan Jude } 2268729f5ecSAllan Jude 2278729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj) < 0) { 2288729f5ecSAllan Jude close(fd); 2298729f5ecSAllan Jude err(EXIT_FAILURE, "ENCIOC_GETNELM"); 2308729f5ecSAllan Jude } 2318729f5ecSAllan Jude 2328729f5ecSAllan Jude objp = calloc(nobj, sizeof(encioc_element_t)); 2338729f5ecSAllan Jude if (objp == NULL) { 2348729f5ecSAllan Jude close(fd); 2358729f5ecSAllan Jude err(EXIT_FAILURE, "calloc()"); 2368729f5ecSAllan Jude } 2378729f5ecSAllan Jude 2388729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETELMMAP, (caddr_t) objp) < 0) { 2398729f5ecSAllan Jude close(fd); 2408729f5ecSAllan Jude err(EXIT_FAILURE, "ENCIOC_GETELMMAP"); 2418729f5ecSAllan Jude } 2428729f5ecSAllan Jude 2438729f5ecSAllan Jude if (isses) { 2448729f5ecSAllan Jude if (sesid > nobj) { 2458729f5ecSAllan Jude close(fd); 2468729f5ecSAllan Jude errx(EXIT_FAILURE, 2478729f5ecSAllan Jude "Requested SES ID does not exist"); 2488729f5ecSAllan Jude } 2496af5d161SAllan Jude do_led(fd, sesid, onoff, setfault); 2508729f5ecSAllan Jude ndisks++; 2518729f5ecSAllan Jude close(fd); 2528729f5ecSAllan Jude break; 2538729f5ecSAllan Jude } 2548729f5ecSAllan Jude for (j = 0; j < nobj; j++) { 2558729f5ecSAllan Jude memset(&objdn, 0, sizeof(objdn)); 2568729f5ecSAllan Jude objdn.elm_idx = objp[j].elm_idx; 2578729f5ecSAllan Jude objdn.elm_names_size = 128; 2588729f5ecSAllan Jude objdn.elm_devnames = calloc(128, sizeof(char)); 2598729f5ecSAllan Jude if (objdn.elm_devnames == NULL) { 2608729f5ecSAllan Jude close(fd); 2618729f5ecSAllan Jude err(EXIT_FAILURE, "calloc()"); 2628729f5ecSAllan Jude } 2638729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETELMDEVNAMES, 2648729f5ecSAllan Jude (caddr_t) &objdn) <0) { 2658729f5ecSAllan Jude continue; 2668729f5ecSAllan Jude } 2678729f5ecSAllan Jude if (objdn.elm_names_len > 0) { 2688729f5ecSAllan Jude if (all) { 2698729f5ecSAllan Jude do_led(fd, objdn.elm_idx, 2706af5d161SAllan Jude onoff, setfault); 2718729f5ecSAllan Jude continue; 2728729f5ecSAllan Jude } 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 3078729f5ecSAllan Jude static int 3088729f5ecSAllan Jude objmap(int argc, char **argv __unused) 3098729f5ecSAllan Jude { 310d7654478SBaptiste Daroussin struct sbuf *extra; 31160f46640SBaptiste Daroussin encioc_string_t stri; 3128729f5ecSAllan Jude encioc_elm_devnames_t e_devname; 3138729f5ecSAllan Jude encioc_elm_status_t e_status; 3148729f5ecSAllan Jude encioc_elm_desc_t e_desc; 3158729f5ecSAllan Jude encioc_element_t *e_ptr; 3168729f5ecSAllan Jude glob_t g; 3178729f5ecSAllan Jude int fd; 3188729f5ecSAllan Jude unsigned int j, nobj; 3198729f5ecSAllan Jude size_t i; 32060f46640SBaptiste Daroussin char str[32]; 3218729f5ecSAllan Jude 3228729f5ecSAllan Jude if (argc != 1) { 3238729f5ecSAllan Jude usage(stderr, "map"); 3248729f5ecSAllan Jude } 3258729f5ecSAllan Jude 3268729f5ecSAllan Jude /* Get the list of ses devices */ 3278729f5ecSAllan Jude if (glob(uflag, 0, NULL, &g) == GLOB_NOMATCH) { 328cddcb259SBaptiste Daroussin globfree(&g); 329cddcb259SBaptiste Daroussin errx(EXIT_FAILURE, "No SES devices found"); 330cddcb259SBaptiste Daroussin } 331cddcb259SBaptiste Daroussin for (i = 0; i < g.gl_pathc; i++) { 332cddcb259SBaptiste Daroussin /* ensure we only got numbers after ses */ 333cddcb259SBaptiste Daroussin if (strspn(g.gl_pathv[i] + 8, "0123456789") != 3348729f5ecSAllan Jude strlen(g.gl_pathv[i] + 8)) { 335cddcb259SBaptiste Daroussin continue; 3368729f5ecSAllan Jude } 337cddcb259SBaptiste Daroussin if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) { 3388729f5ecSAllan Jude /* 3398729f5ecSAllan Jude * Don't treat non-access errors as critical if we are 3408729f5ecSAllan Jude * accessing all devices 3418729f5ecSAllan Jude */ 3428729f5ecSAllan Jude if (errno == EACCES && g.gl_pathc > 1) { 3438729f5ecSAllan Jude err(EXIT_FAILURE, "unable to access SES device"); 3448729f5ecSAllan Jude } 3458729f5ecSAllan Jude warn("unable to access SES device: %s", g.gl_pathv[i]); 3468729f5ecSAllan Jude continue; 347cddcb259SBaptiste Daroussin } 348cddcb259SBaptiste Daroussin 3498729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj) < 0) { 3508729f5ecSAllan Jude close(fd); 351cddcb259SBaptiste Daroussin err(EXIT_FAILURE, "ENCIOC_GETNELM"); 3528729f5ecSAllan Jude } 353cddcb259SBaptiste Daroussin 3548729f5ecSAllan Jude e_ptr = calloc(nobj, sizeof(encioc_element_t)); 3558729f5ecSAllan Jude if (e_ptr == NULL) { 3568729f5ecSAllan Jude close(fd); 357cddcb259SBaptiste Daroussin err(EXIT_FAILURE, "calloc()"); 3588729f5ecSAllan Jude } 359cddcb259SBaptiste Daroussin 3608729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETELMMAP, (caddr_t) e_ptr) < 0) { 3618729f5ecSAllan Jude close(fd); 362cddcb259SBaptiste Daroussin err(EXIT_FAILURE, "ENCIOC_GETELMMAP"); 3638729f5ecSAllan Jude } 364cddcb259SBaptiste Daroussin 3658729f5ecSAllan Jude printf("%s:\n", g.gl_pathv[i] + 5); 36660f46640SBaptiste Daroussin stri.bufsiz = sizeof(str); 36760f46640SBaptiste Daroussin stri.buf = &str[0]; 36860f46640SBaptiste Daroussin if (ioctl(fd, ENCIOC_GETENCNAME, (caddr_t) &stri) == 0) 36960f46640SBaptiste Daroussin printf("\tEnclosure Name: %s\n", stri.buf); 37060f46640SBaptiste Daroussin stri.bufsiz = sizeof(str); 37160f46640SBaptiste Daroussin stri.buf = &str[0]; 37260f46640SBaptiste Daroussin if (ioctl(fd, ENCIOC_GETENCID, (caddr_t) &stri) == 0) 37360f46640SBaptiste Daroussin printf("\tEnclosure ID: %s\n", stri.buf); 37460f46640SBaptiste Daroussin 375cddcb259SBaptiste Daroussin for (j = 0; j < nobj; j++) { 3768729f5ecSAllan Jude /* Get the status of the element */ 3778729f5ecSAllan Jude memset(&e_status, 0, sizeof(e_status)); 3788729f5ecSAllan Jude e_status.elm_idx = e_ptr[j].elm_idx; 3798729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETELMSTAT, 3808729f5ecSAllan Jude (caddr_t) &e_status) < 0) { 3818729f5ecSAllan Jude close(fd); 3828729f5ecSAllan Jude err(EXIT_FAILURE, "ENCIOC_GETELMSTAT"); 3838729f5ecSAllan Jude } 3848729f5ecSAllan Jude /* Get the description of the element */ 3858729f5ecSAllan Jude memset(&e_desc, 0, sizeof(e_desc)); 3868729f5ecSAllan Jude e_desc.elm_idx = e_ptr[j].elm_idx; 3878729f5ecSAllan Jude e_desc.elm_desc_len = UINT16_MAX; 3888729f5ecSAllan Jude e_desc.elm_desc_str = calloc(UINT16_MAX, sizeof(char)); 3898729f5ecSAllan Jude if (e_desc.elm_desc_str == NULL) { 3908729f5ecSAllan Jude close(fd); 391cddcb259SBaptiste Daroussin err(EXIT_FAILURE, "calloc()"); 3928729f5ecSAllan Jude } 3938729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETELMDESC, 3948729f5ecSAllan Jude (caddr_t) &e_desc) < 0) { 3958729f5ecSAllan Jude close(fd); 3968729f5ecSAllan Jude err(EXIT_FAILURE, "ENCIOC_GETELMDESC"); 3978729f5ecSAllan Jude } 3988729f5ecSAllan Jude /* Get the device name(s) of the element */ 3998729f5ecSAllan Jude memset(&e_devname, 0, sizeof(e_devname)); 4008729f5ecSAllan Jude e_devname.elm_idx = e_ptr[j].elm_idx; 4018729f5ecSAllan Jude e_devname.elm_names_size = 128; 4028729f5ecSAllan Jude e_devname.elm_devnames = calloc(128, sizeof(char)); 4038729f5ecSAllan Jude if (e_devname.elm_devnames == NULL) { 4048729f5ecSAllan Jude close(fd); 4058729f5ecSAllan Jude err(EXIT_FAILURE, "calloc()"); 4068729f5ecSAllan Jude } 407cddcb259SBaptiste Daroussin if (ioctl(fd, ENCIOC_GETELMDEVNAMES, 4088729f5ecSAllan Jude (caddr_t) &e_devname) <0) { 4098729f5ecSAllan Jude /* We don't care if this fails */ 4108729f5ecSAllan Jude e_devname.elm_devnames[0] = '\0'; 411cddcb259SBaptiste Daroussin } 4128729f5ecSAllan Jude printf("\tElement %u, Type: %s\n", e_ptr[j].elm_idx, 4138729f5ecSAllan Jude geteltnm(e_ptr[j].elm_type)); 414d7654478SBaptiste Daroussin printf("\t\tStatus: %s (0x%02x 0x%02x 0x%02x 0x%02x)\n", 415d7654478SBaptiste Daroussin scode2ascii(e_status.cstat[0]), e_status.cstat[0], 416d7654478SBaptiste Daroussin e_status.cstat[1], e_status.cstat[2], 417d7654478SBaptiste Daroussin e_status.cstat[3]); 4188729f5ecSAllan Jude if (e_desc.elm_desc_len > 0) { 4198729f5ecSAllan Jude printf("\t\tDescription: %s\n", 4208729f5ecSAllan Jude e_desc.elm_desc_str); 421cddcb259SBaptiste Daroussin } 4228729f5ecSAllan Jude if (e_devname.elm_names_len > 0) { 4238729f5ecSAllan Jude printf("\t\tDevice Names: %s\n", 4248729f5ecSAllan Jude e_devname.elm_devnames); 425cddcb259SBaptiste Daroussin } 426d7654478SBaptiste Daroussin extra = stat2sbuf(e_ptr[j].elm_type, e_status.cstat); 427d7654478SBaptiste Daroussin if (sbuf_len(extra) > 0) { 428d7654478SBaptiste Daroussin printf("\t\tExtra status:\n%s", 429d7654478SBaptiste Daroussin sbuf_data(extra)); 430d7654478SBaptiste Daroussin } 431d7654478SBaptiste Daroussin sbuf_delete(extra); 4328729f5ecSAllan Jude free(e_devname.elm_devnames); 433cddcb259SBaptiste Daroussin } 434f734685eSBaptiste Daroussin free(e_ptr); 435cddcb259SBaptiste Daroussin close(fd); 436cddcb259SBaptiste Daroussin } 437cddcb259SBaptiste Daroussin globfree(&g); 438cddcb259SBaptiste Daroussin 439cddcb259SBaptiste Daroussin return (EXIT_SUCCESS); 440cddcb259SBaptiste Daroussin } 441cddcb259SBaptiste Daroussin 4428729f5ecSAllan Jude static int 4438729f5ecSAllan Jude encstatus(int argc, char **argv __unused) 444cddcb259SBaptiste Daroussin { 4458729f5ecSAllan Jude glob_t g; 4468729f5ecSAllan Jude int fd, status; 4478729f5ecSAllan Jude size_t i, e; 4488729f5ecSAllan Jude u_char estat; 449cddcb259SBaptiste Daroussin 4508729f5ecSAllan Jude status = 0; 4518729f5ecSAllan Jude if (argc != 1) { 4528729f5ecSAllan Jude usage(stderr, "status"); 4538729f5ecSAllan Jude } 4548729f5ecSAllan Jude 4558729f5ecSAllan Jude /* Get the list of ses devices */ 4568729f5ecSAllan Jude if (glob(uflag, 0, NULL, &g) == GLOB_NOMATCH) { 4578729f5ecSAllan Jude globfree(&g); 4588729f5ecSAllan Jude errx(EXIT_FAILURE, "No SES devices found"); 4598729f5ecSAllan Jude } 4608729f5ecSAllan Jude for (i = 0; i < g.gl_pathc; i++) { 4618729f5ecSAllan Jude /* ensure we only got numbers after ses */ 4628729f5ecSAllan Jude if (strspn(g.gl_pathv[i] + 8, "0123456789") != 4638729f5ecSAllan Jude strlen(g.gl_pathv[i] + 8)) { 4648729f5ecSAllan Jude continue; 4658729f5ecSAllan Jude } 4668729f5ecSAllan Jude if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) { 4678729f5ecSAllan Jude /* 4688729f5ecSAllan Jude * Don't treat non-access errors as critical if we are 4698729f5ecSAllan Jude * accessing all devices 4708729f5ecSAllan Jude */ 4718729f5ecSAllan Jude if (errno == EACCES && g.gl_pathc > 1) { 4728729f5ecSAllan Jude err(EXIT_FAILURE, "unable to access SES device"); 4738729f5ecSAllan Jude } 4748729f5ecSAllan Jude warn("unable to access SES device: %s", g.gl_pathv[i]); 4758729f5ecSAllan Jude continue; 4768729f5ecSAllan Jude } 4778729f5ecSAllan Jude 4788729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETENCSTAT, (caddr_t) &estat) < 0) { 4798729f5ecSAllan Jude close(fd); 4808729f5ecSAllan Jude err(EXIT_FAILURE, "ENCIOC_GETENCSTAT"); 4818729f5ecSAllan Jude } 4828729f5ecSAllan Jude 4838729f5ecSAllan Jude printf("%s: ", g.gl_pathv[i] + 5); 4848729f5ecSAllan Jude e = 0; 4858729f5ecSAllan Jude if (estat == 0) { 4868729f5ecSAllan Jude if (status == 0) { 4878729f5ecSAllan Jude status = 1; 4888729f5ecSAllan Jude } 4898729f5ecSAllan Jude printf("OK"); 4908729f5ecSAllan Jude } else { 4918729f5ecSAllan Jude if (estat & SES_ENCSTAT_INFO) { 4928729f5ecSAllan Jude printf("INFO"); 4938729f5ecSAllan Jude e++; 4948729f5ecSAllan Jude } 4958729f5ecSAllan Jude if (estat & SES_ENCSTAT_NONCRITICAL) { 4968729f5ecSAllan Jude if (e) 4978729f5ecSAllan Jude printf(","); 4988729f5ecSAllan Jude printf("NONCRITICAL"); 4998729f5ecSAllan Jude e++; 5008729f5ecSAllan Jude } 5018729f5ecSAllan Jude if (estat & SES_ENCSTAT_CRITICAL) { 5028729f5ecSAllan Jude if (e) 5038729f5ecSAllan Jude printf(","); 5048729f5ecSAllan Jude printf("CRITICAL"); 5058729f5ecSAllan Jude e++; 5068729f5ecSAllan Jude status = -1; 5078729f5ecSAllan Jude } 5088729f5ecSAllan Jude if (estat & SES_ENCSTAT_UNRECOV) { 5098729f5ecSAllan Jude if (e) 5108729f5ecSAllan Jude printf(","); 5118729f5ecSAllan Jude printf("UNRECOV"); 5128729f5ecSAllan Jude e++; 5138729f5ecSAllan Jude status = -1; 5148729f5ecSAllan Jude } 5158729f5ecSAllan Jude } 5168729f5ecSAllan Jude printf("\n"); 5178729f5ecSAllan Jude 5188729f5ecSAllan Jude close(fd); 5198729f5ecSAllan Jude } 5208729f5ecSAllan Jude globfree(&g); 5218729f5ecSAllan Jude 5228729f5ecSAllan Jude if (status == 1) { 5238729f5ecSAllan Jude return (EXIT_SUCCESS); 5248729f5ecSAllan Jude } else { 5258729f5ecSAllan Jude return (EXIT_FAILURE); 5268729f5ecSAllan Jude } 527cddcb259SBaptiste Daroussin } 528cddcb259SBaptiste Daroussin 529cddcb259SBaptiste Daroussin int 530cddcb259SBaptiste Daroussin main(int argc, char **argv) 531cddcb259SBaptiste Daroussin { 5328729f5ecSAllan Jude int i, ch; 533cddcb259SBaptiste Daroussin struct command *cmd = NULL; 534cddcb259SBaptiste Daroussin 5358729f5ecSAllan Jude uflag = "/dev/ses[0-9]*"; 5368729f5ecSAllan Jude while ((ch = getopt_long(argc, argv, "u:", NULL, NULL)) != -1) { 5378729f5ecSAllan Jude switch (ch) { 5388729f5ecSAllan Jude case 'u': 5398729f5ecSAllan Jude uflag = optarg; 5408729f5ecSAllan Jude break; 5418729f5ecSAllan Jude case '?': 5428729f5ecSAllan Jude default: 5438729f5ecSAllan Jude usage(stderr, NULL); 5448729f5ecSAllan Jude } 5458729f5ecSAllan Jude } 5468729f5ecSAllan Jude argc -= optind; 5478729f5ecSAllan Jude argv += optind; 5488729f5ecSAllan Jude 5498729f5ecSAllan Jude if (argc < 1) { 550cddcb259SBaptiste Daroussin warnx("Missing command"); 5518729f5ecSAllan Jude usage(stderr, NULL); 552cddcb259SBaptiste Daroussin } 553cddcb259SBaptiste Daroussin 554cddcb259SBaptiste Daroussin for (i = 0; i < nbcmds; i++) { 5558729f5ecSAllan Jude if (strcmp(argv[0], cmds[i].name) == 0) { 556cddcb259SBaptiste Daroussin cmd = &cmds[i]; 557cddcb259SBaptiste Daroussin break; 558cddcb259SBaptiste Daroussin } 559cddcb259SBaptiste Daroussin } 560cddcb259SBaptiste Daroussin 561cddcb259SBaptiste Daroussin if (cmd == NULL) { 5628729f5ecSAllan Jude warnx("unknown command %s", argv[0]); 5638729f5ecSAllan Jude usage(stderr, NULL); 564cddcb259SBaptiste Daroussin } 565cddcb259SBaptiste Daroussin 566cddcb259SBaptiste Daroussin return (cmd->exec(argc, argv)); 567cddcb259SBaptiste Daroussin } 568