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// This class' header file
30#include "IOUSBMassStorageUFISubclass.h"
31
32#include <IOKit/storage/IOBlockStorageDriver.h>
33#include <IOKit/IOSyncer.h>
34#include <IOKit/usb/IOUFIStorageServices.h>
35#include <IOKit/scsi/SCSICmds_INQUIRY_Definitions.h>
36#include <IOKit/scsi/SCSICommandOperationCodes.h>
37
38#include <IOKit/scsi/SCSITask.h>
39
40// IOKit Power Management headers
41#include <IOKit/pwr_mgt/RootDomain.h>
42
43#include "Debugging.h"
44
45
46//--------------------------------------------------------------------------------------------------
47//	Macros
48//--------------------------------------------------------------------------------------------------
49
50//--------------------------------------------------------------------------------------------------
51//	Constants
52//--------------------------------------------------------------------------------------------------
53
54#define kKeySwitchProperty			"Keyswitch"
55#define kAppleKeySwitchProperty		"AppleKeyswitch"
56
57#define super IOSCSIPrimaryCommandsDevice
58
59enum
60{
61	kIOUSBMassStorageUFIDevicePowerStateSleep 		= 0,
62	kIOUSBMassStorageUFIDevicePowerStateActive		= 1,
63	kIOUSBMassStorageUFIDeviceNumPowerStates		= 2
64};
65
66
67static IOPMPowerState sPowerStates[kIOUSBMassStorageUFIDeviceNumPowerStates] =
68{
69	{ kIOPMPowerStateVersion1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
70	{ kIOPMPowerStateVersion1, IOPMPowerOn, IOPMPowerOn, IOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0}
71};
72
73
74//-----------------------------------------------------------------------------
75//	Globals
76//-----------------------------------------------------------------------------
77
78IOOptionBits	gRestartShutdownFlag = 0;
79
80OSDefineMetaClassAndStructors( IOUSBMassStorageUFISubclass, IOUSBMassStorageClass )
81
82
83#pragma mark -
84#pragma mark *** IOUSBMassStorageUFIDevice declaration ***
85#pragma mark -
86
87OSDefineMetaClassAndStructors( IOUSBMassStorageUFIDevice, IOSCSIPrimaryCommandsDevice )
88
89
90#pragma mark -
91#pragma mark *** Static Class Methods ***
92#pragma mark -
93
94
95//--------------------------------------------------------------------------------------------------
96//	sProcessPoll -	Gets scheduled to execute the polls.	   						[STATIC][PUBLIC]
97//--------------------------------------------------------------------------------------------------
98
99void
100IOUSBMassStorageUFIDevice::sProcessPoll ( void * theUFIDriver, void * refCon )
101{
102	UNUSED( refCon );
103
104	IOUSBMassStorageUFIDevice *	driver;
105
106	driver = (IOUSBMassStorageUFIDevice *) theUFIDriver;
107	require_nonzero ( driver, ErrorExit );
108
109	if( driver->fPollingMode != kPollingMode_Suspended )
110	{
111
112		driver->ProcessPoll();
113
114		if( driver->fPollingMode != kPollingMode_Suspended )
115		{
116			// schedule the poller again
117			driver->EnablePolling();
118		}
119
120	}
121
122	// drop the retain associated with this poll
123	driver->release();
124
125
126ErrorExit:
127
128	return;
129
130}
131
132
133//--------------------------------------------------------------------------------------------------
134//	AsyncReadWriteComplete - Completion routine for I/O							   [STATIC][PRIVATE]
135//--------------------------------------------------------------------------------------------------
136
137void
138IOUSBMassStorageUFIDevice::AsyncReadWriteComplete ( SCSITaskIdentifier request )
139{
140	void *							clientData;
141	IOReturn						status;
142	UInt64							actCount = 0;
143	IOUSBMassStorageUFIDevice *		taskOwner;
144
145
146	if ( request == NULL )
147	{
148		PANIC_NOW ( ( "IOUSBMassStorageUFIDevice::AsyncReadWriteComplete request==NULL." ) );
149	}
150
151	taskOwner = OSDynamicCast ( IOUSBMassStorageUFIDevice, IOSCSIPrimaryCommandsDevice::sGetOwnerForTask ( request ) );
152	if ( taskOwner == NULL )
153	{
154		PANIC_NOW ( ( "IOUSBMassStorageUFIDevice::AsyncReadWriteComplete taskOwner==NULL." ) );
155	}
156
157	// Extract the client data from the SCSITask
158	clientData	= taskOwner->GetApplicationLayerReference( request );
159
160	if ( ( taskOwner->GetServiceResponse( request ) == kSCSIServiceResponse_TASK_COMPLETE ) &&
161		( taskOwner->GetTaskStatus( request ) == kSCSITaskStatus_GOOD ) )
162	{
163		status = kIOReturnSuccess;
164	}
165	else
166	{
167
168		STATUS_LOG ( ( 4, "%s[%p]::Error on read/write", taskOwner->getName(), taskOwner ) );
169		status = kIOReturnError;
170
171	}
172
173	if ( status == kIOReturnSuccess )
174	{
175		actCount = taskOwner->GetDataBuffer( request )->getLength();
176	}
177
178
179	taskOwner->ReleaseSCSITask( request );
180
181	IOUFIStorageServices::AsyncReadWriteComplete( clientData, status, actCount );
182
183}
184
185
186#pragma mark -
187#pragma mark *** Class Methods ***
188#pragma mark -
189
190
191//--------------------------------------------------------------------------------------------------
192//	InitializeDeviceSupport - Initializes device support								 [PROTECTED]
193//--------------------------------------------------------------------------------------------------
194
195bool
196IOUSBMassStorageUFIDevice::InitializeDeviceSupport ( void )
197{
198	bool setupSuccessful 	= false;
199
200
201	// Initialize the medium characteristics
202	fMediumPresent			= false;
203	fMediumIsWriteProtected	= true;
204
205    STATUS_LOG ( ( 6, "%s[%p]::InitializeDeviceSupport called", getName(), this ) );
206
207	ClearNotReadyStatus();
208
209	fPollingMode = kPollingMode_NewMedia;
210
211	fIOUSBMassStorageUFIDeviceReserved = ( IOUSBMassStorageUFIDeviceExpansionData * )
212			IOMalloc ( sizeof ( IOUSBMassStorageUFIDeviceExpansionData ) );
213	require_nonzero ( fIOUSBMassStorageUFIDeviceReserved, ErrorExit );
214
215	require ( ( DetermineDeviceCharacteristics( ) == true ), ErrorExit );
216
217	fPollingThread = thread_call_allocate (
218					( thread_call_func_t ) IOUSBMassStorageUFIDevice::sProcessPoll,
219					( thread_call_param_t ) this );
220	require_nonzero ( fPollingThread, ErrorExit );
221
222	bzero ( fIOUSBMassStorageUFIDeviceReserved,
223			sizeof ( IOUSBMassStorageUFIDeviceExpansionData ) );
224
225	InitializePowerManagement ( GetProtocolDriver ( ) );
226
227	STATUS_LOG ( ( 5, "%s[%p]::InitializeDeviceSupport setupSuccessful = %d", getName(), this, setupSuccessful ) );
228
229	setupSuccessful = true;
230
231ErrorExit:
232
233	if ( setupSuccessful == false )
234	{
235		TerminateDeviceSupport();
236	}
237
238	return setupSuccessful;
239}
240
241
242//--------------------------------------------------------------------------------------------------
243//	StartDeviceSupport - Starts device support											 [PROTECTED]
244//--------------------------------------------------------------------------------------------------
245
246void
247IOUSBMassStorageUFIDevice::StartDeviceSupport ( void )
248{
249	OSBoolean *		shouldNotPoll = NULL;
250
251
252	shouldNotPoll = OSDynamicCast (	OSBoolean,
253									getProperty ( kAppleKeySwitchProperty ) );
254
255	if ( shouldNotPoll != NULL )
256	{
257
258		// See if we should not poll.
259		require ( shouldNotPoll->isFalse ( ), Exit );
260
261	}
262
263	// Start polling
264	EnablePolling ( );
265
266
267Exit:
268
269	CreateStorageServiceNub ( );
270
271}
272
273
274//--------------------------------------------------------------------------------------------------
275//	SuspendDeviceSupport - Suspends device support										 [PROTECTED]
276//--------------------------------------------------------------------------------------------------
277
278void
279IOUSBMassStorageUFIDevice::SuspendDeviceSupport ( void )
280{
281	if( fPollingMode != kPollingMode_Suspended )
282	{
283    	DisablePolling();
284    }
285
286}
287
288
289//--------------------------------------------------------------------------------------------------
290//	ResumeDeviceSupport - Resumes device support										 [PROTECTED]
291//--------------------------------------------------------------------------------------------------
292
293void
294IOUSBMassStorageUFIDevice::ResumeDeviceSupport ( void )
295{
296	// The driver has not found media in the device, restart
297	// the polling for new media.
298	if( fMediumPresent == false )
299	{
300		fPollingMode = kPollingMode_NewMedia;
301
302	    EnablePolling();
303	}
304
305}
306
307
308//--------------------------------------------------------------------------------------------------
309//	StopDeviceSupport - Stops device support											 [PROTECTED]
310//--------------------------------------------------------------------------------------------------
311
312void
313IOUSBMassStorageUFIDevice::StopDeviceSupport ( void )
314{
315	// This is only here to keep the compiler happy since
316	// the method is pure virtual.  We don't need it for UFI.
317}
318
319
320//--------------------------------------------------------------------------------------------------
321//	TerminateDeviceSupport - Terminates device support									 [PROTECTED]
322//--------------------------------------------------------------------------------------------------
323
324void
325IOUSBMassStorageUFIDevice::TerminateDeviceSupport ( void )
326{
327    STATUS_LOG ( ( 6, "%s[%p]::cleanUp called.", getName(), this ) );
328
329    if ( fPollingThread != NULL )
330    {
331
332        thread_call_free ( fPollingThread );
333        fPollingThread = NULL;
334
335    }
336
337	if ( fIOUSBMassStorageUFIDeviceReserved != NULL)
338	{
339		IODelete ( fIOUSBMassStorageUFIDeviceReserved, IOUSBMassStorageUFIDeviceExpansionData, 1 );
340		fIOUSBMassStorageUFIDeviceReserved = NULL;
341	}
342}
343
344
345//--------------------------------------------------------------------------------------------------
346//	ClearNotReadyStatus - Clears any NOT_READY status on device							 [PROTECTED]
347//--------------------------------------------------------------------------------------------------
348
349bool
350IOUSBMassStorageUFIDevice::ClearNotReadyStatus( void )
351{
352	SCSI_Sense_Data				senseBuffer;
353	IOMemoryDescriptor *		bufferDesc;
354	SCSITaskIdentifier			request;
355	bool						driveReady = false;
356	bool						result = true;
357	SCSIServiceResponse 		serviceResponse = kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE;
358
359
360	STATUS_LOG ( ( 6, "%s[%p]::%s called", getName(), this,  __FUNCTION__ ) );
361
362	bufferDesc = IOMemoryDescriptor::withAddress (	( void * ) &senseBuffer,
363													kSenseDefaultSize,
364													kIODirectionIn );
365
366	request = GetSCSITask();
367	do
368	{
369
370		if ( TEST_UNIT_READY ( request ) == true )
371		{
372			// The command was successfully built, now send it
373			serviceResponse = SendCommand ( request, 0 );
374		}
375		else
376		{
377			PANIC_NOW( ( "IOUSBMassStorageUFIDevice::ClearNotReadyStatus malformed command" ) );
378		}
379
380		if ( serviceResponse == kSCSIServiceResponse_TASK_COMPLETE )
381		{
382
383			bool validSense = false;
384
385			if ( GetTaskStatus( request ) == kSCSITaskStatus_CHECK_CONDITION )
386			{
387
388				validSense = GetAutoSenseData( request, &senseBuffer );
389				if ( validSense == false )
390				{
391
392					if ( REQUEST_SENSE( request, bufferDesc, kSenseDefaultSize ) == true )
393					{
394						// The command was successfully built, now send it
395						serviceResponse = SendCommand ( request, 0 );
396					}
397					else
398					{
399						PANIC_NOW ( ( "IOUSBMassStorageUFIDevice::ClearNotReadyStatus malformed command" ) );
400					}
401
402					if ( serviceResponse == kSCSIServiceResponse_TASK_COMPLETE )
403					{
404						validSense = true;
405					}
406
407				}
408
409				if ( validSense == true )
410				{
411					if ( ( ( senseBuffer.SENSE_KEY  & kSENSE_KEY_Mask ) == kSENSE_KEY_NOT_READY  ) &&
412							( senseBuffer.ADDITIONAL_SENSE_CODE == 0x04 ) &&
413							( senseBuffer.ADDITIONAL_SENSE_CODE_QUALIFIER == 0x01 ) )
414					{
415
416						STATUS_LOG ( ( 5, "%s[%p]::drive not ready", getName(), this ) );
417						driveReady = false;
418						IOSleep ( 200 );
419
420					}
421					else if ( ( ( senseBuffer.SENSE_KEY  & kSENSE_KEY_Mask ) == kSENSE_KEY_NOT_READY  ) &&
422							( senseBuffer.ADDITIONAL_SENSE_CODE == 0x04 ) &&
423							( senseBuffer.ADDITIONAL_SENSE_CODE_QUALIFIER == 0x02 ) )
424					{
425						// The drive needs to be spun up. Issue a START_STOP_UNIT to it.
426						if ( START_STOP_UNIT( request, 0x00, 0x00, 0x01 ) == true )
427						{
428							serviceResponse = SendCommand( request, 0 );
429						}
430
431					}
432					else
433					{
434
435						driveReady = true;
436						STATUS_LOG ( (5, "%s[%p]::drive READY", getName(), this ) );
437
438					}
439
440					STATUS_LOG ( ( 5, "%s[%p]:: sense data: %01x, %02x, %02x", getName(), this,
441							   ( senseBuffer.SENSE_KEY  & kSENSE_KEY_Mask ),
442								senseBuffer.ADDITIONAL_SENSE_CODE,
443								senseBuffer.ADDITIONAL_SENSE_CODE_QUALIFIER ) );
444
445				}
446			}
447			else
448			{
449				driveReady = true;
450			}
451
452		}
453		else
454		{
455			// the command failed - perhaps the device was hot unplugged
456			// give other threads some time to run.
457			IOSleep( 200 );
458
459		}
460
461	// check isInactive in case device was hot unplugged during sleep
462	// and we are in an infinite loop here
463	} while( ( driveReady == false ) && ( isInactive() == false ) );
464
465	bufferDesc->release();
466	ReleaseSCSITask ( request );
467
468	result = isInactive() ? false : true;
469	return result;
470
471}
472
473
474//--------------------------------------------------------------------------------------------------
475//	EnablePolling - Schedules the polling thread to run									 [PROTECTED]
476//--------------------------------------------------------------------------------------------------
477
478void
479IOUSBMassStorageUFIDevice::EnablePolling( void )
480{
481    AbsoluteTime	time;
482
483    if ( ( fPollingMode != kPollingMode_Suspended ) &&
484			fPollingThread &&
485			( isInactive() == false ) )
486    {
487        // Retain ourselves so that this object doesn't go away
488        // while we are polling
489        retain();
490
491        clock_interval_to_deadline( 1000, kMillisecondScale, &time );
492
493		// Let's enqueue the polling.
494		if (thread_call_enter_delayed( fPollingThread, time ))
495		{
496			// The call was already enqueued therefore there already is
497			// a pending retain and we must release the last retain to
498			// maintain the proper balance: if we would not release it,
499			// the retain count would keep growing.
500			release();
501		}
502
503	}
504}
505
506
507//--------------------------------------------------------------------------------------------------
508//	DisablePolling - Unschedules the polling thread if it hasn't run yet				 [PROTECTED]
509//--------------------------------------------------------------------------------------------------
510
511void
512IOUSBMassStorageUFIDevice::DisablePolling( void )
513{
514	fPollingMode = kPollingMode_Suspended;
515
516	// Cancel the thread if it is scheduled
517	if( thread_call_cancel( fPollingThread ) )
518	{
519		// It was scheduled, so we balance out the retain()
520		// with a release()
521		release();
522
523	}
524}
525
526
527//--------------------------------------------------------------------------------------------------
528//	DetermineDeviceCharacteristics - Determines device characteristics					 [PROTECTED]
529//--------------------------------------------------------------------------------------------------
530
531bool
532IOUSBMassStorageUFIDevice::DetermineDeviceCharacteristics( void )
533{
534	SCSIServiceResponse 			serviceResponse = kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE;
535	SCSITaskIdentifier				request = NULL;
536	IOMemoryDescriptor *			bufferDesc = NULL;
537    SCSICmd_INQUIRY_StandardData * 	inquiryBuffer = NULL;
538    UInt8							inquiryBufferCount = sizeof ( SCSICmd_INQUIRY_StandardData );
539	bool							succeeded = false;
540	int								loopCount;
541	char							tempString [ kINQUIRY_PRODUCT_IDENTIFICATION_Length + 1 ]; // Maximum + 1 for null char
542	OSString *						string;
543
544
545	STATUS_LOG ( ( 6,  "%s[%p]::DetermineDeviceCharacteristics called", getName(), this ) );
546
547	inquiryBuffer = ( SCSICmd_INQUIRY_StandardData * ) IOMalloc ( inquiryBufferCount );
548	if( inquiryBuffer == NULL )
549	{
550
551		STATUS_LOG ( ( 1, "%s[%p]: Couldn't allocate Inquiry buffer.", getName(), this ) );
552		goto ErrorExit;
553
554	}
555
556	bufferDesc = IOMemoryDescriptor::withAddress ( inquiryBuffer, inquiryBufferCount, kIODirectionIn );
557	if ( bufferDesc == NULL )
558	{
559
560		STATUS_LOG ( ( 1, "%s[%p]: Couldn't alloc Inquiry buffer: ", getName(), this ) );
561		goto ErrorExit;
562
563	}
564
565	request = GetSCSITask();
566	if ( request == NULL )
567	{
568		goto ErrorExit;
569	}
570
571	if ( INQUIRY ( 	request,
572					bufferDesc,
573					0,
574					inquiryBufferCount ) == true )
575	{
576		// The command was successfully built, now send it
577		serviceResponse = SendCommand ( request, 0 );
578
579	}
580	else
581	{
582
583		PANIC_NOW ( ( "IOUSBMassStorageUFIDevice::DetermineDeviceCharacteristics malformed command" ) );
584		goto ErrorExit;
585
586	}
587
588	if ( ( serviceResponse != kSCSIServiceResponse_TASK_COMPLETE ) ||
589		( GetTaskStatus ( request ) != kSCSITaskStatus_GOOD ) )
590	{
591
592		STATUS_LOG ( ( 2, "%s[%p]: Inquiry completed with an error: ", getName(), this ) );
593		goto ErrorExit;
594
595	}
596
597   	// Set the Vendor Identification property for the device.
598   	for ( loopCount = 0; loopCount < kINQUIRY_VENDOR_IDENTIFICATION_Length; loopCount++ )
599   	{
600   		tempString[loopCount] = inquiryBuffer->VENDOR_IDENTIFICATION[loopCount];
601   	}
602
603	tempString[loopCount] = 0;
604
605   	for ( loopCount = kINQUIRY_VENDOR_IDENTIFICATION_Length - 1; loopCount >= 0; loopCount-- )
606   	{
607
608   		if ( tempString[loopCount] != ' ' )
609   		{
610   			// Found a real character
611   			tempString[loopCount+1] = '\0';
612   			break;
613
614   		}
615
616   	}
617
618	string = OSString::withCString ( tempString );
619	if ( string != NULL )
620	{
621
622		fDeviceCharacteristicsDictionary->setObject ( kIOPropertyVendorNameKey, string );
623		string->release();
624
625	}
626
627   	// Set the Product Indentification property for the device.
628   	for ( loopCount = 0; loopCount < kINQUIRY_PRODUCT_IDENTIFICATION_Length; loopCount++ )
629   	{
630   		tempString[loopCount] = inquiryBuffer->PRODUCT_IDENTIFICATION[loopCount];
631   	}
632   	tempString[loopCount] = 0;
633
634   	for ( loopCount = kINQUIRY_PRODUCT_IDENTIFICATION_Length - 1; loopCount >= 0; loopCount-- )
635   	{
636   		if ( tempString[loopCount] != ' ' )
637   		{
638   			// Found a real character
639   			tempString[loopCount+1] = '\0';
640   			break;
641
642   		}
643   	}
644
645	string = OSString::withCString ( tempString );
646	if ( string != NULL )
647	{
648
649		fDeviceCharacteristicsDictionary->setObject ( kIOPropertyProductNameKey, string );
650		string->release();
651
652	}
653
654   	// Set the Product Revision Level property for the device.
655   	for ( loopCount = 0; loopCount < kINQUIRY_PRODUCT_REVISION_LEVEL_Length; loopCount++ )
656   	{
657   		tempString[loopCount] = inquiryBuffer->PRODUCT_REVISION_LEVEL[loopCount];
658   	}
659
660   	tempString[loopCount] = 0;
661
662   	for ( loopCount = kINQUIRY_PRODUCT_REVISION_LEVEL_Length - 1; loopCount >= 0; loopCount-- )
663   	{
664		if ( tempString[loopCount] != ' ' )
665		{
666			// Found a real character
667			tempString[loopCount+1] = '\0';
668			break;
669
670		}
671	}
672
673	string = OSString::withCString ( tempString );
674	if ( string != NULL )
675	{
676
677		fDeviceCharacteristicsDictionary->setObject ( kIOPropertyProductRevisionLevelKey, string );
678		string->release();
679
680	}
681
682	succeeded = true;
683
684
685ErrorExit:
686
687
688	STATUS_LOG ( ( 6, "%s[%p]::DetermineDeviceCharacteristics exiting", getName(), this ) );
689
690	if ( request )
691	{
692		ReleaseSCSITask ( request );
693		request = NULL;
694	}
695
696	if ( bufferDesc )
697	{
698		bufferDesc->release();
699		bufferDesc = NULL;
700	}
701
702	if ( inquiryBuffer )
703	{
704		IOFree ( ( void * ) inquiryBuffer, inquiryBufferCount );
705		inquiryBuffer = NULL;
706	}
707
708	return succeeded;
709
710}
711
712
713//--------------------------------------------------------------------------------------------------
714//	SetMediumCharacteristics - Sets medium characteristics								 [PROTECTED]
715//--------------------------------------------------------------------------------------------------
716
717void
718IOUSBMassStorageUFIDevice::SetMediumCharacteristics( UInt32 blockSize, UInt32 blockCount )
719{
720
721    STATUS_LOG ( ( 6, "%s[%p]::SetMediumCharacteristics called", getName(), this ) );
722	STATUS_LOG ( ( 5, "%s[%p]::mediumBlockSize = %ld, blockCount = %ld", getName(), this, blockSize, blockCount ) );
723
724	fMediumBlockSize	= blockSize;
725	fMediumBlockCount	= blockCount;
726
727	STATUS_LOG ( ( 6, "%s[%p]::SetMediumCharacteristics exiting", getName(), this ) );
728
729}
730
731
732//--------------------------------------------------------------------------------------------------
733//	ResetMediumCharacteristics -	Resets medium characteristics to known values.		 [PROTECTED]
734//--------------------------------------------------------------------------------------------------
735
736void
737IOUSBMassStorageUFIDevice::ResetMediumCharacteristics ( void )
738{
739
740    STATUS_LOG ( ( 6, "%s[%p]::ResetMediumCharacteristics called", getName(), this ) );
741
742	fMediumBlockSize		= 0;
743	fMediumBlockCount		= 0;
744	fMediumPresent			= false;
745	fMediumIsWriteProtected = true;
746
747	STATUS_LOG ( ( 6, "%s[%p]::ResetMediumCharacteristics exiting", getName(), this ) );
748
749}
750
751
752//--------------------------------------------------------------------------------------------------
753//	CreateStorageServiceNub -	Creates the linkage object for IOStorageFamily to use.	 [PROTECTED]
754//--------------------------------------------------------------------------------------------------
755
756void
757IOUSBMassStorageUFIDevice::CreateStorageServiceNub ( void )
758{
759    STATUS_LOG ( ( 6, "%s[%p]::CreateStorageServiceNub entering.", getName(), this ) );
760
761	IOService * 	nub = OSTypeAlloc ( IOUFIStorageServices );
762	if ( nub == NULL )
763	{
764
765		STATUS_LOG ( ( 1, "%s[%p]::CreateStorageServiceNub failed", getName(), this ) );
766		PANIC_NOW ( ( "IOUSBMassStorageUFIDevice::CreateStorageServiceNub failed" ) );
767		return;
768
769	}
770
771	nub->init();
772
773	if ( !nub->attach( this ) )
774	{
775		// panic since the nub can't attach
776		PANIC_NOW ( ( "IOUSBMassStorageUFIDevice::CreateStorageServiceNub unable to attach nub" ) );
777		return;
778
779	}
780
781	nub->registerService(kIOServiceAsynchronous);
782	STATUS_LOG ( ( 6, "%s[%p]::CreateStorageServiceNub exiting.", getName(), this ) );
783
784	nub->release();
785}
786
787
788//--------------------------------------------------------------------------------------------------
789//	ProcessPoll - Processes a poll for media or media removal.							  PROTECTED]
790//--------------------------------------------------------------------------------------------------
791
792void
793IOUSBMassStorageUFIDevice::ProcessPoll ( void )
794{
795	switch ( fPollingMode )
796	{
797
798		case kPollingMode_NewMedia:
799		{
800			PollForNewMedia();
801		}
802		break;
803
804		case kPollingMode_MediaRemoval:
805		{
806			PollForMediaRemoval();
807		}
808		break;
809
810		default:
811		{
812			// This is an unknown polling mode -- do nothing.
813			STATUS_LOG ( ( 1, "%s[%p]:ProcessPoll Unknown polling mode.", getName(), this ) );
814		}
815		break;
816
817	}
818}
819
820
821//--------------------------------------------------------------------------------------------------
822//	PollForNewMedia - Polls for new media insertion.									 [PROTECTED]
823//--------------------------------------------------------------------------------------------------
824
825void
826IOUSBMassStorageUFIDevice::PollForNewMedia( void )
827{
828	bool						mediaFound = false;
829	UInt64						blockCount;
830	UInt64						blockSize;
831
832
833	// Since this is a poll for new media,
834	fMediumPresent	= false;
835
836	mediaFound = DetermineMediaPresence();
837	if ( mediaFound == false )
838	{
839		return;
840	}
841
842	if ( DetermineMediumCapacity ( &blockSize, &blockCount ) == false )
843	{
844		// Capacity could not be determined, treat it like no media inserted
845		// and try again.
846		return;
847	}
848
849	SetMediumCharacteristics ( blockSize, blockCount );
850
851	fMediumIsWriteProtected = DetermineMediumWriteProtectState();
852
853	fMediumPresent	= true;
854
855	// Message up the chain that we have media
856	messageClients ( kIOMessageMediaStateHasChanged,
857					 ( void * ) kIOMediaStateOnline,
858					 sizeof( IOMediaState ) );
859
860	// Media is not locked into the drive, so this is most likely
861	// a manually ejectable device, start polling for media removal.
862	fPollingMode = kPollingMode_MediaRemoval;
863}
864
865
866//--------------------------------------------------------------------------------------------------
867//	DetermineMediaPresence -	Checks if media has been inserted into the
868//								device. If medium is detected, this method
869//								will return true, else it will return false				 [PROTECTED]
870//--------------------------------------------------------------------------------------------------
871
872bool
873IOUSBMassStorageUFIDevice::DetermineMediaPresence ( void )
874{
875	SCSIServiceResponse			serviceResponse = kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE;
876	SCSITaskIdentifier			request = NULL;
877	bool						mediaFound = false;
878	OSBoolean *					keySwitchLocked = NULL;
879
880
881	STATUS_LOG ( ( 6, "%s[%p]::DetermineMediaPresence called", getName(), this ) );
882
883	keySwitchLocked = OSDynamicCast ( OSBoolean, getProperty ( kAppleKeySwitchProperty ) );
884
885	if ( keySwitchLocked != NULL )
886	{
887		// See if we should poll for media.
888		if ( keySwitchLocked->isTrue ( ) )
889		{
890			return false;
891		}
892	}
893
894	request = GetSCSITask();
895	if ( request == NULL )
896	{
897		return false;
898	}
899
900	// Do a TEST_UNIT_READY to generate sense data
901	if ( TEST_UNIT_READY ( request ) == true )
902    {
903    	// The command was successfully built, now send it, set timeout to 10 seconds.
904    	serviceResponse = SendCommand( request, 10 * 1000 );
905
906	}
907	else
908	{
909
910		STATUS_LOG ( ( 1, "%s[%p]::DetermineMediaPresence malformed command", getName(), this ) );
911		goto CheckDone;
912
913	}
914
915	if ( serviceResponse == kSCSIServiceResponse_TASK_COMPLETE )
916	{
917
918		bool					validSense;
919		SCSI_Sense_Data			senseBuffer;
920
921		// Check for valid Autosense data.  If it was not retrieved from the
922		// device, explicitly ask for it by sending a REQUEST SENSE command.
923		validSense = GetAutoSenseData ( request, &senseBuffer );
924		if ( validSense == false )
925		{
926			IOMemoryDescriptor *	bufferDesc;
927
928			bufferDesc = IOMemoryDescriptor::withAddress ( ( void * ) &senseBuffer,
929															kSenseDefaultSize,
930															kIODirectionIn );
931			if( bufferDesc == NULL )
932			{
933
934				STATUS_LOG ( ( 1, "%s[%p]: could not allocate sense buffer descriptor.", getName(), this ) );
935				goto CheckDone;
936
937			}
938
939			// Get the sense data to determine if media is present.
940			if ( REQUEST_SENSE( request, bufferDesc, kSenseDefaultSize ) == true )
941		    {
942		    	// The command was successfully built, now send it
943		    	serviceResponse = SendCommand( request, 0 );
944
945			}
946			else
947			{
948
949				STATUS_LOG ( ( 1, "%s[%p]::PollForMedia malformed command", getName(), this ) );
950				bufferDesc->release();
951				goto CheckDone;
952
953			}
954
955			bufferDesc->release();
956
957			if ( ( serviceResponse != kSCSIServiceResponse_TASK_COMPLETE ) ||
958	 			( GetTaskStatus ( request ) != kSCSITaskStatus_GOOD ) )
959	 		{
960
961				STATUS_LOG ( ( 2, "%s[%p]: REQUEST_SENSE failed", getName(), this ) );
962				goto CheckDone;
963
964	 		}
965
966		}
967
968		if ( ( senseBuffer.ADDITIONAL_SENSE_CODE == 0x04 ) &&
969			( senseBuffer.ADDITIONAL_SENSE_CODE_QUALIFIER == 0x02 ) )
970		{
971			// Since the device has indicated it needs a start, send it one
972			// and then reset the polling.
973			if ( START_STOP_UNIT( request, 0x00,0x00, 1 ) == true )
974		    {
975		    	// The command was successfully built, now send it, set timeout to 10 seconds.
976		    	serviceResponse = SendCommand( request, 0 );
977			}
978
979			goto CheckDone;
980
981		}
982		else if ( ( senseBuffer.ADDITIONAL_SENSE_CODE != 0x00 ) ||
983					( senseBuffer.ADDITIONAL_SENSE_CODE_QUALIFIER != 0x00 ) )
984		{
985
986			STATUS_LOG ( ( 2, "%s[%p]:: ASC = 0x%02x, ASCQ = 0x%02x",
987                            getName(),
988                            this,
989							senseBuffer.ADDITIONAL_SENSE_CODE,
990							senseBuffer.ADDITIONAL_SENSE_CODE_QUALIFIER ) );
991
992			goto CheckDone;
993
994		}
995
996	}
997	else
998	{
999
1000		STATUS_LOG ( ( 2, "%s[%p]:: serviceResponse = %d", getName(), this, serviceResponse ) );
1001		goto CheckDone;
1002
1003	}
1004
1005
1006	UInt8					formatBuffer[12];
1007	IOMemoryDescriptor *	formatDesc;
1008
1009	formatDesc = IOMemoryDescriptor::withAddress ( ( void * ) &formatBuffer[0],
1010													12,
1011													kIODirectionIn );
1012	if ( formatDesc == NULL )
1013	{
1014
1015		STATUS_LOG ( ( 1, "%s[%p]: could not allocate sense buffer descriptor.", getName(), this ) );
1016		goto CheckDone;
1017
1018	}
1019
1020	// If the check makes to to this point, then the TUR returned no errors,
1021	// now send the READ_FORMAT_CAPACITIES to determine is media is truly present.
1022	if ( READ_FORMAT_CAPACITIES ( request, formatDesc, 12 ) == true )
1023    {
1024    	// The command was successfully built, now send it
1025    	serviceResponse = SendCommand( request, 0 );
1026
1027	}
1028	else
1029	{
1030
1031		STATUS_LOG ( ( 1, "%s[%p]::PollForMedia malformed command", getName(), this ) ) ;
1032		formatDesc->release();
1033		goto CheckDone;
1034
1035	}
1036
1037	formatDesc->release();
1038
1039	if ( serviceResponse == kSCSIServiceResponse_TASK_COMPLETE )
1040	{
1041
1042		if ( GetTaskStatus ( request ) == kSCSITaskStatus_CHECK_CONDITION )
1043		{
1044
1045			bool					validSense;
1046			SCSI_Sense_Data			senseBuffer;
1047
1048
1049			validSense = GetAutoSenseData ( request, &senseBuffer );
1050			if ( validSense == false )
1051			{
1052
1053				IOMemoryDescriptor *	bufferDesc;
1054
1055
1056				bufferDesc = IOMemoryDescriptor::withAddress ( ( void * ) &senseBuffer,
1057																kSenseDefaultSize,
1058																kIODirectionIn );
1059				if( bufferDesc == NULL )
1060				{
1061
1062					STATUS_LOG ( ( 1, "%s[%p]: could not allocate sense buffer descriptor.", getName(), this ) );
1063					goto CheckDone;
1064
1065				}
1066
1067				// Get the sense data to determine if media is present.
1068				if ( REQUEST_SENSE ( request, bufferDesc, kSenseDefaultSize ) == true )
1069			    {
1070			    	// The command was successfully built, now send it
1071			    	serviceResponse = SendCommand( request, 0 );
1072
1073				}
1074				else
1075				{
1076
1077					STATUS_LOG ( ( 1, "%s[%p]::PollForMedia malformed command", getName(), this ) );
1078					bufferDesc->release();
1079					goto CheckDone;
1080
1081				}
1082
1083				bufferDesc->release();
1084
1085				// If the REQUEST SENSE comamnd fails to execute, exit and try the
1086				// poll again.
1087				if ( ( serviceResponse != kSCSIServiceResponse_TASK_COMPLETE ) ||
1088		 			( GetTaskStatus( request ) != kSCSITaskStatus_GOOD ) )
1089		 		{
1090
1091					STATUS_LOG ( ( 2, "%s[%p]: REQUEST_SENSE failed", getName(), this ) );
1092					goto CheckDone;
1093
1094		 		}
1095
1096			}
1097
1098			if ( ( ( senseBuffer.SENSE_KEY & kSENSE_KEY_Mask ) == kSENSE_KEY_ILLEGAL_REQUEST )
1099				&& ( senseBuffer.ADDITIONAL_SENSE_CODE == 0x20 ) )
1100			{
1101				// The device indicates that the READ_FORMAT_CAPACITIES command
1102				// is not supported.  Since the device has already returned a good
1103				// status to the TEST_UNIT_READY, report that media was found.
1104				mediaFound = true;
1105				goto CheckDone;
1106
1107			}
1108
1109		}
1110		else if ( GetTaskStatus( request ) != kSCSITaskStatus_GOOD )
1111		{
1112			goto CheckDone;
1113		}
1114	}
1115	else
1116	{
1117
1118		STATUS_LOG ( ( 2, "%s[%p]:: serviceResponse = %d", getName(), this, serviceResponse ) );
1119		goto CheckDone;
1120
1121	}
1122
1123	STATUS_LOG ( ( 4, "%s[%p]:: Formats data: ", getName(), this ) );
1124	for ( int i = 0; i < 12; i ++ )
1125	{
1126		STATUS_LOG ( ( 4, "%s[%p]:: %X : ", getName(), this, formatBuffer[i] ) );
1127	}
1128
1129	if ( formatBuffer[8] == 0x01 )
1130	{
1131
1132		STATUS_LOG ( ( 4, "%s[%p]: unformatted media was found.", getName(), this ) );
1133
1134		// There is unformatted media in the drive, until format support
1135		// is added, treat like no media is present.
1136		goto CheckDone;
1137
1138	}
1139	else if ( formatBuffer[8] != 0x02 )
1140	{
1141
1142		STATUS_LOG ( ( 5, "%s[%p]: no media was found.", getName(), this ) );
1143
1144		// There is no media in the drive, reset the poll.
1145		goto CheckDone;
1146
1147	}
1148
1149	STATUS_LOG ( ( 5, "%s[%p]: media was found.", getName(), this ) );
1150	// At this point, it has been determined that there is usable media
1151	// in the device.
1152	mediaFound = true;
1153
1154
1155CheckDone:
1156
1157	if( request != NULL )
1158	{
1159		ReleaseSCSITask( request );
1160		request = NULL;
1161	}
1162
1163	return mediaFound;
1164
1165}
1166
1167
1168//--------------------------------------------------------------------------------------------------
1169//	DetermineMediumCapacity -	Determines capacity of the medium. Returns true
1170//								if the capacity could be determined, else it
1171//								returns false.											 [PROTECTED]
1172//--------------------------------------------------------------------------------------------------
1173
1174bool
1175IOUSBMassStorageUFIDevice::DetermineMediumCapacity (	UInt64 * blockSize,
1176														UInt64 * blockCount )
1177{
1178	SCSIServiceResponse			serviceResponse = kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE;
1179	UInt32						capacityData[2];
1180	IOMemoryDescriptor *		bufferDesc		= NULL;
1181	SCSITaskIdentifier			request			= NULL;
1182	bool						result;
1183
1184
1185	*blockSize 	= 0;
1186	*blockCount = 0;
1187
1188	request = GetSCSITask();
1189	if ( request == NULL )
1190	{
1191
1192		result = false;
1193		goto IsDone;
1194
1195	}
1196
1197	bufferDesc = IOMemoryDescriptor::withAddress ( capacityData, 8, kIODirectionIn );
1198	if ( bufferDesc == NULL )
1199	{
1200
1201		result = false;
1202		goto IsDone;
1203
1204	}
1205
1206	// We found media, get its capacity
1207	if ( READ_CAPACITY ( request, bufferDesc, 0, 0x00, 0 ) == true )
1208    {
1209    	// The command was successfully built, now send it
1210    	serviceResponse = SendCommand( request, 0 );
1211
1212	}
1213	else
1214	{
1215
1216		STATUS_LOG ( ( 1, "%s[%p]::PollForMedia malformed command", getName(), this ) );
1217    	result = false;
1218    	goto IsDone;
1219
1220	}
1221
1222	if ( ( serviceResponse == kSCSIServiceResponse_TASK_COMPLETE ) &&
1223		 ( GetTaskStatus( request ) == kSCSITaskStatus_GOOD ) )
1224	{
1225
1226		*blockSize 	= ( UInt64 ) OSSwapBigToHostInt32 ( capacityData[1] );
1227		*blockCount = ( UInt64 ) ( OSSwapBigToHostInt32 ( capacityData[0] ) + 1 );
1228		STATUS_LOG ( ( 4, "%s[%p]: Media capacity: %lx and block size: %lx",
1229						getName(), this, ( UInt32 ) *blockCount, ( UInt32 ) *blockSize ) );
1230		result = true;
1231
1232	}
1233	else
1234	{
1235
1236		STATUS_LOG ( ( 2, "%s[%p]: Read Capacity failed", getName(), this ) );
1237    	result = false;
1238
1239	}
1240
1241
1242IsDone:
1243
1244	if ( request != NULL )
1245	{
1246		ReleaseSCSITask ( request );
1247	}
1248
1249	if ( bufferDesc != NULL )
1250	{
1251		bufferDesc->release();
1252	}
1253
1254	return result;
1255
1256}
1257
1258
1259//--------------------------------------------------------------------------------------------------
1260//	DetermineMediumWriteProtectState -	Determines medium write protect state.			 [PROTECTED]
1261//--------------------------------------------------------------------------------------------------
1262
1263bool
1264IOUSBMassStorageUFIDevice::DetermineMediumWriteProtectState( void )
1265{
1266	SCSIServiceResponse 	serviceResponse = kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE;
1267	UInt8					modeBuffer[72];
1268	IOMemoryDescriptor *	bufferDesc = NULL;
1269	SCSITaskIdentifier		request = NULL;
1270	bool					mediumIsProtected = true;
1271
1272
1273	STATUS_LOG ( ( 6, "%s[%p]::checkWriteProtection called", getName(), this ) );
1274
1275	request = GetSCSITask();
1276	if ( request == NULL )
1277	{
1278		// Since a SCSI Task could not be gotten, do the safe thing and report
1279		// the medium as write protected.
1280		return true;
1281	}
1282
1283	bufferDesc = IOMemoryDescriptor::withAddress ( 	modeBuffer,
1284													72,
1285													kIODirectionIn );
1286
1287	if ( bufferDesc == NULL )
1288	{
1289		// Since the Mode Sense data buffer descriptor could not be allocated,
1290		// the command cannot be sent to the drive, exit and report the medium
1291		// as write protected.
1292		goto WriteProtectCheckDone;
1293	}
1294
1295	if ( MODE_SENSE_10 ( 	request,
1296							bufferDesc,
1297							0,
1298							0,
1299							0x3F,
1300							72 ) == true )
1301    {
1302    	// The command was successfully built, now send it
1303    	serviceResponse = SendCommand ( request, 0 );
1304
1305	}
1306	else
1307	{
1308
1309		STATUS_LOG ( ( 1, "%s[%p]::CheckWriteProtection malformed command", getName(), this ) );
1310		goto WriteProtectCheckDone;
1311
1312	}
1313
1314	if ( ( serviceResponse == kSCSIServiceResponse_TASK_COMPLETE ) &&
1315		 ( GetTaskStatus( request ) == kSCSITaskStatus_GOOD ) )
1316	{
1317
1318		if ( ( modeBuffer[3] & 0x80 ) != 0 )
1319		{
1320		 	mediumIsProtected = true;
1321		}
1322		else
1323		{
1324			mediumIsProtected = false;
1325		}
1326
1327	}
1328
1329
1330WriteProtectCheckDone:
1331
1332	if ( bufferDesc != NULL )
1333	{
1334		bufferDesc->release();
1335		bufferDesc = NULL;
1336	}
1337
1338	if ( request != NULL )
1339	{
1340		ReleaseSCSITask ( request );
1341		request = NULL;
1342	}
1343
1344	return mediumIsProtected;
1345}
1346
1347
1348//--------------------------------------------------------------------------------------------------
1349//	PollForMediaRemoval - Polls for media removal.										 [PROTECTED]
1350//--------------------------------------------------------------------------------------------------
1351
1352void
1353IOUSBMassStorageUFIDevice::PollForMediaRemoval ( void )
1354{
1355	SCSIServiceResponse			serviceResponse= kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE;
1356	SCSITaskIdentifier			request = NULL;
1357	bool						mediaRemoved = false;
1358
1359
1360	if ( isInactive() == true )
1361	{
1362		fPollingMode = kPollingMode_Suspended;
1363	}
1364
1365	request = GetSCSITask();
1366	if ( request == NULL )
1367	{
1368		// A SCSI Task could not be gotten, return immediately.
1369		goto Exit;
1370	}
1371
1372	// Do a TEST_UNIT_READY to generate sense data
1373	if ( TEST_UNIT_READY ( request ) == true )
1374    {
1375    	// The command was successfully built, now send it
1376    	serviceResponse = SendCommand( request, 0 );
1377
1378	}
1379	else
1380	{
1381
1382		PANIC_NOW ( ( "IOUSBMassStorageUFIDevice::PollForMediaRemoval malformed command" ) );
1383		goto RemoveCheckDone;
1384
1385	}
1386
1387	if ( serviceResponse == kSCSIServiceResponse_TASK_COMPLETE )
1388	{
1389
1390		bool						validSense;
1391		SCSI_Sense_Data				senseBuffer;
1392		IOMemoryDescriptor *		bufferDesc;
1393
1394
1395		// Check for valid Autosense data.  If it was not retrieved from the
1396		// device, explicitly ask for it by sending a REQUEST SENSE command.
1397		validSense = GetAutoSenseData ( request, &senseBuffer );
1398		if( validSense == false )
1399		{
1400
1401			bufferDesc = IOMemoryDescriptor::withAddress ( ( void * ) &senseBuffer,
1402															kSenseDefaultSize,
1403															kIODirectionIn );
1404			if ( bufferDesc == NULL )
1405			{
1406
1407				STATUS_LOG ( ( 1, "%s[%p]: could not allocate sense buffer descriptor.", getName(), this ) );
1408				goto RemoveCheckDone;
1409
1410			}
1411
1412			if ( REQUEST_SENSE( request, bufferDesc, kSenseDefaultSize ) == true )
1413		    {
1414		    	// The command was successfully built, now send it
1415		    	serviceResponse = SendCommand( request, 0 );
1416
1417			}
1418			else
1419			{
1420
1421				PANIC_NOW ( ( "IOUSBMassStorageUFIDevice::PollForMediaRemoval malformed command" ) );
1422				bufferDesc->release();
1423				goto RemoveCheckDone;
1424
1425			}
1426
1427			bufferDesc->release();
1428
1429			if ( ( serviceResponse != kSCSIServiceResponse_TASK_COMPLETE ) ||
1430	 			( GetTaskStatus( request ) != kSCSITaskStatus_GOOD ) )
1431	 		{
1432
1433				STATUS_LOG ( ( 2, "%s[%p]: REQUEST_SENSE failed", getName(), this ) );
1434				goto RemoveCheckDone;
1435
1436	 		}
1437
1438		}
1439
1440		if ( ( senseBuffer.ADDITIONAL_SENSE_CODE == 0x28 ) ||
1441			( senseBuffer.ADDITIONAL_SENSE_CODE == 0x3A ) )
1442		{
1443			// It has been determined that media has been removed, clean up and
1444			// exit.
1445			mediaRemoved = true;
1446
1447		}
1448
1449	}
1450
1451
1452RemoveCheckDone:
1453
1454	if ( request != NULL )
1455	{
1456
1457		ReleaseSCSITask( request );
1458		request = NULL;
1459
1460	}
1461	if ( mediaRemoved == true )
1462	{
1463		// Media was removed, set the polling to determine when new media has been inserted
1464 		fPollingMode = kPollingMode_NewMedia;
1465
1466		// Message up the chain that we do not have media
1467		messageClients( kIOMessageMediaStateHasChanged,
1468						( void * ) kIOMediaStateOffline );
1469
1470	}
1471
1472Exit:
1473
1474	return;
1475}
1476
1477
1478#pragma mark -
1479#pragma mark *** Power Management ***
1480#pragma mark -
1481
1482
1483//--------------------------------------------------------------------------------------------------
1484//	GetNumberOfPowerStateTransitions -	Asks the driver for the number of state transitions between
1485//										sleep state and the highest power state.
1486//																						 [PROTECTED]
1487//--------------------------------------------------------------------------------------------------
1488
1489UInt32
1490IOUSBMassStorageUFIDevice::GetNumberOfPowerStateTransitions ( void )
1491{
1492	// The number of transitions is the number of states - 1
1493	return ( kIOUSBMassStorageUFIDeviceNumPowerStates - 1 );
1494}
1495
1496
1497//--------------------------------------------------------------------------------------------------
1498// InitializePowerManagement - 		Register the driver with our policy-maker (in the same class).
1499//																						 [PROTECTED]
1500//--------------------------------------------------------------------------------------------------
1501
1502void
1503IOUSBMassStorageUFIDevice::InitializePowerManagement (
1504											IOService * provider )
1505{
1506	fCurrentPowerState = kIOUSBMassStorageUFIDevicePowerStateActive;
1507	fProposedPowerState	= kIOUSBMassStorageUFIDevicePowerStateActive;
1508
1509	// Call our super to get us into the power management tree
1510	super::InitializePowerManagement ( provider );
1511
1512	// Register ourselves as a "policy maker" for this device. We use
1513	// the number of default power states defined by RBC.
1514	registerPowerDriver ( this, sPowerStates, kIOUSBMassStorageUFIDeviceNumPowerStates );
1515
1516	// Make sure we clamp the lowest power setting that we voluntarily go
1517	// We only enter kIOUSBMassStorageUFIDevicePowerStateSleep if told by the
1518	// power manager during a system sleep.
1519    changePowerStateTo ( kIOUSBMassStorageUFIDevicePowerStateActive );
1520
1521}
1522
1523
1524//--------------------------------------------------------------------------------------------------
1525//	GetInitialPowerState -	Asks the driver which power state the device is in at startup time. This
1526//							function is only called	once, right after InitializePowerManagement().
1527//																						 [PROTECTED]
1528//--------------------------------------------------------------------------------------------------
1529
1530UInt32
1531IOUSBMassStorageUFIDevice::GetInitialPowerState ( void )
1532{
1533	return kIOUSBMassStorageUFIDevicePowerStateActive;
1534}
1535
1536
1537//--------------------------------------------------------------------------------------------------
1538//	HandleCheckPowerState - Checks to see if the power state is	"ACTIVE"				 [PROTECTED]
1539//--------------------------------------------------------------------------------------------------
1540
1541void
1542IOUSBMassStorageUFIDevice::HandleCheckPowerState ( void )
1543{
1544
1545	if ( IsDeviceAccessEnabled ( ) )
1546	{
1547
1548		super::HandleCheckPowerState ( kIOUSBMassStorageUFIDevicePowerStateActive );
1549
1550	}
1551
1552}
1553
1554
1555//--------------------------------------------------------------------------------------------------
1556//	TicklePowerManager - Calls activityTickle to tell the power manager we need to be in a certain
1557//						 state to fulfill I/O.											 [PROTECTED]
1558//--------------------------------------------------------------------------------------------------
1559
1560void
1561IOUSBMassStorageUFIDevice::TicklePowerManager ( void )
1562{
1563
1564	// Tell the power manager we must be in active state to handle requests
1565	// "active" state means the minimal possible state in which the driver can
1566	// handle I/O. This may be set to standby, but there is no gain to setting
1567	// the drive to standby and then issuing an I/O, it just requires more time.
1568	// Also, if the drive was asleep, it might need a reset which could put it
1569	// in standby mode anyway, so we usually request the max state from the power
1570	// manager
1571	( void ) super::TicklePowerManager ( kIOUSBMassStorageUFIDevicePowerStateActive );
1572
1573}
1574
1575
1576//--------------------------------------------------------------------------------------------------
1577//	HandlePowerChange - Checks to see if the power state is	"ACTIVE"					 [PROTECTED]
1578//--------------------------------------------------------------------------------------------------
1579
1580void
1581IOUSBMassStorageUFIDevice::HandlePowerChange ( void )
1582{
1583
1584	STATUS_LOG ( ( 5, "IOUSBMassStorageUFIDevice::HandlePowerChange called\n" ) );
1585
1586	// Avoid changing power state to lower state when a restart is in progress.
1587	if ( gRestartShutdownFlag != 0 )
1588	{
1589
1590		if ( fProposedPowerState <= kIOUSBMassStorageUFIDevicePowerStateSleep )
1591		{
1592
1593			fCurrentPowerState = fProposedPowerState;
1594
1595		}
1596
1597	}
1598
1599	if ( ( fProposedPowerState != fCurrentPowerState ) &&
1600			( isInactive ( ) == false ) )
1601	{
1602
1603		switch ( fProposedPowerState )
1604		{
1605
1606			case kIOUSBMassStorageUFIDevicePowerStateSleep:
1607			{
1608
1609				STATUS_LOG ( ( 5, "case kIOUSBMassStorageUFIDevicePowerStateSleep\n" ) );
1610
1611				DisablePolling();
1612
1613				fCurrentPowerState = kIOUSBMassStorageUFIDevicePowerStateSleep;
1614
1615			}
1616			break;
1617
1618			case kIOUSBMassStorageUFIDevicePowerStateActive:
1619			{
1620
1621				STATUS_LOG ( ( 5, "case kIOUSBMassStorageUFIDevicePowerStateActive\n" ) );
1622
1623				fCurrentPowerState = kIOUSBMassStorageUFIDevicePowerStateActive;
1624
1625				if (fMediumPresent == true)
1626				{
1627
1628					// We preserve the state since we already have the media connected
1629					fPollingMode = kPollingMode_MediaRemoval;
1630
1631				}
1632				else
1633				{
1634
1635					fPollingMode = kPollingMode_NewMedia;
1636
1637				}
1638
1639				EnablePolling();
1640
1641			}
1642			break;
1643
1644			default:
1645			{
1646
1647				PANIC_NOW ( ( "Undefined power state issued\n" ) );
1648
1649			}
1650			break;
1651
1652		}
1653
1654	}
1655
1656	if ( isInactive ( ) )
1657	{
1658
1659		fCurrentPowerState = fProposedPowerState;
1660
1661	}
1662
1663}
1664
1665
1666#pragma mark -
1667#pragma mark *** Client Requests Support ***
1668#pragma mark -
1669
1670
1671
1672//--------------------------------------------------------------------------------------------------
1673//	IssueRead - Performs the Synchronous Read Request									 [PROTECTED]
1674//--------------------------------------------------------------------------------------------------
1675
1676IOReturn
1677IOUSBMassStorageUFIDevice::IssueRead ( 	IOMemoryDescriptor *	buffer,
1678										UInt64					startBlock,
1679										UInt64					blockCount )
1680{
1681
1682	SCSIServiceResponse 	serviceResponse = kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE;
1683	SCSITaskIdentifier		request;
1684
1685
1686	STATUS_LOG ( ( 6, "%s[%p]: syncRead Attempted", getName(), this ) );
1687
1688	request = GetSCSITask ( );
1689
1690	if ( READ_10 ( 	request,
1691					buffer,
1692  					fMediumBlockSize,
1693					0,
1694					0,
1695					0,
1696					( SCSICmdField4Byte ) startBlock,
1697					( SCSICmdField2Byte ) blockCount ) == false )
1698    {
1699
1700    	// The command was successfully built, now send it
1701    	serviceResponse = SendCommand( request, 0 );
1702
1703	}
1704	else
1705	{
1706
1707		PANIC_NOW(( "IOUSBMassStorageUFIDevice::IssueRead malformed command" ) );
1708
1709	}
1710
1711	ReleaseSCSITask ( request );
1712
1713	if ( serviceResponse == kSCSIServiceResponse_TASK_COMPLETE )
1714	{
1715
1716		return kIOReturnSuccess;
1717
1718	}
1719	else
1720	{
1721
1722		return kIOReturnError;
1723
1724	}
1725
1726}
1727
1728
1729//--------------------------------------------------------------------------------------------------
1730//	IssueRead - Performs the Asynchronous Read Request									 [PROTECTED]
1731//--------------------------------------------------------------------------------------------------
1732
1733IOReturn
1734IOUSBMassStorageUFIDevice::IssueRead ( 	IOMemoryDescriptor *	buffer,
1735										UInt64					startBlock,
1736										UInt64					blockCount,
1737										void *					clientData )
1738{
1739
1740	IOReturn 				status = kIOReturnSuccess;
1741	SCSITaskIdentifier		request;
1742
1743
1744	STATUS_LOG ( ( 6, "%s[%p]: asyncRead Attempted", getName(), this ) );
1745
1746	request = GetSCSITask();
1747
1748	if (READ_10(	request,
1749					buffer,
1750      				fMediumBlockSize,
1751					0,
1752					0,
1753					0,
1754					( SCSICmdField4Byte ) startBlock,
1755					( SCSICmdField2Byte ) blockCount ) == true )
1756    {
1757
1758    	// The command was successfully built, now send it
1759    	SetApplicationLayerReference( request, clientData );
1760		STATUS_LOG ( ( 6, "%s[%p]::IssueRead send command.", getName(), this ) );
1761    	SendCommand( request, 0, &this->AsyncReadWriteComplete );
1762
1763	}
1764	else
1765	{
1766
1767		PANIC_NOW(( "IOUSBMassStorageUFIDevice::IssueWrite malformed command" ) );
1768		status = kIOReturnError;
1769
1770	}
1771
1772	return status;
1773}
1774
1775
1776//--------------------------------------------------------------------------------------------------
1777//	IssueWrite - Performs the Synchronous Write Request									 [PROTECTED]
1778//--------------------------------------------------------------------------------------------------
1779
1780IOReturn
1781IOUSBMassStorageUFIDevice::IssueWrite ( IOMemoryDescriptor *	buffer,
1782										UInt64					startBlock,
1783										UInt64					blockCount )
1784{
1785
1786	SCSIServiceResponse 	serviceResponse = kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE;
1787	SCSITaskIdentifier		request;
1788
1789
1790	STATUS_LOG ( ( 6, "%s[%p]: syncWrite Attempted", getName(), this ) );
1791
1792	request = GetSCSITask();
1793	if ( WRITE_10 ( request,
1794					buffer,
1795					fMediumBlockSize,
1796					0,
1797					0,
1798					0,
1799					( SCSICmdField4Byte ) startBlock,
1800					( SCSICmdField2Byte ) blockCount ) == true )
1801    {
1802    	// The command was successfully built, now send it
1803    	serviceResponse = SendCommand( request, 0 );
1804
1805	}
1806	else
1807	{
1808		PANIC_NOW ( ( "IOUSBMassStorageUFIDevice::IssueWrite malformed command" ) );
1809	}
1810
1811	ReleaseSCSITask ( request );
1812
1813	if ( serviceResponse == kSCSIServiceResponse_TASK_COMPLETE )
1814	{
1815		return kIOReturnSuccess;
1816	}
1817	else
1818	{
1819		return kIOReturnError;
1820	}
1821
1822}
1823
1824
1825//--------------------------------------------------------------------------------------------------
1826//	IssueWrite - Performs the Asynchronous Write Request								 [PROTECTED]
1827//--------------------------------------------------------------------------------------------------
1828
1829IOReturn
1830IOUSBMassStorageUFIDevice::IssueWrite (	IOMemoryDescriptor *	buffer,
1831										UInt64					startBlock,
1832										UInt64					blockCount,
1833										void *					clientData )
1834{
1835
1836	IOReturn				status = kIOReturnSuccess;
1837	SCSITaskIdentifier		request;
1838
1839
1840	STATUS_LOG ( ( 6, "%s[%p]:: asyncWrite Attempted", getName(), this ) );
1841
1842	request = GetSCSITask();
1843
1844	if ( WRITE_10 ( request,
1845					buffer,
1846   					fMediumBlockSize,
1847					0,
1848					0,
1849					0,
1850					( SCSICmdField4Byte ) startBlock,
1851					( SCSICmdField2Byte ) blockCount ) == true )
1852    {
1853    	// The command was successfully built, now send it
1854    	SetApplicationLayerReference ( request, clientData );
1855		STATUS_LOG ( ( 6, "%s[%p]::IssueWrite send command.", getName(), this ) );
1856    	SendCommand ( request, 0, &this->AsyncReadWriteComplete );
1857
1858	}
1859	else
1860	{
1861		PANIC_NOW ( ( "IOUSBMassStorageUFIDevice::IssueWrite malformed command" ) );
1862	}
1863
1864	return status;
1865
1866}
1867
1868
1869//--------------------------------------------------------------------------------------------------
1870//	SyncReadWrite - 	Translates a synchronous I/O request into a	read or a write.		[PUBLIC]
1871//--------------------------------------------------------------------------------------------------
1872
1873IOReturn
1874IOUSBMassStorageUFIDevice::SyncReadWrite ( 	IOMemoryDescriptor *	buffer,
1875											UInt64					startBlock,
1876											UInt64					blockCount,
1877                         					UInt64					blockSize )
1878{
1879
1880	UNUSED ( blockSize );
1881
1882	IODirection		direction;
1883	IOReturn		theErr;
1884
1885
1886	direction = buffer->getDirection();
1887
1888	if ( direction == kIODirectionIn )
1889	{
1890		theErr = IssueRead( buffer, startBlock, blockCount );
1891	}
1892	else if ( direction == kIODirectionOut )
1893	{
1894		theErr = IssueWrite( buffer, startBlock, blockCount );
1895	}
1896	else
1897	{
1898
1899		STATUS_LOG ( ( 1, "%s[%p]: doSyncReadWrite bad direction argument", getName(), this ) );
1900		theErr = kIOReturnBadArgument;
1901
1902	}
1903
1904	return theErr;
1905
1906}
1907
1908
1909//--------------------------------------------------------------------------------------------------
1910//	AsyncReadWrite - 	Translates a asynchronous I/O request into a read or a write.		[PUBLIC]
1911//--------------------------------------------------------------------------------------------------
1912
1913IOReturn
1914IOUSBMassStorageUFIDevice::AsyncReadWrite (	IOMemoryDescriptor *	buffer,
1915											UInt64					startBlock,
1916											UInt64					blockCount,
1917                         					UInt64					blockSize,
1918											void *					clientData )
1919{
1920
1921	UNUSED ( blockSize );
1922
1923
1924	IODirection		direction;
1925	IOReturn		theErr;
1926
1927
1928	direction = buffer->getDirection();
1929	if ( direction == kIODirectionIn )
1930	{
1931
1932		IssueRead( buffer, startBlock, blockCount, clientData );
1933		theErr = kIOReturnSuccess;
1934
1935	}
1936	else if ( direction == kIODirectionOut )
1937	{
1938
1939		IssueWrite( buffer, startBlock, blockCount, clientData );
1940		theErr = kIOReturnSuccess;
1941
1942	}
1943	else
1944	{
1945
1946		STATUS_LOG ( ( 1, "%s[%p]: doAsyncReadWrite bad direction argument", getName(), this ) );
1947		theErr = kIOReturnBadArgument;
1948
1949	}
1950
1951	return theErr;
1952
1953}
1954
1955
1956//--------------------------------------------------------------------------------------------------
1957//	EjectTheMedium - Changes the polling mode to poll for medium removal.					[PUBLIC]
1958//--------------------------------------------------------------------------------------------------
1959
1960IOReturn
1961IOUSBMassStorageUFIDevice::EjectTheMedium ( void )
1962{
1963
1964    STATUS_LOG ( ( 6, "%s[%p]::EjectTheMedium called", getName(), this ) );
1965
1966	ResetMediumCharacteristics();
1967
1968	// Set the polling to determine when media has been removed
1969	if ( fPollingMode != kPollingMode_MediaRemoval )
1970	{
1971
1972		fPollingMode = kPollingMode_MediaRemoval;
1973
1974		EnablePolling();
1975
1976	}
1977
1978	return kIOReturnSuccess;
1979
1980}
1981
1982
1983//--------------------------------------------------------------------------------------------------
1984//	FormatMedium -	Currently does nothing.						   							[PUBLIC]
1985//--------------------------------------------------------------------------------------------------
1986
1987IOReturn
1988IOUSBMassStorageUFIDevice::FormatMedium ( UInt64 blockCount, UInt64 blockSize )
1989{
1990
1991	UNUSED ( blockCount );
1992	UNUSED ( blockSize );
1993
1994	IOReturn	theErr = kIOReturnSuccess;
1995
1996    STATUS_LOG ( ( 6, "%s[%p]::FormatMedium called", getName(), this ) );
1997
1998	return theErr;
1999
2000}
2001
2002
2003//--------------------------------------------------------------------------------------------------
2004//	GetFormatCapacities - Currently does nothing.					   [					 PUBLIC]
2005//--------------------------------------------------------------------------------------------------
2006
2007UInt32
2008IOUSBMassStorageUFIDevice::GetFormatCapacities(	UInt64 * capacities,
2009												UInt32   capacitiesMaxCount ) const
2010{
2011
2012	UNUSED ( capacities );
2013	UNUSED ( capacitiesMaxCount );
2014
2015    STATUS_LOG ( ( 6, "%s[%p]::doGetFormatCapacities called", getName(), this ) );
2016
2017	return 0;
2018
2019}
2020
2021
2022#pragma mark -
2023#pragma mark *** Device Information Retrieval Methods ***
2024#pragma mark -
2025
2026
2027//--------------------------------------------------------------------------------------------------
2028//	GetVendorString - Returns the vendor string.					   						[PUBLIC]
2029//--------------------------------------------------------------------------------------------------
2030
2031char *
2032IOUSBMassStorageUFIDevice::GetVendorString ( void )
2033{
2034
2035	OSString *		vendorString;
2036
2037	STATUS_LOG ( ( 6, "%s[%p]::%s", getName(), this, __FUNCTION__ ) );
2038
2039	vendorString = ( OSString * ) fDeviceCharacteristicsDictionary->getObject( kIOPropertyVendorNameKey );
2040	if ( vendorString != NULL )
2041	{
2042		return ( ( char * ) vendorString->getCStringNoCopy ( ) );
2043	}
2044	else
2045	{
2046		return ( char * ) "NULL STRING";
2047	}
2048
2049}
2050
2051
2052//--------------------------------------------------------------------------------------------------
2053//	GetProductString - Returns the Product String.											[PUBLIC]
2054//--------------------------------------------------------------------------------------------------
2055
2056char *
2057IOUSBMassStorageUFIDevice::GetProductString ( void )
2058{
2059
2060	OSString *		productString;
2061
2062
2063	STATUS_LOG ( ( 6, "%s[%p]::%s", getName(), this, __FUNCTION__ ) );
2064
2065	productString = ( OSString * ) fDeviceCharacteristicsDictionary->getObject ( kIOPropertyProductNameKey );
2066	if ( productString != NULL )
2067	{
2068		return ( ( char * ) productString->getCStringNoCopy ( ) );
2069	}
2070	else
2071	{
2072		return ( char * ) "NULL STRING";
2073	}
2074
2075}
2076
2077
2078//--------------------------------------------------------------------------------------------------
2079//	GetRevisionString - Returns the Revision String.				   						[PUBLIC]
2080//--------------------------------------------------------------------------------------------------
2081
2082char *
2083IOUSBMassStorageUFIDevice::GetRevisionString ( void )
2084{
2085
2086	OSString *		revisionString;
2087
2088
2089	STATUS_LOG ( ( 6, "%s[%p]::%s", getName(), this, __FUNCTION__ ) );
2090
2091	revisionString = ( OSString * ) fDeviceCharacteristicsDictionary->getObject ( kIOPropertyProductRevisionLevelKey );
2092	if ( revisionString )
2093	{
2094		return ( ( char * ) revisionString->getCStringNoCopy ( ) );
2095	}
2096	else
2097	{
2098		return ( char * ) "NULL STRING";
2099	}
2100
2101}
2102
2103
2104//--------------------------------------------------------------------------------------------------
2105//	GetProtocolCharacteristicsDictionary - Returns the Protocol Characteristics Dictionary.	[PUBLIC]
2106//--------------------------------------------------------------------------------------------------
2107
2108OSDictionary *
2109IOUSBMassStorageUFIDevice::GetProtocolCharacteristicsDictionary ( void )
2110{
2111
2112	STATUS_LOG ( ( 6, "%s[%p]::%s", getName(), this, __FUNCTION__ ) );
2113	return ( OSDictionary * ) getProperty( kIOPropertyProtocolCharacteristicsKey );
2114
2115}
2116
2117
2118//--------------------------------------------------------------------------------------------------
2119//	GetDeviceCharacteristicsDictionary - Returns the Device Characteristics Dictionary.		[PUBLIC]
2120//--------------------------------------------------------------------------------------------------
2121
2122OSDictionary *
2123IOUSBMassStorageUFIDevice::GetDeviceCharacteristicsDictionary ( void )
2124{
2125
2126	STATUS_LOG ( ( 6, "%s[%p]::%s", getName(), this, __FUNCTION__ ) );
2127	return fDeviceCharacteristicsDictionary;
2128
2129}
2130
2131
2132#pragma mark -
2133#pragma mark *** Query methods to report device characteristics ***
2134#pragma mark -
2135
2136
2137//--------------------------------------------------------------------------------------------------
2138//	ReportDeviceMaxBlocksReadTransfer -	Reports max number of blocks a device can handle per read.
2139//																	   						[PUBLIC]
2140//--------------------------------------------------------------------------------------------------
2141
2142UInt64
2143IOUSBMassStorageUFIDevice::ReportDeviceMaxBlocksReadTransfer ( void )
2144{
2145
2146	UInt64	maxBlockCount;
2147
2148
2149    STATUS_LOG ( ( 6, "%s[%p]::%s", getName(), this, __FUNCTION__ ) );
2150
2151	maxBlockCount = 256;
2152
2153	return maxBlockCount;
2154
2155}
2156
2157
2158//--------------------------------------------------------------------------------------------------
2159//	ReportDeviceMaxBlocksWriteTransfer - Reports max number of blocks a device can handle per write.
2160//																	   						[PUBLIC]
2161//--------------------------------------------------------------------------------------------------
2162
2163UInt64
2164IOUSBMassStorageUFIDevice::ReportDeviceMaxBlocksWriteTransfer ( void )
2165{
2166
2167	UInt64	maxBlockCount;
2168
2169
2170    STATUS_LOG ( ( 6, "%s[%p]::%s", getName(), this, __FUNCTION__ ) );
2171
2172	maxBlockCount = 256;
2173
2174	return maxBlockCount;
2175
2176}
2177
2178
2179#pragma mark -
2180#pragma mark *** Query methods to report installed medium characteristics ***
2181#pragma mark -
2182
2183//--------------------------------------------------------------------------------------------------
2184//	ReportMediumBlockSize -	Reports the medium block size.		   							[PUBLIC]
2185//--------------------------------------------------------------------------------------------------
2186
2187UInt64
2188IOUSBMassStorageUFIDevice::ReportMediumBlockSize ( void )
2189{
2190
2191    STATUS_LOG ( ( 5, "%s[%p]::ReportMediumBlockSize blockSize = %ld", getName(), this, ( UInt32 ) fMediumBlockSize ) );
2192	return fMediumBlockSize;
2193
2194}
2195
2196
2197//--------------------------------------------------------------------------------------------------
2198//	ReportMediumTotalBlockCount -	Reports the number of blocks on the medium				[PUBLIC]
2199//--------------------------------------------------------------------------------------------------
2200
2201UInt64
2202IOUSBMassStorageUFIDevice::ReportMediumTotalBlockCount ( void )
2203{
2204
2205    STATUS_LOG ( ( 5, "%s[%p]::ReportMediumTotalBlockCount maxBlock = %ld", getName(), this, fMediumBlockCount ) );
2206	return fMediumBlockCount;
2207
2208}
2209
2210
2211//--------------------------------------------------------------------------------------------------
2212//	ReportMediumWriteProtection -	Reports whether the medium is write protected			 PUBLIC]
2213//--------------------------------------------------------------------------------------------------
2214
2215bool
2216IOUSBMassStorageUFIDevice::ReportMediumWriteProtection ( void )
2217{
2218
2219    STATUS_LOG ( ( 5, "%s[%p]::ReportMediumWriteProtection isWriteProtected = %d.", getName(), this, fMediumIsWriteProtected ) );
2220	return fMediumIsWriteProtected;
2221
2222}
2223
2224
2225#pragma mark -
2226#pragma mark *** Command Builders Utility Methods ***
2227#pragma mark -
2228
2229
2230// Utility routines used by all SCSI Command Set objects
2231
2232//--------------------------------------------------------------------------------------------------
2233//	IsParameterValid -	Validate Parameter used for 1 bit to 1 byte paramaters			 [PROTECTED]
2234//--------------------------------------------------------------------------------------------------
2235
2236bool
2237IOUSBMassStorageUFIDevice::IsParameterValid (	SCSICmdField1Byte param,
2238												SCSICmdField1Byte mask )
2239{
2240
2241	STATUS_LOG ( ( 6, "%s[%p]::IsParameterValid called", getName(), this ) );
2242
2243	if ( ( param | mask ) != mask )
2244	{
2245
2246		STATUS_LOG ( ( 4, "%s[%p]:: param = %x not valid, mask = %x", getName(), this, param, mask ) );
2247		return false;
2248
2249	}
2250
2251	return true;
2252
2253}
2254
2255
2256//--------------------------------------------------------------------------------------------------
2257//	IsParameterValid - Validate Parameter used for 9 bit to 2 byte paramaters			 [PROTECTED]
2258//--------------------------------------------------------------------------------------------------
2259
2260bool
2261IOUSBMassStorageUFIDevice::IsParameterValid (	SCSICmdField2Byte param,
2262												SCSICmdField2Byte mask )
2263{
2264
2265	STATUS_LOG ( ( 6, "%s[%p]::IsParameterValid called", getName(), this ) );
2266
2267	if ( ( param | mask ) != mask )
2268	{
2269
2270		STATUS_LOG ( ( 4, "%s[%p]:: param = %x not valid, mask = %x", getName(), this, param, mask ) );
2271		return false;
2272
2273	}
2274
2275	return true;
2276
2277}
2278
2279
2280////--------------------------------------------------------------------------------------------------
2281//	IsParameterValid - Validate Parameter used for 17 bit to 4 byte paramaters			 [PROTECTED]
2282//--------------------------------------------------------------------------------------------------
2283
2284bool
2285IOUSBMassStorageUFIDevice::IsParameterValid (	SCSICmdField4Byte param,
2286												SCSICmdField4Byte mask )
2287{
2288
2289	STATUS_LOG ( ( 6, "%s[%p]::IsParameterValid called", getName(), this ) );
2290
2291	if ( ( param | mask ) != mask )
2292	{
2293
2294		STATUS_LOG ( ( 4, "%s[%p]:: param = %x not valid, mask = %x", getName(), this,
2295						(unsigned int) param, (unsigned int) mask ) );
2296		return false;
2297
2298	}
2299
2300	return true;
2301
2302}
2303
2304
2305#pragma mark -
2306#pragma mark *** Command Builder Methods ***
2307#pragma mark -
2308
2309
2310//--------------------------------------------------------------------------------------------------
2311//	FORMAT_UNIT - Command Builder														 [PROTECTED]
2312//--------------------------------------------------------------------------------------------------
2313
2314bool
2315IOUSBMassStorageUFIDevice::FORMAT_UNIT(
2316							SCSITaskIdentifier			request,
2317			    			IOMemoryDescriptor *		dataBuffer,
2318			    			IOByteCount					defectListSize,
2319			    			SCSICmdField1Byte 			TRACK_NUMBER,
2320			    			SCSICmdField2Byte 			INTERLEAVE )
2321{
2322
2323	UNUSED ( TRACK_NUMBER );
2324
2325	STATUS_LOG ( ( 6, "%s[%p]::FORMAT_UNIT called", getName(), this ) );
2326
2327	if ( ResetForNewTask ( request ) == false )
2328	{
2329
2330		STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) );
2331		return false;
2332
2333	}
2334
2335	// Do the pre-flight check on the passed in parameters
2336	if ( IsParameterValid ( INTERLEAVE, kSCSICmdFieldMask2Byte ) == false )
2337	{
2338
2339		STATUS_LOG ( ( 4, "%s[%p]:: INTERLEAVE = %x not valid", getName(), this, INTERLEAVE ) );
2340		return false;
2341
2342	}
2343
2344	if ( defectListSize > 0 )
2345	{
2346		// We have data to send to the device,
2347		// make sure that we were given a valid buffer
2348		if ( IsMemoryDescriptorValid( dataBuffer, defectListSize  )
2349				== false )
2350		{
2351
2352			STATUS_LOG ( ( 4, "%s[%p]:: dataBuffer = %x not valid, defectListSize = %x",
2353							getName(), this, dataBuffer, defectListSize ) );
2354			return false;
2355
2356		}
2357
2358	}
2359
2360	// This is a 6-Byte command, fill out the cdb appropriately
2361	SetCommandDescriptorBlock (	request,
2362								kSCSICmd_FORMAT_UNIT,
2363								0x00,
2364								0x00,
2365								( INTERLEAVE >> 8 ) & 0xFF,
2366								  INTERLEAVE		& 0xFF,
2367								0x00 );
2368
2369	// The client has requested a DEFECT LIST be sent to the device
2370	// to be used with the format command
2371	SetDataTransferDirection ( 	request,
2372								kSCSIDataTransfer_FromInitiatorToTarget );
2373	SetDataBuffer ( 			request,
2374								dataBuffer );
2375
2376	return true;
2377
2378}
2379
2380
2381//--------------------------------------------------------------------------------------------------
2382//	  INQUIRY - Command Builder															 [PROTECTED]
2383//--------------------------------------------------------------------------------------------------
2384
2385bool
2386IOUSBMassStorageUFIDevice::INQUIRY (
2387							SCSITaskIdentifier			request,
2388    						IOMemoryDescriptor 			*dataBuffer,
2389    						SCSICmdField1Byte 			PAGE_OR_OPERATION_CODE,
2390    						SCSICmdField1Byte 			ALLOCATION_LENGTH )
2391{
2392
2393	STATUS_LOG ( ( 6, "%s[%p]::INQUIRY called", getName(), this ) );
2394
2395	if ( ResetForNewTask( request ) == false )
2396	{
2397
2398		STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) );
2399		return false;
2400
2401	}
2402
2403	if ( IsParameterValid ( PAGE_OR_OPERATION_CODE, kSCSICmdFieldMask1Byte ) == false )
2404	{
2405
2406		STATUS_LOG ( ( 4, "%s[%p]:: PAGE_OR_OPERATION_CODE = %x not valid",
2407						getName(), this, PAGE_OR_OPERATION_CODE ) );
2408		return false;
2409
2410	}
2411
2412	if ( IsParameterValid ( ALLOCATION_LENGTH, kSCSICmdFieldMask1Byte ) == false )
2413	{
2414
2415		STATUS_LOG ( ( 4, "%s[%p]:: ALLOCATION_LENGTH = %x not valid", getName(), this, ALLOCATION_LENGTH ) );
2416		return false;
2417
2418	}
2419
2420	if ( IsMemoryDescriptorValid( dataBuffer, ALLOCATION_LENGTH ) == false )
2421	{
2422		STATUS_LOG ( ( 4, "%s[%p]:: dataBuffer = %x not valid, ALLOCATION_LENGTH = %x",
2423						getName(), this, dataBuffer, ALLOCATION_LENGTH ) );
2424		return false;
2425	}
2426
2427	// This is a 6-Byte command, fill out the cdb appropriately
2428	SetCommandDescriptorBlock (	request,
2429								kSCSICmd_INQUIRY,
2430								0x00,
2431								PAGE_OR_OPERATION_CODE,
2432								0x00,
2433								ALLOCATION_LENGTH,
2434								0x00 );
2435
2436	SetDataTransferDirection ( 	request,
2437								kSCSIDataTransfer_FromTargetToInitiator );
2438	SetDataBuffer ( 			request,
2439								dataBuffer );
2440	SetRequestedDataTransferCount ( request,
2441									ALLOCATION_LENGTH );
2442
2443	return true;
2444
2445}
2446
2447
2448//--------------------------------------------------------------------------------------------------
2449//	  MODE_SELECT_10 - Command Builder													 [PROTECTED]
2450//--------------------------------------------------------------------------------------------------
2451
2452bool
2453IOUSBMassStorageUFIDevice::MODE_SELECT_10 (
2454							SCSITaskIdentifier			request,
2455    						IOMemoryDescriptor 			*dataBuffer,
2456    						SCSICmdField1Bit 			PF,
2457    						SCSICmdField1Bit 			SP,
2458    						SCSICmdField2Byte 			PARAMETER_LIST_LENGTH )
2459{
2460
2461	STATUS_LOG ( ( 6, "%s[%p]::MODE_SELECT_10 called", getName(), this ) );
2462
2463	if ( ResetForNewTask( request ) == false )
2464	{
2465		STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) );
2466		return false;
2467	}
2468
2469	if( IsParameterValid( PF, kSCSICmdFieldMask1Bit ) == false )
2470	{
2471		STATUS_LOG ( ( 4, "%s[%p]:: PF = %x not valid", getName(), this, PF ) );
2472		return false;
2473	}
2474
2475	if( IsParameterValid( SP, kSCSICmdFieldMask1Bit ) == false )
2476	{
2477		STATUS_LOG ( ( 4, "%s[%p]:: SP = %x not valid", getName(), this, SP ) );
2478		return false;
2479	}
2480
2481	if( IsParameterValid( PARAMETER_LIST_LENGTH, kSCSICmdFieldMask2Byte ) == false )
2482	{
2483		STATUS_LOG ( ( 4, "%s[%p]:: PARAMETER_LIST_LENGTH = %x not valid",
2484                        getName(), this, PARAMETER_LIST_LENGTH ) );
2485		return false;
2486	}
2487
2488	if( IsMemoryDescriptorValid( dataBuffer, PARAMETER_LIST_LENGTH ) == false )
2489	{
2490		STATUS_LOG ( ( 4, "%s[%p]:: dataBuffer = %x not valid, PARAMETER_LIST_LENGTH = %x",
2491						getName(), this, dataBuffer, PARAMETER_LIST_LENGTH ) );
2492		return false;
2493	}
2494
2495	// This is a 10-Byte command, fill out the cdb appropriately
2496	SetCommandDescriptorBlock (	request,
2497								kSCSICmd_MODE_SELECT_10,
2498								( PF << 4 ) | SP,
2499								0x00,
2500								0x00,
2501								0x00,
2502								0x00,
2503								0x00,
2504								( PARAMETER_LIST_LENGTH >> 8 ) & 0xFF,
2505								PARAMETER_LIST_LENGTH & 0xFF,
2506								0x00 );
2507
2508	SetDataTransferDirection ( 	request,
2509								kSCSIDataTransfer_FromInitiatorToTarget );
2510	SetDataBuffer ( 			request,
2511								dataBuffer );
2512	SetRequestedDataTransferCount ( request,
2513									PARAMETER_LIST_LENGTH );
2514
2515	return true;
2516
2517}
2518
2519
2520//--------------------------------------------------------------------------------------------------
2521//	  MODE_SENSE_10 - Command Builder													 [PROTECTED]
2522//--------------------------------------------------------------------------------------------------
2523
2524bool
2525IOUSBMassStorageUFIDevice::MODE_SENSE_10 (
2526							SCSITaskIdentifier			request,
2527    						IOMemoryDescriptor 			*dataBuffer,
2528    						SCSICmdField1Bit 			DBD,
2529	   						SCSICmdField2Bit 			PC,
2530	   						SCSICmdField6Bit 			PAGE_CODE,
2531	   						SCSICmdField2Byte 			ALLOCATION_LENGTH )
2532{
2533
2534	STATUS_LOG ( ( 6, "%s[%p]::MODE_SENSE_10 called", getName(), this ) );
2535
2536	if ( ResetForNewTask ( request ) == false )
2537	{
2538		STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) );
2539		return false;
2540	}
2541
2542	if( IsParameterValid ( DBD, kSCSICmdFieldMask1Bit ) == false )
2543	{
2544		STATUS_LOG ( ( 4, "%s[%p]:: DBD = %x not valid", getName(), this, DBD ) );
2545		return false;
2546	}
2547
2548	if( IsParameterValid ( PC, kSCSICmdFieldMask2Bit ) == false )
2549	{
2550		STATUS_LOG ( ( 4, "%s[%p]:: PC = %x not valid", getName(), this, PC ) );
2551		return false;
2552	}
2553
2554	if( IsParameterValid ( PAGE_CODE, kSCSICmdFieldMask6Bit ) == false )
2555	{
2556		STATUS_LOG ( ( 4, "%s[%p]:: PAGE_CODE = %x not valid", getName(), this, PAGE_CODE ) );
2557		return false;
2558	}
2559
2560	if( IsParameterValid ( ALLOCATION_LENGTH, kSCSICmdFieldMask2Byte ) == false )
2561	{
2562		STATUS_LOG ( ( 4, "%s[%p]:: ALLOCATION_LENGTH = %x not valid", getName(), this, ALLOCATION_LENGTH ) );
2563		return false;
2564	}
2565
2566	if( IsMemoryDescriptorValid ( dataBuffer, ALLOCATION_LENGTH ) == false )
2567	{
2568		STATUS_LOG ( (4, "%s[%p]:: dataBuffer = %x not valid, ALLOCATION_LENGTH = %x",
2569						dataBuffer, ALLOCATION_LENGTH, getName(), this ) );
2570		return false;
2571	}
2572
2573	// This is a 10-Byte command, fill out the cdb appropriately
2574	SetCommandDescriptorBlock (	request,
2575								kSCSICmd_MODE_SENSE_10,
2576								( DBD << 3 ),
2577								( PC << 6 ) | PAGE_CODE,
2578								0x00,
2579								0x00,
2580								0x00,
2581								0x00,
2582								( ALLOCATION_LENGTH >> 8 ) & 0xFF,
2583								  ALLOCATION_LENGTH		   & 0xFF,
2584								0x00 );
2585
2586	SetDataTransferDirection ( 	request,
2587								kSCSIDataTransfer_FromTargetToInitiator );
2588	SetDataBuffer ( 			request,
2589								dataBuffer );
2590	SetRequestedDataTransferCount ( request,
2591									ALLOCATION_LENGTH );
2592
2593	return true;
2594
2595}
2596
2597
2598//--------------------------------------------------------------------------------------------------
2599//	  PREVENT_ALLOW_MEDIUM_REMOVAL - Command Builder									 [PROTECTED]
2600//--------------------------------------------------------------------------------------------------
2601
2602bool
2603IOUSBMassStorageUFIDevice::PREVENT_ALLOW_MEDIUM_REMOVAL(
2604							SCSITaskIdentifier			request,
2605	     					SCSICmdField1Bit 			PREVENT )
2606{
2607
2608	STATUS_LOG ( ( 6, "%s[%p]::PREVENT_ALLOW_MEDIUM_REMOVAL called", getName(), this ) );
2609
2610	if ( ResetForNewTask( request ) == false )
2611	{
2612		STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) );
2613		return false;
2614	}
2615
2616	if( IsParameterValid( PREVENT, kSCSICmdFieldMask2Bit ) == false )
2617	{
2618		STATUS_LOG ( ( 4, "%s[%p]:: PREVENT = %x not valid", getName(), this, PREVENT ) );
2619		return false;
2620	}
2621
2622	// This is a 6-Byte command, fill out the cdb appropriately
2623	SetCommandDescriptorBlock (	request,
2624								kSCSICmd_PREVENT_ALLOW_MEDIUM_REMOVAL,
2625								0x00,
2626								0x00,
2627								0x00,
2628								PREVENT,
2629								0x00 );
2630
2631	SetDataTransferDirection ( 	request,
2632								kSCSIDataTransfer_NoDataTransfer );
2633
2634	return true;
2635
2636}
2637
2638
2639//--------------------------------------------------------------------------------------------------
2640//	  READ_10 - Command Builder															 [PROTECTED]
2641//--------------------------------------------------------------------------------------------------
2642
2643bool
2644IOUSBMassStorageUFIDevice::READ_10 (
2645							SCSITaskIdentifier			request,
2646			    			IOMemoryDescriptor *		dataBuffer,
2647			    			UInt32						blockSize,
2648			    			SCSICmdField1Bit 			DPO,
2649			    			SCSICmdField1Bit 			FUA,
2650							SCSICmdField1Bit 			RELADR,
2651							SCSICmdField4Byte 			LOGICAL_BLOCK_ADDRESS,
2652							SCSICmdField2Byte 			TRANSFER_LENGTH )
2653{
2654
2655	UInt32					requestedByteCount;
2656
2657
2658	STATUS_LOG ( ( 6, "%s[%p]::READ_10 called", getName(), this ) );
2659
2660	if ( ResetForNewTask( request ) == false )
2661	{
2662		STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) );
2663		return false;
2664	}
2665
2666	// Check the validity of the media
2667	if ( blockSize == 0 )
2668	{
2669		// There is no media in the device, or it has an undetermined
2670		// blocksize (could be unformatted).
2671		return false;
2672	}
2673
2674	// Make sure that we were given a valid buffer
2675	if ( dataBuffer == NULL )
2676	{
2677		return false;
2678	}
2679	else
2680	{
2681		// We have a valid buffer object, check that it has the required
2682		// capcity for the data to be transfered.
2683		requestedByteCount = TRANSFER_LENGTH * blockSize;
2684
2685		// We know the number of bytes to transfer, now check that the
2686		// buffer is large enough to accomodate this request.
2687		if ( dataBuffer->getLength() < requestedByteCount )
2688		{
2689			return false;
2690		}
2691
2692	}
2693
2694	// Do the pre-flight check on the passed in parameters
2695	if ( IsParameterValid( DPO, kSCSICmdFieldMask1Bit ) == false )
2696	{
2697		STATUS_LOG ( ( 4, "%s[%p]:: DPO = %x not valid", getName(), this, DPO ) );
2698		return false;
2699	}
2700
2701	if ( IsParameterValid( FUA, kSCSICmdFieldMask1Bit ) == false )
2702	{
2703		STATUS_LOG ( ( 4, "%s[%p]:: FUA = %x not valid", getName(), this, FUA ) );
2704		return false;
2705	}
2706
2707	if ( IsParameterValid( RELADR, kSCSICmdFieldMask1Bit ) == false )
2708	{
2709		STATUS_LOG ( ( 4, "%s[%p]:: RELADR = %x not valid", getName(), this, RELADR ) );
2710		return false;
2711	}
2712
2713	if ( IsParameterValid( LOGICAL_BLOCK_ADDRESS, kSCSICmdFieldMask4Byte ) == false )
2714	{
2715		STATUS_LOG ( ( 4, "%s[%p]:: LOGICAL_BLOCK_ADDRESS = %x not valid",
2716						getName(), this, LOGICAL_BLOCK_ADDRESS ) );
2717		return false;
2718	}
2719
2720	if ( IsParameterValid( TRANSFER_LENGTH, kSCSICmdFieldMask2Byte ) == false )
2721	{
2722		STATUS_LOG ( ( 4, "%s[%p]:: TRANSFER_LENGTH = %x not valid",
2723						getName(), this, TRANSFER_LENGTH ) );
2724		return false;
2725	}
2726
2727	// This is a 10-Byte command, fill out the cdb appropriately
2728	SetCommandDescriptorBlock (	request,
2729								kSCSICmd_READ_10,
2730								( DPO << 4 ) | ( FUA << 3 ) | RELADR,
2731								( LOGICAL_BLOCK_ADDRESS >> 24 ) & 0xFF,
2732								( LOGICAL_BLOCK_ADDRESS >> 16 ) & 0xFF,
2733								( LOGICAL_BLOCK_ADDRESS >> 8  ) & 0xFF,
2734								  LOGICAL_BLOCK_ADDRESS			& 0xFF,
2735								0x00,
2736								( TRANSFER_LENGTH >> 8 ) & 0xFF,
2737								  TRANSFER_LENGTH		 & 0xFF,
2738								0x00 );
2739
2740	SetDataTransferDirection ( 	request,
2741								kSCSIDataTransfer_FromTargetToInitiator );
2742	SetDataBuffer ( 			request,
2743								dataBuffer );
2744	SetRequestedDataTransferCount ( request,
2745									requestedByteCount );
2746
2747	return true;
2748
2749}
2750
2751
2752//--------------------------------------------------------------------------------------------------
2753//	  READ_12 - Command Builder															 [PROTECTED]
2754//--------------------------------------------------------------------------------------------------
2755
2756bool
2757IOUSBMassStorageUFIDevice::READ_12 (
2758							SCSITaskIdentifier			request,
2759			    			IOMemoryDescriptor *		dataBuffer,
2760			    			UInt32						blockSize,
2761			    			SCSICmdField1Bit 			DPO,
2762			    			SCSICmdField1Bit 			FUA,
2763							SCSICmdField1Bit 			RELADR,
2764							SCSICmdField4Byte 			LOGICAL_BLOCK_ADDRESS,
2765							SCSICmdField4Byte 			TRANSFER_LENGTH )
2766{
2767
2768	UInt32					requestedByteCount;
2769
2770
2771	STATUS_LOG ( ( 6, "%s[%p]::READ_12 called", getName(), this ) );
2772
2773	if ( ResetForNewTask( request ) == false )
2774	{
2775		STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) );
2776		return false;
2777	}
2778
2779	// Check the validity of the media
2780	if ( blockSize == 0 )
2781	{
2782		// There is no media in the device, or it has an undetermined
2783		// blocksize (could be unformatted).
2784		return false;
2785	}
2786
2787	// Make sure that we were given a valid buffer
2788	if (dataBuffer == NULL )
2789	{
2790		return false;
2791	}
2792	else
2793	{
2794		// We have a valid buffer object, check that it has the required
2795		// capcity for the data to be transfered.
2796		requestedByteCount = TRANSFER_LENGTH * blockSize;
2797
2798		// We know the number of bytes to transfer, now check that the
2799		// buffer is large enough to accomodate this request.
2800		if ( dataBuffer->getLength() < requestedByteCount )
2801		{
2802			return false;
2803		}
2804
2805	}
2806
2807	// Do the pre-flight check on the passed in parameters
2808	if( IsParameterValid( DPO, kSCSICmdFieldMask1Bit ) == false )
2809	{
2810		STATUS_LOG ( ( 4, "%s[%p]:: DPO = %x not valid", getName(), this, DPO ) );
2811		return false;
2812	}
2813
2814	if( IsParameterValid( FUA, kSCSICmdFieldMask1Bit ) == false )
2815	{
2816		STATUS_LOG ( ( 4, "%s[%p]:: FUA = %x not valid", getName(), this, FUA ) );
2817		return false;
2818	}
2819
2820	if( IsParameterValid( RELADR, kSCSICmdFieldMask1Bit ) == false )
2821	{
2822		STATUS_LOG ( ( 4, "%s[%p]:: RELADR = %x not valid", getName(), this, RELADR ) );
2823		return false;
2824	}
2825
2826	if( IsParameterValid( LOGICAL_BLOCK_ADDRESS, kSCSICmdFieldMask4Byte ) == false )
2827	{
2828		STATUS_LOG ( ( 4, "%s[%p]:: LOGICAL_BLOCK_ADDRESS = %x not valid",
2829						getName(), this, LOGICAL_BLOCK_ADDRESS ) );
2830		return false;
2831	}
2832
2833	if( IsParameterValid( TRANSFER_LENGTH, kSCSICmdFieldMask4Byte ) == false )
2834	{
2835		STATUS_LOG ( ( 4, "%s[%p]:: TRANSFER_LENGTH = %x not valid",
2836						getName(), this, TRANSFER_LENGTH ) );
2837		return false;
2838	}
2839
2840	// This is a 12-Byte command, fill out the cdb appropriately
2841	SetCommandDescriptorBlock (	request,
2842								kSCSICmd_READ_12,
2843								( DPO << 4 ) | ( FUA << 3 ) | RELADR,
2844								( LOGICAL_BLOCK_ADDRESS >> 24 ) & 0xFF,
2845								( LOGICAL_BLOCK_ADDRESS >> 16 ) & 0xFF,
2846								( LOGICAL_BLOCK_ADDRESS >> 8  ) & 0xFF,
2847								  LOGICAL_BLOCK_ADDRESS			& 0xFF,
2848								( TRANSFER_LENGTH >> 24 ) 		& 0xFF,
2849								( TRANSFER_LENGTH >> 16 ) 		& 0xFF,
2850								( TRANSFER_LENGTH >> 8  ) 		& 0xFF,
2851								  TRANSFER_LENGTH				& 0xFF,
2852								0x00,
2853								0x00 );
2854
2855	SetDataTransferDirection( 	request,
2856								kSCSIDataTransfer_FromTargetToInitiator );
2857	SetDataBuffer ( 			request,
2858								dataBuffer );
2859	SetRequestedDataTransferCount ( request,
2860									requestedByteCount );
2861
2862	return true;
2863
2864}
2865
2866
2867//--------------------------------------------------------------------------------------------------
2868//	  READ_CAPACITY - Command Builder													 [PROTECTED]
2869//--------------------------------------------------------------------------------------------------
2870
2871bool
2872IOUSBMassStorageUFIDevice::READ_CAPACITY (
2873							SCSITaskIdentifier			request,
2874			    			IOMemoryDescriptor *		dataBuffer,
2875			    			SCSICmdField1Bit 			RELADR,
2876							SCSICmdField4Byte 			LOGICAL_BLOCK_ADDRESS,
2877							SCSICmdField1Bit 			PMI )
2878{
2879	STATUS_LOG ( ( 6, "%s[%p]::READ_CAPACITY called", getName(), this ) );
2880
2881	if ( ResetForNewTask( request ) == false )
2882	{
2883		STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) );
2884		return false;
2885	}
2886
2887	// Make sure that we were given a buffer
2888	if ( dataBuffer == NULL )
2889	{
2890		return false;
2891	}
2892
2893	// Do the pre-flight check on the passed in parameters
2894	if( IsParameterValid( RELADR, kSCSICmdFieldMask1Bit ) == false )
2895	{
2896		STATUS_LOG ( ( 4, "%s[%p]:: RELADR = %x not valid", getName(), this, RELADR ) );
2897		return false;
2898	}
2899
2900	if( IsParameterValid( LOGICAL_BLOCK_ADDRESS, kSCSICmdFieldMask4Byte ) == false )
2901	{
2902		STATUS_LOG ( ( 4, "%s[%p]:: LOGICAL_BLOCK_ADDRESS = %x not valid",
2903						getName(), this, LOGICAL_BLOCK_ADDRESS ) );
2904		return false;
2905	}
2906
2907	if( IsParameterValid( PMI, kSCSICmdFieldMask1Bit ) == false )
2908	{
2909		STATUS_LOG ( ( 4, "%s[%p]:: PMI = %x not valid", getName(), this, PMI ) );
2910		return false;
2911	}
2912
2913	// This is a 10-Byte command, fill out the cdb appropriately
2914	SetCommandDescriptorBlock(	request,
2915								kSCSICmd_READ_CAPACITY,
2916								RELADR,
2917								( LOGICAL_BLOCK_ADDRESS >> 24 ) & 0xFF,
2918								( LOGICAL_BLOCK_ADDRESS >> 16 ) & 0xFF,
2919								( LOGICAL_BLOCK_ADDRESS >> 8  ) & 0xFF,
2920								  LOGICAL_BLOCK_ADDRESS			& 0xFF,
2921								0x00,
2922								0x00,
2923								PMI,
2924								0x00 );
2925
2926	SetDataTransferDirection( 	request,
2927								kSCSIDataTransfer_FromTargetToInitiator );
2928	SetDataBuffer( 				request,
2929								dataBuffer );
2930	SetRequestedDataTransferCount( 	request, 8 );
2931
2932	return true;
2933}
2934
2935
2936//--------------------------------------------------------------------------------------------------
2937//	  READ_FORMAT_CAPACITIES - Command Builder											 [PROTECTED]
2938//--------------------------------------------------------------------------------------------------
2939
2940bool
2941IOUSBMassStorageUFIDevice::READ_FORMAT_CAPACITIES(
2942							SCSITaskIdentifier			request,
2943			    			IOMemoryDescriptor *		dataBuffer,
2944			    			SCSICmdField2Byte 			ALLOCATION_LENGTH )
2945{
2946
2947	STATUS_LOG ( ( 6, "%s[%p]::READ_CAPACITY called", getName(), this ) );
2948
2949	if ( ResetForNewTask( request ) == false )
2950	{
2951		STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) );
2952		return false;
2953	}
2954
2955	// Make sure that we were given a buffer
2956	if ( dataBuffer == NULL )
2957	{
2958		return false;
2959	}
2960
2961	// Do the pre-flight check on the passed in parameters
2962	if( IsParameterValid( ALLOCATION_LENGTH, kSCSICmdFieldMask2Byte ) == false )
2963	{
2964		STATUS_LOG ( (4, "%s[%p]:: ALLOCATION_LENGTH = %x not valid", getName(), this, ALLOCATION_LENGTH ) );
2965		return false;
2966	}
2967
2968	// This is a 10-Byte command, fill out the cdb appropriately
2969	SetCommandDescriptorBlock (	request,
2970								kSCSICmd_READ_FORMAT_CAPACITIES,
2971								0x00,
2972								0x00,
2973								0x00,
2974								0x00,
2975								0x00,
2976								0x00,
2977								( ALLOCATION_LENGTH >> 8  ) & 0xFF,
2978								  ALLOCATION_LENGTH			& 0xFF,
2979								0x00 );
2980
2981	SetDataTransferDirection ( 	request,
2982								kSCSIDataTransfer_FromTargetToInitiator );
2983	SetDataBuffer ( 			request,
2984								dataBuffer );
2985	SetRequestedDataTransferCount( 	request,
2986									ALLOCATION_LENGTH );
2987
2988	return true;
2989
2990}
2991
2992
2993//--------------------------------------------------------------------------------------------------
2994//	  REQUEST_SENSE - Command Builder													 [PROTECTED]
2995//--------------------------------------------------------------------------------------------------
2996
2997bool
2998IOUSBMassStorageUFIDevice::REQUEST_SENSE (
2999							SCSITaskIdentifier			request,
3000   							IOMemoryDescriptor 			*dataBuffer,
3001			    			SCSICmdField1Byte 			ALLOCATION_LENGTH )
3002{
3003
3004	STATUS_LOG ( ( 6, "%s[%p]::REQUEST_SENSE called", getName(), this ) );
3005
3006	if ( ResetForNewTask( request ) == false )
3007	{
3008		STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) );
3009		return false;
3010	}
3011
3012	if( IsParameterValid( ALLOCATION_LENGTH, kSCSICmdFieldMask1Byte ) == false )
3013	{
3014		STATUS_LOG ( ( 4, "%s[%p]ALLOCATION_LENGTH = %x not valid",
3015						getName(), this, ALLOCATION_LENGTH ) );
3016		return false;
3017	}
3018
3019	// This is a 6-Byte command, fill out the cdb appropriately
3020	SetCommandDescriptorBlock (	request,
3021								kSCSICmd_REQUEST_SENSE,
3022								0x00,
3023								0x00,
3024								0x00,
3025								ALLOCATION_LENGTH,
3026								0x00 );
3027
3028	SetDataTransferDirection ( 	request,
3029								kSCSIDataTransfer_FromTargetToInitiator );
3030	SetDataBuffer ( 			request,
3031								dataBuffer );
3032	SetRequestedDataTransferCount ( request,
3033									ALLOCATION_LENGTH );
3034
3035	return true;
3036
3037}
3038
3039
3040//--------------------------------------------------------------------------------------------------
3041//	  REZERO_UNIT - Command Builder														 [PROTECTED]
3042//--------------------------------------------------------------------------------------------------
3043
3044bool
3045IOUSBMassStorageUFIDevice::REZERO_UNIT ( SCSITaskIdentifier	request )
3046{
3047
3048	UNUSED ( request );
3049
3050	return false;
3051
3052}
3053
3054
3055//--------------------------------------------------------------------------------------------------
3056//	  SEEK - Command Builder															 [PROTECTED]
3057//--------------------------------------------------------------------------------------------------
3058
3059bool
3060IOUSBMassStorageUFIDevice::SEEK (
3061							SCSITaskIdentifier			request,
3062			    			SCSICmdField4Byte 			LOGICAL_BLOCK_ADDRESS )
3063{
3064
3065	UNUSED ( request );
3066	UNUSED ( LOGICAL_BLOCK_ADDRESS );
3067
3068	return false;
3069
3070}
3071
3072
3073//--------------------------------------------------------------------------------------------------
3074//	  SEND_DIAGNOSTICS - Command Builder												 [PROTECTED]
3075//--------------------------------------------------------------------------------------------------
3076
3077bool
3078IOUSBMassStorageUFIDevice::SEND_DIAGNOSTICS (
3079							SCSITaskIdentifier			request,
3080							SCSICmdField1Bit 			PF,
3081							SCSICmdField1Bit 			SELF_TEST,
3082							SCSICmdField1Bit 			DEF_OFL,
3083							SCSICmdField1Bit 			UNIT_OFL )
3084{
3085
3086	STATUS_LOG ( ( 6, "%s[%p]::SEND_DIAGNOSTICS called", getName(), this ) );
3087
3088	if ( ResetForNewTask( request ) == false )
3089	{
3090		STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) );
3091		return false;
3092	}
3093
3094	if( IsParameterValid( PF, kSCSICmdFieldMask1Bit ) == false )
3095	{
3096		STATUS_LOG ( ( 4, "%s[%p]:: PF = %x not valid", getName(), this, PF ) );
3097		return false;
3098	}
3099
3100	if( IsParameterValid ( SELF_TEST, kSCSICmdFieldMask1Bit ) == false )
3101	{
3102		STATUS_LOG ( ( 4, "%s[%p]:: SELF_TEST = %x not valid", getName(), this, SELF_TEST ) );
3103		return false;
3104	}
3105
3106	if( IsParameterValid( DEF_OFL, kSCSICmdFieldMask1Bit ) == false )
3107	{
3108		STATUS_LOG ( ( 4, "%s[%p]:: DEF_OFL = %x not valid", getName(), this, DEF_OFL ) );
3109		return false;
3110	}
3111
3112	if( IsParameterValid( UNIT_OFL, kSCSICmdFieldMask1Bit ) == false )
3113	{
3114		STATUS_LOG ( ( 4, "%s[%p]:: UNIT_OFL = %x not valid", getName(), this, UNIT_OFL ) );
3115		return false;
3116	}
3117
3118	// This is a 6-Byte command, fill out the cdb appropriately
3119	SetCommandDescriptorBlock (	request,
3120								kSCSICmd_SEND_DIAGNOSTICS,
3121								( PF << 4 ) |
3122									( SELF_TEST << 2 ) | ( DEF_OFL << 1 ) | UNIT_OFL,
3123								0x00,
3124								0x00,
3125								0x00,
3126								0x00 );
3127
3128	SetDataTransferDirection ( 	request,
3129								kSCSIDataTransfer_NoDataTransfer);
3130
3131	return true;
3132
3133}
3134
3135
3136//--------------------------------------------------------------------------------------------------
3137//	  START_STOP_UNIT - Command Builder													 [PROTECTED]
3138//--------------------------------------------------------------------------------------------------
3139
3140bool
3141IOUSBMassStorageUFIDevice::START_STOP_UNIT (
3142							SCSITaskIdentifier			request,
3143							SCSICmdField1Bit 			IMMED,
3144							SCSICmdField1Bit 			LOEJ,
3145							SCSICmdField1Bit 			START )
3146{
3147
3148	STATUS_LOG ( ( 6, "%s[%p]::START_STOP_UNIT called", getName(), this ) );
3149
3150	if ( ResetForNewTask( request ) == false )
3151	{
3152		STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) );
3153		return false;
3154	}
3155
3156	// Do the pre-flight check on the passed in parameters
3157	if( IsParameterValid( IMMED, kSCSICmdFieldMask1Bit ) == false )
3158	{
3159		STATUS_LOG ( ( 4, "%s[%p]:: IMMED = %x not valid", getName(), this, IMMED ) );
3160		return false;
3161	}
3162
3163	if( IsParameterValid( LOEJ, kSCSICmdFieldMask1Bit ) == false )
3164	{
3165		STATUS_LOG ( ( 4, "%s[%p]:: LOEJ = %x not valid", getName(), this, LOEJ ) );
3166		return false;
3167	}
3168
3169	if( IsParameterValid( START, kSCSICmdFieldMask1Bit ) == false )
3170	{
3171		STATUS_LOG ( ( 4, "%s[%p]:: START = %x not valid", getName(), this, START ) );
3172		return false;
3173	}
3174
3175	// This is a 6-Byte command, fill out the cdb appropriately
3176	SetCommandDescriptorBlock (	request,
3177								kSCSICmd_START_STOP_UNIT,
3178								IMMED,
3179								0x00,
3180								0x00,
3181								( LOEJ << 1 ) | START,
3182								0x00 );
3183
3184	SetDataTransferDirection ( 	request,
3185								kSCSIDataTransfer_NoDataTransfer );
3186
3187	return true;
3188
3189}
3190
3191
3192//--------------------------------------------------------------------------------------------------
3193//	  TEST_UNIT_READY - Command Builder													 [PROTECTED]
3194//--------------------------------------------------------------------------------------------------
3195
3196bool
3197IOUSBMassStorageUFIDevice::TEST_UNIT_READY (
3198							SCSITaskIdentifier			request )
3199{
3200
3201	STATUS_LOG ( ( 6, "%s[%p]::TEST_UNIT_READY called", getName(), this ) );
3202
3203	if ( ResetForNewTask( request ) == false )
3204	{
3205		STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) );
3206		return false;
3207	}
3208
3209	// This is a 6-Byte command, fill out the cdb appropriately
3210	SetCommandDescriptorBlock (	request,
3211								kSCSICmd_TEST_UNIT_READY,
3212								0x00,
3213								0x00,
3214								0x00,
3215								0x00,
3216								0x00 );
3217
3218	SetDataTransferDirection ( 	request,
3219								kSCSIDataTransfer_NoDataTransfer );
3220
3221	return true;
3222
3223}
3224
3225
3226//--------------------------------------------------------------------------------------------------
3227//	  VERIFY - Command Builder															 [PROTECTED]
3228//--------------------------------------------------------------------------------------------------
3229
3230bool
3231IOUSBMassStorageUFIDevice::VERIFY(
3232							SCSITaskIdentifier			request,
3233							SCSICmdField1Bit 			DPO,
3234							SCSICmdField1Bit 			BYTCHK,
3235							SCSICmdField1Bit 			RELADR,
3236							SCSICmdField4Byte 			LOGICAL_BLOCK_ADDRESS,
3237							SCSICmdField2Byte 			VERIFICATION_LENGTH )
3238{
3239	UNUSED( request );
3240	UNUSED( DPO );
3241	UNUSED( BYTCHK );
3242	UNUSED( RELADR );
3243	UNUSED( LOGICAL_BLOCK_ADDRESS );
3244	UNUSED( VERIFICATION_LENGTH );
3245
3246	return false;
3247}
3248
3249
3250//--------------------------------------------------------------------------------------------------
3251//	  WRITE_10 - Command Builder														 [PROTECTED]
3252//--------------------------------------------------------------------------------------------------
3253
3254bool
3255IOUSBMassStorageUFIDevice::WRITE_10 (
3256							SCSITaskIdentifier			request,
3257			    			IOMemoryDescriptor *		dataBuffer,
3258			    			UInt32						blockSize,
3259			    			SCSICmdField1Bit 			DPO,
3260			    			SCSICmdField1Bit 			FUA,
3261							SCSICmdField1Bit 			RELADR,
3262							SCSICmdField4Byte 			LOGICAL_BLOCK_ADDRESS,
3263							SCSICmdField2Byte 			TRANSFER_LENGTH )
3264{
3265
3266	UInt32					requestedByteCount;
3267
3268
3269	STATUS_LOG ( ( 6, "%s[%p]::WRITE_10 called", getName(), this ) );
3270
3271	if ( ResetForNewTask( request ) == false )
3272	{
3273
3274		STATUS_LOG ( ( 1, "%s[%p]:: ResetForNewTask on the request SCSITask failed.", getName(), this ) );
3275		return false;
3276
3277	}
3278
3279	// Check the validity of the media
3280	if ( blockSize == 0 )
3281	{
3282		// There is no media in the device, or it has an undetermined
3283		// blocksize (could be unformatted).
3284		return false;
3285
3286	}
3287
3288	// Make sure that we were given a valid buffer
3289	if (dataBuffer == NULL )
3290	{
3291
3292		return false;
3293
3294	}
3295	else
3296	{
3297		// We have a valid buffer object, check that it has the required
3298		// capcity for the data to be transfered.
3299		requestedByteCount = TRANSFER_LENGTH * blockSize;
3300
3301		// We know the number of bytes to transfer, now check that the
3302		// buffer is large enough to accomodate this request.
3303		if ( dataBuffer->getLength() < requestedByteCount )
3304		{
3305			return false;
3306		}
3307
3308	}
3309
3310	// Do the pre-flight check on the passed in parameters
3311	if( IsParameterValid ( DPO, kSCSICmdFieldMask1Bit ) == false )
3312	{
3313
3314		STATUS_LOG ( ( 4, "%s[%p]:: DPO = %x not valid", getName(), this, DPO ) );
3315		return false;
3316
3317	}
3318
3319	if( IsParameterValid ( FUA, kSCSICmdFieldMask1Bit ) == false )
3320	{
3321
3322		STATUS_LOG ( ( 4, "%s[%p]:: FUA = %x not valid", getName(), this, FUA ) );
3323		return false;
3324
3325	}
3326
3327	if( IsParameterValid ( RELADR, kSCSICmdFieldMask1Bit ) == false )
3328	{
3329
3330		STATUS_LOG ( ( 4, "%s[%p]:: RELADR = %x not valid", getName(), this, RELADR ) );
3331		return false;
3332
3333	}
3334
3335	if( IsParameterValid ( LOGICAL_BLOCK_ADDRESS, kSCSICmdFieldMask4Byte ) == false )
3336	{
3337
3338		STATUS_LOG ( ( 4, "%s[%p]:: LOGICAL_BLOCK_ADDRESS = %x not valid",
3339						getName(), this, LOGICAL_BLOCK_ADDRESS ) );
3340		return false;
3341
3342	}
3343
3344	if( IsParameterValid ( TRANSFER_LENGTH, kSCSICmdFieldMask2Byte ) == false )
3345	{
3346
3347		STATUS_LOG ( ( 4, "%s[%p]:: TRANSFER_LENGTH = %x not valid",
3348						getName(), this, TRANSFER_LENGTH ) );
3349		return false;
3350
3351	}
3352
3353	// This is a 10-Byte command, fill out the cdb appropriately
3354	SetCommandDescriptorBlock (	request,
3355								kSCSICmd_WRITE_10,
3356								( DPO << 4 ) | ( FUA << 3 ) | RELADR,
3357								( LOGICAL_BLOCK_ADDRESS >> 24 ) & 0xFF,
3358								( LOGICAL_BLOCK_ADDRESS >> 16 ) & 0xFF,
3359								( LOGICAL_BLOCK_ADDRESS >> 8  ) & 0xFF,
3360								  LOGICAL_BLOCK_ADDRESS			& 0xFF,
3361								0x00,
3362								( TRANSFER_LENGTH >> 8 ) & 0xFF,
3363								  TRANSFER_LENGTH		 & 0xFF,
3364								0x00 );
3365
3366	SetDataTransferDirection ( 	request,
3367								kSCSIDataTransfer_FromInitiatorToTarget );
3368	SetDataBuffer ( 			request,
3369								dataBuffer );
3370	SetRequestedDataTransferCount ( request,
3371									requestedByteCount );
3372
3373	return true;
3374
3375}
3376
3377
3378//--------------------------------------------------------------------------------------------------
3379//	  WRITE_12 - Command Builder									[PROTECTED]
3380//--------------------------------------------------------------------------------------------------
3381
3382bool
3383IOUSBMassStorageUFIDevice::WRITE_12 (
3384							SCSITaskIdentifier			request,
3385							IOMemoryDescriptor *		dataBuffer,
3386			    			UInt32						blockSize,
3387			    			SCSICmdField1Bit 			DPO,
3388							SCSICmdField1Bit 			EBP,
3389							SCSICmdField1Bit 			RELADR,
3390							SCSICmdField4Byte 			LOGICAL_BLOCK_ADDRESS,
3391							SCSICmdField4Byte 			TRANSFER_LENGTH )
3392{
3393
3394	UNUSED ( request );
3395	UNUSED ( dataBuffer );
3396	UNUSED ( blockSize );
3397	UNUSED ( DPO );
3398	UNUSED ( EBP );
3399	UNUSED ( RELADR );
3400	UNUSED ( LOGICAL_BLOCK_ADDRESS );
3401	UNUSED ( TRANSFER_LENGTH );
3402
3403	return false;
3404
3405}
3406
3407
3408//--------------------------------------------------------------------------------------------------
3409//	  WRITE_AND_VERIFY - Command Builder												 [PROTECTED]
3410//--------------------------------------------------------------------------------------------------
3411
3412bool
3413IOUSBMassStorageUFIDevice::WRITE_AND_VERIFY (
3414							SCSITaskIdentifier			request,
3415			    			IOMemoryDescriptor *		dataBuffer,
3416			    			UInt32						blockSize,
3417			    			SCSICmdField1Bit 			DPO,
3418			    			SCSICmdField1Bit 			BYTCHK,
3419			    			SCSICmdField1Bit 			RELADR,
3420			    			SCSICmdField4Byte			LOGICAL_BLOCK_ADDRESS,
3421			    			SCSICmdField2Byte 			TRANSFER_LENGTH )
3422{
3423
3424	UNUSED ( request );
3425	UNUSED ( dataBuffer );
3426	UNUSED ( blockSize );
3427	UNUSED ( DPO );
3428	UNUSED ( BYTCHK );
3429	UNUSED ( RELADR );
3430	UNUSED ( LOGICAL_BLOCK_ADDRESS );
3431	UNUSED ( TRANSFER_LENGTH );
3432
3433	return false;
3434
3435}
3436
3437
3438#pragma mark -
3439#pragma mark *** IOUSBMassStorageUFISubclass methods ***
3440#pragma mark -
3441
3442
3443//--------------------------------------------------------------------------------------------------
3444//	  BeginProvidedServices																 [PROTECTED]
3445//--------------------------------------------------------------------------------------------------
3446
3447bool
3448IOUSBMassStorageUFISubclass::BeginProvidedServices ( void )
3449{
3450	// Create the IOUSBMassStorageUFIDevice object
3451	IOUSBMassStorageUFIDevice * 	ufiDevice = OSTypeAlloc ( IOUSBMassStorageUFIDevice );
3452	if( ufiDevice == NULL )
3453	{
3454		STATUS_LOG ( ( 1, "%s[%p]::BeginProvidedServices failed", getName(), this ) );
3455		PANIC_NOW ( ( "IOUSBMassStorageUFISubclass::BeginProvidedServices failed" ) );
3456		return false;
3457	}
3458
3459	ufiDevice->init ( NULL );
3460
3461	if ( !ufiDevice->attach( this ) )
3462	{
3463		// panic since the nub can't attach
3464		PANIC_NOW ( ( "IOUSBMassStorageUFISubclass::BeginProvidedServices unable to attach nub" ) );
3465		return false;
3466	}
3467
3468	if ( ufiDevice->start( this ) == false )
3469	{
3470		ufiDevice->detach( this );
3471	}
3472
3473	STATUS_LOG ( ( 4, "%s[%p]::BeginProvidedServices exiting.", getName(), this ) );
3474
3475	ufiDevice->release();
3476
3477	return true;
3478
3479}
3480
3481
3482//--------------------------------------------------------------------------------------------------
3483//	  EndProvidedServices																 [PROTECTED]
3484//--------------------------------------------------------------------------------------------------
3485
3486bool
3487IOUSBMassStorageUFISubclass::EndProvidedServices ( void )
3488{
3489	return true;
3490}
3491