diff options
author | Marco Peereboom <marco@cvs.openbsd.org> | 2005-07-29 16:01:31 +0000 |
---|---|---|
committer | Marco Peereboom <marco@cvs.openbsd.org> | 2005-07-29 16:01:31 +0000 |
commit | 66403d7b688dbb946e84aeb5eb81b0bbf1c04087 (patch) | |
tree | 1b235b302ff5e36baf0e75a790290e2767293570 /sbin | |
parent | fe6ebae7b56098b265f77fe605c859f777c72443 (diff) |
Redo bioctl because initial implementation was too complex.
tested and ok dlg@ beck@
get it in @deraadt
Diffstat (limited to 'sbin')
-rw-r--r-- | sbin/bioctl/Makefile | 5 | ||||
-rw-r--r-- | sbin/bioctl/bioctl.8 | 48 | ||||
-rw-r--r-- | sbin/bioctl/bioctl.c | 1050 | ||||
-rw-r--r-- | sbin/bioctl/bioctl.h | 52 |
4 files changed, 112 insertions, 1043 deletions
diff --git a/sbin/bioctl/Makefile b/sbin/bioctl/Makefile index aed3cb91772..a25143cfc1f 100644 --- a/sbin/bioctl/Makefile +++ b/sbin/bioctl/Makefile @@ -1,7 +1,8 @@ -# $OpenBSD: Makefile,v 1.5 2005/07/18 15:10:56 dlg Exp $ +# $OpenBSD: Makefile,v 1.6 2005/07/29 16:01:18 marco Exp $ PROG= bioctl -LDADD= -lutil +CFLAGS= -Wall +LDADD= -lutil MAN= bioctl.8 .include <bsd.prog.mk> diff --git a/sbin/bioctl/bioctl.8 b/sbin/bioctl/bioctl.8 index d6941144000..8ced3a82e83 100644 --- a/sbin/bioctl/bioctl.8 +++ b/sbin/bioctl/bioctl.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: bioctl.8,v 1.12 2005/07/18 15:10:56 dlg Exp $ +.\" $OpenBSD: bioctl.8,v 1.13 2005/07/29 16:01:18 marco Exp $ .\" .\" Copyright (c) 2004, 2005 Marco Peereboom .\" @@ -32,12 +32,9 @@ .Sh SYNOPSIS .Nm bioctl .Bk -words -.Op Fl Dehpt -.Op Fl a Ar function -.Op Fl b Ar function -.Op Fl l Ar device-list -.Op Fl u Ar function -.Fl d Ar device +.Op Fl Dhi +.Fl d Ar device | +.Fl f Ar device .Ek .Sh DESCRIPTION .Nm @@ -45,46 +42,21 @@ provides a generic interface for RAID management. .Pp The options are as follows: .Bl -tag -width Ds -.It Fl a Ar function -Get or set alarm state. -Supported functions are: silence/quiet, enable, disable, get, and test. -Or use the first letter of the function. -.It Fl b Ar function -Blink or unblink hard drive LED, if supported by the enclosure. -Supported functions are: blink, alarm (fault LED) and unblink. -Or use the first letter of the function. .It Fl D Enable debug output. .It Fl d Ar device Select RAID controller e.g ami0. -Use the -d option for controller operations. -.It Fl e -Enumerate drives. -.It Fl f Ar disk -Select disk device e.g sd0. -Use the -f option for disk operations. -Either -f or -d must be selected. +Use the -d option for controller operations that impact all disk devices. +.It Fl f Ar device +Select RAID disk e.g sd0. .It Fl h Online help. -.It Fl l Ar device-list -Device list to what the operation/function applies to. -The format is channel:target,channel:target etc. e.g. 0:1,1:3 -.It Fl p -Verify that adapter accepts bioctl commands. -This is a sort of a "device ping". -.It Fl t -Issue a pass-through function to -.Aq device-list . -Supported functions are: -read capacity, inquiry, and test unit ready (TUR). -Or use the first letter of the function name. -.It Fl u Ar function -Start or stop physical disk. -Supported functions are: go and stop. -Or use the first letter of the function. +.It Fl i +Depending on -d or -f enumerate all or only selected RAID device(s). .El .Sh SEE ALSO .Xr bio 4 , +.Xr ami 4 , .Xr scsi 4 .Sh HISTORY The diff --git a/sbin/bioctl/bioctl.c b/sbin/bioctl/bioctl.c index 1395715eb61..08bc98bfa4a 100644 --- a/sbin/bioctl/bioctl.c +++ b/sbin/bioctl/bioctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bioctl.c,v 1.15 2005/07/18 15:10:56 dlg Exp $ */ +/* $OpenBSD: bioctl.c,v 1.16 2005/07/29 16:01:18 marco Exp $ */ /* * Copyright (c) 2004, 2005 Marco Peereboom * All rights reserved. @@ -26,33 +26,27 @@ * */ -#include <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <util.h> - #include <sys/ioctl.h> #include <sys/param.h> #include <sys/queue.h> #include <scsi/scsi_disk.h> #include <scsi/scsi_all.h> -#include <scsi/scsi_ses.h> #include <dev/biovar.h> +#include <errno.h> +#include <err.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <util.h> + #include "bioctl.h" /* globals */ const char *bio_device = "/dev/bio"; -SLIST_HEAD(dev_list, dev); - -/* RAID card device list */ -struct dev_list devices = SLIST_HEAD_INITIALIZER(dev); -/* User provided device list*/ -struct dev_list ul = SLIST_HEAD_INITIALIZER(dev); - int devh = -1; int debug = 0; @@ -63,79 +57,37 @@ main(int argc, char *argv[]) { extern char *optarg; - bioc_capabilities bc; - bioc_alarm ba; + u_int64_t func = 0; + /* u_int64_t subfunc = 0; */ int ch; int rv; - unsigned char *pl; char *bioc_dev = NULL; char *sd_dev = NULL; char *realname = NULL; - char *al_arg = NULL; /* argument to alarm */ - char *ss_arg = NULL; /* argument to start/stop */ - char inq[INQSIZE]; - - struct dev *delm; - - u_int64_t func = 0, subfunc = 0; - u_int32_t devlist = 0; if (argc < 2) usage(); atexit(cleanup); - while ((ch = getopt(argc, argv, "a:b:Dd:ef:hl:pst:u:")) != -1) { + while ((ch = getopt(argc, argv, "Dd:f:hi")) != -1) { switch (ch) { - case 'a': /* alarm */ - func |= BIOC_ALARM; - al_arg = optarg; - break; - case 'b': /* LED blink/unblink */ - func |= BIOC_BLINK; - al_arg = optarg; - break; - - case 'D': /* enable debug */ + case 'D': /* debug */ debug = 1; break; - case 'd': /* device */ + case 'd': /* bio device */ bioc_dev = optarg; break; - case 'e': /* enumerate */ - func |= BIOC_SCSICMD; - subfunc |= F_ENUM; - break; - - case 'f': /* device */ + case 'f': /* scsi device */ sd_dev = optarg; break; - case 'l': /* device list, separated for now use one dev only*/ - func |= PARSELIST; - pl = optarg; - break; - - case 'p': /* ping */ - func |= BIOC_PING; - break; - - case 's': /* status */ - func |= BIOC_STATUS; - break; - - case 't': - func |= BIOC_SCSICMD; - subfunc |= parse_passthru(optarg); - break; - - case 'u': /* start/stop */ - func |= BIOC_STARTSTOP; - ss_arg = optarg; + case 'i': /* inquiry */ + func |= BIOC_INQ; break; case 'h': /* help/usage */ @@ -159,92 +111,18 @@ main(int argc, char *argv[]) if (rv == -1) errx(1, "Can't locate %s device via %s", bl.name, bio_device); - } - else if (sd_dev) { + } else if (sd_dev) { devh = opendev(sd_dev, O_RDWR, OPENDEV_PART, &realname); if (devh == -1) err(1, "Can't open %s", sd_dev); - } - else + } else errx(1, "need -d or -f parameter"); if (debug) warnx("cookie = %p", bl.cookie); - if (func & PARSELIST) - parse_devlist(pl); - - if (!bio_get_capabilities(&bc)) - warnx("could not retrieve capabilities."); - else { - /* we should have everything setup by now so get to work */ - if (func & BIOC_ALARM) - if (bc.ioctls & BIOC_ALARM) - bio_alarm(al_arg); - else - warnx("alarms are not supported."); - - if (func & BIOC_BLINK) - if (bc.ioctls & BIOC_BLINK) - SLIST_FOREACH(delm, &ul, next) { - bio_blink(al_arg, delm->channel, - delm->target); - } - else - warnx("blink is not supported."); - - if (func & BIOC_PING) - if (bc.ioctls & BIOC_PING) - bio_ping(); - else - warnx("ping not supported."); - - if (func & BIOC_STATUS) { - if (bc.ioctls & BIOC_STATUS) - bio_status(); - else - warnx("status function not supported."); - } - - if (func & BIOC_STARTSTOP) { - if (bc.ioctls & BIOC_STARTSTOP) { - SLIST_FOREACH(delm, &ul, next) { - bio_startstop(ss_arg, - delm->channel, delm->target); - } - } else - warnx("start/stop unit not supported."); - } - - if (func & BIOC_SCSICMD) { - if (bc.ioctls & BIOC_SCSICMD) { - if (subfunc & F_READCAP) { - SLIST_FOREACH(delm, &ul, next) { - bio_pt_readcap(delm->channel, - delm->target, F_NOISY); - } - } - - if (subfunc & F_INQUIRY) { - SLIST_FOREACH(delm, &ul, next) { - bio_pt_inquire(delm->channel, - delm->target, F_NOISY, - &inq[0]); - } - } - - if (subfunc & F_TUR) { - SLIST_FOREACH(delm, &ul, next) { - bio_pt_tur(delm->channel, - delm->target); - } - } - - if (subfunc & F_ENUM) - bio_pt_enum(); - } else - warnx("passthrough not supported."); - } + if (func & BIOC_INQ) { + bio_inq(); } return (0); @@ -255,9 +133,7 @@ usage(void) { extern char *__progname; - fprintf(stderr, "usage: %s [-Dehpt] [-a function] [-b function] " - "[-l device list]\n" - "\t[-u function] [-d device | -f disk]\n", __progname); + fprintf(stderr, "usage: %s [-Dhi] [-d device | -f disk]\n", __progname); exit(1); } @@ -265,855 +141,119 @@ usage(void) void cleanup(void) { - struct dev *delm; - if (debug) printf("atexit\n"); - while (devices.slh_first != NULL) { - delm = devices.slh_first; - SLIST_REMOVE_HEAD(&devices, next); - if (debug) - printf("free device: %p\n", delm); - free(delm); - } - - while (ul.slh_first != NULL) { - delm = ul.slh_first; - SLIST_REMOVE_HEAD(&ul, next); - if (debug) - printf("free ul: %p\n", delm); - free(delm); - } - if (devh != -1) close(devh); } -u_int64_t -parse_passthru(char *f) -{ - if (debug) - printf("get_subfunc: %s, ", f); - - switch (f[0]) { - case 'i': /* INQUIRY */ - if (debug) - printf("inquiry\n"); - return (F_INQUIRY); - - case 'e': /* ENUMERATE, not a pass through hmmm */ - if (debug) - printf("enumerate\n"); - return (F_ENUM); - - case 'r': /* READ CAPACITY */ - if (debug) - printf("read cap\n"); - return (F_READCAP); - - case 't': /* TUR */ - if (debug) - printf("TUR\n"); - return (F_TUR); - - default: - errx(1, "invalid pass through function"); - } -} - void -parse_devlist(char *dl) +bio_inq(void) { - u_int8_t c , t, done = 0; - char *es, *s; - struct dev *delm; + bioc_inq bi; + bioc_vol bv; + bioc_disk bd; - es = NULL; - s = dl; + int rv, i, d; - if (debug) - printf("parse: %s\n", dl); - - while (!done) { - c = strtol(s, &es, 10); - if (debug) - printf("%p %p %u %c\n", s, es, c, es[0]); - s = es; - if (es[0] == ':') { - s++; - t = strtol(s, &es, 10); - if (debug) - printf("%p %p %u %c\n", s, es, t, es[0]); - s = es; - - if (c > 4) - errx(1, "invalid channel number"); - if (t > 16) - errx(1, "invalid target number"); - - delm = malloc(sizeof(struct dev)); - if (!delm) - errx(1, "not enough memory"); - - delm->target = t; - delm->channel = c; - SLIST_INSERT_HEAD(&ul, delm, next); - } - if (es[0] == ',') { - s++; - continue; - } - if (es[0] == '\0') { - done = 1; - continue; - } - done = 2; - } - - if (done == 2) { - /* boink */ - errx(1, "invalid device list."); - } -} - -int -bio_get_capabilities(bioc_capabilities *bc) -{ - int rv; - - bc->cookie = bl.cookie; - rv = ioctl(devh, BIOCCAPABILITIES, bc); - if (rv == -1) { - warnx("Error calling bioc_ioctl() via bio_ioctl()"); - return 0; - } - - if (debug) { - printf("ioctls = %016llx\n", bc->ioctls); - printf("raid_types = %08lx\n", bc->raid_types); - } - - return (1); -} - -void -bio_alarm(char *arg) -{ - int rv; - bioc_alarm ba; + memset(&bi, 0, sizeof(bi)); if (debug) - printf("alarm in: %s, ", arg); - - ba.cookie = bl.cookie; - - switch (arg[0]) { - case 'q': /* silence alarm */ - /* FALLTHROUGH */ - case 's': - if (debug) - printf("silence\n"); - ba.opcode = BIOCSALARM_SILENCE; - break; - - case 'e': /* enable alarm */ - if (debug) - printf("enable\n"); - ba.opcode = BIOCSALARM_ENABLE; - break; - - case 'd': /* disable alarm */ - if (debug) - printf("disable\n"); - ba.opcode = BIOCSALARM_DISABLE; - break; - - case 't': /* test alarm */ - if (debug) - printf("test\n"); - ba.opcode = BIOCSALARM_TEST; - break; + printf("bio_inq\n"); - case 'g': /* get alarm state */ - if (debug) - printf("get state\n"); - ba.opcode = BIOCGALARM_STATE; - break; + bi.cookie = bl.cookie; - default: - warnx("invalid alarm function: %s", arg); - return; - } - - rv = ioctl(devh, BIOCALARM, &ba); + rv = ioctl(devh, BIOCINQ, &bi); if (rv == -1) { warnx("bioc_ioctl() call failed"); return; } - if (arg[0] == 'g') { - printf("alarm is currently %s\n", - ba.state ? "enabled" : "disabled"); - } -} - -void -ses_verbose(u_int8_t *rc, u_int8_t len) -{ - struct ses_config_page *scp; - struct ses_type_desc_hdr *tdh; - - char *str; - u_int8_t i; - - scp = (struct ses_config_page *)rc; - printf("element types: %d, id: %s\n", scp->nr_elem_typ, - scp->enc_vendor_id); - - str = (char *) - (&scp->enc_desc_len + scp->enc_desc_len + 1 + - (scp->nr_elem_typ * sizeof(struct ses_type_desc_hdr))); - - for (i = 0; i < scp->nr_elem_typ; i++) { - tdh = (struct ses_type_desc_hdr *) - (&scp->enc_desc_len + scp->enc_desc_len + 1 + - (i * sizeof(struct ses_type_desc_hdr))); - - printf("type: %d, count: %d, sub enclosure id: %d, " - "len: %d, text: %s\n", - tdh->elem_type, tdh->nr_elem, tdh->sub_enc_id, - tdh->type_desc_len, str); - - str += tdh->type_desc_len; - } -} + printf("RAID volumes : %d\n", bi.novol); + printf("Physical disks : %d\n\n", bi.nodisk); -void -bio_blink_userland(u_int8_t opc, u_int8_t c, u_int8_t t) -{ - struct dev *delm; - - /* page 1 stuff */ - struct ses_enc_ctrl_diag_page *cdp; - struct ses_config_page *scp; - struct ses_type_desc_hdr *tdh; - - /* page 2 stuff */ - struct ses_enc_stat_diag_page *esdp; - struct ses_dev_elmt_status_diag *desd; - - u_int8_t rc[SESSIZE]; - u_int8_t rc2[SESSIZE]; - u_int8_t i, elements, found = 0; - - /* FIXME if the raid controllers are clustered we might have more - * than one proc device. */ - - bio_pt_enum(); - - SLIST_FOREACH(delm, &devices, next) { - if (delm->channel != c) - continue; - - if (delm->type != T_PROCESSOR) - continue; - - if (debug) - printf("proc at channel: %d target: %2d\n", - delm->channel, delm->target); - - /* figure out what we have */ - if (!get_ses_page(delm->channel, delm->target, - SES_CFG_DIAG_PAGE, &rc[0], sizeof(rc))) { - return; - } - - if (debug) - ses_verbose(&rc[0], sizeof(rc)); - - /* find first disk element */ - elements = 0; - scp = (struct ses_config_page *)rc; - for (i = 0; i < scp->nr_elem_typ; i++) { - tdh = (struct ses_type_desc_hdr *) - (&scp->enc_desc_len + scp->enc_desc_len + 1 + - (i * sizeof(struct ses_type_desc_hdr))); - - if (tdh->elem_type == STDH_DEVICE) { - found = 1; - break; - } - elements += tdh->nr_elem; - } - - if (debug) { - printf("tdh->elem_type: %d, tdh->nr_elem: %d, " - "elements: %d\n", - tdh->elem_type, tdh->nr_elem, elements); - } - - if (!found) { - if (debug) - printf("no devices found\n"); - - return; - } - - /* get ses page so that we can modify bits for blink */ - if (!get_ses_page(delm->channel, delm->target, - SES_CTRL_DIAG_PAGE, &rc2[0], sizeof(rc2))) { - return; - } - - esdp = (struct ses_enc_stat_diag_page *)rc2; - desd = (struct ses_dev_elmt_status_diag *) - (esdp->elmts + elements); /* FIXME do we need padding? */ - - /* loop through all slots to see if target is available */ - found = 0; - for (i = 0; i < tdh->nr_elem; i++) { - if (debug) - printf("stat: %d, addr: %d, b3: %d, b4: %d\n", - desd->common_status, - desd->slot_addr, - desd->byte3, - desd->byte4); - - if (t == desd->slot_addr) { - found = 1; - break; - } - - desd += 1; /* next element */ - } - - if (!found) { - printf("target: %d not found\n", t); + for (i = 0; i < bi.novol; i++) { + memset(&bv, 0, sizeof(bv)); + bv.cookie = bl.cookie; + bv.volid = i; + rv = ioctl(devh, BIOCVOL, &bv); + if (rv == -1) { + warnx("bioc_ioctl() call failed"); return; } - cdp = (struct ses_enc_ctrl_diag_page *)rc2; - cdp->elmts[i].common_ctrl = SDECD_SELECT; - switch (opc) { - case BIOCSBLINK_ALERT: - cdp->elmts[i].byte4 = SDECD_RQST_FAULT; - cdp->elmts[i].byte3 = 0x00; + printf("\tvolume id: %d\n", bv.volid); + printf("\tstatus : "); + switch (bv.status) { + case BIOC_SVONLINE: + printf("%s\n", BIOC_SVONLINE_S); break; - case BIOCSBLINK_BLINK: - cdp->elmts[i].byte3 = SDECD_RQST_IDENT; - cdp->elmts[i].byte4 = 0x00; + case BIOC_SVOFFLINE: + printf("%s\n", BIOC_SVOFFLINE_S); break; - case BIOCSBLINK_UNBLINK: - cdp->elmts[i].byte3 = 0x00; - cdp->elmts[i].byte4 = 0x00; + case BIOC_SVDEGRADED: + printf("%s\n", BIOC_SVDEGRADED_S); break; + case BIOC_SVINVALID: default: - return; - } - - if (!set_ses_page(delm->channel, delm->target, - &rc2[0], sizeof(rc2))) { - return; - } - - return; /* done */ - } -} - -void -bio_blink(char * arg, u_int8_t c, u_int8_t t) -{ - int rv; - bioc_blink bb; - - if (debug) - printf("blink in: %s, ", arg); - - bb.cookie = bl.cookie; - - switch (arg[0]) { - case 'a': /* blink amber or alert led */ - if (debug) - printf("blink alert\n"); - bb.opcode = BIOCSBLINK_ALERT; - break; - - case 'b': /* blink hdd */ - if (debug) - printf("blink\n"); - bb.opcode = BIOCSBLINK_BLINK; - break; - - case 'u': /* unblink hdd */ - if (debug) - printf("unblink\n"); - bb.opcode = BIOCSBLINK_UNBLINK; - break; - - default: - warnx("invalid blink function: %s", arg); - return; - } - - rv = ioctl(devh, BIOCBLINK, &bb); - if (rv == -1) { - if (errno == EOPNOTSUPP) { - /* operation is not supported in kernel, do it here */ - if (debug) - printf("doing blink in userland\n"); - bio_blink_userland(bb.opcode, c, t); + printf("%s\n", BIOC_SVINVALID_S); } - else - warnx("bioc_ioctl() call failed"); - } -} - -void -bio_ping(void) -{ - int rv; - bioc_ping bp; - - bp.cookie = bl.cookie; - bp.x = 0; - rv = ioctl(devh, BIOCPING, &bp); - if (rv == -1) { - warnx("Error calling bioc_ioctl() via bio_ioctl()"); - return; - } - - printf("x after ioctl() = %i\n", bp.x); -} - -void -bio_startstop(char *arg, u_int8_t c, u_int8_t t) -{ - int rv; - bioc_startstop bs; - - if (debug) - printf("startstop in: %s, ", arg); - - bs.cookie = bl.cookie; - - switch (arg[0]) { - case 's': /* stop unit */ - if (debug) - printf("stop\n"); - bs.opcode = BIOCSUNIT_STOP; - break; - - case 'g': /* start or go unit */ - if (debug) - printf("start\n"); - bs.opcode = BIOCSUNIT_START; - break; - - default: - warnx("invalid start/stop function: %s", arg); - return; - } - - bs.channel = c; - bs.target = t; - - rv = ioctl(devh, BIOCSTARTSTOP, &bs); - if (rv == -1) { - warnx("bioc_ioctl() call failed"); - return; - } - - if (debug) - printf("startstop done\n"); -} - -/* get status, for now only do all */ -void -bio_status(void) -{ - int rv; - bioc_status bs; - - if (debug) - printf("status()\n"); - - bs.cookie = bl.cookie; - bs.opcode = BIOCGSTAT_ALL; - - rv = ioctl(devh, BIOCSTATUS, &bs); - if (rv == -1) { - warnx("bioc_ioctl() call failed"); - return; - } - - if (debug) - printf("status done\n"); -} - -/* read capacity for disk c,t */ -u_int64_t -bio_pt_readcap(u_int8_t c, u_int8_t t, u_int8_t flags) -{ - bioc_scsicmd bpt; - struct read_cap rc; - int rv; - u_int64_t size; - - memset(&bpt, 0, sizeof(bpt)); - bpt.cookie = bl.cookie; - bpt.channel = c; - bpt.target = t; - bpt.cdblen = 10; - bpt.cdb[0] = READ_CAPACITY; - bpt.data = &rc; /* set up return data pointer */ - bpt.datalen = sizeof(rc); - bpt.direction = BIOC_DIRIN; - bpt.senselen = 32; /* silly since the kernel overrides it */ - - rv = ioctl(devh, BIOCSCSICMD, &bpt); - if (rv == -1) { - warnx("READ CAPACITY failed %x", bpt.status); - return (0); - } - else if (bpt.status) { - if (bpt.sensebuf[0] == 0x70 || bpt.sensebuf[0] == 0x71) - print_sense(&bpt.sensebuf[0], bpt.senselen); - else - printf("channel: %d target: %2d READ CAPACITY failed " - "without sense data\n", c, t); - - return (0); - } - - rc.maxlba = betoh32(rc.maxlba); - rc.bsize = betoh32(rc.bsize); - - size = (u_int64_t)rc.maxlba * (u_int64_t)rc.bsize; - - if (debug) - printf("\nREAD CAPACITY: %lu * %lu = %llu\n", - rc.maxlba, rc.bsize, size); - - if (flags & F_NOISY) { - printf("channel: %d target: %2d READ CAPACITY %llu", c, t, - size); - print_cap(size); - printf("\n"); - } - - return (size); -} - - -/* inquire device */ -u_int32_t -bio_pt_inquire(u_int8_t c, u_int8_t t, u_int8_t flags, u_int8_t *inq) -{ - bioc_scsicmd bpt; - int rv, i; - - memset(&bpt, 0, sizeof(bpt)); - bpt.cookie = bl.cookie; - bpt.channel = c; - bpt.target = t; - bpt.cdblen = 6; - bpt.cdb[0] = INQUIRY; - bpt.cdb[4] = INQSIZE; /* LENGTH */ - bpt.data = inq; /* set up return data pointer */ - bpt.datalen = INQSIZE; /* minimum INQ size */ - bpt.direction = BIOC_DIRIN; - bpt.senselen = 32; /* silly since the kernel overrides it */ - - rv = ioctl(devh, BIOCSCSICMD, &bpt); - if (rv == -1) { - warnx("INQUIRY failed %x", bpt.status); - return 0; - } - else if (bpt.status) { - if (bpt.sensebuf[0] == 0x70 || bpt.sensebuf[0] == 0x71) - print_sense(&bpt.sensebuf[0], bpt.senselen); - else - if (flags & F_NOISY) - printf("device %d:%d did not respond to " - "INQUIRY command\n", c, t); - - return 0; - } - - printf("channel: %u target: %2u ", c, t); - print_inquiry(flags, inq, bpt.datalen); - - if (flags & F_NOISY) - printf("\n"); - - return 1; -} - -/* TUR for disk c,t */ -u_int32_t -bio_pt_tur(u_int8_t c, u_int8_t t) -{ - bioc_scsicmd bpt; - int rv; - - if (debug) - printf("tur\n"); - - memset(&bpt, 0, sizeof(bpt)); - bpt.cookie = bl.cookie; - bpt.channel = c; - bpt.target = t; - bpt.cdblen = 6; - bpt.cdb[0] = TEST_UNIT_READY; - bpt.direction = BIOC_DIRNONE; - rv = ioctl(devh, BIOCSCSICMD, &bpt); - if (rv == -1) { - warnx("passthrough failed"); - return (0); - } - - if (bpt.status) { - if (bpt.sensebuf[0] == 0x70 || bpt.sensebuf[0] == 0x71) - print_sense(&bpt.sensebuf[0], bpt.senselen); - else - printf("channel: %d target: %2d: TUR failed without " - "sense data\n", c, t); - - return (0); - } - - printf("channel: %d target: %2d: TUR completed\n", c, t); - - return (1); -} - - -/* enumerate all disks */ -void -bio_pt_enum(void) -{ - bioc_scsicmd bpt; - u_int32_t c, t, i, d; - int rv; - u_int8_t inq[INQSIZE]; - - struct dev *delm; - - d = 0; - for (c = 0; c < 4 /* FIXME */; c++) { - for (t = 0; t < 16 /* FIXME */; t++) { - if (bio_pt_inquire(c, t, F_SILENCE, &inq[0])) { - if (inq[0] & SID_QUAL) - continue; /* invalid device */ - - delm = malloc(sizeof(struct dev)); - if (delm == NULL) - errx(1, "not enough memory"); - delm->id = d++; - delm->target = t; - delm->channel = c; - delm->type = inq[0]; - if (delm->type == T_DIRECT) { - /* FIXME check the return value */ - delm->capacity = bio_pt_readcap( - delm->channel, delm->target, - F_SILENCE); - print_cap(delm->capacity); - } - printf("\n"); - - SLIST_INSERT_HEAD(&devices, delm, next); + printf("\tsize : %lld\n", bv.size); + printf("\traid : %d\n", bv.level); + printf("\tnr disks : %d\n", bv.nodisk); + + for (d = 0; d < bv.nodisk; d++) { + memset(&bd, 0, sizeof(bd)); + bd.cookie = bl.cookie; + bd.diskid = d; + bd.volid = i; + + rv = ioctl(devh, BIOCDISK, &bd); + if (rv == -1) { + warnx("bioc_ioctl() call failed"); + return; } - } /* for t */ - } /* for c */ -} -/* printf sense data */ -void -print_sense(u_int8_t *sensebuf, u_int8_t sensebuflen) -{ - u_int8_t i; - - if (debug) - printf("print_sense() %p, %u\n", sensebuf, sensebuflen); - - for (i = 0; i < sensebuflen; i++) { - printf("%02x ", sensebuf[i]); - } - printf("\n"); - - /* FIXME add some pretty decoding here */ -} - -void -print_inquiry(u_int8_t flags, u_int8_t *inq, u_int8_t inqlen) -{ - u_int8_t i; + printf("\t\tdisk id : %d\n", bd.diskid); + printf("\t\tstatus : "); + switch (bd.status) { + case BIOC_SDONLINE: + printf("%s\n", BIOC_SDONLINE_S); + break; - if (inqlen < INQSIZE) { - /* INQUIRY shall return at least 36 bytes */ - printf("invalid INQUIRY buffer size\n"); - return; - } + case BIOC_SDOFFLINE: + printf("%s\n", BIOC_SDOFFLINE_S); + break; - if (SID_QUAL & inq[0]) { - printf("invalid device\n"); - return; - } + case BIOC_SDFAILED: + printf("%s\n", BIOC_SDFAILED_S); + break; - switch (SID_TYPE & inq[0]) { - case T_DIRECT: - printf("disk "); - break; + case BIOC_SDREBUILD: + printf("%s\n", BIOC_SDREBUILD_S); + break; - case T_PROCESSOR: - printf("proc "); - break; + case BIOC_SDHOTSPARE: + printf("%s\n", BIOC_SDHOTSPARE_S); + break; - default: - printf("unsuported device type\n"); - return; - } + case BIOC_SDUNUSED: + printf("%s\n", BIOC_SDUNUSED_S); + break; - for (i = 0; i < inqlen; i++) { - if (i < 8) { - if ((flags & F_NOISY) || debug) - printf("%02x ", inq[i]); + case BIOC_SDINVALID: + default: + printf("%s\n", BIOC_SDINVALID_S); + } + printf("\t\tvolume id: %d\n", bd.volid); + printf("\t\tsize : %lld\n", bd.size); + printf("\t\tvendor : %s\n", bd.vendor); } - else - printf("%c", inq[i] < ' ' ? ' ' : inq[i]); - } -} - -void print_cap(u_int64_t cap) -{ - if (cap / S_TERA > 1) { - printf(" %3llu TB", cap / S_TERA); - return; - } - - if (cap / S_GIGA > 1) { - printf(" %3llu GB", cap / S_GIGA); - return; - } - - if (cap / S_MEGA > 1) { - printf(" %3llu MB", cap / S_MEGA); - return; - } - - if (cap / S_KILO > 1) { - printf(" %3llu MB", cap / S_KILO); - return; - } - - printf(" %llu B", cap); -} - -#if 0 - /* in case we want to do SAFTE this is the format */ - /* SAF-TE */ - memset(&bpt, 0, sizeof(bpt)); - bpt.cookie = bl.cookie; - bpt.channel = delm->channel; - bpt.target = delm->target; - bpt.cdblen = 10; - bpt.cdb[0] = 0x3c; /* READ BUFFER */ - bpt.cdb[1] = 0x01; /* SAF-TE command */ - bpt.cdb[8] = sizeof(rc); /* LSB size, FIXME */ - bpt.data = &rc[0]; /* set up return data pointer */ - bpt.datalen = sizeof(rc); - bpt.direction = BIOC_DIRIN; - bpt.senselen = 32; /* silly since the kernel overrides it */ -#endif - -int -get_ses_page(u_int8_t c, u_int8_t t, u_int8_t p, u_int8_t *buf, u_int8_t buflen) -{ - bioc_scsicmd bpt; - int rv; - - memset(&bpt, 0, sizeof(bpt)); - bpt.cookie = bl.cookie; - bpt.channel = c; - bpt.target = t; - bpt.cdblen = 6; - bpt.cdb[0] = RECEIVE_DIAGNOSTIC; - /* FIXME add this cdb struct + #defines to scsi_all.h */ - bpt.cdb[1] = 0x01; /* set PCV bit for SES commands */ - bpt.cdb[2] = p; /* SES page nr */ - bpt.cdb[4] = buflen; - bpt.data = buf; /* set up return data pointer */ - bpt.datalen = buflen; - bpt.direction = BIOC_DIRIN; - bpt.senselen = 32; /* silly since the kernel overrides it */ - - rv = ioctl(devh, BIOCSCSICMD, &bpt); - if (rv == -1) { - warnx("RECEIVE_DIAGNOSTIC failed %x", bpt.status); - return (0); - } - else if (bpt.status) { - if (bpt.sensebuf[0] == 0x70 || bpt.sensebuf[0] == 0x71) - print_sense(&bpt.sensebuf[0], bpt.senselen); - else - printf("channel: %d target: %2d RECEIVE_DIAGNOSTIC " - "failed without sense data\n", c, t); - - return (0); - } - - if (debug) { - /* abuse print sense a little */ - print_sense(buf, bpt.datalen); - } - - return (1); -} - -int -set_ses_page(u_int8_t c, u_int8_t t, u_int8_t *buf, u_int8_t buflen) -{ - bioc_scsicmd bpt; - int rv; - - memset(&bpt, 0, sizeof(bpt)); - bpt.cookie = bl.cookie; - bpt.channel = c; - bpt.target = t; - bpt.cdblen = 6; - bpt.cdb[0] = SEND_DIAGNOSTIC; - bpt.cdb[1] = SSD_PF; - bpt.cdb[4] = buflen; - bpt.data = buf; /* set up return data pointer */ - bpt.datalen = buflen; - bpt.direction = BIOC_DIROUT; - bpt.senselen = 32; /* silly since the kernel overrides it */ - - rv = ioctl(devh, BIOCSCSICMD, &bpt); - if (rv == -1) { - warnx("SEND_DIAGNOSTIC failed %x", bpt.status); - return (0); - } - else if (bpt.status) { - if (bpt.sensebuf[0] == 0x70 || bpt.sensebuf[0] == 0x71) - print_sense(&bpt.sensebuf[0], bpt.senselen); - else - printf("channel: %d target: %2d SEND_DIAGNOSTIC " - "failed without sense data\n", c, t); - - return (0); - } - - if (debug) { - /* abuse print sense a little */ - print_sense(buf, bpt.datalen); + printf("\n"); } - - return (1); } diff --git a/sbin/bioctl/bioctl.h b/sbin/bioctl/bioctl.h index 51131f79948..411c3ab67a4 100644 --- a/sbin/bioctl/bioctl.h +++ b/sbin/bioctl/bioctl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bioctl.h,v 1.8 2005/07/18 15:10:56 dlg Exp $ */ +/* $OpenBSD: bioctl.h,v 1.9 2005/07/29 16:01:18 marco Exp $ */ /* * Copyright (c) 2004, 2005 Marco Peereboom * All rights reserved. @@ -37,53 +37,9 @@ #define S_MEGA (1048576llu) #define S_KILO (1024llu) -/* functions */ -#define F_READCAP (0x01) -#define F_ENUM (0x02) -#define F_TUR (0x04) -#define F_INQUIRY (0x08) +void usage(void); +void cleanup(void); -/* flags */ -#define F_SILENCE (0x00) -#define F_NOISY (0x01) - -#define PARSELIST (0x8000000000000000llu) - -struct read_cap { - u_int32_t maxlba; - u_int32_t bsize; -}; - -struct dev { - SLIST_ENTRY(dev) next; - u_int16_t id; - u_int8_t channel; - u_int8_t target; - u_int8_t type; - u_int64_t capacity; -}; - -void usage(void); -void cleanup(void); -u_int64_t parse_passthru(char *); -void parse_devlist(char *); -void print_sense(u_int8_t *, u_int8_t); -void print_inquiry(u_int8_t, u_int8_t*, u_int8_t); -void print_cap(u_int64_t); -int get_ses_page(u_int8_t, u_int8_t, u_int8_t, u_int8_t*, u_int8_t); -int set_ses_page(u_int8_t, u_int8_t, u_int8_t*, u_int8_t); -void ses_verbose(u_int8_t *, u_int8_t); - -int bio_get_capabilities(bioc_capabilities *); -void bio_alarm(char *); -void bio_blink_userland(u_int8_t, u_int8_t, u_int8_t); -void bio_blink(char *, u_int8_t, u_int8_t); -void bio_ping(void); -void bio_startstop(char *, u_int8_t, u_int8_t); -void bio_status(void); -u_int64_t bio_pt_readcap(u_int8_t, u_int8_t, u_int8_t); -u_int32_t bio_pt_inquire(u_int8_t, u_int8_t, u_int8_t, u_int8_t *); -u_int32_t bio_pt_tur(u_int8_t, u_int8_t); -void bio_pt_enum(void); +void bio_inq(void); #endif /* _BIOCTL_H_ */ |