xref: /titanic_51/usr/src/lib/sun_fc/common/TgtFCHBAPort.cc (revision f3aaec0a97c3584095582719a0149d5e94c06ea2)
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 /*
22c946facaSallan  * Copyright 2009 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 <TgtFCHBAPort.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/fctio.h>
43fcf3ce44SJohn Forte #include <sys/fibre-channel/impl/fc_error.h>
44fcf3ce44SJohn Forte #include <sys/fibre-channel/fc_appif.h>
45fcf3ce44SJohn Forte #include <sys/scsi/generic/commands.h>
46fcf3ce44SJohn Forte #include <sys/scsi/impl/commands.h>
47fcf3ce44SJohn Forte #include <sys/scsi/impl/sense.h>
48fcf3ce44SJohn Forte #include <sys/scsi/generic/inquiry.h>
49fcf3ce44SJohn Forte #include <sys/scsi/generic/status.h>
50fcf3ce44SJohn Forte #include <errno.h>
51*f3aaec0aSRichard Lowe #include <cstdlib>
52fcf3ce44SJohn Forte 
53fcf3ce44SJohn Forte 
54fcf3ce44SJohn Forte using namespace std;
55fcf3ce44SJohn Forte 
56fcf3ce44SJohn Forte const int TgtFCHBAPort::MAX_FCTIO_MSG_LEN = 256;
57fcf3ce44SJohn Forte const string TgtFCHBAPort::FCT_DRIVER_PATH = "/devices/pseudo/fct@0:admin";
58fcf3ce44SJohn Forte 
59fcf3ce44SJohn Forte /*
60fcf3ce44SJohn Forte  * Interpret the error code in the fctio_t structure
61fcf3ce44SJohn Forte  *
62fcf3ce44SJohn Forte  * message must be at least MAX_FCTIO_MSG_LEN in length.
63fcf3ce44SJohn Forte  */
64fcf3ce44SJohn Forte void
65fcf3ce44SJohn Forte TgtFCHBAPort::transportError(uint32_t fctio_errno, char *message) {
66fcf3ce44SJohn Forte 	Trace log("transportError");
67fcf3ce44SJohn Forte 	string fcioErrorString;
68fcf3ce44SJohn Forte 	if (message == NULL) {
69fcf3ce44SJohn Forte 	    log.internalError("NULL routine argument");
70fcf3ce44SJohn Forte 	    return;
71fcf3ce44SJohn Forte 	}
72fcf3ce44SJohn Forte 	switch (fctio_errno) {
73fcf3ce44SJohn Forte 	case (uint32_t)FC_FAILURE:
74fcf3ce44SJohn Forte 	    fcioErrorString = "general failure";
75fcf3ce44SJohn Forte 	    break;
76fcf3ce44SJohn Forte 	case (uint32_t)FC_FAILURE_SILENT:
77fcf3ce44SJohn Forte 	    fcioErrorString = "general failure but fail silently";
78fcf3ce44SJohn Forte 	    break;
79fcf3ce44SJohn Forte 	case FC_SUCCESS:
80fcf3ce44SJohn Forte 	    fcioErrorString = "successful completion";
81fcf3ce44SJohn Forte 	    break;
82fcf3ce44SJohn Forte 	case FC_CAP_ERROR:
83fcf3ce44SJohn Forte 	    fcioErrorString = "FCA capability error";
84fcf3ce44SJohn Forte 	    break;
85fcf3ce44SJohn Forte 	case FC_CAP_FOUND:
86fcf3ce44SJohn Forte 	    fcioErrorString = "FCA capability unsettable";
87fcf3ce44SJohn Forte 	    break;
88fcf3ce44SJohn Forte 	case FC_CAP_SETTABLE:
89fcf3ce44SJohn Forte 	    fcioErrorString = "FCA capability settable";
90fcf3ce44SJohn Forte 	    break;
91fcf3ce44SJohn Forte 	case FC_UNBOUND:
92fcf3ce44SJohn Forte 	    fcioErrorString = "unbound stuff";
93fcf3ce44SJohn Forte 	    break;
94fcf3ce44SJohn Forte 	case FC_NOMEM:
95fcf3ce44SJohn Forte 	    fcioErrorString = "allocation error";
96fcf3ce44SJohn Forte 	    break;
97fcf3ce44SJohn Forte 	case FC_BADPACKET:
98fcf3ce44SJohn Forte 	    fcioErrorString = "invalid packet specified/supplied";
99fcf3ce44SJohn Forte 	    break;
100fcf3ce44SJohn Forte 	case FC_OFFLINE:
101fcf3ce44SJohn Forte 	    fcioErrorString = "I/O resource unavailable";
102fcf3ce44SJohn Forte 	    break;
103fcf3ce44SJohn Forte 	case FC_OLDPORT:
104fcf3ce44SJohn Forte 	    fcioErrorString = "operation on non-loop port";
105fcf3ce44SJohn Forte 	    break;
106fcf3ce44SJohn Forte 	case FC_NO_MAP:
107fcf3ce44SJohn Forte 	    fcioErrorString = "requested map unavailable";
108fcf3ce44SJohn Forte 	    break;
109fcf3ce44SJohn Forte 	case FC_TRANSPORT_ERROR:
110fcf3ce44SJohn Forte 	    fcioErrorString = "unable to transport I/O";
111fcf3ce44SJohn Forte 	    break;
112fcf3ce44SJohn Forte 	case FC_ELS_FREJECT:
113fcf3ce44SJohn Forte 	    fcioErrorString = "ELS rejected by a Fabric";
114fcf3ce44SJohn Forte 	    break;
115fcf3ce44SJohn Forte 	case FC_ELS_PREJECT:
116fcf3ce44SJohn Forte 	    fcioErrorString = "ELS rejected by an N_port";
117fcf3ce44SJohn Forte 	    break;
118fcf3ce44SJohn Forte 	case FC_ELS_BAD:
119fcf3ce44SJohn Forte 	    fcioErrorString = "ELS rejected by FCA/fctl";
120fcf3ce44SJohn Forte 	    break;
121fcf3ce44SJohn Forte 	case FC_ELS_MALFORMED:
122fcf3ce44SJohn Forte 	    fcioErrorString = "poorly formed ELS request";
123fcf3ce44SJohn Forte 	    break;
124fcf3ce44SJohn Forte 	case FC_TOOMANY:
125fcf3ce44SJohn Forte 		fcioErrorString = "resource request too large";
126fcf3ce44SJohn Forte 	    break;
127fcf3ce44SJohn Forte 	case FC_UB_BADTOKEN:
128fcf3ce44SJohn Forte 	    fcioErrorString = "invalid unsolicited buffer token";
129fcf3ce44SJohn Forte 	    break;
130fcf3ce44SJohn Forte 	case FC_UB_ERROR:
131fcf3ce44SJohn Forte 	    fcioErrorString = "invalid unsol buf request";
132fcf3ce44SJohn Forte 	    break;
133fcf3ce44SJohn Forte 	case FC_UB_BUSY:
134fcf3ce44SJohn Forte 	    fcioErrorString = "buffer already in use";
135fcf3ce44SJohn Forte 	    break;
136fcf3ce44SJohn Forte 	case FC_BADULP:
137fcf3ce44SJohn Forte 	    fcioErrorString = "Unknown ulp";
138fcf3ce44SJohn Forte 	    break;
139fcf3ce44SJohn Forte 	case FC_BADTYPE:
140fcf3ce44SJohn Forte 	    fcioErrorString = "ULP not registered to handle this FC4 type";
141fcf3ce44SJohn Forte 	    break;
142fcf3ce44SJohn Forte 	case FC_UNCLAIMED:
143fcf3ce44SJohn Forte 	    fcioErrorString = "request or data not claimed";
144fcf3ce44SJohn Forte 	    break;
145fcf3ce44SJohn Forte 	case FC_ULP_SAMEMODULE:
146fcf3ce44SJohn Forte 	    fcioErrorString = "module already in use";
147fcf3ce44SJohn Forte 	    break;
148fcf3ce44SJohn Forte 	case FC_ULP_SAMETYPE:
149fcf3ce44SJohn Forte 	    fcioErrorString = "FC4 module already in use";
150fcf3ce44SJohn Forte 	    break;
151fcf3ce44SJohn Forte 	case FC_ABORTED:
152fcf3ce44SJohn Forte 	    fcioErrorString = "request aborted";
153fcf3ce44SJohn Forte 	    break;
154fcf3ce44SJohn Forte 	case FC_ABORT_FAILED:
155fcf3ce44SJohn Forte 	    fcioErrorString = "abort request failed";
156fcf3ce44SJohn Forte 	    break;
157fcf3ce44SJohn Forte 	case FC_BADEXCHANGE:
158fcf3ce44SJohn Forte 	    fcioErrorString = "exchange doesn�t exist";
159fcf3ce44SJohn Forte 	    break;
160fcf3ce44SJohn Forte 	case FC_BADWWN:
161fcf3ce44SJohn Forte 	    fcioErrorString = "WWN not recognized";
162fcf3ce44SJohn Forte 	    break;
163fcf3ce44SJohn Forte 	case FC_BADDEV:
164fcf3ce44SJohn Forte 	    fcioErrorString = "device unrecognized";
165fcf3ce44SJohn Forte 	    break;
166fcf3ce44SJohn Forte 	case FC_BADCMD:
167fcf3ce44SJohn Forte 	    fcioErrorString = "invalid command issued";
168fcf3ce44SJohn Forte 	    break;
169fcf3ce44SJohn Forte 	case FC_BADOBJECT:
170fcf3ce44SJohn Forte 	    fcioErrorString = "invalid object requested";
171fcf3ce44SJohn Forte 	    break;
172fcf3ce44SJohn Forte 	case FC_BADPORT:
173fcf3ce44SJohn Forte 	    fcioErrorString = "invalid port specified";
174fcf3ce44SJohn Forte 	    break;
175fcf3ce44SJohn Forte 	case FC_NOTTHISPORT:
176fcf3ce44SJohn Forte 	    fcioErrorString = "resource not at this port";
177fcf3ce44SJohn Forte 	    break;
178fcf3ce44SJohn Forte 	case FC_PREJECT:
179fcf3ce44SJohn Forte 	    fcioErrorString = "reject at remote N_Port";
180fcf3ce44SJohn Forte 	    break;
181fcf3ce44SJohn Forte 	case FC_FREJECT:
182fcf3ce44SJohn Forte 	    fcioErrorString = "reject at remote Fabric";
183fcf3ce44SJohn Forte 	    break;
184fcf3ce44SJohn Forte 	case FC_PBUSY:
185fcf3ce44SJohn Forte 	    fcioErrorString = "remote N_Port busy";
186fcf3ce44SJohn Forte 	    break;
187fcf3ce44SJohn Forte 	case FC_FBUSY:
188fcf3ce44SJohn Forte 	    fcioErrorString = "remote Fabric busy";
189fcf3ce44SJohn Forte 	    break;
190fcf3ce44SJohn Forte 	case FC_ALREADY:
191fcf3ce44SJohn Forte 	    fcioErrorString = "already logged in";
192fcf3ce44SJohn Forte 	    break;
193fcf3ce44SJohn Forte 	case FC_LOGINREQ:
194fcf3ce44SJohn Forte 	    fcioErrorString = "login required";
195fcf3ce44SJohn Forte 	    break;
196fcf3ce44SJohn Forte 	case FC_RESETFAIL:
197fcf3ce44SJohn Forte 	    fcioErrorString = "reset failed";
198fcf3ce44SJohn Forte 	    break;
199fcf3ce44SJohn Forte 	case FC_INVALID_REQUEST:
200fcf3ce44SJohn Forte 	    fcioErrorString = "request is invalid";
201fcf3ce44SJohn Forte 	    break;
202fcf3ce44SJohn Forte 	case FC_OUTOFBOUNDS:
203fcf3ce44SJohn Forte 	    fcioErrorString = "port number is out of bounds";
204fcf3ce44SJohn Forte 	    break;
205fcf3ce44SJohn Forte 	case FC_TRAN_BUSY:
206fcf3ce44SJohn Forte 	    fcioErrorString = "command transport busy";
207fcf3ce44SJohn Forte 	    break;
208fcf3ce44SJohn Forte 	case FC_STATEC_BUSY:
209fcf3ce44SJohn Forte 	    fcioErrorString = "port driver currently busy";
210fcf3ce44SJohn Forte 	    break;
211fcf3ce44SJohn Forte 	case FC_DEVICE_BUSY:
212fcf3ce44SJohn Forte 	    fcioErrorString = "transport working on this device";
213fcf3ce44SJohn Forte 	    break;
214fcf3ce44SJohn Forte 	case FC_DEVICE_NOT_TGT:
215fcf3ce44SJohn Forte 	    fcioErrorString = "device is not a SCSI target";
216fcf3ce44SJohn Forte 	    break;
217fcf3ce44SJohn Forte 	default:
218fcf3ce44SJohn Forte 	    snprintf(message, MAX_FCTIO_MSG_LEN, "Unknown error code 0x%x",
219fcf3ce44SJohn Forte 		fctio_errno);
220fcf3ce44SJohn Forte 	    return;
221fcf3ce44SJohn Forte 	}
222fcf3ce44SJohn Forte 	snprintf(message, MAX_FCTIO_MSG_LEN, "%s", fcioErrorString.c_str());
223fcf3ce44SJohn Forte }
224fcf3ce44SJohn Forte 
225fcf3ce44SJohn Forte TgtFCHBAPort::TgtFCHBAPort(string thePath) : HBAPort() {
226fcf3ce44SJohn Forte 	Trace log("TgtFCHBAPort::TgtFCHBAPort");
227fcf3ce44SJohn Forte 	log.debug("Initializing HBA port %s", path.c_str());
228fcf3ce44SJohn Forte 	path = thePath;
229fcf3ce44SJohn Forte 
230fcf3ce44SJohn Forte 	// This routine is not index based, so we can discard stateChange
231fcf3ce44SJohn Forte 	uint64_t tmp;
232fcf3ce44SJohn Forte 	HBA_PORTATTRIBUTES attrs = getPortAttributes(tmp);
233fcf3ce44SJohn Forte 	memcpy(&tmp, &attrs.PortWWN, 8);
234fcf3ce44SJohn Forte 	portWWN = ntohll(tmp);
235fcf3ce44SJohn Forte 	memcpy(&tmp, &attrs.NodeWWN, 8);
236fcf3ce44SJohn Forte 	nodeWWN = ntohll(tmp);
237fcf3ce44SJohn Forte 
238fcf3ce44SJohn Forte 	// For reference, here's how to dump WWN's through C++ streams.
239fcf3ce44SJohn Forte 	// cout << "\tPort WWN: " << hex << setfill('0') << setw(16) << portWWN
240fcf3ce44SJohn Forte 	// << endl;
241fcf3ce44SJohn Forte 	// cout << "\tNode WWN: " << hex << setfill('0') << setw(16) << nodeWWN
242fcf3ce44SJohn Forte 	// << endl;
243fcf3ce44SJohn Forte }
244fcf3ce44SJohn Forte 
245fcf3ce44SJohn Forte HBA_PORTATTRIBUTES TgtFCHBAPort::getPortAttributes(uint64_t &stateChange) {
246fcf3ce44SJohn Forte 	Trace log("TgtFCHBAPort::getPortAttributes");
247fcf3ce44SJohn Forte 
248fcf3ce44SJohn Forte 	HBA_PORTATTRIBUTES	attributes;
249fcf3ce44SJohn Forte 	fctio_t			fctio;
250fcf3ce44SJohn Forte 	fc_tgt_hba_port_attributes_t    attrs;
251fcf3ce44SJohn Forte 
252fcf3ce44SJohn Forte 	memset(&fctio, 0, sizeof (fctio));
253fcf3ce44SJohn Forte 	memset(&attributes, 0, sizeof (attributes));
254fcf3ce44SJohn Forte 
255fcf3ce44SJohn Forte 	uint64_t portwwn = 0;
256fcf3ce44SJohn Forte 	try {
257fcf3ce44SJohn Forte 	    string::size_type offset = path.find_last_of(".");
258fcf3ce44SJohn Forte 	    if (offset >= 0) {
259fcf3ce44SJohn Forte 		string portwwnString = path.substr(offset+1);
260fcf3ce44SJohn Forte 		portwwn = strtoull(portwwnString.c_str(), NULL, 16);
261fcf3ce44SJohn Forte 	    }
262fcf3ce44SJohn Forte 	} catch (...) {
263fcf3ce44SJohn Forte 	    throw BadArgumentException();
264fcf3ce44SJohn Forte 	}
265fcf3ce44SJohn Forte 
266fcf3ce44SJohn Forte 	uint64_t en_wwn = htonll(portwwn);
267fcf3ce44SJohn Forte 
268fcf3ce44SJohn Forte 	fctio.fctio_cmd = FCTIO_GET_ADAPTER_PORT_ATTRIBUTES;
269fcf3ce44SJohn Forte 	fctio.fctio_ilen = 8;
270fcf3ce44SJohn Forte 	fctio.fctio_ibuf = (uint64_t)(uintptr_t)&en_wwn;
271fcf3ce44SJohn Forte 	fctio.fctio_xfer = FCTIO_XFER_READ;
272fcf3ce44SJohn Forte 	fctio.fctio_olen = (uint32_t)(sizeof (attrs));
273fcf3ce44SJohn Forte 	fctio.fctio_obuf = (uint64_t)(uintptr_t)&attrs;
274fcf3ce44SJohn Forte 
275fcf3ce44SJohn Forte 	fct_ioctl(FCTIO_CMD, &fctio);
276fcf3ce44SJohn Forte 
277fcf3ce44SJohn Forte 	stateChange = attrs.lastChange;
278fcf3ce44SJohn Forte 
279fcf3ce44SJohn Forte 	attributes.PortFcId = attrs.PortFcId;
280fcf3ce44SJohn Forte 	attributes.PortType = attrs.PortType;
281fcf3ce44SJohn Forte 	attributes.PortState = attrs.PortState;
282fcf3ce44SJohn Forte 	attributes.PortSupportedClassofService = attrs.PortSupportedClassofService;
283fcf3ce44SJohn Forte 	attributes.PortSupportedSpeed = attrs.PortSupportedSpeed;
284fcf3ce44SJohn Forte 	attributes.PortSpeed = attrs.PortSpeed;
285fcf3ce44SJohn Forte 	attributes.PortMaxFrameSize = attrs.PortMaxFrameSize;
286fcf3ce44SJohn Forte 	attributes.NumberofDiscoveredPorts = attrs.NumberofDiscoveredPorts;
287fcf3ce44SJohn Forte 	memcpy(&attributes.NodeWWN, &attrs.NodeWWN, 8);
288fcf3ce44SJohn Forte 	memcpy(&attributes.PortWWN, &attrs.PortWWN, 8);
289fcf3ce44SJohn Forte 	memcpy(&attributes.FabricName, &attrs.FabricName, 8);
290fcf3ce44SJohn Forte 	memcpy(&attributes.PortSupportedFc4Types, &attrs.PortSupportedFc4Types, 32);
291fcf3ce44SJohn Forte 	memcpy(&attributes.PortActiveFc4Types, &attrs.PortActiveFc4Types, 32);
292fcf3ce44SJohn Forte 	memcpy(&attributes.PortSymbolicName, &attrs.PortSymbolicName, 256);
293fcf3ce44SJohn Forte 
294fcf3ce44SJohn Forte 	strncpy((char *)attributes.OSDeviceName, "Not Applicable", 15);
295fcf3ce44SJohn Forte 	return (attributes);
296fcf3ce44SJohn Forte }
297fcf3ce44SJohn Forte 
298fcf3ce44SJohn Forte HBA_PORTATTRIBUTES TgtFCHBAPort::getDiscoveredAttributes(
299fcf3ce44SJohn Forte 	    HBA_UINT32 discoveredport, uint64_t &stateChange) {
300fcf3ce44SJohn Forte 	Trace log("TgtFCHBAPort::getDiscoverdAttributes(i)");
301fcf3ce44SJohn Forte 
302fcf3ce44SJohn Forte 	HBA_PORTATTRIBUTES		attributes;
303fcf3ce44SJohn Forte 	fctio_t			fctio;
304fcf3ce44SJohn Forte 	fc_tgt_hba_port_attributes_t    attrs;
305fcf3ce44SJohn Forte 
306fcf3ce44SJohn Forte 	memset(&fctio, 0, sizeof (fctio));
307fcf3ce44SJohn Forte 	memset(&attributes, 0, sizeof (attributes));
308fcf3ce44SJohn Forte 
309fcf3ce44SJohn Forte 	uint64_t portwwn = 0;
310fcf3ce44SJohn Forte 	try {
311fcf3ce44SJohn Forte 	    string::size_type offset = path.find_last_of(".");
312fcf3ce44SJohn Forte 	    if (offset >= 0) {
313fcf3ce44SJohn Forte 		string portwwnString = path.substr(offset+1);
314fcf3ce44SJohn Forte 		portwwn = strtoull(portwwnString.c_str(), NULL, 16);
315fcf3ce44SJohn Forte 	    }
316fcf3ce44SJohn Forte 	} catch (...) {
317fcf3ce44SJohn Forte 	    throw BadArgumentException();
318fcf3ce44SJohn Forte 	}
319fcf3ce44SJohn Forte 
320fcf3ce44SJohn Forte 	uint64_t en_wwn = htonll(portwwn);
321fcf3ce44SJohn Forte 
322fcf3ce44SJohn Forte 	fctio.fctio_cmd = FCTIO_GET_DISCOVERED_PORT_ATTRIBUTES;
323fcf3ce44SJohn Forte 	fctio.fctio_ilen = 8;
324fcf3ce44SJohn Forte 	fctio.fctio_ibuf = (uint64_t)(uintptr_t)&en_wwn;
325fcf3ce44SJohn Forte 	fctio.fctio_xfer = FCTIO_XFER_READ;
326fcf3ce44SJohn Forte 	fctio.fctio_olen = (uint32_t)(sizeof (attrs));
327fcf3ce44SJohn Forte 	fctio.fctio_obuf = (uint64_t)(uintptr_t)&attrs;
328fcf3ce44SJohn Forte 	fctio.fctio_alen = (uint32_t)(sizeof (discoveredport));
329fcf3ce44SJohn Forte 	fctio.fctio_abuf = (uint64_t)(uintptr_t)&discoveredport;
330fcf3ce44SJohn Forte 
331fcf3ce44SJohn Forte 	fct_ioctl(FCTIO_CMD, &fctio);
332fcf3ce44SJohn Forte 
333fcf3ce44SJohn Forte 	stateChange = attrs.lastChange;
334fcf3ce44SJohn Forte 
335fcf3ce44SJohn Forte 	attributes.PortFcId = attrs.PortFcId;
336fcf3ce44SJohn Forte 	attributes.PortType = attrs.PortType;
337fcf3ce44SJohn Forte 	attributes.PortState = attrs.PortState;
338fcf3ce44SJohn Forte 	attributes.PortSupportedClassofService = attrs.PortSupportedClassofService;
339fcf3ce44SJohn Forte 	attributes.PortSupportedSpeed = attrs.PortSupportedSpeed;
340fcf3ce44SJohn Forte 	attributes.PortSpeed = attrs.PortSpeed;
341fcf3ce44SJohn Forte 	attributes.PortMaxFrameSize = attrs.PortMaxFrameSize;
342fcf3ce44SJohn Forte 	attributes.NumberofDiscoveredPorts = attrs.NumberofDiscoveredPorts;
343fcf3ce44SJohn Forte 	memcpy(&attributes.NodeWWN, &attrs.NodeWWN, 8);
344fcf3ce44SJohn Forte 	memcpy(&attributes.PortWWN, &attrs.PortWWN, 8);
345fcf3ce44SJohn Forte 	memcpy(&attributes.FabricName, &attrs.FabricName, 8);
346fcf3ce44SJohn Forte 	memcpy(&attributes.PortSupportedFc4Types, &attrs.PortSupportedFc4Types, 32);
347fcf3ce44SJohn Forte 	memcpy(&attributes.PortActiveFc4Types, &attrs.PortActiveFc4Types, 32);
348fcf3ce44SJohn Forte 	memcpy(&attributes.PortSymbolicName, &attrs.PortSymbolicName, 256);
349fcf3ce44SJohn Forte 
350fcf3ce44SJohn Forte 
351fcf3ce44SJohn Forte 	return (attributes);
352fcf3ce44SJohn Forte }
353fcf3ce44SJohn Forte 
354fcf3ce44SJohn Forte HBA_PORTATTRIBUTES TgtFCHBAPort::getDiscoveredAttributes(
355fcf3ce44SJohn Forte 	    uint64_t wwn, uint64_t &stateChange) {
356fcf3ce44SJohn Forte 	Trace log("TgtFCHBAPort::getDiscoverdAttributes(p)");
357fcf3ce44SJohn Forte 
358fcf3ce44SJohn Forte 	HBA_PORTATTRIBUTES attributes;
359fcf3ce44SJohn Forte 	fctio_t			fctio;
360fcf3ce44SJohn Forte 	fc_tgt_hba_port_attributes_t    attrs;
361fcf3ce44SJohn Forte 
362fcf3ce44SJohn Forte 	memset(&fctio, 0, sizeof (fctio));
363fcf3ce44SJohn Forte 	memset(&attributes, 0, sizeof (attributes));
364fcf3ce44SJohn Forte 
365fcf3ce44SJohn Forte 	uint64_t en_wwn = htonll(wwn);
366fcf3ce44SJohn Forte 
367fcf3ce44SJohn Forte 	fctio.fctio_cmd = FCTIO_GET_PORT_ATTRIBUTES;
368fcf3ce44SJohn Forte 	fctio.fctio_olen = (uint32_t)(sizeof (attrs));
369fcf3ce44SJohn Forte 	fctio.fctio_xfer = FCTIO_XFER_READ;
370fcf3ce44SJohn Forte 	fctio.fctio_obuf = (uint64_t)(uintptr_t)&attrs;
371fcf3ce44SJohn Forte 	fctio.fctio_ilen = (uint32_t)(sizeof (wwn));
372fcf3ce44SJohn Forte 	fctio.fctio_ibuf = (uint64_t)(uintptr_t)&en_wwn;
373fcf3ce44SJohn Forte 
374fcf3ce44SJohn Forte 	fct_ioctl(FCTIO_CMD, &fctio);
375fcf3ce44SJohn Forte 
376fcf3ce44SJohn Forte 	stateChange = attrs.lastChange;
377fcf3ce44SJohn Forte 
378fcf3ce44SJohn Forte 	attributes.PortFcId = attrs.PortFcId;
379fcf3ce44SJohn Forte 	attributes.PortType = attrs.PortType;
380fcf3ce44SJohn Forte 	attributes.PortState = attrs.PortState;
381fcf3ce44SJohn Forte 	attributes.PortSupportedClassofService = attrs.PortSupportedClassofService;
382fcf3ce44SJohn Forte 	attributes.PortSupportedSpeed = attrs.PortSupportedSpeed;
383fcf3ce44SJohn Forte 	attributes.PortSpeed = attrs.PortSpeed;
384fcf3ce44SJohn Forte 	attributes.PortMaxFrameSize = attrs.PortMaxFrameSize;
385fcf3ce44SJohn Forte 	attributes.NumberofDiscoveredPorts = attrs.NumberofDiscoveredPorts;
386fcf3ce44SJohn Forte 	memcpy(&attributes.NodeWWN, &attrs.NodeWWN, 8);
387fcf3ce44SJohn Forte 	memcpy(&attributes.PortWWN, &attrs.PortWWN, 8);
388fcf3ce44SJohn Forte 	memcpy(&attributes.FabricName, &attrs.FabricName, 8);
389fcf3ce44SJohn Forte 	memcpy(&attributes.PortSupportedFc4Types, &attrs.PortSupportedFc4Types, 32);
390fcf3ce44SJohn Forte 	memcpy(&attributes.PortActiveFc4Types, &attrs.PortActiveFc4Types, 32);
391fcf3ce44SJohn Forte 	memcpy(&attributes.PortSymbolicName, &attrs.PortSymbolicName, 256);
392fcf3ce44SJohn Forte 
393fcf3ce44SJohn Forte 
394fcf3ce44SJohn Forte 	return (attributes);
395fcf3ce44SJohn Forte }
396fcf3ce44SJohn Forte 
397fcf3ce44SJohn Forte void TgtFCHBAPort::sendRLS(uint64_t destWWN,
398fcf3ce44SJohn Forte 	    void		*pRspBuffer,
399fcf3ce44SJohn Forte 	    HBA_UINT32		*pRspBufferSize) {
400fcf3ce44SJohn Forte 	Trace log("FCHBAPort::sendRLS");
401fcf3ce44SJohn Forte 
402fcf3ce44SJohn Forte 	fctio_t		fctio;
403fcf3ce44SJohn Forte 	// fc_hba_adapter_port_stats_t	fc_port_stat;
404fcf3ce44SJohn Forte 	uint64_t	en_portWWN;
405c946facaSallan 	uint64_t	DestPortID;
406fcf3ce44SJohn Forte 
407fcf3ce44SJohn Forte 	// Validate the arguments
408fcf3ce44SJohn Forte 	if (pRspBuffer == NULL ||
409fcf3ce44SJohn Forte 		pRspBufferSize == NULL) {
410fcf3ce44SJohn Forte 	    log.userError("NULL hba");
411fcf3ce44SJohn Forte 	    throw BadArgumentException();
412fcf3ce44SJohn Forte 	}
413fcf3ce44SJohn Forte 
414fcf3ce44SJohn Forte 	// check to see if we are sending RLS to the HBA
415fcf3ce44SJohn Forte 	HBA_PORTATTRIBUTES attrs;
416fcf3ce44SJohn Forte 	uint64_t tmp;
417fcf3ce44SJohn Forte 	portWWN = getPortWWN();
418fcf3ce44SJohn Forte 	en_portWWN = htonll(portWWN);
419fcf3ce44SJohn Forte 
420fcf3ce44SJohn Forte 	/* The destWWN is either the adapter port or a discovered port. */
421fcf3ce44SJohn Forte 	memset(&fctio, 0, sizeof (fctio));
422c946facaSallan 	fctio.fctio_cmd = FCTIO_GET_LINK_STATUS;
423fcf3ce44SJohn Forte 	fctio.fctio_ibuf = (uint64_t)(uintptr_t)&en_portWWN;
424fcf3ce44SJohn Forte 	fctio.fctio_ilen = (uint32_t)(sizeof (en_portWWN));
425fcf3ce44SJohn Forte 	if (portWWN != destWWN) {
426fcf3ce44SJohn Forte 	    attrs = getDiscoveredAttributes(destWWN, tmp);
427c946facaSallan 	    DestPortID = (uint64_t)attrs.PortFcId;
428c946facaSallan 	    fctio.fctio_abuf = (uint64_t)(uintptr_t)&DestPortID;
429c946facaSallan 	    fctio.fctio_alen = (uint32_t)(sizeof (DestPortID));
430fcf3ce44SJohn Forte 	}
431fcf3ce44SJohn Forte 	fctio.fctio_xfer = FCTIO_XFER_READ;
432fcf3ce44SJohn Forte 	fctio.fctio_flags = 0;
433fcf3ce44SJohn Forte 	fctio.fctio_obuf = (uint64_t)(uintptr_t)new uchar_t[*pRspBufferSize];
434fcf3ce44SJohn Forte 	fctio.fctio_olen = *pRspBufferSize;
435fcf3ce44SJohn Forte 
436fcf3ce44SJohn Forte 	if (fctio.fctio_obuf == NULL) {
437fcf3ce44SJohn Forte 	    log.noMemory();
438fcf3ce44SJohn Forte 	    throw InternalError();
439fcf3ce44SJohn Forte 	}
440fcf3ce44SJohn Forte 
441fcf3ce44SJohn Forte 	fct_ioctl(FCTIO_CMD, &fctio);
442fcf3ce44SJohn Forte 	memcpy(pRspBuffer, (uchar_t *)(uintptr_t)fctio.fctio_obuf,
443fcf3ce44SJohn Forte 	       *pRspBufferSize);
444fcf3ce44SJohn Forte 	if (fctio.fctio_obuf != NULL) {
445fcf3ce44SJohn Forte 	    delete((uchar_t *)(uintptr_t)fctio.fctio_obuf);
446fcf3ce44SJohn Forte 	}
447fcf3ce44SJohn Forte }
448fcf3ce44SJohn Forte 
449fcf3ce44SJohn Forte /**
450fcf3ce44SJohn Forte  * @memo	    Validate that the port is still present in the system
451fcf3ce44SJohn Forte  * @exception	    UnavailableException if the port is not present
452fcf3ce44SJohn Forte  * @version	    1.7
453fcf3ce44SJohn Forte  *
454fcf3ce44SJohn Forte  * @doc		    If the port is still present on the system, the routine
455fcf3ce44SJohn Forte  *		    will return normally.  If the port is not present
456fcf3ce44SJohn Forte  *		    an exception will be thrown.
457fcf3ce44SJohn Forte  */
458fcf3ce44SJohn Forte void TgtFCHBAPort::validatePresent() {
459fcf3ce44SJohn Forte 	Trace log("TgtFCHBAPort::validatePresent");
460fcf3ce44SJohn Forte 	// We already got the adapter list through the ioctl
461fcf3ce44SJohn Forte 	// so calling it again to validate it is too expensive.
462fcf3ce44SJohn Forte }
463fcf3ce44SJohn Forte 
464fcf3ce44SJohn Forte void TgtFCHBAPort::fct_ioctl(int cmd, fctio_t *fctio) {
465fcf3ce44SJohn Forte 	Trace log("TgtFCHBAPort::fct_ioctl");
466fcf3ce44SJohn Forte 	char fcioErrorString[MAX_FCTIO_MSG_LEN] = "";
467fcf3ce44SJohn Forte 	int fd = HBA::_open(FCT_DRIVER_PATH, O_NDELAY | O_RDONLY);
468fcf3ce44SJohn Forte 	try {
469fcf3ce44SJohn Forte 	    HBA::_ioctl(fd, cmd, (uchar_t *)fctio);
470fcf3ce44SJohn Forte 	    close(fd);
471fcf3ce44SJohn Forte 	    if (fctio->fctio_errno) {
472fcf3ce44SJohn Forte 		throw IOError("IOCTL transport failure");
473fcf3ce44SJohn Forte 	    }
474fcf3ce44SJohn Forte 	} catch (...) {
475fcf3ce44SJohn Forte 	    close(fd);
476fcf3ce44SJohn Forte 	    transportError(fctio->fctio_errno, fcioErrorString);
477fcf3ce44SJohn Forte 	    log.genericIOError("ioctl (0x%x) failed. Transport: \"%s\"", cmd,
478fcf3ce44SJohn Forte 		    fcioErrorString);
479fcf3ce44SJohn Forte 	    switch (fctio->fctio_errno) {
480fcf3ce44SJohn Forte 	    case FC_BADWWN:
481fcf3ce44SJohn Forte 		throw IllegalWWNException();
482fcf3ce44SJohn Forte 	    case FC_BADPORT:
483fcf3ce44SJohn Forte 		throw IllegalWWNException();
484fcf3ce44SJohn Forte 	    case FC_OUTOFBOUNDS:
485fcf3ce44SJohn Forte 		throw IllegalIndexException();
486fcf3ce44SJohn Forte 	    case FC_PBUSY:
487fcf3ce44SJohn Forte 	    case FC_FBUSY:
488fcf3ce44SJohn Forte 	    case FC_TRAN_BUSY:
489fcf3ce44SJohn Forte 	    case FC_STATEC_BUSY:
490fcf3ce44SJohn Forte 	    case FC_DEVICE_BUSY:
491fcf3ce44SJohn Forte 		throw BusyException();
492fcf3ce44SJohn Forte 	    case FC_SUCCESS:
493fcf3ce44SJohn Forte 	    default:
494fcf3ce44SJohn Forte 		throw;
495fcf3ce44SJohn Forte 	    }
496fcf3ce44SJohn Forte 	}
497fcf3ce44SJohn Forte }
498