예제 #1
0
        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;
                }
            }
        }
예제 #2
0
        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
                    }
                }
            }
        }