Statistics
| Branch: | Revision:

root / hw / escc.c @ 7f5feab4

History | View | Annotate | Download (26.5 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 9fc391f8 Artyom Tarasenko
            s->rregs[R_INTR] |= INTR_TXINTA;
373 80637a6a blueswir1
            if (s->wregs[W_MINTR] & MINTR_STATUSHI)
374 80637a6a blueswir1
                s->otherchn->rregs[R_IVEC] = IVEC_HITXINTA;
375 80637a6a blueswir1
            else
376 80637a6a blueswir1
                s->otherchn->rregs[R_IVEC] = IVEC_LOTXINTA;
377 80637a6a blueswir1
        } else {
378 80637a6a blueswir1
            s->rregs[R_IVEC] = IVEC_TXINTB;
379 9fc391f8 Artyom Tarasenko
            s->otherchn->rregs[R_INTR] |= INTR_TXINTB;
380 80637a6a blueswir1
        }
381 b4ed08e0 blueswir1
    escc_update_irq(s);
382 9fc391f8 Artyom Tarasenko
    }
383 80637a6a blueswir1
}
384 80637a6a blueswir1
385 80637a6a blueswir1
static inline void clr_rxint(ChannelState *s)
386 80637a6a blueswir1
{
387 80637a6a blueswir1
    s->rxint = 0;
388 80637a6a blueswir1
    s->rxint_under_svc = 0;
389 80637a6a blueswir1
    if (s->chn == chn_a) {
390 80637a6a blueswir1
        if (s->wregs[W_MINTR] & MINTR_STATUSHI)
391 80637a6a blueswir1
            s->otherchn->rregs[R_IVEC] = IVEC_HINOINT;
392 80637a6a blueswir1
        else
393 80637a6a blueswir1
            s->otherchn->rregs[R_IVEC] = IVEC_LONOINT;
394 80637a6a blueswir1
        s->rregs[R_INTR] &= ~INTR_RXINTA;
395 80637a6a blueswir1
    } else {
396 80637a6a blueswir1
        if (s->wregs[W_MINTR] & MINTR_STATUSHI)
397 80637a6a blueswir1
            s->rregs[R_IVEC] = IVEC_HINOINT;
398 80637a6a blueswir1
        else
399 80637a6a blueswir1
            s->rregs[R_IVEC] = IVEC_LONOINT;
400 80637a6a blueswir1
        s->otherchn->rregs[R_INTR] &= ~INTR_RXINTB;
401 80637a6a blueswir1
    }
402 80637a6a blueswir1
    if (s->txint)
403 80637a6a blueswir1
        set_txint(s);
404 b4ed08e0 blueswir1
    escc_update_irq(s);
405 80637a6a blueswir1
}
406 80637a6a blueswir1
407 ba3c64fb bellard
static inline void clr_txint(ChannelState *s)
408 ba3c64fb bellard
{
409 ba3c64fb bellard
    s->txint = 0;
410 e4a89056 bellard
    s->txint_under_svc = 0;
411 b9652ca3 blueswir1
    if (s->chn == chn_a) {
412 12abac85 blueswir1
        if (s->wregs[W_MINTR] & MINTR_STATUSHI)
413 12abac85 blueswir1
            s->otherchn->rregs[R_IVEC] = IVEC_HINOINT;
414 b9652ca3 blueswir1
        else
415 12abac85 blueswir1
            s->otherchn->rregs[R_IVEC] = IVEC_LONOINT;
416 12abac85 blueswir1
        s->rregs[R_INTR] &= ~INTR_TXINTA;
417 b9652ca3 blueswir1
    } else {
418 9fc391f8 Artyom Tarasenko
        s->otherchn->rregs[R_INTR] &= ~INTR_TXINTB;
419 12abac85 blueswir1
        if (s->wregs[W_MINTR] & MINTR_STATUSHI)
420 12abac85 blueswir1
            s->rregs[R_IVEC] = IVEC_HINOINT;
421 b9652ca3 blueswir1
        else
422 12abac85 blueswir1
            s->rregs[R_IVEC] = IVEC_LONOINT;
423 12abac85 blueswir1
        s->otherchn->rregs[R_INTR] &= ~INTR_TXINTB;
424 b9652ca3 blueswir1
    }
425 e4a89056 bellard
    if (s->rxint)
426 e4a89056 bellard
        set_rxint(s);
427 b4ed08e0 blueswir1
    escc_update_irq(s);
428 ba3c64fb bellard
}
429 ba3c64fb bellard
430 b4ed08e0 blueswir1
static void escc_update_parameters(ChannelState *s)
431 35db099d bellard
{
432 35db099d bellard
    int speed, parity, data_bits, stop_bits;
433 35db099d bellard
    QEMUSerialSetParams ssp;
434 35db099d bellard
435 35db099d bellard
    if (!s->chr || s->type != ser)
436 35db099d bellard
        return;
437 35db099d bellard
438 12abac85 blueswir1
    if (s->wregs[W_TXCTRL1] & TXCTRL1_PAREN) {
439 12abac85 blueswir1
        if (s->wregs[W_TXCTRL1] & TXCTRL1_PAREV)
440 35db099d bellard
            parity = 'E';
441 35db099d bellard
        else
442 35db099d bellard
            parity = 'O';
443 35db099d bellard
    } else {
444 35db099d bellard
        parity = 'N';
445 35db099d bellard
    }
446 12abac85 blueswir1
    if ((s->wregs[W_TXCTRL1] & TXCTRL1_STPMSK) == TXCTRL1_2STOP)
447 35db099d bellard
        stop_bits = 2;
448 35db099d bellard
    else
449 35db099d bellard
        stop_bits = 1;
450 12abac85 blueswir1
    switch (s->wregs[W_TXCTRL2] & TXCTRL2_BITMSK) {
451 12abac85 blueswir1
    case TXCTRL2_5BITS:
452 35db099d bellard
        data_bits = 5;
453 35db099d bellard
        break;
454 12abac85 blueswir1
    case TXCTRL2_7BITS:
455 35db099d bellard
        data_bits = 7;
456 35db099d bellard
        break;
457 12abac85 blueswir1
    case TXCTRL2_6BITS:
458 35db099d bellard
        data_bits = 6;
459 35db099d bellard
        break;
460 35db099d bellard
    default:
461 12abac85 blueswir1
    case TXCTRL2_8BITS:
462 35db099d bellard
        data_bits = 8;
463 35db099d bellard
        break;
464 35db099d bellard
    }
465 b4ed08e0 blueswir1
    speed = s->clock / ((s->wregs[W_BRGLO] | (s->wregs[W_BRGHI] << 8)) + 2);
466 12abac85 blueswir1
    switch (s->wregs[W_TXCTRL1] & TXCTRL1_CLKMSK) {
467 12abac85 blueswir1
    case TXCTRL1_CLK1X:
468 35db099d bellard
        break;
469 12abac85 blueswir1
    case TXCTRL1_CLK16X:
470 35db099d bellard
        speed /= 16;
471 35db099d bellard
        break;
472 12abac85 blueswir1
    case TXCTRL1_CLK32X:
473 35db099d bellard
        speed /= 32;
474 35db099d bellard
        break;
475 35db099d bellard
    default:
476 12abac85 blueswir1
    case TXCTRL1_CLK64X:
477 35db099d bellard
        speed /= 64;
478 35db099d bellard
        break;
479 35db099d bellard
    }
480 35db099d bellard
    ssp.speed = speed;
481 35db099d bellard
    ssp.parity = parity;
482 35db099d bellard
    ssp.data_bits = data_bits;
483 35db099d bellard
    ssp.stop_bits = stop_bits;
484 35db099d bellard
    SER_DPRINTF("channel %c: speed=%d parity=%c data=%d stop=%d\n", CHN_C(s),
485 35db099d bellard
                speed, parity, data_bits, stop_bits);
486 35db099d bellard
    qemu_chr_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
487 35db099d bellard
}
488 35db099d bellard
489 c227f099 Anthony Liguori
static void escc_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
490 e80cfcfc bellard
{
491 b3ceef24 blueswir1
    SerialState *serial = opaque;
492 e80cfcfc bellard
    ChannelState *s;
493 e80cfcfc bellard
    uint32_t saddr;
494 e80cfcfc bellard
    int newreg, channel;
495 e80cfcfc bellard
496 e80cfcfc bellard
    val &= 0xff;
497 b4ed08e0 blueswir1
    saddr = (addr >> serial->it_shift) & 1;
498 b4ed08e0 blueswir1
    channel = (addr >> (serial->it_shift + 1)) & 1;
499 b3ceef24 blueswir1
    s = &serial->chn[channel];
500 e80cfcfc bellard
    switch (saddr) {
501 12abac85 blueswir1
    case SERIAL_CTRL:
502 12abac85 blueswir1
        SER_DPRINTF("Write channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg,
503 12abac85 blueswir1
                    val & 0xff);
504 f930d07e blueswir1
        newreg = 0;
505 f930d07e blueswir1
        switch (s->reg) {
506 12abac85 blueswir1
        case W_CMD:
507 12abac85 blueswir1
            newreg = val & CMD_PTR_MASK;
508 12abac85 blueswir1
            val &= CMD_CMD_MASK;
509 f930d07e blueswir1
            switch (val) {
510 12abac85 blueswir1
            case CMD_HI:
511 12abac85 blueswir1
                newreg |= CMD_HI;
512 f930d07e blueswir1
                break;
513 12abac85 blueswir1
            case CMD_CLR_TXINT:
514 ba3c64fb bellard
                clr_txint(s);
515 f930d07e blueswir1
                break;
516 12abac85 blueswir1
            case CMD_CLR_IUS:
517 9fc391f8 Artyom Tarasenko
                if (s->rxint_under_svc) {
518 9fc391f8 Artyom Tarasenko
                    s->rxint_under_svc = 0;
519 9fc391f8 Artyom Tarasenko
                    if (s->txint) {
520 9fc391f8 Artyom Tarasenko
                        set_txint(s);
521 9fc391f8 Artyom Tarasenko
                    }
522 9fc391f8 Artyom Tarasenko
                } else if (s->txint_under_svc) {
523 9fc391f8 Artyom Tarasenko
                    s->txint_under_svc = 0;
524 9fc391f8 Artyom Tarasenko
                }
525 9fc391f8 Artyom Tarasenko
                escc_update_irq(s);
526 f930d07e blueswir1
                break;
527 f930d07e blueswir1
            default:
528 f930d07e blueswir1
                break;
529 f930d07e blueswir1
            }
530 f930d07e blueswir1
            break;
531 12abac85 blueswir1
        case W_INTR ... W_RXCTRL:
532 12abac85 blueswir1
        case W_SYNC1 ... W_TXBUF:
533 12abac85 blueswir1
        case W_MISC1 ... W_CLOCK:
534 12abac85 blueswir1
        case W_MISC2 ... W_EXTINT:
535 f930d07e blueswir1
            s->wregs[s->reg] = val;
536 f930d07e blueswir1
            break;
537 12abac85 blueswir1
        case W_TXCTRL1:
538 12abac85 blueswir1
        case W_TXCTRL2:
539 796d8286 blueswir1
            s->wregs[s->reg] = val;
540 b4ed08e0 blueswir1
            escc_update_parameters(s);
541 796d8286 blueswir1
            break;
542 12abac85 blueswir1
        case W_BRGLO:
543 12abac85 blueswir1
        case W_BRGHI:
544 f930d07e blueswir1
            s->wregs[s->reg] = val;
545 796d8286 blueswir1
            s->rregs[s->reg] = val;
546 b4ed08e0 blueswir1
            escc_update_parameters(s);
547 f930d07e blueswir1
            break;
548 12abac85 blueswir1
        case W_MINTR:
549 12abac85 blueswir1
            switch (val & MINTR_RST_MASK) {
550 f930d07e blueswir1
            case 0:
551 f930d07e blueswir1
            default:
552 f930d07e blueswir1
                break;
553 12abac85 blueswir1
            case MINTR_RST_B:
554 b4ed08e0 blueswir1
                escc_reset_chn(&serial->chn[0]);
555 f930d07e blueswir1
                return;
556 12abac85 blueswir1
            case MINTR_RST_A:
557 b4ed08e0 blueswir1
                escc_reset_chn(&serial->chn[1]);
558 f930d07e blueswir1
                return;
559 12abac85 blueswir1
            case MINTR_RST_ALL:
560 bdb78cae Blue Swirl
                escc_reset(&serial->busdev.qdev);
561 f930d07e blueswir1
                return;
562 f930d07e blueswir1
            }
563 f930d07e blueswir1
            break;
564 f930d07e blueswir1
        default:
565 f930d07e blueswir1
            break;
566 f930d07e blueswir1
        }
567 f930d07e blueswir1
        if (s->reg == 0)
568 f930d07e blueswir1
            s->reg = newreg;
569 f930d07e blueswir1
        else
570 f930d07e blueswir1
            s->reg = 0;
571 f930d07e blueswir1
        break;
572 12abac85 blueswir1
    case SERIAL_DATA:
573 f930d07e blueswir1
        SER_DPRINTF("Write channel %c, ch %d\n", CHN_C(s), val);
574 96c4f569 blueswir1
        s->tx = val;
575 12abac85 blueswir1
        if (s->wregs[W_TXCTRL2] & TXCTRL2_TXEN) { // tx enabled
576 f930d07e blueswir1
            if (s->chr)
577 f930d07e blueswir1
                qemu_chr_write(s->chr, &s->tx, 1);
578 577390ff blueswir1
            else if (s->type == kbd && !s->disabled) {
579 f930d07e blueswir1
                handle_kbd_command(s, val);
580 f930d07e blueswir1
            }
581 f930d07e blueswir1
        }
582 12abac85 blueswir1
        s->rregs[R_STATUS] |= STATUS_TXEMPTY; // Tx buffer empty
583 12abac85 blueswir1
        s->rregs[R_SPEC] |= SPEC_ALLSENT; // All sent
584 96c4f569 blueswir1
        set_txint(s);
585 f930d07e blueswir1
        break;
586 e80cfcfc bellard
    default:
587 f930d07e blueswir1
        break;
588 e80cfcfc bellard
    }
589 e80cfcfc bellard
}
590 e80cfcfc bellard
591 c227f099 Anthony Liguori
static uint32_t escc_mem_readb(void *opaque, target_phys_addr_t addr)
592 e80cfcfc bellard
{
593 b3ceef24 blueswir1
    SerialState *serial = opaque;
594 e80cfcfc bellard
    ChannelState *s;
595 e80cfcfc bellard
    uint32_t saddr;
596 e80cfcfc bellard
    uint32_t ret;
597 e80cfcfc bellard
    int channel;
598 e80cfcfc bellard
599 b4ed08e0 blueswir1
    saddr = (addr >> serial->it_shift) & 1;
600 b4ed08e0 blueswir1
    channel = (addr >> (serial->it_shift + 1)) & 1;
601 b3ceef24 blueswir1
    s = &serial->chn[channel];
602 e80cfcfc bellard
    switch (saddr) {
603 12abac85 blueswir1
    case SERIAL_CTRL:
604 12abac85 blueswir1
        SER_DPRINTF("Read channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg,
605 12abac85 blueswir1
                    s->rregs[s->reg]);
606 f930d07e blueswir1
        ret = s->rregs[s->reg];
607 f930d07e blueswir1
        s->reg = 0;
608 f930d07e blueswir1
        return ret;
609 12abac85 blueswir1
    case SERIAL_DATA:
610 12abac85 blueswir1
        s->rregs[R_STATUS] &= ~STATUS_RXAV;
611 ba3c64fb bellard
        clr_rxint(s);
612 f930d07e blueswir1
        if (s->type == kbd || s->type == mouse)
613 f930d07e blueswir1
            ret = get_queue(s);
614 f930d07e blueswir1
        else
615 f930d07e blueswir1
            ret = s->rx;
616 f930d07e blueswir1
        SER_DPRINTF("Read channel %c, ch %d\n", CHN_C(s), ret);
617 b76482e7 blueswir1
        if (s->chr)
618 b76482e7 blueswir1
            qemu_chr_accept_input(s->chr);
619 f930d07e blueswir1
        return ret;
620 e80cfcfc bellard
    default:
621 f930d07e blueswir1
        break;
622 e80cfcfc bellard
    }
623 e80cfcfc bellard
    return 0;
624 e80cfcfc bellard
}
625 e80cfcfc bellard
626 e80cfcfc bellard
static int serial_can_receive(void *opaque)
627 e80cfcfc bellard
{
628 e80cfcfc bellard
    ChannelState *s = opaque;
629 e4a89056 bellard
    int ret;
630 e4a89056 bellard
631 12abac85 blueswir1
    if (((s->wregs[W_RXCTRL] & RXCTRL_RXEN) == 0) // Rx not enabled
632 12abac85 blueswir1
        || ((s->rregs[R_STATUS] & STATUS_RXAV) == STATUS_RXAV))
633 12abac85 blueswir1
        // char already available
634 f930d07e blueswir1
        ret = 0;
635 e80cfcfc bellard
    else
636 f930d07e blueswir1
        ret = 1;
637 e4a89056 bellard
    return ret;
638 e80cfcfc bellard
}
639 e80cfcfc bellard
640 e80cfcfc bellard
static void serial_receive_byte(ChannelState *s, int ch)
641 e80cfcfc bellard
{
642 35db099d bellard
    SER_DPRINTF("channel %c put ch %d\n", CHN_C(s), ch);
643 12abac85 blueswir1
    s->rregs[R_STATUS] |= STATUS_RXAV;
644 e80cfcfc bellard
    s->rx = ch;
645 ba3c64fb bellard
    set_rxint(s);
646 e80cfcfc bellard
}
647 e80cfcfc bellard
648 e80cfcfc bellard
static void serial_receive_break(ChannelState *s)
649 e80cfcfc bellard
{
650 12abac85 blueswir1
    s->rregs[R_STATUS] |= STATUS_BRK;
651 b4ed08e0 blueswir1
    escc_update_irq(s);
652 e80cfcfc bellard
}
653 e80cfcfc bellard
654 e80cfcfc bellard
static void serial_receive1(void *opaque, const uint8_t *buf, int size)
655 e80cfcfc bellard
{
656 e80cfcfc bellard
    ChannelState *s = opaque;
657 e80cfcfc bellard
    serial_receive_byte(s, buf[0]);
658 e80cfcfc bellard
}
659 e80cfcfc bellard
660 e80cfcfc bellard
static void serial_event(void *opaque, int event)
661 e80cfcfc bellard
{
662 e80cfcfc bellard
    ChannelState *s = opaque;
663 e80cfcfc bellard
    if (event == CHR_EVENT_BREAK)
664 e80cfcfc bellard
        serial_receive_break(s);
665 e80cfcfc bellard
}
666 e80cfcfc bellard
667 d60efc6b Blue Swirl
static CPUReadMemoryFunc * const escc_mem_read[3] = {
668 b4ed08e0 blueswir1
    escc_mem_readb,
669 7c560456 blueswir1
    NULL,
670 7c560456 blueswir1
    NULL,
671 e80cfcfc bellard
};
672 e80cfcfc bellard
673 d60efc6b Blue Swirl
static CPUWriteMemoryFunc * const escc_mem_write[3] = {
674 b4ed08e0 blueswir1
    escc_mem_writeb,
675 7c560456 blueswir1
    NULL,
676 7c560456 blueswir1
    NULL,
677 e80cfcfc bellard
};
678 e80cfcfc bellard
679 bdb78cae Blue Swirl
static const VMStateDescription vmstate_escc_chn = {
680 bdb78cae Blue Swirl
    .name ="escc_chn",
681 bdb78cae Blue Swirl
    .version_id = 2,
682 bdb78cae Blue Swirl
    .minimum_version_id = 1,
683 bdb78cae Blue Swirl
    .minimum_version_id_old = 1,
684 bdb78cae Blue Swirl
    .fields      = (VMStateField []) {
685 bdb78cae Blue Swirl
        VMSTATE_UINT32(vmstate_dummy, ChannelState),
686 bdb78cae Blue Swirl
        VMSTATE_UINT32(reg, ChannelState),
687 bdb78cae Blue Swirl
        VMSTATE_UINT32(rxint, ChannelState),
688 bdb78cae Blue Swirl
        VMSTATE_UINT32(txint, ChannelState),
689 bdb78cae Blue Swirl
        VMSTATE_UINT32(rxint_under_svc, ChannelState),
690 bdb78cae Blue Swirl
        VMSTATE_UINT32(txint_under_svc, ChannelState),
691 bdb78cae Blue Swirl
        VMSTATE_UINT8(rx, ChannelState),
692 bdb78cae Blue Swirl
        VMSTATE_UINT8(tx, ChannelState),
693 bdb78cae Blue Swirl
        VMSTATE_BUFFER(wregs, ChannelState),
694 bdb78cae Blue Swirl
        VMSTATE_BUFFER(rregs, ChannelState),
695 bdb78cae Blue Swirl
        VMSTATE_END_OF_LIST()
696 e4a89056 bellard
    }
697 bdb78cae Blue Swirl
};
698 e80cfcfc bellard
699 bdb78cae Blue Swirl
static const VMStateDescription vmstate_escc = {
700 bdb78cae Blue Swirl
    .name ="escc",
701 bdb78cae Blue Swirl
    .version_id = 2,
702 bdb78cae Blue Swirl
    .minimum_version_id = 1,
703 bdb78cae Blue Swirl
    .minimum_version_id_old = 1,
704 bdb78cae Blue Swirl
    .fields      = (VMStateField []) {
705 bdb78cae Blue Swirl
        VMSTATE_STRUCT_ARRAY(chn, SerialState, 2, 2, vmstate_escc_chn,
706 bdb78cae Blue Swirl
                             ChannelState),
707 bdb78cae Blue Swirl
        VMSTATE_END_OF_LIST()
708 bdb78cae Blue Swirl
    }
709 bdb78cae Blue Swirl
};
710 e80cfcfc bellard
711 c227f099 Anthony Liguori
int escc_init(target_phys_addr_t base, qemu_irq irqA, qemu_irq irqB,
712 aeeb69c7 aurel32
              CharDriverState *chrA, CharDriverState *chrB,
713 aeeb69c7 aurel32
              int clock, int it_shift)
