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 #include <stdio.h> 28 #include <stdlib.h> 29 #include <unistd.h> 30 #include <strings.h> 31 #include <errno.h> 32 #include <sys/param.h> 33 #include <sys/systeminfo.h> 34 #include <sys/sysevent/eventdefs.h> 35 #include <sys/sysevent/dr.h> 36 #include <syslog.h> 37 #include <libnvpair.h> 38 #include <stdarg.h> 39 #include <assert.h> 40 #include <sys/stat.h> 41 #include <dlfcn.h> 42 #include <pcidr.h> 43 #include <pcidr_cfga.h> 44 45 46 PCIDR_PLUGIN_PROTO(attrlistp, optp) 47 { 48 char *fn = PCIDR_PLUGIN_SYMSTR; 49 int rv = 0; 50 char *cfga_errstr = NULL; 51 char *str, *apid; 52 cfga_list_data_t *cfga_listp = NULL; 53 cfga_cmd_t cmd; 54 int cfga_list_len; 55 pcidr_attrs_t dr; 56 57 pcidr_set_logopt(&optp->logopt); 58 59 if (pcidr_get_attrs(attrlistp, &dr) != 0 || 60 pcidr_check_attrs(&dr) != 0) { 61 dprint(DWARN, "%s: invalid or missing attributes\n", fn); 62 return (EINVAL); 63 } 64 65 /* 66 * get state of APID; enforce the cfgadm pci plugin implementation of 67 * returning one matching AP per supplied apid string 68 */ 69 rv = config_list_ext(1, &dr.dr_ap_id, &cfga_listp, &cfga_list_len, 70 NULL, NULL, &cfga_errstr, CFGA_FLAG_LIST_ALL); 71 if (rv != CFGA_OK) { 72 str = pcidr_cfga_err_name(rv); 73 if (str == NULL) 74 str = "unrecognized rv!"; 75 dprint(DDEBUG, "%s: config_list_ext() on apid = \"%s\" " 76 "failed: rv = %d (%s)", fn, dr.dr_ap_id, rv, str); 77 78 if (cfga_errstr != NULL) { 79 dprint(DDEBUG, ", error string = \"%s\"", 80 cfga_errstr); 81 free(cfga_errstr); 82 } 83 dprint(DDEBUG, "\n"); 84 rv = EINVAL; 85 goto OUT; 86 } 87 if (cfga_list_len != 1) { 88 dprint(DWARN, "%s: invalid condition - more than one AP was " 89 "found for the APID \"%s\"\n", fn, dr.dr_ap_id); 90 rv = EINVAL; 91 goto OUT; 92 } 93 94 /* 95 * perform DR 96 */ 97 dprint(DINFO, "%s: showing info and performing DR on APID(s) " 98 "matching \"%s\"\n", fn, dr.dr_ap_id); 99 100 cmd = CFGA_CMD_NONE; 101 dprint(DINFO, "===========================================\n", fn); 102 pcidr_print_cfga(DINFO, &cfga_listp[0], " .. "); 103 apid = cfga_listp[0].ap_phys_id; 104 105 if (strcmp(dr.dr_req_type, DR_REQ_OUTGOING_RES) == 0) { 106 cmd = CFGA_CMD_DISCONNECT; 107 dprint(DINFO, "%s: disconnecting ...\n", fn, apid); 108 109 rv = pcidr_cfga_do_cmd(cmd, &cfga_listp[0]); 110 if (rv < 0) { 111 dprint(DINFO, "%s: disconnect FAILED\n", fn); 112 rv = EIO; 113 } 114 else 115 dprint(DINFO, "%s: disconnect OK\n", fn); 116 117 goto OUT; 118 } 119 if (strcmp(dr.dr_req_type, DR_REQ_INCOMING_RES) == 0) { 120 cmd = CFGA_CMD_CONFIGURE; 121 dprint(DINFO, "%s: configuring ...\n", fn, apid); 122 123 rv = pcidr_cfga_do_cmd(cmd, &cfga_listp[0]); 124 if (rv < 0) { 125 dprint(DINFO, "%s: configure FAILED\n", fn); 126 rv = EIO; 127 } else 128 dprint(DINFO, "%s: configure OK\n", fn); 129 130 goto OUT; 131 } 132 133 /* we should not get here if pcidr_check_attrs() is correct */ 134 dprint(DWARN, "%s: invalid dr_req_type = %s\n", fn, dr.dr_req_type); 135 assert(cmd != CFGA_CMD_NONE); 136 return (EINVAL); 137 /*NOTREACHED*/ 138 OUT: 139 if (cfga_listp != NULL) 140 free(cfga_listp); 141 return (rv); 142 } 143