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#ifndef _IOKIT_IOUSBMASSSTORAGECLASS_H 26#define _IOKIT_IOUSBMASSSTORAGECLASS_H 27 28// Headers for general IOKit definitions 29#include <IOKit/IOLib.h> 30#include <IOKit/IOService.h> 31#include <IOKit/IOMemoryDescriptor.h> 32#include <IOKit/IOMessage.h> 33 34// Headers for USB specific definitions 35#include <IOKit/usb/IOUSBInterface.h> 36#include <IOKit/usb/IOUSBPipe.h> 37#include <IOKit/usb/USBSpec.h> 38#include <IOKit/usb/USB.h> 39 40// Headers for SCSI Protocol support definitions 41#include <IOKit/scsi/IOSCSIProtocolServices.h> 42 43// BSD includes 44#include <sys/sysctl.h> 45 46#define UNUSED(x) ((void)x) 47 48#pragma mark - 49#pragma mark Vendor Specific Device Support 50#define kIOUSBMassStorageCharacteristics "USB Mass Storage Characteristics" 51#define kIOUSBMassStoragePreferredSubclass "Preferred Subclass" 52#define kIOUSBMassStoragePreferredProtocol "Preferred Protocol" 53#define kIOUSBMassStorageUseStandardUSBReset "Use Standard USB Reset" 54#define kIOUSBKnownCSWTagIssues "Known CSW Tag Issues" 55#define kIOUSBMassStorageMaxLogicalUnitNumber "Max Logical Unit Number" 56#define kIOPropertyIOUnitKey "IOUnit" 57#define kIOUSBMassStorageDoNotMatch "Do Not Match MSC" 58#define kIOUSBMassStorageDoNotOperate "Do Not Operate" 59#define kIOUSBMassStorageEnableSuspendResumePM "Enable Port Suspend-Resume PM" 60#define kIOUSBMassStoragePostResetCoolDown "Reset Recovery Time" 61 62#ifndef EMBEDDED 63#define kIOUSBMassStorageSuspendOnReboot "Suspend On Reboot" 64#define kIOUSBMassStorageResetOnResume "Reset On Resume" 65#endif // EMBEDDED 66 67enum 68{ 69 kUSBDAddressLength = 10 70}; 71 72enum 73{ 74 kIOUSBMassStorageReconfigurationTimeoutMS = 5000 75}; 76 77 78#pragma mark - 79#pragma mark CBI Protocol Strutures 80// Structure for the global PB's 81struct CBIRequestBlock 82{ 83 SCSITaskIdentifier request; 84 IOUSBDevRequest cbiDevRequest; 85 SCSICommandDescriptorBlock cbiCDB; 86 IOUSBCompletion cbiCompletion; 87 UInt32 currentState; 88 IOMemoryDescriptor * cbiPhaseDesc; 89 UInt8 cbiGetStatusBuffer[2]; // 2 bytes as specified in the USB spec 90}; 91 92typedef struct CBIRequestBlock CBIRequestBlock; 93 94#pragma mark - 95#pragma mark Bulk Only Protocol Structures 96 97struct StorageBulkOnlyCBW 98{ 99 UInt32 cbwSignature; 100 UInt32 cbwTag; 101 UInt32 cbwTransferLength; 102 UInt8 cbwFlags; 103 UInt8 cbwLUN; // Bits 0-3: LUN, 4-7: Reserved 104 UInt8 cbwCDBLength; // Bits 0-4: CDB Length, 5-7: Reserved 105 UInt8 cbwCDB[16]; 106}; 107 108typedef struct StorageBulkOnlyCBW StorageBulkOnlyCBW; 109 110struct StorageBulkOnlyCSW 111{ 112 UInt32 cswSignature; 113 UInt32 cswTag; 114 UInt32 cswDataResidue; 115 UInt8 cswStatus; 116}; 117 118typedef struct StorageBulkOnlyCSW StorageBulkOnlyCSW; 119 120struct BulkOnlyRequestBlock 121{ 122 SCSITaskIdentifier request; 123 IOUSBCompletion boCompletion; 124 UInt32 currentState; 125 StorageBulkOnlyCBW boCBW; 126 StorageBulkOnlyCSW boCSW; 127 IOMemoryDescriptor * boPhaseDesc; 128 UInt8 boGetStatusBuffer[2]; // 2 bytes as specified in the USB spec 129}; 130 131typedef struct BulkOnlyRequestBlock BulkOnlyRequestBlock; 132 133 134#pragma mark - 135#pragma mark IOUSBMassStorageClass definition 136 137class IOUSBMassStorageClass : public IOSCSIProtocolServices 138{ 139 OSDeclareDefaultStructors(IOUSBMassStorageClass) 140 141private: 142 // ---- Member variables used by all protocols ---- 143 // The interface object that provides the driver with access to the 144 // USB so that it may talk to its device. 145 IOUSBInterface * fInterface; 146 147 // The pipe objects that the driver uses to transport data through a 148 // pipe to the appropriate endpoint. 149 IOUSBPipe * fBulkInPipe; 150 IOUSBPipe * fBulkOutPipe; 151 IOUSBPipe * fInterruptPipe; 152 153 IOUSBDevRequest fUSBDeviceRequest; 154 UInt8 fPreferredSubclass; 155 UInt8 fPreferredProtocol; 156 157 // The maximum Logical Unit Number. This is the highest valid LUN 158 // that the USB device supports, so if the device only supports one 159 // LUN, such as CBI and CB, this number will be zero. 160 UInt8 fMaxLogicalUnitNumber; 161 162 // ---- Member variables used by CBI protocol ---- 163 bool fCBICommandStructInUse; 164 165 CBIRequestBlock fCBICommandRequestBlock; 166 167 // ---- Member variables used by Bulk Only protocol ---- 168 // Command tag, this driver just uses a sequential counter that is 169 // incremented for each CBW that is sent to the device. 170 UInt32 fBulkOnlyCommandTag; 171 172 bool fBulkOnlyCommandStructInUse; 173 174 // Dedicated CBW and CSW IOMemoryDescriptors are listed in the ExpansionData struct. 175 176 // The Request block that contains all the necessary data for 177 // transporting a Bulk Only request across the USB. 178 BulkOnlyRequestBlock fBulkOnlyCommandRequestBlock; 179 180protected: 181 // Reserve space for future expansion. 182 183 // We flatten the ExpansionData for iOS as we're relieved of the burden binary compatibility. 184#ifndef EMBEDDED 185 struct ExpansionData 186 { 187#endif // EMBEDDED 188 bool fResetInProgress; 189 OSSet * fClients; 190 IOUSBPipe * fPotentiallyStalledPipe; 191 bool fUseUSBResetNotBOReset; 192 bool fAbortCurrentSCSITaskInProgress; 193 IOMemoryDescriptor * fCBIMemoryDescriptor; 194 IOMemoryDescriptor * fBulkOnlyCBWMemoryDescriptor; 195 IOMemoryDescriptor * fBulkOnlyCSWMemoryDescriptor; 196 bool fDeviceAttached; 197 bool fWaitingForReconfigurationMessage; 198 bool fTerminating; 199 bool fKnownCSWTagMismatchIssues; 200 bool fPortSuspendResumeForPMEnabled; 201 bool fPortIsSuspended; 202#ifndef EMBEDDED 203 bool fRequiresResetOnResume; 204 bool fAutonomousSpinDownWorkAround; 205#endif // EMBEDDED 206 UInt8 fConsecutiveResetCount; 207#ifndef EMBEDDED 208 bool fClearStallInProgress; /* OBSOLETE */ 209#endif // EMBEDDED 210 bool fTerminationDeferred; 211#ifndef EMBEDDED 212 UInt32 fRequiredMaxBusStall; 213#endif // EMBEDDED 214 bool fBlockOnResetThread; 215 UInt32 fPostDeviceResetCoolDownInterval; 216#ifndef EMBEDDED 217 bool fSuspendOnReboot; 218#endif // EMBEDDED 219 220#ifndef EMBEDDED 221 }; 222 ExpansionData * reserved; 223#endif // EMBEDDED 224 225#ifndef EMBEDDED 226 #define fResetInProgress reserved->fResetInProgress 227 #define fClients reserved->fClients 228 #define fPotentiallyStalledPipe reserved->fPotentiallyStalledPipe 229 #define fUseUSBResetNotBOReset reserved->fUseUSBResetNotBOReset 230 #define fAbortCurrentSCSITaskInProgress reserved->fAbortCurrentSCSITaskInProgress 231 #define fCBIMemoryDescriptor reserved->fCBIMemoryDescriptor 232 #define fBulkOnlyCBWMemoryDescriptor reserved->fBulkOnlyCBWMemoryDescriptor 233 #define fBulkOnlyCSWMemoryDescriptor reserved->fBulkOnlyCSWMemoryDescriptor 234 #define fDeviceAttached reserved->fDeviceAttached 235 #define fWaitingForReconfigurationMessage reserved->fWaitingForReconfigurationMessage 236 #define fTerminating reserved->fTerminating 237 #define fKnownCSWTagMismatchIssues reserved->fKnownCSWTagMismatchIssues 238 #define fPortSuspendResumeForPMEnabled reserved->fPortSuspendResumeForPMEnabled 239 #define fPortIsSuspended reserved->fPortIsSuspended 240 #define fRequiresResetOnResume reserved->fRequiresResetOnResume 241 #define fAutonomousSpinDownWorkAround reserved->fAutonomousSpinDownWorkAround 242 #define fConsecutiveResetCount reserved->fConsecutiveResetCount 243 #define fClearStallInProgress reserved->fClearStallInProgress 244 #define fTerminationDeferred reserved->fTerminationDeferred 245 #define fRequiredMaxBusStall reserved->fRequiredMaxBusStall 246 #define fBlockOnResetThread reserved->fBlockOnResetThread 247 #define fPostDeviceResetCoolDownInterval reserved->fPostDeviceResetCoolDownInterval 248 #define fSuspendOnReboot reserved->fSuspendOnReboot 249#endif // EMBEDDED 250 251 // Enumerated constants used to control various aspects of this 252 // driver. 253 254 // Enumerations for Mass Storage Class Subclass types 255 enum 256 { 257 kUSBStorageRBCSubclass = 1, 258 kUSBStorageSFF8020iSubclass = 2, 259 kUSBStorageQIC157Subclass = 3, 260 kUSBStorageUFISubclass = 4, 261 kUSBStorageSFF8070iSubclass = 5, 262 kUSBStorageSCSITransparentSubclass = 6 263 }; 264 265 // The supported USB Mass Storage Class transport protocols. 266 enum 267 { 268 kProtocolControlBulkInterrupt = 0x00, 269 kProtocolControlBulk = 0x01, 270 kProtocolBulkOnly = 0x50 271 }; 272 273 // ------- Protocol support functions ------------ 274 // The SendSCSICommand function will take a SCSITask Object and transport 275 // it across the physical wire(s) to the device 276 virtual bool SendSCSICommand( 277 SCSITaskIdentifier request, 278 SCSIServiceResponse * serviceResponse, 279 SCSITaskStatus * taskStatus ); 280 281 // The AbortSCSICommand function will abort the indicated SCSITask object, 282 // if it is possible and the SCSITask has not already completed. 283 virtual SCSIServiceResponse AbortSCSICommand( SCSITaskIdentifier abortTask ); 284 285 virtual bool IsProtocolServiceSupported( 286 SCSIProtocolFeature feature, 287 void * serviceValue ); 288 289 virtual bool HandleProtocolServiceFeature( 290 SCSIProtocolFeature feature, 291 void * serviceValue ); 292 293 // Methods for retrieving and setting the object for the Interface 294 IOUSBInterface * GetInterfaceReference( void ); 295 void SetInterfaceReference( IOUSBInterface * newInterface ); 296 297 UInt8 GetInterfaceSubclass( void ); 298 UInt8 GetInterfaceProtocol( void ); 299 300 // Methods for retrieving an object for a Pipe. 301 IOUSBPipe * GetControlPipe( void ); 302 IOUSBPipe * GetBulkInPipe( void ); 303 IOUSBPipe * GetBulkOutPipe( void ); 304 IOUSBPipe * GetInterruptPipe( void ); 305 306 // Methods for getting and setting the maximum LUN of a device. 307 UInt8 GetMaxLogicalUnitNumber( void ) const; 308 void SetMaxLogicalUnitNumber( UInt8 maxLUN ); 309 310 virtual void CompleteSCSICommand( 311 SCSITaskIdentifier request, 312 IOReturn status ); 313 314 virtual bool BeginProvidedServices( void ); 315 virtual bool EndProvidedServices( void ); 316 317 // The Protocol specific helper methods for SendSCSICommand 318 virtual IOReturn SendSCSICommandForCBIProtocol( 319 SCSITaskIdentifier request ); 320 321 virtual IOReturn SendSCSICommandForBulkOnlyProtocol( 322 SCSITaskIdentifier request ); 323 324 // The Protocol specific helper methods for AbortSCSICommand 325 virtual IOReturn AbortSCSICommandForCBIProtocol( 326 SCSITaskIdentifier abortTask ); 327 328 virtual IOReturn AbortSCSICommandForBulkOnlyProtocol( 329 SCSITaskIdentifier abortTask ); 330 331 // Helper methods for performing general USB device requests 332 virtual IOReturn ClearFeatureEndpointStall( 333 IOUSBPipe * thePipe, 334 IOUSBCompletion * completion ); 335 virtual IOReturn GetStatusEndpointStatus( 336 IOUSBPipe * thePipe, 337 void * endpointStatus, 338 IOUSBCompletion * completion ); 339 340 /* All CBI transport related methods. 341 */ 342 // All definitions and structures for the CBI Protocol 343 enum 344 { 345 kUSBStorageAutoStatusSize = 2 // Per the USB CBI Protocol 346 }; 347 348 // Methods for accessing Bulk Only specific member variables. 349 CBIRequestBlock * GetCBIRequestBlock( void ); 350 351 void ReleaseCBIRequestBlock( 352 CBIRequestBlock * cbiRequestBlock ); 353 354 // Methods used for CBI/CB command transportation. 355 static void CBIProtocolUSBCompletionAction( 356 void * target, 357 void * parameter, 358 IOReturn status, 359 UInt32 bufferSizeRemaining); 360 361 IOReturn CBIProtocolTransferData( 362 CBIRequestBlock * cbiRequestBlock, 363 UInt32 nextExecutionState ); 364 365 IOReturn CBIProtocolReadInterrupt( 366 CBIRequestBlock * cbiRequestBlock, 367 UInt32 nextExecutionState ); 368 369 IOReturn CBIGetStatusEndpointStatus( 370 IOUSBPipe * targetPipe, 371 CBIRequestBlock * cbiRequestBlock, 372 UInt32 nextExecutionState ); 373 374 IOReturn CBIClearFeatureEndpointStall( 375 IOUSBPipe * targetPipe, 376 CBIRequestBlock * cbiRequestBlock, 377 UInt32 nextExecutionState ); 378 379 void CBIProtocolCommandCompletion( 380 CBIRequestBlock * cbiRequestBlock, 381 IOReturn resultingStatus, 382 UInt32 bufferSizeRemaining ); 383 384 /* All Bulk Only transport related methods, structures and enums. 385 */ 386 // All Bulk Only specific structures and enums. 387 388 // All definitions and structures for the Bulk Only Protocol 389 // Command Block Wrapper (CBW) 390 enum 391 { 392 // CBW general struture definitions 393 kCommandBlockWrapperSignature = OSSwapHostToBigConstInt32 ( 'USBC' ), 394 kByteCountOfCBW = 31, 395 396 // CBW LUN related definitions 397 kCBWLUNMask = 0x0F, 398 399 kCBWFlagsDataOut = 0x00, 400 kCBWFlagsDataIn = 0x80 401 }; 402 403 // All definitions and structures for the Bulk Only Protocol 404 // Command Status Wrapper (CSW) 405 enum 406 { 407 // CSW general struture definitions 408 kCommandStatusWrapperSignature = OSSwapHostToBigConstInt32 ( 'USBS' ), 409 kByteCountOfCSW = 13, 410 411 // CSW status definitions 412 kCSWCommandPassedError = 0x00, // No error occurred 413 kCSWCommandFailedError = 0x01, /* An error occurred (probably a 414 * bad command or parameter ) */ 415 kCSWPhaseError = 0x02 /* A transfer was performed in 416 * the wrong sequence */ 417 }; 418 419 // Methods for accessing Bulk Only specific member variables. 420 BulkOnlyRequestBlock * GetBulkOnlyRequestBlock( void ); 421 422 void ReleaseBulkOnlyRequestBlock( 423 BulkOnlyRequestBlock * boRequestBlock ); 424 425 UInt32 GetNextBulkOnlyCommandTag( void ); 426 427 // Methods for Bulk Only specific utility commands 428 IOReturn BulkDeviceResetDevice( 429 BulkOnlyRequestBlock * boRequestBlock, 430 UInt32 nextExecutionState ); 431 432 // Methods used for Bulk Only command transportation. 433 IOReturn BulkOnlySendCBWPacket( 434 BulkOnlyRequestBlock * boRequestBlock, 435 UInt32 nextExecutionState ); 436 437 IOReturn BulkOnlyTransferData( 438 BulkOnlyRequestBlock * boRequestBlock, 439 UInt32 nextExecutionState ); 440 441 IOReturn BulkOnlyReceiveCSWPacket( 442 BulkOnlyRequestBlock * boRequestBlock, 443 UInt32 nextExecutionState ); 444 445 void BulkOnlyExecuteCommandCompletion ( 446 BulkOnlyRequestBlock * boRequestBlock, 447 IOReturn resultingStatus, 448 UInt32 bufferSizeRemaining ); 449 450 static void BulkOnlyUSBCompletionAction ( 451 void * target, 452 void * parameter, 453 IOReturn status, 454 UInt32 bufferSizeRemaining ); 455 456public: 457 458 bool init( OSDictionary * propTable ); 459 virtual bool start( IOService * provider ); 460 virtual void stop( IOService * provider ); 461 virtual void free( void ); 462 virtual IOReturn message( UInt32 type, IOService * provider, void * argument = 0 ); 463 464 virtual bool willTerminate( IOService * provider, 465 IOOptionBits options ); 466 467 virtual bool didTerminate( IOService * provider, 468 IOOptionBits options, 469 bool * defer ); 470 471 virtual bool handleOpen( IOService * client, 472 IOOptionBits options, 473 void * arg ); 474 475 virtual void handleClose( IOService * client, 476 IOOptionBits options ); 477 478 virtual bool handleIsOpen( const IOService * client ) const; 479 480 virtual IOReturn HandlePowerOn( void ); 481 482#ifndef EMBEDDED 483 virtual void systemWillShutdown ( IOOptionBits specifier ); 484#endif // EMBEDDED 485 486protected: 487 488 static IOReturn sWaitForReset( void * refcon ); 489 IOReturn GatedWaitForReset( void ); 490 491#ifndef EMBEDDED 492 static IOReturn sWaitForTaskAbort( void * refcon ); /* OBSOLETE */ 493 IOReturn GatedWaitForTaskAbort( void ); /* OBSOLETE */ 494#endif // EMBEDDED 495 496 static void sResetDevice( void * refcon ); 497 498#ifndef EMBEDDED 499 static void sAbortCurrentSCSITask( void * refcon ); /* OBSOLETE */ 500 501 OSMetaClassDeclareReservedUsed( IOUSBMassStorageClass, 1 ); 502 virtual IOReturn StartDeviceRecovery( void ); /* OBSOLETE */ 503 504 OSMetaClassDeclareReservedUsed( IOUSBMassStorageClass, 2 ); 505 virtual void FinishDeviceRecovery( IOReturn status ); /* OBSOLETE */ 506 507 static void DeviceRecoveryCompletionAction( 508 void * target, 509 void * parameter, 510 IOReturn status, 511 UInt32 bufferSizeRemaining ); /* OBSOLETE */ 512#endif // EMBEDDED 513 514 void ResetDeviceNow( bool waitForReset ); 515 516 void AbortCurrentSCSITask( void ); 517 518 bool IsPhysicalInterconnectLocationInternal ( void ); 519 520 IOReturn SuspendPort ( bool suspend ); 521 522private: 523 524 void ClearPipeStall ( void ); 525 526 IOReturn AcceptSCSITask ( SCSITaskIdentifier scsiTask, bool * pAccepted ); 527 528 void CheckDeferredTermination ( void ); 529 530 void GatedCompleteSCSICommand ( SCSITaskIdentifier request, SCSIServiceResponse * serviceResponse, SCSITaskStatus * taskStatus ); 531 532 // Space reserved for future expansion. 533 OSMetaClassDeclareReservedUnused( IOUSBMassStorageClass, 3 ); 534 OSMetaClassDeclareReservedUnused( IOUSBMassStorageClass, 4 ); 535 OSMetaClassDeclareReservedUnused( IOUSBMassStorageClass, 5 ); 536 OSMetaClassDeclareReservedUnused( IOUSBMassStorageClass, 6 ); 537 OSMetaClassDeclareReservedUnused( IOUSBMassStorageClass, 7 ); 538 OSMetaClassDeclareReservedUnused( IOUSBMassStorageClass, 8 ); 539 OSMetaClassDeclareReservedUnused( IOUSBMassStorageClass, 9 ); 540 OSMetaClassDeclareReservedUnused( IOUSBMassStorageClass, 10 ); 541 OSMetaClassDeclareReservedUnused( IOUSBMassStorageClass, 11 ); 542 OSMetaClassDeclareReservedUnused( IOUSBMassStorageClass, 12 ); 543 OSMetaClassDeclareReservedUnused( IOUSBMassStorageClass, 13 ); 544 OSMetaClassDeclareReservedUnused( IOUSBMassStorageClass, 14 ); 545 OSMetaClassDeclareReservedUnused( IOUSBMassStorageClass, 15 ); 546 OSMetaClassDeclareReservedUnused( IOUSBMassStorageClass, 16 ); 547 548}; 549 550 551#endif //_IOKIT_IOUSBMASSSTORAGECLASS_H 552