1*abe9d68eSderaadt /* $OpenBSD: bioctl.c,v 1.27 2005/08/09 01:43:33 deraadt 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 488ccdd032Sderaadt void usage(void); 498ccdd032Sderaadt void cleanup(void); 508ccdd032Sderaadt 518ccdd032Sderaadt void bio_inq(char *); 528ccdd032Sderaadt void bio_alarm(char *); 533af9de98Smarco 54c2126c9aSmarco /* globals */ 55c2126c9aSmarco const char *bio_device = "/dev/bio"; 563af9de98Smarco 573af9de98Smarco int devh = -1; 58*abe9d68eSderaadt int debug; 59*abe9d68eSderaadt int human; 60*abe9d68eSderaadt int verbose; 613af9de98Smarco 623af9de98Smarco struct bio_locate bl; 633af9de98Smarco 643af9de98Smarco int 653af9de98Smarco main(int argc, char *argv[]) 663af9de98Smarco { 673af9de98Smarco extern char *optarg; 68db2730c1Smarco u_int64_t func = 0; 69db2730c1Smarco /* u_int64_t subfunc = 0; */ 70cf6503d7Sderaadt char *bioc_dev = NULL, *sd_dev = NULL; 71cf6503d7Sderaadt char *realname = NULL, *al_arg = NULL; 72cf6503d7Sderaadt int ch, rv; 733af9de98Smarco 743af9de98Smarco if (argc < 2) 753af9de98Smarco usage(); 763af9de98Smarco 77*abe9d68eSderaadt while ((ch = getopt(argc, argv, "ha:Div")) != -1) { 783af9de98Smarco switch (ch) { 79edfd9792Smarco case 'a': /* alarm */ 80edfd9792Smarco func |= BIOC_ALARM; 81edfd9792Smarco al_arg = optarg; 82edfd9792Smarco break; 83db2730c1Smarco case 'D': /* debug */ 843af9de98Smarco debug = 1; 853af9de98Smarco break; 868ccdd032Sderaadt case 'h': 878ccdd032Sderaadt human = 1; 888ccdd032Sderaadt break; 89db2730c1Smarco case 'i': /* inquiry */ 90db2730c1Smarco func |= BIOC_INQ; 913af9de98Smarco break; 92*abe9d68eSderaadt case 'v': 93*abe9d68eSderaadt verbose = 1; 94*abe9d68eSderaadt break; 953af9de98Smarco default: 963af9de98Smarco usage(); 973af9de98Smarco /* NOTREACHED */ 983af9de98Smarco } 993af9de98Smarco } 100cf6503d7Sderaadt argc -= optind; 101cf6503d7Sderaadt argv += optind; 1023af9de98Smarco 1038ccdd032Sderaadt if (argc != 1) 104cf6503d7Sderaadt usage(); 105cf6503d7Sderaadt 106dcbaf4c8Sderaadt if (func == 0) 107dcbaf4c8Sderaadt func |= BIOC_INQ; 108dcbaf4c8Sderaadt 109e4e14ad7Sderaadt /* if at least glob sd[0-9]*, it is a drive identifier */ 110e4e14ad7Sderaadt if (strncmp(argv[0], "sd", 2) == 0 && strlen(argv[0]) > 2 && 111e4e14ad7Sderaadt isdigit(argv[0][2])) 112cf6503d7Sderaadt sd_dev = argv[0]; 113cf6503d7Sderaadt else 114cf6503d7Sderaadt bioc_dev = argv[0]; 11510b411a7Smarco 11610b411a7Smarco if (bioc_dev) { 1173af9de98Smarco devh = open(bio_device, O_RDWR); 1183af9de98Smarco if (devh == -1) 1193af9de98Smarco err(1, "Can't open %s", bio_device); 1203af9de98Smarco 1218ccdd032Sderaadt bl.bl_name = bioc_dev; 1223af9de98Smarco rv = ioctl(devh, BIOCLOCATE, &bl); 1233af9de98Smarco if (rv == -1) 12410b411a7Smarco errx(1, "Can't locate %s device via %s", 1258ccdd032Sderaadt bl.bl_name, bio_device); 126db2730c1Smarco } else if (sd_dev) { 12710b411a7Smarco devh = opendev(sd_dev, O_RDWR, OPENDEV_PART, &realname); 12810b411a7Smarco if (devh == -1) 12910b411a7Smarco err(1, "Can't open %s", sd_dev); 130db2730c1Smarco } else 13110b411a7Smarco errx(1, "need -d or -f parameter"); 1323af9de98Smarco 1333af9de98Smarco if (debug) 1348ccdd032Sderaadt warnx("cookie = %p", bl.bl_cookie); 1353af9de98Smarco 136db2730c1Smarco if (func & BIOC_INQ) { 1378ccdd032Sderaadt bio_inq(sd_dev); 138edfd9792Smarco } else if (func == BIOC_ALARM) { 139edfd9792Smarco bio_alarm(al_arg); 1403af9de98Smarco } 1413af9de98Smarco 1423af9de98Smarco return (0); 1433af9de98Smarco } 1443af9de98Smarco 1453af9de98Smarco void 1463af9de98Smarco usage(void) 1473af9de98Smarco { 1483af9de98Smarco extern char *__progname; 1493af9de98Smarco 150cf6503d7Sderaadt fprintf(stderr, 151*abe9d68eSderaadt "usage: %s [-Dhiv] [-a alarm-function] device\n", __progname); 1523af9de98Smarco exit(1); 1533af9de98Smarco } 1543af9de98Smarco 1553af9de98Smarco void 1568ccdd032Sderaadt bio_inq(char *name) 157d4546a56Sdlg { 158*abe9d68eSderaadt char *status, size[64], scsiname[16], encname[16], serial[32]; 1598ccdd032Sderaadt int rv, i, d, volheader; 1608ccdd032Sderaadt struct bioc_disk bd; 1618ccdd032Sderaadt struct bioc_inq bi; 1628ccdd032Sderaadt struct bioc_vol bv; 163db2730c1Smarco 164db2730c1Smarco memset(&bi, 0, sizeof(bi)); 1653af9de98Smarco 1663af9de98Smarco if (debug) 167db2730c1Smarco printf("bio_inq\n"); 1683af9de98Smarco 1698ccdd032Sderaadt bi.bi_cookie = bl.bl_cookie; 1703af9de98Smarco 171db2730c1Smarco rv = ioctl(devh, BIOCINQ, &bi); 1723af9de98Smarco if (rv == -1) { 1733af9de98Smarco warnx("bioc_ioctl() call failed"); 1743af9de98Smarco return; 1753af9de98Smarco } 1763af9de98Smarco 1778ccdd032Sderaadt volheader = 0; 1788ccdd032Sderaadt for (i = 0; i < bi.bi_novol; i++) { 179db2730c1Smarco memset(&bv, 0, sizeof(bv)); 1808ccdd032Sderaadt bv.bv_cookie = bl.bl_cookie; 1818ccdd032Sderaadt bv.bv_volid = i; 18270a2ae7bSmarco 183db2730c1Smarco rv = ioctl(devh, BIOCVOL, &bv); 1843af9de98Smarco if (rv == -1) { 1853af9de98Smarco warnx("bioc_ioctl() call failed"); 1863af9de98Smarco return; 1873af9de98Smarco } 1883af9de98Smarco 1898ccdd032Sderaadt if (name && strcmp(name, bv.bv_dev) != 0) 1908ccdd032Sderaadt continue; 1918ccdd032Sderaadt 1928ccdd032Sderaadt if (!volheader) { 1938ccdd032Sderaadt volheader = 1; 1948ccdd032Sderaadt printf("%-7s %-10s %-14s %-8s\n", 1958ccdd032Sderaadt "Volume", "Status", "Size", "Device"); 1968ccdd032Sderaadt } 1978ccdd032Sderaadt 1988ccdd032Sderaadt switch (bv.bv_status) { 199db2730c1Smarco case BIOC_SVONLINE: 2008ccdd032Sderaadt status = BIOC_SVONLINE_S; 201db2730c1Smarco break; 202db2730c1Smarco case BIOC_SVOFFLINE: 2038ccdd032Sderaadt status = BIOC_SVOFFLINE_S; 204db2730c1Smarco break; 205db2730c1Smarco case BIOC_SVDEGRADED: 2068ccdd032Sderaadt status = BIOC_SVDEGRADED_S; 207db2730c1Smarco break; 208db2730c1Smarco case BIOC_SVINVALID: 209db2730c1Smarco default: 2108ccdd032Sderaadt status = BIOC_SVINVALID_S; 211d4546a56Sdlg } 2123af9de98Smarco 2138ccdd032Sderaadt snprintf(scsiname, sizeof scsiname, "%s %u", 2148ccdd032Sderaadt bi.bi_dev, bv.bv_volid); 2158ccdd032Sderaadt if (human) 2168ccdd032Sderaadt fmt_scaled(bv.bv_size, size); 2178ccdd032Sderaadt else 2188ccdd032Sderaadt snprintf(size, sizeof size, "%14llu", 2198ccdd032Sderaadt bv.bv_size); 2208ccdd032Sderaadt printf("%7s %-10s %14s %-8s RAID%u\n", 2218ccdd032Sderaadt scsiname, status, size, bv.bv_dev, bv.bv_level); 2228ccdd032Sderaadt 2238ccdd032Sderaadt for (d = 0; d < bv.bv_nodisk; d++) { 224db2730c1Smarco memset(&bd, 0, sizeof(bd)); 2258ccdd032Sderaadt bd.bd_cookie = bl.bl_cookie; 2268ccdd032Sderaadt bd.bd_diskid = d; 2278ccdd032Sderaadt bd.bd_volid = i; 2283af9de98Smarco 229db2730c1Smarco rv = ioctl(devh, BIOCDISK, &bd); 2303af9de98Smarco if (rv == -1) { 2313af9de98Smarco warnx("bioc_ioctl() call failed"); 2323af9de98Smarco return; 2333af9de98Smarco } 2343af9de98Smarco 2358ccdd032Sderaadt switch (bd.bd_status) { 236db2730c1Smarco case BIOC_SDONLINE: 2378ccdd032Sderaadt status = BIOC_SDONLINE_S; 238d4546a56Sdlg break; 239db2730c1Smarco case BIOC_SDOFFLINE: 2408ccdd032Sderaadt status = BIOC_SDOFFLINE_S; 241d4546a56Sdlg break; 242db2730c1Smarco case BIOC_SDFAILED: 2438ccdd032Sderaadt status = BIOC_SDFAILED_S; 244db2730c1Smarco break; 245db2730c1Smarco case BIOC_SDREBUILD: 2468ccdd032Sderaadt status = BIOC_SDREBUILD_S; 247db2730c1Smarco break; 248db2730c1Smarco case BIOC_SDHOTSPARE: 2498ccdd032Sderaadt status = BIOC_SDHOTSPARE_S; 250db2730c1Smarco break; 251db2730c1Smarco case BIOC_SDUNUSED: 2528ccdd032Sderaadt status = BIOC_SDUNUSED_S; 253db2730c1Smarco break; 254db2730c1Smarco case BIOC_SDINVALID: 255d4546a56Sdlg default: 2568ccdd032Sderaadt status = BIOC_SDINVALID_S; 257d4546a56Sdlg } 2588ccdd032Sderaadt if (human) 2598ccdd032Sderaadt fmt_scaled(bd.bd_size, size); 2608ccdd032Sderaadt else 2618ccdd032Sderaadt snprintf(size, sizeof size, "%14llu", 2628ccdd032Sderaadt bd.bd_size); 2638ccdd032Sderaadt snprintf(scsiname, sizeof scsiname, 26443d61178Sderaadt "%u:%u.%u", 26543d61178Sderaadt bd.bd_channel, bd.bd_target, bd.bd_lun); 2665978b28dSderaadt if (bd.bd_procdev[0]) 267*abe9d68eSderaadt strlcpy(encname, bd.bd_procdev, sizeof encname); 2685978b28dSderaadt else 269*abe9d68eSderaadt strlcpy(encname, "noencl", sizeof encname); 270*abe9d68eSderaadt if (bd.bd_serial[0]) 271*abe9d68eSderaadt strlcpy(serial, bd.bd_serial, sizeof serial); 272*abe9d68eSderaadt else 273*abe9d68eSderaadt strlcpy(serial, "unknown serial", sizeof serial); 2748ccdd032Sderaadt 2758ccdd032Sderaadt printf(" %3u %-10s %14s %-7s %-6s <%s>\n", 2768ccdd032Sderaadt bd.bd_diskid, status, size, scsiname, encname, 2778ccdd032Sderaadt bd.bd_vendor); 278*abe9d68eSderaadt if (verbose) 279*abe9d68eSderaadt printf(" %3s %-10s %14s %-7s %-6s '%s'\n", 280*abe9d68eSderaadt "", "", "", "", "", serial); 281d4546a56Sdlg } 282d4546a56Sdlg } 2838ccdd032Sderaadt /* printf("where are my spares?\n"); */ 284d4546a56Sdlg } 285edfd9792Smarco 286edfd9792Smarco void 287edfd9792Smarco bio_alarm(char *arg) 288edfd9792Smarco { 289edfd9792Smarco int rv; 2908ccdd032Sderaadt struct bioc_alarm ba; 291edfd9792Smarco 2928ccdd032Sderaadt ba.ba_cookie = bl.bl_cookie; 293edfd9792Smarco 294edfd9792Smarco switch (arg[0]) { 295edfd9792Smarco case 'q': /* silence alarm */ 296edfd9792Smarco /* FALLTHROUGH */ 297edfd9792Smarco case 's': 2988ccdd032Sderaadt ba.ba_opcode = BIOC_SASILENCE; 299edfd9792Smarco break; 300edfd9792Smarco 301edfd9792Smarco case 'e': /* enable alarm */ 3028ccdd032Sderaadt ba.ba_opcode = BIOC_SAENABLE; 303edfd9792Smarco break; 304edfd9792Smarco 305edfd9792Smarco case 'd': /* disable alarm */ 3068ccdd032Sderaadt ba.ba_opcode = BIOC_SADISABLE; 307edfd9792Smarco break; 308edfd9792Smarco 309edfd9792Smarco case 't': /* test alarm */ 3108ccdd032Sderaadt ba.ba_opcode = BIOC_SATEST; 311edfd9792Smarco break; 312edfd9792Smarco 313edfd9792Smarco case 'g': /* get alarm state */ 3148ccdd032Sderaadt ba.ba_opcode = BIOC_GASTATUS; 315edfd9792Smarco break; 316edfd9792Smarco 317edfd9792Smarco default: 318edfd9792Smarco warnx("invalid alarm function: %s", arg); 319edfd9792Smarco return; 320edfd9792Smarco } 321edfd9792Smarco 322edfd9792Smarco rv = ioctl(devh, BIOCALARM, &ba); 323edfd9792Smarco if (rv == -1) { 324edfd9792Smarco warnx("bioc_ioctl() call failed"); 325edfd9792Smarco return; 326edfd9792Smarco } 327edfd9792Smarco 328edfd9792Smarco if (arg[0] == 'g') { 329edfd9792Smarco printf("alarm is currently %s\n", 3308ccdd032Sderaadt ba.ba_status ? "enabled" : "disabled"); 3318ccdd032Sderaadt 332edfd9792Smarco } 333edfd9792Smarco } 334