Statistics
| Branch: | Revision:

root / hw / escc.c @ ee118d95

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