/* * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * The contents of this file constitute Original Code as defined in and * are subject to the Apple Public Source License Version 1.1 (the * "License"). You may not use this file except in compliance with the * License. Please obtain a copy of the License at * http://www.apple.com/publicsource and read it before using this file. * * This 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 OR NON-INFRINGEMENT. Please see the * License for the specific language governing rights and limitations * under the License. * * @APPLE_LICENSE_HEADER_END@ */ #include #include "AppleGenericPCMultiATADriver.h" #include "AppleGenericPCATAController.h" #include "AppleGenericPCATAKeys.h" #define super IOService OSDefineMetaClassAndStructors( AppleGenericPCMultiATADriver, IOService ) //--------------------------------------------------------------------------- // // Start the Multi-ATA controller driver. // bool AppleGenericPCMultiATADriver::start( IOService * provider ) { if ( super::start(provider) != true ) { return false; } _provider = provider; _provider->retain(); _nubs = createControllerNubs(); if ( _nubs == 0 ) { return false; } _openNubs = OSSet::withCapacity( _nubs->getCount() ); if ( _openNubs == 0 ) { return false; } return true; } //--------------------------------------------------------------------------- // // Release allocated resources before this object is destroyed. // void AppleGenericPCMultiATADriver::free() { if ( _nubs ) { _nubs->release(); _nubs = 0; } if ( _openNubs ) { _openNubs->release(); _openNubs = 0; } if ( _provider ) { _provider->release(); _provider = 0; } super::free(); } //--------------------------------------------------------------------------- // // Create nubs based on the channel information in the driver personality. // OSSet * AppleGenericPCMultiATADriver::createControllerNubs() { OSSet * nubSet; OSArray * channels; OSDictionary * channelInfo; AppleGenericPCATAController * nub; do { nubSet = OSSet::withCapacity(4); if ( nubSet == 0 ) break; // Fetch the ATA channel description array from the property table. channels = OSDynamicCast( OSArray, getProperty( kATAChannelsKey ) ); if ( channels == 0 ) break; for ( UInt32 i = 0; ; i++) { channelInfo = OSDynamicCast( OSDictionary, channels->getObject(i) ); if ( channelInfo == 0 ) break; // Create a new controller nub for each ATA channel. // Attach this nub as a child. nub = new AppleGenericPCATAController; if ( nub ) { if ( nub->init( channelInfo ) && nub->attach( this ) && nubSet->setObject( nub ) ) { nub->registerService(); } nub->release(); } } } while ( false ); // Release and invalidate an empty set. if ( nubSet && (nubSet->getCount() == 0) ) { nubSet->release(); nubSet = 0; } return nubSet; } //--------------------------------------------------------------------------- // // Handle an open request from a client. Several clients can call this // function and hold an open on this controller. // bool AppleGenericPCMultiATADriver::handleOpen( IOService * client, IOOptionBits options, void * arg ) { bool ret = true; // Reject open request from unknown clients, or if the client // already holds an open. if ( ( _nubs->containsObject( client ) == false ) || ( _openNubs->containsObject( client ) == true ) ) return false; // First client open will trigger an open to our provider. if ( _openNubs->getCount() == 0 ) ret = _provider->open( this ); if ( ret ) { _openNubs->setObject( client ); if ( arg ) *((IOService **) arg) = _provider; } return ret; } //--------------------------------------------------------------------------- // // Handle a close request from a client. // void AppleGenericPCMultiATADriver::handleClose( IOService * client, IOOptionBits options ) { // Reject close request from clients that do not hold an open. if ( _openNubs->containsObject( client ) == false ) return; _openNubs->removeObject( client ); // Last client close will trigger a close to our provider. if ( _openNubs->getCount() == 0 ) _provider->close( this ); } //--------------------------------------------------------------------------- // // Report if the specified client has an open on us. // bool AppleGenericPCMultiATADriver::handleIsOpen( const IOService * client ) const { if ( client ) return _openNubs->containsObject( client ); else return ( _openNubs->getCount() != 0 ); } //--------------------------------------------------------------------------- // // PCI specific Multi-ATA controller driver. // #include #undef super #define super AppleGenericPCMultiATADriver OSDefineMetaClassAndStructors( AppleGenericPCMultiPCIATADriver, AppleGenericPCMultiATADriver ) IOService * AppleGenericPCMultiPCIATADriver::probe( IOService * provider, SInt32 * score ) { IOPCIDevice * pciDevice; // Let our superclass probe first. if ( super::probe( provider, score ) == 0 ) return 0; // Verify the provider type. pciDevice = OSDynamicCast( IOPCIDevice, provider ); if ( pciDevice == 0 ) return 0; // BIOS did not enable I/O space decoding. // For now assume the channel is disabled. if ( (pciDevice->configRead16( kIOPCIConfigCommand ) & kIOPCICommandIOSpace) == 0 ) { return 0; } // Perhaps a check to read class code register to make // sure it is an IDE controller? return this; }