Statistics
| Branch: | Revision:

root / hw / ps2.c @ bee8d684

History | View | Annotate | Download (16.9 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 0e43e99c bellard
#define KBD_CMD_GET_ID                 0xF2        /* get keyboard ID */
38 0e43e99c bellard
#define KBD_CMD_SET_RATE        0xF3        /* Set typematic rate */
39 0e43e99c bellard
#define KBD_CMD_ENABLE                0xF4        /* Enable scanning */
40 0e43e99c bellard
#define KBD_CMD_RESET_DISABLE        0xF5        /* reset and disable scanning */
41 0e43e99c bellard
#define KBD_CMD_RESET_ENABLE           0xF6    /* reset and enable scanning */
42 0e43e99c bellard
#define KBD_CMD_RESET                0xFF        /* Reset */
43 0e43e99c bellard
44 0e43e99c bellard
/* Keyboard Replies */
45 0e43e99c bellard
#define KBD_REPLY_POR                0xAA        /* Power on reset */
46 0e43e99c bellard
#define KBD_REPLY_ACK                0xFA        /* Command ACK */
47 0e43e99c bellard
#define KBD_REPLY_RESEND        0xFE        /* Command NACK, send the cmd again */
48 0e43e99c bellard
49 0e43e99c bellard
/* Mouse Commands */
50 0e43e99c bellard
#define AUX_SET_SCALE11                0xE6        /* Set 1:1 scaling */
51 0e43e99c bellard
#define AUX_SET_SCALE21                0xE7        /* Set 2:1 scaling */
52 0e43e99c bellard
#define AUX_SET_RES                0xE8        /* Set resolution */
53 0e43e99c bellard
#define AUX_GET_SCALE                0xE9        /* Get scaling factor */
54 0e43e99c bellard
#define AUX_SET_STREAM                0xEA        /* Set stream mode */
55 0e43e99c bellard
#define AUX_POLL                0xEB        /* Poll */
56 0e43e99c bellard
#define AUX_RESET_WRAP                0xEC        /* Reset wrap mode */
57 0e43e99c bellard
#define AUX_SET_WRAP                0xEE        /* Set wrap mode */
58 0e43e99c bellard
#define AUX_SET_REMOTE                0xF0        /* Set remote mode */
59 0e43e99c bellard
#define AUX_GET_TYPE                0xF2        /* Get type */
60 0e43e99c bellard
#define AUX_SET_SAMPLE                0xF3        /* Set sample rate */
61 0e43e99c bellard
#define AUX_ENABLE_DEV                0xF4        /* Enable aux device */
62 0e43e99c bellard
#define AUX_DISABLE_DEV                0xF5        /* Disable aux device */
63 0e43e99c bellard
#define AUX_SET_DEFAULT                0xF6
64 0e43e99c bellard
#define AUX_RESET                0xFF        /* Reset aux device */
65 0e43e99c bellard
#define AUX_ACK                        0xFA        /* Command byte ACK. */
66 0e43e99c bellard
67 0e43e99c bellard
#define MOUSE_STATUS_REMOTE     0x40
68 0e43e99c bellard
#define MOUSE_STATUS_ENABLED    0x20
69 0e43e99c bellard
#define MOUSE_STATUS_SCALE21    0x10
70 0e43e99c bellard
71 0e43e99c bellard
#define PS2_QUEUE_SIZE 256
72 0e43e99c bellard
73 0e43e99c bellard
typedef struct {
74 0e43e99c bellard
    uint8_t data[PS2_QUEUE_SIZE];
75 0e43e99c bellard
    int rptr, wptr, count;
76 0e43e99c bellard
} PS2Queue;
77 0e43e99c bellard
78 0e43e99c bellard
typedef struct {
79 0e43e99c bellard
    PS2Queue queue;
80 0e43e99c bellard
    int32_t write_cmd;
81 0e43e99c bellard
    void (*update_irq)(void *, int);
82 0e43e99c bellard
    void *update_arg;
83 0e43e99c bellard
} PS2State;
84 0e43e99c bellard
85 0e43e99c bellard
typedef struct {
86 0e43e99c bellard
    PS2State common;
87 0e43e99c bellard
    int scan_enabled;
88 f94f5d71 pbrook
    /* Qemu uses translated PC scancodes internally.  To avoid multiple
89 f94f5d71 pbrook
       conversions we do the translation (if any) in the PS/2 emulation
90 f94f5d71 pbrook
       not the keyboard controller.  */
91 f94f5d71 pbrook
    int translate;
92 0e43e99c bellard
} PS2KbdState;
93 0e43e99c bellard
94 0e43e99c bellard
typedef struct {
95 0e43e99c bellard
    PS2State common;
96 0e43e99c bellard
    uint8_t mouse_status;
97 0e43e99c bellard
    uint8_t mouse_resolution;
98 0e43e99c bellard
    uint8_t mouse_sample_rate;
99 0e43e99c bellard
    uint8_t mouse_wrap;
100 0e43e99c bellard
    uint8_t mouse_type; /* 0 = PS2, 3 = IMPS/2, 4 = IMEX */
101 0e43e99c bellard
    uint8_t mouse_detect_state;
102 0e43e99c bellard
    int mouse_dx; /* current values, needed for 'poll' mode */
103 0e43e99c bellard
    int mouse_dy;
104 0e43e99c bellard
    int mouse_dz;
105 0e43e99c bellard
    uint8_t mouse_buttons;
106 0e43e99c bellard
} PS2MouseState;
107 0e43e99c bellard
108 f94f5d71 pbrook
/* Table to convert from PC scancodes to raw scancodes.  */
109 f94f5d71 pbrook
static const unsigned char ps2_raw_keycode[128] = {
110 f94f5d71 pbrook
          0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13,
111 f94f5d71 pbrook
         21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27,
112 f94f5d71 pbrook
         35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42,
113 f94f5d71 pbrook
         50, 49, 58, 65, 73, 74, 89,124, 17, 41, 88,  5,  6,  4, 12,  3,
114 f94f5d71 pbrook
         11,  2, 10,  1,  9,119,126,108,117,125,123,107,115,116,121,105,
115 f94f5d71 pbrook
        114,122,112,113,127, 96, 97,120,  7, 15, 23, 31, 39, 47, 55, 63,
116 f94f5d71 pbrook
         71, 79, 86, 94,  8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87,111,
117 f94f5d71 pbrook
         19, 25, 57, 81, 83, 92, 95, 98, 99,100,101,103,104,106,109,110
118 f94f5d71 pbrook
};
119 f94f5d71 pbrook
120 0e43e99c bellard
void ps2_queue(void *opaque, int b)
121 0e43e99c bellard
{
122 0e43e99c bellard
    PS2State *s = (PS2State *)opaque;
123 0e43e99c bellard
    PS2Queue *q = &s->queue;
124 0e43e99c bellard
125 0e43e99c bellard
    if (q->count >= PS2_QUEUE_SIZE)
126 0e43e99c bellard
        return;
127 0e43e99c bellard
    q->data[q->wptr] = b;
128 0e43e99c bellard
    if (++q->wptr == PS2_QUEUE_SIZE)
129 0e43e99c bellard
        q->wptr = 0;
130 0e43e99c bellard
    q->count++;
131 0e43e99c bellard
    s->update_irq(s->update_arg, 1);
132 0e43e99c bellard
}
133 0e43e99c bellard
134 0e43e99c bellard
static void ps2_put_keycode(void *opaque, int keycode)
135 0e43e99c bellard
{
136 f94f5d71 pbrook
    PS2KbdState *s = opaque;
137 f94f5d71 pbrook
    if (!s->translate && keycode < 0xe0)
138 f94f5d71 pbrook
      {
139 f94f5d71 pbrook
        if (keycode & 0x80)
140 f94f5d71 pbrook
            ps2_queue(&s->common, 0xf0);
141 f94f5d71 pbrook
        keycode = ps2_raw_keycode[keycode & 0x7f];
142 f94f5d71 pbrook
      }
143 0e43e99c bellard
    ps2_queue(&s->common, keycode);
144 0e43e99c bellard
}
145 0e43e99c bellard
146 0e43e99c bellard
uint32_t ps2_read_data(void *opaque)
147 0e43e99c bellard
{
148 0e43e99c bellard
    PS2State *s = (PS2State *)opaque;
149 0e43e99c bellard
    PS2Queue *q;
150 0e43e99c bellard
    int val, index;
151 3b46e624 ths
152 0e43e99c bellard
    q = &s->queue;
153 0e43e99c bellard
    if (q->count == 0) {
154 0e43e99c bellard
        /* NOTE: if no data left, we return the last keyboard one
155 0e43e99c bellard
           (needed for EMM386) */
156 0e43e99c bellard
        /* XXX: need a timer to do things correctly */
157 0e43e99c bellard
        index = q->rptr - 1;
158 0e43e99c bellard
        if (index < 0)
159 0e43e99c bellard
            index = PS2_QUEUE_SIZE - 1;
160 0e43e99c bellard
        val = q->data[index];
161 0e43e99c bellard
    } else {
162 0e43e99c bellard
        val = q->data[q->rptr];
163 0e43e99c bellard
        if (++q->rptr == PS2_QUEUE_SIZE)
164 0e43e99c bellard
            q->rptr = 0;
165 0e43e99c bellard
        q->count--;
166 0e43e99c bellard
        /* reading deasserts IRQ */
167 0e43e99c bellard
        s->update_irq(s->update_arg, 0);
168 0e43e99c bellard
        /* reassert IRQs if data left */
169 0e43e99c bellard
        s->update_irq(s->update_arg, q->count != 0);
170 0e43e99c bellard
    }
171 0e43e99c bellard
    return val;
172 0e43e99c bellard
}
173 0e43e99c bellard
174 0e43e99c bellard
static void ps2_reset_keyboard(PS2KbdState *s)
175 0e43e99c bellard
{
176 0e43e99c bellard
    s->scan_enabled = 1;
177 0e43e99c bellard
}
178 0e43e99c bellard
179 0e43e99c bellard
void ps2_write_keyboard(void *opaque, int val)
180 0e43e99c bellard
{
181 0e43e99c bellard
    PS2KbdState *s = (PS2KbdState *)opaque;
182 0e43e99c bellard
183 0e43e99c bellard
    switch(s->common.write_cmd) {
184 0e43e99c bellard
    default:
185 0e43e99c bellard
    case -1:
186 0e43e99c bellard
        switch(val) {
187 0e43e99c bellard
        case 0x00:
188 0e43e99c bellard
            ps2_queue(&s->common, KBD_REPLY_ACK);
189 0e43e99c bellard
            break;
190 0e43e99c bellard
        case 0x05:
191 0e43e99c bellard
            ps2_queue(&s->common, KBD_REPLY_RESEND);
192 0e43e99c bellard
            break;
193 0e43e99c bellard
        case KBD_CMD_GET_ID:
194 0e43e99c bellard
            ps2_queue(&s->common, KBD_REPLY_ACK);
195 0e43e99c bellard
            ps2_queue(&s->common, 0xab);
196 0e43e99c bellard
            ps2_queue(&s->common, 0x83);
197 0e43e99c bellard
            break;
198 0e43e99c bellard
        case KBD_CMD_ECHO:
199 0e43e99c bellard
            ps2_queue(&s->common, KBD_CMD_ECHO);
200 0e43e99c bellard
            break;
201 0e43e99c bellard
        case KBD_CMD_ENABLE:
202 0e43e99c bellard
            s->scan_enabled = 1;
203 0e43e99c bellard
            ps2_queue(&s->common, KBD_REPLY_ACK);
204 0e43e99c bellard
            break;
205 0e43e99c bellard
        case KBD_CMD_SET_LEDS:
206 0e43e99c bellard
        case KBD_CMD_SET_RATE:
207 0e43e99c bellard
            s->common.write_cmd = val;
208 0e43e99c bellard
            ps2_queue(&s->common, KBD_REPLY_ACK);
209 0e43e99c bellard
            break;
210 0e43e99c bellard
        case KBD_CMD_RESET_DISABLE:
211 0e43e99c bellard
            ps2_reset_keyboard(s);
212 0e43e99c bellard
            s->scan_enabled = 0;
213 0e43e99c bellard
            ps2_queue(&s->common, KBD_REPLY_ACK);
214 0e43e99c bellard
            break;
215 0e43e99c bellard
        case KBD_CMD_RESET_ENABLE:
216 0e43e99c bellard
            ps2_reset_keyboard(s);
217 0e43e99c bellard
            s->scan_enabled = 1;
218 0e43e99c bellard
            ps2_queue(&s->common, KBD_REPLY_ACK);
219 0e43e99c bellard
            break;
220 0e43e99c bellard
        case KBD_CMD_RESET:
221 0e43e99c bellard
            ps2_reset_keyboard(s);
222 0e43e99c bellard
            ps2_queue(&s->common, KBD_REPLY_ACK);
223 0e43e99c bellard
            ps2_queue(&s->common, KBD_REPLY_POR);
224 0e43e99c bellard
            break;
225 0e43e99c bellard
        default:
226 0e43e99c bellard
            ps2_queue(&s->common, KBD_REPLY_ACK);
227 0e43e99c bellard
            break;
228 0e43e99c bellard
        }
229 0e43e99c bellard
        break;
230 0e43e99c bellard
    case KBD_CMD_SET_LEDS:
231 0e43e99c bellard
        ps2_queue(&s->common, KBD_REPLY_ACK);
232 0e43e99c bellard
        s->common.write_cmd = -1;
233 0e43e99c bellard
        break;
234 0e43e99c bellard
    case KBD_CMD_SET_RATE:
235 0e43e99c bellard
        ps2_queue(&s->common, KBD_REPLY_ACK);
236 0e43e99c bellard
        s->common.write_cmd = -1;
237 0e43e99c bellard
        break;
238 0e43e99c bellard
    }
239 0e43e99c bellard
}
240 0e43e99c bellard
241 f94f5d71 pbrook
/* Set the scancode translation mode.
242 f94f5d71 pbrook
   0 = raw scancodes.
243 f94f5d71 pbrook
   1 = translated scancodes (used by qemu internally).  */
244 f94f5d71 pbrook
245 f94f5d71 pbrook
void ps2_keyboard_set_translation(void *opaque, int mode)
246 f94f5d71 pbrook
{
247 f94f5d71 pbrook
    PS2KbdState *s = (PS2KbdState *)opaque;
248 f94f5d71 pbrook
    s->translate = mode;
249 f94f5d71 pbrook
}
250 f94f5d71 pbrook
251 0e43e99c bellard
static void ps2_mouse_send_packet(PS2MouseState *s)
252 0e43e99c bellard
{
253 0e43e99c bellard
    unsigned int b;
254 0e43e99c bellard
    int dx1, dy1, dz1;
255 0e43e99c bellard
256 0e43e99c bellard
    dx1 = s->mouse_dx;
257 0e43e99c bellard
    dy1 = s->mouse_dy;
258 0e43e99c bellard
    dz1 = s->mouse_dz;
259 0e43e99c bellard
    /* XXX: increase range to 8 bits ? */
260 0e43e99c bellard
    if (dx1 > 127)
261 0e43e99c bellard
        dx1 = 127;
262 0e43e99c bellard
    else if (dx1 < -127)
263 0e43e99c bellard
        dx1 = -127;
264 0e43e99c bellard
    if (dy1 > 127)
265 0e43e99c bellard
        dy1 = 127;
266 0e43e99c bellard
    else if (dy1 < -127)
267 0e43e99c bellard
        dy1 = -127;
268 0e43e99c bellard
    b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07);
269 0e43e99c bellard
    ps2_queue(&s->common, b);
270 0e43e99c bellard
    ps2_queue(&s->common, dx1 & 0xff);
271 0e43e99c bellard
    ps2_queue(&s->common, dy1 & 0xff);
272 0e43e99c bellard
    /* extra byte for IMPS/2 or IMEX */
273 0e43e99c bellard
    switch(s->mouse_type) {
274 0e43e99c bellard
    default:
275 0e43e99c bellard
        break;
276 0e43e99c bellard
    case 3:
277 0e43e99c bellard
        if (dz1 > 127)
278 0e43e99c bellard
            dz1 = 127;
279 0e43e99c bellard
        else if (dz1 < -127)
280 0e43e99c bellard
                dz1 = -127;
281 0e43e99c bellard
        ps2_queue(&s->common, dz1 & 0xff);
282 0e43e99c bellard
        break;
283 0e43e99c bellard
    case 4:
284 0e43e99c bellard
        if (dz1 > 7)
285 0e43e99c bellard
            dz1 = 7;
286 0e43e99c bellard
        else if (dz1 < -7)
287 0e43e99c bellard
            dz1 = -7;
288 0e43e99c bellard
        b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
289 0e43e99c bellard
        ps2_queue(&s->common, b);
290 0e43e99c bellard
        break;
291 0e43e99c bellard
    }
292 0e43e99c bellard
293 0e43e99c bellard
    /* update deltas */
294 0e43e99c bellard
    s->mouse_dx -= dx1;
295 0e43e99c bellard
    s->mouse_dy -= dy1;
296 0e43e99c bellard
    s->mouse_dz -= dz1;
297 0e43e99c bellard
}
298 0e43e99c bellard
299 5fafdf24 ths
static void ps2_mouse_event(void *opaque,
300 0e43e99c bellard
                            int dx, int dy, int dz, int buttons_state)
