Statistics
| Branch: | Revision:

root / hw / ps2.c @ 6059631c

History | View | Annotate | Download (19.2 kB)

1 0e43e99c bellard
/*
2 0e43e99c bellard
 * QEMU PS/2 keyboard/mouse emulation
3 5fafdf24 ths
 *
4 0e43e99c bellard
 * Copyright (c) 2003 Fabrice Bellard
5 5fafdf24 ths
 *
6 0e43e99c bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 0e43e99c bellard
 * of this software and associated documentation files (the "Software"), to deal
8 0e43e99c bellard
 * in the Software without restriction, including without limitation the rights
9 0e43e99c bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 0e43e99c bellard
 * copies of the Software, and to permit persons to whom the Software is
11 0e43e99c bellard
 * furnished to do so, subject to the following conditions:
12 0e43e99c bellard
 *
13 0e43e99c bellard
 * The above copyright notice and this permission notice shall be included in
14 0e43e99c bellard
 * all copies or substantial portions of the Software.
15 0e43e99c bellard
 *
16 0e43e99c bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 0e43e99c bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 0e43e99c bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 0e43e99c bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 0e43e99c bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 0e43e99c bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 0e43e99c bellard
 * THE SOFTWARE.
23 0e43e99c bellard
 */
24 87ecb68b pbrook
#include "hw.h"
25 87ecb68b pbrook
#include "ps2.h"
26 87ecb68b pbrook
#include "console.h"
27 0e43e99c bellard
28 0e43e99c bellard
/* debug PC keyboard */
29 0e43e99c bellard
//#define DEBUG_KBD
30 0e43e99c bellard
31 0e43e99c bellard
/* debug PC keyboard : only mouse */
32 0e43e99c bellard
//#define DEBUG_MOUSE
33 0e43e99c bellard
34 0e43e99c bellard
/* Keyboard Commands */
35 0e43e99c bellard
#define KBD_CMD_SET_LEDS        0xED        /* Set keyboard leds */
36 0e43e99c bellard
#define KBD_CMD_ECHO             0xEE
37 e7d93956 aurel32
#define KBD_CMD_SCANCODE        0xF0        /* Get/set scancode set */
38 0e43e99c bellard
#define KBD_CMD_GET_ID                 0xF2        /* get keyboard ID */
39 0e43e99c bellard
#define KBD_CMD_SET_RATE        0xF3        /* Set typematic rate */
40 0e43e99c bellard
#define KBD_CMD_ENABLE                0xF4        /* Enable scanning */
41 0e43e99c bellard
#define KBD_CMD_RESET_DISABLE        0xF5        /* reset and disable scanning */
42 0e43e99c bellard
#define KBD_CMD_RESET_ENABLE           0xF6    /* reset and enable scanning */
43 0e43e99c bellard
#define KBD_CMD_RESET                0xFF        /* Reset */
44 0e43e99c bellard
45 0e43e99c bellard
/* Keyboard Replies */
46 0e43e99c bellard
#define KBD_REPLY_POR                0xAA        /* Power on reset */
47 35c4d671 aurel32
#define KBD_REPLY_ID                0xAB        /* Keyboard ID */
48 0e43e99c bellard
#define KBD_REPLY_ACK                0xFA        /* Command ACK */
49 0e43e99c bellard
#define KBD_REPLY_RESEND        0xFE        /* Command NACK, send the cmd again */
50 0e43e99c bellard
51 0e43e99c bellard
/* Mouse Commands */
52 0e43e99c bellard
#define AUX_SET_SCALE11                0xE6        /* Set 1:1 scaling */
53 0e43e99c bellard
#define AUX_SET_SCALE21                0xE7        /* Set 2:1 scaling */
54 0e43e99c bellard
#define AUX_SET_RES                0xE8        /* Set resolution */
55 0e43e99c bellard
#define AUX_GET_SCALE                0xE9        /* Get scaling factor */
56 0e43e99c bellard
#define AUX_SET_STREAM                0xEA        /* Set stream mode */
57 0e43e99c bellard
#define AUX_POLL                0xEB        /* Poll */
58 0e43e99c bellard
#define AUX_RESET_WRAP                0xEC        /* Reset wrap mode */
59 0e43e99c bellard
#define AUX_SET_WRAP                0xEE        /* Set wrap mode */
60 0e43e99c bellard
#define AUX_SET_REMOTE                0xF0        /* Set remote mode */
61 0e43e99c bellard
#define AUX_GET_TYPE                0xF2        /* Get type */
62 0e43e99c bellard
#define AUX_SET_SAMPLE                0xF3        /* Set sample rate */
63 0e43e99c bellard
#define AUX_ENABLE_DEV                0xF4        /* Enable aux device */
64 0e43e99c bellard
#define AUX_DISABLE_DEV                0xF5        /* Disable aux device */
65 0e43e99c bellard
#define AUX_SET_DEFAULT                0xF6
66 0e43e99c bellard
#define AUX_RESET                0xFF        /* Reset aux device */
67 0e43e99c bellard
#define AUX_ACK                        0xFA        /* Command byte ACK. */
68 0e43e99c bellard
69 0e43e99c bellard
#define MOUSE_STATUS_REMOTE     0x40
70 0e43e99c bellard
#define MOUSE_STATUS_ENABLED    0x20
71 0e43e99c bellard
#define MOUSE_STATUS_SCALE21    0x10
72 0e43e99c bellard
73 0e43e99c bellard
#define PS2_QUEUE_SIZE 256
74 0e43e99c bellard
75 0e43e99c bellard
typedef struct {
76 0e43e99c bellard
    uint8_t data[PS2_QUEUE_SIZE];
77 0e43e99c bellard
    int rptr, wptr, count;
78 0e43e99c bellard
} PS2Queue;
79 0e43e99c bellard
80 0e43e99c bellard
typedef struct {
81 0e43e99c bellard
    PS2Queue queue;
82 0e43e99c bellard
    int32_t write_cmd;
83 0e43e99c bellard
    void (*update_irq)(void *, int);
84 0e43e99c bellard
    void *update_arg;
85 0e43e99c bellard
} PS2State;
86 0e43e99c bellard
87 0e43e99c bellard
typedef struct {
88 0e43e99c bellard
    PS2State common;
89 0e43e99c bellard
    int scan_enabled;
90 f94f5d71 pbrook
    /* Qemu uses translated PC scancodes internally.  To avoid multiple
91 f94f5d71 pbrook
       conversions we do the translation (if any) in the PS/2 emulation
92 f94f5d71 pbrook
       not the keyboard controller.  */
93 f94f5d71 pbrook
    int translate;
94 e7d93956 aurel32
    int scancode_set; /* 1=XT, 2=AT, 3=PS/2 */
95 0e43e99c bellard
} PS2KbdState;
96 0e43e99c bellard
97 0e43e99c bellard
typedef struct {
98 0e43e99c bellard
    PS2State common;
99 0e43e99c bellard
    uint8_t mouse_status;
100 0e43e99c bellard
    uint8_t mouse_resolution;
101 0e43e99c bellard
    uint8_t mouse_sample_rate;
102 0e43e99c bellard
    uint8_t mouse_wrap;
103 0e43e99c bellard
    uint8_t mouse_type; /* 0 = PS2, 3 = IMPS/2, 4 = IMEX */
104 0e43e99c bellard
    uint8_t mouse_detect_state;
105 0e43e99c bellard
    int mouse_dx; /* current values, needed for 'poll' mode */
106 0e43e99c bellard
    int mouse_dy;
107 0e43e99c bellard
    int mouse_dz;
108 0e43e99c bellard
    uint8_t mouse_buttons;
109 0e43e99c bellard
} PS2MouseState;
110 0e43e99c bellard
111 f94f5d71 pbrook
/* Table to convert from PC scancodes to raw scancodes.  */
112 f94f5d71 pbrook
static const unsigned char ps2_raw_keycode[128] = {
113 7096a96d Roy Tam
  0, 118,  22,  30,  38,  37,  46,  54,  61,  62,  70,  69,  78,  85, 102,  13,
114 7096a96d Roy Tam
 21,  29,  36,  45,  44,  53,  60,  67,  68,  77,  84,  91,  90,  20,  28,  27,
115 7096a96d Roy Tam
 35,  43,  52,  51,  59,  66,  75,  76,  82,  14,  18,  93,  26,  34,  33,  42,
116 7096a96d Roy Tam
 50,  49,  58,  65,  73,  74,  89, 124,  17,  41,  88,   5,   6,   4,  12,   3,
117 7096a96d Roy Tam
 11,   2,  10,   1,   9, 119, 126, 108, 117, 125, 123, 107, 115, 116, 121, 105,
118 7096a96d Roy Tam
114, 122, 112, 113, 127,  96,  97, 120,   7,  15,  23,  31,  39,  47,  55,  63,
119 7096a96d Roy Tam
 71,  79,  86,  94,   8,  16,  24,  32,  40,  48,  56,  64,  72,  80,  87, 111,
120 7096a96d Roy Tam
 19,  25,  57,  81,  83,  92,  95,  98,  99, 100, 101, 103, 104, 106, 109, 110
121 7096a96d Roy Tam
};
122 7096a96d Roy Tam
static const unsigned char ps2_raw_keycode_set3[128] = {
123 7096a96d Roy Tam
  0,   8,  22,  30,  38,  37,  46,  54,  61,  62,  70,  69,  78,  85, 102,  13,
124 7096a96d Roy Tam
 21,  29,  36,  45,  44,  53,  60,  67,  68,  77,  84,  91,  90,  17,  28,  27,
125 7096a96d Roy Tam
 35,  43,  52,  51,  59,  66,  75,  76,  82,  14,  18,  92,  26,  34,  33,  42,
126 7096a96d Roy Tam
 50,  49,  58,  65,  73,  74,  89, 126,  25,  41,  20,   7,  15,  23,  31,  39,
127 7096a96d Roy Tam
 47,   2,  63,  71,  79, 118,  95, 108, 117, 125, 132, 107, 115, 116, 124, 105,
128 7096a96d Roy Tam
114, 122, 112, 113, 127,  96,  97,  86,  94,  15,  23,  31,  39,  47,  55,  63,
129 7096a96d Roy Tam
 71,  79,  86,  94,   8,  16,  24,  32,  40,  48,  56,  64,  72,  80,  87, 111,
130 7096a96d Roy Tam
 19,  25,  57,  81,  83,  92,  95,  98,  99, 100, 101, 103, 104, 106, 109, 110
131 f94f5d71 pbrook
};
132 f94f5d71 pbrook
133 0e43e99c bellard
void ps2_queue(void *opaque, int b)
134 0e43e99c bellard
{
135 0e43e99c bellard
    PS2State *s = (PS2State *)opaque;
136 0e43e99c bellard
    PS2Queue *q = &s->queue;
137 0e43e99c bellard
138 0e43e99c bellard
    if (q->count >= PS2_QUEUE_SIZE)
139 0e43e99c bellard
        return;
140 0e43e99c bellard
    q->data[q->wptr] = b;
141 0e43e99c bellard
    if (++q->wptr == PS2_QUEUE_SIZE)
142 0e43e99c bellard
        q->wptr = 0;
143 0e43e99c bellard
    q->count++;
144 0e43e99c bellard
    s->update_irq(s->update_arg, 1);
145 0e43e99c bellard
}
146 0e43e99c bellard
147 35c4d671 aurel32
/*
148 35c4d671 aurel32
   keycode is expressed as follow:
149 35c4d671 aurel32
   bit 7    - 0 key pressed, 1 = key released
150 35c4d671 aurel32
   bits 6-0 - translated scancode set 2
151 35c4d671 aurel32
 */