714 e80cfcfc bellard
{
715 6c319c82 Blue Swirl
    DeviceState *dev;
716 6c319c82 Blue Swirl
    SysBusDevice *s;
717 6c319c82 Blue Swirl
    SerialState *d;
718 6c319c82 Blue Swirl
719 6c319c82 Blue Swirl
    dev = qdev_create(NULL, "escc");
720 ee6847d1 Gerd Hoffmann
    qdev_prop_set_uint32(dev, "disabled", 0);
721 ee6847d1 Gerd Hoffmann
    qdev_prop_set_uint32(dev, "frequency", clock);
722 ee6847d1 Gerd Hoffmann
    qdev_prop_set_uint32(dev, "it_shift", it_shift);
723 bc19fcaa Blue Swirl
    qdev_prop_set_chr(dev, "chrB", chrB);
724 bc19fcaa Blue Swirl
    qdev_prop_set_chr(dev, "chrA", chrA);
725 ee6847d1 Gerd Hoffmann
    qdev_prop_set_uint32(dev, "chnBtype", ser);
726 ee6847d1 Gerd Hoffmann
    qdev_prop_set_uint32(dev, "chnAtype", ser);
727 e23a1b33 Markus Armbruster
    qdev_init_nofail(dev);
728 6c319c82 Blue Swirl
    s = sysbus_from_qdev(dev);
729 e1a0e47f Aurelien Jarno
    sysbus_connect_irq(s, 0, irqB);
730 e1a0e47f Aurelien Jarno
    sysbus_connect_irq(s, 1, irqA);
731 6c319c82 Blue Swirl
    if (base) {
732 6c319c82 Blue Swirl
        sysbus_mmio_map(s, 0, base);
733 e80cfcfc bellard
    }
734 6c319c82 Blue Swirl
735 6c319c82 Blue Swirl
    d = FROM_SYSBUS(SerialState, s);
736 6c319c82 Blue Swirl
    return d->mmio_index;
737 e80cfcfc bellard
}
738 e80cfcfc bellard
739 8be1f5c8 bellard
static const uint8_t keycodes[128] = {
740 8be1f5c8 bellard
    127, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 43, 53,
741 8be1f5c8 bellard
    54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 89, 76, 77, 78,
742 8be1f5c8 bellard
    79, 80, 81, 82, 83, 84, 85, 86, 87, 42, 99, 88, 100, 101, 102, 103,
743 8be1f5c8 bellard
    104, 105, 106, 107, 108, 109, 110, 47, 19, 121, 119, 5, 6, 8, 10, 12,
744 8be1f5c8 bellard
    14, 16, 17, 18, 7, 98, 23, 68, 69, 70, 71, 91, 92, 93, 125, 112,
745 8be1f5c8 bellard
    113, 114, 94, 50, 0, 0, 124, 9, 11, 0, 0, 0, 0, 0, 0, 0,
746 8be1f5c8 bellard
    90, 0, 46, 22, 13, 111, 52, 20, 96, 24, 28, 74, 27, 123, 44, 66,
747 8be1f5c8 bellard
    0, 45, 2, 4, 48, 0, 0, 21, 0, 0, 0, 0, 0, 120, 122, 67,
748 8be1f5c8 bellard
};
749 8be1f5c8 bellard
750 43febf49 blueswir1
static const uint8_t e0_keycodes[128] = {
751 43febf49 blueswir1
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
752 43febf49 blueswir1
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 76, 0, 0,
753 43febf49 blueswir1
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
754 43febf49 blueswir1
    0, 0, 0, 0, 0, 109, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0,
755 43febf49 blueswir1
    0, 0, 0, 0, 0, 0, 0, 68, 69, 70, 0, 91, 0, 93, 0, 112,
756 43febf49 blueswir1
    113, 114, 94, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
757 43febf49 blueswir1
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
758 c0b5b109 blueswir1
    1, 3, 25, 26, 49, 52, 72, 73, 97, 99, 111, 118, 120, 122, 67, 0,
759 43febf49 blueswir1
};
760 43febf49 blueswir1
761 e80cfcfc bellard
static void sunkbd_event(void *opaque, int ch)
762 e80cfcfc bellard
{
763 e80cfcfc bellard
    ChannelState *s = opaque;
764 8be1f5c8 bellard
    int release = ch & 0x80;
765 8be1f5c8 bellard
766 12abac85 blueswir1
    KBD_DPRINTF("Untranslated keycode %2.2x (%s)\n", ch, release? "release" :
767 12abac85 blueswir1
                "press");
768 bbbb2f0a blueswir1
    switch (ch) {
769 bbbb2f0a blueswir1
    case 58: // Caps lock press
770 bbbb2f0a blueswir1
        s->caps_lock_mode ^= 1;
771 bbbb2f0a blueswir1
        if (s->caps_lock_mode == 2)
772 bbbb2f0a blueswir1
            return; // Drop second press
773 bbbb2f0a blueswir1
        break;
774 bbbb2f0a blueswir1
    case 69: // Num lock press
775 bbbb2f0a blueswir1
        s->num_lock_mode ^= 1;
776 bbbb2f0a blueswir1
        if (s->num_lock_mode == 2)
777 bbbb2f0a blueswir1
            return; // Drop second press
778 bbbb2f0a blueswir1
        break;
779 bbbb2f0a blueswir1
    case 186: // Caps lock release
780 bbbb2f0a blueswir1
        s->caps_lock_mode ^= 2;
781 bbbb2f0a blueswir1
        if (s->caps_lock_mode == 3)
782 bbbb2f0a blueswir1
            return; // Drop first release
783 bbbb2f0a blueswir1
        break;
784 bbbb2f0a blueswir1
    case 197: // Num lock release
785 bbbb2f0a blueswir1
        s->num_lock_mode ^= 2;
786 bbbb2f0a blueswir1
        if (s->num_lock_mode == 3)
787 bbbb2f0a blueswir1
            return; // Drop first release
788 bbbb2f0a blueswir1
        break;
789 bbbb2f0a blueswir1
    case 0xe0:
790 43febf49 blueswir1
        s->e0_mode = 1;
791 43febf49 blueswir1
        return;
792 bbbb2f0a blueswir1
    default:
793 bbbb2f0a blueswir1
        break;
794 43febf49 blueswir1
    }
795 43febf49 blueswir1
    if (s->e0_mode) {
796 43febf49 blueswir1
        s->e0_mode = 0;
797 43febf49 blueswir1
        ch = e0_keycodes[ch & 0x7f];
798 43febf49 blueswir1
    } else {
799 43febf49 blueswir1
        ch = keycodes[ch & 0x7f];
800 43febf49 blueswir1
    }
801 43febf49 blueswir1
    KBD_DPRINTF("Translated keycode %2.2x\n", ch);
802 8be1f5c8 bellard
    put_queue(s, ch | release);
803 8be1f5c8 bellard
}
804 8be1f5c8 bellard
805 8be1f5c8 bellard
static void handle_kbd_command(ChannelState *s, int val)
806 8be1f5c8 bellard
{
807 8be1f5c8 bellard
    KBD_DPRINTF("Command %d\n", val);
808 43febf49 blueswir1
    if (s->led_mode) { // Ignore led byte
809 43febf49 blueswir1
        s->led_mode = 0;
810 43febf49 blueswir1
        return;
811 43febf49 blueswir1
    }
812 8be1f5c8 bellard
    switch (val) {
813 8be1f5c8 bellard
    case 1: // Reset, return type code
814 67deb562 blueswir1
        clear_queue(s);
815 f930d07e blueswir1
        put_queue(s, 0xff);
816 f930d07e blueswir1
        put_queue(s, 4); // Type 4
817 f930d07e blueswir1
        put_queue(s, 0x7f);
818 f930d07e blueswir1
        break;
819 43febf49 blueswir1
    case 0xe: // Set leds
820 43febf49 blueswir1
        s->led_mode = 1;
821 43febf49 blueswir1
        break;
822 8be1f5c8 bellard
    case 7: // Query layout
823 67deb562 blueswir1
    case 0xf:
824 67deb562 blueswir1
        clear_queue(s);
825 f930d07e blueswir1
        put_queue(s, 0xfe);
826 f930d07e blueswir1
        put_queue(s, 0); // XXX, layout?
827 f930d07e blueswir1
        break;
828 8be1f5c8 bellard
    default:
829 f930d07e blueswir1
        break;
830 8be1f5c8 bellard
    }
831 e80cfcfc bellard
}
832 e80cfcfc bellard
833 5fafdf24 ths
static void sunmouse_event(void *opaque,
834 e80cfcfc bellard
                               int dx, int dy, int dz, int buttons_state)
835 e80cfcfc bellard
{
836 e80cfcfc bellard
    ChannelState *s = opaque;
837 e80cfcfc bellard
    int ch;
838 e80cfcfc bellard
839 715748fa bellard
    MS_DPRINTF("dx=%d dy=%d buttons=%01x\n", dx, dy, buttons_state);
840 715748fa bellard
841 715748fa bellard
    ch = 0x80 | 0x7; /* protocol start byte, no buttons pressed */
842 715748fa bellard
843 715748fa bellard
    if (buttons_state & MOUSE_EVENT_LBUTTON)
844 715748fa bellard
        ch ^= 0x4;
845 715748fa bellard
    if (buttons_state & MOUSE_EVENT_MBUTTON)
846 715748fa bellard
        ch ^= 0x2;
847 715748fa bellard
    if (buttons_state & MOUSE_EVENT_RBUTTON)
848 715748fa bellard
        ch ^= 0x1;
849 715748fa bellard
850 715748fa bellard
    put_queue(s, ch);
851 715748fa bellard
852 715748fa bellard
    ch = dx;
853 715748fa bellard
854 715748fa bellard
    if (ch > 127)
855 a0d98a71 Michael S. Tsirkin
        ch = 127;
856 715748fa bellard
    else if (ch < -127)
857 a0d98a71 Michael S. Tsirkin
        ch = -127;
858 715748fa bellard
859 715748fa bellard
    put_queue(s, ch & 0xff);
860 715748fa bellard
861 715748fa bellard
    ch = -dy;
862 715748fa bellard
863 715748fa bellard
    if (ch > 127)
864 084bd071 Michael S. Tsirkin
        ch = 127;
865 715748fa bellard
    else if (ch < -127)
866 084bd071 Michael S. Tsirkin
        ch = -127;
867 715748fa bellard
868 715748fa bellard
    put_queue(s, ch & 0xff);
869 715748fa bellard
870 715748fa bellard
    // MSC protocol specify two extra motion bytes
871 715748fa bellard
872 715748fa bellard
    put_queue(s, 0);
873 715748fa bellard
    put_queue(s, 0);
874 e80cfcfc bellard
}
875 e80cfcfc bellard
876 c227f099 Anthony Liguori
void slavio_serial_ms_kbd_init(target_phys_addr_t base, qemu_irq irq,
877 b4ed08e0 blueswir1
                               int disabled, int clock, int it_shift)
