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.
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.
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]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
31 #include <sys/types.h>
32 #include <netinet/in.h>
41 #define htonll(x) ((((unsigned long long)htonl(x)) << 32) + htonl(x >> 32))
42 #define ntohll(x) ((((unsigned long long)ntohl(x)) << 32) + ntohl(x >> 32))
45 /* Fc4 Types Format */
46 #define FC4_TYPE_WORD_POS(x) ((uint_t)((uint_t)(x) >> 5))
47 #define FC4_TYPE_BIT_POS(x) ((uchar_t)(x) & 0x1F)
49 #define TYPE_IP_FC 0x05
50 #define TYPE_SCSI_FCP 0x08
52 static int fc4_map_is_set(uint32_t *map
, uchar_t ulp_type
);
53 static char *getPortType(HBA_PORTTYPE portType
);
54 static char *getPortState(HBA_PORTSTATE portState
);
55 static void printPortSpeed(HBA_PORTSPEED portSpeed
);
56 static char *getDTypeString(uchar_t dType
);
58 uint64_t wwnConversion(uchar_t
*wwn
) {
60 memcpy(&tmp
, wwn
, sizeof (uint64_t));
65 getPortType(HBA_PORTTYPE portType
) {
67 case HBA_PORTTYPE_UNKNOWN
:
69 case HBA_PORTTYPE_OTHER
:
71 case HBA_PORTTYPE_NOTPRESENT
:
72 return ("not present");
73 case HBA_PORTTYPE_NPORT
:
75 case HBA_PORTTYPE_NLPORT
:
77 case HBA_PORTTYPE_FLPORT
:
79 case HBA_PORTTYPE_FPORT
:
81 case HBA_PORTTYPE_LPORT
:
83 case HBA_PORTTYPE_PTP
:
84 return ("point-to-point");
86 return ("unrecognized type");
91 getPortState(HBA_PORTSTATE portState
) {
93 case HBA_PORTSTATE_UNKNOWN
:
95 case HBA_PORTSTATE_ONLINE
:
97 case HBA_PORTSTATE_OFFLINE
:
99 case HBA_PORTSTATE_BYPASSED
:
101 case HBA_PORTSTATE_DIAGNOSTICS
:
102 return ("diagnostics");
103 case HBA_PORTSTATE_LINKDOWN
:
104 return ("link down");
105 case HBA_PORTSTATE_ERROR
:
107 case HBA_PORTSTATE_LOOPBACK
:
110 return ("unrecognized state");
115 printPortSpeed(HBA_PORTSPEED portSpeed
) {
118 if ((portSpeed
& HBA_PORTSPEED_1GBIT
) == HBA_PORTSPEED_1GBIT
) {
119 fprintf(stdout
, "1Gb ");
122 if ((portSpeed
& HBA_PORTSPEED_2GBIT
) == HBA_PORTSPEED_2GBIT
) {
123 fprintf(stdout
, "2Gb ");
126 if ((portSpeed
& HBA_PORTSPEED_4GBIT
) == HBA_PORTSPEED_4GBIT
) {
127 fprintf(stdout
, "4Gb ");
130 if ((portSpeed
& HBA_PORTSPEED_8GBIT
) == HBA_PORTSPEED_8GBIT
) {
131 fprintf(stdout
, "8Gb ");
134 if ((portSpeed
& HBA_PORTSPEED_10GBIT
) == HBA_PORTSPEED_10GBIT
) {
135 fprintf(stdout
, "10Gb ");
138 if ((portSpeed
& HBA_PORTSPEED_16GBIT
) == HBA_PORTSPEED_16GBIT
) {
139 fprintf(stdout
, "16Gb ");
142 if ((portSpeed
& HBA_PORTSPEED_NOT_NEGOTIATED
)
143 == HBA_PORTSPEED_NOT_NEGOTIATED
) {
144 fprintf(stdout
, "not established ");
147 if (foundSpeed
== 0) {
148 fprintf(stdout
, "not established ");
153 printDiscoPortInfo(HBA_PORTATTRIBUTES
*discoPort
, int scsiTargetType
) {
156 fprintf(stdout
, gettext("Remote Port WWN: %016llx\n"),
157 wwnConversion(discoPort
->PortWWN
.wwn
));
158 fprintf(stdout
, gettext("\tActive FC4 Types: "));
160 (uint32_t *)discoPort
->PortActiveFc4Types
.bits
,
162 fprintf(stdout
, gettext("SCSI"));
166 (uint32_t *)discoPort
->PortActiveFc4Types
.bits
,
168 if (fc4_types
!= 0) {
169 fprintf(stdout
, ",");
171 fprintf(stdout
, gettext("IP"));
174 fprintf(stdout
, "\n");
176 /* print out scsi target type information */
177 fprintf(stdout
, gettext("\tSCSI Target: "));
178 if (scsiTargetType
== SCSI_TARGET_TYPE_YES
) {
179 fprintf(stdout
, gettext("yes\n"));
180 } else if (scsiTargetType
== SCSI_TARGET_TYPE_NO
) {
181 fprintf(stdout
, gettext("no\n"));
183 fprintf(stdout
, gettext("unknown\n"));
185 fprintf(stdout
, gettext("\tPort Symbolic Name: %s\n"),
186 discoPort
->PortSymbolicName
);
187 fprintf(stdout
, gettext("\tNode WWN: %016llx\n"),
188 wwnConversion(discoPort
->NodeWWN
.wwn
));
192 * scan the bitmap array for the specifed ULP type. The bit map array
196 fc4_map_is_set(uint32_t *map
, uchar_t ulp_type
)
199 map
+= FC4_TYPE_WORD_POS(ulp_type
) * 4;
201 if (ntohl((*(uint32_t *)map
)) & (1 << FC4_TYPE_BIT_POS(ulp_type
))) {
209 * prints out all the HBA port information
212 printHBAPortInfo(HBA_PORTATTRIBUTES
*port
,
213 HBA_ADAPTERATTRIBUTES
*attrs
, int mode
) {
214 if (attrs
== NULL
|| port
== NULL
) {
217 fprintf(stdout
, gettext("HBA Port WWN: %016llx\n"),
218 wwnConversion(port
->PortWWN
.wwn
));
219 fprintf(stdout
, gettext("\tPort Mode: %s\n"),
220 (mode
== INITIATOR_MODE
) ? "Initiator" : "Target");
221 fprintf(stdout
, gettext("\tPort ID: %x\n"),
223 fprintf(stdout
, gettext("\tOS Device Name: %s\n"), port
->OSDeviceName
);
225 fprintf(stdout
, gettext("\tManufacturer: %s\n"),
226 attrs
->Manufacturer
);
227 fprintf(stdout
, gettext("\tModel: %s\n"), attrs
->Model
);
228 fprintf(stdout
, gettext("\tFirmware Version: %s\n"),
229 attrs
->FirmwareVersion
);
230 fprintf(stdout
, gettext("\tFCode/BIOS Version: %s\n"),
231 attrs
->OptionROMVersion
);
232 fprintf(stdout
, gettext("\tSerial Number: %s\n"),
233 attrs
->SerialNumber
[0] == 0? "not available":attrs
->SerialNumber
);
235 fprintf(stdout
, gettext("\tDriver Name: %s\n"),
236 attrs
->DriverName
[0] == 0? "not available":attrs
->DriverName
);
237 fprintf(stdout
, gettext("\tDriver Version: %s\n"),
238 attrs
->DriverVersion
[0] == 0? "not available":attrs
->DriverVersion
);
240 fprintf(stdout
, gettext("\tType: %s\n"),
241 getPortType(port
->PortType
));
242 fprintf(stdout
, gettext("\tState: %s\n"),
243 getPortState(port
->PortState
));
245 fprintf(stdout
, gettext("\tSupported Speeds: "));
246 printPortSpeed(port
->PortSupportedSpeed
);
247 fprintf(stdout
, "\n");
249 fprintf(stdout
, gettext("\tCurrent Speed: "));
250 printPortSpeed(port
->PortSpeed
);
251 fprintf(stdout
, "\n");
253 fprintf(stdout
, gettext("\tNode WWN: %016llx\n"),
254 wwnConversion(port
->NodeWWN
.wwn
));
258 printStatus(HBA_STATUS status
) {
261 fprintf(stderr
, gettext("OK"));
263 case HBA_STATUS_ERROR
:
264 fprintf(stderr
, gettext("ERROR"));
266 case HBA_STATUS_ERROR_NOT_SUPPORTED
:
267 fprintf(stderr
, gettext("NOT SUPPORTED"));
269 case HBA_STATUS_ERROR_INVALID_HANDLE
:
270 fprintf(stderr
, gettext("INVALID HANDLE"));
272 case HBA_STATUS_ERROR_ARG
:
273 fprintf(stderr
, gettext("ERROR ARG"));
275 case HBA_STATUS_ERROR_ILLEGAL_WWN
:
276 fprintf(stderr
, gettext("ILLEGAL WWN"));
278 case HBA_STATUS_ERROR_ILLEGAL_INDEX
:
279 fprintf(stderr
, gettext("ILLEGAL INDEX"));
281 case HBA_STATUS_ERROR_MORE_DATA
:
282 fprintf(stderr
, gettext("MORE DATA"));
284 case HBA_STATUS_ERROR_STALE_DATA
:
285 fprintf(stderr
, gettext("STALE DATA"));
287 case HBA_STATUS_SCSI_CHECK_CONDITION
:
288 fprintf(stderr
, gettext("SCSI CHECK CONDITION"));
290 case HBA_STATUS_ERROR_BUSY
:
291 fprintf(stderr
, gettext("BUSY"));
293 case HBA_STATUS_ERROR_TRY_AGAIN
:
294 fprintf(stderr
, gettext("TRY AGAIN"));
296 case HBA_STATUS_ERROR_UNAVAILABLE
:
297 fprintf(stderr
, gettext("UNAVAILABLE"));
300 fprintf(stderr
, "%s %d",
301 gettext("Undefined error code "), status
);
307 printLUNInfo(struct scsi_inquiry
*inq
, HBA_UINT32 scsiLUN
, char *devpath
) {
308 fprintf(stdout
, "\tLUN: %d\n", scsiLUN
);
309 fprintf(stdout
, "\t Vendor: %c%c%c%c%c%c%c%c\n",
318 fprintf(stdout
, "\t Product: %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
335 fprintf(stdout
, gettext("\t OS Device Name: %s\n"), devpath
);
339 printPortStat(fc_rls_acc_t
*rls_payload
) {
340 fprintf(stdout
, gettext("\tLink Error Statistics:\n"));
341 fprintf(stdout
, gettext("\t\tLink Failure Count: %u\n"),
342 rls_payload
->rls_link_fail
);
343 fprintf(stdout
, gettext("\t\tLoss of Sync Count: %u\n"),
344 rls_payload
->rls_sync_loss
);
345 fprintf(stdout
, gettext("\t\tLoss of Signal Count: %u\n"),
346 rls_payload
->rls_sig_loss
);
347 fprintf(stdout
, gettext("\t\tPrimitive Seq Protocol Error Count: %u\n"),
348 rls_payload
->rls_prim_seq_err
);
349 fprintf(stdout
, gettext("\t\tInvalid Tx Word Count: %u\n"),
350 rls_payload
->rls_invalid_word
);
351 fprintf(stdout
, gettext("\t\tInvalid CRC Count: %u\n"),
352 rls_payload
->rls_invalid_crc
);
356 * return device type description
359 * dType - Device type returned from Standard INQUIRY
361 * char string description for device type
364 getDTypeString(uchar_t dType
)
366 switch (dType
& DTYPE_MASK
) {
368 return ("Disk Device");
369 case DTYPE_SEQUENTIAL
:
370 return ("Tape Device");
372 return ("Printer Device");
373 case DTYPE_PROCESSOR
:
374 return ("Processor Device");
376 return ("WORM Device");
378 return ("CD/DVD Device");
380 return ("Scanner Device");
382 return ("Optical Memory Device");
384 return ("Medium Changer Device");
386 return ("Communications Device");
387 case DTYPE_ARRAY_CTRL
:
388 return ("Storage Array Controller Device");
390 return ("Enclosure Services Device");
392 return ("Simplified Direct-access Device");
394 return ("Optical Card Reader/Writer Device");
396 return ("Bridge Controller Commands");
398 return ("Object-based Storage Device");
400 return ("Automation/Drive Interface");
401 case DTYPE_WELLKNOWN
:
402 return ("Well Known Logical Unit");
404 return ("Unknown Device");
406 return ("Undefined");
411 * print the OS device name for the logical-unit object
414 * devListWalk - OS device path info
415 * verbose - boolean indicating whether to display additional info
421 printOSDeviceNameInfo(discoveredDevice
*devListWalk
, boolean_t verbose
)
423 portWWNList
*WWNList
;
424 tgtPortWWNList
*tgtWWNList
;
427 fprintf(stdout
, "OS Device Name: %s\n", devListWalk
->OSDeviceName
);
428 if (verbose
== B_TRUE
) {
429 for (WWNList
= devListWalk
->HBAPortWWN
;
430 WWNList
!= NULL
; WWNList
= WWNList
->next
) {
431 fprintf(stdout
, "\tHBA Port WWN: ");
432 fprintf(stdout
, "%016llx",
433 wwnConversion(WWNList
->portWWN
.wwn
));
434 for (tgtWWNList
= WWNList
->tgtPortWWN
;
435 tgtWWNList
!= NULL
; tgtWWNList
= tgtWWNList
->next
) {
436 fprintf(stdout
, "\n\t\tRemote Port WWN: ");
437 fprintf(stdout
, "%016llx",
438 wwnConversion(tgtWWNList
->portWWN
.wwn
));
439 fprintf(stdout
, "\n\t\t\tLUN: %d",
440 tgtWWNList
->scsiOSLun
);
442 fprintf(stdout
, "\n");
445 fprintf(stdout
, "\tVendor: ");
446 for (count
= sizeof (devListWalk
->VID
), i
= 0; i
< count
; i
++) {
447 if (isprint(devListWalk
->VID
[i
]))
448 fprintf(stdout
, "%c", devListWalk
->VID
[i
]);
451 fprintf(stdout
, "\n\tProduct: ");
452 for (count
= sizeof (devListWalk
->PID
), i
= 0; i
< count
; i
++) {
453 if (isprint(devListWalk
->PID
[i
]))
454 fprintf(stdout
, "%c", devListWalk
->PID
[i
]);
457 fprintf(stdout
, "\n\tDevice Type: %s\n",
458 getDTypeString(devListWalk
->dType
));