Home | History | Annotate | Line # | Download | only in bioctl
bioctl.c revision 1.3
      1  1.3  xtraeme /* $NetBSD: bioctl.c,v 1.3 2007/12/05 13:26:04 xtraeme Exp $ */
      2  1.1   bouyer /* $OpenBSD: bioctl.c,v 1.52 2007/03/20 15:26:06 jmc Exp $       */
      3  1.1   bouyer 
      4  1.1   bouyer /*
      5  1.1   bouyer  * Copyright (c) 2004, 2005 Marco Peereboom
      6  1.1   bouyer  * All rights reserved.
      7  1.1   bouyer  *
      8  1.1   bouyer  * Redistribution and use in source and binary forms, with or without
      9  1.1   bouyer  * modification, are permitted provided that the following conditions
     10  1.1   bouyer  * are met:
     11  1.1   bouyer  * 1. Redistributions of source code must retain the above copyright
     12  1.1   bouyer  *    notice, this list of conditions and the following disclaimer.
     13  1.1   bouyer  * 2. Redistributions in binary form must reproduce the above copyright
     14  1.1   bouyer  *    notice, this list of conditions and the following disclaimer in the
     15  1.1   bouyer  *    documentation and/or other materials provided with the distribution.
     16  1.1   bouyer  *
     17  1.1   bouyer  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
     18  1.1   bouyer  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     19  1.1   bouyer  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     20  1.1   bouyer  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
     21  1.1   bouyer  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     22  1.1   bouyer  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     23  1.1   bouyer  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     24  1.1   bouyer  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     25  1.1   bouyer  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     26  1.1   bouyer  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     27  1.1   bouyer  * SUCH DAMAGE.
     28  1.1   bouyer  *
     29  1.1   bouyer  */
     30  1.1   bouyer #include <sys/cdefs.h>
     31  1.1   bouyer 
     32  1.1   bouyer #ifndef lint
     33  1.3  xtraeme __RCSID("$NetBSD: bioctl.c,v 1.3 2007/12/05 13:26:04 xtraeme Exp $");
     34  1.1   bouyer #endif
     35  1.1   bouyer 
     36  1.1   bouyer #include <sys/ioctl.h>
     37  1.1   bouyer #include <sys/param.h>
     38  1.1   bouyer #include <sys/queue.h>
     39  1.1   bouyer #include <dev/biovar.h>
     40  1.1   bouyer 
     41  1.1   bouyer #include <errno.h>
     42  1.1   bouyer #include <err.h>
     43  1.1   bouyer #include <fcntl.h>
     44  1.1   bouyer #include <util.h>
     45  1.1   bouyer #include <stdio.h>
     46  1.1   bouyer #include <stdlib.h>
     47  1.1   bouyer #include <string.h>
     48  1.1   bouyer #include <unistd.h>
     49  1.1   bouyer #include <ctype.h>
     50  1.1   bouyer #include <util.h>
     51  1.1   bouyer #include "strtonum.h"
     52  1.1   bouyer 
     53  1.1   bouyer struct locator {
     54  1.1   bouyer 	int channel;
     55  1.1   bouyer 	int target;
     56  1.1   bouyer 	int lun;
     57  1.1   bouyer };
     58  1.1   bouyer 
     59  1.2  xtraeme static void usage(void);
     60  1.2  xtraeme static const char *str2locator(const char *, struct locator *);
     61  1.1   bouyer 
     62  1.2  xtraeme static void bio_inq(int, char *);
     63  1.2  xtraeme static void bio_alarm(int, char *);
     64  1.2  xtraeme static void bio_setstate(int, char *);
     65  1.2  xtraeme static void bio_setblink(int, char *, char *, int);
     66  1.2  xtraeme static void bio_blink(int, char *, int, int);
     67  1.2  xtraeme 
     68  1.2  xtraeme static int debug;
     69  1.2  xtraeme static int human;
     70  1.2  xtraeme static int verbose;
     71  1.2  xtraeme 
     72  1.2  xtraeme static struct bio_locate bl;
     73  1.1   bouyer 
     74  1.1   bouyer int
     75  1.1   bouyer main(int argc, char *argv[])
     76  1.1   bouyer {
     77  1.2  xtraeme 	uint64_t func = 0;
     78  1.2  xtraeme 	char *bioc_dev, *al_arg, *bl_arg;
     79  1.2  xtraeme 	int fd, ch, rv, blink;
     80  1.2  xtraeme 
     81  1.2  xtraeme 	bioc_dev = al_arg = bl_arg = NULL;
     82  1.2  xtraeme 	fd = ch = rv = blink = 0;
     83  1.1   bouyer 
     84  1.1   bouyer 	if (argc < 2)
     85  1.1   bouyer 		usage();
     86  1.1   bouyer 
     87  1.2  xtraeme 	setprogname(*argv);
     88  1.2  xtraeme 
     89  1.2  xtraeme 	while ((ch = getopt(argc, argv, "b:c:l:u:H:ha:Dv")) != -1) {
     90  1.1   bouyer 		switch (ch) {
     91  1.1   bouyer 		case 'a': /* alarm */
     92  1.1   bouyer 			func |= BIOC_ALARM;
     93  1.1   bouyer 			al_arg = optarg;
     94  1.1   bouyer 			break;
     95  1.1   bouyer 		case 'b': /* blink */
     96  1.1   bouyer 			func |= BIOC_BLINK;
     97  1.1   bouyer 			blink = BIOC_SBBLINK;
     98  1.1   bouyer 			bl_arg = optarg;
     99  1.1   bouyer 			break;
    100  1.1   bouyer 		case 'u': /* unblink */
    101  1.1   bouyer 			func |= BIOC_BLINK;
    102  1.1   bouyer 			blink = BIOC_SBUNBLINK;
    103  1.1   bouyer 			bl_arg = optarg;
    104  1.1   bouyer 			break;
    105  1.1   bouyer 		case 'D': /* debug */
    106  1.1   bouyer 			debug = 1;
    107  1.1   bouyer 			break;
    108  1.1   bouyer 		case 'H': /* set hotspare */
    109  1.1   bouyer 			func |= BIOC_SETSTATE;
    110  1.1   bouyer 			al_arg = optarg;
    111  1.1   bouyer 			break;
    112  1.1   bouyer 		case 'h':
    113  1.1   bouyer 			human = 1;
    114  1.1   bouyer 			break;
    115  1.1   bouyer 		case 'i': /* inquiry */
    116  1.1   bouyer 			func |= BIOC_INQ;
    117  1.1   bouyer 			break;
    118  1.1   bouyer 		case 'v':
    119  1.1   bouyer 			verbose = 1;
    120  1.1   bouyer 			break;
    121  1.1   bouyer 		default:
    122  1.1   bouyer 			usage();
    123  1.1   bouyer 			/* NOTREACHED */
    124  1.1   bouyer 		}
    125  1.1   bouyer 	}
    126  1.1   bouyer 	argc -= optind;
    127  1.1   bouyer 	argv += optind;
    128  1.1   bouyer 
    129  1.1   bouyer 	if (argc != 1)
    130  1.1   bouyer 		usage();
    131  1.1   bouyer 
    132  1.1   bouyer 	if (func == 0)
    133  1.1   bouyer 		func |= BIOC_INQ;
    134  1.2  xtraeme 
    135  1.2  xtraeme 	bioc_dev = argv[0];
    136  1.1   bouyer 
    137  1.1   bouyer 	if (bioc_dev) {
    138  1.2  xtraeme 		fd = open("/dev/bio", O_RDWR);
    139  1.2  xtraeme 		if (fd == -1)
    140  1.2  xtraeme 			err(EXIT_FAILURE, "Can't open %s", "/dev/bio");
    141  1.1   bouyer 
    142  1.1   bouyer 		bl.bl_name = bioc_dev;
    143  1.2  xtraeme 		rv = ioctl(fd, BIOCLOCATE, &bl);
    144  1.1   bouyer 		if (rv == -1)
    145  1.2  xtraeme 			errx(EXIT_FAILURE, "Can't locate %s device via %s",
    146  1.1   bouyer 			    bl.bl_name, "/dev/bio");
    147  1.1   bouyer 	}
    148  1.1   bouyer 
    149  1.1   bouyer 	if (debug)
    150  1.1   bouyer 		warnx("cookie = %p", bl.bl_cookie);
    151  1.1   bouyer 
    152  1.1   bouyer 	if (func & BIOC_INQ) {
    153  1.2  xtraeme 		bio_inq(fd, bioc_dev);
    154  1.1   bouyer 	} else if (func == BIOC_ALARM) {
    155  1.2  xtraeme 		bio_alarm(fd, al_arg);
    156  1.1   bouyer 	} else if (func == BIOC_BLINK) {
    157  1.2  xtraeme 		bio_setblink(fd, bioc_dev, bl_arg, blink);
    158  1.1   bouyer 	} else if (func == BIOC_SETSTATE) {
    159  1.2  xtraeme 		bio_setstate(fd, al_arg);
    160  1.1   bouyer 	}
    161  1.1   bouyer 
    162  1.2  xtraeme 	exit(EXIT_SUCCESS);
    163  1.1   bouyer }
    164  1.1   bouyer 
    165  1.2  xtraeme static void
    166  1.1   bouyer usage(void)
    167  1.1   bouyer {
    168  1.2  xtraeme 	(void)fprintf(stderr,
    169  1.2  xtraeme 		"usage: %s [-Dhv] [-a alarm-function] "
    170  1.1   bouyer 		"[-b channel:target[.lun]]\n"
    171  1.2  xtraeme 		"\t[-H channel:target[.lun]]\n"
    172  1.2  xtraeme 		"\t[-u channel:target[.lun]] device\n", getprogname());
    173  1.2  xtraeme 	exit(EXIT_FAILURE);
    174  1.2  xtraeme 	/* NOTREACHED */
    175  1.1   bouyer }
    176  1.1   bouyer 
    177  1.2  xtraeme static const char *
    178  1.1   bouyer str2locator(const char *string, struct locator *location)
    179  1.1   bouyer {
    180  1.1   bouyer 	const char *errstr;
    181  1.1   bouyer 	char parse[80], *targ, *lun;
    182  1.1   bouyer 
    183  1.1   bouyer 	strlcpy(parse, string, sizeof parse);
    184  1.1   bouyer 	targ = strchr(parse, ':');
    185  1.1   bouyer 	if (targ == NULL)
    186  1.1   bouyer 		return ("target not specified");
    187  1.1   bouyer 	*targ++ = '\0';
    188  1.1   bouyer 
    189  1.1   bouyer 	lun = strchr(targ, '.');
    190  1.1   bouyer 	if (lun != NULL) {
    191  1.1   bouyer 		*lun++ = '\0';
    192  1.1   bouyer 		location->lun = strtonum(lun, 0, 256, &errstr);
    193  1.1   bouyer 		if (errstr)
    194  1.2  xtraeme 			return errstr;
    195  1.1   bouyer 	} else
    196  1.1   bouyer 		location->lun = 0;
    197  1.1   bouyer 
    198  1.1   bouyer 	location->target = strtonum(targ, 0, 256, &errstr);
    199  1.1   bouyer 	if (errstr)
    200  1.2  xtraeme 		return errstr;
    201  1.1   bouyer 	location->channel = strtonum(parse, 0, 256, &errstr);
    202  1.1   bouyer 	if (errstr)
    203  1.2  xtraeme 		return errstr;
    204  1.2  xtraeme 	return NULL;
    205  1.1   bouyer }
    206  1.1   bouyer 
    207  1.2  xtraeme static void
    208  1.2  xtraeme bio_inq(int fd, char *name)
    209  1.1   bouyer {
    210  1.1   bouyer 	const char *status;
    211  1.1   bouyer 	char size[64], scsiname[16], volname[32];
    212  1.1   bouyer 	char percent[10], seconds[20];
    213  1.1   bouyer 	int rv, i, d, volheader, hotspare, unused;
    214  1.1   bouyer 	char encname[16], serial[32];
    215  1.1   bouyer 	struct bioc_disk bd;
    216  1.1   bouyer 	struct bioc_inq bi;
    217  1.1   bouyer 	struct bioc_vol bv;
    218  1.1   bouyer 
    219  1.1   bouyer 	memset(&bi, 0, sizeof(bi));
    220  1.1   bouyer 
    221  1.1   bouyer 	if (debug)
    222  1.1   bouyer 		printf("bio_inq\n");
    223  1.1   bouyer 
    224  1.1   bouyer 	bi.bi_cookie = bl.bl_cookie;
    225  1.1   bouyer 
    226  1.2  xtraeme 	rv = ioctl(fd, BIOCINQ, &bi);
    227  1.1   bouyer 	if (rv == -1) {
    228  1.1   bouyer 		warn("BIOCINQ");
    229  1.1   bouyer 		return;
    230  1.1   bouyer 	}
    231  1.1   bouyer 
    232  1.1   bouyer 	if (debug)
    233  1.1   bouyer 		printf("bio_inq { %p, %s, %d, %d }\n",
    234  1.1   bouyer 		    bi.bi_cookie,
    235  1.1   bouyer 		    bi.bi_dev,
    236  1.1   bouyer 		    bi.bi_novol,
    237  1.1   bouyer 		    bi.bi_nodisk);
    238  1.1   bouyer 
    239  1.1   bouyer 	volheader = 0;
    240  1.1   bouyer 	for (i = 0; i < bi.bi_novol; i++) {
    241  1.1   bouyer 		memset(&bv, 0, sizeof(bv));
    242  1.1   bouyer 		bv.bv_cookie = bl.bl_cookie;
    243  1.1   bouyer 		bv.bv_volid = i;
    244  1.1   bouyer 		bv.bv_percent = -1;
    245  1.1   bouyer 		bv.bv_seconds = 0;
    246  1.1   bouyer 
    247  1.2  xtraeme 		rv = ioctl(fd, BIOCVOL, &bv);
    248  1.1   bouyer 		if (rv == -1) {
    249  1.1   bouyer 			warn("BIOCVOL");
    250  1.1   bouyer 			return;
    251  1.1   bouyer 		}
    252  1.1   bouyer 
    253  1.1   bouyer 		if (!volheader) {
    254  1.1   bouyer 			volheader = 1;
    255  1.3  xtraeme 			printf("%10s %-10s %14s %-8s\n",
    256  1.1   bouyer 			    "Volume", "Status", "Size", "Device");
    257  1.1   bouyer 		}
    258  1.1   bouyer 
    259  1.1   bouyer 		percent[0] = '\0';
    260  1.1   bouyer 		seconds[0] = '\0';
    261  1.1   bouyer 		if (bv.bv_percent != -1)
    262  1.1   bouyer 			snprintf(percent, sizeof percent,
    263  1.1   bouyer 			    " %d%% done", bv.bv_percent);
    264  1.1   bouyer 		if (bv.bv_seconds)
    265  1.1   bouyer 			snprintf(seconds, sizeof seconds,
    266  1.1   bouyer 			    " %u seconds", bv.bv_seconds);
    267  1.1   bouyer 		switch (bv.bv_status) {
    268  1.1   bouyer 		case BIOC_SVONLINE:
    269  1.1   bouyer 			status = BIOC_SVONLINE_S;
    270  1.1   bouyer 			break;
    271  1.1   bouyer 		case BIOC_SVOFFLINE:
    272  1.1   bouyer 			status = BIOC_SVOFFLINE_S;
    273  1.1   bouyer 			break;
    274  1.1   bouyer 		case BIOC_SVDEGRADED:
    275  1.1   bouyer 			status = BIOC_SVDEGRADED_S;
    276  1.1   bouyer 			break;
    277  1.1   bouyer 		case BIOC_SVBUILDING:
    278  1.1   bouyer 			status = BIOC_SVBUILDING_S;
    279  1.1   bouyer 			break;
    280  1.1   bouyer 		case BIOC_SVREBUILD:
    281  1.1   bouyer 			status = BIOC_SVREBUILD_S;
    282  1.1   bouyer 			break;
    283  1.1   bouyer 		case BIOC_SVSCRUB:
    284  1.1   bouyer 			status = BIOC_SVSCRUB_S;
    285  1.1   bouyer 			break;
    286  1.1   bouyer 		case BIOC_SVINVALID:
    287  1.1   bouyer 		default:
    288  1.1   bouyer 			status = BIOC_SVINVALID_S;
    289  1.1   bouyer 		}
    290  1.1   bouyer 
    291  1.1   bouyer 		snprintf(volname, sizeof volname, "%s %u",
    292  1.1   bouyer 		    bi.bi_dev, bv.bv_volid);
    293  1.1   bouyer 
    294  1.1   bouyer 		if (bv.bv_level == -1 && bv.bv_nodisk == 1) {
    295  1.1   bouyer 			hotspare = 1;
    296  1.1   bouyer 			unused = 0;
    297  1.1   bouyer 		} else if (bv.bv_level == -2 && bv.bv_nodisk == 1) {
    298  1.1   bouyer 			unused = 1;
    299  1.1   bouyer 			hotspare = 0;
    300  1.1   bouyer 		} else {
    301  1.1   bouyer 			unused = 0;
    302  1.1   bouyer 			hotspare = 0;
    303  1.1   bouyer 
    304  1.1   bouyer 			if (human)
    305  1.1   bouyer 				humanize_number(size, 5,
    306  1.1   bouyer 				    (int64_t)bv.bv_size, "", HN_AUTOSCALE,
    307  1.1   bouyer 				    HN_B | HN_NOSPACE | HN_DECIMAL);
    308  1.1   bouyer 			else
    309  1.1   bouyer 				snprintf(size, sizeof size, "%14llu",
    310  1.1   bouyer 				    (long long unsigned int)bv.bv_size);
    311  1.3  xtraeme 			printf("%10s %-10s %14s %-7s RAID%u%s%s\n",
    312  1.1   bouyer 			    volname, status, size, bv.bv_dev,
    313  1.1   bouyer 			    bv.bv_level, percent, seconds);
    314  1.1   bouyer 		}
    315  1.1   bouyer 
    316  1.1   bouyer 		for (d = 0; d < bv.bv_nodisk; d++) {
    317  1.1   bouyer 			memset(&bd, 0, sizeof(bd));
    318  1.1   bouyer 			bd.bd_cookie = bl.bl_cookie;
    319  1.1   bouyer 			bd.bd_diskid = d;
    320  1.1   bouyer 			bd.bd_volid = i;
    321  1.1   bouyer 
    322  1.2  xtraeme 			rv = ioctl(fd, BIOCDISK, &bd);
    323  1.1   bouyer 			if (rv == -1) {
    324  1.1   bouyer 				warn("BIOCDISK");
    325  1.1   bouyer 				return;
    326  1.1   bouyer 			}
    327  1.1   bouyer 
    328  1.1   bouyer 			switch (bd.bd_status) {
    329  1.1   bouyer 			case BIOC_SDONLINE:
    330  1.1   bouyer 				status = BIOC_SDONLINE_S;
    331  1.1   bouyer 				break;
    332  1.1   bouyer 			case BIOC_SDOFFLINE:
    333  1.1   bouyer 				status = BIOC_SDOFFLINE_S;
    334  1.1   bouyer 				break;
    335  1.1   bouyer 			case BIOC_SDFAILED:
    336  1.1   bouyer 				status = BIOC_SDFAILED_S;
    337  1.1   bouyer 				break;
    338  1.1   bouyer 			case BIOC_SDREBUILD:
    339  1.1   bouyer 				status = BIOC_SDREBUILD_S;
    340  1.1   bouyer 				break;
    341  1.1   bouyer 			case BIOC_SDHOTSPARE:
    342  1.1   bouyer 				status = BIOC_SDHOTSPARE_S;
    343  1.1   bouyer 				break;
    344  1.1   bouyer 			case BIOC_SDUNUSED:
    345  1.1   bouyer 				status = BIOC_SDUNUSED_S;
    346  1.1   bouyer 				break;
    347  1.1   bouyer 			case BIOC_SDSCRUB:
    348  1.1   bouyer 				status = BIOC_SDSCRUB_S;
    349  1.1   bouyer 				break;
    350  1.1   bouyer 			case BIOC_SDINVALID:
    351  1.1   bouyer 			default:
    352  1.1   bouyer 				status = BIOC_SDINVALID_S;
    353  1.1   bouyer 			}
    354  1.1   bouyer 
    355  1.1   bouyer 			if (hotspare || unused)
    356  1.1   bouyer 				;	/* use volname from parent volume */
    357  1.1   bouyer 			else
    358  1.1   bouyer 				snprintf(volname, sizeof volname, "    %3u",
    359  1.1   bouyer 				    bd.bd_diskid);
    360  1.1   bouyer 
    361  1.1   bouyer 			if (human)
    362  1.1   bouyer 				humanize_number(size, 5,
    363  1.1   bouyer 				    bd.bd_size, "", HN_AUTOSCALE,
    364  1.1   bouyer 				    HN_B | HN_NOSPACE | HN_DECIMAL);
    365  1.1   bouyer 			else
    366  1.1   bouyer 				snprintf(size, sizeof size, "%14llu",
    367  1.1   bouyer 				    (long long unsigned int)bd.bd_size);
    368  1.1   bouyer 			snprintf(scsiname, sizeof scsiname,
    369  1.1   bouyer 			    "%u:%u.%u",
    370  1.1   bouyer 			    bd.bd_channel, bd.bd_target, bd.bd_lun);
    371  1.1   bouyer 			if (bd.bd_procdev[0])
    372  1.1   bouyer 				strlcpy(encname, bd.bd_procdev, sizeof encname);
    373  1.1   bouyer 			else
    374  1.1   bouyer 				strlcpy(encname, "noencl", sizeof encname);
    375  1.1   bouyer 			if (bd.bd_serial[0])
    376  1.1   bouyer 				strlcpy(serial, bd.bd_serial, sizeof serial);
    377  1.1   bouyer 			else
    378  1.1   bouyer 				strlcpy(serial, "unknown serial", sizeof serial);
    379  1.1   bouyer 
    380  1.3  xtraeme 			printf("%10s %-10s %14s %-7s %-6s <%s>\n",
    381  1.1   bouyer 			    volname, status, size, scsiname, encname,
    382  1.1   bouyer 			    bd.bd_vendor);
    383  1.1   bouyer 			if (verbose)
    384  1.1   bouyer 				printf("%7s %-10s %14s %-7s %-6s '%s'\n",
    385  1.1   bouyer 				    "", "", "", "", "", serial);
    386  1.1   bouyer 		}
    387  1.1   bouyer 	}
    388  1.1   bouyer }
    389  1.1   bouyer 
    390  1.2  xtraeme static void
    391  1.2  xtraeme bio_alarm(int fd, char *arg)
    392  1.1   bouyer {
    393  1.1   bouyer 	int rv;
    394  1.1   bouyer 	struct bioc_alarm ba;
    395  1.1   bouyer 
    396  1.1   bouyer 	ba.ba_cookie = bl.bl_cookie;
    397  1.1   bouyer 
    398  1.1   bouyer 	switch (arg[0]) {
    399  1.1   bouyer 	case 'q': /* silence alarm */
    400  1.1   bouyer 		/* FALLTHROUGH */
    401  1.1   bouyer 	case 's':
    402  1.1   bouyer 		ba.ba_opcode = BIOC_SASILENCE;
    403  1.1   bouyer 		break;
    404  1.1   bouyer 
    405  1.1   bouyer 	case 'e': /* enable alarm */
    406  1.1   bouyer 		ba.ba_opcode = BIOC_SAENABLE;
    407  1.1   bouyer 		break;
    408  1.1   bouyer 
    409  1.1   bouyer 	case 'd': /* disable alarm */
    410  1.1   bouyer 		ba.ba_opcode = BIOC_SADISABLE;
    411  1.1   bouyer 		break;
    412  1.1   bouyer 
    413  1.1   bouyer 	case 't': /* test alarm */
    414  1.1   bouyer 		ba.ba_opcode = BIOC_SATEST;
    415  1.1   bouyer 		break;
    416  1.1   bouyer 
    417  1.1   bouyer 	case 'g': /* get alarm state */
    418  1.1   bouyer 		ba.ba_opcode = BIOC_GASTATUS;
    419  1.1   bouyer 		break;
    420  1.1   bouyer 
    421  1.1   bouyer 	default:
    422  1.1   bouyer 		warnx("invalid alarm function: %s", arg);
    423  1.1   bouyer 		return;
    424  1.1   bouyer 	}
    425  1.1   bouyer 
    426  1.2  xtraeme 	rv = ioctl(fd, BIOCALARM, &ba);
    427  1.1   bouyer 	if (rv == -1) {
    428  1.1   bouyer 		warn("BIOCALARM");
    429  1.1   bouyer 		return;
    430  1.1   bouyer 	}
    431  1.1   bouyer 
    432  1.1   bouyer 	if (arg[0] == 'g') {
    433  1.1   bouyer 		printf("alarm is currently %s\n",
    434  1.1   bouyer 		    ba.ba_status ? "enabled" : "disabled");
    435  1.1   bouyer 
    436  1.1   bouyer 	}
    437  1.1   bouyer }
    438  1.1   bouyer 
    439  1.2  xtraeme static void
    440  1.2  xtraeme bio_setstate(int fd, char *arg)
    441  1.1   bouyer {
    442  1.1   bouyer 	struct bioc_setstate	bs;
    443  1.1   bouyer 	struct locator		location;
    444  1.1   bouyer 	const char		*errstr;
    445  1.1   bouyer 	int			rv;
    446  1.1   bouyer 
    447  1.1   bouyer 	errstr = str2locator(arg, &location);
    448  1.1   bouyer 	if (errstr)
    449  1.1   bouyer 		errx(1, "Target %s: %s", arg, errstr);
    450  1.1   bouyer 
    451  1.1   bouyer 	bs.bs_cookie = bl.bl_cookie;
    452  1.1   bouyer 	bs.bs_status = BIOC_SSHOTSPARE;
    453  1.1   bouyer 	bs.bs_channel = location.channel;
    454  1.1   bouyer 	bs.bs_target = location.target;
    455  1.1   bouyer 	bs.bs_lun = location.lun;
    456  1.1   bouyer 
    457  1.2  xtraeme 	rv = ioctl(fd, BIOCSETSTATE, &bs);
    458  1.1   bouyer 	if (rv == -1) {
    459  1.1   bouyer 		warn("BIOCSETSTATE");
    460  1.1   bouyer 		return;
    461  1.1   bouyer 	}
    462  1.1   bouyer }
    463  1.1   bouyer 
    464  1.2  xtraeme static void
    465  1.2  xtraeme bio_setblink(int fd, char *name, char *arg, int blink)
    466  1.1   bouyer {
    467  1.1   bouyer 	struct locator		location;
    468  1.1   bouyer 	struct bioc_inq		bi;
    469  1.1   bouyer 	struct bioc_vol		bv;
    470  1.1   bouyer 	struct bioc_disk	bd;
    471  1.1   bouyer 	struct bioc_blink	bb;
    472  1.1   bouyer 	const char		*errstr;
    473  1.1   bouyer 	int			v, d, rv;
    474  1.1   bouyer 
    475  1.1   bouyer 	errstr = str2locator(arg, &location);
    476  1.1   bouyer 	if (errstr)
    477  1.1   bouyer 		errx(1, "Target %s: %s", arg, errstr);
    478  1.1   bouyer 
    479  1.1   bouyer 	/* try setting blink on the device directly */
    480  1.1   bouyer 	memset(&bb, 0, sizeof(bb));
    481  1.1   bouyer 	bb.bb_cookie = bl.bl_cookie;
    482  1.1   bouyer 	bb.bb_status = blink;
    483  1.1   bouyer 	bb.bb_target = location.target;
    484  1.1   bouyer 	bb.bb_channel = location.channel;
    485  1.2  xtraeme 	rv = ioctl(fd, BIOCBLINK, &bb);
    486  1.1   bouyer 	if (rv == 0)
    487  1.1   bouyer 		return;
    488  1.1   bouyer 
    489  1.1   bouyer 	/* if the blink didnt work, try to find something that will */
    490  1.1   bouyer 
    491  1.1   bouyer 	memset(&bi, 0, sizeof(bi));
    492  1.1   bouyer 	bi.bi_cookie = bl.bl_cookie;
    493  1.2  xtraeme 	rv = ioctl(fd, BIOCINQ, &bi);
    494  1.1   bouyer 	if (rv == -1) {
    495  1.1   bouyer 		warn("BIOCINQ");
    496  1.1   bouyer 		return;
    497  1.1   bouyer 	}
    498  1.1   bouyer 
    499  1.1   bouyer 	for (v = 0; v < bi.bi_novol; v++) {
    500  1.1   bouyer 		memset(&bv, 0, sizeof(bv));
    501  1.1   bouyer 		bv.bv_cookie = bl.bl_cookie;
    502  1.1   bouyer 		bv.bv_volid = v;
    503  1.2  xtraeme 		rv = ioctl(fd, BIOCVOL, &bv);
    504  1.1   bouyer 		if (rv == -1) {
    505  1.1   bouyer 			warn("BIOCVOL");
    506  1.1   bouyer 			return;
    507  1.1   bouyer 		}
    508  1.1   bouyer 
    509  1.1   bouyer 		if (name && strcmp(name, bv.bv_dev) != 0)
    510  1.1   bouyer 			continue;
    511  1.1   bouyer 
    512  1.1   bouyer 		for (d = 0; d < bv.bv_nodisk; d++) {
    513  1.1   bouyer 			memset(&bd, 0, sizeof(bd));
    514  1.1   bouyer 			bd.bd_cookie = bl.bl_cookie;
    515  1.1   bouyer 			bd.bd_volid = v;
    516  1.1   bouyer 			bd.bd_diskid = d;
    517  1.1   bouyer 
    518  1.2  xtraeme 			rv = ioctl(fd, BIOCDISK, &bd);
    519  1.1   bouyer 			if (rv == -1) {
    520  1.1   bouyer 				warn("BIOCDISK");
    521  1.1   bouyer 				return;
    522  1.1   bouyer 			}
    523  1.1   bouyer 
    524  1.1   bouyer 			if (bd.bd_channel == location.channel &&
    525  1.1   bouyer 			    bd.bd_target == location.target &&
    526  1.1   bouyer 			    bd.bd_lun == location.lun) {
    527  1.1   bouyer 				if (bd.bd_procdev[0] != '\0') {
    528  1.2  xtraeme 					bio_blink(fd, bd.bd_procdev,
    529  1.1   bouyer 					    location.target, blink);
    530  1.1   bouyer 				} else
    531  1.1   bouyer 					warnx("Disk %s is not in an enclosure", arg);
    532  1.1   bouyer 				return;
    533  1.1   bouyer 			}
    534  1.1   bouyer 		}
    535  1.1   bouyer 	}
    536  1.1   bouyer 
    537  1.1   bouyer 	warnx("Disk %s does not exist", arg);
    538  1.1   bouyer 	return;
    539  1.1   bouyer }
    540  1.1   bouyer 
    541  1.2  xtraeme static void
    542  1.2  xtraeme bio_blink(int fd, char *enclosure, int target, int blinktype)
    543  1.1   bouyer {
    544  1.1   bouyer 	struct bio_locate	bio;
    545  1.1   bouyer 	struct bioc_blink	blink;
    546  1.1   bouyer 	int			rv;
    547  1.1   bouyer 
    548  1.1   bouyer 	bio.bl_name = enclosure;
    549  1.2  xtraeme 	rv = ioctl(fd, BIOCLOCATE, &bio);
    550  1.1   bouyer 	if (rv == -1)
    551  1.1   bouyer 		errx(1, "Can't locate %s device via %s", enclosure, "/dev/bio");
    552  1.1   bouyer 
    553  1.1   bouyer 	memset(&blink, 0, sizeof(blink));
    554  1.1   bouyer 	blink.bb_cookie = bio.bl_cookie;
    555  1.1   bouyer 	blink.bb_status = blinktype;
    556  1.1   bouyer 	blink.bb_target = target;
    557  1.1   bouyer 
    558  1.2  xtraeme 	rv = ioctl(fd, BIOCBLINK, &blink);
    559  1.1   bouyer 	if (rv == -1)
    560  1.1   bouyer 		warn("BIOCBLINK");
    561  1.1   bouyer }
    562