152 0e43e99c bellard
static void ps2_put_keycode(void *opaque, int keycode)
153 0e43e99c bellard
{
154 f94f5d71 pbrook
    PS2KbdState *s = opaque;
155 e7d93956 aurel32
156 7096a96d Roy Tam
    /* XXX: add support for scancode set 1 */
157 7096a96d Roy Tam
    if (!s->translate && keycode < 0xe0 && s->scancode_set > 1) {
158 7096a96d Roy Tam
        if (keycode & 0x80) {
159 f94f5d71 pbrook
            ps2_queue(&s->common, 0xf0);
160 7096a96d Roy Tam
        }
161 7096a96d Roy Tam
        if (s->scancode_set == 2) {
162 7096a96d Roy Tam
            keycode = ps2_raw_keycode[keycode & 0x7f];
163 7096a96d Roy Tam
        } else if (s->scancode_set == 3) {
164 7096a96d Roy Tam
            keycode = ps2_raw_keycode_set3[keycode & 0x7f];
165 7096a96d Roy Tam
        }
166 f94f5d71 pbrook
      }
167 0e43e99c bellard
    ps2_queue(&s->common, keycode);
168 0e43e99c bellard
}
169 0e43e99c bellard
170 0e43e99c bellard
uint32_t ps2_read_data(void *opaque)
171 0e43e99c bellard
{
172 0e43e99c bellard
    PS2State *s = (PS2State *)opaque;
173 0e43e99c bellard
    PS2Queue *q;
174 0e43e99c bellard
    int val, index;
175 3b46e624 ths
176 0e43e99c bellard
    q = &s->queue;
177 0e43e99c bellard
    if (q->count == 0) {
178 0e43e99c bellard
        /* NOTE: if no data left, we return the last keyboard one
179 0e43e99c bellard
           (needed for EMM386) */
180 0e43e99c bellard
        /* XXX: need a timer to do things correctly */
181 0e43e99c bellard
        index = q->rptr - 1;
182 0e43e99c bellard
        if (index < 0)
183 0e43e99c bellard
            index = PS2_QUEUE_SIZE - 1;
184 0e43e99c bellard
        val = q->data[index];
185 0e43e99c bellard
    } else {
186 0e43e99c bellard
        val = q->data[q->rptr];
187 0e43e99c bellard
        if (++q->rptr == PS2_QUEUE_SIZE)
188 0e43e99c bellard
            q->rptr = 0;
189 0e43e99c bellard
        q->count--;
190 0e43e99c bellard
        /* reading deasserts IRQ */
191 0e43e99c bellard
        s->update_irq(s->update_arg, 0);
192 0e43e99c bellard
        /* reassert IRQs if data left */
193 0e43e99c bellard
        s->update_irq(s->update_arg, q->count != 0);
194 0e43e99c bellard
    }
195 0e43e99c bellard
    return val;
196 0e43e99c bellard
}
197 0e43e99c bellard
198 0e43e99c bellard
static void ps2_reset_keyboard(PS2KbdState *s)
199 0e43e99c bellard
{
200 0e43e99c bellard
    s->scan_enabled = 1;
201 e7d93956 aurel32
    s->scancode_set = 2;
202 6937b376 Gerd Hoffmann
    kbd_put_ledstate(0);
203 0e43e99c bellard
}
204 0e43e99c bellard
205 0e43e99c bellard
void ps2_write_keyboard(void *opaque, int val)
206 0e43e99c bellard
{
207 0e43e99c bellard
    PS2KbdState *s = (PS2KbdState *)opaque;
208 0e43e99c bellard
209 0e43e99c bellard
    switch(s->common.write_cmd) {
210 0e43e99c bellard
    default:
211 0e43e99c bellard
    case -1:
212 0e43e99c bellard
        switch(val) {
213 0e43e99c bellard
        case 0x00:
214 0e43e99c bellard
            ps2_queue(&s->common, KBD_REPLY_ACK);
215 0e43e99c bellard
            break;
216 0e43e99c bellard
        case 0x05:
217 0e43e99c bellard
            ps2_queue(&s->common, KBD_REPLY_RESEND);
218 0e43e99c bellard
            break;
219 0e43e99c bellard
        case KBD_CMD_GET_ID:
220 0e43e99c bellard
            ps2_queue(&s->common, KBD_REPLY_ACK);
221 e7d93956 aurel32
            /* We emulate a MF2 AT keyboard here */
222 35c4d671 aurel32
            ps2_queue(&s->common, KBD_REPLY_ID);
223 35c4d671 aurel32
            if (s->translate)
224 35c4d671 aurel32
                ps2_queue(&s->common, 0x41);
225 35c4d671 aurel32
            else
226 35c4d671 aurel32
                ps2_queue(&s->common, 0x83);
227 0e43e99c bellard
            break;
228 0e43e99c bellard
        case KBD_CMD_ECHO:
229 0e43e99c bellard
            ps2_queue(&s->common, KBD_CMD_ECHO);
230 0e43e99c bellard
            break;
231 0e43e99c bellard
        case KBD_CMD_ENABLE:
232 0e43e99c bellard
            s->scan_enabled = 1;
233 0e43e99c bellard
            ps2_queue(&s->common, KBD_REPLY_ACK);
234 0e43e99c bellard
            break;
235 e7d93956 aurel32
        case KBD_CMD_SCANCODE:
236 0e43e99c bellard
        case KBD_CMD_SET_LEDS:
237 0e43e99c bellard
        case KBD_CMD_SET_RATE:
238 0e43e99c bellard
            s->common.write_cmd = val;
239 0e43e99c bellard
            ps2_queue(&s->common, KBD_REPLY_ACK);
240 0e43e99c bellard
            break;
241 0e43e99c bellard
        case KBD_CMD_RESET_DISABLE:
242 0e43e99c bellard
            ps2_reset_keyboard(s);
243 0e43e99c bellard
            s->scan_enabled = 0;
244 0e43e99c bellard
            ps2_queue(&s->common, KBD_REPLY_ACK);
245 0e43e99c bellard
            break;
246 0e43e99c bellard
        case KBD_CMD_RESET_ENABLE:
247 0e43e99c bellard
            ps2_reset_keyboard(s);
248 0e43e99c bellard
            s->scan_enabled = 1;
249 0e43e99c bellard
            ps2_queue(&s->common, KBD_REPLY_ACK);
250 0e43e99c bellard
            break;
251 0e43e99c bellard
        case KBD_CMD_RESET:
252 0e43e99c bellard
            ps2_reset_keyboard(s);
253 0e43e99c bellard
            ps2_queue(&s->common, KBD_REPLY_ACK);
254 0e43e99c bellard
            ps2_queue(&s->common, KBD_REPLY_POR);
255 0e43e99c bellard
            break;
256 0e43e99c bellard
        default:
257 0e43e99c bellard
            ps2_queue(&s->common, KBD_REPLY_ACK);
258 0e43e99c bellard
            break;
259 0e43e99c bellard
        }
260 0e43e99c bellard
        break;
261 e7d93956 aurel32
    case KBD_CMD_SCANCODE:
262 e7d93956 aurel32
        if (val == 0) {
263 e7d93956 aurel32
            if (s->scancode_set == 1)
264 e7d93956 aurel32
                ps2_put_keycode(s, 0x43);
265 e7d93956 aurel32
            else if (s->scancode_set == 2)
266 e7d93956 aurel32
                ps2_put_keycode(s, 0x41);
267 e7d93956 aurel32
            else if (s->scancode_set == 3)
268 e7d93956 aurel32
                ps2_put_keycode(s, 0x3f);
269 e7d93956 aurel32
        } else {
270 e7d93956 aurel32
            if (val >= 1 && val <= 3)
271 e7d93956 aurel32
                s->scancode_set = val;
272 e7d93956 aurel32
            ps2_queue(&s->common, KBD_REPLY_ACK);
273 e7d93956 aurel32
        }
274 e7d93956 aurel32
        s->common.write_cmd = -1;
275 e7d93956 aurel32
        break;
276 0e43e99c bellard
    case KBD_CMD_SET_LEDS:
277 6937b376 Gerd Hoffmann
        kbd_put_ledstate(val);
278 0e43e99c bellard
        ps2_queue(&s->common, KBD_REPLY_ACK);
279 0e43e99c bellard
        s->common.write_cmd = -1;
280 0e43e99c bellard
        break;
281 0e43e99c bellard
    case KBD_CMD_SET_RATE:
282 0e43e99c bellard
        ps2_queue(&s->common, KBD_REPLY_ACK);
283 0e43e99c bellard
        s->common.write_cmd = -1;
284 0e43e99c bellard
        break;
285 0e43e99c bellard
    }
286 0e43e99c bellard
}
287 0e43e99c bellard
288 f94f5d71 pbrook
/* Set the scancode translation mode.
289 f94f5d71 pbrook
   0 = raw scancodes.
290 f94f5d71 pbrook
   1 = translated scancodes (used by qemu internally).  */
