qemu

Форк
0
/
escc.c 
1085 строк · 31.7 Кб
1
/*
2
 * QEMU ESCC (Z8030/Z8530/Z85C30/SCC/ESCC) serial port emulation
3
 *
4
 * Copyright (c) 2003-2005 Fabrice Bellard
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24

25
#include "qemu/osdep.h"
26
#include "hw/irq.h"
27
#include "hw/qdev-properties.h"
28
#include "hw/qdev-properties-system.h"
29
#include "hw/sysbus.h"
30
#include "migration/vmstate.h"
31
#include "qemu/module.h"
32
#include "hw/char/escc.h"
33
#include "ui/console.h"
34

35
#include "qemu/cutils.h"
36
#include "trace.h"
37

38
/*
39
 * Chipset docs:
40
 * "Z80C30/Z85C30/Z80230/Z85230/Z85233 SCC/ESCC User Manual",
41
 * http://www.zilog.com/docs/serial/scc_escc_um.pdf
42
 *
43
 * On Sparc32 this is the serial port, mouse and keyboard part of chip STP2001
44
 * (Slave I/O), also produced as NCR89C105. See
45
 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
46
 *
47
 * The serial ports implement full AMD AM8530 or Zilog Z8530 chips,
48
 * mouse and keyboard ports don't implement all functions and they are
49
 * only asynchronous. There is no DMA.
50
 *
51
 * Z85C30 is also used on PowerMacs and m68k Macs.
52
 *
53
 * There are some small differences between Sparc version (sunzilog)
54
 * and PowerMac (pmac):
55
 *  Offset between control and data registers
56
 *  There is some kind of lockup bug, but we can ignore it
57
 *  CTS is inverted
58
 *  DMA on pmac using DBDMA chip
59
 *  pmac can do IRDA and faster rates, sunzilog can only do 38400
60
 *  pmac baud rate generator clock is 3.6864 MHz, sunzilog 4.9152 MHz
61
 *
62
 * Linux driver for m68k Macs is the same as for PowerMac (pmac_zilog),
63
 * but registers are grouped by type and not by channel:
64
 * channel is selected by bit 0 of the address (instead of bit 1)
65
 * and register is selected by bit 1 of the address (instead of bit 0).
66
 */
67

68
/*
69
 * Modifications:
70
 *  2006-Aug-10  Igor Kovalenko :   Renamed KBDQueue to SERIOQueue, implemented
71
 *                                  serial mouse queue.
72
 *                                  Implemented serial mouse protocol.
73
 *
74
 *  2010-May-23  Artyom Tarasenko:  Reworked IUS logic
75
 */
76

77
#define CHN_C(s) ((s)->chn == escc_chn_b ? 'b' : 'a')
78

79
#define SERIAL_CTRL 0
80
#define SERIAL_DATA 1
81

82
#define W_CMD     0
83
#define CMD_PTR_MASK   0x07
84
#define CMD_CMD_MASK   0x38
85
#define CMD_HI         0x08
86
#define CMD_CLR_TXINT  0x28
87
#define CMD_CLR_IUS    0x38
88
#define W_INTR    1
89
#define INTR_INTALL    0x01
90
#define INTR_TXINT     0x02
91
#define INTR_PAR_SPEC  0x04
92
#define INTR_RXMODEMSK 0x18
93
#define INTR_RXINT1ST  0x08
94
#define INTR_RXINTALL  0x10
95
#define INTR_WTRQ_TXRX 0x20
96
#define W_IVEC    2
97
#define W_RXCTRL  3
98
#define RXCTRL_RXEN    0x01
99
#define RXCTRL_HUNT    0x10
100
#define W_TXCTRL1 4
101
#define TXCTRL1_PAREN  0x01
102
#define TXCTRL1_PAREV  0x02
103
#define TXCTRL1_1STOP  0x04
104
#define TXCTRL1_1HSTOP 0x08
105
#define TXCTRL1_2STOP  0x0c
106
#define TXCTRL1_STPMSK 0x0c
107
#define TXCTRL1_CLK1X  0x00
108
#define TXCTRL1_CLK16X 0x40
109
#define TXCTRL1_CLK32X 0x80
110
#define TXCTRL1_CLK64X 0xc0
111
#define TXCTRL1_CLKMSK 0xc0
112
#define W_TXCTRL2 5
113
#define TXCTRL2_TXCRC  0x01
114
#define TXCTRL2_TXEN   0x08
115
#define TXCTRL2_BITMSK 0x60
116
#define TXCTRL2_5BITS  0x00
117
#define TXCTRL2_7BITS  0x20
118
#define TXCTRL2_6BITS  0x40
119
#define TXCTRL2_8BITS  0x60
120
#define W_SYNC1   6
121
#define W_SYNC2   7
122
#define W_TXBUF   8
123
#define W_MINTR   9
124
#define MINTR_VIS      0x01
125
#define MINTR_NV       0x02
126
#define MINTR_STATUSHI 0x10
127
#define MINTR_SOFTIACK 0x20
128
#define MINTR_RST_MASK 0xc0
129
#define MINTR_RST_B    0x40
130
#define MINTR_RST_A    0x80
131
#define MINTR_RST_ALL  0xc0
132
#define W_MISC1  10
133
#define MISC1_ENC_MASK 0x60
134
#define W_CLOCK  11
135
#define CLOCK_TRXC     0x08
136
#define W_BRGLO  12
137
#define W_BRGHI  13
138
#define W_MISC2  14
139
#define MISC2_BRG_EN   0x01
140
#define MISC2_BRG_SRC  0x02
141
#define MISC2_LCL_LOOP 0x10
142
#define MISC2_PLLCMD0  0x20
143
#define MISC2_PLLCMD1  0x40
144
#define MISC2_PLLCMD2  0x80
145
#define W_EXTINT 15
146
#define EXTINT_DCD     0x08
147
#define EXTINT_SYNCINT 0x10
148
#define EXTINT_CTSINT  0x20
149
#define EXTINT_TXUNDRN 0x40
150
#define EXTINT_BRKINT  0x80
151

