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/pwr_mgt/IOPMPrivate.h>
46 #include <IOKit/IOUserClient.h>
47 #include <IOKit/IOKitKeysPrivate.h>
48 #include <IOKit/IOCPU.h>
50 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
51 #include <kern/queue.h>
53 typedef kern_return_t (*iocpu_platform_action_t
)(void * refcon0
, void * refcon1
, uint32_t priority
,
54 void * param1
, void * param2
, void * param3
,
57 struct iocpu_platform_action_entry
60 iocpu_platform_action_t action
;
65 struct iocpu_platform_action_entry
* alloc_list
;
67 typedef struct iocpu_platform_action_entry iocpu_platform_action_entry_t
;
70 iocpu_get_platform_quiesce_queue(void);
73 iocpu_get_platform_active_queue(void);
76 iocpu_platform_cpu_action_init(queue_head_t
* quiesce_queue
, queue_head_t
* init_queue
);
79 iocpu_add_platform_action(queue_head_t
* queue
, iocpu_platform_action_entry_t
* entry
);
82 iocpu_remove_platform_action(iocpu_platform_action_entry_t
* entry
);
85 iocpu_run_platform_actions(queue_head_t
* queue
, uint32_t first_priority
, uint32_t last_priority
,
86 void * param1
, void * param2
, void * param3
);
88 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
90 #define kBootCPUNumber 0
92 static iocpu_platform_action_entry_t
* gIOAllActionsQueue
;
93 static queue_head_t gIOSleepActionQueue
;
94 static queue_head_t gIOWakeActionQueue
;
96 static queue_head_t iocpu_quiesce_queue
;
97 static queue_head_t iocpu_active_queue
;
99 static queue_head_t gIOHaltRestartActionQueue
;
101 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
104 iocpu_platform_cpu_action_init(queue_head_t
* quiesce_queue
, __unused queue_head_t
* init_queue
)
107 enum { kNumQuiesceActions
= 2 };
108 static iocpu_platform_action_entry_t quiesce_actions
[kNumQuiesceActions
] =
110 { { NULL
, NULL
}, (iocpu_platform_action_t
) &clean_mmu_dcache
, 97000, 0, 0, NULL
},
111 { { NULL
, NULL
}, (iocpu_platform_action_t
) &arm_sleep
, 99000, 0, 0, NULL
},
115 for (idx
= 0; idx
< kNumQuiesceActions
; idx
++)
116 iocpu_add_platform_action(quiesce_queue
, &quiesce_actions
[idx
]);
120 queue_head_t
* iocpu_get_platform_quiesce_queue(void)
122 if (!iocpu_quiesce_queue
.next
)
124 queue_init(&iocpu_quiesce_queue
);
125 queue_init(&iocpu_active_queue
);
126 iocpu_platform_cpu_action_init(&iocpu_quiesce_queue
, &iocpu_active_queue
);
128 return (&iocpu_quiesce_queue
);
131 queue_head_t
* iocpu_get_platform_active_queue(void)
133 if (!iocpu_active_queue
.next
)
135 queue_init(&iocpu_quiesce_queue
);
136 queue_init(&iocpu_active_queue
);
137 iocpu_platform_cpu_action_init(&iocpu_quiesce_queue
, &iocpu_active_queue
);
139 return (&iocpu_active_queue
);
142 void iocpu_add_platform_action(queue_head_t
* queue
, iocpu_platform_action_entry_t
* entry
)
144 iocpu_platform_action_entry_t
* next
;
146 queue_iterate(queue
, next
, iocpu_platform_action_entry_t
*, link
)
148 if (next
->priority
> entry
->priority
)
150 queue_insert_before(queue
, entry
, next
, iocpu_platform_action_entry_t
*, link
);
154 queue_enter(queue
, entry
, iocpu_platform_action_entry_t
*, link
); // at tail
157 void iocpu_remove_platform_action(iocpu_platform_action_entry_t
* entry
)
159 remque(&entry
->link
);
163 iocpu_run_platform_actions(queue_head_t
* queue
, uint32_t first_priority
, uint32_t last_priority
,
164 void * param1
, void * param2
, void * param3
)
166 kern_return_t ret
= KERN_SUCCESS
;
167 kern_return_t result
= KERN_SUCCESS
;
168 iocpu_platform_action_entry_t
* next
;
170 queue_iterate(queue
, next
, iocpu_platform_action_entry_t
*, link
)
172 uint32_t pri
= (next
->priority
< 0) ? -next
->priority
: next
->priority
;
173 if ((pri
>= first_priority
) && (pri
<= last_priority
))
175 //kprintf("[%p]", next->action);
176 ret
= (*next
->action
)(next
->refcon0
, next
->refcon1
, pri
, param1
, param2
, param3
, next
->name
);
178 if (KERN_SUCCESS
== result
)
184 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
186 extern "C" kern_return_t
187 IOCPURunPlatformQuiesceActions(void)
189 return (iocpu_run_platform_actions(iocpu_get_platform_quiesce_queue(), 0, 0U-1,
193 extern "C" kern_return_t
194 IOCPURunPlatformActiveActions(void)
196 return (iocpu_run_platform_actions(iocpu_get_platform_active_queue(), 0, 0U-1,
201 IOServicePlatformAction(void * refcon0
, void * refcon1
, uint32_t priority
,
202 void * param1
, void * param2
, void * param3
,
203 const char * service_name
)
206 IOService
* service
= (IOService
*) refcon0
;
207 const OSSymbol
* function
= (const OSSymbol
*) refcon1
;
209 kprintf("%s -> %s\n", function
->getCStringNoCopy(), service_name
);
211 ret
= service
->callPlatformFunction(function
, false,
212 (void *)(uintptr_t) priority
, param1
, param2
, param3
);
218 IOInstallServicePlatformAction(IOService
* service
,
219 const OSSymbol
* key
, queue_head_t
* queue
,
223 iocpu_platform_action_entry_t
* entry
;
226 num
= OSDynamicCast(OSNumber
, service
->getProperty(key
));
230 entry
= IONew(iocpu_platform_action_entry_t
, 1);
231 entry
->action
= &IOServicePlatformAction
;
232 entry
->name
= service
->getName();
233 priority
= num
->unsigned32BitValue();
235 entry
->priority
= -priority
;
237 entry
->priority
= priority
;
238 entry
->refcon0
= service
;
239 entry
->refcon1
= (void *) key
;
241 iocpu_add_platform_action(queue
, entry
);
242 entry
->alloc_list
= gIOAllActionsQueue
;
243 gIOAllActionsQueue
= entry
;
246 extern "C" kern_return_t
247 IOCPURunPlatformHaltRestartActions(uint32_t message
)
250 IORegistryIterator
* iter
;
254 if (!gIOHaltRestartActionQueue
.next
)
256 queue_init(&gIOHaltRestartActionQueue
);
257 iter
= IORegistryIterator::iterateOver(gIOServicePlane
,
258 kIORegistryIterateRecursively
);
264 if (all
) all
->release();
265 all
= iter
->iterateAll();
267 while (!iter
->isValid());
271 while((service
= (IOService
*) all
->getFirstObject()))
273 IOInstallServicePlatformAction(service
, gIOPlatformHaltRestartActionKey
, &gIOHaltRestartActionQueue
, false);
274 all
->removeObject(service
);
280 ret
= iocpu_run_platform_actions(&gIOHaltRestartActionQueue
, 0, 0U-1,
281 (void *)(uintptr_t) message
, NULL
, NULL
);
285 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
287 kern_return_t
PE_cpu_start(cpu_id_t target
,
288 vm_offset_t start_paddr
, vm_offset_t arg_paddr
)
290 IOCPU
*targetCPU
= OSDynamicCast(IOCPU
, (OSObject
*)target
);
292 if (targetCPU
== 0) return KERN_FAILURE
;
293 return targetCPU
->startCPU(start_paddr
, arg_paddr
);
296 void PE_cpu_halt(cpu_id_t target
)
298 IOCPU
*targetCPU
= OSDynamicCast(IOCPU
, (OSObject
*)target
);
300 if (targetCPU
) targetCPU
->haltCPU();
303 void PE_cpu_signal(cpu_id_t source
, cpu_id_t target
)
305 IOCPU
*sourceCPU
= OSDynamicCast(IOCPU
, (OSObject
*)source
);
306 IOCPU
*targetCPU
= OSDynamicCast(IOCPU
, (OSObject
*)target
);
308 if (sourceCPU
&& targetCPU
) sourceCPU
->signalCPU(targetCPU
);
311 void PE_cpu_machine_init(cpu_id_t target
, boolean_t bootb
)
313 IOCPU
*targetCPU
= OSDynamicCast(IOCPU
, (OSObject
*)target
);
315 if (targetCPU
) targetCPU
->initCPU(bootb
);
318 void PE_cpu_machine_quiesce(cpu_id_t target
)
320 IOCPU
*targetCPU
= OSDynamicCast(IOCPU
, (OSObject
*)target
);
322 if (targetCPU
) targetCPU
->quiesceCPU();
326 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
328 #define super IOService
330 OSDefineMetaClassAndAbstractStructors(IOCPU
, IOService
);
331 OSMetaClassDefineReservedUnused(IOCPU
, 0);
332 OSMetaClassDefineReservedUnused(IOCPU
, 1);
333 OSMetaClassDefineReservedUnused(IOCPU
, 2);
334 OSMetaClassDefineReservedUnused(IOCPU
, 3);
335 OSMetaClassDefineReservedUnused(IOCPU
, 4);
336 OSMetaClassDefineReservedUnused(IOCPU
, 5);
337 OSMetaClassDefineReservedUnused(IOCPU
, 6);
338 OSMetaClassDefineReservedUnused(IOCPU
, 7);
340 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
342 static OSArray
*gIOCPUs
;
343 static const OSSymbol
*gIOCPUStateKey
;
344 static OSString
*gIOCPUStateNames
[kIOCPUStateCount
];
346 void IOCPUSleepKernel(void)
350 IOCPU
*bootCPU
= NULL
;
351 IOPMrootDomain
*rootDomain
= IOService::getPMRootDomain();
353 kprintf("IOCPUSleepKernel\n");
355 IORegistryIterator
* iter
;
359 rootDomain
->tracePoint( kIOPMTracePointSleepPlatformActions
);
361 queue_init(&gIOSleepActionQueue
);
362 queue_init(&gIOWakeActionQueue
);
363 queue_init(&gIOHaltRestartActionQueue
);
365 iter
= IORegistryIterator::iterateOver( gIOServicePlane
,
366 kIORegistryIterateRecursively
);
374 all
= iter
->iterateAll();
376 while (!iter
->isValid());
381 while((service
= (IOService
*) all
->getFirstObject()))
383 IOInstallServicePlatformAction(service
, gIOPlatformSleepActionKey
, &gIOSleepActionQueue
, false);
384 IOInstallServicePlatformAction(service
, gIOPlatformWakeActionKey
, &gIOWakeActionQueue
, true);
385 IOInstallServicePlatformAction(service
, gIOPlatformQuiesceActionKey
, iocpu_get_platform_quiesce_queue(), false);
386 IOInstallServicePlatformAction(service
, gIOPlatformActiveActionKey
, iocpu_get_platform_active_queue(), true);
387 IOInstallServicePlatformAction(service
, gIOPlatformHaltRestartActionKey
, &gIOHaltRestartActionQueue
, false);
388 all
->removeObject(service
);
394 iocpu_run_platform_actions(&gIOSleepActionQueue
, 0, 0U-1,
397 rootDomain
->tracePoint( kIOPMTracePointSleepCPUs
);
399 numCPUs
= gIOCPUs
->getCount();
404 target
= OSDynamicCast(IOCPU
, gIOCPUs
->getObject(cnt
));
406 // We make certain that the bootCPU is the last to sleep
407 // We'll skip it for now, and halt it after finishing the
409 if (target
->getCPUNumber() == kBootCPUNumber
)
412 } else if (target
->getCPUState() == kIOCPUStateRunning
)
418 rootDomain
->tracePoint( kIOPMTracePointSleepPlatformDriver
);
420 // Now sleep the boot CPU.
424 rootDomain
->tracePoint( kIOPMTracePointWakePlatformActions
);
426 iocpu_run_platform_actions(&gIOWakeActionQueue
, 0, 0U-1,
429 iocpu_platform_action_entry_t
* entry
;
430 while ((entry
= gIOAllActionsQueue
))
432 gIOAllActionsQueue
= entry
->alloc_list
;
433 iocpu_remove_platform_action(entry
);
434 IODelete(entry
, iocpu_platform_action_entry_t
, 1);
437 if (!queue_empty(&gIOSleepActionQueue
)) panic("gIOSleepActionQueue");
438 if (!queue_empty(&gIOWakeActionQueue
)) panic("gIOWakeActionQueue");
439 if (!queue_empty(&gIOHaltRestartActionQueue
)) panic("gIOHaltRestartActionQueue");
440 gIOHaltRestartActionQueue
.next
= 0;
442 rootDomain
->tracePoint( kIOPMTracePointWakeCPUs
);
444 // Wake the other CPUs.
445 for (cnt
= 0; cnt
< numCPUs
; cnt
++)
447 target
= OSDynamicCast(IOCPU
, gIOCPUs
->getObject(cnt
));
449 // Skip the already-woken boot CPU.
450 if ((target
->getCPUNumber() != kBootCPUNumber
)
451 && (target
->getCPUState() == kIOCPUStateStopped
))
453 processor_start(target
->getMachProcessor());
458 void IOCPU::initCPUs(void)
461 gIOCPUs
= OSArray::withCapacity(1);
463 gIOCPUStateKey
= OSSymbol::withCStringNoCopy("IOCPUState");
465 gIOCPUStateNames
[kIOCPUStateUnregistered
] =
466 OSString::withCStringNoCopy("Unregistered");
467 gIOCPUStateNames
[kIOCPUStateUninitalized
] =
468 OSString::withCStringNoCopy("Uninitalized");
469 gIOCPUStateNames
[kIOCPUStateStopped
] =
470 OSString::withCStringNoCopy("Stopped");
471 gIOCPUStateNames
[kIOCPUStateRunning
] =
472 OSString::withCStringNoCopy("Running");
476 bool IOCPU::start(IOService
*provider
)
478 OSData
*busFrequency
, *cpuFrequency
, *timebaseFrequency
;
480 if (!super::start(provider
)) return false;
487 gIOCPUs
->setObject(this);
489 // Correct the bus, cpu and timebase frequencies in the device tree.
490 if (gPEClockFrequencyInfo
.bus_frequency_hz
< 0x100000000ULL
) {
491 busFrequency
= OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo
.bus_clock_rate_hz
, 4);
493 busFrequency
= OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo
.bus_frequency_hz
, 8);
495 provider
->setProperty("bus-frequency", busFrequency
);
496 busFrequency
->release();
498 if (gPEClockFrequencyInfo
.cpu_frequency_hz
< 0x100000000ULL
) {
499 cpuFrequency
= OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo
.cpu_clock_rate_hz
, 4);
501 cpuFrequency
= OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo
.cpu_frequency_hz
, 8);
503 provider
->setProperty("clock-frequency", cpuFrequency
);
504 cpuFrequency
->release();
506 timebaseFrequency
= OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo
.timebase_frequency_hz
, 4);
507 provider
->setProperty("timebase-frequency", timebaseFrequency
);
508 timebaseFrequency
->release();
510 super::setProperty("IOCPUID", getRegistryEntryID(), sizeof(uint64_t)*8);
513 setCPUState(kIOCPUStateUnregistered
);
518 OSObject
*IOCPU::getProperty(const OSSymbol
*aKey
) const
520 if (aKey
== gIOCPUStateKey
) return gIOCPUStateNames
[_cpuState
];
522 return super::getProperty(aKey
);
525 bool IOCPU::setProperty(const OSSymbol
*aKey
, OSObject
*anObject
)
529 if (aKey
== gIOCPUStateKey
) {
530 stateStr
= OSDynamicCast(OSString
, anObject
);
531 if (stateStr
== 0) return false;
533 if (_cpuNumber
== 0) return false;
535 if (stateStr
->isEqualTo("running")) {
536 if (_cpuState
== kIOCPUStateStopped
) {
537 processor_start(machProcessor
);
538 } else if (_cpuState
!= kIOCPUStateRunning
) {
541 } else if (stateStr
->isEqualTo("stopped")) {
542 if (_cpuState
== kIOCPUStateRunning
) {
544 } else if (_cpuState
!= kIOCPUStateStopped
) {
552 return super::setProperty(aKey
, anObject
);
555 bool IOCPU::serializeProperties(OSSerialize
*serialize
) const
558 OSDictionary
*dict
= dictionaryWithProperties();
559 dict
->setObject(gIOCPUStateKey
, gIOCPUStateNames
[_cpuState
]);
560 result
= dict
->serialize(serialize
);
565 IOReturn
IOCPU::setProperties(OSObject
*properties
)
567 OSDictionary
*dict
= OSDynamicCast(OSDictionary
, properties
);
571 if (dict
== 0) return kIOReturnUnsupported
;
573 stateStr
= OSDynamicCast(OSString
, dict
->getObject(gIOCPUStateKey
));
575 result
= IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator
);
576 if (result
!= kIOReturnSuccess
) return result
;
578 if (setProperty(gIOCPUStateKey
, stateStr
)) return kIOReturnSuccess
;
580 return kIOReturnUnsupported
;
583 return kIOReturnUnsupported
;
586 void IOCPU::signalCPU(IOCPU */
*target*/
)
590 void IOCPU::enableCPUTimeBase(bool /*enable*/)
594 UInt32
IOCPU::getCPUNumber(void)
599 void IOCPU::setCPUNumber(UInt32 cpuNumber
)
601 _cpuNumber
= cpuNumber
;
602 super::setProperty("IOCPUNumber", _cpuNumber
, 32);
605 UInt32
IOCPU::getCPUState(void)
610 void IOCPU::setCPUState(UInt32 cpuState
)
612 if (cpuState
< kIOCPUStateCount
) {
613 _cpuState
= cpuState
;
617 OSArray
*IOCPU::getCPUGroup(void)
622 UInt32
IOCPU::getCPUGroupSize(void)
624 return _cpuGroup
->getCount();
627 processor_t
IOCPU::getMachProcessor(void)
629 return machProcessor
;
633 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
636 #define super IOInterruptController
638 OSDefineMetaClassAndStructors(IOCPUInterruptController
, IOInterruptController
);
640 OSMetaClassDefineReservedUnused(IOCPUInterruptController
, 0);
641 OSMetaClassDefineReservedUnused(IOCPUInterruptController
, 1);
642 OSMetaClassDefineReservedUnused(IOCPUInterruptController
, 2);
643 OSMetaClassDefineReservedUnused(IOCPUInterruptController
, 3);
644 OSMetaClassDefineReservedUnused(IOCPUInterruptController
, 4);
645 OSMetaClassDefineReservedUnused(IOCPUInterruptController
, 5);
649 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
652 IOReturn
IOCPUInterruptController::initCPUInterruptController(int sources
)
656 if (!super::init()) return kIOReturnInvalid
;
660 cpus
= (IOCPU
**)IOMalloc(numCPUs
* sizeof(IOCPU
*));
661 if (cpus
== 0) return kIOReturnNoMemory
;
662 bzero(cpus
, numCPUs
* sizeof(IOCPU
*));
664 vectors
= (IOInterruptVector
*)IOMalloc(numCPUs
* sizeof(IOInterruptVector
));
665 if (vectors
== 0) return kIOReturnNoMemory
;
666 bzero(vectors
, numCPUs
* sizeof(IOInterruptVector
));
668 // Allocate locks for the
669 for (cnt
= 0; cnt
< numCPUs
; cnt
++) {
670 vectors
[cnt
].interruptLock
= IOLockAlloc();
671 if (vectors
[cnt
].interruptLock
== NULL
) {
672 for (cnt
= 0; cnt
< numCPUs
; cnt
++) {
673 if (vectors
[cnt
].interruptLock
!= NULL
)
674 IOLockFree(vectors
[cnt
].interruptLock
);
676 return kIOReturnNoResources
;
680 ml_init_max_cpus(numCPUs
);
682 return kIOReturnSuccess
;
685 void IOCPUInterruptController::registerCPUInterruptController(void)
689 getPlatform()->registerInterruptController(gPlatformInterruptControllerName
,
693 void IOCPUInterruptController::setCPUInterruptProperties(IOService
*service
)
701 if ((service
->getProperty(gIOInterruptControllersKey
) != 0) &&
702 (service
->getProperty(gIOInterruptSpecifiersKey
) != 0))
705 // Create the interrupt specifer array.
706 specifier
= OSArray::withCapacity(numCPUs
);
707 for (cnt
= 0; cnt
< numCPUs
; cnt
++) {
709 tmpData
= OSData::withBytes(&tmpLong
, sizeof(tmpLong
));
710 specifier
->setObject(tmpData
);
714 // Create the interrupt controller array.
715 controller
= OSArray::withCapacity(numCPUs
);
716 for (cnt
= 0; cnt
< numCPUs
; cnt
++) {
717 controller
->setObject(gPlatformInterruptControllerName
);
720 // Put the two arrays into the property table.
721 service
->setProperty(gIOInterruptControllersKey
, controller
);
722 service
->setProperty(gIOInterruptSpecifiersKey
, specifier
);
723 controller
->release();
724 specifier
->release();
727 void IOCPUInterruptController::enableCPUInterrupt(IOCPU
*cpu
)
729 IOInterruptHandler handler
= OSMemberFunctionCast(
730 IOInterruptHandler
, this, &IOCPUInterruptController::handleInterrupt
);
732 ml_install_interrupt_handler(cpu
, cpu
->getCPUNumber(), this, handler
, 0);
734 // Ensure that the increment is seen by all processors
735 OSIncrementAtomic(&enabledCPUs
);
737 if (enabledCPUs
== numCPUs
) thread_wakeup(this);
740 IOReturn
IOCPUInterruptController::registerInterrupt(IOService
*nub
,
743 IOInterruptHandler handler
,
746 IOInterruptVector
*vector
;
748 if (source
>= numCPUs
) return kIOReturnNoResources
;
750 vector
= &vectors
[source
];
752 // Get the lock for this vector.
753 IOTakeLock(vector
->interruptLock
);
755 // Make sure the vector is not in use.
756 if (vector
->interruptRegistered
) {
757 IOUnlock(vector
->interruptLock
);
758 return kIOReturnNoResources
;
761 // Fill in vector with the client's info.
762 vector
->handler
= handler
;
764 vector
->source
= source
;
765 vector
->target
= target
;
766 vector
->refCon
= refCon
;
768 // Get the vector ready. It starts hard disabled.
769 vector
->interruptDisabledHard
= 1;
770 vector
->interruptDisabledSoft
= 1;
771 vector
->interruptRegistered
= 1;
773 IOUnlock(vector
->interruptLock
);
775 if (enabledCPUs
!= numCPUs
) {
776 assert_wait(this, THREAD_UNINT
);
777 thread_block(THREAD_CONTINUE_NULL
);
780 return kIOReturnSuccess
;
783 IOReturn
IOCPUInterruptController::getInterruptType(IOService */
*nub*/
,
787 if (interruptType
== 0) return kIOReturnBadArgument
;
789 *interruptType
= kIOInterruptTypeLevel
;
791 return kIOReturnSuccess
;
794 IOReturn
IOCPUInterruptController::enableInterrupt(IOService */
*nub*/
,
797 // ml_set_interrupts_enabled(true);
798 return kIOReturnSuccess
;
801 IOReturn
IOCPUInterruptController::disableInterrupt(IOService */
*nub*/
,
804 // ml_set_interrupts_enabled(false);
805 return kIOReturnSuccess
;
808 IOReturn
IOCPUInterruptController::causeInterrupt(IOService */
*nub*/
,
811 ml_cause_interrupt();
812 return kIOReturnSuccess
;
815 IOReturn
IOCPUInterruptController::handleInterrupt(void */
*refCon*/
,
819 IOInterruptVector
*vector
;
821 vector
= &vectors
[source
];
823 if (!vector
->interruptRegistered
) return kIOReturnInvalid
;
825 vector
->handler(vector
->target
, vector
->refCon
,
826 vector
->nub
, vector
->source
);
828 return kIOReturnSuccess
;
831 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */