Statistics
| Branch: | Revision:

root / hw / slavio_serial.c @ a350e694

History | View | Annotate | Download (25.1 kB)

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