291 f94f5d71 pbrook
292 f94f5d71 pbrook
void ps2_keyboard_set_translation(void *opaque, int mode)
293 f94f5d71 pbrook
{
294 f94f5d71 pbrook
    PS2KbdState *s = (PS2KbdState *)opaque;
295 f94f5d71 pbrook
    s->translate = mode;
296 f94f5d71 pbrook
}
297 f94f5d71 pbrook
298 0e43e99c bellard
static void ps2_mouse_send_packet(PS2MouseState *s)
299 0e43e99c bellard
{
300 0e43e99c bellard
    unsigned int b;
301 0e43e99c bellard
    int dx1, dy1, dz1;
302 0e43e99c bellard
303 0e43e99c bellard
    dx1 = s->mouse_dx;
304 0e43e99c bellard
    dy1 = s->mouse_dy;
305 0e43e99c bellard
    dz1 = s->mouse_dz;
306 0e43e99c bellard
    /* XXX: increase range to 8 bits ? */
307 0e43e99c bellard
    if (dx1 > 127)
308 0e43e99c bellard
        dx1 = 127;
309 0e43e99c bellard
    else if (dx1 < -127)
310 0e43e99c bellard
        dx1 = -127;
311 0e43e99c bellard
    if (dy1 > 127)
312 0e43e99c bellard
        dy1 = 127;
313 0e43e99c bellard
    else if (dy1 < -127)
314 0e43e99c bellard
        dy1 = -127;
315 0e43e99c bellard
    b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07);
