Mercurial > illumos > illumos-gate
changeset 12426:cdff5d2ea989
PSARC 2009/646 bd - generic block device driver
PSARC 2009/648 sdcard conversion to bd, EOF blk2scsa
6952618 deliver blkdev (PSARC 2009/646)
line wrap: on
line diff
--- 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