Statistics
| Branch: | Revision:

root / hw / slavio_serial.c @ 09b26c5e

History | View | Annotate | Download (13.2 kB)

1 e80cfcfc bellard
/*
2 e80cfcfc bellard
 * QEMU Sparc SLAVIO serial port emulation
3 e80cfcfc bellard
 * 
4 8be1f5c8 bellard
 * Copyright (c) 2003-2005 Fabrice Bellard
5 e80cfcfc bellard
 * 
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 e80cfcfc bellard
 * 
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 8be1f5c8 bellard
#ifdef DEBUG_SERIAL
46 8be1f5c8 bellard
#define SER_DPRINTF(fmt, args...) \
47 8be1f5c8 bellard
do { printf("SER: " fmt , ##args); } while (0)
48 ba3c64fb bellard
#define pic_set_irq(irq, level) \
49 ba3c64fb bellard
do { printf("SER: set_irq(%d): %d\n", (irq), (level)); pic_set_irq((irq),(level));} while (0)
50 8be1f5c8 bellard
#else
51 8be1f5c8 bellard
#define SER_DPRINTF(fmt, args...)
52 8be1f5c8 bellard
#endif
53 8be1f5c8 bellard
#ifdef DEBUG_KBD
54 8be1f5c8 bellard
#define KBD_DPRINTF(fmt, args...) \
55 8be1f5c8 bellard
do { printf("KBD: " fmt , ##args); } while (0)
56 8be1f5c8 bellard
#else
57 8be1f5c8 bellard
#define KBD_DPRINTF(fmt, args...)
58 8be1f5c8 bellard
#endif
59 8be1f5c8 bellard
#ifdef DEBUG_MOUSE
60 8be1f5c8 bellard
#define MS_DPRINTF(fmt, args...) \
61 8be1f5c8 bellard
do { printf("SER: " fmt , ##args); } while (0)
62 8be1f5c8 bellard
#else
63 8be1f5c8 bellard
#define MS_DPRINTF(fmt, args...)
64 8be1f5c8 bellard
#endif
65 8be1f5c8 bellard
66 8be1f5c8 bellard
typedef enum {
67 8be1f5c8 bellard
    chn_a, chn_b,
68 8be1f5c8 bellard
} chn_id_t;
69 8be1f5c8 bellard
70 8be1f5c8 bellard
typedef enum {
71 8be1f5c8 bellard
    ser, kbd, mouse,
72 8be1f5c8 bellard
} chn_type_t;
73 8be1f5c8 bellard
74 8be1f5c8 bellard
#define KBD_QUEUE_SIZE 256
75 8be1f5c8 bellard
76 8be1f5c8 bellard
typedef struct {
77 8be1f5c8 bellard
    uint8_t data[KBD_QUEUE_SIZE];
78 8be1f5c8 bellard
    int rptr, wptr, count;
79 8be1f5c8 bellard
} KBDQueue;
80 8be1f5c8 bellard
81 e80cfcfc bellard
typedef struct ChannelState {
82 e80cfcfc bellard
    int irq;
83 e80cfcfc bellard
    int reg;
84 e80cfcfc bellard
    int rxint, txint;
85 8be1f5c8 bellard
    chn_id_t chn; // this channel, A (base+4) or B (base+0)
86 8be1f5c8 bellard
    chn_type_t type;
87 8be1f5c8 bellard
    struct ChannelState *otherchn;
88 e80cfcfc bellard
    uint8_t rx, tx, wregs[16], rregs[16];
89 8be1f5c8 bellard
    KBDQueue queue;
90 e80cfcfc bellard
    CharDriverState *chr;
91 e80cfcfc bellard
} ChannelState;
92 e80cfcfc bellard
93 e80cfcfc bellard
struct SerialState {
94 e80cfcfc bellard
    struct ChannelState chn[2];
95 e80cfcfc bellard
};
96 e80cfcfc bellard
97 e80cfcfc bellard
#define SERIAL_MAXADDR 7
98 e80cfcfc bellard
99 8be1f5c8 bellard
static void handle_kbd_command(ChannelState *s, int val);
100 8be1f5c8 bellard
static int serial_can_receive(void *opaque);
101 8be1f5c8 bellard
static void serial_receive_byte(ChannelState *s, int ch);
102 8be1f5c8 bellard
103 8be1f5c8 bellard
static void put_queue(void *opaque, int b)
104 8be1f5c8 bellard
{
105 8be1f5c8 bellard
    ChannelState *s = opaque;
106 8be1f5c8 bellard
    KBDQueue *q = &s->queue;
107 8be1f5c8 bellard
108 8be1f5c8 bellard
    KBD_DPRINTF("put: 0x%02x\n", b);
109 8be1f5c8 bellard
    if (q->count >= KBD_QUEUE_SIZE)
110 8be1f5c8 bellard
        return;
111 8be1f5c8 bellard
    q->data[q->wptr] = b;
112 8be1f5c8 bellard
    if (++q->wptr == KBD_QUEUE_SIZE)
113 8be1f5c8 bellard
        q->wptr = 0;
114 8be1f5c8 bellard
    q->count++;
115 8be1f5c8 bellard
    serial_receive_byte(s, 0);
116 8be1f5c8 bellard
}
117 8be1f5c8 bellard
118 8be1f5c8 bellard
static uint32_t get_queue(void *opaque)
119 8be1f5c8 bellard
{
120 8be1f5c8 bellard
    ChannelState *s = opaque;
121 8be1f5c8 bellard
    KBDQueue *q = &s->queue;
122 8be1f5c8 bellard
    int val;
123 8be1f5c8 bellard
    
124 8be1f5c8 bellard
    if (q->count == 0) {
125 8be1f5c8 bellard
        return 0;
126 8be1f5c8 bellard
    } else {
127 8be1f5c8 bellard
        val = q->data[q->rptr];
128 8be1f5c8 bellard
        if (++q->rptr == KBD_QUEUE_SIZE)
129 8be1f5c8 bellard
            q->rptr = 0;
130 8be1f5c8 bellard
        q->count--;
131 8be1f5c8 bellard
    }
132 8be1f5c8 bellard
    KBD_DPRINTF("get 0x%02x\n", val);
133 8be1f5c8 bellard
    if (q->count > 0)
134 8be1f5c8 bellard
        serial_receive_byte(s, 0);
135 8be1f5c8 bellard
    return val;
136 8be1f5c8 bellard
}
137 8be1f5c8 bellard
138 e80cfcfc bellard
static void slavio_serial_update_irq(ChannelState *s)
139 e80cfcfc bellard
{
140 e80cfcfc bellard
    if ((s->wregs[1] & 1) && // interrupts enabled
141 e80cfcfc bellard
        (((s->wregs[1] & 2) && s->txint == 1) || // tx ints enabled, pending
142 e80cfcfc bellard
         ((((s->wregs[1] & 0x18) == 8) || ((s->wregs[1] & 0x18) == 0x10)) &&
143 e80cfcfc bellard
          s->rxint == 1) || // rx ints enabled, pending
144 e80cfcfc bellard
         ((s->wregs[15] & 0x80) && (s->rregs[0] & 0x80)))) { // break int e&p
145 e80cfcfc bellard
        pic_set_irq(s->irq, 1);
146 e80cfcfc bellard
    } else {
147 e80cfcfc bellard
        pic_set_irq(s->irq, 0);
148 e80cfcfc bellard
    }
149 e80cfcfc bellard
}
150 e80cfcfc bellard
151 e80cfcfc bellard
static void slavio_serial_reset_chn(ChannelState *s)
152 e80cfcfc bellard
{
153 e80cfcfc bellard
    int i;
154 e80cfcfc bellard
155 e80cfcfc bellard
    s->reg = 0;
156 e80cfcfc bellard
    for (i = 0; i < SERIAL_MAXADDR; i++) {
157 e80cfcfc bellard
        s->rregs[i] = 0;
158 e80cfcfc bellard
        s->wregs[i] = 0;
159 e80cfcfc bellard
    }
160 e80cfcfc bellard
    s->wregs[4] = 4;
161 e80cfcfc bellard
    s->wregs[9] = 0xc0;
162 e80cfcfc bellard
    s->wregs[11] = 8;
163 e80cfcfc bellard
    s->wregs[14] = 0x30;
164 e80cfcfc bellard
    s->wregs[15] = 0xf8;
165 e80cfcfc bellard
    s->rregs[0] = 0x44;
166 e80cfcfc bellard
    s->rregs[1] = 6;
167 e80cfcfc bellard
168 e80cfcfc bellard
    s->rx = s->tx = 0;
169 e80cfcfc bellard
    s->rxint = s->txint = 0;
170 e80cfcfc bellard
}
171 e80cfcfc bellard
172 e80cfcfc bellard
static void slavio_serial_reset(void *opaque)
173 e80cfcfc bellard
{
174 e80cfcfc bellard
    SerialState *s = opaque;
175 e80cfcfc bellard
    slavio_serial_reset_chn(&s->chn[0]);
176 e80cfcfc bellard
    slavio_serial_reset_chn(&s->chn[1]);
177 e80cfcfc bellard
}
178 e80cfcfc bellard
179 ba3c64fb bellard
static inline void clr_rxint(ChannelState *s)
180 ba3c64fb bellard
{
181 ba3c64fb bellard
    s->rxint = 0;
182 ba3c64fb bellard
    if (s->chn == 0)
183 ba3c64fb bellard
        s->rregs[3] &= ~0x20;
184 ba3c64fb bellard
    else {
185 ba3c64fb bellard
        s->otherchn->rregs[3] &= ~4;
186 ba3c64fb bellard
    }
187 ba3c64fb bellard
    slavio_serial_update_irq(s);
188 ba3c64fb bellard
}
189 ba3c64fb bellard
190 ba3c64fb bellard
static inline void set_rxint(ChannelState *s)
191 ba3c64fb bellard
{
192 ba3c64fb bellard
    s->rxint = 1;
193 ba3c64fb bellard
    if (s->chn == 0)
194 ba3c64fb bellard
        s->rregs[3] |= 0x20;
195 ba3c64fb bellard
    else {
196 ba3c64fb bellard
        s->otherchn->rregs[3] |= 4;
197 ba3c64fb bellard
    }
198 ba3c64fb bellard
    slavio_serial_update_irq(s);
199 ba3c64fb bellard
}
200 ba3c64fb bellard
201 ba3c64fb bellard
static inline void clr_txint(ChannelState *s)
202 ba3c64fb bellard
{
203 ba3c64fb bellard
    s->txint = 0;
204 ba3c64fb bellard
    if (s->chn == 0)
205 ba3c64fb bellard
        s->rregs[3] &= ~0x10;
206 ba3c64fb bellard
    else {
207 ba3c64fb bellard
        s->otherchn->rregs[3] &= ~2;
208 ba3c64fb bellard
    }
209 ba3c64fb bellard
    slavio_serial_update_irq(s);
210 ba3c64fb bellard
}
211 ba3c64fb bellard
212 ba3c64fb bellard
static inline void set_txint(ChannelState *s)
213 ba3c64fb bellard
{
214 ba3c64fb bellard
    s->txint = 1;
215 ba3c64fb bellard
    if (s->chn == 0)
216 ba3c64fb bellard
        s->rregs[3] |= 0x10;
217 ba3c64fb bellard
    else {
218 ba3c64fb bellard
        s->otherchn->rregs[3] |= 2;
219 ba3c64fb bellard
    }
220 ba3c64fb bellard
    slavio_serial_update_irq(s);
221 ba3c64fb bellard
}
222 ba3c64fb bellard
223 3a5c3138 bellard
static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
224 e80cfcfc bellard
{
225 e80cfcfc bellard
    SerialState *ser = opaque;
226 e80cfcfc bellard
    ChannelState *s;
227 e80cfcfc bellard
    uint32_t saddr;
228 e80cfcfc bellard
    int newreg, channel;
229 e80cfcfc bellard
230 e80cfcfc bellard
    val &= 0xff;
231 e80cfcfc bellard
    saddr = (addr & 3) >> 1;
232 e80cfcfc bellard
    channel = (addr & SERIAL_MAXADDR) >> 2;
233 e80cfcfc bellard
    s = &ser->chn[channel];
234 e80cfcfc bellard
    switch (saddr) {
235 e80cfcfc bellard
    case 0:
236 8be1f5c8 bellard
        SER_DPRINTF("Write channel %c, reg[%d] = %2.2x\n", channel? 'b' : 'a', s->reg, val & 0xff);
237 e80cfcfc bellard
        newreg = 0;
238 e80cfcfc bellard
        switch (s->reg) {
239 e80cfcfc bellard
        case 0:
240 e80cfcfc bellard
            newreg = val & 7;
241 e80cfcfc bellard
            val &= 0x38;
242 e80cfcfc bellard
            switch (val) {
243 e80cfcfc bellard
            case 8:
244 f69a8695 bellard
                newreg |= 0x8;
245 e80cfcfc bellard
                break;
246 e80cfcfc bellard
            case 0x20:
247 ba3c64fb bellard
                clr_rxint(s);
248 e80cfcfc bellard
                break;
249 e80cfcfc bellard
            case 0x28:
250 ba3c64fb bellard
                clr_txint(s);
251 ba3c64fb bellard
                break;
252 ba3c64fb bellard
            case 0x38:
253 ba3c64fb bellard
                clr_rxint(s);
254 ba3c64fb bellard
                clr_txint(s);
255 e80cfcfc bellard
                break;
256 e80cfcfc bellard
            default:
257 e80cfcfc bellard
                break;
258 e80cfcfc bellard
            }
259 e80cfcfc bellard
            break;
260 e80cfcfc bellard
        case 1 ... 8:
261 e80cfcfc bellard
        case 10 ... 15:
262 e80cfcfc bellard
            s->wregs[s->reg] = val;
263 e80cfcfc bellard
            break;
264 e80cfcfc bellard
        case 9:
265 e80cfcfc bellard
            switch (val & 0xc0) {
266 e80cfcfc bellard
            case 0:
267 e80cfcfc bellard
            default:
268 e80cfcfc bellard
                break;
269 e80cfcfc bellard
            case 0x40:
270 e80cfcfc bellard
                slavio_serial_reset_chn(&ser->chn[1]);
271 e80cfcfc bellard
                return;
272 e80cfcfc bellard
            case 0x80:
273 e80cfcfc bellard
                slavio_serial_reset_chn(&ser->chn[0]);
274 e80cfcfc bellard
                return;
275 e80cfcfc bellard
            case 0xc0:
276 e80cfcfc bellard
                slavio_serial_reset(ser);
277 e80cfcfc bellard
                return;
278 e80cfcfc bellard
            }
279 e80cfcfc bellard
            break;
280 e80cfcfc bellard
        default:
281 e80cfcfc bellard
            break;
282 e80cfcfc bellard
        }
283 e80cfcfc bellard
        if (s->reg == 0)
284 e80cfcfc bellard
            s->reg = newreg;
285 e80cfcfc bellard
        else
286 e80cfcfc bellard
            s->reg = 0;
287 e80cfcfc bellard
        break;
288 e80cfcfc bellard
    case 1:
289 8be1f5c8 bellard
        SER_DPRINTF("Write channel %c, ch %d\n", channel? 'b' : 'a', val);
290 e80cfcfc bellard
        if (s->wregs[5] & 8) { // tx enabled
291 e80cfcfc bellard
            s->tx = val;
292 e80cfcfc bellard
            if (s->chr)
293 e80cfcfc bellard
                qemu_chr_write(s->chr, &s->tx, 1);
294 8be1f5c8 bellard
            else if (s->type == kbd) {
295 8be1f5c8 bellard
                handle_kbd_command(s, val);
296 8be1f5c8 bellard
            }
297 e80cfcfc bellard
            s->txint = 1;
298 f69a8695 bellard
            s->rregs[0] |= 4; // Tx buffer empty
299 f69a8695 bellard
            s->rregs[1] |= 1; // All sent
300 ba3c64fb bellard
            set_txint(s);
301 8be1f5c8 bellard
            slavio_serial_update_irq(s);
302 e80cfcfc bellard
        }
303 e80cfcfc bellard
        break;
304 e80cfcfc bellard
    default:
305 e80cfcfc bellard
        break;
306 e80cfcfc bellard
    }
307 e80cfcfc bellard
}
308 e80cfcfc bellard
309 3a5c3138 bellard
static uint32_t slavio_serial_mem_readb(void *opaque, target_phys_addr_t addr)
310 e80cfcfc bellard
{
311 e80cfcfc bellard
    SerialState *ser = opaque;
312 e80cfcfc bellard
    ChannelState *s;
313 e80cfcfc bellard
    uint32_t saddr;
314 e80cfcfc bellard
    uint32_t ret;
315 e80cfcfc bellard
    int channel;
316 e80cfcfc bellard
317 e80cfcfc bellard
    saddr = (addr & 3) >> 1;
318 e80cfcfc bellard
    channel = (addr & SERIAL_MAXADDR) >> 2;
319 e80cfcfc bellard
    s = &ser->chn[channel];
320 e80cfcfc bellard
    switch (saddr) {
321 e80cfcfc bellard
    case 0:
322 8be1f5c8 bellard
        SER_DPRINTF("Read channel %c, reg[%d] = %2.2x\n", channel? 'b' : 'a', s->reg, s->rregs[s->reg]);
323 e80cfcfc bellard
        ret = s->rregs[s->reg];
324 e80cfcfc bellard
        s->reg = 0;
325 e80cfcfc bellard
        return ret;
326 e80cfcfc bellard
    case 1:
327 e80cfcfc bellard
        s->rregs[0] &= ~1;
328 ba3c64fb bellard
        clr_rxint(s);
329 8be1f5c8 bellard
        if (s->type == kbd)
330 8be1f5c8 bellard
            ret = get_queue(s);
331 8be1f5c8 bellard
        else
332 8be1f5c8 bellard
            ret = s->rx;
333 f69a8695 bellard
        SER_DPRINTF("Read channel %c, ch %d\n", channel? 'b' : 'a', ret);
334 8be1f5c8 bellard
        return ret;
335 e80cfcfc bellard
    default:
336 e80cfcfc bellard
        break;
337 e80cfcfc bellard
    }
338 e80cfcfc bellard
    return 0;
339 e80cfcfc bellard
}
340 e80cfcfc bellard
341 e80cfcfc bellard
static int serial_can_receive(void *opaque)
342 e80cfcfc bellard
{
343 e80cfcfc bellard
    ChannelState *s = opaque;
344 e80cfcfc bellard
    if (((s->wregs[3] & 1) == 0) // Rx not enabled
345 e80cfcfc bellard
        || ((s->rregs[0] & 1) == 1)) // char already available
346 e80cfcfc bellard
        return 0;
347 e80cfcfc bellard
    else
348 e80cfcfc bellard
        return 1;
349 e80cfcfc bellard
}
350 e80cfcfc bellard
351 e80cfcfc bellard
static void serial_receive_byte(ChannelState *s, int ch)
352 e80cfcfc bellard
{
353 ba3c64fb bellard
    SER_DPRINTF("put ch %d\n", ch);
354 e80cfcfc bellard
    s->rregs[0] |= 1;
355 e80cfcfc bellard
    s->rx = ch;
356 ba3c64fb bellard
    set_rxint(s);
357 e80cfcfc bellard
}
358 e80cfcfc bellard
359 e80cfcfc bellard
static void serial_receive_break(ChannelState *s)
360 e80cfcfc bellard
{
361 e80cfcfc bellard
    s->rregs[0] |= 0x80;
362 e80cfcfc bellard
    slavio_serial_update_irq(s);
363 e80cfcfc bellard
}
364 e80cfcfc bellard
365 e80cfcfc bellard
static void serial_receive1(void *opaque, const uint8_t *buf, int size)
366 e80cfcfc bellard
{
367 e80cfcfc bellard
    ChannelState *s = opaque;
368 e80cfcfc bellard
    serial_receive_byte(s, buf[0]);
369 e80cfcfc bellard
}
370 e80cfcfc bellard
371 e80cfcfc bellard
static void serial_event(void *opaque, int event)
372 e80cfcfc bellard
{
373 e80cfcfc bellard
    ChannelState *s = opaque;
374 e80cfcfc bellard
    if (event == CHR_EVENT_BREAK)
375 e80cfcfc bellard
        serial_receive_break(s);
376 e80cfcfc bellard
}
377 e80cfcfc bellard
378 e80cfcfc bellard
static CPUReadMemoryFunc *slavio_serial_mem_read[3] = {
379 e80cfcfc bellard
    slavio_serial_mem_readb,
380 e80cfcfc bellard
    slavio_serial_mem_readb,
381 e80cfcfc bellard
    slavio_serial_mem_readb,
382 e80cfcfc bellard
};
383 e80cfcfc bellard
384 e80cfcfc bellard
static CPUWriteMemoryFunc *slavio_serial_mem_write[3] = {
385 e80cfcfc bellard
    slavio_serial_mem_writeb,
386 e80cfcfc bellard
    slavio_serial_mem_writeb,
387 e80cfcfc bellard
    slavio_serial_mem_writeb,
388 e80cfcfc bellard
};
389 e80cfcfc bellard
390 e80cfcfc bellard
static void slavio_serial_save_chn(QEMUFile *f, ChannelState *s)
391 e80cfcfc bellard
{
392 e80cfcfc bellard
    qemu_put_be32s(f, &s->irq);
393 e80cfcfc bellard
    qemu_put_be32s(f, &s->reg);
394 e80cfcfc bellard
    qemu_put_be32s(f, &s->rxint);
395 e80cfcfc bellard
    qemu_put_be32s(f, &s->txint);
396 e80cfcfc bellard
    qemu_put_8s(f, &s->rx);
397 e80cfcfc bellard
    qemu_put_8s(f, &s->tx);
398 e80cfcfc bellard
    qemu_put_buffer(f, s->wregs, 16);
399 e80cfcfc bellard
    qemu_put_buffer(f, s->rregs, 16);
400 e80cfcfc bellard
}
401 e80cfcfc bellard
402 e80cfcfc bellard
static void slavio_serial_save(QEMUFile *f, void *opaque)
403 e80cfcfc bellard
{
404 e80cfcfc bellard
    SerialState *s = opaque;
405 e80cfcfc bellard
406 e80cfcfc bellard
    slavio_serial_save_chn(f, &s->chn[0]);
407 e80cfcfc bellard
    slavio_serial_save_chn(f, &s->chn[1]);
408 e80cfcfc bellard
}
409 e80cfcfc bellard
410 e80cfcfc bellard
static int slavio_serial_load_chn(QEMUFile *f, ChannelState *s, int version_id)
411 e80cfcfc bellard
{
412 e80cfcfc bellard
    if (version_id != 1)
413 e80cfcfc bellard
        return -EINVAL;
414 e80cfcfc bellard
415 e80cfcfc bellard
    qemu_get_be32s(f, &s->irq);
416 e80cfcfc bellard
    qemu_get_be32s(f, &s->reg);
417 e80cfcfc bellard
    qemu_get_be32s(f, &s->rxint);
418 e80cfcfc bellard
    qemu_get_be32s(f, &s->txint);
419 e80cfcfc bellard
    qemu_get_8s(f, &s->rx);
420 e80cfcfc bellard
    qemu_get_8s(f, &s->tx);
421 e80cfcfc bellard
    qemu_get_buffer(f, s->wregs, 16);
422 e80cfcfc bellard
    qemu_get_buffer(f, s->rregs, 16);
423 e80cfcfc bellard
    return 0;
424 e80cfcfc bellard
}
425 e80cfcfc bellard
426 e80cfcfc bellard
static int slavio_serial_load(QEMUFile *f, void *opaque, int version_id)
427 e80cfcfc bellard
{
428 e80cfcfc bellard
    SerialState *s = opaque;
429 e80cfcfc bellard
    int ret;
430 e80cfcfc bellard
431 e80cfcfc bellard
    ret = slavio_serial_load_chn(f, &s->chn[0], version_id);
432 e80cfcfc bellard
    if (ret != 0)
433 e80cfcfc bellard
        return ret;
434 e80cfcfc bellard
    ret = slavio_serial_load_chn(f, &s->chn[1], version_id);
435 e80cfcfc bellard
    return ret;
436 e80cfcfc bellard
437 e80cfcfc bellard
}
438 e80cfcfc bellard
439 e80cfcfc bellard
SerialState *slavio_serial_init(int base, int irq, CharDriverState *chr1, CharDriverState *chr2)
440 e80cfcfc bellard
{
441 8be1f5c8 bellard
    int slavio_serial_io_memory, i;
442 e80cfcfc bellard
    SerialState *s;
443 e80cfcfc bellard
444 e80cfcfc bellard
    s = qemu_mallocz(sizeof(SerialState));
445 e80cfcfc bellard
    if (!s)
446 e80cfcfc bellard
        return NULL;
447 e80cfcfc bellard
448 e80cfcfc bellard
    slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read, slavio_serial_mem_write, s);
449 e80cfcfc bellard
    cpu_register_physical_memory(base, SERIAL_MAXADDR, slavio_serial_io_memory);
450 e80cfcfc bellard
451 8be1f5c8 bellard
    s->chn[0].chr = chr1;
452 8be1f5c8 bellard
    s->chn[1].chr = chr2;
453 8be1f5c8 bellard
454 8be1f5c8 bellard
    for (i = 0; i < 2; i++) {
455 8be1f5c8 bellard
        s->chn[i].irq = irq;
456 8be1f5c8 bellard
        s->chn[i].chn = 1 - i;
457 8be1f5c8 bellard
        s->chn[i].type = ser;
458 8be1f5c8 bellard
        if (s->chn[i].chr) {
459 8be1f5c8 bellard
            qemu_chr_add_read_handler(s->chn[i].chr, serial_can_receive, serial_receive1, &s->chn[i]);
460 8be1f5c8 bellard
            qemu_chr_add_event_handler(s->chn[i].chr, serial_event);
461 8be1f5c8 bellard
        }
462 e80cfcfc bellard
    }
463 8be1f5c8 bellard
    s->chn[0].otherchn = &s->chn[1];
464 8be1f5c8 bellard
    s->chn[1].otherchn = &s->chn[0];
465 e80cfcfc bellard
    register_savevm("slavio_serial", base, 1, slavio_serial_save, slavio_serial_load, s);
466 e80cfcfc bellard
    qemu_register_reset(slavio_serial_reset, s);
467 e80cfcfc bellard
    slavio_serial_reset(s);
468 e80cfcfc bellard
    return s;
469 e80cfcfc bellard
}
470 e80cfcfc bellard
471 8be1f5c8 bellard
static const uint8_t keycodes[128] = {
472 8be1f5c8 bellard
    127, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 43, 53,
473 8be1f5c8 bellard
    54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 89, 76, 77, 78,
474 8be1f5c8 bellard
    79, 80, 81, 82, 83, 84, 85, 86, 87, 42, 99, 88, 100, 101, 102, 103,
475 8be1f5c8 bellard
    104, 105, 106, 107, 108, 109, 110, 47, 19, 121, 119, 5, 6, 8, 10, 12,
476 8be1f5c8 bellard
    14, 16, 17, 18, 7, 98, 23, 68, 69, 70, 71, 91, 92, 93, 125, 112,
477 8be1f5c8 bellard
    113, 114, 94, 50, 0, 0, 124, 9, 11, 0, 0, 0, 0, 0, 0, 0,
478 8be1f5c8 bellard
    90, 0, 46, 22, 13, 111, 52, 20, 96, 24, 28, 74, 27, 123, 44, 66,
479 8be1f5c8 bellard
    0, 45, 2, 4, 48, 0, 0, 21, 0, 0, 0, 0, 0, 120, 122, 67,
480 8be1f5c8 bellard
};
481 8be1f5c8 bellard
482 e80cfcfc bellard
static void sunkbd_event(void *opaque, int ch)
483 e80cfcfc bellard
{
484 e80cfcfc bellard
    ChannelState *s = opaque;
485 8be1f5c8 bellard
    int release = ch & 0x80;
486 8be1f5c8 bellard
487 8be1f5c8 bellard
    ch = keycodes[ch & 0x7f];
488 8be1f5c8 bellard
    KBD_DPRINTF("Keycode %d (%s)\n", ch, release? "release" : "press");
489 8be1f5c8 bellard
    put_queue(s, ch | release);
490 8be1f5c8 bellard
}
491 8be1f5c8 bellard
492 8be1f5c8 bellard
static void handle_kbd_command(ChannelState *s, int val)
493 8be1f5c8 bellard
{
494 8be1f5c8 bellard
    KBD_DPRINTF("Command %d\n", val);
495 8be1f5c8 bellard
    switch (val) {
496 8be1f5c8 bellard
    case 1: // Reset, return type code
497 8be1f5c8 bellard
        put_queue(s, 0xff);
498 8be1f5c8 bellard
        put_queue(s, 5); // Type 5
499 8be1f5c8 bellard
        break;
500 8be1f5c8 bellard
    case 7: // Query layout
501 8be1f5c8 bellard
        put_queue(s, 0xfe);
502 8be1f5c8 bellard
        put_queue(s, 0x20); // XXX, layout?
503 8be1f5c8 bellard
        break;
504 8be1f5c8 bellard
    default:
505 8be1f5c8 bellard
        break;
506 8be1f5c8 bellard
    }
507 e80cfcfc bellard
}
508 e80cfcfc bellard
509 e80cfcfc bellard
static void sunmouse_event(void *opaque, 
510 e80cfcfc bellard
                               int dx, int dy, int dz, int buttons_state)
511 e80cfcfc bellard
{
512 e80cfcfc bellard
    ChannelState *s = opaque;
513 e80cfcfc bellard
    int ch;
514 e80cfcfc bellard
515 e80cfcfc bellard
    // XXX
516 e80cfcfc bellard
    ch = 0x42;
517 e80cfcfc bellard
    serial_receive_byte(s, ch);
518 e80cfcfc bellard
}
519 e80cfcfc bellard
520 e80cfcfc bellard
void slavio_serial_ms_kbd_init(int base, int irq)
521 e80cfcfc bellard
{
522 8be1f5c8 bellard
    int slavio_serial_io_memory, i;
523 e80cfcfc bellard
    SerialState *s;
524 e80cfcfc bellard
525 e80cfcfc bellard
    s = qemu_mallocz(sizeof(SerialState));
526 e80cfcfc bellard
    if (!s)
527 e80cfcfc bellard
        return;
528 8be1f5c8 bellard
    for (i = 0; i < 2; i++) {
529 8be1f5c8 bellard
        s->chn[i].irq = irq;
530 8be1f5c8 bellard
        s->chn[i].chn = 1 - i;
531 8be1f5c8 bellard
        s->chn[i].chr = NULL;
532 8be1f5c8 bellard
    }
533 8be1f5c8 bellard
    s->chn[0].otherchn = &s->chn[1];
534 8be1f5c8 bellard
    s->chn[1].otherchn = &s->chn[0];
535 8be1f5c8 bellard
    s->chn[0].type = mouse;
536 8be1f5c8 bellard
    s->chn[1].type = kbd;
537 e80cfcfc bellard
538 e80cfcfc bellard
    slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read, slavio_serial_mem_write, s);
539 e80cfcfc bellard
    cpu_register_physical_memory(base, SERIAL_MAXADDR, slavio_serial_io_memory);
540 e80cfcfc bellard
541 8be1f5c8 bellard
    qemu_add_mouse_event_handler(sunmouse_event, &s->chn[0]);
542 8be1f5c8 bellard
    qemu_add_kbd_event_handler(sunkbd_event, &s->chn[1]);
543 e80cfcfc bellard
    qemu_register_reset(slavio_serial_reset, s);
544 e80cfcfc bellard
    slavio_serial_reset(s);
545 e80cfcfc bellard
}