xref: /freebsd/usr.sbin/sesutil/sesutil.c (revision 20a957e37a425ba76a8fef60cc6c0d066de3d3f7)
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