Exemplo n.º 1
0
bool BrcmPatchRAM::start(IOService *provider)
{
    DebugLog("start\n");

    if (!super::start(provider))
        return false;
    
    // add interrupt source for delayed actions...
    IOWorkLoop* workLoop = getWorkLoop();
    if (!workLoop)
        return false;
    mWorkSource = IOInterruptEventSource::interruptEventSource(this, OSMemberFunctionCast(IOInterruptEventAction, this, &BrcmPatchRAM::processWorkQueue));
    if (!mWorkSource)
        return false;
    workLoop->addEventSource(mWorkSource);
    mWorkPending = 0;

    // add timer for firmware load in the case no re-probe after wake
    mTimer = IOTimerEventSource::timerEventSource(this, OSMemberFunctionCast(IOTimerEventSource::Action, this, &BrcmPatchRAM::onTimerEvent));
    if (!mTimer)
    {
        workLoop->removeEventSource(mWorkSource);
        mWorkSource->release();
        mWorkSource = NULL;
        return false;
    }
    workLoop->addEventSource(mTimer);

    // register for power state notifications
    PMinit();
    registerPowerDriver(this, myTwoStates, 2);
    provider->joinPMtree(this);
    
    return true;
}
bool RTL8139::initEventSources( IOService *provider )
{
	ELG( 0, 0, 'InES', "RTL8139::initEventSources - " );
    DEBUG_LOG( "initEventSources() ===>\n" );

	IOWorkLoop	*wl = getWorkLoop();
	if ( 0 == wl )
        return false;

	fTransmitQueue = getOutputQueue();
	if ( 0 == fTransmitQueue )
        return false;
	fTransmitQueue->setCapacity( kTransmitQueueCapacity );

		// Create an interrupt event source to handle hardware interrupts.

	interruptSrc = IOInterruptEventSource::interruptEventSource(
						this,
					   OSMemberFunctionCast(	IOInterruptEventAction,
												this,
												&RTL8139::interruptOccurred ),
					   provider );

	if ( !interruptSrc || (wl->addEventSource( interruptSrc ) != kIOReturnSuccess) )
		return false;

		// This is important. If the interrupt line is shared with other devices,
		// then the interrupt vector will be enabled only if all corresponding
		// interrupt event sources are enabled. To avoid masking interrupts for
		// other devices that are sharing the interrupt line, the event source
		// is enabled immediately. Hardware interrupt sources remain disabled.

    interruptSrc->enable();

		// Register a timer event source used as a watchdog timer:

	timerSrc = IOTimerEventSource::timerEventSource(
					this,
					OSMemberFunctionCast(	IOTimerEventSource::Action,
											this,
											&RTL8139::timeoutOccurred ) );

	if ( !timerSrc || (wl->addEventSource( timerSrc ) != kIOReturnSuccess) )
		return false;

		// Create a dictionary to hold IONetworkMedium objects:

	mediumDict = OSDictionary::withCapacity( 5 );
	if ( 0 == mediumDict )
		return false;

	DEBUG_LOG( "initEventSources() <===\n" );
	return true;
}/* end initEventSources */
Exemplo n.º 3
0
bool MACJackUserClient::
start(IOService* provider)
{
    WLLogInfo("MACJackUserClient::start()\n");
    
    if (!super::start(provider)) {
        WLLogErr("MACJackUserClient: start: super::start() failed\n");
        return false;
    }

    _provider = OSDynamicCast(MACJackDriver, provider);
    
    if (!_provider)
        return false;

    _wlCard = _provider->getWLCard();

    _userCommandGate = IOCommandGate::commandGate(this);
    if (!_userCommandGate) {
        WLLogErr("MACJackUserClient::start: Couldn't get CommandGate\n");
        return false;
    }

    IOWorkLoop* wl = _provider->getWorkLoop();
    if (wl->addEventSource(_userCommandGate) != kIOReturnSuccess) {
        WLLogErr("MACJackUserClient::start: Couldn't add gate to workloop\n");
        return false;
    }

    _packetQueue = _provider->getPacketQueue();
    
    return true;
}
Exemplo n.º 4
0
bool
org_virtualbox_VBoxGuest::setupVmmDevInterrupts(IOService *pProvider)
{
    IOWorkLoop *pWorkLoop = getWorkLoop();

    if (!pWorkLoop)
        return false;

    m_pInterruptSrc = IOFilterInterruptEventSource::filterInterruptEventSource(this,
                                                                               &deferredInterruptHandler,
                                                                               &directInterruptHandler,
                                                                               pProvider);

    if (kIOReturnSuccess != pWorkLoop->addEventSource(m_pInterruptSrc))
    {
        m_pInterruptSrc->disable();
        m_pInterruptSrc->release();
        m_pInterruptSrc = 0;
        return false;
    }

    m_pInterruptSrc->enable();

    return true;
}
Exemplo n.º 5
0
bool IOHIDEventSystemUserClient::start( IOService * provider )
{
    if( !super::start( provider )) {
      return( false);
    }
  
    owner = (IOHIDSystem *) provider;
    if (owner) {
        owner->retain();
    }
  
  
    IOWorkLoop * workLoop = getWorkLoop();
    if (workLoop == NULL)
    {
       return false;
    }
  
    commandGate = IOCommandGate::commandGate(this);
    if (commandGate == NULL)
    {
       return false;
    }
  
    if (workLoop->addEventSource(commandGate) != kIOReturnSuccess) {
       return false;
    }

    return( true );
}
bool BatteryTracker::start(IOService* provider)
{
    DEBUG_LOG("BatteryTracker::start: entering start\n");
    
    if (!IOService::start(provider))
    {
        IOLog("BatteryTracker: IOService::start failed!\n");
        return false;
    }
    
    IOWorkLoop* workLoop = getWorkLoop();
    if (!workLoop)
    {
        IOLog("BatteryTracker: getWorkLoop failed\n");
        return false;
    }
    m_pCmdGate = IOCommandGate::commandGate(this);
    if (!m_pCmdGate)
    {
        IOLog("BatteryTracker: IOCommandGate::commmandGate failed\n");
        return false;
    }
    workLoop->addEventSource(m_pCmdGate);
    
	DEBUG_LOG("ACPIBatteryManager: Version 1.52 starting BatteryTracker.\n");
    
    m_pBatteryList = OSArray::withCapacity(2);
    m_pLock = IORecursiveLockAlloc();
    
    registerService();
    
    return true;
}
//---------------------------------------------------------------------------
bool AgereET131x::initEventSources( IOService* provider )
{
	// Get a handle to our superclass' workloop.
	//
	IOWorkLoop* myWorkLoop = (IOWorkLoop *) getWorkLoop();
	if (myWorkLoop == NULL) {
		IOLog(" myWorkLoop is NULL.\n");
		return false;
	}
	
	transmitQueue = getOutputQueue();
	if (transmitQueue == NULL) {
		IOLog("getOutputQueue failed.\n");
		return false;
	}
	transmitQueue->setCapacity(NUM_TCB);
	
	interruptSource = IOFilterInterruptEventSource::filterInterruptEventSource( this, &AgereET131x::interruptHandler, &AgereET131x::interruptFilter, provider);
	
	if (!interruptSource ||
		(myWorkLoop->addEventSource(interruptSource) != kIOReturnSuccess)) {
		IOLog("workloop add eventsource interrupt source.\n");
		return false;
	}
	
	// This is important. If the interrupt line is shared with other devices,
	// then the interrupt vector will be enabled only if all corresponding
	// interrupt event sources are enabled. To avoid masking interrupts for
	// other devices that are sharing the interrupt line, the event source
	// is enabled immediately.
	interruptSource->enable();
	
	// Register a timer event source. This is used as a watchdog timer.
	//
	watchdogSource = IOTimerEventSource::timerEventSource(this, &AgereET131x::timeoutHandler );
	if (!watchdogSource || (myWorkLoop->addEventSource(watchdogSource) != kIOReturnSuccess)) {
		IOLog("watchdogSource create failed.\n");
		return false;
	}
	
	mediumDict = OSDictionary::withCapacity(MEDIUM_INDEX_COUNT + 1);
	if (mediumDict == NULL) {
		return false;
	}
	return true;
}
Exemplo n.º 8
0
bool BrcmPatchRAM::start(IOService *provider)
{
    DebugLog("start\n");

    if (!super::start(provider))
        return false;

    // place version/build info in ioreg properties RM,Build and RM,Version
    char buf[128];
    snprintf(buf, sizeof(buf), "%s %s", OSKextGetCurrentIdentifier(), OSKextGetCurrentVersionString());
    setProperty("RM,Version", buf);
#ifdef DEBUG
    setProperty("RM,Build", "Debug-" LOGNAME);
#else
    setProperty("RM,Build", "Release-" LOGNAME);
#endif

   // add interrupt source for delayed actions...
    IOWorkLoop* workLoop = getWorkLoop();
    if (!workLoop)
        return false;
    mWorkSource = IOInterruptEventSource::interruptEventSource(this, OSMemberFunctionCast(IOInterruptEventAction, this, &BrcmPatchRAM::processWorkQueue));
    if (!mWorkSource)
        return false;
    workLoop->addEventSource(mWorkSource);
    mWorkPending = 0;

    // add timer for firmware load in the case no re-probe after wake
    mTimer = IOTimerEventSource::timerEventSource(this, OSMemberFunctionCast(IOTimerEventSource::Action, this, &BrcmPatchRAM::onTimerEvent));
    if (!mTimer)
    {
        workLoop->removeEventSource(mWorkSource);
        mWorkSource->release();
        mWorkSource = NULL;
        return false;
    }
    workLoop->addEventSource(mTimer);

    // register for power state notifications
    PMinit();
    registerPowerDriver(this, myTwoStates, 2);
    provider->joinPMtree(this);
    
    return true;
}
Exemplo n.º 9
0
bool	AREngine::initHardware(IOService* inProvider)
{
	bool theAnswer = false;
	
	if(IOAudioEngine::initHardware(inProvider))
	{
		IOAudioSampleRate theInitialSampleRate = { 0, 0 };
		UInt32 theNumberChannels = 0;
		
		//	create the streams
		if(CreateStreams(&theInitialSampleRate, &theNumberChannels) && (theInitialSampleRate.whole != 0))
		{
			CreateControls(theNumberChannels);
			
			//	figure out how long each block is in microseconds
			mBlockTimeoutMicroseconds = 1000000 * mBlockSize / theInitialSampleRate.whole;
			
			setSampleRate(&theInitialSampleRate);
			
			// Set the number of sample frames in each buffer
			setNumSampleFramesPerBuffer(mBlockSize * mNumberBlocks);
			
			//	set up the timer
			IOWorkLoop* theWorkLoop = getWorkLoop();
			if(theWorkLoop != NULL)
			{
				mTimerEventSource = IOTimerEventSource::timerEventSource(this, TimerFired);
				if(mTimerEventSource != NULL)
				{
					theWorkLoop->addEventSource(mTimerEventSource);
					theAnswer = true;
				}
			}
			
			//	set the safety offset
			//	note that due to cache issues, it probably isn't wise to leave the safety offset at 0,
			//	we set it to 4 here, just to be safe.
			setSampleOffset(4);
			
			//	set up the time stamp generator
			mTimeStampGenerator.SetSampleRate(theInitialSampleRate.whole);
			mTimeStampGenerator.SetFramesPerRingBuffer(mBlockSize * mNumberBlocks);
			
			//	nate that the rate scalar is a 4.28 fixed point number
			//	this means that each incremnt is 1/2^28
			mTimeStampGenerator.SetRateScalar(1UL << 28);
			
			//	set the maximum jitter
//			AbsoluteTime theMaximumJitter = { 0, 0 };
//			nanoseconds_to_absolutetime(5ULL * 1000ULL, &theMaximumJitter);
//			mTimeStampGenerator.SetMaximumJitter(theMaximumJitter.lo);
		}
	}
	
	return theAnswer;
}
Exemplo n.º 10
0
// start is called after initWithTask as a result of the user process calling
// IOServiceOpen.
bool SoftU2FUserClient::start(IOService *provider) {
  IOLog("%s[%p]::%s(%p)\n", getName(), this, __FUNCTION__, provider);

  SoftU2FDevice *device = nullptr;
  IOWorkLoop *workLoop = nullptr;

  if (!OSDynamicCast(SoftU2FDriver, provider))
    goto fail_bad_provider;

  if (!super::start(provider))
    goto fail_super_start;

  device = SoftU2FDevice::newDevice();
  if (!device)
    goto fail_new_device;

  if (!device->attach(this))
    goto fail_device_attach;

  if (!device->start(this))
    goto fail_device_start;

  workLoop = getWorkLoop();
  if (!workLoop)
    goto fail_no_workloop;

  _commandGate = IOCommandGate::commandGate(this);
  if (!_commandGate)
    goto fail_new_cgate;

  if (workLoop->addEventSource(_commandGate) != kIOReturnSuccess)
    goto fail_add_event_source;

  // Our call to device->attach took a retain on the device when it was added to the registry.
  // That will be released when the device is detached from the registry.
  device->release();

  return true;

fail_add_event_source:
fail_new_cgate:
fail_no_workloop:
fail_device_start:
  device->detach(this);

fail_device_attach:
  device->release();

fail_new_device:
  stop(provider);

fail_super_start:
fail_bad_provider:
  return false;
}
Exemplo n.º 11
0
bool org_virtualbox_VBoxGuest::setupVmmDevInterrupts(IOService *pProvider)
{
    IOWorkLoop *pWorkLoop = getWorkLoop();
    if (!pWorkLoop)
        return false;

    m_pInterruptSrc = IOFilterInterruptEventSource::filterInterruptEventSource(this,
                                                                               &vgdrvDarwinDeferredIrqHandler,
                                                                               &vgdrvDarwinDirectIrqHandler,
                                                                               pProvider);
    IOReturn rc = pWorkLoop->addEventSource(m_pInterruptSrc);
    if (rc == kIOReturnSuccess)
    {
        m_pInterruptSrc->enable();
        return true;
    }

    m_pInterruptSrc->disable();
    m_pInterruptSrc->release();
    m_pInterruptSrc = NULL;
    return false;
}
Exemplo n.º 12
0
// Start up the driver
bool WirelessHIDDevice::handleStart(IOService *provider)
{
    WirelessDevice *device;
    IOWorkLoop *workloop;
    
    if (!super::handleStart(provider))
        goto fail;

    device = OSDynamicCast(WirelessDevice, provider);
    if (device == NULL)
        goto fail;
    
    serialTimerCount = 0;
    
	serialTimer = IOTimerEventSource::timerEventSource(this, ChatPadTimerActionWrapper);
	if (serialTimer == NULL)
	{
		IOLog("start - failed to create timer for chatpad\n");
		goto fail;
	}
    workloop = getWorkLoop();
	if ((workloop == NULL) || (workloop->addEventSource(serialTimer) != kIOReturnSuccess))
	{
		IOLog("start - failed to connect timer for chatpad\n");
		goto fail;
	}
    
    device->RegisterWatcher(this, _receivedData, NULL);
    
    device->SendPacket(weirdStart, sizeof(weirdStart));

    serialTimer->setTimeoutMS(1000);

    return true;
    
fail:
    return false;
}
bool AppleSmartBatteryManager::start(IOService *provider)
{
    DEBUG_LOG("AppleSmartBatteryManager::start: called\n");
    
    fProvider = OSDynamicCast(IOACPIPlatformDevice, provider);

    if (!fProvider || !super::start(provider)) {
        return false;
    }

    IOWorkLoop *wl = getWorkLoop();
    if (!wl) {
        return false;
    }

    // Join power management so that we can get a notification early during
    // wakeup to re-sample our battery data. We don't actually power manage
    // any devices.
	
	PMinit();
    registerPowerDriver(this, myTwoStates, 2);
    provider->joinPMtree(this);

    //rehabman: updated version
	IOLog("AppleSmartBatteryManager: Version 1.41 starting\n");

	int value = getPlatform()->numBatteriesSupported();
	DEBUG_LOG("AppleSmartBatteryManager: Battery Supported Count(s) %d.\n", value);

    // TODO: Create battery array to hold battery objects if more than one battery in the system
    
	if (value > 1) 
    { 
		if (kIOReturnSuccess == fProvider->evaluateInteger("_STA", &fBatterySTA)) {
			if (fBatterySTA & BATTERY_PRESENT) {
				goto populateBattery;
			} else {
				goto skipBattery;
			}
		}
	}

populateBattery:

	fBattery = AppleSmartBattery::smartBattery();

	if(!fBattery) 
		return false;

	fBattery->attach(this);

	fBattery->start(this);

    // Command gate for ACPIBatteryManager
    fManagerGate = IOCommandGate::commandGate(this);
    if (!fManagerGate) {
        return false;
    }
    wl->addEventSource(fManagerGate);

    // Command gate for ACPIBattery
    fBatteryGate = IOCommandGate::commandGate(fBattery);
    if (!fBatteryGate) {
        return false;
    }
    wl->addEventSource(fBatteryGate);

	fBattery->registerService(0);

skipBattery:

    this->setName("AppleSmartBatteryManager");
	this->registerService(0);

    return true;
}
bool IOFireWireSBP2LUN::attach(IOService *provider)
{
	IOReturn status = kIOReturnSuccess;
	
	// init fields
	fProviderTarget = NULL;
	fGate 			= NULL;
	fLUNumber 		= 0;
	fORBSet 		= NULL;
	fORBSetIterator = NULL;
	
    FWKLOG( ( "IOFireWireSBP2LUN<%p> : attach\n", this ) );
	
	//
	// attach to provider
	//
	
	if( status == kIOReturnSuccess )
	{
		fProviderTarget = OSDynamicCast( IOFireWireSBP2Target, provider );
		if( !fProviderTarget )
			status = kIOReturnError;
	}
	
	if( status == kIOReturnSuccess )
	{
		fProviderTarget->retain();
		if( !IOService::attach(provider) )
        	status = kIOReturnError;
	}

#if FWDIAGNOSTICS
	
	if( gDiagnostics_Symbol == NULL )
		gDiagnostics_Symbol = OSSymbol::withCString("SBP2 Diagnostics");

	fDiagnostics = IOFireWireSBP2Diagnostics::createDiagnostics();
	if( fDiagnostics )
	{
		setProperty( gDiagnostics_Symbol, fDiagnostics );
	}
	
#endif
	
	//
	// get lun number
	//
	
	if( status == kIOReturnSuccess )
	{
		OSObject *prop;

		// read lun number from registry		
		prop = getProperty( gIOUnit_Symbol );
		fLUNumber = ((OSNumber*)prop)->unsigned32BitValue();
	}
	
    //
    // create login set
    //
    
	if( status == kIOReturnSuccess )
	{
		fLoginSet = OSSet::withCapacity(1);
		if( fLoginSet == NULL )
			status = kIOReturnNoMemory;
	}
	
	if( status == kIOReturnSuccess )
	{
		if( fLoginSet )
            fLoginSetIterator = OSCollectionIterator::withCollection( fLoginSet );
	}
    
    
	//
	// create management orb set
	//
	
	if( status == kIOReturnSuccess )
	{
		fORBSet = OSSet::withCapacity(1);
		if( fORBSet == NULL )
			status = kIOReturnNoMemory;
	}
	
	if( status == kIOReturnSuccess )
	{
		if( fORBSet )
            fORBSetIterator = OSCollectionIterator::withCollection( fORBSet );
	}
	
	//
	// set up command gate
	//
	
	IOWorkLoop * workLoop = NULL;
	if( status == kIOReturnSuccess )
	{
		workLoop = getWorkLoop();
		if( !workLoop ) 
			status = kIOReturnNoResources;
	}
	
	if( status == kIOReturnSuccess )
	{
		fGate = IOCommandGate::commandGate( this );
		if( !fGate )
			status = kIOReturnNoMemory;
	}
	
	if( status == kIOReturnSuccess )
	{
		workLoop->retain();
		workLoop->addEventSource( fGate );
	}
	
    return (status == kIOReturnSuccess);
}
Exemplo n.º 15
0
// Class start
bool
VoodooPState::start(IOService * provider)
{
	if (!IOService::start(provider)) return false;

	// Printout banner
	InfoLog("%s %s (%s) %s %s [%s]",
			KextProductName,
			KextVersion,
			KextConfig,
			KextBuildDate,
			KextBuildTime,
			KextOSX);
	InfoLog("based on VoodooPower 1.2.3.");
	
	
	
	// Setup workloop and timer
	IOWorkLoop* WorkLoop = getWorkLoop();
	if (!WorkLoop) return false;
	TimerEventSource = 
	IOTimerEventSource::timerEventSource(this, OSMemberFunctionCast(IOTimerEventSource::Action,
																	this,
																	&VoodooPState::LoopTimerEvent));
	if (!TimerEventSource) return false;
	
	if (kIOReturnSuccess != WorkLoop->addEventSource(TimerEventSource)) {
		return false;
	}
	
	// Get a SimpleLock
	SimpleLock = IOSimpleLockAlloc();
	if (!SimpleLock) return false;
	
	// Publish the static characteristics
	OSDictionary * dictionary = OSDictionary::withCapacity(13);
	if (!dictionary) return false;
	OSArray * array = OSArray::withCapacity(PStateCount);
	if (!array) return false;
	setDictionaryNumber(keyCpuCoreTech, CpuCoreTech, dictionary);
	setDictionaryNumber(keyFrontSideBus, CpuFSB, dictionary);
	for (int i = 0; i < PStateCount; i++) {
		OSDictionary * pdictionary = OSDictionary::withCapacity(3);
		if (!pdictionary) return false;
		setDictionaryNumber(keyCurrentFrequency, PState[i].frequency, pdictionary);
		setDictionaryNumber(keyCurrentVoltage, PState[i].voltage, pdictionary);
		setDictionaryNumber(keyFid, PState[i].fid, pdictionary);
		setDictionaryNumber(keyDid, PState[i].did, pdictionary);
		setDictionaryNumber(keyVid, PState[i].vid, pdictionary);
		array->setObject(i, pdictionary);
		pdictionary->release();
	}
	setDictionaryArray(keyPStates, array, dictionary);
	setDictionaryString(keyProductName, KextProductName, dictionary);
	setDictionaryString(keyProductVersion, KextVersion, dictionary);
	setDictionaryString(keyBuildConfig, KextConfig, dictionary);
	setDictionaryString(keyBuildDate, KextBuildDate, dictionary);
	setDictionaryString(keyBuildTime, KextBuildTime, dictionary);
	setDictionaryNumber(keyTimerInterval, TimerInterval, dictionary);
	setProperty(keyCharacteristics, dictionary);

	array->release();
	dictionary->release();

	// set initial pstate
	Request = ColdStart ? (PStateCount-1) : 0;	// hot/cold start

	gPEClockFrequencyInfo.cpu_frequency_max_hz = VoodooFrequencyProc(this,&PState[0]) * Mega;
	gPEClockFrequencyInfo.cpu_frequency_min_hz = VoodooFrequencyProc(this,&PState[PStateCount-1]) * Mega;

	LoopTimerEvent();
	
	// Finalize and kick off the loop
	this->registerService(0);
	Ready = true;

	return true;
}
Exemplo n.º 16
0
bool Xbox360Peripheral::start(IOService *provider)
{
    const IOUSBConfigurationDescriptor *cd;
    IOUSBFindInterfaceRequest intf;
    IOUSBFindEndpointRequest pipe;
    XBOX360_OUT_LED led;
    IOWorkLoop *workloop = NULL;
    /*
     * Xbox One controller init packets.
     * The Rock Candy Xbox One controller requires more than just 0x05
     * Minimum required packets unknown.
     */
    UInt8 xoneInitFirst[] = { 0x02, 0x20, 0x01, 0x1C, 0x7E, 0xED, 0x8B, 0x11, 0x0F, 0xA8, 0x00, 0x00, 0x5E, 0x04, 0xD1, 0x02, 0x01, 0x00, 0x01, 0x00, 0x17, 0x01, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00 };
    UInt8 xoneInitSecond[] = { 0x05, 0x20, 0x00, 0x09, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x53 };
    UInt8 xoneInitThird[] = { 0x05, 0x20, 0x01, 0x01, 0x00 };
    UInt8 xoneInitFourth[] = { 0x0A, 0x20, 0x02, 0x03, 0x00, 0x01, 0x14 };
    
    if (!super::start(provider))
		return false;
    // Get device
    device=OSDynamicCast(IOUSBDevice,provider);
    if(device==NULL) {
        IOLog("start - invalid provider\n");
        goto fail;
    }
    // Check for configurations
    if(device->GetNumConfigurations()<1) {
        device=NULL;
        IOLog("start - device has no configurations!\n");
        goto fail;
    }
    // Set configuration
    cd=device->GetFullConfigurationDescriptor(0);
    if(cd==NULL) {
        device=NULL;
        IOLog("start - couldn't get configuration descriptor\n");
        goto fail;
    }
    // Open
    if(!device->open(this)) {
        device=NULL;
        IOLog("start - unable to open device\n");
        goto fail;
    }
    if(device->SetConfiguration(this,cd->bConfigurationValue,true)!=kIOReturnSuccess) {
        IOLog("start - unable to set configuration\n");
        goto fail;
    }
    // Get release
    {
        UInt16 release = device->GetDeviceRelease();
        switch (release) {
            default:
                IOLog("Unknown device release %.4x\n", release);
                // fall through
            case 0x0110:
                chatpadInit[0] = 0x01;
                chatpadInit[1] = 0x02;
                break;
            case 0x0114:
                chatpadInit[0] = 0x09;
                chatpadInit[1] = 0x00;
                break;
        }
    }
    // Find correct interface
    controllerType = Xbox360;
    intf.bInterfaceClass=kIOUSBFindInterfaceDontCare;
    intf.bInterfaceSubClass=93;
    intf.bInterfaceProtocol=1;
    intf.bAlternateSetting=kIOUSBFindInterfaceDontCare;
    interface=device->FindNextInterface(NULL,&intf);
    if(interface==NULL) {
        // Find correct interface, Xbox original
        intf.bInterfaceClass=kIOUSBFindInterfaceDontCare;
        intf.bInterfaceSubClass=66;
        intf.bInterfaceProtocol=0;
        intf.bAlternateSetting=kIOUSBFindInterfaceDontCare;
        interface=device->FindNextInterface(NULL,&intf);
        if(interface==NULL) {
            // Find correct interface, Xbox One
            intf.bInterfaceClass=255;
            intf.bInterfaceSubClass=71;
            intf.bInterfaceProtocol=208;
            intf.bAlternateSetting=kIOUSBFindInterfaceDontCare;
            interface=device->FindNextInterface(NULL, &intf);
            if(interface==NULL)
            {
                IOLog("start - unable to find the interface\n");
                goto fail;
            }
            controllerType = XboxOne;
            goto interfacefound;
        }
        controllerType = XboxOriginal;
        goto interfacefound;
    }
interfacefound:
    interface->open(this);
    // Find pipes
    pipe.direction=kUSBIn;
    pipe.interval=0;
    pipe.type=kUSBInterrupt;
    pipe.maxPacketSize=0;
    inPipe=interface->FindNextPipe(NULL,&pipe);
    if(inPipe==NULL) {
        IOLog("start - unable to find in pipe\n");
        goto fail;
    }
    inPipe->retain();
    pipe.direction=kUSBOut;
    outPipe=interface->FindNextPipe(NULL,&pipe);
    if(outPipe==NULL) {
        IOLog("start - unable to find out pipe\n");
        goto fail;
    }
    outPipe->retain();
    // Get a buffer
    inBuffer=IOBufferMemoryDescriptor::inTaskWithOptions(kernel_task,0,GetMaxPacketSize(inPipe));
    if(inBuffer==NULL) {
        IOLog("start - failed to allocate input buffer\n");
        goto fail;
    }
	// Find chatpad interface
	intf.bInterfaceClass = kIOUSBFindInterfaceDontCare;
	intf.bInterfaceSubClass = 93;
	intf.bInterfaceProtocol = 2;
	intf.bAlternateSetting = kIOUSBFindInterfaceDontCare;
	serialIn = device->FindNextInterface(NULL, &intf);
	if (serialIn == NULL) {
		IOLog("start - unable to find chatpad interface\n");
        goto nochat;
    }
	serialIn->open(this);
	// Find chatpad pipe
	pipe.direction = kUSBIn;
	pipe.interval = 0;
	pipe.type = kUSBInterrupt;
	pipe.maxPacketSize = 0;
	serialInPipe = serialIn->FindNextPipe(NULL, &pipe);
	if (serialInPipe == NULL)
	{
		IOLog("start - unable to find chatpad in pipe\n");
		goto fail;
	}
	serialInPipe->retain();
	// Get a buffer for the chatpad
	serialInBuffer = IOBufferMemoryDescriptor::inTaskWithOptions(kernel_task, 0, GetMaxPacketSize(serialInPipe));
	if (serialInBuffer == NULL)
	{
		IOLog("start - failed to allocate input buffer for chatpad\n");
		goto fail;
	}
	// Create timer for chatpad
	serialTimer = IOTimerEventSource::timerEventSource(this, ChatPadTimerActionWrapper);
	if (serialTimer == NULL)
	{
		IOLog("start - failed to create timer for chatpad\n");
		goto fail;
	}
    workloop = getWorkLoop();
	if ((workloop == NULL) || (workloop->addEventSource(serialTimer) != kIOReturnSuccess))
	{
		IOLog("start - failed to connect timer for chatpad\n");
		goto fail;
	}
	// Configure ChatPad
	// Send 'configuration'
	SendInit(0xa30c, 0x4423);
	SendInit(0x2344, 0x7f03);
	SendInit(0x5839, 0x6832);
	// Set 'switch'
    if ((!SendSwitch(false)) || (!SendSwitch(true)) || (!SendSwitch(false))) {
        // Commenting goto fail fixes the driver for the Hori Real Arcade Pro EX
        //goto fail;
	}
	// Begin toggle
	serialHeard = false;
	serialActive = false;
	serialToggle = false;
	serialResetCount = 0;
	serialTimerState = tsToggle;
	serialTimer->setTimeoutMS(1000);
    // Begin reading
    if (!QueueSerialRead())
        goto fail;
nochat:
    if (!QueueRead())
		goto fail;
    if (controllerType == XboxOne) {
        QueueWrite(&xoneInitFirst, sizeof(xoneInitFirst));
        QueueWrite(&xoneInitSecond, sizeof(xoneInitSecond));
        QueueWrite(&xoneInitThird, sizeof(xoneInitThird));
        QueueWrite(&xoneInitFourth, sizeof(xoneInitFourth));
    } else {
        // Disable LED
        Xbox360_Prepare(led,outLed);
        led.pattern=ledOff;
        QueueWrite(&led,sizeof(led));
    }
    
    // Done
	PadConnect();
	registerService();
    return true;
fail:
    ReleaseAll();
    return false;
}
Exemplo n.º 17
0
bool
MolEnet::start( IOService * provider )
{
	IOPhysicalAddress tx_phys, rx_phys;
	IOPhysicalAddress tx_of_phys, rx_of_phys;
	int i, result;

	if( !super::start(provider) )
		return false;

	if( OSI_Enet2Open() ) {
		is_open = 1;
		return false;
	}
	
	//transmitQueue = OSDynamicCast( IOGatedOutputQueue, getOutputQueue() );
	transmitQueue = OSDynamicCast( IOBasicOutputQueue, getOutputQueue() );
	if( !transmitQueue ) {
		printm("MolEnet: output queue initialization failed\n");
		return false;
	}
	transmitQueue->retain();

	// Allocate a IOMbufBigMemoryCursor instance. Currently, the maximum
	// number of segments is set to 2. The maximum length for each segment
	// is set to the maximum ethernet frame size (plus padding).

	txMBufCursor = IOMbufBigMemoryCursor::withSpecification( NETWORK_BUFSIZE, 2 );
	rxMBufCursor = IOMbufBigMemoryCursor::withSpecification( NETWORK_BUFSIZE, 2 );
	if( !txMBufCursor || !rxMBufCursor ) {
		printm("MolEnet: IOMbufBigMemoryCursor allocation failure\n");
		return false;
	}

	// Get a reference to the IOWorkLoop in our superclass.
	IOWorkLoop * myWorkLoop = getWorkLoop();
	assert(myWorkLoop);

	// Allocate a IOInterruptEventSources.
	_irq = IOInterruptEventSource::interruptEventSource( this, 
				     (IOInterruptEventAction)&MolEnet::rxIRQ, provider, 0);
	
        if( !_irq || (myWorkLoop->addEventSource(_irq) != kIOReturnSuccess )) {
		printm("MolEnet: _irq init failure\n");
		return false;
	}

	// Allocate the ring descriptors
	rx_ring = (enet2_ring_t*)IOMallocContiguous( 2 * RX_NUM_EL * sizeof(enet2_ring_t), 
						     sizeof(enet2_ring_t), &rx_phys );
	tx_ring = (enet2_ring_t*)IOMallocContiguous( 2 * TX_NUM_EL * sizeof(enet2_ring_t),
						     sizeof(enet2_ring_t), &tx_phys );		
	if( !rx_ring || !tx_ring )
		return false;

	rx_of_ring = rx_ring + RX_NUM_EL;
	tx_of_ring = tx_ring + TX_NUM_EL;
	rx_of_phys = rx_phys + sizeof(enet2_ring_t) * RX_NUM_EL;
	tx_of_phys = tx_phys + sizeof(enet2_ring_t) * TX_NUM_EL;

	// Allocate receive buffers
	for( i=0; i<RX_NUM_EL; i++ ) {
		if( !(rxMBuf[i]=allocatePacket( NETWORK_BUFSIZE )) ) {
			printm("MolEnet: packet allocation failed\n");
			return false;
		}
		// reserve 2 bytes before the actual packet
		rxMBuf[i]->m_data += 2;
		rxMBuf[i]->m_len -= 2;
	}

	OSI_Enet2Cntrl( kEnet2Reset );
	result = OSI_Enet2RingSetup( kEnet2SetupRXRing, rx_phys, RX_NUM_EL )
		|| OSI_Enet2RingSetup( kEnet2SetupTXRing, tx_phys, TX_NUM_EL )
		|| OSI_Enet2RingSetup( kEnet2SetupRXOverflowRing, rx_of_phys, RX_NUM_EL )
		|| OSI_Enet2RingSetup( kEnet2SetupTXOverflowRing, tx_of_phys, TX_NUM_EL );
	if( result )
		return false;

	if( !resetAndEnable(false) )
		return false;

	// Create a table of supported media types.
	if( !createMediumTables() )
		return false;

	// Attach an IOEthernetInterface client.
	if( !attachInterface( (IONetworkInterface**)&networkInterface, false ) )
		return false;

	// Ready to service interface requests.
	networkInterface->registerService();

	printm("Ethernet driver 1.1\n");
	return true;
}
bool ACPIBacklightPanel::start( IOService * provider )
{
    DbgLog("%s::%s()\n", this->getName(),__FUNCTION__);

#if 0
    if (!provider)
        return false;

    _provider = provider;
    _provider->retain();
#endif

    _lock = IORecursiveLockAlloc();
    if (!_lock)
        return false;
    
    findDevices(provider);

    getDeviceControl();
    hasSaveMethod = hasSAVEMethod(backLightDevice);
    min = 0;
    max = setupIndexedLevels();
    if (min == max)
    {
        IOLog("ACPIBacklight: setupIndexedLevels failed (min==max)... aborting");
        return false;
    }

    // add interrupt source for delayed actions...
    _workSource = IOInterruptEventSource::interruptEventSource(this, OSMemberFunctionCast(IOInterruptEventAction, this, &ACPIBacklightPanel::processWorkQueue));
    if (!_workSource)
        return false;
    IOWorkLoop* workLoop = getWorkLoop();
    if (!workLoop)
    {
        _workSource->release();
        _workSource = NULL;
        return false;
    }
    workLoop->addEventSource(_workSource);
    _workPending = 0;

    // add timer for smooth fade ins
    if (_extended && !(_options & kDisableSmooth))
    {
        _smoothTimer = IOTimerEventSource::timerEventSource(this, OSMemberFunctionCast(IOTimerEventSource::Action, this, &ACPIBacklightPanel::onSmoothTimer));
        if (_smoothTimer)
            workLoop->addEventSource(_smoothTimer);
    }

    _cmdGate = IOCommandGate::commandGate(this);
    if (_cmdGate)
        workLoop->addEventSource(_cmdGate);

    // initialize from properties
    OSDictionary* dict = getPropertyTable();
    setPropertiesGated(dict);

    // write current values from smoothData
    for (int i = 0; i < countof(smoothData); i++)
    {
        char buf[kSmoothBufSize];
        snprintf(buf, sizeof(buf), kSmoothDelta, i);
        setProperty(buf, smoothData[i].delta, 32);
        snprintf(buf, sizeof(buf), kSmoothStep, i);
        setProperty(buf, smoothData[i].step, 32);
        snprintf(buf, sizeof(buf), kSmoothTimeout, i);
        setProperty(buf, smoothData[i].timeout, 32);
    }
#ifdef DEBUG
    setProperty("CycleTest", 1, 32);
    setProperty("KLVX", 1, 32);
#endif

    // make the service available for clients like 'ioio'...
    registerService();

    // load and set default brightness level
    UInt32 value = loadFromNVRAM();
    DbgLog("%s: loadFromNVRAM returns %d\n", this->getName(), value);

    // registerService above must be called before we wait for the BacklightHandler
    if (useBacklightHandler())
    {
        DbgLog("%s: Waiting for BacklightHandler\n", this->getName());
        waitForService(serviceMatching("BacklightHandler"));
    }

    // after backlight handler is in place, now we can manipulate backlight level
    UInt32 current = queryACPICurentBrightnessLevel();
    setProperty(kRawBrightness, current, 32);
#if 0
    _provider->setProperty("AppleBacklightAtBoot", current, 32);
    _provider->setProperty("AppleMaxBrightness", BCLlevels[BCLlevelsCount-1], 32);
#endif

    _committed_value = _value = _from_value = levelForValue(current);
    DbgLog("%s: current brightness: %d (%d)\n", this->getName(), _from_value, current);
    if (-1 != value)
    {
        _committed_value = value;
        DbgLog("%s: setting to value from nvram %d\n", this->getName(), value);
        setBrightnessLevelSmooth(value);
    }
    _saved_value = _committed_value;

    DbgLog("%s: min = %u, max = %u\n", this->getName(), min, max);

    // announce version
    extern kmod_info_t kmod_info;
    IOLog("ACPIBacklight: Version %s starting on OS X Darwin %d.%d.\n", kmod_info.version, version_major, version_minor);

    // place version/build info in ioreg properties RM,Build and RM,Version
    char buf[128];
    snprintf(buf, sizeof(buf), "%s %s", kmod_info.name, kmod_info.version);
    setProperty("RM,Version", buf);
#ifdef DEBUG
    setProperty("RM,Build", "Debug-" LOGNAME);
#else
    setProperty("RM,Build", "Release-" LOGNAME);
#endif

	return true;
}
bool AppleSmartBatteryManager::start(IOService *provider)
{
    IOCommandGate * gate;
    IOWorkLoop *    wl;

    if(!super::start(provider)) {
        return false;
    }

    fProvider = OSDynamicCast(IOSMBusController, provider);
    if(!fProvider) {
        return false;
    }
    
    const OSSymbol *ucClassName = 
            OSSymbol::withCStringNoCopy("AppleSmartBatteryManagerUserClient");
    setProperty(gIOUserClientClassKey, (OSObject *) ucClassName);
    ucClassName->release();
    
    wl = getWorkLoop();
    if (!wl) {
        return false;
    }

    // Join power management so that we can get a notification early during
    // wakeup to re-sample our battery data. We don't actually power manage
    // any devices.
    PMinit();
    registerPowerDriver(this, myTwoStates, 2);
    provider->joinPMtree(this);
        
    fBattery = AppleSmartBattery::smartBattery();

    if(!fBattery) return false;
    
    fBattery->attach(this);

    fBattery->start(this);

    // Command gate for SmartBatteryManager
    fManagerGate = IOCommandGate::commandGate(this);
    if (!fManagerGate) {
        return false;
    }
    wl->addEventSource(fManagerGate);
    
    // Command gate for SmartBattery
    gate = IOCommandGate::commandGate(fBattery);
    if (!gate) {
        return false;
    }
    wl->addEventSource(gate);
    fBatteryGate = gate;      // enable messages

    // Track UserClient exclusive access to smartbattery
    fExclusiveUserClient = false;

    fBattery->registerService(0);

    this->registerService(0);

    return true;
}
Exemplo n.º 20
0
bool CLASS::allocateSupportObjects( IOService * provider )
{
    fTransmitQueue = OSDynamicCast(IOOutputQueue, getOutputQueue());
    if (fTransmitQueue == 0)
        return false;

    fKDPQueue = IOPacketQueue::withCapacity(~0);
    if (!fKDPQueue)
        return false;

    // Allocate two Mbuf Cursors. One dedicated for transmit and
    // the other for receive. NOTE types are different.

    fRxMbufCursor = IOMbufLittleMemoryCursor::withSpecification(
                    kRxMaxBufferSize, 1);

    fTxMbufCursor = IOMbufNaturalMemoryCursor::withSpecification(
                    kTxMaxBufferSize, 1);

    if (!fRxMbufCursor || !fTxMbufCursor)
    {
        ERROR_LOG("%s: mbuf cursor allocation error\n", getName());
        return false;
    }

    IOWorkLoop * workLoop = (IOWorkLoop *) getWorkLoop();
    if (!workLoop)
    {
        ERROR_LOG("%s: no work loop\n", getName());
        return false;
    }

    // Create an interrupt event source to dispatch interrupts.
    // FIXME: Use interrupt filter event source

    fInterruptSource = IOInterruptEventSource::interruptEventSource(
                       this,
                       &AppleDP83816Ethernet::interruptHandler,
                       provider);

    if (!fInterruptSource ||
        (workLoop->addEventSource(fInterruptSource) != kIOReturnSuccess))
    {
        ERROR_LOG("%s: IOInterruptEventSource error\n", getName());
        return false;
    }

    fWatchdogTimer = IOTimerEventSource::timerEventSource(
                     this,
                     &AppleDP83816Ethernet::timeoutHandler);
    if (!fWatchdogTimer ||
        (workLoop->addEventSource(fWatchdogTimer) != kIOReturnSuccess))
    {
        ERROR_LOG("%s: IOTimerEventSource error\n", getName());
        return false;
    }

    // Very important. If the interrupt line is shared with other devices,
    // then the interrupt vector will be enabled only if all corresponding
    // interrupt event sources are enabled. To avoid masking interrupts for
    // other devices that are sharing the interrupt line, the event source
    // is enabled immediately.

    fInterruptSource->enable();

    return true;
}
bool
SATSMARTUserClient::start ( IOService * provider )
{
    IOWorkLoop *    workLoop = NULL;
    DEBUG_LOG("%s[%p]::%s\n", getClassName(), this, __FUNCTION__);
    
    if ( fProvider != NULL )
    {
        
        ERROR_LOG ( "fProvider != NULL, returning false\n" );
        return false;
        
    }
    
    fProvider = OSDynamicCast ( IOSATServices, provider );
    if ( fProvider == NULL )
    {
        
        ERROR_LOG ( "Provider not IOSATServices\n" );
        return false;
        
    }
    
    if ( !super::start ( provider ) )
    {
        
        ERROR_LOG ( "super rejected provider in start\n" );
        return false;
        
    }
    
    fCommandGate = IOCommandGate::commandGate ( this );
    if ( fCommandGate == NULL )
    {
        
        ERROR_LOG ( "Command gate creation failed\n" );
        return false;
        
    }
    
    workLoop = getWorkLoop ( );
    if ( workLoop == NULL )
    {
        
        ERROR_LOG ( "workLoop == NULL\n" );
        fCommandGate->release ( );
        fCommandGate = NULL;
        return false;
        
    }
    
    workLoop->addEventSource ( fCommandGate );
    
    if ( !fProvider->open ( this, kIOATASMARTUserClientAccessMask, 0 ) )
    {
        
        ERROR_LOG ( "Open failed\n" );
        fCommandGate->release ( );
        fCommandGate = NULL;
        return false;
        
    }
    
    fWorkLoop = workLoop;
    
    // Yes, we found an object to use as our interface
    return true;
    
}
bool ApplePS2Mouse::start(IOService * provider)
{ 
  DEBUG_LOG("%s::start called\n", getName());
    
  //
  // The driver has been instructed to start. This is called after a
  // successful probe and match.
  //

  if (!super::start(provider))
      return false;

  //
  // Maintain a pointer to and retain the provider object.
  //

  _device = (ApplePS2MouseDevice *)provider;
  _device->retain();

  //
  // Setup workloop with command gate for thread syncronization...
  //
  IOWorkLoop* pWorkLoop = getWorkLoop();
  _cmdGate = IOCommandGate::commandGate(this);
  if (!pWorkLoop || !_cmdGate)
  {
    _device->release();
    return false;
  }
  pWorkLoop->addEventSource(_cmdGate);
    
  //
  // Setup button timer event source
  //
  _buttonTimer = IOTimerEventSource::timerEventSource(this, OSMemberFunctionCast(IOTimerEventSource::Action, this, &ApplePS2Mouse::onButtonTimer));
  if (_buttonTimer)
      pWorkLoop->addEventSource(_buttonTimer);
    
  //
  // Lock the controller during initialization
  //
   
  _device->lock();
    
  //
  // Reset and enable the mouse.
  //

  resetMouse();

  //
  // Install our driver's interrupt handler, for asynchronous data delivery.
  //

  _device->installInterruptAction(this,
    OSMemberFunctionCast(PS2InterruptAction, this, &ApplePS2Mouse::interruptOccurred),
    OSMemberFunctionCast(PS2PacketAction, this, &ApplePS2Mouse::packetReady));
  _interruptHandlerInstalled = true;

  // now safe to allow other threads
  _device->unlock();
    
  //
  // Install our power control handler.
  //

  _device->installPowerControlAction( this,OSMemberFunctionCast
           (PS2PowerControlAction,this, &ApplePS2Mouse::setDevicePowerState) );
  _powerControlHandlerInstalled = true;

  //
  // Install message hook for keyboard to trackpad communication
  //
  
  if (actliketrackpad)
  {
    _device->installMessageAction( this,
                                  OSMemberFunctionCast(PS2MessageAction, this, &ApplePS2Mouse::receiveMessage));
    _messageHandlerInstalled = true;
  }
    
  return true;
}
Exemplo n.º 23
0
bool IrDAComm::init(AppleIrDASerial *driver, AppleIrDA *appleirda)
{
    IOReturn rc;
    IOWorkLoop *workloop;
	
    XTRACE(kLogInit, 0, this);
#if (hasTracing > 0)
    DebugLog("log info at 0x%lx", (uintptr_t)IrDALogGetInfo());
#endif
    require(driver, Fail);

    fState = kIrDACommStateStart;
    fDriver = driver;
    //fTimerSrc = nil;
    fTimer = nil;
    fQoS = nil;
    fIrDA = nil;
    fIrComm = nil;
    fWriteBusy = false;
    fGate = nil;
    fStartCounter = 0;          // counter for initial connection attempts
    fStop_thread = nil;

    if (!super::init())
	return false;
    
    fQoS = driver->GetIrDAQoS();
    require(fQoS, Fail);
    
    workloop = fDriver->getWorkLoop();
    require(workloop, Fail);
    
    fStop_thread = thread_call_allocate(stop_thread, this);
    require(fStop_thread, Fail);
    
    fIrDA = TIrGlue::tIrGlue(fDriver, appleirda, workloop, fQoS);       // create irda stack
    require(fIrDA, Fail);
    
    fIrComm = IrComm::irComm(fIrDA, this);                                          // create an ircomm object
    require(fIrComm, Fail);
	
    fGate = IOCommandGate::commandGate(this, 0);    // create a new command gate for our access to IrDA
    require(fGate, Fail);
    
    rc = workloop->addEventSource(fGate);           // add it to the usb workloop
    require(rc == kIOReturnSuccess, Fail);

    fTimer = CTimer::cTimer(workloop, this, &IrDAComm::TimerRoutine);
    require(fTimer, Fail);
    
    fTimer->StartTimer(100, 0);                     // 100ms delay after init and then startup

    //fTimerSrc = IOTimerEventSource::timerEventSource ( driver, &::timeoutRoutine);    // create an io timer
    //require(fTimerSrc, Fail);
    //
    //rc = workloop->addEventSource(fTimerSrc);
    //require(rc == kIOReturnSuccess, Fail);
    //      
    //rc = fTimerSrc->setTimeoutMS(100);            // 100 ms delay after init'ing
    //require(rc == kIOReturnSuccess, Fail);

    return true;

Fail:
    return false;
    
} /* end Initialize */
bool
IOATABlockStorageDriver::start ( IOService * provider )
{
	
	IOReturn		theErr				= kIOReturnSuccess;
	IOWorkLoop *	workLoop			= NULL;
	OSNumber *		numCommandObjects 	= NULL;
	
	STATUS_LOG ( ( "IOATABlockStorageDriver::start entering.\n" ) );
	
	fATADevice 					= NULL;
	fCommandPool				= NULL;
	fATAUnitID					= kATAInvalidDeviceID;
	fATADeviceType				= kUnknownATADeviceType;
	fATASocketType				= kUnknownSocket;
	fAPMLevel					= 0xFF;
	
	// First call start() in our superclass
	if ( super::start ( provider ) == false )
		return false;
	
	// Cache our provider
	fATADevice = OSDynamicCast ( IOATADevice, provider );
	if ( fATADevice == NULL )
		return false;
		
	// Find out if the device type is ATA
	if ( fATADevice->getDeviceType ( ) != reportATADeviceType ( ) )
	{
		
		ERROR_LOG ( ( "IOATABlockStorageDriver::start exiting, not an ATA device.\n" ) );
		return false;
		
	}
	
	reserved = ( ExpansionData * ) IOMalloc ( sizeof ( ExpansionData ) );
	bzero ( reserved, sizeof ( ExpansionData ) );
	
	STATUS_LOG ( ( "IOATABlockStorageDriver::start opening device.\n" ) );
	
	if ( fATADevice->open ( this ) == false )
		return false;
	
	// Cache the drive unit number (master/slave assignment).
	fATAUnitID 	= fATADevice->getUnitID ( );
	fATADeviceType = fATADevice->getDeviceType ( );

	STATUS_LOG ( ( "IOATABlockStorageDriver::start fATAUnitID = %d.\n", ( UInt8 ) fATAUnitID ) );
	STATUS_LOG ( ( "IOATABlockStorageDriver::start fATADeviceType is %d\n", ( UInt8 ) fATADeviceType ) );
		
	bzero ( fDeviceIdentifyData, 512 );

	fDeviceIdentifyBuffer = IOMemoryDescriptor::withAddress ( ( void * ) fDeviceIdentifyData,
																512,
																kIODirectionIn );
	
	assert ( fDeviceIdentifyBuffer != NULL );
	
	fDeviceIdentifyBuffer->prepare ( );
	
	numCommandObjects 	= OSDynamicCast ( OSNumber, getProperty ( "IOCommandPoolSize" ) );
	fNumCommandObjects 	= numCommandObjects->unsigned32BitValue ( );
	
	STATUS_LOG ( ( "IOATABlockStorageDriver::start fNumCommandObjects = %ld\n", fNumCommandObjects ) );
	
	// Create an IOCommandGate (for power management support) and attach
	// this event source to the provider's workloop
	fCommandGate = IOCommandGate::commandGate ( this );
	assert ( fCommandGate != NULL );
	
	workLoop = getWorkLoop ( );
	assert ( workLoop != NULL );
	
	theErr = workLoop->addEventSource ( fCommandGate );
	assert ( theErr == kIOReturnSuccess );
	
	fCommandPool = IOCommandPool::commandPool ( this, workLoop, fNumCommandObjects );
	assert ( fCommandPool != NULL );
	
	allocateATACommandObjects ( );
	
	// Inspect the provider
	if ( inspectDevice ( fATADevice ) == false )
		return false;
	
	fCurrentPowerState 			= kIOATAPowerStateActive;
	fProposedPowerState			= kIOATAPowerStateActive;
	fNumCommandsOutstanding		= 0;
	fPowerTransitionInProgress 	= false;
	
	fPowerManagementThread = thread_call_allocate (
					( thread_call_func_t ) IOATABlockStorageDriver::sPowerManagement,
					( thread_call_param_t ) this );
					
	if ( fPowerManagementThread == NULL )
	{
		
		ERROR_LOG ( ( "thread allocation failed.\n" ) );
		return false;
		
	}
		
	// A policy-maker must make these calls to join the PM tree,
	// and to initialize its state
	PMinit ( );								// initialize power management variables
	setIdleTimerPeriod ( k5Minutes );		// 5 minute inactivity timer
	provider->joinPMtree ( this );  		// join power management tree
	makeUsable ( );
	fPowerManagementInitialized = true;
	initForPM ( );
	
	return ( createNub ( provider ) );
	
}