1*0505205bSdlg /* $OpenBSD: bioctl.c,v 1.37 2005/08/21 23:37:24 dlg Exp $ */ 2cf6503d7Sderaadt 33af9de98Smarco /* 42f39728eSdlg * Copyright (c) 2004, 2005 Marco Peereboom 53af9de98Smarco * All rights reserved. 63af9de98Smarco * 73af9de98Smarco * Redistribution and use in source and binary forms, with or without 83af9de98Smarco * modification, are permitted provided that the following conditions 93af9de98Smarco * are met: 103af9de98Smarco * 1. Redistributions of source code must retain the above copyright 113af9de98Smarco * notice, this list of conditions and the following disclaimer. 123af9de98Smarco * 2. Redistributions in binary form must reproduce the above copyright 133af9de98Smarco * notice, this list of conditions and the following disclaimer in the 143af9de98Smarco * documentation and/or other materials provided with the distribution. 153af9de98Smarco * 163af9de98Smarco * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 173af9de98Smarco * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 183af9de98Smarco * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 193af9de98Smarco * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR 203af9de98Smarco * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 213af9de98Smarco * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 223af9de98Smarco * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 233af9de98Smarco * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 243af9de98Smarco * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 253af9de98Smarco * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 263af9de98Smarco * SUCH DAMAGE. 273af9de98Smarco * 283af9de98Smarco */ 293af9de98Smarco 30c2126c9aSmarco #include <sys/ioctl.h> 31c2126c9aSmarco #include <sys/param.h> 32c2126c9aSmarco #include <sys/queue.h> 33c2126c9aSmarco #include <scsi/scsi_disk.h> 342b69df39Smarco #include <scsi/scsi_all.h> 353af9de98Smarco #include <dev/biovar.h> 363af9de98Smarco 37db2730c1Smarco #include <errno.h> 38db2730c1Smarco #include <err.h> 39db2730c1Smarco #include <fcntl.h> 408ccdd032Sderaadt #include <util.h> 41db2730c1Smarco #include <stdio.h> 42db2730c1Smarco #include <stdlib.h> 43db2730c1Smarco #include <string.h> 44db2730c1Smarco #include <unistd.h> 45e4e14ad7Sderaadt #include <ctype.h> 46db2730c1Smarco #include <util.h> 47db2730c1Smarco 486de960dcSmarco struct locator { 496de960dcSmarco int channel; 506de960dcSmarco int target; 516de960dcSmarco int lun; 526de960dcSmarco }; 536de960dcSmarco 548ccdd032Sderaadt void usage(void); 5541eccc89Sderaadt const char *str2locator(const char *, struct locator *); 568ccdd032Sderaadt void cleanup(void); 578ccdd032Sderaadt 588ccdd032Sderaadt void bio_inq(char *); 598ccdd032Sderaadt void bio_alarm(char *); 606de960dcSmarco void bio_setstate(char *); 61a928c459Sderaadt void bio_setblink(char *, char *, int); 62a928c459Sderaadt void bio_blink(char *, int, int); 633af9de98Smarco 643af9de98Smarco int devh = -1; 65abe9d68eSderaadt int debug; 66abe9d68eSderaadt int human; 67abe9d68eSderaadt int verbose; 683af9de98Smarco 693af9de98Smarco struct bio_locate bl; 703af9de98Smarco 713af9de98Smarco int 723af9de98Smarco main(int argc, char *argv[]) 733af9de98Smarco { 743af9de98Smarco extern char *optarg; 75db2730c1Smarco u_int64_t func = 0; 76db2730c1Smarco /* u_int64_t subfunc = 0; */ 77cf6503d7Sderaadt char *bioc_dev = NULL, *sd_dev = NULL; 78cf6503d7Sderaadt char *realname = NULL, *al_arg = NULL; 79c55617f1Sdlg char *bl_arg = NULL; 80a928c459Sderaadt int ch, rv, blink; 813af9de98Smarco 823af9de98Smarco if (argc < 2) 833af9de98Smarco usage(); 843af9de98Smarco 85a928c459Sderaadt while ((ch = getopt(argc, argv, "b:B:u:H:ha:Div")) != -1) { 863af9de98Smarco switch (ch) { 87edfd9792Smarco case 'a': /* alarm */ 88edfd9792Smarco func |= BIOC_ALARM; 89edfd9792Smarco al_arg = optarg; 90edfd9792Smarco break; 91c55617f1Sdlg case 'b': /* blink */ 92c55617f1Sdlg func |= BIOC_BLINK; 93a928c459Sderaadt blink = BIOC_SBBLINK; 94a928c459Sderaadt bl_arg = optarg; 95a928c459Sderaadt break; 96a928c459Sderaadt case 'B': /* alarm blink */ 97a928c459Sderaadt func |= BIOC_BLINK; 98a928c459Sderaadt blink = BIOC_SBALARM; 99a928c459Sderaadt bl_arg = optarg; 100a928c459Sderaadt break; 101a928c459Sderaadt case 'u': /* unblink */ 102a928c459Sderaadt func |= BIOC_BLINK; 103a928c459Sderaadt blink = BIOC_SBUNBLINK; 104c55617f1Sdlg bl_arg = optarg; 105c55617f1Sdlg break; 106db2730c1Smarco case 'D': /* debug */ 1073af9de98Smarco debug = 1; 1083af9de98Smarco break; 1096de960dcSmarco case 'H': /* set hotspare */ 1106de960dcSmarco func |= BIOC_SETSTATE; 1116de960dcSmarco al_arg = optarg; 1126de960dcSmarco break; 1138ccdd032Sderaadt case 'h': 1148ccdd032Sderaadt human = 1; 1158ccdd032Sderaadt break; 116db2730c1Smarco case 'i': /* inquiry */ 117db2730c1Smarco func |= BIOC_INQ; 1183af9de98Smarco break; 119abe9d68eSderaadt case 'v': 120abe9d68eSderaadt verbose = 1; 121abe9d68eSderaadt break; 1223af9de98Smarco default: 1233af9de98Smarco usage(); 1243af9de98Smarco /* NOTREACHED */ 1253af9de98Smarco } 1263af9de98Smarco } 127cf6503d7Sderaadt argc -= optind; 128cf6503d7Sderaadt argv += optind; 1293af9de98Smarco 1308ccdd032Sderaadt if (argc != 1) 131cf6503d7Sderaadt usage(); 132cf6503d7Sderaadt 133dcbaf4c8Sderaadt if (func == 0) 134dcbaf4c8Sderaadt func |= BIOC_INQ; 135dcbaf4c8Sderaadt 136e4e14ad7Sderaadt /* if at least glob sd[0-9]*, it is a drive identifier */ 137e4e14ad7Sderaadt if (strncmp(argv[0], "sd", 2) == 0 && strlen(argv[0]) > 2 && 138e4e14ad7Sderaadt isdigit(argv[0][2])) 139cf6503d7Sderaadt sd_dev = argv[0]; 140cf6503d7Sderaadt else 141cf6503d7Sderaadt bioc_dev = argv[0]; 14210b411a7Smarco 14310b411a7Smarco if (bioc_dev) { 14441eccc89Sderaadt devh = open("/dev/bio", O_RDWR); 1453af9de98Smarco if (devh == -1) 14641eccc89Sderaadt err(1, "Can't open %s", "/dev/bio"); 1473af9de98Smarco 1488ccdd032Sderaadt bl.bl_name = bioc_dev; 1493af9de98Smarco rv = ioctl(devh, BIOCLOCATE, &bl); 1503af9de98Smarco if (rv == -1) 15110b411a7Smarco errx(1, "Can't locate %s device via %s", 15241eccc89Sderaadt bl.bl_name, "/dev/bio"); 153db2730c1Smarco } else if (sd_dev) { 15410b411a7Smarco devh = opendev(sd_dev, O_RDWR, OPENDEV_PART, &realname); 15510b411a7Smarco if (devh == -1) 15610b411a7Smarco err(1, "Can't open %s", sd_dev); 157db2730c1Smarco } else 15810b411a7Smarco errx(1, "need -d or -f parameter"); 1593af9de98Smarco 1603af9de98Smarco if (debug) 1618ccdd032Sderaadt warnx("cookie = %p", bl.bl_cookie); 1623af9de98Smarco 163db2730c1Smarco if (func & BIOC_INQ) { 1648ccdd032Sderaadt bio_inq(sd_dev); 165edfd9792Smarco } else if (func == BIOC_ALARM) { 166edfd9792Smarco bio_alarm(al_arg); 167c55617f1Sdlg } else if (func == BIOC_BLINK) { 168a928c459Sderaadt bio_setblink(sd_dev, bl_arg, blink); 1696de960dcSmarco } else if (func == BIOC_SETSTATE) { 1706de960dcSmarco bio_setstate(al_arg); 1713af9de98Smarco } 1723af9de98Smarco 1733af9de98Smarco return (0); 1743af9de98Smarco } 1753af9de98Smarco 1763af9de98Smarco void 1773af9de98Smarco usage(void) 1783af9de98Smarco { 1793af9de98Smarco extern char *__progname; 1803af9de98Smarco 181ebaf584eSderaadt fprintf(stderr, "usage: %s [-Dhiv] [-a alarm-function]" 182a928c459Sderaadt " [[-bBHu] chan:targ[.lun]] device\n", __progname); 1833af9de98Smarco exit(1); 1843af9de98Smarco } 1853af9de98Smarco 18641eccc89Sderaadt const char * 1876de960dcSmarco str2locator(const char *string, struct locator *location) 1886de960dcSmarco { 18950d3c4dcSdlg const char *errstr; 19041eccc89Sderaadt char parse[80], *targ, *lun; 1916de960dcSmarco 19241eccc89Sderaadt strlcpy(parse, string, sizeof parse); 19341eccc89Sderaadt targ = strchr(parse, ':'); 1946de960dcSmarco if (targ == NULL) 19541eccc89Sderaadt return ("target not specified"); 1966de960dcSmarco *targ++ = '\0'; 1976de960dcSmarco 19850d3c4dcSdlg lun = strchr(targ, '.'); 1996de960dcSmarco if (lun != NULL) { 2006de960dcSmarco *lun++ = '\0'; 20150d3c4dcSdlg location->lun = strtonum(lun, 0, 256, &errstr); 20250d3c4dcSdlg if (errstr) 20341eccc89Sderaadt return (errstr); 2046de960dcSmarco } else 2056de960dcSmarco location->lun = 0; 2066de960dcSmarco 20750d3c4dcSdlg location->target = strtonum(targ, 0, 256, &errstr); 20850d3c4dcSdlg if (errstr) 20941eccc89Sderaadt return (errstr); 21041eccc89Sderaadt location->channel = strtonum(parse, 0, 256, &errstr); 21150d3c4dcSdlg if (errstr) 21241eccc89Sderaadt return (errstr); 21341eccc89Sderaadt return (NULL); 2146de960dcSmarco } 2156de960dcSmarco 2163af9de98Smarco void 2178ccdd032Sderaadt bio_inq(char *name) 218d4546a56Sdlg { 219aa65acf1Sderaadt char *status, size[64], scsiname[16], volname[32]; 220b9950701Smarco int rv, i, d, volheader, hotspare, unused; 221aa65acf1Sderaadt char encname[16], serial[32]; 2228ccdd032Sderaadt struct bioc_disk bd; 2238ccdd032Sderaadt struct bioc_inq bi; 2248ccdd032Sderaadt struct bioc_vol bv; 225db2730c1Smarco 226db2730c1Smarco memset(&bi, 0, sizeof(bi)); 2273af9de98Smarco 2283af9de98Smarco if (debug) 229db2730c1Smarco printf("bio_inq\n"); 2303af9de98Smarco 2318ccdd032Sderaadt bi.bi_cookie = bl.bl_cookie; 2323af9de98Smarco 233db2730c1Smarco rv = ioctl(devh, BIOCINQ, &bi); 2343af9de98Smarco if (rv == -1) { 235b9950701Smarco warnx("bioc_ioctl(BIOCINQ) call failed"); 2363af9de98Smarco return; 2373af9de98Smarco } 2383af9de98Smarco 2398ccdd032Sderaadt volheader = 0; 2408ccdd032Sderaadt for (i = 0; i < bi.bi_novol; i++) { 241db2730c1Smarco memset(&bv, 0, sizeof(bv)); 2428ccdd032Sderaadt bv.bv_cookie = bl.bl_cookie; 2438ccdd032Sderaadt bv.bv_volid = i; 24470a2ae7bSmarco 245db2730c1Smarco rv = ioctl(devh, BIOCVOL, &bv); 2463af9de98Smarco if (rv == -1) { 247b9950701Smarco warnx("bioc_ioctl(BIOCVOL) call failed"); 2483af9de98Smarco return; 2493af9de98Smarco } 2503af9de98Smarco 2518ccdd032Sderaadt if (name && strcmp(name, bv.bv_dev) != 0) 2528ccdd032Sderaadt continue; 2538ccdd032Sderaadt 2548ccdd032Sderaadt if (!volheader) { 2558ccdd032Sderaadt volheader = 1; 2568ccdd032Sderaadt printf("%-7s %-10s %-14s %-8s\n", 2578ccdd032Sderaadt "Volume", "Status", "Size", "Device"); 2588ccdd032Sderaadt } 2598ccdd032Sderaadt 2608ccdd032Sderaadt switch (bv.bv_status) { 261db2730c1Smarco case BIOC_SVONLINE: 2628ccdd032Sderaadt status = BIOC_SVONLINE_S; 263db2730c1Smarco break; 264db2730c1Smarco case BIOC_SVOFFLINE: 2658ccdd032Sderaadt status = BIOC_SVOFFLINE_S; 266db2730c1Smarco break; 267db2730c1Smarco case BIOC_SVDEGRADED: 2688ccdd032Sderaadt status = BIOC_SVDEGRADED_S; 269db2730c1Smarco break; 270db2730c1Smarco case BIOC_SVINVALID: 271db2730c1Smarco default: 2728ccdd032Sderaadt status = BIOC_SVINVALID_S; 273d4546a56Sdlg } 2743af9de98Smarco 275aa65acf1Sderaadt snprintf(volname, sizeof volname, "%s %u", 2768ccdd032Sderaadt bi.bi_dev, bv.bv_volid); 277b9950701Smarco 278aa65acf1Sderaadt if (bv.bv_level == -1 && bv.bv_nodisk == 1) 279aa65acf1Sderaadt hotspare = 1; 280b9950701Smarco else if (bv.bv_level == -2 && bv.bv_nodisk == 1) 281b9950701Smarco unused = 1; 282aa65acf1Sderaadt else { 283b9950701Smarco unused = 0; 284aa65acf1Sderaadt hotspare = 0; 285aa65acf1Sderaadt 2868ccdd032Sderaadt if (human) 2878ccdd032Sderaadt fmt_scaled(bv.bv_size, size); 2888ccdd032Sderaadt else 2898ccdd032Sderaadt snprintf(size, sizeof size, "%14llu", 2908ccdd032Sderaadt bv.bv_size); 291813b6523Sderaadt printf("%7s %-10s %14s %-7s RAID%u\n", 292aa65acf1Sderaadt volname, status, size, bv.bv_dev, bv.bv_level); 293aa65acf1Sderaadt } 2948ccdd032Sderaadt 2958ccdd032Sderaadt for (d = 0; d < bv.bv_nodisk; d++) { 296db2730c1Smarco memset(&bd, 0, sizeof(bd)); 2978ccdd032Sderaadt bd.bd_cookie = bl.bl_cookie; 2988ccdd032Sderaadt bd.bd_diskid = d; 2998ccdd032Sderaadt bd.bd_volid = i; 3003af9de98Smarco 301db2730c1Smarco rv = ioctl(devh, BIOCDISK, &bd); 3023af9de98Smarco if (rv == -1) { 303b9950701Smarco warnx("bioc_ioctl(BIOCDISK) call failed"); 3043af9de98Smarco return; 3053af9de98Smarco } 3063af9de98Smarco 3078ccdd032Sderaadt switch (bd.bd_status) { 308db2730c1Smarco case BIOC_SDONLINE: 3098ccdd032Sderaadt status = BIOC_SDONLINE_S; 310d4546a56Sdlg break; 311db2730c1Smarco case BIOC_SDOFFLINE: 3128ccdd032Sderaadt status = BIOC_SDOFFLINE_S; 313d4546a56Sdlg break; 314db2730c1Smarco case BIOC_SDFAILED: 3158ccdd032Sderaadt status = BIOC_SDFAILED_S; 316db2730c1Smarco break; 317db2730c1Smarco case BIOC_SDREBUILD: 3188ccdd032Sderaadt status = BIOC_SDREBUILD_S; 319db2730c1Smarco break; 320db2730c1Smarco case BIOC_SDHOTSPARE: 3218ccdd032Sderaadt status = BIOC_SDHOTSPARE_S; 322db2730c1Smarco break; 323db2730c1Smarco case BIOC_SDUNUSED: 3248ccdd032Sderaadt status = BIOC_SDUNUSED_S; 325db2730c1Smarco break; 326db2730c1Smarco case BIOC_SDINVALID: 327d4546a56Sdlg default: 3288ccdd032Sderaadt status = BIOC_SDINVALID_S; 329d4546a56Sdlg } 330aa65acf1Sderaadt 331b9950701Smarco if (hotspare || unused) 332aa65acf1Sderaadt ; /* use volname from parent volume */ 333aa65acf1Sderaadt else 334aa65acf1Sderaadt snprintf(volname, sizeof volname, " %3u", 335aa65acf1Sderaadt bd.bd_diskid); 336aa65acf1Sderaadt 3378ccdd032Sderaadt if (human) 3388ccdd032Sderaadt fmt_scaled(bd.bd_size, size); 3398ccdd032Sderaadt else 3408ccdd032Sderaadt snprintf(size, sizeof size, "%14llu", 3418ccdd032Sderaadt bd.bd_size); 3428ccdd032Sderaadt snprintf(scsiname, sizeof scsiname, 34343d61178Sderaadt "%u:%u.%u", 34443d61178Sderaadt bd.bd_channel, bd.bd_target, bd.bd_lun); 3455978b28dSderaadt if (bd.bd_procdev[0]) 346abe9d68eSderaadt strlcpy(encname, bd.bd_procdev, sizeof encname); 3475978b28dSderaadt else 348abe9d68eSderaadt strlcpy(encname, "noencl", sizeof encname); 349abe9d68eSderaadt if (bd.bd_serial[0]) 350abe9d68eSderaadt strlcpy(serial, bd.bd_serial, sizeof serial); 351abe9d68eSderaadt else 352abe9d68eSderaadt strlcpy(serial, "unknown serial", sizeof serial); 3538ccdd032Sderaadt 354aa65acf1Sderaadt printf("%7s %-10s %14s %-7s %-6s <%s>\n", 355aa65acf1Sderaadt volname, status, size, scsiname, encname, 3568ccdd032Sderaadt bd.bd_vendor); 357abe9d68eSderaadt if (verbose) 358aa65acf1Sderaadt printf("%7s %-10s %14s %-7s %-6s '%s'\n", 359abe9d68eSderaadt "", "", "", "", "", serial); 360d4546a56Sdlg } 361d4546a56Sdlg } 362d4546a56Sdlg } 363edfd9792Smarco 364edfd9792Smarco void 365edfd9792Smarco bio_alarm(char *arg) 366edfd9792Smarco { 367edfd9792Smarco int rv; 3688ccdd032Sderaadt struct bioc_alarm ba; 369edfd9792Smarco 3708ccdd032Sderaadt ba.ba_cookie = bl.bl_cookie; 371edfd9792Smarco 372edfd9792Smarco switch (arg[0]) { 373edfd9792Smarco case 'q': /* silence alarm */ 374edfd9792Smarco /* FALLTHROUGH */ 375edfd9792Smarco case 's': 3768ccdd032Sderaadt ba.ba_opcode = BIOC_SASILENCE; 377edfd9792Smarco break; 378edfd9792Smarco 379edfd9792Smarco case 'e': /* enable alarm */ 3808ccdd032Sderaadt ba.ba_opcode = BIOC_SAENABLE; 381edfd9792Smarco break; 382edfd9792Smarco 383edfd9792Smarco case 'd': /* disable alarm */ 3848ccdd032Sderaadt ba.ba_opcode = BIOC_SADISABLE; 385edfd9792Smarco break; 386edfd9792Smarco 387edfd9792Smarco case 't': /* test alarm */ 3888ccdd032Sderaadt ba.ba_opcode = BIOC_SATEST; 389edfd9792Smarco break; 390edfd9792Smarco 391edfd9792Smarco case 'g': /* get alarm state */ 3928ccdd032Sderaadt ba.ba_opcode = BIOC_GASTATUS; 393edfd9792Smarco break; 394edfd9792Smarco 395edfd9792Smarco default: 396edfd9792Smarco warnx("invalid alarm function: %s", arg); 397edfd9792Smarco return; 398edfd9792Smarco } 399edfd9792Smarco 400edfd9792Smarco rv = ioctl(devh, BIOCALARM, &ba); 401edfd9792Smarco if (rv == -1) { 4026de960dcSmarco warnx("bioc_ioctl(ALARM) call failed"); 403edfd9792Smarco return; 404edfd9792Smarco } 405edfd9792Smarco 406edfd9792Smarco if (arg[0] == 'g') { 407edfd9792Smarco printf("alarm is currently %s\n", 4088ccdd032Sderaadt ba.ba_status ? "enabled" : "disabled"); 4098ccdd032Sderaadt 410edfd9792Smarco } 411edfd9792Smarco } 4126de960dcSmarco 413ebaf584eSderaadt void 414ebaf584eSderaadt bio_setstate(char *arg) 4156de960dcSmarco { 4166de960dcSmarco struct bioc_setstate bs; 4176de960dcSmarco struct locator location; 41841eccc89Sderaadt const char *errstr; 419ebaf584eSderaadt int rv; 4206de960dcSmarco 42141eccc89Sderaadt errstr = str2locator(arg, &location); 42241eccc89Sderaadt if (errstr) 42341eccc89Sderaadt errx(1, "Target %s: %s", arg, errstr); 4246de960dcSmarco 4256de960dcSmarco bs.bs_cookie = bl.bl_cookie; 4266de960dcSmarco bs.bs_status = BIOC_SSHOTSPARE; 4276de960dcSmarco bs.bs_channel = location.channel; 4286de960dcSmarco bs.bs_target = location.target; 4296de960dcSmarco bs.bs_lun = location.lun; 4306de960dcSmarco 4316de960dcSmarco rv = ioctl(devh, BIOCSETSTATE, &bs); 4326de960dcSmarco if (rv == -1) { 4336de960dcSmarco warnx("bioc_ioctl(BIOCSETSTATE) call failed"); 4346de960dcSmarco return; 4356de960dcSmarco } 4366de960dcSmarco } 437c55617f1Sdlg 438c55617f1Sdlg void 439a928c459Sderaadt bio_setblink(char *name, char *arg, int blink) 440c55617f1Sdlg { 44150d3c4dcSdlg struct locator location; 44250d3c4dcSdlg struct bioc_inq bi; 44350d3c4dcSdlg struct bioc_vol bv; 44450d3c4dcSdlg struct bioc_disk bd; 445*0505205bSdlg struct bioc_blink bb; 44641eccc89Sderaadt const char *errstr; 44750d3c4dcSdlg int v, d, rv; 448c55617f1Sdlg 44941eccc89Sderaadt errstr = str2locator(arg, &location); 45041eccc89Sderaadt if (errstr) 45141eccc89Sderaadt errx(1, "Target %s: %s", arg, errstr); 45250d3c4dcSdlg 453*0505205bSdlg /* try setting blink on the device directly */ 454*0505205bSdlg memset(&bb, 0, sizeof(bb)); 455*0505205bSdlg bb.bb_cookie = bl.bl_cookie; 456*0505205bSdlg bb.bb_status = blink; 457*0505205bSdlg bb.bb_target = location.target; 458*0505205bSdlg rv = ioctl(devh, BIOCBLINK, &bb); 459*0505205bSdlg if (rv == 0) 460*0505205bSdlg return; 461*0505205bSdlg 462*0505205bSdlg /* if the blink didnt work, try to find something that will */ 463*0505205bSdlg 46450d3c4dcSdlg memset(&bi, 0, sizeof(bi)); 46550d3c4dcSdlg bi.bi_cookie = bl.bl_cookie; 46650d3c4dcSdlg rv = ioctl(devh, BIOCINQ, &bi); 46750d3c4dcSdlg if (rv == -1) { 46850d3c4dcSdlg warn("bio ioctl(BIOCINQ) call failed"); 46950d3c4dcSdlg return; 47050d3c4dcSdlg } 47150d3c4dcSdlg 47250d3c4dcSdlg for (v = 0; v < bi.bi_novol; v++) { 47350d3c4dcSdlg memset(&bv, 0, sizeof(bv)); 47450d3c4dcSdlg bv.bv_cookie = bl.bl_cookie; 47550d3c4dcSdlg bv.bv_volid = v; 47650d3c4dcSdlg rv = ioctl(devh, BIOCVOL, &bv); 47750d3c4dcSdlg if (rv == -1) { 47850d3c4dcSdlg warn("bio ioctl(BIOCVOL) call failed"); 47950d3c4dcSdlg return; 48050d3c4dcSdlg } 48150d3c4dcSdlg 48250d3c4dcSdlg if (name && strcmp(name, bv.bv_dev) != 0) 48350d3c4dcSdlg continue; 48450d3c4dcSdlg 48550d3c4dcSdlg for (d = 0; d < bv.bv_nodisk; d++) { 48650d3c4dcSdlg memset(&bd, 0, sizeof(bd)); 48750d3c4dcSdlg bd.bd_cookie = bl.bl_cookie; 48850d3c4dcSdlg bd.bd_volid = v; 48950d3c4dcSdlg bd.bd_diskid = d; 49050d3c4dcSdlg 49150d3c4dcSdlg rv = ioctl(devh, BIOCDISK, &bd); 49250d3c4dcSdlg if (rv == -1) { 49350d3c4dcSdlg warn("bio ioctl(BIOCDISK) call failed"); 49450d3c4dcSdlg return; 49550d3c4dcSdlg } 49650d3c4dcSdlg 49750d3c4dcSdlg if (bd.bd_channel == location.channel && 49850d3c4dcSdlg bd.bd_target == location.target && 49950d3c4dcSdlg bd.bd_lun == location.lun) { 50050d3c4dcSdlg if (bd.bd_procdev[0] != '\0') { 50150d3c4dcSdlg bio_blink(bd.bd_procdev, 502a928c459Sderaadt location.target, blink); 50350d3c4dcSdlg } else 50441eccc89Sderaadt warnx("Disk %s is not in an enclosure", arg); 50550d3c4dcSdlg return; 50650d3c4dcSdlg } 50750d3c4dcSdlg } 50850d3c4dcSdlg } 50950d3c4dcSdlg 51041eccc89Sderaadt warnx("Disk %s does not exist", arg); 51150d3c4dcSdlg return; 51250d3c4dcSdlg } 51350d3c4dcSdlg 51450d3c4dcSdlg void 515a928c459Sderaadt bio_blink(char *enclosure, int target, int blinktype) 51650d3c4dcSdlg { 51750d3c4dcSdlg int bioh; 51850d3c4dcSdlg struct bio_locate bio; 51950d3c4dcSdlg struct bioc_blink blink; 52050d3c4dcSdlg int rv; 52150d3c4dcSdlg 52241eccc89Sderaadt bioh = open("/dev/bio", O_RDWR); 52350d3c4dcSdlg if (bioh == -1) 52441eccc89Sderaadt err(1, "Can't open %s", "/dev/bio"); 52550d3c4dcSdlg 52650d3c4dcSdlg bio.bl_name = enclosure; 52750d3c4dcSdlg rv = ioctl(bioh, BIOCLOCATE, &bio); 52850d3c4dcSdlg if (rv == -1) 52941eccc89Sderaadt errx(1, "Can't locate %s device via %s", enclosure, "/dev/bio"); 530c55617f1Sdlg 531c55617f1Sdlg memset(&blink, 0, sizeof(blink)); 53250d3c4dcSdlg blink.bb_cookie = bio.bl_cookie; 533a928c459Sderaadt blink.bb_status = blinktype; 534c55617f1Sdlg blink.bb_target = target; 535c55617f1Sdlg 53650d3c4dcSdlg rv = ioctl(bioh, BIOCBLINK, &blink); 537c55617f1Sdlg if (rv == -1) 53850d3c4dcSdlg warn("bio ioctl(BIOCBLINK) call failed"); 53950d3c4dcSdlg 54050d3c4dcSdlg close(bioh); 541c55617f1Sdlg } 542