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 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 27 #include "FCHBANPIVPort.h" 28 #include <Exceptions.h> 29 #include <Trace.h> 30 #include <sun_fc.h> 31 #include <iostream> 32 #include <iomanip> 33 #include <sys/types.h> 34 #include <sys/mkdev.h> 35 #include <sys/stat.h> 36 #include <fcntl.h> 37 #include <unistd.h> 38 #include <stropts.h> 39 #include <dirent.h> 40 #include <sys/fibre-channel/fc.h> 41 #include <sys/fibre-channel/fcio.h> 42 #include <sys/fibre-channel/ulp/fcp_util.h> 43 #include <sys/fibre-channel/ulp/fcsm.h> 44 #include <sys/fibre-channel/impl/fc_error.h> 45 #include <sys/fibre-channel/fc_appif.h> 46 #include <sys/scsi/generic/commands.h> 47 #include <sys/scsi/impl/commands.h> 48 #include <sys/scsi/impl/sense.h> 49 #include <sys/scsi/generic/inquiry.h> 50 #include <sys/scsi/generic/status.h> 51 #include <errno.h> 52 53 using namespace std; 54 55 const int FCHBANPIVPort::MAX_FCIO_MSG_LEN = 256; 56 57 FCHBANPIVPort::FCHBANPIVPort(string thePath) : HBANPIVPort() { 58 Trace log("FCHBANPIVPort::FCHBANPIVPort"); 59 log.debug("Initializing HBA NPIV port %s", thePath.c_str()); 60 61 try { 62 path = lookupControllerPath(thePath); 63 } catch (...) { 64 log.debug("Unable to lookup controller path and number for %s", 65 thePath.c_str()); 66 path = "/devices"; 67 path += thePath; 68 path += ":fc"; 69 } 70 71 uint64_t tmp; 72 HBA_NPIVATTRIBUTES attrs = getPortAttributes(tmp); 73 memcpy(&tmp, &attrs.PortWWN, 8); 74 portWWN = ntohll(tmp); 75 memcpy(&tmp, &attrs.NodeWWN, 8); 76 nodeWWN = ntohll(tmp); 77 } 78 79 80 HBA_NPIVATTRIBUTES FCHBANPIVPort::getPortAttributes(uint64_t &stateChange) { 81 Trace log("FCHBANPIVPort::getPortAttributes"); 82 83 HBA_NPIVATTRIBUTES attributes; 84 fcio_t fcio; 85 fc_hba_npiv_attributes_t attrs; 86 87 memset(&fcio, 0, sizeof (fcio)); 88 memset(&attributes, 0, sizeof (attributes)); 89 fcio.fcio_cmd = FCIO_GET_NPIV_ATTRIBUTES; 90 fcio.fcio_olen = sizeof (attrs); 91 fcio.fcio_xfer = FCIO_XFER_READ; 92 fcio.fcio_obuf = (caddr_t)&attrs; 93 fp_ioctl(getPath(), FCIO_CMD, &fcio); 94 95 stateChange = attrs.lastChange; 96 memcpy(&attributes.NodeWWN, &attrs.NodeWWN, 8); 97 memcpy(&attributes.PortWWN, &attrs.PortWWN, 8); 98 99 return (attributes); 100 } 101 102 103 void FCHBANPIVPort::fp_ioctl(string path, int cmd, fcio_t *fcio) { 104 Trace log("FCHBANPIVPort::fp_ioctl"); 105 106 char fcioErrorString[MAX_FCIO_MSG_LEN] = ""; 107 int fd = HBA::_open(path, O_NDELAY | O_RDONLY); 108 109 try { 110 int times = 0; 111 HBA::_ioctl(fd, cmd, (uchar_t *)fcio); 112 while (fcio->fcio_errno == FC_STATEC_BUSY) { 113 (void) sleep(2); 114 HBA::_ioctl(fd, cmd, (uchar_t *)fcio); 115 if (times++ > 20) { 116 break; 117 } 118 } 119 close(fd); 120 if (fcio->fcio_errno) { 121 throw IOError("IOCTL transport failure"); 122 } 123 } catch (...) { 124 close(fd); 125 transportError(fcio->fcio_errno, fcioErrorString); 126 log.genericIOError("NPIV Port ioctl (0x%x) failed. Transport: \"%s\"", cmd, 127 fcioErrorString); 128 switch (fcio->fcio_errno) { 129 case FC_BADWWN: 130 throw IllegalWWNException(); 131 case FC_BADPORT: 132 throw IllegalWWNException(); 133 case FC_OUTOFBOUNDS: 134 throw IllegalIndexException(); 135 case FC_PBUSY: 136 case FC_FBUSY: 137 case FC_TRAN_BUSY: 138 case FC_STATEC_BUSY: 139 case FC_DEVICE_BUSY: 140 throw BusyException(); 141 case FC_SUCCESS: 142 default: 143 throw; 144 } 145 } 146 } 147 148 149 /* 150 * Interpret the error code in the fcio_t structure 151 * 152 * message must be at least MAX_FCIO_MSG_LEN in length. 153 */ 154 void 155 FCHBANPIVPort::transportError(uint32_t fcio_errno, char *message) { 156 Trace log("transportError"); 157 158 string fcioErrorString; 159 if (message == NULL) { 160 log.internalError("NULL routine argument"); 161 return; 162 } 163 switch (fcio_errno) { 164 case (uint32_t)FC_FAILURE: 165 fcioErrorString = "general failure"; 166 break; 167 case (uint32_t)FC_FAILURE_SILENT: 168 fcioErrorString = "general failure but fail silently"; 169 break; 170 case FC_SUCCESS: 171 fcioErrorString = "successful completion"; 172 break; 173 case FC_CAP_ERROR: 174 fcioErrorString = "FCA capability error"; 175 break; 176 case FC_CAP_FOUND: 177 fcioErrorString = "FCA capability unsettable"; 178 break; 179 case FC_CAP_SETTABLE: 180 fcioErrorString = "FCA capability settable"; 181 break; 182 case FC_UNBOUND: 183 fcioErrorString = "unbound stuff"; 184 break; 185 case FC_NOMEM: 186 fcioErrorString = "allocation error"; 187 break; 188 case FC_BADPACKET: 189 fcioErrorString = "invalid packet specified/supplied"; 190 break; 191 case FC_OFFLINE: 192 fcioErrorString = "I/O resource unavailable"; 193 break; 194 case FC_OLDPORT: 195 fcioErrorString = "operation on non-loop port"; 196 break; 197 case FC_NO_MAP: 198 fcioErrorString = "requested map unavailable"; 199 break; 200 case FC_TRANSPORT_ERROR: 201 fcioErrorString = "unable to transport I/O"; 202 break; 203 case FC_ELS_FREJECT: 204 fcioErrorString = "ELS rejected by a Fabric"; 205 break; 206 case FC_ELS_PREJECT: 207 fcioErrorString = "ELS rejected by an N_port"; 208 break; 209 case FC_ELS_BAD: 210 fcioErrorString = "ELS rejected by FCA/fctl"; 211 break; 212 case FC_ELS_MALFORMED: 213 fcioErrorString = "poorly formed ELS request"; 214 break; 215 case FC_TOOMANY: 216 fcioErrorString = "resource request too large"; 217 break; 218 case FC_UB_BADTOKEN: 219 fcioErrorString = "invalid unsolicited buffer token"; 220 break; 221 case FC_UB_ERROR: 222 fcioErrorString = "invalid unsol buf request"; 223 break; 224 case FC_UB_BUSY: 225 fcioErrorString = "buffer already in use"; 226 break; 227 case FC_BADULP: 228 fcioErrorString = "Unknown ulp"; 229 break; 230 case FC_BADTYPE: 231 fcioErrorString = "ULP not registered to handle this FC4 type"; 232 break; 233 case FC_UNCLAIMED: 234 fcioErrorString = "request or data not claimed"; 235 break; 236 case FC_ULP_SAMEMODULE: 237 fcioErrorString = "module already in use"; 238 break; 239 case FC_ULP_SAMETYPE: 240 fcioErrorString = "FC4 module already in use"; 241 break; 242 case FC_ABORTED: 243 fcioErrorString = "request aborted"; 244 break; 245 case FC_ABORT_FAILED: 246 fcioErrorString = "abort request failed"; 247 break; 248 case FC_BADEXCHANGE: 249 fcioErrorString = "exchange doesn\325t exist"; 250 break; 251 case FC_BADWWN: 252 fcioErrorString = "WWN not recognized"; 253 break; 254 case FC_BADDEV: 255 fcioErrorString = "device unrecognized"; 256 break; 257 case FC_BADCMD: 258 fcioErrorString = "invalid command issued"; 259 break; 260 case FC_BADOBJECT: 261 fcioErrorString = "invalid object requested"; 262 break; 263 case FC_BADPORT: 264 fcioErrorString = "invalid port specified"; 265 break; 266 case FC_NOTTHISPORT: 267 fcioErrorString = "resource not at this port"; 268 break; 269 case FC_PREJECT: 270 fcioErrorString = "reject at remote N_Port"; 271 break; 272 case FC_FREJECT: 273 fcioErrorString = "reject at remote Fabric"; 274 break; 275 case FC_PBUSY: 276 fcioErrorString = "remote N_Port busy"; 277 break; 278 case FC_FBUSY: 279 fcioErrorString = "remote Fabric busy"; 280 break; 281 case FC_ALREADY: 282 fcioErrorString = "already logged in"; 283 break; 284 case FC_LOGINREQ: 285 fcioErrorString = "login required"; 286 break; 287 case FC_RESETFAIL: 288 fcioErrorString = "reset failed"; 289 break; 290 case FC_INVALID_REQUEST: 291 fcioErrorString = "request is invalid"; 292 break; 293 case FC_OUTOFBOUNDS: 294 fcioErrorString = "port number is out of bounds"; 295 break; 296 case FC_TRAN_BUSY: 297 fcioErrorString = "command transport busy"; 298 break; 299 case FC_STATEC_BUSY: 300 fcioErrorString = "port driver currently busy"; 301 break; 302 case FC_DEVICE_BUSY: 303 fcioErrorString = "transport working on this device"; 304 break; 305 case FC_DEVICE_NOT_TGT: 306 fcioErrorString = "device is not a SCSI target"; 307 break; 308 default: 309 snprintf(message, MAX_FCIO_MSG_LEN, "Unknown error code 0x%x", 310 fcio_errno); 311 return; 312 } 313 snprintf(message, MAX_FCIO_MSG_LEN, "%s", fcioErrorString.c_str()); 314 } 315 316