1*3af9de98Smarco /* $OpenBSD: bioctl.c,v 1.1 2005/03/29 22:04:21 marco Exp $ */ 2*3af9de98Smarco /* 3*3af9de98Smarco * Copyright (c) 2004 Marco Peereboom 4*3af9de98Smarco * All rights reserved. 5*3af9de98Smarco * 6*3af9de98Smarco * Redistribution and use in source and binary forms, with or without 7*3af9de98Smarco * modification, are permitted provided that the following conditions 8*3af9de98Smarco * are met: 9*3af9de98Smarco * 1. Redistributions of source code must retain the above copyright 10*3af9de98Smarco * notice, this list of conditions and the following disclaimer. 11*3af9de98Smarco * 2. Redistributions in binary form must reproduce the above copyright 12*3af9de98Smarco * notice, this list of conditions and the following disclaimer in the 13*3af9de98Smarco * documentation and/or other materials provided with the distribution. 14*3af9de98Smarco * 15*3af9de98Smarco * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 16*3af9de98Smarco * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17*3af9de98Smarco * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18*3af9de98Smarco * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR 19*3af9de98Smarco * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20*3af9de98Smarco * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21*3af9de98Smarco * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22*3af9de98Smarco * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23*3af9de98Smarco * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24*3af9de98Smarco * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25*3af9de98Smarco * SUCH DAMAGE. 26*3af9de98Smarco * 27*3af9de98Smarco */ 28*3af9de98Smarco 29*3af9de98Smarco #include <sys/ioctl.h> 30*3af9de98Smarco #include <sys/param.h> 31*3af9de98Smarco #include <sys/queue.h> 32*3af9de98Smarco #include <scsi/scsi_disk.h> 33*3af9de98Smarco 34*3af9de98Smarco #include <fcntl.h> 35*3af9de98Smarco #include <stdio.h> 36*3af9de98Smarco #include <stdlib.h> 37*3af9de98Smarco #include <unistd.h> 38*3af9de98Smarco 39*3af9de98Smarco #include <dev/biovar.h> 40*3af9de98Smarco 41*3af9de98Smarco #define READCAP 0x01 42*3af9de98Smarco #define ENUM 0x02 43*3af9de98Smarco #define TUR 0x04 44*3af9de98Smarco #define INQUIRY 0x08 45*3af9de98Smarco 46*3af9de98Smarco struct read_cap { 47*3af9de98Smarco u_int32_t maxlba; 48*3af9de98Smarco u_int32_t bsize; 49*3af9de98Smarco }; 50*3af9de98Smarco 51*3af9de98Smarco struct dev { 52*3af9de98Smarco SLIST_ENTRY(dev) next; 53*3af9de98Smarco u_int16_t id; 54*3af9de98Smarco u_int8_t channel; 55*3af9de98Smarco u_int8_t target; 56*3af9de98Smarco u_int64_t capacity; 57*3af9de98Smarco }; 58*3af9de98Smarco 59*3af9de98Smarco void usage(void); 60*3af9de98Smarco void cleanup(void); 61*3af9de98Smarco u_int64_t parse_passthru(char *); 62*3af9de98Smarco void parse_devlist(char *); 63*3af9de98Smarco void print_sense(u_int8_t *, u_int8_t); 64*3af9de98Smarco 65*3af9de98Smarco int bio_get_capabilities(bioc_capabilities *); 66*3af9de98Smarco void bio_alarm(char *); 67*3af9de98Smarco void bio_ping(void); 68*3af9de98Smarco void bio_startstop(char *, u_int8_t, u_int8_t); 69*3af9de98Smarco void bio_status(void); 70*3af9de98Smarco u_int64_t bio_pt_readcap(u_int8_t, u_int8_t); 71*3af9de98Smarco u_int32_t bio_pt_inquire(u_int8_t, u_int8_t, u_int8_t *); 72*3af9de98Smarco u_int32_t bio_pt_tur(u_int8_t, u_int8_t); 73*3af9de98Smarco void bio_pt_enum(void); 74*3af9de98Smarco 75*3af9de98Smarco SLIST_HEAD(dev_list, dev); 76*3af9de98Smarco 77*3af9de98Smarco /* RAID card device list */ 78*3af9de98Smarco struct dev_list devices = SLIST_HEAD_INITIALIZER(dev); 79*3af9de98Smarco /* User provided device list*/ 80*3af9de98Smarco struct dev_list ul = SLIST_HEAD_INITIALIZER(dev); 81*3af9de98Smarco 82*3af9de98Smarco char *bio_device = "/dev/bio"; 83*3af9de98Smarco 84*3af9de98Smarco int devh = -1; 85*3af9de98Smarco int debug = 0; 86*3af9de98Smarco 87*3af9de98Smarco struct bio_locate bl; 88*3af9de98Smarco 89*3af9de98Smarco #define PARSELIST (0x8000000000000000llu) 90*3af9de98Smarco int 91*3af9de98Smarco main(int argc, char *argv[]) 92*3af9de98Smarco { 93*3af9de98Smarco extern char *optarg; 94*3af9de98Smarco 95*3af9de98Smarco bioc_capabilities bc; 96*3af9de98Smarco bioc_alarm ba; 97*3af9de98Smarco 98*3af9de98Smarco int ch; 99*3af9de98Smarco int rv; 100*3af9de98Smarco unsigned char *pl; 101*3af9de98Smarco 102*3af9de98Smarco char *bioc_dev = NULL; 103*3af9de98Smarco char *al_arg = NULL; /* argument to alarm */ 104*3af9de98Smarco char *ss_arg = NULL; /* argument to start/stop */ 105*3af9de98Smarco char inq[36]; 106*3af9de98Smarco 107*3af9de98Smarco struct dev *delm; 108*3af9de98Smarco 109*3af9de98Smarco u_int64_t func = 0, subfunc = 0; 110*3af9de98Smarco u_int32_t devlist = 0; 111*3af9de98Smarco 112*3af9de98Smarco if (argc < 2) 113*3af9de98Smarco usage(); 114*3af9de98Smarco 115*3af9de98Smarco atexit(cleanup); 116*3af9de98Smarco 117*3af9de98Smarco while ((ch = getopt(argc, argv, "a:Dd:ehl:pst:u:")) != -1) { 118*3af9de98Smarco switch (ch) { 119*3af9de98Smarco case 'a': /* alarm */ 120*3af9de98Smarco func |= BIOC_ALARM; 121*3af9de98Smarco al_arg = optarg; 122*3af9de98Smarco break; 123*3af9de98Smarco 124*3af9de98Smarco case 'D': /* enable debug */ 125*3af9de98Smarco debug = 1; 126*3af9de98Smarco break; 127*3af9de98Smarco 128*3af9de98Smarco case 'd': /* device */ 129*3af9de98Smarco bioc_dev = optarg; 130*3af9de98Smarco break; 131*3af9de98Smarco 132*3af9de98Smarco case 'e': /* enumerate */ 133*3af9de98Smarco func |= BIOC_SCSICMD; 134*3af9de98Smarco subfunc |= ENUM; 135*3af9de98Smarco break; 136*3af9de98Smarco 137*3af9de98Smarco case 'l': /* device list, separated for now use one dev only*/ 138*3af9de98Smarco func |= PARSELIST; 139*3af9de98Smarco pl = optarg; 140*3af9de98Smarco break; 141*3af9de98Smarco 142*3af9de98Smarco case 'p': /* ping */ 143*3af9de98Smarco func |= BIOC_PING; 144*3af9de98Smarco break; 145*3af9de98Smarco 146*3af9de98Smarco case 's': /* status */ 147*3af9de98Smarco func |= BIOC_STATUS; 148*3af9de98Smarco break; 149*3af9de98Smarco 150*3af9de98Smarco case 't': 151*3af9de98Smarco func |= BIOC_SCSICMD; 152*3af9de98Smarco subfunc |= parse_passthru(optarg); 153*3af9de98Smarco break; 154*3af9de98Smarco 155*3af9de98Smarco case 'u': /* start/stop */ 156*3af9de98Smarco func |= BIOC_STARTSTOP; 157*3af9de98Smarco ss_arg = optarg; 158*3af9de98Smarco break; 159*3af9de98Smarco 160*3af9de98Smarco case 'h': /* help/usage */ 161*3af9de98Smarco /* FALLTHROUGH */ 162*3af9de98Smarco default: 163*3af9de98Smarco usage(); 164*3af9de98Smarco /* NOTREACHED */ 165*3af9de98Smarco } 166*3af9de98Smarco } 167*3af9de98Smarco 168*3af9de98Smarco devh = open(bio_device, O_RDWR); 169*3af9de98Smarco if (devh == -1) 170*3af9de98Smarco err(1, "Can't open %s", bio_device); 171*3af9de98Smarco 172*3af9de98Smarco bl.name = bioc_dev; 173*3af9de98Smarco rv = ioctl(devh, BIOCLOCATE, &bl); 174*3af9de98Smarco if (rv == -1) 175*3af9de98Smarco errx(1, "Can't locate %s device via %s", bl.name, bio_device); 176*3af9de98Smarco 177*3af9de98Smarco if (debug) 178*3af9de98Smarco warnx("cookie = %p", bl.cookie); 179*3af9de98Smarco 180*3af9de98Smarco if (func & PARSELIST) 181*3af9de98Smarco parse_devlist(pl); 182*3af9de98Smarco 183*3af9de98Smarco if (!bio_get_capabilities(&bc)) 184*3af9de98Smarco warnx("could not retrieve capabilities."); 185*3af9de98Smarco else { 186*3af9de98Smarco /* we should have everything setup by now so get to work */ 187*3af9de98Smarco if (func & BIOC_ALARM) 188*3af9de98Smarco if (bc.ioctls & BIOC_ALARM) 189*3af9de98Smarco bio_alarm(al_arg); 190*3af9de98Smarco else 191*3af9de98Smarco warnx("alarms are not supported."); 192*3af9de98Smarco 193*3af9de98Smarco if (func & BIOC_PING) 194*3af9de98Smarco if (bc.ioctls & BIOC_PING) 195*3af9de98Smarco bio_ping(); 196*3af9de98Smarco else 197*3af9de98Smarco warnx("ping not supported."); 198*3af9de98Smarco 199*3af9de98Smarco if (func & BIOC_STATUS) { 200*3af9de98Smarco if (bc.ioctls & BIOC_STATUS) 201*3af9de98Smarco bio_status(); 202*3af9de98Smarco else 203*3af9de98Smarco warnx("status function not supported."); 204*3af9de98Smarco } 205*3af9de98Smarco 206*3af9de98Smarco if (func & BIOC_STARTSTOP) { 207*3af9de98Smarco if (bc.ioctls & BIOC_STARTSTOP) { 208*3af9de98Smarco SLIST_FOREACH(delm, &ul, next) { 209*3af9de98Smarco bio_startstop(ss_arg, 210*3af9de98Smarco delm->channel, delm->target); 211*3af9de98Smarco } 212*3af9de98Smarco } else 213*3af9de98Smarco warnx("start/stop unit not supported."); 214*3af9de98Smarco } 215*3af9de98Smarco 216*3af9de98Smarco if (func & BIOC_SCSICMD) { 217*3af9de98Smarco if (bc.ioctls & BIOC_SCSICMD) { 218*3af9de98Smarco if (subfunc & READCAP) { 219*3af9de98Smarco SLIST_FOREACH(delm, &ul, next) { 220*3af9de98Smarco bio_pt_readcap(delm->channel, 221*3af9de98Smarco delm->target); 222*3af9de98Smarco } 223*3af9de98Smarco } 224*3af9de98Smarco 225*3af9de98Smarco if (subfunc & INQUIRY) { 226*3af9de98Smarco SLIST_FOREACH(delm, &ul, next) { 227*3af9de98Smarco bio_pt_inquire(delm->channel, 228*3af9de98Smarco delm->target, &inq[0]); 229*3af9de98Smarco } 230*3af9de98Smarco } 231*3af9de98Smarco 232*3af9de98Smarco if (subfunc & TUR) { 233*3af9de98Smarco SLIST_FOREACH(delm, &ul, next) { 234*3af9de98Smarco bio_pt_tur(delm->channel, 235*3af9de98Smarco delm->target); 236*3af9de98Smarco } 237*3af9de98Smarco } 238*3af9de98Smarco 239*3af9de98Smarco if (subfunc & ENUM) 240*3af9de98Smarco bio_pt_enum(); 241*3af9de98Smarco } else 242*3af9de98Smarco warnx("passthrough not supported."); 243*3af9de98Smarco } 244*3af9de98Smarco } 245*3af9de98Smarco 246*3af9de98Smarco return (0); 247*3af9de98Smarco } 248*3af9de98Smarco 249*3af9de98Smarco void 250*3af9de98Smarco usage(void) 251*3af9de98Smarco { 252*3af9de98Smarco extern char *__progname; 253*3af9de98Smarco 254*3af9de98Smarco fprintf(stderr, "usage: %s [-Dehpt] [-a alarm function] [-s get status]" 255*3af9de98Smarco "[-t passthrough] [-l device list] [-u go/stop function ] " 256*3af9de98Smarco "-d raid device\n", __progname); 257*3af9de98Smarco 258*3af9de98Smarco exit(1); 259*3af9de98Smarco } 260*3af9de98Smarco 261*3af9de98Smarco void 262*3af9de98Smarco cleanup(void) 263*3af9de98Smarco { 264*3af9de98Smarco struct dev *delm; 265*3af9de98Smarco 266*3af9de98Smarco if (debug) 267*3af9de98Smarco printf("atexit\n"); 268*3af9de98Smarco 269*3af9de98Smarco while (devices.slh_first != NULL) { 270*3af9de98Smarco delm = devices.slh_first; 271*3af9de98Smarco SLIST_REMOVE_HEAD(&devices, next); 272*3af9de98Smarco if (debug) 273*3af9de98Smarco printf("free device: %p\n", delm); 274*3af9de98Smarco free(delm); 275*3af9de98Smarco } 276*3af9de98Smarco 277*3af9de98Smarco while (ul.slh_first != NULL) { 278*3af9de98Smarco delm = ul.slh_first; 279*3af9de98Smarco SLIST_REMOVE_HEAD(&ul, next); 280*3af9de98Smarco if (debug) 281*3af9de98Smarco printf("free ul: %p\n", delm); 282*3af9de98Smarco free(delm); 283*3af9de98Smarco } 284*3af9de98Smarco 285*3af9de98Smarco if (devh != -1) 286*3af9de98Smarco close(devh); 287*3af9de98Smarco } 288*3af9de98Smarco 289*3af9de98Smarco u_int64_t 290*3af9de98Smarco parse_passthru(char *f) 291*3af9de98Smarco { 292*3af9de98Smarco if (debug) 293*3af9de98Smarco printf("get_subfunc: %s, ", f); 294*3af9de98Smarco 295*3af9de98Smarco switch (f[0]) { 296*3af9de98Smarco case 'i': /* INQUIRY */ 297*3af9de98Smarco if (debug) 298*3af9de98Smarco printf("inquiry\n"); 299*3af9de98Smarco return (INQUIRY); 300*3af9de98Smarco 301*3af9de98Smarco case 'e': /* ENUMERATE, not a pass through hmmm */ 302*3af9de98Smarco if (debug) 303*3af9de98Smarco printf("enumerate\n"); 304*3af9de98Smarco return (ENUM); 305*3af9de98Smarco 306*3af9de98Smarco case 'r': /* READ CAPACITY */ 307*3af9de98Smarco if (debug) 308*3af9de98Smarco printf("read cap\n"); 309*3af9de98Smarco return (READCAP); 310*3af9de98Smarco 311*3af9de98Smarco case 't': /* TUR */ 312*3af9de98Smarco if (debug) 313*3af9de98Smarco printf("TUR\n"); 314*3af9de98Smarco return (TUR); 315*3af9de98Smarco 316*3af9de98Smarco default: 317*3af9de98Smarco errx(1, "invalid pass through function"); 318*3af9de98Smarco } 319*3af9de98Smarco } 320*3af9de98Smarco 321*3af9de98Smarco void 322*3af9de98Smarco parse_devlist(char *dl) 323*3af9de98Smarco { 324*3af9de98Smarco u_int8_t c , t, done = 0; 325*3af9de98Smarco char *es, *s; 326*3af9de98Smarco struct dev *delm; 327*3af9de98Smarco 328*3af9de98Smarco es = NULL; 329*3af9de98Smarco s = dl; 330*3af9de98Smarco 331*3af9de98Smarco if (debug) 332*3af9de98Smarco printf("parse: %s\n", dl); 333*3af9de98Smarco 334*3af9de98Smarco while (!done) { 335*3af9de98Smarco c = strtol(s, &es, 10); 336*3af9de98Smarco if (debug) 337*3af9de98Smarco printf("%p %p %u %c\n", s, es, c, es[0]); 338*3af9de98Smarco s = es; 339*3af9de98Smarco if (es[0] == ':') { 340*3af9de98Smarco s++; 341*3af9de98Smarco t = strtol(s, &es, 10); 342*3af9de98Smarco if (debug) 343*3af9de98Smarco printf("%p %p %u %c\n", s, es, t, es[0]); 344*3af9de98Smarco s = es; 345*3af9de98Smarco 346*3af9de98Smarco if (c > 4) 347*3af9de98Smarco errx(1, "invalid channel number"); 348*3af9de98Smarco if (t > 16) 349*3af9de98Smarco errx(1, "invalid target number"); 350*3af9de98Smarco 351*3af9de98Smarco delm = malloc(sizeof(struct dev)); 352*3af9de98Smarco if (!delm) 353*3af9de98Smarco errx(1, "not enough memory"); 354*3af9de98Smarco 355*3af9de98Smarco delm->target = t; 356*3af9de98Smarco delm->channel = c; 357*3af9de98Smarco SLIST_INSERT_HEAD(&ul, delm, next); 358*3af9de98Smarco } 359*3af9de98Smarco if (es[0] == ',') { 360*3af9de98Smarco s++; 361*3af9de98Smarco continue; 362*3af9de98Smarco } 363*3af9de98Smarco if (es[0] == '\0') { 364*3af9de98Smarco done = 1; 365*3af9de98Smarco continue; 366*3af9de98Smarco } 367*3af9de98Smarco done = 2; 368*3af9de98Smarco } 369*3af9de98Smarco 370*3af9de98Smarco if (done == 2) { 371*3af9de98Smarco /* boink */ 372*3af9de98Smarco errx(1, "invalid device list."); 373*3af9de98Smarco } 374*3af9de98Smarco } 375*3af9de98Smarco 376*3af9de98Smarco int 377*3af9de98Smarco bio_get_capabilities(bioc_capabilities *bc) 378*3af9de98Smarco { 379*3af9de98Smarco int rv; 380*3af9de98Smarco 381*3af9de98Smarco bc->cookie = bl.cookie; 382*3af9de98Smarco rv = ioctl(devh, BIOCCAPABILITIES, bc); 383*3af9de98Smarco if (rv == -1) { 384*3af9de98Smarco warnx("Error calling bioc_ioctl() via bio_ioctl()"); 385*3af9de98Smarco return 0; 386*3af9de98Smarco } 387*3af9de98Smarco 388*3af9de98Smarco if (debug) { 389*3af9de98Smarco printf("ioctls = %016llx\n", bc->ioctls); 390*3af9de98Smarco printf("raid_types = %08lx\n", bc->raid_types); 391*3af9de98Smarco } 392*3af9de98Smarco 393*3af9de98Smarco return (1); 394*3af9de98Smarco } 395*3af9de98Smarco 396*3af9de98Smarco void 397*3af9de98Smarco bio_alarm(char *arg) 398*3af9de98Smarco { 399*3af9de98Smarco int rv; 400*3af9de98Smarco bioc_alarm ba; 401*3af9de98Smarco 402*3af9de98Smarco if (debug) 403*3af9de98Smarco printf("alarm in: %s, ", arg); 404*3af9de98Smarco 405*3af9de98Smarco ba.cookie = bl.cookie; 406*3af9de98Smarco 407*3af9de98Smarco switch (arg[0]) { 408*3af9de98Smarco case 'q': /* silence alarm */ 409*3af9de98Smarco /* FALLTHROUGH */ 410*3af9de98Smarco case 's': 411*3af9de98Smarco if (debug) 412*3af9de98Smarco printf("silence\n"); 413*3af9de98Smarco ba.opcode = BIOCSALARM_SILENCE; 414*3af9de98Smarco break; 415*3af9de98Smarco 416*3af9de98Smarco case 'e': /* enable alarm */ 417*3af9de98Smarco if (debug) 418*3af9de98Smarco printf("enable\n"); 419*3af9de98Smarco ba.opcode = BIOCSALARM_ENABLE; 420*3af9de98Smarco break; 421*3af9de98Smarco 422*3af9de98Smarco case 'd': /* disable alarm */ 423*3af9de98Smarco if (debug) 424*3af9de98Smarco printf("disable\n"); 425*3af9de98Smarco ba.opcode = BIOCSALARM_DISABLE; 426*3af9de98Smarco break; 427*3af9de98Smarco 428*3af9de98Smarco case 't': /* test alarm */ 429*3af9de98Smarco if (debug) 430*3af9de98Smarco printf("test\n"); 431*3af9de98Smarco ba.opcode = BIOCSALARM_TEST; 432*3af9de98Smarco break; 433*3af9de98Smarco 434*3af9de98Smarco case 'g': /* get alarm state */ 435*3af9de98Smarco if (debug) 436*3af9de98Smarco printf("get state\n"); 437*3af9de98Smarco ba.opcode = BIOCGALARM_STATE; 438*3af9de98Smarco break; 439*3af9de98Smarco 440*3af9de98Smarco default: 441*3af9de98Smarco warnx("invalid alarm function: %s", arg); 442*3af9de98Smarco return; 443*3af9de98Smarco } 444*3af9de98Smarco 445*3af9de98Smarco rv = ioctl(devh, BIOCALARM, &ba); 446*3af9de98Smarco if (rv == -1) { 447*3af9de98Smarco warnx("bioc_ioctl() call failed"); 448*3af9de98Smarco return; 449*3af9de98Smarco } 450*3af9de98Smarco 451*3af9de98Smarco if (arg[0] == 'g') { 452*3af9de98Smarco printf("alarm is currently %s\n", 453*3af9de98Smarco ba.state ? "enabled" : "disabled"); 454*3af9de98Smarco } 455*3af9de98Smarco } 456*3af9de98Smarco 457*3af9de98Smarco void 458*3af9de98Smarco bio_ping(void) 459*3af9de98Smarco { 460*3af9de98Smarco int rv; 461*3af9de98Smarco bioc_ping bp; 462*3af9de98Smarco 463*3af9de98Smarco bp.cookie = bl.cookie; 464*3af9de98Smarco bp.x = 0; 465*3af9de98Smarco rv = ioctl(devh, BIOCPING, &bp); 466*3af9de98Smarco if (rv == -1) { 467*3af9de98Smarco warnx("Error calling bioc_ioctl() via bio_ioctl()"); 468*3af9de98Smarco return; 469*3af9de98Smarco } 470*3af9de98Smarco 471*3af9de98Smarco printf("x after ioctl() = %i\n", bp.x); 472*3af9de98Smarco } 473*3af9de98Smarco 474*3af9de98Smarco void 475*3af9de98Smarco bio_startstop(char *arg, u_int8_t c, u_int8_t t) 476*3af9de98Smarco { 477*3af9de98Smarco int rv; 478*3af9de98Smarco bioc_startstop bs; 479*3af9de98Smarco 480*3af9de98Smarco if (debug) 481*3af9de98Smarco printf("startstop in: %s, ", arg); 482*3af9de98Smarco 483*3af9de98Smarco bs.cookie = bl.cookie; 484*3af9de98Smarco 485*3af9de98Smarco switch (arg[0]) { 486*3af9de98Smarco case 's': /* stop unit */ 487*3af9de98Smarco if (debug) 488*3af9de98Smarco printf("stop\n"); 489*3af9de98Smarco bs.opcode = BIOCSUNIT_STOP; 490*3af9de98Smarco break; 491*3af9de98Smarco 492*3af9de98Smarco case 'g': /* start or go unit */ 493*3af9de98Smarco if (debug) 494*3af9de98Smarco printf("start\n"); 495*3af9de98Smarco bs.opcode = BIOCSUNIT_START; 496*3af9de98Smarco break; 497*3af9de98Smarco 498*3af9de98Smarco default: 499*3af9de98Smarco warnx("invalid start/stop function: %s", arg); 500*3af9de98Smarco return; 501*3af9de98Smarco } 502*3af9de98Smarco 503*3af9de98Smarco bs.channel = c; 504*3af9de98Smarco bs.target = t; 505*3af9de98Smarco 506*3af9de98Smarco rv = ioctl(devh, BIOCSTARTSTOP, &bs); 507*3af9de98Smarco if (rv == -1) { 508*3af9de98Smarco warnx("bioc_ioctl() call failed"); 509*3af9de98Smarco return; 510*3af9de98Smarco } 511*3af9de98Smarco 512*3af9de98Smarco if (debug) 513*3af9de98Smarco printf("startstop done\n"); 514*3af9de98Smarco } 515*3af9de98Smarco 516*3af9de98Smarco /* get status, for now only do all */ 517*3af9de98Smarco void 518*3af9de98Smarco bio_status(void) 519*3af9de98Smarco { 520*3af9de98Smarco int rv; 521*3af9de98Smarco bioc_status bs; 522*3af9de98Smarco 523*3af9de98Smarco if (debug) 524*3af9de98Smarco printf("status()\n"); 525*3af9de98Smarco 526*3af9de98Smarco bs.cookie = bl.cookie; 527*3af9de98Smarco bs.opcode = BIOCGSTAT_ALL; 528*3af9de98Smarco 529*3af9de98Smarco rv = ioctl(devh, BIOCSTATUS, &bs); 530*3af9de98Smarco if (rv == -1) { 531*3af9de98Smarco warnx("bioc_ioctl() call failed"); 532*3af9de98Smarco return; 533*3af9de98Smarco } 534*3af9de98Smarco 535*3af9de98Smarco if (debug) 536*3af9de98Smarco printf("status done\n"); 537*3af9de98Smarco } 538*3af9de98Smarco 539*3af9de98Smarco /* read capacity for disk c,t */ 540*3af9de98Smarco u_int64_t 541*3af9de98Smarco bio_pt_readcap(u_int8_t c, u_int8_t t) 542*3af9de98Smarco { 543*3af9de98Smarco bioc_scsicmd bpt; 544*3af9de98Smarco struct read_cap rc; 545*3af9de98Smarco int rv; 546*3af9de98Smarco u_int64_t size; 547*3af9de98Smarco 548*3af9de98Smarco memset(&bpt, 0, sizeof(bpt)); 549*3af9de98Smarco bpt.cookie = bl.cookie; 550*3af9de98Smarco bpt.channel = c; 551*3af9de98Smarco bpt.target = t; 552*3af9de98Smarco bpt.cdblen = 10; 553*3af9de98Smarco bpt.cdb[0] = READ_CAPACITY; 554*3af9de98Smarco bpt.data = &rc; /* set up return data pointer */ 555*3af9de98Smarco bpt.datalen = sizeof(rc); 556*3af9de98Smarco bpt.direction = BIOC_DIRIN; 557*3af9de98Smarco bpt.senselen = 32; /* silly since the kernel overrides it */ 558*3af9de98Smarco 559*3af9de98Smarco rv = ioctl(devh, BIOCSCSICMD, &bpt); 560*3af9de98Smarco if (rv == -1) { 561*3af9de98Smarco warnx("READ CAPACITY failed %x", bpt.status); 562*3af9de98Smarco return (0); 563*3af9de98Smarco } 564*3af9de98Smarco else if (bpt.status) { 565*3af9de98Smarco if (bpt.sensebuf[0] == 0x70 || bpt.sensebuf[0] == 0x71) 566*3af9de98Smarco print_sense(&bpt.sensebuf[0], bpt.senselen); 567*3af9de98Smarco return (0); 568*3af9de98Smarco } 569*3af9de98Smarco 570*3af9de98Smarco rc.maxlba = betoh32(rc.maxlba); 571*3af9de98Smarco rc.bsize = betoh32(rc.bsize); 572*3af9de98Smarco 573*3af9de98Smarco size = (u_int64_t)rc.maxlba * (u_int64_t)rc.bsize; 574*3af9de98Smarco 575*3af9de98Smarco if (debug) 576*3af9de98Smarco printf("READ CAPACITY: %lu * %lu = %llu\n", 577*3af9de98Smarco rc.maxlba, rc.bsize, size); 578*3af9de98Smarco 579*3af9de98Smarco return (size); 580*3af9de98Smarco } 581*3af9de98Smarco 582*3af9de98Smarco 583*3af9de98Smarco /* inquire device */ 584*3af9de98Smarco u_int32_t 585*3af9de98Smarco bio_pt_inquire(u_int8_t c, u_int8_t t, u_int8_t *inq) 586*3af9de98Smarco { 587*3af9de98Smarco bioc_scsicmd bpt; 588*3af9de98Smarco int rv, i; 589*3af9de98Smarco 590*3af9de98Smarco memset(&bpt, 0, sizeof(bpt)); 591*3af9de98Smarco bpt.cookie = bl.cookie; 592*3af9de98Smarco bpt.channel = c; 593*3af9de98Smarco bpt.target = t; 594*3af9de98Smarco bpt.cdblen = 6; 595*3af9de98Smarco bpt.cdb[0] = INQUIRY; 596*3af9de98Smarco bpt.cdb[4] = 36; /* LENGTH */ 597*3af9de98Smarco bpt.data = inq; /* set up return data pointer */ 598*3af9de98Smarco bpt.datalen = 36; /* minimum INQ size */ 599*3af9de98Smarco bpt.direction = BIOC_DIRIN; 600*3af9de98Smarco bpt.senselen = 32; /* silly since the kernel overrides it */ 601*3af9de98Smarco 602*3af9de98Smarco rv = ioctl(devh, BIOCSCSICMD, &bpt); 603*3af9de98Smarco if (rv == -1) { 604*3af9de98Smarco warnx("INQUIRY failed %x", bpt.status); 605*3af9de98Smarco return 0; 606*3af9de98Smarco } 607*3af9de98Smarco else if (bpt.status) { 608*3af9de98Smarco if (bpt.sensebuf[0] == 0x70 || bpt.sensebuf[0] == 0x71) 609*3af9de98Smarco print_sense(&bpt.sensebuf[0], bpt.senselen); 610*3af9de98Smarco 611*3af9de98Smarco return 0; 612*3af9de98Smarco } 613*3af9de98Smarco 614*3af9de98Smarco if (debug) { 615*3af9de98Smarco printf("INQUIRY: "); 616*3af9de98Smarco printf("c: %u t: %u INQUIRY:", c, t); 617*3af9de98Smarco for (i = 0; i < bpt.datalen; i++) { 618*3af9de98Smarco if (i < 8) 619*3af9de98Smarco printf("%0x ", inq[i]); 620*3af9de98Smarco else 621*3af9de98Smarco printf("%c", inq[i] < ' ' ? ' ' : inq[i]); 622*3af9de98Smarco } 623*3af9de98Smarco printf("\n"); 624*3af9de98Smarco } 625*3af9de98Smarco 626*3af9de98Smarco return 1; 627*3af9de98Smarco } 628*3af9de98Smarco 629*3af9de98Smarco /* TUR for disk c,t */ 630*3af9de98Smarco u_int32_t 631*3af9de98Smarco bio_pt_tur(u_int8_t c, u_int8_t t) 632*3af9de98Smarco { 633*3af9de98Smarco bioc_scsicmd bpt; 634*3af9de98Smarco int rv; 635*3af9de98Smarco 636*3af9de98Smarco if (debug) 637*3af9de98Smarco printf("tur\n"); 638*3af9de98Smarco 639*3af9de98Smarco memset(&bpt, 0, sizeof(bpt)); 640*3af9de98Smarco bpt.cookie = bl.cookie; 641*3af9de98Smarco bpt.channel = c; 642*3af9de98Smarco bpt.target = t; 643*3af9de98Smarco bpt.cdblen = 6; 644*3af9de98Smarco bpt.direction = BIOC_DIRNONE; 645*3af9de98Smarco rv = ioctl(devh, BIOCSCSICMD, &bpt); 646*3af9de98Smarco if (rv == -1) { 647*3af9de98Smarco warnx("passthrough failed"); 648*3af9de98Smarco return (0); 649*3af9de98Smarco } 650*3af9de98Smarco 651*3af9de98Smarco if (bpt.status) { 652*3af9de98Smarco if (bpt.sensebuf[0] == 0x70 || bpt.sensebuf[0] == 0x71) 653*3af9de98Smarco print_sense(&bpt.sensebuf[0], bpt.senselen); 654*3af9de98Smarco 655*3af9de98Smarco return (0); 656*3af9de98Smarco } 657*3af9de98Smarco 658*3af9de98Smarco if (debug) 659*3af9de98Smarco printf("tur completed\n"); 660*3af9de98Smarco 661*3af9de98Smarco return (1); 662*3af9de98Smarco } 663*3af9de98Smarco 664*3af9de98Smarco 665*3af9de98Smarco /* enumerate all disks */ 666*3af9de98Smarco void 667*3af9de98Smarco bio_pt_enum(void) 668*3af9de98Smarco { 669*3af9de98Smarco bioc_scsicmd bpt; 670*3af9de98Smarco u_int32_t c, t, i, d; 671*3af9de98Smarco int rv; 672*3af9de98Smarco unsigned char inq[36]; 673*3af9de98Smarco 674*3af9de98Smarco struct dev *delm; 675*3af9de98Smarco 676*3af9de98Smarco d = 0; 677*3af9de98Smarco for (c = 0; c < 2 /* FIXME */; c++) { 678*3af9de98Smarco for (t = 0; t < 16 /* FIXME */; t++) { 679*3af9de98Smarco if (bio_pt_inquire(c, t, &inq[0])) { 680*3af9de98Smarco printf("disk %u: c: %u t: %u\n", d, c, t); 681*3af9de98Smarco delm = malloc(sizeof(struct dev)); 682*3af9de98Smarco if (delm == NULL) 683*3af9de98Smarco errx(1, "not enough memory"); 684*3af9de98Smarco delm->id = d++; 685*3af9de98Smarco delm->target = t; 686*3af9de98Smarco delm->channel = c; 687*3af9de98Smarco SLIST_INSERT_HEAD(&devices, delm, next); 688*3af9de98Smarco } 689*3af9de98Smarco } 690*3af9de98Smarco } 691*3af9de98Smarco 692*3af9de98Smarco /* silly to do this here instead of in the for loop */ 693*3af9de98Smarco SLIST_FOREACH(delm, &devices, next) { 694*3af9de98Smarco /* FIXME check the return value */ 695*3af9de98Smarco delm->capacity = bio_pt_readcap(delm->channel, delm->target); 696*3af9de98Smarco if (debug) 697*3af9de98Smarco printf("%p: %u %u %u %llu\n", delm, delm->id, 698*3af9de98Smarco delm->channel, delm->target, delm->capacity); 699*3af9de98Smarco } 700*3af9de98Smarco } 701*3af9de98Smarco 702*3af9de98Smarco /* printf sense data */ 703*3af9de98Smarco void 704*3af9de98Smarco print_sense(u_int8_t *sensebuf, u_int8_t sensebuflen) 705*3af9de98Smarco { 706*3af9de98Smarco u_int8_t i; 707*3af9de98Smarco 708*3af9de98Smarco if (debug) 709*3af9de98Smarco printf("print_sense() %p, %u\n", sensebuf, sensebuflen); 710*3af9de98Smarco 711*3af9de98Smarco for (i = 0; i < sensebuflen; i++) { 712*3af9de98Smarco printf("%02x ", sensebuf[i]); 713*3af9de98Smarco } 714*3af9de98Smarco printf("\n"); 715*3af9de98Smarco 716*3af9de98Smarco /* FIXME add some pretty decoding here */ 717*3af9de98Smarco } 718