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