I write 0x0100000000000022 to IOAPIC redirect table register pin2, it seems work because the CPU get correct interrupt. But when I read it out, it becomes 0x0010000000100000 0x0000002200000022, the value shift to pin3 and double the first 32bit value. If I read the value twice, it won't shift to pin3 but still double 32bit.
My code:
Code: Select all
static inline unsigned int ioapic_read(unsigned int reg)
{
writel(IOAPIC_BASE+IOAPIC_IOREGSEL, reg);
return readl(IOAPIC_BASE+IOAPIC_IOWIN);
}
static inline void ioapic_write(unsigned int reg, unsigned int value)
{
writel(IOAPIC_BASE+IOAPIC_IOREGSEL, reg);
writel(IOAPIC_BASE+IOAPIC_IOWIN, value);
}
uint64_t get_ioapic_entry(int irq)
{
uint64_t ret;
ret = ioapic_read(IOAPIC_IOREDTBL + 2*irq + 1);
ret <<= 32;
ret |= ioapic_read(IOAPIC_IOREDTBL+2*irq);
return ret;
}
void set_ioapic_entry(int irq, int level, int share)
{
unsigned int h, l;
// if share is true, broadcast the interrupt
if (share)
h = 0xff000000;
else
h = 0x01000000;
// physical destination mode, fixed delivery mode
if (level)
l = 0x0000a000;
else
l = 0;
ioapic_write(IOAPIC_IOREDTBL + 2*irq + 1, h);
ioapic_write(IOAPIC_IOREDTBL + 2*irq, l + T_IRQ + irq);
}
the print code:
cprintf("\n======== IOAPIC interrupt redirect table =========\n");
for (i=0; i<24; i++) {
//get_ioapic_entry(i);
//get_ioapic_entry(i);
cprintf("%02d:%016llx ", i, get_ioapic_entry(i));
if (((i+1)%4) == 0)
cprintf("\n");
}
EDIT: Brendan added code tags..