⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ioapic.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 2 页
字号:
         {
            /* Mask timer IRQ */
            entry.mask = 1;
         }

         if ((apic == 0) && (irq < 16))
	 {
	    Disable8259AIrq(irq);
	 }
         IOAPICWrite(apic, IOAPIC_REDTBL+2*pin+1, *(((PULONG)&entry)+1));
	 IOAPICWrite(apic, IOAPIC_REDTBL+2*pin, *(((PULONG)&entry)+0));

	 IrqApicMap[irq] = apic;

	 DPRINT("Vector %x, Pin %x, Irq %x\n", vector, pin, irq);
      }
   }
}

static VOID 
IOAPICClearPin(ULONG Apic, ULONG Pin)
{
   IOAPIC_ROUTE_ENTRY Entry;

   DPRINT("IOAPICClearPin(Apic %d, Pin %d\n", Apic, Pin);
   /*
    * Disable it in the IO-APIC irq-routing table
    */
   memset(&Entry, 0, sizeof(Entry));
   Entry.mask = 1;

   IOAPICWrite(Apic, IOAPIC_REDTBL + 2 * Pin, *(((PULONG)&Entry) + 0));
   IOAPICWrite(Apic, IOAPIC_REDTBL + 1 + 2 * Pin, *(((PULONG)&Entry) + 1));
}

static VOID 
IOAPICClear(ULONG Apic)
{
   ULONG Pin;

   for (Pin = 0; Pin < /*IOAPICMap[Apic].EntryCount*/24; Pin++)
   {
     IOAPICClearPin(Apic, Pin);
   }
}

static VOID 
IOAPICClearAll(VOID)
{
   ULONG Apic;

   for (Apic = 0; Apic < IOAPICCount; Apic++)
   {
      IOAPICClear(Apic);
   }
}

VOID 
IOAPICEnable(VOID)
{
   ULONG i, tmp;

   /* Setup IRQ to vector translation map */
   memset(&IRQVectorMap, 0, sizeof(IRQVectorMap));

   /*
    * The number of IO-APIC IRQ registers (== #pins):
    */
   for (i = 0; i < IOAPICCount; i++) 
   {
      tmp = IOAPICRead(i, IOAPIC_VER);
      IOAPICMap[i].EntryCount = GET_IOAPIC_MRE(tmp) + 1;
   }

   /*
    * Do not trust the IO-APIC being empty at bootup
    */
   IOAPICClearAll();
}

VOID 
IOAPICSetupIds(VOID)
{
  ULONG tmp, apic, i;
  UCHAR old_id;
  
  /*
   * Set the IOAPIC ID to the value stored in the MPC table.
   */
  for (apic = 0; apic < IOAPICCount; apic++) 
  {
    
    /* Read the register 0 value */
    tmp = IOAPICRead(apic, IOAPIC_ID);
    
    old_id = IOAPICMap[apic].ApicId;
    
    if (IOAPICMap[apic].ApicId >= 0xf) 
    {
      DPRINT1("BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n",
	      apic, IOAPICMap[apic].ApicId);
      DPRINT1("... fixing up to %d. (tell your hw vendor)\n", 
	      GET_IOAPIC_ID(tmp));
      IOAPICMap[apic].ApicId = GET_IOAPIC_ID(tmp);
    }
    
    /*
     * We need to adjust the IRQ routing table
     * if the ID changed.
     */
    if (old_id != IOAPICMap[apic].ApicId)
    {
      for (i = 0; i < IRQCount; i++)
      {
	if (IRQMap[i].DstApicId == old_id)
	{
	  IRQMap[i].DstApicId = IOAPICMap[apic].ApicId;
	}
      }
    }
    
    /*
     * Read the right value from the MPC table and
     * write it into the ID register.
     */
    DPRINT("Changing IO-APIC physical APIC ID to %d\n",
	   IOAPICMap[apic].ApicId);
    
    tmp &= ~IOAPIC_ID_MASK;
    tmp |= SET_IOAPIC_ID(IOAPICMap[apic].ApicId);

    IOAPICWrite(apic, IOAPIC_ID, tmp);
    
    /*
     * Sanity check
     */
    tmp = IOAPICRead(apic, 0);
    if (GET_IOAPIC_ID(tmp) != IOAPICMap[apic].ApicId) 
    {
      DPRINT1("Could not set I/O APIC ID!\n");
      KEBUGCHECK(0);
    }
  }
}

