Merge commit 'a71e11eee4676204c7609c4c9703cc98fbf4669d' into merges
[unleashed.git] / usr / src / lib / libsmedia / plugins / scsi / common / s_generic.c
blob19beb5b9d74f3d60ea0f19c88b8bf7a40459482f
1 /*
2 * CDDL HEADER START
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.
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.
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]
20 * CDDL HEADER END
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 * s_generic.c :
29 * This file contains generic SCSI related functions for scsi plug-in
30 * for libsm.so.
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <sys/ioctl.h>
37 #include <unistd.h>
38 #include <sys/shm.h>
39 #include <sys/mman.h>
40 #include <sys/smedia.h>
41 #include "../../../library/inc/rmedia.h"
42 #include <smserver.h>
43 #include <dirent.h>
44 #include <fcntl.h>
45 #include <sys/scsi/scsi.h>
46 #include <strings.h>
47 #include "../../../library/common/l_defines.h"
50 static int32_t remap_shared_buf(rmedia_handle_t *, size_t, char *);
52 #define W_E_MASK 0x80
53 #define BUF_SIZE_MULTIPLE 0x2000
55 int32_t
56 _m_get_media_info(rmedia_handle_t *handle, void *ip)
58 smmedium_prop_t *medinfo = ip;
59 int32_t ret_val;
60 smedia_reqget_medium_property_t reqget_medium_property;
61 smedia_retget_medium_property_t *retget_medium_property;
62 smedia_reterror_t *reterror;
63 door_arg_t door_args;
64 char rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
66 DPRINTF("get_media_info called.\n");
67 /* Check for valid handle */
68 if (handle == NULL) {
69 DPRINTF("Null Handle\n");
70 errno = EINVAL;
71 return (-1);
73 if (handle->sm_signature != (int32_t)LIBSMEDIA_SIGNATURE) {
74 DPRINTF("Invalid signature in handle.\n");
75 DPRINTF2("Signature expected=0x%x, found=0x%x\n",
76 LIBSMEDIA_SIGNATURE, handle->sm_signature);
77 DPRINTF1("fd=%d\n", handle->sm_fd);
78 errno = EINVAL;
79 return (-1);
81 (void) memset(medinfo, 0, sizeof (smmedium_prop_t));
83 reqget_medium_property.cnum = SMEDIA_CNUM_GET_MEDIUM_PROPERTY;
84 door_args.data_ptr = (char *)&reqget_medium_property;
85 door_args.data_size = sizeof (smedia_services_t);
86 door_args.desc_ptr = NULL;
87 door_args.desc_num = 0;
88 door_args.rbuf = rbuf;
89 door_args.rsize = sizeof (rbuf);
91 ret_val = door_call(handle->sm_door, &door_args);
92 if (ret_val < 0) {
93 perror("door_call");
94 return (-1);
96 retget_medium_property =
97 (smedia_retget_medium_property_t *)((void *)door_args.data_ptr);
98 reterror = (smedia_reterror_t *)((void *)door_args.data_ptr);
99 if (reterror->cnum == SMEDIA_CNUM_ERROR) {
100 DPRINTF1(
101 "Error in get_medium_property. errnum = 0x%x \n", reterror->errnum);
102 errno = reterror->errnum;
103 return (-1);
106 *medinfo = retget_medium_property->smprop;
108 return (0);
111 int32_t
112 _m_get_device_info(rmedia_handle_t *handle, void *ip)
114 struct smdevice_info *dev_info = ip;
115 int32_t ret_val;
116 smedia_reqget_device_info_t reqget_device_info;
117 smedia_retget_device_info_t *retget_device_info;
118 smedia_reterror_t *reterror;
119 door_arg_t door_args;
120 char rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
121 char *vendor_name, *product_name, *fw_version;
123 /* Check for valid handle */
124 if (handle == NULL) {
125 DPRINTF("Null Handle\n");
126 errno = EINVAL;
127 return (-1);
129 if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
130 DPRINTF("Invalid signature in handle.\n");
131 errno = EINVAL;
132 return (-1);
135 vendor_name = (char *)malloc(9);
136 if (vendor_name == NULL) {
137 if (!errno)
138 errno = ENOMEM;
139 return (-1);
141 product_name = (char *)malloc(17);
142 if (product_name == NULL) {
143 free(vendor_name);
144 if (!errno)
145 errno = ENOMEM;
146 return (-1);
149 fw_version = (char *)malloc(18);
150 if (fw_version == NULL) {
151 free(vendor_name);
152 free(product_name);
153 if (!errno)
154 errno = ENOMEM;
155 return (-1);
157 reqget_device_info.cnum = SMEDIA_CNUM_GET_DEVICE_INFO;
158 door_args.data_ptr = (char *)&reqget_device_info;
159 door_args.data_size = sizeof (smedia_services_t);
160 door_args.desc_ptr = NULL;
161 door_args.desc_num = 0;
162 door_args.rbuf = rbuf;
163 door_args.rsize = sizeof (rbuf);
165 ret_val = door_call(handle->sm_door, &door_args);
166 if (ret_val < 0) {
167 perror("door_call");
168 free(vendor_name);
169 free(product_name);
170 free(fw_version);
171 return (-1);
173 retget_device_info = (smedia_retget_device_info_t *)
174 ((void *)door_args.data_ptr);
175 reterror = (smedia_reterror_t *)((void *)door_args.data_ptr);
176 if (reterror->cnum == SMEDIA_CNUM_ERROR) {
177 DPRINTF1("Error in get_device_info. errnum = 0x%x \n",
178 reterror->errnum);
179 errno = reterror->errnum;
180 free(vendor_name);
181 free(product_name);
182 free(fw_version);
183 return (-1);
186 dev_info->sm_vendor_name = vendor_name;
187 dev_info->sm_product_name = product_name;
188 dev_info->sm_firmware_version = fw_version;
191 (void) strlcpy(dev_info->sm_vendor_name,
192 retget_device_info->sm_vendor_name, 8);
193 dev_info->sm_vendor_name[8] = 0;
194 (void) strlcpy(dev_info->sm_product_name,
195 retget_device_info->sm_product_name, 16);
196 dev_info->sm_product_name[16] = 0;
197 (void) strlcpy(dev_info->sm_firmware_version,
198 retget_device_info->sm_firmware_version, 17);
199 dev_info->sm_firmware_version[17] = 0;
201 dev_info->sm_interface_type = retget_device_info->sm_interface_type;
203 #ifdef DEBUG
204 DPRINTF1("Vendor name = %s\n", dev_info->sm_vendor_name);
205 DPRINTF1("product name = %s\n", dev_info->sm_product_name);
206 DPRINTF1("Firmware revision = %s\n", dev_info->sm_firmware_version);
207 #endif /* DEBUG */
209 return (0);
212 int32_t
213 _m_free_device_info(rmedia_handle_t *handle, void *ip)
215 struct smdevice_info *dev_info = ip;
217 /* Check for valid handle */
218 if (handle == NULL) {
219 DPRINTF("Null Handle\n");
220 errno = EINVAL;
221 return (-1);
223 if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
224 DPRINTF("Invalid signature in handle.\n");
225 errno = EINVAL;
226 return (-1);
229 free(dev_info->sm_vendor_name);
230 free(dev_info->sm_product_name);
231 free(dev_info->sm_firmware_version);
232 return (0);
235 int32_t
236 _m_raw_write(rmedia_handle_t *handle, void *i_p)
238 int32_t ret_val;
239 struct raw_params *r_p = (struct raw_params *)i_p;
240 smedia_reqraw_write_t reqraw_write;
241 smedia_retraw_write_t *retraw_write;
242 smedia_reterror_t *reterror;
243 door_arg_t door_args;
244 char rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
246 /* Check for valid handle */
247 if (handle == NULL) {
248 DPRINTF("Null Handle\n");
249 errno = EINVAL;
250 return (-1);
252 if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
253 DPRINTF("Invalid signature in handle.\n");
254 errno = EINVAL;
255 return (-1);
257 (void) mutex_lock(&handle->sm_bufmutex);
258 ret_val = remap_shared_buf(handle, r_p->size, r_p->buffer);
259 if (ret_val != 0) goto error;
260 reqraw_write.cnum = SMEDIA_CNUM_RAW_WRITE;
261 reqraw_write.blockno = r_p->offset;
262 reqraw_write.nbytes = r_p->size;
263 bcopy(r_p->buffer, handle->sm_buf, r_p->size);
264 door_args.data_ptr = (char *)&reqraw_write;
265 door_args.data_size = sizeof (reqraw_write);
266 door_args.desc_ptr = NULL;
267 door_args.desc_num = 0;
268 door_args.rbuf = rbuf;
269 door_args.rsize = sizeof (rbuf);
271 ret_val = door_call(handle->sm_door, &door_args);
272 if (ret_val < 0) {
273 perror("door_call");
274 goto error;
276 retraw_write = (smedia_retraw_write_t *)((void *)door_args.data_ptr);
277 reterror = (smedia_reterror_t *)((void *)door_args.data_ptr);
278 if (reterror->cnum == SMEDIA_CNUM_ERROR) {
279 DPRINTF3("Error in raw write. errnum = 0x%x "
280 "blk_num = 0x%x(%d)\n", reterror->errnum, r_p->offset,
281 r_p->offset);
282 errno = reterror->errnum;
283 goto error;
285 (void) mutex_unlock(&handle->sm_bufmutex);
286 return (retraw_write->nbytes);
288 error:
289 (void) mutex_unlock(&handle->sm_bufmutex);
290 return (-1);
293 size_t
294 _m_raw_read(rmedia_handle_t *handle, void *i_p)
296 struct raw_params *r_p = (struct raw_params *)i_p;
297 int32_t ret_val, bytes_read;
298 smedia_reqraw_read_t reqraw_read;
299 smedia_retraw_read_t *retraw_read;
300 smedia_reterror_t *reterror;
301 door_arg_t door_args;
302 char rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
304 /* Check for valid handle */
305 if (handle == NULL) {
306 DPRINTF("Null Handle\n");
307 errno = EINVAL;
308 return (size_t)(-1);
310 if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
311 DPRINTF("Invalid signature in handle.\n");
312 return (size_t)(-1);
315 * Check if another thread is doing an IO with same handle.
316 * In that case ww block here.
318 (void) mutex_lock(&handle->sm_bufmutex);
319 ret_val = remap_shared_buf(handle, r_p->size, r_p->buffer);
320 if (ret_val != 0) goto error;
322 reqraw_read.cnum = SMEDIA_CNUM_RAW_READ;
323 reqraw_read.blockno = r_p->offset;
324 reqraw_read.nbytes = r_p->size;
325 door_args.data_ptr = (char *)&reqraw_read;
326 door_args.data_size = sizeof (smedia_services_t);
327 door_args.desc_ptr = NULL;
328 door_args.desc_num = 0;
329 door_args.rbuf = rbuf;
330 door_args.rsize = sizeof (rbuf);
332 ret_val = door_call(handle->sm_door, &door_args);
333 if (ret_val < 0) {
334 perror("door_call");
335 goto error;
337 retraw_read = (smedia_retraw_read_t *)((void *)door_args.data_ptr);
338 reterror = (smedia_reterror_t *)((void *)door_args.data_ptr);
339 if (reterror->cnum == SMEDIA_CNUM_ERROR) {
341 * free(rbuf);
343 DPRINTF3("Error in raw read. errnum = 0x%x "
344 "blk_num = 0x%x(%d)\n", reterror->errnum, r_p->offset,
345 r_p->offset);
346 errno = reterror->errnum;
347 goto error;
349 (void) memcpy(r_p->buffer, handle->sm_buf, retraw_read->nbytes);
350 bytes_read = retraw_read->nbytes;
351 (void) mutex_unlock(&handle->sm_bufmutex);
352 return (bytes_read);
354 error:
355 (void) mutex_unlock(&handle->sm_bufmutex);
356 return (size_t)(-1);
360 size_t
361 _m_media_format(rmedia_handle_t *handle, void *ip)
363 int32_t ret_val;
364 struct format_flags *ffl = (struct format_flags *)ip;
365 smedia_reqformat_t reqformat;
366 smedia_reterror_t *reterror;
367 door_arg_t door_args;
368 char rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
370 /* Check for valid handle */
371 if (handle == NULL) {
372 DPRINTF("Null Handle\n");
373 errno = EINVAL;
374 return (size_t)(-1);
376 if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
377 DPRINTF("Invalid signature in handle.\n");
378 errno = EINVAL;
379 return (size_t)(-1);
381 reqformat.cnum = SMEDIA_CNUM_FORMAT;
382 reqformat.flavor = ffl->flavor;
383 reqformat.mode = ffl->mode;
384 door_args.data_ptr = (char *)&reqformat;
385 door_args.data_size = sizeof (smedia_services_t);
386 door_args.desc_ptr = NULL;
387 door_args.desc_num = 0;
388 door_args.rbuf = rbuf;
389 door_args.rsize = sizeof (rbuf);
391 ret_val = door_call(handle->sm_door, &door_args);
392 if (ret_val < 0) {
393 perror("door_call");
394 return (size_t)(-1);
396 reterror = (smedia_reterror_t *)((void *)door_args.data_ptr);
397 if (reterror->cnum == SMEDIA_CNUM_ERROR) {
398 DPRINTF1("Error in format. errnum = 0x%x \n", reterror->errnum);
399 errno = reterror->errnum;
400 return (size_t)(-1);
402 return (0);
405 int32_t
406 _m_get_media_status(rmedia_handle_t *handle, void *ip)
408 smwp_state_t *wp = ip;
409 int32_t ret_val;
410 smedia_reqget_protection_status_t reqget_protection_status;
411 smedia_retget_protection_status_t *retget_protection_status;
412 smedia_reterror_t *reterror;
413 door_arg_t door_args;
414 char rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
416 /* Check for valid handle */
417 if (handle == NULL) {
418 DPRINTF("Null Handle\n");
419 errno = EINVAL;
420 return (-1);
422 if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
423 DPRINTF("Invalid signature in handle.\n");
424 errno = EINVAL;
425 return (-1);
427 reqget_protection_status.cnum = SMEDIA_CNUM_GET_PROTECTION_STATUS;
428 door_args.data_ptr = (char *)&reqget_protection_status;
429 door_args.data_size = sizeof (smedia_services_t);
430 door_args.desc_ptr = NULL;
431 door_args.desc_num = 0;
432 door_args.rbuf = rbuf;
433 door_args.rsize = sizeof (rbuf);
435 ret_val = door_call(handle->sm_door, &door_args);
436 if (ret_val < 0) {
437 perror("door_call");
438 return (-1);
440 retget_protection_status = (smedia_retget_protection_status_t *)
441 ((void *)door_args.data_ptr);
442 reterror = (smedia_reterror_t *)((void *)door_args.data_ptr);
443 if (reterror->cnum == SMEDIA_CNUM_ERROR) {
444 DPRINTF1("Error in get_protection-status. errnum = 0x%x \n",
445 reterror->errnum);
446 errno = reterror->errnum;
447 return (-1);
449 (void) memcpy((char *)wp, (char *)&retget_protection_status->prot_state,
450 sizeof (smwp_state_t));
451 return (0);
454 int32_t
455 _m_set_media_status(rmedia_handle_t *handle, void *ip)
458 smwp_state_t *wp = ip;
459 int32_t ret_val;
460 smedia_reqset_protection_status_t reqset_protection_status;
461 smedia_reterror_t *reterror;
462 door_arg_t door_args;
463 char rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
465 /* Check for valid handle */
466 if (handle == NULL) {
467 DPRINTF("Null Handle\n");
468 errno = EINVAL;
469 return (-1);
471 if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
472 DPRINTF("Invalid signature in handle.\n");
473 errno = EINVAL;
474 return (-1);
476 reqset_protection_status.cnum = SMEDIA_CNUM_SET_PROTECTION_STATUS;
477 reqset_protection_status.prot_state = *wp;
478 door_args.data_ptr = (char *)&reqset_protection_status;
479 door_args.data_size = sizeof (smedia_services_t);
480 door_args.desc_ptr = NULL;
481 door_args.desc_num = 0;
482 door_args.rbuf = rbuf;
483 door_args.rsize = sizeof (rbuf);
485 ret_val = door_call(handle->sm_door, &door_args);
486 if (ret_val < 0) {
487 perror("door_call");
488 return (-1);
490 reterror = (smedia_reterror_t *)((void *)door_args.data_ptr);
491 if (reterror->cnum == SMEDIA_CNUM_ERROR) {
492 DPRINTF1(
493 "Error in set_protection-status. errnum = 0x%x \n", reterror->errnum);
494 errno = reterror->errnum;
495 return (-1);
497 return (0);
500 int32_t
501 _m_reassign_block(rmedia_handle_t *handle, void *ip)
503 uint32_t block;
504 diskaddr_t *blockp = (diskaddr_t *)ip;
505 int32_t ret_val;
506 smedia_reqreassign_block_t reqreassign_block;
507 smedia_reterror_t *reterror;
508 door_arg_t door_args;
509 char rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
511 /* Check for valid handle */
512 if (handle == NULL) {
513 DPRINTF("Null Handle\n");
514 errno = EINVAL;
515 return (-1);
517 if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
518 DPRINTF("Invalid signature in handle.\n");
519 errno = EINVAL;
520 return (-1);
522 block = *blockp;
523 DPRINTF1("reassign block %d\n", block);
524 reqreassign_block.cnum = SMEDIA_CNUM_REASSIGN_BLOCK;
525 reqreassign_block.blockno = block;
526 door_args.data_ptr = (char *)&reqreassign_block;
527 door_args.data_size = sizeof (smedia_services_t);
528 door_args.desc_ptr = NULL;
529 door_args.desc_num = 0;
530 door_args.rbuf = rbuf;
531 door_args.rsize = sizeof (rbuf);
533 ret_val = door_call(handle->sm_door, &door_args);
534 if (ret_val < 0) {
535 perror("door_call");
536 return (-1);
538 reterror = (smedia_reterror_t *)((void *)door_args.data_ptr);
539 if (reterror->cnum == SMEDIA_CNUM_ERROR) {
540 DPRINTF2("Error in reassign_block. block = 0x%x "
541 "errnum = 0x%x \n", block, reterror->errnum);
542 errno = reterror->errnum;
543 return (-1);
545 return (0);
548 /* ARGSUSED1 */
549 int32_t
550 _m_eject(rmedia_handle_t *handle, void *ip)
552 int32_t fd;
554 /* Check for valid handle */
555 if (handle == NULL) {
556 DPRINTF("Null Handle\n");
557 errno = EINVAL;
558 return (-1);
560 if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
561 DPRINTF("Invalid signature in handle.\n");
562 errno = EINVAL;
563 return (-1);
565 fd = handle->sm_fd;
566 return (ioctl(fd, DKIOCEJECT));
569 int32_t
570 _m_device_type(ushort_t ctype, ushort_t mtype)
572 if ((ctype == DKC_SCSI_CCS) ||
573 (ctype == DKC_MD21) ||
574 (ctype == DKC_CDROM)) {
575 if (mtype == 0)
576 return (0);
578 return (-1);
581 int32_t
582 _m_version_no(void)
584 return (SM_SCSI_VERSION_1);
587 int32_t
588 _m_check_format_status(rmedia_handle_t *handle, void *ip)
590 int32_t ret_val;
591 smedia_reqcheck_format_status_t reqcheck_format_status;
592 smedia_retcheck_format_status_t *retcheck_format_status;
593 smedia_reterror_t *reterror;
594 door_arg_t door_args;
595 char rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
597 /* Check for valid handle */
598 if (handle == NULL) {
599 DPRINTF("Null Handle\n");
600 errno = EINVAL;
601 return (-1);
603 if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
604 DPRINTF("Invalid signature in handle.\n");
605 errno = EINVAL;
606 return (-1);
608 reqcheck_format_status.cnum = SMEDIA_CNUM_CHECK_FORMAT_STATUS;
609 door_args.data_ptr = (char *)&reqcheck_format_status;
610 door_args.data_size = sizeof (smedia_services_t);
611 door_args.desc_ptr = NULL;
612 door_args.desc_num = 0;
613 door_args.rbuf = rbuf;
614 door_args.rsize = sizeof (rbuf);
616 ret_val = door_call(handle->sm_door, &door_args);
617 if (ret_val < 0) {
618 perror("door_call");
619 return (-1);
621 retcheck_format_status =
622 (smedia_retcheck_format_status_t *)((void *)door_args.data_ptr);
623 reterror = (smedia_reterror_t *)((void *)door_args.data_ptr);
624 if (reterror->cnum == SMEDIA_CNUM_ERROR) {
625 DPRINTF1("Error in check_format_status. errnum = 0x%x \n",
626 reterror->errnum);
627 errno = reterror->errnum;
628 return (-1);
630 return (retcheck_format_status->percent_complete);
633 int32_t
634 _m_uscsi_cmd(rmedia_handle_t *handle, struct uscsi_cmd *ucmd)
636 int32_t ret_val;
637 smedia_requscsi_cmd_t requscsi_cmd;
638 smedia_retuscsi_cmd_t *retuscsi_cmd;
639 smedia_reterror_t *reterror;
640 door_arg_t door_args;
641 char rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
643 /* Check for valid handle */
644 if (handle == NULL) {
645 DPRINTF("Null Handle\n");
646 errno = EINVAL;
647 return (-1);
649 if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
650 DPRINTF("Invalid signature in handle.\n");
651 errno = EINVAL;
652 return (-1);
655 * We will be validating the user supplied buffer lengths and
656 * buffer pointers.
658 if (ucmd->uscsi_cdblen > MAX_CDB_LEN) {
659 DPRINTF("Invalid cdblen specified.\n");
660 errno = EINVAL;
661 return (-1);
663 if ((ucmd->uscsi_flags & USCSI_RQENABLE) &&
664 (ucmd->uscsi_rqlen > MAX_RQ_LEN)) {
665 DPRINTF("Invalid rqlen specified.\n");
666 errno = EINVAL;
667 return (-1);
669 if (ucmd->uscsi_cdb == NULL) {
670 DPRINTF("cdb buffer is NULL.\n");
671 errno = EINVAL;
672 return (-1);
674 if ((ucmd->uscsi_buflen) && (ucmd->uscsi_bufaddr == NULL)) {
675 DPRINTF("bufaddr is NULL.\n");
676 errno = EINVAL;
677 return (-1);
679 if ((ucmd->uscsi_flags & USCSI_RQENABLE) &&
680 (ucmd->uscsi_rqbuf == NULL)) {
681 DPRINTF("rqbuf is NULL.\n");
682 errno = EINVAL;
683 return (-1);
686 * Check if another thread is doing an IO with same handle.
687 * In that case we block here.
689 (void) mutex_lock(&handle->sm_bufmutex);
690 ret_val = remap_shared_buf(handle, ucmd->uscsi_buflen,
691 ucmd->uscsi_bufaddr);
692 if (ret_val != 0) {
693 DPRINTF("remap of shared buf failed.\n");
694 goto error;
697 requscsi_cmd.cnum = SMEDIA_CNUM_USCSI_CMD;
698 requscsi_cmd.uscsi_flags = ucmd->uscsi_flags;
699 requscsi_cmd.uscsi_timeout = ucmd->uscsi_timeout;
700 requscsi_cmd.uscsi_buflen = ucmd->uscsi_buflen;
701 requscsi_cmd.uscsi_cdblen = ucmd->uscsi_cdblen;
702 requscsi_cmd.uscsi_rqlen = ucmd->uscsi_rqlen;
705 * The uscsi_buflen has been validated in the call to
706 * remap_shared_buf() done earlier.
708 /* Check for write */
709 if (!(ucmd->uscsi_flags & USCSI_READ)) {
710 bcopy(ucmd->uscsi_bufaddr, handle->sm_buf, ucmd->uscsi_buflen);
713 bcopy(ucmd->uscsi_cdb, requscsi_cmd.uscsi_cdb, ucmd->uscsi_cdblen);
715 door_args.data_ptr = (char *)&requscsi_cmd;
716 door_args.data_size = sizeof (smedia_services_t);
717 door_args.desc_ptr = NULL;
718 door_args.desc_num = 0;
719 door_args.rbuf = rbuf;
720 door_args.rsize = sizeof (rbuf);
722 ret_val = door_call(handle->sm_door, &door_args);
723 if (ret_val < 0) {
724 perror("door_call");
725 goto error;
727 retuscsi_cmd = (smedia_retuscsi_cmd_t *)((void *)door_args.data_ptr);
728 reterror = (smedia_reterror_t *)((void *)door_args.data_ptr);
729 if (reterror->cnum == SMEDIA_CNUM_ERROR) {
730 DPRINTF1(
731 "Error in uscsi cmd. errnum = 0x%x\n", reterror->errnum);
732 errno = reterror->errnum;
733 goto error;
735 ucmd->uscsi_status = retuscsi_cmd->uscsi_status;
736 ucmd->uscsi_resid = retuscsi_cmd->uscsi_resid;
737 ucmd->uscsi_rqstatus = retuscsi_cmd->uscsi_rqstatus;
738 ucmd->uscsi_rqresid = retuscsi_cmd->uscsi_rqresid;
739 if ((ucmd->uscsi_flags & USCSI_RQENABLE) &&
740 (ucmd->uscsi_rqbuf != NULL)) {
741 bcopy(retuscsi_cmd->uscsi_rqbuf, ucmd->uscsi_rqbuf,
742 ucmd->uscsi_rqlen);
744 errno = retuscsi_cmd->uscsi_errno;
745 if (errno) {
746 goto error;
749 if (ucmd->uscsi_resid > ucmd->uscsi_buflen) {
751 * Invalid resid value. return error.
753 errno = EINVAL;
754 goto error;
756 if (ucmd->uscsi_flags & USCSI_READ) {
757 (void) memcpy(ucmd->uscsi_bufaddr,
758 handle->sm_buf, ucmd->uscsi_buflen - ucmd->uscsi_resid);
760 (void) mutex_unlock(&handle->sm_bufmutex);
761 #ifdef DEBUG
762 if (retuscsi_cmd->uscsi_retval || ucmd->uscsi_status)
763 DPRINTF2("Error in uscsi_cmd: retval=0x%x uscsi_status=0x%x\n",
764 retuscsi_cmd->uscsi_retval, ucmd->uscsi_status);
765 #endif
766 return (retuscsi_cmd->uscsi_retval);
767 error:
768 (void) mutex_unlock(&handle->sm_bufmutex);
769 return (-1);
772 int32_t
773 remap_shared_buf(rmedia_handle_t *handle, size_t buf_size, char *buffer)
775 char rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
776 char fname[128];
777 smedia_reqset_shfd_t reqset_shfd;
778 smedia_reterror_t *reterror;
779 int ret_val, fd;
780 door_arg_t door_args;
781 door_desc_t ddesc[2];
782 char *fbuf;
783 size_t shared_bufsize;
784 off_t file_size, ret;
786 if (handle->sm_bufsize >= buf_size)
787 return (0);
788 shared_bufsize = ((buf_size + BUF_SIZE_MULTIPLE - 1)/BUF_SIZE_MULTIPLE)
789 * BUF_SIZE_MULTIPLE;
790 if (handle->sm_buffd != -1) {
791 /* extend the file and re-map */
792 fd = handle->sm_buffd;
793 ret_val = munmap(handle->sm_buf, handle->sm_bufsize);
794 if (ret_val != 0) {
795 DPRINTF1("remap:munmap failed. errno = 0x%x\n", errno);
796 (void) close(fd);
797 handle->sm_buf = NULL;
798 handle->sm_bufsize = 0;
799 handle->sm_buffd = -1;
800 return (errno);
802 file_size = lseek(fd, 0, SEEK_END);
803 if (file_size == -1) {
804 DPRINTF1("remap:lseek failed. errno = 0x%x\n", errno);
805 return (errno);
807 handle->sm_buf = NULL;
808 handle->sm_bufsize = 0;
809 handle->sm_buffd = -1;
810 } else {
811 /* create a new file and mapping */
812 (void) sprintf(fname, "/tmp/libsmedia_mmaped_file_XXXXXX");
813 fd = mkstemp(fname);
814 if (fd == -1) {
815 DPRINTF1("remap:mktemp failed. errno = 0x%x\n", errno);
816 return (errno);
818 ret_val = unlink(fname);
819 if (ret_val == -1) {
820 DPRINTF1("remap:unlink failed. errno = 0x%x\n", errno);
821 (void) close(fd);
822 return (errno);
824 file_size = 0;
826 /* Need to start at the beginning of the file when enlarging */
827 ret = lseek(fd, 0, SEEK_SET);
828 if (ret == -1) {
829 DPRINTF1("remap:lseek failed. errno = 0x%x\n", errno);
830 return (errno);
832 while (file_size < shared_bufsize) {
833 ret_val = write(fd, buffer, buf_size);
834 if (ret_val != buf_size) {
835 DPRINTF1("remap:write failed. errno = 0x%x\n", errno);
836 (void) close(fd);
837 return (errno);
839 file_size += buf_size;
841 fbuf = mmap(NULL, shared_bufsize, PROT_READ | PROT_WRITE,
842 MAP_SHARED, fd, 0);
843 if (fbuf == (char *)-1) {
844 perror("mmap failed");
845 (void) close(fd);
846 return (errno);
849 reqset_shfd.cnum = SMEDIA_CNUM_SET_SHFD;
850 reqset_shfd.fdbuf_len = shared_bufsize;
851 ddesc[0].d_data.d_desc.d_descriptor = fd;
852 ddesc[0].d_attributes = DOOR_DESCRIPTOR;
853 door_args.data_ptr = (char *)&reqset_shfd;
854 door_args.data_size = sizeof (reqset_shfd);
855 door_args.desc_ptr = &ddesc[0];
856 door_args.desc_num = 1;
857 door_args.rbuf = rbuf;
858 door_args.rsize = sizeof (rbuf);
860 ret_val = door_call(handle->sm_door, &door_args);
861 if (ret_val < 0) {
862 perror("door_call");
863 (void) close(fd);
864 return (-1);
866 reterror = (smedia_reterror_t *)((void *)door_args.data_ptr);
867 if (reterror->cnum == SMEDIA_CNUM_ERROR) {
868 DPRINTF1("Error in set shfd. errnum = 0x%x\n",
869 reterror->errnum);
870 errno = reterror->errnum;
871 (void) close(fd);
872 return (errno);
874 handle->sm_buffd = fd;
875 handle->sm_buf = fbuf;
876 handle->sm_bufsize = shared_bufsize;
877 DPRINTF("Returned successful from remap shared buf routine.\n");
878 return (0);