1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <unistd.h> 32 #include <strings.h> 33 #include <errno.h> 34 #include <sys/param.h> 35 #include <sys/systeminfo.h> 36 #include <sys/sysevent/eventdefs.h> 37 #include <sys/sysevent/dr.h> 38 #include <syslog.h> 39 #include <libnvpair.h> 40 #include <stdarg.h> 41 #include <assert.h> 42 #include <sys/stat.h> 43 #include <dlfcn.h> 44 #include <pcidr.h> 45 #include <pcidr_cfga.h> 46 47 48 PCIDR_PLUGIN_PROTO(attrlistp, optp) 49 { 50 char *fn = PCIDR_PLUGIN_SYMSTR; 51 int rv = 0; 52 char *cfga_errstr = NULL; 53 char *str, *apid; 54 cfga_list_data_t *cfga_listp = NULL; 55 cfga_cmd_t cmd; 56 int cfga_list_len; 57 pcidr_attrs_t dr; 58 59 pcidr_set_logopt(&optp->logopt); 60 61 if (pcidr_get_attrs(attrlistp, &dr) != 0 || 62 pcidr_check_attrs(&dr) != 0) { 63 dprint(DWARN, "%s: invalid or missing attributes\n", fn); 64 return (EINVAL); 65 } 66 67 /* 68 * get state of APID; enforce the cfgadm pci plugin implementation of 69 * returning one matching AP per supplied apid string 70 */ 71 rv = config_list_ext(1, &dr.dr_ap_id, &cfga_listp, &cfga_list_len, 72 NULL, NULL, &cfga_errstr, CFGA_FLAG_LIST_ALL); 73 if (rv != CFGA_OK) { 74 str = pcidr_cfga_err_name(rv); 75 if (str == NULL) 76 str = "unrecognized rv!"; 77 dprint(DDEBUG, "%s: config_list_ext() on apid = \"%s\" " 78 "failed: rv = %d (%s)", fn, dr.dr_ap_id, rv, str); 79 80 if (cfga_errstr != NULL) { 81 dprint(DDEBUG, ", error string = \"%s\"", 82 cfga_errstr); 83 free(cfga_errstr); 84 } 85 dprint(DDEBUG, "\n"); 86 rv = EINVAL; 87 goto OUT; 88 } 89 if (cfga_list_len != 1) { 90 dprint(DWARN, "%s: invalid condition - more than one AP was " 91 "found for the APID \"%s\"\n", fn, dr.dr_ap_id); 92 rv = EINVAL; 93 goto OUT; 94 } 95 96 /* 97 * perform DR 98 */ 99 dprint(DINFO, "%s: showing info and performing DR on APID(s) " 100 "matching \"%s\"\n", fn, dr.dr_ap_id); 101 102 cmd = CFGA_CMD_NONE; 103 dprint(DINFO, "===========================================\n", fn); 104 pcidr_print_cfga(DINFO, &cfga_listp[0], " .. "); 105 apid = cfga_listp[0].ap_phys_id; 106 107 if (strcmp(dr.dr_req_type, DR_REQ_OUTGOING_RES) == 0) { 108 cmd = CFGA_CMD_DISCONNECT; 109 dprint(DINFO, "%s: disconnecting ...\n", fn, apid); 110 111 rv = pcidr_cfga_do_cmd(cmd, &cfga_listp[0]); 112 if (rv < 0) { 113 dprint(DINFO, "%s: disconnect FAILED\n", fn); 114 rv = EIO; 115 } 116 else 117 dprint(DINFO, "%s: disconnect OK\n", fn); 118 119 goto OUT; 120 } 121 if (strcmp(dr.dr_req_type, DR_REQ_INCOMING_RES) == 0) { 122 cmd = CFGA_CMD_CONFIGURE; 123 dprint(DINFO, "%s: configuring ...\n", fn, apid); 124 125 rv = pcidr_cfga_do_cmd(cmd, &cfga_listp[0]); 126 if (rv < 0) { 127 dprint(DINFO, "%s: configure FAILED\n", fn); 128 rv = EIO; 129 } else 130 dprint(DINFO, "%s: configure OK\n", fn); 131 132 goto OUT; 133 } 134 135 /* we should not get here if pcidr_check_attrs() is correct */ 136 dprint(DWARN, "%s: invalid dr_req_type = %s\n", fn, dr.dr_req_type); 137 assert(cmd != CFGA_CMD_NONE); 138 return (EINVAL); 139 /*NOTREACHED*/ 140 OUT: 141 if (cfga_listp != NULL) 142 free(cfga_listp); 143 return (rv); 144 } 145