152
#define R_STATUS  0
153
#define STATUS_RXAV    0x01
154
#define STATUS_ZERO    0x02
155
#define STATUS_TXEMPTY 0x04
156
#define STATUS_DCD     0x08
157
#define STATUS_SYNC    0x10
158
#define STATUS_CTS     0x20
159
#define STATUS_TXUNDRN 0x40
160
#define STATUS_BRK     0x80
161
#define R_SPEC    1
162
#define SPEC_ALLSENT   0x01
163
#define SPEC_BITS8     0x06
164
#define R_IVEC    2
165
#define IVEC_TXINTB    0x00
166
#define IVEC_LONOINT   0x06
167
#define IVEC_LORXINTA  0x0c
168
#define IVEC_LORXINTB  0x04
169
#define IVEC_LOTXINTA  0x08
170
#define IVEC_HINOINT   0x60
171
#define IVEC_HIRXINTA  0x30
172
#define IVEC_HIRXINTB  0x20
173
#define IVEC_HITXINTA  0x10
174
#define R_INTR    3
175
#define INTR_EXTINTB   0x01
176
#define INTR_TXINTB    0x02
177
#define INTR_RXINTB    0x04
178
#define INTR_EXTINTA   0x08
179
#define INTR_TXINTA    0x10
180
#define INTR_RXINTA    0x20
181
#define R_IPEN    4
182
#define R_TXCTRL1 5
183
#define R_TXCTRL2 6
184
#define R_BC      7
185
#define R_RXBUF   8
186
#define R_RXCTRL  9
187
#define R_MISC   10
188
#define MISC_2CLKMISS  0x40
189
#define R_MISC1  11
190
#define R_BRGLO  12
191
#define R_BRGHI  13
192
#define R_MISC1I 14
193
#define R_EXTINT 15
194

195
static uint8_t sunkbd_layout_dip_switch(const char *sunkbd_layout);
196
static void handle_kbd_command(ESCCChannelState *s, int val);
197
static int serial_can_receive(void *opaque);
198
static void serial_receive_byte(ESCCChannelState *s, int ch);
199

200
static int reg_shift(ESCCState *s)
201
{
202
    return s->bit_swap ? s->it_shift + 1 : s->it_shift;
203
}
204

205
static int chn_shift(ESCCState *s)
206
{
207
    return s->bit_swap ? s->it_shift : s->it_shift + 1;
208
}
209

210
static void clear_queue(void *opaque)
211
{
212
    ESCCChannelState *s = opaque;
213
    ESCCSERIOQueue *q = &s->queue;
214
    q->rptr = q->wptr = q->count = 0;
215
}
216

217
static void put_queue(void *opaque, int b)
218
{
219
    ESCCChannelState *s = opaque;
220
    ESCCSERIOQueue *q = &s->queue;
221

222
    trace_escc_put_queue(CHN_C(s), b);
223
    if (q->count >= ESCC_SERIO_QUEUE_SIZE) {
224
        return;
225
    }
226
    q->data[q->wptr] = b;
227
    if (++q->wptr == ESCC_SERIO_QUEUE_SIZE) {
228
        q->wptr = 0;
229
    }
230
    q->count++;
231
    serial_receive_byte(s, 0);
232
}
233

234
static uint32_t get_queue(void *opaque)
235
{
236
    ESCCChannelState *s = opaque;
237
    ESCCSERIOQueue *q = &s->queue;
238
    int val;
239

240
    if (q->count == 0) {
241
        return 0;
242
    } else {
243
        val = q->data[q->rptr];
244
        if (++q->rptr == ESCC_SERIO_QUEUE_SIZE) {
245
            q->rptr = 0;
246
        }
247
        q->count--;
248
    }
249
    trace_escc_get_queue(CHN_C(s), val);
250
    if (q->count > 0) {
251
        serial_receive_byte(s, 0);
252
    }
253
    return val;
254
}
255

256
static int escc_update_irq_chn(ESCCChannelState *s)
257
{
258
    if ((((s->wregs[W_INTR] & INTR_TXINT) && (s->txint == 1)) ||
259
        /* tx ints enabled, pending */
260
        ((((s->wregs[W_INTR] & INTR_RXMODEMSK) == INTR_RXINT1ST) ||
261
        ((s->wregs[W_INTR] & INTR_RXMODEMSK) == INTR_RXINTALL)) &&
262
            s->rxint == 1) ||
263
        /* rx ints enabled, pending */
264
        ((s->wregs[W_EXTINT] & EXTINT_BRKINT) &&
265
            (s->rregs[R_STATUS] & STATUS_BRK)))) {
266
        /* break int e&p */
267
        return 1;
268
    }
269
    return 0;
270
}
271

272
static void escc_update_irq(ESCCChannelState *s)
273
{
274
    int irq;
275

276
    irq = escc_update_irq_chn(s);
277
    irq |= escc_update_irq_chn(s->otherchn);
278

279
    trace_escc_update_irq(irq);
280
    qemu_set_irq(s->irq, irq);
281
}
282

