Statistics
| Branch: | Revision:

root / hw / escc.c @ 525e0514

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