35#define STATUS_OBF 0x01
36#define STATUS_IBF 0x02
37#define STATUS_SYSFLAG 0x04
38#define STATUS_CMD 0x08
39#define STATUS_INH 0x10
40#define STATUS_AOBF 0x20
41#define STATUS_TIMEOUT 0x40
42#define STATUS_PARITY_ERR 0x80
46#define CTRLCMD_NONE 0x00
47#define CTRLCMD_GET_COMMAND_BYTE 0x20
48#define CTRLCMD_READ_CONTROLLER_RAM_BEGIN 0x21
49#define CTRLCMD_READ_CONTROLLER_RAM_END 0x3f
50#define CTRLCMD_WRITE_COMMAND_BYTE 0x60
51#define CTRLCMD_WRITE_CONTROLLER_RAM_BEGIN 0x61
52#define CTRLCMD_WRITE_CONTROLLER_RAM_END 0x7f
53#define CTRLCMD_DISABLE_MOUSE_PORT 0xa7
54#define CTRLCMD_ENABLE_MOUSE_PORT 0xa8
55#define CTRLCMD_TEST_MOUSE_PORT 0xa9
56#define CTRLCMD_SELF_TEST 0xaa
57#define CTRLCMD_TEST_KEYBOARD_PORT 0xab
58#define CTRLCMD_DISABLE_KEYBOARD 0xad
59#define CTRLCMD_ENABLE_KEYBOARD 0xae
60#define CTRLCMD_READ_INPUT_PORT 0xc0
61#define CTRLCMD_READ_OUTPUT_PORT 0xd0
62#define CTRLCMD_WRITE_OUTPUT_PORT 0xd1
63#define CTRLCMD_WRITE_KEYBOARD_OUTPUT_BUFFER 0xd2
64#define CTRLCMD_WRITE_MOUSE_OUTPUT_BUFFER 0xd3
65#define CTRLCMD_WRITE_TO_MOUSE 0xd4
66#define CTRLCMD_SYSTEM_RESET 0xfe
70#define CMDBYTE_ENABLE_KEYBOARD_IRQ 0x01
71#define CMDBYTE_ENABLE_MOUSE_IRQ 0x02
72#define CMDBYTE_SYSFLAG 0x04
73#define CMDBYTE_UNUSED1 0x08
74#define CMDBYTE_DISABLE_KEYBOARD 0x10
75#define CMDBYTE_DISABLE_MOUSE 0x20
76#define CMDBYTE_STD_SCAN_CONVERSION 0x40
77#define CMDBYTE_UNUSED2 0x80
96 if (!PS2Controller::initialized())
99 m_PS2Controller.keyboard()->enableVirtualKeys(
false,
false);
100 m_keyboard = m_PS2Controller.keyboard();
101 m_mouse = m_PS2Controller.mouse();
109 m_STATUS = STATUS_SYSFLAG | STATUS_INH;
112 m_commandByte = CMDBYTE_ENABLE_KEYBOARD_IRQ | CMDBYTE_ENABLE_MOUSE_IRQ | CMDBYTE_SYSFLAG | CMDBYTE_STD_SCAN_CONVERSION | CMDBYTE_DISABLE_MOUSE;
114 m_executingCommand = CTRLCMD_NONE;
115 m_writeToMouse =
false;
116 m_mousePacketIdx = -1;
121 m_sysReqTriggered =
false;
125uint8_t i8042::read(
int address)
132 m_STATUS &= ~(STATUS_OBF | STATUS_AOBF);
149void i8042::write(
int address, uint8_t value)
158 m_STATUS = (m_STATUS & ~STATUS_CMD) | STATUS_IBF;
166 m_STATUS |= STATUS_CMD | STATUS_IBF;
176 if ((m_STATUS & STATUS_OBF) == 0 && m_keyboard->scancodeAvailable() && (m_commandByte & CMDBYTE_DISABLE_KEYBOARD) == 0) {
177 if (m_commandByte & CMDBYTE_STD_SCAN_CONVERSION) {
179 int scode2 = m_keyboard->getNextScancode();
181 uint8_t scode = Keyboard::convScancodeSet2To1(scode2);
182 m_DBBOUT = (m_DBBOUT == 0xf0 ? (0x80 | scode) : scode);
184 m_STATUS |= STATUS_OBF;
190 int scode2 = m_keyboard->getNextScancode();
193 m_STATUS |= STATUS_OBF;
199 if ((m_STATUS & STATUS_OBF) == 0 && (m_mousePacketIdx > -1 || m_mouse->packetAvailable()) && (m_commandByte & CMDBYTE_DISABLE_MOUSE) == 0) {
200 if (m_mousePacketIdx == -1)
201 m_mouse->getNextPacket(&m_mousePacket);
202 m_DBBOUT = m_mousePacket.data[++m_mousePacketIdx];
203 if (m_mousePacketIdx == m_mouse->getPacketSize() - 1)
204 m_mousePacketIdx = -1;
205 m_STATUS |= STATUS_OBF | STATUS_AOBF;
210 if (m_STATUS & STATUS_CMD) {
211 m_STATUS &= ~(STATUS_IBF | STATUS_CMD);
216 if ((m_STATUS & STATUS_IBF) && m_executingCommand != CTRLCMD_NONE) {
217 m_STATUS &= ~STATUS_IBF;
222 if (m_STATUS & STATUS_IBF) {
223 m_STATUS &= ~(STATUS_IBF | STATUS_PARITY_ERR);
225 m_mouse->sendCommand(m_DBBIN);
227 m_keyboard->sendCommand(m_DBBIN);
228 m_writeToMouse =
false;
229 m_STATUS |= STATUS_PARITY_ERR * m_keyboard->parityError();
233 if (m_keybIntTrigs && trigKeyboardInterrupt())
235 if (m_mouseIntTrigs && trigMouseInterrupt())
240void i8042::execCommand()
242 uint8_t cmd = m_executingCommand == CTRLCMD_NONE ? m_DBBIN : m_executingCommand;
246 case CTRLCMD_GET_COMMAND_BYTE:
247 m_DBBOUT = m_commandByte;
248 m_STATUS |= STATUS_OBF;
251 case CTRLCMD_WRITE_COMMAND_BYTE:
252 if (m_executingCommand) {
254 updateCommandByte(m_DBBIN);
255 m_executingCommand = CTRLCMD_NONE;
258 m_executingCommand = CTRLCMD_WRITE_COMMAND_BYTE;
262 case CTRLCMD_DISABLE_MOUSE_PORT:
266 case CTRLCMD_ENABLE_MOUSE_PORT:
270 case CTRLCMD_TEST_MOUSE_PORT:
271 m_DBBOUT = m_mouse->isMouseAvailable() ? 0x00 : 0x02;
272 m_STATUS |= STATUS_OBF;
275 case CTRLCMD_SELF_TEST:
277 m_STATUS |= STATUS_OBF;
280 case CTRLCMD_TEST_KEYBOARD_PORT:
281 m_DBBOUT = m_keyboard->isKeyboardAvailable() ? 0x00 : 0x02;
282 m_STATUS |= STATUS_OBF;
285 case CTRLCMD_DISABLE_KEYBOARD:
286 updateCommandByte(m_commandByte | CMDBYTE_DISABLE_KEYBOARD);
289 case CTRLCMD_ENABLE_KEYBOARD:
290 updateCommandByte(m_commandByte & ~CMDBYTE_DISABLE_KEYBOARD);
293 case CTRLCMD_WRITE_TO_MOUSE:
297 case CTRLCMD_SYSTEM_RESET:
302 printf(
"8042: unsupported controller command %02X\n", cmd);
308void i8042::enableMouse(
bool value)
310 updateCommandByte(value ? (m_commandByte & ~CMDBYTE_DISABLE_MOUSE) : (m_commandByte | CMDBYTE_DISABLE_MOUSE));
314void i8042::updateCommandByte(uint8_t newValue)
317 if ((newValue ^ m_commandByte) & CMDBYTE_DISABLE_KEYBOARD) {
318 if (newValue & CMDBYTE_DISABLE_KEYBOARD) {
319 m_keyboard->suspendPort();
321 m_keyboard->resumePort();
326 if ((newValue ^ m_commandByte) & CMDBYTE_DISABLE_MOUSE) {
327 if (newValue & CMDBYTE_DISABLE_MOUSE) {
328 m_mouse->suspendPort();
330 m_mouse->resumePort();
334 m_commandByte = newValue;
339bool i8042::trigKeyboardInterrupt()
341 return m_commandByte & CMDBYTE_ENABLE_KEYBOARD_IRQ ? m_keyboardInterrupt(m_context) : true;
345bool i8042::trigMouseInterrupt()
347 return m_commandByte & CMDBYTE_ENABLE_MOUSE_IRQ ? m_mouseInterrupt(m_context) : true;
352void i8042::checkSysReq(
int scode2)
354 if (m_DBBOUT == 0xf0) {
355 if (scode2 == 0x84) {
356 m_sysReqTriggered =
true;
357 }
else if (m_sysReqTriggered && scode2 == 0x11) {
358 m_sysReqTriggered =
false;
static void quickCheckHardware()
Disable re-try when a mouse is not found.
@ KeyboardPort0_MousePort1