Statistics
| Branch: | Revision:

root / hw / slavio_serial.c @ a2d4e44b

History | View | Annotate | Download (16.8 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 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 ba3c64fb bellard
#define pic_set_irq(irq, level) \
56 ba3c64fb bellard
do { printf("SER: set_irq(%d): %d\n", (irq), (level)); pic_set_irq((irq),(level));} while (0)
57 8be1f5c8 bellard
#else
58 8be1f5c8 bellard
#define SER_DPRINTF(fmt, args...)
59 8be1f5c8 bellard
#endif
60 8be1f5c8 bellard
#ifdef DEBUG_KBD
61 8be1f5c8 bellard
#define KBD_DPRINTF(fmt, args...) \
62 8be1f5c8 bellard
do { printf("KBD: " fmt , ##args); } while (0)
63 8be1f5c8 bellard
#else
64 8be1f5c8 bellard
#define KBD_DPRINTF(fmt, args...)
65 8be1f5c8 bellard
#endif
66 8be1f5c8 bellard
#ifdef DEBUG_MOUSE
67 8be1f5c8 bellard
#define MS_DPRINTF(fmt, args...) \
68 715748fa bellard
do { printf("MSC: " fmt , ##args); } while (0)
69 8be1f5c8 bellard
#else
70 8be1f5c8 bellard
#define MS_DPRINTF(fmt, args...)
71 8be1f5c8 bellard
#endif
72 8be1f5c8 bellard
73 8be1f5c8 bellard
typedef enum {
74 8be1f5c8 bellard
    chn_a, chn_b,
75 8be1f5c8 bellard
} chn_id_t;
76 8be1f5c8 bellard
77 35db099d bellard
#define CHN_C(s) ((s)->chn == chn_b? 'b' : 'a')
78 35db099d bellard
79 8be1f5c8 bellard
typedef enum {
80 8be1f5c8 bellard
    ser, kbd, mouse,
81 8be1f5c8 bellard
} chn_type_t;
82 8be1f5c8 bellard
83 715748fa bellard
#define SERIO_QUEUE_SIZE 256
84 8be1f5c8 bellard
85 8be1f5c8 bellard
typedef struct {
86 715748fa bellard
    uint8_t data[SERIO_QUEUE_SIZE];
87 8be1f5c8 bellard
    int rptr, wptr, count;
88 715748fa bellard
} SERIOQueue;
89 8be1f5c8 bellard
90 e80cfcfc bellard
typedef struct ChannelState {
91 e80cfcfc bellard
    int irq;
92 e80cfcfc bellard
    int reg;
93 e4a89056 bellard
    int rxint, txint, rxint_under_svc, txint_under_svc;
94 8be1f5c8 bellard
    chn_id_t chn; // this channel, A (base+4) or B (base+0)
95 8be1f5c8 bellard
    chn_type_t type;
96 8be1f5c8 bellard
    struct ChannelState *otherchn;
97 e80cfcfc bellard
    uint8_t rx, tx, wregs[16], rregs[16];
98 715748fa bellard
    SERIOQueue queue;
99 e80cfcfc bellard
    CharDriverState *chr;
100 e80cfcfc bellard
} ChannelState;
101 e80cfcfc bellard
102 e80cfcfc bellard
struct SerialState {
103 e80cfcfc bellard
    struct ChannelState chn[2];
104 e80cfcfc bellard
};
105 e80cfcfc bellard
106 e80cfcfc bellard
#define SERIAL_MAXADDR 7
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 8be1f5c8 bellard
static void put_queue(void *opaque, int b)
114 8be1f5c8 bellard
{
115 8be1f5c8 bellard
    ChannelState *s = opaque;
116 715748fa bellard
    SERIOQueue *q = &s->queue;
117 8be1f5c8 bellard
118 35db099d bellard
    SER_DPRINTF("channel %c put: 0x%02x\n", CHN_C(s), b);
119 715748fa bellard
    if (q->count >= SERIO_QUEUE_SIZE)
120 8be1f5c8 bellard
        return;
121 8be1f5c8 bellard
    q->data[q->wptr] = b;
122 715748fa bellard
    if (++q->wptr == SERIO_QUEUE_SIZE)
123 8be1f5c8 bellard
        q->wptr = 0;
124 8be1f5c8 bellard
    q->count++;
125 8be1f5c8 bellard
    serial_receive_byte(s, 0);
126 8be1f5c8 bellard
}
127 8be1f5c8 bellard
128 8be1f5c8 bellard
static uint32_t get_queue(void *opaque)
129 8be1f5c8 bellard
{
130 8be1f5c8 bellard
    ChannelState *s = opaque;
131 715748fa bellard
    SERIOQueue *q = &s->queue;
132 8be1f5c8 bellard
    int val;
133 8be1f5c8 bellard
    
134 8be1f5c8 bellard
    if (q->count == 0) {
135 8be1f5c8 bellard
        return 0;
136 8be1f5c8 bellard
    } else {
137 8be1f5c8 bellard
        val = q->data[q->rptr];
138 715748fa bellard
        if (++q->rptr == SERIO_QUEUE_SIZE)
139 8be1f5c8 bellard
            q->rptr = 0;
140 8be1f5c8 bellard
        q->count--;
141 8be1f5c8 bellard
    }
142 35db099d bellard
    KBD_DPRINTF("channel %c get 0x%02x\n", CHN_C(s), val);
143 8be1f5c8 bellard
    if (q->count > 0)
144 8be1f5c8 bellard
        serial_receive_byte(s, 0);
145 8be1f5c8 bellard
    return val;
146 8be1f5c8 bellard
}
147 8be1f5c8 bellard
148 e4a89056 bellard
static int slavio_serial_update_irq_chn(ChannelState *s)
149 e80cfcfc bellard
{
150 e80cfcfc bellard
    if ((s->wregs[1] & 1) && // interrupts enabled
151 e80cfcfc bellard
        (((s->wregs[1] & 2) && s->txint == 1) || // tx ints enabled, pending
152 e80cfcfc bellard
         ((((s->wregs[1] & 0x18) == 8) || ((s->wregs[1] & 0x18) == 0x10)) &&
153 e80cfcfc bellard
          s->rxint == 1) || // rx ints enabled, pending
154 e80cfcfc bellard
         ((s->wregs[15] & 0x80) && (s->rregs[0] & 0x80)))) { // break int e&p
155 e4a89056 bellard
        return 1;
156 e80cfcfc bellard
    }
157 e4a89056 bellard
    return 0;
158 e4a89056 bellard
}
159 e4a89056 bellard
160 e4a89056 bellard
static void slavio_serial_update_irq(ChannelState *s)
161 e4a89056 bellard
{
162 e4a89056 bellard
    int irq;
163 e4a89056 bellard
164 e4a89056 bellard
    irq = slavio_serial_update_irq_chn(s);
165 e4a89056 bellard
    irq |= slavio_serial_update_irq_chn(s->otherchn);
166 e4a89056 bellard
167 e4a89056 bellard
    pic_set_irq(s->irq, irq);
168 e80cfcfc bellard
}
169 e80cfcfc bellard
170 e80cfcfc bellard
static void slavio_serial_reset_chn(ChannelState *s)
171 e80cfcfc bellard
{
172 e80cfcfc bellard
    int i;
173 e80cfcfc bellard
174 e80cfcfc bellard
    s->reg = 0;
175 e80cfcfc bellard
    for (i = 0; i < SERIAL_MAXADDR; i++) {
176 e80cfcfc bellard
        s->rregs[i] = 0;
177 e80cfcfc bellard
        s->wregs[i] = 0;
178 e80cfcfc bellard
    }
179 e80cfcfc bellard
    s->wregs[4] = 4;
180 e80cfcfc bellard
    s->wregs[9] = 0xc0;
181 e80cfcfc bellard
    s->wregs[11] = 8;
182 e80cfcfc bellard
    s->wregs[14] = 0x30;
183 e80cfcfc bellard
    s->wregs[15] = 0xf8;
184 e80cfcfc bellard
    s->rregs[0] = 0x44;
185 e80cfcfc bellard
    s->rregs[1] = 6;
186 e80cfcfc bellard
187 e80cfcfc bellard
    s->rx = s->tx = 0;
188 e80cfcfc bellard
    s->rxint = s->txint = 0;
189 e4a89056 bellard
    s->rxint_under_svc = s->txint_under_svc = 0;
190 e80cfcfc bellard
}
191 e80cfcfc bellard
192 e80cfcfc bellard
static void slavio_serial_reset(void *opaque)
193 e80cfcfc bellard
{
194 e80cfcfc bellard
    SerialState *s = opaque;
195 e80cfcfc bellard
    slavio_serial_reset_chn(&s->chn[0]);
196 e80cfcfc bellard
    slavio_serial_reset_chn(&s->chn[1]);
197 e80cfcfc bellard
}
198 e80cfcfc bellard
199 ba3c64fb bellard
static inline void clr_rxint(ChannelState *s)
200 ba3c64fb bellard
{
201 ba3c64fb bellard
    s->rxint = 0;
202 e4a89056 bellard
    s->rxint_under_svc = 0;
203 35db099d bellard
    if (s->chn == chn_a)
204 ba3c64fb bellard
        s->rregs[3] &= ~0x20;
205 35db099d bellard
    else
206 ba3c64fb bellard
        s->otherchn->rregs[3] &= ~4;
207 e4a89056 bellard
    if (s->txint)
208 e4a89056 bellard
        set_txint(s);
209 e4a89056 bellard
    else
210 e4a89056 bellard
        s->rregs[2] = 6;
211 ba3c64fb bellard
    slavio_serial_update_irq(s);
212 ba3c64fb bellard
}
213 ba3c64fb bellard
214 ba3c64fb bellard
static inline void set_rxint(ChannelState *s)
215 ba3c64fb bellard
{
216 ba3c64fb bellard
    s->rxint = 1;
217 e4a89056 bellard
    if (!s->txint_under_svc) {
218 e4a89056 bellard
        s->rxint_under_svc = 1;
219 35db099d bellard
        if (s->chn == chn_a)
220 e4a89056 bellard
            s->rregs[3] |= 0x20;
221 35db099d bellard
        else
222 e4a89056 bellard
            s->otherchn->rregs[3] |= 4;
223 e4a89056 bellard
        s->rregs[2] = 4;
224 e4a89056 bellard
        slavio_serial_update_irq(s);
225 ba3c64fb bellard
    }
226 ba3c64fb bellard
}
227 ba3c64fb bellard
228 ba3c64fb bellard
static inline void clr_txint(ChannelState *s)
229 ba3c64fb bellard
{
230 ba3c64fb bellard
    s->txint = 0;
231 e4a89056 bellard
    s->txint_under_svc = 0;
232 35db099d bellard
    if (s->chn == chn_a)
233 ba3c64fb bellard
        s->rregs[3] &= ~0x10;
234 35db099d bellard
    else
235 ba3c64fb bellard
        s->otherchn->rregs[3] &= ~2;
236 e4a89056 bellard
    if (s->rxint)
237 e4a89056 bellard
        set_rxint(s);
238 e4a89056 bellard
    else
239 e4a89056 bellard
        s->rregs[2] = 6;
240 ba3c64fb bellard
    slavio_serial_update_irq(s);
241 ba3c64fb bellard
}
242 ba3c64fb bellard
243 ba3c64fb bellard
static inline void set_txint(ChannelState *s)
244 ba3c64fb bellard
{
245 ba3c64fb bellard
    s->txint = 1;
246 e4a89056 bellard
    if (!s->rxint_under_svc) {
247 e4a89056 bellard
        s->txint_under_svc = 1;
248 35db099d bellard
        if (s->chn == chn_a)
249 e4a89056 bellard
            s->rregs[3] |= 0x10;
250 35db099d bellard
        else
251 e4a89056 bellard
            s->otherchn->rregs[3] |= 2;
252 e4a89056 bellard
        s->rregs[2] = 0;
253 e4a89056 bellard
        slavio_serial_update_irq(s);
254 ba3c64fb bellard
    }
255 ba3c64fb bellard
}
256 ba3c64fb bellard
257 35db099d bellard
static void slavio_serial_update_parameters(ChannelState *s)
258 35db099d bellard
{
259 35db099d bellard
    int speed, parity, data_bits, stop_bits;
260 35db099d bellard
    QEMUSerialSetParams ssp;
261 35db099d bellard
262 35db099d bellard
    if (!s->chr || s->type != ser)
263 35db099d bellard
        return;
264 35db099d bellard
265 35db099d bellard
    if (s->wregs[4] & 1) {
266 35db099d bellard
        if (s->wregs[4] & 2)
267 35db099d bellard
            parity = 'E';
268 35db099d bellard
        else
269 35db099d bellard
            parity = 'O';
270 35db099d bellard
    } else {
271 35db099d bellard
        parity = 'N';
272 35db099d bellard
    }
273 35db099d bellard
    if ((s->wregs[4] & 0x0c) == 0x0c)
274 35db099d bellard
        stop_bits = 2;
275 35db099d bellard
    else
276 35db099d bellard
        stop_bits = 1;
277 35db099d bellard
    switch (s->wregs[5] & 0x60) {
278 35db099d bellard
    case 0x00:
279 35db099d bellard
        data_bits = 5;
280 35db099d bellard
        break;
281 35db099d bellard
    case 0x20:
282 35db099d bellard
        data_bits = 7;
283 35db099d bellard
        break;
284 35db099d bellard
    case 0x40:
285 35db099d bellard
        data_bits = 6;
286 35db099d bellard
        break;
287 35db099d bellard
    default:
288 35db099d bellard
    case 0x60:
289 35db099d bellard
        data_bits = 8;
290 35db099d bellard
        break;
291 35db099d bellard
    }
292 35db099d bellard
    speed = 2457600 / ((s->wregs[12] | (s->wregs[13] << 8)) + 2);
293 35db099d bellard
    switch (s->wregs[4] & 0xc0) {
294 35db099d bellard
    case 0x00:
295 35db099d bellard
        break;
296 35db099d bellard
    case 0x40:
297 35db099d bellard
        speed /= 16;
298 35db099d bellard
        break;
299 35db099d bellard
    case 0x80:
300 35db099d bellard
        speed /= 32;
301 35db099d bellard
        break;
302 35db099d bellard
    default:
303 35db099d bellard
    case 0xc0:
304 35db099d bellard
        speed /= 64;
305 35db099d bellard
        break;
306 35db099d bellard
    }
307 35db099d bellard
    ssp.speed = speed;
308 35db099d bellard
    ssp.parity = parity;
309 35db099d bellard
    ssp.data_bits = data_bits;
310 35db099d bellard
    ssp.stop_bits = stop_bits;
311 35db099d bellard
    SER_DPRINTF("channel %c: speed=%d parity=%c data=%d stop=%d\n", CHN_C(s),
312 35db099d bellard
                speed, parity, data_bits, stop_bits);
313 35db099d bellard
    qemu_chr_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
314 35db099d bellard
}
315 35db099d bellard
316 3a5c3138 bellard
static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
317 e80cfcfc bellard
{
318 e80cfcfc bellard
    SerialState *ser = opaque;
319 e80cfcfc bellard
    ChannelState *s;
320 e80cfcfc bellard
    uint32_t saddr;
321 e80cfcfc bellard
    int newreg, channel;
322 e80cfcfc bellard
323 e80cfcfc bellard
    val &= 0xff;
324 e80cfcfc bellard
    saddr = (addr & 3) >> 1;
325 e80cfcfc bellard
    channel = (addr & SERIAL_MAXADDR) >> 2;
326 e80cfcfc bellard
    s = &ser->chn[channel];
327 e80cfcfc bellard
    switch (saddr) {
328 e80cfcfc bellard
    case 0:
329 35db099d bellard
        SER_DPRINTF("Write channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg, val & 0xff);
330 e80cfcfc bellard
        newreg = 0;
331 e80cfcfc bellard
        switch (s->reg) {
332 e80cfcfc bellard
        case 0:
333 e80cfcfc bellard
            newreg = val & 7;
334 e80cfcfc bellard
            val &= 0x38;
335 e80cfcfc bellard
            switch (val) {
336 e80cfcfc bellard
            case 8:
337 f69a8695 bellard
                newreg |= 0x8;
338 e80cfcfc bellard
                break;
339 e80cfcfc bellard
            case 0x28:
340 ba3c64fb bellard
                clr_txint(s);
341 ba3c64fb bellard
                break;
342 ba3c64fb bellard
            case 0x38:
343 e4a89056 bellard
                if (s->rxint_under_svc)
344 e4a89056 bellard
                    clr_rxint(s);
345 e4a89056 bellard
                else if (s->txint_under_svc)
346 e4a89056 bellard
                    clr_txint(s);
347 e80cfcfc bellard
                break;
348 e80cfcfc bellard
            default:
349 e80cfcfc bellard
                break;
350 e80cfcfc bellard
            }
351 e80cfcfc bellard
            break;
352 35db099d bellard
        case 1 ... 3:
353 35db099d bellard
        case 6 ... 8:
354 35db099d bellard
        case 10 ... 11:
355 35db099d bellard
        case 14 ... 15:
356 35db099d bellard
            s->wregs[s->reg] = val;
357 35db099d bellard
            break;
358 35db099d bellard
        case 4:
359 35db099d bellard
        case 5:
360 35db099d bellard
        case 12:
361 35db099d bellard
        case 13:
362 e80cfcfc bellard
            s->wregs[s->reg] = val;
363 35db099d bellard
            slavio_serial_update_parameters(s);
364 e80cfcfc bellard
            break;
365 e80cfcfc bellard
        case 9:
366 e80cfcfc bellard
            switch (val & 0xc0) {
367 e80cfcfc bellard
            case 0:
368 e80cfcfc bellard
            default:
369 e80cfcfc bellard
                break;
370 e80cfcfc bellard
            case 0x40:
371 e80cfcfc bellard
                slavio_serial_reset_chn(&ser->chn[1]);
372 e80cfcfc bellard
                return;
373 e80cfcfc bellard
            case 0x80:
374 e80cfcfc bellard
                slavio_serial_reset_chn(&ser->chn[0]);
375 e80cfcfc bellard
                return;
376 e80cfcfc bellard
            case 0xc0:
377 e80cfcfc bellard
                slavio_serial_reset(ser);
378 e80cfcfc bellard
                return;
379 e80cfcfc bellard
            }
380 e80cfcfc bellard
            break;
381 e80cfcfc bellard
        default:
382 e80cfcfc bellard
            break;
383 e80cfcfc bellard
        }
384 e80cfcfc bellard
        if (s->reg == 0)
385 e80cfcfc bellard
            s->reg = newreg;
386 e80cfcfc bellard
        else
387 e80cfcfc bellard
            s->reg = 0;
388 e80cfcfc bellard
        break;
389 e80cfcfc bellard
    case 1:
390 35db099d bellard
        SER_DPRINTF("Write channel %c, ch %d\n", CHN_C(s), val);
391 e80cfcfc bellard
        if (s->wregs[5] & 8) { // tx enabled
392 e80cfcfc bellard
            s->tx = val;
393 e80cfcfc bellard
            if (s->chr)
394 e80cfcfc bellard
                qemu_chr_write(s->chr, &s->tx, 1);
395 8be1f5c8 bellard
            else if (s->type == kbd) {
396 8be1f5c8 bellard
                handle_kbd_command(s, val);
397 8be1f5c8 bellard
            }
398 f69a8695 bellard
            s->rregs[0] |= 4; // Tx buffer empty
399 f69a8695 bellard
            s->rregs[1] |= 1; // All sent
400 ba3c64fb bellard
            set_txint(s);
401 e80cfcfc bellard
        }
402 e80cfcfc bellard
        break;
403 e80cfcfc bellard
    default:
404 e80cfcfc bellard
        break;
405 e80cfcfc bellard
    }
406 e80cfcfc bellard
}
407 e80cfcfc bellard
408 3a5c3138 bellard
static uint32_t slavio_serial_mem_readb(void *opaque, target_phys_addr_t addr)
409 e80cfcfc bellard
{
410 e80cfcfc bellard
    SerialState *ser = opaque;
411 e80cfcfc bellard
    ChannelState *s;
412 e80cfcfc bellard
    uint32_t saddr;
413 e80cfcfc bellard
    uint32_t ret;
414 e80cfcfc bellard
    int channel;
415 e80cfcfc bellard
416 e80cfcfc bellard
    saddr = (addr & 3) >> 1;
417 e80cfcfc bellard
    channel = (addr & SERIAL_MAXADDR) >> 2;
418 e80cfcfc bellard
    s = &ser->chn[channel];
419 e80cfcfc bellard
    switch (saddr) {
420 e80cfcfc bellard
    case 0:
421 35db099d bellard
        SER_DPRINTF("Read channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg, s->rregs[s->reg]);
422 e80cfcfc bellard
        ret = s->rregs[s->reg];
423 e80cfcfc bellard
        s->reg = 0;
424 e80cfcfc bellard
        return ret;
425 e80cfcfc bellard
    case 1:
426 e80cfcfc bellard
        s->rregs[0] &= ~1;
427 ba3c64fb bellard
        clr_rxint(s);
428 715748fa bellard
        if (s->type == kbd || s->type == mouse)
429 8be1f5c8 bellard
            ret = get_queue(s);
430 8be1f5c8 bellard
        else
431 8be1f5c8 bellard
            ret = s->rx;
432 35db099d bellard
        SER_DPRINTF("Read channel %c, ch %d\n", CHN_C(s), ret);
433 8be1f5c8 bellard
        return ret;
434 e80cfcfc bellard
    default:
435 e80cfcfc bellard
        break;
436 e80cfcfc bellard
    }
437 e80cfcfc bellard
    return 0;
438 e80cfcfc bellard
}
439 e80cfcfc bellard
440 e80cfcfc bellard
static int serial_can_receive(void *opaque)
441 e80cfcfc bellard
{
442 e80cfcfc bellard
    ChannelState *s = opaque;
443 e4a89056 bellard
    int ret;
444 e4a89056 bellard
445 e80cfcfc bellard
    if (((s->wregs[3] & 1) == 0) // Rx not enabled
446 e80cfcfc bellard
        || ((s->rregs[0] & 1) == 1)) // char already available
447 e4a89056 bellard
        ret = 0;
448 e80cfcfc bellard
    else
449 e4a89056 bellard
        ret = 1;
450 35db099d bellard
    //SER_DPRINTF("channel %c can receive %d\n", CHN_C(s), ret);
451 e4a89056 bellard
    return ret;
452 e80cfcfc bellard
}
453 e80cfcfc bellard
454 e80cfcfc bellard
static void serial_receive_byte(ChannelState *s, int ch)
455 e80cfcfc bellard
{
456 35db099d bellard
    SER_DPRINTF("channel %c put ch %d\n", CHN_C(s), ch);
457 e80cfcfc bellard
    s->rregs[0] |= 1;
458 e80cfcfc bellard
    s->rx = ch;
459 ba3c64fb bellard
    set_rxint(s);
460 e80cfcfc bellard
}
461 e80cfcfc bellard
462 e80cfcfc bellard
static void serial_receive_break(ChannelState *s)
463 e80cfcfc bellard
{
464 e80cfcfc bellard
    s->rregs[0] |= 0x80;
465 e80cfcfc bellard
    slavio_serial_update_irq(s);
466 e80cfcfc bellard
}
467 e80cfcfc bellard
468 e80cfcfc bellard
static void serial_receive1(void *opaque, const uint8_t *buf, int size)
469 e80cfcfc bellard
{
470 e80cfcfc bellard
    ChannelState *s = opaque;
471 e80cfcfc bellard
    serial_receive_byte(s, buf[0]);
472 e80cfcfc bellard
}
473 e80cfcfc bellard
474 e80cfcfc bellard
static void serial_event(void *opaque, int event)
475 e80cfcfc bellard
{
476 e80cfcfc bellard
    ChannelState *s = opaque;
477 e80cfcfc bellard
    if (event == CHR_EVENT_BREAK)
478 e80cfcfc bellard
        serial_receive_break(s);
479 e80cfcfc bellard
}
480 e80cfcfc bellard
481 e80cfcfc bellard
static CPUReadMemoryFunc *slavio_serial_mem_read[3] = {
482 e80cfcfc bellard
    slavio_serial_mem_readb,
483 e80cfcfc bellard
    slavio_serial_mem_readb,
484 e80cfcfc bellard
    slavio_serial_mem_readb,
485 e80cfcfc bellard
};
486 e80cfcfc bellard
487 e80cfcfc bellard
static CPUWriteMemoryFunc *slavio_serial_mem_write[3] = {
488 e80cfcfc bellard
    slavio_serial_mem_writeb,
489 e80cfcfc bellard
    slavio_serial_mem_writeb,
490 e80cfcfc bellard
    slavio_serial_mem_writeb,
491 e80cfcfc bellard
};
492 e80cfcfc bellard
493 e80cfcfc bellard
static void slavio_serial_save_chn(QEMUFile *f, ChannelState *s)
494 e80cfcfc bellard
{
495 e80cfcfc bellard
    qemu_put_be32s(f, &s->irq);
496 e80cfcfc bellard
    qemu_put_be32s(f, &s->reg);
497 e80cfcfc bellard
    qemu_put_be32s(f, &s->rxint);
498 e80cfcfc bellard
    qemu_put_be32s(f, &s->txint);
499 e4a89056 bellard
    qemu_put_be32s(f, &s->rxint_under_svc);
500 e4a89056 bellard
    qemu_put_be32s(f, &s->txint_under_svc);
501 e80cfcfc bellard
    qemu_put_8s(f, &s->rx);
502 e80cfcfc bellard
    qemu_put_8s(f, &s->tx);
503 e80cfcfc bellard
    qemu_put_buffer(f, s->wregs, 16);
504 e80cfcfc bellard
    qemu_put_buffer(f, s->rregs, 16);
505 e80cfcfc bellard
}
506 e80cfcfc bellard
507 e80cfcfc bellard
static void slavio_serial_save(QEMUFile *f, void *opaque)
508 e80cfcfc bellard
{
509 e80cfcfc bellard
    SerialState *s = opaque;
510 e80cfcfc bellard
511 e80cfcfc bellard
    slavio_serial_save_chn(f, &s->chn[0]);
512 e80cfcfc bellard
    slavio_serial_save_chn(f, &s->chn[1]);
513 e80cfcfc bellard
}
514 e80cfcfc bellard
515 e80cfcfc bellard
static int slavio_serial_load_chn(QEMUFile *f, ChannelState *s, int version_id)
516 e80cfcfc bellard
{
517 e4a89056 bellard
    if (version_id > 2)
518 e80cfcfc bellard
        return -EINVAL;
519 e80cfcfc bellard
520 e80cfcfc bellard
    qemu_get_be32s(f, &s->irq);
521 e80cfcfc bellard
    qemu_get_be32s(f, &s->reg);
522 e80cfcfc bellard
    qemu_get_be32s(f, &s->rxint);
523 e80cfcfc bellard
    qemu_get_be32s(f, &s->txint);
524 e4a89056 bellard
    if (version_id >= 2) {
525 e4a89056 bellard
        qemu_get_be32s(f, &s->rxint_under_svc);
526 e4a89056 bellard
        qemu_get_be32s(f, &s->txint_under_svc);
527 e4a89056 bellard
    }
528 e80cfcfc bellard
    qemu_get_8s(f, &s->rx);
529 e80cfcfc bellard
    qemu_get_8s(f, &s->tx);
530 e80cfcfc bellard
    qemu_get_buffer(f, s->wregs, 16);
531 e80cfcfc bellard
    qemu_get_buffer(f, s->rregs, 16);
532 e80cfcfc bellard
    return 0;
533 e80cfcfc bellard
}
534 e80cfcfc bellard
535 e80cfcfc bellard
static int slavio_serial_load(QEMUFile *f, void *opaque, int version_id)
536 e80cfcfc bellard
{
537 e80cfcfc bellard
    SerialState *s = opaque;
538 e80cfcfc bellard
    int ret;
539 e80cfcfc bellard
540 e80cfcfc bellard
    ret = slavio_serial_load_chn(f, &s->chn[0], version_id);
541 e80cfcfc bellard
    if (ret != 0)
542 e80cfcfc bellard
        return ret;
543 e80cfcfc bellard
    ret = slavio_serial_load_chn(f, &s->chn[1], version_id);
544 e80cfcfc bellard
    return ret;
545 e80cfcfc bellard
546 e80cfcfc bellard
}
547 e80cfcfc bellard
548 e80cfcfc bellard
SerialState *slavio_serial_init(int base, int irq, CharDriverState *chr1, CharDriverState *chr2)
549 e80cfcfc bellard
{
550 8be1f5c8 bellard
    int slavio_serial_io_memory, i;
551 e80cfcfc bellard
    SerialState *s;
552 e80cfcfc bellard
553 e80cfcfc bellard
    s = qemu_mallocz(sizeof(SerialState));
554 e80cfcfc bellard
    if (!s)
555 e80cfcfc bellard
        return NULL;
556 e80cfcfc bellard
557 e80cfcfc bellard
    slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read, slavio_serial_mem_write, s);
558 e80cfcfc bellard
    cpu_register_physical_memory(base, SERIAL_MAXADDR, slavio_serial_io_memory);
559 e80cfcfc bellard
560 8be1f5c8 bellard
    s->chn[0].chr = chr1;
561 8be1f5c8 bellard
    s->chn[1].chr = chr2;
562 8be1f5c8 bellard
563 8be1f5c8 bellard
    for (i = 0; i < 2; i++) {
564 8be1f5c8 bellard
        s->chn[i].irq = irq;
565 8be1f5c8 bellard
        s->chn[i].chn = 1 - i;
566 8be1f5c8 bellard
        s->chn[i].type = ser;
567 8be1f5c8 bellard
        if (s->chn[i].chr) {
568 8be1f5c8 bellard
            qemu_chr_add_read_handler(s->chn[i].chr, serial_can_receive, serial_receive1, &s->chn[i]);
569 8be1f5c8 bellard
            qemu_chr_add_event_handler(s->chn[i].chr, serial_event);
570 8be1f5c8 bellard
        }
571 e80cfcfc bellard
    }
572 8be1f5c8 bellard
    s->chn[0].otherchn = &s->chn[1];
573 8be1f5c8 bellard
    s->chn[1].otherchn = &s->chn[0];
574 e4a89056 bellard
    register_savevm("slavio_serial", base, 2, slavio_serial_save, slavio_serial_load, s);
575 e80cfcfc bellard
    qemu_register_reset(slavio_serial_reset, s);
576 e80cfcfc bellard
    slavio_serial_reset(s);
577 e80cfcfc bellard
    return s;
578 e80cfcfc bellard
}
579 e80cfcfc bellard
580 8be1f5c8 bellard
static const uint8_t keycodes[128] = {
581 8be1f5c8 bellard
    127, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 43, 53,
582 8be1f5c8 bellard
    54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 89, 76, 77, 78,
583 8be1f5c8 bellard
    79, 80, 81, 82, 83, 84, 85, 86, 87, 42, 99, 88, 100, 101, 102, 103,
584 8be1f5c8 bellard
    104, 105, 106, 107, 108, 109, 110, 47, 19, 121, 119, 5, 6, 8, 10, 12,
585 8be1f5c8 bellard
    14, 16, 17, 18, 7, 98, 23, 68, 69, 70, 71, 91, 92, 93, 125, 112,
586 8be1f5c8 bellard
    113, 114, 94, 50, 0, 0, 124, 9, 11, 0, 0, 0, 0, 0, 0, 0,
587 8be1f5c8 bellard
    90, 0, 46, 22, 13, 111, 52, 20, 96, 24, 28, 74, 27, 123, 44, 66,
588 8be1f5c8 bellard
    0, 45, 2, 4, 48, 0, 0, 21, 0, 0, 0, 0, 0, 120, 122, 67,
589 8be1f5c8 bellard
};
590 8be1f5c8 bellard
591 e80cfcfc bellard
static void sunkbd_event(void *opaque, int ch)
592 e80cfcfc bellard
{
593 e80cfcfc bellard
    ChannelState *s = opaque;
594 8be1f5c8 bellard
    int release = ch & 0x80;
595 8be1f5c8 bellard
596 8be1f5c8 bellard
    ch = keycodes[ch & 0x7f];
597 8be1f5c8 bellard
    KBD_DPRINTF("Keycode %d (%s)\n", ch, release? "release" : "press");
598 8be1f5c8 bellard
    put_queue(s, ch | release);
599 8be1f5c8 bellard
}
600 8be1f5c8 bellard
601 8be1f5c8 bellard
static void handle_kbd_command(ChannelState *s, int val)
602 8be1f5c8 bellard
{
603 8be1f5c8 bellard
    KBD_DPRINTF("Command %d\n", val);
604 8be1f5c8 bellard
    switch (val) {
605 8be1f5c8 bellard
    case 1: // Reset, return type code
606 8be1f5c8 bellard
        put_queue(s, 0xff);
607 8be1f5c8 bellard
        put_queue(s, 5); // Type 5
608 8be1f5c8 bellard
        break;
609 8be1f5c8 bellard
    case 7: // Query layout
610 8be1f5c8 bellard
        put_queue(s, 0xfe);
611 8be1f5c8 bellard
        put_queue(s, 0x20); // XXX, layout?
612 8be1f5c8 bellard
        break;
613 8be1f5c8 bellard
    default:
614 8be1f5c8 bellard
        break;
615 8be1f5c8 bellard
    }
616 e80cfcfc bellard
}
617 e80cfcfc bellard
618 e80cfcfc bellard
static void sunmouse_event(void *opaque, 
619 e80cfcfc bellard
                               int dx, int dy, int dz, int buttons_state)
620 e80cfcfc bellard
{
621 e80cfcfc bellard
    ChannelState *s = opaque;
622 e80cfcfc bellard
    int ch;
623 e80cfcfc bellard
624 e4a89056 bellard
    /* XXX: SDL sometimes generates nul events: we delete them */
625 e4a89056 bellard
    if (dx == 0 && dy == 0 && dz == 0 && buttons_state == 0)
626 e4a89056 bellard
        return;
627 715748fa bellard
    MS_DPRINTF("dx=%d dy=%d buttons=%01x\n", dx, dy, buttons_state);
628 715748fa bellard
629 715748fa bellard
    ch = 0x80 | 0x7; /* protocol start byte, no buttons pressed */
630 715748fa bellard
631 715748fa bellard
    if (buttons_state & MOUSE_EVENT_LBUTTON)
632 715748fa bellard
        ch ^= 0x4;
633 715748fa bellard
    if (buttons_state & MOUSE_EVENT_MBUTTON)
634 715748fa bellard
        ch ^= 0x2;
635 715748fa bellard
    if (buttons_state & MOUSE_EVENT_RBUTTON)
636 715748fa bellard
        ch ^= 0x1;
637 715748fa bellard
638 715748fa bellard
    put_queue(s, ch);
639 715748fa bellard
640 715748fa bellard
    ch = dx;
641 715748fa bellard
642 715748fa bellard
    if (ch > 127)
643 715748fa bellard
        ch=127;
644 715748fa bellard
    else if (ch < -127)
645 715748fa bellard
        ch=-127;
646 715748fa bellard
647 715748fa bellard
    put_queue(s, ch & 0xff);
648 715748fa bellard
649 715748fa bellard
    ch = -dy;
650 715748fa bellard
651 715748fa bellard
    if (ch > 127)
652 715748fa bellard
        ch=127;
653 715748fa bellard
    else if (ch < -127)
654 715748fa bellard
        ch=-127;
655 715748fa bellard
656 715748fa bellard
    put_queue(s, ch & 0xff);
657 715748fa bellard
658 715748fa bellard
    // MSC protocol specify two extra motion bytes
659 715748fa bellard
660 715748fa bellard
    put_queue(s, 0);
661 715748fa bellard
    put_queue(s, 0);
662 e80cfcfc bellard
}
663 e80cfcfc bellard
664 e80cfcfc bellard
void slavio_serial_ms_kbd_init(int base, int irq)
665 e80cfcfc bellard
{
666 8be1f5c8 bellard
    int slavio_serial_io_memory, i;
667 e80cfcfc bellard
    SerialState *s;
668 e80cfcfc bellard
669 e80cfcfc bellard
    s = qemu_mallocz(sizeof(SerialState));
670 e80cfcfc bellard
    if (!s)
671 e80cfcfc bellard
        return;
672 8be1f5c8 bellard
    for (i = 0; i < 2; i++) {
673 8be1f5c8 bellard
        s->chn[i].irq = irq;
674 8be1f5c8 bellard
        s->chn[i].chn = 1 - i;
675 8be1f5c8 bellard
        s->chn[i].chr = NULL;
676 8be1f5c8 bellard
    }
677 8be1f5c8 bellard
    s->chn[0].otherchn = &s->chn[1];
678 8be1f5c8 bellard
    s->chn[1].otherchn = &s->chn[0];
679 8be1f5c8 bellard
    s->chn[0].type = mouse;
680 8be1f5c8 bellard
    s->chn[1].type = kbd;
681 e80cfcfc bellard
682 e80cfcfc bellard
    slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read, slavio_serial_mem_write, s);
683 e80cfcfc bellard
    cpu_register_physical_memory(base, SERIAL_MAXADDR, slavio_serial_io_memory);
684 e80cfcfc bellard
685 ffcdb539 bellard
    qemu_add_mouse_event_handler(sunmouse_event, &s->chn[0], 0);
686 8be1f5c8 bellard
    qemu_add_kbd_event_handler(sunkbd_event, &s->chn[1]);
687 e80cfcfc bellard
    qemu_register_reset(slavio_serial_reset, s);
688 e80cfcfc bellard
    slavio_serial_reset(s);
689 e80cfcfc bellard
}