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
transportError(uint32_t fcio_errno,char * message)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
reportSense(struct scsi_extended_sense * sense,const char * routine)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 */
sendSCSIPassThru(struct fcp_scsi_cmd * fscsi,HBA_UINT32 * responseSize,HBA_UINT32 * senseSize,HBA_UINT8 * scsiStatus)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
scsi_cmd_init(struct fcp_scsi_cmd * fscsi,const char * portname,void * reqbuf,size_t req_len,void * responseBuffer,size_t resp_len,void * senseBuffer,size_t sense_len)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
FCHBAPort(string thePath)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
deleteNPIVPort(uint64_t vportwwn)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
createNPIVPort(uint64_t vnodewwn,uint64_t vportwwn,uint32_t vindex)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
getPortNPIVAttributes(uint64_t & stateChange)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
getPortAttributes(uint64_t & stateChange)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
getDiscoveredAttributes(HBA_UINT32 discoveredport,uint64_t & stateChange)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
getDiscoveredAttributes(uint64_t wwn,uint64_t & stateChange)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
getTargetMappings(PHBA_FCPTARGETMAPPINGV2 userMappings)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
getRNIDMgmtInfo(PHBA_MGMTINFO info)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
sendCTPassThru(void * requestBuffer,HBA_UINT32 requestSize,void * responseBuffer,HBA_UINT32 * responseSize)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
sendRLS(uint64_t destWWN,void * pRspBuffer,HBA_UINT32 * pRspBufferSize)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
sendReportLUNs(uint64_t wwn,void * responseBuffer,HBA_UINT32 * responseSize,HBA_UINT8 * scsiStatus,void * senseBuffer,HBA_UINT32 * senseSize)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 */
sendScsiInquiry(uint64_t wwn,HBA_UINT64 fcLun,HBA_UINT8 cdb1,HBA_UINT8 cdb2,void * responseBuffer,HBA_UINT32 * responseSize,HBA_UINT8 * scsiStatus,void * senseBuffer,HBA_UINT32 * senseSize)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
sendReadCapacity(uint64_t pwwn,HBA_UINT64 fcLun,void * responseBuffer,HBA_UINT32 * responseSize,HBA_UINT8 * scsiStatus,void * senseBuffer,HBA_UINT32 * senseSize)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
sendRNID(uint64_t destwwn,HBA_UINT32 destfcid,HBA_UINT32 nodeIdDataFormat,void * pRspBuffer,HBA_UINT32 * RspBufferSize)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
setRNID(HBA_MGMTINFO info)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
fp_ioctl(string path,int cmd,fcio_t * fcio,int openflag)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
fp_ioctl(string path,int cmd,fcio_t * fcio)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
fcsm_ioctl(int cmd,fcio_t * fcio)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