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