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 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26
27
28 #include <stdio.h>
29 #include <hbaapi.h>
30 #include <string.h>
31 #include <sys/types.h>
32 #include <netinet/in.h>
33 #include <inttypes.h>
34 #include <ctype.h>
35 #include "fcinfo.h"
36
37 #ifdef _BIG_ENDIAN
38 #define htonll(x) (x)
39 #define ntohll(x) (x)
40 #else
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))
43 #endif
44
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)
48
49 #define TYPE_IP_FC 0x05
50 #define TYPE_SCSI_FCP 0x08
51
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);
57
wwnConversion(uchar_t * wwn)58 uint64_t wwnConversion(uchar_t *wwn) {
59 uint64_t tmp;
60 memcpy(&tmp, wwn, sizeof (uint64_t));
61 return (ntohll(tmp));
62 }
63
64 static char *
getPortType(HBA_PORTTYPE portType)65 getPortType(HBA_PORTTYPE portType) {
66 switch (portType) {
67 case HBA_PORTTYPE_UNKNOWN:
68 return ("unknown");
69 case HBA_PORTTYPE_OTHER:
70 return ("other");
71 case HBA_PORTTYPE_NOTPRESENT:
72 return ("not present");
73 case HBA_PORTTYPE_NPORT:
74 return ("N-port");
75 case HBA_PORTTYPE_NLPORT:
76 return ("NL-port");
77 case HBA_PORTTYPE_FLPORT:
78 return ("FL-port");
79 case HBA_PORTTYPE_FPORT:
80 return ("F-port");
81 case HBA_PORTTYPE_LPORT:
82 return ("L-port");
83 case HBA_PORTTYPE_PTP:
84 return ("point-to-point");
85 default:
86 return ("unrecognized type");
87 }
88 }
89
90 static char *
getPortState(HBA_PORTSTATE portState)91 getPortState(HBA_PORTSTATE portState) {
92 switch (portState) {
93 case HBA_PORTSTATE_UNKNOWN:
94 return ("unknown");
95 case HBA_PORTSTATE_ONLINE:
96 return ("online");
97 case HBA_PORTSTATE_OFFLINE:
98 return ("offline");
99 case HBA_PORTSTATE_BYPASSED:
100 return ("bypassed");
101 case HBA_PORTSTATE_DIAGNOSTICS:
102 return ("diagnostics");
103 case HBA_PORTSTATE_LINKDOWN:
104 return ("link down");
105 case HBA_PORTSTATE_ERROR:
106 return ("error");
107 case HBA_PORTSTATE_LOOPBACK:
108 return ("loopback");
109 default:
110 return ("unrecognized state");
111 }
112 }
113
114 static void
printPortSpeed(HBA_PORTSPEED portSpeed)115 printPortSpeed(HBA_PORTSPEED portSpeed) {
116 int foundSpeed = 0;
117
118 if ((portSpeed & HBA_PORTSPEED_1GBIT) == HBA_PORTSPEED_1GBIT) {
119 fprintf(stdout, "1Gb ");
120 foundSpeed = 1;
121 }
122 if ((portSpeed & HBA_PORTSPEED_2GBIT) == HBA_PORTSPEED_2GBIT) {
123 fprintf(stdout, "2Gb ");
124 foundSpeed = 1;
125 }
126 if ((portSpeed & HBA_PORTSPEED_4GBIT) == HBA_PORTSPEED_4GBIT) {
127 fprintf(stdout, "4Gb ");
128 foundSpeed = 1;
129 }
130 if ((portSpeed & HBA_PORTSPEED_8GBIT) == HBA_PORTSPEED_8GBIT) {
131 fprintf(stdout, "8Gb ");
132 foundSpeed = 1;
133 }
134 if ((portSpeed & HBA_PORTSPEED_10GBIT) == HBA_PORTSPEED_10GBIT) {
135 fprintf(stdout, "10Gb ");
136 foundSpeed = 1;
137 }
138 if ((portSpeed & HBA_PORTSPEED_16GBIT) == HBA_PORTSPEED_16GBIT) {
139 fprintf(stdout, "16Gb ");
140 foundSpeed = 1;
141 }
142 if ((portSpeed & HBA_PORTSPEED_NOT_NEGOTIATED)
143 == HBA_PORTSPEED_NOT_NEGOTIATED) {
144 fprintf(stdout, "not established ");
145 foundSpeed = 1;
146 }
147 if (foundSpeed == 0) {
148 fprintf(stdout, "not established ");
149 }
150 }
151
152 void
printDiscoPortInfo(HBA_PORTATTRIBUTES * discoPort,int scsiTargetType)153 printDiscoPortInfo(HBA_PORTATTRIBUTES *discoPort, int scsiTargetType) {
154 int fc4_types = 0;
155
156 fprintf(stdout, gettext("Remote Port WWN: %016llx\n"),
157 wwnConversion(discoPort->PortWWN.wwn));
158 fprintf(stdout, gettext("\tActive FC4 Types: "));
159 if (fc4_map_is_set(
160 (uint32_t *)discoPort->PortActiveFc4Types.bits,
161 TYPE_SCSI_FCP)) {
162 fprintf(stdout, gettext("SCSI"));
163 fc4_types++;
164 }
165 if (fc4_map_is_set(
166 (uint32_t *)discoPort->PortActiveFc4Types.bits,
167 TYPE_IP_FC)) {
168 if (fc4_types != 0) {
169 fprintf(stdout, ",");
170 }
171 fprintf(stdout, gettext("IP"));
172 fc4_types++;
173 }
174 fprintf(stdout, "\n");
175
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"));
182 } else {
183 fprintf(stdout, gettext("unknown\n"));
184 }
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));
189 }
190
191 /*
192 * scan the bitmap array for the specifed ULP type. The bit map array
193 * is 32 bytes long
194 */
195 static int
fc4_map_is_set(uint32_t * map,uchar_t ulp_type)196 fc4_map_is_set(uint32_t *map, uchar_t ulp_type)
197 {
198
199 map += FC4_TYPE_WORD_POS(ulp_type) * 4;
200
201 if (ntohl((*(uint32_t *)map)) & (1 << FC4_TYPE_BIT_POS(ulp_type))) {
202 return (1);
203 }
204
205 return (0);
206 }
207
208 /*
209 * prints out all the HBA port information
210 */
211 void
printHBAPortInfo(HBA_PORTATTRIBUTES * port,HBA_ADAPTERATTRIBUTES * attrs,int mode)212 printHBAPortInfo(HBA_PORTATTRIBUTES *port,
213 HBA_ADAPTERATTRIBUTES *attrs, int mode) {
214 if (attrs == NULL || port == NULL) {
215 return;
216 }
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"),
222 port->PortFcId);
223 fprintf(stdout, gettext("\tOS Device Name: %s\n"), port->OSDeviceName);
224
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);
234
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);
239
240 fprintf(stdout, gettext("\tType: %s\n"),
241 getPortType(port->PortType));
242 fprintf(stdout, gettext("\tState: %s\n"),
243 getPortState(port->PortState));
244
245 fprintf(stdout, gettext("\tSupported Speeds: "));
246 printPortSpeed(port->PortSupportedSpeed);
247 fprintf(stdout, "\n");
248
249 fprintf(stdout, gettext("\tCurrent Speed: "));
250 printPortSpeed(port->PortSpeed);
251 fprintf(stdout, "\n");
252
253 fprintf(stdout, gettext("\tNode WWN: %016llx\n"),
254 wwnConversion(port->NodeWWN.wwn));
255 }
256
257 void
printStatus(HBA_STATUS status)258 printStatus(HBA_STATUS status) {
259 switch (status) {
260 case HBA_STATUS_OK:
261 fprintf(stderr, gettext("OK"));
262 return;
263 case HBA_STATUS_ERROR:
264 fprintf(stderr, gettext("ERROR"));
265 return;
266 case HBA_STATUS_ERROR_NOT_SUPPORTED:
267 fprintf(stderr, gettext("NOT SUPPORTED"));
268 return;
269 case HBA_STATUS_ERROR_INVALID_HANDLE:
270 fprintf(stderr, gettext("INVALID HANDLE"));
271 return;
272 case HBA_STATUS_ERROR_ARG:
273 fprintf(stderr, gettext("ERROR ARG"));
274 return;
275 case HBA_STATUS_ERROR_ILLEGAL_WWN:
276 fprintf(stderr, gettext("ILLEGAL WWN"));
277 return;
278 case HBA_STATUS_ERROR_ILLEGAL_INDEX:
279 fprintf(stderr, gettext("ILLEGAL INDEX"));
280 return;
281 case HBA_STATUS_ERROR_MORE_DATA:
282 fprintf(stderr, gettext("MORE DATA"));
283 return;
284 case HBA_STATUS_ERROR_STALE_DATA:
285 fprintf(stderr, gettext("STALE DATA"));
286 return;
287 case HBA_STATUS_SCSI_CHECK_CONDITION:
288 fprintf(stderr, gettext("SCSI CHECK CONDITION"));
289 return;
290 case HBA_STATUS_ERROR_BUSY:
291 fprintf(stderr, gettext("BUSY"));
292 return;
293 case HBA_STATUS_ERROR_TRY_AGAIN:
294 fprintf(stderr, gettext("TRY AGAIN"));
295 return;
296 case HBA_STATUS_ERROR_UNAVAILABLE:
297 fprintf(stderr, gettext("UNAVAILABLE"));
298 return;
299 default:
300 fprintf(stderr, "%s %d",
301 gettext("Undefined error code "), status);
302 return;
303 }
304 }
305
306 void
printLUNInfo(struct scsi_inquiry * inq,HBA_UINT32 scsiLUN,char * devpath)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",
310 inq->inq_vid[0],
311 inq->inq_vid[1],
312 inq->inq_vid[2],
313 inq->inq_vid[3],
314 inq->inq_vid[4],
315 inq->inq_vid[5],
316 inq->inq_vid[6],
317 inq->inq_vid[7]);
318 fprintf(stdout, "\t Product: %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
319 inq->inq_pid[0],
320 inq->inq_pid[1],
321 inq->inq_pid[2],
322 inq->inq_pid[3],
323 inq->inq_pid[4],
324 inq->inq_pid[5],
325 inq->inq_pid[6],
326 inq->inq_pid[7],
327 inq->inq_pid[8],
328 inq->inq_pid[9],
329 inq->inq_pid[10],
330 inq->inq_pid[11],
331 inq->inq_pid[12],
332 inq->inq_pid[13],
333 inq->inq_pid[14],
334 inq->inq_pid[15]);
335 fprintf(stdout, gettext("\t OS Device Name: %s\n"), devpath);
336 }
337
338 void
printPortStat(fc_rls_acc_t * rls_payload)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);
353 }
354
355 /*
356 * return device type description
357 *
358 * Arguments:
359 * dType - Device type returned from Standard INQUIRY
360 * Returns:
361 * char string description for device type
362 */
363 static char *
getDTypeString(uchar_t dType)364 getDTypeString(uchar_t dType)
365 {
366 switch (dType & DTYPE_MASK) {
367 case DTYPE_DIRECT:
368 return ("Disk Device");
369 case DTYPE_SEQUENTIAL:
370 return ("Tape Device");
371 case DTYPE_PRINTER:
372 return ("Printer Device");
373 case DTYPE_PROCESSOR:
374 return ("Processor Device");
375 case DTYPE_WORM:
376 return ("WORM Device");
377 case DTYPE_RODIRECT:
378 return ("CD/DVD Device");
379 case DTYPE_SCANNER:
380 return ("Scanner Device");
381 case DTYPE_OPTICAL:
382 return ("Optical Memory Device");
383 case DTYPE_CHANGER:
384 return ("Medium Changer Device");
385 case DTYPE_COMM:
386 return ("Communications Device");
387 case DTYPE_ARRAY_CTRL:
388 return ("Storage Array Controller Device");
389 case DTYPE_ESI:
390 return ("Enclosure Services Device");
391 case DTYPE_RBC:
392 return ("Simplified Direct-access Device");
393 case DTYPE_OCRW:
394 return ("Optical Card Reader/Writer Device");
395 case DTYPE_BCC:
396 return ("Bridge Controller Commands");
397 case DTYPE_OSD:
398 return ("Object-based Storage Device");
399 case DTYPE_ADC:
400 return ("Automation/Drive Interface");
401 case DTYPE_WELLKNOWN:
402 return ("Well Known Logical Unit");
403 case DTYPE_UNKNOWN:
404 return ("Unknown Device");
405 default:
406 return ("Undefined");
407 }
408 }
409
410 /*
411 * print the OS device name for the logical-unit object
412 *
413 * Arguments:
414 * devListWalk - OS device path info
415 * verbose - boolean indicating whether to display additional info
416 *
417 * returns:
418 * none
419 */
420 void
printOSDeviceNameInfo(discoveredDevice * devListWalk,boolean_t verbose)421 printOSDeviceNameInfo(discoveredDevice *devListWalk, boolean_t verbose)
422 {
423 portWWNList *WWNList;
424 tgtPortWWNList *tgtWWNList;
425 int i, count;
426
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);
441 }
442 fprintf(stdout, "\n");
443 }
444
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]);
449 }
450
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]);
455 }
456
457 fprintf(stdout, "\n\tDevice Type: %s\n",
458 getDTypeString(devListWalk->dType));
459 }
460 }
461