1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26
27 #include "fcinfo.h"
28 #include <libintl.h>
29
30 struct lun {
31 uchar_t val[8];
32 };
33
34 typedef enum {
35 HBA_PORT,
36 REMOTE_PORT,
37 LOGICAL_UNIT
38 } resource_type;
39
40 typedef struct rep_luns_rsp {
41 uint32_t length;
42 uint32_t rsrvd;
43 struct lun lun[1];
44 } rep_luns_rsp_t;
45
46 static int getTargetMapping(HBA_HANDLE, HBA_WWN myhbaPortWWN,
47 HBA_FCPTARGETMAPPINGV2 **mapping);
48 static int processHBA(HBA_HANDLE handle, HBA_ADAPTERATTRIBUTES attrs,
49 int portIndex, HBA_PORTATTRIBUTES port, HBA_FCPTARGETMAPPINGV2 *map,
50 int resourceType, int flags, int mode);
51 static void processRemotePort(HBA_HANDLE handle, HBA_WWN portWWN,
52 HBA_FCPTARGETMAPPINGV2 *map, int wwnCount, char **wwn_argv, int flags);
53 static void handleRemotePort(HBA_HANDLE handle, HBA_WWN portWWN,
54 HBA_WWN myRemotePortWWN, HBA_PORTATTRIBUTES *discPort);
55 static void printLinkStat(HBA_HANDLE handle, HBA_WWN hbaportWWN,
56 HBA_WWN destWWN);
57 static void handleScsiTarget(HBA_HANDLE handle, HBA_WWN hbaPortWWN,
58 HBA_WWN scsiTargetWWN, HBA_FCPTARGETMAPPINGV2 *map);
59 static int retrieveAttrs(HBA_HANDLE handle, HBA_WWN hbaPortWWN,
60 HBA_ADAPTERATTRIBUTES *attrs, HBA_PORTATTRIBUTES *port, int *portIndex);
61 static void searchDevice(discoveredDevice **devList, HBA_FCPSCSIENTRYV2 entry,
62 HBA_WWN initiatorPortWWN, HBA_HANDLE handle, boolean_t verbose);
63
64 /*
65 * This function retrieve the adapater attributes, port attributes, and
66 * portIndex for the given handle and hba port WWN.
67 *
68 * Arguments:
69 * handle an HBA_HANDLE to a adapter
70 * hbaPortWWN WWN of the port on the adapter to which to retrieve
71 * HBA_PORTATTRIBUTES from
72 * attrs pointer to a HBA_ADAPTERATTRIBUTES structure. Upon
73 * successful completion, this structure will be filled in
74 * port pointer to a HBA_PORTATTRIBUTES structure. Upon successful
75 * completion, this structure will be fill in
76 * portIndex the Index count of the port on the adapter that is
77 * associated with the WWN.
78 *
79 * Returns
80 * 0 successfully retrieve all information
81 * >0 otherwise
82 */
83 static int
retrieveAttrs(HBA_HANDLE handle,HBA_WWN hbaPortWWN,HBA_ADAPTERATTRIBUTES * attrs,HBA_PORTATTRIBUTES * port,int * portIndex)84 retrieveAttrs(HBA_HANDLE handle, HBA_WWN hbaPortWWN,
85 HBA_ADAPTERATTRIBUTES *attrs, HBA_PORTATTRIBUTES *port, int *portIndex)
86 {
87 HBA_STATUS status;
88 int portCtr;
89 int times;
90
91 /* argument checking */
92 if (attrs == NULL || port == NULL || portIndex == NULL) {
93 fprintf(stderr, gettext("Error: Invalid arguments to "
94 "retreiveAttrs\n"));
95 return (1);
96 }
97
98 /* retrieve Adapter attributes */
99 memset(attrs, 0, sizeof (HBA_ADAPTERATTRIBUTES));
100 status = HBA_GetAdapterAttributes(handle, attrs);
101 times = 0;
102 while ((status == HBA_STATUS_ERROR_TRY_AGAIN ||
103 status == HBA_STATUS_ERROR_BUSY) &&
104 times++ < HBA_MAX_RETRIES) {
105 (void) sleep(1);
106 status = HBA_GetAdapterAttributes(handle, attrs);
107 if (status == HBA_STATUS_OK) {
108 break;
109 }
110 }
111 if (status != HBA_STATUS_OK) {
112 fprintf(stderr, gettext("Failed to get adapter "
113 "attributes handle(%d) Reason: "), handle);
114 printStatus(status);
115 fprintf(stderr, "\n");
116 return (1);
117 }
118
119 /*
120 * find the corresponding port on the adapter and retrieve
121 * port attributes as well as the port index
122 */
123 memset(port, 0, sizeof (HBA_PORTATTRIBUTES));
124 for (portCtr = 0; portCtr < attrs->NumberOfPorts; portCtr++) {
125 if ((status = HBA_GetAdapterPortAttributes(handle,
126 portCtr, port)) != HBA_STATUS_OK) {
127 fprintf(stderr,
128 gettext("Error: Failed to get port (%d) "
129 "attributes reason: "), portCtr);
130 printStatus(status);
131 fprintf(stderr, "\n");
132 return (1);
133 }
134 if (memcmp(hbaPortWWN.wwn, port->PortWWN.wwn,
135 sizeof (port->PortWWN.wwn)) == 0) {
136 break;
137 }
138 }
139 if (portCtr >= attrs->NumberOfPorts) {
140 /*
141 * not able to find corresponding port WWN
142 * returning an error
143 */
144 *portIndex = 0;
145 return (1);
146 }
147 *portIndex = portCtr;
148 return (0);
149 }
150
151 /*
152 * This function retrieves target mapping information for the HBA port WWN.
153 * This function will allocate space for the mapping structure which the caller
154 * must free when they are finished
155 *
156 * Arguments:
157 * handle - a handle to a HBA that we will be processing
158 * hbaPortWWN - the port WWN for the HBA port to retrieve the mappings for
159 * mapping - a pointer to a pointer for the target mapping structure
160 * Upon successful completion of this function, *mapping will contain
161 * the target mapping information
162 *
163 * returns:
164 * 0 if successful
165 * 1 otherwise
166 */
167 static int
getTargetMapping(HBA_HANDLE handle,HBA_WWN hbaPortWWN,HBA_FCPTARGETMAPPINGV2 ** mapping)168 getTargetMapping(HBA_HANDLE handle, HBA_WWN hbaPortWWN,
169 HBA_FCPTARGETMAPPINGV2 **mapping)
170 {
171 HBA_FCPTARGETMAPPINGV2 *map;
172 HBA_STATUS status;
173 int count;
174
175 /* argument sanity checking */
176 if (mapping == NULL) {
177 fprintf(stderr, gettext("Internal Error: mapping is NULL"));
178 return (1);
179 }
180 *mapping = NULL;
181 if ((map = calloc(1, sizeof (HBA_FCPTARGETMAPPINGV2))) == NULL) {
182 fprintf(stderr,
183 gettext("Internal Error: Unable to calloc map"));
184 return (1);
185 }
186 status = HBA_GetFcpTargetMappingV2(handle, hbaPortWWN, map);
187 count = map->NumberOfEntries;
188 if (status == HBA_STATUS_ERROR_MORE_DATA) {
189 free(map);
190 if ((map = calloc(1, (sizeof (HBA_FCPSCSIENTRYV2)*(count-1)) +
191 sizeof (HBA_FCPTARGETMAPPINGV2))) == NULL) {
192 fprintf(stderr,
193 gettext("Unable to calloc map of size: %d"), count);
194 return (1);
195 }
196 map->NumberOfEntries = count;
197 status = HBA_GetFcpTargetMappingV2(handle, hbaPortWWN, map);
198 }
199 if (status != HBA_STATUS_OK) {
200 fprintf(stderr,
201 gettext("Error: Unable to get Target Mapping\n"));
202 printStatus(status);
203 fprintf(stderr, "\n");
204 free(map);
205 return (1);
206 }
207 *mapping = map;
208 return (0);
209 }
210
211 /*
212 * This function handles the remoteport object. It will issue a report lun
213 * to determine whether it is a scsi-target and then print the information.
214 *
215 * Arguments:
216 * handle - a handle to a HBA that we will be processing
217 * portWWN - the port WWN for the HBA port we will be issuing the SCSI
218 * ReportLUNS through
219 * remotePortWWN - the port WWN we will be issuing the report lun call to
220 * discPort - PORTATTRIBUTES structure for the remotePortWWN
221 */
222 static void
handleRemotePort(HBA_HANDLE handle,HBA_WWN portWWN,HBA_WWN remotePortWWN,HBA_PORTATTRIBUTES * discPort)223 handleRemotePort(HBA_HANDLE handle, HBA_WWN portWWN, HBA_WWN remotePortWWN,
224 HBA_PORTATTRIBUTES *discPort)
225 {
226 HBA_STATUS status;
227 int scsiTargetType;
228 uchar_t raw_luns[LUN_LENGTH];
229 HBA_UINT32 responseSize = LUN_LENGTH;
230 struct scsi_extended_sense sense;
231 HBA_UINT32 senseSize = sizeof (struct scsi_extended_sense);
232 HBA_UINT8 rep_luns_status;
233
234 /* argument checking */
235 if (discPort == NULL) {
236 return;
237 }
238
239 memset(raw_luns, 0, sizeof (raw_luns));
240 /* going to issue a report lun to check if this is a scsi-target */
241 status = HBA_ScsiReportLUNsV2(handle, portWWN, remotePortWWN,
242 (void *)raw_luns, &responseSize, &rep_luns_status,
243 (void *)&sense, &senseSize);
244 if (status == HBA_STATUS_OK) {
245 scsiTargetType = SCSI_TARGET_TYPE_YES;
246 } else if (status == HBA_STATUS_ERROR_NOT_A_TARGET) {
247 scsiTargetType = SCSI_TARGET_TYPE_NO;
248 } else {
249 scsiTargetType = SCSI_TARGET_TYPE_UNKNOWN;
250 }
251 printDiscoPortInfo(discPort, scsiTargetType);
252 }
253
254 /*
255 * This function will issue the RLS and print out the port statistics for
256 * the given destWWN
257 *
258 * Arguments
259 * handle - a handle to a HBA that we will be processing
260 * hbaPortWWN - the hba port WWN through which the RLS will be sent
261 * destWWN - the remote port to which the RLS will be sent
262 */
263 static void
printLinkStat(HBA_HANDLE handle,HBA_WWN hbaPortWWN,HBA_WWN destWWN)264 printLinkStat(HBA_HANDLE handle, HBA_WWN hbaPortWWN, HBA_WWN destWWN)
265 {
266 HBA_STATUS status;
267 fc_rls_acc_t rls_payload;
268 uint32_t rls_payload_size;
269
270 memset(&rls_payload, 0, sizeof (rls_payload));
271 rls_payload_size = sizeof (rls_payload);
272 status = HBA_SendRLS(handle, hbaPortWWN, destWWN,
273 &rls_payload, &rls_payload_size);
274 if (status != HBA_STATUS_OK) {
275 fprintf(stderr, gettext("Error: SendRLS failed for %016llx\n"),
276 wwnConversion(destWWN.wwn));
277 } else {
278 printPortStat(&rls_payload);
279 }
280 }
281
282 int
printHBANPIVPortInfo(HBA_HANDLE handle,int portindex)283 printHBANPIVPortInfo(HBA_HANDLE handle, int portindex)
284 {
285 HBA_PORTNPIVATTRIBUTES portattrs;
286 HBA_NPIVATTRIBUTES npivattrs;
287 HBA_STATUS status;
288 int index;
289 int times = 0;
290
291 status = Sun_HBA_GetPortNPIVAttributes(handle, portindex, &portattrs);
292 while (status == HBA_STATUS_ERROR_TRY_AGAIN ||
293 status == HBA_STATUS_ERROR_BUSY) {
294 (void) sleep(1);
295 status = Sun_HBA_GetPortNPIVAttributes(
296 handle, portindex, &portattrs);
297 if (times++ > HBA_MAX_RETRIES) {
298 break;
299 }
300 }
301
302 if (status == HBA_STATUS_ERROR_NOT_SUPPORTED) {
303 fprintf(stdout, gettext("\tNPIV Not Supported\n"));
304 return (0);
305 }
306
307 if (status != HBA_STATUS_OK) {
308 fprintf(stderr,
309 gettext("Error: Failed to get port (%d) "
310 "npiv attributes reason: "), portindex);
311 printStatus(status);
312 fprintf(stderr, "\n");
313 return (1);
314 }
315 if (portattrs.MaxNumberOfNPIVPorts) {
316 fprintf(stdout, gettext("\tMax NPIV Ports: %d\n"),
317 portattrs.MaxNumberOfNPIVPorts);
318 } else {
319 fprintf(stdout, gettext("\tNPIV Not Supported\n"));
320 return (0);
321 }
322 fprintf(stdout, gettext("\tNPIV port list:\n"));
323 for (index = 0; index < portattrs.NumberOfNPIVPorts; index++) {
324 int times = 0;
325 status = Sun_HBA_GetNPIVPortInfo(handle,
326 portindex, index, &npivattrs);
327 while (status == HBA_STATUS_ERROR_TRY_AGAIN ||
328 status == HBA_STATUS_ERROR_BUSY) {
329 (void) sleep(1);
330 status = Sun_HBA_GetNPIVPortInfo(handle,
331 portindex, index, &npivattrs);
332 if (times++ > HBA_MAX_RETRIES) {
333 break;
334 }
335 }
336
337 if (status != HBA_STATUS_OK) {
338 fprintf(stderr,
339 gettext("Error: Failed to get npiv port (%d) "
340 "attributes reason: "), index);
341 printStatus(status);
342 fprintf(stderr, "\n");
343 return (1);
344 } else {
345 fprintf(stdout,
346 gettext("\t Virtual Port%d:\n"), index+1);
347 fprintf(stdout, gettext("\t\tNode WWN: %016llx\n"),
348 wwnConversion(npivattrs.NodeWWN.wwn));
349 fprintf(stdout, gettext("\t\tPort WWN: %016llx\n"),
350 wwnConversion(npivattrs.PortWWN.wwn));
351 }
352 }
353 return (0);
354 }
355
356 /*
357 * This function will process hba port, remote port and scsi-target information
358 * for the given handle.
359 *
360 * Arguments:
361 * handle - a handle to a HBA that we will be processing
362 * resourceType - resourceType flag
363 * possible values include: HBA_PORT, REMOTE_PORT
364 * flags - represents options passed in by the user
365 *
366 * Return Value:
367 * 0 sucessfully processed handle
368 * 1 error has occured
369 */
370 static int
processHBA(HBA_HANDLE handle,HBA_ADAPTERATTRIBUTES attrs,int portIndex,HBA_PORTATTRIBUTES port,HBA_FCPTARGETMAPPINGV2 * map,int resourceType,int flags,int mode)371 processHBA(HBA_HANDLE handle, HBA_ADAPTERATTRIBUTES attrs, int portIndex,
372 HBA_PORTATTRIBUTES port, HBA_FCPTARGETMAPPINGV2 *map,
373 int resourceType, int flags, int mode)
374 {
375 HBA_PORTATTRIBUTES discPort;
376 HBA_STATUS status;
377 int discPortCount;
378
379 if (resourceType == HBA_PORT) {
380 if ((flags & PRINT_FCOE) == PRINT_FCOE &&
381 attrs.VendorSpecificID != 0xFC0E) {
382 return (0);
383 }
384 printHBAPortInfo(&port, &attrs, mode);
385 if ((flags & PRINT_LINKSTAT) == PRINT_LINKSTAT) {
386 printLinkStat(handle, port.PortWWN, port.PortWWN);
387 }
388 return (0);
389 }
390 /*
391 * process each of the remote targets from this hba port
392 */
393 for (discPortCount = 0;
394 discPortCount < port.NumberofDiscoveredPorts;
395 discPortCount++) {
396 status = HBA_GetDiscoveredPortAttributes(handle,
397 portIndex, discPortCount, &discPort);
398 if (status != HBA_STATUS_OK) {
399 fprintf(stderr,
400 gettext("Failed to get discovered port (%d)"
401 " attributes reason :"), discPortCount);
402 printStatus(status);
403 fprintf(stderr, "\n");
404 continue;
405 }
406 if (resourceType == REMOTE_PORT) {
407 handleRemotePort(handle, port.PortWWN, discPort.PortWWN,
408 &discPort);
409 if ((flags & PRINT_LINKSTAT) == PRINT_LINKSTAT) {
410 printLinkStat(handle, port.PortWWN,
411 discPort.PortWWN);
412 }
413 if ((flags & PRINT_SCSI_TARGET) == PRINT_SCSI_TARGET) {
414 handleScsiTarget(handle, port.PortWWN,
415 discPort.PortWWN, map);
416 }
417 }
418 }
419 return (0);
420 }
421
422 /*
423 * This function will process remote port information for the given handle.
424 *
425 * Arguments:
426 * handle - a handle to a HBA that we will be processing
427 * portWWN - the port WWN for the HBA port we will be issuing the SCSI
428 * ReportLUNS through
429 * wwnCount - the number of wwns in wwn_argv
430 * wwn_argv - argument vector of WWNs
431 */
432 static void
processRemotePort(HBA_HANDLE handle,HBA_WWN portWWN,HBA_FCPTARGETMAPPINGV2 * map,int wwnCount,char ** wwn_argv,int flags)433 processRemotePort(HBA_HANDLE handle, HBA_WWN portWWN,
434 HBA_FCPTARGETMAPPINGV2 *map, int wwnCount, char **wwn_argv, int flags)
435 {
436 int remote_wwn_counter;
437 uint64_t remotePortWWN;
438 HBA_WWN myremotePortWWN;
439 HBA_PORTATTRIBUTES discPort;
440 HBA_STATUS status;
441
442 for (remote_wwn_counter = 0;
443 remote_wwn_counter < wwnCount;
444 remote_wwn_counter++) {
445 int times = 0;
446 sscanf(wwn_argv[remote_wwn_counter], "%016llx",
447 &remotePortWWN);
448 remotePortWWN = htonll(remotePortWWN);
449 memcpy(myremotePortWWN.wwn, &remotePortWWN,
450 sizeof (remotePortWWN));
451 memset(&discPort, 0, sizeof (discPort));
452 status = HBA_GetPortAttributesByWWN(handle, myremotePortWWN,
453 &discPort);
454 while (status == HBA_STATUS_ERROR_TRY_AGAIN ||
455 status == HBA_STATUS_ERROR_BUSY) {
456 (void) sleep(1);
457 status = HBA_GetPortAttributesByWWN(handle,
458 myremotePortWWN, &discPort);
459 if (times++ > HBA_MAX_RETRIES) {
460 break;
461 }
462 }
463 if (status != HBA_STATUS_OK) {
464 fprintf(stderr, gettext("HBA_GetPortAttributesByWWN "
465 "failed: reason: "));
466 printStatus(status);
467 fprintf(stderr, "\n");
468 continue;
469 }
470 handleRemotePort(handle, portWWN, myremotePortWWN, &discPort);
471 if ((flags & PRINT_LINKSTAT) == PRINT_LINKSTAT) {
472 printLinkStat(handle, portWWN, myremotePortWWN);
473 }
474 if ((flags & PRINT_SCSI_TARGET) == PRINT_SCSI_TARGET) {
475 handleScsiTarget(handle, portWWN,
476 myremotePortWWN, map);
477 }
478 }
479 }
480
481 /*
482 * This function handles printing Scsi target information for remote ports
483 *
484 * Arguments:
485 * handle - a handle to a HBA that we will be processing
486 * hbaPortWWN - the port WWN for the HBA port through which the SCSI call
487 * is being sent
488 * scsiTargetWWN - target port WWN of the remote target the SCSI call is
489 * being sent to
490 * map - a pointer to the target mapping structure for the given HBA port
491 */
492 static void
handleScsiTarget(HBA_HANDLE handle,HBA_WWN hbaPortWWN,HBA_WWN scsiTargetWWN,HBA_FCPTARGETMAPPINGV2 * map)493 handleScsiTarget(HBA_HANDLE handle, HBA_WWN hbaPortWWN, HBA_WWN scsiTargetWWN,
494 HBA_FCPTARGETMAPPINGV2 *map)
495 {
496 HBA_STATUS status;
497 struct scsi_inquiry inq;
498 struct scsi_extended_sense sense;
499 HBA_UINT32 responseSize, senseSize = 0;
500 HBA_UINT8 inq_status;
501 uchar_t raw_luns[DEFAULT_LUN_LENGTH], *lun_string;
502 HBA_UINT8 rep_luns_status;
503 rep_luns_rsp_t *lun_resp;
504 uint64_t fcLUN;
505 int lunNum, numberOfLun, lunCount, count;
506 uint32_t lunlength, tmp_lunlength;
507
508 responseSize = DEFAULT_LUN_LENGTH;
509 senseSize = sizeof (struct scsi_extended_sense);
510 memset(&sense, 0, sizeof (sense));
511 status = HBA_ScsiReportLUNsV2(handle, hbaPortWWN,
512 scsiTargetWWN, (void *)raw_luns, &responseSize,
513 &rep_luns_status, (void *)&sense, &senseSize);
514 /*
515 * if HBA_STATUS_ERROR_NOT_A_TARGET is return, we can assume this is
516 * a remote HBA and move on
517 */
518 if (status == HBA_STATUS_ERROR_NOT_A_TARGET) {
519 return;
520 } else if (status != HBA_STATUS_OK) {
521 fprintf(stderr, gettext("Error has occured. "
522 "HBA_ScsiReportLUNsV2 failed. reason "));
523 printStatus(status);
524 fprintf(stderr, "\n");
525 return;
526 }
527 lun_resp = (rep_luns_rsp_t *)raw_luns;
528 memcpy(&tmp_lunlength, &(lun_resp->length), sizeof (tmp_lunlength));
529 lunlength = htonl(tmp_lunlength);
530 memcpy(&numberOfLun, &lunlength, sizeof (numberOfLun));
531 for (lunCount = 0; lunCount < (numberOfLun / 8); lunCount++) {
532 /*
533 * now issue standard inquiry to get Vendor
534 * and product information
535 */
536 responseSize = sizeof (struct scsi_inquiry);
537 senseSize = sizeof (struct scsi_extended_sense);
538 memset(&inq, 0, sizeof (struct scsi_inquiry));
539 memset(&sense, 0, sizeof (sense));
540 fcLUN = ntohll(wwnConversion(lun_resp->lun[lunCount].val));
541 status = HBA_ScsiInquiryV2(
542 handle,
543 hbaPortWWN,
544 scsiTargetWWN,
545 fcLUN,
546 0, /* EVPD */
547 0,
548 &inq, &responseSize,
549 &inq_status,
550 &sense, &senseSize);
551 if (status != HBA_STATUS_OK) {
552 fprintf(stderr, gettext("Not able to issue Inquiry.\n"));
553 printStatus(status);
554 fprintf(stderr, "\n");
555 strcpy(inq.inq_vid, "Unknown");
556 strcpy(inq.inq_pid, "Unknown");
557 }
558 if (map != NULL) {
559 for (count = 0; count < map->NumberOfEntries; count++) {
560 if ((memcmp(map->entry[count].FcpId.PortWWN.wwn,
561 scsiTargetWWN.wwn,
562 sizeof (scsiTargetWWN.wwn))
563 == 0) &&
564 (memcmp(&(map->entry[count].FcpId.FcpLun),
565 &fcLUN, sizeof (fcLUN)) == 0)) {
566 printLUNInfo(&inq,
567 map->entry[count].ScsiId.ScsiOSLun,
568 map->entry[count].ScsiId.OSDeviceName);
569 break;
570 }
571 }
572 if (count == map->NumberOfEntries) {
573 lun_string = lun_resp->lun[lunCount].val;
574 lunNum = ((lun_string[0] & 0x3F) << 8) |
575 lun_string[1];
576 printLUNInfo(&inq, lunNum, "Unknown");
577 }
578 } else {
579 /* Not able to get any target mapping information */
580 lun_string = lun_resp->lun[lunCount].val;
581 lunNum = ((lun_string[0] & 0x3F) << 8) |
582 lun_string[1];
583 printLUNInfo(&inq, lunNum, "Unknown");
584 }
585 }
586 }
587
588 /*
589 * function to handle the list remoteport command
590 *
591 * Arguments:
592 * wwnCount - the number of wwns in wwn_argv
593 * if wwnCount == 0, then print information on all
594 * remote ports. wwn_argv will not be used in this case
595 * if wwnCount > 0, then print information for the WWNs
596 * given in wwn_argv
597 * wwn_argv - argument vector of WWNs
598 * options - any options specified by the caller
599 *
600 * returns:
601 * 0 if successful
602 * 1 otherwise
603 */
604 int
fc_util_list_remoteport(int wwnCount,char ** wwn_argv,cmdOptions_t * options)605 fc_util_list_remoteport(int wwnCount, char **wwn_argv, cmdOptions_t *options)
606 {
607 HBA_STATUS status;
608 HBA_FCPTARGETMAPPINGV2 *map = NULL;
609 HBA_PORTATTRIBUTES port;
610 HBA_ADAPTERATTRIBUTES attrs;
611 HBA_HANDLE handle;
612 uint64_t hbaPortWWN;
613 HBA_WWN myhbaPortWWN;
614 int processHBA_flags = 0, portCount = 0;
615 int mode;
616
617 /* grab the hba port wwn from the -p option */
618 for (; options->optval; options++) {
619 if (options->optval == 'p') {
620 sscanf(options->optarg, "%016llx",
621 &hbaPortWWN);
622 } else if (options->optval == 's') {
623 processHBA_flags |= PRINT_SCSI_TARGET;
624 } else if (options->optval == 'l') {
625 processHBA_flags |= PRINT_LINKSTAT;
626 } else {
627 fprintf(stderr, gettext("Error: Illegal option: %c.\n"),
628 options->optval);
629 return (1);
630 }
631 }
632 /*
633 * -h option was not specified, this should not happen either.
634 * cmdparse should catch this problem, but checking anyways
635 */
636 if (hbaPortWWN == 0) {
637 fprintf(stderr,
638 gettext("Error: -p option was not specified.\n"));
639 return (1);
640 }
641 if ((status = HBA_LoadLibrary()) != HBA_STATUS_OK) {
642 fprintf(stderr,
643 gettext("Failed to load FC-HBA common library\n"));
644 printStatus(status);
645 fprintf(stderr, "\n");
646 return (1);
647 }
648 hbaPortWWN = htonll(hbaPortWWN);
649 memcpy(myhbaPortWWN.wwn, &hbaPortWWN, sizeof (hbaPortWWN));
650 if ((status = HBA_OpenAdapterByWWN(&handle, myhbaPortWWN))
651 != HBA_STATUS_OK) {
652 status = Sun_HBA_OpenTgtAdapterByWWN(&handle, myhbaPortWWN);
653 if (status != HBA_STATUS_OK) {
654 fprintf(stderr,
655 gettext("Error: Failed to open adapter port. Reason "));
656 printStatus(status);
657 fprintf(stderr, "\n");
658 HBA_FreeLibrary();
659 return (1);
660 } else {
661 if ((processHBA_flags & PRINT_SCSI_TARGET) ==
662 PRINT_SCSI_TARGET) {
663 fprintf(stderr, gettext(
664 "Error: Unsupported option for target mode: %c.\n"),
665 's');
666 HBA_FreeLibrary();
667 return (1);
668 }
669 mode = TARGET_MODE;
670 }
671 } else {
672 mode = INITIATOR_MODE;
673 }
674
675 if ((processHBA_flags & PRINT_SCSI_TARGET) == PRINT_SCSI_TARGET) {
676 getTargetMapping(handle, myhbaPortWWN, &map);
677 }
678 if (wwnCount == 0) {
679 /* get adapater attributes for the given handle */
680 memset(&attrs, 0, sizeof (attrs));
681 memset(&port, 0, sizeof (port));
682 if (retrieveAttrs(handle, myhbaPortWWN, &attrs, &port,
683 &portCount) != 0) {
684 if (map != NULL) {
685 free(map);
686 }
687 HBA_CloseAdapter(handle);
688 HBA_FreeLibrary();
689 return (1);
690 }
691 processHBA(handle, attrs, portCount, port, map, REMOTE_PORT,
692 processHBA_flags, mode);
693 } else {
694 processRemotePort(handle, myhbaPortWWN, map, wwnCount,
695 wwn_argv, processHBA_flags);
696 }
697 if (map != NULL) {
698 free(map);
699 }
700 HBA_CloseAdapter(handle);
701 HBA_FreeLibrary();
702 return (0);
703 }
704
705 /*
706 * process the hbaport object
707 *
708 * Arguments:
709 * wwnCount - count of the number of WWNs in wwn_argv
710 * if wwnCount > 0, then we will only print information for
711 * the hba ports listed in wwn_argv
712 * if wwnCount == 0, then we will print information on all hba ports
713 * wwn_argv - argument array of hba port WWNs
714 * options - any options specified by the caller
715 *
716 * returns:
717 * 0 if successful
718 * 1 otherwise
719 */
720 int
fc_util_list_hbaport(int wwnCount,char ** wwn_argv,cmdOptions_t * options)721 fc_util_list_hbaport(int wwnCount, char **wwn_argv, cmdOptions_t *options)
722 {
723 int port_wwn_counter, numAdapters = 0, numTgtAdapters = 0, i;
724 HBA_STATUS status;
725 char adapterName[256];
726 HBA_HANDLE handle;
727 uint64_t hbaWWN;
728 HBA_WWN myWWN;
729 int processHBA_flags = 0;
730 HBA_PORTATTRIBUTES port;
731 HBA_ADAPTERATTRIBUTES attrs;
732 int portIndex = 0, err_cnt = 0;
733 int mode;
734
735 /* process each of the options */
736 for (; options->optval; options++) {
737 if (options->optval == 'l') {
738 processHBA_flags |= PRINT_LINKSTAT;
739 } else if (options->optval == 'i') {
740 processHBA_flags |= PRINT_INITIATOR;
741 } else if (options->optval == 't') {
742 processHBA_flags |= PRINT_TARGET;
743 } else if (options->optval == 'e') {
744 processHBA_flags |= PRINT_FCOE;
745 }
746 }
747
748 /*
749 * Print both initiator and target if no initiator/target flag
750 * specified.
751 */
752 if (((processHBA_flags & PRINT_INITIATOR) == 0) &&
753 ((processHBA_flags & PRINT_TARGET) == 0)) {
754 processHBA_flags |= PRINT_INITIATOR | PRINT_TARGET;
755 }
756
757 if ((status = HBA_LoadLibrary()) != HBA_STATUS_OK) {
758 fprintf(stderr,
759 gettext("Failed to load FC-HBA common library\n"));
760 printStatus(status);
761 fprintf(stderr, "\n");
762 return (1);
763 }
764 if (wwnCount > 0) {
765 /* list only ports given in wwn_argv */
766 for (port_wwn_counter = 0;
767 port_wwn_counter < wwnCount;
768 port_wwn_counter++) {
769 sscanf(wwn_argv[port_wwn_counter], "%016llx", &hbaWWN);
770 hbaWWN = htonll(hbaWWN);
771 memcpy(myWWN.wwn, &hbaWWN, sizeof (hbaWWN));
772 /* first check to see if it is an initiator port. */
773 if ((processHBA_flags & PRINT_INITIATOR) ==
774 PRINT_INITIATOR) {
775 int times = 0;
776 status = HBA_OpenAdapterByWWN(&handle, myWWN);
777 while (status == HBA_STATUS_ERROR_TRY_AGAIN ||
778 status == HBA_STATUS_ERROR_BUSY) {
779 (void) sleep(1);
780 status = HBA_OpenAdapterByWWN(&handle, myWWN);
781 if (times++ > HBA_MAX_RETRIES) {
782 break;
783 }
784 }
785 if (status != HBA_STATUS_OK) {
786 /* now see if it is a target mode FC port */
787 if ((processHBA_flags & PRINT_TARGET) ==
788 PRINT_TARGET) {
789 status =
790 Sun_HBA_OpenTgtAdapterByWWN(&handle, myWWN);
791 if (status != HBA_STATUS_OK) {
792 fprintf(stderr,
793 gettext(
794 "Error: HBA port %s: not found\n"),
795 wwn_argv[port_wwn_counter]);
796 err_cnt++;
797 continue;
798 } else {
799 /* set the port mode. */
800 mode = TARGET_MODE;
801 }
802 } else {
803 fprintf(stderr,
804 gettext(
805 "Error: HBA port %s: not found\n"),
806 wwn_argv[port_wwn_counter]);
807 err_cnt++;
808 continue;
809 }
810 } else {
811 /* set the port mode. */
812 mode = INITIATOR_MODE;
813 }
814 /* try target mode discovery if print target is set. */
815 } else if ((processHBA_flags & PRINT_TARGET) ==
816 PRINT_TARGET) {
817 status =
818 Sun_HBA_OpenTgtAdapterByWWN(&handle, myWWN);
819 if (status != HBA_STATUS_OK) {
820 fprintf(stderr, gettext(
821 "Error: HBA port %s: not found\n"),
822 wwn_argv[port_wwn_counter]);
823 err_cnt++;
824 continue;
825 } else {
826 /* set the port mode. */
827 mode = TARGET_MODE;
828 }
829 } else {
830 /* should not get here. */
831 fprintf(stderr, gettext(
832 "Error: HBA port %s: not found\n"),
833 wwn_argv[port_wwn_counter]);
834 err_cnt++;
835 continue;
836 }
837 memset(&attrs, 0, sizeof (attrs));
838 memset(&port, 0, sizeof (port));
839 if (retrieveAttrs(handle, myWWN, &attrs, &port,
840 &portIndex) != 0) {
841 HBA_CloseAdapter(handle);
842 continue;
843 }
844 processHBA(handle, attrs, portIndex, port, NULL,
845 HBA_PORT, processHBA_flags, mode);
846 if ((processHBA_flags & PRINT_FCOE) != PRINT_FCOE &&
847 attrs.VendorSpecificID != 0xFC0E &&
848 printHBANPIVPortInfo(handle, portIndex) != 0) {
849 err_cnt++;
850 }
851 HBA_CloseAdapter(handle);
852 }
853 } else {
854 /*
855 * if PRINT_INITIATOR is specified, get the list of initiator
856 * mod port.
857 */
858 if ((processHBA_flags & PRINT_INITIATOR) == PRINT_INITIATOR) {
859 numAdapters = HBA_GetNumberOfAdapters();
860 if ((numAdapters == 0) &&
861 ((processHBA_flags & ~PRINT_INITIATOR) == 0)) {
862 fprintf(stdout, gettext("No Adapters Found.\n"));
863 }
864 for (i = 0; i < numAdapters; i++) {
865 int times = 0;
866 status = HBA_GetAdapterName(i, adapterName);
867 if (status != HBA_STATUS_OK) {
868 fprintf(stderr, gettext(
869 "failed to get adapter %d. Reason: "), i);
870 printStatus(status);
871 fprintf(stderr, "\n");
872 continue;
873 }
874 if ((handle = HBA_OpenAdapter(adapterName)) == 0) {
875 fprintf(stderr, gettext(
876 "Failed to open adapter %s.\n"),
877 adapterName);
878 continue;
879 }
880 /* get adapater attributes for the given handle */
881 memset(&attrs, 0, sizeof (attrs));
882 status =
883 Sun_HBA_NPIVGetAdapterAttributes(handle,
884 &attrs);
885 while ((status == HBA_STATUS_ERROR_TRY_AGAIN ||
886 status == HBA_STATUS_ERROR_BUSY) &&
887 times++ < HBA_MAX_RETRIES) {
888 (void) sleep(1);
889 status =
890 Sun_HBA_NPIVGetAdapterAttributes(handle,
891 &attrs);
892 if (status == HBA_STATUS_OK) {
893 break;
894 }
895 }
896 if (status != HBA_STATUS_OK) {
897 fprintf(stderr,
898 gettext("Failed to get adapter attributes "
899 "handle(%d) Reason: "), handle);
900 printStatus(status);
901 fprintf(stderr, "\n");
902 HBA_CloseAdapter(handle);
903 continue;
904 }
905
906 /* process each port on the given adatpter */
907 for (portIndex = 0;
908 portIndex < attrs.NumberOfPorts;
909 portIndex++) {
910 memset(&port, 0, sizeof (port));
911 if ((status = HBA_GetAdapterPortAttributes(
912 handle, portIndex, &port))
913 != HBA_STATUS_OK) {
914 /*
915 * not able to get port attributes.
916 * print out error * message and move
917 * on to the next port
918 */
919 fprintf(stderr,
920 gettext("Error: Failed to get port "
921 "(%d) attributes reason: "),
922 portIndex);
923 printStatus(status);
924 fprintf(stderr, "\n");
925 continue;
926 }
927 processHBA(handle, attrs, portIndex, port,
928 NULL, HBA_PORT, processHBA_flags,
929 INITIATOR_MODE);
930 if ((processHBA_flags & PRINT_FCOE) !=
931 PRINT_FCOE &&
932 attrs.VendorSpecificID != 0xFC0E &&
933 printHBANPIVPortInfo(handle,
934 portIndex) != 0) {
935 err_cnt++;
936 }
937 }
938 HBA_CloseAdapter(handle);
939 }
940 }
941
942 /*
943 * Get the info on the target mode FC port if PRINT_TARGET
944 * is specified.
945 */
946 if ((processHBA_flags & PRINT_TARGET) == PRINT_TARGET) {
947 numTgtAdapters = Sun_HBA_GetNumberOfTgtAdapters();
948 if (numTgtAdapters == 0 && numAdapters == 0) {
949 fprintf(stdout,
950 gettext("No Adapters Found.\n"));
951 }
952 for (i = 0; i < numTgtAdapters; i++) {
953 status = Sun_HBA_GetTgtAdapterName(i, adapterName);
954 if (status != HBA_STATUS_OK) {
955 fprintf(stderr, gettext(
956 "failed to get adapter %d. Reason: "), i);
957 printStatus(status);
958 fprintf(stderr, "\n");
959 continue;
960 }
961 if ((handle = Sun_HBA_OpenTgtAdapter(adapterName))
962 == 0) {
963 fprintf(stderr, gettext(
964 "Failed to open adapter %s.\n"), adapterName);
965 continue;
966 }
967 /* get adapater attributes for the given handle */
968 memset(&attrs, 0, sizeof (attrs));
969 if ((status = HBA_GetAdapterAttributes(handle, &attrs))
970 != HBA_STATUS_OK) {
971 fprintf(stderr,
972 gettext("Failed to get target mode adapter"
973 "attributes handle(%d) Reason: "),
974 handle);
975 printStatus(status);
976 fprintf(stderr, "\n");
977 continue;
978 }
979
980 /* process each port on the given adatpter */
981 for (portIndex = 0;
982 portIndex < attrs.NumberOfPorts;
983 portIndex++) {
984 memset(&port, 0, sizeof (port));
985 if ((status = HBA_GetAdapterPortAttributes(
986 handle, portIndex, &port))
987 != HBA_STATUS_OK) {
988 /*
989 * not able to get port attributes.
990 * print out error * message and move
991 * on to the next port
992 */
993 fprintf(stderr,
994 gettext("Error: Failed to get port "
995 "(%d) attributes reason: "),
996 portIndex);
997 printStatus(status);
998 fprintf(stderr, "\n");
999 continue;
1000 }
1001 processHBA(handle, attrs, portIndex, port,
1002 NULL, HBA_PORT, processHBA_flags,
1003 TARGET_MODE);
1004 }
1005 HBA_CloseAdapter(handle);
1006 }
1007 }
1008 }
1009
1010 HBA_FreeLibrary();
1011
1012 /*
1013 * print additional error msg for partial failure when more than
1014 * one wwn is specified.
1015 */
1016 if (err_cnt != 0) {
1017 if (wwnCount > 1) {
1018 if (err_cnt == wwnCount) {
1019 fprintf(stderr, gettext(
1020 "Error: All specified HBA ports are not found\n"));
1021 } else {
1022 fprintf(stderr, gettext(
1023 "Error: Some of specified HBA ports are not found\n"));
1024 }
1025 }
1026 return (1);
1027 }
1028
1029 return (0);
1030 }
1031
1032 /*
1033 * Search the existing device list
1034 *
1035 * Take one of two actions:
1036 *
1037 * Add an entry if an entry doesn't exist
1038 * Add WWN data to it if an entry does exist
1039 *
1040 * Arguments:
1041 * devList - OS device path list
1042 * map - target mapping data
1043 * index - index into target mapping data
1044 * initiatorPortWWN - HBA port WWN
1045 * verbose - boolean indicating whether to get additional data
1046 *
1047 * returns:
1048 * none
1049 */
1050 static void
searchDevice(discoveredDevice ** devList,HBA_FCPSCSIENTRYV2 entry,HBA_WWN initiatorPortWWN,HBA_HANDLE handle,boolean_t verbose)1051 searchDevice(discoveredDevice **devList, HBA_FCPSCSIENTRYV2 entry,
1052 HBA_WWN initiatorPortWWN, HBA_HANDLE handle, boolean_t verbose)
1053 {
1054 discoveredDevice *discoveredDevList, *newDevice;
1055 portWWNList *WWNList, *newWWN;
1056 tgtPortWWNList *newTgtWWN;
1057 boolean_t foundDevice = B_FALSE, foundWWN;
1058 struct scsi_inquiry inq;
1059 struct scsi_extended_sense sense;
1060 HBA_UINT32 responseSize, senseSize = 0;
1061 HBA_UINT8 inq_status;
1062 HBA_STATUS status;
1063
1064 for (discoveredDevList = *devList; discoveredDevList != NULL;
1065 discoveredDevList = discoveredDevList->next) {
1066 if (strcmp(entry.ScsiId.OSDeviceName,
1067 discoveredDevList->OSDeviceName) == 0) {
1068 /*
1069 * if only device names are requested,
1070 * no reason to go any further
1071 */
1072 if (verbose == B_FALSE) {
1073 return;
1074 }
1075 foundDevice = B_TRUE;
1076 break;
1077 }
1078 }
1079 if (foundDevice == B_TRUE) {
1080 /* add initiator Port WWN if it doesn't exist */
1081 for (WWNList = discoveredDevList->HBAPortWWN,
1082 foundWWN = B_FALSE; WWNList != NULL;
1083 WWNList = WWNList->next) {
1084 if (memcmp((void *)&(WWNList->portWWN),
1085 (void *)&initiatorPortWWN,
1086 sizeof (HBA_WWN)) == 0) {
1087 foundWWN = B_TRUE;
1088 break;
1089 }
1090 }
1091 if (discoveredDevList->inqSuccess == B_FALSE) {
1092 responseSize = sizeof (struct scsi_inquiry);
1093 senseSize = sizeof (struct scsi_extended_sense);
1094 memset(&inq, 0, sizeof (struct scsi_inquiry));
1095 memset(&sense, 0, sizeof (sense));
1096 status = HBA_ScsiInquiryV2(
1097 handle,
1098 initiatorPortWWN,
1099 entry.FcpId.PortWWN,
1100 entry.FcpId.FcpLun,
1101 0, /* CDB Byte 1 */
1102 0, /* CDB Byte 2 */
1103 &inq, &responseSize,
1104 &inq_status,
1105 &sense, &senseSize);
1106 if (status == HBA_STATUS_OK) {
1107 memcpy(discoveredDevList->VID, inq.inq_vid,
1108 sizeof (discoveredDevList->VID));
1109 memcpy(discoveredDevList->PID, inq.inq_pid,
1110 sizeof (discoveredDevList->PID));
1111 discoveredDevList->dType = inq.inq_dtype;
1112 discoveredDevList->inqSuccess = B_TRUE;
1113 }
1114 }
1115
1116 if (foundWWN == B_FALSE) {
1117 newWWN = (portWWNList *)calloc(1, sizeof (portWWNList));
1118 if (newWWN == NULL) {
1119 perror("Out of memory");
1120 exit(1);
1121 }
1122
1123 /* insert at head */
1124 newWWN->next = discoveredDevList->HBAPortWWN;
1125 discoveredDevList->HBAPortWWN = newWWN;
1126 memcpy((void *)&(newWWN->portWWN),
1127 (void *)&initiatorPortWWN,
1128 sizeof (newWWN->portWWN));
1129 /* add Target Port */
1130 newWWN->tgtPortWWN = (tgtPortWWNList *)calloc(1,
1131 sizeof (tgtPortWWNList));
1132 if (newWWN->tgtPortWWN == NULL) {
1133 perror("Out of memory");
1134 exit(1);
1135 }
1136
1137 memcpy((void *)&(newWWN->tgtPortWWN->portWWN),
1138 (void *)&(entry.FcpId.PortWWN),
1139 sizeof (newWWN->tgtPortWWN->portWWN));
1140 /* Set LUN data */
1141 newWWN->tgtPortWWN->scsiOSLun = entry.ScsiId.ScsiOSLun;
1142 } else { /* add it to existing */
1143 newTgtWWN = (tgtPortWWNList *)calloc(1,
1144 sizeof (tgtPortWWNList));
1145 if (newTgtWWN == NULL) {
1146 perror("Out of memory");
1147 exit(1);
1148 }
1149 /* insert at head */
1150 newTgtWWN->next = WWNList->tgtPortWWN;
1151 WWNList->tgtPortWWN = newTgtWWN;
1152 memcpy((void *)&(newTgtWWN->portWWN),
1153 (void *)&(entry.FcpId.PortWWN),
1154 sizeof (newTgtWWN->portWWN));
1155 /* Set LUN data */
1156 newTgtWWN->scsiOSLun = entry.ScsiId.ScsiOSLun;
1157 }
1158 } else { /* add new entry */
1159 newDevice = (discoveredDevice *)calloc(1,
1160 sizeof (discoveredDevice));
1161 if (newDevice == NULL) {
1162 perror("Out of memory");
1163 exit(1);
1164 }
1165 newDevice->next = *devList; /* insert at head */
1166 *devList = newDevice; /* set new head */
1167
1168 /* Copy device name */
1169 strncpy(newDevice->OSDeviceName, entry.ScsiId.OSDeviceName,
1170 sizeof (newDevice->OSDeviceName) - 1);
1171
1172 /*
1173 * if only device names are requested,
1174 * no reason to go any further
1175 */
1176 if (verbose == B_FALSE) {
1177 return;
1178 }
1179
1180 /*
1181 * copy WWN data
1182 */
1183 newDevice->HBAPortWWN = (portWWNList *)calloc(1,
1184 sizeof (portWWNList));
1185 if (newDevice->HBAPortWWN == NULL) {
1186 perror("Out of memory");
1187 exit(1);
1188 }
1189 memcpy((void *)&(newDevice->HBAPortWWN->portWWN),
1190 (void *)&initiatorPortWWN, sizeof (newWWN->portWWN));
1191
1192 newDevice->HBAPortWWN->tgtPortWWN =
1193 (tgtPortWWNList *)calloc(1, sizeof (tgtPortWWNList));
1194 if (newDevice->HBAPortWWN->tgtPortWWN == NULL) {
1195 perror("Out of memory");
1196 exit(1);
1197 }
1198
1199 memcpy((void *)&(newDevice->HBAPortWWN->tgtPortWWN->portWWN),
1200 (void *)&(entry.FcpId.PortWWN),
1201 sizeof (newDevice->HBAPortWWN->tgtPortWWN->portWWN));
1202
1203 /* Set LUN data */
1204 newDevice->HBAPortWWN->tgtPortWWN->scsiOSLun =
1205 entry.ScsiId.ScsiOSLun;
1206
1207 responseSize = sizeof (struct scsi_inquiry);
1208 senseSize = sizeof (struct scsi_extended_sense);
1209 memset(&inq, 0, sizeof (struct scsi_inquiry));
1210 memset(&sense, 0, sizeof (sense));
1211 status = HBA_ScsiInquiryV2(
1212 handle,
1213 initiatorPortWWN,
1214 entry.FcpId.PortWWN,
1215 entry.FcpId.FcpLun,
1216 0, /* CDB Byte 1 */
1217 0, /* CDB Byte 2 */
1218 &inq, &responseSize,
1219 &inq_status,
1220 &sense, &senseSize);
1221 if (status != HBA_STATUS_OK) {
1222 /* initialize VID/PID/dType as "Unknown" */
1223 strcpy(newDevice->VID, "Unknown");
1224 strcpy(newDevice->PID, "Unknown");
1225 newDevice->dType = DTYPE_UNKNOWN;
1226 /* initialize inq status */
1227 newDevice->inqSuccess = B_FALSE;
1228 } else {
1229 memcpy(newDevice->VID, inq.inq_vid,
1230 sizeof (newDevice->VID));
1231 memcpy(newDevice->PID, inq.inq_pid,
1232 sizeof (newDevice->PID));
1233 newDevice->dType = inq.inq_dtype;
1234 /* initialize inq status */
1235 newDevice->inqSuccess = B_TRUE;
1236 }
1237 }
1238 }
1239
1240
1241 /*
1242 * process the logical-unit object
1243 *
1244 * Arguments:
1245 * luCount - count of the number of device paths in paths_argv
1246 * if pathCount > 0, then we will only print information for
1247 * the device paths listed in paths_argv
1248 * if pathCount == 0, then we will print information on all device
1249 * paths
1250 * luArgv - argument array of device paths
1251 * options - any options specified by the caller
1252 *
1253 * returns:
1254 * 0 if successful
1255 * > 0 otherwise
1256 */
1257 int
fc_util_list_logicalunit(int luCount,char ** luArgv,cmdOptions_t * options)1258 fc_util_list_logicalunit(int luCount, char **luArgv, cmdOptions_t *options)
1259 {
1260 int pathCtr, numAdapters, i, count;
1261 HBA_STATUS status;
1262 char adapterName[256];
1263 HBA_HANDLE handle;
1264 HBA_PORTATTRIBUTES port;
1265 HBA_ADAPTERATTRIBUTES attrs;
1266 int portIndex = 0;
1267 int ret = 0;
1268 boolean_t verbose = B_FALSE;
1269 HBA_FCPTARGETMAPPINGV2 *map = NULL;
1270 discoveredDevice *devListWalk, *devList = NULL;
1271 boolean_t pathFound;
1272
1273 /* process each of the options */
1274 for (; options->optval; options++) {
1275 if (options->optval == 'v') {
1276 verbose = B_TRUE;
1277 }
1278 }
1279
1280 if ((status = HBA_LoadLibrary()) != HBA_STATUS_OK) {
1281 fprintf(stderr,
1282 gettext("Failed to load FC-HBA common library\n"));
1283 printStatus(status);
1284 fprintf(stderr, "\n");
1285 return (1);
1286 }
1287 /*
1288 * Retrieve all device paths. We'll need to traverse the list
1289 * until we find the input paths or all paths if none were given. We
1290 * cannot print as we go since there can be duplicate paths returned
1291 */
1292 numAdapters = HBA_GetNumberOfAdapters();
1293 if (numAdapters == 0) {
1294 return (0);
1295 }
1296 for (i = 0; i < numAdapters; i++) {
1297 int times;
1298 status = HBA_GetAdapterName(i, adapterName);
1299 if (status != HBA_STATUS_OK) {
1300 fprintf(stderr, gettext(
1301 "Failed to get adapter %d. Reason: "), i);
1302 printStatus(status);
1303 fprintf(stderr, "\n");
1304 ret++;
1305 continue;
1306 }
1307 if ((handle = HBA_OpenAdapter(adapterName)) == 0) {
1308 fprintf(stderr, gettext("Failed to open adapter %s\n"),
1309 adapterName);
1310 ret++;
1311 continue;
1312 }
1313 /* get adapter attributes for the given handle */
1314 memset(&attrs, 0, sizeof (attrs));
1315 times = 0;
1316 status = HBA_GetAdapterAttributes(handle, &attrs);
1317 while ((status == HBA_STATUS_ERROR_TRY_AGAIN ||
1318 status == HBA_STATUS_ERROR_BUSY) &&
1319 times++ < HBA_MAX_RETRIES) {
1320 (void) sleep(1);
1321 status = HBA_GetAdapterAttributes(handle, &attrs);
1322 if (status == HBA_STATUS_OK) {
1323 break;
1324 }
1325 }
1326 if (status != HBA_STATUS_OK) {
1327 fprintf(stderr,
1328 gettext("Failed to get adapter attributes "
1329 "handle(%d) Reason: "), handle);
1330 printStatus(status);
1331 fprintf(stderr, "\n");
1332 ret++;
1333 HBA_CloseAdapter(handle);
1334 continue;
1335 }
1336
1337 /* process each port on adapter */
1338 for (portIndex = 0; portIndex < attrs.NumberOfPorts;
1339 portIndex++) {
1340 memset(&port, 0, sizeof (port));
1341 if ((status = HBA_GetAdapterPortAttributes(handle,
1342 portIndex, &port)) != HBA_STATUS_OK) {
1343 /*
1344 * not able to get port attributes.
1345 * print out error message and move
1346 * on to the next port
1347 */
1348 fprintf(stderr, gettext("Failed to get port "
1349 "(%d) attributes reason: "),
1350 portIndex);
1351 printStatus(status);
1352 fprintf(stderr, "\n");
1353 ret++;
1354 continue;
1355 }
1356
1357 /* get OS Device Paths */
1358 getTargetMapping(handle, port.PortWWN, &map);
1359 if (map != NULL) {
1360 for (count = 0; count < map->NumberOfEntries;
1361 count++) {
1362 searchDevice(&devList,
1363 map->entry[count], port.PortWWN,
1364 handle, verbose);
1365 }
1366 }
1367 }
1368 HBA_CloseAdapter(handle);
1369 }
1370 HBA_FreeLibrary();
1371
1372 if (luCount == 0) {
1373 /* list all paths */
1374 for (devListWalk = devList; devListWalk != NULL;
1375 devListWalk = devListWalk->next) {
1376 printOSDeviceNameInfo(devListWalk, verbose);
1377 }
1378 } else {
1379 /*
1380 * list any paths not found first
1381 * this gives the user cleaner output
1382 */
1383 for (pathCtr = 0; pathCtr < luCount; pathCtr++) {
1384 for (devListWalk = devList, pathFound = B_FALSE;
1385 devListWalk != NULL;
1386 devListWalk = devListWalk->next) {
1387 if (strcmp(devListWalk->OSDeviceName,
1388 luArgv[pathCtr]) == 0) {
1389 pathFound = B_TRUE;
1390 }
1391 }
1392 if (pathFound == B_FALSE) {
1393 fprintf(stderr, "%s: no such path\n",
1394 luArgv[pathCtr]);
1395 ret++;
1396 }
1397 }
1398 /* list all paths requested in order requested */
1399 for (pathCtr = 0; pathCtr < luCount; pathCtr++) {
1400 for (devListWalk = devList; devListWalk != NULL;
1401 devListWalk = devListWalk->next) {
1402 if (strcmp(devListWalk->OSDeviceName,
1403 luArgv[pathCtr]) == 0) {
1404 printOSDeviceNameInfo(devListWalk,
1405 verbose);
1406 }
1407 }
1408 }
1409 }
1410 return (ret);
1411 }
1412