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 /*
22a7949318SReed * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23fcf3ce44SJohn Forte * Use is subject to license terms.
24fcf3ce44SJohn Forte */
25fcf3ce44SJohn Forte
26fcf3ce44SJohn Forte
27fcf3ce44SJohn Forte #include <unistd.h>
28fcf3ce44SJohn Forte
29fcf3ce44SJohn Forte #include <TgtFCHBA.h>
30fcf3ce44SJohn Forte #include <Exceptions.h>
31fcf3ce44SJohn Forte #include <Trace.h>
32fcf3ce44SJohn Forte #include <iostream>
33fcf3ce44SJohn Forte #include <iomanip>
34fcf3ce44SJohn Forte #include <cerrno>
35fcf3ce44SJohn Forte #include <cstring>
36fcf3ce44SJohn Forte #include <sys/types.h>
37fcf3ce44SJohn Forte #include <sys/stat.h>
38fcf3ce44SJohn Forte #include <fcntl.h>
39fcf3ce44SJohn Forte #include <unistd.h>
40fcf3ce44SJohn Forte #include <stropts.h>
41fcf3ce44SJohn Forte #include <sys/fctio.h>
42fcf3ce44SJohn Forte #include <sys/fibre-channel/impl/fc_error.h>
43fcf3ce44SJohn Forte #include <TgtFCHBAPort.h>
44fcf3ce44SJohn Forte #include <HBAList.h>
45fcf3ce44SJohn Forte #include <sun_fc.h>
46f3aaec0aSRichard Lowe #include <cstdlib>
47fcf3ce44SJohn Forte
48fcf3ce44SJohn Forte using namespace std;
49fcf3ce44SJohn Forte const string TgtFCHBA::FCT_DRIVER_PATH = "/devices/pseudo/fct@0:admin";
50fcf3ce44SJohn Forte const string TgtFCHBA::FCT_ADAPTER_NAME_PREFIX = "/devices/pseudo/fct@0";
51fcf3ce44SJohn Forte const string TgtFCHBA::FCT_DRIVER_PKG = "SUNWfct";
52fcf3ce44SJohn Forte const int TgtFCHBA::MAX_FCTIO_MSG_LEN = 256;
53fcf3ce44SJohn Forte
TgtFCHBA(string path)54fcf3ce44SJohn Forte TgtFCHBA::TgtFCHBA(string path) : HBA()
55fcf3ce44SJohn Forte {
56fcf3ce44SJohn Forte Trace log("TgtFCHBA::TgtFCHBA");
57fcf3ce44SJohn Forte log.debug("Constructing new Target mode HBA (%s)", path.c_str());
58fcf3ce44SJohn Forte
59fcf3ce44SJohn Forte // Add a target FCHBA port. With fct driver architecuture, all target mode
60fcf3ce44SJohn Forte // FCHBA will have a single port regardless of the multiport support on
61fcf3ce44SJohn Forte // FCA layer.
62fcf3ce44SJohn Forte addPort(new TgtFCHBAPort(path));
63fcf3ce44SJohn Forte name = "INTERNAL-FAILURE"; // Just in case things go wrong
64fcf3ce44SJohn Forte try {
65fcf3ce44SJohn Forte HBA_ADAPTERATTRIBUTES attrs = getHBAAttributes();
66fcf3ce44SJohn Forte name = attrs.Manufacturer;
67fcf3ce44SJohn Forte name += "-";
68fcf3ce44SJohn Forte name += attrs.Model;
69fcf3ce44SJohn Forte name += "-Tgt";
70fcf3ce44SJohn Forte
71fcf3ce44SJohn Forte } catch (HBAException &e) {
72fcf3ce44SJohn Forte log.debug(
73fcf3ce44SJohn Forte "Failed to get HBA attribute for %s", path.c_str());
74fcf3ce44SJohn Forte throw e;
75fcf3ce44SJohn Forte }
76fcf3ce44SJohn Forte }
77fcf3ce44SJohn Forte
getName()78fcf3ce44SJohn Forte std::string TgtFCHBA::getName()
79fcf3ce44SJohn Forte {
80fcf3ce44SJohn Forte Trace log("TgtFCHBA::getName");
81fcf3ce44SJohn Forte return (name);
82fcf3ce44SJohn Forte }
83fcf3ce44SJohn Forte
getHBAAttributes()84fcf3ce44SJohn Forte HBA_ADAPTERATTRIBUTES TgtFCHBA::getHBAAttributes()
85fcf3ce44SJohn Forte {
86fcf3ce44SJohn Forte Trace log("TgtFCHBA::getHBAAttributes");
87fcf3ce44SJohn Forte int fd;
88fcf3ce44SJohn Forte
89fcf3ce44SJohn Forte errno = 0;
90fcf3ce44SJohn Forte HBAPort *port = getPortByIndex(0);
91fcf3ce44SJohn Forte
92fcf3ce44SJohn Forte HBA_ADAPTERATTRIBUTES attributes;
93fcf3ce44SJohn Forte fctio_t fctio;
94fcf3ce44SJohn Forte fc_tgt_hba_adapter_attributes_t attrs;
95fcf3ce44SJohn Forte uint64_t portwwn;
96fcf3ce44SJohn Forte
97fcf3ce44SJohn Forte if ((fd = open(FCT_DRIVER_PATH.c_str(), O_NDELAY | O_RDONLY)) == -1) {
98fcf3ce44SJohn Forte // Why did we fail?
99fcf3ce44SJohn Forte if (errno == EBUSY) {
100fcf3ce44SJohn Forte throw BusyException();
101fcf3ce44SJohn Forte } else if (errno == EAGAIN) {
102fcf3ce44SJohn Forte throw TryAgainException();
103fcf3ce44SJohn Forte } else if (errno == ENOTSUP) {
104fcf3ce44SJohn Forte throw NotSupportedException();
105fcf3ce44SJohn Forte } else {
106fcf3ce44SJohn Forte throw IOError(port);
107fcf3ce44SJohn Forte }
108fcf3ce44SJohn Forte }
109fcf3ce44SJohn Forte
110fcf3ce44SJohn Forte try {
111fcf3ce44SJohn Forte std::string path = port->getPath();
112fcf3ce44SJohn Forte string::size_type offset = path.find_last_of(".");
113fcf3ce44SJohn Forte if (offset >= 0) {
114fcf3ce44SJohn Forte string portwwnString = path.substr(offset+1);
115fcf3ce44SJohn Forte portwwn = strtoull(portwwnString.c_str(), NULL, 16);
116fcf3ce44SJohn Forte }
117fcf3ce44SJohn Forte } catch (...) {
118fcf3ce44SJohn Forte throw BadArgumentException();
119fcf3ce44SJohn Forte }
120fcf3ce44SJohn Forte
121fcf3ce44SJohn Forte uint64_t en_wwn = htonll(portwwn);
122fcf3ce44SJohn Forte
123fcf3ce44SJohn Forte memset(&fctio, 0, sizeof (fctio));
124fcf3ce44SJohn Forte fctio.fctio_cmd = FCTIO_GET_ADAPTER_ATTRIBUTES;
125fcf3ce44SJohn Forte fctio.fctio_olen = (uint32_t)(sizeof (attrs));
126fcf3ce44SJohn Forte fctio.fctio_xfer = FCTIO_XFER_READ;
127fcf3ce44SJohn Forte fctio.fctio_obuf = (uint64_t)(uintptr_t)&attrs;
128fcf3ce44SJohn Forte fctio.fctio_ilen = 8;
129fcf3ce44SJohn Forte fctio.fctio_ibuf = (uint64_t)(uintptr_t)&en_wwn;
130fcf3ce44SJohn Forte
131fcf3ce44SJohn Forte errno = 0;
132fcf3ce44SJohn Forte if (ioctl(fd, FCTIO_CMD, &fctio) != 0) {
133fcf3ce44SJohn Forte close(fd);
134fcf3ce44SJohn Forte if (errno == EBUSY) {
135fcf3ce44SJohn Forte throw BusyException();
136fcf3ce44SJohn Forte } else if (errno == EAGAIN) {
137fcf3ce44SJohn Forte throw TryAgainException();
138fcf3ce44SJohn Forte } else if (errno == ENOTSUP) {
139fcf3ce44SJohn Forte throw NotSupportedException();
140fcf3ce44SJohn Forte } else {
141fcf3ce44SJohn Forte throw IOError("Unable to fetch adapter attributes");
142fcf3ce44SJohn Forte }
143fcf3ce44SJohn Forte }
144fcf3ce44SJohn Forte close(fd);
145fcf3ce44SJohn Forte
146fcf3ce44SJohn Forte /* Now copy over the payload */
147fcf3ce44SJohn Forte attributes.NumberOfPorts = attrs.NumberOfPorts;
148fcf3ce44SJohn Forte attributes.VendorSpecificID = attrs.VendorSpecificID;
149fcf3ce44SJohn Forte memcpy(attributes.Manufacturer, attrs.Manufacturer, 64);
150fcf3ce44SJohn Forte memcpy(attributes.SerialNumber, attrs.SerialNumber, 64);
151fcf3ce44SJohn Forte memcpy(attributes.Model, attrs.Model, 256);
152fcf3ce44SJohn Forte memcpy(attributes.ModelDescription, attrs.ModelDescription, 256);
153fcf3ce44SJohn Forte memcpy(attributes.NodeSymbolicName, attrs.NodeSymbolicName, 256);
154fcf3ce44SJohn Forte memcpy(attributes.HardwareVersion, attrs.HardwareVersion, 256);
155fcf3ce44SJohn Forte memcpy(attributes.DriverVersion, attrs.DriverVersion, 256);
156fcf3ce44SJohn Forte memcpy(attributes.OptionROMVersion, attrs.OptionROMVersion, 256);
157fcf3ce44SJohn Forte memcpy(attributes.FirmwareVersion, attrs.FirmwareVersion, 256);
158fcf3ce44SJohn Forte memcpy(attributes.DriverName, attrs.DriverName, 256);
159fcf3ce44SJohn Forte memcpy(&attributes.NodeWWN, &attrs.NodeWWN, 8);
160fcf3ce44SJohn Forte
161fcf3ce44SJohn Forte return (attributes);
162fcf3ce44SJohn Forte }
163fcf3ce44SJohn Forte
doForceLip()164a7949318SReed int TgtFCHBA::doForceLip()
165a7949318SReed {
166a7949318SReed Trace log("TgtFCHBA::doForceLip");
167a7949318SReed int fd;
168a7949318SReed HBAPort *port = getPortByIndex(0);
169a7949318SReed fctio_t fctio;
170a7949318SReed uint64_t portwwn;
171a7949318SReed
172a7949318SReed errno = 0;
173a7949318SReed if ((fd = open(FCT_DRIVER_PATH.c_str(), O_NDELAY | O_RDONLY)) == -1) {
174a7949318SReed if (errno == EBUSY) {
175a7949318SReed throw BusyException();
176a7949318SReed } else if (errno == EAGAIN) {
177a7949318SReed throw TryAgainException();
178a7949318SReed } else if (errno == ENOTSUP) {
179a7949318SReed throw NotSupportedException();
180a7949318SReed } else {
181a7949318SReed throw IOError(port);
182a7949318SReed }
183a7949318SReed }
184a7949318SReed
185a7949318SReed try {
186a7949318SReed std::string path = port->getPath();
187a7949318SReed string::size_type offset = path.find_last_of(".");
188a7949318SReed if (offset >= 0) {
189a7949318SReed string portwwnString = path.substr(offset+1);
190a7949318SReed portwwn = strtoull(portwwnString.c_str(), NULL, 16);
191a7949318SReed }
192a7949318SReed } catch (...) {
193a7949318SReed throw BadArgumentException();
194a7949318SReed }
195a7949318SReed
196a7949318SReed uint64_t en_wwn = htonll(portwwn);
197a7949318SReed memset(&fctio, 0, sizeof (fctio));
198a7949318SReed fctio.fctio_cmd = FCTIO_FORCE_LIP;
199a7949318SReed fctio.fctio_xfer = FCTIO_XFER_READ;
200a7949318SReed fctio.fctio_ilen = 8;
201a7949318SReed fctio.fctio_ibuf = (uint64_t)(uintptr_t)&en_wwn;
202a7949318SReed
203a7949318SReed errno = 0;
204a7949318SReed if (ioctl(fd, FCTIO_CMD, &fctio) != 0) {
205a7949318SReed close(fd);
206a7949318SReed if (errno == EBUSY) {
207a7949318SReed throw BusyException();
208a7949318SReed } else if (errno == EAGAIN) {
209a7949318SReed throw TryAgainException();
210a7949318SReed } else if (errno == ENOTSUP) {
211a7949318SReed throw NotSupportedException();
212a7949318SReed } else {
213a7949318SReed throw IOError("Unable to reinitialize the link");
214a7949318SReed }
215a7949318SReed } else {
216a7949318SReed close(fd);
217a7949318SReed return ((int)fctio.fctio_errno);
218a7949318SReed }
219a7949318SReed }
220a7949318SReed
loadAdapters(vector<HBA * > & list)221fcf3ce44SJohn Forte void TgtFCHBA::loadAdapters(vector<HBA*> &list)
222fcf3ce44SJohn Forte {
223fcf3ce44SJohn Forte Trace log("TgtFCHBA::loadAdapters");
224fcf3ce44SJohn Forte fctio_t fctio;
225fcf3ce44SJohn Forte fc_tgt_hba_list_t *tgthbaList;
226fcf3ce44SJohn Forte int fd;
227fcf3ce44SJohn Forte int size = 64; // default first attempt
228fcf3ce44SJohn Forte bool retry = false;
229fcf3ce44SJohn Forte struct stat sb;
230fcf3ce44SJohn Forte int bufSize;
231fcf3ce44SJohn Forte char wwnStr[17];
232fcf3ce44SJohn Forte
233fcf3ce44SJohn Forte /* Before we do anything, let's see if FCT is on the system */
234fcf3ce44SJohn Forte errno = 0;
235fcf3ce44SJohn Forte if (stat(FCT_DRIVER_PATH.c_str(), &sb) != 0) {
236fcf3ce44SJohn Forte if (errno == ENOENT) {
237fcf3ce44SJohn Forte log.genericIOError(
238fcf3ce44SJohn Forte "The %s driver is not present."
239fcf3ce44SJohn Forte " Please install the %s package.",
240fcf3ce44SJohn Forte FCT_DRIVER_PATH.c_str(), FCT_DRIVER_PKG.c_str());
241fcf3ce44SJohn Forte throw NotSupportedException();
242fcf3ce44SJohn Forte } else {
243fcf3ce44SJohn Forte log.genericIOError(
244fcf3ce44SJohn Forte "Can not stat the %s driver for reason \"%s\" "
245fcf3ce44SJohn Forte "Unable to get target mode FC adapters.",
246fcf3ce44SJohn Forte FCT_DRIVER_PATH.c_str(), strerror(errno));
247fcf3ce44SJohn Forte throw IOError("Unable to stat FCSM driver");
248fcf3ce44SJohn Forte }
249fcf3ce44SJohn Forte }
250fcf3ce44SJohn Forte
251fcf3ce44SJohn Forte
252fcf3ce44SJohn Forte /* construct fcio struct */
253fcf3ce44SJohn Forte memset(&fctio, 0, sizeof (fctio_t));
254fcf3ce44SJohn Forte fctio.fctio_cmd = FCTIO_ADAPTER_LIST;
255fcf3ce44SJohn Forte fctio.fctio_xfer = FCTIO_XFER_RW;
256fcf3ce44SJohn Forte
257fcf3ce44SJohn Forte /* open the fcsm node so we can send the ioctl to */
258fcf3ce44SJohn Forte errno = 0;
259fcf3ce44SJohn Forte if ((fd = open(FCT_DRIVER_PATH.c_str(), O_RDONLY)) < 0) {
260fcf3ce44SJohn Forte if (errno == EBUSY) {
261fcf3ce44SJohn Forte throw BusyException();
262fcf3ce44SJohn Forte } else if (errno == EAGAIN) {
263fcf3ce44SJohn Forte throw TryAgainException();
264fcf3ce44SJohn Forte } else if (errno == ENOTSUP) {
265fcf3ce44SJohn Forte throw NotSupportedException();
266fcf3ce44SJohn Forte } else if (errno == ENOENT) {
267fcf3ce44SJohn Forte throw UnavailableException();
268fcf3ce44SJohn Forte } else {
269fcf3ce44SJohn Forte throw IOError("Unable to open FCT driver");
270fcf3ce44SJohn Forte }
271fcf3ce44SJohn Forte }
272fcf3ce44SJohn Forte
273fcf3ce44SJohn Forte do {
274fcf3ce44SJohn Forte retry = false;
275fcf3ce44SJohn Forte errno = 0;
276fcf3ce44SJohn Forte bufSize = 8 * (size - 1) + (int) sizeof (fc_tgt_hba_list_t);
277fcf3ce44SJohn Forte tgthbaList = (fc_tgt_hba_list_t *)new uchar_t[bufSize];
278fcf3ce44SJohn Forte tgthbaList->numPorts = size;
279fcf3ce44SJohn Forte fctio.fctio_olen = bufSize;
280fcf3ce44SJohn Forte fctio.fctio_obuf = (uint64_t)(uintptr_t)tgthbaList;
281fcf3ce44SJohn Forte if (ioctl(fd, FCTIO_CMD, &fctio) != 0) {
282fcf3ce44SJohn Forte /* Interpret the fcio error code */
283fcf3ce44SJohn Forte char fcioErrorString[MAX_FCTIO_MSG_LEN] = "";
284fcf3ce44SJohn Forte
285fcf3ce44SJohn Forte log.genericIOError(
286fcf3ce44SJohn Forte "TGT_ADAPTER_LIST failed: "
287fcf3ce44SJohn Forte "Errno: \"%s\"",
288fcf3ce44SJohn Forte strerror(errno));
289fcf3ce44SJohn Forte delete (tgthbaList);
290fcf3ce44SJohn Forte close(fd);
291fcf3ce44SJohn Forte if (errno == EBUSY) {
292fcf3ce44SJohn Forte throw BusyException();
293fcf3ce44SJohn Forte } else if (errno == EAGAIN) {
294fcf3ce44SJohn Forte throw TryAgainException();
295fcf3ce44SJohn Forte } else if (errno == ENOTSUP) {
296fcf3ce44SJohn Forte throw NotSupportedException();
297fcf3ce44SJohn Forte } else if (errno == ENOENT) {
298fcf3ce44SJohn Forte throw UnavailableException();
299fcf3ce44SJohn Forte } else {
300fcf3ce44SJohn Forte throw IOError("Unable to build HBA list");
301fcf3ce44SJohn Forte }
302fcf3ce44SJohn Forte }
303fcf3ce44SJohn Forte if (tgthbaList->numPorts > size) {
304fcf3ce44SJohn Forte log.debug(
305fcf3ce44SJohn Forte "Buffer too small for number of target mode HBAs. Retrying.");
306fcf3ce44SJohn Forte size = tgthbaList->numPorts;
307fcf3ce44SJohn Forte retry = true;
308fcf3ce44SJohn Forte delete (tgthbaList);
309fcf3ce44SJohn Forte }
310fcf3ce44SJohn Forte } while (retry);
311fcf3ce44SJohn Forte
312fcf3ce44SJohn Forte close(fd);
313fcf3ce44SJohn Forte log.debug("Detected %d target mode adapters", tgthbaList->numPorts);
314fcf3ce44SJohn Forte for (int i = 0; i < tgthbaList->numPorts; i++) {
315fcf3ce44SJohn Forte try {
316fcf3ce44SJohn Forte std::string hbapath = FCT_ADAPTER_NAME_PREFIX.c_str();
317fcf3ce44SJohn Forte hbapath += ".";
318fcf3ce44SJohn Forte // move the row with two dimentional uint8 array for WWN
319fcf3ce44SJohn Forte uint64_t tmp = ntohll(*((uint64_t *)&tgthbaList->port_wwn[i][0]));
320fcf3ce44SJohn Forte sprintf(wwnStr, "%llx", tmp);
321fcf3ce44SJohn Forte hbapath += wwnStr;
322fcf3ce44SJohn Forte
323fcf3ce44SJohn Forte HBA *hba = new TgtFCHBA(hbapath);
324fcf3ce44SJohn Forte list.insert(list.begin(), hba);
325fcf3ce44SJohn Forte } catch (...) {
326fcf3ce44SJohn Forte log.debug(
327fcf3ce44SJohn Forte "Ignoring partial failure while loading an HBA");
328fcf3ce44SJohn Forte }
329fcf3ce44SJohn Forte }
330fcf3ce44SJohn Forte if (tgthbaList->numPorts > HBAList::HBA_MAX_PER_LIST) {
331fcf3ce44SJohn Forte delete(tgthbaList);
332fcf3ce44SJohn Forte throw InternalError(
333*0778188fSHengqing Hu "Exceeds max number of adapters that VSL supports.");
334fcf3ce44SJohn Forte }
335fcf3ce44SJohn Forte delete (tgthbaList);
336fcf3ce44SJohn Forte }
337