283
static void escc_reset_chn(ESCCChannelState *s)
284
{
285
    s->reg = 0;
286
    s->rx = s->tx = 0;
287
    s->rxint = s->txint = 0;
288
    s->rxint_under_svc = s->txint_under_svc = 0;
289
    s->e0_mode = s->led_mode = s->caps_lock_mode = s->num_lock_mode = 0;
290
    clear_queue(s);
291
}
292

293
static void escc_soft_reset_chn(ESCCChannelState *s)
294
{
295
    escc_reset_chn(s);
296

297
    s->wregs[W_CMD] = 0;
298
    s->wregs[W_INTR] &= INTR_PAR_SPEC | INTR_WTRQ_TXRX;
299
    s->wregs[W_RXCTRL] &= ~RXCTRL_RXEN;
300
    /* 1 stop bit */
301
    s->wregs[W_TXCTRL1] |= TXCTRL1_1STOP;
302
    s->wregs[W_TXCTRL2] &= TXCTRL2_TXCRC | TXCTRL2_8BITS;
303
    s->wregs[W_MINTR] &= ~MINTR_SOFTIACK;
304
    s->wregs[W_MISC1] &= MISC1_ENC_MASK;
305
    /* PLL disabled */
306
    s->wregs[W_MISC2] &= MISC2_BRG_EN | MISC2_BRG_SRC |
307
                         MISC2_PLLCMD1 | MISC2_PLLCMD2;
308
    s->wregs[W_MISC2] |= MISC2_PLLCMD0;
309
    /* Enable most interrupts */
310
    s->wregs[W_EXTINT] = EXTINT_DCD | EXTINT_SYNCINT | EXTINT_CTSINT |
311
                         EXTINT_TXUNDRN | EXTINT_BRKINT;
312

313
    s->rregs[R_STATUS] &= STATUS_DCD | STATUS_SYNC | STATUS_CTS | STATUS_BRK;
314
    s->rregs[R_STATUS] |= STATUS_TXEMPTY | STATUS_TXUNDRN;
315
    if (s->disabled) {
316
        s->rregs[R_STATUS] |= STATUS_DCD | STATUS_SYNC | STATUS_CTS;
317
    }
318
    s->rregs[R_SPEC] &= SPEC_ALLSENT;
319
    s->rregs[R_SPEC] |= SPEC_BITS8;
320
    s->rregs[R_INTR] = 0;
321
    s->rregs[R_MISC] &= MISC_2CLKMISS;
322
}
323

324
static void escc_hard_reset_chn(ESCCChannelState *s)
325
{
326
    escc_soft_reset_chn(s);
327

328
    /*
329
     * Hard reset is almost identical to soft reset above, except that the
330
     * values of WR9 (W_MINTR), WR10 (W_MISC1), WR11 (W_CLOCK) and WR14
331
     * (W_MISC2) have extra bits forced to 0/1
332
     */
333
    s->wregs[W_MINTR] &= MINTR_VIS | MINTR_NV;
334
    s->wregs[W_MINTR] |= MINTR_RST_B | MINTR_RST_A;
335
    s->wregs[W_MISC1] = 0;
336
    s->wregs[W_CLOCK] = CLOCK_TRXC;
337
    s->wregs[W_MISC2] &= MISC2_PLLCMD1 | MISC2_PLLCMD2;
338
    s->wregs[W_MISC2] |= MISC2_LCL_LOOP | MISC2_PLLCMD0;
339
}
340

341
static void escc_reset(DeviceState *d)
342
{
343
    ESCCState *s = ESCC(d);
344
    int i, j;
345

346
    for (i = 0; i < 2; i++) {
347
        ESCCChannelState *cs = &s->chn[i];
348

349
        /*
350
         * According to the ESCC datasheet "Miscellaneous Questions" section
351
         * on page 384, the values of the ESCC registers are not guaranteed on
352
         * power-on until an explicit hardware or software reset has been
353
         * issued. For now we zero the registers so that a device reset always
354
         * returns the emulated device to a fixed state.
355
         */
356
        for (j = 0; j < ESCC_SERIAL_REGS; j++) {
357
            cs->rregs[j] = 0;
358
            cs->wregs[j] = 0;
359
        }
360

361
        /*
362
         * ...but there is an exception. The "Transmit Interrupts and Transmit
363
         * Buffer Empty Bit" section on page 50 of the ESCC datasheet says of
364
         * the STATUS_TXEMPTY bit in R_STATUS: "After a hardware reset
365
         * (including a hardware reset by software), or a channel reset, this
366
         * bit is set to 1". The Sun PROM checks this bit early on startup and
367
         * gets stuck in an infinite loop if it is not set.
368
         */
369
        cs->rregs[R_STATUS] |= STATUS_TXEMPTY;
370

371
        escc_reset_chn(cs);
372
    }
373
}
374

375
static inline void set_rxint(ESCCChannelState *s)
376
{
377
    s->rxint = 1;
378
    /*
379
     * XXX: missing daisy chaining: escc_chn_b rx should have a lower priority
380
     * than chn_a rx/tx/special_condition service
381
     */
382
    s->rxint_under_svc = 1;
383
    if (s->chn == escc_chn_a) {
384
        s->rregs[R_INTR] |= INTR_RXINTA;
385
        if (s->wregs[W_MINTR] & MINTR_STATUSHI) {
386
            s->otherchn->rregs[R_IVEC] = IVEC_HIRXINTA;
387
        } else {
388
            s->otherchn->rregs[R_IVEC] = IVEC_LORXINTA;
389
        }
390
    } else {
391
        s->otherchn->rregs[R_INTR] |= INTR_RXINTB;
392
        if (s->wregs[W_MINTR] & MINTR_STATUSHI) {
393
            s->rregs[R_IVEC] = IVEC_HIRXINTB;
394
        } else {
395
            s->rregs[R_IVEC] = IVEC_LORXINTB;
396
        }
397
    }
398
    escc_update_irq(s);
399
}
400

