How do I know if an IRQ or Exception is firing? |
When the PC boots up, the PIC IRQ's are mapped to interrupts 8 to 15 and 70 to 77.
So when your kernel boots up and you switch into protected mode, the PIC's remain unchanged, and the low 8 IRQ's end up corresponding to the same interrupt as CPU exceptions 8 to 15. If one of these fire off, you can test if its an CPU exception or IRQ by testing some bits in the PIC status register but there is a much easier way, remap the PIC to use different interrupts than the CPU exceptions! |
What is the PIC? |
The PIC is a "Programmable Interrupt Controler" and
is one of THE important chips, without it, x86 would not be an
interrupt driven architecture.
There needs to be a way for perhiperals and other devices external of the CPU to tell the system than an event has happened or needs to happen. exampels of this; hard disk IO, modem/serial ports, keyboard. Without the PIC interface, you would have to poll all the devices in the system to see if they want to do anything (signal an event), but with the PIC, your system can run along nicely until such time that a device wants to signal an event, which means you dont waste time going to the devices, you let the devices come to you when they are ready. In the begining, the age of the IBM XT, we had only 1 PIC chip giving us 8 hardware interrupt lines, but the 8259A PIC chip has a neat abality, it can cascade! Cascading means you can daisy chain PIC chips together. This is what happened with the introduction of the IBM AT, we had a second PIC chip cascaded onto the first, giving us a total of 15 hardware lines... Why 15 and not 16? Thats because when you cascade chips, the PIC needs to use one of the int lines to signal to the other chip. Thus, in an AT, IRQ line 2 is used to signal the second chip... But to confuse things more, IRQ 9 is redirectd to IRQ 2. So when you get an IRQ 9, the signal is redirected to IRQ 2. |
So can I remap the PIC? |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
The PIC has the ability to be re-programmed to use a different
set of interrupt values than the default ones.
The default PIC values are;
The PIC is programmable, and can be remapped quite easily, but each PIC vector must be divisable by 8, as the 8259A discards the lower 3 bits. In x86 protected mode, it is good to remap the PICs beyond 32 as Intel have designated the first 32 interrupts as "reserved" for cpu exceptions. eg: remap_pics(0x20, 0x28);will remap the pics using 16 linear interrupts from 32 to 48 (0x20-0x2F). /* remap the PIC controller interrupts to our vectors rather than the 8 + 70 as mapped by default */ #define PIC1 0x20 #define PIC2 0xA0 #define PIC1_COMMAND PIC1 #define PIC1_DATA (PIC1+1) #define PIC2_COMMAND PIC2 #define PIC2_DATA (PIC2+1) #define PIC_EOI 0x20 #define ICW1_ICW4 0x01 /* ICW4 (not) needed */ #define ICW1_SINGLE 0x02 /* Single (cascade) mode */ #define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */ #define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */ #define ICW1_INIT 0x10 /* Initialization - required! */ #define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */ #define ICW4_AUTO 0x02 /* Auto (normal) EOI */ #define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */ #define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */ #define ICW4_SFNM 0x10 /* Special fully nested (not) */ void remap_pics(int pic1, int pic2) { UCHAR a1, a2; a1=inb(PIC1_DATA); a2=inb(PIC2_DATA); outb(PIC1_COMMAND, ICW1_INIT+ICW1_ICW4); io_wait(); outb(PIC2_COMMAND, ICW1_INIT+ICW1_ICW4); io_wait(); outb(PIC1_DATA, pic1); io_wait(); outb(PIC2_DATA, pic2); io_wait(); outb(PIC1_DATA, 4); io_wait(); outb(PIC2_DATA, 2); io_wait(); outb(PIC1_DATA, ICW4_8086); io_wait(); outb(PIC2_DATA, ICW4_8086); io_wait(); outb(PIC1_DATA, a1); outb(PIC2_DATA, a2); } |
So whats this NMI then? |
The NMI (&qout;Non Maskable Interrupt") is a hardware driven
interrupt much like the PIC interrupts but the NMI goes diretcly
the cpu, and not via the PIC controller.
Luckily you CAN have control over the NMI, otherwise you could be in deep trouble. The NMI is turned "on"e; (set high) by the memory module when a memory parity error occurs. You have to be carefull about disabling the NMI and the PIC for extended periods of time, your system will hang unless it has a failsafe timer! (Which you do have.. just down kill the PIT timer :)
/* enable the NMI */ void NMI_enable(void) { outb(0x70, inb(0x70)&0x7F); } /* disable the NMI */ void NMI_disable(void) { outb(0x70, inb(0x70)|=0x80); } |
APIC? Advanced Programmable Interrupt Controller |
APIC is the Intel standard for the "new" PIC. Its used in
multiprocessor systems.
I have no more info at this time. |
OPIC? Open Programmable Interrupt Controller |
I have no info on OPIC currently... Other than its a non-intel standard. |