Statistics
| Branch: | Revision:

root / hw / slavio_serial.c @ 2bac6019

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