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