Statistics
| Branch: | Revision:

root / hw / slavio_serial.c @ f68c781c

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