Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenppc_irq.c
Go to the documentation of this file.
00001 /* $Id$ 00002 * 00003 * COPYRIGHT: See COPYING in the top level directory 00004 * PROJECT: ReactOS kernel 00005 * FILE: ntoskrnl/ke/i386/irq.c 00006 * PURPOSE: IRQ handling 00007 * 00008 * PROGRAMMERS: David Welch (welch@mcmail.com) 00009 */ 00010 00011 /* 00012 * NOTE: In general the PIC interrupt priority facilities are used to 00013 * preserve the NT IRQL semantics, global interrupt disables are only used 00014 * to keep the PIC in a consistent state 00015 * 00016 */ 00017 00018 /* INCLUDES ****************************************************************/ 00019 00020 #include <ntoskrnl.h> 00021 #include <ppcmmu/mmu.h> 00022 00023 #define NDEBUG 00024 #include <debug.h> 00025 00026 KDPC KiExpireTimerDpc; 00027 extern ULONG KiMaximumDpcQueueDepth; 00028 extern ULONG KiMinimumDpcRate; 00029 extern ULONG KiAdjustDpcThreshold; 00030 extern ULONG KiIdealDpcRate; 00031 extern LONG KiTickOffset; 00032 extern ULONG KeMaximumIncrement; 00033 extern ULONG KeMinimumIncrement; 00034 extern ULONG KeTimeAdjustment; 00035 00036 extern void PearPCDebug(int ch); 00037 00038 /* GLOBALS *****************************************************************/ 00039 00040 /* Interrupt handler list */ 00041 00042 #define NR_TRAPS 16 00043 #ifdef CONFIG_SMP 00044 00045 #define INT_NAME2(intnum) KiUnexpectedInterrupt##intnum 00046 00047 #define BUILD_INTERRUPT_HANDLER(intnum) \ 00048 VOID INT_NAME2(intnum)(VOID); 00049 00050 #define D(x,y) \ 00051 BUILD_INTERRUPT_HANDLER(x##y) 00052 00053 #define D16(x) \ 00054 D(x,0) D(x,1) D(x,2) D(x,3) \ 00055 D(x,4) D(x,5) D(x,6) D(x,7) \ 00056 D(x,8) D(x,9) D(x,A) D(x,B) \ 00057 D(x,C) D(x,D) D(x,E) D(x,F) 00058 00059 D16(3) D16(4) D16(5) D16(6) 00060 D16(7) D16(8) D16(9) D16(A) 00061 D16(B) D16(C) D16(D) D16(E) 00062 D16(F) 00063 00064 #define L(x,y) \ 00065 (ULONG)& INT_NAME2(x##y) 00066 00067 #define L16(x) \ 00068 L(x,0), L(x,1), L(x,2), L(x,3), \ 00069 L(x,4), L(x,5), L(x,6), L(x,7), \ 00070 L(x,8), L(x,9), L(x,A), L(x,B), \ 00071 L(x,C), L(x,D), L(x,E), L(x,F) 00072 00073 static ULONG irq_handler[ROUND_UP(NR_TRAPS, 16)] = { 00074 L16(3), L16(4), L16(5), L16(6), 00075 L16(7), L16(8), L16(9), L16(A), 00076 L16(B), L16(C), L16(D), L16(E) 00077 }; 00078 00079 #undef L 00080 #undef L16 00081 #undef D 00082 #undef D16 00083 00084 #else /* CONFIG_SMP */ 00085 00086 void trap_handler_0(void); 00087 void trap_handler_1(void); 00088 void trap_handler_2(void); 00089 void trap_handler_3(void); 00090 void trap_handler_4(void); 00091 void trap_handler_5(void); 00092 void trap_handler_6(void); 00093 void trap_handler_7(void); 00094 void trap_handler_8(void); 00095 void trap_handler_9(void); 00096 void trap_handler_10(void); 00097 void trap_handler_11(void); 00098 void trap_handler_12(void); 00099 void trap_handler_13(void); 00100 void trap_handler_14(void); 00101 void trap_handler_15(void); 00102 00103 static unsigned int trap_handler[NR_TRAPS] __attribute__((unused)) = 00104 { 00105 (int)&trap_handler_0, 00106 (int)&trap_handler_1, 00107 (int)&trap_handler_2, 00108 (int)&trap_handler_3, 00109 (int)&trap_handler_4, 00110 (int)&trap_handler_5, 00111 (int)&trap_handler_6, 00112 (int)&trap_handler_7, 00113 (int)&trap_handler_8, 00114 (int)&trap_handler_9, 00115 (int)&trap_handler_10, 00116 (int)&trap_handler_11, 00117 (int)&trap_handler_12, 00118 (int)&trap_handler_13, 00119 (int)&trap_handler_14, 00120 (int)&trap_handler_15, 00121 }; 00122 00123 #endif /* CONFIG_SMP */ 00124 00125 /* 00126 * PURPOSE: Object describing each isr 00127 * NOTE: The data in this table is only modified at passsive level but can 00128 * be accessed at any irq level. 00129 */ 00130 00131 typedef struct 00132 { 00133 LIST_ENTRY ListHead; 00134 KSPIN_LOCK Lock; 00135 ULONG Count; 00136 } 00137 ISR_TABLE, *PISR_TABLE; 00138 00139 #ifdef CONFIG_SMP 00140 static ISR_TABLE IsrTable[NR_TRAPS][MAXIMUM_PROCESSORS]; 00141 #else 00142 static ISR_TABLE IsrTable[NR_TRAPS][1]; 00143 #endif 00144 00145 #define TAG_ISR_LOCK 'LRSI' 00146 00147 /* FUNCTIONS ****************************************************************/ 00148 00149 VOID 00150 INIT_FUNCTION 00151 NTAPI 00152 KeInitInterrupts (VOID) 00153 { 00154 int i, j; 00155 00156 /* 00157 * Setup the IDT entries to point to the interrupt handlers 00158 */ 00159 for (i=0;i<NR_TRAPS;i++) 00160 { 00161 #ifdef CONFIG_SMP 00162 for (j = 0; j < MAXIMUM_PROCESSORS; j++) 00163 #else 00164 j = 0; 00165 #endif 00166 { 00167 InitializeListHead(&IsrTable[i][j].ListHead); 00168 KeInitializeSpinLock(&IsrTable[i][j].Lock); 00169 IsrTable[i][j].Count = 0; 00170 } 00171 } 00172 } 00173 00174 static VOID 00175 KeIRQTrapFrameToTrapFrame(PKIRQ_TRAPFRAME IrqTrapFrame, 00176 PKTRAP_FRAME TrapFrame) 00177 { 00178 } 00179 00180 static VOID 00181 KeTrapFrameToIRQTrapFrame(PKTRAP_FRAME TrapFrame, 00182 PKIRQ_TRAPFRAME IrqTrapFrame) 00183 { 00184 } 00185 00186 /* 00187 * NOTE: On Windows this function takes exactly one parameter and EBP is 00188 * guaranteed to point to KTRAP_FRAME. The function is used only 00189 * by HAL, so there's no point in keeping that prototype. 00190 * 00191 * @implemented 00192 */ 00193 VOID 00194 NTAPI 00195 KeUpdateRunTime(IN PKTRAP_FRAME TrapFrame, 00196 IN KIRQL Irql) 00197 { 00198 PKPRCB Prcb = KeGetCurrentPrcb(); 00199 PKTHREAD CurrentThread; 00200 PKPROCESS CurrentProcess; 00201 00202 /* Make sure we don't go further if we're in early boot phase. */ 00203 if (!(Prcb) || !(Prcb->CurrentThread)) return; 00204 00205 /* Get the current thread and process */ 00206 CurrentThread = Prcb->CurrentThread; 00207 CurrentProcess = CurrentThread->ApcState.Process; 00208 00209 /* Check if we came from user mode */ 00210 if (TrapFrame->PreviousMode != KernelMode) 00211 { 00212 /* Update user times */ 00213 CurrentThread->UserTime++; 00214 InterlockedIncrement((PLONG)&CurrentProcess->UserTime); 00215 Prcb->UserTime++; 00216 } 00217 else 00218 { 00219 /* Check IRQ */ 00220 if (Irql > DISPATCH_LEVEL) 00221 { 00222 /* This was an interrupt */ 00223 Prcb->InterruptTime++; 00224 } 00225 else if ((Irql < DISPATCH_LEVEL) || !(Prcb->DpcRoutineActive)) 00226 { 00227 /* This was normal kernel time */ 00228 CurrentThread->KernelTime++; 00229 InterlockedIncrement((PLONG)&CurrentProcess->KernelTime); 00230 } 00231 else if (Irql == DISPATCH_LEVEL) 00232 { 00233 /* This was DPC time */ 00234 Prcb->DpcTime++; 00235 } 00236 00237 /* Update CPU kernel time in all cases */ 00238 Prcb->KernelTime++; 00239 } 00240 00241 /* Set the last DPC Count and request rate */ 00242 Prcb->DpcLastCount = Prcb->DpcData[0].DpcCount; 00243 Prcb->DpcRequestRate = ((Prcb->DpcData[0].DpcCount - Prcb->DpcLastCount) + 00244 Prcb->DpcRequestRate) / 2; 00245 00246 /* Check if we should request a DPC */ 00247 if ((Prcb->DpcData[0].DpcQueueDepth) && !(Prcb->DpcRoutineActive)) 00248 { 00249 /* Request one */ 00250 HalRequestSoftwareInterrupt(DISPATCH_LEVEL); 00251 00252 /* Update the depth if needed */ 00253 if ((Prcb->DpcRequestRate < KiIdealDpcRate) && 00254 (Prcb->MaximumDpcQueueDepth > 1)) 00255 { 00256 /* Decrease the maximum depth by one */ 00257 Prcb->MaximumDpcQueueDepth--; 00258 } 00259 } 00260 else 00261 { 00262 /* Decrease the adjustment threshold */ 00263 if (!(--Prcb->AdjustDpcThreshold)) 00264 { 00265 /* We've hit 0, reset it */ 00266 Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold; 00267 00268 /* Check if we've hit queue maximum */ 00269 if (KiMaximumDpcQueueDepth != Prcb->MaximumDpcQueueDepth) 00270 { 00271 /* Increase maximum by one */ 00272 Prcb->MaximumDpcQueueDepth++; 00273 } 00274 } 00275 } 00276 00277 /* 00278 * If we're at end of quantum request software interrupt. The rest 00279 * is handled in KiDispatchInterrupt. 00280 * 00281 * NOTE: If one stays at DISPATCH_LEVEL for a long time the DPC routine 00282 * which checks for quantum end will not be executed and decrementing 00283 * the quantum here can result in overflow. This is not a problem since 00284 * we don't care about the quantum value anymore after the QuantumEnd 00285 * flag is set. 00286 */ 00287 if ((CurrentThread->Quantum -= 3) <= 0) 00288 { 00289 Prcb->QuantumEnd = TRUE; 00290 HalRequestSoftwareInterrupt(DISPATCH_LEVEL); 00291 } 00292 } 00293 00294 00295 /* 00296 * NOTE: On Windows this function takes exactly zero parameters and EBP is 00297 * guaranteed to point to KTRAP_FRAME. Also [esp+0] contains an IRQL. 00298 * The function is used only by HAL, so there's no point in keeping 00299 * that prototype. 00300 * 00301 * @implemented 00302 */ 00303 VOID 00304 NTAPI 00305 KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame, 00306 IN KIRQL Irql, 00307 IN ULONG Increment) 00308 { 00309 LONG OldOffset; 00310 LARGE_INTEGER Time; 00311 ASSERT(KeGetCurrentIrql() == PROFILE_LEVEL); 00312 00313 /* Update interrupt time */ 00314 Time.LowPart = SharedUserData->InterruptTime.LowPart; 00315 Time.HighPart = SharedUserData->InterruptTime.High1Time; 00316 Time.QuadPart += Increment; 00317 SharedUserData->InterruptTime.High2Time = Time.u.HighPart; 00318 SharedUserData->InterruptTime.LowPart = Time.u.LowPart; 00319 SharedUserData->InterruptTime.High1Time = Time.u.HighPart; 00320 00321 /* Increase the tick offset */ 00322 KiTickOffset -= Increment; 00323 OldOffset = KiTickOffset; 00324 00325 /* Check if this isn't a tick yet */ 00326 if (KiTickOffset > 0) 00327 { 00328 /* Expire timers */ 00329 KeInsertQueueDpc(&KiExpireTimerDpc, 0, 0); 00330 } 00331 else 00332 { 00333 /* Setup time structure for system time */ 00334 Time.LowPart = SharedUserData->SystemTime.LowPart; 00335 Time.HighPart = SharedUserData->SystemTime.High1Time; 00336 Time.QuadPart += KeTimeAdjustment; 00337 SharedUserData->SystemTime.High2Time = Time.HighPart; 00338 SharedUserData->SystemTime.LowPart = Time.LowPart; 00339 SharedUserData->SystemTime.High1Time = Time.HighPart; 00340 00341 /* Setup time structure for tick time */ 00342 Time.LowPart = KeTickCount.LowPart; 00343 Time.HighPart = KeTickCount.High1Time; 00344 Time.QuadPart += 1; 00345 KeTickCount.High2Time = Time.HighPart; 00346 KeTickCount.LowPart = Time.LowPart; 00347 KeTickCount.High1Time = Time.HighPart; 00348 SharedUserData->TickCount.High2Time = Time.HighPart; 00349 SharedUserData->TickCount.LowPart = Time.LowPart; 00350 SharedUserData->TickCount.High1Time = Time.HighPart; 00351 00352 /* Queue a DPC that will expire timers */ 00353 KeInsertQueueDpc(&KiExpireTimerDpc, 0, 0); 00354 } 00355 00356 /* Update process and thread times */ 00357 if (OldOffset <= 0) 00358 { 00359 /* This was a tick, calculate the next one */ 00360 KiTickOffset += KeMaximumIncrement; 00361 KeUpdateRunTime(TrapFrame, Irql); 00362 } 00363 } 00364 00365 VOID NTAPI 00366 KiInterruptDispatch2 (ULONG vector, KIRQL old_level) 00367 /* 00368 * FUNCTION: Calls all the interrupt handlers for a given irq. 00369 * ARGUMENTS: 00370 * vector - The number of the vector to call handlers for. 00371 * old_level - The irql of the processor when the irq took place. 00372 * NOTES: Must be called at DIRQL. 00373 */ 00374 { 00375 PKINTERRUPT isr; 00376 PLIST_ENTRY current; 00377 KIRQL oldlvl; 00378 PISR_TABLE CurrentIsr; 00379 00380 DPRINT("I(0x%.08x, 0x%.08x)\n", vector, old_level); 00381 00382 /* 00383 * Iterate the list until one of the isr tells us its device interrupted 00384 */ 00385 CurrentIsr = &IsrTable[vector][(ULONG)KeGetCurrentProcessorNumber()]; 00386 00387 KiAcquireSpinLock(&CurrentIsr->Lock); 00388 00389 CurrentIsr->Count++; 00390 current = CurrentIsr->ListHead.Flink; 00391 00392 while (current != &CurrentIsr->ListHead) 00393 { 00394 isr = CONTAINING_RECORD(current,KINTERRUPT,InterruptListEntry); 00395 oldlvl = KeAcquireInterruptSpinLock(isr); 00396 if (isr->ServiceRoutine(isr, isr->ServiceContext)) 00397 { 00398 KeReleaseInterruptSpinLock(isr, oldlvl); 00399 break; 00400 } 00401 KeReleaseInterruptSpinLock(isr, oldlvl); 00402 current = current->Flink; 00403 } 00404 KiReleaseSpinLock(&CurrentIsr->Lock); 00405 } 00406 00407 VOID 00408 KiInterruptDispatch3 (ULONG vector, PKIRQ_TRAPFRAME Trapframe) 00409 /* 00410 * FUNCTION: Calls the irq specific handler for an irq 00411 * ARGUMENTS: 00412 * irq = IRQ that has interrupted 00413 */ 00414 { 00415 KIRQL old_level; 00416 KTRAP_FRAME KernelTrapFrame; 00417 PKTHREAD CurrentThread; 00418 PKTRAP_FRAME OldTrapFrame=NULL; 00419 00420 /* 00421 * At this point we have interrupts disabled, nothing has been done to 00422 * the PIC. 00423 */ 00424 00425 KeGetCurrentPrcb()->InterruptCount++; 00426 00427 /* 00428 * Notify the rest of the kernel of the raised irq level. For the 00429 * default HAL this will send an EOI to the PIC and alter the IRQL. 00430 */ 00431 if (!HalBeginSystemInterrupt (vector, 00432 vector, 00433 &old_level)) 00434 { 00435 return; 00436 } 00437 00438 00439 /* 00440 * Enable interrupts 00441 * NOTE: Only higher priority interrupts will get through 00442 */ 00443 _enable(); 00444 00445 #ifndef CONFIG_SMP 00446 if (vector == 0) 00447 { 00448 KeIRQTrapFrameToTrapFrame(Trapframe, &KernelTrapFrame); 00449 KeUpdateSystemTime(&KernelTrapFrame, old_level, 100000); 00450 } 00451 else 00452 #endif 00453 { 00454 /* 00455 * Actually call the ISR. 00456 */ 00457 KiInterruptDispatch2(vector, old_level); 00458 } 00459 00460 /* 00461 * End the system interrupt. 00462 */ 00463 _disable(); 00464 00465 if (old_level==PASSIVE_LEVEL) 00466 { 00467 HalEndSystemInterrupt (APC_LEVEL, 0); 00468 00469 CurrentThread = KeGetCurrentThread(); 00470 if (CurrentThread!=NULL && CurrentThread->ApcState.UserApcPending) 00471 { 00472 if (CurrentThread->TrapFrame == NULL) 00473 { 00474 OldTrapFrame = CurrentThread->TrapFrame; 00475 KeIRQTrapFrameToTrapFrame(Trapframe, &KernelTrapFrame); 00476 CurrentThread->TrapFrame = &KernelTrapFrame; 00477 } 00478 00479 _enable(); 00480 KiDeliverApc(UserMode, NULL, NULL); 00481 _disable(); 00482 00483 ASSERT(KeGetCurrentThread() == CurrentThread); 00484 if (CurrentThread->TrapFrame == &KernelTrapFrame) 00485 { 00486 KeTrapFrameToIRQTrapFrame(&KernelTrapFrame, Trapframe); 00487 CurrentThread->TrapFrame = OldTrapFrame; 00488 } 00489 } 00490 KeLowerIrql(PASSIVE_LEVEL); 00491 } 00492 else 00493 { 00494 HalEndSystemInterrupt (old_level, 0); 00495 } 00496 00497 } 00498 00499 static VOID 00500 KeDumpIrqList(VOID) 00501 { 00502 PKINTERRUPT current; 00503 PLIST_ENTRY current_entry; 00504 LONG i, j; 00505 KIRQL oldlvl; 00506 BOOLEAN printed; 00507 00508 for (i=0;i<NR_TRAPS;i++) 00509 { 00510 printed = FALSE; 00511 KeRaiseIrql(i,&oldlvl); 00512 00513 for (j=0; j < KeNumberProcessors; j++) 00514 { 00515 KiAcquireSpinLock(&IsrTable[i][j].Lock); 00516 00517 current_entry = IsrTable[i][j].ListHead.Flink; 00518 current = CONTAINING_RECORD(current_entry,KINTERRUPT,InterruptListEntry); 00519 while (current_entry!=&(IsrTable[i][j].ListHead)) 00520 { 00521 if (printed == FALSE) 00522 { 00523 printed = TRUE; 00524 DPRINT("For irq %x:\n",i); 00525 } 00526 DPRINT(" Isr %x\n",current); 00527 current_entry = current_entry->Flink; 00528 current = CONTAINING_RECORD(current_entry,KINTERRUPT,InterruptListEntry); 00529 } 00530 KiReleaseSpinLock(&IsrTable[i][j].Lock); 00531 } 00532 KeLowerIrql(oldlvl); 00533 } 00534 } 00535 00536 /* 00537 * @implemented 00538 */ 00539 BOOLEAN 00540 NTAPI 00541 KeConnectInterrupt(PKINTERRUPT InterruptObject) 00542 { 00543 KIRQL oldlvl,synch_oldlvl; 00544 PKINTERRUPT ListHead; 00545 ULONG Vector; 00546 PISR_TABLE CurrentIsr; 00547 BOOLEAN Result; 00548 00549 DPRINT("KeConnectInterrupt()\n"); 00550 00551 Vector = InterruptObject->Vector; 00552 00553 if (Vector < 0 || Vector >= NR_TRAPS) 00554 return FALSE; 00555 00556 ASSERT (InterruptObject->Number < KeNumberProcessors); 00557 00558 KeSetSystemAffinityThread(1 << InterruptObject->Number); 00559 00560 CurrentIsr = &IsrTable[Vector][(ULONG)InterruptObject->Number]; 00561 00562 KeRaiseIrql(Vector,&oldlvl); 00563 KiAcquireSpinLock(&CurrentIsr->Lock); 00564 00565 /* 00566 * Check if the vector is already in use that we can share it 00567 */ 00568 if (!IsListEmpty(&CurrentIsr->ListHead)) 00569 { 00570 ListHead = CONTAINING_RECORD(CurrentIsr->ListHead.Flink,KINTERRUPT,InterruptListEntry); 00571 if (InterruptObject->ShareVector == FALSE || ListHead->ShareVector==FALSE) 00572 { 00573 KiReleaseSpinLock(&CurrentIsr->Lock); 00574 KeLowerIrql(oldlvl); 00575 KeRevertToUserAffinityThread(); 00576 return FALSE; 00577 } 00578 } 00579 00580 synch_oldlvl = KeAcquireInterruptSpinLock(InterruptObject); 00581 00582 DPRINT("%x %x\n",CurrentIsr->ListHead.Flink, CurrentIsr->ListHead.Blink); 00583 00584 Result = HalEnableSystemInterrupt(Vector, InterruptObject->Irql, InterruptObject->Mode); 00585 if (Result) 00586 { 00587 InsertTailList(&CurrentIsr->ListHead,&InterruptObject->InterruptListEntry); 00588 DPRINT("%x %x\n",InterruptObject->InterruptListEntry.Flink, InterruptObject->InterruptListEntry.Blink); 00589 } 00590 00591 InterruptObject->Connected = TRUE; 00592 KeReleaseInterruptSpinLock(InterruptObject, synch_oldlvl); 00593 00594 /* 00595 * Release the table spinlock 00596 */ 00597 KiReleaseSpinLock(&CurrentIsr->Lock); 00598 KeLowerIrql(oldlvl); 00599 00600 KeDumpIrqList(); 00601 00602 KeRevertToUserAffinityThread(); 00603 00604 return Result; 00605 } 00606 00607 /* 00608 * @implemented 00609 * 00610 * FUNCTION: Releases a drivers isr 00611 * ARGUMENTS: 00612 * InterruptObject = isr to release 00613 */ 00614 BOOLEAN 00615 NTAPI 00616 KeDisconnectInterrupt(PKINTERRUPT InterruptObject) 00617 { 00618 KIRQL oldlvl,synch_oldlvl; 00619 PISR_TABLE CurrentIsr; 00620 BOOLEAN State; 00621 00622 DPRINT1("KeDisconnectInterrupt\n"); 00623 ASSERT (InterruptObject->Number < KeNumberProcessors); 00624 00625 /* Set the affinity */ 00626 KeSetSystemAffinityThread(1 << InterruptObject->Number); 00627 00628 /* Get the ISR Tabe */ 00629 CurrentIsr = &IsrTable[InterruptObject->Vector] 00630 [(ULONG)InterruptObject->Number]; 00631 00632 /* Raise IRQL to required level and lock table */ 00633 KeRaiseIrql(InterruptObject->Vector,&oldlvl); 00634 KiAcquireSpinLock(&CurrentIsr->Lock); 00635 00636 /* Check if it's actually connected */ 00637 if ((State = InterruptObject->Connected)) 00638 { 00639 /* Lock the Interrupt */ 00640 synch_oldlvl = KeAcquireInterruptSpinLock(InterruptObject); 00641 00642 /* Remove this one, and check if all are gone */ 00643 RemoveEntryList(&InterruptObject->InterruptListEntry); 00644 if (IsListEmpty(&CurrentIsr->ListHead)) 00645 { 00646 /* Completely Disable the Interrupt */ 00647 HalDisableSystemInterrupt(InterruptObject->Vector, InterruptObject->Irql); 00648 } 00649 00650 /* Disconnect it */ 00651 InterruptObject->Connected = FALSE; 00652 00653 /* Release the interrupt lock */ 00654 KeReleaseInterruptSpinLock(InterruptObject, synch_oldlvl); 00655 } 00656 /* Release the table spinlock */ 00657 KiReleaseSpinLock(&CurrentIsr->Lock); 00658 KeLowerIrql(oldlvl); 00659 00660 /* Go back to default affinity */ 00661 KeRevertToUserAffinityThread(); 00662 00663 /* Return Old Interrupt State */ 00664 return State; 00665 } 00666 00667 /* 00668 * @implemented 00669 */ 00670 VOID 00671 NTAPI 00672 KeInitializeInterrupt(PKINTERRUPT Interrupt, 00673 PKSERVICE_ROUTINE ServiceRoutine, 00674 PVOID ServiceContext, 00675 PKSPIN_LOCK SpinLock, 00676 ULONG Vector, 00677 KIRQL Irql, 00678 KIRQL SynchronizeIrql, 00679 KINTERRUPT_MODE InterruptMode, 00680 BOOLEAN ShareVector, 00681 CHAR ProcessorNumber, 00682 BOOLEAN FloatingSave) 00683 { 00684 /* Set the Interrupt Header */ 00685 Interrupt->Type = InterruptObject; 00686 Interrupt->Size = sizeof(KINTERRUPT); 00687 00688 /* Check if we got a spinlock */ 00689 if (SpinLock) 00690 { 00691 Interrupt->ActualLock = SpinLock; 00692 } 00693 else 00694 { 00695 /* This means we'll be usin the built-in one */ 00696 KeInitializeSpinLock(&Interrupt->SpinLock); 00697 Interrupt->ActualLock = &Interrupt->SpinLock; 00698 } 00699 00700 /* Set the other settings */ 00701 Interrupt->ServiceRoutine = ServiceRoutine; 00702 Interrupt->ServiceContext = ServiceContext; 00703 Interrupt->Vector = Vector; 00704 Interrupt->Irql = Irql; 00705 Interrupt->SynchronizeIrql = SynchronizeIrql; 00706 Interrupt->Mode = InterruptMode; 00707 Interrupt->ShareVector = ShareVector; 00708 Interrupt->Number = ProcessorNumber; 00709 Interrupt->FloatingSave = FloatingSave; 00710 00711 /* Disconnect it at first */ 00712 Interrupt->Connected = FALSE; 00713 } 00714 00715 VOID KePrintInterruptStatistic(VOID) 00716 { 00717 LONG i, j; 00718 00719 for (j = 0; j < KeNumberProcessors; j++) 00720 { 00721 DPRINT1("CPU%d:\n", j); 00722 for (i = 0; i < NR_TRAPS; i++) 00723 { 00724 if (IsrTable[i][j].Count) 00725 { 00726 DPRINT1(" Irq %x(%d): %d\n", i, i, IsrTable[i][j].Count); 00727 } 00728 } 00729 } 00730 } 00731 00732 BOOLEAN 00733 NTAPI 00734 KeDisableInterrupts(VOID) 00735 { 00736 ULONG Flags = 0; 00737 BOOLEAN Return; 00738 00739 Flags = __readmsr(); 00740 Return = (Flags & 0x8000) ? TRUE: FALSE; 00741 00742 /* Disable interrupts */ 00743 _disable(); 00744 return Return; 00745 } 00746 00747 ULONG 00748 NTAPI 00749 KdpServiceDispatcher(ULONG Service, PCHAR Buffer, ULONG Length); 00750 00751 typedef ULONG (*PSYSCALL_FUN) 00752 (ULONG,ULONG,ULONG,ULONG,ULONG,ULONG,ULONG,ULONG,ULONG,ULONG); 00753 00754 VOID 00755 NTAPI 00756 KiSystemService(ppc_trap_frame_t *trap_frame) 00757 { 00758 int i; 00759 PKSYSTEM_ROUTINE SystemRoutine; 00760 PSYSCALL_FUN SyscallFunction; 00761 00762 switch(trap_frame->gpr[0]) 00763 { 00764 case 0x10000: /* DebugService */ 00765 for( i = 0; i < trap_frame->gpr[5]; i++ ) 00766 { 00767 PearPCDebug(((PCHAR)trap_frame->gpr[4])[i]); 00768 WRITE_PORT_UCHAR((PVOID)0x800003f8, ((PCHAR)trap_frame->gpr[4])[i]); 00769 } 00770 trap_frame->gpr[3] = KdpServiceDispatcher 00771 (trap_frame->gpr[3], 00772 (PCHAR)trap_frame->gpr[4], 00773 trap_frame->gpr[5]); 00774 break; 00775 case 0xf0000: /* Thread startup */ 00776 /* XXX how to use UserThread (gpr[6]) */ 00777 SystemRoutine = (PKSYSTEM_ROUTINE)trap_frame->gpr[3]; 00778 SystemRoutine((PKSTART_ROUTINE)trap_frame->gpr[4], 00779 (PVOID)trap_frame->gpr[5]); 00780 break; 00781 00782 /* Handle a normal system call */ 00783 default: 00784 SyscallFunction = 00785 ((PSYSCALL_FUN*)KeServiceDescriptorTable 00786 [trap_frame->gpr[0] >> 12].Base)[trap_frame->gpr[0] & 0xfff]; 00787 trap_frame->gpr[3] = SyscallFunction 00788 (trap_frame->gpr[3], 00789 trap_frame->gpr[4], 00790 trap_frame->gpr[5], 00791 trap_frame->gpr[6], 00792 trap_frame->gpr[7], 00793 trap_frame->gpr[8], 00794 trap_frame->gpr[9], 00795 trap_frame->gpr[10], 00796 trap_frame->gpr[11], 00797 trap_frame->gpr[12]); 00798 break; 00799 } 00800 } 00801 00802 /* EOF */ Generated on Sat May 26 2012 04:36:20 for ReactOS by
1.7.6.1
|