1/* 2 File: AppleSCSITargetEmulator.h 3 4 Contains: 5 6 Version: 1.0.0 7 8 Copyright: Copyright (c) 2007 by Apple Inc., All Rights Reserved. 9 10Disclaimer:IMPORTANT: This Apple software is supplied to you by Apple Inc. 11("Apple") in consideration of your agreement to the following terms, and your use, 12installation, modification or redistribution of this Apple software constitutes acceptance 13of these terms. If you do not agree with these terms, please do not use, install, modify or 14redistribute this Apple software. 15 16In consideration of your agreement to abide by the following terms, and subject 17to these terms, Apple grants you a personal, non-exclusive license, under Apple's 18copyrights in this original Apple software (the "Apple Software"), to use, reproduce, 19modify and redistribute the Apple Software, with or without modifications, in source and/or 20binary forms; provided that if you redistribute the Apple Software in its entirety 21and without modifications, you must retain this notice and the following text 22and disclaimers in all such redistributions of the Apple Software. Neither the 23name, trademarks, service marks or logos of Apple Inc. may be used to 24endorse or promote products derived from the Apple Software without specific prior 25written permission from Apple. Except as expressly stated in this notice, no 26other rights or licenses, express or implied, are granted by Apple herein, 27including but not limited to any patent rights that may be infringed by your derivative 28works or by other works in which the Apple Software may be incorporated. 29 30The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, 31EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, 32MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE 33OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. IN NO EVENT SHALL APPLE 34BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 35NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 36OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, 37REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED 38AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT 39LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 40*/ 41 42 43//----------------------------------------------------------------------------- 44// Includes 45//----------------------------------------------------------------------------- 46 47#include "AppleSCSITargetEmulator.h" 48#include "AppleSCSILogicalUnitEmulator.h" 49#include "AppleSCSIPDT00Emulator.h" 50#include "AppleSCSIPDT03Emulator.h" 51 52#include <IOKit/scsi/SCSICmds_INQUIRY_Definitions.h> 53#include <IOKit/scsi/SCSICmds_REQUEST_SENSE_Defs.h> 54#include <IOKit/scsi/SCSICmds_REPORT_LUNS_Definitions.h> 55#include <IOKit/scsi/SCSICommandOperationCodes.h> 56#include <IOKit/IOLocks.h> 57 58 59//----------------------------------------------------------------------------- 60// Macros 61//----------------------------------------------------------------------------- 62 63#define DEBUG 1 64#define DEBUG_ASSERT_COMPONENT_NAME_STRING "TargetEmulator" 65 66#if DEBUG 67#define TARGET_EMULATOR_DEBUGGING_LEVEL 4 68#endif 69 70#include "DebugSupport.h" 71 72#if ( TARGET_EMULATOR_DEBUGGING_LEVEL >= 1 ) 73#define PANIC_NOW(x) panic x 74#else 75#define PANIC_NOW(x) 76#endif 77 78#if ( TARGET_EMULATOR_DEBUGGING_LEVEL >= 2 ) 79#define ERROR_LOG(x) IOLog x; IOSleep(1) 80#else 81#define ERROR_LOG(x) 82#endif 83 84#if ( TARGET_EMULATOR_DEBUGGING_LEVEL >= 3 ) 85#define STATUS_LOG(x) IOLog x; IOSleep(1) 86#else 87#define STATUS_LOG(x) 88#endif 89 90#if ( TARGET_EMULATOR_DEBUGGING_LEVEL >= 4 ) 91#define COMMAND_LOG(x) IOLog x; IOSleep(1) 92#else 93#define COMMAND_LOG(x) 94#endif 95 96 97#define super OSObject 98OSDefineMetaClassAndStructors ( AppleSCSITargetEmulator, OSObject ); 99 100 101//----------------------------------------------------------------------------- 102// Prototypes 103//----------------------------------------------------------------------------- 104 105static SInt32 106CompareLUNs ( 107 const OSMetaClassBase * obj1, 108 const OSMetaClassBase * obj2, 109 void * ref ); 110 111 112//----------------------------------------------------------------------------- 113// Globals 114//----------------------------------------------------------------------------- 115 116SCSICmd_INQUIRY_StandardData gInquiryData = 117{ 118 kINQUIRY_PERIPHERAL_QUALIFIER_NotSupported | kINQUIRY_PERIPHERAL_TYPE_UnknownOrNoDeviceType, // PERIPHERAL_DEVICE_TYPE 119 0, // RMB; 120 5, // VERSION 121 2, // RESPONSE_DATA_FORMAT 122 sizeof ( SCSICmd_INQUIRY_StandardData ) - 5, // ADDITIONAL_LENGTH 123 0, // SCCSReserved 124 0, // flags1 125 0, // flags2 126 "APPLE ", 127 "SCSI Emulator ", 128 "1.0", 129}; 130 131SCSI_Sense_Data 132AppleSCSITargetEmulator::sBadLUNSenseData = 133{ 134 /* VALID_RESPONSE_CODE */ 0x80 | kSENSE_RESPONSE_CODE_Current_Errors, 135 /* SEGMENT_NUMBER */ 0x00, // Obsolete 136 /* SENSE_KEY */ kSENSE_KEY_ILLEGAL_REQUEST, 137 /* INFORMATION_1 */ 0x00, 138 /* INFORMATION_2 */ 0x00, 139 /* INFORMATION_3 */ 0x00, 140 /* INFORMATION_4 */ 0x00, 141 /* ADDITIONAL_SENSE_LENGTH */ 0x00, 142 /* COMMAND_SPECIFIC_INFORMATION_1 */ 0x00, 143 /* COMMAND_SPECIFIC_INFORMATION_2 */ 0x00, 144 /* COMMAND_SPECIFIC_INFORMATION_3 */ 0x00, 145 /* COMMAND_SPECIFIC_INFORMATION_4 */ 0x00, 146 /* ADDITIONAL_SENSE_CODE */ 0x25, // LOGICAL UNIT NOT SUPPORTED 147 /* ADDITIONAL_SENSE_CODE_QUALIFIER */ 0x00, 148 /* FIELD_REPLACEABLE_UNIT_CODE */ 0x00, 149 /* SKSV_SENSE_KEY_SPECIFIC_MSB */ 0x00, 150 /* SENSE_KEY_SPECIFIC_MID */ 0x00, 151 /* SENSE_KEY_SPECIFIC_LSB */ 0x00 152}; 153 154SCSI_Sense_Data 155AppleSCSITargetEmulator::sLUNInventoryChangedData = 156{ 157 /* VALID_RESPONSE_CODE */ 0x80 | kSENSE_RESPONSE_CODE_Current_Errors, 158 /* SEGMENT_NUMBER */ 0x00, // Obsolete 159 /* SENSE_KEY */ kSENSE_KEY_UNIT_ATTENTION, 160 /* INFORMATION_1 */ 0x00, 161 /* INFORMATION_2 */ 0x00, 162 /* INFORMATION_3 */ 0x00, 163 /* INFORMATION_4 */ 0x00, 164 /* ADDITIONAL_SENSE_LENGTH */ 0x00, 165 /* COMMAND_SPECIFIC_INFORMATION_1 */ 0x00, 166 /* COMMAND_SPECIFIC_INFORMATION_2 */ 0x00, 167 /* COMMAND_SPECIFIC_INFORMATION_3 */ 0x00, 168 /* COMMAND_SPECIFIC_INFORMATION_4 */ 0x00, 169 /* ADDITIONAL_SENSE_CODE */ 0x3F, // LOGICAL UNIT NOT SUPPORTED 170 /* ADDITIONAL_SENSE_CODE_QUALIFIER */ 0x0E, 171 /* FIELD_REPLACEABLE_UNIT_CODE */ 0x00, 172 /* SKSV_SENSE_KEY_SPECIFIC_MSB */ 0x00, 173 /* SENSE_KEY_SPECIFIC_MID */ 0x00, 174 /* SENSE_KEY_SPECIFIC_LSB */ 0x00 175}; 176 177 178//----------------------------------------------------------------------------- 179// Create 180//----------------------------------------------------------------------------- 181 182AppleSCSITargetEmulator * 183AppleSCSITargetEmulator::Create ( 184 SCSITargetIdentifier targetID ) 185{ 186 187 AppleSCSITargetEmulator * emulator = NULL; 188 bool result = false; 189 190 STATUS_LOG ( ( "AppleSCSITargetEmulator::Create, targetID = %qd\n", targetID ) ); 191 192 emulator = OSTypeAlloc ( AppleSCSITargetEmulator ); 193 require_nonzero ( emulator, ErrorExit ); 194 195 result = emulator->Init ( targetID ); 196 require ( result, ReleaseEmulator ); 197 198 return emulator; 199 200 201ReleaseEmulator: 202 203 204 emulator->release ( ); 205 206 207ErrorExit: 208 209 210 return NULL; 211 212} 213 214 215//----------------------------------------------------------------------------- 216// Init 217//----------------------------------------------------------------------------- 218 219bool 220AppleSCSITargetEmulator::Init ( 221 SCSITargetIdentifier targetID ) 222{ 223 224 bool result = false; 225 AppleSCSIPDT03Emulator * emulator = NULL; 226 227 STATUS_LOG ( ( "AppleSCSITargetEmulator::Init, targetID = %qd\n", targetID ) ); 228 229 result = super::init ( ); 230 require ( result, ErrorExit ); 231 232 fTargetID = targetID; 233 234 fLock = IOLockAlloc ( ); 235 require_nonzero ( fLock, ErrorExit ); 236 237 fLUNs = OSOrderedSet::withCapacity ( 16, CompareLUNs ); 238 require_nonzero ( fLUNs, ReleaseLock ); 239 240 // Allocate LUN0 (PDT 03h device). 241 emulator = OSTypeAlloc ( AppleSCSIPDT03Emulator ); 242 require_nonzero ( emulator, ReleaseSet ); 243 244 emulator->SetLogicalUnitNumber ( 0 ); 245 fLUNs->setObject ( emulator ); 246 emulator->release ( ); 247 248 fLUNDataAvailable = kREPORT_LUNS_HeaderSize + sizeof ( SCSICmd_REPORT_LUNS_LUN_ENTRY ); 249 fLUNReportBufferSize = PAGE_SIZE; 250 251 // Start with a page of memory. Grow as required later. 252 fLUNReportBuffer = ( SCSICmd_REPORT_LUNS_Header * ) IOMalloc ( fLUNReportBufferSize ); 253 require_nonzero ( fLUNReportBuffer, ReleaseSet ); 254 255 bzero ( fLUNReportBuffer, fLUNReportBufferSize ); 256 257 fLUNReportBuffer->LUN_LIST_LENGTH = OSSwapHostToBigInt32 ( sizeof ( SCSICmd_REPORT_LUNS_LUN_ENTRY ) ); 258 fLUNReportBuffer->LUN[0].FIRST_LEVEL_ADDRESSING = OSSwapHostToBigInt16 ( 0 ); 259 260 return true; 261 262 263ReleaseSet: 264 265 266 fLUNs->release ( ); 267 fLUNs = NULL; 268 269 270ReleaseLock: 271 272 273 IOLockFree ( fLock ); 274 fLock = NULL; 275 276 277ErrorExit: 278 279 280 return false; 281 282} 283 284 285//----------------------------------------------------------------------------- 286// free 287//----------------------------------------------------------------------------- 288 289void 290AppleSCSITargetEmulator::free ( void ) 291{ 292 293 STATUS_LOG ( ( "AppleSCSITargetEmulator::free\n" ) ); 294 295 if ( fLUNs != NULL ) 296 { 297 298 fLUNs->release ( ); 299 fLUNs = NULL; 300 301 } 302 303 if ( fLUNReportBuffer != NULL ) 304 { 305 306 IOFree ( fLUNReportBuffer, fLUNReportBufferSize ); 307 fLUNReportBuffer = NULL; 308 fLUNReportBufferSize = 0; 309 310 } 311 312 IOLockFree ( fLock ); 313 fLock = NULL; 314 315 super::free ( ); 316 317} 318 319 320//----------------------------------------------------------------------------- 321// AddLogicalUnit 322//----------------------------------------------------------------------------- 323 324bool 325AppleSCSITargetEmulator::AddLogicalUnit ( 326 SCSILogicalUnitNumber logicalUnit, 327 UInt64 capacity, 328 IOMemoryDescriptor * inquiryBuffer, 329 IOMemoryDescriptor * inquiryPage00Buffer, 330 IOMemoryDescriptor * inquiryPage80Buffer, 331 IOMemoryDescriptor * inquiryPage83Buffer ) 332{ 333 334 AppleSCSIPDT00Emulator * emulator = NULL; 335 bool result = false; 336 bool needsWakeup = false; 337 UInt32 bufferSize = 0; 338 339 STATUS_LOG ( ( "+AppleSCSITargetEmulator::AddLogicalUnit, logicalUnit = %qd, capacity = %qd\n", logicalUnit, capacity ) ); 340 341 require ( ( logicalUnit < 16384 ), ErrorExit ); 342 require ( ( logicalUnit > 0 ), ErrorExit ); 343 344 emulator = AppleSCSIPDT00Emulator::WithCapacity ( capacity ); 345 require_nonzero ( emulator, ErrorExit ); 346 347 emulator->SetLogicalUnitNumber ( logicalUnit ); 348 349 result = emulator->SetDeviceBuffers ( inquiryBuffer, inquiryPage00Buffer, inquiryPage80Buffer, inquiryPage83Buffer ); 350 require ( result, ReleaseEmulator ); 351 352 IOLockLock ( fLock ); 353 354 if ( fState & kTargetStateChangeActiveMask ) 355 { 356 357 fState |= kTargetStateChangeActiveWaitMask; 358 IOLockSleep ( fLock, &fState, THREAD_UNINT ); 359 360 } 361 362 if ( ( fLUNReportBufferSize - fLUNDataAvailable ) < sizeof ( SCSICmd_REPORT_LUNS_LUN_ENTRY ) ) 363 { 364 365 void * buffer = NULL; 366 367 // Double the buffer size. 368 bufferSize = fLUNReportBufferSize << 1; 369 370 // Mark that we're changing state. Anyone who grabs the lock after we 371 // drop it will be forced to sleep and wait until this state change is done. 372 fState |= kTargetStateChangeActiveMask; 373 374 // Drop the lock since IOMalloc might block. 375 IOLockUnlock ( fLock ); 376 377 // Allocate the new buffer. 378 buffer = IOMalloc ( bufferSize ); 379 380 // Reacquire the lock. 381 IOLockLock ( fLock ); 382 383 fState &= ~kTargetStateChangeActiveMask; 384 385 if ( buffer != NULL ) 386 { 387 388 // Free the old buffer. 389 IOFree ( fLUNReportBuffer, fLUNReportBufferSize ); 390 391 // Set the new buffer. 392 fLUNReportBuffer = ( SCSICmd_REPORT_LUNS_Header * ) buffer; 393 fLUNReportBufferSize = bufferSize; 394 395 } 396 397 else 398 { 399 400 if ( fState & kTargetStateChangeActiveWaitMask ) 401 { 402 needsWakeup = true; 403 } 404 405 IOLockUnlock ( fLock ); 406 407 if ( needsWakeup == true ) 408 { 409 IOLockWakeup ( fLock, &fState, false ); 410 } 411 412 goto ReleaseEmulator; 413 414 } 415 416 } 417 418 // Add this LUN emulator to the set. 419 fLUNs->setObject ( emulator ); 420 421 // Rebuild the list. 422 RebuildListOfLUNs ( ); 423 424 if ( fState & kTargetStateChangeActiveWaitMask ) 425 { 426 needsWakeup = true; 427 } 428 429 IOLockUnlock ( fLock ); 430 431 if ( needsWakeup == true ) 432 { 433 IOLockWakeup ( fLock, &fState, false ); 434 } 435 436 emulator->release ( ); 437 438 STATUS_LOG ( ( "-AppleSCSITargetEmulator::AddLogicalUnit\n" ) ); 439 440 return result; 441 442 443ReleaseEmulator: 444 445 446 emulator->release ( ); 447 emulator = NULL; 448 449 450ErrorExit: 451 452 453 STATUS_LOG ( ( "-AppleSCSITargetEmulator::AddLogicalUnit failed!!!\n" ) ); 454 455 return false; 456 457} 458 459 460//----------------------------------------------------------------------------- 461// RemoveLogicalUnit 462//----------------------------------------------------------------------------- 463 464void 465AppleSCSITargetEmulator::RemoveLogicalUnit ( 466 SCSILogicalUnitNumber logicalUnitNumber ) 467{ 468 469 AppleSCSILogicalUnitEmulator * LUN = NULL; 470 int index = 0; 471 int count = 0; 472 473 STATUS_LOG ( ( "AppleSCSITargetEmulator::RemoveLogicalUnit, logicalUnitNumber = %qd\n", logicalUnitNumber ) ); 474 475 IOLockLock ( fLock ); 476 477 count = fLUNs->getCount ( ); 478 479 STATUS_LOG ( ( "count = %d\n", count ) ); 480 481 for ( index = 0; index < count; index++ ) 482 { 483 484 LUN = ( AppleSCSILogicalUnitEmulator * ) fLUNs->getObject ( index ); 485 486 STATUS_LOG ( ( "LUN->GetLogicalUnitNumber ( ) = %qd\n", LUN->GetLogicalUnitNumber ( ) ) ); 487 488 if ( LUN->GetLogicalUnitNumber ( ) == logicalUnitNumber ) 489 { 490 491 fLUNs->removeObject ( LUN ); 492 break; 493 494 } 495 496 } 497 498 // Rebuild the list. 499 RebuildListOfLUNs ( ); 500 501 IOLockUnlock ( fLock ); 502 503} 504 505 506//----------------------------------------------------------------------------- 507// RebuildListOfLUNs 508//----------------------------------------------------------------------------- 509// MUST BE CALLED WITH fLock HELD. 510 511void 512AppleSCSITargetEmulator::RebuildListOfLUNs ( void ) 513{ 514 515 UInt32 index = 0; 516 UInt32 count = 0; 517 UInt32 bufferSize = 0; 518 519 STATUS_LOG ( ( "AppleSCSITargetEmulator::RebuildListOfLUNs\n" ) ); 520 521 // Get the count of emulators (including this new one). 522 count = fLUNs->getCount ( ); 523 524 // Set the bufferSize. 525 bufferSize = count * sizeof ( SCSICmd_REPORT_LUNS_LUN_ENTRY ); 526 527 // Zero the buffer. 528 bzero ( fLUNReportBuffer, fLUNReportBufferSize ); 529 530 // Repopulate the buffer with correct LUN data. 531 fLUNReportBuffer->LUN_LIST_LENGTH = OSSwapHostToBigInt32 ( bufferSize ); 532 533#if USE_LUN_BYTES 534 535 // Repopulate the buffer with correct LUN inventory. 536 for ( index = 0; index < count; index++ ) 537 { 538 539 SCSILogicalUnitBytes logicalUnitBytes = { 0 }; 540 AppleSCSILogicalUnitEmulator * LUN = NULL; 541 542 LUN = ( AppleSCSILogicalUnitEmulator * ) fLUNs->getObject ( index ); 543 LUN->GetLogicalUnitBytes ( &logicalUnitBytes ); 544 545 bcopy ( logicalUnitBytes, &fLUNReportBuffer->LUN[index], sizeof ( SCSILogicalUnitBytes ) ); 546 547 STATUS_LOG ( ( "logicalUnitBytes = 0x%02x 0x%02x, Data = 0x%04x\n", 548 logicalUnitBytes[0], logicalUnitBytes[1], 549 fLUNReportBuffer->LUN[index].FIRST_LEVEL_ADDRESSING ) ); 550 551 } 552 553#else 554 555 // Repopulate the buffer with correct LUN inventory. 556 for ( index = 0; index < count; index++ ) 557 { 558 559 SCSILogicalUnitNumber logicalUnit = 0; 560 AppleSCSILogicalUnitEmulator * LUN = NULL; 561 562 LUN = ( AppleSCSILogicalUnitEmulator * ) fLUNs->getObject ( index ); 563 logicalUnit = LUN->GetLogicalUnitNumber ( ); 564 565 fLUNReportBuffer->LUN[index].FIRST_LEVEL_ADDRESSING = OSSwapHostToBigInt16 ( logicalUnit ); 566 567 } 568 569#endif /* USE_LUN_BYTES */ 570 571 fLUNDataAvailable = bufferSize + kREPORT_LUNS_HeaderSize; 572 573 fLUNInventoryChanged = true; 574 575} 576 577 578#if USE_LUN_BYTES 579 580//----------------------------------------------------------------------------- 581// SendCommand 582//----------------------------------------------------------------------------- 583 584int 585AppleSCSITargetEmulator::SendCommand ( 586 UInt8 * cdb, 587 UInt8 cdbLen, 588 IOMemoryDescriptor * dataDesc, 589 UInt64 * dataLen, 590 SCSILogicalUnitBytes logicalUnitBytes, 591 SCSITaskStatus * scsiStatus, 592 SCSI_Sense_Data * senseBuffer, 593 UInt8 * senseBufferLen ) 594{ 595 596 int result = 0; 597 bool processedCommand = false; 598 599 IOLockLock ( fLock ); 600 601 if ( fLUNInventoryChanged == true ) 602 { 603 604 ERROR_LOG ( ( "Generating UNIT_ATTENTION for LUN inventory change\n" ) ); 605 fLUNInventoryChanged = false; 606 607 *scsiStatus = kSCSITaskStatus_CHECK_CONDITION; 608 if ( senseBuffer != NULL ) 609 { 610 611 UInt8 amount = min ( *senseBufferLen, sizeof ( SCSI_Sense_Data ) ); 612 613 bzero ( senseBuffer, *senseBufferLen ); 614 bcopy ( &sLUNInventoryChangedData, senseBuffer, amount ); 615 616 *senseBufferLen = amount; 617 618 } 619 620 processedCommand = true; 621 622 } 623 624 IOLockUnlock ( fLock ); 625 626 if ( processedCommand == false ) 627 { 628 629 if ( cdb[0] == kSCSICmd_REPORT_LUNS ) 630 { 631 632 COMMAND_LOG ( ( "REPORT_LUNS requested = %qd\n", *dataLen ) ); 633 634 if ( fLUNReportBuffer != NULL ) 635 { 636 637 *dataLen = min ( fLUNDataAvailable, *dataLen ); 638 dataDesc->writeBytes ( 0, fLUNReportBuffer, *dataLen ); 639 640 COMMAND_LOG ( ( "REPORT_LUNS realized = %qd\n", *dataLen ) ); 641 642 *scsiStatus = kSCSITaskStatus_GOOD; 643 644 } 645 646 processedCommand = true; 647 648 } 649 650 else 651 { 652 653 UInt32 index = 0; 654 UInt32 count = 0; 655 AppleSCSILogicalUnitEmulator * LUN = NULL; 656 657 IOLockLock ( fLock ); 658 659 count = fLUNs->getCount ( ); 660 661 // Dispatch to the proper LUN. 662 for ( index = 0; index < count; index++ ) 663 { 664 665 SCSILogicalUnitBytes tempBytes = { 0 }; 666 667 LUN = ( AppleSCSILogicalUnitEmulator * ) fLUNs->getObject ( index ); 668 LUN->GetLogicalUnitBytes ( &tempBytes ); 669 if ( !bcmp ( tempBytes, logicalUnitBytes, sizeof ( SCSILogicalUnitBytes ) ) ) 670 { 671 672 IOLockUnlock ( fLock ); 673 674 result = LUN->SendCommand ( cdb, cdbLen, dataDesc, dataLen, scsiStatus, senseBuffer, senseBufferLen ); 675 processedCommand = true; 676 break; 677 678 } 679 680 } 681 682 if ( processedCommand == false ) 683 { 684 IOLockUnlock ( fLock ); 685 } 686 687 } 688 689 } 690 691 if ( processedCommand == false ) 692 { 693 694 ERROR_LOG ( ( "No LUN found LUN = 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", 695 logicalUnitBytes[0], logicalUnitBytes[1], logicalUnitBytes[2], logicalUnitBytes[3], 696 logicalUnitBytes[4], logicalUnitBytes[5], logicalUnitBytes[6], logicalUnitBytes[7] ) ); 697 698 if ( cdb[0] == kSCSICmd_INQUIRY ) 699 { 700 701 ERROR_LOG ( ( "Special case INQUIRY to unknown LUN\n" ) ); 702 703 if ( *dataLen > cdb[4] ) 704 *dataLen = cdb[4]; 705 706 if ( *dataLen > 0 ) 707 { 708 709 if ( *dataLen > sizeof ( gInquiryData ) ) 710 { 711 *dataLen = sizeof ( gInquiryData ); 712 } 713 714 dataDesc->writeBytes ( 0, &gInquiryData, *dataLen ); 715 716 } 717 718 *scsiStatus = kSCSITaskStatus_GOOD; 719 720 result = 0; 721 722 } 723 724 else 725 { 726 727 ERROR_LOG ( ( "Something other than INQUIRY to unknown LUN, report error\n" ) ); 728 729 *scsiStatus = kSCSITaskStatus_CHECK_CONDITION; 730 if ( senseBuffer != NULL ) 731 { 732 733 UInt8 amount = min ( *senseBufferLen, sizeof ( SCSI_Sense_Data ) ); 734 735 bzero ( senseBuffer, *senseBufferLen ); 736 bcopy ( &sBadLUNSenseData, senseBuffer, amount ); 737 738 *senseBufferLen = amount; 739 740 } 741 742 result = 0; 743 744 } 745 746 } 747 748 return result; 749 750} 751 752 753#else 754 755 756//----------------------------------------------------------------------------- 757// SendCommand 758//----------------------------------------------------------------------------- 759 760int 761AppleSCSITargetEmulator::SendCommand ( 762 UInt8 * cdb, 763 UInt8 cdbLen, 764 IOMemoryDescriptor * dataDesc, 765 UInt64 * dataLen, 766 SCSILogicalUnitNumber logicalUnit, 767 SCSITaskStatus * scsiStatus, 768 SCSI_Sense_Data * senseBuffer, 769 UInt8 * senseBufferLen ) 770{ 771 772 int result = 0; 773 bool processedCommand = false; 774 775 IOLockLock ( fLock ); 776 777 if ( fLUNInventoryChanged == true ) 778 { 779 780 ERROR_LOG ( ( "Generating UNIT_ATTENTION for LUN inventory change\n" ) ); 781 fLUNInventoryChanged = false; 782 783 *scsiStatus = kSCSITaskStatus_CHECK_CONDITION; 784 if ( senseBuffer != NULL ) 785 { 786 787 UInt8 amount = min ( *senseBufferLen, sizeof ( SCSI_Sense_Data ) ); 788 789 bzero ( senseBuffer, *senseBufferLen ); 790 bcopy ( &sLUNInventoryChangedData, senseBuffer, amount ); 791 792 *senseBufferLen = amount; 793 794 } 795 796 processedCommand = true; 797 798 } 799 800 IOLockUnlock ( fLock ); 801 802 if ( processedCommand == false ) 803 { 804 805 if ( cdb[0] == kSCSICmd_REPORT_LUNS ) 806 { 807 808 COMMAND_LOG ( ( "REPORT_LUNS requested = %qd\n", *dataLen ) ); 809 810 if ( fLUNReportBuffer != NULL ) 811 { 812 813 *dataLen = min ( fLUNDataAvailable, *dataLen ); 814 dataDesc->writeBytes ( 0, fLUNReportBuffer, *dataLen ); 815 816 COMMAND_LOG ( ( "REPORT_LUNS realized = %qd\n", *dataLen ) ); 817 818 *scsiStatus = kSCSITaskStatus_GOOD; 819 820 } 821 822 processedCommand = true; 823 824 } 825 826 else 827 { 828 829 UInt32 index = 0; 830 UInt32 count = 0; 831 AppleSCSILogicalUnitEmulator * LUN = NULL; 832 833 IOLockLock ( fLock ); 834 835 count = fLUNs->getCount ( ); 836 837 // Dispatch to the proper LUN. 838 for ( index = 0; index < count; index++ ) 839 { 840 841 LUN = ( AppleSCSILogicalUnitEmulator * ) fLUNs->getObject ( index ); 842 843 if ( logicalUnit == LUN->GetLogicalUnitNumber ( ) ) 844 { 845 846 IOLockUnlock ( fLock ); 847 848 result = LUN->SendCommand ( cdb, cdbLen, dataDesc, dataLen, scsiStatus, senseBuffer, senseBufferLen ); 849 processedCommand = true; 850 break; 851 852 } 853 854 } 855 856 if ( processedCommand == false ) 857 { 858 IOLockUnlock ( fLock ); 859 } 860 861 } 862 863 } 864 865 if ( processedCommand == false ) 866 { 867 868 ERROR_LOG ( ( "No LUN found LUN = %qd\n", logicalUnit ) ); 869 870 if ( cdb[0] == kSCSICmd_INQUIRY ) 871 { 872 873 ERROR_LOG ( ( "Special case INQUIRY to unknown LUN\n" ) ); 874 875 if ( *dataLen > cdb[4] ) 876 *dataLen = cdb[4]; 877 878 if ( *dataLen > 0 ) 879 { 880 881 if ( *dataLen > sizeof ( gInquiryData ) ) 882 { 883 *dataLen = sizeof ( gInquiryData ); 884 } 885 886 dataDesc->writeBytes ( 0, &gInquiryData, *dataLen ); 887 888 } 889 890 *scsiStatus = kSCSITaskStatus_GOOD; 891 892 result = 0; 893 894 } 895 896 else 897 { 898 899 ERROR_LOG ( ( "Something other than INQUIRY to unknown LUN, report error\n" ) ); 900 901 *scsiStatus = kSCSITaskStatus_CHECK_CONDITION; 902 if ( senseBuffer != NULL ) 903 { 904 905 UInt8 amount = min ( *senseBufferLen, sizeof ( SCSI_Sense_Data ) ); 906 907 bzero ( senseBuffer, *senseBufferLen ); 908 bcopy ( &sBadLUNSenseData, senseBuffer, amount ); 909 910 *senseBufferLen = amount; 911 912 } 913 914 result = 0; 915 916 } 917 918 } 919 920 return result; 921 922} 923 924 925#endif /* USE_LUN_BYTES */ 926 927 928//----------------------------------------------------------------------------- 929// CompareLUNs 930//----------------------------------------------------------------------------- 931 932static SInt32 933CompareLUNs ( 934 const OSMetaClassBase * obj1, 935 const OSMetaClassBase * obj2, 936 void * ref ) 937{ 938 939 AppleSCSILogicalUnitEmulator * lun1 = ( AppleSCSILogicalUnitEmulator * ) obj1; 940 AppleSCSILogicalUnitEmulator * lun2 = ( AppleSCSILogicalUnitEmulator * ) obj2; 941 942#if USE_LUN_BYTES 943 944 SCSILogicalUnitBytes temp1Bytes = { 0 }; 945 SCSILogicalUnitBytes temp2Bytes = { 0 }; 946 947 lun1->GetLogicalUnitBytes ( &temp1Bytes ); 948 lun2->GetLogicalUnitBytes ( &temp2Bytes ); 949 950 // Returns a comparison result of the object, a negative value if obj1 > obj2, 951 // 0 if obj1 == obj2, and a positive value if obj1 < obj2 952 return bcmp ( temp2Bytes, temp1Bytes, sizeof ( SCSILogicalUnitBytes ) ); 953 954#else 955 956 return ( lun1->GetLogicalUnitNumber ( ) - lun2->GetLogicalUnitNumber ( ) ); 957 958#endif /* USE_LUN_BYTES */ 959 960} 961