Statistics
| Branch: | Revision:

root / hw / slavio_serial.c @ ca87d03b

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