/* * © Copyright 2004 Apple Computer, Inc. All rights reserved. * * IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. (ÒAppleÓ) in * consideration of your agreement to the following terms, and your use, installation, * modification or redistribution of this Apple software constitutes acceptance of these * terms. If you do not agree with these terms, please do not use, install, modify or * redistribute this Apple software. * * In consideration of your agreement to abide by the following terms, and subject to these * terms, Apple grants you a personal, non exclusive license, under AppleÕs copyrights in this * original Apple software (the ÒApple SoftwareÓ), to use, reproduce, modify and redistribute * the Apple Software, with or without modifications, in source and/or binary forms; provided * that if you redistribute the Apple Software in its entirety and without modifications, you * must retain this notice and the following text and disclaimers in all such redistributions * of the Apple Software. Neither the name, trademarks, service marks or logos of Apple * Computer, Inc. may be used to endorse or promote products derived from the Apple Software * without specific prior written permission from Apple. Except as expressly stated in this * notice, no other rights or licenses, express or implied, are granted by Apple herein, * including but not limited to any patent rights that may be infringed by your derivative * works or by other works in which the Apple Software may be incorporated. * * The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON- * INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE * SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. * * IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, * REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND * WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR * OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ //ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ // Imports //ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ #import #import "SCSIDevice.h" #import "Probing.h" #import "SCSITargetProberKeys.h" #import #import #import #import //ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ // Constants //ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ #define kIOSCSITargetDeviceClassString "IOSCSITargetDevice" // "SCSI I_T Nexus Features" is only defined in // IOSCSIParallelInterfaceController.h, but it isn't exported to user space (yet). // Until it is, we have to create a string here and also copy the enums from the // header as well. // Remove this when the header is exported. #define kSCSI_I_T_NexusFeaturesString @"SCSI I_T Nexus Features" enum { kSCSIParallelFeature_WideDataTransfer = 0, kSCSIParallelFeature_SynchronousDataTransfer = 1, kSCSIParallelFeature_QuickArbitrationAndSelection = 2, kSCSIParallelFeature_DoubleTransitionDataTransfers = 3, kSCSIParallelFeature_InformationUnitTransfers = 4 }; enum { kSCSIParallelFeature_WideDataTransferMask = (1 << kSCSIParallelFeature_WideDataTransfer), kSCSIParallelFeature_SynchronousDataTransferMask = (1 << kSCSIParallelFeature_SynchronousDataTransfer), kSCSIParallelFeature_QuickArbitrationAndSelectionMask = (1 << kSCSIParallelFeature_QuickArbitrationAndSelection), kSCSIParallelFeature_DoubleTransitionDataTransfersMask = (1 << kSCSIParallelFeature_DoubleTransitionDataTransfers), kSCSIParallelFeature_InformationUnitTransfersMask = (1 << kSCSIParallelFeature_InformationUnitTransfers) }; //ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ // Implementation //ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ @implementation SCSIDevice - ( NSString * ) physicalInterconnect { return physicalInterconnect; } - ( NSString * ) manufacturer { return manufacturer; } - ( NSString * ) model { return model; } - ( NSString * ) revision { return revision; } - ( NSString * ) peripheralDeviceType { return peripheralDeviceType; } - ( NSNumber * ) domainIdentifier { return domainIdentifier; } - ( NSNumber * ) deviceIdentifier { return deviceIdentifier; } - ( NSArray * ) features { return features; } - ( NSImage * ) image { return image; } - ( BOOL ) devicePresent { return devicePresent; } - ( BOOL ) isInitiator { return isInitiator; } // Called to initialize the object with an io_service_t. - ( id ) initWithService: ( io_service_t ) service { CFTypeRef property = NULL; id value = NULL; IOReturn result = kIOReturnSuccess; io_iterator_t iterator = MACH_PORT_NULL; self = [ super init ]; if ( self != nil ) { // Init to known state [ self clearInformation ]; // Get the protocol characteristics key. property = IORegistryEntrySearchCFProperty ( service, kIOServicePlane, CFSTR ( kIOPropertyProtocolCharacteristicsKey ), kCFAllocatorDefault, kIORegistryIterateRecursively ); if ( property != NULL ) { // Get the physical interconnect value = ( id ) CFDictionaryGetValue ( ( CFDictionaryRef ) property, CFSTR ( kIOPropertyPhysicalInterconnectTypeKey ) ); [ self setPhysicalInterconnect: ( NSString * ) value ]; // Get the SCSI Domain ID value = ( id ) CFDictionaryGetValue ( ( CFDictionaryRef ) property, CFSTR ( kIOPropertySCSIDomainIdentifierKey ) ); [ self setDomainIdentifier: ( NSNumber * ) value ]; // Get the SCSI Target ID value = ( id ) CFDictionaryGetValue ( ( CFDictionaryRef ) property, CFSTR ( kIOPropertySCSITargetIdentifierKey ) ); [ self setDeviceIdentifier: ( NSNumber * ) value ]; CFRelease ( property ); } // See if there is any more information we can fill in (i.e. is a target present?) result = IORegistryEntryGetChildIterator ( service, kIOServicePlane, &iterator ); if ( result == kIOReturnSuccess ) { io_registry_entry_t entry = MACH_PORT_NULL; entry = IOIteratorNext ( iterator ); while ( entry != MACH_PORT_NULL ) { // Is this an IOSCSITargetDevice? if ( IOObjectConformsTo ( entry, kIOSCSITargetDeviceClassString ) ) { NSNumber * number = nil; // We have a target device present at this location. // Get the information from it. [ self setDevicePresent: YES ]; [ self setImage: [ NSImage imageNamed: kHardDiskImageString ] ]; [ self setIsInitiator: NO ]; // Get the PDT value = ( id ) IORegistryEntrySearchCFProperty ( service, kIOServicePlane, CFSTR ( kIOPropertySCSIPeripheralDeviceType ), kCFAllocatorDefault, kIORegistryIterateRecursively ); [ self setPeripheralDeviceType: [ NSString stringWithFormat: @"%02Xh", [ value intValue ] ] ]; [ value release ]; // Get the Vendor ID value = ( id ) IORegistryEntrySearchCFProperty ( service, kIOServicePlane, CFSTR ( kIOPropertySCSIVendorIdentification ), kCFAllocatorDefault, kIORegistryIterateRecursively ); [ self setManufacturer: value ]; [ value release ]; // Get the Product ID value = ( id ) IORegistryEntrySearchCFProperty ( service, kIOServicePlane, CFSTR ( kIOPropertySCSIProductIdentification ), kCFAllocatorDefault, kIORegistryIterateRecursively ); [ self setModel: value ]; [ value release ]; // Get the Product Revision Level value = ( id ) IORegistryEntrySearchCFProperty ( service, kIOServicePlane, CFSTR ( kIOPropertySCSIProductRevisionLevel ), kCFAllocatorDefault, kIORegistryIterateRecursively ); [ self setRevision: value ]; [ value release ]; // Get the I_T Nexus Features value = ( id ) IORegistryEntrySearchCFProperty ( service, kIOServicePlane, CFSTR ( kIOPropertyProtocolCharacteristicsKey ), kCFAllocatorDefault, kIORegistryIterateRecursively ); number = [ ( NSDictionary * ) value objectForKey: kSCSI_I_T_NexusFeaturesString ]; [ self setFeatures: [ self buildFeatureList: number ] ]; [ value release ]; } IOObjectRelease ( entry ); entry = IOIteratorNext ( iterator ); } IOObjectRelease ( iterator ); } } return self; } // Called to get the SCSI Domain ID for the io_service_t. + ( int ) domainIDForService: ( io_service_t ) service { int domain = 0; id value = nil; // Get the protocol characteristics key. value = ( id ) IORegistryEntrySearchCFProperty ( service, kIOServicePlane, CFSTR ( kIOPropertyProtocolCharacteristicsKey ), kCFAllocatorDefault, 0 ); // Get the SCSI Domain ID. domain = [ [ value objectForKey: @kIOPropertySCSIDomainIdentifierKey ] intValue ]; [ value release ]; return domain; } // Called to get the SCSI Target ID for the io_service_t. + ( int ) targetIDForService: ( io_service_t ) service { int target = 0; id value = nil; // Get the protocol characteristics key. value = ( id ) IORegistryEntrySearchCFProperty ( service, kIOServicePlane, CFSTR ( kIOPropertyProtocolCharacteristicsKey ), kCFAllocatorDefault, 0 ); // Get the SCSI Target ID. target = [ [ value objectForKey: @kIOPropertySCSITargetIdentifierKey ] intValue ]; [ value release ]; return target; } // Builds a feature list out of the bitmask. - ( NSArray * ) buildFeatureList: ( NSNumber * ) number { NSMutableArray * featureList = nil; NSString * string = nil; int value = 0; // Create an array to which we'll add string descriptions. featureList = [ [ [ NSMutableArray alloc ] init ] autorelease ]; // Get the actual value as an int. value = [ number intValue ]; // Does this device support Sync transfer? if ( value & kSCSIParallelFeature_SynchronousDataTransferMask ) { // Yes, get localized string. string = [ [ NSBundle mainBundle ] localizedStringForKey: kSCSIParallelFeatureSyncString value: kSCSIParallelFeatureSyncString table: nil ]; // Add localized string to feature list. [ featureList addObject: string ]; } // Does this device support Wide transfer? if ( value & kSCSIParallelFeature_WideDataTransferMask ) { // Yes, get localized string. string = [ [ NSBundle mainBundle ] localizedStringForKey: kSCSIParallelFeatureWideString value: kSCSIParallelFeatureWideString table: nil ]; // Add localized string to feature list. [ featureList addObject: string ]; } // Does this device support QAS? if ( value & kSCSIParallelFeature_QuickArbitrationAndSelectionMask ) { // Yes, get localized string. string = [ [ NSBundle mainBundle ] localizedStringForKey: kSCSIParallelFeatureQASString value: kSCSIParallelFeatureQASString table: nil ]; // Add localized string to feature list. [ featureList addObject: string ]; } // Does this device support DT? if ( value & kSCSIParallelFeature_DoubleTransitionDataTransfersMask ) { // Yes, get localized string. string = [ [ NSBundle mainBundle ] localizedStringForKey: kSCSIParallelFeatureDTString value: kSCSIParallelFeatureDTString table: nil ]; // Add localized string to feature list. [ featureList addObject: string ]; } // Does this device support IU? if ( value & kSCSIParallelFeature_InformationUnitTransfersMask ) { // Yes, get localized string. string = [ [ NSBundle mainBundle ] localizedStringForKey: kSCSIParallelFeatureIUString value: kSCSIParallelFeatureIUString table: nil ]; // Add localized string to feature list. [ featureList addObject: string ]; } return featureList; } - ( NSString * ) title { NSString * string = @"No Device Present"; if ( devicePresent == YES ) { string = [ NSString stringWithFormat: @"%@ %@", manufacturer, model ]; } return string; } - ( void ) clearInformation { [ self setPhysicalInterconnect: nil ]; [ self setManufacturer: nil ]; [ self setModel: nil ]; [ self setRevision: nil ]; [ self setPeripheralDeviceType: nil ]; [ self setDomainIdentifier: nil ]; [ self setDeviceIdentifier: nil ]; [ self setFeatures: nil ]; [ self setIsInitiator: NO ]; [ self setDevicePresent: NO ]; [ self setImage: [ NSImage imageNamed: kNothingImageString ] ]; } - ( void ) setIsInitiator: ( BOOL ) value { isInitiator = value; if ( isInitiator ) { [ self setPeripheralDeviceType: @"N/A" ]; } } - ( void ) setDevicePresent: ( BOOL ) value { devicePresent = value; } - ( void ) setPhysicalInterconnect: ( NSString * ) p { [ p retain ]; [ physicalInterconnect release ]; physicalInterconnect = p; } - ( void ) setManufacturer: ( NSString * ) m { [ m retain ]; [ manufacturer release ]; manufacturer = m; } - ( void ) setModel: ( NSString * ) m { [ m retain ]; [ model release ]; model = m; } - ( void ) setRevision: ( NSString * ) r { [ r retain ]; [ revision release ]; revision = r; } - ( void ) setPeripheralDeviceType: ( NSString * ) p { [ p retain ]; [ peripheralDeviceType release ]; peripheralDeviceType = p; } - ( void ) setDomainIdentifier: ( NSNumber * ) i { [ i retain ]; [ domainIdentifier release ]; domainIdentifier = i; } - ( void ) setDeviceIdentifier: ( NSNumber * ) i { [ i retain ]; [ deviceIdentifier release ]; deviceIdentifier = i; } - ( void ) setFeatures: ( NSArray * ) f { [ f retain ]; [ features release ]; features = f; } - ( void ) setImage: ( NSImage * ) i { [ i retain ]; [ image release ]; image = i; } // Action method called by clicking on the "Reprobe" button - ( IBAction ) reprobe: ( id ) sender { #pragma unused ( sender ) IOReturn result = kIOReturnSuccess; // Call the ReprobeDomainTarget method and pass the domainID // and targetID for this object since it is the one we are // reprobing. result = ReprobeDomainTarget ( [ domainIdentifier intValue ], [ deviceIdentifier intValue ] ); } @end