OSSet * AppleNForceATARoot::createATAChannels( void ) { OSSet * nubSet; OSDictionary * channelInfo; IORegistryEntry * dtEntry; char* debugInfo; do { nubSet = OSSet::withCapacity(2); if (nubSet == 0) break; if (fProvider->open(this) != true) break; for ( UInt32 channelID = 0; channelID < 2; channelID++ ) { // Create a dictionary for the channel info. Use native mode // settings if possible, else default to legacy mode. debugInfo = "native"; channelInfo = createNativeModeChannelInfo( channelID ); if (channelInfo == 0) { debugInfo = "legacy"; channelInfo = createLegacyModeChannelInfo( channelID ); } if (channelInfo == 0) continue; DEBUG_LOG( "%s::%s() [this=%p] created channel %d in %s mode.\n", getName(), __FUNCTION__, this, (int)channelID, debugInfo ); // Create a nub for each ATA channel. AppleNForceATAChannel * nub = new AppleNForceATAChannel; if ( nub ) { dtEntry = getDTChannelEntry( channelID ); // Invoke special init method in channel nub. if (nub->init( this, channelInfo, dtEntry ) && nub->attach( this )) { nubSet->setObject( nub ); } if ( dtEntry ) { dtEntry->release(); } else { // Platform did not create a device tree entry for // this ATA channel. Do it here. char channelName[5] = {'C','H','N','_','\0'}; channelName[3] = '0' + channelID; nub->setName( channelName ); if (fProvider->inPlane(gIODTPlane)) { nub->attachToParent( fProvider, gIODTPlane ); } } nub->release(); } channelInfo->release(); } fProvider->close( this ); } while ( false ); // Release and invalidate an empty set. if (nubSet && (nubSet->getCount() == 0)) { nubSet->release(); nubSet = 0; } return nubSet; }
OSSet * AppleIntelPIIXATARoot::createATAChannelNubs( void ) { OSSet * nubSet; OSDictionary * channelInfo; IORegistryEntry * dtEntry; UInt32 priChannelMode; UInt32 secChannelMode; UInt8 mapValue = 0; do { nubSet = OSSet::withCapacity(2); if ( nubSet == 0 ) break; if ( _provider->open( this ) != true ) break; priChannelMode = kChannelModePATA; secChannelMode = kChannelModePATA; // Determine SATA channel mode based on Port Mapping Register. if ( getProperty( kSerialATAKey ) == kOSBooleanTrue ) { OSString * hwName; hwName = OSDynamicCast(OSString, getProperty(kControllerNameKey)); mapValue = _provider->configRead8(kPIIX_PCI_MAP); setProperty( kPortMappingKey, mapValue, 8 ); priChannelMode = kChannelModeDisabled; secChannelMode = kChannelModeDisabled; if (hwName) { if (hwName->isEqualTo("ICH7-M SATA")) { mapValue &= 0x3; priChannelMode = gICH7MChannelModeMap[mapValue][0]; secChannelMode = gICH7MChannelModeMap[mapValue][1]; } else if (hwName->isEqualTo("ICH6 SATA") || hwName->isEqualTo("ESB2 SATA")) { mapValue &= 0x3; priChannelMode = gICH6ChannelModeMap[mapValue][0]; secChannelMode = gICH6ChannelModeMap[mapValue][1]; } else if (hwName->isEqualTo("ICH6-M SATA")) { mapValue &= 0x3; priChannelMode = gICH6MChannelModeMap[mapValue][0]; secChannelMode = gICH6MChannelModeMap[mapValue][1]; } else if (hwName->isEqualTo("ICH5 SATA")) { mapValue &= 0x7; priChannelMode = gICH5ChannelModeMap[mapValue][0]; secChannelMode = gICH5ChannelModeMap[mapValue][1]; } else /* if (hwName->isEqualTo("ICH7 SATA")) */ { mapValue &= 0x3; priChannelMode = gICH7ChannelModeMap[mapValue][0]; secChannelMode = gICH7ChannelModeMap[mapValue][1]; } } } if ( priChannelMode == kChannelModeDisabled && secChannelMode == kChannelModeDisabled ) { IOLog("%s: bad value (%x) in Port Mapping register", getName(), mapValue); _provider->close( this ); break; } for ( UInt32 channelID = 0; channelID < 2; channelID++ ) { UInt32 channelMode = (channelID ? secChannelMode : priChannelMode); // Create a dictionary for the channel info. Use native mode // settings if possible, else default to legacy mode. channelInfo = createNativeModeChannelInfo( channelID, channelMode ); if (channelInfo == 0) channelInfo = createLegacyModeChannelInfo( channelID, channelMode ); if (channelInfo == 0) continue; // Create a nub for each ATA channel. AppleIntelPIIXATAChannel * nub = new AppleIntelPIIXATAChannel; if ( nub ) { dtEntry = getDTChannelEntry( channelID ); if ( nub->init( this, channelInfo, dtEntry ) && nub->attach( this ) ) { nubSet->setObject( nub ); } if ( dtEntry ) { dtEntry->release(); } else { // Platform did not create a device tree entry for // this ATA channel. Do it here. char channelName[5] = {'C','H','N','_','\0'}; channelName[3] = '0' + channelID; nub->setName( channelName ); if ( _provider->inPlane(gIODTPlane) ) { nub->attachToParent( _provider, gIODTPlane ); } } nub->release(); } channelInfo->release(); } _provider->close( this ); } while ( false ); // Release and invalidate an empty set. if ( nubSet && (nubSet->getCount() == 0) ) { nubSet->release(); nubSet = 0; } return nubSet; }
OSSet * IOPartitionScheme::juxtaposeMediaObjects(OSSet * partitionsOld, OSSet * partitionsNew) { // // Updates a set of existing partitions, represented by partitionsOld, // with possible updates from a rescan of the disk, represented by // partitionsNew. It returns a new set of partitions with the results, // removing partitions from partitionsOld where applicable, adding // partitions from partitionsNew where applicable, and folding in property // changes to partitions from partitionsNew into partitionsOld where // applicable. // OSIterator * iterator = 0; OSIterator * iterator1 = 0; OSIterator * iterator2 = 0; OSSymbol * key; OSSet * keys = 0; IOMedia * partition; IOMedia * partition1; IOMedia * partition2; OSSet * partitions = 0; OSOrderedSet * partitions1 = 0; OSOrderedSet * partitions2 = 0; UInt32 partitionID = 0; OSDictionary * properties; // Allocate a set to hold the set of media objects representing partitions. partitions = OSSet::withCapacity( partitionsNew->getCapacity( ) ); if ( partitions == 0 ) goto juxtaposeErr; // Prepare the reference set of partitions. partitions1 = OSOrderedSet::withCapacity( partitionsOld->getCapacity( ), partitionComparison, 0 ); if ( partitions1 == 0 ) goto juxtaposeErr; iterator1 = OSCollectionIterator::withCollection( partitionsOld ); if ( iterator1 == 0 ) goto juxtaposeErr; while ( ( partition1 = ( IOMedia * ) iterator1->getNextObject( ) ) ) { partitionID = max( partitionID, strtoul( partition1->getLocation( ), NULL, 10 ) ); partitions1->setObject( partition1 ); } iterator1->release( ); iterator1 = 0; // Prepare the comparison set of partitions. partitions2 = OSOrderedSet::withCapacity( partitionsNew->getCapacity( ), partitionComparison, 0 ); if ( partitions2 == 0 ) goto juxtaposeErr; iterator2 = OSCollectionIterator::withCollection( partitionsNew ); if ( iterator2 == 0 ) goto juxtaposeErr; while ( ( partition2 = ( IOMedia * ) iterator2->getNextObject( ) ) ) { partitionID = max( partitionID, strtoul( partition2->getLocation( ), NULL, 10 ) ); partitions2->setObject( partition2 ); } iterator2->release( ); iterator2 = 0; // Juxtapose the partitions. iterator1 = OSCollectionIterator::withCollection( partitions1 ); if ( iterator1 == 0 ) goto juxtaposeErr; iterator2 = OSCollectionIterator::withCollection( partitions2 ); if ( iterator2 == 0 ) goto juxtaposeErr; partition1 = ( IOMedia * ) iterator1->getNextObject( ); partition2 = ( IOMedia * ) iterator2->getNextObject( ); while ( partition1 || partition2 ) { UInt64 base1; UInt64 base2; base1 = partition1 ? partition1->getBase( ) : UINT64_MAX; base2 = partition2 ? partition2->getBase( ) : UINT64_MAX; #if TARGET_OS_EMBEDDED if ( partition1 && partition2 ) { OSString * uuid1; OSString * uuid2; uuid1 = OSDynamicCast( OSString, partition1->getProperty( kIOMediaUUIDKey ) ); uuid2 = OSDynamicCast( OSString, partition2->getProperty( kIOMediaUUIDKey ) ); if ( uuid1 || uuid2 ) { if ( uuid1 == 0 ) { base1 = UINT64_MAX; } else if ( uuid2 == 0 ) { base2 = UINT64_MAX; } else { int compare; compare = strcmp( uuid1->getCStringNoCopy( ), uuid2->getCStringNoCopy( ) ); if ( compare > 0 ) { base1 = UINT64_MAX; } else if ( compare < 0 ) { base2 = UINT64_MAX; } else { base1 = base2; } } } } #endif /* TARGET_OS_EMBEDDED */ if ( base1 > base2 ) { // A partition was added. partition2->setProperty( kIOMediaLiveKey, true ); iterator = OSCollectionIterator::withCollection( partitions1 ); if ( iterator == 0 ) goto juxtaposeErr; while ( ( partition = ( IOMedia * ) iterator->getNextObject( ) ) ) { if ( strcmp( partition->getLocation( ), partition2->getLocation( ) ) == 0 ) { // Set a location value for this partition. char location[ 12 ]; partitionID++; snprintf( location, sizeof( location ), "%d", ( int ) partitionID ); partition2->setLocation( location ); partition2->setProperty( kIOMediaLiveKey, false ); break; } } iterator->release( ); iterator = 0; if ( partition2->attach( this ) ) { attachMediaObjectToDeviceTree( partition2 ); partition2->registerService( kIOServiceAsynchronous ); } partitions->setObject( partition2 ); partition2 = ( IOMedia * ) iterator2->getNextObject( ); } else if ( base1 < base2 ) { // A partition was removed. partition1->setProperty( kIOMediaLiveKey, false ); if ( handleIsOpen( partition1 ) == false ) { partition1->terminate( kIOServiceSynchronous ); detachMediaObjectFromDeviceTree( partition1 ); } else { partition1->removeProperty( kIOMediaPartitionIDKey ); partitions->setObject( partition1 ); } partition1 = ( IOMedia * ) iterator1->getNextObject( ); } else { // A partition was matched. bool edit; bool move; edit = false; move = false; keys = OSSet::withCapacity( 1 ); if ( keys == 0 ) goto juxtaposeErr; properties = partition2->getPropertyTable( ); // Determine which properties were updated. if ( partition1->getBase( ) != partition2->getBase( ) || partition1->getSize( ) != partition2->getSize( ) || partition1->getPreferredBlockSize( ) != partition2->getPreferredBlockSize( ) || partition1->getAttributes( ) != partition2->getAttributes( ) || partition1->isWhole( ) != partition2->isWhole( ) || partition1->isWritable( ) != partition2->isWritable( ) || strcmp( partition1->getContentHint( ), partition2->getContentHint( ) ) ) { edit = true; } if ( strcmp( partition1->getName( ), partition2->getName( ) ) || strcmp( partition1->getLocation( ), partition2->getLocation( ) ) ) { move = true; } iterator = OSCollectionIterator::withCollection( properties ); if ( iterator == 0 ) goto juxtaposeErr; while ( ( key = ( OSSymbol * ) iterator->getNextObject( ) ) ) { OSObject * value1; OSObject * value2; if ( key->isEqualTo( kIOMediaContentHintKey ) || key->isEqualTo( kIOMediaEjectableKey ) || key->isEqualTo( kIOMediaPreferredBlockSizeKey ) || key->isEqualTo( kIOMediaRemovableKey ) || key->isEqualTo( kIOMediaSizeKey ) || key->isEqualTo( kIOMediaWholeKey ) || key->isEqualTo( kIOMediaWritableKey ) ) { continue; } if ( key->isEqualTo( kIOMediaContentKey ) || key->isEqualTo( kIOMediaLeafKey ) || key->isEqualTo( kIOMediaLiveKey ) || key->isEqualTo( kIOMediaOpenKey ) ) { continue; } value1 = partition1->getProperty( key ); value2 = partition2->getProperty( key ); if ( value1 == 0 || value1->isEqualTo( value2 ) == false ) { keys->setObject( key ); } } iterator->release( ); iterator = 0; // A partition was updated. partition1->setProperty( kIOMediaLiveKey, ( move == false ) ); if ( edit ) { partition1->init( partition2->getBase( ), partition2->getSize( ), partition2->getPreferredBlockSize( ), partition2->getAttributes( ), partition2->isWhole( ), partition2->isWritable( ), partition2->getContentHint( ) ); } if ( keys->getCount( ) ) { iterator = OSCollectionIterator::withCollection( keys ); if ( iterator == 0 ) goto juxtaposeErr; while ( ( key = ( OSSymbol * ) iterator->getNextObject( ) ) ) { partition1->setProperty( key, partition2->getProperty( key ) ); } iterator->release( ); iterator = 0; } if ( edit || keys->getCount( ) ) { partition1->messageClients( kIOMessageServicePropertyChange ); partition1->registerService( kIOServiceAsynchronous ); } keys->release( ); keys = 0; partitions->setObject( partition1 ); partition1 = ( IOMedia * ) iterator1->getNextObject( ); partition2 = ( IOMedia * ) iterator2->getNextObject( ); } } // Release our resources. iterator1->release( ); iterator2->release( ); partitions1->release( ); partitions2->release( ); return partitions; juxtaposeErr: // Release our resources. if ( iterator ) iterator->release( ); if ( iterator1 ) iterator1->release( ); if ( iterator2 ) iterator2->release( ); if ( keys ) keys->release( ); if ( partitions ) partitions->release( ); if ( partitions1 ) partitions1->release( ); if ( partitions2 ) partitions2->release( ); return 0; }