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 /*
22*0c034175SJiri Svoboda  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
23fcf3ce44SJohn Forte  */
24fcf3ce44SJohn Forte 
25fcf3ce44SJohn Forte #include <string.h>
26fcf3ce44SJohn Forte #include <syslog.h>
27fcf3ce44SJohn Forte #include <errno.h>
28fcf3ce44SJohn Forte #include <unistd.h>
29fcf3ce44SJohn Forte #include <stropts.h>
30fcf3ce44SJohn Forte #include <libdevinfo.h>
31fcf3ce44SJohn Forte 
32fcf3ce44SJohn Forte #include "mp_utils.h"
33fcf3ce44SJohn Forte 
34fcf3ce44SJohn Forte 
getOidList(di_node_t root_node,MP_OID_LIST * pOidList,char * pProductID,char * pVendorID)35fcf3ce44SJohn Forte static int getOidList(di_node_t root_node,
36fcf3ce44SJohn Forte 			MP_OID_LIST *pOidList,
37fcf3ce44SJohn Forte 			char *pProductID,
38fcf3ce44SJohn Forte 			char *pVendorID)
39fcf3ce44SJohn Forte {
40fcf3ce44SJohn Forte 	int numNodes = 0;
41fcf3ce44SJohn Forte 	int pidSize = 0;
42fcf3ce44SJohn Forte 	int vidSize = 0;
43fcf3ce44SJohn Forte 
44fcf3ce44SJohn Forte 	int haveList = (NULL != pOidList);
45fcf3ce44SJohn Forte 
46fcf3ce44SJohn Forte 	char *pid = NULL;
47fcf3ce44SJohn Forte 	char *vid = NULL;
48fcf3ce44SJohn Forte 
49fcf3ce44SJohn Forte 	di_node_t sv_node	= DI_NODE_NIL;
50fcf3ce44SJohn Forte 	di_node_t sv_child_node	= DI_NODE_NIL;
51fcf3ce44SJohn Forte 
52*0c034175SJiri Svoboda 	int instNum;
53*0c034175SJiri Svoboda 	int majorNum;
54*0c034175SJiri Svoboda 	MP_UINT64 osn;
55fcf3ce44SJohn Forte 
56fcf3ce44SJohn Forte 
57fcf3ce44SJohn Forte 	log(LOG_INFO, "getOidList()", " - enter");
58fcf3ce44SJohn Forte 
59fcf3ce44SJohn Forte 
60fcf3ce44SJohn Forte 	sv_node = di_drv_first_node("scsi_vhci", root_node);
61fcf3ce44SJohn Forte 	if (DI_NODE_NIL == sv_node) {
62*0c034175SJiri Svoboda 		log(LOG_INFO, "getOidList()", " - di_drv_first_node() failed");
63fcf3ce44SJohn Forte 		return (-1);
64fcf3ce44SJohn Forte 	}
65fcf3ce44SJohn Forte 
66fcf3ce44SJohn Forte 
67fcf3ce44SJohn Forte 	sv_child_node = di_child_node(sv_node);
68fcf3ce44SJohn Forte 
69fcf3ce44SJohn Forte 	while (DI_NODE_NIL != sv_child_node) {
70fcf3ce44SJohn Forte 
71*0c034175SJiri Svoboda 		(void) di_prop_lookup_strings(DDI_DEV_T_ANY, sv_child_node,
72*0c034175SJiri Svoboda 		    "inquiry-product-id", &pid);
73fcf3ce44SJohn Forte 
74fcf3ce44SJohn Forte 		pidSize = strlen(pid);
75fcf3ce44SJohn Forte 
76*0c034175SJiri Svoboda 		(void) di_prop_lookup_strings(DDI_DEV_T_ANY, sv_child_node,
77*0c034175SJiri Svoboda 		    "inquiry-vendor-id", &vid);
78fcf3ce44SJohn Forte 
79fcf3ce44SJohn Forte 		vidSize = strlen(vid);
80fcf3ce44SJohn Forte 
81fcf3ce44SJohn Forte 		if ((0 == strncmp(pProductID, pid, pidSize)) &&
82fcf3ce44SJohn Forte 		    (0 == strncmp(pVendorID, vid, vidSize))) {
83fcf3ce44SJohn Forte 
84*0c034175SJiri Svoboda 			instNum = di_instance(sv_child_node);
85*0c034175SJiri Svoboda 			majorNum = di_driver_major(sv_child_node);
86fcf3ce44SJohn Forte 
87*0c034175SJiri Svoboda 			if (haveList && numNodes < pOidList->oidCount) {
88fcf3ce44SJohn Forte 
89*0c034175SJiri Svoboda 				osn = 0;
90*0c034175SJiri Svoboda 				osn = MP_STORE_INST_TO_ID(instNum, osn);
91*0c034175SJiri Svoboda 				osn = MP_STORE_MAJOR_TO_ID(majorNum, osn);
92fcf3ce44SJohn Forte 
93*0c034175SJiri Svoboda 				pOidList->oids[numNodes].objectType =
94*0c034175SJiri Svoboda 				    MP_OBJECT_TYPE_MULTIPATH_LU;
95fcf3ce44SJohn Forte 
96*0c034175SJiri Svoboda 				pOidList->oids[numNodes].ownerId =
97*0c034175SJiri Svoboda 				    g_pluginOwnerID;
98fcf3ce44SJohn Forte 
99*0c034175SJiri Svoboda 				pOidList->oids[numNodes].objectSequenceNumber =
100*0c034175SJiri Svoboda 				    osn;
101*0c034175SJiri Svoboda 			}
102fcf3ce44SJohn Forte 
103fcf3ce44SJohn Forte 			++numNodes;
104fcf3ce44SJohn Forte 		}
105fcf3ce44SJohn Forte 
106fcf3ce44SJohn Forte 		sv_child_node = di_sibling_node(sv_child_node);
107fcf3ce44SJohn Forte 	}
108fcf3ce44SJohn Forte 
109fcf3ce44SJohn Forte 
110*0c034175SJiri Svoboda 	log(LOG_INFO, "getOidList()", " - numNodes: %d", numNodes);
111fcf3ce44SJohn Forte 	log(LOG_INFO, "getOidList()", " - exit");
112fcf3ce44SJohn Forte 
113fcf3ce44SJohn Forte 	return (numNodes);
114fcf3ce44SJohn Forte }
115fcf3ce44SJohn Forte 
116fcf3ce44SJohn Forte 
117fcf3ce44SJohn Forte MP_STATUS
MP_GetMultipathLusDevProd(MP_OID oid,MP_OID_LIST ** ppList)118fcf3ce44SJohn Forte MP_GetMultipathLusDevProd(MP_OID oid, MP_OID_LIST **ppList)
119fcf3ce44SJohn Forte {
120fcf3ce44SJohn Forte 	di_node_t root_node	= DI_NODE_NIL;
121fcf3ce44SJohn Forte 
122fcf3ce44SJohn Forte 	MP_STATUS mpStatus	= MP_STATUS_SUCCESS;
123fcf3ce44SJohn Forte 
124fcf3ce44SJohn Forte 	int numNodes = 0;
125fcf3ce44SJohn Forte 	int ioctlStatus = 0;
126fcf3ce44SJohn Forte 	int i = 0;
127fcf3ce44SJohn Forte 
128fcf3ce44SJohn Forte 	mp_iocdata_t		mp_ioctl;
129fcf3ce44SJohn Forte 	mp_dev_prod_prop_t	devProdInfo;
130fcf3ce44SJohn Forte 
131fcf3ce44SJohn Forte 	char inqProductID[256];
132fcf3ce44SJohn Forte 	char inqVendorID[256];
133fcf3ce44SJohn Forte 
134fcf3ce44SJohn Forte 
135fcf3ce44SJohn Forte 	log(LOG_INFO, "MP_GetMultipathLusDevProd()", " - enter");
136fcf3ce44SJohn Forte 
137fcf3ce44SJohn Forte 	log(LOG_INFO, "MP_GetMultipathLusDevProd()",
138*0c034175SJiri Svoboda 	    "oid.objectSequenceNumber = %llx",
139*0c034175SJiri Svoboda 	    oid.objectSequenceNumber);
140fcf3ce44SJohn Forte 
141fcf3ce44SJohn Forte 	if (g_scsi_vhci_fd < 0) {
142fcf3ce44SJohn Forte 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
143fcf3ce44SJohn Forte 		    "invalid driver file handle");
144fcf3ce44SJohn Forte 		log(LOG_INFO, "MP_GetMultipathLusDevProd",
145*0c034175SJiri Svoboda 		    " - error exit");
146fcf3ce44SJohn Forte 		return (MP_STATUS_FAILED);
147fcf3ce44SJohn Forte 	}
148fcf3ce44SJohn Forte 
149fcf3ce44SJohn Forte 	(void) memset(&mp_ioctl, 0, sizeof (mp_iocdata_t));
150fcf3ce44SJohn Forte 	(void) memset(&devProdInfo, 0, sizeof (mp_dev_prod_prop_t));
151fcf3ce44SJohn Forte 
152fcf3ce44SJohn Forte 	mp_ioctl.mp_cmd  = MP_GET_DEV_PROD_PROP;
153fcf3ce44SJohn Forte 	mp_ioctl.mp_ibuf = (caddr_t)&oid.objectSequenceNumber;
154fcf3ce44SJohn Forte 	mp_ioctl.mp_ilen = sizeof (oid.objectSequenceNumber);
155fcf3ce44SJohn Forte 	mp_ioctl.mp_obuf = (caddr_t)&devProdInfo;
156fcf3ce44SJohn Forte 	mp_ioctl.mp_olen = sizeof (mp_dev_prod_prop_t);
157fcf3ce44SJohn Forte 	mp_ioctl.mp_xfer = MP_XFER_READ;
158fcf3ce44SJohn Forte 
159fcf3ce44SJohn Forte 	ioctlStatus = ioctl(g_scsi_vhci_fd, MP_CMD, &mp_ioctl);
160fcf3ce44SJohn Forte 
161fcf3ce44SJohn Forte 	log(LOG_INFO, "MP_GetMultipathLusDevProd()",
162*0c034175SJiri Svoboda 	    " IOCTL call returned: %d", ioctlStatus);
163fcf3ce44SJohn Forte 
164fcf3ce44SJohn Forte 	if (ioctlStatus < 0) {
165fcf3ce44SJohn Forte 		ioctlStatus = errno;
166fcf3ce44SJohn Forte 	}
167fcf3ce44SJohn Forte 
168fcf3ce44SJohn Forte 	if (ioctlStatus != 0) {
169fcf3ce44SJohn Forte 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
170fcf3ce44SJohn Forte 		    "IOCTL call failed.  IOCTL error is: %d",
171*0c034175SJiri Svoboda 		    ioctlStatus);
172fcf3ce44SJohn Forte 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
173fcf3ce44SJohn Forte 		    "IOCTL call failed.  IOCTL error is: %s",
174*0c034175SJiri Svoboda 		    strerror(ioctlStatus));
175fcf3ce44SJohn Forte 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
176fcf3ce44SJohn Forte 		    "IOCTL call failed.  mp_ioctl.mp_errno: %x",
177*0c034175SJiri Svoboda 		    mp_ioctl.mp_errno);
178fcf3ce44SJohn Forte 
179fcf3ce44SJohn Forte 		if (ENOTSUP == ioctlStatus) {
180fcf3ce44SJohn Forte 			mpStatus = MP_STATUS_UNSUPPORTED;
181fcf3ce44SJohn Forte 		} else if (0 == mp_ioctl.mp_errno) {
182fcf3ce44SJohn Forte 			mpStatus = MP_STATUS_FAILED;
183fcf3ce44SJohn Forte 		} else {
184fcf3ce44SJohn Forte 			mpStatus = getStatus4ErrorCode(mp_ioctl.mp_errno);
185fcf3ce44SJohn Forte 		}
186fcf3ce44SJohn Forte 
187fcf3ce44SJohn Forte 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
188*0c034175SJiri Svoboda 		    " - error exit");
189fcf3ce44SJohn Forte 
190fcf3ce44SJohn Forte 		return (mpStatus);
191fcf3ce44SJohn Forte 	}
192fcf3ce44SJohn Forte 
193*0c034175SJiri Svoboda 	(void) strncpy(inqProductID, devProdInfo.prodInfo.product,
194*0c034175SJiri Svoboda 	    sizeof (devProdInfo.prodInfo.product));
195fcf3ce44SJohn Forte 
196*0c034175SJiri Svoboda 	(void) strncpy(inqVendorID, devProdInfo.prodInfo.vendor,
197*0c034175SJiri Svoboda 	    sizeof (devProdInfo.prodInfo.vendor));
198fcf3ce44SJohn Forte 
199fcf3ce44SJohn Forte 	log(LOG_INFO, "MP_GetMultipathLusDevProd()",
200*0c034175SJiri Svoboda 	    " - inqProductID:  [%s]", inqProductID);
201fcf3ce44SJohn Forte 	log(LOG_INFO, "MP_GetMultipathLusDevProd()",
202*0c034175SJiri Svoboda 	    " - inqVendorID:   [%s]", inqVendorID);
203fcf3ce44SJohn Forte 
204fcf3ce44SJohn Forte 	root_node = di_init("/", DINFOCACHE);
205fcf3ce44SJohn Forte 	if (DI_NODE_NIL == root_node) {
206fcf3ce44SJohn Forte 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
207*0c034175SJiri Svoboda 		    " - di_init() failed");
208fcf3ce44SJohn Forte 
209fcf3ce44SJohn Forte 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
210*0c034175SJiri Svoboda 		    " - error exit");
211fcf3ce44SJohn Forte 
212fcf3ce44SJohn Forte 		return (MP_STATUS_FAILED);
213fcf3ce44SJohn Forte 	}
214fcf3ce44SJohn Forte 
215*0c034175SJiri Svoboda 	numNodes = getOidList(root_node, NULL, inqProductID, inqVendorID);
216fcf3ce44SJohn Forte 	if (numNodes < 0) {
217fcf3ce44SJohn Forte 
218fcf3ce44SJohn Forte 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
219*0c034175SJiri Svoboda 		    " - unable to get OID list.");
220*0c034175SJiri Svoboda 
221*0c034175SJiri Svoboda 		log(LOG_INFO, "MP_GetMultipathLusDevProd()", " - error exit");
222fcf3ce44SJohn Forte 
223fcf3ce44SJohn Forte 		di_fini(root_node);
224fcf3ce44SJohn Forte 
225fcf3ce44SJohn Forte 		return (MP_STATUS_FAILED);
226fcf3ce44SJohn Forte 	}
227fcf3ce44SJohn Forte 
228fcf3ce44SJohn Forte 
229fcf3ce44SJohn Forte 	if (0 == numNodes) {
230fcf3ce44SJohn Forte 
231fcf3ce44SJohn Forte 		*ppList = createOidList(1);
232fcf3ce44SJohn Forte 		if (NULL == *ppList) {
233fcf3ce44SJohn Forte 
234*0c034175SJiri Svoboda 			log(LOG_INFO, "MP_GetMultipathLusDevProd()",
235*0c034175SJiri Svoboda 			    " - unable to create OID list.");
236fcf3ce44SJohn Forte 
237fcf3ce44SJohn Forte 			log(LOG_INFO, "MP_GetMultipathLusDevProd()",
238*0c034175SJiri Svoboda 			    " - error exit");
239fcf3ce44SJohn Forte 
240fcf3ce44SJohn Forte 			di_fini(root_node);
241fcf3ce44SJohn Forte 
242fcf3ce44SJohn Forte 			return (MP_STATUS_INSUFFICIENT_MEMORY);
243fcf3ce44SJohn Forte 		}
244fcf3ce44SJohn Forte 
245*0c034175SJiri Svoboda 		(*ppList)->oids[0].objectType = MP_OBJECT_TYPE_MULTIPATH_LU;
246*0c034175SJiri Svoboda 		(*ppList)->oids[0].ownerId = g_pluginOwnerID;
247fcf3ce44SJohn Forte 
248fcf3ce44SJohn Forte 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
249*0c034175SJiri Svoboda 		    " - returning empty list.");
250fcf3ce44SJohn Forte 
251fcf3ce44SJohn Forte 		return (MP_STATUS_SUCCESS);
252fcf3ce44SJohn Forte 	}
253fcf3ce44SJohn Forte 
254fcf3ce44SJohn Forte 	*ppList = createOidList(numNodes);
255fcf3ce44SJohn Forte 	if (NULL == *ppList) {
256fcf3ce44SJohn Forte 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
257*0c034175SJiri Svoboda 		    "no memory for *ppList");
258fcf3ce44SJohn Forte 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
259*0c034175SJiri Svoboda 		    " - error exit");
260fcf3ce44SJohn Forte 		return (MP_STATUS_INSUFFICIENT_MEMORY);
261fcf3ce44SJohn Forte 	}
262fcf3ce44SJohn Forte 
263fcf3ce44SJohn Forte 	(*ppList)->oidCount = numNodes;
264fcf3ce44SJohn Forte 
265*0c034175SJiri Svoboda 	numNodes = getOidList(root_node, *ppList, inqProductID, inqVendorID);
266fcf3ce44SJohn Forte 
267fcf3ce44SJohn Forte 	for (i = 0; i < (*ppList)->oidCount; i++) {
268fcf3ce44SJohn Forte 
269fcf3ce44SJohn Forte 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
270*0c034175SJiri Svoboda 		    "(*ppList)->oids[%d].objectType           = %d",
271*0c034175SJiri Svoboda 		    i, (*ppList)->oids[i].objectType);
272fcf3ce44SJohn Forte 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
273*0c034175SJiri Svoboda 		    "(*ppList)->oids[%d].ownerId              = %d",
274*0c034175SJiri Svoboda 		    i, (*ppList)->oids[i].ownerId);
275fcf3ce44SJohn Forte 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
276*0c034175SJiri Svoboda 		    "(*ppList)->oids[%d].objectSequenceNumber = %llx",
277*0c034175SJiri Svoboda 		    i, (*ppList)->oids[i].objectSequenceNumber);
278fcf3ce44SJohn Forte 	}
279fcf3ce44SJohn Forte 
280fcf3ce44SJohn Forte 
281fcf3ce44SJohn Forte 	di_fini(root_node);
282fcf3ce44SJohn Forte 
283fcf3ce44SJohn Forte 	log(LOG_INFO, "MP_GetMultipathLusDevProd()", " - exit");
284fcf3ce44SJohn Forte 
285fcf3ce44SJohn Forte 	return (MP_STATUS_SUCCESS);
286fcf3ce44SJohn Forte 
287fcf3ce44SJohn Forte }
288