Add bio(4) and associated bioctl(8) from OpenBSD, a driver control block

device controllers, and more specifically raid controllers.
Add a new sensor type, ENVSYS_DRIVE, to report drive status. From OpenBSD.
Add bio and sysmon support to mfi(4). This allow userland to query
status for drives and logical volumes attached to a mfi(4) controller. While
there fix some debug printfs in mfi so they compile.
Add bio(4) to amd64 and i386 GENERIC.
This commit is contained in:
bouyer 2007-05-01 17:18:52 +00:00
parent f5ef068cda
commit 982bad256f
23 changed files with 1667 additions and 147 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: mi,v 1.703 2007/04/26 21:22:04 agc Exp $
# $NetBSD: mi,v 1.704 2007/05/01 17:18:52 bouyer Exp $
. base-sys-root
./altroot base-sys-root
./bin base-sys-root
@ -123,6 +123,7 @@
./sbin/amrctl base-sysutil-root
./sbin/apmlabel base-sysutil-root
./sbin/atactl base-sysutil-root
./sbin/bioctl base-sysutil-root
./sbin/badsect base-sysutil-root
./sbin/brconfig base-netutil-root
./sbin/ccdconfig base-sysutil-root

View File

@ -1,4 +1,4 @@
# $NetBSD: mi,v 1.1021 2007/04/30 14:44:28 rmind Exp $
# $NetBSD: mi,v 1.1022 2007/05/01 17:18:52 bouyer Exp $
./etc/mtree/set.comp comp-sys-root
./usr/bin/addr2line comp-debug-bin bfd
./usr/bin/ar comp-util-bin bfd
@ -156,6 +156,7 @@
./usr/include/dev/auconv.h comp-obsolete obsolete
./usr/include/dev/audio_if.h comp-obsolete obsolete
./usr/include/dev/audiovar.h comp-obsolete obsolete
./usr/include/dev/biovar.h comp-c-include
./usr/include/dev/bluetooth comp-c-include
./usr/include/dev/bluetooth/btdev.h comp-c-include
./usr/include/dev/bluetooth/bthidev.h comp-c-include

View File

@ -1,4 +1,4 @@
# $NetBSD: mi,v 1.996 2007/04/26 21:22:04 agc Exp $
# $NetBSD: mi,v 1.997 2007/05/01 17:18:53 bouyer Exp $
./etc/mtree/set.man man-sys-root
./usr/share/info/am-utils.info man-amd-info info
./usr/share/info/as.info man-computil-info bfd,info
@ -721,6 +721,7 @@
./usr/share/man/cat4/bge.0 man-sys-catman .cat
./usr/share/man/cat4/bha.0 man-sys-catman .cat
./usr/share/man/cat4/bicc.0 man-sys-catman .cat
./usr/share/man/cat4/bio.0 man-sys-catman .cat
./usr/share/man/cat4/bktr.0 man-sys-catman .cat
./usr/share/man/cat4/bluetooth.0 man-sys-catman .cat
./usr/share/man/cat4/bmtphy.0 man-sys-catman .cat
@ -1814,6 +1815,7 @@
./usr/share/man/cat8/badsect.0 man-sysutil-catman .cat
./usr/share/man/cat8/bebox/MAKEDEV.0 man-obsolete obsolete
./usr/share/man/cat8/bebox/makedev.0 man-obsolete obsolete
./usr/share/man/cat8/bioctl.0 man-sysutil-catman .cat
./usr/share/man/cat8/boot.0 man-sysutil-catman .cat
./usr/share/man/cat8/bootparamd.0 man-bootserver-catman .cat
./usr/share/man/cat8/bootpd.0 man-bootserver-catman .cat
@ -3172,6 +3174,7 @@
./usr/share/man/man4/bge.4 man-sys-man .man
./usr/share/man/man4/bha.4 man-sys-man .man
./usr/share/man/man4/bicc.4 man-sys-man .man
./usr/share/man/man4/bio.4 man-sys-man .man
./usr/share/man/man4/bktr.4 man-sys-man .man
./usr/share/man/man4/bluetooth.4 man-sys-man .man
./usr/share/man/man4/bmtphy.4 man-sys-man .man
@ -4264,6 +4267,7 @@
./usr/share/man/man8/badsect.8 man-sysutil-man .man
./usr/share/man/man8/bebox/MAKEDEV.8 man-obsolete obsolete
./usr/share/man/man8/bebox/makedev.8 man-obsolete obsolete
./usr/share/man/man8/bioctl.8 man-sysutil-man .man
./usr/share/man/man8/boot.8 man-sysutil-man .man
./usr/share/man/man8/bootparamd.8 man-bootserver-man .man
./usr/share/man/man8/bootpd.8 man-bootserver-man .man

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.104 2007/03/06 11:28:45 dillo Exp $
# $NetBSD: Makefile,v 1.105 2007/05/01 17:18:53 bouyer Exp $
# @(#)Makefile 8.5 (Berkeley) 3/31/94
# Not ported: XNSrouted enpload scsiformat startslip
@ -6,8 +6,8 @@
.include <bsd.own.mk>
SUBDIR= amrctl apmlabel atactl badsect bim brconfig ccdconfig disklabel \
dkctl dkscan_bsdlabel dmesg \
SUBDIR= amrctl apmlabel atactl badsect bim bioctl brconfig ccdconfig \
disklabel dkctl dkscan_bsdlabel dmesg \
drvctl edlabel fastboot fdisk fsck fsirand gpt ifconfig init ldconfig \
mbrlabel mknod modload modunload mount newbtconf nologin \
pdisk ping pppoectl raidctl reboot rcorder rndctl route routed \

10
sbin/bioctl/Makefile Normal file
View File

@ -0,0 +1,10 @@
# $OpenBSD: Makefile,v 1.8 2006/11/26 11:31:08 deraadt Exp $
PROG= bioctl
SRCS= bioctl.c strtonum.c
MAN= bioctl.8
DPADD= ${LIBUTIL}
LDADD= -lutil
.include <bsd.prog.mk>

164
sbin/bioctl/bioctl.8 Normal file
View File

@ -0,0 +1,164 @@
.\" $NetBSD: bioctl.8,v 1.1 2007/05/01 17:18:53 bouyer Exp $
.\" $OpenBSD: bioctl.8,v 1.43 2007/03/20 06:12:11 jmc Exp $
.\"
.\" Copyright (c) 2004, 2005 Marco Peereboom
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
.\" ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd April 8, 2007
.Dt BIOCTL 8
.Os
.Sh NAME
.Nm bioctl
.Nd RAID management interface
.Sh SYNOPSIS
.Nm bioctl
.Bk -words
.Op Fl Dhiv
.Op Fl a Ar alarm-function
.Op Fl b Ar channel:target[.lun]
.Op Fl c Ar raidlevel
.Op Fl H Ar channel:target[.lun]
.Op Fl l Ar special[,special[,...]]
.Op Fl u Ar channel:target[.lun]
.Ar device
.Ek
.Sh DESCRIPTION
RAID device drivers which support management functionality can
register their services with the
.Xr bio 4
driver.
.Nm bioctl
then can be used to maintain RAID volumes.
.Pp
The options are as follows:
.Bl -tag -width Ds
.It Fl a Ar alarm-function
Control the RAID card's alarm functionality, if supported.
.Ar alarm-function
may be one of:
.Pp
.Bl -tag -width disable -compact
.It Ar disable
Disable the alarm on the RAID controller.
.It Ar enable
Enable the alarm on the RAID controller.
.It Ar get
Retrieve the current alarm state (enabled or disabled).
.It Ar silence | Ar quiet
Silence the alarm if it is currently beeping.
.El
.Pp
The
.Ar alarm-function
may be specified as given above,
or by the first letter only
(e.g. -a e).
.It Fl b Ar channel:target[.lun]
Instruct the device at
.Ar channel:target[.lun]
to start blinking, if there is
.Xr ses 4
or
.Xr safte 4
support in the enclosure.
.It Fl c Ar raidlevel
Create a
.Xr softraid 4
device of level
.Ar raidlevel .
The device must begin with
.Dq softraid
followed by a number.
.It Fl D
Enable debug output.
.It Fl H Ar channel:target[.lun]
If the device at
.Ar channel:target[.lun]
is currently marked
.Dq Unused ,
promote it to being a
.Dq Hot Spare .
.It Fl h
Where necessary, produce "human-readable" output.
Use unit suffixes: Byte, Kilobyte, Megabyte,
Gigabyte, Terabyte, Petabyte, Exabyte in order to reduce the number of
digits to four or less.
.It Fl i
Enumerate the selected RAID devices.
.It Fl l Ar special[,special[,...]]
Use
.Ar special
device list to create within the
.Xr softraid 4
framework.
Requires
.Fl c .
.It Fl u Ar channel:target[.lun]
Instruct the device at
.Ar channel:target[.lun]
to cease blinking, if there is
.Xr ses 4
or
.Xr safte 4
support in the enclosure.
.It Fl v
Be more verbose in output.
.It Ar device
Select a drive by name (e.g. sd0) or a RAID controller by name (e.g. ami0).
For operations which will be performed against
.Xr ses 4
or
.Xr safte 4
enclosures, it is also possible to directly specify the enclosure name
(e.g. safte0).
.El
.Sh EXAMPLES
The following command, executed from the command line, shows the status of
the logical drives on the RAID controller:
.Bd -literal
# bioctl -h mfi0
Volume Status Size Device
mfi0 0 Online 74G mfi0 RAID1
0 Online 75G 1:0.0 noencl <ATA WDC WD800JD-75MS1E04>
1 Online 75G 1:1.0 noencl <ATA WDC WD800JD-75MS1E04>
mfi0 1 Online 697G mfi0 RAID5
0 Online 233G 1:3.0 noencl <ATA WDC WD2500JS-75N2E04>
1 Online 233G 1:2.0 noencl <ATA WDC WD2500JS-75N2E04>
2 Online 233G 1:4.0 noencl <ATA WDC WD2500JS-75N2E04>
3 Online 233G 1:5.0 noencl <ATA WDC WD2500JS-75N2E04>
.Ed
.Sh SEE ALSO
.Xr bio 4 ,
.Xr mfi 4 ,
.Sh BUGS
the softraid stuff available at this time.
.Sh HISTORY
The
.Nm
command first appeared in
.Ox 3.8 .
.Sh AUTHORS
The
.Nm
interface was written by
.An Marco Peereboom Aq marco@openbsd.org .