401
static inline void set_txint(ESCCChannelState *s)
402
{
403
    s->txint = 1;
404
    if (!s->rxint_under_svc) {
405
        s->txint_under_svc = 1;
406
        if (s->chn == escc_chn_a) {
407
            if (s->wregs[W_INTR] & INTR_TXINT) {
408
                s->rregs[R_INTR] |= INTR_TXINTA;
409
            }
410
            if (s->wregs[W_MINTR] & MINTR_STATUSHI) {
411
                s->otherchn->rregs[R_IVEC] = IVEC_HITXINTA;
412
            } else {
413
                s->otherchn->rregs[R_IVEC] = IVEC_LOTXINTA;
414
            }
415
        } else {
416
            s->rregs[R_IVEC] = IVEC_TXINTB;
417
            if (s->wregs[W_INTR] & INTR_TXINT) {
418
                s->otherchn->rregs[R_INTR] |= INTR_TXINTB;
419
            }
420
        }
421
        escc_update_irq(s);
422
    }
423
}
424

425
static inline void clr_rxint(ESCCChannelState *s)
426
{
427
    s->rxint = 0;
428
    s->rxint_under_svc = 0;
429
    if (s->chn == escc_chn_a) {
430
        if (s->wregs[W_MINTR] & MINTR_STATUSHI) {
431
            s->otherchn->rregs[R_IVEC] = IVEC_HINOINT;
432
        } else {
433
            s->otherchn->rregs[R_IVEC] = IVEC_LONOINT;
434
        }
435
        s->rregs[R_INTR] &= ~INTR_RXINTA;
436
    } else {
437
        if (s->wregs[W_MINTR] & MINTR_STATUSHI) {
438
            s->rregs[R_IVEC] = IVEC_HINOINT;
439
        } else {
440
            s->rregs[R_IVEC] = IVEC_LONOINT;
441
        }
442
        s->otherchn->rregs[R_INTR] &= ~INTR_RXINTB;
443
    }
444
    if (s->txint) {
445
        set_txint(s);
446
    }
447
    escc_update_irq(s);
448
}
449

450
static inline void clr_txint(ESCCChannelState *s)
451
{
452
    s->txint = 0;
453
    s->txint_under_svc = 0;
454
    if (s->chn == escc_chn_a) {
455
        if (s->wregs[W_MINTR] & MINTR_STATUSHI) {
456
            s->otherchn->rregs[R_IVEC] = IVEC_HINOINT;
457
        } else {
458
            s->otherchn->rregs[R_IVEC] = IVEC_LONOINT;
459
        }
460
        s->rregs[R_INTR] &= ~INTR_TXINTA;
461
    } else {
462
        s->otherchn->rregs[R_INTR] &= ~INTR_TXINTB;
463
        if (s->wregs[W_MINTR] & MINTR_STATUSHI) {
464
            s->rregs[R_IVEC] = IVEC_HINOINT;
465
        } else {
466
            s->rregs[R_IVEC] = IVEC_LONOINT;
467
        }
468
        s->otherchn->rregs[R_INTR] &= ~INTR_TXINTB;
469
    }
470
    if (s->rxint) {
471
        set_rxint(s);
472
    }
473
    escc_update_irq(s);
474
}
475

476
static void escc_update_parameters(ESCCChannelState *s)
477
{
478
    int speed, parity, data_bits, stop_bits;
479
    QEMUSerialSetParams ssp;
480

481
    if (!qemu_chr_fe_backend_connected(&s->chr) || s->type != escc_serial) {
482
        return;
483
    }
484

485
    if (s->wregs[W_TXCTRL1] & TXCTRL1_PAREN) {
486
        if (s->wregs[W_TXCTRL1] & TXCTRL1_PAREV) {
487
            parity = 'E';
488
        } else {
489
            parity = 'O';
490
        }
491
    } else {
492
        parity = 'N';
493
    }
494
    if ((s->wregs[W_TXCTRL1] & TXCTRL1_STPMSK) == TXCTRL1_2STOP) {
495
        stop_bits = 2;
496
    } else {
497
        stop_bits = 1;
498
    }
499
    switch (s->wregs[W_TXCTRL2] & TXCTRL2_BITMSK) {
500
    case TXCTRL2_5BITS:
501
        data_bits = 5;
502
        break;
503
    case TXCTRL2_7BITS:
504
        data_bits = 7;
505
        break;
506
    case TXCTRL2_6BITS:
507
        data_bits = 6;
508
        break;
509
    default:
510
    case TXCTRL2_8BITS:
511
        data_bits = 8;
512
        break;
513
    }
514
    speed = s->clock / ((s->wregs[W_BRGLO] | (s->wregs[W_BRGHI] << 8)) + 2);
515
    switch (s->wregs[W_TXCTRL1] & TXCTRL1_CLKMSK) {
516
    case TXCTRL1_CLK1X:
517
        break;
518
    case TXCTRL1_CLK16X:
519
        speed /= 16;
520
        break;
521
    case TXCTRL1_CLK32X:
522
        speed /= 32;
523
        break;
524
    default:
525
    case TXCTRL1_CLK64X:
526
        speed /= 64;
527
        break;
528
    }
529
    ssp.speed = speed;
530
    ssp.parity = parity;
531
    ssp.data_bits = data_bits;
532
    ssp.stop_bits = stop_bits;
533
    trace_escc_update_parameters(CHN_C(s), speed, parity, data_bits, stop_bits);
534
    qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
535
}
536

