2  * Copyright (c) 1999-2000 Apple Computer, Inc.  All rights reserved. 
   4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 
   6  * This file contains Original Code and/or Modifications of Original Code 
   7  * as defined in and that are subject to the Apple Public Source License 
   8  * Version 2.0 (the 'License'). You may not use this file except in 
   9  * compliance with the License. The rights granted to you under the License 
  10  * may not be used to create, or enable the creation or redistribution of, 
  11  * unlawful or unlicensed copies of an Apple operating system, or to 
  12  * circumvent, violate, or enable the circumvention or violation of, any 
  13  * terms of an Apple operating system software license agreement. 
  15  * Please obtain a copy of the License at 
  16  * http://www.opensource.apple.com/apsl/ and read it before using this file. 
  18  * The Original Code and all software distributed under the License are 
  19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  23  * Please see the License for the specific language governing rights and 
  24  * limitations under the License. 
  26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 
  29  * Copyright (c) 1999-2000 Apple Computer, Inc.  All rights reserved. 
  36 #include <machine/machine_routines.h> 
  37 #include <pexpert/pexpert.h> 
  40 #include <machine/machine_routines.h> 
  42 #include <IOKit/IOLib.h> 
  43 #include <IOKit/IOPlatformExpert.h> 
  44 #include <IOKit/pwr_mgt/RootDomain.h> 
  45 #include <IOKit/IOUserClient.h> 
  46 #include <IOKit/IOKitKeysPrivate.h> 
  47 #include <IOKit/IOCPU.h> 
  49 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
  50 #include <kern/queue.h> 
  52 typedef kern_return_t (*iocpu_platform_action_t
)(void * refcon0
, void * refcon1
, uint32_t priority
, 
  53                                                  void * param1
, void * param2
, void * param3
); 
  55 struct iocpu_platform_action_entry
 
  58     iocpu_platform_action_t           action
; 
  62     struct iocpu_platform_action_entry 
* alloc_list
; 
  64 typedef struct iocpu_platform_action_entry iocpu_platform_action_entry_t
; 
  67 iocpu_get_platform_quiesce_queue(void); 
  70 iocpu_get_platform_active_queue(void); 
  73 iocpu_platform_cpu_action_init(queue_head_t 
* quiesce_queue
, queue_head_t 
* init_queue
); 
  76 iocpu_add_platform_action(queue_head_t 
* queue
, iocpu_platform_action_entry_t 
* entry
); 
  79 iocpu_remove_platform_action(iocpu_platform_action_entry_t 
* entry
); 
  82 iocpu_run_platform_actions(queue_head_t 
* queue
, uint32_t first_priority
, uint32_t last_priority
, 
  83                                         void * param1
, void * param2
, void * param3
); 
  85 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
  87 #define kBootCPUNumber  0 
  89 static iocpu_platform_action_entry_t 
* gIOAllActionsQueue
; 
  90 static queue_head_t gIOSleepActionQueue
; 
  91 static queue_head_t gIOWakeActionQueue
; 
  93 static queue_head_t iocpu_quiesce_queue
; 
  94 static queue_head_t iocpu_active_queue
; 
  96 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
  99 iocpu_platform_cpu_action_init(queue_head_t 
* quiesce_queue
, __unused queue_head_t 
* init_queue
) 
 102     enum { kNumQuiesceActions 
= 2 }; 
 103     static iocpu_platform_action_entry_t quiesce_actions
[kNumQuiesceActions
] =  
 105         { { NULL
, NULL 
}, (iocpu_platform_action_t
) &clean_mmu_dcache
, 97000, 0, 0, NULL 
},     
 106         { { NULL
, NULL 
}, (iocpu_platform_action_t
) &arm_sleep
, 99000, 0, 0, NULL 
},     
 110     for (idx 
= 0; idx 
< kNumQuiesceActions
; idx
++) 
 111         iocpu_add_platform_action(quiesce_queue
, &quiesce_actions
[idx
]); 
 115 queue_head_t 
* iocpu_get_platform_quiesce_queue(void) 
 117     if (!iocpu_quiesce_queue
.next
) 
 119         queue_init(&iocpu_quiesce_queue
); 
 120         queue_init(&iocpu_active_queue
); 
 121         iocpu_platform_cpu_action_init(&iocpu_quiesce_queue
, &iocpu_active_queue
); 
 123     return (&iocpu_quiesce_queue
); 
 126 queue_head_t 