301 0e43e99c bellard
{
302 0e43e99c bellard
    PS2MouseState *s = opaque;
303 0e43e99c bellard
304 0e43e99c bellard
    /* check if deltas are recorded when disabled */
305 0e43e99c bellard
    if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
306 0e43e99c bellard
        return;
307 0e43e99c bellard
308 0e43e99c bellard
    s->mouse_dx += dx;
309 0e43e99c bellard
    s->mouse_dy -= dy;
310 0e43e99c bellard
    s->mouse_dz += dz;
311 0e43e99c bellard
    /* XXX: SDL sometimes generates nul events: we delete them */
312 0e43e99c bellard
    if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0 &&
313 0e43e99c bellard
        s->mouse_buttons == buttons_state)
314 0e43e99c bellard
        return;
315 0e43e99c bellard
    s->mouse_buttons = buttons_state;
316 3b46e624 ths
317 0e43e99c bellard
    if (!(s->mouse_status & MOUSE_STATUS_REMOTE) &&
318 0e43e99c bellard
        (s->common.queue.count < (PS2_QUEUE_SIZE - 16))) {
319 0e43e99c bellard
        for(;;) {
320 0e43e99c bellard
            /* if not remote, send event. Multiple events are sent if
321 0e43e99c bellard
               too big deltas */
322 0e43e99c bellard
            ps2_mouse_send_packet(s);
323 0e43e99c bellard
            if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)
324 0e43e99c bellard
                break;
325 0e43e99c bellard
        }
326 0e43e99c bellard
    }
327 0e43e99c bellard
}
328 0e43e99c bellard
329 548df2ac ths
void ps2_mouse_fake_event(void *opaque)
330 548df2ac ths
{
331 548df2ac ths
    ps2_mouse_event(opaque, 1, 0, 0, 0);
332 548df2ac ths
}
333 548df2ac ths
334 0e43e99c bellard
void ps2_write_mouse(void *opaque, int val)
335 0e43e99c bellard
{
336 0e43e99c bellard
    PS2MouseState *s = (PS2MouseState *)opaque;
337 0e43e99c bellard
#ifdef DEBUG_MOUSE
338 0e43e99c bellard
    printf("kbd: write mouse 0x%02x\n", val);
339 0e43e99c bellard
#endif
340 0e43e99c bellard
    switch(s->common.write_cmd) {
341 0e43e99c bellard
    default:
342 0e43e99c bellard
    case -1:
343 0e43e99c bellard
        /* mouse command */
344 0e43e99c bellard
        if (s->mouse_wrap) {
345 0e43e99c bellard
            if (val == AUX_RESET_WRAP) {
346 0e43e99c bellard
                s->mouse_wrap = 0;
347 0e43e99c bellard
                ps2_queue(&s->common, AUX_ACK);
348 0e43e99c bellard
                return;
349 0e43e99c bellard
            } else if (val != AUX_RESET) {
350 0e43e99c bellard
                ps2_queue(&s->common, val);
351 0e43e99c bellard
                return;
352 0e43e99c bellard
            }
353 0e43e99c bellard
        }
354 0e43e99c bellard
        switch(val) {
355 0e43e99c bellard
        case AUX_SET_SCALE11:
356 0e43e99c bellard
            s->mouse_status &= ~MOUSE_STATUS_SCALE21;
357 0e43e99c bellard
            ps2_queue(&s->common, AUX_ACK);
358 0e43e99c bellard
            break;
359 0e43e99c bellard
        case AUX_SET_SCALE21:
360 0e43e99c bellard
            s->mouse_status |= MOUSE_STATUS_SCALE21;
361 0e43e99c bellard
            ps2_queue(&s->common, AUX_ACK);
362 0e43e99c bellard
            break;
363 0e43e99c bellard
        case AUX_SET_STREAM:
364 0e43e99c bellard
            s->mouse_status &= ~MOUSE_STATUS_REMOTE;
365 0e43e99c bellard
            ps2_queue(&s->common, AUX_ACK);
366 0e43e99c bellard
            break;
367 0e43e99c bellard
        case AUX_SET_WRAP:
368 0e43e99c bellard
            s->mouse_wrap = 1;
369 0e43e99c bellard
            ps2_queue(&s->common, AUX_ACK);
370 0e43e99c bellard
            break;
371 0e43e99c bellard
        case AUX_SET_REMOTE:
372 0e43e99c bellard
            s->mouse_status |= MOUSE_STATUS_REMOTE;
373 0e43e99c bellard
            ps2_queue(&s->common, AUX_ACK);
374 0e43e99c bellard
            break;
375 0e43e99c bellard
        case AUX_GET_TYPE:
376 0e43e99c bellard
            ps2_queue(&s->common, AUX_ACK);
377 0e43e99c bellard
            ps2_queue(&s->common, s->mouse_type);
378 0e43e99c bellard
            break;
379 0e43e99c bellard
        case AUX_SET_RES:
380 0e43e99c bellard
        case AUX_SET_SAMPLE:
381 0e43e99c bellard
            s->common.write_cmd = val;
382 0e43e99c bellard
            ps2_queue(&s->common, AUX_ACK);
383 0e43e99c bellard
            break;
384 0e43e99c bellard
        case AUX_GET_SCALE:
385 0e43e99c bellard
            ps2_queue(&s->common, AUX_ACK);
386 0e43e99c bellard
            ps2_queue(&s->common, s->mouse_status);
387 0e43e99c bellard
            ps2_queue(&s->common, s->mouse_resolution);
388 0e43e99c bellard
            ps2_queue(&s->common, s->mouse_sample_rate);
389 0e43e99c bellard
            break;
390 0e43e99c bellard
        case AUX_POLL:
391 0e43e99c bellard
            ps2_queue(&s->common, AUX_ACK);
392 0e43e99c bellard
            ps2_mouse_send_packet(s);
393 0e43e99c bellard
            break;
394 0e43e99c bellard
        case AUX_ENABLE_DEV:
395 0e43e99c bellard
            s->mouse_status |= MOUSE_STATUS_ENABLED;
396 0e43e99c bellard
            ps2_queue(&s->common, AUX_ACK);
397 0e43e99c bellard
            break;
398 0e43e99c bellard
        case AUX_DISABLE_DEV:
399 0e43e99c bellard
            s->mouse_status &= ~MOUSE_STATUS_ENABLED;
400 0e43e99c bellard
            ps2_queue(&s->common, AUX_ACK);
401 0e43e99c bellard
            break;
402 0e43e99c bellard
        case AUX_SET_DEFAULT:
403 0e43e99c bellard
            s->mouse_sample_rate = 100;
404 0e43e99c bellard
            s->mouse_resolution = 2;
405 0e43e99c bellard
            s->mouse_status = 0;
406 0e43e99c bellard
            ps2_queue(&s->common, AUX_ACK);
407 0e43e99c bellard
            break;
408 0e43e99c bellard
        case AUX_RESET:
409 0e43e99c bellard
            s->mouse_sample_rate = 100;
410 0e43e99c bellard
            s->mouse_resolution = 2;
411 0e43e99c bellard
            s->mouse_status = 0;
412 0e43e99c bellard
            s->mouse_type = 0;
413 0e43e99c bellard
            ps2_queue(&s->common, AUX_ACK);
414 0e43e99c bellard
            ps2_queue(&s->common, 0xaa);
415 0e43e99c bellard
            ps2_queue(&s->common, s->mouse_type);
416 0e43e99c bellard
            break;
417 0e43e99c bellard
        default:
418 0e43e99c bellard
            break;
419 0e43e99c bellard
        }
420 0e43e99c bellard
        break;
421 0e43e99c bellard
    case AUX_SET_SAMPLE:
422 0e43e99c bellard
        s->mouse_sample_rate = val;
423 0e43e99c bellard
        /* detect IMPS/2 or IMEX */
424 0e43e99c bellard
        switch(s->mouse_detect_state) {
425 0e43e99c bellard
        default:
426 0e43e99c bellard
        case 0:
427 0e43e99c bellard
            if (val == 200)
428 0e43e99c bellard
                s->mouse_detect_state = 1;
429 0e43e99c bellard
            break;
430 0e43e99c bellard
        case 1:
431 0e43e99c bellard
            if (val == 100)
432 0e43e99c bellard
                s->mouse_detect_state = 2;
433 0e43e99c bellard
            else if (val == 200)
434 0e43e99c bellard
                s->mouse_detect_state = 3;
435 0e43e99c bellard
            else
436 0e43e99c bellard
                s->mouse_detect_state = 0;
437 0e43e99c bellard
            break;
438 0e43e99c bellard
        case 2:
439 5fafdf24 ths
            if (val == 80)
440 0e43e99c bellard
                s->mouse_type = 3; /* IMPS/2 */
441 0e43e99c bellard
            s->mouse_detect_state = 0;
442 0e43e99c bellard
            break;
443 0e43e99c bellard
        case 3:
444 5fafdf24 ths
            if (val == 80)
445 0e43e99c bellard
                s->mouse_type = 4; /* IMEX */
446 0e43e99c bellard
            s->mouse_detect_state = 0;
447 0e43e99c bellard
            break;
448 0e43e99c bellard
        }
449 0e43e99c bellard
        ps2_queue(&s->common, AUX_ACK);
450 0e43e99c bellard
        s->common.write_cmd = -1;
451 0e43e99c bellard
        break;
452 0e43e99c bellard
    case AUX_SET_RES:
453 0e43e99c bellard
        s->mouse_resolution = val;
454 0e43e99c bellard
        ps2_queue(&s->common, AUX_ACK);
455 0e43e99c bellard
        s->common.write_cmd = -1;
456 0e43e99c bellard
        break;
457 0e43e99c bellard
    }
458 0e43e99c bellard
}
459 0e43e99c bellard
460 0e43e99c bellard
static void ps2_reset(void *opaque)
461 0e43e99c bellard
{
462 0e43e99c bellard
    PS2State *s = (PS2State *)opaque;
463 0e43e99c bellard
    PS2Queue *q;
464 0e43e99c bellard
    s->write_cmd = -1;
465 0e43e99c bellard
    q = &s->queue;
466 0e43e99c bellard
    q->rptr = 0;
467 0e43e99c bellard
    q->wptr = 0;
468 0e43e99c bellard
    q->count = 0;
469 0e43e99c bellard
}
470 0e43e99c bellard
471 7783e9f0 pbrook
static void ps2_common_save (QEMUFile *f, PS2State *s)
472 7783e9f0 pbrook
{
473 bee8d684 ths
    qemu_put_be32 (f, s->write_cmd);
474 bee8d684 ths
    qemu_put_be32 (f, s->queue.rptr);
475 bee8d684 ths
    qemu_put_be32 (f, s->queue.wptr);
476 bee8d684 ths
    qemu_put_be32 (f, s->queue.count);
477 7783e9f0 pbrook
    qemu_put_buffer (f, s->queue.data, sizeof (s->queue.data));
478 7783e9f0 pbrook
}
479 7783e9f0 pbrook
480 7783e9f0 pbrook
static void ps2_common_load (QEMUFile *f, PS2State *s)
481 7783e9f0 pbrook
{
482 bee8d684 ths
    s->write_cmd=qemu_get_be32 (f);
483 bee8d684 ths
    s->queue.rptr=qemu_get_be32 (f);
484 bee8d684 ths
    s->queue.wptr=qemu_get_be32 (f);
485 bee8d684 ths
    s->queue.count=qemu_get_be32 (f);
486 7783e9f0 pbrook
    qemu_get_buffer (f, s->queue.data, sizeof (s->queue.data));
487 7783e9f0 pbrook
}
488 7783e9f0 pbrook
489 0e43e99c bellard
static void ps2_kbd_save(QEMUFile* f, void* opaque)
490 0e43e99c bellard
{
491 0e43e99c bellard
    PS2KbdState *s = (PS2KbdState*)opaque;
492 7783e9f0 pbrook
493 7783e9f0 pbrook
    ps2_common_save (f, &s->common);
494 bee8d684 ths
    qemu_put_be32(f, s->scan_enabled);
495 bee8d684 ths
    qemu_put_be32(f, s->translate);
496 0e43e99c bellard
}
497 0e43e99c bellard
498 0e43e99c bellard
static void ps2_mouse_save(QEMUFile* f, void* opaque)
499 0e43e99c bellard
{
500 0e43e99c bellard
    PS2MouseState *s = (PS2MouseState*)opaque;
501 7783e9f0 pbrook
502 7783e9f0 pbrook
    ps2_common_save (f, &s->common);
503 0e43e99c bellard
    qemu_put_8s(f, &s->mouse_status);
504 0e43e99c bellard
    qemu_put_8s(f, &s->mouse_resolution);
505 0e43e99c bellard
    qemu_put_8s(f, &s->mouse_sample_rate);
506 0e43e99c bellard
    qemu_put_8s(f, &s->mouse_wrap);
507 0e43e99c bellard
    qemu_put_8s(f, &s->mouse_type);
508 0e43e99c bellard
    qemu_put_8s(f, &s->mouse_detect_state);
509 bee8d684 ths
    qemu_put_be32(f, s->mouse_dx);
510 bee8d684 ths
    qemu_put_be32(f, s->mouse_dy);
511 bee8d684 ths
    qemu_put_be32(f, s->mouse_dz);
512 0e43e99c bellard
    qemu_put_8s(f, &s->mouse_buttons);
513 0e43e99c bellard
}
514 0e43e99c bellard
515 0e43e99c bellard
static int ps2_kbd_load(QEMUFile* f, void* opaque, int version_id)
516 0e43e99c bellard
{
517 0e43e99c bellard
    PS2KbdState *s = (PS2KbdState*)opaque;
518 7783e9f0 pbrook
519 7783e9f0 pbrook
    if (version_id != 2)
520 0e43e99c bellard
        return -EINVAL;
521 7783e9f0 pbrook
522 7783e9f0 pbrook
    ps2_common_load (f, &s->common);
523 bee8d684 ths
    s->scan_enabled=qemu_get_be32(f);
524 bee8d684 ths
    s->translate=qemu_get_be32(f);
525 0e43e99c bellard
    return 0;
526 0e43e99c bellard
}
527 0e43e99c bellard
528 0e43e99c bellard
static int ps2_mouse_load(QEMUFile* f, void* opaque, int version_id)
529 0e43e99c bellard
{
530 0e43e99c bellard
    PS2MouseState *s = (PS2MouseState*)opaque;
531 7783e9f0 pbrook
532 7783e9f0 pbrook
    if (version_id != 2)
533 0e43e99c bellard
        return -EINVAL;
534 7783e9f0 pbrook
535 7783e9f0 pbrook
    ps2_common_load (f, &s->common);
536 0e43e99c bellard
    qemu_get_8s(f, &s->mouse_status);
537 0e43e99c bellard
    qemu_get_8s(f, &s->mouse_resolution);
538 0e43e99c bellard
    qemu_get_8s(f, &s->mouse_sample_rate);
539 0e43e99c bellard
    qemu_get_8s(f, &s->mouse_wrap);
540 0e43e99c bellard
    qemu_get_8s(f, &s->mouse_type);
541 0e43e99c bellard
    qemu_get_8s(f, &s->mouse_detect_state);
542 bee8d684 ths
    s->mouse_dx=qemu_get_be32(f);
543 bee8d684 ths
    s->mouse_dy=qemu_get_be32(f);
544 bee8d684 ths
    s->mouse_dz=qemu_get_be32(f);
545 0e43e99c bellard
    qemu_get_8s(f, &s->mouse_buttons);
546 0e43e99c bellard
    return 0;
547 0e43e99c bellard
}
548 0e43e99c bellard
549 0e43e99c bellard
void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
550 0e43e99c bellard
{
551 0e43e99c bellard
    PS2KbdState *s = (PS2KbdState *)qemu_mallocz(sizeof(PS2KbdState));
552 0e43e99c bellard
553 0e43e99c bellard
    s->common.update_irq = update_irq;
554 0e43e99c bellard
    s->common.update_arg = update_arg;
555 0e43e99c bellard
    ps2_reset(&s->common);
556 7783e9f0 pbrook
    register_savevm("ps2kbd", 0, 2, ps2_kbd_save, ps2_kbd_load, s);
557 0e43e99c bellard
    qemu_add_kbd_event_handler(ps2_put_keycode, s);
558 0e43e99c bellard
    qemu_register_reset(ps2_reset, &s->common);
559 0e43e99c bellard
    return s;
560 0e43e99c bellard
}
561 0e43e99c bellard
562 0e43e99c bellard
void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
563 0e43e99c bellard
{
564 0e43e99c bellard
    PS2MouseState *s = (PS2MouseState *)qemu_mallocz(sizeof(PS2MouseState));
565 0e43e99c bellard
566 0e43e99c bellard
    s->common.update_irq = update_irq;
567 0e43e99c bellard
    s->common.update_arg = update_arg;
568 0e43e99c bellard
    ps2_reset(&s->common);
569 7783e9f0 pbrook
    register_savevm("ps2mouse", 0, 2, ps2_mouse_save, ps2_mouse_load, s);
570 455204eb ths
    qemu_add_mouse_event_handler(ps2_mouse_event, s, 0, "QEMU PS/2 Mouse");
571 0e43e99c bellard
    qemu_register_reset(ps2_reset, &s->common);
572 0e43e99c bellard
    return s;
573 0e43e99c bellard
}