mirror of
https://github.com/danbulant/Cosmos
synced 2026-06-13 03:31:22 +00:00
518 lines
No EOL
19 KiB
C#
518 lines
No EOL
19 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace Cosmos.Hardware {
|
|
public class Interrupts {
|
|
[StructLayout(LayoutKind.Explicit, Size = 0x68)]
|
|
public struct TSS
|
|
{
|
|
[FieldOffset(0)]
|
|
public ushort Link;
|
|
[FieldOffset(4)]
|
|
public uint ESP0;
|
|
[FieldOffset(8)]
|
|
public ushort SS0;
|
|
[FieldOffset(12)]
|
|
public uint ESP1;
|
|
[FieldOffset(16)]
|
|
public ushort SS1;
|
|
[FieldOffset(20)]
|
|
public uint ESP2;
|
|
[FieldOffset(24)]
|
|
public ushort SS2;
|
|
[FieldOffset(28)]
|
|
public uint CR3;
|
|
[FieldOffset(32)]
|
|
public uint EIP;
|
|
[FieldOffset(36)]
|
|
public EFlagsEnum EFlags;
|
|
[FieldOffset(40)]
|
|
public uint EAX;
|
|
[FieldOffset(44)]
|
|
public uint ECX;
|
|
[FieldOffset(48)]
|
|
public uint EDX;
|
|
[FieldOffset(52)]
|
|
public uint EBX;
|
|
[FieldOffset(56)]
|
|
public uint ESP;
|
|
[FieldOffset(60)]
|
|
public uint EBP;
|
|
[FieldOffset(64)]
|
|
public uint ESI;
|
|
[FieldOffset(68)]
|
|
public uint EDI;
|
|
[FieldOffset(72)]
|
|
public ushort ES;
|
|
[FieldOffset(76)]
|
|
public ushort CS;
|
|
[FieldOffset(80)]
|
|
public ushort SS;
|
|
[FieldOffset(84)]
|
|
public ushort DS;
|
|
[FieldOffset(88)]
|
|
public ushort FS;
|
|
[FieldOffset(92)]
|
|
public ushort GS;
|
|
[FieldOffset(96)]
|
|
public ushort LDTR;
|
|
[FieldOffset(102)]
|
|
public ushort IOPBOffset;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Explicit, Size = 76)]
|
|
public struct InterruptContext {
|
|
[FieldOffset(0)]
|
|
public uint EDI;
|
|
|
|
[FieldOffset(4)]
|
|
public uint ESI;
|
|
|
|
[FieldOffset(8)]
|
|
public uint EBP;
|
|
|
|
[FieldOffset(12)]
|
|
public uint ESP;
|
|
|
|
[FieldOffset(16)]
|
|
public uint EBX;
|
|
|
|
[FieldOffset(20)]
|
|
public uint EDX;
|
|
|
|
[FieldOffset(24)]
|
|
public uint ECX;
|
|
|
|
[FieldOffset(28)]
|
|
public uint EAX;
|
|
|
|
[FieldOffset(32)]
|
|
public uint Interrupt;
|
|
|
|
[FieldOffset(36)]
|
|
public uint Param;
|
|
|
|
[FieldOffset(40)]
|
|
public uint EIP;
|
|
|
|
[FieldOffset(44)]
|
|
public uint CS;
|
|
|
|
[FieldOffset(48)]
|
|
public EFlagsEnum EFlags;
|
|
|
|
[FieldOffset(52)]
|
|
public uint UserESP;
|
|
}
|
|
|
|
public static void HandleInterrupt_Default(ref InterruptContext aContext) {
|
|
//Console.Write("Interrupt ");
|
|
//WriteNumber(aContext.Interrupt, 32);
|
|
//Console.WriteLine("");
|
|
DebugUtil.LogInterruptOccurred(ref aContext);
|
|
if (aContext.Interrupt >= 0x20 && aContext.Interrupt <= 0x2F) {
|
|
if (aContext.Interrupt >= 0x28) {
|
|
PIC.SignalSecondary();
|
|
} else {
|
|
PIC.SignalPrimary();
|
|
}
|
|
}
|
|
}
|
|
|
|
public delegate void InterruptDelegate(ref InterruptContext aContext);
|
|
|
|
public delegate void ExceptionInterruptDelegate(ref InterruptContext aContext,
|
|
ref bool aHandled);
|
|
|
|
//IRQ 2 - Cascaded signals from IRQs 8-15. A device configured to use IRQ 2 will actually be using IRQ 9
|
|
//IRQ 3 - COM2 (Default) and COM4 (User) serial ports
|
|
//IRQ 4 - COM1 (Default) and COM3 (User) serial ports
|
|
//IRQ 5 - LPT2 Parallel Port 2 or sound card
|
|
//IRQ 6 - Floppy disk controller
|
|
//IRQ 7 - LPT1 Parallel Port 1 or sound card (8-bit Sound Blaster and compatibles)
|
|
|
|
//IRQ 8 - Real time clock
|
|
//IRQ 9 - Free / Open interrupt / Available / SCSI. Any devices configured to use IRQ 2 will actually be using IRQ 9.
|
|
//IRQ 10 - Free / Open interrupt / Available / SCSI
|
|
//IRQ 11 - Free / Open interrupt / Available / SCSI
|
|
//IRQ 12 - PS/2 connector Mouse. If no PS/2 connector mouse is used, this can be used for other peripherals
|
|
//IRQ 13 - ISA / Math Co-Processor
|
|
|
|
//IRQ 0 - System timer. Reserved for the system. Cannot be changed by a user.
|
|
public static void HandleInterrupt_20(ref InterruptContext aContext) {
|
|
PIT.HandleInterrupt();
|
|
PIC.SignalPrimary();
|
|
}
|
|
|
|
public static InterruptDelegate IRQ01;
|
|
//IRQ 1 - Keyboard. Reserved for the system. Cannot be altered even if no keyboard is present or needed.
|
|
public static void HandleInterrupt_21(ref InterruptContext aContext) {
|
|
//Change area
|
|
//
|
|
// Triggers IL2CPU error
|
|
DebugUtil.LogInterruptOccurred(ref aContext);
|
|
IRQ01(ref aContext);
|
|
//
|
|
// Old keyboard
|
|
//Cosmos.Hardware.Keyboard.HandleKeyboardInterrupt();
|
|
//
|
|
// New Keyboard
|
|
//Cosmos.Hardware.PC
|
|
//
|
|
// - End change area
|
|
|
|
PIC.SignalPrimary();
|
|
}
|
|
|
|
//IRQ 5 - (Added for ES1370 AudioPCI)
|
|
public static InterruptDelegate IRQ05;
|
|
|
|
public static void HandleInterrupt_25(ref InterruptContext aContext) {
|
|
if (IRQ05 != null) {
|
|
IRQ05(ref aContext);
|
|
}
|
|
|
|
PIC.SignalSecondary();
|
|
}
|
|
|
|
//IRQ 11 - (Added for RTL8139 network card)
|
|
public static InterruptDelegate IRQ11;
|
|
|
|
public static void HandleInterrupt_2B(ref InterruptContext aContext) {
|
|
//Debugging....
|
|
//DebugUtil.LogInterruptOccurred_Old(aContext);
|
|
//Cosmos.Hardware.DebugUtil.SendMessage("Interrupts", "Interrupt 2B handler (for RTL)");
|
|
//Console.WriteLine("IRQ 11 raised!");
|
|
|
|
if (IRQ11 != null) {
|
|
IRQ11(ref aContext);
|
|
}
|
|
|
|
PIC.SignalSecondary();
|
|
}
|
|
|
|
//IRQ 14 - Primary IDE. If no Primary IDE this can be changed
|
|
public static void HandleInterrupt_2E(ref InterruptContext aContext) {
|
|
Cosmos.Hardware.DebugUtil.SendMessage("IRQ",
|
|
"Primary IDE");
|
|
//Storage.ATAOld.HandleInterruptPrimary();
|
|
Storage.ATA.ATA.HandleInterruptPrimary();
|
|
PIC.SignalSecondary();
|
|
}
|
|
|
|
public static event InterruptDelegate Interrupt30;
|
|
// Interrupt 0x30, enter VMM
|
|
public static void HandleInterrupt_30(ref InterruptContext aContext) {
|
|
DebugUtil.LogInterruptOccurred(ref aContext);
|
|
if (Interrupt30 != null) {
|
|
Interrupt30(ref aContext);
|
|
} else {
|
|
DebugUtil.SendError("Interrupts",
|
|
"Interrupt 0x30 not handled!");
|
|
}
|
|
}
|
|
|
|
public static void HandleInterrupt_35(ref InterruptContext aContext) {
|
|
Cosmos.Hardware.DebugUtil.SendMessage("Interrupts",
|
|
"Interrupt 35 handler");
|
|
DebugUtil.LogInterruptOccurred(ref aContext);
|
|
Console.WriteLine("Interrupt 0x35 occurred");
|
|
aContext.EAX *= 2;
|
|
aContext.EBX *= 2;
|
|
aContext.ECX *= 2;
|
|
aContext.EDX *= 2;
|
|
}
|
|
|
|
//IRQ 15 - Secondary IDE
|
|
public static void HandleInterrupt_2F(ref InterruptContext aContext) {
|
|
Storage.ATA.ATA.HandleInterruptSecondary();
|
|
Cosmos.Hardware.DebugUtil.SendMessage("IRQ",
|
|
"Secondary IDE");
|
|
PIC.SignalSecondary();
|
|
}
|
|
|
|
public static void HandleInterrupt_00(ref InterruptContext aContext) {
|
|
HandleException(aContext.EIP,
|
|
"Divide by zero",
|
|
"EDivideByZero",
|
|
ref aContext);
|
|
}
|
|
|
|
public static void HandleInterrupt_06(ref InterruptContext aContext) {
|
|
HandleException(aContext.EIP,
|
|
"Invalid Opcode",
|
|
"EInvalidOpcode",
|
|
ref aContext);
|
|
}
|
|
|
|
public static event ExceptionInterruptDelegate GeneralProtectionFault;
|
|
|
|
public static void HandleInterrupt_0D(ref InterruptContext aContext) {
|
|
bool xHandled = false;
|
|
DebugUtil.LogInterruptOccurred(ref aContext);
|
|
if (GeneralProtectionFault != null) {
|
|
GeneralProtectionFault(ref aContext,
|
|
ref xHandled);
|
|
}
|
|
if (!xHandled) {
|
|
HandleException(aContext.EIP,
|
|
"General Protection Fault",
|
|
"GPF",
|
|
ref aContext);
|
|
}
|
|
}
|
|
|
|
public static void HandleInterrupt_01(ref InterruptContext aContext) {
|
|
HandleException(aContext.EIP,
|
|
"Debug Exception",
|
|
"Debug Exception",
|
|
ref aContext);
|
|
}
|
|
|
|
public static void HandleInterrupt_02(ref InterruptContext aContext) {
|
|
HandleException(aContext.EIP,
|
|
"Non Maskable Interrupt Exception",
|
|
"Non Maskable Interrupt Exception",
|
|
ref aContext);
|
|
}
|
|
|
|
public static void HandleInterrupt_03(ref InterruptContext aContext) {
|
|
HandleException(aContext.EIP,
|
|
"Breakpoint Exception",
|
|
"Breakpoint Exception",
|
|
ref aContext);
|
|
}
|
|
|
|
public static void HandleInterrupt_04(ref InterruptContext aContext) {
|
|
HandleException(aContext.EIP,
|
|
"Into Detected Overflow Exception",
|
|
"Into Detected Overflow Exception",
|
|
ref aContext);
|
|
}
|
|
|
|
public static void HandleInterrupt_05(ref InterruptContext aContext) {
|
|
HandleException(aContext.EIP,
|
|
"Out of Bounds Exception",
|
|
"Out of Bounds Exception",
|
|
ref aContext);
|
|
}
|
|
|
|
public static void HandleInterrupt_07(ref InterruptContext aContext) {
|
|
HandleException(aContext.EIP,
|
|
"No Coprocessor Exception",
|
|
"No Coprocessor Exception",
|
|
ref aContext);
|
|
}
|
|
|
|
public static void HandleInterrupt_08(ref InterruptContext aContext) {
|
|
HandleException(aContext.EIP,
|
|
"Double Fault Exception",
|
|
"Double Fault Exception",
|
|
ref aContext);
|
|
}
|
|
|
|
public static void HandleInterrupt_09(ref InterruptContext aContext) {
|
|
HandleException(aContext.EIP,
|
|
"Coprocessor Segment Overrun Exception",
|
|
"Coprocessor Segment Overrun Exception",
|
|
ref aContext);
|
|
}
|
|
|
|
public static void HandleInterrupt_0A(ref InterruptContext aContext) {
|
|
HandleException(aContext.EIP,
|
|
"Bad TSS Exception",
|
|
"Bad TSS Exception",
|
|
ref aContext);
|
|
}
|
|
|
|
public static void HandleInterrupt_0B(ref InterruptContext aContext) {
|
|
HandleException(aContext.EIP,
|
|
"Segment Not Present",
|
|
"Segment Not Present",
|
|
ref aContext);
|
|
}
|
|
|
|
public static void HandleInterrupt_0C(ref InterruptContext aContext) {
|
|
HandleException(aContext.EIP,
|
|
"Stack Fault Exception",
|
|
"Stack Fault Exception",
|
|
ref aContext);
|
|
}
|
|
|
|
public static void HandleInterrupt_0E(ref InterruptContext aContext) {
|
|
HandleException(aContext.EIP,
|
|
"Page Fault Exception",
|
|
"Page Fault Exception",
|
|
ref aContext);
|
|
}
|
|
|
|
public static void HandleInterrupt_0F(ref InterruptContext aContext) {
|
|
HandleException(aContext.EIP,
|
|
"Unknown Interrupt Exception",
|
|
"Unknown Interrupt Exception",
|
|
ref aContext);
|
|
}
|
|
|
|
public static void HandleInterrupt_10(ref InterruptContext aContext) {
|
|
HandleException(aContext.EIP,
|
|
"Coprocessor Fault Exception",
|
|
"Coprocessor Fault Exception",
|
|
ref aContext);
|
|
}
|
|
|
|
public static void HandleInterrupt_11(ref InterruptContext aContext) {
|
|
HandleException(aContext.EIP,
|
|
"Alignment Exception",
|
|
"Alignment Exception",
|
|
ref aContext);
|
|
}
|
|
|
|
public static void HandleInterrupt_12(ref InterruptContext aContext) {
|
|
HandleException(aContext.EIP,
|
|
"Machine Check Exception",
|
|
"Machine Check Exception",
|
|
ref aContext);
|
|
}
|
|
|
|
private static void HandleException(uint aEIP,
|
|
string aDescription,
|
|
string aName,
|
|
ref InterruptContext ctx) {
|
|
const string SysFault = "*** System Fault *** ";
|
|
|
|
//Console.ForegroundColor = ConsoleColor.White;
|
|
//Console.BackgroundColor = ConsoleColor.DarkRed;
|
|
Console.Write(SysFault);
|
|
//for (int i = 0; i < Console.WindowWidth - SysFault.Length; i++)
|
|
// Console.Write(" ");
|
|
|
|
//Console.BackgroundColor = ConsoleColor.Black;
|
|
|
|
Console.Write(aDescription);
|
|
Console.Write(" at ");
|
|
WriteNumber(aEIP,
|
|
32);
|
|
|
|
Console.WriteLine();
|
|
// Console.WriteLine("Register States:");
|
|
// TODO: Register states
|
|
|
|
Cosmos.Hardware.DebugUtil.SendMessage("Exceptions",
|
|
aName);
|
|
Console.WriteLine();
|
|
while (true) {
|
|
;
|
|
}
|
|
}
|
|
|
|
// This is to trick IL2CPU to compile it in
|
|
//TODO: Make a new attribute that IL2CPU sees when scanning to force inclusion so we dont have to do this.
|
|
public static void Init()
|
|
{
|
|
#region Compiler magic
|
|
bool xTest = false;
|
|
if (xTest) {
|
|
unsafe {
|
|
InterruptContext xCtx = new InterruptContext();
|
|
HandleInterrupt_Default(ref xCtx);
|
|
HandleInterrupt_00(ref xCtx);
|
|
HandleInterrupt_01(ref xCtx);
|
|
HandleInterrupt_02(ref xCtx);
|
|
HandleInterrupt_03(ref xCtx);
|
|
HandleInterrupt_04(ref xCtx);
|
|
HandleInterrupt_05(ref xCtx);
|
|
HandleInterrupt_06(ref xCtx);
|
|
HandleInterrupt_07(ref xCtx);
|
|
HandleInterrupt_08(ref xCtx);
|
|
HandleInterrupt_09(ref xCtx);
|
|
HandleInterrupt_0A(ref xCtx);
|
|
HandleInterrupt_0B(ref xCtx);
|
|
HandleInterrupt_0C(ref xCtx);
|
|
HandleInterrupt_0D(ref xCtx);
|
|
HandleInterrupt_0E(ref xCtx);
|
|
HandleInterrupt_0F(ref xCtx);
|
|
HandleInterrupt_10(ref xCtx);
|
|
HandleInterrupt_11(ref xCtx);
|
|
HandleInterrupt_12(ref xCtx);
|
|
HandleInterrupt_20(ref xCtx);
|
|
HandleInterrupt_21(ref xCtx);
|
|
HandleInterrupt_25(ref xCtx);
|
|
HandleInterrupt_2B(ref xCtx);
|
|
HandleInterrupt_2E(ref xCtx);
|
|
HandleInterrupt_2F(ref xCtx);
|
|
HandleInterrupt_30(ref xCtx);
|
|
HandleInterrupt_35(ref xCtx);
|
|
}
|
|
}
|
|
#endregion
|
|
}
|
|
|
|
private static void WriteNumber(uint aValue,
|
|
byte aBitCount) {
|
|
uint xValue = aValue;
|
|
byte xCurrentBits = aBitCount;
|
|
Console.Write("0x");
|
|
while (xCurrentBits >= 4) {
|
|
xCurrentBits -= 4;
|
|
byte xCurrentDigit = (byte)((xValue >> xCurrentBits) & 0xF);
|
|
string xDigitString = null;
|
|
switch (xCurrentDigit) {
|
|
case 0:
|
|
xDigitString = "0";
|
|
goto default;
|
|
case 1:
|
|
xDigitString = "1";
|
|
goto default;
|
|
case 2:
|
|
xDigitString = "2";
|
|
goto default;
|
|
case 3:
|
|
xDigitString = "3";
|
|
goto default;
|
|
case 4:
|
|
xDigitString = "4";
|
|
goto default;
|
|
case 5:
|
|
xDigitString = "5";
|
|
goto default;
|
|
case 6:
|
|
xDigitString = "6";
|
|
goto default;
|
|
case 7:
|
|
xDigitString = "7";
|
|
goto default;
|
|
case 8:
|
|
xDigitString = "8";
|
|
goto default;
|
|
case 9:
|
|
xDigitString = "9";
|
|
goto default;
|
|
case 10:
|
|
xDigitString = "A";
|
|
goto default;
|
|
case 11:
|
|
xDigitString = "B";
|
|
goto default;
|
|
case 12:
|
|
xDigitString = "C";
|
|
goto default;
|
|
case 13:
|
|
xDigitString = "D";
|
|
goto default;
|
|
case 14:
|
|
xDigitString = "E";
|
|
goto default;
|
|
case 15:
|
|
xDigitString = "F";
|
|
goto default;
|
|
default:
|
|
Console.Write(xDigitString);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |