/* * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // Includes //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // Libkern includes #include #include #include // Storage Family includes #include // SCSI Architecture Model Family includes #include "SCSITargetDevicePathManager.h" #include "SCSITaskDefinition.h" //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // Macros //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ #define DEBUG 1 #define DEBUG_ASSERT_COMPONENT_NAME_STRING "SCSITargetDevicePathManager" #if DEBUG #define SCSI_PATH_MANAGER_DEBUGGING_LEVEL 0 #endif #include "IOSCSIArchitectureModelFamilyDebugging.h" #if ( SCSI_PATH_MANAGER_DEBUGGING_LEVEL >= 1 ) #define PANIC_NOW(x) IOPanic x #else #define PANIC_NOW(x) #endif #if ( SCSI_PATH_MANAGER_DEBUGGING_LEVEL >= 2 ) #define ERROR_LOG(x) IOLog x #else #define ERROR_LOG(x) #endif #if ( SCSI_PATH_MANAGER_DEBUGGING_LEVEL >= 3 ) #define STATUS_LOG(x) IOLog x; IOSleep(1) #else #define STATUS_LOG(x) #endif #define super OSObject OSDefineMetaClassAndStructors ( SCSITargetDevicePath, OSObject ); #define kIOPropertyBytesTransmittedKey "Bytes Transmitted" #define kIOPropertyBytesReceivedKey "Bytes Received" #define kIOPropertyCommandsProcessedKey "Commands Processed" //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // Create - Create the path object. [PUBLIC][STATIC] //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ SCSITargetDevicePath * SCSITargetDevicePath::Create ( SCSITargetDevicePathManager * manager, IOSCSIProtocolServices * initialPath ) { SCSITargetDevicePath * path = NULL; STATUS_LOG ( ( "SCSITargetDevicePath::Create\n" ) ); path = OSTypeAlloc ( SCSITargetDevicePath ); require_nonzero ( path, ErrorExit ); require ( path->InitWithObjects ( manager, initialPath ), ReleasePath ); return path; ReleasePath: require_nonzero_quiet ( path, ErrorExit ); path->release ( ); path = NULL; ErrorExit: return path; } //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // Create - Create the path object. [PUBLIC][STATIC] //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ bool SCSITargetDevicePath::InitWithObjects ( SCSITargetDevicePathManager * manager, IOSCSIProtocolServices * interface ) { bool result = false; OSNumber * number = NULL; OSString * string = NULL; STATUS_LOG ( ( "SCSITargetDevicePath::InitWithObjects\n" ) ); super::init ( ); fInterface = interface; fPathManager = manager; fStatistics = OSDictionary::withCapacity ( 4 ); require_nonzero ( fStatistics, ErrorExit ); fDomainIdentifier = GetInterfaceDomainIdentifier ( interface ); require_nonzero ( fDomainIdentifier, ReleaseStatistics ); fDomainIdentifier = OSNumber::withNumber ( fDomainIdentifier->unsigned32BitValue ( ), 32 ); fStatistics->setObject ( kIOPropertySCSIDomainIdentifierKey, fDomainIdentifier ); number = OSNumber::withNumber ( ( UInt64 ) 0, 64 ); require_nonzero ( number, ReleaseStatistics ); fBytesTransmitted = number; fStatistics->setObject ( kIOPropertyBytesTransmittedKey, number ); number = OSNumber::withNumber ( ( UInt64 ) 0, 64 ); require_nonzero ( number, ReleaseStatistics ); fBytesReceived = number; fStatistics->setObject ( kIOPropertyBytesReceivedKey, number ); number = OSNumber::withNumber ( ( UInt64 ) 0, 64 ); require_nonzero ( number, ReleaseStatistics ); fCommandsProcessed = number; fStatistics->setObject ( kIOPropertyCommandsProcessedKey, number ); fStatus = kIOPropertyPortStatusLinkEstablishedKey; string = OSString::withCStringNoCopy ( fStatus ); require_nonzero ( string, ReleaseStatistics ); fPathStatus = string; fStatistics->setObject ( kIOPropertyPortStatusKey, string ); STATUS_LOG ( ( "stats has %ld entries\n", fStatistics->getCount ( ) ) ); result = true; return result; ReleaseStatistics: require_nonzero_quiet ( fStatistics, ErrorExit ); fStatistics->release ( ); fStatistics = NULL; ErrorExit: return result; } //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // GetInterfaceDomainIdentifier - Gets Domain ID. [PUBLIC][STATIC] //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ OSNumber * SCSITargetDevicePath::GetInterfaceDomainIdentifier ( const IOSCSIProtocolServices * interface ) { OSDictionary * dict = NULL; OSNumber * number = NULL; OSObject * obj = NULL; obj = interface->getProperty ( kIOPropertyProtocolCharacteristicsKey, gIOServicePlane ); dict = OSDynamicCast ( OSDictionary, obj ); require_nonzero ( dict, ErrorExit ); obj = dict->getObject ( kIOPropertySCSIDomainIdentifierKey ); number = OSDynamicCast ( OSNumber, obj ); require_nonzero ( number, ErrorExit ); ErrorExit: return number; } //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // Activate - Changes path status. [PUBLIC] //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void SCSITargetDevicePath::Activate ( void ) { fStatus = kIOPropertyPortStatusLinkEstablishedKey; fPathStatus->initWithCStringNoCopy ( fStatus ); } //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // Inactivate - Changes path status. [PUBLIC] //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void SCSITargetDevicePath::Inactivate ( void ) { fStatus = kIOPropertyPortStatusNoLinkEstablishedKey; fPathStatus->initWithCStringNoCopy ( fStatus ); } //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // free - Called to free resources. [PUBLIC] //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void SCSITargetDevicePath::free ( void ) { STATUS_LOG ( ( "+SCSITargetDevicePath::free\n" ) ); if ( fStatistics != NULL ) { fStatistics->release ( ); fStatistics = NULL; } if ( fDomainIdentifier != NULL ) { fDomainIdentifier->release ( ); fDomainIdentifier = NULL; } if ( fBytesTransmitted != NULL ) { fBytesTransmitted->release ( ); fBytesTransmitted = NULL; } if ( fBytesReceived != NULL ) { fBytesReceived->release ( ); fBytesReceived = NULL; } if ( fCommandsProcessed != NULL ) { fCommandsProcessed->release ( ); fCommandsProcessed = NULL; } if ( fPathStatus != NULL ) { fPathStatus->release ( ); fPathStatus = NULL; } super::free ( ); STATUS_LOG ( ( "-SCSITargetDevicePath::free\n" ) ); } #undef super #define super OSObject OSDefineMetaClass ( SCSITargetDevicePathManager, OSObject ); OSDefineAbstractStructors ( SCSITargetDevicePathManager, OSObject ); //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // InitializePathManagerForTarget - Initializes the path manager. [PROTECTED] //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ bool SCSITargetDevicePathManager::InitializePathManagerForTarget ( IOSCSITargetDevice * target, IOSCSIProtocolServices * initialPath ) { bool result = false; STATUS_LOG ( ( "SCSITargetDevicePathManager::InitializePathManagerForTarget\n" ) ); super::init ( ); fStatistics = OSArray::withCapacity ( 1 ); require_nonzero ( fStatistics, ErrorExit ); fTarget = target; result = true; return result; ReleaseStats: require_nonzero_quiet ( fStatistics, ReleaseStats ); fStatistics->release ( ); fStatistics = NULL; ErrorExit: return result; } //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ PathTaskCallback - C-C++ Glue code. [PUBLIC][STATIC] //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void SCSITargetDevicePathManager::PathTaskCallback ( SCSITaskIdentifier request ) { SCSITargetDevicePath * path = NULL; SCSITargetDevicePathManager * manager = NULL; IOSCSITargetDevice * target = NULL; STATUS_LOG ( ( "SCSITargetDevicePathManager::PathTaskCallback\n" ) ); path = ( SCSITargetDevicePath * ) GetPathLayerReference ( request ); require_nonzero_quiet ( path, ErrorExit ); manager = path->GetPathManager ( ); require_nonzero ( manager, ErrorExit ); // Call path manager hook for task completion. manager->TaskCompletion ( request, path ); ErrorExit: target = ( IOSCSITargetDevice * ) IOSCSITargetDevice::GetTargetLayerReference ( request ); target->TargetTaskCompletion ( request ); } //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ TaskCompletion - Called to complete a task. [PROTECTED] //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void SCSITargetDevicePathManager::TaskCompletion ( SCSITaskIdentifier request, SCSITargetDevicePath * path ) { UInt64 bytes = 0; IOSCSITargetDevice * target = NULL; STATUS_LOG ( ( "SCSITargetDevicePathManager::TaskCompletion\n" ) ); target = ( IOSCSITargetDevice * ) IOSCSITargetDevice::GetTargetLayerReference ( request ); if ( IsTransmit ( request, target, &bytes ) == true ) { STATUS_LOG ( ( "path->AddBytesTransmitted\n" ) ); path->AddBytesTransmitted ( bytes ); } else if ( IsReceive ( request, target, &bytes ) == true ) { STATUS_LOG ( ( "path->AddBytesReceived\n" ) ); path->AddBytesReceived ( bytes ); } STATUS_LOG ( ( "path->IncrementCommandsProcessed\n" ) ); path->IncrementCommandsProcessed ( ); } //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ IsTransmit - Figures out if packet was transmission from host and if so, // how many bytes were transmitted. [PROTECTED] //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ bool SCSITargetDevicePathManager::IsTransmit ( SCSITaskIdentifier request, IOSCSITargetDevice * target, UInt64 * bytes ) { bool result = false; if ( target->GetDataTransferDirection ( request ) == kSCSIDataTransfer_FromInitiatorToTarget ) { result = true; *bytes = target->GetRealizedDataTransferCount ( request ); } return result; } //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ IsReceive - Figures out if packet was received from device and if so, // how many bytes were transmitted. [PROTECTED] //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ bool SCSITargetDevicePathManager::IsReceive ( SCSITaskIdentifier request, IOSCSITargetDevice * target, UInt64 * bytes ) { bool result = false; if ( target->GetDataTransferDirection ( request ) == kSCSIDataTransfer_FromTargetToInitiator ) { result = true; *bytes = target->GetRealizedDataTransferCount ( request ); } return result; } //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ SetPathLayerReference - Sets path layer reference value. [PROTECTED] //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ bool SCSITargetDevicePathManager::SetPathLayerReference ( SCSITaskIdentifier request, void * newReference ) { SCSITask * scsiRequest = NULL; bool result = NULL; scsiRequest = OSDynamicCast ( SCSITask, request ); if ( scsiRequest != NULL ) { result = scsiRequest->SetPathLayerReference ( newReference ); } return result; } //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ GetPathLayerReference - Gets path layer reference value. [PROTECTED] //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void * SCSITargetDevicePathManager::GetPathLayerReference ( SCSITaskIdentifier request ) { SCSITask * scsiRequest = NULL; void * result = NULL; scsiRequest = OSDynamicCast ( SCSITask, request ); if ( scsiRequest != NULL ) { result = scsiRequest->GetPathLayerReference ( ); } return result; } //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ free - Called to free all resources. [PROTECTED] //ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void SCSITargetDevicePathManager::free ( void ) { STATUS_LOG ( ( "+SCSITargetDevicePathManager::free\n" ) ); if ( fStatistics != NULL ) { fStatistics->release ( ); fStatistics = NULL; } super::free ( ); STATUS_LOG ( ( "-SCSITargetDevicePathManager::free\n" ) ); }