1*10652SHyon.Kim@Sun.COM /*
2*10652SHyon.Kim@Sun.COM * CDDL HEADER START
3*10652SHyon.Kim@Sun.COM *
4*10652SHyon.Kim@Sun.COM * The contents of this file are subject to the terms of the
5*10652SHyon.Kim@Sun.COM * Common Development and Distribution License (the "License").
6*10652SHyon.Kim@Sun.COM * You may not use this file except in compliance with the License.
7*10652SHyon.Kim@Sun.COM *
8*10652SHyon.Kim@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*10652SHyon.Kim@Sun.COM * or http://www.opensolaris.org/os/licensing.
10*10652SHyon.Kim@Sun.COM * See the License for the specific language governing permissions
11*10652SHyon.Kim@Sun.COM * and limitations under the License.
12*10652SHyon.Kim@Sun.COM *
13*10652SHyon.Kim@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
14*10652SHyon.Kim@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*10652SHyon.Kim@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
16*10652SHyon.Kim@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
17*10652SHyon.Kim@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
18*10652SHyon.Kim@Sun.COM *
19*10652SHyon.Kim@Sun.COM * CDDL HEADER END
20*10652SHyon.Kim@Sun.COM */
21*10652SHyon.Kim@Sun.COM /*
22*10652SHyon.Kim@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23*10652SHyon.Kim@Sun.COM * Use is subject to license terms.
24*10652SHyon.Kim@Sun.COM */
25*10652SHyon.Kim@Sun.COM
26*10652SHyon.Kim@Sun.COM #include <unistd.h>
27*10652SHyon.Kim@Sun.COM #include <stdlib.h>
28*10652SHyon.Kim@Sun.COM #include <ctype.h>
29*10652SHyon.Kim@Sun.COM #include <errno.h>
30*10652SHyon.Kim@Sun.COM #include <printAttrs.h>
31*10652SHyon.Kim@Sun.COM #include <smhbaapi.h>
32*10652SHyon.Kim@Sun.COM
33*10652SHyon.Kim@Sun.COM #define TABLEN 2
34*10652SHyon.Kim@Sun.COM typedef struct inputArgs {
35*10652SHyon.Kim@Sun.COM int wwnCount;
36*10652SHyon.Kim@Sun.COM char **wwn_argv;
37*10652SHyon.Kim@Sun.COM uint64_t portWWN;
38*10652SHyon.Kim@Sun.COM char *hbaName;
39*10652SHyon.Kim@Sun.COM int pflag;
40*10652SHyon.Kim@Sun.COM int *wwn_flag;
41*10652SHyon.Kim@Sun.COM } inputArg_t;
42*10652SHyon.Kim@Sun.COM
43*10652SHyon.Kim@Sun.COM typedef struct tgt_mapping {
44*10652SHyon.Kim@Sun.COM SMHBA_SCSIENTRY tgtentry;
45*10652SHyon.Kim@Sun.COM uchar_t inq_vid[8];
46*10652SHyon.Kim@Sun.COM uchar_t inq_pid[16];
47*10652SHyon.Kim@Sun.COM uchar_t inq_dtype;
48*10652SHyon.Kim@Sun.COM struct tgt_mapping *next;
49*10652SHyon.Kim@Sun.COM }tgt_mapping;
50*10652SHyon.Kim@Sun.COM
51*10652SHyon.Kim@Sun.COM /*
52*10652SHyon.Kim@Sun.COM * Remote port tree node structure.
53*10652SHyon.Kim@Sun.COM */
54*10652SHyon.Kim@Sun.COM typedef struct smhba_rp_tree {
55*10652SHyon.Kim@Sun.COM SMHBA_PORTATTRIBUTES portattr;
56*10652SHyon.Kim@Sun.COM SMHBA_SAS_PORT sasattr;
57*10652SHyon.Kim@Sun.COM tgt_mapping *first_entry;
58*10652SHyon.Kim@Sun.COM int printed;
59*10652SHyon.Kim@Sun.COM struct smhba_rp_tree *parent;
60*10652SHyon.Kim@Sun.COM struct smhba_rp_tree *child;
61*10652SHyon.Kim@Sun.COM struct smhba_rp_tree *sibling;
62*10652SHyon.Kim@Sun.COM }rp_tree_t;
63*10652SHyon.Kim@Sun.COM
64*10652SHyon.Kim@Sun.COM /*
65*10652SHyon.Kim@Sun.COM * Report LUN data structure.
66*10652SHyon.Kim@Sun.COM */
67*10652SHyon.Kim@Sun.COM struct lun {
68*10652SHyon.Kim@Sun.COM uchar_t val[8];
69*10652SHyon.Kim@Sun.COM };
70*10652SHyon.Kim@Sun.COM
71*10652SHyon.Kim@Sun.COM typedef struct rep_luns_rsp {
72*10652SHyon.Kim@Sun.COM uint32_t length;
73*10652SHyon.Kim@Sun.COM uint32_t rsrvd;
74*10652SHyon.Kim@Sun.COM struct lun lun[1];
75*10652SHyon.Kim@Sun.COM } rep_luns_rsp_t;
76*10652SHyon.Kim@Sun.COM
77*10652SHyon.Kim@Sun.COM /*
78*10652SHyon.Kim@Sun.COM * The following flag is used for printing HBA header on-demand.
79*10652SHyon.Kim@Sun.COM */
80*10652SHyon.Kim@Sun.COM static int g_printHBA = 0;
81*10652SHyon.Kim@Sun.COM
82*10652SHyon.Kim@Sun.COM /*
83*10652SHyon.Kim@Sun.COM * The following structure is for sorted output of HBA and HBA Port.
84*10652SHyon.Kim@Sun.COM */
85*10652SHyon.Kim@Sun.COM typedef struct _sas_elem {
86*10652SHyon.Kim@Sun.COM char name[256];
87*10652SHyon.Kim@Sun.COM int index;
88*10652SHyon.Kim@Sun.COM }sas_elem_t;
89*10652SHyon.Kim@Sun.COM
90*10652SHyon.Kim@Sun.COM /*
91*10652SHyon.Kim@Sun.COM * The following two functions are for generating hierachy of expander
92*10652SHyon.Kim@Sun.COM * subcommand.
93*10652SHyon.Kim@Sun.COM */
94*10652SHyon.Kim@Sun.COM static int
95*10652SHyon.Kim@Sun.COM sas_rp_tree_insert(rp_tree_t **rproot, rp_tree_t *rpnode);
96*10652SHyon.Kim@Sun.COM static int
97*10652SHyon.Kim@Sun.COM sas_rp_tree_print(HBA_HANDLE handle, char *adapterName,
98*10652SHyon.Kim@Sun.COM HBA_UINT32 portIndex, SMHBA_PORTATTRIBUTES *port,
99*10652SHyon.Kim@Sun.COM rp_tree_t *rpnode, inputArg_t *input, int gident,
100*10652SHyon.Kim@Sun.COM int *printPort);
101*10652SHyon.Kim@Sun.COM static int
102*10652SHyon.Kim@Sun.COM sas_rp_tree_print_desc(HBA_HANDLE handle, HBA_UINT32 portIndex,
103*10652SHyon.Kim@Sun.COM SMHBA_PORTATTRIBUTES *port, rp_tree_t *desc,
104*10652SHyon.Kim@Sun.COM inputArg_t *input, int lident, int gident);
105*10652SHyon.Kim@Sun.COM static int
106*10652SHyon.Kim@Sun.COM sas_print_rpnode(inputArg_t *input,
107*10652SHyon.Kim@Sun.COM rp_tree_t *rpnode, int lident, int gident);
108*10652SHyon.Kim@Sun.COM static void sas_rp_tree_free(rp_tree_t *rproot);
109*10652SHyon.Kim@Sun.COM
110*10652SHyon.Kim@Sun.COM typedef int (*processPortFunc)(HBA_HANDLE handle, char *adapterName,
111*10652SHyon.Kim@Sun.COM HBA_UINT32 portIndex, SMHBA_PORTATTRIBUTES *port,
112*10652SHyon.Kim@Sun.COM SMHBA_ADAPTERATTRIBUTES *attrs, inputArg_t *input);
113*10652SHyon.Kim@Sun.COM
114*10652SHyon.Kim@Sun.COM static int processHBA(inputArg_t *input,
115*10652SHyon.Kim@Sun.COM processPortFunc processPort);
116*10652SHyon.Kim@Sun.COM
117*10652SHyon.Kim@Sun.COM static int isPortWWNInArgv(inputArg_t *input, PHBA_WWN pWWN);
118*10652SHyon.Kim@Sun.COM static int isStringInArgv(inputArg_t *input, const char *adapterName);
119*10652SHyon.Kim@Sun.COM static boolean_t compareLUName(char *cmdArg, char *osName);
120*10652SHyon.Kim@Sun.COM static discoveredDevice *LUList = NULL;
121*10652SHyon.Kim@Sun.COM static targetPortList_t *gTargetPortList = NULL;
122*10652SHyon.Kim@Sun.COM
123*10652SHyon.Kim@Sun.COM /* processes for hanlding local HBA info */
124*10652SHyon.Kim@Sun.COM static int handleHBA(SMHBA_ADAPTERATTRIBUTES *attrs, inputArg_t *input,
125*10652SHyon.Kim@Sun.COM int numberOfPorts, const char *adapterName);
126*10652SHyon.Kim@Sun.COM static int handleHBAPort(HBA_HANDLE handle, char *adapterName,
127*10652SHyon.Kim@Sun.COM HBA_UINT32 portIndex, SMHBA_PORTATTRIBUTES *port,
128*10652SHyon.Kim@Sun.COM SMHBA_ADAPTERATTRIBUTES *attrs, inputArg_t *input);
129*10652SHyon.Kim@Sun.COM static int processHBAPortPhyInfo(HBA_HANDLE handle, HBA_UINT32 portIndex,
130*10652SHyon.Kim@Sun.COM SMHBA_PORTATTRIBUTES *port, int pflag);
131*10652SHyon.Kim@Sun.COM static int processHBAPortPhyStat(HBA_HANDLE handle, HBA_UINT32 portIndex,
132*10652SHyon.Kim@Sun.COM int phyIndex, PSMHBA_SAS_PHY phyattrs, int pflag);
133*10652SHyon.Kim@Sun.COM
134*10652SHyon.Kim@Sun.COM /* process for handling expander info */
135*10652SHyon.Kim@Sun.COM static int handleExpander(HBA_HANDLE handle, char *adapterName,
136*10652SHyon.Kim@Sun.COM HBA_UINT32 portIndex, SMHBA_PORTATTRIBUTES *port,
137*10652SHyon.Kim@Sun.COM SMHBA_ADAPTERATTRIBUTES *attrs, inputArg_t *input);
138*10652SHyon.Kim@Sun.COM
139*10652SHyon.Kim@Sun.COM /* process for handling target port info */
140*10652SHyon.Kim@Sun.COM static int handleTargetPort(HBA_HANDLE handle, char *adapterName,
141*10652SHyon.Kim@Sun.COM HBA_UINT32 portIndex, SMHBA_PORTATTRIBUTES *port,
142*10652SHyon.Kim@Sun.COM SMHBA_ADAPTERATTRIBUTES *attrs, inputArg_t *input);
143*10652SHyon.Kim@Sun.COM
144*10652SHyon.Kim@Sun.COM /* process for handling logical unit info */
145*10652SHyon.Kim@Sun.COM static int handleLogicalUnit(HBA_HANDLE handle, char *adapterName,
146*10652SHyon.Kim@Sun.COM HBA_UINT32 portIndex, SMHBA_PORTATTRIBUTES *port,
147*10652SHyon.Kim@Sun.COM SMHBA_ADAPTERATTRIBUTES *attrs, inputArg_t *input);
148*10652SHyon.Kim@Sun.COM
149*10652SHyon.Kim@Sun.COM /* process for target port SCSI processing */
150*10652SHyon.Kim@Sun.COM static int
151*10652SHyon.Kim@Sun.COM searchTargetPortMappingData(HBA_HANDLE handle, HBA_UINT32 portIndex,
152*10652SHyon.Kim@Sun.COM SMHBA_PORTATTRIBUTES *port, SMHBA_SAS_PORT *sasattr,
153*10652SHyon.Kim@Sun.COM struct targetPortConfig *configData);
154*10652SHyon.Kim@Sun.COM
155*10652SHyon.Kim@Sun.COM /* process for target port config processing */
156*10652SHyon.Kim@Sun.COM static int searchTargetPort(HBA_HANDLE handle, HBA_UINT32 portIndex,
157*10652SHyon.Kim@Sun.COM SMHBA_PORTATTRIBUTES *port, SMHBA_PORTATTRIBUTES *targetattr,
158*10652SHyon.Kim@Sun.COM SMHBA_SAS_PORT *sasattr, int pflag);
159*10652SHyon.Kim@Sun.COM
160*10652SHyon.Kim@Sun.COM /* process for logical-unit config processing */
161*10652SHyon.Kim@Sun.COM static int
162*10652SHyon.Kim@Sun.COM searchDevice(PSMHBA_SCSIENTRY entryP, HBA_HANDLE handle, HBA_WWN hbaPortWWN,
163*10652SHyon.Kim@Sun.COM HBA_WWN domainPortWWN, char *portName, int pflag);
164*10652SHyon.Kim@Sun.COM
165*10652SHyon.Kim@Sun.COM /* get domain port out of hba-port phy attr. */
166*10652SHyon.Kim@Sun.COM HBA_STATUS get_domainPort(HBA_HANDLE handle,
167*10652SHyon.Kim@Sun.COM int portindex, PSMHBA_PORTATTRIBUTES port,
168*10652SHyon.Kim@Sun.COM HBA_WWN *pdomainPort);
169*10652SHyon.Kim@Sun.COM
170*10652SHyon.Kim@Sun.COM static int
171*10652SHyon.Kim@Sun.COM sas_name_comp(const char *name1, const char *name2);
172*10652SHyon.Kim@Sun.COM static void
173*10652SHyon.Kim@Sun.COM sas_elem_sort(sas_elem_t *array, int nelem);
174*10652SHyon.Kim@Sun.COM
175*10652SHyon.Kim@Sun.COM /*
176*10652SHyon.Kim@Sun.COM * function for hba subcommand
177*10652SHyon.Kim@Sun.COM *
178*10652SHyon.Kim@Sun.COM * Arguments:
179*10652SHyon.Kim@Sun.COM * wwnCount - count of the number of WWNs in wwn_argv
180*10652SHyon.Kim@Sun.COM * if wwnCount > 0, then we will only print information for
181*10652SHyon.Kim@Sun.COM * the hba ports listed in wwn_argv
182*10652SHyon.Kim@Sun.COM * if wwnCount == 0, then we will print information on all hba ports
183*10652SHyon.Kim@Sun.COM * wwn_argv - argument array of hba port WWNs
184*10652SHyon.Kim@Sun.COM * options - any options specified by the caller
185*10652SHyon.Kim@Sun.COM *
186*10652SHyon.Kim@Sun.COM * returns:
187*10652SHyon.Kim@Sun.COM * 0 if successful
188*10652SHyon.Kim@Sun.COM * >0 otherwise
189*10652SHyon.Kim@Sun.COM */
190*10652SHyon.Kim@Sun.COM int
sas_util_list_hba(int hbaCount,char ** hba_argv,cmdOptions_t * options)191*10652SHyon.Kim@Sun.COM sas_util_list_hba(int hbaCount, char **hba_argv, cmdOptions_t *options)
192*10652SHyon.Kim@Sun.COM {
193*10652SHyon.Kim@Sun.COM HBA_STATUS status;
194*10652SHyon.Kim@Sun.COM int processHBA_flags = 0;
195*10652SHyon.Kim@Sun.COM inputArg_t input;
196*10652SHyon.Kim@Sun.COM int err_cnt = 0;
197*10652SHyon.Kim@Sun.COM
198*10652SHyon.Kim@Sun.COM /* process each of the options */
199*10652SHyon.Kim@Sun.COM for (; options->optval; options++) {
200*10652SHyon.Kim@Sun.COM switch (options->optval) {
201*10652SHyon.Kim@Sun.COM case 'v':
202*10652SHyon.Kim@Sun.COM processHBA_flags |= PRINT_VERBOSE;
203*10652SHyon.Kim@Sun.COM break;
204*10652SHyon.Kim@Sun.COM default:
205*10652SHyon.Kim@Sun.COM break;
206*10652SHyon.Kim@Sun.COM }
207*10652SHyon.Kim@Sun.COM }
208*10652SHyon.Kim@Sun.COM
209*10652SHyon.Kim@Sun.COM if ((status = HBA_LoadLibrary()) != HBA_STATUS_OK) {
210*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "%s %s\n",
211*10652SHyon.Kim@Sun.COM gettext("Failed to load SM-HBA libraries."
212*10652SHyon.Kim@Sun.COM "Reason:"), getHBAStatus(status));
213*10652SHyon.Kim@Sun.COM err_cnt++;
214*10652SHyon.Kim@Sun.COM return (err_cnt);
215*10652SHyon.Kim@Sun.COM }
216*10652SHyon.Kim@Sun.COM
217*10652SHyon.Kim@Sun.COM (void *) memset(&input, 0, sizeof (input));
218*10652SHyon.Kim@Sun.COM /* utilize wwnCount and wwn_argv for hbaCount and hba_argv */
219*10652SHyon.Kim@Sun.COM input.wwnCount = hbaCount;
220*10652SHyon.Kim@Sun.COM input.wwn_argv = hba_argv;
221*10652SHyon.Kim@Sun.COM input.pflag = processHBA_flags;
222*10652SHyon.Kim@Sun.COM
223*10652SHyon.Kim@Sun.COM /*
224*10652SHyon.Kim@Sun.COM * Process and filter for every local hba,
225*10652SHyon.Kim@Sun.COM * when the hba is not specificed, print all hba(s).
226*10652SHyon.Kim@Sun.COM */
227*10652SHyon.Kim@Sun.COM err_cnt += processHBA(&input, NULL);
228*10652SHyon.Kim@Sun.COM
229*10652SHyon.Kim@Sun.COM (void) HBA_FreeLibrary();
230*10652SHyon.Kim@Sun.COM
231*10652SHyon.Kim@Sun.COM return (err_cnt);
232*10652SHyon.Kim@Sun.COM }
233*10652SHyon.Kim@Sun.COM
234*10652SHyon.Kim@Sun.COM /*
235*10652SHyon.Kim@Sun.COM * function for hba-port subcommand
236*10652SHyon.Kim@Sun.COM *
237*10652SHyon.Kim@Sun.COM * Arguments:
238*10652SHyon.Kim@Sun.COM * wwnCount - count of the number of WWNs in wwn_argv
239*10652SHyon.Kim@Sun.COM * if wwnCount > 0, then we will only print information for
240*10652SHyon.Kim@Sun.COM * the hba ports listed in wwn_argv
241*10652SHyon.Kim@Sun.COM * if wwnCount == 0, then we will print information on all hba ports
242*10652SHyon.Kim@Sun.COM * wwn_argv - argument array of hba port WWNs
243*10652SHyon.Kim@Sun.COM * options - any options specified by the caller
244*10652SHyon.Kim@Sun.COM *
245*10652SHyon.Kim@Sun.COM * returns:
246*10652SHyon.Kim@Sun.COM * 0 if successful
247*10652SHyon.Kim@Sun.COM * >0 otherwise
248*10652SHyon.Kim@Sun.COM */
249*10652SHyon.Kim@Sun.COM int
sas_util_list_hbaport(int wwnCount,char ** wwn_argv,cmdOptions_t * options)250*10652SHyon.Kim@Sun.COM sas_util_list_hbaport(int wwnCount, char **wwn_argv, cmdOptions_t *options)
251*10652SHyon.Kim@Sun.COM {
252*10652SHyon.Kim@Sun.COM HBA_STATUS status;
253*10652SHyon.Kim@Sun.COM int processHBA_flags = 0;
254*10652SHyon.Kim@Sun.COM inputArg_t input;
255*10652SHyon.Kim@Sun.COM int err_cnt = 0;
256*10652SHyon.Kim@Sun.COM char hbaName[256] = {'\0'};
257*10652SHyon.Kim@Sun.COM
258*10652SHyon.Kim@Sun.COM /* process each of the options */
259*10652SHyon.Kim@Sun.COM for (; options->optval; options++) {
260*10652SHyon.Kim@Sun.COM switch (options->optval) {
261*10652SHyon.Kim@Sun.COM case 'a':
262*10652SHyon.Kim@Sun.COM (void *) strlcpy(hbaName,
263*10652SHyon.Kim@Sun.COM options->optarg, sizeof (hbaName));
264*10652SHyon.Kim@Sun.COM break;
265*10652SHyon.Kim@Sun.COM case 'y':
266*10652SHyon.Kim@Sun.COM processHBA_flags |= PRINT_PHY;
267*10652SHyon.Kim@Sun.COM break;
268*10652SHyon.Kim@Sun.COM case 'l':
269*10652SHyon.Kim@Sun.COM processHBA_flags |= PRINT_PHY_LINKSTAT;
270*10652SHyon.Kim@Sun.COM break;
271*10652SHyon.Kim@Sun.COM case 'v':
272*10652SHyon.Kim@Sun.COM processHBA_flags |= PRINT_VERBOSE;
273*10652SHyon.Kim@Sun.COM break;
274*10652SHyon.Kim@Sun.COM default:
275*10652SHyon.Kim@Sun.COM break;
276*10652SHyon.Kim@Sun.COM }
277*10652SHyon.Kim@Sun.COM }
278*10652SHyon.Kim@Sun.COM
279*10652SHyon.Kim@Sun.COM if ((status = HBA_LoadLibrary()) != HBA_STATUS_OK) {
280*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "%s %s\n",
281*10652SHyon.Kim@Sun.COM gettext("Failed to load SM-HBA libraries."
282*10652SHyon.Kim@Sun.COM "Reason:"), getHBAStatus(status));
283*10652SHyon.Kim@Sun.COM err_cnt++;
284*10652SHyon.Kim@Sun.COM return (err_cnt);
285*10652SHyon.Kim@Sun.COM }
286*10652SHyon.Kim@Sun.COM
287*10652SHyon.Kim@Sun.COM (void *) memset(&input, 0, sizeof (input));
288*10652SHyon.Kim@Sun.COM input.wwnCount = wwnCount;
289*10652SHyon.Kim@Sun.COM input.wwn_argv = wwn_argv;
290*10652SHyon.Kim@Sun.COM input.hbaName = hbaName;
291*10652SHyon.Kim@Sun.COM input.pflag = processHBA_flags;
292*10652SHyon.Kim@Sun.COM
293*10652SHyon.Kim@Sun.COM /*
294*10652SHyon.Kim@Sun.COM * Process and filter for every local hba-port,
295*10652SHyon.Kim@Sun.COM * when the hba-port is not specificed, print all hba-port(s).
296*10652SHyon.Kim@Sun.COM */
297*10652SHyon.Kim@Sun.COM err_cnt += processHBA(&input, handleHBAPort);
298*10652SHyon.Kim@Sun.COM
299*10652SHyon.Kim@Sun.COM (void) HBA_FreeLibrary();
300*10652SHyon.Kim@Sun.COM
301*10652SHyon.Kim@Sun.COM return (err_cnt);
302*10652SHyon.Kim@Sun.COM }
303*10652SHyon.Kim@Sun.COM
304*10652SHyon.Kim@Sun.COM /*
305*10652SHyon.Kim@Sun.COM * function for expander subcommand
306*10652SHyon.Kim@Sun.COM *
307*10652SHyon.Kim@Sun.COM * Arguments:
308*10652SHyon.Kim@Sun.COM * wwnCount - the number of Remote Port SAS Address in wwn_argv
309*10652SHyon.Kim@Sun.COM * if wwnCount == 0, then print information on all
310*10652SHyon.Kim@Sun.COM * expander devices.
311*10652SHyon.Kim@Sun.COM * if wwnCount > 0, then print information for the exapnders
312*10652SHyon.Kim@Sun.COM * given in wwn_argv.
313*10652SHyon.Kim@Sun.COM * wwn_argv - array of WWNs
314*10652SHyon.Kim@Sun.COM * options - options specified by the caller
315*10652SHyon.Kim@Sun.COM *
316*10652SHyon.Kim@Sun.COM * returns:
317*10652SHyon.Kim@Sun.COM * 0 if successful
318*10652SHyon.Kim@Sun.COM * >0 otherwise
319*10652SHyon.Kim@Sun.COM */
320*10652SHyon.Kim@Sun.COM int
sas_util_list_expander(int wwnCount,char ** wwn_argv,cmdOptions_t * options)321*10652SHyon.Kim@Sun.COM sas_util_list_expander(int wwnCount, char **wwn_argv, cmdOptions_t *options)
322*10652SHyon.Kim@Sun.COM {
323*10652SHyon.Kim@Sun.COM HBA_STATUS status;
324*10652SHyon.Kim@Sun.COM int processHBA_flags = 0;
325*10652SHyon.Kim@Sun.COM char hbaPort[MAXPATHLEN + 1] = {0};
326*10652SHyon.Kim@Sun.COM inputArg_t input;
327*10652SHyon.Kim@Sun.COM int err_cnt = 0;
328*10652SHyon.Kim@Sun.COM
329*10652SHyon.Kim@Sun.COM /* process each of the options */
330*10652SHyon.Kim@Sun.COM for (; options->optval; options++) {
331*10652SHyon.Kim@Sun.COM switch (options->optval) {
332*10652SHyon.Kim@Sun.COM case 'p':
333*10652SHyon.Kim@Sun.COM (void) strlcpy(hbaPort, options->optarg,
334*10652SHyon.Kim@Sun.COM sizeof (hbaPort));
335*10652SHyon.Kim@Sun.COM break;
336*10652SHyon.Kim@Sun.COM case 't':
337*10652SHyon.Kim@Sun.COM processHBA_flags |= PRINT_TARGET_PORT;
338*10652SHyon.Kim@Sun.COM break;
339*10652SHyon.Kim@Sun.COM case 'v':
340*10652SHyon.Kim@Sun.COM processHBA_flags |= PRINT_VERBOSE;
341*10652SHyon.Kim@Sun.COM break;
342*10652SHyon.Kim@Sun.COM default:
343*10652SHyon.Kim@Sun.COM break;
344*10652SHyon.Kim@Sun.COM }
345*10652SHyon.Kim@Sun.COM }
346*10652SHyon.Kim@Sun.COM
347*10652SHyon.Kim@Sun.COM if ((status = HBA_LoadLibrary()) != HBA_STATUS_OK) {
348*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "%s %s\n",
349*10652SHyon.Kim@Sun.COM gettext("Failed to load SM-HBA libraries."
350*10652SHyon.Kim@Sun.COM "Reason:"), getHBAStatus(status));
351*10652SHyon.Kim@Sun.COM err_cnt++;
352*10652SHyon.Kim@Sun.COM return (err_cnt);
353*10652SHyon.Kim@Sun.COM }
354*10652SHyon.Kim@Sun.COM
355*10652SHyon.Kim@Sun.COM (void *) memset(&input, 0, sizeof (input));
356*10652SHyon.Kim@Sun.COM input.wwnCount = wwnCount;
357*10652SHyon.Kim@Sun.COM input.wwn_argv = wwn_argv;
358*10652SHyon.Kim@Sun.COM input.pflag = processHBA_flags;
359*10652SHyon.Kim@Sun.COM input.hbaName = hbaPort;
360*10652SHyon.Kim@Sun.COM
361*10652SHyon.Kim@Sun.COM /*
362*10652SHyon.Kim@Sun.COM * Process and filter for every hba-port,
363*10652SHyon.Kim@Sun.COM * when the hba-port is not specificed, print all hba-port(s).
364*10652SHyon.Kim@Sun.COM */
365*10652SHyon.Kim@Sun.COM err_cnt += processHBA(&input, handleExpander);
366*10652SHyon.Kim@Sun.COM
367*10652SHyon.Kim@Sun.COM (void) HBA_FreeLibrary();
368*10652SHyon.Kim@Sun.COM
369*10652SHyon.Kim@Sun.COM return (err_cnt);
370*10652SHyon.Kim@Sun.COM }
371*10652SHyon.Kim@Sun.COM
372*10652SHyon.Kim@Sun.COM /*
373*10652SHyon.Kim@Sun.COM * function for target-port subcommand
374*10652SHyon.Kim@Sun.COM *
375*10652SHyon.Kim@Sun.COM * Arguments:
376*10652SHyon.Kim@Sun.COM * wwnCount - the number of Remote Port SAS Address in wwn_argv
377*10652SHyon.Kim@Sun.COM * if wwnCount == 0, then print information on all
378*10652SHyon.Kim@Sun.COM * target ports.
379*10652SHyon.Kim@Sun.COM * if wwnCount > 0, then print information for the target ports
380*10652SHyon.Kim@Sun.COM * given in wwn_argv.
381*10652SHyon.Kim@Sun.COM * wwn_argv - array of WWNs
382*10652SHyon.Kim@Sun.COM * options - options specified by the caller
383*10652SHyon.Kim@Sun.COM *
384*10652SHyon.Kim@Sun.COM * returns:
385*10652SHyon.Kim@Sun.COM * 0 if successful
386*10652SHyon.Kim@Sun.COM * >0 otherwise
387*10652SHyon.Kim@Sun.COM */
388*10652SHyon.Kim@Sun.COM int
sas_util_list_targetport(int tpCount,char ** tpArgv,cmdOptions_t * options)389*10652SHyon.Kim@Sun.COM sas_util_list_targetport(int tpCount, char **tpArgv, cmdOptions_t *options)
390*10652SHyon.Kim@Sun.COM {
391*10652SHyon.Kim@Sun.COM HBA_STATUS status;
392*10652SHyon.Kim@Sun.COM int processHBA_flags = 0;
393*10652SHyon.Kim@Sun.COM int tp, tpFound;
394*10652SHyon.Kim@Sun.COM inputArg_t input;
395*10652SHyon.Kim@Sun.COM targetPortList_t *tpListWalk;
396*10652SHyon.Kim@Sun.COM int err_cnt = 0;
397*10652SHyon.Kim@Sun.COM uint64_t tmpAddr;
398*10652SHyon.Kim@Sun.COM
399*10652SHyon.Kim@Sun.COM /* process each of the options */
400*10652SHyon.Kim@Sun.COM for (; options->optval; options++) {
401*10652SHyon.Kim@Sun.COM switch (options->optval) {
402*10652SHyon.Kim@Sun.COM case 's':
403*10652SHyon.Kim@Sun.COM processHBA_flags |= PRINT_TARGET_SCSI;
404*10652SHyon.Kim@Sun.COM break;
405*10652SHyon.Kim@Sun.COM case 'v':
406*10652SHyon.Kim@Sun.COM processHBA_flags |= PRINT_VERBOSE;
407*10652SHyon.Kim@Sun.COM break;
408*10652SHyon.Kim@Sun.COM default:
409*10652SHyon.Kim@Sun.COM break;
410*10652SHyon.Kim@Sun.COM }
411*10652SHyon.Kim@Sun.COM }
412*10652SHyon.Kim@Sun.COM
413*10652SHyon.Kim@Sun.COM if ((status = HBA_LoadLibrary()) != HBA_STATUS_OK) {
414*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "%s %s\n",
415*10652SHyon.Kim@Sun.COM gettext("Failed to load SM-HBA libraries."
416*10652SHyon.Kim@Sun.COM "Reason:"), getHBAStatus(status));
417*10652SHyon.Kim@Sun.COM err_cnt++;
418*10652SHyon.Kim@Sun.COM return (err_cnt);
419*10652SHyon.Kim@Sun.COM }
420*10652SHyon.Kim@Sun.COM
421*10652SHyon.Kim@Sun.COM (void *) memset(&input, 0, sizeof (input));
422*10652SHyon.Kim@Sun.COM input.wwnCount = tpCount;
423*10652SHyon.Kim@Sun.COM input.wwn_argv = tpArgv;
424*10652SHyon.Kim@Sun.COM input.pflag = processHBA_flags;
425*10652SHyon.Kim@Sun.COM
426*10652SHyon.Kim@Sun.COM /*
427*10652SHyon.Kim@Sun.COM * Process and filter for every hba-port,
428*10652SHyon.Kim@Sun.COM * when the hba-port is not specificed, print all hba-port(s).
429*10652SHyon.Kim@Sun.COM */
430*10652SHyon.Kim@Sun.COM err_cnt += processHBA(&input, handleTargetPort);
431*10652SHyon.Kim@Sun.COM
432*10652SHyon.Kim@Sun.COM if (tpCount == 0) {
433*10652SHyon.Kim@Sun.COM /* list all target port */
434*10652SHyon.Kim@Sun.COM for (tpListWalk = gTargetPortList; tpListWalk != NULL;
435*10652SHyon.Kim@Sun.COM tpListWalk = tpListWalk->next) {
436*10652SHyon.Kim@Sun.COM err_cnt += printTargetPortInfo(tpListWalk, input.pflag);
437*10652SHyon.Kim@Sun.COM }
438*10652SHyon.Kim@Sun.COM } else {
439*10652SHyon.Kim@Sun.COM /*
440*10652SHyon.Kim@Sun.COM * When operands provided, we should set the error code
441*10652SHyon.Kim@Sun.COM * only if there are issues related with the operands.
442*10652SHyon.Kim@Sun.COM */
443*10652SHyon.Kim@Sun.COM err_cnt = 0;
444*10652SHyon.Kim@Sun.COM /*
445*10652SHyon.Kim@Sun.COM * list any paths not found first
446*10652SHyon.Kim@Sun.COM * this gives the user cleaner output
447*10652SHyon.Kim@Sun.COM */
448*10652SHyon.Kim@Sun.COM for (tp = 0; tp < tpCount; tp++) {
449*10652SHyon.Kim@Sun.COM errno = 0;
450*10652SHyon.Kim@Sun.COM tmpAddr = strtoull(tpArgv[tp], NULL, 16);
451*10652SHyon.Kim@Sun.COM if ((tmpAddr == 0) && (errno != 0)) {
452*10652SHyon.Kim@Sun.COM err_cnt++;
453*10652SHyon.Kim@Sun.COM continue;
454*10652SHyon.Kim@Sun.COM }
455*10652SHyon.Kim@Sun.COM for (tpListWalk = gTargetPortList, tpFound = B_FALSE;
456*10652SHyon.Kim@Sun.COM tpListWalk != NULL;
457*10652SHyon.Kim@Sun.COM tpListWalk = tpListWalk->next) {
458*10652SHyon.Kim@Sun.COM if (wwnConversion(tpListWalk->sasattr.
459*10652SHyon.Kim@Sun.COM LocalSASAddress.wwn) == tmpAddr) {
460*10652SHyon.Kim@Sun.COM tpFound = B_TRUE;
461*10652SHyon.Kim@Sun.COM break;
462*10652SHyon.Kim@Sun.COM }
463*10652SHyon.Kim@Sun.COM }
464*10652SHyon.Kim@Sun.COM if (tpFound == B_FALSE) {
465*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr,
466*10652SHyon.Kim@Sun.COM "Error: Target Port %s Not Found \n",
467*10652SHyon.Kim@Sun.COM tpArgv[tp]);
468*10652SHyon.Kim@Sun.COM err_cnt++;
469*10652SHyon.Kim@Sun.COM }
470*10652SHyon.Kim@Sun.COM }
471*10652SHyon.Kim@Sun.COM /* list all paths requested in order requested */
472*10652SHyon.Kim@Sun.COM for (tp = 0; tp < tpCount; tp++) {
473*10652SHyon.Kim@Sun.COM errno = 0;
474*10652SHyon.Kim@Sun.COM tmpAddr = strtoull(tpArgv[tp], NULL, 16);
475*10652SHyon.Kim@Sun.COM if ((tmpAddr == 0) && (errno != 0)) {
476*10652SHyon.Kim@Sun.COM continue;
477*10652SHyon.Kim@Sun.COM }
478*10652SHyon.Kim@Sun.COM for (tpListWalk = gTargetPortList, tpFound = B_FALSE;
479*10652SHyon.Kim@Sun.COM tpListWalk != NULL;
480*10652SHyon.Kim@Sun.COM tpListWalk = tpListWalk->next) {
481*10652SHyon.Kim@Sun.COM if (wwnConversion(tpListWalk->sasattr.
482*10652SHyon.Kim@Sun.COM LocalSASAddress.wwn) == tmpAddr) {
483*10652SHyon.Kim@Sun.COM err_cnt += printTargetPortInfo(
484*10652SHyon.Kim@Sun.COM tpListWalk,
485*10652SHyon.Kim@Sun.COM processHBA_flags);
486*10652SHyon.Kim@Sun.COM }
487*10652SHyon.Kim@Sun.COM }
488*10652SHyon.Kim@Sun.COM }
489*10652SHyon.Kim@Sun.COM }
490*10652SHyon.Kim@Sun.COM (void) HBA_FreeLibrary();
491*10652SHyon.Kim@Sun.COM return (err_cnt);
492*10652SHyon.Kim@Sun.COM }
493*10652SHyon.Kim@Sun.COM /*
494*10652SHyon.Kim@Sun.COM * This function will enumerate all the hba and hba ports,
495*10652SHyon.Kim@Sun.COM * call the callback function to proceed with futher process.
496*10652SHyon.Kim@Sun.COM *
497*10652SHyon.Kim@Sun.COM * Arguments:
498*10652SHyon.Kim@Sun.COM * input - contains all the input parameters.
499*10652SHyon.Kim@Sun.COM * processPort - a callback function when handling each port.
500*10652SHyon.Kim@Sun.COM *
501*10652SHyon.Kim@Sun.COM * Return Value:
502*10652SHyon.Kim@Sun.COM * 0 sucessfully processed handle
503*10652SHyon.Kim@Sun.COM * >0 error has occured
504*10652SHyon.Kim@Sun.COM */
505*10652SHyon.Kim@Sun.COM static int
processHBA(inputArg_t * input,processPortFunc processPort)506*10652SHyon.Kim@Sun.COM processHBA(inputArg_t *input, processPortFunc processPort)
507*10652SHyon.Kim@Sun.COM {
508*10652SHyon.Kim@Sun.COM int numAdapters = 0;
509*10652SHyon.Kim@Sun.COM int matchedHBAs = 0;
510*10652SHyon.Kim@Sun.COM int matchedHBAPorts = 0;
511*10652SHyon.Kim@Sun.COM int hbaPortExist = 0;
512*10652SHyon.Kim@Sun.COM HBA_STATUS status;
513*10652SHyon.Kim@Sun.COM HBA_HANDLE handle;
514*10652SHyon.Kim@Sun.COM HBA_UINT32 numberOfPorts = 0;
515*10652SHyon.Kim@Sun.COM int portIndex = 0;
516*10652SHyon.Kim@Sun.COM HBA_PORTTYPE porttype;
517*10652SHyon.Kim@Sun.COM SMHBA_LIBRARYATTRIBUTES libattrs;
518*10652SHyon.Kim@Sun.COM SMHBA_ADAPTERATTRIBUTES attrs;
519*10652SHyon.Kim@Sun.COM SMHBA_PORTATTRIBUTES port;
520*10652SHyon.Kim@Sun.COM SMHBA_SAS_PORT sasattrs;
521*10652SHyon.Kim@Sun.COM int i, sum, ret = 0;
522*10652SHyon.Kim@Sun.COM int remote_avail = 0;
523*10652SHyon.Kim@Sun.COM int local_avail = 0;
524*10652SHyon.Kim@Sun.COM sas_elem_t *adpt_array = NULL;
525*10652SHyon.Kim@Sun.COM sas_elem_t *port_array = NULL;
526*10652SHyon.Kim@Sun.COM
527*10652SHyon.Kim@Sun.COM numAdapters = HBA_GetNumberOfAdapters();
528*10652SHyon.Kim@Sun.COM if (numAdapters == 0) {
529*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "%s\n",
530*10652SHyon.Kim@Sun.COM gettext("Error: No Adapters Found."));
531*10652SHyon.Kim@Sun.COM return (++ret);
532*10652SHyon.Kim@Sun.COM }
533*10652SHyon.Kim@Sun.COM
534*10652SHyon.Kim@Sun.COM /*
535*10652SHyon.Kim@Sun.COM * To deal with mismatching HBA/HBA Port/Expander Port, we need an
536*10652SHyon.Kim@Sun.COM * array of flags for each operands.
537*10652SHyon.Kim@Sun.COM */
538*10652SHyon.Kim@Sun.COM if (input->wwnCount && (processPort != handleTargetPort) &&
539*10652SHyon.Kim@Sun.COM (processPort != handleLogicalUnit)) {
540*10652SHyon.Kim@Sun.COM input->wwn_flag = calloc(input->wwnCount, sizeof (int));
541*10652SHyon.Kim@Sun.COM if (input->wwn_flag == NULL) {
542*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "%s\n",
543*10652SHyon.Kim@Sun.COM gettext("No enough memory on heap"));
544*10652SHyon.Kim@Sun.COM return (++ret);
545*10652SHyon.Kim@Sun.COM }
546*10652SHyon.Kim@Sun.COM }
547*10652SHyon.Kim@Sun.COM
548*10652SHyon.Kim@Sun.COM adpt_array = calloc(numAdapters, sizeof (sas_elem_t));
549*10652SHyon.Kim@Sun.COM if (adpt_array == NULL) {
550*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "%s\n",
551*10652SHyon.Kim@Sun.COM gettext("No enough memory on heap"));
552*10652SHyon.Kim@Sun.COM if (input->wwn_flag) {
553*10652SHyon.Kim@Sun.COM free(input->wwn_flag);
554*10652SHyon.Kim@Sun.COM input->wwn_flag = NULL;
555*10652SHyon.Kim@Sun.COM }
556*10652SHyon.Kim@Sun.COM return (++ret);
557*10652SHyon.Kim@Sun.COM }
558*10652SHyon.Kim@Sun.COM for (i = 0; i < numAdapters; i++) {
559*10652SHyon.Kim@Sun.COM status =
560*10652SHyon.Kim@Sun.COM SMHBA_GetVendorLibraryAttributes(i, &libattrs);
561*10652SHyon.Kim@Sun.COM /*
562*10652SHyon.Kim@Sun.COM * If we get SAS incompatible library warning here,
563*10652SHyon.Kim@Sun.COM * just skip the following steps.
564*10652SHyon.Kim@Sun.COM */
565*10652SHyon.Kim@Sun.COM if (status != 1) {
566*10652SHyon.Kim@Sun.COM continue;
567*10652SHyon.Kim@Sun.COM }
568*10652SHyon.Kim@Sun.COM status = HBA_GetAdapterName(i, adpt_array[i].name);
569*10652SHyon.Kim@Sun.COM if (status != HBA_STATUS_OK) {
570*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "%s %d %s %s\n",
571*10652SHyon.Kim@Sun.COM gettext("Error: Failed to get the name for"
572*10652SHyon.Kim@Sun.COM " HBA index"),
573*10652SHyon.Kim@Sun.COM i, gettext("Reason:"),
574*10652SHyon.Kim@Sun.COM getHBAStatus(status));
575*10652SHyon.Kim@Sun.COM ret++;
576*10652SHyon.Kim@Sun.COM continue;
577*10652SHyon.Kim@Sun.COM }
578*10652SHyon.Kim@Sun.COM adpt_array[i].index = i;
579*10652SHyon.Kim@Sun.COM }
580*10652SHyon.Kim@Sun.COM /* Sort the HBA Name in place. */
581*10652SHyon.Kim@Sun.COM sas_elem_sort(adpt_array, numAdapters);
582*10652SHyon.Kim@Sun.COM
583*10652SHyon.Kim@Sun.COM for (i = 0; i < numAdapters; i++) {
584*10652SHyon.Kim@Sun.COM int times = 0;
585*10652SHyon.Kim@Sun.COM if (adpt_array[i].name[0] != '\0') {
586*10652SHyon.Kim@Sun.COM if ((handle = HBA_OpenAdapter(adpt_array[i].name))
587*10652SHyon.Kim@Sun.COM == 0) {
588*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "%s %s.\n",
589*10652SHyon.Kim@Sun.COM gettext("Error: Failed to open adapter"),
590*10652SHyon.Kim@Sun.COM adpt_array[i].name);
591*10652SHyon.Kim@Sun.COM ret++;
592*10652SHyon.Kim@Sun.COM continue;
593*10652SHyon.Kim@Sun.COM }
594*10652SHyon.Kim@Sun.COM } else {
595*10652SHyon.Kim@Sun.COM continue;
596*10652SHyon.Kim@Sun.COM }
597*10652SHyon.Kim@Sun.COM
598*10652SHyon.Kim@Sun.COM /*
599*10652SHyon.Kim@Sun.COM * We need to support an adapter without hba port.
600*10652SHyon.Kim@Sun.COM * So get attributes anyway.
601*10652SHyon.Kim@Sun.COM */
602*10652SHyon.Kim@Sun.COM (void *) memset(&attrs, 0, sizeof (attrs));
603*10652SHyon.Kim@Sun.COM status = SMHBA_GetAdapterAttributes(handle, &attrs);
604*10652SHyon.Kim@Sun.COM while ((status == HBA_STATUS_ERROR_TRY_AGAIN ||
605*10652SHyon.Kim@Sun.COM status == HBA_STATUS_ERROR_BUSY) &&
606*10652SHyon.Kim@Sun.COM times++ < HBA_MAX_RETRIES) {
607*10652SHyon.Kim@Sun.COM (void) sleep(1);
608*10652SHyon.Kim@Sun.COM status = SMHBA_GetAdapterAttributes(handle,
609*10652SHyon.Kim@Sun.COM &attrs);
610*10652SHyon.Kim@Sun.COM }
611*10652SHyon.Kim@Sun.COM if (status != HBA_STATUS_OK) {
612*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "%s %s %s %s\n",
613*10652SHyon.Kim@Sun.COM gettext("Error: Failed to get attributes"
614*10652SHyon.Kim@Sun.COM " for HBA "), adpt_array[i].name,
615*10652SHyon.Kim@Sun.COM gettext("Reason:"),
616*10652SHyon.Kim@Sun.COM getHBAStatus(status));
617*10652SHyon.Kim@Sun.COM
618*10652SHyon.Kim@Sun.COM HBA_CloseAdapter(handle);
619*10652SHyon.Kim@Sun.COM ret++;
620*10652SHyon.Kim@Sun.COM continue;
621*10652SHyon.Kim@Sun.COM }
622*10652SHyon.Kim@Sun.COM
623*10652SHyon.Kim@Sun.COM status = SMHBA_GetNumberOfPorts(handle, &numberOfPorts);
624*10652SHyon.Kim@Sun.COM if (status != HBA_STATUS_OK) {
625*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "%s %s %s %s\n",
626*10652SHyon.Kim@Sun.COM gettext("Error: Failed to get number of ports "
627*10652SHyon.Kim@Sun.COM "for HBA"), adpt_array[i].name,
628*10652SHyon.Kim@Sun.COM gettext("Reason:"),
629*10652SHyon.Kim@Sun.COM getHBAStatus(status));
630*10652SHyon.Kim@Sun.COM HBA_CloseAdapter(handle);
631*10652SHyon.Kim@Sun.COM ret++;
632*10652SHyon.Kim@Sun.COM continue;
633*10652SHyon.Kim@Sun.COM }
634*10652SHyon.Kim@Sun.COM
635*10652SHyon.Kim@Sun.COM /*
636*10652SHyon.Kim@Sun.COM * Deal with each subcommand for hba filter here,
637*10652SHyon.Kim@Sun.COM * processPort is NULL for hba subcommand.
638*10652SHyon.Kim@Sun.COM */
639*10652SHyon.Kim@Sun.COM if (processPort == NULL) {
640*10652SHyon.Kim@Sun.COM matchedHBAs += handleHBA(&attrs, input,
641*10652SHyon.Kim@Sun.COM numberOfPorts, adpt_array[i].name);
642*10652SHyon.Kim@Sun.COM HBA_CloseAdapter(handle);
643*10652SHyon.Kim@Sun.COM continue;
644*10652SHyon.Kim@Sun.COM } else if (processPort == handleHBAPort) {
645*10652SHyon.Kim@Sun.COM if (input->hbaName[0] != '\0') {
646*10652SHyon.Kim@Sun.COM if (strcmp(input->hbaName,
647*10652SHyon.Kim@Sun.COM adpt_array[i].name) == 0) {
648*10652SHyon.Kim@Sun.COM matchedHBAs++;
649*10652SHyon.Kim@Sun.COM } else {
650*10652SHyon.Kim@Sun.COM continue;
651*10652SHyon.Kim@Sun.COM }
652*10652SHyon.Kim@Sun.COM } else {
653*10652SHyon.Kim@Sun.COM matchedHBAs++;
654*10652SHyon.Kim@Sun.COM }
655*10652SHyon.Kim@Sun.COM } else {
656*10652SHyon.Kim@Sun.COM matchedHBAs++;
657*10652SHyon.Kim@Sun.COM }
658*10652SHyon.Kim@Sun.COM
659*10652SHyon.Kim@Sun.COM /*
660*10652SHyon.Kim@Sun.COM * In order to have a sorted output for HBA Port, we should
661*10652SHyon.Kim@Sun.COM * do the sorting before moving on.
662*10652SHyon.Kim@Sun.COM */
663*10652SHyon.Kim@Sun.COM if (numberOfPorts) {
664*10652SHyon.Kim@Sun.COM port_array = calloc(numberOfPorts, sizeof (sas_elem_t));
665*10652SHyon.Kim@Sun.COM }
666*10652SHyon.Kim@Sun.COM for (portIndex = 0; portIndex < numberOfPorts; portIndex++) {
667*10652SHyon.Kim@Sun.COM if ((status = SMHBA_GetPortType(handle,
668*10652SHyon.Kim@Sun.COM portIndex, &porttype)) != HBA_STATUS_OK) {
669*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "%s %s %s %s\n",
670*10652SHyon.Kim@Sun.COM gettext("Failed to get adapter port type "
671*10652SHyon.Kim@Sun.COM "for HBA"), adpt_array[i].name,
672*10652SHyon.Kim@Sun.COM gettext("Reason:"),
673*10652SHyon.Kim@Sun.COM getHBAStatus(status));
674*10652SHyon.Kim@Sun.COM ret++;
675*10652SHyon.Kim@Sun.COM continue;
676*10652SHyon.Kim@Sun.COM }
677*10652SHyon.Kim@Sun.COM if (porttype != HBA_PORTTYPE_SASDEVICE) {
678*10652SHyon.Kim@Sun.COM /* skip any non-sas hba port */
679*10652SHyon.Kim@Sun.COM continue;
680*10652SHyon.Kim@Sun.COM }
681*10652SHyon.Kim@Sun.COM (void *) memset(&port, 0, sizeof (port));
682*10652SHyon.Kim@Sun.COM (void *) memset(&sasattrs, 0, sizeof (sasattrs));
683*10652SHyon.Kim@Sun.COM port.PortSpecificAttribute.SASPort = &sasattrs;
684*10652SHyon.Kim@Sun.COM if ((status = SMHBA_GetAdapterPortAttributes(
685*10652SHyon.Kim@Sun.COM handle, portIndex, &port)) != HBA_STATUS_OK) {
686*10652SHyon.Kim@Sun.COM /*
687*10652SHyon.Kim@Sun.COM * Not able to get port attributes.
688*10652SHyon.Kim@Sun.COM * print out error message and
689*10652SHyon.Kim@Sun.COM * move on to the next port
690*10652SHyon.Kim@Sun.COM */
691*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "%s %s %s %d %s %s\n",
692*10652SHyon.Kim@Sun.COM gettext("Error: Failed to get port "
693*10652SHyon.Kim@Sun.COM "attributes for HBA"), adpt_array[i].name,
694*10652SHyon.Kim@Sun.COM gettext("port index"), portIndex,
695*10652SHyon.Kim@Sun.COM gettext("Reason:"),
696*10652SHyon.Kim@Sun.COM getHBAStatus(status));
697*10652SHyon.Kim@Sun.COM ret++;
698*10652SHyon.Kim@Sun.COM continue;
699*10652SHyon.Kim@Sun.COM }
700*10652SHyon.Kim@Sun.COM (void) strlcpy(port_array[portIndex].name,
701*10652SHyon.Kim@Sun.COM port.OSDeviceName,
702*10652SHyon.Kim@Sun.COM sizeof (port_array[portIndex].name));
703*10652SHyon.Kim@Sun.COM port_array[portIndex].index = portIndex;
704*10652SHyon.Kim@Sun.COM }
705*10652SHyon.Kim@Sun.COM /* Sort the HBA Port Name here. */
706*10652SHyon.Kim@Sun.COM if (port_array) {
707*10652SHyon.Kim@Sun.COM sas_elem_sort(port_array, numberOfPorts);
708*10652SHyon.Kim@Sun.COM }
709*10652SHyon.Kim@Sun.COM /*
710*10652SHyon.Kim@Sun.COM * Sum up the local hba ports available.
711*10652SHyon.Kim@Sun.COM */
712*10652SHyon.Kim@Sun.COM local_avail += numberOfPorts;
713*10652SHyon.Kim@Sun.COM
714*10652SHyon.Kim@Sun.COM /*
715*10652SHyon.Kim@Sun.COM * Clear g_printHBA flag for expander subcommand.
716*10652SHyon.Kim@Sun.COM */
717*10652SHyon.Kim@Sun.COM g_printHBA = 0;
718*10652SHyon.Kim@Sun.COM
719*10652SHyon.Kim@Sun.COM /* process each port on the given adapter */
720*10652SHyon.Kim@Sun.COM for (portIndex = 0;
721*10652SHyon.Kim@Sun.COM portIndex < numberOfPorts;
722*10652SHyon.Kim@Sun.COM portIndex++) {
723*10652SHyon.Kim@Sun.COM /*
724*10652SHyon.Kim@Sun.COM * We only handle the port which is valid.
725*10652SHyon.Kim@Sun.COM */
726*10652SHyon.Kim@Sun.COM if (port_array[portIndex].name[0] == '\0') {
727*10652SHyon.Kim@Sun.COM continue;
728*10652SHyon.Kim@Sun.COM }
729*10652SHyon.Kim@Sun.COM (void *) memset(&port, 0, sizeof (port));
730*10652SHyon.Kim@Sun.COM (void *) memset(&sasattrs, 0, sizeof (sasattrs));
731*10652SHyon.Kim@Sun.COM port.PortSpecificAttribute.SASPort = &sasattrs;
732*10652SHyon.Kim@Sun.COM
733*10652SHyon.Kim@Sun.COM (void) SMHBA_GetAdapterPortAttributes(handle,
734*10652SHyon.Kim@Sun.COM port_array[portIndex].index, &port);
735*10652SHyon.Kim@Sun.COM
736*10652SHyon.Kim@Sun.COM /*
737*10652SHyon.Kim@Sun.COM * We have different things to do for the three
738*10652SHyon.Kim@Sun.COM * sub-commands here.
739*10652SHyon.Kim@Sun.COM */
740*10652SHyon.Kim@Sun.COM if (processPort == handleHBAPort) {
741*10652SHyon.Kim@Sun.COM /*
742*10652SHyon.Kim@Sun.COM * For hba-port, we will check whether the
743*10652SHyon.Kim@Sun.COM * specified hba port exist first.
744*10652SHyon.Kim@Sun.COM * But if no hba port specified, we should
745*10652SHyon.Kim@Sun.COM * by pass this check(just let hbaPortExist
746*10652SHyon.Kim@Sun.COM * be 1).
747*10652SHyon.Kim@Sun.COM */
748*10652SHyon.Kim@Sun.COM if (input->wwnCount > 0) {
749*10652SHyon.Kim@Sun.COM if (isStringInArgv(input,
750*10652SHyon.Kim@Sun.COM port.OSDeviceName)) {
751*10652SHyon.Kim@Sun.COM hbaPortExist = 1;
752*10652SHyon.Kim@Sun.COM if (g_printHBA == 0) {
753*10652SHyon.Kim@Sun.COM (void *) fprintf(stdout,
754*10652SHyon.Kim@Sun.COM "%s %s\n",
755*10652SHyon.Kim@Sun.COM "HBA Name:",
756*10652SHyon.Kim@Sun.COM adpt_array[i].name);
757*10652SHyon.Kim@Sun.COM g_printHBA = 1;
758*10652SHyon.Kim@Sun.COM }
759*10652SHyon.Kim@Sun.COM }
760*10652SHyon.Kim@Sun.COM } else {
761*10652SHyon.Kim@Sun.COM hbaPortExist = 1;
762*10652SHyon.Kim@Sun.COM if (g_printHBA == 0) {
763*10652SHyon.Kim@Sun.COM (void *) fprintf(stdout,
764*10652SHyon.Kim@Sun.COM "%s %s\n",
765*10652SHyon.Kim@Sun.COM "HBA Name:",
766*10652SHyon.Kim@Sun.COM adpt_array[i].name);
767*10652SHyon.Kim@Sun.COM g_printHBA = 1;
768*10652SHyon.Kim@Sun.COM }
769*10652SHyon.Kim@Sun.COM }
770*10652SHyon.Kim@Sun.COM }
771*10652SHyon.Kim@Sun.COM
772*10652SHyon.Kim@Sun.COM if (processPort == handleExpander) {
773*10652SHyon.Kim@Sun.COM /*
774*10652SHyon.Kim@Sun.COM * For expander device, input->hbaName is
775*10652SHyon.Kim@Sun.COM * the hba port name specified on the
776*10652SHyon.Kim@Sun.COM * command line(with -p option).
777*10652SHyon.Kim@Sun.COM */
778*10652SHyon.Kim@Sun.COM if (input->hbaName[0] != '\0') {
779*10652SHyon.Kim@Sun.COM if (strcmp(input->hbaName,
780*10652SHyon.Kim@Sun.COM port.OSDeviceName) == 0)
781*10652SHyon.Kim@Sun.COM hbaPortExist = 1;
782*10652SHyon.Kim@Sun.COM } else
783*10652SHyon.Kim@Sun.COM hbaPortExist = 1;
784*10652SHyon.Kim@Sun.COM }
785*10652SHyon.Kim@Sun.COM
786*10652SHyon.Kim@Sun.COM if (processPort == handleTargetPort) {
787*10652SHyon.Kim@Sun.COM /*
788*10652SHyon.Kim@Sun.COM * For target port, we don't need to check the
789*10652SHyon.Kim@Sun.COM * hba port address, so let it go here.
790*10652SHyon.Kim@Sun.COM */
791*10652SHyon.Kim@Sun.COM hbaPortExist = 1;
792*10652SHyon.Kim@Sun.COM }
793*10652SHyon.Kim@Sun.COM
794*10652SHyon.Kim@Sun.COM if (processPort == handleLogicalUnit) {
795*10652SHyon.Kim@Sun.COM /*
796*10652SHyon.Kim@Sun.COM * For lu, we don't need to check the hba
797*10652SHyon.Kim@Sun.COM * port address, so let it go here.
798*10652SHyon.Kim@Sun.COM */
799*10652SHyon.Kim@Sun.COM hbaPortExist = 1;
800*10652SHyon.Kim@Sun.COM }
801*10652SHyon.Kim@Sun.COM
802*10652SHyon.Kim@Sun.COM if (hbaPortExist) {
803*10652SHyon.Kim@Sun.COM if (port.PortSpecificAttribute.SASPort->
804*10652SHyon.Kim@Sun.COM NumberofDiscoveredPorts) {
805*10652SHyon.Kim@Sun.COM remote_avail++;
806*10652SHyon.Kim@Sun.COM }
807*10652SHyon.Kim@Sun.COM ret += (*processPort)(handle,
808*10652SHyon.Kim@Sun.COM adpt_array[i].name,
809*10652SHyon.Kim@Sun.COM port_array[portIndex].index, &port,
810*10652SHyon.Kim@Sun.COM &attrs, input);
811*10652SHyon.Kim@Sun.COM /*
812*10652SHyon.Kim@Sun.COM * We should reset the hbaPortExist flag
813*10652SHyon.Kim@Sun.COM * here for next round of check and count
814*10652SHyon.Kim@Sun.COM * for the machedHBAPorts.
815*10652SHyon.Kim@Sun.COM */
816*10652SHyon.Kim@Sun.COM hbaPortExist = 0;
817*10652SHyon.Kim@Sun.COM matchedHBAPorts++;
818*10652SHyon.Kim@Sun.COM }
819*10652SHyon.Kim@Sun.COM }
820*10652SHyon.Kim@Sun.COM if (port_array) {
821*10652SHyon.Kim@Sun.COM free(port_array);
822*10652SHyon.Kim@Sun.COM port_array = NULL;
823*10652SHyon.Kim@Sun.COM }
824*10652SHyon.Kim@Sun.COM HBA_CloseAdapter(handle);
825*10652SHyon.Kim@Sun.COM }
826*10652SHyon.Kim@Sun.COM if (adpt_array) {
827*10652SHyon.Kim@Sun.COM free(adpt_array);
828*10652SHyon.Kim@Sun.COM adpt_array = NULL;
829*10652SHyon.Kim@Sun.COM }
830*10652SHyon.Kim@Sun.COM
831*10652SHyon.Kim@Sun.COM /*
832*10652SHyon.Kim@Sun.COM * When we are here, we have traversed all the hba and hba ports.
833*10652SHyon.Kim@Sun.COM */
834*10652SHyon.Kim@Sun.COM if (matchedHBAs == 0) {
835*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "%s\n",
836*10652SHyon.Kim@Sun.COM gettext("Error: Matching HBA not found."));
837*10652SHyon.Kim@Sun.COM if (input->wwn_flag) {
838*10652SHyon.Kim@Sun.COM free(input->wwn_flag);
839*10652SHyon.Kim@Sun.COM input->wwn_flag = NULL;
840*10652SHyon.Kim@Sun.COM }
841*10652SHyon.Kim@Sun.COM return (++ret);
842*10652SHyon.Kim@Sun.COM } else if (processPort == NULL) {
843*10652SHyon.Kim@Sun.COM /*
844*10652SHyon.Kim@Sun.COM * processPort == NULL signifies hba subcommand.
845*10652SHyon.Kim@Sun.COM * If enter here, it means we have at least one matching
846*10652SHyon.Kim@Sun.COM * hba, we need to check if there are mismatching ones.
847*10652SHyon.Kim@Sun.COM */
848*10652SHyon.Kim@Sun.COM for (i = 0; i < input->wwnCount; i++) {
849*10652SHyon.Kim@Sun.COM if (input->wwn_flag[i] == 0) {
850*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "%s %s %s\n",
851*10652SHyon.Kim@Sun.COM gettext("Error: HBA"),
852*10652SHyon.Kim@Sun.COM input->wwn_argv[i],
853*10652SHyon.Kim@Sun.COM gettext("not found."));
854*10652SHyon.Kim@Sun.COM ret++;
855*10652SHyon.Kim@Sun.COM }
856*10652SHyon.Kim@Sun.COM }
857*10652SHyon.Kim@Sun.COM } else {
858*10652SHyon.Kim@Sun.COM if (local_avail > 0 && matchedHBAPorts == 0) {
859*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "%s\n",
860*10652SHyon.Kim@Sun.COM gettext("Error: Matching HBA Port "
861*10652SHyon.Kim@Sun.COM "not found."));
862*10652SHyon.Kim@Sun.COM if (input->wwn_flag) {
863*10652SHyon.Kim@Sun.COM free(input->wwn_flag);
864*10652SHyon.Kim@Sun.COM input->wwn_flag = NULL;
865*10652SHyon.Kim@Sun.COM }
866*10652SHyon.Kim@Sun.COM return (++ret);
867*10652SHyon.Kim@Sun.COM } else if (local_avail == 0) {
868*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "%s\n",
869*10652SHyon.Kim@Sun.COM gettext("Error: No HBA Port Configured."));
870*10652SHyon.Kim@Sun.COM if (input->wwn_flag) {
871*10652SHyon.Kim@Sun.COM free(input->wwn_flag);
872*10652SHyon.Kim@Sun.COM input->wwn_flag = NULL;
873*10652SHyon.Kim@Sun.COM }
874*10652SHyon.Kim@Sun.COM return (++ret);
875*10652SHyon.Kim@Sun.COM } else if (processPort == handleHBAPort) {
876*10652SHyon.Kim@Sun.COM /*
877*10652SHyon.Kim@Sun.COM * If enter here, we have at least one HBA port
878*10652SHyon.Kim@Sun.COM * matched. For hba-port subcommand, we shall check
879*10652SHyon.Kim@Sun.COM * whether there are operands mismatching.
880*10652SHyon.Kim@Sun.COM */
881*10652SHyon.Kim@Sun.COM for (i = 0; i < input->wwnCount; i++) {
882*10652SHyon.Kim@Sun.COM if (input->wwn_flag[i] == 0) {
883*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "%s %s %s\n",
884*10652SHyon.Kim@Sun.COM gettext("Error: HBA Port"),
885*10652SHyon.Kim@Sun.COM input->wwn_argv[i],
886*10652SHyon.Kim@Sun.COM gettext("not found."));
887*10652SHyon.Kim@Sun.COM ret++;
888*10652SHyon.Kim@Sun.COM }
889*10652SHyon.Kim@Sun.COM }
890*10652SHyon.Kim@Sun.COM }
891*10652SHyon.Kim@Sun.COM }
892*10652SHyon.Kim@Sun.COM
893*10652SHyon.Kim@Sun.COM /*
894*10652SHyon.Kim@Sun.COM * For expander subcommand, we need to check if the
895*10652SHyon.Kim@Sun.COM * specified sas address(ese) exist (none/partial/all).
896*10652SHyon.Kim@Sun.COM */
897*10652SHyon.Kim@Sun.COM if (processPort == handleExpander) {
898*10652SHyon.Kim@Sun.COM if (input->wwnCount > 0) {
899*10652SHyon.Kim@Sun.COM sum = 0;
900*10652SHyon.Kim@Sun.COM for (i = 0; i < input->wwnCount; i++) {
901*10652SHyon.Kim@Sun.COM sum += input->wwn_flag[i];
902*10652SHyon.Kim@Sun.COM }
903*10652SHyon.Kim@Sun.COM /*
904*10652SHyon.Kim@Sun.COM * If sum is zero, it means that for all the given
905*10652SHyon.Kim@Sun.COM * operands matching count is zero. So none of the
906*10652SHyon.Kim@Sun.COM * specified SAS address exist actually.
907*10652SHyon.Kim@Sun.COM */
908*10652SHyon.Kim@Sun.COM if (sum == 0) {
909*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, gettext("Error: "
910*10652SHyon.Kim@Sun.COM "Matching SAS Address not found.\n"));
911*10652SHyon.Kim@Sun.COM free(input->wwn_flag);
912*10652SHyon.Kim@Sun.COM input->wwn_flag = NULL;
913*10652SHyon.Kim@Sun.COM return (++ret);
914*10652SHyon.Kim@Sun.COM }
915*10652SHyon.Kim@Sun.COM
916*10652SHyon.Kim@Sun.COM /*
917*10652SHyon.Kim@Sun.COM * If we get here, it means that some of the specified
918*10652SHyon.Kim@Sun.COM * sas address exist, we will know through looping the
919*10652SHyon.Kim@Sun.COM * wwn_flag array.
920*10652SHyon.Kim@Sun.COM */
921*10652SHyon.Kim@Sun.COM for (i = 0; i < input->wwnCount; i++) {
922*10652SHyon.Kim@Sun.COM if (input->wwn_flag[i] == 0) {
923*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "%s %s %s\n",
924*10652SHyon.Kim@Sun.COM gettext("Error: SAS Address"),
925*10652SHyon.Kim@Sun.COM input->wwn_argv[i],
926*10652SHyon.Kim@Sun.COM gettext("not found."));
927*10652SHyon.Kim@Sun.COM ret++;
928*10652SHyon.Kim@Sun.COM }
929*10652SHyon.Kim@Sun.COM }
930*10652SHyon.Kim@Sun.COM }
931*10652SHyon.Kim@Sun.COM /* even if no remote port is found it is not an error. */
932*10652SHyon.Kim@Sun.COM }
933*10652SHyon.Kim@Sun.COM if (input->wwn_flag) {
934*10652SHyon.Kim@Sun.COM free(input->wwn_flag);
935*10652SHyon.Kim@Sun.COM input->wwn_flag = NULL;
936*10652SHyon.Kim@Sun.COM }
937*10652SHyon.Kim@Sun.COM return (ret);
938*10652SHyon.Kim@Sun.COM }
939*10652SHyon.Kim@Sun.COM
940*10652SHyon.Kim@Sun.COM /*
941*10652SHyon.Kim@Sun.COM * This function will handle the phy stuff for hba-port subcommand.
942*10652SHyon.Kim@Sun.COM *
943*10652SHyon.Kim@Sun.COM * Arguments:
944*10652SHyon.Kim@Sun.COM * handle - handle to hba port.
945*10652SHyon.Kim@Sun.COM * portIndex - the index of hba port currently being processed.
946*10652SHyon.Kim@Sun.COM * port - pointer to hba port attributes.
947*10652SHyon.Kim@Sun.COM * pflag - options user specified.
948*10652SHyon.Kim@Sun.COM *
949*10652SHyon.Kim@Sun.COM * Return Value:
950*10652SHyon.Kim@Sun.COM * 0 sucessfully processed handle
951*10652SHyon.Kim@Sun.COM * >0 error has occured
952*10652SHyon.Kim@Sun.COM */
953*10652SHyon.Kim@Sun.COM static int
processHBAPortPhyInfo(HBA_HANDLE handle,HBA_UINT32 portIndex,SMHBA_PORTATTRIBUTES * port,int pflag)954*10652SHyon.Kim@Sun.COM processHBAPortPhyInfo(HBA_HANDLE handle, HBA_UINT32 portIndex,
955*10652SHyon.Kim@Sun.COM SMHBA_PORTATTRIBUTES *port, int pflag)
956*10652SHyon.Kim@Sun.COM {
957*10652SHyon.Kim@Sun.COM int phyIndex = 0, err_cnt = 0;
958*10652SHyon.Kim@Sun.COM HBA_UINT32 numphys = 0;
959*10652SHyon.Kim@Sun.COM HBA_STATUS status = 0;
960*10652SHyon.Kim@Sun.COM SMHBA_SAS_PHY phyattrs;
961*10652SHyon.Kim@Sun.COM
962*10652SHyon.Kim@Sun.COM if (port == NULL)
963*10652SHyon.Kim@Sun.COM return (++err_cnt);
964*10652SHyon.Kim@Sun.COM
965*10652SHyon.Kim@Sun.COM numphys = port->PortSpecificAttribute.SASPort->NumberofPhys;
966*10652SHyon.Kim@Sun.COM if (numphys == 0)
967*10652SHyon.Kim@Sun.COM return (0);
968*10652SHyon.Kim@Sun.COM
969*10652SHyon.Kim@Sun.COM if ((pflag & PRINT_PHY) || (pflag & PRINT_PHY_LINKSTAT))
970*10652SHyon.Kim@Sun.COM (void *) fprintf(stdout, "%s\n", " Phy Information:");
971*10652SHyon.Kim@Sun.COM else
972*10652SHyon.Kim@Sun.COM return (0);
973*10652SHyon.Kim@Sun.COM
974*10652SHyon.Kim@Sun.COM
975*10652SHyon.Kim@Sun.COM for (phyIndex = 0; phyIndex < numphys; phyIndex++) {
976*10652SHyon.Kim@Sun.COM (void *) memset(&phyattrs, 0, sizeof (phyattrs));
977*10652SHyon.Kim@Sun.COM status = SMHBA_GetSASPhyAttributes(
978*10652SHyon.Kim@Sun.COM handle, portIndex, phyIndex, &phyattrs);
979*10652SHyon.Kim@Sun.COM if (status != HBA_STATUS_OK) {
980*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "%s %d %s %s\n",
981*10652SHyon.Kim@Sun.COM gettext("Failed to get SAS Phy attributes"
982*10652SHyon.Kim@Sun.COM "phyIndex"), phyIndex,
983*10652SHyon.Kim@Sun.COM gettext("Reason:"),
984*10652SHyon.Kim@Sun.COM getHBAStatus(status));
985*10652SHyon.Kim@Sun.COM err_cnt++;
986*10652SHyon.Kim@Sun.COM continue;
987*10652SHyon.Kim@Sun.COM }
988*10652SHyon.Kim@Sun.COM if (pflag & PRINT_PHY)
989*10652SHyon.Kim@Sun.COM printHBAPortPhyInfo(&phyattrs);
990*10652SHyon.Kim@Sun.COM if (pflag & PRINT_PHY_LINKSTAT)
991*10652SHyon.Kim@Sun.COM err_cnt += processHBAPortPhyStat(handle,
992*10652SHyon.Kim@Sun.COM portIndex, phyIndex, &phyattrs, pflag);
993*10652SHyon.Kim@Sun.COM }
994*10652SHyon.Kim@Sun.COM return (err_cnt);
995*10652SHyon.Kim@Sun.COM }
996*10652SHyon.Kim@Sun.COM
997*10652SHyon.Kim@Sun.COM /*
998*10652SHyon.Kim@Sun.COM * This function will handle the phy stuff for hba-port subcommand.
999*10652SHyon.Kim@Sun.COM *
1000*10652SHyon.Kim@Sun.COM * Arguments:
1001*10652SHyon.Kim@Sun.COM * handle - handle to hba port.
1002*10652SHyon.Kim@Sun.COM * portIndex - the index of hba port currently being processed.
1003*10652SHyon.Kim@Sun.COM * port - pointer to hba port attributes.
1004*10652SHyon.Kim@Sun.COM * pflag - options user specified.
1005*10652SHyon.Kim@Sun.COM *
1006*10652SHyon.Kim@Sun.COM * Return Value:
1007*10652SHyon.Kim@Sun.COM * 0 sucessfully processed handle
1008*10652SHyon.Kim@Sun.COM * >0 error has occured
1009*10652SHyon.Kim@Sun.COM */
1010*10652SHyon.Kim@Sun.COM static int
processHBAPortPhyStat(HBA_HANDLE handle,HBA_UINT32 portIndex,int phyIndex,PSMHBA_SAS_PHY phyattrs,int pflag)1011*10652SHyon.Kim@Sun.COM processHBAPortPhyStat(HBA_HANDLE handle, HBA_UINT32 portIndex, int phyIndex,
1012*10652SHyon.Kim@Sun.COM PSMHBA_SAS_PHY phyattrs, int pflag)
1013*10652SHyon.Kim@Sun.COM {
1014*10652SHyon.Kim@Sun.COM HBA_STATUS status = 0;
1015*10652SHyon.Kim@Sun.COM SMHBA_PHYSTATISTICS phystat;
1016*10652SHyon.Kim@Sun.COM SMHBA_SASPHYSTATISTICS sasphystat;
1017*10652SHyon.Kim@Sun.COM
1018*10652SHyon.Kim@Sun.COM if ((pflag & PRINT_PHY) == 0) {
1019*10652SHyon.Kim@Sun.COM (void *) fprintf(stdout, "%s %d\n",
1020*10652SHyon.Kim@Sun.COM " Identifier:", phyattrs->PhyIdentifier);
1021*10652SHyon.Kim@Sun.COM }
1022*10652SHyon.Kim@Sun.COM
1023*10652SHyon.Kim@Sun.COM (void *) memset(&phystat, 0, sizeof (phystat));
1024*10652SHyon.Kim@Sun.COM (void *) memset(&sasphystat, 0, sizeof (sasphystat));
1025*10652SHyon.Kim@Sun.COM phystat.SASPhyStatistics = &sasphystat;
1026*10652SHyon.Kim@Sun.COM status = SMHBA_GetPhyStatistics(handle, portIndex, phyIndex, &phystat);
1027*10652SHyon.Kim@Sun.COM if (status != HBA_STATUS_OK) {
1028*10652SHyon.Kim@Sun.COM (void *) fprintf(stdout, "%s\n",
1029*10652SHyon.Kim@Sun.COM " Link Error Statistics:");
1030*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "%s\n",
1031*10652SHyon.Kim@Sun.COM gettext(" Failed to retrieve Link "
1032*10652SHyon.Kim@Sun.COM "Error Statistics!"));
1033*10652SHyon.Kim@Sun.COM return (1);
1034*10652SHyon.Kim@Sun.COM }
1035*10652SHyon.Kim@Sun.COM printHBAPortPhyStatistics(phystat.SASPhyStatistics);
1036*10652SHyon.Kim@Sun.COM return (0);
1037*10652SHyon.Kim@Sun.COM }
1038*10652SHyon.Kim@Sun.COM
1039*10652SHyon.Kim@Sun.COM /*
1040*10652SHyon.Kim@Sun.COM * Check whether the pWWN exist in the WWNs list which specified by user.
1041*10652SHyon.Kim@Sun.COM *
1042*10652SHyon.Kim@Sun.COM * Arguments:
1043*10652SHyon.Kim@Sun.COM * input - contains all the input parameters.
1044*10652SHyon.Kim@Sun.COM * pWWN - pointer to the hba port sas address.
1045*10652SHyon.Kim@Sun.COM *
1046*10652SHyon.Kim@Sun.COM * Return Value:
1047*10652SHyon.Kim@Sun.COM * 1 true, the pWWN exist in the sas address list specified.
1048*10652SHyon.Kim@Sun.COM * 0 false.
1049*10652SHyon.Kim@Sun.COM */
1050*10652SHyon.Kim@Sun.COM static int
isPortWWNInArgv(inputArg_t * input,PHBA_WWN pWWN)1051*10652SHyon.Kim@Sun.COM isPortWWNInArgv(inputArg_t *input, PHBA_WWN pWWN)
1052*10652SHyon.Kim@Sun.COM {
1053*10652SHyon.Kim@Sun.COM int port_wwn_counter = 0;
1054*10652SHyon.Kim@Sun.COM int portfound = 0;
1055*10652SHyon.Kim@Sun.COM uint64_t hbaWWN;
1056*10652SHyon.Kim@Sun.COM
1057*10652SHyon.Kim@Sun.COM /* list only ports given in wwn_argv */
1058*10652SHyon.Kim@Sun.COM for (port_wwn_counter = 0;
1059*10652SHyon.Kim@Sun.COM port_wwn_counter < input->wwnCount;
1060*10652SHyon.Kim@Sun.COM port_wwn_counter++) {
1061*10652SHyon.Kim@Sun.COM hbaWWN = strtoull(input->wwn_argv[port_wwn_counter], NULL,
1062*10652SHyon.Kim@Sun.COM 16);
1063*10652SHyon.Kim@Sun.COM if (hbaWWN == 0 && errno != 0)
1064*10652SHyon.Kim@Sun.COM continue;
1065*10652SHyon.Kim@Sun.COM if (wwnConversion(pWWN->wwn) == hbaWWN) {
1066*10652SHyon.Kim@Sun.COM if (input->wwn_flag) {
1067*10652SHyon.Kim@Sun.COM input->wwn_flag[port_wwn_counter]++;
1068*10652SHyon.Kim@Sun.COM }
1069*10652SHyon.Kim@Sun.COM portfound = 1;
1070*10652SHyon.Kim@Sun.COM }
1071*10652SHyon.Kim@Sun.COM }
1072*10652SHyon.Kim@Sun.COM return (portfound);
1073*10652SHyon.Kim@Sun.COM }
1074*10652SHyon.Kim@Sun.COM
1075*10652SHyon.Kim@Sun.COM /*
1076*10652SHyon.Kim@Sun.COM * Check whether the string value exists in the input list,
1077*10652SHyon.Kim@Sun.COM * which specified by user.
1078*10652SHyon.Kim@Sun.COM *
1079*10652SHyon.Kim@Sun.COM * Arguments:
1080*10652SHyon.Kim@Sun.COM * input - contains all the input parameters.
1081*10652SHyon.Kim@Sun.COM * stringName - could be hba adapter name
1082*10652SHyon.Kim@Sun.COM * hba-port name.
1083*10652SHyon.Kim@Sun.COM *
1084*10652SHyon.Kim@Sun.COM * Return Value:
1085*10652SHyon.Kim@Sun.COM * 1 true, the HBA exists in the list specified.
1086*10652SHyon.Kim@Sun.COM * 0 false.
1087*10652SHyon.Kim@Sun.COM */
1088*10652SHyon.Kim@Sun.COM static int
isStringInArgv(inputArg_t * input,const char * stringName)1089*10652SHyon.Kim@Sun.COM isStringInArgv(inputArg_t *input, const char *stringName)
1090*10652SHyon.Kim@Sun.COM {
1091*10652SHyon.Kim@Sun.COM int counter = 0;
1092*10652SHyon.Kim@Sun.COM int found = 0;
1093*10652SHyon.Kim@Sun.COM
1094*10652SHyon.Kim@Sun.COM /* list only hba(s) given in wwn_argv */
1095*10652SHyon.Kim@Sun.COM for (counter = 0;
1096*10652SHyon.Kim@Sun.COM counter < input->wwnCount;
1097*10652SHyon.Kim@Sun.COM counter++) {
1098*10652SHyon.Kim@Sun.COM if (strcmp(input->wwn_argv[counter],
1099*10652SHyon.Kim@Sun.COM stringName) == 0) {
1100*10652SHyon.Kim@Sun.COM if (input->wwn_flag)
1101*10652SHyon.Kim@Sun.COM input->wwn_flag[counter]++;
1102*10652SHyon.Kim@Sun.COM found = 1;
1103*10652SHyon.Kim@Sun.COM }
1104*10652SHyon.Kim@Sun.COM }
1105*10652SHyon.Kim@Sun.COM return (found);
1106*10652SHyon.Kim@Sun.COM }
1107*10652SHyon.Kim@Sun.COM
1108*10652SHyon.Kim@Sun.COM /*
1109*10652SHyon.Kim@Sun.COM * Callback function for hba subcommand.
1110*10652SHyon.Kim@Sun.COM *
1111*10652SHyon.Kim@Sun.COM * Arguments:
1112*10652SHyon.Kim@Sun.COM * attrs - pointer to adapter attributes currently being processed.
1113*10652SHyon.Kim@Sun.COM * input - contains all the input parameters.
1114*10652SHyon.Kim@Sun.COM * numberOfPorts - number of ports of this HBA.
1115*10652SHyon.Kim@Sun.COM *
1116*10652SHyon.Kim@Sun.COM * Return Value:
1117*10652SHyon.Kim@Sun.COM * matching number
1118*10652SHyon.Kim@Sun.COM */
handleHBA(SMHBA_ADAPTERATTRIBUTES * attrs,inputArg_t * input,int numberOfPorts,const char * adapterName)1119*10652SHyon.Kim@Sun.COM static int handleHBA(SMHBA_ADAPTERATTRIBUTES *attrs, inputArg_t *input,
1120*10652SHyon.Kim@Sun.COM int numberOfPorts, const char *adapterName)
1121*10652SHyon.Kim@Sun.COM {
1122*10652SHyon.Kim@Sun.COM int matchingHBA = 1;
1123*10652SHyon.Kim@Sun.COM
1124*10652SHyon.Kim@Sun.COM if (input->wwnCount == 0) {
1125*10652SHyon.Kim@Sun.COM printHBAInfo(attrs, input->pflag, numberOfPorts, adapterName);
1126*10652SHyon.Kim@Sun.COM } else {
1127*10652SHyon.Kim@Sun.COM if (isStringInArgv(input, adapterName)) {
1128*10652SHyon.Kim@Sun.COM printHBAInfo(attrs,
1129*10652SHyon.Kim@Sun.COM input->pflag, numberOfPorts, adapterName);
1130*10652SHyon.Kim@Sun.COM } else {
1131*10652SHyon.Kim@Sun.COM matchingHBA = 0;
1132*10652SHyon.Kim@Sun.COM }
1133*10652SHyon.Kim@Sun.COM }
1134*10652SHyon.Kim@Sun.COM
1135*10652SHyon.Kim@Sun.COM return (matchingHBA);
1136*10652SHyon.Kim@Sun.COM }
1137*10652SHyon.Kim@Sun.COM
1138*10652SHyon.Kim@Sun.COM /*
1139*10652SHyon.Kim@Sun.COM * Callback function for hba-port subcommand.
1140*10652SHyon.Kim@Sun.COM *
1141*10652SHyon.Kim@Sun.COM * Arguments:
1142*10652SHyon.Kim@Sun.COM * handle - handle to hba port.
1143*10652SHyon.Kim@Sun.COM * portIndex - the index of hba port currently being processed.
1144*10652SHyon.Kim@Sun.COM * port - pointer to hba port attributes.
1145*10652SHyon.Kim@Sun.COM * attrs - pointer to adapter attributes currently being processed.
1146*10652SHyon.Kim@Sun.COM * input - contains all the input parameters.
1147*10652SHyon.Kim@Sun.COM *
1148*10652SHyon.Kim@Sun.COM * Return Value:
1149*10652SHyon.Kim@Sun.COM * 0 sucessfully processed handle
1150*10652SHyon.Kim@Sun.COM * >0 error has occured
1151*10652SHyon.Kim@Sun.COM */
1152*10652SHyon.Kim@Sun.COM /*ARGSUSED*/
handleHBAPort(HBA_HANDLE handle,char * adapterName,HBA_UINT32 portIndex,SMHBA_PORTATTRIBUTES * port,SMHBA_ADAPTERATTRIBUTES * attrs,inputArg_t * input)1153*10652SHyon.Kim@Sun.COM static int handleHBAPort(HBA_HANDLE handle, char *adapterName,
1154*10652SHyon.Kim@Sun.COM HBA_UINT32 portIndex, SMHBA_PORTATTRIBUTES *port,
1155*10652SHyon.Kim@Sun.COM SMHBA_ADAPTERATTRIBUTES *attrs, inputArg_t *input)
1156*10652SHyon.Kim@Sun.COM {
1157*10652SHyon.Kim@Sun.COM int ret = 0;
1158*10652SHyon.Kim@Sun.COM printHBAPortInfo(port, attrs, input->pflag);
1159*10652SHyon.Kim@Sun.COM ret = processHBAPortPhyInfo(handle, portIndex, port, input->pflag);
1160*10652SHyon.Kim@Sun.COM return (ret);
1161*10652SHyon.Kim@Sun.COM }
1162*10652SHyon.Kim@Sun.COM
1163*10652SHyon.Kim@Sun.COM /*
1164*10652SHyon.Kim@Sun.COM * Callback function for expander subcommand.
1165*10652SHyon.Kim@Sun.COM *
1166*10652SHyon.Kim@Sun.COM * Arguments:
1167*10652SHyon.Kim@Sun.COM * handle - handle to hba port.
1168*10652SHyon.Kim@Sun.COM * portIndex - the index of hba port currently being processed.
1169*10652SHyon.Kim@Sun.COM * port - pointer to hba port attributes.
1170*10652SHyon.Kim@Sun.COM * attrs - pointer to adapter attributes currently being processed.
1171*10652SHyon.Kim@Sun.COM * input - contains all the input parameters.
1172*10652SHyon.Kim@Sun.COM *
1173*10652SHyon.Kim@Sun.COM * Return Value:
1174*10652SHyon.Kim@Sun.COM * 0 sucessfully processed handle
1175*10652SHyon.Kim@Sun.COM * >0 error has occured
1176*10652SHyon.Kim@Sun.COM */
1177*10652SHyon.Kim@Sun.COM /*ARGSUSED*/
handleExpander(HBA_HANDLE handle,char * adapterName,HBA_UINT32 portIndex,SMHBA_PORTATTRIBUTES * port,SMHBA_ADAPTERATTRIBUTES * attrs,inputArg_t * input)1178*10652SHyon.Kim@Sun.COM static int handleExpander(HBA_HANDLE handle, char *adapterName,
1179*10652SHyon.Kim@Sun.COM HBA_UINT32 portIndex, SMHBA_PORTATTRIBUTES *port,
1180*10652SHyon.Kim@Sun.COM SMHBA_ADAPTERATTRIBUTES *attrs, inputArg_t *input)
1181*10652SHyon.Kim@Sun.COM {
1182*10652SHyon.Kim@Sun.COM SMHBA_PORTATTRIBUTES attr;
1183*10652SHyon.Kim@Sun.COM SMHBA_SAS_PORT sasport;
1184*10652SHyon.Kim@Sun.COM HBA_STATUS status;
1185*10652SHyon.Kim@Sun.COM int ret = 0;
1186*10652SHyon.Kim@Sun.COM int i, numberOfRP;
1187*10652SHyon.Kim@Sun.COM rp_tree_t *rpnode;
1188*10652SHyon.Kim@Sun.COM rp_tree_t *rproot = NULL;
1189*10652SHyon.Kim@Sun.COM rp_tree_t *unsolved_head = NULL;
1190*10652SHyon.Kim@Sun.COM rp_tree_t *unsolved_tail = NULL;
1191*10652SHyon.Kim@Sun.COM rp_tree_t *unsolved_sentinel = NULL;
1192*10652SHyon.Kim@Sun.COM int printPort = 0;
1193*10652SHyon.Kim@Sun.COM int numberOfEXP = 0;
1194*10652SHyon.Kim@Sun.COM int unsolved_inserted = 0;
1195*10652SHyon.Kim@Sun.COM int unsolved_left = 0;
1196*10652SHyon.Kim@Sun.COM int disco_port_fail = 0;
1197*10652SHyon.Kim@Sun.COM boolean_t firstPrinted = B_FALSE;
1198*10652SHyon.Kim@Sun.COM
1199*10652SHyon.Kim@Sun.COM (void *) memset(&attr, 0, sizeof (attr));
1200*10652SHyon.Kim@Sun.COM (void *) memset(&sasport, 0, sizeof (sasport));
1201*10652SHyon.Kim@Sun.COM attr.PortSpecificAttribute.SASPort = &sasport;
1202*10652SHyon.Kim@Sun.COM
1203*10652SHyon.Kim@Sun.COM /*
1204*10652SHyon.Kim@Sun.COM * Retrive all expander device from this hba port first.
1205*10652SHyon.Kim@Sun.COM */
1206*10652SHyon.Kim@Sun.COM if ((numberOfRP = port->PortSpecificAttribute.SASPort->
1207*10652SHyon.Kim@Sun.COM NumberofDiscoveredPorts) == 0) {
1208*10652SHyon.Kim@Sun.COM /* no remote port. just return 0. */
1209*10652SHyon.Kim@Sun.COM return (ret);
1210*10652SHyon.Kim@Sun.COM }
1211*10652SHyon.Kim@Sun.COM
1212*10652SHyon.Kim@Sun.COM for (i = 0; i < numberOfRP; i++) {
1213*10652SHyon.Kim@Sun.COM rpnode = calloc(1, sizeof (rp_tree_t));
1214*10652SHyon.Kim@Sun.COM rpnode->portattr.PortSpecificAttribute.SASPort =
1215*10652SHyon.Kim@Sun.COM &rpnode->sasattr;
1216*10652SHyon.Kim@Sun.COM status = SMHBA_GetDiscoveredPortAttributes(handle,
1217*10652SHyon.Kim@Sun.COM portIndex, i, &rpnode->portattr);
1218*10652SHyon.Kim@Sun.COM if (status != HBA_STATUS_OK) {
1219*10652SHyon.Kim@Sun.COM disco_port_fail++;
1220*10652SHyon.Kim@Sun.COM free(rpnode);
1221*10652SHyon.Kim@Sun.COM ret++;
1222*10652SHyon.Kim@Sun.COM continue;
1223*10652SHyon.Kim@Sun.COM }
1224*10652SHyon.Kim@Sun.COM
1225*10652SHyon.Kim@Sun.COM if (rpnode->portattr.PortType == HBA_PORTTYPE_SASEXPANDER) {
1226*10652SHyon.Kim@Sun.COM numberOfEXP++;
1227*10652SHyon.Kim@Sun.COM }
1228*10652SHyon.Kim@Sun.COM /*
1229*10652SHyon.Kim@Sun.COM * We will try to insert this expander device and target
1230*10652SHyon.Kim@Sun.COM * ports into the topology tree. If we failed, we can chain
1231*10652SHyon.Kim@Sun.COM * them together and try again when we have all the
1232*10652SHyon.Kim@Sun.COM * discovered port information in hands.
1233*10652SHyon.Kim@Sun.COM */
1234*10652SHyon.Kim@Sun.COM if (rproot == NULL && memcmp(port->
1235*10652SHyon.Kim@Sun.COM PortSpecificAttribute.SASPort->LocalSASAddress.wwn,
1236*10652SHyon.Kim@Sun.COM rpnode->sasattr.AttachedSASAddress.wwn,
1237*10652SHyon.Kim@Sun.COM sizeof (HBA_WWN)) == 0) {
1238*10652SHyon.Kim@Sun.COM /*
1239*10652SHyon.Kim@Sun.COM * The root node of tree should
1240*10652SHyon.Kim@Sun.COM * be set up first.
1241*10652SHyon.Kim@Sun.COM */
1242*10652SHyon.Kim@Sun.COM rproot = rpnode;
1243*10652SHyon.Kim@Sun.COM } else {
1244*10652SHyon.Kim@Sun.COM /*
1245*10652SHyon.Kim@Sun.COM * If we can not set up the root node of
1246*10652SHyon.Kim@Sun.COM * the tree or we failed to insert
1247*10652SHyon.Kim@Sun.COM * the disocvered port node, queue it up then.
1248*10652SHyon.Kim@Sun.COM */
1249*10652SHyon.Kim@Sun.COM if (rproot == NULL ||
1250*10652SHyon.Kim@Sun.COM sas_rp_tree_insert(&rproot, rpnode) != 0) {
1251*10652SHyon.Kim@Sun.COM if (unsolved_head == NULL) {
1252*10652SHyon.Kim@Sun.COM unsolved_head = rpnode;
1253*10652SHyon.Kim@Sun.COM unsolved_tail = rpnode;
1254*10652SHyon.Kim@Sun.COM } else {
1255*10652SHyon.Kim@Sun.COM rpnode->sibling = unsolved_head;
1256*10652SHyon.Kim@Sun.COM unsolved_head = rpnode;
1257*10652SHyon.Kim@Sun.COM }
1258*10652SHyon.Kim@Sun.COM }
1259*10652SHyon.Kim@Sun.COM }
1260*10652SHyon.Kim@Sun.COM }
1261*10652SHyon.Kim@Sun.COM
1262*10652SHyon.Kim@Sun.COM if (disco_port_fail) {
1263*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "%s %d %s %s\n",
1264*10652SHyon.Kim@Sun.COM gettext("Error: Failed to get attributes for"),
1265*10652SHyon.Kim@Sun.COM disco_port_fail,
1266*10652SHyon.Kim@Sun.COM gettext("connected ports of HBA port"),
1267*10652SHyon.Kim@Sun.COM port->OSDeviceName);
1268*10652SHyon.Kim@Sun.COM }
1269*10652SHyon.Kim@Sun.COM
1270*10652SHyon.Kim@Sun.COM /* no expander found. No need further processing. */
1271*10652SHyon.Kim@Sun.COM if (numberOfEXP == 0) {
1272*10652SHyon.Kim@Sun.COM while (unsolved_head) {
1273*10652SHyon.Kim@Sun.COM unsolved_tail =
1274*10652SHyon.Kim@Sun.COM unsolved_head->sibling;
1275*10652SHyon.Kim@Sun.COM free(unsolved_head);
1276*10652SHyon.Kim@Sun.COM unsolved_head = unsolved_tail;
1277*10652SHyon.Kim@Sun.COM }
1278*10652SHyon.Kim@Sun.COM if (rproot) sas_rp_tree_free(rproot);
1279*10652SHyon.Kim@Sun.COM return (ret);
1280*10652SHyon.Kim@Sun.COM }
1281*10652SHyon.Kim@Sun.COM
1282*10652SHyon.Kim@Sun.COM /*
1283*10652SHyon.Kim@Sun.COM * When we're here, we should already have all information,
1284*10652SHyon.Kim@Sun.COM * now we try again to insert them into the topology tree.
1285*10652SHyon.Kim@Sun.COM * unsolved_head is the pointer which point to the head of
1286*10652SHyon.Kim@Sun.COM * unsolved rpnode linked list.
1287*10652SHyon.Kim@Sun.COM * unsolved_tail is the pointer which point to the tail of
1288*10652SHyon.Kim@Sun.COM * unsolved rpnode linked list.
1289*10652SHyon.Kim@Sun.COM * unsolved_sentinel is for insertion failure detection.
1290*10652SHyon.Kim@Sun.COM * When we're trying to insert the rpnodes from unsolved
1291*10652SHyon.Kim@Sun.COM * linked list, it may happen that some of the rpnodes can
1292*10652SHyon.Kim@Sun.COM * not be inserted no matter how many times we loop through
1293*10652SHyon.Kim@Sun.COM * this linked list. So we use unsolved_sentinel to identify
1294*10652SHyon.Kim@Sun.COM * the tail of last round of scanning, and unsolved_inserted
1295*10652SHyon.Kim@Sun.COM * which is a counter will be used to count how many rpnodes
1296*10652SHyon.Kim@Sun.COM * have been inserted from last round, if it is zero, which
1297*10652SHyon.Kim@Sun.COM * means that we can not insert rpnodes into rptree any more,
1298*10652SHyon.Kim@Sun.COM * and we should stop and deallocate the memory they occupied.
1299*10652SHyon.Kim@Sun.COM */
1300*10652SHyon.Kim@Sun.COM unsolved_sentinel = unsolved_tail;
1301*10652SHyon.Kim@Sun.COM while (unsolved_head) {
1302*10652SHyon.Kim@Sun.COM rpnode = unsolved_head;
1303*10652SHyon.Kim@Sun.COM unsolved_head = unsolved_head->sibling;
1304*10652SHyon.Kim@Sun.COM if (unsolved_head == NULL)
1305*10652SHyon.Kim@Sun.COM unsolved_tail = NULL;
1306*10652SHyon.Kim@Sun.COM rpnode->sibling = NULL;
1307*10652SHyon.Kim@Sun.COM if (sas_rp_tree_insert(&rproot, rpnode) != 0) {
1308*10652SHyon.Kim@Sun.COM unsolved_tail->sibling = rpnode;
1309*10652SHyon.Kim@Sun.COM unsolved_tail = rpnode;
1310*10652SHyon.Kim@Sun.COM if (rpnode == unsolved_sentinel) {
1311*10652SHyon.Kim@Sun.COM /*
1312*10652SHyon.Kim@Sun.COM * We just scanned one round for the
1313*10652SHyon.Kim@Sun.COM * unsolved list. Check to see whether we
1314*10652SHyon.Kim@Sun.COM * have nodes inserted, if none, we should
1315*10652SHyon.Kim@Sun.COM * break in case of an indefinite loop.
1316*10652SHyon.Kim@Sun.COM */
1317*10652SHyon.Kim@Sun.COM if (unsolved_inserted == 0) {
1318*10652SHyon.Kim@Sun.COM /*
1319*10652SHyon.Kim@Sun.COM * Indicate there is unhandled node.
1320*10652SHyon.Kim@Sun.COM * Chain free the whole unsolved
1321*10652SHyon.Kim@Sun.COM * list here.
1322*10652SHyon.Kim@Sun.COM */
1323*10652SHyon.Kim@Sun.COM unsolved_left++;
1324*10652SHyon.Kim@Sun.COM break;
1325*10652SHyon.Kim@Sun.COM } else {
1326*10652SHyon.Kim@Sun.COM unsolved_inserted = 0;
1327*10652SHyon.Kim@Sun.COM unsolved_sentinel = unsolved_tail;
1328*10652SHyon.Kim@Sun.COM }
1329*10652SHyon.Kim@Sun.COM }
1330*10652SHyon.Kim@Sun.COM } else {
1331*10652SHyon.Kim@Sun.COM /*
1332*10652SHyon.Kim@Sun.COM * We just inserted one rpnode, increment the
1333*10652SHyon.Kim@Sun.COM * unsolved_inserted counter. We will utilize this
1334*10652SHyon.Kim@Sun.COM * counter to detect an indefinite insertion loop.
1335*10652SHyon.Kim@Sun.COM */
1336*10652SHyon.Kim@Sun.COM unsolved_inserted++;
1337*10652SHyon.Kim@Sun.COM }
1338*10652SHyon.Kim@Sun.COM }
1339*10652SHyon.Kim@Sun.COM
1340*10652SHyon.Kim@Sun.COM /* check if there is left out discovered ports. */
1341*10652SHyon.Kim@Sun.COM if (unsolved_left) {
1342*10652SHyon.Kim@Sun.COM ret++;
1343*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "%s %s\n",
1344*10652SHyon.Kim@Sun.COM gettext("Error: Failed to establish expander topology on"),
1345*10652SHyon.Kim@Sun.COM port->OSDeviceName);
1346*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "%s\n",
1347*10652SHyon.Kim@Sun.COM gettext(" Folowing port(s) are unresolved."));
1348*10652SHyon.Kim@Sun.COM while (unsolved_head) {
1349*10652SHyon.Kim@Sun.COM unsolved_tail =
1350*10652SHyon.Kim@Sun.COM unsolved_head->sibling;
1351*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "%s%016llx ",
1352*10652SHyon.Kim@Sun.COM firstPrinted ? "" : "\t",
1353*10652SHyon.Kim@Sun.COM wwnConversion(unsolved_head->sasattr.
1354*10652SHyon.Kim@Sun.COM LocalSASAddress.wwn));
1355*10652SHyon.Kim@Sun.COM if (firstPrinted == B_FALSE) firstPrinted = B_TRUE;
1356*10652SHyon.Kim@Sun.COM free(unsolved_head);
1357*10652SHyon.Kim@Sun.COM unsolved_head = unsolved_tail;
1358*10652SHyon.Kim@Sun.COM }
1359*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "\n");
1360*10652SHyon.Kim@Sun.COM /* still print what we have */
1361*10652SHyon.Kim@Sun.COM ret += sas_rp_tree_print(handle, adapterName, portIndex,
1362*10652SHyon.Kim@Sun.COM port, rproot, input, 2 * TABLEN, &printPort);
1363*10652SHyon.Kim@Sun.COM } else {
1364*10652SHyon.Kim@Sun.COM ret += sas_rp_tree_print(handle, adapterName, portIndex,
1365*10652SHyon.Kim@Sun.COM port, rproot, input, 2 * TABLEN, &printPort);
1366*10652SHyon.Kim@Sun.COM }
1367*10652SHyon.Kim@Sun.COM
1368*10652SHyon.Kim@Sun.COM if (rproot) sas_rp_tree_free(rproot);
1369*10652SHyon.Kim@Sun.COM
1370*10652SHyon.Kim@Sun.COM return (ret);
1371*10652SHyon.Kim@Sun.COM }
1372*10652SHyon.Kim@Sun.COM
1373*10652SHyon.Kim@Sun.COM /*
1374*10652SHyon.Kim@Sun.COM * Callback function for target-port subcommand.
1375*10652SHyon.Kim@Sun.COM *
1376*10652SHyon.Kim@Sun.COM * Arguments:
1377*10652SHyon.Kim@Sun.COM * handle - handle to hba port.
1378*10652SHyon.Kim@Sun.COM * portIndex - the index of hba port currently being processed.
1379*10652SHyon.Kim@Sun.COM * port - pointer to hba port attributes.
1380*10652SHyon.Kim@Sun.COM * attrs - pointer to adapter attributes currently being processed.
1381*10652SHyon.Kim@Sun.COM * input - contains all the input parameters.
1382*10652SHyon.Kim@Sun.COM *
1383*10652SHyon.Kim@Sun.COM * Return Value:
1384*10652SHyon.Kim@Sun.COM * 0 sucessfully processed handle
1385*10652SHyon.Kim@Sun.COM * >0 error has occured
1386*10652SHyon.Kim@Sun.COM */
1387*10652SHyon.Kim@Sun.COM /*ARGSUSED*/
handleTargetPort(HBA_HANDLE handle,char * adapterName,HBA_UINT32 portIndex,SMHBA_PORTATTRIBUTES * port,SMHBA_ADAPTERATTRIBUTES * attrs,inputArg_t * input)1388*10652SHyon.Kim@Sun.COM static int handleTargetPort(HBA_HANDLE handle, char *adapterName,
1389*10652SHyon.Kim@Sun.COM HBA_UINT32 portIndex, SMHBA_PORTATTRIBUTES *port,
1390*10652SHyon.Kim@Sun.COM SMHBA_ADAPTERATTRIBUTES *attrs, inputArg_t *input)
1391*10652SHyon.Kim@Sun.COM {
1392*10652SHyon.Kim@Sun.COM HBA_STATUS status;
1393*10652SHyon.Kim@Sun.COM SMHBA_PORTATTRIBUTES targetattr;
1394*10652SHyon.Kim@Sun.COM SMHBA_SAS_PORT sasattr;
1395*10652SHyon.Kim@Sun.COM int i;
1396*10652SHyon.Kim@Sun.COM int ret = 0;
1397*10652SHyon.Kim@Sun.COM int disco_port_fail = 0;
1398*10652SHyon.Kim@Sun.COM
1399*10652SHyon.Kim@Sun.COM targetattr.PortSpecificAttribute.SASPort = &sasattr;
1400*10652SHyon.Kim@Sun.COM
1401*10652SHyon.Kim@Sun.COM for (i = 0; i < port->PortSpecificAttribute.SASPort->
1402*10652SHyon.Kim@Sun.COM NumberofDiscoveredPorts; i++) {
1403*10652SHyon.Kim@Sun.COM status = SMHBA_GetDiscoveredPortAttributes(handle,
1404*10652SHyon.Kim@Sun.COM portIndex, i, &targetattr);
1405*10652SHyon.Kim@Sun.COM if (status != HBA_STATUS_OK) {
1406*10652SHyon.Kim@Sun.COM disco_port_fail++;
1407*10652SHyon.Kim@Sun.COM } else {
1408*10652SHyon.Kim@Sun.COM /* skip expander device */
1409*10652SHyon.Kim@Sun.COM if (targetattr.PortType != HBA_PORTTYPE_SASEXPANDER) {
1410*10652SHyon.Kim@Sun.COM ret += searchTargetPort(handle, portIndex, port,
1411*10652SHyon.Kim@Sun.COM &targetattr, &sasattr, input->pflag);
1412*10652SHyon.Kim@Sun.COM }
1413*10652SHyon.Kim@Sun.COM }
1414*10652SHyon.Kim@Sun.COM }
1415*10652SHyon.Kim@Sun.COM
1416*10652SHyon.Kim@Sun.COM if (disco_port_fail) {
1417*10652SHyon.Kim@Sun.COM ret++;
1418*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "%s %d %s %s\n",
1419*10652SHyon.Kim@Sun.COM gettext("Error: Failed to get attributes for"),
1420*10652SHyon.Kim@Sun.COM disco_port_fail,
1421*10652SHyon.Kim@Sun.COM gettext("connected ports of HBA port"),
1422*10652SHyon.Kim@Sun.COM port->OSDeviceName);
1423*10652SHyon.Kim@Sun.COM }
1424*10652SHyon.Kim@Sun.COM return (ret);
1425*10652SHyon.Kim@Sun.COM }
1426*10652SHyon.Kim@Sun.COM
1427*10652SHyon.Kim@Sun.COM /*
1428*10652SHyon.Kim@Sun.COM * ****************************************************************************
1429*10652SHyon.Kim@Sun.COM *
1430*10652SHyon.Kim@Sun.COM * compareLUName -
1431*10652SHyon.Kim@Sun.COM * compare names directly and also check if disk namees match with
1432*10652SHyon.Kim@Sun.COM * different slice number or /devices path are speicified and matches.
1433*10652SHyon.Kim@Sun.COM *
1434*10652SHyon.Kim@Sun.COM * cmdArg - first string to compare
1435*10652SHyon.Kim@Sun.COM * osName - os name from attributes
1436*10652SHyon.Kim@Sun.COM *
1437*10652SHyon.Kim@Sun.COM * returns B_TRUE if the strings match either directly or via devid
1438*10652SHyon.Kim@Sun.COM * B_FALSE otherwise
1439*10652SHyon.Kim@Sun.COM *
1440*10652SHyon.Kim@Sun.COM * ****************************************************************************
1441*10652SHyon.Kim@Sun.COM */
1442*10652SHyon.Kim@Sun.COM static boolean_t
compareLUName(char * cmdArg,char * osName)1443*10652SHyon.Kim@Sun.COM compareLUName(char *cmdArg, char *osName)
1444*10652SHyon.Kim@Sun.COM {
1445*10652SHyon.Kim@Sun.COM
1446*10652SHyon.Kim@Sun.COM boolean_t isSame = B_FALSE;
1447*10652SHyon.Kim@Sun.COM char dev1[MAXPATHLEN], dev2[MAXPATHLEN];
1448*10652SHyon.Kim@Sun.COM char *ch1, *ch2;
1449*10652SHyon.Kim@Sun.COM
1450*10652SHyon.Kim@Sun.COM if (strcmp(cmdArg, osName) == 0) {
1451*10652SHyon.Kim@Sun.COM isSame = B_TRUE;
1452*10652SHyon.Kim@Sun.COM } else {
1453*10652SHyon.Kim@Sun.COM /* user input didn't match, try to match the core of args. */
1454*10652SHyon.Kim@Sun.COM (void) strlcpy(dev1, cmdArg, MAXPATHLEN);
1455*10652SHyon.Kim@Sun.COM (void) strlcpy(dev2, osName, MAXPATHLEN);
1456*10652SHyon.Kim@Sun.COM /* is this /devices path */
1457*10652SHyon.Kim@Sun.COM if (((ch1 = strrchr(dev1, ',')) != NULL) &&
1458*10652SHyon.Kim@Sun.COM ((ch2 = strrchr(dev2, ',')) != NULL)) {
1459*10652SHyon.Kim@Sun.COM *ch1 = *ch2 = '\0';
1460*10652SHyon.Kim@Sun.COM if (strcmp(dev1, dev2) == 0) {
1461*10652SHyon.Kim@Sun.COM isSame = B_TRUE;
1462*10652SHyon.Kim@Sun.COM }
1463*10652SHyon.Kim@Sun.COM /* is this a /dev link */
1464*10652SHyon.Kim@Sun.COM } else if ((strncmp(dev1, "/dev/", 5) == 0) &&
1465*10652SHyon.Kim@Sun.COM (strncmp(dev2, "/dev/", 5) == 0)) {
1466*10652SHyon.Kim@Sun.COM if ((strstr(dev1, "dsk") != NULL) &&
1467*10652SHyon.Kim@Sun.COM ((strstr(dev2, "dsk") != NULL))) {
1468*10652SHyon.Kim@Sun.COM /* if it is disk link */
1469*10652SHyon.Kim@Sun.COM if (((ch1 = strrchr(dev1, 's')) != NULL) &&
1470*10652SHyon.Kim@Sun.COM ((ch2 = strrchr(dev2, 's')) != NULL)) {
1471*10652SHyon.Kim@Sun.COM *ch1 = *ch2 = '\0';
1472*10652SHyon.Kim@Sun.COM if (strcmp(dev1, dev2) == 0) {
1473*10652SHyon.Kim@Sun.COM isSame = B_TRUE;
1474*10652SHyon.Kim@Sun.COM }
1475*10652SHyon.Kim@Sun.COM }
1476*10652SHyon.Kim@Sun.COM } else {
1477*10652SHyon.Kim@Sun.COM /* other dev links */
1478*10652SHyon.Kim@Sun.COM if (strcmp(dev1, dev2) == 0) {
1479*10652SHyon.Kim@Sun.COM isSame = B_TRUE;
1480*10652SHyon.Kim@Sun.COM }
1481*10652SHyon.Kim@Sun.COM }
1482*10652SHyon.Kim@Sun.COM }
1483*10652SHyon.Kim@Sun.COM } /* compare */
1484*10652SHyon.Kim@Sun.COM
1485*10652SHyon.Kim@Sun.COM return (isSame);
1486*10652SHyon.Kim@Sun.COM }
1487*10652SHyon.Kim@Sun.COM
1488*10652SHyon.Kim@Sun.COM /*
1489*10652SHyon.Kim@Sun.COM * Process logical-unit(lu) subcommand.
1490*10652SHyon.Kim@Sun.COM *
1491*10652SHyon.Kim@Sun.COM * Arguments:
1492*10652SHyon.Kim@Sun.COM * luCount - number of OS device name(s) specified by user.
1493*10652SHyon.Kim@Sun.COM * luArgv - array of OS device name(s) specified by user.
1494*10652SHyon.Kim@Sun.COM * options - all the options specified by user.
1495*10652SHyon.Kim@Sun.COM *
1496*10652SHyon.Kim@Sun.COM * Return Value:
1497*10652SHyon.Kim@Sun.COM * 0 sucessfully processed handle
1498*10652SHyon.Kim@Sun.COM * >0 error has occured
1499*10652SHyon.Kim@Sun.COM */
1500*10652SHyon.Kim@Sun.COM int
sas_util_list_logicalunit(int luCount,char ** luArgv,cmdOptions_t * options)1501*10652SHyon.Kim@Sun.COM sas_util_list_logicalunit(int luCount, char **luArgv, cmdOptions_t *options)
1502*10652SHyon.Kim@Sun.COM {
1503*10652SHyon.Kim@Sun.COM HBA_STATUS status;
1504*10652SHyon.Kim@Sun.COM int processHBA_flags = 0;
1505*10652SHyon.Kim@Sun.COM int lu;
1506*10652SHyon.Kim@Sun.COM boolean_t pathFound;
1507*10652SHyon.Kim@Sun.COM boolean_t verbose;
1508*10652SHyon.Kim@Sun.COM inputArg_t input;
1509*10652SHyon.Kim@Sun.COM discoveredDevice *LUListWalk = NULL;
1510*10652SHyon.Kim@Sun.COM int err_cnt = 0;
1511*10652SHyon.Kim@Sun.COM
1512*10652SHyon.Kim@Sun.COM for (; options->optval; options++) {
1513*10652SHyon.Kim@Sun.COM if (options->optval == 'v') {
1514*10652SHyon.Kim@Sun.COM processHBA_flags |= PRINT_VERBOSE;
1515*10652SHyon.Kim@Sun.COM }
1516*10652SHyon.Kim@Sun.COM }
1517*10652SHyon.Kim@Sun.COM
1518*10652SHyon.Kim@Sun.COM /* HBA_LoadLibrary() */
1519*10652SHyon.Kim@Sun.COM if ((status = HBA_LoadLibrary()) != HBA_STATUS_OK) {
1520*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "%s %s\n",
1521*10652SHyon.Kim@Sun.COM gettext("Failed to load SM-HBA libraries."
1522*10652SHyon.Kim@Sun.COM "Reason:"), getHBAStatus(status));
1523*10652SHyon.Kim@Sun.COM err_cnt++;
1524*10652SHyon.Kim@Sun.COM return (err_cnt);
1525*10652SHyon.Kim@Sun.COM }
1526*10652SHyon.Kim@Sun.COM
1527*10652SHyon.Kim@Sun.COM (void *) memset(&input, 0, sizeof (input));
1528*10652SHyon.Kim@Sun.COM input.pflag = processHBA_flags;
1529*10652SHyon.Kim@Sun.COM input.wwnCount = luCount;
1530*10652SHyon.Kim@Sun.COM input.wwn_argv = luArgv;
1531*10652SHyon.Kim@Sun.COM
1532*10652SHyon.Kim@Sun.COM err_cnt += processHBA(&input, handleLogicalUnit);
1533*10652SHyon.Kim@Sun.COM verbose = (input.pflag & PRINT_VERBOSE) ? B_TRUE : B_FALSE;
1534*10652SHyon.Kim@Sun.COM
1535*10652SHyon.Kim@Sun.COM if (luCount == 0) {
1536*10652SHyon.Kim@Sun.COM /* list all paths */
1537*10652SHyon.Kim@Sun.COM for (LUListWalk = LUList; LUListWalk != NULL;
1538*10652SHyon.Kim@Sun.COM LUListWalk = LUListWalk->next) {
1539*10652SHyon.Kim@Sun.COM err_cnt += printOSDeviceNameInfo(LUListWalk, verbose);
1540*10652SHyon.Kim@Sun.COM }
1541*10652SHyon.Kim@Sun.COM } else {
1542*10652SHyon.Kim@Sun.COM /*
1543*10652SHyon.Kim@Sun.COM * When operands provided, we should set the error code
1544*10652SHyon.Kim@Sun.COM * only if there are issues related with the operands.
1545*10652SHyon.Kim@Sun.COM */
1546*10652SHyon.Kim@Sun.COM err_cnt = 0;
1547*10652SHyon.Kim@Sun.COM /*
1548*10652SHyon.Kim@Sun.COM * list any paths not found first
1549*10652SHyon.Kim@Sun.COM * this gives the user cleaner output
1550*10652SHyon.Kim@Sun.COM */
1551*10652SHyon.Kim@Sun.COM for (lu = 0; lu < luCount; lu++) {
1552*10652SHyon.Kim@Sun.COM for (LUListWalk = LUList, pathFound = B_FALSE;
1553*10652SHyon.Kim@Sun.COM LUListWalk != NULL;
1554*10652SHyon.Kim@Sun.COM LUListWalk = LUListWalk->next) {
1555*10652SHyon.Kim@Sun.COM if (compareLUName(luArgv[lu],
1556*10652SHyon.Kim@Sun.COM LUListWalk->OSDeviceName)) {
1557*10652SHyon.Kim@Sun.COM pathFound = B_TRUE;
1558*10652SHyon.Kim@Sun.COM break;
1559*10652SHyon.Kim@Sun.COM }
1560*10652SHyon.Kim@Sun.COM }
1561*10652SHyon.Kim@Sun.COM if (pathFound == B_FALSE) {
1562*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr,
1563*10652SHyon.Kim@Sun.COM "Error: Logical Unit %s Not Found \n",
1564*10652SHyon.Kim@Sun.COM luArgv[lu]);
1565*10652SHyon.Kim@Sun.COM err_cnt++;
1566*10652SHyon.Kim@Sun.COM }
1567*10652SHyon.Kim@Sun.COM }
1568*10652SHyon.Kim@Sun.COM /* list all paths requested in order requested */
1569*10652SHyon.Kim@Sun.COM for (lu = 0; lu < luCount; lu++) {
1570*10652SHyon.Kim@Sun.COM for (LUListWalk = LUList; LUListWalk != NULL;
1571*10652SHyon.Kim@Sun.COM LUListWalk = LUListWalk->next) {
1572*10652SHyon.Kim@Sun.COM if (compareLUName(luArgv[lu],
1573*10652SHyon.Kim@Sun.COM LUListWalk->OSDeviceName)) {
1574*10652SHyon.Kim@Sun.COM err_cnt += printOSDeviceNameInfo(
1575*10652SHyon.Kim@Sun.COM LUListWalk,
1576*10652SHyon.Kim@Sun.COM verbose);
1577*10652SHyon.Kim@Sun.COM }
1578*10652SHyon.Kim@Sun.COM }
1579*10652SHyon.Kim@Sun.COM }
1580*10652SHyon.Kim@Sun.COM }
1581*10652SHyon.Kim@Sun.COM (void) HBA_FreeLibrary();
1582*10652SHyon.Kim@Sun.COM return (err_cnt);
1583*10652SHyon.Kim@Sun.COM }
1584*10652SHyon.Kim@Sun.COM
1585*10652SHyon.Kim@Sun.COM /*
1586*10652SHyon.Kim@Sun.COM * Callback function for logical-unit(lu) subcommand.
1587*10652SHyon.Kim@Sun.COM *
1588*10652SHyon.Kim@Sun.COM * Arguments:
1589*10652SHyon.Kim@Sun.COM * handle - handle to hba port.
1590*10652SHyon.Kim@Sun.COM * portIndex - the index of hba port currently being processed.
1591*10652SHyon.Kim@Sun.COM * port - pointer to hba port attributes.
1592*10652SHyon.Kim@Sun.COM * attrs - pointer to adapter attributes currently being processed.
1593*10652SHyon.Kim@Sun.COM * input - contains all the input parameters.
1594*10652SHyon.Kim@Sun.COM *
1595*10652SHyon.Kim@Sun.COM * Return Value:
1596*10652SHyon.Kim@Sun.COM * 0 sucessfully processed handle
1597*10652SHyon.Kim@Sun.COM * >0 error has occured
1598*10652SHyon.Kim@Sun.COM */
1599*10652SHyon.Kim@Sun.COM /*ARGSUSED*/
handleLogicalUnit(HBA_HANDLE handle,char * adapterName,HBA_UINT32 portIndex,SMHBA_PORTATTRIBUTES * port,SMHBA_ADAPTERATTRIBUTES * attrs,inputArg_t * input)1600*10652SHyon.Kim@Sun.COM static int handleLogicalUnit(HBA_HANDLE handle, char *adapterName,
1601*10652SHyon.Kim@Sun.COM HBA_UINT32 portIndex, SMHBA_PORTATTRIBUTES *port,
1602*10652SHyon.Kim@Sun.COM SMHBA_ADAPTERATTRIBUTES *attrs, inputArg_t *input)
1603*10652SHyon.Kim@Sun.COM {
1604*10652SHyon.Kim@Sun.COM HBA_STATUS status;
1605*10652SHyon.Kim@Sun.COM SMHBA_TARGETMAPPING *map;
1606*10652SHyon.Kim@Sun.COM HBA_WWN hbaPortWWN, domainPortWWN;
1607*10652SHyon.Kim@Sun.COM char *portName = NULL;
1608*10652SHyon.Kim@Sun.COM int numentries;
1609*10652SHyon.Kim@Sun.COM int count = 0;
1610*10652SHyon.Kim@Sun.COM int ret = 0;
1611*10652SHyon.Kim@Sun.COM
1612*10652SHyon.Kim@Sun.COM hbaPortWWN = port->PortSpecificAttribute.SASPort->LocalSASAddress;
1613*10652SHyon.Kim@Sun.COM portName = port->OSDeviceName;
1614*10652SHyon.Kim@Sun.COM
1615*10652SHyon.Kim@Sun.COM status = get_domainPort(handle, portIndex, port, &domainPortWWN);
1616*10652SHyon.Kim@Sun.COM switch (status) {
1617*10652SHyon.Kim@Sun.COM case HBA_STATUS_OK:
1618*10652SHyon.Kim@Sun.COM break;
1619*10652SHyon.Kim@Sun.COM case HBA_STATUS_ERROR_NOT_SUPPORTED:
1620*10652SHyon.Kim@Sun.COM /* don't increase error flag for no phy configuration */
1621*10652SHyon.Kim@Sun.COM return (ret);
1622*10652SHyon.Kim@Sun.COM case HBA_STATUS_ERROR:
1623*10652SHyon.Kim@Sun.COM default:
1624*10652SHyon.Kim@Sun.COM return (++ret);
1625*10652SHyon.Kim@Sun.COM }
1626*10652SHyon.Kim@Sun.COM
1627*10652SHyon.Kim@Sun.COM if ((map = calloc(1, sizeof (*map))) == NULL) {
1628*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "%s\n",
1629*10652SHyon.Kim@Sun.COM gettext("No enough memory on heap."));
1630*10652SHyon.Kim@Sun.COM return (++ret);
1631*10652SHyon.Kim@Sun.COM }
1632*10652SHyon.Kim@Sun.COM map->NumberOfEntries = 1;
1633*10652SHyon.Kim@Sun.COM
1634*10652SHyon.Kim@Sun.COM /*
1635*10652SHyon.Kim@Sun.COM * First, we need to get the target mapping data from this hba
1636*10652SHyon.Kim@Sun.COM * port.
1637*10652SHyon.Kim@Sun.COM */
1638*10652SHyon.Kim@Sun.COM status = SMHBA_GetTargetMapping(handle,
1639*10652SHyon.Kim@Sun.COM hbaPortWWN, domainPortWWN, map);
1640*10652SHyon.Kim@Sun.COM
1641*10652SHyon.Kim@Sun.COM if (status == HBA_STATUS_ERROR_MORE_DATA) {
1642*10652SHyon.Kim@Sun.COM numentries = map->NumberOfEntries;
1643*10652SHyon.Kim@Sun.COM free(map);
1644*10652SHyon.Kim@Sun.COM map = calloc(1, sizeof (HBA_UINT32) +
1645*10652SHyon.Kim@Sun.COM (numentries * sizeof (SMHBA_SCSIENTRY)));
1646*10652SHyon.Kim@Sun.COM if (map == NULL) {
1647*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "%s\n",
1648*10652SHyon.Kim@Sun.COM gettext("No enough memory on heap."));
1649*10652SHyon.Kim@Sun.COM return (++ret);
1650*10652SHyon.Kim@Sun.COM }
1651*10652SHyon.Kim@Sun.COM map->NumberOfEntries = numentries;
1652*10652SHyon.Kim@Sun.COM status = SMHBA_GetTargetMapping(handle,
1653*10652SHyon.Kim@Sun.COM hbaPortWWN, domainPortWWN, map);
1654*10652SHyon.Kim@Sun.COM }
1655*10652SHyon.Kim@Sun.COM
1656*10652SHyon.Kim@Sun.COM if (status != HBA_STATUS_OK) {
1657*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "%s %016llx %s %s\n",
1658*10652SHyon.Kim@Sun.COM gettext("Error: Failed to get SCSI mapping data for "
1659*10652SHyon.Kim@Sun.COM "the HBA port"), wwnConversion(hbaPortWWN.wwn),
1660*10652SHyon.Kim@Sun.COM gettext("Reason:"),
1661*10652SHyon.Kim@Sun.COM getHBAStatus(status));
1662*10652SHyon.Kim@Sun.COM free(map);
1663*10652SHyon.Kim@Sun.COM return (++ret);
1664*10652SHyon.Kim@Sun.COM }
1665*10652SHyon.Kim@Sun.COM
1666*10652SHyon.Kim@Sun.COM /*
1667*10652SHyon.Kim@Sun.COM * By iterating each entry of the targetmapping data, we will
1668*10652SHyon.Kim@Sun.COM * construct a global list of logical unit.
1669*10652SHyon.Kim@Sun.COM */
1670*10652SHyon.Kim@Sun.COM for (count = 0; count < map->NumberOfEntries; count++) {
1671*10652SHyon.Kim@Sun.COM ret += searchDevice(
1672*10652SHyon.Kim@Sun.COM &(map->entry[count]), handle, hbaPortWWN, domainPortWWN,
1673*10652SHyon.Kim@Sun.COM portName, input->pflag);
1674*10652SHyon.Kim@Sun.COM }
1675*10652SHyon.Kim@Sun.COM free(map);
1676*10652SHyon.Kim@Sun.COM return (ret);
1677*10652SHyon.Kim@Sun.COM }
1678*10652SHyon.Kim@Sun.COM
1679*10652SHyon.Kim@Sun.COM /*
1680*10652SHyon.Kim@Sun.COM * Search the matching targetmapping data for given target port and SAM LUN
1681*10652SHyon.Kim@Sun.COM * and return target mapping data if found.
1682*10652SHyon.Kim@Sun.COM *
1683*10652SHyon.Kim@Sun.COM * Arguments:
1684*10652SHyon.Kim@Sun.COM * handle - handle to hba port.
1685*10652SHyon.Kim@Sun.COM * portIndex - hba port index
1686*10652SHyon.Kim@Sun.COM * port - hba port attributes.
1687*10652SHyon.Kim@Sun.COM * targetportWWN - target port SAS address.
1688*10652SHyon.Kim@Sun.COM * domainportWWN - domain port SAS address.
1689*10652SHyon.Kim@Sun.COM * domainportttr - target port SAS attributes.
1690*10652SHyon.Kim@Sun.COM * samLUN - samLUN from report LUNs data.
1691*10652SHyon.Kim@Sun.COM * data - matching target mapping data.
1692*10652SHyon.Kim@Sun.COM *
1693*10652SHyon.Kim@Sun.COM * Return Value:
1694*10652SHyon.Kim@Sun.COM * 0 sucessfully processed handle
1695*10652SHyon.Kim@Sun.COM * >0 error has occured
1696*10652SHyon.Kim@Sun.COM */
1697*10652SHyon.Kim@Sun.COM static int
searchTargetPortMappingData(HBA_HANDLE handle,HBA_UINT32 portIndex,SMHBA_PORTATTRIBUTES * port,SMHBA_SAS_PORT * sasattr,struct targetPortConfig * configData)1698*10652SHyon.Kim@Sun.COM searchTargetPortMappingData(HBA_HANDLE handle, HBA_UINT32 portIndex,
1699*10652SHyon.Kim@Sun.COM SMHBA_PORTATTRIBUTES *port, SMHBA_SAS_PORT *sasattr,
1700*10652SHyon.Kim@Sun.COM struct targetPortConfig *configData)
1701*10652SHyon.Kim@Sun.COM {
1702*10652SHyon.Kim@Sun.COM int ret = 0;
1703*10652SHyon.Kim@Sun.COM HBA_STATUS status;
1704*10652SHyon.Kim@Sun.COM SMHBA_TARGETMAPPING *map = NULL;
1705*10652SHyon.Kim@Sun.COM HBA_WWN hbaPortWWN, domainPortWWN;
1706*10652SHyon.Kim@Sun.COM int numentries, count;
1707*10652SHyon.Kim@Sun.COM targetPortMappingData_t *TPMapData;
1708*10652SHyon.Kim@Sun.COM struct scsi_inquiry inq;
1709*10652SHyon.Kim@Sun.COM struct scsi_extended_sense sense;
1710*10652SHyon.Kim@Sun.COM HBA_UINT32 responseSize, senseSize = 0;
1711*10652SHyon.Kim@Sun.COM uchar_t rawLUNs[DEFAULT_LUN_LENGTH], *lun_string;
1712*10652SHyon.Kim@Sun.COM HBA_UINT8 scsiStatus;
1713*10652SHyon.Kim@Sun.COM rep_luns_rsp_t *lun_resp;
1714*10652SHyon.Kim@Sun.COM int lunNum, numberOfLun, lunCount;
1715*10652SHyon.Kim@Sun.COM uint32_t lunlength, tmp_lunlength;
1716*10652SHyon.Kim@Sun.COM uint64_t sasLUN;
1717*10652SHyon.Kim@Sun.COM SMHBA_SCSILUN smhbaLUN;
1718*10652SHyon.Kim@Sun.COM
1719*10652SHyon.Kim@Sun.COM hbaPortWWN = port->PortSpecificAttribute.SASPort->
1720*10652SHyon.Kim@Sun.COM LocalSASAddress;
1721*10652SHyon.Kim@Sun.COM
1722*10652SHyon.Kim@Sun.COM status = get_domainPort(handle, portIndex, port, &domainPortWWN);
1723*10652SHyon.Kim@Sun.COM if (status == HBA_STATUS_OK) {
1724*10652SHyon.Kim@Sun.COM if ((map = calloc(1, sizeof (*map))) == NULL) {
1725*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "%s\n",
1726*10652SHyon.Kim@Sun.COM gettext("No enough memory on heap."));
1727*10652SHyon.Kim@Sun.COM return (++ret);
1728*10652SHyon.Kim@Sun.COM }
1729*10652SHyon.Kim@Sun.COM map->NumberOfEntries = 1;
1730*10652SHyon.Kim@Sun.COM
1731*10652SHyon.Kim@Sun.COM status = SMHBA_GetTargetMapping(handle, hbaPortWWN,
1732*10652SHyon.Kim@Sun.COM domainPortWWN, map);
1733*10652SHyon.Kim@Sun.COM
1734*10652SHyon.Kim@Sun.COM if (status == HBA_STATUS_ERROR_MORE_DATA) {
1735*10652SHyon.Kim@Sun.COM numentries = map->NumberOfEntries;
1736*10652SHyon.Kim@Sun.COM free(map);
1737*10652SHyon.Kim@Sun.COM map = calloc(1, sizeof (HBA_UINT32) +
1738*10652SHyon.Kim@Sun.COM (numentries * sizeof (SMHBA_SCSIENTRY)));
1739*10652SHyon.Kim@Sun.COM if (map == NULL) {
1740*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "%s\n",
1741*10652SHyon.Kim@Sun.COM gettext("No enough memory on heap."));
1742*10652SHyon.Kim@Sun.COM return (++ret);
1743*10652SHyon.Kim@Sun.COM }
1744*10652SHyon.Kim@Sun.COM map->NumberOfEntries = numentries;
1745*10652SHyon.Kim@Sun.COM status = SMHBA_GetTargetMapping(handle,
1746*10652SHyon.Kim@Sun.COM hbaPortWWN, domainPortWWN, map);
1747*10652SHyon.Kim@Sun.COM }
1748*10652SHyon.Kim@Sun.COM
1749*10652SHyon.Kim@Sun.COM if (status != HBA_STATUS_OK) {
1750*10652SHyon.Kim@Sun.COM /* continue to build mapping data based SCSI info */
1751*10652SHyon.Kim@Sun.COM ret++;
1752*10652SHyon.Kim@Sun.COM free(map);
1753*10652SHyon.Kim@Sun.COM map = NULL;
1754*10652SHyon.Kim@Sun.COM }
1755*10652SHyon.Kim@Sun.COM }
1756*10652SHyon.Kim@Sun.COM
1757*10652SHyon.Kim@Sun.COM /*
1758*10652SHyon.Kim@Sun.COM * Get report lun data.
1759*10652SHyon.Kim@Sun.COM */
1760*10652SHyon.Kim@Sun.COM responseSize = DEFAULT_LUN_LENGTH;
1761*10652SHyon.Kim@Sun.COM senseSize = sizeof (struct scsi_extended_sense);
1762*10652SHyon.Kim@Sun.COM (void) memset(&sense, 0, sizeof (sense));
1763*10652SHyon.Kim@Sun.COM status = SMHBA_ScsiReportLUNs(
1764*10652SHyon.Kim@Sun.COM handle,
1765*10652SHyon.Kim@Sun.COM hbaPortWWN,
1766*10652SHyon.Kim@Sun.COM sasattr->LocalSASAddress,
1767*10652SHyon.Kim@Sun.COM domainPortWWN,
1768*10652SHyon.Kim@Sun.COM (void *)rawLUNs,
1769*10652SHyon.Kim@Sun.COM &responseSize,
1770*10652SHyon.Kim@Sun.COM &scsiStatus,
1771*10652SHyon.Kim@Sun.COM (void *) &sense, &senseSize);
1772*10652SHyon.Kim@Sun.COM
1773*10652SHyon.Kim@Sun.COM /*
1774*10652SHyon.Kim@Sun.COM * if HBA_STATUS_ERROR_NOT_A_TARGET is return, we can assume this is
1775*10652SHyon.Kim@Sun.COM * a remote HBA and move on
1776*10652SHyon.Kim@Sun.COM */
1777*10652SHyon.Kim@Sun.COM if (status != HBA_STATUS_OK) {
1778*10652SHyon.Kim@Sun.COM configData->reportLUNsFailed = B_TRUE;
1779*10652SHyon.Kim@Sun.COM if (map != NULL) {
1780*10652SHyon.Kim@Sun.COM /*
1781*10652SHyon.Kim@Sun.COM * Let's search mapping data and indicate that Report
1782*10652SHyon.Kim@Sun.COM * LUNs failed.
1783*10652SHyon.Kim@Sun.COM */
1784*10652SHyon.Kim@Sun.COM for (count = 0; count < map->NumberOfEntries; count++) {
1785*10652SHyon.Kim@Sun.COM if (memcmp(map->entry[count].PortLun.
1786*10652SHyon.Kim@Sun.COM PortWWN.wwn, sasattr->LocalSASAddress.wwn,
1787*10652SHyon.Kim@Sun.COM sizeof (HBA_WWN)) == 0) {
1788*10652SHyon.Kim@Sun.COM /* allocate mapping data for each LUN */
1789*10652SHyon.Kim@Sun.COM TPMapData = calloc(1,
1790*10652SHyon.Kim@Sun.COM sizeof (targetPortMappingData_t));
1791*10652SHyon.Kim@Sun.COM if (TPMapData == NULL) {
1792*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "%s\n",
1793*10652SHyon.Kim@Sun.COM gettext("No enough "
1794*10652SHyon.Kim@Sun.COM "memory."));
1795*10652SHyon.Kim@Sun.COM free(map);
1796*10652SHyon.Kim@Sun.COM return (++ret);
1797*10652SHyon.Kim@Sun.COM }
1798*10652SHyon.Kim@Sun.COM TPMapData->mappingExist = B_TRUE;
1799*10652SHyon.Kim@Sun.COM TPMapData->osLUN =
1800*10652SHyon.Kim@Sun.COM map->entry[count].ScsiId.ScsiOSLun;
1801*10652SHyon.Kim@Sun.COM (void) strlcpy(TPMapData->osDeviceName,
1802*10652SHyon.Kim@Sun.COM map->entry[count].ScsiId.
1803*10652SHyon.Kim@Sun.COM OSDeviceName,
1804*10652SHyon.Kim@Sun.COM sizeof (TPMapData->osDeviceName));
1805*10652SHyon.Kim@Sun.COM TPMapData->inq_vid[0] = '\0';
1806*10652SHyon.Kim@Sun.COM TPMapData->inq_pid[0] = '\0';
1807*10652SHyon.Kim@Sun.COM TPMapData->inq_dtype = DTYPE_UNKNOWN;
1808*10652SHyon.Kim@Sun.COM if (configData->map == NULL) {
1809*10652SHyon.Kim@Sun.COM configData->map = TPMapData;
1810*10652SHyon.Kim@Sun.COM } else {
1811*10652SHyon.Kim@Sun.COM TPMapData->next =
1812*10652SHyon.Kim@Sun.COM configData->map->next;
1813*10652SHyon.Kim@Sun.COM configData->map = TPMapData;
1814*10652SHyon.Kim@Sun.COM }
1815*10652SHyon.Kim@Sun.COM }
1816*10652SHyon.Kim@Sun.COM }
1817*10652SHyon.Kim@Sun.COM }
1818*10652SHyon.Kim@Sun.COM (void) free(map);
1819*10652SHyon.Kim@Sun.COM return (++ret);
1820*10652SHyon.Kim@Sun.COM }
1821*10652SHyon.Kim@Sun.COM lun_resp = (rep_luns_rsp_t *)((void *)rawLUNs);
1822*10652SHyon.Kim@Sun.COM (void) memcpy(&tmp_lunlength, &(lun_resp->length),
1823*10652SHyon.Kim@Sun.COM sizeof (tmp_lunlength));
1824*10652SHyon.Kim@Sun.COM lunlength = ntohl(tmp_lunlength);
1825*10652SHyon.Kim@Sun.COM (void) memcpy(&numberOfLun, &lunlength, sizeof (numberOfLun));
1826*10652SHyon.Kim@Sun.COM for (lunCount = 0; lunCount < (numberOfLun / 8); lunCount++) {
1827*10652SHyon.Kim@Sun.COM /* allocate mapping data for each LUN */
1828*10652SHyon.Kim@Sun.COM TPMapData = calloc(1,
1829*10652SHyon.Kim@Sun.COM sizeof (targetPortMappingData_t));
1830*10652SHyon.Kim@Sun.COM if (TPMapData == NULL) {
1831*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "%s\n",
1832*10652SHyon.Kim@Sun.COM gettext("No enough memory."));
1833*10652SHyon.Kim@Sun.COM free(map);
1834*10652SHyon.Kim@Sun.COM return (++ret);
1835*10652SHyon.Kim@Sun.COM }
1836*10652SHyon.Kim@Sun.COM
1837*10652SHyon.Kim@Sun.COM (void) memcpy(&TPMapData->reportLUN, lun_resp->
1838*10652SHyon.Kim@Sun.COM lun[lunCount].val, sizeof (SMHBA_SCSILUN));
1839*10652SHyon.Kim@Sun.COM
1840*10652SHyon.Kim@Sun.COM /*
1841*10652SHyon.Kim@Sun.COM * now issue standard inquiry to get Vendor
1842*10652SHyon.Kim@Sun.COM * and product information
1843*10652SHyon.Kim@Sun.COM */
1844*10652SHyon.Kim@Sun.COM responseSize = sizeof (struct scsi_inquiry);
1845*10652SHyon.Kim@Sun.COM senseSize = sizeof (struct scsi_extended_sense);
1846*10652SHyon.Kim@Sun.COM (void) memset(&inq, 0, sizeof (struct scsi_inquiry));
1847*10652SHyon.Kim@Sun.COM (void) memset(&sense, 0, sizeof (sense));
1848*10652SHyon.Kim@Sun.COM sasLUN = ntohll(wwnConversion(lun_resp->lun[lunCount].val));
1849*10652SHyon.Kim@Sun.COM (void) memcpy(&smhbaLUN, &sasLUN, sizeof (SMHBA_SCSILUN));
1850*10652SHyon.Kim@Sun.COM status = SMHBA_ScsiInquiry(
1851*10652SHyon.Kim@Sun.COM handle,
1852*10652SHyon.Kim@Sun.COM hbaPortWWN,
1853*10652SHyon.Kim@Sun.COM sasattr->LocalSASAddress,
1854*10652SHyon.Kim@Sun.COM domainPortWWN,
1855*10652SHyon.Kim@Sun.COM smhbaLUN,
1856*10652SHyon.Kim@Sun.COM 0,
1857*10652SHyon.Kim@Sun.COM 0,
1858*10652SHyon.Kim@Sun.COM (void *) &inq, &responseSize,
1859*10652SHyon.Kim@Sun.COM &scsiStatus,
1860*10652SHyon.Kim@Sun.COM (void *) &sense, &senseSize);
1861*10652SHyon.Kim@Sun.COM if (status != HBA_STATUS_OK) {
1862*10652SHyon.Kim@Sun.COM TPMapData->inq_vid[0] = '\0';
1863*10652SHyon.Kim@Sun.COM TPMapData->inq_pid[0] = '\0';
1864*10652SHyon.Kim@Sun.COM TPMapData->inq_dtype = DTYPE_UNKNOWN;
1865*10652SHyon.Kim@Sun.COM /* indicate that inquiry for this lun is failed */
1866*10652SHyon.Kim@Sun.COM TPMapData->inquiryFailed = B_TRUE;
1867*10652SHyon.Kim@Sun.COM } else {
1868*10652SHyon.Kim@Sun.COM (void *) memcpy(TPMapData->inq_vid, inq.inq_vid,
1869*10652SHyon.Kim@Sun.COM sizeof (TPMapData->inq_vid));
1870*10652SHyon.Kim@Sun.COM (void *) memcpy(TPMapData->inq_pid, inq.inq_pid,
1871*10652SHyon.Kim@Sun.COM sizeof (TPMapData->inq_pid));
1872*10652SHyon.Kim@Sun.COM TPMapData->inq_dtype = inq.inq_dtype;
1873*10652SHyon.Kim@Sun.COM }
1874*10652SHyon.Kim@Sun.COM
1875*10652SHyon.Kim@Sun.COM if (map != NULL) {
1876*10652SHyon.Kim@Sun.COM for (count = 0; count < map->NumberOfEntries; count++) {
1877*10652SHyon.Kim@Sun.COM if ((memcmp(map->entry[count].PortLun.
1878*10652SHyon.Kim@Sun.COM PortWWN.wwn, sasattr->LocalSASAddress.wwn,
1879*10652SHyon.Kim@Sun.COM sizeof (HBA_WWN)) == 0) &&
1880*10652SHyon.Kim@Sun.COM (memcmp(&(map->entry[count].PortLun.
1881*10652SHyon.Kim@Sun.COM TargetLun), &smhbaLUN,
1882*10652SHyon.Kim@Sun.COM sizeof (SMHBA_SCSILUN))
1883*10652SHyon.Kim@Sun.COM == 0)) {
1884*10652SHyon.Kim@Sun.COM TPMapData->mappingExist = B_TRUE;
1885*10652SHyon.Kim@Sun.COM TPMapData->osLUN =
1886*10652SHyon.Kim@Sun.COM map->entry[count].ScsiId.ScsiOSLun;
1887*10652SHyon.Kim@Sun.COM (void) strlcpy(TPMapData->osDeviceName,
1888*10652SHyon.Kim@Sun.COM map->entry[count].ScsiId.
1889*10652SHyon.Kim@Sun.COM OSDeviceName,
1890*10652SHyon.Kim@Sun.COM sizeof (TPMapData->osDeviceName));
1891*10652SHyon.Kim@Sun.COM break;
1892*10652SHyon.Kim@Sun.COM }
1893*10652SHyon.Kim@Sun.COM }
1894*10652SHyon.Kim@Sun.COM if (count == map->NumberOfEntries) {
1895*10652SHyon.Kim@Sun.COM TPMapData->osDeviceName[0] = '\0';
1896*10652SHyon.Kim@Sun.COM lun_string = lun_resp->lun[lunCount].val;
1897*10652SHyon.Kim@Sun.COM lunNum = ((lun_string[0] & 0x3F) << 8) |
1898*10652SHyon.Kim@Sun.COM lun_string[1];
1899*10652SHyon.Kim@Sun.COM TPMapData->osLUN = lunNum;
1900*10652SHyon.Kim@Sun.COM }
1901*10652SHyon.Kim@Sun.COM } else {
1902*10652SHyon.Kim@Sun.COM /* Not able to get any target mapping information */
1903*10652SHyon.Kim@Sun.COM TPMapData->osDeviceName[0] = '\0';
1904*10652SHyon.Kim@Sun.COM lun_string = lun_resp->lun[lunCount].val;
1905*10652SHyon.Kim@Sun.COM lunNum = ((lun_string[0] & 0x3F) << 8) |
1906*10652SHyon.Kim@Sun.COM lun_string[1];
1907*10652SHyon.Kim@Sun.COM TPMapData->osLUN = lunNum;
1908*10652SHyon.Kim@Sun.COM }
1909*10652SHyon.Kim@Sun.COM
1910*10652SHyon.Kim@Sun.COM if (configData->map == NULL) {
1911*10652SHyon.Kim@Sun.COM configData->map = TPMapData;
1912*10652SHyon.Kim@Sun.COM } else {
1913*10652SHyon.Kim@Sun.COM TPMapData->next = configData->map->next;
1914*10652SHyon.Kim@Sun.COM configData->map = TPMapData;
1915*10652SHyon.Kim@Sun.COM }
1916*10652SHyon.Kim@Sun.COM }
1917*10652SHyon.Kim@Sun.COM free(map);
1918*10652SHyon.Kim@Sun.COM return (ret);
1919*10652SHyon.Kim@Sun.COM }
1920*10652SHyon.Kim@Sun.COM
1921*10652SHyon.Kim@Sun.COM /*
1922*10652SHyon.Kim@Sun.COM * Search the discovered LUs and construct the global LU list.
1923*10652SHyon.Kim@Sun.COM *
1924*10652SHyon.Kim@Sun.COM * Arguments:
1925*10652SHyon.Kim@Sun.COM * handle - handle to hba port.
1926*10652SHyon.Kim@Sun.COM * portIndex - hba port index
1927*10652SHyon.Kim@Sun.COM * port - hba port attributes.
1928*10652SHyon.Kim@Sun.COM * targetattr - target port attributes.
1929*10652SHyon.Kim@Sun.COM * sasattr - target port SAS attributes.
1930*10652SHyon.Kim@Sun.COM * pflag - options the user specified.
1931*10652SHyon.Kim@Sun.COM *
1932*10652SHyon.Kim@Sun.COM * Return Value:
1933*10652SHyon.Kim@Sun.COM * 0 sucessfully processed handle
1934*10652SHyon.Kim@Sun.COM * >0 error has occured
1935*10652SHyon.Kim@Sun.COM */
1936*10652SHyon.Kim@Sun.COM static int
searchTargetPort(HBA_HANDLE handle,HBA_UINT32 portIndex,SMHBA_PORTATTRIBUTES * port,SMHBA_PORTATTRIBUTES * targetattr,SMHBA_SAS_PORT * sasattr,int pflag)1937*10652SHyon.Kim@Sun.COM searchTargetPort(HBA_HANDLE handle, HBA_UINT32 portIndex,
1938*10652SHyon.Kim@Sun.COM SMHBA_PORTATTRIBUTES *port, SMHBA_PORTATTRIBUTES *targetattr,
1939*10652SHyon.Kim@Sun.COM SMHBA_SAS_PORT *sasattr, int pflag)
1940*10652SHyon.Kim@Sun.COM {
1941*10652SHyon.Kim@Sun.COM int ret = 0;
1942*10652SHyon.Kim@Sun.COM HBA_WWN expander;
1943*10652SHyon.Kim@Sun.COM HBA_WWN domainPortWWN;
1944*10652SHyon.Kim@Sun.COM targetPortList_t *discoveredTP, *newTP;
1945*10652SHyon.Kim@Sun.COM targetPortConfig_t *TPConfig, *newConfig, *prevConfig;
1946*10652SHyon.Kim@Sun.COM boolean_t foundTP = B_FALSE;
1947*10652SHyon.Kim@Sun.COM boolean_t foundConfig = B_FALSE;
1948*10652SHyon.Kim@Sun.COM int status;
1949*10652SHyon.Kim@Sun.COM SMHBA_PORTATTRIBUTES tgtattr;
1950*10652SHyon.Kim@Sun.COM SMHBA_SAS_PORT tgtsasport;
1951*10652SHyon.Kim@Sun.COM int expanderValid = 0;
1952*10652SHyon.Kim@Sun.COM
1953*10652SHyon.Kim@Sun.COM status = get_domainPort(handle, portIndex, port, &domainPortWWN);
1954*10652SHyon.Kim@Sun.COM switch (status) {
1955*10652SHyon.Kim@Sun.COM case HBA_STATUS_OK:
1956*10652SHyon.Kim@Sun.COM break;
1957*10652SHyon.Kim@Sun.COM case HBA_STATUS_ERROR_NOT_SUPPORTED:
1958*10652SHyon.Kim@Sun.COM /* don't increase error flag for no phy configuration */
1959*10652SHyon.Kim@Sun.COM return (ret);
1960*10652SHyon.Kim@Sun.COM case HBA_STATUS_ERROR:
1961*10652SHyon.Kim@Sun.COM default:
1962*10652SHyon.Kim@Sun.COM return (++ret);
1963*10652SHyon.Kim@Sun.COM }
1964*10652SHyon.Kim@Sun.COM
1965*10652SHyon.Kim@Sun.COM /*
1966*10652SHyon.Kim@Sun.COM * First, we will iterate the already constructed target port
1967*10652SHyon.Kim@Sun.COM * list to see whether there is a target port already exist with
1968*10652SHyon.Kim@Sun.COM * matching target port SAS address.
1969*10652SHyon.Kim@Sun.COM */
1970*10652SHyon.Kim@Sun.COM for (discoveredTP = gTargetPortList; discoveredTP != NULL;
1971*10652SHyon.Kim@Sun.COM discoveredTP = discoveredTP->next) {
1972*10652SHyon.Kim@Sun.COM if (memcmp((void *)sasattr->LocalSASAddress.wwn,
1973*10652SHyon.Kim@Sun.COM (void *)discoveredTP->sasattr.LocalSASAddress.wwn,
1974*10652SHyon.Kim@Sun.COM sizeof (HBA_WWN)) == 0) {
1975*10652SHyon.Kim@Sun.COM /*
1976*10652SHyon.Kim@Sun.COM * if the target port exist and
1977*10652SHyon.Kim@Sun.COM * verbose is not set, just return
1978*10652SHyon.Kim@Sun.COM */
1979*10652SHyon.Kim@Sun.COM if (((pflag & PRINT_VERBOSE) == 0) &&
1980*10652SHyon.Kim@Sun.COM ((pflag & PRINT_TARGET_SCSI) == 0)) {
1981*10652SHyon.Kim@Sun.COM return (ret);
1982*10652SHyon.Kim@Sun.COM }
1983*10652SHyon.Kim@Sun.COM foundTP = B_TRUE;
1984*10652SHyon.Kim@Sun.COM break;
1985*10652SHyon.Kim@Sun.COM }
1986*10652SHyon.Kim@Sun.COM }
1987*10652SHyon.Kim@Sun.COM
1988*10652SHyon.Kim@Sun.COM if (foundTP == B_TRUE) {
1989*10652SHyon.Kim@Sun.COM /*
1990*10652SHyon.Kim@Sun.COM * If there is a target port already exist, we should
1991*10652SHyon.Kim@Sun.COM * add more information on the target port to construct the
1992*10652SHyon.Kim@Sun.COM * whole topology.
1993*10652SHyon.Kim@Sun.COM * Here we will check whether the current hba port name
1994*10652SHyon.Kim@Sun.COM * has already been added.
1995*10652SHyon.Kim@Sun.COM */
1996*10652SHyon.Kim@Sun.COM /* first get the expander SAS address compare */
1997*10652SHyon.Kim@Sun.COM if (memcmp((void *)port->PortSpecificAttribute.SASPort->
1998*10652SHyon.Kim@Sun.COM LocalSASAddress.wwn, (void *)sasattr->
1999*10652SHyon.Kim@Sun.COM AttachedSASAddress.wwn, sizeof (HBA_WWN)) == 0) {
2000*10652SHyon.Kim@Sun.COM /* NO expander */
2001*10652SHyon.Kim@Sun.COM (void) memset((void *)expander.wwn, 0,
2002*10652SHyon.Kim@Sun.COM sizeof (HBA_WWN));
2003*10652SHyon.Kim@Sun.COM expanderValid = 1;
2004*10652SHyon.Kim@Sun.COM } else {
2005*10652SHyon.Kim@Sun.COM if (wwnConversion(sasattr->AttachedSASAddress.wwn)
2006*10652SHyon.Kim@Sun.COM != 0) {
2007*10652SHyon.Kim@Sun.COM /* expander exist. We should verify it. */
2008*10652SHyon.Kim@Sun.COM (void) memcpy((void *)expander.wwn,
2009*10652SHyon.Kim@Sun.COM (void *)sasattr->AttachedSASAddress.wwn,
2010*10652SHyon.Kim@Sun.COM sizeof (HBA_WWN));
2011*10652SHyon.Kim@Sun.COM
2012*10652SHyon.Kim@Sun.COM (void *) memset(&tgtattr, 0, sizeof (tgtattr));
2013*10652SHyon.Kim@Sun.COM (void *) memset(&tgtsasport, 0,
2014*10652SHyon.Kim@Sun.COM sizeof (tgtsasport));
2015*10652SHyon.Kim@Sun.COM tgtattr.PortSpecificAttribute.SASPort
2016*10652SHyon.Kim@Sun.COM = &tgtsasport;
2017*10652SHyon.Kim@Sun.COM status = SMHBA_GetPortAttributesByWWN(handle,
2018*10652SHyon.Kim@Sun.COM sasattr->AttachedSASAddress, domainPortWWN,
2019*10652SHyon.Kim@Sun.COM &tgtattr);
2020*10652SHyon.Kim@Sun.COM if (status == HBA_STATUS_OK && tgtattr.PortType
2021*10652SHyon.Kim@Sun.COM == HBA_PORTTYPE_SASEXPANDER) {
2022*10652SHyon.Kim@Sun.COM expanderValid = 1;
2023*10652SHyon.Kim@Sun.COM }
2024*10652SHyon.Kim@Sun.COM }
2025*10652SHyon.Kim@Sun.COM }
2026*10652SHyon.Kim@Sun.COM
2027*10652SHyon.Kim@Sun.COM for (TPConfig = discoveredTP->configEntry,
2028*10652SHyon.Kim@Sun.COM foundConfig = B_FALSE; TPConfig != NULL;
2029*10652SHyon.Kim@Sun.COM TPConfig = TPConfig->next) {
2030*10652SHyon.Kim@Sun.COM if ((strcmp(TPConfig->hbaPortName,
2031*10652SHyon.Kim@Sun.COM port->OSDeviceName) == 0) &&
2032*10652SHyon.Kim@Sun.COM (memcmp((void *)expander.wwn, (void *)TPConfig->
2033*10652SHyon.Kim@Sun.COM expanderSASAddr.wwn,
2034*10652SHyon.Kim@Sun.COM sizeof (HBA_WWN)) == 0)) {
2035*10652SHyon.Kim@Sun.COM foundConfig = B_TRUE;
2036*10652SHyon.Kim@Sun.COM break;
2037*10652SHyon.Kim@Sun.COM }
2038*10652SHyon.Kim@Sun.COM }
2039*10652SHyon.Kim@Sun.COM
2040*10652SHyon.Kim@Sun.COM /*
2041*10652SHyon.Kim@Sun.COM * If we get here, it means that it is a new hba port/exapnder
2042*10652SHyon.Kim@Sun.COM * sas address for this discovered target port.
2043*10652SHyon.Kim@Sun.COM */
2044*10652SHyon.Kim@Sun.COM if (foundConfig == B_FALSE) {
2045*10652SHyon.Kim@Sun.COM newConfig = (targetPortConfig_t *)calloc(1,
2046*10652SHyon.Kim@Sun.COM sizeof (targetPortConfig_t));
2047*10652SHyon.Kim@Sun.COM if (newConfig == NULL) {
2048*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr,
2049*10652SHyon.Kim@Sun.COM "%s\n", strerror(errno));
2050*10652SHyon.Kim@Sun.COM return (++ret);
2051*10652SHyon.Kim@Sun.COM }
2052*10652SHyon.Kim@Sun.COM
2053*10652SHyon.Kim@Sun.COM (void) strlcpy(newConfig->hbaPortName, port->
2054*10652SHyon.Kim@Sun.COM OSDeviceName, sizeof (newConfig->hbaPortName));
2055*10652SHyon.Kim@Sun.COM (void) memcpy((void *)newConfig->expanderSASAddr.wwn,
2056*10652SHyon.Kim@Sun.COM (void *)expander.wwn, sizeof (HBA_WWN));
2057*10652SHyon.Kim@Sun.COM newConfig->expanderValid = expanderValid;
2058*10652SHyon.Kim@Sun.COM if (discoveredTP->configEntry == NULL) {
2059*10652SHyon.Kim@Sun.COM discoveredTP->configEntry = newConfig;
2060*10652SHyon.Kim@Sun.COM } else {
2061*10652SHyon.Kim@Sun.COM TPConfig = discoveredTP->configEntry;
2062*10652SHyon.Kim@Sun.COM prevConfig = TPConfig;
2063*10652SHyon.Kim@Sun.COM while (TPConfig != NULL &&
2064*10652SHyon.Kim@Sun.COM sas_name_comp(newConfig->hbaPortName,
2065*10652SHyon.Kim@Sun.COM TPConfig->hbaPortName) > 0) {
2066*10652SHyon.Kim@Sun.COM prevConfig = TPConfig;
2067*10652SHyon.Kim@Sun.COM TPConfig = TPConfig->next;
2068*10652SHyon.Kim@Sun.COM }
2069*10652SHyon.Kim@Sun.COM if (TPConfig == prevConfig) {
2070*10652SHyon.Kim@Sun.COM /* Should be inserted in the head. */
2071*10652SHyon.Kim@Sun.COM newConfig->next = TPConfig;
2072*10652SHyon.Kim@Sun.COM discoveredTP->configEntry = newConfig;
2073*10652SHyon.Kim@Sun.COM } else {
2074*10652SHyon.Kim@Sun.COM newConfig->next = TPConfig;
2075*10652SHyon.Kim@Sun.COM prevConfig->next = newConfig;
2076*10652SHyon.Kim@Sun.COM }
2077*10652SHyon.Kim@Sun.COM }
2078*10652SHyon.Kim@Sun.COM /* if scsi option is not set return */
2079*10652SHyon.Kim@Sun.COM if ((pflag & PRINT_TARGET_SCSI) == 0) {
2080*10652SHyon.Kim@Sun.COM return (0);
2081*10652SHyon.Kim@Sun.COM } else {
2082*10652SHyon.Kim@Sun.COM return (searchTargetPortMappingData(
2083*10652SHyon.Kim@Sun.COM handle, portIndex, port,
2084*10652SHyon.Kim@Sun.COM sasattr, newConfig));
2085*10652SHyon.Kim@Sun.COM }
2086*10652SHyon.Kim@Sun.COM }
2087*10652SHyon.Kim@Sun.COM } else {
2088*10652SHyon.Kim@Sun.COM /*
2089*10652SHyon.Kim@Sun.COM * Here we got a new target port which has not ever exist
2090*10652SHyon.Kim@Sun.COM * in our global target port list. So add it to the list.
2091*10652SHyon.Kim@Sun.COM * list.
2092*10652SHyon.Kim@Sun.COM */
2093*10652SHyon.Kim@Sun.COM newTP = (targetPortList_t *)calloc(1,
2094*10652SHyon.Kim@Sun.COM sizeof (targetPortList_t));
2095*10652SHyon.Kim@Sun.COM
2096*10652SHyon.Kim@Sun.COM if (newTP == NULL) {
2097*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "%s\n", strerror(errno));
2098*10652SHyon.Kim@Sun.COM return (++ret);
2099*10652SHyon.Kim@Sun.COM }
2100*10652SHyon.Kim@Sun.COM
2101*10652SHyon.Kim@Sun.COM (void) memcpy((void *)&newTP->targetattr, (void *)targetattr,
2102*10652SHyon.Kim@Sun.COM sizeof (SMHBA_PORTATTRIBUTES));
2103*10652SHyon.Kim@Sun.COM (void) memcpy((void *)&newTP->sasattr, (void *)sasattr,
2104*10652SHyon.Kim@Sun.COM sizeof (SMHBA_SAS_PORT));
2105*10652SHyon.Kim@Sun.COM
2106*10652SHyon.Kim@Sun.COM newConfig = (targetPortConfig_t *)calloc(1,
2107*10652SHyon.Kim@Sun.COM sizeof (targetPortConfig_t));
2108*10652SHyon.Kim@Sun.COM
2109*10652SHyon.Kim@Sun.COM if (newConfig == NULL) {
2110*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "%s\n", strerror(errno));
2111*10652SHyon.Kim@Sun.COM free(newTP);
2112*10652SHyon.Kim@Sun.COM return (++ret);
2113*10652SHyon.Kim@Sun.COM }
2114*10652SHyon.Kim@Sun.COM
2115*10652SHyon.Kim@Sun.COM (void) strlcpy(newConfig->hbaPortName, port->OSDeviceName,
2116*10652SHyon.Kim@Sun.COM sizeof (newConfig->hbaPortName));
2117*10652SHyon.Kim@Sun.COM if (memcmp((void *)port->PortSpecificAttribute.SASPort->
2118*10652SHyon.Kim@Sun.COM LocalSASAddress.wwn, (void *)sasattr->
2119*10652SHyon.Kim@Sun.COM AttachedSASAddress.wwn, sizeof (HBA_WWN)) == 0) {
2120*10652SHyon.Kim@Sun.COM /* NO expander */
2121*10652SHyon.Kim@Sun.COM (void) memset((void *)newConfig->expanderSASAddr.wwn,
2122*10652SHyon.Kim@Sun.COM 0, sizeof (HBA_WWN));
2123*10652SHyon.Kim@Sun.COM } else {
2124*10652SHyon.Kim@Sun.COM /* expander exist. We should verify it. */
2125*10652SHyon.Kim@Sun.COM (void) memcpy((void *)newConfig->expanderSASAddr.wwn,
2126*10652SHyon.Kim@Sun.COM (void *)sasattr->AttachedSASAddress.wwn,
2127*10652SHyon.Kim@Sun.COM sizeof (HBA_WWN));
2128*10652SHyon.Kim@Sun.COM
2129*10652SHyon.Kim@Sun.COM (void *) memset(&tgtattr, 0, sizeof (tgtattr));
2130*10652SHyon.Kim@Sun.COM (void *) memset(&tgtsasport, 0, sizeof (tgtsasport));
2131*10652SHyon.Kim@Sun.COM tgtattr.PortSpecificAttribute.SASPort = &tgtsasport;
2132*10652SHyon.Kim@Sun.COM status = SMHBA_GetPortAttributesByWWN(handle,
2133*10652SHyon.Kim@Sun.COM sasattr->AttachedSASAddress, domainPortWWN,
2134*10652SHyon.Kim@Sun.COM &tgtattr);
2135*10652SHyon.Kim@Sun.COM if (status == HBA_STATUS_OK && tgtattr.PortType ==
2136*10652SHyon.Kim@Sun.COM HBA_PORTTYPE_SASEXPANDER) {
2137*10652SHyon.Kim@Sun.COM expanderValid = 1;
2138*10652SHyon.Kim@Sun.COM }
2139*10652SHyon.Kim@Sun.COM newConfig->expanderValid = expanderValid;
2140*10652SHyon.Kim@Sun.COM }
2141*10652SHyon.Kim@Sun.COM
2142*10652SHyon.Kim@Sun.COM newTP->configEntry = newConfig;
2143*10652SHyon.Kim@Sun.COM
2144*10652SHyon.Kim@Sun.COM newTP->next = gTargetPortList; /* insert at head */
2145*10652SHyon.Kim@Sun.COM gTargetPortList = newTP; /* set new head */
2146*10652SHyon.Kim@Sun.COM
2147*10652SHyon.Kim@Sun.COM /* if scsi option is not set return */
2148*10652SHyon.Kim@Sun.COM if ((pflag & PRINT_TARGET_SCSI) == 0) {
2149*10652SHyon.Kim@Sun.COM return (0);
2150*10652SHyon.Kim@Sun.COM } else {
2151*10652SHyon.Kim@Sun.COM return (searchTargetPortMappingData(
2152*10652SHyon.Kim@Sun.COM handle, portIndex, port, sasattr, newConfig));
2153*10652SHyon.Kim@Sun.COM }
2154*10652SHyon.Kim@Sun.COM }
2155*10652SHyon.Kim@Sun.COM return (ret);
2156*10652SHyon.Kim@Sun.COM }
2157*10652SHyon.Kim@Sun.COM
2158*10652SHyon.Kim@Sun.COM /*
2159*10652SHyon.Kim@Sun.COM * Search the discovered LUs and construct the global LU list.
2160*10652SHyon.Kim@Sun.COM *
2161*10652SHyon.Kim@Sun.COM * Arguments:
2162*10652SHyon.Kim@Sun.COM * entryP - one of the target mapping data.
2163*10652SHyon.Kim@Sun.COM * handle - handle to hba port.
2164*10652SHyon.Kim@Sun.COM * hbaPortWWN - hba port sas address.
2165*10652SHyon.Kim@Sun.COM * domainPortWWN - domain port WWN for this sas domain.
2166*10652SHyon.Kim@Sun.COM * portName - HBA port OS Device Name.
2167*10652SHyon.Kim@Sun.COM * pflag - options the user specified.
2168*10652SHyon.Kim@Sun.COM *
2169*10652SHyon.Kim@Sun.COM * Return Value:
2170*10652SHyon.Kim@Sun.COM * 0 sucessfully processed handle
2171*10652SHyon.Kim@Sun.COM * >0 error has occured
2172*10652SHyon.Kim@Sun.COM */
2173*10652SHyon.Kim@Sun.COM static int
searchDevice(PSMHBA_SCSIENTRY entryP,HBA_HANDLE handle,HBA_WWN hbaPortWWN,HBA_WWN domainPortWWN,char * portName,int pflag)2174*10652SHyon.Kim@Sun.COM searchDevice(PSMHBA_SCSIENTRY entryP,
2175*10652SHyon.Kim@Sun.COM HBA_HANDLE handle, HBA_WWN hbaPortWWN, HBA_WWN domainPortWWN,
2176*10652SHyon.Kim@Sun.COM char *portName, int pflag)
2177*10652SHyon.Kim@Sun.COM {
2178*10652SHyon.Kim@Sun.COM HBA_STATUS status;
2179*10652SHyon.Kim@Sun.COM int ret = 0;
2180*10652SHyon.Kim@Sun.COM discoveredDevice *discoveredLU, *newDevice;
2181*10652SHyon.Kim@Sun.COM portList *portElem, *newPort, *prevElem;
2182*10652SHyon.Kim@Sun.COM tgtPortWWNList *newTgtWWN, *TgtWWNList;
2183*10652SHyon.Kim@Sun.COM boolean_t foundDevice = B_FALSE;
2184*10652SHyon.Kim@Sun.COM boolean_t foundPort = B_FALSE;
2185*10652SHyon.Kim@Sun.COM struct scsi_inquiry inq;
2186*10652SHyon.Kim@Sun.COM HBA_UINT32 responseSize, senseSize = 0;
2187*10652SHyon.Kim@Sun.COM HBA_UINT8 inq_status;
2188*10652SHyon.Kim@Sun.COM SMHBA_SCSILUN smhbaLUN;
2189*10652SHyon.Kim@Sun.COM struct scsi_extended_sense sense;
2190*10652SHyon.Kim@Sun.COM
2191*10652SHyon.Kim@Sun.COM /* if OSDeviceName is not set, we don't need to search */
2192*10652SHyon.Kim@Sun.COM if (entryP->ScsiId.OSDeviceName[0] == '\0') {
2193*10652SHyon.Kim@Sun.COM return (ret);
2194*10652SHyon.Kim@Sun.COM }
2195*10652SHyon.Kim@Sun.COM
2196*10652SHyon.Kim@Sun.COM /*
2197*10652SHyon.Kim@Sun.COM * First, we will iterate the already constructed discovered LU
2198*10652SHyon.Kim@Sun.COM * list to see whether there is a LU already exist with the same OS
2199*10652SHyon.Kim@Sun.COM * device name as current target mapping data entry.
2200*10652SHyon.Kim@Sun.COM */
2201*10652SHyon.Kim@Sun.COM for (discoveredLU = LUList; discoveredLU != NULL;
2202*10652SHyon.Kim@Sun.COM discoveredLU = discoveredLU->next) {
2203*10652SHyon.Kim@Sun.COM if (strcmp(entryP->ScsiId.OSDeviceName,
2204*10652SHyon.Kim@Sun.COM discoveredLU->OSDeviceName) == 0) {
2205*10652SHyon.Kim@Sun.COM /*
2206*10652SHyon.Kim@Sun.COM * if there is existing OS Device Name and
2207*10652SHyon.Kim@Sun.COM * verbose is not set, just return
2208*10652SHyon.Kim@Sun.COM */
2209*10652SHyon.Kim@Sun.COM if ((pflag & PRINT_VERBOSE) == 0) {
2210*10652SHyon.Kim@Sun.COM return (ret);
2211*10652SHyon.Kim@Sun.COM }
2212*10652SHyon.Kim@Sun.COM foundDevice = B_TRUE;
2213*10652SHyon.Kim@Sun.COM break;
2214*10652SHyon.Kim@Sun.COM }
2215*10652SHyon.Kim@Sun.COM }
2216*10652SHyon.Kim@Sun.COM
2217*10652SHyon.Kim@Sun.COM if (foundDevice == B_TRUE) {
2218*10652SHyon.Kim@Sun.COM /*
2219*10652SHyon.Kim@Sun.COM * If there is a discovered LU already exist, we should
2220*10652SHyon.Kim@Sun.COM * add more information on this LU to construct the whole
2221*10652SHyon.Kim@Sun.COM * topology.
2222*10652SHyon.Kim@Sun.COM * Here we will check whether the current hba port has
2223*10652SHyon.Kim@Sun.COM * already been added.
2224*10652SHyon.Kim@Sun.COM */
2225*10652SHyon.Kim@Sun.COM for (portElem = discoveredLU->HBAPortList,
2226*10652SHyon.Kim@Sun.COM foundPort = B_FALSE; portElem != NULL;
2227*10652SHyon.Kim@Sun.COM portElem = portElem->next) {
2228*10652SHyon.Kim@Sun.COM if (strcmp(portElem->portName,
2229*10652SHyon.Kim@Sun.COM portName) == 0) {
2230*10652SHyon.Kim@Sun.COM foundPort = B_TRUE;
2231*10652SHyon.Kim@Sun.COM break;
2232*10652SHyon.Kim@Sun.COM }
2233*10652SHyon.Kim@Sun.COM }
2234*10652SHyon.Kim@Sun.COM
2235*10652SHyon.Kim@Sun.COM /*
2236*10652SHyon.Kim@Sun.COM * If we get here, it means that it is a new hba port name
2237*10652SHyon.Kim@Sun.COM * for this discovered LU.
2238*10652SHyon.Kim@Sun.COM */
2239*10652SHyon.Kim@Sun.COM if (foundPort == B_FALSE) {
2240*10652SHyon.Kim@Sun.COM newPort = (portList *)calloc(1, sizeof (portList));
2241*10652SHyon.Kim@Sun.COM if (newPort == NULL) {
2242*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr,
2243*10652SHyon.Kim@Sun.COM "%s\n", strerror(errno));
2244*10652SHyon.Kim@Sun.COM return (++ret);
2245*10652SHyon.Kim@Sun.COM }
2246*10652SHyon.Kim@Sun.COM (void) strlcpy(newPort->portName, portName,
2247*10652SHyon.Kim@Sun.COM sizeof (newPort->portName));
2248*10652SHyon.Kim@Sun.COM
2249*10652SHyon.Kim@Sun.COM portElem = discoveredLU->HBAPortList;
2250*10652SHyon.Kim@Sun.COM prevElem = portElem;
2251*10652SHyon.Kim@Sun.COM while (portElem != NULL &&
2252*10652SHyon.Kim@Sun.COM sas_name_comp(newPort->portName, portElem->portName)
2253*10652SHyon.Kim@Sun.COM > 0) {
2254*10652SHyon.Kim@Sun.COM prevElem = portElem;
2255*10652SHyon.Kim@Sun.COM portElem = portElem->next;
2256*10652SHyon.Kim@Sun.COM }
2257*10652SHyon.Kim@Sun.COM if (portElem == prevElem) {
2258*10652SHyon.Kim@Sun.COM /* Insert in the head of list. */
2259*10652SHyon.Kim@Sun.COM newPort->next = portElem;
2260*10652SHyon.Kim@Sun.COM discoveredLU->HBAPortList = newPort;
2261*10652SHyon.Kim@Sun.COM } else {
2262*10652SHyon.Kim@Sun.COM newPort->next = portElem;
2263*10652SHyon.Kim@Sun.COM prevElem->next = newPort;
2264*10652SHyon.Kim@Sun.COM }
2265*10652SHyon.Kim@Sun.COM /* add Target Port */
2266*10652SHyon.Kim@Sun.COM newPort->tgtPortWWN = (tgtPortWWNList *)calloc(1,
2267*10652SHyon.Kim@Sun.COM sizeof (tgtPortWWNList));
2268*10652SHyon.Kim@Sun.COM if (newPort->tgtPortWWN == NULL) {
2269*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr,
2270*10652SHyon.Kim@Sun.COM "%s\n", strerror(errno));
2271*10652SHyon.Kim@Sun.COM return (++ret);
2272*10652SHyon.Kim@Sun.COM }
2273*10652SHyon.Kim@Sun.COM (void *) memcpy((void *)&(newPort->tgtPortWWN->portWWN),
2274*10652SHyon.Kim@Sun.COM (void *)&(entryP->PortLun.PortWWN),
2275*10652SHyon.Kim@Sun.COM sizeof (HBA_WWN));
2276*10652SHyon.Kim@Sun.COM /* Set LUN data */
2277*10652SHyon.Kim@Sun.COM newPort->tgtPortWWN->scsiOSLun =
2278*10652SHyon.Kim@Sun.COM entryP->ScsiId.ScsiOSLun;
2279*10652SHyon.Kim@Sun.COM } else {
2280*10652SHyon.Kim@Sun.COM /*
2281*10652SHyon.Kim@Sun.COM * Otherwise, we just need to add the target port
2282*10652SHyon.Kim@Sun.COM * sas address information.
2283*10652SHyon.Kim@Sun.COM */
2284*10652SHyon.Kim@Sun.COM for (TgtWWNList = portElem->tgtPortWWN;
2285*10652SHyon.Kim@Sun.COM TgtWWNList != NULL;
2286*10652SHyon.Kim@Sun.COM TgtWWNList = TgtWWNList->next) {
2287*10652SHyon.Kim@Sun.COM if (memcmp(&TgtWWNList->portWWN,
2288*10652SHyon.Kim@Sun.COM &entryP->PortLun.PortWWN,
2289*10652SHyon.Kim@Sun.COM sizeof (HBA_WWN)) == 0)
2290*10652SHyon.Kim@Sun.COM return (0);
2291*10652SHyon.Kim@Sun.COM }
2292*10652SHyon.Kim@Sun.COM /* add it to existing */
2293*10652SHyon.Kim@Sun.COM newTgtWWN = (tgtPortWWNList *)calloc(1,
2294*10652SHyon.Kim@Sun.COM sizeof (tgtPortWWNList));
2295*10652SHyon.Kim@Sun.COM if (newTgtWWN == NULL) {
2296*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr,
2297*10652SHyon.Kim@Sun.COM "%s\n", strerror(errno));
2298*10652SHyon.Kim@Sun.COM return (++ret);
2299*10652SHyon.Kim@Sun.COM }
2300*10652SHyon.Kim@Sun.COM /* insert at head */
2301*10652SHyon.Kim@Sun.COM newTgtWWN->next = portElem->tgtPortWWN;
2302*10652SHyon.Kim@Sun.COM portElem->tgtPortWWN = newTgtWWN;
2303*10652SHyon.Kim@Sun.COM (void *) memcpy((void *)&(newTgtWWN->portWWN),
2304*10652SHyon.Kim@Sun.COM (void *)&(entryP->PortLun.PortWWN),
2305*10652SHyon.Kim@Sun.COM sizeof (HBA_WWN));
2306*10652SHyon.Kim@Sun.COM /* Set LUN data */
2307*10652SHyon.Kim@Sun.COM newTgtWWN->scsiOSLun =
2308*10652SHyon.Kim@Sun.COM entryP->ScsiId.ScsiOSLun;
2309*10652SHyon.Kim@Sun.COM }
2310*10652SHyon.Kim@Sun.COM } else {
2311*10652SHyon.Kim@Sun.COM /*
2312*10652SHyon.Kim@Sun.COM * Here we got a new discovered LU which has not ever exist
2313*10652SHyon.Kim@Sun.COM * in our global LU list. So add it into our global LU
2314*10652SHyon.Kim@Sun.COM * list.
2315*10652SHyon.Kim@Sun.COM */
2316*10652SHyon.Kim@Sun.COM newDevice = (discoveredDevice *)calloc(1,
2317*10652SHyon.Kim@Sun.COM sizeof (discoveredDevice));
2318*10652SHyon.Kim@Sun.COM
2319*10652SHyon.Kim@Sun.COM if (newDevice == NULL) {
2320*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "%s\n", strerror(errno));
2321*10652SHyon.Kim@Sun.COM return (++ret);
2322*10652SHyon.Kim@Sun.COM }
2323*10652SHyon.Kim@Sun.COM newDevice->next = LUList; /* insert at head */
2324*10652SHyon.Kim@Sun.COM LUList = newDevice; /* set new head */
2325*10652SHyon.Kim@Sun.COM
2326*10652SHyon.Kim@Sun.COM /* copy device name */
2327*10652SHyon.Kim@Sun.COM (void *) strlcpy(newDevice->OSDeviceName,
2328*10652SHyon.Kim@Sun.COM entryP->ScsiId.OSDeviceName,
2329*10652SHyon.Kim@Sun.COM sizeof (newDevice->OSDeviceName));
2330*10652SHyon.Kim@Sun.COM
2331*10652SHyon.Kim@Sun.COM /* if verbose is not set return */
2332*10652SHyon.Kim@Sun.COM if ((pflag & PRINT_VERBOSE) == 0) {
2333*10652SHyon.Kim@Sun.COM return (0);
2334*10652SHyon.Kim@Sun.COM }
2335*10652SHyon.Kim@Sun.COM
2336*10652SHyon.Kim@Sun.COM /* copy WWN data */
2337*10652SHyon.Kim@Sun.COM newDevice->HBAPortList = (portList *)calloc(1,
2338*10652SHyon.Kim@Sun.COM sizeof (portList));
2339*10652SHyon.Kim@Sun.COM if (newDevice->HBAPortList == NULL) {
2340*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "%s\n", strerror(errno));
2341*10652SHyon.Kim@Sun.COM return (++ret);
2342*10652SHyon.Kim@Sun.COM }
2343*10652SHyon.Kim@Sun.COM (void) strlcpy(newDevice->HBAPortList->portName,
2344*10652SHyon.Kim@Sun.COM portName, sizeof (newDevice->HBAPortList->portName));
2345*10652SHyon.Kim@Sun.COM
2346*10652SHyon.Kim@Sun.COM newDevice->HBAPortList->tgtPortWWN =
2347*10652SHyon.Kim@Sun.COM (tgtPortWWNList *)calloc(1, sizeof (tgtPortWWNList));
2348*10652SHyon.Kim@Sun.COM if (newDevice->HBAPortList->tgtPortWWN == NULL) {
2349*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "%s\n", strerror(errno));
2350*10652SHyon.Kim@Sun.COM return (++ret);
2351*10652SHyon.Kim@Sun.COM }
2352*10652SHyon.Kim@Sun.COM
2353*10652SHyon.Kim@Sun.COM (void *) memcpy((void *)&(newDevice->HBAPortList->\
2354*10652SHyon.Kim@Sun.COM tgtPortWWN->portWWN),
2355*10652SHyon.Kim@Sun.COM (void *)&(entryP->PortLun.PortWWN),
2356*10652SHyon.Kim@Sun.COM sizeof (HBA_WWN));
2357*10652SHyon.Kim@Sun.COM newDevice->HBAPortList->tgtPortWWN->scsiOSLun =
2358*10652SHyon.Kim@Sun.COM entryP->ScsiId.ScsiOSLun;
2359*10652SHyon.Kim@Sun.COM
2360*10652SHyon.Kim@Sun.COM responseSize = sizeof (struct scsi_inquiry);
2361*10652SHyon.Kim@Sun.COM senseSize = sizeof (struct scsi_extended_sense);
2362*10652SHyon.Kim@Sun.COM (void *) memset(&inq, 0, sizeof (struct scsi_inquiry));
2363*10652SHyon.Kim@Sun.COM (void *) memset(&sense, 0, sizeof (sense));
2364*10652SHyon.Kim@Sun.COM (void *) memcpy(&smhbaLUN, &entryP->PortLun.TargetLun,
2365*10652SHyon.Kim@Sun.COM sizeof (smhbaLUN));
2366*10652SHyon.Kim@Sun.COM
2367*10652SHyon.Kim@Sun.COM /*
2368*10652SHyon.Kim@Sun.COM * Retrieve the VPD data for the newly found discovered LU.
2369*10652SHyon.Kim@Sun.COM */
2370*10652SHyon.Kim@Sun.COM status = SMHBA_ScsiInquiry(
2371*10652SHyon.Kim@Sun.COM handle,
2372*10652SHyon.Kim@Sun.COM hbaPortWWN,
2373*10652SHyon.Kim@Sun.COM entryP->PortLun.PortWWN,
2374*10652SHyon.Kim@Sun.COM domainPortWWN,
2375*10652SHyon.Kim@Sun.COM smhbaLUN,
2376*10652SHyon.Kim@Sun.COM 0,
2377*10652SHyon.Kim@Sun.COM 0,
2378*10652SHyon.Kim@Sun.COM (void *) &inq, &responseSize,
2379*10652SHyon.Kim@Sun.COM &inq_status,
2380*10652SHyon.Kim@Sun.COM (void *) &sense, &senseSize);
2381*10652SHyon.Kim@Sun.COM
2382*10652SHyon.Kim@Sun.COM if (status != HBA_STATUS_OK) {
2383*10652SHyon.Kim@Sun.COM /* init VID/PID/dType as '\0' */
2384*10652SHyon.Kim@Sun.COM newDevice->VID[0] = '\0';
2385*10652SHyon.Kim@Sun.COM newDevice->PID[0] = '\0';
2386*10652SHyon.Kim@Sun.COM newDevice->dType = DTYPE_UNKNOWN;
2387*10652SHyon.Kim@Sun.COM /* initialize inq status */
2388*10652SHyon.Kim@Sun.COM newDevice->inquiryFailed = B_TRUE;
2389*10652SHyon.Kim@Sun.COM ret++;
2390*10652SHyon.Kim@Sun.COM } else {
2391*10652SHyon.Kim@Sun.COM (void *) memcpy(newDevice->VID, inq.inq_vid,
2392*10652SHyon.Kim@Sun.COM sizeof (newDevice->VID));
2393*10652SHyon.Kim@Sun.COM (void *) memcpy(newDevice->PID, inq.inq_pid,
2394*10652SHyon.Kim@Sun.COM sizeof (newDevice->PID));
2395*10652SHyon.Kim@Sun.COM newDevice->dType = inq.inq_dtype;
2396*10652SHyon.Kim@Sun.COM /* initialize inq status */
2397*10652SHyon.Kim@Sun.COM newDevice->inquiryFailed = B_FALSE;
2398*10652SHyon.Kim@Sun.COM }
2399*10652SHyon.Kim@Sun.COM }
2400*10652SHyon.Kim@Sun.COM return (ret);
2401*10652SHyon.Kim@Sun.COM }
2402*10652SHyon.Kim@Sun.COM
2403*10652SHyon.Kim@Sun.COM /*
2404*10652SHyon.Kim@Sun.COM * Function we use to insert a newly discovered port.
2405*10652SHyon.Kim@Sun.COM * Return:
2406*10652SHyon.Kim@Sun.COM * 0 - success
2407*10652SHyon.Kim@Sun.COM * >0 - failed
2408*10652SHyon.Kim@Sun.COM */
2409*10652SHyon.Kim@Sun.COM static int
sas_rp_tree_insert(rp_tree_t ** rproot,rp_tree_t * rpnode)2410*10652SHyon.Kim@Sun.COM sas_rp_tree_insert(rp_tree_t **rproot,
2411*10652SHyon.Kim@Sun.COM rp_tree_t *rpnode)
2412*10652SHyon.Kim@Sun.COM {
2413*10652SHyon.Kim@Sun.COM HBA_UINT8 *wwn1, *wwn2, *wwn3;
2414*10652SHyon.Kim@Sun.COM rp_tree_t *node_ptr;
2415*10652SHyon.Kim@Sun.COM int ret = 0;
2416*10652SHyon.Kim@Sun.COM
2417*10652SHyon.Kim@Sun.COM if (rproot == NULL) {
2418*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "%s\n",
2419*10652SHyon.Kim@Sun.COM gettext("Error: NULL rproot"));
2420*10652SHyon.Kim@Sun.COM return (1);
2421*10652SHyon.Kim@Sun.COM }
2422*10652SHyon.Kim@Sun.COM
2423*10652SHyon.Kim@Sun.COM if (rpnode == NULL) {
2424*10652SHyon.Kim@Sun.COM (void *) fprintf(stderr, "%s\n",
2425*10652SHyon.Kim@Sun.COM gettext("Error: NULL rpnode"));
2426*10652SHyon.Kim@Sun.COM return (1);
2427*10652SHyon.Kim@Sun.COM }
2428*10652SHyon.Kim@Sun.COM
2429*10652SHyon.Kim@Sun.COM if (*rproot == NULL) {
2430*10652SHyon.Kim@Sun.COM *rproot = rpnode;
2431*10652SHyon.Kim@Sun.COM return (0);
2432*10652SHyon.Kim@Sun.COM }
2433*10652SHyon.Kim@Sun.COM
2434*10652SHyon.Kim@Sun.COM wwn1 = (*rproot)->sasattr.LocalSASAddress.wwn;
2435*10652SHyon.Kim@Sun.COM wwn2 = (*rproot)->sasattr.AttachedSASAddress.wwn;
2436*10652SHyon.Kim@Sun.COM wwn3 = rpnode->sasattr.AttachedSASAddress.wwn;
2437*10652SHyon.Kim@Sun.COM
2438*10652SHyon.Kim@Sun.COM /*
2439*10652SHyon.Kim@Sun.COM * If the attched sas address is equal to the local sas address,
2440*10652SHyon.Kim@Sun.COM * then this should be a child node of current root node.
2441*10652SHyon.Kim@Sun.COM */
2442*10652SHyon.Kim@Sun.COM if (memcmp(wwn1, wwn3, sizeof (HBA_WWN)) == 0) {
2443*10652SHyon.Kim@Sun.COM (void) sas_rp_tree_insert(&(*rproot)->child, rpnode);
2444*10652SHyon.Kim@Sun.COM rpnode->parent = *rproot;
2445*10652SHyon.Kim@Sun.COM } else if (memcmp(wwn2, wwn3, sizeof (HBA_WWN)) == 0) {
2446*10652SHyon.Kim@Sun.COM /*
2447*10652SHyon.Kim@Sun.COM * If the attached sas address is equal to the attached sas
2448*10652SHyon.Kim@Sun.COM * address of current root node, then this should be a
2449*10652SHyon.Kim@Sun.COM * sibling node.
2450*10652SHyon.Kim@Sun.COM * Insert the SAS/SATA Device at the head of sibling list.
2451*10652SHyon.Kim@Sun.COM */
2452*10652SHyon.Kim@Sun.COM if (rpnode->portattr.PortType != HBA_PORTTYPE_SASEXPANDER) {
2453*10652SHyon.Kim@Sun.COM rpnode->sibling = *rproot;
2454*10652SHyon.Kim@Sun.COM *rproot = rpnode;
2455*10652SHyon.Kim@Sun.COM } else {
2456*10652SHyon.Kim@Sun.COM /*
2457*10652SHyon.Kim@Sun.COM * Insert the SAS Expander at the tail of sibling
2458*10652SHyon.Kim@Sun.COM * list.
2459*10652SHyon.Kim@Sun.COM */
2460*10652SHyon.Kim@Sun.COM node_ptr = *rproot;
2461*10652SHyon.Kim@Sun.COM while (node_ptr->sibling != NULL)
2462*10652SHyon.Kim@Sun.COM node_ptr = node_ptr->sibling;
2463*10652SHyon.Kim@Sun.COM node_ptr->sibling = rpnode;
2464*10652SHyon.Kim@Sun.COM }
2465*10652SHyon.Kim@Sun.COM rpnode->parent = (*rproot)->parent;
2466*10652SHyon.Kim@Sun.COM } else {
2467*10652SHyon.Kim@Sun.COM /*
2468*10652SHyon.Kim@Sun.COM * If enter here, we should first try to insert the discovered
2469*10652SHyon.Kim@Sun.COM * port node into the child sub-tree, then try to insert to the
2470*10652SHyon.Kim@Sun.COM * sibling sub-trees. If we failed to insert the discovered
2471*10652SHyon.Kim@Sun.COM * port node, return 1. The caller will queue this node
2472*10652SHyon.Kim@Sun.COM * up and retry insertion later.
2473*10652SHyon.Kim@Sun.COM */
2474*10652SHyon.Kim@Sun.COM if ((*rproot)->child) {
2475*10652SHyon.Kim@Sun.COM ret = sas_rp_tree_insert(&(*rproot)->child, rpnode);
2476*10652SHyon.Kim@Sun.COM }
2477*10652SHyon.Kim@Sun.COM if ((*rproot)->child == NULL || ret != 0) {
2478*10652SHyon.Kim@Sun.COM if ((*rproot)->sibling) {
2479*10652SHyon.Kim@Sun.COM ret = sas_rp_tree_insert(&(*rproot)->sibling,
2480*10652SHyon.Kim@Sun.COM rpnode);
2481*10652SHyon.Kim@Sun.COM } else
2482*10652SHyon.Kim@Sun.COM ret = 1;
2483*10652SHyon.Kim@Sun.COM }
2484*10652SHyon.Kim@Sun.COM return (ret);
2485*10652SHyon.Kim@Sun.COM }
2486*10652SHyon.Kim@Sun.COM return (0);
2487*10652SHyon.Kim@Sun.COM }
2488*10652SHyon.Kim@Sun.COM
2489*10652SHyon.Kim@Sun.COM /*
2490*10652SHyon.Kim@Sun.COM * Function which will print out the whole disocvered port topology.
2491*10652SHyon.Kim@Sun.COM * Here we use the Preorder Traversal algorithm.
2492*10652SHyon.Kim@Sun.COM * The indentation rules are:
2493*10652SHyon.Kim@Sun.COM * 1 * TABLEN - for attributes
2494*10652SHyon.Kim@Sun.COM * 2 * TABLEN - for next tier target port/expander
2495*10652SHyon.Kim@Sun.COM */
2496*10652SHyon.Kim@Sun.COM static int
sas_rp_tree_print(HBA_HANDLE handle,char * adapterName,HBA_UINT32 portIndex,SMHBA_PORTATTRIBUTES * port,rp_tree_t * rpnode,inputArg_t * input,int gident,int * printPort)2497*10652SHyon.Kim@Sun.COM sas_rp_tree_print(HBA_HANDLE handle, char *adapterName,
2498*10652SHyon.Kim@Sun.COM HBA_UINT32 portIndex, SMHBA_PORTATTRIBUTES *port,
2499*10652SHyon.Kim@Sun.COM rp_tree_t *rpnode, inputArg_t *input,
2500*10652SHyon.Kim@Sun.COM int gident, int *printPort)
2501*10652SHyon.Kim@Sun.COM {
2502*10652SHyon.Kim@Sun.COM int ret = 0, lident;
2503*10652SHyon.Kim@Sun.COM
2504*10652SHyon.Kim@Sun.COM if (rpnode == NULL)
2505*10652SHyon.Kim@Sun.COM return (ret);
2506*10652SHyon.Kim@Sun.COM lident = gident;
2507*10652SHyon.Kim@Sun.COM
2508*10652SHyon.Kim@Sun.COM /*
2509*10652SHyon.Kim@Sun.COM * We assume that all the nodes are disocvered ports(sas device or
2510*10652SHyon.Kim@Sun.COM * expander).
2511*10652SHyon.Kim@Sun.COM */
2512*10652SHyon.Kim@Sun.COM if (input->wwnCount > 0) {
2513*10652SHyon.Kim@Sun.COM /* Adjust local indentation if a discovered port specified. */
2514*10652SHyon.Kim@Sun.COM lident = 2 * TABLEN;
2515*10652SHyon.Kim@Sun.COM /*
2516*10652SHyon.Kim@Sun.COM * Check whether current node match one of the specified
2517*10652SHyon.Kim@Sun.COM * SAS addresses.
2518*10652SHyon.Kim@Sun.COM */
2519*10652SHyon.Kim@Sun.COM if ((rpnode->portattr.PortType != HBA_PORTTYPE_SASEXPANDER) ||
2520*10652SHyon.Kim@Sun.COM !isPortWWNInArgv(input,
2521*10652SHyon.Kim@Sun.COM &rpnode->sasattr.LocalSASAddress)) {
2522*10652SHyon.Kim@Sun.COM /*
2523*10652SHyon.Kim@Sun.COM * Step down to child tree first.
2524*10652SHyon.Kim@Sun.COM */
2525*10652SHyon.Kim@Sun.COM ret += sas_rp_tree_print(handle, adapterName,
2526*10652SHyon.Kim@Sun.COM portIndex, port, rpnode->child, input,
2527*10652SHyon.Kim@Sun.COM gident + 2 * TABLEN, printPort);
2528*10652SHyon.Kim@Sun.COM /*
2529*10652SHyon.Kim@Sun.COM * Then check the sibling tree.
2530*10652SHyon.Kim@Sun.COM */
2531*10652SHyon.Kim@Sun.COM ret += sas_rp_tree_print(handle, adapterName,
2532*10652SHyon.Kim@Sun.COM portIndex, port, rpnode->sibling, input,
2533*10652SHyon.Kim@Sun.COM gident, printPort);
2534*10652SHyon.Kim@Sun.COM return (ret);
2535*10652SHyon.Kim@Sun.COM }
2536*10652SHyon.Kim@Sun.COM }
2537*10652SHyon.Kim@Sun.COM
2538*10652SHyon.Kim@Sun.COM if ((rpnode->portattr.PortType == HBA_PORTTYPE_SASEXPANDER) ||
2539*10652SHyon.Kim@Sun.COM (input->pflag & PRINT_TARGET_PORT)) {
2540*10652SHyon.Kim@Sun.COM /*
2541*10652SHyon.Kim@Sun.COM * We should print the header(HBA Name + HBA Port Name)
2542*10652SHyon.Kim@Sun.COM * on-demand. It means that, if we have expander device
2543*10652SHyon.Kim@Sun.COM * address specified on the command line, we should print
2544*10652SHyon.Kim@Sun.COM * the header once we find a matching one. Or we will
2545*10652SHyon.Kim@Sun.COM * print the header from the beginning of the output.
2546*10652SHyon.Kim@Sun.COM */
2547*10652SHyon.Kim@Sun.COM if (g_printHBA == 0) {
2548*10652SHyon.Kim@Sun.COM (void *) fprintf(stdout, "%s %s\n",
2549*10652SHyon.Kim@Sun.COM "HBA Name:", adapterName);
2550*10652SHyon.Kim@Sun.COM g_printHBA = 1;
2551*10652SHyon.Kim@Sun.COM }
2552*10652SHyon.Kim@Sun.COM
2553*10652SHyon.Kim@Sun.COM if (*printPort == 0) {
2554*10652SHyon.Kim@Sun.COM (void *) fprintf(stdout, "%s%s %s\n",
2555*10652SHyon.Kim@Sun.COM getIndentSpaces(TABLEN),
2556*10652SHyon.Kim@Sun.COM "HBA Port Name:", port->OSDeviceName);
2557*10652SHyon.Kim@Sun.COM *printPort = 1;
2558*10652SHyon.Kim@Sun.COM }
2559*10652SHyon.Kim@Sun.COM ret += sas_print_rpnode(input, rpnode, lident, gident);
2560*10652SHyon.Kim@Sun.COM }
2561*10652SHyon.Kim@Sun.COM
2562*10652SHyon.Kim@Sun.COM /*
2563*10652SHyon.Kim@Sun.COM * If operands provided with "-t" option specified, we will print
2564*10652SHyon.Kim@Sun.COM * the immediate child nodes information under the expander.
2565*10652SHyon.Kim@Sun.COM */
2566*10652SHyon.Kim@Sun.COM if (input->pflag & PRINT_TARGET_PORT) {
2567*10652SHyon.Kim@Sun.COM /* no operand. ignore the option. */
2568*10652SHyon.Kim@Sun.COM if (input->wwnCount > 0) {
2569*10652SHyon.Kim@Sun.COM if (rpnode->portattr.PortType ==
2570*10652SHyon.Kim@Sun.COM HBA_PORTTYPE_SASEXPANDER) {
2571*10652SHyon.Kim@Sun.COM ret += sas_rp_tree_print_desc(handle,
2572*10652SHyon.Kim@Sun.COM portIndex, port, rpnode->child,
2573*10652SHyon.Kim@Sun.COM input,
2574*10652SHyon.Kim@Sun.COM lident + 2 * TABLEN,
2575*10652SHyon.Kim@Sun.COM gident + 2 * TABLEN);
2576*10652SHyon.Kim@Sun.COM }
2577*10652SHyon.Kim@Sun.COM }
2578*10652SHyon.Kim@Sun.COM }
2579*10652SHyon.Kim@Sun.COM
2580*10652SHyon.Kim@Sun.COM /*
2581*10652SHyon.Kim@Sun.COM * Here we use DFS(Depth First Search) algorithm to traverse the
2582*10652SHyon.Kim@Sun.COM * whole tree.
2583*10652SHyon.Kim@Sun.COM */
2584*10652SHyon.Kim@Sun.COM ret += sas_rp_tree_print(handle, adapterName,
2585*10652SHyon.Kim@Sun.COM portIndex, port, rpnode->child, input,
2586*10652SHyon.Kim@Sun.COM gident + 2 * TABLEN, printPort);
2587*10652SHyon.Kim@Sun.COM ret += sas_rp_tree_print(handle, adapterName,
2588*10652SHyon.Kim@Sun.COM portIndex, port, rpnode->sibling, input,
2589*10652SHyon.Kim@Sun.COM gident, printPort);
2590*10652SHyon.Kim@Sun.COM return (ret);
2591*10652SHyon.Kim@Sun.COM }
2592*10652SHyon.Kim@Sun.COM
2593*10652SHyon.Kim@Sun.COM /*
2594*10652SHyon.Kim@Sun.COM * Function which will destroy the whole discovered port tree.
2595*10652SHyon.Kim@Sun.COM * Here we use the Postorder Traversal algorithm.
2596*10652SHyon.Kim@Sun.COM */
sas_rp_tree_free(rp_tree_t * rproot)2597*10652SHyon.Kim@Sun.COM static void sas_rp_tree_free(rp_tree_t *rproot)
2598*10652SHyon.Kim@Sun.COM {
2599*10652SHyon.Kim@Sun.COM tgt_mapping *cur, *next;
2600*10652SHyon.Kim@Sun.COM
2601*10652SHyon.Kim@Sun.COM if (rproot == NULL)
2602*10652SHyon.Kim@Sun.COM return;
2603*10652SHyon.Kim@Sun.COM
2604*10652SHyon.Kim@Sun.COM /*
2605*10652SHyon.Kim@Sun.COM * Free child tree first.
2606*10652SHyon.Kim@Sun.COM */
2607*10652SHyon.Kim@Sun.COM if (rproot->child) {
2608*10652SHyon.Kim@Sun.COM sas_rp_tree_free(rproot->child);
2609*10652SHyon.Kim@Sun.COM }
2610*10652SHyon.Kim@Sun.COM
2611*10652SHyon.Kim@Sun.COM /*
2612*10652SHyon.Kim@Sun.COM * Free sibling trees then.
2613*10652SHyon.Kim@Sun.COM */
2614*10652SHyon.Kim@Sun.COM if (rproot->sibling) {
2615*10652SHyon.Kim@Sun.COM sas_rp_tree_free(rproot->sibling);
2616*10652SHyon.Kim@Sun.COM }
2617*10652SHyon.Kim@Sun.COM
2618*10652SHyon.Kim@Sun.COM /*
2619*10652SHyon.Kim@Sun.COM * Free root node at last.
2620*10652SHyon.Kim@Sun.COM */
2621*10652SHyon.Kim@Sun.COM cur = rproot->first_entry;
2622*10652SHyon.Kim@Sun.COM while (cur != NULL) {
2623*10652SHyon.Kim@Sun.COM next = cur->next;
2624*10652SHyon.Kim@Sun.COM free(cur);
2625*10652SHyon.Kim@Sun.COM cur = next;
2626*10652SHyon.Kim@Sun.COM }
2627*10652SHyon.Kim@Sun.COM free(rproot);
2628*10652SHyon.Kim@Sun.COM }
2629*10652SHyon.Kim@Sun.COM
2630*10652SHyon.Kim@Sun.COM /*
2631*10652SHyon.Kim@Sun.COM * Function used to print out all the descendant nodes.
2632*10652SHyon.Kim@Sun.COM * handle - handle to HBA.
2633*10652SHyon.Kim@Sun.COM * port - port attributes of current HBA port.
2634*10652SHyon.Kim@Sun.COM * desc - the root node of a subtree which will be processed.
2635*10652SHyon.Kim@Sun.COM * input - input argument.
2636*10652SHyon.Kim@Sun.COM * lident - local indentation for shifting indentation.
2637*10652SHyon.Kim@Sun.COM * gident - global indentation, can also be used to obtain Tier number.
2638*10652SHyon.Kim@Sun.COM */
2639*10652SHyon.Kim@Sun.COM /*ARGSUSED*/
2640*10652SHyon.Kim@Sun.COM static int
sas_rp_tree_print_desc(HBA_HANDLE handle,HBA_UINT32 portIndex,SMHBA_PORTATTRIBUTES * port,rp_tree_t * desc,inputArg_t * input,int lident,int gident)2641*10652SHyon.Kim@Sun.COM sas_rp_tree_print_desc(HBA_HANDLE handle, HBA_UINT32 portIndex,
2642*10652SHyon.Kim@Sun.COM SMHBA_PORTATTRIBUTES *port, rp_tree_t *desc,
2643*10652SHyon.Kim@Sun.COM inputArg_t *input, int lident, int gident)
2644*10652SHyon.Kim@Sun.COM {
2645*10652SHyon.Kim@Sun.COM int ret = 0;
2646*10652SHyon.Kim@Sun.COM rp_tree_t *rp_node;
2647*10652SHyon.Kim@Sun.COM
2648*10652SHyon.Kim@Sun.COM if (desc == NULL)
2649*10652SHyon.Kim@Sun.COM return (ret);
2650*10652SHyon.Kim@Sun.COM /*
2651*10652SHyon.Kim@Sun.COM * Walk through the subtree of desc by Pre-Order Traversal Algo.
2652*10652SHyon.Kim@Sun.COM */
2653*10652SHyon.Kim@Sun.COM for (rp_node = desc; rp_node != NULL; rp_node = rp_node->sibling) {
2654*10652SHyon.Kim@Sun.COM ret += sas_print_rpnode(input, rp_node, lident, gident);
2655*10652SHyon.Kim@Sun.COM }
2656*10652SHyon.Kim@Sun.COM
2657*10652SHyon.Kim@Sun.COM return (ret);
2658*10652SHyon.Kim@Sun.COM }
2659*10652SHyon.Kim@Sun.COM
2660*10652SHyon.Kim@Sun.COM /*
2661*10652SHyon.Kim@Sun.COM * Function used to print the information of specified SAS address.
2662*10652SHyon.Kim@Sun.COM * handle - handle to a HBA.
2663*10652SHyon.Kim@Sun.COM * port - port attributes of a HBA port.
2664*10652SHyon.Kim@Sun.COM * rpnode - discovered port which will be processed.
2665*10652SHyon.Kim@Sun.COM * lident - local indentation used for shifting indentation.
2666*10652SHyon.Kim@Sun.COM * gident - global indentation used for calculating "Tier" number.
2667*10652SHyon.Kim@Sun.COM */
2668*10652SHyon.Kim@Sun.COM static int
sas_print_rpnode(inputArg_t * input,rp_tree_t * rpnode,int lident,int gident)2669*10652SHyon.Kim@Sun.COM sas_print_rpnode(inputArg_t *input,
2670*10652SHyon.Kim@Sun.COM rp_tree_t *rpnode, int lident, int gident)
2671*10652SHyon.Kim@Sun.COM {
2672*10652SHyon.Kim@Sun.COM int ret = 0;
2673*10652SHyon.Kim@Sun.COM
2674*10652SHyon.Kim@Sun.COM if (rpnode->portattr.PortType == HBA_PORTTYPE_SASEXPANDER) {
2675*10652SHyon.Kim@Sun.COM (void *) fprintf(stdout, "%s%s(Tier %d): %016llx\n",
2676*10652SHyon.Kim@Sun.COM getIndentSpaces(lident),
2677*10652SHyon.Kim@Sun.COM "Expander SAS Address",
2678*10652SHyon.Kim@Sun.COM gident / (2 * TABLEN),
2679*10652SHyon.Kim@Sun.COM wwnConversion(rpnode->sasattr.LocalSASAddress.wwn));
2680*10652SHyon.Kim@Sun.COM } else {
2681*10652SHyon.Kim@Sun.COM (void *) fprintf(stdout, "%s%s %016llx\n",
2682*10652SHyon.Kim@Sun.COM getIndentSpaces(lident),
2683*10652SHyon.Kim@Sun.COM "Target Port SAS Address:",
2684*10652SHyon.Kim@Sun.COM wwnConversion(rpnode->sasattr.LocalSASAddress.wwn));
2685*10652SHyon.Kim@Sun.COM }
2686*10652SHyon.Kim@Sun.COM if (input->pflag & PRINT_VERBOSE) {
2687*10652SHyon.Kim@Sun.COM if (rpnode->portattr.PortType != HBA_PORTTYPE_SASEXPANDER) {
2688*10652SHyon.Kim@Sun.COM (void *) fprintf(stdout, "%s%s %s\n",
2689*10652SHyon.Kim@Sun.COM getIndentSpaces(TABLEN + lident),
2690*10652SHyon.Kim@Sun.COM "Type:",
2691*10652SHyon.Kim@Sun.COM getStateString(rpnode->portattr.PortType,
2692*10652SHyon.Kim@Sun.COM porttype_string));
2693*10652SHyon.Kim@Sun.COM } else {
2694*10652SHyon.Kim@Sun.COM (void *) fprintf(stdout, "%s%s %s\n",
2695*10652SHyon.Kim@Sun.COM getIndentSpaces(TABLEN + lident),
2696*10652SHyon.Kim@Sun.COM "OS Device Name:",
2697*10652SHyon.Kim@Sun.COM rpnode->portattr.OSDeviceName);
2698*10652SHyon.Kim@Sun.COM (void *) fprintf(stdout, "%s%s %s\n",
2699*10652SHyon.Kim@Sun.COM getIndentSpaces(TABLEN + lident),
2700*10652SHyon.Kim@Sun.COM "State: ",
2701*10652SHyon.Kim@Sun.COM getStateString(rpnode->portattr.PortState,
2702*10652SHyon.Kim@Sun.COM portstate_string));
2703*10652SHyon.Kim@Sun.COM }
2704*10652SHyon.Kim@Sun.COM }
2705*10652SHyon.Kim@Sun.COM rpnode->printed = 1;
2706*10652SHyon.Kim@Sun.COM return (ret);
2707*10652SHyon.Kim@Sun.COM }
2708*10652SHyon.Kim@Sun.COM
2709*10652SHyon.Kim@Sun.COM /*
2710*10652SHyon.Kim@Sun.COM * Function used to get the correct domainPortWWN as needed by some of the
2711*10652SHyon.Kim@Sun.COM * SMHBA APIs.
2712*10652SHyon.Kim@Sun.COM * handle - handle to a HBA.
2713*10652SHyon.Kim@Sun.COM * portIndex - index to locate the port.
2714*10652SHyon.Kim@Sun.COM * port - pointer to the structure holding port attributes.
2715*10652SHyon.Kim@Sun.COM * pdomainPort - pointer to the buffer holding domainPortWWN.
2716*10652SHyon.Kim@Sun.COM */
2717*10652SHyon.Kim@Sun.COM HBA_STATUS
get_domainPort(HBA_HANDLE handle,int portIndex,PSMHBA_PORTATTRIBUTES port,HBA_WWN * pdomainPort)2718*10652SHyon.Kim@Sun.COM get_domainPort(HBA_HANDLE handle,
2719*10652SHyon.Kim@Sun.COM int portIndex, PSMHBA_PORTATTRIBUTES port,
2720*10652SHyon.Kim@Sun.COM HBA_WWN *pdomainPort)
2721*10652SHyon.Kim@Sun.COM {
2722*10652SHyon.Kim@Sun.COM HBA_STATUS status;
2723*10652SHyon.Kim@Sun.COM PSMHBA_SAS_PORT sasport;
2724*10652SHyon.Kim@Sun.COM SMHBA_SAS_PHY phyattr;
2725*10652SHyon.Kim@Sun.COM
2726*10652SHyon.Kim@Sun.COM sasport = port->PortSpecificAttribute.SASPort;
2727*10652SHyon.Kim@Sun.COM (void *) memset(pdomainPort, 0, sizeof (HBA_WWN));
2728*10652SHyon.Kim@Sun.COM /*
2729*10652SHyon.Kim@Sun.COM * Since iport can exist without any phys,
2730*10652SHyon.Kim@Sun.COM * sasinfo hba-port -v has indicated numberOfPhys;
2731*10652SHyon.Kim@Sun.COM * if there is no phys within the hba, just return OK.
2732*10652SHyon.Kim@Sun.COM */
2733*10652SHyon.Kim@Sun.COM if (sasport->NumberofPhys > 0) {
2734*10652SHyon.Kim@Sun.COM status = SMHBA_GetSASPhyAttributes(handle, portIndex,
2735*10652SHyon.Kim@Sun.COM 0, &phyattr);
2736*10652SHyon.Kim@Sun.COM if (status != HBA_STATUS_OK)
2737*10652SHyon.Kim@Sun.COM return (status);
2738*10652SHyon.Kim@Sun.COM (void *) memcpy(pdomainPort, &phyattr.domainPortWWN,
2739*10652SHyon.Kim@Sun.COM sizeof (HBA_WWN));
2740*10652SHyon.Kim@Sun.COM } else {
2741*10652SHyon.Kim@Sun.COM /* return not supported for no phy configured */
2742*10652SHyon.Kim@Sun.COM return (HBA_STATUS_ERROR_NOT_SUPPORTED);
2743*10652SHyon.Kim@Sun.COM }
2744*10652SHyon.Kim@Sun.COM return (HBA_STATUS_OK);
2745*10652SHyon.Kim@Sun.COM }
2746*10652SHyon.Kim@Sun.COM
2747*10652SHyon.Kim@Sun.COM /*
2748*10652SHyon.Kim@Sun.COM * Comparison function for comparing names possibly ending with digits.
2749*10652SHyon.Kim@Sun.COM * Return:
2750*10652SHyon.Kim@Sun.COM * <0 - name1 is less than name2.
2751*10652SHyon.Kim@Sun.COM * 0 - name1 is equal with name2.
2752*10652SHyon.Kim@Sun.COM * >0 - name1 is more than name2.
2753*10652SHyon.Kim@Sun.COM */
2754*10652SHyon.Kim@Sun.COM static int
sas_name_comp(const char * name1,const char * name2)2755*10652SHyon.Kim@Sun.COM sas_name_comp(const char *name1, const char *name2)
2756*10652SHyon.Kim@Sun.COM {
2757*10652SHyon.Kim@Sun.COM int i = 0;
2758*10652SHyon.Kim@Sun.COM
2759*10652SHyon.Kim@Sun.COM if (name1 == name2)
2760*10652SHyon.Kim@Sun.COM return (0);
2761*10652SHyon.Kim@Sun.COM
2762*10652SHyon.Kim@Sun.COM while ((name1[i] == name2[i]) && (name1[i] != '\0'))
2763*10652SHyon.Kim@Sun.COM i++;
2764*10652SHyon.Kim@Sun.COM
2765*10652SHyon.Kim@Sun.COM /* If neither of name1[i] and name2[i] is '\0'. */
2766*10652SHyon.Kim@Sun.COM if (isdigit(name1[i]) && isdigit(name2[i]))
2767*10652SHyon.Kim@Sun.COM return (atoi(&name1[i]) - atoi(&name2[i]));
2768*10652SHyon.Kim@Sun.COM
2769*10652SHyon.Kim@Sun.COM /* One of name1[i] and name2[i] is not digit. */
2770*10652SHyon.Kim@Sun.COM return (name1[i] - name2[i]);
2771*10652SHyon.Kim@Sun.COM }
2772*10652SHyon.Kim@Sun.COM /*
2773*10652SHyon.Kim@Sun.COM * Comparison function for sorting HBA/HBA Port.
2774*10652SHyon.Kim@Sun.COM * arg1 - first argument of type sas_elem_t.
2775*10652SHyon.Kim@Sun.COM * arg2 - second argument of type sas_elem_t.
2776*10652SHyon.Kim@Sun.COM * Return:
2777*10652SHyon.Kim@Sun.COM * <0 - arg1 is less than arg2.
2778*10652SHyon.Kim@Sun.COM * 0 - arg1 is equal with arg2.
2779*10652SHyon.Kim@Sun.COM * >0 - arg1 is more than arg2.
2780*10652SHyon.Kim@Sun.COM */
2781*10652SHyon.Kim@Sun.COM static int
sas_elem_compare(const void * arg1,const void * arg2)2782*10652SHyon.Kim@Sun.COM sas_elem_compare(const void *arg1, const void *arg2)
2783*10652SHyon.Kim@Sun.COM {
2784*10652SHyon.Kim@Sun.COM sas_elem_t *p1, *p2;
2785*10652SHyon.Kim@Sun.COM p1 = (sas_elem_t *)arg1;
2786*10652SHyon.Kim@Sun.COM p2 = (sas_elem_t *)arg2;
2787*10652SHyon.Kim@Sun.COM return (sas_name_comp(p1->name, p2->name));
2788*10652SHyon.Kim@Sun.COM }
2789*10652SHyon.Kim@Sun.COM
2790*10652SHyon.Kim@Sun.COM /*
2791*10652SHyon.Kim@Sun.COM * Sorting function for HBA/HBA Port output.
2792*10652SHyon.Kim@Sun.COM * array - elements array of type sas_elem_t.
2793*10652SHyon.Kim@Sun.COM * nelem - number of elements in array of type sas_elem_t.
2794*10652SHyon.Kim@Sun.COM */
2795*10652SHyon.Kim@Sun.COM static void
sas_elem_sort(sas_elem_t * array,int nelem)2796*10652SHyon.Kim@Sun.COM sas_elem_sort(sas_elem_t *array, int nelem)
2797*10652SHyon.Kim@Sun.COM {
2798*10652SHyon.Kim@Sun.COM qsort((void *)array, nelem, sizeof (sas_elem_t), sas_elem_compare);
2799*10652SHyon.Kim@Sun.COM }
2800