17836SJohn.Forte@Sun.COM /*
27836SJohn.Forte@Sun.COM  * CDDL HEADER START
37836SJohn.Forte@Sun.COM  *
47836SJohn.Forte@Sun.COM  * The contents of this file are subject to the terms of the
57836SJohn.Forte@Sun.COM  * Common Development and Distribution License (the "License").
67836SJohn.Forte@Sun.COM  * You may not use this file except in compliance with the License.
77836SJohn.Forte@Sun.COM  *
87836SJohn.Forte@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97836SJohn.Forte@Sun.COM  * or http://www.opensolaris.org/os/licensing.
107836SJohn.Forte@Sun.COM  * See the License for the specific language governing permissions
117836SJohn.Forte@Sun.COM  * and limitations under the License.
127836SJohn.Forte@Sun.COM  *
137836SJohn.Forte@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
147836SJohn.Forte@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157836SJohn.Forte@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
167836SJohn.Forte@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
177836SJohn.Forte@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
187836SJohn.Forte@Sun.COM  *
197836SJohn.Forte@Sun.COM  * CDDL HEADER END
207836SJohn.Forte@Sun.COM  */
217836SJohn.Forte@Sun.COM /*
22*12334SJiri.Svoboda@Sun.COM  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
237836SJohn.Forte@Sun.COM  */
247836SJohn.Forte@Sun.COM 
257836SJohn.Forte@Sun.COM #include <string.h>
267836SJohn.Forte@Sun.COM #include <syslog.h>
277836SJohn.Forte@Sun.COM #include <errno.h>
287836SJohn.Forte@Sun.COM #include <unistd.h>
297836SJohn.Forte@Sun.COM #include <stropts.h>
307836SJohn.Forte@Sun.COM #include <libdevinfo.h>
317836SJohn.Forte@Sun.COM 
327836SJohn.Forte@Sun.COM #include "mp_utils.h"
337836SJohn.Forte@Sun.COM 
347836SJohn.Forte@Sun.COM 
getOidList(di_node_t root_node,MP_OID_LIST * pOidList,char * pProductID,char * pVendorID)357836SJohn.Forte@Sun.COM static int getOidList(di_node_t root_node,
367836SJohn.Forte@Sun.COM 			MP_OID_LIST *pOidList,
377836SJohn.Forte@Sun.COM 			char *pProductID,
387836SJohn.Forte@Sun.COM 			char *pVendorID)
397836SJohn.Forte@Sun.COM {
407836SJohn.Forte@Sun.COM 	int numNodes = 0;
417836SJohn.Forte@Sun.COM 	int pidSize = 0;
427836SJohn.Forte@Sun.COM 	int vidSize = 0;
437836SJohn.Forte@Sun.COM 
447836SJohn.Forte@Sun.COM 	int haveList = (NULL != pOidList);
457836SJohn.Forte@Sun.COM 
467836SJohn.Forte@Sun.COM 	char *pid = NULL;
477836SJohn.Forte@Sun.COM 	char *vid = NULL;
487836SJohn.Forte@Sun.COM 
497836SJohn.Forte@Sun.COM 	di_node_t sv_node	= DI_NODE_NIL;
507836SJohn.Forte@Sun.COM 	di_node_t sv_child_node	= DI_NODE_NIL;
517836SJohn.Forte@Sun.COM 
52*12334SJiri.Svoboda@Sun.COM 	int instNum;
53*12334SJiri.Svoboda@Sun.COM 	int majorNum;
54*12334SJiri.Svoboda@Sun.COM 	MP_UINT64 osn;
557836SJohn.Forte@Sun.COM 
567836SJohn.Forte@Sun.COM 
577836SJohn.Forte@Sun.COM 	log(LOG_INFO, "getOidList()", " - enter");
587836SJohn.Forte@Sun.COM 
597836SJohn.Forte@Sun.COM 
607836SJohn.Forte@Sun.COM 	sv_node = di_drv_first_node("scsi_vhci", root_node);
617836SJohn.Forte@Sun.COM 	if (DI_NODE_NIL == sv_node) {
62*12334SJiri.Svoboda@Sun.COM 		log(LOG_INFO, "getOidList()", " - di_drv_first_node() failed");
637836SJohn.Forte@Sun.COM 		return (-1);
647836SJohn.Forte@Sun.COM 	}
657836SJohn.Forte@Sun.COM 
667836SJohn.Forte@Sun.COM 
677836SJohn.Forte@Sun.COM 	sv_child_node = di_child_node(sv_node);
687836SJohn.Forte@Sun.COM 
697836SJohn.Forte@Sun.COM 	while (DI_NODE_NIL != sv_child_node) {
707836SJohn.Forte@Sun.COM 
71*12334SJiri.Svoboda@Sun.COM 		(void) di_prop_lookup_strings(DDI_DEV_T_ANY, sv_child_node,
72*12334SJiri.Svoboda@Sun.COM 		    "inquiry-product-id", &pid);
737836SJohn.Forte@Sun.COM 
747836SJohn.Forte@Sun.COM 		pidSize = strlen(pid);
757836SJohn.Forte@Sun.COM 
76*12334SJiri.Svoboda@Sun.COM 		(void) di_prop_lookup_strings(DDI_DEV_T_ANY, sv_child_node,
77*12334SJiri.Svoboda@Sun.COM 		    "inquiry-vendor-id", &vid);
787836SJohn.Forte@Sun.COM 
797836SJohn.Forte@Sun.COM 		vidSize = strlen(vid);
807836SJohn.Forte@Sun.COM 
817836SJohn.Forte@Sun.COM 		if ((0 == strncmp(pProductID, pid, pidSize)) &&
827836SJohn.Forte@Sun.COM 		    (0 == strncmp(pVendorID, vid, vidSize))) {
837836SJohn.Forte@Sun.COM 
84*12334SJiri.Svoboda@Sun.COM 			instNum = di_instance(sv_child_node);
85*12334SJiri.Svoboda@Sun.COM 			majorNum = di_driver_major(sv_child_node);
867836SJohn.Forte@Sun.COM 
87*12334SJiri.Svoboda@Sun.COM 			if (haveList && numNodes < pOidList->oidCount) {
887836SJohn.Forte@Sun.COM 
89*12334SJiri.Svoboda@Sun.COM 				osn = 0;
90*12334SJiri.Svoboda@Sun.COM 				osn = MP_STORE_INST_TO_ID(instNum, osn);
91*12334SJiri.Svoboda@Sun.COM 				osn = MP_STORE_MAJOR_TO_ID(majorNum, osn);
927836SJohn.Forte@Sun.COM 
93*12334SJiri.Svoboda@Sun.COM 				pOidList->oids[numNodes].objectType =
94*12334SJiri.Svoboda@Sun.COM 				    MP_OBJECT_TYPE_MULTIPATH_LU;
957836SJohn.Forte@Sun.COM 
96*12334SJiri.Svoboda@Sun.COM 				pOidList->oids[numNodes].ownerId =
97*12334SJiri.Svoboda@Sun.COM 				    g_pluginOwnerID;
987836SJohn.Forte@Sun.COM 
99*12334SJiri.Svoboda@Sun.COM 				pOidList->oids[numNodes].objectSequenceNumber =
100*12334SJiri.Svoboda@Sun.COM 				    osn;
101*12334SJiri.Svoboda@Sun.COM 			}
1027836SJohn.Forte@Sun.COM 
1037836SJohn.Forte@Sun.COM 			++numNodes;
1047836SJohn.Forte@Sun.COM 		}
1057836SJohn.Forte@Sun.COM 
1067836SJohn.Forte@Sun.COM 		sv_child_node = di_sibling_node(sv_child_node);
1077836SJohn.Forte@Sun.COM 	}
1087836SJohn.Forte@Sun.COM 
1097836SJohn.Forte@Sun.COM 
110*12334SJiri.Svoboda@Sun.COM 	log(LOG_INFO, "getOidList()", " - numNodes: %d", numNodes);
1117836SJohn.Forte@Sun.COM 	log(LOG_INFO, "getOidList()", " - exit");
1127836SJohn.Forte@Sun.COM 
1137836SJohn.Forte@Sun.COM 	return (numNodes);
1147836SJohn.Forte@Sun.COM }
1157836SJohn.Forte@Sun.COM 
1167836SJohn.Forte@Sun.COM 
1177836SJohn.Forte@Sun.COM MP_STATUS
MP_GetMultipathLusDevProd(MP_OID oid,MP_OID_LIST ** ppList)1187836SJohn.Forte@Sun.COM MP_GetMultipathLusDevProd(MP_OID oid, MP_OID_LIST **ppList)
1197836SJohn.Forte@Sun.COM {
1207836SJohn.Forte@Sun.COM 	di_node_t root_node	= DI_NODE_NIL;
1217836SJohn.Forte@Sun.COM 
1227836SJohn.Forte@Sun.COM 	MP_STATUS mpStatus	= MP_STATUS_SUCCESS;
1237836SJohn.Forte@Sun.COM 
1247836SJohn.Forte@Sun.COM 	int numNodes = 0;
1257836SJohn.Forte@Sun.COM 	int ioctlStatus = 0;
1267836SJohn.Forte@Sun.COM 	int i = 0;
1277836SJohn.Forte@Sun.COM 
1287836SJohn.Forte@Sun.COM 	mp_iocdata_t		mp_ioctl;
1297836SJohn.Forte@Sun.COM 	mp_dev_prod_prop_t	devProdInfo;
1307836SJohn.Forte@Sun.COM 
1317836SJohn.Forte@Sun.COM 	char inqProductID[256];
1327836SJohn.Forte@Sun.COM 	char inqVendorID[256];
1337836SJohn.Forte@Sun.COM 
1347836SJohn.Forte@Sun.COM 
1357836SJohn.Forte@Sun.COM 	log(LOG_INFO, "MP_GetMultipathLusDevProd()", " - enter");
1367836SJohn.Forte@Sun.COM 
1377836SJohn.Forte@Sun.COM 	log(LOG_INFO, "MP_GetMultipathLusDevProd()",
138*12334SJiri.Svoboda@Sun.COM 	    "oid.objectSequenceNumber = %llx",
139*12334SJiri.Svoboda@Sun.COM 	    oid.objectSequenceNumber);
1407836SJohn.Forte@Sun.COM 
1417836SJohn.Forte@Sun.COM 	if (g_scsi_vhci_fd < 0) {
1427836SJohn.Forte@Sun.COM 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
1437836SJohn.Forte@Sun.COM 		    "invalid driver file handle");
1447836SJohn.Forte@Sun.COM 		log(LOG_INFO, "MP_GetMultipathLusDevProd",
145*12334SJiri.Svoboda@Sun.COM 		    " - error exit");
1467836SJohn.Forte@Sun.COM 		return (MP_STATUS_FAILED);
1477836SJohn.Forte@Sun.COM 	}
1487836SJohn.Forte@Sun.COM 
1497836SJohn.Forte@Sun.COM 	(void) memset(&mp_ioctl, 0, sizeof (mp_iocdata_t));
1507836SJohn.Forte@Sun.COM 	(void) memset(&devProdInfo, 0, sizeof (mp_dev_prod_prop_t));
1517836SJohn.Forte@Sun.COM 
1527836SJohn.Forte@Sun.COM 	mp_ioctl.mp_cmd  = MP_GET_DEV_PROD_PROP;
1537836SJohn.Forte@Sun.COM 	mp_ioctl.mp_ibuf = (caddr_t)&oid.objectSequenceNumber;
1547836SJohn.Forte@Sun.COM 	mp_ioctl.mp_ilen = sizeof (oid.objectSequenceNumber);
1557836SJohn.Forte@Sun.COM 	mp_ioctl.mp_obuf = (caddr_t)&devProdInfo;
1567836SJohn.Forte@Sun.COM 	mp_ioctl.mp_olen = sizeof (mp_dev_prod_prop_t);
1577836SJohn.Forte@Sun.COM 	mp_ioctl.mp_xfer = MP_XFER_READ;
1587836SJohn.Forte@Sun.COM 
1597836SJohn.Forte@Sun.COM 	ioctlStatus = ioctl(g_scsi_vhci_fd, MP_CMD, &mp_ioctl);
1607836SJohn.Forte@Sun.COM 
1617836SJohn.Forte@Sun.COM 	log(LOG_INFO, "MP_GetMultipathLusDevProd()",
162*12334SJiri.Svoboda@Sun.COM 	    " IOCTL call returned: %d", ioctlStatus);
1637836SJohn.Forte@Sun.COM 
1647836SJohn.Forte@Sun.COM 	if (ioctlStatus < 0) {
1657836SJohn.Forte@Sun.COM 		ioctlStatus = errno;
1667836SJohn.Forte@Sun.COM 	}
1677836SJohn.Forte@Sun.COM 
1687836SJohn.Forte@Sun.COM 	if (ioctlStatus != 0) {
1697836SJohn.Forte@Sun.COM 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
1707836SJohn.Forte@Sun.COM 		    "IOCTL call failed.  IOCTL error is: %d",
171*12334SJiri.Svoboda@Sun.COM 		    ioctlStatus);
1727836SJohn.Forte@Sun.COM 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
1737836SJohn.Forte@Sun.COM 		    "IOCTL call failed.  IOCTL error is: %s",
174*12334SJiri.Svoboda@Sun.COM 		    strerror(ioctlStatus));
1757836SJohn.Forte@Sun.COM 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
1767836SJohn.Forte@Sun.COM 		    "IOCTL call failed.  mp_ioctl.mp_errno: %x",
177*12334SJiri.Svoboda@Sun.COM 		    mp_ioctl.mp_errno);
1787836SJohn.Forte@Sun.COM 
1797836SJohn.Forte@Sun.COM 		if (ENOTSUP == ioctlStatus) {
1807836SJohn.Forte@Sun.COM 			mpStatus = MP_STATUS_UNSUPPORTED;
1817836SJohn.Forte@Sun.COM 		} else if (0 == mp_ioctl.mp_errno) {
1827836SJohn.Forte@Sun.COM 			mpStatus = MP_STATUS_FAILED;
1837836SJohn.Forte@Sun.COM 		} else {
1847836SJohn.Forte@Sun.COM 			mpStatus = getStatus4ErrorCode(mp_ioctl.mp_errno);
1857836SJohn.Forte@Sun.COM 		}
1867836SJohn.Forte@Sun.COM 
1877836SJohn.Forte@Sun.COM 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
188*12334SJiri.Svoboda@Sun.COM 		    " - error exit");
1897836SJohn.Forte@Sun.COM 
1907836SJohn.Forte@Sun.COM 		return (mpStatus);
1917836SJohn.Forte@Sun.COM 	}
1927836SJohn.Forte@Sun.COM 
193*12334SJiri.Svoboda@Sun.COM 	(void) strncpy(inqProductID, devProdInfo.prodInfo.product,
194*12334SJiri.Svoboda@Sun.COM 	    sizeof (devProdInfo.prodInfo.product));
1957836SJohn.Forte@Sun.COM 
196*12334SJiri.Svoboda@Sun.COM 	(void) strncpy(inqVendorID, devProdInfo.prodInfo.vendor,
197*12334SJiri.Svoboda@Sun.COM 	    sizeof (devProdInfo.prodInfo.vendor));
1987836SJohn.Forte@Sun.COM 
1997836SJohn.Forte@Sun.COM 	log(LOG_INFO, "MP_GetMultipathLusDevProd()",
200*12334SJiri.Svoboda@Sun.COM 	    " - inqProductID:  [%s]", inqProductID);
2017836SJohn.Forte@Sun.COM 	log(LOG_INFO, "MP_GetMultipathLusDevProd()",
202*12334SJiri.Svoboda@Sun.COM 	    " - inqVendorID:   [%s]", inqVendorID);
2037836SJohn.Forte@Sun.COM 
2047836SJohn.Forte@Sun.COM 	root_node = di_init("/", DINFOCACHE);
2057836SJohn.Forte@Sun.COM 	if (DI_NODE_NIL == root_node) {
2067836SJohn.Forte@Sun.COM 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
207*12334SJiri.Svoboda@Sun.COM 		    " - di_init() failed");
2087836SJohn.Forte@Sun.COM 
2097836SJohn.Forte@Sun.COM 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
210*12334SJiri.Svoboda@Sun.COM 		    " - error exit");
2117836SJohn.Forte@Sun.COM 
2127836SJohn.Forte@Sun.COM 		return (MP_STATUS_FAILED);
2137836SJohn.Forte@Sun.COM 	}
2147836SJohn.Forte@Sun.COM 
215*12334SJiri.Svoboda@Sun.COM 	numNodes = getOidList(root_node, NULL, inqProductID, inqVendorID);
2167836SJohn.Forte@Sun.COM 	if (numNodes < 0) {
2177836SJohn.Forte@Sun.COM 
218*12334SJiri.Svoboda@Sun.COM 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
219*12334SJiri.Svoboda@Sun.COM 		    " - unable to get OID list.");
2207836SJohn.Forte@Sun.COM 
221*12334SJiri.Svoboda@Sun.COM 		log(LOG_INFO, "MP_GetMultipathLusDevProd()", " - error exit");
2227836SJohn.Forte@Sun.COM 
2237836SJohn.Forte@Sun.COM 		di_fini(root_node);
2247836SJohn.Forte@Sun.COM 
2257836SJohn.Forte@Sun.COM 		return (MP_STATUS_FAILED);
2267836SJohn.Forte@Sun.COM 	}
2277836SJohn.Forte@Sun.COM 
2287836SJohn.Forte@Sun.COM 
2297836SJohn.Forte@Sun.COM 	if (0 == numNodes) {
2307836SJohn.Forte@Sun.COM 
2317836SJohn.Forte@Sun.COM 		*ppList = createOidList(1);
2327836SJohn.Forte@Sun.COM 		if (NULL == *ppList) {
2337836SJohn.Forte@Sun.COM 
234*12334SJiri.Svoboda@Sun.COM 			log(LOG_INFO, "MP_GetMultipathLusDevProd()",
235*12334SJiri.Svoboda@Sun.COM 			    " - unable to create OID list.");
2367836SJohn.Forte@Sun.COM 
2377836SJohn.Forte@Sun.COM 			log(LOG_INFO, "MP_GetMultipathLusDevProd()",
238*12334SJiri.Svoboda@Sun.COM 			    " - error exit");
2397836SJohn.Forte@Sun.COM 
2407836SJohn.Forte@Sun.COM 			di_fini(root_node);
2417836SJohn.Forte@Sun.COM 
2427836SJohn.Forte@Sun.COM 			return (MP_STATUS_INSUFFICIENT_MEMORY);
2437836SJohn.Forte@Sun.COM 		}
2447836SJohn.Forte@Sun.COM 
245*12334SJiri.Svoboda@Sun.COM 		(*ppList)->oids[0].objectType = MP_OBJECT_TYPE_MULTIPATH_LU;
246*12334SJiri.Svoboda@Sun.COM 		(*ppList)->oids[0].ownerId = g_pluginOwnerID;
2477836SJohn.Forte@Sun.COM 
2487836SJohn.Forte@Sun.COM 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
249*12334SJiri.Svoboda@Sun.COM 		    " - returning empty list.");
2507836SJohn.Forte@Sun.COM 
2517836SJohn.Forte@Sun.COM 		return (MP_STATUS_SUCCESS);
2527836SJohn.Forte@Sun.COM 	}
2537836SJohn.Forte@Sun.COM 
2547836SJohn.Forte@Sun.COM 	*ppList = createOidList(numNodes);
2557836SJohn.Forte@Sun.COM 	if (NULL == *ppList) {
2567836SJohn.Forte@Sun.COM 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
257*12334SJiri.Svoboda@Sun.COM 		    "no memory for *ppList");
2587836SJohn.Forte@Sun.COM 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
259*12334SJiri.Svoboda@Sun.COM 		    " - error exit");
2607836SJohn.Forte@Sun.COM 		return (MP_STATUS_INSUFFICIENT_MEMORY);
2617836SJohn.Forte@Sun.COM 	}
2627836SJohn.Forte@Sun.COM 
2637836SJohn.Forte@Sun.COM 	(*ppList)->oidCount = numNodes;
2647836SJohn.Forte@Sun.COM 
265*12334SJiri.Svoboda@Sun.COM 	numNodes = getOidList(root_node, *ppList, inqProductID, inqVendorID);
2667836SJohn.Forte@Sun.COM 
2677836SJohn.Forte@Sun.COM 	for (i = 0; i < (*ppList)->oidCount; i++) {
2687836SJohn.Forte@Sun.COM 
2697836SJohn.Forte@Sun.COM 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
270*12334SJiri.Svoboda@Sun.COM 		    "(*ppList)->oids[%d].objectType           = %d",
271*12334SJiri.Svoboda@Sun.COM 		    i, (*ppList)->oids[i].objectType);
2727836SJohn.Forte@Sun.COM 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
273*12334SJiri.Svoboda@Sun.COM 		    "(*ppList)->oids[%d].ownerId              = %d",
274*12334SJiri.Svoboda@Sun.COM 		    i, (*ppList)->oids[i].ownerId);
2757836SJohn.Forte@Sun.COM 		log(LOG_INFO, "MP_GetMultipathLusDevProd()",
276*12334SJiri.Svoboda@Sun.COM 		    "(*ppList)->oids[%d].objectSequenceNumber = %llx",
277*12334SJiri.Svoboda@Sun.COM 		    i, (*ppList)->oids[i].objectSequenceNumber);
2787836SJohn.Forte@Sun.COM 	}
2797836SJohn.Forte@Sun.COM 
2807836SJohn.Forte@Sun.COM 
2817836SJohn.Forte@Sun.COM 	di_fini(root_node);
2827836SJohn.Forte@Sun.COM 
2837836SJohn.Forte@Sun.COM 	log(LOG_INFO, "MP_GetMultipathLusDevProd()", " - exit");
2847836SJohn.Forte@Sun.COM 
2857836SJohn.Forte@Sun.COM 	return (MP_STATUS_SUCCESS);
2867836SJohn.Forte@Sun.COM 
2877836SJohn.Forte@Sun.COM }
288