/* This is performance critical and should probably be done in assembler */
VOID IOAPICMaskIrq(ULONG Irq)
{
   IOAPIC_ROUTE_ENTRY Entry;
   ULONG Apic = IrqApicMap[Irq];

   *(((PULONG)&Entry)+0) = IOAPICRead(Apic, IOAPIC_REDTBL+2*Irq);
   *(((PULONG)&Entry)+1) = IOAPICRead(Apic, IOAPIC_REDTBL+2*Irq+1);
   Entry.dest.logical.logical_dest &= ~(1 << KeGetCurrentProcessorNumber());
   if (Entry.dest.logical.logical_dest == 0)
   {
      Entry.mask = 1;
   }
   IOAPICWrite(Apic, IOAPIC_REDTBL+2*Irq+1, *(((PULONG)&Entry)+1));
   IOAPICWrite(Apic, IOAPIC_REDTBL+2*Irq, *(((PULONG)&Entry)+0));
}

/* This is performance critical and should probably be done in assembler */
VOID IOAPICUnmaskIrq(ULONG Irq)
{
   IOAPIC_ROUTE_ENTRY Entry;
   ULONG Apic = IrqApicMap[Irq];

   *(((PULONG)&Entry)+0) = IOAPICRead(Apic, IOAPIC_REDTBL+2*Irq);
   *(((PULONG)&Entry)+1) = IOAPICRead(Apic, IOAPIC_REDTBL+2*Irq+1);
   Entry.dest.logical.logical_dest |= 1 << KeGetCurrentProcessorNumber();
   Entry.mask = 0;
   IOAPICWrite(Apic, IOAPIC_REDTBL+2*Irq+1, *(((PULONG)&Entry)+1));
   IOAPICWrite(Apic, IOAPIC_REDTBL+2*Irq, *(((PULONG)&Entry)+0));
}

VOID IOAPICDump(VOID)
{
   ULONG apic, i;
   ULONG reg0, reg1, reg2=0;

   DbgPrint("Number of MP IRQ sources: %d.\n", IRQCount);
   for (i = 0; i < IOAPICCount; i++) 
   {
      DbgPrint("Number of IO-APIC #%d registers: %d.\n",
	       IOAPICMap[i].ApicId,
               IOAPICMap[i].EntryCount);
   }

   /*
    * We are a bit conservative about what we expect.  We have to
    * know about every hardware change ASAP.
    */
   DbgPrint("Testing the IO APIC.......................\n");

   for (apic = 0; apic < IOAPICCount; apic++) 
   {
      reg0 = IOAPICRead(apic, IOAPIC_ID);
      reg1 = IOAPICRead(apic, IOAPIC_VER);
      if (GET_IOAPIC_VERSION(reg1) >= 0x10) 
      {
         reg2 = IOAPICRead(apic, IOAPIC_ARB);
      }

      DbgPrint("\n");
      DbgPrint("IO APIC #%d......\n", IOAPICMap[apic].ApicId);
      DbgPrint(".... register #00: %08X\n", reg0);
      DbgPrint(".......    : physical APIC id: %02X\n", GET_IOAPIC_ID(reg0));
      if (reg0 & 0xF0FFFFFF) 
      {
         DbgPrint("  WARNING: Unexpected IO-APIC\n");
      }

      DbgPrint(".... register #01: %08X\n", reg1);
      i = GET_IOAPIC_MRE(reg1);

      DbgPrint(".......     : max redirection entries: %04X\n", i);
      if ((i != 0x0f) &&    /* older (Neptune) boards */
	  (i != 0x17) &&    /* typical ISA+PCI boards */
	  (i != 0x1b) &&    /* Compaq Proliant boards */
	  (i != 0x1f) &&    /* dual Xeon boards */
          (i != 0x22) &&   /* bigger Xeon boards */
	  (i != 0x2E) &&
	  (i != 0x3F)) 
      {
         DbgPrint("  WARNING: Unexpected IO-APIC\n");
      }

      i = GET_IOAPIC_VERSION(reg1);
      DbgPrint(".......     : IO APIC version: %04X\n", i);
      if ((i != 0x01) &&    /* 82489DX IO-APICs */
	  (i != 0x10) &&    /* oldest IO-APICs */
	  (i != 0x11) &&    /* Pentium/Pro IO-APICs */
	  (i != 0x13))	    /* Xeon IO-APICs */
      {
         DbgPrint("  WARNING: Unexpected IO-APIC\n");
      }

      if (reg1 & 0xFF00FF00) 
      {
         DbgPrint("  WARNING: Unexpected IO-APIC\n");
      }

      if (GET_IOAPIC_VERSION(reg1) >= 0x10) 
      {
	 DbgPrint(".... register #02: %08X\n", reg2);
	 DbgPrint(".......     : arbitration: %02X\n",
	          GET_IOAPIC_ARB(reg2));
  	 if (reg2 & 0xF0FFFFFF) 
	 {
            DbgPrint("  WARNING: Unexpected IO-APIC\n");
         }
      }

      DbgPrint(".... IRQ redirection table:\n");
      DbgPrint(" NR Log Phy Mask Trig IRR Pol"
	       " Stat Dest Deli Vect:   \n");

      for (i = 0; i <= GET_IOAPIC_MRE(reg1); i++) 
      {
         IOAPIC_ROUTE_ENTRY entry;

	 *(((PULONG)&entry)+0) = IOAPICRead(apic, 0x10+i*2);
	 *(((PULONG)&entry)+1) = IOAPICRead(apic, 0x11+i*2);

	 DbgPrint(" %02x %03X %02X  ",
		  i,
		  entry.dest.logical.logical_dest,
		  entry.dest.physical.physical_dest);

         DbgPrint("%C    %C    %1d  %C    %C    %C     %03X    %02X\n",
		  (entry.mask == 0) ? 'U' : 'M',            // Unmasked/masked
		  (entry.trigger == 0) ? 'E' : 'L',         // Edge/level sensitive
		  entry.irr,
		  (entry.polarity == 0) ? 'H' : 'L',        // Active high/active low
		  (entry.delivery_status == 0) ? 'I' : 'S', // Idle / send pending
		  (entry.dest_mode == 0) ? 'P' : 'L',       // Physical logical
		  entry.delivery_mode,
		  entry.vector);
      }
   }

   DbgPrint(".................................... done.\n");
}

