The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/iokit/Kernel/IOCPU.cpp

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 64e93dbaa491d02186c957c7a33499c5


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.