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