1/*
2 * Copyright (c) 1998-2014 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 since 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#ifndef EMBEDDED
216        UInt32					fPostDeviceResetCoolDownInterval;
217		bool					fSuspendOnReboot;
218#endif // EMBEDDED
219		UInt8					fResetStatus;
220
221#ifndef EMBEDDED
222	};
223    ExpansionData *				reserved;
224#endif // EMBEDDED
225
226#ifndef EMBEDDED
227	#define fResetInProgress					reserved->fResetInProgress
228	#define fClients							reserved->fClients
229	#define fPotentiallyStalledPipe				reserved->fPotentiallyStalledPipe
230    #define fUseUSBResetNotBOReset				reserved->fUseUSBResetNotBOReset
231	#define fAbortCurrentSCSITaskInProgress		reserved->fAbortCurrentSCSITaskInProgress
232    #define fCBIMemoryDescriptor                reserved->fCBIMemoryDescriptor
233	#define	fBulkOnlyCBWMemoryDescriptor		reserved->fBulkOnlyCBWMemoryDescriptor
234	#define	fBulkOnlyCSWMemoryDescriptor		reserved->fBulkOnlyCSWMemoryDescriptor
235    #define fDeviceAttached                     reserved->fDeviceAttached
236	#define fWaitingForReconfigurationMessage	reserved->fWaitingForReconfigurationMessage
237	#define fTerminating						reserved->fTerminating
238    #define fKnownCSWTagMismatchIssues          reserved->fKnownCSWTagMismatchIssues
239    #define fPortSuspendResumeForPMEnabled      reserved->fPortSuspendResumeForPMEnabled
240    #define fPortIsSuspended                    reserved->fPortIsSuspended
241    #define fRequiresResetOnResume				reserved->fRequiresResetOnResume
242    #define fAutonomousSpinDownWorkAround		reserved->fAutonomousSpinDownWorkAround
243    #define fConsecutiveResetCount				reserved->fConsecutiveResetCount
244    #define fClearStallInProgress				reserved->fClearStallInProgress
245    #define fTerminationDeferred				reserved->fTerminationDeferred
246    #define fRequiredMaxBusStall				reserved->fRequiredMaxBusStall
247    #define fBlockOnResetThread					reserved->fBlockOnResetThread
248    #define fPostDeviceResetCoolDownInterval	reserved->fPostDeviceResetCoolDownInterval
249    #define fSuspendOnReboot					reserved->fSuspendOnReboot
250    #define fResetStatus						reserved->fResetStatus
251#endif // EMBEDDED
252
253	// Enumerated constants used to control various aspects of this
254	// driver.
255
256	// Enumerates the fResetStatus
257	enum
258	{
259		kUSBResetStatusSuccess				= 0,
260		kUSBResetStatusFailure				= 1
261	};
262
263	// Enumerations for Mass Storage Class Subclass types
264	enum
265	{
266		kUSBStorageRBCSubclass 				= 1,
267		kUSBStorageSFF8020iSubclass 		= 2,
268		kUSBStorageQIC157Subclass			= 3,
269		kUSBStorageUFISubclass				= 4,
270		kUSBStorageSFF8070iSubclass			= 5,
271		kUSBStorageSCSITransparentSubclass	= 6
272	};
273
274	// The supported USB Mass Storage Class transport protocols.
275	enum
276	{
277		kProtocolControlBulkInterrupt	= 0x00,
278		kProtocolControlBulk			= 0x01,
279		kProtocolBulkOnly				= 0x50
280	};
281
282	// ------- Protocol support functions ------------
283	// The SendSCSICommand function will take a SCSITask Object and transport
284	// it across the physical wire(s) to the device
285	virtual bool    		SendSCSICommand(
286								SCSITaskIdentifier 		request,
287								SCSIServiceResponse *	serviceResponse,
288								SCSITaskStatus		*	taskStatus );
289
290	// The AbortSCSICommand function will abort the indicated SCSITask object,
291	// if it is possible and the SCSITask has not already completed.
292    virtual SCSIServiceResponse    	AbortSCSICommand( SCSITaskIdentifier abortTask );
293
294	virtual bool					IsProtocolServiceSupported(
295										SCSIProtocolFeature 	feature,
296										void * 					serviceValue );
297
298	virtual bool					HandleProtocolServiceFeature(
299										SCSIProtocolFeature 	feature,
300										void * 					serviceValue );
301
302	// Methods for retrieving and setting the object for the Interface
303	IOUSBInterface *		GetInterfaceReference( void );
304	void					SetInterfaceReference( IOUSBInterface * newInterface );
305
306	UInt8					GetInterfaceSubclass( void );
307	UInt8					GetInterfaceProtocol( void );
308
309	// Methods for retrieving an object for a Pipe.
310	IOUSBPipe *				GetControlPipe( void );
311	IOUSBPipe *				GetBulkInPipe( void );
312	IOUSBPipe *				GetBulkOutPipe( void );
313	IOUSBPipe *				GetInterruptPipe( void );
314
315	// Methods for getting and setting the maximum LUN of a device.
316	UInt8					GetMaxLogicalUnitNumber( void ) const;
317	void					SetMaxLogicalUnitNumber( UInt8 maxLUN );
318
319	virtual void 			CompleteSCSICommand(
320								SCSITaskIdentifier request,
321								IOReturn status );
322
323	virtual	bool			BeginProvidedServices( void );
324	virtual	bool			EndProvidedServices( void );
325
326	// The Protocol specific helper methods for SendSCSICommand
327	virtual IOReturn		SendSCSICommandForCBIProtocol(
328                                                          SCSITaskIdentifier request );
329
330	virtual IOReturn		SendSCSICommandForBulkOnlyProtocol(
331                                                               SCSITaskIdentifier request );
332
333	// The Protocol specific helper methods for AbortSCSICommand
334	virtual IOReturn		AbortSCSICommandForCBIProtocol(
335                                                           SCSITaskIdentifier abortTask );
336
337	virtual IOReturn		AbortSCSICommandForBulkOnlyProtocol(
338                                                                SCSITaskIdentifier abortTask );
339
340	// Helper methods for performing general USB device requests
341	virtual IOReturn		ClearFeatureEndpointStall(
342								IOUSBPipe *			thePipe,
343								IOUSBCompletion	*	completion );
344	virtual IOReturn 		GetStatusEndpointStatus(
345								IOUSBPipe *			thePipe,
346								void *				endpointStatus,
347								IOUSBCompletion	*	completion );
348
349 	/* All CBI transport related methods.
350 	 */
351	// All definitions and structures for the CBI Protocol
352	enum
353	{
354 		kUSBStorageAutoStatusSize	= 2		// Per the USB CBI Protocol
355 	};
356
357 	// Methods for accessing Bulk Only specific member variables.
358	CBIRequestBlock *		GetCBIRequestBlock( void );
359
360	void 					ReleaseCBIRequestBlock(
361								CBIRequestBlock *	cbiRequestBlock );
362
363	// Methods used for CBI/CB command transportation.
364	static void		CBIProtocolUSBCompletionAction(
365						void *					target,
366		                void *					parameter,
367		                IOReturn				status,
368		                UInt32					bufferSizeRemaining);
369
370	IOReturn		CBIProtocolTransferData(
371						CBIRequestBlock *		cbiRequestBlock,
372						UInt32					nextExecutionState );
373
374	IOReturn		CBIProtocolReadInterrupt(
375						CBIRequestBlock *		cbiRequestBlock,
376						UInt32					nextExecutionState );
377
378	IOReturn		CBIGetStatusEndpointStatus(
379						IOUSBPipe *				targetPipe,
380						CBIRequestBlock *		cbiRequestBlock,
381						UInt32					nextExecutionState );
382
383	IOReturn		CBIClearFeatureEndpointStall(
384						IOUSBPipe *				targetPipe,
385						CBIRequestBlock *		cbiRequestBlock,
386						UInt32					nextExecutionState );
387
388	void 			CBIProtocolCommandCompletion(
389						CBIRequestBlock *		cbiRequestBlock,
390		                IOReturn				resultingStatus,
391		                UInt32					bufferSizeRemaining );
392
393 	/* All Bulk Only transport related methods, structures and enums.
394 	 */
395 	// All Bulk Only specific structures and enums.
396
397	// All definitions and structures for the Bulk Only Protocol
398	// Command Block Wrapper (CBW)
399	enum
400	{
401		// CBW general struture definitions
402		kCommandBlockWrapperSignature	= OSSwapHostToBigConstInt32 ( 'USBC' ),
403		kByteCountOfCBW					= 31,
404
405		// CBW LUN related definitions
406		kCBWLUNMask						= 0x0F,
407
408		kCBWFlagsDataOut				= 0x00,
409		kCBWFlagsDataIn					= 0x80
410	};
411
412	// All definitions and structures for the Bulk Only Protocol
413	// Command Status Wrapper (CSW)
414	enum
415	{
416		// CSW general struture definitions
417		kCommandStatusWrapperSignature	= OSSwapHostToBigConstInt32 ( 'USBS' ),
418		kByteCountOfCSW					= 13,
419
420		// CSW status definitions
421		kCSWCommandPassedError 			= 0x00,	// No error occurred
422		kCSWCommandFailedError			= 0x01,	/* An error occurred (probably a
423											 	 * bad command or parameter ) */
424		kCSWPhaseError					= 0x02	/* A transfer was performed in
425											 	 * the wrong sequence */
426	};
427
428 	// Methods for accessing Bulk Only specific member variables.
429	BulkOnlyRequestBlock *	GetBulkOnlyRequestBlock( void );
430
431	void 			ReleaseBulkOnlyRequestBlock(
432						BulkOnlyRequestBlock * 		boRequestBlock );
433
434	UInt32			GetNextBulkOnlyCommandTag( void );
435
436	// Methods for Bulk Only specific utility commands
437	IOReturn		BulkDeviceResetDevice(
438						BulkOnlyRequestBlock *		boRequestBlock,
439						UInt32						nextExecutionState );
440
441	// Methods used for Bulk Only command transportation.
442	IOReturn		BulkOnlySendCBWPacket(
443						BulkOnlyRequestBlock *		boRequestBlock,
444						UInt32						nextExecutionState );
445
446	IOReturn		BulkOnlyTransferData(
447						BulkOnlyRequestBlock *		boRequestBlock,
448						UInt32						nextExecutionState );
449
450	IOReturn		BulkOnlyReceiveCSWPacket(
451						BulkOnlyRequestBlock *		boRequestBlock,
452						UInt32						nextExecutionState );
453
454	void			BulkOnlyExecuteCommandCompletion (
455						BulkOnlyRequestBlock *		boRequestBlock,
456		                IOReturn					resultingStatus,
457		                UInt32						bufferSizeRemaining );
458
459	static void		BulkOnlyUSBCompletionAction (
460		                void *			target,
461		                void *			parameter,
462		                IOReturn		status,
463		                UInt32			bufferSizeRemaining );
464
465public:
466
467    bool				init( OSDictionary * 	propTable );
468    virtual bool		start( IOService *	 	provider );
469    virtual void 		stop( IOService * 		provider );
470	virtual void		free( void );
471	virtual	IOReturn	message( UInt32 type, IOService * provider, void * argument = 0 );
472
473	virtual bool        willTerminate(  IOService *     provider,
474                                        IOOptionBits    options );
475
476	virtual bool        didTerminate(	IOService *     provider,
477                                        IOOptionBits    options,
478										bool *			defer );
479
480	virtual bool		handleOpen( IOService *		client,
481									IOOptionBits	options,
482									void *			arg );
483
484	virtual void		handleClose( IOService *	client,
485									 IOOptionBits	options );
486
487	virtual bool		handleIsOpen(  const IOService * client ) const;
488
489	virtual IOReturn	HandlePowerOn( void );
490
491#ifndef EMBEDDED
492	virtual void		systemWillShutdown ( IOOptionBits specifier );
493#endif // EMBEDDED
494
495protected:
496
497	static IOReturn		sWaitForReset( void * refcon );
498	IOReturn			GatedWaitForReset( void );
499
500#ifndef EMBEDDED
501	static IOReturn		sWaitForTaskAbort( void * refcon );			/* OBSOLETE */
502	IOReturn			GatedWaitForTaskAbort( void );				/* OBSOLETE */
503#endif // EMBEDDED
504
505	static void			sResetDevice( void * refcon );
506
507#ifndef EMBEDDED
508	static void			sAbortCurrentSCSITask( void * refcon );		/* OBSOLETE */
509
510    OSMetaClassDeclareReservedUsed( IOUSBMassStorageClass, 1 );
511	virtual IOReturn	StartDeviceRecovery( void );				/* OBSOLETE */
512
513    OSMetaClassDeclareReservedUsed( IOUSBMassStorageClass, 2 );
514	virtual void		FinishDeviceRecovery( IOReturn	status );	/* OBSOLETE */
515
516	static void			DeviceRecoveryCompletionAction(
517		                	void *			target,
518		                	void *			parameter,
519		                	IOReturn		status,
520		                	UInt32			bufferSizeRemaining );	/* OBSOLETE */
521#endif // EMBEDDED
522
523	IOReturn       ResetDeviceNow( bool waitForReset );
524
525	void                AbortCurrentSCSITask( void );
526
527	bool                IsPhysicalInterconnectLocationInternal ( void );
528
529	IOReturn            SuspendPort ( bool suspend );
530
531private:
532
533	void				ClearPipeStall ( void );
534
535	IOReturn			AcceptSCSITask ( SCSITaskIdentifier scsiTask, bool * pAccepted );
536
537	void				CheckDeferredTermination ( void );
538
539	void				GatedCompleteSCSICommand ( SCSITaskIdentifier request, SCSIServiceResponse * serviceResponse, SCSITaskStatus * taskStatus );
540
541	// Space reserved for future expansion.
542    OSMetaClassDeclareReservedUnused( IOUSBMassStorageClass, 3 );
543    OSMetaClassDeclareReservedUnused( IOUSBMassStorageClass, 4 );
544    OSMetaClassDeclareReservedUnused( IOUSBMassStorageClass, 5 );
545    OSMetaClassDeclareReservedUnused( IOUSBMassStorageClass, 6 );
546    OSMetaClassDeclareReservedUnused( IOUSBMassStorageClass, 7 );
547    OSMetaClassDeclareReservedUnused( IOUSBMassStorageClass, 8 );
548    OSMetaClassDeclareReservedUnused( IOUSBMassStorageClass, 9 );
549    OSMetaClassDeclareReservedUnused( IOUSBMassStorageClass, 10 );
550    OSMetaClassDeclareReservedUnused( IOUSBMassStorageClass, 11 );
551    OSMetaClassDeclareReservedUnused( IOUSBMassStorageClass, 12 );
552    OSMetaClassDeclareReservedUnused( IOUSBMassStorageClass, 13 );
553    OSMetaClassDeclareReservedUnused( IOUSBMassStorageClass, 14 );
554    OSMetaClassDeclareReservedUnused( IOUSBMassStorageClass, 15 );
555    OSMetaClassDeclareReservedUnused( IOUSBMassStorageClass, 16 );
556
557};
558
559
560#endif //_IOKIT_IOUSBMASSSTORAGECLASS_H
561