Rewrite of the MS busmouse support to make it work with DOS and Win95 drivers.
The device exists for some years now, but it was never functional and it is not yet mentioned in the docs. After studying Linux kernel sources and a lot of tests it is now usable. A configure option doesn't exist, so it must be enabled in config.h. At runtime it is only loaded if the mouse type is set to 'bus'.
This commit is contained in:
parent
49c639e00d
commit
59faa4d3ae
@ -2,7 +2,7 @@
|
||||
// $Id$
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2004-2009 The Bochs Project
|
||||
// Copyright (C) 2004-2013 The Bochs Project
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@ -35,13 +35,25 @@
|
||||
|
||||
bx_busm_c *theBusMouse = NULL;
|
||||
|
||||
#define BUS_MOUSE_IRQ 5
|
||||
|
||||
#define PORT_CONTROL 0x023C
|
||||
#define PORT_DATA 0x023D
|
||||
#define PORT_SIGNATURE 0x023E
|
||||
#define PORT_CONFIG 0x023F
|
||||
|
||||
#define BUSM_CTRL_READ_BUTTONS 0x00
|
||||
#define BUSM_CTRL_READ_X 0x01
|
||||
#define BUSM_CTRL_READ_Y 0x02
|
||||
#define BUSM_CTRL_COMMAND 0x07
|
||||
|
||||
int libbusmouse_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[])
|
||||
{
|
||||
// Create one instance of the busmouse device object.
|
||||
theBusMouse = new bx_busm_c();
|
||||
// Register this device.
|
||||
BX_REGISTER_DEVICE_DEVMODEL (plugin, type, theBusMouse, BX_PLUGIN_BUSMOUSE);
|
||||
return(0); // Success
|
||||
BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theBusMouse, BX_PLUGIN_BUSMOUSE);
|
||||
return 0; // Success
|
||||
}
|
||||
|
||||
void libbusmouse_LTX_plugin_fini(void)
|
||||
@ -78,53 +90,35 @@ void bx_busm_c::init(void)
|
||||
|
||||
BX_BUSM_THIS mouse_delayed_dx = 0;
|
||||
BX_BUSM_THIS mouse_delayed_dy = 0;
|
||||
BX_BUSM_THIS mouse_buttons = 0;
|
||||
BX_BUSM_THIS current_x =
|
||||
BX_BUSM_THIS current_y =
|
||||
BX_BUSM_THIS current_b = 0;
|
||||
|
||||
BX_BUSM_THIS sig_port_sequ = 0;
|
||||
BX_BUSM_THIS interrupts = 0; // interrupts off
|
||||
BX_BUSM_THIS command_val = 0; // command byte
|
||||
BX_BUSM_THIS cur_command = 0;
|
||||
BX_BUSM_THIS control_val = 0; // the control port value
|
||||
BX_BUSM_THIS command_val = 0; // command byte
|
||||
BX_BUSM_THIS sig_port_sequ = 0; // signature byte toggle
|
||||
BX_BUSM_THIS interrupts = 0; // interrupts off
|
||||
BX_BUSM_THIS needs_update = 0;
|
||||
|
||||
// the control port values
|
||||
BX_BUSM_THIS control_val =
|
||||
BX_BUSM_THIS control.mode_set =
|
||||
BX_BUSM_THIS control.modeA_select =
|
||||
BX_BUSM_THIS control.portA_dir =
|
||||
BX_BUSM_THIS control.portC_upper_dir =
|
||||
BX_BUSM_THIS control.modeBC_select =
|
||||
BX_BUSM_THIS control.portB_dir =
|
||||
BX_BUSM_THIS control.portC_lower_dir =
|
||||
BX_BUSM_THIS control_val = 0;
|
||||
|
||||
BX_INFO(("Initialized BusMouse"));
|
||||
BX_INFO(("BusMouse initialized"));
|
||||
}
|
||||
|
||||
void bx_busm_c::register_state(void)
|
||||
{
|
||||
bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "busmouse", "Busmouse State");
|
||||
BXRS_HEX_PARAM_FIELD(list, mouse_delayed_dx, BX_BUSM_THIS mouse_delayed_dx);
|
||||
BXRS_HEX_PARAM_FIELD(list, mouse_delayed_dx, BX_BUSM_THIS mouse_delayed_dy);
|
||||
BXRS_DEC_PARAM_FIELD(list, mouse_delayed_dx, BX_BUSM_THIS mouse_delayed_dx);
|
||||
BXRS_DEC_PARAM_FIELD(list, mouse_delayed_dy, BX_BUSM_THIS mouse_delayed_dy);
|
||||
BXRS_HEX_PARAM_FIELD(list, mouse_buttons, BX_BUSM_THIS mouse_buttons);
|
||||
BXRS_HEX_PARAM_FIELD(list, current_x, BX_BUSM_THIS current_x);
|
||||
BXRS_HEX_PARAM_FIELD(list, current_y, BX_BUSM_THIS current_y);
|
||||
BXRS_HEX_PARAM_FIELD(list, current_b, BX_BUSM_THIS current_b);
|
||||
BXRS_HEX_PARAM_FIELD(list, sig_port_sequ, BX_BUSM_THIS sig_port_sequ);
|
||||
|
||||
BXRS_HEX_PARAM_FIELD(list, control_val, BX_BUSM_THIS control_val);
|
||||
|
||||
bx_list_c *ctrl = new bx_list_c(list, "control");
|
||||
BXRS_PARAM_BOOL(ctrl, mode_set, BX_BUSM_THIS control.mode_set);
|
||||
BXRS_HEX_PARAM_FIELD(ctrl, modeA_select, BX_BUSM_THIS control.modeA_select);
|
||||
BXRS_PARAM_BOOL(ctrl, portA_dir, BX_BUSM_THIS control.portA_dir);
|
||||
BXRS_PARAM_BOOL(ctrl, portC_upper_dir, BX_BUSM_THIS control.portC_upper_dir);
|
||||
BXRS_PARAM_BOOL(ctrl, modeBC_select, BX_BUSM_THIS control.modeBC_select);
|
||||
BXRS_PARAM_BOOL(ctrl, portB_dir, BX_BUSM_THIS control.portB_dir);
|
||||
BXRS_PARAM_BOOL(ctrl, portC_lower_dir, BX_BUSM_THIS control.portC_lower_dir);
|
||||
|
||||
BXRS_PARAM_BOOL(list, interrupts, BX_BUSM_THIS interrupts);
|
||||
BXRS_PARAM_BOOL(list, packet_update, BX_BUSM_THIS packet_update);
|
||||
BXRS_HEX_PARAM_FIELD(list, cur_command, BX_BUSM_THIS cur_command);
|
||||
BXRS_HEX_PARAM_FIELD(list, command_val, BX_BUSM_THIS command_val);
|
||||
BXRS_PARAM_BOOL(list, sig_port_sequ, BX_BUSM_THIS sig_port_sequ);
|
||||
BXRS_PARAM_BOOL(list, interrupts, BX_BUSM_THIS interrupts);
|
||||
BXRS_PARAM_BOOL(list, needs_update, BX_BUSM_THIS needs_update);
|
||||
}
|
||||
|
||||
// static IO port read callback handler
|
||||
@ -145,47 +139,41 @@ Bit32u bx_busm_c::read(Bit32u address, unsigned io_len)
|
||||
Bit8u value = 0;
|
||||
|
||||
switch (address) {
|
||||
case 0x023C:
|
||||
case PORT_CONTROL:
|
||||
value = BX_BUSM_THIS control_val;
|
||||
/* value = (BX_BUSM_THIS control.mode_set ? 1<<7 : 0)
|
||||
* | (BX_BUSM_THIS control.modeA_select <<5)
|
||||
* | (BX_BUSM_THIS control.portA_dir ? 1<<4 : 0)
|
||||
* | (BX_BUSM_THIS control.portC_upper_dir ? 1<<3 : 0)
|
||||
* | (BX_BUSM_THIS control.modeBC_select ? 1<<2 : 0)
|
||||
* | (BX_BUSM_THIS control.portB_dir ? 1<<1 : 0)
|
||||
* | (BX_BUSM_THIS control.portC_lower_dir ? 1<<0 : 0);
|
||||
*/ break;
|
||||
case 0x023D: // data
|
||||
switch (BX_BUSM_THIS cur_command) {
|
||||
case 0x00: // read buttons
|
||||
break;
|
||||
case PORT_DATA:
|
||||
switch (BX_BUSM_THIS control_val) {
|
||||
case BUSM_CTRL_READ_BUTTONS:
|
||||
value = BX_BUSM_THIS current_b;
|
||||
break;
|
||||
case 0x01: // read x
|
||||
case BUSM_CTRL_READ_X:
|
||||
value = BX_BUSM_THIS current_x;
|
||||
break;
|
||||
case 0x02: // read y
|
||||
case BUSM_CTRL_READ_Y:
|
||||
value = BX_BUSM_THIS current_y;
|
||||
break;
|
||||
case 0x07: // command mode
|
||||
case BUSM_CTRL_COMMAND:
|
||||
value = BX_BUSM_THIS command_val;
|
||||
break;
|
||||
default:
|
||||
BX_PANIC(("Unknown command to data port: %x", BX_BUSM_THIS cur_command));
|
||||
BX_ERROR(("Reading data port in unsupported mode 0x%02x", BX_BUSM_THIS control_val));
|
||||
}
|
||||
break;
|
||||
case 0x023E: // sig
|
||||
if (!(BX_BUSM_THIS sig_port_sequ & 1))
|
||||
case PORT_SIGNATURE:
|
||||
if (!BX_BUSM_THIS sig_port_sequ) {
|
||||
value = 0xDE;
|
||||
else
|
||||
value = 0x22; // Manufacture id?
|
||||
BX_BUSM_THIS sig_port_sequ++;
|
||||
} else {
|
||||
value = 0x22; // Manufacturer id ?
|
||||
}
|
||||
BX_BUSM_THIS sig_port_sequ ^= 1;
|
||||
break;
|
||||
case 0x023F:
|
||||
BX_PANIC(("Read from port 0x023F"));
|
||||
case PORT_CONFIG:
|
||||
BX_ERROR(("Unsupported read from port 0x%04x", address));
|
||||
break;
|
||||
}
|
||||
|
||||
BX_INFO(("read from address 0x%04x, value = 0x%02x ", address, value));
|
||||
BX_DEBUG(("read from address 0x%04x, value = 0x%02x ", address, value));
|
||||
|
||||
return value;
|
||||
}
|
||||
@ -206,66 +194,44 @@ void bx_busm_c::write(Bit32u address, Bit32u value, unsigned io_len)
|
||||
UNUSED(this_ptr);
|
||||
#endif // !BX_USE_BUSM_SMF
|
||||
|
||||
BX_INFO(("write to address 0x%04x, value = 0x%02x ", address, value));
|
||||
BX_DEBUG(("write to address 0x%04x, value = 0x%02x ", address, value));
|
||||
|
||||
switch (address) {
|
||||
case 0x023C: // control
|
||||
BX_BUSM_THIS control.mode_set = (value & 0x80) ? 1 : 0;
|
||||
BX_BUSM_THIS control.modeA_select = (value & 0x60) >> 5;
|
||||
BX_BUSM_THIS control.portA_dir = (value & 0x10) ? 1 : 0;
|
||||
BX_BUSM_THIS control.portC_upper_dir = (value & 0x08) ? 1 : 0;
|
||||
BX_BUSM_THIS control.modeBC_select = (value & 0x04) ? 1 : 0;
|
||||
BX_BUSM_THIS control.portB_dir = (value & 0x02) ? 1 : 0;
|
||||
BX_BUSM_THIS control.portC_lower_dir = (value & 0x01) ? 1 : 0;
|
||||
BX_BUSM_THIS control_val = value;
|
||||
|
||||
/*
|
||||
switch (value) {
|
||||
case 0x00: // read buttons
|
||||
case 0x01: // read x
|
||||
case 0x02: // read y
|
||||
case 0x07:
|
||||
BX_BUSM_THIS cur_command = (Bit8u) value;
|
||||
break;
|
||||
case 0x80: // reset
|
||||
BX_BUSM_THIS cur_command = 0x00;
|
||||
BX_BUSM_THIS command_val = 0x80;
|
||||
break;
|
||||
default:
|
||||
BX_PANIC(("Unknown command to control port %x", value));
|
||||
}
|
||||
*/
|
||||
case PORT_CONTROL:
|
||||
BX_BUSM_THIS control_val = value & 0x07;
|
||||
break;
|
||||
case 0x023D: // data port
|
||||
switch (BX_BUSM_THIS cur_command) {
|
||||
case 0x07: // command mode
|
||||
switch (value) {
|
||||
case 0x10: // interrupts off
|
||||
BX_BUSM_THIS interrupts = 0;
|
||||
break;
|
||||
case 0x11: // interrupts on
|
||||
BX_BUSM_THIS interrupts = 1;
|
||||
break;
|
||||
default:
|
||||
BX_BUSM_THIS command_val = value;
|
||||
if ((value & 0x20) == 0)
|
||||
DEV_pic_lower_irq(BUS_MOUSE_IRQ);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
BX_PANIC(("Unknown command written to data port: %x", BX_BUSM_THIS cur_command));
|
||||
case PORT_DATA:
|
||||
if (BX_BUSM_THIS control_val == BUSM_CTRL_COMMAND) {
|
||||
if ((value & 0x20) == 0x20) {
|
||||
BX_BUSM_THIS update_mouse_data();
|
||||
} else {
|
||||
DEV_pic_lower_irq(BUS_MOUSE_IRQ);
|
||||
}
|
||||
switch (value) {
|
||||
case 0x10: // interrupts off
|
||||
BX_BUSM_THIS interrupts = 0;
|
||||
break;
|
||||
case 0x09:
|
||||
case 0x11: // interrupts on
|
||||
BX_BUSM_THIS interrupts = 1;
|
||||
break;
|
||||
case 0x16: // test irq
|
||||
DEV_pic_raise_irq(BUS_MOUSE_IRQ);
|
||||
break;
|
||||
}
|
||||
BX_BUSM_THIS command_val = value;
|
||||
} else {
|
||||
BX_ERROR(("Value 0x%02x written in supported mode 0x%02x", value, BX_BUSM_THIS control_val));
|
||||
}
|
||||
break;
|
||||
case 0x023E:
|
||||
BX_PANIC(("Write to port 0x023E"));
|
||||
break;
|
||||
case 0x023F:
|
||||
BX_PANIC(("Write to port 0x023F"));
|
||||
case PORT_SIGNATURE:
|
||||
case PORT_CONFIG:
|
||||
BX_ERROR(("Unsupported write to port 0x%04x (value = 0x%02x)", address, value));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bx_busm_c::mouse_enq_static(void *dev, int delta_x, int delta_y, int delta_z, unsigned button_state)
|
||||
void bx_busm_c::mouse_enq_static(void *dev, int delta_x, int delta_y, int delta_z, unsigned button_state, bx_bool absxy)
|
||||
{
|
||||
((bx_busm_c*)dev)->mouse_enq(delta_x, delta_y, delta_z, button_state);
|
||||
}
|
||||
@ -278,13 +244,21 @@ void bx_busm_c::mouse_enq(int delta_x, int delta_y, int delta_z, unsigned button
|
||||
if ((delta_y < -1) || (delta_y > 1))
|
||||
delta_y /= 2;
|
||||
|
||||
if(delta_x>127) delta_x=127;
|
||||
if(delta_y>127) delta_y=127;
|
||||
if(delta_x<-128) delta_x=-128;
|
||||
if(delta_y<-128) delta_y=-128;
|
||||
if (delta_x > 127) delta_x =127;
|
||||
if (delta_y > 127) delta_y =127;
|
||||
if (delta_x < -128) delta_x = -128;
|
||||
if (delta_y < -128) delta_y = -128;
|
||||
|
||||
BX_BUSM_THIS mouse_delayed_dx+=delta_x;
|
||||
BX_BUSM_THIS mouse_delayed_dy-=delta_y;
|
||||
BX_BUSM_THIS mouse_delayed_dx += delta_x;
|
||||
BX_BUSM_THIS mouse_delayed_dy -= delta_y;
|
||||
BX_BUSM_THIS mouse_buttons = (Bit8u)(0x40 | ((button_state & 1) << 2) |
|
||||
((button_state & 2) >> 1));
|
||||
BX_BUSM_THIS needs_update = 1;
|
||||
}
|
||||
|
||||
void bx_busm_c::update_mouse_data()
|
||||
{
|
||||
int delta_x, delta_y;
|
||||
|
||||
if (BX_BUSM_THIS mouse_delayed_dx > 127) {
|
||||
delta_x = 127;
|
||||
@ -306,12 +280,14 @@ void bx_busm_c::mouse_enq(int delta_x, int delta_y, int delta_z, unsigned button
|
||||
delta_y = BX_BUSM_THIS mouse_delayed_dy;
|
||||
BX_BUSM_THIS mouse_delayed_dy = 0;
|
||||
}
|
||||
|
||||
if ((BX_BUSM_THIS cur_command & 0x20) == 0x00) {
|
||||
BX_BUSM_THIS current_x = (Bit8u) delta_x;
|
||||
BX_BUSM_THIS current_y = (Bit8u) delta_y;
|
||||
BX_BUSM_THIS current_b = (Bit8u) ~(((button_state & 0x01)<<2) | ((button_state & 0x02) >> 1));
|
||||
if ((BX_BUSM_THIS mouse_delayed_dx == 0) &&
|
||||
(BX_BUSM_THIS mouse_delayed_dy == 0)) {
|
||||
BX_BUSM_THIS needs_update = 0;
|
||||
}
|
||||
|
||||
BX_BUSM_THIS current_x = (Bit8u) delta_x;
|
||||
BX_BUSM_THIS current_y = (Bit8u) delta_y;
|
||||
BX_BUSM_THIS current_b = mouse_buttons;
|
||||
}
|
||||
|
||||
void bx_busm_c::timer_handler(void *this_ptr)
|
||||
@ -324,7 +300,7 @@ void bx_busm_c::timer_handler(void *this_ptr)
|
||||
void bx_busm_c::busm_timer(void)
|
||||
{
|
||||
// if interrupts are on, fire the interrupt
|
||||
if (BX_BUSM_THIS interrupts) {
|
||||
if (BX_BUSM_THIS interrupts && BX_BUSM_THIS needs_update) {
|
||||
DEV_pic_raise_irq(BUS_MOUSE_IRQ);
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
// $Id$
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2004-2009 The Bochs Project
|
||||
// Copyright (C) 2004-2013 The Bochs Project
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@ -19,11 +19,11 @@
|
||||
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
|
||||
#if BX_SUPPORT_BUSMOUSE
|
||||
|
||||
#ifndef _PCBUSM_H
|
||||
#define _PCBUSM_H
|
||||
|
||||
#if BX_SUPPORT_BUSMOUSE
|
||||
|
||||
// these keywords should only be used in busmouse.cc
|
||||
#if BX_USE_BUSM_SMF
|
||||
# define BX_BUSM_SMF static
|
||||
@ -33,13 +33,6 @@
|
||||
# define BX_BUSM_THIS
|
||||
#endif
|
||||
|
||||
#define BUS_MOUSE_IRQ 5
|
||||
|
||||
#define PORT_CONTROL 0x023C
|
||||
#define PORT_DATA 0x023D
|
||||
#define PORT_SIGNATURE 0x023E
|
||||
#define PORT_CONFIG 0x023F
|
||||
|
||||
class bx_busm_c : public bx_devmodel_c {
|
||||
public:
|
||||
bx_busm_c();
|
||||
@ -52,8 +45,11 @@ public:
|
||||
private:
|
||||
static void timer_handler(void *);
|
||||
void busm_timer(void);
|
||||
static void mouse_enq_static(void *dev, int delta_x, int delta_y, int delta_z, unsigned button_state);
|
||||
|
||||
static void mouse_enq_static(void *dev, int delta_x, int delta_y, int delta_z, unsigned button_state, bx_bool absxy);
|
||||
void mouse_enq(int delta_x, int delta_y, int delta_z, unsigned button_state);
|
||||
void update_mouse_data(void);
|
||||
|
||||
static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len);
|
||||
static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len);
|
||||
#if !BX_USE_BUSM_SMF
|
||||
@ -65,44 +61,16 @@ private:
|
||||
|
||||
int mouse_delayed_dx;
|
||||
int mouse_delayed_dy;
|
||||
Bit8u mouse_buttons;
|
||||
Bit8u current_x, current_y, current_b;
|
||||
|
||||
// signature port
|
||||
Bit8u sig_port_sequ; // bit0: 0 or 1. A register read rotates between two values? 0xDE and Hardware ID?
|
||||
|
||||
// D7 = Mode set flag (1 = active)
|
||||
// D6,D5 = Mode selection (port A)
|
||||
// 00 = Mode 0 = Basic I/O
|
||||
// 01 = Mode 1 = Strobed I/O
|
||||
// 10 = Mode 2 = Bi-dir bus
|
||||
// D4 = Port A direction (1 = input)
|
||||
// D3 = Port C (upper 4 bits)
|
||||
// direction. (1 = input)
|
||||
// D2 = Mode selection (port B & C)
|
||||
// 0 = Mode 0 = Basic I/O
|
||||
// 1 = Mode 1 = Strobed I/O
|
||||
// D1 = Port B direction (1 = input)
|
||||
// D0 = Port C (lower 4 bits)
|
||||
// direction. (1 = input)
|
||||
Bit8u control_val;
|
||||
struct {
|
||||
bx_bool mode_set;
|
||||
Bit8u modeA_select;
|
||||
bx_bool portA_dir; // 1 = input
|
||||
bx_bool portC_upper_dir; // 1 = input
|
||||
bx_bool modeBC_select;
|
||||
bx_bool portB_dir; // 1 = input
|
||||
bx_bool portC_lower_dir; // 1 = input
|
||||
} control;
|
||||
|
||||
|
||||
Bit8u command_val; // current command val
|
||||
bx_bool interrupts; // 0 or 1. interrupts off or on.
|
||||
bx_bool packet_update; // 0 or 1. allow the mouse to update the packet?
|
||||
|
||||
Bit8u cur_command; // current command
|
||||
Bit8u command_val; // current command val
|
||||
bx_bool sig_port_sequ; // A register read rotates between two values? 0xDE and Hardware ID?
|
||||
bx_bool needs_update; // update of mouse data register required
|
||||
};
|
||||
|
||||
#endif // #ifndef _PCBUSM_H
|
||||
|
||||
#endif // BX_SUPPORT_BUSMOUSE
|
||||
|
||||
#endif // #ifndef _PCBUSM_H
|
||||
|
Loading…
x
Reference in New Issue
Block a user