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 @@
 # mja...@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 @@
  * mja...@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 @@
  * mja...@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 ***
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to