537
static void escc_mem_write(void *opaque, hwaddr addr,
538
                           uint64_t val, unsigned size)
539
{
540
    ESCCState *serial = opaque;
541
    ESCCChannelState *s;
542
    uint32_t saddr;
543
    int newreg, channel;
544

545
    val &= 0xff;
546
    saddr = (addr >> reg_shift(serial)) & 1;
547
    channel = (addr >> chn_shift(serial)) & 1;
548
    s = &serial->chn[channel];
549
    switch (saddr) {
550
    case SERIAL_CTRL:
551
        trace_escc_mem_writeb_ctrl(CHN_C(s), s->reg, val & 0xff);
552
        newreg = 0;
553
        switch (s->reg) {
554
        case W_CMD:
555
            newreg = val & CMD_PTR_MASK;
556
            val &= CMD_CMD_MASK;
557
            switch (val) {
558
            case CMD_HI:
559
                newreg |= CMD_HI;
560
                break;
561
            case CMD_CLR_TXINT:
562
                clr_txint(s);
563
                break;
564
            case CMD_CLR_IUS:
565
                if (s->rxint_under_svc) {
566
                    s->rxint_under_svc = 0;
567
                    if (s->txint) {
568
                        set_txint(s);
569
                    }
570
                } else if (s->txint_under_svc) {
571
                    s->txint_under_svc = 0;
572
                }
573
                escc_update_irq(s);
574
                break;
575
            default:
576
                break;
577
            }
578
            break;
579
        case W_RXCTRL:
580
            s->wregs[s->reg] = val;
581
            if (val & RXCTRL_HUNT) {
582
                s->rregs[R_STATUS] |= STATUS_SYNC;
583
            }
584
            break;
585
        case W_INTR ... W_IVEC:
586
        case W_SYNC1 ... W_TXBUF:
587
        case W_MISC1 ... W_CLOCK:
588
        case W_MISC2 ... W_EXTINT:
589
            s->wregs[s->reg] = val;
590
            break;
591
        case W_TXCTRL1:
592
            s->wregs[s->reg] = val;
593
            /*
594
             * The ESCC datasheet states that SPEC_ALLSENT is always set in
595
             * sync mode, and set in async mode when all characters have
596
             * cleared the transmitter. Since writes to SERIAL_DATA use the
597
             * blocking qemu_chr_fe_write_all() function to write each
598
             * character, the guest can never see the state when async data
599
             * is in the process of being transmitted so we can set this bit
600
             * unconditionally regardless of the state of the W_TXCTRL1 mode
601
             * bits.
602
             */
603
            s->rregs[R_SPEC] |= SPEC_ALLSENT;
604
            escc_update_parameters(s);
605
            break;
606
        case W_TXCTRL2:
607
            s->wregs[s->reg] = val;
608
            escc_update_parameters(s);
609
            break;
610
        case W_BRGLO:
611
        case W_BRGHI:
612
            s->wregs[s->reg] = val;
613
            s->rregs[s->reg] = val;
614
            escc_update_parameters(s);
615
            break;
616
        case W_MINTR:
617
            switch (val & MINTR_RST_MASK) {
618
            case 0:
619
            default:
620
                break;
621
            case MINTR_RST_B:
622
                trace_escc_soft_reset_chn(CHN_C(&serial->chn[0]));
623
                escc_soft_reset_chn(&serial->chn[0]);
624
                return;
625
            case MINTR_RST_A:
626
                trace_escc_soft_reset_chn(CHN_C(&serial->chn[1]));
627
                escc_soft_reset_chn(&serial->chn[1]);
628
                return;
629
            case MINTR_RST_ALL:
630
                trace_escc_hard_reset();
631
                escc_hard_reset_chn(&serial->chn[0]);
632
                escc_hard_reset_chn(&serial->chn[1]);
633
                return;
634
            }
635
            break;
636
        default:
637
            break;
638
        }
639
        if (s->reg == 0) {
640
            s->reg = newreg;
641
        } else {
642
            s->reg = 0;
643
        }
644
        break;
645
    case SERIAL_DATA:
646
        trace_escc_mem_writeb_data(CHN_C(s), val);
647
        /*
648
         * Lower the irq when data is written to the Tx buffer and no other
649
         * interrupts are currently pending. The irq will be raised again once
650
         * the Tx buffer becomes empty below.
651
         */
652
        s->txint = 0;
653
        escc_update_irq(s);
654
        s->tx = val;
655
        if (s->wregs[W_TXCTRL2] & TXCTRL2_TXEN) { /* tx enabled */
656
            if (s->wregs[W_MISC2] & MISC2_LCL_LOOP) {
657
                serial_receive_byte(s, s->tx);
658
            } else if (qemu_chr_fe_backend_connected(&s->chr)) {
659
                /*
660
                 * XXX this blocks entire thread. Rewrite to use
661
                 * qemu_chr_fe_write and background I/O callbacks
662
                 */
663
                qemu_chr_fe_write_all(&s->chr, &s->tx, 1);
664
            } else if (s->type == escc_kbd && !s->disabled) {
665
                handle_kbd_command(s, val);
666
            }
667
        }
668
        s->rregs[R_STATUS] |= STATUS_TXEMPTY; /* Tx buffer empty */
669
        s->rregs[R_SPEC] |= SPEC_ALLSENT; /* All sent */
670
        set_txint(s);
671
        break;
672
    default:
673
        break;
674
    }
675
}
676