316 0e43e99c bellard
    ps2_queue(&s->common, b);
317 0e43e99c bellard
    ps2_queue(&s->common, dx1 & 0xff);
318 0e43e99c bellard
    ps2_queue(&s->common, dy1 & 0xff);
319 0e43e99c bellard
    /* extra byte for IMPS/2 or IMEX */
320 0e43e99c bellard
    switch(s->mouse_type) {
321 0e43e99c bellard
    default:
322 0e43e99c bellard
        break;
323 0e43e99c bellard
    case 3:
324 0e43e99c bellard
        if (dz1 > 127)
325 0e43e99c bellard
            dz1 = 127;
326 0e43e99c bellard
        else if (dz1 < -127)
327 0e43e99c bellard
                dz1 = -127;
328 0e43e99c bellard
        ps2_queue(&s->common, dz1 & 0xff);
329 0e43e99c bellard
        break;
330 0e43e99c bellard
    case 4:
331 0e43e99c bellard
        if (dz1 > 7)
332 0e43e99c bellard
            dz1 = 7;
333 0e43e99c bellard
        else if (dz1 < -7)
334 0e43e99c bellard
            dz1 = -7;
335 0e43e99c bellard
        b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
336 0e43e99c bellard
        ps2_queue(&s->common, b);
337 0e43e99c bellard
        break;
338 0e43e99c bellard
    }
