1/*
2 * Copyright (c) 2002-2007 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
30// SCSI Parallel Family includes
31#include "IOSCSIParallelInterfaceController.h"
32#include "IOSCSIParallelInterfaceDevice.h"
33#include "SCSIParallelTask.h"
34#include "SCSIParallelTimer.h"
35#include "SCSIParallelWorkLoop.h"
36
37// Libkern includes
38#include <libkern/OSAtomic.h>
39#include <libkern/c++/OSData.h>
40#include <libkern/c++/OSDictionary.h>
41#include <libkern/c++/OSNumber.h>
42#include <libkern/c++/OSString.h>
43
44// Generic IOKit includes
45#include <IOKit/IOLib.h>
46#include <IOKit/IOService.h>
47#include <IOKit/IOFilterInterruptEventSource.h>
48#include <IOKit/IOKitKeys.h>
49#include <IOKit/IOCommandPool.h>
50#include <IOKit/storage/IOStorageProtocolCharacteristics.h>
51#include <IOKit/storage/IOStorageDeviceCharacteristics.h>
52
53
54//-----------------------------------------------------------------------------
55//	Macros
56//-----------------------------------------------------------------------------
57
58
59#define DEBUG 												0
60#define DEBUG_ASSERT_COMPONENT_NAME_STRING					"SPI Controller"
61
62#if DEBUG
63#define SCSI_PARALLEL_INTERFACE_CONTROLLER_DEBUGGING_LEVEL	0
64#endif
65
66#include "IOSCSIParallelFamilyDebugging.h"
67
68#if ( SCSI_PARALLEL_INTERFACE_CONTROLLER_DEBUGGING_LEVEL >= 1 )
69#define PANIC_NOW(x)		panic x
70#else
71#define PANIC_NOW(x)
72#endif
73
74#if ( SCSI_PARALLEL_INTERFACE_CONTROLLER_DEBUGGING_LEVEL >= 2 )
75#define ERROR_LOG(x)		IOLog x
76#else
77#define ERROR_LOG(x)
78#endif
79
80#if ( SCSI_PARALLEL_INTERFACE_CONTROLLER_DEBUGGING_LEVEL >= 3 )
81#define STATUS_LOG(x)		IOLog x
82#else
83#define STATUS_LOG(x)
84#endif
85
86
87#define super IOService
88OSDefineMetaClass ( IOSCSIParallelInterfaceController, IOService );
89OSDefineAbstractStructors ( IOSCSIParallelInterfaceController, IOService );
90
91
92//-----------------------------------------------------------------------------
93//	Constants
94//-----------------------------------------------------------------------------
95
96#define kIOPropertySCSIInitiatorManagesTargets		"Manages Targets"
97#define kIOPropertyControllerCharacteristicsKey		"Controller Characteristics"
98#define kIOPropertyDeviceTreeEntryKey				"IODeviceTreeEntry"
99
100enum
101{
102	kWorldWideNameDataSize 		= 8,
103	kAddressIdentifierDataSize 	= 3,
104	kALPADataSize				= 1,
105	kSASAddressDataSize			= 8
106};
107
108enum
109{
110	kPhysicalInterconnectDictionaryEntryCount	= 3,
111	kHBAContraintsDictionaryEntryCount			= 7
112};
113
114
115//-----------------------------------------------------------------------------
116//	Static initialization
117//-----------------------------------------------------------------------------
118
119SInt32	IOSCSIParallelInterfaceController::fSCSIParallelDomainCount = 0;
120
121
122//-----------------------------------------------------------------------------
123//	Prototypes
124//-----------------------------------------------------------------------------
125
126static IOSCSIParallelInterfaceDevice *
127GetDevice (	SCSIParallelTaskIdentifier 	parallelTask );
128
129static void
130CopyProtocolCharacteristicsProperties ( OSDictionary * dict, IOService * service );
131
132
133#if 0
134#pragma mark -
135#pragma mark IOKit Member Routines
136#pragma mark -
137#endif
138
139
140//-----------------------------------------------------------------------------
141//	handleOpen - Handles opens on the object						  [PRIVATE]
142//-----------------------------------------------------------------------------
143
144bool
145IOSCSIParallelInterfaceController::handleOpen ( IOService *		client,
146												IOOptionBits	options,
147												void *			arg )
148{
149
150	bool	result = false;
151
152	STATUS_LOG ( ( "+IOSCSIParallelInterfaceController::handleOpen\n" ) );
153
154	result = fClients->setObject ( client );
155
156	STATUS_LOG ( ( "-IOSCSIParallelInterfaceController::handleOpen\n" ) );
157
158	return result;
159
160}
161
162
163//-----------------------------------------------------------------------------
164//	handleClose - Handles closes on the object						  [PRIVATE]
165//-----------------------------------------------------------------------------
166
167void
168IOSCSIParallelInterfaceController::handleClose (
169							IOService *		client,
170							IOOptionBits	options )
171{
172
173	STATUS_LOG ( ( "IOSCSIParallelInterfaceController::handleClose\n" ) );
174	fClients->removeObject ( client );
175
176}
177
178
179//-----------------------------------------------------------------------------
180//	handleIsOpen - Figures out if there are any opens on this object. [PRIVATE]
181//-----------------------------------------------------------------------------
182
183bool
184IOSCSIParallelInterfaceController::handleIsOpen ( const IOService * client ) const
185{
186
187	bool	result = false;
188
189	STATUS_LOG ( ( "+IOSCSIParallelInterfaceController::handleIsOpen\n" ) );
190
191	// Are they asking if a specific object has us open?
192	if ( client != NULL )
193	{
194		result = fClients->containsObject ( client );
195	}
196
197	// They're asking if we are open for any client
198	else
199	{
200		result = ( fClients->getCount ( ) > 0 ) ? true : false;
201	}
202
203	STATUS_LOG ( ( "-IOSCSIParallelInterfaceController::handleIsOpen\n" ) );
204
205	return result;
206
207}
208
209
210//-----------------------------------------------------------------------------
211//	start - Begins provided services.								  [PRIVATE]
212//-----------------------------------------------------------------------------
213
214bool
215IOSCSIParallelInterfaceController::start ( IOService * provider )
216{
217
218	OSDictionary *	dict		= NULL;
219	OSDictionary *	copyDict	= NULL;
220	OSNumber *		number		= NULL;
221	bool			result		= false;
222
223	STATUS_LOG ( ( "IOSCSIParallelInterfaceController start.\n" ) );
224
225	fSCSIDomainIdentifier = OSIncrementAtomic ( &fSCSIParallelDomainCount );
226
227	result = super::start ( provider );
228	require ( result, PROVIDER_START_FAILURE );
229
230	require_nonzero ( provider, PROVIDER_START_FAILURE );
231
232	result = provider->open ( this );
233	require ( result, PROVIDER_START_FAILURE );
234
235	fProvider					= provider;
236	fWorkLoop					= NULL;
237	fTimerEvent					= NULL;
238	fDispatchEvent				= NULL;
239	fControllerGate				= NULL;
240	fHBAHasBeenInitialized 		= false;
241	fHBACanAcceptClientRequests = false;
242	fClients					= OSSet::withCapacity ( 1 );
243
244	fDeviceLock = IOSimpleLockAlloc ( );
245	require_nonzero ( fDeviceLock, DEVICE_LOCK_ALLOC_FAILURE );
246
247	result = CreateWorkLoop ( provider );
248	require ( result, WORKLOOP_CREATE_FAILURE );
249
250	dict = OSDictionary::withCapacity ( 1 );
251	require_nonzero ( dict, CONTROLLER_DICT_FAILURE );
252
253	setProperty ( kIOPropertyControllerCharacteristicsKey, dict );
254	dict->release ( );
255	dict = NULL;
256
257	// See if a protocol characteristics property already exists for the controller
258	copyDict = OSDynamicCast ( OSDictionary, copyProperty ( kIOPropertyProtocolCharacteristicsKey ) );
259	if ( copyDict != NULL )
260	{
261
262		// Create a deep copy of the dictionary.
263		dict = ( OSDictionary * ) copyDict->copyCollection ( );
264		copyDict->release ( );
265
266	}
267
268	else
269	{
270
271		// A Protocol Characteristics dictionary could not be retrieved, so one
272		// will be created.
273		dict = OSDictionary::withCapacity ( kPhysicalInterconnectDictionaryEntryCount );
274
275	}
276
277	if ( dict != NULL )
278	{
279
280		OSNumber *	number = NULL;
281
282		// Copy any relevant properties from the IOService into the dictionary.
283		CopyProtocolCharacteristicsProperties ( dict, this );
284
285		// Set the domain ID.
286		number = OSNumber::withNumber ( fSCSIDomainIdentifier, 32 );
287		if ( number != NULL )
288		{
289
290			dict->setObject ( kIOPropertySCSIDomainIdentifierKey, number );
291			number->release ( );
292			number = NULL;
293
294		}
295
296		setProperty ( kIOPropertyProtocolCharacteristicsKey, dict );
297
298		// Release it since we created it.
299		dict->release ( );
300
301	}
302
303	// All the necessary preparation work has been done
304	// for this superclass, now Initialize the chip driver.
305	result = InitializeController ( );
306	require ( result, INIT_CONTROLLER_FAILURE );
307
308	// Retrieve the Initiator Identifier for this HBA.
309	fInitiatorIdentifier = ReportInitiatorIdentifier ( );
310	number = OSNumber::withNumber ( fInitiatorIdentifier, 64 );
311	if ( number != NULL )
312	{
313
314		setProperty ( kIOPropertySCSIInitiatorIdentifierKey, number );
315		number->release ( );
316		number = NULL;
317
318	}
319
320	// Now that the controller has been succesfully initialized, retrieve the
321	// necessary HBA specific information.
322	fHighestSupportedDeviceID = ReportHighestSupportedDeviceID ( );
323
324	// Set the Device List structure to an initial value
325	InitializeDeviceList ( );
326
327	fSupportedTaskCount = ReportMaximumTaskCount ( );
328
329	// Allocate the SCSIParallelTasks and the pool
330	result = AllocateSCSIParallelTasks ( );
331	require ( result, TASK_ALLOCATE_FAILURE );
332
333	// The HBA has been fully initialized and is now ready to provide
334	// its services to the system.
335	fHBAHasBeenInitialized = true;
336
337	result = StartController ( );
338	require ( result, START_CONTROLLER_FAILURE );
339
340	// The controller is now ready to accept requests, set the flag so
341	// that the commands will be accepted
342	fHBACanAcceptClientRequests = true;
343
344	// Enable interrupts for the work loop as the
345	// HBA child class may need it to start the controller.
346	fWorkLoop->enableAllInterrupts ( );
347
348	// Now create SCSI Device objects
349	result = DoesHBAPerformDeviceManagement ( );
350
351	// Set the property
352	setProperty ( kIOPropertySCSIInitiatorManagesTargets, result );
353
354	if ( result == false )
355	{
356
357		// This HBA does not support a mechanism for device attach/detach
358		// notification, go ahead and create target devices.
359		for ( UInt32 index = 0; index <= fHighestSupportedDeviceID; index++ )
360		{
361
362			CreateTargetForID ( index );
363
364		}
365
366	}
367
368	registerService ( );
369	result = true;
370
371	// The controller has been initialized and can accept requests.  Target
372	// devices have either been created, or the HBA will create them as needed.
373	return result;
374
375
376START_CONTROLLER_FAILURE:
377	// START_CONTROLLER_FAILURE:
378	// If execution jumped to this label, the HBA child class was unsuccessful
379	// at starting its sevices.
380
381	// First step is to release the allocated SCSI Parallel Tasks
382	DeallocateSCSIParallelTasks ( );
383
384
385TASK_ALLOCATE_FAILURE:
386	// TASK_ALLOCATE_FAILURE:
387	// If execution jumped to this label, SCSI Parallel Tasks failed to be
388	// allocated.
389
390	// Since the HBA child class was initialized, it needs to be terminated.
391	fHBAHasBeenInitialized = false;
392	TerminateController ( );
393
394
395INIT_CONTROLLER_FAILURE:
396	// INIT_CONTROLLER_FAILURE:
397	// If execution jumped to this label, the HBA child class failed to
398	// properly initialize.	Nothing to clean up, so fall through this label to
399	// next exception handling point.
400
401
402CONTROLLER_DICT_FAILURE:
403	// If execution jumped to this label, the HBA child class failed to
404	// create its controller characteristics dictionary.
405
406	// Release the workloop and associated objects.
407	ReleaseWorkLoop ( );
408
409
410WORKLOOP_CREATE_FAILURE:
411	// WORKLOOP_CREATE_FAILURE:
412	// If execution jumped to this label, the workloop or associated objects
413	// could not be allocated.
414	IOSimpleLockFree ( fDeviceLock );
415	fDeviceLock = NULL;
416
417
418DEVICE_LOCK_ALLOC_FAILURE:
419	// DEVICE_LOCK_ALLOC_FAILURE:
420	// Call the superclass to stop.
421	super::stop ( provider );
422
423
424PROVIDER_START_FAILURE:
425	// PROVIDER_START_FAILURE:
426	// If execution jumped to this label, the Provider was not successfully
427	// started, no cleanup needs to be done.
428
429	// Since the start attempt was not successful, report that by
430	// returning false.
431	return false;
432
433}
434
435
436//-----------------------------------------------------------------------------
437//	stop - Ends provided services.									  [PRIVATE]
438//-----------------------------------------------------------------------------
439
440void
441IOSCSIParallelInterfaceController::stop ( IOService * provider )
442{
443
444	// Halt all services from the subclass.
445	StopController ( );
446
447	if ( fHBAHasBeenInitialized == true )
448	{
449
450		fHBAHasBeenInitialized = false;
451
452		// Inform the subclass to terminate all allocated resources
453		TerminateController ( );
454
455	}
456
457	// Free all of the SCSIParallelTasks and the pool.
458	DeallocateSCSIParallelTasks ( );
459
460	// Release all WorkLoop related resources
461	ReleaseWorkLoop ( );
462
463	super::stop ( provider );
464
465}
466
467
468
469//-----------------------------------------------------------------------------
470//	free - Frees resources.											[PROTECTED]
471//-----------------------------------------------------------------------------
472
473void
474IOSCSIParallelInterfaceController::free ( void )
475{
476
477	if ( fDeviceLock != NULL )
478	{
479
480		IOSimpleLockFree ( fDeviceLock );
481		fDeviceLock = NULL;
482
483	}
484
485	super::free ( );
486
487}
488
489
490//-----------------------------------------------------------------------------
491//	willTerminate - Prevent HBA from accepting any further commands.
492//																	[PROTECTED]
493//-----------------------------------------------------------------------------
494
495bool
496IOSCSIParallelInterfaceController::willTerminate (
497	IOService * 		provider,
498	IOOptionBits		options )
499{
500
501	SCSITargetIdentifier	index = 0;
502
503	// Prevent any new requests from being sent to the controller.
504	fHBACanAcceptClientRequests = false;
505
506	for ( index = 0; index < fHighestSupportedDeviceID; index++ )
507	{
508		DestroyTargetForID ( index );
509	}
510
511	return true;
512
513}
514
515
516//-----------------------------------------------------------------------------
517//	didTerminate - Closes provider if all outstanding I/O is complete.
518//																	[PROTECTED]
519//-----------------------------------------------------------------------------
520
521bool
522IOSCSIParallelInterfaceController::didTerminate (
523	IOService * 		provider,
524	IOOptionBits		options,
525	bool *				defer )
526{
527
528	if ( fProvider->isOpen ( this ) == true )
529	{
530		fProvider->close ( this );
531	}
532
533	return true;
534
535}
536
537
538//-----------------------------------------------------------------------------
539//	getWorkLoop - Gets the workloop.								  [PRIVATE]
540//-----------------------------------------------------------------------------
541
542IOWorkLoop *
543IOSCSIParallelInterfaceController::getWorkLoop ( void ) const
544{
545	return GetWorkLoop ( );
546}
547
548
549//-----------------------------------------------------------------------------
550//	GetProvider - Gets the provider object.							[PROTECTED]
551//-----------------------------------------------------------------------------
552
553IOService *
554IOSCSIParallelInterfaceController::GetProvider ( void )
555{
556	return fProvider;
557}
558
559
560//-----------------------------------------------------------------------------
561//	GetSCSIDomainIdentifier - Gets the domain identifier.			[PROTECTED]
562//-----------------------------------------------------------------------------
563
564SInt32
565IOSCSIParallelInterfaceController::GetSCSIDomainIdentifier ( void )
566{
567	return fSCSIDomainIdentifier;
568}
569
570
571#if 0
572#pragma mark -
573#pragma mark Property Management
574#pragma mark -
575#endif
576
577
578//-----------------------------------------------------------------------------
579//	SetHBAProperty - Sets a property for this object.	 			   [PUBLIC]
580//-----------------------------------------------------------------------------
581
582bool
583IOSCSIParallelInterfaceController::SetHBAProperty (
584									const char *	key,
585									OSObject *	 	value )
586{
587
588	bool			result 		= false;
589	OSDictionary *	hbaDict		= NULL;
590	OSDictionary *	copyDict	= NULL;
591
592	require_nonzero ( key, ErrorExit );
593	require_nonzero ( value, ErrorExit );
594
595	// We should be within a synchronized context (i.e. holding the workloop lock),
596	if ( fWorkLoop->inGate ( ) == false )
597	{
598
599		// Let's make sure to grab the lock and call this routine again.
600		result = fControllerGate->runAction (
601					OSMemberFunctionCast (
602						IOCommandGate::Action,
603						this,
604						&IOSCSIParallelInterfaceController::SetHBAProperty ),
605					( void * ) key,
606					( void * ) value );
607
608		goto ErrorExit;
609
610	}
611
612	copyDict = OSDynamicCast ( OSDictionary, copyProperty ( kIOPropertyControllerCharacteristicsKey ) );
613	require_nonzero ( copyDict, ErrorExit );
614
615	hbaDict = ( OSDictionary * ) copyDict->copyCollection ( );
616	copyDict->release ( );
617
618	require_nonzero ( hbaDict, ErrorExit );
619
620	if ( strcmp ( key, kIOPropertyVendorNameKey ) == 0 )
621	{
622		result = hbaDict->setObject ( key, value );
623	}
624
625	else if ( strcmp ( key, kIOPropertyProductNameKey ) == 0 )
626	{
627		result = hbaDict->setObject ( key, value );
628	}
629
630	else if ( strcmp ( key, kIOPropertyProductRevisionLevelKey ) == 0 )
631	{
632		result = hbaDict->setObject ( key, value );
633	}
634
635	else if ( strcmp ( key, kIOPropertyPortDescriptionKey ) == 0 )
636	{
637		result = hbaDict->setObject ( key, value );
638	}
639
640	else if ( strcmp ( key, kIOPropertyPortSpeedKey ) == 0 )
641	{
642		result = hbaDict->setObject ( key, value );
643	}
644
645	else if ( strcmp ( key, kIOPropertySCSIParallelSignalingTypeKey ) == 0 )
646	{
647		result = hbaDict->setObject ( key, value );
648	}
649
650	else if ( strcmp ( key, kIOPropertyFibreChannelCableDescriptionKey ) == 0 )
651	{
652		result = hbaDict->setObject ( key, value );
653	}
654
655	else if ( strcmp ( key, kIOPropertyFibreChannelPortWorldWideNameKey ) == 0 )
656	{
657
658		OSData * data = OSDynamicCast ( OSData, value );
659
660		require_nonzero ( data, ErrorExit );
661		require ( ( data->getLength ( ) == kWorldWideNameDataSize ), ErrorExit );
662		result = hbaDict->setObject ( key, value );
663		result = hbaDict->setObject ( kIOPropertySCSIPortIdentifierKey, value );
664
665	}
666
667	else if ( strcmp ( key, kIOPropertyFibreChannelNodeWorldWideNameKey ) == 0 )
668	{
669
670		OSData * data = OSDynamicCast ( OSData, value );
671
672		require_nonzero ( data, ErrorExit );
673		require ( ( data->getLength ( ) == kWorldWideNameDataSize ), ErrorExit );
674		result = hbaDict->setObject ( key, value );
675
676	}
677
678	else if ( strcmp ( key, kIOPropertyFibreChannelAddressIdentifierKey ) == 0 )
679	{
680
681		OSData * data = OSDynamicCast ( OSData, value );
682
683		require_nonzero ( data, ErrorExit );
684		require ( ( data->getLength ( ) == kAddressIdentifierDataSize ), ErrorExit );
685		result = hbaDict->setObject ( key, value );
686
687	}
688
689	else if ( strcmp ( key, kIOPropertyFibreChannelALPAKey ) == 0 )
690	{
691
692		OSData * data = OSDynamicCast ( OSData, value );
693
694		require_nonzero ( data, ErrorExit );
695		require ( ( data->getLength ( ) == kALPADataSize ), ErrorExit );
696		result = hbaDict->setObject ( key, value );
697
698	}
699
700	else if ( strcmp ( key, kIOPropertyPortTopologyKey ) == 0 )
701	{
702		result = hbaDict->setObject ( key, value );
703	}
704
705	else if ( strcmp ( key, kIOPropertySASAddressKey ) == 0 )
706	{
707
708		OSData * data = OSDynamicCast ( OSData, value );
709
710		require_nonzero ( data, ErrorExit );
711		require ( ( data->getLength ( ) == kSASAddressDataSize ), ErrorExit );
712		result = hbaDict->setObject ( key, value );
713		result = hbaDict->setObject ( kIOPropertySCSIPortIdentifierKey, value );
714
715	}
716
717	else
718	{
719		ERROR_LOG ( ( "SetHBAProperty: Unrecognized property key = %s", key ) );
720	}
721
722	setProperty ( kIOPropertyControllerCharacteristicsKey, hbaDict );
723	hbaDict->release ( );
724	hbaDict = NULL;
725
726	messageClients ( kIOMessageServicePropertyChange );
727
728
729ErrorExit:
730
731
732	return result;
733
734}
735
736
737//-----------------------------------------------------------------------------
738//	RemoveHBAProperty - Removes a property for this object. 		   [PUBLIC]
739//-----------------------------------------------------------------------------
740
741void
742IOSCSIParallelInterfaceController::RemoveHBAProperty ( const char * key )
743{
744
745	OSDictionary *	hbaDict		= NULL;
746	OSDictionary *	copyDict	= NULL;
747
748	require_nonzero ( key, ErrorExit );
749
750	// We should be within a synchronized context (i.e. holding the workloop lock),
751	if ( fWorkLoop->inGate ( ) == false )
752	{
753
754		// Let's make sure to grab the lock and call this routine again.
755		fControllerGate->runAction (
756			OSMemberFunctionCast (
757				IOCommandGate::Action,
758				this,
759				&IOSCSIParallelInterfaceController::RemoveHBAProperty ),
760			( void * ) key );
761
762		goto ErrorExit;
763
764	}
765
766	copyDict = OSDynamicCast ( OSDictionary, copyProperty ( kIOPropertyControllerCharacteristicsKey ) );
767	require_nonzero ( copyDict, ErrorExit );
768
769	hbaDict = ( OSDictionary * ) copyDict->copyCollection ( );
770	copyDict->release ( );
771
772	require_nonzero ( hbaDict, ErrorExit );
773
774	if ( hbaDict->getObject ( key ) != NULL )
775	{
776
777		hbaDict->removeObject ( key );
778
779	}
780
781	setProperty ( kIOPropertyControllerCharacteristicsKey, hbaDict );
782	hbaDict->release ( );
783	hbaDict = NULL;
784
785	messageClients ( kIOMessageServicePropertyChange );
786
787
788ErrorExit:
789
790
791	return;
792
793}
794
795
796#if 0
797#pragma mark -
798#pragma mark WorkLoop Management
799#pragma mark -
800#endif
801
802
803//-----------------------------------------------------------------------------
804//	GetWorkLoop - Gets the workloop.								[PROTECTED]
805//-----------------------------------------------------------------------------
806
807IOWorkLoop *
808IOSCSIParallelInterfaceController::GetWorkLoop ( void ) const
809{
810	return fWorkLoop;
811}
812
813
814//-----------------------------------------------------------------------------
815//	GetCommandGate - Gets the command gate.							[PROTECTED]
816//-----------------------------------------------------------------------------
817
818IOCommandGate *
819IOSCSIParallelInterfaceController::GetCommandGate ( void )
820{
821	return fControllerGate;
822}
823
824
825//-----------------------------------------------------------------------------
826//	CreateWorkLoop - Creates the workloop and associated objects.	  [PRIVATE]
827//-----------------------------------------------------------------------------
828
829bool
830IOSCSIParallelInterfaceController::CreateWorkLoop ( IOService * provider )
831{
832
833	bool		result = false;
834	IOReturn	status = kIOReturnSuccess;
835	char		lockGroupName[64];
836
837	bzero ( lockGroupName, sizeof ( lockGroupName ) );
838
839	snprintf ( lockGroupName, 64, "SCSI Domain %d", ( int ) fSCSIDomainIdentifier );
840
841	if ( fWorkLoop == NULL )
842	{
843
844		fWorkLoop = SCSIParallelWorkLoop::Create ( lockGroupName );
845		require_nonzero ( fWorkLoop, CREATE_WORKLOOP_FAILURE );
846
847	}
848
849	// Create a timer.
850	fTimerEvent = SCSIParallelTimer::CreateTimerEventSource ( this,
851			( IOTimerEventSource::Action ) &IOSCSIParallelInterfaceController::TimeoutOccurred );
852	require_nonzero ( fTimerEvent, TIMER_CREATION_FAILURE );
853
854	// Add the timer to the workloop.
855	status = fWorkLoop->addEventSource ( fTimerEvent );
856	require_success ( status, ADD_TES_FAILURE );
857
858	// Ask the subclass to create the device interrupt.
859	fDispatchEvent = CreateDeviceInterrupt (
860		&IOSCSIParallelInterfaceController::ServiceInterrupt,
861		&IOSCSIParallelInterfaceController::FilterInterrupt,
862		provider );
863
864	// Virtual HBAs or HBAs that want to handle interrupts differently might
865	// return NULL. We'll allow that, but they'll have to deal with things
866	// themselves.
867	if ( fDispatchEvent != NULL )
868	{
869
870		// Add the interrupt event source to the workloop.
871		status = fWorkLoop->addEventSource ( fDispatchEvent );
872		require_success ( status, ADD_ISR_EVENT_FAILURE );
873
874	}
875
876	// Create a command gate.
877	fControllerGate = IOCommandGate::commandGate ( this, NULL );
878	require_nonzero ( fControllerGate, ALLOCATE_COMMAND_GATE_FAILURE );
879
880	// Add the command gate to the workloop.
881	status = fWorkLoop->addEventSource ( fControllerGate );
882	require_success ( status,  ADD_GATE_EVENT_FAILURE );
883
884	result = true;
885
886	return result;
887
888
889ADD_GATE_EVENT_FAILURE:
890
891
892	require_nonzero_quiet ( fControllerGate, ALLOCATE_COMMAND_GATE_FAILURE );
893	fControllerGate->release ( );
894	fControllerGate = NULL;
895
896
897ALLOCATE_COMMAND_GATE_FAILURE:
898
899
900	if ( fDispatchEvent != NULL )
901	{
902		fWorkLoop->removeEventSource ( fDispatchEvent );
903	}
904
905
906ADD_ISR_EVENT_FAILURE:
907
908
909	if ( fDispatchEvent != NULL )
910	{
911
912		fDispatchEvent->release ( );
913		fDispatchEvent = NULL;
914
915	}
916
917	fWorkLoop->removeEventSource ( fTimerEvent );
918
919
920ADD_TES_FAILURE:
921
922
923	require_nonzero_quiet ( fTimerEvent, TIMER_CREATION_FAILURE );
924	fTimerEvent->release ( );
925	fTimerEvent = NULL;
926
927
928TIMER_CREATION_FAILURE:
929
930
931	require_nonzero_quiet ( fWorkLoop, CREATE_WORKLOOP_FAILURE );
932	fWorkLoop->release ( );
933	fWorkLoop = NULL;
934
935
936CREATE_WORKLOOP_FAILURE:
937
938
939	return result;
940
941}
942
943
944//-----------------------------------------------------------------------------
945//	ReleaseWorkLoop - Releases the workloop and associated objects.	  [PRIVATE]
946//-----------------------------------------------------------------------------
947
948void
949IOSCSIParallelInterfaceController::ReleaseWorkLoop ( void )
950{
951
952	// Make sure we have a workloop.
953	if ( fWorkLoop != NULL )
954	{
955
956		// Remove all the event sources from the workloop
957		// and deallocate them.
958
959		if ( fControllerGate != NULL )
960		{
961
962			fWorkLoop->removeEventSource ( fControllerGate );
963			fControllerGate->release ( );
964			fControllerGate = NULL;
965
966		}
967
968		if ( fTimerEvent != NULL )
969		{
970
971			fWorkLoop->removeEventSource ( fTimerEvent );
972			fTimerEvent->release ( );
973			fTimerEvent = NULL;
974
975		}
976
977		if ( fDispatchEvent != NULL )
978		{
979
980			fWorkLoop->removeEventSource ( fDispatchEvent );
981			fDispatchEvent->release ( );
982			fDispatchEvent = NULL;
983
984		}
985
986		fWorkLoop->release ( );
987		fWorkLoop = NULL;
988
989	}
990
991}
992
993
994#if 0
995#pragma mark -
996#pragma mark SCSI Parallel Task Management
997#pragma mark -
998#endif
999
1000
1001//-----------------------------------------------------------------------------
1002//	GetSCSIParallelTask - Gets a parallel task from the pool.		   [PUBLIC]
1003//-----------------------------------------------------------------------------
1004
1005SCSIParallelTaskIdentifier
1006IOSCSIParallelInterfaceController::GetSCSIParallelTask ( bool blockForCommand )
1007{
1008
1009	SCSIParallelTask *		parallelTask = NULL;
1010
1011	parallelTask = ( SCSIParallelTask * ) fParallelTaskPool->getCommand ( blockForCommand );
1012	if ( parallelTask != NULL )
1013	{
1014		parallelTask->ResetForNewTask ( );
1015	}
1016
1017	return ( SCSIParallelTaskIdentifier ) parallelTask;
1018
1019}
1020
1021
1022//-----------------------------------------------------------------------------
1023//	FreeSCSIParallelTask - Returns a parallel task to the pool.		   [PUBLIC]
1024//-----------------------------------------------------------------------------
1025
1026void
1027IOSCSIParallelInterfaceController::FreeSCSIParallelTask (
1028							SCSIParallelTaskIdentifier returnTask )
1029{
1030
1031	SCSIParallelTask *	parallelTask	= NULL;
1032	IOReturn			status			= kIOReturnSuccess;
1033
1034	parallelTask = OSDynamicCast ( SCSIParallelTask, returnTask );
1035
1036	require_nonzero ( parallelTask, ERROR_EXIT_NULL_TASK );
1037
1038	parallelTask->SetSCSITaskIdentifier ( NULL );
1039
1040	status = parallelTask->clearMemoryDescriptor ( false );
1041
1042	if ( status != kIOReturnSuccess )
1043	{
1044
1045		ERROR_LOG ( ( "FreeSCSIParallelTask: Task %p seems to be still active. "
1046					"IODMACommand::complete ( ) may not have been called for "
1047					"this task.", returnTask ) );
1048
1049	}
1050
1051	fParallelTaskPool->returnCommand ( ( IOCommand * ) returnTask );
1052
1053	return;
1054
1055
1056ERROR_EXIT_NULL_TASK:
1057
1058
1059	STATUS_LOG ( ( "FreeSCSIParallelTask: Encountered a NULL task pointer!\n" ) );
1060
1061	return;
1062
1063}
1064
1065
1066//-----------------------------------------------------------------------------
1067//	AllocateSCSIParallelTasks - Allocates parallel tasks for the pool.
1068//																	  [PRIVATE]
1069//-----------------------------------------------------------------------------
1070
1071bool
1072IOSCSIParallelInterfaceController::AllocateSCSIParallelTasks ( void )
1073{
1074
1075	bool				result			= false;
1076	SCSIParallelTask *	parallelTask 	= NULL;
1077	UInt32				taskSize		= 0;
1078	UInt32				index			= 0;
1079	UInt64				mask			= 0;
1080	OSNumber *			value			= NULL;
1081	OSDictionary *		constraints		= NULL;
1082	OSObject *			obj				= NULL;
1083
1084	// Default alignment is 16-byte aligned, 32-bit memory only.
1085	taskSize 	= ReportHBASpecificTaskDataSize ( );
1086	constraints = OSDictionary::withCapacity ( kHBAContraintsDictionaryEntryCount );
1087
1088	require_nonzero ( constraints, ERROR_EXIT );
1089
1090	ReportHBAConstraints ( constraints );
1091
1092	// Set constraints for cluster layer / IOBlockStorageDriver.
1093	value = OSDynamicCast ( OSNumber, constraints->getObject ( kIOMaximumSegmentCountReadKey ) );
1094	if ( value != NULL )
1095	{
1096		setProperty ( kIOMaximumSegmentCountReadKey, value );
1097	}
1098
1099	value = OSDynamicCast ( OSNumber, constraints->getObject ( kIOMaximumSegmentCountWriteKey ) );
1100	if ( value != NULL )
1101	{
1102		setProperty ( kIOMaximumSegmentCountWriteKey, value );
1103	}
1104
1105	value = OSDynamicCast ( OSNumber, constraints->getObject ( kIOMaximumSegmentByteCountReadKey ) );
1106	if ( value != NULL )
1107	{
1108		setProperty ( kIOMaximumSegmentByteCountReadKey, value );
1109	}
1110
1111	value = OSDynamicCast ( OSNumber, constraints->getObject ( kIOMaximumSegmentByteCountWriteKey ) );
1112	if ( value != NULL )
1113	{
1114		setProperty ( kIOMaximumSegmentByteCountWriteKey, value );
1115	}
1116
1117	value = OSDynamicCast ( OSNumber, constraints->getObject ( kIOMinimumSegmentAlignmentByteCountKey ) );
1118	if ( value != NULL )
1119	{
1120		setProperty ( kIOMinimumSegmentAlignmentByteCountKey, value );
1121	}
1122
1123	value = OSDynamicCast ( OSNumber, constraints->getObject ( kIOMaximumSegmentAddressableBitCountKey ) );
1124	if ( value != NULL )
1125	{
1126		setProperty ( kIOMaximumSegmentAddressableBitCountKey, value );
1127	}
1128
1129	value = OSDynamicCast ( OSNumber, constraints->getObject ( kIOMinimumHBADataAlignmentMaskKey ) );
1130	mask  = value->unsigned64BitValue ( );
1131
1132	obj = constraints->getObject ( kIOHierarchicalLogicalUnitSupportKey );
1133	if ( obj != NULL )
1134	{
1135		setProperty ( kIOHierarchicalLogicalUnitSupportKey, obj );
1136	}
1137
1138	constraints->release ( );
1139	constraints = NULL;
1140
1141	fParallelTaskPool = IOCommandPool::withWorkLoop ( fWorkLoop );
1142	require_nonzero ( fParallelTaskPool, POOL_CREATION_FAILURE );
1143
1144	// As long as a single SCSI Parallel Task can be allocated, the HBA
1145	// can function.  Check to see if the first one can be allocated.
1146	parallelTask = SCSIParallelTask::Create ( taskSize, mask );
1147	require_nonzero ( parallelTask, TASK_CREATION_FAILURE );
1148
1149	result = InitializeDMASpecification ( parallelTask );
1150	require ( result, TASK_INIT_FAILURE );
1151
1152	// Send the single command into the pool.
1153	fParallelTaskPool->returnCommand ( parallelTask );
1154
1155	// Now try to allocate the remaining Tasks that the HBA reports that it
1156	// can support.
1157	for ( index = 1; index < fSupportedTaskCount; index++ )
1158	{
1159
1160		// Allocate the command with enough space for the HBA specific data
1161		parallelTask = SCSIParallelTask::Create ( taskSize, mask );
1162		if ( parallelTask != NULL )
1163		{
1164
1165			result = InitializeDMASpecification ( parallelTask );
1166			if ( result == false )
1167			{
1168
1169				parallelTask->release ( );
1170				break;
1171
1172			}
1173
1174			// Send the next command into the pool.
1175			fParallelTaskPool->returnCommand ( parallelTask );
1176
1177		}
1178
1179	}
1180
1181	// Did the subclass override the command pool size?
1182	value = OSDynamicCast ( OSNumber, getProperty ( kIOCommandPoolSizeKey ) );
1183	if ( value == NULL )
1184	{
1185
1186		// No, set the default to be the number of commands we allocated.
1187		setProperty ( kIOCommandPoolSizeKey, index, 32 );
1188
1189	}
1190
1191	// Since at least a single SCSI Parallel Task was allocated, this
1192	// HBA can function.
1193	result = true;
1194
1195	return result;
1196
1197
1198TASK_INIT_FAILURE:
1199
1200
1201	require_nonzero ( parallelTask, TASK_CREATION_FAILURE );
1202	parallelTask->release ( );
1203	parallelTask = NULL;
1204
1205
1206TASK_CREATION_FAILURE:
1207
1208
1209	require_nonzero ( fParallelTaskPool, POOL_CREATION_FAILURE );
1210	fParallelTaskPool->release ( );
1211	fParallelTaskPool = NULL;
1212
1213
1214POOL_CREATION_FAILURE:
1215ERROR_EXIT:
1216
1217
1218	return result;
1219
1220}
1221
1222
1223//-----------------------------------------------------------------------------
1224//	DeallocateSCSIParallelTasks - Deallocates parallel tasks in the pool.
1225//																	  [PRIVATE]
1226//-----------------------------------------------------------------------------
1227
1228void
1229IOSCSIParallelInterfaceController::DeallocateSCSIParallelTasks ( void )
1230{
1231
1232	SCSIParallelTask *	parallelTask = NULL;
1233
1234	require_nonzero ( fParallelTaskPool, Exit );
1235
1236	parallelTask = ( SCSIParallelTask * ) fParallelTaskPool->getCommand ( false );
1237	while ( parallelTask != NULL )
1238	{
1239
1240		parallelTask->release ( );
1241		parallelTask = ( SCSIParallelTask * ) fParallelTaskPool->getCommand ( false );
1242
1243	}
1244
1245	fParallelTaskPool->release ( );
1246	fParallelTaskPool = NULL;
1247
1248
1249Exit:
1250
1251
1252	return;
1253
1254}
1255
1256
1257#if 0
1258#pragma mark -
1259#pragma mark SCSI Parallel Task Execution
1260#pragma mark -
1261#endif
1262
1263
1264//-----------------------------------------------------------------------------
1265//	ExecuteParallelTask - Executes a parallel task.					   [PUBLIC]
1266//-----------------------------------------------------------------------------
1267
1268SCSIServiceResponse
1269IOSCSIParallelInterfaceController::ExecuteParallelTask (
1270							SCSIParallelTaskIdentifier 			parallelRequest )
1271{
1272
1273	SCSIServiceResponse	serviceResponse = kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE;
1274
1275	// If the controller has requested a suspend,
1276	// return the command and let it add it back to the queue.
1277	if ( fHBACanAcceptClientRequests == true )
1278	{
1279
1280		// If the controller has not suspended, send the task now.
1281		serviceResponse = ProcessParallelTask ( parallelRequest );
1282
1283	}
1284
1285	return serviceResponse;
1286
1287}
1288
1289
1290//-----------------------------------------------------------------------------
1291//	CompleteParallelTask - Completes a parallel task.				[PROTECTED]
1292//-----------------------------------------------------------------------------
1293
1294void
1295IOSCSIParallelInterfaceController::CompleteParallelTask (
1296							SCSIParallelTaskIdentifier 	parallelRequest,
1297							SCSITaskStatus	 			completionStatus,
1298							SCSIServiceResponse 		serviceResponse )
1299{
1300
1301	IOSCSIParallelInterfaceDevice *		target = NULL;
1302
1303	STATUS_LOG ( ( "+IOSCSIParallelInterfaceController::CompleteParallelTask\n" ) );
1304
1305	// We should be within a synchronized context (i.e. holding the workloop lock),
1306	// but some subclassers aren't so bright. <sigh>
1307	if ( fWorkLoop->inGate ( ) == false )
1308	{
1309
1310		// Let's make sure to grab the lock and call this routine again.
1311		fControllerGate->runAction (
1312			OSMemberFunctionCast (
1313				IOCommandGate::Action,
1314				this,
1315				&IOSCSIParallelInterfaceController::CompleteParallelTask ),
1316			parallelRequest,
1317			( void * ) completionStatus,
1318			( void * ) serviceResponse );
1319
1320		goto Exit;
1321
1322	}
1323
1324	// Remove the task from the timeout list.
1325	( ( SCSIParallelTimer * ) fTimerEvent )->RemoveTask ( parallelRequest );
1326
1327	target = GetDevice ( parallelRequest );
1328	require_nonzero ( target, Exit );
1329
1330	// Complete the command
1331	target->CompleteSCSITask (	parallelRequest,
1332								serviceResponse,
1333								completionStatus );
1334
1335
1336Exit:
1337
1338
1339	STATUS_LOG ( ( "-IOSCSIParallelInterfaceController::CompleteParallelTask\n" ) );
1340	return;
1341
1342}
1343
1344
1345//-----------------------------------------------------------------------------
1346//	FindTaskForAddress - Finds a task by its address (ITLQ nexus)	   [PUBLIC]
1347//-----------------------------------------------------------------------------
1348
1349SCSIParallelTaskIdentifier
1350IOSCSIParallelInterfaceController::FindTaskForAddress (
1351							SCSIDeviceIdentifier 		theT,
1352							SCSILogicalUnitNumber		theL,
1353							SCSITaggedTaskIdentifier	theQ )
1354{
1355
1356	SCSIParallelTaskIdentifier			task	= NULL;
1357	IOSCSIParallelInterfaceDevice *		target 	= NULL;
1358
1359	target = GetTargetForID ( theT );
1360	require_nonzero ( target, Exit );
1361
1362	// A valid object exists for the target ID, request that it find
1363	// the task on its outstanding queue.
1364	task = target->FindTaskForAddress ( theL, theQ );
1365
1366
1367Exit:
1368
1369
1370	return task;
1371
1372}
1373
1374
1375//-----------------------------------------------------------------------------
1376//	FindTaskForControllerIdentifier - Finds a task by its unique ID	   [PUBLIC]
1377//-----------------------------------------------------------------------------
1378
1379SCSIParallelTaskIdentifier
1380IOSCSIParallelInterfaceController::FindTaskForControllerIdentifier (
1381							SCSIDeviceIdentifier 		theTarget,
1382							UInt64						theIdentifier )
1383{
1384
1385	SCSIParallelTaskIdentifier			task	= NULL;
1386	IOSCSIParallelInterfaceDevice *		target 	= NULL;
1387
1388	target = GetTargetForID ( theTarget );
1389	require_nonzero ( target, Exit );
1390
1391	// A valid object exists for the target ID, request that it find
1392	// the task on its outstanding queue.
1393	task = target->FindTaskForControllerIdentifier ( theIdentifier );
1394
1395
1396Exit:
1397
1398
1399	return task;
1400
1401}
1402
1403// The completion callback for the SAM-2 Task Management functions.
1404// The implementation for these will be added when the support for these
1405// are added in the SCSI Parallel Interface Device object
1406
1407//-----------------------------------------------------------------------------
1408//	CompleteAbortTask - Completes the AbortTaskRequest.	 			[PROTECTED]
1409//-----------------------------------------------------------------------------
1410
1411void
1412IOSCSIParallelInterfaceController::CompleteAbortTask (
1413					SCSITargetIdentifier 		theT,
1414					SCSILogicalUnitNumber		theL,
1415					SCSITaggedTaskIdentifier	theQ,
1416					SCSIServiceResponse 		serviceResponse )
1417{
1418}
1419
1420
1421//-----------------------------------------------------------------------------
1422//	CompleteAbortTaskSet - Completes the AbortTaskSetRequest.		[PROTECTED]
1423//-----------------------------------------------------------------------------
1424
1425void
1426IOSCSIParallelInterfaceController::CompleteAbortTaskSet (
1427					SCSITargetIdentifier 		theT,
1428					SCSILogicalUnitNumber		theL,
1429					SCSIServiceResponse 		serviceResponse )
1430{
1431}
1432
1433
1434//-----------------------------------------------------------------------------
1435//	CompleteClearACA - Completes the ClearACARequest.				[PROTECTED]
1436//-----------------------------------------------------------------------------
1437
1438void
1439IOSCSIParallelInterfaceController::CompleteClearACA (
1440					SCSITargetIdentifier 		theT,
1441					SCSILogicalUnitNumber		theL,
1442					SCSIServiceResponse 		serviceResponse )
1443{
1444}
1445
1446
1447//-----------------------------------------------------------------------------
1448//	CompleteClearTaskSet - Completes the ClearTaskSetRequest.		[PROTECTED]
1449//-----------------------------------------------------------------------------
1450
1451void
1452IOSCSIParallelInterfaceController::CompleteClearTaskSet (
1453					SCSITargetIdentifier 		theT,
1454					SCSILogicalUnitNumber		theL,
1455					SCSIServiceResponse 		serviceResponse )
1456{
1457}
1458
1459
1460//-----------------------------------------------------------------------------
1461//	CompleteLogicalUnitReset - Completes the LogicalUnitResetRequest.
1462//																	[PROTECTED]
1463//-----------------------------------------------------------------------------
1464
1465void
1466IOSCSIParallelInterfaceController::CompleteLogicalUnitReset (
1467					SCSITargetIdentifier 		theT,
1468					SCSILogicalUnitNumber		theL,
1469					SCSIServiceResponse 		serviceResponse )
1470{
1471}
1472
1473
1474//-----------------------------------------------------------------------------
1475//	CompleteTargetReset - Completes the TargetResetRequest  		[PROTECTED]
1476//-----------------------------------------------------------------------------
1477
1478void
1479IOSCSIParallelInterfaceController::CompleteTargetReset (
1480					SCSITargetIdentifier 		theT,
1481					SCSIServiceResponse 		serviceResponse )
1482{
1483}
1484
1485
1486//-----------------------------------------------------------------------------
1487//	ServiceInterrupt - Calls the registered interrupt handler. 		  [PRIVATE]
1488//-----------------------------------------------------------------------------
1489
1490void
1491IOSCSIParallelInterfaceController::ServiceInterrupt (
1492							OSObject *					theObject,
1493							IOInterruptEventSource *	theSource,
1494							int							count  )
1495{
1496	( ( IOSCSIParallelInterfaceController * ) theObject )->HandleInterruptRequest ( );
1497}
1498
1499
1500//-----------------------------------------------------------------------------
1501//	FilterInterrupt - Calls the registered interrupt filter. 		  [PRIVATE]
1502//-----------------------------------------------------------------------------
1503
1504bool
1505IOSCSIParallelInterfaceController::FilterInterrupt (
1506							OSObject *						theObject,
1507							IOFilterInterruptEventSource *	theSource  )
1508{
1509	return ( ( IOSCSIParallelInterfaceController * ) theObject )->FilterInterruptRequest ( );
1510}
1511
1512
1513//-----------------------------------------------------------------------------
1514//	FilterInterruptRequest - Default filter routine. 				[PROTECTED]
1515//-----------------------------------------------------------------------------
1516
1517bool
1518IOSCSIParallelInterfaceController::FilterInterruptRequest ( void )
1519{
1520	return true;
1521}
1522
1523
1524//-----------------------------------------------------------------------------
1525//	EnableInterrupt - Enables the interrupt event source.	  		[PROTECTED]
1526//-----------------------------------------------------------------------------
1527
1528void
1529IOSCSIParallelInterfaceController::EnableInterrupt ( void )
1530{
1531
1532	if ( fDispatchEvent != NULL )
1533	{
1534		fDispatchEvent->enable ( );
1535	}
1536
1537}
1538
1539
1540//-----------------------------------------------------------------------------
1541//	DisableInterrupt - Disables the interrupt event source.	  		[PROTECTED]
1542//-----------------------------------------------------------------------------
1543
1544void
1545IOSCSIParallelInterfaceController::DisableInterrupt ( void )
1546{
1547
1548	if ( fDispatchEvent != NULL )
1549	{
1550		fDispatchEvent->disable ( );
1551	}
1552
1553}
1554
1555
1556//-----------------------------------------------------------------------------
1557//	SignalInterrupt - Cause the work loop to schedule the interrupt action
1558//					  even if the filter routine returns false.		[PROTECTED]
1559//-----------------------------------------------------------------------------
1560
1561void
1562IOSCSIParallelInterfaceController::SignalInterrupt ( void )
1563{
1564
1565	if ( fDispatchEvent != NULL )
1566	{
1567		( ( IOFilterInterruptEventSource * ) fDispatchEvent )->signalInterrupt ( );
1568	}
1569
1570}
1571
1572
1573#if 0
1574#pragma mark -
1575#pragma mark Timeout Management
1576#pragma mark -
1577#endif
1578
1579
1580//-----------------------------------------------------------------------------
1581//	SetTimeoutForTask - Sets the timeout.					  		[PROTECTED]
1582//-----------------------------------------------------------------------------
1583
1584void
1585IOSCSIParallelInterfaceController::SetTimeoutForTask (
1586							SCSIParallelTaskIdentifier 		parallelTask,
1587							UInt32							timeoutOverride )
1588{
1589
1590	( ( SCSIParallelTimer * ) fTimerEvent )->SetTimeout (	parallelTask,
1591															timeoutOverride );
1592
1593}
1594
1595
1596//-----------------------------------------------------------------------------
1597//	TimeoutOccurred - Calls the timeout handler.			  		  [PRIVATE]
1598//-----------------------------------------------------------------------------
1599
1600void
1601IOSCSIParallelInterfaceController::TimeoutOccurred (
1602							OSObject *					theObject,
1603							IOTimerEventSource * 		theSender )
1604{
1605
1606	SCSIParallelTimer *			timer		= NULL;
1607	SCSIParallelTaskIdentifier	expiredTask	= NULL;
1608
1609	timer = OSDynamicCast ( SCSIParallelTimer, theSender );
1610	if ( timer != NULL )
1611	{
1612
1613		timer->BeginTimeoutContext ( );
1614
1615		expiredTask = timer->GetExpiredTask ( );
1616		while ( expiredTask != NULL )
1617		{
1618
1619			( ( IOSCSIParallelInterfaceController * ) theObject )->HandleTimeout ( expiredTask );
1620			expiredTask = timer->GetExpiredTask ( );
1621
1622		}
1623
1624		timer->EndTimeoutContext ( );
1625
1626		// Rearm the timer
1627		timer->Rearm ( );
1628
1629	}
1630
1631}
1632
1633
1634//-----------------------------------------------------------------------------
1635//	HandleTimeout - Generic timeout handler. Subclasses should override.
1636//															  		[PROTECTED]
1637//-----------------------------------------------------------------------------
1638
1639void
1640IOSCSIParallelInterfaceController::HandleTimeout (
1641						SCSIParallelTaskIdentifier			parallelRequest )
1642{
1643
1644	check ( parallelRequest != NULL );
1645	CompleteParallelTask ( 	parallelRequest,
1646							kSCSITaskStatus_TaskTimeoutOccurred,
1647							kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE );
1648
1649}
1650
1651
1652#if 0
1653#pragma mark -
1654#pragma mark SCSI Parallel Device Management
1655#pragma mark -
1656#endif
1657
1658
1659//-----------------------------------------------------------------------------
1660//	CreateTargetForID - Creates a target device for the ID specified.
1661//																	[PROTECTED]
1662//-----------------------------------------------------------------------------
1663
1664bool
1665IOSCSIParallelInterfaceController::CreateTargetForID (
1666										SCSITargetIdentifier	targetID )
1667{
1668
1669	OSDictionary *	dict 	= NULL;
1670	bool			result	= false;
1671
1672	dict = OSDictionary::withCapacity ( 0 );
1673	require_nonzero ( dict, DICT_CREATION_FAILED );
1674
1675	result = CreateTargetForID ( targetID, dict );
1676
1677	dict->release ( );
1678	dict = NULL;
1679
1680
1681DICT_CREATION_FAILED:
1682
1683
1684	return result;
1685
1686}
1687
1688
1689//-----------------------------------------------------------------------------
1690//	CreateTargetForID - Creates a target device for the ID specified.
1691//																	[PROTECTED]
1692//-----------------------------------------------------------------------------
1693
1694bool
1695IOSCSIParallelInterfaceController::CreateTargetForID (
1696										SCSITargetIdentifier	targetID,
1697										OSDictionary * 			properties )
1698{
1699
1700	IOSCSIParallelInterfaceDevice *		newDevice 	= NULL;
1701	IORegistryEntry *					entry		= NULL;
1702	bool								result		= false;
1703
1704	// Some subclasses like to create targets from within the StartController() override.
1705	// In those cases, fHBACanAcceptClientRequests is still false. We force it to true
1706	// in this case since a target is getting created - the HBA must be ready for I/O
1707	// by that time...
1708	if ( fHBACanAcceptClientRequests == false )
1709		fHBACanAcceptClientRequests = true;
1710
1711	// Verify that the device ID is not that of the initiator.
1712	require ( ( targetID != fInitiatorIdentifier ), INVALID_PARAMETER_EXIT );
1713
1714	// First check to see if this device already exists
1715	require ( ( GetTargetForID ( targetID ) == NULL ), INVALID_PARAMETER_EXIT );
1716
1717	// See if the controller has a device tree entry it wants us to hook this
1718	// target upto (e.g. to get io-device-location keys).
1719	entry = OSDynamicCast ( IORegistryEntry, properties->getObject ( kIOPropertyDeviceTreeEntryKey ) );
1720
1721	// Create the IOSCSIParallelInterfaceDevice object
1722	newDevice = IOSCSIParallelInterfaceDevice::CreateTarget (
1723									targetID,
1724									ReportHBASpecificDeviceDataSize ( ),
1725									entry );
1726	require_nonzero ( newDevice, DEVICE_CREATION_FAILED_EXIT );
1727
1728	AddDeviceToTargetList ( newDevice );
1729
1730	result = newDevice->attach ( this );
1731	require ( result, ATTACH_FAILED_EXIT );
1732
1733	result = newDevice->SetInitialTargetProperties ( properties );
1734	require ( result, START_FAILED_EXIT );
1735
1736	result = newDevice->start ( this );
1737	require ( result, START_FAILED_EXIT );
1738
1739	newDevice->release ( );
1740
1741	// The SCSI Device was successfully created.
1742	result = true;
1743
1744	return result;
1745
1746
1747START_FAILED_EXIT:
1748
1749
1750	// Detach the target device
1751	newDevice->detach ( this );
1752
1753
1754ATTACH_FAILED_EXIT:
1755
1756
1757	RemoveDeviceFromTargetList ( newDevice );
1758
1759	// The device can now be destroyed.
1760	newDevice->DestroyTarget ( );
1761
1762
1763DEVICE_CREATION_FAILED_EXIT:
1764INVALID_PARAMETER_EXIT:
1765
1766
1767	return result;
1768
1769}
1770
1771
1772//-----------------------------------------------------------------------------
1773//	DestroyTargetForID - Destroys a target device for the ID specified.
1774//																	[PROTECTED]
1775//-----------------------------------------------------------------------------
1776
1777void
1778IOSCSIParallelInterfaceController::DestroyTargetForID (
1779									SCSITargetIdentifier		targetID )
1780{
1781
1782	IOSCSIParallelInterfaceDevice *		victimDevice = NULL;
1783
1784	victimDevice = GetTargetForID ( targetID );
1785	if ( victimDevice == NULL )
1786	{
1787
1788		// There is no object for this target in the device list,
1789		// so return without doing anything.
1790		return;
1791
1792	}
1793
1794	// Remove the IOSCSIParallelInterfaceDevice from the device list.
1795	RemoveDeviceFromTargetList ( victimDevice );
1796
1797	// The device can now be destroyed.
1798	victimDevice->DestroyTarget ( );
1799	victimDevice->terminate ( );
1800
1801}
1802
1803
1804//-----------------------------------------------------------------------------
1805//	SetTargetProperty - Sets a property for the specified target.	[PROTECTED]
1806//-----------------------------------------------------------------------------
1807
1808bool
1809IOSCSIParallelInterfaceController::SetTargetProperty (
1810					SCSIDeviceIdentifier 				targetID,
1811					const char * 						key,
1812					OSObject *							value )
1813{
1814
1815	bool								result	= false;
1816	IOSCSIParallelInterfaceDevice * 	device	= NULL;
1817
1818	device = GetTargetForID ( targetID );
1819
1820	require_nonzero ( device, ErrorExit );
1821	result = device->SetTargetProperty ( key, value );
1822
1823
1824ErrorExit:
1825
1826
1827	return result;
1828
1829}
1830
1831
1832//-----------------------------------------------------------------------------
1833//	RemoveTargetProperty - Removes a property from the specified target.
1834//																	[PROTECTED]
1835//-----------------------------------------------------------------------------
1836
1837void
1838IOSCSIParallelInterfaceController::RemoveTargetProperty (
1839					SCSIDeviceIdentifier 				targetID,
1840					const char * 						key )
1841{
1842
1843	IOSCSIParallelInterfaceDevice * 	device	= NULL;
1844
1845	device = GetTargetForID ( targetID );
1846
1847	require_nonzero ( device, ErrorExit );
1848	device->RemoveTargetProperty ( key );
1849
1850
1851ErrorExit:
1852
1853
1854	return;
1855
1856}
1857
1858
1859#if 0
1860#pragma mark -
1861#pragma mark Device List Management
1862#pragma mark -
1863#endif
1864
1865/*
1866 * The following member routines are used to manage the array of linked lists, the Device
1867 * List, that allow quick access to the SCSI Parallel Device objects.  These routines
1868 * have intricate knowledge about the layout of the Device List since they are responsible
1869 * for managing it and so they are the only ones that are allowed to directly access that
1870 * structure.  Any other routine that needs to retrieve an element from the Device List
1871 * must use these routines to obtain it so that if necessity causes to the Device List
1872 * structure to change, they are not broken.
1873 */
1874
1875
1876//-----------------------------------------------------------------------------
1877//	InitializeDeviceList - Initializes device list.					  [PRIVATE]
1878//-----------------------------------------------------------------------------
1879
1880void
1881IOSCSIParallelInterfaceController::InitializeDeviceList ( void )
1882{
1883
1884	// Initialize the SCSI Parallel Device Array to all NULL pointers
1885	for ( UInt32 i = 0; i < kSCSIParallelDeviceListArrayCount; i++ )
1886	{
1887		fParallelDeviceList[i] = NULL;
1888	}
1889
1890}
1891
1892
1893//-----------------------------------------------------------------------------
1894//	GetTargetForID - Gets the device object for the specified targetID.
1895//																	[PROTECTED]
1896//-----------------------------------------------------------------------------
1897
1898IOSCSIParallelInterfaceDevice *
1899IOSCSIParallelInterfaceController::GetTargetForID ( SCSITargetIdentifier targetID )
1900{
1901
1902	IOSCSIParallelInterfaceDevice *		device		= NULL;
1903	IOInterruptState					lockState	= 0;
1904	UInt8								indexID		= 0;
1905
1906	require ( ( targetID >= 0 ), INVALID_PARAMETER_FAILURE );
1907	require ( ( targetID <= fHighestSupportedDeviceID ), INVALID_PARAMETER_FAILURE );
1908	require ( ( targetID != fInitiatorIdentifier ), INVALID_PARAMETER_FAILURE );
1909
1910	lockState = IOSimpleLockLockDisableInterrupt ( fDeviceLock );
1911
1912	// Hash the index.
1913	indexID = targetID & kSCSIParallelDeviceListIndexMask;
1914
1915	// Walk the list for the indexID
1916	device = fParallelDeviceList[indexID];
1917
1918	while ( device != NULL )
1919	{
1920
1921		if ( device->GetTargetIdentifier ( ) == targetID )
1922		{
1923
1924			// This is the device in which the client is interested, break
1925			// so that the current pointer will be returned.
1926			break;
1927
1928		}
1929
1930		// Get the next element in the list
1931		device = device->GetNextDeviceInList ( );
1932
1933	}
1934
1935	IOSimpleLockUnlockEnableInterrupt ( fDeviceLock, lockState );
1936
1937
1938INVALID_PARAMETER_FAILURE:
1939
1940
1941	return device;
1942
1943}
1944
1945
1946//-----------------------------------------------------------------------------
1947//	AddDeviceToTargetList - Adds a device to the target list.		  [PRIVATE]
1948//-----------------------------------------------------------------------------
1949
1950void
1951IOSCSIParallelInterfaceController::AddDeviceToTargetList (
1952							IOSCSIParallelInterfaceDevice *				newDevice )
1953{
1954
1955	UInt8					indexID		= 0;
1956	IOInterruptState		lockState	= 0;
1957
1958	STATUS_LOG ( ( "+IOSCSIParallelInterfaceController::AddDeviceToTargetList\n" ) );
1959
1960	lockState = IOSimpleLockLockDisableInterrupt ( fDeviceLock );
1961
1962	// Hash the index.
1963	indexID = newDevice->GetTargetIdentifier ( ) & kSCSIParallelDeviceListIndexMask;
1964
1965	// Set the pointer in the SCSI Device array
1966	if ( fParallelDeviceList[indexID] == NULL )
1967	{
1968
1969		// This is the first device object created for this
1970		// index, set the array pointer to the new object.
1971		fParallelDeviceList[indexID] = newDevice;
1972		newDevice->SetNextDeviceInList ( NULL );
1973		newDevice->SetPreviousDeviceInList ( NULL );
1974
1975	}
1976
1977	else
1978	{
1979
1980		// This is not the first device object for this index,
1981		// walk the list at this index and add it to the end.
1982		IOSCSIParallelInterfaceDevice *	currentDevice;
1983
1984		currentDevice = fParallelDeviceList[indexID];
1985		while ( currentDevice->GetNextDeviceInList ( ) != NULL )
1986		{
1987			currentDevice = currentDevice->GetNextDeviceInList ( );
1988		}
1989
1990		currentDevice->SetNextDeviceInList ( newDevice );
1991		newDevice->SetNextDeviceInList ( NULL );
1992		newDevice->SetPreviousDeviceInList ( currentDevice );
1993
1994	}
1995
1996	IOSimpleLockUnlockEnableInterrupt ( fDeviceLock, lockState );
1997
1998	STATUS_LOG ( ( "-IOSCSIParallelInterfaceController::AddDeviceToTargetList\n" ) );
1999
2000}
2001
2002
2003//-----------------------------------------------------------------------------
2004//	RemoveDeviceFromTargetList - Removes a device from the target list.
2005//																	  [PRIVATE]
2006//-----------------------------------------------------------------------------
2007
2008void
2009IOSCSIParallelInterfaceController::RemoveDeviceFromTargetList (
2010							IOSCSIParallelInterfaceDevice * 	victimDevice )
2011{
2012
2013	IOSCSIParallelInterfaceDevice *		nextDevice	= NULL;
2014	IOSCSIParallelInterfaceDevice *		prevDevice	= NULL;
2015	IOInterruptState					lockState	= 0;
2016
2017	lockState = IOSimpleLockLockDisableInterrupt ( fDeviceLock );
2018
2019	nextDevice = victimDevice->GetNextDeviceInList ( );
2020	prevDevice = victimDevice->GetPreviousDeviceInList ( );
2021
2022	if ( prevDevice != NULL )
2023	{
2024
2025		// There is a previous device, set it to the victim's next device
2026		prevDevice->SetNextDeviceInList ( nextDevice );
2027
2028	}
2029
2030	else
2031	{
2032
2033		// There is not a previous device, set the pointer in the array
2034		// to the victim's next device.
2035		UInt8	indexID = 0;
2036
2037		// Hash the index.
2038		indexID = victimDevice->GetTargetIdentifier ( ) & kSCSIParallelDeviceListIndexMask;
2039
2040		// Set the Device List element to point at the device object that was following
2041		// the device object that is being removed.  If there was no next device,
2042		// the nextDevice pointer will be NULL causing the Device List no longer have
2043		// any devices at this index.
2044		fParallelDeviceList[indexID] = nextDevice;
2045
2046	}
2047
2048	if ( nextDevice != NULL )
2049	{
2050
2051		// The next device is not NULL, set it to the victim's previous
2052		nextDevice->SetPreviousDeviceInList ( prevDevice );
2053
2054	}
2055
2056	// Clear out the victim's previous and next pointers
2057	victimDevice->SetNextDeviceInList ( NULL );
2058	victimDevice->SetPreviousDeviceInList ( NULL );
2059
2060	IOSimpleLockUnlockEnableInterrupt ( fDeviceLock, lockState );
2061
2062}
2063
2064
2065#if 0
2066#pragma mark -
2067#pragma mark Controller Child Class
2068#pragma mark -
2069#endif
2070
2071
2072//-----------------------------------------------------------------------------
2073//	DoesHBAPerformAutoSense - Default implementation.				   [PUBLIC]
2074//-----------------------------------------------------------------------------
2075
2076bool
2077IOSCSIParallelInterfaceController::DoesHBAPerformAutoSense ( void )
2078{
2079	return false;
2080}
2081
2082
2083//-----------------------------------------------------------------------------
2084//	DoesHBASupportMultiPathing - Default implementation.			   [PUBLIC]
2085//-----------------------------------------------------------------------------
2086
2087bool
2088IOSCSIParallelInterfaceController::DoesHBASupportMultiPathing ( void )
2089{
2090
2091	OSString *		interface	= NULL;
2092	OSDictionary *	dict		= NULL;
2093	bool			result		= true;
2094
2095
2096	// Get Protocol Characteristics.
2097	dict = OSDynamicCast ( OSDictionary, getProperty ( kIOPropertyProtocolCharacteristicsKey ) );
2098
2099	if ( dict != NULL )
2100	{
2101
2102		interface = OSDynamicCast ( OSString, dict->getObject ( kIOPropertyPhysicalInterconnectTypeKey ) );
2103
2104		if ( interface != NULL )
2105		{
2106
2107			if ( ( interface->isEqualTo ( kIOPropertyPhysicalInterconnectTypeSCSIParallel ) ) ||
2108				( interface->isEqualTo ( kIOPropertyPhysicalInterconnectTypeSerialAttachedSCSI ) ) )
2109			{
2110
2111				// No Multipathing for parallel SCSI and SAS by default.
2112				result = false;
2113
2114			}
2115
2116		}
2117
2118	}
2119
2120	return result;
2121}
2122
2123
2124//-----------------------------------------------------------------------------
2125//	ReportHBAConstraints - Default implementation.				 	   [PUBLIC]
2126//-----------------------------------------------------------------------------
2127
2128void
2129IOSCSIParallelInterfaceController::ReportHBAConstraints (
2130	OSDictionary *		constraints )
2131{
2132
2133	UInt64			value	= 0;
2134	OSNumber *		number	= NULL;
2135
2136	// Default alignment is 16-byte aligned, 32-bit memory only.
2137	value = 0x00000000FFFFFFF0ULL;
2138
2139	number = OSNumber::withNumber ( value, 64 );
2140	if ( number != NULL )
2141	{
2142
2143		constraints->setObject ( kIOMinimumHBADataAlignmentMaskKey, number );
2144		number->release ( );
2145
2146	}
2147
2148	// 32-bit addressing by default.
2149	value = 32;
2150	number = OSNumber::withNumber ( value, 64 );
2151	if ( number != NULL )
2152	{
2153
2154		constraints->setObject ( kIOMaximumSegmentAddressableBitCountKey, number );
2155		number->release ( );
2156
2157	}
2158
2159	// 4-byte alignment by default.
2160	value = 4;
2161	number = OSNumber::withNumber ( value, 64 );
2162	if ( number != NULL )
2163	{
2164
2165		constraints->setObject ( kIOMinimumSegmentAlignmentByteCountKey, number );
2166		number->release ( );
2167
2168	}
2169
2170}
2171
2172
2173//-----------------------------------------------------------------------------
2174//	InitializeDMASpecification - Default implementation.		 	[PROTECTED]
2175//-----------------------------------------------------------------------------
2176
2177bool
2178IOSCSIParallelInterfaceController::InitializeDMASpecification (
2179	IODMACommand * command )
2180{
2181
2182	bool	result = false;
2183
2184	result = command->initWithSpecification (
2185		kIODMACommandOutputHost32,
2186		32,			// addressBits
2187		4096,		// PAGE_SIZE
2188		IODMACommand::kMapped,
2189		1048576,	// 1MB I/O
2190		4			// 4-byte aligned segments
2191		);
2192
2193	return result;
2194
2195}
2196
2197
2198//-----------------------------------------------------------------------------
2199//	CreateDeviceInterrupt - Default implementation.				 	[PROTECTED]
2200//-----------------------------------------------------------------------------
2201
2202IOInterruptEventSource *
2203IOSCSIParallelInterfaceController::CreateDeviceInterrupt (
2204	IOInterruptEventSource::Action			action,
2205	IOFilterInterruptEventSource::Filter	filter,
2206	IOService *								provider )
2207{
2208
2209	IOInterruptEventSource *	ies = NULL;
2210
2211	ies = IOFilterInterruptEventSource::filterInterruptEventSource (
2212		this,
2213		action,
2214		filter,
2215		provider,
2216		0 );
2217
2218	check ( ies != NULL );
2219
2220	return ies;
2221
2222}
2223
2224
2225//-----------------------------------------------------------------------------
2226//	SuspendServices - Suspends services temporarily.				[PROTECTED]
2227//-----------------------------------------------------------------------------
2228
2229void
2230IOSCSIParallelInterfaceController::SuspendServices ( void )
2231{
2232
2233	// The HBA child class has requested the suspension of tasks.
2234	fHBACanAcceptClientRequests = false;
2235
2236}
2237
2238
2239//-----------------------------------------------------------------------------
2240//	ResumeServices - Resume services temporarily.					[PROTECTED]
2241//-----------------------------------------------------------------------------
2242
2243void
2244IOSCSIParallelInterfaceController::ResumeServices ( void )
2245{
2246
2247	// The HBA child class has allowed the submission of tasks.
2248	fHBACanAcceptClientRequests = true;
2249
2250}
2251
2252
2253//-----------------------------------------------------------------------------
2254//	NotifyClientsOfBusReset - Notifies clients of bus resets.		[PROTECTED]
2255//-----------------------------------------------------------------------------
2256
2257void
2258IOSCSIParallelInterfaceController::NotifyClientsOfBusReset ( void )
2259{
2260	messageClients ( kSCSIControllerNotificationBusReset );
2261}
2262
2263
2264//-----------------------------------------------------------------------------
2265//	NotifyClientsOfPortStatusChange - Notifies clients of port status changes.
2266//																	[PROTECTED]
2267//-----------------------------------------------------------------------------
2268
2269void
2270IOSCSIParallelInterfaceController::NotifyClientsOfPortStatusChange (
2271												SCSIPortStatus newStatus )
2272{
2273
2274	OSDictionary *	hbaDict		= NULL;
2275	OSDictionary *	copyDict	= NULL;
2276	OSString *		string 		= NULL;
2277	char *			linkStatus	= NULL;
2278
2279	copyDict = OSDynamicCast ( OSDictionary, copyProperty ( kIOPropertyControllerCharacteristicsKey ) );
2280	require_nonzero ( copyDict, ErrorExit );
2281
2282	hbaDict = ( OSDictionary * ) copyDict->copyCollection ( );
2283	copyDict->release ( );
2284
2285	require_nonzero ( hbaDict, ErrorExit );
2286
2287	switch ( newStatus )
2288	{
2289
2290		case kSCSIPort_StatusOnline:
2291			linkStatus = ( char * ) kIOPropertyPortStatusLinkEstablishedKey;
2292			break;
2293
2294		case kSCSIPort_StatusOffline:
2295			linkStatus = ( char * ) kIOPropertyPortStatusNoLinkEstablishedKey;
2296			break;
2297
2298		case kSCSIPort_StatusFailure:
2299			linkStatus = ( char * ) kIOPropertyPortStatusLinkFailedKey;
2300			break;
2301
2302		default:
2303			break;
2304
2305	}
2306
2307	string = OSString::withCString ( linkStatus );
2308	if ( string != NULL )
2309	{
2310
2311		hbaDict->setObject ( kIOPropertyPortStatusKey, string );
2312		string->release ( );
2313		string = NULL;
2314
2315	}
2316
2317	setProperty ( kIOPropertyControllerCharacteristicsKey, hbaDict );
2318	hbaDict->release ( );
2319	hbaDict = NULL;
2320
2321
2322ErrorExit:
2323
2324
2325	messageClients ( kSCSIPort_NotificationStatusChange, ( void * ) newStatus );
2326
2327}
2328
2329
2330#if 0
2331#pragma mark -
2332#pragma mark SCSI Parallel Task Object Accessors
2333#pragma mark -
2334#endif
2335
2336
2337//-----------------------------------------------------------------------------
2338//	GetSCSITaskIdentifier - Gets SCSITaskIdentifier for task.		[PROTECTED]
2339//-----------------------------------------------------------------------------
2340
2341SCSITaskIdentifier
2342IOSCSIParallelInterfaceController::GetSCSITaskIdentifier (
2343							SCSIParallelTaskIdentifier 	parallelTask )
2344{
2345
2346	SCSIParallelTask *	tempTask = ( SCSIParallelTask * ) parallelTask;
2347
2348	if ( tempTask == NULL )
2349	{
2350		return NULL;
2351	}
2352
2353	return tempTask->GetSCSITaskIdentifier ( );
2354
2355}
2356
2357
2358//-----------------------------------------------------------------------------
2359//	GetTargetIdentifier - Gets SCSITargetIdentifier for task.		[PROTECTED]
2360//-----------------------------------------------------------------------------
2361
2362SCSITargetIdentifier
2363IOSCSIParallelInterfaceController::GetTargetIdentifier (
2364							SCSIParallelTaskIdentifier 	parallelTask )
2365{
2366
2367	SCSIParallelTask *	tempTask = ( SCSIParallelTask * ) parallelTask;
2368
2369	if ( tempTask == NULL )
2370	{
2371		return NULL;
2372	}
2373
2374	return tempTask->GetTargetIdentifier ( );
2375
2376}
2377
2378
2379//-----------------------------------------------------------------------------
2380//	GetDevice - Gets Device for task.								   [STATIC]
2381//-----------------------------------------------------------------------------
2382
2383static IOSCSIParallelInterfaceDevice *
2384GetDevice (	SCSIParallelTaskIdentifier 	parallelTask )
2385{
2386
2387	SCSIParallelTask *	tempTask = ( SCSIParallelTask * ) parallelTask;
2388
2389	if ( tempTask == NULL )
2390	{
2391		return NULL;
2392	}
2393
2394	return tempTask->GetDevice ( );
2395
2396}
2397
2398
2399//-----------------------------------------------------------------------------
2400//	CopyProtocolCharacteristicsProperties - Copies properties from object
2401//											to dictionary.			   [STATIC]
2402//-----------------------------------------------------------------------------
2403
2404static void
2405CopyProtocolCharacteristicsProperties ( OSDictionary * dict, IOService * service )
2406{
2407
2408	OSString *		string = NULL;
2409	OSNumber *		number = NULL;
2410
2411	// Set the Physical Interconnect property if it doesn't already exist.
2412	if ( dict->getObject ( kIOPropertyPhysicalInterconnectTypeKey ) == NULL )
2413	{
2414
2415		string = OSDynamicCast ( OSString, service->getProperty ( kIOPropertyPhysicalInterconnectTypeKey ) );
2416		if ( string == NULL )
2417		{
2418
2419			string = OSString::withCString ( kIOPropertyPhysicalInterconnectTypeSCSIParallel );
2420			if ( string != NULL )
2421			{
2422
2423				dict->setObject ( kIOPropertyPhysicalInterconnectTypeKey, string );
2424				string->release ( );
2425				string = NULL;
2426
2427			}
2428
2429		}
2430
2431		else
2432		{
2433
2434			dict->setObject ( kIOPropertyPhysicalInterconnectTypeKey, string );
2435
2436		}
2437
2438	}
2439
2440	// Set the Physical Interconnect Location property if it doesn't already exist.
2441	if ( dict->getObject ( kIOPropertyPhysicalInterconnectLocationKey ) == NULL )
2442	{
2443
2444		string = OSDynamicCast ( OSString, service->getProperty ( kIOPropertyPhysicalInterconnectLocationKey ) );
2445		if ( string == NULL )
2446		{
2447
2448			string = OSString::withCString ( kIOPropertyInternalExternalKey );
2449			if ( string != NULL )
2450			{
2451
2452				dict->setObject ( kIOPropertyPhysicalInterconnectLocationKey, string );
2453				string->release ( );
2454				string = NULL;
2455
2456			}
2457
2458		}
2459
2460		else
2461		{
2462
2463			dict->setObject ( kIOPropertyPhysicalInterconnectLocationKey, string );
2464
2465		}
2466
2467	}
2468
2469	// Set the Timeout Duration properties if they don't already exist.
2470	if ( dict->getObject ( kIOPropertyReadTimeOutDurationKey ) == NULL )
2471	{
2472
2473		number = OSDynamicCast ( OSNumber, service->getProperty ( kIOPropertyReadTimeOutDurationKey ) );
2474		if ( number != NULL )
2475		{
2476
2477			dict->setObject ( kIOPropertyReadTimeOutDurationKey, number );
2478
2479		}
2480
2481	}
2482
2483	if ( dict->getObject ( kIOPropertyWriteTimeOutDurationKey ) == NULL )
2484	{
2485
2486		number = OSDynamicCast ( OSNumber, service->getProperty ( kIOPropertyWriteTimeOutDurationKey ) );
2487		if ( number != NULL )
2488		{
2489
2490			dict->setObject ( kIOPropertyWriteTimeOutDurationKey, number );
2491
2492		}
2493
2494	}
2495
2496}
2497
2498
2499// ---- Methods for Accessing data in the client's SCSI Task Object ----
2500// Method to retrieve the LUN that identifies the Logical Unit whose Task
2501// Set to which this task is to be added.
2502// --> Currently this only supports Level 1 Addressing, complete
2503// Hierachal LUN addressing will need to be added to the SCSI Task object
2504// and the Peripheral Device Type objects which will represent Logical Units.
2505// Since that will be completed before this is released, this method will be
2506// changed at that time.
2507
2508
2509//-----------------------------------------------------------------------------
2510//	GetLogicalUnitNumber - Gets SCSILogicalUnitNumber for task.		[PROTECTED]
2511//-----------------------------------------------------------------------------
2512
2513SCSILogicalUnitNumber
2514IOSCSIParallelInterfaceController::GetLogicalUnitNumber (
2515							SCSIParallelTaskIdentifier 		parallelTask )
2516{
2517
2518	SCSIParallelTask *	tempTask = ( SCSIParallelTask * ) parallelTask;
2519
2520	if ( tempTask == NULL )
2521	{
2522		return 0;
2523	}
2524
2525	return tempTask->GetLogicalUnitNumber ( );
2526
2527}
2528
2529
2530//-----------------------------------------------------------------------------
2531//  GetLogicalUnitBytes - Gets SCSILogicalUnitBytes for task.		[PROTECTED]
2532//-----------------------------------------------------------------------------
2533void
2534IOSCSIParallelInterfaceController::GetLogicalUnitBytes (
2535							SCSIParallelTaskIdentifier      parallelTask,
2536							SCSILogicalUnitBytes *          logicalUnitBytes )
2537{
2538
2539	SCSIParallelTask *  tempTask = ( SCSIParallelTask * ) parallelTask;
2540
2541	if ( tempTask == NULL )
2542	{
2543		return;
2544	}
2545
2546	return tempTask->GetLogicalUnitBytes ( logicalUnitBytes );
2547
2548}
2549
2550
2551
2552//-----------------------------------------------------------------------------
2553//	GetTaggedTaskIdentifier - Gets SCSITaggedTaskIdentifier for task.
2554//																	[PROTECTED]
2555//-----------------------------------------------------------------------------
2556
2557SCSITaggedTaskIdentifier
2558IOSCSIParallelInterfaceController::GetTaggedTaskIdentifier (
2559							SCSIParallelTaskIdentifier		parallelTask )
2560{
2561
2562	SCSIParallelTask *	tempTask = ( SCSIParallelTask * ) parallelTask;
2563
2564	if ( tempTask == NULL )
2565	{
2566		return kSCSIUntaggedTaskIdentifier;
2567	}
2568
2569	return tempTask->GetTaggedTaskIdentifier ( );
2570
2571}
2572
2573
2574//-----------------------------------------------------------------------------
2575//	GetTaskAttribute - Gets SCSITaskAttribute for task. 			[PROTECTED]
2576//-----------------------------------------------------------------------------
2577
2578SCSITaskAttribute
2579IOSCSIParallelInterfaceController::GetTaskAttribute (
2580							SCSIParallelTaskIdentifier 		parallelTask )
2581{
2582
2583	SCSIParallelTask *	tempTask = ( SCSIParallelTask * ) parallelTask;
2584
2585	if ( tempTask == NULL )
2586	{
2587		return kSCSITask_SIMPLE;
2588	}
2589
2590	return tempTask->GetTaskAttribute ( );
2591
2592}
2593
2594
2595//-----------------------------------------------------------------------------
2596//	GetCommandDescriptorBlockSize - Gets CDB size for task. 		[PROTECTED]
2597//-----------------------------------------------------------------------------
2598
2599UInt8
2600IOSCSIParallelInterfaceController::GetCommandDescriptorBlockSize (
2601							SCSIParallelTaskIdentifier 		parallelTask )
2602{
2603
2604	SCSIParallelTask *	tempTask = ( SCSIParallelTask * ) parallelTask;
2605
2606	if ( tempTask == NULL )
2607	{
2608		return 0;
2609	}
2610
2611	return tempTask->GetCommandDescriptorBlockSize ( );
2612
2613}
2614
2615
2616//-----------------------------------------------------------------------------
2617//	GetCommandDescriptorBlock - This will always return a 16 Byte CDB.
2618//														 			[PROTECTED]
2619//-----------------------------------------------------------------------------
2620
2621bool
2622IOSCSIParallelInterfaceController::GetCommandDescriptorBlock (
2623							SCSIParallelTaskIdentifier 		parallelTask,
2624							SCSICommandDescriptorBlock * 	cdbData )
2625{
2626
2627	SCSIParallelTask *	tempTask = ( SCSIParallelTask * ) parallelTask;
2628
2629	if ( tempTask == NULL )
2630	{
2631		return false;
2632	}
2633
2634	return tempTask->GetCommandDescriptorBlock ( cdbData );
2635
2636}
2637
2638
2639//-----------------------------------------------------------------------------
2640//	GetDataTransferDirection - Gets data transfer direction.		[PROTECTED]
2641//-----------------------------------------------------------------------------
2642
2643UInt8
2644IOSCSIParallelInterfaceController::GetDataTransferDirection (
2645							SCSIParallelTaskIdentifier 		parallelTask )
2646{
2647
2648	SCSIParallelTask *	tempTask = ( SCSIParallelTask * ) parallelTask;
2649
2650	if ( tempTask == NULL )
2651	{
2652		return kSCSIDataTransfer_NoDataTransfer;
2653	}
2654
2655	return tempTask->GetDataTransferDirection ( );
2656
2657}
2658
2659
2660//-----------------------------------------------------------------------------
2661//	GetRequestedDataTransferCount - Gets requested transfer count.	[PROTECTED]
2662//-----------------------------------------------------------------------------
2663
2664UInt64
2665IOSCSIParallelInterfaceController::GetRequestedDataTransferCount (
2666							SCSIParallelTaskIdentifier 		parallelTask )
2667{
2668
2669	SCSIParallelTask *	tempTask = ( SCSIParallelTask * ) parallelTask;
2670
2671	if ( tempTask == NULL )
2672	{
2673		return 0;
2674	}
2675
2676	return tempTask->GetRequestedDataTransferCount ( );
2677
2678}
2679
2680
2681//-----------------------------------------------------------------------------
2682//	GetRealizedDataTransferCount - Gets realized transfer count.	[PROTECTED]
2683//-----------------------------------------------------------------------------
2684
2685UInt64
2686IOSCSIParallelInterfaceController::GetRealizedDataTransferCount (
2687							SCSIParallelTaskIdentifier 		parallelTask )
2688{
2689
2690	SCSIParallelTask *	tempTask = ( SCSIParallelTask * ) parallelTask;
2691
2692	if ( tempTask == NULL )
2693	{
2694		return 0;
2695	}
2696
2697	return tempTask->GetRealizedDataTransferCount ( );
2698
2699}
2700
2701
2702//-----------------------------------------------------------------------------
2703//	SetRealizedDataTransferCount - Sets realized transfer count.	[PROTECTED]
2704//-----------------------------------------------------------------------------
2705
2706bool
2707IOSCSIParallelInterfaceController::SetRealizedDataTransferCount (
2708				SCSIParallelTaskIdentifier 		parallelTask,
2709				UInt64 							realizedTransferCountInBytes )
2710{
2711
2712	SCSIParallelTask *	tempTask = ( SCSIParallelTask * ) parallelTask;
2713
2714	if ( tempTask == NULL )
2715	{
2716		return false;
2717	}
2718
2719	return tempTask->SetRealizedDataTransferCount ( realizedTransferCountInBytes );
2720
2721}
2722
2723
2724//-----------------------------------------------------------------------------
2725//	IncrementRealizedDataTransferCount - Adjusts realized transfer count.
2726//																	[PROTECTED]
2727//-----------------------------------------------------------------------------
2728
2729void
2730IOSCSIParallelInterfaceController::IncrementRealizedDataTransferCount (
2731				SCSIParallelTaskIdentifier 		parallelTask,
2732				UInt64 							realizedTransferCountInBytes )
2733{
2734
2735	SCSIParallelTask *	tempTask = ( SCSIParallelTask * ) parallelTask;
2736
2737	if ( tempTask == NULL )
2738	{
2739		return;
2740	}
2741
2742	return tempTask->IncrementRealizedDataTransferCount ( realizedTransferCountInBytes );
2743
2744}
2745
2746
2747//-----------------------------------------------------------------------------
2748//	GetDataBuffer - Gets data buffer associated with this task.		[PROTECTED]
2749//-----------------------------------------------------------------------------
2750
2751IOMemoryDescriptor *
2752IOSCSIParallelInterfaceController::GetDataBuffer (
2753							SCSIParallelTaskIdentifier 		parallelTask )
2754{
2755
2756	SCSIParallelTask *	tempTask = ( SCSIParallelTask * ) parallelTask;
2757
2758	if ( tempTask == NULL )
2759	{
2760		return NULL;
2761	}
2762
2763	return tempTask->GetDataBuffer ( );
2764
2765}
2766
2767
2768//-----------------------------------------------------------------------------
2769//	GetDataBufferOffset - Gets data buffer offset associated with this task.
2770//																	[PROTECTED]
2771//-----------------------------------------------------------------------------
2772
2773UInt64
2774IOSCSIParallelInterfaceController::GetDataBufferOffset (
2775							SCSIParallelTaskIdentifier 		parallelTask )
2776{
2777
2778	SCSIParallelTask *	tempTask = ( SCSIParallelTask * ) parallelTask;
2779
2780	if ( tempTask == NULL )
2781	{
2782		return 0;
2783	}
2784
2785	return tempTask->GetDataBufferOffset ( );
2786
2787}
2788
2789
2790//-----------------------------------------------------------------------------
2791//	GetDMACommand - Gets IODMACommand associated with this task.	[PROTECTED]
2792//-----------------------------------------------------------------------------
2793
2794IODMACommand *
2795IOSCSIParallelInterfaceController::GetDMACommand (
2796							SCSIParallelTaskIdentifier 		parallelTask )
2797{
2798	return ( IODMACommand * ) parallelTask;
2799}
2800
2801
2802//-----------------------------------------------------------------------------
2803//	GetTimeoutDuration - 	Gets timeout duration in milliseconds associated.
2804//							with this task.							[PROTECTED]
2805//-----------------------------------------------------------------------------
2806
2807UInt32
2808IOSCSIParallelInterfaceController::GetTimeoutDuration (
2809							SCSIParallelTaskIdentifier 		parallelTask )
2810{
2811
2812	SCSIParallelTask *	tempTask = ( SCSIParallelTask * ) parallelTask;
2813
2814	if ( tempTask == NULL )
2815	{
2816		return 0;
2817	}
2818
2819	return tempTask->GetTimeoutDuration ( );
2820
2821}
2822
2823
2824//-----------------------------------------------------------------------------
2825//	SetAutoSenseData - 	Sets autosense data in task.				[PROTECTED]
2826//-----------------------------------------------------------------------------
2827
2828bool
2829IOSCSIParallelInterfaceController::SetAutoSenseData (
2830							SCSIParallelTaskIdentifier 		parallelTask,
2831							SCSI_Sense_Data * 				newSenseData,
2832							UInt8							senseDataSize )
2833{
2834
2835	SCSIParallelTask *	tempTask = ( SCSIParallelTask * ) parallelTask;
2836
2837	if ( tempTask == NULL )
2838	{
2839		return false;
2840	}
2841
2842	return tempTask->SetAutoSenseData ( newSenseData, senseDataSize );
2843
2844}
2845
2846
2847//-----------------------------------------------------------------------------
2848//	GetAutoSenseData - 	Gets autosense data in task.				[PROTECTED]
2849//-----------------------------------------------------------------------------
2850
2851bool
2852IOSCSIParallelInterfaceController::GetAutoSenseData (
2853 							SCSIParallelTaskIdentifier 		parallelTask,
2854 							SCSI_Sense_Data * 				receivingBuffer,
2855 							UInt8							senseDataSize )
2856{
2857
2858	SCSIParallelTask *	tempTask = ( SCSIParallelTask * ) parallelTask;
2859
2860	if ( tempTask == NULL )
2861	{
2862		return false;
2863	}
2864
2865	return tempTask->GetAutoSenseData ( receivingBuffer, senseDataSize );
2866
2867}
2868
2869
2870//-----------------------------------------------------------------------------
2871//	GetAutoSenseDataSize - 	Gets autosense data size.				[PROTECTED]
2872//-----------------------------------------------------------------------------
2873
2874UInt8
2875IOSCSIParallelInterfaceController::GetAutoSenseDataSize (
2876 							SCSIParallelTaskIdentifier 		parallelTask )
2877{
2878
2879	SCSIParallelTask *	tempTask = ( SCSIParallelTask * ) parallelTask;
2880
2881	if ( tempTask == NULL )
2882	{
2883		return 0;
2884	}
2885
2886	return tempTask->GetAutoSenseDataSize ( );
2887
2888}
2889
2890
2891//-----------------------------------------------------------------------------
2892//	GetSCSIParallelFeatureNegotiation - Gets SCSIParallelFeatureRequest status
2893//										for specified feature.		[PROTECTED]
2894//-----------------------------------------------------------------------------
2895
2896SCSIParallelFeatureRequest
2897IOSCSIParallelInterfaceController::GetSCSIParallelFeatureNegotiation (
2898							SCSIParallelTaskIdentifier 		parallelTask,
2899							SCSIParallelFeature 			requestedFeature )
2900{
2901
2902	SCSIParallelTask *	tempTask = ( SCSIParallelTask * ) parallelTask;
2903
2904	if ( tempTask == NULL )
2905	{
2906		return kSCSIParallelFeature_NoNegotiation;
2907	}
2908
2909	return tempTask->GetSCSIParallelFeatureNegotiation ( requestedFeature );
2910
2911}
2912
2913
2914//-----------------------------------------------------------------------------
2915//	GetSCSIParallelFeatureNegotiationCount - 	Gets SCSIParallelFeatureRequest
2916//												count.				[PROTECTED]
2917//-----------------------------------------------------------------------------
2918
2919UInt64
2920IOSCSIParallelInterfaceController::GetSCSIParallelFeatureNegotiationCount (
2921							SCSIParallelTaskIdentifier 		parallelTask)
2922{
2923
2924	SCSIParallelTask *	tempTask = ( SCSIParallelTask * ) parallelTask;
2925
2926	if ( tempTask == NULL )
2927	{
2928		return 0;
2929	}
2930
2931	return tempTask->GetSCSIParallelFeatureNegotiationCount ( );
2932
2933}
2934
2935
2936//-----------------------------------------------------------------------------
2937//	SetSCSIParallelFeatureNegotiationResult - 	Sets SCSIParallelFeatureResult
2938//												status for specified feature.
2939//																	[PROTECTED]
2940//-----------------------------------------------------------------------------
2941
2942void
2943IOSCSIParallelInterfaceController::SetSCSIParallelFeatureNegotiationResult (
2944							SCSIParallelTaskIdentifier 		parallelTask,
2945							SCSIParallelFeature 			requestedFeature,
2946							SCSIParallelFeatureResult 		newResult )
2947{
2948
2949	SCSIParallelTask *	tempTask = ( SCSIParallelTask * ) parallelTask;
2950
2951	if ( tempTask == NULL )
2952	{
2953		return;
2954	}
2955
2956	return tempTask->SetSCSIParallelFeatureNegotiationResult ( requestedFeature, newResult );
2957
2958}
2959
2960
2961//-----------------------------------------------------------------------------
2962//	GetSCSIParallelFeatureNegotiationResult - 	Gets SCSIParallelFeatureResult
2963//												for requested feature.
2964//																	[PROTECTED]
2965//-----------------------------------------------------------------------------
2966
2967SCSIParallelFeatureResult
2968IOSCSIParallelInterfaceController::GetSCSIParallelFeatureNegotiationResult (
2969							SCSIParallelTaskIdentifier 	parallelTask,
2970							SCSIParallelFeature 		requestedFeature )
2971{
2972
2973	SCSIParallelTask *	tempTask = ( SCSIParallelTask * ) parallelTask;
2974
2975	if ( tempTask == NULL )
2976	{
2977		return kSCSIParallelFeature_NegotitiationUnchanged;
2978	}
2979
2980	return tempTask->GetSCSIParallelFeatureNegotiationResult ( requestedFeature );
2981
2982}
2983
2984
2985//-----------------------------------------------------------------------------
2986//	GetSCSIParallelFeatureNegotiationResultCount - 	Gets SCSIParallelFeatureResult
2987//													count.			[PROTECTED]
2988//-----------------------------------------------------------------------------
2989
2990UInt64
2991IOSCSIParallelInterfaceController::GetSCSIParallelFeatureNegotiationResultCount (
2992							SCSIParallelTaskIdentifier 		parallelTask )
2993{
2994
2995	SCSIParallelTask *	tempTask = ( SCSIParallelTask * ) parallelTask;
2996
2997	if ( tempTask == NULL )
2998	{
2999		return 0;
3000	}
3001
3002	return tempTask->GetSCSIParallelFeatureNegotiationResultCount ( );
3003
3004}
3005
3006
3007//-----------------------------------------------------------------------------
3008//	SetControllerTaskIdentifier - Sets the unique identifier for the task.
3009//																	[PROTECTED]
3010//-----------------------------------------------------------------------------
3011
3012void
3013IOSCSIParallelInterfaceController::SetControllerTaskIdentifier (
3014							SCSIParallelTaskIdentifier 		parallelTask,
3015							UInt64 							newIdentifier )
3016{
3017
3018	SCSIParallelTask *	tempTask = ( SCSIParallelTask * ) parallelTask;
3019
3020	if ( tempTask == NULL )
3021	{
3022		return;
3023	}
3024
3025	return tempTask->SetControllerTaskIdentifier ( newIdentifier );
3026
3027}
3028
3029
3030//-----------------------------------------------------------------------------
3031//	GetControllerTaskIdentifier - Gets the unique identifier for the task.
3032//																	[PROTECTED]
3033//-----------------------------------------------------------------------------
3034
3035UInt64
3036IOSCSIParallelInterfaceController::GetControllerTaskIdentifier (
3037							SCSIParallelTaskIdentifier 		parallelTask )
3038{
3039
3040	SCSIParallelTask *	tempTask = ( SCSIParallelTask * ) parallelTask;
3041
3042	if ( tempTask == NULL )
3043	{
3044		return 0;
3045	}
3046
3047	return tempTask->GetControllerTaskIdentifier ( );
3048
3049}
3050
3051
3052//-----------------------------------------------------------------------------
3053//	GetHBADataSize - Gets size of HBA data allocated in the task.	[PROTECTED]
3054//-----------------------------------------------------------------------------
3055
3056UInt32
3057IOSCSIParallelInterfaceController::GetHBADataSize (
3058							SCSIParallelTaskIdentifier 	parallelTask )
3059{
3060
3061	SCSIParallelTask *	tempTask = ( SCSIParallelTask * ) parallelTask;
3062
3063	if ( tempTask == NULL )
3064	{
3065		return 0;
3066	}
3067
3068	return tempTask->GetHBADataSize ( );
3069
3070}
3071
3072
3073//-----------------------------------------------------------------------------
3074//	GetHBADataPointer - Gets pointer to HBA data.					[PROTECTED]
3075//-----------------------------------------------------------------------------
3076
3077void *
3078IOSCSIParallelInterfaceController::GetHBADataPointer (
3079							SCSIParallelTaskIdentifier 	parallelTask )
3080{
3081
3082	SCSIParallelTask *	tempTask = ( SCSIParallelTask * ) parallelTask;
3083
3084	if ( tempTask == NULL )
3085	{
3086		return NULL;
3087	}
3088
3089	return tempTask->GetHBADataPointer ( );
3090
3091}
3092
3093
3094//-----------------------------------------------------------------------------
3095//	GetHBADataDescriptor - Gets IOMemoryDescriptor for HBA data.	[PROTECTED]
3096//-----------------------------------------------------------------------------
3097
3098IOMemoryDescriptor *
3099IOSCSIParallelInterfaceController::GetHBADataDescriptor (
3100							SCSIParallelTaskIdentifier 	parallelTask )
3101{
3102
3103	SCSIParallelTask *	tempTask = ( SCSIParallelTask * ) parallelTask;
3104
3105	if ( tempTask == NULL )
3106	{
3107		return NULL;
3108	}
3109
3110	return tempTask->GetHBADataDescriptor ( );
3111
3112}
3113
3114
3115#if 0
3116#pragma mark -
3117#pragma mark SCSI Parallel Device Object Accessors
3118#pragma mark -
3119#endif
3120
3121
3122//-----------------------------------------------------------------------------
3123//	GetHBATargetDataSize - Gets size of HBA data for the target.	[PROTECTED]
3124//-----------------------------------------------------------------------------
3125
3126UInt32
3127IOSCSIParallelInterfaceController::GetHBATargetDataSize (
3128								SCSITargetIdentifier 	targetID )
3129{
3130
3131	IOSCSIParallelInterfaceDevice *	targetDevice;
3132
3133	targetDevice = GetTargetForID ( targetID );
3134	if ( targetDevice == NULL )
3135	{
3136		return 0;
3137	}
3138
3139	return targetDevice->GetHBADataSize ( );
3140
3141}
3142
3143
3144//-----------------------------------------------------------------------------
3145//	GetHBATargetDataPointer - Gets size of HBA data for the target.	[PROTECTED]
3146//-----------------------------------------------------------------------------
3147
3148void *
3149IOSCSIParallelInterfaceController::GetHBATargetDataPointer (
3150								SCSITargetIdentifier 	targetID )
3151{
3152
3153	IOSCSIParallelInterfaceDevice *	targetDevice;
3154
3155	targetDevice = GetTargetForID ( targetID );
3156	if ( targetDevice == NULL )
3157	{
3158		return NULL;
3159	}
3160
3161	return targetDevice->GetHBADataPointer ( );
3162
3163}
3164
3165
3166#if 0
3167#pragma mark -
3168#pragma mark VTable Padding
3169#pragma mark -
3170#endif
3171
3172
3173// Space reserved for future expansion.
3174OSMetaClassDefineReservedUsed ( IOSCSIParallelInterfaceController,  1 );		// Used for DoesHBAPerformAutoSense
3175OSMetaClassDefineReservedUsed ( IOSCSIParallelInterfaceController,  2 );		// Used for ReportHBAConstraints
3176
3177OSMetaClassDefineReservedUsed ( IOSCSIParallelInterfaceController,  3 );		// Used for DoesHBASupportMultiPathing
3178OSMetaClassDefineReservedUnused ( IOSCSIParallelInterfaceController,  4 );
3179OSMetaClassDefineReservedUnused ( IOSCSIParallelInterfaceController,  5 );
3180OSMetaClassDefineReservedUnused ( IOSCSIParallelInterfaceController,  6 );
3181OSMetaClassDefineReservedUnused ( IOSCSIParallelInterfaceController,  7 );
3182OSMetaClassDefineReservedUnused ( IOSCSIParallelInterfaceController,  8 );
3183
3184OSMetaClassDefineReservedUsed ( IOSCSIParallelInterfaceController,  9 );		// Used for HandleTimeout
3185OSMetaClassDefineReservedUsed ( IOSCSIParallelInterfaceController, 10 );		// Used for FilterInterruptRequest
3186OSMetaClassDefineReservedUsed ( IOSCSIParallelInterfaceController, 11 );		// Used for InitializeDMASpecification
3187OSMetaClassDefineReservedUsed ( IOSCSIParallelInterfaceController, 12 );		// Used for CreateDeviceInterrupt
3188
3189OSMetaClassDefineReservedUnused ( IOSCSIParallelInterfaceController, 13 );
3190OSMetaClassDefineReservedUnused ( IOSCSIParallelInterfaceController, 14 );
3191OSMetaClassDefineReservedUnused ( IOSCSIParallelInterfaceController, 15 );
3192OSMetaClassDefineReservedUnused ( IOSCSIParallelInterfaceController, 16 );
3193