irq.c

来自「一个类似windows」· C语言 代码 · 共 586 行 · 第 1/2 页

C
586
字号
      KeIRQTrapFrameToTrapFrame(Trapframe, &KernelTrapFrame);
      KeUpdateSystemTime(&KernelTrapFrame, old_level);
   }
   else
#endif
   {
     /*
      * Actually call the ISR.
      */
     KiInterruptDispatch2(vector, old_level);
   }

   /*
    * End the system interrupt.
    */
   Ke386DisableInterrupts();

   if (old_level==PASSIVE_LEVEL && Trapframe->Cs != KGDT_R0_CODE)
     {
       HalEndSystemInterrupt (APC_LEVEL, 0);

       CurrentThread = KeGetCurrentThread();
       if (CurrentThread!=NULL && CurrentThread->ApcState.UserApcPending)
         {
           DPRINT("PID: %d, TID: %d CS %04x/%04x\n",
                  ((PETHREAD)CurrentThread)->ThreadsProcess->UniqueProcessId,
                  ((PETHREAD)CurrentThread)->Cid.UniqueThread,
                  Trapframe->Cs,
                  CurrentThread->TrapFrame ? CurrentThread->TrapFrame->Cs : 0);
           if (CurrentThread->TrapFrame == NULL)
             {
               OldTrapFrame = CurrentThread->TrapFrame;
               KeIRQTrapFrameToTrapFrame(Trapframe, &KernelTrapFrame);
               CurrentThread->TrapFrame = &KernelTrapFrame;
             }

           Ke386EnableInterrupts();
           KiDeliverApc(UserMode, NULL, NULL);
           Ke386DisableInterrupts();

           ASSERT(KeGetCurrentThread() == CurrentThread);
           if (CurrentThread->TrapFrame == &KernelTrapFrame)
             {
               KeTrapFrameToIRQTrapFrame(&KernelTrapFrame, Trapframe);
               CurrentThread->TrapFrame = OldTrapFrame;
             }
         }
       KeLowerIrql(PASSIVE_LEVEL);
     }
   else
     {
       HalEndSystemInterrupt (old_level, 0);
     }

}

static VOID
KeDumpIrqList(VOID)
{
   PKINTERRUPT current;
   PLIST_ENTRY current_entry;
   LONG i, j;
   KIRQL oldlvl;
   BOOLEAN printed;

   for (i=0;i<NR_IRQS;i++)
     {
        printed = FALSE;
        KeRaiseIrql(VECTOR2IRQL(i + IRQ_BASE),&oldlvl);

        for (j=0; j < KeNumberProcessors; j++)
          {
            KiAcquireSpinLock(&IsrTable[i][j].Lock);

            current_entry = IsrTable[i][j].ListHead.Flink;
            current = CONTAINING_RECORD(current_entry,KINTERRUPT,InterruptListEntry);
            while (current_entry!=&(IsrTable[i][j].ListHead))
              {
                if (printed == FALSE)
                  {
                    printed = TRUE;
                    DPRINT("For irq %x:\n",i);
                  }
                DPRINT("   Isr %x\n",current);
                current_entry = current_entry->Flink;
                current = CONTAINING_RECORD(current_entry,KINTERRUPT,InterruptListEntry);
              }
            KiReleaseSpinLock(&IsrTable[i][j].Lock);
          }
        KeLowerIrql(oldlvl);
     }
}

/*
 * @implemented
 */
BOOLEAN 
STDCALL
KeConnectInterrupt(PKINTERRUPT InterruptObject)
{
   KIRQL oldlvl,synch_oldlvl;
   PKINTERRUPT ListHead;
   ULONG Vector;
   PISR_TABLE CurrentIsr;
   BOOLEAN Result;

   DPRINT("KeConnectInterrupt()\n");

   Vector = InterruptObject->Vector;

   if (Vector < IRQ_BASE || Vector >= IRQ_BASE + NR_IRQS)
      return FALSE;

   Vector -= IRQ_BASE;

   ASSERT (InterruptObject->Number < KeNumberProcessors);

   KeSetSystemAffinityThread(1 << InterruptObject->Number);

   CurrentIsr = &IsrTable[Vector][(ULONG)InterruptObject->Number];

   KeRaiseIrql(VECTOR2IRQL(Vector + IRQ_BASE),&oldlvl);
   KiAcquireSpinLock(&CurrentIsr->Lock);

   /*
    * Check if the vector is already in use that we can share it
    */
   if (!IsListEmpty(&CurrentIsr->ListHead))
   {
      ListHead = CONTAINING_RECORD(CurrentIsr->ListHead.Flink,KINTERRUPT,InterruptListEntry);
      if (InterruptObject->ShareVector == FALSE || ListHead->ShareVector==FALSE)
      {
         KiReleaseSpinLock(&CurrentIsr->Lock);
         KeLowerIrql(oldlvl);
         KeRevertToUserAffinityThread();
         return FALSE;
      }
   }

   synch_oldlvl = KeAcquireInterruptSpinLock(InterruptObject);

   DPRINT("%x %x\n",CurrentIsr->ListHead.Flink, CurrentIsr->ListHead.Blink);

   Result = HalEnableSystemInterrupt(Vector + IRQ_BASE, InterruptObject->Irql, InterruptObject->Mode);
   if (Result)
   {
      InsertTailList(&CurrentIsr->ListHead,&InterruptObject->InterruptListEntry);
      DPRINT("%x %x\n",InterruptObject->InterruptListEntry.Flink, InterruptObject->InterruptListEntry.Blink);
   }

   InterruptObject->Connected = TRUE;
   KeReleaseInterruptSpinLock(InterruptObject, synch_oldlvl);

   /*
    * Release the table spinlock
    */
   KiReleaseSpinLock(&CurrentIsr->Lock);
   KeLowerIrql(oldlvl);

   KeDumpIrqList();

   KeRevertToUserAffinityThread();

   return Result;
}

