/*
* Copyright (c) 2004-2007 Apple Inc. All rights reserved.
*
* IMPORTANT: This Apple software is supplied to you by Apple 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 <unistd.h>
#import "SCSIDevice.h"
#import "Probing.h"
#import "SCSITargetProberKeys.h"
#import <IOKit/IOKitLib.h>
#import <IOKit/IOKitKeys.h>
#import <IOKit/storage/IOStorageProtocolCharacteristics.h>
#import <IOKit/scsi/SCSICmds_INQUIRY_Definitions.h>
//ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
// 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: @" [ 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: @" }
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