Statistics
| Branch: | Revision:

root / hw / slavio_serial.c @ c6d86a33

History | View | Annotate | Download (24.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 87ecb68b pbrook
#include "hw.h"
25 87ecb68b pbrook
#include "sun4m.h"
26 87ecb68b pbrook
#include "qemu-char.h"
27 87ecb68b pbrook
#include "console.h"
28 87ecb68b pbrook
29 8be1f5c8 bellard
/* debug serial */
30 e80cfcfc bellard
//#define DEBUG_SERIAL
31 e80cfcfc bellard
32 e80cfcfc bellard
/* debug keyboard */
33 e80cfcfc bellard
//#define DEBUG_KBD
34 e80cfcfc bellard
35 8be1f5c8 bellard
/* debug mouse */
36 e80cfcfc bellard
//#define DEBUG_MOUSE
37 e80cfcfc bellard
38 e80cfcfc bellard
/*
39 e80cfcfc bellard
 * This is the serial port, mouse and keyboard part of chip STP2001
40 e80cfcfc bellard
 * (Slave I/O), also produced as NCR89C105. See
41 e80cfcfc bellard
 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
42 5fafdf24 ths
 *
43 e80cfcfc bellard
 * The serial ports implement full AMD AM8530 or Zilog Z8530 chips,
44 e80cfcfc bellard
 * mouse and keyboard ports don't implement all functions and they are
45 e80cfcfc bellard
 * only asynchronous. There is no DMA.
46 e80cfcfc bellard
 *
47 e80cfcfc bellard
 */
48 e80cfcfc bellard
49 715748fa bellard
/*
50 715748fa bellard
 * Modifications:
51 715748fa bellard
 *  2006-Aug-10  Igor Kovalenko :   Renamed KBDQueue to SERIOQueue, implemented
52 715748fa bellard
 *                                  serial mouse queue.
53 715748fa bellard
 *                                  Implemented serial mouse protocol.
54 715748fa bellard
 */
55 715748fa bellard
56 8be1f5c8 bellard
#ifdef DEBUG_SERIAL
57 8be1f5c8 bellard
#define SER_DPRINTF(fmt, args...) \
58 8be1f5c8 bellard
do { printf("SER: " fmt , ##args); } while (0)
59 8be1f5c8 bellard
#else
60 8be1f5c8 bellard
#define SER_DPRINTF(fmt, args...)
61 8be1f5c8 bellard
#endif
62 8be1f5c8 bellard
#ifdef DEBUG_KBD
63 8be1f5c8 bellard
#define KBD_DPRINTF(fmt, args...) \
64 8be1f5c8 bellard
do { printf("KBD: " fmt , ##args); } while (0)
65 8be1f5c8 bellard
#else
66 8be1f5c8 bellard
#define KBD_DPRINTF(fmt, args...)
67 8be1f5c8 bellard
#endif
68 8be1f5c8 bellard
#ifdef DEBUG_MOUSE
69 8be1f5c8 bellard
#define MS_DPRINTF(fmt, args...) \
70 715748fa bellard
do { printf("MSC: " fmt , ##args); } while (0)
71 8be1f5c8 bellard
#else
72 8be1f5c8 bellard
#define MS_DPRINTF(fmt, args...)
73 8be1f5c8 bellard
#endif
74 8be1f5c8 bellard
75 8be1f5c8 bellard
typedef enum {
76 8be1f5c8 bellard
    chn_a, chn_b,
77 8be1f5c8 bellard
} chn_id_t;
78 8be1f5c8 bellard
79 35db099d bellard
#define CHN_C(s) ((s)->chn == chn_b? 'b' : 'a')
80 35db099d bellard
81 8be1f5c8 bellard
typedef enum {
82 8be1f5c8 bellard
    ser, kbd, mouse,
83 8be1f5c8 bellard
} chn_type_t;
84 8be1f5c8 bellard
85 715748fa bellard
#define SERIO_QUEUE_SIZE 256
86 8be1f5c8 bellard
87 8be1f5c8 bellard
typedef struct {
88 715748fa bellard
    uint8_t data[SERIO_QUEUE_SIZE];
89 8be1f5c8 bellard
    int rptr, wptr, count;
90 715748fa bellard
} SERIOQueue;
91 8be1f5c8 bellard
92 12abac85 blueswir1
#define SERIAL_REGS 16
93 e80cfcfc bellard
typedef struct ChannelState {
94 d537cf6c pbrook
    qemu_irq irq;
95 22548760 blueswir1
    uint32_t reg;
96 22548760 blueswir1
    uint32_t rxint, txint, rxint_under_svc, txint_under_svc;
97 8be1f5c8 bellard
    chn_id_t chn; // this channel, A (base+4) or B (base+0)
98 8be1f5c8 bellard
    chn_type_t type;
99 8be1f5c8 bellard
    struct ChannelState *otherchn;
100 12abac85 blueswir1
    uint8_t rx, tx, wregs[SERIAL_REGS], rregs[SERIAL_REGS];
101 715748fa bellard
    SERIOQueue queue;
102 e80cfcfc bellard
    CharDriverState *chr;
103 bbbb2f0a blueswir1
    int e0_mode, led_mode, caps_lock_mode, num_lock_mode;
104 577390ff blueswir1
    int disabled;
105 e80cfcfc bellard
} ChannelState;
106 e80cfcfc bellard
107 e80cfcfc bellard
struct SerialState {
108 e80cfcfc bellard
    struct ChannelState chn[2];
109 e80cfcfc bellard
};
110 e80cfcfc bellard
111 e64d7d59 blueswir1
#define SERIAL_SIZE 8
112 12abac85 blueswir1
#define SERIAL_CTRL 0
113 12abac85 blueswir1
#define SERIAL_DATA 1
114 12abac85 blueswir1
115 12abac85 blueswir1
#define W_CMD     0
116 12abac85 blueswir1
#define CMD_PTR_MASK   0x07
117 12abac85 blueswir1
#define CMD_CMD_MASK   0x38
118 12abac85 blueswir1
#define CMD_HI         0x08
119 12abac85 blueswir1
#define CMD_CLR_TXINT  0x28
120 12abac85 blueswir1
#define CMD_CLR_IUS    0x38
121 12abac85 blueswir1
#define W_INTR    1
122 12abac85 blueswir1
#define INTR_INTALL    0x01
123 12abac85 blueswir1
#define INTR_TXINT     0x02
124 12abac85 blueswir1
#define INTR_RXMODEMSK 0x18
125 12abac85 blueswir1
#define INTR_RXINT1ST  0x08
126 12abac85 blueswir1
#define INTR_RXINTALL  0x10
127 12abac85 blueswir1
#define W_IVEC    2
128 12abac85 blueswir1
#define W_RXCTRL  3
129 12abac85 blueswir1
#define RXCTRL_RXEN    0x01
130 12abac85 blueswir1
#define W_TXCTRL1 4
131 12abac85 blueswir1
#define TXCTRL1_PAREN  0x01
132 12abac85 blueswir1
#define TXCTRL1_PAREV  0x02
133 12abac85 blueswir1
#define TXCTRL1_1STOP  0x04
134 12abac85 blueswir1
#define TXCTRL1_1HSTOP 0x08
135 12abac85 blueswir1
#define TXCTRL1_2STOP  0x0c
136 12abac85 blueswir1
#define TXCTRL1_STPMSK 0x0c
137 12abac85 blueswir1
#define TXCTRL1_CLK1X  0x00
138 12abac85 blueswir1
#define TXCTRL1_CLK16X 0x40
139 12abac85 blueswir1
#define TXCTRL1_CLK32X 0x80
140 12abac85 blueswir1
#define TXCTRL1_CLK64X 0xc0
141 12abac85 blueswir1
#define TXCTRL1_CLKMSK 0xc0
142 12abac85 blueswir1
#define W_TXCTRL2 5
143 12abac85 blueswir1
#define TXCTRL2_TXEN   0x08
144 12abac85 blueswir1
#define TXCTRL2_BITMSK 0x60
145 12abac85 blueswir1
#define TXCTRL2_5BITS  0x00
146 12abac85 blueswir1
#define TXCTRL2_7BITS  0x20
147 12abac85 blueswir1
#define TXCTRL2_6BITS  0x40
148 12abac85 blueswir1
#define TXCTRL2_8BITS  0x60
149 12abac85 blueswir1
#define W_SYNC1   6
150 12abac85 blueswir1
#define W_SYNC2   7
151 12abac85 blueswir1
#define W_TXBUF   8
152 12abac85 blueswir1
#define W_MINTR   9
153 12abac85 blueswir1
#define MINTR_STATUSHI 0x10
154 12abac85 blueswir1
#define MINTR_RST_MASK 0xc0
155 12abac85 blueswir1
#define MINTR_RST_B    0x40
156 12abac85 blueswir1
#define MINTR_RST_A    0x80
157 12abac85 blueswir1
#define MINTR_RST_ALL  0xc0
158 12abac85 blueswir1
#define W_MISC1  10
159 12abac85 blueswir1
#define W_CLOCK  11
160 12abac85 blueswir1
#define CLOCK_TRXC     0x08
161 12abac85 blueswir1
#define W_BRGLO  12
162 12abac85 blueswir1
#define W_BRGHI  13
163 12abac85 blueswir1
#define W_MISC2  14
164 12abac85 blueswir1
#define MISC2_PLLDIS   0x30
165 12abac85 blueswir1
#define W_EXTINT 15
166 12abac85 blueswir1
#define EXTINT_DCD     0x08
167 12abac85 blueswir1
#define EXTINT_SYNCINT 0x10
168 12abac85 blueswir1
#define EXTINT_CTSINT  0x20
169 12abac85 blueswir1
#define EXTINT_TXUNDRN 0x40
170 12abac85 blueswir1
#define EXTINT_BRKINT  0x80
171 12abac85 blueswir1
172 12abac85 blueswir1
#define R_STATUS  0
173 12abac85 blueswir1
#define STATUS_RXAV    0x01
174 12abac85 blueswir1
#define STATUS_ZERO    0x02
175 12abac85 blueswir1
#define STATUS_TXEMPTY 0x04
176 12abac85 blueswir1
#define STATUS_DCD     0x08
177 12abac85 blueswir1
#define STATUS_SYNC    0x10
178 12abac85 blueswir1
#define STATUS_CTS     0x20
179 12abac85 blueswir1
#define STATUS_TXUNDRN 0x40
180 12abac85 blueswir1
#define STATUS_BRK     0x80
181 12abac85 blueswir1
#define R_SPEC    1
182 12abac85 blueswir1
#define SPEC_ALLSENT   0x01
183 12abac85 blueswir1
#define SPEC_BITS8     0x06
184 12abac85 blueswir1
#define R_IVEC    2
185 12abac85 blueswir1
#define IVEC_TXINTB    0x00
186 12abac85 blueswir1
#define IVEC_LONOINT   0x06
187 12abac85 blueswir1
#define IVEC_LORXINTA  0x0c
188 12abac85 blueswir1
#define IVEC_LORXINTB  0x04
189 12abac85 blueswir1
#define IVEC_LOTXINTA  0x08
190 12abac85 blueswir1
#define IVEC_HINOINT   0x60
191 12abac85 blueswir1
#define IVEC_HIRXINTA  0x30
192 12abac85 blueswir1
#define IVEC_HIRXINTB  0x20
193 12abac85 blueswir1
#define IVEC_HITXINTA  0x10
194 12abac85 blueswir1
#define R_INTR    3
195 12abac85 blueswir1
#define INTR_EXTINTB   0x01
196 12abac85 blueswir1
#define INTR_TXINTB    0x02
197 12abac85 blueswir1
#define INTR_RXINTB    0x04
198 12abac85 blueswir1
#define INTR_EXTINTA   0x08
199 12abac85 blueswir1
#define INTR_TXINTA    0x10
200 12abac85 blueswir1
#define INTR_RXINTA    0x20
201 12abac85 blueswir1
#define R_IPEN    4
202 12abac85 blueswir1
#define R_TXCTRL1 5
203 12abac85 blueswir1
#define R_TXCTRL2 6
204 12abac85 blueswir1
#define R_BC      7
205 12abac85 blueswir1
#define R_RXBUF   8
206 12abac85 blueswir1
#define R_RXCTRL  9
207 12abac85 blueswir1
#define R_MISC   10
208 12abac85 blueswir1
#define R_MISC1  11
209 12abac85 blueswir1
#define R_BRGLO  12
210 12abac85 blueswir1
#define R_BRGHI  13
211 12abac85 blueswir1
#define R_MISC1I 14
212 12abac85 blueswir1
#define R_EXTINT 15
213 e80cfcfc bellard
214 8be1f5c8 bellard
static void handle_kbd_command(ChannelState *s, int val);
215 8be1f5c8 bellard
static int serial_can_receive(void *opaque);
216 8be1f5c8 bellard
static void serial_receive_byte(ChannelState *s, int ch);
217 8be1f5c8 bellard
218 67deb562 blueswir1
static void clear_queue(void *opaque)
219 67deb562 blueswir1
{
220 67deb562 blueswir1
    ChannelState *s = opaque;
221 67deb562 blueswir1
    SERIOQueue *q = &s->queue;
222 67deb562 blueswir1
    q->rptr = q->wptr = q->count = 0;
223 67deb562 blueswir1
}
224 67deb562 blueswir1
225 8be1f5c8 bellard
static void put_queue(void *opaque, int b)
226 8be1f5c8 bellard
{
227 8be1f5c8 bellard
    ChannelState *s = opaque;
228 715748fa bellard
    SERIOQueue *q = &s->queue;
229 8be1f5c8 bellard
230 35db099d bellard
    SER_DPRINTF("channel %c put: 0x%02x\n", CHN_C(s), b);
231 715748fa bellard
    if (q->count >= SERIO_QUEUE_SIZE)
232 8be1f5c8 bellard
        return;
233 8be1f5c8 bellard
    q->data[q->wptr] = b;
234 715748fa bellard
    if (++q->wptr == SERIO_QUEUE_SIZE)
235 8be1f5c8 bellard
        q->wptr = 0;
236 8be1f5c8 bellard
    q->count++;
237 8be1f5c8 bellard
    serial_receive_byte(s, 0);
238 8be1f5c8 bellard
}
239 8be1f5c8 bellard
240 8be1f5c8 bellard
static uint32_t get_queue(void *opaque)
241 8be1f5c8 bellard
{
242 8be1f5c8 bellard
    ChannelState *s = opaque;
243 715748fa bellard
    SERIOQueue *q = &s->queue;
244 8be1f5c8 bellard
    int val;
245 3b46e624 ths
246 8be1f5c8 bellard
    if (q->count == 0) {
247 f930d07e blueswir1
        return 0;
248 8be1f5c8 bellard
    } else {
249 8be1f5c8 bellard
        val = q->data[q->rptr];
250 715748fa bellard
        if (++q->rptr == SERIO_QUEUE_SIZE)
251 8be1f5c8 bellard
            q->rptr = 0;
252 8be1f5c8 bellard
        q->count--;
253 8be1f5c8 bellard
    }
254 67deb562 blueswir1
    SER_DPRINTF("channel %c get 0x%02x\n", CHN_C(s), val);
255 8be1f5c8 bellard
    if (q->count > 0)
256 f930d07e blueswir1
        serial_receive_byte(s, 0);
257 8be1f5c8 bellard
    return val;
258 8be1f5c8 bellard
}
259 8be1f5c8 bellard
260 e4a89056 bellard
static int slavio_serial_update_irq_chn(ChannelState *s)
261 e80cfcfc bellard
{
262 9277bc72 blueswir1
    if ((((s->wregs[W_INTR] & INTR_TXINT) && s->txint == 1) ||
263 12abac85 blueswir1
         // tx ints enabled, pending
264 12abac85 blueswir1
         ((((s->wregs[W_INTR] & INTR_RXMODEMSK) == INTR_RXINT1ST) ||
265 12abac85 blueswir1
           ((s->wregs[W_INTR] & INTR_RXMODEMSK) == INTR_RXINTALL)) &&
266 f930d07e blueswir1
          s->rxint == 1) || // rx ints enabled, pending
267 12abac85 blueswir1
         ((s->wregs[W_EXTINT] & EXTINT_BRKINT) &&
268 12abac85 blueswir1
          (s->rregs[R_STATUS] & STATUS_BRK)))) { // break int e&p
269 e4a89056 bellard
        return 1;
270 e80cfcfc bellard
    }
271 e4a89056 bellard
    return 0;
272 e4a89056 bellard
}
273 e4a89056 bellard
274 e4a89056 bellard
static void slavio_serial_update_irq(ChannelState *s)
275 e4a89056 bellard
{
276 e4a89056 bellard
    int irq;
277 e4a89056 bellard
278 e4a89056 bellard
    irq = slavio_serial_update_irq_chn(s);
279 e4a89056 bellard
    irq |= slavio_serial_update_irq_chn(s->otherchn);
280 e4a89056 bellard
281 d537cf6c pbrook
    SER_DPRINTF("IRQ = %d\n", irq);
282 d537cf6c pbrook
    qemu_set_irq(s->irq, irq);
283 e80cfcfc bellard
}
284 e80cfcfc bellard
285 e80cfcfc bellard
static void slavio_serial_reset_chn(ChannelState *s)
286 e80cfcfc bellard
{
287 e80cfcfc bellard
    int i;
288 e80cfcfc bellard
289 e80cfcfc bellard
    s->reg = 0;
290 5aca8c3b blueswir1
    for (i = 0; i < SERIAL_SIZE; i++) {
291 f930d07e blueswir1
        s->rregs[i] = 0;
292 f930d07e blueswir1
        s->wregs[i] = 0;
293 e80cfcfc bellard
    }
294 12abac85 blueswir1
    s->wregs[W_TXCTRL1] = TXCTRL1_1STOP; // 1X divisor, 1 stop bit, no parity
295 12abac85 blueswir1
    s->wregs[W_MINTR] = MINTR_RST_ALL;
296 12abac85 blueswir1
    s->wregs[W_CLOCK] = CLOCK_TRXC; // Synch mode tx clock = TRxC
297 12abac85 blueswir1
    s->wregs[W_MISC2] = MISC2_PLLDIS; // PLL disabled
298 12abac85 blueswir1
    s->wregs[W_EXTINT] = EXTINT_DCD | EXTINT_SYNCINT | EXTINT_CTSINT |
299 12abac85 blueswir1
        EXTINT_TXUNDRN | EXTINT_BRKINT; // Enable most interrupts
300 577390ff blueswir1
    if (s->disabled)
301 12abac85 blueswir1
        s->rregs[R_STATUS] = STATUS_TXEMPTY | STATUS_DCD | STATUS_SYNC |
302 12abac85 blueswir1
            STATUS_CTS | STATUS_TXUNDRN;
303 577390ff blueswir1
    else
304 12abac85 blueswir1
        s->rregs[R_STATUS] = STATUS_TXEMPTY | STATUS_TXUNDRN;
305 f48c537d blueswir1
    s->rregs[R_SPEC] = SPEC_BITS8 | SPEC_ALLSENT;
306 e80cfcfc bellard
307 e80cfcfc bellard
    s->rx = s->tx = 0;
308 e80cfcfc bellard
    s->rxint = s->txint = 0;
309 e4a89056 bellard
    s->rxint_under_svc = s->txint_under_svc = 0;
310 bbbb2f0a blueswir1
    s->e0_mode = s->led_mode = s->caps_lock_mode = s->num_lock_mode = 0;
311 67deb562 blueswir1
    clear_queue(s);
312 e80cfcfc bellard
}
313 e80cfcfc bellard
314 e80cfcfc bellard
static void slavio_serial_reset(void *opaque)
315 e80cfcfc bellard
{
316 e80cfcfc bellard
    SerialState *s = opaque;
317 e80cfcfc bellard
    slavio_serial_reset_chn(&s->chn[0]);
318 e80cfcfc bellard
    slavio_serial_reset_chn(&s->chn[1]);
319 e80cfcfc bellard
}
320 e80cfcfc bellard
321 ba3c64fb bellard
static inline void set_rxint(ChannelState *s)
322 ba3c64fb bellard
{
323 ba3c64fb bellard
    s->rxint = 1;
324 e4a89056 bellard
    if (!s->txint_under_svc) {
325 e4a89056 bellard
        s->rxint_under_svc = 1;
326 67deb562 blueswir1
        if (s->chn == chn_a) {
327 12abac85 blueswir1
            if (s->wregs[W_MINTR] & MINTR_STATUSHI)
328 12abac85 blueswir1
                s->otherchn->rregs[R_IVEC] = IVEC_HIRXINTA;
329 67deb562 blueswir1
            else
330 12abac85 blueswir1
                s->otherchn->rregs[R_IVEC] = IVEC_LORXINTA;
331 67deb562 blueswir1
        } else {
332 12abac85 blueswir1
            if (s->wregs[W_MINTR] & MINTR_STATUSHI)
333 12abac85 blueswir1
                s->rregs[R_IVEC] = IVEC_HIRXINTB;
334 67deb562 blueswir1
            else
335 12abac85 blueswir1
                s->rregs[R_IVEC] = IVEC_LORXINTB;
336 67deb562 blueswir1
        }
337 ba3c64fb bellard
    }
338 b9652ca3 blueswir1
    if (s->chn == chn_a)
339 12abac85 blueswir1
        s->rregs[R_INTR] |= INTR_RXINTA;
340 b9652ca3 blueswir1
    else
341 12abac85 blueswir1
        s->otherchn->rregs[R_INTR] |= INTR_RXINTB;
342 b9652ca3 blueswir1
    slavio_serial_update_irq(s);
343 ba3c64fb bellard
}
344 ba3c64fb bellard
345 80637a6a blueswir1
static inline void set_txint(ChannelState *s)
346 80637a6a blueswir1
{
347 80637a6a blueswir1
    s->txint = 1;
348 80637a6a blueswir1
    if (!s->rxint_under_svc) {
349 80637a6a blueswir1
        s->txint_under_svc = 1;
350 80637a6a blueswir1
        if (s->chn == chn_a) {
351 80637a6a blueswir1
            if (s->wregs[W_MINTR] & MINTR_STATUSHI)
352 80637a6a blueswir1
                s->otherchn->rregs[R_IVEC] = IVEC_HITXINTA;
353 80637a6a blueswir1
            else
354 80637a6a blueswir1
                s->otherchn->rregs[R_IVEC] = IVEC_LOTXINTA;
355 80637a6a blueswir1
        } else {
356 80637a6a blueswir1
            s->rregs[R_IVEC] = IVEC_TXINTB;
357 80637a6a blueswir1
        }
358 80637a6a blueswir1
    }
359 80637a6a blueswir1
    if (s->chn == chn_a)
360 80637a6a blueswir1
        s->rregs[R_INTR] |= INTR_TXINTA;
361 80637a6a blueswir1
    else
362 80637a6a blueswir1
        s->otherchn->rregs[R_INTR] |= INTR_TXINTB;
363 80637a6a blueswir1
    slavio_serial_update_irq(s);
364 80637a6a blueswir1
}
365 80637a6a blueswir1
366 80637a6a blueswir1
static inline void clr_rxint(ChannelState *s)
367 80637a6a blueswir1
{
368 80637a6a blueswir1
    s->rxint = 0;
369 80637a6a blueswir1
    s->rxint_under_svc = 0;
370 80637a6a blueswir1
    if (s->chn == chn_a) {
371 80637a6a blueswir1
        if (s->wregs[W_MINTR] & MINTR_STATUSHI)
372 80637a6a blueswir1
            s->otherchn->rregs[R_IVEC] = IVEC_HINOINT;
373 80637a6a blueswir1
        else
374 80637a6a blueswir1
            s->otherchn->rregs[R_IVEC] = IVEC_LONOINT;
375 80637a6a blueswir1
        s->rregs[R_INTR] &= ~INTR_RXINTA;
376 80637a6a blueswir1
    } else {
377 80637a6a blueswir1
        if (s->wregs[W_MINTR] & MINTR_STATUSHI)
378 80637a6a blueswir1
            s->rregs[R_IVEC] = IVEC_HINOINT;
379 80637a6a blueswir1
        else
380 80637a6a blueswir1
            s->rregs[R_IVEC] = IVEC_LONOINT;
381 80637a6a blueswir1
        s->otherchn->rregs[R_INTR] &= ~INTR_RXINTB;
382 80637a6a blueswir1
    }
383 80637a6a blueswir1
    if (s->txint)
384 80637a6a blueswir1
        set_txint(s);
385 80637a6a blueswir1
    slavio_serial_update_irq(s);
386 80637a6a blueswir1
}
387 80637a6a blueswir1
388 ba3c64fb bellard
static inline void clr_txint(ChannelState *s)
389 ba3c64fb bellard
{
390 ba3c64fb bellard
    s->txint = 0;
391 e4a89056 bellard
    s->txint_under_svc = 0;
392 b9652ca3 blueswir1
    if (s->chn == chn_a) {
393 12abac85 blueswir1
        if (s->wregs[W_MINTR] & MINTR_STATUSHI)
394 12abac85 blueswir1
            s->otherchn->rregs[R_IVEC] = IVEC_HINOINT;
395 b9652ca3 blueswir1
        else
396 12abac85 blueswir1
            s->otherchn->rregs[R_IVEC] = IVEC_LONOINT;
397 12abac85 blueswir1
        s->rregs[R_INTR] &= ~INTR_TXINTA;
398 b9652ca3 blueswir1
    } else {
399 12abac85 blueswir1
        if (s->wregs[W_MINTR] & MINTR_STATUSHI)
400 12abac85 blueswir1
            s->rregs[R_IVEC] = IVEC_HINOINT;
401 b9652ca3 blueswir1
        else
402 12abac85 blueswir1
            s->rregs[R_IVEC] = IVEC_LONOINT;
403 12abac85 blueswir1
        s->otherchn->rregs[R_INTR] &= ~INTR_TXINTB;
404 b9652ca3 blueswir1
    }
405 e4a89056 bellard
    if (s->rxint)
406 e4a89056 bellard
        set_rxint(s);
407 ba3c64fb bellard
    slavio_serial_update_irq(s);
408 ba3c64fb bellard
}
409 ba3c64fb bellard
410 35db099d bellard
static void slavio_serial_update_parameters(ChannelState *s)
411 35db099d bellard
{
412 35db099d bellard
    int speed, parity, data_bits, stop_bits;
413 35db099d bellard
    QEMUSerialSetParams ssp;
414 35db099d bellard
415 35db099d bellard
    if (!s->chr || s->type != ser)
416 35db099d bellard
        return;
417 35db099d bellard
418 12abac85 blueswir1
    if (s->wregs[W_TXCTRL1] & TXCTRL1_PAREN) {
419 12abac85 blueswir1
        if (s->wregs[W_TXCTRL1] & TXCTRL1_PAREV)
420 35db099d bellard
            parity = 'E';
421 35db099d bellard
        else
422 35db099d bellard
            parity = 'O';
423 35db099d bellard
    } else {
424 35db099d bellard
        parity = 'N';
425 35db099d bellard
    }
426 12abac85 blueswir1
    if ((s->wregs[W_TXCTRL1] & TXCTRL1_STPMSK) == TXCTRL1_2STOP)
427 35db099d bellard
        stop_bits = 2;
428 35db099d bellard
    else
429 35db099d bellard
        stop_bits = 1;
430 12abac85 blueswir1
    switch (s->wregs[W_TXCTRL2] & TXCTRL2_BITMSK) {
431 12abac85 blueswir1
    case TXCTRL2_5BITS:
432 35db099d bellard
        data_bits = 5;
433 35db099d bellard
        break;
434 12abac85 blueswir1
    case TXCTRL2_7BITS:
435 35db099d bellard
        data_bits = 7;
436 35db099d bellard
        break;
437 12abac85 blueswir1
    case TXCTRL2_6BITS:
438 35db099d bellard
        data_bits = 6;
439 35db099d bellard
        break;
440 35db099d bellard
    default:
441 12abac85 blueswir1
    case TXCTRL2_8BITS:
442 35db099d bellard
        data_bits = 8;
443 35db099d bellard
        break;
444 35db099d bellard
    }
445 12abac85 blueswir1
    speed = 2457600 / ((s->wregs[W_BRGLO] | (s->wregs[W_BRGHI] << 8)) + 2);
446 12abac85 blueswir1
    switch (s->wregs[W_TXCTRL1] & TXCTRL1_CLKMSK) {
447 12abac85 blueswir1
    case TXCTRL1_CLK1X:
448 35db099d bellard
        break;
449 12abac85 blueswir1
    case TXCTRL1_CLK16X:
450 35db099d bellard
        speed /= 16;
451 35db099d bellard
        break;
452 12abac85 blueswir1
    case TXCTRL1_CLK32X:
453 35db099d bellard
        speed /= 32;
454 35db099d bellard
        break;
455 35db099d bellard
    default:
456 12abac85 blueswir1
    case TXCTRL1_CLK64X:
457 35db099d bellard
        speed /= 64;
458 35db099d bellard
        break;
459 35db099d bellard
    }
460 35db099d bellard
    ssp.speed = speed;
461 35db099d bellard
    ssp.parity = parity;
462 35db099d bellard
    ssp.data_bits = data_bits;
463 35db099d bellard
    ssp.stop_bits = stop_bits;
464 35db099d bellard
    SER_DPRINTF("channel %c: speed=%d parity=%c data=%d stop=%d\n", CHN_C(s),
465 35db099d bellard
                speed, parity, data_bits, stop_bits);
466 35db099d bellard
    qemu_chr_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
467 35db099d bellard
}
468 35db099d bellard
469 12abac85 blueswir1
static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr,
470 12abac85 blueswir1
                                     uint32_t val)
471 e80cfcfc bellard
{
472 b3ceef24 blueswir1
    SerialState *serial = opaque;
473 e80cfcfc bellard
    ChannelState *s;
474 e80cfcfc bellard
    uint32_t saddr;
475 e80cfcfc bellard
    int newreg, channel;
476 e80cfcfc bellard
477 e80cfcfc bellard
    val &= 0xff;
478 e80cfcfc bellard
    saddr = (addr & 3) >> 1;
479 e64d7d59 blueswir1
    channel = addr >> 2;
480 b3ceef24 blueswir1
    s = &serial->chn[channel];
481 e80cfcfc bellard
    switch (saddr) {
482 12abac85 blueswir1
    case SERIAL_CTRL:
483 12abac85 blueswir1
        SER_DPRINTF("Write channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg,
484 12abac85 blueswir1
                    val & 0xff);
485 f930d07e blueswir1
        newreg = 0;
486 f930d07e blueswir1
        switch (s->reg) {
487 12abac85 blueswir1
        case W_CMD:
488 12abac85 blueswir1
            newreg = val & CMD_PTR_MASK;
489 12abac85 blueswir1
            val &= CMD_CMD_MASK;
490 f930d07e blueswir1
            switch (val) {
491 12abac85 blueswir1
            case CMD_HI:
492 12abac85 blueswir1
                newreg |= CMD_HI;
493 f930d07e blueswir1
                break;
494 12abac85 blueswir1
            case CMD_CLR_TXINT:
495 ba3c64fb bellard
                clr_txint(s);
496 f930d07e blueswir1
                break;
497 12abac85 blueswir1
            case CMD_CLR_IUS:
498 e4a89056 bellard
                if (s->rxint_under_svc)
499 e4a89056 bellard
                    clr_rxint(s);
500 e4a89056 bellard
                else if (s->txint_under_svc)
501 e4a89056 bellard
                    clr_txint(s);
502 f930d07e blueswir1
                break;
503 f930d07e blueswir1
            default:
504 f930d07e blueswir1
                break;
505 f930d07e blueswir1
            }
506 f930d07e blueswir1
            break;
507 12abac85 blueswir1
        case W_INTR ... W_RXCTRL:
508 12abac85 blueswir1
        case W_SYNC1 ... W_TXBUF:
509 12abac85 blueswir1
        case W_MISC1 ... W_CLOCK:
510 12abac85 blueswir1
        case W_MISC2 ... W_EXTINT:
511 f930d07e blueswir1
            s->wregs[s->reg] = val;
512 f930d07e blueswir1
            break;
513 12abac85 blueswir1
        case W_TXCTRL1:
514 12abac85 blueswir1
        case W_TXCTRL2:
515 796d8286 blueswir1
            s->wregs[s->reg] = val;
516 796d8286 blueswir1
            slavio_serial_update_parameters(s);
517 796d8286 blueswir1
            break;
518 12abac85 blueswir1
        case W_BRGLO:
519 12abac85 blueswir1
        case W_BRGHI:
520 f930d07e blueswir1
            s->wregs[s->reg] = val;
521 796d8286 blueswir1
            s->rregs[s->reg] = val;
522 35db099d bellard
            slavio_serial_update_parameters(s);
523 f930d07e blueswir1
            break;
524 12abac85 blueswir1
        case W_MINTR:
525 12abac85 blueswir1
            switch (val & MINTR_RST_MASK) {
526 f930d07e blueswir1
            case 0:
527 f930d07e blueswir1
            default:
528 f930d07e blueswir1
                break;
529 12abac85 blueswir1
            case MINTR_RST_B:
530 399bf6be blueswir1
                slavio_serial_reset_chn(&serial->chn[0]);
531 f930d07e blueswir1
                return;
532 12abac85 blueswir1
            case MINTR_RST_A:
533 399bf6be blueswir1
                slavio_serial_reset_chn(&serial->chn[1]);
534 f930d07e blueswir1
                return;
535 12abac85 blueswir1
            case MINTR_RST_ALL:
536 f930d07e blueswir1
                slavio_serial_reset(serial);
537 f930d07e blueswir1
                return;
538 f930d07e blueswir1
            }
539 f930d07e blueswir1
            break;
540 f930d07e blueswir1
        default:
541 f930d07e blueswir1
            break;
542 f930d07e blueswir1
        }
543 f930d07e blueswir1
        if (s->reg == 0)
544 f930d07e blueswir1
            s->reg = newreg;
545 f930d07e blueswir1
        else
546 f930d07e blueswir1
            s->reg = 0;
547 f930d07e blueswir1
        break;
548 12abac85 blueswir1
    case SERIAL_DATA:
549 f930d07e blueswir1
        SER_DPRINTF("Write channel %c, ch %d\n", CHN_C(s), val);
550 96c4f569 blueswir1
        s->tx = val;
551 12abac85 blueswir1
        if (s->wregs[W_TXCTRL2] & TXCTRL2_TXEN) { // tx enabled
552 f930d07e blueswir1
            if (s->chr)
553 f930d07e blueswir1
                qemu_chr_write(s->chr, &s->tx, 1);
554 577390ff blueswir1
            else if (s->type == kbd && !s->disabled) {
555 f930d07e blueswir1
                handle_kbd_command(s, val);
556 f930d07e blueswir1
            }
557 f930d07e blueswir1
        }
558 12abac85 blueswir1
        s->rregs[R_STATUS] |= STATUS_TXEMPTY; // Tx buffer empty
559 12abac85 blueswir1
        s->rregs[R_SPEC] |= SPEC_ALLSENT; // All sent
560 96c4f569 blueswir1
        set_txint(s);
561 f930d07e blueswir1
        break;
562 e80cfcfc bellard
    default:
563 f930d07e blueswir1
        break;
564 e80cfcfc bellard
    }
565 e80cfcfc bellard
}
566 e80cfcfc bellard
567 3a5c3138 bellard
static uint32_t slavio_serial_mem_readb(void *opaque, target_phys_addr_t addr)
568 e80cfcfc bellard
{
569 b3ceef24 blueswir1
    SerialState *serial = opaque;
570 e80cfcfc bellard
    ChannelState *s;
571 e80cfcfc bellard
    uint32_t saddr;
572 e80cfcfc bellard
    uint32_t ret;
573 e80cfcfc bellard
    int channel;
574 e80cfcfc bellard
575 e80cfcfc bellard
    saddr = (addr & 3) >> 1;
576 e64d7d59 blueswir1
    channel = addr >> 2;
577 b3ceef24 blueswir1
    s = &serial->chn[channel];
578 e80cfcfc bellard
    switch (saddr) {
579 12abac85 blueswir1
    case SERIAL_CTRL:
580 12abac85 blueswir1
        SER_DPRINTF("Read channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg,
581 12abac85 blueswir1
                    s->rregs[s->reg]);
582 f930d07e blueswir1
        ret = s->rregs[s->reg];
583 f930d07e blueswir1
        s->reg = 0;
584 f930d07e blueswir1
        return ret;
585 12abac85 blueswir1
    case SERIAL_DATA:
586 12abac85 blueswir1
        s->rregs[R_STATUS] &= ~STATUS_RXAV;
587 ba3c64fb bellard
        clr_rxint(s);
588 f930d07e blueswir1
        if (s->type == kbd || s->type == mouse)
589 f930d07e blueswir1
            ret = get_queue(s);
590 f930d07e blueswir1
        else
591 f930d07e blueswir1
            ret = s->rx;
592 f930d07e blueswir1
        SER_DPRINTF("Read channel %c, ch %d\n", CHN_C(s), ret);
593 b76482e7 blueswir1
        if (s->chr)
594 b76482e7 blueswir1
            qemu_chr_accept_input(s->chr);
595 f930d07e blueswir1
        return ret;
596 e80cfcfc bellard
    default:
597 f930d07e blueswir1
        break;
598 e80cfcfc bellard
    }
599 e80cfcfc bellard
    return 0;
600 e80cfcfc bellard
}
601 e80cfcfc bellard
602 e80cfcfc bellard
static int serial_can_receive(void *opaque)
603 e80cfcfc bellard
{
604 e80cfcfc bellard
    ChannelState *s = opaque;
605 e4a89056 bellard
    int ret;
606 e4a89056 bellard
607 12abac85 blueswir1
    if (((s->wregs[W_RXCTRL] & RXCTRL_RXEN) == 0) // Rx not enabled
608 12abac85 blueswir1
        || ((s->rregs[R_STATUS] & STATUS_RXAV) == STATUS_RXAV))
609 12abac85 blueswir1
        // char already available
610 f930d07e blueswir1
        ret = 0;
611 e80cfcfc bellard
    else
612 f930d07e blueswir1
        ret = 1;
613 e4a89056 bellard
    return ret;
614 e80cfcfc bellard
}
615 e80cfcfc bellard
616 e80cfcfc bellard
static void serial_receive_byte(ChannelState *s, int ch)
617 e80cfcfc bellard
{
618 35db099d bellard
    SER_DPRINTF("channel %c put ch %d\n", CHN_C(s), ch);
619 12abac85 blueswir1
    s->rregs[R_STATUS] |= STATUS_RXAV;
620 e80cfcfc bellard
    s->rx = ch;
621 ba3c64fb bellard
    set_rxint(s);
622 e80cfcfc bellard
}
623 e80cfcfc bellard
624 e80cfcfc bellard
static void serial_receive_break(ChannelState *s)
625 e80cfcfc bellard
{
626 12abac85 blueswir1
    s->rregs[R_STATUS] |= STATUS_BRK;
627 e80cfcfc bellard
    slavio_serial_update_irq(s);
628 e80cfcfc bellard
}
629 e80cfcfc bellard
630 e80cfcfc bellard
static void serial_receive1(void *opaque, const uint8_t *buf, int size)
631 e80cfcfc bellard
{
632 e80cfcfc bellard
    ChannelState *s = opaque;
633 e80cfcfc bellard
    serial_receive_byte(s, buf[0]);
634 e80cfcfc bellard
}
635 e80cfcfc bellard
636 e80cfcfc bellard
static void serial_event(void *opaque, int event)
637 e80cfcfc bellard
{
638 e80cfcfc bellard
    ChannelState *s = opaque;
639 e80cfcfc bellard
    if (event == CHR_EVENT_BREAK)
640 e80cfcfc bellard
        serial_receive_break(s);
641 e80cfcfc bellard
}
642 e80cfcfc bellard
643 e80cfcfc bellard
static CPUReadMemoryFunc *slavio_serial_mem_read[3] = {
644 e80cfcfc bellard
    slavio_serial_mem_readb,
645 7c560456 blueswir1
    NULL,
646 7c560456 blueswir1
    NULL,
647 e80cfcfc bellard
};
648 e80cfcfc bellard
649 e80cfcfc bellard
static CPUWriteMemoryFunc *slavio_serial_mem_write[3] = {
650 e80cfcfc bellard
    slavio_serial_mem_writeb,
651 7c560456 blueswir1
    NULL,
652 7c560456 blueswir1
    NULL,
653 e80cfcfc bellard
};
654 e80cfcfc bellard
655 e80cfcfc bellard
static void slavio_serial_save_chn(QEMUFile *f, ChannelState *s)
656 e80cfcfc bellard
{
657 22548760 blueswir1
    uint32_t tmp = 0;
658 22548760 blueswir1
659 d537cf6c pbrook
    qemu_put_be32s(f, &tmp); /* unused, was IRQ.  */
660 e80cfcfc bellard
    qemu_put_be32s(f, &s->reg);
661 e80cfcfc bellard
    qemu_put_be32s(f, &s->rxint);
662 e80cfcfc bellard
    qemu_put_be32s(f, &s->txint);
663 e4a89056 bellard
    qemu_put_be32s(f, &s->rxint_under_svc);
664 e4a89056 bellard
    qemu_put_be32s(f, &s->txint_under_svc);
665 e80cfcfc bellard
    qemu_put_8s(f, &s->rx);
666 e80cfcfc bellard
    qemu_put_8s(f, &s->tx);
667 12abac85 blueswir1
    qemu_put_buffer(f, s->wregs, SERIAL_REGS);
668 12abac85 blueswir1
    qemu_put_buffer(f, s->rregs, SERIAL_REGS);
669 e80cfcfc bellard
}
670 e80cfcfc bellard
671 e80cfcfc bellard
static void slavio_serial_save(QEMUFile *f, void *opaque)
672 e80cfcfc bellard
{
673 e80cfcfc bellard
    SerialState *s = opaque;
674 e80cfcfc bellard
675 e80cfcfc bellard
    slavio_serial_save_chn(f, &s->chn[0]);
676 e80cfcfc bellard
    slavio_serial_save_chn(f, &s->chn[1]);
677 e80cfcfc bellard
}
678 e80cfcfc bellard
679 e80cfcfc bellard
static int slavio_serial_load_chn(QEMUFile *f, ChannelState *s, int version_id)
680 e80cfcfc bellard
{
681 22548760 blueswir1
    uint32_t tmp;
682 d537cf6c pbrook
683 e4a89056 bellard
    if (version_id > 2)
684 e80cfcfc bellard
        return -EINVAL;
685 e80cfcfc bellard
686 d537cf6c pbrook
    qemu_get_be32s(f, &tmp); /* unused */
687 e80cfcfc bellard
    qemu_get_be32s(f, &s->reg);
688 e80cfcfc bellard
    qemu_get_be32s(f, &s->rxint);
689 e80cfcfc bellard
    qemu_get_be32s(f, &s->txint);
690 e4a89056 bellard
    if (version_id >= 2) {
691 e4a89056 bellard
        qemu_get_be32s(f, &s->rxint_under_svc);
692 e4a89056 bellard
        qemu_get_be32s(f, &s->txint_under_svc);
693 e4a89056 bellard
    }
694 e80cfcfc bellard
    qemu_get_8s(f, &s->rx);
695 e80cfcfc bellard
    qemu_get_8s(f, &s->tx);
696 12abac85 blueswir1
    qemu_get_buffer(f, s->wregs, SERIAL_REGS);
697 12abac85 blueswir1
    qemu_get_buffer(f, s->rregs, SERIAL_REGS);
698 e80cfcfc bellard
    return 0;
699 e80cfcfc bellard
}
700 e80cfcfc bellard
701 e80cfcfc bellard
static int slavio_serial_load(QEMUFile *f, void *opaque, int version_id)
702 e80cfcfc bellard
{
703 e80cfcfc bellard
    SerialState *s = opaque;
704 e80cfcfc bellard
    int ret;
705 e80cfcfc bellard
706 e80cfcfc bellard
    ret = slavio_serial_load_chn(f, &s->chn[0], version_id);
707 e80cfcfc bellard
    if (ret != 0)
708 f930d07e blueswir1
        return ret;
709 e80cfcfc bellard
    ret = slavio_serial_load_chn(f, &s->chn[1], version_id);
710 e80cfcfc bellard
    return ret;
711 e80cfcfc bellard
712 e80cfcfc bellard
}
713 e80cfcfc bellard
714 5dcb6b91 blueswir1
SerialState *slavio_serial_init(target_phys_addr_t base, qemu_irq irq,
715 5dcb6b91 blueswir1
                                CharDriverState *chr1, CharDriverState *chr2)
716 e80cfcfc bellard
{
717 8be1f5c8 bellard
    int slavio_serial_io_memory, i;
718 e80cfcfc bellard
    SerialState *s;
719 e80cfcfc bellard
720 e80cfcfc bellard
    s = qemu_mallocz(sizeof(SerialState));
721 e80cfcfc bellard
    if (!s)
722 e80cfcfc bellard
        return NULL;
723 e80cfcfc bellard
724 12abac85 blueswir1
    slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read,
725 12abac85 blueswir1
                                                     slavio_serial_mem_write,
726 12abac85 blueswir1
                                                     s);
727 5aca8c3b blueswir1
    cpu_register_physical_memory(base, SERIAL_SIZE, slavio_serial_io_memory);
728 e80cfcfc bellard
729 8be1f5c8 bellard
    s->chn[0].chr = chr1;
730 8be1f5c8 bellard
    s->chn[1].chr = chr2;
731 577390ff blueswir1
    s->chn[0].disabled = 0;
732 577390ff blueswir1
    s->chn[1].disabled = 0;
733 8be1f5c8 bellard
734 8be1f5c8 bellard
    for (i = 0; i < 2; i++) {
735 f930d07e blueswir1
        s->chn[i].irq = irq;
736 f930d07e blueswir1
        s->chn[i].chn = 1 - i;
737 f930d07e blueswir1
        s->chn[i].type = ser;
738 f930d07e blueswir1
        if (s->chn[i].chr) {
739 f930d07e blueswir1
            qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive,
740 e5b0bc44 pbrook
                                  serial_receive1, serial_event, &s->chn[i]);
741 f930d07e blueswir1
        }
742 e80cfcfc bellard
    }
743 8be1f5c8 bellard
    s->chn[0].otherchn = &s->chn[1];
744 8be1f5c8 bellard
    s->chn[1].otherchn = &s->chn[0];
745 12abac85 blueswir1
    register_savevm("slavio_serial", base, 2, slavio_serial_save,
746 12abac85 blueswir1
                    slavio_serial_load, s);
747 e80cfcfc bellard
    qemu_register_reset(slavio_serial_reset, s);
748 e80cfcfc bellard
    slavio_serial_reset(s);
749 e80cfcfc bellard
    return s;
750 e80cfcfc bellard
}
751 e80cfcfc bellard
752 8be1f5c8 bellard
static const uint8_t keycodes[128] = {
753 8be1f5c8 bellard
    127, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 43, 53,
754 8be1f5c8 bellard
    54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 89, 76, 77, 78,
755 8be1f5c8 bellard
    79, 80, 81, 82, 83, 84, 85, 86, 87, 42, 99, 88, 100, 101, 102, 103,
756 8be1f5c8 bellard
    104, 105, 106, 107, 108, 109, 110, 47, 19, 121, 119, 5, 6, 8, 10, 12,
757 8be1f5c8 bellard
    14, 16, 17, 18, 7, 98, 23, 68, 69, 70, 71, 91, 92, 93, 125, 112,
758 8be1f5c8 bellard
    113, 114, 94, 50, 0, 0, 124, 9, 11, 0, 0, 0, 0, 0, 0, 0,
759 8be1f5c8 bellard
    90, 0, 46, 22, 13, 111, 52, 20, 96, 24, 28, 74, 27, 123, 44, 66,
760 8be1f5c8 bellard
    0, 45, 2, 4, 48, 0, 0, 21, 0, 0, 0, 0, 0, 120, 122, 67,
761 8be1f5c8 bellard
};
762 8be1f5c8 bellard
763 43febf49 blueswir1
static const uint8_t e0_keycodes[128] = {
764 43febf49 blueswir1
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
765 43febf49 blueswir1
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 76, 0, 0,
766 43febf49 blueswir1
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
767 43febf49 blueswir1
    0, 0, 0, 0, 0, 109, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0,
768 43febf49 blueswir1
    0, 0, 0, 0, 0, 0, 0, 68, 69, 70, 0, 91, 0, 93, 0, 112,
769 43febf49 blueswir1
    113, 114, 94, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
770 43febf49 blueswir1
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
771 c0b5b109 blueswir1
    1, 3, 25, 26, 49, 52, 72, 73, 97, 99, 111, 118, 120, 122, 67, 0,
772 43febf49 blueswir1
};
773 43febf49 blueswir1
774 e80cfcfc bellard
static void sunkbd_event(void *opaque, int ch)
775 e80cfcfc bellard
{
776 e80cfcfc bellard
    ChannelState *s = opaque;
777 8be1f5c8 bellard
    int release = ch & 0x80;
778 8be1f5c8 bellard
779 12abac85 blueswir1
    KBD_DPRINTF("Untranslated keycode %2.2x (%s)\n", ch, release? "release" :
780 12abac85 blueswir1
                "press");
781 bbbb2f0a blueswir1
    switch (ch) {
782 bbbb2f0a blueswir1
    case 58: // Caps lock press
783 bbbb2f0a blueswir1
        s->caps_lock_mode ^= 1;
784 bbbb2f0a blueswir1
        if (s->caps_lock_mode == 2)
785 bbbb2f0a blueswir1
            return; // Drop second press
786 bbbb2f0a blueswir1
        break;
787 bbbb2f0a blueswir1
    case 69: // Num lock press
788 bbbb2f0a blueswir1
        s->num_lock_mode ^= 1;
789 bbbb2f0a blueswir1
        if (s->num_lock_mode == 2)
790 bbbb2f0a blueswir1
            return; // Drop second press
791 bbbb2f0a blueswir1
        break;
792 bbbb2f0a blueswir1
    case 186: // Caps lock release
793 bbbb2f0a blueswir1
        s->caps_lock_mode ^= 2;
794 bbbb2f0a blueswir1
        if (s->caps_lock_mode == 3)
795 bbbb2f0a blueswir1
            return; // Drop first release
796 bbbb2f0a blueswir1
        break;
797 bbbb2f0a blueswir1
    case 197: // Num lock release
798 bbbb2f0a blueswir1
        s->num_lock_mode ^= 2;
799 bbbb2f0a blueswir1
        if (s->num_lock_mode == 3)
800 bbbb2f0a blueswir1
            return; // Drop first release
801 bbbb2f0a blueswir1
        break;
802 bbbb2f0a blueswir1
    case 0xe0:
803 43febf49 blueswir1
        s->e0_mode = 1;
804 43febf49 blueswir1
        return;
805 bbbb2f0a blueswir1
    default:
806 bbbb2f0a blueswir1
        break;
807 43febf49 blueswir1
    }
808 43febf49 blueswir1
    if (s->e0_mode) {
809 43febf49 blueswir1
        s->e0_mode = 0;
810 43febf49 blueswir1
        ch = e0_keycodes[ch & 0x7f];
811 43febf49 blueswir1
    } else {
812 43febf49 blueswir1
        ch = keycodes[ch & 0x7f];
813 43febf49 blueswir1
    }
814 43febf49 blueswir1
    KBD_DPRINTF("Translated keycode %2.2x\n", ch);
815 8be1f5c8 bellard
    put_queue(s, ch | release);
816 8be1f5c8 bellard
}
817 8be1f5c8 bellard
818 8be1f5c8 bellard
static void handle_kbd_command(ChannelState *s, int val)
819 8be1f5c8 bellard
{
820 8be1f5c8 bellard
    KBD_DPRINTF("Command %d\n", val);
821 43febf49 blueswir1
    if (s->led_mode) { // Ignore led byte
822 43febf49 blueswir1
        s->led_mode = 0;
823 43febf49 blueswir1
        return;
824 43febf49 blueswir1
    }
825 8be1f5c8 bellard
    switch (val) {
826 8be1f5c8 bellard
    case 1: // Reset, return type code
827 67deb562 blueswir1
        clear_queue(s);
828 f930d07e blueswir1
        put_queue(s, 0xff);
829 f930d07e blueswir1
        put_queue(s, 4); // Type 4
830 f930d07e blueswir1
        put_queue(s, 0x7f);
831 f930d07e blueswir1
        break;
832 43febf49 blueswir1
    case 0xe: // Set leds
833 43febf49 blueswir1
        s->led_mode = 1;
834 43febf49 blueswir1
        break;
835 8be1f5c8 bellard
    case 7: // Query layout
836 67deb562 blueswir1
    case 0xf:
837 67deb562 blueswir1
        clear_queue(s);
838 f930d07e blueswir1
        put_queue(s, 0xfe);
839 f930d07e blueswir1
        put_queue(s, 0); // XXX, layout?
840 f930d07e blueswir1
        break;
841 8be1f5c8 bellard
    default:
842 f930d07e blueswir1
        break;
843 8be1f5c8 bellard
    }
844 e80cfcfc bellard
}
845 e80cfcfc bellard
846 5fafdf24 ths
static void sunmouse_event(void *opaque,
847 e80cfcfc bellard
                               int dx, int dy, int dz, int buttons_state)
848 e80cfcfc bellard
{
849 e80cfcfc bellard
    ChannelState *s = opaque;
850 e80cfcfc bellard
    int ch;
851 e80cfcfc bellard
852 715748fa bellard
    MS_DPRINTF("dx=%d dy=%d buttons=%01x\n", dx, dy, buttons_state);
853 715748fa bellard
854 715748fa bellard
    ch = 0x80 | 0x7; /* protocol start byte, no buttons pressed */
855 715748fa bellard
856 715748fa bellard
    if (buttons_state & MOUSE_EVENT_LBUTTON)
857 715748fa bellard
        ch ^= 0x4;
858 715748fa bellard
    if (buttons_state & MOUSE_EVENT_MBUTTON)
859 715748fa bellard
        ch ^= 0x2;
860 715748fa bellard
    if (buttons_state & MOUSE_EVENT_RBUTTON)
861 715748fa bellard
        ch ^= 0x1;
862 715748fa bellard
863 715748fa bellard
    put_queue(s, ch);
864 715748fa bellard
865 715748fa bellard
    ch = dx;
866 715748fa bellard
867 715748fa bellard
    if (ch > 127)
868 715748fa bellard
        ch=127;
869 715748fa bellard
    else if (ch < -127)
870 715748fa bellard
        ch=-127;
871 715748fa bellard
872 715748fa bellard
    put_queue(s, ch & 0xff);
873 715748fa bellard
874 715748fa bellard
    ch = -dy;
875 715748fa bellard
876 715748fa bellard
    if (ch > 127)
877 715748fa bellard
        ch=127;
878 715748fa bellard
    else if (ch < -127)
879 715748fa bellard
        ch=-127;
880 715748fa bellard
881 715748fa bellard
    put_queue(s, ch & 0xff);
882 715748fa bellard
883 715748fa bellard
    // MSC protocol specify two extra motion bytes
884 715748fa bellard
885 715748fa bellard
    put_queue(s, 0);
886 715748fa bellard
    put_queue(s, 0);
887 e80cfcfc bellard
}
888 e80cfcfc bellard
889 577390ff blueswir1
void slavio_serial_ms_kbd_init(target_phys_addr_t base, qemu_irq irq,
890 577390ff blueswir1
                               int disabled)
891 e80cfcfc bellard
{
892 8be1f5c8 bellard
    int slavio_serial_io_memory, i;
893 e80cfcfc bellard
    SerialState *s;
894 e80cfcfc bellard
895 e80cfcfc bellard
    s = qemu_mallocz(sizeof(SerialState));
896 e80cfcfc bellard
    if (!s)
897 e80cfcfc bellard
        return;
898 8be1f5c8 bellard
    for (i = 0; i < 2; i++) {
899 f930d07e blueswir1
        s->chn[i].irq = irq;
900 f930d07e blueswir1
        s->chn[i].chn = 1 - i;
901 f930d07e blueswir1
        s->chn[i].chr = NULL;
902 8be1f5c8 bellard
    }
903 8be1f5c8 bellard
    s->chn[0].otherchn = &s->chn[1];
904 8be1f5c8 bellard
    s->chn[1].otherchn = &s->chn[0];
905 8be1f5c8 bellard
    s->chn[0].type = mouse;
906 8be1f5c8 bellard
    s->chn[1].type = kbd;
907 577390ff blueswir1
    s->chn[0].disabled = disabled;
908 577390ff blueswir1
    s->chn[1].disabled = disabled;
909 e80cfcfc bellard
910 12abac85 blueswir1
    slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read,
911 12abac85 blueswir1
                                                     slavio_serial_mem_write,
912 12abac85 blueswir1
                                                     s);
913 5aca8c3b blueswir1
    cpu_register_physical_memory(base, SERIAL_SIZE, slavio_serial_io_memory);
914 e80cfcfc bellard
915 12abac85 blueswir1
    qemu_add_mouse_event_handler(sunmouse_event, &s->chn[0], 0,
916 12abac85 blueswir1
                                 "QEMU Sun Mouse");
917 8be1f5c8 bellard
    qemu_add_kbd_event_handler(sunkbd_event, &s->chn[1]);
918 12abac85 blueswir1
    register_savevm("slavio_serial_mouse", base, 2, slavio_serial_save,
919 12abac85 blueswir1
                    slavio_serial_load, s);
920 e80cfcfc bellard
    qemu_register_reset(slavio_serial_reset, s);
921 e80cfcfc bellard
    slavio_serial_reset(s);
922 e80cfcfc bellard
}