677
static uint64_t escc_mem_read(void *opaque, hwaddr addr,
678
                              unsigned size)
679
{
680
    ESCCState *serial = opaque;
681
    ESCCChannelState *s;
682
    uint32_t saddr;
683
    uint32_t ret;
684
    int channel;
685

686
    saddr = (addr >> reg_shift(serial)) & 1;
687
    channel = (addr >> chn_shift(serial)) & 1;
688
    s = &serial->chn[channel];
689
    switch (saddr) {
690
    case SERIAL_CTRL:
691
        trace_escc_mem_readb_ctrl(CHN_C(s), s->reg, s->rregs[s->reg]);
692
        ret = s->rregs[s->reg];
693
        s->reg = 0;
694
        return ret;
695
    case SERIAL_DATA:
696
        s->rregs[R_STATUS] &= ~STATUS_RXAV;
697
        clr_rxint(s);
698
        if (s->type == escc_kbd || s->type == escc_mouse) {
699
            ret = get_queue(s);
700
        } else {
701
            ret = s->rx;
702
        }
703
        trace_escc_mem_readb_data(CHN_C(s), ret);
704
        qemu_chr_fe_accept_input(&s->chr);
705
        return ret;
706
    default:
707
        break;
708
    }
709
    return 0;
710
}
711

712
static const MemoryRegionOps escc_mem_ops = {
713
    .read = escc_mem_read,
714
    .write = escc_mem_write,
715
    .endianness = DEVICE_NATIVE_ENDIAN,
716
    .valid = {
717
        .min_access_size = 1,
718
        .max_access_size = 1,
719
    },
720
};
721

722
static int serial_can_receive(void *opaque)
723
{
724
    ESCCChannelState *s = opaque;
725
    int ret;
726

727
    if (((s->wregs[W_RXCTRL] & RXCTRL_RXEN) == 0) /* Rx not enabled */
728
        || ((s->rregs[R_STATUS] & STATUS_RXAV) == STATUS_RXAV)) {
729
        /* char already available */
730
        ret = 0;
731
    } else {
732
        ret = 1;
733
    }
734
    return ret;
735
}
736

737
static void serial_receive_byte(ESCCChannelState *s, int ch)
738
{
739
    trace_escc_serial_receive_byte(CHN_C(s), ch);
740
    s->rregs[R_STATUS] |= STATUS_RXAV;
741
    s->rx = ch;
742
    set_rxint(s);
743
}
744

745
static void serial_receive_break(ESCCChannelState *s)
746
{
747
    s->rregs[R_STATUS] |= STATUS_BRK;
748
    escc_update_irq(s);
749
}
750

751
static void serial_receive1(void *opaque, const uint8_t *buf, int size)
752
{
753
    ESCCChannelState *s = opaque;
754
    serial_receive_byte(s, buf[0]);
755
}
756

757
static void serial_event(void *opaque, QEMUChrEvent event)
758
{
759
    ESCCChannelState *s = opaque;
760
    if (event == CHR_EVENT_BREAK) {
761
        serial_receive_break(s);
762
    }
763
}
764

765
static const VMStateDescription vmstate_escc_chn = {
766
    .name = "escc_chn",
767
    .version_id = 2,
768
    .minimum_version_id = 1,
769
    .fields = (const VMStateField[]) {
770
        VMSTATE_UINT32(vmstate_dummy, ESCCChannelState),
771
        VMSTATE_UINT32(reg, ESCCChannelState),
772
        VMSTATE_UINT32(rxint, ESCCChannelState),
773
        VMSTATE_UINT32(txint, ESCCChannelState),
774
        VMSTATE_UINT32(rxint_under_svc, ESCCChannelState),
775
        VMSTATE_UINT32(txint_under_svc, ESCCChannelState),
776
        VMSTATE_UINT8(rx, ESCCChannelState),
777
        VMSTATE_UINT8(tx, ESCCChannelState),
778
        VMSTATE_BUFFER(wregs, ESCCChannelState),
779
        VMSTATE_BUFFER(rregs, ESCCChannelState),
780
        VMSTATE_END_OF_LIST()
781
    }
782
};
783

784
static const VMStateDescription vmstate_escc = {
785
    .name = "escc",
786
    .version_id = 2,
787
    .minimum_version_id = 1,
788
    .fields = (const VMStateField[]) {
789
        VMSTATE_STRUCT_ARRAY(chn, ESCCState, 2, 2, vmstate_escc_chn,
790
                             ESCCChannelState),
791
        VMSTATE_END_OF_LIST()
792
    }
793
};
794

795
static void sunkbd_handle_event(DeviceState *dev, QemuConsole *src,
796
                                InputEvent *evt)