661
sbin/bioctl/bioctl.c Normal file
View File

@ -0,0 +1,661 @@
/* $NetBSD: bioctl.c,v 1.1 2007/05/01 17:18:53 bouyer Exp $ */
/* $OpenBSD: bioctl.c,v 1.52 2007/03/20 15:26:06 jmc Exp $ */
/*
* Copyright (c) 2004, 2005 Marco Peereboom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: bioctl.c,v 1.1 2007/05/01 17:18:53 bouyer Exp $");
#endif
#include <sys/ioctl.h>
#include <sys/param.h>
#include <sys/queue.h>
// #include <scsi/scsipi_disk.h>
// #include <scsi/scsipi_all.h>
#include <dev/biovar.h>
#include <errno.h>
#include <err.h>
#include <fcntl.h>
#include <util.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <util.h>
#include "strtonum.h"
struct locator {
int channel;
int target;
int lun;
};
void usage(void);
const char *str2locator(const char *, struct locator *);
void cleanup(void);
void bio_inq(char *);
void bio_alarm(char *);
void bio_setstate(char *);
void bio_setblink(char *, char *, int);
void bio_blink(char *, int, int);
void bio_createraid(u_int16_t, char *);
int devh = -1;
int debug;
int human;
int verbose;
struct bio_locate bl;
int
main(int argc, char *argv[])
{
extern char *optarg;
u_int64_t func = 0;
/* u_int64_t subfunc = 0; XXX */
char *bioc_dev = NULL, *sd_dev = NULL;
char /* *realname = NULL, XXX */ *al_arg = NULL;
char *bl_arg = NULL, *dev_list = NULL;
int ch, rv, blink = 0; /* XXX GCC */
u_int16_t cr_level = 0; /* XXX GCC */
if (argc < 2)
usage();
while ((ch = getopt(argc, argv, "b:c:l:u:H:ha:Div")) != -1) {
switch (ch) {
case 'a': /* alarm */
func |= BIOC_ALARM;
al_arg = optarg;
break;
case 'b': /* blink */
func |= BIOC_BLINK;
blink = BIOC_SBBLINK;
bl_arg = optarg;
break;
case 'c': /* create */
func |= BIOC_CREATERAID;
cr_level = atoi(optarg);
break;
case 'u': /* unblink */
func |= BIOC_BLINK;
blink = BIOC_SBUNBLINK;
bl_arg = optarg;
break;
case 'D': /* debug */
debug = 1;
break;
case 'H': /* set hotspare */
func |= BIOC_SETSTATE;
al_arg = optarg;
break;
case 'h':
human = 1;
break;
case 'i': /* inquiry */
func |= BIOC_INQ;
break;
case 'l': /* device list */
func |= BIOC_DEVLIST;
dev_list = optarg;
break;
case 'v':
verbose = 1;
break;
default:
usage();
/* NOTREACHED */
}
}
argc -= optind;
argv += optind;
if (argc != 1)
usage();
if (func == 0)
func |= BIOC_INQ;
#if 0
/* if at least glob sd[0-9]*, it is a drive identifier */
if (strncmp(argv[0], "sd", 2) == 0 && strlen(argv[0]) > 2 &&
isdigit((int)argv[0][2]))
sd_dev = argv[0];
else
#endif
bioc_dev = argv[0];
if (bioc_dev) {
devh = open("/dev/bio", O_RDWR);
if (devh == -1)
err(1, "Can't open %s", "/dev/bio");
bl.bl_name = bioc_dev;
rv = ioctl(devh, BIOCLOCATE, &bl);
if (rv == -1)
errx(1, "Can't locate %s device via %s",
bl.bl_name, "/dev/bio");
}
#if 0
else if (sd_dev) {
devh = opendev(sd_dev, O_RDWR, OPENDEV_PART, &realname);
if (devh == -1)
err(1, "Can't open %s", sd_dev);
}
#endif
else
errx(1, "need -d or -f parameter");
if (debug)
warnx("cookie = %p", bl.bl_cookie);
if (func & BIOC_INQ) {
bio_inq(sd_dev);
} else if (func == BIOC_ALARM) {
bio_alarm(al_arg);
} else if (func == BIOC_BLINK) {
bio_setblink(sd_dev, bl_arg, blink);
} else if (func == BIOC_SETSTATE) {
bio_setstate(al_arg);
} else if (func & BIOC_CREATERAID || func & BIOC_DEVLIST) {
if (!(func & BIOC_CREATERAID))
errx(1, "need -c parameter");
if (!(func & BIOC_DEVLIST))
errx(1, "need -l parameter");
if (sd_dev)
errx(1, "can't use sd device");
bio_createraid(cr_level, dev_list);
}
return (0);
}
void
usage(void)
{
extern char *__progname;
fprintf(stderr,
"usage: %s [-Dhiv] [-a alarm-function] "
"[-b channel:target[.lun]]\n"
"\t[-c raidlevel] [-H channel:target[.lun]]\n"
"\t[-l special[,special[,...]]] "
"[-u channel:target[.lun]] device\n", __progname);
exit(1);
}
const char *
str2locator(const char *string, struct locator *location)
{
const char *errstr;
char parse[80], *targ, *lun;
strlcpy(parse, string, sizeof parse);
targ = strchr(parse, ':');
if (targ == NULL)
return ("target not specified");
*targ++ = '\0';
lun = strchr(targ, '.');
if (lun != NULL) {
*lun++ = '\0';
location->lun = strtonum(lun, 0, 256, &errstr);
if (errstr)
return (errstr);
} else
location->lun = 0;
location->target = strtonum(targ, 0, 256, &errstr);
if (errstr)
return (errstr);
location->channel = strtonum(parse, 0, 256, &errstr);
if (errstr)
return (errstr);
return (NULL);
}
void
bio_inq(char *name)
{
const char *status;
char size[64], scsiname[16], volname[32];
char percent[10], seconds[20];
int rv, i, d, volheader, hotspare, unused;
char encname[16], serial[32];
struct bioc_disk bd;
struct bioc_inq bi;
struct bioc_vol bv;
memset(&bi, 0, sizeof(bi));
if (debug)
printf("bio_inq\n");
bi.bi_cookie = bl.bl_cookie;
rv = ioctl(devh, BIOCINQ, &bi);
if (rv == -1) {
warn("BIOCINQ");
return;
}
if (debug)
printf("bio_inq { %p, %s, %d, %d }\n",
bi.bi_cookie,
bi.bi_dev,
bi.bi_novol,
bi.bi_nodisk);
volheader = 0;
for (i = 0; i < bi.bi_novol; i++) {
memset(&bv, 0, sizeof(bv));
bv.bv_cookie = bl.bl_cookie;
bv.bv_volid = i;
bv.bv_percent = -1;
bv.bv_seconds = 0;
rv = ioctl(devh, BIOCVOL, &bv);
if (rv == -1) {
warn("BIOCVOL");
return;
}
if (name && strcmp(name, bv.bv_dev) != 0)
continue;
if (!volheader) {
volheader = 1;
printf("%-7s %-10s %14s %-8s\n",
"Volume", "Status", "Size", "Device");
}
percent[0] = '\0';
seconds[0] = '\0';
if (bv.bv_percent != -1)
snprintf(percent, sizeof percent,
" %d%% done", bv.bv_percent);
if (bv.bv_seconds)
snprintf(seconds, sizeof seconds,
" %u seconds", bv.bv_seconds);
switch (bv.bv_status) {
case BIOC_SVONLINE:
status = BIOC_SVONLINE_S;
break;
case BIOC_SVOFFLINE:
status = BIOC_SVOFFLINE_S;
break;
case BIOC_SVDEGRADED:
status = BIOC_SVDEGRADED_S;
break;
case BIOC_SVBUILDING:
status = BIOC_SVBUILDING_S;
break;
case BIOC_SVREBUILD:
status = BIOC_SVREBUILD_S;
break;
case BIOC_SVSCRUB:
status = BIOC_SVSCRUB_S;
break;
case BIOC_SVINVALID:
default:
status = BIOC_SVINVALID_S;
}
snprintf(volname, sizeof volname, "%s %u",
bi.bi_dev, bv.bv_volid);
if (bv.bv_level == -1 && bv.bv_nodisk == 1) {
hotspare = 1;
unused = 0;
} else if (bv.bv_level == -2 && bv.bv_nodisk == 1) {
unused = 1;
hotspare = 0;
} else {
unused = 0;
hotspare = 0;
if (human)
humanize_number(size, 5,
(int64_t)bv.bv_size, "", HN_AUTOSCALE,
HN_B | HN_NOSPACE | HN_DECIMAL);
else
snprintf(size, sizeof size, "%14llu",
(long long unsigned int)bv.bv_size);
printf("%7s %-10s %14s %-7s RAID%u%s%s\n",
volname, status, size, bv.bv_dev,
bv.bv_level, percent, seconds);
}
for (d = 0; d < bv.bv_nodisk; d++) {
memset(&bd, 0, sizeof(bd));
bd.bd_cookie = bl.bl_cookie;
bd.bd_diskid = d;
bd.bd_volid = i;
rv = ioctl(devh, BIOCDISK, &bd);
if (rv == -1) {
warn("BIOCDISK");
return;
}
switch (bd.bd_status) {
case BIOC_SDONLINE:
status = BIOC_SDONLINE_S;
break;
case BIOC_SDOFFLINE:
status = BIOC_SDOFFLINE_S;
break;
case BIOC_SDFAILED:
status = BIOC_SDFAILED_S;
break;
case BIOC_SDREBUILD:
status = BIOC_SDREBUILD_S;
break;
case BIOC_SDHOTSPARE:
status = BIOC_SDHOTSPARE_S;
break;
case BIOC_SDUNUSED:
status = BIOC_SDUNUSED_S;
break;
case BIOC_SDSCRUB:
status = BIOC_SDSCRUB_S;
break;
case BIOC_SDINVALID:
default:
status = BIOC_SDINVALID_S;
}
if (hotspare || unused)
; /* use volname from parent volume */
else
snprintf(volname, sizeof volname, " %3u",
bd.bd_diskid);
if (human)
humanize_number(size, 5,
bd.bd_size, "", HN_AUTOSCALE,
HN_B | HN_NOSPACE | HN_DECIMAL);
else
snprintf(size, sizeof size, "%14llu",
(long long unsigned int)bd.bd_size);
snprintf(scsiname, sizeof scsiname,
"%u:%u.%u",
bd.bd_channel, bd.bd_target, bd.bd_lun);
if (bd.bd_procdev[0])
strlcpy(encname, bd.bd_procdev, sizeof encname);
else
strlcpy(encname, "noencl", sizeof encname);
if (bd.bd_serial[0])
strlcpy(serial, bd.bd_serial, sizeof serial);
else
strlcpy(serial, "unknown serial", sizeof serial);
printf("%7s %-10s %14s %-7s %-6s <%s>\n",
volname, status, size, scsiname, encname,
bd.bd_vendor);
if (verbose)
printf("%7s %-10s %14s %-7s %-6s '%s'\n",
"", "", "", "", "", serial);
}
}
}
void
bio_alarm(char *arg)
{
int rv;
struct bioc_alarm ba;
ba.ba_cookie = bl.bl_cookie;
switch (arg[0]) {
case 'q': /* silence alarm */
/* FALLTHROUGH */
case 's':
ba.ba_opcode = BIOC_SASILENCE;
break;
case 'e': /* enable alarm */
ba.ba_opcode = BIOC_SAENABLE;
break;
case 'd': /* disable alarm */
ba.ba_opcode = BIOC_SADISABLE;
break;
case 't': /* test alarm */
ba.ba_opcode = BIOC_SATEST;
break;
case 'g': /* get alarm state */
ba.ba_opcode = BIOC_GASTATUS;
break;
default:
warnx("invalid alarm function: %s", arg);
return;
}
rv = ioctl(devh, BIOCALARM, &ba);
if (rv == -1) {
warn("BIOCALARM");
return;
}
if (arg[0] == 'g') {
printf("alarm is currently %s\n",
ba.ba_status ? "enabled" : "disabled");
}
}
void
bio_setstate(char *arg)
{
struct bioc_setstate bs;
struct locator location;
const char *errstr;
int rv;
errstr = str2locator(arg, &location);
if (errstr)
errx(1, "Target %s: %s", arg, errstr);
bs.bs_cookie = bl.bl_cookie;
bs.bs_status = BIOC_SSHOTSPARE;
bs.bs_channel = location.channel;
bs.bs_target = location.target;
bs.bs_lun = location.lun;
rv = ioctl(devh, BIOCSETSTATE, &bs);
if (rv == -1) {
warn("BIOCSETSTATE");
return;
}
}
void
bio_setblink(char *name, char *arg, int blink)
{
struct locator location;
struct bioc_inq bi;
struct bioc_vol bv;
struct bioc_disk bd;
struct bioc_blink bb;
const char *errstr;
int v, d, rv;
errstr = str2locator(arg, &location);
if (errstr)
errx(1, "Target %s: %s", arg, errstr);
/* try setting blink on the device directly */
memset(&bb, 0, sizeof(bb));
bb.bb_cookie = bl.bl_cookie;
bb.bb_status = blink;
bb.bb_target = location.target;
bb.bb_channel = location.channel;
rv = ioctl(devh, BIOCBLINK, &bb);
if (rv == 0)
return;
/* if the blink didnt work, try to find something that will */
memset(&bi, 0, sizeof(bi));
bi.bi_cookie = bl.bl_cookie;
rv = ioctl(devh, BIOCINQ, &bi);
if (rv == -1) {
warn("BIOCINQ");
return;
}
for (v = 0; v < bi.bi_novol; v++) {
memset(&bv, 0, sizeof(bv));
bv.bv_cookie = bl.bl_cookie;
bv.bv_volid = v;
rv = ioctl(devh, BIOCVOL, &bv);
if (rv == -1) {
warn("BIOCVOL");
return;
}
if (name && strcmp(name, bv.bv_dev) != 0)
continue;
for (d = 0; d < bv.bv_nodisk; d++) {
memset(&bd, 0, sizeof(bd));
bd.bd_cookie = bl.bl_cookie;
bd.bd_volid = v;
bd.bd_diskid = d;
rv = ioctl(devh, BIOCDISK, &bd);
if (rv == -1) {
warn("BIOCDISK");
return;
}
if (bd.bd_channel == location.channel &&
bd.bd_target == location.target &&
bd.bd_lun == location.lun) {
if (bd.bd_procdev[0] != '\0') {
bio_blink(bd.bd_procdev,
location.target, blink);
} else
warnx("Disk %s is not in an enclosure", arg);
return;
}
}
}
warnx("Disk %s does not exist", arg);
return;
}
void
bio_blink(char *enclosure, int target, int blinktype)
{
int bioh;
struct bio_locate bio;
struct bioc_blink blink;
int rv;
bioh = open("/dev/bio", O_RDWR);
if (bioh == -1)
err(1, "Can't open %s", "/dev/bio");
bio.bl_name = enclosure;
rv = ioctl(bioh, BIOCLOCATE, &bio);
if (rv == -1)
errx(1, "Can't locate %s device via %s", enclosure, "/dev/bio");
memset(&blink, 0, sizeof(blink));
blink.bb_cookie = bio.bl_cookie;
blink.bb_status = blinktype;
blink.bb_target = target;
rv = ioctl(bioh, BIOCBLINK, &blink);
if (rv == -1)
warn("BIOCBLINK");
close(bioh);
}
void
bio_createraid(u_int16_t level, char *dev_list)
{
struct bioc_createraid create;
int rv;
u_int16_t min_disks = 0;
if (debug)
printf("bio_createraid\n");
if (!dev_list)
errx(1, "no devices specified");
switch (level) {
case 0:
min_disks = 1;
break;
case 1:
min_disks = 2;
break;
default:
errx(1, "unsuported raid level");
}
/* XXX validate device list for real */
#if 0
if (strncmp(dev_list, "sd", 2) == 0 && strlen(dev_list) > 2 &&
isdigit(dev_list[2])) {
if (strlen(dev_list) != 3)
errx(1, "only one device supported");
if (debug)
printf("bio_createraid: dev_list: %s\n", dev_list);
}
else
errx(1, "no sd device specified");
#endif
memset(&create, 0, sizeof(create));
create.bc_cookie = bl.bl_cookie;
create.bc_level = level;
create.bc_dev_list_len = strlen(dev_list);
create.bc_dev_list = dev_list;
rv = ioctl(devh, BIOCCREATERAID, &create);
if (rv == -1) {
warn("BIOCCREATERAID");
return;
}
}

