svn commit: r235911 - in head: share/examples/ses
share/examples/ses/srcs sys/cam/scsi sys/conf sys/fs/devfs
sys/modules/cam usr.bin/kdump
Alexander Motin
mav at FreeBSD.org
Thu May 24 14:07:44 UTC 2012
Author: mav
Date: Thu May 24 14:07:44 2012
New Revision: 235911
URL: http://svn.freebsd.org/changeset/base/235911
Log:
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
Added:
head/sys/cam/scsi/scsi_enc.c (contents, props changed)
head/sys/cam/scsi/scsi_enc.h (contents, props changed)
head/sys/cam/scsi/scsi_enc_internal.h (contents, props changed)
head/sys/cam/scsi/scsi_enc_safte.c (contents, props changed)
head/sys/cam/scsi/scsi_enc_ses.c (contents, props changed)
Deleted:
head/sys/cam/scsi/scsi_ses.c
Modified:
head/share/examples/ses/Makefile.inc
head/share/examples/ses/srcs/eltsub.c
head/share/examples/ses/srcs/getencstat.c
head/share/examples/ses/srcs/getnobj.c
head/share/examples/ses/srcs/getobjmap.c
head/share/examples/ses/srcs/getobjstat.c
head/share/examples/ses/srcs/inienc.c
head/share/examples/ses/srcs/sesd.c
head/share/examples/ses/srcs/setencstat.c
head/share/examples/ses/srcs/setobjstat.c
head/sys/cam/scsi/scsi_ses.h
head/sys/conf/files
head/sys/fs/devfs/devfs_vnops.c
head/sys/modules/cam/Makefile
head/usr.bin/kdump/mkioctls
Modified: head/share/examples/ses/Makefile.inc
==============================================================================
--- head/share/examples/ses/Makefile.inc Thu May 24 13:15:15 2012 (r235910)
+++ head/share/examples/ses/Makefile.inc Thu May 24 14:07:44 2012 (r235911)
@@ -32,7 +32,6 @@
# mjacob at feral.com
#
-CFLAGS+= -I/usr/include/cam/scsi -DSESINC="<scsi_ses.h>"
BINDIR?= /usr/sbin
CLEANFILES+= ${MAN}
Modified: head/share/examples/ses/srcs/eltsub.c
==============================================================================
--- head/share/examples/ses/srcs/eltsub.c Thu May 24 13:15:15 2012 (r235910)
+++ head/share/examples/ses/srcs/eltsub.c Thu May 24 14:07:44 2012 (r235911)
@@ -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
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);
}
Modified: head/share/examples/ses/srcs/getencstat.c
==============================================================================
--- head/share/examples/ses/srcs/getencstat.c Thu May 24 13:15:15 2012 (r235910)
+++ head/share/examples/ses/srcs/getencstat.c Thu May 24 14:07:44 2012 (r235911)
@@ -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);
Modified: head/share/examples/ses/srcs/getnobj.c
==============================================================================
--- head/share/examples/ses/srcs/getnobj.c Thu May 24 13:15:15 2012 (r235910)
+++ head/share/examples/ses/srcs/getnobj.c Thu May 24 14:07:44 2012 (r235911)
@@ -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)
Modified: head/share/examples/ses/srcs/getobjmap.c
==============================================================================
--- head/share/examples/ses/srcs/getobjmap.c Thu May 24 13:15:15 2012 (r235910)
+++ head/share/examples/ses/srcs/getobjmap.c Thu May 24 14:07:44 2012 (r235911)
@@ -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"
Modified: head/share/examples/ses/srcs/getobjstat.c
==============================================================================
--- head/share/examples/ses/srcs/getobjstat.c Thu May 24 13:15:15 2012 (r235910)
+++ head/share/examples/ses/srcs/getobjstat.c Thu May 24 14:07:44 2012 (r235911)
@@ -32,11 +32,14 @@
* mjacob at 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)
Modified: head/share/examples/ses/srcs/inienc.c
==============================================================================
--- head/share/examples/ses/srcs/inienc.c Thu May 24 13:15:15 2012 (r235910)
+++ head/share/examples/ses/srcs/inienc.c Thu May 24 14:07:44 2012 (r235911)
@@ -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)
Modified: head/share/examples/ses/srcs/sesd.c
==============================================================================
--- head/share/examples/ses/srcs/sesd.c Thu May 24 13:15:15 2012 (r235910)
+++ head/share/examples/ses/srcs/sesd.c Thu May 24 14:07:44 2012 (r235911)
@@ -32,6 +32,8 @@
* mjacob at 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;
}
Modified: head/share/examples/ses/srcs/setencstat.c
==============================================================================
--- head/share/examples/ses/srcs/setencstat.c Thu May 24 13:15:15 2012 (r235910)
+++ head/share/examples/ses/srcs/setencstat.c Thu May 24 14:07:44 2012 (r235911)
@@ -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);
Modified: head/share/examples/ses/srcs/setobjstat.c
==============================================================================
--- head/share/examples/ses/srcs/setobjstat.c Thu May 24 13:15:15 2012 (r235910)
+++ head/share/examples/ses/srcs/setobjstat.c Thu May 24 14:07:44 2012 (r235911)
@@ -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 @@ usage:
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 @@ usage:
}
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);
Added: head/sys/cam/scsi/scsi_enc.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/sys/cam/scsi/scsi_enc.c Thu May 24 14:07:44 2012 (r235911)
@@ -0,0 +1,1011 @@
+/*-
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+
+#include <sys/conf.h>
+#include <sys/errno.h>
+#include <sys/fcntl.h>
+#include <sys/kernel.h>
+#include <sys/kthread.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/queue.h>
+#include <sys/sx.h>
+#include <sys/systm.h>
+#include <sys/sysctl.h>
+#include <sys/types.h>
+
+#include <machine/stdarg.h>
+
+#include <cam/cam.h>
+#include <cam/cam_ccb.h>
+#include <cam/cam_debug.h>
+#include <cam/cam_periph.h>
+#include <cam/cam_xpt_periph.h>
+
+#include <cam/scsi/scsi_all.h>
+#include <cam/scsi/scsi_message.h>
+#include <cam/scsi/scsi_enc.h>
+#include <cam/scsi/scsi_enc_internal.h>
+
+#include <opt_enc.h>
+
+MALLOC_DEFINE(M_SCSIENC, "SCSI ENC", "SCSI ENC buffers");
+
+/* Enclosure type independent driver */
+
+#define SEN_ID "UNISYS SUN_SEN"
+#define SEN_ID_LEN 24
+
+static d_open_t enc_open;
+static d_close_t enc_close;
+static d_ioctl_t enc_ioctl;
+static periph_init_t enc_init;
+static periph_ctor_t enc_ctor;
+static periph_oninv_t enc_oninvalidate;
+static periph_dtor_t enc_dtor;
+static periph_start_t enc_start;
+
+static void enc_async(void *, uint32_t, struct cam_path *, void *);
+static enctyp enc_type(struct ccb_getdev *);
+
+SYSCTL_NODE(_kern_cam, OID_AUTO, enc, CTLFLAG_RD, 0,
+ "CAM Enclosure Services driver");
+
+static struct periph_driver encdriver = {
+ enc_init, "ses",
+ TAILQ_HEAD_INITIALIZER(encdriver.units), /* generation */ 0
+};
+
+PERIPHDRIVER_DECLARE(enc, encdriver);
+
+static struct cdevsw enc_cdevsw = {
+ .d_version = D_VERSION,
+ .d_open = enc_open,
+ .d_close = enc_close,
+ .d_ioctl = enc_ioctl,
+ .d_name = "ses",
+ .d_flags = 0,
+};
+
+static void
+enc_init(void)
+{
+ cam_status status;
+
+ /*
+ * Install a global async callback. This callback will
+ * receive async callbacks like "new device found".
+ */
+ status = xpt_register_async(AC_FOUND_DEVICE, enc_async, NULL, NULL);
+
+ if (status != CAM_REQ_CMP) {
+ printf("enc: Failed to attach master async callback "
+ "due to status 0x%x!\n", status);
+ }
+}
+
+static void
+enc_oninvalidate(struct cam_periph *periph)
+{
+ struct enc_softc *enc;
+
+ enc = periph->softc;
+
+ enc->enc_flags |= ENC_FLAG_INVALID;
+
+ /* If the sub-driver has an invalidate routine, call it */
+ if (enc->enc_vec.softc_invalidate != NULL)
+ enc->enc_vec.softc_invalidate(enc);
+
+ /*
+ * Unregister any async callbacks.
+ */
+ xpt_register_async(0, enc_async, periph, periph->path);
+
+ /*
+ * Shutdown our daemon.
+ */
+ enc->enc_flags |= ENC_FLAG_SHUTDOWN;
+ if (enc->enc_daemon != NULL) {
+ /* Signal and wait for the ses daemon to terminate. */
+ wakeup(enc->enc_daemon);
+ /*
+ * We're called with the SIM mutex held, but we're dropping
+ * the update mutex here on sleep. So we have to manually
+ * drop the SIM mutex.
+ */
+ cam_periph_sleep(enc->periph, enc->enc_daemon,
+ PUSER, "thtrm", 0);
+ }
+ callout_drain(&enc->status_updater);
+
+ xpt_print(periph->path, "lost device\n");
+}
+
+static void
+enc_dtor(struct cam_periph *periph)
+{
+ struct enc_softc *enc;
+
+ enc = periph->softc;
+
+ xpt_print(periph->path, "removing device entry\n");
+ cam_periph_unlock(periph);
+ destroy_dev(enc->enc_dev);
+ cam_periph_lock(periph);
+
+ /* If the sub-driver has a cleanup routine, call it */
+ if (enc->enc_vec.softc_cleanup != NULL)
+ enc->enc_vec.softc_cleanup(enc);
+
+ if (enc->enc_boot_hold_ch.ich_func != NULL) {
+ config_intrhook_disestablish(&enc->enc_boot_hold_ch);
+ enc->enc_boot_hold_ch.ich_func = NULL;
+ }
+
+ ENC_FREE(enc);
+}
+
+static void
+enc_async(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
+{
+ struct cam_periph *periph;
+
+ periph = (struct cam_periph *)callback_arg;
+
+ switch(code) {
+ case AC_FOUND_DEVICE:
+ {
+ struct ccb_getdev *cgd;
+ cam_status status;
+ path_id_t path_id;
+
+ cgd = (struct ccb_getdev *)arg;
+ if (arg == NULL) {
+ break;
+ }
+
+ if (enc_type(cgd) == ENC_NONE) {
+ /*
+ * Schedule announcement of the ENC bindings for
+ * this device if it is managed by a SEP.
+ */
+ path_id = xpt_path_path_id(path);
+ xpt_lock_buses();
+ TAILQ_FOREACH(periph, &encdriver.units, unit_links) {
+ struct enc_softc *softc;
+
+ softc = (struct enc_softc *)periph->softc;
+ if (xpt_path_path_id(periph->path) != path_id
+ || softc == NULL
+ || (softc->enc_flags & ENC_FLAG_INITIALIZED)
+ == 0
+ || softc->enc_vec.device_found == NULL)
+ continue;
+
+ softc->enc_vec.device_found(softc);
+ }
+ xpt_unlock_buses();
+ return;
+ }
+
+ status = cam_periph_alloc(enc_ctor, enc_oninvalidate,
+ enc_dtor, enc_start, "ses", CAM_PERIPH_BIO,
+ cgd->ccb_h.path, enc_async, AC_FOUND_DEVICE, cgd);
+
+ if (status != CAM_REQ_CMP && status != CAM_REQ_INPROG) {
+ printf("enc_async: Unable to probe new device due to "
+ "status 0x%x\n", status);
+ }
+ break;
+ }
+ default:
+ cam_periph_async(periph, code, path, arg);
+ break;
+ }
+}
+
+static int
+enc_open(struct cdev *dev, int flags, int fmt, struct thread *td)
+{
+ struct cam_periph *periph;
+ struct enc_softc *softc;
+ int error = 0;
+
+ periph = (struct cam_periph *)dev->si_drv1;
+ if (periph == NULL) {
+ return (ENXIO);
+ }
+
+ if (cam_periph_acquire(periph) != CAM_REQ_CMP)
+ return (ENXIO);
+
+ cam_periph_lock(periph);
+
+ softc = (struct enc_softc *)periph->softc;
+
+ if ((softc->enc_flags & ENC_FLAG_INITIALIZED) == 0) {
+ error = ENXIO;
+ goto out;
+ }
+ if (softc->enc_flags & ENC_FLAG_INVALID) {
+ error = ENXIO;
+ goto out;
+ }
+
+out:
+ cam_periph_unlock(periph);
+ if (error) {
+ cam_periph_release(periph);
+ }
+ return (error);
+}
+
+static int
+enc_close(struct cdev *dev, int flag, int fmt, struct thread *td)
+{
+ struct cam_periph *periph;
+ struct enc_softc *softc;
+
+ periph = (struct cam_periph *)dev->si_drv1;
+ if (periph == NULL)
+ return (ENXIO);
+
+ cam_periph_lock(periph);
+
+ softc = (struct enc_softc *)periph->softc;
+
+ cam_periph_unlock(periph);
+ cam_periph_release(periph);
+
+ return (0);
+}
+
+static void
+enc_start(struct cam_periph *p, union ccb *sccb)
+{
+ struct enc_softc *enc;
+
+ enc = p->softc;
+ ENC_DLOG(enc, "%s enter imm=%d prio=%d\n",
+ __func__, p->immediate_priority, p->pinfo.priority);
+ if (p->immediate_priority <= p->pinfo.priority) {
+ SLIST_INSERT_HEAD(&p->ccb_list, &sccb->ccb_h, periph_links.sle);
+ p->immediate_priority = CAM_PRIORITY_NONE;
+ wakeup(&p->ccb_list);
+ } else
+ xpt_release_ccb(sccb);
+ ENC_DLOG(enc, "%s exit\n", __func__);
+}
+
+void
+enc_done(struct cam_periph *periph, union ccb *dccb)
+{
+ wakeup(&dccb->ccb_h.cbfcnp);
+}
+
+int
+enc_error(union ccb *ccb, uint32_t cflags, uint32_t sflags)
+{
+ struct enc_softc *softc;
+ struct cam_periph *periph;
+
+ periph = xpt_path_periph(ccb->ccb_h.path);
+ softc = (struct enc_softc *)periph->softc;
+
+ return (cam_periph_error(ccb, cflags, sflags, &softc->saved_ccb));
+}
+
+static int
+enc_ioctl(struct cdev *dev, u_long cmd, caddr_t arg_addr, int flag,
+ struct thread *td)
+{
+ struct cam_periph *periph;
+ encioc_enc_status_t tmp;
+ encioc_string_t sstr;
+ encioc_elm_status_t elms;
+ encioc_elm_desc_t elmd;
+ encioc_elm_devnames_t elmdn;
+ encioc_element_t *uelm;
+ enc_softc_t *enc;
+ enc_cache_t *cache;
+ void *addr;
+ int error, i;
+
+
+ if (arg_addr)
+ addr = *((caddr_t *) arg_addr);
+ else
+ addr = NULL;
+
+ periph = (struct cam_periph *)dev->si_drv1;
+ if (periph == NULL)
+ return (ENXIO);
+
+ CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering encioctl\n"));
+
+ cam_periph_lock(periph);
+ enc = (struct enc_softc *)periph->softc;
+ cache = &enc->enc_cache;
+
+ /*
+ * Now check to see whether we're initialized or not.
+ * This actually should never fail as we're not supposed
+ * to get past enc_open w/o successfully initializing
+ * things.
+ */
+ if ((enc->enc_flags & ENC_FLAG_INITIALIZED) == 0) {
+ cam_periph_unlock(periph);
+ return (ENXIO);
+ }
+ cam_periph_unlock(periph);
+
+ error = 0;
+
+ CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
+ ("trying to do ioctl %#lx\n", cmd));
+
+ /*
+ * If this command can change the device's state,
+ * we must have the device open for writing.
+ *
+ * For commands that get information about the
+ * device- we don't need to lock the peripheral
+ * if we aren't running a command. The periph
+ * also can't go away while a user process has
+ * it open.
+ */
+ switch (cmd) {
+ case ENCIOC_GETNELM:
+ case ENCIOC_GETELMMAP:
+ case ENCIOC_GETENCSTAT:
+ case ENCIOC_GETELMSTAT:
+ case ENCIOC_GETELMDESC:
+ case ENCIOC_GETELMDEVNAMES:
+ break;
+ default:
+ if ((flag & FWRITE) == 0) {
+ return (EBADF);
+ }
+ }
+
+ /*
+ * XXX The values read here are only valid for the current
+ * configuration generation. We need these ioctls
+ * to also pass in/out a generation number.
+ */
+ sx_slock(&enc->enc_cache_lock);
+ switch (cmd) {
+ case ENCIOC_GETNELM:
+ error = copyout(&cache->nelms, addr, sizeof (cache->nelms));
+ break;
+
+ case ENCIOC_GETELMMAP:
+ for (uelm = addr, i = 0; i != cache->nelms; i++) {
+ encioc_element_t kelm;
+ kelm.elm_idx = i;
+ kelm.elm_subenc_id = cache->elm_map[i].subenclosure;
+ kelm.elm_type = cache->elm_map[i].enctype;
+ error = copyout(&kelm, &uelm[i], sizeof(kelm));
+ if (error)
+ break;
+ }
+ break;
+
+ case ENCIOC_GETENCSTAT:
+ cam_periph_lock(periph);
+ error = enc->enc_vec.get_enc_status(enc, 1);
+ if (error) {
+ cam_periph_unlock(periph);
+ break;
+ }
+ tmp = cache->enc_status;
+ cam_periph_unlock(periph);
+ error = copyout(&tmp, addr, sizeof(tmp));
+ cache->enc_status = tmp;
+ break;
+
+ case ENCIOC_SETENCSTAT:
+ error = copyin(addr, &tmp, sizeof(tmp));
+ if (error)
+ break;
+ cam_periph_lock(periph);
+ error = enc->enc_vec.set_enc_status(enc, tmp, 1);
+ cam_periph_unlock(periph);
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-head
mailing list