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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <sun_sas.h> 28 29 /* 30 * Retrieves the attributes for a specific discovered port by WWN 31 */ 32 HBA_STATUS 33 Sun_sasGetPortAttributesByWWN(HBA_HANDLE handle, HBA_WWN portWWN, 34 HBA_WWN domainPortWWN, PSMHBA_PORTATTRIBUTES attributes) 35 { 36 const char ROUTINE[] = "Sun_sasGetPortAttributesByWWN"; 37 HBA_STATUS status; 38 struct sun_sas_hba *hba_ptr; 39 struct sun_sas_port *hba_port_ptr, *hba_disco_port; 40 int index, chkDomainPort = 0, domainFound = 0; 41 42 /* Validate the arguments */ 43 if (attributes == NULL) { 44 log(LOG_DEBUG, ROUTINE, "NULL port attributes"); 45 return (HBA_STATUS_ERROR_ARG); 46 } 47 48 if (wwnConversion(domainPortWWN.wwn) != 0) { 49 chkDomainPort = 1; 50 } 51 52 lock(&all_hbas_lock); 53 index = RetrieveIndex(handle); 54 lock(&open_handles_lock); 55 hba_ptr = RetrieveHandle(index); 56 if (hba_ptr == NULL) { 57 log(LOG_DEBUG, ROUTINE, "Invalid handle %08lx.", handle); 58 unlock(&open_handles_lock); 59 unlock(&all_hbas_lock); 60 return (HBA_STATUS_ERROR_INVALID_HANDLE); 61 } 62 63 /* Check for stale data */ 64 status = verifyAdapter(hba_ptr); 65 if (status != HBA_STATUS_OK) { 66 log(LOG_DEBUG, ROUTINE, "Verify adapter failed"); 67 unlock(&open_handles_lock); 68 unlock(&all_hbas_lock); 69 return (status); 70 } 71 72 if (hba_ptr->first_port == NULL) { 73 /* This is probably an internal failure of the library */ 74 if (hba_ptr->device_path) { 75 log(LOG_DEBUG, ROUTINE, 76 "Internal failure: Adapter %s contains " 77 "no port data", hba_ptr->device_path); 78 } else { 79 log(LOG_DEBUG, ROUTINE, 80 "Internal failure: Adapter at index %d contains " 81 "no port data", hba_ptr->index); 82 } 83 unlock(&open_handles_lock); 84 unlock(&all_hbas_lock); 85 return (HBA_STATUS_ERROR); 86 } 87 88 /* Loop over all Adapter ports */ 89 for (hba_port_ptr = hba_ptr->first_port; 90 hba_port_ptr != NULL; 91 hba_port_ptr = hba_port_ptr->next) { 92 if (chkDomainPort) { 93 if (validateDomainAddress(hba_port_ptr, 94 domainPortWWN) != HBA_STATUS_OK) { 95 continue; 96 } else 97 domainFound = 1; 98 } 99 100 if (wwnConversion(hba_port_ptr->port_attributes. 101 PortSpecificAttribute.SASPort->LocalSASAddress.wwn) == 102 wwnConversion(portWWN.wwn)) { 103 /* 104 * We should indicate an error if we enter here 105 * without domainPortWWN set. 106 */ 107 if (chkDomainPort == 0) { 108 log(LOG_DEBUG, ROUTINE, 109 "Domain Port WWN should be set when " 110 "querying HBA port %016llx for " 111 "handle %08lx", 112 wwnConversion(portWWN.wwn), handle); 113 unlock(&open_handles_lock); 114 unlock(&all_hbas_lock); 115 return (HBA_STATUS_ERROR_ARG); 116 } 117 attributes->PortType = 118 hba_port_ptr->port_attributes.PortType; 119 attributes->PortState = 120 hba_port_ptr->port_attributes.PortState; 121 (void) strlcpy(attributes->OSDeviceName, 122 hba_port_ptr->port_attributes.OSDeviceName, 123 sizeof (attributes->OSDeviceName)); 124 (void) memcpy(attributes->PortSpecificAttribute.SASPort, 125 hba_port_ptr->port_attributes.PortSpecificAttribute. 126 SASPort, sizeof (struct SMHBA_SAS_Port)); 127 128 unlock(&open_handles_lock); 129 unlock(&all_hbas_lock); 130 return (HBA_STATUS_OK); 131 } 132 133 /* check to make sure there are devices attached to this port */ 134 if (hba_port_ptr->first_attached_port != NULL) { 135 136 /* Loop over all discovered ports */ 137 for (hba_disco_port = hba_port_ptr->first_attached_port; 138 hba_disco_port != NULL; 139 hba_disco_port = hba_disco_port->next) { 140 if (wwnConversion(hba_disco_port-> 141 port_attributes.PortSpecificAttribute. 142 SASPort->LocalSASAddress.wwn) == 143 wwnConversion(portWWN.wwn)) { 144 attributes->PortType = 145 hba_disco_port->port_attributes. 146 PortType; 147 attributes->PortState = 148 hba_disco_port->port_attributes. 149 PortState; 150 (void) strlcpy(attributes->OSDeviceName, 151 hba_disco_port->port_attributes. 152 OSDeviceName, 153 sizeof (attributes->OSDeviceName)); 154 (void) memcpy(attributes-> 155 PortSpecificAttribute.SASPort, 156 hba_disco_port->port_attributes. 157 PortSpecificAttribute.SASPort, 158 sizeof (struct SMHBA_SAS_Port)); 159 unlock(&open_handles_lock); 160 unlock(&all_hbas_lock); 161 return (HBA_STATUS_OK); 162 } 163 } 164 } 165 if (chkDomainPort) { 166 log(LOG_DEBUG, ROUTINE, 167 "Invalid Port WWN %016llx for handle %08lx", 168 wwnConversion(portWWN.wwn), handle); 169 unlock(&open_handles_lock); 170 unlock(&all_hbas_lock); 171 return (HBA_STATUS_ERROR_ILLEGAL_WWN); 172 } 173 } 174 if (chkDomainPort && domainFound == 0) { 175 log(LOG_DEBUG, ROUTINE, "No Matching domain port" 176 " (%16llx) for port (%16llx) for handle %08lx", 177 wwnConversion(domainPortWWN.wwn), 178 wwnConversion(portWWN.wwn), 179 handle); 180 } else { 181 /* We enter here only when chkDomainPort == 0 */ 182 log(LOG_DEBUG, ROUTINE, 183 "Invalid Port WWN %016llx for handle %08lx", 184 wwnConversion(portWWN.wwn), handle); 185 } 186 unlock(&open_handles_lock); 187 unlock(&all_hbas_lock); 188 return (HBA_STATUS_ERROR_ILLEGAL_WWN); 189 } 190