/* * 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. * * 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 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include #include #include #include /* * misc config_admin(3cfgadm) related routines */ static struct { cfga_stat_t stat; char *name; } pcidr_cfga_stat_nametab[] = { {CFGA_STAT_NONE, "CFGA_STAT_NONE"}, {CFGA_STAT_EMPTY, "CFGA_STAT_EMPTY"}, {CFGA_STAT_DISCONNECTED, "CFGA_STAT_DISCONNECTED"}, {CFGA_STAT_CONNECTED, "CFGA_STAT_CONNECTED"}, {CFGA_STAT_UNCONFIGURED, "CFGA_STAT_UNCONFIGURED"}, {CFGA_STAT_CONFIGURED, "CFGA_STAT_CONFIGURED"}, }; static int pcidr_cfga_stat_nametab_len = sizeof (pcidr_cfga_stat_nametab) / sizeof (pcidr_cfga_stat_nametab[0]); char * pcidr_cfga_stat_name(cfga_stat_t val) { int i; for (i = 0; i < pcidr_cfga_stat_nametab_len; i++) { if (pcidr_cfga_stat_nametab[i].stat == val) return (pcidr_cfga_stat_nametab[i].name); } return (NULL); } static struct { cfga_cmd_t cmd; char *name; } pcidr_cfga_cmd_nametab[] = { {CFGA_CMD_NONE, "CFGA_CMD_NONE"}, {CFGA_CMD_LOAD, "CFGA_CMD_LOAD"}, {CFGA_CMD_UNLOAD, "CFGA_CMD_UNLOAD"}, {CFGA_CMD_CONNECT, "CFGA_CMD_CONNECT"}, {CFGA_CMD_DISCONNECT, "CFGA_CMD_DISCONNECT"}, {CFGA_CMD_CONFIGURE, "CFGA_CMD_CONFIGURE"}, {CFGA_CMD_UNCONFIGURE, "CFGA_CMD_UNCONFIGURE"}, }; static int pcidr_cfga_cmd_nametab_len = sizeof (pcidr_cfga_cmd_nametab) / sizeof (pcidr_cfga_cmd_nametab[0]); char * pcidr_cfga_cmd_name(cfga_cmd_t val) { int i; for (i = 0; i < pcidr_cfga_cmd_nametab_len; i++) { if (pcidr_cfga_cmd_nametab[i].cmd == val) return (pcidr_cfga_cmd_nametab[i].name); } return (NULL); } static struct { cfga_cond_t cond; char *name; } pcidr_cfga_cond_nametab[] = { {CFGA_COND_UNKNOWN, "CFGA_COND_UNKNOWN"}, {CFGA_COND_OK, "CFGA_COND_OK"}, {CFGA_COND_FAILING, "CFGA_COND_FAILING"}, {CFGA_COND_FAILED, "CFGA_COND_FAILED"}, {CFGA_COND_UNUSABLE, "CFGA_COND_UNUSABLE"}, }; static int pcidr_cfga_cond_nametab_len = sizeof (pcidr_cfga_cond_nametab) / sizeof (pcidr_cfga_cond_nametab[0]); char * pcidr_cfga_cond_name(cfga_cond_t val) { int i; for (i = 0; i < pcidr_cfga_cond_nametab_len; i++) { if (pcidr_cfga_cond_nametab[i].cond == val) return (pcidr_cfga_cond_nametab[i].name); } return (NULL); } static struct { cfga_err_t err; char *name; } pcidr_cfga_err_nametab[] = { {CFGA_OK, "CFGA_OK"}, {CFGA_NACK, "CFGA_NACK"}, {CFGA_NOTSUPP, "CFGA_NOTSUPP"}, {CFGA_OPNOTSUPP, "CFGA_OPNOTSUPP"}, {CFGA_PRIV, "CFGA_PRIV"}, {CFGA_BUSY, "CFGA_BUSY"}, {CFGA_SYSTEM_BUSY, "CFGA_SYSTEM_BUSY"}, {CFGA_DATA_ERROR, "CFGA_DATA_ERROR"}, {CFGA_LIB_ERROR, "CFGA_LIB_ERROR"}, {CFGA_NO_LIB, "CFGA_NO_LIB"}, {CFGA_INSUFFICENT_CONDITION, "CFGA_INSUFFICENT_CONDITION"}, {CFGA_INVAL, "CFGA_INVAL"}, {CFGA_ERROR, "CFGA_ERROR"}, {CFGA_APID_NOEXIST, "CFGA_APID_NOEXIST"}, {CFGA_ATTR_INVAL, "CFGA_ATTR_INVAL"}, }; static int pcidr_cfga_err_nametab_len = sizeof (pcidr_cfga_err_nametab) / sizeof (pcidr_cfga_err_nametab[0]); char * pcidr_cfga_err_name(cfga_err_t val) { int i; for (i = 0; i < pcidr_cfga_err_nametab_len; i++) { if (pcidr_cfga_err_nametab[i].err == val) return (pcidr_cfga_err_nametab[i].name); } return (NULL); } void pcidr_print_cfga(dlvl_t lvl, cfga_list_data_t *datap, char *prestr) { char *str; if (prestr == NULL) prestr = ""; dprint(lvl, "%slogical APID = %s\n", prestr, datap->ap_log_id); dprint(lvl, "%sphyiscal APID = %s\n", prestr, datap->ap_phys_id); dprint(lvl, "%sAP class = %s\n", prestr, datap->ap_class); str = pcidr_cfga_stat_name(datap->ap_r_state); if (str == NULL) str = "(unrecognized cfga_stat_t value!)"; dprint(lvl, "%sAP receptacle state = %s\n", prestr, str); str = pcidr_cfga_stat_name(datap->ap_o_state); if (str == NULL) str = "(unrecognized cfga_stat_t value!)"; dprint(lvl, "%sAP occupant state = %s\n", prestr, str); str = pcidr_cfga_cond_name(datap->ap_cond); if (str == NULL) str = "(unrecognized cfga_cond_t value!)"; dprint(lvl, "%sAP condition = %s\n", prestr, str); dprint(lvl, "%sAP busy indicator = %d\n", prestr, datap->ap_busy); str = ctime(&datap->ap_status_time); str[strlen(str) - 1] = '\0'; /* get rid of newline */ dprint(lvl, "%sAP last change time = %ld (%s)\n", prestr, datap->ap_status_time, str); dprint(lvl, "%sAP info = %s\n", prestr, datap->ap_info); dprint(lvl, "%sAP type = %s\n", prestr, datap->ap_type); } /* * for use with config_admin(3cfgadm) functions in their * parameter */ int pcidr_cfga_msg_func(void *datap, const char *msg) { pcidr_cfga_msg_data_t *dp = (pcidr_cfga_msg_data_t *)datap; char *prestr = dp->prestr; if (prestr == NULL) prestr = ""; dprint(dp->dlvl, "%s%s", prestr, msg); return (0); } /* * for use with config_admin(3cfgadm) functions in their * parameter */ /*ARGSUSED*/ int pcidr_cfga_confirm_func(void *datap, const char *msg) { return (1); } /* * returns 0 if successful, -1 if unusuccesful, 1 if the AP already had * performed on it */ int pcidr_cfga_do_cmd(cfga_cmd_t cmd, cfga_list_data_t *cfga_listp) { char *fn = "pcidr_cfga_do_cmd"; int rv, i, j; char *cmdnm, *cfga_errstr, *apid, *str; int cmdarr[2]; int cmdarr_len = sizeof (cmdarr) / sizeof (cmdarr[0]); struct cfga_msg cfga_msg; pcidr_cfga_msg_data_t cfga_msg_data; struct cfga_confirm cfga_confirm; cfga_flags_t cfga_flags; cmdnm = pcidr_cfga_cmd_name(cmd); assert(cmdnm != NULL); apid = cfga_listp->ap_phys_id; cfga_msg_data.dlvl = DDEBUG; cfga_msg_data.prestr = "pcidr_cfga_do_cmd(msg): "; cfga_msg.message_routine = pcidr_cfga_msg_func; cfga_msg.appdata_ptr = (void *)&cfga_msg_data; cfga_confirm.confirm = pcidr_cfga_confirm_func; cfga_confirm.appdata_ptr = NULL; cfga_flags = CFGA_FLAG_VERBOSE; if (cfga_listp->ap_busy != 0) { dprint(DDEBUG, "%s: apid = %s is busy\n", fn, cfga_listp->ap_phys_id); return (-1); } /* * explicitly perform each step that would otherwise be done * implicitly by cfgadm to isolate errors */ j = 0; switch (cmd) { case CFGA_CMD_CONFIGURE: if (cfga_listp->ap_o_state < CFGA_STAT_CONNECTED) { cmdarr[j] = CFGA_CMD_CONNECT; j++; } if (cfga_listp->ap_o_state < CFGA_STAT_CONFIGURED) { cmdarr[j] = CFGA_CMD_CONFIGURE; j++; } if (cfga_listp->ap_o_state >= CFGA_STAT_CONFIGURED) goto ALREADY; break; case CFGA_CMD_DISCONNECT: if (cfga_listp->ap_o_state >= CFGA_STAT_CONFIGURED) { cmdarr[j] = CFGA_CMD_UNCONFIGURE; j++; } if (cfga_listp->ap_o_state >= CFGA_STAT_CONNECTED) { cmdarr[j] = CFGA_CMD_DISCONNECT; j++; } if (cfga_listp->ap_r_state <= CFGA_STAT_DISCONNECTED) goto ALREADY; break; default: dprint(DDEBUG, "%s: unsupported cmd %d\n", cmd); return (-1); } assert(j <= cmdarr_len); for (i = 0; i < j; i++) { cmd = cmdarr[i]; cmdnm = pcidr_cfga_cmd_name(cmd); assert(cmdnm != NULL); rv = config_change_state(cmd, 1, &apid, NULL, &cfga_confirm, &cfga_msg, &cfga_errstr, cfga_flags); if (rv != CFGA_OK) { dprint(DDEBUG, "%s: command %s failed on apid %s", fn, cmdnm, apid); str = pcidr_cfga_err_name(rv); if (str == NULL) str = "unrecognized rv!"; dprint(DDEBUG, ": rv = %d (%s)", rv, str); if (cfga_errstr != NULL) { dprint(DDEBUG, ", error string = " "\"%s\"", cfga_errstr); free(cfga_errstr); } dprint(DDEBUG, "\n"); return (-1); } } return (0); /*NOTREACHED*/ ALREADY: dprint(DDEBUG, "%s: command %s already done on apid %s\n", fn, cmdnm, apid); return (1); }