Statistics
| Branch: | Revision:

root / hw / ps2.c @ 0986ac3b

History | View | Annotate | Download (16.9 kB)

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