797
{
798
    ESCCChannelState *s = (ESCCChannelState *)dev;
799
    int qcode, keycode;
800
    InputKeyEvent *key;
801

802
    assert(evt->type == INPUT_EVENT_KIND_KEY);
803
    key = evt->u.key.data;
804
    qcode = qemu_input_key_value_to_qcode(key->key);
805
    trace_escc_sunkbd_event_in(qcode, QKeyCode_str(qcode),
806
                               key->down);
807

808
    if (qcode == Q_KEY_CODE_CAPS_LOCK) {
809
        if (key->down) {
810
            s->caps_lock_mode ^= 1;
811
            if (s->caps_lock_mode == 2) {
812
                return; /* Drop second press */
813
            }
814
        } else {
815
            s->caps_lock_mode ^= 2;
816
            if (s->caps_lock_mode == 3) {
817
                return; /* Drop first release */
818
            }
819
        }
820
    }
821

822
    if (qcode == Q_KEY_CODE_NUM_LOCK) {
823
        if (key->down) {
824
            s->num_lock_mode ^= 1;
825
            if (s->num_lock_mode == 2) {
826
                return; /* Drop second press */
827
            }
828
        } else {
829
            s->num_lock_mode ^= 2;
830
            if (s->num_lock_mode == 3) {
831
                return; /* Drop first release */
832
            }
833
        }
834
    }
835

836
    if (qcode >= qemu_input_map_qcode_to_sun_len) {
837
        return;
838
    }
839

840
    keycode = qemu_input_map_qcode_to_sun[qcode];
841
    if (!key->down) {
842
        keycode |= 0x80;
843
    }
844
    trace_escc_sunkbd_event_out(keycode);
845
    put_queue(s, keycode);
846
}
847

848
static const QemuInputHandler sunkbd_handler = {
849
    .name  = "sun keyboard",
850
    .mask  = INPUT_EVENT_MASK_KEY,
851
    .event = sunkbd_handle_event,
852
};
853

854
static uint8_t sunkbd_layout_dip_switch(const char *kbd_layout)
855
{
856
    /* Return the value of the dip-switches in a SUN Type 5 keyboard */
857
    static uint8_t ret = 0xff;
858

859
    if ((ret == 0xff) && kbd_layout) {
860
        int i;
861
        struct layout_values {
862
            const char *lang;
863
            uint8_t dip;
864
        } languages[] =
865
            /*
866
             * Dip values from table 3-16 Layouts for Type 4, 5 and 5c Keyboards
867
             */
868
            {
869
                {"en-us", 0x21}, /* U.S.A. (US5.kt) */
870
                                 /* 0x22 is some other US (US_UNIX5.kt) */
871
                {"fr",    0x23}, /* France (France5.kt) */
872
                {"da",    0x24}, /* Denmark (Denmark5.kt) */
873
                {"de",    0x25}, /* Germany (Germany5.kt) */
874
                {"it",    0x26}, /* Italy (Italy5.kt) */
875
                {"nl",    0x27}, /* The Netherlands (Netherland5.kt) */
876
                {"no",    0x28}, /* Norway (Norway.kt) */
877
                {"pt",    0x29}, /* Portugal (Portugal5.kt) */
878
                {"es",    0x2a}, /* Spain (Spain5.kt) */
879
                {"sv",    0x2b}, /* Sweden (Sweden5.kt) */
880
                {"fr-ch", 0x2c}, /* Switzerland/French (Switzer_Fr5.kt) */
881
                {"de-ch", 0x2d}, /* Switzerland/German (Switzer_Ge5.kt) */
882
                {"en-gb", 0x2e}, /* Great Britain (UK5.kt) */
883
                {"ko",    0x2f}, /* Korea (Korea5.kt) */
884
                {"tw",    0x30}, /* Taiwan (Taiwan5.kt) */
885
                {"ja",    0x31}, /* Japan (Japan5.kt) */
886
                {"fr-ca", 0x32}, /* Canada/French (Canada_Fr5.kt) */
887
                {"hu",    0x33}, /* Hungary (Hungary5.kt) */
888
                {"pl",    0x34}, /* Poland (Poland5.kt) */
889
                {"cz",    0x35}, /* Czech (Czech5.kt) */
890
                {"ru",    0x36}, /* Russia (Russia5.kt) */
891
                {"lv",    0x37}, /* Latvia (Latvia5.kt) */
892
                {"tr",    0x38}, /* Turkey-Q5 (TurkeyQ5.kt) */
893
                {"gr",    0x39}, /* Greece (Greece5.kt) */
894
                {"ar",    0x3a}, /* Arabic (Arabic5.kt) */
895
                {"lt",    0x3b}, /* Lithuania (Lithuania5.kt) */
896
                {"nl-be", 0x3c}, /* Belgium (Belgian5.kt) */
897
                {"be",    0x3c}, /* Belgium (Belgian5.kt) */
898
            };
899

900
        for (i = 0;
901
             i < sizeof(languages) / sizeof(struct layout_values);
902
             i++) {
903
            if (!strcmp(kbd_layout, languages[i].lang)) {
904
                ret = languages[i].dip;
905
                return ret;
906
            }
907
        }
908

909
        /* Found no known language code */
910
        if ((kbd_layout[0] >= '0') && (kbd_layout[0] <= '9')) {
911
            unsigned int tmp;
912

913
            /* As a fallback we also accept numeric dip switch value */
914
            if (!qemu_strtoui(kbd_layout, NULL, 0, &tmp)) {
915
                ret = tmp;
916
            }
917
        }
918
    }
919

920
    if (ret == 0xff) {
921
        /* Final fallback if keyboard_layout was not set or recognized */
922
        ret = 0x21; /* en-us layout */
923
    }
924
    return ret;
925
}
926

927
static void handle_kbd_command(ESCCChannelState *s, int val)
928
{
929
    trace_escc_kbd_command(val);
930
    if (s->led_mode) { /* Ignore led byte */
931
        s->led_mode = 0;
932
        return;
933
    }
934
    switch (val) {
935
    case 1: /* Reset, return type code */
936
        clear_queue(s);
937
        put_queue(s, 0xff);
938
        put_queue(s, 4); /* Type 4 */
939
        put_queue(s, 0x7f);
940
        break;
941
    case 0xe: /* Set leds */
942
        s->led_mode = 1;
943
        break;
944
    case 7: /* Query layout */
945
    case 0xf:
946
        clear_queue(s);
947
        put_queue(s, 0xfe);
948
        put_queue(s, sunkbd_layout_dip_switch(s->sunkbd_layout));
949
        break;
950
    default:
951
        break;
952
    }
953
}
954