72
sbin/bioctl/strtonum.c Normal file
View File

@ -0,0 +1,72 @@
/* $NetBSD: strtonum.c,v 1.1 2007/05/01 17:18:54 bouyer Exp $ */
/* $OpenBSD: strtonum.c,v 1.6 2004/08/03 19:38:01 millert Exp $ */
/*
* Copyright (c) 2004 Ted Unangst and Todd Miller
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: strtonum.c,v 1.1 2007/05/01 17:18:54 bouyer Exp $");
#endif
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
#include "strtonum.h"
#define INVALID 1
#define TOOSMALL 2
#define TOOLARGE 3
long long
strtonum(const char *numstr, long long minval, long long maxval,
const char **errstrp)
{
long long ll = 0;
char *ep;
int error = 0;
struct errval {
const char *errstr;
int err;
} ev[4] = {
{ NULL, 0 },
{ "invalid", EINVAL },
{ "too small", ERANGE },
{ "too large", ERANGE },
};
ev[0].err = errno;
errno = 0;
if (minval > maxval)
error = INVALID;
else {
ll = strtoll(numstr, &ep, 10);
if (numstr == ep || *ep != '\0')
error = INVALID;
else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
error = TOOSMALL;
else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
error = TOOLARGE;
}
if (errstrp != NULL)
*errstrp = ev[error].errstr;
errno = ev[error].err;
if (error)
ll = 0;
return (ll);
}

4
sbin/bioctl/strtonum.h Normal file
View File

@ -0,0 +1,4 @@
/* $NetBSD: strtonum.h,v 1.1 2007/05/01 17:18:54 bouyer Exp $ */
long long strtonum(const char *, long long, long long, const char **);

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.425 2007/04/21 06:11:58 plunky Exp $
# $NetBSD: Makefile,v 1.426 2007/05/01 17:18:54 bouyer Exp $
# @(#)Makefile 8.1 (Berkeley) 6/18/93
MAN= aac.4 ac97.4 acardide.4 aceride.4 acphy.4 adc.4 adt7467c.4 adv.4 \
@ -8,7 +8,7 @@ MAN= aac.4 ac97.4 acardide.4 aceride.4 acphy.4 adc.4 adt7467c.4 adv.4 \
ath.4 atppc.4 attimer.4 atw.4 \
auacer.4 audio.4 audiocs.4 auich.4 \
auixp.4 autri.4 auvia.4 awi.4 azalia.4 \
bba.4 bce.4 be.4 bge.4 bnx.4 bha.4 bktr.4 bluetooth.4 bmtphy.4 \
bba.4 bce.4 be.4 bge.4 bnx.4 bha.4 bio.4 bktr.4 bluetooth.4 bmtphy.4 \
bpf.4 brgphy.4 bridge.4 bthidev.4 bthub.4 btkbd.4 btms.4 btsco.4 \
btuart.4 cac.4 cardbus.4 carp.4 ccd.4 cd.4 \
cec.4 cgd.4 cfb.4 ch.4 chipsfb.4 ciphy.4 ciss.4 clcs.4 clct.4 clnp.4 \