339 0e43e99c bellard
340 0e43e99c bellard
    /* update deltas */
341 0e43e99c bellard
    s->mouse_dx -= dx1;
342 0e43e99c bellard
    s->mouse_dy -= dy1;
343 0e43e99c bellard
    s->mouse_dz -= dz1;
344 0e43e99c bellard
}
345 0e43e99c bellard
346 5fafdf24 ths
static void ps2_mouse_event(void *opaque,
347 0e43e99c bellard
                            int dx, int dy, int dz, int buttons_state)
348 0e43e99c bellard
{
349 0e43e99c bellard
    PS2MouseState *s = opaque;
350 0e43e99c bellard
351 0e43e99c bellard
    /* check if deltas are recorded when disabled */
352 0e43e99c bellard
    if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
353 0e43e99c bellard
        return;
354 0e43e99c bellard
355 0e43e99c bellard
    s->mouse_dx += dx;
356 0e43e99c bellard
    s->mouse_dy -= dy;
357 0e43e99c bellard
    s->mouse_dz += dz;
358 0e43e99c bellard
    /* XXX: SDL sometimes generates nul events: we delete them */
359 0e43e99c bellard
    if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0 &&
360 0e43e99c bellard
        s->mouse_buttons == buttons_state)
361 0e43e99c bellard
        return;
362 0e43e99c bellard
    s->mouse_buttons = buttons_state;
363 3b46e624 ths
364 0e43e99c bellard
    if (!(s->mouse_status & MOUSE_STATUS_REMOTE) &&
365 0e43e99c bellard
        (s->common.queue.count < (PS2_QUEUE_SIZE - 16))) {
366 0e43e99c bellard
        for(;;) {
367 0e43e99c bellard
            /* if not remote, send event. Multiple events are sent if
368 0e43e99c bellard
               too big deltas */
369 0e43e99c bellard
            ps2_mouse_send_packet(s);
370 0e43e99c bellard
            if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)
371 0e43e99c bellard
                break;
372 0e43e99c bellard
        }
373 0e43e99c bellard
    }