955
static void sunmouse_event(void *opaque,
956
                               int dx, int dy, int dz, int buttons_state)
957
{
958
    ESCCChannelState *s = opaque;
959
    int ch;
960

961
    trace_escc_sunmouse_event(dx, dy, buttons_state);
962
    ch = 0x80 | 0x7; /* protocol start byte, no buttons pressed */
963

964
    if (buttons_state & MOUSE_EVENT_LBUTTON) {
965
        ch ^= 0x4;
966
    }
967
    if (buttons_state & MOUSE_EVENT_MBUTTON) {
968
        ch ^= 0x2;
969
    }
970
    if (buttons_state & MOUSE_EVENT_RBUTTON) {
971
        ch ^= 0x1;
972
    }
973

974
    put_queue(s, ch);
975

976
    ch = dx;
977

978
    if (ch > 127) {
979
        ch = 127;
980
    } else if (ch < -127) {
981
        ch = -127;
982
    }
983

984
    put_queue(s, ch & 0xff);
985

986
    ch = -dy;
987

988
    if (ch > 127) {
989
        ch = 127;
990
    } else if (ch < -127) {
991
        ch = -127;
992
    }
993

994
    put_queue(s, ch & 0xff);
995

996
    /* MSC protocol specifies two extra motion bytes */
997

998
    put_queue(s, 0);
999
    put_queue(s, 0);
1000
}
1001

1002
static void escc_init1(Object *obj)
1003
{
1004
    ESCCState *s = ESCC(obj);
1005
    SysBusDevice *dev = SYS_BUS_DEVICE(obj);
1006
    unsigned int i;
1007

1008
    for (i = 0; i < 2; i++) {
1009
        sysbus_init_irq(dev, &s->chn[i].irq);
1010
        s->chn[i].chn = 1 - i;
1011
    }
1012
    s->chn[0].otherchn = &s->chn[1];
1013
    s->chn[1].otherchn = &s->chn[0];
1014

1015
    sysbus_init_mmio(dev, &s->mmio);
1016
}
1017

1018
static void escc_realize(DeviceState *dev, Error **errp)
1019
{
1020
    ESCCState *s = ESCC(dev);
1021
    unsigned int i;
1022

1023
    s->chn[0].disabled = s->disabled;
1024
    s->chn[1].disabled = s->disabled;
1025

1026
    memory_region_init_io(&s->mmio, OBJECT(dev), &escc_mem_ops, s, "escc",
1027
                          ESCC_SIZE << s->it_shift);
1028

1029
    for (i = 0; i < 2; i++) {
1030
        if (qemu_chr_fe_backend_connected(&s->chn[i].chr)) {
1031
            s->chn[i].clock = s->frequency / 2;
1032
            qemu_chr_fe_set_handlers(&s->chn[i].chr, serial_can_receive,
1033
                                     serial_receive1, serial_event, NULL,
1034
                                     &s->chn[i], NULL, true);
1035
        }
1036
    }
1037

1038
    if (s->chn[0].type == escc_mouse) {
1039
        qemu_add_mouse_event_handler(sunmouse_event, &s->chn[0], 0,
1040
                                     "QEMU Sun Mouse");
1041
    }
1042
    if (s->chn[1].type == escc_kbd) {
1043
        s->chn[1].hs = qemu_input_handler_register((DeviceState *)(&s->chn[1]),
1044
                                                   &sunkbd_handler);
1045
    }
1046
}
1047

1048
static Property escc_properties[] = {
1049
    DEFINE_PROP_UINT32("frequency", ESCCState, frequency,   0),
1050
    DEFINE_PROP_UINT32("it_shift",  ESCCState, it_shift,    0),
1051
    DEFINE_PROP_BOOL("bit_swap",    ESCCState, bit_swap,    false),
1052
    DEFINE_PROP_UINT32("disabled",  ESCCState, disabled,    0),
1053
    DEFINE_PROP_UINT32("chnBtype",  ESCCState, chn[0].type, 0),
1054
    DEFINE_PROP_UINT32("chnAtype",  ESCCState, chn[1].type, 0),
1055
    DEFINE_PROP_CHR("chrB", ESCCState, chn[0].chr),
1056
    DEFINE_PROP_CHR("chrA", ESCCState, chn[1].chr),
1057
    DEFINE_PROP_STRING("chnA-sunkbd-layout", ESCCState, chn[1].sunkbd_layout),
1058
    DEFINE_PROP_END_OF_LIST(),
1059
};
1060

1061
static void escc_class_init(ObjectClass *klass, void *data)
1062
{
1063
    DeviceClass *dc = DEVICE_CLASS(klass);
1064

1065
    dc->reset = escc_reset;
1066
    dc->realize = escc_realize;
1067
    dc->vmsd = &vmstate_escc;
1068
    device_class_set_props(dc, escc_properties);
1069
    set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
1070
}
1071

1072
static const TypeInfo escc_info = {
1073
    .name          = TYPE_ESCC,
1074
    .parent        = TYPE_SYS_BUS_DEVICE,
1075
    .instance_size = sizeof(ESCCState),
1076
    .instance_init = escc_init1,
1077
    .class_init    = escc_class_init,
1078
};
1079

1080
static void escc_register_types(void)
1081
{
1082
    type_register_static(&escc_info);
1083
}
1084

1085
type_init(escc_register_types)
1086

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.