1fcf3ce44SJohn Forte /*
2fcf3ce44SJohn Forte * CDDL HEADER START
3fcf3ce44SJohn Forte *
4fcf3ce44SJohn Forte * The contents of this file are subject to the terms of the
5fcf3ce44SJohn Forte * Common Development and Distribution License (the "License").
6fcf3ce44SJohn Forte * You may not use this file except in compliance with the License.
7fcf3ce44SJohn Forte *
8fcf3ce44SJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fcf3ce44SJohn Forte * or http://www.opensolaris.org/os/licensing.
10fcf3ce44SJohn Forte * See the License for the specific language governing permissions
11fcf3ce44SJohn Forte * and limitations under the License.
12fcf3ce44SJohn Forte *
13fcf3ce44SJohn Forte * When distributing Covered Code, include this CDDL HEADER in each
14fcf3ce44SJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fcf3ce44SJohn Forte * If applicable, add the following below this CDDL HEADER, with the
16fcf3ce44SJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying
17fcf3ce44SJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner]
18fcf3ce44SJohn Forte *
19fcf3ce44SJohn Forte * CDDL HEADER END
20fcf3ce44SJohn Forte */
21fcf3ce44SJohn Forte /*
22fcf3ce44SJohn Forte * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23fcf3ce44SJohn Forte * Use is subject to license terms.
24fcf3ce44SJohn Forte */
25fcf3ce44SJohn Forte
26fcf3ce44SJohn Forte
27fcf3ce44SJohn Forte #include "cfga_fp.h"
28fcf3ce44SJohn Forte #include <sys/fibre-channel/impl/fc_error.h>
29fcf3ce44SJohn Forte
30fcf3ce44SJohn Forte /* Structure for walking the tree */
31fcf3ce44SJohn Forte typedef struct {
32fcf3ce44SJohn Forte apid_t *apidp;
33fcf3ce44SJohn Forte char *xport_logp;
34fcf3ce44SJohn Forte ldata_list_t *listp;
35fcf3ce44SJohn Forte fpcfga_cmd_t cmd;
36fcf3ce44SJohn Forte cfga_stat_t chld_config;
37fcf3ce44SJohn Forte cfga_type_t xport_type;
38fcf3ce44SJohn Forte cfga_stat_t xport_rstate;
39fcf3ce44SJohn Forte fpcfga_ret_t ret;
40fcf3ce44SJohn Forte int l_errno;
41fcf3ce44SJohn Forte } fpcfga_list_t;
42fcf3ce44SJohn Forte
43fcf3ce44SJohn Forte typedef struct {
44fcf3ce44SJohn Forte uint_t itype;
45fcf3ce44SJohn Forte const char *ntype;
46fcf3ce44SJohn Forte const char *name;
47fcf3ce44SJohn Forte } fpcfga_devtype_t;
48fcf3ce44SJohn Forte
49fcf3ce44SJohn Forte #define ERR_INQ_DTYPE 0xff
50fcf3ce44SJohn Forte
51fcf3ce44SJohn Forte /* The TYPE field is parseable and should not contain spaces */
52fcf3ce44SJohn Forte #define FP_FC_PORT_TYPE "fc"
53fcf3ce44SJohn Forte #define FP_FC_PORT_ERROR "fc-error"
54fcf3ce44SJohn Forte #define FP_FC_FABRIC_PORT_TYPE "fc-fabric"
55fcf3ce44SJohn Forte #define FP_FC_PUBLIC_PORT_TYPE "fc-public"
56fcf3ce44SJohn Forte #define FP_FC_PRIVATE_PORT_TYPE "fc-private"
57fcf3ce44SJohn Forte #define FP_FC_PT_TO_PT_PORT_TYPE "fc-pt_to_pt"
58fcf3ce44SJohn Forte
59fcf3ce44SJohn Forte /* Indicates no plag passing */
60fcf3ce44SJohn Forte #define NO_FLAG 0
61fcf3ce44SJohn Forte
62fcf3ce44SJohn Forte /* defines for retry algorithm */
63fcf3ce44SJohn Forte #define OPEN_RETRY_COUNT 5
64fcf3ce44SJohn Forte #define OPEN_RETRY_INTERVAL 10000 /* 1/100 of a sec. */
65fcf3ce44SJohn Forte #define IOCTL_RETRY_COUNT 5
66fcf3ce44SJohn Forte #define IOCTL_RETRY_INTERVAL 5000000 /* 5 sec */
67fcf3ce44SJohn Forte
68fcf3ce44SJohn Forte /* define for fcp scsi passthru wait */
69fcf3ce44SJohn Forte #define FCP_SCSI_CMD_TIMEOUT 10
70fcf3ce44SJohn Forte
71fcf3ce44SJohn Forte /* define for fcp pseudo node */
72fcf3ce44SJohn Forte #define FCP_PATH "/devices/pseudo/fcp@0:fcp"
73fcf3ce44SJohn Forte
74fcf3ce44SJohn Forte /* Function prototypes */
75fcf3ce44SJohn Forte static fpcfga_ret_t postprocess_list_data(const ldata_list_t *listp,
76fcf3ce44SJohn Forte fpcfga_cmd_t cmd, cfga_stat_t chld_config, int *np, uint_t flags);
77fcf3ce44SJohn Forte static int stat_fc_dev(di_node_t node, void *arg);
78fcf3ce44SJohn Forte static int stat_FCP_dev(di_node_t node, void *arg);
79fcf3ce44SJohn Forte static fpcfga_ret_t do_stat_fca_xport(fpcfga_list_t *lap, int limited_stat,
80fcf3ce44SJohn Forte HBA_PORTATTRIBUTES portAttrs);
81fcf3ce44SJohn Forte static int get_xport_state(di_node_t node, void *arg);
82fcf3ce44SJohn Forte
83fcf3ce44SJohn Forte static fpcfga_ret_t do_stat_fc_dev(const di_node_t node, const char *nodepath,
84fcf3ce44SJohn Forte fpcfga_list_t *lap, int limited_stat);
85fcf3ce44SJohn Forte static fpcfga_ret_t do_stat_FCP_dev(const di_node_t node, const char *nodepath,
86fcf3ce44SJohn Forte fpcfga_list_t *lap, int limited_stat);
87fcf3ce44SJohn Forte static cfga_stat_t xport_devinfo_to_recep_state(uint_t xport_di_state);
88fcf3ce44SJohn Forte static cfga_stat_t dev_devinfo_to_occupant_state(uint_t dev_di_state);
89fcf3ce44SJohn Forte static void get_hw_info(di_node_t node, cfga_list_data_t *clp);
90fcf3ce44SJohn Forte static const char *get_device_type(di_node_t);
91fcf3ce44SJohn Forte static fpcfga_ret_t init_ldata_for_accessible_dev(const char *dyncomp,
92fcf3ce44SJohn Forte uchar_t inq_type, fpcfga_list_t *lap);
93fcf3ce44SJohn Forte static fpcfga_ret_t init_ldata_for_accessible_FCP_dev(const char *port_wwn,
94fcf3ce44SJohn Forte int num_luns, struct report_lun_resp *resp_buf,
95fcf3ce44SJohn Forte fpcfga_list_t *larg, int *l_errnop);
96fcf3ce44SJohn Forte static fpcfga_ret_t is_dyn_ap_on_ldata_list(const char *port_wwn,
97fcf3ce44SJohn Forte const ldata_list_t *listp, ldata_list_t **matchldpp, int *l_errno);
98fcf3ce44SJohn Forte static fpcfga_ret_t is_FCP_dev_ap_on_ldata_list(const char *port_wwn,
99fcf3ce44SJohn Forte const int lun_num, ldata_list_t *ldatap, ldata_list_t **matchldpp);
100fcf3ce44SJohn Forte
101fcf3ce44SJohn Forte static fpcfga_ret_t init_ldata_for_mpath_dev(di_path_t path, char *port_wwn,
102fcf3ce44SJohn Forte int *l_errnop, fpcfga_list_t *lap);
103fcf3ce44SJohn Forte static fpcfga_ret_t insert_ldata_to_ldatalist(const char *port_wwn,
104fcf3ce44SJohn Forte int *lun_nump, ldata_list_t *listp, ldata_list_t **ldatapp);
105fcf3ce44SJohn Forte static fpcfga_ret_t insert_fc_dev_ldata(const char *port_wwn,
106fcf3ce44SJohn Forte ldata_list_t *listp, ldata_list_t **ldatapp);
107fcf3ce44SJohn Forte static fpcfga_ret_t insert_FCP_dev_ldata(const char *port_wwn, int lun_num,
108fcf3ce44SJohn Forte ldata_list_t *listp, ldata_list_t **ldatapp);
109fcf3ce44SJohn Forte static int stat_path_info_fc_dev(di_node_t root, fpcfga_list_t *lap,
110fcf3ce44SJohn Forte int *l_errnop);
111fcf3ce44SJohn Forte static int stat_path_info_FCP_dev(di_node_t root, fpcfga_list_t *lap,
112fcf3ce44SJohn Forte int *l_errnop);
113fcf3ce44SJohn Forte static fpcfga_ret_t get_accessible_FCP_dev_ldata(const char *dyncomp,
114fcf3ce44SJohn Forte fpcfga_list_t *lap, int *l_errnop);
115fcf3ce44SJohn Forte static fpcfga_ret_t get_standard_inq_data(const char *xport_phys,
116fcf3ce44SJohn Forte const char *dyncomp, uchar_t *lun_num, struct scsi_inquiry **inq_buf,
117fcf3ce44SJohn Forte int *l_errnop);
118fcf3ce44SJohn Forte static void init_fcp_scsi_cmd(struct fcp_scsi_cmd *fscsi, uchar_t *lun_num,
119fcf3ce44SJohn Forte la_wwn_t *pwwn, void *scmdbuf, size_t scmdbuf_len, void *respbuf,
120fcf3ce44SJohn Forte size_t respbuf_len, void *sensebuf, size_t sensebuf_len);
121fcf3ce44SJohn Forte static fpcfga_ret_t issue_fcp_scsi_cmd(const char *xport_phys,
122fcf3ce44SJohn Forte struct fcp_scsi_cmd *fscsi, int *l_errnop);
123fcf3ce44SJohn Forte static uchar_t get_inq_dtype(char *xport_phys, char *dyncomp, HBA_HANDLE handle,
124fcf3ce44SJohn Forte HBA_PORTATTRIBUTES *portAttrs, HBA_PORTATTRIBUTES *discPortAttrs);
125fcf3ce44SJohn Forte
126fcf3ce44SJohn Forte static fpcfga_devtype_t device_list[] = {
127fcf3ce44SJohn Forte { DTYPE_DIRECT, DDI_NT_BLOCK_CHAN, "disk"},
128fcf3ce44SJohn Forte { DTYPE_DIRECT, DDI_NT_BLOCK, "disk"},
129fcf3ce44SJohn Forte { DTYPE_DIRECT, DDI_NT_BLOCK_WWN, "disk"},
130fcf3ce44SJohn Forte { DTYPE_DIRECT, DDI_NT_BLOCK_FABRIC, "disk"},
131fcf3ce44SJohn Forte { DTYPE_SEQUENTIAL, DDI_NT_TAPE, "tape"},
132fcf3ce44SJohn Forte { DTYPE_PRINTER, NULL, "printer"},
133fcf3ce44SJohn Forte { DTYPE_PROCESSOR, NULL, "processor"},
134fcf3ce44SJohn Forte { DTYPE_WORM, NULL, "WORM"},
135fcf3ce44SJohn Forte { DTYPE_RODIRECT, DDI_NT_CD_CHAN, "CD-ROM"},
136fcf3ce44SJohn Forte { DTYPE_RODIRECT, DDI_NT_CD, "CD-ROM"},
137fcf3ce44SJohn Forte { DTYPE_SCANNER, NULL, "scanner"},
138fcf3ce44SJohn Forte { DTYPE_OPTICAL, NULL, "optical"},
139fcf3ce44SJohn Forte { DTYPE_CHANGER, NULL, "med-changer"},
140fcf3ce44SJohn Forte { DTYPE_COMM, NULL, "comm-device"},
141fcf3ce44SJohn Forte { DTYPE_ARRAY_CTRL, NULL, "array-ctrl"},
142fcf3ce44SJohn Forte { DTYPE_ESI, NULL, "ESI"},
143fcf3ce44SJohn Forte /*
144fcf3ce44SJohn Forte * This has to be the LAST entry for DTYPE_UNKNOWN_INDEX.
145fcf3ce44SJohn Forte * Add entries before this.
146fcf3ce44SJohn Forte */
147fcf3ce44SJohn Forte { DTYPE_UNKNOWN, NULL, "unknown"}
148fcf3ce44SJohn Forte };
149fcf3ce44SJohn Forte
150fcf3ce44SJohn Forte #define N_DEVICE_TYPES (sizeof (device_list) / sizeof (device_list[0]))
151fcf3ce44SJohn Forte
152fcf3ce44SJohn Forte #define DTYPE_UNKNOWN_INDEX (N_DEVICE_TYPES - 1)
153fcf3ce44SJohn Forte
154fcf3ce44SJohn Forte /*
155fcf3ce44SJohn Forte * Main routine for list operation.
156fcf3ce44SJohn Forte * It calls various routines to consturct ldata list and
157fcf3ce44SJohn Forte * postprocess the list data.
158fcf3ce44SJohn Forte *
159fcf3ce44SJohn Forte * Overall algorithm:
160fcf3ce44SJohn Forte * Get the device list on input hba port and construct ldata list for
161fcf3ce44SJohn Forte * accesible devices.
162fcf3ce44SJohn Forte * Stat hba port and devices through walking the device tree.
163fcf3ce44SJohn Forte * Verify the validity of the list data.
164fcf3ce44SJohn Forte */
165fcf3ce44SJohn Forte fpcfga_ret_t
do_list(apid_t * apidp,fpcfga_cmd_t cmd,ldata_list_t ** llpp,int * nelemp,char ** errstring)166fcf3ce44SJohn Forte do_list(
167fcf3ce44SJohn Forte apid_t *apidp,
168fcf3ce44SJohn Forte fpcfga_cmd_t cmd,
169fcf3ce44SJohn Forte ldata_list_t **llpp,
170fcf3ce44SJohn Forte int *nelemp,
171fcf3ce44SJohn Forte char **errstring)
172fcf3ce44SJohn Forte {
173fcf3ce44SJohn Forte int n = -1, l_errno = 0, limited_stat;
174fcf3ce44SJohn Forte walkarg_t walkarg;
175fcf3ce44SJohn Forte fpcfga_list_t larg = {NULL};
176fcf3ce44SJohn Forte fpcfga_ret_t ret;
177fcf3ce44SJohn Forte la_wwn_t pwwn;
178fcf3ce44SJohn Forte char *dyncomp = NULL;
179fcf3ce44SJohn Forte HBA_HANDLE handle;
180fcf3ce44SJohn Forte HBA_PORTATTRIBUTES portAttrs;
181fcf3ce44SJohn Forte HBA_PORTATTRIBUTES discPortAttrs;
182fcf3ce44SJohn Forte HBA_STATUS status;
183fcf3ce44SJohn Forte int portIndex, discIndex;
184fcf3ce44SJohn Forte int retry;
185fcf3ce44SJohn Forte uchar_t inq_dtype;
186fcf3ce44SJohn Forte
187fcf3ce44SJohn Forte if (*llpp != NULL || *nelemp != 0) {
188fcf3ce44SJohn Forte return (FPCFGA_ERR);
189fcf3ce44SJohn Forte }
190fcf3ce44SJohn Forte
191fcf3ce44SJohn Forte /* Create the hba logid (also base component of logical ap_id) */
192fcf3ce44SJohn Forte ret = make_xport_logid(apidp->xport_phys, &larg.xport_logp, &l_errno);
193fcf3ce44SJohn Forte if (ret != FPCFGA_OK) {
194fcf3ce44SJohn Forte cfga_err(errstring, l_errno, ERR_LIST, 0);
195fcf3ce44SJohn Forte return (FPCFGA_ERR);
196fcf3ce44SJohn Forte }
197fcf3ce44SJohn Forte
198fcf3ce44SJohn Forte assert(larg.xport_logp != NULL);
199fcf3ce44SJohn Forte
200fcf3ce44SJohn Forte larg.cmd = cmd;
201fcf3ce44SJohn Forte larg.apidp = apidp;
202fcf3ce44SJohn Forte larg.xport_rstate = CFGA_STAT_NONE;
203fcf3ce44SJohn Forte
204fcf3ce44SJohn Forte if ((ret = findMatchingAdapterPort(larg.apidp->xport_phys, &handle,
205fcf3ce44SJohn Forte &portIndex, &portAttrs, errstring)) != FPCFGA_OK) {
206fcf3ce44SJohn Forte S_FREE(larg.xport_logp);
207fcf3ce44SJohn Forte return (ret);
208fcf3ce44SJohn Forte }
209fcf3ce44SJohn Forte
210fcf3ce44SJohn Forte /*
211fcf3ce44SJohn Forte * If stating a specific device, we will do limited stat on fca port.
212fcf3ce44SJohn Forte * otherwise full stat on fca part is required.
213fcf3ce44SJohn Forte * If stating a specific device we don't know if it exists or is
214fcf3ce44SJohn Forte * configured yet. larg.ret is set to apid noexist for do_stat_dev.
215fcf3ce44SJohn Forte * otherwise larg.ret is set to ok initially.
216fcf3ce44SJohn Forte */
217fcf3ce44SJohn Forte if (larg.cmd == FPCFGA_STAT_FC_DEV) {
218fcf3ce44SJohn Forte limited_stat = 1; /* for do_stat_fca_xport */
219fcf3ce44SJohn Forte larg.ret = FPCFGA_APID_NOEXIST; /* for stat_fc_dev */
220fcf3ce44SJohn Forte } else {
221fcf3ce44SJohn Forte limited_stat = 0; /* for do_stat_fca_xport */
222fcf3ce44SJohn Forte larg.ret = FPCFGA_OK; /* for stat_fc_dev */
223fcf3ce44SJohn Forte }
224fcf3ce44SJohn Forte
225fcf3ce44SJohn Forte /* For all list commands, the fca port needs to be stat'ed */
226fcf3ce44SJohn Forte if ((ret = do_stat_fca_xport(&larg, limited_stat,
227fcf3ce44SJohn Forte portAttrs)) != FPCFGA_OK) {
228fcf3ce44SJohn Forte cfga_err(errstring, larg.l_errno, ERR_LIST, 0);
229fcf3ce44SJohn Forte list_free(&larg.listp);
230fcf3ce44SJohn Forte S_FREE(larg.xport_logp);
231fcf3ce44SJohn Forte HBA_CloseAdapter(handle);
232fcf3ce44SJohn Forte HBA_FreeLibrary();
233fcf3ce44SJohn Forte return (ret);
234fcf3ce44SJohn Forte }
235fcf3ce44SJohn Forte
236fcf3ce44SJohn Forte #ifdef DEBUG
237fcf3ce44SJohn Forte if (limited_stat) {
238fcf3ce44SJohn Forte assert(larg.listp == NULL);
239fcf3ce44SJohn Forte } else {
240fcf3ce44SJohn Forte assert(larg.listp != NULL);
241fcf3ce44SJohn Forte }
242fcf3ce44SJohn Forte #endif
243fcf3ce44SJohn Forte /*
244fcf3ce44SJohn Forte * If stat'ing a FCA port or ALL, we have the bus stat data at
245fcf3ce44SJohn Forte * this point.
246fcf3ce44SJohn Forte * Assume that the bus has no configured children.
247fcf3ce44SJohn Forte */
248fcf3ce44SJohn Forte larg.chld_config = CFGA_STAT_UNCONFIGURED;
249fcf3ce44SJohn Forte
250fcf3ce44SJohn Forte switch (larg.cmd) {
251fcf3ce44SJohn Forte case FPCFGA_STAT_FC_DEV:
252fcf3ce44SJohn Forte /* la_wwn_t has uchar_t raw_wwn[8] thus no need to free. */
253fcf3ce44SJohn Forte if (cvt_dyncomp_to_lawwn(apidp->dyncomp, &pwwn) != 0) {
254fcf3ce44SJohn Forte cfga_err(errstring, 0, ERR_LIST, 0);
255fcf3ce44SJohn Forte list_free(&larg.listp);
256fcf3ce44SJohn Forte S_FREE(larg.xport_logp);
257fcf3ce44SJohn Forte HBA_CloseAdapter(handle);
258fcf3ce44SJohn Forte HBA_FreeLibrary();
259fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
260fcf3ce44SJohn Forte }
261fcf3ce44SJohn Forte /*
262fcf3ce44SJohn Forte * if the dyncomp exists on disco ports construct list_data
263fcf3ce44SJohn Forte * otherwise return FPCFGA_APID_NOEXIST.
264fcf3ce44SJohn Forte */
265fcf3ce44SJohn Forte retry = 0;
266fcf3ce44SJohn Forte do {
267fcf3ce44SJohn Forte status = getPortAttrsByWWN(handle,
268fcf3ce44SJohn Forte *((HBA_WWN *)(&pwwn)), &discPortAttrs);
269fcf3ce44SJohn Forte if (status == HBA_STATUS_ERROR_STALE_DATA) {
270fcf3ce44SJohn Forte /* get Port Attributes again after refresh. */
271fcf3ce44SJohn Forte HBA_RefreshInformation(handle);
272fcf3ce44SJohn Forte } else {
273fcf3ce44SJohn Forte break; /* either okay or some other error */
274fcf3ce44SJohn Forte }
275fcf3ce44SJohn Forte } while (retry++ < HBA_MAX_RETRIES);
276fcf3ce44SJohn Forte
277fcf3ce44SJohn Forte if (status == HBA_STATUS_OK) {
278fcf3ce44SJohn Forte /*
279fcf3ce44SJohn Forte * if dyncomp found in disco ports
280fcf3ce44SJohn Forte * construct ldata_list and return.
281fcf3ce44SJohn Forte * otherwise continue to stat on dev tree with
282fcf3ce44SJohn Forte * larg.ret set to access_ok which informs stat_fc_dev
283fcf3ce44SJohn Forte * the existence of device on disco ports.
284fcf3ce44SJohn Forte *
285fcf3ce44SJohn Forte * if path is null that guatantees the node is not
286fcf3ce44SJohn Forte * configured. if node is detached the path
287fcf3ce44SJohn Forte * is incomplete and not usable for further
288fcf3ce44SJohn Forte * operations like uscsi_inq so take care of it here.
289fcf3ce44SJohn Forte */
290fcf3ce44SJohn Forte inq_dtype = get_inq_dtype(apidp->xport_phys,
291fcf3ce44SJohn Forte apidp->dyncomp, handle, &portAttrs, &discPortAttrs);
292fcf3ce44SJohn Forte
293fcf3ce44SJohn Forte if (init_ldata_for_accessible_dev(apidp->dyncomp,
294fcf3ce44SJohn Forte inq_dtype, &larg) != FPCFGA_OK) {
295fcf3ce44SJohn Forte cfga_err(errstring, larg.l_errno,
296fcf3ce44SJohn Forte ERR_LIST, 0);
297fcf3ce44SJohn Forte list_free(&larg.listp);
298fcf3ce44SJohn Forte S_FREE(larg.xport_logp);
299fcf3ce44SJohn Forte HBA_CloseAdapter(handle);
300fcf3ce44SJohn Forte HBA_FreeLibrary();
301fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
302fcf3ce44SJohn Forte }
303fcf3ce44SJohn Forte if (apidp->lunlist == NULL) {
304fcf3ce44SJohn Forte n = 0;
305fcf3ce44SJohn Forte if (postprocess_list_data(
306fcf3ce44SJohn Forte larg.listp, cmd,
307fcf3ce44SJohn Forte larg.chld_config, &n, NO_FLAG) !=
308fcf3ce44SJohn Forte FPCFGA_OK) {
309fcf3ce44SJohn Forte cfga_err(errstring,
310fcf3ce44SJohn Forte larg.l_errno, ERR_LIST, 0);
311fcf3ce44SJohn Forte list_free(&larg.listp);
312fcf3ce44SJohn Forte S_FREE(larg.xport_logp);
313fcf3ce44SJohn Forte HBA_CloseAdapter(handle);
314fcf3ce44SJohn Forte HBA_FreeLibrary();
315fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
316fcf3ce44SJohn Forte }
317fcf3ce44SJohn Forte *nelemp = n;
318fcf3ce44SJohn Forte *llpp = larg.listp;
319fcf3ce44SJohn Forte S_FREE(larg.xport_logp);
320fcf3ce44SJohn Forte HBA_CloseAdapter(handle);
321fcf3ce44SJohn Forte HBA_FreeLibrary();
322fcf3ce44SJohn Forte return (FPCFGA_OK);
323fcf3ce44SJohn Forte }
324fcf3ce44SJohn Forte larg.ret = FPCFGA_ACCESS_OK;
325fcf3ce44SJohn Forte } else if (status == HBA_STATUS_ERROR_ILLEGAL_WWN) {
326fcf3ce44SJohn Forte /*
327fcf3ce44SJohn Forte * path indicates if the node exists in dev tree.
328fcf3ce44SJohn Forte * if not found in dev tree return apid no exist.
329fcf3ce44SJohn Forte * otherwise continue to stat with larg.ret set to
330fcf3ce44SJohn Forte * apid_noexist.
331fcf3ce44SJohn Forte */
332fcf3ce44SJohn Forte if (apidp->lunlist == NULL) {
333fcf3ce44SJohn Forte list_free(&larg.listp);
334fcf3ce44SJohn Forte S_FREE(larg.xport_logp);
335fcf3ce44SJohn Forte HBA_CloseAdapter(handle);
336fcf3ce44SJohn Forte HBA_FreeLibrary();
337fcf3ce44SJohn Forte return (FPCFGA_APID_NOEXIST);
338fcf3ce44SJohn Forte }
339fcf3ce44SJohn Forte } else { /* any error */
340fcf3ce44SJohn Forte /*
341fcf3ce44SJohn Forte * path indicates if the node exists in dev tree.
342fcf3ce44SJohn Forte * if not found in dev tree return lib error.
343fcf3ce44SJohn Forte * otherwise continue to stat with larg.ret set to
344fcf3ce44SJohn Forte * apid_noexist.
345fcf3ce44SJohn Forte */
346fcf3ce44SJohn Forte if (apidp->lunlist == NULL) {
347fcf3ce44SJohn Forte cfga_err(errstring, 0, ERR_FC_GET_DEVLIST, 0);
348fcf3ce44SJohn Forte list_free(&larg.listp);
349fcf3ce44SJohn Forte S_FREE(larg.xport_logp);
350fcf3ce44SJohn Forte HBA_CloseAdapter(handle);
351fcf3ce44SJohn Forte HBA_FreeLibrary();
352fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
353fcf3ce44SJohn Forte }
354fcf3ce44SJohn Forte }
355fcf3ce44SJohn Forte break;
356fcf3ce44SJohn Forte case FPCFGA_STAT_ALL:
357fcf3ce44SJohn Forte /*
358fcf3ce44SJohn Forte * for each dev in disco ports, create a ldata_list element.
359fcf3ce44SJohn Forte * if if no disco ports found, continue to stat on devinfo tree
360fcf3ce44SJohn Forte * to see if any node exist on the fca port.
361fcf3ce44SJohn Forte */
362fcf3ce44SJohn Forte for (discIndex = 0;
363fcf3ce44SJohn Forte discIndex < portAttrs.NumberofDiscoveredPorts;
364fcf3ce44SJohn Forte discIndex++) {
365fcf3ce44SJohn Forte if (getDiscPortAttrs(handle, portIndex,
366fcf3ce44SJohn Forte discIndex, &discPortAttrs)) {
367fcf3ce44SJohn Forte /* Move on to the next target */
368fcf3ce44SJohn Forte continue;
369fcf3ce44SJohn Forte }
370fcf3ce44SJohn Forte memcpy(&pwwn, &discPortAttrs.PortWWN, sizeof (la_wwn_t));
371fcf3ce44SJohn Forte cvt_lawwn_to_dyncomp(&pwwn, &dyncomp, &l_errno);
372fcf3ce44SJohn Forte if (dyncomp == NULL) {
373fcf3ce44SJohn Forte cfga_err(errstring, l_errno, ERR_LIST, 0);
374fcf3ce44SJohn Forte list_free(&larg.listp);
375fcf3ce44SJohn Forte S_FREE(larg.xport_logp);
376fcf3ce44SJohn Forte HBA_CloseAdapter(handle);
377fcf3ce44SJohn Forte HBA_FreeLibrary();
378fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
379fcf3ce44SJohn Forte }
380fcf3ce44SJohn Forte inq_dtype = get_inq_dtype(apidp->xport_phys, dyncomp,
381fcf3ce44SJohn Forte handle, &portAttrs, &discPortAttrs);
382fcf3ce44SJohn Forte
383fcf3ce44SJohn Forte if ((ret = init_ldata_for_accessible_dev(
384fcf3ce44SJohn Forte dyncomp, inq_dtype, &larg)) != FPCFGA_OK) {
385fcf3ce44SJohn Forte S_FREE(dyncomp);
386fcf3ce44SJohn Forte cfga_err(errstring, larg.l_errno, ERR_LIST, 0);
387fcf3ce44SJohn Forte list_free(&larg.listp);
388fcf3ce44SJohn Forte S_FREE(larg.xport_logp);
389fcf3ce44SJohn Forte HBA_CloseAdapter(handle);
390fcf3ce44SJohn Forte HBA_FreeLibrary();
391fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
392fcf3ce44SJohn Forte }
393fcf3ce44SJohn Forte S_FREE(dyncomp);
394fcf3ce44SJohn Forte }
395fcf3ce44SJohn Forte break;
396fcf3ce44SJohn Forte default:
397fcf3ce44SJohn Forte break;
398fcf3ce44SJohn Forte }
399fcf3ce44SJohn Forte
400fcf3ce44SJohn Forte /* we need to stat at least 1 device for all commands */
401fcf3ce44SJohn Forte if (apidp->flags == FLAG_DEVINFO_FORCE) {
402fcf3ce44SJohn Forte walkarg.flags = FLAG_DEVINFO_FORCE;
403fcf3ce44SJohn Forte } else {
404fcf3ce44SJohn Forte walkarg.flags = 0;
405fcf3ce44SJohn Forte }
406fcf3ce44SJohn Forte
407fcf3ce44SJohn Forte walkarg.flags |= FLAG_PATH_INFO_WALK;
408fcf3ce44SJohn Forte walkarg.walkmode.node_args.flags = DI_WALK_CLDFIRST;
409fcf3ce44SJohn Forte walkarg.walkmode.node_args.fcn = stat_fc_dev;
410fcf3ce44SJohn Forte
411fcf3ce44SJohn Forte /*
412fcf3ce44SJohn Forte * Subtree is ALWAYS rooted at the HBA (not at the device) as
413fcf3ce44SJohn Forte * otherwise deadlock may occur if bus is disconnected.
414fcf3ce44SJohn Forte *
415fcf3ce44SJohn Forte * DINFOPROP was sufficient on apidp->xport_phys prior to the support
416fcf3ce44SJohn Forte * on scsi_vhci child node. In order to get the link between
417fcf3ce44SJohn Forte * scsi_vhci node and path info node the snap shot of the
418fcf3ce44SJohn Forte * the whole device tree is required with DINFOCPYALL | DINFOPATH flag.
419fcf3ce44SJohn Forte */
420fcf3ce44SJohn Forte ret = walk_tree(apidp->xport_phys, &larg, DINFOCPYALL | DINFOPATH,
421fcf3ce44SJohn Forte &walkarg, FPCFGA_WALK_NODE, &larg.l_errno);
422fcf3ce44SJohn Forte
423fcf3ce44SJohn Forte /*
424fcf3ce44SJohn Forte * ret from walk_tree is either FPCFGA_OK or FPCFGA_ERR.
425fcf3ce44SJohn Forte * larg.ret is used to detect other errors. Make sure larg.ret
426fcf3ce44SJohn Forte * is set to a correct error.
427fcf3ce44SJohn Forte */
428fcf3ce44SJohn Forte if (ret != FPCFGA_OK || (ret = larg.ret) != FPCFGA_OK) {
429fcf3ce44SJohn Forte if (ret != FPCFGA_APID_NOEXIST) {
430fcf3ce44SJohn Forte cfga_err(errstring, larg.l_errno, ERR_LIST, 0);
431fcf3ce44SJohn Forte }
432fcf3ce44SJohn Forte /* if larg.ret = FPCFGA_APID_NOEXIST; */
433fcf3ce44SJohn Forte goto out;
434fcf3ce44SJohn Forte }
435fcf3ce44SJohn Forte
436fcf3ce44SJohn Forte assert(larg.listp != NULL);
437fcf3ce44SJohn Forte
438fcf3ce44SJohn Forte n = 0;
439fcf3ce44SJohn Forte ret = postprocess_list_data(larg.listp, cmd, larg.chld_config, &n,
440fcf3ce44SJohn Forte NO_FLAG);
441fcf3ce44SJohn Forte if (ret != FPCFGA_OK) {
442fcf3ce44SJohn Forte cfga_err(errstring, 0, ERR_LIST, 0);
443fcf3ce44SJohn Forte ret = FPCFGA_LIB_ERR;
444fcf3ce44SJohn Forte goto out;
445fcf3ce44SJohn Forte }
446fcf3ce44SJohn Forte
447fcf3ce44SJohn Forte *nelemp = n;
448fcf3ce44SJohn Forte *llpp = larg.listp;
449fcf3ce44SJohn Forte ret = FPCFGA_OK;
450fcf3ce44SJohn Forte /* FALLTHROUGH */
451fcf3ce44SJohn Forte out:
452fcf3ce44SJohn Forte if (ret != FPCFGA_OK) list_free(&larg.listp);
453fcf3ce44SJohn Forte S_FREE(larg.xport_logp);
454fcf3ce44SJohn Forte HBA_CloseAdapter(handle);
455fcf3ce44SJohn Forte HBA_FreeLibrary();
456fcf3ce44SJohn Forte return (ret);
457fcf3ce44SJohn Forte }
458fcf3ce44SJohn Forte
459fcf3ce44SJohn Forte /*
460fcf3ce44SJohn Forte * Main routine for list operation when show_FCP_dev option is given.
461fcf3ce44SJohn Forte * It calls various routines to consturct ldata list and
462fcf3ce44SJohn Forte * postprocess the list data.
463fcf3ce44SJohn Forte *
464fcf3ce44SJohn Forte * The difference between do_list() and do_list_FCP_dev() is to
465fcf3ce44SJohn Forte * process FCP SCSI LUN data list via uscsi report lun operation and
466fcf3ce44SJohn Forte * stat lun level instead of port WWN based target level.
467fcf3ce44SJohn Forte * The rest of logic is same.
468fcf3ce44SJohn Forte *
469fcf3ce44SJohn Forte * Overall algorithm:
470fcf3ce44SJohn Forte * Get the device list on input hba port and construct ldata list for
471fcf3ce44SJohn Forte * accesible devices.
472fcf3ce44SJohn Forte * For each configured device, USCSI report lun is issued and ldata list
473fcf3ce44SJohn Forte * with FCP device level(LUN) information is created.
474fcf3ce44SJohn Forte * Stat hba port and LUN devices through walking the device tree.
475fcf3ce44SJohn Forte * Verify the validity of the list data.
476fcf3ce44SJohn Forte */
477fcf3ce44SJohn Forte fpcfga_ret_t
do_list_FCP_dev(const char * ap_id,uint_t flags,fpcfga_cmd_t cmd,ldata_list_t ** llpp,int * nelemp,char ** errstring)478fcf3ce44SJohn Forte do_list_FCP_dev(
479fcf3ce44SJohn Forte const char *ap_id,
480fcf3ce44SJohn Forte uint_t flags,
481fcf3ce44SJohn Forte fpcfga_cmd_t cmd,
482fcf3ce44SJohn Forte ldata_list_t **llpp,
483fcf3ce44SJohn Forte int *nelemp,
484fcf3ce44SJohn Forte char **errstring)
485fcf3ce44SJohn Forte {
486fcf3ce44SJohn Forte int n = -1, l_errno = 0, limited_stat, len;
487fcf3ce44SJohn Forte walkarg_t walkarg;
488fcf3ce44SJohn Forte fpcfga_list_t larg = {NULL};
489fcf3ce44SJohn Forte fpcfga_ret_t ret;
490fcf3ce44SJohn Forte la_wwn_t pwwn;
491fcf3ce44SJohn Forte char *xport_phys = NULL, *dyn = NULL, *dyncomp = NULL,
492fcf3ce44SJohn Forte *lun_dyn = NULL;
493fcf3ce44SJohn Forte apid_t apid_con = {NULL};
494fcf3ce44SJohn Forte HBA_HANDLE handle;
495fcf3ce44SJohn Forte HBA_PORTATTRIBUTES portAttrs;
496fcf3ce44SJohn Forte HBA_PORTATTRIBUTES discPortAttrs;
497fcf3ce44SJohn Forte HBA_STATUS status;
498fcf3ce44SJohn Forte int portIndex, discIndex;
499fcf3ce44SJohn Forte int retry;
500fcf3ce44SJohn Forte uint64_t lun = 0;
501fcf3ce44SJohn Forte struct scsi_inquiry inq;
502fcf3ce44SJohn Forte struct scsi_extended_sense sense;
503fcf3ce44SJohn Forte HBA_UINT8 scsiStatus;
504fcf3ce44SJohn Forte uint32_t inquirySize = sizeof (inq),
505fcf3ce44SJohn Forte senseSize = sizeof (sense);
506fcf3ce44SJohn Forte
507fcf3ce44SJohn Forte if (*llpp != NULL || *nelemp != 0) {
508fcf3ce44SJohn Forte return (FPCFGA_ERR);
509fcf3ce44SJohn Forte }
510fcf3ce44SJohn Forte
511fcf3ce44SJohn Forte if ((xport_phys = pathdup(ap_id, &l_errno)) == NULL) {
512fcf3ce44SJohn Forte cfga_err(errstring, l_errno, ERR_OP_FAILED, 0);
513fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
514fcf3ce44SJohn Forte }
515fcf3ce44SJohn Forte
516fcf3ce44SJohn Forte /* Extract the base(hba) and dynamic(device) component if any */
517fcf3ce44SJohn Forte if ((dyn = GET_DYN(xport_phys)) != NULL) {
518fcf3ce44SJohn Forte len = strlen(DYN_TO_DYNCOMP(dyn)) + 1;
519fcf3ce44SJohn Forte dyncomp = calloc(1, len);
520fcf3ce44SJohn Forte if (dyncomp == NULL) {
521fcf3ce44SJohn Forte cfga_err(errstring, errno, ERR_OP_FAILED, 0);
522fcf3ce44SJohn Forte S_FREE(xport_phys);
523fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
524fcf3ce44SJohn Forte }
525fcf3ce44SJohn Forte
526fcf3ce44SJohn Forte (void) strcpy(dyncomp, DYN_TO_DYNCOMP(dyn));
527fcf3ce44SJohn Forte /* Remove the dynamic component from the base. */
528fcf3ce44SJohn Forte *dyn = '\0';
529fcf3ce44SJohn Forte /* if lun dyncomp exists delete it */
530fcf3ce44SJohn Forte if ((lun_dyn = GET_LUN_DYN(dyncomp)) != NULL) {
531fcf3ce44SJohn Forte *lun_dyn = '\0';
532fcf3ce44SJohn Forte }
533fcf3ce44SJohn Forte }
534fcf3ce44SJohn Forte
535fcf3ce44SJohn Forte apid_con.xport_phys = xport_phys;
536fcf3ce44SJohn Forte apid_con.dyncomp = dyncomp;
537fcf3ce44SJohn Forte apid_con.flags = flags;
538fcf3ce44SJohn Forte
539fcf3ce44SJohn Forte larg.apidp = &apid_con;
540fcf3ce44SJohn Forte
541fcf3ce44SJohn Forte /* Create the hba logid (also base component of logical ap_id) */
542fcf3ce44SJohn Forte ret = make_xport_logid(larg.apidp->xport_phys, &larg.xport_logp,
543fcf3ce44SJohn Forte &l_errno);
544fcf3ce44SJohn Forte if (ret != FPCFGA_OK) {
545fcf3ce44SJohn Forte cfga_err(errstring, l_errno, ERR_LIST, 0);
546fcf3ce44SJohn Forte S_FREE(larg.apidp->xport_phys);
547fcf3ce44SJohn Forte S_FREE(larg.apidp->dyncomp);
548fcf3ce44SJohn Forte return (FPCFGA_ERR);
549fcf3ce44SJohn Forte }
550fcf3ce44SJohn Forte
551fcf3ce44SJohn Forte assert(larg.xport_logp != NULL);
552fcf3ce44SJohn Forte
553fcf3ce44SJohn Forte larg.cmd = cmd;
554fcf3ce44SJohn Forte larg.xport_rstate = CFGA_STAT_NONE;
555fcf3ce44SJohn Forte
556fcf3ce44SJohn Forte if ((ret = findMatchingAdapterPort(larg.apidp->xport_phys, &handle,
557fcf3ce44SJohn Forte &portIndex, &portAttrs, errstring)) != FPCFGA_OK) {
558fcf3ce44SJohn Forte S_FREE(larg.xport_logp);
559fcf3ce44SJohn Forte S_FREE(larg.apidp->dyncomp);
560fcf3ce44SJohn Forte return (ret);
561fcf3ce44SJohn Forte }
562fcf3ce44SJohn Forte
563fcf3ce44SJohn Forte /*
564fcf3ce44SJohn Forte * If stating a specific device, we will do limited stat on fca port.
565fcf3ce44SJohn Forte * otherwise full stat on fca part is required.
566fcf3ce44SJohn Forte * If stating a specific device we don't know if it exists or is
567fcf3ce44SJohn Forte * configured yet. larg.ret is set to apid noexist for do_stat_dev.
568fcf3ce44SJohn Forte * otherwise larg.ret is set to ok initially.
569fcf3ce44SJohn Forte */
570fcf3ce44SJohn Forte if (larg.cmd == FPCFGA_STAT_FC_DEV) {
571fcf3ce44SJohn Forte limited_stat = 1; /* for do_stat_fca_xport */
572fcf3ce44SJohn Forte larg.ret = FPCFGA_APID_NOEXIST; /* for stat_fc_dev */
573fcf3ce44SJohn Forte } else {
574fcf3ce44SJohn Forte limited_stat = 0; /* for do_stat_fca_xport */
575fcf3ce44SJohn Forte larg.ret = FPCFGA_OK; /* for stat_fc_dev */
576fcf3ce44SJohn Forte }
577fcf3ce44SJohn Forte
578fcf3ce44SJohn Forte /* For all list commands, the fca port needs to be stat'ed */
579fcf3ce44SJohn Forte if ((ret = do_stat_fca_xport(&larg, limited_stat,
580fcf3ce44SJohn Forte portAttrs)) != FPCFGA_OK) {
581fcf3ce44SJohn Forte cfga_err(errstring, larg.l_errno, ERR_LIST, 0);
582fcf3ce44SJohn Forte list_free(&larg.listp);
583fcf3ce44SJohn Forte S_FREE(larg.xport_logp);
584fcf3ce44SJohn Forte S_FREE(larg.apidp->xport_phys);
585fcf3ce44SJohn Forte S_FREE(larg.apidp->dyncomp);
586fcf3ce44SJohn Forte HBA_CloseAdapter(handle);
587fcf3ce44SJohn Forte HBA_FreeLibrary();
588fcf3ce44SJohn Forte return (ret);
589fcf3ce44SJohn Forte }
590fcf3ce44SJohn Forte
591fcf3ce44SJohn Forte /*
592fcf3ce44SJohn Forte * If stat'ing a FCA port or ALL, we have the bus stat data at
593fcf3ce44SJohn Forte * this point.
594fcf3ce44SJohn Forte * Assume that the bus has no configured children.
595fcf3ce44SJohn Forte */
596fcf3ce44SJohn Forte larg.chld_config = CFGA_STAT_UNCONFIGURED;
597fcf3ce44SJohn Forte
598fcf3ce44SJohn Forte switch (larg.cmd) {
599fcf3ce44SJohn Forte case FPCFGA_STAT_FC_DEV:
600fcf3ce44SJohn Forte /* la_wwn_t has uchar_t raw_wwn[8] thus no need to free. */
601fcf3ce44SJohn Forte if (cvt_dyncomp_to_lawwn(larg.apidp->dyncomp, &pwwn) != 0) {
602fcf3ce44SJohn Forte cfga_err(errstring, 0, ERR_LIST, 0);
603fcf3ce44SJohn Forte list_free(&larg.listp);
604fcf3ce44SJohn Forte S_FREE(larg.xport_logp);
605fcf3ce44SJohn Forte S_FREE(larg.apidp->xport_phys);
606fcf3ce44SJohn Forte S_FREE(larg.apidp->dyncomp);
607fcf3ce44SJohn Forte HBA_CloseAdapter(handle);
608fcf3ce44SJohn Forte HBA_FreeLibrary();
609fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
610fcf3ce44SJohn Forte }
611fcf3ce44SJohn Forte /*
612fcf3ce44SJohn Forte * if the dyncomp exists on disco ports construct list_data
613fcf3ce44SJohn Forte * otherwise return FPCFGA_APID_NOEXIST.
614fcf3ce44SJohn Forte */
615fcf3ce44SJohn Forte retry = 0;
616fcf3ce44SJohn Forte do {
617fcf3ce44SJohn Forte status = getPortAttrsByWWN(handle,
618fcf3ce44SJohn Forte *((HBA_WWN *)(&pwwn)), &discPortAttrs);
619fcf3ce44SJohn Forte if (status == HBA_STATUS_ERROR_STALE_DATA) {
620fcf3ce44SJohn Forte /* get Port Attributes again after refresh. */
621fcf3ce44SJohn Forte HBA_RefreshInformation(handle);
622fcf3ce44SJohn Forte } else {
623fcf3ce44SJohn Forte break; /* either okay or some other error */
624fcf3ce44SJohn Forte }
625fcf3ce44SJohn Forte } while (retry++ < HBA_MAX_RETRIES);
626fcf3ce44SJohn Forte
627fcf3ce44SJohn Forte if (status == HBA_STATUS_OK) {
628fcf3ce44SJohn Forte /*
629fcf3ce44SJohn Forte * if dyncomp exists only in dev list
630fcf3ce44SJohn Forte * construct ldata_list and return.
631fcf3ce44SJohn Forte * otherwise continue to stat on dev tree with
632fcf3ce44SJohn Forte * larg.ret set to access_ok which informs stat_fc_dev
633fcf3ce44SJohn Forte * the existence of device on dev_list.
634fcf3ce44SJohn Forte *
635fcf3ce44SJohn Forte * if path is null that guatantees the node is not
636fcf3ce44SJohn Forte * configured. if node is detached the path
637fcf3ce44SJohn Forte * is incomplete and not usable for further
638fcf3ce44SJohn Forte * operations like uscsi_inq so take care of it here.
639fcf3ce44SJohn Forte */
640fcf3ce44SJohn Forte status = HBA_ScsiInquiryV2(handle, portAttrs.PortWWN,
641fcf3ce44SJohn Forte discPortAttrs.PortWWN, lun, 0, 0,
642fcf3ce44SJohn Forte &inq, &inquirySize, &scsiStatus,
643fcf3ce44SJohn Forte &sense, &senseSize);
644fcf3ce44SJohn Forte if (status == HBA_STATUS_OK) {
645fcf3ce44SJohn Forte inq.inq_dtype = inq.inq_dtype & DTYPE_MASK;
646fcf3ce44SJohn Forte } else if (status == HBA_STATUS_ERROR_NOT_A_TARGET) {
647fcf3ce44SJohn Forte inq.inq_dtype = DTYPE_UNKNOWN;
648fcf3ce44SJohn Forte } else {
649fcf3ce44SJohn Forte inq.inq_dtype = ERR_INQ_DTYPE;
650fcf3ce44SJohn Forte }
651fcf3ce44SJohn Forte
652fcf3ce44SJohn Forte if (init_ldata_for_accessible_dev(larg.apidp->dyncomp,
653fcf3ce44SJohn Forte inq.inq_dtype, &larg) != FPCFGA_OK) {
654fcf3ce44SJohn Forte cfga_err(errstring, larg.l_errno,
655fcf3ce44SJohn Forte ERR_LIST, 0);
656fcf3ce44SJohn Forte list_free(&larg.listp);
657fcf3ce44SJohn Forte S_FREE(larg.xport_logp);
658fcf3ce44SJohn Forte S_FREE(larg.apidp->xport_phys);
659fcf3ce44SJohn Forte S_FREE(larg.apidp->dyncomp);
660fcf3ce44SJohn Forte HBA_CloseAdapter(handle);
661fcf3ce44SJohn Forte HBA_FreeLibrary();
662fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
663fcf3ce44SJohn Forte }
664fcf3ce44SJohn Forte if ((ret = get_accessible_FCP_dev_ldata(
665fcf3ce44SJohn Forte larg.apidp->dyncomp, &larg, &l_errno))
666fcf3ce44SJohn Forte != FPCFGA_OK) {
667fcf3ce44SJohn Forte cfga_err(errstring, larg.l_errno, ERR_LIST, 0);
668fcf3ce44SJohn Forte list_free(&larg.listp);
669fcf3ce44SJohn Forte S_FREE(larg.xport_logp);
670fcf3ce44SJohn Forte S_FREE(larg.apidp->xport_phys);
671fcf3ce44SJohn Forte S_FREE(larg.apidp->dyncomp);
672fcf3ce44SJohn Forte HBA_CloseAdapter(handle);
673fcf3ce44SJohn Forte HBA_FreeLibrary();
674fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
675fcf3ce44SJohn Forte } else {
676fcf3ce44SJohn Forte /* continue to stat dev with access okay. */
677fcf3ce44SJohn Forte larg.ret = FPCFGA_ACCESS_OK;
678fcf3ce44SJohn Forte }
679fcf3ce44SJohn Forte } else if (status == HBA_STATUS_ERROR_ILLEGAL_WWN) {
680fcf3ce44SJohn Forte /*
681fcf3ce44SJohn Forte * path indicates if the node exists in dev tree.
682fcf3ce44SJohn Forte * if not found in dev tree return apid no exist.
683fcf3ce44SJohn Forte * otherwise continue to stat with larg.ret set to
684fcf3ce44SJohn Forte * apid_noexist.
685fcf3ce44SJohn Forte */
686fcf3ce44SJohn Forte if (larg.apidp->lunlist == NULL) {
687fcf3ce44SJohn Forte list_free(&larg.listp);
688fcf3ce44SJohn Forte S_FREE(larg.xport_logp);
689fcf3ce44SJohn Forte HBA_CloseAdapter(handle);
690fcf3ce44SJohn Forte HBA_FreeLibrary();
691fcf3ce44SJohn Forte return (FPCFGA_APID_NOEXIST);
692fcf3ce44SJohn Forte }
693fcf3ce44SJohn Forte } else { /* not found or any error */
694fcf3ce44SJohn Forte /*
695fcf3ce44SJohn Forte * continue to stat dev with larg.ret set to
696fcf3ce44SJohn Forte * apid_noexist.
697fcf3ce44SJohn Forte */
698fcf3ce44SJohn Forte larg.ret = FPCFGA_APID_NOEXIST;
699fcf3ce44SJohn Forte }
700fcf3ce44SJohn Forte break;
701fcf3ce44SJohn Forte case FPCFGA_STAT_ALL:
702fcf3ce44SJohn Forte /*
703fcf3ce44SJohn Forte * for each dev in disco ports, create a ldata_list element.
704fcf3ce44SJohn Forte * if if no disco ports found, continue to stat on devinfo tree
705fcf3ce44SJohn Forte * to see if any node exist on the fca port.
706fcf3ce44SJohn Forte */
707fcf3ce44SJohn Forte for (discIndex = 0;
708fcf3ce44SJohn Forte discIndex < portAttrs.NumberofDiscoveredPorts;
709fcf3ce44SJohn Forte discIndex++) {
710fcf3ce44SJohn Forte if (getDiscPortAttrs(handle, portIndex,
711fcf3ce44SJohn Forte discIndex, &discPortAttrs)) {
712fcf3ce44SJohn Forte /* Move on to the next target */
713fcf3ce44SJohn Forte continue;
714fcf3ce44SJohn Forte }
715fcf3ce44SJohn Forte memcpy(&pwwn, &discPortAttrs.PortWWN, sizeof (la_wwn_t));
716fcf3ce44SJohn Forte cvt_lawwn_to_dyncomp(&pwwn, &dyncomp, &l_errno);
717fcf3ce44SJohn Forte if (dyncomp == NULL) {
718fcf3ce44SJohn Forte cfga_err(errstring, l_errno, ERR_LIST, 0);
719fcf3ce44SJohn Forte list_free(&larg.listp);
720fcf3ce44SJohn Forte S_FREE(larg.xport_logp);
721fcf3ce44SJohn Forte S_FREE(larg.apidp->xport_phys);
722fcf3ce44SJohn Forte S_FREE(larg.apidp->dyncomp);
723fcf3ce44SJohn Forte HBA_CloseAdapter(handle);
724fcf3ce44SJohn Forte HBA_FreeLibrary();
725fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
726fcf3ce44SJohn Forte }
727fcf3ce44SJohn Forte status = HBA_ScsiInquiryV2(handle, portAttrs.PortWWN,
728fcf3ce44SJohn Forte discPortAttrs.PortWWN, lun, 0, 0,
729fcf3ce44SJohn Forte &inq, &inquirySize, &scsiStatus,
730fcf3ce44SJohn Forte &sense, &senseSize);
731fcf3ce44SJohn Forte if (status == HBA_STATUS_OK) {
732fcf3ce44SJohn Forte inq.inq_dtype = inq.inq_dtype & DTYPE_MASK;
733fcf3ce44SJohn Forte } else if (status == HBA_STATUS_ERROR_NOT_A_TARGET) {
734fcf3ce44SJohn Forte inq.inq_dtype = DTYPE_UNKNOWN;
735fcf3ce44SJohn Forte } else {
736fcf3ce44SJohn Forte inq.inq_dtype = ERR_INQ_DTYPE;
737fcf3ce44SJohn Forte }
738fcf3ce44SJohn Forte if ((ret = init_ldata_for_accessible_dev(
739fcf3ce44SJohn Forte dyncomp, inq.inq_dtype, &larg)) != FPCFGA_OK) {
740fcf3ce44SJohn Forte S_FREE(dyncomp);
741fcf3ce44SJohn Forte cfga_err(errstring, larg.l_errno, ERR_LIST, 0);
742fcf3ce44SJohn Forte list_free(&larg.listp);
743fcf3ce44SJohn Forte S_FREE(larg.xport_logp);
744fcf3ce44SJohn Forte S_FREE(larg.apidp->xport_phys);
745fcf3ce44SJohn Forte S_FREE(larg.apidp->dyncomp);
746fcf3ce44SJohn Forte HBA_CloseAdapter(handle);
747fcf3ce44SJohn Forte HBA_FreeLibrary();
748fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
749fcf3ce44SJohn Forte }
750fcf3ce44SJohn Forte if ((ret = get_accessible_FCP_dev_ldata(
751fcf3ce44SJohn Forte dyncomp, &larg, &l_errno)) != FPCFGA_OK) {
752fcf3ce44SJohn Forte S_FREE(dyncomp);
753fcf3ce44SJohn Forte cfga_err(errstring, larg.l_errno, ERR_LIST, 0);
754fcf3ce44SJohn Forte list_free(&larg.listp);
755fcf3ce44SJohn Forte S_FREE(larg.xport_logp);
756fcf3ce44SJohn Forte S_FREE(larg.apidp->xport_phys);
757fcf3ce44SJohn Forte S_FREE(larg.apidp->dyncomp);
758fcf3ce44SJohn Forte HBA_CloseAdapter(handle);
759fcf3ce44SJohn Forte HBA_FreeLibrary();
760fcf3ce44SJohn Forte return (ret);
761fcf3ce44SJohn Forte }
762fcf3ce44SJohn Forte S_FREE(dyncomp);
763fcf3ce44SJohn Forte }
764fcf3ce44SJohn Forte break;
765fcf3ce44SJohn Forte /* default: continue */
766fcf3ce44SJohn Forte }
767fcf3ce44SJohn Forte
768fcf3ce44SJohn Forte /* we need to stat at least 1 device for all commands */
769fcf3ce44SJohn Forte if ((larg.apidp->flags & FLAG_DEVINFO_FORCE) == FLAG_DEVINFO_FORCE) {
770fcf3ce44SJohn Forte walkarg.flags = FLAG_DEVINFO_FORCE;
771fcf3ce44SJohn Forte } else {
772fcf3ce44SJohn Forte walkarg.flags = 0;
773fcf3ce44SJohn Forte }
774fcf3ce44SJohn Forte
775fcf3ce44SJohn Forte walkarg.flags |= FLAG_PATH_INFO_WALK;
776fcf3ce44SJohn Forte walkarg.walkmode.node_args.flags = DI_WALK_CLDFIRST;
777fcf3ce44SJohn Forte walkarg.walkmode.node_args.fcn = stat_FCP_dev;
778fcf3ce44SJohn Forte
779fcf3ce44SJohn Forte /*
780fcf3ce44SJohn Forte * Subtree is ALWAYS rooted at the HBA (not at the device) as
781fcf3ce44SJohn Forte * otherwise deadlock may occur if bus is disconnected.
782fcf3ce44SJohn Forte *
783fcf3ce44SJohn Forte * DINFOPROP was sufficient on apidp->xport_phys prior to the support
784fcf3ce44SJohn Forte * on scsi_vhci child node. In order to get the link between
785fcf3ce44SJohn Forte * scsi_vhci node and path info node the snap shot of the
786fcf3ce44SJohn Forte * the whole device tree is required with DINFOCPYALL | DINFOPATH flag.
787fcf3ce44SJohn Forte */
788fcf3ce44SJohn Forte ret = walk_tree(larg.apidp->xport_phys, &larg, DINFOCPYALL | DINFOPATH,
789fcf3ce44SJohn Forte &walkarg, FPCFGA_WALK_NODE, &larg.l_errno);
790fcf3ce44SJohn Forte
791fcf3ce44SJohn Forte /*
792fcf3ce44SJohn Forte * ret from walk_tree is either FPCFGA_OK or FPCFGA_ERR.
793fcf3ce44SJohn Forte * larg.ret is used to detect other errors. Make sure larg.ret
794fcf3ce44SJohn Forte * is set to a correct error.
795fcf3ce44SJohn Forte */
796fcf3ce44SJohn Forte if (ret != FPCFGA_OK || (ret = larg.ret) != FPCFGA_OK) {
797fcf3ce44SJohn Forte if (ret != FPCFGA_APID_NOEXIST) {
798fcf3ce44SJohn Forte cfga_err(errstring, larg.l_errno, ERR_LIST, 0);
799fcf3ce44SJohn Forte }
800fcf3ce44SJohn Forte /* if larg.ret = FPCFGA_APID_NOEXIST return. */
801fcf3ce44SJohn Forte list_free(&larg.listp);
802fcf3ce44SJohn Forte S_FREE(larg.xport_logp);
803fcf3ce44SJohn Forte S_FREE(larg.apidp->xport_phys);
804fcf3ce44SJohn Forte S_FREE(larg.apidp->dyncomp);
805fcf3ce44SJohn Forte HBA_CloseAdapter(handle);
806fcf3ce44SJohn Forte HBA_FreeLibrary();
807fcf3ce44SJohn Forte return (ret);
808fcf3ce44SJohn Forte }
809fcf3ce44SJohn Forte
810fcf3ce44SJohn Forte assert(larg.listp != NULL);
811fcf3ce44SJohn Forte
812fcf3ce44SJohn Forte n = 0;
813fcf3ce44SJohn Forte ret = postprocess_list_data(larg.listp, cmd, larg.chld_config, &n,
814fcf3ce44SJohn Forte flags);
815fcf3ce44SJohn Forte if (ret != FPCFGA_OK) {
816fcf3ce44SJohn Forte cfga_err(errstring, 0, ERR_LIST, 0);
817fcf3ce44SJohn Forte list_free(&larg.listp);
818fcf3ce44SJohn Forte S_FREE(larg.xport_logp);
819fcf3ce44SJohn Forte S_FREE(larg.apidp->xport_phys);
820fcf3ce44SJohn Forte S_FREE(larg.apidp->dyncomp);
821fcf3ce44SJohn Forte HBA_CloseAdapter(handle);
822fcf3ce44SJohn Forte HBA_FreeLibrary();
823fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
824fcf3ce44SJohn Forte }
825fcf3ce44SJohn Forte
826fcf3ce44SJohn Forte *nelemp = n;
827fcf3ce44SJohn Forte *llpp = larg.listp;
828fcf3ce44SJohn Forte ret = FPCFGA_OK;
829fcf3ce44SJohn Forte S_FREE(larg.xport_logp);
830fcf3ce44SJohn Forte S_FREE(larg.apidp->xport_phys);
831fcf3ce44SJohn Forte S_FREE(larg.apidp->dyncomp);
832fcf3ce44SJohn Forte HBA_CloseAdapter(handle);
833fcf3ce44SJohn Forte HBA_FreeLibrary();
834fcf3ce44SJohn Forte return (FPCFGA_OK);
835fcf3ce44SJohn Forte }
836fcf3ce44SJohn Forte
837fcf3ce44SJohn Forte /*
838fcf3ce44SJohn Forte * This routine returns initialize struct fcp_ioctl.
839fcf3ce44SJohn Forte */
840fcf3ce44SJohn Forte static void
init_fcp_scsi_cmd(struct fcp_scsi_cmd * fscsi,uchar_t * lun_num,la_wwn_t * pwwn,void * scmdbuf,size_t scmdbuf_len,void * respbuf,size_t respbuf_len,void * sensebuf,size_t sensebuf_len)841fcf3ce44SJohn Forte init_fcp_scsi_cmd(
842fcf3ce44SJohn Forte struct fcp_scsi_cmd *fscsi,
843fcf3ce44SJohn Forte uchar_t *lun_num,
844fcf3ce44SJohn Forte la_wwn_t *pwwn,
845fcf3ce44SJohn Forte void *scmdbuf,
846fcf3ce44SJohn Forte size_t scmdbuf_len,
847fcf3ce44SJohn Forte void *respbuf,
848fcf3ce44SJohn Forte size_t respbuf_len,
849fcf3ce44SJohn Forte void *sensebuf,
850fcf3ce44SJohn Forte size_t sensebuf_len)
851fcf3ce44SJohn Forte {
852fcf3ce44SJohn Forte memset(fscsi, 0, sizeof (struct fcp_scsi_cmd));
853fcf3ce44SJohn Forte memset(scmdbuf, 0, scmdbuf_len);
854fcf3ce44SJohn Forte memcpy(fscsi->scsi_fc_pwwn.raw_wwn, pwwn, sizeof (u_longlong_t));
855fcf3ce44SJohn Forte fscsi->scsi_fc_rspcode = 0;
856fcf3ce44SJohn Forte fscsi->scsi_flags = FCP_SCSI_READ;
857fcf3ce44SJohn Forte fscsi->scsi_timeout = FCP_SCSI_CMD_TIMEOUT; /* second */
858fcf3ce44SJohn Forte fscsi->scsi_cdbbufaddr = (caddr_t)scmdbuf;
859fcf3ce44SJohn Forte fscsi->scsi_cdblen = scmdbuf_len;
860fcf3ce44SJohn Forte fscsi->scsi_bufaddr = (caddr_t)respbuf;
861fcf3ce44SJohn Forte fscsi->scsi_buflen = respbuf_len;
862fcf3ce44SJohn Forte fscsi->scsi_bufresid = 0;
863fcf3ce44SJohn Forte fscsi->scsi_bufstatus = 0;
864fcf3ce44SJohn Forte fscsi->scsi_rqbufaddr = (caddr_t)sensebuf;
865fcf3ce44SJohn Forte fscsi->scsi_rqlen = sensebuf_len;
866fcf3ce44SJohn Forte fscsi->scsi_rqresid = 0;
867fcf3ce44SJohn Forte memcpy(&fscsi->scsi_lun, lun_num, sizeof (fscsi->scsi_lun));
868fcf3ce44SJohn Forte }
869fcf3ce44SJohn Forte
870fcf3ce44SJohn Forte /*
871fcf3ce44SJohn Forte * This routine returns issues FCP_TGT_SEND_SCSI
872fcf3ce44SJohn Forte */
873fcf3ce44SJohn Forte static fpcfga_ret_t
issue_fcp_scsi_cmd(const char * xport_phys,struct fcp_scsi_cmd * fscsi,int * l_errnop)874fcf3ce44SJohn Forte issue_fcp_scsi_cmd(
875fcf3ce44SJohn Forte const char *xport_phys,
876fcf3ce44SJohn Forte struct fcp_scsi_cmd *fscsi,
877fcf3ce44SJohn Forte int *l_errnop)
878fcf3ce44SJohn Forte {
879fcf3ce44SJohn Forte struct stat stbuf;
880fcf3ce44SJohn Forte int fcp_fd, retry, rv;
881fcf3ce44SJohn Forte
882fcf3ce44SJohn Forte if (stat(xport_phys, &stbuf) < 0) {
883fcf3ce44SJohn Forte *l_errnop = errno;
884fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
885fcf3ce44SJohn Forte }
886fcf3ce44SJohn Forte
887fcf3ce44SJohn Forte fscsi->scsi_fc_port_num = (uint32_t)minor(stbuf.st_rdev);
888fcf3ce44SJohn Forte fcp_fd = open(FCP_PATH, O_RDONLY | O_NDELAY);
889fcf3ce44SJohn Forte retry = 0;
890fcf3ce44SJohn Forte while (fcp_fd < 0 && retry++ < OPEN_RETRY_COUNT && (
891fcf3ce44SJohn Forte errno == EBUSY || errno == EAGAIN)) {
892fcf3ce44SJohn Forte (void) usleep(OPEN_RETRY_INTERVAL);
893fcf3ce44SJohn Forte fcp_fd = open(FCP_PATH, O_RDONLY|O_NDELAY);
894fcf3ce44SJohn Forte }
895fcf3ce44SJohn Forte if (fcp_fd < 0) {
896fcf3ce44SJohn Forte *l_errnop = errno;
897fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
898fcf3ce44SJohn Forte }
899fcf3ce44SJohn Forte
900fcf3ce44SJohn Forte rv = ioctl(fcp_fd, FCP_TGT_SEND_SCSI, fscsi);
901fcf3ce44SJohn Forte retry = 0;
902fcf3ce44SJohn Forte while ((rv != 0 && retry++ < IOCTL_RETRY_COUNT &&
903fcf3ce44SJohn Forte (errno == EBUSY || errno == EAGAIN)) ||
904fcf3ce44SJohn Forte (retry++ < IOCTL_RETRY_COUNT &&
905fcf3ce44SJohn Forte ((uchar_t)fscsi->scsi_bufstatus & STATUS_MASK)
906fcf3ce44SJohn Forte == STATUS_BUSY)) {
907fcf3ce44SJohn Forte (void) usleep(IOCTL_RETRY_INTERVAL);
908fcf3ce44SJohn Forte rv = ioctl(fcp_fd, FCP_TGT_SEND_SCSI, fscsi);
909fcf3ce44SJohn Forte }
910fcf3ce44SJohn Forte close(fcp_fd);
911fcf3ce44SJohn Forte
912fcf3ce44SJohn Forte if (fscsi->scsi_fc_status == FC_DEVICE_NOT_TGT) {
913fcf3ce44SJohn Forte return (FPCFGA_FCP_SEND_SCSI_DEV_NOT_TGT);
914fcf3ce44SJohn Forte } else if (rv != 0 || fscsi->scsi_bufstatus != 0) {
915fcf3ce44SJohn Forte *l_errnop = errno;
916fcf3ce44SJohn Forte return (FPCFGA_FCP_TGT_SEND_SCSI_FAILED);
917fcf3ce44SJohn Forte }
918fcf3ce44SJohn Forte return (FPCFGA_OK);
919fcf3ce44SJohn Forte }
920fcf3ce44SJohn Forte
921fcf3ce44SJohn Forte /*
922fcf3ce44SJohn Forte * This routine returns standard inq data for
923fcf3ce44SJohn Forte * a target represented by dyncomp.
924fcf3ce44SJohn Forte *
925fcf3ce44SJohn Forte * Calls FCP passthru ioctl FCP_TGT_SEND_SCSI to get inquiry data.
926fcf3ce44SJohn Forte *
927fcf3ce44SJohn Forte * Caller should free the *inq_buf.
928fcf3ce44SJohn Forte */
929fcf3ce44SJohn Forte static fpcfga_ret_t
get_standard_inq_data(const char * xport_phys,const char * dyncomp,uchar_t * lun_num,struct scsi_inquiry ** inq_buf,int * l_errnop)930fcf3ce44SJohn Forte get_standard_inq_data(
931fcf3ce44SJohn Forte const char *xport_phys,
932fcf3ce44SJohn Forte const char *dyncomp,
933fcf3ce44SJohn Forte uchar_t *lun_num,
934fcf3ce44SJohn Forte struct scsi_inquiry **inq_buf,
935fcf3ce44SJohn Forte int *l_errnop)
936fcf3ce44SJohn Forte {
937fcf3ce44SJohn Forte struct fcp_scsi_cmd fscsi;
938fcf3ce44SJohn Forte struct scsi_extended_sense sensebuf;
939fcf3ce44SJohn Forte union scsi_cdb scsi_inq_req;
940fcf3ce44SJohn Forte la_wwn_t pwwn;
941fcf3ce44SJohn Forte int alloc_len;
942fcf3ce44SJohn Forte fpcfga_ret_t ret;
943fcf3ce44SJohn Forte
944fcf3ce44SJohn Forte
945fcf3ce44SJohn Forte alloc_len = sizeof (struct scsi_inquiry);
946fcf3ce44SJohn Forte if ((*inq_buf = (struct scsi_inquiry *)calloc(1, alloc_len)) == NULL) {
947fcf3ce44SJohn Forte *l_errnop = errno;
948fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
949fcf3ce44SJohn Forte }
950fcf3ce44SJohn Forte
951fcf3ce44SJohn Forte if (cvt_dyncomp_to_lawwn(dyncomp, &pwwn) != 0) {
952fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
953fcf3ce44SJohn Forte }
954fcf3ce44SJohn Forte
955fcf3ce44SJohn Forte init_fcp_scsi_cmd(&fscsi, lun_num, &pwwn, &scsi_inq_req,
956fcf3ce44SJohn Forte sizeof (scsi_inq_req), *inq_buf, alloc_len, &sensebuf,
957fcf3ce44SJohn Forte sizeof (struct scsi_extended_sense));
958fcf3ce44SJohn Forte scsi_inq_req.scc_cmd = SCMD_INQUIRY;
959fcf3ce44SJohn Forte scsi_inq_req.g0_count0 = sizeof (struct scsi_inquiry);
960fcf3ce44SJohn Forte
961fcf3ce44SJohn Forte if ((ret = issue_fcp_scsi_cmd(xport_phys, &fscsi, l_errnop))
962fcf3ce44SJohn Forte != FPCFGA_OK) {
963fcf3ce44SJohn Forte S_FREE(*inq_buf);
964fcf3ce44SJohn Forte return (ret);
965fcf3ce44SJohn Forte }
966fcf3ce44SJohn Forte
967fcf3ce44SJohn Forte return (FPCFGA_OK);
968fcf3ce44SJohn Forte }
969fcf3ce44SJohn Forte
970fcf3ce44SJohn Forte /*
971fcf3ce44SJohn Forte * This routine returns report lun data and number of luns found
972fcf3ce44SJohn Forte * on a target represented by dyncomp.
973fcf3ce44SJohn Forte *
974fcf3ce44SJohn Forte * Calls FCP passthru ioctl FCP_TGT_SEND_SCSI to get report lun data.
975fcf3ce44SJohn Forte *
976fcf3ce44SJohn Forte * Caller should free the *resp_buf when FPCFGA_OK is returned.
977fcf3ce44SJohn Forte */
978fcf3ce44SJohn Forte fpcfga_ret_t
get_report_lun_data(const char * xport_phys,const char * dyncomp,int * num_luns,report_lun_resp_t ** resp_buf,struct scsi_extended_sense * sensebuf,int * l_errnop)979fcf3ce44SJohn Forte get_report_lun_data(
980fcf3ce44SJohn Forte const char *xport_phys,
981fcf3ce44SJohn Forte const char *dyncomp,
982fcf3ce44SJohn Forte int *num_luns,
983fcf3ce44SJohn Forte report_lun_resp_t **resp_buf,
984fcf3ce44SJohn Forte struct scsi_extended_sense *sensebuf,
985fcf3ce44SJohn Forte int *l_errnop)
986fcf3ce44SJohn Forte {
987fcf3ce44SJohn Forte struct fcp_scsi_cmd fscsi;
988fcf3ce44SJohn Forte union scsi_cdb scsi_rl_req;
989fcf3ce44SJohn Forte la_wwn_t pwwn;
990fcf3ce44SJohn Forte int alloc_len;
991fcf3ce44SJohn Forte fpcfga_ret_t ret;
992fcf3ce44SJohn Forte uchar_t lun_data[SAM_LUN_SIZE];
993fcf3ce44SJohn Forte
994fcf3ce44SJohn Forte alloc_len = sizeof (struct report_lun_resp);
995fcf3ce44SJohn Forte if ((*resp_buf = (report_lun_resp_t *)calloc(1, alloc_len)) == NULL) {
996fcf3ce44SJohn Forte *l_errnop = errno;
997fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
998fcf3ce44SJohn Forte }
999fcf3ce44SJohn Forte
1000fcf3ce44SJohn Forte if (cvt_dyncomp_to_lawwn(dyncomp, &pwwn) != 0) {
1001fcf3ce44SJohn Forte S_FREE(*resp_buf);
1002fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
1003fcf3ce44SJohn Forte }
1004fcf3ce44SJohn Forte
1005fcf3ce44SJohn Forte /* sending to LUN 0 so initializing lun_data buffer to be 0 */
1006fcf3ce44SJohn Forte memset(lun_data, 0, sizeof (lun_data));
1007fcf3ce44SJohn Forte init_fcp_scsi_cmd(&fscsi, lun_data, &pwwn, &scsi_rl_req,
1008fcf3ce44SJohn Forte sizeof (scsi_rl_req), *resp_buf, alloc_len, sensebuf,
1009fcf3ce44SJohn Forte sizeof (struct scsi_extended_sense));
1010fcf3ce44SJohn Forte scsi_rl_req.scc_cmd = FP_SCMD_REPORT_LUN;
1011fcf3ce44SJohn Forte FORMG5COUNT(&scsi_rl_req, alloc_len);
1012fcf3ce44SJohn Forte
1013fcf3ce44SJohn Forte if ((ret = issue_fcp_scsi_cmd(xport_phys, &fscsi, l_errnop))
1014fcf3ce44SJohn Forte != FPCFGA_OK) {
1015fcf3ce44SJohn Forte S_FREE(*resp_buf);
1016fcf3ce44SJohn Forte return (ret);
1017fcf3ce44SJohn Forte }
1018fcf3ce44SJohn Forte
1019fcf3ce44SJohn Forte if (ntohl((*resp_buf)->num_lun) >
1020fcf3ce44SJohn Forte (sizeof (struct report_lun_resp) - REPORT_LUN_HDR_SIZE)) {
1021fcf3ce44SJohn Forte alloc_len = (*resp_buf)->num_lun + REPORT_LUN_HDR_SIZE;
1022fcf3ce44SJohn Forte S_FREE(*resp_buf);
1023fcf3ce44SJohn Forte if ((*resp_buf = (report_lun_resp_t *)calloc(1, alloc_len))
1024fcf3ce44SJohn Forte == NULL) {
1025fcf3ce44SJohn Forte *l_errnop = errno;
1026fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
1027fcf3ce44SJohn Forte }
1028fcf3ce44SJohn Forte (void) memset((char *)*resp_buf, 0, alloc_len);
1029fcf3ce44SJohn Forte FORMG5COUNT(&scsi_rl_req, alloc_len);
1030fcf3ce44SJohn Forte
1031fcf3ce44SJohn Forte fscsi.scsi_bufaddr = (caddr_t)*resp_buf;
1032fcf3ce44SJohn Forte fscsi.scsi_buflen = alloc_len;
1033fcf3ce44SJohn Forte
1034fcf3ce44SJohn Forte if ((ret = issue_fcp_scsi_cmd(xport_phys, &fscsi, l_errnop))
1035fcf3ce44SJohn Forte != FPCFGA_OK) {
1036fcf3ce44SJohn Forte S_FREE(*resp_buf);
1037fcf3ce44SJohn Forte return (ret);
1038fcf3ce44SJohn Forte }
1039fcf3ce44SJohn Forte }
1040fcf3ce44SJohn Forte
1041fcf3ce44SJohn Forte /* num_lun represent number of luns * 8. */
1042fcf3ce44SJohn Forte *num_luns = ntohl((*resp_buf)->num_lun) >> 3;
1043fcf3ce44SJohn Forte
1044fcf3ce44SJohn Forte return (FPCFGA_OK);
1045fcf3ce44SJohn Forte }
1046fcf3ce44SJohn Forte
1047fcf3ce44SJohn Forte /*
1048fcf3ce44SJohn Forte * Routine for consturct ldata list for each FCP SCSI LUN device
1049fcf3ce44SJohn Forte * for a discovered target device.
1050fcf3ce44SJohn Forte * It calls get_report_lun_data to get report lun data and
1051fcf3ce44SJohn Forte * construct ldata list per each lun.
1052fcf3ce44SJohn Forte *
1053fcf3ce44SJohn Forte * It is called only when show_FCP_dev option is given.
1054fcf3ce44SJohn Forte *
1055fcf3ce44SJohn Forte * Overall algorithm:
1056fcf3ce44SJohn Forte * Get the report lun data thru FCP passthru ioctl.
1057fcf3ce44SJohn Forte * Call init_ldata_for_accessible_FCP_dev to process the report LUN data.
1058fcf3ce44SJohn Forte * For each LUN found standard inquiry is issued to get device type.
1059fcf3ce44SJohn Forte */
1060fcf3ce44SJohn Forte static fpcfga_ret_t
get_accessible_FCP_dev_ldata(const char * dyncomp,fpcfga_list_t * lap,int * l_errnop)1061fcf3ce44SJohn Forte get_accessible_FCP_dev_ldata(
1062fcf3ce44SJohn Forte const char *dyncomp,
1063fcf3ce44SJohn Forte fpcfga_list_t *lap,
1064fcf3ce44SJohn Forte int *l_errnop)
1065fcf3ce44SJohn Forte {
1066fcf3ce44SJohn Forte report_lun_resp_t *resp_buf;
1067fcf3ce44SJohn Forte struct scsi_extended_sense sense;
1068fcf3ce44SJohn Forte int num_luns;
1069fcf3ce44SJohn Forte fpcfga_ret_t ret;
1070fcf3ce44SJohn Forte
1071fcf3ce44SJohn Forte memset(&sense, 0, sizeof (sense));
1072fcf3ce44SJohn Forte if ((ret = get_report_lun_data(lap->apidp->xport_phys, dyncomp,
1073fcf3ce44SJohn Forte &num_luns, &resp_buf, &sense, l_errnop)) != FPCFGA_OK) {
1074fcf3ce44SJohn Forte /*
1075fcf3ce44SJohn Forte * when report lun data fails then return FPCFGA_OK thus
1076fcf3ce44SJohn Forte * keep the ldata for the target which is acquired previously.
1077fcf3ce44SJohn Forte * For remote hba node this will be normal.
1078fcf3ce44SJohn Forte * For a target error may already be detected through
1079fcf3ce44SJohn Forte * FCP_TGT_INQ.
1080fcf3ce44SJohn Forte */
1081fcf3ce44SJohn Forte if ((ret == FPCFGA_FCP_TGT_SEND_SCSI_FAILED) ||
1082fcf3ce44SJohn Forte (ret == FPCFGA_FCP_SEND_SCSI_DEV_NOT_TGT)) {
1083fcf3ce44SJohn Forte ret = FPCFGA_OK;
1084fcf3ce44SJohn Forte }
1085fcf3ce44SJohn Forte return (ret);
1086fcf3ce44SJohn Forte }
1087fcf3ce44SJohn Forte
1088fcf3ce44SJohn Forte if (num_luns > 0) {
1089fcf3ce44SJohn Forte ret = init_ldata_for_accessible_FCP_dev(
1090fcf3ce44SJohn Forte dyncomp, num_luns, resp_buf, lap, l_errnop);
1091fcf3ce44SJohn Forte } else {
1092fcf3ce44SJohn Forte /*
1093fcf3ce44SJohn Forte * proceed with to stat if no lun found.
1094fcf3ce44SJohn Forte * This will make the target apid will be kept.
1095fcf3ce44SJohn Forte */
1096fcf3ce44SJohn Forte ret = FPCFGA_OK;
1097fcf3ce44SJohn Forte }
1098fcf3ce44SJohn Forte
1099fcf3ce44SJohn Forte S_FREE(resp_buf);
1100fcf3ce44SJohn Forte return (ret);
1101fcf3ce44SJohn Forte }
1102fcf3ce44SJohn Forte
1103fcf3ce44SJohn Forte /*
1104fcf3ce44SJohn Forte * Routine for checking validity of ldata list based on input argumemnt.
1105fcf3ce44SJohn Forte * Set the occupant state of hba port if the list is valid.
1106fcf3ce44SJohn Forte */
1107fcf3ce44SJohn Forte static fpcfga_ret_t
postprocess_list_data(const ldata_list_t * listp,fpcfga_cmd_t cmd,cfga_stat_t chld_config,int * np,uint_t flags)1108fcf3ce44SJohn Forte postprocess_list_data(
1109fcf3ce44SJohn Forte const ldata_list_t *listp,
1110fcf3ce44SJohn Forte fpcfga_cmd_t cmd,
1111fcf3ce44SJohn Forte cfga_stat_t chld_config,
1112fcf3ce44SJohn Forte int *np,
1113fcf3ce44SJohn Forte uint_t flags)
1114fcf3ce44SJohn Forte {
1115fcf3ce44SJohn Forte ldata_list_t *tmplp = NULL;
1116fcf3ce44SJohn Forte cfga_list_data_t *xport_ldatap = NULL;
1117fcf3ce44SJohn Forte int i;
1118fcf3ce44SJohn Forte
1119fcf3ce44SJohn Forte
1120fcf3ce44SJohn Forte *np = 0;
1121fcf3ce44SJohn Forte
1122fcf3ce44SJohn Forte if (listp == NULL) {
1123fcf3ce44SJohn Forte return (FPCFGA_ERR);
1124fcf3ce44SJohn Forte }
1125fcf3ce44SJohn Forte
1126fcf3ce44SJohn Forte tmplp = (ldata_list_t *)listp;
1127fcf3ce44SJohn Forte for (i = 0; tmplp != NULL; tmplp = tmplp->next) {
1128fcf3ce44SJohn Forte i++;
1129fcf3ce44SJohn Forte if (GET_DYN(tmplp->ldata.ap_phys_id) == NULL) {
1130fcf3ce44SJohn Forte /* A bus stat data */
1131fcf3ce44SJohn Forte assert(GET_DYN(tmplp->ldata.ap_log_id) == NULL);
1132fcf3ce44SJohn Forte xport_ldatap = &tmplp->ldata;
1133fcf3ce44SJohn Forte #ifdef DEBUG
1134fcf3ce44SJohn Forte } else {
1135fcf3ce44SJohn Forte assert(GET_DYN(tmplp->ldata.ap_log_id) != NULL);
1136fcf3ce44SJohn Forte #endif
1137fcf3ce44SJohn Forte }
1138fcf3ce44SJohn Forte }
1139fcf3ce44SJohn Forte
1140fcf3ce44SJohn Forte switch (cmd) {
1141fcf3ce44SJohn Forte case FPCFGA_STAT_FC_DEV:
1142fcf3ce44SJohn Forte if ((flags & FLAG_FCP_DEV) == FLAG_FCP_DEV) {
1143fcf3ce44SJohn Forte if (i < 1 || xport_ldatap != NULL) {
1144fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
1145fcf3ce44SJohn Forte }
1146fcf3ce44SJohn Forte } else {
1147fcf3ce44SJohn Forte if (i != 1 || xport_ldatap != NULL) {
1148fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
1149fcf3ce44SJohn Forte }
1150fcf3ce44SJohn Forte }
1151fcf3ce44SJohn Forte break;
1152fcf3ce44SJohn Forte case FPCFGA_STAT_FCA_PORT:
1153fcf3ce44SJohn Forte if (i != 1 || xport_ldatap == NULL) {
1154fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
1155fcf3ce44SJohn Forte }
1156fcf3ce44SJohn Forte break;
1157fcf3ce44SJohn Forte case FPCFGA_STAT_ALL:
1158fcf3ce44SJohn Forte if (i < 1 || xport_ldatap == NULL) {
1159fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
1160fcf3ce44SJohn Forte }
1161fcf3ce44SJohn Forte break;
1162fcf3ce44SJohn Forte default:
1163fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
1164fcf3ce44SJohn Forte }
1165fcf3ce44SJohn Forte
1166fcf3ce44SJohn Forte *np = i;
1167fcf3ce44SJohn Forte
1168fcf3ce44SJohn Forte /* Fill in the occupant (child) state. */
1169fcf3ce44SJohn Forte if (xport_ldatap != NULL) {
1170fcf3ce44SJohn Forte xport_ldatap->ap_o_state = chld_config;
1171fcf3ce44SJohn Forte }
1172fcf3ce44SJohn Forte return (FPCFGA_OK);
1173fcf3ce44SJohn Forte }
1174fcf3ce44SJohn Forte
1175fcf3ce44SJohn Forte /*
1176fcf3ce44SJohn Forte * Routine for checking each target device found in device tree.
1177fcf3ce44SJohn Forte * When the matching port WWN dev is found from the accessble ldata list
1178fcf3ce44SJohn Forte * the target device is updated with configured ostate.
1179fcf3ce44SJohn Forte *
1180fcf3ce44SJohn Forte * Overall algorithm:
1181fcf3ce44SJohn Forte * Parse the device tree to find configured devices which matches with
1182fcf3ce44SJohn Forte * list argument. If cmd is stat on a specific target device it
1183fcf3ce44SJohn Forte * matches port WWN and continues to further processing. If cmd is
1184fcf3ce44SJohn Forte * stat on hba port all the device target under the hba are processed.
1185fcf3ce44SJohn Forte */
1186fcf3ce44SJohn Forte static int
stat_fc_dev(di_node_t node,void * arg)1187fcf3ce44SJohn Forte stat_fc_dev(di_node_t node, void *arg)
1188fcf3ce44SJohn Forte {
1189fcf3ce44SJohn Forte fpcfga_list_t *lap = NULL;
1190fcf3ce44SJohn Forte char *devfsp = NULL, *nodepath = NULL;
1191fcf3ce44SJohn Forte size_t len = 0;
1192fcf3ce44SJohn Forte int limited_stat = 0, match_minor, rv;
1193fcf3ce44SJohn Forte fpcfga_ret_t ret;
1194fcf3ce44SJohn Forte di_prop_t prop = DI_PROP_NIL;
1195fcf3ce44SJohn Forte uchar_t *port_wwn_data;
1196fcf3ce44SJohn Forte char port_wwn[WWN_SIZE*2+1];
1197fcf3ce44SJohn Forte int count;
1198fcf3ce44SJohn Forte
1199fcf3ce44SJohn Forte lap = (fpcfga_list_t *)arg;
1200fcf3ce44SJohn Forte
1201fcf3ce44SJohn Forte /*
1202fcf3ce44SJohn Forte * Skip partial nodes
1203fcf3ce44SJohn Forte *
1204fcf3ce44SJohn Forte * This checking is from the scsi plug-in and will be deleted for
1205fcf3ce44SJohn Forte * fp plug-in. The node will be processed for fp even if it is
1206fcf3ce44SJohn Forte * in driver detached state. From fp perspective the node is configured
1207fcf3ce44SJohn Forte * as long as the node is not in offline or down state.
1208fcf3ce44SJohn Forte * scsi plug-in considers the known state when it is offlined
1209fcf3ce44SJohn Forte * regradless of driver detached state or when it is not in driver
1210fcf3ce44SJohn Forte * detached state like normal state.
1211fcf3ce44SJohn Forte * If the node is only in driver detached state it is considered as
1212fcf3ce44SJohn Forte * unknown state.
1213fcf3ce44SJohn Forte *
1214fcf3ce44SJohn Forte * if (!known_state(node) && (lap->cmd != FPCFGA_STAT_FC_DEV)) {
1215fcf3ce44SJohn Forte * return (DI_WALK_CONTINUE);
1216fcf3ce44SJohn Forte *
1217fcf3ce44SJohn Forte */
1218fcf3ce44SJohn Forte
1219fcf3ce44SJohn Forte devfsp = di_devfs_path(node);
1220fcf3ce44SJohn Forte if (devfsp == NULL) {
1221fcf3ce44SJohn Forte rv = DI_WALK_CONTINUE;
1222fcf3ce44SJohn Forte goto out;
1223fcf3ce44SJohn Forte }
1224fcf3ce44SJohn Forte
1225fcf3ce44SJohn Forte len = strlen(DEVICES_DIR) + strlen(devfsp) + 1;
1226fcf3ce44SJohn Forte
1227fcf3ce44SJohn Forte nodepath = calloc(1, len);
1228fcf3ce44SJohn Forte if (nodepath == NULL) {
1229fcf3ce44SJohn Forte lap->l_errno = errno;
1230fcf3ce44SJohn Forte lap->ret = FPCFGA_LIB_ERR;
1231fcf3ce44SJohn Forte rv = DI_WALK_TERMINATE;
1232fcf3ce44SJohn Forte goto out;
1233fcf3ce44SJohn Forte }
1234fcf3ce44SJohn Forte
1235fcf3ce44SJohn Forte (void) snprintf(nodepath, len, "%s%s", DEVICES_DIR, devfsp);
1236fcf3ce44SJohn Forte
1237fcf3ce44SJohn Forte /* Skip node if it is HBA */
1238fcf3ce44SJohn Forte match_minor = 0;
1239fcf3ce44SJohn Forte if (!dev_cmp(lap->apidp->xport_phys, nodepath, match_minor)) {
1240fcf3ce44SJohn Forte rv = DI_WALK_CONTINUE;
1241fcf3ce44SJohn Forte goto out;
1242fcf3ce44SJohn Forte }
1243fcf3ce44SJohn Forte
1244fcf3ce44SJohn Forte /* If stat'ing a specific device, is this node that device */
1245fcf3ce44SJohn Forte if (lap->cmd == FPCFGA_STAT_FC_DEV) {
1246fcf3ce44SJohn Forte /* checks port wwn property to find a match */
1247fcf3ce44SJohn Forte while ((prop = di_prop_next(node, prop))
1248fcf3ce44SJohn Forte != DI_PROP_NIL) {
1249fcf3ce44SJohn Forte if ((strcmp(PORT_WWN_PROP,
1250fcf3ce44SJohn Forte di_prop_name(prop)) == 0) &&
1251fcf3ce44SJohn Forte (di_prop_type(prop) ==
1252fcf3ce44SJohn Forte DI_PROP_TYPE_BYTE)) {
1253fcf3ce44SJohn Forte break;
1254fcf3ce44SJohn Forte }
1255fcf3ce44SJohn Forte }
1256fcf3ce44SJohn Forte
1257fcf3ce44SJohn Forte if (prop != DI_PROP_NIL) {
1258fcf3ce44SJohn Forte count = di_prop_bytes(prop, &port_wwn_data);
1259fcf3ce44SJohn Forte if (count != WWN_SIZE) {
1260fcf3ce44SJohn Forte lap->ret = FPCFGA_LIB_ERR;
1261fcf3ce44SJohn Forte rv = DI_WALK_TERMINATE;
1262fcf3ce44SJohn Forte goto out;
1263fcf3ce44SJohn Forte }
1264fcf3ce44SJohn Forte (void) sprintf(port_wwn, "%016llx",
1265fcf3ce44SJohn Forte (wwnConversion(port_wwn_data)));
1266fcf3ce44SJohn Forte /*
1267fcf3ce44SJohn Forte * port wwn doesn't match contine to walk
1268fcf3ce44SJohn Forte * if match call do_stat_fc_dev.
1269fcf3ce44SJohn Forte */
1270fcf3ce44SJohn Forte if (strncmp(port_wwn, lap->apidp->dyncomp,
1271fcf3ce44SJohn Forte WWN_SIZE*2)) {
1272fcf3ce44SJohn Forte rv = DI_WALK_CONTINUE;
1273fcf3ce44SJohn Forte goto out;
1274fcf3ce44SJohn Forte }
1275fcf3ce44SJohn Forte } else {
1276fcf3ce44SJohn Forte rv = DI_WALK_CONTINUE;
1277fcf3ce44SJohn Forte goto out;
1278fcf3ce44SJohn Forte }
1279fcf3ce44SJohn Forte }
1280fcf3ce44SJohn Forte
1281fcf3ce44SJohn Forte /*
1282fcf3ce44SJohn Forte * If stat'ing a xport only, we look at device nodes only to get
1283fcf3ce44SJohn Forte * xport configuration status. So a limited stat will suffice.
1284fcf3ce44SJohn Forte */
1285fcf3ce44SJohn Forte if (lap->cmd == FPCFGA_STAT_FCA_PORT) {
1286fcf3ce44SJohn Forte limited_stat = 1;
1287fcf3ce44SJohn Forte } else {
1288fcf3ce44SJohn Forte limited_stat = 0;
1289fcf3ce44SJohn Forte }
1290fcf3ce44SJohn Forte
1291fcf3ce44SJohn Forte /*
1292fcf3ce44SJohn Forte * Ignore errors if stat'ing a bus or listing all
1293fcf3ce44SJohn Forte */
1294fcf3ce44SJohn Forte ret = do_stat_fc_dev(node, nodepath, lap, limited_stat);
1295fcf3ce44SJohn Forte if (ret != FPCFGA_OK) {
1296fcf3ce44SJohn Forte if (lap->cmd == FPCFGA_STAT_FC_DEV) {
1297fcf3ce44SJohn Forte lap->ret = ret;
1298fcf3ce44SJohn Forte rv = DI_WALK_TERMINATE;
1299fcf3ce44SJohn Forte } else {
1300fcf3ce44SJohn Forte rv = DI_WALK_CONTINUE;
1301fcf3ce44SJohn Forte }
1302fcf3ce44SJohn Forte goto out;
1303fcf3ce44SJohn Forte }
1304fcf3ce44SJohn Forte
1305fcf3ce44SJohn Forte /* Are we done ? */
1306fcf3ce44SJohn Forte rv = DI_WALK_CONTINUE;
1307fcf3ce44SJohn Forte if (lap->cmd == FPCFGA_STAT_FCA_PORT &&
1308fcf3ce44SJohn Forte lap->chld_config == CFGA_STAT_CONFIGURED) {
1309fcf3ce44SJohn Forte rv = DI_WALK_TERMINATE;
1310fcf3ce44SJohn Forte } else if (lap->cmd == FPCFGA_STAT_FC_DEV) {
1311fcf3ce44SJohn Forte /*
1312fcf3ce44SJohn Forte * If stat'ing a specific device, we are done at this point.
1313fcf3ce44SJohn Forte */
1314fcf3ce44SJohn Forte rv = DI_WALK_TERMINATE;
1315fcf3ce44SJohn Forte }
1316fcf3ce44SJohn Forte
1317fcf3ce44SJohn Forte /*FALLTHRU*/
1318fcf3ce44SJohn Forte out:
1319fcf3ce44SJohn Forte S_FREE(nodepath);
1320fcf3ce44SJohn Forte if (devfsp != NULL) di_devfs_path_free(devfsp);
1321fcf3ce44SJohn Forte return (rv);
1322fcf3ce44SJohn Forte }
1323fcf3ce44SJohn Forte
1324fcf3ce44SJohn Forte /*
1325fcf3ce44SJohn Forte * Routine for checking each FCP SCSI LUN device found in device tree.
1326fcf3ce44SJohn Forte * When the matching port WWN and LUN are found from the accessble ldata list
1327fcf3ce44SJohn Forte * the FCP SCSI LUN is updated with configured ostate.
1328fcf3ce44SJohn Forte *
1329fcf3ce44SJohn Forte * Overall algorithm:
1330fcf3ce44SJohn Forte * Parse the device tree to find configured devices which matches with
1331fcf3ce44SJohn Forte * list argument. If cmd is stat on a specific target device it
1332fcf3ce44SJohn Forte * matches port WWN and continues to further processing. If cmd is
1333fcf3ce44SJohn Forte * stat on hba port all the FCP SCSI LUN under the hba are processed.
1334fcf3ce44SJohn Forte */
1335fcf3ce44SJohn Forte static int
stat_FCP_dev(di_node_t node,void * arg)1336fcf3ce44SJohn Forte stat_FCP_dev(di_node_t node, void *arg)
1337fcf3ce44SJohn Forte {
1338fcf3ce44SJohn Forte fpcfga_list_t *lap = NULL;
1339fcf3ce44SJohn Forte char *devfsp = NULL, *nodepath = NULL;
1340fcf3ce44SJohn Forte size_t len = 0;
1341fcf3ce44SJohn Forte int limited_stat = 0, match_minor, rv, di_ret;
1342fcf3ce44SJohn Forte fpcfga_ret_t ret;
1343fcf3ce44SJohn Forte uchar_t *port_wwn_data;
1344fcf3ce44SJohn Forte char port_wwn[WWN_SIZE*2+1];
1345fcf3ce44SJohn Forte
1346fcf3ce44SJohn Forte lap = (fpcfga_list_t *)arg;
1347fcf3ce44SJohn Forte
1348fcf3ce44SJohn Forte devfsp = di_devfs_path(node);
1349fcf3ce44SJohn Forte if (devfsp == NULL) {
1350fcf3ce44SJohn Forte rv = DI_WALK_CONTINUE;
1351fcf3ce44SJohn Forte goto out;
1352fcf3ce44SJohn Forte }
1353fcf3ce44SJohn Forte
1354fcf3ce44SJohn Forte len = strlen(DEVICES_DIR) + strlen(devfsp) + 1;
1355fcf3ce44SJohn Forte
1356fcf3ce44SJohn Forte nodepath = calloc(1, len);
1357fcf3ce44SJohn Forte if (nodepath == NULL) {
1358fcf3ce44SJohn Forte lap->l_errno = errno;
1359fcf3ce44SJohn Forte lap->ret = FPCFGA_LIB_ERR;
1360fcf3ce44SJohn Forte rv = DI_WALK_TERMINATE;
1361fcf3ce44SJohn Forte goto out;
1362fcf3ce44SJohn Forte }
1363fcf3ce44SJohn Forte
1364fcf3ce44SJohn Forte (void) snprintf(nodepath, len, "%s%s", DEVICES_DIR, devfsp);
1365fcf3ce44SJohn Forte
1366fcf3ce44SJohn Forte /* Skip node if it is HBA */
1367fcf3ce44SJohn Forte match_minor = 0;
1368fcf3ce44SJohn Forte if (!dev_cmp(lap->apidp->xport_phys, nodepath, match_minor)) {
1369fcf3ce44SJohn Forte rv = DI_WALK_CONTINUE;
1370fcf3ce44SJohn Forte goto out;
1371fcf3ce44SJohn Forte }
1372fcf3ce44SJohn Forte
1373fcf3ce44SJohn Forte /* If stat'ing a specific device, is this node that device */
1374fcf3ce44SJohn Forte if (lap->cmd == FPCFGA_STAT_FC_DEV) {
1375fcf3ce44SJohn Forte /* checks port wwn property to find a match */
1376fcf3ce44SJohn Forte di_ret = di_prop_lookup_bytes(DDI_DEV_T_ANY, node,
1377fcf3ce44SJohn Forte PORT_WWN_PROP, &port_wwn_data);
1378fcf3ce44SJohn Forte if (di_ret == -1) {
1379fcf3ce44SJohn Forte rv = DI_WALK_CONTINUE;
1380fcf3ce44SJohn Forte goto out;
1381fcf3ce44SJohn Forte } else {
1382fcf3ce44SJohn Forte (void) sprintf(port_wwn, "%016llx",
1383fcf3ce44SJohn Forte (wwnConversion(port_wwn_data)));
1384fcf3ce44SJohn Forte /*
1385fcf3ce44SJohn Forte * port wwn doesn't match contine to walk
1386fcf3ce44SJohn Forte * if match call do_stat_FCP_dev.
1387fcf3ce44SJohn Forte */
1388fcf3ce44SJohn Forte if (strncmp(port_wwn, lap->apidp->dyncomp,
1389fcf3ce44SJohn Forte WWN_SIZE*2)) {
1390fcf3ce44SJohn Forte rv = DI_WALK_CONTINUE;
1391fcf3ce44SJohn Forte goto out;
1392fcf3ce44SJohn Forte }
1393fcf3ce44SJohn Forte }
1394fcf3ce44SJohn Forte }
1395fcf3ce44SJohn Forte
1396fcf3ce44SJohn Forte /*
1397fcf3ce44SJohn Forte * If stat'ing a xport only, we look at device nodes only to get
1398fcf3ce44SJohn Forte * xport configuration status. So a limited stat will suffice.
1399fcf3ce44SJohn Forte */
1400fcf3ce44SJohn Forte if (lap->cmd == FPCFGA_STAT_FCA_PORT) {
1401fcf3ce44SJohn Forte limited_stat = 1;
1402fcf3ce44SJohn Forte } else {
1403fcf3ce44SJohn Forte limited_stat = 0;
1404fcf3ce44SJohn Forte }
1405fcf3ce44SJohn Forte
1406fcf3ce44SJohn Forte /*
1407fcf3ce44SJohn Forte * Ignore errors if stat'ing a bus or listing all
1408fcf3ce44SJohn Forte */
1409fcf3ce44SJohn Forte ret = do_stat_FCP_dev(node, nodepath, lap, limited_stat);
1410fcf3ce44SJohn Forte if (ret != FPCFGA_OK) {
1411fcf3ce44SJohn Forte rv = DI_WALK_CONTINUE;
1412fcf3ce44SJohn Forte goto out;
1413fcf3ce44SJohn Forte }
1414fcf3ce44SJohn Forte
1415fcf3ce44SJohn Forte /* Are we done ? */
1416fcf3ce44SJohn Forte rv = DI_WALK_CONTINUE;
1417fcf3ce44SJohn Forte if (lap->cmd == FPCFGA_STAT_FCA_PORT &&
1418fcf3ce44SJohn Forte lap->chld_config == CFGA_STAT_CONFIGURED) {
1419fcf3ce44SJohn Forte rv = DI_WALK_TERMINATE;
1420fcf3ce44SJohn Forte }
1421fcf3ce44SJohn Forte
1422fcf3ce44SJohn Forte /*FALLTHRU*/
1423fcf3ce44SJohn Forte out:
1424fcf3ce44SJohn Forte S_FREE(nodepath);
1425fcf3ce44SJohn Forte if (devfsp != NULL) di_devfs_path_free(devfsp);
1426fcf3ce44SJohn Forte return (rv);
1427fcf3ce44SJohn Forte }
1428fcf3ce44SJohn Forte
1429fcf3ce44SJohn Forte static fpcfga_ret_t
do_stat_fca_xport(fpcfga_list_t * lap,int limited_stat,HBA_PORTATTRIBUTES portAttrs)1430fcf3ce44SJohn Forte do_stat_fca_xport(fpcfga_list_t *lap, int limited_stat,
1431fcf3ce44SJohn Forte HBA_PORTATTRIBUTES portAttrs)
1432fcf3ce44SJohn Forte {
1433fcf3ce44SJohn Forte cfga_list_data_t *clp = NULL;
1434fcf3ce44SJohn Forte ldata_list_t *listp = NULL;
1435fcf3ce44SJohn Forte int l_errno = 0;
1436fcf3ce44SJohn Forte uint_t devinfo_state = 0;
1437fcf3ce44SJohn Forte walkarg_t walkarg;
1438fcf3ce44SJohn Forte fpcfga_ret_t ret;
1439fcf3ce44SJohn Forte cfga_cond_t cond = CFGA_COND_UNKNOWN;
1440fcf3ce44SJohn Forte
1441fcf3ce44SJohn Forte assert(lap->xport_logp != NULL);
1442fcf3ce44SJohn Forte
1443fcf3ce44SJohn Forte /* Get xport state */
1444fcf3ce44SJohn Forte if (lap->apidp->flags == FLAG_DEVINFO_FORCE) {
1445fcf3ce44SJohn Forte walkarg.flags = FLAG_DEVINFO_FORCE;
1446fcf3ce44SJohn Forte } else {
1447fcf3ce44SJohn Forte walkarg.flags = 0;
1448fcf3ce44SJohn Forte }
1449fcf3ce44SJohn Forte walkarg.walkmode.node_args.flags = 0;
1450fcf3ce44SJohn Forte walkarg.walkmode.node_args.fcn = get_xport_state;
1451fcf3ce44SJohn Forte
1452fcf3ce44SJohn Forte ret = walk_tree(lap->apidp->xport_phys, &devinfo_state,
1453fcf3ce44SJohn Forte DINFOCPYALL | DINFOPATH, &walkarg, FPCFGA_WALK_NODE, &l_errno);
1454fcf3ce44SJohn Forte if (ret == FPCFGA_OK) {
1455fcf3ce44SJohn Forte lap->xport_rstate = xport_devinfo_to_recep_state(devinfo_state);
1456fcf3ce44SJohn Forte } else {
1457fcf3ce44SJohn Forte lap->xport_rstate = CFGA_STAT_NONE;
1458fcf3ce44SJohn Forte }
1459fcf3ce44SJohn Forte
1460fcf3ce44SJohn Forte /*
1461fcf3ce44SJohn Forte * Get topology works okay even if the fp port is connected
1462fcf3ce44SJohn Forte * to a switch and no devices connected to the switch.
1463fcf3ce44SJohn Forte * In this case the list will only shows fp port info without
1464fcf3ce44SJohn Forte * any device listed.
1465fcf3ce44SJohn Forte */
1466fcf3ce44SJohn Forte switch (portAttrs.PortType) {
1467fcf3ce44SJohn Forte case HBA_PORTTYPE_NLPORT:
1468fcf3ce44SJohn Forte (void) snprintf(lap->xport_type,
1469fcf3ce44SJohn Forte sizeof (lap->xport_type), "%s",
1470fcf3ce44SJohn Forte FP_FC_PUBLIC_PORT_TYPE);
1471fcf3ce44SJohn Forte break;
1472fcf3ce44SJohn Forte case HBA_PORTTYPE_NPORT:
1473fcf3ce44SJohn Forte (void) snprintf(lap->xport_type,
1474fcf3ce44SJohn Forte sizeof (lap->xport_type), "%s",
1475fcf3ce44SJohn Forte FP_FC_FABRIC_PORT_TYPE);
1476fcf3ce44SJohn Forte break;
1477fcf3ce44SJohn Forte case HBA_PORTTYPE_LPORT:
1478fcf3ce44SJohn Forte (void) snprintf(lap->xport_type,
1479fcf3ce44SJohn Forte sizeof (lap->xport_type), "%s",
1480fcf3ce44SJohn Forte FP_FC_PRIVATE_PORT_TYPE);
1481fcf3ce44SJohn Forte break;
1482fcf3ce44SJohn Forte case HBA_PORTTYPE_PTP:
1483fcf3ce44SJohn Forte (void) snprintf(lap->xport_type,
1484fcf3ce44SJohn Forte sizeof (lap->xport_type), "%s",
1485fcf3ce44SJohn Forte FP_FC_PT_TO_PT_PORT_TYPE);
1486fcf3ce44SJohn Forte break;
1487fcf3ce44SJohn Forte /*
1488fcf3ce44SJohn Forte * HBA_PORTTYPE_UNKNOWN means nothing is connected
1489fcf3ce44SJohn Forte */
1490fcf3ce44SJohn Forte case HBA_PORTTYPE_UNKNOWN:
1491fcf3ce44SJohn Forte (void) snprintf(lap->xport_type,
1492fcf3ce44SJohn Forte sizeof (lap->xport_type), "%s",
1493fcf3ce44SJohn Forte FP_FC_PORT_TYPE);
1494fcf3ce44SJohn Forte break;
1495fcf3ce44SJohn Forte /* NOT_PRESENT, OTHER, FPORT, FLPORT */
1496fcf3ce44SJohn Forte default:
1497fcf3ce44SJohn Forte (void) snprintf(lap->xport_type,
1498fcf3ce44SJohn Forte sizeof (lap->xport_type), "%s",
1499fcf3ce44SJohn Forte FP_FC_PORT_TYPE);
1500fcf3ce44SJohn Forte cond = CFGA_COND_FAILED;
1501fcf3ce44SJohn Forte break;
1502fcf3ce44SJohn Forte }
1503fcf3ce44SJohn Forte
1504fcf3ce44SJohn Forte if (limited_stat) {
1505fcf3ce44SJohn Forte /* We only want to know bus(receptacle) connect status */
1506fcf3ce44SJohn Forte return (FPCFGA_OK);
1507fcf3ce44SJohn Forte }
1508fcf3ce44SJohn Forte
1509fcf3ce44SJohn Forte listp = calloc(1, sizeof (ldata_list_t));
1510fcf3ce44SJohn Forte if (listp == NULL) {
1511fcf3ce44SJohn Forte lap->l_errno = errno;
1512fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
1513fcf3ce44SJohn Forte }
1514fcf3ce44SJohn Forte
1515fcf3ce44SJohn Forte clp = &listp->ldata;
1516fcf3ce44SJohn Forte
1517fcf3ce44SJohn Forte (void) snprintf(clp->ap_log_id, sizeof (clp->ap_log_id), "%s",
1518fcf3ce44SJohn Forte lap->xport_logp);
1519fcf3ce44SJohn Forte (void) snprintf(clp->ap_phys_id, sizeof (clp->ap_phys_id), "%s",
1520fcf3ce44SJohn Forte lap->apidp->xport_phys);
1521fcf3ce44SJohn Forte
1522fcf3ce44SJohn Forte clp->ap_class[0] = '\0'; /* Filled by libcfgadm */
1523fcf3ce44SJohn Forte clp->ap_r_state = lap->xport_rstate;
1524fcf3ce44SJohn Forte clp->ap_o_state = lap->chld_config;
1525fcf3ce44SJohn Forte clp->ap_cond = cond;
1526fcf3ce44SJohn Forte clp->ap_busy = 0;
1527fcf3ce44SJohn Forte clp->ap_status_time = (time_t)-1;
1528fcf3ce44SJohn Forte clp->ap_info[0] = '\0';
1529fcf3ce44SJohn Forte (void) strncpy(clp->ap_type, lap->xport_type, sizeof (clp->ap_type));
1530fcf3ce44SJohn Forte
1531fcf3ce44SJohn Forte /* Link it in. lap->listp is NULL originally. */
1532fcf3ce44SJohn Forte listp->next = lap->listp;
1533fcf3ce44SJohn Forte /* lap->listp now gets cfga_list_data for the fca port. */
1534fcf3ce44SJohn Forte lap->listp = listp;
1535fcf3ce44SJohn Forte
1536fcf3ce44SJohn Forte return (FPCFGA_OK);
1537fcf3ce44SJohn Forte }
1538fcf3ce44SJohn Forte
1539fcf3ce44SJohn Forte
1540fcf3ce44SJohn Forte static int
get_xport_state(di_node_t node,void * arg)1541fcf3ce44SJohn Forte get_xport_state(di_node_t node, void *arg)
1542fcf3ce44SJohn Forte {
1543fcf3ce44SJohn Forte uint_t *di_statep = (uint_t *)arg;
1544fcf3ce44SJohn Forte
1545fcf3ce44SJohn Forte *di_statep = di_state(node);
1546fcf3ce44SJohn Forte
1547fcf3ce44SJohn Forte return (DI_WALK_TERMINATE);
1548fcf3ce44SJohn Forte }
1549fcf3ce44SJohn Forte
1550fcf3ce44SJohn Forte /*
1551fcf3ce44SJohn Forte * Routine for updating ldata list based on the state of device node.
1552fcf3ce44SJohn Forte * When no matching accessible ldata is found a new ldata is created
1553fcf3ce44SJohn Forte * with proper state information.
1554fcf3ce44SJohn Forte *
1555fcf3ce44SJohn Forte * Overall algorithm:
1556fcf3ce44SJohn Forte * If the device node is online and the matching ldata is found
1557fcf3ce44SJohn Forte * the target device is updated with configued and unknown condition.
1558fcf3ce44SJohn Forte * If the device node is offline or down and the matching ldata is found
1559fcf3ce44SJohn Forte * the target device is updated with configued and unusable condition.
1560fcf3ce44SJohn Forte * If the device node is online but the matching ldata is not found
1561fcf3ce44SJohn Forte * the target device is created with configued and failing condition.
1562fcf3ce44SJohn Forte * If the device node is offline or down and the matching ldata is not found
1563fcf3ce44SJohn Forte * the target device is created with configued and unusable condition.
1564fcf3ce44SJohn Forte */
1565fcf3ce44SJohn Forte static fpcfga_ret_t
do_stat_fc_dev(const di_node_t node,const char * nodepath,fpcfga_list_t * lap,int limited_stat)1566fcf3ce44SJohn Forte do_stat_fc_dev(
1567fcf3ce44SJohn Forte const di_node_t node,
1568fcf3ce44SJohn Forte const char *nodepath,
1569fcf3ce44SJohn Forte fpcfga_list_t *lap,
1570fcf3ce44SJohn Forte int limited_stat)
1571fcf3ce44SJohn Forte {
1572fcf3ce44SJohn Forte uint_t dctl_state = 0, devinfo_state = 0;
1573fcf3ce44SJohn Forte char *dyncomp = NULL;
1574fcf3ce44SJohn Forte cfga_list_data_t *clp = NULL;
1575fcf3ce44SJohn Forte cfga_busy_t busy;
1576fcf3ce44SJohn Forte ldata_list_t *listp = NULL;
1577fcf3ce44SJohn Forte ldata_list_t *matchldp = NULL;
1578fcf3ce44SJohn Forte int l_errno = 0;
1579fcf3ce44SJohn Forte cfga_stat_t ostate;
1580fcf3ce44SJohn Forte cfga_cond_t cond;
1581fcf3ce44SJohn Forte fpcfga_ret_t ret;
1582fcf3ce44SJohn Forte
1583fcf3ce44SJohn Forte assert(lap->apidp->xport_phys != NULL);
1584fcf3ce44SJohn Forte assert(lap->xport_logp != NULL);
1585fcf3ce44SJohn Forte
1586fcf3ce44SJohn Forte cond = CFGA_COND_UNKNOWN;
1587fcf3ce44SJohn Forte
1588fcf3ce44SJohn Forte devinfo_state = di_state(node);
1589fcf3ce44SJohn Forte ostate = dev_devinfo_to_occupant_state(devinfo_state);
1590fcf3ce44SJohn Forte
1591fcf3ce44SJohn Forte /*
1592fcf3ce44SJohn Forte * NOTE: The framework cannot currently detect layered driver
1593fcf3ce44SJohn Forte * opens, so the busy indicator is not very reliable. Also,
1594fcf3ce44SJohn Forte * non-root users will not be able to determine busy
1595fcf3ce44SJohn Forte * status (libdevice needs root permissions).
1596fcf3ce44SJohn Forte * This should probably be fixed by adding a DI_BUSY to the di_state()
1597fcf3ce44SJohn Forte * routine in libdevinfo.
1598fcf3ce44SJohn Forte */
1599fcf3ce44SJohn Forte if (devctl_cmd(nodepath, FPCFGA_DEV_GETSTATE, &dctl_state,
1600fcf3ce44SJohn Forte &l_errno) == FPCFGA_OK) {
1601fcf3ce44SJohn Forte busy = ((dctl_state & DEVICE_BUSY) == DEVICE_BUSY) ? 1 : 0;
1602fcf3ce44SJohn Forte } else {
1603fcf3ce44SJohn Forte busy = 0;
1604fcf3ce44SJohn Forte }
1605fcf3ce44SJohn Forte
1606fcf3ce44SJohn Forte /* We only want to know device config state */
1607fcf3ce44SJohn Forte if (limited_stat) {
1608fcf3ce44SJohn Forte if (((strcmp(lap->xport_type, FP_FC_FABRIC_PORT_TYPE) == 0) ||
1609fcf3ce44SJohn Forte strcmp(lap->xport_type, FP_FC_PUBLIC_PORT_TYPE) == 0)) {
1610fcf3ce44SJohn Forte lap->chld_config = CFGA_STAT_CONFIGURED;
1611fcf3ce44SJohn Forte } else {
1612fcf3ce44SJohn Forte if (ostate != CFGA_STAT_UNCONFIGURED) {
1613fcf3ce44SJohn Forte lap->chld_config = CFGA_STAT_CONFIGURED;
1614fcf3ce44SJohn Forte }
1615fcf3ce44SJohn Forte }
1616fcf3ce44SJohn Forte return (FPCFGA_OK);
1617fcf3ce44SJohn Forte }
1618fcf3ce44SJohn Forte
1619fcf3ce44SJohn Forte /*
1620fcf3ce44SJohn Forte * If child device is configured, see if it is accessible also
1621fcf3ce44SJohn Forte * for FPCFGA_STAT_FC_DEV cmd.
1622fcf3ce44SJohn Forte */
1623fcf3ce44SJohn Forte if (lap->cmd == FPCFGA_STAT_FC_DEV) {
1624fcf3ce44SJohn Forte switch (ostate) {
1625fcf3ce44SJohn Forte case CFGA_STAT_CONFIGURED:
1626fcf3ce44SJohn Forte /*
1627fcf3ce44SJohn Forte * if configured and not accessble, the device is
1628fcf3ce44SJohn Forte * till be displayed with failing condition.
1629fcf3ce44SJohn Forte * return code should be FPCFGA_OK to display it.
1630fcf3ce44SJohn Forte */
1631fcf3ce44SJohn Forte case CFGA_STAT_NONE:
1632fcf3ce44SJohn Forte /*
1633fcf3ce44SJohn Forte * If not unconfigured and not attached
1634fcf3ce44SJohn Forte * the state is set to CFGA_STAT_NONE currently.
1635fcf3ce44SJohn Forte * This is okay for the detached node due to
1636fcf3ce44SJohn Forte * the driver being unloaded.
1637fcf3ce44SJohn Forte * May need to define another state to
1638fcf3ce44SJohn Forte * isolate the detached only state.
1639fcf3ce44SJohn Forte *
1640fcf3ce44SJohn Forte * handle the same way as configured.
1641fcf3ce44SJohn Forte */
1642fcf3ce44SJohn Forte if (lap->ret != FPCFGA_ACCESS_OK) {
1643fcf3ce44SJohn Forte cond = CFGA_COND_FAILING;
1644fcf3ce44SJohn Forte }
1645fcf3ce44SJohn Forte lap->chld_config = CFGA_STAT_CONFIGURED;
1646fcf3ce44SJohn Forte break;
1647fcf3ce44SJohn Forte case CFGA_STAT_UNCONFIGURED:
1648fcf3ce44SJohn Forte /*
1649fcf3ce44SJohn Forte * if unconfigured - offline or down,
1650fcf3ce44SJohn Forte * set to cond to unusable regardless of accessibility.
1651fcf3ce44SJohn Forte * This behavior needs to be examined further.
1652fcf3ce44SJohn Forte * When the device is not accessible the node
1653fcf3ce44SJohn Forte * may get offline or down. In that case failing
1654fcf3ce44SJohn Forte * cond may make more sense.
1655fcf3ce44SJohn Forte * In anycase the ostate will be set to configured
1656fcf3ce44SJohn Forte * configured.
1657fcf3ce44SJohn Forte */
1658fcf3ce44SJohn Forte cond = CFGA_COND_UNUSABLE;
1659fcf3ce44SJohn Forte /*
1660fcf3ce44SJohn Forte * For fabric port the fca port is considered as
1661fcf3ce44SJohn Forte * configured since user configured previously
1662fcf3ce44SJohn Forte * for any existing node. Otherwise when the
1663fcf3ce44SJohn Forte * device was accessible, the hba is considered as
1664fcf3ce44SJohn Forte * configured.
1665fcf3ce44SJohn Forte */
1666fcf3ce44SJohn Forte if (((strcmp(lap->xport_type,
1667fcf3ce44SJohn Forte FP_FC_PUBLIC_PORT_TYPE) == 0) ||
1668fcf3ce44SJohn Forte (strcmp(lap->xport_type,
1669fcf3ce44SJohn Forte FP_FC_FABRIC_PORT_TYPE) == 0)) ||
1670fcf3ce44SJohn Forte (lap->ret == FPCFGA_ACCESS_OK)) {
1671fcf3ce44SJohn Forte lap->chld_config = CFGA_STAT_CONFIGURED;
1672fcf3ce44SJohn Forte } else {
1673fcf3ce44SJohn Forte lap->ret = FPCFGA_APID_NOEXIST;
1674fcf3ce44SJohn Forte return (FPCFGA_OK);
1675fcf3ce44SJohn Forte }
1676fcf3ce44SJohn Forte break;
1677fcf3ce44SJohn Forte default:
1678fcf3ce44SJohn Forte break;
1679fcf3ce44SJohn Forte }
1680fcf3ce44SJohn Forte
1681fcf3ce44SJohn Forte /* if device found in disco ports, ldata already created. */
1682fcf3ce44SJohn Forte if (lap->ret == FPCFGA_ACCESS_OK) {
1683fcf3ce44SJohn Forte /*
1684fcf3ce44SJohn Forte * if cond is not changed then don't update
1685fcf3ce44SJohn Forte * condition to keep the previous condition.
1686fcf3ce44SJohn Forte */
1687fcf3ce44SJohn Forte if (cond != CFGA_COND_UNKNOWN) {
1688fcf3ce44SJohn Forte lap->listp->ldata.ap_cond = cond;
1689fcf3ce44SJohn Forte }
1690fcf3ce44SJohn Forte lap->listp->ldata.ap_o_state = CFGA_STAT_CONFIGURED;
1691fcf3ce44SJohn Forte lap->listp->ldata.ap_busy = busy;
1692fcf3ce44SJohn Forte lap->ret = FPCFGA_OK;
1693fcf3ce44SJohn Forte return (FPCFGA_OK);
1694fcf3ce44SJohn Forte }
1695fcf3ce44SJohn Forte }
1696fcf3ce44SJohn Forte
1697fcf3ce44SJohn Forte /*
1698fcf3ce44SJohn Forte * if cmd is stat all check ldata list
1699fcf3ce44SJohn Forte * to see if the node exist on the dev list. Otherwise create
1700fcf3ce44SJohn Forte * the list element.
1701fcf3ce44SJohn Forte */
1702fcf3ce44SJohn Forte if (lap->cmd == FPCFGA_STAT_ALL) {
1703fcf3ce44SJohn Forte if (lap->listp != NULL) {
1704fcf3ce44SJohn Forte if ((ret = make_dyncomp_from_dinode(node,
1705fcf3ce44SJohn Forte &dyncomp, &l_errno)) != FPCFGA_OK) {
1706fcf3ce44SJohn Forte return (ret);
1707fcf3ce44SJohn Forte }
1708fcf3ce44SJohn Forte ret = is_dyn_ap_on_ldata_list(dyncomp, lap->listp,
1709fcf3ce44SJohn Forte &matchldp, &l_errno);
1710fcf3ce44SJohn Forte switch (ret) {
1711fcf3ce44SJohn Forte case FPCFGA_ACCESS_OK:
1712fcf3ce44SJohn Forte /* node exists so set ostate to configured. */
1713fcf3ce44SJohn Forte lap->chld_config = CFGA_STAT_CONFIGURED;
1714fcf3ce44SJohn Forte matchldp->ldata.ap_o_state =
1715fcf3ce44SJohn Forte CFGA_STAT_CONFIGURED;
1716fcf3ce44SJohn Forte matchldp->ldata.ap_busy = busy;
1717fcf3ce44SJohn Forte clp = &matchldp->ldata;
1718fcf3ce44SJohn Forte switch (ostate) {
1719fcf3ce44SJohn Forte case CFGA_STAT_CONFIGURED:
1720fcf3ce44SJohn Forte /*
1721fcf3ce44SJohn Forte * If not unconfigured and not attached
1722fcf3ce44SJohn Forte * the state is set to CFGA_STAT_NONE currently.
1723fcf3ce44SJohn Forte * This is okay for the detached node due to
1724fcf3ce44SJohn Forte * the driver being unloaded.
1725fcf3ce44SJohn Forte * May need to define another state to
1726fcf3ce44SJohn Forte * isolate the detached only state.
1727fcf3ce44SJohn Forte */
1728fcf3ce44SJohn Forte case CFGA_STAT_NONE:
1729fcf3ce44SJohn Forte /* update ap_type and ap_info */
1730fcf3ce44SJohn Forte get_hw_info(node, clp);
1731fcf3ce44SJohn Forte break;
1732fcf3ce44SJohn Forte /*
1733fcf3ce44SJohn Forte * node is offline or down.
1734fcf3ce44SJohn Forte * set cond to unusable.
1735fcf3ce44SJohn Forte */
1736fcf3ce44SJohn Forte case CFGA_STAT_UNCONFIGURED:
1737fcf3ce44SJohn Forte /*
1738fcf3ce44SJohn Forte * if cond is not unknown
1739fcf3ce44SJohn Forte * we already set the cond from
1740fcf3ce44SJohn Forte * a different node with the same
1741fcf3ce44SJohn Forte * port WWN or initial probing
1742fcf3ce44SJohn Forte * was failed so don't update again.
1743fcf3ce44SJohn Forte */
1744fcf3ce44SJohn Forte if (matchldp->ldata.ap_cond ==
1745fcf3ce44SJohn Forte CFGA_COND_UNKNOWN) {
1746fcf3ce44SJohn Forte matchldp->ldata.ap_cond =
1747fcf3ce44SJohn Forte CFGA_COND_UNUSABLE;
1748fcf3ce44SJohn Forte }
1749fcf3ce44SJohn Forte break;
1750fcf3ce44SJohn Forte default:
1751fcf3ce44SJohn Forte break;
1752fcf3ce44SJohn Forte }
1753fcf3ce44SJohn Forte /* node found in ldata list so just return. */
1754fcf3ce44SJohn Forte lap->ret = FPCFGA_OK;
1755fcf3ce44SJohn Forte S_FREE(dyncomp);
1756fcf3ce44SJohn Forte return (FPCFGA_OK);
1757fcf3ce44SJohn Forte case FPCFGA_LIB_ERR:
1758fcf3ce44SJohn Forte lap->l_errno = l_errno;
1759fcf3ce44SJohn Forte S_FREE(dyncomp);
1760fcf3ce44SJohn Forte return (ret);
1761fcf3ce44SJohn Forte case FPCFGA_APID_NOACCESS:
1762fcf3ce44SJohn Forte switch (ostate) {
1763fcf3ce44SJohn Forte /* node is attached but not in dev list */
1764fcf3ce44SJohn Forte case CFGA_STAT_CONFIGURED:
1765fcf3ce44SJohn Forte case CFGA_STAT_NONE:
1766fcf3ce44SJohn Forte lap->chld_config = CFGA_STAT_CONFIGURED;
1767fcf3ce44SJohn Forte cond = CFGA_COND_FAILING;
1768fcf3ce44SJohn Forte break;
1769fcf3ce44SJohn Forte /*
1770fcf3ce44SJohn Forte * node is offline or down.
1771fcf3ce44SJohn Forte * set cond to unusable.
1772fcf3ce44SJohn Forte */
1773fcf3ce44SJohn Forte case CFGA_STAT_UNCONFIGURED:
1774fcf3ce44SJohn Forte /*
1775fcf3ce44SJohn Forte * For fabric port the fca port is
1776fcf3ce44SJohn Forte * considered as configured since user
1777fcf3ce44SJohn Forte * configured previously for any
1778fcf3ce44SJohn Forte * existing node.
1779fcf3ce44SJohn Forte */
1780fcf3ce44SJohn Forte cond = CFGA_COND_UNUSABLE;
1781fcf3ce44SJohn Forte if ((strcmp(lap->xport_type,
1782fcf3ce44SJohn Forte FP_FC_PUBLIC_PORT_TYPE) == 0) ||
1783fcf3ce44SJohn Forte (strcmp(lap->xport_type,
1784fcf3ce44SJohn Forte FP_FC_FABRIC_PORT_TYPE) == 0)) {
1785fcf3ce44SJohn Forte lap->chld_config =
1786fcf3ce44SJohn Forte CFGA_STAT_CONFIGURED;
1787fcf3ce44SJohn Forte } else {
1788fcf3ce44SJohn Forte lap->ret = FPCFGA_OK;
1789fcf3ce44SJohn Forte S_FREE(dyncomp);
1790fcf3ce44SJohn Forte return (FPCFGA_OK);
1791fcf3ce44SJohn Forte }
1792fcf3ce44SJohn Forte break;
1793fcf3ce44SJohn Forte default:
1794fcf3ce44SJohn Forte /*
1795fcf3ce44SJohn Forte * continue to create ldata_list struct for
1796fcf3ce44SJohn Forte * this node
1797fcf3ce44SJohn Forte */
1798fcf3ce44SJohn Forte break;
1799fcf3ce44SJohn Forte }
1800fcf3ce44SJohn Forte default:
1801fcf3ce44SJohn Forte break;
1802fcf3ce44SJohn Forte }
1803fcf3ce44SJohn Forte } else {
1804fcf3ce44SJohn Forte /*
1805fcf3ce44SJohn Forte * dev_list is null so there is no accessible dev.
1806fcf3ce44SJohn Forte * set the cond and continue to create ldata.
1807fcf3ce44SJohn Forte */
1808fcf3ce44SJohn Forte switch (ostate) {
1809fcf3ce44SJohn Forte case CFGA_STAT_CONFIGURED:
1810fcf3ce44SJohn Forte case CFGA_STAT_NONE:
1811fcf3ce44SJohn Forte cond = CFGA_COND_FAILING;
1812fcf3ce44SJohn Forte lap->chld_config = CFGA_STAT_CONFIGURED;
1813fcf3ce44SJohn Forte break;
1814fcf3ce44SJohn Forte /*
1815fcf3ce44SJohn Forte * node is offline or down.
1816fcf3ce44SJohn Forte * set cond to unusable.
1817fcf3ce44SJohn Forte */
1818fcf3ce44SJohn Forte case CFGA_STAT_UNCONFIGURED:
1819fcf3ce44SJohn Forte cond = CFGA_COND_UNUSABLE;
1820fcf3ce44SJohn Forte /*
1821fcf3ce44SJohn Forte * For fabric port the fca port is
1822fcf3ce44SJohn Forte * considered as configured since user
1823fcf3ce44SJohn Forte * configured previously for any
1824fcf3ce44SJohn Forte * existing node.
1825fcf3ce44SJohn Forte */
1826fcf3ce44SJohn Forte if ((strcmp(lap->xport_type,
1827fcf3ce44SJohn Forte FP_FC_PUBLIC_PORT_TYPE) == 0) ||
1828fcf3ce44SJohn Forte (strcmp(lap->xport_type,
1829fcf3ce44SJohn Forte FP_FC_FABRIC_PORT_TYPE) == 0)) {
1830fcf3ce44SJohn Forte lap->chld_config =
1831fcf3ce44SJohn Forte CFGA_STAT_CONFIGURED;
1832fcf3ce44SJohn Forte } else {
1833fcf3ce44SJohn Forte lap->ret = FPCFGA_OK;
1834fcf3ce44SJohn Forte S_FREE(dyncomp);
1835fcf3ce44SJohn Forte return (FPCFGA_OK);
1836fcf3ce44SJohn Forte }
1837fcf3ce44SJohn Forte break;
1838fcf3ce44SJohn Forte default:
1839fcf3ce44SJohn Forte break;
1840fcf3ce44SJohn Forte }
1841fcf3ce44SJohn Forte }
1842fcf3ce44SJohn Forte }
1843fcf3ce44SJohn Forte
1844fcf3ce44SJohn Forte listp = calloc(1, sizeof (ldata_list_t));
1845fcf3ce44SJohn Forte if (listp == NULL) {
1846fcf3ce44SJohn Forte lap->l_errno = errno;
1847fcf3ce44SJohn Forte S_FREE(dyncomp);
1848fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
1849fcf3ce44SJohn Forte }
1850fcf3ce44SJohn Forte
1851fcf3ce44SJohn Forte clp = &listp->ldata;
1852fcf3ce44SJohn Forte
1853fcf3ce44SJohn Forte /* Create the dynamic component. */
1854fcf3ce44SJohn Forte if (dyncomp == NULL) {
1855fcf3ce44SJohn Forte ret = make_dyncomp_from_dinode(node, &dyncomp, &l_errno);
1856fcf3ce44SJohn Forte if (ret != FPCFGA_OK) {
1857fcf3ce44SJohn Forte S_FREE(listp);
1858fcf3ce44SJohn Forte return (ret);
1859fcf3ce44SJohn Forte }
1860fcf3ce44SJohn Forte }
1861fcf3ce44SJohn Forte
1862fcf3ce44SJohn Forte /* Create logical and physical ap_id */
1863fcf3ce44SJohn Forte (void) snprintf(clp->ap_log_id, sizeof (clp->ap_log_id), "%s%s%s",
1864fcf3ce44SJohn Forte lap->xport_logp, DYN_SEP, dyncomp);
1865fcf3ce44SJohn Forte
1866fcf3ce44SJohn Forte (void) snprintf(clp->ap_phys_id, sizeof (clp->ap_phys_id), "%s%s%s",
1867fcf3ce44SJohn Forte lap->apidp->xport_phys, DYN_SEP, dyncomp);
1868fcf3ce44SJohn Forte
1869fcf3ce44SJohn Forte S_FREE(dyncomp);
1870fcf3ce44SJohn Forte
1871fcf3ce44SJohn Forte clp->ap_class[0] = '\0'; /* Filled in by libcfgadm */
1872fcf3ce44SJohn Forte clp->ap_r_state = lap->xport_rstate;
1873fcf3ce44SJohn Forte /* set to ostate to configured and set cond with info. */
1874fcf3ce44SJohn Forte clp->ap_o_state = CFGA_STAT_CONFIGURED;
1875fcf3ce44SJohn Forte clp->ap_cond = cond;
1876fcf3ce44SJohn Forte clp->ap_busy = busy;
1877fcf3ce44SJohn Forte clp->ap_status_time = (time_t)-1;
1878fcf3ce44SJohn Forte
1879fcf3ce44SJohn Forte /* get ap_type and ap_info. */
1880fcf3ce44SJohn Forte get_hw_info(node, clp);
1881fcf3ce44SJohn Forte
1882fcf3ce44SJohn Forte /* Link it in */
1883fcf3ce44SJohn Forte listp->next = lap->listp;
1884fcf3ce44SJohn Forte lap->listp = listp;
1885fcf3ce44SJohn Forte
1886fcf3ce44SJohn Forte lap->ret = FPCFGA_OK;
1887fcf3ce44SJohn Forte return (FPCFGA_OK);
1888fcf3ce44SJohn Forte }
1889fcf3ce44SJohn Forte
1890fcf3ce44SJohn Forte /*
1891fcf3ce44SJohn Forte * Wrapper routine for handling path info.
1892fcf3ce44SJohn Forte *
1893fcf3ce44SJohn Forte * When show_FCP_dev option is given stat_path_info_FCP_dev() is called.
1894fcf3ce44SJohn Forte * Otherwise stat_path_info_fc_dev() is called.
1895fcf3ce44SJohn Forte */
1896fcf3ce44SJohn Forte int
stat_path_info_node(di_node_t root,void * arg,int * l_errnop)1897fcf3ce44SJohn Forte stat_path_info_node(
1898fcf3ce44SJohn Forte di_node_t root,
1899fcf3ce44SJohn Forte void *arg,
1900fcf3ce44SJohn Forte int *l_errnop)
1901fcf3ce44SJohn Forte {
1902fcf3ce44SJohn Forte fpcfga_list_t *lap = NULL;
1903fcf3ce44SJohn Forte
1904fcf3ce44SJohn Forte lap = (fpcfga_list_t *)arg;
1905fcf3ce44SJohn Forte if ((lap->apidp->flags & (FLAG_FCP_DEV)) == FLAG_FCP_DEV) {
1906fcf3ce44SJohn Forte return (stat_path_info_FCP_dev(root, lap, l_errnop));
1907fcf3ce44SJohn Forte } else {
1908fcf3ce44SJohn Forte return (stat_path_info_fc_dev(root, lap, l_errnop));
1909fcf3ce44SJohn Forte }
1910fcf3ce44SJohn Forte }
1911fcf3ce44SJohn Forte
1912fcf3ce44SJohn Forte /*
1913fcf3ce44SJohn Forte * Routine for updating ldata list based on the state of path info node.
1914fcf3ce44SJohn Forte * When no matching accessible ldata is found a new ldata is created
1915fcf3ce44SJohn Forte * with proper state information.
1916fcf3ce44SJohn Forte *
1917fcf3ce44SJohn Forte * Overall algorithm:
1918fcf3ce44SJohn Forte * If the path info node is not offline and the matching ldata is found
1919fcf3ce44SJohn Forte * the target device is updated with configued and unknown condition.
1920fcf3ce44SJohn Forte * If the path info node is offline or failed and the matching ldata is found
1921fcf3ce44SJohn Forte * the target device is updated with configued and unusable condition.
1922fcf3ce44SJohn Forte * If the path info node is online but the matching ldata is not found
1923fcf3ce44SJohn Forte * the target device is created with configued and failing condition.
1924fcf3ce44SJohn Forte * If the path info is offline or failed and the matching ldata is not found
1925fcf3ce44SJohn Forte * the target device is created with configued and unusable condition.
1926fcf3ce44SJohn Forte */
1927fcf3ce44SJohn Forte static int
stat_path_info_fc_dev(di_node_t root,fpcfga_list_t * lap,int * l_errnop)1928fcf3ce44SJohn Forte stat_path_info_fc_dev(
1929fcf3ce44SJohn Forte di_node_t root,
1930fcf3ce44SJohn Forte fpcfga_list_t *lap,
1931fcf3ce44SJohn Forte int *l_errnop)
1932fcf3ce44SJohn Forte {
1933fcf3ce44SJohn Forte ldata_list_t *matchldp = NULL;
1934fcf3ce44SJohn Forte di_path_t path = DI_PATH_NIL;
1935fcf3ce44SJohn Forte uchar_t *port_wwn_data;
1936fcf3ce44SJohn Forte char port_wwn[WWN_SIZE*2+1];
1937fcf3ce44SJohn Forte int count;
1938fcf3ce44SJohn Forte fpcfga_ret_t ret;
1939fcf3ce44SJohn Forte di_path_state_t pstate;
1940fcf3ce44SJohn Forte
1941fcf3ce44SJohn Forte if (root == DI_NODE_NIL) {
1942fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
1943fcf3ce44SJohn Forte }
1944fcf3ce44SJohn Forte
1945fcf3ce44SJohn Forte /*
1946fcf3ce44SJohn Forte * if stat on a specific dev and walk_node found it okay
1947fcf3ce44SJohn Forte * then just return ok.
1948fcf3ce44SJohn Forte */
1949fcf3ce44SJohn Forte if ((lap->cmd == FPCFGA_STAT_FC_DEV) && (lap->ret == FPCFGA_OK)) {
1950fcf3ce44SJohn Forte return (FPCFGA_OK);
1951fcf3ce44SJohn Forte }
1952fcf3ce44SJohn Forte
1953fcf3ce44SJohn Forte /*
1954fcf3ce44SJohn Forte * if stat on a fca xport and chld_config is set
1955fcf3ce44SJohn Forte * then just return ok.
1956fcf3ce44SJohn Forte */
1957fcf3ce44SJohn Forte if ((lap->cmd == FPCFGA_STAT_FCA_PORT) &&
1958fcf3ce44SJohn Forte (lap->chld_config == CFGA_STAT_CONFIGURED)) {
1959fcf3ce44SJohn Forte return (FPCFGA_OK);
1960fcf3ce44SJohn Forte }
1961fcf3ce44SJohn Forte
1962fcf3ce44SJohn Forte /*
1963fcf3ce44SJohn Forte * when there is no path_info node return FPCFGA_OK.
1964fcf3ce44SJohn Forte * That way the result from walk_node shall be maintained.
1965fcf3ce44SJohn Forte */
1966fcf3ce44SJohn Forte if ((path = di_path_next_client(root, path)) == DI_PATH_NIL) {
1967fcf3ce44SJohn Forte /*
1968fcf3ce44SJohn Forte * if the dev was in dev list but not found
1969fcf3ce44SJohn Forte * return OK to indicate is not configured.
1970fcf3ce44SJohn Forte */
1971fcf3ce44SJohn Forte if (lap->ret == FPCFGA_ACCESS_OK) {
1972fcf3ce44SJohn Forte lap->ret = FPCFGA_OK;
1973fcf3ce44SJohn Forte }
1974fcf3ce44SJohn Forte return (FPCFGA_OK);
1975fcf3ce44SJohn Forte }
1976fcf3ce44SJohn Forte
1977fcf3ce44SJohn Forte /* if stat on fca port return. */
1978fcf3ce44SJohn Forte if (lap->cmd == FPCFGA_STAT_FCA_PORT) {
1979fcf3ce44SJohn Forte if (((strcmp(lap->xport_type, FP_FC_FABRIC_PORT_TYPE) == 0) ||
1980fcf3ce44SJohn Forte strcmp(lap->xport_type, FP_FC_PUBLIC_PORT_TYPE) == 0)) {
1981fcf3ce44SJohn Forte lap->chld_config = CFGA_STAT_CONFIGURED;
1982fcf3ce44SJohn Forte return (FPCFGA_OK);
1983fcf3ce44SJohn Forte } else {
1984fcf3ce44SJohn Forte if ((pstate = di_path_state(path)) !=
1985fcf3ce44SJohn Forte DI_PATH_STATE_OFFLINE) {
1986fcf3ce44SJohn Forte lap->chld_config = CFGA_STAT_CONFIGURED;
1987fcf3ce44SJohn Forte return (FPCFGA_OK);
1988fcf3ce44SJohn Forte }
1989fcf3ce44SJohn Forte }
1990fcf3ce44SJohn Forte }
1991fcf3ce44SJohn Forte /*
1992fcf3ce44SJohn Forte * now parse the path info node.
1993fcf3ce44SJohn Forte */
1994fcf3ce44SJohn Forte do {
1995fcf3ce44SJohn Forte count = di_path_prop_lookup_bytes(path, PORT_WWN_PROP,
1996fcf3ce44SJohn Forte &port_wwn_data);
1997fcf3ce44SJohn Forte if (count != WWN_SIZE) {
1998fcf3ce44SJohn Forte ret = FPCFGA_LIB_ERR;
1999fcf3ce44SJohn Forte break;
2000fcf3ce44SJohn Forte }
2001fcf3ce44SJohn Forte
2002fcf3ce44SJohn Forte (void) sprintf(port_wwn, "%016llx",
2003fcf3ce44SJohn Forte (wwnConversion(port_wwn_data)));
2004fcf3ce44SJohn Forte switch (lap->cmd) {
2005fcf3ce44SJohn Forte case FPCFGA_STAT_FC_DEV:
2006fcf3ce44SJohn Forte /* if no match contine to the next path info node. */
2007fcf3ce44SJohn Forte if (strncmp(port_wwn, lap->apidp->dyncomp,
2008fcf3ce44SJohn Forte WWN_SIZE*2)) {
2009fcf3ce44SJohn Forte break;
2010fcf3ce44SJohn Forte }
2011fcf3ce44SJohn Forte /* if device in dev_list, ldata already created. */
2012fcf3ce44SJohn Forte if (lap->ret == FPCFGA_ACCESS_OK) {
2013fcf3ce44SJohn Forte lap->listp->ldata.ap_o_state =
2014fcf3ce44SJohn Forte CFGA_STAT_CONFIGURED;
2015fcf3ce44SJohn Forte if (((pstate = di_path_state(path)) ==
2016fcf3ce44SJohn Forte DI_PATH_STATE_OFFLINE) ||
2017fcf3ce44SJohn Forte (pstate == DI_PATH_STATE_FAULT)) {
2018fcf3ce44SJohn Forte lap->listp->ldata.ap_cond =
2019fcf3ce44SJohn Forte CFGA_COND_UNUSABLE;
2020fcf3ce44SJohn Forte }
2021fcf3ce44SJohn Forte lap->ret = FPCFGA_OK;
2022fcf3ce44SJohn Forte return (FPCFGA_OK);
2023fcf3ce44SJohn Forte } else {
2024fcf3ce44SJohn Forte if ((strcmp(lap->xport_type,
2025fcf3ce44SJohn Forte FP_FC_PUBLIC_PORT_TYPE) == 0) ||
2026fcf3ce44SJohn Forte (strcmp(lap->xport_type,
2027fcf3ce44SJohn Forte FP_FC_FABRIC_PORT_TYPE) == 0)) {
2028fcf3ce44SJohn Forte lap->chld_config = CFGA_STAT_CONFIGURED;
2029fcf3ce44SJohn Forte return (init_ldata_for_mpath_dev(
2030fcf3ce44SJohn Forte path, port_wwn, l_errnop, lap));
2031fcf3ce44SJohn Forte } else {
2032fcf3ce44SJohn Forte if ((di_path_state(path)) !=
2033fcf3ce44SJohn Forte DI_PATH_STATE_OFFLINE) {
2034fcf3ce44SJohn Forte return (init_ldata_for_mpath_dev(
2035fcf3ce44SJohn Forte path, port_wwn, l_errnop, lap));
2036fcf3ce44SJohn Forte } else {
2037fcf3ce44SJohn Forte lap->ret = FPCFGA_APID_NOEXIST;
2038fcf3ce44SJohn Forte return (FPCFGA_OK);
2039fcf3ce44SJohn Forte }
2040fcf3ce44SJohn Forte }
2041fcf3ce44SJohn Forte }
2042fcf3ce44SJohn Forte case FPCFGA_STAT_ALL:
2043fcf3ce44SJohn Forte /* check if there is list data. */
2044fcf3ce44SJohn Forte if (lap->listp != NULL) {
2045fcf3ce44SJohn Forte ret = is_dyn_ap_on_ldata_list(port_wwn,
2046fcf3ce44SJohn Forte lap->listp, &matchldp, l_errnop);
2047fcf3ce44SJohn Forte if (ret == FPCFGA_ACCESS_OK) {
2048fcf3ce44SJohn Forte lap->chld_config = CFGA_STAT_CONFIGURED;
2049fcf3ce44SJohn Forte matchldp->ldata.ap_o_state =
2050fcf3ce44SJohn Forte CFGA_STAT_CONFIGURED;
2051fcf3ce44SJohn Forte /*
2052fcf3ce44SJohn Forte * Update the condition as unusable
2053fcf3ce44SJohn Forte * if the pathinfo state is failed
2054fcf3ce44SJohn Forte * or offline.
2055fcf3ce44SJohn Forte */
2056fcf3ce44SJohn Forte if (((pstate = di_path_state(path)) ==
2057fcf3ce44SJohn Forte DI_PATH_STATE_OFFLINE) ||
2058fcf3ce44SJohn Forte (pstate ==
2059fcf3ce44SJohn Forte DI_PATH_STATE_FAULT)) {
2060fcf3ce44SJohn Forte matchldp->ldata.ap_cond =
2061fcf3ce44SJohn Forte CFGA_COND_UNUSABLE;
2062fcf3ce44SJohn Forte }
2063fcf3ce44SJohn Forte break;
2064fcf3ce44SJohn Forte } else if (ret == FPCFGA_LIB_ERR) {
2065fcf3ce44SJohn Forte lap->l_errno = *l_errnop;
2066fcf3ce44SJohn Forte return (ret);
2067fcf3ce44SJohn Forte }
2068fcf3ce44SJohn Forte }
2069fcf3ce44SJohn Forte /*
2070fcf3ce44SJohn Forte * now create ldata for this particular path info node.
2071fcf3ce44SJohn Forte * if port top is private loop and pathinfo is in
2072fcf3ce44SJohn Forte * in offline state don't include to ldata list.
2073fcf3ce44SJohn Forte */
2074fcf3ce44SJohn Forte if (((strcmp(lap->xport_type,
2075fcf3ce44SJohn Forte FP_FC_PUBLIC_PORT_TYPE) == 0) ||
2076fcf3ce44SJohn Forte (strcmp(lap->xport_type,
2077fcf3ce44SJohn Forte FP_FC_FABRIC_PORT_TYPE) == 0)) ||
2078fcf3ce44SJohn Forte (di_path_state(path) !=
2079fcf3ce44SJohn Forte DI_PATH_STATE_OFFLINE)) {
2080fcf3ce44SJohn Forte lap->chld_config = CFGA_STAT_CONFIGURED;
2081fcf3ce44SJohn Forte ret = init_ldata_for_mpath_dev(
2082fcf3ce44SJohn Forte path, port_wwn, l_errnop, lap);
2083fcf3ce44SJohn Forte if (ret != FPCFGA_OK) {
2084fcf3ce44SJohn Forte return (ret);
2085fcf3ce44SJohn Forte }
2086fcf3ce44SJohn Forte }
2087fcf3ce44SJohn Forte break;
2088fcf3ce44SJohn Forte case FPCFGA_STAT_FCA_PORT:
2089fcf3ce44SJohn Forte if (di_path_state(path) != DI_PATH_STATE_OFFLINE) {
2090fcf3ce44SJohn Forte lap->chld_config = CFGA_STAT_CONFIGURED;
2091fcf3ce44SJohn Forte return (FPCFGA_OK);
2092fcf3ce44SJohn Forte }
2093fcf3ce44SJohn Forte }
2094fcf3ce44SJohn Forte path = di_path_next_client(root, path);
2095fcf3ce44SJohn Forte } while (path != DI_PATH_NIL);
2096fcf3ce44SJohn Forte
2097fcf3ce44SJohn Forte return (FPCFGA_OK);
2098fcf3ce44SJohn Forte
2099fcf3ce44SJohn Forte }
2100fcf3ce44SJohn Forte
2101fcf3ce44SJohn Forte /*
2102fcf3ce44SJohn Forte * Routine for updating ldata list based on the state of path info node.
2103fcf3ce44SJohn Forte * When no matching accessible ldata is found a new ldata is created
2104fcf3ce44SJohn Forte * with proper state information.
2105fcf3ce44SJohn Forte *
2106fcf3ce44SJohn Forte * The difference from stat_path_info_fc_dev() is
2107fcf3ce44SJohn Forte * to handle FCP SCSI LUN information. Otherwise overall algorithm is
2108fcf3ce44SJohn Forte * same.
2109fcf3ce44SJohn Forte *
2110fcf3ce44SJohn Forte * Overall algorithm:
2111fcf3ce44SJohn Forte * If the path info node is not offline and the matching ldata is found
2112fcf3ce44SJohn Forte * the target device is updated with configued and unknown condition.
2113fcf3ce44SJohn Forte * If the path info node is offline or failed and the matching ldata is found
2114fcf3ce44SJohn Forte * the target device is updated with configued and unusable condition.
2115fcf3ce44SJohn Forte * If the path info node is online but the matching ldata is not found
2116fcf3ce44SJohn Forte * the target device is created with configued and failing condition.
2117fcf3ce44SJohn Forte * If the path info is offline or failed and the matching ldata is not found
2118fcf3ce44SJohn Forte * the target device is created with configued and unusable condition.
2119fcf3ce44SJohn Forte */
2120fcf3ce44SJohn Forte static int
stat_path_info_FCP_dev(di_node_t root,fpcfga_list_t * lap,int * l_errnop)2121fcf3ce44SJohn Forte stat_path_info_FCP_dev(
2122fcf3ce44SJohn Forte di_node_t root,
2123fcf3ce44SJohn Forte fpcfga_list_t *lap,
2124fcf3ce44SJohn Forte int *l_errnop)
2125fcf3ce44SJohn Forte {
2126fcf3ce44SJohn Forte ldata_list_t *matchldp = NULL, *listp = NULL;
2127fcf3ce44SJohn Forte cfga_list_data_t *clp;
2128fcf3ce44SJohn Forte di_path_t path = DI_PATH_NIL;
2129fcf3ce44SJohn Forte di_node_t client_node = DI_NODE_NIL;
2130fcf3ce44SJohn Forte char *port_wwn = NULL, *nodepath = NULL;
2131fcf3ce44SJohn Forte int *lun_nump;
2132fcf3ce44SJohn Forte fpcfga_ret_t ldata_ret;
2133fcf3ce44SJohn Forte di_path_state_t pstate;
2134fcf3ce44SJohn Forte cfga_busy_t busy;
2135fcf3ce44SJohn Forte uint_t dctl_state = 0;
2136fcf3ce44SJohn Forte
2137fcf3ce44SJohn Forte if (root == DI_NODE_NIL) {
2138fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
2139fcf3ce44SJohn Forte }
2140fcf3ce44SJohn Forte
2141fcf3ce44SJohn Forte /*
2142fcf3ce44SJohn Forte * if stat on a fca xport and chld_config is set
2143fcf3ce44SJohn Forte * then just return ok.
2144fcf3ce44SJohn Forte */
2145fcf3ce44SJohn Forte if ((lap->cmd == FPCFGA_STAT_FCA_PORT) &&
2146fcf3ce44SJohn Forte (lap->chld_config == CFGA_STAT_CONFIGURED)) {
2147fcf3ce44SJohn Forte return (FPCFGA_OK);
2148fcf3ce44SJohn Forte }
2149fcf3ce44SJohn Forte /*
2150fcf3ce44SJohn Forte * when there is no path_info node return FPCFGA_OK.
2151fcf3ce44SJohn Forte * That way the result from walk_node shall be maintained.
2152fcf3ce44SJohn Forte */
2153fcf3ce44SJohn Forte if ((path = di_path_next_client(root, path)) == DI_PATH_NIL) {
2154fcf3ce44SJohn Forte /*
2155fcf3ce44SJohn Forte * if the dev was in dev list but not found
2156fcf3ce44SJohn Forte * return ok.
2157fcf3ce44SJohn Forte */
2158fcf3ce44SJohn Forte if (lap->ret == FPCFGA_ACCESS_OK) {
2159fcf3ce44SJohn Forte lap->ret = FPCFGA_OK;
2160fcf3ce44SJohn Forte }
2161fcf3ce44SJohn Forte return (FPCFGA_OK);
2162fcf3ce44SJohn Forte }
2163fcf3ce44SJohn Forte /*
2164fcf3ce44SJohn Forte * If stat on fca port and port topology is fabric return here.
2165fcf3ce44SJohn Forte * If not fabric return only when path state is not offfline.
2166fcf3ce44SJohn Forte * The other cases are handbled below.
2167fcf3ce44SJohn Forte */
2168fcf3ce44SJohn Forte if (lap->cmd == FPCFGA_STAT_FCA_PORT) {
2169fcf3ce44SJohn Forte if (((strcmp(lap->xport_type, FP_FC_FABRIC_PORT_TYPE) == 0) ||
2170fcf3ce44SJohn Forte strcmp(lap->xport_type, FP_FC_PUBLIC_PORT_TYPE) == 0)) {
2171fcf3ce44SJohn Forte lap->chld_config = CFGA_STAT_CONFIGURED;
2172fcf3ce44SJohn Forte return (FPCFGA_OK);
2173fcf3ce44SJohn Forte } else {
2174fcf3ce44SJohn Forte if ((pstate = di_path_state(path)) !=
2175fcf3ce44SJohn Forte DI_PATH_STATE_OFFLINE) {
2176fcf3ce44SJohn Forte lap->chld_config = CFGA_STAT_CONFIGURED;
2177fcf3ce44SJohn Forte return (FPCFGA_OK);
2178fcf3ce44SJohn Forte }
2179fcf3ce44SJohn Forte }
2180fcf3ce44SJohn Forte }
2181fcf3ce44SJohn Forte /*
2182fcf3ce44SJohn Forte * now parse the path info node.
2183fcf3ce44SJohn Forte */
2184fcf3ce44SJohn Forte do {
2185fcf3ce44SJohn Forte switch (lap->cmd) {
2186fcf3ce44SJohn Forte case FPCFGA_STAT_FC_DEV:
2187fcf3ce44SJohn Forte if ((make_portwwn_luncomp_from_pinode(path, &port_wwn,
2188fcf3ce44SJohn Forte &lun_nump, l_errnop)) != FPCFGA_OK) {
2189fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
2190fcf3ce44SJohn Forte }
2191fcf3ce44SJohn Forte
2192fcf3ce44SJohn Forte if ((ldata_ret = is_FCP_dev_ap_on_ldata_list(port_wwn,
2193fcf3ce44SJohn Forte *lun_nump, lap->listp, &matchldp))
2194fcf3ce44SJohn Forte == FPCFGA_LIB_ERR) {
2195fcf3ce44SJohn Forte S_FREE(port_wwn);
2196fcf3ce44SJohn Forte return (ldata_ret);
2197fcf3ce44SJohn Forte }
2198fcf3ce44SJohn Forte
2199fcf3ce44SJohn Forte if (ldata_ret == FPCFGA_ACCESS_OK) {
2200fcf3ce44SJohn Forte lap->chld_config = CFGA_STAT_CONFIGURED;
2201fcf3ce44SJohn Forte matchldp->ldata.ap_o_state =
2202fcf3ce44SJohn Forte CFGA_STAT_CONFIGURED;
2203fcf3ce44SJohn Forte /*
2204fcf3ce44SJohn Forte * Update the condition as unusable
2205fcf3ce44SJohn Forte * if the pathinfo state is failed
2206fcf3ce44SJohn Forte * or offline.
2207fcf3ce44SJohn Forte */
2208fcf3ce44SJohn Forte if (((pstate = di_path_state(path)) ==
2209fcf3ce44SJohn Forte DI_PATH_STATE_OFFLINE) ||
2210fcf3ce44SJohn Forte (pstate == DI_PATH_STATE_FAULT)) {
2211fcf3ce44SJohn Forte matchldp->ldata.ap_cond =
2212fcf3ce44SJohn Forte CFGA_COND_UNUSABLE;
2213fcf3ce44SJohn Forte }
2214fcf3ce44SJohn Forte lap->ret = FPCFGA_OK;
2215fcf3ce44SJohn Forte break;
2216fcf3ce44SJohn Forte }
2217fcf3ce44SJohn Forte
2218fcf3ce44SJohn Forte if (strncmp(port_wwn, lap->apidp->dyncomp, WWN_SIZE*2)
2219fcf3ce44SJohn Forte != 0) {
2220fcf3ce44SJohn Forte break;
2221fcf3ce44SJohn Forte }
2222fcf3ce44SJohn Forte /*
2223fcf3ce44SJohn Forte * now create ldata for this particular path info node.
2224fcf3ce44SJohn Forte * if port top is private loop and pathinfo is in
2225fcf3ce44SJohn Forte * in offline state don't include to ldata list.
2226fcf3ce44SJohn Forte */
2227fcf3ce44SJohn Forte if (((strcmp(lap->xport_type,
2228fcf3ce44SJohn Forte FP_FC_PUBLIC_PORT_TYPE) == 0) ||
2229fcf3ce44SJohn Forte (strcmp(lap->xport_type,
2230fcf3ce44SJohn Forte FP_FC_FABRIC_PORT_TYPE) == 0)) ||
2231fcf3ce44SJohn Forte (di_path_state(path) !=
2232fcf3ce44SJohn Forte DI_PATH_STATE_OFFLINE)) {
2233fcf3ce44SJohn Forte lap->chld_config = CFGA_STAT_CONFIGURED;
2234fcf3ce44SJohn Forte /* create ldata for this pi node. */
2235fcf3ce44SJohn Forte client_node = di_path_client_node(path);
2236fcf3ce44SJohn Forte if (client_node == DI_NODE_NIL) {
2237fcf3ce44SJohn Forte *l_errnop = errno;
2238fcf3ce44SJohn Forte S_FREE(port_wwn);
2239fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
2240fcf3ce44SJohn Forte }
2241fcf3ce44SJohn Forte if ((construct_nodepath_from_dinode(
2242fcf3ce44SJohn Forte client_node, &nodepath, l_errnop))
2243fcf3ce44SJohn Forte != FPCFGA_OK) {
2244fcf3ce44SJohn Forte S_FREE(port_wwn);
2245fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
2246fcf3ce44SJohn Forte }
2247fcf3ce44SJohn Forte
2248fcf3ce44SJohn Forte listp = calloc(1, sizeof (ldata_list_t));
2249fcf3ce44SJohn Forte if (listp == NULL) {
2250fcf3ce44SJohn Forte S_FREE(port_wwn);
2251fcf3ce44SJohn Forte S_FREE(nodepath);
2252fcf3ce44SJohn Forte lap->l_errno = errno;
2253fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
2254fcf3ce44SJohn Forte }
2255fcf3ce44SJohn Forte
2256fcf3ce44SJohn Forte clp = &listp->ldata;
2257fcf3ce44SJohn Forte
2258fcf3ce44SJohn Forte /* Create logical and physical ap_id */
2259fcf3ce44SJohn Forte (void) snprintf(clp->ap_log_id,
2260fcf3ce44SJohn Forte sizeof (clp->ap_log_id), "%s%s%s%s%d",
2261fcf3ce44SJohn Forte lap->xport_logp, DYN_SEP, port_wwn,
2262fcf3ce44SJohn Forte LUN_COMP_SEP, *lun_nump);
2263fcf3ce44SJohn Forte (void) snprintf(clp->ap_phys_id,
2264fcf3ce44SJohn Forte sizeof (clp->ap_phys_id), "%s%s%s%s%d",
2265fcf3ce44SJohn Forte lap->apidp->xport_phys, DYN_SEP, port_wwn,
2266fcf3ce44SJohn Forte LUN_COMP_SEP, *lun_nump);
2267fcf3ce44SJohn Forte /*
2268fcf3ce44SJohn Forte * We reached here since FCP dev is not found
2269fcf3ce44SJohn Forte * in ldata list but path info node exists.
2270fcf3ce44SJohn Forte *
2271fcf3ce44SJohn Forte * Update the condition as failing
2272fcf3ce44SJohn Forte * if the pathinfo state was normal.
2273fcf3ce44SJohn Forte * Update the condition as unusable
2274fcf3ce44SJohn Forte * if the pathinfo state is failed
2275fcf3ce44SJohn Forte * or offline.
2276fcf3ce44SJohn Forte */
2277fcf3ce44SJohn Forte clp->ap_class[0] = '\0'; /* Filled by libcfgadm */
2278fcf3ce44SJohn Forte clp->ap_o_state = CFGA_STAT_CONFIGURED;
2279fcf3ce44SJohn Forte if (((pstate = di_path_state(path))
2280fcf3ce44SJohn Forte == DI_PATH_STATE_OFFLINE) ||
2281fcf3ce44SJohn Forte (pstate == DI_PATH_STATE_FAULT)) {
2282fcf3ce44SJohn Forte clp->ap_cond = CFGA_COND_UNUSABLE;
2283fcf3ce44SJohn Forte } else {
2284fcf3ce44SJohn Forte clp->ap_cond = CFGA_COND_FAILING;
2285fcf3ce44SJohn Forte }
2286fcf3ce44SJohn Forte clp->ap_r_state = lap->xport_rstate;
2287fcf3ce44SJohn Forte clp->ap_info[0] = '\0';
2288fcf3ce44SJohn Forte /* update ap_type and ap_info */
2289fcf3ce44SJohn Forte get_hw_info(client_node, clp);
2290fcf3ce44SJohn Forte if (devctl_cmd(nodepath, FPCFGA_DEV_GETSTATE,
2291fcf3ce44SJohn Forte &dctl_state, l_errnop) == FPCFGA_OK) {
2292fcf3ce44SJohn Forte busy = ((dctl_state & DEVICE_BUSY)
2293fcf3ce44SJohn Forte == DEVICE_BUSY) ? 1 : 0;
2294fcf3ce44SJohn Forte } else {
2295fcf3ce44SJohn Forte busy = 0;
2296fcf3ce44SJohn Forte }
2297fcf3ce44SJohn Forte clp->ap_busy = busy;
2298fcf3ce44SJohn Forte clp->ap_status_time = (time_t)-1;
2299fcf3ce44SJohn Forte
2300fcf3ce44SJohn Forte (void) insert_ldata_to_ldatalist(port_wwn,
2301fcf3ce44SJohn Forte lun_nump, listp, &(lap->listp));
2302fcf3ce44SJohn Forte }
2303fcf3ce44SJohn Forte break;
2304fcf3ce44SJohn Forte case FPCFGA_STAT_ALL:
2305fcf3ce44SJohn Forte if ((make_portwwn_luncomp_from_pinode(path, &port_wwn,
2306fcf3ce44SJohn Forte &lun_nump, l_errnop)) != FPCFGA_OK) {
2307fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
2308fcf3ce44SJohn Forte }
2309fcf3ce44SJohn Forte
2310fcf3ce44SJohn Forte if ((ldata_ret = is_FCP_dev_ap_on_ldata_list(port_wwn,
2311fcf3ce44SJohn Forte *lun_nump, lap->listp, &matchldp))
2312fcf3ce44SJohn Forte == FPCFGA_LIB_ERR) {
2313fcf3ce44SJohn Forte S_FREE(port_wwn);
2314fcf3ce44SJohn Forte return (ldata_ret);
2315fcf3ce44SJohn Forte }
2316fcf3ce44SJohn Forte
2317fcf3ce44SJohn Forte if (ldata_ret == FPCFGA_ACCESS_OK) {
2318fcf3ce44SJohn Forte lap->chld_config = CFGA_STAT_CONFIGURED;
2319fcf3ce44SJohn Forte matchldp->ldata.ap_o_state =
2320fcf3ce44SJohn Forte CFGA_STAT_CONFIGURED;
2321fcf3ce44SJohn Forte /*
2322fcf3ce44SJohn Forte * Update the condition as unusable
2323fcf3ce44SJohn Forte * if the pathinfo state is failed
2324fcf3ce44SJohn Forte * or offline.
2325fcf3ce44SJohn Forte */
2326fcf3ce44SJohn Forte if (((pstate = di_path_state(path)) ==
2327fcf3ce44SJohn Forte DI_PATH_STATE_OFFLINE) ||
2328fcf3ce44SJohn Forte (pstate == DI_PATH_STATE_FAULT)) {
2329fcf3ce44SJohn Forte matchldp->ldata.ap_cond =
2330fcf3ce44SJohn Forte CFGA_COND_UNUSABLE;
2331fcf3ce44SJohn Forte }
2332fcf3ce44SJohn Forte break;
2333fcf3ce44SJohn Forte }
2334fcf3ce44SJohn Forte /*
2335fcf3ce44SJohn Forte * now create ldata for this particular path info node.
2336fcf3ce44SJohn Forte * if port top is private loop and pathinfo is in
2337fcf3ce44SJohn Forte * in offline state don't include to ldata list.
2338fcf3ce44SJohn Forte */
2339fcf3ce44SJohn Forte if (((strcmp(lap->xport_type,
2340fcf3ce44SJohn Forte FP_FC_PUBLIC_PORT_TYPE) == 0) ||
2341fcf3ce44SJohn Forte (strcmp(lap->xport_type,
2342fcf3ce44SJohn Forte FP_FC_FABRIC_PORT_TYPE) == 0)) ||
2343fcf3ce44SJohn Forte (di_path_state(path) !=
2344fcf3ce44SJohn Forte DI_PATH_STATE_OFFLINE)) {
2345fcf3ce44SJohn Forte lap->chld_config = CFGA_STAT_CONFIGURED;
2346fcf3ce44SJohn Forte /* create ldata for this pi node. */
2347fcf3ce44SJohn Forte client_node = di_path_client_node(path);
2348fcf3ce44SJohn Forte if (client_node == DI_NODE_NIL) {
2349fcf3ce44SJohn Forte *l_errnop = errno;
2350fcf3ce44SJohn Forte S_FREE(port_wwn);
2351fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
2352fcf3ce44SJohn Forte }
2353fcf3ce44SJohn Forte if ((construct_nodepath_from_dinode(
2354fcf3ce44SJohn Forte client_node, &nodepath, l_errnop))
2355fcf3ce44SJohn Forte != FPCFGA_OK) {
2356fcf3ce44SJohn Forte S_FREE(port_wwn);
2357fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
2358fcf3ce44SJohn Forte }
2359fcf3ce44SJohn Forte
2360fcf3ce44SJohn Forte listp = calloc(1, sizeof (ldata_list_t));
2361fcf3ce44SJohn Forte if (listp == NULL) {
2362fcf3ce44SJohn Forte S_FREE(port_wwn);
2363fcf3ce44SJohn Forte S_FREE(nodepath);
2364fcf3ce44SJohn Forte lap->l_errno = errno;
2365fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
2366fcf3ce44SJohn Forte }
2367fcf3ce44SJohn Forte
2368fcf3ce44SJohn Forte clp = &listp->ldata;
2369fcf3ce44SJohn Forte
2370fcf3ce44SJohn Forte /* Create logical and physical ap_id */
2371fcf3ce44SJohn Forte (void) snprintf(clp->ap_log_id,
2372fcf3ce44SJohn Forte sizeof (clp->ap_log_id), "%s%s%s%s%d",
2373fcf3ce44SJohn Forte lap->xport_logp, DYN_SEP, port_wwn,
2374fcf3ce44SJohn Forte LUN_COMP_SEP, *lun_nump);
2375fcf3ce44SJohn Forte (void) snprintf(clp->ap_phys_id,
2376fcf3ce44SJohn Forte sizeof (clp->ap_phys_id), "%s%s%s%s%d",
2377fcf3ce44SJohn Forte lap->apidp->xport_phys, DYN_SEP, port_wwn,
2378fcf3ce44SJohn Forte LUN_COMP_SEP, *lun_nump);
2379fcf3ce44SJohn Forte /*
2380fcf3ce44SJohn Forte * We reached here since FCP dev is not found
2381fcf3ce44SJohn Forte * in ldata list but path info node exists.
2382fcf3ce44SJohn Forte *
2383fcf3ce44SJohn Forte * Update the condition as failing
2384fcf3ce44SJohn Forte * if the pathinfo state was normal.
2385fcf3ce44SJohn Forte * Update the condition as unusable
2386fcf3ce44SJohn Forte * if the pathinfo state is failed
2387fcf3ce44SJohn Forte * or offline.
2388fcf3ce44SJohn Forte */
2389fcf3ce44SJohn Forte clp->ap_class[0] = '\0'; /* Filled by libcfgadm */
2390fcf3ce44SJohn Forte clp->ap_o_state = CFGA_STAT_CONFIGURED;
2391fcf3ce44SJohn Forte if (((pstate = di_path_state(path))
2392fcf3ce44SJohn Forte == DI_PATH_STATE_OFFLINE) ||
2393fcf3ce44SJohn Forte (pstate == DI_PATH_STATE_FAULT)) {
2394fcf3ce44SJohn Forte clp->ap_cond = CFGA_COND_UNUSABLE;
2395fcf3ce44SJohn Forte } else {
2396fcf3ce44SJohn Forte clp->ap_cond = CFGA_COND_FAILING;
2397fcf3ce44SJohn Forte }
2398fcf3ce44SJohn Forte clp->ap_r_state = lap->xport_rstate;
2399fcf3ce44SJohn Forte clp->ap_info[0] = '\0';
2400fcf3ce44SJohn Forte /* update ap_type and ap_info */
2401fcf3ce44SJohn Forte get_hw_info(client_node, clp);
2402fcf3ce44SJohn Forte if (devctl_cmd(nodepath, FPCFGA_DEV_GETSTATE,
2403fcf3ce44SJohn Forte &dctl_state, l_errnop) == FPCFGA_OK) {
2404fcf3ce44SJohn Forte busy = ((dctl_state & DEVICE_BUSY)
2405fcf3ce44SJohn Forte == DEVICE_BUSY) ? 1 : 0;
2406fcf3ce44SJohn Forte } else {
2407fcf3ce44SJohn Forte busy = 0;
2408fcf3ce44SJohn Forte }
2409fcf3ce44SJohn Forte clp->ap_busy = busy;
2410fcf3ce44SJohn Forte clp->ap_status_time = (time_t)-1;
2411fcf3ce44SJohn Forte
2412fcf3ce44SJohn Forte (void) insert_ldata_to_ldatalist(port_wwn,
2413fcf3ce44SJohn Forte lun_nump, listp, &(lap->listp));
2414fcf3ce44SJohn Forte }
2415fcf3ce44SJohn Forte break;
2416fcf3ce44SJohn Forte case FPCFGA_STAT_FCA_PORT:
2417fcf3ce44SJohn Forte if (di_path_state(path) != DI_PATH_STATE_OFFLINE) {
2418fcf3ce44SJohn Forte lap->chld_config = CFGA_STAT_CONFIGURED;
2419fcf3ce44SJohn Forte lap->ret = FPCFGA_OK;
2420fcf3ce44SJohn Forte return (FPCFGA_OK);
2421fcf3ce44SJohn Forte }
2422fcf3ce44SJohn Forte }
2423fcf3ce44SJohn Forte path = di_path_next_client(root, path);
2424fcf3ce44SJohn Forte } while (path != DI_PATH_NIL);
2425fcf3ce44SJohn Forte
2426fcf3ce44SJohn Forte lap->ret = FPCFGA_OK;
2427fcf3ce44SJohn Forte S_FREE(port_wwn);
2428fcf3ce44SJohn Forte S_FREE(nodepath);
2429fcf3ce44SJohn Forte return (FPCFGA_OK);
2430fcf3ce44SJohn Forte
2431fcf3ce44SJohn Forte }
2432fcf3ce44SJohn Forte
2433fcf3ce44SJohn Forte /*
2434fcf3ce44SJohn Forte * Routine for updating ldata list based on the state of device node.
2435fcf3ce44SJohn Forte * When no matching accessible ldata is found a new ldata is created
2436fcf3ce44SJohn Forte * with proper state information.
2437fcf3ce44SJohn Forte *
2438fcf3ce44SJohn Forte * The difference from do_stat_fc_dev() is
2439fcf3ce44SJohn Forte * to handle FCP SCSI LUN information. Otherwise overall algorithm is
2440fcf3ce44SJohn Forte * same.
2441fcf3ce44SJohn Forte *
2442fcf3ce44SJohn Forte * Overall algorithm:
2443fcf3ce44SJohn Forte * If the device node is online and the matching ldata is found
2444fcf3ce44SJohn Forte * the target device is updated with configued and unknown condition.
2445fcf3ce44SJohn Forte * If the device node is offline or down and the matching ldata is found
2446fcf3ce44SJohn Forte * the target device is updated with configued and unusable condition.
2447fcf3ce44SJohn Forte * If the device node is online but the matching ldata is not found
2448fcf3ce44SJohn Forte * the target device is created with configued and failing condition.
2449fcf3ce44SJohn Forte * If the device node is offline or down and the matching ldata is not found
2450fcf3ce44SJohn Forte * the target device is created with configued and unusable condition.
2451fcf3ce44SJohn Forte */
2452fcf3ce44SJohn Forte static fpcfga_ret_t
do_stat_FCP_dev(const di_node_t node,const char * nodepath,fpcfga_list_t * lap,int limited_stat)2453fcf3ce44SJohn Forte do_stat_FCP_dev(
2454fcf3ce44SJohn Forte const di_node_t node,
2455fcf3ce44SJohn Forte const char *nodepath,
2456fcf3ce44SJohn Forte fpcfga_list_t *lap,
2457fcf3ce44SJohn Forte int limited_stat)
2458fcf3ce44SJohn Forte {
2459fcf3ce44SJohn Forte uint_t dctl_state = 0, devinfo_state = 0;
2460fcf3ce44SJohn Forte char *port_wwn = NULL;
2461fcf3ce44SJohn Forte cfga_list_data_t *clp = NULL;
2462fcf3ce44SJohn Forte cfga_busy_t busy;
2463fcf3ce44SJohn Forte ldata_list_t *listp = NULL;
2464fcf3ce44SJohn Forte ldata_list_t *matchldp = NULL;
2465fcf3ce44SJohn Forte int l_errno = 0, *lun_nump;
2466fcf3ce44SJohn Forte cfga_stat_t ostate;
2467fcf3ce44SJohn Forte cfga_cond_t cond;
2468fcf3ce44SJohn Forte fpcfga_ret_t ldata_ret;
2469fcf3ce44SJohn Forte
2470fcf3ce44SJohn Forte assert(lap->apidp->xport_phys != NULL);
2471fcf3ce44SJohn Forte assert(lap->xport_logp != NULL);
2472fcf3ce44SJohn Forte
2473fcf3ce44SJohn Forte cond = CFGA_COND_UNKNOWN;
2474fcf3ce44SJohn Forte
2475fcf3ce44SJohn Forte devinfo_state = di_state(node);
2476fcf3ce44SJohn Forte ostate = dev_devinfo_to_occupant_state(devinfo_state);
2477fcf3ce44SJohn Forte
2478fcf3ce44SJohn Forte /*
2479fcf3ce44SJohn Forte * NOTE: The devctl framework cannot currently detect layered driver
2480fcf3ce44SJohn Forte * opens, so the busy indicator is not very reliable. Also,
2481fcf3ce44SJohn Forte * non-root users will not be able to determine busy
2482fcf3ce44SJohn Forte * status (libdevice needs root permissions).
2483fcf3ce44SJohn Forte * This should probably be fixed by adding a DI_BUSY to the di_state()
2484fcf3ce44SJohn Forte * routine in libdevinfo.
2485fcf3ce44SJohn Forte */
2486fcf3ce44SJohn Forte if (devctl_cmd(nodepath, FPCFGA_DEV_GETSTATE, &dctl_state,
2487fcf3ce44SJohn Forte &l_errno) == FPCFGA_OK) {
2488fcf3ce44SJohn Forte busy = ((dctl_state & DEVICE_BUSY) == DEVICE_BUSY) ? 1 : 0;
2489fcf3ce44SJohn Forte } else {
2490fcf3ce44SJohn Forte busy = 0;
2491fcf3ce44SJohn Forte }
2492fcf3ce44SJohn Forte
2493fcf3ce44SJohn Forte /* We only want to know device config state */
2494fcf3ce44SJohn Forte if (limited_stat) {
2495fcf3ce44SJohn Forte if (((strcmp(lap->xport_type, FP_FC_FABRIC_PORT_TYPE) == 0) ||
2496fcf3ce44SJohn Forte strcmp(lap->xport_type, FP_FC_PUBLIC_PORT_TYPE) == 0)) {
2497fcf3ce44SJohn Forte lap->chld_config = CFGA_STAT_CONFIGURED;
2498fcf3ce44SJohn Forte } else {
2499fcf3ce44SJohn Forte if (ostate != CFGA_STAT_UNCONFIGURED) {
2500fcf3ce44SJohn Forte lap->chld_config = CFGA_STAT_CONFIGURED;
2501fcf3ce44SJohn Forte }
2502fcf3ce44SJohn Forte }
2503fcf3ce44SJohn Forte return (FPCFGA_OK);
2504fcf3ce44SJohn Forte }
2505fcf3ce44SJohn Forte
2506fcf3ce44SJohn Forte /*
2507fcf3ce44SJohn Forte * If child device is configured, see if it is accessible also
2508fcf3ce44SJohn Forte * for FPCFGA_STAT_FC_DEV cmd.
2509fcf3ce44SJohn Forte */
2510fcf3ce44SJohn Forte if ((make_portwwn_luncomp_from_dinode(node, &port_wwn, &lun_nump,
2511fcf3ce44SJohn Forte &l_errno)) != FPCFGA_OK) {
2512fcf3ce44SJohn Forte lap->l_errno = l_errno;
2513fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
2514fcf3ce44SJohn Forte }
2515fcf3ce44SJohn Forte
2516fcf3ce44SJohn Forte if ((ldata_ret = is_FCP_dev_ap_on_ldata_list(port_wwn, *lun_nump,
2517fcf3ce44SJohn Forte lap->listp, &matchldp)) == FPCFGA_LIB_ERR) {
2518fcf3ce44SJohn Forte lap->l_errno = l_errno;
2519fcf3ce44SJohn Forte S_FREE(port_wwn);
2520fcf3ce44SJohn Forte return (ldata_ret);
2521fcf3ce44SJohn Forte }
2522fcf3ce44SJohn Forte
2523fcf3ce44SJohn Forte if (lap->cmd == FPCFGA_STAT_FC_DEV) {
2524fcf3ce44SJohn Forte switch (ostate) {
2525fcf3ce44SJohn Forte case CFGA_STAT_CONFIGURED:
2526fcf3ce44SJohn Forte /*
2527fcf3ce44SJohn Forte * if configured and not accessble, the device is
2528fcf3ce44SJohn Forte * till be displayed with failing condition.
2529fcf3ce44SJohn Forte * return code should be FPCFGA_OK to display it.
2530fcf3ce44SJohn Forte */
2531fcf3ce44SJohn Forte case CFGA_STAT_NONE:
2532fcf3ce44SJohn Forte /*
2533fcf3ce44SJohn Forte * If not unconfigured and not attached
2534fcf3ce44SJohn Forte * the state is set to CFGA_STAT_NONE currently.
2535fcf3ce44SJohn Forte * This is okay for the detached node due to
2536fcf3ce44SJohn Forte * the driver being unloaded.
2537fcf3ce44SJohn Forte * May need to define another state to
2538fcf3ce44SJohn Forte * isolate the detached only state.
2539fcf3ce44SJohn Forte *
2540fcf3ce44SJohn Forte * handle the same way as configured.
2541fcf3ce44SJohn Forte */
2542fcf3ce44SJohn Forte if (ldata_ret != FPCFGA_ACCESS_OK) {
2543fcf3ce44SJohn Forte cond = CFGA_COND_FAILING;
2544fcf3ce44SJohn Forte }
2545fcf3ce44SJohn Forte lap->chld_config = CFGA_STAT_CONFIGURED;
2546fcf3ce44SJohn Forte break;
2547fcf3ce44SJohn Forte case CFGA_STAT_UNCONFIGURED:
2548fcf3ce44SJohn Forte /*
2549fcf3ce44SJohn Forte * if unconfigured - offline or down,
2550fcf3ce44SJohn Forte * set to cond to unusable regardless of accessibility.
2551fcf3ce44SJohn Forte * This behavior needs to be examined further.
2552fcf3ce44SJohn Forte * When the device is not accessible the node
2553fcf3ce44SJohn Forte * may get offline or down. In that case failing
2554fcf3ce44SJohn Forte * cond may make more sense.
2555fcf3ce44SJohn Forte * In anycase the ostate will be set to configured
2556fcf3ce44SJohn Forte * configured.
2557fcf3ce44SJohn Forte */
2558fcf3ce44SJohn Forte cond = CFGA_COND_UNUSABLE;
2559fcf3ce44SJohn Forte /*
2560fcf3ce44SJohn Forte * For fabric port the fca port is considered as
2561fcf3ce44SJohn Forte * configured since user configured previously
2562fcf3ce44SJohn Forte * for any existing node. Otherwise when the
2563fcf3ce44SJohn Forte * device was accessible, the hba is considered as
2564fcf3ce44SJohn Forte * configured.
2565fcf3ce44SJohn Forte */
2566fcf3ce44SJohn Forte if (((strcmp(lap->xport_type,
2567fcf3ce44SJohn Forte FP_FC_PUBLIC_PORT_TYPE) == 0) ||
2568fcf3ce44SJohn Forte (strcmp(lap->xport_type,
2569fcf3ce44SJohn Forte FP_FC_FABRIC_PORT_TYPE) == 0)) ||
2570fcf3ce44SJohn Forte (lap->ret == FPCFGA_ACCESS_OK)) {
2571fcf3ce44SJohn Forte lap->chld_config = CFGA_STAT_CONFIGURED;
2572fcf3ce44SJohn Forte } else {
2573fcf3ce44SJohn Forte /*
2574fcf3ce44SJohn Forte * if lap->ret is okay there is at least
2575fcf3ce44SJohn Forte * one matching ldata exist. Need to keep
2576fcf3ce44SJohn Forte * okay ret to display the matching ones.
2577fcf3ce44SJohn Forte */
2578fcf3ce44SJohn Forte if (lap->ret != FPCFGA_OK) {
2579fcf3ce44SJohn Forte lap->ret = FPCFGA_APID_NOEXIST;
2580fcf3ce44SJohn Forte }
2581fcf3ce44SJohn Forte S_FREE(port_wwn);
2582fcf3ce44SJohn Forte return (FPCFGA_OK);
2583fcf3ce44SJohn Forte }
2584fcf3ce44SJohn Forte break;
2585fcf3ce44SJohn Forte default:
2586fcf3ce44SJohn Forte break;
2587fcf3ce44SJohn Forte }
2588fcf3ce44SJohn Forte
2589fcf3ce44SJohn Forte /* if device found in dev_list, ldata already created. */
2590fcf3ce44SJohn Forte if (ldata_ret == FPCFGA_ACCESS_OK) {
2591fcf3ce44SJohn Forte /*
2592fcf3ce44SJohn Forte * if cond is not changed then don't update
2593fcf3ce44SJohn Forte * condition to keep any condtion
2594fcf3ce44SJohn Forte * from initial discovery. If the initial
2595fcf3ce44SJohn Forte * cond was failed the same condition will be kept.
2596fcf3ce44SJohn Forte */
2597fcf3ce44SJohn Forte if (cond != CFGA_COND_UNKNOWN) {
2598fcf3ce44SJohn Forte matchldp->ldata.ap_cond = cond;
2599fcf3ce44SJohn Forte }
2600fcf3ce44SJohn Forte matchldp->ldata.ap_o_state = CFGA_STAT_CONFIGURED;
2601fcf3ce44SJohn Forte matchldp->ldata.ap_busy = busy;
2602fcf3ce44SJohn Forte /* update ap_info via inquiry */
2603fcf3ce44SJohn Forte clp = &matchldp->ldata;
2604fcf3ce44SJohn Forte /* update ap_type and ap_info */
2605fcf3ce44SJohn Forte get_hw_info(node, clp);
2606fcf3ce44SJohn Forte lap->ret = FPCFGA_OK;
2607fcf3ce44SJohn Forte S_FREE(port_wwn);
2608fcf3ce44SJohn Forte return (FPCFGA_OK);
2609fcf3ce44SJohn Forte }
2610fcf3ce44SJohn Forte }
2611fcf3ce44SJohn Forte
2612fcf3ce44SJohn Forte /*
2613fcf3ce44SJohn Forte * if cmd is stat all check ldata list
2614fcf3ce44SJohn Forte * to see if the node exist on the dev list. Otherwise create
2615fcf3ce44SJohn Forte * the list element.
2616fcf3ce44SJohn Forte */
2617fcf3ce44SJohn Forte if (lap->cmd == FPCFGA_STAT_ALL) {
2618fcf3ce44SJohn Forte switch (ldata_ret) {
2619fcf3ce44SJohn Forte case FPCFGA_ACCESS_OK:
2620fcf3ce44SJohn Forte /* node exists so set ostate to configured. */
2621fcf3ce44SJohn Forte lap->chld_config = CFGA_STAT_CONFIGURED;
2622fcf3ce44SJohn Forte matchldp->ldata.ap_o_state =
2623fcf3ce44SJohn Forte CFGA_STAT_CONFIGURED;
2624fcf3ce44SJohn Forte matchldp->ldata.ap_busy = busy;
2625fcf3ce44SJohn Forte clp = &matchldp->ldata;
2626fcf3ce44SJohn Forte switch (ostate) {
2627fcf3ce44SJohn Forte case CFGA_STAT_CONFIGURED:
2628fcf3ce44SJohn Forte /*
2629fcf3ce44SJohn Forte * If not unconfigured and not attached
2630fcf3ce44SJohn Forte * the state is set to CFGA_STAT_NONE currently.
2631fcf3ce44SJohn Forte * This is okay for the detached node due to
2632fcf3ce44SJohn Forte * the driver being unloaded.
2633fcf3ce44SJohn Forte * May need to define another state to
2634fcf3ce44SJohn Forte * isolate the detached only state.
2635fcf3ce44SJohn Forte */
2636fcf3ce44SJohn Forte case CFGA_STAT_NONE:
2637fcf3ce44SJohn Forte /* update ap_type and ap_info */
2638fcf3ce44SJohn Forte get_hw_info(node, clp);
2639fcf3ce44SJohn Forte break;
2640fcf3ce44SJohn Forte /*
2641fcf3ce44SJohn Forte * node is offline or down.
2642fcf3ce44SJohn Forte * set cond to unusable.
2643fcf3ce44SJohn Forte */
2644fcf3ce44SJohn Forte case CFGA_STAT_UNCONFIGURED:
2645fcf3ce44SJohn Forte /*
2646fcf3ce44SJohn Forte * if cond is not unknown
2647fcf3ce44SJohn Forte * initial probing was failed
2648fcf3ce44SJohn Forte * so don't update again.
2649fcf3ce44SJohn Forte */
2650fcf3ce44SJohn Forte if (matchldp->ldata.ap_cond ==
2651fcf3ce44SJohn Forte CFGA_COND_UNKNOWN) {
2652fcf3ce44SJohn Forte matchldp->ldata.ap_cond =
2653fcf3ce44SJohn Forte CFGA_COND_UNUSABLE;
2654fcf3ce44SJohn Forte }
2655fcf3ce44SJohn Forte break;
2656fcf3ce44SJohn Forte default:
2657fcf3ce44SJohn Forte break;
2658fcf3ce44SJohn Forte }
2659fcf3ce44SJohn Forte /* node found in ldata list so just return. */
2660fcf3ce44SJohn Forte lap->ret = FPCFGA_OK;
2661fcf3ce44SJohn Forte S_FREE(port_wwn);
2662fcf3ce44SJohn Forte return (FPCFGA_OK);
2663fcf3ce44SJohn Forte case FPCFGA_APID_NOACCESS:
2664fcf3ce44SJohn Forte switch (ostate) {
2665fcf3ce44SJohn Forte /* node is attached but not in dev list */
2666fcf3ce44SJohn Forte case CFGA_STAT_CONFIGURED:
2667fcf3ce44SJohn Forte case CFGA_STAT_NONE:
2668fcf3ce44SJohn Forte lap->chld_config = CFGA_STAT_CONFIGURED;
2669fcf3ce44SJohn Forte cond = CFGA_COND_FAILING;
2670fcf3ce44SJohn Forte break;
2671fcf3ce44SJohn Forte /*
2672fcf3ce44SJohn Forte * node is offline or down.
2673fcf3ce44SJohn Forte * set cond to unusable.
2674fcf3ce44SJohn Forte */
2675fcf3ce44SJohn Forte case CFGA_STAT_UNCONFIGURED:
2676fcf3ce44SJohn Forte /*
2677fcf3ce44SJohn Forte * For fabric port the fca port is
2678fcf3ce44SJohn Forte * considered as configured since user
2679fcf3ce44SJohn Forte * configured previously for any
2680fcf3ce44SJohn Forte * existing node.
2681fcf3ce44SJohn Forte */
2682fcf3ce44SJohn Forte cond = CFGA_COND_UNUSABLE;
2683fcf3ce44SJohn Forte if ((strcmp(lap->xport_type,
2684fcf3ce44SJohn Forte FP_FC_PUBLIC_PORT_TYPE) == 0) ||
2685fcf3ce44SJohn Forte (strcmp(lap->xport_type,
2686fcf3ce44SJohn Forte FP_FC_FABRIC_PORT_TYPE) == 0)) {
2687fcf3ce44SJohn Forte lap->chld_config =
2688fcf3ce44SJohn Forte CFGA_STAT_CONFIGURED;
2689fcf3ce44SJohn Forte } else {
2690fcf3ce44SJohn Forte lap->ret = FPCFGA_OK;
2691fcf3ce44SJohn Forte S_FREE(port_wwn);
2692fcf3ce44SJohn Forte return (FPCFGA_OK);
2693fcf3ce44SJohn Forte }
2694fcf3ce44SJohn Forte break;
2695fcf3ce44SJohn Forte default:
2696fcf3ce44SJohn Forte /*
2697fcf3ce44SJohn Forte * continue to create ldata_list struct for
2698fcf3ce44SJohn Forte * this node
2699fcf3ce44SJohn Forte */
2700fcf3ce44SJohn Forte break;
2701fcf3ce44SJohn Forte }
2702fcf3ce44SJohn Forte default:
2703fcf3ce44SJohn Forte break;
2704fcf3ce44SJohn Forte }
2705fcf3ce44SJohn Forte }
2706fcf3ce44SJohn Forte
2707fcf3ce44SJohn Forte listp = calloc(1, sizeof (ldata_list_t));
2708fcf3ce44SJohn Forte if (listp == NULL) {
2709fcf3ce44SJohn Forte lap->l_errno = errno;
2710fcf3ce44SJohn Forte S_FREE(port_wwn);
2711fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
2712fcf3ce44SJohn Forte }
2713fcf3ce44SJohn Forte
2714fcf3ce44SJohn Forte clp = &listp->ldata;
2715fcf3ce44SJohn Forte
2716fcf3ce44SJohn Forte /* Create logical and physical ap_id */
2717fcf3ce44SJohn Forte (void) snprintf(clp->ap_log_id, sizeof (clp->ap_log_id),
2718fcf3ce44SJohn Forte "%s%s%s%s%d", lap->xport_logp, DYN_SEP, port_wwn,
2719fcf3ce44SJohn Forte LUN_COMP_SEP, *lun_nump);
2720fcf3ce44SJohn Forte (void) snprintf(clp->ap_phys_id, sizeof (clp->ap_phys_id),
2721fcf3ce44SJohn Forte "%s%s%s%s%d", lap->apidp->xport_phys, DYN_SEP, port_wwn,
2722fcf3ce44SJohn Forte LUN_COMP_SEP, *lun_nump);
2723fcf3ce44SJohn Forte clp->ap_class[0] = '\0'; /* Filled in by libcfgadm */
2724fcf3ce44SJohn Forte clp->ap_r_state = lap->xport_rstate;
2725fcf3ce44SJohn Forte clp->ap_o_state = CFGA_STAT_CONFIGURED;
2726fcf3ce44SJohn Forte clp->ap_cond = cond;
2727fcf3ce44SJohn Forte clp->ap_busy = busy;
2728fcf3ce44SJohn Forte clp->ap_status_time = (time_t)-1;
2729fcf3ce44SJohn Forte clp->ap_info[0] = '\0';
2730fcf3ce44SJohn Forte
2731fcf3ce44SJohn Forte get_hw_info(node, clp);
2732fcf3ce44SJohn Forte
2733fcf3ce44SJohn Forte (void) insert_ldata_to_ldatalist(port_wwn, lun_nump, listp,
2734fcf3ce44SJohn Forte &(lap->listp));
2735fcf3ce44SJohn Forte
2736fcf3ce44SJohn Forte lap->ret = FPCFGA_OK;
2737fcf3ce44SJohn Forte S_FREE(port_wwn);
2738fcf3ce44SJohn Forte return (FPCFGA_OK);
2739fcf3ce44SJohn Forte }
2740fcf3ce44SJohn Forte
2741fcf3ce44SJohn Forte /*
2742fcf3ce44SJohn Forte * Searches the ldata_list to find if the the input port_wwn exist.
2743fcf3ce44SJohn Forte *
2744fcf3ce44SJohn Forte * Input: port_wwn, ldata_list.
2745fcf3ce44SJohn Forte * Return value: FPCFGA_APID_NOACCESS if not found on ldata_list.
2746fcf3ce44SJohn Forte * FPCFGA_ACCESS_OK if found on ldata_list.
2747fcf3ce44SJohn Forte */
2748fcf3ce44SJohn Forte static fpcfga_ret_t
is_dyn_ap_on_ldata_list(const char * port_wwn,const ldata_list_t * listp,ldata_list_t ** matchldpp,int * l_errnop)2749fcf3ce44SJohn Forte is_dyn_ap_on_ldata_list(const char *port_wwn, const ldata_list_t *listp,
2750fcf3ce44SJohn Forte ldata_list_t **matchldpp, int *l_errnop)
2751fcf3ce44SJohn Forte {
2752fcf3ce44SJohn Forte char *dyn = NULL, *dyncomp = NULL;
2753fcf3ce44SJohn Forte int len;
2754fcf3ce44SJohn Forte ldata_list_t *tmplp;
2755fcf3ce44SJohn Forte fpcfga_ret_t ret;
2756fcf3ce44SJohn Forte
2757fcf3ce44SJohn Forte
2758fcf3ce44SJohn Forte ret = FPCFGA_APID_NOACCESS;
2759fcf3ce44SJohn Forte
2760fcf3ce44SJohn Forte tmplp = (ldata_list_t *)listp;
2761fcf3ce44SJohn Forte while (tmplp != NULL) {
2762fcf3ce44SJohn Forte if ((dyn = GET_DYN(tmplp->ldata.ap_phys_id)) != NULL) {
2763fcf3ce44SJohn Forte len = strlen(DYN_TO_DYNCOMP(dyn)) + 1;
2764fcf3ce44SJohn Forte dyncomp = calloc(1, len);
2765fcf3ce44SJohn Forte if (dyncomp == NULL) {
2766fcf3ce44SJohn Forte *l_errnop = errno;
2767fcf3ce44SJohn Forte ret = FPCFGA_LIB_ERR;
2768fcf3ce44SJohn Forte break;
2769fcf3ce44SJohn Forte }
2770fcf3ce44SJohn Forte (void) strcpy(dyncomp, DYN_TO_DYNCOMP(dyn));
2771fcf3ce44SJohn Forte if (!(strncmp(port_wwn, dyncomp, WWN_SIZE*2))) {
2772fcf3ce44SJohn Forte *matchldpp = tmplp;
2773fcf3ce44SJohn Forte S_FREE(dyncomp);
2774fcf3ce44SJohn Forte ret = FPCFGA_ACCESS_OK;
2775fcf3ce44SJohn Forte break;
2776fcf3ce44SJohn Forte }
2777fcf3ce44SJohn Forte S_FREE(dyncomp);
2778fcf3ce44SJohn Forte }
2779fcf3ce44SJohn Forte tmplp = tmplp->next;
2780fcf3ce44SJohn Forte }
2781fcf3ce44SJohn Forte
2782fcf3ce44SJohn Forte return (ret);
2783fcf3ce44SJohn Forte }
2784fcf3ce44SJohn Forte
2785fcf3ce44SJohn Forte /*
2786fcf3ce44SJohn Forte * Searches the ldata_list to find if the the input port_wwn and lun exist.
2787fcf3ce44SJohn Forte *
2788fcf3ce44SJohn Forte * Input: port_wwn, ldata_list.
2789fcf3ce44SJohn Forte * Return value: FPCFGA_APID_NOACCESS if not found on ldata_list.
2790fcf3ce44SJohn Forte * FPCFGA_ACCESS_OK if found on ldata_list.
2791fcf3ce44SJohn Forte */
2792fcf3ce44SJohn Forte static fpcfga_ret_t
is_FCP_dev_ap_on_ldata_list(const char * port_wwn,const int lun_num,ldata_list_t * ldatap,ldata_list_t ** matchldpp)2793fcf3ce44SJohn Forte is_FCP_dev_ap_on_ldata_list(const char *port_wwn, const int lun_num,
2794fcf3ce44SJohn Forte ldata_list_t *ldatap,
2795fcf3ce44SJohn Forte ldata_list_t **matchldpp)
2796fcf3ce44SJohn Forte {
2797fcf3ce44SJohn Forte ldata_list_t *curlp = NULL;
2798fcf3ce44SJohn Forte char *dyn = NULL, *dyncomp = NULL;
2799fcf3ce44SJohn Forte char *lun_dyn = NULL, *lunp = NULL;
2800fcf3ce44SJohn Forte int ldata_lun;
2801fcf3ce44SJohn Forte fpcfga_ret_t ret;
2802fcf3ce44SJohn Forte
2803fcf3ce44SJohn Forte /*
2804fcf3ce44SJohn Forte * if there is no list data just return the FCP dev list.
2805fcf3ce44SJohn Forte * Normally this should not occur since list data should
2806fcf3ce44SJohn Forte * be created through discoveredPort list.
2807fcf3ce44SJohn Forte */
2808fcf3ce44SJohn Forte ret = FPCFGA_APID_NOACCESS;
2809fcf3ce44SJohn Forte if (ldatap == NULL) {
2810fcf3ce44SJohn Forte return (ret);
2811fcf3ce44SJohn Forte }
2812fcf3ce44SJohn Forte
2813fcf3ce44SJohn Forte dyn = GET_DYN(ldatap->ldata.ap_phys_id);
2814fcf3ce44SJohn Forte if (dyn != NULL) dyncomp = DYN_TO_DYNCOMP(dyn);
2815fcf3ce44SJohn Forte if ((dyncomp != NULL) &&
2816fcf3ce44SJohn Forte (strncmp(dyncomp, port_wwn, WWN_SIZE*2) == 0)) {
2817fcf3ce44SJohn Forte lun_dyn = GET_LUN_DYN(dyncomp);
2818fcf3ce44SJohn Forte if (lun_dyn != NULL) {
2819fcf3ce44SJohn Forte lunp = LUN_DYN_TO_LUNCOMP(lun_dyn);
2820fcf3ce44SJohn Forte if ((ldata_lun = atoi(lunp)) == lun_num) {
2821fcf3ce44SJohn Forte *matchldpp = ldatap;
2822fcf3ce44SJohn Forte return (FPCFGA_ACCESS_OK);
2823fcf3ce44SJohn Forte } else if (ldata_lun > lun_num) {
2824fcf3ce44SJohn Forte return (ret);
2825fcf3ce44SJohn Forte }
2826fcf3ce44SJohn Forte /* else continue */
2827fcf3ce44SJohn Forte } else {
2828fcf3ce44SJohn Forte /* we have match without lun comp. */
2829fcf3ce44SJohn Forte *matchldpp = ldatap;
2830fcf3ce44SJohn Forte return (FPCFGA_ACCESS_OK);
2831fcf3ce44SJohn Forte }
2832fcf3ce44SJohn Forte }
2833fcf3ce44SJohn Forte
2834fcf3ce44SJohn Forte curlp = ldatap->next;
2835fcf3ce44SJohn Forte
2836fcf3ce44SJohn Forte dyn = dyncomp = NULL;
2837fcf3ce44SJohn Forte lun_dyn = lunp = NULL;
2838fcf3ce44SJohn Forte while (curlp != NULL) {
2839fcf3ce44SJohn Forte dyn = GET_DYN(curlp->ldata.ap_phys_id);
2840fcf3ce44SJohn Forte if (dyn != NULL) dyncomp = DYN_TO_DYNCOMP(dyn);
2841fcf3ce44SJohn Forte if ((dyncomp != NULL) &&
2842fcf3ce44SJohn Forte (strncmp(dyncomp, port_wwn, WWN_SIZE*2) == 0)) {
2843fcf3ce44SJohn Forte lun_dyn = GET_LUN_DYN(dyncomp);
2844fcf3ce44SJohn Forte if (lun_dyn != NULL) {
2845fcf3ce44SJohn Forte lunp = LUN_DYN_TO_LUNCOMP(lun_dyn);
2846fcf3ce44SJohn Forte if ((ldata_lun = atoi(lunp)) == lun_num) {
2847fcf3ce44SJohn Forte *matchldpp = curlp;
2848fcf3ce44SJohn Forte return (FPCFGA_ACCESS_OK);
2849fcf3ce44SJohn Forte } else if (ldata_lun > lun_num) {
2850fcf3ce44SJohn Forte return (ret);
2851fcf3ce44SJohn Forte }
2852fcf3ce44SJohn Forte /* else continue */
2853fcf3ce44SJohn Forte } else {
2854fcf3ce44SJohn Forte /* we have match without lun comp. */
2855fcf3ce44SJohn Forte *matchldpp = curlp;
2856fcf3ce44SJohn Forte return (FPCFGA_ACCESS_OK);
2857fcf3ce44SJohn Forte }
2858fcf3ce44SJohn Forte }
2859fcf3ce44SJohn Forte dyn = dyncomp = NULL;
2860fcf3ce44SJohn Forte lun_dyn = lunp = NULL;
2861fcf3ce44SJohn Forte curlp = curlp->next;
2862fcf3ce44SJohn Forte }
2863fcf3ce44SJohn Forte
2864fcf3ce44SJohn Forte return (ret);
2865fcf3ce44SJohn Forte
2866fcf3ce44SJohn Forte }
2867fcf3ce44SJohn Forte
2868fcf3ce44SJohn Forte /*
2869fcf3ce44SJohn Forte * This routine is called when a pathinfo without matching pwwn in dev_list
2870fcf3ce44SJohn Forte * is found.
2871fcf3ce44SJohn Forte */
2872fcf3ce44SJohn Forte static fpcfga_ret_t
init_ldata_for_mpath_dev(di_path_t path,char * pwwn,int * l_errnop,fpcfga_list_t * lap)2873fcf3ce44SJohn Forte init_ldata_for_mpath_dev(di_path_t path, char *pwwn, int *l_errnop,
2874fcf3ce44SJohn Forte fpcfga_list_t *lap)
2875fcf3ce44SJohn Forte {
2876fcf3ce44SJohn Forte ldata_list_t *listp = NULL;
2877fcf3ce44SJohn Forte cfga_list_data_t *clp = NULL;
2878fcf3ce44SJohn Forte size_t devlen;
2879fcf3ce44SJohn Forte char *devpath;
2880fcf3ce44SJohn Forte di_node_t client_node = DI_NODE_NIL;
2881fcf3ce44SJohn Forte uint_t dctl_state = 0;
2882fcf3ce44SJohn Forte cfga_busy_t busy;
2883fcf3ce44SJohn Forte char *client_path;
2884fcf3ce44SJohn Forte di_path_state_t pstate;
2885fcf3ce44SJohn Forte
2886fcf3ce44SJohn Forte /* get the client node path */
2887fcf3ce44SJohn Forte if (path == DI_PATH_NIL) {
2888fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
2889fcf3ce44SJohn Forte }
2890fcf3ce44SJohn Forte client_node = di_path_client_node(path);
2891fcf3ce44SJohn Forte if (client_node == DI_NODE_NIL) {
2892fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
2893fcf3ce44SJohn Forte }
2894fcf3ce44SJohn Forte if ((client_path = di_devfs_path(client_node)) == NULL) {
2895fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
2896fcf3ce44SJohn Forte }
2897fcf3ce44SJohn Forte devlen = strlen(DEVICES_DIR) + strlen(client_path) + 1;
2898fcf3ce44SJohn Forte devpath = calloc(1, devlen);
2899fcf3ce44SJohn Forte if (devpath == NULL) {
2900fcf3ce44SJohn Forte di_devfs_path_free(client_path);
2901fcf3ce44SJohn Forte *l_errnop = errno;
2902fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
2903fcf3ce44SJohn Forte }
2904fcf3ce44SJohn Forte (void) snprintf(devpath, devlen, "%s%s", DEVICES_DIR, client_path);
2905fcf3ce44SJohn Forte
2906fcf3ce44SJohn Forte /* now need to create ldata for this dev */
2907fcf3ce44SJohn Forte listp = calloc(1, sizeof (ldata_list_t));
2908fcf3ce44SJohn Forte if (listp == NULL) {
2909fcf3ce44SJohn Forte di_devfs_path_free(client_path);
2910fcf3ce44SJohn Forte S_FREE(devpath);
2911fcf3ce44SJohn Forte *l_errnop = errno;
2912fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
2913fcf3ce44SJohn Forte }
2914fcf3ce44SJohn Forte
2915fcf3ce44SJohn Forte clp = &listp->ldata;
2916fcf3ce44SJohn Forte
2917fcf3ce44SJohn Forte /* Create logical and physical ap_id */
2918fcf3ce44SJohn Forte (void) snprintf(clp->ap_log_id, sizeof (clp->ap_log_id), "%s%s%s",
2919fcf3ce44SJohn Forte lap->xport_logp, DYN_SEP, pwwn);
2920fcf3ce44SJohn Forte (void) snprintf(clp->ap_phys_id, sizeof (clp->ap_phys_id), "%s%s%s",
2921fcf3ce44SJohn Forte lap->apidp->xport_phys, DYN_SEP, pwwn);
2922fcf3ce44SJohn Forte
2923fcf3ce44SJohn Forte /* Filled in by libcfgadm */
2924fcf3ce44SJohn Forte clp->ap_class[0] = '\0'; /* Filled by libcfgadm */
2925fcf3ce44SJohn Forte clp->ap_r_state = lap->xport_rstate;
2926fcf3ce44SJohn Forte /* set to ostate to configured. */
2927fcf3ce44SJohn Forte clp->ap_o_state = CFGA_STAT_CONFIGURED;
2928fcf3ce44SJohn Forte /*
2929fcf3ce44SJohn Forte * This routine is called when a port WWN is not found in dev list
2930fcf3ce44SJohn Forte * but path info node exists.
2931fcf3ce44SJohn Forte *
2932fcf3ce44SJohn Forte * Update the condition as failing if the pathinfo state was normal.
2933fcf3ce44SJohn Forte * Update the condition as unusable if the pathinfo state is failed
2934fcf3ce44SJohn Forte * or offline.
2935fcf3ce44SJohn Forte */
2936fcf3ce44SJohn Forte if (((pstate = di_path_state(path)) == DI_PATH_STATE_OFFLINE) ||
2937fcf3ce44SJohn Forte (pstate == DI_PATH_STATE_FAULT)) {
2938fcf3ce44SJohn Forte clp->ap_cond = CFGA_COND_UNUSABLE;
2939fcf3ce44SJohn Forte } else {
2940fcf3ce44SJohn Forte clp->ap_cond = CFGA_COND_FAILING;
2941fcf3ce44SJohn Forte }
2942fcf3ce44SJohn Forte clp->ap_status_time = (time_t)-1;
2943fcf3ce44SJohn Forte /* update ap_type and ap_info */
2944fcf3ce44SJohn Forte get_hw_info(client_node, clp);
2945fcf3ce44SJohn Forte
2946fcf3ce44SJohn Forte if (devctl_cmd(devpath, FPCFGA_DEV_GETSTATE,
2947fcf3ce44SJohn Forte &dctl_state, l_errnop) == FPCFGA_OK) {
2948fcf3ce44SJohn Forte busy = ((dctl_state & DEVICE_BUSY) == DEVICE_BUSY) ? 1 : 0;
2949fcf3ce44SJohn Forte } else {
2950fcf3ce44SJohn Forte busy = 0;
2951fcf3ce44SJohn Forte }
2952fcf3ce44SJohn Forte clp->ap_busy = busy;
2953fcf3ce44SJohn Forte /* Link it in */
2954fcf3ce44SJohn Forte listp->next = lap->listp;
2955fcf3ce44SJohn Forte lap->listp = listp;
2956fcf3ce44SJohn Forte
2957fcf3ce44SJohn Forte di_devfs_path_free(client_path);
2958fcf3ce44SJohn Forte S_FREE(devpath);
2959fcf3ce44SJohn Forte
2960fcf3ce44SJohn Forte /* now return with ok status with ldata. */
2961fcf3ce44SJohn Forte lap->ret = FPCFGA_OK;
2962fcf3ce44SJohn Forte return (FPCFGA_OK);
2963fcf3ce44SJohn Forte }
2964fcf3ce44SJohn Forte
2965fcf3ce44SJohn Forte /*
2966fcf3ce44SJohn Forte * Initialize the cfga_list_data struct for an accessible device
2967fcf3ce44SJohn Forte * from g_get_dev_list().
2968fcf3ce44SJohn Forte *
2969fcf3ce44SJohn Forte * Input: fca port ldata.
2970fcf3ce44SJohn Forte * Output: device cfga_list_data.
2971fcf3ce44SJohn Forte *
2972fcf3ce44SJohn Forte */
2973fcf3ce44SJohn Forte static fpcfga_ret_t
init_ldata_for_accessible_dev(const char * dyncomp,uchar_t inq_type,fpcfga_list_t * lap)2974fcf3ce44SJohn Forte init_ldata_for_accessible_dev(const char *dyncomp, uchar_t inq_type,
2975fcf3ce44SJohn Forte fpcfga_list_t *lap)
2976fcf3ce44SJohn Forte {
2977fcf3ce44SJohn Forte ldata_list_t *listp = NULL;
2978fcf3ce44SJohn Forte cfga_list_data_t *clp = NULL;
2979fcf3ce44SJohn Forte int i;
2980fcf3ce44SJohn Forte
2981fcf3ce44SJohn Forte listp = calloc(1, sizeof (ldata_list_t));
2982fcf3ce44SJohn Forte if (listp == NULL) {
2983fcf3ce44SJohn Forte lap->l_errno = errno;
2984fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
2985fcf3ce44SJohn Forte }
2986fcf3ce44SJohn Forte
2987fcf3ce44SJohn Forte clp = &listp->ldata;
2988fcf3ce44SJohn Forte
2989fcf3ce44SJohn Forte assert(dyncomp != NULL);
2990fcf3ce44SJohn Forte
2991fcf3ce44SJohn Forte /* Create logical and physical ap_id */
2992fcf3ce44SJohn Forte (void) snprintf(clp->ap_log_id, sizeof (clp->ap_log_id), "%s%s%s",
2993fcf3ce44SJohn Forte lap->xport_logp, DYN_SEP, dyncomp);
2994fcf3ce44SJohn Forte
2995fcf3ce44SJohn Forte (void) snprintf(clp->ap_phys_id, sizeof (clp->ap_phys_id), "%s%s%s",
2996fcf3ce44SJohn Forte lap->apidp->xport_phys, DYN_SEP, dyncomp);
2997fcf3ce44SJohn Forte
2998fcf3ce44SJohn Forte clp->ap_class[0] = '\0'; /* Filled in by libcfgadm */
2999fcf3ce44SJohn Forte clp->ap_r_state = lap->xport_rstate;
3000fcf3ce44SJohn Forte clp->ap_o_state = CFGA_STAT_UNCONFIGURED;
3001fcf3ce44SJohn Forte clp->ap_cond = CFGA_COND_UNKNOWN;
3002fcf3ce44SJohn Forte clp->ap_busy = 0;
3003fcf3ce44SJohn Forte clp->ap_status_time = (time_t)-1;
3004fcf3ce44SJohn Forte clp->ap_info[0] = '\0';
3005fcf3ce44SJohn Forte for (i = 0; i < N_DEVICE_TYPES; i++) {
3006fcf3ce44SJohn Forte if (inq_type == device_list[i].itype) {
3007fcf3ce44SJohn Forte (void) snprintf(clp->ap_type, sizeof (clp->ap_type),
3008fcf3ce44SJohn Forte "%s", (char *)device_list[i].name);
3009fcf3ce44SJohn Forte break;
3010fcf3ce44SJohn Forte }
3011fcf3ce44SJohn Forte }
3012fcf3ce44SJohn Forte if (i == N_DEVICE_TYPES) {
3013fcf3ce44SJohn Forte if (inq_type == ERR_INQ_DTYPE) {
3014fcf3ce44SJohn Forte clp->ap_cond = CFGA_COND_FAILED;
3015fcf3ce44SJohn Forte snprintf(clp->ap_type, sizeof (clp->ap_type), "%s",
3016fcf3ce44SJohn Forte (char *)GET_MSG_STR(ERR_UNAVAILABLE));
3017fcf3ce44SJohn Forte } else {
3018fcf3ce44SJohn Forte (void) snprintf(clp->ap_type, sizeof (clp->ap_type),
3019fcf3ce44SJohn Forte "%s", "unknown");
3020fcf3ce44SJohn Forte }
3021fcf3ce44SJohn Forte }
3022fcf3ce44SJohn Forte
3023fcf3ce44SJohn Forte /* Link it in */
3024fcf3ce44SJohn Forte (void) insert_ldata_to_ldatalist(dyncomp, NULL, listp, &(lap->listp));
3025fcf3ce44SJohn Forte
3026fcf3ce44SJohn Forte return (FPCFGA_OK);
3027fcf3ce44SJohn Forte }
3028fcf3ce44SJohn Forte
3029fcf3ce44SJohn Forte /*
3030fcf3ce44SJohn Forte * Initialize the cfga_list_data struct for an accessible FCP SCSI LUN device
3031fcf3ce44SJohn Forte * from the report lun data.
3032fcf3ce44SJohn Forte *
3033fcf3ce44SJohn Forte * Input: fca port ldata. report lun info
3034fcf3ce44SJohn Forte * Output: device cfga_list_data.
3035fcf3ce44SJohn Forte *
3036fcf3ce44SJohn Forte */
3037fcf3ce44SJohn Forte static fpcfga_ret_t
init_ldata_for_accessible_FCP_dev(const char * port_wwn,int num_luns,struct report_lun_resp * resp_buf,fpcfga_list_t * lap,int * l_errnop)3038fcf3ce44SJohn Forte init_ldata_for_accessible_FCP_dev(
3039fcf3ce44SJohn Forte const char *port_wwn,
3040fcf3ce44SJohn Forte int num_luns,
3041fcf3ce44SJohn Forte struct report_lun_resp *resp_buf,
3042fcf3ce44SJohn Forte fpcfga_list_t *lap,
3043fcf3ce44SJohn Forte int *l_errnop)
3044fcf3ce44SJohn Forte {
3045fcf3ce44SJohn Forte ldata_list_t *listp = NULL, *listp_start = NULL, *listp_end = NULL,
3046fcf3ce44SJohn Forte *prevlp = NULL, *curlp = NULL, *matchp_start = NULL,
3047fcf3ce44SJohn Forte *matchp_end = NULL;
3048fcf3ce44SJohn Forte cfga_list_data_t *clp = NULL;
3049fcf3ce44SJohn Forte char *dyn = NULL, *dyncomp = NULL;
3050fcf3ce44SJohn Forte uchar_t *lun_string;
3051fcf3ce44SJohn Forte uint16_t lun_num;
3052fcf3ce44SJohn Forte int i, j, str_ret;
3053fcf3ce44SJohn Forte fpcfga_ret_t ret;
3054fcf3ce44SJohn Forte char dtype[CFGA_TYPE_LEN];
3055fcf3ce44SJohn Forte struct scsi_inquiry *inq_buf;
3056fcf3ce44SJohn Forte uchar_t peri_qual;
3057fcf3ce44SJohn Forte cfga_cond_t cond = CFGA_COND_UNKNOWN;
3058fcf3ce44SJohn Forte uchar_t lun_num_raw[SAM_LUN_SIZE];
3059fcf3ce44SJohn Forte
3060fcf3ce44SJohn Forte /* when number of lun is 0 it is not an error. so just return ok. */
3061fcf3ce44SJohn Forte if (num_luns == 0) {
3062fcf3ce44SJohn Forte return (FPCFGA_OK);
3063fcf3ce44SJohn Forte }
3064fcf3ce44SJohn Forte
3065fcf3ce44SJohn Forte for (i = 0; i < num_luns; i++) {
3066fcf3ce44SJohn Forte lun_string = (uchar_t *)&(resp_buf->lun_string[i]);
3067fcf3ce44SJohn Forte memcpy(lun_num_raw, lun_string, sizeof (lun_num_raw));
3068fcf3ce44SJohn Forte if ((ret = get_standard_inq_data(lap->apidp->xport_phys, port_wwn,
3069fcf3ce44SJohn Forte lun_num_raw, &inq_buf, l_errnop))
3070fcf3ce44SJohn Forte != FPCFGA_OK) {
3071fcf3ce44SJohn Forte if (ret == FPCFGA_FCP_TGT_SEND_SCSI_FAILED) {
3072fcf3ce44SJohn Forte (void) strlcpy(dtype,
3073fcf3ce44SJohn Forte (char *)GET_MSG_STR(ERR_UNAVAILABLE), CFGA_TYPE_LEN);
3074fcf3ce44SJohn Forte cond = CFGA_COND_FAILED;
3075fcf3ce44SJohn Forte } else {
3076fcf3ce44SJohn Forte S_FREE(inq_buf);
3077fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
3078fcf3ce44SJohn Forte }
3079fcf3ce44SJohn Forte } else {
3080fcf3ce44SJohn Forte peri_qual = inq_buf->inq_dtype & FP_PERI_QUAL_MASK;
3081fcf3ce44SJohn Forte /*
3082fcf3ce44SJohn Forte * peripheral qualifier is not 0 so the device node should not
3083fcf3ce44SJohn Forte * included in the ldata list. There should not be a device
3084fcf3ce44SJohn Forte * node for the lun either.
3085fcf3ce44SJohn Forte */
3086fcf3ce44SJohn Forte if (peri_qual != DPQ_POSSIBLE) {
3087fcf3ce44SJohn Forte S_FREE(inq_buf);
3088fcf3ce44SJohn Forte continue;
3089fcf3ce44SJohn Forte }
3090*21f023dfSToomas Soome *dtype = '\0';
3091fcf3ce44SJohn Forte for (j = 0; j < N_DEVICE_TYPES; j++) {
3092fcf3ce44SJohn Forte if ((inq_buf->inq_dtype & DTYPE_MASK)
3093fcf3ce44SJohn Forte == device_list[j].itype) {
3094fcf3ce44SJohn Forte (void) strlcpy(dtype, (char *)device_list[j].name,
3095fcf3ce44SJohn Forte CFGA_TYPE_LEN);
3096fcf3ce44SJohn Forte break;
3097fcf3ce44SJohn Forte }
3098fcf3ce44SJohn Forte }
3099*21f023dfSToomas Soome if (*dtype == '\0') {
3100fcf3ce44SJohn Forte (void) strlcpy(dtype,
3101fcf3ce44SJohn Forte (char *)device_list[DTYPE_UNKNOWN_INDEX].name,
3102fcf3ce44SJohn Forte CFGA_TYPE_LEN);
3103fcf3ce44SJohn Forte }
3104fcf3ce44SJohn Forte }
3105fcf3ce44SJohn Forte /*
3106fcf3ce44SJohn Forte * Followed FCP driver for getting lun number from report
3107fcf3ce44SJohn Forte * lun data.
3108fcf3ce44SJohn Forte * According to SAM-2 there are multiple address method for
3109fcf3ce44SJohn Forte * FCP SCIS LUN. Logincal unit addressing, peripheral device
3110fcf3ce44SJohn Forte * addressing, flat space addressing, and extended logical
3111fcf3ce44SJohn Forte * unit addressing.
3112fcf3ce44SJohn Forte *
3113fcf3ce44SJohn Forte * as of 11/2001 FCP supports logical unit addressing and
3114fcf3ce44SJohn Forte * peripheral device addressing even thoough 3 defined.
3115fcf3ce44SJohn Forte * SSFCP_LUN_ADDRESSING 0x80
3116fcf3ce44SJohn Forte * SSFCP_PD_ADDRESSING 0x00
3117fcf3ce44SJohn Forte * SSFCP_VOLUME_ADDRESSING 0x40
3118fcf3ce44SJohn Forte *
3119fcf3ce44SJohn Forte * the menthod below is used by FCP when (lun_string[0] & 0xC0)
3120fcf3ce44SJohn Forte * is either SSFCP_LUN_ADDRESSING or SSFCP_PD_ADDRESSING mode.
3121fcf3ce44SJohn Forte */
3122fcf3ce44SJohn Forte lun_num = ((lun_string[0] & 0x3F) << 8) | lun_string[1];
3123fcf3ce44SJohn Forte listp = calloc(1, sizeof (ldata_list_t));
3124fcf3ce44SJohn Forte if (listp == NULL) {
3125fcf3ce44SJohn Forte *l_errnop = errno;
3126fcf3ce44SJohn Forte list_free(&listp_start);
3127fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
3128fcf3ce44SJohn Forte }
3129fcf3ce44SJohn Forte
3130fcf3ce44SJohn Forte clp = &listp->ldata;
3131fcf3ce44SJohn Forte /* Create logical and physical ap_id */
3132fcf3ce44SJohn Forte (void) snprintf(clp->ap_log_id, sizeof (clp->ap_log_id),
3133fcf3ce44SJohn Forte "%s%s%s%s%d", lap->xport_logp, DYN_SEP, port_wwn,
3134fcf3ce44SJohn Forte LUN_COMP_SEP, lun_num);
3135fcf3ce44SJohn Forte (void) snprintf(clp->ap_phys_id, sizeof (clp->ap_phys_id),
3136fcf3ce44SJohn Forte "%s%s%s%s%d", lap->apidp->xport_phys, DYN_SEP, port_wwn,
3137fcf3ce44SJohn Forte LUN_COMP_SEP, lun_num);
3138fcf3ce44SJohn Forte (void) strncpy(clp->ap_type, dtype, strlen(dtype));
3139fcf3ce44SJohn Forte clp->ap_class[0] = '\0'; /* Filled in by libcfgadm */
3140fcf3ce44SJohn Forte clp->ap_r_state = lap->xport_rstate;
3141fcf3ce44SJohn Forte clp->ap_o_state = CFGA_STAT_UNCONFIGURED;
3142fcf3ce44SJohn Forte clp->ap_cond = cond;
3143fcf3ce44SJohn Forte clp->ap_busy = 0;
3144fcf3ce44SJohn Forte clp->ap_status_time = (time_t)-1;
3145fcf3ce44SJohn Forte clp->ap_info[0] = '\0';
3146fcf3ce44SJohn Forte if (listp_start == NULL) {
3147fcf3ce44SJohn Forte listp_start = listp;
3148fcf3ce44SJohn Forte } else {
3149fcf3ce44SJohn Forte if ((ret = insert_FCP_dev_ldata(
3150fcf3ce44SJohn Forte port_wwn, lun_num, listp,
3151fcf3ce44SJohn Forte &listp_start)) != FPCFGA_OK) {
3152fcf3ce44SJohn Forte list_free(&listp_start);
3153fcf3ce44SJohn Forte return (ret);
3154fcf3ce44SJohn Forte }
3155fcf3ce44SJohn Forte }
3156fcf3ce44SJohn Forte listp = NULL;
3157fcf3ce44SJohn Forte S_FREE(inq_buf);
3158fcf3ce44SJohn Forte }
3159fcf3ce44SJohn Forte
3160fcf3ce44SJohn Forte /*
3161fcf3ce44SJohn Forte * list data can be null when device peripheral qualifier is not 0
3162fcf3ce44SJohn Forte * for any luns. Return ok to continue.
3163fcf3ce44SJohn Forte */
3164fcf3ce44SJohn Forte if (listp_start == NULL) {
3165fcf3ce44SJohn Forte return (FPCFGA_OK);
3166fcf3ce44SJohn Forte }
3167fcf3ce44SJohn Forte /*
3168fcf3ce44SJohn Forte * get the end of list for later uses.
3169fcf3ce44SJohn Forte */
3170fcf3ce44SJohn Forte curlp = listp_start->next;
3171fcf3ce44SJohn Forte prevlp = listp_start;
3172fcf3ce44SJohn Forte while (curlp) {
3173fcf3ce44SJohn Forte prevlp = curlp;
3174fcf3ce44SJohn Forte curlp = curlp->next;
3175fcf3ce44SJohn Forte }
3176fcf3ce44SJohn Forte listp_end = prevlp;
3177fcf3ce44SJohn Forte
3178fcf3ce44SJohn Forte /*
3179fcf3ce44SJohn Forte * if there is no list data just return the FCP dev list.
3180fcf3ce44SJohn Forte * Normally this should not occur since list data should
3181fcf3ce44SJohn Forte * be created through g_get_dev_list().
3182fcf3ce44SJohn Forte */
3183fcf3ce44SJohn Forte if (lap->listp == NULL) {
3184fcf3ce44SJohn Forte lap->listp = listp_start;
3185fcf3ce44SJohn Forte for (listp = listp_start; listp != NULL; listp = listp->next) {
3186fcf3ce44SJohn Forte listp->ldata.ap_cond = CFGA_COND_FAILING;
3187fcf3ce44SJohn Forte }
3188fcf3ce44SJohn Forte return (FPCFGA_OK);
3189fcf3ce44SJohn Forte }
3190fcf3ce44SJohn Forte
3191fcf3ce44SJohn Forte dyn = GET_DYN(lap->listp->ldata.ap_phys_id);
3192fcf3ce44SJohn Forte if ((dyn != NULL) && ((dyncomp = DYN_TO_DYNCOMP(dyn)) != NULL)) {
3193fcf3ce44SJohn Forte if ((str_ret = strncmp(dyncomp, port_wwn, WWN_SIZE*2)) == 0) {
3194fcf3ce44SJohn Forte matchp_start = matchp_end = lap->listp;
3195fcf3ce44SJohn Forte while (matchp_end->next != NULL) {
3196fcf3ce44SJohn Forte dyn = GET_DYN(
3197fcf3ce44SJohn Forte matchp_end->next->ldata.ap_phys_id);
3198fcf3ce44SJohn Forte if ((dyn != NULL) &&
3199fcf3ce44SJohn Forte ((dyncomp = DYN_TO_DYNCOMP(dyn)) != NULL)) {
3200fcf3ce44SJohn Forte if ((str_ret = strncmp(dyncomp,
3201fcf3ce44SJohn Forte port_wwn, WWN_SIZE*2)) == 0) {
3202fcf3ce44SJohn Forte matchp_end = matchp_end->next;
3203fcf3ce44SJohn Forte } else {
3204fcf3ce44SJohn Forte break;
3205fcf3ce44SJohn Forte }
3206fcf3ce44SJohn Forte } else {
3207fcf3ce44SJohn Forte break;
3208fcf3ce44SJohn Forte }
3209fcf3ce44SJohn Forte }
3210fcf3ce44SJohn Forte /* fillup inqdtype */
3211fcf3ce44SJohn Forte for (listp = listp_start; listp != NULL;
3212fcf3ce44SJohn Forte listp = listp->next) {
3213fcf3ce44SJohn Forte listp->ldata.ap_cond =
3214fcf3ce44SJohn Forte lap->listp->ldata.ap_cond;
3215fcf3ce44SJohn Forte }
3216fcf3ce44SJohn Forte /* link the new elem of lap->listp. */
3217fcf3ce44SJohn Forte listp_end->next = matchp_end->next;
3218fcf3ce44SJohn Forte /* free the one matching wwn. */
3219fcf3ce44SJohn Forte matchp_end->next = NULL;
3220fcf3ce44SJohn Forte list_free(&matchp_start);
3221fcf3ce44SJohn Forte /* link lap->listp to listp_start. */
3222fcf3ce44SJohn Forte lap->listp = listp_start;
3223fcf3ce44SJohn Forte return (FPCFGA_OK);
3224fcf3ce44SJohn Forte } else if (str_ret > 0) {
3225fcf3ce44SJohn Forte for (listp = listp_start; listp != NULL;
3226fcf3ce44SJohn Forte listp = listp->next) {
3227fcf3ce44SJohn Forte listp->ldata.ap_cond = CFGA_COND_FAILING;
3228fcf3ce44SJohn Forte }
3229fcf3ce44SJohn Forte listp_end->next = lap->listp->next;
3230fcf3ce44SJohn Forte lap->listp = listp_start;
3231fcf3ce44SJohn Forte return (FPCFGA_OK);
3232fcf3ce44SJohn Forte }
3233fcf3ce44SJohn Forte }
3234fcf3ce44SJohn Forte
3235fcf3ce44SJohn Forte prevlp = lap->listp;
3236fcf3ce44SJohn Forte curlp = lap->listp->next;
3237fcf3ce44SJohn Forte
3238fcf3ce44SJohn Forte dyn = dyncomp = NULL;
3239fcf3ce44SJohn Forte while (curlp != NULL) {
3240fcf3ce44SJohn Forte dyn = GET_DYN(curlp->ldata.ap_phys_id);
3241fcf3ce44SJohn Forte if ((dyn != NULL) &&
3242fcf3ce44SJohn Forte ((dyncomp = DYN_TO_DYNCOMP(dyn)) != NULL)) {
3243fcf3ce44SJohn Forte if ((str_ret = strncmp(dyncomp, port_wwn,
3244fcf3ce44SJohn Forte WWN_SIZE*2)) == 0) {
3245fcf3ce44SJohn Forte matchp_start = matchp_end = curlp;
3246fcf3ce44SJohn Forte while (matchp_end->next != NULL) {
3247fcf3ce44SJohn Forte dyn = GET_DYN(
3248fcf3ce44SJohn Forte matchp_end->next->ldata.ap_phys_id);
3249fcf3ce44SJohn Forte if ((dyn != NULL) &&
3250fcf3ce44SJohn Forte ((dyncomp = DYN_TO_DYNCOMP(dyn))
3251fcf3ce44SJohn Forte != NULL)) {
3252fcf3ce44SJohn Forte if ((str_ret = strncmp(dyncomp,
3253fcf3ce44SJohn Forte port_wwn, WWN_SIZE*2))
3254fcf3ce44SJohn Forte == 0) {
3255fcf3ce44SJohn Forte matchp_end =
3256fcf3ce44SJohn Forte matchp_end->next;
3257fcf3ce44SJohn Forte } else {
3258fcf3ce44SJohn Forte break;
3259fcf3ce44SJohn Forte }
3260fcf3ce44SJohn Forte } else {
3261fcf3ce44SJohn Forte break;
3262fcf3ce44SJohn Forte }
3263fcf3ce44SJohn Forte }
3264fcf3ce44SJohn Forte for (listp = listp_start; listp != NULL;
3265fcf3ce44SJohn Forte listp = listp->next) {
3266fcf3ce44SJohn Forte listp->ldata.ap_cond = curlp->ldata.ap_cond;
3267fcf3ce44SJohn Forte }
3268fcf3ce44SJohn Forte /* link the next elem to listp_end. */
3269fcf3ce44SJohn Forte listp_end->next = matchp_end->next;
3270fcf3ce44SJohn Forte /* link prevlp to listp_start to drop curlp. */
3271fcf3ce44SJohn Forte prevlp->next = listp_start;
3272fcf3ce44SJohn Forte /* free matching pwwn elem. */
3273fcf3ce44SJohn Forte matchp_end->next = NULL;
3274fcf3ce44SJohn Forte list_free(&matchp_start);
3275fcf3ce44SJohn Forte return (FPCFGA_OK);
3276fcf3ce44SJohn Forte } else if (str_ret > 0) {
3277fcf3ce44SJohn Forte for (listp = listp_start; listp != NULL;
3278fcf3ce44SJohn Forte listp = listp->next) {
3279fcf3ce44SJohn Forte /*
3280fcf3ce44SJohn Forte * Dev not found from accessible
3281fcf3ce44SJohn Forte * fc dev list but the node should
3282fcf3ce44SJohn Forte * exist. Set to failing cond now
3283fcf3ce44SJohn Forte * and check the node state later.
3284fcf3ce44SJohn Forte */
3285fcf3ce44SJohn Forte listp->ldata.ap_cond = CFGA_COND_FAILING;
3286fcf3ce44SJohn Forte }
3287fcf3ce44SJohn Forte /* keep the cur elem by linking to list_end. */
3288fcf3ce44SJohn Forte listp_end->next = curlp;
3289fcf3ce44SJohn Forte prevlp->next = listp_start;
3290fcf3ce44SJohn Forte return (FPCFGA_OK);
3291fcf3ce44SJohn Forte }
3292fcf3ce44SJohn Forte }
3293fcf3ce44SJohn Forte dyn = dyncomp = NULL;
3294fcf3ce44SJohn Forte prevlp = curlp;
3295fcf3ce44SJohn Forte curlp = curlp->next;
3296fcf3ce44SJohn Forte }
3297fcf3ce44SJohn Forte
3298fcf3ce44SJohn Forte prevlp->next = listp_start;
3299fcf3ce44SJohn Forte for (listp = listp_start; listp != NULL; listp = listp->next) {
3300fcf3ce44SJohn Forte listp->ldata.ap_cond = CFGA_COND_FAILING;
3301fcf3ce44SJohn Forte }
3302fcf3ce44SJohn Forte
3303fcf3ce44SJohn Forte return (FPCFGA_OK);
3304fcf3ce44SJohn Forte
3305fcf3ce44SJohn Forte }
3306fcf3ce44SJohn Forte
3307fcf3ce44SJohn Forte /* fill in device type, vid, pid from properties */
3308fcf3ce44SJohn Forte static void
get_hw_info(di_node_t node,cfga_list_data_t * clp)3309fcf3ce44SJohn Forte get_hw_info(di_node_t node, cfga_list_data_t *clp)
3310fcf3ce44SJohn Forte {
3311fcf3ce44SJohn Forte char *cp = NULL;
3312fcf3ce44SJohn Forte char *inq_vid, *inq_pid;
3313fcf3ce44SJohn Forte int i;
3314fcf3ce44SJohn Forte
3315fcf3ce44SJohn Forte /*
3316fcf3ce44SJohn Forte * if the type is not previously assigned with valid SCSI device type
3317fcf3ce44SJohn Forte * check devinfo to find the type.
3318fcf3ce44SJohn Forte * once device is configured it should have a valid device type.
3319fcf3ce44SJohn Forte * device node is configured but no valid device type is found
3320fcf3ce44SJohn Forte * the type will be set to unavailable.
3321fcf3ce44SJohn Forte */
3322fcf3ce44SJohn Forte if (clp->ap_type != NULL) {
3323fcf3ce44SJohn Forte /*
3324fcf3ce44SJohn Forte * if the type is not one of defined SCSI device type
3325fcf3ce44SJohn Forte * check devinfo to find the type.
3326fcf3ce44SJohn Forte *
3327fcf3ce44SJohn Forte * Note: unknown type is not a valid device type.
3328fcf3ce44SJohn Forte * It is added in to the device list table to provide
3329fcf3ce44SJohn Forte * constant string of "unknown".
3330fcf3ce44SJohn Forte */
3331fcf3ce44SJohn Forte for (i = 0; i < (N_DEVICE_TYPES -1); i++) {
3332fcf3ce44SJohn Forte if (strncmp((char *)clp->ap_type, (char *)device_list[i].name,
3333fcf3ce44SJohn Forte sizeof (clp->ap_type)) == 0) {
3334fcf3ce44SJohn Forte break;
3335fcf3ce44SJohn Forte }
3336fcf3ce44SJohn Forte }
3337fcf3ce44SJohn Forte if (i == (N_DEVICE_TYPES - 1)) {
3338fcf3ce44SJohn Forte cp = (char *)get_device_type(node);
3339fcf3ce44SJohn Forte if (cp == NULL) {
3340fcf3ce44SJohn Forte cp = (char *)GET_MSG_STR(ERR_UNAVAILABLE);
3341fcf3ce44SJohn Forte }
3342fcf3ce44SJohn Forte (void) snprintf(clp->ap_type, sizeof (clp->ap_type), "%s",
3343fcf3ce44SJohn Forte S_STR(cp));
3344fcf3ce44SJohn Forte }
3345fcf3ce44SJohn Forte } else {
3346fcf3ce44SJohn Forte cp = (char *)get_device_type(node);
3347fcf3ce44SJohn Forte if (cp == NULL) {
3348fcf3ce44SJohn Forte cp = (char *)GET_MSG_STR(ERR_UNAVAILABLE);
3349fcf3ce44SJohn Forte }
3350fcf3ce44SJohn Forte (void) snprintf(clp->ap_type, sizeof (clp->ap_type), "%s",
3351fcf3ce44SJohn Forte S_STR(cp));
3352fcf3ce44SJohn Forte }
3353fcf3ce44SJohn Forte
3354fcf3ce44SJohn Forte /*
3355fcf3ce44SJohn Forte * Fill in vendor and product ID.
3356fcf3ce44SJohn Forte */
3357fcf3ce44SJohn Forte if ((di_prop_lookup_strings(DDI_DEV_T_ANY, node,
3358fcf3ce44SJohn Forte "inquiry-product-id", &inq_pid) == 1) &&
3359fcf3ce44SJohn Forte (di_prop_lookup_strings(DDI_DEV_T_ANY, node,
3360fcf3ce44SJohn Forte "inquiry-vendor-id", &inq_vid) == 1)) {
3361fcf3ce44SJohn Forte (void) snprintf(clp->ap_info, sizeof (clp->ap_info),
3362fcf3ce44SJohn Forte "%s %s", inq_vid, inq_pid);
3363fcf3ce44SJohn Forte }
3364fcf3ce44SJohn Forte }
3365fcf3ce44SJohn Forte
3366fcf3ce44SJohn Forte /*
3367fcf3ce44SJohn Forte * Get dtype from "inquiry-device-type" property. If not present,
3368fcf3ce44SJohn Forte * derive it from minor node type
3369fcf3ce44SJohn Forte */
3370fcf3ce44SJohn Forte static const char *
get_device_type(di_node_t node)3371fcf3ce44SJohn Forte get_device_type(di_node_t node)
3372fcf3ce44SJohn Forte {
3373fcf3ce44SJohn Forte char *name = NULL;
3374fcf3ce44SJohn Forte int *inq_dtype;
3375fcf3ce44SJohn Forte int i;
3376fcf3ce44SJohn Forte
3377fcf3ce44SJohn Forte if (node == DI_NODE_NIL) {
3378fcf3ce44SJohn Forte return (NULL);
3379fcf3ce44SJohn Forte }
3380fcf3ce44SJohn Forte
3381fcf3ce44SJohn Forte /* first, derive type based on inquiry property */
3382fcf3ce44SJohn Forte if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "inquiry-device-type",
3383fcf3ce44SJohn Forte &inq_dtype) != -1) {
3384fcf3ce44SJohn Forte int itype = (*inq_dtype) & DTYPE_MASK;
3385fcf3ce44SJohn Forte
3386fcf3ce44SJohn Forte for (i = 0; i < N_DEVICE_TYPES; i++) {
3387fcf3ce44SJohn Forte if (itype == device_list[i].itype) {
3388fcf3ce44SJohn Forte name = (char *)device_list[i].name;
3389fcf3ce44SJohn Forte break;
3390fcf3ce44SJohn Forte }
3391fcf3ce44SJohn Forte }
3392fcf3ce44SJohn Forte /*
3393fcf3ce44SJohn Forte * when found to be unknown type, set name to null to check
3394fcf3ce44SJohn Forte * device minor node type.
3395fcf3ce44SJohn Forte */
3396fcf3ce44SJohn Forte if (i == (N_DEVICE_TYPES - 1)) {
3397fcf3ce44SJohn Forte name = NULL;
3398fcf3ce44SJohn Forte }
3399fcf3ce44SJohn Forte }
3400fcf3ce44SJohn Forte
3401fcf3ce44SJohn Forte /* if property fails, use minor nodetype */
3402fcf3ce44SJohn Forte if (name == NULL) {
3403fcf3ce44SJohn Forte char *nodetype;
3404fcf3ce44SJohn Forte di_minor_t minor = di_minor_next(node, DI_MINOR_NIL);
3405fcf3ce44SJohn Forte
3406fcf3ce44SJohn Forte if ((minor != DI_MINOR_NIL) &&
3407fcf3ce44SJohn Forte ((nodetype = di_minor_nodetype(minor)) != NULL)) {
3408fcf3ce44SJohn Forte for (i = 0; i < N_DEVICE_TYPES; i++) {
3409fcf3ce44SJohn Forte if (device_list[i].ntype &&
3410fcf3ce44SJohn Forte (strcmp(nodetype, device_list[i].ntype)
3411fcf3ce44SJohn Forte == 0)) {
3412fcf3ce44SJohn Forte name = (char *)device_list[i].name;
3413fcf3ce44SJohn Forte break;
3414fcf3ce44SJohn Forte }
3415fcf3ce44SJohn Forte }
3416fcf3ce44SJohn Forte }
3417fcf3ce44SJohn Forte }
3418fcf3ce44SJohn Forte
3419fcf3ce44SJohn Forte return (name);
3420fcf3ce44SJohn Forte }
3421fcf3ce44SJohn Forte
3422fcf3ce44SJohn Forte /* Transform list data to stat data */
3423fcf3ce44SJohn Forte fpcfga_ret_t
list_ext_postprocess(ldata_list_t ** llpp,int nelem,cfga_list_data_t ** ap_id_list,int * nlistp,char ** errstring)3424fcf3ce44SJohn Forte list_ext_postprocess(
3425fcf3ce44SJohn Forte ldata_list_t **llpp,
3426fcf3ce44SJohn Forte int nelem,
3427fcf3ce44SJohn Forte cfga_list_data_t **ap_id_list,
3428fcf3ce44SJohn Forte int *nlistp,
3429fcf3ce44SJohn Forte char **errstring)
3430fcf3ce44SJohn Forte {
3431fcf3ce44SJohn Forte cfga_list_data_t *ldatap = NULL;
3432fcf3ce44SJohn Forte ldata_list_t *tmplp = NULL;
3433fcf3ce44SJohn Forte int i = -1;
3434fcf3ce44SJohn Forte
3435fcf3ce44SJohn Forte *ap_id_list = NULL;
3436fcf3ce44SJohn Forte *nlistp = 0;
3437fcf3ce44SJohn Forte
3438fcf3ce44SJohn Forte if (*llpp == NULL || nelem < 0) {
3439fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
3440fcf3ce44SJohn Forte }
3441fcf3ce44SJohn Forte
3442fcf3ce44SJohn Forte if (nelem == 0) {
3443fcf3ce44SJohn Forte return (FPCFGA_APID_NOEXIST);
3444fcf3ce44SJohn Forte }
3445fcf3ce44SJohn Forte
3446fcf3ce44SJohn Forte ldatap = calloc(nelem, sizeof (cfga_list_data_t));
3447fcf3ce44SJohn Forte if (ldatap == NULL) {
3448fcf3ce44SJohn Forte cfga_err(errstring, errno, ERR_LIST, 0);
3449fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
3450fcf3ce44SJohn Forte }
3451fcf3ce44SJohn Forte
3452fcf3ce44SJohn Forte /* Extract the list_data structures from the linked list */
3453fcf3ce44SJohn Forte tmplp = *llpp;
3454fcf3ce44SJohn Forte for (i = 0; i < nelem && tmplp != NULL; i++) {
3455fcf3ce44SJohn Forte ldatap[i] = tmplp->ldata;
3456fcf3ce44SJohn Forte tmplp = tmplp->next;
3457fcf3ce44SJohn Forte }
3458fcf3ce44SJohn Forte
3459fcf3ce44SJohn Forte if (i < nelem || tmplp != NULL) {
3460fcf3ce44SJohn Forte S_FREE(ldatap);
3461fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
3462fcf3ce44SJohn Forte }
3463fcf3ce44SJohn Forte
3464fcf3ce44SJohn Forte *nlistp = nelem;
3465fcf3ce44SJohn Forte *ap_id_list = ldatap;
3466fcf3ce44SJohn Forte
3467fcf3ce44SJohn Forte return (FPCFGA_OK);
3468fcf3ce44SJohn Forte }
3469fcf3ce44SJohn Forte
3470fcf3ce44SJohn Forte /*
3471fcf3ce44SJohn Forte * Convert bus state to receptacle state
3472fcf3ce44SJohn Forte */
3473fcf3ce44SJohn Forte static cfga_stat_t
xport_devinfo_to_recep_state(uint_t xport_di_state)3474fcf3ce44SJohn Forte xport_devinfo_to_recep_state(uint_t xport_di_state)
3475fcf3ce44SJohn Forte {
3476fcf3ce44SJohn Forte cfga_stat_t rs;
3477fcf3ce44SJohn Forte
3478fcf3ce44SJohn Forte switch (xport_di_state) {
3479fcf3ce44SJohn Forte case DI_BUS_QUIESCED:
3480fcf3ce44SJohn Forte case DI_BUS_DOWN:
3481fcf3ce44SJohn Forte rs = CFGA_STAT_DISCONNECTED;
3482fcf3ce44SJohn Forte break;
3483fcf3ce44SJohn Forte /*
3484fcf3ce44SJohn Forte * NOTE: An explicit flag for active should probably be added to
3485fcf3ce44SJohn Forte * libdevinfo.
3486fcf3ce44SJohn Forte */
3487fcf3ce44SJohn Forte default:
3488fcf3ce44SJohn Forte rs = CFGA_STAT_CONNECTED;
3489fcf3ce44SJohn Forte break;
3490fcf3ce44SJohn Forte }
3491fcf3ce44SJohn Forte
3492fcf3ce44SJohn Forte return (rs);
3493fcf3ce44SJohn Forte }
3494fcf3ce44SJohn Forte
3495fcf3ce44SJohn Forte /*
3496fcf3ce44SJohn Forte * Convert device state to occupant state
3497fcf3ce44SJohn Forte * if driver is attached the node is configured.
3498fcf3ce44SJohn Forte * if offline or down the node is unconfigured.
3499fcf3ce44SJohn Forte * if only driver detached it is none state which is treated the same
3500fcf3ce44SJohn Forte * way as configured state.
3501fcf3ce44SJohn Forte */
3502fcf3ce44SJohn Forte static cfga_stat_t
dev_devinfo_to_occupant_state(uint_t dev_di_state)3503fcf3ce44SJohn Forte dev_devinfo_to_occupant_state(uint_t dev_di_state)
3504fcf3ce44SJohn Forte {
3505fcf3ce44SJohn Forte /* Driver attached ? */
3506fcf3ce44SJohn Forte if ((dev_di_state & DI_DRIVER_DETACHED) != DI_DRIVER_DETACHED) {
3507fcf3ce44SJohn Forte return (CFGA_STAT_CONFIGURED);
3508fcf3ce44SJohn Forte }
3509fcf3ce44SJohn Forte
3510fcf3ce44SJohn Forte if ((dev_di_state & DI_DEVICE_OFFLINE) == DI_DEVICE_OFFLINE ||
3511fcf3ce44SJohn Forte (dev_di_state & DI_DEVICE_DOWN) == DI_DEVICE_DOWN) {
3512fcf3ce44SJohn Forte return (CFGA_STAT_UNCONFIGURED);
3513fcf3ce44SJohn Forte } else {
3514fcf3ce44SJohn Forte return (CFGA_STAT_NONE);
3515fcf3ce44SJohn Forte }
3516fcf3ce44SJohn Forte }
3517fcf3ce44SJohn Forte
3518fcf3ce44SJohn Forte /*
3519fcf3ce44SJohn Forte * Wrapper routine for inserting ldata to make an sorted ldata list.
3520fcf3ce44SJohn Forte *
3521fcf3ce44SJohn Forte * When show_FCP_dev option is given insert_FCP_dev_ldata() is called.
3522fcf3ce44SJohn Forte * Otherwise insert_fc_dev_ldata() is called.
3523fcf3ce44SJohn Forte */
3524fcf3ce44SJohn Forte static fpcfga_ret_t
insert_ldata_to_ldatalist(const char * port_wwn,int * lun_nump,ldata_list_t * listp,ldata_list_t ** ldatapp)3525fcf3ce44SJohn Forte insert_ldata_to_ldatalist(
3526fcf3ce44SJohn Forte const char *port_wwn,
3527fcf3ce44SJohn Forte int *lun_nump,
3528fcf3ce44SJohn Forte ldata_list_t *listp,
3529fcf3ce44SJohn Forte ldata_list_t **ldatapp)
3530fcf3ce44SJohn Forte {
3531fcf3ce44SJohn Forte
3532fcf3ce44SJohn Forte if (lun_nump == NULL) {
3533fcf3ce44SJohn Forte return (insert_fc_dev_ldata(port_wwn, listp, ldatapp));
3534fcf3ce44SJohn Forte } else {
3535fcf3ce44SJohn Forte return
3536fcf3ce44SJohn Forte (insert_FCP_dev_ldata(port_wwn, *lun_nump, listp, ldatapp));
3537fcf3ce44SJohn Forte }
3538fcf3ce44SJohn Forte }
3539fcf3ce44SJohn Forte
3540fcf3ce44SJohn Forte /*
3541fcf3ce44SJohn Forte * Insert an input ldata to ldata list to make sorted ldata list.
3542fcf3ce44SJohn Forte */
3543fcf3ce44SJohn Forte static fpcfga_ret_t
insert_fc_dev_ldata(const char * port_wwn,ldata_list_t * listp,ldata_list_t ** ldatapp)3544fcf3ce44SJohn Forte insert_fc_dev_ldata(
3545fcf3ce44SJohn Forte const char *port_wwn,
3546fcf3ce44SJohn Forte ldata_list_t *listp,
3547fcf3ce44SJohn Forte ldata_list_t **ldatapp)
3548fcf3ce44SJohn Forte {
3549fcf3ce44SJohn Forte ldata_list_t *prevlp = NULL, *curlp = NULL;
3550fcf3ce44SJohn Forte char *dyn = NULL, *dyncomp = NULL;
3551fcf3ce44SJohn Forte
3552fcf3ce44SJohn Forte if (*ldatapp == NULL) {
3553fcf3ce44SJohn Forte *ldatapp = listp;
3554fcf3ce44SJohn Forte return (FPCFGA_OK);
3555fcf3ce44SJohn Forte }
3556fcf3ce44SJohn Forte
3557fcf3ce44SJohn Forte dyn = GET_DYN((*ldatapp)->ldata.ap_phys_id);
3558fcf3ce44SJohn Forte if (dyn != NULL) dyncomp = DYN_TO_DYNCOMP(dyn);
3559fcf3ce44SJohn Forte if ((dyncomp != NULL) &&
3560fcf3ce44SJohn Forte (strncmp(dyncomp, port_wwn, WWN_SIZE*2) >= 0)) {
3561fcf3ce44SJohn Forte listp->next = *ldatapp;
3562fcf3ce44SJohn Forte *ldatapp = listp;
3563fcf3ce44SJohn Forte return (FPCFGA_OK);
3564fcf3ce44SJohn Forte }
3565fcf3ce44SJohn Forte /* else continue */
3566fcf3ce44SJohn Forte
3567fcf3ce44SJohn Forte prevlp = *ldatapp;
3568fcf3ce44SJohn Forte curlp = (*ldatapp)->next;
3569fcf3ce44SJohn Forte
3570fcf3ce44SJohn Forte dyn = dyncomp = NULL;
3571fcf3ce44SJohn Forte while (curlp != NULL) {
3572fcf3ce44SJohn Forte dyn = GET_DYN(curlp->ldata.ap_phys_id);
3573fcf3ce44SJohn Forte if (dyn != NULL) dyncomp = DYN_TO_DYNCOMP(dyn);
3574fcf3ce44SJohn Forte if ((dyncomp != NULL) &&
3575fcf3ce44SJohn Forte (strncmp(dyncomp, port_wwn, WWN_SIZE*2) >= 0)) {
3576fcf3ce44SJohn Forte listp->next = prevlp->next;
3577fcf3ce44SJohn Forte prevlp->next = listp;
3578fcf3ce44SJohn Forte return (FPCFGA_OK);
3579fcf3ce44SJohn Forte }
3580fcf3ce44SJohn Forte dyn = dyncomp = NULL;
3581fcf3ce44SJohn Forte prevlp = curlp;
3582fcf3ce44SJohn Forte curlp = curlp->next;
3583fcf3ce44SJohn Forte }
3584fcf3ce44SJohn Forte
3585fcf3ce44SJohn Forte /* add the ldata to the end of the list. */
3586fcf3ce44SJohn Forte prevlp->next = listp;
3587fcf3ce44SJohn Forte return (FPCFGA_OK);
3588fcf3ce44SJohn Forte }
3589fcf3ce44SJohn Forte
3590fcf3ce44SJohn Forte /*
3591fcf3ce44SJohn Forte * Insert an input ldata to ldata list to make sorted ldata list.
3592fcf3ce44SJohn Forte */
3593fcf3ce44SJohn Forte static fpcfga_ret_t
insert_FCP_dev_ldata(const char * port_wwn,int lun_num,ldata_list_t * listp,ldata_list_t ** ldatapp)3594fcf3ce44SJohn Forte insert_FCP_dev_ldata(
3595fcf3ce44SJohn Forte const char *port_wwn,
3596fcf3ce44SJohn Forte int lun_num,
3597fcf3ce44SJohn Forte ldata_list_t *listp,
3598fcf3ce44SJohn Forte ldata_list_t **ldatapp)
3599fcf3ce44SJohn Forte {
3600fcf3ce44SJohn Forte ldata_list_t *prevlp = NULL, *curlp = NULL;
3601fcf3ce44SJohn Forte char *dyn = NULL, *dyncomp = NULL;
3602fcf3ce44SJohn Forte char *lun_dyn = NULL, *lunp = NULL;
3603fcf3ce44SJohn Forte
3604fcf3ce44SJohn Forte if (*ldatapp == NULL) {
3605fcf3ce44SJohn Forte *ldatapp = listp;
3606fcf3ce44SJohn Forte return (FPCFGA_OK);
3607fcf3ce44SJohn Forte }
3608fcf3ce44SJohn Forte
3609fcf3ce44SJohn Forte dyn = GET_DYN((*ldatapp)->ldata.ap_phys_id);
3610fcf3ce44SJohn Forte if (dyn != NULL) dyncomp = DYN_TO_DYNCOMP(dyn);
3611fcf3ce44SJohn Forte if ((dyncomp != NULL) &&
3612fcf3ce44SJohn Forte (strncmp(dyncomp, port_wwn, WWN_SIZE*2) == 0)) {
3613fcf3ce44SJohn Forte lun_dyn = GET_LUN_DYN(dyncomp);
3614fcf3ce44SJohn Forte if (lun_dyn != NULL) {
3615fcf3ce44SJohn Forte lunp = LUN_DYN_TO_LUNCOMP(lun_dyn);
3616fcf3ce44SJohn Forte if ((atoi(lunp)) >= lun_num) {
3617fcf3ce44SJohn Forte listp->next = *ldatapp;
3618fcf3ce44SJohn Forte *ldatapp = listp;
3619fcf3ce44SJohn Forte return (FPCFGA_OK);
3620fcf3ce44SJohn Forte }
3621fcf3ce44SJohn Forte }
3622fcf3ce44SJohn Forte } else if ((dyncomp != NULL) &&
3623fcf3ce44SJohn Forte (strncmp(dyncomp, port_wwn, WWN_SIZE*2) > 0)) {
3624fcf3ce44SJohn Forte listp->next = *ldatapp;
3625fcf3ce44SJohn Forte *ldatapp = listp;
3626fcf3ce44SJohn Forte return (FPCFGA_OK);
3627fcf3ce44SJohn Forte }
3628fcf3ce44SJohn Forte
3629fcf3ce44SJohn Forte prevlp = *ldatapp;
3630fcf3ce44SJohn Forte curlp = (*ldatapp)->next;
3631fcf3ce44SJohn Forte
3632fcf3ce44SJohn Forte dyn = dyncomp = NULL;
3633fcf3ce44SJohn Forte lun_dyn = lunp = NULL;
3634fcf3ce44SJohn Forte while (curlp != NULL) {
3635fcf3ce44SJohn Forte dyn = GET_DYN(curlp->ldata.ap_phys_id);
3636fcf3ce44SJohn Forte if (dyn != NULL) dyncomp = DYN_TO_DYNCOMP(dyn);
3637fcf3ce44SJohn Forte
3638fcf3ce44SJohn Forte if ((dyncomp != NULL) &&
3639fcf3ce44SJohn Forte (strncmp(dyncomp, port_wwn, WWN_SIZE*2) == 0)) {
3640fcf3ce44SJohn Forte lun_dyn = GET_LUN_DYN(dyncomp);
3641fcf3ce44SJohn Forte if (lun_dyn != NULL) {
3642fcf3ce44SJohn Forte lunp = LUN_DYN_TO_LUNCOMP(lun_dyn);
3643fcf3ce44SJohn Forte if ((atoi(lunp)) >= lun_num) {
3644fcf3ce44SJohn Forte listp->next = prevlp->next;
3645fcf3ce44SJohn Forte prevlp->next = listp;
3646fcf3ce44SJohn Forte return (FPCFGA_OK);
3647fcf3ce44SJohn Forte }
3648fcf3ce44SJohn Forte }
3649fcf3ce44SJohn Forte /* else continue */
3650fcf3ce44SJohn Forte } else if ((dyncomp != NULL) &&
3651fcf3ce44SJohn Forte (strncmp(dyncomp, port_wwn, WWN_SIZE*2) > 0)) {
3652fcf3ce44SJohn Forte listp->next = prevlp->next;
3653fcf3ce44SJohn Forte prevlp->next = listp;
3654fcf3ce44SJohn Forte return (FPCFGA_OK);
3655fcf3ce44SJohn Forte }
3656fcf3ce44SJohn Forte /* else continue */
3657fcf3ce44SJohn Forte
3658fcf3ce44SJohn Forte dyn = dyncomp = NULL;
3659fcf3ce44SJohn Forte lun_dyn = lunp = NULL;
3660fcf3ce44SJohn Forte prevlp = curlp;
3661fcf3ce44SJohn Forte curlp = curlp->next;
3662fcf3ce44SJohn Forte }
3663fcf3ce44SJohn Forte
3664fcf3ce44SJohn Forte /* add the ldata to the end of the list. */
3665fcf3ce44SJohn Forte prevlp->next = listp;
3666fcf3ce44SJohn Forte return (FPCFGA_OK);
3667fcf3ce44SJohn Forte }
3668fcf3ce44SJohn Forte
3669fcf3ce44SJohn Forte /*
3670fcf3ce44SJohn Forte * This function will return the dtype for the given device
3671fcf3ce44SJohn Forte * It will first issue a report lun to lun 0 and then it will issue a SCSI
3672fcf3ce44SJohn Forte * Inquiry to the first lun returned by report luns.
3673fcf3ce44SJohn Forte *
3674fcf3ce44SJohn Forte * If everything is successful, the dtype will be returned with the peri
3675fcf3ce44SJohn Forte * qualifier masked out.
3676fcf3ce44SJohn Forte *
3677fcf3ce44SJohn Forte * If either the report lun or the scsi inquiry fails, we will first check
3678fcf3ce44SJohn Forte * the return status. If the return status is SCSI_DEVICE_NOT_TGT, then
3679fcf3ce44SJohn Forte * we will assume this is a remote HBA and return an UNKNOWN DTYPE
3680fcf3ce44SJohn Forte * for all other failures, we will return a dtype of ERR_INQ_DTYPE
3681fcf3ce44SJohn Forte */
3682fcf3ce44SJohn Forte static uchar_t
get_inq_dtype(char * xport_phys,char * dyncomp,HBA_HANDLE handle,HBA_PORTATTRIBUTES * portAttrs,HBA_PORTATTRIBUTES * discPortAttrs)3683fcf3ce44SJohn Forte get_inq_dtype(char *xport_phys, char *dyncomp, HBA_HANDLE handle,
3684fcf3ce44SJohn Forte HBA_PORTATTRIBUTES *portAttrs, HBA_PORTATTRIBUTES *discPortAttrs) {
3685fcf3ce44SJohn Forte HBA_STATUS status;
3686fcf3ce44SJohn Forte report_lun_resp_t *resp_buf;
3687fcf3ce44SJohn Forte int num_luns = 0, ret, l_errno;
3688fcf3ce44SJohn Forte uchar_t *lun_string;
3689fcf3ce44SJohn Forte uint64_t lun = 0;
3690fcf3ce44SJohn Forte struct scsi_inquiry inq;
3691fcf3ce44SJohn Forte struct scsi_extended_sense sense;
3692fcf3ce44SJohn Forte HBA_UINT8 scsiStatus;
3693fcf3ce44SJohn Forte uint32_t inquirySize = sizeof (inq);
3694fcf3ce44SJohn Forte uint32_t senseSize = sizeof (sense);
3695fcf3ce44SJohn Forte
3696fcf3ce44SJohn Forte memset(&inq, 0, sizeof (inq));
3697fcf3ce44SJohn Forte memset(&sense, 0, sizeof (sense));
3698fcf3ce44SJohn Forte if ((ret = get_report_lun_data(xport_phys, dyncomp,
3699fcf3ce44SJohn Forte &num_luns, &resp_buf, &sense, &l_errno))
3700fcf3ce44SJohn Forte != FPCFGA_OK) {
3701fcf3ce44SJohn Forte /*
3702fcf3ce44SJohn Forte * Checking the sense key data as well as the additional
3703fcf3ce44SJohn Forte * sense key. The SES Node is not required to repond
3704fcf3ce44SJohn Forte * to Report LUN. In the case of Minnow, the SES node
3705fcf3ce44SJohn Forte * returns with KEY_ILLEGAL_REQUEST and the additional
3706fcf3ce44SJohn Forte * sense key of 0x20. In this case we will blindly
3707fcf3ce44SJohn Forte * send the SCSI Inquiry call to lun 0
3708fcf3ce44SJohn Forte *
3709fcf3ce44SJohn Forte * if we get any other error we will set the inq_type
3710fcf3ce44SJohn Forte * appropriately
3711fcf3ce44SJohn Forte */
3712fcf3ce44SJohn Forte if ((sense.es_key == KEY_ILLEGAL_REQUEST) &&
3713fcf3ce44SJohn Forte (sense.es_add_code == 0x20)) {
3714fcf3ce44SJohn Forte lun = 0;
3715fcf3ce44SJohn Forte } else {
3716fcf3ce44SJohn Forte if (ret == FPCFGA_FCP_SEND_SCSI_DEV_NOT_TGT) {
3717fcf3ce44SJohn Forte inq.inq_dtype = DTYPE_UNKNOWN;
3718fcf3ce44SJohn Forte } else {
3719fcf3ce44SJohn Forte inq.inq_dtype = ERR_INQ_DTYPE;
3720fcf3ce44SJohn Forte }
3721fcf3ce44SJohn Forte return (inq.inq_dtype);
3722fcf3ce44SJohn Forte }
3723fcf3ce44SJohn Forte } else {
3724fcf3ce44SJohn Forte /* send the inquiry to the first lun */
3725fcf3ce44SJohn Forte lun_string = (uchar_t *)&(resp_buf->lun_string[0]);
3726fcf3ce44SJohn Forte memcpy(&lun, lun_string, sizeof (lun));
3727fcf3ce44SJohn Forte S_FREE(resp_buf);
3728fcf3ce44SJohn Forte }
3729fcf3ce44SJohn Forte
3730fcf3ce44SJohn Forte memset(&sense, 0, sizeof (sense));
3731fcf3ce44SJohn Forte status = HBA_ScsiInquiryV2(handle,
3732fcf3ce44SJohn Forte portAttrs->PortWWN, discPortAttrs->PortWWN, lun, 0, 0,
3733fcf3ce44SJohn Forte &inq, &inquirySize, &scsiStatus, &sense, &senseSize);
3734fcf3ce44SJohn Forte if (status == HBA_STATUS_OK) {
3735fcf3ce44SJohn Forte inq.inq_dtype = inq.inq_dtype & DTYPE_MASK;
3736fcf3ce44SJohn Forte } else if (status == HBA_STATUS_ERROR_NOT_A_TARGET) {
3737fcf3ce44SJohn Forte inq.inq_dtype = DTYPE_UNKNOWN;
3738fcf3ce44SJohn Forte } else {
3739fcf3ce44SJohn Forte inq.inq_dtype = ERR_INQ_DTYPE;
3740fcf3ce44SJohn Forte }
3741fcf3ce44SJohn Forte return (inq.inq_dtype);
3742fcf3ce44SJohn Forte }
3743