ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

ppc_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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.