summaryrefslogtreecommitdiffstats
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/char/escc.c263
-rw-r--r--hw/char/trace-events2
-rw-r--r--hw/input/ps2.c214
-rw-r--r--hw/m68k/q800.c38
-rw-r--r--hw/misc/mac_via.c547
-rw-r--r--hw/sparc/sun4m.c2
6 files changed, 593 insertions, 473 deletions
diff --git a/hw/char/escc.c b/hw/char/escc.c
index 52e7978287..0fce4f6324 100644
--- a/hw/char/escc.c
+++ b/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);
diff --git a/hw/char/trace-events b/hw/char/trace-events
index 1436fb462d..b774832af4 100644
--- a/hw/char/trace-events
+++ b/hw/char/trace-events
@@ -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"
diff --git a/hw/input/ps2.c b/hw/input/ps2.c
index 8dd482c1f6..9376a8f4ce 100644
--- a/hw/input/ps2.c
+++ b/hw/input/ps2.c
@@ -74,7 +74,13 @@
#define MOUSE_STATUS_ENABLED 0x20
#define MOUSE_STATUS_SCALE21 0x10
-#define PS2_QUEUE_SIZE 16 /* Buffer size required by PS/2 protocol */
+/*
+ * PS/2 buffer size. Keep 256 bytes for compatibility with
+ * older QEMU versions.
+ */
+#define PS2_BUFFER_SIZE 256
+#define PS2_QUEUE_SIZE 16 /* Queue size required by PS/2 protocol */
+#define PS2_QUEUE_HEADROOM 8 /* Queue size for keyboard command replies */
/* Bits for 'modifiers' field in PS2KbdState */
#define MOD_CTRL_L (1 << 0)
@@ -85,10 +91,8 @@
#define MOD_ALT_R (1 << 5)
typedef struct {
- /* Keep the data array 256 bytes long, which compatibility
- with older qemu versions. */
- uint8_t data[256];
- int rptr, wptr, count;
+ uint8_t data[PS2_BUFFER_SIZE];
+ int rptr, wptr, cwptr, count;
} PS2Queue;
struct PS2State {
@@ -183,6 +187,7 @@ static void ps2_reset_queue(PS2State *s)
q->rptr = 0;
q->wptr = 0;
+ q->cwptr = -1;
q->count = 0;
}
@@ -195,13 +200,14 @@ void ps2_queue_noirq(PS2State *s, int b)
{
PS2Queue *q = &s->queue;
- if (q->count == PS2_QUEUE_SIZE) {
+ if (q->count >= PS2_QUEUE_SIZE) {
return;
}
q->data[q->wptr] = b;
- if (++q->wptr == PS2_QUEUE_SIZE)
+ if (++q->wptr == PS2_BUFFER_SIZE) {
q->wptr = 0;
+ }
q->count++;
}
@@ -256,6 +262,63 @@ void ps2_queue_4(PS2State *s, int b1, int b2, int b3, int b4)
ps2_raise_irq(s);
}
+static void ps2_cqueue_data(PS2Queue *q, int b)
+{
+ q->data[q->cwptr] = b;
+ if (++q->cwptr >= PS2_BUFFER_SIZE) {
+ q->cwptr = 0;
+ }
+ q->count++;
+}
+
+static void ps2_cqueue_1(PS2State *s, int b1)
+{
+ PS2Queue *q = &s->queue;
+
+ q->rptr = (q->rptr - 1) & (PS2_BUFFER_SIZE - 1);
+ q->cwptr = q->rptr;
+ ps2_cqueue_data(q, b1);
+ ps2_raise_irq(s);
+}
+
+static void ps2_cqueue_2(PS2State *s, int b1, int b2)
+{
+ PS2Queue *q = &s->queue;
+
+ q->rptr = (q->rptr - 2) & (PS2_BUFFER_SIZE - 1);
+ q->cwptr = q->rptr;
+ ps2_cqueue_data(q, b1);
+ ps2_cqueue_data(q, b2);
+ ps2_raise_irq(s);
+}
+
+static void ps2_cqueue_3(PS2State *s, int b1, int b2, int b3)
+{
+ PS2Queue *q = &s->queue;
+
+ q->rptr = (q->rptr - 3) & (PS2_BUFFER_SIZE - 1);
+ q->cwptr = q->rptr;
+ ps2_cqueue_data(q, b1);
+ ps2_cqueue_data(q, b2);
+ ps2_cqueue_data(q, b3);
+ ps2_raise_irq(s);
+}
+
+static void ps2_cqueue_reset(PS2State *s)
+{
+ PS2Queue *q = &s->queue;
+ int ccount;
+
+ if (q->cwptr == -1) {
+ return;
+ }
+
+ ccount = (q->cwptr - q->rptr) & (PS2_BUFFER_SIZE - 1);
+ q->count -= ccount;
+ q->rptr = q->cwptr;
+ q->cwptr = -1;
+}
+
/* keycode is the untranslated scancode in the current scancode set. */
static void ps2_put_keycode(void *opaque, int keycode)
{
@@ -509,14 +572,20 @@ uint32_t ps2_read_data(PS2State *s)
(needed for EMM386) */
/* XXX: need a timer to do things correctly */
index = q->rptr - 1;
- if (index < 0)
- index = PS2_QUEUE_SIZE - 1;
+ if (index < 0) {
+ index = PS2_BUFFER_SIZE - 1;
+ }
val = q->data[index];
} else {
val = q->data[q->rptr];
- if (++q->rptr == PS2_QUEUE_SIZE)
+ if (++q->rptr == PS2_BUFFER_SIZE) {
q->rptr = 0;
+ }
q->count--;
+ if (q->rptr == q->cwptr) {
+ /* command reply queue is empty */
+ q->cwptr = -1;
+ }
/* reading deasserts IRQ */
s->update_irq(s->update_arg, 0);
/* reassert IRQs if data left */
@@ -548,92 +617,83 @@ void ps2_write_keyboard(void *opaque, int val)
PS2KbdState *s = (PS2KbdState *)opaque;
trace_ps2_write_keyboard(opaque, val);
+ ps2_cqueue_reset(&s->common);
switch(s->common.write_cmd) {
default:
case -1:
switch(val) {
case 0x00:
- ps2_queue(&s->common, KBD_REPLY_ACK);
+ ps2_cqueue_1(&s->common, KBD_REPLY_ACK);
break;
case 0x05:
- ps2_queue(&s->common, KBD_REPLY_RESEND);
+ ps2_cqueue_1(&s->common, KBD_REPLY_RESEND);
break;
case KBD_CMD_GET_ID:
/* We emulate a MF2 AT keyboard here */
- if (s->translate)
- ps2_queue_3(&s->common,
- KBD_REPLY_ACK,
- KBD_REPLY_ID,
- 0x41);
- else
- ps2_queue_3(&s->common,
- KBD_REPLY_ACK,
- KBD_REPLY_ID,
- 0x83);
+ ps2_cqueue_3(&s->common, KBD_REPLY_ACK, KBD_REPLY_ID,
+ s->translate ? 0x41 : 0x83);
break;
case KBD_CMD_ECHO:
- ps2_queue(&s->common, KBD_CMD_ECHO);
+ ps2_cqueue_1(&s->common, KBD_CMD_ECHO);
break;
case KBD_CMD_ENABLE:
s->scan_enabled = 1;
- ps2_queue(&s->common, KBD_REPLY_ACK);
+ ps2_cqueue_1(&s->common, KBD_REPLY_ACK);
break;
case KBD_CMD_SCANCODE:
case KBD_CMD_SET_LEDS:
case KBD_CMD_SET_RATE:
case KBD_CMD_SET_MAKE_BREAK:
s->common.write_cmd = val;
- ps2_queue(&s->common, KBD_REPLY_ACK);
+ ps2_cqueue_1(&s->common, KBD_REPLY_ACK);
break;
case KBD_CMD_RESET_DISABLE:
ps2_reset_keyboard(s);
s->scan_enabled = 0;
- ps2_queue(&s->common, KBD_REPLY_ACK);
+ ps2_cqueue_1(&s->common, KBD_REPLY_ACK);
break;
case KBD_CMD_RESET_ENABLE:
ps2_reset_keyboard(s);
s->scan_enabled = 1;
- ps2_queue(&s->common, KBD_REPLY_ACK);
+ ps2_cqueue_1(&s->common, KBD_REPLY_ACK);
break;
case KBD_CMD_RESET:
ps2_reset_keyboard(s);
- ps2_queue_2(&s->common,
+ ps2_cqueue_2(&s->common,
KBD_REPLY_ACK,
KBD_REPLY_POR);
break;
case KBD_CMD_SET_TYPEMATIC:
- ps2_queue(&s->common, KBD_REPLY_ACK);
+ ps2_cqueue_1(&s->common, KBD_REPLY_ACK);
break;
default:
- ps2_queue(&s->common, KBD_REPLY_RESEND);
+ ps2_cqueue_1(&s->common, KBD_REPLY_RESEND);
break;
}
break;
case KBD_CMD_SET_MAKE_BREAK:
- ps2_queue(&s->common, KBD_REPLY_ACK);
+ ps2_cqueue_1(&s->common, KBD_REPLY_ACK);
s->common.write_cmd = -1;
break;
case KBD_CMD_SCANCODE:
if (val == 0) {
- if (s->common.queue.count <= PS2_QUEUE_SIZE - 2) {
- ps2_queue(&s->common, KBD_REPLY_ACK);
- ps2_put_keycode(s, s->scancode_set);
- }
+ ps2_cqueue_2(&s->common, KBD_REPLY_ACK, s->translate ?
+ translate_table[s->scancode_set] : s->scancode_set);
} else if (val >= 1 && val <= 3) {
s->scancode_set = val;
- ps2_queue(&s->common, KBD_REPLY_ACK);
+ ps2_cqueue_1(&s->common, KBD_REPLY_ACK);
} else {
- ps2_queue(&s->common, KBD_REPLY_RESEND);
+ ps2_cqueue_1(&s->common, KBD_REPLY_RESEND);
}
s->common.write_cmd = -1;
break;
case KBD_CMD_SET_LEDS:
ps2_set_ledstate(s, val);
- ps2_queue(&s->common, KBD_REPLY_ACK);
+ ps2_cqueue_1(&s->common, KBD_REPLY_ACK);
s->common.write_cmd = -1;
break;
case KBD_CMD_SET_RATE:
- ps2_queue(&s->common, KBD_REPLY_ACK);
+ ps2_cqueue_1(&s->common, KBD_REPLY_ACK);
s->common.write_cmd = -1;
break;
}
@@ -926,30 +986,27 @@ static void ps2_common_reset(PS2State *s)
static void ps2_common_post_load(PS2State *s)
{
PS2Queue *q = &s->queue;
- uint8_t i, size;
- uint8_t tmp_data[PS2_QUEUE_SIZE];
-
- /* set the useful data buffer queue size, < PS2_QUEUE_SIZE */
- size = q->count;
- if (q->count < 0) {
- size = 0;
- } else if (q->count > PS2_QUEUE_SIZE) {
- size = PS2_QUEUE_SIZE;
- }
+ int ccount = 0;
- /* move the queue elements to the start of data array */
- for (i = 0; i < size; i++) {
- if (q->rptr < 0 || q->rptr >= sizeof(q->data)) {
- q->rptr = 0;
+ /* limit the number of queued command replies to PS2_QUEUE_HEADROOM */
+ if (q->cwptr != -1) {
+ ccount = (q->cwptr - q->rptr) & (PS2_BUFFER_SIZE - 1);
+ if (ccount > PS2_QUEUE_HEADROOM) {
+ ccount = PS2_QUEUE_HEADROOM;
}
- tmp_data[i] = q->data[q->rptr++];
}
- memcpy(q->data, tmp_data, size);
- /* reset rptr/wptr/count */
- q->rptr = 0;
- q->wptr = (size == PS2_QUEUE_SIZE) ? 0 : size;
- q->count = size;
+ /* limit the scancode queue size to PS2_QUEUE_SIZE */
+ if (q->count < ccount) {
+ q->count = ccount;
+ } else if (q->count > ccount + PS2_QUEUE_SIZE) {
+ q->count = ccount + PS2_QUEUE_SIZE;
+ }
+
+ /* sanitize rptr and recalculate wptr and cwptr */
+ q->rptr = q->rptr & (PS2_BUFFER_SIZE - 1);
+ q->wptr = (q->rptr + q->count) & (PS2_BUFFER_SIZE - 1);
+ q->cwptr = ccount ? (q->rptr + ccount) & (PS2_BUFFER_SIZE - 1) : -1;
}
static void ps2_kbd_reset(void *opaque)
@@ -1040,6 +1097,22 @@ static const VMStateDescription vmstate_ps2_keyboard_need_high_bit = {
}
};
+static bool ps2_keyboard_cqueue_needed(void *opaque)
+{
+ PS2KbdState *s = opaque;
+
+ return s->common.queue.cwptr != -1; /* the queue is mostly empty */
+}
+
+static const VMStateDescription vmstate_ps2_keyboard_cqueue = {
+ .name = "ps2kbd/command_reply_queue",
+ .needed = ps2_keyboard_cqueue_needed,
+ .fields = (VMStateField[]) {
+ VMSTATE_INT32(common.queue.cwptr, PS2KbdState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static int ps2_kbd_post_load(void* opaque, int version_id)
{
PS2KbdState *s = (PS2KbdState*)opaque;
@@ -1053,22 +1126,11 @@ static int ps2_kbd_post_load(void* opaque, int version_id)
return 0;
}
-static int ps2_kbd_pre_save(void *opaque)
-{
- PS2KbdState *s = (PS2KbdState *)opaque;
- PS2State *ps2 = &s->common;
-
- ps2_common_post_load(ps2);
-
- return 0;
-}
-
static const VMStateDescription vmstate_ps2_keyboard = {
.name = "ps2kbd",
.version_id = 3,
.minimum_version_id = 2,
.post_load = ps2_kbd_post_load,
- .pre_save = ps2_kbd_pre_save,
.fields = (VMStateField[]) {
VMSTATE_STRUCT(common, PS2KbdState, 0, vmstate_ps2_common, PS2State),
VMSTATE_INT32(scan_enabled, PS2KbdState),
@@ -1079,6 +1141,7 @@ static const VMStateDescription vmstate_ps2_keyboard = {
.subsections = (const VMStateDescription*[]) {
&vmstate_ps2_keyboard_ledstate,
&vmstate_ps2_keyboard_need_high_bit,
+ &vmstate_ps2_keyboard_cqueue,
NULL
}
};
@@ -1093,22 +1156,11 @@ static int ps2_mouse_post_load(void *opaque, int version_id)
return 0;
}
-static int ps2_mouse_pre_save(void *opaque)
-{
- PS2MouseState *s = (PS2MouseState *)opaque;
- PS2State *ps2 = &s->common;
-
- ps2_common_post_load(ps2);
-
- return 0;
-}
-
static const VMStateDescription vmstate_ps2_mouse = {
.name = "ps2mouse",
.version_id = 2,
.minimum_version_id = 2,
.post_load = ps2_mouse_post_load,
- .pre_save = ps2_mouse_pre_save,
.fields = (VMStateField[]) {
VMSTATE_STRUCT(common, PS2MouseState, 0, vmstate_ps2_common, PS2State),
VMSTATE_UINT8(mouse_status, PS2MouseState),
diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c
index ac0a13060b..5ba87f789c 100644
--- a/hw/m68k/q800.c
+++ b/hw/m68k/q800.c
@@ -225,7 +225,7 @@ static void q800_init(MachineState *machine)
hwaddr parameters_base;
CPUState *cs;
DeviceState *dev;
- DeviceState *via_dev;
+ DeviceState *via1_dev, *via2_dev;
DeviceState *escc_orgate;
SysBusESPState *sysbus_esp;
ESPState *esp;
@@ -270,28 +270,30 @@ static void q800_init(MachineState *machine)
object_property_set_link(OBJECT(glue), "cpu", OBJECT(cpu), &error_abort);
sysbus_realize_and_unref(SYS_BUS_DEVICE(glue), &error_fatal);
- /* VIA */
-
- via_dev = qdev_new(TYPE_MAC_VIA);
+ /* VIA 1 */
+ via1_dev = qdev_new(TYPE_MOS6522_Q800_VIA1);
dinfo = drive_get(IF_MTD, 0, 0);
if (dinfo) {
- qdev_prop_set_drive(via_dev, "drive", blk_by_legacy_dinfo(dinfo));
+ qdev_prop_set_drive(via1_dev, "drive", blk_by_legacy_dinfo(dinfo));
}
- sysbus = SYS_BUS_DEVICE(via_dev);
+ sysbus = SYS_BUS_DEVICE(via1_dev);
sysbus_realize_and_unref(sysbus, &error_fatal);
- sysbus_mmio_map(sysbus, 0, VIA_BASE);
- qdev_connect_gpio_out_named(DEVICE(sysbus), "irq", 0,
- qdev_get_gpio_in(glue, 0));
- qdev_connect_gpio_out_named(DEVICE(sysbus), "irq", 1,
- qdev_get_gpio_in(glue, 1));
-
+ sysbus_mmio_map(sysbus, 1, VIA_BASE);
+ sysbus_connect_irq(sysbus, 0, qdev_get_gpio_in(glue, 0));
- adb_bus = qdev_get_child_bus(via_dev, "adb.0");
+ adb_bus = qdev_get_child_bus(via1_dev, "adb.0");
dev = qdev_new(TYPE_ADB_KEYBOARD);
qdev_realize_and_unref(dev, adb_bus, &error_fatal);
dev = qdev_new(TYPE_ADB_MOUSE);
qdev_realize_and_unref(dev, adb_bus, &error_fatal);
+ /* VIA 2 */
+ via2_dev = qdev_new(TYPE_MOS6522_Q800_VIA2);
+ sysbus = SYS_BUS_DEVICE(via2_dev);
+ sysbus_realize_and_unref(sysbus, &error_fatal);
+ sysbus_mmio_map(sysbus, 1, VIA_BASE + VIA_SIZE);
+ sysbus_connect_irq(sysbus, 0, qdev_get_gpio_in(glue, 1));
+
/* MACSONIC */
if (nb_nics > 1) {
@@ -375,12 +377,10 @@ static void q800_init(MachineState *machine)
sysbus = SYS_BUS_DEVICE(dev);
sysbus_realize_and_unref(sysbus, &error_fatal);
- sysbus_connect_irq(sysbus, 0, qdev_get_gpio_in_named(via_dev,
- "via2-irq",
- VIA2_IRQ_SCSI_BIT));
- sysbus_connect_irq(sysbus, 1,
- qdev_get_gpio_in_named(via_dev, "via2-irq",
- VIA2_IRQ_SCSI_DATA_BIT));
+ sysbus_connect_irq(sysbus, 0, qdev_get_gpio_in(via2_dev,
+ VIA2_IRQ_SCSI_BIT));
+ sysbus_connect_irq(sysbus, 1, qdev_get_gpio_in(via2_dev,
+ VIA2_IRQ_SCSI_DATA_BIT));
sysbus_mmio_map(sysbus, 0, ESP_BASE);
sysbus_mmio_map(sysbus, 1, ESP_PDMA);
diff --git a/hw/misc/mac_via.c b/hw/misc/mac_via.c
index ff0156db76..d1abcd97b5 100644
--- a/hw/misc/mac_via.c
+++ b/hw/misc/mac_via.c
@@ -34,11 +34,9 @@
#include "qemu/log.h"
/*
- * VIAs: There are two in every machine,
+ * VIAs: There are two in every machine
*/
-#define VIA_SIZE (0x2000)
-
/*
* Not all of these are true post MacII I think.
* CSA: probably the ones CHRP marks as 'unused' change purposes
@@ -374,11 +372,10 @@ static void via2_irq_request(void *opaque, int irq, int level)
}
-static void pram_update(MacVIAState *m)
+static void pram_update(MOS6522Q800VIA1State *v1s)
{
- if (m->blk) {
- if (blk_pwrite(m->blk, 0, m->mos6522_via1.PRAM,
- sizeof(m->mos6522_via1.PRAM), 0) < 0) {
+ if (v1s->blk) {
+ if (blk_pwrite(v1s->blk, 0, v1s->PRAM, sizeof(v1s->PRAM), 0) < 0) {
qemu_log("pram_update: cannot write to file\n");
}
}
@@ -434,9 +431,8 @@ static int via1_rtc_compact_cmd(uint8_t value)
return REG_INVALID;
}
-static void via1_rtc_update(MacVIAState *m)
+static void via1_rtc_update(MOS6522Q800VIA1State *v1s)
{
- MOS6522Q800VIA1State *v1s = &m->mos6522_via1;
MOS6522State *s = MOS6522(v1s);
int cmd, sector, addr;
uint32_t time;
@@ -448,40 +444,40 @@ static void via1_rtc_update(MacVIAState *m)
if (s->dirb & VIA1B_vRTCData) {
/* send bits to the RTC */
if (!(v1s->last_b & VIA1B_vRTCClk) && (s->b & VIA1B_vRTCClk)) {
- m->data_out <<= 1;
- m->data_out |= s->b & VIA1B_vRTCData;
- m->data_out_cnt++;
+ v1s->data_out <<= 1;
+ v1s->data_out |= s->b & VIA1B_vRTCData;
+ v1s->data_out_cnt++;
}
- trace_via1_rtc_update_data_out(m->data_out_cnt, m->data_out);
+ trace_via1_rtc_update_data_out(v1s->data_out_cnt, v1s->data_out);
} else {
- trace_via1_rtc_update_data_in(m->data_in_cnt, m->data_in);
+ trace_via1_rtc_update_data_in(v1s->data_in_cnt, v1s->data_in);
/* receive bits from the RTC */
if ((v1s->last_b & VIA1B_vRTCClk) &&
!(s->b & VIA1B_vRTCClk) &&
- m->data_in_cnt) {
+ v1s->data_in_cnt) {
s->b = (s->b & ~VIA1B_vRTCData) |
- ((m->data_in >> 7) & VIA1B_vRTCData);
- m->data_in <<= 1;
- m->data_in_cnt--;
+ ((v1s->data_in >> 7) & VIA1B_vRTCData);
+ v1s->data_in <<= 1;
+ v1s->data_in_cnt--;
}
return;
}
- if (m->data_out_cnt != 8) {
+ if (v1s->data_out_cnt != 8) {
return;
}
- m->data_out_cnt = 0;
+ v1s->data_out_cnt = 0;
- trace_via1_rtc_internal_status(m->cmd, m->alt, m->data_out);
+ trace_via1_rtc_internal_status(v1s->cmd, v1s->alt, v1s->data_out);
/* first byte: it's a command */
- if (m->cmd == REG_EMPTY) {
+ if (v1s->cmd == REG_EMPTY) {
- cmd = via1_rtc_compact_cmd(m->data_out);
+ cmd = via1_rtc_compact_cmd(v1s->data_out);
trace_via1_rtc_internal_cmd(cmd);
if (cmd == REG_INVALID) {
- trace_via1_rtc_cmd_invalid(m->data_out);
+ trace_via1_rtc_cmd_invalid(v1s->data_out);
return;
}
@@ -493,20 +489,20 @@ static void via1_rtc_update(MacVIAState *m)
* register 3 is highest-order byte
*/
- time = m->tick_offset + (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)
+ time = v1s->tick_offset + (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)
/ NANOSECONDS_PER_SECOND);
trace_via1_rtc_internal_time(time);
- m->data_in = (time >> ((cmd & 0x03) << 3)) & 0xff;
- m->data_in_cnt = 8;
+ v1s->data_in = (time >> ((cmd & 0x03) << 3)) & 0xff;
+ v1s->data_in_cnt = 8;
trace_via1_rtc_cmd_seconds_read((cmd & 0x7f) - REG_0,
- m->data_in);
+ v1s->data_in);
break;
case REG_PRAM_ADDR...REG_PRAM_ADDR_LAST:
/* PRAM address 0x00 -> 0x13 */
- m->data_in = v1s->PRAM[(cmd & 0x7f) - REG_PRAM_ADDR];
- m->data_in_cnt = 8;
+ v1s->data_in = v1s->PRAM[(cmd & 0x7f) - REG_PRAM_ADDR];
+ v1s->data_in_cnt = 8;
trace_via1_rtc_cmd_pram_read((cmd & 0x7f) - REG_PRAM_ADDR,
- m->data_in);
+ v1s->data_in);
break;
case REG_PRAM_SECT...REG_PRAM_SECT_LAST:
/*
@@ -514,7 +510,7 @@ static void via1_rtc_update(MacVIAState *m)
* the only two-byte read command
*/
trace_via1_rtc_internal_set_cmd(cmd);
- m->cmd = cmd;
+ v1s->cmd = cmd;
break;
default:
g_assert_not_reached();
@@ -524,9 +520,9 @@ static void via1_rtc_update(MacVIAState *m)
}
/* this is a write command, needs a parameter */
- if (cmd == REG_WPROTECT || !m->wprotect) {
+ if (cmd == REG_WPROTECT || !v1s->wprotect) {
trace_via1_rtc_internal_set_cmd(cmd);
- m->cmd = cmd;
+ v1s->cmd = cmd;
} else {
trace_via1_rtc_internal_ignore_cmd(cmd);
}
@@ -534,46 +530,47 @@ static void via1_rtc_update(MacVIAState *m)
}
/* second byte: it's a parameter */
- if (m->alt == REG_EMPTY) {
- switch (m->cmd & 0x7f) {
+ if (v1s->alt == REG_EMPTY) {
+ switch (v1s->cmd & 0x7f) {
case REG_0...REG_3: /* seconds register */
/* FIXME */
- trace_via1_rtc_cmd_seconds_write(m->cmd - REG_0, m->data_out);
- m->cmd = REG_EMPTY;
+ trace_via1_rtc_cmd_seconds_write(v1s->cmd - REG_0, v1s->data_out);
+ v1s->cmd = REG_EMPTY;
break;
case REG_TEST:
/* device control: nothing to do */
- trace_via1_rtc_cmd_test_write(m->data_out);
- m->cmd = REG_EMPTY;
+ trace_via1_rtc_cmd_test_write(v1s->data_out);
+ v1s->cmd = REG_EMPTY;
break;
case REG_WPROTECT:
/* Write Protect register */
- trace_via1_rtc_cmd_wprotect_write(m->data_out);
- m->wprotect = !!(m->data_out & 0x80);
- m->cmd = REG_EMPTY;
+ trace_via1_rtc_cmd_wprotect_write(v1s->data_out);
+ v1s->wprotect = !!(v1s->data_out & 0x80);
+ v1s->cmd = REG_EMPTY;
break;
case REG_PRAM_ADDR...REG_PRAM_ADDR_LAST:
/* PRAM address 0x00 -> 0x13 */
- trace_via1_rtc_cmd_pram_write(m->cmd - REG_PRAM_ADDR, m->data_out);
- v1s->PRAM[m->cmd - REG_PRAM_ADDR] = m->data_out;
- pram_update(m);
- m->cmd = REG_EMPTY;
+ trace_via1_rtc_cmd_pram_write(v1s->cmd - REG_PRAM_ADDR,
+ v1s->data_out);
+ v1s->PRAM[v1s->cmd - REG_PRAM_ADDR] = v1s->data_out;
+ pram_update(v1s);
+ v1s->cmd = REG_EMPTY;
break;
case REG_PRAM_SECT...REG_PRAM_SECT_LAST:
- addr = (m->data_out >> 2) & 0x1f;
- sector = (m->cmd & 0x7f) - REG_PRAM_SECT;
- if (m->cmd & 0x80) {
+ addr = (v1s->data_out >> 2) & 0x1f;
+ sector = (v1s->cmd & 0x7f) - REG_PRAM_SECT;
+ if (v1s->cmd & 0x80) {
/* it's a read */
- m->data_in = v1s->PRAM[sector * 32 + addr];
- m->data_in_cnt = 8;
+ v1s->data_in = v1s->PRAM[sector * 32 + addr];
+ v1s->data_in_cnt = 8;
trace_via1_rtc_cmd_pram_sect_read(sector, addr,
sector * 32 + addr,
- m->data_in);
- m->cmd = REG_EMPTY;
+ v1s->data_in);
+ v1s->cmd = REG_EMPTY;
} else {
/* it's a write, we need one more parameter */
trace_via1_rtc_internal_set_alt(addr, sector, addr);
- m->alt = addr;
+ v1s->alt = addr;
}
break;
default:
@@ -584,22 +581,21 @@ static void via1_rtc_update(MacVIAState *m)
}
/* third byte: it's the data of a REG_PRAM_SECT write */
- g_assert(REG_PRAM_SECT <= m->cmd && m->cmd <= REG_PRAM_SECT_LAST);
- sector = m->cmd - REG_PRAM_SECT;
- v1s->PRAM[sector * 32 + m->alt] = m->data_out;
- pram_update(m);
- trace_via1_rtc_cmd_pram_sect_write(sector, m->alt, sector * 32 + m->alt,
- m->data_out);
- m->alt = REG_EMPTY;
- m->cmd = REG_EMPTY;
+ g_assert(REG_PRAM_SECT <= v1s->cmd && v1s->cmd <= REG_PRAM_SECT_LAST);
+ sector = v1s->cmd - REG_PRAM_SECT;
+ v1s->PRAM[sector * 32 + v1s->alt] = v1s->data_out;
+ pram_update(v1s);
+ trace_via1_rtc_cmd_pram_sect_write(sector, v1s->alt, sector * 32 + v1s->alt,
+ v1s->data_out);
+ v1s->alt = REG_EMPTY;
+ v1s->cmd = REG_EMPTY;
}
static void adb_via_poll(void *opaque)
{
- MacVIAState *m = opaque;
- MOS6522Q800VIA1State *v1s = MOS6522_Q800_VIA1(&m->mos6522_via1);
+ MOS6522Q800VIA1State *v1s = MOS6522_Q800_VIA1(opaque);
MOS6522State *s = MOS6522(v1s);
- ADBBusState *adb_bus = &m->adb_bus;
+ ADBBusState *adb_bus = &v1s->adb_bus;
uint8_t obuf[9];
uint8_t *data = &s->sr;
int olen;
@@ -611,50 +607,50 @@ static void adb_via_poll(void *opaque)
*/
adb_autopoll_block(adb_bus);
- if (m->adb_data_in_size > 0 && m->adb_data_in_index == 0) {
+ if (v1s->adb_data_in_size > 0 && v1s->adb_data_in_index == 0) {
/*
* For older Linux kernels that switch to IDLE mode after sending the
* ADB command, detect if there is an existing response and return that
* as a a "fake" autopoll reply or bus timeout accordingly
*/
- *data = m->adb_data_out[0];
- olen = m->adb_data_in_size;
+ *data = v1s->adb_data_out[0];
+ olen = v1s->adb_data_in_size;
s->b &= ~VIA1B_vADBInt;
- qemu_irq_raise(m->adb_data_ready);
+ qemu_irq_raise(v1s->adb_data_ready);
} else {
/*
* Otherwise poll as normal
*/
- m->adb_data_in_index = 0;
- m->adb_data_out_index = 0;
+ v1s->adb_data_in_index = 0;
+ v1s->adb_data_out_index = 0;
olen = adb_poll(adb_bus, obuf, adb_bus->autopoll_mask);
if (olen > 0) {
/* Autopoll response */
*data = obuf[0];
olen--;
- memcpy(m->adb_data_in, &obuf[1], olen);
- m->adb_data_in_size = olen;
+ memcpy(v1s->adb_data_in, &obuf[1], olen);
+ v1s->adb_data_in_size = olen;
s->b &= ~VIA1B_vADBInt;
- qemu_irq_raise(m->adb_data_ready);
+ qemu_irq_raise(v1s->adb_data_ready);
} else {
- *data = m->adb_autopoll_cmd;
+ *data = v1s->adb_autopoll_cmd;
obuf[0] = 0xff;
obuf[1] = 0xff;
olen = 2;
- memcpy(m->adb_data_in, obuf, olen);
- m->adb_data_in_size = olen;
+ memcpy(v1s->adb_data_in, obuf, olen);
+ v1s->adb_data_in_size = olen;
s->b &= ~VIA1B_vADBInt;
- qemu_irq_raise(m->adb_data_ready);
+ qemu_irq_raise(v1s->adb_data_ready);
}
}
trace_via1_adb_poll(*data, (s->b & VIA1B_vADBInt) ? "+" : "-",
- adb_bus->status, m->adb_data_in_index, olen);
+ adb_bus->status, v1s->adb_data_in_index, olen);
}
static int adb_via_send_len(uint8_t data)
@@ -687,11 +683,10 @@ static int adb_via_send_len(uint8_t data)
}
}
-static void adb_via_send(MacVIAState *s, int state, uint8_t data)
+static void adb_via_send(MOS6522Q800VIA1State *v1s, int state, uint8_t data)
{
- MOS6522Q800VIA1State *v1s = MOS6522_Q800_VIA1(&s->mos6522_via1);
MOS6522State *ms = MOS6522(v1s);
- ADBBusState *adb_bus = &s->adb_bus;
+ ADBBusState *adb_bus = &v1s->adb_bus;
uint16_t autopoll_mask;
switch (state) {
@@ -707,22 +702,22 @@ static void adb_via_send(MacVIAState *s, int state, uint8_t data)
ms->b &= ~VIA1B_vADBInt;
} else {
ms->b |= VIA1B_vADBInt;
- s->adb_data_out_index = 0;
- s->adb_data_out[s->adb_data_out_index++] = data;
+ v1s->adb_data_out_index = 0;
+ v1s->adb_data_out[v1s->adb_data_out_index++] = data;
}
trace_via1_adb_send(" NEW", data, (ms->b & VIA1B_vADBInt) ? "+" : "-");
- qemu_irq_raise(s->adb_data_ready);
+ qemu_irq_raise(v1s->adb_data_ready);
break;
case ADB_STATE_EVEN:
case ADB_STATE_ODD:
ms->b |= VIA1B_vADBInt;
- s->adb_data_out[s->adb_data_out_index++] = data;
+ v1s->adb_data_out[v1s->adb_data_out_index++] = data;
trace_via1_adb_send(state == ADB_STATE_EVEN ? "EVEN" : " ODD",
data, (ms->b & VIA1B_vADBInt) ? "+" : "-");
- qemu_irq_raise(s->adb_data_ready);
+ qemu_irq_raise(v1s->adb_data_ready);
break;
case ADB_STATE_IDLE:
@@ -730,40 +725,39 @@ static void adb_via_send(MacVIAState *s, int state, uint8_t data)
}
/* If the command is complete, execute it */
- if (s->adb_data_out_index == adb_via_send_len(s->adb_data_out[0])) {
- s->adb_data_in_size = adb_request(adb_bus, s->adb_data_in,
- s->adb_data_out,
- s->adb_data_out_index);
- s->adb_data_in_index = 0;
+ if (v1s->adb_data_out_index == adb_via_send_len(v1s->adb_data_out[0])) {
+ v1s->adb_data_in_size = adb_request(adb_bus, v1s->adb_data_in,
+ v1s->adb_data_out,
+ v1s->adb_data_out_index);
+ v1s->adb_data_in_index = 0;
if (adb_bus->status & ADB_STATUS_BUSTIMEOUT) {
/*
* Bus timeout (but allow first EVEN and ODD byte to indicate
* timeout via vADBInt and SRQ status)
*/
- s->adb_data_in[0] = 0xff;
- s->adb_data_in[1] = 0xff;
- s->adb_data_in_size = 2;
+ v1s->adb_data_in[0] = 0xff;
+ v1s->adb_data_in[1] = 0xff;
+ v1s->adb_data_in_size = 2;
}
/*
* If last command is TALK, store it for use by autopoll and adjust
* the autopoll mask accordingly
*/
- if ((s->adb_data_out[0] & 0xc) == 0xc) {
- s->adb_autopoll_cmd = s->adb_data_out[0];
+ if ((v1s->adb_data_out[0] & 0xc) == 0xc) {
+ v1s->adb_autopoll_cmd = v1s->adb_data_out[0];
- autopoll_mask = 1 << (s->adb_autopoll_cmd >> 4);
+ autopoll_mask = 1 << (v1s->adb_autopoll_cmd >> 4);
adb_set_autopoll_mask(adb_bus, autopoll_mask);
}
}
}
-static void adb_via_receive(MacVIAState *s, int state, uint8_t *data)
+static void adb_via_receive(MOS6522Q800VIA1State *v1s, int state, uint8_t *data)
{
- MOS6522Q800VIA1State *v1s = MOS6522_Q800_VIA1(&s->mos6522_via1);
MOS6522State *ms = MOS6522(v1s);
- ADBBusState *adb_bus = &s->adb_bus;
+ ADBBusState *adb_bus = &v1s->adb_bus;
uint16_t pending;
switch (state) {
@@ -777,16 +771,16 @@ static void adb_via_receive(MacVIAState *s, int state, uint8_t *data)
trace_via1_adb_receive("IDLE", *data,
(ms->b & VIA1B_vADBInt) ? "+" : "-", adb_bus->status,
- s->adb_data_in_index, s->adb_data_in_size);
+ v1s->adb_data_in_index, v1s->adb_data_in_size);
break;
case ADB_STATE_EVEN:
case ADB_STATE_ODD:
- switch (s->adb_data_in_index) {
+ switch (v1s->adb_data_in_index) {
case 0:
/* First EVEN byte: vADBInt indicates bus timeout */
- *data = s->adb_data_in[s->adb_data_in_index];
+ *data = v1s->adb_data_in[v1s->adb_data_in_index];
if (adb_bus->status & ADB_STATUS_BUSTIMEOUT) {
ms->b &= ~VIA1B_vADBInt;
} else {
@@ -795,16 +789,16 @@ static void adb_via_receive(MacVIAState *s, int state, uint8_t *data)
trace_via1_adb_receive(state == ADB_STATE_EVEN ? "EVEN" : " ODD",
*data, (ms->b & VIA1B_vADBInt) ? "+" : "-",
- adb_bus->status, s->adb_data_in_index,
- s->adb_data_in_size);
+ adb_bus->status, v1s->adb_data_in_index,
+ v1s->adb_data_in_size);
- s->adb_data_in_index++;
+ v1s->adb_data_in_index++;
break;
case 1:
/* First ODD byte: vADBInt indicates SRQ */
- *data = s->adb_data_in[s->adb_data_in_index];
- pending = adb_bus->pending & ~(1 << (s->adb_autopoll_cmd >> 4));
+ *data = v1s->adb_data_in[v1s->adb_data_in_index];
+ pending = adb_bus->pending & ~(1 << (v1s->adb_autopoll_cmd >> 4));
if (pending) {
ms->b &= ~VIA1B_vADBInt;
} else {
@@ -813,10 +807,10 @@ static void adb_via_receive(MacVIAState *s, int state, uint8_t *data)
trace_via1_adb_receive(state == ADB_STATE_EVEN ? "EVEN" : " ODD",
*data, (ms->b & VIA1B_vADBInt) ? "+" : "-",
- adb_bus->status, s->adb_data_in_index,
- s->adb_data_in_size);
+ adb_bus->status, v1s->adb_data_in_index,
+ v1s->adb_data_in_size);
- s->adb_data_in_index++;
+ v1s->adb_data_in_index++;
break;
default:
@@ -826,11 +820,11 @@ static void adb_via_receive(MacVIAState *s, int state, uint8_t *data)
* end of the poll reply, so provide these extra bytes below to
* keep it happy
*/
- if (s->adb_data_in_index < s->adb_data_in_size) {
+ if (v1s->adb_data_in_index < v1s->adb_data_in_size) {
/* Next data byte */
- *data = s->adb_data_in[s->adb_data_in_index];
+ *data = v1s->adb_data_in[v1s->adb_data_in_index];
ms->b |= VIA1B_vADBInt;
- } else if (s->adb_data_in_index == s->adb_data_in_size) {
+ } else if (v1s->adb_data_in_index == v1s->adb_data_in_size) {
if (adb_bus->status & ADB_STATUS_BUSTIMEOUT) {
/* Bus timeout (no more data) */
*data = 0xff;
@@ -849,23 +843,22 @@ static void adb_via_receive(MacVIAState *s, int state, uint8_t *data)
trace_via1_adb_receive(state == ADB_STATE_EVEN ? "EVEN" : " ODD",
*data, (ms->b & VIA1B_vADBInt) ? "+" : "-",
- adb_bus->status, s->adb_data_in_index,
- s->adb_data_in_size);
+ adb_bus->status, v1s->adb_data_in_index,
+ v1s->adb_data_in_size);
- if (s->adb_data_in_index <= s->adb_data_in_size) {
- s->adb_data_in_index++;
+ if (v1s->adb_data_in_index <= v1s->adb_data_in_size) {
+ v1s->adb_data_in_index++;
}
break;
}
- qemu_irq_raise(s->adb_data_ready);
+ qemu_irq_raise(v1s->adb_data_ready);
break;
}
}
-static void via1_adb_update(MacVIAState *m)
+static void via1_adb_update(MOS6522Q800VIA1State *v1s)
{
- MOS6522Q800VIA1State *v1s = MOS6522_Q800_VIA1(&m->mos6522_via1);
MOS6522State *s = MOS6522(v1s);
int oldstate, state;
@@ -875,10 +868,10 @@ static void via1_adb_update(MacVIAState *m)
if (state != oldstate) {
if (s->acr & VIA1ACR_vShiftOut) {
/* output mode */
- adb_via_send(m, state, s->sr);
+ adb_via_send(v1s, state, s->sr);
} else {
/* input mode */
- adb_via_receive(m, state, &s->sr);
+ adb_via_receive(v1s, state, &s->sr);
}
}
}
@@ -896,7 +889,6 @@ static void mos6522_q800_via1_write(void *opaque, hwaddr addr, uint64_t val,
unsigned size)
{
MOS6522Q800VIA1State *v1s = MOS6522_Q800_VIA1(opaque);
- MacVIAState *m = container_of(v1s, MacVIAState, mos6522_via1);
MOS6522State *ms = MOS6522(v1s);
addr = (addr >> 9) & 0xf;
@@ -904,8 +896,8 @@ static void mos6522_q800_via1_write(void *opaque, hwaddr addr, uint64_t val,
switch (addr) {
case VIA_REG_B:
- via1_rtc_update(m);
- via1_adb_update(m);
+ via1_rtc_update(v1s);
+ via1_adb_update(v1s);
v1s->last_b = ms->b;
break;
@@ -951,216 +943,155 @@ static const MemoryRegionOps mos6522_q800_via2_ops = {
},
};
-static void mac_via_reset(DeviceState *dev)
+static void via1_postload_update_cb(void *opaque, bool running, RunState state)
{
- MacVIAState *m = MAC_VIA(dev);
- ADBBusState *adb_bus = &m->adb_bus;
+ MOS6522Q800VIA1State *v1s = MOS6522_Q800_VIA1(opaque);
- adb_set_autopoll_enabled(adb_bus, true);
+ qemu_del_vm_change_state_handler(v1s->vmstate);
+ v1s->vmstate = NULL;
+
+ pram_update(v1s);
+}
+
+static int via1_post_load(void *opaque, int version_id)
+{
+ MOS6522Q800VIA1State *v1s = MOS6522_Q800_VIA1(opaque);
+
+ if (v1s->blk) {
+ v1s->vmstate = qemu_add_vm_change_state_handler(
+ via1_postload_update_cb, v1s);
+ }
+
+ return 0;
+}
+
+/* VIA 1 */
+static void mos6522_q800_via1_reset(DeviceState *dev)
+{
+ MOS6522Q800VIA1State *v1s = MOS6522_Q800_VIA1(dev);
+ MOS6522State *ms = MOS6522(v1s);
+ MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(ms);
+ ADBBusState *adb_bus = &v1s->adb_bus;
+
+ mdc->parent_reset(dev);
+
+ ms->timers[0].frequency = VIA_TIMER_FREQ;
+ ms->timers[1].frequency = VIA_TIMER_FREQ;
+
+ ms->b = VIA1B_vADB_StateMask | VIA1B_vADBInt | VIA1B_vRTCEnb;
- m->cmd = REG_EMPTY;
- m->alt = REG_EMPTY;
+ /* ADB/RTC */
+ adb_set_autopoll_enabled(adb_bus, true);
+ v1s->cmd = REG_EMPTY;
+ v1s->alt = REG_EMPTY;
}
-static void mac_via_realize(DeviceState *dev, Error **errp)
+static void mos6522_q800_via1_realize(DeviceState *dev, Error **errp)
{
- MacVIAState *m = MAC_VIA(dev);
- MOS6522State *ms;
- ADBBusState *adb_bus = &m->adb_bus;
+ MOS6522Q800VIA1State *v1s = MOS6522_Q800_VIA1(dev);
+ ADBBusState *adb_bus = &v1s->adb_bus;
struct tm tm;
int ret;
- /* Init VIAs 1 and 2 */
- object_initialize_child(OBJECT(dev), "via1", &m->mos6522_via1,
- TYPE_MOS6522_Q800_VIA1);
-
- object_initialize_child(OBJECT(dev), "via2", &m->mos6522_via2,
- TYPE_MOS6522_Q800_VIA2);
-
- /* Pass through mos6522 output IRQs */
- ms = MOS6522(&m->mos6522_via1);
- object_property_add_alias(OBJECT(dev), "irq[0]", OBJECT(ms),
- SYSBUS_DEVICE_GPIO_IRQ "[0]");
- ms = MOS6522(&m->mos6522_via2);
- object_property_add_alias(OBJECT(dev), "irq[1]", OBJECT(ms),
- SYSBUS_DEVICE_GPIO_IRQ "[0]");
-
- sysbus_realize(SYS_BUS_DEVICE(&m->mos6522_via1), &error_abort);
- sysbus_realize(SYS_BUS_DEVICE(&m->mos6522_via2), &error_abort);
-
- /* Pass through mos6522 input IRQs */
- qdev_pass_gpios(DEVICE(&m->mos6522_via1), dev, "via1-irq");
- qdev_pass_gpios(DEVICE(&m->mos6522_via2), dev, "via2-irq");
-
- /* VIA 1 */
- m->mos6522_via1.one_second_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL,
- via1_one_second,
- &m->mos6522_via1);
- via1_one_second_update(&m->mos6522_via1);
- m->mos6522_via1.sixty_hz_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
- via1_sixty_hz,
- &m->mos6522_via1);
- via1_sixty_hz_update(&m->mos6522_via1);
+ v1s->one_second_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, via1_one_second,
+ v1s);
+ via1_one_second_update(v1s);
+ v1s->sixty_hz_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, via1_sixty_hz,
+ v1s);
+ via1_sixty_hz_update(v1s);
qemu_get_timedate(&tm, 0);
- m->tick_offset = (uint32_t)mktimegm(&tm) + RTC_OFFSET;
+ v1s->tick_offset = (uint32_t)mktimegm(&tm) + RTC_OFFSET;
- adb_register_autopoll_callback(adb_bus, adb_via_poll, m);
- m->adb_data_ready = qdev_get_gpio_in_named(dev, "via1-irq",
- VIA1_IRQ_ADB_READY_BIT);
+ adb_register_autopoll_callback(adb_bus, adb_via_poll, v1s);
+ v1s->adb_data_ready = qdev_get_gpio_in(dev, VIA1_IRQ_ADB_READY_BIT);
- if (m->blk) {
- int64_t len = blk_getlength(m->blk);
+ if (v1s->blk) {
+ int64_t len = blk_getlength(v1s->blk);
if (len < 0) {
error_setg_errno(errp, -len,
"could not get length of backing image");
return;
}
- ret = blk_set_perm(m->blk,
+ ret = blk_set_perm(v1s->blk,
BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE,
BLK_PERM_ALL, errp);
if (ret < 0) {
return;
}
- len = blk_pread(m->blk, 0, m->mos6522_via1.PRAM,
- sizeof(m->mos6522_via1.PRAM));
- if (len != sizeof(m->mos6522_via1.PRAM)) {
+ len = blk_pread(v1s->blk, 0, v1s->PRAM, sizeof(v1s->PRAM));
+ if (len != sizeof(v1s->PRAM)) {
error_setg(errp, "can't read PRAM contents");
return;
}
}
}
-static void mac_via_init(Object *obj)
+static void mos6522_q800_via1_init(Object *obj)
{
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
- MacVIAState *m = MAC_VIA(obj);
-
- /* MMIO */
- memory_region_init(&m->mmio, obj, "mac-via", 2 * VIA_SIZE);
- sysbus_init_mmio(sbd, &m->mmio);
+ MOS6522Q800VIA1State *v1s = MOS6522_Q800_VIA1(obj);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(v1s);
- memory_region_init_io(&m->via1mem, obj, &mos6522_q800_via1_ops,
- &m->mos6522_via1, "via1", VIA_SIZE);
- memory_region_add_subregion(&m->mmio, 0x0, &m->via1mem);
-
- memory_region_init_io(&m->via2mem, obj, &mos6522_q800_via2_ops,
- &m->mos6522_via2, "via2", VIA_SIZE);
- memory_region_add_subregion(&m->mmio, VIA_SIZE, &m->via2mem);
+ memory_region_init_io(&v1s->via_mem, obj, &mos6522_q800_via1_ops, v1s,
+ "via1", VIA_SIZE);
+ sysbus_init_mmio(sbd, &v1s->via_mem);
/* ADB */
- qbus_create_inplace((BusState *)&m->adb_bus, sizeof(m->adb_bus),
- TYPE_ADB_BUS, DEVICE(obj), "adb.0");
-}
+ qbus_create_inplace((BusState *)&v1s->adb_bus, sizeof(v1s->adb_bus),
+ TYPE_ADB_BUS, DEVICE(v1s), "adb.0");
-static void postload_update_cb(void *opaque, bool running, RunState state)
-{
- MacVIAState *m = MAC_VIA(opaque);
-
- qemu_del_vm_change_state_handler(m->vmstate);
- m->vmstate = NULL;
-
- pram_update(m);
+ qdev_init_gpio_in(DEVICE(obj), via1_irq_request, VIA1_IRQ_NB);
}
-static int mac_via_post_load(void *opaque, int version_id)
-{
- MacVIAState *m = MAC_VIA(opaque);
-
- if (m->blk) {
- m->vmstate = qemu_add_vm_change_state_handler(postload_update_cb,
- m);
- }
-
- return 0;
-}
-
-static const VMStateDescription vmstate_mac_via = {
- .name = "mac-via",
- .version_id = 2,
- .minimum_version_id = 2,
- .post_load = mac_via_post_load,
+static const VMStateDescription vmstate_q800_via1 = {
+ .name = "q800-via1",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .post_load = via1_post_load,
.fields = (VMStateField[]) {
- /* VIAs */
- VMSTATE_STRUCT(mos6522_via1.parent_obj, MacVIAState, 0, vmstate_mos6522,
- MOS6522State),
- VMSTATE_UINT8(mos6522_via1.last_b, MacVIAState),
- VMSTATE_BUFFER(mos6522_via1.PRAM, MacVIAState),
- VMSTATE_TIMER_PTR(mos6522_via1.one_second_timer, MacVIAState),
- VMSTATE_INT64(mos6522_via1.next_second, MacVIAState),
- VMSTATE_TIMER_PTR(mos6522_via1.sixty_hz_timer, MacVIAState),
- VMSTATE_INT64(mos6522_via1.next_sixty_hz, MacVIAState),
- VMSTATE_STRUCT(mos6522_via2.parent_obj, MacVIAState, 0, vmstate_mos6522,
+ VMSTATE_STRUCT(parent_obj, MOS6522Q800VIA1State, 0, vmstate_mos6522,
MOS6522State),
+ VMSTATE_UINT8(last_b, MOS6522Q800VIA1State),
/* RTC */
- VMSTATE_UINT32(tick_offset, MacVIAState),
- VMSTATE_UINT8(data_out, MacVIAState),
- VMSTATE_INT32(data_out_cnt, MacVIAState),
- VMSTATE_UINT8(data_in, MacVIAState),
- VMSTATE_UINT8(data_in_cnt, MacVIAState),
- VMSTATE_UINT8(cmd, MacVIAState),
- VMSTATE_INT32(wprotect, MacVIAState),
- VMSTATE_INT32(alt, MacVIAState),
+ VMSTATE_BUFFER(PRAM, MOS6522Q800VIA1State),
+ VMSTATE_UINT32(tick_offset, MOS6522Q800VIA1State),
+ VMSTATE_UINT8(data_out, MOS6522Q800VIA1State),
+ VMSTATE_INT32(data_out_cnt, MOS6522Q800VIA1State),
+ VMSTATE_UINT8(data_in, MOS6522Q800VIA1State),
+ VMSTATE_UINT8(data_in_cnt, MOS6522Q800VIA1State),
+ VMSTATE_UINT8(cmd, MOS6522Q800VIA1State),
+ VMSTATE_INT32(wprotect, MOS6522Q800VIA1State),
+ VMSTATE_INT32(alt, MOS6522Q800VIA1State),
/* ADB */
- VMSTATE_INT32(adb_data_in_size, MacVIAState),
- VMSTATE_INT32(adb_data_in_index, MacVIAState),
- VMSTATE_INT32(adb_data_out_index, MacVIAState),
- VMSTATE_BUFFER(adb_data_in, MacVIAState),
- VMSTATE_BUFFER(adb_data_out, MacVIAState),
- VMSTATE_UINT8(adb_autopoll_cmd, MacVIAState),
+ VMSTATE_INT32(adb_data_in_size, MOS6522Q800VIA1State),
+ VMSTATE_INT32(adb_data_in_index, MOS6522Q800VIA1State),
+ VMSTATE_INT32(adb_data_out_index, MOS6522Q800VIA1State),
+ VMSTATE_BUFFER(adb_data_in, MOS6522Q800VIA1State),
+ VMSTATE_BUFFER(adb_data_out, MOS6522Q800VIA1State),
+ VMSTATE_UINT8(adb_autopoll_cmd, MOS6522Q800VIA1State),
+ /* Timers */
+ VMSTATE_TIMER_PTR(one_second_timer, MOS6522Q800VIA1State),
+ VMSTATE_INT64(next_second, MOS6522Q800VIA1State),
+ VMSTATE_TIMER_PTR(sixty_hz_timer, MOS6522Q800VIA1State),
+ VMSTATE_INT64(next_sixty_hz, MOS6522Q800VIA1State),
VMSTATE_END_OF_LIST()
}
};
-static Property mac_via_properties[] = {
- DEFINE_PROP_DRIVE("drive", MacVIAState, blk),
+static Property mos6522_q800_via1_properties[] = {
+ DEFINE_PROP_DRIVE("drive", MOS6522Q800VIA1State, blk),
DEFINE_PROP_END_OF_LIST(),
};
-static void mac_via_class_init(ObjectClass *oc, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(oc);
-
- dc->realize = mac_via_realize;
- dc->reset = mac_via_reset;
- dc->vmsd = &vmstate_mac_via;
- device_class_set_props(dc, mac_via_properties);
-}
-
-static TypeInfo mac_via_info = {
- .name = TYPE_MAC_VIA,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(MacVIAState),
- .instance_init = mac_via_init,
- .class_init = mac_via_class_init,
-};
-
-/* VIA 1 */
-static void mos6522_q800_via1_reset(DeviceState *dev)
-{
- MOS6522State *ms = MOS6522(dev);
- MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(ms);
-
- mdc->parent_reset(dev);
-
- ms->timers[0].frequency = VIA_TIMER_FREQ;
- ms->timers[1].frequency = VIA_TIMER_FREQ;
-
- ms->b = VIA1B_vADB_StateMask | VIA1B_vADBInt | VIA1B_vRTCEnb;
-}
-
-static void mos6522_q800_via1_init(Object *obj)
-{
- qdev_init_gpio_in_named(DEVICE(obj), via1_irq_request, "via1-irq",
- VIA1_IRQ_NB);
-}
-
static void mos6522_q800_via1_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
+ dc->realize = mos6522_q800_via1_realize;
dc->reset = mos6522_q800_via1_reset;
+ dc->vmsd = &vmstate_q800_via1;
+ device_class_set_props(dc, mos6522_q800_via1_properties);
}
static const TypeInfo mos6522_q800_via1_type_info = {
@@ -1192,20 +1123,61 @@ static void mos6522_q800_via2_reset(DeviceState *dev)
ms->dirb = 0;
ms->b = 0;
+ ms->dira = 0;
+ ms->a = 0x7f;
+}
+
+static void via2_nubus_irq_request(void *opaque, int irq, int level)
+{
+ MOS6522Q800VIA2State *v2s = opaque;
+ MOS6522State *s = MOS6522(v2s);
+ MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(s);
+
+ if (level) {
+ /* Port A nubus IRQ inputs are active LOW */
+ s->a &= ~(1 << irq);
+ s->ifr |= 1 << VIA2_IRQ_NUBUS_BIT;
+ } else {
+ s->a |= (1 << irq);
+ s->ifr &= ~(1 << VIA2_IRQ_NUBUS_BIT);
+ }
+
+ mdc->update_irq(s);
}
static void mos6522_q800_via2_init(Object *obj)
{
- qdev_init_gpio_in_named(DEVICE(obj), via2_irq_request, "via2-irq",
- VIA2_IRQ_NB);
+ MOS6522Q800VIA2State *v2s = MOS6522_Q800_VIA2(obj);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(v2s);
+
+ memory_region_init_io(&v2s->via_mem, obj, &mos6522_q800_via2_ops, v2s,
+ "via2", VIA_SIZE);
+ sysbus_init_mmio(sbd, &v2s->via_mem);
+
+ qdev_init_gpio_in(DEVICE(obj), via2_irq_request, VIA2_IRQ_NB);
+
+ qdev_init_gpio_in_named(DEVICE(obj), via2_nubus_irq_request, "nubus-irq",
+ VIA2_NUBUS_IRQ_NB);
}
+static const VMStateDescription vmstate_q800_via2 = {
+ .name = "q800-via2",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_STRUCT(parent_obj, MOS6522Q800VIA2State, 0, vmstate_mos6522,
+ MOS6522State),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static void mos6522_q800_via2_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
MOS6522DeviceClass *mdc = MOS6522_CLASS(oc);
dc->reset = mos6522_q800_via2_reset;
+ dc->vmsd = &vmstate_q800_via2;
mdc->portB_write = mos6522_q800_via2_portB_write;
}
@@ -1221,7 +1193,6 @@ static void mac_via_register_types(void)
{
type_register_static(&mos6522_q800_via1_type_info);
type_register_static(&mos6522_q800_via2_type_info);
- type_register_static(&mac_via_info);
}
type_init(mac_via_register_types);
diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c
index 42e139849e..7f3a7c0027 100644
--- a/hw/sparc/sun4m.c
+++ b/hw/sparc/sun4m.c
@@ -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;
}