diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2005-07-18 15:10:58 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2005-07-18 15:10:58 +0000 |
commit | 69c687924e0aac6b65efd331cab86c86bfb61fc4 (patch) | |
tree | 4940df3520abad4620c539904122cae61ba9c405 | |
parent | 266c19464df004208d3eb2fc4d421579a43b28cd (diff) |
revert marcos bio changes, mickey not ok
-rw-r--r-- | sbin/bioctl/Makefile | 5 | ||||
-rw-r--r-- | sbin/bioctl/bioctl.8 | 55 | ||||
-rw-r--r-- | sbin/bioctl/bioctl.c | 1018 | ||||
-rw-r--r-- | sbin/bioctl/bioctl.h | 52 | ||||
-rw-r--r-- | sys/dev/biovar.h | 187 | ||||
-rw-r--r-- | sys/dev/ic/ami.c | 481 | ||||
-rw-r--r-- | sys/dev/ic/amireg.h | 4 | ||||
-rw-r--r-- | sys/dev/ic/amivar.h | 3 |
8 files changed, 1198 insertions, 607 deletions
diff --git a/sbin/bioctl/Makefile b/sbin/bioctl/Makefile index 8c28a82ef3c..aed3cb91772 100644 --- a/sbin/bioctl/Makefile +++ b/sbin/bioctl/Makefile @@ -1,8 +1,7 @@ -# $OpenBSD: Makefile,v 1.4 2005/07/18 01:29:19 marco Exp $ +# $OpenBSD: Makefile,v 1.5 2005/07/18 15:10:56 dlg Exp $ PROG= bioctl -CFLAGS= -Wall -LDADD= -lutil +LDADD= -lutil MAN= bioctl.8 .include <bsd.prog.mk> diff --git a/sbin/bioctl/bioctl.8 b/sbin/bioctl/bioctl.8 index 0368ac2eabf..d6941144000 100644 --- a/sbin/bioctl/bioctl.8 +++ b/sbin/bioctl/bioctl.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: bioctl.8,v 1.11 2005/07/18 14:34:41 jmc Exp $ +.\" $OpenBSD: bioctl.8,v 1.12 2005/07/18 15:10:56 dlg Exp $ .\" .\" Copyright (c) 2004, 2005 Marco Peereboom .\" @@ -32,9 +32,12 @@ .Sh SYNOPSIS .Nm bioctl .Bk -words -.Op Fl Dhi -.Fl d Ar device | -.Fl f Ar device +.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 .Ek .Sh DESCRIPTION .Nm @@ -42,25 +45,45 @@ 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 the RAID controller e.g. ami0. -Use this option for controller operations that impact all disk devices. -.It Fl f Ar device -Select the RAID disk e.g. sd0. +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. .It Fl h Online help. -.It Fl i -Depending on whether the -.Fl d -or -.Fl f -option was selected, -enumerate all or only the selected RAID device(s). +.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. .El .Sh SEE ALSO -.Xr ami 4 , .Xr bio 4 , .Xr scsi 4 .Sh HISTORY diff --git a/sbin/bioctl/bioctl.c b/sbin/bioctl/bioctl.c index d3067e1d739..1395715eb61 100644 --- a/sbin/bioctl/bioctl.c +++ b/sbin/bioctl/bioctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bioctl.c,v 1.14 2005/07/18 14:34:41 jmc Exp $ */ +/* $OpenBSD: bioctl.c,v 1.15 2005/07/18 15:10:56 dlg Exp $ */ /* * Copyright (c) 2004, 2005 Marco Peereboom * All rights reserved. @@ -26,6 +26,13 @@ * */ +#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> @@ -34,20 +41,18 @@ #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; @@ -58,37 +63,79 @@ main(int argc, char *argv[]) { extern char *optarg; - u_int64_t func = 0; - /* u_int64_t subfunc = 0; */ + bioc_capabilities bc; + bioc_alarm ba; 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, "Dd:f:hi")) != -1) { + while ((ch = getopt(argc, argv, "a:b:Dd:ef:hl:pst:u:")) != -1) { switch (ch) { - case 'D': /* debug */ + 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 */ debug = 1; break; - case 'd': /* bio device */ + case 'd': /* device */ bioc_dev = optarg; break; - case 'f': /* scsi device */ + case 'e': /* enumerate */ + func |= BIOC_SCSICMD; + subfunc |= F_ENUM; + break; + + case 'f': /* device */ sd_dev = optarg; break; - case 'i': /* inquiry */ - func |= BIOC_INQ; + 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; break; case 'h': /* help/usage */ @@ -124,8 +171,80 @@ main(int argc, char *argv[]) if (debug) warnx("cookie = %p", bl.cookie); - if (func & BIOC_INQ) { - bio_inq(); + 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."); + } } return (0); @@ -136,7 +255,9 @@ usage(void) { extern char *__progname; - fprintf(stderr, "usage: %s [-Dhi] -d device | -f device\n", __progname); + fprintf(stderr, "usage: %s [-Dehpt] [-a function] [-b function] " + "[-l device list]\n" + "\t[-u function] [-d device | -f disk]\n", __progname); exit(1); } @@ -144,72 +265,855 @@ 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 -bio_inq(void) +parse_devlist(char *dl) { - bioc_inq bi; - bioc_vol bv; - bioc_disk bd; + u_int8_t c , t, done = 0; + char *es, *s; + struct dev *delm; + + es = NULL; + s = dl; - int rv, i, d; + if (debug) + printf("parse: %s\n", dl); - memset(&bi, 0, sizeof(bi)); + 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; if (debug) - printf("bio_inq\n"); + printf("alarm in: %s, ", arg); + + ba.cookie = bl.cookie; - bi.cookie = bl.cookie; + switch (arg[0]) { + case 'q': /* silence alarm */ + /* FALLTHROUGH */ + case 's': + if (debug) + printf("silence\n"); + ba.opcode = BIOCSALARM_SILENCE; + break; - rv = ioctl(devh, BIOCINQ, &bi); + 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; + + case 'g': /* get alarm state */ + if (debug) + printf("get state\n"); + ba.opcode = BIOCGALARM_STATE; + break; + + default: + warnx("invalid alarm function: %s", arg); + return; + } + + rv = ioctl(devh, BIOCALARM, &ba); if (rv == -1) { warnx("bioc_ioctl() call failed"); return; } - printf("RAID volumes : %d\n", bi.novol); - printf("Physical disks : %d\n\n", bi.nodisk); + 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; - for (i = 0; i < bi.novol; i++) { - memset(&bv, 0, sizeof(bv)); - bv.cookie = bl.cookie; - bv.volid = i; + scp = (struct ses_config_page *)rc; + printf("element types: %d, id: %s\n", scp->nr_elem_typ, + scp->enc_vendor_id); - rv = ioctl(devh, BIOCVOL, &bv); - if (rv == -1) { - warnx("bioc_ioctl() call failed"); + 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; + } +} + +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; } - printf("\tvolume id: %d\n", bv.volid); - printf("\tstatus : %d\n", bv.status); - printf("\tsize : %lld\n", bv.size); - printf("\traid : %d\n", bv.level); - printf("\tnr disks : %d\n", bv.nodisk); + if (debug) + ses_verbose(&rc[0], sizeof(rc)); - for (d = 0; d < bv.nodisk; d++) { - memset(&bd, 0, sizeof(bd)); - bd.cookie = bl.cookie; - bd.diskid = 0; + /* 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))); - rv = ioctl(devh, BIOCDISK, &bd); - if (rv == -1) { - warnx("bioc_ioctl() call failed"); - return; + if (tdh->elem_type == STDH_DEVICE) { + found = 1; + break; } + elements += tdh->nr_elem; + } - printf("\t\tdisk id : %d\n", bd.diskid); - printf("\t\tstatus : %d\n", bd.status); - printf("\t\tvolume id: %d\n", bd.volid); - printf("\t\tsize : %lld\n", bd.size); - printf("\t\tvendor : %s\n", bd.vendor); + 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); + + 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; + break; + + case BIOCSBLINK_BLINK: + cdp->elmts[i].byte3 = SDECD_RQST_IDENT; + cdp->elmts[i].byte4 = 0x00; + break; + + case BIOCSBLINK_UNBLINK: + cdp->elmts[i].byte3 = 0x00; + cdp->elmts[i].byte4 = 0x00; + break; + + 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); + } + 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); + } + } /* 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; + + if (inqlen < INQSIZE) { + /* INQUIRY shall return at least 36 bytes */ + printf("invalid INQUIRY buffer size\n"); + return; + } + + if (SID_QUAL & inq[0]) { + printf("invalid device\n"); + return; + } + + switch (SID_TYPE & inq[0]) { + case T_DIRECT: + printf("disk "); + break; + + case T_PROCESSOR: + printf("proc "); + break; + + default: + printf("unsuported device type\n"); + return; + } + + for (i = 0; i < inqlen; i++) { + if (i < 8) { + if ((flags & F_NOISY) || debug) + printf("%02x ", inq[i]); + } + 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); + } + + return (1); } diff --git a/sbin/bioctl/bioctl.h b/sbin/bioctl/bioctl.h index 6974eafabe1..51131f79948 100644 --- a/sbin/bioctl/bioctl.h +++ b/sbin/bioctl/bioctl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bioctl.h,v 1.7 2005/07/18 01:29:19 marco Exp $ */ +/* $OpenBSD: bioctl.h,v 1.8 2005/07/18 15:10:56 dlg Exp $ */ /* * Copyright (c) 2004, 2005 Marco Peereboom * All rights reserved. @@ -37,9 +37,53 @@ #define S_MEGA (1048576llu) #define S_KILO (1024llu) -void usage(void); -void cleanup(void); +/* functions */ +#define F_READCAP (0x01) +#define F_ENUM (0x02) +#define F_TUR (0x04) +#define F_INQUIRY (0x08) -void bio_inq(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); #endif /* _BIOCTL_H_ */ diff --git a/sys/dev/biovar.h b/sys/dev/biovar.h index 410ef126d28..2fb76943011 100644 --- a/sys/dev/biovar.h +++ b/sys/dev/biovar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: biovar.h,v 1.6 2005/07/18 01:29:01 marco Exp $ */ +/* $OpenBSD: biovar.h,v 1.7 2005/07/18 15:10:57 dlg Exp $ */ /* * Copyright (c) 2002 Niklas Hallqvist. All rights reserved. @@ -50,56 +50,147 @@ int bio_register(struct device *, int (*)(struct device *, u_long, /* RAID section */ -#define BIOCINQ _IOWR('B', 32, bioc_inq) -typedef struct _bioc_inq { - void *cookie; - - int novol; /* nr of volumes */ - int nodisk; /* nr of total disks */ -} bioc_inq; +#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 */ -#define BIOCDISK _IOWR('B', 33, bioc_disk) -/* structure that represents a disk in a RAID volume */ -typedef struct _bioc_disk { +/* ioctl tunnel defines */ +/* SHALL be implemented */ +#define BIOCPING _IOWR('B', 32, bioc_ping) +typedef struct _bioc_ping { void *cookie; + int x; +} bioc_ping; - int diskid; /* virtual disk id */ - int status; /* current status */ - int volid; /* associate with volume, if -1 unused */ - - 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; +/* 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; -#define BIOCVOL _IOWR('B', 34, bioc_vol) -/* structure that represents a RAID volume */ -typedef struct _bioc_vol { + /* 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 { + 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 { 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 status; /* current status */ -#define BIOC_SONLINE 0x00 -#define BIOC_SOFFLINE 0x01 -#define BIOC_SDEGRADED 0x02 - 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 49e98cbbb3b..885a77eae3e 100644 --- a/sys/dev/ic/ami.c +++ b/sys/dev/ic/ami.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ami.c,v 1.47 2005/07/18 01:29:01 marco Exp $ */ +/* $OpenBSD: ami.c,v 1.48 2005/07/18 15:10:56 dlg Exp $ */ /* * Copyright (c) 2001 Michael Shalayeff @@ -45,7 +45,7 @@ * Theo de Raadt. */ -/*#define AMI_DEBUG */ +/*#define AMI_DEBUG */ #include <sys/param.h> #include <sys/systm.h> @@ -76,11 +76,11 @@ #define AMI_D_DMA 0x0008 #define AMI_D_IOCTL 0x0010 int ami_debug = 0 -/* | AMI_D_CMD*/ -/* | AMI_D_INTR*/ -/* | AMI_D_MISC*/ -/* | AMI_D_DMA*/ - | AMI_D_IOCTL + | AMI_D_CMD + | AMI_D_INTR + | AMI_D_MISC +/* | AMI_D_DMA */ +/* | AMI_D_IOCTL */ ; #else #define AMI_DPRINTF(m,a) /* m, a */ @@ -136,19 +136,11 @@ 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_inq(struct ami_softc *, bioc_inq *); -int ami_ioctl_vol(struct ami_softc *, bioc_vol *); -int ami_ioctl_disk(struct ami_softc *, bioc_disk *); -#if 0 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 *); -#endif #endif /* NBIO > 0 */ struct ami_ccb * @@ -590,7 +582,6 @@ ami_attach(sc) sc->sc_link.adapter = &ami_switch; sc->sc_link.adapter_target = sc->sc_maxunits; sc->sc_link.adapter_buswidth = sc->sc_maxunits; - sc->sc_state_ch = 1; /* mark state as changed */ #ifdef AMI_DEBUG printf(": FW %s, BIOS v%s, %dMB RAM\n" @@ -1689,7 +1680,6 @@ 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)); @@ -1698,461 +1688,6 @@ ami_scsi_ioctl(struct scsi_link *link, u_long cmd, } #if NBIO > 0 -struct disk { - SLIST_ENTRY(disk) next; - bioc_disk bd; - - int ch; - int tg; -}; - -struct volume { - SLIST_ENTRY(volume) next; - bioc_vol bv; -}; - -SLIST_HEAD(disk_list, disk); -struct disk_list disks = SLIST_HEAD_INITIALIZER(disk); - -SLIST_HEAD(vol_list, volume); -struct vol_list volumes = SLIST_HEAD_INITIALIZER(volume); - -int -ami_ioctl(dev, cmd, addr) - struct device *dev; - u_long cmd; - caddr_t addr; -{ - struct ami_softc *sc = (struct ami_softc *)dev; - ami_lock_t lock; - int error = 0; - - AMI_DPRINTF(AMI_D_IOCTL, ("%s: ioctl()\n", sc->sc_dev.dv_xname)); - - if (sc->sc_flags & AMI_BROKEN) - return ENODEV; /* can't do this to broken device for now */ - - lock = AMI_LOCK_AMI(sc); - if (sc->sc_flags & AMI_CMDWAIT) { - AMI_UNLOCK_AMI(sc, lock); - return EBUSY; - } - - switch (cmd) { - 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", - 100 * 60) == EWOULDBLOCK) - return EWOULDBLOCK; - } - - switch (cmd) { - case BIOCINQ: - AMI_DPRINTF(AMI_D_IOCTL, ("inquiry\n")); - error = ami_ioctl_inq(sc, (bioc_inq *)addr); - break; - - case BIOCVOL: - AMI_DPRINTF(AMI_D_IOCTL, ("volume\n")); - error = ami_ioctl_vol(sc, (bioc_vol *)addr); - break; - - case BIOCDISK: - AMI_DPRINTF(AMI_D_IOCTL, ("disk\n")); - error = ami_ioctl_disk(sc, (bioc_disk *)addr); - break; - - default: - AMI_DPRINTF(AMI_D_IOCTL, ("%s: invalid ioctl\n", - sc->sc_dev.dv_xname)); - error = EINVAL; - } - - sc->sc_flags &= ~AMI_CMDWAIT; - wakeup(&sc->sc_ccbq); - - AMI_UNLOCK_AMI(sc, lock); - - return (error); -} - -int -ami_drv_inq(sc, ch, tg, inqbuf) - struct ami_softc *sc; - u_int8_t ch; - u_int8_t tg; - void *inqbuf; -{ - struct ami_ccb *ccb; - struct ami_iocmd *cmd; - struct ami_passthrough *ps; - struct scsi_inquiry_data *pp; - 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, 1, - "ami mgmt"))) { - error = ENOMEM; - goto bail; - } - - pa = idataseg[0].ds_addr; - ps = idata; - pp = idata + sizeof *ps; - - ccb = ami_get_ccb(sc); - ccb->ccb_data = NULL; - cmd = ccb->ccb_cmd; - - cmd->acc_cmd = AMI_PASSTHRU; - cmd->acc_passthru.apt_data = htole32(pa); - - memset(ps, 0, sizeof *ps); - - ps->apt_channel = ch; - ps->apt_target = tg; - ps->apt_ncdb = sizeof(struct scsi_inquiry); - ps->apt_nsense = sizeof(struct scsi_sense_data); - - 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); - - AMI_DPRINTF(AMI_D_IOCTL, ("%s: ami_drv_inq(%p, %02x, %02x, ,%p) ", - sc->sc_dev.dv_xname, sc, ch, tg, inqbuf)); - - if (ami_cmd(ccb, BUS_DMA_WAITOK, 1) == 0) { - AMI_DPRINTF(AMI_D_IOCTL, ("completed\n")); - - memcpy(inqbuf, pp, sizeof(struct scsi_inquiry_data)); - } - else { - AMI_DPRINTF(AMI_D_IOCTL, ("failed\n")); - - error = EINVAL; - } - -bail: - ami_freemem(sc->dmat, &idatamap, idataseg, NBPG, 1, "ami mgmt"); - - return (error); -} - -int -ami_mgmt(sc, opcode, par1, par2, size, buffer) - struct ami_softc *sc; - u_int8_t opcode; - u_int8_t par1; - u_int8_t par2; - size_t size; - void *buffer; -{ - 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; - - cmd->acc_cmd = opcode; - cmd->acc_io.aio_channel = par1; - cmd->acc_io.aio_param = par2; - cmd->acc_io.aio_data = htole32(pa); - - AMI_DPRINTF(AMI_D_IOCTL, ("%s: ami_mgmt(%p, %02x, %02x, %02x, %d,%p) ", - sc->sc_dev.dv_xname, sc, opcode, par1, par2, size, buffer)); - - if (ami_cmd(ccb, BUS_DMA_WAITOK, 1) == 0) { - AMI_DPRINTF(AMI_D_IOCTL, ("completed\n")); - - memcpy(buffer, idata, size); - } - 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_inq(sc, bi) - struct ami_softc *sc; - bioc_inq *bi; -{ - struct scsi_inquiry_data inqbuf; - struct ami_big_diskarray *p; /* struct too large for stack */ - struct volume *vol; - struct disk *dk; - int i, s, t, c; - int off; - int error = 0; - - if (!sc->sc_state_ch) { - bi->novol = 0; - bi->nodisk = 0; - SLIST_FOREACH(vol, &volumes, next) { - bi->novol++; - bi->nodisk += vol->bv.nodisk; - } - - return 0; - } - - AMI_DPRINTF(AMI_D_IOCTL, ("%s: biocinq", sc->sc_dev.dv_xname)); - - 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); - } - - bi->nodisk = 0; - - for (c = 0; c < 4; c++) { /* FIXME get max channel from inq3 */ - for (t = 0; t < AMI_MAX_TARGET; t++) { - if (!ami_drv_inq(sc, c, t, &inqbuf)) { - if ((inqbuf.device & SID_TYPE) != T_DIRECT) - /* XXX save c:t if PROC for later use */ - continue; /* we only care about disk */ - - dk = malloc(sizeof(struct disk), M_DEVBUF, - M_NOWAIT); - if (!dk) { - /* FIXME */ - panic("not enough memory."); - } - - dk->ch = c; - dk->tg = t; - dk->bd.diskid = bi->nodisk; - dk->bd.status = 0; /* XXX xlate */ - dk->bd.volid = -1; /* not yet claimed */ - dk->bd.size = 0; /* GETCAP or get in 2nd pass */ - strlcpy(dk->bd.vendor, inqbuf.vendor, - 8 + 16 + 4 + 1); /* vendor prod rev zero */ - - bi->nodisk++; - - SLIST_INSERT_HEAD(&disks, dk, next); - } - else { - AMI_DPRINTF(AMI_D_IOCTL, ("c: %d t: %d " - "fail\n", c, t)); - } - } - } - - if (!ami_mgmt(sc, AMI_FCOP, AMI_FC_RDCONF, 0, sizeof *p, p)) { - bi->novol = p->ada_nld; - - AMI_DPRINTF(AMI_D_IOCTL, ("novol: %d nodisk: %d p: %p\n", - bi->novol, bi->nodisk, &p)); - - /* setup volume list */ - for (i = 0; i < p->ada_nld; i++) { - vol = malloc(sizeof(struct volume), M_DEVBUF, M_NOWAIT); - if (!vol) { - /* FIXME */ - panic("not enough memory."); - } - - vol->bv.volid = i; - vol->bv.status = 0; /* XXX translate ami status */ - vol->bv.size = 0; - vol->bv.level = p->ada_ldrv[i].adl_raidlvl; - vol->bv.nodisk = 0; - /* do string ops here, question is how */ - - for (s = 0; s < p->ada_ldrv[i].adl_spandepth; s++) { - for (t = 0; t < p->ada_ldrv[i].adl_nstripes; t++) { - vol->bv.nodisk++; - - off = p->ada_ldrv[i].adl_spans[s].ads_devs[t].add_channel * AMI_MAX_TARGET + p->ada_ldrv[i].adl_spans[s].ads_devs[t].add_target; - /* walk disk list and add size */ - SLIST_FOREACH(dk, &disks, next) { - if (dk->ch != (p->ada_ldrv[i].adl_spans[s].ads_devs[t].add_target >> 4) || dk->tg != (p->ada_ldrv[i].adl_spans[s].ads_devs[t].add_target & 0x0f)) - continue; - - dk->bd.size = (quad_t)p->ada_pdrv[off].adp_size; - dk->bd.volid = i; - - AMI_DPRINTF(AMI_D_IOCTL, ("\tdiskid: %d\n", dk->bd.diskid)); - AMI_DPRINTF(AMI_D_IOCTL, ("\tstatus: %d\n", dk->bd.status)); - AMI_DPRINTF(AMI_D_IOCTL, ("\tvolid : %d\n", dk->bd.volid)); - AMI_DPRINTF(AMI_D_IOCTL, ("\tsize : %d\n", dk->bd.size)); - AMI_DPRINTF(AMI_D_IOCTL, ("\tvendor: %s\n", dk->bd.vendor)); - AMI_DPRINTF(AMI_D_IOCTL, ("\tchan : %d\n", dk->ch)); - AMI_DPRINTF(AMI_D_IOCTL, ("\ttarget: %d\n", dk->tg)); - - } - } - - switch (vol->bv.level) { - case 0: - vol->bv.size += p->ada_ldrv[i].adl_spans[s].ads_length * p->ada_ldrv[i].adl_nstripes; - break; - - case 1: - vol->bv.size += p->ada_ldrv[i].adl_spans[s].ads_length; - break; - - case 5: - vol->bv.size += p->ada_ldrv[i].adl_spans[s].ads_length * (p->ada_ldrv[i].adl_nstripes - 1); - break; - } - - } - - if (p->ada_ldrv[i].adl_spandepth > 1) - vol->bv.level *= 10; - - vol->bv.size *= (quad_t)512; - - AMI_DPRINTF(AMI_D_IOCTL, ("voldid: %d\n", - vol->bv.volid)); - AMI_DPRINTF(AMI_D_IOCTL, ("status: %d\n", - vol->bv.status)); - AMI_DPRINTF(AMI_D_IOCTL, ("size : %lld\n", - vol->bv.size)); - AMI_DPRINTF(AMI_D_IOCTL, ("level : %d\n", - vol->bv.level)); - AMI_DPRINTF(AMI_D_IOCTL, ("nodisk: %d\n", - vol->bv.nodisk)); - - SLIST_INSERT_HEAD(&volumes, vol, next); - } - -#if 0 - printf("LD: %d %d\n", p->ada_nld, sizeof p); - - for (i = 0; i < p->ada_nld; i++) { - printf("\tspandepth: %d\n", p->ada_ldrv[i].adl_spandepth); - printf("\traidlvl : %d\n", p->ada_ldrv[i].adl_raidlvl); - printf("\trd ahead : %d\n", p->ada_ldrv[i].adl_rdahead); - printf("\tstrp size: %d\n", p->ada_ldrv[i].adl_stripesz); - printf("\tstatus : %d\n", p->ada_ldrv[i].adl_status); - printf("\twr policy: %d\n", p->ada_ldrv[i].adl_wrpolicy); - printf("\tdirectio : %d\n", p->ada_ldrv[i].adl_directio); - printf("\tnr stripe: %d\n", p->ada_ldrv[i].adl_nstripes); - for (s = 0; s < p->ada_ldrv[i].adl_spandepth; s++) { - for (t = 0; t < p->ada_ldrv[i].adl_nstripes; t++) { - off = p->ada_ldrv[i].adl_spans[s].ads_devs[t].add_channel * - AMI_MAX_TARGET + - p->ada_ldrv[i].adl_spans[s].ads_devs[t].add_target; - - printf("\t\tspan : %d\n", s); - printf("\t\tstart : %d\n", - (u_int32_t)p->ada_ldrv[i].adl_spans[s].ads_start); - printf("\t\tlength : %d\n", - (u_int32_t)p->ada_ldrv[i].adl_spans[s].ads_length); - - printf("\t\t\tchannel : %02x\n", - p->ada_ldrv[i].adl_spans[s].ads_devs[t].add_channel); - printf("\t\t\ttarget : %02x\n", - p->ada_ldrv[i].adl_spans[s].ads_devs[t].add_target); - printf("\t\t\toff : %d\n"); - - printf("\t\t\ttype : %d\n", - p->ada_pdrv[off].adp_type); - printf("\t\t\tstatus : %d\n", - p->ada_pdrv[off].adp_ostatus); - printf("\t\t\tdepth : %d\n", - p->ada_pdrv[off].adp_tagdepth); - printf("\t\t\tsneg : %d\n", - p->ada_pdrv[off].adp_sneg); - printf("\t\t\tsize : %d\n\n", - (u_int32_t)p->ada_pdrv[off].adp_size); - } - } - } -#endif - } - else { - AMI_DPRINTF(AMI_D_IOCTL, ("failed\n")); - error = EINVAL; - } - - free(p, M_DEVBUF); - - sc->sc_state_ch = 0; /* state normalized */ - - return (error); -} - -int -ami_ioctl_vol(sc, bv) - struct ami_softc *sc; - bioc_vol *bv; -{ - struct volume *vol; - int error = EINVAL; - - AMI_DPRINTF(AMI_D_IOCTL, ("%s: biocvol\n", sc->sc_dev.dv_xname)); - - SLIST_FOREACH(vol, &volumes, next) { - if (bv->volid != vol->bv.volid) - continue; - - memcpy(bv, &vol->bv, sizeof *bv); - error = 0; - } - - return (error); -} - -int -ami_ioctl_disk(sc, bd) - struct ami_softc *sc; - bioc_disk *bd; -{ - struct disk *dk; - int error = EINVAL; - - AMI_DPRINTF(AMI_D_IOCTL, ("%s: biocdisk\n", sc->sc_dev.dv_xname)); - - SLIST_FOREACH(dk, &disks, next) { - if (bd->diskid != dk->bd.diskid) - continue; - - memcpy(bd, &dk->bd, sizeof *bd); - error = 0; - } - - return (error); -} - -#if 0 int ami_ioctl(dev, cmd, addr) struct device *dev; @@ -2537,8 +2072,6 @@ ami_ioctl_passthru(sc, bp) return (error); } -#endif - #endif /* NBIO > 0 */ #ifdef AMI_DEBUG diff --git a/sys/dev/ic/amireg.h b/sys/dev/ic/amireg.h index 204237944e5..84841c2aea8 100644 --- a/sys/dev/ic/amireg.h +++ b/sys/dev/ic/amireg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: amireg.h,v 1.16 2005/07/18 01:29:01 marco Exp $ */ +/* $OpenBSD: amireg.h,v 1.17 2005/07/18 15:10:57 dlg Exp $ */ /* * Copyright (c) 2000 Michael Shalayeff @@ -223,8 +223,6 @@ #define AMI_HSPDIAG 0xb1 #define AMI_GESENSEINFO 0xb2 /* get extended sense info */ #define AMI_SYSFLUSH 0xfe /* flush system */ -#define AMI_GETINQ 0xcf /* get proc & drive inquiry data */ -/* this needs to be removed when the new bioctl goes in */ #define AMI_ALARM 0x51 /* alarm functions */ #define AMI_ALARM_OFF 0x00 #define AMI_ALARM_ON 0x01 diff --git a/sys/dev/ic/amivar.h b/sys/dev/ic/amivar.h index 798e91937b0..68edd84a843 100644 --- a/sys/dev/ic/amivar.h +++ b/sys/dev/ic/amivar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: amivar.h,v 1.12 2005/07/18 01:29:01 marco Exp $ */ +/* $OpenBSD: amivar.h,v 1.13 2005/07/18 15:10:57 dlg Exp $ */ /* * Copyright (c) 2001 Michael Shalayeff @@ -92,7 +92,6 @@ struct ami_softc { struct timeout sc_requeue_tmo; struct timeout sc_poll_tmo; int sc_dis_poll; - int sc_state_ch; char sc_fwver[16]; char sc_biosver[16]; |