/** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/hl/pic.c * DESCRIPTION: Programmable Interrupt Controller (PIC) support * DEVELOPERS: Rafal Kupiec * Jozef Nagy */ #include /** * Initializes the 8259 PIC. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID HlInitializePic(VOID) { /* Start in cascade mode */ HlWritePic(PIC_MASTER_COMMAND, PIC_ICW1_INIT | PIC_ICW1_ICW4); HlWritePic(PIC_SLAVE_COMMAND, PIC_ICW1_INIT | PIC_ICW1_ICW4); /* Master PIC Vector offset */ HlWritePic(PIC_MASTER_DATA, 0x20); /* Slave PIC Vector offset */ HlWritePic(PIC_SLAVE_DATA, 0x28); /* Tell Master PIC that there is a Slave PIC */ HlWritePic(PIC_MASTER_DATA, 4); /* Tell Slave PIC its cascade identity */ HlWritePic(PIC_SLAVE_DATA, 2); /* Tell Master PIC to use 8086 mode */ HlWritePic(PIC_MASTER_DATA, PIC_ICW4_8086); /* Tell Slave PIC to use 8086 mode */ HlWritePic(PIC_SLAVE_DATA, PIC_ICW4_8086); /* Mask all IRQs by default */ for (UCHAR Irq = 0; Irq < 16; Irq++) { HlSetMaskIrqPic(Irq); } } /** * Masks an IRQ in the 8259 PIC. * * @param Irq * Supplies the IRQ number to be masked. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID HlSetMaskIrqPic(UINT Irq) { UINT Port; if(Irq < 8) { Port = PIC_MASTER_DATA; } else { Port = PIC_SLAVE_DATA; Irq -= 8; } HlWritePic(Port, HlIoPortInByte(Port) | (1 << Irq)); } /** * Clears an IRQ mask in the 8259 PIC. * * @param Irq * Supplies the IRQ number to be unmasked. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID HlClearMaskIrqPic(UINT Irq) { UINT Port; if(Irq < 8) { Port = PIC_MASTER_DATA; } else { Port = PIC_SLAVE_DATA; Irq -= 8; } HlWritePic(Port, HlIoPortInByte(Port) & ~(1 << Irq)); } /** * Disables the 8259 PIC. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID HlDisablePic(VOID) { HlIoPortOutByte(PIC_MASTER_DATA, 0xFF); HlIoPortOutByte(PIC_SLAVE_DATA, 0xFF); } XTFASTCALL VOID HlWritePic(IN UCHAR Register, IN UCHAR Value) { /* Send data */ HlIoPortOutByte(Register, Value); /* Wait for some time to make sure PIC has processed the data */ HlIoPortWait(); } /** * Reads from the local APIC register. * * @param Register * Supplies the APIC register to read from. * * @return This routine returns the value read from the APIC register. * * @since XT 1.0 */ XTFASTCALL ULONG HlReadApicRegister(IN APIC_REGISTER Register) { return RtlReadRegisterLong((PULONG)APIC_BASE + (Register << 4)); } /** * Writes to the local APIC register. * * @param Register * Supplies the APIC register to write to. * * @param Value * Supplies the value to write to the APIC register. * * @return This routine does not return any value. * * @since XT 1.0 */ XTFASTCALL VOID HlWriteApicRegister(IN APIC_REGISTER Register, IN ULONG Value) { RtlWriteRegisterLong((PULONG)APIC_BASE + (Register << 4), Value); }