using Cosmos.Core; namespace Cosmos.Core { // PIC is not in hardware becuase its a special core piece like CPU that is not interacted with by anything except Core. // // Remaps the IRQ's to INT20-INT2F /// /// PIC class. Used to manage PIC interrupts. /// public class PIC { // This is here and not in BaseGroups for 2 reasons. // 1) Its needed before the other Basegroups are created. // 2) Its only used by this class, and it also exists in Core. /// /// Master PIC. /// protected IOGroup.PIC Master = new IOGroup.PIC(false); /// /// Slave PIC. /// protected IOGroup.PIC Slave = new IOGroup.PIC(true); /// /// Commands. /// protected enum Cmd { /// /// Initialize. /// Init = 0x10, /// /// End of interrupt. /// EOI = 0x20 } /// /// Master end of interrupt. /// public void EoiMaster() { Master.Cmd.Byte = (byte) Cmd.EOI; } /// /// Slave end of interrupt. /// public void EoiSlave() { Master.Cmd.Byte = (byte) Cmd.EOI; Slave.Cmd.Byte = (byte) Cmd.EOI; } /// /// Create new instance of the class. /// public PIC() { // MTW: to disable PIT, send 0x01 to Master mask // Right now we mask all IRQs. We enable them as we add // support for them. The 0x08 on master MUST remain. IRQ7 // has a problem of "spurious requests" and is therefore unreliable. // It used for LPT2 (and sometimes old 8 bit sound blasters). We likely // won't need either of those for a very long time, so we just mask it // completely. For more info: // http://en.wikipedia.org/wiki/Intel_8259#Spurious_Interrupts //Init(Master, 0x20, 4, 0xFD | 0x08); //Init(Slave, 0x28, 2, 0xFF); //for now enable keyboard, mouse(ps2) Remap(0x20, 0xF8 | 0x08, 0x28, 0xEB); } /// /// Remap master and slave relationship. /// /// Master start. /// Master mask. /// Slave start. /// Slave mask. private void Remap(byte masterStart, byte masterMask, byte slaveStart, byte slaveMask) { #region consts // source: osdev.org #pragma warning disable const byte ICW1_ICW4 = 0x01; // ICW4 (not) needed const byte ICW1_SINGLE = 0x02; // Single (cascade) mode const byte ICW1_INTERVAL4 = 0x04; // Call address interval 4 (8) const byte ICW1_LEVEL = 0x08; // Level triggered (edge) mode const byte ICW1_INIT = 0x10; const byte ICW4_8086 = 0x01; // 8086/88 mode const byte ICW4_AUTO = 0x02; // auto (normal) EOI const byte ICW4_BUF_SLAVE = 0x08; // buffered mode/slave const byte ICW4_BUF_MASTER = 0x0C; // buffered mode/master const byte ICW4_SFNM = 0x10; // special fully nested (not) #pragma warning restore #endregion var xOldMasterMask = Master.Data.Byte; var xOldSlaveMask = Slave.Data.Byte; Master.Cmd.Byte = ICW1_INIT + ICW1_ICW4; IOPort.Wait(); Slave.Cmd.Byte = ICW1_INIT + ICW1_ICW4; IOPort.Wait(); Master.Data.Byte = masterStart; IOPort.Wait(); Slave.Data.Byte = slaveStart; IOPort.Wait(); // magic: Master.Data.Byte = 4; IOPort.Wait(); Slave.Data.Byte = 2; IOPort.Wait(); // set modes: Master.Data.Byte = ICW4_8086; IOPort.Wait(); Slave.Data.Byte = ICW4_8086; IOPort.Wait(); // set masks: Master.Data.Byte = masterMask; IOPort.Wait(); //Slave.Data.Byte = slaveMask; //IOPort.Wait(); } /// /// Initialize PIC. /// /// A PIC. /// A base data port. /// Slave relationship message. /// A mask. protected void Init(IOGroup.PIC aPIC, byte aBase, byte aIDunno, byte aMask) { // We need to remap the PIC interrupt lines to the CPU. The BIOS sets // them in a way compatible for 16 bit mode, but in a way that causes problems // for 32 bit mode. // The only way to remap them however is to completely reinitialize the PICs. byte xOldMask = aPIC.Data.Byte; //#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 */ Master.Cmd.Byte = (byte) Cmd.Init | 0x01; IOPort.Wait(); // ICW2 Master.Data.Byte = aBase; IOPort.Wait(); // ICW3 // Somehow tells them about master/slave relationship Master.Data.Byte = aIDunno; IOPort.Wait(); //#define ICW4_AUTO 0x02 /C:\Data\Cosmos\source2\Kernel\System\Hardware\Core\Cosmos.Core\CPU.cs* 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) */ //0x01 8086/88 (MCS-80/85) mode Master.Data.Byte = 0x01; IOPort.Wait(); // Set mask Master.Data.Byte = aMask; IOPort.Wait(); } } }