878 e80cfcfc bellard
{
879 6c319c82 Blue Swirl
    DeviceState *dev;
880 6c319c82 Blue Swirl
    SysBusDevice *s;
881 6c319c82 Blue Swirl
882 6c319c82 Blue Swirl
    dev = qdev_create(NULL, "escc");
883 ee6847d1 Gerd Hoffmann
    qdev_prop_set_uint32(dev, "disabled", disabled);
884 ee6847d1 Gerd Hoffmann
    qdev_prop_set_uint32(dev, "frequency", clock);
885 ee6847d1 Gerd Hoffmann
    qdev_prop_set_uint32(dev, "it_shift", it_shift);
886 bc19fcaa Blue Swirl
    qdev_prop_set_chr(dev, "chrB", NULL);
887 bc19fcaa Blue Swirl
    qdev_prop_set_chr(dev, "chrA", NULL);
888 ee6847d1 Gerd Hoffmann
    qdev_prop_set_uint32(dev, "chnBtype", mouse);
889 ee6847d1 Gerd Hoffmann
    qdev_prop_set_uint32(dev, "chnAtype", kbd);
890 e23a1b33 Markus Armbruster
    qdev_init_nofail(dev);
891 6c319c82 Blue Swirl
    s = sysbus_from_qdev(dev);
892 6c319c82 Blue Swirl
    sysbus_connect_irq(s, 0, irq);
893 6c319c82 Blue Swirl
    sysbus_connect_irq(s, 1, irq);
894 6c319c82 Blue Swirl
    sysbus_mmio_map(s, 0, base);
895 6c319c82 Blue Swirl
}
896 b4ed08e0 blueswir1
897 81a322d4 Gerd Hoffmann
static int escc_init1(SysBusDevice *dev)
898 6c319c82 Blue Swirl
{
899 6c319c82 Blue Swirl
    SerialState *s = FROM_SYSBUS(SerialState, dev);
900 6c319c82 Blue Swirl
    int io;
901 6c319c82 Blue Swirl
    unsigned int i;
902 ee6847d1 Gerd Hoffmann
903 ee6847d1 Gerd Hoffmann
    s->chn[0].disabled = s->disabled;
904 ee6847d1 Gerd Hoffmann
    s->chn[1].disabled = s->disabled;
905 8be1f5c8 bellard
    for (i = 0; i < 2; i++) {
906 6c319c82 Blue Swirl
        sysbus_init_irq(dev, &s->chn[i].irq);
907 f930d07e blueswir1
        s->chn[i].chn = 1 - i;
908 ee6847d1 Gerd Hoffmann
        s->chn[i].clock = s->frequency / 2;
909 6c319c82 Blue Swirl
        if (s->chn[i].chr) {
910 6c319c82 Blue Swirl
            qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive,
911 6c319c82 Blue Swirl
                                  serial_receive1, serial_event, &s->chn[i]);
912 6c319c82 Blue Swirl
        }
913 8be1f5c8 bellard
    }
