qemu-sparc queue
-----BEGIN PGP SIGNATURE----- iQFSBAABCgA8FiEEzGIauY6CIA2RXMnEW8LFb64PMh8FAmE4oxgeHG1hcmsuY2F2 ZS1heWxhbmRAaWxhbmRlLmNvLnVrAAoJEFvCxW+uDzIfZlsIAJg7WX26r0G0fTSI BnmY/Je968rQcLyCNhpUYRaQAeFzCAIBV/nkcVtiDkFMeFCM3rgn/21sbwgRi/K+ 8rRaVT02qcXrUnYniaJcVg51r0aEoMwrt7/GU5utpt21tKIL09ZM5OjFeYHYMFVB D98rzf1b83rbEp+jiwwuFfVC9blaqokNdHHEJUCWgQEurgZD5iJ6NsqeSdtPppr4 2ujH93lTwyijY/oq7pL5zVGmDsnXYBPz/34ox8XF0OCRBLfil10q1jcQOoJBuql4 GZpe885793xUD/8i1LF3KKsXbz7LbjRij7tFKhvgoeGJRNuuVrP8kNVVyaa6no86 b+UskgA= =M7sK -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/mcayland/tags/qemu-sparc-20210908' into staging qemu-sparc queue # gpg: Signature made Wed 08 Sep 2021 12:48:40 BST # gpg: using RSA key CC621AB98E82200D915CC9C45BC2C56FAE0F321F # gpg: issuer "mark.cave-ayland@ilande.co.uk" # gpg: Good signature from "Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>" [full] # Primary key fingerprint: CC62 1AB9 8E82 200D 915C C9C4 5BC2 C56F AE0F 321F * remotes/mcayland/tags/qemu-sparc-20210908: escc: fix STATUS_SYNC bit in R_STATUS register escc: re-use escc_reset_chn() for soft reset escc: remove register changes from escc_reset_chn() escc: implement hard reset as described in the datasheet escc: implement soft reset as described in the datasheet escc: introduce escc_hard_reset_chn() for hardware reset escc: introduce escc_soft_reset_chn() for software reset escc: reset register values to zero in escc_reset() escc: checkpatch fixes sun4m: fix setting CPU id when more than one CPU is present tcg: Drop gen_io_end() target/sparc: Drop use of gen_io_end() Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
500f1f3e81
@ -92,6 +92,3 @@ When the translator is handling an instruction of this kind:
|
||||
}
|
||||
|
||||
* it must end the TB immediately after this instruction
|
||||
|
||||
Note that some older front-ends call a "gen_io_end()" function:
|
||||
this is obsolete and should not be used.
|
||||
|
263
hw/char/escc.c
263
hw/char/escc.c
@ -86,12 +86,15 @@
|
||||
#define W_INTR 1
|
||||
#define INTR_INTALL 0x01
|
||||
#define INTR_TXINT 0x02
|
||||
#define INTR_PAR_SPEC 0x04
|
||||
#define INTR_RXMODEMSK 0x18
|
||||
#define INTR_RXINT1ST 0x08
|
||||
#define INTR_RXINTALL 0x10
|
||||
#define INTR_WTRQ_TXRX 0x20
|
||||
#define W_IVEC 2
|
||||
#define W_RXCTRL 3
|
||||
#define RXCTRL_RXEN 0x01
|
||||
#define RXCTRL_HUNT 0x10
|
||||
#define W_TXCTRL1 4
|
||||
#define TXCTRL1_PAREN 0x01
|
||||
#define TXCTRL1_PAREV 0x02
|
||||
@ -105,6 +108,7 @@
|
||||
#define TXCTRL1_CLK64X 0xc0
|
||||
#define TXCTRL1_CLKMSK 0xc0
|
||||
#define W_TXCTRL2 5
|
||||
#define TXCTRL2_TXCRC 0x01
|
||||
#define TXCTRL2_TXEN 0x08
|
||||
#define TXCTRL2_BITMSK 0x60
|
||||
#define TXCTRL2_5BITS 0x00
|
||||
@ -115,18 +119,27 @@
|
||||
#define W_SYNC2 7
|
||||
#define W_TXBUF 8
|
||||
#define W_MINTR 9
|
||||
#define MINTR_VIS 0x01
|
||||
#define MINTR_NV 0x02
|
||||
#define MINTR_STATUSHI 0x10
|
||||
#define MINTR_SOFTIACK 0x20
|
||||
#define MINTR_RST_MASK 0xc0
|
||||
#define MINTR_RST_B 0x40
|
||||
#define MINTR_RST_A 0x80
|
||||
#define MINTR_RST_ALL 0xc0
|
||||
#define W_MISC1 10
|
||||
#define MISC1_ENC_MASK 0x60
|
||||
#define W_CLOCK 11
|
||||
#define CLOCK_TRXC 0x08
|
||||
#define W_BRGLO 12
|
||||
#define W_BRGHI 13
|
||||
#define W_MISC2 14
|
||||
#define MISC2_PLLDIS 0x30
|
||||
#define MISC2_BRG_EN 0x01
|
||||
#define MISC2_BRG_SRC 0x02
|
||||
#define MISC2_LCL_LOOP 0x10
|
||||
#define MISC2_PLLCMD0 0x20
|
||||
#define MISC2_PLLCMD1 0x40
|
||||
#define MISC2_PLLCMD2 0x80
|
||||
#define W_EXTINT 15
|
||||
#define EXTINT_DCD 0x08
|
||||
#define EXTINT_SYNCINT 0x10
|
||||
@ -170,6 +183,7 @@
|
||||
#define R_RXBUF 8
|
||||
#define R_RXCTRL 9
|
||||
#define R_MISC 10
|
||||
#define MISC_2CLKMISS 0x40
|
||||
#define R_MISC1 11
|
||||
#define R_BRGLO 12
|
||||
#define R_BRGHI 13
|
||||
@ -230,20 +244,23 @@ static uint32_t get_queue(void *opaque)
|
||||
q->count--;
|
||||
}
|
||||
trace_escc_get_queue(CHN_C(s), val);
|
||||
if (q->count > 0)
|
||||
if (q->count > 0) {
|
||||
serial_receive_byte(s, 0);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
static int escc_update_irq_chn(ESCCChannelState *s)
|
||||
{
|
||||
if ((((s->wregs[W_INTR] & INTR_TXINT) && (s->txint == 1)) ||
|
||||
// tx ints enabled, pending
|
||||
((((s->wregs[W_INTR] & INTR_RXMODEMSK) == INTR_RXINT1ST) ||
|
||||
((s->wregs[W_INTR] & INTR_RXMODEMSK) == INTR_RXINTALL)) &&
|
||||
s->rxint == 1) || // rx ints enabled, pending
|
||||
((s->wregs[W_EXTINT] & EXTINT_BRKINT) &&
|
||||
(s->rregs[R_STATUS] & STATUS_BRK)))) { // break int e&p
|
||||
/* tx ints enabled, pending */
|
||||
((((s->wregs[W_INTR] & INTR_RXMODEMSK) == INTR_RXINT1ST) ||
|
||||
((s->wregs[W_INTR] & INTR_RXMODEMSK) == INTR_RXINTALL)) &&
|
||||
s->rxint == 1) ||
|
||||
/* rx ints enabled, pending */
|
||||
((s->wregs[W_EXTINT] & EXTINT_BRKINT) &&
|
||||
(s->rregs[R_STATUS] & STATUS_BRK)))) {
|
||||
/* break int e&p */
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@ -262,26 +279,7 @@ static void escc_update_irq(ESCCChannelState *s)
|
||||
|
||||
static void escc_reset_chn(ESCCChannelState *s)
|
||||
{
|
||||
int i;
|
||||
|
||||
s->reg = 0;
|
||||
for (i = 0; i < ESCC_SERIAL_REGS; i++) {
|
||||
s->rregs[i] = 0;
|
||||
s->wregs[i] = 0;
|
||||
}
|
||||
s->wregs[W_TXCTRL1] = TXCTRL1_1STOP; // 1X divisor, 1 stop bit, no parity
|
||||
s->wregs[W_MINTR] = MINTR_RST_ALL;
|
||||
s->wregs[W_CLOCK] = CLOCK_TRXC; // Synch mode tx clock = TRxC
|
||||
s->wregs[W_MISC2] = MISC2_PLLDIS; // PLL disabled
|
||||
s->wregs[W_EXTINT] = EXTINT_DCD | EXTINT_SYNCINT | EXTINT_CTSINT |
|
||||
EXTINT_TXUNDRN | EXTINT_BRKINT; // Enable most interrupts
|
||||
if (s->disabled)
|
||||
s->rregs[R_STATUS] = STATUS_TXEMPTY | STATUS_DCD | STATUS_SYNC |
|
||||
STATUS_CTS | STATUS_TXUNDRN;
|
||||
else
|
||||
s->rregs[R_STATUS] = STATUS_TXEMPTY | STATUS_TXUNDRN;
|
||||
s->rregs[R_SPEC] = SPEC_BITS8 | SPEC_ALLSENT;
|
||||
|
||||
s->rx = s->tx = 0;
|
||||
s->rxint = s->txint = 0;
|
||||
s->rxint_under_svc = s->txint_under_svc = 0;
|
||||
@ -289,32 +287,99 @@ static void escc_reset_chn(ESCCChannelState *s)
|
||||
clear_queue(s);
|
||||
}
|
||||
|
||||
static void escc_soft_reset_chn(ESCCChannelState *s)
|
||||
{
|
||||
escc_reset_chn(s);
|
||||
|
||||
s->wregs[W_CMD] = 0;
|
||||
s->wregs[W_INTR] &= INTR_PAR_SPEC | INTR_WTRQ_TXRX;
|
||||
s->wregs[W_RXCTRL] &= ~RXCTRL_RXEN;
|
||||
/* 1 stop bit */
|
||||
s->wregs[W_TXCTRL1] |= TXCTRL1_1STOP;
|
||||
s->wregs[W_TXCTRL2] &= TXCTRL2_TXCRC | TXCTRL2_8BITS;
|
||||
s->wregs[W_MINTR] &= ~MINTR_SOFTIACK;
|
||||
s->wregs[W_MISC1] &= MISC1_ENC_MASK;
|
||||
/* PLL disabled */
|
||||
s->wregs[W_MISC2] &= MISC2_BRG_EN | MISC2_BRG_SRC |
|
||||
MISC2_PLLCMD1 | MISC2_PLLCMD2;
|
||||
s->wregs[W_MISC2] |= MISC2_PLLCMD0;
|
||||
/* Enable most interrupts */
|
||||
s->wregs[W_EXTINT] = EXTINT_DCD | EXTINT_SYNCINT | EXTINT_CTSINT |
|
||||
EXTINT_TXUNDRN | EXTINT_BRKINT;
|
||||
|
||||
s->rregs[R_STATUS] &= STATUS_DCD | STATUS_SYNC | STATUS_CTS | STATUS_BRK;
|
||||
s->rregs[R_STATUS] |= STATUS_TXEMPTY | STATUS_TXUNDRN;
|
||||
if (s->disabled) {
|
||||
s->rregs[R_STATUS] |= STATUS_DCD | STATUS_SYNC | STATUS_CTS;
|
||||
}
|
||||
s->rregs[R_SPEC] &= SPEC_ALLSENT;
|
||||
s->rregs[R_SPEC] |= SPEC_BITS8;
|
||||
s->rregs[R_INTR] = 0;
|
||||
s->rregs[R_MISC] &= MISC_2CLKMISS;
|
||||
}
|
||||
|
||||
static void escc_hard_reset_chn(ESCCChannelState *s)
|
||||
{
|
||||
escc_soft_reset_chn(s);
|
||||
|
||||
/*
|
||||
* Hard reset is almost identical to soft reset above, except that the
|
||||
* values of WR9 (W_MINTR), WR10 (W_MISC1), WR11 (W_CLOCK) and WR14
|
||||
* (W_MISC2) have extra bits forced to 0/1
|
||||
*/
|
||||
s->wregs[W_MINTR] &= MINTR_VIS | MINTR_NV;
|
||||
s->wregs[W_MINTR] |= MINTR_RST_B | MINTR_RST_A;
|
||||
s->wregs[W_MISC1] = 0;
|
||||
s->wregs[W_CLOCK] = CLOCK_TRXC;
|
||||
s->wregs[W_MISC2] &= MISC2_PLLCMD1 | MISC2_PLLCMD2;
|
||||
s->wregs[W_MISC2] |= MISC2_LCL_LOOP | MISC2_PLLCMD0;
|
||||
}
|
||||
|
||||
static void escc_reset(DeviceState *d)
|
||||
{
|
||||
ESCCState *s = ESCC(d);
|
||||
int i, j;
|
||||
|
||||
escc_reset_chn(&s->chn[0]);
|
||||
escc_reset_chn(&s->chn[1]);
|
||||
for (i = 0; i < 2; i++) {
|
||||
ESCCChannelState *cs = &s->chn[i];
|
||||
|
||||
/*
|
||||
* According to the ESCC datasheet "Miscellaneous Questions" section
|
||||
* on page 384, the values of the ESCC registers are not guaranteed on
|
||||
* power-on until an explicit hardware or software reset has been
|
||||
* issued. For now we zero the registers so that a device reset always
|
||||
* returns the emulated device to a fixed state.
|
||||
*/
|
||||
for (j = 0; j < ESCC_SERIAL_REGS; j++) {
|
||||
cs->rregs[j] = 0;
|
||||
cs->wregs[j] = 0;
|
||||
}
|
||||
escc_reset_chn(cs);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void set_rxint(ESCCChannelState *s)
|
||||
{
|
||||
s->rxint = 1;
|
||||
/* XXX: missing daisy chainnig: escc_chn_b rx should have a lower priority
|
||||
than chn_a rx/tx/special_condition service*/
|
||||
/*
|
||||
* XXX: missing daisy chaining: escc_chn_b rx should have a lower priority
|
||||
* than chn_a rx/tx/special_condition service
|
||||
*/
|
||||
s->rxint_under_svc = 1;
|
||||
if (s->chn == escc_chn_a) {
|
||||
s->rregs[R_INTR] |= INTR_RXINTA;
|
||||
if (s->wregs[W_MINTR] & MINTR_STATUSHI)
|
||||
if (s->wregs[W_MINTR] & MINTR_STATUSHI) {
|
||||
s->otherchn->rregs[R_IVEC] = IVEC_HIRXINTA;
|
||||
else
|
||||
} else {
|
||||
s->otherchn->rregs[R_IVEC] = IVEC_LORXINTA;
|
||||
}
|
||||
} else {
|
||||
s->otherchn->rregs[R_INTR] |= INTR_RXINTB;
|
||||
if (s->wregs[W_MINTR] & MINTR_STATUSHI)
|
||||
if (s->wregs[W_MINTR] & MINTR_STATUSHI) {
|
||||
s->rregs[R_IVEC] = IVEC_HIRXINTB;
|
||||
else
|
||||
} else {
|
||||
s->rregs[R_IVEC] = IVEC_LORXINTB;
|
||||
}
|
||||
}
|
||||
escc_update_irq(s);
|
||||
}
|
||||
@ -328,17 +393,18 @@ static inline void set_txint(ESCCChannelState *s)
|
||||
if (s->wregs[W_INTR] & INTR_TXINT) {
|
||||
s->rregs[R_INTR] |= INTR_TXINTA;
|
||||
}
|
||||
if (s->wregs[W_MINTR] & MINTR_STATUSHI)
|
||||
if (s->wregs[W_MINTR] & MINTR_STATUSHI) {
|
||||
s->otherchn->rregs[R_IVEC] = IVEC_HITXINTA;
|
||||
else
|
||||
} else {
|
||||
s->otherchn->rregs[R_IVEC] = IVEC_LOTXINTA;
|
||||
}
|
||||
} else {
|
||||
s->rregs[R_IVEC] = IVEC_TXINTB;
|
||||
if (s->wregs[W_INTR] & INTR_TXINT) {
|
||||
s->otherchn->rregs[R_INTR] |= INTR_TXINTB;
|
||||
}
|
||||
}
|
||||
escc_update_irq(s);
|
||||
escc_update_irq(s);
|
||||
}
|
||||
}
|
||||
|
||||
@ -347,20 +413,23 @@ static inline void clr_rxint(ESCCChannelState *s)
|
||||
s->rxint = 0;
|
||||
s->rxint_under_svc = 0;
|
||||
if (s->chn == escc_chn_a) {
|
||||
if (s->wregs[W_MINTR] & MINTR_STATUSHI)
|
||||
if (s->wregs[W_MINTR] & MINTR_STATUSHI) {
|
||||
s->otherchn->rregs[R_IVEC] = IVEC_HINOINT;
|
||||
else
|
||||
} else {
|
||||
s->otherchn->rregs[R_IVEC] = IVEC_LONOINT;
|
||||
}
|
||||
s->rregs[R_INTR] &= ~INTR_RXINTA;
|
||||
} else {
|
||||
if (s->wregs[W_MINTR] & MINTR_STATUSHI)
|
||||
if (s->wregs[W_MINTR] & MINTR_STATUSHI) {
|
||||
s->rregs[R_IVEC] = IVEC_HINOINT;
|
||||
else
|
||||
} else {
|
||||
s->rregs[R_IVEC] = IVEC_LONOINT;
|
||||
}
|
||||
s->otherchn->rregs[R_INTR] &= ~INTR_RXINTB;
|
||||
}
|
||||
if (s->txint)
|
||||
if (s->txint) {
|
||||
set_txint(s);
|
||||
}
|
||||
escc_update_irq(s);
|
||||
}
|
||||
|
||||
@ -369,21 +438,24 @@ static inline void clr_txint(ESCCChannelState *s)
|
||||
s->txint = 0;
|
||||
s->txint_under_svc = 0;
|
||||
if (s->chn == escc_chn_a) {
|
||||
if (s->wregs[W_MINTR] & MINTR_STATUSHI)
|
||||
if (s->wregs[W_MINTR] & MINTR_STATUSHI) {
|
||||
s->otherchn->rregs[R_IVEC] = IVEC_HINOINT;
|
||||
else
|
||||
} else {
|
||||
s->otherchn->rregs[R_IVEC] = IVEC_LONOINT;
|
||||
}
|
||||
s->rregs[R_INTR] &= ~INTR_TXINTA;
|
||||
} else {
|
||||
s->otherchn->rregs[R_INTR] &= ~INTR_TXINTB;
|
||||
if (s->wregs[W_MINTR] & MINTR_STATUSHI)
|
||||
if (s->wregs[W_MINTR] & MINTR_STATUSHI) {
|
||||
s->rregs[R_IVEC] = IVEC_HINOINT;
|
||||
else
|
||||
} else {
|
||||
s->rregs[R_IVEC] = IVEC_LONOINT;
|
||||
}
|
||||
s->otherchn->rregs[R_INTR] &= ~INTR_TXINTB;
|
||||
}
|
||||
if (s->rxint)
|
||||
if (s->rxint) {
|
||||
set_rxint(s);
|
||||
}
|
||||
escc_update_irq(s);
|
||||
}
|
||||
|
||||
@ -392,21 +464,24 @@ static void escc_update_parameters(ESCCChannelState *s)
|
||||
int speed, parity, data_bits, stop_bits;
|
||||
QEMUSerialSetParams ssp;
|
||||
|
||||
if (!qemu_chr_fe_backend_connected(&s->chr) || s->type != escc_serial)
|
||||
if (!qemu_chr_fe_backend_connected(&s->chr) || s->type != escc_serial) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (s->wregs[W_TXCTRL1] & TXCTRL1_PAREN) {
|
||||
if (s->wregs[W_TXCTRL1] & TXCTRL1_PAREV)
|
||||
if (s->wregs[W_TXCTRL1] & TXCTRL1_PAREV) {
|
||||
parity = 'E';
|
||||
else
|
||||
} else {
|
||||
parity = 'O';
|
||||
}
|
||||
} else {
|
||||
parity = 'N';
|
||||
}
|
||||
if ((s->wregs[W_TXCTRL1] & TXCTRL1_STPMSK) == TXCTRL1_2STOP)
|
||||
if ((s->wregs[W_TXCTRL1] & TXCTRL1_STPMSK) == TXCTRL1_2STOP) {
|
||||
stop_bits = 2;
|
||||
else
|
||||
} else {
|
||||
stop_bits = 1;
|
||||
}
|
||||
switch (s->wregs[W_TXCTRL2] & TXCTRL2_BITMSK) {
|
||||
case TXCTRL2_5BITS:
|
||||
data_bits = 5;
|
||||
@ -487,7 +562,13 @@ static void escc_mem_write(void *opaque, hwaddr addr,
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case W_INTR ... W_RXCTRL:
|
||||
case W_RXCTRL:
|
||||
s->wregs[s->reg] = val;
|
||||
if (val & RXCTRL_HUNT) {
|
||||
s->rregs[R_STATUS] |= STATUS_SYNC;
|
||||
}
|
||||
break;
|
||||
case W_INTR ... W_IVEC:
|
||||
case W_SYNC1 ... W_TXBUF:
|
||||
case W_MISC1 ... W_CLOCK:
|
||||
case W_MISC2 ... W_EXTINT:
|
||||
@ -510,23 +591,28 @@ static void escc_mem_write(void *opaque, hwaddr addr,
|
||||
default:
|
||||
break;
|
||||
case MINTR_RST_B:
|
||||
escc_reset_chn(&serial->chn[0]);
|
||||
trace_escc_soft_reset_chn(CHN_C(&serial->chn[0]));
|
||||
escc_soft_reset_chn(&serial->chn[0]);
|
||||
return;
|
||||
case MINTR_RST_A:
|
||||
escc_reset_chn(&serial->chn[1]);
|
||||
trace_escc_soft_reset_chn(CHN_C(&serial->chn[1]));
|
||||
escc_soft_reset_chn(&serial->chn[1]);
|
||||
return;
|
||||
case MINTR_RST_ALL:
|
||||
escc_reset(DEVICE(serial));
|
||||
trace_escc_hard_reset();
|
||||
escc_hard_reset_chn(&serial->chn[0]);
|
||||
escc_hard_reset_chn(&serial->chn[1]);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (s->reg == 0)
|
||||
if (s->reg == 0) {
|
||||
s->reg = newreg;
|
||||
else
|
||||
} else {
|
||||
s->reg = 0;
|
||||
}
|
||||
break;
|
||||
case SERIAL_DATA:
|
||||
trace_escc_mem_writeb_data(CHN_C(s), val);
|
||||
@ -538,17 +624,19 @@ static void escc_mem_write(void *opaque, hwaddr addr,
|
||||
s->txint = 0;
|
||||
escc_update_irq(s);
|
||||
s->tx = val;
|
||||
if (s->wregs[W_TXCTRL2] & TXCTRL2_TXEN) { // tx enabled
|
||||
if (s->wregs[W_TXCTRL2] & TXCTRL2_TXEN) { /* tx enabled */
|
||||
if (qemu_chr_fe_backend_connected(&s->chr)) {
|
||||
/* XXX this blocks entire thread. Rewrite to use
|
||||
* qemu_chr_fe_write and background I/O callbacks */
|
||||
/*
|
||||
* XXX this blocks entire thread. Rewrite to use
|
||||
* qemu_chr_fe_write and background I/O callbacks
|
||||
*/
|
||||
qemu_chr_fe_write_all(&s->chr, &s->tx, 1);
|
||||
} else if (s->type == escc_kbd && !s->disabled) {
|
||||
handle_kbd_command(s, val);
|
||||
}
|
||||
}
|
||||
s->rregs[R_STATUS] |= STATUS_TXEMPTY; // Tx buffer empty
|
||||
s->rregs[R_SPEC] |= SPEC_ALLSENT; // All sent
|
||||
s->rregs[R_STATUS] |= STATUS_TXEMPTY; /* Tx buffer empty */
|
||||
s->rregs[R_SPEC] |= SPEC_ALLSENT; /* All sent */
|
||||
set_txint(s);
|
||||
break;
|
||||
default:
|
||||
@ -606,12 +694,13 @@ static int serial_can_receive(void *opaque)
|
||||
ESCCChannelState *s = opaque;
|
||||
int ret;
|
||||
|
||||
if (((s->wregs[W_RXCTRL] & RXCTRL_RXEN) == 0) // Rx not enabled
|
||||
|| ((s->rregs[R_STATUS] & STATUS_RXAV) == STATUS_RXAV))
|
||||
// char already available
|
||||
if (((s->wregs[W_RXCTRL] & RXCTRL_RXEN) == 0) /* Rx not enabled */
|
||||
|| ((s->rregs[R_STATUS] & STATUS_RXAV) == STATUS_RXAV)) {
|
||||
/* char already available */
|
||||
ret = 0;
|
||||
else
|
||||
} else {
|
||||
ret = 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -638,12 +727,13 @@ static void serial_receive1(void *opaque, const uint8_t *buf, int size)
|
||||
static void serial_event(void *opaque, QEMUChrEvent event)
|
||||
{
|
||||
ESCCChannelState *s = opaque;
|
||||
if (event == CHR_EVENT_BREAK)
|
||||
if (event == CHR_EVENT_BREAK) {
|
||||
serial_receive_break(s);
|
||||
}
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_escc_chn = {
|
||||
.name ="escc_chn",
|
||||
.name = "escc_chn",
|
||||
.version_id = 2,
|
||||
.minimum_version_id = 1,
|
||||
.fields = (VMStateField[]) {
|
||||
@ -662,7 +752,7 @@ static const VMStateDescription vmstate_escc_chn = {
|
||||
};
|
||||
|
||||
static const VMStateDescription vmstate_escc = {
|
||||
.name ="escc",
|
||||
.name = "escc",
|
||||
.version_id = 2,
|
||||
.minimum_version_id = 1,
|
||||
.fields = (VMStateField[]) {
|
||||
@ -734,21 +824,21 @@ static QemuInputHandler sunkbd_handler = {
|
||||
static void handle_kbd_command(ESCCChannelState *s, int val)
|
||||
{
|
||||
trace_escc_kbd_command(val);
|
||||
if (s->led_mode) { // Ignore led byte
|
||||
if (s->led_mode) { /* Ignore led byte */
|
||||
s->led_mode = 0;
|
||||
return;
|
||||
}
|
||||
switch (val) {
|
||||
case 1: // Reset, return type code
|
||||
case 1: /* Reset, return type code */
|
||||
clear_queue(s);
|
||||
put_queue(s, 0xff);
|
||||
put_queue(s, 4); // Type 4
|
||||
put_queue(s, 4); /* Type 4 */
|
||||
put_queue(s, 0x7f);
|
||||
break;
|
||||
case 0xe: // Set leds
|
||||
case 0xe: /* Set leds */
|
||||
s->led_mode = 1;
|
||||
break;
|
||||
case 7: // Query layout
|
||||
case 7: /* Query layout */
|
||||
case 0xf:
|
||||
clear_queue(s);
|
||||
put_queue(s, 0xfe);
|
||||
@ -768,34 +858,39 @@ static void sunmouse_event(void *opaque,
|
||||
trace_escc_sunmouse_event(dx, dy, buttons_state);
|
||||
ch = 0x80 | 0x7; /* protocol start byte, no buttons pressed */
|
||||
|
||||
if (buttons_state & MOUSE_EVENT_LBUTTON)
|
||||
if (buttons_state & MOUSE_EVENT_LBUTTON) {
|
||||
ch ^= 0x4;
|
||||
if (buttons_state & MOUSE_EVENT_MBUTTON)
|
||||
}
|
||||
if (buttons_state & MOUSE_EVENT_MBUTTON) {
|
||||
ch ^= 0x2;
|
||||
if (buttons_state & MOUSE_EVENT_RBUTTON)
|
||||
}
|
||||
if (buttons_state & MOUSE_EVENT_RBUTTON) {
|
||||
ch ^= 0x1;
|
||||
}
|
||||
|
||||
put_queue(s, ch);
|
||||
|
||||
ch = dx;
|
||||
|
||||
if (ch > 127)
|
||||
if (ch > 127) {
|
||||
ch = 127;
|
||||
else if (ch < -127)
|
||||
} else if (ch < -127) {
|
||||
ch = -127;
|
||||
}
|
||||
|
||||
put_queue(s, ch & 0xff);
|
||||
|
||||
ch = -dy;
|
||||
|
||||
if (ch > 127)
|
||||
if (ch > 127) {
|
||||
ch = 127;
|
||||
else if (ch < -127)
|
||||
} else if (ch < -127) {
|
||||
ch = -127;
|
||||
}
|
||||
|
||||
put_queue(s, ch & 0xff);
|
||||
|
||||
// MSC protocol specify two extra motion bytes
|
||||
/* MSC protocol specifies two extra motion bytes */
|
||||
|
||||
put_queue(s, 0);
|
||||
put_queue(s, 0);
|
||||
|
@ -36,6 +36,8 @@ grlib_apbuart_writel_unknown(uint64_t addr, uint32_t value) "addr 0x%"PRIx64" va
|
||||
grlib_apbuart_readl_unknown(uint64_t addr) "addr 0x%"PRIx64
|
||||
|
||||
# escc.c
|
||||
escc_hard_reset(void) "hard reset"
|
||||
escc_soft_reset_chn(char channel) "soft reset channel %c"
|
||||
escc_put_queue(char channel, int b) "channel %c put: 0x%02x"
|
||||
escc_get_queue(char channel, int val) "channel %c get 0x%02x"
|
||||
escc_update_irq(int irq) "IRQ = %d"
|
||||
|
@ -803,11 +803,11 @@ static void cpu_devinit(const char *cpu_type, unsigned int id,
|
||||
cpu = SPARC_CPU(object_new(cpu_type));
|
||||
env = &cpu->env;
|
||||
|
||||
cpu_sparc_set_id(env, id);
|
||||
qemu_register_reset(sun4m_cpu_reset, cpu);
|
||||
object_property_set_bool(OBJECT(cpu), "start-powered-off", id != 0,
|
||||
&error_fatal);
|
||||
qdev_realize_and_unref(DEVICE(cpu), NULL, &error_fatal);
|
||||
cpu_sparc_set_id(env, id);
|
||||
*cpu_irqs = qemu_allocate_irqs(cpu_set_irq, cpu, MAX_PILS);
|
||||
env->prom_addr = prom_addr;
|
||||
}
|
||||
|
@ -17,22 +17,6 @@ static inline void gen_io_start(void)
|
||||
tcg_temp_free_i32(tmp);
|
||||
}
|
||||
|
||||
/*
|
||||
* cpu->can_do_io is cleared automatically at the beginning of
|
||||
* each translation block. The cost is minimal and only paid
|
||||
* for -icount, plus it would be very easy to forget doing it
|
||||
* in the translator. Therefore, backends only need to call
|
||||
* gen_io_start.
|
||||
*/
|
||||
static inline void gen_io_end(void)
|
||||
{
|
||||
TCGv_i32 tmp = tcg_const_i32(0);
|
||||
tcg_gen_st_i32(tmp, cpu_env,
|
||||
offsetof(ArchCPU, parent_obj.can_do_io) -
|
||||
offsetof(ArchCPU, env));
|
||||
tcg_temp_free_i32(tmp);
|
||||
}
|
||||
|
||||
static inline void gen_tb_start(const TranslationBlock *tb)
|
||||
{
|
||||
TCGv_i32 count;
|
||||
@ -64,7 +48,16 @@ static inline void gen_tb_start(const TranslationBlock *tb)
|
||||
tcg_gen_st16_i32(count, cpu_env,
|
||||
offsetof(ArchCPU, neg.icount_decr.u16.low) -
|
||||
offsetof(ArchCPU, env));
|
||||
gen_io_end();
|
||||
/*
|
||||
* cpu->can_do_io is cleared automatically here at the beginning of
|
||||
* each translation block. The cost is minimal and only paid for
|
||||
* -icount, plus it would be very easy to forget doing it in the
|
||||
* translator. Doing it here means we don't need a gen_io_end() to
|
||||
* go with gen_io_start().
|
||||
*/
|
||||
tcg_gen_st_i32(tcg_constant_i32(0), cpu_env,
|
||||
offsetof(ArchCPU, parent_obj.can_do_io) -
|
||||
offsetof(ArchCPU, env));
|
||||
}
|
||||
|
||||
tcg_temp_free_i32(count);
|
||||
|
@ -3401,7 +3401,8 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
|
||||
tcg_temp_free_i32(r_const);
|
||||
gen_store_gpr(dc, rd, cpu_dst);
|
||||
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
|
||||
gen_io_end();
|
||||
/* I/O operations in icount mode must end the TB */
|
||||
dc->base.is_jmp = DISAS_EXIT;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -3454,7 +3455,8 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
|
||||
tcg_temp_free_i32(r_const);
|
||||
gen_store_gpr(dc, rd, cpu_dst);
|
||||
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
|
||||
gen_io_end();
|
||||
/* I/O operations in icount mode must end the TB */
|
||||
dc->base.is_jmp = DISAS_EXIT;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -3588,7 +3590,8 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
|
||||
tcg_temp_free_ptr(r_tickptr);
|
||||
tcg_temp_free_i32(r_const);
|
||||
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
|
||||
gen_io_end();
|
||||
/* I/O operations in icount mode must end the TB */
|
||||
dc->base.is_jmp = DISAS_EXIT;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -4582,7 +4585,8 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
|
||||
}
|
||||
gen_helper_wrpstate(cpu_env, cpu_tmp0);
|
||||
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
|
||||
gen_io_end();
|
||||
/* I/O ops in icount mode must end the TB */
|
||||
dc->base.is_jmp = DISAS_EXIT;
|
||||
}
|
||||
dc->npc = DYNAMIC_PC;
|
||||
break;
|
||||
@ -4598,7 +4602,8 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
|
||||
}
|
||||
gen_helper_wrpil(cpu_env, cpu_tmp0);
|
||||
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
|
||||
gen_io_end();
|
||||
/* I/O ops in icount mode must end the TB */
|
||||
dc->base.is_jmp = DISAS_EXIT;
|
||||
}
|
||||
break;
|
||||
case 9: // cwp
|
||||
@ -4697,10 +4702,6 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
|
||||
gen_helper_tick_set_limit(r_tickptr,
|
||||
cpu_hstick_cmpr);
|
||||
tcg_temp_free_ptr(r_tickptr);
|
||||
if (tb_cflags(dc->base.tb) &
|
||||
CF_USE_ICOUNT) {
|
||||
gen_io_end();
|
||||
}
|
||||
/* End TB to handle timer interrupt */
|
||||
dc->base.is_jmp = DISAS_EXIT;
|
||||
}
|
||||
@ -5327,9 +5328,6 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
|
||||
gen_io_start();
|
||||
}
|
||||
gen_helper_done(cpu_env);
|
||||
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
|
||||
gen_io_end();
|
||||
}
|
||||
goto jmp_insn;
|
||||
case 1:
|
||||
if (!supervisor(dc))
|
||||
@ -5340,9 +5338,6 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
|
||||
gen_io_start();
|
||||
}
|
||||
gen_helper_retry(cpu_env);
|
||||
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
|
||||
gen_io_end();
|
||||
}
|
||||
goto jmp_insn;
|
||||
default:
|
||||
goto illegal_insn;
|
||||
|
Loading…
Reference in New Issue
Block a user