/*
 * @implemented
 *
 * FUNCTION: Releases a drivers isr
 * ARGUMENTS:
 *        InterruptObject = isr to release
 */
BOOLEAN 
STDCALL
KeDisconnectInterrupt(PKINTERRUPT InterruptObject)
{
    KIRQL oldlvl,synch_oldlvl;
    PISR_TABLE CurrentIsr;
    BOOLEAN State;

    DPRINT1("KeDisconnectInterrupt\n");
    ASSERT (InterruptObject->Number < KeNumberProcessors);

    /* Set the affinity */
    KeSetSystemAffinityThread(1 << InterruptObject->Number);

    /* Get the ISR Tabe */
    CurrentIsr = &IsrTable[InterruptObject->Vector - IRQ_BASE]
                          [(ULONG)InterruptObject->Number];

    /* Raise IRQL to required level and lock table */
    KeRaiseIrql(VECTOR2IRQL(InterruptObject->Vector),&oldlvl);
    KiAcquireSpinLock(&CurrentIsr->Lock);

    /* Check if it's actually connected */
    if ((State = InterruptObject->Connected))
    {
        /* Lock the Interrupt */
        synch_oldlvl = KeAcquireInterruptSpinLock(InterruptObject);

        /* Remove this one, and check if all are gone */
        RemoveEntryList(&InterruptObject->InterruptListEntry);
        if (IsListEmpty(&CurrentIsr->ListHead))
        {
            /* Completely Disable the Interrupt */
            HalDisableSystemInterrupt(InterruptObject->Vector, InterruptObject->Irql);
        }
        
        /* Disconnect it */
        InterruptObject->Connected = FALSE;
    
        /* Release the interrupt lock */
        KeReleaseInterruptSpinLock(InterruptObject, synch_oldlvl);
    }
    /* Release the table spinlock */
    KiReleaseSpinLock(&CurrentIsr->Lock);
    KeLowerIrql(oldlvl);

    /* Go back to default affinity */
    KeRevertToUserAffinityThread();
    
    /* Return Old Interrupt State */
    return State;
}

/*
 * @implemented
 */
VOID
STDCALL
KeInitializeInterrupt(PKINTERRUPT Interrupt,
                      PKSERVICE_ROUTINE ServiceRoutine,
                      PVOID ServiceContext,
                      PKSPIN_LOCK SpinLock,
                      ULONG Vector,
                      KIRQL Irql,
                      KIRQL SynchronizeIrql,
                      KINTERRUPT_MODE InterruptMode,
                      BOOLEAN ShareVector,
                      CHAR ProcessorNumber,
                      BOOLEAN FloatingSave)
{
    /* Set the Interrupt Header */
    Interrupt->Type = InterruptObject;
    Interrupt->Size = sizeof(KINTERRUPT);
    
    /* Check if we got a spinlock */
    if (SpinLock)
    {
        Interrupt->ActualLock = SpinLock;
    }
    else
    {
        /* This means we'll be usin the built-in one */
        KeInitializeSpinLock(&Interrupt->SpinLock);
        Interrupt->ActualLock = &Interrupt->SpinLock;
    }
    
    /* Set the other settings */
    Interrupt->ServiceRoutine = ServiceRoutine;
    Interrupt->ServiceContext = ServiceContext;
    Interrupt->Vector = Vector;
    Interrupt->Irql = Irql;
    Interrupt->SynchronizeIrql = SynchronizeIrql;
    Interrupt->Mode = InterruptMode;
    Interrupt->ShareVector = ShareVector;
    Interrupt->Number = ProcessorNumber;
    Interrupt->FloatingSave = FloatingSave;
    
    /* Disconnect it at first */
    Interrupt->Connected = FALSE;
}

VOID KePrintInterruptStatistic(VOID)
{
   LONG i, j;

   for (j = 0; j < KeNumberProcessors; j++)
   {
      DPRINT1("CPU%d:\n", j);
      for (i = 0; i < NR_IRQS; i++)
      {
         if (IsrTable[i][j].Count)
         {
             DPRINT1("  Irq %x(%d): %d\n", i, VECTOR2IRQ(i + IRQ_BASE), IsrTable[i][j].Count);
         }
      }
   }
}

/* EOF */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?