Added 8259 PIC support #5

Merged
belliash merged 12 commits from :master into master 2023-11-29 20:07:17 +01:00
8 changed files with 197 additions and 0 deletions
Showing only changes of commit 1c031e8be9 - Show all commits

View File

@ -43,4 +43,8 @@ VOID
HlIoPortOutShort(IN USHORT Port,
IN USHORT Value);
XTCDECL
VOID
HlIoPortWait(VOID);
#endif /* __XTDK_AMD64_HLFUNCS_H */

View File

@ -90,6 +90,25 @@
#define COMPORT_REG_MSR 0x06 /* Modem Status Register */
#define COMPORT_REG_SR 0x07 /* Scratch Register */
/* 8259 PIC ports */
belliash marked this conversation as resolved Outdated

Does any other platform than x86 and x86_64 support 8259 PIC? If not, this should be architecture specific.

Does any other platform than x86 and x86_64 support 8259 PIC? If not, this should be architecture specific.
#define PIC_MASTER_COMMAND 0xA0
#define PIC_MASTER_DATA 0xA1
#define PIC_SLAVE_COMMAND 0x20
#define PIC_SLAVE_DATA 0x21
belliash marked this conversation as resolved Outdated

I think Master and Slave (PIC1 and PIC2) I/O port addresses are swapped.

I think Master and Slave (PIC1 and PIC2) I/O port addresses are swapped.
/* 8259 PIC commands */
#define PIC_ICW1_ICW4 0x01 /* Indicates that ICW4 will be present */
#define PIC_ICW1_SINGLE 0x02 /* Single (cascade) mode */
#define PIC_ICW1_INTERVAL4 0x04 /* Call address interva l 4 (8) */
#define PIC_ICW1_LEVEL 0x08 /* Level triggered (edge) mode */
#define PIC_ICW1_INIT 0x10 /* Initialization - required! */
#define PIC_ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */
#define PIC_ICW4_AUTO 0x02 /* Auto (normal) EOI */
#define PIC_ICW4_BUF_MASTER 0x0C /* Buffered mode/master */
#define PIC_ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */
#define PIC_ICW4_SFNM 0x10 /* Special fully nested (not) */
/* APIC Register Address Map */
typedef enum _APIC_REGISTER
{

View File

@ -43,4 +43,8 @@ VOID
HlIoPortOutShort(IN USHORT Port,
IN USHORT Value);
XTCDECL
VOID
HlIoPortWait(VOID);
#endif /* __XTDK_I686_HLFUNCS_H */

View File

@ -143,3 +143,19 @@ HlIoPortOutShort(IN USHORT Port,
: "a" (Value),
"Nd" (Port));
}
/**
* Sends a 0x00 byte to an unused IO port.
* This operation takes 1 - 4 microseconds and functions as an
* imprecise wait function.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTCDECL
VOID
HlIoPortWait(VOID)
belliash marked this conversation as resolved Outdated

Do you think this function might be useful anywhere else, or could we just call HlIoPortOutByte(0x80, 0x00); directly as currently it is used only in HlWritePic()?

Do you think this function might be useful anywhere else, or could we just call ```HlIoPortOutByte(0x80, 0x00);``` directly as currently it is used only in ```HlWritePic()```?
{
HlIoPortOutByte(0x80, 0x00);
}

View File

@ -143,3 +143,19 @@ HlIoPortOutShort(IN USHORT Port,
: "a" (Value),
"Nd" (Port));
}
/**
* Sends a 0x00 byte to an unused IO port.
* This operation takes 1 - 4 microseconds and functions as an
* imprecise wait function.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTCDECL
VOID
HlIoPortWait(VOID)
{
HlIoPortOutByte(0x80, 0x00);
}

View File

@ -4,10 +4,124 @@
* FILE: xtoskrnl/hl/pic.c
* DESCRIPTION: Programmable Interrupt Controller (PIC) support
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
* Jozef Nagy <schkwve@gmail.com>
*/
#include <xtos.h>
/**
* 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 */
belliash marked this conversation as resolved Outdated

What do you think about putting an empty line before each comment? In my opinion it is easy to read, if comment says what does below block of code do and each block ends up with an empty line.

What do you think about putting an empty line before each comment? In my opinion it is easy to read, if comment says what does below block of code do and each block ends up with an empty line.
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++)
belliash marked this conversation as resolved Outdated

Do we need to mask all IRQs if we finally disable PIC and use APIC? Do we want to support PIC as a failover?

Do we need to mask all IRQs if we finally disable PIC and use APIC? Do we want to support PIC as a failover?
Outdated
Review

I have not found any mention of IRQs being explicitly masked or unmasked in any documents, so I masked them so the kernel doesn't get interrupted when the IRQ isn't ready to be served yet (in the case that PIC is indeed used as a failsafe).

I have not found any mention of IRQs being explicitly masked or unmasked in any documents, so I masked them so the kernel doesn't get interrupted when the IRQ isn't ready to be served yet (in the case that PIC is indeed used as a failsafe).
{
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.

View File

@ -13,6 +13,26 @@
/* HAL library routines forward references */
XTCDECL
VOID
HlInitializePic(VOID);
XTCDECL
VOID
HlSetMaskIrqPic(UINT Irq);
XTCDECL
VOID
HlClearMaskIrqPic(UINT Irq);
XTCDECL
VOID
HlDisablePic(VOID);
XTFASTCALL
VOID
HlWritePic(IN UCHAR Register, IN UCHAR Value);
XTAPI
VOID
HlClearScreen(VOID);

View File

@ -69,6 +69,10 @@ KepInitializeMachine(VOID)
/* Re-enable IDE interrupts */
HlIoPortOutByte(0x376, 0);
HlIoPortOutByte(0x3F6, 0);
/* Disable the legacy PIC */
HlInitializePic();
HlDisablePic();
}
/**