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 | |
parent | fe6ebae7b56098b265f77fe605c859f777c72443 (diff) |
Redo bioctl because initial implementation was too complex.
tested and ok dlg@ beck@
get it in @deraadt
-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 | ||||
-rw-r--r-- | sys/dev/biovar.h | 210 | ||||
-rw-r--r-- | sys/dev/ic/ami.c | 503 | ||||
-rw-r--r-- | sys/dev/ic/amireg.h | 8 | ||||
-rw-r--r-- | sys/dev/ic/amivar.h | 2 |
8 files changed, 444 insertions, 1434 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_ */ diff --git a/sys/dev/biovar.h b/sys/dev/biovar.h index 2fb76943011..d5f45aa85d5 100644 --- a/sys/dev/biovar.h +++ b/sys/dev/biovar.h @@ -1,7 +1,8 @@ -/* $OpenBSD: biovar.h,v 1.7 2005/07/18 15:10:57 dlg Exp $ */ +/* $OpenBSD: biovar.h,v 1.8 2005/07/29 16:01:29 marco Exp $ */ /* * Copyright (c) 2002 Niklas Hallqvist. All rights reserved. + * Copyright (c) 2005 Marco Peereboom. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -50,147 +51,78 @@ int bio_register(struct device *, int (*)(struct device *, u_long, /* RAID section */ -#define BIOC_MAX_CDB 16 -#define BIOC_MAX_SENSE 32 -#define BIOC_MAX_PHYSDISK 128 /* based on FC arrays */ -#define BIOC_MAX_VIRTDISK 128 /* based on FC arrays */ - -/* ioctl tunnel defines */ -/* SHALL be implemented */ -#define BIOCPING _IOWR('B', 32, bioc_ping) -typedef struct _bioc_ping { +#define BIOCINQ _IOWR('B', 32, bioc_inq) +typedef struct _bioc_inq { void *cookie; - int x; -} bioc_ping; -/* SHALL be implemented */ -#define BIOCCAPABILITIES _IOWR('B', 33, bioc_capabilities) -typedef struct _bioc_capabilities { - void *cookie; - u_int64_t ioctls; /* bit field, 1 ioctl supported */ -#define BIOC_PING 0x01 -#define BIOC_ALARM 0x02 -#define BIOC_PREP_REMOVAL 0x04 -#define BIOC_REBUILD 0x08 -#define BIOC_STATUS 0x10 -#define BIOC_SCSICMD 0x20 -#define BIOC_STARTSTOP 0x40 -#define BIOC_BLINK 0x80 - u_int32_t raid_types; /* bit field, 1 supported raid type */ -#define BIOC_RAID0 0x01 -#define BIOC_RAID1 0x02 -#define BIOC_RAID3 0x04 -#define BIOC_RAID5 0x08 -#define BIOC_RAID10 0x10 -#define BIOC_RAID01 0x20 -#define BIOC_RAID50 0x40 -} bioc_capabilities; - -/* OPTIONAL */ -#define BIOCALARM _IOWR('B', 34, bioc_alarm) -typedef struct _bioc_alarm { - void *cookie; - u_int32_t opcode; -#define BIOCSALARM_DISABLE 0x00 -#define BIOCSALARM_ENABLE 0x01 -#define BIOCSALARM_SILENCE 0x02 -#define BIOCGALARM_STATE 0x03 -#define BIOCSALARM_TEST 0x04 - u_int8_t state; /* only used with GET function */ -} bioc_alarm; - -/* OPTIONAL */ -#define BIOCSCSICMD _IOWR('B', 35, bioc_scsicmd) -typedef struct _bioc_scsicmd { - void *cookie; + int novol; /* nr of volumes */ + int nodisk; /* nr of total disks */ +} bioc_inq; - /* in (kernel centric) */ - u_int8_t channel; - u_int8_t target; - u_int8_t cdb[BIOC_MAX_CDB]; - u_int8_t cdblen; - u_int8_t direction; /* 0 = out, 1 = in, this is userland centric */ -#define BIOC_DIROUT 0x00 -#define BIOC_DIRIN 0x01 -#define BIOC_DIRNONE 0x02 - - /* out (kernel centric) */ - u_int8_t status; - u_int8_t sensebuf[BIOC_MAX_SENSE]; - u_int8_t senselen; - - /* in & out (kernel centric) */ - void *data; - u_int32_t datalen; /* going in it governs the maximum buffer size - going out it contains actual bytes transfered */ -} bioc_scsicmd; - -/* OPTIONAL */ -#define BIOCSTARTSTOP _IOWR('B', 36, bioc_startstop) -typedef struct _bioc_startstop { - void *cookie; - u_int8_t opcode; -#define BIOCSUNIT_START 0x00 -#define BIOCSUNIT_STOP 0x01 - u_int8_t channel; - u_int8_t target; -} bioc_startstop; - -/* SHALL be implemented */ -#define BIOCSTATUS _IOWR('B', 37, bioc_status) -typedef struct _bioc_status { +#define BIOCDISK _IOWR('B', 33, bioc_disk) +/* structure that represents a disk in a RAID volume */ +typedef struct _bioc_disk { void *cookie; - u_int8_t opcode; -#define BIOCGSTAT_CHANGE 0x00 /* any changes since last call? */ -#define BIOCGSTAT_ALL 0x01 /* get all status */ -#define BIOCGSTAT_PHYSDISK 0x02 /* get physical disk status only */ -#define BIOCGSTAT_VIRTDISK 0x03 /* get virtual disk status only */ -#define BIOCGSTAT_BATTERY 0x04 /* get battery status only */ -#define BIOCGSTAT_ENCLOSURE 0x05 /* get enclosure status only */ -#define BIOCGSTAT_TEMPERATURE 0x06 /* get temperature status only */ - u_int8_t status; /* global status flag */ -#define BIOC_STATOK 0x00 /* status is OK */ -#define BIOC_STATDEGRAD 0x01 /* status is degraded */ -#define BIOC_STATCRIT 0x02 /* status is critical */ -#define BIOC_STATBAT 0x04 /* something wrong with battery */ -#define BIOC_STATENC 0x08 /* something wrong with enclosure */ -#define BIOC_STATTEMP 0x10 /* something is over/under heating */ - /* return fields used per request define in opcode */ - u_int8_t channels; /* max channels */ - u_int8_t buswidth; /* max physical drives per channel */ - /* filled in when called with BIOCGSTAT_PHYSDISK set */ - u_int8_t pdcount; /* physical disk counter */ - u_int8_t physdisk[BIOC_MAX_PHYSDISK]; -#define BIOC_PDUNUSED 0x00 /* disk not present */ -#define BIOC_PDONLINE 0x01 /* disk present */ -#define BIOC_PDOFFLINE 0x02 /* disk present but offline */ -#define BIOC_PDINUSE 0x04 /* critical operation in progress */ - /* filled in when called with BIOCGSTAT_VIRTDISK set */ - u_int8_t vdcount; /* virtual disk counter */ - u_int8_t virtdisk[BIOC_MAX_VIRTDISK]; -#define BIOC_VDUNUSED 0x00 /* disk not present */ -#define BIOC_VDONLINE 0x01 /* disk present */ -#define BIOC_VDOFFLINE 0x02 /* disk present but offline */ -#define BIOC_VDINUSE 0x04 /* critical operation in progress */ - /* filled in when called with BIOCGSTAT_BATTERY set */ - u_int8_t batstat; /* battery status */ -#define BIOC_BATNOTPRES 0x00 /* battery not present */ -#define BIOC_BATMISSING 0x01 /* battery removed */ -#define BIOC_BATVOLTERR 0x02 /* battery low/high power */ -#define BIOC_BATTEMP 0x04 /* battery over/under temp*/ - /* NOTYET: encloure status & temperature status */ -} bioc_status; - -/* OPTIONAL */ -/* depending on the controller it is handled either in userland or in kernel */ -#define BIOCBLINK _IOWR('B', 38, bioc_blink) -typedef struct _bioc_blink { + + int volid; /* associate with volume, if -1 unused */ + int diskid; /* virtual disk id */ + int status; /* current status */ +#define BIOC_SDONLINE 0x00 +#define BIOC_SDONLINE_S "Online" +#define BIOC_SDOFFLINE 0x01 +#define BIOC_SDOFFLINE_S "Offline" +#define BIOC_SDFAILED 0x02 +#define BIOC_SDFAILED_S "Failed" +#define BIOC_SDREBUILD 0x03 +#define BIOC_SDREBUILD_S "Rebuild" +#define BIOC_SDHOTSPARE 0x04 +#define BIOC_SDHOTSPARE_S "Hot spare" +#define BIOC_SDUNUSED 0x05 +#define BIOC_SDUNUSED_S "Unused" +#define BIOC_SDINVALID 0xff +#define BIOC_SDINVALID_S "Invalid" + int resv; /* align */ + + quad_t size; /* size of the disk */ + + /* this is provided by the physical disks if suported */ + char vendor[8]; /* vendor string */ + char product[16]; /* product string */ + char revision[4]; /* revision string */ + char pad[4]; /* zero terminate in here */ + + /* XXX get this too? */ + /* serial number */ +} bioc_disk; + +#define BIOCVOL _IOWR('B', 34, bioc_vol) +/* structure that represents a RAID volume */ +typedef struct _bioc_vol { void *cookie; - u_int8_t opcode; -#define BIOCSBLINK_BLINK 0x00 -#define BIOCSBLINK_UNBLINK 0x01 -#define BIOCSBLINK_ALERT 0x02 - u_int8_t channel; - u_int8_t target; -} bioc_blink; + int volid; /* volume id */ + int resv1; /* for binary compatibility */ + int status; /* current status */ +#define BIOC_SVONLINE 0x00 +#define BIOC_SVONLINE_S "Online" +#define BIOC_SVOFFLINE 0x01 +#define BIOC_SVOFFLINE_S "Offline" +#define BIOC_SVDEGRADED 0x02 +#define BIOC_SVDEGRADED_S "Degraded" +#define BIOC_SVINVALID 0xff +#define BIOC_SVINVALID_S "Invalid" + int resv2; /* align */ + quad_t size; /* size of the disk */ + int level; /* raid level */ + int nodisk; /* nr of drives */ + + /* this is provided by the RAID card */ + char vendor[8]; /* vendor string */ + char product[16]; /* product string */ + char revision[4]; /* revision string */ + char pad[4]; /* zero terminate in here */ +} bioc_vol; + +#define BIOC_INQ 0x01 +#define BIOC_DISK 0x02 +#define BIOC_VOL 0x04 diff --git a/sys/dev/ic/ami.c b/sys/dev/ic/ami.c index 885a77eae3e..2a4075db29b 100644 --- a/sys/dev/ic/ami.c +++ b/sys/dev/ic/ami.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ami.c,v 1.48 2005/07/18 15:10:56 dlg Exp $ */ +/* $OpenBSD: ami.c,v 1.49 2005/07/29 16:01:30 marco Exp $ */ /* * Copyright (c) 2001 Michael Shalayeff @@ -136,11 +136,13 @@ void ami_copy_internal_data(struct scsi_xfer *xs, void *v, size_t size); int ami_inquire(struct ami_softc *sc, u_int8_t op); #if NBIO > 0 +int ami_mgmt(struct ami_softc *, u_int8_t, u_int8_t, u_int8_t, + size_t, void *); +int ami_drv_inq(struct ami_softc *, u_int8_t, u_int8_t, void *); int ami_ioctl(struct device *, u_long, caddr_t); -int ami_ioctl_alarm(struct ami_softc *, bioc_alarm *); -int ami_ioctl_startstop( struct ami_softc *, bioc_startstop *); -int ami_ioctl_status( struct ami_softc *, bioc_status *); -int ami_ioctl_passthru(struct ami_softc *, bioc_scsicmd *); +int ami_ioctl_inq(struct ami_softc *, bioc_inq *); +int ami_ioctl_vol(struct ami_softc *, bioc_vol *); +int ami_ioctl_disk(struct ami_softc *, bioc_disk *); #endif /* NBIO > 0 */ struct ami_ccb * @@ -1680,6 +1682,7 @@ ami_scsi_ioctl(struct scsi_link *link, u_long cmd, caddr_t addr, int flag, struct proc *p) { struct ami_softc *sc = (struct ami_softc *)link->adapter_softc; + /* u_int8_t target = link->target; */ if (sc->sc_ioctl) return (sc->sc_ioctl(link->adapter_softc, cmd, addr)); @@ -1694,11 +1697,11 @@ ami_ioctl(dev, cmd, addr) u_long cmd; caddr_t addr; { - int error = 0; struct ami_softc *sc = (struct ami_softc *)dev; ami_lock_t lock; + int error = 0; - /* FIXME do we need to test for sc_dis_poll? */ + AMI_DPRINTF(AMI_D_IOCTL, ("%s: ioctl ", sc->sc_dev.dv_xname)); if (sc->sc_flags & AMI_BROKEN) return ENODEV; /* can't do this to broken device for now */ @@ -1710,11 +1713,9 @@ ami_ioctl(dev, cmd, addr) } switch (cmd) { - case BIOCALARM: - case BIOCBLINK: - case BIOCSTARTSTOP: - case BIOCSTATUS: - case BIOCSCSICMD: + case BIOCINQ: + case BIOCVOL: + case BIOCDISK: sc->sc_flags |= AMI_CMDWAIT; while (!TAILQ_EMPTY(&sc->sc_ccbq)) if (tsleep(&sc->sc_free_ccb, PRIBIO, "ami_ioctl", @@ -1723,51 +1724,19 @@ ami_ioctl(dev, cmd, addr) } switch (cmd) { - case BIOCPING: - ((bioc_ping *)addr)->x++; - - AMI_DPRINTF(AMI_D_IOCTL, ("%s: biocping: %x\n", - sc->sc_dev.dv_xname, ((bioc_ping *)addr)->x)); - break; - - case BIOCCAPABILITIES: - ((bioc_capabilities *)addr)->ioctls = - BIOC_ALARM | BIOC_PING | BIOC_SCSICMD | BIOC_STARTSTOP | - BIOC_STATUS | BIOC_BLINK; - - ((bioc_capabilities *)addr)->raid_types = - BIOC_RAID0 | BIOC_RAID1 | BIOC_RAID5 | - BIOC_RAID10 | BIOC_RAID50; - - AMI_DPRINTF(AMI_D_IOCTL, ("%s: bioccapabilities: ioctls: " - "%016llx raid_types: %08lx\n", - sc->sc_dev.dv_xname, - ((bioc_capabilities *)addr)->ioctls, - ((bioc_capabilities *)addr)->raid_types)); - break; - - case BIOCALARM: - error = ami_ioctl_alarm(sc, (bioc_alarm *)addr); - break; - - case BIOCBLINK: - error = EOPNOTSUPP; /* let userland land knows it must issue - * a cdb to handle blinking. */ + case BIOCINQ: + AMI_DPRINTF(AMI_D_IOCTL, ("inq ")); + error = ami_ioctl_inq(sc, (bioc_inq *)addr); break; - case BIOCSTARTSTOP: - AMI_DPRINTF(AMI_D_IOCTL, ("start stop unit\n")); - error = ami_ioctl_startstop(sc, (bioc_startstop *)addr); + case BIOCVOL: + AMI_DPRINTF(AMI_D_IOCTL, ("vol ")); + error = ami_ioctl_vol(sc, (bioc_vol *)addr); break; - case BIOCSTATUS: - AMI_DPRINTF(AMI_D_IOCTL, ("status\n")); - error = ami_ioctl_status(sc, (bioc_status *)addr); - break; - - case BIOCSCSICMD: - AMI_DPRINTF(AMI_D_IOCTL, ("scsi cmd\n")); - error = ami_ioctl_passthru(sc, (bioc_scsicmd *)addr); + case BIOCDISK: + AMI_DPRINTF(AMI_D_IOCTL, ("disk ")); + error = ami_ioctl_disk(sc, (bioc_disk *)addr); break; default: @@ -1785,290 +1754,324 @@ ami_ioctl(dev, cmd, addr) } int -ami_ioctl_alarm(sc, ra) +ami_drv_inq(sc, ch, tg, inqbuf) struct ami_softc *sc; - bioc_alarm *ra; + u_int8_t ch; + u_int8_t tg; + void *inqbuf; { - int error = 0; - struct ami_ccb *ccb; + struct ami_ccb *ccb; struct ami_iocmd *cmd; - void *idata; + struct ami_passthrough *ps; + struct scsi_inquiry_data *pp; + void *idata; bus_dmamap_t idatamap; bus_dma_segment_t idataseg[1]; paddr_t pa; - u_int8_t *p; - + int error = 0; - if (!(idata = ami_allocmem(sc->dmat, &idatamap, idataseg, - NBPG, 1, "ioctl data"))) { - ami_freemem(sc->dmat, &idatamap, idataseg, - NBPG, 1, "ioctl data"); - return ENOMEM; + if (!(idata = ami_allocmem(sc->dmat, &idatamap, idataseg, NBPG, 1, + "ami mgmt"))) { + error = ENOMEM; + goto bail; } pa = idataseg[0].ds_addr; - p = idata; + ps = idata; + pp = idata + sizeof *ps; ccb = ami_get_ccb(sc); ccb->ccb_data = NULL; cmd = ccb->ccb_cmd; - cmd->acc_cmd = AMI_ALARM; - cmd->acc_io.aio_channel = 0; - cmd->acc_io.aio_param = 0; - cmd->acc_io.aio_data = htole32(pa); - - switch(ra->opcode) { - case BIOCSALARM_DISABLE: - *p = AMI_ALARM_OFF; - break; - - case BIOCSALARM_ENABLE: - *p = AMI_ALARM_ON; - break; - - case BIOCSALARM_SILENCE: - *p = AMI_ALARM_QUIET; - break; - - case BIOCGALARM_STATE: - *p = AMI_ALARM_GET; - break; + cmd->acc_cmd = AMI_PASSTHRU; + cmd->acc_passthru.apt_data = htole32(pa); - case BIOCSALARM_TEST: - *p = AMI_ALARM_TEST; - break; + memset(ps, 0, sizeof *ps); - default: - AMI_DPRINTF(AMI_D_IOCTL, ("%s: biocalarm invalid opcode %x\n", - sc->sc_dev.dv_xname, ra->opcode)); - ami_put_ccb(ccb); - return EINVAL; - } + ps->apt_channel = ch; + ps->apt_target = tg; + ps->apt_ncdb = sizeof(struct scsi_inquiry); + ps->apt_nsense = sizeof(struct scsi_sense_data); - AMI_DPRINTF(AMI_D_IOCTL, ("%s: biocalarm: in: %x ", - sc->sc_dev.dv_xname, *p)); + ps->apt_cdb[0] = INQUIRY; + ps->apt_cdb[1] = 0; + ps->apt_cdb[2] = 0; + ps->apt_cdb[3] = 0; + ps->apt_cdb[4] = sizeof(struct scsi_inquiry_data); /* INQUIRY length */ + ps->apt_cdb[5] = 0; + ps->apt_data = htole32(pa + sizeof *ps); + ps->apt_datalen = sizeof(struct scsi_inquiry_data); - if (ami_cmd(ccb, BUS_DMA_WAITOK, 1) == 0) { - AMI_DPRINTF(AMI_D_IOCTL, ("out %x\n", *p)); - if (ra->opcode == BIOCGALARM_STATE) - ra->state = *p; - else - ra->state = 0; - } - else { - AMI_DPRINTF(AMI_D_IOCTL, ("failed\n")); + if (ami_cmd(ccb, BUS_DMA_WAITOK, 1) == 0) + memcpy(inqbuf, pp, sizeof(struct scsi_inquiry_data)); + else error = EINVAL; - } - ami_freemem(sc->dmat, &idatamap, idataseg, NBPG, 1, "ioctl data"); +bail: + ami_freemem(sc->dmat, &idatamap, idataseg, NBPG, 1, "ami mgmt"); return (error); } int -ami_ioctl_startstop(sc, bs) +ami_mgmt(sc, opcode, par1, par2, size, buffer) struct ami_softc *sc; - bioc_startstop *bs; + u_int8_t opcode; + u_int8_t par1; + u_int8_t par2; + size_t size; + void *buffer; { - int error = 0; - struct ami_ccb *ccb; + struct ami_ccb *ccb; struct ami_iocmd *cmd; + void *idata; + bus_dmamap_t idatamap; + bus_dma_segment_t idataseg[1]; + paddr_t pa; + int error = 0; + + if (!(idata = ami_allocmem(sc->dmat, &idatamap, idataseg, NBPG, + (size / NBPG) + 1, "ami mgmt"))) { + error = ENOMEM; + goto bail; + } + + pa = idataseg[0].ds_addr; ccb = ami_get_ccb(sc); ccb->ccb_data = NULL; cmd = ccb->ccb_cmd; - AMI_DPRINTF(AMI_D_IOCTL, ("start/stop %d unit %d %d\n", - bs->opcode, bs->channel, bs->target)); + cmd->acc_cmd = opcode; + cmd->acc_io.aio_channel = par1; + cmd->acc_io.aio_param = par2; + cmd->acc_io.aio_data = htole32(pa); - if (bs->opcode == BIOCSUNIT_START) - cmd->acc_cmd = AMI_STARTU; - else if (bs->opcode == BIOCSUNIT_STOP) - cmd->acc_cmd = AMI_STOPU; + if (ami_cmd(ccb, BUS_DMA_WAITOK, 1) == 0) + memcpy(buffer, idata, size); else - return EINVAL; - - /* FIXME test if channel and target are in range */ - cmd->acc_io.aio_channel = bs->channel; - cmd->acc_io.aio_param = bs->target; - cmd->acc_io.aio_pad[0] = AMI_STARTU_SYNC; - cmd->acc_io.aio_data = NULL; - - if (ami_cmd(ccb, BUS_DMA_WAITOK, 1) == 0) { - AMI_DPRINTF(AMI_D_IOCTL, ("%s\n", - bs->opcode == BIOCSUNIT_START ? "started" : "stopped")); - } - else { - AMI_DPRINTF(AMI_D_IOCTL, ("failed\n")); error = EINVAL; - } + +bail:; + ami_freemem(sc->dmat, &idatamap, idataseg, NBPG, (size / NBPG) + 1, + "ami mgmt"); return (error); } int -ami_ioctl_status(sc, bs) +ami_ioctl_inq(sc, bi) struct ami_softc *sc; - bioc_status *bs; + bioc_inq *bi; { + char plist[AMI_BIG_MAX_PDRIVES]; + struct ami_big_diskarray *p; /* struct too large for stack */ + int i, s, t; + int off; int error = 0; - struct ami_ccb *ccb; - struct ami_iocmd *cmd; - void *idata; - bus_dmamap_t idatamap; - bus_dma_segment_t idataseg[1]; - paddr_t pa; - u_int8_t *p; - if (!(idata = ami_allocmem(sc->dmat, &idatamap, idataseg, - NBPG, 1, "ioctl data"))) { - ami_freemem(sc->dmat, &idatamap, idataseg, - NBPG, 1, "ioctl data"); - return ENOMEM; + p = malloc(sizeof *p, M_DEVBUF, M_NOWAIT); + if (!p) { + printf("%s: no memory for raw interface\n",sc->sc_dev.dv_xname); + return (ENOMEM); } - pa = idataseg[0].ds_addr; - p = idata; + if (ami_mgmt(sc, AMI_FCOP, AMI_FC_RDCONF, 0, sizeof *p, p)) { + error = EINVAL; + goto bail; + } - ccb = ami_get_ccb(sc); - ccb->ccb_data = NULL; - cmd = ccb->ccb_cmd; + memset(plist, 0, sizeof plist); - cmd->acc_cmd = AMI_FCOP; - cmd->acc_io.aio_channel = AMI_FC_EINQ3; - cmd->acc_io.aio_param = AMI_FC_EINQ3_SOLICITED_FULL; - cmd->acc_io.aio_data = htole32(pa); + bi->novol = p->ada_nld; + bi->nodisk = 0; - AMI_DPRINTF(AMI_D_IOCTL, ("status %d\n", bs->opcode)); + /* do we actually care how many disks we have at this point? */ + for (i = 0; i < p->ada_nld; i++) + for (s = 0; s < p->ald[i].adl_spandepth; s++) + for (t = 0; t < p->ald[i].adl_nstripes; t++) { + off = p->ald[i].asp[s].adv[t].add_channel * + AMI_MAX_TARGET + + p->ald[i].asp[s].adv[t].add_target; - if (ami_cmd(ccb, BUS_DMA_WAITOK, 1) == 0) { - AMI_DPRINTF(AMI_D_IOCTL, ("success\n")); - } - else { - AMI_DPRINTF(AMI_D_IOCTL, ("failed\n")); - error = EINVAL; - } + if (!plist[off]) { + plist[off] = 1; + bi->nodisk++; + + } + } - ami_freemem(sc->dmat, &idatamap, idataseg, NBPG, 1, "ioctl data"); +bail: + free(p, M_DEVBUF); return (error); } int -ami_ioctl_passthru(sc, bp) +ami_ioctl_vol(sc, bv) struct ami_softc *sc; - bioc_scsicmd *bp; + bioc_vol *bv; { + struct ami_big_diskarray *p; /* struct too large for stack */ + int i, s, t; int error = 0; - struct ami_ccb *ccb; - struct ami_iocmd *cmd; - struct ami_passthrough *ps; - void *idata; - bus_dmamap_t idatamap; - bus_dma_segment_t idataseg[1]; - paddr_t pa; -#ifdef AMI_DEBUG - u_int8_t i = 0; -#endif /* AMI_DEBUG */ + p = malloc(sizeof *p, M_DEVBUF, M_NOWAIT); + if (!p) { + printf("%s: no memory for raw interface\n",sc->sc_dev.dv_xname); + return (ENOMEM); + } - AMI_DPRINTF(AMI_D_IOCTL, ("in passthrough\n")); + if (ami_mgmt(sc, AMI_FCOP, AMI_FC_RDCONF, 0, sizeof *p, p)) { + error = EINVAL; + goto bail; + } - /* FIXME: validate channel/target pair, or let the firmware bomb it? - */ + if (bv->volid > p->ada_nld) { + error = EINVAL; + goto bail; + } - if (bp->cdblen > BIOC_MAX_CDB) - return (EINVAL); + i = bv->volid; - if (bp->direction == BIOC_DIRIN && - (bp->datalen == 0 || bp->data == NULL)) - /* if userland expects data give us a len and a pointer */ - return (EINVAL); + switch (p->ald[i].adl_status) { + case AMI_RDRV_OFFLINE: + bv->status = BIOC_SVOFFLINE; + break; - if (bp->datalen > 1024) - return (EINVAL); /* cap at 1k for now */ + case AMI_RDRV_DEGRADED: + bv->status = BIOC_SVDEGRADED; + break; - if (!(idata = ami_allocmem(sc->dmat, &idatamap, idataseg, - NBPG, 1, "ioctl data"))) { - ami_freemem(sc->dmat, &idatamap, idataseg, - NBPG, 1, "ioctl data"); - return (ENOMEM); + case AMI_RDRV_OPTIMAL: + bv->status = BIOC_SVONLINE; + break; + + default: + bv->status = BIOC_SVINVALID; } - pa = idataseg[0].ds_addr; - ps = idata; + bv->size = 0; + bv->level = p->ald[i].adl_raidlvl; + bv->nodisk = 0; - ccb = ami_get_ccb(sc); - ccb->ccb_data = NULL; - cmd = ccb->ccb_cmd; + for (s = 0; s < p->ald[i].adl_spandepth; s++) { + for (t = 0; t < p->ald[i].adl_nstripes; t++) + bv->nodisk++; - cmd->acc_cmd = AMI_PASSTHRU; - cmd->acc_passthru.apt_data = htole32(pa); + switch (bv->level) { + case 0: + bv->size += p->ald[i].asp[s].ads_length * + p->ald[i].adl_nstripes; + break; - memset(ps, 0, sizeof *ps); + case 1: + bv->size += p->ald[i].asp[s].ads_length; + break; - ps->apt_channel = bp->channel; - ps->apt_target = bp->target; - ps->apt_ncdb = bp->cdblen; - ps->apt_nsense = BIOC_MAX_SENSE; /* do not let userland dictate this */ - memcpy(&ps->apt_cdb[0], &bp->cdb[0], bp->cdblen); + case 5: + bv->size += p->ald[i].asp[s].ads_length * + (p->ald[i].adl_nstripes - 1); + break; + } + } - ps->apt_data = htole32(pa + sizeof *ps); - ps->apt_datalen = bp->datalen; + if (p->ald[i].adl_spandepth > 1) + bv->level *= 10; - if (bp->direction == BIOC_DIROUT) { - /* userland sent us some data */ - copyin(bp->data, idata + sizeof *ps, ps->apt_datalen); - } + bv->size *= (quad_t)512; -#ifdef AMI_DEBUG - AMI_DPRINTF(AMI_D_IOCTL, ("%s: ps->apt_channel: %x, ps->apt_target: %x " - "ps->apt_cdblen: %x ps->apt_data: %x ps->apt_datalen: %x\n%s: cdb: " - , sc->sc_dev.dv_xname, ps->apt_channel, ps->apt_target, - ps->apt_ncdb, ps->apt_data, ps->apt_datalen, sc->sc_dev.dv_xname)); +bail: + free(p, M_DEVBUF); + + return (error); +} + +int +ami_ioctl_disk(sc, bd) + struct ami_softc *sc; + bioc_disk *bd; +{ + struct scsi_inquiry_data inqbuf; + struct ami_big_diskarray *p; /* struct too large for stack */ + int i, s, t, d; + int off; + int error = 0; - for (i = 0; i < ps->apt_ncdb; i++) { - printf("%0x ", ps->apt_cdb[i]); + p = malloc(sizeof *p, M_DEVBUF, M_NOWAIT); + if (!p) { + printf("%s: no memory for raw interface\n",sc->sc_dev.dv_xname); + return (ENOMEM); } - printf("\n"); -#endif /* AMI_DEBUG */ - if (ami_cmd(ccb, BUS_DMA_WAITOK, 1) == 0) { - AMI_DPRINTF(AMI_D_IOCTL, ("cdb issued\n")); - if (bp->direction == BIOC_DIRIN) { - /* userland expects data */ - bp->datalen = ps->apt_datalen; - AMI_DPRINTF(AMI_D_IOCTL, ("%s: passthrough %x\n", - sc->sc_dev.dv_xname, ps->apt_datalen)); - copyout(idata + sizeof *ps, bp->data, ps->apt_datalen); - } + if (ami_mgmt(sc, AMI_FCOP, AMI_FC_RDCONF, 0, sizeof *p, p)) { + error = EINVAL; + goto bail; } - else { - /* copy sense data back to user space */ - memcpy(&bp->sensebuf[0], &ps->apt_sense[0], ps->apt_nsense); - bp->senselen = ps->apt_nsense; - /* - * this needs to be checked in userland since error can't - * be set. Setting it prevents it from being coppied back to - * userland - */ - bp->status = 1; -#ifdef AMI_DEBUG - AMI_DPRINTF(AMI_D_IOCTL, ("%s: passthrough failed %x %x\n%s: ", - sc->sc_dev.dv_xname, bp->status, bp->senselen, - sc->sc_dev.dv_xname)); + if (bd->volid > p->ada_nld) { + error = EINVAL; + goto bail; + } - for (i = 0; i < bp->senselen; i++) - printf("%0x ", bp->sensebuf[i]); + i = bd->volid; + error = EINVAL; - printf("\n"); -#endif /* AMI_DEBUG */ + for (s = 0, d = 0; s < p->ald[i].adl_spandepth; s++) { + for (t = 0; t < p->ald[i].adl_nstripes; t++) { + if (d != bd->diskid) { + d++; + continue; + } + + off = p->ald[i].asp[s].adv[t].add_channel * + AMI_MAX_TARGET + + p->ald[i].asp[s].adv[t].add_target; + + switch (p->apd[off].adp_ostatus) { + case AMI_PD_UNCNF: + bd->status = BIOC_SDUNUSED; + break; + + case AMI_PD_ONLINE: + bd->status = BIOC_SDONLINE; + break; + + case AMI_PD_FAILED: + bd->status = BIOC_SDFAILED; + break; + + case AMI_PD_RBLD: + bd->status = BIOC_SDREBUILD; + break; + + case AMI_PD_HOTSPARE: + bd->status = BIOC_SDHOTSPARE; + break; + + default: + bd->status = BIOC_SDINVALID; + } + + bd->size = (quad_t)p->apd[off].adp_size * (quad_t)512; + + if (!ami_drv_inq(sc, + (p->ald[i].asp[s].adv[t].add_target >> 4), + (p->ald[i].asp[s].adv[t].add_target & 0x0f), + &inqbuf)) { + strlcpy(bd->vendor, inqbuf.vendor, + 8 + 16 + 4 + 1); /* vendor prod rev zero */ + } + + error = 0; + goto bail; + } } - ami_freemem(sc->dmat, &idatamap, idataseg, NBPG, 1, "ioctl data"); +bail: + free(p, M_DEVBUF); return (error); } diff --git a/sys/dev/ic/amireg.h b/sys/dev/ic/amireg.h index 84841c2aea8..bb77476191c 100644 --- a/sys/dev/ic/amireg.h +++ b/sys/dev/ic/amireg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: amireg.h,v 1.17 2005/07/18 15:10:57 dlg Exp $ */ +/* $OpenBSD: amireg.h,v 1.18 2005/07/29 16:01:30 marco Exp $ */ /* * Copyright (c) 2000 Michael Shalayeff @@ -223,6 +223,8 @@ #define AMI_HSPDIAG 0xb1 #define AMI_GESENSEINFO 0xb2 /* get extended sense info */ #define AMI_SYSFLUSH 0xfe /* flush system */ +/* this needs to be removed when the new bioctl goes in */ +#define AMI_GETINQ 0xcf /* get proc & drive inquiry data */ #define AMI_ALARM 0x51 /* alarm functions */ #define AMI_ALARM_OFF 0x00 #define AMI_ALARM_ON 0x01 @@ -570,6 +572,7 @@ struct ami_diskarray { struct ami_big_diskarray { u_int8_t ada_nld; u_int8_t ada_pad[3]; +#define ald ada_ldrv struct { u_int8_t adl_spandepth; u_int8_t adl_raidlvl; @@ -579,15 +582,18 @@ struct ami_big_diskarray { u_int8_t adl_wrpolicy; u_int8_t adl_directio; u_int8_t adl_nstripes; +#define asp adl_spans struct { u_int32_t ads_start; u_int32_t ads_length; /* blocks */ +#define adv ads_devs struct { u_int8_t add_channel; u_int8_t add_target; } ads_devs[AMI_BIG_MAX_DEVDEPTH]; } adl_spans[AMI_BIG_MAX_SPANDEPTH]; } ada_ldrv[AMI_BIG_MAX_LDRIVES]; +#define apd ada_pdrv struct { u_int8_t adp_type; /* SCSI device type */ u_int8_t adp_ostatus; /* status during config */ diff --git a/sys/dev/ic/amivar.h b/sys/dev/ic/amivar.h index 68edd84a843..49197359608 100644 --- a/sys/dev/ic/amivar.h +++ b/sys/dev/ic/amivar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: amivar.h,v 1.13 2005/07/18 15:10:57 dlg Exp $ */ +/* $OpenBSD: amivar.h,v 1.14 2005/07/29 16:01:30 marco Exp $ */ /* * Copyright (c) 2001 Michael Shalayeff |