PSARC 2009/646 bd - generic block device driver
PSARC 2009/648 sdcard conversion to bd, EOF blk2scsa
6952618 deliver blkdev (PSARC 2009/646)
--- a/usr/src/Makefile.lint Tue May 18 11:19:39 2010 +0800
+++ b/usr/src/Makefile.lint Mon May 17 21:17:01 2010 -0700
@@ -329,7 +329,6 @@
lib/auditd_plugins \
lib/brand/sn1 \
lib/brand/solaris10 \
- lib/cfgadm_plugins/sdcard \
lib/crypt_modules \
lib/extendedFILE \
lib/libadutils \
--- a/usr/src/cmd/hal/hald/solaris/devinfo.c Tue May 18 11:19:39 2010 +0800
+++ b/usr/src/cmd/hal/hald/solaris/devinfo.c Mon May 17 21:17:01 2010 -0700
@@ -2,8 +2,7 @@
*
* devinfo.c : main file for libdevinfo-based device enumeration
*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
*
* Licensed under the Academic Free License version 2.1
*
@@ -133,6 +132,7 @@
&devinfo_ide_handler,
&devinfo_scsi_handler,
&devinfo_pcata_handler,
+ &devinfo_blkdev_handler,
&devinfo_floppy_handler,
&devinfo_usb_handler,
&devinfo_ieee1394_handler,
--- a/usr/src/cmd/hal/hald/solaris/devinfo_storage.c Tue May 18 11:19:39 2010 +0800
+++ b/usr/src/cmd/hal/hald/solaris/devinfo_storage.c Mon May 17 21:17:01 2010 -0700
@@ -2,8 +2,7 @@
*
* devinfo_storage.c : storage devices
*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
*
* Licensed under the Academic Free License version 2.1
*
@@ -63,6 +62,8 @@
static HalDevice *devinfo_scsi_storage_add(HalDevice *parent, di_node_t node, char *devfs_path);
HalDevice *devinfo_pcata_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type);
static HalDevice *devinfo_pcata_storage_add(HalDevice *parent, di_node_t node, char *devfs_path);
+HalDevice *devinfo_blkdev_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type);
+static HalDevice *devinfo_blkdev_storage_add(HalDevice *parent, di_node_t node, char *devfs_path);
HalDevice *devinfo_floppy_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type);
static void devinfo_floppy_add_volume(HalDevice *parent, di_node_t node);
static HalDevice *devinfo_lofi_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type);
@@ -110,6 +111,14 @@
NULL,
NULL
};
+DevinfoDevHandler devinfo_blkdev_handler = {
+ devinfo_blkdev_add,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
DevinfoDevHandler devinfo_floppy_handler = {
devinfo_floppy_add,
NULL,
@@ -433,6 +442,74 @@
return (d);
}
+/* blkdev */
+
+HalDevice *
+devinfo_blkdev_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type)
+{
+ int *i;
+ char *driver_name;
+ HalDevice *d;
+ char udi[HAL_PATH_MAX];
+
+ driver_name = di_driver_name (node);
+ if ((driver_name == NULL) || (strcmp (driver_name, "blkdev") != 0)) {
+ return (NULL);
+ }
+
+ d = hal_device_new ();
+
+ devinfo_set_default_properties (d, parent, node, devfs_path);
+ hal_device_property_set_string (d, "info.subsystem", "pseudo");
+
+ hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+ "%s/%s%d", hal_device_get_udi (parent), di_node_name(node), di_instance (node));
+ hal_device_set_udi (d, udi);
+ hal_device_property_set_string (d, "info.udi", udi);
+ hal_device_property_set_string (d, "info.product", "Block Device");
+
+ devinfo_add_enqueue (d, devfs_path, &devinfo_blkdev_handler);
+
+ return (devinfo_blkdev_storage_add (d, node, devfs_path));
+}
+
+static HalDevice *
+devinfo_blkdev_storage_add(HalDevice *parent, di_node_t node, char *devfs_path)
+{
+ HalDevice *d;
+ char *driver_name;
+ int *i;
+ char *s;
+ char udi[HAL_PATH_MAX];
+
+ d = hal_device_new ();
+
+ devinfo_set_default_properties (d, parent, node, devfs_path);
+ hal_device_property_set_string (d, "info.category", "storage");
+
+ hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+ "%s/blkdev%d", hal_device_get_udi (parent), di_instance (node));
+ hal_device_set_udi (d, udi);
+ hal_device_property_set_string (d, "info.udi", udi);
+
+ hal_device_add_capability (d, "storage");
+
+ hal_device_property_set_int (d, "storage.lun", 0);
+
+ PROP_BOOL(d, node, i, "hotpluggable", "storage.hotpluggable");
+ PROP_BOOL(d, node, i, "removable-media", "storage.removable");
+
+ hal_device_property_set_bool (d, "storage.requires_eject", FALSE);
+ hal_device_property_set_bool (d, "storage.media_check_enabled", TRUE);
+ hal_device_property_set_string (d, "storage.drive_type", "disk");
+
+ hal_device_add_capability (d, "block");
+
+ devinfo_storage_minors (d, node, devfs_path, FALSE);
+
+ return (d);
+}
+
/* floppy */
HalDevice *
--- a/usr/src/cmd/hal/hald/solaris/devinfo_storage.h Tue May 18 11:19:39 2010 +0800
+++ b/usr/src/cmd/hal/hald/solaris/devinfo_storage.h Mon May 17 21:17:01 2010 -0700
@@ -2,15 +2,12 @@
*
* devinfo_storage.h : definitions for storage devices
*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
*
* Licensed under the Academic Free License version 2.1
*
**************************************************************************/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifndef DEVINFO_STORAGE_H
#define DEVINFO_STORAGE_H
@@ -19,6 +16,7 @@
extern DevinfoDevHandler devinfo_ide_handler;
extern DevinfoDevHandler devinfo_scsi_handler;
extern DevinfoDevHandler devinfo_pcata_handler;
+extern DevinfoDevHandler devinfo_blkdev_handler;
extern DevinfoDevHandler devinfo_floppy_handler;
extern DevinfoDevHandler devinfo_lofi_handler;
--- a/usr/src/lib/cfgadm_plugins/Makefile Tue May 18 11:19:39 2010 +0800
+++ b/usr/src/lib/cfgadm_plugins/Makefile Mon May 17 21:17:01 2010 -0700
@@ -19,15 +19,14 @@
# CDDL HEADER END
#
#
-# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
#
# lib/cfgadm_plugins/Makefile
#
include $(SRC)/Makefile.master
-COMMON_SUBDIRS= scsi sdcard pci usb ib fp shp sbd
+COMMON_SUBDIRS= scsi pci usb ib fp shp sbd
sparc_SUBDIRS= ac sysctrl
i386_SUBDIRS= sata
--- a/usr/src/lib/cfgadm_plugins/sdcard/Makefile Tue May 18 11:19:39 2010 +0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-include ../../Makefile.lib
-
-SUBDIRS = $(MACH)
-$(BUILD64)SUBDIRS += $(MACH64)
-
-all := TARGET= all
-clean := TARGET= clean
-clobber := TARGET= clobber
-delete := TARGET= delete
-install := TARGET= install
-lint := TARGET= lint
-_msg := TARGET= _msg
-package := TARGET= package
-
-TEXT_DOMAIN= SUNW_OST_OSLIB
-XGETFLAGS= -a -x sdcard.xcl
-POFILE= sdcard.po
-POFILES= generic.po
-
-SED= sed
-GREP= grep
-CP= cp
-
-.KEEP_STATE:
-
-all clean clobber delete install lint package: $(SUBDIRS)
-
-$(SUBDIRS): FRC
- @cd $@; pwd; $(MAKE) $(TARGET)
-
-_msg: $(MSGDOMAIN) $(POFILE)
- $(RM) $(MSGDOMAIN)/$(POFILE)
- $(CP) $(POFILE) $(MSGDOMAIN)
-
-$(POFILE): $(POFILES)
- $(RM) $@
- $(CAT) $(POFILES) > $@
-
-$(POFILES):
- $(RM) messages.po
- $(XGETTEXT) $(XGETFLAGS) `$(GREP) -l gettext */*.[ch]`
- $(SED) -e '/^# msg/d' -e '/^domain/d' messages.po > $@
- $(RM) messages.po
-
-FRC:
--- a/usr/src/lib/cfgadm_plugins/sdcard/Makefile.com Tue May 18 11:19:39 2010 +0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-LIBRARY= sdcard.a
-VERS= .1
-
-OBJECTS= cfga_sdcard.o
-
-# include library definitions
-include ../../../Makefile.lib
-
-SRCDIR = ../common
-ROOTLIBDIR= $(ROOT)/usr/lib/cfgadm
-ROOTLIBDIR64= $(ROOTLIBDIR)/$(MACH64)
-
-LIBS= $(DYNLIB)
-
-LINTFLAGS += -DDEBUG
-LINTFLAGS64 += -DDEBUG
-
-CFLAGS += $(CCVERBOSE)
-CFLAGS64 += $(CCVERBOSE)
-
-LDLIBS += -lc -ldevice -ldevinfo -lrcm
-
-.KEEP_STATE:
-
-all: $(LIBS)
-
-lint: lintcheck
-
-# Install rules
-
-$(ROOTLIBDIR)/%: % $(ROOTLIBDIR)
- $(INS.file)
-
-$(ROOTLIBDIR64)/%: % $(ROOTLIBDIR64)
- $(INS.file)
-
-$(ROOTLIBDIR) $(ROOTLIBDIR64):
- $(INS.dir)
-
-# include library targets
-include ../../../Makefile.targ
-
-objs/%.o pics/%.o: ../common/%.c
- $(COMPILE.c) -o $@ $<
- $(POST_PROCESS_O)
--- a/usr/src/lib/cfgadm_plugins/sdcard/amd64/Makefile Tue May 18 11:19:39 2010 +0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-include ../Makefile.com
-include ../../../Makefile.lib.64
-CFLAGS += -D_POSIX_PTHREAD_SEMANTICS
-LINTFLAGS += -D_POSIX_PTHREAD_SEMANTICS
-
-.KEEP_STATE:
-
-install: all $(ROOTLIBS64) $(ROOTLINKS64)
--- a/usr/src/lib/cfgadm_plugins/sdcard/common/cfga_sdcard.c Tue May 18 11:19:39 2010 +0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1933 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#include <sys/param.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <string.h>
-#include <dirent.h>
-#include "cfga_sdcard.h"
-
-/*
- * This file contains the entry points to the plug-in as defined in the
- * config_admin(3X) man page.
- */
-
-/*
- * Set the version number for the cfgadm library's use.
- */
-int cfga_version = CFGA_HSL_V2;
-
-enum {
- HELP_HEADER = 1,
- HELP_CONFIG,
- HELP_RESET_SLOT,
- HELP_UNKNOWN
-};
-
-/* SDCARD specific help messages */
-static char *sdcard_help[] = {
- NULL,
- "SD card specific commands:\n",
- " cfgadm -c [configure|unconfigure|disconnect|connect] ap_id "
- "[ap_id...]\n",
- " cfgadm -x sdcard_reset_slot ap_id [ap_id...]\n",
- "\tunknown command or option:\n",
- NULL
-}; /* End help messages */
-
-
-/*
- * Messages.
- */
-static msgcvt_t sdcard_msgs[] = {
- /* CFGA_SDCARD_OK */
- { CVT, CFGA_OK, "" },
-
- /* CFGA_SDCARD_NACK */
- { CVT, CFGA_NACK, "" },
-
- /* CFGA_SDCARD_UNKNOWN / CFGA_LIB_ERROR -> "Library error" */
- { CVT, CFGA_LIB_ERROR, "Unknown message; internal error" },
-
- /* CFGA_SDCARD_PRIV / CFGA_PRIV -> "Insufficient privileges" */
- { CVT, CFGA_PRIV, "" },
-
- /*
- * CFGA_SDCARD_DYNAMIC_AP /
- * CFGA_LIB_ERROR -> "Configuration operation invalid"
- */
- { CVT, CFGA_INVAL, "Cannot identify attached device" },
-
- /* CFGA_SDCARD_INTERNAL_ERROR / CFGA_LIB_ERROR -> "Library error" */
- { CVT, CFGA_LIB_ERROR, "Internal error" },
-
- /* CFGA_SDCARD_ALLOC_FAIL / CFGA_LIB_ERROR -> "Library error" */
- { CVT, CFGA_LIB_ERROR, "Memory allocation failure" },
-
- /* CFGA_SDCARD_IOCTL / CFGA_ERROR -> "Hardware specific failure" */
- { CVT, CFGA_ERROR, "Driver ioctl failed " },
-
- /* CFGA_SDCARD_DEVCTL / CFGA_LIB_ERROR -> "Library error" */
- { CVT, CFGA_LIB_ERROR, "Internal error: "
- "Cannot allocate devctl handle " },
-
- /* CFGA_SDCARD_AP / CFGA_APID_NOEXIST -> "Attachment point not found" */
- { CVT, CFGA_APID_NOEXIST, "" },
-
- /*
- * CFGA_SDCARD_BUSY /
- * CFGA_SYSTEM_BUSY -> "System is busy, try again"
- */
- { CVT, CFGA_SYSTEM_BUSY, "" },
-
- /* CFGA_SDCARD_DEVLINK / CFGA_LIB_ERROR -> "Library error" */
- { CVT, CFGA_LIB_ERROR, "Could not find /dev/cfg link for " },
-
- /*
- * CFGA_SDCARD_INVALID_DEVNAME /
- * CFGA_INVAL -> "Configuration operation invalid"
- */
- { CVT, CFGA_INVAL, "Cannot specify device name" },
-
- /* CFGA_SDCARD_DATA_ERROR / CFGA_DATA_ERROR -> "Data error" */
- { CVT, CFGA_DATA_ERROR, "cfgadm data error" },
-
- /*
- * CFGA_SDCARD_DEV_CONFIGURE /
- * CFGA_ERROR -> "Hardware specific failure"
- */
- { CVT, CFGA_ERROR, "Failed to config device at " },
-
- /*
- * CFGA_SDCARD_DEV_UNCONFIGURE /
- * CFGA_ERROR -> "Hardware specific failure"
- */
- { CVT, CFGA_ERROR, "Failed to unconfig device at " },
-
- /*
- * CFGA_SDCARD_NOT_CONNECTED
- * CFGA_INVAL -> "Configuration operation invalid"
- */
- { CVT, CFGA_INVAL, "No device connected to " },
-
- /*
- * CFGA_SDCARD_DISCONNECTED
- * CFGA_INVAL -> "Configuration operation invalid"
- */
- { CVT, CFGA_INVAL, "Slot already disconnected at " },
-
- /*
- * CFGA_SDCARD_NOT_CONFIGURED /
- * CFGA_INVAL -> "Configuration operation invalid"
- */
- { CVT, CFGA_INVAL, "No device configured at " },
-
- /*
- * CFGA_SDCARD_ALREADY_CONNECTED /
- * CFGA_INVAL -> "Configuration operation invalid"
- */
- { CVT, CFGA_INVAL, "Device already connected to " },
-
- /*
- * CFGA_SDCARD_ALREADY_CONFIGURED /
- * CFGA_INVAL -> "Configuration operation invalid"
- */
- { CVT, CFGA_INVAL, "Device already configured at " },
-
- /* CFGA_SDCARD_DEVICE_UNCONFIGURED */
- { CVT, CFGA_OK, "Device unconfigured prior to disconnect" },
-
- /*
- * CFGA_SDCARD_OPNOTSUPP /
- * CFGA_OPNOTSUPP -> "Configuration operation not supported"
- */
- { CVT, CFGA_OPNOTSUPP, "Operation not supported" },
-
- /*
- * CFGA_SDCARD_HWOPNOTSUPP /
- * CFGA_ERROR -> "Hardware specific failure"
- */
- { CVT, CFGA_ERROR, "Hardware specific operation not supported" },
-
- /* CFGA_SDCARD_OPTIONS / CFGA_ERROR -> "Hardware specific failure" */
- { CVT, CFGA_ERROR, "Hardware specific option not supported" },
-
- /* CFGA_SDCARD_STATE / CFGA_LIB_ERROR -> "Library error" */
- { CVT, CFGA_LIB_ERROR, "Internal error: Unrecognized ap state" },
-
- /* CFGA_SDCARD_OPEN / CFGA_LIB_ERROR -> "Library error" */
- { CVT, CFGA_LIB_ERROR, "Cannot open " },
-
- /*
- * CFGA_SDCARD_RCM_HANDLE /
- * CFGA_ERROR -> "Hardware specific failure"
- */
- { CVT, CFGA_ERROR, "cannot get RCM handle"},
-
- /*
- * CFGA_SDCARD_RCM_OFFLINE /
- * CFGA_SYSTEM_BUSY -> "System is busy, try again"
- */
- { CVT, CFGA_SYSTEM_BUSY, "failed to offline: "},
-
- /*
- * CFGA_SDCARD_RCM_REMOVE /
- * CFGA_SYSTEM_BUSY -> "System is busy, try again"
- */
- { CVT, CFGA_SYSTEM_BUSY, "failed to remove: "},
-
- /*
- * CFGA_SDCARD_RCM_ONLINE /
- * CFGA_SYSTEM_BUSY -> "System is busy, try again"
- */
- { CVT, CFGA_ERROR, "failed to online: "},
-
- /* CFGA_SDCARD_CONFIRM_RESET */
- { CVT, CFGA_OK, "Reset the device at %s?\n"
- "This will operation will disrupt activity on the SD card.\n"
- "Continue"
- },
-
- /* CFGA_SDCARD_CONFIRM_UNCONFIGURE */
- { CVT, CFGA_OK, "Unconfigure the device at %s?\n"
- "This will operation will disrupt activity on the SD card.\n"
- "Continue"
- },
-
- /* CFGA_SDCARD_CONFIRM_DISCONNECT */
- { CVT, CFGA_OK, "Disconnect the device at %s?\n"
- "This will operation will disrupt activity on the SD card.\n"
- "Continue"
- }
-};
-
-static cfga_err_t
-sdcard_err_msg(char **errstring, cfga_sdcard_ret_t ret, const char *, int);
-
-static cfga_sdcard_ret_t
-verify_params(const char *ap_id, const char *options, char **errstring);
-
-static cfga_sdcard_ret_t
-setup_for_devctl_cmd(const char *ap_id, devctl_hdl_t *devctl_hdl, uint_t oflag);
-
-static cfga_sdcard_ret_t
-slot_state(devctl_hdl_t hdl, ap_rstate_t *rstate, ap_ostate_t *ostate);
-
-static cfga_sdcard_ret_t
-do_control_ioctl(const char *ap_id, int subcommand, void *data, size_t size);
-
-static void
-cleanup_after_devctl_cmd(devctl_hdl_t devctl_hdl);
-
-static cfga_sdcard_ret_t
-sdcard_get_devicepath(const char *ap_id, char *devpath);
-
-static cfga_sdcard_ret_t
-sdcard_reset_slot(const char *ap_id);
-
-static int
-sdcard_confirm(struct cfga_confirm *confp, char *msg);
-
-static cfga_sdcard_ret_t
-sdcard_rcm_offline(char *, char **, cfga_flags_t);
-
-static void
-sdcard_rcm_online(char *, char **);
-
-static void
-sdcard_rcm_remove(char *, char **);
-
-static void
-sdcard_rcm_info_table(rcm_info_t *, char **);
-
-static cfga_sdcard_ret_t
-sdcard_rcm_init(void);
-
-
-
-/* Utilities */
-
-static cfga_sdcard_ret_t
-physpath_to_devlink(const char *basedir, const char *node_path,
- char **logpp, int *l_errnop)
-{
- char *linkpath;
- char *buf;
- char *real_path;
- DIR *dp;
- struct dirent *dep, *newdep;
- int deplen;
- boolean_t found = B_FALSE;
- int err = 0;
- struct stat sb;
- char *p;
- cfga_sdcard_ret_t rv = CFGA_SDCARD_INTERNAL_ERROR;
-
- /*
- * Using libdevinfo for this is overkill and kills performance
- * when multiple consumers of libcfgadm are executing
- * concurrently.
- */
- if ((dp = opendir(basedir)) == NULL) {
- *l_errnop = errno;
- return (CFGA_SDCARD_INTERNAL_ERROR);
- }
-
- linkpath = malloc(PATH_MAX);
- buf = malloc(PATH_MAX);
- real_path = malloc(PATH_MAX);
-
- deplen = pathconf(basedir, _PC_NAME_MAX);
- deplen = (deplen <= 0 ? MAXNAMELEN : deplen) +
- sizeof (struct dirent);
- dep = (struct dirent *)malloc(deplen);
-
- if (dep == NULL || linkpath == NULL || buf == NULL ||
- real_path == NULL) {
- *l_errnop = ENOMEM;
- rv = CFGA_SDCARD_ALLOC_FAIL;
- goto pp_cleanup;
- }
-
- *logpp = NULL;
-
- while (!found && (err = readdir_r(dp, dep, &newdep)) == 0 &&
- newdep != NULL) {
-
- assert(newdep == dep);
-
- if (strcmp(dep->d_name, ".") == 0 ||
- strcmp(dep->d_name, "..") == 0)
- continue;
-
- (void) snprintf(linkpath, MAXPATHLEN,
- "%s/%s", basedir, dep->d_name);
-
- if (lstat(linkpath, &sb) < 0)
- continue;
-
- if (S_ISDIR(sb.st_mode)) {
-
- if ((rv = physpath_to_devlink(linkpath, node_path,
- logpp, l_errnop)) != CFGA_SDCARD_OK) {
-
- goto pp_cleanup;
- }
-
- if (*logpp != NULL)
- found = B_TRUE;
-
- } else if (S_ISLNK(sb.st_mode)) {
-
- bzero(buf, PATH_MAX);
- if (readlink(linkpath, buf, PATH_MAX) < 0)
- continue;
-
-
- /*
- * realpath() is too darn slow, so fake
- * it, by using what we know about /dev
- * links: they are always of the form:
- * <"../">+/devices/<path>
- */
- p = buf;
- while (strncmp(p, "../", 3) == 0)
- p += 3;
-
- if (p != buf)
- p--; /* back up to get a slash */
-
- assert (*p == '/');
-
- if (strcmp(p, node_path) == 0) {
- *logpp = strdup(linkpath);
- if (*logpp == NULL) {
-
- rv = CFGA_SDCARD_ALLOC_FAIL;
- goto pp_cleanup;
- }
-
- found = B_TRUE;
- }
- }
- }
-
- free(linkpath);
- free(buf);
- free(real_path);
- free(dep);
- (void) closedir(dp);
-
- if (err != 0) {
- *l_errnop = err;
- return (CFGA_SDCARD_INTERNAL_ERROR);
- }
-
- return (CFGA_SDCARD_OK);
-
-pp_cleanup:
-
- if (dp)
- (void) closedir(dp);
- if (dep)
- free(dep);
- if (linkpath)
- free(linkpath);
- if (buf)
- free(buf);
- if (real_path)
- free(real_path);
- if (*logpp) {
- free(*logpp);
- *logpp = NULL;
- }
- return (rv);
-}
-
-
-/*
- * Given the index into a table (msgcvt_t) of messages, get the message
- * string, converting it to the proper locale if necessary.
- * NOTE: Indexes are defined in cfga_sdcard.h
- */
-static const char *
-get_msg(uint_t msg_index, msgcvt_t *msg_tbl, uint_t tbl_size)
-{
- if (msg_index >= tbl_size) {
- msg_index = CFGA_SDCARD_UNKNOWN;
- }
-
- return ((msg_tbl[msg_index].intl) ?
- dgettext(TEXT_DOMAIN, msg_tbl[msg_index].msgstr) :
- msg_tbl[msg_index].msgstr);
-}
-
-/*
- * Allocates and creates a message string (in *ret_str),
- * by concatenating all the (char *) args together, in order.
- * Last arg MUST be NULL.
- */
-static void
-set_msg(char **ret_str, ...)
-{
- char *str;
- size_t total_len;
- va_list valist;
-
- va_start(valist, ret_str);
-
- total_len = (*ret_str == NULL) ? 0 : strlen(*ret_str);
-
- while ((str = va_arg(valist, char *)) != NULL) {
- size_t len = strlen(str);
- char *old_str = *ret_str;
-
- *ret_str = (char *)realloc(*ret_str, total_len + len + 1);
- if (*ret_str == NULL) {
- /* We're screwed */
- free(old_str);
- va_end(valist);
- return;
- }
-
- (void) strcpy(*ret_str + total_len, str);
- total_len += len;
- }
-
- va_end(valist);
-}
-
-/*
- * Error message handling.
- * For the rv passed in, looks up the corresponding error message string(s),
- * internationalized if necessary, and concatenates it into a new
- * memory buffer, and points *errstring to it.
- * Note not all rvs will result in an error message return, as not all
- * error conditions warrant an SD-specific error message - for those
- * conditions the cfgadm generic messages are sufficient.
- *
- * Some messages may display ap_id or errno, which is why they are passed
- * in.
- */
-cfga_err_t
-sdcard_err_msg(
- char **errstring,
- cfga_sdcard_ret_t rv,
- const char *ap_id,
- int l_errno)
-{
- if (errstring == NULL) {
- return (sdcard_msgs[rv].cfga_err);
- }
-
- /*
- * Generate the appropriate SDCARD-specific error message(s) (if any).
- */
- switch (rv) {
- case CFGA_SDCARD_OK:
- case CFGA_NACK:
- /* Special case - do nothing. */
- break;
-
- case CFGA_SDCARD_UNKNOWN:
- case CFGA_SDCARD_PRIV:
- case CFGA_SDCARD_DYNAMIC_AP:
- case CFGA_SDCARD_INTERNAL_ERROR:
- case CFGA_SDCARD_ALLOC_FAIL:
- case CFGA_SDCARD_DATA_ERROR:
- case CFGA_SDCARD_OPNOTSUPP:
- case CFGA_SDCARD_OPTIONS:
- case CFGA_SDCARD_STATE:
-
- /* These messages require no additional strings passed. */
- set_msg(errstring, ERR_STR(rv), NULL);
- break;
-
- case CFGA_SDCARD_HWOPNOTSUPP:
- /* hardware-specific help needed */
- set_msg(errstring, ERR_STR(rv), NULL);
- set_msg(errstring, "\n",
- dgettext(TEXT_DOMAIN, sdcard_help[HELP_HEADER]), NULL);
- set_msg(errstring, sdcard_help[HELP_RESET_SLOT], NULL);
- break;
-
- case CFGA_SDCARD_AP:
- case CFGA_SDCARD_BUSY:
- case CFGA_SDCARD_DEVLINK:
- case CFGA_SDCARD_DEV_CONFIGURE:
- case CFGA_SDCARD_DEV_UNCONFIGURE:
- case CFGA_SDCARD_NOT_CONNECTED:
- case CFGA_SDCARD_DISCONNECTED:
- case CFGA_SDCARD_NOT_CONFIGURED:
- case CFGA_SDCARD_ALREADY_CONNECTED:
- case CFGA_SDCARD_ALREADY_CONFIGURED:
-
- case CFGA_SDCARD_RCM_HANDLE:
- case CFGA_SDCARD_RCM_ONLINE:
- case CFGA_SDCARD_RCM_OFFLINE:
- case CFGA_SDCARD_RCM_REMOVE:
- /* These messages also print ap_id. */
- set_msg(errstring, ERR_STR(rv), "ap_id: ", ap_id, "", NULL);
- break;
-
-
- case CFGA_SDCARD_IOCTL:
- /* These messages also print errno. */
- {
- char *errno_str = l_errno ? strerror(l_errno) : "";
-
- set_msg(errstring, ERR_STR(rv), errno_str,
- l_errno ? "\n" : "", NULL);
- break;
- }
-
- case CFGA_SDCARD_OPEN:
- /* These messages also apid and errno. */
- {
- char *errno_str = l_errno ? strerror(l_errno) : "";
-
- set_msg(errstring, ERR_STR(rv), "ap_id: ", ap_id, "\n",
- errno_str, l_errno ? "\n" : "", NULL);
- break;
- }
-
- default:
- set_msg(errstring, ERR_STR(CFGA_SDCARD_INTERNAL_ERROR), NULL);
-
- } /* end switch */
-
-
- /*
- * Determine the proper error code to send back to the cfgadm library.
- */
- return (sdcard_msgs[rv].cfga_err);
-}
-
-
-/*
- * Entry points
- */
-/* cfgadm entry point */
-/*ARGSUSED*/
-cfga_err_t
-cfga_change_state(
- cfga_cmd_t state_change_cmd,
- const char *ap_id,
- const char *options,
- struct cfga_confirm *confp,
- struct cfga_msg *msgp,
- char **errstring,
- cfga_flags_t flags)
-{
- int ret;
- ap_rstate_t rstate;
- ap_ostate_t ostate;
- devctl_hdl_t hdl = NULL;
- cfga_sdcard_ret_t rv = CFGA_SDCARD_OK;
- char *pdyn;
- int i;
- char devpath[MAXPATHLEN];
- char msg[256];
-
- /*
- * All sub-commands which can change state of device require
- * root privileges.
- */
- if (geteuid() != 0) {
- rv = CFGA_SDCARD_PRIV;
- goto bailout;
- }
-
- if ((rv = verify_params(ap_id, options, errstring)) != CFGA_SDCARD_OK) {
- (void) cfga_help(msgp, options, flags);
- goto bailout;
- }
-
- if ((rv = setup_for_devctl_cmd(ap_id, &hdl, DC_RDONLY)) !=
- CFGA_SDCARD_OK) {
- goto bailout;
- }
-
- switch (state_change_cmd) {
- case CFGA_CMD_CONFIGURE:
- if ((rv = slot_state(hdl, &rstate, &ostate)) != CFGA_SDCARD_OK)
- goto bailout;
-
- if (ostate == AP_OSTATE_CONFIGURED) {
- rv = CFGA_SDCARD_ALREADY_CONFIGURED;
- goto bailout;
- }
- /* Disallow dynamic AP name component */
- if (GET_DYN(ap_id) != NULL) {
- rv = CFGA_SDCARD_INVALID_DEVNAME;
- goto bailout;
- }
-
- if (rstate == AP_RSTATE_EMPTY) {
- rv = CFGA_SDCARD_NOT_CONNECTED;
- goto bailout;
- }
- rv = CFGA_SDCARD_OK;
-
- if (devctl_ap_configure(hdl, NULL) != 0) {
- rv = CFGA_SDCARD_DEV_CONFIGURE;
- goto bailout;
- }
-
- for (i = 0; i < 15; i++) {
- /*
- * We wait up to ~30 seconds for this to complete.
- * Hotplug is done asynchronously.
- */
- rv = sdcard_get_devicepath(ap_id, devpath);
- if (rv == CFGA_SDCARD_OK)
- break;
- (void) sleep(2);
- }
- if (rv != CFGA_SDCARD_OK) {
- rv = CFGA_SDCARD_DEV_CONFIGURE;
- goto bailout;
- }
-
- break;
-
- case CFGA_CMD_UNCONFIGURE:
- if ((rv = slot_state(hdl, &rstate, &ostate)) != CFGA_SDCARD_OK)
- goto bailout;
-
- if (rstate != AP_RSTATE_CONNECTED) {
- rv = CFGA_SDCARD_NOT_CONNECTED;
- goto bailout;
- }
-
- if (ostate != AP_OSTATE_CONFIGURED) {
- rv = CFGA_SDCARD_NOT_CONFIGURED;
- goto bailout;
- }
- /* Strip off AP name dynamic component, if present */
- if ((pdyn = GET_DYN(ap_id)) != NULL) {
- *pdyn = '\0';
- }
-
- rv = CFGA_SDCARD_OK;
-
- /*LINTED E_SEC_PRINTF_VAR_FMT*/
- (void) snprintf(msg, sizeof (msg),
- ERR_STR(CFGA_SDCARD_CONFIRM_UNCONFIGURE), ap_id);
-
- if (!sdcard_confirm(confp, msg)) {
- rv = CFGA_SDCARD_NACK;
- break;
- }
-
- if (sdcard_get_devicepath(ap_id, devpath) != CFGA_SDCARD_OK) {
- (void) printf("cfga_change_state: "
- "get device path failed\n");
- rv = CFGA_SDCARD_DEV_UNCONFIGURE;
- break;
- }
-
- rv = sdcard_rcm_offline(devpath, errstring, flags);
- if (rv != CFGA_SDCARD_OK) {
- break;
- }
-
- ret = devctl_ap_unconfigure(hdl, NULL);
-
- if (ret != 0) {
- rv = CFGA_SDCARD_DEV_UNCONFIGURE;
- if (errno == EBUSY) {
- rv = CFGA_SDCARD_BUSY;
- }
- sdcard_rcm_online(devpath, errstring);
- } else {
- sdcard_rcm_remove(devpath, errstring);
- }
-
- break;
-
- case CFGA_CMD_DISCONNECT:
- if ((rv = slot_state(hdl, &rstate, &ostate)) != CFGA_SDCARD_OK)
- goto bailout;
-
- if (rstate == AP_RSTATE_DISCONNECTED) {
- rv = CFGA_SDCARD_DISCONNECTED;
- goto bailout;
- }
-
- /* Strip off AP name dynamic component, if present */
- if ((pdyn = GET_DYN(ap_id)) != NULL) {
- *pdyn = '\0';
- }
-
-
- rv = CFGA_SDCARD_OK; /* other statuses don't matter */
-
-
- /*
- * If the port originally with device attached and was
- * unconfigured already, the devicepath for the sd will be
- * removed. sdcard_get_devicepath in this case is not necessary.
- */
-
- /* only call rcm_offline if the state was CONFIGURED */
- if (ostate == AP_OSTATE_CONFIGURED) {
- if (sdcard_get_devicepath(ap_id, devpath) !=
- CFGA_SDCARD_OK) {
- (void) printf(
- "cfga_change_state: get path failed\n");
- rv = CFGA_SDCARD_DEV_UNCONFIGURE;
- break;
- }
-
- /*LINTED E_SEC_PRINTF_VAR_FMT*/
- (void) snprintf(msg, sizeof (msg),
- ERR_STR(CFGA_SDCARD_CONFIRM_DISCONNECT), ap_id);
- if (!sdcard_confirm(confp, msg)) {
- rv = CFGA_SDCARD_NACK;
- break;
- }
-
- rv = sdcard_rcm_offline(devpath, errstring, flags);
- if (rv != CFGA_SDCARD_OK) {
- break;
- }
-
- ret = devctl_ap_unconfigure(hdl, NULL);
- if (ret != 0) {
- (void) printf(
- "devctl_ap_unconfigure failed\n");
- rv = CFGA_SDCARD_DEV_UNCONFIGURE;
- if (errno == EBUSY)
- rv = CFGA_SDCARD_BUSY;
- sdcard_rcm_online(devpath, errstring);
-
- /*
- * The current policy is that if unconfigure
- * failed, do not continue with disconnect.
- */
- break;
- } else {
- (void) printf("%s\n",
- ERR_STR(CFGA_SDCARD_DEVICE_UNCONFIGURED));
- sdcard_rcm_remove(devpath, errstring);
- }
- } else if (rstate == AP_RSTATE_CONNECTED ||
- rstate == AP_RSTATE_EMPTY) {
- /*LINTED E_SEC_PRINTF_VAR_FMT*/
- (void) snprintf(msg, sizeof (msg),
- ERR_STR(CFGA_SDCARD_CONFIRM_DISCONNECT), ap_id);
-
- if (!sdcard_confirm(confp, msg)) {
- rv = CFGA_SDCARD_NACK;
- break;
- }
- }
- ret = devctl_ap_disconnect(hdl, NULL);
- if (ret != 0) {
- rv = CFGA_SDCARD_IOCTL;
- if (errno == EBUSY) {
- rv = CFGA_SDCARD_BUSY;
- }
- }
- break;
-
- case CFGA_CMD_CONNECT:
- if ((rv = slot_state(hdl, &rstate, &ostate)) != CFGA_SDCARD_OK)
- goto bailout;
-
- if (rstate == AP_RSTATE_CONNECTED) {
- rv = CFGA_SDCARD_ALREADY_CONNECTED;
- goto bailout;
- }
-
- /* Disallow dynamic AP name component */
- if (GET_DYN(ap_id) != NULL) {
- rv = CFGA_SDCARD_INVALID_DEVNAME;
- goto bailout;
- }
-
- ret = devctl_ap_connect(hdl, NULL);
- if (ret != 0) {
- rv = CFGA_SDCARD_IOCTL;
- } else {
- rv = CFGA_SDCARD_OK;
- }
-
- break;
-
- case CFGA_CMD_LOAD:
- case CFGA_CMD_UNLOAD:
- (void) cfga_help(msgp, options, flags);
- rv = CFGA_SDCARD_OPNOTSUPP;
- break;
-
- case CFGA_CMD_NONE:
- default:
- (void) cfga_help(msgp, options, flags);
- rv = CFGA_SDCARD_INTERNAL_ERROR;
- }
-
-bailout:
- cleanup_after_devctl_cmd(hdl);
-
- return (sdcard_err_msg(errstring, rv, ap_id, errno));
-}
-
-/* cfgadm entry point */
-/*ARGSUSED*/
-cfga_err_t
-cfga_private_func(
- const char *func,
- const char *ap_id,
- const char *options,
- struct cfga_confirm *confp,
- struct cfga_msg *msgp,
- char **errstring,
- cfga_flags_t flags)
-{
- devctl_hdl_t hdl = NULL;
- cfga_sdcard_ret_t rv;
- char *str_p;
- char msg[256];
-
- if ((rv = verify_params(ap_id, NULL, errstring)) != CFGA_SDCARD_OK) {
- (void) cfga_help(msgp, options, flags);
- return (sdcard_err_msg(errstring, rv, ap_id, errno));
- }
-
- /*
- * All subcommands which can change state of device require
- * root privileges.
- */
- if (geteuid() != 0) {
- rv = CFGA_SDCARD_PRIV;
- goto bailout;
- }
-
- if (func == NULL) {
- rv = CFGA_SDCARD_OPTIONS;
- goto bailout;
- }
-
- if ((rv = setup_for_devctl_cmd(ap_id, &hdl, 0)) != CFGA_SDCARD_OK) {
- goto bailout;
- }
-
- /* We do not care here about dynamic AP name component */
- if ((str_p = GET_DYN(ap_id)) != NULL) {
- *str_p = '\0';
- }
-
- if (strcmp(func, RESET_SLOT) == 0) {
- /*LINTED E_SEC_PRINTF_VAR_FMT*/
- (void) snprintf(msg, sizeof (msg),
- ERR_STR(CFGA_SDCARD_CONFIRM_RESET), ap_id);
-
- if (!sdcard_confirm(confp, msg)) {
- rv = CFGA_SDCARD_NACK;
- goto bailout;
- }
- if ((rv = sdcard_reset_slot(ap_id)) != CFGA_SDCARD_OK) {
- goto bailout;
- }
-
- rv = CFGA_SDCARD_OK;
- } else {
-
- /* Unrecognized operation request */
- rv = CFGA_SDCARD_HWOPNOTSUPP;
- }
-
-bailout:
- cleanup_after_devctl_cmd(hdl);
-
- return (sdcard_err_msg(errstring, rv, ap_id, errno));
-
-}
-
-/* cfgadm entry point */
-/*ARGSUSED*/
-cfga_err_t
-cfga_test(
- const char *ap_id,
- const char *options,
- struct cfga_msg *msgp,
- char **errstring,
- cfga_flags_t flags)
-{
- /* Should call ioctl for self test - phase 2 */
- return (CFGA_OPNOTSUPP);
-}
-
-
-struct chk_dev {
- int c_isblk;
- char *c_minor;
-};
-
-/*ARGSUSED*/
-static int
-chk_dev_fcn(di_node_t node, di_minor_t minor, void *arg)
-{
- char *mn;
- struct chk_dev *chkp = (struct chk_dev *)arg;
-
- mn = di_minor_name(minor);
- if (mn == NULL)
- return (DI_WALK_CONTINUE);
-
- if (strcmp(mn, chkp->c_minor) != 0)
- return (DI_WALK_CONTINUE);
-
- chkp->c_isblk = di_minor_spectype(minor) == S_IFBLK ? 1 : 0;
-
- return (DI_WALK_TERMINATE);
-}
-
-/*
- * Don't use devfs if stat() in /devices fails. Use libdevinfo instead.
- * Retired devices don't show up in devfs.
- *
- * Returns:
- * 1 - minor exists and is of type BLK
- * 0 - minor does not exist or is not of type BLK.
- */
-static int
-is_devinfo_blk(char *minor_path)
-{
- char *minor_portion;
- struct chk_dev chk_dev;
- di_node_t node;
- int rv;
-
- /*
- * prune minor path for di_init() - no /devices prefix and no minor name
- */
- if (strncmp(minor_path, "/devices/", strlen("/devices/")) != 0)
- return (0);
-
- minor_portion = strrchr(minor_path, MINOR_SEP);
- if (minor_portion == NULL)
- return (0);
-
- *minor_portion = 0;
-
- node = di_init(minor_path + strlen("/devices"), DINFOMINOR);
-
- *minor_portion = MINOR_SEP;
-
- if (node == DI_NODE_NIL)
- return (0);
-
- chk_dev.c_isblk = 0;
- chk_dev.c_minor = minor_portion + 1;
-
- rv = di_walk_minor(node, NULL, 0, &chk_dev, chk_dev_fcn);
-
- di_fini(node);
-
- if (rv == 0 && chk_dev.c_isblk)
- return (1);
- else
- return (0);
-}
-
-/*
- * The dynamic component buffer returned by this function has to be freed!
- */
-cfga_sdcard_ret_t
-sdcard_make_dyncomp(const char *ap_id, char **dyncomp)
-{
- char *cp = NULL;
- int l_errno;
- char devpath[MAXPATHLEN];
- char minor_path[MAXPATHLEN];
- char name_part[MAXNAMELEN];
- char *devlink = NULL;
- char *minor_portion = NULL;
- int deplen;
- int err;
- DIR *dp = NULL;
- struct stat sb;
- struct dirent *dep = NULL;
- struct dirent *newdep = NULL;
- char *p;
-
- assert(dyncomp != NULL);
-
- /*
- * Get target node path
- */
- if (sdcard_get_devicepath(ap_id, devpath) != CFGA_SDCARD_OK) {
-
- (void) printf("cfga_list_ext: cannot locate target device\n");
- return (CFGA_SDCARD_DYNAMIC_AP);
-
- } else {
-
- cp = strrchr(devpath, PATH_SEP);
- assert(cp != NULL);
-
- /*
- * If the child node is the sdcard node, then what we really
- * want is the grandchild. But we know that the grandchild
- * will always be disk@0,0.
- */
- if (strstr(cp, "/sdcard@") == cp) {
- /* sdcard nodes have disk children, if any */
- (void) strlcat(devpath, "/disk@0,0", sizeof (devpath));
- cp = strrchr(cp, PATH_SEP);
- }
- *cp = 0; /* terminate path for opendir() */
-
- (void) strncpy(name_part, cp + 1, MAXNAMELEN);
-
- /*
- * Using libdevinfo for this is overkill and kills
- * performance when many consumers are using libcfgadm
- * concurrently.
- */
- if ((dp = opendir(devpath)) == NULL) {
- goto bailout;
- }
-
- /*
- * deplen is large enough to fit the largest path-
- * struct dirent includes one byte (the terminator)
- * so we don't add 1 to the calculation here.
- */
- deplen = pathconf(devpath, _PC_NAME_MAX);
- deplen = ((deplen <= 0) ? MAXNAMELEN : deplen) +
- sizeof (struct dirent);
- dep = (struct dirent *)malloc(deplen);
- if (dep == NULL)
- goto bailout;
-
- while ((err = readdir_r(dp, dep, &newdep)) == 0 &&
- newdep != NULL) {
-
- assert(newdep == dep);
-
- if (strcmp(dep->d_name, ".") == 0 ||
- strcmp(dep->d_name, "..") == 0 ||
- (minor_portion = strchr(dep->d_name,
- MINOR_SEP)) == NULL)
- continue;
-
- *minor_portion = 0;
- if (strcmp(dep->d_name, name_part) != 0)
- continue;
- *minor_portion = MINOR_SEP;
-
- (void) snprintf(minor_path, MAXPATHLEN,
- "%s/%s", devpath, dep->d_name);
-
- /*
- * If stat() fails, the device *may* be retired.
- * Check via libdevinfo if the device has a BLK minor.
- * We don't use libdevinfo all the time, since taking
- * a snapshot is slower than a stat().
- */
- if (stat(minor_path, &sb) < 0) {
- if (is_devinfo_blk(minor_path)) {
- break;
- } else {
- continue;
- }
- }
-
- if (S_ISBLK(sb.st_mode))
- break;
- }
-
- (void) closedir(dp);
- free(dep);
-
- dp = NULL;
- dep = NULL;
-
- /*
- * If there was an error, or we didn't exit the loop
- * by finding a block or character device, bail out.
- */
- if (err != 0 || newdep == NULL)
- goto bailout;
-
- /*
- * Look for links to the physical path in /dev/dsk,
- * since we ONLY looked for BLOCK devices above.
- */
-
- (void) physpath_to_devlink("/dev/dsk",
- minor_path, &devlink, &l_errno);
-
- /* postprocess and copy logical name here */
- if (devlink != NULL) {
- /*
- * For disks, remove partition/slice info
- */
- if ((cp = strstr(devlink, "dsk/")) != NULL) {
- /* cXtYdZ[(s[0..15])|(p[0..X])] */
- if ((p = strchr(cp + 4, 'd')) != NULL) {
- p++; /* Skip the 'd' */
- while (*p != 0 && isdigit(*p))
- p++;
- *p = 0;
- }
- *dyncomp = strdup(cp);
- }
-
- free(devlink);
- }
-
- return (CFGA_SDCARD_OK);
- }
-
-bailout:
- if (dp)
- (void) closedir(dp);
- if (dep)
- free(dep);
- return (CFGA_SDCARD_DYNAMIC_AP);
-}
-
-void
-sdcard_clean_string(char *s, int sz)
-{
- int len;
- char *p;
-
- /* ensure null termination */
- s[sz - 1] = '\0';
- p = s;
-
- /* strip leading white space */
- while (*p == ' ') p++;
- (void) memmove(s, p, strlen(p));
-
- len = strlen(s) - 1;
- /* trim trailing space */
- while ((len >= 0) && (s[len] == ' ')) {
- s[len] = '\0';
- len--;
- }
-
- for (/* nop */; len >= 0; len--) {
- char c = s[len];
- if (((c >= 'a') && (c <= 'z')) ||
- ((c >= 'A') && (c <= 'Z')) ||
- ((c >= '0') && (c <= '9')) ||
- (c == '_') || (c == '+') || (c == '-'))
- continue;
- s[len] = '_';
- }
-}
-
-/* cfgadm entry point */
-/*ARGSUSED*/
-cfga_err_t
-cfga_list_ext(
- const char *ap_id,
- cfga_list_data_t **ap_id_list,
- int *nlistp,
- const char *options,
- const char *listopts,
- char **errstring,
- cfga_flags_t flags)
-{
- int l_errno;
- char *ap_id_log = NULL;
- devctl_hdl_t devctl_hdl = NULL;
- cfga_sdcard_ret_t rv = CFGA_SDCARD_OK;
- devctl_ap_state_t devctl_ap_state;
- char *pdyn;
-
-
- if ((rv = verify_params(ap_id, options, errstring)) != CFGA_SDCARD_OK) {
- (void) cfga_help(NULL, options, flags);
- goto bailout;
- }
- /* We do not care here about dynamic AP name component */
- if ((pdyn = GET_DYN(ap_id)) != NULL) {
- *pdyn = '\0';
- }
-
- if (ap_id_list == NULL || nlistp == NULL) {
- rv = CFGA_SDCARD_DATA_ERROR;
- (void) cfga_help(NULL, options, flags);
- goto bailout;
- }
-
- /* Get ap status */
- if ((rv = setup_for_devctl_cmd(ap_id, &devctl_hdl, DC_RDONLY)) !=
- CFGA_SDCARD_OK) {
- goto bailout;
- }
-
- /* will call dc_cmd to send IOCTL to kernel */
- if (devctl_ap_getstate(devctl_hdl, NULL, &devctl_ap_state) == -1) {
- cleanup_after_devctl_cmd(devctl_hdl);
- rv = CFGA_SDCARD_IOCTL;
- goto bailout;
- }
-
- cleanup_after_devctl_cmd(devctl_hdl);
-
- /*
- * Create cfga_list_data_t struct.
- */
- if ((*ap_id_list =
- (cfga_list_data_t *)malloc(sizeof (**ap_id_list))) == NULL) {
- rv = CFGA_SDCARD_ALLOC_FAIL;
- goto bailout;
- }
- *nlistp = 1;
-
- /*
- * Rest of the code fills in the cfga_list_data_t struct.
- */
-
- /* Get /dev/cfg path to corresponding to the physical ap_id */
- /* Remember ap_id_log must be freed */
- rv = physpath_to_devlink(CFGA_DEV_DIR, (char *)ap_id,
- &ap_id_log, &l_errno);
-
- if (rv != 0) {
- rv = CFGA_SDCARD_DEVLINK;
- goto bailout;
- }
-
- /* Get logical ap_id corresponding to the physical */
- if (ap_id_log == NULL || strstr(ap_id_log, CFGA_DEV_DIR) == NULL) {
- rv = CFGA_SDCARD_DEVLINK;
- goto bailout;
- }
-
- (void) strlcpy((*ap_id_list)->ap_log_id,
- /* Strip off /dev/cfg/ */ ap_id_log + strlen(CFGA_DEV_DIR)+ 1,
- sizeof ((*ap_id_list)->ap_log_id));
-
- free(ap_id_log);
- ap_id_log = NULL;
-
- (void) strlcpy((*ap_id_list)->ap_phys_id, ap_id,
- sizeof ((*ap_id_list)->ap_phys_id));
-
- switch (devctl_ap_state.ap_rstate) {
- case AP_RSTATE_EMPTY:
- (*ap_id_list)->ap_r_state = CFGA_STAT_EMPTY;
- break;
-
- case AP_RSTATE_DISCONNECTED:
- (*ap_id_list)->ap_r_state = CFGA_STAT_DISCONNECTED;
- break;
-
- case AP_RSTATE_CONNECTED:
- (*ap_id_list)->ap_r_state = CFGA_STAT_CONNECTED;
- break;
-
- default:
- rv = CFGA_SDCARD_STATE;
- goto bailout;
- }
-
- switch (devctl_ap_state.ap_ostate) {
- case AP_OSTATE_CONFIGURED:
- (*ap_id_list)->ap_o_state = CFGA_STAT_CONFIGURED;
- break;
-
- case AP_OSTATE_UNCONFIGURED:
- (*ap_id_list)->ap_o_state = CFGA_STAT_UNCONFIGURED;
- break;
-
- default:
- rv = CFGA_SDCARD_STATE;
- goto bailout;
- }
-
- switch (devctl_ap_state.ap_condition) {
- case AP_COND_OK:
- (*ap_id_list)->ap_cond = CFGA_COND_OK;
- break;
-
- case AP_COND_FAILING:
- (*ap_id_list)->ap_cond = CFGA_COND_FAILING;
- break;
-
- case AP_COND_FAILED:
- (*ap_id_list)->ap_cond = CFGA_COND_FAILED;
- break;
-
- case AP_COND_UNUSABLE:
- (*ap_id_list)->ap_cond = CFGA_COND_UNUSABLE;
- break;
-
- case AP_COND_UNKNOWN:
- (*ap_id_list)->ap_cond = CFGA_COND_UNKNOWN;
- break;
-
- default:
- rv = CFGA_SDCARD_STATE;
- goto bailout;
- }
-
- (*ap_id_list)->ap_class[0] = '\0'; /* Filled by libcfgadm */
- (*ap_id_list)->ap_busy = devctl_ap_state.ap_in_transition;
- (*ap_id_list)->ap_status_time = devctl_ap_state.ap_last_change;
- (*ap_id_list)->ap_info[0] = NULL;
-
- if ((*ap_id_list)->ap_r_state == CFGA_STAT_CONNECTED) {
- sda_card_info_t ci;
- char *ct;
-
- /*
- * Fill in the 'Information' field for the -v option
- */
- rv = do_control_ioctl(ap_id, SDA_CFGA_GET_CARD_INFO,
- &ci, sizeof (ci));
- if (rv != CFGA_SDCARD_OK) {
- goto bailout;
- }
-
- switch (ci.ci_type) {
- case SDA_CT_MMC:
- case SDA_CT_SDMEM:
- case SDA_CT_SDHC:
- case SDA_CT_SDCOMBO:
- /* these are all memory cards */
- sdcard_clean_string(ci.ci_pid, sizeof (ci.ci_pid));
-
- /*
- * We don't display the mfg id, because we
- * have no reliable way to look it up.
- */
- (void) snprintf((*ap_id_list)->ap_info,
- sizeof ((*ap_id_list)->ap_info),
- "Mod: %s Rev: %d.%d Date: %d/%d SN: %X",
- ci.ci_pid[0] ? ci.ci_pid : "?",
- ci.ci_major, ci.ci_minor,
- ci.ci_month, (int)ci.ci_year + 1900,
- ci.ci_serial);
- break;
- default:
- /*
- * we don't know what this is really... need to
- * parse CIS later.
- */
- (void) strlcpy((*ap_id_list)->ap_info, "",
- sizeof ((*ap_id_list)->ap_info));
- break;
- }
-
- switch (ci.ci_type) {
- case SDA_CT_UNKNOWN:
- ct = "unknown";
- break;
- case SDA_CT_MMC:
- ct = "mmc";
- break;
- case SDA_CT_SDMEM:
- ct = "sdcard";
- break;
- case SDA_CT_SDHC:
- ct = "sdhc";
- break;
- case SDA_CT_SDCOMBO:
- ct = "sd-combo";
- break;
- case SDA_CT_SDIO:
- ct = "sdio";
- break;
- }
-
- (void) strlcpy((*ap_id_list)->ap_type, ct,
- sizeof ((*ap_id_list)->ap_type));
-
- if ((*ap_id_list)->ap_o_state == CFGA_STAT_CONFIGURED) {
-
- char *dyncomp = NULL;
-
- /*
- * This is the case where we need to generate
- * a dynamic component of the ap_id, i.e. device.
- */
- (void) sdcard_make_dyncomp(ap_id, &dyncomp);
- if (dyncomp != NULL) {
- (void) strcat((*ap_id_list)->ap_log_id,
- DYN_SEP);
- (void) strlcat((*ap_id_list)->ap_log_id,
- dyncomp,
- sizeof ((*ap_id_list)->ap_log_id));
- free(dyncomp);
- }
- }
-
- } else {
- (void) strlcpy((*ap_id_list)->ap_type, "sdcard-slot",
- sizeof ((*ap_id_list)->ap_type));
- }
-
- return (sdcard_err_msg(errstring, rv, ap_id, errno));
-
-bailout:
- if (*ap_id_list != NULL) {
- free(*ap_id_list);
- }
- if (ap_id_log != NULL) {
- free(ap_id_log);
- }
-
- return (sdcard_err_msg(errstring, rv, ap_id, errno));
-}
-
-/*
- * This routine accepts a string and prints it using
- * the message print routine argument.
- */
-static void
-cfga_msg(struct cfga_msg *msgp, const char *str)
-{
- int len;
- char *q;
-
- if (msgp == NULL || msgp->message_routine == NULL) {
- (void) printf("cfga_msg: NULL msgp\n");
- return;
- }
-
- if ((len = strlen(str)) == 0) {
- (void) printf("cfga_msg: null str\n");
- return;
- }
-
- if ((q = (char *)calloc(len + 1, 1)) == NULL) {
- perror("cfga_msg");
- return;
- }
-
- (void) strcpy(q, str);
- (*msgp->message_routine)(msgp->appdata_ptr, q);
-
- free(q);
-}
-
-/* cfgadm entry point */
-/*ARGSUSED*/
-cfga_err_t
-cfga_help(struct cfga_msg *msgp, const char *options, cfga_flags_t flags)
-{
- if (options != NULL) {
- cfga_msg(msgp,
- dgettext(TEXT_DOMAIN, sdcard_help[HELP_UNKNOWN]));
- cfga_msg(msgp, options);
- }
- cfga_msg(msgp, dgettext(TEXT_DOMAIN, sdcard_help[HELP_HEADER]));
- cfga_msg(msgp, sdcard_help[HELP_CONFIG]);
- cfga_msg(msgp, sdcard_help[HELP_RESET_SLOT]);
-
- return (CFGA_OK);
-}
-
-
-/*
- * Ensure the ap_id passed is in the correct (physical ap_id) form:
- * path/device:xx
- * where xx is a one or two-digit number.
- *
- * Note the library always calls the plugin with a physical ap_id.
- */
-static int
-verify_valid_apid(const char *ap_id)
-{
- char *l_ap_id;
-
- if (ap_id == NULL)
- return (-1);
-
- l_ap_id = strrchr(ap_id, MINOR_SEP);
- l_ap_id++;
-
- if (strspn(l_ap_id, "0123456789") != strlen(l_ap_id)) {
- /* Bad characters in the ap_id */
- return (-1);
- }
-
- return (0);
-}
-
-
-
-/*
- * Verify the params passed in are valid.
- */
-static cfga_sdcard_ret_t
-verify_params(const char *ap_id, const char *options, char **errstring)
-{
- char *pdyn, *lap_id;
- int rv;
-
- if (errstring != NULL) {
- *errstring = NULL;
- }
-
- if (options != NULL) {
- return (CFGA_SDCARD_OPTIONS);
- }
-
- /* Strip dynamic AP name component if it is present. */
- lap_id = strdup(ap_id);
- if (lap_id == NULL) {
- return (CFGA_SDCARD_ALLOC_FAIL);
- }
- if ((pdyn = GET_DYN(lap_id)) != NULL) {
- *pdyn = '\0';
- }
-
- if (verify_valid_apid(lap_id) != 0) {
- rv = CFGA_SDCARD_AP;
- } else {
- rv = CFGA_SDCARD_OK;
- }
- free(lap_id);
-
- return (rv);
-}
-
-/*
- * Pair of routines to set up for/clean up after a devctl_ap_* lib call.
- */
-static void
-cleanup_after_devctl_cmd(devctl_hdl_t devctl_hdl)
-{
- if (devctl_hdl != NULL) {
- devctl_release(devctl_hdl);
- }
-}
-
-static cfga_sdcard_ret_t
-setup_for_devctl_cmd(const char *ap_id, devctl_hdl_t *devctl_hdl, uint_t oflag)
-{
- char *lap_id, *pdyn;
-
- lap_id = strdup(ap_id);
- if (lap_id == NULL)
- return (CFGA_SDCARD_ALLOC_FAIL);
- if ((pdyn = GET_DYN(lap_id)) != NULL) {
- *pdyn = '\0';
- }
-
- /* Get a devctl handle to pass to the devctl_ap_XXX functions */
- if ((*devctl_hdl = devctl_ap_acquire(lap_id, oflag)) == NULL) {
- (void) fprintf(stderr, "[libcfgadm:sdcard] "
- "setup_for_devctl_cmd: devctl_ap_acquire failed: %s\n",
- strerror(errno));
- free(lap_id);
- return (CFGA_SDCARD_DEVCTL);
- }
-
- free(lap_id);
- return (CFGA_SDCARD_OK);
-}
-
-
-static cfga_sdcard_ret_t
-slot_state(devctl_hdl_t hdl, ap_rstate_t *rstate, ap_ostate_t *ostate)
-{
- devctl_ap_state_t devctl_ap_state;
-
- if (devctl_ap_getstate(hdl, NULL, &devctl_ap_state) == -1) {
- (void) printf("devctl_ap_getstate failed, errno: %d\n", errno);
- return (CFGA_SDCARD_IOCTL);
- }
- *rstate = devctl_ap_state.ap_rstate;
- *ostate = devctl_ap_state.ap_ostate;
- return (CFGA_SDCARD_OK);
-}
-
-/*
- * Given a subcommand to the DEVCTL_AP_CONTROL ioctl, rquest the size of
- * the data to be returned, allocate a buffer, then get the data.
- */
-cfga_sdcard_ret_t
-do_control_ioctl(const char *ap_id, int subcommand, void *data, size_t size)
-{
- int fd = -1;
- cfga_sdcard_ret_t rv = CFGA_SDCARD_OK;
- struct sda_ap_control apc;
-
- if ((fd = open(ap_id, O_RDONLY)) == -1) {
- (void) printf("do_control_ioctl: open: errno:%d\n", errno);
- rv = CFGA_SDCARD_OPEN;
- goto bailout;
- }
-
- apc.cmd = subcommand;
- apc.data = data;
- apc.size = size;
-
- /* Execute IOCTL */
- if (ioctl(fd, DEVCTL_AP_CONTROL, &apc) != 0) {
- rv = CFGA_SDCARD_IOCTL;
- goto bailout;
- }
-
- (void) close(fd);
-
- return (rv);
-
-bailout:
- if (fd != -1) {
- (void) close(fd);
- }
-
- if ((rv != CFGA_SDCARD_OK) && (errno == EBUSY)) {
- rv = CFGA_SDCARD_BUSY;
- }
-
- return (rv);
-}
-
-
-static int
-sdcard_confirm(struct cfga_confirm *confp, char *msg)
-{
- int rval;
-
- if (confp == NULL || confp->confirm == NULL) {
- return (0);
- }
- rval = (*confp->confirm)(confp->appdata_ptr, msg);
-
- return (rval);
-}
-
-
-cfga_sdcard_ret_t
-sdcard_get_devicepath(const char *ap_id, char *devpath)
-{
- return (do_control_ioctl(ap_id, SDA_CFGA_GET_DEVICE_PATH,
- devpath, MAXPATHLEN));
-}
-
-cfga_sdcard_ret_t
-sdcard_reset_slot(const char *ap_id)
-{
- return (do_control_ioctl(ap_id, SDA_CFGA_RESET_SLOT, NULL, 0));
-}
-
-static rcm_handle_t *rcm_handle = NULL;
-static mutex_t rcm_handle_lock = DEFAULTMUTEX;
-
-/*
- * sdcard_rcm_offline:
- * Offline resource consumers.
- */
-cfga_sdcard_ret_t
-sdcard_rcm_offline(char *devpath, char **errstring, cfga_flags_t flags)
-{
- int rret;
- uint_t rflags;
- rcm_info_t *rinfo = NULL;
- cfga_sdcard_ret_t ret;
-
- if ((ret = sdcard_rcm_init()) != CFGA_SDCARD_OK) {
- return (ret);
- }
-
- /* Translate the cfgadm flags to RCM flags */
- rflags = (flags & CFGA_FLAG_FORCE) ? RCM_FORCE : 0;
-
- rret = rcm_request_offline(rcm_handle, devpath, rflags, &rinfo);
- if (rret != RCM_SUCCESS) {
- if (rinfo) {
- sdcard_rcm_info_table(rinfo, errstring);
- rcm_free_info(rinfo);
- rinfo = NULL;
- }
-
- if (rret == RCM_FAILURE) {
- sdcard_rcm_online(devpath, errstring);
- }
- ret = CFGA_SDCARD_RCM_OFFLINE;
- }
- return (ret);
-}
-
-
-/*
- * sdcard_rcm_online:
- * Online resource consumers that were previously offlined.
- */
-void
-sdcard_rcm_online(char *devpath, char **errstring)
-{
- rcm_info_t *rinfo = NULL;
-
- if (sdcard_rcm_init() != CFGA_SDCARD_OK) {
- return;
- }
-
- if (rcm_notify_online(rcm_handle, devpath, 0, &rinfo) !=
- RCM_SUCCESS && (rinfo != NULL)) {
- sdcard_rcm_info_table(rinfo, errstring);
- rcm_free_info(rinfo);
- rinfo = NULL;
- }
-}
-
-/*
- * sdcard_rcm_remove:
- * Remove resource consumers after their kernel removal.
- */
-void
-sdcard_rcm_remove(char *devpath, char **errstring)
-{
- rcm_info_t *rinfo = NULL;
-
- if (sdcard_rcm_init() != CFGA_SDCARD_OK) {
- return;
- }
-
- if (rcm_notify_remove(rcm_handle, devpath, 0, &rinfo) !=
- RCM_SUCCESS && (rinfo != NULL)) {
-
- sdcard_rcm_info_table(rinfo, errstring);
- rcm_free_info(rinfo);
- rinfo = NULL;
- }
-}
-
-
-/*
- * sdcard_rcm_init:
- * Contains common initialization code for entering a sdcard_rcm_xx() routine.
- */
-static cfga_sdcard_ret_t
-sdcard_rcm_init(void)
-{
- /* Get a handle for the RCM operations */
- (void) mutex_lock(&rcm_handle_lock);
- if (rcm_handle == NULL) {
- if (rcm_alloc_handle(NULL, RCM_NOPID, NULL, &rcm_handle) !=
- RCM_SUCCESS) {
- (void) mutex_unlock(&rcm_handle_lock);
-
- return (CFGA_SDCARD_RCM_HANDLE);
- }
- }
- (void) mutex_unlock(&rcm_handle_lock);
-
- return (CFGA_SDCARD_OK);
-}
-
-
-#define MAX_FORMAT 80 /* for info table */
-
-/*
- * sdcard_rcm_info_table:
- * Takes an opaque rcm_info_t pointer and a character pointer,
- * and appends the rcm_info_t data in the form of a table to the
- * given character pointer.
- */
-static void
-sdcard_rcm_info_table(rcm_info_t *rinfo, char **table)
-{
- int i;
- size_t w;
- size_t width = 0;
- size_t w_rsrc = 0;
- size_t w_info = 0;
- size_t table_size = 0;
- uint_t tuples = 0;
- rcm_info_tuple_t *tuple = NULL;
- char *rsrc;
- char *info;
- char *newtable;
- static char format[MAX_FORMAT];
- const char *infostr;
-
- /* Protect against invalid arguments */
- if (rinfo == NULL || table == NULL) {
- return;
- }
-
- /* Set localized table header strings */
- rsrc = dgettext(TEXT_DOMAIN, "Resource");
- info = dgettext(TEXT_DOMAIN, "Information");
-
-
- /* A first pass, to size up the RCM information */
- while (tuple = rcm_info_next(rinfo, tuple)) {
- if ((infostr = rcm_info_info(tuple)) != NULL) {
- tuples++;
- if ((w = strlen(rcm_info_rsrc(tuple))) > w_rsrc)
- w_rsrc = w;
- if ((w = strlen(infostr)) > w_info)
- w_info = w;
- }
- }
-
- /* If nothing was sized up above, stop early */
- if (tuples == 0) {
- return;
- }
-
- /* Adjust column widths for column headings */
- if ((w = strlen(rsrc)) > w_rsrc) {
- w_rsrc = w;
- } else if ((w_rsrc - w) % 2) {
- w_rsrc++;
- }
-
- if ((w = strlen(info)) > w_info) {
- w_info = w;
- } else if ((w_info - w) % 2) {
- w_info++;
- }
-
-
- /*
- * Compute the total line width of each line,
- * accounting for intercolumn spacing.
- */
- width = w_info + w_rsrc + 4;
-
- /* Allocate space for the table */
- table_size = (2 + tuples) * (width + 1) + 2;
- if (*table == NULL) {
- /* zero fill for the strcat() call below */
- *table = calloc(table_size, sizeof (char));
- if (*table == NULL) {
- return;
- }
- } else {
- newtable = realloc(*table, strlen(*table) + table_size);
- if (newtable == NULL) {
- return;
- } else {
- *table = newtable;
- }
- }
-
- /* Place a table header into the string */
-
-
- /* The resource header */
- (void) strcat(*table, "\n");
- w = strlen(rsrc);
-
- for (i = 0; i < ((w_rsrc - w) / 2); i++) {
- (void) strcat(*table, " ");
- }
- (void) strcat(*table, rsrc);
-
- for (i = 0; i < ((w_rsrc - w) / 2); i++) {
- (void) strcat(*table, " ");
- }
-
- /* The information header */
- (void) strcat(*table, " ");
- w = strlen(info);
- for (i = 0; i < ((w_info - w) / 2); i++) {
- (void) strcat(*table, " ");
- }
- (void) strcat(*table, info);
-
- for (i = 0; i < ((w_info - w) / 2); i++) {
- (void) strcat(*table, " ");
- }
-
- (void) strcat(*table, "\n");
-
- /* Underline the headers */
- for (i = 0; i < w_rsrc; i++) {
- (void) strcat(*table, "-");
- }
-
- (void) strcat(*table, " ");
- for (i = 0; i < w_info; i++) {
- (void) strcat(*table, "-");
- }
-
-
- (void) strcat(*table, "\n");
-
- /* Construct the format string */
- (void) snprintf(format, MAX_FORMAT, "%%-%ds %%-%ds",
- (int)w_rsrc, (int)w_info);
-
- /* Add the tuples to the table string */
- tuple = NULL;
- while ((tuple = rcm_info_next(rinfo, tuple)) != NULL) {
- if ((infostr = rcm_info_info(tuple)) != NULL) {
- (void) sprintf(&((*table)[strlen(*table)]),
- format, rcm_info_rsrc(tuple), infostr);
- (void) strcat(*table, "\n");
- }
- }
-}
--- a/usr/src/lib/cfgadm_plugins/sdcard/common/cfga_sdcard.h Tue May 18 11:19:39 2010 +0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,138 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _CFGA_SDCARD_H
-#define _CFGA_SDCARD_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdlib.h>
-#include <strings.h>
-#include <fcntl.h>
-#include <ctype.h>
-#include <unistd.h>
-#include <libintl.h>
-#include <libdevice.h>
-#include <sys/varargs.h>
-
-#include <libdevinfo.h>
-#include <libdevice.h>
-#include <librcm.h>
-#include <synch.h>
-#include <thread.h>
-#include <assert.h>
-#include <sys/sdcard/sda_ioctl.h>
-
-#define CFGA_PLUGIN_LIB
-#include <config_admin.h>
-
-/* Misc text strings */
-#define CFGA_DEV_DIR "/dev/cfg"
-#define DYN_SEP "::"
-#define CFGA_DEVCTL_NODE ":devctl"
-#define MINOR_SEP ':'
-#define PATH_SEP '/'
-
-#define RESET_SLOT "sdcard_reset_slot"
-
-/* for confirm operation */
-#define SDCARD_CONFIRM_1 \
- "This operation will suspend activity on the SD card device\nContinue"
-#define SDCARD_CONFIRM_2 \
- "This operation will disrupt activity on the SD card device\nContinue"
-
-#define GET_DYN(a) (((a) != NULL) ? \
- strstr((a), DYN_SEP) : (void *)0)
-
-
-/* Messages */
-
-typedef struct msgcvt {
- int intl; /* Flag: if 1, internationalize */
- cfga_err_t cfga_err; /* Error code libcfgadm understands */
- const char *msgstr;
-} msgcvt_t;
-
-#define NO_CVT 0
-#define CVT 1
-
-#define MSG_TBL_SZ(table) (sizeof ((table)) / sizeof (msgcvt_t))
-
-/* Messages */
-
-
-/* Error message ids (and indices into sdcard_error_msgs) */
-typedef enum {
- CFGA_SDCARD_OK = 0,
- CFGA_SDCARD_NACK,
- CFGA_SDCARD_UNKNOWN,
- CFGA_SDCARD_PRIV,
- CFGA_SDCARD_DYNAMIC_AP,
- CFGA_SDCARD_INTERNAL_ERROR,
- CFGA_SDCARD_ALLOC_FAIL,
- CFGA_SDCARD_IOCTL,
- CFGA_SDCARD_DEVCTL,
- CFGA_SDCARD_AP,
- CFGA_SDCARD_BUSY,
- CFGA_SDCARD_DEVLINK,
- CFGA_SDCARD_INVALID_DEVNAME,
- CFGA_SDCARD_DATA_ERROR,
- CFGA_SDCARD_DEV_CONFIGURE,
- CFGA_SDCARD_DEV_UNCONFIGURE,
- CFGA_SDCARD_NOT_CONNECTED,
- CFGA_SDCARD_DISCONNECTED,
- CFGA_SDCARD_NOT_CONFIGURED,
- CFGA_SDCARD_ALREADY_CONNECTED,
- CFGA_SDCARD_ALREADY_CONFIGURED,
- CFGA_SDCARD_DEVICE_UNCONFIGURED,
- CFGA_SDCARD_OPNOTSUPP,
- CFGA_SDCARD_HWOPNOTSUPP,
- CFGA_SDCARD_OPTIONS,
- CFGA_SDCARD_STATE,
- CFGA_SDCARD_OPEN,
- CFGA_SDCARD_RCM_HANDLE,
- CFGA_SDCARD_RCM_OFFLINE,
- CFGA_SDCARD_RCM_REMOVE,
- CFGA_SDCARD_RCM_ONLINE,
- CFGA_SDCARD_CONFIRM_RESET,
- CFGA_SDCARD_CONFIRM_UNCONFIGURE,
- CFGA_SDCARD_CONFIRM_DISCONNECT
-} cfga_sdcard_ret_t;
-
-/*
- * Given an error msg index, look up the associated string, and
- * convert it to the current locale if required.
- */
-#define ERR_STR(msg_idx) \
- (get_msg((msg_idx), sdcard_msgs, MSG_TBL_SZ(sdcard_msgs)))
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _CFGA_SDCARD_H */
--- a/usr/src/lib/cfgadm_plugins/sdcard/common/mapfile-vers Tue May 18 11:19:39 2010 +0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-#
-# MAPFILE HEADER START
-#
-# WARNING: STOP NOW. DO NOT MODIFY THIS FILE.
-# Object versioning must comply with the rules detailed in
-#
-# usr/src/lib/README.mapfiles
-#
-# You should not be making modifications here until you've read the most current
-# copy of that file. If you need help, contact a gatekeeper for guidance.
-#
-# MAPFILE HEADER END
-#
-
-SUNWprivate_1.1 {
- global:
- cfga_change_state;
- cfga_help;
- cfga_list_ext;
- cfga_private_func;
- cfga_test;
- cfga_version;
- local:
- *;
-};
--- a/usr/src/lib/cfgadm_plugins/sdcard/i386/Makefile Tue May 18 11:19:39 2010 +0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-include ../Makefile.com
-CFLAGS += -D_POSIX_PTHREAD_SEMANTICS
-LINTFLAGS += -D_POSIX_PTHREAD_SEMANTICS
-
-.KEEP_STATE:
-
-install: all $(ROOTLIBS) $(ROOTLINKS)
--- a/usr/src/lib/cfgadm_plugins/sdcard/sdcard.xcl Tue May 18 11:19:39 2010 +0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-
-#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-# lib/cfgadm_plugins/sdcard/sdcard.xcl
-#
-msgid "/devices/"
-msgid "/devices"
-msgid "/"
-msgid "."
-msgid "C"
-msgid "\n"
-msgid "-"
-msgid "ap_id: "
-msgid " %s%s\n%s"
-msgid "%s/%s"
-msgid "%s\n"
-msgid "../"
-msgid ""
-msgid "cfga_change_state: get device path failed\n"
-msgid "cfga_change_state: get path failed\n"
-msgid "devctl_ap_unconfigure failed\n"
-#msgid "No valid option specified\n"
-msgid "cfga_list_ext: cannot locate target device\n"
-msgid "dsk/"
-msgid "/dev/dsk"
-msgid "/dsk/"
-msgid "/rdsk/"
-msgid "/dev/"
-msgid "/disk@0,0"
-msgid "/sdcard@"
-msgid "Mod: %s Rev: %d.%d Date: %d/%d SN: %X"
-msgid "::"
-msgid "cfga_msg"
-msgid "cfga_msg: NULL msgp\n"
-msgid "cfga_msg: null str\n"
-msgid "0123456789"
-msgid ".."
-msgid "[libcfgadm:sdcard] "
- "setup_for_devctl_cmd: devctl_ap_acquire failed: %s\n"
-msgid "devctl_ap_getstate failed, errno: %d\n"
-msgid "do_control_ioctl: open: errno:%d\n"
-msgid "ioctl failed (size)"
-msgid " "
-msgid " "
-msgid "%%-%ds %%-%ds"
-msgid " cfgadm -c [configure|unconfigure|disconnect|connect] ap_id "
- "[ap_id...]\n"
-msgid " cfgadm -x sdcard_reset_slot ap_id [ap_id...]\n"
--- a/usr/src/lib/cfgadm_plugins/sdcard/sparc/Makefile Tue May 18 11:19:39 2010 +0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-include ../Makefile.com
-CFLAGS += -D_POSIX_PTHREAD_SEMANTICS
-LINTFLAGS += -D_POSIX_PTHREAD_SEMANTICS
-
-.KEEP_STATE:
-
-install: all $(ROOTLIBS) $(ROOTLINKS)
--- a/usr/src/lib/cfgadm_plugins/sdcard/sparcv9/Makefile Tue May 18 11:19:39 2010 +0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-include ../Makefile.com
-include ../../../Makefile.lib.64
-CFLAGS += -D_POSIX_PTHREAD_SEMANTICS
-LINTFLAGS += -D_POSIX_PTHREAD_SEMANTICS
-
-.KEEP_STATE:
-
-install: all $(ROOTLIBS64) $(ROOTLINKS64)
--- a/usr/src/lib/libsmedia/library/common/l_defines.h Tue May 18 11:19:39 2010 +0800
+++ b/usr/src/lib/libsmedia/library/common/l_defines.h Mon May 17 21:17:01 2010 -0700
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,15 +19,12 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1999-2001 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#ifndef _L_DEFINES_H_
#define _L_DEFINES_H_
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -76,6 +72,7 @@
#define SM_PCMEM_VERSION_1 1
#define SM_PLUGIN_VERSION 1
#define SM_PCATA_VERSION_1 1
+#define SM_BLKDEV_VERSION_1 1
#ifdef __cplusplus
}
--- a/usr/src/lib/libsmedia/library/inc/smedia.h Tue May 18 11:19:39 2010 +0800
+++ b/usr/src/lib/libsmedia/library/inc/smedia.h Mon May 17 21:17:01 2010 -0700
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#ifndef _SMEDIA_H_
@@ -62,6 +61,7 @@
#define IF_SCSI 0x0
#define IF_FLOPPY 0x1
#define IF_PCMCIA 0x2
+#define IF_BLOCK 0x3
typedef struct smmedium_property {
@@ -86,6 +86,7 @@
#define SM_SCSI_FLOPPY 0x10005 /* SCSI floppy device */
#define SM_PCMCIA_MEM 0x20006 /* PCMCIA memory card (Obsolete) */
#define SM_PCMCIA_ATA 0x20007 /* PCMCIA ata card */
+#define SM_BLOCK 0x20008 /* Generic block device */
#define SM_NOT_PRESENT 0xFFFF
--- a/usr/src/lib/libsmedia/plugins/Makefile Tue May 18 11:19:39 2010 +0800
+++ b/usr/src/lib/libsmedia/plugins/Makefile Mon May 17 21:17:01 2010 -0700
@@ -19,13 +19,13 @@
# CDDL HEADER END
#
#
-# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
#
# lib/libsmedia/plugins/Makefile
SUBDIRS = \
+ blkdev \
scsi \
floppy \
pcata
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libsmedia/plugins/blkdev/Makefile Mon May 17 21:17:01 2010 -0700
@@ -0,0 +1,29 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+#
+#
+# lib/libsmedia/plugins/bd/Makefile
+
+include ../../../Makefile.lib
+include Makefile.targ
+include ../Makefile.plugin
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libsmedia/plugins/blkdev/Makefile.targ Mon May 17 21:17:01 2010 -0700
@@ -0,0 +1,31 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+#
+# lib/libsmedia/plugins/bd/Makefile.targ
+
+LIBRARY= sm_blkdev.a
+VERS= .1
+
+OBJECTS= b_generic.o
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libsmedia/plugins/blkdev/amd64/Makefile Mon May 17 21:17:01 2010 -0700
@@ -0,0 +1,35 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+#
+
+include ../Makefile.targ
+include ../../../../Makefile.lib
+include ../../../../Makefile.targ
+include ../../Makefile.com
+include ../../../../Makefile.lib.64
+
+.KEEP_STATE:
+
+all: $(LIBS) $(TXTS)
+
+install: all $(PLUGINDIR64) .WAIT $(PLUGINS64)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libsmedia/plugins/blkdev/common/b_generic.c Mon May 17 21:17:01 2010 -0700
@@ -0,0 +1,206 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
+/*
+ * b_generic.c :
+ * This file contains the functions for generic block devices
+ * for libsmedia.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <locale.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/dkio.h>
+#include <string.h>
+#include "../../../library/inc/smedia.h"
+#include "../../../library/inc/rmedia.h"
+#include "../../../library/common/l_defines.h"
+
+#define PERROR(string) my_perror(gettext(string))
+
+static void
+my_perror(char *err_string)
+{
+
+ int error_no;
+ if (errno == 0)
+ return;
+
+ error_no = errno;
+ (void) fprintf(stderr, gettext(err_string));
+ (void) fprintf(stderr, gettext(" : "));
+ errno = error_no;
+ perror("");
+}
+
+int32_t
+_m_version_no(void)
+{
+ return (SM_BLKDEV_VERSION_1);
+}
+
+int32_t
+_m_device_type(ushort_t ctype, ushort_t mtype)
+{
+ if (ctype == DKC_BLKDEV) {
+ if (mtype == 0)
+ return (0);
+ }
+ return (-1);
+}
+
+
+int32_t
+_m_get_media_info(rmedia_handle_t *handle, void *ip)
+{
+ smmedium_prop_t *mp = (smmedium_prop_t *)ip;
+ struct dk_geom dkg;
+ struct dk_minfo minfo;
+ enum dkio_state state = DKIO_NONE;
+ int ret_val;
+
+ if (handle == NULL) {
+ DPRINTF("Null Handle\n");
+ errno = EINVAL;
+ return (-1);
+ }
+ if (handle->sm_signature != (int32_t)LIBSMEDIA_SIGNATURE) {
+ DPRINTF2("Signature expected=0x%x, found=0x%x\n",
+ LIBSMEDIA_SIGNATURE, handle->sm_signature);
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (ioctl(handle->sm_fd, DKIOCSTATE, &state) < 0) {
+ PERROR("DKIOCSTATE failed");
+ return (-1);
+ }
+
+ if (state != DKIO_INSERTED) {
+ DPRINTF("No media.\n");
+ mp->sm_media_type = SM_NOT_PRESENT;
+ mp->sm_version = SMMEDIA_PROP_V_1;
+ return (0);
+
+ }
+
+ ret_val = ioctl(handle->sm_fd, DKIOCGMEDIAINFO, &minfo);
+ if (ret_val < 0) {
+ DPRINTF("DKIOCGMEDIAINFO ioctl failed");
+ return (ret_val);
+ }
+ ret_val = ioctl(handle->sm_fd, DKIOCGGEOM, &dkg);
+ if (ret_val < 0) {
+ DPRINTF("DKIOCGGEOM ioctl failed");
+ return (ret_val);
+ }
+
+ mp->sm_media_type = SM_BLOCK;
+ mp->sm_blocksize = minfo.dki_lbsize;
+ mp->sm_capacity = minfo.dki_capacity;
+ mp->sm_pcyl = dkg.dkg_pcyl;
+ mp->sm_nhead = dkg.dkg_nhead;
+ mp->sm_nsect = dkg.dkg_nsect;
+ return (0);
+}
+
+
+
+/* ARGSUSED0 */
+
+int32_t
+_m_get_device_info(rmedia_handle_t *handle, void *ip)
+{
+ smdevice_info_t *mp = (smdevice_info_t *)ip;
+ char *vendor_name, *product_name, *fw_version;
+
+ if (handle == NULL) {
+ DPRINTF("Null Handle\n");
+ errno = EINVAL;
+ return (-1);
+ }
+ if (handle->sm_signature != (int32_t)LIBSMEDIA_SIGNATURE) {
+ DPRINTF2("Signature expected=0x%x, found=0x%x\n",
+ LIBSMEDIA_SIGNATURE, handle->sm_signature);
+ errno = EINVAL;
+ return (-1);
+ }
+ vendor_name = (char *)malloc(1);
+ if (vendor_name == NULL) {
+ if (!errno)
+ errno = ENOMEM;
+ return (-1);
+ }
+ product_name = (char *)malloc(1);
+ if (product_name == NULL) {
+ free(vendor_name);
+ if (!errno)
+ errno = ENOMEM;
+ return (-1);
+ }
+
+ fw_version = (char *)malloc(1);
+ if (fw_version == NULL) {
+ free(vendor_name);
+ free(product_name);
+ if (!errno)
+ errno = ENOMEM;
+ return (-1);
+ }
+
+ /* Note: we could potentially offer more here */
+ vendor_name[0] = 0;
+ product_name[0] = 0;
+ fw_version[0] = 0;
+ mp->sm_interface_type = IF_BLOCK;
+ mp->sm_vendor_name = vendor_name;
+ mp->sm_product_name = product_name;
+ mp->sm_firmware_version = fw_version;
+ return (0);
+}
+
+int32_t
+_m_free_device_info(rmedia_handle_t *handle, void *ip)
+{
+ struct smdevice_info *dev_info = ip;
+
+ /* Check for valid handle */
+ if (handle == NULL) {
+ DPRINTF("Null Handle\n");
+ errno = EINVAL;
+ return (-1);
+ }
+ if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
+ DPRINTF("Invalid signature in handle.\n");
+ errno = EINVAL;
+ return (-1);
+ }
+
+ free(dev_info->sm_vendor_name);
+ free(dev_info->sm_product_name);
+ free(dev_info->sm_firmware_version);
+ return (0);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libsmedia/plugins/blkdev/common/mapfile-vers Mon May 17 21:17:01 2010 -0700
@@ -0,0 +1,48 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+#
+
+#
+# MAPFILE HEADER START
+#
+# WARNING: STOP NOW. DO NOT MODIFY THIS FILE.
+# Object versioning must comply with the rules detailed in
+#
+# usr/src/lib/README.mapfiles
+#
+# You should not be making modifications here until you've read the most current
+# copy of that file. If you need help, contact a gatekeeper for guidance.
+#
+# MAPFILE HEADER END
+#
+
+SUNWprivate_1.1 {
+ global:
+ _m_device_type;
+ _m_free_device_info;
+ _m_get_device_info;
+ _m_get_media_info;
+ _m_version_no;
+ local:
+ *;
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libsmedia/plugins/blkdev/i386/Makefile Mon May 17 21:17:01 2010 -0700
@@ -0,0 +1,35 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+#
+
+include ../Makefile.targ
+include ../../../../Makefile.lib
+include ../../../../Makefile.targ
+include ../../Makefile.com
+
+.KEEP_STATE:
+
+all: $(LIBS) $(TXTS)
+
+
+install: all $(PLUGINDIR) .WAIT $(PLUGINS)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libsmedia/plugins/blkdev/sparc/Makefile Mon May 17 21:17:01 2010 -0700
@@ -0,0 +1,34 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+#
+
+include ../Makefile.targ
+include ../../../../Makefile.lib
+include ../../../../Makefile.targ
+include ../../Makefile.com
+
+.KEEP_STATE:
+
+all: $(LIBS) $(TXTS)
+
+install: all $(PLUGINDIR) .WAIT $(PLUGINS)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libsmedia/plugins/blkdev/sparcv9/Makefile Mon May 17 21:17:01 2010 -0700
@@ -0,0 +1,35 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+#
+
+include ../Makefile.targ
+include ../../../../Makefile.lib
+include ../../../../Makefile.targ
+include ../../Makefile.com
+include ../../../../Makefile.lib.64
+
+.KEEP_STATE:
+
+all: $(LIBS) $(TXTS)
+
+install: all $(PLUGINDIR64) .WAIT $(PLUGINS64)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/pkg/manifests/driver-storage-blkdev.mf Mon May 17 21:17:01 2010 -0700
@@ -0,0 +1,45 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+#
+
+#
+# This package will install successfully into any zone, global or
+# non-global. The files, directories, links, and hardlinks, however,
+# will only be installed into the global zone.
+#
+<include hollow_zone_pkg>
+set name=pkg.fmri value=pkg:/driver/storage/blkdev@$(PKGVERS)
+set name=pkg.description value="Generic Block Driver"
+set name=pkg.summary value="Generic Block Driver"
+set name=info.classification value=org.opensolaris.category.2008:Drivers/Storage
+set name=variant.arch value=$(ARCH)
+set name=variant.opensolaris.zone value=global value=nonglobal
+dir path=kernel group=sys
+dir path=kernel/drv group=sys
+dir path=kernel/drv/$(ARCH64) group=sys
+driver name=blkdev perms="* 0640 root root"
+file path=kernel/drv/$(ARCH64)/blkdev group=sys
+$(i386_ONLY)file path=kernel/drv/blkdev group=sys
+license cr_Sun license=cr_Sun
+license lic_CDDL license=lic_CDDL
--- a/usr/src/pkg/manifests/driver-storage-sdcard.mf Tue May 18 11:19:39 2010 +0800
+++ b/usr/src/pkg/manifests/driver-storage-sdcard.mf Mon May 17 21:17:01 2010 -0700
@@ -20,8 +20,7 @@
#
#
-# Copyright 2010 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
#
#
@@ -44,13 +43,10 @@
$(i386_ONLY)dir path=kernel/drv/$(ARCH64) group=sys
$(i386_ONLY)dir path=kernel/misc group=sys
$(i386_ONLY)dir path=kernel/misc/$(ARCH64) group=sys
-$(i386_ONLY)driver name=sdcard perms="* 0644 root root"
$(i386_ONLY)driver name=sdhost perms="* 0644 root root" \
alias=pciclass,080500 \
alias=pciclass,080501
-$(i386_ONLY)file path=kernel/drv/$(ARCH64)/sdcard group=sys
$(i386_ONLY)file path=kernel/drv/$(ARCH64)/sdhost group=sys
-$(i386_ONLY)file path=kernel/drv/sdcard group=sys
$(i386_ONLY)file path=kernel/drv/sdhost group=sys
$(i386_ONLY)file path=kernel/misc/$(ARCH64)/sda group=sys mode=0755 \
reboot-needed=true
--- a/usr/src/pkg/manifests/service-storage-removable-media.mf Tue May 18 11:19:39 2010 +0800
+++ b/usr/src/pkg/manifests/service-storage-removable-media.mf Mon May 17 21:17:01 2010 -0700
@@ -20,8 +20,7 @@
#
#
-# Copyright 2010 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
#
set name=pkg.fmri value=pkg:/service/storage/removable-media@$(PKGVERS)
@@ -46,10 +45,12 @@
file path=usr/lib/libsmedia.so.1
file path=usr/lib/llib-lsmedia
file path=usr/lib/llib-lsmedia.ln
+file path=usr/lib/smedia/$(ARCH64)/sm_blkdev.so.1 mode=0555
file path=usr/lib/smedia/$(ARCH64)/sm_fd.so.1 mode=0555
file path=usr/lib/smedia/$(ARCH64)/sm_pcata.so.1 mode=0555
file path=usr/lib/smedia/$(ARCH64)/sm_scsi.so.1 mode=0555
file path=usr/lib/smedia/rpc.smserverd mode=0555
+file path=usr/lib/smedia/sm_blkdev.so.1 mode=0555
file path=usr/lib/smedia/sm_fd.so.1 mode=0555
file path=usr/lib/smedia/sm_pcata.so.1 mode=0555
file path=usr/lib/smedia/sm_scsi.so.1 mode=0555
--- a/usr/src/pkg/manifests/system-header.mf Tue May 18 11:19:39 2010 +0800
+++ b/usr/src/pkg/manifests/system-header.mf Mon May 17 21:17:01 2010 -0700
@@ -803,6 +803,7 @@
file path=usr/include/sys/bitmap.h
file path=usr/include/sys/bitset.h
file path=usr/include/sys/bl.h
+file path=usr/include/sys/blkdev.h
file path=usr/include/sys/bmc_intf.h
file path=usr/include/sys/bofi.h
file path=usr/include/sys/bofi_impl.h
--- a/usr/src/pkg/manifests/system-kernel.mf Tue May 18 11:19:39 2010 +0800
+++ b/usr/src/pkg/manifests/system-kernel.mf Mon May 17 21:17:01 2010 -0700
@@ -20,8 +20,7 @@
#
#
-# Copyright 2010 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
#
#
@@ -632,7 +631,6 @@
$(i386_ONLY)file path=kernel/misc/$(ARCH64)/agpmaster group=sys mode=0755 \
reboot-needed=true
file path=kernel/misc/$(ARCH64)/bignum group=sys mode=0755 reboot-needed=true
-file path=kernel/misc/$(ARCH64)/blk2scsa group=sys mode=0755 reboot-needed=true
$(i386_ONLY)file path=kernel/misc/$(ARCH64)/bootdev group=sys mode=0755 \
reboot-needed=true
file path=kernel/misc/$(ARCH64)/busra group=sys mode=0755 reboot-needed=true
@@ -683,8 +681,6 @@
$(i386_ONLY)file path=kernel/misc/agpmaster group=sys mode=0755 \
reboot-needed=true
$(i386_ONLY)file path=kernel/misc/bignum group=sys mode=0755 reboot-needed=true
-$(i386_ONLY)file path=kernel/misc/blk2scsa group=sys mode=0755 \
- reboot-needed=true
$(i386_ONLY)file path=kernel/misc/bootdev group=sys mode=0755 reboot-needed=true
$(i386_ONLY)file path=kernel/misc/busra group=sys mode=0755 reboot-needed=true
$(i386_ONLY)file path=kernel/misc/cardbus group=sys mode=0755 reboot-needed=true
--- a/usr/src/pkg/manifests/system-library.mf Tue May 18 11:19:39 2010 +0800
+++ b/usr/src/pkg/manifests/system-library.mf Mon May 17 21:17:01 2010 -0700
@@ -295,14 +295,12 @@
file path=usr/lib/cfgadm/$(ARCH64)/pci.so.1
$(i386_ONLY)file path=usr/lib/cfgadm/$(ARCH64)/sata.so.1
file path=usr/lib/cfgadm/$(ARCH64)/scsi.so.1
-file path=usr/lib/cfgadm/$(ARCH64)/sdcard.so.1
file path=usr/lib/cfgadm/$(ARCH64)/shp.so.1
file path=usr/lib/cfgadm/$(ARCH64)/usb.so.1
file path=usr/lib/cfgadm/ib.so.1
file path=usr/lib/cfgadm/pci.so.1
$(i386_ONLY)file path=usr/lib/cfgadm/sata.so.1
file path=usr/lib/cfgadm/scsi.so.1
-file path=usr/lib/cfgadm/sdcard.so.1
file path=usr/lib/cfgadm/shp.so.1
file path=usr/lib/cfgadm/usb.so.1
file path=usr/lib/extendedFILE.so.1
@@ -916,14 +914,12 @@
link path=usr/lib/cfgadm/$(ARCH64)/pci.so target=./pci.so.1
$(i386_ONLY)link path=usr/lib/cfgadm/$(ARCH64)/sata.so target=./sata.so.1
link path=usr/lib/cfgadm/$(ARCH64)/scsi.so target=./scsi.so.1
-link path=usr/lib/cfgadm/$(ARCH64)/sdcard.so target=./sdcard.so.1
link path=usr/lib/cfgadm/$(ARCH64)/shp.so target=./shp.so.1
link path=usr/lib/cfgadm/$(ARCH64)/usb.so target=./usb.so.1
link path=usr/lib/cfgadm/ib.so target=./ib.so.1
link path=usr/lib/cfgadm/pci.so target=./pci.so.1
$(i386_ONLY)link path=usr/lib/cfgadm/sata.so target=./sata.so.1
link path=usr/lib/cfgadm/scsi.so target=./scsi.so.1
-link path=usr/lib/cfgadm/sdcard.so target=./sdcard.so.1
link path=usr/lib/cfgadm/shp.so target=./shp.so.1
link path=usr/lib/cfgadm/usb.so target=./usb.so.1
link path=usr/lib/lib300.so target=./lib300.so.1
--- a/usr/src/tools/scripts/bfu.sh Tue May 18 11:19:39 2010 +0800
+++ b/usr/src/tools/scripts/bfu.sh Mon May 17 21:17:01 2010 -0700
@@ -8454,6 +8454,22 @@
rm -rf $usr/ucb/tek
rm -rf $usr/ucb/vplot
+ # Remove blk2scsa
+ rm -f $root/kernel/drv/blk2scsa
+ rm -f $root/kernel/drv/amd64/blk2scsa
+ rm -f $root/kernel/drv/sparcv9/blk2scsa
+
+ # Remove sdcard kernel module and cfgadm plugin - use blkdev now
+ rm -f $root/kernel/drv/sdcard
+ rm -f $root/kernel/drv/amd64/sdcard
+ rm -f $root/kernel/drv/sparcv9/sdcard
+ rm -f $usr/lib/cfgadm/sdcard.so.1
+ rm -f $usr/lib/cfgadm/sdcard.so
+ rm -f $usr/lib/cfgadm/amd64/sdcard.so.1
+ rm -f $usr/lib/cfgadm/amd64/sdcard.so
+ rm -f $usr/lib/cfgadm/sparcv9/sdcard.so.1
+ rm -f $usr/lib/cfgadm/sparcv9/sdcard.so
+
#
# Remove legacy pcmcia bits
#
--- a/usr/src/uts/common/Makefile.files Tue May 18 11:19:39 2010 +0800
+++ b/usr/src/uts/common/Makefile.files Mon May 17 21:17:01 2010 -0700
@@ -468,6 +468,8 @@
AC97_OBJS += ac97.o ac97_ad.o ac97_alc.o ac97_cmi.o
+BLKDEV_OBJS += blkdev.o
+
CARDBUS_OBJS += cardbus.o cardbus_hp.o cardbus_cfg.o
CONSKBD_OBJS += conskbd.o
@@ -1939,9 +1941,7 @@
#
# sdcard modules
#
-SDA_OBJS = sda_cmd.o sda_host.o sda_init.o sda_mem.o sda_mod.o \
- sda_nexus.o sda_slot.o
-SDCARD_OBJS = sdcard.o
+SDA_OBJS = sda_cmd.o sda_host.o sda_init.o sda_mem.o sda_mod.o sda_slot.o
SDHOST_OBJS = sdhost.o
#
--- a/usr/src/uts/common/Makefile.rules Tue May 18 11:19:39 2010 +0800
+++ b/usr/src/uts/common/Makefile.rules Mon May 17 21:17:01 2010 -0700
@@ -646,6 +646,10 @@
$(COMPILE.c) -o $@ $<
$(CTFCONVERT_O)
+$(OBJS_DIR)/%.o: $(UTSBASE)/common/io/blkdev/%.c
+ $(COMPILE.c) -o $@ $<
+ $(CTFCONVERT_O)
+
$(OBJS_DIR)/%.o: $(UTSBASE)/common/io/bpf/%.c
$(COMPILE.c) -o $@ $<
$(CTFCONVERT_O)
@@ -1971,6 +1975,9 @@
$(LINTS_DIR)/%.ln: $(UTSBASE)/common/io/bge/%.c
@($(LHEAD) $(LINT.c) $< $(LTAIL))
+$(LINTS_DIR)/%.ln: $(UTSBASE)/common/io/blkdev/%.c
+ @($(LHEAD) $(LINT.c) $< $(LTAIL))
+
$(LINTS_DIR)/%.ln: $(UTSBASE)/common/io/cardbus/%.c
@($(LHEAD) $(LINT.c) $< $(LTAIL))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/io/blkdev/blkdev.c Mon May 17 21:17:01 2010 -0700
@@ -0,0 +1,1634 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#include <sys/types.h>
+#include <sys/ksynch.h>
+#include <sys/kmem.h>
+#include <sys/file.h>
+#include <sys/errno.h>
+#include <sys/open.h>
+#include <sys/buf.h>
+#include <sys/uio.h>
+#include <sys/aio_req.h>
+#include <sys/cred.h>
+#include <sys/modctl.h>
+#include <sys/cmlb.h>
+#include <sys/conf.h>
+#include <sys/devops.h>
+#include <sys/list.h>
+#include <sys/sysmacros.h>
+#include <sys/dkio.h>
+#include <sys/vtoc.h>
+#include <sys/scsi/scsi.h> /* for DTYPE_DIRECT */
+#include <sys/kstat.h>
+#include <sys/fs/dv_node.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/note.h>
+#include <sys/blkdev.h>
+
+#define BD_MAXPART 64
+#define BDINST(dev) (getminor(dev) / BD_MAXPART)
+#define BDPART(dev) (getminor(dev) % BD_MAXPART)
+
+typedef struct bd bd_t;
+typedef struct bd_xfer_impl bd_xfer_impl_t;
+
+struct bd {
+ void *d_private;
+ dev_info_t *d_dip;
+ kmutex_t d_ocmutex;
+ kmutex_t d_iomutex;
+ kmutex_t d_statemutex;
+ kcondvar_t d_statecv;
+ enum dkio_state d_state;
+ cmlb_handle_t d_cmlbh;
+ unsigned d_open_lyr[BD_MAXPART]; /* open count */
+ uint64_t d_open_excl; /* bit mask indexed by partition */
+ uint64_t d_open_reg[OTYPCNT]; /* bit mask */
+
+ uint32_t d_qsize;
+ uint32_t d_qactive;
+ uint32_t d_maxxfer;
+ uint32_t d_blkshift;
+ uint64_t d_numblks;
+ ddi_devid_t d_devid;
+
+ kmem_cache_t *d_cache;
+ list_t d_runq;
+ list_t d_waitq;
+ kstat_t *d_ksp;
+ kstat_io_t *d_kiop;
+
+ boolean_t d_rdonly;
+ boolean_t d_removable;
+ boolean_t d_hotpluggable;
+ boolean_t d_use_dma;
+
+ ddi_dma_attr_t d_dma;
+ bd_ops_t d_ops;
+ bd_handle_t d_handle;
+};
+
+struct bd_handle {
+ bd_ops_t h_ops;
+ ddi_dma_attr_t *h_dma;
+ dev_info_t *h_parent;
+ dev_info_t *h_child;
+ void *h_private;
+ bd_t *h_bd;
+ char *h_name;
+ char h_addr[20]; /* enough for %X,%X */
+};
+
+struct bd_xfer_impl {
+ bd_xfer_t i_public;
+ list_node_t i_linkage;
+ bd_t *i_bd;
+ buf_t *i_bp;
+ uint_t i_num_win;
+ uint_t i_cur_win;
+ off_t i_offset;
+ int (*i_func)(void *, bd_xfer_t *);
+ uint32_t i_blkshift;
+ size_t i_len;
+ size_t i_resid;
+};
+
+#define i_dmah i_public.x_dmah
+#define i_dmac i_public.x_dmac
+#define i_ndmac i_public.x_ndmac
+#define i_kaddr i_public.x_kaddr
+#define i_nblks i_public.x_nblks
+#define i_blkno i_public.x_blkno
+
+
+/*
+ * Private prototypes.
+ */
+
+static int bd_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
+static int bd_attach(dev_info_t *, ddi_attach_cmd_t);
+static int bd_detach(dev_info_t *, ddi_detach_cmd_t);
+
+static int bd_open(dev_t *, int, int, cred_t *);
+static int bd_close(dev_t, int, int, cred_t *);
+static int bd_strategy(struct buf *);
+static int bd_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
+static int bd_read(dev_t, struct uio *, cred_t *);
+static int bd_write(dev_t, struct uio *, cred_t *);
+static int bd_aread(dev_t, struct aio_req *, cred_t *);
+static int bd_awrite(dev_t, struct aio_req *, cred_t *);
+static int bd_prop_op(dev_t, dev_info_t *, ddi_prop_op_t, int, char *,
+ caddr_t, int *);
+
+static int bd_tg_rdwr(dev_info_t *, uchar_t, void *, diskaddr_t, size_t,
+ void *);
+static int bd_tg_getinfo(dev_info_t *, int, void *, void *);
+static int bd_xfer_ctor(void *, void *, int);
+static void bd_xfer_dtor(void *, void *);
+static void bd_sched(bd_t *);
+static void bd_submit(bd_t *, bd_xfer_impl_t *);
+static void bd_runq_exit(bd_xfer_impl_t *, int);
+static void bd_update_state(bd_t *);
+static int bd_check_state(bd_t *, enum dkio_state *);
+static int bd_flush_write_cache(bd_t *, struct dk_callback *);
+
+struct cmlb_tg_ops bd_tg_ops = {
+ TG_DK_OPS_VERSION_1,
+ bd_tg_rdwr,
+ bd_tg_getinfo,
+};
+
+static struct cb_ops bd_cb_ops = {
+ bd_open, /* open */
+ bd_close, /* close */
+ bd_strategy, /* strategy */
+ nodev, /* print */
+ nodev, /* dump */
+ bd_read, /* read */
+ bd_write, /* write */
+ bd_ioctl, /* ioctl */
+ nodev, /* devmap */
+ nodev, /* mmap */
+ nodev, /* segmap */
+ nochpoll, /* poll */
+ bd_prop_op, /* cb_prop_op */
+ 0, /* streamtab */
+ D_64BIT | D_MP, /* Driver comaptibility flag */
+ CB_REV, /* cb_rev */
+ bd_aread, /* async read */
+ bd_awrite /* async write */
+};
+
+struct dev_ops bd_dev_ops = {
+ DEVO_REV, /* devo_rev, */
+ 0, /* refcnt */
+ bd_getinfo, /* getinfo */
+ nulldev, /* identify */
+ nulldev, /* probe */
+ bd_attach, /* attach */
+ bd_detach, /* detach */
+ nodev, /* reset */
+ &bd_cb_ops, /* driver operations */
+ NULL, /* bus operations */
+ NULL, /* power */
+ ddi_quiesce_not_needed, /* quiesce */
+};
+
+static struct modldrv modldrv = {
+ &mod_driverops,
+ "Generic Block Device",
+ &bd_dev_ops,
+};
+
+static struct modlinkage modlinkage = {
+ MODREV_1, { &modldrv, NULL }
+};
+
+static void *bd_state;
+static krwlock_t bd_lock;
+
+int
+_init(void)
+{
+ int rv;
+
+ rv = ddi_soft_state_init(&bd_state, sizeof (struct bd), 2);
+ if (rv != DDI_SUCCESS) {
+ return (rv);
+ }
+ rw_init(&bd_lock, NULL, RW_DRIVER, NULL);
+ rv = mod_install(&modlinkage);
+ if (rv != DDI_SUCCESS) {
+ rw_destroy(&bd_lock);
+ ddi_soft_state_fini(&bd_state);
+ }
+ return (rv);
+}
+
+int
+_fini(void)
+{
+ int rv;
+
+ rv = mod_remove(&modlinkage);
+ if (rv == DDI_SUCCESS) {
+ rw_destroy(&bd_lock);
+ ddi_soft_state_fini(&bd_state);
+ }
+ return (rv);
+}
+
+int
+_info(struct modinfo *modinfop)
+{
+ return (mod_info(&modlinkage, modinfop));
+}
+
+static int
+bd_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **resultp)
+{
+ bd_t *bd;
+ minor_t inst;
+
+ _NOTE(ARGUNUSED(dip));
+
+ inst = BDINST((dev_t)arg);
+
+ switch (cmd) {
+ case DDI_INFO_DEVT2DEVINFO:
+ bd = ddi_get_soft_state(bd_state, inst);
+ if (bd == NULL) {
+ return (DDI_FAILURE);
+ }
+ *resultp = (void *)bd->d_dip;
+ break;
+
+ case DDI_INFO_DEVT2INSTANCE:
+ *resultp = (void *)(intptr_t)inst;
+ break;
+
+ default:
+ return (DDI_FAILURE);
+ }
+ return (DDI_SUCCESS);
+}
+
+static int
+bd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
+{
+ int inst;
+ bd_handle_t hdl;
+ bd_t *bd;
+ bd_drive_t drive;
+ int rv;
+ char name[16];
+ char kcache[32];
+
+ switch (cmd) {
+ case DDI_ATTACH:
+ break;
+ case DDI_RESUME:
+ /* We don't do anything native for suspend/resume */
+ return (DDI_SUCCESS);
+ default:
+ return (DDI_FAILURE);
+ }
+
+ inst = ddi_get_instance(dip);
+ hdl = ddi_get_parent_data(dip);
+
+ (void) snprintf(name, sizeof (name), "%s%d",
+ ddi_driver_name(dip), ddi_get_instance(dip));
+ (void) snprintf(kcache, sizeof (kcache), "%s_xfer", name);
+
+ if (hdl == NULL) {
+ cmn_err(CE_WARN, "%s: missing parent data!", name);
+ return (DDI_FAILURE);
+ }
+
+ if (ddi_soft_state_zalloc(bd_state, inst) != DDI_SUCCESS) {
+ cmn_err(CE_WARN, "%s: unable to zalloc soft state!", name);
+ return (DDI_FAILURE);
+ }
+ bd = ddi_get_soft_state(bd_state, inst);
+
+ if (hdl->h_dma) {
+ bd->d_dma = *(hdl->h_dma);
+ bd->d_dma.dma_attr_granular =
+ max(DEV_BSIZE, bd->d_dma.dma_attr_granular);
+ bd->d_use_dma = B_TRUE;
+
+ if (bd->d_maxxfer &&
+ (bd->d_maxxfer != bd->d_dma.dma_attr_maxxfer)) {
+ cmn_err(CE_WARN,
+ "%s: inconsistent maximum transfer size!",
+ name);
+ /* We force it */
+ bd->d_maxxfer = bd->d_dma.dma_attr_maxxfer;
+ } else {
+ bd->d_maxxfer = bd->d_dma.dma_attr_maxxfer;
+ }
+ } else {
+ bd->d_use_dma = B_FALSE;
+ if (bd->d_maxxfer == 0) {
+ bd->d_maxxfer = 1024 * 1024;
+ }
+ }
+ bd->d_ops = hdl->h_ops;
+ bd->d_private = hdl->h_private;
+ bd->d_blkshift = 9; /* 512 bytes, to start */
+
+ if (bd->d_maxxfer % DEV_BSIZE) {
+ cmn_err(CE_WARN, "%s: maximum transfer misaligned!", name);
+ bd->d_maxxfer &= ~(DEV_BSIZE - 1);
+ }
+ if (bd->d_maxxfer < DEV_BSIZE) {
+ cmn_err(CE_WARN, "%s: maximum transfer size too small!", name);
+ ddi_soft_state_free(bd_state, inst);
+ return (DDI_FAILURE);
+ }
+
+ bd->d_dip = dip;
+ bd->d_handle = hdl;
+ hdl->h_bd = bd;
+ ddi_set_driver_private(dip, bd);
+
+ mutex_init(&bd->d_iomutex, NULL, MUTEX_DRIVER, NULL);
+ mutex_init(&bd->d_ocmutex, NULL, MUTEX_DRIVER, NULL);
+ mutex_init(&bd->d_statemutex, NULL, MUTEX_DRIVER, NULL);
+ cv_init(&bd->d_statecv, NULL, CV_DRIVER, NULL);
+
+ list_create(&bd->d_waitq, sizeof (bd_xfer_impl_t),
+ offsetof(struct bd_xfer_impl, i_linkage));
+ list_create(&bd->d_runq, sizeof (bd_xfer_impl_t),
+ offsetof(struct bd_xfer_impl, i_linkage));
+
+ bd->d_cache = kmem_cache_create(kcache, sizeof (bd_xfer_impl_t), 8,
+ bd_xfer_ctor, bd_xfer_dtor, NULL, bd, NULL, 0);
+
+ bd->d_ksp = kstat_create(ddi_driver_name(dip), inst, NULL, "disk",
+ KSTAT_TYPE_IO, 1, KSTAT_FLAG_PERSISTENT);
+ if (bd->d_ksp != NULL) {
+ bd->d_ksp->ks_lock = &bd->d_iomutex;
+ kstat_install(bd->d_ksp);
+ bd->d_kiop = bd->d_ksp->ks_data;
+ } else {
+ /*
+ * Even if we cannot create the kstat, we create a
+ * scratch kstat. The reason for this is to ensure
+ * that we can update the kstat all of the time,
+ * without adding an extra branch instruction.
+ */
+ bd->d_kiop = kmem_zalloc(sizeof (kstat_io_t), KM_SLEEP);
+ }
+
+ cmlb_alloc_handle(&bd->d_cmlbh);
+
+ bd->d_state = DKIO_NONE;
+
+ bzero(&drive, sizeof (drive));
+ bd->d_ops.o_drive_info(bd->d_private, &drive);
+ bd->d_qsize = drive.d_qsize;
+ bd->d_maxxfer = drive.d_maxxfer;
+ bd->d_removable = drive.d_removable;
+ bd->d_hotpluggable = drive.d_hotpluggable;
+
+ rv = cmlb_attach(dip, &bd_tg_ops, DTYPE_DIRECT,
+ bd->d_removable, bd->d_hotpluggable,
+ drive.d_lun >= 0 ? DDI_NT_BLOCK_CHAN : DDI_NT_BLOCK,
+ CMLB_FAKE_LABEL_ONE_PARTITION, bd->d_cmlbh, bd);
+ if (rv != 0) {
+ cmlb_free_handle(&bd->d_cmlbh);
+ kmem_cache_destroy(bd->d_cache);
+ mutex_destroy(&bd->d_iomutex);
+ mutex_destroy(&bd->d_ocmutex);
+ mutex_destroy(&bd->d_statemutex);
+ cv_destroy(&bd->d_statecv);
+ list_destroy(&bd->d_waitq);
+ list_destroy(&bd->d_runq);
+ if (bd->d_ksp != NULL) {
+ kstat_delete(bd->d_ksp);
+ bd->d_ksp = NULL;
+ } else {
+ kmem_free(bd->d_kiop, sizeof (kstat_io_t));
+ }
+ ddi_soft_state_free(bd_state, inst);
+ return (DDI_FAILURE);
+ }
+
+ if (bd->d_ops.o_devid_init != NULL) {
+ rv = bd->d_ops.o_devid_init(bd->d_private, dip, &bd->d_devid);
+ if (rv == DDI_SUCCESS) {
+ if (ddi_devid_register(dip, bd->d_devid) !=
+ DDI_SUCCESS) {
+ cmn_err(CE_WARN,
+ "%s: unable to register devid", name);
+ }
+ }
+ }
+
+ /*
+ * Add a zero-length attribute to tell the world we support
+ * kernel ioctls (for layered drivers). Also set up properties
+ * used by HAL to identify removable media.
+ */
+ (void) ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP,
+ DDI_KERNEL_IOCTL, NULL, 0);
+ if (bd->d_removable) {
+ (void) ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP,
+ "removable-media", NULL, 0);
+ }
+ if (bd->d_hotpluggable) {
+ (void) ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP,
+ "hotpluggable", NULL, 0);
+ }
+
+ ddi_report_dev(dip);
+
+ return (DDI_SUCCESS);
+}
+
+static int
+bd_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
+{
+ bd_t *bd;
+
+ bd = ddi_get_driver_private(dip);
+
+ switch (cmd) {
+ case DDI_DETACH:
+ break;
+ case DDI_SUSPEND:
+ /* We don't suspend, but our parent does */
+ return (DDI_SUCCESS);
+ default:
+ return (DDI_FAILURE);
+ }
+ if (bd->d_ksp != NULL) {
+ kstat_delete(bd->d_ksp);
+ bd->d_ksp = NULL;
+ } else {
+ kmem_free(bd->d_kiop, sizeof (kstat_io_t));
+ }
+ cmlb_detach(bd->d_cmlbh, bd);
+ cmlb_free_handle(&bd->d_cmlbh);
+ if (bd->d_devid)
+ ddi_devid_free(bd->d_devid);
+ kmem_cache_destroy(bd->d_cache);
+ mutex_destroy(&bd->d_iomutex);
+ mutex_destroy(&bd->d_ocmutex);
+ mutex_destroy(&bd->d_statemutex);
+ cv_destroy(&bd->d_statecv);
+ list_destroy(&bd->d_waitq);
+ list_destroy(&bd->d_runq);
+ ddi_soft_state_free(bd_state, ddi_get_instance(dip));
+ return (DDI_SUCCESS);
+}
+
+static int
+bd_xfer_ctor(void *buf, void *arg, int kmflag)
+{
+ bd_xfer_impl_t *xi;
+ bd_t *bd = arg;
+ int (*dcb)(caddr_t);
+
+ if (kmflag == KM_SLEEP) {
+ dcb = DDI_DMA_SLEEP;
+ } else {
+ dcb = DDI_DMA_DONTWAIT;
+ }
+
+ xi = buf;
+ bzero(xi, sizeof (*xi));
+ xi->i_bd = bd;
+
+ if (bd->d_use_dma) {
+ if (ddi_dma_alloc_handle(bd->d_dip, &bd->d_dma, dcb, NULL,
+ &xi->i_dmah) != DDI_SUCCESS) {
+ return (-1);
+ }
+ }
+
+ return (0);
+}
+
+static void
+bd_xfer_dtor(void *buf, void *arg)
+{
+ bd_xfer_impl_t *xi = buf;
+
+ _NOTE(ARGUNUSED(arg));
+
+ if (xi->i_dmah)
+ ddi_dma_free_handle(&xi->i_dmah);
+ xi->i_dmah = NULL;
+}
+
+static bd_xfer_impl_t *
+bd_xfer_alloc(bd_t *bd, struct buf *bp, int (*func)(void *, bd_xfer_t *),
+ int kmflag)
+{
+ bd_xfer_impl_t *xi;
+ int rv;
+ int status;
+ unsigned dir;
+ int (*cb)(caddr_t);
+ size_t len;
+ uint32_t shift;
+
+ if (kmflag == KM_SLEEP) {
+ cb = DDI_DMA_SLEEP;
+ } else {
+ cb = DDI_DMA_DONTWAIT;
+ }
+
+ xi = kmem_cache_alloc(bd->d_cache, kmflag);
+ if (xi == NULL) {
+ bioerror(bp, ENOMEM);
+ return (NULL);
+ }
+
+ ASSERT(bp);
+ ASSERT(bp->b_bcount);
+
+ xi->i_bp = bp;
+ xi->i_func = func;
+ xi->i_blkno = bp->b_lblkno;
+
+ if (bp->b_bcount == 0) {
+ xi->i_len = 0;
+ xi->i_nblks = 0;
+ xi->i_kaddr = NULL;
+ xi->i_resid = 0;
+ xi->i_num_win = 0;
+ goto done;
+ }
+
+ if (bp->b_flags & B_READ) {
+ dir = DDI_DMA_READ;
+ xi->i_func = bd->d_ops.o_read;
+ } else {
+ dir = DDI_DMA_WRITE;
+ xi->i_func = bd->d_ops.o_write;
+ }
+
+ shift = bd->d_blkshift;
+ xi->i_blkshift = shift;
+
+ if (!bd->d_use_dma) {
+ bp_mapin(bp);
+ rv = 0;
+ xi->i_offset = 0;
+ xi->i_num_win =
+ (bp->b_bcount + (bd->d_maxxfer - 1)) / bd->d_maxxfer;
+ xi->i_cur_win = 0;
+ xi->i_len = min(bp->b_bcount, bd->d_maxxfer);
+ xi->i_nblks = xi->i_len >> shift;
+ xi->i_kaddr = bp->b_un.b_addr;
+ xi->i_resid = bp->b_bcount;
+ } else {
+
+ /*
+ * We have to use consistent DMA if the address is misaligned.
+ */
+ if (((bp->b_flags & (B_PAGEIO | B_REMAPPED)) != B_PAGEIO) &&
+ ((uintptr_t)bp->b_un.b_addr & 0x7)) {
+ dir |= DDI_DMA_CONSISTENT | DDI_DMA_PARTIAL;
+ } else {
+ dir |= DDI_DMA_STREAMING | DDI_DMA_PARTIAL;
+ }
+
+ status = ddi_dma_buf_bind_handle(xi->i_dmah, bp, dir, cb,
+ NULL, &xi->i_dmac, &xi->i_ndmac);
+ switch (status) {
+ case DDI_DMA_MAPPED:
+ xi->i_num_win = 1;
+ xi->i_cur_win = 0;
+ xi->i_offset = 0;
+ xi->i_len = bp->b_bcount;
+ xi->i_nblks = xi->i_len >> shift;
+ xi->i_resid = bp->b_bcount;
+ rv = 0;
+ break;
+ case DDI_DMA_PARTIAL_MAP:
+ xi->i_cur_win = 0;
+
+ if ((ddi_dma_numwin(xi->i_dmah, &xi->i_num_win) !=
+ DDI_SUCCESS) ||
+ (ddi_dma_getwin(xi->i_dmah, 0, &xi->i_offset,
+ &len, &xi->i_dmac, &xi->i_ndmac) !=
+ DDI_SUCCESS) ||
+ (P2PHASE(len, shift) != 0)) {
+ (void) ddi_dma_unbind_handle(xi->i_dmah);
+ rv = EFAULT;
+ goto done;
+ }
+ xi->i_len = len;
+ xi->i_nblks = xi->i_len >> shift;
+ xi->i_resid = bp->b_bcount;
+ rv = 0;
+ break;
+ case DDI_DMA_NORESOURCES:
+ rv = EAGAIN;
+ goto done;
+ case DDI_DMA_TOOBIG:
+ rv = EINVAL;
+ goto done;
+ case DDI_DMA_NOMAPPING:
+ case DDI_DMA_INUSE:
+ default:
+ rv = EFAULT;
+ goto done;
+ }
+ }
+
+done:
+ if (rv != 0) {
+ kmem_cache_free(bd->d_cache, xi);
+ bioerror(bp, rv);
+ return (NULL);
+ }
+
+ return (xi);
+}
+
+static void
+bd_xfer_free(bd_xfer_impl_t *xi)
+{
+ if (xi->i_dmah) {
+ (void) ddi_dma_unbind_handle(xi->i_dmah);
+ }
+ kmem_cache_free(xi->i_bd->d_cache, xi);
+}
+
+static int
+bd_open(dev_t *devp, int flag, int otyp, cred_t *credp)
+{
+ dev_t dev = *devp;
+ bd_t *bd;
+ minor_t part;
+ minor_t inst;
+ uint64_t mask;
+ boolean_t ndelay;
+ int rv;
+ diskaddr_t nblks;
+ diskaddr_t lba;
+
+ _NOTE(ARGUNUSED(credp));
+
+ part = BDPART(dev);
+ inst = BDINST(dev);
+
+ if (otyp >= OTYPCNT)
+ return (EINVAL);
+
+ ndelay = (flag & (FNDELAY | FNONBLOCK)) ? B_TRUE : B_FALSE;
+
+ /*
+ * Block any DR events from changing the set of registered
+ * devices while we function.
+ */
+ rw_enter(&bd_lock, RW_READER);
+ if ((bd = ddi_get_soft_state(bd_state, inst)) == NULL) {
+ rw_exit(&bd_lock);
+ return (ENXIO);
+ }
+
+ mutex_enter(&bd->d_ocmutex);
+
+ ASSERT(part < 64);
+ mask = (1U << part);
+
+ bd_update_state(bd);
+
+ if (cmlb_validate(bd->d_cmlbh, 0, bd) != 0) {
+
+ /* non-blocking opens are allowed to succeed */
+ if (!ndelay) {
+ rv = ENXIO;
+ goto done;
+ }
+ } else if (cmlb_partinfo(bd->d_cmlbh, part, &nblks, &lba,
+ NULL, NULL, bd) == 0) {
+
+ /*
+ * We read the partinfo, verify valid ranges. If the
+ * partition is invalid, and we aren't blocking or
+ * doing a raw access, then fail. (Non-blocking and
+ * raw accesses can still succeed to allow a disk with
+ * bad partition data to opened by format and fdisk.)
+ */
+ if ((!nblks) && ((!ndelay) || (otyp != OTYP_CHR))) {
+ rv = ENXIO;
+ goto done;
+ }
+ } else if (!ndelay) {
+ /*
+ * cmlb_partinfo failed -- invalid partition or no
+ * disk label.
+ */
+ rv = ENXIO;
+ goto done;
+ }
+
+ if ((flag & FWRITE) && bd->d_rdonly) {
+ rv = EROFS;
+ goto done;
+ }
+
+ if ((bd->d_open_excl) & (mask)) {
+ rv = EBUSY;
+ goto done;
+ }
+ if (flag & FEXCL) {
+ if (bd->d_open_lyr[part]) {
+ rv = EBUSY;
+ goto done;
+ }
+ for (int i = 0; i < OTYP_LYR; i++) {
+ if (bd->d_open_reg[i] & mask) {
+ rv = EBUSY;
+ goto done;
+ }
+ }
+ }
+
+ if (otyp == OTYP_LYR) {
+ bd->d_open_lyr[part]++;
+ } else {
+ bd->d_open_reg[otyp] |= mask;
+ }
+ if (flag & FEXCL) {
+ bd->d_open_excl |= mask;
+ }
+
+ rv = 0;
+done:
+ mutex_exit(&bd->d_ocmutex);
+ rw_exit(&bd_lock);
+
+ return (rv);
+}
+
+static int
+bd_close(dev_t dev, int flag, int otyp, cred_t *credp)
+{
+ bd_t *bd;
+ minor_t inst;
+ minor_t part;
+ uint64_t mask;
+ boolean_t last = B_TRUE;
+
+ _NOTE(ARGUNUSED(flag));
+ _NOTE(ARGUNUSED(credp));
+
+ part = BDPART(dev);
+ inst = BDINST(dev);
+
+ ASSERT(part < 64);
+ mask = (1U << part);
+
+ rw_enter(&bd_lock, RW_READER);
+
+ if ((bd = ddi_get_soft_state(bd_state, inst)) == NULL) {
+ rw_exit(&bd_lock);
+ return (ENXIO);
+ }
+
+ mutex_enter(&bd->d_ocmutex);
+ if (bd->d_open_excl & mask) {
+ bd->d_open_excl &= ~mask;
+ }
+ if (otyp == OTYP_LYR) {
+ bd->d_open_lyr[part]--;
+ } else {
+ bd->d_open_reg[otyp] &= ~mask;
+ }
+ for (int i = 0; i < 64; i++) {
+ if (bd->d_open_lyr[part]) {
+ last = B_FALSE;
+ }
+ }
+ for (int i = 0; last && (i < OTYP_LYR); i++) {
+ if (bd->d_open_reg[i]) {
+ last = B_FALSE;
+ }
+ }
+ mutex_exit(&bd->d_ocmutex);
+
+ if (last) {
+ cmlb_invalidate(bd->d_cmlbh, bd);
+ }
+ rw_exit(&bd_lock);
+
+ return (0);
+}
+
+static int
+bd_read(dev_t dev, struct uio *uio, cred_t *credp)
+{
+ _NOTE(ARGUNUSED(credp));
+ return (physio(bd_strategy, NULL, dev, B_READ, minphys, uio));
+}
+
+static int
+bd_write(dev_t dev, struct uio *uio, cred_t *credp)
+{
+ _NOTE(ARGUNUSED(credp));
+ return (physio(bd_strategy, NULL, dev, B_WRITE, minphys, uio));
+}
+
+static int
+bd_aread(dev_t dev, struct aio_req *aio, cred_t *credp)
+{
+ _NOTE(ARGUNUSED(credp));
+ return (aphysio(bd_strategy, anocancel, dev, B_READ, minphys, aio));
+}
+
+static int
+bd_awrite(dev_t dev, struct aio_req *aio, cred_t *credp)
+{
+ _NOTE(ARGUNUSED(credp));
+ return (aphysio(bd_strategy, anocancel, dev, B_WRITE, minphys, aio));
+}
+
+static int
+bd_strategy(struct buf *bp)
+{
+ minor_t inst;
+ minor_t part;
+ bd_t *bd;
+ diskaddr_t p_lba;
+ diskaddr_t p_nblks;
+ diskaddr_t b_nblks;
+ bd_xfer_impl_t *xi;
+ uint32_t shift;
+ int (*func)(void *, bd_xfer_t *);
+
+ part = BDPART(bp->b_edev);
+ inst = BDINST(bp->b_edev);
+
+ ASSERT(bp);
+
+ bp->b_resid = bp->b_bcount;
+
+ if ((bd = ddi_get_soft_state(bd_state, inst)) == NULL) {
+ bioerror(bp, ENXIO);
+ biodone(bp);
+ return (0);
+ }
+
+ if (cmlb_partinfo(bd->d_cmlbh, part, &p_nblks, &p_lba,
+ NULL, NULL, bd)) {
+ bioerror(bp, ENXIO);
+ biodone(bp);
+ return (0);
+ }
+
+ shift = bd->d_blkshift;
+
+ if ((P2PHASE(bp->b_bcount, (1U << shift)) != 0) ||
+ (bp->b_lblkno > p_nblks)) {
+ bioerror(bp, ENXIO);
+ biodone(bp);
+ return (0);
+ }
+ b_nblks = bp->b_bcount >> shift;
+ if ((bp->b_lblkno == p_nblks) || (bp->b_bcount == 0)) {
+ biodone(bp);
+ return (0);
+ }
+
+ if ((b_nblks + bp->b_lblkno) > p_nblks) {
+ bp->b_resid = ((bp->b_lblkno + b_nblks - p_nblks) << shift);
+ bp->b_bcount -= bp->b_resid;
+ } else {
+ bp->b_resid = 0;
+ }
+ func = (bp->b_flags & B_READ) ? bd->d_ops.o_read : bd->d_ops.o_write;
+
+ xi = bd_xfer_alloc(bd, bp, func, KM_NOSLEEP);
+ if (xi == NULL) {
+ xi = bd_xfer_alloc(bd, bp, func, KM_PUSHPAGE);
+ }
+ if (xi == NULL) {
+ /* bd_request_alloc will have done bioerror */
+ biodone(bp);
+ return (0);
+ }
+ xi->i_blkno = bp->b_lblkno + p_lba;
+
+ bd_submit(bd, xi);
+
+ return (0);
+}
+
+static int
+bd_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *credp, int *rvalp)
+{
+ minor_t inst;
+ uint16_t part;
+ bd_t *bd;
+ void *ptr = (void *)arg;
+ int rv;
+
+ part = BDPART(dev);
+ inst = BDINST(dev);
+
+ if ((bd = ddi_get_soft_state(bd_state, inst)) == NULL) {
+ return (ENXIO);
+ }
+
+ rv = cmlb_ioctl(bd->d_cmlbh, dev, cmd, arg, flag, credp, rvalp, bd);
+ if (rv != ENOTTY)
+ return (rv);
+
+ switch (cmd) {
+ case DKIOCGMEDIAINFO: {
+ struct dk_minfo minfo;
+
+ /* make sure our state information is current */
+ bd_update_state(bd);
+ bzero(&minfo, sizeof (minfo));
+ minfo.dki_media_type = DK_FIXED_DISK;
+ minfo.dki_lbsize = (1U << bd->d_blkshift);
+ minfo.dki_capacity = bd->d_numblks;
+ if (ddi_copyout(&minfo, ptr, sizeof (minfo), flag)) {
+ return (EFAULT);
+ }
+ return (0);
+ }
+ case DKIOCINFO: {
+ struct dk_cinfo cinfo;
+ bzero(&cinfo, sizeof (cinfo));
+ cinfo.dki_ctype = DKC_BLKDEV;
+ cinfo.dki_cnum = ddi_get_instance(ddi_get_parent(bd->d_dip));
+ (void) snprintf(cinfo.dki_cname, sizeof (cinfo.dki_cname),
+ "%s", ddi_driver_name(ddi_get_parent(bd->d_dip)));
+ (void) snprintf(cinfo.dki_dname, sizeof (cinfo.dki_dname),
+ "%s", ddi_driver_name(bd->d_dip));
+ cinfo.dki_unit = inst;
+ cinfo.dki_flags = DKI_FMTVOL;
+ cinfo.dki_partition = part;
+ cinfo.dki_maxtransfer = bd->d_maxxfer / DEV_BSIZE;
+ cinfo.dki_addr = 0;
+ cinfo.dki_slave = 0;
+ cinfo.dki_space = 0;
+ cinfo.dki_prio = 0;
+ cinfo.dki_vec = 0;
+ if (ddi_copyout(&cinfo, ptr, sizeof (cinfo), flag)) {
+ return (EFAULT);
+ }
+ return (0);
+ }
+ case DKIOCREMOVABLE: {
+ int i;
+ i = bd->d_removable ? 1 : 0;
+ if (ddi_copyout(&i, ptr, sizeof (i), flag)) {
+ return (EFAULT);
+ }
+ return (0);
+ }
+ case DKIOCHOTPLUGGABLE: {
+ int i;
+ i = bd->d_hotpluggable ? 1 : 0;
+ if (ddi_copyout(&i, ptr, sizeof (i), flag)) {
+ return (EFAULT);
+ }
+ return (0);
+ }
+ case DKIOCREADONLY: {
+ int i;
+ i = bd->d_rdonly ? 1 : 0;
+ if (ddi_copyout(&i, ptr, sizeof (i), flag)) {
+ return (EFAULT);
+ }
+ return (0);
+ }
+ case DKIOCSTATE: {
+ enum dkio_state state;
+ if (ddi_copyin(ptr, &state, sizeof (state), flag)) {
+ return (EFAULT);
+ }
+ if ((rv = bd_check_state(bd, &state)) != 0) {
+ return (rv);
+ }
+ if (ddi_copyout(&state, ptr, sizeof (state), flag)) {
+ return (EFAULT);
+ }
+ return (0);
+ }
+ case DKIOCFLUSHWRITECACHE: {
+ struct dk_callback *dkc;
+
+ dkc = flag & FKIOCTL ? (void *)arg : NULL;
+ rv = bd_flush_write_cache(bd, dkc);
+ return (rv);
+ }
+
+ default:
+ break;
+
+ }
+ return (ENOTTY);
+}
+
+static int
+bd_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags,
+ char *name, caddr_t valuep, int *lengthp)
+{
+ bd_t *bd;
+
+ bd = ddi_get_soft_state(bd_state, ddi_get_instance(dip));
+ if (bd == NULL)
+ return (ddi_prop_op(dev, dip, prop_op, mod_flags,
+ name, valuep, lengthp));
+
+ return (cmlb_prop_op(bd->d_cmlbh, dev, dip, prop_op, mod_flags, name,
+ valuep, lengthp, BDPART(dev), bd));
+}
+
+
+static int
+bd_tg_rdwr(dev_info_t *dip, uchar_t cmd, void *bufaddr, diskaddr_t start,
+ size_t length, void *tg_cookie)
+{
+ bd_t *bd;
+ buf_t *bp;
+ bd_xfer_impl_t *xi;
+ int rv;
+ int (*func)(void *, bd_xfer_t *);
+
+ _NOTE(ARGUNUSED(dip));
+
+
+ bd = tg_cookie;
+ if (P2PHASE(length, (1U << bd->d_blkshift)) != 0) {
+ /* We can only transfer whole blocks at a time! */
+ return (EINVAL);
+ }
+
+ bp = getrbuf(KM_SLEEP);
+
+ switch (cmd) {
+ case TG_READ:
+ bp->b_flags = B_READ;
+ func = bd->d_ops.o_read;
+ break;
+ case TG_WRITE:
+ bp->b_flags = B_WRITE;
+ func = bd->d_ops.o_write;
+ break;
+ default:
+ freerbuf(bp);
+ return (EINVAL);
+ }
+
+ bp->b_un.b_addr = bufaddr;
+ bp->b_bcount = length;
+ xi = bd_xfer_alloc(bd, bp, func, KM_SLEEP);
+ if (xi == NULL) {
+ rv = geterror(bp);
+ freerbuf(bp);
+ return (rv);
+ }
+
+ xi->i_blkno = start;
+ bd_submit(bd, xi);
+ (void) biowait(bp);
+ rv = geterror(bp);
+ freerbuf(bp);
+
+ return (rv);
+}
+
+static int
+bd_tg_getinfo(dev_info_t *dip, int cmd, void *arg, void *tg_cookie)
+{
+ bd_t *bd;
+
+ _NOTE(ARGUNUSED(dip));
+ bd = tg_cookie;
+
+ switch (cmd) {
+ case TG_GETPHYGEOM:
+ case TG_GETVIRTGEOM:
+ /*
+ * We don't have any "geometry" as such, let cmlb
+ * fabricate something.
+ */
+ return (ENOTTY);
+
+ case TG_GETCAPACITY:
+ bd_update_state(bd);
+ *(diskaddr_t *)arg = bd->d_numblks;
+ return (0);
+
+ case TG_GETBLOCKSIZE:
+ *(uint32_t *)arg = (1U << bd->d_blkshift);
+ return (0);
+
+ case TG_GETATTR:
+ /*
+ * It turns out that cmlb really doesn't do much for
+ * non-writable media, but lets make the information
+ * available for it in case it does more in the
+ * future. (The value is currently used for
+ * triggering special behavior for CD-ROMs.)
+ */
+ bd_update_state(bd);
+ ((tg_attribute_t *)arg)->media_is_writable =
+ bd->d_rdonly ? B_FALSE : B_TRUE;
+ return (0);
+
+ default:
+ return (EINVAL);
+ }
+}
+
+
+static void
+bd_sched(bd_t *bd)
+{
+ bd_xfer_impl_t *xi;
+ struct buf *bp;
+ int rv;
+
+ ASSERT(mutex_owned(&bd->d_iomutex));
+
+ while ((bd->d_qactive < bd->d_qsize) &&
+ ((xi = list_remove_head(&bd->d_waitq)) != NULL)) {
+ bd->d_qactive++;
+ kstat_waitq_to_runq(bd->d_kiop);
+ list_insert_tail(&bd->d_runq, xi);
+
+ /* Submit the job to driver */
+ rv = xi->i_func(bd->d_private, &xi->i_public);
+ if (rv != 0) {
+ bd->d_qactive--;
+ kstat_runq_exit(bd->d_kiop);
+ list_remove(&bd->d_runq, xi);
+
+ mutex_exit(&bd->d_iomutex);
+ bp = xi->i_bp;
+ bd_xfer_free(xi);
+ bioerror(bp, rv);
+ biodone(bp);
+ mutex_enter(&bd->d_iomutex);
+ }
+ }
+}
+
+static void
+bd_submit(bd_t *bd, bd_xfer_impl_t *xi)
+{
+ mutex_enter(&bd->d_iomutex);
+ list_insert_tail(&bd->d_waitq, xi);
+ kstat_waitq_enter(bd->d_kiop);
+ bd_sched(bd);
+ mutex_exit(&bd->d_iomutex);
+}
+
+static void
+bd_runq_exit(bd_xfer_impl_t *xi, int err)
+{
+ bd_t *bd = xi->i_bd;
+ buf_t *bp = xi->i_bp;
+
+ ASSERT(mutex_owned(&bd->d_iomutex));
+
+ bd->d_qactive--;
+ kstat_runq_exit(bd->d_kiop);
+ if (err == 0) {
+ if (bp->b_flags & B_READ) {
+ bd->d_kiop->reads++;
+ bd->d_kiop->nread += (bp->b_bcount - xi->i_resid);
+ } else {
+ bd->d_kiop->writes++;
+ bd->d_kiop->nwritten += (bp->b_bcount - xi->i_resid);
+ }
+ }
+ list_remove(&bd->d_runq, xi);
+ bd_sched(bd);
+}
+
+static void
+bd_update_state(bd_t *bd)
+{
+ enum dkio_state state;
+ bd_media_t media;
+ boolean_t docmlb = B_FALSE;
+
+ bzero(&media, sizeof (media));
+
+ mutex_enter(&bd->d_statemutex);
+ if (bd->d_ops.o_media_info(bd->d_private, &media) == 0) {
+ if ((1U << bd->d_blkshift) != media.m_blksize) {
+ if ((media.m_blksize < 512) ||
+ (!ISP2(media.m_blksize)) ||
+ (P2PHASE(bd->d_maxxfer, media.m_blksize))) {
+ cmn_err(CE_WARN,
+ "%s%d: Invalid media block size (%d)",
+ ddi_driver_name(bd->d_dip),
+ ddi_get_instance(bd->d_dip),
+ media.m_blksize);
+ /*
+ * We can't use the media, treat it as
+ * not present.
+ */
+ state = DKIO_EJECTED;
+ bd->d_numblks = 0;
+ } else {
+ bd->d_blkshift = ddi_ffs(media.m_blksize) - 1;
+ bd->d_numblks = media.m_nblks;
+ bd->d_rdonly = media.m_readonly;
+ state = DKIO_INSERTED;
+ }
+
+ /* Device size changed */
+ docmlb = B_TRUE;
+
+ } else {
+ if (bd->d_numblks != media.m_nblks) {
+ /* Device size changed */
+ docmlb = B_TRUE;
+ }
+ bd->d_numblks = media.m_nblks;
+ bd->d_rdonly = media.m_readonly;
+ state = DKIO_INSERTED;
+ }
+
+ } else {
+ bd->d_numblks = 0;
+ state = DKIO_EJECTED;
+ }
+ if (state != bd->d_state) {
+ bd->d_state = state;
+ cv_broadcast(&bd->d_statecv);
+ docmlb = B_TRUE;
+ }
+ mutex_exit(&bd->d_statemutex);
+
+ if (docmlb) {
+ if (state == DKIO_INSERTED) {
+ (void) cmlb_validate(bd->d_cmlbh, 0, bd);
+ } else {
+ cmlb_invalidate(bd->d_cmlbh, bd);
+ }
+ }
+}
+
+static int
+bd_check_state(bd_t *bd, enum dkio_state *state)
+{
+ clock_t when;
+
+ for (;;) {
+
+ bd_update_state(bd);
+
+ mutex_enter(&bd->d_statemutex);
+
+ if (bd->d_state != *state) {
+ *state = bd->d_state;
+ mutex_exit(&bd->d_statemutex);
+ break;
+ }
+
+ when = drv_usectohz(1000000);
+ if (cv_reltimedwait_sig(&bd->d_statecv, &bd->d_statemutex,
+ when, TR_CLOCK_TICK) == 0) {
+ mutex_exit(&bd->d_statemutex);
+ return (EINTR);
+ }
+
+ mutex_exit(&bd->d_statemutex);
+ }
+
+ return (0);
+}
+
+static int
+bd_flush_write_cache_done(struct buf *bp)
+{
+ struct dk_callback *dc = (void *)bp->b_private;
+
+ (*dc->dkc_callback)(dc->dkc_cookie, geterror(bp));
+ kmem_free(dc, sizeof (*dc));
+ freerbuf(bp);
+ return (0);
+}
+
+static int
+bd_flush_write_cache(bd_t *bd, struct dk_callback *dkc)
+{
+ buf_t *bp;
+ struct dk_callback *dc;
+ bd_xfer_impl_t *xi;
+ int rv;
+
+ if (bd->d_ops.o_sync_cache == NULL) {
+ return (ENOTSUP);
+ }
+ if ((bp = getrbuf(KM_SLEEP)) == NULL) {
+ return (ENOMEM);
+ }
+ bp->b_resid = 0;
+ bp->b_bcount = 0;
+
+ xi = bd_xfer_alloc(bd, bp, bd->d_ops.o_sync_cache, KM_SLEEP);
+ if (xi == NULL) {
+ rv = geterror(bp);
+ freerbuf(bp);
+ return (rv);
+ }
+
+ if (dkc != NULL) {
+ /* Make a private copy of the callback structure */
+ dc = kmem_alloc(sizeof (*dc), KM_SLEEP);
+ *dc = *dkc;
+ bp->b_private = dc;
+ bp->b_iodone = bd_flush_write_cache_done;
+ }
+
+ bd_submit(bd, xi);
+ if (dkc == NULL) {
+ /* wait synchronously */
+ (void) biowait(bp);
+ rv = geterror(bp);
+ freerbuf(bp);
+ } else {
+ /* deferred via callback */
+ rv = 0;
+ }
+ return (rv);
+}
+
+/*
+ * Nexus support.
+ */
+int
+bd_bus_ctl(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t ctlop,
+ void *arg, void *result)
+{
+ bd_handle_t hdl;
+
+ switch (ctlop) {
+ case DDI_CTLOPS_REPORTDEV:
+ cmn_err(CE_CONT, "?Block device: %s@%s, %s%d\n",
+ ddi_node_name(rdip), ddi_get_name_addr(rdip),
+ ddi_driver_name(rdip), ddi_get_instance(rdip));
+ return (DDI_SUCCESS);
+
+ case DDI_CTLOPS_INITCHILD:
+ hdl = ddi_get_parent_data((dev_info_t *)arg);
+ if (hdl == NULL) {
+ return (DDI_NOT_WELL_FORMED);
+ }
+ ddi_set_name_addr((dev_info_t *)arg, hdl->h_addr);
+ return (DDI_SUCCESS);
+
+ case DDI_CTLOPS_UNINITCHILD:
+ ddi_set_name_addr((dev_info_t *)arg, NULL);
+ ndi_prop_remove_all((dev_info_t *)arg);
+ return (DDI_SUCCESS);
+
+ default:
+ return (ddi_ctlops(dip, rdip, ctlop, arg, result));
+ }
+}
+
+/*
+ * Functions for device drivers.
+ */
+bd_handle_t
+bd_alloc_handle(void *private, bd_ops_t *ops, ddi_dma_attr_t *dma, int kmflag)
+{
+ bd_handle_t hdl;
+
+ hdl = kmem_zalloc(sizeof (*hdl), kmflag);
+ if (hdl != NULL) {
+ hdl->h_ops = *ops;
+ hdl->h_dma = dma;
+ hdl->h_private = private;
+ }
+
+ return (hdl);
+}
+
+void
+bd_free_handle(bd_handle_t hdl)
+{
+ kmem_free(hdl, sizeof (*hdl));
+}
+
+int
+bd_attach_handle(dev_info_t *dip, bd_handle_t hdl)
+{
+ dev_info_t *child;
+ bd_drive_t drive;
+
+ /* if drivers don't override this, make it assume none */
+ drive.d_lun = -1;
+ hdl->h_ops.o_drive_info(hdl->h_private, &drive);
+
+ hdl->h_parent = dip;
+ hdl->h_name = "blkdev";
+
+ if (drive.d_lun >= 0) {
+ (void) snprintf(hdl->h_addr, sizeof (hdl->h_addr), "%X,%X",
+ drive.d_target, drive.d_lun);
+ } else {
+ (void) snprintf(hdl->h_addr, sizeof (hdl->h_addr), "%X",
+ drive.d_target);
+ }
+ if (ndi_devi_alloc(dip, hdl->h_name, (pnode_t)DEVI_SID_NODEID,
+ &child) != NDI_SUCCESS) {
+ cmn_err(CE_WARN, "%s%d: unable to allocate node %s@%s",
+ ddi_driver_name(dip), ddi_get_instance(dip),
+ "blkdev", hdl->h_addr);
+ return (DDI_FAILURE);
+ }
+
+ ddi_set_parent_data(child, hdl);
+ hdl->h_child = child;
+
+ if (ndi_devi_online(child, 0) == NDI_FAILURE) {
+ cmn_err(CE_WARN, "%s%d: failed bringing node %s@%s online",
+ ddi_driver_name(dip), ddi_get_instance(dip),
+ hdl->h_name, hdl->h_addr);
+ (void) ndi_devi_free(child);
+ return (DDI_FAILURE);
+ }
+
+ return (DDI_SUCCESS);
+}
+
+int
+bd_detach_handle(bd_handle_t hdl)
+{
+ int circ;
+ int rv;
+ char *devnm;
+
+ if (hdl->h_child == NULL) {
+ return (DDI_SUCCESS);
+ }
+ ndi_devi_enter(hdl->h_parent, &circ);
+ if (i_ddi_node_state(hdl->h_child) < DS_INITIALIZED) {
+ rv = ddi_remove_child(hdl->h_child, 0);
+ } else {
+ devnm = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
+ (void) ddi_deviname(hdl->h_child, devnm);
+ (void) devfs_clean(hdl->h_parent, devnm + 1, DV_CLEAN_FORCE);
+ rv = ndi_devi_unconfig_one(hdl->h_parent, devnm + 1, NULL,
+ NDI_DEVI_REMOVE | NDI_UNCONFIG);
+ kmem_free(devnm, MAXNAMELEN + 1);
+ }
+ if (rv == 0) {
+ hdl->h_child = NULL;
+ }
+
+ ndi_devi_exit(hdl->h_parent, circ);
+ return (rv = NDI_SUCCESS ? DDI_SUCCESS : DDI_FAILURE);
+}
+
+void
+bd_xfer_done(bd_xfer_t *xfer, int err)
+{
+ bd_xfer_impl_t *xi = (void *)xfer;
+ buf_t *bp = xi->i_bp;
+ int rv;
+ bd_t *bd = xi->i_bd;
+ size_t len;
+
+ mutex_enter(&bd->d_iomutex);
+ if (err != 0) {
+ bd_runq_exit(xi, err);
+ mutex_exit(&bd->d_iomutex);
+
+ bp->b_resid += xi->i_resid;
+ bd_xfer_free(xi);
+ bioerror(bp, err);
+ biodone(bp);
+ return;
+ }
+
+ xi->i_cur_win++;
+ xi->i_resid -= xi->i_len;
+
+ if (xi->i_resid == 0) {
+ /* Job completed succcessfully! */
+ bd_runq_exit(xi, 0);
+ mutex_exit(&bd->d_iomutex);
+
+ bd_xfer_free(xi);
+ biodone(bp);
+ return;
+ }
+
+ xi->i_blkno += xi->i_nblks;
+
+ if (bd->d_use_dma) {
+ /* More transfer still pending... advance to next DMA window. */
+ rv = ddi_dma_getwin(xi->i_dmah, xi->i_cur_win,
+ &xi->i_offset, &len, &xi->i_dmac, &xi->i_ndmac);
+ } else {
+ /* Advance memory window. */
+ xi->i_kaddr += xi->i_len;
+ xi->i_offset += xi->i_len;
+ len = min(bp->b_bcount - xi->i_offset, bd->d_maxxfer);
+ }
+
+
+ if ((rv != DDI_SUCCESS) ||
+ (P2PHASE(len, (1U << xi->i_blkshift) != 0))) {
+ bd_runq_exit(xi, EFAULT);
+ mutex_exit(&bd->d_iomutex);
+
+ bp->b_resid += xi->i_resid;
+ bd_xfer_free(xi);
+ bioerror(bp, EFAULT);
+ biodone(bp);
+ return;
+ }
+ xi->i_len = len;
+ xi->i_nblks = len >> xi->i_blkshift;
+
+ /* Submit next window to hardware. */
+ rv = xi->i_func(bd->d_private, &xi->i_public);
+ if (rv != 0) {
+ bd_runq_exit(xi, rv);
+ mutex_exit(&bd->d_iomutex);
+
+ bp->b_resid += xi->i_resid;
+ bd_xfer_free(xi);
+ bioerror(bp, rv);
+ biodone(bp);
+ return;
+ }
+
+ mutex_exit(&bd->d_iomutex);
+}
+
+void
+bd_state_change(bd_handle_t hdl)
+{
+ bd_t *bd;
+
+ if ((bd = hdl->h_bd) != NULL) {
+ bd_update_state(bd);
+ }
+}
+
+void
+bd_mod_init(struct dev_ops *devops)
+{
+ static struct bus_ops bd_bus_ops = {
+ BUSO_REV, /* busops_rev */
+ nullbusmap, /* bus_map */
+ NULL, /* bus_get_intrspec (OBSOLETE) */
+ NULL, /* bus_add_intrspec (OBSOLETE) */
+ NULL, /* bus_remove_intrspec (OBSOLETE) */
+ i_ddi_map_fault, /* bus_map_fault */
+ ddi_dma_map, /* bus_dma_map */
+ ddi_dma_allochdl, /* bus_dma_allochdl */
+ ddi_dma_freehdl, /* bus_dma_freehdl */
+ ddi_dma_bindhdl, /* bus_dma_bindhdl */
+ ddi_dma_unbindhdl, /* bus_dma_unbindhdl */
+ ddi_dma_flush, /* bus_dma_flush */
+ ddi_dma_win, /* bus_dma_win */
+ ddi_dma_mctl, /* bus_dma_ctl */
+ bd_bus_ctl, /* bus_ctl */
+ ddi_bus_prop_op, /* bus_prop_op */
+ NULL, /* bus_get_eventcookie */
+ NULL, /* bus_add_eventcall */
+ NULL, /* bus_remove_eventcall */
+ NULL, /* bus_post_event */
+ NULL, /* bus_intr_ctl (OBSOLETE) */
+ NULL, /* bus_config */
+ NULL, /* bus_unconfig */
+ NULL, /* bus_fm_init */
+ NULL, /* bus_fm_fini */
+ NULL, /* bus_fm_access_enter */
+ NULL, /* bus_fm_access_exit */
+ NULL, /* bus_power */
+ NULL, /* bus_intr_op */
+ };
+
+ devops->devo_bus_ops = &bd_bus_ops;
+
+ /*
+ * NB: The device driver is free to supply its own
+ * character entry device support.
+ */
+}
+
+void
+bd_mod_fini(struct dev_ops *devops)
+{
+ devops->devo_bus_ops = NULL;
+}
--- a/usr/src/uts/common/io/scsi/adapters/blk2scsa/blk2scsa.c Tue May 18 11:19:39 2010 +0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2005 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#include <sys/types.h>
-#include <sys/ksynch.h>
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-#include <sys/note.h>
-#include <sys/scsi/scsi.h>
-#include <sys/scsi/adapters/blk2scsa.h>
-
-/*
- * We implement the following SCSI-2 commands on behalf of targets:
- *
- * SCMD_DOORLOCK
- * SCMD_FORMAT
- * SCMD_INQUIRY
- * SCMD_MODE_SENSE
- * SCMD_READ
- * SCMD_READ_G1
- * SCMD_READ_CAPACITY
- * SCMD_RELEASE
- * SCMD_REQUEST_SENSE
- * SCMD_RESERVE
- * SCMD_SDIAG
- * SCMD_START_STOP
- * SCMD_TEST_UNIT_READY
- * SCMD_WRITE
- * SCMD_WRITE_G1
- *
- * We really should, at some point in the future, investigate offering
- * more complete SCSI-3 commands, including the G4 and G5 variants of
- * READ and WRITE, MODE_SELECT, PERSISTENT_RESERVE_IN,
- * PERSISTENT_RESERVE_OUT, SYNCHRONIZE_CACHE, READ_MEDIAL_SERIAL,
- * REPORT_LUNS, etc.
- */
-
-typedef struct b2s_request_impl b2s_request_impl_t;
-
-struct b2s_request_impl {
- b2s_request_t ri_public;
- struct scsi_pkt *ri_pkt;
- struct scsi_arq_status *ri_sts;
- buf_t *ri_bp;
-
- size_t ri_resid;
- b2s_nexus_t *ri_nexus;
- b2s_leaf_t *ri_leaf;
- void (*ri_done)(struct b2s_request_impl *);
-};
-
-#define ri_lun ri_public.br_lun
-#define ri_target ri_public.br_target
-#define ri_cmd ri_public.br_cmd
-#define ri_errno ri_public.br_errno
-#define ri_count ri_public.br_count
-#define ri_xfered ri_public.br_xfered
-
-#define ri_flags ri_public.br_flags
-#define ri_media ri_public.br_media
-#define ri_inquiry ri_public.br_inquiry
-#define ri_lba ri_public.br_lba
-#define ri_nblks ri_public.br_nblks
-
-struct b2s_nexus {
- dev_info_t *n_dip;
- struct scsi_hba_tran *n_tran;
- void *n_private;
- ddi_dma_attr_t *n_dma;
- boolean_t (*n_request)(void *, b2s_request_t *);
-
- kmutex_t n_lock;
- kcondvar_t n_cv;
- boolean_t n_attached;
- list_t n_leaves;
-};
-#define B2S_NEXUS_ATTACHED (1U << 0)
-
-_NOTE(MUTEX_PROTECTS_DATA(b2s_nexus::n_lock, b2s_nexus::n_leaves))
-_NOTE(SCHEME_PROTECTS_DATA("stable data", b2s_nexus::n_dip))
-_NOTE(SCHEME_PROTECTS_DATA("stable data", b2s_nexus::n_private))
-_NOTE(SCHEME_PROTECTS_DATA("stable data", b2s_nexus::n_request))
-_NOTE(SCHEME_PROTECTS_DATA("stable data", b2s_nexus::n_dma))
-_NOTE(SCHEME_PROTECTS_DATA("stable data", b2s_nexus::n_tran))
-_NOTE(SCHEME_PROTECTS_DATA("client synchronized", b2s_nexus::n_attached))
-
-struct b2s_leaf {
- b2s_nexus_t *l_nexus;
- uint_t l_target;
- uint_t l_lun;
- uint32_t l_flags;
- char *l_uuid;
- uint32_t l_refcnt;
- list_node_t l_node;
- struct scsi_inquiry l_inq;
- uint64_t l_eui;
-};
-
-_NOTE(MUTEX_PROTECTS_DATA(b2s_nexus::n_lock, b2s_leaf::l_node))
-_NOTE(MUTEX_PROTECTS_DATA(b2s_nexus::n_lock, b2s_leaf::l_refcnt))
-_NOTE(MUTEX_PROTECTS_DATA(b2s_nexus::n_lock, b2s_leaf::l_uuid))
-_NOTE(MUTEX_PROTECTS_DATA(b2s_nexus::n_lock, b2s_leaf::l_lun))
-_NOTE(MUTEX_PROTECTS_DATA(b2s_nexus::n_lock, b2s_leaf::l_target))
-_NOTE(MUTEX_PROTECTS_DATA(b2s_nexus::n_lock, b2s_leaf::l_nexus))
-_NOTE(DATA_READABLE_WITHOUT_LOCK(b2s_leaf::l_uuid))
-_NOTE(DATA_READABLE_WITHOUT_LOCK(b2s_leaf::l_lun))
-_NOTE(DATA_READABLE_WITHOUT_LOCK(b2s_leaf::l_target))
-_NOTE(DATA_READABLE_WITHOUT_LOCK(b2s_leaf::l_nexus))
-
-_NOTE(SCHEME_PROTECTS_DATA("stable data", scsi_hba_tran))
-_NOTE(SCHEME_PROTECTS_DATA("unshared data", b2s_request_impl))
-_NOTE(SCHEME_PROTECTS_DATA("unique per packet", scsi_arq_status))
-_NOTE(SCHEME_PROTECTS_DATA("unique per packet", scsi_pkt))
-_NOTE(SCHEME_PROTECTS_DATA("unique per packet", scsi_inquiry))
-_NOTE(SCHEME_PROTECTS_DATA("client synchronized", b2s_leaf::l_flags))
-
-/*
- * This copies a string into a target buf, obeying the size limits
- * of the target. It does not null terminate, ever.
- */
-#define COPYSTR(src, dst) bcopy(src, dst, min(strlen(src), sizeof (dst)))
-
-/*
- * Thank you SCSA, for making it a PITA to deal with a single byte
- * value by turning it into a bitfield!
- */
-#define PUTSTAT(dst, val) (*((uint8_t *)(void *)&dst) = val)
-
-struct b2s_error {
- uint8_t e_reason; /* scsi CMD_xxx reason */
- uint8_t e_status; /* scsi STATUS_xxx code */
- uint8_t e_skey; /* sense key */
- uint8_t e_asc; /* additional sense code */
- uint8_t e_ascq; /* sense code qualifier */
- uint8_t e_sksv[3]; /* sense key specific-value */
-};
-
-static struct b2s_error b2s_errs[B2S_NERRS];
-
-static struct modlmisc modlmisc = {
- &mod_miscops,
- "SCSA Block Device Emulation",
-};
-
-static struct modlinkage modlinkage = {
- MODREV_1, { &modlmisc, NULL }
-};
-
-/*
- * For layers that don't provide a DMA attribute, we offer a default
- * one. Such devices probably just want to do mapin, all of the time,
- * but since SCSI doesn't give us a way to indicate that, we have to
- * provide a fake attribute. Slightly wasteful, but PIO-only disk
- * devices are going to have some performance issues anyway.
- *
- * For such devices, we only want to commit to transferring 64K at a time,
- * and let the SCSA layer break it up for us.
- */
-static struct ddi_dma_attr b2s_default_dma_attr = {
- DMA_ATTR_V0,
- 0, /* lo address */
- 0xffffffffffffffffULL, /* high address */
- 0xffffU, /* DMA counter max */
- 1, /* alignment */
- 0x0c, /* burst sizes */
- 1, /* minimum transfer size */
- 0xffffU, /* maximum transfer size */
- 0xffffU, /* maximum segment size */
- 1, /* scatter/gather list length */
- 1, /* granularity */
- 0 /* DMA flags */
-};
-
-
-/*
- * Private prototypes.
- */
-
-static int b2s_tran_tgt_init(dev_info_t *, dev_info_t *,
- scsi_hba_tran_t *, struct scsi_device *);
-static void b2s_tran_tgt_free(dev_info_t *, dev_info_t *,
- scsi_hba_tran_t *, struct scsi_device *);
-static int b2s_tran_getcap(struct scsi_address *, char *, int);
-static int b2s_tran_setcap(struct scsi_address *, char *, int, int);
-static void b2s_tran_destroy_pkt(struct scsi_address *, struct scsi_pkt *);
-static struct scsi_pkt *b2s_tran_init_pkt(struct scsi_address *,
- struct scsi_pkt *, struct buf *, int, int, int, int,
- int (*)(caddr_t), caddr_t);
-static int b2s_tran_start(struct scsi_address *, struct scsi_pkt *);
-static int b2s_tran_abort(struct scsi_address *, struct scsi_pkt *);
-static int b2s_tran_reset(struct scsi_address *, int);
-static int b2s_bus_config(dev_info_t *, uint_t, ddi_bus_config_op_t, void *,
- dev_info_t **);
-static b2s_leaf_t *b2s_hold_leaf(b2s_nexus_t *, uint_t, uint_t);
-static dev_info_t *b2s_find_node(b2s_nexus_t *, b2s_leaf_t *);
-static int b2s_create_node(b2s_nexus_t *, b2s_leaf_t *, dev_info_t **);
-static int b2s_update_props(dev_info_t *, b2s_leaf_t *, char **, int);
-static void b2s_inquiry_done(b2s_request_impl_t *);
-static int b2s_inquiry(b2s_leaf_t *);
-static void b2s_init_err_table(void);
-static int b2s_scmd_inq(b2s_request_impl_t *);
-static int b2s_scmd_tur(b2s_request_impl_t *);
-static int b2s_scmd_doorlock(b2s_request_impl_t *);
-static int b2s_scmd_format(b2s_request_impl_t *);
-static int b2s_scmd_readcap(b2s_request_impl_t *);
-static int b2s_scmd_rw(b2s_request_impl_t *);
-static int b2s_scmd_rqs(b2s_request_impl_t *);
-static int b2s_scmd_sdiag(b2s_request_impl_t *);
-static int b2s_scmd_start_stop(b2s_request_impl_t *);
-static int b2s_scmd_mode_sense(b2s_request_impl_t *);
-static int b2s_scmd_reserve_release(b2s_request_impl_t *);
-static void b2s_scmd_readcap_done(b2s_request_impl_t *);
-static void b2s_scmd_mode_sense_done(b2s_request_impl_t *);
-static void b2s_warn(b2s_leaf_t *, const char *, ...);
-
-int
-_init(void)
-{
- int rv;
-
- b2s_init_err_table();
- rv = mod_install(&modlinkage);
- return (rv);
-}
-
-int
-_fini(void)
-{
- int rv;
-
- rv = mod_remove(&modlinkage);
- return (rv);
-}
-
-int
-_info(struct modinfo *modinfop)
-{
- return (mod_info(&modlinkage, modinfop));
-}
-
-int
-b2s_mod_init(struct modlinkage *modlp)
-{
- return (scsi_hba_init(modlp));
-}
-
-void
-b2s_mod_fini(struct modlinkage *modlp)
-{
- scsi_hba_fini(modlp);
-}
-
-void
-b2s_init_err_table(void)
-{
- int i;
-
- /* fill up most of them with defaults */
- for (i = 0; i < B2S_NERRS; i++) {
- b2s_errs[i].e_reason = CMD_CMPLT;
- b2s_errs[i].e_status = STATUS_CHECK;
- b2s_errs[i].e_skey = KEY_NO_SENSE;
- b2s_errs[i].e_asc = 0;
- b2s_errs[i].e_ascq = 0;
- b2s_errs[i].e_sksv[0] = 0;
- b2s_errs[i].e_sksv[1] = 0;
- b2s_errs[i].e_sksv[2] = 0;
- }
-
- /* now flesh out real values */
- b2s_errs[B2S_EOK].e_status = STATUS_GOOD;
-
- b2s_errs[B2S_ENOTSUP].e_skey = KEY_ILLEGAL_REQUEST;
- b2s_errs[B2S_ENOTSUP].e_asc = 0x20;
-
- b2s_errs[B2S_EFORMATTING].e_skey = KEY_NOT_READY;
- b2s_errs[B2S_EFORMATTING].e_asc = 0x04;
- b2s_errs[B2S_EFORMATTING].e_ascq = 0x04;
- b2s_errs[B2S_EFORMATTING].e_sksv[0] = 0x80;
-
- b2s_errs[B2S_ENOMEDIA].e_skey = KEY_NOT_READY;
- b2s_errs[B2S_ENOMEDIA].e_asc = 0x3A;
-
- b2s_errs[B2S_EMEDIACHG].e_skey = KEY_UNIT_ATTENTION;
- b2s_errs[B2S_EMEDIACHG].e_asc = 0x28;
-
- b2s_errs[B2S_ESTOPPED].e_skey = KEY_NOT_READY;
- b2s_errs[B2S_ESTOPPED].e_asc = 0x04;
- b2s_errs[B2S_ESTOPPED].e_ascq = 0x02;
-
- b2s_errs[B2S_EBLKADDR].e_skey = KEY_ILLEGAL_REQUEST;
- b2s_errs[B2S_EBLKADDR].e_asc = 0x21;
-
- b2s_errs[B2S_EIO].e_skey = KEY_HARDWARE_ERROR;
- b2s_errs[B2S_EIO].e_asc = 0x08;
- b2s_errs[B2S_EIO].e_ascq = 0x00;
-
- b2s_errs[B2S_EHARDWARE].e_skey = KEY_HARDWARE_ERROR;
- b2s_errs[B2S_EHARDWARE].e_asc = 0x44;
-
- b2s_errs[B2S_ENODEV].e_reason = CMD_DEV_GONE;
-
- b2s_errs[B2S_EMEDIA].e_skey = KEY_MEDIUM_ERROR;
-
- b2s_errs[B2S_EDOORLOCK].e_skey = KEY_NOT_READY;
- b2s_errs[B2S_EDOORLOCK].e_asc = 0x53;
- b2s_errs[B2S_EDOORLOCK].e_ascq = 0x02;
-
- b2s_errs[B2S_EWPROTECT].e_skey = KEY_DATA_PROTECT;
- b2s_errs[B2S_EWPROTECT].e_asc = 0x27;
-
- b2s_errs[B2S_ESTARTING].e_skey = KEY_NOT_READY;
- b2s_errs[B2S_ESTARTING].e_asc = 0x04;
- b2s_errs[B2S_ESTARTING].e_ascq = 0x01;
-
- b2s_errs[B2S_ETIMEDOUT].e_skey = KEY_ABORTED_COMMAND;
- b2s_errs[B2S_ETIMEDOUT].e_asc = 0x08;
- b2s_errs[B2S_ETIMEDOUT].e_ascq = 0x01;
-
- /*
- * This one, SYSTEM_RESOURCE_FAILURE, is not really legal for
- * DTYPE_DIRECT in SCSI-2, but sd doesn't care, and reporting
- * it this way may help diagnosis. sd will retry it in any
- * case.
- */
- b2s_errs[B2S_ENOMEM].e_skey = KEY_ABORTED_COMMAND;
- b2s_errs[B2S_ENOMEM].e_asc = 0x55;
-
- b2s_errs[B2S_ERESET].e_reason = CMD_RESET;
-
- b2s_errs[B2S_EABORT].e_reason = CMD_ABORTED;
-
- b2s_errs[B2S_ERSVD].e_status = STATUS_RESERVATION_CONFLICT;
-
- b2s_errs[B2S_EINVAL].e_skey = KEY_ILLEGAL_REQUEST;
- b2s_errs[B2S_EINVAL].e_asc = 0x24;
-
- b2s_errs[B2S_EPARAM].e_skey = KEY_ILLEGAL_REQUEST;
- b2s_errs[B2S_EPARAM].e_asc = 0x26;
-
- b2s_errs[B2S_EBADMSG].e_reason = CMD_BADMSG;
-}
-
-/*
- * Locate the the leaf node for the given target/lun. This must be
- * called with the nexus lock held.
- */
-b2s_leaf_t *
-b2s_get_leaf(b2s_nexus_t *n, uint_t target, uint_t lun)
-{
- b2s_leaf_t *l;
-
- ASSERT(mutex_owned(&n->n_lock));
-
- l = list_head(&n->n_leaves);
- while (l != NULL) {
- ASSERT(l->l_nexus == n);
- if ((l->l_target == target) && (l->l_lun == lun)) {
- break;
- }
- l = list_next(&n->n_leaves, l);
- }
-
- return (l);
-}
-
-/*
- * Locate the the leaf node for the given target/lun, and hold it. The
- * nexus lock must *NOT* be held.
- */
-b2s_leaf_t *
-b2s_hold_leaf(b2s_nexus_t *n, uint_t target, uint_t lun)
-{
- b2s_leaf_t *l;
-
- mutex_enter(&n->n_lock);
- l = b2s_get_leaf(n, target, lun);
- if (l != NULL) {
- l->l_refcnt++;
- }
- mutex_exit(&n->n_lock);
- return (l);
-}
-
-/*
- * Drop the hold on the leaf.
- */
-void
-b2s_rele_leaf(b2s_leaf_t *l)
-{
- b2s_nexus_t *n = l->l_nexus;
- mutex_enter(&n->n_lock);
- l->l_refcnt--;
- if (l->l_refcnt == 0) {
- list_remove(&n->n_leaves, l);
- kmem_free(l->l_uuid, strlen(l->l_uuid) + 1);
- kmem_free(l, sizeof (*l));
- }
- mutex_exit(&n->n_lock);
-}
-
-/*
- * This is used to walk the list of leaves safely, without requiring the
- * nexus lock to be held. The returned leaf is held. (If the passed in
- * lastl is not NULL, then it is released as well.)
- *
- * Pass NULL for lastl to start the walk.
- */
-b2s_leaf_t *
-b2s_next_leaf(b2s_nexus_t *n, b2s_leaf_t *lastl)
-{
- b2s_leaf_t *l;
-
- mutex_enter(&n->n_lock);
- if (lastl == NULL) {
- l = list_head(&n->n_leaves);
- } else {
- l = list_next(&n->n_leaves, lastl);
- }
- if (l != NULL) {
- l->l_refcnt++;
- }
- mutex_exit(&n->n_lock);
-
- if (lastl != NULL) {
- b2s_rele_leaf(lastl);
- }
-
- return (l);
-}
-
-void
-b2s_request_mapin(b2s_request_t *req, caddr_t *addrp, size_t *lenp)
-{
- b2s_request_impl_t *ri = (void *)req;
- buf_t *bp;
-
- if (((bp = ri->ri_bp) != NULL) && (bp->b_bcount != 0)) {
- *addrp = bp->b_un.b_addr;
- *lenp = bp->b_bcount;
- } else {
- *addrp = 0;
- *lenp = 0;
- }
-}
-
-void
-b2s_request_dma(b2s_request_t *req, uint_t *ndmacp, ddi_dma_cookie_t **dmacsp)
-{
- /*
- * Direct DMA support was removed; SCSA can't easily deal with
- * HBAs that have restrictions which would require partial DMA
- * to be used.
- */
- _NOTE(ARGUNUSED(req));
-
- *ndmacp = 0;
- *dmacsp = NULL;
-}
-
-void
-b2s_request_done_pkt(b2s_request_impl_t *ri)
-{
- struct scsi_pkt *pkt;
- uint8_t status;
- struct scsi_arq_status *sts = ri->ri_sts;
- b2s_err_t err;
-
- err = ri->ri_errno;
-
- pkt = ri->ri_pkt;
- pkt->pkt_resid = ri->ri_resid;
-
- bzero(sts, sizeof (*sts));
-
- /*
- * Make sure that the status is in range of our known errs. If we
- * don't know it, then just cobble up a bogus one.
- */
- if ((err < 0) || (err >= B2S_NERRS)) {
- pkt->pkt_reason = CMD_TRAN_ERR;
- } else {
- pkt->pkt_reason = b2s_errs[err].e_reason;
- status = b2s_errs[err].e_status;
- }
-
- if (pkt->pkt_reason == CMD_CMPLT) {
-
- pkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
- STATE_SENT_CMD | STATE_GOT_STATUS;
-
- PUTSTAT(sts->sts_status, status);
-
- if (status == STATUS_CHECK) {
- /*
- * Contingent allegiance. We need to do the
- * ARQ thing.
- */
- PUTSTAT(sts->sts_rqpkt_status, STATUS_GOOD);
-
- sts->sts_rqpkt_reason = CMD_CMPLT;
- sts->sts_rqpkt_resid = 0;
- sts->sts_rqpkt_state = STATE_XFERRED_DATA |
- STATE_GOT_BUS | STATE_GOT_STATUS;
-
- sts->sts_sensedata.es_valid = 1;
- sts->sts_sensedata.es_class = CLASS_EXTENDED_SENSE;
- sts->sts_sensedata.es_key = b2s_errs[err].e_skey;
- sts->sts_sensedata.es_add_code = b2s_errs[err].e_asc;
- sts->sts_sensedata.es_qual_code = b2s_errs[err].e_ascq;
- bcopy(sts->sts_sensedata.es_skey_specific,
- b2s_errs[err].e_sksv, 3);
- /*
- * Stash any residue information.
- */
- sts->sts_sensedata.es_info_1 =
- (ri->ri_resid >> 24) & 0xff;
- sts->sts_sensedata.es_info_2 =
- (ri->ri_resid >> 16) & 0xff;
- sts->sts_sensedata.es_info_3 =
- (ri->ri_resid >> 8) & 0xff;
- sts->sts_sensedata.es_info_4 =
- (ri->ri_resid) & 0xff;
-
- pkt->pkt_state |= STATE_ARQ_DONE;
- }
-
- } else if (pkt->pkt_reason == CMD_ABORTED) {
- pkt->pkt_statistics |= STAT_ABORTED;
- } else if (pkt->pkt_reason == CMD_RESET) {
- pkt->pkt_statistics |= STAT_DEV_RESET;
- } else {
- pkt->pkt_state |= STATE_GOT_BUS | STATE_GOT_TARGET |
- STATE_SENT_CMD;
- }
-
- /*
- * N.B.: Obviously not all commands actually have a SCSI
- * DATA-IN or DATA-OUT phase. But it doesn't matter, since
- * sd.c only bothers to look at this flag for request sense
- * traffic, which is always correct within our emulation.
- *
- * We go ahead and set it on all good packets however, since
- * there may in the future be some additional checks to make
- * sure a data transfer occurred. This seems safer (since
- * then sd should examine pkt_resid) rather than leaving it
- * off by default.
- */
- if (ri->ri_errno == 0) {
- pkt->pkt_state |= STATE_XFERRED_DATA;
- }
-
- /*
- * Finally, execute the callback (unless running POLLED)
- */
- if ((pkt->pkt_flags & FLAG_NOINTR) == 0) {
- scsi_hba_pkt_comp(pkt);
- }
-
-}
-
-void
-b2s_request_done(b2s_request_t *req, b2s_err_t err, size_t resid)
-{
- b2s_request_impl_t *ri = (void *)req;
-
- ri->ri_errno = err;
- ri->ri_resid = (ssize_t)resid;
-
- /*
- * Post process... this is used for massaging results into
- * what SCSI wants.
- */
- if (ri->ri_done != NULL)
- ri->ri_done(ri);
-
- /*
- * For SCSI packets, we have special completion handling. For
- * internal requests, we just mark the request done so the caller
- * can free it.
- */
- if (ri->ri_pkt == NULL) {
- b2s_nexus_t *n = ri->ri_nexus;
-
- mutex_enter(&n->n_lock);
- ri->ri_flags |= B2S_REQUEST_FLAG_DONE;
- cv_broadcast(&n->n_cv);
- mutex_exit(&n->n_lock);
- } else {
- b2s_request_done_pkt(ri);
- }
-}
-
-int
-b2s_tran_tgt_init(dev_info_t *hbadip, dev_info_t *tgtdip,
- scsi_hba_tran_t *tran, struct scsi_device *sd)
-{
- uint_t tgt, lun;
- b2s_nexus_t *n;
- b2s_leaf_t *l;
-
- _NOTE(ARGUNUSED(hbadip));
- _NOTE(ARGUNUSED(sd));
-
- /*
- * Lookup the target and lun.
- */
- tgt = (uint_t)ddi_prop_get_int(DDI_DEV_T_ANY, tgtdip,
- DDI_PROP_DONTPASS, "target", -1);
-
- lun = (uint_t)ddi_prop_get_int(DDI_DEV_T_ANY, tgtdip,
- DDI_PROP_DONTPASS, "lun", -1);
-
- n = tran->tran_hba_private;
-
- /*
- * Hold the leaf node as long as the devinfo node is using it.
- */
- l = b2s_hold_leaf(n, tgt, lun);
- if (l == NULL) {
- /*
- * Target node not found on bus.
- */
- return (DDI_FAILURE);
- }
- tran->tran_tgt_private = l;
-
- return (DDI_SUCCESS);
-}
-
-void
-b2s_tran_tgt_free(dev_info_t *hbadip, dev_info_t *tgtdip,
- scsi_hba_tran_t *tran, struct scsi_device *sd)
-{
- b2s_leaf_t *l;
-
- _NOTE(ARGUNUSED(hbadip));
- _NOTE(ARGUNUSED(tgtdip));
- _NOTE(ARGUNUSED(sd));
-
- l = tran->tran_tgt_private;
- ASSERT(l != NULL);
- b2s_rele_leaf(l);
-}
-
-struct scsi_pkt *
-b2s_tran_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt,
- struct buf *bp, int cmdlen, int statuslen, int tgtlen, int flags,
- int (*cb)(caddr_t), caddr_t cbarg)
-{
- dev_info_t *dip;
- scsi_hba_tran_t *tran;
- b2s_request_impl_t *ri;
-
- _NOTE(ARGUNUSED(cbarg));
- _NOTE(ARGUNUSED(flags));
-
- tran = ap->a_hba_tran;
- dip = tran->tran_hba_dip;
-
- /*
- * Unconditional mapin for now, so we will always have kernel
- * virtual addresses to work with.
- */
- if (bp && (bp->b_bcount)) {
- bp_mapin(bp);
- }
-
- if (pkt == NULL) {
- /* we can only support these two kinds of callbacks */
- cb = (cb == SLEEP_FUNC) ? SLEEP_FUNC : NULL_FUNC;
- pkt = scsi_hba_pkt_alloc(dip, ap, cmdlen, statuslen,
- tgtlen, sizeof (b2s_request_impl_t), cb, NULL);
- if (pkt == NULL)
- return (NULL);
-
- ri = pkt->pkt_ha_private;
- ri->ri_pkt = pkt;
- ri->ri_sts = (void *)pkt->pkt_scbp;
- ri->ri_bp = bp;
- }
-
- return (pkt);
-}
-
-void
-b2s_tran_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
-{
- scsi_hba_pkt_free(ap, pkt);
-}
-
-int
-b2s_tran_getcap(struct scsi_address *ap, char *cap, int whom)
-{
- int capid;
-
- _NOTE(ARGUNUSED(ap));
- _NOTE(ARGUNUSED(whom));
-
- capid = scsi_hba_lookup_capstr(cap);
-
- switch (capid) {
- case SCSI_CAP_ARQ:
- case SCSI_CAP_UNTAGGED_QING:
- return (1);
- case SCSI_CAP_DMA_MAX:
- return (65536);
-
- default:
- return (-1);
- }
-}
-
-int
-b2s_tran_abort(struct scsi_address *ap, struct scsi_pkt *pkt)
-{
- b2s_request_impl_t *ri;
- b2s_nexus_t *n = ap->a_hba_tran->tran_hba_private;
- b2s_leaf_t *l = ap->a_hba_tran->tran_tgt_private;
- int err;
-
- /*
- * We can only do the blind abort of all packets. We have
- * no way to request an individual packet be aborted.
- */
- if (pkt != NULL) {
- return (B_FALSE);
- }
-
- ri = kmem_zalloc(sizeof (*ri), KM_NOSLEEP);
- if (ri == NULL) {
- return (B_FALSE);
- }
- ri->ri_cmd = B2S_CMD_ABORT;
- ri->ri_target = l->l_target;
- ri->ri_lun = l->l_lun;
- ri->ri_flags = B2S_REQUEST_FLAG_HEAD;
- ri->ri_leaf = l;
- ri->ri_nexus = n;
- /* leave all else null */
-
- /*
- * Submit request to device driver.
- */
- if (!n->n_request(n->n_private, &ri->ri_public)) {
- /* this shouldn't happen, since we are just starting out */
- b2s_warn(l, "Busy trying to abort");
- kmem_free(ri, sizeof (*ri));
- return (B_FALSE);
- }
-
- /*
- * Wait for command completion.
- */
- mutex_enter(&n->n_lock);
- while ((ri->ri_flags & B2S_REQUEST_FLAG_DONE) == 0)
- cv_wait(&n->n_cv, &n->n_lock);
- mutex_exit(&n->n_lock);
-
- err = ri->ri_errno;
- kmem_free(ri, sizeof (*ri));
-
- if (err != 0) {
- b2s_warn(l, "Failed during abort (error %d)", err);
- return (B_FALSE);
- }
-
- return (B_TRUE);
-}
-
-int
-b2s_tran_reset(struct scsi_address *ap, int level)
-{
- b2s_request_impl_t *ri;
- b2s_nexus_t *n = ap->a_hba_tran->tran_hba_private;
- b2s_leaf_t *l = ap->a_hba_tran->tran_tgt_private;
- int err;
-
- if (level == RESET_LUN) {
- return (B_FALSE);
- }
-
- ri = kmem_zalloc(sizeof (*ri), KM_NOSLEEP);
- if (ri == NULL) {
- return (B_FALSE);
- }
- ri->ri_cmd = B2S_CMD_RESET;
- ri->ri_target = l->l_target;
- ri->ri_lun = l->l_lun;
- ri->ri_flags = B2S_REQUEST_FLAG_HEAD;
- ri->ri_leaf = l;
- ri->ri_nexus = n;
- /* leave all else null */
-
- /*
- * Submit request to device driver.
- */
- if (!n->n_request(n->n_private, &ri->ri_public)) {
- /* this shouldn't happen, since we are just starting out */
- b2s_warn(l, "Busy trying to reset");
- kmem_free(ri, sizeof (*ri));
- return (B_FALSE);
- }
-
- /*
- * Wait for command completion.
- */
- mutex_enter(&n->n_lock);
- while ((ri->ri_flags & B2S_REQUEST_FLAG_DONE) == 0)
- cv_wait(&n->n_cv, &n->n_lock);
- mutex_exit(&n->n_lock);
-
- err = ri->ri_errno;
- kmem_free(ri, sizeof (*ri));
-
- if (err != 0) {
- b2s_warn(l, "Failed during reset (error %d)", err);
- return (B_FALSE);
- }
-
- return (B_TRUE);
-}
-
-int
-b2s_tran_setcap(struct scsi_address *ap, char *cap, int val, int whom)
-{
- int capid;
-
- _NOTE(ARGUNUSED(ap));
- _NOTE(ARGUNUSED(val));
- _NOTE(ARGUNUSED(whom));
-
- capid = scsi_hba_lookup_capstr(cap);
-
- switch (capid) {
- case SCSI_CAP_ARQ:
- if (val == 0) {
- return (0);
- } else {
- return (1);
- }
-
- default:
- return (-1);
- }
-}
-
-int
-b2s_tran_start(struct scsi_address *ap, struct scsi_pkt *pkt)
-{
- b2s_request_impl_t *ri = pkt->pkt_ha_private;
- b2s_nexus_t *n = ap->a_hba_tran->tran_hba_private;
- b2s_leaf_t *l = ap->a_hba_tran->tran_tgt_private;
-
- ri->ri_errno = B2S_EOK;
- ri->ri_resid = 0;
- bzero(&ri->ri_public.br_args, sizeof (ri->ri_public.br_args));
- ri->ri_flags = 0;
- ri->ri_done = NULL;
-
- if ((n == NULL) || (l == NULL) ||
- ((l->l_flags & B2S_LEAF_DETACHED) != 0)) {
- /*
- * Leaf is not on the bus!
- *
- * We should add support for inquiry when lun != 0,
- * even if when the lun does not exist, but lun 0 is
- * present. But, it turns out this is not strictly
- * required by sd(7d).
- */
- b2s_request_done(&ri->ri_public, B2S_ENODEV, 0);
- return (TRAN_ACCEPT);
- }
-
- ri->ri_nexus = n;
- ri->ri_leaf = l;
- ri->ri_target = l->l_target;
- ri->ri_lun = l->l_lun;
-
- if (pkt->pkt_flags & FLAG_NOINTR)
- ri->ri_flags |= B2S_REQUEST_FLAG_POLL;
- if (pkt->pkt_flags & FLAG_HEAD)
- ri->ri_flags |= B2S_REQUEST_FLAG_HEAD;
-
- switch (pkt->pkt_cdbp[0]) {
- case SCMD_DOORLOCK:
- return (b2s_scmd_doorlock(ri));
-
- case SCMD_FORMAT:
- return (b2s_scmd_format(ri));
-
- case SCMD_INQUIRY:
- return (b2s_scmd_inq(ri));
-
- case SCMD_REQUEST_SENSE:
- return (b2s_scmd_rqs(ri));
-
- case SCMD_SDIAG:
- return (b2s_scmd_sdiag(ri));
-
- case SCMD_TEST_UNIT_READY:
- return (b2s_scmd_tur(ri));
-
- case SCMD_READ_CAPACITY:
- return (b2s_scmd_readcap(ri));
-
- case SCMD_RELEASE:
- case SCMD_RESERVE:
- return (b2s_scmd_reserve_release(ri));
-
- case SCMD_START_STOP:
- return (b2s_scmd_start_stop(ri));
-
- case SCMD_MODE_SENSE:
- return (b2s_scmd_mode_sense(ri));
-
- case SCMD_READ:
- case SCMD_READ_G1:
- case SCMD_WRITE:
- case SCMD_WRITE_G1:
- return (b2s_scmd_rw(ri));
-
- default:
- b2s_request_done(&ri->ri_public, B2S_ENOTSUP, 0);
- return (TRAN_ACCEPT);
- }
-}
-
-/*
- * Publish standard properties on a newly created devinfo node.
- */
-int
-b2s_update_props(dev_info_t *dip, b2s_leaf_t *l, char **compat, int ncompat)
-{
- if (ndi_prop_update_int(DDI_DEV_T_NONE, dip, "target", l->l_target) !=
- DDI_PROP_SUCCESS) {
- return (DDI_FAILURE);
- }
- if (ndi_prop_update_int(DDI_DEV_T_NONE, dip, "lun", l->l_lun) !=
- DDI_PROP_SUCCESS) {
- return (DDI_FAILURE);
- }
- if (ndi_prop_update_int(DDI_DEV_T_NONE, dip, "pm-capable", 1) !=
- DDI_PROP_SUCCESS) {
- return (DDI_FAILURE);
- }
- if (ndi_prop_update_string_array(DDI_DEV_T_NONE, dip, "compatible",
- compat, ncompat) != DDI_PROP_SUCCESS) {
- return (DDI_FAILURE);
- }
- if (ndi_prop_update_string(DDI_DEV_T_NONE, dip, "unique-id",
- l->l_uuid) != DDI_PROP_SUCCESS) {
- return (DDI_FAILURE);
- }
-
- if (l->l_flags & B2S_LEAF_HOTPLUGGABLE) {
- if (ndi_prop_create_boolean(DDI_DEV_T_NONE, dip,
- "hotpluggable") != DDI_PROP_SUCCESS) {
- return (DDI_FAILURE);
- }
- }
-
- return (DDI_SUCCESS);
-}
-
-/*
- * Find the devinfo node associated with the leaf, looking up by target and
- * lun. (Alternatively in the future we could use a full address)
- *
- * This must be called with the tree lock held.
- */
-dev_info_t *
-b2s_find_node(b2s_nexus_t *n, b2s_leaf_t *l)
-{
- dev_info_t *dip;
- int tgt, lun;
-
- dip = ddi_get_child(n->n_dip);
- while (dip != NULL) {
-
- tgt = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
- DDI_PROP_DONTPASS, "target", -1);
-
- lun = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
- DDI_PROP_DONTPASS, "lun", -1);
-
- /* is this the right target */
- if ((lun == l->l_lun) && (tgt == l->l_target)) {
- return (dip);
- }
-
- dip = ddi_get_next_sibling(dip);
- }
-
- return (NULL);
-
-}
-
-/*
- * Create and attach a devinfo node for the supplied nexus/leaf
- * combination.
- */
-int
-b2s_create_node(b2s_nexus_t *n, b2s_leaf_t *l, dev_info_t **dipp)
-{
- dev_info_t *dip;
- char *name;
- char **compat;
- int ncompat;
- int rv;
-
- /*
- * If the node was already created, then we're done.
- */
- if ((dip = b2s_find_node(n, l)) != NULL) {
- if (dipp)
- *dipp = dip;
- return (DDI_SUCCESS);
- }
-
- ASSERT(l != NULL);
-
- /*
- * Perform an inquiry to collect key information.
- */
- if (b2s_inquiry(l) != DDI_SUCCESS) {
- return (DDI_FAILURE);
- }
-
- scsi_hba_nodename_compatible_get(&l->l_inq, NULL, l->l_inq.inq_dtype,
- NULL, &name, &compat, &ncompat);
-
- if (ndi_devi_alloc(n->n_dip, name, DEVI_SID_NODEID, &dip) !=
- NDI_SUCCESS) {
- scsi_hba_nodename_compatible_free(name, compat);
- b2s_warn(l, "Unable to create devinfo node");
- return (DDI_FAILURE);
- }
-
- if (b2s_update_props(dip, l, compat, ncompat) != DDI_SUCCESS) {
- scsi_hba_nodename_compatible_free(name, compat);
- ndi_prop_remove_all(dip);
- (void) ndi_devi_free(dip);
- b2s_warn(l, "Unable to create properties");
- return (DDI_FAILURE);
- }
- scsi_hba_nodename_compatible_free(name, compat);
-
- if (dipp) {
- /*
- * We were called by bus_config BUS_CONFIG_ONE,
- * and therefore must be done synchronously.
- */
- rv = ndi_devi_online(dip, NDI_ONLINE_ATTACH);
- if (rv == NDI_SUCCESS)
- *dipp = dip;
- } else {
- /*
- * The rest of the time, asynchronous is easier and
- * safer (nexus could call us from interrupt context).
- */
- rv = ndi_devi_online_async(dip,
- NDI_ONLINE_ATTACH | NDI_NOSLEEP);
- }
- if (rv != NDI_SUCCESS) {
- b2s_warn(l, "Failed to online device");
- ndi_prop_remove_all(dip);
- (void) ndi_devi_free(dip);
- return (DDI_FAILURE);
- }
-
- return (DDI_SUCCESS);
-}
-
-int
-b2s_bus_config(dev_info_t *ndip, uint_t flag, ddi_bus_config_op_t op,
- void *arg, dev_info_t **ldip)
-{
- long val;
- char *ptr;
- int rv;
- scsi_hba_tran_t *tran;
- b2s_leaf_t *l;
- b2s_nexus_t *n;
- int circ;
- uint_t target, lun;
-
- tran = ddi_get_driver_private(ndip);
- n = tran->tran_hba_private;
-
- ndi_devi_enter(ndip, &circ);
-
- switch (op) {
- case BUS_CONFIG_ONE:
-
- /*
- * First parse out the target and lun from the
- * address.
- */
- if ((ptr = strchr((char *)arg, '@')) == NULL) {
- rv = NDI_FAILURE;
- break;
- }
- ptr++;
- if ((ddi_strtol(ptr, &ptr, 16, &val) != 0) ||
- (val < 0) || (*ptr != ',')) {
- rv = NDI_FAILURE;
- break;
- }
- ptr++;
- target = (uint_t)val;
- if ((ddi_strtol(ptr, &ptr, 16, &val) != 0) ||
- (val < 0) || (*ptr != 0)) {
- rv = NDI_FAILURE;
- break;
- }
- lun = (uint_t)val;
-
- /*
- * Now lookup the leaf, and if we have it, attempt to create
- * the devinfo node for it.
- */
- rv = NDI_SUCCESS;
- if ((l = b2s_hold_leaf(n, target, lun)) != NULL) {
- if (b2s_create_node(n, l, ldip) != DDI_SUCCESS) {
- rv = NDI_FAILURE;
- }
- b2s_rele_leaf(l);
- break;
- }
- break;
-
- case BUS_CONFIG_DRIVER:
- case BUS_CONFIG_ALL:
-
- l = b2s_next_leaf(n, NULL);
- while (l != NULL) {
- (void) b2s_create_node(n, l, NULL);
- l = b2s_next_leaf(n, l);
- }
-
- rv = NDI_SUCCESS;
- break;
-
- default:
- rv = NDI_FAILURE;
- break;
- }
-
- if (rv == NDI_SUCCESS) {
- rv = ndi_busop_bus_config(ndip, flag, op, arg, ldip, 0);
- }
-
- ndi_devi_exit(ndip, circ);
- return (rv);
-}
-
-void
-b2s_inquiry_done(b2s_request_impl_t *ri)
-{
- struct scsi_inquiry *inqp = &ri->ri_leaf->l_inq;
-
- /*
- * The only post processing we have to do is to massage the
- * strings into the inquiry structure.
- */
- COPYSTR(ri->ri_inquiry.inq_vendor, inqp->inq_vid);
- COPYSTR(ri->ri_inquiry.inq_product, inqp->inq_pid);
- COPYSTR(ri->ri_inquiry.inq_revision, inqp->inq_revision);
- COPYSTR(ri->ri_inquiry.inq_serial, inqp->inq_serial);
-}
-
-int
-b2s_inquiry(b2s_leaf_t *l)
-{
- b2s_nexus_t *n;
- b2s_request_impl_t *ri;
- struct scsi_inquiry *inqp;
- int err;
-
- inqp = &l->l_inq;
- n = l->l_nexus;
-
- /*
- * Set up basic structure, including space padding for ASCII strings.
- */
- bzero(inqp, sizeof (*inqp));
- (void) memset(inqp->inq_vid, ' ', sizeof (inqp->inq_vid));
- (void) memset(inqp->inq_pid, ' ', sizeof (inqp->inq_pid));
- (void) memset(inqp->inq_revision, ' ', sizeof (inqp->inq_revision));
- (void) memset(inqp->inq_serial, ' ', sizeof (inqp->inq_serial));
- inqp->inq_len = sizeof (*inqp) - 4;
- inqp->inq_ansi = 2;
- inqp->inq_rdf = RDF_SCSI2;
- inqp->inq_dtype = DTYPE_DIRECT;
- if (l->l_flags & B2S_LEAF_REMOVABLE)
- inqp->inq_rmb = 1;
-
- /*
- * To get product strings, we have to issue a query to the driver.
- */
- ri = kmem_zalloc(sizeof (*ri), KM_NOSLEEP);
- if (ri == NULL) {
- return (DDI_FAILURE);
- }
- ri->ri_cmd = B2S_CMD_INQUIRY;
- ri->ri_target = l->l_target;
- ri->ri_lun = l->l_lun;
- ri->ri_flags = B2S_REQUEST_FLAG_HEAD;
- ri->ri_leaf = l;
- ri->ri_nexus = n;
- ri->ri_done = b2s_inquiry_done;
- /* leave all else null */
-
- /*
- * Submit inquiry request to device driver.
- */
- if (!n->n_request(n->n_private, &ri->ri_public)) {
- /* this shouldn't happen, since we are just starting out */
- b2s_warn(l, "Busy trying to collect inquiry data");
- kmem_free(ri, sizeof (*ri));
- return (DDI_FAILURE);
- }
-
- /*
- * Wait for inquiry completion.
- */
- mutex_enter(&n->n_lock);
- while ((ri->ri_flags & B2S_REQUEST_FLAG_DONE) == 0)
- cv_wait(&n->n_cv, &n->n_lock);
- mutex_exit(&n->n_lock);
-
- err = ri->ri_errno;
- kmem_free(ri, sizeof (*ri));
-
- if (err != 0) {
- b2s_warn(l, "Failed during inquiry (error %d)", err);
- return (DDI_FAILURE);
- }
-
- return (DDI_SUCCESS);
-}
-
-int
-b2s_scmd_inq(b2s_request_impl_t *ri)
-{
- b2s_leaf_t *l = ri->ri_leaf;
- union scsi_cdb *cdb = (void *)ri->ri_pkt->pkt_cdbp;
- caddr_t ptr;
- size_t resid, len;
- uint8_t hdr[4];
- const uint8_t *data;
- uint8_t page83[12];
-
- /*
- * Suppport inquiry pages: 0 is the list itself, and 80 is the
- * unit serial number (in ASCII).
- */
- const uint8_t supp[3] = { 0, 0x80, 0x83 };
-
- b2s_request_mapin(&ri->ri_public, &ptr, &len);
-
- hdr[2] = 0;
-
- /*
- * We don't support the EVP data bit, and hence neither a page code.
- * This corresponds to the entire G0 address field (which includes
- * a few reserved bits).
- */
- switch (GETG0ADDR(cdb)) {
- case 0x00000: /* standard SCSI inquiry */
- resid = min(sizeof (l->l_inq), GETG0COUNT(cdb));
- len = min(resid, len);
- bcopy(&l->l_inq, ptr, len);
- ri->ri_resid = resid - len;
- b2s_request_done(&ri->ri_public, B2S_EOK, 0);
- return (TRAN_ACCEPT);
-
- case 0x10000: /* page 0 supported VPD pages */
- data = supp;
- hdr[0] = DTYPE_DIRECT;
- hdr[1] = 0; /* page code */
- hdr[2] = 0;
- hdr[3] = l->l_eui ? 3 : 2; /* page length */
- break;
-
- case 0x18000: /* page 80 unit serial number */
- data = (uint8_t *)l->l_uuid;
- hdr[0] = DTYPE_DIRECT;
- hdr[1] = 0x80; /* page code */
- hdr[2] = 0;
- hdr[3] = l->l_uuid ? strlen(l->l_uuid) : 0; /* page len */
- break;
-
- case 0x18300: /* page 83 WWN */
- if (l->l_eui == 0) {
- b2s_request_done(&ri->ri_public, B2S_EINVAL, 0);
- return (TRAN_ACCEPT);
- }
- data = page83;
- hdr[0] = DTYPE_DIRECT;
- hdr[1] = 0x83; /* page code */
- hdr[2] = 0;
- hdr[3] = 12; /* length, only 12 bytes */
-
- /* lun designator */
- page83[0] = 1; /* binary */
- page83[1] = 2; /* lun association, eui-64 type */
- page83[2] = 0; /* reserved */
- page83[3] = 8; /* designator length */
- SCSI_WRITE64(&page83[4], l->l_eui);
-
- /* Note that we don't bother with port or target ids */
- break;
-
- default:
- b2s_request_done(&ri->ri_public, B2S_EINVAL, 0);
- return (TRAN_ACCEPT);
- }
-
- resid = min(hdr[3] + 4, GETG0COUNT(cdb));
- len = min(resid, len);
- ri->ri_resid = resid - len;
-
- /* now copy the header */
- len = min(resid, 4);
- bcopy(hdr, ptr, len);
- resid -= len;
-
- /* now copy the actual page data */
- bcopy(data, ptr + len, resid);
-
- b2s_request_done(&ri->ri_public, B2S_EOK, 0);
- return (TRAN_ACCEPT);
-}
-
-int
-b2s_scmd_rqs(b2s_request_impl_t *ri)
-{
- union scsi_cdb *cdb = (void *)ri->ri_pkt->pkt_cdbp;
- size_t len, resid;
- caddr_t ptr;
- int rv;
-
- /* Like inquiry, the entire G0 address field must be zero. */
- if (GETG0ADDR(cdb) != 0) {
- rv = B2S_EINVAL;
- len = 0;
- resid = 0;
- } else {
- struct scsi_extended_sense es;
-
- /*
- * We always use ARQ, unconditionally, so this command
- * can always return success.
- */
- bzero(&es, sizeof (es));
- es.es_valid = 1;
- es.es_class = CLASS_EXTENDED_SENSE;
- es.es_key = KEY_NO_SENSE;
-
- resid = sizeof (es);
-
- b2s_request_mapin(&ri->ri_public, &ptr, &len);
-
- len = min(resid, len);
- bcopy(&es, ptr, len);
- resid -= len;
-
- rv = B2S_EOK;
- }
- b2s_request_done(&ri->ri_public, rv, resid);
- return (TRAN_ACCEPT);
-}
-
-int
-b2s_scmd_sdiag(b2s_request_impl_t *ri)
-{
- union scsi_cdb *cdb = (void *)ri->ri_pkt->pkt_cdbp;
- int rv;
-
- /* we only support the SELFTEST bit */
- if ((GETG0TAG(cdb) & 0x4) == 0) {
- rv = B2S_EINVAL;
- } else {
- rv = B2S_EOK;
- }
- b2s_request_done(&ri->ri_public, rv, 0);
- return (TRAN_ACCEPT);
-}
-
-int
-b2s_scmd_tur(b2s_request_impl_t *ri)
-{
- b2s_nexus_t *n = ri->ri_nexus;
-
- ri->ri_cmd = B2S_CMD_GETMEDIA;
- if (!n->n_request(n->n_private, &ri->ri_public)) {
- return (TRAN_BUSY);
- }
- return (TRAN_ACCEPT);
-}
-
-int
-b2s_scmd_doorlock(b2s_request_impl_t *ri)
-{
- b2s_nexus_t *n = ri->ri_nexus;
- union scsi_cdb *cdb = (void *)ri->ri_pkt->pkt_cdbp;
-
- /*
- * Bit 0 of the count indicates the "Prevent" mode. All other address
- * and count bits are reserved.
- */
- if ((GETG0ADDR(cdb) != 0) || ((GETG0COUNT(cdb) & 0xFE) != 0)) {
- b2s_request_done(&ri->ri_public, B2S_EINVAL, 0);
- return (TRAN_ACCEPT);
- }
-
- ri->ri_cmd = (GETG0COUNT(cdb) != 0) ? B2S_CMD_LOCK : B2S_CMD_UNLOCK;
- if (!n->n_request(n->n_private, &ri->ri_public)) {
- return (TRAN_BUSY);
- }
- return (TRAN_ACCEPT);
-}
-
-int
-b2s_scmd_format(b2s_request_impl_t *ri)
-{
- b2s_nexus_t *n = ri->ri_nexus;
- union scsi_cdb *cdb = (void *)ri->ri_pkt->pkt_cdbp;
- size_t len;
- caddr_t ptr;
-
- if (GETG0TAG(cdb) & 0x7) {
- b2s_request_done(&ri->ri_public, B2S_EINVAL, 0);
- return (TRAN_ACCEPT);
- }
-
- if (GETG0TAG(cdb) & FPB_DATA) {
- /*
- * FmtData set. A defect list is attached.
- *
- * This is an awful lot of work just to support a command
- * option we don't ever care about. SCSI-2 says we have
- * to do it.
- *
- * The alternative would just be to ignore the defect list
- * and format options altogether. That would be a lot easier.
- */
-
- b2s_request_mapin(&ri->ri_public, &ptr, &len);
-
- if (len < 4) {
- b2s_request_done(&ri->ri_public, B2S_EBADMSG, 0);
- return (TRAN_ACCEPT);
- }
-
- if ((ptr[0] != 0) || (ptr[2] != 0) || (ptr[3] != 0) ||
- ((ptr[1] & 0xF9) != 0)) {
- b2s_request_done(&ri->ri_public, B2S_EPARAM, 0);
- return (TRAN_ACCEPT);
- }
-
- if (ptr[1] & 0x2) {
- ri->ri_flags |= B2S_REQUEST_FLAG_IMMED;
- }
-
- } else if (GETG0TAG(cdb) & FPB_CMPLT) {
- /*
- * No defect list, so this bit (CmpLst) should have been zero!
- */
- b2s_request_done(&ri->ri_public, B2S_EINVAL, 0);
- return (TRAN_ACCEPT);
- }
-
- ri->ri_cmd = B2S_CMD_FORMAT;
- if (!n->n_request(n->n_private, &ri->ri_public)) {
- return (TRAN_BUSY);
- }
-
- return (TRAN_ACCEPT);
-}
-
-void
-b2s_scmd_readcap_done(b2s_request_impl_t *ri)
-{
- uint32_t lba;
- union scsi_cdb *cdb = (void *)ri->ri_pkt->pkt_cdbp;
- struct scsi_capacity cap;
- caddr_t ptr;
- size_t resid, len;
-
- /*
- * Lower layer resid is meaningless here.
- */
- if (ri->ri_errno != B2S_EOK) {
- return;
- }
-
- lba = GETG1ADDR(cdb);
-
- switch (GETG1COUNT(cdb)) {
- case 0: /* PMI == 0 */
- if (lba != 0) {
- ri->ri_errno = B2S_EINVAL;
- return;
- }
- break;
- case 1: /* PMI == 1 */
- if (lba >= ri->ri_media.media_nblks) {
- ri->ri_errno = B2S_EBLKADDR;
- return;
- }
- break;
- default:
- ri->ri_errno = B2S_EINVAL;
- return;
- }
-
- /*
- * Note that the capacity is the LBA of the last block, not the
- * number of blocks. A little surprising if you don't pay close
- * enough attention to the spec.
- */
- SCSI_WRITE32(&cap.capacity, ri->ri_media.media_nblks - 1);
- SCSI_WRITE32(&cap.lbasize, ri->ri_media.media_blksz);
-
- b2s_request_mapin(&ri->ri_public, &ptr, &len);
-
- if (len != 0) {
- resid = sizeof (cap);
- len = min(resid, len);
- bcopy(&cap, ptr, len);
- ri->ri_resid = resid - len;
- }
-}
-
-int
-b2s_scmd_readcap(b2s_request_impl_t *ri)
-{
- b2s_nexus_t *n = ri->ri_nexus;
- union scsi_cdb *cdb = (void *)ri->ri_pkt->pkt_cdbp;
-
- /*
- * No transfer by real target.
- */
- ri->ri_done = b2s_scmd_readcap_done;
-
- if ((GETG1TAG(cdb)) != 0) {
- b2s_request_done(&ri->ri_public, B2S_EINVAL, 0);
- return (TRAN_ACCEPT);
- }
-
- ri->ri_cmd = B2S_CMD_GETMEDIA;
- if (!n->n_request(n->n_private, &ri->ri_public)) {
- return (TRAN_BUSY);
- }
-
- return (TRAN_ACCEPT);
-}
-
-int
-b2s_scmd_reserve_release(b2s_request_impl_t *ri)
-{
- union scsi_cdb *cdb = (void *)ri->ri_pkt->pkt_cdbp;
-
- /* we aren't checking fields we don't care about */
- if ((GETG0TAG(cdb) & 0x1) != 0) {
- /* extent reservations not supported */
- b2s_request_done(&ri->ri_public, B2S_EINVAL, 0);
- return (TRAN_ACCEPT);
- }
-
- /*
- * We don't support multi-initiator access, so we always
- * return success.
- */
-
- b2s_request_done(&ri->ri_public, B2S_EOK, 0);
- return (TRAN_ACCEPT);
-}
-
-int
-b2s_scmd_start_stop(b2s_request_impl_t *ri)
-{
- b2s_nexus_t *n = ri->ri_nexus;
- union scsi_cdb *cdb = (void *)ri->ri_pkt->pkt_cdbp;
- uint8_t count;
-
- switch (GETG0ADDR(cdb)) {
- case 0:
- break;
- case 0x10000: /* immed set */
- ri->ri_flags |= B2S_REQUEST_FLAG_IMMED;
- break;
- default:
- b2s_request_done(&ri->ri_public, B2S_EINVAL, 0);
- return (TRAN_ACCEPT);
- }
- count = GETG0COUNT(cdb);
- if (count > 3) {
- b2s_request_done(&ri->ri_public, B2S_EINVAL, 0);
- return (TRAN_ACCEPT);
- }
- if (count & 0x2)
- ri->ri_flags |= B2S_REQUEST_FLAG_LOAD_EJECT;
- if (count & 0x1) {
- ri->ri_cmd = B2S_CMD_START;
- } else {
- ri->ri_cmd = B2S_CMD_STOP;
- }
-
- if (!n->n_request(n->n_private, &ri->ri_public)) {
- return (TRAN_BUSY);
- }
- return (TRAN_ACCEPT);
-}
-
-void
-b2s_scmd_mode_sense_done(b2s_request_impl_t *ri)
-{
- uchar_t *cdb = ri->ri_pkt->pkt_cdbp;
- uint8_t pc, page, devspec;
- caddr_t ptr;
- size_t len, resid;
- uint8_t data[16];
-
- if ((ri->ri_errno == 0) &&
- ((ri->ri_media.media_flags & B2S_MEDIA_FLAG_READ_ONLY) == 0)) {
- devspec = 0;
- } else {
- /* this marks the media read-only */
- devspec = 0x80;
- }
-
- pc = page = cdb[2];
- pc &= 0xc0;
- page &= 0x3f;
-
- /* we do not support savable parameters, at all */
- if ((pc & 0xc0) == 0x3) {
- ri->ri_errno = B2S_ENOSAV;
- ri->ri_resid = 0;
- return;
- }
-
- b2s_request_mapin(&ri->ri_public, &ptr, &resid);
-
- if ((page == 0x9) || (page == 0x3f)) {
- /* Peripheral device page */
-
- /* header */
- data[0] = 9 + 3; /* length following */
- data[1] = 0; /* medium type */
- data[2] = devspec; /* mostly r/w flag */
- data[3] = 0; /* block descriptor len */
- len = min(4, resid);
-
- bcopy(data, ptr, len);
- resid -= len;
- ptr += len;
-
- /* page data - 9 bytes long */
- bzero(data, 9);
- data[0] = 0x9; /* page code */
- data[1] = 0x8; /* following data */
- len = min(resid, 9);
- bcopy(data, ptr, len);
- resid -= len;
- ptr += len;
- }
-
- if ((page == 0xa) || (page == 0x3f)) {
- /* Control mode page */
-
- /* header */
- data[0] = 8 + 3; /* length following */
- data[1] = 0; /* medium type */
- data[2] = devspec; /* mostly r/w flag */
- data[3] = 0; /* block descriptor len */
- len = min(4, resid);
-
- bcopy(data, ptr, len);
- resid -= len;
- ptr += len;
-
- /* page data - 9 bytes long */
- bzero(data, 8);
- data[0] = 0xa; /* page code */
- data[1] = 0x7; /* following data */
- len = min(resid, 9);
- bcopy(data, ptr, len);
- resid -= len;
- ptr += len;
- }
-
- ri->ri_resid = 0;
- ri->ri_errno = B2S_EOK;
-}
-
-int
-b2s_scmd_mode_sense(b2s_request_impl_t *ri)
-{
- b2s_nexus_t *n = ri->ri_nexus;
-
- ri->ri_done = b2s_scmd_mode_sense_done;
- ri->ri_cmd = B2S_CMD_GETMEDIA;
- if (!n->n_request(n->n_private, &ri->ri_public)) {
- return (TRAN_BUSY);
- }
- return (TRAN_ACCEPT);
-}
-
-int
-b2s_scmd_rw(b2s_request_impl_t *ri)
-{
- b2s_nexus_t *n = ri->ri_nexus;
- uint32_t lba;
- uint32_t nblks;
- union scsi_cdb *cdb = (void *)ri->ri_pkt->pkt_cdbp;
-
- switch (GETGROUP(cdb)) {
- case CDB_GROUPID_0:
- nblks = GETG0COUNT(cdb);
- nblks = nblks ? nblks : 256;
- lba = GETG0ADDR(cdb);
- break;
- case CDB_GROUPID_1:
- if (GETG1TAG(cdb)) {
- /* we don't support relative addresses */
- b2s_request_done(&ri->ri_public, B2S_EINVAL, 0);
- return (TRAN_ACCEPT);
- }
- lba = GETG1ADDR(cdb);
- nblks = GETG1COUNT(cdb);
- break;
- default:
- b2s_request_done(&ri->ri_public, B2S_ENOTSUP, 0);
- return (TRAN_ACCEPT);
- }
-
- if (nblks == 0) {
- b2s_request_done(&ri->ri_public, 0, 0);
- return (TRAN_ACCEPT);
- }
-
- ri->ri_nblks = nblks;
- ri->ri_lba = lba;
- ri->ri_flags |= B2S_REQUEST_FLAG_BLKS;
- ri->ri_cmd = (GETCMD(cdb)) == SCMD_READ ?
- B2S_CMD_READ : B2S_CMD_WRITE;
-
- if (!n->n_request(n->n_private, &ri->ri_public)) {
- return (TRAN_BUSY);
- }
- return (TRAN_ACCEPT);
-}
-
-void
-b2s_warn(b2s_leaf_t *l, const char *fmt, ...)
-{
- va_list ap;
- b2s_nexus_t *n;
- char msg[256];
-
- n = l->l_nexus;
-
- (void) snprintf(msg, sizeof (msg), "%s%d target %d lun %d: %s",
- ddi_driver_name(n->n_dip), ddi_get_instance(n->n_dip),
- l->l_target, l->l_lun, fmt);
-
- va_start(ap, fmt);
- vcmn_err(CE_WARN, msg, ap);
- va_end(ap);
-}
-
-b2s_nexus_t *
-b2s_alloc_nexus(b2s_nexus_info_t *info)
-{
- b2s_nexus_t *n;
- struct scsi_hba_tran *tran;
-
- if (info->nexus_version != B2S_VERSION_0)
- return (NULL);
-
- n = kmem_zalloc(sizeof (*n), KM_SLEEP);
- mutex_init(&n->n_lock, NULL, MUTEX_DRIVER, NULL);
- cv_init(&n->n_cv, NULL, CV_DRIVER, NULL);
- list_create(&n->n_leaves, sizeof (struct b2s_leaf),
- offsetof(struct b2s_leaf, l_node));
-
- n->n_dip = info->nexus_dip;
- n->n_private = info->nexus_private;
- n->n_request = info->nexus_request;
- if (info->nexus_dma_attr != NULL) {
- n->n_dma = info->nexus_dma_attr;
- } else {
- n->n_dma = &b2s_default_dma_attr;
- }
-
- tran = scsi_hba_tran_alloc(n->n_dip, SCSI_HBA_CANSLEEP);
- if (tran == NULL) {
- list_destroy(&n->n_leaves);
- mutex_destroy(&n->n_lock);
- cv_destroy(&n->n_cv);
- kmem_free(n, sizeof (*n));
- return (NULL);
- }
- n->n_tran = tran;
-
- tran->tran_hba_dip = n->n_dip;
- tran->tran_hba_private = n;
- tran->tran_tgt_private = NULL;
- tran->tran_tgt_init = b2s_tran_tgt_init;
- tran->tran_tgt_free = b2s_tran_tgt_free;
- tran->tran_tgt_probe = scsi_hba_probe;
- tran->tran_tgt_free = NULL;
- tran->tran_start = b2s_tran_start;
- tran->tran_reset = b2s_tran_reset;
- tran->tran_abort = b2s_tran_abort;
- tran->tran_getcap = b2s_tran_getcap;
- tran->tran_setcap = b2s_tran_setcap;
- tran->tran_init_pkt = b2s_tran_init_pkt;
- tran->tran_destroy_pkt = b2s_tran_destroy_pkt;
- tran->tran_hba_len = sizeof (b2s_request_impl_t);
- tran->tran_bus_config = b2s_bus_config;
-
- return (n);
-}
-
-void
-b2s_free_nexus(b2s_nexus_t *n)
-{
- b2s_leaf_t *l;
-
- /*
- * Toss any registered leaves, if we haven't already done so.
- * At this point we don't care about upper layers, because the
- * DDI should not have allowed us to detach if there were busy
- * targets.
- */
- while ((l = list_head(&n->n_leaves)) != NULL) {
- list_remove(&n->n_leaves, l);
- kmem_free(l, sizeof (struct b2s_leaf));
- }
- list_destroy(&n->n_leaves);
- mutex_destroy(&n->n_lock);
- cv_destroy(&n->n_cv);
- kmem_free(n, sizeof (struct b2s_nexus));
-}
-
-int
-b2s_attach_nexus(b2s_nexus_t *n)
-{
- int rv;
-
- rv = scsi_hba_attach_setup(n->n_dip, n->n_dma, n->n_tran,
- SCSI_HBA_TRAN_SCB | SCSI_HBA_TRAN_CDB | SCSI_HBA_TRAN_CLONE);
- if (rv == 0) {
- n->n_attached = B_TRUE;
- }
- return (rv);
-}
-
-int
-b2s_detach_nexus(b2s_nexus_t *n)
-{
- int rv;
-
- if (n->n_attached) {
- rv = scsi_hba_detach(n->n_dip);
- if (rv == 0) {
- n->n_attached = B_FALSE;
- }
- } else {
- rv = 0;
- }
- return ((rv == 0) ? DDI_SUCCESS : DDI_FAILURE);
-}
-
-b2s_leaf_t *
-b2s_attach_leaf(b2s_nexus_t *n, b2s_leaf_info_t *info)
-{
- b2s_leaf_t *l;
- uint_t target = info->leaf_target;
- uint_t lun = info->leaf_lun;
- const char *uuid = info->leaf_unique_id;
- uint32_t flags = info->leaf_flags;
- uint64_t eui = info->leaf_eui;
-
- if (uuid == NULL) {
- uuid = "";
- }
-
- mutex_enter(&n->n_lock);
-
- /*
- * If the leaf already exists, it is a sign that the device
- * was kept around because it was still in use. In that case,
- * we attempt to detect the situation where the node is the same
- * as the previous one, and reconnect it.
- */
- if ((l = b2s_get_leaf(n, target, lun)) != NULL) {
- if (strcmp(l->l_uuid, uuid) != 0) {
- /*
- * Leaf already exists, but is not the same! This
- * would be a good time to issue a warning.
- */
- mutex_exit(&n->n_lock);
- b2s_warn(l, "Target disconnected while still in use.");
- b2s_warn(l, "Reconnect the previous target device.");
- return (NULL);
- }
- l->l_flags &= ~B2S_LEAF_DETACHED;
- } else {
- if ((l = kmem_zalloc(sizeof (*l), KM_NOSLEEP)) == NULL) {
- mutex_exit(&n->n_lock);
- b2s_warn(l, "Unable to allocate target state.");
- return (NULL);
- }
- l->l_nexus = n;
- l->l_target = target;
- l->l_lun = lun;
- l->l_flags = flags;
- l->l_eui = eui;
-
- /* strdup would be nice here */
- l->l_uuid = kmem_alloc(strlen(uuid) + 1, KM_NOSLEEP);
- if (l->l_uuid == NULL) {
- mutex_exit(&n->n_lock);
- kmem_free(l, sizeof (*l));
- b2s_warn(l, "Unable to allocate target UUID storage.");
- return (NULL);
- }
- (void) strcpy(l->l_uuid, uuid);
-
- list_insert_tail(&n->n_leaves, l);
- }
-
- /*
- * Make sure we hold it, so that it won't be freed out from
- * underneath us.
- */
- l->l_refcnt++;
- mutex_exit(&n->n_lock);
-
- /*
- * If the HBA is currently attached, then we need to attach
- * the node right now. This supports "hotplug". Note that
- * if the node is a reinsert, then this should degenerate into
- * a NOP.
- */
- if (n->n_attached) {
- int circ;
- ndi_devi_enter(n->n_dip, &circ);
- (void) b2s_create_node(n, l, NULL);
- ndi_devi_exit(n->n_dip, circ);
- }
-
- return (l);
-}
-
-void
-b2s_detach_leaf(b2s_leaf_t *l)
-{
- b2s_nexus_t *n = l->l_nexus;
- dev_info_t *dip;
- int circ;
-
- l->l_flags |= B2S_LEAF_DETACHED;
-
- /*
- * Search for an appropriate child devinfo.
- */
- ndi_devi_enter(n->n_dip, &circ);
- dip = b2s_find_node(n, l);
- if (dip != NULL) {
- (void) ndi_devi_offline(dip, NDI_DEVI_REMOVE);
- }
- ndi_devi_exit(n->n_dip, circ);
-
- b2s_rele_leaf(l);
-}
--- a/usr/src/uts/common/io/sdcard/adapters/sdhost/sdhost.c Tue May 18 11:19:39 2010 +0800
+++ b/usr/src/uts/common/io/sdcard/adapters/sdhost/sdhost.c Mon May 17 21:17:01 2010 -0700
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include "sdhost.h"
@@ -368,7 +367,7 @@
}
shp->sh_host = sda_host_alloc(dip, shp->sh_numslots, &sdhost_ops,
- &shp->sh_dmaattr);
+ NULL);
if (shp->sh_host == NULL) {
cmn_err(CE_WARN, "Failed allocating SD host structure");
goto failed;
--- a/usr/src/uts/common/io/sdcard/impl/mapfile Tue May 18 11:19:39 2010 +0800
+++ b/usr/src/uts/common/io/sdcard/impl/mapfile Mon May 17 21:17:01 2010 -0700
@@ -20,8 +20,7 @@
#
#
-# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
#
#
@@ -55,10 +54,6 @@
sda_host_fault;
sda_host_log;
- # project private interfaces used by sdcard
- sda_mem_init;
- sda_mem_fini;
-
local:
*;
};
--- a/usr/src/uts/common/io/sdcard/impl/sda_cmd.c Tue May 18 11:19:39 2010 +0800
+++ b/usr/src/uts/common/io/sdcard/impl/sda_cmd.c Mon May 17 21:17:01 2010 -0700
@@ -19,18 +19,13 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
* SD card common framework. This module provides most of the common
* functionality so that SecureDigital host adapters and client devices
* (such as the sdcard driver) can share common code.
- *
- * NB that this file contains a fair bit of non-DDI compliant code.
- * But writing a nexus driver would be impossible to do with only DDI
- * compliant interfaces.
*/
#include <sys/types.h>
@@ -74,7 +69,8 @@
#define c_resid c_public.sc_resid
#define c_flags c_public.sc_flags
#define c_ndmac c_public.sc_ndmac
-#define c_dmacs c_public.sc_dmacs
+#define c_dmah c_public.sc_dmah
+#define c_dmac c_public.sc_dmac
#define c_kvaddr c_public.sc_kvaddr
/*
@@ -224,14 +220,21 @@
errno = SDA_ENODEV;
}
if (errno != SDA_EOK) {
- sda_slot_exit(slot);
- /* fail it synchronously */
- sda_cmd_notify(cmdp, SDA_CMDF_DAT | SDA_CMDF_BUSY, errno);
- return;
- }
+ /*
+ * We have to return failure conditions asynchronously.
+ * What we do in this case is mark the command failed,
+ * and move it to the abortlist so that the slot thread
+ * will execute the failure notification asynchronously.
+ *
+ * NB: using 0 for flags ensures that we don't execute
+ * the notification callback yet, we're just stashing
+ * the errno.
+ */
+ sda_cmd_notify(cmdp, 0, errno);
+ list_insert_tail(&slot->s_abortlist, cmdp);
- /* Initialization commands go to the head of the class */
- if (c->c_flags & SDA_CMDF_INIT) {
+ } else if (c->c_flags & SDA_CMDF_INIT) {
+ /* Initialization commands go to the head of the class */
list_insert_head(&slot->s_cmdlist, c);
} else {
list_insert_tail(&slot->s_cmdlist, c);
@@ -274,8 +277,10 @@
c->c_blksz = 0;
c->c_kvaddr = 0;
+ c->c_dmah = 0;
c->c_ndmac = 0;
- c->c_dmacs = NULL;
+ c->c_dmah = NULL;
+ bzero(&c->c_dmac, sizeof (c->c_dmac));
c->c_flags = 0;
c->c_slot = slot;
@@ -309,7 +314,8 @@
c->c_kvaddr = 0;
c->c_ndmac = 0;
- c->c_dmacs = NULL;
+ c->c_dmah = NULL;
+ bzero(&c->c_dmac, sizeof (c->c_dmac));
c->c_flags = 0;
c->c_slot = slot;
--- a/usr/src/uts/common/io/sdcard/impl/sda_host.c Tue May 18 11:19:39 2010 +0800
+++ b/usr/src/uts/common/io/sdcard/impl/sda_host.c Mon May 17 21:17:01 2010 -0700
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -37,78 +36,19 @@
#include <sys/sdcard/sda_impl.h>
/*
- * Static Variables.
- */
-
-static struct bus_ops sda_host_bus_ops = {
- BUSO_REV, /* busops_rev */
- nullbusmap, /* bus_map */
- NULL, /* bus_get_intrspec (OBSOLETE) */
- NULL, /* bus_add_intrspec (OBSOLETE) */
- NULL, /* bus_remove_intrspec (OBSOLETE) */
- i_ddi_map_fault, /* bus_map_fault */
- ddi_dma_map, /* bus_dma_map */
- ddi_dma_allochdl, /* bus_dma_allochdl */
- ddi_dma_freehdl, /* bus_dma_freehdl */
- ddi_dma_bindhdl, /* bus_dma_bindhdl */
- ddi_dma_unbindhdl, /* bus_dma_unbindhdl */
- ddi_dma_flush, /* bus_dma_flush */
- ddi_dma_win, /* bus_dma_win */
- ddi_dma_mctl, /* bus_dma_ctl */
- sda_nexus_bus_ctl, /* bus_ctl */
- ddi_bus_prop_op, /* bus_prop_op */
- NULL, /* bus_get_eventcookie */
- NULL, /* bus_add_eventcall */
- NULL, /* bus_remove_eventcall */
- NULL, /* bus_post_event */
- NULL, /* bus_intr_ctl (OBSOLETE) */
- NULL, /* sda_nexus_bus_config, */ /* bus_config */
- NULL, /* sda_nexus_bus_unconfig, */ /* bus_unconfig */
- NULL, /* bus_fm_init */
- NULL, /* bus_fm_fini */
- NULL, /* bus_fm_access_enter */
- NULL, /* bus_fm_access_exit */
- NULL, /* bus_power */
- NULL, /* bus_intr_op */
-};
-
-static struct cb_ops sda_host_cb_ops = {
- sda_nexus_open, /* cb_open */
- sda_nexus_close, /* cb_close */
- nodev, /* cb_strategy */
- nodev, /* cb_print */
- nodev, /* cb_dump */
- nodev, /* cb_read */
- nodev, /* cb_write */
- sda_nexus_ioctl, /* cb_ioctl */
- nodev, /* cb_devmap */
- nodev, /* cb_mmap */
- nodev, /* cb_segmap */
- nochpoll, /* cb_poll */
- ddi_prop_op, /* cb_prop_op */
- NULL, /* cb_str */
- D_MP, /* cb_flag */
- CB_REV, /* cb_rev */
- nodev, /* cb_aread */
- nodev, /* cb_awrite */
-};
-
-/*
* Implementation.
*/
void
sda_host_init_ops(struct dev_ops *devops)
{
- devops->devo_getinfo = sda_nexus_getinfo;
- devops->devo_cb_ops = &sda_host_cb_ops;
- devops->devo_bus_ops = &sda_host_bus_ops;
+ bd_mod_init(devops);
}
void
sda_host_fini_ops(struct dev_ops *devops)
{
- devops->devo_bus_ops = NULL;
+ bd_mod_fini(devops);
}
sda_host_t *
@@ -173,11 +113,6 @@
sda_host_detect(h, i);
}
- /*
- * Register (create) nexus minor nodes.
- */
- sda_nexus_register(h);
-
return (DDI_SUCCESS);
}
@@ -185,11 +120,6 @@
sda_host_detach(sda_host_t *h)
{
/*
- * Unregister nexus minor nodes.
- */
- sda_nexus_unregister(h);
-
- /*
* Detach slots.
*/
for (int i = 0; i < h->h_nslot; i++) {
--- a/usr/src/uts/common/io/sdcard/impl/sda_mem.c Tue May 18 11:19:39 2010 +0800
+++ b/usr/src/uts/common/io/sdcard/impl/sda_mem.c Mon May 17 21:17:01 2010 -0700
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -30,23 +29,16 @@
#include <sys/types.h>
#include <sys/note.h>
#include <sys/conf.h>
-#include <sys/scsi/adapters/blk2scsa.h>
+#include <sys/blkdev.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
#include <sys/sdcard/sda.h>
#include <sys/sdcard/sda_impl.h>
-static int sda_mem_attach(dev_info_t *, ddi_attach_cmd_t);
-static int sda_mem_detach(dev_info_t *, ddi_detach_cmd_t);
-static int sda_mem_quiesce(dev_info_t *);
-static b2s_err_t sda_mem_b2s_errno(sda_err_t);
-static boolean_t sda_mem_b2s_request(void *, b2s_request_t *);
-static boolean_t sda_mem_b2s_rw(sda_slot_t *, b2s_request_t *);
-static void sda_mem_b2s_done(sda_cmd_t *);
+static int sda_mem_errno(sda_err_t);
+static int sda_mem_rw(sda_slot_t *, bd_xfer_t *, uint8_t, uint16_t);
+static void sda_mem_done(sda_cmd_t *);
static void sda_mem_getstring(uint32_t *, char *, int, int);
-static int sda_mem_parse_cid_csd(sda_slot_t *, dev_info_t *);
-static int sda_mem_cmd(sda_slot_t *, uint8_t, uint32_t, uint8_t, uint32_t *);
-
/*
* To minimize complexity and reduce layering, we implement almost the
@@ -56,417 +48,160 @@
*/
/*
- * SCSA layer supplies a cb_ops, but we don't want it, because we
- * don't want to expose a SCSI attachment point. (Our parent handles
- * the attachment point, the SCSI one would be confusing.) We have to
- * supply a stubbed out one, to prevent SCSA from trying to create minor
- * nodes on our behalf.
- *
- * Perhaps at some future point we might want to expose a separate set
- * of ioctls for these nodes, but for now we rely on our parent to do
- * all that work.
- */
-static struct cb_ops sda_mem_ops = {
- nodev, /* cb_open */
- nodev, /* cb_close */
- nodev, /* cb_strategy */
- nodev, /* cb_print */
- nodev, /* cb_dump */
- nodev, /* cb_read */
- nodev, /* cb_write */
- nodev, /* cb_ioctl */
- nodev, /* cb_devmap */
- nodev, /* cb_mmap */
- nodev, /* cb_segmap */
- nochpoll, /* cb_chpoll */
- ddi_prop_op, /* cb_prop_op */
- NULL, /* cb_stream */
- D_MP /* cb_flag */
-};
-
-/*
- * Here are the public functions.
- */
-void
-sda_mem_init(struct modlinkage *modlp)
-{
- struct dev_ops *devo;
-
- devo = ((struct modldrv *)(modlp->ml_linkage[0]))->drv_dev_ops;
- devo->devo_attach = sda_mem_attach;
- devo->devo_detach = sda_mem_detach;
- devo->devo_quiesce = sda_mem_quiesce;
-
- devo->devo_cb_ops = &sda_mem_ops;
-
- /* it turns out that this can't ever really fail */
- (void) b2s_mod_init(modlp);
-}
-
-void
-sda_mem_fini(struct modlinkage *modlp)
-{
- b2s_mod_fini(modlp);
-}
-
-/*
* Everything beyond this is private.
*/
int
-sda_mem_cmd(sda_slot_t *slot, uint8_t cmd, uint32_t arg, uint8_t rtype,
- uint32_t *resp)
+sda_mem_errno(sda_err_t errno)
{
- sda_cmd_t *cmdp;
- int errno;
+ /* the hot path */
+ if (errno == SDA_EOK) {
+ return (0);
+ }
- cmdp = sda_cmd_alloc(slot, cmd, arg, rtype, NULL, KM_SLEEP);
- if (cmdp == NULL) {
+ switch (errno) {
+ case SDA_ENOMEM:
return (ENOMEM);
+ case SDA_ETIME:
+ return (ETIMEDOUT);
+ case SDA_EWPROTECT:
+ return (EROFS);
+ case SDA_ESUSPENDED:
+ case SDA_ENODEV:
+ return (ENODEV);
+ case SDA_EFAULT:
+ case SDA_ECRC7:
+ case SDA_EPROTO:
+ case SDA_ERESET:
+ case SDA_EIO:
+ case SDA_ERESID:
+ default:
+ return (EIO);
}
- errno = sda_cmd_exec(slot, cmdp, resp);
- sda_cmd_free(cmdp);
-
- return (errno);
}
-boolean_t
-sda_mem_b2s_rw(sda_slot_t *slot, b2s_request_t *reqp)
+void
+sda_mem_done(sda_cmd_t *cmdp)
+{
+ bd_xfer_t *xfer = sda_cmd_data(cmdp);
+ int errno = sda_cmd_errno(cmdp);
+
+ bd_xfer_done(xfer, sda_mem_errno(errno));
+ sda_cmd_free(cmdp);
+}
+
+int
+sda_mem_rw(sda_slot_t *slot, bd_xfer_t *xfer, uint8_t cmd, uint16_t flags)
{
sda_cmd_t *cmdp;
uint64_t nblks;
uint64_t blkno;
uint16_t rblen;
- int rv;
- uint8_t index;
- uint16_t flags;
- blkno = reqp->br_lba;
- nblks = reqp->br_nblks;
+ blkno = xfer->x_blkno;
+ nblks = xfer->x_nblks;
- switch (reqp->br_cmd) {
- case B2S_CMD_READ:
- if (nblks > 1) {
- index = CMD_READ_MULTI;
- flags = SDA_CMDF_DAT | SDA_CMDF_MEM | SDA_CMDF_READ |
- SDA_CMDF_AUTO_CMD12;
- } else {
- index = CMD_READ_SINGLE;
- flags = SDA_CMDF_DAT | SDA_CMDF_MEM | SDA_CMDF_READ;
- }
- break;
- case B2S_CMD_WRITE:
- if (nblks > 1) {
- index = CMD_WRITE_MULTI;
- flags = SDA_CMDF_DAT | SDA_CMDF_MEM | SDA_CMDF_WRITE |
- SDA_CMDF_AUTO_CMD12;
- } else {
- index = CMD_WRITE_SINGLE;
- flags = SDA_CMDF_DAT | SDA_CMDF_MEM | SDA_CMDF_WRITE;
- }
- break;
- default:
- ASSERT(0);
- break;
+ ASSERT(nblks != 0);
+
+ if ((blkno + nblks) > slot->s_nblks) {
+ return (EINVAL);
}
- cmdp = sda_cmd_alloc(slot, index, blkno << slot->s_bshift,
- R1, reqp, KM_NOSLEEP);
+ cmdp = sda_cmd_alloc(slot, cmd, blkno << slot->s_bshift,
+ R1, xfer, KM_NOSLEEP);
if (cmdp == NULL) {
- b2s_request_done(reqp, B2S_ENOMEM, 0);
- return (B_TRUE);
+ return (ENOMEM);
}
if (slot->s_hostp->h_dma != NULL) {
- b2s_request_dma(reqp, &cmdp->sc_ndmac, &cmdp->sc_dmacs);
+ cmdp->sc_dmah = xfer->x_dmah;
+ cmdp->sc_ndmac = xfer->x_ndmac;
+ cmdp->sc_dmac = xfer->x_dmac;
cmdp->sc_kvaddr = 0;
} else {
cmdp->sc_ndmac = 0;
- }
- if ((slot->s_caps & SLOT_CAP_NOPIO) == 0) {
- size_t maplen;
- b2s_request_mapin(reqp, &cmdp->sc_kvaddr, &maplen);
- }
-
- if (nblks == 0) {
- /*
- * This is not strictly a failure, but no work to do.
- * We have to do it late here because we don't want to
- * by pass the above media readiness checks.
- */
- rv = B2S_EOK;
- goto failed;
- }
- if (nblks > 0xffff) {
- rv = B2S_EINVAL;
- goto failed;
+ cmdp->sc_kvaddr = xfer->x_kaddr;
}
rblen = slot->s_blksz;
- if ((blkno + nblks) > slot->s_nblks) {
- rv = B2S_EBLKADDR;
- goto failed;
- }
-
- cmdp->sc_rtype = R1;
+ /* other fields are set by sda_cmd_alloc */
cmdp->sc_blksz = rblen;
cmdp->sc_nblks = (uint16_t)nblks;
- cmdp->sc_index = index;
cmdp->sc_flags = flags;
- sda_cmd_submit(slot, cmdp, sda_mem_b2s_done);
- return (B_TRUE);
-
-failed:
- sda_cmd_free(cmdp);
- b2s_request_done(reqp, rv, 0);
- return (B_TRUE);
+ sda_cmd_submit(slot, cmdp, sda_mem_done);
+ return (0);
}
-boolean_t
-sda_mem_b2s_format(sda_slot_t *slot, b2s_request_t *reqp)
+int
+sda_mem_bd_read(void *arg, bd_xfer_t *xfer)
{
- sda_cmd_t *cmdp;
- int rv;
-
+ sda_slot_t *slot = arg;
+ uint8_t cmd;
+ uint16_t flags;
- rv = sda_mem_cmd(slot, CMD_ERASE_START, 0, R1, NULL);
- if (rv != 0) {
- b2s_request_done(reqp, sda_mem_b2s_errno(rv), 0);
- return (B_TRUE);
- }
- rv = sda_mem_cmd(slot, CMD_ERASE_END, slot->s_nblks - 1, R1, NULL);
- if (rv != 0) {
- b2s_request_done(reqp, sda_mem_b2s_errno(rv), 0);
- return (B_TRUE);
+ if (xfer->x_nblks > 1) {
+ cmd = CMD_READ_MULTI;
+ flags = SDA_CMDF_DAT | SDA_CMDF_MEM | SDA_CMDF_READ |
+ SDA_CMDF_AUTO_CMD12;
+ } else {
+ cmd = CMD_READ_SINGLE;
+ flags = SDA_CMDF_DAT | SDA_CMDF_MEM | SDA_CMDF_READ;
}
- cmdp = sda_cmd_alloc(slot, CMD_ERASE, 0, R1b, reqp, KM_NOSLEEP);
- if (cmdp == NULL) {
- b2s_request_done(reqp, B2S_ENOMEM, 0);
- return (B_TRUE);
- }
- cmdp->sc_flags = SDA_CMDF_DAT | SDA_CMDF_MEM;
-
- sda_cmd_submit(slot, cmdp, sda_mem_b2s_done);
- return (B_TRUE);
+ return (sda_mem_rw(slot, xfer, cmd, flags));
}
-b2s_err_t
-sda_mem_b2s_errno(sda_err_t errno)
+int
+sda_mem_bd_write(void *arg, bd_xfer_t *xfer)
{
- /* the hot path */
- if (errno == SDA_EOK) {
- return (B2S_EOK);
+ sda_slot_t *slot = arg;
+ uint8_t cmd;
+ uint16_t flags;
+
+ if ((slot->s_flags & SLOTF_WRITABLE) == 0) {
+ return (EROFS);
+ }
+ if (xfer->x_nblks > 1) {
+ cmd = CMD_WRITE_MULTI;
+ flags = SDA_CMDF_DAT | SDA_CMDF_MEM | SDA_CMDF_WRITE |
+ SDA_CMDF_AUTO_CMD12;
+ } else {
+ cmd = CMD_WRITE_SINGLE;
+ flags = SDA_CMDF_DAT | SDA_CMDF_MEM | SDA_CMDF_WRITE;
}
- switch (errno) {
- case SDA_ENOMEM:
- return (B2S_ENOMEM);
- case SDA_ETIME:
- return (B2S_ETIMEDOUT);
- case SDA_EWPROTECT:
- return (B2S_EWPROTECT);
- case SDA_ESUSPENDED:
- case SDA_ENODEV:
- return (B2S_ENOMEDIA);
- case SDA_EFAULT:
- case SDA_ECRC7:
- case SDA_EPROTO:
- return (B2S_EHARDWARE);
- case SDA_ERESET:
- return (B2S_ERESET);
- case SDA_EIO:
- case SDA_ERESID:
- default:
- return (B2S_EIO);
- }
+ return (sda_mem_rw(slot, xfer, cmd, flags));
}
void
-sda_mem_b2s_done(sda_cmd_t *cmdp)
-{
- b2s_request_t *reqp = sda_cmd_data(cmdp);
- int errno = sda_cmd_errno(cmdp);
-
- b2s_request_done(reqp, sda_mem_b2s_errno(errno), cmdp->sc_resid);
- sda_cmd_free(cmdp);
-}
-
-boolean_t
-sda_mem_b2s_request(void *arg, b2s_request_t *reqp)
+sda_mem_bd_driveinfo(void *arg, bd_drive_t *drive)
{
sda_slot_t *slot = arg;
- int rv;
- switch (reqp->br_cmd) {
- case B2S_CMD_WRITE:
- if ((slot->s_flags & SLOTF_WRITABLE) == 0) {
- rv = B2S_EWPROTECT;
- } else {
- return (sda_mem_b2s_rw(slot, reqp));
- }
- break;
-
- case B2S_CMD_READ:
- return (sda_mem_b2s_rw(slot, reqp));
-
- case B2S_CMD_INQUIRY:
- reqp->br_inquiry.inq_vendor = "OSOL";
- reqp->br_inquiry.inq_product =
- slot->s_flags & SLOTF_MMC ? "MultiMediaCard" :
- slot->s_flags & SLOTF_SDHC ? "SDHC Memory Card" :
- "SD Memory Card";
- reqp->br_inquiry.inq_revision = "";
- reqp->br_inquiry.inq_serial = "";
- rv = B2S_EOK;
- break;
-
- case B2S_CMD_GETMEDIA:
- if (!slot->s_ready) {
- rv = B2S_ENODEV;
- } else {
- reqp->br_media.media_blksz = slot->s_blksz;
- reqp->br_media.media_nblks = slot->s_nblks;
- /* detect read-only cards */
- if (slot->s_flags & SLOTF_WRITABLE) {
- reqp->br_media.media_flags = 0;
- } else {
- reqp->br_media.media_flags =
- B2S_MEDIA_FLAG_READ_ONLY;
- }
- rv = B2S_EOK;
- }
- break;
-
- case B2S_CMD_FORMAT:
- return (sda_mem_b2s_format(slot, reqp));
-
- case B2S_CMD_ABORT:
- sda_slot_mem_reset(slot, SDA_EABORT);
- rv = B2S_EOK;
- break;
-
- case B2S_CMD_RESET:
- sda_slot_mem_reset(slot, SDA_ERESET);
- rv = B2S_EOK;
- break;
-
- case B2S_CMD_START:
- case B2S_CMD_STOP:
- case B2S_CMD_SYNC:
- rv = B2S_EOK;
- break;
-
- case B2S_CMD_LOCK:
- case B2S_CMD_UNLOCK:
- default:
- rv = B2S_ENOTSUP;
- break;
- }
-
- b2s_request_done(reqp, rv, 0);
- return (B_TRUE);
+ drive->d_qsize = 4; /* we queue up internally, 4 is enough */
+ drive->d_maxxfer = 65536;
+ drive->d_removable = B_TRUE;
+ drive->d_hotpluggable = B_FALSE;
+ drive->d_target = slot->s_slot_num;
}
int
-sda_mem_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
+sda_mem_bd_mediainfo(void *arg, bd_media_t *media)
{
- sda_slot_t *slot;
- b2s_nexus_t *nexus;
- b2s_nexus_info_t nexinfo;
- b2s_leaf_info_t leafinfo;
-
- switch (cmd) {
- case DDI_ATTACH:
- if ((slot = ddi_get_parent_data(dip)) == NULL) {
- return (DDI_FAILURE);
- }
-
- if (sda_mem_parse_cid_csd(slot, dip) != DDI_SUCCESS) {
- return (DDI_FAILURE);
- }
-
- nexinfo.nexus_version = B2S_VERSION_0;
- nexinfo.nexus_private = slot;
- nexinfo.nexus_dip = dip;
- nexinfo.nexus_dma_attr = slot->s_hostp->h_dma;
- nexinfo.nexus_request = sda_mem_b2s_request;
-
- nexus = b2s_alloc_nexus(&nexinfo);
- if (nexus == NULL) {
- return (DDI_FAILURE);
- }
-
- leafinfo.leaf_target = 0;
- leafinfo.leaf_lun = 0;
- leafinfo.leaf_flags =
- B2S_LEAF_REMOVABLE | B2S_LEAF_HOTPLUGGABLE;
- leafinfo.leaf_unique_id = slot->s_uuid;
- leafinfo.leaf_eui = 0;
-
- slot->s_leaf = b2s_attach_leaf(nexus, &leafinfo);
- if (slot->s_leaf == NULL) {
- b2s_free_nexus(nexus);
- return (DDI_FAILURE);
- }
+ sda_slot_t *slot = arg;
- slot->s_nexus = nexus;
- if (b2s_attach_nexus(nexus) != DDI_SUCCESS) {
- slot->s_nexus = NULL;
- b2s_free_nexus(nexus);
- return (DDI_FAILURE);
- }
- slot->s_nexus = nexus;
-
- return (DDI_SUCCESS);
-
-
- case DDI_RESUME:
- return (DDI_SUCCESS);
-
- default:
- return (DDI_FAILURE);
+ sda_slot_enter(slot);
+ if (!slot->s_ready) {
+ sda_slot_exit(slot);
+ return (ENXIO);
}
-}
-
-int
-sda_mem_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
-{
- sda_slot_t *slot;
- b2s_nexus_t *nexus;
-
- switch (cmd) {
- case DDI_DETACH:
- if ((slot = ddi_get_parent_data(dip)) == NULL) {
- return (DDI_FAILURE);
- }
- if ((nexus = slot->s_nexus) == NULL) {
- /* nothing to do */
- return (DDI_SUCCESS);
- }
- if (b2s_detach_nexus(nexus) != DDI_SUCCESS) {
- return (DDI_FAILURE);
- }
- slot->s_nexus = NULL;
- b2s_free_nexus(nexus);
- return (DDI_SUCCESS);
-
- case DDI_SUSPEND:
- return (DDI_SUCCESS);
-
- default:
- return (DDI_FAILURE);
- }
-}
-
-int
-sda_mem_quiesce(dev_info_t *dip)
-{
- _NOTE(ARGUNUSED(dip));
- /* no work to do */
- return (DDI_SUCCESS);
+ media->m_nblks = slot->s_nblks;
+ media->m_blksize = slot->s_blksz;
+ media->m_readonly = slot->s_flags & SLOTF_WRITABLE ? B_FALSE : B_TRUE;
+ sda_slot_exit(slot);
+ return (0);
}
uint32_t
@@ -510,7 +245,7 @@
}
int
-sda_mem_parse_cid_csd(sda_slot_t *slot, dev_info_t *dip)
+sda_mem_parse_cid_csd(sda_slot_t *slot)
{
uint32_t *rcid;
uint32_t *rcsd;
@@ -519,8 +254,6 @@
uint16_t bshift;
uint32_t cmult;
uint32_t csize;
- char date[16];
- char *dtype;
rcid = slot->s_rcid;
rcsd = slot->s_rcsd;
@@ -531,7 +264,6 @@
switch (csdver) {
case 0:
csize = sda_mem_getbits(rcsd, 73, 12);
- /* see comment above */
rblen = (1 << sda_mem_getbits(rcsd, 83, 4));
cmult = (4 << sda_mem_getbits(rcsd, 49, 3));
bshift = 9;
@@ -548,7 +280,6 @@
return (DDI_FAILURE);
}
- dtype = slot->s_flags & SLOTF_SDHC ? "sdhc" : "sdcard";
slot->s_mfg = sda_mem_getbits(rcid, 127, 8);
sda_mem_getstring(rcid, slot->s_oem, 119, 2);
sda_mem_getstring(rcid, slot->s_prod, 103, 5);
@@ -565,8 +296,6 @@
return (DDI_FAILURE);
}
- dtype = "mmc";
-
switch (sda_mem_getbits(rcsd, 125, 4)) {
case 0: /* MMC 1.0 - 1.2 */
case 1: /* MMC 1.4 */
@@ -633,33 +362,6 @@
(slot->s_perm_wp != 0) || (slot->s_temp_wp != 0)) {
slot->s_flags &= ~SLOTF_WRITABLE;
}
- (void) snprintf(date, sizeof (date), "%02d-%04d",
- slot->s_month, slot->s_year);
-
-#define prop_set_int(name, val) \
- (void) ddi_prop_update_int(DDI_DEV_T_NONE, dip, name, val)
-#define prop_set_str(name, val) \
- (void) ddi_prop_update_string(DDI_DEV_T_NONE, dip, name, val)
-#define prop_set_bool(name, val) \
- if (val) (void) ddi_prop_create(DDI_DEV_T_NONE, dip, 0, name, NULL, 0)
-
- prop_set_str("device-type", dtype);
- prop_set_int("mfg-id", slot->s_mfg);
- prop_set_str("product-id", slot->s_prod);
- prop_set_str("oem-id", slot->s_oem);
- prop_set_str("mfg-date", date);
-
- prop_set_int("block-size", slot->s_blksz);
- prop_set_int("num-blocks", slot->s_nblks);
- prop_set_int("max-freq", slot->s_maxclk);
- prop_set_bool("dsr-implemented", slot->s_dsr);
- prop_set_int("ccc", slot->s_ccc);
- prop_set_bool("perm-wp", slot->s_perm_wp);
- prop_set_bool("temp-wp", slot->s_temp_wp);
-
-#undef prop_set_int
-#undef prop_set_str
-#undef prop_set_bool
return (DDI_SUCCESS);
}
--- a/usr/src/uts/common/io/sdcard/impl/sda_mod.c Tue May 18 11:19:39 2010 +0800
+++ b/usr/src/uts/common/io/sdcard/impl/sda_mod.c Mon May 17 21:17:01 2010 -0700
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -53,11 +52,9 @@
int rv;
sda_cmd_init();
- sda_nexus_init();
if ((rv = mod_install(&modlinkage)) != 0) {
sda_cmd_fini();
- sda_nexus_fini();
}
return (rv);
@@ -70,7 +67,6 @@
if ((rv = mod_remove(&modlinkage)) == 0) {
sda_cmd_fini();
- sda_nexus_fini();
}
return (rv);
}
--- a/usr/src/uts/common/io/sdcard/impl/sda_nexus.c Tue May 18 11:19:39 2010 +0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,920 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-/*
- * SD card nexus support.
- *
- * NB that this file contains a fair bit of non-DDI compliant code.
- * But writing a nexus driver would be impossible to do with only DDI
- * compliant interfaces.
- */
-
-#include <sys/types.h>
-#include <sys/modctl.h>
-#include <sys/list.h>
-#include <sys/mkdev.h>
-#include <sys/file.h>
-#include <sys/errno.h>
-#include <sys/open.h>
-#include <sys/cred.h>
-#include <sys/stat.h>
-#include <sys/conf.h>
-#include <sys/sysmacros.h>
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-#include <sys/sunndi.h>
-#include <sys/sdcard/sda.h>
-#include <sys/sdcard/sda_ioctl.h>
-#include <sys/sdcard/sda_impl.h>
-#include <sys/fs/dv_node.h>
-
-/*
- * Local prototypes.
- */
-
-static sda_host_t *sda_nexus_lookup_dev(dev_t);
-static int sda_nexus_ap_ioctl(sda_host_t *, int, int, intptr_t);
-static int sda_nexus_ap_control(sda_host_t *, int, intptr_t, int);
-static int sda_nexus_ap_disconnect(sda_slot_t *);
-static int sda_nexus_ap_configure(sda_slot_t *);
-static int sda_nexus_ap_unconfigure(sda_slot_t *);
-static void sda_nexus_ap_getstate(sda_slot_t *, devctl_ap_state_t *);
-static void sda_nexus_reinsert(sda_slot_t *);
-static void sda_nexus_create(sda_slot_t *);
-
-/*
- * Static Variables.
- */
-
-static kmutex_t sda_nexus_lock;
-static list_t sda_nexus_list;
-
-/*
- * Minor number allocation.
- *
- * We have up to NBITSMINOR32 (18) bits available.
- *
- * For each instance, we need one minor number for each slot, and one
- * minor number for the devctl node.
- *
- * For simplicity's sake, we use the lower 8 bits for AP and DEVCTL nodes,
- * and the remaining 10 bits for the instance number.
- */
-#define MINOR_DC 0xff
-#define DEV_SLOT(dev) (getminor(dev) & 0xff)
-#define DEV_INST(dev) (getminor(dev) >> 8)
-#define MKMINOR_AP(inst, slot) (((slot) & 0xff) | ((inst) << 8))
-#define MKMINOR_DC(inst) (((inst) << 8) | MINOR_DC)
-
-/*
- * Implementation.
- */
-
-void
-sda_nexus_init(void)
-{
- list_create(&sda_nexus_list, sizeof (sda_host_t),
- offsetof(struct sda_host, h_node));
- mutex_init(&sda_nexus_lock, NULL, MUTEX_DRIVER, NULL);
-}
-
-void
-sda_nexus_fini(void)
-{
- list_destroy(&sda_nexus_list);
- mutex_destroy(&sda_nexus_lock);
-}
-
-int
-sda_nexus_bus_ctl(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t ctlop,
- void *arg, void *result)
-{
- switch (ctlop) {
- case DDI_CTLOPS_REPORTDEV:
- {
- cmn_err(CE_CONT, "?SD-device: %s@%s, %s#%d\n",
- ddi_node_name(rdip), ddi_get_name_addr(rdip),
- ddi_driver_name(rdip), ddi_get_instance(rdip));
-
- return (DDI_SUCCESS);
- }
-
- case DDI_CTLOPS_INITCHILD:
- {
- dev_info_t *child_dip = (dev_info_t *)arg;
- dev_info_t *ndip;
- sda_slot_t *slot;
- char addr[16];
-
- if ((slot = ddi_get_parent_data(child_dip)) == NULL) {
- sda_slot_err(NULL, "Parent data struct missing!");
- return (DDI_NOT_WELL_FORMED);
- }
-
- /*
- * TODO: SDIO: We will need to use x,y addresses for
- * SDIO function numbers. Memory cards will always
- * resid at address 0. Probably this can be passed in
- * to this function using properties.
- */
- (void) snprintf(addr, sizeof (addr), "%x", slot->s_slot_num);
-
- /*
- * Prevent duplicate nodes.
- */
- ndip = ndi_devi_find(dip, ddi_node_name(child_dip), addr);
- if (ndip && (ndip != child_dip)) {
- sda_slot_err(slot, "Duplicate device node found "
- "(%s@%s)", ddi_node_name(ndip), addr);
- }
-
- /*
- * Stash the address in the devinfo node.
- */
- ddi_set_name_addr(child_dip, addr);
-
- return (DDI_SUCCESS);
- }
-
- case DDI_CTLOPS_UNINITCHILD:
- {
- dev_info_t *child_dip = (dev_info_t *)arg;
-
- ddi_set_name_addr(child_dip, NULL);
- ndi_prop_remove_all(child_dip);
- return (DDI_SUCCESS);
- }
-
- case DDI_CTLOPS_SIDDEV:
- /*
- * All SDA target devices are self-identifying.
- */
- return (DDI_SUCCESS);
-
- case DDI_CTLOPS_SLAVEONLY:
- /*
- * We don't support DMA master for SDA targets.
- */
- return (DDI_SUCCESS);
-
- case DDI_CTLOPS_AFFINITY:
- /*
- * NB: We may want to revisit this later, so that functions
- * on one card can see other functions on the same card.
- * Right now there is no need.
- */
- return (DDI_FAILURE);
-
- case DDI_CTLOPS_DMAPMAPC:
- case DDI_CTLOPS_REPORTINT:
- case DDI_CTLOPS_POKE:
- case DDI_CTLOPS_PEEK:
- case DDI_CTLOPS_NREGS:
- case DDI_CTLOPS_REGSIZE:
- /*
- * We don't support any of these (yet?).
- */
- return (DDI_FAILURE);
-
- default:
- /*
- * Everything else goes to the parent nexus.
- */
- return (ddi_ctlops(dip, rdip, ctlop, arg, result));
- }
-}
-
-void
-sda_nexus_register(sda_host_t *h)
-{
- int i;
- int inst;
- char name[16];
-
- mutex_enter(&sda_nexus_lock);
- list_insert_tail(&sda_nexus_list, h);
- mutex_exit(&sda_nexus_lock);
-
- /*
- * Now create minor nodes. Note that failures to create these nodes
- * are mostly harmless, so we don't do much besides warn about it.
- * (It means cfgadm will be useless, but most folks aren't likely
- * to use cfgadm anyway.)
- */
-
- inst = ddi_get_instance(h->h_dip);
-
- /*
- * Create the devctl minor node.
- */
- if (ddi_create_minor_node(h->h_dip, "devctl", S_IFCHR,
- MKMINOR_DC(inst), DDI_NT_NEXUS, 0) != DDI_SUCCESS) {
- sda_slot_err(NULL, "Unable to create devctl node");
- }
-
- for (i = 0; i < h->h_nslot; i++) {
-
- sda_slot_t *slot;
-
- slot = &h->h_slots[i];
- /*
- * Create the attachment point minor nodes.
- */
- (void) snprintf(name, sizeof (name), "%d", i);
- if (ddi_create_minor_node(h->h_dip, name, S_IFCHR,
- MKMINOR_AP(inst, i), DDI_NT_SDCARD_ATTACHMENT_POINT,
- 0) != DDI_SUCCESS) {
- sda_slot_err(slot,
- "Unable to create attachment point node");
- }
- }
-}
-
-void
-sda_nexus_unregister(sda_host_t *h)
-{
- /*
- * Remove all minor nodes.
- */
- ddi_remove_minor_node(h->h_dip, NULL);
-
- mutex_enter(&sda_nexus_lock);
- list_remove(&sda_nexus_list, h);
- mutex_exit(&sda_nexus_lock);
-}
-
-sda_host_t *
-sda_nexus_lookup_dev(dev_t dev)
-{
- major_t maj;
- int inst;
- sda_host_t *h;
-
- ASSERT(mutex_owned(&sda_nexus_lock));
-
- maj = getmajor(dev);
- inst = DEV_INST(dev);
-
- h = list_head(&sda_nexus_list);
- while (h != NULL) {
- if ((ddi_driver_major(h->h_dip) == maj) &&
- (ddi_get_instance(h->h_dip) == inst)) {
- break;
- }
- h = list_next(&sda_nexus_list, h);
- }
- return (h);
-}
-
-void
-sda_nexus_create(sda_slot_t *slot)
-{
- dev_info_t *pdip, *cdip;
- int rv;
-
- pdip = slot->s_hostp->h_dip;
-
- /*
- * SDIO: This whole function will need to be recrafted to
- * support non-memory children. For SDIO, there could be
- * multiple functions, which get inserted or removed together.
- */
-
- if (ndi_devi_alloc(pdip, "sdcard", DEVI_SID_NODEID, &cdip) !=
- NDI_SUCCESS) {
- sda_slot_err(slot, "Failed allocating devinfo node");
- return;
- }
-
- ddi_set_parent_data(cdip, slot);
- slot->s_dip = NULL;
-
- /*
- * Make sure the child node gets suspend/resume events.
- */
- rv = ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "pm-capable", 1);
- if (rv != 0) {
- sda_slot_err(slot, "Failed creating pm-capable property");
- (void) ndi_devi_free(cdip);
- return;
- }
-
- sda_slot_enter(slot);
- slot->s_ready = B_TRUE;
- sda_slot_exit(slot);
-
- if (ndi_devi_online(cdip, NDI_ONLINE_ATTACH) != NDI_SUCCESS) {
- sda_slot_err(slot, "Failed bringing node online");
- (void) ndi_devi_free(cdip);
- } else {
- slot->s_dip = cdip;
- }
-}
-
-void
-sda_nexus_reinsert(sda_slot_t *slot)
-{
- dev_info_t *cdip, *pdip;
- int circ;
-
- pdip = slot->s_hostp->h_dip;
-
- ndi_devi_enter(pdip, &circ);
- sda_slot_enter(slot);
- if ((cdip = slot->s_dip) != NULL) {
- mutex_enter(&DEVI(cdip)->devi_lock);
- DEVI_SET_DEVICE_REINSERTED(cdip);
- mutex_exit(&DEVI(cdip)->devi_lock);
- }
- sda_slot_exit(slot);
- slot->s_warn = B_FALSE;
- slot->s_ready = B_TRUE;
- ndi_devi_exit(pdip, circ);
-}
-
-void
-sda_nexus_insert(sda_slot_t *slot)
-{
- char uuid[40];
- boolean_t match;
-
- if (slot->s_flags & SLOTF_MEMORY) {
- (void) snprintf(uuid, sizeof (uuid), "%c%08X%08X%08X%08X",
- slot->s_flags & SLOTF_MMC ? 'M' : 'S',
- slot->s_rcid[0], slot->s_rcid[1],
- slot->s_rcid[2], slot->s_rcid[3]);
- } else {
- /*
- * SDIO: For SDIO, we can write the card's MANFID
- * tuple in CIS to the UUID. Until we support SDIO,
- * we just suppress creating devinfo nodes.
- */
- sda_slot_err(slot, "Non-memory target not supported");
- uuid[0] = 0;
- }
-
- match = ((uuid[0] != 0) && (strcmp(slot->s_uuid, uuid) == 0));
-
- if (slot->s_dip != NULL) {
- if (!match) {
- sda_slot_err(slot, "Card removed while still in use.");
- sda_slot_err(slot, "Please reinsert previous card.");
-
- sda_nexus_remove(slot);
- } else {
- sda_nexus_reinsert(slot);
- }
- } else {
- /*
- * Remember the UUID.
- */
- (void) strlcpy(slot->s_uuid, uuid, sizeof (slot->s_uuid));
- /*
- * Create the children.
- */
- if (uuid[0] != 0)
- sda_nexus_create(slot);
- }
-}
-
-void
-sda_nexus_remove(sda_slot_t *slot)
-{
- sda_host_t *h = slot->s_hostp;
- dev_info_t *pdip = h->h_dip;
- dev_info_t *cdip;
- int circ;
- boolean_t reap = B_FALSE;
-
- ndi_devi_enter(pdip, &circ);
- if ((cdip = slot->s_dip) != NULL) {
- reap = B_TRUE;
-
- mutex_enter(&(DEVI(cdip))->devi_lock);
- DEVI_SET_DEVICE_REMOVED(cdip);
- mutex_exit(&(DEVI(cdip))->devi_lock);
- }
- ndi_devi_exit(pdip, circ);
-
- if (reap) {
- mutex_enter(&slot->s_evlock);
- slot->s_reap = B_TRUE;
- mutex_exit(&slot->s_evlock);
- sda_slot_wakeup(slot);
- }
-}
-
-void
-sda_nexus_reap(void *arg)
-{
- sda_slot_t *slot = arg;
- dev_info_t *pdip = slot->s_hostp->h_dip;
- dev_info_t *cdip;
- int circ;
- char *devnm;
- int rv;
-
- devnm = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
-
- ndi_devi_enter(pdip, &circ);
- sda_slot_enter(slot);
-
- cdip = slot->s_dip;
-
- if ((cdip != NULL) && DEVI_IS_DEVICE_REMOVED(cdip)) {
-
- sda_slot_exit(slot);
-
- if (i_ddi_node_state(cdip) < DS_INITIALIZED) {
- rv = ddi_remove_child(cdip, 0);
- } else {
- (void) ddi_deviname(cdip, devnm);
- (void) devfs_clean(pdip, devnm + 1, DV_CLEAN_FORCE);
- rv = ndi_devi_unconfig_one(pdip, devnm + 1, NULL,
- NDI_DEVI_REMOVE | NDI_UNCONFIG);
- }
-
- if (rv != NDI_SUCCESS) {
-
- mutex_enter(&slot->s_evlock);
- slot->s_reap = B_TRUE;
- mutex_exit(&slot->s_evlock);
- ndi_devi_exit(pdip, circ);
- return;
- }
- sda_slot_enter(slot);
-
- if (slot->s_dip == cdip) {
- slot->s_dip = NULL;
- }
- }
- sda_slot_exit(slot);
-
- mutex_enter(&slot->s_evlock);
- /* woohoo, done reaping nodes */
- slot->s_reap = B_FALSE;
- mutex_exit(&slot->s_evlock);
-
- ndi_devi_exit(pdip, circ);
- kmem_free(devnm, MAXNAMELEN + 1);
-}
-
-/*ARGSUSED3*/
-int
-sda_nexus_open(dev_t *devp, int flags, int otyp, cred_t *credp)
-{
- int rv = 0;
- sda_host_t *h;
-
- if (otyp != OTYP_CHR)
- return (EINVAL);
-
- mutex_enter(&sda_nexus_lock);
- if ((h = sda_nexus_lookup_dev(*devp)) == NULL) {
- mutex_exit(&sda_nexus_lock);
- return (ENXIO);
- }
-
- if (flags & FEXCL) {
- if ((h->h_flags & (HOST_SOPEN|HOST_XOPEN)) != 0) {
- rv = EBUSY;
- } else {
- h->h_flags |= HOST_XOPEN;
- }
- } else {
- if ((h->h_flags & HOST_XOPEN) != 0) {
- rv = EBUSY;
- } else {
- h->h_flags |= HOST_SOPEN;
- }
- }
- mutex_exit(&sda_nexus_lock);
- return (rv);
-}
-
-/*ARGSUSED1*/
-int
-sda_nexus_close(dev_t dev, int flag, int otyp, cred_t *credp)
-{
- sda_host_t *h;
-
- if (otyp != OTYP_CHR)
- return (EINVAL);
-
- mutex_enter(&sda_nexus_lock);
- if ((h = sda_nexus_lookup_dev(dev)) == NULL) {
- mutex_exit(&sda_nexus_lock);
- return (ENXIO);
- }
- h->h_flags &= ~(HOST_XOPEN | HOST_SOPEN);
- mutex_exit(&sda_nexus_lock);
- return (0);
-}
-
-void
-sda_nexus_ap_getstate(sda_slot_t *slot, devctl_ap_state_t *ap_state)
-{
- dev_info_t *cdip;
- dev_info_t *pdip = slot->s_hostp->h_dip;
- int circ;
-
- ndi_devi_enter(pdip, &circ);
- sda_slot_enter(slot);
-
- /*
- * Default state.
- */
- ap_state->ap_rstate = AP_RSTATE_EMPTY;
- ap_state->ap_condition = AP_COND_OK;
- ap_state->ap_ostate = AP_OSTATE_UNCONFIGURED;
-
- if (slot->s_inserted) {
- ap_state->ap_rstate = AP_RSTATE_CONNECTED;
- }
-
- if ((cdip = slot->s_dip) != NULL) {
- mutex_enter(&DEVI(cdip)->devi_lock);
- if (DEVI_IS_DEVICE_REMOVED(cdip)) {
- ap_state->ap_condition = AP_COND_UNUSABLE;
- }
- if (DEVI_IS_DEVICE_OFFLINE(cdip) ||
- DEVI_IS_DEVICE_DOWN(cdip)) {
- ap_state->ap_ostate = AP_OSTATE_UNCONFIGURED;
- } else {
- ap_state->ap_ostate = AP_OSTATE_CONFIGURED;
- }
- mutex_exit(&DEVI(cdip)->devi_lock);
- }
-
- if (slot->s_failed) {
- ap_state->ap_condition = AP_COND_FAILED;
- }
-
- ap_state->ap_last_change = slot->s_stamp;
- ap_state->ap_in_transition = slot->s_intransit;
-
- sda_slot_exit(slot);
- ndi_devi_exit(pdip, circ);
-}
-
-int
-sda_nexus_ap_disconnect(sda_slot_t *slot)
-{
- dev_info_t *cdip;
- dev_info_t *pdip = slot->s_hostp->h_dip;
- int rv = 0;
- int circ;
-
- /* if a child node exists, try to delete it */
- ndi_devi_enter(pdip, &circ);
-
- sda_slot_enter(slot);
- if ((cdip = slot->s_dip) != NULL) {
- if (ndi_devi_offline(cdip, NDI_DEVI_REMOVE) != NDI_SUCCESS) {
- /* couldn't disconnect, why not? */
- rv = EBUSY;
- goto done;
- }
- }
- slot->s_stamp = ddi_get_time();
- slot->s_dip = NULL;
-done:
- sda_slot_exit(slot);
- ndi_devi_exit(pdip, circ);
- return (rv);
-}
-
-int
-sda_nexus_ap_unconfigure(sda_slot_t *slot)
-{
- dev_info_t *cdip;
- dev_info_t *pdip = slot->s_hostp->h_dip;
- int rv = 0;
- int circ;
-
- /* attempt to unconfigure the node */
- ndi_devi_enter(pdip, &circ);
- sda_slot_enter(slot);
- if ((cdip = slot->s_dip) != NULL) {
- if (ndi_devi_offline(cdip, NDI_UNCONFIG) != NDI_SUCCESS) {
- /* failed to unconfigure the node (EBUSY?) */
- rv = EIO;
- goto done;
- }
- }
- slot->s_stamp = ddi_get_time();
- slot->s_dip = NULL;
-done:
- sda_slot_exit(slot);
- ndi_devi_exit(pdip, circ);
- return (rv);
-}
-
-int
-sda_nexus_ap_configure(sda_slot_t *slot)
-{
- dev_info_t *cdip;
-
- sda_slot_enter(slot);
- if (slot->s_inserted == B_FALSE) {
- /* device not present */
- sda_slot_exit(slot);
- return (ENXIO);
- }
-
- /* attempt to configure the node */
- if ((cdip = slot->s_dip) == NULL) {
- sda_slot_exit(slot);
- /* node not there! */
- return (ENXIO);
- }
- sda_slot_exit(slot);
-
- slot->s_intransit = 1;
-
- if (ndi_devi_online(cdip, NDI_CONFIG) != NDI_SUCCESS) {
- /* failed to configure the node */
- slot->s_intransit = 0;
- return (EIO);
- }
- slot->s_intransit = 0;
- slot->s_stamp = ddi_get_time();
- return (0);
-}
-
-int
-sda_nexus_ap_ioctl(sda_host_t *h, int snum, int cmd, intptr_t arg)
-{
- struct devctl_iocdata *dcp = NULL;
- devctl_ap_state_t ap_state;
- sda_slot_t *slot;
- int rv = 0;
-
- /*
- * In theory we could try to support this operation on the
- * DEVCTL minor, but then we would need a slot member in the
- * user nvlist. For now its easiest to assume a 1:1 relation
- * between the AP minor node, and the slot number.
- */
- if (snum >= h->h_nslot) {
- return (ENXIO);
- }
- slot = &h->h_slots[snum];
-
- if (ndi_dc_allochdl((void *)arg, &dcp) != NDI_SUCCESS)
- return (EFAULT);
-
- switch (cmd) {
- case DEVCTL_AP_DISCONNECT:
- rv = sda_nexus_ap_disconnect(slot);
- break;
-
- case DEVCTL_AP_UNCONFIGURE:
- rv = sda_nexus_ap_unconfigure(slot);
- break;
-
- case DEVCTL_AP_CONFIGURE:
- rv = sda_nexus_ap_configure(slot);
- break;
-
- case DEVCTL_AP_GETSTATE:
- bzero(&ap_state, sizeof (ap_state));
- sda_nexus_ap_getstate(slot, &ap_state);
- if (ndi_dc_return_ap_state(&ap_state, dcp) != NDI_SUCCESS) {
- rv = EFAULT;
- }
- break;
- }
-
- ndi_dc_freehdl(dcp);
-
- return (rv);
-}
-
-int
-sda_nexus_ap_control(sda_host_t *h, int snum, intptr_t arg, int mode)
-{
- struct sda_ap_control apc;
- struct sda_ap_control32 apc32;
- sda_slot_t *slot;
- int rv = 0;
-
- if (snum >= h->h_nslot) {
- return (ENXIO);
- }
- slot = &h->h_slots[snum];
-
- switch (ddi_model_convert_from(mode & FMODELS)) {
- case DDI_MODEL_ILP32:
- if (ddi_copyin((void *)arg, &apc32, sizeof (apc32), mode) !=
- 0) {
- return (EFAULT);
- }
- apc.cmd = apc32.cmd;
- apc.size = apc32.size;
- apc.data = (caddr_t *)(intptr_t)apc32.data;
- break;
- case DDI_MODEL_NONE:
- if (ddi_copyin((void *)arg, &apc, sizeof (apc), mode) != 0) {
- return (EFAULT);
- }
- break;
- }
-
- switch (apc.cmd) {
- case SDA_CFGA_GET_CARD_INFO: {
- sda_card_info_t ci;
-
- bzero(&ci, sizeof (ci));
- if (apc.size < sizeof (sda_card_info_t)) {
- apc.size = sizeof (sda_card_info_t);
- break;
- }
- sda_slot_enter(slot);
- if (!slot->s_inserted) {
- ci.ci_type = SDA_CT_UNKNOWN;
- } else if (slot->s_flags & SLOTF_MMC) {
- ci.ci_type = SDA_CT_MMC;
- } else if (slot->s_flags & SLOTF_SDIO) {
- if (slot->s_flags & SLOTF_MEMORY) {
- ci.ci_type = SDA_CT_SDCOMBO;
- } else {
- ci.ci_type = SDA_CT_SDIO;
- }
- } else if (slot->s_flags & SLOTF_SDMEM) {
- if (slot->s_flags & SLOTF_SDHC) {
- ci.ci_type = SDA_CT_SDHC;
- } else {
- ci.ci_type = SDA_CT_SDMEM;
- }
- } else {
- ci.ci_type = SDA_CT_UNKNOWN;
- }
-
- if (slot->s_flags & SLOTF_MEMORY) {
- ci.ci_mfg = slot->s_mfg;
- (void) strlcpy(ci.ci_oem,
- slot->s_oem, sizeof (ci.ci_oem));
- (void) strlcpy(ci.ci_pid,
- slot->s_prod, sizeof (ci.ci_pid));
- ci.ci_serial = slot->s_serial;
- ci.ci_month = slot->s_month;
- ci.ci_year = (slot->s_year - 1900) & 0xff;
- ci.ci_major = slot->s_majver;
- ci.ci_minor = slot->s_minver;
- }
-
- sda_slot_exit(slot);
-
- if (ddi_copyout(&ci, apc.data, sizeof (ci), mode) != 0) {
- return (EFAULT);
- }
-
- break;
- }
-
- case SDA_CFGA_GET_DEVICE_PATH:
- {
- char path[MAXPATHLEN];
- dev_info_t *cdip;
- int slen;
-
- sda_slot_enter(slot);
- if ((cdip = slot->s_dip) == NULL) {
- sda_slot_exit(slot);
- return (ENOENT);
- }
- (void) strcpy(path, "/devices");
- (void) ddi_pathname(cdip, path + strlen(path));
- slen = strlen(path) + 1;
- sda_slot_exit(slot);
- if (apc.size < slen) {
- apc.size = slen;
- rv = ENOSPC;
- break;
- }
- apc.size = slen;
- if (ddi_copyout(path, apc.data, slen, mode) != 0) {
- return (EFAULT);
- }
- break;
- }
-
- case SDA_CFGA_RESET_SLOT:
- {
- sda_slot_enter(slot);
- slot->s_failed = B_FALSE;
- sda_slot_exit(slot);
- sda_slot_reset(slot);
- sda_slot_detect(slot);
- break;
- }
-
- default:
- return (EINVAL);
- }
-
- switch (ddi_model_convert_from(mode & FMODELS)) {
- case DDI_MODEL_ILP32:
- apc32.cmd = apc.cmd;
- apc32.size = (size32_t)apc.size;
- apc32.data = (caddr32_t)(intptr_t)apc.data;
- if (ddi_copyout(&apc32, (void *)arg, sizeof (apc32), mode) !=
- 0) {
- return (EFAULT);
- }
- break;
- case DDI_MODEL_NONE:
- if (ddi_copyout(&apc, (void *)arg, sizeof (apc), mode) != 0) {
- return (EFAULT);
- }
- break;
- }
- return (rv);
-}
-
-/*ARGSUSED4*/
-int
-sda_nexus_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
- int *rvp)
-{
- sda_host_t *h;
-
- mutex_enter(&sda_nexus_lock);
- h = sda_nexus_lookup_dev(dev);
- mutex_exit(&sda_nexus_lock);
-
- if (h == NULL)
- return (ENXIO);
-
- switch (cmd) {
- case DEVCTL_DEVICE_GETSTATE:
- case DEVCTL_DEVICE_ONLINE:
- case DEVCTL_DEVICE_OFFLINE:
- case DEVCTL_DEVICE_REMOVE:
- case DEVCTL_BUS_GETSTATE:
- return (ndi_devctl_ioctl(h->h_dip, cmd, arg, mode, 0));
-
- case DEVCTL_AP_DISCONNECT:
- case DEVCTL_AP_CONFIGURE:
- case DEVCTL_AP_UNCONFIGURE:
- case DEVCTL_AP_GETSTATE:
- return (sda_nexus_ap_ioctl(h, DEV_SLOT(dev), cmd, arg));
-
- case DEVCTL_AP_CONTROL:
- return (sda_nexus_ap_control(h, DEV_SLOT(dev), arg, mode));
-
- default:
- return (ENOTSUP);
- }
-}
-
-/*ARGSUSED*/
-int
-sda_nexus_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **resp)
-{
- sda_host_t *h;
- int rv;
-
- rv = DDI_FAILURE;
-
- switch (cmd) {
- case DDI_INFO_DEVT2DEVINFO:
- mutex_enter(&sda_nexus_lock);
- h = sda_nexus_lookup_dev((dev_t)arg);
- if (h != NULL) {
- *resp = h->h_dip;
- rv = DDI_SUCCESS;
- }
- mutex_exit(&sda_nexus_lock);
- break;
-
- case DDI_INFO_DEVT2INSTANCE:
- *resp = (void *)(intptr_t)DEV_INST((dev_t)arg);
- rv = DDI_SUCCESS;
- break;
- }
- return (rv);
-}
--- a/usr/src/uts/common/io/sdcard/impl/sda_slot.c Tue May 18 11:19:39 2010 +0800
+++ b/usr/src/uts/common/io/sdcard/impl/sda_slot.c Mon May 17 21:17:01 2010 -0700
@@ -19,26 +19,18 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
* SD card slot support.
- *
- * NB that this file contains a fair bit of non-DDI compliant code.
- * But writing a nexus driver would be impossible to do with only DDI
- * compliant interfaces.
*/
#include <sys/types.h>
-#include <sys/sysmacros.h>
-#include <sys/cpuvar.h>
#include <sys/cmn_err.h>
#include <sys/varargs.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
-#include <sys/sunndi.h>
#include <sys/sdcard/sda_impl.h>
@@ -256,39 +248,31 @@
sda_slot_power_off(slot);
sda_slot_abort(slot, SDA_ENODEV);
sda_slot_exit(slot);
- sda_nexus_remove(slot);
+ } else if ((slot->s_flags & SLOTF_MEMORY) == 0) {
+ /*
+ * SDIO: For SDIO, we can write the card's
+ * MANFID tuple in CIS to the UUID. Until we
+ * support SDIO, we just suppress creating
+ * devinfo nodes.
+ */
+ sda_slot_err(slot, "Non-memory target not supported");
} else {
- sda_nexus_insert(slot);
+
+ sda_slot_enter(slot);
+ if (sda_mem_parse_cid_csd(slot) != DDI_SUCCESS) {
+ sda_slot_err(slot,
+ "Unable to parse card identification");
+ } else {
+ slot->s_warn = B_FALSE;
+ slot->s_ready = B_TRUE;
+ }
+ sda_slot_exit(slot);
}
slot->s_stamp = ddi_get_time();
slot->s_intransit = 0;
-}
-
-void
-sda_slot_mem_reset(sda_slot_t *slot, sda_err_t errno)
-{
- sda_cmd_t *cmdp;
-
- sda_slot_enter(slot);
- cmdp = list_head(&slot->s_cmdlist);
- while (cmdp != NULL) {
- sda_cmd_t *next;
- next = list_next(&slot->s_cmdlist, cmdp);
- if (cmdp->sc_flags & SDA_CMDF_MEM) {
- list_remove(&slot->s_cmdlist, cmdp);
- sda_cmd_notify(cmdp, 0, errno);
- mutex_enter(&slot->s_evlock);
- list_insert_tail(&slot->s_abortlist, cmdp);
- mutex_exit(&slot->s_evlock);
- }
- cmdp = next;
- }
- sda_slot_exit(slot);
-
- /* wake up to process the abort list */
- sda_slot_wakeup(slot);
+ bd_state_change(slot->s_bdh);
}
void
@@ -300,14 +284,13 @@
if ((cmdp = slot->s_xfrp) != NULL) {
slot->s_xfrp = NULL;
- sda_cmd_notify(cmdp, SDA_CMDF_BUSY | SDA_CMDF_DAT, errno);
+ sda_cmd_notify(cmdp, 0, errno);
+ list_insert_tail(&slot->s_abortlist, cmdp);
}
while ((cmdp = list_head(&slot->s_cmdlist)) != NULL) {
list_remove(&slot->s_cmdlist, cmdp);
sda_cmd_notify(cmdp, 0, errno);
- mutex_enter(&slot->s_evlock);
list_insert_tail(&slot->s_abortlist, cmdp);
- mutex_exit(&slot->s_evlock);
}
sda_slot_wakeup(slot);
@@ -421,9 +404,8 @@
*/
sda_slot_reset(slot);
- sda_nexus_remove(slot);
-
slot->s_intransit = 0;
+ bd_state_change(slot->s_bdh);
}
sda_slot_exit(slot);
@@ -490,6 +472,17 @@
cv_destroy(&slot->s_evcv);
}
+static bd_ops_t sda_bd_ops = {
+ BD_OPS_VERSION_0,
+ sda_mem_bd_driveinfo,
+ sda_mem_bd_mediainfo,
+ NULL, /* devid_init */
+ NULL, /* sync_cache */
+ sda_mem_bd_read,
+ sda_mem_bd_write,
+ NULL /* dump */
+};
+
void
sda_slot_attach(sda_slot_t *slot)
{
@@ -511,6 +504,9 @@
* card initialization.
*/
+ slot->s_bdh = bd_alloc_handle(slot, &sda_bd_ops, h->h_dma, KM_SLEEP);
+ ASSERT(slot->s_bdh);
+
sda_slot_enter(slot);
(void) snprintf(name, sizeof (name), "slot_%d_hp_tq",
@@ -521,6 +517,8 @@
/* Generally, this failure should never occur */
sda_slot_err(slot, "Unable to create hotplug slot taskq");
sda_slot_exit(slot);
+ bd_free_handle(slot->s_bdh);
+ slot->s_bdh = NULL;
return;
}
@@ -533,6 +531,8 @@
/* Generally, this failure should never occur */
sda_slot_err(slot, "Unable to create main slot taskq");
sda_slot_exit(slot);
+ bd_free_handle(slot->s_bdh);
+ slot->s_bdh = NULL;
return;
}
(void) ddi_taskq_dispatch(slot->s_main_tq, sda_slot_thread, slot,
@@ -560,6 +560,8 @@
}
sda_slot_exit(slot);
+
+ (void) bd_attach_handle(h->h_dip, slot->s_bdh);
}
void
@@ -568,6 +570,8 @@
/*
* Shut down the thread.
*/
+ (void) bd_detach_handle(slot->s_bdh);
+
mutex_enter(&slot->s_evlock);
slot->s_detach = B_TRUE;
cv_broadcast(&slot->s_evcv);
@@ -581,6 +585,8 @@
ddi_taskq_destroy(slot->s_main_tq);
if (slot->s_hp_tq)
ddi_taskq_destroy(slot->s_hp_tq);
+
+ bd_free_handle(slot->s_bdh);
}
void
@@ -681,15 +687,6 @@
continue;
}
- if (slot->s_reap) {
- /*
- * Do not sleep while holding the evlock. If this
- * fails, we'll just try again the next cycle.
- */
- (void) ddi_taskq_dispatch(slot->s_hp_tq,
- sda_nexus_reap, slot, DDI_NOSLEEP);
- }
-
if ((slot->s_xfrp != NULL) && (gethrtime() > slot->s_xfrtmo)) {
/*
* The device stalled processing the data request.
@@ -710,8 +707,7 @@
/*
* We use a timed wait if we are waiting for a
- * data transfer to complete, or if we might
- * need to reap child nodes. Otherwise we
+ * data transfer to complete. Otherwise we
* avoid the timed wait to avoid waking CPU
* (power savings.)
*/
@@ -731,16 +727,7 @@
slot->s_wake = B_FALSE;
- /*
- * Possibly reap child nodes.
- */
- if (slot->s_reap) {
- slot->s_reap = B_FALSE;
- mutex_exit(&slot->s_evlock);
- sda_nexus_reap(slot);
- } else {
- mutex_exit(&slot->s_evlock);
- }
+ mutex_exit(&slot->s_evlock);
/*
* We're awake now, so look for work to do. First
@@ -826,12 +813,6 @@
*/
if ((!slot->s_ready) && (cmdp->sc_flags & SDA_CMDF_MEM)) {
rv = SDA_ENODEV;
- if (!slot->s_warn) {
- sda_slot_err(slot,
- "Device removed while in use. "
- "Please reinsert!");
- slot->s_warn = B_TRUE;
- }
} else {
rv = slot->s_ops.so_cmd(slot->s_prv, cmdp);
}
--- a/usr/src/uts/common/io/sdcard/targets/sdcard/sdcard.c Tue May 18 11:19:39 2010 +0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,106 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-/*
- * SD memory card target driver. It relies on the SDA common
- * framework, and translates to SCSA. That is to say, it emulates a
- * simple SCSI block device.
- *
- * The entire driver is a tiny shim for the SDA framework, because to
- * make life simplify and reduce layering overhead, we just use implementation
- * in the SDA framework.
- *
- * (We have to be a separate driver, unfortunately, because SDA nexus drivers
- * need to support SDIO and memory targets, and there can only be one bus_ops
- * per driver.)
- */
-
-#include <sys/types.h>
-#include <sys/modctl.h>
-#include <sys/conf.h>
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-
-
-/* our entire API with SDA is miniscule */
-extern void sda_mem_init(struct modlinkage *);
-extern void sda_mem_fini(struct modlinkage *);
-
-static struct dev_ops sdcard_devops = {
- DEVO_REV,
- 0,
- NULL,
- nulldev,
- nulldev,
- NULL,
- NULL,
- nodev,
- NULL, /* cb_ops */
- NULL, /* bus_ops */
- NULL, /* power */
- NULL, /* quiesce */
-};
-
-static struct modldrv modldrv = {
- &mod_driverops,
- "SD Memory Slot",
- &sdcard_devops,
-};
-
-static struct modlinkage modlinkage = {
- MODREV_1, { &modldrv, NULL }
-};
-
-int
-_init(void)
-{
- int rv;
-
- sda_mem_init(&modlinkage);
-
- if ((rv = mod_install(&modlinkage)) != 0) {
- sda_mem_fini(&modlinkage);
- return (rv);
- }
- return (rv);
-}
-
-int
-_fini(void)
-{
- int rv;
-
- if ((rv = mod_remove(&modlinkage)) == 0) {
- sda_mem_fini(&modlinkage);
- return (rv);
- }
- return (rv);
-}
-
-int
-_info(struct modinfo *modinfop)
-{
- return (mod_info(&modlinkage, modinfop));
-}
--- a/usr/src/uts/common/io/warlock/blk2scsa.wlcmd Tue May 18 11:19:39 2010 +0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-root b2s_mod_fini
-root b2s_mod_init
-root b2s_alloc_nexus
-root b2s_attach_leaf
-root b2s_attach_nexus
-root b2s_detach_leaf
-root b2s_detach_nexus
-root b2s_free_nexus
-root b2s_request_dma
-root b2s_tran_tgt_free
-root b2s_tran_tgt_init
-
-root b2s_tran_setup_pkt
-root b2s_tran_start
-root b2s_tran_teardown_pkt
-root b2s_tran_tgt_free
-root b2s_tran_tgt_init
-
-add bus_ops::bus_config targets b2s_bus_config
-
-add scsi_pkt::pkt_comp targets \
- b2s_tran_teardown_pkt \
- b2s_tran_setup_pkt \
- b2s_tran_abort \
- b2s_tran_reset \
- b2s_tran_getcap \
- b2s_tran_setcap \
- b2s_tran_start
-
-add b2s_nexus::n_request targets b2s_request_dma
-
-add bus_ops::bus_add_eventcall targets warlock_dummy
-add bus_ops::bus_unconfig targets warlock_dummy
-add bus_ops::bus_get_eventcookie targets warlock_dummy
-add bus_ops::bus_intr_ctl targets warlock_dummy
-add bus_ops::bus_post_event targets warlock_dummy
-add bus_ops::bus_remove_eventcall targets warlock_dummy
-
--- a/usr/src/uts/common/io/warlock/sdhost.wlcmd Tue May 18 11:19:39 2010 +0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-root sda_host_log
-root sdhost_poll
-
-add sda_slot::s_ops.so_cmd targets sdhost_cmd \
- sdhost_halt
-add sda_slot::s_ops.so_getprop targets sdhost_getprop
-add sda_slot::s_ops.so_reset targets sdhost_reset
-add sda_slot::s_ops.so_setprop targets sdhost_setprop
-
--- a/usr/src/uts/common/sys/Makefile Tue May 18 11:19:39 2010 +0800
+++ b/usr/src/uts/common/sys/Makefile Mon May 17 21:17:01 2010 -0700
@@ -85,6 +85,7 @@
bitmap.h \
bitset.h \
bl.h \
+ blkdev.h \
bmc_intf.h \
bofi.h \
bofi_impl.h \
@@ -935,8 +936,7 @@
sddef.h \
smp.h
-SCSIADHDRS= \
- blk2scsa.h
+SCSIADHDRS=
SCSICADHDRS=
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/sys/blkdev.h Mon May 17 21:17:01 2010 -0700
@@ -0,0 +1,155 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#ifndef _SYS_BLKDEV_H
+#define _SYS_BLKDEV_H
+
+#include <sys/types.h>
+#include <sys/ksynch.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This describes a fairly simple block device. The idea here is that
+ * these things want to take advantage of the common labelling support,
+ * but do not need all the capabilities of SCSA. So we make quite a few
+ * simplifications:
+ *
+ * 1) Device block size is fixed at 512 bytes. (Devices with larger
+ * block sizes can still operate, but will need to support some
+ * form of read-modify-write, and will take a performance penalty.)
+ *
+ * 2) Non-rotating media. We assume a simple linear layout.
+ *
+ * 3) Fixed queue depth, for each device. The adapter driver reports
+ * the queue depth at registration. We don't have any form of
+ * dynamic flow control.
+ *
+ * 4) Negligible power management support. The framework does not support
+ * fine grained power management. If the adapter driver wants to use
+ * such, it will need to manage power on its own.
+ *
+ * 5) Suspend/resume support managed by the adapter driver. We don't
+ * support suspend/resume directly. The adapter device driver will
+ * need to manage this on its own behalf.
+ *
+ * 6) No request priorities. Transfers are assumed to execute in
+ * roughly FIFO order. The adapter driver may reorder them, but the
+ * submitter has no control over that.
+ *
+ * 7) No request cancellation. Once submitted, the job completes or
+ * fails. It cannot be canceled.
+ *
+ * 8) Limited support for removable media. There is no support for
+ * locking bay doors or mechanised media bays. This could be
+ * added, but at present the only such interesting devices are
+ * covered by the SCSI disk driver.
+ */
+
+typedef struct bd_handle *bd_handle_t;
+typedef struct bd_xfer bd_xfer_t;
+typedef struct bd_drive bd_drive_t;
+typedef struct bd_media bd_media_t;
+typedef struct bd_ops bd_ops_t;
+
+
+struct bd_xfer {
+ /*
+ * NB: If using DMA the br_ndmac will be non-zero. Otherwise
+ * the br_kaddr will be non-NULL.
+ */
+ diskaddr_t x_blkno;
+ size_t x_nblks;
+ ddi_dma_handle_t x_dmah;
+ ddi_dma_cookie_t x_dmac;
+ unsigned x_ndmac;
+ caddr_t x_kaddr;
+};
+
+#define BD_XFER_POLL (1U << 0) /* no interrupts (dump) */
+
+struct bd_drive {
+ uint32_t d_qsize;
+ uint32_t d_maxxfer;
+ boolean_t d_removable;
+ boolean_t d_hotpluggable;
+ int d_target;
+ int d_lun;
+};
+
+struct bd_media {
+ /*
+ * NB: The block size must be a power of two not less than
+ * DEV_BSIZE (512). Other values of the block size will
+ * simply not function and the media will be rejected.
+ *
+ * The block size must also divide evenly into the device's
+ * d_maxxfer field. If the maxxfer is a power of two larger
+ * than the block size, then this will automatically be
+ * satisfied.
+ */
+ uint64_t m_nblks;
+ uint32_t m_blksize;
+ boolean_t m_readonly;
+};
+
+#define BD_INFO_FLAG_REMOVABLE (1U << 0)
+#define BD_INFO_FLAG_HOTPLUGGABLE (1U << 1)
+#define BD_INFO_FLAG_READ_ONLY (1U << 2)
+
+struct bd_ops {
+ int o_version;
+ void (*o_drive_info)(void *, bd_drive_t *);
+ int (*o_media_info)(void *, bd_media_t *);
+ int (*o_devid_init)(void *, dev_info_t *, ddi_devid_t *);
+ int (*o_sync_cache)(void *, bd_xfer_t *);
+ int (*o_read)(void *, bd_xfer_t *);
+ int (*o_write)(void *, bd_xfer_t *);
+ int (*o_dump)(void *, bd_xfer_t *);
+};
+
+#define BD_OPS_VERSION_0 0
+
+/*
+ * Note, one handler *per* address. Drivers with multiple targets at
+ * different addresses must use separate handles.
+ */
+bd_handle_t bd_alloc_handle(void *, bd_ops_t *, ddi_dma_attr_t *, int);
+void bd_free_handle(bd_handle_t);
+int bd_attach_handle(dev_info_t *, bd_handle_t);
+int bd_detach_handle(bd_handle_t);
+void bd_state_change(bd_handle_t);
+void bd_xfer_done(bd_xfer_t *, int);
+void bd_mod_init(struct dev_ops *);
+void bd_mod_fini(struct dev_ops *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_BLKDEV_H */
--- a/usr/src/uts/common/sys/dkio.h Tue May 18 11:19:39 2010 +0800
+++ b/usr/src/uts/common/sys/dkio.h Mon May 17 21:17:01 2010 -0700
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1982, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#ifndef _SYS_DKIO_H
@@ -85,6 +84,7 @@
#define DKC_PCMCIA_MEM 21 /* PCMCIA memory disk-like type (Obsolete) */
#define DKC_PCMCIA_ATA 22 /* PCMCIA AT Attached type */
#define DKC_VBD 23 /* virtual block device */
+#define DKC_BLKDEV 24 /* generic block device (see blkdev(7d)) */
/*
* Sun reserves up through 1023
--- a/usr/src/uts/common/sys/scsi/adapters/blk2scsa.h Tue May 18 11:19:39 2010 +0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,183 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _SYS_SCSI_ADAPTERS_BLK2SCSA_H
-#define _SYS_SCSI_ADAPTERS_BLK2SCSA_H
-
-#include <sys/types.h>
-#include <sys/ksynch.h>
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct b2s_nexus_info b2s_nexus_info_t;
-typedef struct b2s_leaf_info b2s_leaf_info_t;
-typedef struct b2s_media b2s_media_t;
-typedef struct b2s_inquiry b2s_inquiry_t;
-typedef struct b2s_request b2s_request_t;
-typedef struct b2s_nexus b2s_nexus_t;
-typedef struct b2s_leaf b2s_leaf_t;
-
-struct b2s_media {
- uint64_t media_blksz;
- uint64_t media_nblks;
- uint64_t media_flags;
-};
-#define B2S_MEDIA_FLAG_READ_ONLY (1U << 1)
-#define B2S_MEDIA_FLAG_LOCKED (1U << 2)
-
-
-struct b2s_inquiry {
- const char *inq_vendor;
- const char *inq_product;
- const char *inq_revision;
- const char *inq_serial;
-};
-
-struct b2s_nexus_info {
- int nexus_version;
- dev_info_t *nexus_dip;
- void *nexus_private;
- ddi_dma_attr_t *nexus_dma_attr;
- boolean_t (*nexus_request)(void *, b2s_request_t *);
-};
-
-struct b2s_leaf_info {
- uint_t leaf_target;
- uint_t leaf_lun;
- uint32_t leaf_flags;
- const char *leaf_unique_id;
- uint64_t leaf_eui;
-};
-
-#define B2S_LEAF_REMOVABLE (1U << 0)
-#define B2S_LEAF_HOTPLUGGABLE (1U << 1)
-/* these values reserved! */
-#define B2S_LEAF_DETACHED (1U << 16)
-
-typedef enum {
- B2S_CMD_GETMEDIA = 0, /* get content */
- B2S_CMD_FORMAT = 1, /* format media */
- B2S_CMD_START = 2, /* spin up */
- B2S_CMD_STOP = 3, /* spin down */
- B2S_CMD_LOCK = 4, /* lock media door */
- B2S_CMD_UNLOCK = 5, /* unlock media door */
- B2S_CMD_READ = 6, /* read blocks */
- B2S_CMD_WRITE = 7, /* write blocks */
- B2S_CMD_SYNC = 8, /* flush write cache */
- B2S_CMD_INQUIRY = 9, /* inquiry data */
- B2S_CMD_RESET = 10, /* reset of bus */
- B2S_CMD_ABORT = 11, /* abort inflight commands */
-} b2s_cmd_t;
-
-typedef enum {
- B2S_EOK = 0, /* success */
- B2S_ENOTSUP = 1, /* operation not sup */
- B2S_EFORMATTING = 2, /* busy formatting */
- B2S_ENOMEDIA = 3, /* media not mounted */
- B2S_EMEDIACHG = 4, /* media changed */
- B2S_ESTOPPED = 5, /* unit not started */
- B2S_EBLKADDR = 6, /* blkno invalid */
- B2S_EIO = 7, /* general failure */
- B2S_EHARDWARE = 8, /* hardware error */
- B2S_ENODEV = 9, /* hardware removed */
- B2S_EMEDIA = 10, /* media problem */
- B2S_EDOORLOCK = 11, /* door lock engaged */
- B2S_EWPROTECT = 12, /* write protected */
- B2S_ESTARTING = 13, /* unit spinning up */
- B2S_ETIMEDOUT = 14, /* request timed out */
- B2S_ENOMEM = 15, /* out of memory */
- B2S_ERESET = 16, /* reset aborted command */
- B2S_EABORT = 17, /* aborted command */
-
- /* these are framework internal use only */
- B2S_ERSVD = 18, /* unit reserved */
- B2S_EINVAL = 19, /* invalid parameter */
- B2S_EPARAM = 20, /* bad parameter */
- B2S_EBADMSG = 21, /* malformed message */
- B2S_ENOSAV = 22, /* no saveable parms */
-
- /* used internally for array sizing, must be last */
- B2S_NERRS = 23
-} b2s_err_t;
-
-#define B2S_REQUEST_FLAG_POLL (1U << 0) /* use polled io */
-#define B2S_REQUEST_FLAG_HEAD (1U << 1)
-#define B2S_REQUEST_FLAG_DONE (1U << 2)
-#define B2S_REQUEST_FLAG_LOAD_EJECT (1U << 3) /* for start/stop */
-#define B2S_REQUEST_FLAG_IMMED (1U << 4) /* get status immed */
-/* framework internal flags */
-#define B2S_REQUEST_FLAG_BLKS (1U << 16) /* block-oriented */
-#define B2S_REQUEST_FLAG_MAPIN (1U << 17) /* bp_mapin done */
-
-struct b2s_request {
- b2s_cmd_t br_cmd;
- b2s_err_t br_errno;
- uint_t br_target;
- uint_t br_lun;
- uint32_t br_flags;
-
- /* note that this member should come last for future expansion */
- union {
- uint64_t a_ints[6];
- b2s_media_t a_media;
- b2s_inquiry_t a_inquiry;
- } br_args;
-};
-#define br_lba br_args.a_ints[0]
-#define br_nblks br_args.a_ints[1]
-#define br_media br_args.a_media
-#define br_inquiry br_args.a_inquiry
-
-
-int b2s_mod_init(struct modlinkage *);
-void b2s_mod_fini(struct modlinkage *);
-
-/* used as version to alloc_hba */
-#define B2S_VERSION_0 0
-
-b2s_nexus_t *b2s_alloc_nexus(b2s_nexus_info_t *);
-void b2s_free_nexus(b2s_nexus_t *);
-int b2s_attach_nexus(b2s_nexus_t *);
-int b2s_detach_nexus(b2s_nexus_t *);
-
-b2s_leaf_t *b2s_attach_leaf(b2s_nexus_t *, b2s_leaf_info_t *);
-void b2s_detach_leaf(b2s_leaf_t *);
-
-/*
- * Address information.
- */
-void b2s_request_mapin(b2s_request_t *, caddr_t *, size_t *);
-void b2s_request_dma(b2s_request_t *, uint_t *, ddi_dma_cookie_t **);
-void b2s_request_done(b2s_request_t *, b2s_err_t, size_t);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _SYS_SCSI_ADAPTERS_BLK2SCSA_H */
--- a/usr/src/uts/common/sys/sdcard/sda.h Tue May 18 11:19:39 2010 +0800
+++ b/usr/src/uts/common/sys/sdcard/sda.h Mon May 17 21:17:01 2010 -0700
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#ifndef _SYS_SDCARD_SDA_H
@@ -222,8 +221,9 @@
uint32_t sc_resid;
+ ddi_dma_handle_t sc_dmah;
uint_t sc_ndmac; /* # DMA cookies */
- ddi_dma_cookie_t *sc_dmacs; /* actual DMA cookies */
+ ddi_dma_cookie_t sc_dmac; /* actual DMA cookies */
caddr_t sc_kvaddr; /* kernel virtual address */
#define SDA_CMDF_READ 0x0001 /* transfer direction */
@@ -236,8 +236,6 @@
#define SDA_CMDF_MEM 0x0800 /* memory target command */
};
-_NOTE(SCHEME_PROTECTS_DATA("unshared request", sda_cmd))
-
/*
* The framework has two APIs. The first API is for host controllers,
* and is referred to as SDHOST. The second API is for target devices,
--- a/usr/src/uts/common/sys/sdcard/sda_impl.h Tue May 18 11:19:39 2010 +0800
+++ b/usr/src/uts/common/sys/sdcard/sda_impl.h Mon May 17 21:17:01 2010 -0700
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#ifndef _SYS_SDCARD_SDA_IMPL_H
@@ -29,6 +28,7 @@
#include <sys/list.h>
#include <sys/ksynch.h>
#include <sys/note.h>
+#include <sys/blkdev.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
#include <sys/sdcard/sda.h>
@@ -153,24 +153,9 @@
uint8_t s_perm_wp; /* permanent write protect set? */
uint8_t s_temp_wp; /* temporary write protect set? */
- char s_uuid[40]; /* fabricated universal unique id */
-
- struct b2s_nexus *s_nexus;
- struct b2s_leaf *s_leaf;
+ bd_handle_t s_bdh; /* block dev handle */
};
-_NOTE(MUTEX_PROTECTS_DATA(sda_slot::s_lock, sda_slot::s_circular))
-_NOTE(MUTEX_PROTECTS_DATA(sda_slot::s_evlock, sda_slot::s_wake))
-_NOTE(MUTEX_PROTECTS_DATA(sda_slot::s_evlock, sda_slot::s_detach))
-_NOTE(MUTEX_PROTECTS_DATA(sda_slot::s_evlock, sda_slot::s_detect))
-_NOTE(MUTEX_PROTECTS_DATA(sda_slot::s_evlock, sda_slot::s_suspend))
-_NOTE(MUTEX_PROTECTS_DATA(sda_slot::s_evlock, sda_slot::s_fault))
-_NOTE(MUTEX_PROTECTS_DATA(sda_slot::s_evlock, sda_slot::s_xfrdone))
-_NOTE(MUTEX_PROTECTS_DATA(sda_slot::s_evlock, sda_slot::s_errno))
-_NOTE(SCHEME_PROTECTS_DATA("slot_enter", sda_slot::s_warn))
-_NOTE(SCHEME_PROTECTS_DATA("slot_enter", sda_slot::s_xfrtmo))
-_NOTE(SCHEME_PROTECTS_DATA("slot_enter", sda_slot::s_xfrp))
-
/*
* Per host state. One per devinfo node. There could be multiple
* slots per devinfo node.
@@ -189,10 +174,6 @@
#define HOST_SOPEN (1U << 3) /* shared open */
};
-_NOTE(SCHEME_PROTECTS_DATA("stable data", sda_host::h_dip))
-_NOTE(SCHEME_PROTECTS_DATA("stable data", sda_host::h_nslot))
-_NOTE(SCHEME_PROTECTS_DATA("stable data", sda_host::h_dma))
-
/*
* Useful function-like macros.
*/
@@ -230,6 +211,11 @@
void sda_mem_fini(struct modlinkage *);
uint32_t sda_mem_maxclk(sda_slot_t *);
uint32_t sda_mem_getbits(uint32_t *, int, int);
+int sda_mem_parse_cid_csd(sda_slot_t *);
+int sda_mem_bd_read(void *, bd_xfer_t *);
+int sda_mem_bd_write(void *, bd_xfer_t *);
+void sda_mem_bd_driveinfo(void *, bd_drive_t *);
+int sda_mem_bd_mediainfo(void *, bd_media_t *);
/*
@@ -269,7 +255,6 @@
void sda_slot_reset(sda_slot_t *);
void sda_slot_shutdown(sda_slot_t *);
void sda_slot_transfer(sda_slot_t *, sda_err_t);
-void sda_slot_mem_reset(sda_slot_t *, sda_err_t);
void sda_slot_fault(sda_slot_t *, sda_fault_t);
/*PRINTFLIKE2*/
void sda_slot_err(sda_slot_t *, const char *, ...);
--- a/usr/src/uts/intel/Makefile.intel.shared Tue May 18 11:19:39 2010 +0800
+++ b/usr/src/uts/intel/Makefile.intel.shared Mon May 17 21:17:01 2010 -0700
@@ -209,6 +209,7 @@
DRV_KMODS += audiovia823x
DRV_KMODS_32 += audiovia97
DRV_KMODS += bl
+DRV_KMODS += blkdev
DRV_KMODS += bge
DRV_KMODS += bofi
DRV_KMODS += bpf
@@ -315,7 +316,6 @@
DRV_KMODS += rwn
DRV_KMODS += sad
DRV_KMODS += sd
-DRV_KMODS += sdcard
DRV_KMODS += sdhost
DRV_KMODS += sgen
DRV_KMODS += si3124
@@ -573,7 +573,6 @@
MISC_KMODS += acpica
MISC_KMODS += agpmaster
MISC_KMODS += bignum
-MISC_KMODS += blk2scsa
MISC_KMODS += bootdev
MISC_KMODS += busra
MISC_KMODS += cmlb
--- a/usr/src/uts/intel/blk2scsa/Makefile Tue May 18 11:19:39 2010 +0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,106 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-
-#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-#
-# This makefile drives the production of the blk2scsa driver
-# intel architecture dependent
-#
-
-#
-# Paths to the base of the uts directory trees
-#
-UTSBASE = ../..
-
-#
-# Define the module and object file sets.
-#
-MODULE = blk2scsa
-OBJECTS = $(BLK2SCSA_OBJS:%=$(OBJS_DIR)/%)
-LINTS = $(BLK2SCSA_OBJS:%.o=$(LINTS_DIR)/%.ln)
-ROOTMODULE = $(ROOT_MISC_DIR)/$(MODULE)
-WARLOCK_OUT = $(BLK2SCSA_OBJS:%.o=%.ll)
-WARLOCK_OK = $(MODULE).ok
-WLCMD_DIR = $(UTSBASE)/common/io/warlock
-
-#
-# Include common rules.
-#
-include $(UTSBASE)/intel/Makefile.intel
-
-#
-# Define targets.
-#
-ALL_TARGET = $(BINARY)
-LINT_TARGET = $(MODULE).lint
-INSTALL_TARGET = $(BINARY) $(ROOTMODULE)
-
-#
-# Note dependancy on misc/scsi.
-#
-LDFLAGS += -dy -N"misc/scsi"
-
-#
-# Default build targets.
-#
-.KEEP_STATE:
-
-def: $(DEF_DEPS)
-
-all: $(ALL_DEPS)
-
-clean: $(CLEAN_DEPS)
-
-clobber: $(CLOBBER_DEPS)
-
-lint: $(LINT_DEPS)
-
-modlintlib: $(MODLINTLIB_DEPS)
-
-clean.lint: $(CLEAN_LINT_DEPS)
-
-install: $(INSTALL_DEPS)
-
-#
-# Include common targets.
-#
-include $(UTSBASE)/intel/Makefile.targ
-
-WLCC = wlcc
-TOUCH = touch
-WARLOCK = warlock
-
-warlock: $(WARLOCK_OK)
-
-$(WARLOCK_OK): $(WARLOCK_OUT)
- $(WARLOCK) -c $(WLCMD_DIR)/blk2scsa.wlcmd \
- $(WARLOCK_OUT) \
- -l ../warlock/scsi.ll -l ../warlock/ddi_dki_impl.ll
- $(TOUCH) $@
-
-%.ll: $(UTSBASE)/common/io/scsi/adapters/blk2scsa/%.c
- $(WLCC) $(CPPFLAGS) -DDEBUG -o $@ $<
-
-
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/intel/blkdev/Makefile Mon May 17 21:17:01 2010 -0700
@@ -0,0 +1,84 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+#
+
+#
+# This makefile drives the production of the blkdev driver
+#
+
+#
+# Paths to the base of the uts directory trees
+#
+UTSBASE = ../..
+
+#
+# Define the module and object file sets.
+#
+MODULE = blkdev
+OBJECTS = $(BLKDEV_OBJS:%=$(OBJS_DIR)/%)
+LINTS = $(BLKDEV_OBJS:%.o=$(LINTS_DIR)/%.ln)
+ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE)
+
+#
+# Include common rules.
+#
+include $(UTSBASE)/intel/Makefile.intel
+
+#
+# Define targets.
+#
+ALL_TARGET = $(BINARY)
+LINT_TARGET = $(MODULE).lint
+INSTALL_TARGET = $(BINARY) $(ROOTMODULE)
+
+#
+# Note dependancy on misc/scsi.
+#
+LDFLAGS += -dy -Nmisc/cmlb
+
+#
+# Default build targets.
+#
+.KEEP_STATE:
+
+def: $(DEF_DEPS)
+
+all: $(ALL_DEPS)
+
+clean: $(CLEAN_DEPS)
+
+clobber: $(CLOBBER_DEPS)
+
+lint: $(LINT_DEPS)
+
+modlintlib: $(MODLINTLIB_DEPS)
+
+clean.lint: $(CLEAN_LINT_DEPS)
+
+install: $(INSTALL_DEPS)
+
+#
+# Include common targets.
+#
+include $(UTSBASE)/intel/Makefile.targ
--- a/usr/src/uts/intel/sda/Makefile Tue May 18 11:19:39 2010 +0800
+++ b/usr/src/uts/intel/sda/Makefile Mon May 17 21:17:01 2010 -0700
@@ -20,8 +20,7 @@
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
#
#
@@ -45,8 +44,6 @@
OBJECTS = $(SDA_OBJS:%=$(OBJS_DIR)/%)
LINTS = $(SDA_OBJS:%.o=$(LINTS_DIR)/%.ln)
ROOTMODULE = $(ROOT_MISC_DIR)/$(MODULE)
-WARLOCK_OUT = $(SDA_OBJS:%.o=%.ll)
-WARLOCK_OK = $(MODULE).ok
#
# Include common rules.
@@ -72,11 +69,11 @@
CFLAGS += $(CCVERBOSE)
#
-# dependency on blk2scsa module, scope limiting mapfile
+# dependency on blkdev module, scope limiting mapfile
# Note that we have to allow CTFMERGE to use fuzzy matching
#
MAPFILE = $(UTSBASE)/common/io/sdcard/impl/mapfile
-LDFLAGS += -dy -Nmisc/blk2scsa -B reduce -M $(MAPFILE)
+LDFLAGS += -dy -Ndrv/blkdev -B reduce -M $(MAPFILE)
CTFMRGFLAGS += -f
#
@@ -104,15 +101,3 @@
# Include common targets.
#
include $(UTSBASE)/intel/Makefile.targ
-
-WLCC = wlcc
-TOUCH = touch
-WARLOCK = warlock
-
-warlock: $(WARLOCK_OK)
-
-$(WARLOCK_OK): $(WARLOCK_OUT)
- $(TOUCH) $@
-
-%.ll: $(UTSBASE)/common/io/sdcard/impl/%.c
- $(WLCC) $(CPPFLAGS) -DDEBUG -o $@ $<
--- a/usr/src/uts/intel/sdcard/Makefile Tue May 18 11:19:39 2010 +0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-
-#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-#
-# uts/intel/sdcard/Makefile
-#
-# This makefile drives the production of the sdcard driver.
-#
-# intel architecture dependent
-#
-
-#
-# Path to the base of the uts directory tree (usually /usr/src/uts).
-#
-UTSBASE = ../..
-
-#
-# Define the module and object file sets.
-#
-MODULE = sdcard
-OBJECTS = $(SDCARD_OBJS:%=$(OBJS_DIR)/%)
-LINTS = $(SDCARD_OBJS:%.o=$(LINTS_DIR)/%.ln)
-ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE)
-
-#
-# Include common rules.
-#
-include $(UTSBASE)/intel/Makefile.intel
-
-#
-# Define targets
-#
-ALL_TARGET = $(BINARY)
-LINT_TARGET = $(MODULE).lint
-INSTALL_TARGET = $(BINARY) $(ROOTMODULE)
-
-#
-# Overrides.
-#
-DEBUG_FLGS =
-DEBUG_DEFS += $(DEBUG_FLGS)
-
-#
-# lint pass one enforcement
-#
-CFLAGS += $(CCVERBOSE)
-
-#
-# dependency on sda module
-#
-LDFLAGS += -dy -N misc/sda
-
-#
-# Default build targets.
-#
-.KEEP_STATE:
-
-def: $(DEF_DEPS)
-
-all: $(ALL_DEPS)
-
-clean: $(CLEAN_DEPS)
-
-clobber: $(CLOBBER_DEPS)
-
-lint: $(LINT_DEPS)
-
-modlintlib: $(MODLINTLIB_DEPS)
-
-clean.lint: $(CLEAN_LINT_DEPS)
-
-install: $(INSTALL_DEPS)
-
-#
-# Include common targets.
-#
-include $(UTSBASE)/intel/Makefile.targ
--- a/usr/src/uts/intel/sdhost/Makefile Tue May 18 11:19:39 2010 +0800
+++ b/usr/src/uts/intel/sdhost/Makefile Mon May 17 21:17:01 2010 -0700
@@ -20,8 +20,7 @@
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
#
#
@@ -45,9 +44,6 @@
OBJECTS = $(SDHOST_OBJS:%=$(OBJS_DIR)/%)
LINTS = $(SDHOST_OBJS:%.o=$(LINTS_DIR)/%.ln)
ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE)
-WARLOCK_OUT = $(SDHOST_OBJS:%.o=%.ll)
-WARLOCK_OK = $(MODULE).ok
-WLCMD_DIR = $(UTSBASE)/common/io/warlock
#
# Include common rules.
@@ -73,7 +69,7 @@
CFLAGS += $(CCVERBOSE)
#
-# dependency on scsi module
+# dependency on sda module
#
LDFLAGS += -dy -Nmisc/sda
@@ -102,26 +98,3 @@
# Include common targets.
#
include $(UTSBASE)/intel/Makefile.targ
-
-WARLOCK = warlock
-WLCC = wlcc
-TOUCH = touch
-SDA_LLS = $(SDA_OBJS:%.o= -l ../sda/%.ll)
-BLK2SCSA_LLS = $(BLK2SCSA_OBJS:%.o= -l ../blk2scsa/%.ll)
-
-warlock: $(WARLOCK_OK)
-
-blk2scsa.wl:
- @cd ../blk2scsa; pwd; $(MAKE) warlock
-
-sda.wl:
- @cd ../sda; pwd; $(MAKE) warlock
-
-$(WARLOCK_OK): $(WARLOCK_OUT) $(WLCMD_DIR)/sdhost.wlcmd blk2scsa.wl sda.wl
- $(WARLOCK) -c $(WLCMD_DIR)/sdhost.wlcmd $(WARLOCK_OUT) \
- $(SDA_LLS) $(BLK2SCSA_LLS) \
- -l ../warlock/ddi_dki_impl.ll
- $(TOUCH) $@
-
-%.ll: $(UTSBASE)/common/io/sdcard/adapters/sdhost/%.c
- $(WLCC) $(CPPFLAGS) -DDEBUG -o $@ $<
--- a/usr/src/uts/intel/warlock/Makefile Tue May 18 11:19:39 2010 +0800
+++ b/usr/src/uts/intel/warlock/Makefile Mon May 17 21:17:01 2010 -0700
@@ -20,8 +20,7 @@
#
#
-# Copyright 2010 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
#
# uts/intel/warlock/Makefile
#
@@ -52,7 +51,7 @@
# lock_lint rules
#
all: warlock warlock.1394 warlock.ecpp warlock.scsi \
- warlock.usb warlock.ib warlock.sata warlock.sdcard warlock.wc
+ warlock.usb warlock.ib warlock.sata warlock.wc
warlock: $(MODULE).ok
@@ -88,7 +87,6 @@
@cd ../sd; $(MAKE) clean; $(MAKE) warlock
@cd ../ses; $(MAKE) clean; $(MAKE) warlock
@cd ../st; $(MAKE) clean; $(MAKE) warlock
- @cd ../blk2scsa; $(MAKE) clean; $(MAKE) warlock
$(CLOSED_BUILD) @cd $(CLOSED)/uts/intel/glm; $(MAKE) clean; $(MAKE) warlock
$(CLOSED_BUILD) @cd $(CLOSED)/uts/intel/mpt; $(MAKE) clean; $(MAKE) warlock
@@ -120,9 +118,5 @@
$(CLOSED_BUILD) @cd $(CLOSED)/uts/intel/marvell88sx; \
$(MAKE) clean; $(MAKE) warlock
-warlock.sdcard:
- @cd ../sda; $(MAKE) clean; $(MAKE) warlock
- @cd ../sdhost; $(MAKE) clean; $(MAKE) warlock
-
warlock.wc:
@cd ../wc; $(MAKE) clean; $(MAKE) warlock
--- a/usr/src/uts/sparc/Makefile.sparc.shared Tue May 18 11:19:39 2010 +0800
+++ b/usr/src/uts/sparc/Makefile.sparc.shared Mon May 17 21:17:01 2010 -0700
@@ -201,7 +201,7 @@
#
# Common Drivers (usually pseudo drivers) (/kernel/drv):
#
-DRV_KMODS += aggr arp audio bl bofi clone cn conskbd consms cpuid
+DRV_KMODS += aggr arp audio bl blkdev bofi clone cn conskbd consms cpuid
DRV_KMODS += crypto cryptoadm devinfo dump
DRV_KMODS += dtrace fasttrap fbt lockstat profile sdt systrace dcpc
DRV_KMODS += fssnap icmp icmp6 ip ip6 ipnet ipsecah
@@ -425,7 +425,6 @@
MISC_KMODS += qlc_fw_2500
MISC_KMODS += qlc_fw_6322
MISC_KMODS += qlc_fw_8100
-MISC_KMODS += blk2scsa
MISC_KMODS += spuni
MISC_KMODS += hwa1480_fw uwba
MISC_KMODS += mii
--- a/usr/src/uts/sparc/blk2scsa/Makefile Tue May 18 11:19:39 2010 +0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,105 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-
-#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-#
-# This makefile drives the production of the blk2scsa driver
-# sparc architecture dependent
-#
-
-#
-# Paths to the base of the uts directory trees
-#
-UTSBASE = ../..
-
-#
-# Define the module and object file sets.
-#
-MODULE = blk2scsa
-OBJECTS = $(BLK2SCSA_OBJS:%=$(OBJS_DIR)/%)
-LINTS = $(BLK2SCSA_OBJS:%.o=$(LINTS_DIR)/%.ln)
-ROOTMODULE = $(ROOT_MISC_DIR)/$(MODULE)
-WARLOCK_OUT = $(BLK2SCSA_OBJS:%.o=%.ll)
-WARLOCK_OK = $(MODULE).ok
-WLCMD_DIR = $(UTSBASE)/common/io/warlock
-
-#
-# Include common rules.
-#
-include $(UTSBASE)/sparc/Makefile.sparc
-
-#
-# Define targets.
-#
-ALL_TARGET = $(BINARY)
-LINT_TARGET = $(MODULE).lint
-INSTALL_TARGET = $(BINARY) $(ROOTMODULE)
-
-#
-# Note dependancy on misc/scsi.
-#
-LDFLAGS += -dy -N"misc/scsi"
-
-#
-# Default build targets.
-#
-.KEEP_STATE:
-
-def: $(DEF_DEPS)
-
-all: $(ALL_DEPS)
-
-clean: $(CLEAN_DEPS)
-
-clobber: $(CLOBBER_DEPS)
-
-lint: $(LINT_DEPS)
-
-modlintlib: $(MODLINTLIB_DEPS)
-
-clean.lint: $(CLEAN_LINT_DEPS)
-
-install: $(INSTALL_DEPS)
-
-#
-# Include common targets.
-#
-include $(UTSBASE)/sparc/Makefile.targ
-
-WLCC = wlcc
-TOUCH = touch
-WARLOCK = warlock
-
-warlock: $(WARLOCK_OK)
-
-$(WARLOCK_OK): $(WARLOCK_OUT)
- $(WARLOCK) -c $(WLCMD_DIR)/blk2scsa.wlcmd \
- $(WARLOCK_OUT) \
- -l ../warlock/scsi.ll -l ../warlock/ddi_dki_impl.ll
- $(TOUCH) $@
-
-%.ll: $(UTSBASE)/common/io/scsi/adapters/blk2scsa/%.c
- $(WLCC) $(CPPFLAGS) -DDEBUG -o $@ $<
-
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/sparc/blkdev/Makefile Mon May 17 21:17:01 2010 -0700
@@ -0,0 +1,84 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+#
+
+#
+# This makefile drives the production of the blkdev driver
+#
+
+#
+# Paths to the base of the uts directory trees
+#
+UTSBASE = ../..
+
+#
+# Define the module and object file sets.
+#
+MODULE = blkdev
+OBJECTS = $(BLKDEV_OBJS:%=$(OBJS_DIR)/%)
+LINTS = $(BLKDEV_OBJS:%.o=$(LINTS_DIR)/%.ln)
+ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE)
+
+#
+# Include common rules.
+#
+include $(UTSBASE)/sparc/Makefile.sparc
+
+#
+# Define targets.
+#
+ALL_TARGET = $(BINARY)
+LINT_TARGET = $(MODULE).lint
+INSTALL_TARGET = $(BINARY) $(ROOTMODULE)
+
+#
+# Note dependancy on misc/scsi.
+#
+LDFLAGS += -dy -Nmisc/cmlb
+
+#
+# Default build targets.
+#
+.KEEP_STATE:
+
+def: $(DEF_DEPS)
+
+all: $(ALL_DEPS)
+
+clean: $(CLEAN_DEPS)
+
+clobber: $(CLOBBER_DEPS)
+
+lint: $(LINT_DEPS)
+
+modlintlib: $(MODLINTLIB_DEPS)
+
+clean.lint: $(CLEAN_LINT_DEPS)
+
+install: $(INSTALL_DEPS)
+
+#
+# Include common targets.
+#
+include $(UTSBASE)/sparc/Makefile.targ
--- a/usr/src/uts/sparc/warlock/Makefile Tue May 18 11:19:39 2010 +0800
+++ b/usr/src/uts/sparc/warlock/Makefile Mon May 17 21:17:01 2010 -0700
@@ -18,8 +18,7 @@
#
# CDDL HEADER END
#
-# Copyright 2010 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
#
# sparc architecture dependent
#
@@ -94,7 +93,6 @@
@cd ../ses; $(MAKE) clean; $(MAKE) warlock
@cd ../st; $(MAKE) clean; $(MAKE) warlock
@cd ../ssd; $(MAKE) clean; $(MAKE) warlock
- @cd ../blk2scsa; $(MAKE) clean; $(MAKE) warlock
$(CLOSED_BUILD) @cd $(CLOSED)/uts/sparc/uata; $(MAKE) clean; $(MAKE) warlock
$(CLOSED_BUILD) @cd $(CLOSED)/uts/sparc/glm; $(MAKE) clean; $(MAKE) warlock
$(CLOSED_BUILD) @cd $(CLOSED)/uts/sparc/mpt; $(MAKE) clean; $(MAKE) warlock