📄 interruptcontroller.java
字号:
/* JPC: A x86 PC Hardware Emulator for a pure Java Virtual Machine Release Version 2.0 A project from the Physics Dept, The University of Oxford Copyright (C) 2007 Isis Innovation Limited This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Details (including contact information) can be found at: www.physics.ox.ac.uk/jpc*/package org.jpc.emulator.motherboard;import org.jpc.emulator.processor.*;import org.jpc.emulator.HardwareComponent;import java.io.*;/** * i8259 Programmable Interrupt Controller emulation. */public class InterruptController implements IOPortCapable, HardwareComponent{ private InterruptControllerElement master; private InterruptControllerElement slave; private Processor connectedCPU; public InterruptController() { ioportRegistered = false; master = new InterruptControllerElement(true); slave = new InterruptControllerElement(false); } public void dumpState(DataOutput output) throws IOException { master.dumpState(output); slave.dumpState(output); } public void loadState(DataInput input) throws IOException { ioportRegistered = false; master.loadState(input); slave.loadState(input); } private void updateIRQ() { int slaveIRQ, masterIRQ; /* first look at slave irq */ slaveIRQ = slave.getIRQ(); if (slaveIRQ >= 0) { /* if irq request by slave pic, signal Master PIC */ master.setIRQ(2,1); master.setIRQ(2,0); } /* look at requested IRQ */ masterIRQ = master.getIRQ(); if(masterIRQ >= 0) { connectedCPU.raiseInterrupt(); } } public void setIRQ(int irqNumber, int level) { switch (irqNumber >>> 3) { case 0: //master master.setIRQ(irqNumber & 7, level); this.updateIRQ(); break; case 1: //slave slave.setIRQ(irqNumber & 7, level); this.updateIRQ(); break; default: } } public int cpuGetInterrupt() { int masterIRQ, slaveIRQ; /* read the irq from the PIC */ masterIRQ = master.getIRQ(); if (masterIRQ >= 0) { master.intAck(masterIRQ); if (masterIRQ == 2) { slaveIRQ = slave.getIRQ(); if (slaveIRQ >= 0) { slave.intAck(slaveIRQ); } else { /* spurious IRQ on slave controller */ slaveIRQ = 7; } this.updateIRQ(); return slave.irqBase + slaveIRQ; //masterIRQ = slaveIRQ + 8; } else { this.updateIRQ(); return master.irqBase + masterIRQ; } } else { /* spurious IRQ on host controller */ masterIRQ = 7; this.updateIRQ(); return master.irqBase + masterIRQ; } } private int intAckRead() { int ret = master.pollRead(0x00); if (ret == 2) ret = slave.pollRead(0x80) + 8; master.readRegisterSelect = true; return ret; } private class InterruptControllerElement { private byte lastInterruptRequestRegister; //edge detection private byte interruptRequestRegister; private byte interruptMaskRegister; private byte interruptServiceRegister; private int priorityAdd; // highest IRQ priority private int irqBase; private boolean readRegisterSelect; private boolean poll; private boolean specialMask; private int initState; private boolean fourByteInit; private byte elcr; //(elcr) PIIX3 edge/level trigger selection private byte elcrMask; private boolean specialFullyNestedMode; private boolean autoEOI; private boolean rotateOnAutoEOI; private int[] ioPorts; public InterruptControllerElement(boolean master) { if (master == true) { ioPorts = new int[]{0x20, 0x21, 0x4d0}; elcrMask = (byte)0xf8; } else { ioPorts = new int[]{0xa0, 0xa1, 0x4d1}; elcrMask = (byte)0xde; } } public void dumpState(DataOutput output) throws IOException { output.writeByte(lastInterruptRequestRegister); output.writeByte(interruptRequestRegister); output.writeByte(interruptMaskRegister); output.writeByte(interruptServiceRegister); output.writeInt(priorityAdd); output.writeInt(irqBase); output.writeBoolean(readRegisterSelect); output.writeBoolean(poll); output.writeBoolean(specialMask); output.writeInt(initState); output.writeBoolean(autoEOI); output.writeBoolean(rotateOnAutoEOI); output.writeBoolean(specialFullyNestedMode); output.writeBoolean(fourByteInit); output.writeByte(elcr); output.writeByte(elcrMask); output.writeInt(ioPorts.length); for (int i=0; i< ioPorts.length; i++) output.writeInt(ioPorts[i]); } public void loadState(DataInput input) throws IOException { lastInterruptRequestRegister = input.readByte(); interruptRequestRegister = input.readByte(); interruptMaskRegister = input.readByte(); interruptServiceRegister = input.readByte(); priorityAdd = input.readInt(); irqBase = input.readInt(); readRegisterSelect = input.readBoolean(); poll = input.readBoolean(); specialMask = input.readBoolean(); initState = input.readInt(); autoEOI = input.readBoolean(); rotateOnAutoEOI = input.readBoolean(); specialFullyNestedMode = input.readBoolean(); fourByteInit = input.readBoolean(); elcr = input.readByte(); elcrMask = input.readByte(); int len = input.readInt(); ioPorts = new int[len]; for (int i=0; i< len; i++) ioPorts[i] = input.readInt(); } /* BEGIN IOPortCapable Methods */ public int[] ioPortsRequested() { return ioPorts; } public byte ioPortRead(int address) { if(poll) { poll = false; return (byte)this.pollRead(address); } if ((address & 1) == 0) { if (readRegisterSelect) { return interruptServiceRegister; } return interruptRequestRegister; } return interruptMaskRegister; } public byte elcrRead() { return elcr; } public boolean ioPortWrite(int address, byte data) //t/f updateIRQ { int priority, command, irq; address &= 1; if (address == 0) { if (0 != (data & 0x10)) { /* init */ this.reset(); connectedCPU.clearInterrupt(); initState = 1; fourByteInit = ((data & 1) != 0); if (0 != (data & 0x02)) System.err.println("single mode not supported"); if (0 != (data & 0x08)) System.err.println("level sensitive irq not supported"); } else if (0 != (data & 0x08)) { if (0 != (data & 0x04)) poll = true; if (0 != (data & 0x02)) readRegisterSelect = ((data & 0x01) != 0); if (0 != (data & 0x40)) specialMask = (((data >>> 5) & 1) != 0); } else { command = data >>> 5; switch(command) { case 0: case 4: rotateOnAutoEOI = ((command >>> 2) != 0); break; case 1: // end of interrupt case 5: priority = this.getPriority(interruptServiceRegister); if (priority != 8) { irq = (priority + priorityAdd) & 7; interruptServiceRegister = (byte)(interruptServiceRegister & ~(1 << irq)); if (command == 5) priorityAdd = (irq + 1) & 7; return true; } break; case 3: irq = data & 7; interruptServiceRegister = (byte)(interruptServiceRegister & ~(1 << irq)); return true; case 6: priorityAdd = (data + 1) & 7; return true; case 7: irq = data & 7; interruptServiceRegister = (byte)(interruptServiceRegister & ~(1 << irq)); priorityAdd = (irq + 1) & 7; return true; default: /* no operation */ break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -