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 <unistd.h> 28 29 #include <FCHBA.h> 30 #include <Exceptions.h> 31 #include <Trace.h> 32 #include <iostream> 33 #include <iomanip> 34 #include <cerrno> 35 #include <cstring> 36 #include <sys/types.h> 37 #include <sys/stat.h> 38 #include <fcntl.h> 39 #include <unistd.h> 40 #include <stropts.h> 41 #include <sys/fibre-channel/fcio.h> 42 #include <sys/fibre-channel/ulp/fcsm.h> 43 #include <FCHBAPort.h> 44 #include <HBAList.h> 45 46 using namespace std; 47 const string FCHBA::FCSM_DRIVER_PATH = "/devices/pseudo/fcsm@0:fcsm"; 48 const string FCHBA::FCSM_DRIVER_PKG = "SUNWfcsm"; 49 const int FCHBA::MAX_FCIO_MSG_LEN = 256; 50 51 FCHBA::FCHBA(string path) : HBA() { 52 Trace log("FCHBA::FCHBA"); 53 log.debug("Constructing new HBA (%s)", path.c_str()); 54 55 // Add first port 56 addPort(new FCHBAPort(path)); 57 58 name = "INTERNAL-FAILURE"; // Just in case things go wrong 59 try { 60 HBA_ADAPTERATTRIBUTES attrs = getHBAAttributes(); 61 name = attrs.Manufacturer; 62 name += "-"; 63 name += attrs.Model; 64 65 // Grab any other ports on this adapter 66 for (int i = 1; i < attrs.NumberOfPorts; i++) { 67 fcio_t fcio; 68 int fd; 69 char nextPath[MAXPATHLEN]; 70 71 log.debug("Fetching other port %d", i); 72 73 // construct fcio struct 74 memset(&fcio, 0, sizeof (fcio_t)); 75 memset(nextPath, 0, sizeof (nextPath)); 76 fcio.fcio_cmd = FCIO_GET_OTHER_ADAPTER_PORTS; 77 fcio.fcio_xfer = FCIO_XFER_RW; 78 79 fcio.fcio_olen = MAXPATHLEN; 80 fcio.fcio_obuf = (char *)nextPath; 81 fcio.fcio_ilen = sizeof (i); 82 fcio.fcio_ibuf = (char *)&i; 83 84 // open the fcsm node so we can send the ioctl to 85 errno = 0; 86 HBAPort *port = getPortByIndex(0); 87 if ((fd = open(port->getPath().c_str(), O_NDELAY | O_RDONLY)) == 88 -1) { 89 log.debug("Unable to open %d opened (%s)", i, 90 port->getPath().c_str()); 91 if (errno == EBUSY) { 92 throw BusyException(); 93 } else if (errno == EAGAIN) { 94 throw TryAgainException(); 95 } else if (errno == ENOTSUP) { 96 throw NotSupportedException(); 97 } else if (errno == ENOENT) { 98 throw UnavailableException(); 99 } else { 100 throw IOError("Unable to open FCSM driver"); 101 } 102 } 103 log.debug("Other port %d opened", i); 104 105 errno = 0; 106 if (ioctl(fd, FCIO_CMD, &fcio) != 0) { 107 // Interpret the fcio error code 108 char fcioErrorString[MAX_FCIO_MSG_LEN] = ""; 109 110 log.genericIOError( 111 "ADAPTER_LIST failed: " 112 "Errno: \"%s\"", 113 strerror(errno)); 114 close(fd); 115 if (errno == EBUSY) { 116 throw BusyException(); 117 } else if (errno == EAGAIN) { 118 throw TryAgainException(); 119 } else if (errno == ENOTSUP) { 120 throw NotSupportedException(); 121 } else if (errno == ENOENT) { 122 throw UnavailableException(); 123 } else { 124 throw IOError("Unable to build HBA list"); 125 } 126 } 127 close(fd); 128 log.debug("About to add port %d (%s)", i, nextPath); 129 addPort(new FCHBAPort(nextPath)); 130 } 131 } catch (HBAException &e) { 132 log.internalError( 133 "Unable to construct HBA."); 134 throw e; 135 } 136 } 137 138 std::string FCHBA::getName() { 139 Trace log("FCHBA::getName"); 140 return (name); 141 } 142 143 HBA_ADAPTERATTRIBUTES FCHBA::getHBAAttributes() { 144 Trace log("FCHBA::getHBAAttributes"); 145 int fd; 146 147 errno = 0; 148 HBAPort *port = getPortByIndex(0); 149 if ((fd = open(port->getPath().c_str(), O_NDELAY | O_RDONLY)) == -1) { 150 // Why did we fail? 151 if (errno == EBUSY) { 152 throw BusyException(); 153 } else if (errno == EAGAIN) { 154 throw TryAgainException(); 155 } else if (errno == ENOTSUP) { 156 throw NotSupportedException(); 157 } else { 158 throw IOError(port); 159 } 160 } 161 162 HBA_ADAPTERATTRIBUTES attributes; 163 fcio_t fcio; 164 fc_hba_adapter_attributes_t attrs; 165 166 memset(&fcio, 0, sizeof (fcio)); 167 168 fcio.fcio_cmd = FCIO_GET_ADAPTER_ATTRIBUTES; 169 fcio.fcio_olen = sizeof (attrs); 170 fcio.fcio_xfer = FCIO_XFER_READ; 171 fcio.fcio_obuf = (caddr_t)&attrs; 172 173 174 errno = 0; 175 if (ioctl(fd, FCIO_CMD, &fcio) != 0) { 176 close(fd); 177 if (errno == EBUSY) { 178 throw BusyException(); 179 } else if (errno == EAGAIN) { 180 throw TryAgainException(); 181 } else if (errno == ENOTSUP) { 182 throw NotSupportedException(); 183 } else { 184 throw IOError("Unable to fetch adapter attributes"); 185 } 186 } 187 close(fd); 188 189 /* Now copy over the payload */ 190 attributes.NumberOfPorts = attrs.NumberOfPorts; 191 attributes.VendorSpecificID = attrs.VendorSpecificID; 192 memcpy(attributes.Manufacturer, attrs.Manufacturer, 64); 193 memcpy(attributes.SerialNumber, attrs.SerialNumber, 64); 194 memcpy(attributes.Model, attrs.Model, 256); 195 memcpy(attributes.ModelDescription, attrs.ModelDescription, 256); 196 memcpy(attributes.NodeSymbolicName, attrs.NodeSymbolicName, 256); 197 memcpy(attributes.HardwareVersion, attrs.HardwareVersion, 256); 198 memcpy(attributes.DriverVersion, attrs.DriverVersion, 256); 199 memcpy(attributes.OptionROMVersion, attrs.OptionROMVersion, 256); 200 memcpy(attributes.FirmwareVersion, attrs.FirmwareVersion, 256); 201 memcpy(attributes.DriverName, attrs.DriverName, 256); 202 memcpy(&attributes.NodeWWN, &attrs.NodeWWN, 8); 203 204 return (attributes); 205 } 206 207 HBA_ADAPTERATTRIBUTES FCHBA::npivGetHBAAttributes() { 208 Trace log("FCHBA::npivGetHBAAttributes"); 209 int fd; 210 211 errno = 0; 212 HBAPort *port = getPortByIndex(0); 213 if ((fd = open(port->getPath().c_str(), O_NDELAY | O_RDONLY)) == -1) { 214 // Why did we fail? 215 if (errno == EBUSY) { 216 throw BusyException(); 217 } else if (errno == EAGAIN) { 218 throw TryAgainException(); 219 } else if (errno == ENOTSUP) { 220 throw NotSupportedException(); 221 } else { 222 throw IOError(port); 223 } 224 } 225 226 HBA_ADAPTERATTRIBUTES attributes; 227 fcio_t fcio; 228 fc_hba_adapter_attributes_t attrs; 229 230 memset(&fcio, 0, sizeof (fcio)); 231 fcio.fcio_cmd = FCIO_NPIV_GET_ADAPTER_ATTRIBUTES; 232 fcio.fcio_olen = sizeof (attrs); 233 fcio.fcio_xfer = FCIO_XFER_READ; 234 fcio.fcio_obuf = (caddr_t)&attrs; 235 errno = 0; 236 237 if (ioctl(fd, FCIO_CMD, &fcio) != 0) { 238 close(fd); 239 if (errno == EBUSY) { 240 throw BusyException(); 241 } else if (errno == EAGAIN) { 242 throw TryAgainException(); 243 } else if (errno == ENOTSUP) { 244 throw NotSupportedException(); 245 } else { 246 throw IOError("Unable to fetch adapter attributes"); 247 } 248 } 249 close(fd); 250 251 /* Now copy over the payload */ 252 attributes.NumberOfPorts = attrs.NumberOfPorts; 253 attributes.VendorSpecificID = attrs.VendorSpecificID; 254 memcpy(attributes.Manufacturer, attrs.Manufacturer, 64); 255 memcpy(attributes.SerialNumber, attrs.SerialNumber, 64); 256 memcpy(attributes.Model, attrs.Model, 256); 257 memcpy(attributes.ModelDescription, attrs.ModelDescription, 256); 258 memcpy(attributes.NodeSymbolicName, attrs.NodeSymbolicName, 256); 259 memcpy(attributes.HardwareVersion, attrs.HardwareVersion, 256); 260 memcpy(attributes.DriverVersion, attrs.DriverVersion, 256); 261 memcpy(attributes.OptionROMVersion, attrs.OptionROMVersion, 256); 262 memcpy(attributes.FirmwareVersion, attrs.FirmwareVersion, 256); 263 memcpy(attributes.DriverName, attrs.DriverName, 256); 264 memcpy(&attributes.NodeWWN, &attrs.NodeWWN, 8); 265 266 return (attributes); 267 } 268 269 void FCHBA::loadAdapters(vector<HBA*> &list) { 270 Trace log("FCHBA::loadAdapters"); 271 fcio_t fcio; 272 fc_hba_list_t *pathList; 273 int fd; 274 int size = 64; // default first attempt 275 bool retry = false; 276 struct stat sb; 277 int bufSize; 278 279 /* Before we do anything, let's see if FCSM is on the system */ 280 errno = 0; 281 if (stat(FCSM_DRIVER_PATH.c_str(), &sb) != 0) { 282 if (errno == ENOENT) { 283 log.genericIOError( 284 "The %s driver is not present. Unable to issue " 285 "CT commands. Please install the %s package.", 286 FCSM_DRIVER_PATH.c_str(), FCSM_DRIVER_PKG.c_str()); 287 throw NotSupportedException(); 288 } else { 289 log.genericIOError( 290 "Can not stat the %s driver for reason \"%s\" " 291 "Unable to issue CT commands.", 292 FCSM_DRIVER_PATH.c_str(), strerror(errno)); 293 throw IOError("Unable to stat FCSM driver"); 294 } 295 } 296 297 298 /* construct fcio struct */ 299 memset(&fcio, 0, sizeof (fcio_t)); 300 fcio.fcio_cmd = FCSMIO_ADAPTER_LIST; 301 fcio.fcio_xfer = FCIO_XFER_RW; 302 303 304 /* open the fcsm node so we can send the ioctl to */ 305 errno = 0; 306 if ((fd = open(FCSM_DRIVER_PATH.c_str(), O_RDONLY)) < 0) { 307 if (errno == EBUSY) { 308 throw BusyException(); 309 } else if (errno == EAGAIN) { 310 throw TryAgainException(); 311 } else if (errno == ENOTSUP) { 312 throw NotSupportedException(); 313 } else if (errno == ENOENT) { 314 throw UnavailableException(); 315 } else { 316 throw IOError("Unable to open FCSM driver"); 317 } 318 } 319 320 do { 321 retry = false; 322 errno = 0; 323 bufSize = MAXPATHLEN * size + (int) sizeof (fc_hba_list_t) - 1; 324 pathList = (fc_hba_list_t *)new uchar_t[bufSize]; 325 pathList->numAdapters = size; 326 fcio.fcio_olen = bufSize; 327 fcio.fcio_obuf = (char *)pathList; 328 if (ioctl(fd, FCSMIO_CMD, &fcio) != 0) { 329 /* Interpret the fcio error code */ 330 char fcioErrorString[MAX_FCIO_MSG_LEN] = ""; 331 332 log.genericIOError( 333 "ADAPTER_LIST failed: " 334 "Errno: \"%s\"", 335 strerror(errno)); 336 delete (pathList); 337 close(fd); 338 if (errno == EBUSY) { 339 throw BusyException(); 340 } else if (errno == EAGAIN) { 341 throw TryAgainException(); 342 } else if (errno == ENOTSUP) { 343 throw NotSupportedException(); 344 } else if (errno == ENOENT) { 345 throw UnavailableException(); 346 } else { 347 throw IOError("Unable to build HBA list"); 348 } 349 } 350 if (pathList->numAdapters > size) { 351 log.debug( 352 "Buffer too small for number of HBAs. Retrying."); 353 size = pathList->numAdapters; 354 retry = true; 355 delete (pathList); 356 } 357 } while (retry); 358 359 close(fd); 360 log.debug("Detected %d adapters", pathList->numAdapters); 361 for (int i = 0; i < pathList->numAdapters; i++) { 362 try { 363 HBA *hba = new FCHBA(pathList->hbaPaths[i]); 364 list.insert(list.begin(), hba); 365 } catch (...) { 366 log.debug( 367 "Ignoring partial failure while loading an HBA"); 368 } 369 } 370 if (pathList->numAdapters > HBAList::HBA_MAX_PER_LIST) { 371 delete(pathList); 372 throw InternalError( 373 "Exceeds max number of adatpers that VSL supports."); 374 } 375 delete (pathList); 376 } 377