1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate /*
30*0Sstevel@tonic-gate  * s_generic.c :
31*0Sstevel@tonic-gate  *      This file contains generic SCSI related functions for scsi plug-in
32*0Sstevel@tonic-gate  * 	for libsm.so.
33*0Sstevel@tonic-gate  */
34*0Sstevel@tonic-gate 
35*0Sstevel@tonic-gate 
36*0Sstevel@tonic-gate #include <sys/types.h>
37*0Sstevel@tonic-gate #include <sys/stat.h>
38*0Sstevel@tonic-gate #include <sys/ioctl.h>
39*0Sstevel@tonic-gate #include <unistd.h>
40*0Sstevel@tonic-gate #include <sys/shm.h>
41*0Sstevel@tonic-gate #include <sys/mman.h>
42*0Sstevel@tonic-gate #include <sys/smedia.h>
43*0Sstevel@tonic-gate #include "../../../library/inc/rmedia.h"
44*0Sstevel@tonic-gate #include <smserver.h>
45*0Sstevel@tonic-gate #include <dirent.h>
46*0Sstevel@tonic-gate #include <fcntl.h>
47*0Sstevel@tonic-gate #include <sys/scsi/scsi.h>
48*0Sstevel@tonic-gate #include <strings.h>
49*0Sstevel@tonic-gate #include "../../../library/common/l_defines.h"
50*0Sstevel@tonic-gate 
51*0Sstevel@tonic-gate 
52*0Sstevel@tonic-gate static int32_t remap_shared_buf(rmedia_handle_t *, size_t, char *);
53*0Sstevel@tonic-gate 
54*0Sstevel@tonic-gate #define	W_E_MASK 0x80
55*0Sstevel@tonic-gate #define	BUF_SIZE_MULTIPLE	0x2000
56*0Sstevel@tonic-gate 
57*0Sstevel@tonic-gate int32_t
_m_get_media_info(rmedia_handle_t * handle,void * ip)58*0Sstevel@tonic-gate _m_get_media_info(rmedia_handle_t *handle, void *ip)
59*0Sstevel@tonic-gate {
60*0Sstevel@tonic-gate 	smmedium_prop_t *medinfo = ip;
61*0Sstevel@tonic-gate 	int32_t ret_val;
62*0Sstevel@tonic-gate 	smedia_reqget_medium_property_t	reqget_medium_property;
63*0Sstevel@tonic-gate 	smedia_retget_medium_property_t	*retget_medium_property;
64*0Sstevel@tonic-gate 	smedia_reterror_t	*reterror;
65*0Sstevel@tonic-gate 	door_arg_t	door_args;
66*0Sstevel@tonic-gate 	char	rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
67*0Sstevel@tonic-gate 
68*0Sstevel@tonic-gate 	DPRINTF("get_media_info called.\n");
69*0Sstevel@tonic-gate 	/* Check for valid handle */
70*0Sstevel@tonic-gate 	if (handle == NULL) {
71*0Sstevel@tonic-gate 		DPRINTF("Null Handle\n");
72*0Sstevel@tonic-gate 		errno = EINVAL;
73*0Sstevel@tonic-gate 		return (-1);
74*0Sstevel@tonic-gate 	}
75*0Sstevel@tonic-gate 	if (handle->sm_signature != (int32_t)LIBSMEDIA_SIGNATURE) {
76*0Sstevel@tonic-gate 		DPRINTF("Invalid signature in handle.\n");
77*0Sstevel@tonic-gate 		DPRINTF2(
78*0Sstevel@tonic-gate 		"Signature expected=0x%x, found=0x%x\n",
79*0Sstevel@tonic-gate 			LIBSMEDIA_SIGNATURE, handle->sm_signature);
80*0Sstevel@tonic-gate 		DPRINTF1("fd=%d\n", handle->sm_fd);
81*0Sstevel@tonic-gate 		errno = EINVAL;
82*0Sstevel@tonic-gate 		return (-1);
83*0Sstevel@tonic-gate 	}
84*0Sstevel@tonic-gate 	(void) memset((void *) medinfo, 0, sizeof (smmedium_prop_t));
85*0Sstevel@tonic-gate 
86*0Sstevel@tonic-gate 	reqget_medium_property.cnum = SMEDIA_CNUM_GET_MEDIUM_PROPERTY;
87*0Sstevel@tonic-gate 	door_args.data_ptr = (char *)&reqget_medium_property;
88*0Sstevel@tonic-gate 	door_args.data_size = sizeof (smedia_services_t);
89*0Sstevel@tonic-gate 	door_args.desc_ptr = NULL;
90*0Sstevel@tonic-gate 	door_args.desc_num = 0;
91*0Sstevel@tonic-gate 	door_args.rbuf = rbuf;
92*0Sstevel@tonic-gate 	door_args.rsize = sizeof (rbuf);
93*0Sstevel@tonic-gate 
94*0Sstevel@tonic-gate 	ret_val = door_call(handle->sm_door, &door_args);
95*0Sstevel@tonic-gate 	if (ret_val < 0) {
96*0Sstevel@tonic-gate 		perror("door_call");
97*0Sstevel@tonic-gate 		return (-1);
98*0Sstevel@tonic-gate 	}
99*0Sstevel@tonic-gate 	retget_medium_property =
100*0Sstevel@tonic-gate 		(smedia_retget_medium_property_t *)((void *)door_args.data_ptr);
101*0Sstevel@tonic-gate 	reterror = (smedia_reterror_t *)((void *)door_args.data_ptr);
102*0Sstevel@tonic-gate 	if (reterror->cnum == SMEDIA_CNUM_ERROR) {
103*0Sstevel@tonic-gate 		DPRINTF1(
104*0Sstevel@tonic-gate 	"Error in get_medium_property. errnum = 0x%x \n", reterror->errnum);
105*0Sstevel@tonic-gate 		errno = reterror->errnum;
106*0Sstevel@tonic-gate 		return (-1);
107*0Sstevel@tonic-gate 	}
108*0Sstevel@tonic-gate 
109*0Sstevel@tonic-gate 	*medinfo = retget_medium_property->smprop;
110*0Sstevel@tonic-gate 
111*0Sstevel@tonic-gate 	return (0);
112*0Sstevel@tonic-gate }
113*0Sstevel@tonic-gate 
114*0Sstevel@tonic-gate int32_t
_m_get_device_info(rmedia_handle_t * handle,void * ip)115*0Sstevel@tonic-gate _m_get_device_info(rmedia_handle_t *handle, void *ip)
116*0Sstevel@tonic-gate {
117*0Sstevel@tonic-gate 	struct smdevice_info *dev_info = ip;
118*0Sstevel@tonic-gate 	int32_t	ret_val;
119*0Sstevel@tonic-gate 	smedia_reqget_device_info_t	reqget_device_info;
120*0Sstevel@tonic-gate 	smedia_retget_device_info_t	*retget_device_info;
121*0Sstevel@tonic-gate 	smedia_reterror_t	*reterror;
122*0Sstevel@tonic-gate 	door_arg_t	door_args;
123*0Sstevel@tonic-gate 	char	rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
124*0Sstevel@tonic-gate 	char *vendor_name, *product_name, *fw_version;
125*0Sstevel@tonic-gate 
126*0Sstevel@tonic-gate 	/* Check for valid handle */
127*0Sstevel@tonic-gate 	if (handle == NULL) {
128*0Sstevel@tonic-gate 		DPRINTF("Null Handle\n");
129*0Sstevel@tonic-gate 		errno = EINVAL;
130*0Sstevel@tonic-gate 		return (-1);
131*0Sstevel@tonic-gate 	}
132*0Sstevel@tonic-gate 	if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
133*0Sstevel@tonic-gate 		DPRINTF("Invalid signature in handle.\n");
134*0Sstevel@tonic-gate 		errno = EINVAL;
135*0Sstevel@tonic-gate 		return (-1);
136*0Sstevel@tonic-gate 	}
137*0Sstevel@tonic-gate 
138*0Sstevel@tonic-gate 	vendor_name = (char *)malloc(9);
139*0Sstevel@tonic-gate 	if (vendor_name == NULL) {
140*0Sstevel@tonic-gate 		if (!errno)
141*0Sstevel@tonic-gate 			errno = ENOMEM;
142*0Sstevel@tonic-gate 		return (-1);
143*0Sstevel@tonic-gate 	}
144*0Sstevel@tonic-gate 	product_name = (char *)malloc(17);
145*0Sstevel@tonic-gate 	if (product_name == NULL) {
146*0Sstevel@tonic-gate 		free(vendor_name);
147*0Sstevel@tonic-gate 		if (!errno)
148*0Sstevel@tonic-gate 			errno = ENOMEM;
149*0Sstevel@tonic-gate 		return (-1);
150*0Sstevel@tonic-gate 	}
151*0Sstevel@tonic-gate 
152*0Sstevel@tonic-gate 	fw_version = (char *)malloc(18);
153*0Sstevel@tonic-gate 	if (fw_version == NULL) {
154*0Sstevel@tonic-gate 		free(vendor_name);
155*0Sstevel@tonic-gate 		free(product_name);
156*0Sstevel@tonic-gate 		if (!errno)
157*0Sstevel@tonic-gate 			errno = ENOMEM;
158*0Sstevel@tonic-gate 		return (-1);
159*0Sstevel@tonic-gate 	}
160*0Sstevel@tonic-gate 	reqget_device_info.cnum = SMEDIA_CNUM_GET_DEVICE_INFO;
161*0Sstevel@tonic-gate 	door_args.data_ptr = (char *)&reqget_device_info;
162*0Sstevel@tonic-gate 	door_args.data_size = sizeof (smedia_services_t);
163*0Sstevel@tonic-gate 	door_args.desc_ptr = NULL;
164*0Sstevel@tonic-gate 	door_args.desc_num = 0;
165*0Sstevel@tonic-gate 	door_args.rbuf = rbuf;
166*0Sstevel@tonic-gate 	door_args.rsize = sizeof (rbuf);
167*0Sstevel@tonic-gate 
168*0Sstevel@tonic-gate 	ret_val = door_call(handle->sm_door, &door_args);
169*0Sstevel@tonic-gate 	if (ret_val < 0) {
170*0Sstevel@tonic-gate 		perror("door_call");
171*0Sstevel@tonic-gate 		free(vendor_name);
172*0Sstevel@tonic-gate 		free(product_name);
173*0Sstevel@tonic-gate 		free(fw_version);
174*0Sstevel@tonic-gate 		return (-1);
175*0Sstevel@tonic-gate 	}
176*0Sstevel@tonic-gate 	retget_device_info = (smedia_retget_device_info_t *)
177*0Sstevel@tonic-gate 		((void *)door_args.data_ptr);
178*0Sstevel@tonic-gate 	reterror = (smedia_reterror_t *)((void *)door_args.data_ptr);
179*0Sstevel@tonic-gate 	if (reterror->cnum == SMEDIA_CNUM_ERROR) {
180*0Sstevel@tonic-gate 		DPRINTF1(
181*0Sstevel@tonic-gate 	"Error in get_device_info. errnum = 0x%x \n", reterror->errnum);
182*0Sstevel@tonic-gate 		errno = reterror->errnum;
183*0Sstevel@tonic-gate 		free(vendor_name);
184*0Sstevel@tonic-gate 		free(product_name);
185*0Sstevel@tonic-gate 		free(fw_version);
186*0Sstevel@tonic-gate 		return (-1);
187*0Sstevel@tonic-gate 	}
188*0Sstevel@tonic-gate 
189*0Sstevel@tonic-gate 	dev_info->sm_vendor_name = vendor_name;
190*0Sstevel@tonic-gate 	dev_info->sm_product_name = product_name;
191*0Sstevel@tonic-gate 	dev_info->sm_firmware_version = fw_version;
192*0Sstevel@tonic-gate 
193*0Sstevel@tonic-gate 
194*0Sstevel@tonic-gate 	(void) strlcpy(dev_info->sm_vendor_name,
195*0Sstevel@tonic-gate 		retget_device_info->sm_vendor_name, 8);
196*0Sstevel@tonic-gate 	dev_info->sm_vendor_name[8] = 0;
197*0Sstevel@tonic-gate 	(void) strlcpy(dev_info->sm_product_name,
198*0Sstevel@tonic-gate 		retget_device_info->sm_product_name, 16);
199*0Sstevel@tonic-gate 	dev_info->sm_product_name[16] = 0;
200*0Sstevel@tonic-gate 	(void) strlcpy(dev_info->sm_firmware_version,
201*0Sstevel@tonic-gate 		retget_device_info->sm_firmware_version, 17);
202*0Sstevel@tonic-gate 	dev_info->sm_firmware_version[17] = 0;
203*0Sstevel@tonic-gate 
204*0Sstevel@tonic-gate 	dev_info->sm_interface_type = retget_device_info->sm_interface_type;
205*0Sstevel@tonic-gate 
206*0Sstevel@tonic-gate #ifdef DEBUG
207*0Sstevel@tonic-gate 	DPRINTF1("Vendor name = %s\n", dev_info->sm_vendor_name);
208*0Sstevel@tonic-gate 	DPRINTF1("product name = %s\n", dev_info->sm_product_name);
209*0Sstevel@tonic-gate 	DPRINTF1("Firmware revision = %s\n", dev_info->sm_firmware_version);
210*0Sstevel@tonic-gate #endif /* DEBUG */
211*0Sstevel@tonic-gate 
212*0Sstevel@tonic-gate 	return (0);
213*0Sstevel@tonic-gate }
214*0Sstevel@tonic-gate 
215*0Sstevel@tonic-gate int32_t
_m_free_device_info(rmedia_handle_t * handle,void * ip)216*0Sstevel@tonic-gate _m_free_device_info(rmedia_handle_t *handle, void *ip)
217*0Sstevel@tonic-gate {
218*0Sstevel@tonic-gate 	struct smdevice_info *dev_info = ip;
219*0Sstevel@tonic-gate 
220*0Sstevel@tonic-gate 	/* Check for valid handle */
221*0Sstevel@tonic-gate 	if (handle == NULL) {
222*0Sstevel@tonic-gate 		DPRINTF("Null Handle\n");
223*0Sstevel@tonic-gate 		errno = EINVAL;
224*0Sstevel@tonic-gate 		return (-1);
225*0Sstevel@tonic-gate 	}
226*0Sstevel@tonic-gate 	if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
227*0Sstevel@tonic-gate 		DPRINTF("Invalid signature in handle.\n");
228*0Sstevel@tonic-gate 		errno = EINVAL;
229*0Sstevel@tonic-gate 		return (-1);
230*0Sstevel@tonic-gate 	}
231*0Sstevel@tonic-gate 
232*0Sstevel@tonic-gate 	free(dev_info->sm_vendor_name);
233*0Sstevel@tonic-gate 	free(dev_info->sm_product_name);
234*0Sstevel@tonic-gate 	free(dev_info->sm_firmware_version);
235*0Sstevel@tonic-gate 	return (0);
236*0Sstevel@tonic-gate }
237*0Sstevel@tonic-gate 
238*0Sstevel@tonic-gate int32_t
_m_raw_write(rmedia_handle_t * handle,void * i_p)239*0Sstevel@tonic-gate _m_raw_write(rmedia_handle_t *handle, void *i_p)
240*0Sstevel@tonic-gate {
241*0Sstevel@tonic-gate 	int32_t	ret_val;
242*0Sstevel@tonic-gate 	struct raw_params *r_p = (struct raw_params *)i_p;
243*0Sstevel@tonic-gate 	smedia_reqraw_write_t	reqraw_write;
244*0Sstevel@tonic-gate 	smedia_retraw_write_t	*retraw_write;
245*0Sstevel@tonic-gate 	smedia_reterror_t	*reterror;
246*0Sstevel@tonic-gate 	door_arg_t	door_args;
247*0Sstevel@tonic-gate 	char	rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
248*0Sstevel@tonic-gate 
249*0Sstevel@tonic-gate 	/* Check for valid handle */
250*0Sstevel@tonic-gate 	if (handle == NULL) {
251*0Sstevel@tonic-gate 		DPRINTF("Null Handle\n");
252*0Sstevel@tonic-gate 		errno = EINVAL;
253*0Sstevel@tonic-gate 		return (-1);
254*0Sstevel@tonic-gate 	}
255*0Sstevel@tonic-gate 	if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
256*0Sstevel@tonic-gate 		DPRINTF("Invalid signature in handle.\n");
257*0Sstevel@tonic-gate 		errno = EINVAL;
258*0Sstevel@tonic-gate 		return (-1);
259*0Sstevel@tonic-gate 	}
260*0Sstevel@tonic-gate 	(void) mutex_lock(&handle->sm_bufmutex);
261*0Sstevel@tonic-gate 	ret_val = remap_shared_buf(handle, r_p->size, r_p->buffer);
262*0Sstevel@tonic-gate 	if (ret_val != 0) goto error;
263*0Sstevel@tonic-gate 	reqraw_write.cnum = SMEDIA_CNUM_RAW_WRITE;
264*0Sstevel@tonic-gate 	reqraw_write.blockno = r_p->offset;
265*0Sstevel@tonic-gate 	reqraw_write.nbytes = r_p->size;
266*0Sstevel@tonic-gate 	bcopy(r_p->buffer, handle->sm_buf, r_p->size);
267*0Sstevel@tonic-gate 	door_args.data_ptr = (char *)&reqraw_write;
268*0Sstevel@tonic-gate 	door_args.data_size = sizeof (reqraw_write);
269*0Sstevel@tonic-gate 	door_args.desc_ptr = NULL;
270*0Sstevel@tonic-gate 	door_args.desc_num = 0;
271*0Sstevel@tonic-gate 	door_args.rbuf = rbuf;
272*0Sstevel@tonic-gate 	door_args.rsize = sizeof (rbuf);
273*0Sstevel@tonic-gate 
274*0Sstevel@tonic-gate 	ret_val = door_call(handle->sm_door, &door_args);
275*0Sstevel@tonic-gate 	if (ret_val < 0) {
276*0Sstevel@tonic-gate 		perror("door_call");
277*0Sstevel@tonic-gate 		goto error;
278*0Sstevel@tonic-gate 	}
279*0Sstevel@tonic-gate 	retraw_write = (smedia_retraw_write_t *)((void *)door_args.data_ptr);
280*0Sstevel@tonic-gate 	reterror = (smedia_reterror_t *)((void *)door_args.data_ptr);
281*0Sstevel@tonic-gate 	if (reterror->cnum == SMEDIA_CNUM_ERROR) {
282*0Sstevel@tonic-gate 		DPRINTF3(
283*0Sstevel@tonic-gate 	"Error in raw write. errnum = 0x%x blk_num = 0x%x(%d)\n",
284*0Sstevel@tonic-gate 		reterror->errnum, r_p->offset, r_p->offset);
285*0Sstevel@tonic-gate 		errno = reterror->errnum;
286*0Sstevel@tonic-gate 		goto error;
287*0Sstevel@tonic-gate 	}
288*0Sstevel@tonic-gate 	(void) mutex_unlock(&handle->sm_bufmutex);
289*0Sstevel@tonic-gate 	return (retraw_write->nbytes);
290*0Sstevel@tonic-gate 
291*0Sstevel@tonic-gate error:
292*0Sstevel@tonic-gate 	(void) mutex_unlock(&handle->sm_bufmutex);
293*0Sstevel@tonic-gate 	return (-1);
294*0Sstevel@tonic-gate }
295*0Sstevel@tonic-gate 
296*0Sstevel@tonic-gate size_t
_m_raw_read(rmedia_handle_t * handle,void * i_p)297*0Sstevel@tonic-gate _m_raw_read(rmedia_handle_t *handle, void *i_p)
298*0Sstevel@tonic-gate {
299*0Sstevel@tonic-gate 	struct raw_params *r_p = (struct raw_params *)i_p;
300*0Sstevel@tonic-gate 	int32_t	ret_val, bytes_read;
301*0Sstevel@tonic-gate 	smedia_reqraw_read_t	reqraw_read;
302*0Sstevel@tonic-gate 	smedia_retraw_read_t	*retraw_read;
303*0Sstevel@tonic-gate 	smedia_reterror_t	*reterror;
304*0Sstevel@tonic-gate 	door_arg_t	door_args;
305*0Sstevel@tonic-gate 	char	rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
306*0Sstevel@tonic-gate 
307*0Sstevel@tonic-gate 	/* Check for valid handle */
308*0Sstevel@tonic-gate 	if (handle == NULL) {
309*0Sstevel@tonic-gate 		DPRINTF("Null Handle\n");
310*0Sstevel@tonic-gate 		errno = EINVAL;
311*0Sstevel@tonic-gate 		return (size_t)(-1);
312*0Sstevel@tonic-gate 	}
313*0Sstevel@tonic-gate 	if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
314*0Sstevel@tonic-gate 		DPRINTF("Invalid signature in handle.\n");
315*0Sstevel@tonic-gate 		return (size_t)(-1);
316*0Sstevel@tonic-gate 	}
317*0Sstevel@tonic-gate 	/*
318*0Sstevel@tonic-gate 	 * Check if another thread is doing an IO with same handle.
319*0Sstevel@tonic-gate 	 * In that case ww block here.
320*0Sstevel@tonic-gate 	 */
321*0Sstevel@tonic-gate 	(void) mutex_lock(&handle->sm_bufmutex);
322*0Sstevel@tonic-gate 	ret_val = remap_shared_buf(handle, r_p->size, r_p->buffer);
323*0Sstevel@tonic-gate 	if (ret_val != 0) goto error;
324*0Sstevel@tonic-gate 
325*0Sstevel@tonic-gate 	reqraw_read.cnum = SMEDIA_CNUM_RAW_READ;
326*0Sstevel@tonic-gate 	reqraw_read.blockno = r_p->offset;
327*0Sstevel@tonic-gate 	reqraw_read.nbytes = r_p->size;
328*0Sstevel@tonic-gate 	door_args.data_ptr = (char *)&reqraw_read;
329*0Sstevel@tonic-gate 	door_args.data_size = sizeof (smedia_services_t);
330*0Sstevel@tonic-gate 	door_args.desc_ptr = NULL;
331*0Sstevel@tonic-gate 	door_args.desc_num = 0;
332*0Sstevel@tonic-gate 	door_args.rbuf = rbuf;
333*0Sstevel@tonic-gate 	door_args.rsize = sizeof (rbuf);
334*0Sstevel@tonic-gate 
335*0Sstevel@tonic-gate 	ret_val = door_call(handle->sm_door, &door_args);
336*0Sstevel@tonic-gate 	if (ret_val < 0) {
337*0Sstevel@tonic-gate 		perror("door_call");
338*0Sstevel@tonic-gate 		goto error;
339*0Sstevel@tonic-gate 	}
340*0Sstevel@tonic-gate 	retraw_read = (smedia_retraw_read_t *)((void *)door_args.data_ptr);
341*0Sstevel@tonic-gate 	reterror = (smedia_reterror_t *)((void *)door_args.data_ptr);
342*0Sstevel@tonic-gate 	if (reterror->cnum == SMEDIA_CNUM_ERROR) {
343*0Sstevel@tonic-gate 		/*
344*0Sstevel@tonic-gate 		 * free(rbuf);
345*0Sstevel@tonic-gate 		 */
346*0Sstevel@tonic-gate 		DPRINTF3(
347*0Sstevel@tonic-gate 	"Error in raw read. errnum = 0x%x blk_num = 0x%x(%d)\n",
348*0Sstevel@tonic-gate 		reterror->errnum, r_p->offset, r_p->offset);
349*0Sstevel@tonic-gate 		errno = reterror->errnum;
350*0Sstevel@tonic-gate 		goto error;
351*0Sstevel@tonic-gate 	}
352*0Sstevel@tonic-gate 	(void) memcpy(r_p->buffer, handle->sm_buf, retraw_read->nbytes);
353*0Sstevel@tonic-gate 	bytes_read = retraw_read->nbytes;
354*0Sstevel@tonic-gate 	(void) mutex_unlock(&handle->sm_bufmutex);
355*0Sstevel@tonic-gate 	return (bytes_read);
356*0Sstevel@tonic-gate 
357*0Sstevel@tonic-gate error:
358*0Sstevel@tonic-gate 	(void) mutex_unlock(&handle->sm_bufmutex);
359*0Sstevel@tonic-gate 	return (size_t)(-1);
360*0Sstevel@tonic-gate 
361*0Sstevel@tonic-gate }
362*0Sstevel@tonic-gate 
363*0Sstevel@tonic-gate size_t
_m_media_format(rmedia_handle_t * handle,void * ip)364*0Sstevel@tonic-gate _m_media_format(rmedia_handle_t *handle, void *ip)
365*0Sstevel@tonic-gate {
366*0Sstevel@tonic-gate 	int32_t ret_val;
367*0Sstevel@tonic-gate 	struct format_flags *ffl = (struct format_flags *)ip;
368*0Sstevel@tonic-gate 	smedia_reqformat_t	reqformat;
369*0Sstevel@tonic-gate 	smedia_retformat_t	*retformat;
370*0Sstevel@tonic-gate 	smedia_reterror_t	*reterror;
371*0Sstevel@tonic-gate 	door_arg_t	door_args;
372*0Sstevel@tonic-gate 	char	rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
373*0Sstevel@tonic-gate 
374*0Sstevel@tonic-gate 	/* Check for valid handle */
375*0Sstevel@tonic-gate 	if (handle == NULL) {
376*0Sstevel@tonic-gate 		DPRINTF("Null Handle\n");
377*0Sstevel@tonic-gate 		errno = EINVAL;
378*0Sstevel@tonic-gate 		return (size_t)(-1);
379*0Sstevel@tonic-gate 	}
380*0Sstevel@tonic-gate 	if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
381*0Sstevel@tonic-gate 		DPRINTF("Invalid signature in handle.\n");
382*0Sstevel@tonic-gate 		errno = EINVAL;
383*0Sstevel@tonic-gate 		return (size_t)(-1);
384*0Sstevel@tonic-gate 	}
385*0Sstevel@tonic-gate 	reqformat.cnum = SMEDIA_CNUM_FORMAT;
386*0Sstevel@tonic-gate 	reqformat.flavor = ffl->flavor;
387*0Sstevel@tonic-gate 	reqformat.mode = ffl->mode;
388*0Sstevel@tonic-gate 	door_args.data_ptr = (char *)&reqformat;
389*0Sstevel@tonic-gate 	door_args.data_size = sizeof (smedia_services_t);
390*0Sstevel@tonic-gate 	door_args.desc_ptr = NULL;
391*0Sstevel@tonic-gate 	door_args.desc_num = 0;
392*0Sstevel@tonic-gate 	door_args.rbuf = rbuf;
393*0Sstevel@tonic-gate 	door_args.rsize = sizeof (rbuf);
394*0Sstevel@tonic-gate 
395*0Sstevel@tonic-gate 	ret_val = door_call(handle->sm_door, &door_args);
396*0Sstevel@tonic-gate 	if (ret_val < 0) {
397*0Sstevel@tonic-gate 		perror("door_call");
398*0Sstevel@tonic-gate 		return (size_t)(-1);
399*0Sstevel@tonic-gate 	}
400*0Sstevel@tonic-gate 	retformat = (smedia_retformat_t *)((void *)door_args.data_ptr);
401*0Sstevel@tonic-gate #ifdef lint
402*0Sstevel@tonic-gate 	retformat = retformat;
403*0Sstevel@tonic-gate #endif
404*0Sstevel@tonic-gate 	reterror = (smedia_reterror_t *)((void *)door_args.data_ptr);
405*0Sstevel@tonic-gate 	if (reterror->cnum == SMEDIA_CNUM_ERROR) {
406*0Sstevel@tonic-gate 		DPRINTF1("Error in format. errnum = 0x%x \n", reterror->errnum);
407*0Sstevel@tonic-gate 		errno = reterror->errnum;
408*0Sstevel@tonic-gate 		return (size_t)(-1);
409*0Sstevel@tonic-gate 	}
410*0Sstevel@tonic-gate 	return (0);
411*0Sstevel@tonic-gate }
412*0Sstevel@tonic-gate 
413*0Sstevel@tonic-gate int32_t
_m_get_media_status(rmedia_handle_t * handle,void * ip)414*0Sstevel@tonic-gate _m_get_media_status(rmedia_handle_t *handle, void *ip)
415*0Sstevel@tonic-gate {
416*0Sstevel@tonic-gate 	smwp_state_t	*wp = ip;
417*0Sstevel@tonic-gate 	int32_t ret_val;
418*0Sstevel@tonic-gate 	smedia_reqget_protection_status_t	reqget_protection_status;
419*0Sstevel@tonic-gate 	smedia_retget_protection_status_t	*retget_protection_status;
420*0Sstevel@tonic-gate 	smedia_reterror_t	*reterror;
421*0Sstevel@tonic-gate 	door_arg_t	door_args;
422*0Sstevel@tonic-gate 	char	rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
423*0Sstevel@tonic-gate 
424*0Sstevel@tonic-gate 	/* Check for valid handle */
425*0Sstevel@tonic-gate 	if (handle == NULL) {
426*0Sstevel@tonic-gate 		DPRINTF("Null Handle\n");
427*0Sstevel@tonic-gate 		errno = EINVAL;
428*0Sstevel@tonic-gate 		return (-1);
429*0Sstevel@tonic-gate 	}
430*0Sstevel@tonic-gate 	if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
431*0Sstevel@tonic-gate 		DPRINTF("Invalid signature in handle.\n");
432*0Sstevel@tonic-gate 		errno = EINVAL;
433*0Sstevel@tonic-gate 		return (-1);
434*0Sstevel@tonic-gate 	}
435*0Sstevel@tonic-gate 	reqget_protection_status.cnum = SMEDIA_CNUM_GET_PROTECTION_STATUS;
436*0Sstevel@tonic-gate 	door_args.data_ptr = (char *)&reqget_protection_status;
437*0Sstevel@tonic-gate 	door_args.data_size = sizeof (smedia_services_t);
438*0Sstevel@tonic-gate 	door_args.desc_ptr = NULL;
439*0Sstevel@tonic-gate 	door_args.desc_num = 0;
440*0Sstevel@tonic-gate 	door_args.rbuf = rbuf;
441*0Sstevel@tonic-gate 	door_args.rsize = sizeof (rbuf);
442*0Sstevel@tonic-gate 
443*0Sstevel@tonic-gate 	ret_val = door_call(handle->sm_door, &door_args);
444*0Sstevel@tonic-gate 	if (ret_val < 0) {
445*0Sstevel@tonic-gate 		perror("door_call");
446*0Sstevel@tonic-gate 		return (-1);
447*0Sstevel@tonic-gate 	}
448*0Sstevel@tonic-gate 	retget_protection_status =
449*0Sstevel@tonic-gate 		(smedia_retget_protection_status_t *)
450*0Sstevel@tonic-gate 		((void *)door_args.data_ptr);
451*0Sstevel@tonic-gate 	reterror = (smedia_reterror_t *)((void *)door_args.data_ptr);
452*0Sstevel@tonic-gate 	if (reterror->cnum == SMEDIA_CNUM_ERROR) {
453*0Sstevel@tonic-gate 		DPRINTF1(
454*0Sstevel@tonic-gate 	"Error in get_protection-status. errnum = 0x%x \n", reterror->errnum);
455*0Sstevel@tonic-gate 		errno = reterror->errnum;
456*0Sstevel@tonic-gate 		return (-1);
457*0Sstevel@tonic-gate 	}
458*0Sstevel@tonic-gate 	(void) memcpy((char *)wp, (char *)&retget_protection_status->prot_state,
459*0Sstevel@tonic-gate 		sizeof (smwp_state_t));
460*0Sstevel@tonic-gate 	return (0);
461*0Sstevel@tonic-gate }
462*0Sstevel@tonic-gate 
463*0Sstevel@tonic-gate int32_t
_m_set_media_status(rmedia_handle_t * handle,void * ip)464*0Sstevel@tonic-gate _m_set_media_status(rmedia_handle_t *handle, void *ip) {
465*0Sstevel@tonic-gate 
466*0Sstevel@tonic-gate 	smwp_state_t	*wp = ip;
467*0Sstevel@tonic-gate 	int32_t ret_val;
468*0Sstevel@tonic-gate 	smedia_reqset_protection_status_t	reqset_protection_status;
469*0Sstevel@tonic-gate 	smedia_reterror_t	*reterror;
470*0Sstevel@tonic-gate 	door_arg_t	door_args;
471*0Sstevel@tonic-gate 	char	rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
472*0Sstevel@tonic-gate 
473*0Sstevel@tonic-gate 	/* Check for valid handle */
474*0Sstevel@tonic-gate 	if (handle == NULL) {
475*0Sstevel@tonic-gate 		DPRINTF("Null Handle\n");
476*0Sstevel@tonic-gate 		errno = EINVAL;
477*0Sstevel@tonic-gate 		return (-1);
478*0Sstevel@tonic-gate 	}
479*0Sstevel@tonic-gate 	if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
480*0Sstevel@tonic-gate 		DPRINTF("Invalid signature in handle.\n");
481*0Sstevel@tonic-gate 		errno = EINVAL;
482*0Sstevel@tonic-gate 		return (-1);
483*0Sstevel@tonic-gate 	}
484*0Sstevel@tonic-gate 	reqset_protection_status.cnum = SMEDIA_CNUM_SET_PROTECTION_STATUS;
485*0Sstevel@tonic-gate 	reqset_protection_status.prot_state = *wp;
486*0Sstevel@tonic-gate 	door_args.data_ptr = (char *)&reqset_protection_status;
487*0Sstevel@tonic-gate 	door_args.data_size = sizeof (smedia_services_t);
488*0Sstevel@tonic-gate 	door_args.desc_ptr = NULL;
489*0Sstevel@tonic-gate 	door_args.desc_num = 0;
490*0Sstevel@tonic-gate 	door_args.rbuf = rbuf;
491*0Sstevel@tonic-gate 	door_args.rsize = sizeof (rbuf);
492*0Sstevel@tonic-gate 
493*0Sstevel@tonic-gate 	ret_val = door_call(handle->sm_door, &door_args);
494*0Sstevel@tonic-gate 	if (ret_val < 0) {
495*0Sstevel@tonic-gate 		perror("door_call");
496*0Sstevel@tonic-gate 		return (-1);
497*0Sstevel@tonic-gate 	}
498*0Sstevel@tonic-gate 	reterror = (smedia_reterror_t *)((void *)door_args.data_ptr);
499*0Sstevel@tonic-gate 	if (reterror->cnum == SMEDIA_CNUM_ERROR) {
500*0Sstevel@tonic-gate 		DPRINTF1(
501*0Sstevel@tonic-gate 	"Error in set_protection-status. errnum = 0x%x \n", reterror->errnum);
502*0Sstevel@tonic-gate 		errno = reterror->errnum;
503*0Sstevel@tonic-gate 		return (-1);
504*0Sstevel@tonic-gate 	}
505*0Sstevel@tonic-gate 	return (0);
506*0Sstevel@tonic-gate }
507*0Sstevel@tonic-gate 
508*0Sstevel@tonic-gate int32_t
_m_reassign_block(rmedia_handle_t * handle,void * ip)509*0Sstevel@tonic-gate _m_reassign_block(rmedia_handle_t *handle, void *ip)
510*0Sstevel@tonic-gate {
511*0Sstevel@tonic-gate 	uint32_t block;
512*0Sstevel@tonic-gate 	diskaddr_t *blockp  = (diskaddr_t *)ip;
513*0Sstevel@tonic-gate 	int32_t	ret_val;
514*0Sstevel@tonic-gate 	smedia_reqreassign_block_t	reqreassign_block;
515*0Sstevel@tonic-gate 	smedia_reterror_t		*reterror;
516*0Sstevel@tonic-gate 	door_arg_t	door_args;
517*0Sstevel@tonic-gate 	char	rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
518*0Sstevel@tonic-gate 
519*0Sstevel@tonic-gate 	/* Check for valid handle */
520*0Sstevel@tonic-gate 	if (handle == NULL) {
521*0Sstevel@tonic-gate 		DPRINTF("Null Handle\n");
522*0Sstevel@tonic-gate 		errno = EINVAL;
523*0Sstevel@tonic-gate 		return (-1);
524*0Sstevel@tonic-gate 	}
525*0Sstevel@tonic-gate 	if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
526*0Sstevel@tonic-gate 		DPRINTF("Invalid signature in handle.\n");
527*0Sstevel@tonic-gate 		errno = EINVAL;
528*0Sstevel@tonic-gate 		return (-1);
529*0Sstevel@tonic-gate 	}
530*0Sstevel@tonic-gate 	block = *blockp;
531*0Sstevel@tonic-gate 	DPRINTF1("reassign block %d\n", block);
532*0Sstevel@tonic-gate 	reqreassign_block.cnum = SMEDIA_CNUM_REASSIGN_BLOCK;
533*0Sstevel@tonic-gate 	reqreassign_block.blockno = block;
534*0Sstevel@tonic-gate 	door_args.data_ptr = (char *)&reqreassign_block;
535*0Sstevel@tonic-gate 	door_args.data_size = sizeof (smedia_services_t);
536*0Sstevel@tonic-gate 	door_args.desc_ptr = NULL;
537*0Sstevel@tonic-gate 	door_args.desc_num = 0;
538*0Sstevel@tonic-gate 	door_args.rbuf = rbuf;
539*0Sstevel@tonic-gate 	door_args.rsize = sizeof (rbuf);
540*0Sstevel@tonic-gate 
541*0Sstevel@tonic-gate 	ret_val = door_call(handle->sm_door, &door_args);
542*0Sstevel@tonic-gate 	if (ret_val < 0) {
543*0Sstevel@tonic-gate 		perror("door_call");
544*0Sstevel@tonic-gate 		return (-1);
545*0Sstevel@tonic-gate 	}
546*0Sstevel@tonic-gate 	reterror = (smedia_reterror_t *)((void *)door_args.data_ptr);
547*0Sstevel@tonic-gate 	if (reterror->cnum == SMEDIA_CNUM_ERROR) {
548*0Sstevel@tonic-gate 		DPRINTF2(
549*0Sstevel@tonic-gate 		"Error in reassign_block. block = 0x%x errnum = 0x%x \n",
550*0Sstevel@tonic-gate 			block, reterror->errnum);
551*0Sstevel@tonic-gate 		errno = reterror->errnum;
552*0Sstevel@tonic-gate 		return (-1);
553*0Sstevel@tonic-gate 	}
554*0Sstevel@tonic-gate 	return (0);
555*0Sstevel@tonic-gate }
556*0Sstevel@tonic-gate 
557*0Sstevel@tonic-gate /* ARGSUSED1 */
558*0Sstevel@tonic-gate int32_t
_m_eject(rmedia_handle_t * handle,void * ip)559*0Sstevel@tonic-gate _m_eject(rmedia_handle_t *handle, void *ip)
560*0Sstevel@tonic-gate {
561*0Sstevel@tonic-gate 	int32_t	fd;
562*0Sstevel@tonic-gate 
563*0Sstevel@tonic-gate 	/* Check for valid handle */
564*0Sstevel@tonic-gate 	if (handle == NULL) {
565*0Sstevel@tonic-gate 		DPRINTF("Null Handle\n");
566*0Sstevel@tonic-gate 		errno = EINVAL;
567*0Sstevel@tonic-gate 		return (-1);
568*0Sstevel@tonic-gate 	}
569*0Sstevel@tonic-gate 	if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
570*0Sstevel@tonic-gate 		DPRINTF("Invalid signature in handle.\n");
571*0Sstevel@tonic-gate 		errno = EINVAL;
572*0Sstevel@tonic-gate 		return (-1);
573*0Sstevel@tonic-gate 	}
574*0Sstevel@tonic-gate 	fd = handle->sm_fd;
575*0Sstevel@tonic-gate 	return (ioctl(fd, DKIOCEJECT));
576*0Sstevel@tonic-gate }
577*0Sstevel@tonic-gate 
578*0Sstevel@tonic-gate int32_t
_m_device_type(ushort_t ctype,ushort_t mtype)579*0Sstevel@tonic-gate _m_device_type(ushort_t ctype, ushort_t mtype)
580*0Sstevel@tonic-gate {
581*0Sstevel@tonic-gate 	if ((ctype == DKC_SCSI_CCS) ||
582*0Sstevel@tonic-gate 		(ctype == DKC_MD21) ||
583*0Sstevel@tonic-gate 		(ctype == DKC_CDROM)) {
584*0Sstevel@tonic-gate 		if (mtype == 0)
585*0Sstevel@tonic-gate 			return (0);
586*0Sstevel@tonic-gate 	}
587*0Sstevel@tonic-gate 	return (-1);
588*0Sstevel@tonic-gate }
589*0Sstevel@tonic-gate 
590*0Sstevel@tonic-gate int32_t
_m_version_no(void)591*0Sstevel@tonic-gate _m_version_no(void)
592*0Sstevel@tonic-gate {
593*0Sstevel@tonic-gate 	return (SM_SCSI_VERSION_1);
594*0Sstevel@tonic-gate }
595*0Sstevel@tonic-gate 
596*0Sstevel@tonic-gate int32_t
_m_check_format_status(rmedia_handle_t * handle,void * ip)597*0Sstevel@tonic-gate _m_check_format_status(rmedia_handle_t *handle, void *ip)
598*0Sstevel@tonic-gate {
599*0Sstevel@tonic-gate 	int32_t ret_val;
600*0Sstevel@tonic-gate 	smedia_reqcheck_format_status_t	reqcheck_format_status;
601*0Sstevel@tonic-gate 	smedia_retcheck_format_status_t	*retcheck_format_status;
602*0Sstevel@tonic-gate 	smedia_reterror_t	*reterror;
603*0Sstevel@tonic-gate 	door_arg_t	door_args;
604*0Sstevel@tonic-gate 	char	rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
605*0Sstevel@tonic-gate #ifdef	lint
606*0Sstevel@tonic-gate 	ip = ip;
607*0Sstevel@tonic-gate #endif
608*0Sstevel@tonic-gate 
609*0Sstevel@tonic-gate 	/* Check for valid handle */
610*0Sstevel@tonic-gate 	if (handle == NULL) {
611*0Sstevel@tonic-gate 		DPRINTF("Null Handle\n");
612*0Sstevel@tonic-gate 		errno = EINVAL;
613*0Sstevel@tonic-gate 		return (-1);
614*0Sstevel@tonic-gate 	}
615*0Sstevel@tonic-gate 	if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
616*0Sstevel@tonic-gate 		DPRINTF("Invalid signature in handle.\n");
617*0Sstevel@tonic-gate 		errno = EINVAL;
618*0Sstevel@tonic-gate 		return (-1);
619*0Sstevel@tonic-gate 	}
620*0Sstevel@tonic-gate 	reqcheck_format_status.cnum = SMEDIA_CNUM_CHECK_FORMAT_STATUS;
621*0Sstevel@tonic-gate 	door_args.data_ptr = (char *)&reqcheck_format_status;
622*0Sstevel@tonic-gate 	door_args.data_size = sizeof (smedia_services_t);
623*0Sstevel@tonic-gate 	door_args.desc_ptr = NULL;
624*0Sstevel@tonic-gate 	door_args.desc_num = 0;
625*0Sstevel@tonic-gate 	door_args.rbuf = rbuf;
626*0Sstevel@tonic-gate 	door_args.rsize = sizeof (rbuf);
627*0Sstevel@tonic-gate 
628*0Sstevel@tonic-gate 	ret_val = door_call(handle->sm_door, &door_args);
629*0Sstevel@tonic-gate 	if (ret_val < 0) {
630*0Sstevel@tonic-gate 		perror("door_call");
631*0Sstevel@tonic-gate 		return (-1);
632*0Sstevel@tonic-gate 	}
633*0Sstevel@tonic-gate 	retcheck_format_status =
634*0Sstevel@tonic-gate 		(smedia_retcheck_format_status_t *)((void *)door_args.data_ptr);
635*0Sstevel@tonic-gate 	reterror = (smedia_reterror_t *)((void *)door_args.data_ptr);
636*0Sstevel@tonic-gate 	if (reterror->cnum == SMEDIA_CNUM_ERROR) {
637*0Sstevel@tonic-gate 		DPRINTF1(
638*0Sstevel@tonic-gate 	"Error in check_format_status. errnum = 0x%x \n", reterror->errnum);
639*0Sstevel@tonic-gate 		errno = reterror->errnum;
640*0Sstevel@tonic-gate 		return (-1);
641*0Sstevel@tonic-gate 	}
642*0Sstevel@tonic-gate 	return (retcheck_format_status->percent_complete);
643*0Sstevel@tonic-gate }
644*0Sstevel@tonic-gate 
645*0Sstevel@tonic-gate int32_t
_m_uscsi_cmd(rmedia_handle_t * handle,struct uscsi_cmd * ucmd)646*0Sstevel@tonic-gate _m_uscsi_cmd(rmedia_handle_t *handle, struct uscsi_cmd *ucmd)
647*0Sstevel@tonic-gate {
648*0Sstevel@tonic-gate 	int32_t	ret_val;
649*0Sstevel@tonic-gate 	smedia_requscsi_cmd_t	requscsi_cmd;
650*0Sstevel@tonic-gate 	smedia_retuscsi_cmd_t	*retuscsi_cmd;
651*0Sstevel@tonic-gate 	smedia_reterror_t	*reterror;
652*0Sstevel@tonic-gate 	door_arg_t	door_args;
653*0Sstevel@tonic-gate 	char	rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
654*0Sstevel@tonic-gate 
655*0Sstevel@tonic-gate 	/* Check for valid handle */
656*0Sstevel@tonic-gate 	if (handle == NULL) {
657*0Sstevel@tonic-gate 		DPRINTF("Null Handle\n");
658*0Sstevel@tonic-gate 		errno = EINVAL;
659*0Sstevel@tonic-gate 		return (-1);
660*0Sstevel@tonic-gate 	}
661*0Sstevel@tonic-gate 	if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
662*0Sstevel@tonic-gate 		DPRINTF("Invalid signature in handle.\n");
663*0Sstevel@tonic-gate 		errno = EINVAL;
664*0Sstevel@tonic-gate 		return (-1);
665*0Sstevel@tonic-gate 	}
666*0Sstevel@tonic-gate 	/*
667*0Sstevel@tonic-gate 	 * We will be validating the user supplied buffer lengths and
668*0Sstevel@tonic-gate 	 * buffer pointers.
669*0Sstevel@tonic-gate 	 */
670*0Sstevel@tonic-gate 	if (ucmd->uscsi_cdblen > MAX_CDB_LEN) {
671*0Sstevel@tonic-gate 		DPRINTF("Invalid cdblen specified.\n");
672*0Sstevel@tonic-gate 		errno = EINVAL;
673*0Sstevel@tonic-gate 		return (-1);
674*0Sstevel@tonic-gate 	}
675*0Sstevel@tonic-gate 	if ((ucmd->uscsi_flags & USCSI_RQENABLE) &&
676*0Sstevel@tonic-gate 	    (ucmd->uscsi_rqlen > MAX_RQ_LEN)) {
677*0Sstevel@tonic-gate 		DPRINTF("Invalid rqlen specified.\n");
678*0Sstevel@tonic-gate 		errno = EINVAL;
679*0Sstevel@tonic-gate 		return (-1);
680*0Sstevel@tonic-gate 	}
681*0Sstevel@tonic-gate 	if (ucmd->uscsi_cdb == NULL) {
682*0Sstevel@tonic-gate 		DPRINTF("cdb buffer is NULL.\n");
683*0Sstevel@tonic-gate 		errno = EINVAL;
684*0Sstevel@tonic-gate 		return (-1);
685*0Sstevel@tonic-gate 	}
686*0Sstevel@tonic-gate 	if ((ucmd->uscsi_buflen) && (ucmd->uscsi_bufaddr == NULL)) {
687*0Sstevel@tonic-gate 		DPRINTF("bufaddr is NULL.\n");
688*0Sstevel@tonic-gate 		errno = EINVAL;
689*0Sstevel@tonic-gate 		return (-1);
690*0Sstevel@tonic-gate 	}
691*0Sstevel@tonic-gate 	if ((ucmd->uscsi_flags & USCSI_RQENABLE) &&
692*0Sstevel@tonic-gate 	    (ucmd->uscsi_rqbuf == NULL)) {
693*0Sstevel@tonic-gate 		DPRINTF("rqbuf is NULL.\n");
694*0Sstevel@tonic-gate 		errno = EINVAL;
695*0Sstevel@tonic-gate 		return (-1);
696*0Sstevel@tonic-gate 	}
697*0Sstevel@tonic-gate 	/*
698*0Sstevel@tonic-gate 	 * Check if another thread is doing an IO with same handle.
699*0Sstevel@tonic-gate 	 * In that case we block here.
700*0Sstevel@tonic-gate 	 */
701*0Sstevel@tonic-gate 	(void) mutex_lock(&handle->sm_bufmutex);
702*0Sstevel@tonic-gate 	ret_val = remap_shared_buf(handle, ucmd->uscsi_buflen,
703*0Sstevel@tonic-gate 			ucmd->uscsi_bufaddr);
704*0Sstevel@tonic-gate 	if (ret_val != 0) {
705*0Sstevel@tonic-gate 		DPRINTF("remap of shared buf failed.\n");
706*0Sstevel@tonic-gate 		goto error;
707*0Sstevel@tonic-gate 	}
708*0Sstevel@tonic-gate 
709*0Sstevel@tonic-gate 	requscsi_cmd.cnum = SMEDIA_CNUM_USCSI_CMD;
710*0Sstevel@tonic-gate 	requscsi_cmd.uscsi_flags = ucmd->uscsi_flags;
711*0Sstevel@tonic-gate 	requscsi_cmd.uscsi_timeout = ucmd->uscsi_timeout;
712*0Sstevel@tonic-gate 	requscsi_cmd.uscsi_buflen = ucmd->uscsi_buflen;
713*0Sstevel@tonic-gate 	requscsi_cmd.uscsi_cdblen = ucmd->uscsi_cdblen;
714*0Sstevel@tonic-gate 	requscsi_cmd.uscsi_rqlen = ucmd->uscsi_rqlen;
715*0Sstevel@tonic-gate 
716*0Sstevel@tonic-gate 	/*
717*0Sstevel@tonic-gate 	 * The uscsi_buflen has been validated in the call to
718*0Sstevel@tonic-gate 	 * remap_shared_buf() done earlier.
719*0Sstevel@tonic-gate 	 */
720*0Sstevel@tonic-gate 	/* Check for write */
721*0Sstevel@tonic-gate 	if (!(ucmd->uscsi_flags & USCSI_READ)) {
722*0Sstevel@tonic-gate 		bcopy(ucmd->uscsi_bufaddr, handle->sm_buf, ucmd->uscsi_buflen);
723*0Sstevel@tonic-gate 	}
724*0Sstevel@tonic-gate 
725*0Sstevel@tonic-gate 	bcopy(ucmd->uscsi_cdb, requscsi_cmd.uscsi_cdb, ucmd->uscsi_cdblen);
726*0Sstevel@tonic-gate 
727*0Sstevel@tonic-gate 	door_args.data_ptr = (char *)&requscsi_cmd;
728*0Sstevel@tonic-gate 	door_args.data_size = sizeof (smedia_services_t);
729*0Sstevel@tonic-gate 	door_args.desc_ptr = NULL;
730*0Sstevel@tonic-gate 	door_args.desc_num = 0;
731*0Sstevel@tonic-gate 	door_args.rbuf = rbuf;
732*0Sstevel@tonic-gate 	door_args.rsize = sizeof (rbuf);
733*0Sstevel@tonic-gate 
734*0Sstevel@tonic-gate 	ret_val = door_call(handle->sm_door, &door_args);
735*0Sstevel@tonic-gate 	if (ret_val < 0) {
736*0Sstevel@tonic-gate 		perror("door_call");
737*0Sstevel@tonic-gate 		goto error;
738*0Sstevel@tonic-gate 	}
739*0Sstevel@tonic-gate 	retuscsi_cmd = (smedia_retuscsi_cmd_t *)((void *)door_args.data_ptr);
740*0Sstevel@tonic-gate 	reterror = (smedia_reterror_t *)((void *)door_args.data_ptr);
741*0Sstevel@tonic-gate 	if (reterror->cnum == SMEDIA_CNUM_ERROR) {
742*0Sstevel@tonic-gate 		DPRINTF1(
743*0Sstevel@tonic-gate 		"Error in uscsi cmd. errnum = 0x%x\n", reterror->errnum);
744*0Sstevel@tonic-gate 		errno = reterror->errnum;
745*0Sstevel@tonic-gate 		goto error;
746*0Sstevel@tonic-gate 	}
747*0Sstevel@tonic-gate 	ucmd->uscsi_status = retuscsi_cmd->uscsi_status;
748*0Sstevel@tonic-gate 	ucmd->uscsi_resid = retuscsi_cmd->uscsi_resid;
749*0Sstevel@tonic-gate 	ucmd->uscsi_rqstatus = retuscsi_cmd->uscsi_rqstatus;
750*0Sstevel@tonic-gate 	ucmd->uscsi_rqresid = retuscsi_cmd->uscsi_rqresid;
751*0Sstevel@tonic-gate 	if ((ucmd->uscsi_flags & USCSI_RQENABLE) &&
752*0Sstevel@tonic-gate 		(ucmd->uscsi_rqbuf != NULL)) {
753*0Sstevel@tonic-gate 		bcopy(retuscsi_cmd->uscsi_rqbuf,
754*0Sstevel@tonic-gate 			ucmd->uscsi_rqbuf, ucmd->uscsi_rqlen);
755*0Sstevel@tonic-gate 	}
756*0Sstevel@tonic-gate 	errno = retuscsi_cmd->uscsi_errno;
757*0Sstevel@tonic-gate 	if (errno) {
758*0Sstevel@tonic-gate 		goto error;
759*0Sstevel@tonic-gate 	}
760*0Sstevel@tonic-gate 
761*0Sstevel@tonic-gate 	if (ucmd->uscsi_resid > ucmd->uscsi_buflen) {
762*0Sstevel@tonic-gate 		/*
763*0Sstevel@tonic-gate 		 * Invalid resid value. return error.
764*0Sstevel@tonic-gate 		 */
765*0Sstevel@tonic-gate 		errno = EINVAL;
766*0Sstevel@tonic-gate 		goto error;
767*0Sstevel@tonic-gate 	}
768*0Sstevel@tonic-gate 	if (ucmd->uscsi_flags & USCSI_READ) {
769*0Sstevel@tonic-gate 		(void) memcpy(ucmd->uscsi_bufaddr,
770*0Sstevel@tonic-gate 				handle->sm_buf,
771*0Sstevel@tonic-gate 				ucmd->uscsi_buflen - ucmd->uscsi_resid);
772*0Sstevel@tonic-gate 	}
773*0Sstevel@tonic-gate 	(void) mutex_unlock(&handle->sm_bufmutex);
774*0Sstevel@tonic-gate #ifdef DEBUG
775*0Sstevel@tonic-gate 	if (retuscsi_cmd->uscsi_retval || ucmd->uscsi_status)
776*0Sstevel@tonic-gate 		DPRINTF2("Error in uscsi_cmd: retval=0x%x uscsi_status=0x%x\n",
777*0Sstevel@tonic-gate 			retuscsi_cmd->uscsi_retval, ucmd->uscsi_status);
778*0Sstevel@tonic-gate #endif
779*0Sstevel@tonic-gate 	return (retuscsi_cmd->uscsi_retval);
780*0Sstevel@tonic-gate error:
781*0Sstevel@tonic-gate 	(void) mutex_unlock(&handle->sm_bufmutex);
782*0Sstevel@tonic-gate 	return (-1);
783*0Sstevel@tonic-gate }
784*0Sstevel@tonic-gate 
785*0Sstevel@tonic-gate int32_t
remap_shared_buf(rmedia_handle_t * handle,size_t buf_size,char * buffer)786*0Sstevel@tonic-gate remap_shared_buf(rmedia_handle_t *handle, size_t buf_size, char *buffer)
787*0Sstevel@tonic-gate {
788*0Sstevel@tonic-gate 	char	rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
789*0Sstevel@tonic-gate 	char	fname[128];
790*0Sstevel@tonic-gate 	smedia_reqset_shfd_t	reqset_shfd;
791*0Sstevel@tonic-gate 	smedia_reterror_t	*reterror;
792*0Sstevel@tonic-gate 	int	ret_val, fd;
793*0Sstevel@tonic-gate 	door_arg_t	door_args;
794*0Sstevel@tonic-gate 	door_desc_t	ddesc[2];
795*0Sstevel@tonic-gate 	char	*fbuf;
796*0Sstevel@tonic-gate 	size_t	shared_bufsize;
797*0Sstevel@tonic-gate 	off_t	file_size, ret;
798*0Sstevel@tonic-gate 
799*0Sstevel@tonic-gate 	if (handle->sm_bufsize >= buf_size)
800*0Sstevel@tonic-gate 		return (0);
801*0Sstevel@tonic-gate 	shared_bufsize = ((buf_size + BUF_SIZE_MULTIPLE - 1)/BUF_SIZE_MULTIPLE)
802*0Sstevel@tonic-gate 		* BUF_SIZE_MULTIPLE;
803*0Sstevel@tonic-gate 	if (handle->sm_buffd != -1) {
804*0Sstevel@tonic-gate 		/* extend the file and re-map */
805*0Sstevel@tonic-gate 		fd = handle->sm_buffd;
806*0Sstevel@tonic-gate 		ret_val = munmap(handle->sm_buf, handle->sm_bufsize);
807*0Sstevel@tonic-gate 		if (ret_val != 0) {
808*0Sstevel@tonic-gate 			DPRINTF1("remap:munmap failed. errno = 0x%x\n", errno);
809*0Sstevel@tonic-gate 			(void) close(fd);
810*0Sstevel@tonic-gate 			handle->sm_buf = NULL;
811*0Sstevel@tonic-gate 			handle->sm_bufsize = 0;
812*0Sstevel@tonic-gate 			handle->sm_buffd = -1;
813*0Sstevel@tonic-gate 			return (errno);
814*0Sstevel@tonic-gate 		}
815*0Sstevel@tonic-gate 		file_size = lseek(fd, 0, SEEK_END);
816*0Sstevel@tonic-gate 		if (file_size == -1) {
817*0Sstevel@tonic-gate 			DPRINTF1("remap:lseek failed. errno = 0x%x\n", errno);
818*0Sstevel@tonic-gate 			return (errno);
819*0Sstevel@tonic-gate 		}
820*0Sstevel@tonic-gate 		handle->sm_buf = NULL;
821*0Sstevel@tonic-gate 		handle->sm_bufsize = 0;
822*0Sstevel@tonic-gate 		handle->sm_buffd = -1;
823*0Sstevel@tonic-gate 	} else {
824*0Sstevel@tonic-gate 		/* create a new file and mapping */
825*0Sstevel@tonic-gate 		(void) sprintf(fname, "/tmp/libsmedia_mmaped_file_XXXXXX");
826*0Sstevel@tonic-gate 		fd = mkstemp(fname);
827*0Sstevel@tonic-gate 		if (fd == -1) {
828*0Sstevel@tonic-gate 			DPRINTF1("remap:mktemp failed. errno = 0x%x\n", errno);
829*0Sstevel@tonic-gate 			return (errno);
830*0Sstevel@tonic-gate 		}
831*0Sstevel@tonic-gate 		ret_val = unlink(fname);
832*0Sstevel@tonic-gate 		if (ret_val == -1) {
833*0Sstevel@tonic-gate 			DPRINTF1("remap:unlink failed. errno = 0x%x\n", errno);
834*0Sstevel@tonic-gate 			(void) close(fd);
835*0Sstevel@tonic-gate 			return (errno);
836*0Sstevel@tonic-gate 		}
837*0Sstevel@tonic-gate 		file_size = 0;
838*0Sstevel@tonic-gate 	}
839*0Sstevel@tonic-gate 	/* Need to start at the beginning of the file when enlarging */
840*0Sstevel@tonic-gate 	ret = lseek(fd, 0, SEEK_SET);
841*0Sstevel@tonic-gate 	if (ret == -1) {
842*0Sstevel@tonic-gate 		DPRINTF1("remap:lseek failed. errno = 0x%x\n", errno);
843*0Sstevel@tonic-gate 		return (errno);
844*0Sstevel@tonic-gate 	}
845*0Sstevel@tonic-gate 	while (file_size < shared_bufsize) {
846*0Sstevel@tonic-gate 		ret_val = write(fd, buffer, buf_size);
847*0Sstevel@tonic-gate 		if (ret_val != buf_size) {
848*0Sstevel@tonic-gate 			DPRINTF1("remap:write failed. errno = 0x%x\n", errno);
849*0Sstevel@tonic-gate 			(void) close(fd);
850*0Sstevel@tonic-gate 			return (errno);
851*0Sstevel@tonic-gate 		}
852*0Sstevel@tonic-gate 		file_size += buf_size;
853*0Sstevel@tonic-gate 	}
854*0Sstevel@tonic-gate 	fbuf = (char *)mmap(0, shared_bufsize, PROT_READ | PROT_WRITE,
855*0Sstevel@tonic-gate 		MAP_SHARED, fd, 0);
856*0Sstevel@tonic-gate 	if (fbuf == (char *)-1) {
857*0Sstevel@tonic-gate 		perror("mmap failed");
858*0Sstevel@tonic-gate 		(void) close(fd);
859*0Sstevel@tonic-gate 		return (errno);
860*0Sstevel@tonic-gate 	}
861*0Sstevel@tonic-gate 
862*0Sstevel@tonic-gate 	reqset_shfd.cnum = SMEDIA_CNUM_SET_SHFD;
863*0Sstevel@tonic-gate 	reqset_shfd.fdbuf_len = shared_bufsize;
864*0Sstevel@tonic-gate 	ddesc[0].d_data.d_desc.d_descriptor = fd;
865*0Sstevel@tonic-gate 	ddesc[0].d_attributes = DOOR_DESCRIPTOR;
866*0Sstevel@tonic-gate 	door_args.data_ptr = (char *)&reqset_shfd;
867*0Sstevel@tonic-gate 	door_args.data_size = sizeof (reqset_shfd);
868*0Sstevel@tonic-gate 	door_args.desc_ptr = &ddesc[0];
869*0Sstevel@tonic-gate 	door_args.desc_num = 1;
870*0Sstevel@tonic-gate 	door_args.rbuf = rbuf;
871*0Sstevel@tonic-gate 	door_args.rsize = sizeof (rbuf);
872*0Sstevel@tonic-gate 
873*0Sstevel@tonic-gate 	ret_val = door_call(handle->sm_door, &door_args);
874*0Sstevel@tonic-gate 	if (ret_val < 0) {
875*0Sstevel@tonic-gate 		perror("door_call");
876*0Sstevel@tonic-gate 		(void) close(fd);
877*0Sstevel@tonic-gate 		return (-1);
878*0Sstevel@tonic-gate 	}
879*0Sstevel@tonic-gate 	reterror = (smedia_reterror_t *)((void *)door_args.data_ptr);
880*0Sstevel@tonic-gate 	if (reterror->cnum == SMEDIA_CNUM_ERROR) {
881*0Sstevel@tonic-gate 		DPRINTF1("Error in set shfd. errnum = 0x%x\n",
882*0Sstevel@tonic-gate 			reterror->errnum);
883*0Sstevel@tonic-gate 		errno = reterror->errnum;
884*0Sstevel@tonic-gate 		(void) close(fd);
885*0Sstevel@tonic-gate 		return (errno);
886*0Sstevel@tonic-gate 	}
887*0Sstevel@tonic-gate 	handle->sm_buffd = fd;
888*0Sstevel@tonic-gate 	handle->sm_buf = fbuf;
889*0Sstevel@tonic-gate 	handle->sm_bufsize = shared_bufsize;
890*0Sstevel@tonic-gate 	DPRINTF("Returned successful from remap shared buf routine.\n");
891*0Sstevel@tonic-gate 	return (0);
892*0Sstevel@tonic-gate }
893