Statistics
| Branch: | Revision:

root / hw / slavio_serial.c @ a062e36c

History | View | Annotate | Download (19.6 kB)

1 e80cfcfc bellard
/*
2 e80cfcfc bellard
 * QEMU Sparc SLAVIO serial port emulation
3 5fafdf24 ths
 *
4 8be1f5c8 bellard
 * Copyright (c) 2003-2005 Fabrice Bellard
5 5fafdf24 ths
 *
6 e80cfcfc bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 e80cfcfc bellard
 * of this software and associated documentation files (the "Software"), to deal
8 e80cfcfc bellard
 * in the Software without restriction, including without limitation the rights
9 e80cfcfc bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 e80cfcfc bellard
 * copies of the Software, and to permit persons to whom the Software is
11 e80cfcfc bellard
 * furnished to do so, subject to the following conditions:
12 e80cfcfc bellard
 *
13 e80cfcfc bellard
 * The above copyright notice and this permission notice shall be included in
14 e80cfcfc bellard
 * all copies or substantial portions of the Software.
15 e80cfcfc bellard
 *
16 e80cfcfc bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 e80cfcfc bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 e80cfcfc bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 e80cfcfc bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 e80cfcfc bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 e80cfcfc bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 e80cfcfc bellard
 * THE SOFTWARE.
23 e80cfcfc bellard
 */
24 e80cfcfc bellard
#include "vl.h"
25 8be1f5c8 bellard
/* debug serial */
26 e80cfcfc bellard
//#define DEBUG_SERIAL
27 e80cfcfc bellard
28 e80cfcfc bellard
/* debug keyboard */
29 e80cfcfc bellard
//#define DEBUG_KBD
30 e80cfcfc bellard
31 8be1f5c8 bellard
/* debug mouse */
32 e80cfcfc bellard
//#define DEBUG_MOUSE
33 e80cfcfc bellard
34 e80cfcfc bellard
/*
35 e80cfcfc bellard
 * This is the serial port, mouse and keyboard part of chip STP2001
36 e80cfcfc bellard
 * (Slave I/O), also produced as NCR89C105. See
37 e80cfcfc bellard
 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
38 5fafdf24 ths
 *
39 e80cfcfc bellard
 * The serial ports implement full AMD AM8530 or Zilog Z8530 chips,
40 e80cfcfc bellard
 * mouse and keyboard ports don't implement all functions and they are
41 e80cfcfc bellard
 * only asynchronous. There is no DMA.
42 e80cfcfc bellard
 *
43 e80cfcfc bellard
 */
44 e80cfcfc bellard
45 715748fa bellard
/*
46 715748fa bellard
 * Modifications:
47 715748fa bellard
 *  2006-Aug-10  Igor Kovalenko :   Renamed KBDQueue to SERIOQueue, implemented
48 715748fa bellard
 *                                  serial mouse queue.
49 715748fa bellard
 *                                  Implemented serial mouse protocol.
50 715748fa bellard
 */
