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 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 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 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 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 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 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 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 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 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 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 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 582 _m_version_no(void) 583 { 584 return (SM_SCSI_VERSION_1); 585 } 586 587 int32_t 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 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 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