66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * CDDL HEADER START
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * The contents of this file are subject to the terms of the
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Common Development and Distribution License (the "License").
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * You may not use this file except in compliance with the License.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * See the License for the specific language governing permissions
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * and limitations under the License.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * When distributing Covered Code, include this CDDL HEADER in each
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If applicable, add the following below this CDDL HEADER, with the
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * fields enclosed by brackets "[]" replaced with your own identifying
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * information: Portions Copyright [yyyy] [name of copyright owner]
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * CDDL HEADER END
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Use is subject to license terms.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * This file contains the entry points to the plug-in as defined in the
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * config_admin(3X) man page.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Set the version number for the cfgadm library's use.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/* SATA specific help messages */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "SATA specific commands:\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf " cfgadm -c [configure|unconfigure|disconnect|connect] ap_id "
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "[ap_id...]\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf " cfgadm -x sata_reset_port ap_id [ap_id...]\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf " cfgadm -x sata_reset_device ap_id [ap_id...]\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf " cfgadm -x sata_reset_all ap_id\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf " cfgadm -x sata_port_deactivate ap_id [ap_id...]\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf " cfgadm -x sata_port_activate ap_id [ap_id...]\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf " cfgadm -x sata_port_self_test ap_id [ap_id...]\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf " cfgadm -t ap_id\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "\tunknown command or option:\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}; /* End help messages */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Messages.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* CFGA_SATA_OK */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* CFGA_SATA_NACK */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* CFGA_SATA_DEVICE_UNCONFIGURED */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf { CVT, CFGA_OK, "Device unconfigured prior to disconnect" },
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* CFGA_SATA_UNKNOWN / CFGA_LIB_ERROR -> "Library error" */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf { CVT, CFGA_LIB_ERROR, "Unknown message; internal error" },
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* CFGA_SATA_INTERNAL_ERROR / CFGA_LIB_ERROR -> "Library error" */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* CFGA_SATA_DATA_ERROR / CFGA_DATA_ERROR -> "Data error" */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* CFGA_SATA_OPTIONS / CFGA_ERROR -> "Hardware specific failure" */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf { CVT, CFGA_ERROR, "Hardware specific option not supported" },
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* CFGA_SATA_HWOPNOTSUPP / CFGA_ERROR -> "Hardware specific failure" */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf { CVT, CFGA_ERROR, "Hardware specific operation not supported" },
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * CFGA_SATA_DYNAMIC_AP /
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * CFGA_LIB_ERROR -> "Configuration operation invalid"
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* CFGA_SATA_AP / CFGA_APID_NOEXIST -> "Attachment point not found" */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* CFGA_SATA_PORT / CFGA_LIB_ERROR -> "Library error" */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf { CVT, CFGA_LIB_ERROR, "Cannot determine sata port number for " },
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* CFGA_SATA_DEVCTL / CFGA_LIB_ERROR -> "Library error" */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "Cannot allocate devctl handle " },
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * CFGA_SATA_DEV_CONFIGURE /
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * CFGA_ERROR -> "Hardware specific failure"
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * CFGA_SATA_DEV_UNCONFIGURE /
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * CFGA_ERROR -> "Hardware specific failure"
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * CFGA_SATA_DISCONNECTED
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * CFGA_INVAL -> "Configuration operation invalid"
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * CFGA_SATA_NOT_CONNECTED
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * CFGA_INVAL -> "Configuration operation invalid"
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * CFGA_SATA_NOT_CONFIGURED /
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * CFGA_INVAL -> "Configuration operation invalid"
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * CFGA_SATA_ALREADY_CONNECTED /
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * CFGA_INVAL -> "Configuration operation invalid"
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * CFGA_SATA_ALREADY_CONFIGURED /
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * CFGA_INVAL -> "Configuration operation invalid"
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * CFGA_SATA_INVALID_DEVNAME /
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * CFGA_INVAL -> "Configuration operation invalid"
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* CFGA_SATA_OPEN / CFGA_LIB_ERROR -> "Library error" */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* CFGA_SATA_IOCTL / CFGA_ERROR -> "Hardware specific failure" */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * CFGA_SATA_BUSY /
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * CFGA_SYSTEM_BUSY -> "System is busy, try again"
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* CFGA_SATA_ALLOC_FAIL / CFGA_LIB_ERROR -> "Library error" */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * CFGA_SATA_OPNOTSUPP /
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * CFGA_OPNOTSUPP -> "Configuration operation not supported"
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* CFGA_SATA_DEVLINK / CFGA_LIB_ERROR -> "Library error" */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf { CVT, CFGA_LIB_ERROR, "Could not find /dev/cfg link for " },
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* CFGA_SATA_STATE / CFGA_LIB_ERROR -> "Library error" */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf { CVT, CFGA_LIB_ERROR, "Internal error: Unrecognized ap state" },
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* CFGA_SATA_PRIV / CFGA_PRIV -> "Insufficient privileges" */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* CFGA_SATA_NVLIST / CFGA_ERROR -> "Hardware specific failure" */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* CFGA_SATA_ZEROLEN / CFGA_ERROR -> "Hardware specific failure" */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf { CVT, CFGA_ERROR, "Internal error (zerolength string)" },
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* CFGA_SATA_RCM_HANDLE / CFGA_ERROR -> "Hardware specific failure" */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * CFGA_SATA_RCM_ONLINE /
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * CFGA_SYSTEM_BUSY -> "System is busy, try again"
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * CFGA_SATA_RCM_OFFLINE /
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * CFGA_SYSTEM_BUSY -> "System is busy, try again"
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* CFGA_SATA_RCM_INFO / CFGA_ERROR -> "Hardware specific failure" */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf}; /* End error messages */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfverify_params(const char *ap_id, const char *options, char **errstring);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfsetup_for_devctl_cmd(const char *ap_id, devctl_hdl_t *devctl_hdl,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfdo_control_ioctl(const char *ap_id, sata_cfga_apctl_t subcommand, uint_t arg,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfcleanup_after_devctl_cmd(devctl_hdl_t devctl_hdl, nvlist_t *user_nvlist);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic char *
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhangget_port_num(const char *ap_id, uint32_t *port);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/* Utilities */
724365f7556fc4201fdb11766ebc6bd918523130sethgphyspath_to_devlink(const char *basedir, const char *node_path,
724365f7556fc4201fdb11766ebc6bd918523130sethg * Using libdevinfo for this is overkill and kills performance
724365f7556fc4201fdb11766ebc6bd918523130sethg * when multiple consumers of libcfgadm are executing
724365f7556fc4201fdb11766ebc6bd918523130sethg * concurrently.
724365f7556fc4201fdb11766ebc6bd918523130sethg sizeof (struct dirent);
724365f7556fc4201fdb11766ebc6bd918523130sethg while (!found && (err = readdir_r(dp, dep, &newdep)) == 0 &&
724365f7556fc4201fdb11766ebc6bd918523130sethg * realpath() is too darn slow, so fake
724365f7556fc4201fdb11766ebc6bd918523130sethg * it, by using what we know about /dev
724365f7556fc4201fdb11766ebc6bd918523130sethg * links: they are always of the form:
724365f7556fc4201fdb11766ebc6bd918523130sethg * <"../">+/devices/<path>
724365f7556fc4201fdb11766ebc6bd918523130sethg p--; /* back up to get a slash */
724365f7556fc4201fdb11766ebc6bd918523130sethg if (err != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Given the index into a table (msgcvt_t) of messages, get the message
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * string, converting it to the proper locale if necessary.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * NOTE: Indexes are defined in cfga_sata.h
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic const char *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfget_msg(uint_t msg_index, msgcvt_t *msg_tbl, uint_t tbl_size)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang dgettext(TEXT_DOMAIN, msg_tbl[msg_index].msgstr) :
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Allocates and creates a message string (in *ret_str),
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * by concatenating all the (char *) args together, in order.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Last arg MUST be NULL.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf *ret_str = (char *)realloc(*ret_str, total_len + len + 1);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* We're screwed */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Error message handling.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * For the rv passed in, looks up the corresponding error message string(s),
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * internationalized if necessary, and concatenates it into a new
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * memory buffer, and points *errstring to it.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Note not all rvs will result in an error message return, as not all
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * error conditions warrant a SATA-specific error message - for those
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * conditions the cfgadm generic messages are sufficient.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Some messages may display ap_id or errno, which is why they are passed
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Generate the appropriate SATA-specific error message(s) (if any).
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf switch (rv) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Special case - do nothing. */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* These messages require no additional strings passed. */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* hardware-specific help needed */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang dgettext(TEXT_DOMAIN, sata_help[HELP_HEADER]), NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf set_msg(errstring, sata_help[HELP_PORT_ACTIVATE], NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf set_msg(errstring, sata_help[HELP_PORT_DEACTIVATE], NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf set_msg(errstring, sata_help[HELP_PORT_SELF_TEST], NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf set_msg(errstring, sata_help[HELP_CNTRL_SELF_TEST], NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* These messages also print ap_id. */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf set_msg(errstring, ERR_STR(rv), "ap_id: ", ap_id, "", NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* These messages also print errno. */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* These messages also apid and errno. */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf set_msg(errstring, ERR_STR(CFGA_SATA_INTERNAL_ERROR), NULL);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf } /* end switch */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Determine the proper error code to send back to the cfgadm library.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Entry points
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/* cfgadm entry point */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*ARGSUSED*/
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * All sub-commands which can change state of device require
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * root privileges.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (geteuid() != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((rv = verify_params(ap_id, options, errstring)) != CFGA_SATA_OK) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Checking device type. A port multiplier is not configurable - it is
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * already configured as soon as it is connected.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((rv = do_control_ioctl(ap_id, SATA_CFGA_GET_AP_TYPE, NULL,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (void **)&str_type, &size)) != CFGA_SATA_OK) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* no such deivce */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (strncmp(str_type, "sata-pmult", sizeof ("sata-pmult")) == 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Disallow dynamic AP name component */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Try for some time as SATA hotplug thread
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * takes a while to create the path then
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * eventually give up.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Strip off AP name dynamic component, if present */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "cfga_change_state: get device path failed\n");
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((rv = sata_rcm_offline(ap_id, errstring, devpath, flags))
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ret != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Strip off AP name dynamic component, if present */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If the port originally with device attached and was
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * unconfigured already, the devicepath for the sd will be
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * removed. sata_get_devicepath in this case is not necessary.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* only call rcm_offline if the state was CONFIGURED */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "cfga_change_state: get path failed\n");
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ret != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "devctl_ap_unconfigure failed\n");
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * The current policy is that if unconfigure
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * failed, do not continue with disconnect.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * If the port needs to be forced into the
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * disconnect (shutdown) state,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * the -x sata_port_poweroff command should be
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * used instead of -c disconnect
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ret != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Disallow dynamic AP name component */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (ret != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/* cfgadm entry point */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((rv = verify_params(ap_id, NULL, errstring)) != CFGA_SATA_OK) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * All subcommands which can change state of device require
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * root privileges.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (geteuid() != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((rv = setup_for_devctl_cmd(ap_id, &hdl, &list, 0)) !=
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* We do not care here about dynamic AP name component */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = do_control_ioctl(ap_id, SATA_CFGA_RESET_PORT, NULL,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Reset device function requires device to be connected
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = do_control_ioctl(ap_id, SATA_CFGA_RESET_DEVICE, NULL,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = do_control_ioctl(ap_id, SATA_CFGA_PORT_DEACTIVATE, NULL,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Unrecognized operation request */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/* cfgadm entry point */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*ARGSUSED*/
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Should call ioctl for self test - phase 2 */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf minorpath = di_devfs_minor_path(di_minor_next(node, DI_MINOR_NIL));
d7b0e458c7037dd10fe3ea153208b18f5b11c8cavikram/*ARGSUSED*/
d7b0e458c7037dd10fe3ea153208b18f5b11c8cavikramchk_dev_fcn(di_node_t node, di_minor_t minor, void *arg)
d7b0e458c7037dd10fe3ea153208b18f5b11c8cavikram chkp->c_isblk = di_minor_spectype(minor) == S_IFBLK ? 1 : 0;
d7b0e458c7037dd10fe3ea153208b18f5b11c8cavikram * Don't use devfs if stat() in /devices fails. Use libdevinfo instead.
d7b0e458c7037dd10fe3ea153208b18f5b11c8cavikram * Retired devices don't show up in devfs.
d7b0e458c7037dd10fe3ea153208b18f5b11c8cavikram * 1 - minor exists and is of type BLK
d7b0e458c7037dd10fe3ea153208b18f5b11c8cavikram * 0 - minor does not exist or is not of type BLK.
d7b0e458c7037dd10fe3ea153208b18f5b11c8cavikram * prune minor path for di_init() - no /devices prefix and no minor name
d7b0e458c7037dd10fe3ea153208b18f5b11c8cavikram if (strncmp(minor_path, "/devices/", strlen("/devices/")) != 0)
d7b0e458c7037dd10fe3ea153208b18f5b11c8cavikram return (0);
d7b0e458c7037dd10fe3ea153208b18f5b11c8cavikram return (0);
d7b0e458c7037dd10fe3ea153208b18f5b11c8cavikram node = di_init(minor_path + strlen("/devices"), DINFOMINOR);
d7b0e458c7037dd10fe3ea153208b18f5b11c8cavikram return (0);
d7b0e458c7037dd10fe3ea153208b18f5b11c8cavikram rv = di_walk_minor(node, NULL, 0, &chk_dev, chk_dev_fcn);
d7b0e458c7037dd10fe3ea153208b18f5b11c8cavikram return (1);
d7b0e458c7037dd10fe3ea153208b18f5b11c8cavikram return (0);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * The dynamic component buffer returned by this function has to be freed!
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing Chinasata_make_dyncomp(const char *ap_id, char **dyncomp, const char *type)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Get target node path
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) printf("cfga_list_ext: cannot locate target device\n");
724365f7556fc4201fdb11766ebc6bd918523130sethg * Using libdevinfo for this is overkill and kills
724365f7556fc4201fdb11766ebc6bd918523130sethg * performance when many consumers are using libcfgadm
724365f7556fc4201fdb11766ebc6bd918523130sethg * concurrently.
724365f7556fc4201fdb11766ebc6bd918523130sethg * deplen is large enough to fit the largest path-
724365f7556fc4201fdb11766ebc6bd918523130sethg * struct dirent includes one byte (the terminator)
724365f7556fc4201fdb11766ebc6bd918523130sethg * so we don't add 1 to the calculation here.
724365f7556fc4201fdb11766ebc6bd918523130sethg sizeof (struct dirent);
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China * Break directly for tape device
d7b0e458c7037dd10fe3ea153208b18f5b11c8cavikram * If stat() fails, the device *may* be retired.
d7b0e458c7037dd10fe3ea153208b18f5b11c8cavikram * Check via libdevinfo if the device has a BLK minor.
d7b0e458c7037dd10fe3ea153208b18f5b11c8cavikram * We don't use libdevinfo all the time, since taking
d7b0e458c7037dd10fe3ea153208b18f5b11c8cavikram * a snapshot is slower than a stat().
724365f7556fc4201fdb11766ebc6bd918523130sethg * If there was an error, or we didn't exit the loop
724365f7556fc4201fdb11766ebc6bd918523130sethg * by finding a block or character device, bail out.
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China * Look for links to the physical path in /dev/dsk
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China * and /dev/rmt. So far, sata modue supports disk,
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China * dvd and tape devices, so we will first look for
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China * BLOCK devices, and then look for tape devices.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* postprocess and copy logical name here */
545e5dad7996785cfebf226c5ef410c1b154740fsethg * For disks, remove partition/slice info
545e5dad7996785cfebf226c5ef410c1b154740fsethg /* cXtYdZ[(s[0..15])|(p[0..X])] */
545e5dad7996785cfebf226c5ef410c1b154740fsethg p++; /* Skip the 'd' */
545e5dad7996785cfebf226c5ef410c1b154740fsethg while (*p != 0 && isdigit(*p))
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China } else if (strcmp(type, "tape") == 0) {
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China * For tape device, logical name looks like
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China (void) physpath_to_devlink("/dev/rmt",
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China if ((cp = strstr(devlink, "rmt/")) != NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/* cfgadm entry point */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/*ARGSUSED*/
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((rv = verify_params(ap_id, options, errstring)) != CFGA_SATA_OK) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* We do not care here about dynamic AP name component */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Get ap status */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((rv = setup_for_devctl_cmd(ap_id, &devctl_hdl, &user_nvlist,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* will call dc_cmd to send IOCTL to kernel */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Create cfga_list_data_t struct.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (cfga_list_data_t *)malloc(sizeof (**ap_id_list))) == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Rest of the code fills in the cfga_list_data_t struct.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Get /dev/cfg path to corresponding to the physical ap_id */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Remember ap_id_log must be freed */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (rv != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Get logical ap_id corresponding to the physical */
20e7b521b938d6074a4b93c9c2f69c6281a26e3asethg if (ap_id_log == NULL || strstr(ap_id_log, CFGA_DEV_DIR) == NULL) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Strip off /dev/cfg/ */ ap_id_log + strlen(CFGA_DEV_DIR)+ 1,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (*ap_id_list)->ap_r_state = CFGA_STAT_DISCONNECTED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (*ap_id_list)->ap_r_state = CFGA_STAT_CONNECTED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (*ap_id_list)->ap_o_state = CFGA_STAT_CONFIGURED;
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (*ap_id_list)->ap_o_state = CFGA_STAT_UNCONFIGURED;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (*ap_id_list)->ap_class[0] = '\0'; /* Filled by libcfgadm */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (*ap_id_list)->ap_busy = devctl_ap_state.ap_in_transition;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (*ap_id_list)->ap_status_time = devctl_ap_state.ap_last_change;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Fill in the 'Information' field for the -v option
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Model (MOD:)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((rv = do_control_ioctl(ap_id, SATA_CFGA_GET_MODEL_INFO,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "SATA_CFGA_GET_MODULE_INFO ioctl failed\n");
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* drop leading and trailing spaces */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Fill in the 'Information' field for the -v option
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Firmware revision (FREV:)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "SATA_CFGA_GET_REVFIRMWARE_INFO ioctl failed\n");
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* drop leading and trailing spaces */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Fill in the 'Information' field for the -v option
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Serial Number (SN:)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf "SATA_CFGA_GET_SERIALNUMBER_INFO ioctl failed\n");
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* drop leading and trailing spaces */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Fill in ap_type which is collected from HBA driver */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* call do_control_ioctl TBD */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((rv = do_control_ioctl(ap_id, SATA_CFGA_GET_AP_TYPE, NULL,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "SATA_CFGA_GET_AP_TYPE ioctl failed\n");
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Checking device type. Port multiplier has no dynamic
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if (strncmp((*ap_id_list)->ap_type, "sata-pmult",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang sizeof ("sata-pmult")) == 0)
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((*ap_id_list)->ap_o_state == CFGA_STAT_CONFIGURED &&
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * This is the case where we need to generate
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * a dynamic component of the ap_id, i.e. device.
385470574fb49e32c324af06c01d697a16cc3c4bying tian - Beijing China rv = sata_make_dyncomp(ap_id, &dyncomp,
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* This is an empty port */
2c2d21e98a95cba5687ec6574c974a5c6c4a6adbRichard Lowe if (get_port_num(ap_id, &port) != CFGA_SATA_OK) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (void) strlcpy((*ap_id_list)->ap_type, "pmult-port",
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang (void) strlcpy((*ap_id_list)->ap_type, "sata-port",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * This routine accepts a string adn prints it using
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * the message print routine argument.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/* cfgadm entry point */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf/* ARGSUSED */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfcfga_help(struct cfga_msg *msgp, const char *options, cfga_flags_t flags)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cfga_msg(msgp, dgettext(TEXT_DOMAIN, sata_help[HELP_UNKNOWN]));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf cfga_msg(msgp, dgettext(TEXT_DOMAIN, sata_help[HELP_HEADER]));
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Ensure the ap_id passed is in the correct (physical ap_id) form:
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * where xx is a one or two-digit number.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Note the library always calls the plugin with a physical ap_id.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (-1);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (strspn(l_ap_id, "0123456789.") != strlen(l_ap_id)) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Bad characters in the ap_id */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (-1);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* ap_id has 1..2 or more than 2 dots */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (-1);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (0);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Verify the params passed in are valid.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Strip dynamic AP name component if it is present. */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Takes a validated ap_id and extracts the port number.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang * Port multiplier is supported now.
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Get the cport number */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang cport_str = strrchr(ap_id, (int)*MINOR_SEP) + strlen(MINOR_SEP);
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((cport & ~SATA_CFGA_CPORT_MASK) != 0 || errno != 0) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang /* Get pmport number if there is a PORT_SEPARATOR */
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((pmport_str = strrchr(ap_id, (int)*PORT_SEPARATOR)) != 0) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang if ((pmport & ~SATA_CFGA_PMPORT_MASK) != 0 || errno != 0) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang *port = cport | (pmport << SATA_CFGA_PMPORT_SHIFT) | qual;
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Pair of routines to set up for/clean up after a devctl_ap_* lib call.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic void
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfcleanup_after_devctl_cmd(devctl_hdl_t devctl_hdl, nvlist_t *user_nvlist)
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Get a devctl handle to pass to the devctl_ap_XXX functions */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((*devctl_hdl = devctl_ap_acquire((char *)lap_id, oflag)) == NULL) {
724365f7556fc4201fdb11766ebc6bd918523130sethg "setup_for_devctl_cmd: devctl_ap_acquire failed: %s\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Set up nvlist to pass the port number down to the driver */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (nvlist_alloc(user_nvlistp, NV_UNIQUE_NAME_TYPE, NULL) != 0) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Get port id, for Port Multiplier port, things could be a little bit
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * complicated because of "port.port" format in ap_id, thus for
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * port multiplier port, port number should be coded as 32bit int
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * with the sig 16 bit as sata channel number, least 16 bit as
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * the port number of sata port multiplier port.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((rv = get_port_num(lap_id, &port)) != CFGA_SATA_OK) {
8aa6aadbbfba50077655c6a46a5e269c880e4ab4Xiao-Yu Zhang "setup_for_devctl_cmd: get_port_num, errno: %d\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Creates an int32_t entry */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (nvlist_add_int32(*user_nvlistp, PORT, port) == -1) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) cleanup_after_devctl_cmd(*devctl_hdl, *user_nvlistp);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if (devctl_ap_getstate(hdl, list, &devctl_ap_state) == -1) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) printf("devctl_ap_getstate failed, errno: %d\n", errno);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Given a subcommand to the DEVCTL_AP_CONTROL ioctl, rquest the size of
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * the data to be returned, allocate a buffer, then get the data.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Returns *descrp (which must be freed) and size.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Note SATA_DESCR_TYPE_STRING returns an ASCII NULL-terminated string,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * not a string descr.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfdo_control_ioctl(const char *ap_id, sata_cfga_apctl_t subcommand, uint_t arg,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf if ((rv = get_port_num(ap_id, &port)) != CFGA_SATA_OK) {
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf (void) printf("do_control_ioctl: open failed: errno:%d\n",
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Find out how large a buf we need to get the data.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * Note the ioctls only accept/return a 32-bit int for a get_size
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf * to avoid 32/64 and BE/LE issues.
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf /* Execute IOCTL */
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return (0);
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlfstatic char *
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf rv = do_control_ioctl(ap_id, SATA_CFGA_GET_DEVICE_PATH, NULL,
66f9d5cb3cc0652e2d9d1366fb950efbe4ca2f24mlf return ((char *)NULL);