Hi, I have an issue where I’m not sure what is wrong with the following code. Now I admit that I still don’t fully understand how to use the IOREGSEL and IOWIN registers for IOAPIC access. Not properly documented (IMO).
Now I get a hold of the APIC base address. Then I do a MmMapIoSpace. So far so good. And I would expect it to be correct because of it (although I don’t rule anything out). Now I have to write to a 32-bit IOREGSEL and read from a 32-bit IOWIN register. The way I do it is to use WRITE_REGISTER_ULONG64 and READ_REGISTER_ULONG64. Now I don’t think they are correct because the registers are 32-bit wide only, but the 32 bit version of the macros only takes a 32-bit address. So I’m lost here as to how to do it on a 64-bit OS like Windows 10. MmMapIoSpace returns a 64 bit address of course.
If there is any other mistakes you see please feel free to shout out. The code in its simplest form is as follows. (error checking left out as well). I loop through and return as soon as I find something.
#define APIC_CHUNKSIZE 0x20
// I/O APIC
pOutputData->dwApicBaseAddress = GetApicBaseAddress();
PHYSICAL_ADDRESS physAddress = { 0 };
physAddress.LowPart = pOutputData->dwApicBaseAddress & APIC_MASK;
hIoMemMap = MmMapIoSpace(physAddress, APIC_CHUNK_SIZE, MmNonCached);
volatile PULONGLONG pApicIoRegSel = (PULONGLONG)hIoMemMap;
pApicIoRegSel += 0x00;
volatile PULONGLONG pApicIoWin = (PULONGLONG)hIoMemMap;
pApicIoWin += 0x10;
int irq = 0x10;
ULONGLONG qwApicData(0);
do
{
WRITE_REGISTER_ULONG64(pApicIoRegSel, irq);//IRQ_APIC_KEYBOARD);
qwApicData = READ_REGISTER_ULONG64(pApicIoWin);
if (qwApicData != 0) {
break;
}
if (qwApicData == 0) {
WRITE_REGISTER_ULONG64(pApicIoRegSel, irq+1);//IRQ_APIC_KEYBOARD);
qwApicData = READ_REGISTER_ULONG64(pApicIoWin);
if (qwApicData != 0) {
break;
}
}
irq += 2;
} while (irq <= 0x3E);
pOutputData->qwIOAPIC_IRQ1 = qwApicData;
MmUnmapIoSpace(hIoMemMap, APIC_CHUNK_SIZE);
The code executes in kernel mode driver and returns 0, never finding anything.
regards
Kjetil