1/* 2 * Copyright (c) 1999-2000 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 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. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 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. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/* 29 * Copyright (c) 1999-2000 Apple Computer, Inc. All rights reserved. 30 * 31 * DRI: Josh de Cesare 32 * 33 */ 34 35extern "C" { 36#include <machine/machine_routines.h> 37#include <pexpert/pexpert.h> 38} 39 40#include <machine/machine_routines.h> 41 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> 48 49/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 50#include <kern/queue.h> 51 52typedef kern_return_t (*iocpu_platform_action_t)(void * refcon0, void * refcon1, uint32_t priority, 53 void * param1, void * param2, void * param3); 54 55struct iocpu_platform_action_entry 56{ 57 queue_chain_t link; 58 iocpu_platform_action_t action; 59 int32_t priority; 60 void * refcon0; 61 void * refcon1; 62 struct iocpu_platform_action_entry * alloc_list; 63}; 64typedef struct iocpu_platform_action_entry iocpu_platform_action_entry_t; 65 66queue_head_t * 67iocpu_get_platform_quiesce_queue(void); 68 69queue_head_t * 70iocpu_get_platform_active_queue(void); 71 72void 73iocpu_platform_cpu_action_init(queue_head_t * quiesce_queue, queue_head_t * init_queue); 74 75void 76iocpu_add_platform_action(queue_head_t * queue, iocpu_platform_action_entry_t * entry); 77 78void 79iocpu_remove_platform_action(iocpu_platform_action_entry_t * entry); 80 81kern_return_t 82iocpu_run_platform_actions(queue_head_t * queue, uint32_t first_priority, uint32_t last_priority, 83 void * param1, void * param2, void * param3); 84 85/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 86 87#define kBootCPUNumber 0 88 89static iocpu_platform_action_entry_t * gIOAllActionsQueue; 90static queue_head_t gIOSleepActionQueue; 91static queue_head_t gIOWakeActionQueue; 92 93static queue_head_t iocpu_quiesce_queue; 94static queue_head_t iocpu_active_queue; 95 96/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 97 98void 99iocpu_platform_cpu_action_init(queue_head_t * quiesce_queue, __unused queue_head_t * init_queue) 100{ 101#if 0 102 enum { kNumQuiesceActions = 2 }; 103 static iocpu_platform_action_entry_t quiesce_actions[kNumQuiesceActions] = 104 { 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 }, 107 }; 108 unsigned int idx; 109 110 for (idx = 0; idx < kNumQuiesceActions; idx++) 111 iocpu_add_platform_action(quiesce_queue, &quiesce_actions[idx]); 112#endif 113} 114 115queue_head_t * iocpu_get_platform_quiesce_queue(void) 116{ 117 if (!iocpu_quiesce_queue.next) 118 { 119 queue_init(&iocpu_quiesce_queue); 120 queue_init(&iocpu_active_queue); 121 iocpu_platform_cpu_action_init(&iocpu_quiesce_queue, &iocpu_active_queue); 122 } 123 return (&iocpu_quiesce_queue); 124} 125 126queue_head_t * iocpu_get_platform_active_queue(void) 127{ 128 return (&iocpu_active_queue); 129} 130 131void iocpu_add_platform_action(queue_head_t * queue, iocpu_platform_action_entry_t * entry) 132{ 133 iocpu_platform_action_entry_t * next; 134 135 queue_iterate(queue, next, iocpu_platform_action_entry_t *, link) 136 { 137 if (next->priority > entry->priority) 138 { 139 queue_insert_before(queue, entry, next, iocpu_platform_action_entry_t *, link); 140 return; 141 } 142 } 143 queue_enter(queue, entry, iocpu_platform_action_entry_t *, link); // at tail 144} 145 146void iocpu_remove_platform_action(iocpu_platform_action_entry_t * entry) 147{ 148 remque(&entry->link); 149} 150 151kern_return_t 152iocpu_run_platform_actions(queue_head_t * queue, uint32_t first_priority, uint32_t last_priority, 153 void * param1, void * param2, void * param3) 154{ 155 kern_return_t ret = KERN_SUCCESS; 156 kern_return_t result = KERN_SUCCESS; 157 iocpu_platform_action_entry_t * next; 158 159 queue_iterate(queue, next, iocpu_platform_action_entry_t *, link) 160 { 161 uint32_t pri = (next->priority < 0) ? -next->priority : next->priority; 162 if ((pri >= first_priority) && (pri <= last_priority)) 163 { 164 //kprintf("[%p]", next->action); 165 ret = (*next->action)(next->refcon0, next->refcon1, pri, param1, param2, param3); 166 } 167 if (KERN_SUCCESS == result) 168 result = ret; 169 } 170 return (result); 171} 172 173/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 174 175extern "C" kern_return_t 176IOCPURunPlatformQuiesceActions(void) 177{ 178 return (iocpu_run_platform_actions(iocpu_get_platform_quiesce_queue(), 0, 0UL-1, 179 NULL, NULL, NULL)); 180} 181 182extern "C" kern_return_t 183IOCPURunPlatformActiveActions(void) 184{ 185 return (iocpu_run_platform_actions(iocpu_get_platform_active_queue(), 0, 0UL-1, 186 NULL, NULL, NULL)); 187} 188 189static kern_return_t 190IOServicePlatformAction(void * refcon0, void * refcon1, uint32_t priority, 191 void * param1, void * param2, void * param3) 192{ 193 IOReturn ret; 194 IOService * service = (IOService *) refcon0; 195 const OSSymbol * function = (const OSSymbol *) refcon1; 196 197 kprintf("%s -> %s\n", function->getCStringNoCopy(), service->getName()); 198 199 ret = service->callPlatformFunction(function, false, 200 (void *) priority, param1, param2, param3); 201 202 return (ret); 203} 204 205static void 206IOInstallServicePlatformAction(IOService * service, 207 const OSSymbol * key, queue_head_t * queue, 208 bool reverse) 209{ 210 OSNumber * num; 211 iocpu_platform_action_entry_t * entry; 212 uint32_t priority; 213 214 num = OSDynamicCast(OSNumber, service->getProperty(key)); 215 if (!num) 216 return; 217 218 entry = IONew(iocpu_platform_action_entry_t, 1); 219 entry->action = &IOServicePlatformAction; 220 priority = num->unsigned32BitValue(); 221 if (reverse) 222 entry->priority = -priority; 223 else 224 entry->priority = priority; 225 entry->refcon0 = service; 226 entry->refcon1 = (void *) key; 227 228 iocpu_add_platform_action(queue, entry); 229 entry->alloc_list = gIOAllActionsQueue; 230 gIOAllActionsQueue = entry; 231} 232 233/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 234 235kern_return_t PE_cpu_start(cpu_id_t target, 236 vm_offset_t start_paddr, vm_offset_t arg_paddr) 237{ 238 IOCPU *targetCPU = OSDynamicCast(IOCPU, (OSObject *)target); 239 240 if (targetCPU == 0) return KERN_FAILURE; 241 return targetCPU->startCPU(start_paddr, arg_paddr); 242} 243 244void PE_cpu_halt(cpu_id_t target) 245{ 246 IOCPU *targetCPU = OSDynamicCast(IOCPU, (OSObject *)target); 247 248 if (targetCPU) targetCPU->haltCPU(); 249} 250 251void PE_cpu_signal(cpu_id_t source, cpu_id_t target) 252{ 253 IOCPU *sourceCPU = OSDynamicCast(IOCPU, (OSObject *)source); 254 IOCPU *targetCPU = OSDynamicCast(IOCPU, (OSObject *)target); 255 256 if (sourceCPU && targetCPU) sourceCPU->signalCPU(targetCPU); 257} 258 259void PE_cpu_machine_init(cpu_id_t target, boolean_t bootb) 260{ 261 IOCPU *targetCPU = OSDynamicCast(IOCPU, (OSObject *)target); 262 263 if (targetCPU) targetCPU->initCPU(bootb); 264} 265 266void PE_cpu_machine_quiesce(cpu_id_t target) 267{ 268 IOCPU *targetCPU = OSDynamicCast(IOCPU, (OSObject *)target); 269 270 if (targetCPU) targetCPU->quiesceCPU(); 271} 272 273 274/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 275 276#define super IOService 277 278OSDefineMetaClassAndAbstractStructors(IOCPU, IOService); 279OSMetaClassDefineReservedUnused(IOCPU, 0); 280OSMetaClassDefineReservedUnused(IOCPU, 1); 281OSMetaClassDefineReservedUnused(IOCPU, 2); 282OSMetaClassDefineReservedUnused(IOCPU, 3); 283OSMetaClassDefineReservedUnused(IOCPU, 4); 284OSMetaClassDefineReservedUnused(IOCPU, 5); 285OSMetaClassDefineReservedUnused(IOCPU, 6); 286OSMetaClassDefineReservedUnused(IOCPU, 7); 287 288/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 289 290static OSArray *gIOCPUs; 291static const OSSymbol *gIOCPUStateKey; 292static OSString *gIOCPUStateNames[kIOCPUStateCount]; 293 294void IOCPUSleepKernel(void) 295{ 296 long cnt, numCPUs; 297 IOCPU *target; 298 IOCPU *bootCPU = NULL; 299 300 kprintf("IOCPUSleepKernel\n"); 301 302 OSIterator * iter; 303 IOService * service; 304 305 queue_init(&gIOSleepActionQueue); 306 queue_init(&gIOWakeActionQueue); 307 308 iter = IORegistryIterator::iterateOver( gIOServicePlane, 309 kIORegistryIterateRecursively ); 310 if( iter) 311 { 312 do 313 { 314 iter->reset(); 315 while((service = (IOService *) iter->getNextObject())) 316 { 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); 321 } 322 } 323 while( !service && !iter->isValid()); 324 iter->release(); 325 } 326 327 iocpu_run_platform_actions(&gIOSleepActionQueue, 0, 0UL-1, 328 NULL, NULL, NULL); 329 330 numCPUs = gIOCPUs->getCount(); 331 // Sleep the CPUs. 332 cnt = numCPUs; 333 while (cnt--) 334 { 335 target = OSDynamicCast(IOCPU, gIOCPUs->getObject(cnt)); 336 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 339 // non-boot CPU's. 340 if (target->getCPUNumber() == kBootCPUNumber) 341 { 342 bootCPU = target; 343 } else if (target->getCPUState() == kIOCPUStateRunning) 344 { 345 target->haltCPU(); 346 } 347 } 348 349 // Now sleep the boot CPU. 350 if (bootCPU) 351 bootCPU->haltCPU(); 352 353 iocpu_run_platform_actions(&gIOWakeActionQueue, 0, 0UL-1, 354 NULL, NULL, NULL); 355 356 iocpu_platform_action_entry_t * entry; 357 while ((entry = gIOAllActionsQueue)) 358 { 359 gIOAllActionsQueue = entry->alloc_list; 360 iocpu_remove_platform_action(entry); 361 IODelete(entry, iocpu_platform_action_entry_t, 1); 362 } 363 364 if (!queue_empty(&gIOSleepActionQueue)) 365 IOPanic("gIOSleepActionQueue"); 366 if (!queue_empty(&gIOWakeActionQueue)) 367 IOPanic("gIOWakeActionQueue"); 368 369 // Wake the other CPUs. 370 for (cnt = 0; cnt < numCPUs; cnt++) 371 { 372 target = OSDynamicCast(IOCPU, gIOCPUs->getObject(cnt)); 373 374 // Skip the already-woken boot CPU. 375 if ((target->getCPUNumber() != kBootCPUNumber) 376 && (target->getCPUState() == kIOCPUStateStopped)) 377 { 378 processor_start(target->getMachProcessor()); 379 } 380 } 381} 382 383void IOCPU::initCPUs(void) 384{ 385 if (gIOCPUs == 0) { 386 gIOCPUs = OSArray::withCapacity(1); 387 388 gIOCPUStateKey = OSSymbol::withCStringNoCopy("IOCPUState"); 389 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"); 398 } 399} 400 401bool IOCPU::start(IOService *provider) 402{ 403 OSData *busFrequency, *cpuFrequency, *timebaseFrequency; 404 405 if (!super::start(provider)) return false; 406 407 initCPUs(); 408 409 _cpuGroup = gIOCPUs; 410 cpuNub = provider; 411 412 gIOCPUs->setObject(this); 413 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); 417 } else { 418 busFrequency = OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo.bus_frequency_hz, 8); 419 } 420 provider->setProperty("bus-frequency", busFrequency); 421 busFrequency->release(); 422 423 if (gPEClockFrequencyInfo.cpu_frequency_hz < 0x100000000ULL) { 424 cpuFrequency = OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo.cpu_clock_rate_hz, 4); 425 } else { 426 cpuFrequency = OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo.cpu_frequency_hz, 8); 427 } 428 provider->setProperty("clock-frequency", cpuFrequency); 429 cpuFrequency->release(); 430 431 timebaseFrequency = OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo.timebase_frequency_hz, 4); 432 provider->setProperty("timebase-frequency", timebaseFrequency); 433 timebaseFrequency->release(); 434 435 super::setProperty("IOCPUID", (UInt32)this, 32); 436 437 setCPUNumber(0); 438 setCPUState(kIOCPUStateUnregistered); 439 440 return true; 441} 442 443OSObject *IOCPU::getProperty(const OSSymbol *aKey) const 444{ 445 if (aKey == gIOCPUStateKey) return gIOCPUStateNames[_cpuState]; 446 447 return super::getProperty(aKey); 448} 449 450bool IOCPU::setProperty(const OSSymbol *aKey, OSObject *anObject) 451{ 452 OSString *stateStr; 453 454 if (aKey == gIOCPUStateKey) { 455 stateStr = OSDynamicCast(OSString, anObject); 456 if (stateStr == 0) return false; 457 458 if (_cpuNumber == 0) return false; 459 460 if (stateStr->isEqualTo("running")) { 461 if (_cpuState == kIOCPUStateStopped) { 462 processor_start(machProcessor); 463 } else if (_cpuState != kIOCPUStateRunning) { 464 return false; 465 } 466 } else if (stateStr->isEqualTo("stopped")) { 467 if (_cpuState == kIOCPUStateRunning) { 468 haltCPU(); 469 } else if (_cpuState != kIOCPUStateStopped) { 470 return false; 471 } 472 } else return false; 473 474 return true; 475 } 476 477 return super::setProperty(aKey, anObject); 478} 479 480bool IOCPU::serializeProperties(OSSerialize *serialize) const 481{ 482 bool result; 483 OSDictionary *dict = dictionaryWithProperties(); 484 dict->setObject(gIOCPUStateKey, gIOCPUStateNames[_cpuState]); 485 result = dict->serialize(serialize); 486 dict->release(); 487 return result; 488} 489 490IOReturn IOCPU::setProperties(OSObject *properties) 491{ 492 OSDictionary *dict = OSDynamicCast(OSDictionary, properties); 493 OSString *stateStr; 494 IOReturn result; 495 496 if (dict == 0) return kIOReturnUnsupported; 497 498 stateStr = OSDynamicCast(OSString, dict->getObject(gIOCPUStateKey)); 499 if (stateStr != 0) { 500 result = IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator); 501 if (result != kIOReturnSuccess) return result; 502 503 if (setProperty(gIOCPUStateKey, stateStr)) return kIOReturnSuccess; 504 505 return kIOReturnUnsupported; 506 } 507 508 return kIOReturnUnsupported; 509} 510 511void IOCPU::signalCPU(IOCPU */*target*/) 512{ 513} 514 515void IOCPU::enableCPUTimeBase(bool /*enable*/) 516{ 517} 518 519UInt32 IOCPU::getCPUNumber(void) 520{ 521 return _cpuNumber; 522} 523 524void IOCPU::setCPUNumber(UInt32 cpuNumber) 525{ 526 _cpuNumber = cpuNumber; 527 super::setProperty("IOCPUNumber", _cpuNumber, 32); 528} 529 530UInt32 IOCPU::getCPUState(void) 531{ 532 return _cpuState; 533} 534 535void IOCPU::setCPUState(UInt32 cpuState) 536{ 537 if (cpuState < kIOCPUStateCount) { 538 _cpuState = cpuState; 539 } 540} 541 542OSArray *IOCPU::getCPUGroup(void) 543{ 544 return _cpuGroup; 545} 546 547UInt32 IOCPU::getCPUGroupSize(void) 548{ 549 return _cpuGroup->getCount(); 550} 551 552processor_t IOCPU::getMachProcessor(void) 553{ 554 return machProcessor; 555} 556 557 558/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 559 560#undef super 561#define super IOInterruptController 562 563OSDefineMetaClassAndStructors(IOCPUInterruptController, IOInterruptController); 564 565OSMetaClassDefineReservedUnused(IOCPUInterruptController, 0); 566OSMetaClassDefineReservedUnused(IOCPUInterruptController, 1); 567OSMetaClassDefineReservedUnused(IOCPUInterruptController, 2); 568OSMetaClassDefineReservedUnused(IOCPUInterruptController, 3); 569OSMetaClassDefineReservedUnused(IOCPUInterruptController, 4); 570OSMetaClassDefineReservedUnused(IOCPUInterruptController, 5); 571 572 573 574/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 575 576 577IOReturn IOCPUInterruptController::initCPUInterruptController(int sources) 578{ 579 int cnt; 580 581 if (!super::init()) return kIOReturnInvalid; 582 583 numCPUs = sources; 584 585 cpus = (IOCPU **)IOMalloc(numCPUs * sizeof(IOCPU *)); 586 if (cpus == 0) return kIOReturnNoMemory; 587 bzero(cpus, numCPUs * sizeof(IOCPU *)); 588 589 vectors = (IOInterruptVector *)IOMalloc(numCPUs * sizeof(IOInterruptVector)); 590 if (vectors == 0) return kIOReturnNoMemory; 591 bzero(vectors, numCPUs * sizeof(IOInterruptVector)); 592 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); 600 } 601 return kIOReturnNoResources; 602 } 603 } 604 605 ml_init_max_cpus(numCPUs); 606 607 return kIOReturnSuccess; 608} 609 610void IOCPUInterruptController::registerCPUInterruptController(void) 611{ 612 registerService(); 613 614 getPlatform()->registerInterruptController(gPlatformInterruptControllerName, 615 this); 616} 617 618void IOCPUInterruptController::setCPUInterruptProperties(IOService *service) 619{ 620 int cnt; 621 OSArray *controller; 622 OSArray *specifier; 623 OSData *tmpData; 624 long tmpLong; 625 626 if ((service->getProperty(gIOInterruptControllersKey) != 0) && 627 (service->getProperty(gIOInterruptSpecifiersKey) != 0)) 628 return; 629 630 // Create the interrupt specifer array. 631 specifier = OSArray::withCapacity(numCPUs); 632 for (cnt = 0; cnt < numCPUs; cnt++) { 633 tmpLong = cnt; 634 tmpData = OSData::withBytes(&tmpLong, sizeof(tmpLong)); 635 specifier->setObject(tmpData); 636 tmpData->release(); 637 }; 638 639 // Create the interrupt controller array. 640 controller = OSArray::withCapacity(numCPUs); 641 for (cnt = 0; cnt < numCPUs; cnt++) { 642 controller->setObject(gPlatformInterruptControllerName); 643 } 644 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(); 650} 651 652void IOCPUInterruptController::enableCPUInterrupt(IOCPU *cpu) 653{ 654 IOInterruptHandler handler = OSMemberFunctionCast( 655 IOInterruptHandler, this, &IOCPUInterruptController::handleInterrupt); 656 657 ml_install_interrupt_handler(cpu, cpu->getCPUNumber(), this, handler, 0); 658 659 enabledCPUs++; 660 661 if (enabledCPUs == numCPUs) thread_wakeup(this); 662} 663 664IOReturn IOCPUInterruptController::registerInterrupt(IOService *nub, 665 int source, 666 void *target, 667 IOInterruptHandler handler, 668 void *refCon) 669{ 670 IOInterruptVector *vector; 671 672 if (source >= numCPUs) return kIOReturnNoResources; 673 674 vector = &vectors[source]; 675 676 // Get the lock for this vector. 677 IOTakeLock(vector->interruptLock); 678 679 // Make sure the vector is not in use. 680 if (vector->interruptRegistered) { 681 IOUnlock(vector->interruptLock); 682 return kIOReturnNoResources; 683 } 684 685 // Fill in vector with the client's info. 686 vector->handler = handler; 687 vector->nub = nub; 688 vector->source = source; 689 vector->target = target; 690 vector->refCon = refCon; 691 692 // Get the vector ready. It starts hard disabled. 693 vector->interruptDisabledHard = 1; 694 vector->interruptDisabledSoft = 1; 695 vector->interruptRegistered = 1; 696 697 IOUnlock(vector->interruptLock); 698 699 if (enabledCPUs != numCPUs) { 700 assert_wait(this, THREAD_UNINT); 701 thread_block(THREAD_CONTINUE_NULL); 702 } 703 704 return kIOReturnSuccess; 705} 706 707IOReturn IOCPUInterruptController::getInterruptType(IOService */*nub*/, 708 int /*source*/, 709 int *interruptType) 710{ 711 if (interruptType == 0) return kIOReturnBadArgument; 712 713 *interruptType = kIOInterruptTypeLevel; 714 715 return kIOReturnSuccess; 716} 717 718IOReturn IOCPUInterruptController::enableInterrupt(IOService */*nub*/, 719 int /*source*/) 720{ 721// ml_set_interrupts_enabled(true); 722 return kIOReturnSuccess; 723} 724 725IOReturn IOCPUInterruptController::disableInterrupt(IOService */*nub*/, 726 int /*source*/) 727{ 728// ml_set_interrupts_enabled(false); 729 return kIOReturnSuccess; 730} 731 732IOReturn IOCPUInterruptController::causeInterrupt(IOService */*nub*/, 733 int /*source*/) 734{ 735 ml_cause_interrupt(); 736 return kIOReturnSuccess; 737} 738 739IOReturn IOCPUInterruptController::handleInterrupt(void */*refCon*/, 740 IOService */*nub*/, 741 int source) 742{ 743 IOInterruptVector *vector; 744 745 vector = &vectors[source]; 746 747 if (!vector->interruptRegistered) return kIOReturnInvalid; 748 749 vector->handler(vector->target, vector->refCon, 750 vector->nub, vector->source); 751 752 return kIOReturnSuccess; 753} 754 755/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 756