From owner-svn-src-all@FreeBSD.ORG Thu May 24 14:07:44 2012 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id B21891065799; Thu, 24 May 2012 14:07:44 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 98FFF8FC12; Thu, 24 May 2012 14:07:44 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q4OE7iJI042327; Thu, 24 May 2012 14:07:44 GMT (envelope-from mav@svn.freebsd.org) Received: (from mav@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q4OE7i47042313; Thu, 24 May 2012 14:07:44 GMT (envelope-from mav@svn.freebsd.org) Message-Id: <201205241407.q4OE7i47042313@svn.freebsd.org> From: Alexander Motin Date: Thu, 24 May 2012 14:07:44 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: 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 X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 24 May 2012 14:07:44 -0000 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@feral.com # -CFLAGS+= -I/usr/include/cam/scsi -DSESINC="" 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 +#include +#include #include #include #include -#include SESINC +#include +#include #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, "", 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 +#include +#include #include #include #include #include #include -#include SESINC +#include +#include #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 +#include +#include #include #include #include #include #include -#include SESINC +#include +#include 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 +#include +#include #include #include #include #include -#include SESINC +#include +#include #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@feral.com */ #include +#include +#include #include #include #include #include -#include SESINC +#include +#include 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 +#include +#include #include #include #include #include -#include SESINC +#include +#include 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@feral.com */ #include +#include +#include #include #include #include @@ -39,7 +41,8 @@ #include #include #include -#include SESINC +#include +#include #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 +#include +#include #include #include #include #include -#include SESINC +#include +#include 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 +#include +#include #include #include #include #include -#include SESINC +#include +#include 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 +__FBSDID("$FreeBSD$"); + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +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 ***