124
share/man/man4/bio.4 Normal file
View File

@ -0,0 +1,124 @@
.\" $NetBSD: bio.4,v 1.1 2007/05/01 17:20:10 bouyer Exp $
.\" $OpenBSD: bio.4,v 1.19 2006/09/20 22:22:37 jmc Exp $
.\"
.\" Copyright (c) 2002 Niklas Hallqvist
.\" Copyright (c) 2006 Marco Peereboom
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. The name of the author may not be used to endorse or promote products
.\" derived from this software without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
.\" DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
.\" INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
.\" (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
.\" SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
.\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
.\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd April 8, 2007
.Dt BIO 4
.Os
.Sh NAME
.Nm bio
.Nd Block IO ioctl tunnel pseudo-device
.Sh SYNOPSIS
.Cd "pseudo-device bio"
.Sh DESCRIPTION
The
.Nm
driver provides userland applications
.Xr ioctl 2
access to devices otherwise not found as
.Pa /dev
nodes.
The
.Pa /dev/bio
device node operates by delegating ioctl
calls to a requested device driver.
Only drivers which have registered with the
.Nm
device can be accessed via this interface.
.Pp
The following device drivers register with
.Nm
for volume management:
.Pp
.Bl -tag -width ciss(4)XX -offset indent -compact
.\" .It Xr ami 4
.\" American Megatrends Inc. MegaRAID PATA/SATA/SCSI RAID controller
.\" .It Xr arc 4
.\" Areca Technology Corporation SATA RAID controller
.\" .It Xr ciss 4
.\" Compaq Smart ARRAY 5/6 SAS/SATA/SCSI RAID controller
.It Xr mfi 4
LSI Logic & Dell MegaRAID SAS RAID controller
.El
.Pp
The following ioctl calls apply to the
.Nm bio
device:
.Bl -tag -width BIOCCAPABILITIES
.It Dv BIOCLOCATE
Locate a named device and give back a cookie to the application
for subsequent ioctl calls.
The cookie is used to tunnel further ioctls to the right device.
.It Dv BIOCINQ
Retrieve number of volumes and physical disks for a specific device.
.It Dv BIOCDISK
Retrieve detailed information for the specified physical disk.
Information returned can include status, size, channel, target, lun,
vendor name, serial number and processor device (ses or safte).
.It Dv BIOCVOL
Retrieve detailed information for the specified volume.
Information returned can include status, size, RAID level, number of disks,
device name association (sd?) and vendor name.
.It Dv BIOCALARM
Control the alarm beeper on the device.
Supported states are: disable alarm, enable alarm, silence alarm, status and
test alarm.
.Pp
Note: These options might not be supported on all hardware.
.It Dv BIOCBLINK
Blink an LED of the specified physical disk.
Supported blink states are: blink LED, unblink LED and blink alarm LED.
.Pp
Note: This option is only supported if the disk is governed by ses(4) or
safte(4) and the hardware supports hardware blinking.
.It Dv BIOCSETSTATE
Alter the state of specified physical disk.
Supported states are: create hot-spare, online disk and offline disk.
.El
.Sh FILES
.Bl -tag -width /dev/bio -compact
.It Pa /dev/bio
ioctl tunnel device
.El
.Sh SEE ALSO
.Xr ioctl 2 ,
.Xr bioctl 8
.Sh HISTORY
The
.Nm
driver first appeared in
.Ox 3.2 .
.Sh AUTHORS
.An -nosplit
The
.Nm
driver was written by
.An Niklas Hallqvist Aq niklas@openbsd.org .
The API was written by
.An Marco Peereboom Aq marco@openbsd.org .

View File

@ -1,4 +1,4 @@
# $NetBSD: GENERIC,v 1.138 2007/04/23 04:55:07 dyoung Exp $
# $NetBSD: GENERIC,v 1.139 2007/05/01 17:18:54 bouyer Exp $
#
# GENERIC machine description file
#
@ -22,7 +22,7 @@ include "arch/amd64/conf/std.amd64"
options INCLUDE_CONFIG_FILE # embed config file in kernel binary
#ident "GENERIC-$Revision: 1.138 $"
#ident "GENERIC-$Revision: 1.139 $"
maxusers 32 # estimated number of users
@ -882,6 +882,7 @@ pseudo-device crypto # /dev/crypto device
pseudo-device swcrypto # software crypto implementation
# disk/mass storage pseudo-devices
pseudo-device bio # RAID control device driver
pseudo-device ccd 4 # concatenated/striped disk devices
#pseudo-device cgd 4 # cryptographic disk devices
pseudo-device raid 8 # RAIDframe disk driver

View File

@ -1,4 +1,4 @@
# $NetBSD: GENERIC,v 1.824 2007/04/26 17:11:36 dyoung Exp $
# $NetBSD: GENERIC,v 1.825 2007/05/01 17:18:54 bouyer Exp $
#
# GENERIC machine description file
#
@ -22,7 +22,7 @@ include "arch/i386/conf/std.i386"
options INCLUDE_CONFIG_FILE # embed config file in kernel binary
#ident "GENERIC-$Revision: 1.824 $"
#ident "GENERIC-$Revision: 1.825 $"
maxusers 32 # estimated number of users
@ -1361,6 +1361,7 @@ pseudo-device crypto # /dev/crypto device
pseudo-device swcrypto # software crypto implementation
# disk/mass storage pseudo-devices
pseudo-device bio # RAID control device driver
pseudo-device ccd 4 # concatenated/striped disk devices
#pseudo-device cgd 4 # cryptographic disk devices
pseudo-device raid 8 # RAIDframe disk driver

View File

@ -1,4 +1,4 @@
# $NetBSD: XEN2_DOM0,v 1.24 2007/03/14 12:27:24 drochner Exp $
# $NetBSD: XEN2_DOM0,v 1.25 2007/05/01 17:18:55 bouyer Exp $
include "arch/xen/conf/std.xen"
@ -683,6 +683,7 @@ pseudo-device crypto # /dev/crypto device
pseudo-device swcrypto # software crypto implementation
# disk/mass storage pseudo-devices
pseudo-device bio # RAID control device driver
pseudo-device ccd 4 # concatenated/striped disk devices
#pseudo-device cgd 4 # cryptographic disk devices
pseudo-device raid 8 # RAIDframe disk driver

View File

@ -1,4 +1,4 @@
# $NetBSD: files,v 1.838 2007/04/30 14:44:29 rmind Exp $
# $NetBSD: files,v 1.839 2007/05/01 17:18:55 bouyer Exp $
# @(#)files.newconf 7.5 (Berkeley) 5/10/93
@ -1144,6 +1144,7 @@ defpseudo rnd
defpseudo ksyms
defpseudo nullcons
defpseudo lockstat
defpseudo bio: sysmon_envsys
defpseudo loop: ifnet
defpseudo sl: ifnet
@ -1242,6 +1243,7 @@ file dev/auconv.c auconv | mulaw
file dev/audio.c audio | midi | midibus needs-flag
file dev/audiobell.c audiobell
file dev/aurateconv.c aurateconv needs-flag
file dev/bio.c bio needs-flag
file dev/ccd.c ccd needs-flag
file dev/cgd.c cgd needs-flag
file dev/cgd_crypto.c cgd

View File

@ -1,4 +1,4 @@
# $NetBSD: majors,v 1.33 2007/03/20 16:37:12 drochner Exp $
# $NetBSD: majors,v 1.34 2007/05/01 17:18:55 bouyer Exp $
#
# Device majors for Machine-Independent drivers.
#
@ -30,4 +30,5 @@ device-major lockstat char 177 lockstat
device-major puffs char 178 puffs
device-major srt char 179 srt
device-major drm char 180 drmbase
device-major bio char 181 bio
device-major twa char 187 twa

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.24 2006/09/07 00:20:28 ad Exp $
# $NetBSD: Makefile,v 1.25 2007/05/01 17:18:55 bouyer Exp $
SUBDIR= apm ata bluetooth dec dmover hpc i2o ic ieee1394 ir isa microcode ofw \
pci pckbport pcmcia raidframe sbus scsipi sun tc usb vme wscons
@ -6,6 +6,6 @@ SUBDIR= apm ata bluetooth dec dmover hpc i2o ic ieee1394 ir isa microcode ofw \
INCSDIR= /usr/include/dev
# Only install includes which are used by userland
INCS= ccdvar.h cgdvar.h fssvar.h kttcpio.h lockstat.h md.h vndvar.h
INCS= biovar.h ccdvar.h cgdvar.h fssvar.h kttcpio.h lockstat.h md.h vndvar.h
.include <bsd.kinc.mk>

