Statistics
| Branch: | Revision:

root / hw / escc.c @ 2f172849

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