Statistics
| Branch: | Revision:

root / hw / slavio_serial.c @ 5dafc53f

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