下保护模式的内容..这些都是基础的东西... ..
NT中....物理地址 可以分为: RAM的地址和硬件寄存器的地址...
页框号 = 物理地址>> PAGE_SHIFT
如果 页框号 > MmHighestPossiblePhysicalPage 将表明这个地址是硬件寄存器的..
否则会以PageFrameIndex为INDEX检测MiPfnBitMap 的位设..如果位设为1..则表示该物理地址是RAM的物理地址,,,,
帖上一段.....硬件REG做为物理地址的...
//IO APIC使用重定向机制,我们不可以直接操作它的寄存器的,我们应该通过映射来完成
//IOREGSEL and IOWIN registers 位于IO APIC's base address的0x00和0x10偏移处.
//IO APIC's base address在NT中被映射到物理地址 0XFEC00000
//所以 IOREGSEL and IOWIN registers 的物理地址分别是 0XFEC00000,0XFEC00010
//访问他们的话只要用MmMapIoSpace()就可以了..
//如果系统不支持APIC...vector = 0x30+IRQ; Sysnap 2009.5.22
BOOLEAN IsIoapicEnable()
{
BOOLEAN bis = FALSE;
__asm
{
mov eax,1
cpuid
and edx, 0x00000200
cmp edx,0
jne __A
mov bis,0
__A:
mov ecx,0x1b
rdmsr
and eax,0x00000800
cmp eax,0
jne __B
mov bis,0
jmp __C
__B:
mov bis,1
__C:
}
return bis;
}
DWORD IRQtoVector(DWORD dwIRQ)
{
PULONG lpIoapicMapBase = NULL;
DWORD dwVector = -1;
PHYSICAL_ADDRESS IoapicBase; // i/o apic mapped pointer
if( IsIoapicEnable() == FALSE)
{
dwVector = 0x30+dwIRQ;
return dwVector;
}
IoapicBase = RtlConvertLongToLargeInteger(0xFEC00000);
lpIoapicMapBase = (PULONG)MmMapIoSpace(IoapicBase, 0xFF, MmNonCached);
if(lpIoapicMapBase == NULL || dwIRQ >23)
{
//
return -1;
}
// 把0x10 + 2 * dwIRQ 写到 IOREGSEL 寄存器
lpIoapicMapBase[0] = 0x10 + 2 * dwIRQ; // 0x10 + 2 * IRQ, Keyboard's irq is 1
// 接着可以读 IOWIN 寄存器
dwVector = lpIoapicMapBase[4] & 0xFF;
MmUnmapIoSpace(lpIoapicMapBase, 0xff);
return dwVector;
}
DbgPrint("--0x%x",IRQtoVector(12));