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 #include <ctype.h>
27 #include <printAttrs.h>
28
29 static SAS_STATE hbastatus_string[] = {
30 HBA_STATUS_OK, "Okay",
31 HBA_STATUS_ERROR, "Error",
32 HBA_STATUS_ERROR_NOT_SUPPORTED, "Not Supported",
33 HBA_STATUS_ERROR_INVALID_HANDLE, "Invalid Handle",
34 HBA_STATUS_ERROR_ARG, "Argument Error",
35 HBA_STATUS_ERROR_ILLEGAL_WWN, "Illegal WWN",
36 HBA_STATUS_ERROR_ILLEGAL_INDEX, "Illegal Index",
37 HBA_STATUS_ERROR_MORE_DATA, "Not Enough Buffer for Data",
38 HBA_STATUS_ERROR_STALE_DATA, "Stale Data",
39 HBA_STATUS_SCSI_CHECK_CONDITION, "SCSI Check Condition",
40 HBA_STATUS_ERROR_BUSY, "Busy",
41 HBA_STATUS_ERROR_TRY_AGAIN, "Try Again",
42 HBA_STATUS_ERROR_UNAVAILABLE, "Unavailable",
43 HBA_STATUS_ERROR_ELS_REJECT, "ELS Reject",
44 HBA_STATUS_ERROR_INVALID_LUN, "Invalid LUN",
45 HBA_STATUS_ERROR_INCOMPATIBLE, "Request Incompatible",
46 HBA_STATUS_ERROR_AMBIGUOUS_WWN, "Ambiguous WWN",
47 HBA_STATUS_ERROR_LOCAL_BUS, "Local Bus Error",
48 HBA_STATUS_ERROR_LOCAL_TARGET, "Local Target Error",
49 HBA_STATUS_ERROR_LOCAL_LUN, "Local LUN Error",
50 HBA_STATUS_ERROR_LOCAL_SCSIID_BOUND, "Local SCSIID Bound",
51 HBA_STATUS_ERROR_TARGET_FCID, "Target FCID Error",
52 HBA_STATUS_ERROR_TARGET_NODE_WWN, "Target Node WWN Error",
53 HBA_STATUS_ERROR_TARGET_PORT_WWN, "Target Port WWN Error",
54 HBA_STATUS_ERROR_TARGET_LUN, "Target LUN Error",
55 HBA_STATUS_ERROR_TARGET_LUID, "Target LUID Error",
56 HBA_STATUS_ERROR_NO_SUCH_BINDING, "No Such Binding",
57 HBA_STATUS_ERROR_NOT_A_TARGET, "Not a Target",
58 HBA_STATUS_ERROR_UNSUPPORTED_FC4, "Unsupported FC4",
59 HBA_STATUS_ERROR_INCAPABLE, "Incapable",
60 HBA_STATUS_ERROR_TARGET_BUSY, "Target Busy",
61 HBA_STATUS_ERROR_NOT_LOADED, "Not Loaded",
62 HBA_STATUS_ERROR_ALREADY_LOADED, "Alreday Loaded",
63 HBA_STATUS_ERROR_ILLEGAL_FCID, "Illegal FCID",
64 HBA_STATUS_ERROR_NOT_ASCSIDEVICE, "Not a SCSI Device",
65 HBA_STATUS_ERROR_INVALID_PROTOCOL_TYPE, "Invalid Protocol Type",
66 HBA_STATUS_ERROR_BAD_EVENT_TYPE, "Bad Event Type",
67 -1, NULL
68 };
69
70 SAS_STATE porttype_string[] = {
71 HBA_PORTTYPE_UNKNOWN, "UNKNOWN",
72 HBA_PORTTYPE_OTHER, "OTHER",
73 HBA_PORTTYPE_NOTPRESENT, "NOT Present",
74 HBA_PORTTYPE_SASDEVICE, "SAS Device",
75 HBA_PORTTYPE_SATADEVICE, "SATA Device",
76 HBA_PORTTYPE_SASEXPANDER, "SAS Expander",
77 -1, NULL,
78 };
79
80 SAS_STATE portstate_string[] = {
81 HBA_PORTSTATE_UNKNOWN, "unknown",
82 HBA_PORTSTATE_ONLINE, "online",
83 HBA_PORTSTATE_OFFLINE, "offline",
84 HBA_PORTSTATE_BYPASSED, "bypassed",
85 HBA_PORTSTATE_DIAGNOSTICS, "diagnostics",
86 HBA_PORTSTATE_LINKDOWN, "link Down",
87 HBA_PORTSTATE_ERROR, "port Error",
88 HBA_PORTSTATE_LOOPBACK, "loopback",
89 HBA_PORTSTATE_DEGRADED, "degraded",
90 -1, NULL,
91 };
92
93 static SAS_STATE phystate_string[] = {
94 HBA_SASSTATE_UNKNOWN, "unknown",
95 HBA_SASSTATE_DISABLED, "disabled",
96 HBA_SASSTATE_FAILED, "failed",
97 HBA_SASSTATE_SATASPINUP, "sata-spinup",
98 HBA_SASSTATE_SATAPORTSEL, "sata-portselector",
99 HBA_SASSPEED_1_5GBIT, "1.5Gbit",
100 HBA_SASSPEED_3GBIT, "3Gbit",
101 HBA_SASSPEED_6GBIT, "6Gbit",
102 -1, NULL,
103 };
104
105 static SAS_STATE dtype_string[] = {
106 DTYPE_DIRECT, "Disk Device",
107 DTYPE_SEQUENTIAL, "Tape Device",
108 DTYPE_PRINTER, "Printer Device",
109 DTYPE_PROCESSOR, "Processor Device",
110 DTYPE_WORM, "WORM Device",
111 DTYPE_RODIRECT, "CD/DVD Device",
112 DTYPE_SCANNER, "Scanner Device",
113 DTYPE_OPTICAL, "Optical Memory Device",
114 DTYPE_CHANGER, "Medium Changer Device",
115 DTYPE_COMM, "Communications Device",
116 DTYPE_ARRAY_CTRL, "Storage Array Controller Device",
117 DTYPE_ESI, "Enclosure Services Device",
118 DTYPE_RBC, "Simplified Direct-access Device",
119 DTYPE_OCRW, "Optical Card Reader/Writer Device",
120 DTYPE_BCC, "Bridge Controller Commands",
121 DTYPE_OSD, "Object-based Storage Device",
122 DTYPE_ADC, "Automation/Drive Interface",
123 DTYPE_WELLKNOWN, "Well Known Logical Unit",
124 DTYPE_UNKNOWN, "Unknown Device",
125 -1, NULL
126 };
127
128 static char *getPhyStateString(HBA_UINT32 key, phystat_type phyt);
129
130 char *
getIndentSpaces(int number)131 getIndentSpaces(int number)
132 {
133 int i = 0;
134 /* the maximum indent with terminator '\0' */
135 static char ret[MAXINDENT+1];
136
137 if (number > MAXINDENT)
138 number = MAXINDENT;
139
140 for (i = 0; i < number; i++) {
141 ret[i] = ' ';
142 }
143 ret[i] = '\0';
144 return (ret);
145 }
146
147 char *
getStateString(HBA_UINT32 key,SAS_STATE * stat_string)148 getStateString(HBA_UINT32 key, SAS_STATE *stat_string)
149 {
150 static char ret[64];
151 while (stat_string->key != -1) {
152 if (stat_string->key == key) {
153 return ((char *)stat_string->value);
154 }
155 stat_string++;
156 }
157 (void *) sprintf(ret, "Undefined value (%d)", key);
158 return (ret);
159 }
160
161 static char *
getPhyStateString(HBA_UINT32 key,phystat_type phyt)162 getPhyStateString(HBA_UINT32 key, phystat_type phyt)
163 {
164 int i = 0, len = 0, match = 0;
165 HBA_UINT32 physpeed[] = {
166 HBA_SASSPEED_1_5GBIT,
167 HBA_SASSPEED_3GBIT,
168 HBA_SASSPEED_6GBIT
169 };
170
171 len = sizeof (physpeed) / sizeof (HBA_UINT32);
172 for (i = 0; i < len; i++) {
173 if (key == physpeed[i]) {
174 match = 1;
175 break;
176 }
177 }
178
179 if (match == 1) {
180 if (phyt == PHY_STATE)
181 return ("enabled");
182 else
183 return (getStateString(key, phystate_string));
184 } else {
185 if (phyt == PHY_STATE)
186 return (getStateString(key, phystate_string));
187 else
188 return ("not available");
189 }
190 }
191
192 char *
getHBAStatus(HBA_STATUS key)193 getHBAStatus(HBA_STATUS key)
194 {
195 return (getStateString(key, hbastatus_string));
196 }
197
198 /*
199 * return device type description
200 *
201 * Arguments:
202 * dType - Device type returned from Standard INQUIRY
203 * Returns:
204 * char string description for device type
205 */
206 char *
getDTypeString(uchar_t dType)207 getDTypeString(uchar_t dType)
208 {
209 return (getStateString((dType & DTYPE_MASK), dtype_string));
210 }
211
212 uint64_t
wwnConversion(uchar_t * wwn)213 wwnConversion(uchar_t *wwn)
214 {
215 uint64_t tmp;
216 (void *) memcpy(&tmp, wwn, sizeof (uint64_t));
217 return (ntohll(tmp));
218 }
219
220 /*
221 * prints out HBA information
222 */
223 void
printHBAInfo(SMHBA_ADAPTERATTRIBUTES * attrs,int pflag,int numberOfPorts,const char * adapterName)224 printHBAInfo(SMHBA_ADAPTERATTRIBUTES *attrs, int pflag, int numberOfPorts,
225 const char *adapterName)
226 {
227
228 (void *) fprintf(stdout, "%s %s\n", "HBA Name:", adapterName);
229
230 if (pflag & PRINT_VERBOSE) {
231 (void *) fprintf(stdout, "%s%s %s\n",
232 getIndentSpaces(4), "Manufacturer:",
233 attrs->Manufacturer[0] == 0?
234 "not available":attrs->Manufacturer);
235 (void *) fprintf(stdout, "%s%s %s\n",
236 getIndentSpaces(4), "Model: ",
237 attrs->Model[0] == 0? "not available":attrs->Model);
238 (void *) fprintf(stdout, "%s%s %s\n",
239 getIndentSpaces(4),
240 "Firmware Version:",
241 attrs->FirmwareVersion[0] == 0? "not available":
242 attrs->FirmwareVersion);
243 (void *) fprintf(stdout, "%s%s %s\n",
244 getIndentSpaces(4),
245 "FCode/BIOS Version:",
246 attrs->OptionROMVersion[0] == 0? "not available":
247 attrs->OptionROMVersion);
248 (void *) fprintf(stdout, "%s%s %s\n",
249 getIndentSpaces(4),
250 "Serial Number:",
251 attrs->SerialNumber[0] == 0? "not available":
252 attrs->SerialNumber);
253 (void *) fprintf(stdout, "%s%s %s\n",
254 getIndentSpaces(4),
255 "Driver Name:",
256 attrs->DriverName[0] == 0? "not available":
257 attrs->DriverName);
258 (void *) fprintf(stdout, "%s%s %s\n",
259 getIndentSpaces(4),
260 "Driver Version:",
261 attrs->DriverVersion[0] == 0? "not available":
262 attrs->DriverVersion);
263 (void *) fprintf(stdout, "%s%s %d\n",
264 getIndentSpaces(4),
265 "Number of HBA Ports:",
266 numberOfPorts);
267 }
268 }
269
270 /*
271 * prints out all the HBA port information
272 */
273 void
printHBAPortInfo(SMHBA_PORTATTRIBUTES * port,SMHBA_ADAPTERATTRIBUTES * attrs,int pflag)274 printHBAPortInfo(SMHBA_PORTATTRIBUTES *port,
275 SMHBA_ADAPTERATTRIBUTES *attrs, int pflag) {
276
277 if ((port == NULL) || (attrs == NULL)) {
278 return;
279 }
280
281 (void *) fprintf(stdout, "%s%s %s\n",
282 getIndentSpaces(2),
283 "HBA Port Name:",
284 port->OSDeviceName);
285
286 if (!(pflag & PRINT_VERBOSE)) {
287 return;
288 }
289
290 if (port->PortType != HBA_PORTTYPE_SASDEVICE)
291 return;
292
293 (void *) fprintf(stdout, "%s%s %s\n",
294 getIndentSpaces(4),
295 "Type:",
296 getStateString(port->PortType, porttype_string));
297 (void *) fprintf(stdout, "%s%s %s\n",
298 getIndentSpaces(4),
299 "State:",
300 getStateString(port->PortState, portstate_string));
301
302 (void *) fprintf(stdout, "%s%s %016llx\n",
303 getIndentSpaces(4),
304 "Local SAS Address:",
305 wwnConversion(port->PortSpecificAttribute.SASPort->\
306 LocalSASAddress.wwn));
307
308 (void *) fprintf(stdout, "%s%s %016llx\n",
309 getIndentSpaces(4),
310 "Attached SAS Address:",
311 wwnConversion(port->PortSpecificAttribute.SASPort->\
312 AttachedSASAddress.wwn));
313
314 (void *) fprintf(stdout, "%s%s %d\n",
315 getIndentSpaces(4),
316 "Number of Phys:",
317 port->PortSpecificAttribute.SASPort->NumberofPhys);
318 }
319
320 void
printHBAPortPhyInfo(SMHBA_SAS_PHY * phyinfo)321 printHBAPortPhyInfo(SMHBA_SAS_PHY *phyinfo)
322 {
323 if (phyinfo == NULL)
324 return;
325
326 (void *) fprintf(stdout, "%s%s %u\n",
327 getIndentSpaces(6),
328 "Identifier:",
329 phyinfo->PhyIdentifier);
330
331 (void *) fprintf(stdout, "%s%s %s\n",
332 getIndentSpaces(8),
333 "State: ",
334 getPhyStateString(phyinfo->NegotiatedLinkRate, PHY_STATE));
335 (void *) fprintf(stdout, "%s%s %s/%s\n",
336 getIndentSpaces(8),
337 "HardwareLinkRate(Min/Max):",
338 getPhyStateString(phyinfo->HardwareMinLinkRate, PHY_SPEED),
339 getPhyStateString(phyinfo->HardwareMaxLinkRate, PHY_SPEED));
340 (void *) fprintf(stdout, "%s%s %s/%s\n",
341 getIndentSpaces(8),
342 "ProgrammedLinkRate(Min/Max):",
343 getPhyStateString(phyinfo->ProgrammedMinLinkRate, PHY_SPEED),
344 getPhyStateString(phyinfo->ProgrammedMaxLinkRate, PHY_SPEED));
345 (void *) fprintf(stdout, "%s%s %s\n",
346 getIndentSpaces(8),
347 "NegotiatedLinkRate:",
348 getPhyStateString(phyinfo->NegotiatedLinkRate, PHY_SPEED));
349 }
350
351 void
printHBAPortPhyStatistics(SMHBA_SASPHYSTATISTICS * phystat)352 printHBAPortPhyStatistics(SMHBA_SASPHYSTATISTICS *phystat)
353 {
354 if (phystat == NULL)
355 return;
356
357 (void *) fprintf(stdout, "%s%s\n",
358 getIndentSpaces(8),
359 "Link Error Statistics:");
360 (void *) fprintf(stdout, "%s%s %llu\n",
361 getIndentSpaces(12),
362 "Invalid Dword:",
363 phystat->InvalidDwordCount);
364 (void *) fprintf(stdout, "%s%s %llu\n",
365 getIndentSpaces(12),
366 "Running Disparity Error:",
367 phystat->RunningDisparityErrorCount);
368 (void *) fprintf(stdout, "%s%s %llu\n",
369 getIndentSpaces(12),
370 "Loss of Dword Sync:",
371 phystat->LossofDwordSyncCount);
372 (void *) fprintf(stdout, "%s%s %llu\n",
373 getIndentSpaces(12),
374 "Reset Problem:",
375 phystat->PhyResetProblemCount);
376 }
377
378 /*
379 * print the OS device name for the logical-unit object
380 *
381 * Arguments:
382 * devListWalk - OS device path info
383 * verbose - boolean indicating whether to display additional info
384 *
385 * returns:
386 * 0 - we're good.
387 * >0 - we met issues.
388 */
389 int
printTargetPortInfo(targetPortList_t * TPListWalk,int pflag)390 printTargetPortInfo(targetPortList_t *TPListWalk, int pflag)
391 {
392 targetPortConfig_t *configList;
393 targetPortMappingData_t *mapList;
394 int count, i;
395 int ret = 0;
396
397 (void *) fprintf(stdout, "Target Port SAS Address: %016llx\n",
398 wwnConversion(TPListWalk->sasattr.LocalSASAddress.wwn));
399 if ((pflag & PRINT_VERBOSE) || (pflag & PRINT_TARGET_SCSI)) {
400 (void *) fprintf(stdout, "%sType: %s\n", getIndentSpaces(4),
401 getStateString(TPListWalk->targetattr.PortType,
402 porttype_string));
403 for (configList = TPListWalk->configEntry;
404 configList != NULL; configList = configList->next) {
405 (void *) fprintf(stdout, "%sHBA Port Name: %s\n",
406 getIndentSpaces(4), configList->hbaPortName);
407 if (wwnConversion(configList->expanderSASAddr.wwn) !=
408 0) {
409 if (configList->expanderValid) {
410 (void *) fprintf(stdout,
411 "%sExpander Device SAS Address:"
412 " %016llx",
413 getIndentSpaces(8),
414 wwnConversion(configList->
415 expanderSASAddr.wwn));
416 } else {
417 (void *) fprintf(stdout,
418 "%sExpander Device SAS Address:"
419 " %016llx (Failed to Validate"
420 " Attached Port.)",
421 getIndentSpaces(8),
422 wwnConversion(configList->
423 expanderSASAddr.wwn));
424 ret++;
425 }
426 } else {
427 if (configList->expanderValid) {
428 (void *) fprintf(stdout,
429 "%sExpander Device SAS Address: %s",
430 getIndentSpaces(8),
431 "None (direct attached)");
432 } else {
433 (void *) fprintf(stdout,
434 "%sExpander Device SAS Address: %s",
435 getIndentSpaces(8),
436 "None (Failed to Get"
437 " Attached Port)");
438 }
439 }
440 (void *) fprintf(stdout, "\n");
441 if (pflag & PRINT_TARGET_SCSI) {
442
443 if (configList->reportLUNsFailed) {
444 (void *) fprintf(stdout,
445 "%s %016llx\n",
446 gettext("Error: Failed to get "
447 "ReportLun Data on"),
448 wwnConversion(TPListWalk->
449 sasattr.LocalSASAddress.wwn));
450 ret++;
451 continue;
452 }
453
454 for (mapList = configList->map;
455 mapList != NULL; mapList = mapList->next) {
456 (void *) fprintf(stdout, "%sLUN : %d\n",
457 getIndentSpaces(12),
458 mapList->osLUN);
459 if (mapList->mappingExist) {
460 (void *) fprintf(stdout,
461 "%sOS Device Name : %s\n",
462 getIndentSpaces(14),
463 (mapList->osDeviceName[0] ==
464 '\0') ? "Not avaialble" :
465 mapList->osDeviceName);
466 } else {
467 (void *) fprintf(stdout,
468 "%sOS Device Name : %s\n",
469 getIndentSpaces(14), "No "
470 "matching OS Device "
471 "found.");
472 ret++;
473 }
474 /* indentation changed here */
475 if (mapList->inquiryFailed) {
476 (void *) fprintf(stdout, "%s %s LUN %d\n",
477 gettext("Error: Failed to get Inquiry Data on"),
478 mapList->osDeviceName, mapList->osLUN);
479 ret++;
480 } else {
481 (void *) fprintf(stdout, "%sVendor: ",
482 getIndentSpaces(14));
483 for (count = sizeof (mapList->inq_vid), i = 0;
484 i < count; i++) {
485 if (isprint(mapList->inq_vid[i]))
486 (void *) fprintf(stdout, "%c",
487 mapList->inq_vid[i]);
488 }
489
490 (void *) fprintf(stdout, "\n%sProduct: ",
491 getIndentSpaces(14));
492 for (count = sizeof (mapList->inq_pid), i = 0;
493 i < count; i++) {
494 if (isprint(mapList->inq_pid[i]))
495 (void *) fprintf(stdout, "%c",
496 mapList->inq_pid[i]);
497 }
498
499 (void *) fprintf(stdout, "\n%sDevice Type: %s\n",
500 getIndentSpaces(14),
501 getDTypeString(mapList->inq_dtype));
502 }
503 /* indentation changed back */
504 }
505 }
506 }
507 }
508 return (ret);
509 }
510
511 /*
512 * print the OS device name for the logical-unit object
513 *
514 * Arguments:
515 * devListWalk - OS device path info
516 * verbose - boolean indicating whether to display additional info
517 *
518 * returns:
519 * 0 - we're good.
520 * >0 - we met issues.
521 */
522 int
printOSDeviceNameInfo(discoveredDevice * devListWalk,boolean_t verbose)523 printOSDeviceNameInfo(discoveredDevice *devListWalk, boolean_t verbose)
524 {
525 portList *portElem;
526 tgtPortWWNList *tgtWWNList;
527 int i, count;
528 int ret = 0;
529
530 (void *) fprintf(stdout, "OS Device Name: %s\n",
531 devListWalk->OSDeviceName);
532 if (verbose == B_TRUE) {
533 for (portElem = devListWalk->HBAPortList;
534 portElem != NULL; portElem = portElem->next) {
535 (void *) fprintf(stdout, "%sHBA Port Name: ",
536 getIndentSpaces(4));
537 (void *) fprintf(stdout, "%s", portElem->portName);
538 for (tgtWWNList = portElem->tgtPortWWN;
539 tgtWWNList != NULL; tgtWWNList = tgtWWNList->next) {
540 (void *) fprintf(stdout,
541 "\n%sTarget Port SAS Address: ",
542 getIndentSpaces(8));
543 (void *) fprintf(stdout, "%016llx",
544 wwnConversion(tgtWWNList->portWWN.wwn));
545 (void *) fprintf(stdout, "\n%sLUN: %u",
546 getIndentSpaces(12),
547 tgtWWNList->scsiOSLun);
548 }
549 (void *) fprintf(stdout, "\n");
550 }
551
552 if (devListWalk->inquiryFailed) {
553 (void *) fprintf(stdout, "%s %s\n",
554 gettext("Error: Failed to get Inquiry data "
555 "on device"), devListWalk->OSDeviceName);
556 ret++;
557 } else {
558 (void *) fprintf(stdout, "%sVendor: ",
559 getIndentSpaces(4));
560 for (count = sizeof (devListWalk->VID), i = 0;
561 i < count; i++) {
562 if (isprint(devListWalk->VID[i]))
563 (void *) fprintf(stdout, "%c",
564 devListWalk->VID[i]);
565 }
566
567 (void *) fprintf(stdout, "\n%sProduct: ",
568 getIndentSpaces(4));
569 for (count = sizeof (devListWalk->PID), i = 0;
570 i < count; i++) {
571 if (isprint(devListWalk->PID[i]))
572 (void *) fprintf(stdout, "%c",
573 devListWalk->PID[i]);
574 }
575
576 (void *) fprintf(stdout, "\n%sDevice Type: %s\n",
577 getIndentSpaces(4),
578 getDTypeString(devListWalk->dType));
579 }
580 }
581 return (ret);
582 }
583