* iocpu_get_platform_active_queue(void) 
 128     return (&iocpu_active_queue
); 
 131 void iocpu_add_platform_action(queue_head_t 
* queue
, iocpu_platform_action_entry_t 
* entry
) 
 133     iocpu_platform_action_entry_t 
* next
; 
 135     queue_iterate(queue
, next
, iocpu_platform_action_entry_t 
*, link
) 
 137         if (next
->priority 
> entry
->priority
) 
 139             queue_insert_before(queue
, entry
, next
, iocpu_platform_action_entry_t 
*, link
); 
 143     queue_enter(queue
, entry
, iocpu_platform_action_entry_t 
*, link
);   // at tail 
 146 void iocpu_remove_platform_action(iocpu_platform_action_entry_t 
* entry
) 
 148     remque(&entry
->link
); 
 152 iocpu_run_platform_actions(queue_head_t 
* queue
, uint32_t first_priority
, uint32_t last_priority
, 
 153                                         void * param1
, void * param2
, void * param3
) 
 155     kern_return_t                ret 
= KERN_SUCCESS
; 
 156     kern_return_t                result 
= KERN_SUCCESS
; 
 157     iocpu_platform_action_entry_t 
* next
; 
 159     queue_iterate(queue
, next
, iocpu_platform_action_entry_t 
*, link
) 
 161         uint32_t pri 
= (next
->priority 
< 0) ? -next
->priority 
: next
->priority
; 
 162         if ((pri 
>= first_priority
) && (pri 
<= last_priority
)) 
 164             //kprintf("[%p]", next->action); 
 165             ret 
