示例#1
0
文件: at_main.cpp 项目: aelam/iats
int 
at_sw_init(at_adapter *adapter)
{
    at_hw *hw = &adapter->hw;
    IOPCIDevice *pdev = adapter->pdev;

    /* PCI config space info */

    hw->vendor_id = pdev->configRead16(kIOPCIConfigVendorID);
    hw->device_id = pdev->configRead16(kIOPCIConfigDeviceID);
    hw->subsystem_vendor_id = pdev->configRead16(kIOPCIConfigSubSystemVendorID);
    hw->subsystem_id = pdev->configRead16(kIOPCIConfigSubSystemID);

	hw->revision_id = pdev->configRead8(kIOPCIConfigRevisionID);
	hw->pci_cmd_word = pdev->configRead16(kIOPCIConfigCommand);

    adapter->wol = 0;

    adapter->ict = 50000;  // 100ms
    
    adapter->link_speed = SPEED_0;   // hardware init
    adapter->link_duplex = FULL_DUPLEX; //

  
    hw->phy_configured = false;
    hw->preamble_len = 7;
    hw->ipgt = 0x60;
    hw->min_ifg = 0x50;
    hw->ipgr1 = 0x40;
    hw->ipgr2 = 0x60;
    hw->retry_buf = 2;
    
    hw->max_retry = 0xf;
    hw->lcol = 0x37;
    hw->jam_ipg = 7;
    
    hw->fc_rxd_hi = 0;
    hw->fc_rxd_lo = 0; 
    
    hw->max_frame_size = 1500;
    
    atomic_set(&adapter->irq_sem, 1);
    adapter->stats_lock = IOSimpleLockAlloc();
    adapter->tx_lock = IOSimpleLockAlloc();
    

	
    return 0;
}
示例#2
0
bool
testthreadcall::start( IOService * provider )
{
	boolean_t ret;
	uint64_t deadline;
    
    IOLog("%s\n", __PRETTY_FUNCTION__);
    
    if (!super::start(provider)) {
        return false;
    }
    
    IOLog("Attempting thread_call_allocate\n");
	tcall = thread_call_allocate(thread_call_test_func, this);
    IOLog("thread_call_t %p\n", tcall);
    
	tlock = IOSimpleLockAlloc();
	IOLog("tlock %p\n", tlock);
	
	clock_interval_to_deadline(5, NSEC_PER_SEC, &deadline);
	IOLog("%d sec deadline is %llu\n", 5, deadline);
	
	ret = thread_call_enter_delayed(tcall, deadline);
	
    return true;
}
示例#3
0
bool iTCOWatchdog::init (OSDictionary* dict)
{
    OSNumber *nkey;
    OSBoolean *bkey;
    bool res;
    
    //DbgPrint(drvid, "init\n");
    res = super::init(dict);
    
    Timeout = DEFAULT_TIMEOUT;
    SelfFeeding = false;
    WorkaroundBug = false;
    
    if ((conf = OSDynamicCast(OSDictionary, getProperty("Settings"))) &&
        (nkey = OSDynamicCast(OSNumber, conf->getObject("Timeout"))))
        Timeout = nkey->unsigned32BitValue();
    if (conf && (bkey = OSDynamicCast(OSBoolean, conf->getObject("SelfFeeding"))))
        SelfFeeding = bkey->isTrue();
    if (conf && (bkey = OSDynamicCast(OSBoolean, conf->getObject("UnsafeWorkaroundBIOSBug"))))
        WorkaroundBug = bkey->isTrue();
    
    first_run = true;
    is_active = SMIWereEnabled = false;
    
    GCSMem.range = NULL; GCSMem.map = NULL;
    
    lock = IOSimpleLockAlloc();
    
    return res;
}
IOReturn IOSharedInterruptController::initInterruptController(IOInterruptController *parentController, OSData *parentSource)
{
  int      cnt, interruptType;
  IOReturn error;
  
  if (!super::init())
    return kIOReturnNoResources;
  
  // Set provider to this so enable/disable nub stuff works.
  provider = this;
  
  // Allocate the IOInterruptSource so this can act like a nub.
  _interruptSources = (IOInterruptSource *)IOMalloc(sizeof(IOInterruptSource));
  if (_interruptSources == 0) return kIOReturnNoMemory;
  _numInterruptSources = 1;
  
  // Set up the IOInterruptSource to point at this.
  _interruptSources[0].interruptController = parentController;
  _interruptSources[0].vectorData = parentSource;
  
  sourceIsLevel = false;
  error = provider->getInterruptType(0, &interruptType);
  if (error == kIOReturnSuccess) {
    if (interruptType & kIOInterruptTypeLevel)
      sourceIsLevel = true;
  }
  
  // Allocate the memory for the vectors
  numVectors = 32; // For now a constant number.
  vectors = (IOInterruptVector *)IOMalloc(numVectors * sizeof(IOInterruptVector));
  if (vectors == NULL) {
    IOFree(_interruptSources, sizeof(IOInterruptSource));
    return kIOReturnNoMemory;
  }
  bzero(vectors, numVectors * sizeof(IOInterruptVector));
  
  // Allocate the lock for the controller.
  controllerLock = IOSimpleLockAlloc();
  if (controllerLock == 0) return kIOReturnNoResources;
  
  // Allocate locks for the vectors.
  for (cnt = 0; cnt < numVectors; cnt++) {
    vectors[cnt].interruptLock = IOLockAlloc();
    if (vectors[cnt].interruptLock == NULL) {
      for (cnt = 0; cnt < numVectors; cnt++) {
	if (vectors[cnt].interruptLock != NULL)
	  IOLockFree(vectors[cnt].interruptLock);
      }
      return kIOReturnNoResources;
    }
  }
  
  vectorsRegistered = 0;
  vectorsEnabled = 0;
  controllerDisabled = 1;
  
  return kIOReturnSuccess;
}
bool AgereET131x::init(OSDictionary *properties)
{
	//IOLog("AgereET131x::init()\n");
	if (super::init(properties) == false) 
		return false;
	
	enabledForNetif = false;
	
	pciDevice = NULL;
	mediumDict = NULL;
	csrPCIAddress = NULL;
	interruptSource = NULL;
	watchdogSource = NULL;
	netif = NULL;
	
	transmitQueue = NULL;
	rxMbufCursor = NULL;
	txMbufCursor = NULL;
	
	for (int i = 0; i < MEDIUM_INDEX_COUNT; i++) {
		mediumTable[i] = NULL;
	}

	suspend = false;

    adapter.Lock = IOSimpleLockAlloc();
    adapter.TCBSendQLock = IOSimpleLockAlloc();
    adapter.TCBReadyQLock = IOSimpleLockAlloc();
    adapter.SendHWLock = IOSimpleLockAlloc();
    adapter.RcvLock = IOSimpleLockAlloc();
    adapter.FbrLock = IOSimpleLockAlloc();
    adapter.PHYLock = IOSimpleLockAlloc();

	return true;
}
bool DldIPCUserClient::InitIPCUserClientStaticPart()
{
    DldIPCUserClient::WaitLock = IOSimpleLockAlloc();
    assert( DldIPCUserClient::WaitLock );
    if( ! DldIPCUserClient::WaitLock )
        return false;
    
    return true;
}
示例#7
0
bool IOWorkLoop::init()
{
    // The super init and gateLock allocation MUST be done first
    if ( !super::init() )
        return false;
	
    if ( gateLock == NULL ) {
        if ( !( gateLock = IORecursiveLockAlloc()) )
            return false;
    }
	
    if ( workToDoLock == NULL ) {
        if ( !(workToDoLock = IOSimpleLockAlloc()) )
            return false;
        IOSimpleLockInit(workToDoLock);
        workToDo = false;
    }

    if ( controlG == NULL ) {
        controlG = IOCommandGate::commandGate(
            this,
            OSMemberFunctionCast(
                IOCommandGate::Action,
                this,
                &IOWorkLoop::_maintRequest));

        if ( !controlG )
            return false;
        // Point the controlGate at the workLoop.  Usually addEventSource
        // does this automatically.  The problem is in this case addEventSource
        // uses the control gate and it has to be bootstrapped.
        controlG->setWorkLoop(this);
        if (addEventSource(controlG) != kIOReturnSuccess)
            return false;
    }

    if ( workThread == NULL ) {
        thread_continue_t cptr = OSMemberFunctionCast(
            thread_continue_t,
            this,
            &IOWorkLoop::threadMain);
        if (KERN_SUCCESS != kernel_thread_start(cptr, this, &workThread))
            return false;
    }

    return true;
}
bool IOFWSyncer::init(bool twoRetains)
{
    if (!OSObject::init())
        return false;

    if (!(guardLock = IOSimpleLockAlloc()) )
        return false;
	
    IOSimpleLockInit(guardLock);

    if(twoRetains)
	retain();

    fResult = kIOReturnSuccess;

    reinit();

    return true;
}
示例#9
0
bool driver::init(OSDictionary *properties) {
    OSArray *speedArray = NULL;
    OSCollectionIterator *speedIterator = NULL;
    OSString *speedKey;

    chkpoint("Initializing\n");
    if (super::init(properties) == false) fail("super::init");
	
    speedArray = OSDynamicCast(OSArray, getProperty(kVID));
    if (speedArray == NULL) fail("no " kVID "!\n");

    speedIterator = OSCollectionIterator::withCollection(speedArray);
    if (speedIterator == NULL) fail("no speediterator!\n");

    speedIterator->reset();
    while (speedKey = (OSString *)speedIterator->getNextObject()) {
         sscanf(speedKey->getCStringNoCopy(),"%d,%d,%x",&speedstep_cpu_setting[num_speeds].cpuMhz,&speedstep_cpu_setting[num_speeds].cpuMv,&speedstep_cpu_setting[num_speeds].VID);
	 if (speedstep_cpu_setting[num_speeds].cpuMhz<=100 || speedstep_cpu_setting[num_speeds].cpuMv<=700 || speedstep_cpu_setting[num_speeds].VID < 0xFF) { // Some sane values - 700mv is the absolute minimum possible?
	  bzero(&speedstep_cpu_setting[num_speeds],sizeof(speedstep_cpu_t));
	  err("Ignoring invalid mhz,mv specified = %s\n",speedKey->getCStringNoCopy());
	 } else {
	  //speedstep_cpu_setting[num_speeds].VID=VID(speedstep_cpu_setting[num_speeds].cpuMhz,speedstep_cpu_setting[num_speeds].cpuMv);
	  info("Identified configured speed %uMhz, %umv, VID=0x%04x\n",speedstep_cpu_setting[num_speeds].cpuMhz,speedstep_cpu_setting[num_speeds].cpuMv,speedstep_cpu_setting[num_speeds].VID);
          num_speeds++;
	 }
    }
	
    if (!num_speeds) fail("No valid speeds given"); // No valid settings, bail!
    dbg("%d speed settings used\n", num_speeds);

    eist_lock=IOSimpleLockAlloc();
    if (!eist_lock) fail("IOSimpleLockAlloc");
	
    return(true);
	
    fail:
    return(false);
}
bool CLASS::init(OSDictionary* dictionary)
{
	/*
	 * (64-bit/32-bit)
	 * sizeof(USBXHCI)           = 0x23B80/0x1A640
	 * sizeof(IOUSBControllerV3) = 680/492
	 * sizeof(IOUSBControllerV2) = 440/360
	 * sizeof(IOUSBController)   = 176/100
	 * sizeof(IOUSBBus)          = 136/80
	 *
	 * Inheritance
	 *   XHCIIsochEndpoint: public IOUSBControllerIsochEndpoint
	 *   XHCIIsochTransferDescriptor: public IOUSBControllerIsochListElement
	 *   XHCIAsyncEndpoint: public OSObject
	 *   XHCIAsyncTransferDescriptor: public OSObject
	 *   RootHubPortTable: public OSObject
	 *   TTBandwidthTable: public OSObject
	 *
	 * Compiler symbol options
	 *   LONG_RESET - enable complex reset sequence related to Intel Series 7 muxed ports
	 *   DEBOUNCING - enable port debounce code
	 */
	if (!super::init(dictionary)) {
		IOLog("%s: super::init failed\n", __FUNCTION__);
		return false;
	}
	_controllerSpeed = kUSBDeviceSpeedSuper;
	_isochScheduleLock = IOSimpleLockAlloc();
	if (!_isochScheduleLock) {
		IOLog("%s: Unable to allocate SimpleLock\n", __FUNCTION__);
		return false;
	}
	_uimInitialized = false;
	_myBusState = kUSBBusStateReset;
	return true;
}
示例#11
0
bool IOWorkLoop::init()
{
    // The super init and gateLock allocation MUST be done first.
    if ( !super::init() )
        return false;
	
	// Allocate our ExpansionData if it hasn't been allocated already.
	if ( !reserved )
	{
		reserved = IONew(ExpansionData,1);
		if ( !reserved )
			return false;
		
		bzero(reserved,sizeof(ExpansionData));
	}
	
#if DEBUG
	OSBacktrace ( reserved->allocationBacktrace, sizeof ( reserved->allocationBacktrace ) / sizeof ( reserved->allocationBacktrace[0] ) );
#endif
	
    if ( gateLock == NULL ) {
        if ( !( gateLock = IORecursiveLockAlloc()) )
            return false;
    }
	
    if ( workToDoLock == NULL ) {
        if ( !(workToDoLock = IOSimpleLockAlloc()) )
            return false;
        IOSimpleLockInit(workToDoLock);
        workToDo = false;
    }

    if (!reserved) {
        reserved = IONew(ExpansionData, 1);
        reserved->options = 0;
    }
	
    IOStatisticsRegisterCounter();

    if ( controlG == NULL ) {
        controlG = IOCommandGate::commandGate(
            this,
            OSMemberFunctionCast(
                IOCommandGate::Action,
                this,
                &IOWorkLoop::_maintRequest));

        if ( !controlG )
            return false;
        // Point the controlGate at the workLoop.  Usually addEventSource
        // does this automatically.  The problem is in this case addEventSource
        // uses the control gate and it has to be bootstrapped.
        controlG->setWorkLoop(this);
        if (addEventSource(controlG) != kIOReturnSuccess)
            return false;
    }

    if ( workThread == NULL ) {
        thread_continue_t cptr = OSMemberFunctionCast(
            thread_continue_t,
            this,
            &IOWorkLoop::threadMain);
        if (KERN_SUCCESS != kernel_thread_start(cptr, this, &workThread))
            return false;
    }

    (void) thread_set_tag(workThread, THREAD_TAG_IOWORKLOOP);
    return true;
}
bool com_reidburke_air_IntelEnhancedSpeedStep::init(OSDictionary* dict) {
	bool res = super::init(dict);
	info("Initializing xnu-speedstep-air\n");
  
  // read data
  cpuid_update_generic_info();
  
	/* Allocate our spinlock for later use */
	Lock = IOSimpleLockAlloc();
	/* Check for a patched kernel which properly implements rtc_clock_stepped() */
	uint64_t magic = -1; // means autodetect
	
	OSBoolean* debugMsgs = (OSBoolean*) dict->getObject("DebugMessages");
	if (debugMsgs != 0)
		DebugOn = debugMsgs->getValue();
	else
		DebugOn = false;
	
	OSNumber* kernelFeatures = (OSNumber*) dict->getObject("KernelFeatures");
	if (kernelFeatures != 0)
		magic = kernelFeatures->unsigned8BitValue();
	
	if (magic == 255) nanoseconds_to_absolutetime(~(0), &magic); //255uint = -1 int
	
	if (magic == 1) {
		RtcFixKernel = true;
		Below1Ghz	= false;
	} else if (magic == 2) {
		RtcFixKernel = true;
		Below1Ghz	= true;
	} else if (magic == 3) {
		RtcFixKernel = false;
		Below1Ghz = true;
	} else {
		RtcFixKernel = false;
		Below1Ghz	= false;
	}
	
	checkForNby2Ratio(); // check and store in global variable before loading pstate override
	if (getFSB() == false)
		return false;
	
	OSArray* overrideTable = (OSArray*) dict->getObject("PStateTable");
	if (overrideTable != 0 )
		loadPStateOverride(overrideTable);
	
	OSNumber* defaultState = (OSNumber*) dict->getObject("DefaultPState");
	if (defaultState != 0)
		DefaultPState = defaultState->unsigned8BitValue();
	else
		DefaultPState = -1; // indicate no default state

	OSNumber* maxLatency = (OSNumber*) dict->getObject("Latency");
	if (maxLatency != 0)
		MaxLatency = maxLatency->unsigned32BitValue();
	else
		MaxLatency = 0;
	
 	
  /* Make preliminary check */
	if ( (strcmp(cpuid_info()->cpuid_vendor, CPUID_VID_INTEL) == 0) // Check it's actually Intel
      && ( cpuid_info()->cpuid_features & CPUID_FEATURE_EST) ) { // Check it supports EST
	 
    autostart = (OSNumber*) dict->getObject("AutoStart");
    info( "do autostart %d \n", autostart->unsigned8BitValue() );
    
    if ( autostart != 0 && autostart->unsigned8BitValue() == 1 ) {
      Throttler = new AutoThrottler;
      if (Throttler) {
        dbg("Throttler instantiated.\n");
        OSNumber* targetload = (OSNumber*) dict->getObject("TargetCPULoad");
        if (targetload != 0)
          Throttler->targetCPULoad = (targetload->unsigned16BitValue()) * 10;
        else
          Throttler->targetCPULoad = 700;
      }
    }
	}
  
	totalThrottles = 0;
	frequencyUsage[0] = '\0';
	
	/* Return whatever the superclass returned */
	return res;
}
// 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;
}
示例#14
0
bool AppleGPIO::start(IOService *provider)
{
	bool					doSleepWake;
	UInt32					i, flags, intCapable;
	IOPlatformFunction		*func;
	const OSSymbol			*functionSymbol = OSSymbol::withCString("InstantiatePlatformFunctions");
	IOReturn				retval;
	IOService				*parentDev;
	OSData					*data;

	if (!super::start(provider)) return(false);
	
	// set my id
	data = OSDynamicCast(OSData, provider->getProperty("reg"));
	if (!data) return(false);
	
	fGPIOID = *(UInt32 *)data->getBytesNoCopy();
	
	// find the gpio parent
	parentDev = OSDynamicCast(IOService, provider->getParentEntry(gIODTPlane));
	if (!parentDev) return(false);

	fParent = OSDynamicCast(IOService, parentDev->getChildEntry(gIOServicePlane));
	if (!fParent) return(false);

	// Create the interrupt register/enable symbols
	fSymIntRegister 	= OSSymbol::withCString(kIOPFInterruptRegister);
	fSymIntUnRegister 	= OSSymbol::withCString(kIOPFInterruptUnRegister);
	fSymIntEnable 		= OSSymbol::withCString(kIOPFInterruptEnable);
	fSymIntDisable		= OSSymbol::withCString(kIOPFInterruptDisable);

	// Allocate our constant callPlatformFunction symbols so we can be called at interrupt time.

	fSymGPIOParentWriteGPIO = OSSymbol::withCString(kSymGPIOParentWriteGPIO);
	fSymGPIOParentReadGPIO = OSSymbol::withCString(kSymGPIOParentReadGPIO);

	// Scan for platform-do-xxx functions
	fPlatformFuncArray = NULL;

	DLOG("AppleGPIO::start(%s@%lx) - calling InstantiatePlatformFunctions\n",
			provider->getName(), fGPIOID);

	retval = provider->getPlatform()->callPlatformFunction(functionSymbol, false,
			(void *)provider, (void *)&fPlatformFuncArray, (void *)0, (void *)0);

	DLOG("AppleGPIO::start(%s@%lx) - InstantiatePlatformFunctions returned %ld, pfArray %sNULL\n",
			provider->getName(), fGPIOID, retval, fPlatformFuncArray ? "NOT " : "");

	if (retval == kIOReturnSuccess && (fPlatformFuncArray != NULL))
	{
		// Find out if the GPIO parent supports interrupt events
		if (fParent->callPlatformFunction(kSymGPIOParentIntCapable, false, &intCapable, 0, 0, 0)
				!= kIOReturnSuccess)
		{
			intCapable = 0;
		}

		DLOG("AppleGPIO::start(%s@%lx) - iterating platformFunc array, count = %ld\n",
			provider->getName(), fGPIOID, fPlatformFuncArray->getCount());

		doSleepWake = false;

		UInt32 count = fPlatformFuncArray->getCount();
		for (i = 0; i < count; i++)
		{
			if (func = OSDynamicCast(IOPlatformFunction, fPlatformFuncArray->getObject(i)))
			{
				flags = func->getCommandFlags();

				DLOG ("AppleGPIO::start(%s@%lx) - functionCheck - got function, flags 0x%lx, pHandle 0x%lx\n", 
					provider->getName(), fGPIOID, flags, func->getCommandPHandle());

				// If this function is flagged to be performed at initialization, do it
				if (flags & kIOPFFlagOnInit)
				{
					performFunction(func, (void *)1, (void *)0, (void *)0, (void *)0);
				}

				if ((flags & kIOPFFlagOnDemand) || ((flags & kIOPFFlagIntGen) && intCapable))
				{
					// Set the flag to indicate whether any of the platform functions are using
					// interrupts -- this is used to allocate some locks that are needed for this
					// functionality
					if ((flags & kIOPFFlagIntGen) && (fIntGen == false))
					{
						fIntGen = true;

						// Allocate event-related state variable locks
						fClientsLock = IOSimpleLockAlloc();
						fAmRegisteredLock = IOLockAlloc();
						fAmEnabledLock = IOSimpleLockAlloc();
					}
					
					// This is a bit of overkill.  Strictly speaking the lock needs to protect
					// individual platformFunc array entries so that only one thread is executing
					// that function at a time.  The way we're using it here is only one of *any*
					// of the platform functions can be executing at a time.
					if (!fPFLock) fPFLock = IOLockAlloc();	// Use for both On-Demand and IntGen functions

					// On-Demand and IntGen functions need to have a resource published
					func->publishPlatformFunction(this);
				}

				// If we need to do anything at sleep/wake time, we'll need to set this
				// flag so we know to register for notifications
				if (flags & (kIOPFFlagOnSleep | kIOPFFlagOnWake))
					doSleepWake = true;
			}
			else
			{
				// This function won't be used -- generate a warning
				IOLog("AppleGPIO::start(%s@%lx) - functionCheck - not an IOPlatformFunction object\n",
						getProvider()->getName(), fGPIOID);
			}
		}

		// Register sleep and wake notifications
		if (doSleepWake)
		{
			mach_timespec_t	waitTimeout;

			waitTimeout.tv_sec = 30;
			waitTimeout.tv_nsec = 0;

			pmRootDomain = OSDynamicCast(IOPMrootDomain,
					waitForService(serviceMatching("IOPMrootDomain"), &waitTimeout));

			if (pmRootDomain != 0)
			{
				DLOG("AppleGPIO::start to acknowledge power changes\n");
				pmRootDomain->registerInterestedDriver(this);
			}
			else
			{
				IOLog("AppleGPIO failed to register PM interest!");
			}
		}
	}


#ifdef OLD_STYLE_COMPAT
	/*
	 * Legacy Support
	 *
	 * In the initial implementation, extra strings were published for event registration
	 * and deregistration as well as enable/disable functions.  In the IOPlatformFunction
	 * implementation, the client access these functions by calling the platform-xxx function
	 * and passing one of four OSSymbol objects (see fSymIntRegister, fSymIntUnRegister,
	 * fSymIntEnable, fSymIntDisable).  For now, we need to continue to support the old
	 * implementation.  The following code will generate and publish resources for these
	 * functions.
	 */

	if (fIntGen)
	{
		const OSSymbol 	*functionSym, *aKey;
		char			funcNameWithPrefix[160];
		const char		*funcName;

		UInt32 count = fPlatformFuncArray->getCount();
		for (i = 0; i < count; i++)
		{
			// Only publish strings for on-demand and int-gen functions
			if ((func = OSDynamicCast(IOPlatformFunction, fPlatformFuncArray->getObject(i))) != NULL &&
				(func->getCommandFlags() & (kIOPFFlagOnDemand | kIOPFFlagIntGen)) != NULL)
			{
				functionSym = func->getPlatformFunctionName();
				if (!functionSym)
					continue;
				else
					funcName = functionSym->getCStringNoCopy() + strlen(kFunctionRequiredPrefix);
			
				// register string list
				strncpy(funcNameWithPrefix, kFunctionRegisterPrefix, strlen (kFunctionRegisterPrefix)+1);
				strncat(funcNameWithPrefix, funcName, sizeof (funcNameWithPrefix) - strlen (funcNameWithPrefix) - 1);
				funcNameWithPrefix[sizeof (funcNameWithPrefix) - 1] = '\0';

				if ((aKey = OSSymbol::withCString(funcNameWithPrefix)) == 0)
					continue;

				ADD_OBJ_TO_SET(aKey, fRegisterStrings);

				// unregister string list
				strncpy(funcNameWithPrefix, kFunctionUnregisterPrefix, strlen (kFunctionUnregisterPrefix)+1);
				strncat(funcNameWithPrefix, funcName, sizeof (funcNameWithPrefix) - strlen (funcNameWithPrefix) - 1);
				funcNameWithPrefix[sizeof (funcNameWithPrefix) - 1] = '\0';
				
				if ((aKey = OSSymbol::withCString(funcNameWithPrefix)) == 0)
					continue;
				
				ADD_OBJ_TO_SET(aKey, fUnregisterStrings);

				// register string list
				strncpy(funcNameWithPrefix, kFunctionEvtEnablePrefix, strlen (kFunctionEvtEnablePrefix)+1);
				strncat(funcNameWithPrefix, funcName, sizeof (funcNameWithPrefix) - strlen (funcNameWithPrefix) - 1);
				funcNameWithPrefix[sizeof (funcNameWithPrefix) - 1] = '\0';

				if ((aKey = OSSymbol::withCString(funcNameWithPrefix)) == 0)
					continue;

				ADD_OBJ_TO_SET(aKey, fEnableStrings);

				// register string list
				strncpy(funcNameWithPrefix, kFunctionEvtDisablePrefix, strlen (kFunctionEvtDisablePrefix)+1);
				strncat(funcNameWithPrefix, funcName, sizeof (funcNameWithPrefix) - strlen (funcNameWithPrefix) - 1);
				funcNameWithPrefix[sizeof (funcNameWithPrefix) - 1] = '\0';

				if ((aKey = OSSymbol::withCString(funcNameWithPrefix)) == 0)
					continue;

				ADD_OBJ_TO_SET(aKey, fDisableStrings);
			}
		}

		publishStrings(fRegisterStrings);
		publishStrings(fUnregisterStrings);
		publishStrings(fEnableStrings);
		publishStrings(fDisableStrings);
	}

#endif

	if (fPlatformFuncArray && fPlatformFuncArray->getCount() > 0)
	{
		registerService();
		return(true);
	}
	else
	{
		// No reason for me to be here
		return(false);
	}
}