|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * DRI: Josh de Cesare
5: *
6: */
7:
8: extern "C" {
9: #include <machine/machine_routines.h>
10: #include <pexpert/pexpert.h>
11: }
12:
13: #include <IOKit/IOLib.h>
14: #include <IOKit/IOPlatformExpert.h>
15: #include <IOKit/IOCPU.h>
16:
17:
18: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
19:
20: kern_return_t PE_cpu_start(cpu_id_t target,
21: vm_offset_t start_paddr, vm_offset_t arg_paddr)
22: {
23: IOCPU *targetCPU = OSDynamicCast(IOCPU, (OSObject *)target);
24:
25: if (targetCPU == 0) return KERN_FAILURE;
26: return targetCPU->startCPU(start_paddr, arg_paddr);
27: }
28:
29: void PE_cpu_halt(cpu_id_t target,
30: vm_offset_t start_paddr, vm_offset_t arg_paddr)
31: {
32: IOCPU *targetCPU = OSDynamicCast(IOCPU, (OSObject *)target);
33:
34: if (targetCPU) targetCPU->haltCPU(start_paddr, arg_paddr);
35: }
36:
37: void PE_cpu_signal(cpu_id_t source, cpu_id_t target)
38: {
39: IOCPU *sourceCPU = OSDynamicCast(IOCPU, (OSObject *)source);
40: IOCPU *targetCPU = OSDynamicCast(IOCPU, (OSObject *)target);
41:
42: if (sourceCPU && targetCPU) sourceCPU->signalCPU(targetCPU);
43: }
44:
45: void PE_cpu_machine_init(cpu_id_t target)
46: {
47: IOCPU *targetCPU = OSDynamicCast(IOCPU, (OSObject *)target);
48:
49: if (targetCPU) targetCPU->initCPU();
50: }
51:
52:
53: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
54:
55: #define super IOService
56:
57: OSDefineMetaClass(IOCPU, IOService);
58: OSDefineAbstractStructors(IOCPU, IOService);
59:
60: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
61:
62: static OSDictionary *gIOCPUs;
63:
64: void IOCPU::initCPUs(void)
65: {
66: gIOCPUs = OSDictionary::withCapacity(1);
67: }
68:
69: bool IOCPU::start(IOService *provider)
70: {
71: if (!super::start(provider)) return false;
72:
73: cpuGroup = gIOCPUs;
74: cpuNub = provider;
75:
76: cpuState = kIOCPUStateUnregistered;
77:
78: return true;
79: }
80:
81: void IOCPU::initCPU(void)
82: {
83: // Do default interrupt stuff.
84:
85:
86: cpuState = kIOCPUStateRunning;
87: }
88:
89: kern_return_t IOCPU::startCPU(vm_offset_t /*start_paddr*/,
90: vm_offset_t /*arg_paddr*/)
91: {
92: return KERN_FAILURE;
93: }
94:
95: void IOCPU::haltCPU(vm_offset_t /*start_paddr*/,
96: vm_offset_t /*arg_paddr*/)
97: {
98: }
99:
100: void IOCPU::signalCPU(IOCPU */*target*/)
101: {
102: }
103:
104: int IOCPU::getCPUNumber(void)
105: {
106: return physCPU;
107: }
108:
109: int IOCPU::getCPUState(void)
110: {
111: return cpuState;
112: }
113:
114: OSDictionary *IOCPU::getCPUGroup(void)
115: {
116: return cpuGroup;
117: }
118:
119: int IOCPU::getCPUGroupSize(void)
120: {
121: return cpuGroup->getCount();
122: }
123:
124: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
125:
126: #undef super
127: #define super IOInterruptController
128:
129: OSDefineMetaClassAndStructors(IOCPUInterruptController, IOInterruptController);
130:
131: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
132:
133:
134: IOReturn IOCPUInterruptController::initCPUInterruptController(int sources)
135: {
136: int cnt;
137:
138: if (!super::init()) return kIOReturnInvalid;
139:
140: numCPUs = sources;
141:
142: cpus = (IOCPU **)IOMalloc(numCPUs * sizeof(IOCPU *));
143: if (cpus == 0) return kIOReturnNoMemory;
144: bzero(cpus, numCPUs * sizeof(IOCPU *));
145:
146: vectors = (IOInterruptVector *)IOMalloc(numCPUs * sizeof(IOInterruptVector));
147: if (vectors == 0) return kIOReturnNoMemory;
148: bzero(vectors, numCPUs * sizeof(IOInterruptVector));
149:
150: // Allocate locks for the
151: for (cnt = 0; cnt < numCPUs; cnt++) {
152: vectors[cnt].interruptLock = IOLockAlloc();
153: if (vectors[cnt].interruptLock == NULL) {
154: for (cnt = 0; cnt < numCPUs; cnt++) {
155: if (vectors[cnt].interruptLock != NULL)
156: IOLockFree(vectors[cnt].interruptLock);
157: }
158: return kIOReturnNoResources;
159: }
160: }
161:
162: return kIOReturnSuccess;
163: }
164:
165: void IOCPUInterruptController::registerCPUInterruptController(void)
166: {
167: registerService();
168:
169: getPlatform()->registerInterruptController(gPlatformInterruptControllerName,
170: this);
171: }
172:
173: void IOCPUInterruptController::setCPUInterruptProperties(IOService *service)
174: {
175: int cnt;
176: OSArray *controller;
177: OSArray *specifier;
178: OSData *tmpData;
179: long tmpLong;
180:
181: // Create the interrupt specifer array.
182: specifier = OSArray::withCapacity(numCPUs);
183: for (cnt = 0; cnt < numCPUs; cnt++) {
184: tmpLong = cnt;
185: tmpData = OSData::withBytes(&tmpLong, sizeof(tmpLong));
186: specifier->setObject(tmpData);
187: tmpData->release();
188: };
189:
190: // Create the interrupt controller array.
191: controller = OSArray::withCapacity(numCPUs);
192: for (cnt = 0; cnt < numCPUs; cnt++) {
193: controller->setObject(gPlatformInterruptControllerName);
194: }
195:
196: // Put the two arrays into the property table.
197: service->setProperty(gIOInterruptControllersKey, controller);
198: service->setProperty(gIOInterruptSpecifiersKey, specifier);
199: controller->release();
200: specifier->release();
201: }
202:
203: void IOCPUInterruptController::enableCPUInterrupt(IOCPU *cpu)
204: {
205: ml_install_interrupt_handler(cpu, cpu->getCPUNumber(), this,
206: (IOInterruptHandler)&IOCPUInterruptController::handleInterrupt, 0);
207:
208: enabledCPUs++;
209:
210: if (enabledCPUs == numCPUs) thread_wakeup(this);
211: }
212:
213: IOReturn IOCPUInterruptController::registerInterrupt(IOService *nub,
214: int source,
215: void *target,
216: IOInterruptHandler handler,
217: void *refCon)
218: {
219: IOInterruptVector *vector;
220:
221: if (source >= numCPUs) return kIOReturnNoResources;
222:
223: vector = &vectors[source];
224:
225: // Get the lock for this vector.
226: IOTakeLock(vector->interruptLock);
227:
228: // Make sure the vector is not in use.
229: if (vector->interruptRegistered) {
230: IOUnlock(vector->interruptLock);
231: return kIOReturnNoResources;
232: }
233:
234: // Fill in vector with the client's info.
235: vector->handler = handler;
236: vector->nub = nub;
237: vector->source = source;
238: vector->target = target;
239: vector->refCon = refCon;
240:
241: // Get the vector ready. It starts hard disabled.
242: vector->interruptDisabledHard = 1;
243: vector->interruptDisabledSoft = 1;
244: vector->interruptRegistered = 1;
245:
246: IOUnlock(vector->interruptLock);
247:
248: if (enabledCPUs != numCPUs) {
249: assert_wait(this, THREAD_UNINT);
250: thread_block(0);
251: }
252:
253: return kIOReturnSuccess;
254: }
255:
256: IOReturn IOCPUInterruptController::getInterruptType(IOService */*nub*/,
257: int /*source*/,
258: int *interruptType)
259: {
260: if (interruptType == 0) return kIOReturnBadArgument;
261:
262: *interruptType = kIOInterruptTypeLevel;
263:
264: return kIOReturnSuccess;
265: }
266:
267: IOReturn IOCPUInterruptController::enableInterrupt(IOService */*nub*/,
268: int /*source*/)
269: {
270: // ml_set_interrupts_enabled(true);
271: return kIOReturnSuccess;
272: }
273:
274: IOReturn IOCPUInterruptController::disableInterrupt(IOService */*nub*/,
275: int /*source*/)
276: {
277: // ml_set_interrupts_enabled(false);
278: return kIOReturnSuccess;
279: }
280:
281: IOReturn IOCPUInterruptController::causeInterrupt(IOService */*nub*/,
282: int /*source*/)
283: {
284: ml_cause_interrupt();
285: return kIOReturnSuccess;
286: }
287:
288: IOReturn IOCPUInterruptController::handleInterrupt(void */*refCon*/,
289: IOService */*nub*/,
290: int source)
291: {
292: IOInterruptVector *vector;
293:
294: vector = &vectors[source];
295:
296: if (!vector->interruptRegistered) return kIOReturnInvalid;
297:
298: vector->handler(vector->target, vector->refCon,
299: vector->nub, vector->source);
300:
301: return kIOReturnSuccess;
302: }
303:
304: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.