public override void Out(uint port, ushort value) { UpdateCh0(); if ((port & 0xFFF8) == 0) { // DMA controller: channel setup Channel chan = channels[(port >> 1) & 3]; int x = 0; int y = 0; if ((port & 1) == 0) { // base/current address x = chan.BaseAddress; y = chan.CurrentAddress; } else { x = chan.BaseCount; y = chan.CurrentCount; } bool p = msbFlipFlop; msbFlipFlop = !p; if (p) { x = (int)((x & 0xFF) | ((value << 8) & 0xFF00)); y = (int)((y & 0xFF) | ((value << 8) & 0xFF00)); } else { x = (int)((x & 0xFF00) | (value & 0xFF)); y = (int)((y & 0xFF00) | (value & 0xFF)); } if ((port & 1) == 0) { chan.BaseAddress = x; chan.CurrentAddress = y; } else { chan.BaseCount = x; chan.CurrentCount = y; } } else if ((port & 0xFFF8) == 0x8) { // DMA controller: operation registers if ((port & 0xF) == ((uint)8)) // write command register { cmdReg = value; if ((value & 0x10) == 0) { prioChannel = 0; // enable fixed priority } if ((value & 1) == 1) { cpu.RaiseException("DMA8237: memory-to-memory transfer not implemented"); } } // set/reset request register else if ((port & 0xF) == ((uint)9)) { if ((value & 4) == 0) { //reqReg = reqReg & (!(1 << (value & 3))); // reset request bit reqReg &= ~(1 << (value & 3)); } else { reqReg = reqReg | (1 << (value & 3)); // set request bit if ((value & 7) == 4) { cpu.RaiseException("DMA8237: software request on channel 0 not implemented"); } } } // set/reset mask register else if ((port & 0xF) == ((uint)10)) { if ((value & 4) == 0) { //MaskReg = MaskReg & (!(1 << (value & 3))); // reset mask bit MaskReg &= ~(1 << (value & 3)); } else { MaskReg = MaskReg | (1 << (value & 3)); // set mask bit } channels[value & 3].Masked = (int)((value >> 2) & 1); } // write mode register else if ((port & 0xF) == ((uint)11)) { channels[value & 3].Mode = value; channels[value & 3].Direction = (int)((value >> 5) & 1); channels[value & 3].AutoInit = (int)((value >> 4) & 1); channels[value & 3].WriteMode = (int)((value >> 2) & 1); if ((value & 3) == 0 && (value & 0xDC) != 0x58) { cpu.RaiseException("DMA8237: unsupported mode on channel 0"); } } // clear msb flipflop else if ((port & 0xF) == ((uint)12)) { msbFlipFlop = false; } // master clear else if ((port & 0xF) == ((uint)13)) { msbFlipFlop = false; cmdReg = 0; statusReg = 0; reqReg = 0; tempReg = 0; MaskReg = 0xF; } // clear mask register else if ((port & 0xF) == ((uint)14)) { MaskReg = 0; } // write mask register else if ((port & 0xF) == ((uint)15)) { MaskReg = value; } TryHandleRequest(); } else if ((port & 0xFFF8) == 0x80) { // DMA page registers if (port == ((uint)(0x81))) { channels[2].Page = value; } else if (port == ((uint)(0x82))) { channels[3].Page = value; } else if (port == ((uint)(0x83))) { channels[1].Page = value; } else if (port == ((uint)(0x87))) { channels[0].Page = value; } } }
private void Run() { ArrayList cleanInputBuf = new ArrayList(); ArrayList inputBuf = new ArrayList(); Task tsk = null; ExternalInputEvent evt = default(ExternalInputEvent); while (true) { // Detect the end of the simulation run if (nextTime == STOPPING) { nextTime = pq.MinPriority(); break; } if (pendingInput.Count > 0) { // Fetch pending input events inputBuf = pendingInput; pendingInput = cleanInputBuf; } else if (nextTime <= mCurrentTime) { // Fetch the next pending task tsk = NextTask(); if (ReferenceEquals(tsk, null)) { continue; // This task was canceled, go round again } inputBuf.Clear(); } else { tsk = null; } if (inputBuf.Count > 0) { // Process pending input events for (int i = 0; i <= inputBuf.Count - 1; i++) { evt = (ExternalInputEvent)(inputBuf[i]); evt.TimeStamp = mCurrentTime; evt.Handler.HandleInput(evt); } inputBuf.Clear(); cleanInputBuf = inputBuf; } else if (tsk != null) { // Run the first pending task tsk.Start(); } else { // Run the CPU simulation for a bit (maxRunCycl) try { mCPU.RunEmulation(); } catch (Exception ex) { X8086.Notify("Shit happens at {0}:{1}: {2}", X8086.NotificationReasons.Fck, mCPU.Registers.CS.ToString("X4"), mCPU.Registers.IP.ToString("X4"), ex.Message); mCPU.RaiseException($"Scheduler Main Loop Error: {ex.Message}"); } if (mCPU.IsHalted) { SkipToNextEvent(); // The CPU is halted, skip immediately to the next event } } } }