MFprojects/zfsd:

Revamp the CAM enclosure services driver.
This updated driver uses an in-kernel daemon to track state changes and
publishes physical path location information\for disk elements into the
CAM device database.

Sponsored by:   Spectra Logic Corporation
Sponsored by:   iXsystems, Inc.
Submitted by:   gibbs, will, mav
This commit is contained in:
Alexander Motin 2012-05-24 14:07:44 +00:00
parent 0fc0793eee
commit f6ad3f237a
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=235911
21 changed files with 7976 additions and 2727 deletions

View File

@ -32,7 +32,6 @@
# mjacob@feral.com
#
CFLAGS+= -I/usr/include/cam/scsi -DSESINC="<scsi_ses.h>"
BINDIR?= /usr/sbin
CLEANFILES+= ${MAN}

View File

@ -33,10 +33,13 @@
*/
#include <unistd.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include SESINC
#include <cam/scsi/scsi_all.h>
#include <cam/scsi/scsi_enc.h>
#include "eltsub.h"
@ -46,79 +49,82 @@ geteltnm(int type)
static char rbuf[132];
switch (type) {
case SESTYP_UNSPECIFIED:
case ELMTYP_UNSPECIFIED:
sprintf(rbuf, "Unspecified");
break;
case SESTYP_DEVICE:
sprintf(rbuf, "Device");
case ELMTYP_DEVICE:
sprintf(rbuf, "Device Slot");
break;
case SESTYP_POWER:
sprintf(rbuf, "Power supply");
case ELMTYP_POWER:
sprintf(rbuf, "Power Supply");
break;
case SESTYP_FAN:
sprintf(rbuf, "Cooling element");
case ELMTYP_FAN:
sprintf(rbuf, "Cooling");
break;
case SESTYP_THERM:
sprintf(rbuf, "Temperature sensors");
case ELMTYP_THERM:
sprintf(rbuf, "Temperature Sensors");
break;
case SESTYP_DOORLOCK:
case ELMTYP_DOORLOCK:
sprintf(rbuf, "Door Lock");
break;
case SESTYP_ALARM:
case ELMTYP_ALARM:
sprintf(rbuf, "Audible alarm");
break;
case SESTYP_ESCC:
sprintf(rbuf, "Enclosure services controller electronics");
case ELMTYP_ESCC:
sprintf(rbuf, "Enclosure Eervices Controller Electronics");
break;
case SESTYP_SCC:
sprintf(rbuf, "SCC controller electronics");
case ELMTYP_SCC:
sprintf(rbuf, "SCC Controller Electronics");
break;
case SESTYP_NVRAM:
sprintf(rbuf, "Nonvolatile cache");
case ELMTYP_NVRAM:
sprintf(rbuf, "Nonvolatile Cache");
break;
case SESTYP_UPS:
sprintf(rbuf, "Uninterruptible power supply");
case ELMTYP_INV_OP_REASON:
sprintf(rbuf, "Invalid Operation Reason");
break;
case SESTYP_DISPLAY:
case ELMTYP_UPS:
sprintf(rbuf, "Uninterruptible Power Supply");
break;
case ELMTYP_DISPLAY:
sprintf(rbuf, "Display");
break;
case SESTYP_KEYPAD:
sprintf(rbuf, "Key pad entry device");
case ELMTYP_KEYPAD:
sprintf(rbuf, "Key Pad Entry");
break;
case SESTYP_ENCLOSURE:
case ELMTYP_ENCLOSURE:
sprintf(rbuf, "Enclosure");
break;
case SESTYP_SCSIXVR:
sprintf(rbuf, "SCSI port/transceiver");
case ELMTYP_SCSIXVR:
sprintf(rbuf, "SCSI Port/Transceiver");
break;
case SESTYP_LANGUAGE:
case ELMTYP_LANGUAGE:
sprintf(rbuf, "Language");
break;
case SESTYP_COMPORT:
case ELMTYP_COMPORT:
sprintf(rbuf, "Communication Port");
break;
case SESTYP_VOM:
case ELMTYP_VOM:
sprintf(rbuf, "Voltage Sensor");
break;
case SESTYP_AMMETER:
case ELMTYP_AMMETER:
sprintf(rbuf, "Current Sensor");
break;
case SESTYP_SCSI_TGT:
sprintf(rbuf, "SCSI target port");
case ELMTYP_SCSI_TGT:
sprintf(rbuf, "SCSI Target Port");
break;
case SESTYP_SCSI_INI:
sprintf(rbuf, "SCSI initiator port");
case ELMTYP_SCSI_INI:
sprintf(rbuf, "SCSI Initiator Port");
break;
case SESTYP_SUBENC:
sprintf(rbuf, "Simple sub-enclosure");
case ELMTYP_SUBENC:
sprintf(rbuf, "Simple Subenclosure");
break;
case SESTYP_ARRAY:
sprintf(rbuf, "Array device");
case ELMTYP_ARRAY_DEV:
sprintf(rbuf, "Array Device Slot");
break;
case SESTYP_SASEXPANDER:
case ELMTYP_SAS_EXP:
sprintf(rbuf, "SAS Expander");
break;
case SESTYP_SASCONNECTOR:
case ELMTYP_SAS_CONN:
sprintf(rbuf, "SAS Connector");
break;
default:
@ -134,31 +140,34 @@ scode2ascii(u_char code)
static char rbuf[32];
switch (code & 0xf) {
case SES_OBJSTAT_UNSUPPORTED:
sprintf(rbuf, "status not supported");
sprintf(rbuf, "Unsupported");
break;
case SES_OBJSTAT_OK:
sprintf(rbuf, "ok");
sprintf(rbuf, "OK");
break;
case SES_OBJSTAT_CRIT:
sprintf(rbuf, "critical");
sprintf(rbuf, "Critical");
break;
case SES_OBJSTAT_NONCRIT:
sprintf(rbuf, "non-critical");
sprintf(rbuf, "Noncritical");
break;
case SES_OBJSTAT_UNRECOV:
sprintf(rbuf, "unrecoverable");
sprintf(rbuf, "Unrecoverable");
break;
case SES_OBJSTAT_NOTINSTALLED:
sprintf(rbuf, "not installed");
sprintf(rbuf, "Not Installed");
break;
case SES_OBJSTAT_UNKNOWN:
sprintf(rbuf, "unknown status");
sprintf(rbuf, "Unknown");
break;
case SES_OBJSTAT_NOTAVAIL:
sprintf(rbuf, "status not available");
sprintf(rbuf, "Not Available");
break;
case SES_OBJSTAT_NOACCESS:
sprintf(rbuf, "No Access Allowed");
break;
default:
sprintf(rbuf, "unknown status code %x", code & 0xf);
sprintf(rbuf, "<Status 0x%x>", code & 0xf);
break;
}
return (rbuf);
@ -171,7 +180,7 @@ stat2ascii(int eletype __unused, u_char *cstat)
static char ebuf[256], *scode;
scode = scode2ascii(cstat[0]);
sprintf(ebuf, "Status=%s (bytes=0x%02x 0x%02x 0x%02x 0x%02x)",
sprintf(ebuf, "status: %s (0x%02x 0x%02x 0x%02x 0x%02x)",
scode, cstat[0], cstat[1], cstat[2], cstat[3]);
return (ebuf);
}

View File

@ -33,20 +33,25 @@
*/
#include <unistd.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include SESINC
#include <cam/scsi/scsi_all.h>
#include <cam/scsi/scsi_enc.h>
#include "eltsub.h"
int
main(int a, char **v)
{
ses_object *objp;
ses_objstat ob;
encioc_element_t *objp;
encioc_elm_status_t ob;
encioc_elm_desc_t objd;
encioc_elm_devnames_t objdn;
int fd, nobj, f, i, verbose, quiet, errors;
u_char estat;
@ -73,13 +78,13 @@ main(int a, char **v)
perror(*v);
continue;
}
if (ioctl(fd, SESIOC_GETNOBJ, (caddr_t) &nobj) < 0) {
perror("SESIOC_GETNOBJ");
if (ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj) < 0) {
perror("ENCIOC_GETNELM");
(void) close(fd);
continue;
}
if (ioctl(fd, SESIOC_GETENCSTAT, (caddr_t) &estat) < 0) {
perror("SESIOC_GETENCSTAT");
if (ioctl(fd, ENCIOC_GETENCSTAT, (caddr_t) &estat) < 0) {
perror("ENCIOC_GETENCSTAT");
(void) close(fd);
continue;
}
@ -113,38 +118,64 @@ main(int a, char **v)
}
}
fprintf(stdout, ">\n");
objp = calloc(nobj, sizeof (ses_object));
objp = calloc(nobj, sizeof (encioc_element_t));
if (objp == NULL) {
perror("calloc");
(void) close(fd);
continue;
}
if (ioctl(fd, SESIOC_GETOBJMAP, (caddr_t) objp) < 0) {
perror("SESIOC_GETOBJMAP");
if (ioctl(fd, ENCIOC_GETELMMAP, (caddr_t) objp) < 0) {
perror("ENCIOC_GETELMMAP");
(void) close(fd);
continue;
}
for (i = 0; i < nobj; i++) {
ob.obj_id = objp[i].obj_id;
if (ioctl(fd, SESIOC_GETOBJSTAT, (caddr_t) &ob) < 0) {
perror("SESIOC_GETOBJSTAT");
ob.elm_idx = objp[i].elm_idx;
if (ioctl(fd, ENCIOC_GETELMSTAT, (caddr_t) &ob) < 0) {
perror("ENCIOC_GETELMSTAT");
(void) close(fd);
break;
}
if ((ob.cstat[0] & 0xf) == SES_OBJSTAT_OK) {
if (verbose) {
fprintf(stdout,
"Element 0x%x: %s OK (%s)\n",
ob.obj_id,
geteltnm(objp[i].object_type),
stat2ascii(objp[i].object_type,
ob.cstat));
}
bzero(&objd, sizeof(objd));
objd.elm_idx = objp[i].elm_idx;
objd.elm_desc_len = UINT16_MAX;
objd.elm_desc_str = calloc(UINT16_MAX, sizeof(char));
if (objd.elm_desc_str == NULL) {
perror("calloc");
(void) close(fd);
continue;
}
fprintf(stdout, "Element 0x%x: %s, %s\n",
ob.obj_id, geteltnm(objp[i].object_type),
stat2ascii(objp[i].object_type, ob.cstat));
if (ioctl(fd, ENCIOC_GETELMDESC, (caddr_t)&objd) < 0) {
perror("ENCIOC_GETELMDESC");
(void) close(fd);
break;
}
bzero(&objdn, sizeof(objdn));
objdn.elm_idx = objp[i].elm_idx;
objdn.elm_names_size = 128;
objdn.elm_devnames = calloc(128, sizeof(char));
if (objdn.elm_devnames == NULL) {
perror("calloc");
(void) close(fd);
break;
}
/*
* This ioctl isn't critical and has a good chance
* of returning -1.
*/
(void)ioctl(fd, ENCIOC_GETELMDEVNAMES, (caddr_t)&objdn);
fprintf(stdout, "Element 0x%x: %s", ob.elm_idx,
geteltnm(objp[i].elm_type));
fprintf(stdout, ", %s",
stat2ascii(objp[i].elm_type, ob.cstat));
if (objd.elm_desc_len > 0)
fprintf(stdout, ", descriptor: '%s'",
objd.elm_desc_str);
if (objdn.elm_names_len > 0)
fprintf(stdout, ", dev: '%s'",
objdn.elm_devnames);
fprintf(stdout, "\n");
free(objdn.elm_devnames);
}
free(objp);
(void) close(fd);

View File

@ -33,12 +33,15 @@
*/
#include <unistd.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include SESINC
#include <cam/scsi/scsi_all.h>
#include <cam/scsi/scsi_ses.h>
int
main(int argc, char **argv)

View File

@ -33,11 +33,14 @@
*/
#include <unistd.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include SESINC
#include <cam/scsi/scsi_all.h>
#include <cam/scsi/scsi_ses.h>
#include "eltsub.h"

View File

@ -32,11 +32,14 @@
* mjacob@feral.com
*/
#include <unistd.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include SESINC
#include <cam/scsi/scsi_all.h>
#include <cam/scsi/scsi_ses.h>
int
main(int a, char **v)

View File

@ -33,11 +33,14 @@
*/
#include <unistd.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include SESINC
#include <cam/scsi/scsi_all.h>
#include <cam/scsi/scsi_ses.h>
int
main(int a, char **v)

View File

@ -32,6 +32,8 @@
* mjacob@feral.com
*/
#include <unistd.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
@ -39,7 +41,8 @@
#include <string.h>
#include <syslog.h>
#include <sys/ioctl.h>
#include SESINC
#include <cam/scsi/scsi_all.h>
#include <cam/scsi/scsi_enc.h>
#define ALLSTAT (SES_ENCSTAT_UNRECOV | SES_ENCSTAT_CRITICAL | \
SES_ENCSTAT_NONCRITICAL | SES_ENCSTAT_INFO)
@ -54,7 +57,7 @@ main(int a, char **v)
static const char *usage =
"usage: %s [ -d ] [ -t pollinterval ] device [ device ]\n";
int fd, polltime, dev, devbase, nodaemon;
ses_encstat stat, *carray;
encioc_enc_status_t stat, *carray;
if (a < 2) {
fprintf(stderr, usage, *v);
@ -83,7 +86,7 @@ main(int a, char **v)
return (1);
}
for (dev = devbase; dev < a; dev++)
carray[dev] = (ses_encstat) -1;
carray[dev] = (encioc_enc_status_t) -1;
/*
* Check to make sure we can open all devices
@ -94,8 +97,8 @@ main(int a, char **v)
perror(v[dev]);
return (1);
}
if (ioctl(fd, SESIOC_INIT, NULL) < 0) {
fprintf(stderr, "%s: SESIOC_INIT fails- %s\n",
if (ioctl(fd, ENCIOC_INIT, NULL) < 0) {
fprintf(stderr, "%s: ENCIOC_INIT fails- %s\n",
v[dev], strerror(errno));
return (1);
}
@ -122,9 +125,9 @@ main(int a, char **v)
/*
* Get the actual current enclosure status.
*/
if (ioctl(fd, SESIOC_GETENCSTAT, (caddr_t) &stat) < 0) {
if (ioctl(fd, ENCIOC_GETENCSTAT, (caddr_t) &stat) < 0) {
syslog(LOG_ERR,
"%s: SESIOC_GETENCSTAT- %m", v[dev]);
"%s: ENCIOC_GETENCSTAT- %m", v[dev]);
(void) close(fd);
continue;
}

View File

@ -33,18 +33,21 @@
*/
#include <unistd.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include SESINC
#include <cam/scsi/scsi_all.h>
#include <cam/scsi/scsi_enc.h>
int
main(int a, char **v)
{
int fd;
long val;
ses_encstat stat;
encioc_enc_status_t stat;
if (a != 3) {
fprintf(stderr, "usage: %s device enclosure_status\n", *v);
@ -57,9 +60,9 @@ main(int a, char **v)
}
val = strtol(v[2], NULL, 0);
stat = (ses_encstat) val;
if (ioctl(fd, SESIOC_SETENCSTAT, (caddr_t) &stat) < 0) {
perror("SESIOC_SETENCSTAT");
stat = (encioc_enc_status_t)val;
if (ioctl(fd, ENCIOC_SETENCSTAT, (caddr_t) &stat) < 0) {
perror("ENCIOC_SETENCSTAT");
}
(void) close(fd);
return (0);

View File

@ -33,18 +33,21 @@
*/
#include <unistd.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include SESINC
#include <cam/scsi/scsi_all.h>
#include <cam/scsi/scsi_enc.h>
int
main(int a, char **v)
{
int fd;
int i;
ses_objstat obj;
encioc_elm_status_t obj;
long cvt;
char *x;
@ -64,7 +67,7 @@ main(int a, char **v)
if (x == v[2]) {
goto usage;
}
obj.obj_id = cvt;
obj.elm_idx = cvt;
for (i = 0; i < 4; i++) {
x = v[3 + i];
cvt = strtol(v[3 + i], &x, 0);
@ -73,8 +76,8 @@ main(int a, char **v)
}
obj.cstat[i] = cvt;
}
if (ioctl(fd, SESIOC_SETOBJSTAT, (caddr_t) &obj) < 0) {
perror("SESIOC_SETOBJSTAT");
if (ioctl(fd, ENCIOC_SETELMSTAT, (caddr_t) &obj) < 0) {
perror("ENCIOC_SETELMSTAT");
}
(void) close(fd);
return (0);

1011
sys/cam/scsi/scsi_enc.c Normal file

File diff suppressed because it is too large Load Diff

219
sys/cam/scsi/scsi_enc.h Normal file
View File

@ -0,0 +1,219 @@
/* $FreeBSD$ */
/*-
* Copyright (c) 2000 by Matthew Jacob
* 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,
* without modification, immediately at the beginning of the file.
* 2. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* the GNU Public License ("GPL").
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
*/
#ifndef _SCSI_ENC_H_
#define _SCSI_ENC_H_
#include <cam/scsi/scsi_ses.h>
#define ENCIOC ('s' - 040)
#define ENCIOC_GETNELM _IO(ENCIOC, 1)
#define ENCIOC_GETELMMAP _IO(ENCIOC, 2)
#define ENCIOC_GETENCSTAT _IO(ENCIOC, 3)
#define ENCIOC_SETENCSTAT _IO(ENCIOC, 4)
#define ENCIOC_GETELMSTAT _IO(ENCIOC, 5)
#define ENCIOC_SETELMSTAT _IO(ENCIOC, 6)
#define ENCIOC_GETTEXT _IO(ENCIOC, 7)
#define ENCIOC_INIT _IO(ENCIOC, 8)
#define ENCIOC_GETELMDESC _IO(ENCIOC, 9)
#define ENCIOC_GETELMDEVNAMES _IO(ENCIOC, 10)
#define ENCIOC_GETSTRING _IO(ENCIOC, 11)
#define ENCIOC_SETSTRING _IO(ENCIOC, 12)
/*
* Platform Independent Definitions for enclosure devices.
*/
/*
* SCSI Based Environmental Services Application Defines
*
* Based almost entirely on SCSI-3 ENC Revision 8A specification,
* but slightly abstracted as the underlying device may in fact
* be a SAF-TE or vendor unique device.
*/
/*
* ENC Driver Operations:
* (The defines themselves are platform and access method specific)
*
* ENCIOC_GETNELM
* ENCIOC_GETELMMAP
* ENCIOC_GETENCSTAT
* ENCIOC_SETENCSTAT
* ENCIOC_GETELMSTAT
* ENCIOC_SETELMSTAT
* ENCIOC_INIT
*
*
* An application finds out how many elements an enclosure instance
* is managing by performing a ENCIOC_GETNELM operation. It then
* performs a ENCIOC_GETELMMAP to get the map that contains the
* elment identifiers for all elements (see encioc_element_t below).
* This information is static.
*
* The application may perform ENCIOC_GETELMSTAT operations to retrieve
* status on an element (see the enc_elm_status_t structure below),
* ENCIOC_SETELMSTAT operations to set status for an element.
*
* Similarly, overall enclosure status me be fetched or set via
* ENCIOC_GETENCSTAT or ENCIOC_SETENCSTAT operations (see encioc_enc_status_t
* below).
*
* Readers should note that there is nothing that requires either a set
* or a clear operation to actually latch and do anything in the target.
*
* A ENCIOC_INIT operation causes the enclosure to be initialized.
*/
/* Element Types */
typedef enum {
ELMTYP_UNSPECIFIED = 0x00,
ELMTYP_DEVICE = 0x01,
ELMTYP_POWER = 0x02,
ELMTYP_FAN = 0x03,
ELMTYP_THERM = 0x04,
ELMTYP_DOORLOCK = 0x05,
ELMTYP_ALARM = 0x06,
ELMTYP_ESCC = 0x07, /* Enclosure SCC */
ELMTYP_SCC = 0x08, /* SCC */
ELMTYP_NVRAM = 0x09,
ELMTYP_INV_OP_REASON = 0x0a,
ELMTYP_UPS = 0x0b,
ELMTYP_DISPLAY = 0x0c,
ELMTYP_KEYPAD = 0x0d,
ELMTYP_ENCLOSURE = 0x0e,
ELMTYP_SCSIXVR = 0x0f,
ELMTYP_LANGUAGE = 0x10,
ELMTYP_COMPORT = 0x11,
ELMTYP_VOM = 0x12,
ELMTYP_AMMETER = 0x13,
ELMTYP_SCSI_TGT = 0x14,
ELMTYP_SCSI_INI = 0x15,
ELMTYP_SUBENC = 0x16,
ELMTYP_ARRAY_DEV = 0x17,
ELMTYP_SAS_EXP = 0x18, /* SAS expander */
ELMTYP_SAS_CONN = 0x19 /* SAS connector */
} elm_type_t;
typedef struct encioc_element {
/* Element Index */
unsigned int elm_idx;
/* ID of SubEnclosure containing Element*/
unsigned int elm_subenc_id;
/* Element Type */
elm_type_t elm_type;
} encioc_element_t;
/*
* Overall Enclosure Status
*/
typedef unsigned char encioc_enc_status_t;
/*
* Element Status
*/
typedef struct encioc_elm_status {
unsigned int elm_idx;
unsigned char cstat[4];
} encioc_elm_status_t;
/*
* ENC String structure, for StringIn and StringOut commands; use this with
* the ENCIOC_GETSTRING and ENCIOC_SETSTRING ioctls.
*/
typedef struct encioc_string {
size_t bufsiz; /* IN/OUT: length of string provided/returned */
#define ENC_STRING_MAX 0xffff
uint8_t *buf; /* IN/OUT: string */
} encioc_string_t;
/*============================================================================*/
/*
* SES v2 r20 6.1.10 (pg 39) - Element Descriptor diagnostic page
* Tables 21, 22, and 23
*/
typedef struct encioc_elm_desc {
unsigned int elm_idx; /* IN: elment requested */
uint16_t elm_desc_len; /* IN: buffer size; OUT: bytes written */
char *elm_desc_str; /* IN/OUT: buffer for descriptor data */
} encioc_elm_desc_t;
/*
* ENCIOC_GETELMDEVNAMES:
* ioctl structure to get an element's device names, if available
*/
typedef struct encioc_elm_devnames {
unsigned int elm_idx; /* IN: element index */
size_t elm_names_size;/* IN: size of elm_devnames */
size_t elm_names_len; /* OUT: actual size returned */
/*
* IN/OUT: comma separated list of peripheral driver
* instances servicing this element.
*/
char *elm_devnames;
} encioc_elm_devnames_t;
/* ioctl structure for requesting FC info for a port */
typedef struct encioc_elm_fc_port {
unsigned int elm_idx;
unsigned int port_idx;
struct ses_elm_fc_port port_data;
} encioc_elm_fc_port_t;
/* ioctl structure for requesting SAS info for element phys */
typedef struct encioc_elm_sas_device_phy {
unsigned int elm_idx;
unsigned int phy_idx;
struct ses_elm_sas_device_phy phy_data;
} enioc_elm_sas_phy_t;
/* ioctl structure for requesting SAS info for an expander phy */
typedef struct encioc_elm_sas_expander_phy {
unsigned int elm_idx;
unsigned int phy_idx;
struct ses_elm_sas_expander_phy phy_data;
} encioc_elm_sas_expander_phy_t;
/* ioctl structure for requesting SAS info for a port phy */
typedef struct encioc_elm_sas_port_phy {
unsigned int elm_idx;
unsigned int phy_idx;
struct ses_elm_sas_port_phy phy_data;
} enioc_elm_sas_port_phy_t;
/* ioctl structure for requesting additional status for an element */
typedef struct encioc_addl_status {
unsigned int elm_idx;
union ses_elm_addlstatus_descr_hdr addl_hdr;
union ses_elm_addlstatus_proto_hdr proto_hdr;
} enioc_addl_status_t;
#endif /* _SCSI_ENC_H_ */

View File

@ -0,0 +1,230 @@
/*-
* Copyright (c) 2000 Matthew Jacob
* 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,
* without modification, immediately at the beginning of the file.
* 2. 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 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 AUTHOR 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.
*
* $FreeBSD$
*/
/*
* This file contains definitions only intended for use within
* sys/cam/scsi/scsi_enc*.c, and not in other kernel components.
*/
#ifndef __SCSI_ENC_INTERNAL_H__
#define __SCSI_ENC_INTERNAL_H__
typedef struct enc_element {
uint32_t
enctype : 8, /* enclosure type */
subenclosure : 8, /* subenclosure id */
svalid : 1, /* enclosure information valid */
overall_status_elem: 1,/*
* This object represents generic
* status about all objects of this
* type.
*/
priv : 14; /* private data, per object */
uint8_t encstat[4]; /* state && stats */
uint8_t *physical_path; /* Device physical path data. */
u_int physical_path_len; /* Length of device path data. */
void *elm_private; /* per-type object data */
} enc_element_t;
typedef enum {
ENC_NONE,
ENC_SES_SCSI2,
ENC_SES,
ENC_SES_PASSTHROUGH,
ENC_SEN,
ENC_SAFT,
ENC_SEMB_SES,
ENC_SEMB_SAFT
} enctyp;
/* Platform Independent Driver Internal Definitions for enclosure devices. */
typedef struct enc_softc enc_softc_t;
struct enc_fsm_state;
typedef int fsm_fill_handler_t(enc_softc_t *ssc,
struct enc_fsm_state *state,
union ccb *ccb,
uint8_t *buf);
typedef int fsm_error_handler_t(union ccb *ccb, uint32_t cflags,
uint32_t sflags);
typedef int fsm_done_handler_t(enc_softc_t *ssc,
struct enc_fsm_state *state, union ccb *ccb,
uint8_t **bufp, int error, int xfer_len);
struct enc_fsm_state {
const char *name;
int page_code;
size_t buf_size;
uint32_t timeout;
fsm_fill_handler_t *fill;
fsm_done_handler_t *done;
fsm_error_handler_t *error;
};
typedef int (enc_softc_init_t)(enc_softc_t *);
typedef void (enc_softc_invalidate_t)(enc_softc_t *);
typedef void (enc_softc_cleanup_t)(enc_softc_t *);
typedef int (enc_init_enc_t)(enc_softc_t *);
typedef int (enc_get_enc_status_t)(enc_softc_t *, int);
typedef int (enc_set_enc_status_t)(enc_softc_t *, encioc_enc_status_t, int);
typedef int (enc_get_elm_status_t)(enc_softc_t *, encioc_elm_status_t *, int);
typedef int (enc_set_elm_status_t)(enc_softc_t *, encioc_elm_status_t *, int);
typedef int (enc_get_elm_desc_t)(enc_softc_t *, encioc_elm_desc_t *);
typedef int (enc_get_elm_devnames_t)(enc_softc_t *, encioc_elm_devnames_t *);
typedef int (enc_handle_string_t)(enc_softc_t *, encioc_string_t *, int);
typedef void (enc_device_found_t)(enc_softc_t *);
typedef void (enc_poll_status_t)(enc_softc_t *);
struct enc_vec {
enc_softc_invalidate_t *softc_invalidate;
enc_softc_cleanup_t *softc_cleanup;
enc_init_enc_t *init_enc;
enc_get_enc_status_t *get_enc_status;
enc_set_enc_status_t *set_enc_status;
enc_get_elm_status_t *get_elm_status;
enc_set_elm_status_t *set_elm_status;
enc_get_elm_desc_t *get_elm_desc;
enc_get_elm_devnames_t *get_elm_devnames;
enc_handle_string_t *handle_string;
enc_device_found_t *device_found;
enc_poll_status_t *poll_status;
};
typedef struct enc_cache {
enc_element_t *elm_map; /* objects */
int nelms; /* number of objects */
encioc_enc_status_t enc_status; /* overall status */
void *private; /* per-type private data */
} enc_cache_t;
/* Enclosure instance toplevel structure */
struct enc_softc {
enctyp enc_type; /* type of enclosure */
struct enc_vec enc_vec; /* vector to handlers */
void *enc_private; /* per-type private data */
/**
* "Published" configuration and state data available to
* external consumers.
*/
enc_cache_t enc_cache;
/**
* Configuration and state data being actively updated
* by the enclosure daemon.
*/
enc_cache_t enc_daemon_cache;
struct sx enc_cache_lock;
uint8_t enc_flags;
#define ENC_FLAG_INVALID 0x01
#define ENC_FLAG_INITIALIZED 0x02
#define ENC_FLAG_SHUTDOWN 0x04
union ccb saved_ccb;
struct cdev *enc_dev;
struct cam_periph *periph;
/* Bitmap of pending operations. */
uint32_t pending_actions;
/* The action on which the state machine is currently working. */
uint32_t current_action;
#define ENC_UPDATE_NONE 0x00
#define ENC_UPDATE_INVALID 0xff
/* Callout for auto-updating enclosure status */
struct callout status_updater;
struct proc *enc_daemon;
struct enc_fsm_state *enc_fsm_states;
struct intr_config_hook enc_boot_hold_ch;
};
static inline enc_cache_t *
enc_other_cache(enc_softc_t *enc, enc_cache_t *primary)
{
return (primary == &enc->enc_cache
? &enc->enc_daemon_cache : &enc->enc_cache);
}
/* SES Management mode page - SES2r20 Table 59 */
struct ses_mgmt_mode_page {
struct scsi_mode_header_6 header;
struct scsi_mode_blk_desc blk_desc;
uint8_t byte0; /* ps : 1, spf : 1, page_code : 6 */
#define SES_MGMT_MODE_PAGE_CODE 0x14
uint8_t length;
#define SES_MGMT_MODE_PAGE_LEN 6
uint8_t reserved[3];
uint8_t byte5; /* reserved : 7, enbltc : 1 */
#define SES_MGMT_TIMED_COMP_EN 0x1
uint8_t max_comp_time[2];
};
/* Enclosure core interface for sub-drivers */
int enc_runcmd(struct enc_softc *, char *, int, char *, int *);
void enc_log(struct enc_softc *, const char *, ...);
void enc_done(struct cam_periph *, union ccb *);
int enc_error(union ccb *, uint32_t, uint32_t);
void enc_update_request(enc_softc_t *, uint32_t);
/* SES Native interface */
enc_softc_init_t ses_softc_init;
/* SAF-TE interface */
enc_softc_init_t safte_softc_init;
/* Helper macros */
MALLOC_DECLARE(M_SCSIENC);
#define ENC_CFLAGS CAM_RETRY_SELTO
#define ENC_FLAGS SF_NO_PRINT | SF_RETRY_UA
#define STRNCMP strncmp
#define PRINTF printf
#define ENC_LOG enc_log
#if defined(DEBUG) || defined(ENC_DEBUG)
#define ENC_DLOG enc_log
#else
#define ENC_DLOG if (0) enc_log
#endif
#define ENC_VLOG if (bootverbose) enc_log
#define ENC_MALLOC(amt) malloc(amt, M_SCSIENC, M_NOWAIT)
#define ENC_MALLOCZ(amt) malloc(amt, M_SCSIENC, M_ZERO|M_NOWAIT)
/* Cast away const avoiding GCC warnings. */
#define ENC_FREE(ptr) free((void *)((uintptr_t)ptr), M_SCSIENC)
#define ENC_FREE_AND_NULL(ptr) do { \
if (ptr != NULL) { \
ENC_FREE(ptr); \
ptr = NULL; \
} \
} while(0)
#define MEMZERO bzero
#define MEMCPY(dest, src, amt) bcopy(src, dest, amt)
#endif /* __SCSI_ENC_INTERNAL_H__ */

File diff suppressed because it is too large Load Diff

2816
sys/cam/scsi/scsi_enc_ses.c Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -134,7 +134,9 @@ cam/scsi/scsi_low_pisa.c optional ct | ncv | nsp | stg
cam/scsi/scsi_pass.c optional pass
cam/scsi/scsi_pt.c optional pt
cam/scsi/scsi_sa.c optional sa
cam/scsi/scsi_ses.c optional ses
cam/scsi/scsi_enc.c optional ses
cam/scsi/scsi_enc_ses.c optional ses
cam/scsi/scsi_enc_safte.c optional ses
cam/scsi/scsi_sg.c optional sg
cam/scsi/scsi_targ_bh.c optional targbh
cam/scsi/scsi_target.c optional targ

View File

@ -1266,8 +1266,53 @@ static int
devfs_readlink(struct vop_readlink_args *ap)
{
struct devfs_dirent *de;
struct cdev_priv *cdp;
de = ap->a_vp->v_data;
cdp = de->de_cdp;
if (cdp != NULL && (cdp->cdp_c.si_flags & SI_ALIAS) != 0) {
struct devfs_mount *dmp;
struct prison *pr;
char *mp;
int mp_len;
int pr_path_len;
int err;
/*
* For device aliases, construct an absolute symlink (to
* shorten its length and avoid the ugliness of a relative
* link) by prepending the fully qualified path to the root
* of this devfs. For a non-jailed process, the devfs root
* is our mount point. For a jailed process, we must remove
* any jail prefix in our mount point so that our response
* matches the user process's world view.
*/
dmp = VFSTODEVFS(ap->a_vp->v_mount);
mp = dmp->dm_mount->mnt_stat.f_mntonname;
mp_len = strlen(mp);
pr = ap->a_cred->cr_prison;
pr_path_len = strlen(pr->pr_path);
if (strncmp(pr->pr_path, mp, pr_path_len) == 0
&& mp[pr_path_len] == '/') {
mp += pr_path_len;
mp_len -= pr_path_len;
}
err = uiomove(mp, mp_len, ap->a_uio);
if (err != 0)
return (err);
/*
* Devfs cannot be the root file system, so its
* mount point must always be terminated by a '/'.
*/
err = uiomove("/", 1, ap->a_uio);
if (err != 0)
return (err);
}
return (uiomove(de->de_symlink, strlen(de->de_symlink), ap->a_uio));
}

View File

@ -14,7 +14,7 @@ SRCS+= opt_scsi.h
SRCS+= opt_cd.h
SRCS+= opt_pt.h
SRCS+= opt_sa.h
SRCS+= opt_ses.h
SRCS+= opt_enc.h
SRCS+= device_if.h bus_if.h vnode_if.h
SRCS+= cam.c
.if exists($S/${MACHINE}/${MACHINE}/cam_machdep.c)
@ -26,7 +26,9 @@ SRCS+= scsi_da.c
SRCS+= scsi_pass.c
SRCS+= scsi_pt.c
SRCS+= scsi_sa.c
SRCS+= scsi_ses.c
SRCS+= scsi_enc.c
SRCS+= scsi_enc_ses.c
SRCS+= scsi_enc_safte.c
SRCS+= scsi_sg.c
SRCS+= scsi_targ_bh.c scsi_target.c
SRCS+= scsi_xpt.c

View File

@ -63,6 +63,8 @@ BEGIN {
print "#include <netinet6/ip6_mroute.h>"
print "#include <stdio.h>"
print "#include <cam/cam.h>"
print "#include <stddef.h>"
print "#include <stdint.h>"
print ""
print ioctl_includes
print ""