Remapping the PIC in QEMU
Posted: Tue Jan 09, 2018 4:42 pm
First, has anyone been able to successfully remap the PIC in the QEMU emulator? That is, is remapping supported? If so, then I have a problem that I am not sure how to solve. Remapping seems very simple, requiring only four IO writes to the 8259 as it walks through a simple state machine, yet somehow mine is refusing to move from default offsets (master=0x08, slave=0x70).
I have read the 8295 wiki page wiki page. I have also read through the 8259 datasheet, with particular emphases on the Initialization Control Word (ICW) sequence (see pg 10). The sequence can be distilled down to the following writes:
Master:
For ICW2, write the desired offset keeping in mind the lower three bits are not used.
For ICW3, write 4 to the master PIC (indicating a slave is connected to IRQ2) and write 2 to the slave (setting its slave ID)
For ICW4, D0 is set to configure the 8259 to run in 8086 mode
My code does exactly that (pic_outb wraps outb):
I have interrupt stubs installed for each entry in the IDT that will print the vector number and halt the system. I know the 8259 is not being remapped because the number being printed does not change. For testing I em enabling the keyboard interrupt, which nominally prints 9 to the screen (since the default master PIC offset is 8 ). However, even after attempting to remap I observe the same handler (9) is executed. It behaves like the writes are being ignored. Also, I have tried doing the above above sequence directly (without macros or use of variables) and the result remains the same.
Any ideas?
I have read the 8295 wiki page wiki page. I have also read through the 8259 datasheet, with particular emphases on the Initialization Control Word (ICW) sequence (see pg 10). The sequence can be distilled down to the following writes:
Master:
- ICW1 = 0x11 (cmd)
ICW2 = offset (data)
ICW3 = 0x04 (data)
ICW4 = 0x01 (data)
- ICW1 = 0x11 (cmd)
ICW2 = offset (data)
ICW3 = 0x02 (data)
ICW4 = 0x01 (data)
For ICW2, write the desired offset keeping in mind the lower three bits are not used.
For ICW3, write 4 to the master PIC (indicating a slave is connected to IRQ2) and write 2 to the slave (setting its slave ID)
For ICW4, D0 is set to configure the 8259 to run in 8086 mode
My code does exactly that (pic_outb wraps outb):
Code: Select all
#define PIC8259_MASTER_CMD 0x20
#define PIC8259_MASTER_DATA 0x21
#define PIC8259_SLAVE_CMD 0xa0
#define PIC8259_SLAVE_DATA 0xa1
#define ICW1_IC4_NEEDED (1 << 0)
#define ICW1_D4_BEGIN_ICW (1 << 4)
#define ICW4_uPM_8086 (1 << 0)
/* ICW1: Edge triggered (default), cascade mode (deafult), ICW4 is needed */
pic_outb(PIC8259_MASTER_CMD, ICW1_D4_BEGIN_ICW | ICW1_IC4_NEEDED);
pic_outb(PIC8259_SLAVE_CMD, ICW1_D4_BEGIN_ICW | ICW1_IC4_NEEDED);
/* ICW2: Fully nexted mode (default), vector offset (rebase) */
pic_outb(PIC8259_MASTER_DATA, moffset);
pic_outb(PIC8259_SLAVE_DATA, soffset);
pic_outb(PIC8259_MASTER_DATA, (1 << 2));
pic_outb(PIC8259_SLAVE_DATA, 2);
/* ICW4: Non-buffered mode (default), EOI required (default), 8086 mode */
pic_outb(PIC8259_MASTER_DATA, ICW4_uPM_8086);
pic_outb(PIC8259_SLAVE_DATA, ICW4_uPM_8086);
Any ideas?