234
sys/dev/bio.c Normal file
View File

@ -0,0 +1,234 @@
/* $NetBSD: bio.c,v 1.1 2007/05/01 17:20:11 bouyer Exp $ */
/* $OpenBSD: bio.c,v 1.9 2007/03/20 02:35:55 marco Exp $ */
/*
* Copyright (c) 2002 Niklas Hallqvist. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* A device controller ioctl tunnelling device. */
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: bio.c,v 1.1 2007/05/01 17:20:11 bouyer Exp $");
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/device.h>
#include <sys/event.h>
#include <sys/ioctl.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/systm.h>
#include <sys/mutex.h>
#include <sys/proc.h>
#include <sys/kauth.h>
#include <dev/biovar.h>
struct bio_mapping {
LIST_ENTRY(bio_mapping) bm_link;
struct device *bm_dev;
int (*bm_ioctl)(struct device *, u_long, void *);
};
LIST_HEAD(, bio_mapping) bios = LIST_HEAD_INITIALIZER(bios);
static kmutex_t bio_lock;
void bioattach(int);
int bioclose(dev_t, int, int, struct lwp *);
int bioioctl(dev_t, u_long, void *, int, struct lwp *);
int bioopen(dev_t, int, int, struct lwp *);
int bio_delegate_ioctl(struct bio_mapping *, u_long, void *);
struct bio_mapping *bio_lookup(char *);
int bio_validate(void *);
const struct cdevsw bio_cdevsw = {
bioopen, bioclose, noread, nowrite, bioioctl,
nostop, notty, nopoll, nommap, nokqfilter, 0
};
void
bioattach(int nunits)
{
mutex_init(&bio_lock, MUTEX_DRIVER, IPL_BIO);
}
int
bioopen(dev_t dev, int flags, int mode, struct lwp *l)
{
return (0);
}
int
bioclose(dev_t dev, int flags, int mode, struct lwp *l)
{
return (0);
}
int
bioioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
{
struct bio_locate *locate;
struct bio_common *common;
char name[16];
int error;
switch(cmd) {
case BIOCLOCATE:
case BIOCINQ:
case BIOCDISK:
case BIOCVOL:
error = kauth_authorize_device_passthru(l->l_cred, dev,
KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_READCONF, addr);
if (error)
return (error);
break;
case BIOCBLINK:
case BIOCSETSTATE:
error = kauth_authorize_device_passthru(l->l_cred, dev,
KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_WRITECONF, addr);
if (error)
return (error);
break;
case BIOCALARM: {
struct bioc_alarm *alarm = (struct bioc_alarm *)addr;
switch (alarm->ba_opcode) {
case BIOC_SADISABLE:
case BIOC_SAENABLE:
case BIOC_SASILENCE:
case BIOC_SATEST:
error = kauth_authorize_device_passthru(l->l_cred, dev,
KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_WRITECONF, addr);
if (error)
return (error);
break;
case BIOC_GASTATUS:
error = kauth_authorize_device_passthru(l->l_cred, dev,
KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_READCONF, addr);
if (error)
return (error);
break;
default:
return EINVAL;
}
break;
}
default:
return ENOTTY;
}
switch (cmd) {
case BIOCLOCATE:
locate = (struct bio_locate *)addr;
error = copyinstr(locate->bl_name, name, 16, NULL);
if (error != 0)
return (error);
locate->bl_cookie = bio_lookup(name);
if (locate->bl_cookie == NULL)
return (ENOENT);
break;
default:
common = (struct bio_common *)addr;
mutex_enter(&bio_lock);
if (!bio_validate(common->bc_cookie)) {
mutex_exit(&bio_lock);
return (ENOENT);
}
mutex_exit(&bio_lock);
error = bio_delegate_ioctl(
(struct bio_mapping *)common->bc_cookie, cmd, addr);
return (error);
}
return (0);
}
int
bio_register(struct device *dev, int (*ioctl)(struct device *, u_long, void *))
{
struct bio_mapping *bm;
MALLOC(bm, struct bio_mapping *, sizeof *bm, M_DEVBUF, M_NOWAIT);
if (bm == NULL)
return (ENOMEM);
bm->bm_dev = dev;
bm->bm_ioctl = ioctl;
mutex_enter(&bio_lock);
LIST_INSERT_HEAD(&bios, bm, bm_link);
mutex_exit(&bio_lock);
return (0);
}
void
bio_unregister(struct device *dev)
{
struct bio_mapping *bm, *next;
mutex_enter(&bio_lock);
for (bm = LIST_FIRST(&bios); bm != NULL; bm = next) {
next = LIST_NEXT(bm, bm_link);
if (dev == bm->bm_dev) {
LIST_REMOVE(bm, bm_link);
free(bm, M_DEVBUF);
}
}
mutex_exit(&bio_lock);
}
struct bio_mapping *
bio_lookup(char *name)
{
struct bio_mapping *bm;
mutex_enter(&bio_lock);
LIST_FOREACH(bm, &bios, bm_link) {
if (strcmp(name, bm->bm_dev->dv_xname) == 0) {
mutex_exit(&bio_lock);
return (bm);
}
}
mutex_exit(&bio_lock);
return (NULL);
}
int
bio_validate(void *cookie)
{
struct bio_mapping *bm;
LIST_FOREACH(bm, &bios, bm_link) {
if (bm == cookie) {
return (1);
}
}
return (0);
}
int
bio_delegate_ioctl(struct bio_mapping *bm, u_long cmd, void *addr)
{
return (bm->bm_ioctl(bm->bm_dev, cmd, addr));
}

191
sys/dev/biovar.h Normal file
View File

@ -0,0 +1,191 @@
/* $NetBSD: biovar.h,v 1.1 2007/05/01 17:20:11 bouyer Exp $ */
/* $OpenBSD: biovar.h,v 1.26 2007/03/19 03:02:08 marco Exp $ */
/*
* Copyright (c) 2002 Niklas Hallqvist. All rights reserved.
* Copyright (c) 2005 Marco Peereboom. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Devices getting ioctls through this interface should use ioctl class 'B'
* and command numbers starting from 32, lower ones are reserved for generic
* ioctls. All ioctl data must be structures which start with a void *
* cookie.
*/
#include <sys/types.h>
struct bio_common {
void *bc_cookie;
};
/* convert name to a cookie */
#define BIOCLOCATE _IOWR('B', 0, struct bio_locate)
struct bio_locate {
void *bl_cookie;
char *bl_name;
};
#ifdef _KERNEL
int bio_register(struct device *, int (*)(struct device *, u_long,
void *));
void bio_unregister(struct device *);
#endif
#define BIOCINQ _IOWR('B', 32, struct bioc_inq)
struct bioc_inq {
void *bi_cookie;
char bi_dev[16]; /* controller device */
int bi_novol; /* nr of volumes */
int bi_nodisk; /* nr of total disks */
};
#define BIOCDISK _IOWR('B', 33, struct bioc_disk)
/* structure that represents a disk in a RAID volume */
struct bioc_disk {
void *bd_cookie;
u_int16_t bd_channel;
u_int16_t bd_target;
u_int16_t bd_lun;
u_int16_t bd_other_id; /* unused for now */
int bd_volid; /* associate with volume */
int bd_diskid; /* virtual disk */
int bd_status; /* current status */
#define BIOC_SDONLINE 0x00
#define BIOC_SDONLINE_S "Online"
#define BIOC_SDOFFLINE 0x01
#define BIOC_SDOFFLINE_S "Offline"
#define BIOC_SDFAILED 0x02
#define BIOC_SDFAILED_S "Failed"
#define BIOC_SDREBUILD 0x03
#define BIOC_SDREBUILD_S "Rebuild"
#define BIOC_SDHOTSPARE 0x04
#define BIOC_SDHOTSPARE_S "Hot spare"
#define BIOC_SDUNUSED 0x05
#define BIOC_SDUNUSED_S "Unused"
#define BIOC_SDSCRUB 0x06
#define BIOC_SDSCRUB_S "Scrubbing"
#define BIOC_SDINVALID 0xff
#define BIOC_SDINVALID_S "Invalid"
size_t bd_size; /* size of the disk */
char bd_vendor[32]; /* scsi string */
char bd_serial[32]; /* serial number */
char bd_procdev[16]; /* processor device */
};
#define BIOCVOL _IOWR('B', 34, struct bioc_vol)
/* structure that represents a RAID volume */
struct bioc_vol {
void *bv_cookie;
int bv_volid; /* volume id */
int16_t bv_percent; /* percent done operation */
u_int16_t bv_seconds; /* seconds of progress so far */
int bv_status; /* current status */
#define BIOC_SVONLINE 0x00
#define BIOC_SVONLINE_S "Online"
#define BIOC_SVOFFLINE 0x01
#define BIOC_SVOFFLINE_S "Offline"
#define BIOC_SVDEGRADED 0x02
#define BIOC_SVDEGRADED_S "Degraded"
#define BIOC_SVBUILDING 0x03
#define BIOC_SVBUILDING_S "Building"
#define BIOC_SVSCRUB 0x04
#define BIOC_SVSCRUB_S "Scrubbing"
#define BIOC_SVREBUILD 0x05
#define BIOC_SVREBUILD_S "Rebuild"
#define BIOC_SVINVALID 0xff
#define BIOC_SVINVALID_S "Invalid"
size_t bv_size; /* size of the disk */
int bv_level; /* raid level */
int bv_nodisk; /* nr of drives */
char bv_dev[16]; /* device */
char bv_vendor[32]; /* scsi string */
};
#define BIOCALARM _IOWR('B', 35, struct bioc_alarm)
struct bioc_alarm {
void *ba_cookie;
int ba_opcode;
int ba_status; /* only used with get state */
#define BIOC_SADISABLE 0x00 /* disable alarm */
#define BIOC_SAENABLE 0x01 /* enable alarm */
#define BIOC_SASILENCE 0x02 /* silence alarm */
#define BIOC_GASTATUS 0x03 /* get status */
#define BIOC_SATEST 0x04 /* test alarm */
};
#define BIOCBLINK _IOWR('B', 36, struct bioc_blink)
struct bioc_blink {
void *bb_cookie;
u_int16_t bb_channel;
u_int16_t bb_target;
int bb_status; /* current status */
#define BIOC_SBUNBLINK 0x00 /* disable blinking */
#define BIOC_SBBLINK 0x01 /* enable blink */
#define BIOC_SBALARM 0x02 /* enable alarm blink */
};
#define BIOCSETSTATE _IOWR('B', 37, struct bioc_setstate)
struct bioc_setstate {
void *bs_cookie;
u_int16_t bs_channel;
u_int16_t bs_target;
u_int16_t bs_lun;
u_int16_t bs_other_id; /* unused for now */
int bs_status; /* change to this status */
#define BIOC_SSONLINE 0x00 /* online disk */
#define BIOC_SSOFFLINE 0x01 /* offline disk */
#define BIOC_SSHOTSPARE 0x02 /* mark as hotspare */
#define BIOC_SSREBUILD 0x03 /* rebuild on this disk */
int bs_volid; /* volume id for rebuild */
};
#define BIOCCREATERAID _IOWR('B', 38, struct bioc_createraid)
struct bioc_createraid {
void *bc_cookie;
char *bc_dev_list;
u_int16_t bc_dev_list_len;
u_int16_t bc_level;
};
/* kernel and userspace defines */
#define BIOC_INQ 0x0001
#define BIOC_DISK 0x0002
#define BIOC_VOL 0x0004
#define BIOC_ALARM 0x0008
#define BIOC_BLINK 0x0010
#define BIOC_SETSTATE 0x0020
#define BIOC_CREATERAID 0x0040
/* user space defines */
#define BIOC_DEVLIST 0x10000