374 0e43e99c bellard
}
375 0e43e99c bellard
376 548df2ac ths
void ps2_mouse_fake_event(void *opaque)
377 548df2ac ths
{
378 548df2ac ths
    ps2_mouse_event(opaque, 1, 0, 0, 0);
379 548df2ac ths
}
380 548df2ac ths
381 0e43e99c bellard
void ps2_write_mouse(void *opaque, int val)
382 0e43e99c bellard
{
383 0e43e99c bellard
    PS2MouseState *s = (PS2MouseState *)opaque;
384 0e43e99c bellard
#ifdef DEBUG_MOUSE
385 0e43e99c bellard
    printf("kbd: write mouse 0x%02x\n", val);
386 0e43e99c bellard
#endif
387 0e43e99c bellard
    switch(s->common.write_cmd) {
388 0e43e99c bellard
    default:
389 0e43e99c bellard
    case -1:
390 0e43e99c bellard
        /* mouse command */
391 0e43e99c bellard
        if (s->mouse_wrap) {
392 0e43e99c bellard
            if (val == AUX_RESET_WRAP) {
393 0e43e99c bellard
                s->mouse_wrap = 0;
394 0e43e99c bellard
                ps2_queue(&s->common, AUX_ACK);
395 0e43e99c bellard
                return;
396 0e43e99c bellard
            } else if (val != AUX_RESET) {
397 0e43e99c bellard
                ps2_queue(&s->common, val);
398 0e43e99c bellard
                return;
399 0e43e99c bellard
            }
400 0e43e99c bellard
        }
401 0e43e99c bellard
        switch(val) {
402 0e43e99c bellard
        case AUX_SET_SCALE11:
403 0e43e99c bellard
            s->mouse_status &= ~MOUSE_STATUS_SCALE21;
404 0e43e99c bellard
            ps2_queue(&s->common, AUX_ACK);
405 0e43e99c bellard
            break;
406 0e43e99c bellard
        case AUX_SET_SCALE21:
407 0e43e99c bellard
            s->mouse_status |= MOUSE_STATUS_SCALE21;
408 0e43e99c bellard
            ps2_queue(&s->common, AUX_ACK);
409 0e43e99c bellard
            break;
410 0e43e99c bellard
        case AUX_SET_STREAM:
411 0e43e99c bellard
            s->mouse_status &= ~MOUSE_STATUS_REMOTE;
412 0e43e99c bellard
            ps2_queue(&s->common, AUX_ACK);
413 0e43e99c bellard
            break;
414 0e43e99c bellard
        case AUX_SET_WRAP:
415 0e43e99c bellard
            s->mouse_wrap = 1;
416 0e43e99c bellard
            ps2_queue(&s->common, AUX_ACK);
417 0e43e99c bellard
            break;
418 0e43e99c bellard
        case AUX_SET_REMOTE:
419 0e43e99c bellard
            s->mouse_status |= MOUSE_STATUS_REMOTE;
420 0e43e99c bellard
            ps2_queue(&s->common, AUX_ACK);
421 0e43e99c bellard
            break;
422 0e43e99c bellard
        case AUX_GET_TYPE:
423 0e43e99c bellard
            ps2_queue(&s->common, AUX_ACK);
424 0e43e99c bellard
            ps2_queue(&s->common, s->mouse_type);
425 0e43e99c bellard
            break;
426 0e43e99c bellard
        case AUX_SET_RES:
427 0e43e99c bellard
        case AUX_SET_SAMPLE:
428 0e43e99c bellard
            s->common.write_cmd = val;
429 0e43e99c bellard
            ps2_queue(&s->common, AUX_ACK);
430 0e43e99c bellard
            break;
431 0e43e99c bellard
        case AUX_GET_SCALE:
432 0e43e99c bellard
            ps2_queue(&s->common, AUX_ACK);
433 0e43e99c bellard
            ps2_queue(&s->common, s->mouse_status);
434 0e43e99c bellard
            ps2_queue(&s->common, s->mouse_resolution);
435 0e43e99c bellard
            ps2_queue(&s->common, s->mouse_sample_rate);
436 0e43e99c bellard
            break;
437 0e43e99c bellard
        case AUX_POLL:
438 0e43e99c bellard
            ps2_queue(&s->common, AUX_ACK);
439 0e43e99c bellard
            ps2_mouse_send_packet(s);
440 0e43e99c bellard
            break;
441 0e43e99c bellard
        case AUX_ENABLE_DEV:
442 0e43e99c bellard
            s->mouse_status |= MOUSE_STATUS_ENABLED;
443 0e43e99c bellard
            ps2_queue(&s->common, AUX_ACK);
444 0e43e99c bellard
            break;
445 0e43e99c bellard
        case AUX_DISABLE_DEV:
446 0e43e99c bellard
            s->mouse_status &= ~MOUSE_STATUS_ENABLED;
447 0e43e99c bellard
            ps2_queue(&s->common, AUX_ACK);
448 0e43e99c bellard
            break;
449 0e43e99c bellard
        case AUX_SET_DEFAULT:
450 0e43e99c bellard
            s->mouse_sample_rate = 100;
451 0e43e99c bellard
            s->mouse_resolution = 2;
452 0e43e99c bellard
            s->mouse_status = 0;
453 0e43e99c bellard
            ps2_queue(&s->common, AUX_ACK);
454 0e43e99c bellard
            break;
455 0e43e99c bellard
        case AUX_RESET:
456 0e43e99c bellard
            s->mouse_sample_rate = 100;
457 0e43e99c bellard
            s->mouse_resolution = 2;
458 0e43e99c bellard
            s->mouse_status = 0;
459 0e43e99c bellard
            s->mouse_type = 0;
460 0e43e99c bellard
            ps2_queue(&s->common, AUX_ACK);
461 0e43e99c bellard
            ps2_queue(&s->common, 0xaa);
462 0e43e99c bellard
            ps2_queue(&s->common, s->mouse_type);
463 0e43e99c bellard
            break;
464 0e43e99c bellard
        default:
465 0e43e99c bellard
            break;
466 0e43e99c bellard
        }
467 0e43e99c bellard
        break;
468 0e43e99c bellard
    case AUX_SET_SAMPLE:
469 0e43e99c bellard
        s->mouse_sample_rate = val;
470 0e43e99c bellard
        /* detect IMPS/2 or IMEX */
471 0e43e99c bellard
        switch(s->mouse_detect_state) {
472 0e43e99c bellard
        default:
473 0e43e99c bellard
        case 0:
474 0e43e99c bellard
            if (val == 200)
475 0e43e99c bellard
                s->mouse_detect_state = 1;
476 0e43e99c bellard
            break;
477 0e43e99c bellard
        case 1:
478 0e43e99c bellard
            if (val == 100)
479 0e43e99c bellard
                s->mouse_detect_state = 2;
480 0e43e99c bellard
            else if (val == 200)
481 0e43e99c bellard
                s->mouse_detect_state = 3;
482 0e43e99c bellard
            else
483 0e43e99c bellard
                s->mouse_detect_state = 0;
484 0e43e99c bellard
            break;
485 0e43e99c bellard
        case 2:
486 5fafdf24 ths
            if (val == 80)
487 0e43e99c bellard
                s->mouse_type = 3; /* IMPS/2 */
488 0e43e99c bellard
            s->mouse_detect_state = 0;
489 0e43e99c bellard
            break;
490 0e43e99c bellard
        case 3:
491 5fafdf24 ths
            if (val == 80)
492 0e43e99c bellard
                s->mouse_type = 4; /* IMEX */
493 0e43e99c bellard
            s->mouse_detect_state = 0;
494 0e43e99c bellard
            break;
495 0e43e99c bellard
        }
496 0e43e99c bellard
        ps2_queue(&s->common, AUX_ACK);
497 0e43e99c bellard
        s->common.write_cmd = -1;
498 0e43e99c bellard
        break;
499 0e43e99c bellard
    case AUX_SET_RES:
500 0e43e99c bellard
        s->mouse_resolution = val;
501 0e43e99c bellard
        ps2_queue(&s->common, AUX_ACK);
502 0e43e99c bellard
        s->common.write_cmd = -1;
503 0e43e99c bellard
        break;
504 0e43e99c bellard
    }
505 0e43e99c bellard
}
506 0e43e99c bellard
507 ef74679a Dinesh Subhraveti
static void ps2_common_reset(PS2State *s)
508 0e43e99c bellard
{
509 0e43e99c bellard
    PS2Queue *q;
510 0e43e99c bellard
    s->write_cmd = -1;
511 0e43e99c bellard
    q = &s->queue;
512 0e43e99c bellard
    q->rptr = 0;
513 0e43e99c bellard
    q->wptr = 0;
514 0e43e99c bellard
    q->count = 0;
515 deeccef3 aliguori
    s->update_irq(s->update_arg, 0);
516 0e43e99c bellard
}
517 0e43e99c bellard
518 ef74679a Dinesh Subhraveti
static void ps2_kbd_reset(void *opaque)
519 ef74679a Dinesh Subhraveti
{
520 ef74679a Dinesh Subhraveti
    PS2KbdState *s = (PS2KbdState *) opaque;
521 ef74679a Dinesh Subhraveti
522 ef74679a Dinesh Subhraveti
    ps2_common_reset(&s->common);
523 ef74679a Dinesh Subhraveti
    s->scan_enabled = 0;
524 ef74679a Dinesh Subhraveti
    s->translate = 0;
525 ef74679a Dinesh Subhraveti
    s->scancode_set = 0;
526 ef74679a Dinesh Subhraveti
}
527 ef74679a Dinesh Subhraveti
528 ef74679a Dinesh Subhraveti
static void ps2_mouse_reset(void *opaque)
529 ef74679a Dinesh Subhraveti
{
530 ef74679a Dinesh Subhraveti
    PS2MouseState *s = (PS2MouseState *) opaque;
531 ef74679a Dinesh Subhraveti
532 ef74679a Dinesh Subhraveti
    ps2_common_reset(&s->common);
533 ef74679a Dinesh Subhraveti
    s->mouse_status = 0;
534 ef74679a Dinesh Subhraveti
    s->mouse_resolution = 0;
535 ef74679a Dinesh Subhraveti
    s->mouse_sample_rate = 0;
536 ef74679a Dinesh Subhraveti
    s->mouse_wrap = 0;
537 ef74679a Dinesh Subhraveti
    s->mouse_type = 0;
538 ef74679a Dinesh Subhraveti
    s->mouse_detect_state = 0;
539 ef74679a Dinesh Subhraveti
    s->mouse_dx = 0;
540 ef74679a Dinesh Subhraveti
    s->mouse_dy = 0;
541 ef74679a Dinesh Subhraveti
    s->mouse_dz = 0;
542 ef74679a Dinesh Subhraveti
    s->mouse_buttons = 0;
543 ef74679a Dinesh Subhraveti
}
544 ef74679a Dinesh Subhraveti
545 b31442c3 Juan Quintela
static const VMStateDescription vmstate_ps2_common = {
546 b31442c3 Juan Quintela
    .name = "PS2 Common State",
547 b31442c3 Juan Quintela
    .version_id = 3,
548 b31442c3 Juan Quintela
    .minimum_version_id = 2,
549 b31442c3 Juan Quintela
    .minimum_version_id_old = 2,
550 b31442c3 Juan Quintela
    .fields      = (VMStateField []) {
551 b31442c3 Juan Quintela
        VMSTATE_INT32(write_cmd, PS2State),
552 b31442c3 Juan Quintela
        VMSTATE_INT32(queue.rptr, PS2State),
553 b31442c3 Juan Quintela
        VMSTATE_INT32(queue.wptr, PS2State),
554 b31442c3 Juan Quintela
        VMSTATE_INT32(queue.count, PS2State),
555 b31442c3 Juan Quintela
        VMSTATE_BUFFER(queue.data, PS2State),
556 b31442c3 Juan Quintela
        VMSTATE_END_OF_LIST()
557 b31442c3 Juan Quintela
    }
558 b31442c3 Juan Quintela
};
559 0e43e99c bellard
560 db596c53 Juan Quintela
static int ps2_kbd_post_load(void* opaque, int version_id)
561 0e43e99c bellard
{
562 0e43e99c bellard
    PS2KbdState *s = (PS2KbdState*)opaque;
563 7783e9f0 pbrook
564 db596c53 Juan Quintela
    if (version_id == 2)
565 e7d93956 aurel32
        s->scancode_set=2;
566 0e43e99c bellard
    return 0;
567 0e43e99c bellard
}
568 0e43e99c bellard
569 b31442c3 Juan Quintela
static const VMStateDescription vmstate_ps2_keyboard = {
570 b31442c3 Juan Quintela
    .name = "ps2kbd",
571 b31442c3 Juan Quintela
    .version_id = 3,
572 db596c53 Juan Quintela
    .minimum_version_id = 2,
573 b31442c3 Juan Quintela
    .minimum_version_id_old = 2,
574 db596c53 Juan Quintela
    .post_load = ps2_kbd_post_load,
575 b31442c3 Juan Quintela
    .fields      = (VMStateField []) {
576 b31442c3 Juan Quintela
        VMSTATE_STRUCT(common, PS2KbdState, 0, vmstate_ps2_common, PS2State),
577 b31442c3 Juan Quintela
        VMSTATE_INT32(scan_enabled, PS2KbdState),
578 b31442c3 Juan Quintela
        VMSTATE_INT32(translate, PS2KbdState),
579 b31442c3 Juan Quintela
        VMSTATE_INT32_V(scancode_set, PS2KbdState,3),
580 b31442c3 Juan Quintela
        VMSTATE_END_OF_LIST()
581 b31442c3 Juan Quintela
    }
582 b31442c3 Juan Quintela
};
583 7783e9f0 pbrook
584 b31442c3 Juan Quintela
static const VMStateDescription vmstate_ps2_mouse = {
585 b31442c3 Juan Quintela
    .name = "ps2mouse",
586 b31442c3 Juan Quintela
    .version_id = 2,
587 b31442c3 Juan Quintela
    .minimum_version_id = 2,
588 b31442c3 Juan Quintela
    .minimum_version_id_old = 2,
589 b31442c3 Juan Quintela
    .fields      = (VMStateField []) {
590 b31442c3 Juan Quintela
        VMSTATE_STRUCT(common, PS2MouseState, 0, vmstate_ps2_common, PS2State),
591 b31442c3 Juan Quintela
        VMSTATE_UINT8(mouse_status, PS2MouseState),
592 b31442c3 Juan Quintela
        VMSTATE_UINT8(mouse_resolution, PS2MouseState),
593 b31442c3 Juan Quintela
        VMSTATE_UINT8(mouse_sample_rate, PS2MouseState),
594 b31442c3 Juan Quintela
        VMSTATE_UINT8(mouse_wrap, PS2MouseState),
595 b31442c3 Juan Quintela
        VMSTATE_UINT8(mouse_type, PS2MouseState),
596 b31442c3 Juan Quintela
        VMSTATE_UINT8(mouse_detect_state, PS2MouseState),
597 b31442c3 Juan Quintela
        VMSTATE_INT32(mouse_dx, PS2MouseState),
598 b31442c3 Juan Quintela
        VMSTATE_INT32(mouse_dy, PS2MouseState),
599 b31442c3 Juan Quintela
        VMSTATE_INT32(mouse_dz, PS2MouseState),
600 b31442c3 Juan Quintela
        VMSTATE_UINT8(mouse_buttons, PS2MouseState),
601 b31442c3 Juan Quintela
        VMSTATE_END_OF_LIST()
602 b31442c3 Juan Quintela
    }
603 b31442c3 Juan Quintela
};
604 0e43e99c bellard
605 0e43e99c bellard
void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
606 0e43e99c bellard
{
607 0e43e99c bellard
    PS2KbdState *s = (PS2KbdState *)qemu_mallocz(sizeof(PS2KbdState));
608 0e43e99c bellard
609 0e43e99c bellard
    s->common.update_irq = update_irq;
610 0e43e99c bellard
    s->common.update_arg = update_arg;
611 e7d93956 aurel32
    s->scancode_set = 2;
612 0be71e32 Alex Williamson
    vmstate_register(NULL, 0, &vmstate_ps2_keyboard, s);
613 0e43e99c bellard
    qemu_add_kbd_event_handler(ps2_put_keycode, s);
614 ef74679a Dinesh Subhraveti
    qemu_register_reset(ps2_kbd_reset, s);
615 0e43e99c bellard
    return s;
616 0e43e99c bellard
}
617 0e43e99c bellard
618 0e43e99c bellard
void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
619 0e43e99c bellard
{
620 0e43e99c bellard
    PS2MouseState *s = (PS2MouseState *)qemu_mallocz(sizeof(PS2MouseState));
621 0e43e99c bellard
622 0e43e99c bellard
    s->common.update_irq = update_irq;
623 0e43e99c bellard
    s->common.update_arg = update_arg;
624 0be71e32 Alex Williamson
    vmstate_register(NULL, 0, &vmstate_ps2_mouse, s);
625 455204eb ths
    qemu_add_mouse_event_handler(ps2_mouse_event, s, 0, "QEMU PS/2 Mouse");
626 ef74679a Dinesh Subhraveti
    qemu_register_reset(ps2_mouse_reset, s);
627 0e43e99c bellard
    return s;
628 0e43e99c bellard
}