PSARC/2009/058 physical eject button
6795138 Solaris ignores eject button on optical drives
--- a/usr/src/cmd/hal/addons/storage/Makefile Fri Sep 04 15:35:04 2009 -0700
+++ b/usr/src/cmd/hal/addons/storage/Makefile Sat Sep 05 09:21:22 2009 -0700
@@ -19,11 +19,9 @@
# CDDL HEADER END
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
-#
PROG = hald-addon-storage
OBJS = addon-storage.o logger.o
@@ -34,7 +32,7 @@
ROOTCMDDIR = $(ROOTLIB_HAL)
-LDLIBS += -lc -ldbus-1 -lhal
+LDLIBS += -lc -ldbus-1 -lhal -lnvpair -lsysevent
CPPFLAGS += $(HAL_DBUS_CPPFLAGS) $(HAL_CONFIG_CPPFLAGS)
CPPFLAGS += -I$(ROOT)/usr/include/hal -I../../hald
--- a/usr/src/cmd/hal/addons/storage/addon-storage.c Fri Sep 04 15:35:04 2009 -0700
+++ b/usr/src/cmd/hal/addons/storage/addon-storage.c Sat Sep 05 09:21:22 2009 -0700
@@ -2,15 +2,13 @@
*
* addon-storage.c : watch removable media state changes
*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* Licensed under the Academic Free License version 2.1
*
**************************************************************************/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
@@ -30,6 +28,8 @@
#include <sys/mnttab.h>
#include <sys/dkio.h>
#include <priv.h>
+#include <libsysevent.h>
+#include <sys/sysevent/dev.h>
#include <libhal.h>
@@ -37,6 +37,13 @@
#define SLEEP_PERIOD 5
+static char *udi;
+static char *devfs_path;
+LibHalContext *ctx = NULL;
+static sysevent_handle_t *shp = NULL;
+
+static void sysevent_dev_handler(sysevent_t *);
+
static void
my_dbus_error_free(DBusError *error)
{
@@ -46,6 +53,85 @@
}
static void
+sysevent_init ()
+{
+ const char *subcl[1];
+
+ shp = sysevent_bind_handle (sysevent_dev_handler);
+ if (shp == NULL) {
+ HAL_DEBUG (("sysevent_bind_handle failed %d", errno));
+ return;
+ }
+
+ subcl[0] = ESC_DEV_EJECT_REQUEST;
+ if (sysevent_subscribe_event (shp, EC_DEV_STATUS, subcl, 1) != 0) {
+ HAL_INFO (("subscribe(dev_status) failed %d", errno));
+ sysevent_unbind_handle (shp);
+ return;
+ }
+}
+
+static void
+sysevent_fini ()
+{
+ if (shp != NULL) {
+ sysevent_unbind_handle (shp);
+ shp = NULL;
+ }
+}
+
+static void
+sysevent_dev_handler (sysevent_t *ev)
+{
+ char *class;
+ char *subclass;
+ nvlist_t *attr_list;
+ char *phys_path, *path;
+ char *p;
+ int len;
+ DBusError error;
+
+ if ((class = sysevent_get_class_name (ev)) == NULL)
+ return;
+
+ if ((subclass = sysevent_get_subclass_name (ev)) == NULL)
+ return;
+
+ if ((strcmp (class, EC_DEV_STATUS) != 0) ||
+ (strcmp (subclass, ESC_DEV_EJECT_REQUEST) != 0))
+ return;
+
+ if (sysevent_get_attr_list (ev, &attr_list) != 0)
+ return;
+
+ if (nvlist_lookup_string (attr_list, DEV_PHYS_PATH, &phys_path) != 0) {
+ goto out;
+ }
+
+ /* see if event belongs to our LUN (ignore slice and "/devices" ) */
+ if (strncmp (phys_path, "/devices", sizeof ("/devices") - 1) == 0)
+ path = phys_path + sizeof ("/devices") - 1;
+ else
+ path = phys_path;
+
+ if ((p = strrchr (path, ':')) == NULL)
+ goto out;
+ len = (uintptr_t)p - (uintptr_t)path;
+ if (strncmp (path, devfs_path, len) != 0)
+ goto out;
+
+ HAL_DEBUG (("sysevent_dev_handler %s %s", subclass, phys_path));
+
+ /* we got it, tell the world */
+ dbus_error_init (&error);
+ libhal_device_emit_condition (ctx, udi, "EjectPressed", "", &error);
+ dbus_error_free (&error);
+
+out:
+ nvlist_free(attr_list);
+}
+
+static void
force_unmount (LibHalContext *ctx, const char *udi)
{
DBusError error;
@@ -202,6 +288,9 @@
/* to open logindevperm'd devices */
(void) priv_addset(pPrivSet, PRIV_FILE_DAC_READ);
+ /* to receive sysevents */
+ (void) priv_addset(pPrivSet, PRIV_SYS_CONFIG);
+
/* Set the permitted privilege set. */
if (setppriv(PRIV_SET, PRIV_PERMITTED, pPrivSet) != 0) {
return;
@@ -224,9 +313,7 @@
int
main (int argc, char *argv[])
{
- char *udi;
char *device_file, *raw_device_file;
- LibHalContext *ctx = NULL;
DBusError error;
char *bus;
char *drive_type;
@@ -245,11 +332,15 @@
goto out;
if ((drive_type = getenv ("HAL_PROP_STORAGE_DRIVE_TYPE")) == NULL)
goto out;
+ if ((devfs_path = getenv ("HAL_PROP_SOLARIS_DEVFS_PATH")) == NULL)
+ goto out;
drop_privileges ();
setup_logger ();
+ sysevent_init ();
+
support_media_changed_str = getenv ("HAL_PROP_STORAGE_CDROM_SUPPORT_MEDIA_CHANGED");
if (support_media_changed_str != NULL && strcmp (support_media_changed_str, "true") == 0)
support_media_changed = TRUE;
@@ -347,6 +438,7 @@
}
out:
+ sysevent_fini ();
if (ctx != NULL) {
my_dbus_error_free (&error);
libhal_ctx_shutdown (ctx, &error);
--- a/usr/src/cmd/rmmount/rmmount.c Fri Sep 04 15:35:04 2009 -0700
+++ b/usr/src/cmd/rmmount/rmmount.c Sat Sep 05 09:21:22 2009 -0700
@@ -19,12 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
@@ -134,7 +132,7 @@
action = INSERT;
}
- if ((hal_ctx = rmm_hal_init(0, 0, 0, &error, &rmm_error)) == NULL) {
+ if ((hal_ctx = rmm_hal_init(0, 0, 0, 0, &error, &rmm_error)) == NULL) {
(void) fprintf(stderr, gettext("warning: %s\n"),
rmm_strerror(&error, rmm_error));
rmm_dbus_error_free(&error);
--- a/usr/src/cmd/rmvolmgr/rmm_common.c Fri Sep 04 15:35:04 2009 -0700
+++ b/usr/src/cmd/rmvolmgr/rmm_common.c Sat Sep 05 09:21:22 2009 -0700
@@ -19,12 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <stdio.h>
#include <errno.h>
#include <string.h>
@@ -64,7 +62,7 @@
LibHalContext *
rmm_hal_init(LibHalDeviceAdded devadd_cb, LibHalDeviceRemoved devrem_cb,
- LibHalDevicePropertyModified propmod_cb,
+ LibHalDevicePropertyModified propmod_cb, LibHalDeviceCondition cond_cb,
DBusError *error, rmm_error_t *rmm_error)
{
DBusConnection *dbus_conn;
@@ -114,6 +112,9 @@
return (NULL);
}
}
+ if (cond_cb != NULL) {
+ libhal_ctx_set_device_condition(ctx, cond_cb);
+ }
if (!libhal_ctx_init(ctx, error)) {
dprintf("libhal_ctx_init failed: %s", rmm_strerror(error, -1));
--- a/usr/src/cmd/rmvolmgr/rmm_common.h Fri Sep 04 15:35:04 2009 -0700
+++ b/usr/src/cmd/rmvolmgr/rmm_common.h Sat Sep 05 09:21:22 2009 -0700
@@ -19,15 +19,13 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _COMMON_H
#define _COMMON_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -68,7 +66,8 @@
extern char *progname;
LibHalContext *rmm_hal_init(LibHalDeviceAdded, LibHalDeviceRemoved,
- LibHalDevicePropertyModified, DBusError *, rmm_error_t *);
+ LibHalDevicePropertyModified, LibHalDeviceCondition,
+ DBusError *, rmm_error_t *);
void rmm_hal_fini(LibHalContext *hal_ctx);
LibHalDrive *rmm_hal_volume_find(LibHalContext *, const char *,
--- a/usr/src/cmd/rmvolmgr/rmvolmgr.c Fri Sep 04 15:35:04 2009 -0700
+++ b/usr/src/cmd/rmvolmgr/rmvolmgr.c Sat Sep 05 09:21:22 2009 -0700
@@ -19,12 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* rmvolmgr daemon
*/
@@ -72,12 +70,17 @@
static boolean_t opt_n; /* disable legacy mountpoint symlinks */
static boolean_t opt_s; /* system instance */
+/* SMF property "eject_button" */
+static boolean_t rmm_prop_eject_button = B_TRUE;
+
static void get_smf_properties();
static int daemon(int nochdir, int noclose);
static void rmm_device_added(LibHalContext *ctx, const char *udi);
static void rmm_device_removed(LibHalContext *ctx, const char *udi);
static void rmm_property_modified(LibHalContext *ctx, const char *udi,
const char *key, dbus_bool_t is_removed, dbus_bool_t is_added);
+static void rmm_device_condition(LibHalContext *ctx, const char *udi,
+ const char *name, const char *detail);
static void rmm_mount_all();
static void rmm_unmount_all();
static void sigexit(int signo);
@@ -200,7 +203,8 @@
signal(SIGUSR2, SIG_IGN);
if ((hal_ctx = rmm_hal_init(rmm_device_added, rmm_device_removed,
- rmm_property_modified, &error, &rmm_error)) == NULL) {
+ rmm_property_modified, rmm_device_condition,
+ &error, &rmm_error)) == NULL) {
dbus_error_free(&error);
return (1);
}
@@ -247,6 +251,14 @@
}
scf_simple_prop_free(prop);
}
+
+ if ((prop = scf_simple_prop_get(NULL, RMVOLMGR_FMRI,
+ "rmvolmgr", "eject_button")) != NULL) {
+ if ((val = scf_simple_prop_next_boolean(prop)) != NULL) {
+ rmm_prop_eject_button = (*val != 0);
+ }
+ scf_simple_prop_free(prop);
+ }
}
/* ARGSUSED */
@@ -482,6 +494,34 @@
}
}
+static void
+storage_eject_pressed(const char *udi)
+{
+ DBusError error;
+
+ /* ignore if disabled via SMF or claimed by another volume manager */
+ if (!rmm_prop_eject_button ||
+ libhal_device_get_property_bool(hal_ctx, udi, "info.claimed",
+ NULL)) {
+ return;
+ }
+
+ dbus_error_init(&error);
+ (void) rmm_hal_eject(hal_ctx, udi, &error);
+ rmm_dbus_error_free(&error);
+}
+
+/* ARGSUSED */
+static void
+rmm_device_condition(LibHalContext *ctx, const char *udi,
+ const char *name, const char *detail)
+{
+ if ((strcmp(name, "EjectPressed") == 0) &&
+ libhal_device_query_capability(hal_ctx, udi, "storage", NULL)) {
+ storage_eject_pressed(udi);
+ }
+}
+
/*
* Mount all mountable volumes
*/
--- a/usr/src/cmd/rmvolmgr/vold.c Fri Sep 04 15:35:04 2009 -0700
+++ b/usr/src/cmd/rmvolmgr/vold.c Sat Sep 05 09:21:22 2009 -0700
@@ -19,12 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* Vold compatibility for rmvolmgr: emulate old commands as well as
* action_filemgr.so to notify legacy apps via /tmp/.removable pipes.
@@ -277,7 +275,7 @@
rmm_vold_actions_enabled = B_TRUE;
}
- if ((hal_ctx = rmm_hal_init(0, 0, 0, &error, &rmm_error)) == NULL) {
+ if ((hal_ctx = rmm_hal_init(0, 0, 0, 0, &error, &rmm_error)) == NULL) {
rmm_dbus_error_free(&error);
/* if HAL's not running, must be root */
@@ -534,8 +532,7 @@
prog_name, prog_pid, errno);
return (1);
}
- }
-
+ }
}
/* only support one action at a time XXX */
@@ -585,7 +582,7 @@
}
} else {
dprintf("%s[%d]: action(): invalid action: %s\n",
- __FILE__, __LINE__, action);
+ __FILE__, __LINE__, action);
result = FALSE;
}
@@ -594,7 +591,7 @@
}
dprintf("%s[%d]: leaving action(), result = %s\n",
- __FILE__, __LINE__, result_strings[result]);
+ __FILE__, __LINE__, result_strings[result]);
if (mnt_zoneid > GLOBAL_ZONEID) {
/* exit forked local zone process */
@@ -666,7 +663,7 @@
* file name conflicts.
*/
sprintf(notify_file, "%s-%s", symdev,
- aa[ai]->aa_partname);
+ aa[ai]->aa_partname);
} else {
sprintf(notify_file, "%s-0", symdev);
}
@@ -699,13 +696,13 @@
* file name conflicts.
*/
sprintf(notify_file, "%s-%s", symdev,
- aa[0]->aa_partname);
+ aa[0]->aa_partname);
} else {
sprintf(notify_file, "%s-0", symdev);
}
if ((aa[0]->aa_type != NULL) &&
- (strcmp(aa[0]->aa_type, "backup_slice")
- == 0)) {
+ (strcmp(aa[0]->aa_type, "backup_slice")
+ == 0)) {
reason = "backup_slice";
} else {
reason = "unformatted_media";
@@ -723,15 +720,15 @@
}
raw_partitionp = aa[0]->aa_rawpath;
result = create_one_notify_file(fstype,
- mount_point,
- notify_file,
- raw_partitionp,
- reason,
- symdev);
+ mount_point,
+ notify_file,
+ raw_partitionp,
+ reason,
+ symdev);
ai++;
}
dprintf("%s[%d]: leaving create_notify_files(), result = %s\n",
- __FILE__, __LINE__, result_strings[result]);
+ __FILE__, __LINE__, result_strings[result]);
return (result);
}
@@ -765,12 +762,12 @@
int result;
dprintf("%s[%d]:Entering create_one_notify_file()\n",
- __FILE__, __LINE__);
+ __FILE__, __LINE__);
dprintf("\tcreate_one_notify_file(): fstype = %s\n", fstype);
dprintf("\tcreate_one_notify_file(): mount_point = %s\n", mount_point);
dprintf("\tcreate_one_notify_file(): notify_file = %s\n", notify_file);
dprintf("\tcreate_one_notify_file(): raw_partitionp = %s\n",
- raw_partitionp);
+ raw_partitionp);
if (reason != NULL) {
dprintf("\tcreate_one_notify_file(): reason = %s\n", reason);
} else {
@@ -819,42 +816,42 @@
*/
(void) remove(notify_file);
file_descriptor =
- open(notify_file, O_CREAT|O_EXCL|O_WRONLY, 0644);
+ open(notify_file, O_CREAT|O_EXCL|O_WRONLY, 0644);
if (file_descriptor < 0) {
dprintf("%s[%d]: can't create %s/%s; %m\n",
- __FILE__, __LINE__, NOTIFY_DIR, notify_file);
+ __FILE__, __LINE__, NOTIFY_DIR, notify_file);
result = FALSE;
} else {
filep = fdopen(file_descriptor, "w");
if (filep != NULL) {
if (reason == NULL) {
(void) fprintf(filep, "%s %s %s",
- mount_point,
- raw_partitionp,
- fstype);
+ mount_point,
+ raw_partitionp,
+ fstype);
(void) fclose(filep);
dprintf("%s[%d]: Just wrote %s %s %s to %s\n",
- __FILE__,
- __LINE__,
- mount_point,
- raw_partitionp,
- fstype,
- notify_file);
+ __FILE__,
+ __LINE__,
+ mount_point,
+ raw_partitionp,
+ fstype,
+ notify_file);
} else {
(void) fprintf(filep, "%s %s",
- reason, raw_partitionp);
+ reason, raw_partitionp);
(void) fclose(filep);
dprintf("%s[%d]: Just wrote %s %s to %s\n",
- __FILE__,
- __LINE__,
- reason,
- raw_partitionp,
- notify_file);
+ __FILE__,
+ __LINE__,
+ reason,
+ raw_partitionp,
+ notify_file);
}
} else {
dprintf("%s[%d]: can't write %s/%s; %m\n",
- __FILE__, __LINE__,
- NOTIFY_DIR, notify_file);
+ __FILE__, __LINE__,
+ NOTIFY_DIR, notify_file);
(void) close(file_descriptor);
result = FALSE;
}
@@ -862,7 +859,7 @@
popdir(current_working_dir_fd);
}
dprintf("%s[%d]: leaving create_one_notify_file, result = %s\n",
- __FILE__, __LINE__, result_strings[result]);
+ __FILE__, __LINE__, result_strings[result]);
return (result);
}
@@ -910,7 +907,7 @@
dirp = opendir(".");
if (dirp == NULL) {
dprintf("%s[%d]:opendir failed on '.'; %m\n",
- __FILE__, __LINE__);
+ __FILE__, __LINE__);
popdir(current_working_dir_fd);
result = FALSE;
}
@@ -933,7 +930,7 @@
continue;
}
(void) sprintf(namebuf, "%s/%s",
- NOTIFY_DIR, dir_entryp->d_name);
+ NOTIFY_DIR, dir_entryp->d_name);
if ((fd = open(namebuf, O_WRONLY|O_NDELAY)) < 0) {
dprintf("%s[%d]: open failed for %s; %m\n",
__FILE__, __LINE__, namebuf);
@@ -946,7 +943,7 @@
*/
if ((fstat(fd, &sb) < 0) || (!S_ISFIFO(sb.st_mode))) {
dprintf("%s[%d]: %s isn't a named pipe\n",
- __FILE__, __LINE__, namebuf);
+ __FILE__, __LINE__, namebuf);
(void) close(fd);
continue;
@@ -965,7 +962,7 @@
popdir(current_working_dir_fd);
}
dprintf("%s[%d]: leaving notify_clients(), result = %s\n",
- __FILE__, __LINE__, result_strings[result]);
+ __FILE__, __LINE__, result_strings[result]);
return (result);
}
@@ -1010,25 +1007,25 @@
if (lstat(dir, &stat_buf) < 0) {
dprintf("%s[%d]: push_dir_and_check(): %s does not exist\n",
- __FILE__, __LINE__, dir);
+ __FILE__, __LINE__, dir);
return (-1);
}
if (!(S_ISDIR(stat_buf.st_mode))) {
dprintf("%s[%d]: push_dir_and_check(): %s not a directory.\n",
- __FILE__, __LINE__, dir);
+ __FILE__, __LINE__, dir);
(void) remove(dir);
return (-1);
}
if ((current_working_dir_fd = open(".", O_RDONLY)) < 0) {
dprintf("%s[%d]: push_dir_and_check(): can't open %s.\n",
- __FILE__, __LINE__, dir);
+ __FILE__, __LINE__, dir);
return (-1);
}
if (chdir(dir) < 0) {
(void) close(current_working_dir_fd);
dprintf("%s[%d]: push_dir_and_check(): can't chdir() to %s.\n",
- __FILE__, __LINE__, dir);
+ __FILE__, __LINE__, dir);
return (-1);
}
return (current_working_dir_fd);
@@ -1049,8 +1046,8 @@
result = TRUE;
symdev = aa[ai]->aa_symdev;
while ((result == TRUE) &&
- (aa[ai] != NULL) &&
- (aa[ai]->aa_path != NULL)) {
+ (aa[ai] != NULL) &&
+ (aa[ai]->aa_path != NULL)) {
if (not_mountable(aa[ai])) {
sprintf(notify_file, "%s-0", symdev);
@@ -1063,7 +1060,7 @@
* file name conflicts.
*/
sprintf(notify_file, "%s-%s",
- symdev, aa[0]->aa_partname);
+ symdev, aa[0]->aa_partname);
} else {
sprintf(notify_file, "%s-0", symdev);
}
@@ -1074,7 +1071,7 @@
}
if ((result == TRUE) && (remove(notify_file) < 0)) {
dprintf("%s[%d]: remove %s/%s; %m\n",
- __FILE__, __LINE__, NOTIFY_DIR, notify_file);
+ __FILE__, __LINE__, NOTIFY_DIR, notify_file);
result = FALSE;
}
if (current_working_dir_fd != -1) {
@@ -1083,7 +1080,7 @@
ai++;
}
dprintf("%s[%d]: leaving remove_notify_files(), result = %s\n",
- __FILE__, __LINE__, result_strings[result]);
+ __FILE__, __LINE__, result_strings[result]);
return (result);
}
--- a/usr/src/cmd/volcheck/volcheck.c Fri Sep 04 15:35:04 2009 -0700
+++ b/usr/src/cmd/volcheck/volcheck.c Sat Sep 05 09:21:22 2009 -0700
@@ -19,12 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@@ -83,7 +81,7 @@
}
}
- if ((hal_ctx = rmm_hal_init(0, 0, 0, &error, &rmm_error)) == NULL) {
+ if ((hal_ctx = rmm_hal_init(0, 0, 0, 0, &error, &rmm_error)) == NULL) {
(void) fprintf(stderr,
gettext("HAL initialization failed: %s\n"),
rmm_strerror(&error, rmm_error));
--- a/usr/src/cmd/volrmmount/volrmmount.c Fri Sep 04 15:35:04 2009 -0700
+++ b/usr/src/cmd/volrmmount/volrmmount.c Sat Sep 05 09:21:22 2009 -0700
@@ -19,12 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@@ -105,7 +103,7 @@
return (1);
}
- if ((hal_ctx = rmm_hal_init(0, 0, 0, &error, &rmm_error)) == NULL) {
+ if ((hal_ctx = rmm_hal_init(0, 0, 0, 0, &error, &rmm_error)) == NULL) {
(void) fprintf(stderr,
gettext("HAL initialization failed: %s\n"),
rmm_strerror(&error, rmm_error));
--- a/usr/src/uts/common/io/scsi/impl/scsi_watch.c Fri Sep 04 15:35:04 2009 -0700
+++ b/usr/src/uts/common/io/scsi/impl/scsi_watch.c Sat Sep 05 09:21:22 2009 -0700
@@ -122,6 +122,7 @@
struct scsi_pkt *swr_pkt; /* TUR pkt itself */
struct scsi_pkt *swr_rqpkt; /* request sense pkt */
struct buf *swr_rqbp; /* bp for request sense data */
+ struct buf *swr_mmcbp; /* bp for MMC command data */
int (*swr_callback)(); /* callback to driver */
caddr_t swr_callback_arg;
kcondvar_t swr_terminate_cv; /* cv to wait on to cleanup */
@@ -147,6 +148,9 @@
#define SWR_SUSPEND_REQUESTED 2 /* req. pending suspend */
#define SWR_SUSPENDED 3 /* req. is suspended */
+static opaque_t scsi_watch_request_submit_impl(struct scsi_device *devp,
+ int interval, int sense_length, int (*callback)(), caddr_t cb_arg,
+ boolean_t mmc);
static void scsi_watch_request_destroy(struct scsi_watch_request *swr);
static void scsi_watch_thread(void);
static void scsi_watch_request_intr(struct scsi_pkt *pkt);
@@ -195,9 +199,35 @@
int (*callback)(), /* callback function */
caddr_t cb_arg) /* device number */
{
+ return (scsi_watch_request_submit_impl(devp, interval, sense_length,
+ callback, cb_arg, B_FALSE));
+}
+
+opaque_t
+scsi_mmc_watch_request_submit(
+ struct scsi_device *devp,
+ int interval,
+ int sense_length,
+ int (*callback)(), /* callback function */
+ caddr_t cb_arg) /* device number */
+{
+ return (scsi_watch_request_submit_impl(devp, interval, sense_length,
+ callback, cb_arg, B_TRUE));
+}
+
+static opaque_t
+scsi_watch_request_submit_impl(
+ struct scsi_device *devp,
+ int interval,
+ int sense_length,
+ int (*callback)(), /* callback function */
+ caddr_t cb_arg, /* device number */
+ boolean_t mmc)
+{
register struct scsi_watch_request *swr = NULL;
register struct scsi_watch_request *sswr, *p;
struct buf *bp = NULL;
+ struct buf *mmcbp = NULL;
struct scsi_pkt *rqpkt = NULL;
struct scsi_pkt *pkt = NULL;
uchar_t dtype;
@@ -259,15 +289,27 @@
rqpkt->pkt_flags |= FLAG_HEAD;
/*
- * Create TUR pkt or a zero byte WRITE(10) based on the
- * disk-type for reservation state.
+ * Create TUR pkt or GET STATUS EVENT NOTIFICATION for MMC requests or
+ * a zero byte WRITE(10) based on the disk-type for reservation state.
* For inq_dtype of SBC (DIRECT, dtype == 0)
* OR for RBC devices (dtype is 0xE) AND for
* ANSI version of SPC/SPC-2/SPC-3 (inq_ansi == 3-5).
*/
dtype = devp->sd_inq->inq_dtype & DTYPE_MASK;
- if (((dtype == 0) || (dtype == 0xE)) &&
+ if (mmc) {
+ mmcbp = scsi_alloc_consistent_buf(ROUTE, NULL,
+ 8, B_READ, SLEEP_FUNC, NULL);
+
+ pkt = scsi_init_pkt(ROUTE, (struct scsi_pkt *)NULL, mmcbp,
+ CDB_GROUP1, sizeof (struct scsi_arq_status),
+ 0, 0, SLEEP_FUNC, NULL);
+
+ (void) scsi_setup_cdb((union scsi_cdb *)pkt->pkt_cdbp,
+ SCMD_GET_EVENT_STATUS_NOTIFICATION, 0, 8, 0);
+ pkt->pkt_cdbp[1] = 1; /* polled */
+ pkt->pkt_cdbp[4] = 1 << SD_GESN_MEDIA_CLASS;
+ } else if (((dtype == 0) || (dtype == 0xE)) &&
(devp->sd_inq->inq_ansi > 2)) {
pkt = scsi_init_pkt(ROUTE, (struct scsi_pkt *)NULL, NULL,
CDB_GROUP1, sizeof (struct scsi_arq_status),
@@ -297,6 +339,7 @@
*/
swr->swr_rqbp = bp;
swr->swr_rqpkt = rqpkt;
+ swr->swr_mmcbp = mmcbp;
swr->swr_pkt = pkt;
swr->swr_timeout = swr->swr_interval = drv_usectohz(interval);
swr->swr_callback = callback;
@@ -465,6 +508,9 @@
scsi_destroy_pkt(swr->swr_rqpkt);
scsi_free_consistent_buf(swr->swr_rqbp);
+ if (swr->swr_mmcbp != NULL) {
+ scsi_free_consistent_buf(swr->swr_mmcbp);
+ }
scsi_destroy_pkt(swr->swr_pkt);
cv_signal(&swr->swr_terminate_cv);
}
@@ -945,6 +991,9 @@
result.sensep = rqsensep;
result.actual_sense_length = (uchar_t)amt;
result.pkt = swr->swr_pkt;
+ if (swr->swr_mmcbp != NULL) {
+ bcopy(swr->swr_mmcbp->b_un.b_addr, result.mmc_data, 8);
+ }
if ((*swr->swr_callback)(swr->swr_callback_arg, &result)) {
swr->swr_what = SWR_STOP;
--- a/usr/src/uts/common/io/scsi/targets/sd.c Fri Sep 04 15:35:04 2009 -0700
+++ b/usr/src/uts/common/io/scsi/targets/sd.c Sat Sep 05 09:21:22 2009 -0700
@@ -1018,7 +1018,9 @@
#define sd_taskq_create ssd_taskq_create
#define sd_taskq_delete ssd_taskq_delete
#define sd_target_change_task ssd_target_change_task
+#define sd_log_dev_status_event ssd_log_dev_status_event
#define sd_log_lun_expansion_event ssd_log_lun_expansion_event
+#define sd_log_eject_request_event ssd_log_eject_request_event
#define sd_media_change_task ssd_media_change_task
#define sd_handle_mchange ssd_handle_mchange
#define sd_send_scsi_DOORLOCK ssd_send_scsi_DOORLOCK
@@ -1041,6 +1043,9 @@
#define sd_send_scsi_MODE_SELECT ssd_send_scsi_MODE_SELECT
#define sd_send_scsi_RDWR ssd_send_scsi_RDWR
#define sd_send_scsi_LOG_SENSE ssd_send_scsi_LOG_SENSE
+#define sd_send_scsi_GET_EVENT_STATUS_NOTIFICATION \
+ ssd_send_scsi_GET_EVENT_STATUS_NOTIFICATION
+#define sd_gesn_media_data_valid ssd_gesn_media_data_valid
#define sd_alloc_rqs ssd_alloc_rqs
#define sd_free_rqs ssd_free_rqs
#define sd_dump_memory ssd_dump_memory
@@ -1092,6 +1097,7 @@
#define sr_eject ssr_eject
#define sr_ejected ssr_ejected
#define sr_check_wp ssr_check_wp
+#define sd_watch_request_submit ssd_watch_request_submit
#define sd_check_media ssd_check_media
#define sd_media_watch_cb ssd_media_watch_cb
#define sd_delayed_cv_broadcast ssd_delayed_cv_broadcast
@@ -1485,7 +1491,9 @@
static void sd_taskq_create(void);
static void sd_taskq_delete(void);
static void sd_target_change_task(void *arg);
+static void sd_log_dev_status_event(struct sd_lun *un, char *esc, int km_flag);
static void sd_log_lun_expansion_event(struct sd_lun *un, int km_flag);
+static void sd_log_eject_request_event(struct sd_lun *un, int km_flag);
static void sd_media_change_task(void *arg);
static int sd_handle_mchange(struct sd_lun *un);
@@ -1528,6 +1536,9 @@
static int sd_send_scsi_LOG_SENSE(sd_ssc_t *ssc, uchar_t *bufaddr,
uint16_t buflen, uchar_t page_code, uchar_t page_control,
uint16_t param_ptr, int path_flag);
+static int sd_send_scsi_GET_EVENT_STATUS_NOTIFICATION(sd_ssc_t *ssc,
+ uchar_t *bufaddr, size_t buflen, uchar_t class_req);
+static boolean_t sd_gesn_media_data_valid(uchar_t *data);
static int sd_alloc_rqs(struct scsi_device *devp, struct sd_lun *un);
static void sd_free_rqs(struct sd_lun *un);
@@ -1590,6 +1601,7 @@
static int sr_eject(dev_t dev);
static void sr_ejected(register struct sd_lun *un);
static int sr_check_wp(dev_t dev);
+static opaque_t sd_watch_request_submit(struct sd_lun *un);
static int sd_check_media(dev_t dev, enum dkio_state state);
static int sd_media_watch_cb(caddr_t arg, struct scsi_watch_result *resultp);
static void sd_delayed_cv_broadcast(void *arg);
@@ -3405,6 +3417,8 @@
int rtn;
uchar_t *out_data_rw, *out_data_hd;
uchar_t *rqbuf_rw, *rqbuf_hd;
+ uchar_t *out_data_gesn;
+ int gesn_len;
struct sd_lun *un;
ASSERT(ssc != NULL);
@@ -3437,6 +3451,28 @@
*/
un->un_f_mmc_cap = TRUE;
+ /* See if GET STATUS EVENT NOTIFICATION is supported */
+ if (un->un_f_mmc_gesn_polling) {
+ gesn_len = SD_GESN_HEADER_LEN + SD_GESN_MEDIA_DATA_LEN;
+ out_data_gesn = kmem_zalloc(gesn_len, KM_SLEEP);
+
+ rtn = sd_send_scsi_GET_EVENT_STATUS_NOTIFICATION(ssc,
+ out_data_gesn, gesn_len, 1 << SD_GESN_MEDIA_CLASS);
+
+ sd_ssc_assessment(ssc, SD_FMT_IGNORE);
+
+ if ((rtn != 0) || !sd_gesn_media_data_valid(out_data_gesn)) {
+ un->un_f_mmc_gesn_polling = FALSE;
+ SD_INFO(SD_LOG_ATTACH_DETACH, un,
+ "sd_set_mmc_caps: gesn not supported "
+ "%d %x %x %x %x\n", rtn,
+ out_data_gesn[0], out_data_gesn[1],
+ out_data_gesn[2], out_data_gesn[3]);
+ }
+
+ kmem_free(out_data_gesn, gesn_len);
+ }
+
/* Get to the page data */
sense_mhp = (struct mode_header_grp2 *)buf;
bd_len = (sense_mhp->bdesc_length_hi << 8) |
@@ -4177,6 +4213,20 @@
un->un_saved_throttle = un->un_throttle = sd_max_throttle;
un->un_min_throttle = sd_min_throttle;
}
+
+ if (strcasecmp(name, "mmc-gesn-polling") == 0) {
+ if (strcasecmp(value, "true") == 0) {
+ un->un_f_mmc_gesn_polling = TRUE;
+ } else if (strcasecmp(value, "false") == 0) {
+ un->un_f_mmc_gesn_polling = FALSE;
+ } else {
+ goto value_invalid;
+ }
+ SD_INFO(SD_LOG_ATTACH_DETACH, un, "sd_set_properties: "
+ "mmc-gesn-polling set to %d\n",
+ un->un_f_mmc_gesn_polling);
+ }
+
return;
value_invalid:
@@ -6529,7 +6579,6 @@
int log_sense_page;
int medium_present;
time_t intvlp;
- dev_t dev;
struct pm_trans_data sd_pm_tran_data;
uchar_t save_state;
int sval;
@@ -6545,7 +6594,6 @@
return (DDI_FAILURE);
}
- dev = sd_make_device(SD_DEVINFO(un));
ssc = sd_ssc_init(un);
SD_TRACE(SD_LOG_IO_PM, un, "sdpower: entry, level = %d\n", level);
@@ -6959,11 +7007,8 @@
un->un_f_watcht_stopped = FALSE;
mutex_exit(SD_MUTEX(un));
- temp_token = scsi_watch_request_submit(
- SD_SCSI_DEVP(un),
- sd_check_media_time,
- SENSE_LENGTH, sd_media_watch_cb,
- (caddr_t)dev);
+ temp_token =
+ sd_watch_request_submit(un);
mutex_enter(SD_MUTEX(un));
un->un_swr_token = temp_token;
}
@@ -7539,6 +7584,12 @@
un->un_f_rmw_type = SD_RMW_TYPE_DEFAULT;
/*
+ * GET EVENT STATUS NOTIFICATION media polling enabled by default, but
+ * can be overridden via [s]sd-config-list "mmc-gesn-polling" property.
+ */
+ un->un_f_mmc_gesn_polling = TRUE;
+
+ /*
* Retrieve the properties from the static driver table or the driver
* configuration file (.conf) for this unit and update the soft state
* for the device as needed for the indicated properties.
@@ -8016,7 +8067,6 @@
sd_set_mmc_caps(ssc);
}
-
/*
* Add a zero-length attribute to tell the world we support
* kernel ioctls (for layered drivers)
@@ -19475,33 +19525,34 @@
sd_ssc_fini(ssc);
}
-/*
- * Function: sd_log_lun_expansion_event
- *
- * Description: Log lun expansion sys event
+
+/*
+ * Function: sd_log_dev_status_event
+ *
+ * Description: Log EC_dev_status sysevent
*
* Context: Never called from interrupt context
*/
static void
-sd_log_lun_expansion_event(struct sd_lun *un, int km_flag)
+sd_log_dev_status_event(struct sd_lun *un, char *esc, int km_flag)
{
int err;
char *path;
- nvlist_t *dle_attr_list;
+ nvlist_t *attr_list;
/* Allocate and build sysevent attribute list */
- err = nvlist_alloc(&dle_attr_list, NV_UNIQUE_NAME_TYPE, km_flag);
+ err = nvlist_alloc(&attr_list, NV_UNIQUE_NAME_TYPE, km_flag);
if (err != 0) {
SD_ERROR(SD_LOG_ERROR, un,
- "sd_log_lun_expansion_event: fail to allocate space\n");
+ "sd_log_dev_status_event: fail to allocate space\n");
return;
}
path = kmem_alloc(MAXPATHLEN, km_flag);
if (path == NULL) {
- nvlist_free(dle_attr_list);
+ nvlist_free(attr_list);
SD_ERROR(SD_LOG_ERROR, un,
- "sd_log_lun_expansion_event: fail to allocate space\n");
+ "sd_log_dev_status_event: fail to allocate space\n");
return;
}
/*
@@ -19513,27 +19564,56 @@
(void) snprintf(path + strlen(path), MAXPATHLEN - strlen(path),
":a");
- err = nvlist_add_string(dle_attr_list, DEV_PHYS_PATH, path);
+ err = nvlist_add_string(attr_list, DEV_PHYS_PATH, path);
if (err != 0) {
- nvlist_free(dle_attr_list);
+ nvlist_free(attr_list);
kmem_free(path, MAXPATHLEN);
SD_ERROR(SD_LOG_ERROR, un,
- "sd_log_lun_expansion_event: fail to add attribute\n");
+ "sd_log_dev_status_event: fail to add attribute\n");
return;
}
/* Log dynamic lun expansion sysevent */
err = ddi_log_sysevent(SD_DEVINFO(un), SUNW_VENDOR, EC_DEV_STATUS,
- ESC_DEV_DLE, dle_attr_list, NULL, km_flag);
+ esc, attr_list, NULL, km_flag);
if (err != DDI_SUCCESS) {
SD_ERROR(SD_LOG_ERROR, un,
- "sd_log_lun_expansion_event: fail to log sysevent\n");
- }
-
- nvlist_free(dle_attr_list);
+ "sd_log_dev_status_event: fail to log sysevent\n");
+ }
+
+ nvlist_free(attr_list);
kmem_free(path, MAXPATHLEN);
}
+
+/*
+ * Function: sd_log_lun_expansion_event
+ *
+ * Description: Log lun expansion sys event
+ *
+ * Context: Never called from interrupt context
+ */
+static void
+sd_log_lun_expansion_event(struct sd_lun *un, int km_flag)
+{
+ sd_log_dev_status_event(un, ESC_DEV_DLE, km_flag);
+}
+
+
+/*
+ * Function: sd_log_eject_request_event
+ *
+ * Description: Log eject request sysevent
+ *
+ * Context: Never called from interrupt context
+ */
+static void
+sd_log_eject_request_event(struct sd_lun *un, int km_flag)
+{
+ sd_log_dev_status_event(un, ESC_DEV_EJECT_REQUEST, km_flag);
+}
+
+
/*
* Function: sd_media_change_task
*
@@ -21822,6 +21902,94 @@
/*
+ * Function: sd_send_scsi_GET_EVENT_STATUS_NOTIFICATION
+ *
+ * Description: Issue the scsi GET EVENT STATUS NOTIFICATION command.
+ *
+ * Arguments: ssc - ssc contains pointer to driver soft state (unit)
+ * structure for this target.
+ * bufaddr
+ * buflen
+ * class_req
+ *
+ * Return Code: 0 - Success
+ * errno return code from sd_ssc_send()
+ *
+ * Context: Can sleep. Does not return until command is completed.
+ */
+
+static int
+sd_send_scsi_GET_EVENT_STATUS_NOTIFICATION(sd_ssc_t *ssc, uchar_t *bufaddr,
+ size_t buflen, uchar_t class_req)
+{
+ union scsi_cdb cdb;
+ struct uscsi_cmd ucmd_buf;
+ int status;
+ struct sd_lun *un;
+
+ ASSERT(ssc != NULL);
+ un = ssc->ssc_un;
+ ASSERT(un != NULL);
+ ASSERT(!mutex_owned(SD_MUTEX(un)));
+ ASSERT(bufaddr != NULL);
+
+ SD_TRACE(SD_LOG_IO, un,
+ "sd_send_scsi_GET_EVENT_STATUS_NOTIFICATION: entry: un:0x%p\n", un);
+
+ bzero(&cdb, sizeof (cdb));
+ bzero(&ucmd_buf, sizeof (ucmd_buf));
+ bzero(bufaddr, buflen);
+
+ cdb.scc_cmd = SCMD_GET_EVENT_STATUS_NOTIFICATION;
+ cdb.cdb_opaque[1] = 1; /* polled */
+ cdb.cdb_opaque[4] = class_req;
+ FORMG1COUNT(&cdb, buflen);
+
+ ucmd_buf.uscsi_cdb = (char *)&cdb;
+ ucmd_buf.uscsi_cdblen = CDB_GROUP1;
+ ucmd_buf.uscsi_bufaddr = (caddr_t)bufaddr;
+ ucmd_buf.uscsi_buflen = buflen;
+ ucmd_buf.uscsi_rqbuf = NULL;
+ ucmd_buf.uscsi_rqlen = 0;
+ ucmd_buf.uscsi_flags = USCSI_READ | USCSI_SILENT;
+ ucmd_buf.uscsi_timeout = 60;
+
+ status = sd_ssc_send(ssc, &ucmd_buf, FKIOCTL,
+ UIO_SYSSPACE, SD_PATH_DIRECT);
+
+ /*
+ * Only handle status == 0, the upper-level caller
+ * will put different assessment based on the context.
+ */
+ if (status == 0) {
+ sd_ssc_assessment(ssc, SD_FMT_STANDARD);
+
+ if (ucmd_buf.uscsi_resid != 0) {
+ status = EIO;
+ }
+ }
+
+ SD_TRACE(SD_LOG_IO, un,
+ "sd_send_scsi_GET_EVENT_STATUS_NOTIFICATION: exit\n");
+
+ return (status);
+}
+
+
+static boolean_t
+sd_gesn_media_data_valid(uchar_t *data)
+{
+ uint16_t len;
+
+ len = (data[1] << 8) | data[0];
+ return ((len >= 6) &&
+ ((data[2] & SD_GESN_HEADER_NEA) == 0) &&
+ ((data[2] & SD_GESN_HEADER_CLASS) == SD_GESN_MEDIA_CLASS) &&
+ ((data[3] & (1 << SD_GESN_MEDIA_CLASS)) != 0));
+}
+
+
+/*
* Function: sdioctl
*
* Description: Driver's ioctl(9e) entry point function.
@@ -23350,6 +23518,32 @@
}
/*
+ * Function: sd_watch_request_submit
+ *
+ * Description: Call scsi_watch_request_submit or scsi_mmc_watch_request_submit
+ * depending on which is supported by device.
+ */
+static opaque_t
+sd_watch_request_submit(struct sd_lun *un)
+{
+ dev_t dev;
+
+ /* All submissions are unified to use same device number */
+ dev = sd_make_device(SD_DEVINFO(un));
+
+ if (un->un_f_mmc_cap && un->un_f_mmc_gesn_polling) {
+ return (scsi_mmc_watch_request_submit(SD_SCSI_DEVP(un),
+ sd_check_media_time, SENSE_LENGTH, sd_media_watch_cb,
+ (caddr_t)dev));
+ } else {
+ return (scsi_watch_request_submit(SD_SCSI_DEVP(un),
+ sd_check_media_time, SENSE_LENGTH, sd_media_watch_cb,
+ (caddr_t)dev));
+ }
+}
+
+
+/*
* Function: sd_check_media
*
* Description: This utility routine implements the functionality for the
@@ -23380,18 +23574,11 @@
opaque_t token = NULL;
int rval = 0;
sd_ssc_t *ssc;
- dev_t sub_dev;
if ((un = ddi_get_soft_state(sd_state, SDUNIT(dev))) == NULL) {
return (ENXIO);
}
- /*
- * sub_dev is used when submitting request to scsi watch.
- * All submissions are unified to use same device number.
- */
- sub_dev = sd_make_device(SD_DEVINFO(un));
-
SD_TRACE(SD_LOG_COMMON, un, "sd_check_media: entry\n");
ssc = sd_ssc_init(un);
@@ -23423,9 +23610,7 @@
goto done;
}
- token = scsi_watch_request_submit(SD_SCSI_DEVP(un),
- sd_check_media_time, SENSE_LENGTH, sd_media_watch_cb,
- (caddr_t)sub_dev);
+ token = sd_watch_request_submit(un);
sd_pm_exit(un);
@@ -23663,12 +23848,25 @@
return (0);
}
- /*
- * If there was a check condition then sensep points to valid sense data
- * If status was not a check condition but a reservation or busy status
- * then the new state is DKIO_NONE
- */
- if (sensep != NULL) {
+ if (un->un_f_mmc_cap && un->un_f_mmc_gesn_polling) {
+ if (sd_gesn_media_data_valid(resultp->mmc_data)) {
+ if ((resultp->mmc_data[5] &
+ SD_GESN_MEDIA_EVENT_STATUS_PRESENT) != 0) {
+ state = DKIO_INSERTED;
+ } else {
+ state = DKIO_EJECTED;
+ }
+ if ((resultp->mmc_data[4] & SD_GESN_MEDIA_EVENT_CODE) ==
+ SD_GESN_MEDIA_EVENT_EJECTREQUEST) {
+ sd_log_eject_request_event(un, KM_NOSLEEP);
+ }
+ }
+ } else if (sensep != NULL) {
+ /*
+ * If there was a check condition then sensep points to valid
+ * sense data. If status was not a check condition but a
+ * reservation or busy status then the new state is DKIO_NONE.
+ */
skey = scsi_sense_key(sensep);
asc = scsi_sense_asc(sensep);
ascq = scsi_sense_ascq(sensep);
--- a/usr/src/uts/common/sys/scsi/generic/commands.h Fri Sep 04 15:35:04 2009 -0700
+++ b/usr/src/uts/common/sys/scsi/generic/commands.h Sat Sep 05 09:21:22 2009 -0700
@@ -20,15 +20,13 @@
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _SYS_SCSI_GENERIC_COMMANDS_H
#define _SYS_SCSI_GENERIC_COMMANDS_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -289,6 +287,36 @@
/* SCMD_SET_LIMITS 0x33 */
/*
+ * Group 1 Commands, MMC Devices
+ */
+
+/* GET EVENT STATUS NOTIFICATION, MMC-3 5.6 */
+#define SCMD_GET_EVENT_STATUS_NOTIFICATION 0x4a
+
+/* event header */
+#define SD_GESN_HEADER_LEN 4
+#define SD_GESN_HEADER_NEA 0x80 /* byte 2 */
+#define SD_GESN_HEADER_CLASS 0x07 /* byte 2 */
+
+/* media class event class and event data that follows the header */
+#define SD_GESN_MEDIA_CLASS 4
+
+#define SD_GESN_MEDIA_DATA_LEN 4
+#define SD_GESN_MEDIA_EVENT_CODE 0x0f /* byte 0 */
+#define SD_GESN_MEDIA_EVENT_STATUS_PRESENT 0x02 /* byte 1 */
+#define SD_GESN_MEDIA_EVENT_STATUS_TRAY_OPEN 0x01 /* byte 1 */
+
+/* media event code */
+#define SD_GESN_MEDIA_EVENT_NOCHG 0
+#define SD_GESN_MEDIA_EVENT_EJECTREQUEST 1
+#define SD_GESN_MEDIA_EVENT_NEWMEDIA 2
+#define SD_GESN_MEDIA_EVENT_MEDIAREMOVAL 3
+#define SD_GESN_MEDIA_EVENT_MEDIACHANGED 4
+#define SD_GESN_MEDIA_EVENT_BGFORMATCOMPLETED 5
+#define SD_GESN_MEDIA_EVENT_BGFORMATRESTARTED 6
+
+
+/*
* Group 3 Commands
*/
#define SCMD_VAR_LEN 0x7f
--- a/usr/src/uts/common/sys/scsi/scsi_watch.h Fri Sep 04 15:35:04 2009 -0700
+++ b/usr/src/uts/common/sys/scsi/scsi_watch.h Sat Sep 05 09:21:22 2009 -0700
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -34,6 +34,7 @@
struct scsi_status *statusp;
struct scsi_extended_sense *sensep;
uchar_t actual_sense_length;
+ uchar_t mmc_data[8];
struct scsi_pkt *pkt;
};
@@ -57,6 +58,9 @@
opaque_t scsi_watch_request_submit(struct scsi_device *devp,
int interval, int sense_length,
int (*callback)(), caddr_t cb_arg);
+opaque_t scsi_mmc_watch_request_submit(struct scsi_device *devp,
+ int interval, int sense_length,
+ int (*callback)(), caddr_t cb_arg);
int scsi_watch_request_terminate(opaque_t token, int flags);
int scsi_watch_get_ref_count(opaque_t token);
void scsi_watch_resume(opaque_t token);
--- a/usr/src/uts/common/sys/scsi/targets/sddef.h Fri Sep 04 15:35:04 2009 -0700
+++ b/usr/src/uts/common/sys/scsi/targets/sddef.h Sat Sep 05 09:21:22 2009 -0700
@@ -454,7 +454,9 @@
un_f_pm_log_sense_smart :1, /* log sense support SMART */
/* feature attribute */
un_f_is_solid_state :1, /* has solid state media */
- un_f_reserved :6;
+ un_f_mmc_gesn_polling :1, /* use GET EVENT STATUS */
+ /* NOTIFICATION for polling */
+ un_f_reserved :5;
/* Ptr to table of strings for ASC/ASCQ error message printing */
struct scsi_asq_key_strings *un_additional_codes;
--- a/usr/src/uts/common/sys/sysevent/eventdefs.h Fri Sep 04 15:35:04 2009 -0700
+++ b/usr/src/uts/common/sys/sysevent/eventdefs.h Sat Sep 05 09:21:22 2009 -0700
@@ -202,9 +202,16 @@
/* device tree branch removed */
#define ESC_DEV_BRANCH_REMOVE "ESC_dev_branch_remove"
-/* device capacity dynamically changed */
+/*
+ * EC_DEV_STATUS subclass definitions
+ *
+ * device capacity dynamically changed
+ */
#define ESC_DEV_DLE "ESC_dev_dle"
+/* LUN has received an eject request from the user */
+#define ESC_DEV_EJECT_REQUEST "ESC_dev_eject_request"
+
/* FMA Fault and Error event protocol subclass */
#define ESC_FM_ERROR "ESC_FM_error"
#define ESC_FM_ERROR_REPLAY "ESC_FM_error_replay"