View File

@ -1,4 +1,4 @@
/* $NetBSD: mfi.c,v 1.3 2007/03/04 06:01:58 christos Exp $ */
/* $NetBSD: mfi.c,v 1.4 2007/05/01 17:18:55 bouyer Exp $ */
/* $OpenBSD: mfi.c,v 1.66 2006/11/28 23:59:45 dlg Exp $ */
/*
* Copyright (c) 2006 Marco Peereboom <marco@peereboom.us>
@ -17,9 +17,9 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: mfi.c,v 1.3 2007/03/04 06:01:58 christos Exp $");
__KERNEL_RCSID(0, "$NetBSD: mfi.c,v 1.4 2007/05/01 17:18:55 bouyer Exp $");
/* #include "bio.h" XXX */
#include "bio.h"
#include <sys/param.h>
#include <sys/systm.h>
@ -46,7 +46,6 @@ __KERNEL_RCSID(0, "$NetBSD: mfi.c,v 1.3 2007/03/04 06:01:58 christos Exp $");
#if NBIO > 0
#include <dev/biovar.h>
#include <sys/sensors.h>
#endif /* NBIO > 0 */
#ifdef MFI_DEBUG
@ -103,7 +102,10 @@ int mfi_ioctl_blink(struct mfi_softc *sc, struct bioc_blink *);
int mfi_ioctl_setstate(struct mfi_softc *, struct bioc_setstate *);
int mfi_bio_hs(struct mfi_softc *, int, int, void *);
int mfi_create_sensors(struct mfi_softc *);
void mfi_refresh_sensors(void *);
int mfi_sensor_gtredata(struct sysmon_envsys *,
struct envsys_tre_data *);
int mfi_sensor_streinfo(struct sysmon_envsys *,
struct envsys_basic_info *);
#endif /* NBIO > 0 */
struct mfi_ccb *
@ -190,11 +192,11 @@ mfi_init_ccb(struct mfi_softc *sc)
}
DNPRINTF(MFI_D_CCB,
"ccb(%d): %p frame: %#x (%#x) sense: %#x (%#x) map: %#x\n",
"ccb(%d): %p frame: %#lx (%#lx) sense: %#lx (%#lx) map: %#lx\n",
ccb->ccb_frame->mfr_header.mfh_context, ccb,
ccb->ccb_frame, ccb->ccb_pframe,
ccb->ccb_sense, ccb->ccb_psense,
ccb->ccb_dmamap);
(u_long)ccb->ccb_frame, (u_long)ccb->ccb_pframe,
(u_long)ccb->ccb_sense, (u_long)ccb->ccb_psense,
(u_long)ccb->ccb_dmamap);
/* add ccb to queue */
mfi_put_ccb(ccb);
@ -223,14 +225,14 @@ mfi_read(struct mfi_softc *sc, bus_size_t r)
BUS_SPACE_BARRIER_READ);
rv = bus_space_read_4(sc->sc_iot, sc->sc_ioh, r);
DNPRINTF(MFI_D_RW, "%s: mr 0x%x 0x08%x ", DEVNAME(sc), r, rv);
DNPRINTF(MFI_D_RW, "%s: mr 0x%lx 0x08%x ", DEVNAME(sc), (u_long)r, rv);
return (rv);
}
void
mfi_write(struct mfi_softc *sc, bus_size_t r, uint32_t v)
{
DNPRINTF(MFI_D_RW, "%s: mw 0x%x 0x%08x", DEVNAME(sc), r, v);
DNPRINTF(MFI_D_RW, "%s: mw 0x%lx 0x%08x", DEVNAME(sc), (u_long)r, v);
bus_space_write_4(sc->sc_iot, sc->sc_ioh, r, v);
bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
@ -243,8 +245,8 @@ mfi_allocmem(struct mfi_softc *sc, size_t size)
struct mfi_mem *mm;
int nsegs;
DNPRINTF(MFI_D_MEM, "%s: mfi_allocmem: %d\n", DEVNAME(sc),
size);
DNPRINTF(MFI_D_MEM, "%s: mfi_allocmem: %ld\n", DEVNAME(sc),
(long)size);
mm = malloc(sizeof(struct mfi_mem), M_DEVBUF, M_NOWAIT);
if (mm == NULL)
@ -270,7 +272,7 @@ mfi_allocmem(struct mfi_softc *sc, size_t size)
goto unmap;
DNPRINTF(MFI_D_MEM, " kva: %p dva: %p map: %p\n",
mm->am_kva, mm->am_map->dm_segs[0].ds_addr, mm->am_map);
mm->am_kva, (void *)mm->am_map->dm_segs[0].ds_addr, mm->am_map);
memset(mm->am_kva, 0, size);
return (mm);
@ -544,7 +546,7 @@ mfi_get_info(struct mfi_softc *sc)
sc->sc_info.mci_host.mih_port_count);
for (i = 0; i < 8; i++)
printf("%.0llx ", sc->sc_info.mci_host.mih_port_addr[i]);
printf("%.0lx ", sc->sc_info.mci_host.mih_port_addr[i]);
printf("\n");
printf("%s: type %.x port_count %d port_addr ",
@ -553,7 +555,7 @@ mfi_get_info(struct mfi_softc *sc)
sc->sc_info.mci_device.mid_port_count);
for (i = 0; i < 8; i++)
printf("%.0llx ", sc->sc_info.mci_device.mid_port_addr[i]);
printf("%.0lx ", sc->sc_info.mci_device.mid_port_addr[i]);
printf("\n");
#endif /* MFI_DEBUG */
@ -586,8 +588,6 @@ mfi_attach(struct mfi_softc *sc)
TAILQ_INIT(&sc->sc_ccb_freeq);
/* rw_init(&sc->sc_lock, "mfi_lock"); XXX */
status = mfi_read(sc, MFI_OMSG0);
sc->sc_max_cmds = status & MFI_STATE_MAXCMD_MASK;
sc->sc_max_sgl = (status & MFI_STATE_MAXSGL_MASK) >> 16;
@ -693,7 +693,6 @@ mfi_attach(struct mfi_softc *sc)
panic("%s: controller registration failed", DEVNAME(sc));
else
sc->sc_ioctl = mfi_ioctl;
if (mfi_create_sensors(sc) != 0)
aprint_error("%s: unable to create sensors\n", DEVNAME(sc));
#endif /* NBIO > 0 */
@ -794,9 +793,11 @@ mfi_intr(void *arg)
/* write status back to acknowledge interrupt */
mfi_write(sc, MFI_OSTS, status);
DNPRINTF(MFI_D_INTR, "%s: mfi_intr %#x %#x\n", DEVNAME(sc), sc, pcq);
pcq = MFIMEM_KVA(sc->sc_pcq);
DNPRINTF(MFI_D_INTR, "%s: mfi_intr %#lx %#lx\n", DEVNAME(sc),
(u_long)sc, (u_long)pcq);
bus_dmamap_sync(sc->sc_dmat, MFIMEM_MAP(sc->sc_pcq), 0,
sizeof(uint32_t) * sc->sc_max_cmds + sizeof(struct mfi_prod_cons),
BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
@ -892,8 +893,8 @@ mfi_scsi_xs_done(struct mfi_ccb *ccb)
struct mfi_softc *sc = ccb->ccb_sc;
struct mfi_frame_header *hdr = &ccb->ccb_frame->mfr_header;
DNPRINTF(MFI_D_INTR, "%s: mfi_scsi_xs_done %#x %#x\n",
DEVNAME(sc), ccb, ccb->ccb_frame);
DNPRINTF(MFI_D_INTR, "%s: mfi_scsi_xs_done %#lx %#lx\n",
DEVNAME(sc), (u_long)ccb, (u_long)ccb->ccb_frame);
if (xs->data != NULL) {
DNPRINTF(MFI_D_INTR, "%s: mfi_scsi_xs_done sync\n",
@ -916,9 +917,9 @@ mfi_scsi_xs_done(struct mfi_ccb *ccb)
ccb->ccb_psense - MFIMEM_DVA(sc->sc_sense),
MFI_SENSE_SIZE, BUS_DMASYNC_POSTREAD);
DNPRINTF(MFI_D_INTR,
"%s: mfi_scsi_xs_done sense %#x %x %x\n",
"%s: mfi_scsi_xs_done sense %#x %lx %lx\n",
DEVNAME(sc), hdr->mfh_scsi_status,
&xs->sense, ccb->ccb_sense);
(u_long)&xs->sense, (u_long)ccb->ccb_sense);
memset(&xs->sense, 0, sizeof(xs->sense));
memcpy(&xs->sense, ccb->ccb_sense,
sizeof(struct scsi_sense_data));
@ -998,9 +999,6 @@ mfi_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req,
uint8_t mbox[MFI_MBOX_SIZE];
int s;
DNPRINTF(MFI_D_CMD, "%s: mfi_scsipi_request req %d opcode: %#x\n",
DEVNAME(sc), req, xs->cmd->opcode);
switch (req) {
case ADAPTER_REQ_GROW_RESOURCES:
/* Not supported. */
@ -1013,6 +1011,10 @@ mfi_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req,
}
xs = arg;
DNPRINTF(MFI_D_CMD, "%s: mfi_scsipi_request req %d opcode: %#x\n",
DEVNAME(sc), req, xs->cmd->opcode);
periph = xs->xs_periph;
target = periph->periph_target;
@ -1142,8 +1144,8 @@ mfi_create_sgl(struct mfi_ccb *ccb, int flags)
union mfi_sgl *sgl;
int error, i;
DNPRINTF(MFI_D_DMA, "%s: mfi_create_sgl %#x\n", DEVNAME(sc),
ccb->ccb_data);
DNPRINTF(MFI_D_DMA, "%s: mfi_create_sgl %#lx\n", DEVNAME(sc),
(u_long)ccb->ccb_data);
if (!ccb->ccb_data)
return (1);
@ -1263,8 +1265,8 @@ mfi_mgmt_done(struct mfi_ccb *ccb)
struct mfi_softc *sc = ccb->ccb_sc;
struct mfi_frame_header *hdr = &ccb->ccb_frame->mfr_header;
DNPRINTF(MFI_D_INTR, "%s: mfi_mgmt_done %#x %#x\n",
DEVNAME(sc), ccb, ccb->ccb_frame);
DNPRINTF(MFI_D_INTR, "%s: mfi_mgmt_done %#lx %#lx\n",
DEVNAME(sc), (u_long)ccb, (u_long)ccb->ccb_frame);
if (ccb->ccb_data != NULL) {
DNPRINTF(MFI_D_INTR, "%s: mfi_mgmt_done sync\n",
@ -1300,10 +1302,9 @@ mfi_ioctl(struct device *dev, u_long cmd, void *addr)
struct mfi_softc *sc = (struct mfi_softc *)dev;
int error = 0;
int s = splbio();
DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl ", DEVNAME(sc));
rw_enter_write(&sc->sc_lock);
switch (cmd) {
case BIOCINQ:
DNPRINTF(MFI_D_IOCTL, "inq\n");
@ -1339,9 +1340,8 @@ mfi_ioctl(struct device *dev, u_long cmd, void *addr)
DNPRINTF(MFI_D_IOCTL, " invalid ioctl\n");
error = EINVAL;
}
rw_exit_write(&sc->sc_lock);
splx(s);
DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl return %x\n", DEVNAME(sc), error);
return (error);
}
@ -1458,6 +1458,8 @@ mfi_ioctl_vol(struct mfi_softc *sc, struct bioc_vol *bv)
rv = 0;
done:
DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_vol done %x\n",
DEVNAME(sc), rv);
return (rv);
}
@ -1468,7 +1470,7 @@ mfi_ioctl_disk(struct mfi_softc *sc, struct bioc_disk *bd)
struct mfi_array *ar;
struct mfi_ld_cfg *ld;
struct mfi_pd_details *pd;
struct scsi_inquiry_data *inqbuf;
struct scsipi_inquiry_data *inqbuf;
char vend[8+16+4+1];
int i, rv = EINVAL;
int arr, vol, disk;
@ -1478,7 +1480,7 @@ mfi_ioctl_disk(struct mfi_softc *sc, struct bioc_disk *bd)
DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_disk %#x\n",
DEVNAME(sc), bd->bd_diskid);
pd = malloc(sizeof *pd, M_DEVBUF, M_WAITOK);
pd = malloc(sizeof *pd, M_DEVBUF, M_WAITOK | M_ZERO);
/* send single element command to retrieve size for full structure */
cfg = malloc(sizeof *cfg, M_DEVBUF, M_WAITOK);
@ -1554,6 +1556,7 @@ mfi_ioctl_disk(struct mfi_softc *sc, struct bioc_disk *bd)
/* get the remaining fields */
*((uint16_t *)&mbox) = ar[arr].pd[disk].mar_pd.mfp_id;
memset(pd, 0, sizeof(*pd));
if (mfi_mgmt(sc, MR_DCMD_PD_GET_INFO, MFI_DATA_IN,
sizeof *pd, pd, mbox))
goto freeme;
@ -1563,7 +1566,7 @@ mfi_ioctl_disk(struct mfi_softc *sc, struct bioc_disk *bd)
/* if pd->mpd_enc_idx is 0 then it is not in an enclosure */
bd->bd_channel = pd->mpd_enc_idx;
inqbuf = (struct scsi_inquiry_data *)&pd->mpd_inq_data;
inqbuf = (struct scsipi_inquiry_data *)&pd->mpd_inq_data;
memcpy(vend, inqbuf->vendor, sizeof vend - 1);
vend[sizeof vend - 1] = '\0';
strlcpy(bd->bd_vendor, vend, sizeof(bd->bd_vendor));
@ -1761,7 +1764,7 @@ mfi_bio_hs(struct mfi_softc *sc, int volid, int type, void *bio_hs)
struct mfi_pd_details *pd;
struct bioc_disk *sdhs;
struct bioc_vol *vdhs;
struct scsi_inquiry_data *inqbuf;
struct scsipi_inquiry_data *inqbuf;
char vend[8+16+4+1];
int i, rv = EINVAL;
uint32_t size;
@ -1772,7 +1775,7 @@ mfi_bio_hs(struct mfi_softc *sc, int volid, int type, void *bio_hs)
if (!bio_hs)
return (EINVAL);
pd = malloc(sizeof *pd, M_DEVBUF, M_WAITOK);
pd = malloc(sizeof *pd, M_DEVBUF, M_WAITOK | M_ZERO);
/* send single element command to retrieve size for full structure */
cfg = malloc(sizeof *cfg, M_DEVBUF, M_WAITOK);
@ -1832,8 +1835,8 @@ mfi_bio_hs(struct mfi_softc *sc, int volid, int type, void *bio_hs)
sdhs->bd_size = pd->mpd_size / 2; /* XXX why? / 2 */
sdhs->bd_channel = pd->mpd_enc_idx;
sdhs->bd_target = pd->mpd_enc_slot;
inqbuf = (struct scsi_inquiry_data *)&pd->mpd_inq_data;
memcpy(vend, inqbuf->vendor, sizeof vend - 1);
inqbuf = (struct scsipi_inquiry_data *)&pd->mpd_inq_data;
memcpy(vend, inqbuf->vendor, sizeof(vend) - 1);
vend[sizeof vend - 1] = '\0';
strlcpy(sdhs->bd_vendor, vend, sizeof(sdhs->bd_vendor));
break;
@ -1854,97 +1857,110 @@ freeme:
int
mfi_create_sensors(struct mfi_softc *sc)
{
struct device *dev;
struct scsibus_softc *ssc;
int i;
struct envsys_range env_ranges[2];
int nsensors = sc->sc_ld_cnt;
TAILQ_FOREACH(dev, &alldevs, dv_list) {
if (dev->dv_parent != &sc->sc_dev)
continue;
env_ranges[0].low = 0;
env_ranges[0].high = nsensors;
env_ranges[0].units = ENVSYS_DRIVE;
env_ranges[1].low = 1;
env_ranges[1].high = 0;
env_ranges[1].units = 0;
/* check if this is the scsibus for the logical disks */
ssc = (struct scsibus_softc *)dev;
if (ssc->adapter_link == &sc->sc_link)
break;
sc->sc_sensor_data =
malloc(sizeof(struct envsys_tre_data) * nsensors,
M_DEVBUF, M_NOWAIT | M_ZERO);
if (sc->sc_sensor_data == NULL) {
aprint_error("%s: can't allocate envsys_tre_data\n",
DEVNAME(sc));
return(ENOMEM);
}
if (ssc == NULL)
return (1);
sc->sc_sensors = malloc(sizeof(struct sensor) * sc->sc_ld_cnt,
M_DEVBUF, M_WAITOK);
if (sc->sc_sensors == NULL)
return (1);
bzero(sc->sc_sensors, sizeof(struct sensor) * sc->sc_ld_cnt);
for (i = 0; i < sc->sc_ld_cnt; i++) {
if (ssc->sc_link[i][0] == NULL)
goto bad;
dev = ssc->sc_link[i][0]->device_softc;
sc->sc_sensors[i].type = SENSOR_DRIVE;
sc->sc_sensors[i].status = SENSOR_S_UNKNOWN;
strlcpy(sc->sc_sensors[i].device, DEVNAME(sc),
sizeof(sc->sc_sensors[i].device));
strlcpy(sc->sc_sensors[i].desc, dev->dv_xname,
sizeof(sc->sc_sensors[i].desc));
sensor_add(&sc->sc_sensors[i]);
sc->sc_sensor_info =
malloc(sizeof(struct envsys_basic_info) * nsensors,
M_DEVBUF, M_NOWAIT | M_ZERO);
if (sc->sc_sensor_info == NULL) {
aprint_error("%s: can't allocate envsys_basic_info\n",
DEVNAME(sc));
return(ENOMEM);
}
for (i = 0; i < nsensors; i++) {
sc->sc_sensor_data[i].sensor = i;
sc->sc_sensor_data[i].units = ENVSYS_DRIVE;
sc->sc_sensor_data[i].validflags = ENVSYS_FVALID;
sc->sc_sensor_data[i].warnflags = ENVSYS_WARN_OK;
sc->sc_sensor_info[i].sensor = i;
sc->sc_sensor_info[i].units = ENVSYS_DRIVE;
sc->sc_sensor_info[i].validflags = ENVSYS_FVALID;
/* logical drives */
snprintf(sc->sc_sensor_info[i].desc,
sizeof(sc->sc_sensor_info[i].desc), "%s:%d",
DEVNAME(sc), i);
}
sc->sc_ranges = env_ranges;
sc->sc_envsys.sme_cookie = sc;
sc->sc_envsys.sme_gtredata = mfi_sensor_gtredata;
sc->sc_envsys.sme_streinfo = mfi_sensor_streinfo;
sc->sc_envsys.sme_nsensors = sc->sc_ld_cnt;
sc->sc_envsys.sme_envsys_version = 1000;
if (sysmon_envsys_register(&sc->sc_envsys)) {
printf("%s: unable to register with sysmon\n", DEVNAME(sc));
return(1);
}
if (sensor_task_register(sc, mfi_refresh_sensors, 10) != 0)
goto bad;
return (0);
bad:
while (--i >= 0)
sensor_del(&sc->sc_sensors[i]);
free(sc->sc_sensors, M_DEVBUF);
return (1);
}
void
mfi_refresh_sensors(void *arg)
int
mfi_sensor_gtredata(struct sysmon_envsys *sme, struct envsys_tre_data *tred)
{
struct mfi_softc *sc = arg;
int i;
struct mfi_softc *sc = sme->sme_cookie;
struct bioc_vol bv;
int s;
if (tred->sensor >= sc->sc_ld_cnt || tred->sensor < 0)
return EINVAL;
for (i = 0; i < sc->sc_ld_cnt; i++) {
bzero(&bv, sizeof(bv));
bv.bv_volid = i;
if (mfi_ioctl_vol(sc, &bv))
return;
switch(bv.bv_status) {
case BIOC_SVOFFLINE:
sc->sc_sensors[i].value = SENSOR_DRIVE_FAIL;
sc->sc_sensors[i].status = SENSOR_S_CRIT;
break;
case BIOC_SVDEGRADED:
sc->sc_sensors[i].value = SENSOR_DRIVE_PFAIL;
sc->sc_sensors[i].status = SENSOR_S_WARN;
break;
case BIOC_SVSCRUB:
case BIOC_SVONLINE:
sc->sc_sensors[i].value = SENSOR_DRIVE_ONLINE;
sc->sc_sensors[i].status = SENSOR_S_OK;
break;
case BIOC_SVINVALID:
/* FALLTRHOUGH */
default:
sc->sc_sensors[i].value = 0; /* unknown */
sc->sc_sensors[i].status = SENSOR_S_UNKNOWN;
}
bzero(&bv, sizeof(bv));
bv.bv_volid = tred->sensor;
s = splbio();
if (mfi_ioctl_vol(sc, &bv)) {
splx(s);
return EIO;
}
splx(s);
switch(bv.bv_status) {
case BIOC_SVOFFLINE:
tred->cur.data_us = ENVSYS_DRIVE_FAIL;
tred->warnflags = ENVSYS_WARN_CRITOVER;
break;
case BIOC_SVDEGRADED:
tred->cur.data_us = ENVSYS_DRIVE_PFAIL;
tred->warnflags = ENVSYS_WARN_OVER;
break;
case BIOC_SVSCRUB:
case BIOC_SVONLINE:
tred->cur.data_us = ENVSYS_DRIVE_ONLINE;
tred->warnflags = ENVSYS_WARN_OK;
break;
case BIOC_SVINVALID:
/* FALLTRHOUGH */
default:
tred->cur.data_us = 0; /* unknown */
tred->warnflags = ENVSYS_WARN_CRITOVER;
}
tred->validflags = ENVSYS_FVALID | ENVSYS_FCURVALID;
tred->units = ENVSYS_DRIVE;
return 0;
}
int
mfi_sensor_streinfo(struct sysmon_envsys *sme, struct envsys_basic_info *binfo)
{
binfo->validflags = 0;
return 0;
}
#endif /* NBIO > 0 */

View File

@ -1,4 +1,4 @@
/* $NetBSD: mfivar.h,v 1.3 2007/03/04 06:01:58 christos Exp $ */
/* $NetBSD: mfivar.h,v 1.4 2007/05/01 17:18:55 bouyer Exp $ */
/* $OpenBSD: mfivar.h,v 1.28 2006/08/31 18:18:46 marco Exp $ */
/*
* Copyright (c) 2006 Marco Peereboom <marco@peereboom.us>
@ -16,9 +16,12 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <dev/sysmon/sysmonvar.h>
#include <sys/envsys.h>
#define DEVNAME(_s) ((_s)->sc_dev.dv_xname)
/* #define MFI_DEBUG */
// #define MFI_DEBUG
#ifdef MFI_DEBUG
extern uint32_t mfi_debug;
#define DPRINTF(x...) do { if (mfi_debug) printf(x); } while(0)
@ -142,7 +145,11 @@ struct mfi_softc {
struct mfi_ccb_list sc_ccb_freeq;
struct sensor *sc_sensors;
struct sysmon_envsys sc_envsys;
#define sc_ranges sc_envsys.sme_ranges
#define sc_sensor_info sc_envsys.sme_sensor_info
#define sc_sensor_data sc_envsys.sme_sensor_data
};
int mfi_attach(struct mfi_softc *sc);

View File

@ -1,4 +1,4 @@
/* $NetBSD: envsys.h,v 1.10 2006/03/15 11:22:23 lukem Exp $ */
/* $NetBSD: envsys.h,v 1.11 2007/05/01 17:18:56 bouyer Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@ -95,16 +95,34 @@ enum envsys_units {
ENVSYS_SAMPHOUR,
ENVSYS_INDICATOR, /* boolean indicator */
ENVSYS_INTEGER, /* generic integer return */
ENVSYS_DRIVE, /* disk status */
ENVSYS_NSENSORS
};
/* drive status */
#define ENVSYS_DRIVE_EMPTY 1
#define ENVSYS_DRIVE_READY 2
#define ENVSYS_DRIVE_POWERUP 3
#define ENVSYS_DRIVE_ONLINE 4
#define ENVSYS_DRIVE_IDLE 5
#define ENVSYS_DRIVE_ACTIVE 6
#define ENVSYS_DRIVE_REBUILD 7
#define ENVSYS_DRIVE_POWERDOWN 8
#define ENVSYS_DRIVE_FAIL 9
#define ENVSYS_DRIVE_PFAIL 10
#ifdef ENVSYSUNITNAMES
static const char * const envsysunitnames[] = {
"degC", "RPM", "VAC", "V", "Ohms", "W",
"A", "Wh", "Ah", "bool", "integer", "Unk"
"A", "Wh", "Ah", "bool", "integer", "drive", "Unk"
};
static const char * const envsysdrivestatus[] = {
"unknown", "empty", "ready", "powering up", "online", "idle", "active",
"rebuilding", "powering down", "failed", "degraded"
};
#endif
/* flags for validflags */
#define ENVSYS_FVALID 0x00000001 /* sensor is valid */
#define ENVSYS_FCURVALID 0x00000002 /* cur for this sens is valid */

View File

@ -1,4 +1,4 @@
/* $NetBSD: envstat.c,v 1.23 2006/08/31 10:25:04 gson Exp $ */
/* $NetBSD: envstat.c,v 1.24 2007/05/01 17:18:56 bouyer Exp $ */
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
@ -38,7 +38,7 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: envstat.c,v 1.23 2006/08/31 10:25:04 gson Exp $");
__RCSID("$NetBSD: envstat.c,v 1.24 2007/05/01 17:18:56 bouyer Exp $");
#endif
#include <fcntl.h>
@ -231,6 +231,9 @@ printrow(int *cetds, envsys_tre_data_t *etds, envsys_basic_info_t *ebis,
/* different units need some magic */
switch (ebis[i].units)
{
case ENVSYS_DRIVE:
printf(": drive %s",
envsysdrivestatus[etds[i].cur.data_us]);
case ENVSYS_INDICATOR:
break;
case ENVSYS_INTEGER:
@ -319,6 +322,10 @@ values(size_t width, int celsius, envsys_tre_data_t *etds,
}
switch(etds[i].units) {
case ENVSYS_DRIVE:
printf(" %*.*s", (int)width, (int)width,
envsysdrivestatus[etds[i].cur.data_us]);
break;
case ENVSYS_INDICATOR:
printf(" %*.*s", (int)width, (int)width,
etds[i].cur.data_us ? "ON" : "OFF");