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// General OS Services header files 30#include <libkern/OSByteOrder.h> 31 32// Local includes 33#include "IOUSBMassStorageClass.h" 34#include "IOUSBMassStorageClassTimestamps.h" 35#include "Debugging.h" 36 37// IOKit includes 38#include <IOKit/scsi/IOSCSIPeripheralDeviceNub.h> 39#include <IOKit/IODeviceTreeSupport.h> 40#include <IOKit/IOKitKeys.h> 41 42//-------------------------------------------------------------------------------------------------- 43// Defines 44//-------------------------------------------------------------------------------------------------- 45 46// Default timeout values 47enum 48{ 49 kDefaultReadTimeoutDuration = 30000, 50 kDefaultWriteTimeoutDuration = 30000 51}; 52 53// Default maximum transfer count, in bytes 54enum 55{ 56 kDefaultMaximumByteCountRead = 131072, 57 kDefaultMaximumByteCountWrite = 131072, 58 kDefaultMaximumByteCountReadUSB3 = 1048576, 59 kDefaultMaximumByteCountWriteUSB3 = 1048576 60}; 61 62// Maximum number of consecutive I/Os which can be aborted with a Device Reset, 63// before the device will be considered removed. 64enum 65{ 66 kMaxConsecutiveResets = 5 67}; 68 69 70//-------------------------------------------------------------------------------------------------- 71// Macros 72//-------------------------------------------------------------------------------------------------- 73 74#define fWorkLoop fIOSCSIProtocolInterfaceReserved->fWorkLoop 75 76 77//-------------------------------------------------------------------------------------------------- 78// Declarations - USBMassStorageClassGlobals 79//-------------------------------------------------------------------------------------------------- 80 81class USBMassStorageClassGlobals 82{ 83 84 public: 85 86 // Constructor 87 USBMassStorageClassGlobals ( void ); 88 89 // Desctructor 90 virtual ~USBMassStorageClassGlobals ( void ); 91 92}; 93 94 95//-------------------------------------------------------------------------------------------------- 96// Globals - USBMassStorageClassGlobals 97//-------------------------------------------------------------------------------------------------- 98 99 100UInt32 gUSBDebugFlags = 0; // Externally defined in IOUSBMassStorageClass.h 101static USBMassStorageClassGlobals gUSBGlobals; 102 103static int USBMassStorageClassSysctl ( struct sysctl_oid * oidp, void * arg1, int arg2, struct sysctl_req * req ); 104SYSCTL_PROC ( _debug, OID_AUTO, USBMassStorageClass, CTLFLAG_RW, 0, 0, USBMassStorageClassSysctl, "USBMassStorageClass", "USBMassStorageClass debug interface" ); 105 106 107//-------------------------------------------------------------------------------------------------- 108// USBMassStorageClassSysctl - Sysctl handler. [STATIC] 109//-------------------------------------------------------------------------------------------------- 110 111static int 112USBMassStorageClassSysctl ( struct sysctl_oid * oidp, void * arg1, int arg2, struct sysctl_req * req ) 113{ 114 115 int error = 0; 116 USBSysctlArgs usbArgs; 117 118 UNUSED ( oidp ); 119 UNUSED ( arg1 ); 120 UNUSED ( arg2 ); 121 122 STATUS_LOG ( ( 1, "+USBMassStorageClassGlobals: gUSBDebugFlags = 0x%08X\n", ( unsigned int ) gUSBDebugFlags ) ); 123 124 error = SYSCTL_IN ( req, &usbArgs, sizeof ( usbArgs ) ); 125 if ( ( error == 0 ) && ( usbArgs.type == kUSBTypeDebug ) ) 126 { 127 128 if ( usbArgs.operation == kUSBOperationGetFlags ) 129 { 130 131 usbArgs.debugFlags = gUSBDebugFlags; 132 error = SYSCTL_OUT ( req, &usbArgs, sizeof ( usbArgs ) ); 133 134 } 135 136 else if ( usbArgs.operation == kUSBOperationSetFlags ) 137 { 138 gUSBDebugFlags = usbArgs.debugFlags; 139 } 140 141 } 142 143 STATUS_LOG ( ( 1, "-USBMassStorageClassGlobals: gUSBDebugFlags = 0x%08X\n", ( unsigned int ) gUSBDebugFlags ) ); 144 145 return error; 146 147} 148 149 150//-------------------------------------------------------------------------------------------------- 151// USBMassStorageClassGlobals - Default Constructor [PUBLIC] 152//-------------------------------------------------------------------------------------------------- 153 154USBMassStorageClassGlobals::USBMassStorageClassGlobals ( void ) 155{ 156 157 int debugFlags; 158 159 STATUS_LOG ( ( 1, "+USBMassStorageClassGlobals::USBMassStorageClassGlobals\n" ) ); 160 161 if ( PE_parse_boot_argn ( "USB-MassStorage", &debugFlags, sizeof ( debugFlags ) ) ) 162 { 163 gUSBDebugFlags = debugFlags; 164 } 165 166 // Register our sysctl interface 167 sysctl_register_oid ( &sysctl__debug_USBMassStorageClass ); 168 169 STATUS_LOG ( ( 1, "-USBMassStorageClassGlobals::USBMassStorageClassGlobals\n" ) ); 170 171} 172 173 174//-------------------------------------------------------------------------------------------------- 175// USBMassStorageClassGlobals - Destructor [PUBLIC] 176//-------------------------------------------------------------------------------------------------- 177 178USBMassStorageClassGlobals::~USBMassStorageClassGlobals ( void ) 179{ 180 181 STATUS_LOG ( ( 1, "+~USBMassStorageClassGlobals::USBMassStorageClassGlobals\n" ) ); 182 183 // Unregister our sysctl interface 184 sysctl_unregister_oid ( &sysctl__debug_USBMassStorageClass ); 185 186 STATUS_LOG ( ( 1, "-~USBMassStorageClassGlobals::USBMassStorageClassGlobals\n" ) ); 187 188} 189 190 191//-------------------------------------------------------------------------------------------------- 192// Declarations - IOUSBMassStorageClass 193//-------------------------------------------------------------------------------------------------- 194 195#define super IOSCSIProtocolServices 196 197OSDefineMetaClassAndStructors( IOUSBMassStorageClass, IOSCSIProtocolServices ) 198 199 200//-------------------------------------------------------------------------------------------------- 201// init - Called at initialization time [PUBLIC] 202//-------------------------------------------------------------------------------------------------- 203 204bool 205IOUSBMassStorageClass::init ( OSDictionary * propTable ) 206{ 207 if ( super::init( propTable ) == false) 208 { 209 return false; 210 } 211 212 return true; 213 214} 215 216//-------------------------------------------------------------------------------------------------- 217// start - Called at services start time (after successful matching) [PUBLIC] 218//-------------------------------------------------------------------------------------------------- 219 220bool 221IOUSBMassStorageClass::start ( IOService * provider ) 222{ 223 IOUSBFindEndpointRequest request; 224 OSDictionary * characterDict = NULL; 225 OSObject * obj = NULL; 226 IOReturn result = kIOReturnError; 227 bool retVal = false; 228 OSNumber * number = NULL; 229 bool success = false; 230 231 232 if ( super::start( provider ) == false ) 233 { 234 STATUS_LOG(( 1, "%s[%p]: superclass start failure.", getName(), this)); 235 return false; 236 } 237 238 RecordUSBTimeStamp ( UMC_TRACE ( kIOUSBMassStorageClassStart ), 239 ( uintptr_t ) this, NULL, 240 NULL, NULL ); 241 242#ifndef EMBEDDED 243 // Allocate data for our expansion data. 244 reserved = ( ExpansionData * ) IOMalloc ( sizeof ( ExpansionData ) ); 245 bzero ( reserved, sizeof ( ExpansionData ) ); 246#endif // EMBEDDED 247 248 // Save the reference to the interface on the device that will be 249 // the provider for this object. 250 SetInterfaceReference ( OSDynamicCast ( IOUSBInterface, provider ) ); 251 if ( GetInterfaceReference ( ) == NULL ) 252 { 253 254 STATUS_LOG ( ( 1, "%s[%p]: the provider is not an IOUSBInterface object", 255 getName(), this ) ); 256 // If our provider is not a IOUSBInterface object, return false 257 // to indicate that the object could not be correctly 258 // instantiated. 259 // The USB Mass Storage Class specification requires that all 260 // devices be a composite device with a Mass Storage interface 261 // so this object will always be an interface driver. 262 goto Exit; 263 264 } 265 266 // Check if a subclass has marked this device as not to be operated at all. 267 if ( provider->getProperty ( kIOUSBMassStorageDoNotMatch ) != NULL ) 268 { 269 goto abortStart; 270 } 271 272 RecordUSBTimeStamp ( UMC_TRACE ( kAtUSBAddress ), 273 ( uintptr_t ) this, ( unsigned int ) GetInterfaceReference()->GetDevice()->GetAddress(), 274 NULL, NULL ); 275 276 STATUS_LOG ( ( 6, "%s[%p]: USB Mass Storage @ %d", 277 getName(), this, 278 GetInterfaceReference()->GetDevice()->GetAddress() ) ); 279 280 if ( GetInterfaceReference()->open( this ) == false) 281 { 282 283 STATUS_LOG ( ( 1, "%s[%p]: could not open the interface", getName(), this ) ); 284 goto Exit; 285 286 } 287 288 // Set the IOUSBPipe object pointers to NULL so that the driver can 289 // release these objects if instantition is not successful. 290 fBulkInPipe = NULL; 291 fBulkOutPipe = NULL; 292 fInterruptPipe = NULL; 293 294 // Default is to have no clients 295 fClients = NULL; 296 297 // Default is to have a max lun of 0. 298 SetMaxLogicalUnitNumber ( 0 ); 299 300 // Initialize all Bulk Only related member variables to their default 301 // states. 302 fBulkOnlyCommandTag = 0; 303 fBulkOnlyCommandStructInUse = false; 304 305 // Initialize all CBI related member variables to their default 306 // states. 307 fCBICommandStructInUse = false; 308 309 // Flag we use to indicate whether or not the device requires the standard 310 // USB device reset instead of the BO reset. This applies to BO devices only. 311 fUseUSBResetNotBOReset = false; 312 313 // Certain Bulk-Only device are subject to erroneous CSW tags. 314 fKnownCSWTagMismatchIssues = false; 315 316 // Flag to let us know if we've seen the reconfiguration message following a device reset. 317 // If we proceed with operations prior to receiving the message we may end up booting a 318 // CBW out on the bus prior to the SET_CONFIGURATION which follows the reset. This will 319 // hamper recovery and confuse the state machine of the USB device we're operating. 320 fWaitingForReconfigurationMessage = false; 321 322 // Used to determine if we're going to block on the reset thread or not. 323 fBlockOnResetThread = false; 324 325 // Used to determine where we should close our provider at time of termination. 326 fTerminating = false; 327 328 // IOSAM may request that we suspend/resume our port instead of spin up/down media. 329 fPortSuspendResumeForPMEnabled = false; 330 331#ifndef EMBEDDED 332 // Workaround flag for devices which spin themselves up/down and have problems with driver intervention. 333 fAutonomousSpinDownWorkAround = false; 334 335 // Some devices with complicated interal logic require some "cool down" time following a 336 // USB device reset before they can resume servicing requests. 337 fPostDeviceResetCoolDownInterval = 0; 338#endif // EMBEDDED 339 340 // Check if the personality for this device specifies a preferred protocol 341 characterDict = OSDynamicCast ( OSDictionary, getProperty( kIOUSBMassStorageCharacteristics ) ); 342 if ( characterDict == NULL ) 343 { 344 // This device does not specify a preferred protocol, use the protocol 345 // defined in the descriptor. 346 fPreferredProtocol = GetInterfaceReference()->GetInterfaceProtocol(); 347 fPreferredSubclass = GetInterfaceReference()->GetInterfaceSubClass(); 348 349 } 350 else 351 { 352 353 OSNumber * preferredProtocol; 354 OSNumber * preferredSubclass; 355 356 357 RecordUSBTimeStamp ( UMC_TRACE ( kIOUMCStorageCharacDictFound ), 358 ( uintptr_t ) this, NULL, NULL, NULL ); 359 360 // Check if we have a USB storage personality for this particular device. 361 preferredProtocol = OSDynamicCast ( OSNumber, characterDict->getObject( kIOUSBMassStoragePreferredProtocol ) ); 362 if ( preferredProtocol == NULL ) 363 { 364 // This device does not specify a preferred protocol, use the 365 // protocol defined in the interface descriptor. 366 fPreferredProtocol = GetInterfaceReference()->GetInterfaceProtocol(); 367 368 } 369 else 370 { 371 // This device has a preferred protocol, use that. 372 fPreferredProtocol = preferredProtocol->unsigned32BitValue(); 373 374 } 375 376 // Check if this device is not to be operated at all. 377 if ( characterDict->getObject( kIOUSBMassStorageDoNotOperate ) != NULL ) 378 { 379 goto abortStart; 380 } 381 382 // Check if this device is known not to support the bulk-only USB reset. 383 if ( characterDict->getObject ( kIOUSBMassStorageUseStandardUSBReset ) != NULL ) 384 { 385 fUseUSBResetNotBOReset = true; 386 } 387 388 // Is this a device which has CBW/CSW tag issues? 389 if ( characterDict->getObject ( kIOUSBKnownCSWTagIssues ) != NULL ) 390 { 391 fKnownCSWTagMismatchIssues = true; 392 } 393 394 if ( characterDict->getObject( kIOUSBMassStorageEnableSuspendResumePM ) != NULL ) 395 { 396 fPortSuspendResumeForPMEnabled = true; 397 } 398 399#ifndef EMBEDDED 400 // Check if this device is known to have problems when waking from sleep 401 if ( characterDict->getObject( kIOUSBMassStorageResetOnResume ) != NULL ) 402 { 403 404 STATUS_LOG ( ( 4, "%s[%p]: knownResetOnResumeDevice", getName(), this ) ); 405 fRequiresResetOnResume = true; 406 407 } 408#endif // EMBEDDED 409 410 // Check to see if this device requires some time after USB reset to collect itself. 411 if ( characterDict->getObject( kIOUSBMassStoragePostResetCoolDown ) != NULL ) 412 { 413 414 OSNumber * coolDownPeriod = NULL; 415 416 coolDownPeriod = OSDynamicCast ( OSNumber, characterDict->getObject( kIOUSBMassStoragePostResetCoolDown ) ); 417 418 // Ensure we didn't get something of thew wrong type. 419 if ( coolDownPeriod != NULL ) 420 { 421 422 // Fetch our cool down interval. 423 fPostDeviceResetCoolDownInterval = coolDownPeriod->unsigned32BitValue ( ); 424 425 } 426 427 } 428 429 // Check if the personality for this device specifies a preferred subclass 430 preferredSubclass = OSDynamicCast ( OSNumber, characterDict->getObject( kIOUSBMassStoragePreferredSubclass )); 431 if ( preferredSubclass == NULL ) 432 { 433 // This device does not specify a preferred subclass, use the 434 // subclass defined in the interface descriptor. 435 fPreferredSubclass = GetInterfaceReference()->GetInterfaceSubClass(); 436 437 } 438 else 439 { 440 // This device has a preferred protocol, use that. 441 fPreferredSubclass = preferredSubclass->unsigned32BitValue(); 442 443 } 444 445#ifndef EMBEDDED 446 // Check if the device needs to be suspended on reboot 447 if ( characterDict->getObject ( kIOUSBMassStorageSuspendOnReboot ) != NULL ) 448 { 449 450 fSuspendOnReboot = true; 451 452 } 453#endif // EMBEDDED 454 455 } 456 457 STATUS_LOG ( ( 6, "%s[%p]: Preferred Protocol is: %d", getName(), this, fPreferredProtocol ) ); 458 STATUS_LOG ( ( 6, "%s[%p]: Preferred Subclass is: %d", getName(), this, fPreferredSubclass ) ); 459 460 // Verify that the device has a supported interface type and configure that 461 // Interrupt pipe if the protocol requires one. 462 STATUS_LOG ( ( 7, "%s[%p]: Configure the Storage interface", getName(), this ) ); 463 switch ( GetInterfaceProtocol() ) 464 { 465 case kProtocolControlBulkInterrupt: 466 { 467 RecordUSBTimeStamp ( UMC_TRACE ( kCBIProtocolDeviceDetected ), 468 ( uintptr_t ) this, NULL, 469 NULL, NULL ); 470 471 // Find the interrupt pipe for the device. 472 // Note that the pipe will already be retained on our behalf. 473 request.type = kUSBInterrupt; 474 request.direction = kUSBIn; 475 fInterruptPipe = GetInterfaceReference()->FindNextPipe ( NULL, &request, true ); 476 477 STATUS_LOG ( ( 7, "%s[%p]: find interrupt pipe", getName(), this ) ); 478 require_nonzero ( fInterruptPipe, abortStart ); 479 480 fCBIMemoryDescriptor = IOMemoryDescriptor::withAddress ( 481 &fCBICommandRequestBlock.cbiGetStatusBuffer, 482 kUSBStorageAutoStatusSize, 483 kIODirectionIn ); 484 require_nonzero ( fCBIMemoryDescriptor, abortStart ); 485 486 result = fCBIMemoryDescriptor->prepare(); 487 require_success ( result, abortStart ); 488 } 489 break; 490 491 case kProtocolControlBulk: 492 // Since all the CB devices I have seen do not use the interrupt 493 // endpoint, even if it exists, ignore it if present. 494 case kProtocolBulkOnly: 495 { 496 497 STATUS_LOG ( ( 7, "%s[%p]: Bulk Only - skip interrupt pipe", getName(), this ) ); 498 499 RecordUSBTimeStamp ( UMC_TRACE ( kBODeviceDetected ), 500 ( uintptr_t ) this, NULL, NULL, NULL ); 501 502 // Allocate the memory descriptor needed to send the CBW out. 503 fBulkOnlyCBWMemoryDescriptor = IOMemoryDescriptor::withAddress ( 504 &fBulkOnlyCommandRequestBlock.boCBW, 505 kByteCountOfCBW, 506 kIODirectionOut ); 507 require_nonzero ( fBulkOnlyCBWMemoryDescriptor, abortStart ); 508 509 result = fBulkOnlyCBWMemoryDescriptor->prepare(); 510 require_success ( result, abortStart ); 511 512 // Allocate the memory descriptor needed to retrieve the CSW. 513 fBulkOnlyCSWMemoryDescriptor = IOMemoryDescriptor::withAddress ( 514 &fBulkOnlyCommandRequestBlock.boCSW, 515 kByteCountOfCSW, 516 kIODirectionIn ); 517 require_nonzero ( fBulkOnlyCSWMemoryDescriptor, abortStart ); 518 519 result = fBulkOnlyCSWMemoryDescriptor->prepare(); 520 require_success ( result, abortStart ); 521 522 } 523 break; 524 525 default: 526 { 527 RecordUSBTimeStamp ( UMC_TRACE ( kNoProtocolForDevice ), 528 ( uintptr_t ) this, NULL, NULL, NULL ); 529 530 // The device has a protocol that the driver does not 531 // support. Return false to indicate that instantiation was 532 // not successful. 533 goto abortStart; 534 } 535 break; 536 } 537 538 // Find the Bulk In pipe for the device 539 STATUS_LOG ( ( 7, "%s[%p]: find bulk in pipe", getName(), this ) ); 540 request.type = kUSBBulk; 541 request.direction = kUSBIn; 542 fBulkInPipe = GetInterfaceReference()->FindNextPipe ( NULL, &request, true ); 543 require_nonzero ( fBulkInPipe, abortStart ); 544 545 // Find the Bulk Out pipe for the device 546 STATUS_LOG ( ( 7, "%s[%p]: find bulk out pipe", getName(), this ) ); 547 request.type = kUSBBulk; 548 request.direction = kUSBOut; 549 fBulkOutPipe = GetInterfaceReference()->FindNextPipe ( NULL, &request, true ); 550 require_nonzero ( fBulkOutPipe, abortStart ); 551 552 // Build the Protocol Characteristics dictionary since not all devices will have a 553 // SCSI Peripheral Device Nub to guarantee its existance. 554 characterDict = OSDynamicCast ( OSDictionary, getProperty ( kIOPropertyProtocolCharacteristicsKey ) ); 555 if ( characterDict == NULL ) 556 { 557 characterDict = OSDictionary::withCapacity ( 1 ); 558 } 559 560 else 561 { 562 characterDict->retain ( ); 563 } 564 565 require_nonzero ( characterDict, abortStart ); 566 567 obj = getProperty ( kIOPropertyPhysicalInterconnectTypeKey ); 568 if ( obj != NULL ) 569 { 570 characterDict->setObject ( kIOPropertyPhysicalInterconnectTypeKey, obj ); 571 } 572 573 obj = getProperty ( kIOPropertyPhysicalInterconnectLocationKey ); 574 if ( obj != NULL ) 575 { 576 characterDict->setObject ( kIOPropertyPhysicalInterconnectLocationKey, obj ); 577 } 578 579 // Check to see if this device is internal or not. The results of this check if successful 580 // will override location data provided in IOKit personalities. 581 if ( IsPhysicalInterconnectLocationInternal ( ) ) 582 { 583 584 OSString * internalString = NULL; 585 586 587 internalString = OSString::withCString ( kIOPropertyInternalKey ); 588 if ( internalString != NULL ) 589 { 590 591 characterDict->setObject ( kIOPropertyPhysicalInterconnectLocationKey, internalString ); 592 internalString->release ( ); 593 internalString = NULL; 594 595 } 596 597 } 598 599 obj = getProperty ( kIOPropertyReadTimeOutDurationKey ); 600 if ( obj != NULL ) 601 { 602 characterDict->setObject ( kIOPropertyReadTimeOutDurationKey, obj ); 603 } 604 else 605 { 606 607 number = OSNumber::withNumber ( kDefaultReadTimeoutDuration, 32 ); 608 if ( number != NULL ) 609 { 610 611 characterDict->setObject ( kIOPropertyReadTimeOutDurationKey, number ); 612 number->release ( ); 613 number = NULL; 614 615 } 616 617 } 618 619 obj = getProperty ( kIOPropertyWriteTimeOutDurationKey ); 620 if ( obj != NULL ) 621 { 622 characterDict->setObject ( kIOPropertyWriteTimeOutDurationKey, obj ); 623 } 624 else 625 { 626 627 number = OSNumber::withNumber ( kDefaultWriteTimeoutDuration, 32 ); 628 if ( number != NULL ) 629 { 630 631 characterDict->setObject ( kIOPropertyWriteTimeOutDurationKey, number ); 632 number->release ( ); 633 number = NULL; 634 635 } 636 637 } 638 639 setProperty ( kIOPropertyProtocolCharacteristicsKey, characterDict ); 640 641 characterDict->release ( ); 642 characterDict = NULL; 643 644 STATUS_LOG ( ( 6, "%s[%p]: successfully configured", getName(), this ) ); 645 646#if defined (__i386__) || defined (__x86_64__) 647 { 648 // As USB booting is only supporting on i386 based, do not compile for PPC. 649 char usbDeviceAddress [ kUSBDAddressLength ]; 650 OSNumber * usbDeviceID; 651 652 snprintf ( usbDeviceAddress, kUSBDAddressLength, "%x", ( int ) GetInterfaceReference()->GetDevice()->GetAddress() ); 653 654 usbDeviceID = OSNumber::withNumber ( ( int ) GetInterfaceReference()->GetDevice()->GetAddress(), 64 ); 655 if ( usbDeviceID != NULL ) 656 { 657 658 setProperty ( kIOPropertyIOUnitKey, usbDeviceID ); 659 setLocation ( ( const char * ) usbDeviceAddress, gIODTPlane ); 660 661 usbDeviceID->release ( ); 662 663 } 664 } 665#endif 666 667 668 // Device configured. We're attached. 669 fDeviceAttached = true; 670 671 InitializePowerManagement ( GetInterfaceReference() ); 672 673 success = BeginProvidedServices(); 674 require ( success, abortStart ); 675 676 retVal = true; 677 goto Exit; 678 679abortStart: 680 681 STATUS_LOG ( ( 1, "%s[%p]: aborting startup. Stop the provider.", getName(), this ) ); 682 683 if ( IsPowerManagementIntialized() ) 684 { 685 686 PMstop(); 687 688 } 689 690 // Close and nullify our USB Interface. 691 { 692 IOUSBInterface * currentInterface; 693 694 currentInterface = GetInterfaceReference(); 695 696 if ( currentInterface != NULL ) 697 { 698 699 SetInterfaceReference( NULL ); 700 currentInterface->close( this ); 701 702 } 703 704 } 705 706 if ( fCBIMemoryDescriptor != NULL ) 707 { 708 fCBIMemoryDescriptor->complete(); 709 fCBIMemoryDescriptor->release(); 710 fCBIMemoryDescriptor = NULL; 711 } 712 713 if ( fBulkOnlyCBWMemoryDescriptor != NULL ) 714 { 715 fBulkOnlyCBWMemoryDescriptor->complete(); 716 fBulkOnlyCBWMemoryDescriptor->release(); 717 fBulkOnlyCBWMemoryDescriptor = NULL; 718 } 719 720 if ( fBulkOnlyCSWMemoryDescriptor != NULL ) 721 { 722 fBulkOnlyCSWMemoryDescriptor->complete(); 723 fBulkOnlyCSWMemoryDescriptor->release(); 724 fBulkOnlyCSWMemoryDescriptor = NULL; 725 } 726 727 // Call the stop method to clean up any allocated resources. 728 stop ( provider ); 729 730Exit: 731 732 return retVal; 733 734} 735 736//-------------------------------------------------------------------------------------------------- 737// stop - Called at stop time [PUBLIC] 738//-------------------------------------------------------------------------------------------------- 739 740void 741IOUSBMassStorageClass::stop ( IOService * provider ) 742{ 743 // I am logging this as a 1 because if anything is logging after this we want to know about it. 744 // This should be the last message we see. Bye bye! 745 STATUS_LOG ( ( 1, "%s[%p]: stop: Called", getName(), this ) ); 746 747 RecordUSBTimeStamp ( UMC_TRACE ( kIOUSBMassStorageClassStop ), 748 ( uintptr_t ) this, NULL, NULL, NULL ); 749 750 EndProvidedServices ( ); 751 752 // Release and NULL our pipe pointers so we don't try to access our provider. 753 754 if ( fBulkInPipe != NULL ) 755 { 756 757 fBulkInPipe->release ( ); 758 fBulkInPipe = NULL; 759 760 } 761 762 if ( fBulkOutPipe != NULL ) 763 { 764 765 fBulkOutPipe->release ( ); 766 fBulkOutPipe = NULL; 767 768 } 769 770 if ( fInterruptPipe != NULL ) 771 { 772 773 fInterruptPipe->release ( ); 774 fInterruptPipe = NULL; 775 776 } 777 778 // Release our retain on the provider's workLoop. 779 780 super::stop ( provider ); 781} 782 783 784//-------------------------------------------------------------------------------------------------- 785// free - Called by IOKit to free any resources. [PUBLIC] 786//-------------------------------------------------------------------------------------------------- 787 788void 789IOUSBMassStorageClass::free ( void ) 790{ 791 792 STATUS_LOG ( ( 1, "%s[%p]: free: Called", getName(), this ) ); 793 794#ifndef EMBEDDED 795require_nonzero ( reserved, Exit ); 796#endif // EMBEDDED 797 798 // Since fClients is defined as reserved->fClients we don't want 799 // to dereference it unless reserved is non-NULL. 800 if ( fClients != NULL ) 801 { 802 803 fClients->release ( ); 804 fClients = NULL; 805 806 } 807 808 if ( fCBIMemoryDescriptor != NULL ) 809 { 810 811 fCBIMemoryDescriptor->complete ( ); 812 fCBIMemoryDescriptor->release ( ); 813 fCBIMemoryDescriptor = NULL; 814 815 } 816 817 if ( fBulkOnlyCBWMemoryDescriptor != NULL ) 818 { 819 820 fBulkOnlyCBWMemoryDescriptor->complete ( ); 821 fBulkOnlyCBWMemoryDescriptor->release ( ); 822 fBulkOnlyCBWMemoryDescriptor = NULL; 823 824 } 825 826 if ( fBulkOnlyCSWMemoryDescriptor != NULL ) 827 { 828 829 fBulkOnlyCSWMemoryDescriptor->complete ( ); 830 fBulkOnlyCSWMemoryDescriptor->release ( ); 831 fBulkOnlyCSWMemoryDescriptor = NULL; 832 833 } 834 835#ifndef EMBEDDED 836 IOFree ( reserved, sizeof ( ExpansionData ) ); 837 reserved = NULL; 838#endif // EMBEDDED 839 840Exit: 841 842 843 super::free ( ); 844 845} 846 847 848//-------------------------------------------------------------------------------------------------- 849// message - Called by IOKit to deliver messages. [PUBLIC] 850//-------------------------------------------------------------------------------------------------- 851 852IOReturn 853IOUSBMassStorageClass::message ( UInt32 type, IOService * provider, void * argument ) 854{ 855 IOReturn result = kIOReturnSuccess; 856 857 RecordUSBTimeStamp ( UMC_TRACE ( kMessagedCalled ), ( uintptr_t ) this, type, NULL, NULL ); 858 859 STATUS_LOG ( ( 4, "%s[%p]: message = %lx called", getName ( ), this, type ) ); 860 switch ( type ) 861 { 862 863 case kIOUSBMessagePortHasBeenResumed: 864 { 865 866 STATUS_LOG ( ( 2, "%s[%p]: message kIOUSBMessagePortHasBeenResumed.", getName ( ), this ) ); 867 868#ifndef EMBEDDED 869 if ( fRequiresResetOnResume == true ) 870 { 871 ResetDeviceNow ( true ); 872 } 873#else // EMBEDDED 874 ResetDeviceNow ( true ); 875#endif // EMBEDDED 876 877 } 878 break; 879 880 case kIOUSBMessageCompositeDriverReconfigured: 881 { 882 fWaitingForReconfigurationMessage = false; 883 } 884 break; 885 886 default: 887 { 888 STATUS_LOG ( ( 2, "%s[%p]: message default case.", getName ( ), this ) ); 889 result = super::message ( type, provider, argument ); 890 } 891 892 } 893 894 return result; 895 896} 897 898 899//-------------------------------------------------------------------------------------------------- 900// willTerminate [PUBLIC] 901//-------------------------------------------------------------------------------------------------- 902 903bool 904IOUSBMassStorageClass::willTerminate ( IOService * provider, 905 IOOptionBits options ) 906{ 907 908 STATUS_LOG ( ( 2, "%s[%p]: willTerminate called.", getName ( ), this ) ); 909 910 RecordUSBTimeStamp ( UMC_TRACE ( kWillTerminateCalled ), 911 ( uintptr_t ) this, ( uintptr_t ) GetInterfaceReference ( ), 912 ( unsigned int ) isInactive ( ), NULL ); 913 914 // Mark ourselves as terminating so we don't accept any additional I/O. 915 fTerminating = true; 916 917 // Let clients know that the device is gone. 918 SendNotification_DeviceRemoved ( ); 919 920 return super::willTerminate ( provider, options ); 921 922} 923 924 925//-------------------------------------------------------------------------------------------------- 926// didTerminate [PUBLIC] 927//-------------------------------------------------------------------------------------------------- 928 929bool 930IOUSBMassStorageClass::didTerminate ( IOService * provider, IOOptionBits options, bool * defer ) 931{ 932 933 IOUSBInterface * currentInterface; 934 IOReturn status; 935 bool success; 936 937 // This method comes at the end of the termination sequence. Hopefully, all of our outstanding IO is complete 938 // in which case we can just close our provider and IOKit will take care of the rest. Otherwise, we need to 939 // hold on to the device and IOKit will terminate us when we close it later. 940 941 STATUS_LOG ( ( 3 , "%s[%p]::didTerminate: Entered with options=0x%x defer=%d", getName ( ), this, options, ( defer ? *defer : false ) ) ); 942 943 // Abort pipes to ensure that any outstanding USB requests are returned to us. 944 // For USB it is the responsibility of the client driver to request outstanding 945 // I/O requests be returned once driver termination has been initiated. 946 947 if ( fBulkInPipe != NULL ) 948 { 949 fBulkInPipe->Abort ( ); 950 } 951 952 if ( fBulkOutPipe != NULL ) 953 { 954 fBulkOutPipe->Abort ( ); 955 } 956 957 if ( fInterruptPipe != NULL ) 958 { 959 fInterruptPipe->Abort ( ); 960 } 961 962 // If we have a SCSI task outstanding, we will block here until it completes. 963 // This ensures that we don't try to send requests to our provider after we have closed it. 964 fTerminationDeferred = fBulkOnlyCommandStructInUse | fCBICommandStructInUse; 965 966 RecordUSBTimeStamp ( UMC_TRACE ( kDidTerminateCalled ), 967 ( uintptr_t ) this, ( unsigned int ) fTerminationDeferred, NULL, NULL ); 968 969 while ( fTerminationDeferred == true ) 970 { 971 972 STATUS_LOG ( ( 3 , "%s[%p]::didTerminate: Sleeping on fTerminationDeferred", getName ( ), this ) ); 973 status = fCommandGate->commandSleep ( &fTerminationDeferred, THREAD_UNINT ); 974 STATUS_LOG ( ( 3 , "%s[%p]::didTerminate: Awoke with status=0x%x fTerminationDeferred=%d", getName ( ), this, status, fTerminationDeferred ) ); 975 976 } 977 978 // Close our provider, and clear our reference to it. 979 980 currentInterface = GetInterfaceReference ( ); 981 require_nonzero ( currentInterface, ErrorExit ); 982 983 STATUS_LOG ( ( 3 , "%s[%p]::didTerminate: Closing provider", getName ( ), this ) ); 984 SetInterfaceReference ( NULL ); 985 currentInterface->close ( this ); 986 STATUS_LOG ( ( 3 , "%s[%p]::didTerminate: Closed provider", getName ( ), this ) ); 987 988 989ErrorExit: 990 991 992 success = super::didTerminate ( provider, options, defer ); 993 994 STATUS_LOG ( ( 3 , "%s[%p]::didTerminate: Returning success=%d defer=%d", getName ( ), this, success, ( defer ? *defer : false ) ) ); 995 996 return success; 997 998} 999 1000 1001#ifndef EMBEDDED 1002 1003//-------------------------------------------------------------------------------------------------- 1004// systemWillShutdown [PUBLIC] 1005//-------------------------------------------------------------------------------------------------- 1006 1007void 1008IOUSBMassStorageClass::systemWillShutdown ( IOOptionBits specifier ) 1009{ 1010 1011 STATUS_LOG ( ( 3 , "%s[%p]::systemWillShutdown: specifier = 0x%x fSuspendOnReboot = %s", getName ( ), this, specifier, fSuspendOnReboot ? "true" : "false" ) ); 1012 1013 if ( ( fSuspendOnReboot == true ) && ( ( specifier == kIOMessageSystemWillRestart ) || ( specifier == kIOMessageSystemWillPowerOff ) ) ) 1014 { 1015 1016 SuspendPort ( true ); 1017 1018 } 1019 1020 super::systemWillShutdown ( specifier ); 1021 1022} 1023 1024#endif // EMBEDDED 1025 1026 1027//-------------------------------------------------------------------------------------------------- 1028// BeginProvidedServices [PROTECTED] 1029//-------------------------------------------------------------------------------------------------- 1030 1031bool 1032IOUSBMassStorageClass::BeginProvidedServices ( void ) 1033{ 1034 1035 // If this is a BO device that supports multiple LUNs, we will need 1036 // to spawn off a nub for each valid LUN. If this is a CBI/CB 1037 // device or a BO device that only supports LUN 0, this object can 1038 // register itself as the nub. 1039 STATUS_LOG ( ( 7, "%s[%p]: Determine the maximum LUN", getName(), this ) ); 1040 1041 if ( GetInterfaceProtocol() == kProtocolBulkOnly ) 1042 { 1043 IOReturn status = kIOReturnError; 1044 bool maxLUNDetermined = false; 1045 OSDictionary * characterDict = NULL; 1046 1047 1048 // Before we issue the GetMaxLUN call let's check if this device 1049 // specifies a MaxLogicalUnitNumber as part of its personality. 1050 characterDict = OSDynamicCast ( OSDictionary, getProperty ( kIOUSBMassStorageCharacteristics ) ); 1051 if ( characterDict != NULL ) 1052 { 1053 1054 OSNumber * maxLUN = OSDynamicCast ( OSNumber, 1055 characterDict->getObject ( kIOUSBMassStorageMaxLogicalUnitNumber ) ); 1056 1057 if( maxLUN != NULL ) 1058 { 1059 1060 RecordUSBTimeStamp ( UMC_TRACE ( kBOPreferredMaxLUN ), 1061 ( uintptr_t ) this, maxLUN->unsigned8BitValue(), NULL, NULL ); 1062 1063 STATUS_LOG ( ( 4, "%s[%p]: Number of LUNs %u.", getName(), this, maxLUN->unsigned8BitValue() ) ); 1064 1065 SetMaxLogicalUnitNumber ( maxLUN->unsigned8BitValue() ); 1066 maxLUNDetermined = true; 1067 1068 } 1069 1070 } 1071 1072 if( maxLUNDetermined == false ) 1073 { 1074 // The device is a Bulk Only transport device, issue the 1075 // GetMaxLUN call to determine what the maximum value is. 1076 bool triedReset = false; 1077 UInt8 clearPipeAttempts = 0; 1078 1079 // We want to loop until we get a satisfactory response to GetMaxLUN, either an answer or failure. 1080 while ( status != kIOReturnSuccess ) 1081 { 1082 1083 // Build the USB command 1084 fUSBDeviceRequest.bmRequestType = USBmakebmRequestType( kUSBIn, kUSBClass, kUSBInterface ); 1085 fUSBDeviceRequest.bRequest = 0xFE; 1086 fUSBDeviceRequest.wValue = 0; 1087 fUSBDeviceRequest.wIndex = GetInterfaceReference()->GetInterfaceNumber(); 1088 fUSBDeviceRequest.wLength = 1; 1089 fUSBDeviceRequest.pData = &fMaxLogicalUnitNumber; 1090 1091 STATUS_LOG ( ( 4, "%s[%p]: Issuing device request to find max LUN", getName(), this ) ); 1092 1093 // Send the command over the control endpoint 1094 status = GetInterfaceReference()->DeviceRequest ( &fUSBDeviceRequest ); 1095 1096 RecordUSBTimeStamp ( UMC_TRACE ( kBOGetMaxLUNReturned ), 1097 ( uintptr_t ) this, status, fMaxLogicalUnitNumber, ( unsigned int ) triedReset ); 1098 1099 STATUS_LOG ( ( 4, "%s[%p]: DeviceRequest GetMaxLUN returned status = %x", getName(), this, status ) ); 1100 1101 if ( status != kIOReturnSuccess ) 1102 { 1103 1104 SetMaxLogicalUnitNumber( 0 ); 1105 if( ( status == kIOUSBPipeStalled ) && ( clearPipeAttempts < 3 ) ) 1106 { 1107 1108 UInt8 eStatus[2]; 1109 1110 STATUS_LOG ( ( 4, "%s[%p]: calling GetStatusEndpointStatus to clear stall", getName(), this ) ); 1111 1112 // Throw in an extra Get Status to clear up devices that stall the 1113 // control pipe like the early Iomega devices. 1114 GetStatusEndpointStatus( GetControlPipe(), &eStatus[0], NULL); 1115 1116 clearPipeAttempts++; 1117 1118 } 1119 else if ( ( status == kIOReturnNotResponding ) && ( triedReset == false ) ) 1120 { 1121 1122 // The device isn't responding. Let us reset the device, and try again. 1123 1124 STATUS_LOG ( ( 4, "%s[%p]: BeginProvidedServices: device not responding, reseting.", getName(), this ) ); 1125 1126 // Reset the device on its own thread so we don't deadlock. 1127 ResetDeviceNow ( true ); 1128 1129 triedReset = true; 1130 1131 } 1132 else 1133 { 1134 break; 1135 } 1136 1137 } 1138 1139 } 1140 1141 } 1142 1143 } 1144 else 1145 { 1146 // CBI and CB protocols do not support LUNs so for these the 1147 // maximum LUN will always be zero. 1148 SetMaxLogicalUnitNumber( 0 ); 1149 } 1150 1151 RecordUSBTimeStamp ( UMC_TRACE ( kLUNConfigurationComplete ), 1152 ( uintptr_t ) this, GetMaxLogicalUnitNumber ( ), NULL, NULL ); 1153 1154 STATUS_LOG ( ( 5, "%s[%p]: Configured, Max LUN = %d", getName(), this, GetMaxLogicalUnitNumber() ) ); 1155 1156 // If this is a BO device that supports multiple LUNs, we will need 1157 // to spawn off a nub for each valid LUN. If this is a CBI/CB 1158 // device or a BO device that only supports LUN 0, this object can 1159 // register itself as the nub. 1160 if ( GetMaxLogicalUnitNumber() > 0 ) 1161 { 1162 // Allocate space for our set that will keep track of the LUNs. 1163 fClients = OSSet::withCapacity ( GetMaxLogicalUnitNumber() + 1 ); 1164 1165 for( int loopLUN = 0; loopLUN <= GetMaxLogicalUnitNumber(); loopLUN++ ) 1166 { 1167 STATUS_LOG ( ( 6, "%s[%p]::CreatePeripheralDeviceNubForLUN entering.", getName(), this ) ); 1168 1169 IOSCSILogicalUnitNub * nub = OSTypeAlloc( IOSCSILogicalUnitNub ); 1170 1171 if( nub == NULL ) 1172 { 1173 PANIC_NOW ( ( "IOUSBMassStorageClass::CreatePeripheralDeviceNubForLUN failed" ) ); 1174 return false; 1175 } 1176 1177 if ( nub->init( 0 ) == false ) 1178 { 1179 // Release our nub before we return so we don't leak... 1180 nub->release(); 1181 // We didn't init successfully so we should return false. 1182 return false; 1183 } 1184 1185 if ( nub->attach( this ) == false ) 1186 { 1187 if( isInactive() == false ) 1188 { 1189 // panic since the nub can't attach and we are active 1190 PANIC_NOW ( ( "IOUSBMassStorageClass::CreatePeripheralDeviceNubForLUN unable to attach nub" ) ); 1191 } 1192 1193 // Release our nub before we return so we don't leak... 1194 nub->release(); 1195 // We didn't attach so we should return false. 1196 return false; 1197 } 1198 1199 nub->SetLogicalUnitNumber ( loopLUN ); 1200 if ( nub->start ( this ) == false ) 1201 { 1202 nub->detach ( this ); 1203 } 1204 else 1205 { 1206 nub->registerService ( kIOServiceAsynchronous ); 1207 } 1208 1209 nub->release(); 1210 nub = NULL; 1211 1212 STATUS_LOG ( ( 6, "%s[%p]::CreatePeripheralDeviceNubForLUN exiting.", getName(), this ) ); 1213 } 1214 } 1215 1216 // Calling registerService() will start driver matching and result in our handleOpen() method 1217 // being called by an IOSCSIPeripheralDeviceNub object. In the multi-LUN case in which our 1218 // nubs have already been instantiated (above), that open will fail because our MaxLogicalUnitNumber 1219 // is nonzero. In the single LUN case, the open will succeed and the rest of the storage stack 1220 // will be built upon it. 1221 registerService ( kIOServiceAsynchronous ); 1222 1223 return true; 1224 1225} 1226 1227 1228//-------------------------------------------------------------------------------------------------- 1229// EndProvidedServices [PROTECTED] 1230//-------------------------------------------------------------------------------------------------- 1231 1232bool 1233IOUSBMassStorageClass::EndProvidedServices 1234( void ) 1235{ 1236 return true; 1237} 1238 1239 1240#pragma mark - 1241#pragma mark *** CDB Transport Methods *** 1242#pragma mark - 1243 1244 1245//-------------------------------------------------------------------------------------------------- 1246// SendSCSICommand [PROTECTED] 1247//-------------------------------------------------------------------------------------------------- 1248 1249bool 1250IOUSBMassStorageClass::SendSCSICommand ( 1251 SCSITaskIdentifier request, 1252 SCSIServiceResponse * serviceResponse, 1253 SCSITaskStatus * taskStatus ) 1254{ 1255 1256 IOReturn status; 1257 SCSICommandDescriptorBlock cdbData; 1258 bool accepted = false; 1259 1260 STATUS_LOG ( ( 6, "%s[%p]: SendSCSICommand Entered with request=%p", getName ( ), this, request ) ); 1261 1262 // Close the commandGate, then check whether we can accept this new SCSI task. 1263 // If so, then atomically set the commandStructInUse flag. 1264 1265 fCommandGate->runAction ( OSMemberFunctionCast ( IOCommandGate::Action, 1266 this, 1267 &IOUSBMassStorageClass::AcceptSCSITask ), 1268 request, 1269 &accepted ); 1270 1271 require_quiet ( accepted, Exit ); 1272 1273 // Now that we have committed to accepting this task, we must return kSCSIServiceResponse_Request_In_Progress, 1274 // even if we subsequently fail that task from within this method via CommandCompleted(). 1275 1276 *taskStatus = kSCSITaskStatus_No_Status; 1277 *serviceResponse = kSCSIServiceResponse_Request_In_Process; 1278 1279 GetCommandDescriptorBlock( request, &cdbData ); 1280 1281 RecordUSBTimeStamp ( UMC_TRACE ( kCDBLog1 ), 1282 ( uintptr_t ) this, ( uintptr_t ) request, 1283 ( cdbData[ 0] ) | ( cdbData[ 1] << 8 ) | ( cdbData[ 2] << 16 ) | ( cdbData[ 3] << 24 ), 1284 ( cdbData[ 4] ) | ( cdbData[ 5] << 8 ) | ( cdbData[ 6] << 16 ) | ( cdbData[ 7] << 24 ) ); 1285 1286 RecordUSBTimeStamp ( UMC_TRACE ( kCDBLog2 ), 1287 ( uintptr_t ) this, ( uintptr_t ) request, 1288 ( cdbData[ 8] ) | ( cdbData[ 9] << 8 ) | ( cdbData[10] << 16 ) | ( cdbData[11] << 24 ), 1289 ( cdbData[12] ) | ( cdbData[13] << 8 ) | ( cdbData[14] << 16 ) | ( cdbData[15] << 24 ) ); 1290 1291#if USB_MASS_STORAGE_DEBUG 1292 1293 STATUS_LOG ( ( 4, "%s[%p]: SendSCSICommand CDB data: ", getName(), this ) ); 1294 1295 if ( GetCommandDescriptorBlockSize ( request ) == kSCSICDBSize_6Byte ) 1296 STATUS_LOG ( ( 4, "%s[%p]: %X : %X : %X : %X : %X : %X", 1297 getName(), this, cdbData[0], cdbData[1], 1298 cdbData[2], cdbData[3], cdbData[4], cdbData[5] ) ); 1299 else if ( GetCommandDescriptorBlockSize ( request ) == kSCSICDBSize_10Byte ) 1300 STATUS_LOG ( ( 4, "%s[%p]: %X : %X : %X : %X : %X : %X : %X : %X : %X : %X", 1301 getName(), this, cdbData[0], cdbData[1], 1302 cdbData[2], cdbData[3], cdbData[4], cdbData[5], 1303 cdbData[6], cdbData[7], cdbData[8], cdbData[9] ) ); 1304 else if ( GetCommandDescriptorBlockSize ( request ) == kSCSICDBSize_12Byte ) 1305 STATUS_LOG ( ( 4, "%s[%p]: %X : %X : %X : %X : %X : %X : %X : %X : %X : %X : %X : %X", 1306 getName(), this, cdbData[0], cdbData[1], 1307 cdbData[2], cdbData[3], cdbData[4], cdbData[5], 1308 cdbData[6], cdbData[7], cdbData[8], cdbData[9], 1309 cdbData[10], cdbData[11] ) ); 1310 else if ( GetCommandDescriptorBlockSize ( request ) == kSCSICDBSize_16Byte ) 1311 STATUS_LOG ( ( 4, "%s[%p]: %X : %X : %X : %X : %X : %X : %X : %X : %X : %X : %X : %X : %X : %X : %X : %X", 1312 getName(), this, cdbData[0], cdbData[1], 1313 cdbData[2], cdbData[3], cdbData[4], cdbData[5], 1314 cdbData[6], cdbData[7], cdbData[8], cdbData[9], 1315 cdbData[10], cdbData[11], cdbData[12], cdbData[13], 1316 cdbData[14], cdbData[15] ) ); 1317#endif 1318 1319 require_action ( ( isInactive ( ) == false ), ErrorExit, status = kIOReturnNoDevice ); 1320 1321 if ( GetInterfaceProtocol() == kProtocolBulkOnly ) 1322 { 1323 1324 status = SendSCSICommandForBulkOnlyProtocol ( request ); 1325 1326 RecordUSBTimeStamp ( UMC_TRACE ( kBOSendSCSICommandReturned ), 1327 ( uintptr_t ) this, ( uintptr_t ) request, status, NULL ); 1328 1329 STATUS_LOG ( ( 5, "%s[%p]: SendSCSICommandforBulkOnlyProtocol returned %x", getName ( ), this, status ) ); 1330 1331 } 1332 1333 else 1334 { 1335 1336 status = SendSCSICommandForCBIProtocol ( request ); 1337 1338 RecordUSBTimeStamp ( UMC_TRACE ( kCBISendSCSICommandReturned ), 1339 ( uintptr_t ) this, ( uintptr_t ) request, status, NULL ); 1340 1341 STATUS_LOG ( ( 5, "%s[%p]: SendSCSICommandforCBIProtocol returned %x", getName ( ), this, status ) ); 1342 1343 } 1344 1345 // A nonzero status indicates that we could not post the USB CBW request to the device, probably due to termination. 1346 // In that case, we fail this task via a call to CommandCompleted(). 1347 // We never fail a task with an immediate serviceResponse, because the retain which ExecuteTask() took on us on 1348 // behalf of the SCSI task would never be released, preventing us from being freed. 1349 1350 1351ErrorExit: 1352 1353 1354 if ( status != kIOReturnSuccess ) 1355 { 1356 1357 SCSIServiceResponse localServiceResponse = kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE; 1358 SCSITaskStatus localTaskStatus = kSCSITaskStatus_DeliveryFailure; 1359 1360 STATUS_LOG ( ( 5, "%s[%p]: Failing immediately due to status=0x%x", getName ( ), this, status ) ); 1361 1362 // An error was seen which prevented the command from being sent. Fail the SCSI task. 1363 fCommandGate->runAction ( 1364 OSMemberFunctionCast ( IOCommandGate::Action, 1365 this, 1366 &IOUSBMassStorageClass::GatedCompleteSCSICommand ), 1367 request, 1368 ( void * ) &localServiceResponse, 1369 ( void * ) &localTaskStatus ); 1370 1371 } 1372 1373 1374Exit: 1375 1376 1377 STATUS_LOG ( ( 6, "%s[%p]: SendSCSICommand returning accepted=%d", getName ( ), this, accepted ) ); 1378 1379 return accepted; 1380 1381} 1382 1383 1384//-------------------------------------------------------------------------------------------------- 1385// CompleteSCSICommand [PROTECTED] 1386//-------------------------------------------------------------------------------------------------- 1387 1388void 1389IOUSBMassStorageClass::CompleteSCSICommand ( SCSITaskIdentifier request, IOReturn status ) 1390{ 1391 1392 SCSITaskStatus taskStatus; 1393 1394 check ( fWorkLoop->inGate ( ) == true ); 1395 1396 fBulkOnlyCommandStructInUse = false; 1397 fCBICommandStructInUse = false; 1398 1399 // Clear the count of consecutive I/Os which required a USB Device Reset. 1400 fConsecutiveResetCount = 0; 1401 1402 if ( status == kIOReturnSuccess ) 1403 { 1404 taskStatus = kSCSITaskStatus_GOOD; 1405 } 1406 else 1407 { 1408 1409 taskStatus = kSCSITaskStatus_CHECK_CONDITION; 1410 1411 // Make this error easier to see in the trace output. 1412 RecordUSBTimeStamp ( UMC_TRACE ( kCompletingCommandWithError ), ( uintptr_t ) this, NULL, NULL, NULL ); 1413 1414 } 1415 1416 STATUS_LOG ( ( 6, "%s[%p]: CompleteSCSICommand request=%p taskStatus=0x%02x", getName(), this, request, taskStatus ) ); 1417 1418 RecordUSBTimeStamp ( UMC_TRACE ( kCompleteSCSICommand ), 1419 ( uintptr_t ) this, ( uintptr_t ) request, 1420 kSCSIServiceResponse_TASK_COMPLETE, taskStatus ); 1421 1422 CommandCompleted ( request, kSCSIServiceResponse_TASK_COMPLETE, taskStatus ); 1423 1424 // If didTerminate() was called while this SCSI task was outstanding, then termination would 1425 // have been deferred until it completed. Check for that now, while behind the command gate. 1426 CheckDeferredTermination ( ); 1427 1428} 1429 1430 1431//-------------------------------------------------------------------------------------------------- 1432// AbortSCSICommand [PROTECTED] 1433//-------------------------------------------------------------------------------------------------- 1434 1435SCSIServiceResponse 1436IOUSBMassStorageClass::AbortSCSICommand ( SCSITaskIdentifier abortTask ) 1437{ 1438 1439 IOReturn status = kIOReturnSuccess; 1440 1441 STATUS_LOG ( ( 6, "%s[%p]: AbortSCSICommand was called", getName(), this ) ); 1442 if ( abortTask == NULL ) 1443 { 1444 // We were given an invalid SCSI Task object. Let the client know. 1445 STATUS_LOG ( ( 1, "%s[%p]: AbortSCSICommand was called with a NULL CDB object", getName(), this ) ); 1446 return kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE; 1447 } 1448 1449 if ( fTerminating == true ) 1450 { 1451 // We have an invalid interface, the device has probably been removed. 1452 // Nothing else to do except to report an error. 1453 STATUS_LOG ( ( 1, "%s[%p]: AbortSCSICommand was called with a NULL interface", getName(), this ) ); 1454 return kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE; 1455 } 1456 1457 RecordUSBTimeStamp ( UMC_TRACE( kAbortedTask ), 1458 ( uintptr_t ) this, ( uintptr_t ) abortTask, NULL, NULL ); 1459 1460 if ( GetInterfaceReference()->GetInterfaceProtocol() == kProtocolBulkOnly ) 1461 { 1462 status = AbortSCSICommandForBulkOnlyProtocol( abortTask ); 1463 STATUS_LOG ( ( 5, "%s[%p]: abortCDBforBulkOnlyProtocol returned %x", getName(), this, status ) ); 1464 } 1465 1466 else 1467 { 1468 status = AbortSCSICommandForCBIProtocol( abortTask ); 1469 STATUS_LOG ( ( 5, "%s[%p]: abortCDBforCBIProtocol returned %x", getName(), this, status ) ); 1470 } 1471 1472 // Since the driver currently does not support abort, return an error 1473 return kSCSIServiceResponse_FUNCTION_REJECTED; 1474 1475} 1476 1477 1478//-------------------------------------------------------------------------------------------------- 1479// IsProtocolServiceSupported [PROTECTED] 1480//-------------------------------------------------------------------------------------------------- 1481 1482bool 1483IOUSBMassStorageClass::IsProtocolServiceSupported ( 1484 SCSIProtocolFeature feature, 1485 void * serviceValue ) 1486{ 1487 1488 bool isSupported = false; 1489 OSDictionary * characterDict = NULL; 1490 IOUSBInterface * interfaceRef = NULL; 1491 IOUSBDevice * deviceRef = NULL; 1492 UInt8 deviceSpeed = 0; 1493 1494 // Check to see if we're super speed USB 3.0 device. If we are we can increase the size of the 1495 // maximum I/O size to something more befitting of a "super" speed bus. 1496 interfaceRef = GetInterfaceReference ( ); 1497 if ( interfaceRef != NULL ) 1498 { 1499 1500 deviceRef = interfaceRef->GetDevice ( ); 1501 if ( deviceRef != NULL ) 1502 { 1503 deviceSpeed = deviceRef->GetSpeed ( ); 1504 } 1505 1506 } 1507 1508 STATUS_LOG ( ( 6, "%s[%p]::IsProtocolServiceSupported called for feature=%d", getName ( ), this, feature ) ); 1509 1510 characterDict = OSDynamicCast ( OSDictionary, ( getProperty ( kIOPropertySCSIDeviceCharacteristicsKey ) ) ); 1511 1512 switch ( feature ) 1513 { 1514 1515 case kSCSIProtocolFeature_GetMaximumLogicalUnitNumber: 1516 { 1517 1518 * ( ( UInt32 * ) serviceValue ) = GetMaxLogicalUnitNumber ( ); 1519 isSupported = true; 1520 1521 } 1522 break; 1523 1524 // We must state our maximum byte counts, because the default values chosen by the 1525 // storage stack are too large for most USB devices. 1526 1527 case kSCSIProtocolFeature_MaximumReadTransferByteCount: 1528 { 1529 1530 UInt32 maxByteCount = kDefaultMaximumByteCountWrite; 1531 1532#ifndef EMBEDDED 1533 // For super speed ( or faster ) devices we permit a larger I/O size. 1534 if ( deviceSpeed >= kUSBDeviceSpeedSuper ) 1535 { 1536 maxByteCount = kDefaultMaximumByteCountReadUSB3; 1537 } 1538#endif // EMBEDDED 1539 1540 if ( characterDict != NULL ) 1541 { 1542 1543 OSNumber * number = OSDynamicCast ( OSNumber, characterDict->getObject ( kIOMaximumByteCountReadKey ) ); 1544 if ( number != NULL) 1545 { 1546 1547 maxByteCount = number->unsigned32BitValue ( ); 1548 1549 } 1550 1551 } 1552 1553 *( ( UInt32 * ) serviceValue ) = maxByteCount; 1554 isSupported = true; 1555 1556 } 1557 break; 1558 1559 case kSCSIProtocolFeature_MaximumWriteTransferByteCount: 1560 { 1561 1562 UInt32 maxByteCount = kDefaultMaximumByteCountWrite; 1563 1564#ifndef EMBEDDED 1565 // For super speed ( or faster ) devices we permit a larger I/O size. 1566 if ( deviceSpeed >= kUSBDeviceSpeedSuper ) 1567 { 1568 maxByteCount = kDefaultMaximumByteCountWriteUSB3; 1569 } 1570#endif // EMBEDDED 1571 1572 if ( characterDict != NULL ) 1573 { 1574 1575 OSNumber * number = OSDynamicCast ( OSNumber, characterDict->getObject ( kIOMaximumByteCountWriteKey ) ); 1576 if ( number != NULL) 1577 { 1578 1579 maxByteCount = number->unsigned32BitValue ( ); 1580 1581 } 1582 1583 } 1584 1585 *( ( UInt32 * ) serviceValue ) = maxByteCount; 1586 isSupported = true; 1587 1588 } 1589 break; 1590 1591 // We only state our maximum block counts if they are specified in the Device Characteristics dictionary. 1592 // Otherwise, we let the storage stack calculate the block counts from our byte counts. 1593 1594 case kSCSIProtocolFeature_MaximumReadBlockTransferCount: 1595 { 1596 1597 OSNumber * number = NULL; 1598 1599 require_quiet ( characterDict, Exit ); 1600 1601 number = OSDynamicCast ( OSNumber, characterDict->getObject ( kIOMaximumBlockCountReadKey ) ); 1602 require_quiet ( number, Exit ); 1603 1604 *( ( UInt32 * ) serviceValue ) = number->unsigned32BitValue ( ); 1605 isSupported = true; 1606 1607 } 1608 break; 1609 1610 case kSCSIProtocolFeature_MaximumWriteBlockTransferCount: 1611 { 1612 1613 OSNumber * number = NULL; 1614 1615 require_quiet ( characterDict, Exit ); 1616 1617 number = OSDynamicCast ( OSNumber, characterDict->getObject ( kIOMaximumBlockCountWriteKey ) ); 1618 require_quiet ( number, Exit ); 1619 1620 *( ( UInt32 * ) serviceValue ) = number->unsigned32BitValue ( ); 1621 isSupported = true; 1622 1623 } 1624 break; 1625 1626#ifndef EMBEDDED 1627 case kSCSIProtocolFeature_ProtocolSpecificPowerControl: 1628 { 1629 1630 if ( fPortSuspendResumeForPMEnabled == true ) 1631 { 1632 1633 STATUS_LOG ( ( 6, "%s[%p]::IsProtocolServiceSupported - fPortSuspendResumeForPMEnabled enabled", getName ( ), this ) ); 1634 isSupported = true; 1635 1636 } 1637 1638 if ( characterDict != NULL ) 1639 { 1640 1641 if ( characterDict->getObject ( kIOPropertyAutonomousSpinDownKey ) != NULL ) 1642 { 1643 1644 STATUS_LOG ( ( 6, "%s[%p]::IsProtocolServiceSupported - fAutonomousSpinDownWorkAround enabled", getName ( ), this ) ); 1645 1646 fAutonomousSpinDownWorkAround = true; 1647 isSupported = true; 1648 1649 } 1650 1651 } 1652 1653 } 1654 break; 1655#endif // EMBEDDED 1656 1657 default: 1658 break; 1659 1660 } 1661 1662 1663Exit: 1664 1665 1666 return isSupported; 1667 1668} 1669 1670 1671//-------------------------------------------------------------------------------------------------- 1672// HandleProtocolServiceFeature [PROTECTED] 1673//-------------------------------------------------------------------------------------------------- 1674 1675bool 1676IOUSBMassStorageClass::HandleProtocolServiceFeature ( 1677 SCSIProtocolFeature feature, 1678 void * serviceValue ) 1679{ 1680 1681 bool isSupported = false; 1682 1683 1684 STATUS_LOG ( ( 6, "%s[%p]::HandleProtocolServiceFeature called, feature=%lu", getName(), this, ( UInt32 ) feature ) ); 1685 1686 1687 switch ( feature ) 1688 { 1689 1690 case kSCSIProtocolFeature_ProtocolSpecificPowerControl: 1691 { 1692 1693 IOReturn status = kIOReturnError; 1694 UInt32 value = * ( UInt32 * ) serviceValue; 1695 1696 1697 // By having indicated support for this feature, the IOSAM layer calls this method during power 1698 // transitions, to allow us to perform any protocol-specific power handling in place of its 1699 // default power handling (e.g. - issue a START_STOP_UNIT command). 1700 1701 if ( fPortSuspendResumeForPMEnabled == true ) 1702 { 1703 1704 // This flag indicates that we should suspend the device when powering off, 1705 // and resume it when powering up. 1706 1707 if ( value == kSCSIProtocolPowerStateOff ) 1708 { 1709 1710 STATUS_LOG ( ( 6, "%s[%p]::HandleProtocolServiceFeature suspend port", getName(), this ) ); 1711 1712 // Suspend the port. 1713 status = SuspendPort ( true ); 1714 require ( ( status == kIOReturnSuccess ), Exit ); 1715 1716 } 1717 1718 if ( value == kSCSIProtocolPowerStateOn ) 1719 { 1720 1721 STATUS_LOG ( ( 6, "%s[%p]::HandleProtocolServiceFeature resume port", getName(), this ) ); 1722 1723 // Resume the port. 1724 status = SuspendPort ( false ); 1725 require ( ( status == kIOReturnSuccess ), Exit ); 1726 1727 } 1728 1729 isSupported = true; 1730 1731 } 1732 1733#ifndef EMBEDDED 1734 else if ( fAutonomousSpinDownWorkAround == true ) 1735 { 1736 1737 STATUS_LOG ( ( 6, "%s[%p]::HandleProtocolServiceFeature NOP START_STOP", getName(), this ) ); 1738 1739 // This a workaround for devices which spin themselves up/down and can't 1740 // properly handle START_STOP commands from the host when the drive is 1741 // already in the requested state. We need do nothing here - we've already 1742 // prevented IOSAM from issuing the START_STOP command. 1743 1744 isSupported = true; 1745 1746 } 1747#endif // EMBEDDED 1748 1749 } 1750 break; 1751 1752 // Default to super class. 1753 default: 1754 { 1755 1756 // Not a supported feature of this protocol. 1757 STATUS_LOG ( ( 6, "%s[%p]::HandleProtocolServiceFeature called for a feature we do not support", getName(), this ) ); 1758 1759 } 1760 break; 1761 1762 } 1763 1764 1765Exit: 1766 1767 return isSupported; 1768 1769} 1770 1771 1772#pragma mark - 1773#pragma mark *** Standard USB Command Methods *** 1774#pragma mark - 1775 1776 1777//-------------------------------------------------------------------------------------------------- 1778// ClearFeatureEndpointStall - Method to do the CLEAR_FEATURE command for 1779// an ENDPOINT_STALL feature. 1780// [PROTECTED] 1781//-------------------------------------------------------------------------------------------------- 1782 1783IOReturn 1784IOUSBMassStorageClass::ClearFeatureEndpointStall ( 1785 IOUSBPipe * thePipe, 1786 IOUSBCompletion * completion ) 1787{ 1788 1789 IOReturn status = kIOReturnInternalError; 1790 thread_t thread = NULL; 1791 1792 STATUS_LOG((5, "%s[%p]: ClearFeatureEndpointStall Entered with thePipe=%p", getName(), this, thePipe )); 1793 1794 if ( ( fTerminating == true ) || 1795 ( thePipe == NULL ) ) 1796 { 1797 // We're terminating, the device has probably been removed. 1798 // Nothing else to do except to report an error. 1799 status = kIOReturnDeviceError; 1800 goto Exit; 1801 } 1802 1803 // Use the fPotentiallyStalledPipe iVar to pass the stalled pipe to the spawned thread. 1804 fPotentiallyStalledPipe = thePipe; 1805 1806 // Verify the assumptions that the helper thread will make when finding the completion structure. 1807 if ( GetInterfaceProtocol() == kProtocolBulkOnly ) 1808 { 1809 require ( completion == &GetBulkOnlyRequestBlock()->boCompletion, Exit ); 1810 } 1811 1812 else 1813 { 1814 require ( completion == &GetCBIRequestBlock()->cbiCompletion, Exit ); 1815 } 1816 1817 // Increment the retain count here, in order to keep our object around while the spawned thread executes. 1818 // This retain will be balanced by a release in the spawned thread when it exits. 1819 retain(); 1820 1821 // Spawn a helper thread to actually clear the pipe stall, because some methods 1822 // may not be called from the USB completion thread. 1823 status = kernel_thread_start ( 1824 OSMemberFunctionCast ( thread_continue_t, this, &IOUSBMassStorageClass::ClearPipeStall ), 1825 this, 1826 &thread ); 1827 if ( status != kIOReturnSuccess ) 1828 { 1829 1830 // The thread won't run, so restore the state that it was supposed to do. 1831 release(); 1832 1833 } 1834 1835Exit: 1836 1837 STATUS_LOG ( ( 5, "%s[%p]: ClearFeatureEndpointStall returning status=0x%x thread=%p", getName(), this, status, thread ) ); 1838 1839 return status; 1840 1841} 1842 1843 1844//-------------------------------------------------------------------------------------------------- 1845// GetStatusEndpointStatus - Method to do the GET_STATUS command for the 1846// endpoint that the IOUSBPipe is connected to. 1847// [PROTECTED] 1848//-------------------------------------------------------------------------------------------------- 1849 1850IOReturn 1851IOUSBMassStorageClass::GetStatusEndpointStatus ( 1852 IOUSBPipe * thePipe, 1853 void * endpointStatus, 1854 IOUSBCompletion * completion ) 1855{ 1856 1857 IOReturn status; 1858 1859 if ( ( fTerminating == true ) || 1860 ( thePipe == NULL ) ) 1861 { 1862 // We're terminating, the device has probably been removed. 1863 // Nothing else to do except to report an error. 1864 return kIOReturnDeviceError; 1865 } 1866 1867 // Clear out the structure for the request 1868 bzero( &fUSBDeviceRequest, sizeof ( IOUSBDevRequest ) ); 1869 1870 // Build the USB command 1871 fUSBDeviceRequest.bmRequestType = USBmakebmRequestType ( kUSBIn, kUSBStandard, kUSBEndpoint ); 1872 fUSBDeviceRequest.bRequest = kUSBRqGetStatus; 1873 fUSBDeviceRequest.wValue = 0; // Zero is EndpointStall 1874 fUSBDeviceRequest.wIndex = thePipe->GetEndpointNumber(); 1875 1876 if ( thePipe == GetBulkInPipe() ) 1877 { 1878 fUSBDeviceRequest.wIndex |= 0x80; 1879 } 1880 1881 fUSBDeviceRequest.wLength = 2; 1882 fUSBDeviceRequest.pData = endpointStatus; 1883 1884 // Send the command over the control endpoint 1885 status = GetInterfaceReference()->DeviceRequest ( &fUSBDeviceRequest, completion ); 1886 STATUS_LOG ( ( 5, "%s[%p]: GetStatusEndpointStatus returned %x", getName(), this, status ) ); 1887 1888 RecordUSBTimeStamp ( UMC_TRACE ( kGetEndPointStatus ), 1889 ( uintptr_t ) this, status, 1890 thePipe->GetEndpointNumber(), NULL ); 1891 1892 return status; 1893 1894} 1895 1896#pragma mark - 1897#pragma mark *** Accessor Methods For All Protocol Variables *** 1898#pragma mark - 1899 1900 1901/* The following methods are for use only by this class */ 1902 1903 1904//-------------------------------------------------------------------------------------------------- 1905// GetInterfaceReference - Method to do the GET_STATUS command for the 1906// endpoint that the IOUSBPipe is connected to. 1907// [PROTECTED] 1908//-------------------------------------------------------------------------------------------------- 1909 1910IOUSBInterface * 1911IOUSBMassStorageClass::GetInterfaceReference ( void ) 1912{ 1913 1914 if ( fInterface == NULL ) 1915 { 1916 STATUS_LOG ( ( 2, "%s[%p]: GetInterfaceReference - Interface is NULL.", getName(), this ) ); 1917 } 1918 1919 return fInterface; 1920 1921} 1922 1923 1924//-------------------------------------------------------------------------------------------------- 1925// SetInterfaceReference [PROTECTED] 1926//-------------------------------------------------------------------------------------------------- 1927 1928void 1929IOUSBMassStorageClass::SetInterfaceReference ( IOUSBInterface * newInterface ) 1930{ 1931 fInterface = newInterface; 1932} 1933 1934 1935//-------------------------------------------------------------------------------------------------- 1936// GetInterfaceSubClass [PROTECTED] 1937//-------------------------------------------------------------------------------------------------- 1938 1939UInt8 1940IOUSBMassStorageClass::GetInterfaceSubclass ( void ) 1941{ 1942 return fPreferredSubclass; 1943} 1944 1945 1946//-------------------------------------------------------------------------------------------------- 1947// GetInterfaceProtocol [PROTECTED] 1948//-------------------------------------------------------------------------------------------------- 1949 1950UInt8 1951IOUSBMassStorageClass::GetInterfaceProtocol ( void ) 1952{ 1953 return fPreferredProtocol; 1954} 1955 1956 1957//-------------------------------------------------------------------------------------------------- 1958// GetControlPipe [PROTECTED] 1959//-------------------------------------------------------------------------------------------------- 1960 1961IOUSBPipe * 1962IOUSBMassStorageClass::GetControlPipe ( void ) 1963{ 1964 1965 if ( fTerminating == true ) 1966 { 1967 return NULL; 1968 } 1969 1970 return GetInterfaceReference()->GetDevice()->GetPipeZero(); 1971 1972} 1973 1974 1975//-------------------------------------------------------------------------------------------------- 1976// GetBulkInPipe [PROTECTED] 1977//-------------------------------------------------------------------------------------------------- 1978 1979IOUSBPipe * 1980IOUSBMassStorageClass::GetBulkInPipe ( void ) 1981{ 1982 return fBulkInPipe; 1983} 1984 1985 1986//-------------------------------------------------------------------------------------------------- 1987// GetBulkOutPipe [PROTECTED] 1988//-------------------------------------------------------------------------------------------------- 1989 1990IOUSBPipe * 1991IOUSBMassStorageClass::GetBulkOutPipe ( void ) 1992{ 1993 return fBulkOutPipe; 1994} 1995 1996 1997//-------------------------------------------------------------------------------------------------- 1998// GetInterruptPipe [PROTECTED] 1999//-------------------------------------------------------------------------------------------------- 2000 2001IOUSBPipe * 2002IOUSBMassStorageClass::GetInterruptPipe ( void ) 2003{ 2004 return fInterruptPipe; 2005} 2006 2007 2008//-------------------------------------------------------------------------------------------------- 2009// GetMaxLogicalUnitNumber [PROTECTED] 2010//-------------------------------------------------------------------------------------------------- 2011 2012UInt8 2013IOUSBMassStorageClass::GetMaxLogicalUnitNumber ( void ) const 2014{ 2015 return fMaxLogicalUnitNumber; 2016} 2017 2018 2019//-------------------------------------------------------------------------------------------------- 2020// SetMaxLogicalUnitNumber [PROTECTED] 2021//-------------------------------------------------------------------------------------------------- 2022 2023void 2024IOUSBMassStorageClass::SetMaxLogicalUnitNumber ( UInt8 maxLUN ) 2025{ 2026 fMaxLogicalUnitNumber = maxLUN; 2027} 2028 2029 2030#pragma mark - 2031#pragma mark *** Accessor Methods For CBI Protocol Variables *** 2032#pragma mark - 2033 2034//-------------------------------------------------------------------------------------------------- 2035// GetCBIRequestBlock [PROTECTED] 2036//-------------------------------------------------------------------------------------------------- 2037 2038CBIRequestBlock * 2039IOUSBMassStorageClass::GetCBIRequestBlock ( void ) 2040{ 2041 2042 // Return a pointer to the CBIRequestBlock 2043 return &fCBICommandRequestBlock; 2044 2045} 2046 2047 2048//-------------------------------------------------------------------------------------------------- 2049// ReleaseCBIRequestBlock [PROTECTED] 2050//-------------------------------------------------------------------------------------------------- 2051 2052void 2053IOUSBMassStorageClass::ReleaseCBIRequestBlock ( CBIRequestBlock * cbiRequestBlock ) 2054{ 2055 2056 // Clear the request and completion to avoid possible double callbacks. 2057 cbiRequestBlock->request = NULL; 2058 2059 // Since we only allow one command and the CBIRequestBlock is 2060 // a member variable, no need to do anything. 2061 return; 2062 2063} 2064 2065#pragma mark - 2066#pragma mark *** Accessor Methods For Bulk Only Protocol Variables *** 2067#pragma mark - 2068 2069 2070//-------------------------------------------------------------------------------------------------- 2071// GetBulkOnlyRequestBlock [PROTECTED] 2072//-------------------------------------------------------------------------------------------------- 2073 2074BulkOnlyRequestBlock * 2075IOUSBMassStorageClass::GetBulkOnlyRequestBlock ( void ) 2076{ 2077 2078 // Return a pointer to the BulkOnlyRequestBlock 2079 return &fBulkOnlyCommandRequestBlock; 2080 2081} 2082 2083 2084//-------------------------------------------------------------------------------------------------- 2085// ReleaseBulkOnlyRequestBlock [PROTECTED] 2086//-------------------------------------------------------------------------------------------------- 2087 2088void 2089IOUSBMassStorageClass::ReleaseBulkOnlyRequestBlock ( BulkOnlyRequestBlock * boRequestBlock ) 2090{ 2091 2092 // Clear the request and completion to avoid possible double callbacks. 2093 boRequestBlock->request = NULL; 2094 2095 // Since we only allow one command and the BulkOnlyRequestBlock is 2096 // a member variable, no need to do anything. 2097 return; 2098 2099} 2100 2101 2102//-------------------------------------------------------------------------------------------------- 2103// GetNextBulkOnlyCommandTag [PROTECTED] 2104//-------------------------------------------------------------------------------------------------- 2105 2106UInt32 2107IOUSBMassStorageClass::GetNextBulkOnlyCommandTag ( void ) 2108{ 2109 2110 fBulkOnlyCommandTag++; 2111 2112 return fBulkOnlyCommandTag; 2113 2114} 2115 2116#pragma mark - 2117#pragma mark *** Miscellaneous Methods *** 2118#pragma mark - 2119 2120 2121//-------------------------------------------------------------------------------------------------- 2122// AcceptSCSITask [PRIVATE] 2123//-------------------------------------------------------------------------------------------------- 2124 2125IOReturn 2126IOUSBMassStorageClass::AcceptSCSITask ( SCSITaskIdentifier request, bool * accepted ) 2127{ 2128 2129 *accepted = false; 2130 2131 if ( GetInterfaceProtocol ( ) == kProtocolBulkOnly ) 2132 { 2133 2134 if ( fBulkOnlyCommandStructInUse == true ) 2135 { 2136 2137 RecordUSBTimeStamp ( UMC_TRACE ( kBOCommandAlreadyInProgress ), 2138 ( uintptr_t ) this, ( uintptr_t ) request, NULL, NULL ); 2139 goto Exit; 2140 2141 } 2142 2143 fBulkOnlyCommandStructInUse = true; 2144 2145 } 2146 2147 else 2148 { 2149 2150 if ( fCBICommandStructInUse == true ) 2151 { 2152 2153 RecordUSBTimeStamp ( UMC_TRACE ( kCBICommandAlreadyInProgress ), 2154 ( uintptr_t ) this, ( uintptr_t ) request, NULL, NULL ); 2155 2156 goto Exit; 2157 2158 } 2159 2160 fCBICommandStructInUse = true; 2161 2162 } 2163 2164 *accepted = true; 2165 2166 2167Exit: 2168 2169 2170 return kIOReturnSuccess; 2171 2172} 2173 2174 2175//-------------------------------------------------------------------------------------------------- 2176// CheckDeferredTermination [PRIVATE] 2177//-------------------------------------------------------------------------------------------------- 2178 2179void 2180IOUSBMassStorageClass::CheckDeferredTermination ( void ) 2181{ 2182 2183 require ( fWorkLoop->inGate ( ) == true, Exit ); 2184 2185 if ( fTerminationDeferred == true ) 2186 { 2187 2188 fTerminationDeferred = false; 2189 2190 STATUS_LOG ( ( 6, "%s[%p]: CheckDeferredTermination: Waking didTerminate thread", getName(), this ) ); 2191 2192 fCommandGate->commandWakeup ( &fTerminationDeferred, false ); 2193 2194 } 2195 2196 2197Exit: 2198 2199 2200 return; 2201 2202} 2203 2204 2205//-------------------------------------------------------------------------------------------------- 2206// GatedCompleteSCSICommand [PRIVATE] 2207//-------------------------------------------------------------------------------------------------- 2208 2209void 2210IOUSBMassStorageClass::GatedCompleteSCSICommand ( 2211 SCSITaskIdentifier request, 2212 SCSIServiceResponse * serviceResponse, 2213 SCSITaskStatus * taskStatus ) 2214{ 2215 2216 require ( request != NULL, Exit ); 2217 require ( serviceResponse != NULL, Exit ); 2218 require ( taskStatus != NULL, Exit ); 2219 2220 fBulkOnlyCommandStructInUse = false; 2221 fCBICommandStructInUse = false; 2222 2223 // Clear the count of consecutive I/Os which required a USB Device Reset. 2224 fConsecutiveResetCount = 0; 2225 2226 STATUS_LOG ( ( 4, "%s[%p]: GatedCompleteSCSICommand request=%p serviceResponse=%d taskStatus=0x%02x", getName(), this, request, *serviceResponse, *taskStatus ) ); 2227 2228 RecordUSBTimeStamp ( UMC_TRACE ( kCompleteSCSICommand ), 2229 ( uintptr_t ) this, ( uintptr_t ) request, 2230 *serviceResponse, *taskStatus ); 2231 2232 CommandCompleted ( request, *serviceResponse, *taskStatus ); 2233 2234 // If didTerminate() was called while this SCSI task was outstanding, then termination would 2235 // have been deferred until it completed. Check for that now, while behind the command gate. 2236 CheckDeferredTermination ( ); 2237 2238 2239Exit: 2240 2241 2242 return; 2243 2244} 2245 2246 2247//-------------------------------------------------------------------------------------------------- 2248// HandlePowerOn - Will get called when a device has been resumed [PUBLIC] 2249//-------------------------------------------------------------------------------------------------- 2250 2251IOReturn 2252IOUSBMassStorageClass::HandlePowerOn ( void ) 2253{ 2254 2255 UInt8 eStatus[2]; 2256 2257 // The USB hub port that the device is connected to has been resumed, 2258 // check to see if the device is still responding correctly and if not, 2259 // fix it so that it is. 2260 STATUS_LOG(( 6, "%s[%p]: HandlePowerOn", getName(), this )); 2261 2262#ifndef EMBEDDED 2263 if ( ( GetStatusEndpointStatus ( GetBulkInPipe(), &eStatus[0], NULL ) != kIOReturnSuccess ) || 2264 ( fRequiresResetOnResume == true ) ) 2265 { 2266 2267 RecordUSBTimeStamp ( UMC_TRACE ( kHandlePowerOnUSBReset ), ( uintptr_t ) this, NULL, NULL, NULL ); 2268 2269 ResetDeviceNow ( true ); 2270 2271 } 2272#else 2273 ResetDeviceNow( true ); 2274#endif 2275 2276 // If our port was suspended before sleep, it would have been resumed as part 2277 // of the global resume on system wake. 2278 fPortIsSuspended = false; 2279 2280 return kIOReturnSuccess; 2281 2282} 2283 2284 2285//-------------------------------------------------------------------------------------------------- 2286// handleOpen [PUBLIC] 2287//-------------------------------------------------------------------------------------------------- 2288 2289bool 2290IOUSBMassStorageClass::handleOpen ( IOService * client, 2291 IOOptionBits options, 2292 void * arg ) 2293{ 2294 2295 bool result = false; 2296 2297 2298 // If this is a normal open on a single LUN device. 2299 if ( GetMaxLogicalUnitNumber() == 0 ) 2300 { 2301 2302 result = super::handleOpen ( client, options, arg ); 2303 goto Exit; 2304 2305 } 2306 2307 // It's an open from a multi-LUN client 2308 require_nonzero ( fClients, ErrorExit ); 2309 require_nonzero ( OSDynamicCast ( IOSCSILogicalUnitNub, client ), ErrorExit ); 2310 result = fClients->setObject ( client ); 2311 2312 2313Exit: 2314ErrorExit: 2315 2316 2317 return result; 2318 2319} 2320 2321 2322//-------------------------------------------------------------------------------------------------- 2323// handleClose [PUBLIC] 2324//-------------------------------------------------------------------------------------------------- 2325 2326void 2327IOUSBMassStorageClass::handleClose ( IOService * client, 2328 IOOptionBits options ) 2329{ 2330 2331 if ( GetMaxLogicalUnitNumber() == 0 ) 2332 { 2333 super::handleClose ( client, options ); 2334 return; 2335 } 2336 2337 require_nonzero ( fClients, Exit ); 2338 2339 if ( fClients->containsObject ( client ) ) 2340 { 2341 fClients->removeObject( client ); 2342 2343 if ( ( fClients->getCount() == 0 ) && isInactive() ) 2344 { 2345 message ( kIOMessageServiceIsRequestingClose, getProvider(), 0 ); 2346 } 2347 } 2348 2349 2350Exit: 2351 2352 2353 return; 2354 2355} 2356 2357 2358//-------------------------------------------------------------------------------------------------- 2359// handleIsOpen [PUBLIC] 2360//-------------------------------------------------------------------------------------------------- 2361 2362bool 2363IOUSBMassStorageClass::handleIsOpen ( const IOService * client ) const 2364{ 2365 2366 bool result = false; 2367 UInt8 lun = GetMaxLogicalUnitNumber(); 2368 2369 require_nonzero ( lun, CallSuperClass ); 2370 require_nonzero ( fClients, CallSuperClass ); 2371 2372 // General case (is anybody open) 2373 if ( ( client == NULL ) && ( fClients->getCount ( ) != 0 ) ) 2374 { 2375 result = true; 2376 } 2377 2378 else 2379 { 2380 // specific case (is this client open) 2381 result = fClients->containsObject ( client ); 2382 } 2383 2384 return result; 2385 2386 2387CallSuperClass: 2388 2389 2390 result = super::handleIsOpen ( client ); 2391 return result; 2392 2393} 2394 2395 2396//-------------------------------------------------------------------------------------------------- 2397// sWaitForReset [STATIC][PROTECTED] 2398//-------------------------------------------------------------------------------------------------- 2399 2400IOReturn 2401IOUSBMassStorageClass::sWaitForReset ( void * refcon ) 2402{ 2403 2404 return ( ( IOUSBMassStorageClass * ) refcon )->GatedWaitForReset(); 2405 2406} 2407 2408 2409//-------------------------------------------------------------------------------------------------- 2410// GatedWaitForReset [PROTECTED] 2411//-------------------------------------------------------------------------------------------------- 2412 2413IOReturn 2414IOUSBMassStorageClass::GatedWaitForReset ( void ) 2415{ 2416 2417 IOReturn status = kIOReturnSuccess; 2418 2419 while ( fResetInProgress == true ) 2420 { 2421 status = fCommandGate->commandSleep ( &fResetInProgress, THREAD_UNINT ); 2422 } 2423 2424 return status; 2425 2426} 2427 2428 2429#ifndef EMBEDDED 2430//-------------------------------------------------------------------------------------------------- 2431// sWaitForTaskAbort [STATIC][PROTECTED] 2432//-------------------------------------------------------------------------------------------------- 2433 2434IOReturn 2435IOUSBMassStorageClass::sWaitForTaskAbort ( void * refcon ) 2436{ 2437 return kIOReturnUnsupported; 2438} 2439 2440 2441//-------------------------------------------------------------------------------------------------- 2442// GatedWaitForTaskAbort [PROTECTED] 2443//-------------------------------------------------------------------------------------------------- 2444 2445IOReturn 2446IOUSBMassStorageClass::GatedWaitForTaskAbort ( void ) 2447{ 2448 return kIOReturnUnsupported; 2449} 2450#endif // EMBEDDED 2451 2452 2453//-------------------------------------------------------------------------------------------------- 2454// sResetDevice [STATIC][PROTECTED] 2455//-------------------------------------------------------------------------------------------------- 2456 2457void 2458IOUSBMassStorageClass::sResetDevice ( void * refcon ) 2459{ 2460 2461 IOUSBMassStorageClass * driver = NULL; 2462 IOUSBInterface * interfaceRef = NULL; 2463 IOUSBDevice * deviceRef = NULL; 2464 IOReturn status = kIOReturnError; 2465 thread_t thread = THREAD_NULL; 2466 UInt32 deviceInfo = 0; 2467 2468 driver = ( IOUSBMassStorageClass * ) refcon; 2469 require ( ( driver != NULL ), Exit ); 2470 2471 STATUS_LOG ( ( 4, "%s[%p]: sResetDevice Entered", driver->getName ( ), driver ) ); 2472 2473 // Check if we should bail out because we are 2474 // being terminated. 2475 if ( ( driver->fTerminating == true ) || 2476 ( driver->isInactive ( ) == true ) ) 2477 { 2478 2479 STATUS_LOG ( ( 2, "%s[%p]: sResetDevice - We are being terminated!", driver->getName ( ), driver ) ); 2480 RecordUSBTimeStamp ( UMC_TRACE ( kUSBDeviceResetWhileTerminating ), ( uintptr_t ) driver, 2481 ( unsigned int ) driver->fTerminating, ( unsigned int ) driver->isInactive ( ), NULL ); 2482 2483 goto ErrorExit; 2484 2485 } 2486 2487 interfaceRef = driver->GetInterfaceReference ( ); 2488 require ( ( interfaceRef != NULL ), ErrorExit ); 2489 2490 deviceRef = interfaceRef->GetDevice ( ); 2491 require ( ( deviceRef != NULL ), ErrorExit ); 2492 2493 // Check that we are still connected to the hub and that our port is enabled. 2494 status = deviceRef->GetDeviceInformation ( &deviceInfo ); 2495 STATUS_LOG ( ( 5, "%s[%p]: GetDeviceInfo returned status = %x deviceInfo = %x", driver->getName ( ), driver, status, deviceInfo ) ); 2496 RecordUSBTimeStamp ( UMC_TRACE ( kDeviceInformation ), ( uintptr_t ) driver, status, deviceInfo, NULL ); 2497 require_noerr ( status, ErrorExit ); 2498 2499 // If GetDeviceInformation ( ) failed, or if the device is no longer connected, or if the device 2500 // has been disabled by the IOUSBFamily, don't reset it. 2501 if ( ( ( deviceInfo & kUSBInformationDeviceIsConnectedMask ) == 0 ) || 2502 ( ( ( deviceInfo & kUSBInformationDeviceIsEnabledMask ) == 0 ) && ( ( deviceInfo & kUSBInformationDeviceIsInternalMask ) == 0 ) ) ) 2503 { 2504 2505 status = kIOReturnNoDevice; 2506 RecordUSBTimeStamp ( UMC_TRACE ( kUSBDeviceResetAfterDisconnect ), ( uintptr_t ) driver, NULL, NULL, NULL ); 2507 goto ErrorExit; 2508 2509 } 2510 2511 // Make sure our port isn't suspended, it shouldn't be, but just in case. 2512 // If the port is active this will be a NOP. 2513 if ( deviceInfo & kUSBInformationDeviceIsSuspendedMask ) 2514 { 2515 driver->SuspendPort ( false ); 2516 } 2517 2518 // Device is still attached. Lets try resetting it. 2519 status = deviceRef->ResetDevice(); 2520 STATUS_LOG ( ( 5, "%s[%p]: ResetDevice() returned = %x", driver->getName ( ), driver, status ) ); 2521 RecordUSBTimeStamp ( UMC_TRACE ( kUSBDeviceResetReturned ), ( uintptr_t ) driver, status, NULL, NULL ); 2522 require ( ( status == kIOReturnSuccess ), ErrorExit ); 2523 2524 // We successfully reset the device. Now we have to wait for the fWaitingForReconfigurationMessage 2525 // message in order for the reset process to be considered complete. If we resume activity prior 2526 // to receive the message our I/O may resume before the SET_CONFIGURATION following device reset 2527 // makes it to our device. 2528 driver->fWaitingForReconfigurationMessage = true; 2529 2530 // Reset host side data toggles. 2531 if ( driver->fBulkInPipe != NULL ) 2532 { 2533 driver->fBulkInPipe->ClearPipeStall ( false ); 2534 } 2535 2536 if ( driver->fBulkOutPipe != NULL ) 2537 { 2538 driver->fBulkOutPipe->ClearPipeStall ( false ); 2539 } 2540 2541 if ( driver->fInterruptPipe != NULL ) 2542 { 2543 driver->fInterruptPipe->ClearPipeStall ( false ); 2544 } 2545 2546 2547ErrorExit: 2548 2549 2550 STATUS_LOG ( ( 2, "%s[%p]: sResetDevice status=0x%x fResetInProgress=%d", driver->getName ( ), driver, status, driver->fResetInProgress ) ); 2551 2552 if ( status != kIOReturnSuccess ) 2553 { 2554 2555 // We set the device state to detached so the proper status for the 2556 // device is returned along with the aborted SCSITask. 2557 driver->fDeviceAttached = false; 2558 2559 // Let the clients know that the device is gone. 2560 driver->SendNotification_DeviceRemoved ( ); 2561 2562 } 2563 2564 else 2565 { 2566 2567 UInt16 timeout = 0; 2568 2569 while ( ( timeout < kIOUSBMassStorageReconfigurationTimeoutMS ) && 2570 ( driver->fWaitingForReconfigurationMessage == true ) ) 2571 { 2572 2573 // Hang out for a ms. 2574 IOSleep ( 1 ); 2575 2576 // Increment our timeout counter. 2577 timeout++; 2578 2579 } 2580 2581 // Do we have a device which requires some to collect itself following a USB device reset? 2582 // We only do this if the device successfully reconfigured. 2583 if ( ( driver->fPostDeviceResetCoolDownInterval != 0 ) && 2584 ( driver->fWaitingForReconfigurationMessage == false ) ) 2585 { 2586 2587 // We do. Wait the prescribed amount of time. 2588 IOSleep ( driver->fPostDeviceResetCoolDownInterval ); 2589 2590 } 2591 2592 } 2593 2594 // We complete the failed I/O with kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE 2595 // and either kSCSITaskStatus_DeliveryFailure or kSCSITaskStatus_DeviceNotPresent, 2596 // as per the fDeviceAttached flag. 2597 driver->AbortCurrentSCSITask ( ); 2598 2599 // If the maximum number of unsuccessful resets has been exceeded, then terminate ourself. 2600 if ( driver->fDeviceAttached == false && ( driver->isInactive() == false ) ) 2601 { 2602 2603 // Leave behind some of evidence that there was a catastorphic failure which guided us to self termination. 2604 IOLog ( "[%p](%u)/(%u) Device not responding\n", driver, driver->fConsecutiveResetCount, kMaxConsecutiveResets ); 2605 2606 if ( driver->GetInterfaceReference() != NULL ) 2607 { 2608 driver->GetInterfaceReference()->setProperty ( "IOUSBMassStorageClass Detached", driver->fConsecutiveResetCount, 8 ); 2609 } 2610 2611 // Terminate. 2612 driver->terminate(); 2613 2614 } 2615 2616 driver->fResetInProgress = false; 2617 2618 if ( driver->fBlockOnResetThread == false ) 2619 { 2620 // Unblock our main thread. 2621 driver->fCommandGate->commandWakeup ( &driver->fResetInProgress, false ); 2622 2623 } 2624 2625 STATUS_LOG ( ( 6, "%s[%p]: sResetDevice exiting.", driver->getName ( ), driver ) ); 2626 2627 // We retained the driver in ResetDeviceNow() when 2628 // we created a thread for sResetDevice(). 2629 driver->release(); 2630 2631 // Terminate the thread. 2632 thread = current_thread ( ); 2633 require ( ( thread != THREAD_NULL ), Exit ); 2634 2635 thread_deallocate ( thread ); 2636 thread_terminate ( thread ); 2637 2638 2639Exit: 2640 2641 2642 return; 2643 2644} 2645 2646 2647#ifndef EMBEDDED 2648//-------------------------------------------------------------------------------------------------- 2649// sAbortCurrentSCSITask [STATIC][PROTECTED] 2650//-------------------------------------------------------------------------------------------------- 2651 2652void 2653IOUSBMassStorageClass::sAbortCurrentSCSITask ( void * refcon ) 2654{ 2655} 2656#endif // EMBEDDED 2657 2658 2659//-------------------------------------------------------------------------------------------------- 2660// ClearPipeStall - Method to recover from a pipe stall. 2661// 2662// This method runs on a helper thread because IOUSBPipe::ClearPipeStall() must 2663// not be called from the USB completion thread. 2664// [PRIVATE] 2665//-------------------------------------------------------------------------------------------------- 2666 2667void 2668IOUSBMassStorageClass::ClearPipeStall( void ) 2669{ 2670 2671 IOReturn status = kIOReturnBadArgument; 2672 IOUSBPipe * pipe; 2673 UInt8 endpointNumber; 2674 IOUSBCompletion * completion; 2675 IOUSBInterface * interfaceRef; 2676 thread_t thread; 2677 2678 STATUS_LOG ( ( 4, "%s[%p]: ClearPipeStall Entered with endpoint %d", getName ( ), this, fPotentiallyStalledPipe ? fPotentiallyStalledPipe->GetEndpointNumber() : -1 ) ); 2679 2680 // The pipe to be cleared is specified by instance variable. 2681 pipe = fPotentiallyStalledPipe; 2682 require ( ( pipe != NULL ), Exit ); 2683 2684 endpointNumber = pipe->GetEndpointNumber(); 2685 if ( pipe->GetDirection() == kUSBIn ) 2686 { 2687 endpointNumber |= 0x80; 2688 } 2689 2690 if ( fTerminating == true ) 2691 { 2692 status = kIOReturnOffline; 2693 goto Exit; 2694 } 2695 2696 // Make sure that the Data Toggles are reset before issuing the CLEAR_FEATURE device request. 2697 // This synchronous method must not be called from the USB completion thread. 2698 status = pipe->ClearPipeStall ( false ); 2699 require_success ( status, Exit ); 2700 2701 // Clear out the structure for the request 2702 bzero ( &fUSBDeviceRequest, sizeof ( IOUSBDevRequest ) ); 2703 2704 // Build the USB command 2705 fUSBDeviceRequest.bmRequestType = USBmakebmRequestType ( kUSBNone, kUSBStandard, kUSBEndpoint ); 2706 fUSBDeviceRequest.bRequest = kUSBRqClearFeature; 2707 fUSBDeviceRequest.wValue = kUSBFeatureEndpointStall; 2708 fUSBDeviceRequest.wIndex = endpointNumber; 2709 2710 // We assume that the relevent IOUSBCompletion block can be determined solely from the interface protocol. 2711 if ( GetInterfaceProtocol() == kProtocolBulkOnly ) 2712 { 2713 completion = &GetBulkOnlyRequestBlock()->boCompletion; 2714 } 2715 2716 else 2717 { 2718 completion = &GetCBIRequestBlock()->cbiCompletion; 2719 } 2720 2721 interfaceRef = GetInterfaceReference(); 2722 require ( interfaceRef != NULL, Exit ); 2723 2724 // Send the command over the control endpoint. Because we specify a completion argument, it executes 2725 // asynchronously, with a callback to the protocol-specific completion method. 2726 status = interfaceRef->DeviceRequest( &fUSBDeviceRequest, completion ); 2727 2728 RecordUSBTimeStamp ( UMC_TRACE ( kClearEndPointStall ), ( uintptr_t ) this, status, 2729 pipe->GetEndpointNumber(), NULL ); 2730 2731Exit: 2732 2733 STATUS_LOG ( ( 5, "%s[%p]: ClearPipeStall Returning with status=0x%x", getName(), this, status ) ); 2734 2735 // Decrement our retain count here, to balance the retain which occurred when our task was spawned. 2736 release(); 2737 2738 // Terminate our helper thread. 2739 thread = current_thread ( ); 2740 thread_deallocate ( thread ); 2741 thread_terminate ( thread ); 2742 2743} 2744 2745 2746#ifndef EMBEDDED 2747OSMetaClassDefineReservedUsed ( IOUSBMassStorageClass, 1 ); 2748 2749//-------------------------------------------------------------------------------------------------- 2750// StartDeviceRecovery - The recovery sequence to restore functionality for 2751// devices that stop responding (like many devices 2752// after a Suspend/Resume). [PROTECTED] 2753//-------------------------------------------------------------------------------------------------- 2754 2755IOReturn 2756IOUSBMassStorageClass::StartDeviceRecovery ( void ) 2757{ 2758 // First check to see if the device is still connected. 2759 UInt8 eStatus[2]; 2760 IOReturn status = kIOReturnError; 2761 2762 // The USB hub port that the device is connected to has been resumed, 2763 // check to see if the device is still responding correctly and if not, 2764 // fix it so that it is. 2765 STATUS_LOG ( ( 5, "%s[%p]: StartDeviceRecovery", getName(), this ) ); 2766 2767 if ( fBulkOnlyCommandStructInUse == true ) 2768 { 2769 // Set up the IOUSBCompletion structure 2770 fBulkOnlyCommandRequestBlock.boCompletion.target = this; 2771 fBulkOnlyCommandRequestBlock.boCompletion.action = &this->DeviceRecoveryCompletionAction; 2772 status = GetStatusEndpointStatus ( GetBulkInPipe(), &eStatus[0], &fBulkOnlyCommandRequestBlock.boCompletion); 2773 } 2774 2775 else if ( fCBICommandStructInUse == true ) 2776 { 2777 // Set up the IOUSBCompletion structure 2778 fCBICommandRequestBlock.cbiCompletion.target = this; 2779 fCBICommandRequestBlock.cbiCompletion.action = &this->DeviceRecoveryCompletionAction; 2780 status = GetStatusEndpointStatus ( GetBulkInPipe(), &eStatus[0], &fCBICommandRequestBlock.cbiCompletion); 2781 } 2782 2783 return status; 2784} 2785 2786OSMetaClassDefineReservedUsed ( IOUSBMassStorageClass, 2 ); 2787 2788 2789//-------------------------------------------------------------------------------------------------- 2790// FinishDeviceRecovery [PROTECTED] 2791//-------------------------------------------------------------------------------------------------- 2792 2793void 2794IOUSBMassStorageClass::FinishDeviceRecovery ( IOReturn status ) 2795{ 2796 ResetDeviceNow( false ); 2797} 2798 2799 2800//-------------------------------------------------------------------------------------------------- 2801// DeviceRecoveryCompletionAction [PROTECTED] 2802//-------------------------------------------------------------------------------------------------- 2803 2804void 2805IOUSBMassStorageClass::DeviceRecoveryCompletionAction ( 2806 void * target, 2807 void * parameter, 2808 IOReturn status, 2809 UInt32 bufferSizeRemaining) 2810{ 2811 2812 UNUSED ( parameter ); 2813 UNUSED ( bufferSizeRemaining ); 2814 2815 IOUSBMassStorageClass * theMSC; 2816 2817 theMSC = ( IOUSBMassStorageClass * ) target; 2818 theMSC->FinishDeviceRecovery ( status ); 2819 2820} 2821#endif // EMBEDDED 2822 2823 2824//-------------------------------------------------------------------------------------------------- 2825// ResetDeviceNow [PROTECTED] 2826//-------------------------------------------------------------------------------------------------- 2827 2828void 2829IOUSBMassStorageClass::ResetDeviceNow ( bool waitForReset ) 2830{ 2831 2832 thread_t thread = THREAD_NULL; 2833 kern_return_t result = KERN_FAILURE; 2834 2835 // Make sure we aren't terminating. 2836 require ( ( fTerminating == false ), Exit ); 2837 require ( ( isInactive ( ) == false ), Exit ); 2838 2839 // We call retain here so that the driver will stick around long enough for 2840 // sResetDevice() to do it's thing in case we are being terminated. The 2841 // retain() is balanced with a release in sResetDevice(). 2842 retain ( ); 2843 2844 STATUS_LOG ( ( 4, "%s[%p]: ResetDeviceNow waitForReset=%d fConsecutiveResetCount=%d", getName(), this, waitForReset, fConsecutiveResetCount ) ); 2845 2846 // Reset the device on its own thread so we don't deadlock. 2847 fResetInProgress = true; 2848 2849 // When peforming a USB device reset, we have two options. We can actively block on the reset thread, 2850 // or we can not block and wait for the IOUSBFamily to send us a message about our device being 2851 // reset. If we're reseting from a callback thread, we can't block, so we have to use the message option. 2852 2853 fBlockOnResetThread = !waitForReset; 2854 2855 result = kernel_thread_start ( ( thread_continue_t ) &IOUSBMassStorageClass::sResetDevice, 2856 this, 2857 &thread ); 2858 require ( ( result == KERN_SUCCESS ), ErrorExit ); 2859 2860 if ( waitForReset == true ) 2861 { 2862 fCommandGate->runAction ( ( IOCommandGate::Action ) &IOUSBMassStorageClass::sWaitForReset ); 2863 } 2864 2865 2866Exit: 2867 2868 2869 // If the reset didnt happen complete the failed command with an error here. 2870 if ( ( result == KERN_FAILURE ) && 2871 ( fBulkOnlyCommandStructInUse | fCBICommandStructInUse ) ) 2872 { 2873 AbortCurrentSCSITask ( ); 2874 } 2875 2876 STATUS_LOG ( ( 4, "%s[%p]: ResetDeviceNow exiting\n", getName(), this ) ); 2877 2878 2879 return; 2880 2881 2882ErrorExit: 2883 2884 2885 fResetInProgress = false; 2886 2887 release ( ); 2888 2889 2890} 2891 2892 2893//-------------------------------------------------------------------------------------------------- 2894// AbortCurrentSCSITask [PROTECTED] 2895// 2896// This method is used to fail an I/O for which its error recovery required either a Bulk Only 2897// Reset or a Device Reset. It has the important side effect of incrementing the 2898// fConsecutiveReset counter which is used to escalate the type of reset, and to terminate 2899// ourself when multiple reset attempts fail to recover the device. 2900//-------------------------------------------------------------------------------------------------- 2901 2902void 2903IOUSBMassStorageClass::AbortCurrentSCSITask ( void ) 2904{ 2905 2906 SCSITaskIdentifier currentTask = NULL; 2907 2908 if ( fWorkLoop->inGate ( ) == false ) 2909 { 2910 2911 fCommandGate->runAction ( 2912 OSMemberFunctionCast ( 2913 IOCommandGate::Action, 2914 this, 2915 &IOUSBMassStorageClass::AbortCurrentSCSITask ) ); 2916 2917 return; 2918 2919 } 2920 2921 // We are holding the workLoop gate. 2922 2923 STATUS_LOG ( ( 4, "%s[%p]: AbortCurrentSCSITask Entered", getName(), this ) ); 2924 2925 if( fBulkOnlyCommandStructInUse == true ) 2926 { 2927 currentTask = fBulkOnlyCommandRequestBlock.request; 2928 } 2929 2930 else if( fCBICommandStructInUse == true ) 2931 { 2932 currentTask = fCBICommandRequestBlock.request; 2933 } 2934 2935 if ( currentTask != NULL ) 2936 { 2937 2938 SCSITaskStatus taskStatus; 2939 2940 fBulkOnlyCommandStructInUse = false; 2941 fBulkOnlyCommandRequestBlock.request = NULL; 2942 fCBICommandStructInUse = false; 2943 fCBICommandRequestBlock.request = NULL; 2944 2945 // Increment the count of consecutive I/Os which were aborted during a reset. 2946 // If that count is greater than the max, then consider the drive unusable, and mark the device as detached 2947 // so that the non-responsive volume doesn't hang restart, shutdown or applications. 2948 // Note that we will call terminate after releasing the WorkLoop because it also requires the 2949 // arbitration lock, and this could cause a deadlock if a software eject causes a close which requires I/Os. 2950 fConsecutiveResetCount++; 2951 if ( ( fConsecutiveResetCount > kMaxConsecutiveResets ) && ( fDeviceAttached == true ) ) 2952 { 2953 2954 IOLog ( "%s[%p]: The device is still unresponsive after %u consecutive USB Device Resets; it will be terminated.\n", getName(), this, fConsecutiveResetCount ); 2955 fDeviceAttached = false; 2956 2957 } 2958 2959 else 2960 { 2961 STATUS_LOG ( ( 4, "%s[%p]: AbortCurrentSCSITask fConsecutiveResetCount=%u", getName(), this, fConsecutiveResetCount ) ); 2962 } 2963 2964 RecordUSBTimeStamp ( UMC_TRACE( kAbortCurrentSCSITask ), 2965 ( uintptr_t ) this, ( uintptr_t ) currentTask, ( uintptr_t ) fDeviceAttached, ( uintptr_t ) fConsecutiveResetCount ); 2966 2967 if ( fDeviceAttached == false ) 2968 { 2969 2970 STATUS_LOG ( ( 1, "%s[%p]: AbortCurrentSCSITask Aborting currentTask=%p with device not present.", getName(), this, currentTask ) ); 2971 fTerminating = true; 2972 SendNotification_DeviceRemoved ( ); 2973 taskStatus = kSCSITaskStatus_DeviceNotPresent; 2974 2975 } 2976 2977 else 2978 { 2979 2980 STATUS_LOG ( ( 1, "%s[%p]: AbortCurrentSCSITask Aborting currentTask=%p with delivery failure.", getName(), this, currentTask ) ); 2981 taskStatus = kSCSITaskStatus_DeliveryFailure; 2982 2983 } 2984 2985 RecordUSBTimeStamp ( UMC_TRACE ( kCompleteSCSICommand ), 2986 ( uintptr_t ) this, ( uintptr_t ) currentTask, 2987 kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE, taskStatus ); 2988 2989 CommandCompleted ( currentTask, kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE, taskStatus ); 2990 2991 // If didTerminate() was called while this SCSI task was outstanding, then termination would 2992 // have been deferred until it completed. Check for that now, while behind the command gate. 2993 CheckDeferredTermination ( ); 2994 2995 } 2996 2997 STATUS_LOG ( ( 4, "%s[%p]: AbortCurrentSCSITask Exiting", getName(), this ) ); 2998 2999} 3000 3001 3002//----------------------------------------------------------------------------- 3003// - IsPhysicalInterconnectLocationInternal [PROTECTED] 3004//----------------------------------------------------------------------------- 3005 3006bool 3007IOUSBMassStorageClass::IsPhysicalInterconnectLocationInternal ( void ) 3008{ 3009 3010 IOReturn status = kIOReturnError; 3011 IOUSBInterface * usbInterface = NULL; 3012 IOUSBDevice * usbDevice = NULL; 3013 UInt32 deviceInformation = 0; 3014 bool internal = false; 3015 3016 3017 // We acquire our references individually to avoid panics. 3018 3019 // Get a reference to our USB interface. 3020 usbInterface = GetInterfaceReference(); 3021 require ( ( usbInterface != NULL ), ErrorExit ); 3022 3023 // Get a reference to our USB device. 3024 usbDevice = usbInterface->GetDevice(); 3025 require ( ( usbDevice != NULL ), ErrorExit ); 3026 3027 status = usbDevice->GetDeviceInformation ( &deviceInformation ); 3028 require_success ( status, ErrorExit ); 3029 3030 // Marking both captive and internal devices as internal. 3031 if ( ( deviceInformation & ( 1 << kUSBInformationDeviceIsCaptiveBit ) ) || 3032 ( deviceInformation & ( 1 << kUSBInformationDeviceIsInternalBit ) ) ) 3033 { 3034 internal = true; 3035 } 3036 3037 3038ErrorExit: 3039 3040 return internal; 3041 3042} 3043 3044 3045//----------------------------------------------------------------------------- 3046// - SuspendPort [PROTECTED] 3047//----------------------------------------------------------------------------- 3048 3049IOReturn 3050IOUSBMassStorageClass::SuspendPort ( bool suspend ) 3051{ 3052 3053 3054 STATUS_LOG ( ( 4, "%s[%p]: SuspendPort entered with suspend=%d onThread=%d", getName ( ), this, suspend, fWorkLoop->onThread ( ) ) ); 3055 3056 IOReturn status = kIOReturnError; 3057 IOUSBInterface * usbInterfaceRef = NULL; 3058 IOUSBDevice * usbDeviceRef = NULL; 3059 3060 3061 // See if we're already in the desired state. 3062 if ( suspend == fPortIsSuspended ) 3063 { 3064 3065 STATUS_LOG ( ( 4, "%s[%p]: SuspendPort !!!ALREADY!!! in desired state.", getName(), this ) ); 3066 3067 status = kIOReturnSuccess; 3068 goto Exit; 3069 3070 } 3071 3072 // Get our Device reference safely. 3073 usbInterfaceRef = GetInterfaceReference(); 3074 require ( usbInterfaceRef, Exit ); 3075 3076 usbDeviceRef = usbInterfaceRef->GetDevice(); 3077 require ( usbDeviceRef, Exit ); 3078 3079 // Suspend the USB port so that a remote wakeup will detect new media. 3080 if ( suspend == true ) 3081 { 3082 3083 STATUS_LOG ( ( 6, "%s[%p]::SuspendPort suspend port", getName(), this ) ); 3084 3085 // Suspend the port. 3086 status = usbDeviceRef->SuspendDevice ( true ); 3087 require ( ( status == kIOReturnSuccess ), Exit ); 3088 3089 // Suspend was successful, our USB port is now suspended. 3090 fPortIsSuspended = true; 3091 3092 } 3093 3094 // If the port was suspended, resume it, the host wants the drive back online. 3095 if ( suspend == false ) 3096 { 3097 3098 STATUS_LOG ( ( 6, "%s[%p]::SuspendPort resume port", getName(), this ) ); 3099 3100 // Resume the port. 3101 status = usbDeviceRef->SuspendDevice ( false ); 3102 require ( ( status == kIOReturnSuccess ), Exit ); 3103 3104 // It takes the USB controller a little while to get back on the line. 3105 IOSleep ( 15 ); 3106 // Resume was successful, our USB port is now active. 3107 fPortIsSuspended = false; 3108 3109 } 3110 3111 3112Exit: 3113 3114 3115 RecordUSBTimeStamp ( UMC_TRACE ( kSuspendPort ), ( uintptr_t ) this, status, suspend, NULL ); 3116 3117 STATUS_LOG ( ( 4, "%s[%p]: SuspendPort: returning status=0x%x fPortIsSuspended=%d", getName ( ), this, status, fPortIsSuspended ) ); 3118 return status; 3119 3120} 3121 3122#pragma mark 3123#pragma mark *** Reserved for future expansion *** 3124#pragma mark 3125 3126// Space reserved for future expansion. 3127OSMetaClassDefineReservedUnused( IOUSBMassStorageClass, 3 ); 3128OSMetaClassDefineReservedUnused( IOUSBMassStorageClass, 4 ); 3129OSMetaClassDefineReservedUnused( IOUSBMassStorageClass, 5 ); 3130OSMetaClassDefineReservedUnused( IOUSBMassStorageClass, 6 ); 3131OSMetaClassDefineReservedUnused( IOUSBMassStorageClass, 7 ); 3132OSMetaClassDefineReservedUnused( IOUSBMassStorageClass, 8 ); 3133OSMetaClassDefineReservedUnused( IOUSBMassStorageClass, 9 ); 3134OSMetaClassDefineReservedUnused( IOUSBMassStorageClass, 10 ); 3135OSMetaClassDefineReservedUnused( IOUSBMassStorageClass, 11 ); 3136OSMetaClassDefineReservedUnused( IOUSBMassStorageClass, 12 ); 3137OSMetaClassDefineReservedUnused( IOUSBMassStorageClass, 13 ); 3138OSMetaClassDefineReservedUnused( IOUSBMassStorageClass, 14 ); 3139OSMetaClassDefineReservedUnused( IOUSBMassStorageClass, 15 ); 3140OSMetaClassDefineReservedUnused( IOUSBMassStorageClass, 16 ); 3141