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