📄 keyboard.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.peripheral;import org.jpc.emulator.motherboard.*;import org.jpc.emulator.memory.*;import org.jpc.emulator.processor.*;import org.jpc.emulator.*;import java.io.*;public class Keyboard extends AbstractHardwareComponent implements IOPortCapable{ /* Keyboard Controller Commands */ private static final byte KBD_CCMD_READ_MODE = (byte)0x20; /* Read mode bits */ private static final byte KBD_CCMD_WRITE_MODE = (byte)0x60; /* Write mode bits */ private static final byte KBD_CCMD_GET_VERSION = (byte)0xA1; /* Get controller version */ private static final byte KBD_CCMD_MOUSE_DISABLE = (byte)0xA7; /* Disable mouse interface */ private static final byte KBD_CCMD_MOUSE_ENABLE = (byte)0xA8; /* Enable mouse interface */ private static final byte KBD_CCMD_TEST_MOUSE = (byte)0xA9; /* Mouse interface test */ private static final byte KBD_CCMD_SELF_TEST = (byte)0xAA; /* Controller self test */ private static final byte KBD_CCMD_KBD_TEST = (byte)0xAB; /* Keyboard interface test */ private static final byte KBD_CCMD_KBD_DISABLE = (byte)0xAD; /* Keyboard interface disable */ private static final byte KBD_CCMD_KBD_ENABLE = (byte)0xAE; /* Keyboard interface enable */ private static final byte KBD_CCMD_READ_INPORT = (byte)0xC0; /* read input port */ private static final byte KBD_CCMD_READ_OUTPORT = (byte)0xD0; /* read output port */ private static final byte KBD_CCMD_WRITE_OUTPORT = (byte)0xD1; /* write output port */ private static final byte KBD_CCMD_WRITE_OBUF = (byte)0xD2; private static final byte KBD_CCMD_WRITE_AUX_OBUF = (byte)0xD3; /* Write to output buffer as if initiated by the auxiliary device */ private static final byte KBD_CCMD_WRITE_MOUSE = (byte)0xD4; /* Write the following byte to the mouse */ private static final byte KBD_CCMD_DISABLE_A20 = (byte)0xDD; /* HP vectra only ? */ private static final byte KBD_CCMD_ENABLE_A20 = (byte)0xDF; /* HP vectra only ? */ private static final byte KBD_CCMD_RESET = (byte)0xFE; /* Keyboard Commands */ private static final byte KBD_CMD_SET_LEDS = (byte)0xED;; /* Set keyboard leds */ private static final byte KBD_CMD_ECHO = (byte)0xEE; private static final byte KBD_CMD_GET_ID = (byte)0xF2; /* get keyboard ID */ private static final byte KBD_CMD_SET_RATE = (byte)0xF3; /* Set typematic rate */ private static final byte KBD_CMD_ENABLE = (byte)0xF4; /* Enable scanning */ private static final byte KBD_CMD_RESET_DISABLE = (byte)0xF5; /* reset and disable scanning */ private static final byte KBD_CMD_RESET_ENABLE = (byte)0xF6; /* reset and enable scanning */ private static final byte KBD_CMD_RESET = (byte)0xFF; /* Reset */ /* Keyboard Replies */ private static final byte KBD_REPLY_POR = (byte)0xAA; /* Power on reset */ private static final byte KBD_REPLY_ACK = (byte)0xFA; /* Command ACK */ private static final byte KBD_REPLY_RESEND = (byte)0xFE; /* Command NACK, send the cmd again */ /* Status Register Bits */ private static final byte KBD_STAT_OBF = (byte)0x01; /* Keyboard output buffer full */ private static final byte KBD_STAT_IBF = (byte)0x02; /* Keyboard input buffer full */ private static final byte KBD_STAT_SELFTEST = (byte)0x04; /* Self test successful */ private static final byte KBD_STAT_CMD = (byte)0x08; /* Last write was a command write (0=data) */ private static final byte KBD_STAT_UNLOCKED = (byte)0x10; /* Zero if keyboard locked */ private static final byte KBD_STAT_MOUSE_OBF = (byte)0x20; /* Mouse output buffer full */ private static final byte KBD_STAT_GTO = (byte)0x40; /* General receive/xmit timeout */ private static final byte KBD_STAT_PERR = (byte)0x80; /* Parity error */ /* Controller Mode Register Bits */ private static final int KBD_MODE_KBD_INT = 0x01; /* Keyboard data generate IRQ1 */ private static final int KBD_MODE_MOUSE_INT = 0x02; /* Mouse data generate IRQ12 */ private static final int KBD_MODE_SYS = 0x04; /* The system flag (?) */ private static final int KBD_MODE_NO_KEYLOCK = 0x08; /* The keylock doesn't affect the keyboard if set */ private static final int KBD_MODE_DISABLE_KBD = 0x10; /* Disable keyboard interface */ private static final int KBD_MODE_DISABLE_MOUSE = 0x20; /* Disable mouse interface */ private static final int KBD_MODE_KCC = 0x40; /* Scan code conversion to PC format */ private static final int KBD_MODE_RFU = 0x80; /* Mouse Commands */ private static final byte AUX_SET_SCALE11 = (byte)0xE6; /* Set 1:1 scaling */ private static final byte AUX_SET_SCALE21 = (byte)0xE7; /* Set 2:1 scaling */ private static final byte AUX_SET_RES = (byte)0xE8; /* Set resolution */ private static final byte AUX_GET_SCALE = (byte)0xE9; /* Get scaling factor */ private static final byte AUX_SET_STREAM = (byte)0xEA; /* Set stream mode */ private static final byte AUX_POLL = (byte)0xEB; /* Poll */ private static final byte AUX_RESET_WRAP = (byte)0xEC; /* Reset wrap mode */ private static final byte AUX_SET_WRAP = (byte)0xEE; /* Set wrap mode */ private static final byte AUX_SET_REMOTE = (byte)0xF0; /* Set remote mode */ private static final byte AUX_GET_TYPE = (byte)0xF2; /* Get type */ private static final byte AUX_SET_SAMPLE = (byte)0xF3; /* Set sample rate */ private static final byte AUX_ENABLE_DEV = (byte)0xF4; /* Enable aux device */ private static final byte AUX_DISABLE_DEV = (byte)0xF5; /* Disable aux device */ private static final byte AUX_SET_DEFAULT = (byte)0xF6; private static final byte AUX_RESET = (byte)0xFF; /* Reset aux device */ private static final byte AUX_ACK = (byte)0xFA; /* Command byte ACK. */ private static final byte MOUSE_STATUS_REMOTE = (byte)0x40; private static final byte MOUSE_STATUS_ENABLED = (byte)0x20; private static final byte MOUSE_STATUS_SCALE21 = (byte)0x10; private static final int MOUSE_TYPE = 0; /* 0 = PS2, 3 = IMPS/2, 4 = IMEX */ private static final int KBD_QUEUE_SIZE = 256; //Instance Variables private KeyboardQueue queue; private byte commandWrite; private byte status; private int mode; /* keyboard state */ private int keyboardWriteCommand; private boolean keyboardScanEnabled; /* mouse state */ //Split this off? private int mouseWriteCommand; private int mouseStatus; private int mouseResolution; private int mouseSampleRate; private boolean mouseWrap; private int mouseDetectState; private int mouseDx; private int mouseDy; private int mouseDz; private int mouseButtons; private boolean ioportRegistered; private InterruptController irqDevice; private Processor cpu; private PhysicalAddressSpace physicalAddressSpace; private LinearAddressSpace linearAddressSpace; public Keyboard() { ioportRegistered = false; queue = new KeyboardQueue(); physicalAddressSpace = null; linearAddressSpace = null; cpu = null; reset(); } public void dumpState(DataOutput output) throws IOException { output.writeByte(commandWrite); output.writeByte(status); output.writeByte(mode); output.writeInt(keyboardWriteCommand); output.writeBoolean(keyboardScanEnabled); output.writeInt(mouseWriteCommand); output.writeInt(mouseStatus); output.writeInt(mouseResolution); output.writeInt(mouseSampleRate); output.writeBoolean(mouseWrap); output.writeInt(mouseDetectState); output.writeInt(mouseDx); output.writeInt(mouseDy); output.writeInt(mouseDz); output.writeInt(mouseButtons); //dump keyboard queue queue.dumpState(output); } public void loadState(DataInput input) throws IOException { ioportRegistered = false; commandWrite = input.readByte(); status = input.readByte(); mode = input.readByte(); keyboardWriteCommand = input.readInt(); keyboardScanEnabled = input.readBoolean(); mouseWriteCommand = input.readInt(); mouseStatus = input.readInt(); mouseResolution = input.readInt(); mouseSampleRate = input.readInt(); mouseWrap = input.readBoolean(); mouseDetectState = input.readInt(); mouseDx = input.readInt(); mouseDy = input.readInt(); mouseDz = input.readInt(); mouseButtons = input.readInt(); //load keyboard queue queue.loadState(input); } //IOPortCapable Methods public int[] ioPortsRequested() { return new int[]{0x60, 0x64}; } public int ioPortReadByte(int address) { switch (address) { case 0x60: return readData(); case 0x64: return 0xff & status; default: return (int)0xffffffff; } } public int ioPortReadWord(int address) { return (0xff & ioPortReadByte(address)) | (0xff00 & ioPortReadByte(address + 1)); } public int ioPortReadLong(int address) { System.out.println("Keyboard Read Long"); return (int)0xffffffff; } public void ioPortWriteByte(int address, int data) { switch (address) { case 0x60: writeData((byte)data); break; case 0x64: writeCommand((byte)data); break; default: } } public void ioPortWriteWord(int address, int data) { ioPortWriteByte(address, data); ioPortWriteByte(address + 1, data >> 8); } public void ioPortWriteLong(int address, int data) { ioPortWriteWord(address, data); ioPortWriteWord(address + 2, data >> 16); } public void reset() { irqDevice = null; cpu = null; physicalAddressSpace = null; linearAddressSpace = null; ioportRegistered = false; keyboardWriteCommand = -1; mouseWriteCommand = -1; mode = KBD_MODE_KBD_INT | KBD_MODE_MOUSE_INT; status = (byte)(KBD_STAT_CMD | KBD_STAT_UNLOCKED); queue.reset(); commandWrite = 0; keyboardWriteCommand = 0; keyboardScanEnabled = false; mouseWriteCommand = 0; mouseStatus = 0; mouseResolution = 0; mouseSampleRate = 0; mouseWrap = false; mouseDetectState = 0; mouseDx = 0; mouseDy = 0; mouseDz = 0; mouseButtons = 0; } private void setGateA20State(boolean value) { physicalAddressSpace.setGateA20State(value); } private synchronized byte readData() { byte val = queue.readData(); updateIRQ(); return val; } private synchronized void writeData(byte data) { switch(commandWrite) { case 0: writeKeyboard(data); break; case KBD_CCMD_WRITE_MODE: mode = 0xff & data; updateIRQ(); break; case KBD_CCMD_WRITE_OBUF: queue.writeData(data, (byte)0); break; case KBD_CCMD_WRITE_AUX_OBUF: queue.writeData(data, (byte)1); break; case KBD_CCMD_WRITE_OUTPORT: setGateA20State((data & 0x2) != 0); if (0x1 != (data & 0x1)) cpu.reset(); break; case KBD_CCMD_WRITE_MOUSE: writeMouse(data); break; default: break; } commandWrite = (byte)0x00; } private synchronized void writeCommand(byte data) { switch(data) { case KBD_CCMD_READ_MODE: queue.writeData((byte)mode, (byte)0); break; case KBD_CCMD_WRITE_MODE: case KBD_CCMD_WRITE_OBUF: case KBD_CCMD_WRITE_AUX_OBUF: case KBD_CCMD_WRITE_MOUSE: case KBD_CCMD_WRITE_OUTPORT: commandWrite = data; break; case KBD_CCMD_MOUSE_DISABLE: mode |= KBD_MODE_DISABLE_MOUSE; break; case KBD_CCMD_MOUSE_ENABLE: mode &= ~KBD_MODE_DISABLE_MOUSE; break; case KBD_CCMD_TEST_MOUSE: queue.writeData((byte)0x00, (byte)0); break; case KBD_CCMD_SELF_TEST: status = (byte)(status | KBD_STAT_SELFTEST); queue.writeData((byte)0x55, (byte)0); break; case KBD_CCMD_KBD_TEST: queue.writeData((byte)0x00, (byte)0); break; case KBD_CCMD_KBD_DISABLE: mode |= KBD_MODE_DISABLE_KBD; updateIRQ(); break; case KBD_CCMD_KBD_ENABLE: mode &= ~KBD_MODE_DISABLE_KBD; updateIRQ(); break; case KBD_CCMD_READ_INPORT: queue.writeData((byte)0x00, (byte)0); break; case KBD_CCMD_READ_OUTPORT: /* XXX: check that */ data = (byte)(0x01 | (physicalAddressSpace.getGateA20State() ? 0x02 : 0x00)); if (0 != (status & KBD_STAT_OBF)) data |= 0x10; if (0 != (status & KBD_STAT_MOUSE_OBF)) data |= 0x20; queue.writeData(data, (byte)0); break; case KBD_CCMD_ENABLE_A20: setGateA20State(true); break; case KBD_CCMD_DISABLE_A20: setGateA20State(false); break; case KBD_CCMD_RESET: cpu.reset(); break; case (byte)0xff: /* ignore that - I don't know what is its use */ break; default: System.err.println("Unsupported Keyboard Command " + Integer.toHexString(0xff & data)); break; } } private synchronized void writeKeyboard(byte data) { switch(keyboardWriteCommand) { default: case -1: switch(data) { case 0x00: queue.writeData(KBD_REPLY_ACK, (byte)0); break; case 0x05: queue.writeData(KBD_REPLY_RESEND, (byte)0); break; case KBD_CMD_GET_ID: queue.writeData(KBD_REPLY_ACK, (byte)0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -