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 /*
28 * s_generic.c :
29 * This file contains generic SCSI related functions for scsi plug-in
30 * for libsm.so.
31 */
32
33
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"
48
49
50 static int32_t remap_shared_buf(rmedia_handle_t *, size_t, char *);
51
52 #define W_E_MASK 0x80
53 #define BUF_SIZE_MULTIPLE 0x2000
54
55 int32_t
_m_get_media_info(rmedia_handle_t * handle,void * ip)56 _m_get_media_info(rmedia_handle_t *handle, void *ip)
57 {
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)];
65
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);
72 }
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);
80 }
81 (void) memset((void *) medinfo, 0, sizeof (smmedium_prop_t));
82
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);
90
91 ret_val = door_call(handle->sm_door, &door_args);
92 if (ret_val < 0) {
93 perror("door_call");
94 return (-1);
95 }
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);
104 }
105
106 *medinfo = retget_medium_property->smprop;
107
108 return (0);
109 }
110
111 int32_t
_m_get_device_info(rmedia_handle_t * handle,void * ip)112 _m_get_device_info(rmedia_handle_t *handle, void *ip)
113 {
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;
122
123 /* Check for valid handle */
124 if (handle == NULL) {
125 DPRINTF("Null Handle\n");
126 errno = EINVAL;
127 return (-1);
128 }
129 if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
130 DPRINTF("Invalid signature in handle.\n");
131 errno = EINVAL;
132 return (-1);
133 }
134
135 vendor_name = (char *)malloc(9);
136 if (vendor_name == NULL) {
137 if (!errno)
138 errno = ENOMEM;
139 return (-1);
140 }
141 product_name = (char *)malloc(17);
142 if (product_name == NULL) {
143 free(vendor_name);
144 if (!errno)
145 errno = ENOMEM;
146 return (-1);
147 }
148
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);
156 }
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);
164
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);
172 }
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);
184 }
185
186 dev_info->sm_vendor_name = vendor_name;
187 dev_info->sm_product_name = product_name;
188 dev_info->sm_firmware_version = fw_version;
189
190
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;
200
201 dev_info->sm_interface_type = retget_device_info->sm_interface_type;
202
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 */
208
209 return (0);
210 }
211
212 int32_t
_m_free_device_info(rmedia_handle_t * handle,void * ip)213 _m_free_device_info(rmedia_handle_t *handle, void *ip)
214 {
215 struct smdevice_info *dev_info = ip;
216
217 /* Check for valid handle */
218 if (handle == NULL) {
219 DPRINTF("Null Handle\n");
220 errno = EINVAL;
221 return (-1);
222 }
223 if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
224 DPRINTF("Invalid signature in handle.\n");
225 errno = EINVAL;
226 return (-1);
227 }
228
229 free(dev_info->sm_vendor_name);
230 free(dev_info->sm_product_name);
231 free(dev_info->sm_firmware_version);
232 return (0);
233 }
234
235 int32_t
_m_raw_write(rmedia_handle_t * handle,void * i_p)236 _m_raw_write(rmedia_handle_t *handle, void *i_p)
237 {
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)];
245
246 /* Check for valid handle */
247 if (handle == NULL) {
248 DPRINTF("Null Handle\n");
249 errno = EINVAL;
250 return (-1);
251 }
252 if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
253 DPRINTF("Invalid signature in handle.\n");
254 errno = EINVAL;
255 return (-1);
256 }
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);
270
271 ret_val = door_call(handle->sm_door, &door_args);
272 if (ret_val < 0) {
273 perror("door_call");
274 goto error;
275 }
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;
284 }
285 (void) mutex_unlock(&handle->sm_bufmutex);
286 return (retraw_write->nbytes);
287
288 error:
289 (void) mutex_unlock(&handle->sm_bufmutex);
290 return (-1);
291 }
292
293 size_t
_m_raw_read(rmedia_handle_t * handle,void * i_p)294 _m_raw_read(rmedia_handle_t *handle, void *i_p)
295 {
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)];
303
304 /* Check for valid handle */
305 if (handle == NULL) {
306 DPRINTF("Null Handle\n");
307 errno = EINVAL;
308 return (size_t)(-1);
309 }
310 if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
311 DPRINTF("Invalid signature in handle.\n");
312 return (size_t)(-1);
313 }
314 /*
315 * Check if another thread is doing an IO with same handle.
316 * In that case ww block here.
317 */
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;
321
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);
331
332 ret_val = door_call(handle->sm_door, &door_args);
333 if (ret_val < 0) {
334 perror("door_call");
335 goto error;
336 }
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) {
340 /*
341 * free(rbuf);
342 */
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;
348 }
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);
353
354 error:
355 (void) mutex_unlock(&handle->sm_bufmutex);
356 return (size_t)(-1);
357
358 }
359
360 size_t
_m_media_format(rmedia_handle_t * handle,void * ip)361 _m_media_format(rmedia_handle_t *handle, void *ip)
362 {
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)];
369
370 /* Check for valid handle */
371 if (handle == NULL) {
372 DPRINTF("Null Handle\n");
373 errno = EINVAL;
374 return (size_t)(-1);
375 }
376 if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
377 DPRINTF("Invalid signature in handle.\n");
378 errno = EINVAL;
379 return (size_t)(-1);
380 }
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);
390
391 ret_val = door_call(handle->sm_door, &door_args);
392 if (ret_val < 0) {
393 perror("door_call");
394 return (size_t)(-1);
395 }
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);
401 }
402 return (0);
403 }
404
405 int32_t
_m_get_media_status(rmedia_handle_t * handle,void * ip)406 _m_get_media_status(rmedia_handle_t *handle, void *ip)
407 {
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)];
415
416 /* Check for valid handle */
417 if (handle == NULL) {
418 DPRINTF("Null Handle\n");
419 errno = EINVAL;
420 return (-1);
421 }
422 if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
423 DPRINTF("Invalid signature in handle.\n");
424 errno = EINVAL;
425 return (-1);
426 }
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);
434
435 ret_val = door_call(handle->sm_door, &door_args);
436 if (ret_val < 0) {
437 perror("door_call");
438 return (-1);
439 }
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);
448 }
449 (void) memcpy((char *)wp, (char *)&retget_protection_status->prot_state,
450 sizeof (smwp_state_t));
451 return (0);
452 }
453
454 int32_t
_m_set_media_status(rmedia_handle_t * handle,void * ip)455 _m_set_media_status(rmedia_handle_t *handle, void *ip)
456 {
457
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)];
464
465 /* Check for valid handle */
466 if (handle == NULL) {
467 DPRINTF("Null Handle\n");
468 errno = EINVAL;
469 return (-1);
470 }
471 if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
472 DPRINTF("Invalid signature in handle.\n");
473 errno = EINVAL;
474 return (-1);
475 }
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);
484
485 ret_val = door_call(handle->sm_door, &door_args);
486 if (ret_val < 0) {
487 perror("door_call");
488 return (-1);
489 }
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);
496 }
497 return (0);
498 }
499
500 int32_t
_m_reassign_block(rmedia_handle_t * handle,void * ip)501 _m_reassign_block(rmedia_handle_t *handle, void *ip)
502 {
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)];
510
511 /* Check for valid handle */
512 if (handle == NULL) {
513 DPRINTF("Null Handle\n");
514 errno = EINVAL;
515 return (-1);
516 }
517 if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
518 DPRINTF("Invalid signature in handle.\n");
519 errno = EINVAL;
520 return (-1);
521 }
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);
532
533 ret_val = door_call(handle->sm_door, &door_args);
534 if (ret_val < 0) {
535 perror("door_call");
536 return (-1);
537 }
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);
544 }
545 return (0);
546 }
547
548 /* ARGSUSED1 */
549 int32_t
_m_eject(rmedia_handle_t * handle,void * ip)550 _m_eject(rmedia_handle_t *handle, void *ip)
551 {
552 int32_t fd;
553
554 /* Check for valid handle */
555 if (handle == NULL) {
556 DPRINTF("Null Handle\n");
557 errno = EINVAL;
558 return (-1);
559 }
560 if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
561 DPRINTF("Invalid signature in handle.\n");
562 errno = EINVAL;
563 return (-1);
564 }
565 fd = handle->sm_fd;
566 return (ioctl(fd, DKIOCEJECT));
567 }
568
569 int32_t
_m_device_type(ushort_t ctype,ushort_t mtype)570 _m_device_type(ushort_t ctype, ushort_t mtype)
571 {
572 if ((ctype == DKC_SCSI_CCS) ||
573 (ctype == DKC_MD21) ||
574 (ctype == DKC_CDROM)) {
575 if (mtype == 0)
576 return (0);
577 }
578 return (-1);
579 }
580
581 int32_t
_m_version_no(void)582 _m_version_no(void)
583 {
584 return (SM_SCSI_VERSION_1);
585 }
586
587 int32_t
_m_check_format_status(rmedia_handle_t * handle,void * ip)588 _m_check_format_status(rmedia_handle_t *handle, void *ip)
589 {
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)];
596 #ifdef lint
597 ip = ip;
598 #endif
599
600 /* Check for valid handle */
601 if (handle == NULL) {
602 DPRINTF("Null Handle\n");
603 errno = EINVAL;
604 return (-1);
605 }
606 if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
607 DPRINTF("Invalid signature in handle.\n");
608 errno = EINVAL;
609 return (-1);
610 }
611 reqcheck_format_status.cnum = SMEDIA_CNUM_CHECK_FORMAT_STATUS;
612 door_args.data_ptr = (char *)&reqcheck_format_status;
613 door_args.data_size = sizeof (smedia_services_t);
614 door_args.desc_ptr = NULL;
615 door_args.desc_num = 0;
616 door_args.rbuf = rbuf;
617 door_args.rsize = sizeof (rbuf);
618
619 ret_val = door_call(handle->sm_door, &door_args);
620 if (ret_val < 0) {
621 perror("door_call");
622 return (-1);
623 }
624 retcheck_format_status =
625 (smedia_retcheck_format_status_t *)((void *)door_args.data_ptr);
626 reterror = (smedia_reterror_t *)((void *)door_args.data_ptr);
627 if (reterror->cnum == SMEDIA_CNUM_ERROR) {
628 DPRINTF1("Error in check_format_status. errnum = 0x%x \n",
629 reterror->errnum);
630 errno = reterror->errnum;
631 return (-1);
632 }
633 return (retcheck_format_status->percent_complete);
634 }
635
636 int32_t
_m_uscsi_cmd(rmedia_handle_t * handle,struct uscsi_cmd * ucmd)637 _m_uscsi_cmd(rmedia_handle_t *handle, struct uscsi_cmd *ucmd)
638 {
639 int32_t ret_val;
640 smedia_requscsi_cmd_t requscsi_cmd;
641 smedia_retuscsi_cmd_t *retuscsi_cmd;
642 smedia_reterror_t *reterror;
643 door_arg_t door_args;
644 char rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
645
646 /* Check for valid handle */
647 if (handle == NULL) {
648 DPRINTF("Null Handle\n");
649 errno = EINVAL;
650 return (-1);
651 }
652 if (handle->sm_signature != LIBSMEDIA_SIGNATURE) {
653 DPRINTF("Invalid signature in handle.\n");
654 errno = EINVAL;
655 return (-1);
656 }
657 /*
658 * We will be validating the user supplied buffer lengths and
659 * buffer pointers.
660 */
661 if (ucmd->uscsi_cdblen > MAX_CDB_LEN) {
662 DPRINTF("Invalid cdblen specified.\n");
663 errno = EINVAL;
664 return (-1);
665 }
666 if ((ucmd->uscsi_flags & USCSI_RQENABLE) &&
667 (ucmd->uscsi_rqlen > MAX_RQ_LEN)) {
668 DPRINTF("Invalid rqlen specified.\n");
669 errno = EINVAL;
670 return (-1);
671 }
672 if (ucmd->uscsi_cdb == NULL) {
673 DPRINTF("cdb buffer is NULL.\n");
674 errno = EINVAL;
675 return (-1);
676 }
677 if ((ucmd->uscsi_buflen) && (ucmd->uscsi_bufaddr == NULL)) {
678 DPRINTF("bufaddr is NULL.\n");
679 errno = EINVAL;
680 return (-1);
681 }
682 if ((ucmd->uscsi_flags & USCSI_RQENABLE) &&
683 (ucmd->uscsi_rqbuf == NULL)) {
684 DPRINTF("rqbuf is NULL.\n");
685 errno = EINVAL;
686 return (-1);
687 }
688 /*
689 * Check if another thread is doing an IO with same handle.
690 * In that case we block here.
691 */
692 (void) mutex_lock(&handle->sm_bufmutex);
693 ret_val = remap_shared_buf(handle, ucmd->uscsi_buflen,
694 ucmd->uscsi_bufaddr);
695 if (ret_val != 0) {
696 DPRINTF("remap of shared buf failed.\n");
697 goto error;
698 }
699
700 requscsi_cmd.cnum = SMEDIA_CNUM_USCSI_CMD;
701 requscsi_cmd.uscsi_flags = ucmd->uscsi_flags;
702 requscsi_cmd.uscsi_timeout = ucmd->uscsi_timeout;
703 requscsi_cmd.uscsi_buflen = ucmd->uscsi_buflen;
704 requscsi_cmd.uscsi_cdblen = ucmd->uscsi_cdblen;
705 requscsi_cmd.uscsi_rqlen = ucmd->uscsi_rqlen;
706
707 /*
708 * The uscsi_buflen has been validated in the call to
709 * remap_shared_buf() done earlier.
710 */
711 /* Check for write */
712 if (!(ucmd->uscsi_flags & USCSI_READ)) {
713 bcopy(ucmd->uscsi_bufaddr, handle->sm_buf, ucmd->uscsi_buflen);
714 }
715
716 bcopy(ucmd->uscsi_cdb, requscsi_cmd.uscsi_cdb, ucmd->uscsi_cdblen);
717
718 door_args.data_ptr = (char *)&requscsi_cmd;
719 door_args.data_size = sizeof (smedia_services_t);
720 door_args.desc_ptr = NULL;
721 door_args.desc_num = 0;
722 door_args.rbuf = rbuf;
723 door_args.rsize = sizeof (rbuf);
724
725 ret_val = door_call(handle->sm_door, &door_args);
726 if (ret_val < 0) {
727 perror("door_call");
728 goto error;
729 }
730 retuscsi_cmd = (smedia_retuscsi_cmd_t *)((void *)door_args.data_ptr);
731 reterror = (smedia_reterror_t *)((void *)door_args.data_ptr);
732 if (reterror->cnum == SMEDIA_CNUM_ERROR) {
733 DPRINTF1(
734 "Error in uscsi cmd. errnum = 0x%x\n", reterror->errnum);
735 errno = reterror->errnum;
736 goto error;
737 }
738 ucmd->uscsi_status = retuscsi_cmd->uscsi_status;
739 ucmd->uscsi_resid = retuscsi_cmd->uscsi_resid;
740 ucmd->uscsi_rqstatus = retuscsi_cmd->uscsi_rqstatus;
741 ucmd->uscsi_rqresid = retuscsi_cmd->uscsi_rqresid;
742 if ((ucmd->uscsi_flags & USCSI_RQENABLE) &&
743 (ucmd->uscsi_rqbuf != NULL)) {
744 bcopy(retuscsi_cmd->uscsi_rqbuf, ucmd->uscsi_rqbuf,
745 ucmd->uscsi_rqlen);
746 }
747 errno = retuscsi_cmd->uscsi_errno;
748 if (errno) {
749 goto error;
750 }
751
752 if (ucmd->uscsi_resid > ucmd->uscsi_buflen) {
753 /*
754 * Invalid resid value. return error.
755 */
756 errno = EINVAL;
757 goto error;
758 }
759 if (ucmd->uscsi_flags & USCSI_READ) {
760 (void) memcpy(ucmd->uscsi_bufaddr,
761 handle->sm_buf, ucmd->uscsi_buflen - ucmd->uscsi_resid);
762 }
763 (void) mutex_unlock(&handle->sm_bufmutex);
764 #ifdef DEBUG
765 if (retuscsi_cmd->uscsi_retval || ucmd->uscsi_status)
766 DPRINTF2("Error in uscsi_cmd: retval=0x%x uscsi_status=0x%x\n",
767 retuscsi_cmd->uscsi_retval, ucmd->uscsi_status);
768 #endif
769 return (retuscsi_cmd->uscsi_retval);
770 error:
771 (void) mutex_unlock(&handle->sm_bufmutex);
772 return (-1);
773 }
774
775 int32_t
remap_shared_buf(rmedia_handle_t * handle,size_t buf_size,char * buffer)776 remap_shared_buf(rmedia_handle_t *handle, size_t buf_size, char *buffer)
777 {
778 char rbuf[sizeof (smedia_services_t) + sizeof (door_desc_t)];
779 char fname[128];
780 smedia_reqset_shfd_t reqset_shfd;
781 smedia_reterror_t *reterror;
782 int ret_val, fd;
783 door_arg_t door_args;
784 door_desc_t ddesc[2];
785 char *fbuf;
786 size_t shared_bufsize;
787 off_t file_size, ret;
788
789 if (handle->sm_bufsize >= buf_size)
790 return (0);
791 shared_bufsize = ((buf_size + BUF_SIZE_MULTIPLE - 1)/BUF_SIZE_MULTIPLE)
792 * BUF_SIZE_MULTIPLE;
793 if (handle->sm_buffd != -1) {
794 /* extend the file and re-map */
795 fd = handle->sm_buffd;
796 ret_val = munmap(handle->sm_buf, handle->sm_bufsize);
797 if (ret_val != 0) {
798 DPRINTF1("remap:munmap failed. errno = 0x%x\n", errno);
799 (void) close(fd);
800 handle->sm_buf = NULL;
801 handle->sm_bufsize = 0;
802 handle->sm_buffd = -1;
803 return (errno);
804 }
805 file_size = lseek(fd, 0, SEEK_END);
806 if (file_size == -1) {
807 DPRINTF1("remap:lseek failed. errno = 0x%x\n", errno);
808 return (errno);
809 }
810 handle->sm_buf = NULL;
811 handle->sm_bufsize = 0;
812 handle->sm_buffd = -1;
813 } else {
814 /* create a new file and mapping */
815 (void) sprintf(fname, "/tmp/libsmedia_mmaped_file_XXXXXX");
816 fd = mkstemp(fname);
817 if (fd == -1) {
818 DPRINTF1("remap:mktemp failed. errno = 0x%x\n", errno);
819 return (errno);
820 }
821 ret_val = unlink(fname);
822 if (ret_val == -1) {
823 DPRINTF1("remap:unlink failed. errno = 0x%x\n", errno);
824 (void) close(fd);
825 return (errno);
826 }
827 file_size = 0;
828 }
829 /* Need to start at the beginning of the file when enlarging */
830 ret = lseek(fd, 0, SEEK_SET);
831 if (ret == -1) {
832 DPRINTF1("remap:lseek failed. errno = 0x%x\n", errno);
833 return (errno);
834 }
835 while (file_size < shared_bufsize) {
836 ret_val = write(fd, buffer, buf_size);
837 if (ret_val != buf_size) {
838 DPRINTF1("remap:write failed. errno = 0x%x\n", errno);
839 (void) close(fd);
840 return (errno);
841 }
842 file_size += buf_size;
843 }
844 fbuf = mmap(NULL, shared_bufsize, PROT_READ | PROT_WRITE,
845 MAP_SHARED, fd, 0);
846 if (fbuf == (char *)-1) {
847 perror("mmap failed");
848 (void) close(fd);
849 return (errno);
850 }
851
852 reqset_shfd.cnum = SMEDIA_CNUM_SET_SHFD;
853 reqset_shfd.fdbuf_len = shared_bufsize;
854 ddesc[0].d_data.d_desc.d_descriptor = fd;
855 ddesc[0].d_attributes = DOOR_DESCRIPTOR;
856 door_args.data_ptr = (char *)&reqset_shfd;
857 door_args.data_size = sizeof (reqset_shfd);
858 door_args.desc_ptr = &ddesc[0];
859 door_args.desc_num = 1;
860 door_args.rbuf = rbuf;
861 door_args.rsize = sizeof (rbuf);
862
863 ret_val = door_call(handle->sm_door, &door_args);
864 if (ret_val < 0) {
865 perror("door_call");
866 (void) close(fd);
867 return (-1);
868 }
869 reterror = (smedia_reterror_t *)((void *)door_args.data_ptr);
870 if (reterror->cnum == SMEDIA_CNUM_ERROR) {
871 DPRINTF1("Error in set shfd. errnum = 0x%x\n",
872 reterror->errnum);
873 errno = reterror->errnum;
874 (void) close(fd);
875 return (errno);
876 }
877 handle->sm_buffd = fd;
878 handle->sm_buf = fbuf;
879 handle->sm_bufsize = shared_bufsize;
880 DPRINTF("Returned successful from remap shared buf routine.\n");
881 return (0);
882 }
883