= (*next
->action
)(next
->refcon0
, next
->refcon1
, pri
, param1
, param2
, param3
); 
 167         if (KERN_SUCCESS 
== result
) 
 173 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
 175 extern "C" kern_return_t 
 
 176 IOCPURunPlatformQuiesceActions(void) 
 178     return (iocpu_run_platform_actions(iocpu_get_platform_quiesce_queue(), 0, 0U-1, 
 182 extern "C" kern_return_t 
 
 183 IOCPURunPlatformActiveActions(void) 
 185     return (iocpu_run_platform_actions(iocpu_get_platform_active_queue(), 0, 0U-1, 
 190 IOServicePlatformAction(void * refcon0
, void * refcon1
, uint32_t priority
, 
 191                           void * param1
, void * param2
, void * param3
) 
 194     IOService 
*      service  
= (IOService 
*)      refcon0
; 
 195     const OSSymbol 
* function 
= (const OSSymbol 
*) refcon1
; 
 197     kprintf("%s -> %s\n", function
->getCStringNoCopy(), service
->getName()); 
 199     ret 
= service
->callPlatformFunction(function
, false,  
 200                                          (void *) priority
, param1
, param2
, param3
); 
 206 IOInstallServicePlatformAction(IOService 
* service
,  
 207                                 const OSSymbol 
* key
, queue_head_t 
* queue
, 
 211     iocpu_platform_action_entry_t 
* entry
; 
 214     num 
= OSDynamicCast(OSNumber
, service
->getProperty(key
)); 
 218     entry 
= IONew(iocpu_platform_action_entry_t
, 1); 
 219     entry
->action 
= &IOServicePlatformAction
; 
 220     priority 
= num
->unsigned32BitValue(); 
 222         entry
->priority 
= -priority
; 
 224         entry
->priority 
= priority
; 
 225     entry
->refcon0 
= service
; 
 226     entry
->refcon1 
= (void *) key
; 
 228     iocpu_add_platform_action(queue
, entry
); 
 229     entry
->alloc_list 
= gIOAllActionsQueue
; 
 230     gIOAllActionsQueue 
= entry
; 
 233 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
 235 kern_return_t 
PE_cpu_start(cpu_id_t target
, 
 236                            vm_offset_t start_paddr
, vm_offset_t arg_paddr
) 
 238   IOCPU 
*targetCPU 
= OSDynamicCast(IOCPU
, (OSObject 
*)target
); 
 240   if (targetCPU 
== 0) return KERN_FAILURE
; 
 241   return targetCPU
->startCPU(start_paddr
, arg_paddr
); 
 244 void PE_cpu_halt(cpu_id_t target
) 
 246   IOCPU 
*targetCPU 
= OSDynamicCast(IOCPU
, (OSObject 
*)target
); 
 248   if (targetCPU
) targetCPU
->haltCPU(); 
 251 void PE_cpu_signal(cpu_id_t source
, cpu_id_t target
) 
 253   IOCPU 
*sourceCPU 
= OSDynamicCast(IOCPU
, (OSObject 
*)source
); 
 254   IOCPU 
*targetCPU 
= OSDynamicCast(IOCPU
, (OSObject 
*)target
); 
 256   if (sourceCPU 
&& targetCPU
) sourceCPU
->signalCPU(targetCPU
); 
 259 void PE_cpu_machine_init(cpu_id_t target
, boolean_t bootb
) 
 261   IOCPU 
*targetCPU 
= OSDynamicCast(IOCPU
, (OSObject 
*)target
); 
 263   if (targetCPU
) targetCPU
->initCPU(bootb
); 
 266 void PE_cpu_machine_quiesce(cpu_id_t target
) 
 268   IOCPU 
*targetCPU 
= OSDynamicCast(IOCPU
, (OSObject 
*)target
); 
 270   if (targetCPU
) targetCPU
->quiesceCPU(); 
 274 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
 276 #define super IOService 
 278 OSDefineMetaClassAndAbstractStructors(IOCPU
, IOService
); 
 279 OSMetaClassDefineReservedUnused(IOCPU
, 0); 
 280 OSMetaClassDefineReservedUnused(IOCPU
, 1); 
 281 OSMetaClassDefineReservedUnused(IOCPU
, 2); 
 282 OSMetaClassDefineReservedUnused(IOCPU
, 3); 
 283 OSMetaClassDefineReservedUnused(IOCPU
, 4); 
 284 OSMetaClassDefineReservedUnused(IOCPU
, 5); 
 285 OSMetaClassDefineReservedUnused(IOCPU
, 6); 
 286 OSMetaClassDefineReservedUnused(IOCPU
, 7); 
 288 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
 290 static OSArray 
*gIOCPUs
; 
 291 static const OSSymbol 
*gIOCPUStateKey
; 
 292 static OSString 
*gIOCPUStateNames
[kIOCPUStateCount
]; 
 294 void IOCPUSleepKernel(void) 
 298     IOCPU 
*bootCPU 
= NULL
; 
 300     kprintf("IOCPUSleepKernel\n"); 
 305     queue_init(&gIOSleepActionQueue
); 
 306     queue_init(&gIOWakeActionQueue
); 
 308     iter 
= IORegistryIterator::iterateOver( gIOServicePlane
, 
 309                                             kIORegistryIterateRecursively 
); 
 315             while((service 
= (IOService 
*) iter
->getNextObject())) 
 317                 IOInstallServicePlatformAction(service
, gIOPlatformSleepActionKey
,   &gIOSleepActionQueue
,               false); 
 318                 IOInstallServicePlatformAction(service
, gIOPlatformWakeActionKey
,    &gIOWakeActionQueue
,                true); 
 319                 IOInstallServicePlatformAction(service
, gIOPlatformQuiesceActionKey
, iocpu_get_platform_quiesce_queue(), false); 
 320                 IOInstallServicePlatformAction(service
, gIOPlatformActiveActionKey
,  iocpu_get_platform_active_queue(),  true); 
 323         while( !service 
&& !iter
->isValid()); 
 327     iocpu_run_platform_actions(&gIOSleepActionQueue
, 0, 0U-1, 
 330     numCPUs 
= gIOCPUs
->getCount(); 
 335         target 
= OSDynamicCast(IOCPU
, gIOCPUs
->getObject(cnt
)); 
 337         // We make certain that the bootCPU is the last to sleep 
 338         // We'll skip it for now, and halt it after finishing the 
 340         if (target
->getCPUNumber() == kBootCPUNumber
)  
 343         } else if (target
->getCPUState() == kIOCPUStateRunning
)  
 349     // Now sleep the boot CPU. 
 353     iocpu_run_platform_actions(&gIOWakeActionQueue
, 0, 0U-1, 
 356     iocpu_platform_action_entry_t 
* entry
; 
 357     while ((entry 
= gIOAllActionsQueue
)) 
 359         gIOAllActionsQueue 
= entry
->alloc_list
; 
 360         iocpu_remove_platform_action(entry
); 
 361         IODelete(entry
, iocpu_platform_action_entry_t
, 1); 
 364     if (!queue_empty(&gIOSleepActionQueue
)) 
 365         panic("gIOSleepActionQueue"); 
 366     if (!queue_empty(&gIOWakeActionQueue
)) 
 367         panic("gIOWakeActionQueue"); 
 369     // Wake the other CPUs. 
 370     for (cnt 
= 0; cnt 
< numCPUs
; cnt
++)  
 372         target 
= OSDynamicCast(IOCPU
, gIOCPUs
->getObject(cnt
)); 
 374         // Skip the already-woken boot CPU. 
 375         if ((target
->getCPUNumber() != kBootCPUNumber
) 
 376             && (target
->getCPUState() == kIOCPUStateStopped
)) 
 378             processor_start(target
->getMachProcessor()); 
 383 void IOCPU::initCPUs(void) 
 386     gIOCPUs 
= OSArray::withCapacity(1); 
 388     gIOCPUStateKey 
= OSSymbol::withCStringNoCopy("IOCPUState"); 
 390     gIOCPUStateNames
[kIOCPUStateUnregistered
] = 
 391       OSString::withCStringNoCopy("Unregistered"); 
 392     gIOCPUStateNames
[kIOCPUStateUninitalized
] = 
 393       OSString::withCStringNoCopy("Uninitalized"); 
 394     gIOCPUStateNames
[kIOCPUStateStopped
] = 
 395       OSString::withCStringNoCopy("Stopped"); 
 396     gIOCPUStateNames
[kIOCPUStateRunning
] = 
 397       OSString::withCStringNoCopy("Running"); 
 401 bool IOCPU::start(IOService 
*provider
) 
 403   OSData 
*busFrequency
, *cpuFrequency
, *timebaseFrequency
; 
 405   if (!super::start(provider
)) return false; 
 412   gIOCPUs
->setObject(this); 
 414   // Correct the bus, cpu and timebase frequencies in the device tree. 
 415   if (gPEClockFrequencyInfo
.bus_frequency_hz 
< 0x100000000ULL
) { 
 416     busFrequency 
= OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo
.bus_clock_rate_hz
, 4); 
 418     busFrequency 
= OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo
.bus_frequency_hz
, 8); 
 420   provider
->setProperty("bus-frequency", busFrequency
); 
 421   busFrequency
->release(); 
 423   if (gPEClockFrequencyInfo
.cpu_frequency_hz 
< 0x100000000ULL
) { 
 424     cpuFrequency 
= OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo
.cpu_clock_rate_hz
, 4); 
 426     cpuFrequency 
= OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo
.cpu_frequency_hz
, 8); 
 428   provider
->setProperty("clock-frequency", cpuFrequency
); 
 429   cpuFrequency
->release(); 
 431   timebaseFrequency 
= OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo
.timebase_frequency_hz
, 4); 
 432   provider
->setProperty("timebase-frequency", timebaseFrequency
); 
 433   timebaseFrequency
->release(); 
 435   super::setProperty("IOCPUID", (uintptr_t)this, sizeof(uintptr_t)*8); 
 438   setCPUState(kIOCPUStateUnregistered
); 
 443 OSObject 
*IOCPU::getProperty(const OSSymbol 
*aKey
) const 
 445   if (aKey 
== gIOCPUStateKey
) return gIOCPUStateNames
[_cpuState
]; 
 447   return super::getProperty(aKey
); 
 450 bool IOCPU::setProperty(const OSSymbol 
*aKey
, OSObject 
*anObject
) 
 454   if (aKey 
== gIOCPUStateKey
) { 
 455     stateStr 
= OSDynamicCast(OSString
, anObject
); 
 456     if (stateStr 
== 0) return false; 
 458     if (_cpuNumber 
== 0) return false; 
 460     if (stateStr
->isEqualTo("running")) { 
 461       if (_cpuState 
== kIOCPUStateStopped
) { 
 462         processor_start(machProcessor
); 
 463       } else if (_cpuState 
!= kIOCPUStateRunning
) { 
 466     } else if (stateStr
->isEqualTo("stopped")) { 
 467       if (_cpuState 
== kIOCPUStateRunning
) { 
 469       } else if (_cpuState 
!= kIOCPUStateStopped
) { 
 477   return super::setProperty(aKey
, anObject
); 
 480 bool IOCPU::serializeProperties(OSSerialize 
*serialize
) const 
 483         OSDictionary 
*dict 
= dictionaryWithProperties(); 
 484         dict
->setObject(gIOCPUStateKey
, gIOCPUStateNames
[_cpuState
]); 
 485         result 
= dict
->serialize(serialize
); 
 490 IOReturn 
IOCPU::setProperties(OSObject 
*properties
) 
 492   OSDictionary 
*dict 
= OSDynamicCast(OSDictionary
, properties
); 
 496   if (dict 
== 0) return kIOReturnUnsupported
; 
 498   stateStr 
= OSDynamicCast(OSString
, dict
->getObject(gIOCPUStateKey
)); 
 500     result 
= IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator
); 
 501     if (result 
!= kIOReturnSuccess
) return result
; 
 503     if (setProperty(gIOCPUStateKey
, stateStr
)) return kIOReturnSuccess
; 
 505     return kIOReturnUnsupported
; 
 508   return kIOReturnUnsupported
; 
 511 void IOCPU::signalCPU(IOCPU */
*target*/
) 
 515 void IOCPU::enableCPUTimeBase(bool /*enable*/) 
 519 UInt32 
IOCPU::getCPUNumber(void) 
 524 void IOCPU::setCPUNumber(UInt32 cpuNumber
) 
 526   _cpuNumber 
= cpuNumber
; 
 527   super::setProperty("IOCPUNumber", _cpuNumber
, 32); 
 530 UInt32 
IOCPU::getCPUState(void) 
 535 void IOCPU::setCPUState(UInt32 cpuState
) 
 537   if (cpuState 
< kIOCPUStateCount
) { 
 538     _cpuState 
= cpuState
; 
 542 OSArray 
*IOCPU::getCPUGroup(void) 
 547 UInt32 
IOCPU::getCPUGroupSize(void) 
 549   return _cpuGroup
->getCount(); 
 552 processor_t 
IOCPU::getMachProcessor(void) 
 554   return machProcessor
; 
 558 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
 561 #define super IOInterruptController 
 563 OSDefineMetaClassAndStructors(IOCPUInterruptController
, IOInterruptController
); 
 565 OSMetaClassDefineReservedUnused(IOCPUInterruptController
, 0); 
 566 OSMetaClassDefineReservedUnused(IOCPUInterruptController
, 1); 
 567 OSMetaClassDefineReservedUnused(IOCPUInterruptController
, 2); 
 568 OSMetaClassDefineReservedUnused(IOCPUInterruptController
, 3); 
 569 OSMetaClassDefineReservedUnused(IOCPUInterruptController
, 4); 
 570 OSMetaClassDefineReservedUnused(IOCPUInterruptController
, 5); 
 574 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
 577 IOReturn 
IOCPUInterruptController::initCPUInterruptController(int sources
) 
 581   if (!super::init()) return kIOReturnInvalid
; 
 585   cpus 
= (IOCPU 
**)IOMalloc(numCPUs 
* sizeof(IOCPU 
*)); 
 586   if (cpus 
== 0) return kIOReturnNoMemory
; 
 587   bzero(cpus
, numCPUs 
* sizeof(IOCPU 
*)); 
 589   vectors 
= (IOInterruptVector 
*)IOMalloc(numCPUs 
* sizeof(IOInterruptVector
)); 
 590   if (vectors 
== 0) return kIOReturnNoMemory
; 
 591   bzero(vectors
, numCPUs 
* sizeof(IOInterruptVector
)); 
 593   // Allocate locks for the 
 594   for (cnt 
= 0; cnt 
< numCPUs
; cnt
++) { 
 595     vectors
[cnt
].interruptLock 
= IOLockAlloc(); 
 596     if (vectors
[cnt
].interruptLock 
== NULL
) { 
 597       for (cnt 
= 0; cnt 
< numCPUs
; cnt
++) { 
 598         if (vectors
[cnt
].interruptLock 
!= NULL
) 
 599           IOLockFree(vectors
[cnt
].interruptLock
); 
 601       return kIOReturnNoResources
; 
 605   ml_init_max_cpus(numCPUs
); 
 607   return kIOReturnSuccess
; 
 610 void IOCPUInterruptController::registerCPUInterruptController(void) 
 614   getPlatform()->registerInterruptController(gPlatformInterruptControllerName
, 
 618 void IOCPUInterruptController::setCPUInterruptProperties(IOService 
*service
) 
 626   if ((service
->getProperty(gIOInterruptControllersKey
) != 0) && 
 627       (service
->getProperty(gIOInterruptSpecifiersKey
) != 0)) 
 630   // Create the interrupt specifer array. 
 631   specifier 
= OSArray::withCapacity(numCPUs
); 
 632   for (cnt 
= 0; cnt 
< numCPUs
; cnt
++) { 
 634     tmpData 
= OSData::withBytes(&tmpLong
, sizeof(tmpLong
)); 
 635     specifier
->setObject(tmpData
); 
 639   // Create the interrupt controller array. 
 640   controller 
= OSArray::withCapacity(numCPUs
); 
 641   for (cnt 
= 0; cnt 
< numCPUs
; cnt
++) { 
 642     controller
->setObject(gPlatformInterruptControllerName
); 
 645   // Put the two arrays into the property table. 
 646   service
->setProperty(gIOInterruptControllersKey
, controller
); 
 647   service
->setProperty(gIOInterruptSpecifiersKey
, specifier
); 
 648   controller
->release(); 
 649   specifier
->release(); 
 652 void IOCPUInterruptController::enableCPUInterrupt(IOCPU 
*cpu
) 
 654         IOInterruptHandler handler 
= OSMemberFunctionCast( 
 655                 IOInterruptHandler
, this, &IOCPUInterruptController::handleInterrupt
); 
 657         ml_install_interrupt_handler(cpu
, cpu
->getCPUNumber(), this, handler
, 0); 
 661   if (enabledCPUs 
== numCPUs
) thread_wakeup(this); 
 664 IOReturn 
IOCPUInterruptController::registerInterrupt(IOService 
*nub
, 
 667                                                      IOInterruptHandler handler
, 
 670   IOInterruptVector 
*vector
; 
 672   if (source 
>= numCPUs
) return kIOReturnNoResources
; 
 674   vector 
= &vectors
[source
]; 
 676   // Get the lock for this vector. 
 677   IOTakeLock(vector
->interruptLock
); 
 679   // Make sure the vector is not in use. 
 680   if (vector
->interruptRegistered
) { 
 681     IOUnlock(vector
->interruptLock
); 
 682     return kIOReturnNoResources
; 
 685   // Fill in vector with the client's info. 
 686   vector
->handler 
= handler
; 
 688   vector
->source  
= source
; 
 689   vector
->target  
= target
; 
 690   vector
->refCon  
= refCon
; 
 692   // Get the vector ready.  It starts hard disabled. 
 693   vector
->interruptDisabledHard 
= 1; 
 694   vector
->interruptDisabledSoft 
= 1; 
 695   vector
->interruptRegistered   
= 1; 
 697   IOUnlock(vector
->interruptLock
); 
 699   if (enabledCPUs 
!= numCPUs
) { 
 700     assert_wait(this, THREAD_UNINT
); 
 701     thread_block(THREAD_CONTINUE_NULL
); 
 704   return kIOReturnSuccess
; 
 707 IOReturn 
IOCPUInterruptController::getInterruptType(IOService */
*nub*/
, 
 711   if (interruptType 
== 0) return kIOReturnBadArgument
; 
 713   *interruptType 
= kIOInterruptTypeLevel
; 
 715   return kIOReturnSuccess
; 
 718 IOReturn 
IOCPUInterruptController::enableInterrupt(IOService */
*nub*/
, 
 721 //  ml_set_interrupts_enabled(true); 
 722   return kIOReturnSuccess
; 
 725 IOReturn 
IOCPUInterruptController::disableInterrupt(IOService */
*nub*/
, 
 728 //  ml_set_interrupts_enabled(false); 
 729   return kIOReturnSuccess
; 
 732 IOReturn 
IOCPUInterruptController::causeInterrupt(IOService */
*nub*/
, 
 735   ml_cause_interrupt(); 
 736   return kIOReturnSuccess
; 
 739 IOReturn 
IOCPUInterruptController::handleInterrupt(void */
*refCon*/
, 
 743   IOInterruptVector 
*vector
; 
 745   vector 
= &vectors
[source
]; 
 747   if (!vector
->interruptRegistered
) return kIOReturnInvalid
; 
 749   vector
->handler(vector
->target
, vector
->refCon
, 
 750                   vector
->nub
, vector
->source
); 
 752   return kIOReturnSuccess
; 
 755 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */