Statistics
| Branch: | Revision:

root / hw / slavio_serial.c @ 5fafdf24

History | View | Annotate | Download (17.9 kB)

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