DevPS2.cpp revision 846d020b7ea3d570a7addeda15cce8bb91e7229b
deb4998ba50060c48cce222fd18a8eed053918d7vboxsync * DevPS2 - PS/2 keyboard & mouse controller device.
deb4998ba50060c48cce222fd18a8eed053918d7vboxsync * Copyright (C) 2006-2013 Oracle Corporation
deb4998ba50060c48cce222fd18a8eed053918d7vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
deb4998ba50060c48cce222fd18a8eed053918d7vboxsync * available from http://www.virtualbox.org. This file is free software;
deb4998ba50060c48cce222fd18a8eed053918d7vboxsync * you can redistribute it and/or modify it under the terms of the GNU
deb4998ba50060c48cce222fd18a8eed053918d7vboxsync * General Public License (GPL) as published by the Free Software
deb4998ba50060c48cce222fd18a8eed053918d7vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
deb4998ba50060c48cce222fd18a8eed053918d7vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
deb4998ba50060c48cce222fd18a8eed053918d7vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
deb4998ba50060c48cce222fd18a8eed053918d7vboxsync * --------------------------------------------------------------------
deb4998ba50060c48cce222fd18a8eed053918d7vboxsync * This code is based on:
deb4998ba50060c48cce222fd18a8eed053918d7vboxsync * QEMU PC keyboard emulation (revision 1.12)
deb4998ba50060c48cce222fd18a8eed053918d7vboxsync * Copyright (c) 2003 Fabrice Bellard
deb4998ba50060c48cce222fd18a8eed053918d7vboxsync * Permission is hereby granted, free of charge, to any person obtaining a copy
deb4998ba50060c48cce222fd18a8eed053918d7vboxsync * of this software and associated documentation files (the "Software"), to deal
deb4998ba50060c48cce222fd18a8eed053918d7vboxsync * in the Software without restriction, including without limitation the rights
deb4998ba50060c48cce222fd18a8eed053918d7vboxsync * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
deb4998ba50060c48cce222fd18a8eed053918d7vboxsync * copies of the Software, and to permit persons to whom the Software is
deb4998ba50060c48cce222fd18a8eed053918d7vboxsync * furnished to do so, subject to the following conditions:
#include "VBoxDD.h"
#include "PS2Dev.h"
#define TARGET_I386
#ifndef VBOX_WITH_NEW_PS2M
#ifndef VBOX_DEVICE_STRUCT_TESTCASE
PDMBOTHCBDECL(int) kbdIOPortDataRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
PDMBOTHCBDECL(int) kbdIOPortDataWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
PDMBOTHCBDECL(int) kbdIOPortStatusRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
PDMBOTHCBDECL(int) kbdIOPortCommandWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
#define DEBUG_KBD
#define DEBUG_MOUSE
#ifndef VBOX_WITH_NEW_PS2M
MOUSE_PROT_PS2 = 0,
int rptr;
int wptr;
int count;
* The keyboard controller/device state.
typedef struct KBDState
#ifndef VBOX_WITH_NEW_PS2M
#ifndef VBOX_WITH_NEW_PS2M
#ifdef VBOX_DEVICE_STRUCT_TESTCASE
#ifdef VBOX_WITH_NEW_PS2M
#ifdef VBOX_DEVICE_STRUCT_TESTCASE
} Mouse;
} KBDState;
#ifndef VBOX_DEVICE_STRUCT_TESTCASE
#ifndef VBOX_WITH_NEW_PS2M
irq1_level = 0;
irq12_level = 0;
bool fHaveData = true;
if (s->translate)
fHaveData = false;
if (fHaveData)
#ifdef VBOX_WITH_NEW_PS2M
kbd_update_irq(s);
#ifndef VBOX_WITH_NEW_PS2M
#ifdef DEBUG_KBD
switch (aux)
kbd_update_irq(s);
#if defined(DEBUG_KBD)
return val;
#ifdef DEBUG_KBD
switch(val) {
case KBD_CCMD_READ_MODE:
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:
case KBD_CCMD_MOUSE_DISABLE:
case KBD_CCMD_MOUSE_ENABLE:
kbd_update_irq(s);
case KBD_CCMD_TEST_MOUSE:
case KBD_CCMD_SELF_TEST:
# ifndef IN_RING3
case KBD_CCMD_KBD_TEST:
case KBD_CCMD_KBD_DISABLE:
case KBD_CCMD_KBD_ENABLE:
kbd_update_irq(s);
case KBD_CCMD_READ_INPORT:
case KBD_CCMD_READ_OUTPORT:
#ifdef TARGET_I386
#ifdef TARGET_I386
case KBD_CCMD_ENABLE_A20:
# ifndef IN_RING3
case KBD_CCMD_DISABLE_A20:
# ifndef IN_RING3
case KBD_CCMD_READ_TSTINP:
case KBD_CCMD_RESET:
case KBD_CCMD_RESET_ALT:
#ifndef IN_RING3
kbc_dbb_out(s, 0);
return rc;
kbd_update_irq(s);
#ifdef DEBUG_KBD
return val;
#ifdef VBOX_WITH_NEW_PS2M
return NULL;
#ifndef VBOX_WITH_NEW_PS2M
| fButtonsLow;
if (s->mouse_dw > 0)
else if (s->mouse_dw < 0)
else if (s->mouse_dz > 0)
else if (s->mouse_dz < 0)
#ifdef IN_RING3
return s->mouse_dx
|| s->mouse_dy
|| s->mouse_dz
|| s->mouse_dw
int buttons_state)
while ( kbd_mouse_unreported(s)
kbd_mouse_send_packet(s, false);
if (pDrv)
#ifdef DEBUG_MOUSE
switch(s->mouse_write_cmd) {
if (s->mouse_wrap) {
s->mouse_wrap = 0;
return VINF_SUCCESS;
return VINF_SUCCESS;
switch(val) {
case AUX_SET_SCALE11:
case AUX_SET_SCALE21:
case AUX_SET_STREAM:
case AUX_SET_WRAP:
case AUX_SET_REMOTE:
case AUX_GET_TYPE:
case AUX_SET_RES:
case AUX_SET_SAMPLE:
case AUX_GET_SCALE:
case AUX_POLL:
kbd_mouse_send_packet(s, true);
case AUX_ENABLE_DEV:
#ifdef IN_RING3
case AUX_DISABLE_DEV:
#ifdef IN_RING3
case AUX_SET_DEFAULT:
#ifdef IN_RING3
s->mouse_status = 0;
case AUX_RESET:
#ifdef IN_RING3
s->mouse_status = 0;
case AUX_SET_SAMPLE:
switch(s->mouse_detect_state) {
s->mouse_detect_state = 0;
s->mouse_detect_state = 0;
s->mouse_detect_state = 0;
s->mouse_detect_state = 0;
case AUX_SET_RES:
return rc;
#ifdef DEBUG_KBD
switch(s->write_cmd) {
kbd_update_irq(s);
case KBD_CCMD_WRITE_MODE:
kbd_update_irq(s);
case KBD_CCMD_WRITE_OBUF:
case KBD_CCMD_WRITE_AUX_OBUF:
case KBD_CCMD_WRITE_OUTPORT:
#ifdef TARGET_I386
# ifndef IN_RING3
# ifndef IN_RING3
case KBD_CCMD_WRITE_MOUSE:
#ifdef VBOX_WITH_NEW_PS2M
kbd_update_irq(s);
s->write_cmd = 0;
return rc;
#ifdef IN_RING3
#ifndef VBOX_WITH_NEW_PS2M
s->write_cmd = 0;
s->translate = 0;
#ifndef VBOX_WITH_NEW_PS2M
if (s->mouse_status)
s->mouse_status = 0;
s->mouse_resolution = 0;
s->mouse_sample_rate = 0;
s->mouse_wrap = 0;
s->mouse_detect_state = 0;
s->mouse_dx = 0;
s->mouse_dy = 0;
s->mouse_dz = 0;
s->mouse_dw = 0;
s->mouse_flags = 0;
s->mouse_buttons = 0;
s->mouse_buttons_reported = 0;
#ifndef VBOX_WITH_NEW_PS2M
#ifndef VBOX_WITH_NEW_PS2M
for (i = s->mouse_command_queue.rptr; cItems-- > 0; i = (i + 1) % RT_ELEMENTS(s->mouse_command_queue.data))
for (i = s->mouse_event_queue.rptr; cItems-- > 0; i = (i + 1) % RT_ELEMENTS(s->mouse_event_queue.data))
int rc;
#ifndef VBOX_WITH_NEW_PS2M
return rc;
for (i = 0; i < u32; i++)
return rc;
#ifndef VBOX_WITH_NEW_PS2M
return rc;
for (i = 0; i < u32; i++)
return rc;
return rc;
for (i = 0; i < u32; i++)
return rc;
return rc;
for (i = 0; i < u32; i++)
return rc;
return rc;
for (i = 0; i < u32; i++)
return rc;
return rc;
if (u32 != ~0U)
#ifndef VBOX_WITH_NEW_PS2M
PDMBOTHCBDECL(int) kbdIOPortDataRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
return VINF_SUCCESS;
return VERR_IOM_IOPORT_UNUSED;
PDMBOTHCBDECL(int) kbdIOPortDataWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
return rc;
PDMBOTHCBDECL(int) kbdIOPortStatusRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
return VINF_SUCCESS;
return VERR_IOM_IOPORT_UNUSED;
PDMBOTHCBDECL(int) kbdIOPortCommandWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
return rc;
#ifdef IN_RING3
#ifdef VBOX_WITH_NEW_PS2M
return VINF_SUCCESS;
static DECLCALLBACK(int) kbdLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
int rc;
#ifdef VBOX_WITH_NEW_PS2M
return rc;
int rc;
return rc;
#ifdef VBOX_WITH_NEW_PS2M
#ifndef VBOX_WITH_NEW_PS2M
return NULL;
return VINF_SUCCESS;
int rc;
switch (iLUN)
return rc;
#ifdef VBOX_WITH_NEW_PS2M
rc = PDMDevHlpDriverAttach(pDevIns, iLUN, &pThis->Mouse.IBase, &pThis->Mouse.pDrvBase, "Aux (Mouse) Port");
Log(("%s/%d: warning: no driver attached to LUN #1!\n", pDevIns->pReg->szName, pDevIns->iInstance));
return VERR_PDM_NO_SUCH_LUN;
return rc;
switch (iLUN)
#ifdef VBOX_WITH_NEW_PS2M
int rc;
bool fGCEnabled;
bool fR0Enabled;
return rc;
#ifdef VBOX_WITH_NEW_PS2M
return rc;
rc = PDMDevHlpIOPortRegister(pDevIns, 0x60, 1, NULL, kbdIOPortDataWrite, kbdIOPortDataRead, NULL, NULL, "PC Keyboard - Data");
return rc;
rc = PDMDevHlpIOPortRegister(pDevIns, 0x64, 1, NULL, kbdIOPortCommandWrite, kbdIOPortStatusRead, NULL, NULL, "PC Keyboard - Command / Status");
return rc;
if (fGCEnabled)
rc = PDMDevHlpIOPortRegisterRC(pDevIns, 0x60, 1, 0, "kbdIOPortDataWrite", "kbdIOPortDataRead", NULL, NULL, "PC Keyboard - Data");
return rc;
rc = PDMDevHlpIOPortRegisterRC(pDevIns, 0x64, 1, 0, "kbdIOPortCommandWrite", "kbdIOPortStatusRead", NULL, NULL, "PC Keyboard - Command / Status");
return rc;
if (fR0Enabled)
rc = PDMDevHlpIOPortRegisterR0(pDevIns, 0x60, 1, 0, "kbdIOPortDataWrite", "kbdIOPortDataRead", NULL, NULL, "PC Keyboard - Data");
return rc;
rc = PDMDevHlpIOPortRegisterR0(pDevIns, 0x64, 1, 0, "kbdIOPortCommandWrite", "kbdIOPortStatusRead", NULL, NULL, "PC Keyboard - Command / Status");
return rc;
return rc;
return rc;
return rc;
return VINF_SUCCESS;
PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT | PDM_DEVREG_FLAGS_GUEST_BITS_32_64 | PDM_DEVREG_FLAGS_PAE36 | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0,
sizeof(KBDState),
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,