1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26#include <string.h>
27#include <syslog.h>
28#include <errno.h>
29#include <unistd.h>
30#include <stropts.h>
31
32
33#include "mp_utils.h"
34
35
36MP_STATUS
37MP_GetTargetPortOidList(MP_OID oid, MP_OID_LIST **ppList)
38{
39	MP_STATUS mpStatus = MP_STATUS_SUCCESS;
40
41
42	log(LOG_INFO, "MP_GetTargetPortOidList()", " - enter");
43
44
45	mpStatus = getTargetPortOidList(oid, ppList);
46
47
48	log(LOG_INFO, "MP_GetTargetPortOidList()", " - exit");
49
50	return (mpStatus);
51}
52
53
54
55MP_STATUS
56getTargetPortOidList(MP_OID oid, MP_OID_LIST **ppList)
57{
58	mp_iocdata_t mp_ioctl;
59
60	uint64_t *objList = NULL;
61
62	int numOBJ = 0;
63	int i = 0;
64	int ioctlStatus = 0;
65
66	MP_STATUS mpStatus = MP_STATUS_SUCCESS;
67
68
69	log(LOG_INFO, "getTargetPortOidList()", " - enter");
70
71
72	log(LOG_INFO, "getTargetPortOidList()",
73		"oid.objectSequenceNumber = %llx",
74		oid.objectSequenceNumber);
75
76	if (g_scsi_vhci_fd < 0) {
77		log(LOG_INFO, "getTargetPortOidList()",
78		    "invalid driver file handle");
79		log(LOG_INFO, "getTargetPortOidList()", " - error exit");
80		return (MP_STATUS_FAILED);
81	}
82
83	objList = (uint64_t *)calloc(1, DEFAULT_BUFFER_SIZE_TPG);
84	if (NULL == objList) {
85		log(LOG_INFO, "getTargetPortOidList()",
86			"no memory for objList(1)");
87		log(LOG_INFO, "getTargetPortOidList()",
88			" - error exit");
89		return (MP_STATUS_INSUFFICIENT_MEMORY);
90	}
91
92	(void) memset(&mp_ioctl, 0, sizeof (mp_iocdata_t));
93
94	mp_ioctl.mp_cmd  = MP_GET_TARGET_PORT_LIST_FOR_TPG;
95	mp_ioctl.mp_ibuf = (caddr_t)&oid.objectSequenceNumber;
96	mp_ioctl.mp_ilen = sizeof (oid.objectSequenceNumber);
97	mp_ioctl.mp_obuf = (caddr_t)objList;
98	mp_ioctl.mp_olen = DEFAULT_BUFFER_SIZE_TPG;
99	mp_ioctl.mp_xfer = MP_XFER_READ;
100
101	log(LOG_INFO, "getTargetPortOidList()",
102		"mp_ioctl.mp_cmd (MP_GET_TARGET_PORT_LIST_FOR_TPG): %d",
103		mp_ioctl.mp_cmd);
104	log(LOG_INFO, "getTargetPortOidList()",
105		"mp_ioctl.mp_obuf: %x", mp_ioctl.mp_obuf);
106	log(LOG_INFO, "getTargetPortOidList()",
107		"mp_ioctl.mp_olen: %d", mp_ioctl.mp_olen);
108	log(LOG_INFO, "getTargetPortOidList()",
109		"mp_ioctl.mp_xfer: %d (MP_XFER_READ)",
110		mp_ioctl.mp_xfer);
111
112	ioctlStatus = ioctl(g_scsi_vhci_fd, MP_CMD, &mp_ioctl);
113	log(LOG_INFO, "getTargetPortOidList()",
114		"ioctl call returned ioctlStatus: %d",
115		ioctlStatus);
116
117	if (ioctlStatus < 0) {
118		ioctlStatus = errno;
119	}
120
121	if ((ioctlStatus != 0) && (MP_MORE_DATA != mp_ioctl.mp_errno)) {
122
123		log(LOG_INFO, "getTargetPortOidList()",
124		    "IOCTL call failed.  IOCTL error is: %d",
125			ioctlStatus);
126		log(LOG_INFO, "getTargetPortOidList()",
127		    "IOCTL call failed.  IOCTL error is: %s",
128			strerror(ioctlStatus));
129		log(LOG_INFO, "getTargetPortOidList()",
130		    "IOCTL call failed.  mp_ioctl.mp_errno: %x",
131			mp_ioctl.mp_errno);
132
133
134		free(objList);
135
136		if (ENOTSUP == ioctlStatus) {
137			mpStatus = MP_STATUS_UNSUPPORTED;
138		} else if (0 == mp_ioctl.mp_errno) {
139			mpStatus = MP_STATUS_FAILED;
140		} else {
141			mpStatus = getStatus4ErrorCode(mp_ioctl.mp_errno);
142		}
143
144		log(LOG_INFO, "getTargetPortOidList()",
145			" - error exit");
146
147		return (mpStatus);
148	}
149
150	log(LOG_INFO, "getTargetPortOidList()",
151		" - mp_ioctl.mp_alen : %d",
152		mp_ioctl.mp_alen);
153	log(LOG_INFO, "getTargetPortOidList()",
154		" - sizeof (uint64_t): %d",
155		sizeof (uint64_t));
156
157	numOBJ = mp_ioctl.mp_alen / sizeof (uint64_t);
158	log(LOG_INFO, "getTargetPortOidList()",
159	    "Length of list: %d", numOBJ);
160
161	if (numOBJ < 1) {
162		log(LOG_INFO, "getTargetPortOidList()",
163			"driver returned empty list.");
164
165		free(objList);
166
167		*ppList = createOidList(1);
168		if (NULL == *ppList) {
169			log(LOG_INFO,
170				"getTargetPortOidList()",
171				"no memory for MP_OID_LIST");
172			log(LOG_INFO,
173				"getTargetPortOidList()",
174				" - error exit");
175			return (MP_STATUS_INSUFFICIENT_MEMORY);
176		}
177
178		return (MP_STATUS_SUCCESS);
179	}
180
181	if (mp_ioctl.mp_alen > DEFAULT_BUFFER_SIZE_TPG) {
182
183		log(LOG_INFO, "getTargetPortOidList()",
184			"buffer size too small, need : %d",
185			mp_ioctl.mp_alen);
186
187		free(objList);
188
189		objList = (uint64_t *)calloc(1, numOBJ * sizeof (uint64_t));
190		if (NULL == objList) {
191			log(LOG_INFO, "getTargetPortOidList()",
192				"no memory for objList(2)");
193			log(LOG_INFO, "getTargetPortOidList()",
194				" - error exit");
195			return (MP_STATUS_INSUFFICIENT_MEMORY);
196		}
197
198		(void) memset(&mp_ioctl, 0, sizeof (mp_iocdata_t));
199
200		mp_ioctl.mp_cmd  = MP_GET_TARGET_PORT_LIST_FOR_TPG;
201		mp_ioctl.mp_ibuf = (caddr_t)&oid.objectSequenceNumber;
202		mp_ioctl.mp_ilen = sizeof (oid.objectSequenceNumber);
203		mp_ioctl.mp_obuf = (caddr_t)objList;
204		mp_ioctl.mp_olen = numOBJ * sizeof (uint64_t);
205		mp_ioctl.mp_xfer = MP_XFER_READ;
206
207		log(LOG_INFO, "getTargetPortOidList()",
208			"mp_ioctl.mp_cmd (MP_GET_TARGET_PORT_LIST_FOR_TPG): %d",
209			mp_ioctl.mp_cmd);
210		log(LOG_INFO, "getTargetPortOidList()",
211			"mp_ioctl.mp_obuf: %x", mp_ioctl.mp_obuf);
212		log(LOG_INFO, "getTargetPortOidList()",
213			"mp_ioctl.mp_olen: %d", mp_ioctl.mp_olen);
214		log(LOG_INFO, "getTargetPortOidList()",
215			"mp_ioctl.mp_xfer: %d (MP_XFER_READ)",
216			mp_ioctl.mp_xfer);
217
218		ioctlStatus = ioctl(g_scsi_vhci_fd, MP_CMD, &mp_ioctl);
219		log(LOG_INFO, "getTargetPortOidList()",
220			"ioctl call returned ioctlStatus: %d",
221			ioctlStatus);
222
223		if (ioctlStatus < 0) {
224			ioctlStatus = errno;
225		}
226
227		if (ioctlStatus != 0) {
228
229			log(LOG_INFO, "getTargetPortOidList()",
230				"IOCTL call failed.  IOCTL error is: %d",
231				ioctlStatus);
232			log(LOG_INFO, "getTargetPortOidList()",
233				"IOCTL call failed.  IOCTL error is: %s",
234				strerror(ioctlStatus));
235			log(LOG_INFO, "getTargetPortOidList()",
236				"IOCTL call failed.  mp_ioctl.mp_errno: %x",
237				mp_ioctl.mp_errno);
238
239
240			free(objList);
241
242			if (ENOTSUP == ioctlStatus) {
243				mpStatus = MP_STATUS_UNSUPPORTED;
244			} else if (0 == mp_ioctl.mp_errno) {
245				mpStatus = MP_STATUS_FAILED;
246			} else {
247				mpStatus =
248					getStatus4ErrorCode(mp_ioctl.mp_errno);
249			}
250
251			log(LOG_INFO, "getTargetPortOidList()",
252				" - error exit");
253
254			return (mpStatus);
255		}
256	}
257
258
259	*ppList = createOidList(numOBJ);
260	if (NULL == *ppList) {
261		log(LOG_INFO, "getTargetPortOidList()",
262			"no memory for *ppList");
263		free(objList);
264		log(LOG_INFO, "getTargetPortOidList()",
265			" - error exit");
266		return (MP_STATUS_INSUFFICIENT_MEMORY);
267	}
268
269	(*ppList)->oidCount = numOBJ;
270
271	log(LOG_INFO, "getTargetPortOidList()",
272		"(*ppList)->oidCount = %d",
273		(*ppList)->oidCount);
274
275	for (i = 0; i < numOBJ; i++) {
276		(*ppList)->oids[i].objectType = MP_OBJECT_TYPE_TARGET_PORT;
277		(*ppList)->oids[i].ownerId = g_pluginOwnerID;
278		(*ppList)->oids[i].objectSequenceNumber = objList[i];
279
280		log(LOG_INFO, "getTargetPortOidList()",
281			"(*ppList)->oids[%d].objectType           = %d",
282			i, (*ppList)->oids[i].objectType);
283		log(LOG_INFO, "getTargetPortOidList()",
284			"(*ppList)->oids[%d].ownerId              = %d",
285			i, (*ppList)->oids[i].ownerId);
286		log(LOG_INFO, "getTargetPortOidList()",
287			"(*ppList)->oids[%d].objectSequenceNumber = %llx",
288			i, (*ppList)->oids[i].objectSequenceNumber);
289	}
290
291	free(objList);
292
293
294	log(LOG_INFO, "getTargetPortOidList()", " - exit");
295
296	return (MP_STATUS_SUCCESS);
297}
298