/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2015 PALO, Richard
*/
#include <sys/ccompile.h>
#include <sys/byteorder.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <strings.h>
#include <ctype.h>
#include <scsi/libsmp_plugin.h>
static void fatal(int, const char *, ...) __NORETURN;
static void
{
}
static char *
{
switch (result) {
return ("Function accepted");
break;
case SMP_RES_UNKNOWN_FUNCTION:
return ("Unknown function");
break;
case SMP_RES_FUNCTION_FAILED:
return ("Function failed");
break;
return ("Invalid request frame length");
break;
return ("Invalid expander change count");
break;
case SMP_RES_BUSY:
return ("Busy");
break;
return ("Incomplete descriptor list");
break;
return ("PHY does not exist");
break;
return ("Index does not exist");
break;
return ("PHY does not support SATA");
break;
return ("Unknown PHY operation");
break;
return ("Unknown PHY test function");
break;
return ("PHY test in progress");
break;
case SMP_RES_PHY_VACANT:
return ("PHY vacant");
break;
return ("Unknown PHY event source");
break;
return ("Unknown descriptor type");
break;
return ("Unknown PHY filter");
break;
return ("Affiliation violation");
break;
case SMP_RES_ZONE_VIOLATION:
return ("Zone violation");
break;
return ("No management access rights");
break;
break;
return ("Zone lock violation");
break;
case SMP_RES_NOT_ACTIVATED:
return ("Not activated");
break;
return ("Zone group out of range");
break;
return ("No physical presence");
break;
return ("Saving not supported");
break;
return ("Source zone group does not exist");
break;
return ("Disabled password not supported");
break;
default:
break;
}
return (NULL);
}
static void
{
smp_fini();
}
}
static void
{
if (smp_result_str == NULL) {
result);
} else {
}
}
static void
{
smp_fini();
}
}
static void
{
if (tp) {
}
smp_fini();
}
/* ARGSUSED */
static void
{
/*
* Verify the expander supports the PHY-based expander route table
*/
if (route_indexes == 0) {
smp_cleanup();
}
ri_idx = 0;
pi_idx = 0;
smp_cleanup();
} else {
}
(void) printf("%6s %6s %3s %14s\n",
"RT Idx", "PHY ID", "DIS", "Routed SASAddr");
smp_execute();
if (result != SMP_RES_FUNCTION_ACCEPTED) {
pi_idx++;
continue;
}
if (rirp->srrir_exp_route_entry_disabled == 0) {
(void) printf("%6d %6d %3d %016llx\n",
}
pi_idx++;
}
ri_idx++;
pi_idx = 0;
}
if (!enabled_entries) {
(void) printf("No enabled entries in the table.\n");
}
smp_cleanup();
exit(0);
}
static char *
{
char *src_str;
*peak_detector = B_FALSE;
switch (src) {
case SMP_PHY_EVENT_NO_EVENT:
src_str = "No event";
break;
src_str = "Invalid DWORD count";
break;
src_str = "Running disparity error count";
break;
src_str = "Loss of DWORD sync count";
break;
src_str = "PHY reset problem count";
break;
src_str = "Elasticity buffer overflow count";
break;
src_str = "Received ERROR count";
break;
src_str = "Received address frame error count";
break;
src_str = "Transmitted abandon-class OPEN_REJECT count";
break;
src_str = "Received abandon-class OPEN_REJECT count";
break;
src_str = "Transmitted retry-class OPEN_REJECT count";
break;
src_str = "Received retry-class OPEN_REJECT count";
break;
src_str = "Received AIP (WAITING ON PARTIAL) count";
break;
src_str = "Received AIP (WAITING ON CONNECTION) count";
break;
src_str = "Transmitted BREAK count";
break;
src_str = "Received BREAK count";
break;
src_str = "BREAK timeout count";
break;
src_str = "Connection count";
break;
src_str = "Peak transmitted pathway blocked count";
*peak_detector = B_TRUE;
break;
src_str = "Peak transmitted arbitration wait time";
*peak_detector = B_TRUE;
break;
src_str = "Peak arbitration time";
*peak_detector = B_TRUE;
break;
src_str = "Peak connection time";
*peak_detector = B_TRUE;
break;
src_str = "Transmitted SSP frame count";
break;
src_str = "Received SSP frame count";
break;
src_str = "Transmitted SSP frame error count";
break;
src_str = "Received SSP frame error count";
break;
src_str = "Transmitted CREDIT_BLOCKED count";
break;
src_str = "Received CREDIT_BLOCKED count";
break;
src_str = "Transmitted SATA frame count";
break;
src_str = "Received SATA frame count";
break;
src_str = "SATA flow control buffer overflow count";
break;
src_str = "Transmitted SMP frame count";
break;
src_str = "Received SMP frame count";
break;
src_str = "Received SMP frame error count";
break;
default:
src_str = "<Unknown>";
break;
}
return (src_str);
}
static void
{
errno = 0;
if (argc < 3)
if (errno != 0)
switch (func) {
case SMP_FUNC_DISCOVER:
case SMP_FUNC_REPORT_PHY_ERROR_LOG: {
if (argc != 4) {
fatal(-1,
"Usage: %s <device> 0x%x <phy identifier>\n",
}
break;
}
if (argc < 4) {
fatal(-1,
"Usage: %s <device> 0x%x <SAS Address Index>\n",
}
break;
}
if (argc < 4) {
fatal(-1,
"Usage: %s <device> 0x%x <report type>\n",
}
break;
}
case SMP_FUNC_ENABLE_DISABLE_ZONING: {
if (argc != 4) {
fatal(-1,
"Usage: %s <device> 0x%x "
"[0(no change) | 1(enable)| 2(disable)]\n",
}
break;
}
case SMP_FUNC_REPORT_BROADCAST: {
if (argc != 4) {
}
break;
}
case SMP_FUNC_REPORT_ROUTE_INFO: {
if (argc != 5) {
fatal(-1,
"Usage: %s <device> 0x%x <exp_route_idx> "
}
break;
}
case SMP_FUNC_PHY_CONTROL: {
if (argc != 5) {
fatal(-1,
"Usage: %s <device> 0x%x <phy identifier> "
" <phy operation>\n",
}
break;
}
default: {
break;
}
}
}
int
{
uint_t i, j;
char *yesorno;
/*
* If the arguments are invalid, this function will not return.
*/
if (smp_init(LIBSMP_VERSION) != 0)
smp_fini();
}
smp_fini();
}
switch (func) {
case SMP_FUNC_DISCOVER: {
break;
}
case SMP_FUNC_REPORT_ROUTE_INFO: {
break;
}
case SMP_FUNC_ENABLE_DISABLE_ZONING: {
break;
}
case SMP_FUNC_PHY_CONTROL: {
break;
}
break;
}
case SMP_FUNC_REPORT_PHY_ERROR_LOG: {
break;
}
case SMP_FUNC_REPORT_PHY_EVENT: {
break;
}
break;
}
case SMP_FUNC_REPORT_BROADCAST: {
break;
}
default:
smp_fini();
}
smp_execute();
switch (func) {
case SMP_FUNC_DISCOVER: {
(void) printf("Addr: %016llx Phy: %02x\n",
(void) printf("Peer: %016llx Phy: %02x\n",
(void) printf("Device type: %01x\n",
break;
}
int idx;
switch (rp->srzmpr_rpt_type) {
case SMP_ZMP_TYPE_CURRENT:
rpt_type = "Current";
break;
case SMP_ZMP_TYPE_SAVED:
rpt_type = "Saved";
break;
case SMP_ZMP_TYPE_DEFAULT:
rpt_type = "Default";
break;
default:
rpt_type = "(Unknown Type)";
break;
}
(void) printf("%02x",
}
(void) printf("\n");
break;
}
(void) printf("Expander change count: 0x%04x\n",
(void) printf("Expander route table change count: 0x%04x\n",
if (rtlr->srertlr_zoning_enabled) {
zoning = 1;
} else {
zoning = 0;
}
if (rtlr->srertlr_configuring) {
} else {
}
(void) printf("Starting PHY identifier: %d\n",
(void) printf("#%03d: Routed SAS addr: %016llx ",
(void) printf("PHY bitmap: 0x");
(void) printf("%02x",
}
(void) printf("\n");
if (zoning) {
(void) printf("\tZone group: %d\n",
}
}
(void) printf("\n");
break;
}
case SMP_FUNC_REPORT_PHY_ERROR_LOG: {
(void) printf("PHY error log for PHY %d:\n",
(void) printf("\tInvalid DWORD count: %d\n",
(void) printf("\tRunning disparity error count: %d\n",
(void) printf("\tLoss of DWORD sync count: %d\n",
(void) printf("\tPHY reset problem count: %d\n",
break;
}
case SMP_FUNC_REPORT_PHY_EVENT: {
&rper->srper_phy_event_descrs[0];
int idx;
(void) printf("PHY event for PHY %d:\n",
(void) printf("Number of PHY event descriptors: %d\n",
(void) printf("%50s : %d\n",
if (peak) {
(void) printf("\tPeak value detector "
"threshold: %d\n",
}
perd++;
}
break;
}
case SMP_FUNC_REPORT_BROADCAST: {
(void) printf("\tNumber of broadcast descriptors: %d\n",
bcount);
(void) printf("\t%7s %5s %5s %8s\n",
"BCType", "PhyID", "BCRsn", "BC Count");
(void) printf("\t%7s %5s %5s %8s\n",
bdp++;
}
break;
}
default:
for (i = 0; i < smp_resp_len; i += 8) {
(void) printf("%02x: ", i);
for (j = i; j < i + 8; j++)
if (j < smp_resp_len)
else
(void) printf(" ");
for (j = i; j < i + 8; j++)
(void) printf("%c",
'\0');
(void) printf("\n");
}
break;
}
smp_cleanup();
return (0);
}