]> Git Repo - qemu.git/blame - hw/pckbd.c
added I/O API - io port API change - added multiple network interface support - redir...
[qemu.git] / hw / pckbd.c
CommitLineData
80cabfad
FB
1/*
2 * QEMU PC keyboard emulation
3 *
4 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24#include <stdlib.h>
25#include <stdio.h>
26#include <stdarg.h>
27#include <string.h>
28#include <getopt.h>
29#include <inttypes.h>
30#include <unistd.h>
31#include <sys/mman.h>
32#include <fcntl.h>
33#include <signal.h>
34#include <time.h>
35#include <sys/time.h>
36#include <malloc.h>
37#include <termios.h>
38#include <sys/poll.h>
39#include <errno.h>
40#include <sys/wait.h>
41#include <netinet/in.h>
42
43#include "cpu.h"
44#include "vl.h"
45
46/* debug PC keyboard */
47//#define DEBUG_KBD
48
49/* debug PC keyboard : only mouse */
50//#define DEBUG_MOUSE
51
52/* Keyboard Controller Commands */
53#define KBD_CCMD_READ_MODE 0x20 /* Read mode bits */
54#define KBD_CCMD_WRITE_MODE 0x60 /* Write mode bits */
55#define KBD_CCMD_GET_VERSION 0xA1 /* Get controller version */
56#define KBD_CCMD_MOUSE_DISABLE 0xA7 /* Disable mouse interface */
57#define KBD_CCMD_MOUSE_ENABLE 0xA8 /* Enable mouse interface */
58#define KBD_CCMD_TEST_MOUSE 0xA9 /* Mouse interface test */
59#define KBD_CCMD_SELF_TEST 0xAA /* Controller self test */
60#define KBD_CCMD_KBD_TEST 0xAB /* Keyboard interface test */
61#define KBD_CCMD_KBD_DISABLE 0xAD /* Keyboard interface disable */
62#define KBD_CCMD_KBD_ENABLE 0xAE /* Keyboard interface enable */
63#define KBD_CCMD_READ_INPORT 0xC0 /* read input port */
64#define KBD_CCMD_READ_OUTPORT 0xD0 /* read output port */
65#define KBD_CCMD_WRITE_OUTPORT 0xD1 /* write output port */
66#define KBD_CCMD_WRITE_OBUF 0xD2
67#define KBD_CCMD_WRITE_AUX_OBUF 0xD3 /* Write to output buffer as if
68 initiated by the auxiliary device */
69#define KBD_CCMD_WRITE_MOUSE 0xD4 /* Write the following byte to the mouse */
70#define KBD_CCMD_DISABLE_A20 0xDD /* HP vectra only ? */
71#define KBD_CCMD_ENABLE_A20 0xDF /* HP vectra only ? */
72#define KBD_CCMD_RESET 0xFE
73
74/* Keyboard Commands */
75#define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */
76#define KBD_CMD_ECHO 0xEE
77#define KBD_CMD_GET_ID 0xF2 /* get keyboard ID */
78#define KBD_CMD_SET_RATE 0xF3 /* Set typematic rate */
79#define KBD_CMD_ENABLE 0xF4 /* Enable scanning */
80#define KBD_CMD_RESET_DISABLE 0xF5 /* reset and disable scanning */
81#define KBD_CMD_RESET_ENABLE 0xF6 /* reset and enable scanning */
82#define KBD_CMD_RESET 0xFF /* Reset */
83
84/* Keyboard Replies */
85#define KBD_REPLY_POR 0xAA /* Power on reset */
86#define KBD_REPLY_ACK 0xFA /* Command ACK */
87#define KBD_REPLY_RESEND 0xFE /* Command NACK, send the cmd again */
88
89/* Status Register Bits */
90#define KBD_STAT_OBF 0x01 /* Keyboard output buffer full */
91#define KBD_STAT_IBF 0x02 /* Keyboard input buffer full */
92#define KBD_STAT_SELFTEST 0x04 /* Self test successful */
93#define KBD_STAT_CMD 0x08 /* Last write was a command write (0=data) */
94#define KBD_STAT_UNLOCKED 0x10 /* Zero if keyboard locked */
95#define KBD_STAT_MOUSE_OBF 0x20 /* Mouse output buffer full */
96#define KBD_STAT_GTO 0x40 /* General receive/xmit timeout */
97#define KBD_STAT_PERR 0x80 /* Parity error */
98
99/* Controller Mode Register Bits */
100#define KBD_MODE_KBD_INT 0x01 /* Keyboard data generate IRQ1 */
101#define KBD_MODE_MOUSE_INT 0x02 /* Mouse data generate IRQ12 */
102#define KBD_MODE_SYS 0x04 /* The system flag (?) */
103#define KBD_MODE_NO_KEYLOCK 0x08 /* The keylock doesn't affect the keyboard if set */
104#define KBD_MODE_DISABLE_KBD 0x10 /* Disable keyboard interface */
105#define KBD_MODE_DISABLE_MOUSE 0x20 /* Disable mouse interface */
106#define KBD_MODE_KCC 0x40 /* Scan code conversion to PC format */
107#define KBD_MODE_RFU 0x80
108
109/* Mouse Commands */
110#define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */
111#define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */
112#define AUX_SET_RES 0xE8 /* Set resolution */
113#define AUX_GET_SCALE 0xE9 /* Get scaling factor */
114#define AUX_SET_STREAM 0xEA /* Set stream mode */
115#define AUX_POLL 0xEB /* Poll */
116#define AUX_RESET_WRAP 0xEC /* Reset wrap mode */
117#define AUX_SET_WRAP 0xEE /* Set wrap mode */
118#define AUX_SET_REMOTE 0xF0 /* Set remote mode */
119#define AUX_GET_TYPE 0xF2 /* Get type */
120#define AUX_SET_SAMPLE 0xF3 /* Set sample rate */
121#define AUX_ENABLE_DEV 0xF4 /* Enable aux device */
122#define AUX_DISABLE_DEV 0xF5 /* Disable aux device */
123#define AUX_SET_DEFAULT 0xF6
124#define AUX_RESET 0xFF /* Reset aux device */
125#define AUX_ACK 0xFA /* Command byte ACK. */
126
127#define MOUSE_STATUS_REMOTE 0x40
128#define MOUSE_STATUS_ENABLED 0x20
129#define MOUSE_STATUS_SCALE21 0x10
130
131#define KBD_QUEUE_SIZE 256
132
133typedef struct {
134 uint8_t data[KBD_QUEUE_SIZE];
135 int rptr, wptr, count;
136} KBDQueue;
137
138typedef struct KBDState {
139 KBDQueue queues[2];
140 uint8_t write_cmd; /* if non zero, write data to port 60 is expected */
141 uint8_t status;
142 uint8_t mode;
143 /* keyboard state */
144 int kbd_write_cmd;
145 int scan_enabled;
146 /* mouse state */
147 int mouse_write_cmd;
148 uint8_t mouse_status;
149 uint8_t mouse_resolution;
150 uint8_t mouse_sample_rate;
151 uint8_t mouse_wrap;
152 uint8_t mouse_type; /* 0 = PS2, 3 = IMPS/2, 4 = IMEX */
153 uint8_t mouse_detect_state;
154 int mouse_dx; /* current values, needed for 'poll' mode */
155 int mouse_dy;
156 int mouse_dz;
157 uint8_t mouse_buttons;
158} KBDState;
159
160KBDState kbd_state;
161int reset_requested;
162
163/* update irq and KBD_STAT_[MOUSE_]OBF */
164/* XXX: not generating the irqs if KBD_MODE_DISABLE_KBD is set may be
165 incorrect, but it avoids having to simulate exact delays */
166static void kbd_update_irq(KBDState *s)
167{
168 int irq12_level, irq1_level;
169
170 irq1_level = 0;
171 irq12_level = 0;
172 s->status &= ~(KBD_STAT_OBF | KBD_STAT_MOUSE_OBF);
173 if (s->queues[0].count != 0 ||
174 s->queues[1].count != 0) {
175 s->status |= KBD_STAT_OBF;
176 if (s->queues[1].count != 0) {
177 s->status |= KBD_STAT_MOUSE_OBF;
178 if (s->mode & KBD_MODE_MOUSE_INT)
179 irq12_level = 1;
180 } else {
181 if ((s->mode & KBD_MODE_KBD_INT) &&
182 !(s->mode & KBD_MODE_DISABLE_KBD))
183 irq1_level = 1;
184 }
185 }
186 pic_set_irq(1, irq1_level);
187 pic_set_irq(12, irq12_level);
188}
189
190static void kbd_queue(KBDState *s, int b, int aux)
191{
192 KBDQueue *q = &kbd_state.queues[aux];
193
194#if defined(DEBUG_MOUSE) || defined(DEBUG_KBD)
195 if (aux)
196 printf("mouse event: 0x%02x\n", b);
197#ifdef DEBUG_KBD
198 else
199 printf("kbd event: 0x%02x\n", b);
200#endif
201#endif
202 if (q->count >= KBD_QUEUE_SIZE)
203 return;
204 q->data[q->wptr] = b;
205 if (++q->wptr == KBD_QUEUE_SIZE)
206 q->wptr = 0;
207 q->count++;
208 kbd_update_irq(s);
209}
210
211void kbd_put_keycode(int keycode)
212{
213 KBDState *s = &kbd_state;
214 kbd_queue(s, keycode, 0);
215}
216
217static uint32_t kbd_read_status(CPUState *env, uint32_t addr)
218{
219 KBDState *s = &kbd_state;
220 int val;
221 val = s->status;
222#if defined(DEBUG_KBD)
223 printf("kbd: read status=0x%02x\n", val);
224#endif
225 return val;
226}
227
228static void kbd_write_command(CPUState *env, uint32_t addr, uint32_t val)
229{
230 KBDState *s = &kbd_state;
231
232#ifdef DEBUG_KBD
233 printf("kbd: write cmd=0x%02x\n", val);
234#endif
235 switch(val) {
236 case KBD_CCMD_READ_MODE:
237 kbd_queue(s, s->mode, 0);
238 break;
239 case KBD_CCMD_WRITE_MODE:
240 case KBD_CCMD_WRITE_OBUF:
241 case KBD_CCMD_WRITE_AUX_OBUF:
242 case KBD_CCMD_WRITE_MOUSE:
243 case KBD_CCMD_WRITE_OUTPORT:
244 s->write_cmd = val;
245 break;
246 case KBD_CCMD_MOUSE_DISABLE:
247 s->mode |= KBD_MODE_DISABLE_MOUSE;
248 break;
249 case KBD_CCMD_MOUSE_ENABLE:
250 s->mode &= ~KBD_MODE_DISABLE_MOUSE;
251 break;
252 case KBD_CCMD_TEST_MOUSE:
253 kbd_queue(s, 0x00, 0);
254 break;
255 case KBD_CCMD_SELF_TEST:
256 s->status |= KBD_STAT_SELFTEST;
257 kbd_queue(s, 0x55, 0);
258 break;
259 case KBD_CCMD_KBD_TEST:
260 kbd_queue(s, 0x00, 0);
261 break;
262 case KBD_CCMD_KBD_DISABLE:
263 s->mode |= KBD_MODE_DISABLE_KBD;
264 kbd_update_irq(s);
265 break;
266 case KBD_CCMD_KBD_ENABLE:
267 s->mode &= ~KBD_MODE_DISABLE_KBD;
268 kbd_update_irq(s);
269 break;
270 case KBD_CCMD_READ_INPORT:
271 kbd_queue(s, 0x00, 0);
272 break;
273 case KBD_CCMD_READ_OUTPORT:
274 /* XXX: check that */
275#ifdef TARGET_I386
276 val = 0x01 | (((cpu_single_env->a20_mask >> 20) & 1) << 1);
277#else
278 val = 0x01;
279#endif
280 if (s->status & KBD_STAT_OBF)
281 val |= 0x10;
282 if (s->status & KBD_STAT_MOUSE_OBF)
283 val |= 0x20;
284 kbd_queue(s, val, 0);
285 break;
286#ifdef TARGET_I386
287 case KBD_CCMD_ENABLE_A20:
288 cpu_x86_set_a20(env, 1);
289 break;
290 case KBD_CCMD_DISABLE_A20:
291 cpu_x86_set_a20(env, 0);
292 break;
293#endif
294 case KBD_CCMD_RESET:
295 reset_requested = 1;
296 cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT);
297 break;
298 case 0xff:
299 /* ignore that - I don't know what is its use */
300 break;
301 default:
302 fprintf(stderr, "qemu: unsupported keyboard cmd=0x%02x\n", val);
303 break;
304 }
305}
306
307static uint32_t kbd_read_data(CPUState *env, uint32_t addr)
308{
309 KBDState *s = &kbd_state;
310 KBDQueue *q;
311 int val, index;
312
313 q = &s->queues[0]; /* first check KBD data */
314 if (q->count == 0)
315 q = &s->queues[1]; /* then check AUX data */
316 if (q->count == 0) {
317 /* NOTE: if no data left, we return the last keyboard one
318 (needed for EMM386) */
319 /* XXX: need a timer to do things correctly */
320 q = &s->queues[0];
321 index = q->rptr - 1;
322 if (index < 0)
323 index = KBD_QUEUE_SIZE - 1;
324 val = q->data[index];
325 } else {
326 val = q->data[q->rptr];
327 if (++q->rptr == KBD_QUEUE_SIZE)
328 q->rptr = 0;
329 q->count--;
330 /* reading deasserts IRQ */
331 if (q == &s->queues[0])
332 pic_set_irq(1, 0);
333 else
334 pic_set_irq(12, 0);
335 }
336 /* reassert IRQs if data left */
337 kbd_update_irq(s);
338#ifdef DEBUG_KBD
339 printf("kbd: read data=0x%02x\n", val);
340#endif
341 return val;
342}
343
344static void kbd_reset_keyboard(KBDState *s)
345{
346 s->scan_enabled = 1;
347}
348
349static void kbd_write_keyboard(KBDState *s, int val)
350{
351 switch(s->kbd_write_cmd) {
352 default:
353 case -1:
354 switch(val) {
355 case 0x00:
356 kbd_queue(s, KBD_REPLY_ACK, 0);
357 break;
358 case 0x05:
359 kbd_queue(s, KBD_REPLY_RESEND, 0);
360 break;
361 case KBD_CMD_GET_ID:
362 kbd_queue(s, KBD_REPLY_ACK, 0);
363 kbd_queue(s, 0xab, 0);
364 kbd_queue(s, 0x83, 0);
365 break;
366 case KBD_CMD_ECHO:
367 kbd_queue(s, KBD_CMD_ECHO, 0);
368 break;
369 case KBD_CMD_ENABLE:
370 s->scan_enabled = 1;
371 kbd_queue(s, KBD_REPLY_ACK, 0);
372 break;
373 case KBD_CMD_SET_LEDS:
374 case KBD_CMD_SET_RATE:
375 s->kbd_write_cmd = val;
376 kbd_queue(s, KBD_REPLY_ACK, 0);
377 break;
378 case KBD_CMD_RESET_DISABLE:
379 kbd_reset_keyboard(s);
380 s->scan_enabled = 0;
381 kbd_queue(s, KBD_REPLY_ACK, 0);
382 break;
383 case KBD_CMD_RESET_ENABLE:
384 kbd_reset_keyboard(s);
385 s->scan_enabled = 1;
386 kbd_queue(s, KBD_REPLY_ACK, 0);
387 break;
388 case KBD_CMD_RESET:
389 kbd_reset_keyboard(s);
390 kbd_queue(s, KBD_REPLY_ACK, 0);
391 kbd_queue(s, KBD_REPLY_POR, 0);
392 break;
393 default:
394 kbd_queue(s, KBD_REPLY_ACK, 0);
395 break;
396 }
397 break;
398 case KBD_CMD_SET_LEDS:
399 kbd_queue(s, KBD_REPLY_ACK, 0);
400 s->kbd_write_cmd = -1;
401 break;
402 case KBD_CMD_SET_RATE:
403 kbd_queue(s, KBD_REPLY_ACK, 0);
404 s->kbd_write_cmd = -1;
405 break;
406 }
407}
408
409static void kbd_mouse_send_packet(KBDState *s)
410{
411 unsigned int b;
412 int dx1, dy1, dz1;
413
414 dx1 = s->mouse_dx;
415 dy1 = s->mouse_dy;
416 dz1 = s->mouse_dz;
417 /* XXX: increase range to 8 bits ? */
418 if (dx1 > 127)
419 dx1 = 127;
420 else if (dx1 < -127)
421 dx1 = -127;
422 if (dy1 > 127)
423 dy1 = 127;
424 else if (dy1 < -127)
425 dy1 = -127;
426 b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07);
427 kbd_queue(s, b, 1);
428 kbd_queue(s, dx1 & 0xff, 1);
429 kbd_queue(s, dy1 & 0xff, 1);
430 /* extra byte for IMPS/2 or IMEX */
431 switch(s->mouse_type) {
432 default:
433 break;
434 case 3:
435 if (dz1 > 127)
436 dz1 = 127;
437 else if (dz1 < -127)
438 dz1 = -127;
439 kbd_queue(s, dz1 & 0xff, 1);
440 break;
441 case 4:
442 if (dz1 > 7)
443 dz1 = 7;
444 else if (dz1 < -7)
445 dz1 = -7;
446 b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
447 kbd_queue(s, b, 1);
448 break;
449 }
450
451 /* update deltas */
452 s->mouse_dx -= dx1;
453 s->mouse_dy -= dy1;
454 s->mouse_dz -= dz1;
455}
456
457void kbd_mouse_event(int dx, int dy, int dz, int buttons_state)
458{
459 KBDState *s = &kbd_state;
460
461 /* check if deltas are recorded when disabled */
462 if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
463 return;
464
465 s->mouse_dx += dx;
466 s->mouse_dy -= dy;
467 s->mouse_dz += dz;
468 s->mouse_buttons = buttons_state;
469
470 if (!(s->mouse_status & MOUSE_STATUS_REMOTE) &&
471 (s->queues[1].count < (KBD_QUEUE_SIZE - 16))) {
472 for(;;) {
473 /* if not remote, send event. Multiple events are sent if
474 too big deltas */
475 kbd_mouse_send_packet(s);
476 if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)
477 break;
478 }
479 }
480}
481
482static void kbd_write_mouse(KBDState *s, int val)
483{
484#ifdef DEBUG_MOUSE
485 printf("kbd: write mouse 0x%02x\n", val);
486#endif
487 switch(s->mouse_write_cmd) {
488 default:
489 case -1:
490 /* mouse command */
491 if (s->mouse_wrap) {
492 if (val == AUX_RESET_WRAP) {
493 s->mouse_wrap = 0;
494 kbd_queue(s, AUX_ACK, 1);
495 return;
496 } else if (val != AUX_RESET) {
497 kbd_queue(s, val, 1);
498 return;
499 }
500 }
501 switch(val) {
502 case AUX_SET_SCALE11:
503 s->mouse_status &= ~MOUSE_STATUS_SCALE21;
504 kbd_queue(s, AUX_ACK, 1);
505 break;
506 case AUX_SET_SCALE21:
507 s->mouse_status |= MOUSE_STATUS_SCALE21;
508 kbd_queue(s, AUX_ACK, 1);
509 break;
510 case AUX_SET_STREAM:
511 s->mouse_status &= ~MOUSE_STATUS_REMOTE;
512 kbd_queue(s, AUX_ACK, 1);
513 break;
514 case AUX_SET_WRAP:
515 s->mouse_wrap = 1;
516 kbd_queue(s, AUX_ACK, 1);
517 break;
518 case AUX_SET_REMOTE:
519 s->mouse_status |= MOUSE_STATUS_REMOTE;
520 kbd_queue(s, AUX_ACK, 1);
521 break;
522 case AUX_GET_TYPE:
523 kbd_queue(s, AUX_ACK, 1);
524 kbd_queue(s, s->mouse_type, 1);
525 break;
526 case AUX_SET_RES:
527 case AUX_SET_SAMPLE:
528 s->mouse_write_cmd = val;
529 kbd_queue(s, AUX_ACK, 1);
530 break;
531 case AUX_GET_SCALE:
532 kbd_queue(s, AUX_ACK, 1);
533 kbd_queue(s, s->mouse_status, 1);
534 kbd_queue(s, s->mouse_resolution, 1);
535 kbd_queue(s, s->mouse_sample_rate, 1);
536 break;
537 case AUX_POLL:
538 kbd_queue(s, AUX_ACK, 1);
539 kbd_mouse_send_packet(s);
540 break;
541 case AUX_ENABLE_DEV:
542 s->mouse_status |= MOUSE_STATUS_ENABLED;
543 kbd_queue(s, AUX_ACK, 1);
544 break;
545 case AUX_DISABLE_DEV:
546 s->mouse_status &= ~MOUSE_STATUS_ENABLED;
547 kbd_queue(s, AUX_ACK, 1);
548 break;
549 case AUX_SET_DEFAULT:
550 s->mouse_sample_rate = 100;
551 s->mouse_resolution = 2;
552 s->mouse_status = 0;
553 kbd_queue(s, AUX_ACK, 1);
554 break;
555 case AUX_RESET:
556 s->mouse_sample_rate = 100;
557 s->mouse_resolution = 2;
558 s->mouse_status = 0;
559 kbd_queue(s, AUX_ACK, 1);
560 kbd_queue(s, 0xaa, 1);
561 kbd_queue(s, s->mouse_type, 1);
562 break;
563 default:
564 break;
565 }
566 break;
567 case AUX_SET_SAMPLE:
568 s->mouse_sample_rate = val;
569#if 0
570 /* detect IMPS/2 or IMEX */
571 switch(s->mouse_detect_state) {
572 default:
573 case 0:
574 if (val == 200)
575 s->mouse_detect_state = 1;
576 break;
577 case 1:
578 if (val == 100)
579 s->mouse_detect_state = 2;
580 else if (val == 200)
581 s->mouse_detect_state = 3;
582 else
583 s->mouse_detect_state = 0;
584 break;
585 case 2:
586 if (val == 80)
587 s->mouse_type = 3; /* IMPS/2 */
588 s->mouse_detect_state = 0;
589 break;
590 case 3:
591 if (val == 80)
592 s->mouse_type = 4; /* IMEX */
593 s->mouse_detect_state = 0;
594 break;
595 }
596#endif
597 kbd_queue(s, AUX_ACK, 1);
598 s->mouse_write_cmd = -1;
599 break;
600 case AUX_SET_RES:
601 s->mouse_resolution = val;
602 kbd_queue(s, AUX_ACK, 1);
603 s->mouse_write_cmd = -1;
604 break;
605 }
606}
607
608void kbd_write_data(CPUState *env, uint32_t addr, uint32_t val)
609{
610 KBDState *s = &kbd_state;
611
612#ifdef DEBUG_KBD
613 printf("kbd: write data=0x%02x\n", val);
614#endif
615
616 switch(s->write_cmd) {
617 case 0:
618 kbd_write_keyboard(s, val);
619 break;
620 case KBD_CCMD_WRITE_MODE:
621 s->mode = val;
622 kbd_update_irq(s);
623 break;
624 case KBD_CCMD_WRITE_OBUF:
625 kbd_queue(s, val, 0);
626 break;
627 case KBD_CCMD_WRITE_AUX_OBUF:
628 kbd_queue(s, val, 1);
629 break;
630 case KBD_CCMD_WRITE_OUTPORT:
631#ifdef TARGET_I386
632 cpu_x86_set_a20(env, (val >> 1) & 1);
633#endif
634 if (!(val & 1)) {
635 reset_requested = 1;
636 cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT);
637 }
638 break;
639 case KBD_CCMD_WRITE_MOUSE:
640 kbd_write_mouse(s, val);
641 break;
642 default:
643 break;
644 }
645 s->write_cmd = 0;
646}
647
648void kbd_reset(KBDState *s)
649{
650 KBDQueue *q;
651 int i;
652
653 s->kbd_write_cmd = -1;
654 s->mouse_write_cmd = -1;
655 s->mode = KBD_MODE_KBD_INT | KBD_MODE_MOUSE_INT;
656 s->status = KBD_STAT_CMD | KBD_STAT_UNLOCKED;
657 for(i = 0; i < 2; i++) {
658 q = &s->queues[i];
659 q->rptr = 0;
660 q->wptr = 0;
661 q->count = 0;
662 }
663}
664
665void kbd_init(void)
666{
667 kbd_reset(&kbd_state);
668 register_ioport_read(0x60, 1, kbd_read_data, 1);
669 register_ioport_write(0x60, 1, kbd_write_data, 1);
670 register_ioport_read(0x64, 1, kbd_read_status, 1);
671 register_ioport_write(0x64, 1, kbd_write_command, 1);
672}
This page took 0.097784 seconds and 4 git commands to generate.