Statistics
| Branch: | Revision:

root / hw / escc.c @ 377a7f06

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