1/* 2 * Copyright (c) 1998-2012 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 25//-------------------------------------------------------------------------------------------------- 26// Includes 27//-------------------------------------------------------------------------------------------------- 28 29// This class' header file 30#include "IOUSBMassStorageUFISubclass.h" 31 32#include <IOKit/storage/IOBlockStorageDriver.h> 33#include <IOKit/IOSyncer.h> 34#include <IOKit/usb/IOUFIStorageServices.h> 35#include <IOKit/scsi/SCSICmds_INQUIRY_Definitions.h> 36#include <IOKit/scsi/SCSICommandOperationCodes.h> 37 38#include <IOKit/scsi/SCSITask.h> 39 40// IOKit Power Management headers 41#include <IOKit/pwr_mgt/RootDomain.h> 42 43#include "Debugging.h" 44 45 46//-------------------------------------------------------------------------------------------------- 47// Macros 48//-------------------------------------------------------------------------------------------------- 49 50//-------------------------------------------------------------------------------------------------- 51// Constants 52//-------------------------------------------------------------------------------------------------- 53 54#define kKeySwitchProperty "Keyswitch" 55#define kAppleKeySwitchProperty "AppleKeyswitch" 56 57#define super IOSCSIPrimaryCommandsDevice 58 59enum 60{ 61 kIOUSBMassStorageUFIDevicePowerStateSleep = 0, 62 kIOUSBMassStorageUFIDevicePowerStateActive = 1, 63 kIOUSBMassStorageUFIDeviceNumPowerStates = 2 64}; 65 66 67static IOPMPowerState sPowerStates[kIOUSBMassStorageUFIDeviceNumPowerStates] = 68{ 69 { kIOPMPowerStateVersion1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 70 { kIOPMPowerStateVersion1, IOPMPowerOn, IOPMPowerOn, IOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0} 71}; 72 73 74//----------------------------------------------------------------------------- 75// Globals 76//----------------------------------------------------------------------------- 77 78IOOptionBits gRestartShutdownFlag = 0; 79 80OSDefineMetaClassAndStructors( IOUSBMassStorageUFISubclass, IOUSBMassStorageClass ) 81 82 83#pragma mark - 84#pragma mark *** IOUSBMassStorageUFIDevice declaration *** 85#pragma mark - 86 87OSDefineMetaClassAndStructors( IOUSBMassStorageUFIDevice, IOSCSIPrimaryCommandsDevice ) 88 89 90#pragma mark - 91#pragma mark *** Static Class Methods *** 92#pragma mark - 93 94 95//-------------------------------------------------------------------------------------------------- 96// sProcessPoll - Gets scheduled to execute the polls. [STATIC][PUBLIC] 97//-------------------------------------------------------------------------------------------------- 98 99void 100IOUSBMassStorageUFIDevice::sProcessPoll ( void * theUFIDriver, void * refCon ) 101{ 102 UNUSED( refCon ); 103 104 IOUSBMassStorageUFIDevice * driver; 105 106 driver = (IOUSBMassStorageUFIDevice *) theUFIDriver; 107 require_nonzero ( driver, ErrorExit ); 108 109 if( driver->fPollingMode != kPollingMode_Suspended ) 110 { 111 112 driver->ProcessPoll(); 113 114 if( driver->fPollingMode != kPollingMode_Suspended ) 115 { 116 // schedule the poller again 117 driver->EnablePolling(); 118 } 119 120 } 121 122 // drop the retain associated with this poll 123 driver->release(); 124 125 126ErrorExit: 127 128 return; 129 130} 131 132 133//-------------------------------------------------------------------------------------------------- 134// AsyncReadWriteComplete - Completion routine for I/O [STATIC][PRIVATE] 135//-------------------------------------------------------------------------------------------------- 136 137void 138IOUSBMassStorageUFIDevice::AsyncReadWriteComplete ( SCSITaskIdentifier request ) 139{ 140 void * clientData; 141 IOReturn status; 142 UInt64 actCount = 0; 143 IOUSBMassStorageUFIDevice * taskOwner; 144 145 146 if ( request == NULL ) 147 { 148 PANIC_NOW ( ( "IOUSBMassStorageUFIDevice::AsyncReadWriteComplete request==NULL." ) ); 149 } 150 151 taskOwner = OSDynamicCast ( IOUSBMassStorageUFIDevice, IOSCSIPrimaryCommandsDevice::sGetOwnerForTask ( request ) ); 152 if ( taskOwner == NULL ) 153 { 154 PANIC_NOW ( ( "IOUSBMassStorageUFIDevice::AsyncReadWriteComplete taskOwner==NULL." ) ); 155 } 156 157 // Extract the client data from the SCSITask 158 clientData = taskOwner->GetApplicationLayerReference( request ); 159 160 if ( ( taskOwner->GetServiceResponse( request ) == kSCSIServiceResponse_TASK_COMPLETE ) && 161 ( taskOwner->GetTaskStatus( request ) == kSCSITaskStatus_GOOD ) ) 162 { 163 status = kIOReturnSuccess; 164 } 165 else 166 { 167 168 STATUS_LOG ( ( 4, "%s[%p]::Error on read/write", taskOwner->getName(), taskOwner ) ); 169 status = kIOReturnError; 170 171 } 172 173 if ( status == kIOReturnSuccess ) 174 { 175 actCount = taskOwner->GetDataBuffer( request )->getLength(); 176 } 177 178 179 taskOwner->ReleaseSCSITask( request ); 180 181 IOUFIStorageServices::AsyncReadWriteComplete( clientData, status, actCount ); 182 183} 184 185 186#pragma mark - 187#pragma mark *** Class Methods *** 188#pragma mark - 189 190 191//-------------------------------------------------------------------------------------------------- 192// InitializeDeviceSupport - Initializes device support [PROTECTED] 193//-------------------------------------------------------------------------------------------------- 194 195bool 196IOUSBMassStorageUFIDevice::InitializeDeviceSupport ( void ) 197{ 198 bool setupSuccessful = false; 199 200 201 // Initialize the medium characteristics 202 fMediumPresent = false; 203 fMediumIsWriteProtected = true; 204 205 STATUS_LOG ( ( 6, "%s[%p]::InitializeDeviceSupport called", getName(), this ) ); 206 207 ClearNotReadyStatus(); 208 209 fPollingMode = kPollingMode_NewMedia; 210 211 fIOUSBMassStorageUFIDeviceReserved = ( IOUSBMassStorageUFIDeviceExpansionData * ) 212 IOMalloc ( sizeof ( IOUSBMassStorageUFIDeviceExpansionData ) ); 213 require_nonzero ( fIOUSBMassStorageUFIDeviceReserved, ErrorExit ); 214 215 require ( ( DetermineDeviceCharacteristics( ) == true ), ErrorExit ); 216 217 fPollingThread = thread_call_allocate ( 218 ( thread_call_func_t ) IOUSBMassStorageUFIDevice::sProcessPoll, 219 ( thread_call_param_t ) this ); 220 require_nonzero ( fPollingThread, ErrorExit ); 221 222 bzero ( fIOUSBMassStorageUFIDeviceReserved, 223 sizeof ( IOUSBMassStorageUFIDeviceExpansionData ) ); 224 225 InitializePowerManagement ( GetProtocolDriver ( ) ); 226 227 STATUS_LOG ( ( 5, "%s[%p]::InitializeDeviceSupport setupSuccessful = %d", getName(), this, setupSuccessful ) ); 228 229 setupSuccessful = true; 230 231ErrorExit: 232 233 if ( setupSuccessful == false ) 234 { 235 TerminateDeviceSupport(); 236 } 237 238 return setupSuccessful; 239} 240 241 242//-------------------------------------------------------------------------------------------------- 243// StartDeviceSupport - Starts device support [PROTECTED] 244//-------------------------------------------------------------------------------------------------- 245 246void 247IOUSBMassStorageUFIDevice::StartDeviceSupport ( void ) 248{ 249 OSBoolean * shouldNotPoll = NULL; 250 251 252 shouldNotPoll = OSDynamicCast ( OSBoolean, 253 getProperty ( kAppleKeySwitchProperty ) ); 254 255 if ( shouldNotPoll != NULL ) 256 { 257 258 // See if we should not poll. 259 require ( shouldNotPoll->isFalse ( ), Exit ); 260 261 } 262 263 // Start polling 264 EnablePolling ( ); 265 266 267Exit: 268 269 CreateStorageServiceNub ( ); 270 271} 272 273 274//-------------------------------------------------------------------------------------------------- 275// SuspendDeviceSupport - Suspends device support [PROTECTED] 276//-------------------------------------------------------------------------------------------------- 277 278void 279IOUSBMassStorageUFIDevice::SuspendDeviceSupport ( void ) 280{ 281 if( fPollingMode != kPollingMode_Suspended ) 282 { 283 DisablePolling(); 284 } 285 286} 287 288 289//-------------------------------------------------------------------------------------------------- 290// ResumeDeviceSupport - Resumes device support [PROTECTED] 291//-------------------------------------------------------------------------------------------------- 292 293void 294IOUSBMassStorageUFIDevice::ResumeDeviceSupport ( void ) 295{ 296 // The driver has not found media in the device, restart 297 // the polling for new media. 298 if( fMediumPresent == false ) 299 { 300 fPollingMode = kPollingMode_NewMedia; 301 302 EnablePolling(); 303 } 304 305} 306 307 308//-------------------------------------------------------------------------------------------------- 309// StopDeviceSupport - Stops device support [PROTECTED] 310//-------------------------------------------------------------------------------------------------- 311 312void 313IOUSBMassStorageUFIDevice::StopDeviceSupport ( void ) 314{ 315 // This is only here to keep the compiler happy since 316 // the method is pure virtual. We don't need it for UFI. 317} 318 319 320//-------------------------------------------------------------------------------------------------- 321// TerminateDeviceSupport - Terminates device support [PROTECTED] 322//-------------------------------------------------------------------------------------------------- 323 324void 325IOUSBMassStorageUFIDevice::TerminateDeviceSupport ( void ) 326{ 327 STATUS_LOG ( ( 6, "%s[%p]::cleanUp called.", getName(), this ) ); 328 329 if ( fPollingThread != NULL ) 330 { 331 332 thread_call_free ( fPollingThread ); 333 fPollingThread = NULL; 334 335 } 336 337 if ( fIOUSBMassStorageUFIDeviceReserved != NULL) 338 { 339 IODelete ( fIOUSBMassStorageUFIDeviceReserved, IOUSBMassStorageUFIDeviceExpansionData, 1 ); 340 fIOUSBMassStorageUFIDeviceReserved = NULL; 341 } 342} 343 344 345//-------------------------------------------------------------------------------------------------- 346// ClearNotReadyStatus - Clears any NOT_READY status on device [PROTECTED] 347//-------------------------------------------------------------------------------------------------- 348 349bool 350IOUSBMassStorageUFIDevice::ClearNotReadyStatus( void ) 351{ 352 SCSI_Sense_Data senseBuffer; 353 IOMemoryDescriptor * bufferDesc; 354 SCSITaskIdentifier request; 355 bool driveReady = false; 356 bool result = true; 357 SCSIServiceResponse serviceResponse = kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE; 358 359 360 STATUS_LOG ( ( 6, "%s[%p]::%s called", getName(), this, __FUNCTION__ ) ); 361 362 bufferDesc = IOMemoryDescriptor::withAddress ( ( void * ) &senseBuffer, 363 kSenseDefaultSize, 364 kIODirectionIn ); 365 366 request = GetSCSITask(); 367 do 368 { 369 370 if ( TEST_UNIT_READY ( request ) == true ) 371 { 372 // The command was successfully built, now send it 373 serviceResponse = SendCommand ( request, 0 ); 374 } 375 else 376 { 377 PANIC_NOW( ( "IOUSBMassStorageUFIDevice::ClearNotReadyStatus malformed command" ) ); 378 } 379 380 if ( serviceResponse == kSCSIServiceResponse_TASK_COMPLETE ) 381 { 382 383 bool validSense = false; 384 385 if ( GetTaskStatus( request ) == kSCSITaskStatus_CHECK_CONDITION ) 386 { 387 388 validSense = GetAutoSenseData( request, &senseBuffer ); 389 if ( validSense == false ) 390 { 391 392 if ( REQUEST_SENSE( request, bufferDesc, kSenseDefaultSize ) == true ) 393 { 394 // The command was successfully built, now send it 395 serviceResponse = SendCommand ( request, 0 ); 396 } 397 else 398 { 399 PANIC_NOW ( ( "IOUSBMassStorageUFIDevice::ClearNotReadyStatus malformed command" ) ); 400 } 401 402 if ( serviceResponse == kSCSIServiceResponse_TASK_COMPLETE ) 403 { 404 validSense = true; 405 } 406 407 } 408 409 if ( validSense == true ) 410 { 411 if ( ( ( senseBuffer.SENSE_KEY & kSENSE_KEY_Mask ) == kSENSE_KEY_NOT_READY ) && 412 ( senseBuffer.ADDITIONAL_SENSE_CODE == 0x04 ) && 413 ( senseBuffer.ADDITIONAL_SENSE_CODE_QUALIFIER == 0x01 ) ) 414 { 415 416 STATUS_LOG ( ( 5, "%s[%p]::drive not ready", getName(), this ) ); 417 driveReady = false; 418 IOSleep ( 200 ); 419 420 } 421 else if ( ( ( senseBuffer.SENSE_KEY & kSENSE_KEY_Mask ) == kSENSE_KEY_NOT_READY ) && 422 ( senseBuffer.ADDITIONAL_SENSE_CODE == 0x04 ) && 423 ( senseBuffer.ADDITIONAL_SENSE_CODE_QUALIFIER == 0x02 ) ) 424 { 425 // The drive needs to be spun up. Issue a START_STOP_UNIT to it. 426 if ( START_STOP_UNIT( request, 0x00, 0x00, 0x01 ) == true ) 427 { 428 serviceResponse = SendCommand( request, 0 ); 429 } 430 431 } 432 else 433 { 434 435 driveReady = true; 436 STATUS_LOG ( (5, "%s[%p]::drive READY", getName(), this ) ); 437 438 } 439 440 STATUS_LOG ( ( 5, "%s[%p]:: sense data: %01x, %02x, %02x", getName(), this, 441 ( senseBuffer.SENSE_KEY & kSENSE_KEY_Mask ), 442 senseBuffer.ADDITIONAL_SENSE_CODE, 443 senseBuffer.ADDITIONAL_SENSE_CODE_QUALIFIER ) ); 444 445 } 446 } 447 else 448 { 449 driveReady = true; 450 } 451 452 } 453 else 454 { 455 // the command failed - perhaps the device was hot unplugged 456 // give other threads some time to run. 457 IOSleep( 200 ); 458 459 } 460 461 // check isInactive in case device was hot unplugged during sleep 462 // and we are in an infinite loop here 463 } while( ( driveReady == false ) && ( isInactive() == false ) ); 464 465 bufferDesc->release(); 466 ReleaseSCSITask ( request ); 467 468 result = isInactive() ? false : true; 469 return result; 470 471} 472 473 474//-------------------------------------------------------------------------------------------------- 475// EnablePolling - Schedules the polling thread to run [PROTECTED] 476//-------------------------------------------------------------------------------------------------- 477 478void 479IOUSBMassStorageUFIDevice::EnablePolling( void ) 480{ 481 AbsoluteTime time; 482 483 if ( ( fPollingMode != kPollingMode_Suspended ) && 484 fPollingThread && 485 ( isInactive() == false ) ) 486 { 487 // Retain ourselves so that this object doesn't go away 488 // while we are polling 489 retain(); 490 491 clock_interval_to_deadline( 1000, kMillisecondScale, &time ); 492 493 // Let's enqueue the polling. 494 if (thread_call_enter_delayed( fPollingThread, time )) 495 { 496 // The call was already enqueued therefore there already is 497 // a pending retain and we must release the last retain to 498 // maintain the proper balance: if we would not release it, 499 // the retain count would keep growing. 500 release(); 501 } 502 503 } 504} 505 506 507//-------------------------------------------------------------------------------------------------- 508// DisablePolling - Unschedules the polling thread if it hasn't run yet [PROTECTED] 509//-------------------------------------------------------------------------------------------------- 510 511void 512IOUSBMassStorageUFIDevice::DisablePolling( void ) 513{ 514 fPollingMode = kPollingMode_Suspended; 515 516 // Cancel the thread if it is scheduled 517 if( thread_call_cancel( fPollingThread ) ) 518 { 519 // It was scheduled, so we balance out the retain() 520 // with a release() 521 release(); 522 523 } 524} 525 526 527//-------------------------------------------------------------------------------------------------- 528// DetermineDeviceCharacteristics - Determines device characteristics [PROTECTED] 529//-------------------------------------------------------------------------------------------------- 530 531bool 532IOUSBMassStorageUFIDevice::DetermineDeviceCharacteristics( void ) 533{ 534 SCSIServiceResponse serviceResponse = kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE; 535 SCSITaskIdentifier request = NULL; 536 IOMemoryDescriptor * bufferDesc = NULL; 537 SCSICmd_INQUIRY_StandardData * inquiryBuffer = NULL; 538 UInt8 inquiryBufferCount = sizeof ( SCSICmd_INQUIRY_StandardData ); 539 bool succeeded = false; 540 int loopCount; 541 char tempString [ kINQUIRY_PRODUCT_IDENTIFICATION_Length + 1 ]; // Maximum + 1 for null char 542 OSString * string; 543 544 545 STATUS_LOG ( ( 6, "%s[%p]::DetermineDeviceCharacteristics called", getName(), this ) ); 546 547 inquiryBuffer = ( SCSICmd_INQUIRY_StandardData * ) IOMalloc ( inquiryBufferCount ); 548 if( inquiryBuffer == NULL ) 549 { 550 551 STATUS_LOG ( ( 1, "%s[%p]: Couldn't allocate Inquiry buffer.", getName(), this ) ); 552 goto ErrorExit; 553 554 } 555 556 bufferDesc = IOMemoryDescriptor::withAddress ( inquiryBuffer, inquiryBufferCount, kIODirectionIn ); 557 if ( bufferDesc == NULL ) 558 { 559 560 STATUS_LOG ( ( 1, "%s[%p]: Couldn't alloc Inquiry buffer: ", getName(), this ) ); 561 goto ErrorExit; 562 563 } 564 565 request = GetSCSITask(); 566 if ( request == NULL ) 567 { 568 goto ErrorExit; 569 } 570 571 if ( INQUIRY ( request, 572 bufferDesc, 573 0, 574 inquiryBufferCount ) == true ) 575 { 576 // The command was successfully built, now send it 577 serviceResponse = SendCommand ( request, 0 ); 578 579 } 580 else 581 { 582 583 PANIC_NOW ( ( "IOUSBMassStorageUFIDevice::DetermineDeviceCharacteristics malformed command" ) ); 584 goto ErrorExit; 585 586 } 587 588 if ( ( serviceResponse != kSCSIServiceResponse_TASK_COMPLETE ) || 589 ( GetTaskStatus ( request ) != kSCSITaskStatus_GOOD ) ) 590 { 591 592 STATUS_LOG ( ( 2, "%s[%p]: Inquiry completed with an error: ", getName(), this ) ); 593 goto ErrorExit; 594 595 } 596 597 // Set the Vendor Identification property for the device. 598 for ( loopCount = 0; loopCount < kINQUIRY_VENDOR_IDENTIFICATION_Length; loopCount++ ) 599 { 600 tempString[loopCount] = inquiryBuffer->VENDOR_IDENTIFICATION[loopCount]; 601 } 602 603 tempString[loopCount] = 0; 604 605 for ( loopCount = kINQUIRY_VENDOR_IDENTIFICATION_Length - 1; loopCount >= 0; loopCount-- ) 606 { 607 608 if ( tempString[loopCount] != ' ' ) 609 { 610 // Found a real character 611 tempString[loopCount+1] = '\0'; 612 break; 613 614 } 615 616 } 617 618 string = OSString::withCString ( tempString ); 619 if ( string != NULL ) 620 { 621 622 fDeviceCharacteristicsDictionary->setObject ( kIOPropertyVendorNameKey, string ); 623 string->release(); 624 625 } 626 627 // Set the Product Indentification property for the device. 628 for ( loopCount = 0; loopCount < kINQUIRY_PRODUCT_IDENTIFICATION_Length; loopCount++ ) 629 { 630 tempString[loopCount] = inquiryBuffer->PRODUCT_IDENTIFICATION[loopCount]; 631 } 632 tempString[loopCount] = 0; 633 634 for ( loopCount = kINQUIRY_PRODUCT_IDENTIFICATION_Length - 1; loopCount >= 0; loopCount-- ) 635 { 636 if ( tempString[loopCount] != ' ' ) 637 { 638 // Found a real character 639 tempString[loopCount+1] = '\0'; 640 break; 641 642 } 643 } 644 645 string = OSString::withCString ( tempString ); 646 if ( string != NULL ) 647 { 648 649 fDeviceCharacteristicsDictionary->setObject ( kIOPropertyProductNameKey, string ); 650 string->release(); 651 652 } 653 654 // Set the Product Revision Level property for the device. 655 for ( loopCount = 0; loopCount < kINQUIRY_PRODUCT_REVISION_LEVEL_Length; loopCount++ ) 656 { 657 tempString[loopCount] = inquiryBuffer->PRODUCT_REVISION_LEVEL[loopCount]; 658 } 659 660 tempString[loopCount] = 0; 661 662 for ( loopCount = kINQUIRY_PRODUCT_REVISION_LEVEL_Length - 1; loopCount >= 0; loopCount-- ) 663 { 664 if ( tempString[loopCount] != ' ' ) 665 { 666 // Found a real character 667 tempString[loopCount+1] = '\0'; 668 break; 669 670 } 671 } 672 673 string = OSString::withCString ( tempString ); 674 if ( string != NULL ) 675 { 676 677 fDeviceCharacteristicsDictionary->setObject ( kIOPropertyProductRevisionLevelKey, string ); 678 string->release(); 679 680 } 681 682 succeeded = true; 683 684 685ErrorExit: 686 687 688 STATUS_LOG ( ( 6, "%s[%p]::DetermineDeviceCharacteristics exiting", getName(), this ) ); 689 690 if ( request ) 691 { 692 ReleaseSCSITask ( request ); 693 request = NULL; 694 } 695 696 if ( bufferDesc ) 697 { 698 bufferDesc->release(); 699 bufferDesc = NULL; 700 } 701 702 if ( inquiryBuffer ) 703 { 704 IOFree ( ( void * ) inquiryBuffer, inquiryBufferCount ); 705 inquiryBuffer = NULL; 706 } 707 708 return succeeded; 709 710} 711 712 713//-------------------------------------------------------------------------------------------------- 714// SetMediumCharacteristics - Sets medium characteristics [PROTECTED] 715//-------------------------------------------------------------------------------------------------- 716 717void 718IOUSBMassStorageUFIDevice::SetMediumCharacteristics( UInt32 blockSize, UInt32 blockCount ) 719{ 720 721 STATUS_LOG ( ( 6, "%s[%p]::SetMediumCharacteristics called", getName(), this ) ); 722 STATUS_LOG ( ( 5, "%s[%p]::mediumBlockSize = %ld, blockCount = %ld", getName(), this, blockSize, blockCount ) ); 723 724 fMediumBlockSize = blockSize; 725 fMediumBlockCount = blockCount; 726 727 STATUS_LOG ( ( 6, "%s[%p]::SetMediumCharacteristics exiting", getName(), this ) ); 728 729} 730 731 732//-------------------------------------------------------------------------------------------------- 733// ResetMediumCharacteristics - Resets medium characteristics to known values. [PROTECTED] 734//-------------------------------------------------------------------------------------------------- 735 736void 737IOUSBMassStorageUFIDevice::ResetMediumCharacteristics ( void ) 738{ 739 740 STATUS_LOG ( ( 6, "%s[%p]::ResetMediumCharacteristics called", getName(), this ) ); 741 742 fMediumBlockSize = 0; 743 fMediumBlockCount = 0; 744 fMediumPresent = false; 745 fMediumIsWriteProtected = true; 746 747 STATUS_LOG ( ( 6, "%s[%p]::ResetMediumCharacteristics exiting", getName(), this ) ); 748 749} 750 751 752//-------------------------------------------------------------------------------------------------- 753// CreateStorageServiceNub - Creates the linkage object for IOStorageFamily to use. [PROTECTED] 754//-------------------------------------------------------------------------------------------------- 755 756void 757IOUSBMassStorageUFIDevice::CreateStorageServiceNub ( void ) 758{ 759 STATUS_LOG ( ( 6, "%s[%p]::CreateStorageServiceNub entering.", getName(), this ) ); 760 761 IOService * nub = OSTypeAlloc ( IOUFIStorageServices ); 762 if ( nub == NULL ) 763 { 764 765 STATUS_LOG ( ( 1, "%s[%p]::CreateStorageServiceNub failed", getName(), this ) ); 766 PANIC_NOW ( ( "IOUSBMassStorageUFIDevice::CreateStorageServiceNub failed" ) ); 767 return; 768 769 } 770 771 nub->init(); 772 773 if ( !nub->attach( this ) ) 774 { 775 // panic since the nub can't attach 776 PANIC_NOW ( ( "IOUSBMassStorageUFIDevice::CreateStorageServiceNub unable to attach nub" ) ); 777 return; 778 779 } 780 781 nub->registerService(kIOServiceAsynchronous); 782 STATUS_LOG ( ( 6, "%s[%p]::CreateStorageServiceNub exiting.", getName(), this ) ); 783 784 nub->release(); 785} 786 787 788//-------------------------------------------------------------------------------------------------- 789// ProcessPoll - Processes a poll for media or media removal. PROTECTED] 790//-------------------------------------------------------------------------------------------------- 791 792void 793IOUSBMassStorageUFIDevice::ProcessPoll ( void ) 794{ 795 switch ( fPollingMode ) 796 { 797 798 case kPollingMode_NewMedia: 799 { 800 PollForNewMedia(); 801 } 802 break; 803 804 case kPollingMode_MediaRemoval: 805 { 806 PollForMediaRemoval(); 807 } 808 break; 809 810 default: 811 { 812 // This is an unknown polling mode -- do nothing. 813 STATUS_LOG ( ( 1, "%s[%p]:ProcessPoll Unknown polling mode.", getName(), this ) ); 814 } 815 break; 816 817 } 818} 819 820 821//-------------------------------------------------------------------------------------------------- 822// PollForNewMedia - Polls for new media insertion. [PROTECTED] 823//-------------------------------------------------------------------------------------------------- 824 825void 826IOUSBMassStorageUFIDevice::PollForNewMedia( void ) 827{ 828 bool mediaFound = false; 829 UInt64 blockCount; 830 UInt64 blockSize; 831 832 833 // Since this is a poll for new media, 834 fMediumPresent = false; 835 836 mediaFound = DetermineMediaPresence(); 837 if ( mediaFound == false ) 838 { 839 return; 840 } 841 842 if ( DetermineMediumCapacity ( &blockSize, &blockCount ) == false ) 843 { 844 // Capacity could not be determined, treat it like no media inserted 845 // and try again. 846 return; 847 } 848 849 SetMediumCharacteristics ( blockSize, blockCount ); 850 851 fMediumIsWriteProtected = DetermineMediumWriteProtectState(); 852 853 fMediumPresent = true; 854 855 // Message up the chain that we have media 856 messageClients ( kIOMessageMediaStateHasChanged, 857 ( void * ) kIOMediaStateOnline, 858 sizeof( IOMediaState ) ); 859 860 // Media is not locked into the drive, so this is most likely 861 // a manually ejectable device, start polling for media removal. 862 fPollingMode = kPollingMode_MediaRemoval; 863} 864 865 866//-------------------------------------------------------------------------------------------------- 867// DetermineMediaPresence - Checks if media has been inserted into the 868// device. If medium is detected, this method 869// will return true, else it will return false [PROTECTED] 870//-------------------------------------------------------------------------------------------------- 871 872bool 873IOUSBMassStorageUFIDevice::DetermineMediaPresence ( void ) 874{ 875 SCSIServiceResponse serviceResponse = kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE; 876 SCSITaskIdentifier request = NULL; 877 bool mediaFound = false; 878 OSBoolean * keySwitchLocked = NULL; 879 880 881 STATUS_LOG ( ( 6, "%s[%p]::DetermineMediaPresence called", getName(), this ) ); 882 883 keySwitchLocked = OSDynamicCast ( OSBoolean, getProperty ( kAppleKeySwitchProperty ) ); 884 885 if ( keySwitchLocked != NULL ) 886 { 887 // See if we should poll for media. 888 if ( keySwitchLocked->isTrue ( ) ) 889 { 890 return false; 891 } 892 } 893 894 request = GetSCSITask(); 895 if ( request == NULL ) 896 { 897 return false; 898 } 899 900 // Do a TEST_UNIT_READY to generate sense data 901 if ( TEST_UNIT_READY ( request ) == true ) 902 { 903 // The command was successfully built, now send it, set timeout to 10 seconds. 904 serviceResponse = SendCommand( request, 10 * 1000 ); 905 906 } 907 else 908 { 909 910 STATUS_LOG ( ( 1, "%s[%p]::DetermineMediaPresence malformed command", getName(), this ) ); 911 goto CheckDone; 912 913 } 914 915 if ( serviceResponse == kSCSIServiceResponse_TASK_COMPLETE ) 916 { 917 918 bool validSense; 919 SCSI_Sense_Data senseBuffer; 920 921 // Check for valid Autosense data. If it was not retrieved from the 922 // device, explicitly ask for it by sending a REQUEST SENSE command. 923 validSense = GetAutoSenseData ( request, &senseBuffer ); 924 if ( validSense == false ) 925 { 926 IOMemoryDescriptor * bufferDesc; 927 928 bufferDesc = IOMemoryDescriptor::withAddress ( ( void * ) &senseBuffer, 929 kSenseDefaultSize, 930 kIODirectionIn ); 931 if( bufferDesc == NULL ) 932 { 933 934 STATUS_LOG ( ( 1, "%s[%p]: could not allocate sense buffer descriptor.", getName(), this ) ); 935 goto CheckDone; 936 937 } 938 939 // Get the sense data to determine if media is present. 940 if ( REQUEST_SENSE( request, bufferDesc, kSenseDefaultSize ) == true ) 941 { 942 // The command was successfully built, now send it 943 serviceResponse = SendCommand( request, 0 ); 944 945 } 946 else 947 { 948 949 STATUS_LOG ( ( 1, "%s[%p]::PollForMedia malformed command", getName(), this ) ); 950 bufferDesc->release(); 951 goto CheckDone; 952 953 } 954 955 bufferDesc->release(); 956 957 if ( ( serviceResponse != kSCSIServiceResponse_TASK_COMPLETE ) || 958 ( GetTaskStatus ( request ) != kSCSITaskStatus_GOOD ) ) 959 { 960 961 STATUS_LOG ( ( 2, "%s[%p]: REQUEST_SENSE failed", getName(), this ) ); 962 goto CheckDone; 963 964 } 965 966 } 967 968 if ( ( senseBuffer.ADDITIONAL_SENSE_CODE == 0x04 ) && 969 ( senseBuffer.ADDITIONAL_SENSE_CODE_QUALIFIER == 0x02 ) ) 970 { 971 // Since the device has indicated it needs a start, send it one 972 // and then reset the polling. 973 if ( START_STOP_UNIT( request, 0x00,0x00, 1 ) == true ) 974 { 975 // The command was successfully built, now send it, set timeout to 10 seconds. 976 serviceResponse = SendCommand( request, 0 ); 977 } 978 979 goto CheckDone; 980 981 } 982 else if ( ( senseBuffer.ADDITIONAL_SENSE_CODE != 0x00 ) || 983 ( senseBuffer.ADDITIONAL_SENSE_CODE_QUALIFIER != 0x00 ) ) 984 { 985 986 STATUS_LOG ( ( 2, "%s[%p]:: ASC = 0x%02x, ASCQ = 0x%02x", 987 getName(), 988 this, 989 senseBuffer.ADDITIONAL_SENSE_CODE, 990 senseBuffer.ADDITIONAL_SENSE_CODE_QUALIFIER ) ); 991 992 goto CheckDone; 993 994 } 995 996 } 997 else 998 { 999 1000 STATUS_LOG ( ( 2, "%s[%p]:: serviceResponse = %d", getName(), this, serviceResponse ) ); 1001 goto CheckDone; 1002 1003 } 1004 1005 1006 UInt8 formatBuffer[12]; 1007 IOMemoryDescriptor * formatDesc; 1008 1009 formatDesc = IOMemoryDescriptor::withAddress ( ( void * ) &formatBuffer[0], 1010 12, 1011 kIODirectionIn ); 1012 if ( formatDesc == NULL ) 1013 { 1014 1015 STATUS_LOG ( ( 1, "%s[%p]: could not allocate sense buffer descriptor.", getName(), this ) ); 1016 goto CheckDone; 1017 1018 } 1019 1020 // If the check makes to to this point, then the TUR returned no errors, 1021 // now send the READ_FORMAT_CAPACITIES to determine is media is truly present. 1022 if ( READ_FORMAT_CAPACITIES ( request, formatDesc, 12 ) == true ) 1023 { 1024 // The command was successfully built, now send it 1025 serviceResponse = SendCommand( request, 0 ); 1026 1027 } 1028 else 1029 { 1030 1031 STATUS_LOG ( ( 1, "%s[%p]::PollForMedia malformed command", getName(), this ) ) ; 1032 formatDesc->release(); 1033 goto CheckDone; 1034 1035 } 1036 1037 formatDesc->release(); 1038 1039 if ( serviceResponse == kSCSIServiceResponse_TASK_COMPLETE ) 1040 { 1041 1042 if ( GetTaskStatus ( request ) == kSCSITaskStatus_CHECK_CONDITION ) 1043 { 1044 1045 bool validSense; 1046 SCSI_Sense_Data senseBuffer; 1047 1048 1049 validSense = GetAutoSenseData ( request, &senseBuffer ); 1050 if ( validSense == false ) 1051 { 1052 1053 IOMemoryDescriptor * bufferDesc; 1054 1055 1056 bufferDesc = IOMemoryDescriptor::withAddress ( ( void * ) &senseBuffer, 1057 kSenseDefaultSize, 1058 kIODirectionIn ); 1059 if( bufferDesc == NULL ) 1060 { 1061 1062 STATUS_LOG ( ( 1, "%s[%p]: could not allocate sense buffer descriptor.", getName(), this ) ); 1063 goto CheckDone; 1064 1065 } 1066 1067 // Get the sense data to determine if media is present. 1068 if ( REQUEST_SENSE ( request, bufferDesc, kSenseDefaultSize ) == true ) 1069 { 1070 // The command was successfully built, now send it 1071 serviceResponse = SendCommand( request, 0 ); 1072 1073 } 1074 else 1075 { 1076 1077 STATUS_LOG ( ( 1, "%s[%p]::PollForMedia malformed command", getName(), this ) ); 1078 bufferDesc->release(); 1079 goto CheckDone; 1080 1081 } 1082 1083 bufferDesc->release(); 1084 1085 // If the REQUEST SENSE comamnd fails to execute, exit and try the 1086 // poll again. 1087 if ( ( serviceResponse != kSCSIServiceResponse_TASK_COMPLETE ) || 1088 ( GetTaskStatus( request ) != kSCSITaskStatus_GOOD ) ) 1089 { 1090 1091 STATUS_LOG ( ( 2, "%s[%p]: REQUEST_SENSE failed", getName(), this ) ); 1092 goto CheckDone; 1093 1094 } 1095 1096 } 1097 1098 if ( ( ( senseBuffer.SENSE_KEY & kSENSE_KEY_Mask ) == kSENSE_KEY_ILLEGAL_REQUEST ) 1099 && ( senseBuffer.ADDITIONAL_SENSE_CODE == 0x20 ) ) 1100 { 1101 // The device indicates that the READ_FORMAT_CAPACITIES command 1102 // is not supported. Since the device has already returned a good 1103 // status to the TEST_UNIT_READY, report that media was found. 1104 mediaFound = true; 1105 goto CheckDone; 1106 1107 } 1108 1109 } 1110 else if ( GetTaskStatus( request ) != kSCSITaskStatus_GOOD ) 1111 { 1112 goto CheckDone; 1113 } 1114 } 1115 else 1116 { 1117 1118 STATUS_LOG ( ( 2, "%s[%p]:: serviceResponse = %d", getName(), this, serviceResponse ) ); 1119 goto CheckDone; 1120 1121 } 1122 1123 STATUS_LOG ( ( 4, "%s[%p]:: Formats data: ", getName(), this ) ); 1124 for ( int i = 0; i < 12; i ++ ) 1125 { 1126 STATUS_LOG ( ( 4, "%s[%p]:: %X : ", getName(), this, formatBuffer[i] ) ); 1127 } 1128 1129 if ( formatBuffer[8] == 0x01 ) 1130 { 1131 1132 STATUS_LOG ( ( 4, "%s[%p]: unformatted media was found.", getName(), this ) ); 1133 1134 // There is unformatted media in the drive, until format support 1135 // is added, treat like no media is present. 1136 goto CheckDone; 1137 1138 } 1139 else if ( formatBuffer[8] != 0x02 ) 1140 { 1141 1142 STATUS_LOG ( ( 5, "%s[%p]: no media was found.", getName(), this ) ); 1143 1144 // There is no media in the drive, reset the poll. 1145 goto CheckDone; 1146 1147 } 1148 1149 STATUS_LOG ( ( 5, "%s[%p]: media was found.", getName(), this ) ); 1150 // At this point, it has been determined that there is usable media 1151 // in the device. 1152 mediaFound = true; 1153 1154 1155CheckDone: 1156 1157 if( request != NULL ) 1158 { 1159 ReleaseSCSITask( request ); 1160 request = NULL; 1161 } 1162 1163 return mediaFound; 1164 1165} 1166 1167 1168//-------------------------------------------------------------------------------------------------- 1169// DetermineMediumCapacity - Determines capacity of the medium. Returns true 1170// if the capacity could be determined, else it 1171// returns false. [PROTECTED] 1172//-------------------------------------------------------------------------------------------------- 1173 1174bool 1175IOUSBMassStorageUFIDevice::DetermineMediumCapacity ( UInt64 * blockSize, 1176 UInt64 * blockCount ) 1177{ 1178 SCSIServiceResponse serviceResponse = kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE; 1179 UInt32 capacityData[2]; 1180 IOMemoryDescriptor * bufferDesc = NULL; 1181 SCSITaskIdentifier request = NULL; 1182 bool result; 1183 1184 1185 *blockSize = 0; 1186 *blockCount = 0; 1187 1188 request = GetSCSITask(); 1189 if ( request == NULL ) 1190 { 1191 1192 result = false; 1193 goto IsDone; 1194 1195 } 1196 1197 bufferDesc = IOMemoryDescriptor::withAddress ( capacityData, 8, kIODirectionIn ); 1198 if ( bufferDesc == NULL ) 1199 { 1200 1201 result = false; 1202 goto IsDone; 1203 1204 } 1205 1206 // We found media, get its capacity 1207 if ( READ_CAPACITY ( request, bufferDesc, 0, 0x00, 0 ) == true ) 1208 { 1209 // The command was successfully built, now send it 1210 serviceResponse = SendCommand( request, 0 ); 1211 1212 } 1213 else 1214 { 1215 1216 STATUS_LOG ( ( 1, "%s[%p]::PollForMedia malformed command", getName(), this ) ); 1217 result = false; 1218 goto IsDone; 1219 1220 } 1221 1222 if ( ( serviceResponse == kSCSIServiceResponse_TASK_COMPLETE ) && 1223 ( GetTaskStatus( request ) == kSCSITaskStatus_GOOD ) ) 1224 { 1225 1226 *blockSize = ( UInt64 ) OSSwapBigToHostInt32 ( capacityData[1] ); 1227 *blockCount = ( UInt64 ) ( OSSwapBigToHostInt32 ( capacityData[0] ) + 1 ); 1228 STATUS_LOG ( ( 4, "%s[%p]: Media capacity: %lx and block size: %lx", 1229 getName(), this, ( UInt32 ) *blockCount, ( UInt32 ) *blockSize ) ); 1230 result = true; 1231 1232 } 1233 else 1234 { 1235 1236 STATUS_LOG ( ( 2, "%s[%p]: Read Capacity failed", getName(), this ) ); 1237 result = false; 1238 1239 } 1240 1241 1242IsDone: 1243 1244 if ( request != NULL ) 1245 { 1246 ReleaseSCSITask ( request ); 1247 } 1248 1249 if ( bufferDesc != NULL ) 1250 { 1251 bufferDesc->release(); 1252 } 1253 1254 return result; 1255 1256} 1257 1258 1259//-------------------------------------------------------------------------------------------------- 1260// DetermineMediumWriteProtectState - Determines medium write protect state. [PROTECTED] 1261//-------------------------------------------------------------------------------------------------- 1262 1263bool 1264IOUSBMassStorageUFIDevice::DetermineMediumWriteProtectState( void ) 1265{ 1266 SCSIServiceResponse serviceResponse = kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE; 1267 UInt8 modeBuffer[72]; 1268 IOMemoryDescriptor * bufferDesc = NULL; 1269 SCSITaskIdentifier request = NULL; 1270 bool mediumIsProtected = true; 1271 1272 1273 STATUS_LOG ( ( 6, "%s[%p]::checkWriteProtection called", getName(), this ) ); 1274 1275 request = GetSCSITask(); 1276 if ( request == NULL ) 1277 { 1278 // Since a SCSI Task could not be gotten, do the safe thing and report 1279 // the medium as write protected. 1280 return true; 1281 } 1282 1283 bufferDesc = IOMemoryDescriptor::withAddress ( modeBuffer, 1284 72, 1285 kIODirectionIn ); 1286 1287 if ( bufferDesc == NULL ) 1288 { 1289 // Since the Mode Sense data buffer descriptor could not be allocated, 1290 // the command cannot be sent to the drive, exit and report the medium 1291 // as write protected. 1292 goto WriteProtectCheckDone; 1293 } 1294 1295 if ( MODE_SENSE_10 ( request, 1296 bufferDesc, 1297 0, 1298 0, 1299 0x3F, 1300 72 ) == true ) 1301 { 1302 // The command was successfully built, now send it 1303 serviceResponse = SendCommand ( request, 0 ); 1304 1305 } 1306 else 1307 { 1308 1309 STATUS_LOG ( ( 1, "%s[%p]::CheckWriteProtection malformed command", getName(), this ) ); 1310 goto WriteProtectCheckDone; 1311 1312 } 1313 1314 if ( ( serviceResponse == kSCSIServiceResponse_TASK_COMPLETE ) && 1315 ( GetTaskStatus( request ) == kSCSITaskStatus_GOOD ) ) 1316 { 1317 1318 if ( ( modeBuffer[3] & 0x80 ) != 0 ) 1319 { 1320 mediumIsProtected = true; 1321 } 1322 else 1323 { 1324 mediumIsProtected = false; 1325 } 1326 1327 } 1328 1329 1330WriteProtectCheckDone: 1331 1332 if ( bufferDesc != NULL ) 1333 { 1334 bufferDesc->release(); 1335 bufferDesc = NULL; 1336 } 1337 1338 if ( request != NULL ) 1339 { 1340 ReleaseSCSITask ( request ); 1341 request = NULL; 1342 } 1343 1344 return mediumIsProtected; 1345} 1346 1347 1348//-------------------------------------------------------------------------------------------------- 1349// PollForMediaRemoval - Polls for media removal. [PROTECTED] 1350//-------------------------------------------------------------------------------------------------- 1351 1352void 1353IOUSBMassStorageUFIDevice::PollForMediaRemoval ( void ) 1354{ 1355 SCSIServiceResponse serviceResponse= kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE; 1356 SCSITaskIdentifier request = NULL; 1357 bool mediaRemoved = false; 1358 1359 1360 if ( isInactive() == true ) 1361 { 1362 fPollingMode = kPollingMode_Suspended; 1363 } 1364 1365 request = GetSCSITask(); 1366 if ( request == NULL ) 1367 { 1368 // A SCSI Task could not be gotten, return immediately. 1369 goto Exit; 1370 } 1371 1372 // Do a TEST_UNIT_READY to generate sense data 1373 if ( TEST_UNIT_READY ( request ) == true ) 1374 { 1375 // The command was successfully built, now send it 1376 serviceResponse = SendCommand( request, 0 ); 1377 1378 } 1379 else 1380 { 1381 1382 PANIC_NOW ( ( "IOUSBMassStorageUFIDevice::PollForMediaRemoval malformed command" ) ); 1383 goto RemoveCheckDone; 1384 1385 } 1386 1387 if ( serviceResponse == kSCSIServiceResponse_TASK_COMPLETE ) 1388 { 1389 1390 bool validSense; 1391 SCSI_Sense_Data senseBuffer; 1392 IOMemoryDescriptor * bufferDesc; 1393 1394 1395 // Check for valid Autosense data. If it was not retrieved from the 1396 // device, explicitly ask for it by sending a REQUEST SENSE command. 1397 validSense = GetAutoSenseData ( request, &senseBuffer ); 1398 if( validSense == false ) 1399 { 1400 1401 bufferDesc = IOMemoryDescriptor::withAddress ( ( void * ) &senseBuffer, 1402 kSenseDefaultSize, 1403 kIODirectionIn ); 1404 if ( bufferDesc == NULL ) 1405 { 1406 1407 STATUS_LOG ( ( 1, "%s[%p]: could not allocate sense buffer descriptor.", getName(), this ) ); 1408 goto RemoveCheckDone; 1409 1410 } 1411 1412 if ( REQUEST_SENSE( request, bufferDesc, kSenseDefaultSize ) == true ) 1413 { 1414 // The command was successfully built, now send it 1415 serviceResponse = SendCommand( request, 0 ); 1416 1417 } 1418 else 1419 { 1420 1421 PANIC_NOW ( ( "IOUSBMassStorageUFIDevice::PollForMediaRemoval malformed command" ) ); 1422 bufferDesc->release(); 1423 goto RemoveCheckDone; 1424 1425 } 1426 1427 bufferDesc->release(); 1428 1429 if ( ( serviceResponse != kSCSIServiceResponse_TASK_COMPLETE ) || 1430 ( GetTaskStatus( request ) != kSCSITaskStatus_GOOD ) ) 1431 { 1432 1433 STATUS_LOG ( ( 2, "%s[%p]: REQUEST_SENSE failed", getName(), this ) ); 1434 goto RemoveCheckDone; 1435 1436 } 1437 1438 } 1439 1440 if ( ( senseBuffer.ADDITIONAL_SENSE_CODE == 0x28 ) || 1441 ( senseBuffer.ADDITIONAL_SENSE_CODE == 0x3A ) ) 1442 { 1443 // It has been determined that media has been removed, clean up and 1444 // exit. 1445 mediaRemoved = true; 1446 1447 } 1448 1449 } 1450 1451 1452RemoveCheckDone: 1453 1454 if ( request != NULL ) 1455 { 1456 1457 ReleaseSCSITask( request ); 1458 request = NULL; 1459 1460 } 1461 if ( mediaRemoved == true ) 1462 { 1463 // Media was removed, set the polling to determine when new media has been inserted 1464 fPollingMode = kPollingMode_NewMedia; 1465 1466 // Message up the chain that we do not have media 1467 messageClients( kIOMessageMediaStateHasChanged, 1468 ( void * ) kIOMediaStateOffline ); 1469 1470 } 1471 1472Exit: 1473 1474 return; 1475} 1476 1477 1478#pragma mark - 1479#pragma mark *** Power Management *** 1480#pragma mark - 1481 1482 1483//-------------------------------------------------------------------------------------------------- 1484// GetNumberOfPowerStateTransitions - Asks the driver for the number of state transitions between 1485// sleep state and the highest power state. 1486// [PROTECTED] 1487//-------------------------------------------------------------------------------------------------- 1488 1489UInt32 1490IOUSBMassStorageUFIDevice::GetNumberOfPowerStateTransitions ( void ) 1491{ 1492 // The number of transitions is the number of states - 1 1493 return ( kIOUSBMassStorageUFIDeviceNumPowerStates - 1 ); 1494} 1495 1496 1497//-------------------------------------------------------------------------------------------------- 1498// InitializePowerManagement - Register the driver with our policy-maker (in the same class). 1499// [PROTECTED] 1500//-------------------------------------------------------------------------------------------------- 1501 1502void 1503IOUSBMassStorageUFIDevice::InitializePowerManagement ( 1504 IOService * provider ) 1505{ 1506 fCurrentPowerState = kIOUSBMassStorageUFIDevicePowerStateActive; 1507 fProposedPowerState = kIOUSBMassStorageUFIDevicePowerStateActive; 1508 1509 // Call our super to get us into the power management tree 1510 super::InitializePowerManagement ( provider ); 1511 1512 // Register ourselves as a "policy maker" for this device. We use 1513 // the number of default power states defined by RBC. 1514 registerPowerDriver ( this, sPowerStates, kIOUSBMassStorageUFIDeviceNumPowerStates ); 1515 1516 // Make sure we clamp the lowest power setting that we voluntarily go 1517 // We only enter kIOUSBMassStorageUFIDevicePowerStateSleep if told by the 1518 // power manager during a system sleep. 1519 changePowerStateTo ( kIOUSBMassStorageUFIDevicePowerStateActive ); 1520 1521} 1522 1523 1524//-------------------------------------------------------------------------------------------------- 1525// GetInitialPowerState - Asks the driver which power state the device is in at startup time. This 1526// function is only called once, right after InitializePowerManagement(). 1527// [PROTECTED] 1528//-------------------------------------------------------------------------------------------------- 1529 1530UInt32 1531IOUSBMassStorageUFIDevice::GetInitialPowerState ( void ) 1532{ 1533 return kIOUSBMassStorageUFIDevicePowerStateActive; 1534} 1535 1536 1537//-------------------------------------------------------------------------------------------------- 1538// HandleCheckPowerState - Checks to see if the power state is "ACTIVE" [PROTECTED] 1539//-------------------------------------------------------------------------------------------------- 1540 1541void 1542IOUSBMassStorageUFIDevice::HandleCheckPowerState ( void ) 1543{ 1544 1545 if ( IsDeviceAccessEnabled ( ) ) 1546 { 1547 1548 super::HandleCheckPowerState ( kIOUSBMassStorageUFIDevicePowerStateActive ); 1549 1550 } 1551 1552} 1553 1554 1555//-------------------------------------------------------------------------------------------------- 1556// TicklePowerManager - Calls activityTickle to tell the power manager we need to be in a certain 1557// state to fulfill I/O. [PROTECTED] 1558//-------------------------------------------------------------------------------------------------- 1559 1560void 1561IOUSBMassStorageUFIDevice::TicklePowerManager ( void ) 1562{ 1563 1564 // Tell the power manager we must be in active state to handle requests 1565 // "active" state means the minimal possible state in which the driver can 1566 // handle I/O. This may be set to standby, but there is no gain to setting 1567 // the drive to standby and then issuing an I/O, it just requires more time. 1568 // Also, if the drive was asleep, it might need a reset which could put it 1569 // in standby mode anyway, so we usually request the max state from the power 1570 // manager 1571 ( void ) super::TicklePowerManager ( kIOUSBMassStorageUFIDevicePowerStateActive ); 1572 1573} 1574 1575 1576//-------------------------------------------------------------------------------------------------- 1577// HandlePowerChange - Checks to see if the power state is "ACTIVE" [PROTECTED] 1578//-------------------------------------------------------------------------------------------------- 1579 1580void 1581IOUSBMassStorageUFIDevice::HandlePowerChange ( void ) 1582{ 1583 1584 STATUS_LOG ( ( 5, "IOUSBMassStorageUFIDevice::HandlePowerChange called\n" ) ); 1585 1586 // Avoid changing power state to lower state when a restart is in progress. 1587 if ( gRestartShutdownFlag != 0 ) 1588 { 1589 1590 if ( fProposedPowerState <= kIOUSBMassStorageUFIDevicePowerStateSleep ) 1591 { 1592 1593 fCurrentPowerState = fProposedPowerState; 1594 1595 } 1596 1597 } 1598 1599 if ( ( fProposedPowerState != fCurrentPowerState ) && 1600 ( isInactive ( ) == false ) ) 1601 { 1602 1603 switch ( fProposedPowerState ) 1604 { 1605 1606 case kIOUSBMassStorageUFIDevicePowerStateSleep: 1607 { 1608 1609 STATUS_LOG ( ( 5, "case kIOUSBMassStorageUFIDevicePowerStateSleep\n" ) ); 1610 1611 DisablePolling(); 1612 1613 fCurrentPowerState = kIOUSBMassStorageUFIDevicePowerStateSleep; 1614 1615 } 1616 break; 1617 1618 case kIOUSBMassStorageUFIDevicePowerStateActive: 1619 { 1620 1621 STATUS_LOG ( ( 5, "case kIOUSBMassStorageUFIDevicePowerStateActive\n" ) ); 1622 1623 fCurrentPowerState = kIOUSBMassStorageUFIDevicePowerStateActive; 1624 1625 if (fMediumPresent == true) 1626 { 1627 1628 // We preserve the state since we already have the media connected 1629 fPollingMode = kPollingMode_MediaRemoval; 1630 1631 } 1632 else 1633 { 1634 1635 fPollingMode = kPollingMode_NewMedia; 1636 1637 } 1638 1639 EnablePolling(); 1640 1641 } 1642 break; 1643 1644 default: 1645 { 1646 1647 PANIC_NOW ( ( "Undefined power state issued\n" ) ); 1648 1649 } 1650 break; 1651 1652 } 1653 1654 } 1655 1656 if ( isInactive ( ) ) 1657 { 1658 1659 fCurrentPowerState = fProposedPowerState; 1660 1661 } 1662 1663} 1664 1665 1666#pragma mark - 1667#pragma mark *** Client Requests Support *** 1668#pragma mark - 1669 1670 1671 1672//-------------------------------------------------------------------------------------------------- 1673// IssueRead - Performs the Synchronous Read Request [PROTECTED] 1674//-------------------------------------------------------------------------------------------------- 1675 1676IOReturn 1677IOUSBMassStorageUFIDevice::IssueRead ( IOMemoryDescriptor * buffer, 1678 UInt64 startBlock, 1679 UInt64 blockCount ) 1680{ 1681 1682 SCSIServiceResponse serviceResponse = kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE; 1683 SCSITaskIdentifier request; 1684 1685 1686 STATUS_LOG ( ( 6, "%s[%p]: syncRead Attempted", getName(), this ) ); 1687 1688 request = GetSCSITask ( ); 1689 1690 if ( READ_10 ( request, 1691 buffer, 1692 fMediumBlockSize, 1693 0, 1694 0, 1695 0, 1696 ( SCSICmdField4Byte ) startBlock, 1697 ( SCSICmdField2Byte ) blockCount ) == false ) 1698 { 1699 1700 // The command was successfully built, now send it 1701 serviceResponse = SendCommand( request, 0 ); 1702 1703 } 1704 else 1705 { 1706 1707 PANIC_NOW(( "IOUSBMassStorageUFIDevice::IssueRead malformed command" ) ); 1708 1709 } 1710 1711 ReleaseSCSITask ( request ); 1712 1713 if ( serviceResponse == kSCSIServiceResponse_TASK_COMPLETE ) 1714 { 1715 1716 return kIOReturnSuccess; 1717 1718 } 1719 else 1720 { 1721 1722 return kIOReturnError; 1723 1724 } 1725 1726} 1727 1728 1729//-------------------------------------------------------------------------------------------------- 1730// IssueRead - Performs the Asynchronous Read Request [PROTECTED] 1731//-------------------------------------------------------------------------------------------------- 1732 1733IOReturn 1734IOUSBMassStorageUFIDevice::IssueRead ( IOMemoryDescriptor * buffer, 1735 UInt64 startBlock, 1736 UInt64 blockCount, 1737 void * clientData ) 1738{ 1739 1740 IOReturn status = kIOReturnSuccess; 1741 SCSITaskIdentifier request; 1742 1743 1744 STATUS_LOG ( ( 6, "%s[%p]: asyncRead Attempted", getName(), this ) ); 1745 1746 request = GetSCSITask(); 1747 1748 if (READ_10( request, 1749 buffer, 1750 fMediumBlockSize, 1751 0, 1752 0, 1753 0, 1754 ( SCSICmdField4Byte ) startBlock, 1755 ( SCSICmdField2Byte ) blockCount ) == true ) 1756 { 1757 1758 // The command was successfully built, now send it 1759 SetApplicationLayerReference( request, clientData ); 1760 STATUS_LOG ( ( 6, "%s[%p]::IssueRead send command.", getName(), this ) ); 1761 SendCommand( request, 0, &this->AsyncReadWriteComplete ); 1762 1763 } 1764 else 1765 { 1766 1767 PANIC_NOW(( "IOUSBMassStorageUFIDevice::IssueWrite malformed command" ) ); 1768 status = kIOReturnError; 1769 1770 } 1771 1772 return status; 1773} 1774 1775 1776//-------------------------------------------------------------------------------------------------- 1777// IssueWrite - Performs the Synchronous Write Request [PROTECTED] 1778//-------------------------------------------------------------------------------------------------- 1779 1780IOReturn 1781IOUSBMassStorageUFIDevice::IssueWrite ( IOMemoryDescriptor * buffer, 1782 UInt64 startBlock, 1783 UInt64 blockCount ) 1784{ 1785 1786 SCSIServiceResponse serviceResponse = kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE; 1787 SCSITaskIdentifier request; 1788 1789 1790 STATUS_LOG ( ( 6, "%s[%p]: syncWrite Attempted", getName(), this ) ); 1791 1792 request = GetSCSITask(); 1793 if ( WRITE_10 ( request, 1794 buffer, 1795 fMediumBlockSize, 1796 0, 1797 0, 1798 0, 1799 ( SCSICmdField4Byte ) startBlock, 1800 ( SCSICmdField2Byte ) blockCount ) == true ) 1801 { 1802 // The command was successfully built, now send it 1803 serviceResponse = SendCommand( request, 0 ); 1804 1805 } 1806 else 1807 { 1808 PANIC_NOW ( ( "IOUSBMassStorageUFIDevice::IssueWrite malformed command" ) ); 1809 } 1810 1811 ReleaseSCSITask ( request ); 1812 1813 if ( serviceResponse == kSCSIServiceResponse_TASK_COMPLETE ) 1814 { 1815 return kIOReturnSuccess; 1816 } 1817 else 1818 { 1819 return kIOReturnError; 1820 } 1821 1822} 1823 1824 1825//-------------------------------------------------------------------------------------------------- 1826// IssueWrite - Performs the Asynchronous Write Request [PROTECTED] 1827//-------------------------------------------------------------------------------------------------- 1828 1829IOReturn 1830IOUSBMassStorageUFIDevice::IssueWrite ( IOMemoryDescriptor * buffer, 1831 UInt64 startBlock, 1832 UInt64 blockCount, 1833 void * clientData ) 1834{ 1835 1836 IOReturn status = kIOReturnSuccess; 1837 SCSITaskIdentifier request; 1838 1839 1840 STATUS_LOG ( ( 6, "%s[%p]:: asyncWrite Attempted", getName(), this ) ); 1841 1842 request = GetSCSITask(); 1843 1844 if ( WRITE_10 ( request, 1845 buffer, 1846 fMediumBlockSize, 1847 0, 1848 0, 1849 0, 1850 ( SCSICmdField4Byte ) startBlock, 1851 ( SCSICmdField2Byte ) blockCount ) == true ) 1852 { 1853 // The command was successfully built, now send it 1854 SetApplicationLayerReference ( request, clientData ); 1855 STATUS_LOG ( ( 6, "%s[%p]::IssueWrite send command.", getName(), this ) ); 1856 SendCommand ( request, 0, &this->AsyncReadWriteComplete ); 1857 1858 } 1859 else 1860 { 1861 PANIC_NOW ( ( "IOUSBMassStorageUFIDevice::IssueWrite malformed command" ) ); 1862 } 1863 1864 return status; 1865 1866} 1867 1868 1869//-------------------------------------------------------------------------------------------------- 1870// SyncReadWrite - Translates a synchronous I/O request into a read or a write. [PUBLIC] 1871//-------------------------------------------------------------------------------------------------- 1872 1873IOReturn 1874IOUSBMassStorageUFIDevice::SyncReadWrite ( IOMemoryDescriptor * buffer, 1875 UInt64 startBlock, 1876 UInt64 blockCount, 1877 UInt64 blockSize ) 1878{ 1879 1880 UNUSED ( blockSize ); 1881 1882 IODirection direction; 1883 IOReturn theErr; 1884 1885 1886 direction = buffer->getDirection(); 1887 1888 if ( direction == kIODirectionIn ) 1889 { 1890 theErr = IssueRead( buffer, startBlock, blockCount ); 1891 } 1892 else if ( direction == kIODirectionOut ) 1893 { 1894 theErr = IssueWrite( buffer, startBlock, blockCount ); 1895 } 1896 else 1897 { 1898 1899 STATUS_LOG ( ( 1, "%s[%p]: doSyncReadWrite bad direction argument", getName(), this ) ); 1900 theErr = kIOReturnBadArgument; 1901 1902 } 1903 1904 return theErr; 1905 1906} 1907 1908 1909//-------------------------------------------------------------------------------------------------- 1910// AsyncReadWrite - Translates a asynchronous I/O request into a read or a write. [PUBLIC] 1911//-------------------------------------------------------------------------------------------------- 1912 1913IOReturn 1914IOUSBMassStorageUFIDevice::AsyncReadWrite ( IOMemoryDescriptor * buffer, 1915 UInt64 startBlock, 1916 UInt64 blockCount, 1917 UInt64 blockSize, 1918 void * clientData ) 1919{ 1920 1921 UNUSED ( blockSize ); 1922 1923 1924 IODirection direction; 1925 IOReturn theErr; 1926 1927 1928 direction = buffer->getDirection(); 1929 if ( direction == kIODirectionIn ) 1930 { 1931 1932 IssueRead( buffer, startBlock, blockCount, clientData ); 1933 theErr = kIOReturnSuccess; 1934 1935 } 1936 else if ( direction == kIODirectionOut ) 1937 { 1938 1939 IssueWrite( buffer, startBlock, blockCount, clientData ); 1940 theErr = kIOReturnSuccess; 1941 1942 } 1943 else 1944 { 1945 1946 STATUS_LOG ( ( 1, "%s[%p]: doAsyncReadWrite bad direction argument", getName(), this ) ); 1947 theErr = kIOReturnBadArgument; 1948 1949 } 1950 1951 return theErr; 1952 1953} 1954 1955 1956//-------------------------------------------------------------------------------------------------- 1957// EjectTheMedium - Changes the polling mode to poll for medium removal. [PUBLIC] 1958//-------------------------------------------------------------------------------------------------- 1959 1960IOReturn 1961IOUSBMassStorageUFIDevice::EjectTheMedium ( void ) 1962{ 1963 1964 STATUS_LOG ( ( 6, "%s[%p]::EjectTheMedium called", getName(), this ) ); 1965 1966 ResetMediumCharacteristics(); 1967 1968 // Set the polling to determine when media has been removed 1969 if ( fPollingMode != kPollingMode_MediaRemoval ) 1970 { 1971 1972 fPollingMode = kPollingMode_MediaRemoval; 1973 1974 EnablePolling(); 1975 1976 } 1977 1978 return kIOReturnSuccess; 1979 1980} 1981 1982 1983//-------------------------------------------------------------------------------------------------- 1984// FormatMedium - Currently does nothing. [PUBLIC] 1985//-------------------------------------------------------------------------------------------------- 1986 1987IOReturn 1988IOUSBMassStorageUFIDevice::FormatMedium ( UInt64 blockCount, UInt64 blockSize ) 1989{ 1990 1991 UNUSED ( blockCount ); 1992 UNUSED ( blockSize ); 1993 1994 IOReturn theErr = kIOReturnSuccess; 1995 1996 STATUS_LOG ( ( 6, "%s[%p]::FormatMedium called", getName(), this ) ); 1997 1998 return theErr; 1999 2000} 2001 2002 2003//-------------------------------------------------------------------------------------------------- 2004// GetFormatCapacities - Currently does nothing. [ PUBLIC] 2005//-------------------------------------------------------------------------------------------------- 2006 2007UInt32 2008IOUSBMassStorageUFIDevice::GetFormatCapacities( UInt64 * capacities, 2009 UInt32 capacitiesMaxCount ) const 2010{ 2011 2012 UNUSED ( capacities ); 2013 UNUSED ( capacitiesMaxCount ); 2014 2015 STATUS_LOG ( ( 6, "%s[%p]::doGetFormatCapacities called", getName(), this ) ); 2016 2017 return 0; 2018 2019} 2020 2021 2022#pragma mark - 2023#pragma mark *** Device Information Retrieval Methods *** 2024#pragma mark - 2025 2026 2027//-------------------------------------------------------------------------------------------------- 2028// GetVendorString - Returns the vendor string. [PUBLIC] 2029//-------------------------------------------------------------------------------------------------- 2030 2031char * 2032IOUSBMassStorageUFIDevice::GetVendorString ( void ) 2033{ 2034 2035 OSString * vendorString; 2036 2037 STATUS_LOG ( ( 6, "%s[%p]::%s", getName(), this, __FUNCTION__ ) ); 2038 2039 vendorString = ( OSString * ) fDeviceCharacteristicsDictionary->getObject( kIOPropertyVendorNameKey ); 2040 if ( vendorString != NULL ) 2041 { 2042 return ( ( char * ) vendorString->getCStringNoCopy ( ) ); 2043 } 2044 else 2045 { 2046 return ( char * ) "NULL STRING"; 2047 } 2048 2049} 2050 2051 2052//-------------------------------------------------------------------------------------------------- 2053// GetProductString - Returns the Product String. [PUBLIC] 2054//-------------------------------------------------------------------------------------------------- 2055 2056char * 2057IOUSBMassStorageUFIDevice::GetProductString ( void ) 2058{ 2059 2060 OSString * productString; 2061 2062 2063 STATUS_LOG ( ( 6, "%s[%p]::%s", getName(), this, __FUNCTION__ ) ); 2064 2065 productString = ( OSString * ) fDeviceCharacteristicsDictionary->getObject ( kIOPropertyProductNameKey ); 2066 if ( productString != NULL ) 2067 { 2068 return ( ( char * ) productString->getCStringNoCopy ( ) ); 2069 } 2070 else 2071 { 2072 return ( char * ) "NULL STRING"; 2073 } 2074 2075} 2076 2077 2078//-------------------------------------------------------------------------------------------------- 2079// GetRevisionString - Returns the Revision String. [PUBLIC] 2080//-------------------------------------------------------------------------------------------------- 2081 2082char * 2083IOUSBMassStorageUFIDevice::GetRevisionString ( void ) 2084{ 2085 2086 OSString * revisionString; 2087 2088 2089 STATUS_LOG ( ( 6, "%s[%p]::%s", getName(), this, __FUNCTION__ ) ); 2090 2091 revisionString = ( OSString * ) fDeviceCharacteristicsDictionary->getObject ( kIOPropertyProductRevisionLevelKey ); 2092 if ( revisionString ) 2093 { 2094 return ( ( char * ) revisionString->getCStringNoCopy ( ) ); 2095 } 2096 else 2097 { 2098 return ( char * ) "NULL STRING"; 2099 } 2100 2101} 2102 2103 2104//-------------------------------------------------------------------------------------------------- 2105// GetProtocolCharacteristicsDictionary - Returns the Protocol Characteristics Dictionary. [PUBLIC] 2106//-------------------------------------------------------------------------------------------------- 2107 2108OSDictionary * 2109IOUSBMassStorageUFIDevice::GetProtocolCharacteristicsDictionary ( void ) 2110{ 2111 2112 STATUS_LOG ( ( 6, "%s[%p]::%s", getName(), this, __FUNCTION__ ) ); 2113 return ( OSDictionary * ) getProperty( kIOPropertyProtocolCharacteristicsKey ); 2114 2115} 2116 2117 2118//-------------------------------------------------------------------------------------------------- 2119// GetDeviceCharacteristicsDictionary - Returns the Device Characteristics Dictionary. [PUBLIC] 2120//-------------------------------------------------------------------------------------------------- 2121 2122OSDictionary * 2123IOUSBMassStorageUFIDevice::GetDeviceCharacteristicsDictionary ( void ) 2124{ 2125 2126 STATUS_LOG ( ( 6, "%s[%p]::%s", getName(), this, __FUNCTION__ ) ); 2127 return fDeviceCharacteristicsDictionary; 2128 2129} 2130 2131 2132#pragma mark - 2133#pragma mark *** Query methods to report device characteristics *** 2134#pragma mark - 2135 2136 2137//-------------------------------------------------------------------------------------------------- 2138// ReportDeviceMaxBlocksReadTransfer - Reports max number of blocks a device can handle per read. 2139// [PUBLIC] 2140//-------------------------------------------------------------------------------------------------- 2141 2142UInt64 2143IOUSBMassStorageUFIDevice::ReportDeviceMaxBlocksReadTransfer ( void ) 2144{ 2145 2146 UInt64 maxBlockCount; 2147 2148 2149 STATUS_LOG ( ( 6, "%s[%p]::%s", getName(), this, __FUNCTION__ ) ); 2150 2151 maxBlockCount = 256; 2152 2153 return maxBlockCount; 2154 2155} 2156 2157 2158//-------------------------------------------------------------------------------------------------- 2159// ReportDeviceMaxBlocksWriteTransfer - Reports max number of blocks a device can handle per write. 2160// [PUBLIC] 2161//-------------------------------------------------------------------------------------------------- 2162 2163UInt64 2164IOUSBMassStorageUFIDevice::ReportDeviceMaxBlocksWriteTransfer ( void ) 2165{ 2166 2167 UInt64 maxBlockCount; 2168 2169 2170 STATUS_LOG ( ( 6, "%s[%p]::%s", getName(), this, __FUNCTION__ ) ); 2171 2172 maxBlockCount = 256; 2173 2174 return maxBlockCount; 2175 2176} 2177 2178 2179#pragma mark - 2180#pragma mark *** Query methods to report installed medium characteristics *** 2181#pragma mark - 2182 2183//-------------------------------------------------------------------------------------------------- 2184// ReportMediumBlockSize - Reports the medium block size. [PUBLIC] 2185//-------------------------------------------------------------------------------------------------- 2186 2187UInt64 2188IOUSBMassStorageUFIDevice::ReportMediumBlockSize ( void ) 2189{ 2190 2191 STATUS_LOG ( ( 5, "%s[%p]::ReportMediumBlockSize blockSize = %ld", getName(), this, ( UInt32 ) fMediumBlockSize ) ); 2192 return fMediumBlockSize; 2193 2194} 2195 2196 2197//-------------------------------------------------------------------------------------------------- 2198// ReportMediumTotalBlockCount - Reports the number of blocks on the medium [PUBLIC] 2199//-------------------------------------------------------------------------------------------------- 2200 2201UInt64 2202IOUSBMassStorageUFIDevice::ReportMediumTotalBlockCount ( void ) 2203{ 2204 2205 STATUS_LOG ( ( 5, "%s[%p]::ReportMediumTotalBlockCount maxBlock = %ld", getName(), this, fMediumBlockCount ) ); 2206 return fMediumBlockCount; 2207 2208} 2209 2210 2211//-------------------------------------------------------------------------------------------------- 2212// ReportMediumWriteProtection - Reports whether the medium is write protected PUBLIC] 2213//-------------------------------------------------------------------------------------------------- 2214 2215bool 2216IOUSBMassStorageUFIDevice::ReportMediumWriteProtection ( void ) 2217{ 2218 2219 STATUS_LOG ( ( 5, "%s[%p]::ReportMediumWriteProtection isWriteProtected = %d.", getName(), this, fMediumIsWriteProtected ) ); 2220 return fMediumIsWriteProtected; 2221 2222} 2223 2224 2225#pragma mark - 2226#pragma mark *** Command Builders Utility Methods *** 2227#pragma mark - 2228 2229 2230// Utility routines used by all SCSI Command Set objects 2231 2232//-------------------------------------------------------------------------------------------------- 2233// IsParameterValid - Validate Parameter used for 1 bit to 1 byte paramaters [PROTECTED] 2234//-------------------------------------------------------------------------------------------------- 2235 2236bool 2237IOUSBMassStorageUFIDevice::IsParameterValid ( SCSICmdField1Byte param, 2238 SCSICmdField1Byte mask ) 2239{ 2240 2241 STATUS_LOG ( ( 6, "%s[%p]::IsParameterValid called", getName(), this ) ); 2242 2243 if ( ( param | mask ) != mask ) 2244 { 2245 2246 STATUS_LOG ( ( 4, "%s[%p]:: param = %x not valid, mask = %x", getName(), this, param, mask ) ); 2247 return false; 2248 2249 } 2250 2251 return true; 2252 2253} 2254 2255 2256//-------------------------------------------------------------------------------------------------- 2257// IsParameterValid - Validate Parameter used for 9 bit to 2 byte paramaters [PROTECTED] 2258//-------------------------------------------------------------------------------------------------- 2259 2260bool 2261IOUSBMassStorageUFIDevice::IsParameterValid ( SCSICmdField2Byte param, 2262 SCSICmdField2Byte mask ) 2263{ 2264 2265 STATUS_LOG ( ( 6, "%s[%p]::IsParameterValid called", getName(), this ) ); 2266 2267 if ( ( param | mask ) != mask ) 2268 { 2269 2270 STATUS_LOG ( ( 4, "%s[%p]:: param = %x not valid, mask = %x", getName(), this, param, mask ) ); 2271 return false; 2272 2273 } 2274 2275 return true; 2276 2277} 2278 2279 2280////-------------------------------------------------------------------------------------------------- 2281// IsParameterValid - Validate Parameter used for 17 bit to 4 byte paramaters [PROTECTED] 2282//-------------------------------------------------------------------------------------------------- 2283 2284bool 2285IOUSBMassStorageUFIDevice::IsParameterValid ( SCSICmdField4Byte param, 2286 SCSICmdField4Byte mask ) 2287{ 2288 2289 STATUS_LOG ( ( 6, "%s[%p]::IsParameterValid called", getName(), this ) ); 2290 2291 if ( ( param | mask ) != mask ) 2292 { 2293 2294 STATUS_LOG ( ( 4, "%s[%p]:: param = %x not valid, mask = %x", getName(), this, 2295 (unsigned int) param, (unsigned int) mask ) ); 2296 return false; 2297 2298 } 2299 2300 return true; 2301 2302} 2303 2304 2305#pragma mark - 2306#pragma mark *** Command Builder Methods *** 2307#pragma mark - 2308 2309 2310//-------------------------------------------------------------------------------------------------- 2311// FORMAT_UNIT - Command Builder [PROTECTED] 2312//-------------------------------------------------------------------------------------------------- 2313 2314bool 2315IOUSBMassStorageUFIDevice::FORMAT_UNIT( 2316 SCSITaskIdentifier request, 2317 IOMemoryDescriptor * dataBuffer, 2318 IOByteCount defectListSize, 2319 SCSICmdField1Byte TRACK_NUMBER, 2320 SCSICmdField2Byte INTERLEAVE ) 2321{ 2322 2323 UNUSED ( TRACK_NUMBER ); 2324 2325 STATUS_LOG ( ( 6, "%s[%p]::FORMAT_UNIT called", getName(), this ) ); 2326 2327 if ( ResetForNewTask ( request ) == false ) 2328 { 2329 2330 STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) ); 2331 return false; 2332 2333 } 2334 2335 // Do the pre-flight check on the passed in parameters 2336 if ( IsParameterValid ( INTERLEAVE, kSCSICmdFieldMask2Byte ) == false ) 2337 { 2338 2339 STATUS_LOG ( ( 4, "%s[%p]:: INTERLEAVE = %x not valid", getName(), this, INTERLEAVE ) ); 2340 return false; 2341 2342 } 2343 2344 if ( defectListSize > 0 ) 2345 { 2346 // We have data to send to the device, 2347 // make sure that we were given a valid buffer 2348 if ( IsMemoryDescriptorValid( dataBuffer, defectListSize ) 2349 == false ) 2350 { 2351 2352 STATUS_LOG ( ( 4, "%s[%p]:: dataBuffer = %x not valid, defectListSize = %x", 2353 getName(), this, dataBuffer, defectListSize ) ); 2354 return false; 2355 2356 } 2357 2358 } 2359 2360 // This is a 6-Byte command, fill out the cdb appropriately 2361 SetCommandDescriptorBlock ( request, 2362 kSCSICmd_FORMAT_UNIT, 2363 0x00, 2364 0x00, 2365 ( INTERLEAVE >> 8 ) & 0xFF, 2366 INTERLEAVE & 0xFF, 2367 0x00 ); 2368 2369 // The client has requested a DEFECT LIST be sent to the device 2370 // to be used with the format command 2371 SetDataTransferDirection ( request, 2372 kSCSIDataTransfer_FromInitiatorToTarget ); 2373 SetDataBuffer ( request, 2374 dataBuffer ); 2375 2376 return true; 2377 2378} 2379 2380 2381//-------------------------------------------------------------------------------------------------- 2382// INQUIRY - Command Builder [PROTECTED] 2383//-------------------------------------------------------------------------------------------------- 2384 2385bool 2386IOUSBMassStorageUFIDevice::INQUIRY ( 2387 SCSITaskIdentifier request, 2388 IOMemoryDescriptor *dataBuffer, 2389 SCSICmdField1Byte PAGE_OR_OPERATION_CODE, 2390 SCSICmdField1Byte ALLOCATION_LENGTH ) 2391{ 2392 2393 STATUS_LOG ( ( 6, "%s[%p]::INQUIRY called", getName(), this ) ); 2394 2395 if ( ResetForNewTask( request ) == false ) 2396 { 2397 2398 STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) ); 2399 return false; 2400 2401 } 2402 2403 if ( IsParameterValid ( PAGE_OR_OPERATION_CODE, kSCSICmdFieldMask1Byte ) == false ) 2404 { 2405 2406 STATUS_LOG ( ( 4, "%s[%p]:: PAGE_OR_OPERATION_CODE = %x not valid", 2407 getName(), this, PAGE_OR_OPERATION_CODE ) ); 2408 return false; 2409 2410 } 2411 2412 if ( IsParameterValid ( ALLOCATION_LENGTH, kSCSICmdFieldMask1Byte ) == false ) 2413 { 2414 2415 STATUS_LOG ( ( 4, "%s[%p]:: ALLOCATION_LENGTH = %x not valid", getName(), this, ALLOCATION_LENGTH ) ); 2416 return false; 2417 2418 } 2419 2420 if ( IsMemoryDescriptorValid( dataBuffer, ALLOCATION_LENGTH ) == false ) 2421 { 2422 STATUS_LOG ( ( 4, "%s[%p]:: dataBuffer = %x not valid, ALLOCATION_LENGTH = %x", 2423 getName(), this, dataBuffer, ALLOCATION_LENGTH ) ); 2424 return false; 2425 } 2426 2427 // This is a 6-Byte command, fill out the cdb appropriately 2428 SetCommandDescriptorBlock ( request, 2429 kSCSICmd_INQUIRY, 2430 0x00, 2431 PAGE_OR_OPERATION_CODE, 2432 0x00, 2433 ALLOCATION_LENGTH, 2434 0x00 ); 2435 2436 SetDataTransferDirection ( request, 2437 kSCSIDataTransfer_FromTargetToInitiator ); 2438 SetDataBuffer ( request, 2439 dataBuffer ); 2440 SetRequestedDataTransferCount ( request, 2441 ALLOCATION_LENGTH ); 2442 2443 return true; 2444 2445} 2446 2447 2448//-------------------------------------------------------------------------------------------------- 2449// MODE_SELECT_10 - Command Builder [PROTECTED] 2450//-------------------------------------------------------------------------------------------------- 2451 2452bool 2453IOUSBMassStorageUFIDevice::MODE_SELECT_10 ( 2454 SCSITaskIdentifier request, 2455 IOMemoryDescriptor *dataBuffer, 2456 SCSICmdField1Bit PF, 2457 SCSICmdField1Bit SP, 2458 SCSICmdField2Byte PARAMETER_LIST_LENGTH ) 2459{ 2460 2461 STATUS_LOG ( ( 6, "%s[%p]::MODE_SELECT_10 called", getName(), this ) ); 2462 2463 if ( ResetForNewTask( request ) == false ) 2464 { 2465 STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) ); 2466 return false; 2467 } 2468 2469 if( IsParameterValid( PF, kSCSICmdFieldMask1Bit ) == false ) 2470 { 2471 STATUS_LOG ( ( 4, "%s[%p]:: PF = %x not valid", getName(), this, PF ) ); 2472 return false; 2473 } 2474 2475 if( IsParameterValid( SP, kSCSICmdFieldMask1Bit ) == false ) 2476 { 2477 STATUS_LOG ( ( 4, "%s[%p]:: SP = %x not valid", getName(), this, SP ) ); 2478 return false; 2479 } 2480 2481 if( IsParameterValid( PARAMETER_LIST_LENGTH, kSCSICmdFieldMask2Byte ) == false ) 2482 { 2483 STATUS_LOG ( ( 4, "%s[%p]:: PARAMETER_LIST_LENGTH = %x not valid", 2484 getName(), this, PARAMETER_LIST_LENGTH ) ); 2485 return false; 2486 } 2487 2488 if( IsMemoryDescriptorValid( dataBuffer, PARAMETER_LIST_LENGTH ) == false ) 2489 { 2490 STATUS_LOG ( ( 4, "%s[%p]:: dataBuffer = %x not valid, PARAMETER_LIST_LENGTH = %x", 2491 getName(), this, dataBuffer, PARAMETER_LIST_LENGTH ) ); 2492 return false; 2493 } 2494 2495 // This is a 10-Byte command, fill out the cdb appropriately 2496 SetCommandDescriptorBlock ( request, 2497 kSCSICmd_MODE_SELECT_10, 2498 ( PF << 4 ) | SP, 2499 0x00, 2500 0x00, 2501 0x00, 2502 0x00, 2503 0x00, 2504 ( PARAMETER_LIST_LENGTH >> 8 ) & 0xFF, 2505 PARAMETER_LIST_LENGTH & 0xFF, 2506 0x00 ); 2507 2508 SetDataTransferDirection ( request, 2509 kSCSIDataTransfer_FromInitiatorToTarget ); 2510 SetDataBuffer ( request, 2511 dataBuffer ); 2512 SetRequestedDataTransferCount ( request, 2513 PARAMETER_LIST_LENGTH ); 2514 2515 return true; 2516 2517} 2518 2519 2520//-------------------------------------------------------------------------------------------------- 2521// MODE_SENSE_10 - Command Builder [PROTECTED] 2522//-------------------------------------------------------------------------------------------------- 2523 2524bool 2525IOUSBMassStorageUFIDevice::MODE_SENSE_10 ( 2526 SCSITaskIdentifier request, 2527 IOMemoryDescriptor *dataBuffer, 2528 SCSICmdField1Bit DBD, 2529 SCSICmdField2Bit PC, 2530 SCSICmdField6Bit PAGE_CODE, 2531 SCSICmdField2Byte ALLOCATION_LENGTH ) 2532{ 2533 2534 STATUS_LOG ( ( 6, "%s[%p]::MODE_SENSE_10 called", getName(), this ) ); 2535 2536 if ( ResetForNewTask ( request ) == false ) 2537 { 2538 STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) ); 2539 return false; 2540 } 2541 2542 if( IsParameterValid ( DBD, kSCSICmdFieldMask1Bit ) == false ) 2543 { 2544 STATUS_LOG ( ( 4, "%s[%p]:: DBD = %x not valid", getName(), this, DBD ) ); 2545 return false; 2546 } 2547 2548 if( IsParameterValid ( PC, kSCSICmdFieldMask2Bit ) == false ) 2549 { 2550 STATUS_LOG ( ( 4, "%s[%p]:: PC = %x not valid", getName(), this, PC ) ); 2551 return false; 2552 } 2553 2554 if( IsParameterValid ( PAGE_CODE, kSCSICmdFieldMask6Bit ) == false ) 2555 { 2556 STATUS_LOG ( ( 4, "%s[%p]:: PAGE_CODE = %x not valid", getName(), this, PAGE_CODE ) ); 2557 return false; 2558 } 2559 2560 if( IsParameterValid ( ALLOCATION_LENGTH, kSCSICmdFieldMask2Byte ) == false ) 2561 { 2562 STATUS_LOG ( ( 4, "%s[%p]:: ALLOCATION_LENGTH = %x not valid", getName(), this, ALLOCATION_LENGTH ) ); 2563 return false; 2564 } 2565 2566 if( IsMemoryDescriptorValid ( dataBuffer, ALLOCATION_LENGTH ) == false ) 2567 { 2568 STATUS_LOG ( (4, "%s[%p]:: dataBuffer = %x not valid, ALLOCATION_LENGTH = %x", 2569 dataBuffer, ALLOCATION_LENGTH, getName(), this ) ); 2570 return false; 2571 } 2572 2573 // This is a 10-Byte command, fill out the cdb appropriately 2574 SetCommandDescriptorBlock ( request, 2575 kSCSICmd_MODE_SENSE_10, 2576 ( DBD << 3 ), 2577 ( PC << 6 ) | PAGE_CODE, 2578 0x00, 2579 0x00, 2580 0x00, 2581 0x00, 2582 ( ALLOCATION_LENGTH >> 8 ) & 0xFF, 2583 ALLOCATION_LENGTH & 0xFF, 2584 0x00 ); 2585 2586 SetDataTransferDirection ( request, 2587 kSCSIDataTransfer_FromTargetToInitiator ); 2588 SetDataBuffer ( request, 2589 dataBuffer ); 2590 SetRequestedDataTransferCount ( request, 2591 ALLOCATION_LENGTH ); 2592 2593 return true; 2594 2595} 2596 2597 2598//-------------------------------------------------------------------------------------------------- 2599// PREVENT_ALLOW_MEDIUM_REMOVAL - Command Builder [PROTECTED] 2600//-------------------------------------------------------------------------------------------------- 2601 2602bool 2603IOUSBMassStorageUFIDevice::PREVENT_ALLOW_MEDIUM_REMOVAL( 2604 SCSITaskIdentifier request, 2605 SCSICmdField1Bit PREVENT ) 2606{ 2607 2608 STATUS_LOG ( ( 6, "%s[%p]::PREVENT_ALLOW_MEDIUM_REMOVAL called", getName(), this ) ); 2609 2610 if ( ResetForNewTask( request ) == false ) 2611 { 2612 STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) ); 2613 return false; 2614 } 2615 2616 if( IsParameterValid( PREVENT, kSCSICmdFieldMask2Bit ) == false ) 2617 { 2618 STATUS_LOG ( ( 4, "%s[%p]:: PREVENT = %x not valid", getName(), this, PREVENT ) ); 2619 return false; 2620 } 2621 2622 // This is a 6-Byte command, fill out the cdb appropriately 2623 SetCommandDescriptorBlock ( request, 2624 kSCSICmd_PREVENT_ALLOW_MEDIUM_REMOVAL, 2625 0x00, 2626 0x00, 2627 0x00, 2628 PREVENT, 2629 0x00 ); 2630 2631 SetDataTransferDirection ( request, 2632 kSCSIDataTransfer_NoDataTransfer ); 2633 2634 return true; 2635 2636} 2637 2638 2639//-------------------------------------------------------------------------------------------------- 2640// READ_10 - Command Builder [PROTECTED] 2641//-------------------------------------------------------------------------------------------------- 2642 2643bool 2644IOUSBMassStorageUFIDevice::READ_10 ( 2645 SCSITaskIdentifier request, 2646 IOMemoryDescriptor * dataBuffer, 2647 UInt32 blockSize, 2648 SCSICmdField1Bit DPO, 2649 SCSICmdField1Bit FUA, 2650 SCSICmdField1Bit RELADR, 2651 SCSICmdField4Byte LOGICAL_BLOCK_ADDRESS, 2652 SCSICmdField2Byte TRANSFER_LENGTH ) 2653{ 2654 2655 UInt32 requestedByteCount; 2656 2657 2658 STATUS_LOG ( ( 6, "%s[%p]::READ_10 called", getName(), this ) ); 2659 2660 if ( ResetForNewTask( request ) == false ) 2661 { 2662 STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) ); 2663 return false; 2664 } 2665 2666 // Check the validity of the media 2667 if ( blockSize == 0 ) 2668 { 2669 // There is no media in the device, or it has an undetermined 2670 // blocksize (could be unformatted). 2671 return false; 2672 } 2673 2674 // Make sure that we were given a valid buffer 2675 if ( dataBuffer == NULL ) 2676 { 2677 return false; 2678 } 2679 else 2680 { 2681 // We have a valid buffer object, check that it has the required 2682 // capcity for the data to be transfered. 2683 requestedByteCount = TRANSFER_LENGTH * blockSize; 2684 2685 // We know the number of bytes to transfer, now check that the 2686 // buffer is large enough to accomodate this request. 2687 if ( dataBuffer->getLength() < requestedByteCount ) 2688 { 2689 return false; 2690 } 2691 2692 } 2693 2694 // Do the pre-flight check on the passed in parameters 2695 if ( IsParameterValid( DPO, kSCSICmdFieldMask1Bit ) == false ) 2696 { 2697 STATUS_LOG ( ( 4, "%s[%p]:: DPO = %x not valid", getName(), this, DPO ) ); 2698 return false; 2699 } 2700 2701 if ( IsParameterValid( FUA, kSCSICmdFieldMask1Bit ) == false ) 2702 { 2703 STATUS_LOG ( ( 4, "%s[%p]:: FUA = %x not valid", getName(), this, FUA ) ); 2704 return false; 2705 } 2706 2707 if ( IsParameterValid( RELADR, kSCSICmdFieldMask1Bit ) == false ) 2708 { 2709 STATUS_LOG ( ( 4, "%s[%p]:: RELADR = %x not valid", getName(), this, RELADR ) ); 2710 return false; 2711 } 2712 2713 if ( IsParameterValid( LOGICAL_BLOCK_ADDRESS, kSCSICmdFieldMask4Byte ) == false ) 2714 { 2715 STATUS_LOG ( ( 4, "%s[%p]:: LOGICAL_BLOCK_ADDRESS = %x not valid", 2716 getName(), this, LOGICAL_BLOCK_ADDRESS ) ); 2717 return false; 2718 } 2719 2720 if ( IsParameterValid( TRANSFER_LENGTH, kSCSICmdFieldMask2Byte ) == false ) 2721 { 2722 STATUS_LOG ( ( 4, "%s[%p]:: TRANSFER_LENGTH = %x not valid", 2723 getName(), this, TRANSFER_LENGTH ) ); 2724 return false; 2725 } 2726 2727 // This is a 10-Byte command, fill out the cdb appropriately 2728 SetCommandDescriptorBlock ( request, 2729 kSCSICmd_READ_10, 2730 ( DPO << 4 ) | ( FUA << 3 ) | RELADR, 2731 ( LOGICAL_BLOCK_ADDRESS >> 24 ) & 0xFF, 2732 ( LOGICAL_BLOCK_ADDRESS >> 16 ) & 0xFF, 2733 ( LOGICAL_BLOCK_ADDRESS >> 8 ) & 0xFF, 2734 LOGICAL_BLOCK_ADDRESS & 0xFF, 2735 0x00, 2736 ( TRANSFER_LENGTH >> 8 ) & 0xFF, 2737 TRANSFER_LENGTH & 0xFF, 2738 0x00 ); 2739 2740 SetDataTransferDirection ( request, 2741 kSCSIDataTransfer_FromTargetToInitiator ); 2742 SetDataBuffer ( request, 2743 dataBuffer ); 2744 SetRequestedDataTransferCount ( request, 2745 requestedByteCount ); 2746 2747 return true; 2748 2749} 2750 2751 2752//-------------------------------------------------------------------------------------------------- 2753// READ_12 - Command Builder [PROTECTED] 2754//-------------------------------------------------------------------------------------------------- 2755 2756bool 2757IOUSBMassStorageUFIDevice::READ_12 ( 2758 SCSITaskIdentifier request, 2759 IOMemoryDescriptor * dataBuffer, 2760 UInt32 blockSize, 2761 SCSICmdField1Bit DPO, 2762 SCSICmdField1Bit FUA, 2763 SCSICmdField1Bit RELADR, 2764 SCSICmdField4Byte LOGICAL_BLOCK_ADDRESS, 2765 SCSICmdField4Byte TRANSFER_LENGTH ) 2766{ 2767 2768 UInt32 requestedByteCount; 2769 2770 2771 STATUS_LOG ( ( 6, "%s[%p]::READ_12 called", getName(), this ) ); 2772 2773 if ( ResetForNewTask( request ) == false ) 2774 { 2775 STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) ); 2776 return false; 2777 } 2778 2779 // Check the validity of the media 2780 if ( blockSize == 0 ) 2781 { 2782 // There is no media in the device, or it has an undetermined 2783 // blocksize (could be unformatted). 2784 return false; 2785 } 2786 2787 // Make sure that we were given a valid buffer 2788 if (dataBuffer == NULL ) 2789 { 2790 return false; 2791 } 2792 else 2793 { 2794 // We have a valid buffer object, check that it has the required 2795 // capcity for the data to be transfered. 2796 requestedByteCount = TRANSFER_LENGTH * blockSize; 2797 2798 // We know the number of bytes to transfer, now check that the 2799 // buffer is large enough to accomodate this request. 2800 if ( dataBuffer->getLength() < requestedByteCount ) 2801 { 2802 return false; 2803 } 2804 2805 } 2806 2807 // Do the pre-flight check on the passed in parameters 2808 if( IsParameterValid( DPO, kSCSICmdFieldMask1Bit ) == false ) 2809 { 2810 STATUS_LOG ( ( 4, "%s[%p]:: DPO = %x not valid", getName(), this, DPO ) ); 2811 return false; 2812 } 2813 2814 if( IsParameterValid( FUA, kSCSICmdFieldMask1Bit ) == false ) 2815 { 2816 STATUS_LOG ( ( 4, "%s[%p]:: FUA = %x not valid", getName(), this, FUA ) ); 2817 return false; 2818 } 2819 2820 if( IsParameterValid( RELADR, kSCSICmdFieldMask1Bit ) == false ) 2821 { 2822 STATUS_LOG ( ( 4, "%s[%p]:: RELADR = %x not valid", getName(), this, RELADR ) ); 2823 return false; 2824 } 2825 2826 if( IsParameterValid( LOGICAL_BLOCK_ADDRESS, kSCSICmdFieldMask4Byte ) == false ) 2827 { 2828 STATUS_LOG ( ( 4, "%s[%p]:: LOGICAL_BLOCK_ADDRESS = %x not valid", 2829 getName(), this, LOGICAL_BLOCK_ADDRESS ) ); 2830 return false; 2831 } 2832 2833 if( IsParameterValid( TRANSFER_LENGTH, kSCSICmdFieldMask4Byte ) == false ) 2834 { 2835 STATUS_LOG ( ( 4, "%s[%p]:: TRANSFER_LENGTH = %x not valid", 2836 getName(), this, TRANSFER_LENGTH ) ); 2837 return false; 2838 } 2839 2840 // This is a 12-Byte command, fill out the cdb appropriately 2841 SetCommandDescriptorBlock ( request, 2842 kSCSICmd_READ_12, 2843 ( DPO << 4 ) | ( FUA << 3 ) | RELADR, 2844 ( LOGICAL_BLOCK_ADDRESS >> 24 ) & 0xFF, 2845 ( LOGICAL_BLOCK_ADDRESS >> 16 ) & 0xFF, 2846 ( LOGICAL_BLOCK_ADDRESS >> 8 ) & 0xFF, 2847 LOGICAL_BLOCK_ADDRESS & 0xFF, 2848 ( TRANSFER_LENGTH >> 24 ) & 0xFF, 2849 ( TRANSFER_LENGTH >> 16 ) & 0xFF, 2850 ( TRANSFER_LENGTH >> 8 ) & 0xFF, 2851 TRANSFER_LENGTH & 0xFF, 2852 0x00, 2853 0x00 ); 2854 2855 SetDataTransferDirection( request, 2856 kSCSIDataTransfer_FromTargetToInitiator ); 2857 SetDataBuffer ( request, 2858 dataBuffer ); 2859 SetRequestedDataTransferCount ( request, 2860 requestedByteCount ); 2861 2862 return true; 2863 2864} 2865 2866 2867//-------------------------------------------------------------------------------------------------- 2868// READ_CAPACITY - Command Builder [PROTECTED] 2869//-------------------------------------------------------------------------------------------------- 2870 2871bool 2872IOUSBMassStorageUFIDevice::READ_CAPACITY ( 2873 SCSITaskIdentifier request, 2874 IOMemoryDescriptor * dataBuffer, 2875 SCSICmdField1Bit RELADR, 2876 SCSICmdField4Byte LOGICAL_BLOCK_ADDRESS, 2877 SCSICmdField1Bit PMI ) 2878{ 2879 STATUS_LOG ( ( 6, "%s[%p]::READ_CAPACITY called", getName(), this ) ); 2880 2881 if ( ResetForNewTask( request ) == false ) 2882 { 2883 STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) ); 2884 return false; 2885 } 2886 2887 // Make sure that we were given a buffer 2888 if ( dataBuffer == NULL ) 2889 { 2890 return false; 2891 } 2892 2893 // Do the pre-flight check on the passed in parameters 2894 if( IsParameterValid( RELADR, kSCSICmdFieldMask1Bit ) == false ) 2895 { 2896 STATUS_LOG ( ( 4, "%s[%p]:: RELADR = %x not valid", getName(), this, RELADR ) ); 2897 return false; 2898 } 2899 2900 if( IsParameterValid( LOGICAL_BLOCK_ADDRESS, kSCSICmdFieldMask4Byte ) == false ) 2901 { 2902 STATUS_LOG ( ( 4, "%s[%p]:: LOGICAL_BLOCK_ADDRESS = %x not valid", 2903 getName(), this, LOGICAL_BLOCK_ADDRESS ) ); 2904 return false; 2905 } 2906 2907 if( IsParameterValid( PMI, kSCSICmdFieldMask1Bit ) == false ) 2908 { 2909 STATUS_LOG ( ( 4, "%s[%p]:: PMI = %x not valid", getName(), this, PMI ) ); 2910 return false; 2911 } 2912 2913 // This is a 10-Byte command, fill out the cdb appropriately 2914 SetCommandDescriptorBlock( request, 2915 kSCSICmd_READ_CAPACITY, 2916 RELADR, 2917 ( LOGICAL_BLOCK_ADDRESS >> 24 ) & 0xFF, 2918 ( LOGICAL_BLOCK_ADDRESS >> 16 ) & 0xFF, 2919 ( LOGICAL_BLOCK_ADDRESS >> 8 ) & 0xFF, 2920 LOGICAL_BLOCK_ADDRESS & 0xFF, 2921 0x00, 2922 0x00, 2923 PMI, 2924 0x00 ); 2925 2926 SetDataTransferDirection( request, 2927 kSCSIDataTransfer_FromTargetToInitiator ); 2928 SetDataBuffer( request, 2929 dataBuffer ); 2930 SetRequestedDataTransferCount( request, 8 ); 2931 2932 return true; 2933} 2934 2935 2936//-------------------------------------------------------------------------------------------------- 2937// READ_FORMAT_CAPACITIES - Command Builder [PROTECTED] 2938//-------------------------------------------------------------------------------------------------- 2939 2940bool 2941IOUSBMassStorageUFIDevice::READ_FORMAT_CAPACITIES( 2942 SCSITaskIdentifier request, 2943 IOMemoryDescriptor * dataBuffer, 2944 SCSICmdField2Byte ALLOCATION_LENGTH ) 2945{ 2946 2947 STATUS_LOG ( ( 6, "%s[%p]::READ_CAPACITY called", getName(), this ) ); 2948 2949 if ( ResetForNewTask( request ) == false ) 2950 { 2951 STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) ); 2952 return false; 2953 } 2954 2955 // Make sure that we were given a buffer 2956 if ( dataBuffer == NULL ) 2957 { 2958 return false; 2959 } 2960 2961 // Do the pre-flight check on the passed in parameters 2962 if( IsParameterValid( ALLOCATION_LENGTH, kSCSICmdFieldMask2Byte ) == false ) 2963 { 2964 STATUS_LOG ( (4, "%s[%p]:: ALLOCATION_LENGTH = %x not valid", getName(), this, ALLOCATION_LENGTH ) ); 2965 return false; 2966 } 2967 2968 // This is a 10-Byte command, fill out the cdb appropriately 2969 SetCommandDescriptorBlock ( request, 2970 kSCSICmd_READ_FORMAT_CAPACITIES, 2971 0x00, 2972 0x00, 2973 0x00, 2974 0x00, 2975 0x00, 2976 0x00, 2977 ( ALLOCATION_LENGTH >> 8 ) & 0xFF, 2978 ALLOCATION_LENGTH & 0xFF, 2979 0x00 ); 2980 2981 SetDataTransferDirection ( request, 2982 kSCSIDataTransfer_FromTargetToInitiator ); 2983 SetDataBuffer ( request, 2984 dataBuffer ); 2985 SetRequestedDataTransferCount( request, 2986 ALLOCATION_LENGTH ); 2987 2988 return true; 2989 2990} 2991 2992 2993//-------------------------------------------------------------------------------------------------- 2994// REQUEST_SENSE - Command Builder [PROTECTED] 2995//-------------------------------------------------------------------------------------------------- 2996 2997bool 2998IOUSBMassStorageUFIDevice::REQUEST_SENSE ( 2999 SCSITaskIdentifier request, 3000 IOMemoryDescriptor *dataBuffer, 3001 SCSICmdField1Byte ALLOCATION_LENGTH ) 3002{ 3003 3004 STATUS_LOG ( ( 6, "%s[%p]::REQUEST_SENSE called", getName(), this ) ); 3005 3006 if ( ResetForNewTask( request ) == false ) 3007 { 3008 STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) ); 3009 return false; 3010 } 3011 3012 if( IsParameterValid( ALLOCATION_LENGTH, kSCSICmdFieldMask1Byte ) == false ) 3013 { 3014 STATUS_LOG ( ( 4, "%s[%p]ALLOCATION_LENGTH = %x not valid", 3015 getName(), this, ALLOCATION_LENGTH ) ); 3016 return false; 3017 } 3018 3019 // This is a 6-Byte command, fill out the cdb appropriately 3020 SetCommandDescriptorBlock ( request, 3021 kSCSICmd_REQUEST_SENSE, 3022 0x00, 3023 0x00, 3024 0x00, 3025 ALLOCATION_LENGTH, 3026 0x00 ); 3027 3028 SetDataTransferDirection ( request, 3029 kSCSIDataTransfer_FromTargetToInitiator ); 3030 SetDataBuffer ( request, 3031 dataBuffer ); 3032 SetRequestedDataTransferCount ( request, 3033 ALLOCATION_LENGTH ); 3034 3035 return true; 3036 3037} 3038 3039 3040//-------------------------------------------------------------------------------------------------- 3041// REZERO_UNIT - Command Builder [PROTECTED] 3042//-------------------------------------------------------------------------------------------------- 3043 3044bool 3045IOUSBMassStorageUFIDevice::REZERO_UNIT ( SCSITaskIdentifier request ) 3046{ 3047 3048 UNUSED ( request ); 3049 3050 return false; 3051 3052} 3053 3054 3055//-------------------------------------------------------------------------------------------------- 3056// SEEK - Command Builder [PROTECTED] 3057//-------------------------------------------------------------------------------------------------- 3058 3059bool 3060IOUSBMassStorageUFIDevice::SEEK ( 3061 SCSITaskIdentifier request, 3062 SCSICmdField4Byte LOGICAL_BLOCK_ADDRESS ) 3063{ 3064 3065 UNUSED ( request ); 3066 UNUSED ( LOGICAL_BLOCK_ADDRESS ); 3067 3068 return false; 3069 3070} 3071 3072 3073//-------------------------------------------------------------------------------------------------- 3074// SEND_DIAGNOSTICS - Command Builder [PROTECTED] 3075//-------------------------------------------------------------------------------------------------- 3076 3077bool 3078IOUSBMassStorageUFIDevice::SEND_DIAGNOSTICS ( 3079 SCSITaskIdentifier request, 3080 SCSICmdField1Bit PF, 3081 SCSICmdField1Bit SELF_TEST, 3082 SCSICmdField1Bit DEF_OFL, 3083 SCSICmdField1Bit UNIT_OFL ) 3084{ 3085 3086 STATUS_LOG ( ( 6, "%s[%p]::SEND_DIAGNOSTICS called", getName(), this ) ); 3087 3088 if ( ResetForNewTask( request ) == false ) 3089 { 3090 STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) ); 3091 return false; 3092 } 3093 3094 if( IsParameterValid( PF, kSCSICmdFieldMask1Bit ) == false ) 3095 { 3096 STATUS_LOG ( ( 4, "%s[%p]:: PF = %x not valid", getName(), this, PF ) ); 3097 return false; 3098 } 3099 3100 if( IsParameterValid ( SELF_TEST, kSCSICmdFieldMask1Bit ) == false ) 3101 { 3102 STATUS_LOG ( ( 4, "%s[%p]:: SELF_TEST = %x not valid", getName(), this, SELF_TEST ) ); 3103 return false; 3104 } 3105 3106 if( IsParameterValid( DEF_OFL, kSCSICmdFieldMask1Bit ) == false ) 3107 { 3108 STATUS_LOG ( ( 4, "%s[%p]:: DEF_OFL = %x not valid", getName(), this, DEF_OFL ) ); 3109 return false; 3110 } 3111 3112 if( IsParameterValid( UNIT_OFL, kSCSICmdFieldMask1Bit ) == false ) 3113 { 3114 STATUS_LOG ( ( 4, "%s[%p]:: UNIT_OFL = %x not valid", getName(), this, UNIT_OFL ) ); 3115 return false; 3116 } 3117 3118 // This is a 6-Byte command, fill out the cdb appropriately 3119 SetCommandDescriptorBlock ( request, 3120 kSCSICmd_SEND_DIAGNOSTICS, 3121 ( PF << 4 ) | 3122 ( SELF_TEST << 2 ) | ( DEF_OFL << 1 ) | UNIT_OFL, 3123 0x00, 3124 0x00, 3125 0x00, 3126 0x00 ); 3127 3128 SetDataTransferDirection ( request, 3129 kSCSIDataTransfer_NoDataTransfer); 3130 3131 return true; 3132 3133} 3134 3135 3136//-------------------------------------------------------------------------------------------------- 3137// START_STOP_UNIT - Command Builder [PROTECTED] 3138//-------------------------------------------------------------------------------------------------- 3139 3140bool 3141IOUSBMassStorageUFIDevice::START_STOP_UNIT ( 3142 SCSITaskIdentifier request, 3143 SCSICmdField1Bit IMMED, 3144 SCSICmdField1Bit LOEJ, 3145 SCSICmdField1Bit START ) 3146{ 3147 3148 STATUS_LOG ( ( 6, "%s[%p]::START_STOP_UNIT called", getName(), this ) ); 3149 3150 if ( ResetForNewTask( request ) == false ) 3151 { 3152 STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) ); 3153 return false; 3154 } 3155 3156 // Do the pre-flight check on the passed in parameters 3157 if( IsParameterValid( IMMED, kSCSICmdFieldMask1Bit ) == false ) 3158 { 3159 STATUS_LOG ( ( 4, "%s[%p]:: IMMED = %x not valid", getName(), this, IMMED ) ); 3160 return false; 3161 } 3162 3163 if( IsParameterValid( LOEJ, kSCSICmdFieldMask1Bit ) == false ) 3164 { 3165 STATUS_LOG ( ( 4, "%s[%p]:: LOEJ = %x not valid", getName(), this, LOEJ ) ); 3166 return false; 3167 } 3168 3169 if( IsParameterValid( START, kSCSICmdFieldMask1Bit ) == false ) 3170 { 3171 STATUS_LOG ( ( 4, "%s[%p]:: START = %x not valid", getName(), this, START ) ); 3172 return false; 3173 } 3174 3175 // This is a 6-Byte command, fill out the cdb appropriately 3176 SetCommandDescriptorBlock ( request, 3177 kSCSICmd_START_STOP_UNIT, 3178 IMMED, 3179 0x00, 3180 0x00, 3181 ( LOEJ << 1 ) | START, 3182 0x00 ); 3183 3184 SetDataTransferDirection ( request, 3185 kSCSIDataTransfer_NoDataTransfer ); 3186 3187 return true; 3188 3189} 3190 3191 3192//-------------------------------------------------------------------------------------------------- 3193// TEST_UNIT_READY - Command Builder [PROTECTED] 3194//-------------------------------------------------------------------------------------------------- 3195 3196bool 3197IOUSBMassStorageUFIDevice::TEST_UNIT_READY ( 3198 SCSITaskIdentifier request ) 3199{ 3200 3201 STATUS_LOG ( ( 6, "%s[%p]::TEST_UNIT_READY called", getName(), this ) ); 3202 3203 if ( ResetForNewTask( request ) == false ) 3204 { 3205 STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) ); 3206 return false; 3207 } 3208 3209 // This is a 6-Byte command, fill out the cdb appropriately 3210 SetCommandDescriptorBlock ( request, 3211 kSCSICmd_TEST_UNIT_READY, 3212 0x00, 3213 0x00, 3214 0x00, 3215 0x00, 3216 0x00 ); 3217 3218 SetDataTransferDirection ( request, 3219 kSCSIDataTransfer_NoDataTransfer ); 3220 3221 return true; 3222 3223} 3224 3225 3226//-------------------------------------------------------------------------------------------------- 3227// VERIFY - Command Builder [PROTECTED] 3228//-------------------------------------------------------------------------------------------------- 3229 3230bool 3231IOUSBMassStorageUFIDevice::VERIFY( 3232 SCSITaskIdentifier request, 3233 SCSICmdField1Bit DPO, 3234 SCSICmdField1Bit BYTCHK, 3235 SCSICmdField1Bit RELADR, 3236 SCSICmdField4Byte LOGICAL_BLOCK_ADDRESS, 3237 SCSICmdField2Byte VERIFICATION_LENGTH ) 3238{ 3239 UNUSED( request ); 3240 UNUSED( DPO ); 3241 UNUSED( BYTCHK ); 3242 UNUSED( RELADR ); 3243 UNUSED( LOGICAL_BLOCK_ADDRESS ); 3244 UNUSED( VERIFICATION_LENGTH ); 3245 3246 return false; 3247} 3248 3249 3250//-------------------------------------------------------------------------------------------------- 3251// WRITE_10 - Command Builder [PROTECTED] 3252//-------------------------------------------------------------------------------------------------- 3253 3254bool 3255IOUSBMassStorageUFIDevice::WRITE_10 ( 3256 SCSITaskIdentifier request, 3257 IOMemoryDescriptor * dataBuffer, 3258 UInt32 blockSize, 3259 SCSICmdField1Bit DPO, 3260 SCSICmdField1Bit FUA, 3261 SCSICmdField1Bit RELADR, 3262 SCSICmdField4Byte LOGICAL_BLOCK_ADDRESS, 3263 SCSICmdField2Byte TRANSFER_LENGTH ) 3264{ 3265 3266 UInt32 requestedByteCount; 3267 3268 3269 STATUS_LOG ( ( 6, "%s[%p]::WRITE_10 called", getName(), this ) ); 3270 3271 if ( ResetForNewTask( request ) == false ) 3272 { 3273 3274 STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) ); 3275 return false; 3276 3277 } 3278 3279 // Check the validity of the media 3280 if ( blockSize == 0 ) 3281 { 3282 // There is no media in the device, or it has an undetermined 3283 // blocksize (could be unformatted). 3284 return false; 3285 3286 } 3287 3288 // Make sure that we were given a valid buffer 3289 if (dataBuffer == NULL ) 3290 { 3291 3292 return false; 3293 3294 } 3295 else 3296 { 3297 // We have a valid buffer object, check that it has the required 3298 // capcity for the data to be transfered. 3299 requestedByteCount = TRANSFER_LENGTH * blockSize; 3300 3301 // We know the number of bytes to transfer, now check that the 3302 // buffer is large enough to accomodate this request. 3303 if ( dataBuffer->getLength() < requestedByteCount ) 3304 { 3305 return false; 3306 } 3307 3308 } 3309 3310 // Do the pre-flight check on the passed in parameters 3311 if( IsParameterValid ( DPO, kSCSICmdFieldMask1Bit ) == false ) 3312 { 3313 3314 STATUS_LOG ( ( 4, "%s[%p]:: DPO = %x not valid", getName(), this, DPO ) ); 3315 return false; 3316 3317 } 3318 3319 if( IsParameterValid ( FUA, kSCSICmdFieldMask1Bit ) == false ) 3320 { 3321 3322 STATUS_LOG ( ( 4, "%s[%p]:: FUA = %x not valid", getName(), this, FUA ) ); 3323 return false; 3324 3325 } 3326 3327 if( IsParameterValid ( RELADR, kSCSICmdFieldMask1Bit ) == false ) 3328 { 3329 3330 STATUS_LOG ( ( 4, "%s[%p]:: RELADR = %x not valid", getName(), this, RELADR ) ); 3331 return false; 3332 3333 } 3334 3335 if( IsParameterValid ( LOGICAL_BLOCK_ADDRESS, kSCSICmdFieldMask4Byte ) == false ) 3336 { 3337 3338 STATUS_LOG ( ( 4, "%s[%p]:: LOGICAL_BLOCK_ADDRESS = %x not valid", 3339 getName(), this, LOGICAL_BLOCK_ADDRESS ) ); 3340 return false; 3341 3342 } 3343 3344 if( IsParameterValid ( TRANSFER_LENGTH, kSCSICmdFieldMask2Byte ) == false ) 3345 { 3346 3347 STATUS_LOG ( ( 4, "%s[%p]:: TRANSFER_LENGTH = %x not valid", 3348 getName(), this, TRANSFER_LENGTH ) ); 3349 return false; 3350 3351 } 3352 3353 // This is a 10-Byte command, fill out the cdb appropriately 3354 SetCommandDescriptorBlock ( request, 3355 kSCSICmd_WRITE_10, 3356 ( DPO << 4 ) | ( FUA << 3 ) | RELADR, 3357 ( LOGICAL_BLOCK_ADDRESS >> 24 ) & 0xFF, 3358 ( LOGICAL_BLOCK_ADDRESS >> 16 ) & 0xFF, 3359 ( LOGICAL_BLOCK_ADDRESS >> 8 ) & 0xFF, 3360 LOGICAL_BLOCK_ADDRESS & 0xFF, 3361 0x00, 3362 ( TRANSFER_LENGTH >> 8 ) & 0xFF, 3363 TRANSFER_LENGTH & 0xFF, 3364 0x00 ); 3365 3366 SetDataTransferDirection ( request, 3367 kSCSIDataTransfer_FromInitiatorToTarget ); 3368 SetDataBuffer ( request, 3369 dataBuffer ); 3370 SetRequestedDataTransferCount ( request, 3371 requestedByteCount ); 3372 3373 return true; 3374 3375} 3376 3377 3378//-------------------------------------------------------------------------------------------------- 3379// WRITE_12 - Command Builder [PROTECTED] 3380//-------------------------------------------------------------------------------------------------- 3381 3382bool 3383IOUSBMassStorageUFIDevice::WRITE_12 ( 3384 SCSITaskIdentifier request, 3385 IOMemoryDescriptor * dataBuffer, 3386 UInt32 blockSize, 3387 SCSICmdField1Bit DPO, 3388 SCSICmdField1Bit EBP, 3389 SCSICmdField1Bit RELADR, 3390 SCSICmdField4Byte LOGICAL_BLOCK_ADDRESS, 3391 SCSICmdField4Byte TRANSFER_LENGTH ) 3392{ 3393 3394 UNUSED ( request ); 3395 UNUSED ( dataBuffer ); 3396 UNUSED ( blockSize ); 3397 UNUSED ( DPO ); 3398 UNUSED ( EBP ); 3399 UNUSED ( RELADR ); 3400 UNUSED ( LOGICAL_BLOCK_ADDRESS ); 3401 UNUSED ( TRANSFER_LENGTH ); 3402 3403 return false; 3404 3405} 3406 3407 3408//-------------------------------------------------------------------------------------------------- 3409// WRITE_AND_VERIFY - Command Builder [PROTECTED] 3410//-------------------------------------------------------------------------------------------------- 3411 3412bool 3413IOUSBMassStorageUFIDevice::WRITE_AND_VERIFY ( 3414 SCSITaskIdentifier request, 3415 IOMemoryDescriptor * dataBuffer, 3416 UInt32 blockSize, 3417 SCSICmdField1Bit DPO, 3418 SCSICmdField1Bit BYTCHK, 3419 SCSICmdField1Bit RELADR, 3420 SCSICmdField4Byte LOGICAL_BLOCK_ADDRESS, 3421 SCSICmdField2Byte TRANSFER_LENGTH ) 3422{ 3423 3424 UNUSED ( request ); 3425 UNUSED ( dataBuffer ); 3426 UNUSED ( blockSize ); 3427 UNUSED ( DPO ); 3428 UNUSED ( BYTCHK ); 3429 UNUSED ( RELADR ); 3430 UNUSED ( LOGICAL_BLOCK_ADDRESS ); 3431 UNUSED ( TRANSFER_LENGTH ); 3432 3433 return false; 3434 3435} 3436 3437 3438#pragma mark - 3439#pragma mark *** IOUSBMassStorageUFISubclass methods *** 3440#pragma mark - 3441 3442 3443//-------------------------------------------------------------------------------------------------- 3444// BeginProvidedServices [PROTECTED] 3445//-------------------------------------------------------------------------------------------------- 3446 3447bool 3448IOUSBMassStorageUFISubclass::BeginProvidedServices ( void ) 3449{ 3450 // Create the IOUSBMassStorageUFIDevice object 3451 IOUSBMassStorageUFIDevice * ufiDevice = OSTypeAlloc ( IOUSBMassStorageUFIDevice ); 3452 if( ufiDevice == NULL ) 3453 { 3454 STATUS_LOG ( ( 1, "%s[%p]::BeginProvidedServices failed", getName(), this ) ); 3455 PANIC_NOW ( ( "IOUSBMassStorageUFISubclass::BeginProvidedServices failed" ) ); 3456 return false; 3457 } 3458 3459 ufiDevice->init ( NULL ); 3460 3461 if ( !ufiDevice->attach( this ) ) 3462 { 3463 // panic since the nub can't attach 3464 PANIC_NOW ( ( "IOUSBMassStorageUFISubclass::BeginProvidedServices unable to attach nub" ) ); 3465 return false; 3466 } 3467 3468 if ( ufiDevice->start( this ) == false ) 3469 { 3470 ufiDevice->detach( this ); 3471 } 3472 3473 STATUS_LOG ( ( 4, "%s[%p]::BeginProvidedServices exiting.", getName(), this ) ); 3474 3475 ufiDevice->release(); 3476 3477 return true; 3478 3479} 3480 3481 3482//-------------------------------------------------------------------------------------------------- 3483// EndProvidedServices [PROTECTED] 3484//-------------------------------------------------------------------------------------------------- 3485 3486bool 3487IOUSBMassStorageUFISubclass::EndProvidedServices ( void ) 3488{ 3489 return true; 3490} 3491