Statistics
| Branch: | Revision:

root / hw / escc.c @ 0200db65

History | View | Annotate | Download (25.8 kB)

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