VOID
HaliReconfigurePciInterrupts(VOID)
{
   ULONG i;

   for (i = 0; i < IRQCount; i++)
   {
      if (BUSMap[IRQMap[i].SrcBusId] == MP_BUS_PCI)
      {
         DPRINT("%02x: IrqType %02x, IrqFlag %02x, SrcBusId %02x, SrcBusIrq %02x"
	        ", DstApicId %02x, DstApicInt %02x\n",
	        i, IRQMap[i].IrqType, IRQMap[i].IrqFlag, IRQMap[i].SrcBusId, 
	        IRQMap[i].SrcBusIrq, IRQMap[i].DstApicId, IRQMap[i].DstApicInt);

	 if(1 != HalSetBusDataByOffset(PCIConfiguration, 
	                               IRQMap[i].SrcBusId, 
				       (IRQMap[i].SrcBusIrq >> 2) & 0x1f, 
				       &IRQMap[i].DstApicInt, 
				       0x3c /*PCI_INTERRUPT_LINE*/, 
				       1))
	 {
	    CHECKPOINT;
	 }
      }
   }
}

VOID Disable8259AIrq(ULONG irq)
{
    ULONG tmp;

    if (irq >= 8) 
    {
       tmp = READ_PORT_UCHAR((PUCHAR)0xA1);
       tmp |= (1 << (irq - 8));
       WRITE_PORT_UCHAR((PUCHAR)0xA1, tmp);
    } 
    else 
    {
       tmp = READ_PORT_UCHAR((PUCHAR)0x21);
       tmp |= (1 << irq);
       WRITE_PORT_UCHAR((PUCHAR)0x21, tmp);
    }
}

ULONG IOAPICRead(ULONG Apic, ULONG Offset)
{
  PULONG Base;

  Base = (PULONG)IOAPICMap[Apic].ApicAddress;
  *Base = Offset;
  return *((PULONG)((ULONG)Base + IOAPIC_IOWIN));
}

VOID IOAPICWrite(ULONG Apic, ULONG Offset, ULONG Value)
{
  PULONG Base;

  Base = (PULONG)IOAPICMap[Apic].ApicAddress;
  *Base = Offset;
  *((PULONG)((ULONG)Base + IOAPIC_IOWIN)) = Value;
}

/* EOF */

⌨️ 快捷键说明

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