914 8be1f5c8 bellard
    s->chn[0].otherchn = &s->chn[1];
915 8be1f5c8 bellard
    s->chn[1].otherchn = &s->chn[0];
916 e80cfcfc bellard
917 6c319c82 Blue Swirl
    io = cpu_register_io_memory(escc_mem_read, escc_mem_write, s);
918 6c319c82 Blue Swirl
    sysbus_init_mmio(dev, ESCC_SIZE << s->it_shift, io);
919 6c319c82 Blue Swirl
    s->mmio_index = io;
920 e80cfcfc bellard
921 6c319c82 Blue Swirl
    if (s->chn[0].type == mouse) {
922 6c319c82 Blue Swirl
        qemu_add_mouse_event_handler(sunmouse_event, &s->chn[0], 0,
923 6c319c82 Blue Swirl
                                     "QEMU Sun Mouse");
924 6c319c82 Blue Swirl
    }
925 6c319c82 Blue Swirl
    if (s->chn[1].type == kbd) {
926 6c319c82 Blue Swirl
        qemu_add_kbd_event_handler(sunkbd_event, &s->chn[1]);
927 6c319c82 Blue Swirl
    }
928 bdb78cae Blue Swirl
929 81a322d4 Gerd Hoffmann
    return 0;
930 e80cfcfc bellard
}
931 6c319c82 Blue Swirl
932 6c319c82 Blue Swirl
static SysBusDeviceInfo escc_info = {
933 6c319c82 Blue Swirl
    .init = escc_init1,
934 6c319c82 Blue Swirl
    .qdev.name  = "escc",
935 6c319c82 Blue Swirl
    .qdev.size  = sizeof(SerialState),
936 bdb78cae Blue Swirl
    .qdev.vmsd  = &vmstate_escc,
937 bdb78cae Blue Swirl
    .qdev.reset = escc_reset,
938 ee6847d1 Gerd Hoffmann
    .qdev.props = (Property[]) {
939 ec02f7de Gerd Hoffmann
        DEFINE_PROP_UINT32("frequency", SerialState, frequency,   0),
940 ec02f7de Gerd Hoffmann
        DEFINE_PROP_UINT32("it_shift",  SerialState, it_shift,    0),
941 ec02f7de Gerd Hoffmann
        DEFINE_PROP_UINT32("disabled",  SerialState, disabled,    0),
942 ec02f7de Gerd Hoffmann
        DEFINE_PROP_UINT32("disabled",  SerialState, disabled,    0),
943 ec02f7de Gerd Hoffmann
        DEFINE_PROP_UINT32("chnBtype",  SerialState, chn[0].type, 0),
944 ec02f7de Gerd Hoffmann
        DEFINE_PROP_UINT32("chnAtype",  SerialState, chn[1].type, 0),
945 ec02f7de Gerd Hoffmann
        DEFINE_PROP_CHR("chrB", SerialState, chn[0].chr),
946 ec02f7de Gerd Hoffmann
        DEFINE_PROP_CHR("chrA", SerialState, chn[1].chr),
947 ec02f7de Gerd Hoffmann
        DEFINE_PROP_END_OF_LIST(),
948 6c319c82 Blue Swirl
    }
949 6c319c82 Blue Swirl
};
950 6c319c82 Blue Swirl
951 6c319c82 Blue Swirl
static void escc_register_devices(void)
952 6c319c82 Blue Swirl
{
953 6c319c82 Blue Swirl
    sysbus_register_withprop(&escc_info);
954 6c319c82 Blue Swirl
}
955 6c319c82 Blue Swirl
956 6c319c82 Blue Swirl
device_init(escc_register_devices)