summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2005-07-18 15:10:58 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2005-07-18 15:10:58 +0000
commit69c687924e0aac6b65efd331cab86c86bfb61fc4 (patch)
tree4940df3520abad4620c539904122cae61ba9c405
parent266c19464df004208d3eb2fc4d421579a43b28cd (diff)
revert marcos bio changes, mickey not ok
-rw-r--r--sbin/bioctl/Makefile5
-rw-r--r--sbin/bioctl/bioctl.855
-rw-r--r--sbin/bioctl/bioctl.c1018
-rw-r--r--sbin/bioctl/bioctl.h52
-rw-r--r--sys/dev/biovar.h187
-rw-r--r--sys/dev/ic/ami.c481
-rw-r--r--sys/dev/ic/amireg.h4
-rw-r--r--sys/dev/ic/amivar.h3
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];