1fcf3ce44SJohn Forte /* 2fcf3ce44SJohn Forte * CDDL HEADER START 3fcf3ce44SJohn Forte * 4fcf3ce44SJohn Forte * The contents of this file are subject to the terms of the 5fcf3ce44SJohn Forte * Common Development and Distribution License (the "License"). 6fcf3ce44SJohn Forte * You may not use this file except in compliance with the License. 7fcf3ce44SJohn Forte * 8fcf3ce44SJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9fcf3ce44SJohn Forte * or http://www.opensolaris.org/os/licensing. 10fcf3ce44SJohn Forte * See the License for the specific language governing permissions 11fcf3ce44SJohn Forte * and limitations under the License. 12fcf3ce44SJohn Forte * 13fcf3ce44SJohn Forte * When distributing Covered Code, include this CDDL HEADER in each 14fcf3ce44SJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15fcf3ce44SJohn Forte * If applicable, add the following below this CDDL HEADER, with the 16fcf3ce44SJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying 17fcf3ce44SJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner] 18fcf3ce44SJohn Forte * 19fcf3ce44SJohn Forte * CDDL HEADER END 20fcf3ce44SJohn Forte */ 21fcf3ce44SJohn Forte /* 22*c465437aSallan * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23fcf3ce44SJohn Forte * Use is subject to license terms. 24fcf3ce44SJohn Forte */ 25fcf3ce44SJohn Forte 26fcf3ce44SJohn Forte 27fcf3ce44SJohn Forte 28fcf3ce44SJohn Forte #include <FCHBAPort.h> 29fcf3ce44SJohn Forte #include <Exceptions.h> 30fcf3ce44SJohn Forte #include <Trace.h> 31fcf3ce44SJohn Forte #include <sun_fc.h> 32fcf3ce44SJohn Forte #include <iostream> 33fcf3ce44SJohn Forte #include <iomanip> 34fcf3ce44SJohn Forte #include <sys/types.h> 35fcf3ce44SJohn Forte #include <sys/mkdev.h> 36fcf3ce44SJohn Forte #include <sys/stat.h> 37fcf3ce44SJohn Forte #include <fcntl.h> 38fcf3ce44SJohn Forte #include <unistd.h> 39fcf3ce44SJohn Forte #include <stropts.h> 40fcf3ce44SJohn Forte #include <dirent.h> 41fcf3ce44SJohn Forte #include <sys/fibre-channel/fc.h> 42fcf3ce44SJohn Forte #include <sys/fibre-channel/fcio.h> 43fcf3ce44SJohn Forte #include <sys/fibre-channel/ulp/fcp_util.h> 44fcf3ce44SJohn Forte #include <sys/fibre-channel/ulp/fcsm.h> 45fcf3ce44SJohn Forte #include <sys/fibre-channel/impl/fc_error.h> 46fcf3ce44SJohn Forte #include <sys/fibre-channel/fc_appif.h> 47fcf3ce44SJohn Forte #include <sys/scsi/generic/commands.h> 48fcf3ce44SJohn Forte #include <sys/scsi/impl/commands.h> 49fcf3ce44SJohn Forte #include <sys/scsi/impl/sense.h> 50fcf3ce44SJohn Forte #include <sys/scsi/generic/inquiry.h> 51fcf3ce44SJohn Forte #include <sys/scsi/generic/status.h> 52fcf3ce44SJohn Forte #include <errno.h> 53fcf3ce44SJohn Forte #include <FCHBANPIVPort.h> 54fcf3ce44SJohn Forte 55fcf3ce44SJohn Forte 56fcf3ce44SJohn Forte using namespace std; 57fcf3ce44SJohn Forte 58fcf3ce44SJohn Forte const int FCHBAPort::MAX_FCIO_MSG_LEN = 256; 59fcf3ce44SJohn Forte const string FCHBAPort::FCSM_DRIVER_PATH = "/devices/pseudo/fcsm@0:fcsm"; 60fcf3ce44SJohn Forte const string FCHBAPort::FCP_DRIVER_PATH = "/devices/pseudo/fcp@0:fcp"; 61fcf3ce44SJohn Forte 62fcf3ce44SJohn Forte /* 63fcf3ce44SJohn Forte * Interpret the error code in the fcio_t structure 64fcf3ce44SJohn Forte * 65fcf3ce44SJohn Forte * message must be at least MAX_FCIO_MSG_LEN in length. 66fcf3ce44SJohn Forte */ 67fcf3ce44SJohn Forte void 68fcf3ce44SJohn Forte FCHBAPort::transportError(uint32_t fcio_errno, char *message) { 69fcf3ce44SJohn Forte Trace log("transportError"); 70fcf3ce44SJohn Forte string fcioErrorString; 71fcf3ce44SJohn Forte if (message == NULL) { 72fcf3ce44SJohn Forte log.internalError("NULL routine argument"); 73fcf3ce44SJohn Forte return; 74fcf3ce44SJohn Forte } 75fcf3ce44SJohn Forte switch (fcio_errno) { 76fcf3ce44SJohn Forte case (uint32_t)FC_FAILURE: 77fcf3ce44SJohn Forte fcioErrorString = "general failure"; 78fcf3ce44SJohn Forte break; 79fcf3ce44SJohn Forte case (uint32_t)FC_FAILURE_SILENT: 80fcf3ce44SJohn Forte fcioErrorString = "general failure but fail silently"; 81fcf3ce44SJohn Forte break; 82fcf3ce44SJohn Forte case FC_SUCCESS: 83fcf3ce44SJohn Forte fcioErrorString = "successful completion"; 84fcf3ce44SJohn Forte break; 85fcf3ce44SJohn Forte case FC_CAP_ERROR: 86fcf3ce44SJohn Forte fcioErrorString = "FCA capability error"; 87fcf3ce44SJohn Forte break; 88fcf3ce44SJohn Forte case FC_CAP_FOUND: 89fcf3ce44SJohn Forte fcioErrorString = "FCA capability unsettable"; 90fcf3ce44SJohn Forte break; 91fcf3ce44SJohn Forte case FC_CAP_SETTABLE: 92fcf3ce44SJohn Forte fcioErrorString = "FCA capability settable"; 93fcf3ce44SJohn Forte break; 94fcf3ce44SJohn Forte case FC_UNBOUND: 95fcf3ce44SJohn Forte fcioErrorString = "unbound stuff"; 96fcf3ce44SJohn Forte break; 97fcf3ce44SJohn Forte case FC_NOMEM: 98fcf3ce44SJohn Forte fcioErrorString = "allocation error"; 99fcf3ce44SJohn Forte break; 100fcf3ce44SJohn Forte case FC_BADPACKET: 101fcf3ce44SJohn Forte fcioErrorString = "invalid packet specified/supplied"; 102fcf3ce44SJohn Forte break; 103fcf3ce44SJohn Forte case FC_OFFLINE: 104fcf3ce44SJohn Forte fcioErrorString = "I/O resource unavailable"; 105fcf3ce44SJohn Forte break; 106fcf3ce44SJohn Forte case FC_OLDPORT: 107fcf3ce44SJohn Forte fcioErrorString = "operation on non-loop port"; 108fcf3ce44SJohn Forte break; 109fcf3ce44SJohn Forte case FC_NO_MAP: 110fcf3ce44SJohn Forte fcioErrorString = "requested map unavailable"; 111fcf3ce44SJohn Forte break; 112fcf3ce44SJohn Forte case FC_TRANSPORT_ERROR: 113fcf3ce44SJohn Forte fcioErrorString = "unable to transport I/O"; 114fcf3ce44SJohn Forte break; 115fcf3ce44SJohn Forte case FC_ELS_FREJECT: 116fcf3ce44SJohn Forte fcioErrorString = "ELS rejected by a Fabric"; 117fcf3ce44SJohn Forte break; 118fcf3ce44SJohn Forte case FC_ELS_PREJECT: 119fcf3ce44SJohn Forte fcioErrorString = "ELS rejected by an N_port"; 120fcf3ce44SJohn Forte break; 121fcf3ce44SJohn Forte case FC_ELS_BAD: 122fcf3ce44SJohn Forte fcioErrorString = "ELS rejected by FCA/fctl"; 123fcf3ce44SJohn Forte break; 124fcf3ce44SJohn Forte case FC_ELS_MALFORMED: 125fcf3ce44SJohn Forte fcioErrorString = "poorly formed ELS request"; 126fcf3ce44SJohn Forte break; 127fcf3ce44SJohn Forte case FC_TOOMANY: 128fcf3ce44SJohn Forte fcioErrorString = "resource request too large"; 129fcf3ce44SJohn Forte break; 130fcf3ce44SJohn Forte case FC_UB_BADTOKEN: 131fcf3ce44SJohn Forte fcioErrorString = "invalid unsolicited buffer token"; 132fcf3ce44SJohn Forte break; 133fcf3ce44SJohn Forte case FC_UB_ERROR: 134fcf3ce44SJohn Forte fcioErrorString = "invalid unsol buf request"; 135fcf3ce44SJohn Forte break; 136fcf3ce44SJohn Forte case FC_UB_BUSY: 137fcf3ce44SJohn Forte fcioErrorString = "buffer already in use"; 138fcf3ce44SJohn Forte break; 139fcf3ce44SJohn Forte case FC_BADULP: 140fcf3ce44SJohn Forte fcioErrorString = "Unknown ulp"; 141fcf3ce44SJohn Forte break; 142fcf3ce44SJohn Forte case FC_BADTYPE: 143fcf3ce44SJohn Forte fcioErrorString = "ULP not registered to handle this FC4 type"; 144fcf3ce44SJohn Forte break; 145fcf3ce44SJohn Forte case FC_UNCLAIMED: 146fcf3ce44SJohn Forte fcioErrorString = "request or data not claimed"; 147fcf3ce44SJohn Forte break; 148fcf3ce44SJohn Forte case FC_ULP_SAMEMODULE: 149fcf3ce44SJohn Forte fcioErrorString = "module already in use"; 150fcf3ce44SJohn Forte break; 151fcf3ce44SJohn Forte case FC_ULP_SAMETYPE: 152fcf3ce44SJohn Forte fcioErrorString = "FC4 module already in use"; 153fcf3ce44SJohn Forte break; 154fcf3ce44SJohn Forte case FC_ABORTED: 155fcf3ce44SJohn Forte fcioErrorString = "request aborted"; 156fcf3ce44SJohn Forte break; 157fcf3ce44SJohn Forte case FC_ABORT_FAILED: 158fcf3ce44SJohn Forte fcioErrorString = "abort request failed"; 159fcf3ce44SJohn Forte break; 160fcf3ce44SJohn Forte case FC_BADEXCHANGE: 161fcf3ce44SJohn Forte fcioErrorString = "exchange doesn�t exist"; 162fcf3ce44SJohn Forte break; 163fcf3ce44SJohn Forte case FC_BADWWN: 164fcf3ce44SJohn Forte fcioErrorString = "WWN not recognized"; 165fcf3ce44SJohn Forte break; 166fcf3ce44SJohn Forte case FC_BADDEV: 167fcf3ce44SJohn Forte fcioErrorString = "device unrecognized"; 168fcf3ce44SJohn Forte break; 169fcf3ce44SJohn Forte case FC_BADCMD: 170fcf3ce44SJohn Forte fcioErrorString = "invalid command issued"; 171fcf3ce44SJohn Forte break; 172fcf3ce44SJohn Forte case FC_BADOBJECT: 173fcf3ce44SJohn Forte fcioErrorString = "invalid object requested"; 174fcf3ce44SJohn Forte break; 175fcf3ce44SJohn Forte case FC_BADPORT: 176fcf3ce44SJohn Forte fcioErrorString = "invalid port specified"; 177fcf3ce44SJohn Forte break; 178fcf3ce44SJohn Forte case FC_NOTTHISPORT: 179fcf3ce44SJohn Forte fcioErrorString = "resource not at this port"; 180fcf3ce44SJohn Forte break; 181fcf3ce44SJohn Forte case FC_PREJECT: 182fcf3ce44SJohn Forte fcioErrorString = "reject at remote N_Port"; 183fcf3ce44SJohn Forte break; 184fcf3ce44SJohn Forte case FC_FREJECT: 185fcf3ce44SJohn Forte fcioErrorString = "reject at remote Fabric"; 186fcf3ce44SJohn Forte break; 187fcf3ce44SJohn Forte case FC_PBUSY: 188fcf3ce44SJohn Forte fcioErrorString = "remote N_Port busy"; 189fcf3ce44SJohn Forte break; 190fcf3ce44SJohn Forte case FC_FBUSY: 191fcf3ce44SJohn Forte fcioErrorString = "remote Fabric busy"; 192fcf3ce44SJohn Forte break; 193fcf3ce44SJohn Forte case FC_ALREADY: 194fcf3ce44SJohn Forte fcioErrorString = "already logged in"; 195fcf3ce44SJohn Forte break; 196fcf3ce44SJohn Forte case FC_LOGINREQ: 197fcf3ce44SJohn Forte fcioErrorString = "login required"; 198fcf3ce44SJohn Forte break; 199fcf3ce44SJohn Forte case FC_RESETFAIL: 200fcf3ce44SJohn Forte fcioErrorString = "reset failed"; 201fcf3ce44SJohn Forte break; 202fcf3ce44SJohn Forte case FC_INVALID_REQUEST: 203fcf3ce44SJohn Forte fcioErrorString = "request is invalid"; 204fcf3ce44SJohn Forte break; 205fcf3ce44SJohn Forte case FC_OUTOFBOUNDS: 206fcf3ce44SJohn Forte fcioErrorString = "port number is out of bounds"; 207fcf3ce44SJohn Forte break; 208fcf3ce44SJohn Forte case FC_TRAN_BUSY: 209fcf3ce44SJohn Forte fcioErrorString = "command transport busy"; 210fcf3ce44SJohn Forte break; 211fcf3ce44SJohn Forte case FC_STATEC_BUSY: 212fcf3ce44SJohn Forte fcioErrorString = "port driver currently busy"; 213fcf3ce44SJohn Forte break; 214fcf3ce44SJohn Forte case FC_DEVICE_BUSY: 215fcf3ce44SJohn Forte fcioErrorString = "transport working on this device"; 216fcf3ce44SJohn Forte break; 217fcf3ce44SJohn Forte case FC_DEVICE_NOT_TGT: 218fcf3ce44SJohn Forte fcioErrorString = "device is not a SCSI target"; 219fcf3ce44SJohn Forte break; 220fcf3ce44SJohn Forte default: 221fcf3ce44SJohn Forte snprintf(message, MAX_FCIO_MSG_LEN, "Unknown error code 0x%x", 222fcf3ce44SJohn Forte fcio_errno); 223fcf3ce44SJohn Forte return; 224fcf3ce44SJohn Forte } 225fcf3ce44SJohn Forte snprintf(message, MAX_FCIO_MSG_LEN, "%s", fcioErrorString.c_str()); 226fcf3ce44SJohn Forte } 227fcf3ce44SJohn Forte 228fcf3ce44SJohn Forte static void 229fcf3ce44SJohn Forte reportSense(struct scsi_extended_sense *sense, const char *routine) { 230fcf3ce44SJohn Forte Trace log("reportSense"); 231fcf3ce44SJohn Forte string msg; 232fcf3ce44SJohn Forte if (!sense) { 233fcf3ce44SJohn Forte log.internalError("NULL sense argument passed."); 234fcf3ce44SJohn Forte return; 235fcf3ce44SJohn Forte } 236fcf3ce44SJohn Forte if (!routine) { 237fcf3ce44SJohn Forte log.internalError("NULL routine argument passed."); 238fcf3ce44SJohn Forte return; 239fcf3ce44SJohn Forte } 240fcf3ce44SJohn Forte log.genericIOError("SCSI FAILURE"); 241fcf3ce44SJohn Forte switch (sense->es_key) { 242fcf3ce44SJohn Forte case KEY_NO_SENSE: 243fcf3ce44SJohn Forte msg = "No sense"; 244fcf3ce44SJohn Forte break; 245fcf3ce44SJohn Forte case KEY_RECOVERABLE_ERROR: 246fcf3ce44SJohn Forte msg = "Recoverable error"; 247fcf3ce44SJohn Forte break; 248fcf3ce44SJohn Forte case KEY_NOT_READY: 249fcf3ce44SJohn Forte msg = "Not ready"; 250fcf3ce44SJohn Forte break; 251fcf3ce44SJohn Forte case KEY_MEDIUM_ERROR: 252fcf3ce44SJohn Forte msg = "Medium error"; 253fcf3ce44SJohn Forte break; 254fcf3ce44SJohn Forte case KEY_HARDWARE_ERROR: 255fcf3ce44SJohn Forte msg = "Hardware error"; 256fcf3ce44SJohn Forte break; 257fcf3ce44SJohn Forte case KEY_ILLEGAL_REQUEST: 258fcf3ce44SJohn Forte msg = "Illegal request"; 259fcf3ce44SJohn Forte break; 260fcf3ce44SJohn Forte case KEY_UNIT_ATTENTION: 261fcf3ce44SJohn Forte msg = "Unit attention"; 262fcf3ce44SJohn Forte break; 263fcf3ce44SJohn Forte case KEY_DATA_PROTECT: 264fcf3ce44SJohn Forte msg = "Data protect"; 265fcf3ce44SJohn Forte break; 266fcf3ce44SJohn Forte case KEY_BLANK_CHECK: 267fcf3ce44SJohn Forte msg = "Blank check"; 268fcf3ce44SJohn Forte break; 269fcf3ce44SJohn Forte case KEY_VENDOR_UNIQUE: 270fcf3ce44SJohn Forte msg = "Vendor Unique"; 271fcf3ce44SJohn Forte break; 272fcf3ce44SJohn Forte case KEY_COPY_ABORTED: 273fcf3ce44SJohn Forte msg = "Copy aborted"; 274fcf3ce44SJohn Forte break; 275fcf3ce44SJohn Forte case KEY_ABORTED_COMMAND: 276fcf3ce44SJohn Forte msg = "Aborted command"; 277fcf3ce44SJohn Forte break; 278fcf3ce44SJohn Forte case KEY_EQUAL: 279fcf3ce44SJohn Forte msg = "Equal"; 280fcf3ce44SJohn Forte break; 281fcf3ce44SJohn Forte case KEY_VOLUME_OVERFLOW: 282fcf3ce44SJohn Forte msg = "Volume overflow"; 283fcf3ce44SJohn Forte break; 284fcf3ce44SJohn Forte case KEY_MISCOMPARE: 285fcf3ce44SJohn Forte msg = "Miscompare"; 286fcf3ce44SJohn Forte break; 287fcf3ce44SJohn Forte case KEY_RESERVED: 288fcf3ce44SJohn Forte msg = "Reserved"; 289fcf3ce44SJohn Forte break; 290fcf3ce44SJohn Forte default: 291fcf3ce44SJohn Forte msg = "unknown sense key"; 292fcf3ce44SJohn Forte } 293fcf3ce44SJohn Forte log.genericIOError("\tSense key: %s", msg.c_str()); 294fcf3ce44SJohn Forte log.genericIOError("\tASC = 0x%x", sense->es_add_code); 295fcf3ce44SJohn Forte log.genericIOError("\tASCQ = 0x%x", sense->es_qual_code); 296fcf3ce44SJohn Forte } 297fcf3ce44SJohn Forte 298fcf3ce44SJohn Forte /* 299fcf3ce44SJohn Forte * Issue a SCSI pass thru command. 300fcf3ce44SJohn Forte * Returns a scsi status value. 301fcf3ce44SJohn Forte */ 302fcf3ce44SJohn Forte void FCHBAPort::sendSCSIPassThru(struct fcp_scsi_cmd *fscsi, 303fcf3ce44SJohn Forte HBA_UINT32 *responseSize, HBA_UINT32 *senseSize, 304fcf3ce44SJohn Forte HBA_UINT8 *scsiStatus) { 305fcf3ce44SJohn Forte Trace log("FCHBAPort::sendSCSIPassThru"); 306fcf3ce44SJohn Forte int fd; 307fcf3ce44SJohn Forte HBA_STATUS ret; 308fcf3ce44SJohn Forte int count; 309fcf3ce44SJohn Forte char fcioErrorString[MAX_FCIO_MSG_LEN] = ""; 310fcf3ce44SJohn Forte hrtime_t start; 311fcf3ce44SJohn Forte hrtime_t end; 312fcf3ce44SJohn Forte int ioctl_errno; 313fcf3ce44SJohn Forte double duration; 314fcf3ce44SJohn Forte la_wwn_t wwn; 315fcf3ce44SJohn Forte 316fcf3ce44SJohn Forte if (fscsi == NULL || 317fcf3ce44SJohn Forte responseSize == NULL || 318fcf3ce44SJohn Forte senseSize == NULL || 319fcf3ce44SJohn Forte scsiStatus == NULL) { 320fcf3ce44SJohn Forte throw BadArgumentException(); 321fcf3ce44SJohn Forte } 322fcf3ce44SJohn Forte 323fcf3ce44SJohn Forte memcpy(&wwn, fscsi->scsi_fc_pwwn.raw_wwn, sizeof (la_wwn_t)); 324fcf3ce44SJohn Forte start = gethrtime(); 325fcf3ce44SJohn Forte fscsi->scsi_fc_port_num = instanceNumber; 326fcf3ce44SJohn Forte 327fcf3ce44SJohn Forte fd = HBA::_open(FCP_DRIVER_PATH, O_RDONLY | O_NDELAY); 328fcf3ce44SJohn Forte count = 0; 329fcf3ce44SJohn Forte ioctl_errno = 0; 330fcf3ce44SJohn Forte 331fcf3ce44SJohn Forte if (ioctl(fd, FCP_TGT_SEND_SCSI, fscsi) != 0) { 332fcf3ce44SJohn Forte /* save off errno */ 333fcf3ce44SJohn Forte ioctl_errno = errno; 334fcf3ce44SJohn Forte close(fd); 335fcf3ce44SJohn Forte /* 336fcf3ce44SJohn Forte * collect SCSI status first regrardless of the value. 337fcf3ce44SJohn Forte * 0 is a good status so this should be okay 338fcf3ce44SJohn Forte */ 339fcf3ce44SJohn Forte *scsiStatus = fscsi->scsi_bufstatus & STATUS_MASK; 340fcf3ce44SJohn Forte transportError(fscsi->scsi_fc_status, fcioErrorString); 341fcf3ce44SJohn Forte 342fcf3ce44SJohn Forte /* Did we get a check condition? */ 343fcf3ce44SJohn Forte if ((fscsi->scsi_bufstatus & STATUS_MASK) == STATUS_CHECK) { 344fcf3ce44SJohn Forte *senseSize = fscsi->scsi_rqlen; 345fcf3ce44SJohn Forte throw CheckConditionException(); 346fcf3ce44SJohn Forte } else if (fscsi->scsi_fc_status == FC_DEVICE_NOT_TGT) { 347fcf3ce44SJohn Forte /* 348fcf3ce44SJohn Forte * fcp driver returns FC_DEVICE_NOT_TGT when the node is not 349fcf3ce44SJohn Forte * scsi-capable like remote hba nodes. 350fcf3ce44SJohn Forte */ 351fcf3ce44SJohn Forte throw NotATargetException(); 352fcf3ce44SJohn Forte } else if (fscsi->scsi_fc_status == FC_INVALID_LUN) { 353fcf3ce44SJohn Forte throw InvalidLUNException(); 354fcf3ce44SJohn Forte } else if (ioctl_errno == EBUSY) { 355fcf3ce44SJohn Forte throw BusyException(); 356fcf3ce44SJohn Forte } else if (ioctl_errno == EAGAIN) { 357fcf3ce44SJohn Forte throw TryAgainException(); 358fcf3ce44SJohn Forte } else if (ioctl_errno == ENOTSUP) { 359fcf3ce44SJohn Forte throw NotSupportedException(); 360fcf3ce44SJohn Forte } else if (ioctl_errno == ENOENT) { 361fcf3ce44SJohn Forte throw UnavailableException(); 362fcf3ce44SJohn Forte } else { 363fcf3ce44SJohn Forte throw IOError(this, wwnConversion(wwn.raw_wwn), 364fcf3ce44SJohn Forte fscsi->scsi_lun); 365fcf3ce44SJohn Forte } 366fcf3ce44SJohn Forte } else { 367fcf3ce44SJohn Forte close(fd); 368fcf3ce44SJohn Forte /* Just in case, check for a check-condition state */ 369fcf3ce44SJohn Forte if ((fscsi->scsi_bufstatus & STATUS_MASK) == STATUS_CHECK) { 370fcf3ce44SJohn Forte *scsiStatus = fscsi->scsi_bufstatus & STATUS_MASK; 371fcf3ce44SJohn Forte *senseSize = fscsi->scsi_rqlen; 372fcf3ce44SJohn Forte throw CheckConditionException(); 373fcf3ce44SJohn Forte } 374fcf3ce44SJohn Forte } 375fcf3ce44SJohn Forte 376fcf3ce44SJohn Forte /* Record the response data */ 377fcf3ce44SJohn Forte *scsiStatus = fscsi->scsi_bufstatus & STATUS_MASK; 378fcf3ce44SJohn Forte *responseSize = fscsi->scsi_buflen; 379fcf3ce44SJohn Forte *senseSize = fscsi->scsi_rqlen; 380fcf3ce44SJohn Forte 381fcf3ce44SJohn Forte /* Do some quick duration calcuations */ 382fcf3ce44SJohn Forte end = gethrtime(); 383fcf3ce44SJohn Forte duration = end - start; 384fcf3ce44SJohn Forte duration /= HR_SECOND; 385fcf3ce44SJohn Forte log.debug("Total SCSI IO time for HBA %s " 386fcf3ce44SJohn Forte "target %016llx was %.4f seconds", getPath().c_str(), 387fcf3ce44SJohn Forte wwnConversion(wwn.raw_wwn), duration); 388fcf3ce44SJohn Forte 389fcf3ce44SJohn Forte #ifdef DEBUG 390fcf3ce44SJohn Forte /* Did we have any failure */ 391fcf3ce44SJohn Forte if (ret != HBA_STATUS_OK) { 392fcf3ce44SJohn Forte log.genericIOError( 393fcf3ce44SJohn Forte "Ioctl failed for device \"%s\" target %016llx." 394fcf3ce44SJohn Forte " Errno: \"%s\"(%d), " 395fcf3ce44SJohn Forte "Transport: \"%s\", SCSI Status: 0x%x" 396fcf3ce44SJohn Forte "responseSize = %d, senseSize = %d", 397fcf3ce44SJohn Forte getPath().c_str(), wwnConversion(fscsi->scsi_fc_pwwn.raw_wwn), 398fcf3ce44SJohn Forte strerror(ioctl_errno), ioctl_errno, fcioErrorString, 399fcf3ce44SJohn Forte *scsiStatus, *responseSize, *senseSize); 400fcf3ce44SJohn Forte /* We may or may not have sense data */ 401fcf3ce44SJohn Forte reportSense((struct scsi_extended_sense *)fscsi->scsi_rqbufaddr, 402fcf3ce44SJohn Forte ROUTINE); 403fcf3ce44SJohn Forte } 404fcf3ce44SJohn Forte #endif 405fcf3ce44SJohn Forte 406fcf3ce44SJohn Forte } 407fcf3ce44SJohn Forte 408fcf3ce44SJohn Forte /* 409fcf3ce44SJohn Forte * constructs the fcp_scsi_cmd struct for SCSI_Inquiry, SendReadCapacity, or 410fcf3ce44SJohn Forte * SendReportLUNs 411fcf3ce44SJohn Forte */ 412fcf3ce44SJohn Forte /*#include <fcio.h> 413fcf3ce44SJohn Forte #include <fcp_util.h>*/ 414fcf3ce44SJohn Forte inline void 415fcf3ce44SJohn Forte scsi_cmd_init(struct fcp_scsi_cmd *fscsi, const char *portname, void *reqbuf, 416fcf3ce44SJohn Forte size_t req_len, void *responseBuffer, size_t resp_len, 417fcf3ce44SJohn Forte void *senseBuffer, size_t sense_len) { 418fcf3ce44SJohn Forte Trace log("scsi_cmd_init"); 419fcf3ce44SJohn Forte fscsi->scsi_fc_rspcode = 0; 420fcf3ce44SJohn Forte fscsi->scsi_flags = FCP_SCSI_READ; 421fcf3ce44SJohn Forte fscsi->scsi_timeout = 10 /* sec */; 422fcf3ce44SJohn Forte fscsi->scsi_cdbbufaddr = (char *)reqbuf; 423fcf3ce44SJohn Forte fscsi->scsi_cdblen = (uint32_t) req_len; 424fcf3ce44SJohn Forte fscsi->scsi_bufaddr = (char *)responseBuffer; 425fcf3ce44SJohn Forte fscsi->scsi_buflen = (uint32_t) resp_len; 426fcf3ce44SJohn Forte fscsi->scsi_bufresid = 0; 427fcf3ce44SJohn Forte fscsi->scsi_bufstatus = 0; 428fcf3ce44SJohn Forte fscsi->scsi_rqbufaddr = (char *)senseBuffer; 429fcf3ce44SJohn Forte fscsi->scsi_rqlen = (uint32_t) sense_len; 430fcf3ce44SJohn Forte fscsi->scsi_rqresid = 0; 431fcf3ce44SJohn Forte } 432fcf3ce44SJohn Forte 433fcf3ce44SJohn Forte 434fcf3ce44SJohn Forte FCHBAPort::FCHBAPort(string thePath) : HBAPort() { 435fcf3ce44SJohn Forte Trace log("FCHBAPort::FCHBAPort"); 436fcf3ce44SJohn Forte log.debug("Initializing HBA port %s", thePath.c_str()); 437fcf3ce44SJohn Forte fcio_t fcio; 438fcf3ce44SJohn Forte int size = 200; 439fcf3ce44SJohn Forte fc_hba_npiv_port_list_t *pathList; 440fcf3ce44SJohn Forte bool retry = false; 441fcf3ce44SJohn Forte int bufSize; 442fcf3ce44SJohn Forte 443fcf3ce44SJohn Forte try { 444fcf3ce44SJohn Forte path = lookupControllerPath(thePath); 445fcf3ce44SJohn Forte sscanf(path.c_str(), "/dev/cfg/c%d", &controllerNumber); 446fcf3ce44SJohn Forte } catch (...) { 447fcf3ce44SJohn Forte log.debug("Unable to lookup controller path and number for %s", 448fcf3ce44SJohn Forte thePath.c_str()); 449fcf3ce44SJohn Forte path = "/devices"; 450fcf3ce44SJohn Forte path += thePath; 451fcf3ce44SJohn Forte path += ":fc"; 452fcf3ce44SJohn Forte controllerNumber = -1; 453fcf3ce44SJohn Forte } 454fcf3ce44SJohn Forte 455fcf3ce44SJohn Forte // Fetch the minor number for later use 456fcf3ce44SJohn Forte struct stat sbuf; 457fcf3ce44SJohn Forte if (stat(path.c_str(), &sbuf) == -1) { 458fcf3ce44SJohn Forte throw IOError("Unable to stat device path: " + path); 459fcf3ce44SJohn Forte } 460fcf3ce44SJohn Forte instanceNumber = minor(sbuf.st_rdev); 461fcf3ce44SJohn Forte 462fcf3ce44SJohn Forte // This routine is not index based, so we can discard stateChange 463fcf3ce44SJohn Forte uint64_t tmp; 464fcf3ce44SJohn Forte HBA_PORTATTRIBUTES attrs = getPortAttributes(tmp); 465fcf3ce44SJohn Forte memcpy(&tmp, &attrs.PortWWN, 8); 466fcf3ce44SJohn Forte portWWN = ntohll(tmp); 467fcf3ce44SJohn Forte memcpy(&tmp, &attrs.NodeWWN, 8); 468fcf3ce44SJohn Forte nodeWWN = ntohll(tmp); 469fcf3ce44SJohn Forte 470fcf3ce44SJohn Forte // For reference, here's how to dump WWN's through C++ streams. 471fcf3ce44SJohn Forte // cout << "\tPort WWN: " << hex << setfill('0') << setw(16) << portWWN 472fcf3ce44SJohn Forte // << endl; 473fcf3ce44SJohn Forte // cout << "\tNode WWN: " << hex << setfill('0') << setw(16) << nodeWWN 474fcf3ce44SJohn Forte // << endl; 475fcf3ce44SJohn Forte 476fcf3ce44SJohn Forte // we should add code here to build NPIVPORT instance 477fcf3ce44SJohn Forte // Get Port's NPIV port list ( include nwwn and pwwn and path) 478fcf3ce44SJohn Forte memset((caddr_t)&fcio, 0, sizeof (fcio)); 479fcf3ce44SJohn Forte fcio.fcio_cmd = FCIO_GET_NPIV_PORT_LIST; 480fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_READ; 481fcf3ce44SJohn Forte do { 482fcf3ce44SJohn Forte retry = false; 483*c465437aSallan bufSize = MAXPATHLEN * (size - 1) + (int) sizeof (fc_hba_npiv_port_list_t); 484fcf3ce44SJohn Forte pathList = (fc_hba_npiv_port_list_t *) new uchar_t[bufSize]; 485fcf3ce44SJohn Forte pathList->numAdapters = size; 486fcf3ce44SJohn Forte fcio.fcio_olen = bufSize; 487fcf3ce44SJohn Forte fcio.fcio_obuf = (char *)pathList; 488fcf3ce44SJohn Forte fp_ioctl(getPath(), FCIO_CMD, &fcio); 489fcf3ce44SJohn Forte if (pathList->numAdapters > size) { 490fcf3ce44SJohn Forte log.debug("Buffer too small for number of NPIV Port.Retry."); 491fcf3ce44SJohn Forte size = pathList->numAdapters; 492fcf3ce44SJohn Forte retry = true; 493fcf3ce44SJohn Forte delete (pathList); 494fcf3ce44SJohn Forte } 495fcf3ce44SJohn Forte } while (retry); 496fcf3ce44SJohn Forte log.debug("Get %d npiv ports", pathList->numAdapters); 497fcf3ce44SJohn Forte // Make instance for each NPIV Port 498fcf3ce44SJohn Forte for ( int i = 0; i < pathList->numAdapters; i++) { 499fcf3ce44SJohn Forte try { 500fcf3ce44SJohn Forte addPort(new FCHBANPIVPort(pathList->hbaPaths[i])); 501fcf3ce44SJohn Forte } catch (...) { 502fcf3ce44SJohn Forte log.debug("Ignoring partial failure"); 503fcf3ce44SJohn Forte } 504fcf3ce44SJohn Forte } 505fcf3ce44SJohn Forte delete (pathList); 506fcf3ce44SJohn Forte } 507fcf3ce44SJohn Forte 508fcf3ce44SJohn Forte uint32_t FCHBAPort::deleteNPIVPort(uint64_t vportwwn) { 509fcf3ce44SJohn Forte Trace log("FCHBAPort::deleteNPIVPort"); 510fcf3ce44SJohn Forte fcio_t fcio; 511fcf3ce44SJohn Forte la_wwn_t lawwn[1]; 512fcf3ce44SJohn Forte int ret = 0; 513fcf3ce44SJohn Forte 514fcf3ce44SJohn Forte memset(&fcio, 0, sizeof(fcio)); 515fcf3ce44SJohn Forte uint64_t en_wwn = htonll(vportwwn); 516fcf3ce44SJohn Forte memcpy(&lawwn[0], &en_wwn, sizeof (en_wwn)); 517fcf3ce44SJohn Forte 518fcf3ce44SJohn Forte fcio.fcio_cmd = FCIO_DELETE_NPIV_PORT; 519fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_WRITE; 520fcf3ce44SJohn Forte fcio.fcio_ilen = sizeof (la_wwn_t) * 2; 521fcf3ce44SJohn Forte fcio.fcio_ibuf = (caddr_t)&lawwn; 522fcf3ce44SJohn Forte 523fcf3ce44SJohn Forte fp_ioctl(getPath(), FCIO_CMD, &fcio); 524fcf3ce44SJohn Forte 525fcf3ce44SJohn Forte return (ret); 526fcf3ce44SJohn Forte } 527fcf3ce44SJohn Forte 528fcf3ce44SJohn Forte uint32_t FCHBAPort::createNPIVPort(uint64_t vnodewwn, uint64_t vportwwn, uint32_t vindex) { 529fcf3ce44SJohn Forte Trace log("FCHBAPort::createNPIVPort"); 530fcf3ce44SJohn Forte fcio_t fcio; 531fcf3ce44SJohn Forte la_wwn_t lawwn[2]; 532fcf3ce44SJohn Forte uint32_t vportindex = 0; 533fcf3ce44SJohn Forte HBA_NPIVCREATEENTRY entrybuf; 534fcf3ce44SJohn Forte 535fcf3ce44SJohn Forte memset(&fcio, 0, sizeof(fcio)); 536fcf3ce44SJohn Forte uint64_t en_wwn = htonll(vnodewwn); 537fcf3ce44SJohn Forte memcpy(&entrybuf.VNodeWWN, &en_wwn, sizeof (en_wwn)); 538fcf3ce44SJohn Forte en_wwn = htonll(vportwwn); 539fcf3ce44SJohn Forte memcpy(&entrybuf.VPortWWN, &en_wwn, sizeof (en_wwn)); 540fcf3ce44SJohn Forte entrybuf.vindex = vindex; 541fcf3ce44SJohn Forte 542fcf3ce44SJohn Forte fcio.fcio_cmd = FCIO_CREATE_NPIV_PORT; 543fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_READ; 544fcf3ce44SJohn Forte fcio.fcio_olen = sizeof (uint32_t); 545fcf3ce44SJohn Forte fcio.fcio_obuf = (caddr_t)&vportindex; 546fcf3ce44SJohn Forte fcio.fcio_ilen = sizeof (HBA_NPIVCREATEENTRY); 547fcf3ce44SJohn Forte fcio.fcio_ibuf = (caddr_t)&entrybuf; 548fcf3ce44SJohn Forte 549fcf3ce44SJohn Forte fp_ioctl(getPath(), FCIO_CMD, &fcio); 550fcf3ce44SJohn Forte 551fcf3ce44SJohn Forte return (vportindex); 552fcf3ce44SJohn Forte } 553fcf3ce44SJohn Forte 554fcf3ce44SJohn Forte HBA_PORTNPIVATTRIBUTES FCHBAPort::getPortNPIVAttributes(uint64_t &stateChange) { 555fcf3ce44SJohn Forte Trace log("FCHBAPort::getPortNPIVAttributes"); 556fcf3ce44SJohn Forte 557fcf3ce44SJohn Forte HBA_PORTNPIVATTRIBUTES attributes; 558fcf3ce44SJohn Forte fc_hba_port_npiv_attributes_t attrs; 559fcf3ce44SJohn Forte fcio_t fcio; 560fcf3ce44SJohn Forte 561fcf3ce44SJohn Forte memset(&fcio, 0, sizeof(fcio)); 562fcf3ce44SJohn Forte memset(&attributes, 0, sizeof(attributes)); 563fcf3ce44SJohn Forte 564fcf3ce44SJohn Forte fcio.fcio_cmd = FCIO_GET_ADAPTER_PORT_NPIV_ATTRIBUTES; 565fcf3ce44SJohn Forte fcio.fcio_olen = sizeof(attrs); 566fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_READ; 567fcf3ce44SJohn Forte fcio.fcio_obuf = (caddr_t)&attrs; 568fcf3ce44SJohn Forte 569fcf3ce44SJohn Forte fp_ioctl(getPath(), FCIO_CMD, &fcio); 570fcf3ce44SJohn Forte 571fcf3ce44SJohn Forte stateChange = attrs.lastChange; 572fcf3ce44SJohn Forte attributes.npivflag = attrs.npivflag; 573fcf3ce44SJohn Forte memcpy(&attributes.NodeWWN, &attrs.NodeWWN, 8); 574fcf3ce44SJohn Forte memcpy(&attributes.PortWWN, &attrs.PortWWN, 8); 575fcf3ce44SJohn Forte attributes.MaxNumberOfNPIVPorts = attrs.MaxNumberOfNPIVPorts; 576fcf3ce44SJohn Forte attributes.NumberOfNPIVPorts = attrs.NumberOfNPIVPorts; 577fcf3ce44SJohn Forte 578fcf3ce44SJohn Forte return (attributes); 579fcf3ce44SJohn Forte } 580fcf3ce44SJohn Forte 581fcf3ce44SJohn Forte HBA_PORTATTRIBUTES FCHBAPort::getPortAttributes(uint64_t &stateChange) { 582fcf3ce44SJohn Forte Trace log("FCHBAPort::getPortAttributes"); 583fcf3ce44SJohn Forte 584fcf3ce44SJohn Forte HBA_PORTATTRIBUTES attributes; 585fcf3ce44SJohn Forte fcio_t fcio; 586fcf3ce44SJohn Forte fc_hba_port_attributes_t attrs; 587fcf3ce44SJohn Forte 588fcf3ce44SJohn Forte memset(&fcio, 0, sizeof (fcio)); 589fcf3ce44SJohn Forte memset(&attributes, 0, sizeof (attributes)); 590fcf3ce44SJohn Forte 591fcf3ce44SJohn Forte fcio.fcio_cmd = FCIO_GET_ADAPTER_PORT_ATTRIBUTES; 592fcf3ce44SJohn Forte fcio.fcio_olen = sizeof (attrs); 593fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_READ; 594fcf3ce44SJohn Forte fcio.fcio_obuf = (caddr_t)&attrs; 595fcf3ce44SJohn Forte 596fcf3ce44SJohn Forte fp_ioctl(getPath(), FCIO_CMD, &fcio); 597fcf3ce44SJohn Forte 598fcf3ce44SJohn Forte stateChange = attrs.lastChange; 599fcf3ce44SJohn Forte 600fcf3ce44SJohn Forte attributes.PortFcId = attrs.PortFcId; 601fcf3ce44SJohn Forte attributes.PortType = attrs.PortType; 602fcf3ce44SJohn Forte attributes.PortState = attrs.PortState; 603fcf3ce44SJohn Forte attributes.PortSupportedClassofService = attrs.PortSupportedClassofService; 604fcf3ce44SJohn Forte attributes.PortSupportedSpeed = attrs.PortSupportedSpeed; 605fcf3ce44SJohn Forte attributes.PortSpeed = attrs.PortSpeed; 606fcf3ce44SJohn Forte attributes.PortMaxFrameSize = attrs.PortMaxFrameSize; 607fcf3ce44SJohn Forte attributes.NumberofDiscoveredPorts = attrs.NumberofDiscoveredPorts; 608fcf3ce44SJohn Forte memcpy(&attributes.NodeWWN, &attrs.NodeWWN, 8); 609fcf3ce44SJohn Forte memcpy(&attributes.PortWWN, &attrs.PortWWN, 8); 610fcf3ce44SJohn Forte memcpy(&attributes.FabricName, &attrs.FabricName, 8); 611fcf3ce44SJohn Forte memcpy(&attributes.PortSupportedFc4Types, &attrs.PortSupportedFc4Types, 32); 612fcf3ce44SJohn Forte memcpy(&attributes.PortActiveFc4Types, &attrs.PortActiveFc4Types, 32); 613fcf3ce44SJohn Forte memcpy(&attributes.PortSymbolicName, &attrs.PortSymbolicName, 256); 614fcf3ce44SJohn Forte 615fcf3ce44SJohn Forte strncpy((char *)attributes.OSDeviceName, getPath().c_str(), 256); 616fcf3ce44SJohn Forte return (attributes); 617fcf3ce44SJohn Forte } 618fcf3ce44SJohn Forte 619fcf3ce44SJohn Forte HBA_PORTATTRIBUTES FCHBAPort::getDiscoveredAttributes( 620fcf3ce44SJohn Forte HBA_UINT32 discoveredport, uint64_t &stateChange) { 621fcf3ce44SJohn Forte Trace log("FCHBAPort::getDiscoverdAttributes(i)"); 622fcf3ce44SJohn Forte 623fcf3ce44SJohn Forte HBA_PORTATTRIBUTES attributes; 624fcf3ce44SJohn Forte fcio_t fcio; 625fcf3ce44SJohn Forte fc_hba_port_attributes_t attrs; 626fcf3ce44SJohn Forte 627fcf3ce44SJohn Forte memset(&fcio, 0, sizeof (fcio)); 628fcf3ce44SJohn Forte memset(&attributes, 0, sizeof (attributes)); 629fcf3ce44SJohn Forte 630fcf3ce44SJohn Forte fcio.fcio_cmd = FCIO_GET_DISCOVERED_PORT_ATTRIBUTES; 631fcf3ce44SJohn Forte fcio.fcio_olen = sizeof (attrs); 632fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_READ; 633fcf3ce44SJohn Forte fcio.fcio_obuf = (caddr_t)&attrs; 634fcf3ce44SJohn Forte fcio.fcio_ilen = sizeof (discoveredport); 635fcf3ce44SJohn Forte fcio.fcio_ibuf = (caddr_t)&discoveredport; 636fcf3ce44SJohn Forte 637fcf3ce44SJohn Forte fp_ioctl(getPath(), FCIO_CMD, &fcio); 638fcf3ce44SJohn Forte 639fcf3ce44SJohn Forte stateChange = attrs.lastChange; 640fcf3ce44SJohn Forte 641fcf3ce44SJohn Forte attributes.PortFcId = attrs.PortFcId; 642fcf3ce44SJohn Forte attributes.PortType = attrs.PortType; 643fcf3ce44SJohn Forte attributes.PortState = attrs.PortState; 644fcf3ce44SJohn Forte attributes.PortSupportedClassofService = attrs.PortSupportedClassofService; 645fcf3ce44SJohn Forte attributes.PortSupportedSpeed = attrs.PortSupportedSpeed; 646fcf3ce44SJohn Forte attributes.PortSpeed = attrs.PortSpeed; 647fcf3ce44SJohn Forte attributes.PortMaxFrameSize = attrs.PortMaxFrameSize; 648fcf3ce44SJohn Forte attributes.NumberofDiscoveredPorts = attrs.NumberofDiscoveredPorts; 649fcf3ce44SJohn Forte memcpy(&attributes.NodeWWN, &attrs.NodeWWN, 8); 650fcf3ce44SJohn Forte memcpy(&attributes.PortWWN, &attrs.PortWWN, 8); 651fcf3ce44SJohn Forte memcpy(&attributes.FabricName, &attrs.FabricName, 8); 652fcf3ce44SJohn Forte memcpy(&attributes.PortSupportedFc4Types, &attrs.PortSupportedFc4Types, 32); 653fcf3ce44SJohn Forte memcpy(&attributes.PortActiveFc4Types, &attrs.PortActiveFc4Types, 32); 654fcf3ce44SJohn Forte memcpy(&attributes.PortSymbolicName, &attrs.PortSymbolicName, 256); 655fcf3ce44SJohn Forte 656fcf3ce44SJohn Forte 657fcf3ce44SJohn Forte return (attributes); 658fcf3ce44SJohn Forte } 659fcf3ce44SJohn Forte 660fcf3ce44SJohn Forte HBA_PORTATTRIBUTES FCHBAPort::getDiscoveredAttributes( 661fcf3ce44SJohn Forte uint64_t wwn, uint64_t &stateChange) { 662fcf3ce44SJohn Forte Trace log("FCHBAPort::getDiscoverdAttributes(p)"); 663fcf3ce44SJohn Forte 664fcf3ce44SJohn Forte HBA_PORTATTRIBUTES attributes; 665fcf3ce44SJohn Forte fcio_t fcio; 666fcf3ce44SJohn Forte fc_hba_port_attributes_t attrs; 667fcf3ce44SJohn Forte la_wwn_t lawwn; 668fcf3ce44SJohn Forte 669fcf3ce44SJohn Forte memset(&fcio, 0, sizeof (fcio)); 670fcf3ce44SJohn Forte memset(&attributes, 0, sizeof (attributes)); 671fcf3ce44SJohn Forte 672fcf3ce44SJohn Forte uint64_t en_wwn = htonll(wwn); 673fcf3ce44SJohn Forte memcpy(&lawwn, &en_wwn, sizeof (en_wwn)); 674fcf3ce44SJohn Forte 675fcf3ce44SJohn Forte fcio.fcio_cmd = FCIO_GET_PORT_ATTRIBUTES; 676fcf3ce44SJohn Forte fcio.fcio_olen = sizeof (attrs); 677fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_READ; 678fcf3ce44SJohn Forte fcio.fcio_obuf = (caddr_t)&attrs; 679fcf3ce44SJohn Forte fcio.fcio_ilen = sizeof (wwn); 680fcf3ce44SJohn Forte fcio.fcio_ibuf = (caddr_t)&lawwn; 681fcf3ce44SJohn Forte 682fcf3ce44SJohn Forte fp_ioctl(getPath(), FCIO_CMD, &fcio); 683fcf3ce44SJohn Forte 684fcf3ce44SJohn Forte stateChange = attrs.lastChange; 685fcf3ce44SJohn Forte 686fcf3ce44SJohn Forte attributes.PortFcId = attrs.PortFcId; 687fcf3ce44SJohn Forte attributes.PortType = attrs.PortType; 688fcf3ce44SJohn Forte attributes.PortState = attrs.PortState; 689fcf3ce44SJohn Forte attributes.PortSupportedClassofService = attrs.PortSupportedClassofService; 690fcf3ce44SJohn Forte attributes.PortSupportedSpeed = attrs.PortSupportedSpeed; 691fcf3ce44SJohn Forte attributes.PortSpeed = attrs.PortSpeed; 692fcf3ce44SJohn Forte attributes.PortMaxFrameSize = attrs.PortMaxFrameSize; 693fcf3ce44SJohn Forte attributes.NumberofDiscoveredPorts = attrs.NumberofDiscoveredPorts; 694fcf3ce44SJohn Forte memcpy(&attributes.NodeWWN, &attrs.NodeWWN, 8); 695fcf3ce44SJohn Forte memcpy(&attributes.PortWWN, &attrs.PortWWN, 8); 696fcf3ce44SJohn Forte memcpy(&attributes.FabricName, &attrs.FabricName, 8); 697fcf3ce44SJohn Forte memcpy(&attributes.PortSupportedFc4Types, &attrs.PortSupportedFc4Types, 32); 698fcf3ce44SJohn Forte memcpy(&attributes.PortActiveFc4Types, &attrs.PortActiveFc4Types, 32); 699fcf3ce44SJohn Forte memcpy(&attributes.PortSymbolicName, &attrs.PortSymbolicName, 256); 700fcf3ce44SJohn Forte 701fcf3ce44SJohn Forte 702fcf3ce44SJohn Forte return (attributes); 703fcf3ce44SJohn Forte } 704fcf3ce44SJohn Forte 705fcf3ce44SJohn Forte 706fcf3ce44SJohn Forte void FCHBAPort::getTargetMappings(PHBA_FCPTARGETMAPPINGV2 userMappings) { 707fcf3ce44SJohn Forte Trace log("FCHBAPort::getTargetMappings"); 708fcf3ce44SJohn Forte int i, index; 709fcf3ce44SJohn Forte uint_t total_entries = 0; 710fcf3ce44SJohn Forte 711fcf3ce44SJohn Forte struct fcp_ioctl fioctl; 712fcf3ce44SJohn Forte fc_hba_target_mappings_t *mappings; 713fcf3ce44SJohn Forte int fd; 714fcf3ce44SJohn Forte bool zeroLength = false; 715fcf3ce44SJohn Forte 716fcf3ce44SJohn Forte 717fcf3ce44SJohn Forte if (userMappings == NULL) { 718fcf3ce44SJohn Forte log.userError("Null mapping argument "); 719fcf3ce44SJohn Forte throw BadArgumentException(); 720fcf3ce44SJohn Forte } 721fcf3ce44SJohn Forte 722fcf3ce44SJohn Forte /* It's possible they didn't give any space */ 723fcf3ce44SJohn Forte if (userMappings->NumberOfEntries == 0) { 724fcf3ce44SJohn Forte zeroLength = true; 725fcf3ce44SJohn Forte userMappings->NumberOfEntries = 1; 726fcf3ce44SJohn Forte /* We have to give the driver at least one space */ 727fcf3ce44SJohn Forte } 728fcf3ce44SJohn Forte 729fcf3ce44SJohn Forte mappings = (fc_hba_target_mappings_t *)new uchar_t[ 730fcf3ce44SJohn Forte (sizeof (fc_hba_mapping_entry_t)) * 731fcf3ce44SJohn Forte (userMappings->NumberOfEntries - 1) + 732fcf3ce44SJohn Forte sizeof (fc_hba_target_mappings_t)]; 733fcf3ce44SJohn Forte if (mappings == NULL) { 734fcf3ce44SJohn Forte log.noMemory(); 735fcf3ce44SJohn Forte throw InternalError(); 736fcf3ce44SJohn Forte } 737fcf3ce44SJohn Forte 738fcf3ce44SJohn Forte 739fcf3ce44SJohn Forte fioctl.fp_minor = instanceNumber; 740fcf3ce44SJohn Forte fioctl.listlen = ((uint32_t) (sizeof (fc_hba_mapping_entry_t))) * 741fcf3ce44SJohn Forte (userMappings->NumberOfEntries - 1) + 742fcf3ce44SJohn Forte (uint32_t) sizeof (fc_hba_target_mappings_t); 743fcf3ce44SJohn Forte fioctl.list = (caddr_t)mappings; 744fcf3ce44SJohn Forte 745fcf3ce44SJohn Forte fd = HBA::_open(FCP_DRIVER_PATH, O_RDONLY | O_NDELAY); 746fcf3ce44SJohn Forte 747fcf3ce44SJohn Forte log.debug("Performing IOCTL to fetch mappings"); 748fcf3ce44SJohn Forte 749fcf3ce44SJohn Forte if (ioctl(fd, FCP_GET_TARGET_MAPPINGS, &fioctl) != 0) { 750fcf3ce44SJohn Forte delete (mappings); 751fcf3ce44SJohn Forte close(fd); 752fcf3ce44SJohn Forte if (errno == EBUSY) { 753fcf3ce44SJohn Forte throw BusyException(); 754fcf3ce44SJohn Forte } else if (errno == EAGAIN) { 755fcf3ce44SJohn Forte throw TryAgainException(); 756fcf3ce44SJohn Forte } else if (errno == ENOTSUP) { 757fcf3ce44SJohn Forte throw NotSupportedException(); 758fcf3ce44SJohn Forte } else if (errno == ENOENT) { 759fcf3ce44SJohn Forte throw UnavailableException(); 760fcf3ce44SJohn Forte } else { 761fcf3ce44SJohn Forte throw IOError("Unable to fetch target mappings"); 762fcf3ce44SJohn Forte } 763fcf3ce44SJohn Forte } 764fcf3ce44SJohn Forte 765fcf3ce44SJohn Forte close(fd); 766fcf3ce44SJohn Forte // Quickly iterate through and copy the data over to the client 767fcf3ce44SJohn Forte for (i = 0; i < userMappings->NumberOfEntries && !zeroLength && 768fcf3ce44SJohn Forte i < mappings->numLuns; i++) { 769fcf3ce44SJohn Forte string raw = mappings->entries[i].targetDriver; 770fcf3ce44SJohn Forte 771fcf3ce44SJohn Forte 772fcf3ce44SJohn Forte if (raw.length() <= 0) { 773fcf3ce44SJohn Forte log.internalError("Bad target mapping without path, truncating."); 774fcf3ce44SJohn Forte break; 775fcf3ce44SJohn Forte } 776fcf3ce44SJohn Forte /* 777fcf3ce44SJohn Forte * Ideally, we'd like to ask some standard Solaris interface 778fcf3ce44SJohn Forte * "What is the prefered minor node for this target?" 779fcf3ce44SJohn Forte * but no such interface exists today. So, for now, 780fcf3ce44SJohn Forte * we just hard-code ":n" for tapes, ":c,raw" for disks, 781fcf3ce44SJohn Forte * and ":0" for enclosures. 782fcf3ce44SJohn Forte * Devices with other generic names will be presented through 783fcf3ce44SJohn Forte * first matching /dev path. 784fcf3ce44SJohn Forte */ 785fcf3ce44SJohn Forte if ((raw.find("/st@") != raw.npos) || 786fcf3ce44SJohn Forte (raw.find("/tape@") != raw.npos)) { 787fcf3ce44SJohn Forte raw += ":n"; 788fcf3ce44SJohn Forte } else if ((raw.find("/ssd@") != raw.npos) || 789fcf3ce44SJohn Forte (raw.find("/sd@") != raw.npos) || 790fcf3ce44SJohn Forte (raw.find("/disk@") != raw.npos)) { 791fcf3ce44SJohn Forte raw += ":c,raw"; 792fcf3ce44SJohn Forte } else if ((raw.find("/ses@") != raw.npos) || 793fcf3ce44SJohn Forte (raw.find("/enclosure@") != raw.npos)) { 794fcf3ce44SJohn Forte raw += ":0"; 795fcf3ce44SJohn Forte } else { 796fcf3ce44SJohn Forte log.debug( 797fcf3ce44SJohn Forte "Unrecognized target driver (%s), using first matching /dev path", 798fcf3ce44SJohn Forte raw.c_str()); 799fcf3ce44SJohn Forte } 800fcf3ce44SJohn Forte snprintf(userMappings->entry[i].ScsiId.OSDeviceName, 801fcf3ce44SJohn Forte sizeof (userMappings->entry[i].ScsiId.OSDeviceName), 802fcf3ce44SJohn Forte "/devices%s", raw.c_str()); 803fcf3ce44SJohn Forte userMappings->entry[i].ScsiId.ScsiBusNumber = 804fcf3ce44SJohn Forte controllerNumber; 805fcf3ce44SJohn Forte userMappings->entry[i].ScsiId.ScsiTargetNumber = 806fcf3ce44SJohn Forte mappings->entries[i].targetNumber; 807fcf3ce44SJohn Forte userMappings->entry[i].ScsiId.ScsiOSLun = 808fcf3ce44SJohn Forte mappings->entries[i].osLUN; 809fcf3ce44SJohn Forte userMappings->entry[i].FcpId.FcId = 810fcf3ce44SJohn Forte mappings->entries[i].d_id; 811fcf3ce44SJohn Forte memcpy(userMappings->entry[i].FcpId.NodeWWN.wwn, 812fcf3ce44SJohn Forte mappings->entries[i].NodeWWN.raw_wwn, 813fcf3ce44SJohn Forte sizeof (la_wwn_t)); 814fcf3ce44SJohn Forte memcpy(userMappings->entry[i].FcpId.PortWWN.wwn, 815fcf3ce44SJohn Forte mappings->entries[i].PortWWN.raw_wwn, 816fcf3ce44SJohn Forte sizeof (la_wwn_t)); 817fcf3ce44SJohn Forte 818fcf3ce44SJohn Forte userMappings->entry[i].FcpId.FcpLun = 819fcf3ce44SJohn Forte mappings->entries[i].samLUN; 820fcf3ce44SJohn Forte 821fcf3ce44SJohn Forte memcpy(userMappings->entry[i].LUID.buffer, 822fcf3ce44SJohn Forte mappings->entries[i].guid, 823fcf3ce44SJohn Forte sizeof (userMappings->entry[i].LUID.buffer)); 824fcf3ce44SJohn Forte } 825fcf3ce44SJohn Forte 826fcf3ce44SJohn Forte log.debug("Total mappings: %d %08x %08x", 827fcf3ce44SJohn Forte mappings->numLuns, mappings->entries[i].osLUN, mappings->entries[i].samLUN); 828fcf3ce44SJohn Forte 829fcf3ce44SJohn Forte // If everything is good, convert paths to sym-links 830fcf3ce44SJohn Forte if (mappings->numLuns > 0 && !zeroLength) { 831fcf3ce44SJohn Forte if (userMappings->NumberOfEntries >= mappings->numLuns) { 832fcf3ce44SJohn Forte // User buffer is larger than needed. (All is good) 833fcf3ce44SJohn Forte userMappings->NumberOfEntries = mappings->numLuns; 834fcf3ce44SJohn Forte convertToShortNames(userMappings); 835fcf3ce44SJohn Forte } else { 836fcf3ce44SJohn Forte // User buffer is non zero, but too small. Don't bother with links 837fcf3ce44SJohn Forte userMappings->NumberOfEntries = mappings->numLuns; 838fcf3ce44SJohn Forte delete (mappings); 839fcf3ce44SJohn Forte throw MoreDataException(); 840fcf3ce44SJohn Forte } 841fcf3ce44SJohn Forte } else if (mappings->numLuns > 0) { 842fcf3ce44SJohn Forte // Zero length buffer, but we've got mappings 843fcf3ce44SJohn Forte userMappings->NumberOfEntries = mappings->numLuns; 844fcf3ce44SJohn Forte delete (mappings); 845fcf3ce44SJohn Forte throw MoreDataException(); 846fcf3ce44SJohn Forte } else { 847fcf3ce44SJohn Forte // No mappings, no worries 848fcf3ce44SJohn Forte userMappings->NumberOfEntries = 0; 849fcf3ce44SJohn Forte delete (mappings); 850fcf3ce44SJohn Forte return; 851fcf3ce44SJohn Forte } 852fcf3ce44SJohn Forte delete (mappings); 853fcf3ce44SJohn Forte } 854fcf3ce44SJohn Forte 855fcf3ce44SJohn Forte void FCHBAPort::getRNIDMgmtInfo(PHBA_MGMTINFO info) { 856fcf3ce44SJohn Forte Trace log("FCHBAPort::getRNIDMgmtInfo"); 857fcf3ce44SJohn Forte HBA_STATUS status = HBA_STATUS_OK; 858fcf3ce44SJohn Forte fc_rnid_t rnid; 859fcf3ce44SJohn Forte fcio_t fcio; 860fcf3ce44SJohn Forte 861fcf3ce44SJohn Forte 862fcf3ce44SJohn Forte if (info == NULL) { 863fcf3ce44SJohn Forte log.userError("NULL port management info"); 864fcf3ce44SJohn Forte throw BadArgumentException(); 865fcf3ce44SJohn Forte } 866fcf3ce44SJohn Forte 867fcf3ce44SJohn Forte // Get the RNID information from the first port 868fcf3ce44SJohn Forte memset(&rnid, 0, sizeof (fc_rnid_t)); 869fcf3ce44SJohn Forte memset((caddr_t)&fcio, 0, sizeof (fcio)); 870fcf3ce44SJohn Forte 871fcf3ce44SJohn Forte fcio.fcio_cmd = FCIO_GET_NODE_ID; 872fcf3ce44SJohn Forte fcio.fcio_olen = sizeof (fc_rnid_t); 873fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_READ; 874fcf3ce44SJohn Forte fcio.fcio_obuf = (caddr_t)&rnid; 875fcf3ce44SJohn Forte fp_ioctl(getPath(), FCIO_CMD, &fcio); 876fcf3ce44SJohn Forte 877fcf3ce44SJohn Forte // Copy out the struct members of rnid into PHBA_MGMTINFO struct 878fcf3ce44SJohn Forte memcpy(&info->wwn, &(rnid.global_id), sizeof (info->wwn)); 879fcf3ce44SJohn Forte memcpy(&info->unittype, &(rnid.unit_type), sizeof (info->unittype)); 880fcf3ce44SJohn Forte memcpy(&info->PortId, &(rnid.port_id), sizeof (info->PortId)); 881fcf3ce44SJohn Forte memcpy(&info->NumberOfAttachedNodes, &(rnid.num_attached), 882fcf3ce44SJohn Forte sizeof (info->NumberOfAttachedNodes)); 883fcf3ce44SJohn Forte memcpy(&info->IPVersion, &(rnid.ip_version), sizeof (info->IPVersion)); 884fcf3ce44SJohn Forte memcpy(&info->UDPPort, &(rnid.udp_port), sizeof (info->UDPPort)); 885fcf3ce44SJohn Forte memcpy(&info->IPAddress, &(rnid.ip_addr), sizeof (info->IPAddress)); 886fcf3ce44SJohn Forte memcpy(&info->TopologyDiscoveryFlags, &(rnid.topo_flags), 887fcf3ce44SJohn Forte sizeof (info->TopologyDiscoveryFlags)); 888fcf3ce44SJohn Forte } 889fcf3ce44SJohn Forte 890fcf3ce44SJohn Forte void FCHBAPort::sendCTPassThru(void *requestBuffer, HBA_UINT32 requestSize, 891fcf3ce44SJohn Forte void *responseBuffer, HBA_UINT32 *responseSize) { 892fcf3ce44SJohn Forte Trace log("FCHBAPort::sendCTPassThru"); 893fcf3ce44SJohn Forte fcio_t fcio; 894fcf3ce44SJohn Forte struct stat sbuf; 895fcf3ce44SJohn Forte minor_t minor_node; 896fcf3ce44SJohn Forte hrtime_t start, end; 897fcf3ce44SJohn Forte double duration; 898fcf3ce44SJohn Forte 899fcf3ce44SJohn Forte // Validate the arguments 900fcf3ce44SJohn Forte if (requestBuffer == NULL) { 901fcf3ce44SJohn Forte log.userError("NULL request buffer"); 902fcf3ce44SJohn Forte throw BadArgumentException(); 903fcf3ce44SJohn Forte } 904fcf3ce44SJohn Forte if (responseBuffer == NULL) { 905fcf3ce44SJohn Forte log.userError("NULL response buffer"); 906fcf3ce44SJohn Forte throw BadArgumentException(); 907fcf3ce44SJohn Forte } 908fcf3ce44SJohn Forte 909fcf3ce44SJohn Forte minor_node = instanceNumber; 910fcf3ce44SJohn Forte 911fcf3ce44SJohn Forte // construct fcio struct 912fcf3ce44SJohn Forte memset(&fcio, 0, sizeof (fcio_t)); 913fcf3ce44SJohn Forte fcio.fcio_cmd = FCSMIO_CT_CMD; 914fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_RW; 915fcf3ce44SJohn Forte 916fcf3ce44SJohn Forte fcio.fcio_ilen = requestSize; 917fcf3ce44SJohn Forte fcio.fcio_ibuf = (char *)requestBuffer; 918fcf3ce44SJohn Forte fcio.fcio_olen = *responseSize; 919fcf3ce44SJohn Forte fcio.fcio_obuf = (char *)responseBuffer; 920fcf3ce44SJohn Forte 921fcf3ce44SJohn Forte fcio.fcio_alen = sizeof (minor_t); 922fcf3ce44SJohn Forte fcio.fcio_abuf = (char *)&minor_node; 923fcf3ce44SJohn Forte 924fcf3ce44SJohn Forte 925fcf3ce44SJohn Forte start = gethrtime(); 926fcf3ce44SJohn Forte fcsm_ioctl(FCSMIO_CMD, &fcio); 927fcf3ce44SJohn Forte 928fcf3ce44SJohn Forte // Do some calculations on the duration of the ioctl. 929fcf3ce44SJohn Forte end = gethrtime(); 930fcf3ce44SJohn Forte duration = end - start; 931fcf3ce44SJohn Forte duration /= HR_SECOND; 932fcf3ce44SJohn Forte log.debug( 933fcf3ce44SJohn Forte "Total CTPASS ioctl call for HBA %s was %.4f seconds", 934fcf3ce44SJohn Forte getPath().c_str(), duration); 935fcf3ce44SJohn Forte } 936fcf3ce44SJohn Forte 937fcf3ce44SJohn Forte void FCHBAPort::sendRLS(uint64_t destWWN, 938fcf3ce44SJohn Forte void *pRspBuffer, 939fcf3ce44SJohn Forte HBA_UINT32 *pRspBufferSize) { 940fcf3ce44SJohn Forte Trace log("FCHBAPort::sendRLS"); 941fcf3ce44SJohn Forte 942fcf3ce44SJohn Forte fcio_t fcio; 943fcf3ce44SJohn Forte fc_portid_t rls_req; 944fcf3ce44SJohn Forte 945fcf3ce44SJohn Forte 946fcf3ce44SJohn Forte // Validate the arguments 947fcf3ce44SJohn Forte if (pRspBuffer == NULL || 948fcf3ce44SJohn Forte pRspBufferSize == NULL) { 949fcf3ce44SJohn Forte log.userError("NULL hba"); 950fcf3ce44SJohn Forte throw BadArgumentException(); 951fcf3ce44SJohn Forte } 952fcf3ce44SJohn Forte 953fcf3ce44SJohn Forte // check to see if we are sending RLS to the HBA 954fcf3ce44SJohn Forte HBA_PORTATTRIBUTES attrs; 955fcf3ce44SJohn Forte uint64_t tmp; 956fcf3ce44SJohn Forte if (getPortWWN() == destWWN) { 957fcf3ce44SJohn Forte attrs = getPortAttributes(tmp); 958fcf3ce44SJohn Forte } else { 959fcf3ce44SJohn Forte attrs = getDiscoveredAttributes(destWWN, tmp); 960fcf3ce44SJohn Forte } 961fcf3ce44SJohn Forte 962fcf3ce44SJohn Forte memcpy(&rls_req, &attrs.PortFcId, 963fcf3ce44SJohn Forte sizeof (attrs.PortFcId)); 964fcf3ce44SJohn Forte 965fcf3ce44SJohn Forte memset((caddr_t)&fcio, 0, sizeof (fcio)); 966fcf3ce44SJohn Forte fcio.fcio_cmd = FCIO_LINK_STATUS; 967fcf3ce44SJohn Forte fcio.fcio_ibuf = (caddr_t)&rls_req; 968fcf3ce44SJohn Forte fcio.fcio_ilen = sizeof (rls_req); 969fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_RW; 970fcf3ce44SJohn Forte fcio.fcio_flags = 0; 971fcf3ce44SJohn Forte fcio.fcio_cmd_flags = FCIO_CFLAGS_RLS_DEST_NPORT; 972fcf3ce44SJohn Forte fcio.fcio_obuf = (char *)new uchar_t[*pRspBufferSize]; 973fcf3ce44SJohn Forte fcio.fcio_olen = *pRspBufferSize; 974fcf3ce44SJohn Forte 975fcf3ce44SJohn Forte if (fcio.fcio_obuf == NULL) { 976fcf3ce44SJohn Forte log.noMemory(); 977fcf3ce44SJohn Forte throw InternalError(); 978fcf3ce44SJohn Forte } 979fcf3ce44SJohn Forte 980fcf3ce44SJohn Forte fp_ioctl(getPath(), FCIO_CMD, &fcio); 981fcf3ce44SJohn Forte memcpy(pRspBuffer, fcio.fcio_obuf, *pRspBufferSize); 982fcf3ce44SJohn Forte if (fcio.fcio_obuf != NULL) { 983fcf3ce44SJohn Forte delete(fcio.fcio_obuf); 984fcf3ce44SJohn Forte } 985fcf3ce44SJohn Forte } 986fcf3ce44SJohn Forte 987fcf3ce44SJohn Forte void FCHBAPort::sendReportLUNs(uint64_t wwn, 988fcf3ce44SJohn Forte void *responseBuffer, HBA_UINT32 *responseSize, 989fcf3ce44SJohn Forte HBA_UINT8 *scsiStatus, 990fcf3ce44SJohn Forte void *senseBuffer, HBA_UINT32 *senseSize) { 991fcf3ce44SJohn Forte Trace log("FCHBAPort::sendReportLUNs"); 992fcf3ce44SJohn Forte struct fcp_scsi_cmd fscsi; 993fcf3ce44SJohn Forte union scsi_cdb scsi_rl_req; 994fcf3ce44SJohn Forte uint64_t targetWwn = htonll(wwn); 995fcf3ce44SJohn Forte 996fcf3ce44SJohn Forte // Validate the arguments 997fcf3ce44SJohn Forte if (responseBuffer == NULL || 998fcf3ce44SJohn Forte senseBuffer == NULL || 999fcf3ce44SJohn Forte responseSize == NULL || 1000fcf3ce44SJohn Forte senseSize == NULL) { 1001fcf3ce44SJohn Forte throw BadArgumentException(); 1002fcf3ce44SJohn Forte } 1003fcf3ce44SJohn Forte 1004fcf3ce44SJohn Forte memset(&fscsi, 0, sizeof (fscsi)); 1005fcf3ce44SJohn Forte memset(&scsi_rl_req, 0, sizeof (scsi_rl_req)); 1006fcf3ce44SJohn Forte memcpy(fscsi.scsi_fc_pwwn.raw_wwn, &targetWwn, sizeof (la_wwn_t)); 1007fcf3ce44SJohn Forte 1008fcf3ce44SJohn Forte scsi_cmd_init(&fscsi, getPath().c_str(), &scsi_rl_req, 1009fcf3ce44SJohn Forte sizeof (scsi_rl_req), responseBuffer, *responseSize, 1010fcf3ce44SJohn Forte senseBuffer, *senseSize); 1011fcf3ce44SJohn Forte 1012fcf3ce44SJohn Forte fscsi.scsi_lun = 0; 1013fcf3ce44SJohn Forte scsi_rl_req.scc_cmd = SCMD_REPORT_LUNS; 1014fcf3ce44SJohn Forte FORMG5COUNT(&scsi_rl_req, *responseSize); 1015fcf3ce44SJohn Forte sendSCSIPassThru(&fscsi, responseSize, senseSize, scsiStatus); 1016fcf3ce44SJohn Forte } 1017fcf3ce44SJohn Forte 1018fcf3ce44SJohn Forte /* 1019fcf3ce44SJohn Forte * arguments: 1020fcf3ce44SJohn Forte * wwn - remote target WWN where the SCSI Inquiry shall be sent 1021fcf3ce44SJohn Forte * fcLun - the SCSI LUN to which the SCSI Inquiry shall be sent 1022fcf3ce44SJohn Forte * cdb1 - the second byte of the CDB for the SCSI Inquiry 1023fcf3ce44SJohn Forte * cdb2 - the third byte of teh CDB for the SCSI Inquiry 1024fcf3ce44SJohn Forte * responseBuffer - shall be a pointer to a buffer to receive the SCSI 1025fcf3ce44SJohn Forte * Inquiry command response 1026fcf3ce44SJohn Forte * responseSize - a pointer to the size of the buffer to receive 1027fcf3ce44SJohn Forte * the SCSI Inquiry. 1028fcf3ce44SJohn Forte * scsiStatus - a pointer to a buffer to receive SCSI status 1029fcf3ce44SJohn Forte * senseBuffer - pointer to a buffer to receive SCSI sense data 1030fcf3ce44SJohn Forte * seneseSize - pointer to the size of the buffer to receive SCSI sense 1031fcf3ce44SJohn Forte * data 1032fcf3ce44SJohn Forte */ 1033fcf3ce44SJohn Forte void FCHBAPort::sendScsiInquiry(uint64_t wwn, HBA_UINT64 fcLun, 1034fcf3ce44SJohn Forte HBA_UINT8 cdb1, HBA_UINT8 cdb2, void *responseBuffer, 1035fcf3ce44SJohn Forte HBA_UINT32 *responseSize, HBA_UINT8 *scsiStatus, void *senseBuffer, 1036fcf3ce44SJohn Forte HBA_UINT32 *senseSize) { 1037fcf3ce44SJohn Forte Trace log("FCHBAPort::sendScsiInquiry"); 1038fcf3ce44SJohn Forte 1039fcf3ce44SJohn Forte struct fcp_scsi_cmd fscsi; 1040fcf3ce44SJohn Forte union scsi_cdb scsi_inq_req; 1041fcf3ce44SJohn Forte uint64_t targetWwn = htonll(wwn); 1042fcf3ce44SJohn Forte 1043fcf3ce44SJohn Forte // Validate the arguments 1044fcf3ce44SJohn Forte if (responseBuffer == NULL || 1045fcf3ce44SJohn Forte senseBuffer == NULL || 1046fcf3ce44SJohn Forte responseSize == NULL || 1047fcf3ce44SJohn Forte senseSize == NULL) { 1048fcf3ce44SJohn Forte throw BadArgumentException(); 1049fcf3ce44SJohn Forte } 1050fcf3ce44SJohn Forte 1051fcf3ce44SJohn Forte memset(&fscsi, 0, sizeof (fscsi)); 1052fcf3ce44SJohn Forte memset(&scsi_inq_req, 0, sizeof (scsi_inq_req)); 1053fcf3ce44SJohn Forte memcpy(fscsi.scsi_fc_pwwn.raw_wwn, &targetWwn, sizeof (la_wwn_t)); 1054fcf3ce44SJohn Forte 1055fcf3ce44SJohn Forte 1056fcf3ce44SJohn Forte scsi_cmd_init(&fscsi, getPath().c_str(), &scsi_inq_req, 1057fcf3ce44SJohn Forte sizeof (scsi_inq_req), responseBuffer, *responseSize, 1058fcf3ce44SJohn Forte senseBuffer, *senseSize); 1059fcf3ce44SJohn Forte fscsi.scsi_lun = fcLun; 1060fcf3ce44SJohn Forte 1061fcf3ce44SJohn Forte scsi_inq_req.scc_cmd = SCMD_INQUIRY; 1062fcf3ce44SJohn Forte scsi_inq_req.g0_addr1 = cdb2; 1063fcf3ce44SJohn Forte scsi_inq_req.g0_addr2 = cdb1; 1064fcf3ce44SJohn Forte scsi_inq_req.g0_count0 = *responseSize; 1065fcf3ce44SJohn Forte 1066fcf3ce44SJohn Forte 1067fcf3ce44SJohn Forte sendSCSIPassThru(&fscsi, responseSize, senseSize, scsiStatus); 1068fcf3ce44SJohn Forte } 1069fcf3ce44SJohn Forte 1070fcf3ce44SJohn Forte 1071fcf3ce44SJohn Forte void FCHBAPort::sendReadCapacity(uint64_t pwwn, 1072fcf3ce44SJohn Forte HBA_UINT64 fcLun, void *responseBuffer, 1073fcf3ce44SJohn Forte HBA_UINT32 *responseSize, HBA_UINT8 *scsiStatus, 1074fcf3ce44SJohn Forte void *senseBuffer, HBA_UINT32 *senseSize) { 1075fcf3ce44SJohn Forte Trace log("FCHBAPort::sendReadCapacity"); 1076fcf3ce44SJohn Forte 1077fcf3ce44SJohn Forte struct fcp_scsi_cmd fscsi; 1078fcf3ce44SJohn Forte union scsi_cdb scsi_rc_req; 1079fcf3ce44SJohn Forte uint64_t targetWwn = htonll(pwwn); 1080fcf3ce44SJohn Forte 1081fcf3ce44SJohn Forte // Validate the arguments 1082fcf3ce44SJohn Forte if (responseBuffer == NULL || 1083fcf3ce44SJohn Forte senseBuffer == NULL || 1084fcf3ce44SJohn Forte responseSize == NULL || 1085fcf3ce44SJohn Forte senseSize == NULL || 1086fcf3ce44SJohn Forte scsiStatus == NULL) { 1087fcf3ce44SJohn Forte throw BadArgumentException(); 1088fcf3ce44SJohn Forte } 1089fcf3ce44SJohn Forte 1090fcf3ce44SJohn Forte memset(&fscsi, 0, sizeof (fscsi)); 1091fcf3ce44SJohn Forte memset(&scsi_rc_req, 0, sizeof (scsi_rc_req)); 1092fcf3ce44SJohn Forte 1093fcf3ce44SJohn Forte scsi_cmd_init(&fscsi, getPath().c_str(), &scsi_rc_req, 1094fcf3ce44SJohn Forte sizeof (scsi_rc_req), responseBuffer, *responseSize, 1095fcf3ce44SJohn Forte senseBuffer, *senseSize); 1096fcf3ce44SJohn Forte 1097fcf3ce44SJohn Forte memcpy(fscsi.scsi_fc_pwwn.raw_wwn, &targetWwn, sizeof (la_wwn_t)); 1098fcf3ce44SJohn Forte fscsi.scsi_lun = fcLun; 1099fcf3ce44SJohn Forte 1100fcf3ce44SJohn Forte scsi_rc_req.scc_cmd = SCMD_READ_CAPACITY; 1101fcf3ce44SJohn Forte scsi_rc_req.g1_reladdr = 0; 1102fcf3ce44SJohn Forte 1103fcf3ce44SJohn Forte scsi_rc_req.g1_addr3 = 0; 1104fcf3ce44SJohn Forte scsi_rc_req.g1_count0 = 0; 1105fcf3ce44SJohn Forte 1106fcf3ce44SJohn Forte sendSCSIPassThru(&fscsi, responseSize, senseSize, scsiStatus); 1107fcf3ce44SJohn Forte } 1108fcf3ce44SJohn Forte 1109fcf3ce44SJohn Forte void FCHBAPort::sendRNID(uint64_t destwwn, HBA_UINT32 destfcid, 1110fcf3ce44SJohn Forte HBA_UINT32 nodeIdDataFormat, void *pRspBuffer, 1111fcf3ce44SJohn Forte HBA_UINT32 *RspBufferSize) { 1112fcf3ce44SJohn Forte Trace log("FCHBAPort::sendRNID"); 1113fcf3ce44SJohn Forte int localportfound, remoteportfound, send; 1114fcf3ce44SJohn Forte fcio_t fcio; 1115fcf3ce44SJohn Forte 1116fcf3ce44SJohn Forte // Validate the arguments 1117fcf3ce44SJohn Forte if (pRspBuffer == NULL || 1118fcf3ce44SJohn Forte RspBufferSize == NULL) { 1119fcf3ce44SJohn Forte throw BadArgumentException(); 1120fcf3ce44SJohn Forte } 1121fcf3ce44SJohn Forte // NodeIdDataFormat must be within the range of 0x00 and 0xff 1122fcf3ce44SJohn Forte if (nodeIdDataFormat > 0xff) { 1123fcf3ce44SJohn Forte log.userError( 1124fcf3ce44SJohn Forte "NodeIdDataFormat must be within the range of 0x00 " 1125fcf3ce44SJohn Forte "and 0xFF"); 1126fcf3ce44SJohn Forte throw BadArgumentException(); 1127fcf3ce44SJohn Forte } 1128fcf3ce44SJohn Forte 1129fcf3ce44SJohn Forte 1130fcf3ce44SJohn Forte remoteportfound = 0; 1131fcf3ce44SJohn Forte if (destfcid != 0) { 1132fcf3ce44SJohn Forte try { 1133fcf3ce44SJohn Forte uint64_t tmp; 1134fcf3ce44SJohn Forte HBA_PORTATTRIBUTES attrs = getDiscoveredAttributes(destwwn, 1135fcf3ce44SJohn Forte tmp); 1136fcf3ce44SJohn Forte if (attrs.PortFcId == destfcid) { 1137fcf3ce44SJohn Forte send = 1; 1138fcf3ce44SJohn Forte remoteportfound = 1; 1139fcf3ce44SJohn Forte } else { 1140fcf3ce44SJohn Forte send = 0; 1141fcf3ce44SJohn Forte remoteportfound = 1; 1142fcf3ce44SJohn Forte } 1143fcf3ce44SJohn Forte } catch (HBAException &e) { 1144fcf3ce44SJohn Forte /* 1145fcf3ce44SJohn Forte * Send RNID if destination port not 1146fcf3ce44SJohn Forte * present in the discovered ports table 1147fcf3ce44SJohn Forte */ 1148fcf3ce44SJohn Forte } 1149fcf3ce44SJohn Forte if (remoteportfound == 0) { 1150fcf3ce44SJohn Forte send = 1; 1151fcf3ce44SJohn Forte } 1152fcf3ce44SJohn Forte } else { 1153fcf3ce44SJohn Forte send = 1; 1154fcf3ce44SJohn Forte } 1155fcf3ce44SJohn Forte 1156fcf3ce44SJohn Forte if (!send) { 1157fcf3ce44SJohn Forte // Can we log something so we can figure out why? 1158fcf3ce44SJohn Forte throw BadArgumentException(); 1159fcf3ce44SJohn Forte } 1160fcf3ce44SJohn Forte 1161fcf3ce44SJohn Forte memset((caddr_t)&fcio, 0, sizeof (fcio)); 1162fcf3ce44SJohn Forte uint64_t netdestwwn = htonll(destwwn); 1163fcf3ce44SJohn Forte fcio.fcio_cmd = FCIO_SEND_NODE_ID; 1164fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_READ; 1165fcf3ce44SJohn Forte fcio.fcio_cmd_flags = nodeIdDataFormat; 1166fcf3ce44SJohn Forte fcio.fcio_ilen = sizeof (la_wwn_t); 1167fcf3ce44SJohn Forte fcio.fcio_ibuf = (caddr_t)&netdestwwn; 1168fcf3ce44SJohn Forte fcio.fcio_olen = *RspBufferSize; 1169fcf3ce44SJohn Forte fcio.fcio_obuf = (char *)new uchar_t[*RspBufferSize]; 1170fcf3ce44SJohn Forte 1171fcf3ce44SJohn Forte 1172fcf3ce44SJohn Forte if (fcio.fcio_obuf == NULL) { 1173fcf3ce44SJohn Forte log.noMemory(); 1174fcf3ce44SJohn Forte throw InternalError(); 1175fcf3ce44SJohn Forte } 1176fcf3ce44SJohn Forte 1177fcf3ce44SJohn Forte fp_ioctl(getPath(), FCIO_CMD, &fcio); 1178fcf3ce44SJohn Forte 1179fcf3ce44SJohn Forte memcpy(pRspBuffer, fcio.fcio_obuf, *RspBufferSize); 1180fcf3ce44SJohn Forte 1181fcf3ce44SJohn Forte if (fcio.fcio_obuf != NULL) { 1182fcf3ce44SJohn Forte delete(fcio.fcio_obuf); 1183fcf3ce44SJohn Forte } 1184fcf3ce44SJohn Forte } 1185fcf3ce44SJohn Forte 1186fcf3ce44SJohn Forte void FCHBAPort::setRNID(HBA_MGMTINFO info) { 1187fcf3ce44SJohn Forte Trace log("FCHBAPort::setRNID"); 1188fcf3ce44SJohn Forte fc_rnid_t rnid; 1189fcf3ce44SJohn Forte fcio_t fcio; 1190fcf3ce44SJohn Forte 1191fcf3ce44SJohn Forte memset(&rnid, 0, sizeof (fc_rnid_t)); 1192fcf3ce44SJohn Forte memset((caddr_t)&fcio, 0, sizeof (fcio)); 1193fcf3ce44SJohn Forte 1194fcf3ce44SJohn Forte 1195fcf3ce44SJohn Forte fcio.fcio_cmd = FCIO_SET_NODE_ID; 1196fcf3ce44SJohn Forte fcio.fcio_ilen = sizeof (fc_rnid_t); 1197fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_WRITE; 1198fcf3ce44SJohn Forte fcio.fcio_ibuf = (caddr_t)&rnid; 1199fcf3ce44SJohn Forte 1200fcf3ce44SJohn Forte 1201fcf3ce44SJohn Forte // Copy the HBA_MGMTINFO into fc_rnid_t struct 1202fcf3ce44SJohn Forte memcpy(&(rnid.unit_type), &(info.unittype), sizeof (rnid.unit_type)); 1203fcf3ce44SJohn Forte memcpy(&(rnid.port_id), &(info.PortId), sizeof (rnid.port_id)); 1204fcf3ce44SJohn Forte memcpy(&(rnid.global_id), &(info.wwn), sizeof (info.wwn)); 1205fcf3ce44SJohn Forte memcpy(&(rnid.num_attached), &(info.NumberOfAttachedNodes), 1206fcf3ce44SJohn Forte sizeof (rnid.num_attached)); 1207fcf3ce44SJohn Forte memcpy(&(rnid.ip_version), &(info.IPVersion), sizeof (rnid.ip_version)); 1208fcf3ce44SJohn Forte memcpy(&(rnid.udp_port), &(info.UDPPort), sizeof (rnid.udp_port)); 1209fcf3ce44SJohn Forte memcpy(&(rnid.ip_addr), &info.IPAddress, sizeof (rnid.ip_addr)); 1210fcf3ce44SJohn Forte memcpy(&(rnid.topo_flags), &(info.TopologyDiscoveryFlags), 1211fcf3ce44SJohn Forte sizeof (rnid.topo_flags)); 1212fcf3ce44SJohn Forte 1213fcf3ce44SJohn Forte fp_ioctl(getPath(), FCIO_CMD, &fcio, O_NDELAY | O_RDONLY | O_EXCL); 1214fcf3ce44SJohn Forte } 1215fcf3ce44SJohn Forte 1216fcf3ce44SJohn Forte void FCHBAPort::fp_ioctl(string path, int cmd, fcio_t *fcio, int openflag) { 1217fcf3ce44SJohn Forte Trace log("FCHBAPort::fp_ioctl with openflag"); 1218fcf3ce44SJohn Forte char fcioErrorString[MAX_FCIO_MSG_LEN] = ""; 1219fcf3ce44SJohn Forte int fd = HBA::_open(path, openflag); 1220fcf3ce44SJohn Forte try { 1221fcf3ce44SJohn Forte int times = 0; 1222fcf3ce44SJohn Forte HBA::_ioctl(fd, cmd, (uchar_t *)fcio); 1223fcf3ce44SJohn Forte while (fcio->fcio_errno == FC_STATEC_BUSY) { 1224fcf3ce44SJohn Forte sleep(1); 1225fcf3ce44SJohn Forte HBA::_ioctl(fd, cmd, (uchar_t *)fcio); 1226fcf3ce44SJohn Forte if (times++ > 10) { 1227fcf3ce44SJohn Forte break; 1228fcf3ce44SJohn Forte } 1229fcf3ce44SJohn Forte } 1230fcf3ce44SJohn Forte close(fd); 1231fcf3ce44SJohn Forte if (fcio->fcio_errno) { 1232fcf3ce44SJohn Forte throw IOError("IOCTL transport failure"); 1233fcf3ce44SJohn Forte } 1234fcf3ce44SJohn Forte } catch (...) { 1235fcf3ce44SJohn Forte close(fd); 1236fcf3ce44SJohn Forte transportError(fcio->fcio_errno, fcioErrorString); 1237fcf3ce44SJohn Forte log.genericIOError("ioctl (0x%x) failed. Transport: \"%s\"", cmd, 1238fcf3ce44SJohn Forte fcioErrorString); 1239fcf3ce44SJohn Forte switch (fcio->fcio_errno) { 1240fcf3ce44SJohn Forte case FC_BADWWN: 1241fcf3ce44SJohn Forte throw IllegalWWNException(); 1242fcf3ce44SJohn Forte case FC_BADPORT: 1243fcf3ce44SJohn Forte throw IllegalWWNException(); 1244fcf3ce44SJohn Forte case FC_OUTOFBOUNDS: 1245fcf3ce44SJohn Forte throw IllegalIndexException(); 1246fcf3ce44SJohn Forte case FC_PBUSY: 1247fcf3ce44SJohn Forte case FC_FBUSY: 1248fcf3ce44SJohn Forte case FC_TRAN_BUSY: 1249fcf3ce44SJohn Forte case FC_STATEC_BUSY: 1250fcf3ce44SJohn Forte case FC_DEVICE_BUSY: 1251fcf3ce44SJohn Forte throw BusyException(); 1252fcf3ce44SJohn Forte case FC_SUCCESS: 1253fcf3ce44SJohn Forte default: 1254fcf3ce44SJohn Forte throw; 1255fcf3ce44SJohn Forte } 1256fcf3ce44SJohn Forte } 1257fcf3ce44SJohn Forte } 1258fcf3ce44SJohn Forte 1259fcf3ce44SJohn Forte void FCHBAPort::fp_ioctl(string path, int cmd, fcio_t *fcio) { 1260fcf3ce44SJohn Forte Trace log("FCHBAPort::fp_ioctl"); 1261fcf3ce44SJohn Forte fp_ioctl(path, cmd, fcio, O_NDELAY | O_RDONLY); 1262fcf3ce44SJohn Forte } 1263fcf3ce44SJohn Forte 1264fcf3ce44SJohn Forte void FCHBAPort::fcsm_ioctl(int cmd, fcio_t *fcio) { 1265fcf3ce44SJohn Forte // We use the same error handling as fp, so just re-use 1266fcf3ce44SJohn Forte fp_ioctl(FCSM_DRIVER_PATH, cmd, fcio); 1267fcf3ce44SJohn Forte } 1268