Statistics
| Branch: | Revision:

root / hw / ps2.c @ 78895427

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