1 /////////////////////////////////////////////////////////////////////////
2 // $Id: keyboard.cc,v 1.135 2008/09/18 17:18:36 sshwarts Exp $
3 /////////////////////////////////////////////////////////////////////////
5 // Copyright (C) 2002 MandrakeSoft S.A.
9 // 75002 Paris - France
10 // http://www.linux-mandrake.com/
11 // http://www.mandrakesoft.com/
13 // This library is free software; you can redistribute it and/or
14 // modify it under the terms of the GNU Lesser General Public
15 // License as published by the Free Software Foundation; either
16 // version 2 of the License, or (at your option) any later version.
18 // This library is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 // Lesser General Public License for more details.
23 // You should have received a copy of the GNU Lesser General Public
24 // License along with this library; if not, write to the Free Software
25 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 /////////////////////////////////////////////////////////////////////////
28 // Now features proper implementation of keyboard opcodes 0xF4 to 0xF6
29 // Silently ignores PS/2 keyboard extensions (0xF7 to 0xFD)
30 // Explicit panic on resend (0xFE)
32 // Emmanuel Marty <core@ggi-project.org>
34 // NB: now the PS/2 mouse support is in, outb changes meaning
35 // in conjunction with auxb
36 // auxb == 0 && outb == 0 => both buffers empty (nothing to read)
37 // auxb == 0 && outb == 1 => keyboard controller output buffer full
38 // auxb == 1 && outb == 0 => not used
39 // auxb == 1 && outb == 1 => mouse output buffer full.
42 // Notes from Christophe Bothamy <cbbochs@free.fr>
44 // This file includes code from Ludovic Lange (http://ludovic.lange.free.fr)
45 // Implementation of 3 scancodes sets mf1,mf2,mf3 with or without translation.
46 // Default is mf2 with translation
47 // Ability to switch between scancodes sets
48 // Ability to turn translation on or off
50 // Define BX_PLUGGABLE in files that can be compiled into plugins. For
51 // platforms that require a special tag on exported symbols, BX_PLUGGABLE
52 // is used to know when we are exporting symbols and when we are importing.
57 #include "scancodes.h"
59 #define LOG_THIS theKeyboard->
60 #define VERBOSE_KBD_DEBUG 0
63 bx_keyb_c
*theKeyboard
= NULL
;
65 int libkeyboard_LTX_plugin_init(plugin_t
*plugin
, plugintype_t type
, int argc
, char *argv
[])
67 // Create one instance of the keyboard device object.
68 theKeyboard
= new bx_keyb_c();
69 // Before this plugin was loaded, pluginKeyboard pointed to a stub.
70 // Now make it point to the real thing.
71 bx_devices
.pluginKeyboard
= theKeyboard
;
72 // Register this device.
73 BX_REGISTER_DEVICE_DEVMODEL(plugin
, type
, theKeyboard
, BX_PLUGIN_KEYBOARD
);
77 void libkeyboard_LTX_plugin_fini(void)
82 bx_keyb_c::bx_keyb_c()
89 bx_keyb_c::~bx_keyb_c()
91 // remove runtime parameter handler
92 SIM
->get_param_bool(BXPN_MOUSE_ENABLED
)->set_handler(NULL
);
93 SIM
->get_param_num(BXPN_KBD_PASTE_DELAY
)->set_handler(NULL
);
94 if (pastebuf
!= NULL
) {
98 bx_list_c
*list
= (bx_list_c
*)SIM
->get_param(BXPN_WX_KBD_STATE
);
106 // flush internal buffer and reset keyboard settings to power-up condition
107 void bx_keyb_c::resetinternals(bx_bool powerup
)
109 BX_KEY_THIS s
.kbd_internal_buffer
.num_elements
= 0;
110 for (int i
=0; i
<BX_KBD_ELEMENTS
; i
++)
111 BX_KEY_THIS s
.kbd_internal_buffer
.buffer
[i
] = 0;
112 BX_KEY_THIS s
.kbd_internal_buffer
.head
= 0;
114 BX_KEY_THIS s
.kbd_internal_buffer
.expecting_typematic
= 0;
116 // Default scancode set is mf2 (translation is controlled by the 8042)
117 BX_KEY_THIS s
.kbd_controller
.expecting_scancodes_set
= 0;
118 BX_KEY_THIS s
.kbd_controller
.current_scancodes_set
= 1;
121 BX_KEY_THIS s
.kbd_internal_buffer
.expecting_led_write
= 0;
122 BX_KEY_THIS s
.kbd_internal_buffer
.delay
= 1; // 500 mS
123 BX_KEY_THIS s
.kbd_internal_buffer
.repeat_rate
= 0x0b; // 10.9 chars/sec
127 void bx_keyb_c::init(void)
129 BX_DEBUG(("Init $Id: keyboard.cc,v 1.135 2008/09/18 17:18:36 sshwarts Exp $"));
132 DEV_register_irq(1, "8042 Keyboard controller");
133 DEV_register_irq(12, "8042 Keyboard controller (PS/2 mouse)");
135 DEV_register_ioread_handler(this, read_handler
,
136 0x0060, "8042 Keyboard controller", 1);
137 DEV_register_ioread_handler(this, read_handler
,
138 0x0064, "8042 Keyboard controller", 1);
139 DEV_register_iowrite_handler(this, write_handler
,
140 0x0060, "8042 Keyboard controller", 1);
141 DEV_register_iowrite_handler(this, write_handler
,
142 0x0064, "8042 Keyboard controller", 1);
143 BX_KEY_THIS timer_handle
= bx_pc_system
.register_timer(this, timer_handler
,
144 SIM
->get_param_num(BXPN_KBD_SERIAL_DELAY
)->get(), 1, 1,
145 "8042 Keyboard controller");
149 BX_KEY_THIS s
.kbd_internal_buffer
.led_status
= 0;
150 BX_KEY_THIS s
.kbd_internal_buffer
.scanning_enabled
= 1;
152 BX_KEY_THIS s
.mouse_internal_buffer
.num_elements
= 0;
153 for (i
=0; i
<BX_MOUSE_BUFF_SIZE
; i
++)
154 BX_KEY_THIS s
.mouse_internal_buffer
.buffer
[i
] = 0;
155 BX_KEY_THIS s
.mouse_internal_buffer
.head
= 0;
157 BX_KEY_THIS s
.kbd_controller
.pare
= 0;
158 BX_KEY_THIS s
.kbd_controller
.tim
= 0;
159 BX_KEY_THIS s
.kbd_controller
.auxb
= 0;
160 BX_KEY_THIS s
.kbd_controller
.keyl
= 1;
161 BX_KEY_THIS s
.kbd_controller
.c_d
= 1;
162 BX_KEY_THIS s
.kbd_controller
.sysf
= 0;
163 BX_KEY_THIS s
.kbd_controller
.inpb
= 0;
164 BX_KEY_THIS s
.kbd_controller
.outb
= 0;
166 BX_KEY_THIS s
.kbd_controller
.kbd_clock_enabled
= 1;
167 BX_KEY_THIS s
.kbd_controller
.aux_clock_enabled
= 0;
168 BX_KEY_THIS s
.kbd_controller
.allow_irq1
= 1;
169 BX_KEY_THIS s
.kbd_controller
.allow_irq12
= 1;
170 BX_KEY_THIS s
.kbd_controller
.kbd_output_buffer
= 0;
171 BX_KEY_THIS s
.kbd_controller
.aux_output_buffer
= 0;
172 BX_KEY_THIS s
.kbd_controller
.last_comm
= 0;
173 BX_KEY_THIS s
.kbd_controller
.expecting_port60h
= 0;
174 BX_KEY_THIS s
.kbd_controller
.irq1_requested
= 0;
175 BX_KEY_THIS s
.kbd_controller
.irq12_requested
= 0;
176 BX_KEY_THIS s
.kbd_controller
.expecting_mouse_parameter
= 0;
177 BX_KEY_THIS s
.kbd_controller
.bat_in_progress
= 0;
178 BX_KEY_THIS s
.kbd_controller
.scancodes_translate
= 1;
180 BX_KEY_THIS s
.kbd_controller
.timer_pending
= 0;
182 // Mouse initialization stuff
183 BX_KEY_THIS s
.mouse
.captured
= SIM
->get_param_bool(BXPN_MOUSE_ENABLED
)->get();
184 BX_KEY_THIS s
.mouse
.type
= SIM
->get_param_enum(BXPN_MOUSE_TYPE
)->get();
185 BX_KEY_THIS s
.mouse
.sample_rate
= 100; // reports per second
186 BX_KEY_THIS s
.mouse
.resolution_cpmm
= 4; // 4 counts per millimeter
187 BX_KEY_THIS s
.mouse
.scaling
= 1; /* 1:1 (default) */
188 BX_KEY_THIS s
.mouse
.mode
= MOUSE_MODE_RESET
;
189 BX_KEY_THIS s
.mouse
.enable
= 0;
190 BX_KEY_THIS s
.mouse
.delayed_dx
= 0;
191 BX_KEY_THIS s
.mouse
.delayed_dy
= 0;
192 BX_KEY_THIS s
.mouse
.delayed_dz
= 0;
193 BX_KEY_THIS s
.mouse
.im_request
= 0; // wheel mouse mode request
194 BX_KEY_THIS s
.mouse
.im_mode
= 0; // wheel mouse mode
196 for (i
=0; i
<BX_KBD_CONTROLLER_QSIZE
; i
++)
197 BX_KEY_THIS s
.controller_Q
[i
] = 0;
198 BX_KEY_THIS s
.controller_Qsize
= 0;
199 BX_KEY_THIS s
.controller_Qsource
= 0;
201 // clear paste buffer
202 BX_KEY_THIS pastebuf
= NULL
;
203 BX_KEY_THIS pastebuf_len
= 0;
204 BX_KEY_THIS pastebuf_ptr
= 0;
205 BX_KEY_THIS
paste_delay_changed(SIM
->get_param_num(BXPN_KBD_PASTE_DELAY
)->get());
206 BX_KEY_THIS paste_service
= 0;
207 BX_KEY_THIS stop_paste
= 0;
209 // mouse port installed on system board
210 DEV_cmos_set_reg(0x14, DEV_cmos_get_reg(0x14) | 0x04);
212 // add keyboard LEDs to the statusbar
213 BX_KEY_THIS statusbar_id
[0] = bx_gui
->register_statusitem("NUM");
214 BX_KEY_THIS statusbar_id
[1] = bx_gui
->register_statusitem("CAPS");
215 BX_KEY_THIS statusbar_id
[2] = bx_gui
->register_statusitem("SCRL");
218 bx_param_num_c
*param
;
220 if (SIM
->get_param("wxdebug") != NULL
) {
221 // register shadow params (Experimental, not a complete list by far)
222 list
= (bx_list_c
*)SIM
->get_param(BXPN_WX_KBD_STATE
);
224 list
= new bx_list_c(SIM
->get_param("wxdebug"), "keyboard",
225 "Keyboard State", 20);
227 new bx_shadow_bool_c(list
, "irq1_req",
228 "Keyboard IRQ1 requested",
229 &BX_KEY_THIS s
.kbd_controller
.irq1_requested
);
230 new bx_shadow_bool_c(list
, "irq12_req",
231 "Keyboard IRQ12 requested",
232 &BX_KEY_THIS s
.kbd_controller
.irq12_requested
);
233 param
= new bx_shadow_num_c(list
, "timer_pending",
234 &BX_KEY_THIS s
.kbd_controller
.timer_pending
);
235 param
->set_label("Keyboard timer pending");
236 new bx_shadow_bool_c(list
, "pare",
238 &BX_KEY_THIS s
.kbd_controller
.pare
);
239 new bx_shadow_bool_c(list
, "tim",
241 &BX_KEY_THIS s
.kbd_controller
.tim
);
242 new bx_shadow_bool_c(list
, "auxb",
244 &BX_KEY_THIS s
.kbd_controller
.auxb
);
245 new bx_shadow_bool_c(list
, "keyl",
247 &BX_KEY_THIS s
.kbd_controller
.keyl
);
248 new bx_shadow_bool_c(list
, "c_d",
250 &BX_KEY_THIS s
.kbd_controller
.c_d
);
251 new bx_shadow_bool_c(list
, "sysf",
253 &BX_KEY_THIS s
.kbd_controller
.sysf
);
254 new bx_shadow_bool_c(list
, "inpb",
256 &BX_KEY_THIS s
.kbd_controller
.inpb
);
257 new bx_shadow_bool_c(list
, "outb",
259 &BX_KEY_THIS s
.kbd_controller
.outb
);
263 // init runtime parameters
264 SIM
->get_param_bool(BXPN_MOUSE_ENABLED
)->set_handler(kbd_param_handler
);
265 SIM
->get_param_bool(BXPN_MOUSE_ENABLED
)->set_runtime_param(1);
266 SIM
->get_param_num(BXPN_KBD_PASTE_DELAY
)->set_handler(kbd_param_handler
);
267 SIM
->get_param_num(BXPN_KBD_PASTE_DELAY
)->set_runtime_param(1);
270 void bx_keyb_c::reset(unsigned type
)
272 if (BX_KEY_THIS pastebuf
!= NULL
) {
273 BX_KEY_THIS stop_paste
= 1;
277 void bx_keyb_c::register_state(void)
283 bx_list_c
*list
= new bx_list_c(SIM
->get_bochs_root(), "keyboard", "Keyboard State", 7);
284 bx_list_c
*ctrl
= new bx_list_c(list
, "controller", 23);
285 BXRS_PARAM_BOOL(ctrl
, tim
, BX_KEY_THIS s
.kbd_controller
.tim
);
286 BXRS_PARAM_BOOL(ctrl
, auxb
, BX_KEY_THIS s
.kbd_controller
.auxb
);
287 BXRS_PARAM_BOOL(ctrl
, c_d
, BX_KEY_THIS s
.kbd_controller
.c_d
);
288 BXRS_PARAM_BOOL(ctrl
, sysf
, BX_KEY_THIS s
.kbd_controller
.sysf
);
289 BXRS_PARAM_BOOL(ctrl
, inpb
, BX_KEY_THIS s
.kbd_controller
.inpb
);
290 BXRS_PARAM_BOOL(ctrl
, outb
, BX_KEY_THIS s
.kbd_controller
.outb
);
291 BXRS_PARAM_BOOL(ctrl
, kbd_clock_enabled
, BX_KEY_THIS s
.kbd_controller
.kbd_clock_enabled
);
292 BXRS_PARAM_BOOL(ctrl
, aux_clock_enabled
, BX_KEY_THIS s
.kbd_controller
.aux_clock_enabled
);
293 BXRS_PARAM_BOOL(ctrl
, allow_irq1
, BX_KEY_THIS s
.kbd_controller
.allow_irq1
);
294 BXRS_PARAM_BOOL(ctrl
, allow_irq12
, BX_KEY_THIS s
.kbd_controller
.allow_irq12
);
295 BXRS_HEX_PARAM_FIELD(ctrl
, kbd_output_buffer
, BX_KEY_THIS s
.kbd_controller
.kbd_output_buffer
);
296 BXRS_HEX_PARAM_FIELD(ctrl
, aux_output_buffer
, BX_KEY_THIS s
.kbd_controller
.aux_output_buffer
);
297 BXRS_HEX_PARAM_FIELD(ctrl
, last_comm
, BX_KEY_THIS s
.kbd_controller
.last_comm
);
298 BXRS_DEC_PARAM_FIELD(ctrl
, expecting_port60h
, BX_KEY_THIS s
.kbd_controller
.expecting_port60h
);
299 BXRS_DEC_PARAM_FIELD(ctrl
, expecting_mouse_parameter
, BX_KEY_THIS s
.kbd_controller
.expecting_mouse_parameter
);
300 BXRS_HEX_PARAM_FIELD(ctrl
, last_mouse_command
, BX_KEY_THIS s
.kbd_controller
.last_mouse_command
);
301 BXRS_DEC_PARAM_FIELD(ctrl
, timer_pending
, BX_KEY_THIS s
.kbd_controller
.timer_pending
);
302 BXRS_PARAM_BOOL(ctrl
, irq1_requested
, BX_KEY_THIS s
.kbd_controller
.irq1_requested
);
303 BXRS_PARAM_BOOL(ctrl
, irq12_requested
, BX_KEY_THIS s
.kbd_controller
.irq12_requested
);
304 BXRS_PARAM_BOOL(ctrl
, scancodes_translate
, BX_KEY_THIS s
.kbd_controller
.scancodes_translate
);
305 BXRS_PARAM_BOOL(ctrl
, expecting_scancodes_set
, BX_KEY_THIS s
.kbd_controller
.expecting_scancodes_set
);
306 BXRS_DEC_PARAM_FIELD(ctrl
, current_scancodes_set
, BX_KEY_THIS s
.kbd_controller
.current_scancodes_set
);
307 BXRS_PARAM_BOOL(ctrl
, bat_in_progress
, BX_KEY_THIS s
.kbd_controller
.bat_in_progress
);
308 bx_list_c
*mouse
= new bx_list_c(list
, "mouse", 12);
309 BXRS_DEC_PARAM_FIELD(mouse
, sample_rate
, BX_KEY_THIS s
.mouse
.sample_rate
);
310 BXRS_DEC_PARAM_FIELD(mouse
, resolution_cpmm
, BX_KEY_THIS s
.mouse
.resolution_cpmm
);
311 BXRS_DEC_PARAM_FIELD(mouse
, scaling
, BX_KEY_THIS s
.mouse
.scaling
);
312 BXRS_DEC_PARAM_FIELD(mouse
, mode
, BX_KEY_THIS s
.mouse
.mode
);
313 BXRS_DEC_PARAM_FIELD(mouse
, saved_mode
, BX_KEY_THIS s
.mouse
.saved_mode
);
314 BXRS_PARAM_BOOL(mouse
, enable
, BX_KEY_THIS s
.mouse
.enable
);
315 BXRS_DEC_PARAM_FIELD(mouse
, button_status
, BX_KEY_THIS s
.mouse
.button_status
);
316 BXRS_DEC_PARAM_FIELD(mouse
, delayed_dx
, BX_KEY_THIS s
.mouse
.delayed_dx
);
317 BXRS_DEC_PARAM_FIELD(mouse
, delayed_dy
, BX_KEY_THIS s
.mouse
.delayed_dy
);
318 BXRS_DEC_PARAM_FIELD(mouse
, delayed_dz
, BX_KEY_THIS s
.mouse
.delayed_dz
);
319 BXRS_DEC_PARAM_FIELD(mouse
, im_request
, BX_KEY_THIS s
.mouse
.im_request
);
320 BXRS_PARAM_BOOL(mouse
, im_mode
, BX_KEY_THIS s
.mouse
.im_mode
);
321 bx_list_c
*kbdbuf
= new bx_list_c(list
, "kbd_internal_buffer", 9);
322 BXRS_DEC_PARAM_FIELD(kbdbuf
, num_elements
, BX_KEY_THIS s
.kbd_internal_buffer
.num_elements
);
323 buffer
= new bx_list_c(kbdbuf
, "buffer", BX_KBD_ELEMENTS
);
324 for (i
=0; i
<BX_KBD_ELEMENTS
; i
++) {
325 sprintf(name
, "%d", i
);
326 new bx_shadow_num_c(buffer
, name
, &BX_KEY_THIS s
.kbd_internal_buffer
.buffer
[i
], BASE_HEX
);
328 BXRS_DEC_PARAM_FIELD(kbdbuf
, head
, BX_KEY_THIS s
.kbd_internal_buffer
.head
);
329 BXRS_PARAM_BOOL(kbdbuf
, expecting_typematic
, BX_KEY_THIS s
.kbd_internal_buffer
.expecting_typematic
);
330 BXRS_PARAM_BOOL(kbdbuf
, expecting_led_write
, BX_KEY_THIS s
.kbd_internal_buffer
.expecting_led_write
);
331 BXRS_DEC_PARAM_FIELD(kbdbuf
, delay
, BX_KEY_THIS s
.kbd_internal_buffer
.delay
);
332 BXRS_DEC_PARAM_FIELD(kbdbuf
, repeat_rate
, BX_KEY_THIS s
.kbd_internal_buffer
.repeat_rate
);
333 BXRS_DEC_PARAM_FIELD(kbdbuf
, led_status
, BX_KEY_THIS s
.kbd_internal_buffer
.led_status
);
334 BXRS_PARAM_BOOL(kbdbuf
, scanning_enabled
, BX_KEY_THIS s
.kbd_internal_buffer
.scanning_enabled
);
335 bx_list_c
*mousebuf
= new bx_list_c(list
, "mouse_internal_buffer", 3);
336 BXRS_DEC_PARAM_FIELD(mousebuf
, num_elements
, BX_KEY_THIS s
.mouse_internal_buffer
.num_elements
);
337 buffer
= new bx_list_c(mousebuf
, "buffer", BX_MOUSE_BUFF_SIZE
);
338 for (i
=0; i
<BX_MOUSE_BUFF_SIZE
; i
++) {
339 sprintf(name
, "%d", i
);
340 new bx_shadow_num_c(buffer
, name
, &BX_KEY_THIS s
.mouse_internal_buffer
.buffer
[i
], BASE_HEX
);
342 BXRS_DEC_PARAM_FIELD(mousebuf
, head
, BX_KEY_THIS s
.mouse_internal_buffer
.head
);
343 buffer
= new bx_list_c(list
, "controller_Q", BX_KBD_CONTROLLER_QSIZE
);
344 for (i
=0; i
<BX_KBD_CONTROLLER_QSIZE
; i
++) {
345 sprintf(name
, "%d", i
);
346 new bx_shadow_num_c(buffer
, name
, &BX_KEY_THIS s
.controller_Q
[i
], BASE_HEX
);
348 BXRS_DEC_PARAM_FIELD(list
, controller_Qsize
, BX_KEY_THIS s
.controller_Qsize
);
349 BXRS_DEC_PARAM_FIELD(list
, controller_Qsource
, BX_KEY_THIS s
.controller_Qsource
);
352 void bx_keyb_c::after_restore_state(void)
354 Bit8u value
= BX_KEY_THIS s
.kbd_internal_buffer
.led_status
;
356 bx_gui
->statusbar_setitem(BX_KEY_THIS statusbar_id
[0], value
& 0x02);
357 bx_gui
->statusbar_setitem(BX_KEY_THIS statusbar_id
[1], value
& 0x04);
358 bx_gui
->statusbar_setitem(BX_KEY_THIS statusbar_id
[2], value
& 0x01);
362 Bit64s
bx_keyb_c::kbd_param_handler(bx_param_c
*param
, int set
, Bit64s val
)
365 char pname
[BX_PATHNAME_LEN
];
366 param
->get_param_path(pname
, BX_PATHNAME_LEN
);
367 if (!strcmp(pname
, BXPN_MOUSE_ENABLED
)) {
368 bx_gui
->mouse_enabled_changed(val
!=0);
369 BX_KEY_THIS
mouse_enabled_changed(val
!=0);
370 } else if (!strcmp(pname
, BXPN_KBD_PASTE_DELAY
)) {
371 BX_KEY_THIS
paste_delay_changed((Bit32u
)val
);
373 BX_PANIC(("kbd_param_handler called with unexpected parameter '%s'", pname
));
379 void bx_keyb_c::paste_delay_changed(Bit32u value
)
381 BX_KEY_THIS pastedelay
= value
/ BX_IODEV_HANDLER_PERIOD
;
382 BX_INFO(("will paste characters every %d keyboard ticks",BX_KEY_THIS pastedelay
));
385 // static IO port read callback handler
386 // redirects to non-static class handler to avoid virtual functions
388 // read function - the big picture:
389 // if address == data port then
390 // if byte for mouse then return it
391 // else if byte for keyboard then return it
392 // else address== status port
393 // assemble the status bits and return them.
395 Bit32u
bx_keyb_c::read_handler(void *this_ptr
, Bit32u address
, unsigned io_len
)
398 bx_keyb_c
*class_ptr
= (bx_keyb_c
*)this_ptr
;
400 return (class_ptr
->read(address
, io_len
));
403 Bit32u
bx_keyb_c::read(Bit32u address
, unsigned io_len
)
407 #endif // !BX_USE_KEY_SMF
410 if (address
== 0x60) { /* output buffer */
411 if (BX_KEY_THIS s
.kbd_controller
.auxb
) { /* mouse byte available */
412 val
= BX_KEY_THIS s
.kbd_controller
.aux_output_buffer
;
413 BX_KEY_THIS s
.kbd_controller
.aux_output_buffer
= 0;
414 BX_KEY_THIS s
.kbd_controller
.outb
= 0;
415 BX_KEY_THIS s
.kbd_controller
.auxb
= 0;
416 BX_KEY_THIS s
.kbd_controller
.irq12_requested
= 0;
418 if (BX_KEY_THIS s
.controller_Qsize
) {
420 BX_KEY_THIS s
.kbd_controller
.aux_output_buffer
= BX_KEY_THIS s
.controller_Q
[0];
421 BX_KEY_THIS s
.kbd_controller
.outb
= 1;
422 BX_KEY_THIS s
.kbd_controller
.auxb
= 1;
423 if (BX_KEY_THIS s
.kbd_controller
.allow_irq12
)
424 BX_KEY_THIS s
.kbd_controller
.irq12_requested
= 1;
425 for (i
=0; i
<BX_KEY_THIS s
.controller_Qsize
-1; i
++) {
426 // move Q elements towards head of queue by one
427 BX_KEY_THIS s
.controller_Q
[i
] = BX_KEY_THIS s
.controller_Q
[i
+1];
429 BX_KEY_THIS s
.controller_Qsize
--;
432 DEV_pic_lower_irq(12);
434 BX_DEBUG(("[mouse] read from 0x%02x returns 0x%02x", address
, val
));
437 else if (BX_KEY_THIS s
.kbd_controller
.outb
) { /* kbd byte available */
438 val
= BX_KEY_THIS s
.kbd_controller
.kbd_output_buffer
;
439 BX_KEY_THIS s
.kbd_controller
.outb
= 0;
440 BX_KEY_THIS s
.kbd_controller
.auxb
= 0;
441 BX_KEY_THIS s
.kbd_controller
.irq1_requested
= 0;
442 BX_KEY_THIS s
.kbd_controller
.bat_in_progress
= 0;
444 if (BX_KEY_THIS s
.controller_Qsize
) {
446 BX_KEY_THIS s
.kbd_controller
.aux_output_buffer
= BX_KEY_THIS s
.controller_Q
[0];
447 BX_KEY_THIS s
.kbd_controller
.outb
= 1;
448 BX_KEY_THIS s
.kbd_controller
.auxb
= 1;
449 if (BX_KEY_THIS s
.kbd_controller
.allow_irq1
)
450 BX_KEY_THIS s
.kbd_controller
.irq1_requested
= 1;
451 for (i
=0; i
<BX_KEY_THIS s
.controller_Qsize
-1; i
++) {
452 // move Q elements towards head of queue by one
453 BX_KEY_THIS s
.controller_Q
[i
] = BX_KEY_THIS s
.controller_Q
[i
+1];
455 BX_DEBUG(("s.controller_Qsize: %02X",BX_KEY_THIS s
.controller_Qsize
));
456 BX_KEY_THIS s
.controller_Qsize
--;
459 DEV_pic_lower_irq(1);
461 BX_DEBUG(("READ(%02x) = %02x", (unsigned) address
, (unsigned) val
));
465 BX_DEBUG(("num_elements = %d", BX_KEY_THIS s
.kbd_internal_buffer
.num_elements
));
466 BX_DEBUG(("read from port 60h with outb empty"));
467 return BX_KEY_THIS s
.kbd_controller
.kbd_output_buffer
;
471 #if BX_CPU_LEVEL >= 2
472 else if (address
== 0x64) { /* status register */
473 val
= (BX_KEY_THIS s
.kbd_controller
.pare
<< 7) |
474 (BX_KEY_THIS s
.kbd_controller
.tim
<< 6) |
475 (BX_KEY_THIS s
.kbd_controller
.auxb
<< 5) |
476 (BX_KEY_THIS s
.kbd_controller
.keyl
<< 4) |
477 (BX_KEY_THIS s
.kbd_controller
.c_d
<< 3) |
478 (BX_KEY_THIS s
.kbd_controller
.sysf
<< 2) |
479 (BX_KEY_THIS s
.kbd_controller
.inpb
<< 1) |
480 BX_KEY_THIS s
.kbd_controller
.outb
;
481 BX_KEY_THIS s
.kbd_controller
.tim
= 0;
485 #else /* BX_CPU_LEVEL > 0 */
486 /* XT MODE, System 8255 Mode Register */
487 else if (address
== 0x64) { /* status register */
488 BX_DEBUG(("IO read from port 64h, system 8255 mode register"));
489 return BX_KEY_THIS s
.kbd_controller
.outb
;
491 #endif /* BX_CPU_LEVEL > 0 */
493 BX_PANIC(("unknown address in io read to keyboard port %x",
494 (unsigned) address
));
495 return 0; /* keep compiler happy */
498 // static IO port write callback handler
499 // redirects to non-static class handler to avoid virtual functions
501 void bx_keyb_c::write_handler(void *this_ptr
, Bit32u address
, Bit32u value
, unsigned io_len
)
504 bx_keyb_c
*class_ptr
= (bx_keyb_c
*)this_ptr
;
505 class_ptr
->write(address
, value
, io_len
);
508 void bx_keyb_c::write(Bit32u address
, Bit32u value
, unsigned io_len
)
512 #endif // !BX_USE_KEY_SMF
514 static int kbd_initialized
=0;
516 BX_DEBUG(("keyboard: 8-bit write to %04x = %02x", (unsigned)address
, (unsigned)value
));
519 case 0x60: // input buffer
520 // if expecting data byte from command last sent to port 64h
521 if (BX_KEY_THIS s
.kbd_controller
.expecting_port60h
) {
522 BX_KEY_THIS s
.kbd_controller
.expecting_port60h
= 0;
523 // data byte written last to 0x60
524 BX_KEY_THIS s
.kbd_controller
.c_d
= 0;
525 if (BX_KEY_THIS s
.kbd_controller
.inpb
) {
526 BX_PANIC(("write to port 60h, not ready for write"));
528 switch (BX_KEY_THIS s
.kbd_controller
.last_comm
) {
529 case 0x60: // write command byte
531 bx_bool scan_convert
, disable_keyboard
,
534 scan_convert
= (value
>> 6) & 0x01;
535 disable_aux
= (value
>> 5) & 0x01;
536 disable_keyboard
= (value
>> 4) & 0x01;
537 BX_KEY_THIS s
.kbd_controller
.sysf
= (value
>> 2) & 0x01;
538 BX_KEY_THIS s
.kbd_controller
.allow_irq1
= (value
>> 0) & 0x01;
539 BX_KEY_THIS s
.kbd_controller
.allow_irq12
= (value
>> 1) & 0x01;
540 set_kbd_clock_enable(!disable_keyboard
);
541 set_aux_clock_enable(!disable_aux
);
542 if (BX_KEY_THIS s
.kbd_controller
.allow_irq12
&& BX_KEY_THIS s
.kbd_controller
.auxb
)
543 BX_KEY_THIS s
.kbd_controller
.irq12_requested
= 1;
544 else if (BX_KEY_THIS s
.kbd_controller
.allow_irq1
&& BX_KEY_THIS s
.kbd_controller
.outb
)
545 BX_KEY_THIS s
.kbd_controller
.irq1_requested
= 1;
547 BX_DEBUG((" allow_irq12 set to %u",
548 (unsigned) BX_KEY_THIS s
.kbd_controller
.allow_irq12
));
550 BX_INFO(("keyboard: scan convert turned off"));
552 // (mch) NT needs this
553 BX_KEY_THIS s
.kbd_controller
.scancodes_translate
= scan_convert
;
556 case 0xcb: // write keyboard controller mode
557 BX_DEBUG(("write keyboard controller mode with value %02xh", (unsigned) value
));
559 case 0xd1: // write output port
560 BX_DEBUG(("write output port with value %02xh", (unsigned) value
));
561 BX_DEBUG(("write output port : %sable A20",(value
& 0x02)?"en":"dis"));
562 BX_SET_ENABLE_A20((value
& 0x02) != 0);
563 if (!(value
& 0x01)) {
564 BX_INFO(("write output port : processor reset requested!"));
565 bx_pc_system
.Reset(BX_RESET_SOFTWARE
);
568 case 0xd4: // Write to mouse
569 // I don't think this enables the AUX clock
570 //set_aux_clock_enable(1); // enable aux clock line
571 kbd_ctrl_to_mouse(value
);
572 // ??? should I reset to previous value of aux enable?
575 case 0xd3: // write mouse output buffer
576 // Queue in mouse output buffer
577 controller_enQ(value
, 1);
581 // Queue in keyboard output buffer
582 controller_enQ(value
, 0);
586 BX_PANIC(("=== unsupported write to port 60h(lastcomm=%02x): %02x",
587 (unsigned) BX_KEY_THIS s
.kbd_controller
.last_comm
, (unsigned) value
));
590 // data byte written last to 0x60
591 BX_KEY_THIS s
.kbd_controller
.c_d
= 0;
592 BX_KEY_THIS s
.kbd_controller
.expecting_port60h
= 0;
593 /* pass byte to keyboard */
594 /* ??? should conditionally pass to mouse device here ??? */
595 if (BX_KEY_THIS s
.kbd_controller
.kbd_clock_enabled
==0) {
596 set_kbd_clock_enable(1);
598 kbd_ctrl_to_kbd(value
);
602 case 0x64: // control register
603 // command byte written last to 0x64
604 BX_KEY_THIS s
.kbd_controller
.c_d
= 1;
605 BX_KEY_THIS s
.kbd_controller
.last_comm
= value
;
606 // most commands NOT expecting port60 write next
607 BX_KEY_THIS s
.kbd_controller
.expecting_port60h
= 0;
610 case 0x20: // get keyboard command byte
611 BX_DEBUG(("get keyboard command byte"));
612 // controller output buffer must be empty
613 if (BX_KEY_THIS s
.kbd_controller
.outb
) {
614 BX_ERROR(("kbd: OUTB set and command 0x%02x encountered", value
));
618 (BX_KEY_THIS s
.kbd_controller
.scancodes_translate
<< 6) |
619 ((!BX_KEY_THIS s
.kbd_controller
.aux_clock_enabled
) << 5) |
620 ((!BX_KEY_THIS s
.kbd_controller
.kbd_clock_enabled
) << 4) |
622 (BX_KEY_THIS s
.kbd_controller
.sysf
<< 2) |
623 (BX_KEY_THIS s
.kbd_controller
.allow_irq12
<< 1) |
624 (BX_KEY_THIS s
.kbd_controller
.allow_irq1
<< 0);
625 controller_enQ(command_byte
, 0);
627 case 0x60: // write command byte
628 BX_DEBUG(("write command byte"));
629 // following byte written to port 60h is command byte
630 BX_KEY_THIS s
.kbd_controller
.expecting_port60h
= 1;
634 BX_DEBUG(("keyboard BIOS name not supported"));
638 BX_DEBUG(("keyboard BIOS version not supported"));
641 case 0xa7: // disable the aux device
642 set_aux_clock_enable(0);
643 BX_DEBUG(("aux device disabled"));
645 case 0xa8: // enable the aux device
646 set_aux_clock_enable(1);
647 BX_DEBUG(("aux device enabled"));
649 case 0xa9: // Test Mouse Port
650 // controller output buffer must be empty
651 if (BX_KEY_THIS s
.kbd_controller
.outb
) {
652 BX_PANIC(("kbd: OUTB set and command 0x%02x encountered", value
));
655 controller_enQ(0x00, 0); // no errors detected
657 case 0xaa: // motherboard controller self test
658 BX_DEBUG(("Self Test"));
659 if (kbd_initialized
== 0) {
660 BX_KEY_THIS s
.controller_Qsize
= 0;
661 BX_KEY_THIS s
.kbd_controller
.outb
= 0;
664 // controller output buffer must be empty
665 if (BX_KEY_THIS s
.kbd_controller
.outb
) {
666 BX_ERROR(("kbd: OUTB set and command 0x%02x encountered", value
));
669 // (mch) Why is this commented out??? Enabling
670 BX_KEY_THIS s
.kbd_controller
.sysf
= 1; // self test complete
671 controller_enQ(0x55, 0); // controller OK
673 case 0xab: // Interface Test
674 // controller output buffer must be empty
675 if (BX_KEY_THIS s
.kbd_controller
.outb
) {
676 BX_PANIC(("kbd: OUTB set and command 0x%02x encountered", value
));
679 controller_enQ(0x00, 0);
681 case 0xad: // disable keyboard
682 set_kbd_clock_enable(0);
683 BX_DEBUG(("keyboard disabled"));
685 case 0xae: // enable keyboard
686 set_kbd_clock_enable(1);
687 BX_DEBUG(("keyboard enabled"));
689 case 0xaf: // get controller version
690 BX_INFO(("'get controller version' not supported yet"));
692 case 0xc0: // read input port
693 // controller output buffer must be empty
694 if (BX_KEY_THIS s
.kbd_controller
.outb
) {
695 BX_PANIC(("kbd: OUTB set and command 0x%02x encountered", value
));
698 // keyboard not inhibited
699 controller_enQ(0x80, 0);
701 case 0xca: // read keyboard controller mode
702 controller_enQ(0x01, 0); // PS/2 (MCA)interface
704 case 0xcb: // write keyboard controller mode
705 BX_DEBUG(("write keyboard controller mode"));
706 // write keyboard controller mode to bit 0 of port 0x60
707 BX_KEY_THIS s
.kbd_controller
.expecting_port60h
= 1;
709 case 0xd0: // read output port: next byte read from port 60h
710 BX_DEBUG(("io write to port 64h, command d0h (partial)"));
711 // controller output buffer must be empty
712 if (BX_KEY_THIS s
.kbd_controller
.outb
) {
713 BX_PANIC(("kbd: OUTB set and command 0x%02x encountered", value
));
717 (BX_KEY_THIS s
.kbd_controller
.irq12_requested
<< 5) |
718 (BX_KEY_THIS s
.kbd_controller
.irq1_requested
<< 4) |
719 (BX_GET_ENABLE_A20() << 1) |
723 case 0xd1: // write output port: next byte written to port 60h
724 BX_DEBUG(("write output port"));
725 // following byte to port 60h written to output port
726 BX_KEY_THIS s
.kbd_controller
.expecting_port60h
= 1;
729 case 0xd3: // write mouse output buffer
730 //FIXME: Why was this a panic?
731 BX_DEBUG(("io write 0x64: command = 0xD3(write mouse outb)"));
732 // following byte to port 60h written to output port as mouse write.
733 BX_KEY_THIS s
.kbd_controller
.expecting_port60h
= 1;
736 case 0xd4: // write to mouse
737 BX_DEBUG(("io write 0x64: command = 0xD4 (write to mouse)"));
738 // following byte written to port 60h
739 BX_KEY_THIS s
.kbd_controller
.expecting_port60h
= 1;
742 case 0xd2: // write keyboard output buffer
743 BX_DEBUG(("io write 0x64: write keyboard output buffer"));
744 BX_KEY_THIS s
.kbd_controller
.expecting_port60h
= 1;
746 case 0xdd: // Disable A20 Address Line
747 BX_SET_ENABLE_A20(0);
749 case 0xdf: // Enable A20 Address Line
750 BX_SET_ENABLE_A20(1);
752 case 0xc1: // Continuous Input Port Poll, Low
753 case 0xc2: // Continuous Input Port Poll, High
754 case 0xe0: // Read Test Inputs
755 BX_PANIC(("io write 0x64: command = %02xh", (unsigned) value
));
758 case 0xfe: // System (cpu?) Reset, transition to real mode
759 BX_INFO(("io write 0x64: command 0xfe: reset cpu"));
760 bx_pc_system
.Reset(BX_RESET_SOFTWARE
);
764 if (value
==0xff || (value
>=0xf0 && value
<=0xfd)) {
765 /* useless pulse output bit commands ??? */
766 BX_DEBUG(("io write to port 64h, useless command %02x",
770 BX_ERROR(("unsupported io write to keyboard port %x, value = %x",
771 (unsigned) address
, (unsigned) value
));
777 BX_PANIC(("unknown address in bx_keyb_c::write()"));
781 // service_paste_buf() transfers data from the paste buffer to the hardware
782 // keyboard buffer. It tries to transfer as many chars as possible at a
783 // time, but because different chars require different numbers of scancodes
784 // we have to be conservative. Note that this process depends on the
785 // keymap tables to know what chars correspond to what keys, and which
786 // chars require a shift or other modifier.
787 void bx_keyb_c::service_paste_buf()
789 if (!BX_KEY_THIS pastebuf
) return;
790 BX_DEBUG(("service_paste_buf: ptr at %d out of %d", BX_KEY_THIS pastebuf_ptr
, BX_KEY_THIS pastebuf_len
));
791 int fill_threshold
= BX_KBD_ELEMENTS
- 8;
792 BX_KEY_THIS paste_service
= 1;
793 while ((BX_KEY_THIS pastebuf_ptr
< BX_KEY_THIS pastebuf_len
) && !BX_KEY_THIS stop_paste
) {
794 if (BX_KEY_THIS s
.kbd_internal_buffer
.num_elements
>= fill_threshold
) {
795 BX_KEY_THIS paste_service
= 0;
798 // there room in the buffer for a keypress and a key release.
799 // send one keypress and a key release.
800 Bit8u byte
= BX_KEY_THIS pastebuf
[BX_KEY_THIS pastebuf_ptr
];
801 BXKeyEntry
*entry
= bx_keymap
.findAsciiChar(byte
);
803 BX_ERROR(("paste character 0x%02x ignored", byte
));
805 BX_DEBUG(("pasting character 0x%02x. baseKey is %04x", byte
, entry
->baseKey
));
806 if (entry
->modKey
!= BX_KEYMAP_UNKNOWN
)
807 BX_KEY_THIS
gen_scancode(entry
->modKey
);
808 BX_KEY_THIS
gen_scancode(entry
->baseKey
);
809 BX_KEY_THIS
gen_scancode(entry
->baseKey
| BX_KEY_RELEASED
);
810 if (entry
->modKey
!= BX_KEYMAP_UNKNOWN
)
811 BX_KEY_THIS
gen_scancode(entry
->modKey
| BX_KEY_RELEASED
);
813 BX_KEY_THIS pastebuf_ptr
++;
815 // reached end of pastebuf. free the memory it was using.
816 delete [] BX_KEY_THIS pastebuf
;
817 BX_KEY_THIS pastebuf
= NULL
;
818 BX_KEY_THIS stop_paste
= 0;
819 BX_KEY_THIS paste_service
= 0;
822 // paste_bytes schedules an arbitrary number of ASCII characters to be
823 // inserted into the hardware queue as it become available. Any previous
824 // paste which is still in progress will be thrown out. BYTES is a pointer
825 // to a region of memory containing the chars to be pasted. When the paste
826 // is complete, the keyboard code will call delete [] bytes;
827 void bx_keyb_c::paste_bytes(Bit8u
*bytes
, Bit32s length
)
829 BX_DEBUG(("paste_bytes: %d bytes", length
));
830 if (BX_KEY_THIS pastebuf
) {
831 BX_ERROR(("previous paste was not completed! %d chars lost",
832 BX_KEY_THIS pastebuf_len
- BX_KEY_THIS pastebuf_ptr
));
833 delete [] BX_KEY_THIS pastebuf
; // free the old paste buffer
835 BX_KEY_THIS pastebuf
= bytes
;
836 BX_KEY_THIS pastebuf_ptr
= 0;
837 BX_KEY_THIS pastebuf_len
= length
;
838 BX_KEY_THIS
service_paste_buf();
841 void bx_keyb_c::gen_scancode(Bit32u key
)
843 unsigned char *scancode
;
846 if ((BX_KEY_THIS pastebuf
!= NULL
) && (!BX_KEY_THIS paste_service
)) {
847 BX_KEY_THIS stop_paste
= 1;
851 BX_DEBUG(("gen_scancode(): %s %s", bx_keymap
.getBXKeyName(key
), (key
>> 31)?"released":"pressed"));
853 if (!BX_KEY_THIS s
.kbd_controller
.scancodes_translate
)
854 BX_DEBUG(("keyboard: gen_scancode with scancode_translate cleared"));
856 // Ignore scancode if keyboard clock is driven low
857 if (BX_KEY_THIS s
.kbd_controller
.kbd_clock_enabled
==0)
860 // Ignore scancode if scanning is disabled
861 if (BX_KEY_THIS s
.kbd_internal_buffer
.scanning_enabled
==0)
864 // Switch between make and break code
865 if (key
& BX_KEY_RELEASED
)
866 scancode
=(unsigned char *)scancodes
[(key
&0xFF)][BX_KEY_THIS s
.kbd_controller
.current_scancodes_set
].brek
;
868 scancode
=(unsigned char *)scancodes
[(key
&0xFF)][BX_KEY_THIS s
.kbd_controller
.current_scancodes_set
].make
;
870 #if BX_SUPPORT_PCIUSB
871 if (DEV_usb_keyboard_connected()) {
872 // if we have a keyboard/keypad installed, we need to call its handler first
873 if (DEV_usb_key_enq(scancode
)) return;
877 if (BX_KEY_THIS s
.kbd_controller
.scancodes_translate
) {
878 // Translate before send
881 for (i
=0; i
<strlen((const char *)scancode
); i
++) {
882 if (scancode
[i
] == 0xF0)
885 BX_DEBUG(("gen_scancode(): writing translated %02x",translation8042
[scancode
[i
] ] | escaped
));
886 kbd_enQ(translation8042
[scancode
[i
]] | escaped
);
893 for (i
=0; i
<strlen((const char *)scancode
); i
++) {
894 BX_DEBUG(("gen_scancode(): writing raw %02x",scancode
[i
]));
895 kbd_enQ(scancode
[i
]);
901 void BX_CPP_AttrRegparmN(1)
902 bx_keyb_c::set_kbd_clock_enable(Bit8u value
)
904 bx_bool prev_kbd_clock_enabled
;
907 BX_KEY_THIS s
.kbd_controller
.kbd_clock_enabled
= 0;
909 /* is another byte waiting to be sent from the keyboard ? */
910 prev_kbd_clock_enabled
= BX_KEY_THIS s
.kbd_controller
.kbd_clock_enabled
;
911 BX_KEY_THIS s
.kbd_controller
.kbd_clock_enabled
= 1;
913 if (prev_kbd_clock_enabled
==0 && BX_KEY_THIS s
.kbd_controller
.outb
==0) {
919 void bx_keyb_c::set_aux_clock_enable(Bit8u value
)
921 bx_bool prev_aux_clock_enabled
;
923 BX_DEBUG(("set_aux_clock_enable(%u)", (unsigned) value
));
925 BX_KEY_THIS s
.kbd_controller
.aux_clock_enabled
= 0;
927 /* is another byte waiting to be sent from the keyboard ? */
928 prev_aux_clock_enabled
= BX_KEY_THIS s
.kbd_controller
.aux_clock_enabled
;
929 BX_KEY_THIS s
.kbd_controller
.aux_clock_enabled
= 1;
930 if (prev_aux_clock_enabled
==0 && BX_KEY_THIS s
.kbd_controller
.outb
==0)
935 Bit8u
bx_keyb_c::get_kbd_enable(void)
937 BX_DEBUG(("get_kbd_enable(): getting kbd_clock_enabled of: %02x",
938 (unsigned) BX_KEY_THIS s
.kbd_controller
.kbd_clock_enabled
));
940 return(BX_KEY_THIS s
.kbd_controller
.kbd_clock_enabled
);
943 void bx_keyb_c::controller_enQ(Bit8u data
, unsigned source
)
945 // source is 0 for keyboard, 1 for mouse
947 BX_DEBUG(("controller_enQ(%02x) source=%02x", (unsigned) data
,source
));
949 // see if we need to Q this byte from the controller
950 // remember this includes mouse bytes.
951 if (BX_KEY_THIS s
.kbd_controller
.outb
) {
952 if (BX_KEY_THIS s
.controller_Qsize
>= BX_KBD_CONTROLLER_QSIZE
)
953 BX_PANIC(("controller_enq(): controller_Q full!"));
954 BX_KEY_THIS s
.controller_Q
[BX_KEY_THIS s
.controller_Qsize
++] = data
;
955 BX_KEY_THIS s
.controller_Qsource
= source
;
960 if (source
== 0) { // keyboard
961 BX_KEY_THIS s
.kbd_controller
.kbd_output_buffer
= data
;
962 BX_KEY_THIS s
.kbd_controller
.outb
= 1;
963 BX_KEY_THIS s
.kbd_controller
.auxb
= 0;
964 BX_KEY_THIS s
.kbd_controller
.inpb
= 0;
965 if (BX_KEY_THIS s
.kbd_controller
.allow_irq1
)
966 BX_KEY_THIS s
.kbd_controller
.irq1_requested
= 1;
968 BX_KEY_THIS s
.kbd_controller
.aux_output_buffer
= data
;
969 BX_KEY_THIS s
.kbd_controller
.outb
= 1;
970 BX_KEY_THIS s
.kbd_controller
.auxb
= 1;
971 BX_KEY_THIS s
.kbd_controller
.inpb
= 0;
972 if (BX_KEY_THIS s
.kbd_controller
.allow_irq12
)
973 BX_KEY_THIS s
.kbd_controller
.irq12_requested
= 1;
977 void bx_keyb_c::kbd_enQ_imm(Bit8u val
)
981 if (BX_KEY_THIS s
.kbd_internal_buffer
.num_elements
>= BX_KBD_ELEMENTS
) {
982 BX_PANIC(("internal keyboard buffer full (imm)"));
986 /* enqueue scancode in multibyte internal keyboard buffer */
987 tail
= (BX_KEY_THIS s
.kbd_internal_buffer
.head
+ BX_KEY_THIS s
.kbd_internal_buffer
.num_elements
) %
990 BX_KEY_THIS s
.kbd_controller
.kbd_output_buffer
= val
;
991 BX_KEY_THIS s
.kbd_controller
.outb
= 1;
993 if (BX_KEY_THIS s
.kbd_controller
.allow_irq1
)
994 BX_KEY_THIS s
.kbd_controller
.irq1_requested
= 1;
997 void bx_keyb_c::kbd_enQ(Bit8u scancode
)
1001 BX_DEBUG(("kbd_enQ(0x%02x)", (unsigned) scancode
));
1003 if (BX_KEY_THIS s
.kbd_internal_buffer
.num_elements
>= BX_KBD_ELEMENTS
) {
1004 BX_INFO(("internal keyboard buffer full, ignoring scancode.(%02x)",
1005 (unsigned) scancode
));
1009 /* enqueue scancode in multibyte internal keyboard buffer */
1010 BX_DEBUG(("kbd_enQ: putting scancode 0x%02x in internal buffer",
1011 (unsigned) scancode
));
1012 tail
= (BX_KEY_THIS s
.kbd_internal_buffer
.head
+ BX_KEY_THIS s
.kbd_internal_buffer
.num_elements
) %
1014 BX_KEY_THIS s
.kbd_internal_buffer
.buffer
[tail
] = scancode
;
1015 BX_KEY_THIS s
.kbd_internal_buffer
.num_elements
++;
1017 if (!BX_KEY_THIS s
.kbd_controller
.outb
&& BX_KEY_THIS s
.kbd_controller
.kbd_clock_enabled
) {
1019 BX_DEBUG(("activating timer..."));
1024 bx_bool
bx_keyb_c::mouse_enQ_packet(Bit8u b1
, Bit8u b2
, Bit8u b3
, Bit8u b4
)
1027 if (BX_KEY_THIS s
.mouse
.im_mode
) bytes
= 4;
1029 if ((BX_KEY_THIS s
.mouse_internal_buffer
.num_elements
+ bytes
) >= BX_MOUSE_BUFF_SIZE
) {
1030 return(0); /* buffer doesn't have the space */
1036 if (BX_KEY_THIS s
.mouse
.im_mode
) mouse_enQ(b4
);
1041 void bx_keyb_c::mouse_enQ(Bit8u mouse_data
)
1045 BX_DEBUG(("mouse_enQ(%02x)", (unsigned) mouse_data
));
1047 if (BX_KEY_THIS s
.mouse_internal_buffer
.num_elements
>= BX_MOUSE_BUFF_SIZE
) {
1048 BX_ERROR(("[mouse] internal mouse buffer full, ignoring mouse data.(%02x)",
1049 (unsigned) mouse_data
));
1053 /* enqueue mouse data in multibyte internal mouse buffer */
1054 tail
= (BX_KEY_THIS s
.mouse_internal_buffer
.head
+ BX_KEY_THIS s
.mouse_internal_buffer
.num_elements
) %
1056 BX_KEY_THIS s
.mouse_internal_buffer
.buffer
[tail
] = mouse_data
;
1057 BX_KEY_THIS s
.mouse_internal_buffer
.num_elements
++;
1059 if (!BX_KEY_THIS s
.kbd_controller
.outb
&& BX_KEY_THIS s
.kbd_controller
.aux_clock_enabled
) {
1065 void bx_keyb_c::kbd_ctrl_to_kbd(Bit8u value
)
1068 BX_DEBUG(("controller passed byte %02xh to keyboard", value
));
1070 if (BX_KEY_THIS s
.kbd_internal_buffer
.expecting_typematic
) {
1071 BX_KEY_THIS s
.kbd_internal_buffer
.expecting_typematic
= 0;
1072 BX_KEY_THIS s
.kbd_internal_buffer
.delay
= (value
>> 5) & 0x03;
1073 switch (BX_KEY_THIS s
.kbd_internal_buffer
.delay
) {
1074 case 0: BX_INFO(("setting delay to 250 mS (unused)")); break;
1075 case 1: BX_INFO(("setting delay to 500 mS (unused)")); break;
1076 case 2: BX_INFO(("setting delay to 750 mS (unused)")); break;
1077 case 3: BX_INFO(("setting delay to 1000 mS (unused)")); break;
1079 BX_KEY_THIS s
.kbd_internal_buffer
.repeat_rate
= value
& 0x1f;
1080 double cps
= 1 /((double)(8 + (value
& 0x07)) * (double)exp(log((double)2) * (double)((value
>> 3) & 0x03)) * 0.00417);
1081 BX_INFO(("setting repeat rate to %.1f cps (unused)", cps
));
1082 kbd_enQ(0xFA); // send ACK
1086 if (BX_KEY_THIS s
.kbd_internal_buffer
.expecting_led_write
) {
1087 BX_KEY_THIS s
.kbd_internal_buffer
.expecting_led_write
= 0;
1088 BX_KEY_THIS s
.kbd_internal_buffer
.led_status
= value
;
1089 BX_DEBUG(("LED status set to %02x",
1090 (unsigned) BX_KEY_THIS s
.kbd_internal_buffer
.led_status
));
1091 bx_gui
->statusbar_setitem(BX_KEY_THIS statusbar_id
[0], value
& 0x02);
1092 bx_gui
->statusbar_setitem(BX_KEY_THIS statusbar_id
[1], value
& 0x04);
1093 bx_gui
->statusbar_setitem(BX_KEY_THIS statusbar_id
[2], value
& 0x01);
1094 kbd_enQ(0xFA); // send ACK %%%
1098 if (BX_KEY_THIS s
.kbd_controller
.expecting_scancodes_set
) {
1099 BX_KEY_THIS s
.kbd_controller
.expecting_scancodes_set
= 0;
1102 BX_KEY_THIS s
.kbd_controller
.current_scancodes_set
= (value
-1);
1103 BX_INFO(("Switched to scancode set %d",
1104 (unsigned) BX_KEY_THIS s
.kbd_controller
.current_scancodes_set
+ 1));
1107 BX_ERROR(("Received scancodes set out of range: %d", value
));
1108 kbd_enQ(0xFF); // send ERROR
1111 // Send ACK (SF patch #1159626)
1113 // Send current scancodes set to port 0x60
1114 kbd_enQ(1 + (BX_KEY_THIS s
.kbd_controller
.current_scancodes_set
));
1120 case 0x00: // ??? ignore and let OS timeout with no response
1121 kbd_enQ(0xFA); // send ACK %%%
1125 // (mch) trying to get this to work...
1126 BX_KEY_THIS s
.kbd_controller
.sysf
= 1;
1130 case 0xed: // LED Write
1131 BX_KEY_THIS s
.kbd_internal_buffer
.expecting_led_write
= 1;
1132 kbd_enQ_imm(0xFA); // send ACK %%%
1136 kbd_enQ(0xEE); // return same byte (EEh) as echo diagnostic
1139 case 0xf0: // Select alternate scan code set
1140 BX_KEY_THIS s
.kbd_controller
.expecting_scancodes_set
= 1;
1141 BX_DEBUG(("Expecting scancode set info..."));
1142 kbd_enQ(0xFA); // send ACK
1145 case 0xf2: // identify keyboard
1146 BX_INFO(("identify keyboard command received"));
1148 // XT sends nothing, AT sends ACK
1149 // MFII with translation sends ACK+ABh+41h
1150 // MFII without translation sends ACK+ABh+83h
1151 if (SIM
->get_param_enum(BXPN_KBD_TYPE
)->get() != BX_KBD_XT_TYPE
) {
1153 if (SIM
->get_param_enum(BXPN_KBD_TYPE
)->get() == BX_KBD_MF_TYPE
) {
1156 if(BX_KEY_THIS s
.kbd_controller
.scancodes_translate
)
1164 case 0xf3: // typematic info
1165 BX_KEY_THIS s
.kbd_internal_buffer
.expecting_typematic
= 1;
1166 BX_INFO(("setting typematic info"));
1167 kbd_enQ(0xFA); // send ACK
1170 case 0xf4: // enable keyboard
1171 BX_KEY_THIS s
.kbd_internal_buffer
.scanning_enabled
= 1;
1172 kbd_enQ(0xFA); // send ACK
1175 case 0xf5: // reset keyboard to power-up settings and disable scanning
1177 kbd_enQ(0xFA); // send ACK
1178 BX_KEY_THIS s
.kbd_internal_buffer
.scanning_enabled
= 0;
1179 BX_INFO(("reset-disable command received"));
1182 case 0xf6: // reset keyboard to power-up settings and enable scanning
1184 kbd_enQ(0xFA); // send ACK
1185 BX_KEY_THIS s
.kbd_internal_buffer
.scanning_enabled
= 1;
1186 BX_INFO(("reset-enable command received"));
1189 case 0xfe: // resend. aiiee.
1190 BX_PANIC(("got 0xFE (resend)"));
1193 case 0xff: // reset: internal keyboard reset and afterwards the BAT
1194 BX_DEBUG(("reset command received"));
1196 kbd_enQ(0xFA); // send ACK
1197 BX_KEY_THIS s
.kbd_controller
.bat_in_progress
= 1;
1198 kbd_enQ(0xAA); // BAT test passed
1205 case 0xf7: // PS/2 Set All Keys To Typematic
1206 case 0xf8: // PS/2 Set All Keys to Make/Break
1207 case 0xf9: // PS/2 PS/2 Set All Keys to Make
1208 case 0xfa: // PS/2 Set All Keys to Typematic Make/Break
1209 case 0xfb: // PS/2 Set Key Type to Typematic
1210 case 0xfc: // PS/2 Set Key Type to Make/Break
1211 case 0xfd: // PS/2 Set Key Type to Make
1213 BX_ERROR(("kbd_ctrl_to_kbd(): got value of 0x%02x", value
));
1214 kbd_enQ(0xFE); /* send NACK */
1219 void bx_keyb_c::timer_handler(void *this_ptr
)
1221 bx_keyb_c
*class_ptr
= (bx_keyb_c
*)this_ptr
;
1224 retval
=class_ptr
->periodic(1);
1227 DEV_pic_raise_irq(1);
1229 DEV_pic_raise_irq(12);
1232 unsigned bx_keyb_c::periodic(Bit32u usec_delta
)
1234 /* static int multiple=0; */
1235 static unsigned count_before_paste
=0;
1240 if (BX_KEY_THIS s
.kbd_controller
.kbd_clock_enabled
) {
1241 if(++count_before_paste
>=BX_KEY_THIS pastedelay
) {
1242 // after the paste delay, consider adding moving more chars
1243 // from the paste buffer to the keyboard buffer.
1244 BX_KEY_THIS
service_paste_buf();
1245 count_before_paste
=0;
1249 retval
= BX_KEY_THIS s
.kbd_controller
.irq1_requested
| (BX_KEY_THIS s
.kbd_controller
.irq12_requested
<< 1);
1250 BX_KEY_THIS s
.kbd_controller
.irq1_requested
= 0;
1251 BX_KEY_THIS s
.kbd_controller
.irq12_requested
= 0;
1253 if (BX_KEY_THIS s
.kbd_controller
.timer_pending
== 0) {
1257 if (usec_delta
>= BX_KEY_THIS s
.kbd_controller
.timer_pending
) {
1258 BX_KEY_THIS s
.kbd_controller
.timer_pending
= 0;
1260 BX_KEY_THIS s
.kbd_controller
.timer_pending
-= usec_delta
;
1264 if (BX_KEY_THIS s
.kbd_controller
.outb
) {
1268 /* nothing in outb, look for possible data xfer from keyboard or mouse */
1269 if (BX_KEY_THIS s
.kbd_internal_buffer
.num_elements
&&
1270 (BX_KEY_THIS s
.kbd_controller
.kbd_clock_enabled
|| BX_KEY_THIS s
.kbd_controller
.bat_in_progress
)) {
1271 BX_DEBUG(("service_keyboard: key in internal buffer waiting"));
1272 BX_KEY_THIS s
.kbd_controller
.kbd_output_buffer
=
1273 BX_KEY_THIS s
.kbd_internal_buffer
.buffer
[BX_KEY_THIS s
.kbd_internal_buffer
.head
];
1274 BX_KEY_THIS s
.kbd_controller
.outb
= 1;
1275 // commented out since this would override the current state of the
1276 // mouse buffer flag - no bug seen - just seems wrong (das)
1277 // BX_KEY_THIS s.kbd_controller.auxb = 0;
1278 BX_KEY_THIS s
.kbd_internal_buffer
.head
= (BX_KEY_THIS s
.kbd_internal_buffer
.head
+ 1) %
1280 BX_KEY_THIS s
.kbd_internal_buffer
.num_elements
--;
1281 if (BX_KEY_THIS s
.kbd_controller
.allow_irq1
)
1282 BX_KEY_THIS s
.kbd_controller
.irq1_requested
= 1;
1284 create_mouse_packet(0);
1285 if (BX_KEY_THIS s
.kbd_controller
.aux_clock_enabled
&& BX_KEY_THIS s
.mouse_internal_buffer
.num_elements
) {
1286 BX_DEBUG(("service_keyboard: key(from mouse) in internal buffer waiting"));
1287 BX_KEY_THIS s
.kbd_controller
.aux_output_buffer
=
1288 BX_KEY_THIS s
.mouse_internal_buffer
.buffer
[BX_KEY_THIS s
.mouse_internal_buffer
.head
];
1290 BX_KEY_THIS s
.kbd_controller
.outb
= 1;
1291 BX_KEY_THIS s
.kbd_controller
.auxb
= 1;
1292 BX_KEY_THIS s
.mouse_internal_buffer
.head
= (BX_KEY_THIS s
.mouse_internal_buffer
.head
+ 1) %
1294 BX_KEY_THIS s
.mouse_internal_buffer
.num_elements
--;
1295 if (BX_KEY_THIS s
.kbd_controller
.allow_irq12
)
1296 BX_KEY_THIS s
.kbd_controller
.irq12_requested
= 1;
1298 BX_DEBUG(("service_keyboard(): no keys waiting"));
1304 void bx_keyb_c::activate_timer(void)
1306 if (BX_KEY_THIS s
.kbd_controller
.timer_pending
== 0) {
1307 BX_KEY_THIS s
.kbd_controller
.timer_pending
= 1;
1311 void bx_keyb_c::kbd_ctrl_to_mouse(Bit8u value
)
1313 // if we are not using a ps2 mouse, some of the following commands need to return different values
1315 if ((BX_KEY_THIS s
.mouse
.type
== BX_MOUSE_TYPE_PS2
) ||
1316 (BX_KEY_THIS s
.mouse
.type
== BX_MOUSE_TYPE_IMPS2
)) is_ps2
= 1;
1318 BX_DEBUG(("MOUSE: kbd_ctrl_to_mouse(%02xh)", (unsigned) value
));
1319 BX_DEBUG((" enable = %u", (unsigned) BX_KEY_THIS s
.mouse
.enable
));
1320 BX_DEBUG((" allow_irq12 = %u",
1321 (unsigned) BX_KEY_THIS s
.kbd_controller
.allow_irq12
));
1322 BX_DEBUG((" aux_clock_enabled = %u",
1323 (unsigned) BX_KEY_THIS s
.kbd_controller
.aux_clock_enabled
));
1325 // an ACK (0xFA) is always the first response to any valid input
1326 // received from the system other than Set-Wrap-Mode & Resend-Command
1328 if (BX_KEY_THIS s
.kbd_controller
.expecting_mouse_parameter
) {
1329 BX_KEY_THIS s
.kbd_controller
.expecting_mouse_parameter
= 0;
1330 switch (BX_KEY_THIS s
.kbd_controller
.last_mouse_command
) {
1331 case 0xf3: // Set Mouse Sample Rate
1332 BX_KEY_THIS s
.mouse
.sample_rate
= value
;
1333 BX_DEBUG(("[mouse] Sampling rate set: %d Hz", value
));
1334 if ((value
== 200) && (!BX_KEY_THIS s
.mouse
.im_request
)) {
1335 BX_KEY_THIS s
.mouse
.im_request
= 1;
1336 } else if ((value
== 100) && (BX_KEY_THIS s
.mouse
.im_request
== 1)) {
1337 BX_KEY_THIS s
.mouse
.im_request
= 2;
1338 } else if ((value
== 80) && (BX_KEY_THIS s
.mouse
.im_request
== 2)) {
1339 if (BX_KEY_THIS s
.mouse
.type
== BX_MOUSE_TYPE_IMPS2
) {
1340 BX_INFO(("wheel mouse mode enabled"));
1341 BX_KEY_THIS s
.mouse
.im_mode
= 1;
1343 BX_INFO(("wheel mouse mode request rejected"));
1345 BX_KEY_THIS s
.mouse
.im_request
= 0;
1347 BX_KEY_THIS s
.mouse
.im_request
= 0;
1349 controller_enQ(0xFA, 1); // ack
1352 case 0xe8: // Set Mouse Resolution
1355 BX_KEY_THIS s
.mouse
.resolution_cpmm
= 1;
1358 BX_KEY_THIS s
.mouse
.resolution_cpmm
= 2;
1361 BX_KEY_THIS s
.mouse
.resolution_cpmm
= 4;
1364 BX_KEY_THIS s
.mouse
.resolution_cpmm
= 8;
1367 BX_PANIC(("[mouse] Unknown resolution %d", value
));
1370 BX_DEBUG(("[mouse] Resolution set to %d counts per mm",
1371 BX_KEY_THIS s
.mouse
.resolution_cpmm
));
1373 controller_enQ(0xFA, 1); // ack
1377 BX_PANIC(("MOUSE: unknown last command (%02xh)", (unsigned) BX_KEY_THIS s
.kbd_controller
.last_mouse_command
));
1380 BX_KEY_THIS s
.kbd_controller
.expecting_mouse_parameter
= 0;
1381 BX_KEY_THIS s
.kbd_controller
.last_mouse_command
= value
;
1383 // test for wrap mode first
1384 if (BX_KEY_THIS s
.mouse
.mode
== MOUSE_MODE_WRAP
) {
1385 // if not a reset command or reset wrap mode
1386 // then just echo the byte.
1387 if ((value
!= 0xff) && (value
!= 0xec)) {
1389 BX_INFO(("[mouse] wrap mode: Ignoring command %0X02.",value
));
1390 controller_enQ(value
,1);
1396 case 0xe6: // Set Mouse Scaling to 1:1
1397 controller_enQ(0xFA, 1); // ACK
1398 BX_KEY_THIS s
.mouse
.scaling
= 2;
1399 BX_DEBUG(("[mouse] Scaling set to 1:1"));
1402 case 0xe7: // Set Mouse Scaling to 2:1
1403 controller_enQ(0xFA, 1); // ACK
1404 BX_KEY_THIS s
.mouse
.scaling
= 2;
1405 BX_DEBUG(("[mouse] Scaling set to 2:1"));
1408 case 0xe8: // Set Mouse Resolution
1409 controller_enQ(0xFA, 1); // ACK
1410 BX_KEY_THIS s
.kbd_controller
.expecting_mouse_parameter
= 1;
1413 case 0xea: // Set Stream Mode
1415 BX_INFO(("[mouse] Mouse stream mode on."));
1416 BX_KEY_THIS s
.mouse
.mode
= MOUSE_MODE_STREAM
;
1417 controller_enQ(0xFA, 1); // ACK
1420 case 0xec: // Reset Wrap Mode
1421 // unless we are in wrap mode ignore the command
1422 if (BX_KEY_THIS s
.mouse
.mode
== MOUSE_MODE_WRAP
) {
1424 BX_INFO(("[mouse] Mouse wrap mode off."));
1425 // restore previous mode except disable stream mode reporting.
1426 // ### TODO disabling reporting in stream mode
1427 BX_KEY_THIS s
.mouse
.mode
= BX_KEY_THIS s
.mouse
.saved_mode
;
1428 controller_enQ(0xFA, 1); // ACK
1431 case 0xee: // Set Wrap Mode
1432 // ### TODO flush output queue.
1433 // ### TODO disable interrupts if in stream mode.
1435 BX_INFO(("[mouse] Mouse wrap mode on."));
1436 BX_KEY_THIS s
.mouse
.saved_mode
= BX_KEY_THIS s
.mouse
.mode
;
1437 BX_KEY_THIS s
.mouse
.mode
= MOUSE_MODE_WRAP
;
1438 controller_enQ(0xFA, 1); // ACK
1441 case 0xf0: // Set Remote Mode (polling mode, i.e. not stream mode.)
1443 BX_INFO(("[mouse] Mouse remote mode on."));
1444 // ### TODO should we flush/discard/ignore any already queued packets?
1445 BX_KEY_THIS s
.mouse
.mode
= MOUSE_MODE_REMOTE
;
1446 controller_enQ(0xFA, 1); // ACK
1449 case 0xf2: // Read Device Type
1450 controller_enQ(0xFA, 1); // ACK
1451 if (BX_KEY_THIS s
.mouse
.im_mode
)
1452 controller_enQ(0x03, 1); // Device ID (wheel z-mouse)
1454 controller_enQ(0x00, 1); // Device ID (standard)
1455 BX_DEBUG(("[mouse] Read mouse ID"));
1458 case 0xf3: // Set Mouse Sample Rate (sample rate written to port 60h)
1459 controller_enQ(0xFA, 1); // ACK
1460 BX_KEY_THIS s
.kbd_controller
.expecting_mouse_parameter
= 1;
1463 case 0xf4: // Enable (in stream mode)
1464 // is a mouse present?
1466 BX_KEY_THIS s
.mouse
.enable
= 1;
1467 controller_enQ(0xFA, 1); // ACK
1468 BX_DEBUG(("[mouse] Mouse enabled (stream mode)"));
1470 // a mouse isn't present. We need to return a 0xFE (resend) instead of a 0xFA (ACK)
1471 controller_enQ(0xFE, 1); // RESEND
1472 BX_KEY_THIS s
.kbd_controller
.tim
= 1;
1476 case 0xf5: // Disable (in stream mode)
1477 BX_KEY_THIS s
.mouse
.enable
= 0;
1478 controller_enQ(0xFA, 1); // ACK
1479 BX_DEBUG(("[mouse] Mouse disabled (stream mode)"));
1482 case 0xf6: // Set Defaults
1483 BX_KEY_THIS s
.mouse
.sample_rate
= 100; /* reports per second (default) */
1484 BX_KEY_THIS s
.mouse
.resolution_cpmm
= 4; /* 4 counts per millimeter (default) */
1485 BX_KEY_THIS s
.mouse
.scaling
= 1; /* 1:1 (default) */
1486 BX_KEY_THIS s
.mouse
.enable
= 0;
1487 BX_KEY_THIS s
.mouse
.mode
= MOUSE_MODE_STREAM
;
1488 controller_enQ(0xFA, 1); // ACK
1489 BX_DEBUG(("[mouse] Set Defaults"));
1493 // is a mouse present?
1495 BX_KEY_THIS s
.mouse
.sample_rate
= 100; /* reports per second (default) */
1496 BX_KEY_THIS s
.mouse
.resolution_cpmm
= 4; /* 4 counts per millimeter (default) */
1497 BX_KEY_THIS s
.mouse
.scaling
= 1; /* 1:1 (default) */
1498 BX_KEY_THIS s
.mouse
.mode
= MOUSE_MODE_RESET
;
1499 BX_KEY_THIS s
.mouse
.enable
= 0;
1500 if (BX_KEY_THIS s
.mouse
.im_mode
)
1501 BX_INFO(("wheel mouse mode disabled"));
1502 BX_KEY_THIS s
.mouse
.im_mode
= 0;
1503 /* (mch) NT expects an ack here */
1504 controller_enQ(0xFA, 1); // ACK
1505 controller_enQ(0xAA, 1); // completion code
1506 controller_enQ(0x00, 1); // ID code (standard after reset)
1507 BX_DEBUG(("[mouse] Mouse reset"));
1509 // a mouse isn't present. We need to return a 0xFE (resend) instead of a 0xFA (ACK)
1510 controller_enQ(0xFE, 1); // RESEND
1511 BX_KEY_THIS s
.kbd_controller
.tim
= 1;
1515 case 0xe9: // Get mouse information
1516 // should we ack here? (mch): Yes
1517 controller_enQ(0xFA, 1); // ACK
1518 controller_enQ(BX_KEY_THIS s
.mouse
.get_status_byte(), 1); // status
1519 controller_enQ(BX_KEY_THIS s
.mouse
.get_resolution_byte(), 1); // resolution
1520 controller_enQ(BX_KEY_THIS s
.mouse
.sample_rate
, 1); // sample rate
1521 BX_DEBUG(("[mouse] Get mouse information"));
1524 case 0xeb: // Read Data (send a packet when in Remote Mode)
1525 controller_enQ(0xFA, 1); // ACK
1526 // perhaps we should be adding some movement here.
1527 mouse_enQ_packet(((BX_KEY_THIS s
.mouse
.button_status
& 0x0f) | 0x08),
1528 0x00, 0x00, 0x00); // bit3 of first byte always set
1529 //assumed we really aren't in polling mode, a rather odd assumption.
1530 BX_ERROR(("[mouse] Warning: Read Data command partially supported."));
1533 case 0xbb: // OS/2 Warp 3 uses this command
1534 BX_ERROR(("[mouse] ignoring 0xbb command"));
1538 // If PS/2 mouse present, send NACK for unknown commands, otherwise ignore
1540 BX_ERROR(("[mouse] kbd_ctrl_to_mouse(): got value of 0x%02x", value
));
1541 controller_enQ(0xFE, 1); /* send NACK */
1547 void bx_keyb_c::create_mouse_packet(bx_bool force_enq
)
1549 Bit8u b1
, b2
, b3
, b4
;
1551 if(BX_KEY_THIS s
.mouse_internal_buffer
.num_elements
&& !force_enq
)
1554 Bit16s delta_x
= BX_KEY_THIS s
.mouse
.delayed_dx
;
1555 Bit16s delta_y
= BX_KEY_THIS s
.mouse
.delayed_dy
;
1556 Bit8u button_state
=BX_KEY_THIS s
.mouse
.button_status
| 0x08;
1558 if(!force_enq
&& !delta_x
&& !delta_y
) {
1562 if(delta_x
>254) delta_x
=254;
1563 if(delta_x
<-254) delta_x
=-254;
1564 if(delta_y
>254) delta_y
=254;
1565 if(delta_y
<-254) delta_y
=-254;
1567 b1
= (button_state
& 0x0f) | 0x08; // bit3 always set
1569 if ((delta_x
>=0) && (delta_x
<=255)) {
1570 b2
= (Bit8u
) delta_x
;
1571 BX_KEY_THIS s
.mouse
.delayed_dx
-=delta_x
;
1573 else if (delta_x
> 255) {
1575 BX_KEY_THIS s
.mouse
.delayed_dx
-=255;
1577 else if (delta_x
>= -256) {
1578 b2
= (Bit8u
) delta_x
;
1580 BX_KEY_THIS s
.mouse
.delayed_dx
-=delta_x
;
1585 BX_KEY_THIS s
.mouse
.delayed_dx
+=256;
1588 if ((delta_y
>=0) && (delta_y
<=255)) {
1589 b3
= (Bit8u
) delta_y
;
1590 BX_KEY_THIS s
.mouse
.delayed_dy
-=delta_y
;
1592 else if (delta_y
> 255) {
1594 BX_KEY_THIS s
.mouse
.delayed_dy
-=255;
1596 else if (delta_y
>= -256) {
1597 b3
= (Bit8u
) delta_y
;
1599 BX_KEY_THIS s
.mouse
.delayed_dy
-=delta_y
;
1604 BX_KEY_THIS s
.mouse
.delayed_dy
+=256;
1607 b4
= (Bit8u
) -BX_KEY_THIS s
.mouse
.delayed_dz
;
1609 mouse_enQ_packet(b1
, b2
, b3
, b4
);
1613 void bx_keyb_c::mouse_enabled_changed(bx_bool enabled
)
1615 BX_KEY_THIS s
.mouse
.captured
= enabled
;
1616 #if BX_SUPPORT_PCIUSB
1617 // if an usb mouse is connected, notify the device about the status change
1618 if (DEV_usb_mouse_connected()) {
1619 DEV_usb_mouse_enabled_changed(enabled
);
1624 if (BX_KEY_THIS s
.mouse
.delayed_dx
|| BX_KEY_THIS s
.mouse
.delayed_dy
||
1625 BX_KEY_THIS s
.mouse
.delayed_dz
) {
1626 create_mouse_packet(1);
1628 BX_KEY_THIS s
.mouse
.delayed_dx
=0;
1629 BX_KEY_THIS s
.mouse
.delayed_dy
=0;
1630 BX_KEY_THIS s
.mouse
.delayed_dz
=0;
1631 BX_DEBUG(("PS/2 mouse %s", enabled
?"enabled":"disabled"));
1634 void bx_keyb_c::mouse_motion(int delta_x
, int delta_y
, int delta_z
, unsigned button_state
)
1638 // If mouse events are disabled on the GUI headerbar, don't
1639 // generate any mouse data
1640 if (!BX_KEY_THIS s
.mouse
.captured
)
1643 #if BX_SUPPORT_PCIUSB
1644 // if an usb mouse is connected, redirect mouse data to the usb device
1645 if (DEV_usb_mouse_connected()) {
1646 DEV_usb_mouse_enq(delta_x
, delta_y
, delta_z
, button_state
);
1651 // if type == serial, redirect mouse data to the serial device
1652 if ((BX_KEY_THIS s
.mouse
.type
== BX_MOUSE_TYPE_SERIAL
) ||
1653 (BX_KEY_THIS s
.mouse
.type
== BX_MOUSE_TYPE_SERIAL_WHEEL
) ||
1654 (BX_KEY_THIS s
.mouse
.type
== BX_MOUSE_TYPE_SERIAL_MSYS
)) {
1655 DEV_serial_mouse_enq(delta_x
, delta_y
, delta_z
, button_state
);
1659 #if BX_SUPPORT_BUSMOUSE
1660 // if type == bus, redirect mouse data to the bus device
1661 if (BX_KEY_THIS s
.mouse
.type
== BX_MOUSE_TYPE_BUS
) {
1662 DEV_bus_mouse_enq(delta_x
, delta_y
, 0, button_state
);
1667 // don't generate interrupts if we are in remote mode.
1668 if (BX_KEY_THIS s
.mouse
.mode
== MOUSE_MODE_REMOTE
)
1669 // is there any point in doing any work if we don't act on the result
1673 // Note: enable only applies in STREAM MODE.
1674 if (BX_KEY_THIS s
.mouse
.enable
==0)
1677 // scale down the motion
1678 if ((delta_x
< -1) || (delta_x
> 1))
1680 if ((delta_y
< -1) || (delta_y
> 1))
1683 if (!BX_KEY_THIS s
.mouse
.im_mode
)
1686 #ifdef VERBOSE_KBD_DEBUG
1687 if (delta_x
!= 0 || delta_y
!= 0 || delta_z
!= 0)
1688 BX_DEBUG(("[mouse] Dx=%d Dy=%d Dz=%d", delta_x
, delta_y
, delta_z
));
1689 #endif /* ifdef VERBOSE_KBD_DEBUG */
1691 if ((delta_x
==0) && (delta_y
==0) && (delta_z
==0) && (BX_KEY_THIS s
.mouse
.button_status
== (button_state
& 0x7))) {
1692 BX_DEBUG(("Ignoring useless mouse_motion call:"));
1693 BX_DEBUG(("This should be fixed in the gui code."));
1697 if ((BX_KEY_THIS s
.mouse
.button_status
!= (button_state
& 0x7)) || delta_z
) {
1701 BX_KEY_THIS s
.mouse
.button_status
= button_state
& 0x7;
1703 if(delta_x
>255) delta_x
=255;
1704 if(delta_y
>255) delta_y
=255;
1705 if(delta_x
<-256) delta_x
=-256;
1706 if(delta_y
<-256) delta_y
=-256;
1708 BX_KEY_THIS s
.mouse
.delayed_dx
+=delta_x
;
1709 BX_KEY_THIS s
.mouse
.delayed_dy
+=delta_y
;
1710 BX_KEY_THIS s
.mouse
.delayed_dz
= delta_z
;
1712 if((BX_KEY_THIS s
.mouse
.delayed_dx
>255)||
1713 (BX_KEY_THIS s
.mouse
.delayed_dx
<-256)||
1714 (BX_KEY_THIS s
.mouse
.delayed_dy
>255)||
1715 (BX_KEY_THIS s
.mouse
.delayed_dy
<-256)) {
1719 create_mouse_packet(force_enq
);