51 715748fa bellard
52 8be1f5c8 bellard
#ifdef DEBUG_SERIAL
53 8be1f5c8 bellard
#define SER_DPRINTF(fmt, args...) \
54 8be1f5c8 bellard
do { printf("SER: " fmt , ##args); } while (0)
55 8be1f5c8 bellard
#else
56 8be1f5c8 bellard
#define SER_DPRINTF(fmt, args...)
57 8be1f5c8 bellard
#endif
58 8be1f5c8 bellard
#ifdef DEBUG_KBD
59 8be1f5c8 bellard
#define KBD_DPRINTF(fmt, args...) \
60 8be1f5c8 bellard
do { printf("KBD: " fmt , ##args); } while (0)
61 8be1f5c8 bellard
#else
62 8be1f5c8 bellard
#define KBD_DPRINTF(fmt, args...)
63 8be1f5c8 bellard
#endif
64 8be1f5c8 bellard
#ifdef DEBUG_MOUSE
65 8be1f5c8 bellard
#define MS_DPRINTF(fmt, args...) \
66 715748fa bellard
do { printf("MSC: " fmt , ##args); } while (0)
67 8be1f5c8 bellard
#else
68 8be1f5c8 bellard
#define MS_DPRINTF(fmt, args...)
69 8be1f5c8 bellard
#endif
70 8be1f5c8 bellard
71 8be1f5c8 bellard
typedef enum {
72 8be1f5c8 bellard
    chn_a, chn_b,
73 8be1f5c8 bellard
} chn_id_t;
74 8be1f5c8 bellard
75 35db099d bellard
#define CHN_C(s) ((s)->chn == chn_b? 'b' : 'a')
76 35db099d bellard
77 8be1f5c8 bellard
typedef enum {
78 8be1f5c8 bellard
    ser, kbd, mouse,
79 8be1f5c8 bellard
} chn_type_t;
80 8be1f5c8 bellard
81 715748fa bellard
#define SERIO_QUEUE_SIZE 256
82 8be1f5c8 bellard
83 8be1f5c8 bellard
typedef struct {
84 715748fa bellard
    uint8_t data[SERIO_QUEUE_SIZE];
85 8be1f5c8 bellard
    int rptr, wptr, count;
86 715748fa bellard
} SERIOQueue;
87 8be1f5c8 bellard
88 e80cfcfc bellard
typedef struct ChannelState {
89 d537cf6c pbrook
    qemu_irq irq;
90 e80cfcfc bellard
    int reg;
91 e4a89056 bellard
    int rxint, txint, rxint_under_svc, txint_under_svc;
92 8be1f5c8 bellard
    chn_id_t chn; // this channel, A (base+4) or B (base+0)
93 8be1f5c8 bellard
    chn_type_t type;
94 8be1f5c8 bellard
    struct ChannelState *otherchn;
95 e80cfcfc bellard
    uint8_t rx, tx, wregs[16], rregs[16];
96 715748fa bellard
    SERIOQueue queue;
97 e80cfcfc bellard
    CharDriverState *chr;
98 bbbb2f0a blueswir1
    int e0_mode, led_mode, caps_lock_mode, num_lock_mode;
99 e80cfcfc bellard
} ChannelState;
100 e80cfcfc bellard
101 e80cfcfc bellard
struct SerialState {
102 e80cfcfc bellard
    struct ChannelState chn[2];
103 e80cfcfc bellard
};
104 e80cfcfc bellard
105 e80cfcfc bellard
#define SERIAL_MAXADDR 7
106 5aca8c3b blueswir1
#define SERIAL_SIZE (SERIAL_MAXADDR + 1)
107 e80cfcfc bellard
108 8be1f5c8 bellard
static void handle_kbd_command(ChannelState *s, int val);
109 8be1f5c8 bellard
static int serial_can_receive(void *opaque);
110 8be1f5c8 bellard
static void serial_receive_byte(ChannelState *s, int ch);
111 e4a89056 bellard
static inline void set_txint(ChannelState *s);
112 8be1f5c8 bellard
113 67deb562 blueswir1
static void clear_queue(void *opaque)
114 67deb562 blueswir1
{
115 67deb562 blueswir1
    ChannelState *s = opaque;
116 67deb562 blueswir1
    SERIOQueue *q = &s->queue;
117 67deb562 blueswir1
    q->rptr = q->wptr = q->count = 0;
118 67deb562 blueswir1
}
119 67deb562 blueswir1
120 8be1f5c8 bellard
static void put_queue(void *opaque, int b)
121 8be1f5c8 bellard
{
122 8be1f5c8 bellard
    ChannelState *s = opaque;
123 715748fa bellard
    SERIOQueue *q = &s->queue;
124 8be1f5c8 bellard
125 35db099d bellard
    SER_DPRINTF("channel %c put: 0x%02x\n", CHN_C(s), b);
126 715748fa bellard
    if (q->count >= SERIO_QUEUE_SIZE)
127 8be1f5c8 bellard
        return;
128 8be1f5c8 bellard
    q->data[q->wptr] = b;
129 715748fa bellard
    if (++q->wptr == SERIO_QUEUE_SIZE)
130 8be1f5c8 bellard
        q->wptr = 0;
131 8be1f5c8 bellard
    q->count++;
132 8be1f5c8 bellard
    serial_receive_byte(s, 0);
133 8be1f5c8 bellard
}
134 8be1f5c8 bellard
135 8be1f5c8 bellard
static uint32_t get_queue(void *opaque)
136 8be1f5c8 bellard
{
137 8be1f5c8 bellard
    ChannelState *s = opaque;
138 715748fa bellard
    SERIOQueue *q = &s->queue;
139 8be1f5c8 bellard
    int val;
140 3b46e624 ths
141 8be1f5c8 bellard
    if (q->count == 0) {
142 8be1f5c8 bellard
        return 0;
143 8be1f5c8 bellard
    } else {
144 8be1f5c8 bellard
        val = q->data[q->rptr];
145 715748fa bellard
        if (++q->rptr == SERIO_QUEUE_SIZE)
146 8be1f5c8 bellard
            q->rptr = 0;
147 8be1f5c8 bellard
        q->count--;
148 8be1f5c8 bellard
    }
149 67deb562 blueswir1
    SER_DPRINTF("channel %c get 0x%02x\n", CHN_C(s), val);
150 8be1f5c8 bellard
    if (q->count > 0)
151 8be1f5c8 bellard
        serial_receive_byte(s, 0);
152 8be1f5c8 bellard
    return val;
153 8be1f5c8 bellard
}
154 8be1f5c8 bellard
155 e4a89056 bellard
static int slavio_serial_update_irq_chn(ChannelState *s)
156 e80cfcfc bellard
{
157 e80cfcfc bellard
    if ((s->wregs[1] & 1) && // interrupts enabled
158 e80cfcfc bellard
        (((s->wregs[1] & 2) && s->txint == 1) || // tx ints enabled, pending
159 e80cfcfc bellard
         ((((s->wregs[1] & 0x18) == 8) || ((s->wregs[1] & 0x18) == 0x10)) &&
160 e80cfcfc bellard
          s->rxint == 1) || // rx ints enabled, pending
161 e80cfcfc bellard
         ((s->wregs[15] & 0x80) && (s->rregs[0] & 0x80)))) { // break int e&p
162 e4a89056 bellard
        return 1;
163 e80cfcfc bellard
    }
164 e4a89056 bellard
    return 0;
165 e4a89056 bellard
}
166 e4a89056 bellard
167 e4a89056 bellard
static void slavio_serial_update_irq(ChannelState *s)
168 e4a89056 bellard
{
169 e4a89056 bellard
    int irq;
170 e4a89056 bellard
171 e4a89056 bellard
    irq = slavio_serial_update_irq_chn(s);
172 e4a89056 bellard
    irq |= slavio_serial_update_irq_chn(s->otherchn);
173 e4a89056 bellard
174 d537cf6c pbrook
    SER_DPRINTF("IRQ = %d\n", irq);
175 d537cf6c pbrook
    qemu_set_irq(s->irq, irq);
176 e80cfcfc bellard
}
177 e80cfcfc bellard
178 e80cfcfc bellard
static void slavio_serial_reset_chn(ChannelState *s)
179 e80cfcfc bellard
{
180 e80cfcfc bellard
    int i;
181 e80cfcfc bellard
182 e80cfcfc bellard
    s->reg = 0;
183 5aca8c3b blueswir1
    for (i = 0; i < SERIAL_SIZE; i++) {
184 e80cfcfc bellard
        s->rregs[i] = 0;
185 e80cfcfc bellard
        s->wregs[i] = 0;
186 e80cfcfc bellard
    }
187 e80cfcfc bellard
    s->wregs[4] = 4;
188 e80cfcfc bellard
    s->wregs[9] = 0xc0;
189 e80cfcfc bellard
    s->wregs[11] = 8;
190 e80cfcfc bellard
    s->wregs[14] = 0x30;
191 e80cfcfc bellard
    s->wregs[15] = 0xf8;
192 e80cfcfc bellard
    s->rregs[0] = 0x44;
193 e80cfcfc bellard
    s->rregs[1] = 6;
194 e80cfcfc bellard
195 e80cfcfc bellard
    s->rx = s->tx = 0;
196 e80cfcfc bellard
    s->rxint = s->txint = 0;
197 e4a89056 bellard
    s->rxint_under_svc = s->txint_under_svc = 0;
198 bbbb2f0a blueswir1
    s->e0_mode = s->led_mode = s->caps_lock_mode = s->num_lock_mode = 0;
199 67deb562 blueswir1
    clear_queue(s);
200 e80cfcfc bellard
}
201 e80cfcfc bellard
202 e80cfcfc bellard
static void slavio_serial_reset(void *opaque)
203 e80cfcfc bellard
{
204 e80cfcfc bellard
    SerialState *s = opaque;
205 e80cfcfc bellard
    slavio_serial_reset_chn(&s->chn[0]);
206 e80cfcfc bellard
    slavio_serial_reset_chn(&s->chn[1]);
207 e80cfcfc bellard
}
208 e80cfcfc bellard
209 ba3c64fb bellard
static inline void clr_rxint(ChannelState *s)
210 ba3c64fb bellard
{
211 ba3c64fb bellard
    s->rxint = 0;
212 e4a89056 bellard
    s->rxint_under_svc = 0;
213 67deb562 blueswir1
    if (s->chn == chn_a) {
214 67deb562 blueswir1
        if (s->wregs[9] & 0x10)
215 67deb562 blueswir1
            s->otherchn->rregs[2] = 0x60;
216 67deb562 blueswir1
        else
217 67deb562 blueswir1
            s->otherchn->rregs[2] = 0x06;
218 ba3c64fb bellard
        s->rregs[3] &= ~0x20;
219 67deb562 blueswir1
    } else {
220 67deb562 blueswir1
        if (s->wregs[9] & 0x10)
221 67deb562 blueswir1
            s->rregs[2] = 0x60;
222 67deb562 blueswir1
        else
223 67deb562 blueswir1
            s->rregs[2] = 0x06;
224 ba3c64fb bellard
        s->otherchn->rregs[3] &= ~4;
225 67deb562 blueswir1
    }
226 e4a89056 bellard
    if (s->txint)
227 e4a89056 bellard
        set_txint(s);
228 ba3c64fb bellard
    slavio_serial_update_irq(s);
229 ba3c64fb bellard
}
230 ba3c64fb bellard
231 ba3c64fb bellard
static inline void set_rxint(ChannelState *s)
232 ba3c64fb bellard
{
233 ba3c64fb bellard
    s->rxint = 1;
234 e4a89056 bellard
    if (!s->txint_under_svc) {
235 e4a89056 bellard
        s->rxint_under_svc = 1;
236 67deb562 blueswir1
        if (s->chn == chn_a) {
237 67deb562 blueswir1
            if (s->wregs[9] & 0x10)
238 67deb562 blueswir1
                s->otherchn->rregs[2] = 0x30;
239 67deb562 blueswir1
            else
240 67deb562 blueswir1
                s->otherchn->rregs[2] = 0x0c;
241 67deb562 blueswir1
        } else {
242 67deb562 blueswir1
            if (s->wregs[9] & 0x10)
243 67deb562 blueswir1
                s->rregs[2] = 0x20;
244 67deb562 blueswir1
            else
245 67deb562 blueswir1
                s->rregs[2] = 0x04;
246 67deb562 blueswir1
        }
247 ba3c64fb bellard
    }
248 b9652ca3 blueswir1
    if (s->chn == chn_a)
249 b9652ca3 blueswir1
        s->rregs[3] |= 0x20;
250 b9652ca3 blueswir1
    else
251 b9652ca3 blueswir1
        s->otherchn->rregs[3] |= 4;
252 b9652ca3 blueswir1
    slavio_serial_update_irq(s);
253 ba3c64fb bellard
}
254 ba3c64fb bellard
255 ba3c64fb bellard
static inline void clr_txint(ChannelState *s)
256 ba3c64fb bellard
{
257 ba3c64fb bellard
    s->txint = 0;
258 e4a89056 bellard
    s->txint_under_svc = 0;
259 b9652ca3 blueswir1
    if (s->chn == chn_a) {
260 b9652ca3 blueswir1
        if (s->wregs[9] & 0x10)
261 b9652ca3 blueswir1
            s->otherchn->rregs[2] = 0x60;
262 b9652ca3 blueswir1
        else
263 b9652ca3 blueswir1
            s->otherchn->rregs[2] = 0x06;
264 ba3c64fb bellard
        s->rregs[3] &= ~0x10;
265 b9652ca3 blueswir1
    } else {
266 b9652ca3 blueswir1
        if (s->wregs[9] & 0x10)
267 b9652ca3 blueswir1
            s->rregs[2] = 0x60;
268 b9652ca3 blueswir1
        else
269 b9652ca3 blueswir1
            s->rregs[2] = 0x06;
270 ba3c64fb bellard
        s->otherchn->rregs[3] &= ~2;
271 b9652ca3 blueswir1
    }
272 e4a89056 bellard
    if (s->rxint)
273 e4a89056 bellard
        set_rxint(s);
274 ba3c64fb bellard
    slavio_serial_update_irq(s);
275 ba3c64fb bellard
}
276 ba3c64fb bellard
277 ba3c64fb bellard
static inline void set_txint(ChannelState *s)
278 ba3c64fb bellard
{
279 ba3c64fb bellard
    s->txint = 1;
280 e4a89056 bellard
    if (!s->rxint_under_svc) {
281 e4a89056 bellard
        s->txint_under_svc = 1;
282 b9652ca3 blueswir1
        if (s->chn == chn_a) {
283 b9652ca3 blueswir1
            if (s->wregs[9] & 0x10)
284 b9652ca3 blueswir1
                s->otherchn->rregs[2] = 0x10;
285 b9652ca3 blueswir1
            else
286 b9652ca3 blueswir1
                s->otherchn->rregs[2] = 0x08;
287 b9652ca3 blueswir1
        } else {
288 b9652ca3 blueswir1
            s->rregs[2] = 0;
289 b9652ca3 blueswir1
        }
290 ba3c64fb bellard
    }
291 b9652ca3 blueswir1
    if (s->chn == chn_a)
292 b9652ca3 blueswir1
        s->rregs[3] |= 0x10;
293 b9652ca3 blueswir1
    else
294 b9652ca3 blueswir1
        s->otherchn->rregs[3] |= 2;
295 b9652ca3 blueswir1
    slavio_serial_update_irq(s);
296 ba3c64fb bellard
}
297 ba3c64fb bellard
298 35db099d bellard
static void slavio_serial_update_parameters(ChannelState *s)
299 35db099d bellard
{
300 35db099d bellard
    int speed, parity, data_bits, stop_bits;
301 35db099d bellard
    QEMUSerialSetParams ssp;
302 35db099d bellard
303 35db099d bellard
    if (!s->chr || s->type != ser)
304 35db099d bellard
        return;
305 35db099d bellard
306 35db099d bellard
    if (s->wregs[4] & 1) {
307 35db099d bellard
        if (s->wregs[4] & 2)
308 35db099d bellard
            parity = 'E';
309 35db099d bellard
        else
310 35db099d bellard
            parity = 'O';
311 35db099d bellard
    } else {
312 35db099d bellard
        parity = 'N';
313 35db099d bellard
    }
314 35db099d bellard
    if ((s->wregs[4] & 0x0c) == 0x0c)
315 35db099d bellard
        stop_bits = 2;
316 35db099d bellard
    else
317 35db099d bellard
        stop_bits = 1;
318 35db099d bellard
    switch (s->wregs[5] & 0x60) {
319 35db099d bellard
    case 0x00:
320 35db099d bellard
        data_bits = 5;
321 35db099d bellard
        break;
322 35db099d bellard
    case 0x20:
323 35db099d bellard
        data_bits = 7;
324 35db099d bellard
        break;
325 35db099d bellard
    case 0x40:
326 35db099d bellard
        data_bits = 6;
327 35db099d bellard
        break;
328 35db099d bellard
    default:
329 35db099d bellard
    case 0x60:
330 35db099d bellard
        data_bits = 8;
331 35db099d bellard
        break;
332 35db099d bellard
    }
333 35db099d bellard
    speed = 2457600 / ((s->wregs[12] | (s->wregs[13] << 8)) + 2);
334 35db099d bellard
    switch (s->wregs[4] & 0xc0) {
335 35db099d bellard
    case 0x00:
336 35db099d bellard
        break;
337 35db099d bellard
    case 0x40:
338 35db099d bellard
        speed /= 16;
339 35db099d bellard
        break;
340 35db099d bellard
    case 0x80:
341 35db099d bellard
        speed /= 32;
342 35db099d bellard
        break;
343 35db099d bellard
    default:
344 35db099d bellard
    case 0xc0:
345 35db099d bellard
        speed /= 64;
346 35db099d bellard
        break;
347 35db099d bellard
    }
348 35db099d bellard
    ssp.speed = speed;
349 35db099d bellard
    ssp.parity = parity;
350 35db099d bellard
    ssp.data_bits = data_bits;
351 35db099d bellard
    ssp.stop_bits = stop_bits;
352 35db099d bellard
    SER_DPRINTF("channel %c: speed=%d parity=%c data=%d stop=%d\n", CHN_C(s),
353 35db099d bellard
                speed, parity, data_bits, stop_bits);
354 35db099d bellard
    qemu_chr_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
355 35db099d bellard
}
356 35db099d bellard
357 3a5c3138 bellard
static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
358 e80cfcfc bellard
{
359 b3ceef24 blueswir1
    SerialState *serial = opaque;
360 e80cfcfc bellard
    ChannelState *s;
361 e80cfcfc bellard
    uint32_t saddr;
362 e80cfcfc bellard
    int newreg, channel;
363 e80cfcfc bellard
364 e80cfcfc bellard
    val &= 0xff;
365 e80cfcfc bellard
    saddr = (addr & 3) >> 1;
366 e80cfcfc bellard
    channel = (addr & SERIAL_MAXADDR) >> 2;
367 b3ceef24 blueswir1
    s = &serial->chn[channel];
368 e80cfcfc bellard
    switch (saddr) {
369 e80cfcfc bellard
    case 0:
370 35db099d bellard
        SER_DPRINTF("Write channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg, val & 0xff);
371 e80cfcfc bellard
        newreg = 0;
372 e80cfcfc bellard
        switch (s->reg) {
373 e80cfcfc bellard
        case 0:
374 e80cfcfc bellard
            newreg = val & 7;
375 e80cfcfc bellard
            val &= 0x38;
376 e80cfcfc bellard
            switch (val) {
377 e80cfcfc bellard
            case 8:
378 f69a8695 bellard
                newreg |= 0x8;
379 e80cfcfc bellard
                break;
380 e80cfcfc bellard
            case 0x28:
381 ba3c64fb bellard
                clr_txint(s);
382 ba3c64fb bellard
                break;
383 ba3c64fb bellard
            case 0x38:
384 e4a89056 bellard
                if (s->rxint_under_svc)
385 e4a89056 bellard
                    clr_rxint(s);
386 e4a89056 bellard
                else if (s->txint_under_svc)
387 e4a89056 bellard
                    clr_txint(s);
388 e80cfcfc bellard
                break;
389 e80cfcfc bellard
            default:
390 e80cfcfc bellard
                break;
391 e80cfcfc bellard
            }
392 e80cfcfc bellard
            break;
393 35db099d bellard
        case 1 ... 3:
394 35db099d bellard
        case 6 ... 8:
395 35db099d bellard
        case 10 ... 11:
396 35db099d bellard
        case 14 ... 15:
397 35db099d bellard
            s->wregs[s->reg] = val;
398 35db099d bellard
            break;
399 35db099d bellard
        case 4:
400 35db099d bellard
        case 5:
401 35db099d bellard
        case 12:
402 35db099d bellard
        case 13:
403 e80cfcfc bellard
            s->wregs[s->reg] = val;
404 35db099d bellard
            slavio_serial_update_parameters(s);
405 e80cfcfc bellard
            break;
406 e80cfcfc bellard
        case 9:
407 e80cfcfc bellard
            switch (val & 0xc0) {
408 e80cfcfc bellard
            case 0:
409 e80cfcfc bellard
            default:
410 e80cfcfc bellard
                break;
411 e80cfcfc bellard
            case 0x40:
412 b3ceef24 blueswir1
                slavio_serial_reset_chn(&serial->chn[1]);
413 e80cfcfc bellard
                return;
414 e80cfcfc bellard
            case 0x80:
415 b3ceef24 blueswir1
                slavio_serial_reset_chn(&serial->chn[0]);
416 e80cfcfc bellard
                return;
417 e80cfcfc bellard
            case 0xc0:
418 b3ceef24 blueswir1
                slavio_serial_reset(serial);
419 e80cfcfc bellard
                return;
420 e80cfcfc bellard
            }
421 e80cfcfc bellard
            break;
422 e80cfcfc bellard
        default:
423 e80cfcfc bellard
            break;
424 e80cfcfc bellard
        }
425 e80cfcfc bellard
        if (s->reg == 0)
426 e80cfcfc bellard
            s->reg = newreg;
427 e80cfcfc bellard
        else
428 e80cfcfc bellard
            s->reg = 0;
429 e80cfcfc bellard
        break;
430 e80cfcfc bellard
    case 1:
431 35db099d bellard
        SER_DPRINTF("Write channel %c, ch %d\n", CHN_C(s), val);
432 96c4f569 blueswir1
        s->tx = val;
433 e80cfcfc bellard
        if (s->wregs[5] & 8) { // tx enabled
434 e80cfcfc bellard
            if (s->chr)
435 e80cfcfc bellard
                qemu_chr_write(s->chr, &s->tx, 1);
436 8be1f5c8 bellard
            else if (s->type == kbd) {
437 8be1f5c8 bellard
                handle_kbd_command(s, val);
438 8be1f5c8 bellard
            }
439 e80cfcfc bellard
        }
440 96c4f569 blueswir1
        s->rregs[0] |= 4; // Tx buffer empty
441 96c4f569 blueswir1
        s->rregs[1] |= 1; // All sent
442 96c4f569 blueswir1
        set_txint(s);
443 e80cfcfc bellard
        break;
444 e80cfcfc bellard
    default:
445 e80cfcfc bellard
        break;
446 e80cfcfc bellard
    }
447 e80cfcfc bellard
}
448 e80cfcfc bellard
449 3a5c3138 bellard
static uint32_t slavio_serial_mem_readb(void *opaque, target_phys_addr_t addr)
450 e80cfcfc bellard
{
451 b3ceef24 blueswir1
    SerialState *serial = opaque;
452 e80cfcfc bellard
    ChannelState *s;
453 e80cfcfc bellard
    uint32_t saddr;
454 e80cfcfc bellard
    uint32_t ret;
455 e80cfcfc bellard
    int channel;
456 e80cfcfc bellard
457 e80cfcfc bellard
    saddr = (addr & 3) >> 1;
458 e80cfcfc bellard
    channel = (addr & SERIAL_MAXADDR) >> 2;
459 b3ceef24 blueswir1
    s = &serial->chn[channel];
460 e80cfcfc bellard
    switch (saddr) {
461 e80cfcfc bellard
    case 0:
462 35db099d bellard
        SER_DPRINTF("Read channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg, s->rregs[s->reg]);
463 e80cfcfc bellard
        ret = s->rregs[s->reg];
464 e80cfcfc bellard
        s->reg = 0;
465 e80cfcfc bellard
        return ret;
466 e80cfcfc bellard
    case 1:
467 e80cfcfc bellard
        s->rregs[0] &= ~1;
468 ba3c64fb bellard
        clr_rxint(s);
469 715748fa bellard
        if (s->type == kbd || s->type == mouse)
470 8be1f5c8 bellard
            ret = get_queue(s);
471 8be1f5c8 bellard
        else
472 8be1f5c8 bellard
            ret = s->rx;
473 35db099d bellard
        SER_DPRINTF("Read channel %c, ch %d\n", CHN_C(s), ret);
474 8be1f5c8 bellard
        return ret;
475 e80cfcfc bellard
    default:
476 e80cfcfc bellard
        break;
477 e80cfcfc bellard
    }
478 e80cfcfc bellard
    return 0;
479 e80cfcfc bellard
}
480 e80cfcfc bellard
481 e80cfcfc bellard
static int serial_can_receive(void *opaque)
482 e80cfcfc bellard
{
483 e80cfcfc bellard
    ChannelState *s = opaque;
484 e4a89056 bellard
    int ret;
485 e4a89056 bellard
486 e80cfcfc bellard
    if (((s->wregs[3] & 1) == 0) // Rx not enabled
487 e80cfcfc bellard
        || ((s->rregs[0] & 1) == 1)) // char already available
488 e4a89056 bellard
        ret = 0;
489 e80cfcfc bellard
    else
490 e4a89056 bellard
        ret = 1;
491 35db099d bellard
    //SER_DPRINTF("channel %c can receive %d\n", CHN_C(s), ret);
492 e4a89056 bellard
    return ret;
493 e80cfcfc bellard
}
494 e80cfcfc bellard
495 e80cfcfc bellard
static void serial_receive_byte(ChannelState *s, int ch)
496 e80cfcfc bellard
{
497 35db099d bellard
    SER_DPRINTF("channel %c put ch %d\n", CHN_C(s), ch);
498 e80cfcfc bellard
    s->rregs[0] |= 1;
499 e80cfcfc bellard
    s->rx = ch;
500 ba3c64fb bellard
    set_rxint(s);
501 e80cfcfc bellard
}
502 e80cfcfc bellard
503 e80cfcfc bellard
static void serial_receive_break(ChannelState *s)
504 e80cfcfc bellard
{
505 e80cfcfc bellard
    s->rregs[0] |= 0x80;
506 e80cfcfc bellard
    slavio_serial_update_irq(s);
507 e80cfcfc bellard
}
508 e80cfcfc bellard
509 e80cfcfc bellard
static void serial_receive1(void *opaque, const uint8_t *buf, int size)
510 e80cfcfc bellard
{
511 e80cfcfc bellard
    ChannelState *s = opaque;
512 e80cfcfc bellard
    serial_receive_byte(s, buf[0]);
513 e80cfcfc bellard
}
514 e80cfcfc bellard
515 e80cfcfc bellard
static void serial_event(void *opaque, int event)
516 e80cfcfc bellard
{
517 e80cfcfc bellard
    ChannelState *s = opaque;
518 e80cfcfc bellard
    if (event == CHR_EVENT_BREAK)
519 e80cfcfc bellard
        serial_receive_break(s);
520 e80cfcfc bellard
}
521 e80cfcfc bellard
522 e80cfcfc bellard
static CPUReadMemoryFunc *slavio_serial_mem_read[3] = {
523 e80cfcfc bellard
    slavio_serial_mem_readb,
524 e80cfcfc bellard
    slavio_serial_mem_readb,
525 e80cfcfc bellard
    slavio_serial_mem_readb,
526 e80cfcfc bellard
};
527 e80cfcfc bellard
528 e80cfcfc bellard
static CPUWriteMemoryFunc *slavio_serial_mem_write[3] = {
529 e80cfcfc bellard
    slavio_serial_mem_writeb,
530 e80cfcfc bellard
    slavio_serial_mem_writeb,
531 e80cfcfc bellard
    slavio_serial_mem_writeb,
532 e80cfcfc bellard
};
533 e80cfcfc bellard
534 e80cfcfc bellard
static void slavio_serial_save_chn(QEMUFile *f, ChannelState *s)
535 e80cfcfc bellard
{
536 d537cf6c pbrook
    int tmp;
537 d537cf6c pbrook
    tmp = 0;
538 d537cf6c pbrook
    qemu_put_be32s(f, &tmp); /* unused, was IRQ.  */
539 e80cfcfc bellard
    qemu_put_be32s(f, &s->reg);
540 e80cfcfc bellard
    qemu_put_be32s(f, &s->rxint);
541 e80cfcfc bellard
    qemu_put_be32s(f, &s->txint);
542 e4a89056 bellard
    qemu_put_be32s(f, &s->rxint_under_svc);
543 e4a89056 bellard
    qemu_put_be32s(f, &s->txint_under_svc);
544 e80cfcfc bellard
    qemu_put_8s(f, &s->rx);
545 e80cfcfc bellard
    qemu_put_8s(f, &s->tx);
546 e80cfcfc bellard
    qemu_put_buffer(f, s->wregs, 16);
547 e80cfcfc bellard
    qemu_put_buffer(f, s->rregs, 16);
548 e80cfcfc bellard
}
549 e80cfcfc bellard
550 e80cfcfc bellard
static void slavio_serial_save(QEMUFile *f, void *opaque)
551 e80cfcfc bellard
{
552 e80cfcfc bellard
    SerialState *s = opaque;
553 e80cfcfc bellard
554 e80cfcfc bellard
    slavio_serial_save_chn(f, &s->chn[0]);
555 e80cfcfc bellard
    slavio_serial_save_chn(f, &s->chn[1]);
556 e80cfcfc bellard
}
557 e80cfcfc bellard
558 e80cfcfc bellard
static int slavio_serial_load_chn(QEMUFile *f, ChannelState *s, int version_id)
559 e80cfcfc bellard
{
560 d537cf6c pbrook
    int tmp;
561 d537cf6c pbrook
562 e4a89056 bellard
    if (version_id > 2)
563 e80cfcfc bellard
        return -EINVAL;
564 e80cfcfc bellard
565 d537cf6c pbrook
    qemu_get_be32s(f, &tmp); /* unused */
566 e80cfcfc bellard
    qemu_get_be32s(f, &s->reg);
567 e80cfcfc bellard
    qemu_get_be32s(f, &s->rxint);
568 e80cfcfc bellard
    qemu_get_be32s(f, &s->txint);
569 e4a89056 bellard
    if (version_id >= 2) {
570 e4a89056 bellard
        qemu_get_be32s(f, &s->rxint_under_svc);
571 e4a89056 bellard
        qemu_get_be32s(f, &s->txint_under_svc);
572 e4a89056 bellard
    }
573 e80cfcfc bellard
    qemu_get_8s(f, &s->rx);
574 e80cfcfc bellard
    qemu_get_8s(f, &s->tx);
575 e80cfcfc bellard
    qemu_get_buffer(f, s->wregs, 16);
576 e80cfcfc bellard
    qemu_get_buffer(f, s->rregs, 16);
577 e80cfcfc bellard
    return 0;
578 e80cfcfc bellard
}
579 e80cfcfc bellard
580 e80cfcfc bellard
static int slavio_serial_load(QEMUFile *f, void *opaque, int version_id)
581 e80cfcfc bellard
{
582 e80cfcfc bellard
    SerialState *s = opaque;
583 e80cfcfc bellard
    int ret;
584 e80cfcfc bellard
585 e80cfcfc bellard
    ret = slavio_serial_load_chn(f, &s->chn[0], version_id);
586 e80cfcfc bellard
    if (ret != 0)
587 e80cfcfc bellard
        return ret;
588 e80cfcfc bellard
    ret = slavio_serial_load_chn(f, &s->chn[1], version_id);
589 e80cfcfc bellard
    return ret;
590 e80cfcfc bellard
591 e80cfcfc bellard
}
592 e80cfcfc bellard
593 5dcb6b91 blueswir1
SerialState *slavio_serial_init(target_phys_addr_t base, qemu_irq irq,
594 5dcb6b91 blueswir1
                                CharDriverState *chr1, CharDriverState *chr2)
595 e80cfcfc bellard
{
596 8be1f5c8 bellard
    int slavio_serial_io_memory, i;
597 e80cfcfc bellard
    SerialState *s;
598 e80cfcfc bellard
599 e80cfcfc bellard
    s = qemu_mallocz(sizeof(SerialState));
600 e80cfcfc bellard
    if (!s)
601 e80cfcfc bellard
        return NULL;
602 e80cfcfc bellard
603 e80cfcfc bellard
    slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read, slavio_serial_mem_write, s);
604 5aca8c3b blueswir1
    cpu_register_physical_memory(base, SERIAL_SIZE, slavio_serial_io_memory);
605 e80cfcfc bellard
606 8be1f5c8 bellard
    s->chn[0].chr = chr1;
607 8be1f5c8 bellard
    s->chn[1].chr = chr2;
608 8be1f5c8 bellard
609 8be1f5c8 bellard
    for (i = 0; i < 2; i++) {
610 8be1f5c8 bellard
        s->chn[i].irq = irq;
611 8be1f5c8 bellard
        s->chn[i].chn = 1 - i;
612 8be1f5c8 bellard
        s->chn[i].type = ser;
613 8be1f5c8 bellard
        if (s->chn[i].chr) {
614 e5b0bc44 pbrook
            qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive,
615 e5b0bc44 pbrook
                                  serial_receive1, serial_event, &s->chn[i]);
616 8be1f5c8 bellard
        }
617 e80cfcfc bellard
    }
618 8be1f5c8 bellard
    s->chn[0].otherchn = &s->chn[1];
619 8be1f5c8 bellard
    s->chn[1].otherchn = &s->chn[0];
620 e4a89056 bellard
    register_savevm("slavio_serial", base, 2, slavio_serial_save, slavio_serial_load, s);
621 e80cfcfc bellard
    qemu_register_reset(slavio_serial_reset, s);
622 e80cfcfc bellard
    slavio_serial_reset(s);
623 e80cfcfc bellard
    return s;
624 e80cfcfc bellard
}
625 e80cfcfc bellard
626 8be1f5c8 bellard
static const uint8_t keycodes[128] = {
627 8be1f5c8 bellard
    127, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 43, 53,
628 8be1f5c8 bellard
    54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 89, 76, 77, 78,
629 8be1f5c8 bellard
    79, 80, 81, 82, 83, 84, 85, 86, 87, 42, 99, 88, 100, 101, 102, 103,
630 8be1f5c8 bellard
    104, 105, 106, 107, 108, 109, 110, 47, 19, 121, 119, 5, 6, 8, 10, 12,
631 8be1f5c8 bellard
    14, 16, 17, 18, 7, 98, 23, 68, 69, 70, 71, 91, 92, 93, 125, 112,
632 8be1f5c8 bellard
    113, 114, 94, 50, 0, 0, 124, 9, 11, 0, 0, 0, 0, 0, 0, 0,
633 8be1f5c8 bellard
    90, 0, 46, 22, 13, 111, 52, 20, 96, 24, 28, 74, 27, 123, 44, 66,
634 8be1f5c8 bellard
    0, 45, 2, 4, 48, 0, 0, 21, 0, 0, 0, 0, 0, 120, 122, 67,
635 8be1f5c8 bellard
};
636 8be1f5c8 bellard
637 43febf49 blueswir1
static const uint8_t e0_keycodes[128] = {
638 43febf49 blueswir1
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
639 43febf49 blueswir1
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 76, 0, 0,
640 43febf49 blueswir1
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
641 43febf49 blueswir1
    0, 0, 0, 0, 0, 109, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0,
642 43febf49 blueswir1
    0, 0, 0, 0, 0, 0, 0, 68, 69, 70, 0, 91, 0, 93, 0, 112,
643 43febf49 blueswir1
    113, 114, 94, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
644 43febf49 blueswir1
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
645 43febf49 blueswir1
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
646 43febf49 blueswir1
};
647 43febf49 blueswir1
648 e80cfcfc bellard
static void sunkbd_event(void *opaque, int ch)
649 e80cfcfc bellard
{
650 e80cfcfc bellard
    ChannelState *s = opaque;
651 8be1f5c8 bellard
    int release = ch & 0x80;
652 8be1f5c8 bellard
653 43febf49 blueswir1
    KBD_DPRINTF("Untranslated keycode %2.2x (%s)\n", ch, release? "release" : "press");
654 bbbb2f0a blueswir1
    switch (ch) {
655 bbbb2f0a blueswir1
    case 58: // Caps lock press
656 bbbb2f0a blueswir1
        s->caps_lock_mode ^= 1;
657 bbbb2f0a blueswir1
        if (s->caps_lock_mode == 2)
658 bbbb2f0a blueswir1
            return; // Drop second press
659 bbbb2f0a blueswir1
        break;
660 bbbb2f0a blueswir1
    case 69: // Num lock press
661 bbbb2f0a blueswir1
        s->num_lock_mode ^= 1;
662 bbbb2f0a blueswir1
        if (s->num_lock_mode == 2)
663 bbbb2f0a blueswir1
            return; // Drop second press
664 bbbb2f0a blueswir1
        break;
665 bbbb2f0a blueswir1
    case 186: // Caps lock release
666 bbbb2f0a blueswir1
        s->caps_lock_mode ^= 2;
667 bbbb2f0a blueswir1
        if (s->caps_lock_mode == 3)
668 bbbb2f0a blueswir1
            return; // Drop first release
669 bbbb2f0a blueswir1
        break;
670 bbbb2f0a blueswir1
    case 197: // Num lock release
671 bbbb2f0a blueswir1
        s->num_lock_mode ^= 2;
672 bbbb2f0a blueswir1
        if (s->num_lock_mode == 3)
673 bbbb2f0a blueswir1
            return; // Drop first release
674 bbbb2f0a blueswir1
        break;
675 bbbb2f0a blueswir1
    case 0xe0:
676 43febf49 blueswir1
        s->e0_mode = 1;
677 43febf49 blueswir1
        return;
678 bbbb2f0a blueswir1
    default:
679 bbbb2f0a blueswir1
        break;
680 43febf49 blueswir1
    }
681 43febf49 blueswir1
    if (s->e0_mode) {
682 43febf49 blueswir1
        s->e0_mode = 0;
683 43febf49 blueswir1
        ch = e0_keycodes[ch & 0x7f];
684 43febf49 blueswir1
    } else {
685 43febf49 blueswir1
        ch = keycodes[ch & 0x7f];
686 43febf49 blueswir1
    }
687 43febf49 blueswir1
    KBD_DPRINTF("Translated keycode %2.2x\n", ch);
688 8be1f5c8 bellard
    put_queue(s, ch | release);
689 8be1f5c8 bellard
}
690 8be1f5c8 bellard
691 8be1f5c8 bellard
static void handle_kbd_command(ChannelState *s, int val)
692 8be1f5c8 bellard
{
693 8be1f5c8 bellard
    KBD_DPRINTF("Command %d\n", val);
694 43febf49 blueswir1
    if (s->led_mode) { // Ignore led byte
695 43febf49 blueswir1
        s->led_mode = 0;
696 43febf49 blueswir1
        return;
697 43febf49 blueswir1
    }
698 8be1f5c8 bellard
    switch (val) {
699 8be1f5c8 bellard
    case 1: // Reset, return type code
700 67deb562 blueswir1
        clear_queue(s);
701 8be1f5c8 bellard
        put_queue(s, 0xff);
702 67deb562 blueswir1
        put_queue(s, 4); // Type 4
703 43febf49 blueswir1
        put_queue(s, 0x7f);
704 8be1f5c8 bellard
        break;
705 43febf49 blueswir1
    case 0xe: // Set leds
706 43febf49 blueswir1
        s->led_mode = 1;
707 43febf49 blueswir1
        break;
708 8be1f5c8 bellard
    case 7: // Query layout
709 67deb562 blueswir1
    case 0xf:
710 67deb562 blueswir1
        clear_queue(s);
711 8be1f5c8 bellard
        put_queue(s, 0xfe);
712 43febf49 blueswir1
        put_queue(s, 0); // XXX, layout?
713 8be1f5c8 bellard
        break;
714 8be1f5c8 bellard
    default:
715 8be1f5c8 bellard
        break;
716 8be1f5c8 bellard
    }
717 e80cfcfc bellard
}
718 e80cfcfc bellard
719 5fafdf24 ths
static void sunmouse_event(void *opaque,
720 e80cfcfc bellard
                               int dx, int dy, int dz, int buttons_state)
721 e80cfcfc bellard
{
722 e80cfcfc bellard
    ChannelState *s = opaque;
723 e80cfcfc bellard
    int ch;
724 e80cfcfc bellard
725 715748fa bellard
    MS_DPRINTF("dx=%d dy=%d buttons=%01x\n", dx, dy, buttons_state);
726 715748fa bellard
727 715748fa bellard
    ch = 0x80 | 0x7; /* protocol start byte, no buttons pressed */
728 715748fa bellard
729 715748fa bellard
    if (buttons_state & MOUSE_EVENT_LBUTTON)
730 715748fa bellard
        ch ^= 0x4;
731 715748fa bellard
    if (buttons_state & MOUSE_EVENT_MBUTTON)
732 715748fa bellard
        ch ^= 0x2;
733 715748fa bellard
    if (buttons_state & MOUSE_EVENT_RBUTTON)
734 715748fa bellard
        ch ^= 0x1;
735 715748fa bellard
736 715748fa bellard
    put_queue(s, ch);
737 715748fa bellard
738 715748fa bellard
    ch = dx;
739 715748fa bellard
740 715748fa bellard
    if (ch > 127)
741 715748fa bellard
        ch=127;
742 715748fa bellard
    else if (ch < -127)
743 715748fa bellard
        ch=-127;
744 715748fa bellard
745 715748fa bellard
    put_queue(s, ch & 0xff);
746 715748fa bellard
747 715748fa bellard
    ch = -dy;
748 715748fa bellard
749 715748fa bellard
    if (ch > 127)
750 715748fa bellard
        ch=127;
751 715748fa bellard
    else if (ch < -127)
752 715748fa bellard
        ch=-127;
753 715748fa bellard
754 715748fa bellard
    put_queue(s, ch & 0xff);
755 715748fa bellard
756 715748fa bellard
    // MSC protocol specify two extra motion bytes
757 715748fa bellard
758 715748fa bellard
    put_queue(s, 0);
759 715748fa bellard
    put_queue(s, 0);
760 e80cfcfc bellard
}
761 e80cfcfc bellard
762 5dcb6b91 blueswir1
void slavio_serial_ms_kbd_init(target_phys_addr_t base, qemu_irq irq)
763 e80cfcfc bellard
{
764 8be1f5c8 bellard
    int slavio_serial_io_memory, i;
765 e80cfcfc bellard
    SerialState *s;
766 e80cfcfc bellard
767 e80cfcfc bellard
    s = qemu_mallocz(sizeof(SerialState));
768 e80cfcfc bellard
    if (!s)
769 e80cfcfc bellard
        return;
770 8be1f5c8 bellard
    for (i = 0; i < 2; i++) {
771 8be1f5c8 bellard
        s->chn[i].irq = irq;
772 8be1f5c8 bellard
        s->chn[i].chn = 1 - i;
773 8be1f5c8 bellard
        s->chn[i].chr = NULL;
774 8be1f5c8 bellard
    }
775 8be1f5c8 bellard
    s->chn[0].otherchn = &s->chn[1];
776 8be1f5c8 bellard
    s->chn[1].otherchn = &s->chn[0];
777 8be1f5c8 bellard
    s->chn[0].type = mouse;
778 8be1f5c8 bellard
    s->chn[1].type = kbd;
779 e80cfcfc bellard
780 e80cfcfc bellard
    slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read, slavio_serial_mem_write, s);
781 5aca8c3b blueswir1
    cpu_register_physical_memory(base, SERIAL_SIZE, slavio_serial_io_memory);
782 e80cfcfc bellard
783 455204eb ths
    qemu_add_mouse_event_handler(sunmouse_event, &s->chn[0], 0, "QEMU Sun Mouse");
784 8be1f5c8 bellard
    qemu_add_kbd_event_handler(sunkbd_event, &s->chn[1]);
785 5425a216 blueswir1
    register_savevm("slavio_serial_mouse", base, 2, slavio_serial_save, slavio_serial_load, s);
786 e80cfcfc bellard
    qemu_register_reset(slavio_serial_reset, s);
787 e80cfcfc bellard
    slavio_serial_reset(s);
788 e80cfcfc bellard
}