static char * sata_get_devicepath(const char *ap_id) { char *devpath = NULL; size_t size; cfga_sata_ret_t rv; rv = do_control_ioctl(ap_id, SATA_CFGA_GET_DEVICE_PATH, NULL, (void **)&devpath, &size); if (rv == CFGA_SATA_OK) { return (devpath); } else { return ((char *)NULL); } }
/* cfgadm entry point */ 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) { int len; char *msg; nvlist_t *list = NULL; ap_ostate_t ostate; ap_rstate_t rstate; devctl_hdl_t hdl = NULL; cfga_sata_ret_t rv; char *str_p; size_t size; if ((rv = verify_params(ap_id, NULL, errstring)) != CFGA_SATA_OK) { (void) cfga_help(msgp, options, flags); return (sata_err_msg(errstring, rv, ap_id, errno)); } /* * All subcommands which can change state of device require * root privileges. */ if (geteuid() != 0) { rv = CFGA_SATA_PRIV; goto bailout; } if (func == NULL) { (void) printf("No valid option specified\n"); rv = CFGA_SATA_OPTIONS; goto bailout; } if ((rv = setup_for_devctl_cmd(ap_id, &hdl, &list, 0)) != CFGA_SATA_OK) { goto bailout; } /* We do not care here about dynamic AP name component */ if ((str_p = GET_DYN(ap_id)) != NULL) { *str_p = '\0'; } rv = CFGA_SATA_OK; if (strcmp(func, SATA_RESET_PORT) == 0) { len = strlen(SATA_CONFIRM_PORT) + strlen(SATA_CONFIRM_DEVICE_ABORT) + strlen("Reset Port") + strlen(ap_id); if ((msg = (char *)calloc(len +3, 1)) != NULL) { (void) snprintf(msg, len +3, "Reset" " %s%s\n%s", SATA_CONFIRM_PORT, ap_id, SATA_CONFIRM_DEVICE_ABORT); } else { rv = CFGA_SATA_NACK; goto bailout; } if (!sata_confirm(confp, msg)) { rv = CFGA_SATA_NACK; goto bailout; } rv = do_control_ioctl(ap_id, SATA_CFGA_RESET_PORT, NULL, (void **)&str_p, &size); } else if (strcmp(func, SATA_RESET_DEVICE) == 0) { if ((rv = port_state(hdl, list, &rstate, &ostate)) != CFGA_SATA_OK) goto bailout; /* * Reset device function requires device to be connected */ if (rstate != AP_RSTATE_CONNECTED) { rv = CFGA_SATA_NOT_CONNECTED; goto bailout; } len = strlen(SATA_CONFIRM_DEVICE) + strlen(SATA_CONFIRM_DEVICE_ABORT) + strlen("Reset Device") + strlen(ap_id); if ((msg = (char *)calloc(len +3, 1)) != NULL) { (void) snprintf(msg, len +3, "Reset" " %s%s\n%s", SATA_CONFIRM_DEVICE, ap_id, SATA_CONFIRM_DEVICE_ABORT); } else { rv = CFGA_SATA_NACK; goto bailout; } if (!sata_confirm(confp, msg)) { rv = CFGA_SATA_NACK; goto bailout; } rv = do_control_ioctl(ap_id, SATA_CFGA_RESET_DEVICE, NULL, (void **)&str_p, &size); } else if (strcmp(func, SATA_RESET_ALL) == 0) { len = strlen(SATA_CONFIRM_CONTROLLER) + strlen(SATA_CONFIRM_CONTROLLER_ABORT) + strlen("Reset All") + strlen(ap_id); if ((msg = (char *)calloc(len +3, 1)) != NULL) { (void) snprintf(msg, len +3, "Reset" " %s%s\n%s", SATA_CONFIRM_CONTROLLER, ap_id, SATA_CONFIRM_CONTROLLER_ABORT); } else { rv = CFGA_SATA_NACK; goto bailout; } if (!sata_confirm(confp, msg)) { rv = CFGA_SATA_NACK; goto bailout; } rv = do_control_ioctl(ap_id, SATA_CFGA_RESET_ALL, NULL, (void **)&str_p, &size); } else if (strcmp(func, SATA_PORT_DEACTIVATE) == 0) { len = strlen(SATA_CONFIRM_PORT) + strlen(SATA_CONFIRM_PORT_DISABLE) + strlen("Deactivate Port") + strlen(ap_id); if ((msg = (char *)calloc(len +3, 1)) != NULL) { (void) snprintf(msg, len +3, "Deactivate" " %s%s\n%s", SATA_CONFIRM_PORT, ap_id, SATA_CONFIRM_PORT_DISABLE); } else { rv = CFGA_SATA_NACK; goto bailout; } if (!sata_confirm(confp, msg)) { rv = CFGA_SATA_NACK; goto bailout; } rv = do_control_ioctl(ap_id, SATA_CFGA_PORT_DEACTIVATE, NULL, (void **)&str_p, &size); } else if (strcmp(func, SATA_PORT_ACTIVATE) == 0) { len = strlen(SATA_CONFIRM_PORT) + strlen(SATA_CONFIRM_PORT_ENABLE) + strlen("Activate Port") + strlen(ap_id); if ((msg = (char *)calloc(len +3, 1)) != NULL) { (void) snprintf(msg, len +3, "Activate" " %s%s\n%s", SATA_CONFIRM_PORT, ap_id, SATA_CONFIRM_PORT_ENABLE); } else { rv = CFGA_SATA_NACK; goto bailout; } if (!sata_confirm(confp, msg)) { rv = CFGA_SATA_NACK; goto bailout; } rv = do_control_ioctl(ap_id, SATA_CFGA_PORT_ACTIVATE, NULL, (void **)&str_p, &size); goto bailout; } else if (strcmp(func, SATA_PORT_SELF_TEST) == 0) { len = strlen(SATA_CONFIRM_PORT) + strlen(SATA_CONFIRM_DEVICE_SUSPEND) + strlen("Self Test Port") + strlen(ap_id); if ((msg = (char *)calloc(len +3, 1)) != NULL) { (void) snprintf(msg, len +3, "Self Test" " %s%s\n%s", SATA_CONFIRM_PORT, ap_id, SATA_CONFIRM_DEVICE_SUSPEND); } else { rv = CFGA_SATA_NACK; goto bailout; } if (!sata_confirm(confp, msg)) { rv = CFGA_SATA_NACK; goto bailout; } rv = do_control_ioctl(ap_id, SATA_CFGA_PORT_SELF_TEST, NULL, (void **)&str_p, &size); } else { /* Unrecognized operation request */ rv = CFGA_SATA_HWOPNOTSUPP; } bailout: cleanup_after_devctl_cmd(hdl, list); return (sata_err_msg(errstring, rv, ap_id, errno)); }
/*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; size_t size; nvlist_t *user_nvlist = NULL; devctl_hdl_t devctl_hdl = NULL; cfga_sata_ret_t rv = CFGA_SATA_OK; devctl_ap_state_t devctl_ap_state; char *pdyn; if ((rv = verify_params(ap_id, options, errstring)) != CFGA_SATA_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_SATA_DATA_ERROR; (void) cfga_help(NULL, options, flags); goto bailout; } /* Get ap status */ if ((rv = setup_for_devctl_cmd(ap_id, &devctl_hdl, &user_nvlist, DC_RDONLY)) != CFGA_SATA_OK) { goto bailout; } /* will call dc_cmd to send IOCTL to kernel */ if (devctl_ap_getstate(devctl_hdl, user_nvlist, &devctl_ap_state) == -1) { cleanup_after_devctl_cmd(devctl_hdl, user_nvlist); rv = CFGA_SATA_IOCTL; goto bailout; } cleanup_after_devctl_cmd(devctl_hdl, user_nvlist); /* * Create cfga_list_data_t struct. */ if ((*ap_id_list = (cfga_list_data_t *)malloc(sizeof (**ap_id_list))) == NULL) { rv = CFGA_SATA_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_SATA_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_SATA_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_SATA_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_SATA_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_SATA_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) { char *str_p; int skip, i; /* * Fill in the 'Information' field for the -v option * Model (MOD:) */ if ((rv = do_control_ioctl(ap_id, SATA_CFGA_GET_MODEL_INFO, NULL, (void **)&str_p, &size)) != CFGA_SATA_OK) { (void) printf( "SATA_CFGA_GET_MODULE_INFO ioctl failed\n"); goto bailout; } /* drop leading and trailing spaces */ skip = strspn(str_p, " "); for (i = size - 1; i >= 0; i--) { if (str_p[i] == '\040') str_p[i] = '\0'; else if (str_p[i] != '\0') break; } (void) strlcpy((*ap_id_list)->ap_info, "Mod: ", sizeof ((*ap_id_list)->ap_info)); (void) strlcat((*ap_id_list)->ap_info, str_p + skip, sizeof ((*ap_id_list)->ap_info)); free(str_p); /* * Fill in the 'Information' field for the -v option * Firmware revision (FREV:) */ if ((rv = do_control_ioctl(ap_id, SATA_CFGA_GET_REVFIRMWARE_INFO, NULL, (void **)&str_p, &size)) != CFGA_SATA_OK) { (void) printf( "SATA_CFGA_GET_REVFIRMWARE_INFO ioctl failed\n"); goto bailout; } /* drop leading and trailing spaces */ skip = strspn(str_p, " "); for (i = size - 1; i >= 0; i--) { if (str_p[i] == '\040') str_p[i] = '\0'; else if (str_p[i] != '\0') break; } (void) strlcat((*ap_id_list)->ap_info, " FRev: ", sizeof ((*ap_id_list)->ap_info)); (void) strlcat((*ap_id_list)->ap_info, str_p + skip, sizeof ((*ap_id_list)->ap_info)); free(str_p); /* * Fill in the 'Information' field for the -v option * Serial Number (SN:) */ if ((rv = do_control_ioctl(ap_id, SATA_CFGA_GET_SERIALNUMBER_INFO, NULL, (void **)&str_p, &size)) != CFGA_SATA_OK) { (void) printf( "SATA_CFGA_GET_SERIALNUMBER_INFO ioctl failed\n"); goto bailout; } /* drop leading and trailing spaces */ skip = strspn(str_p, " "); for (i = size - 1; i >= 0; i--) { if (str_p[i] == '\040') str_p[i] = '\0'; else if (str_p[i] != '\0') break; } (void) strlcat((*ap_id_list)->ap_info, " SN: ", sizeof ((*ap_id_list)->ap_info)); (void) strlcat((*ap_id_list)->ap_info, str_p + skip, sizeof ((*ap_id_list)->ap_info)); free(str_p); /* Fill in ap_type which is collected from HBA driver */ /* call do_control_ioctl TBD */ if ((rv = do_control_ioctl(ap_id, SATA_CFGA_GET_AP_TYPE, NULL, (void **)&str_p, &size)) != CFGA_SATA_OK) { (void) printf( "SATA_CFGA_GET_AP_TYPE ioctl failed\n"); goto bailout; } (void) strlcpy((*ap_id_list)->ap_type, str_p, sizeof ((*ap_id_list)->ap_type)); free(str_p); 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. */ rv = sata_make_dyncomp(ap_id, &dyncomp); if (rv != CFGA_SATA_OK) goto bailout; 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 { /* Change it when port multiplier is supported */ (void) strlcpy((*ap_id_list)->ap_type, "sata-port", sizeof ((*ap_id_list)->ap_type)); } return (sata_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 (sata_err_msg(errstring, rv, ap_id, errno)); }
/*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; int len; char *msg; char *devpath; nvlist_t *nvl = NULL; ap_rstate_t rstate; ap_ostate_t ostate; devctl_hdl_t hdl = NULL; cfga_sata_ret_t rv = CFGA_SATA_OK; char *pdyn; char *str_type; size_t size; boolean_t pmult = B_FALSE; /* * All sub-commands which can change state of device require * root privileges. */ if (geteuid() != 0) { rv = CFGA_SATA_PRIV; goto bailout; } if ((rv = verify_params(ap_id, options, errstring)) != CFGA_SATA_OK) { (void) cfga_help(msgp, options, flags); goto bailout; } if ((rv = setup_for_devctl_cmd(ap_id, &hdl, &nvl, DC_RDONLY)) != CFGA_SATA_OK) { goto bailout; } /* * Checking device type. A port multiplier is not configurable - it is * already configured as soon as it is connected. */ if ((rv = do_control_ioctl(ap_id, SATA_CFGA_GET_AP_TYPE, NULL, (void **)&str_type, &size)) != CFGA_SATA_OK) { /* no such deivce */ goto bailout; } if (strncmp(str_type, "sata-pmult", sizeof ("sata-pmult")) == 0) { pmult = B_TRUE; } switch (state_change_cmd) { case CFGA_CMD_CONFIGURE: if (pmult == B_TRUE) { rv = CFGA_SATA_HWOPNOTSUPP; goto bailout; } if ((rv = port_state(hdl, nvl, &rstate, &ostate)) != CFGA_SATA_OK) goto bailout; if (ostate == AP_OSTATE_CONFIGURED) { rv = CFGA_SATA_ALREADY_CONFIGURED; goto bailout; } /* Disallow dynamic AP name component */ if (GET_DYN(ap_id) != NULL) { rv = CFGA_SATA_INVALID_DEVNAME; goto bailout; } if (rstate == AP_RSTATE_EMPTY) { rv = CFGA_SATA_NOT_CONNECTED; goto bailout; } rv = CFGA_SATA_OK; if (devctl_ap_configure(hdl, nvl) != 0) { rv = CFGA_SATA_DEV_CONFIGURE; goto bailout; } devpath = sata_get_devicepath(ap_id); if (devpath == NULL) { int i; /* * Try for some time as SATA hotplug thread * takes a while to create the path then * eventually give up. */ for (i = 0; i < 12 && (devpath == NULL); i++) { (void) sleep(6); devpath = sata_get_devicepath(ap_id); } if (devpath == NULL) { rv = CFGA_SATA_DEV_CONFIGURE; break; } } S_FREE(devpath); break; case CFGA_CMD_UNCONFIGURE: if (pmult == B_TRUE) { rv = CFGA_SATA_HWOPNOTSUPP; goto bailout; } if ((rv = port_state(hdl, nvl, &rstate, &ostate)) != CFGA_SATA_OK) goto bailout; if (rstate != AP_RSTATE_CONNECTED) { rv = CFGA_SATA_NOT_CONNECTED; goto bailout; } if (ostate != AP_OSTATE_CONFIGURED) { rv = CFGA_SATA_NOT_CONFIGURED; goto bailout; } /* Strip off AP name dynamic component, if present */ if ((pdyn = GET_DYN(ap_id)) != NULL) { *pdyn = '\0'; } rv = CFGA_SATA_OK; len = strlen(SATA_CONFIRM_DEVICE) + strlen(SATA_CONFIRM_DEVICE_SUSPEND) + strlen("Unconfigure") + strlen(ap_id); if ((msg = (char *)calloc(len +3, 1)) != NULL) { (void) snprintf(msg, len + 3, "Unconfigure" " %s%s\n%s", SATA_CONFIRM_DEVICE, ap_id, SATA_CONFIRM_DEVICE_SUSPEND); } if (!sata_confirm(confp, msg)) { free(msg); rv = CFGA_SATA_NACK; break; } free(msg); devpath = sata_get_devicepath(ap_id); if (devpath == NULL) { (void) printf( "cfga_change_state: get device path failed\n"); rv = CFGA_SATA_DEV_UNCONFIGURE; break; } if ((rv = sata_rcm_offline(ap_id, errstring, devpath, flags)) != CFGA_SATA_OK) { break; } ret = devctl_ap_unconfigure(hdl, nvl); if (ret != 0) { rv = CFGA_SATA_DEV_UNCONFIGURE; if (errno == EBUSY) { rv = CFGA_SATA_BUSY; } (void) sata_rcm_online(ap_id, errstring, devpath, flags); } else { (void) sata_rcm_remove(ap_id, errstring, devpath, flags); } S_FREE(devpath); break; case CFGA_CMD_DISCONNECT: if ((rv = port_state(hdl, nvl, &rstate, &ostate)) != CFGA_SATA_OK) goto bailout; if (rstate == AP_RSTATE_DISCONNECTED) { rv = CFGA_SATA_DISCONNECTED; goto bailout; } /* Strip off AP name dynamic component, if present */ if ((pdyn = GET_DYN(ap_id)) != NULL) { *pdyn = '\0'; } rv = CFGA_SATA_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. sata_get_devicepath in this case is not necessary. */ /* only call rcm_offline if the state was CONFIGURED */ if (ostate == AP_OSTATE_CONFIGURED && pmult == B_FALSE) { devpath = sata_get_devicepath(ap_id); if (devpath == NULL) { (void) printf( "cfga_change_state: get path failed\n"); rv = CFGA_SATA_DEV_UNCONFIGURE; break; } len = strlen(SATA_CONFIRM_DEVICE) + strlen(SATA_CONFIRM_DEVICE_SUSPEND) + strlen("Disconnect") + strlen(ap_id); if ((msg = (char *)calloc(len +3, 1)) != NULL) { (void) snprintf(msg, len + 3, "Disconnect" " %s%s\n%s", SATA_CONFIRM_DEVICE, ap_id, SATA_CONFIRM_DEVICE_SUSPEND); } if (!sata_confirm(confp, msg)) { free(msg); rv = CFGA_SATA_NACK; break; } free(msg); if ((rv = sata_rcm_offline(ap_id, errstring, devpath, flags)) != CFGA_SATA_OK) { break; } ret = devctl_ap_unconfigure(hdl, nvl); if (ret != 0) { (void) printf( "devctl_ap_unconfigure failed\n"); rv = CFGA_SATA_DEV_UNCONFIGURE; if (errno == EBUSY) rv = CFGA_SATA_BUSY; (void) sata_rcm_online(ap_id, errstring, devpath, flags); S_FREE(devpath); /* * The current policy is that if unconfigure * failed, do not continue with disconnect. * If the port needs to be forced into the * disconnect (shutdown) state, * the -x sata_port_poweroff command should be * used instead of -c disconnect */ break; } else { (void) printf("%s\n", ERR_STR(CFGA_SATA_DEVICE_UNCONFIGURED)); (void) sata_rcm_remove(ap_id, errstring, devpath, flags); } S_FREE(devpath); } else if (rstate == AP_RSTATE_CONNECTED || rstate == AP_RSTATE_EMPTY) { len = strlen(SATA_CONFIRM_PORT) + strlen(SATA_CONFIRM_PORT_DISABLE) + strlen("Deactivate Port") + strlen(ap_id); if ((msg = (char *)calloc(len +3, 1)) != NULL) { (void) snprintf(msg, len +3, "Disconnect" " %s%s\n%s", SATA_CONFIRM_PORT, ap_id, SATA_CONFIRM_PORT_DISABLE); } if (!sata_confirm(confp, msg)) { free(msg); rv = CFGA_SATA_NACK; break; } } ret = devctl_ap_disconnect(hdl, nvl); if (ret != 0) { rv = CFGA_SATA_IOCTL; if (errno == EBUSY) { rv = CFGA_SATA_BUSY; } } break; case CFGA_CMD_CONNECT: if ((rv = port_state(hdl, nvl, &rstate, &ostate)) != CFGA_SATA_OK) goto bailout; if (rstate == AP_RSTATE_CONNECTED) { rv = CFGA_SATA_ALREADY_CONNECTED; goto bailout; } len = strlen(SATA_CONFIRM_PORT) + strlen(SATA_CONFIRM_PORT_ENABLE) + strlen("Activate Port") + strlen(ap_id); if ((msg = (char *)calloc(len +3, 1)) != NULL) { (void) snprintf(msg, len +3, "Activate" " %s%s\n%s", SATA_CONFIRM_PORT, ap_id, SATA_CONFIRM_PORT_ENABLE); } if (!sata_confirm(confp, msg)) { rv = CFGA_SATA_NACK; break; } /* Disallow dynamic AP name component */ if (GET_DYN(ap_id) != NULL) { rv = CFGA_SATA_INVALID_DEVNAME; goto bailout; } ret = devctl_ap_connect(hdl, nvl); if (ret != 0) { rv = CFGA_SATA_IOCTL; } else { rv = CFGA_SATA_OK; } break; case CFGA_CMD_LOAD: case CFGA_CMD_UNLOAD: (void) cfga_help(msgp, options, flags); rv = CFGA_SATA_OPNOTSUPP; break; case CFGA_CMD_NONE: default: (void) cfga_help(msgp, options, flags); rv = CFGA_SATA_INTERNAL_ERROR; } bailout: cleanup_after_devctl_cmd(hdl, nvl); return (sata_err_msg(errstring, rv, ap_id, errno)); }