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