• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#objective-cqtwindows誰得cocoapythonphprubygameguibathyscaphec翻訳omegat計画中(planning stage)frameworktwittertestdomvb.netdirectxbtronarduinopreviewerゲームエンジン

Commit MetaInfo

Revision87ecccea7e71715f63f1f36fbe23aaa73adf3b8a (tree)
Time2022-01-30 23:33:48
AuthorYoshinori Sato <ysato@user...>
CommiterYoshinori Sato

Log Message

hw/char/renesas_sci: Add fifo buffer to backend interface.

SCI does not have a fifo, it is necessary to send and receive

at a bit rate speed.

But, qemu's chardev backend does not have a buffer,

so it sends received data continuously.

By buffering the received data with the FIFO, continuous

received data can be received.

Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>

Change Summary

Incremental Difference

--- a/hw/char/renesas_sci.c
+++ b/hw/char/renesas_sci.c
@@ -69,32 +69,63 @@ REG8(SEMR, 7)
6969 FIELD(SEMR, ACS0, 0, 1)
7070 FIELD(SEMR, ABCS, 4, 1)
7171
72-static int can_receive(void *opaque)
72+enum {
73+ RXFIFO_DEPTH = 16,
74+};
75+
76+static void set_next_event(RSCIState *sci, int evt, int64_t expire)
7377 {
74- RSCIState *sci = RSCI(opaque);
75- if (sci->rx_next > qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)) {
76- return 0;
78+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
79+
80+ if (expire > 0) {
81+ timer_mod(&sci->timer[evt], now + expire);
7782 } else {
78- return FIELD_EX8(sci->scr, SCR, RE);
83+ timer_del(&sci->timer[evt]);
7984 }
8085 }
8186
82-static void receive(void *opaque, const uint8_t *buf, int size)
87+static int can_receive(void *opaque)
8388 {
8489 RSCIState *sci = RSCI(opaque);
85- sci->rx_next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + sci->trtime;
86- if (FIELD_EX8(sci->ssr, SSR, RDRF) || size > 1) {
90+ return FIELD_EX8(sci->scr, SCR, RE) ? fifo8_num_free(&sci->rxfifo) : 0;
91+}
92+
93+static void sci_rx_event(void *opaque)
94+{
95+ RSCIState *sci = RSCI(opaque);
96+ uint32_t rd;
97+
98+ if (fifo8_is_empty(&sci->rxfifo)) {
99+ /* receiver idle state */
100+ set_next_event(sci, RXTIMER, 0);
101+ return;
102+ }
103+ rd = fifo8_pop(&sci->rxfifo);
104+ if (FIELD_EX8(sci->ssr, SSR, RDRF)) {
105+ /* Don't receive last byte */
87106 sci->ssr = FIELD_DP8(sci->ssr, SSR, ORER, 1);
88107 if (FIELD_EX8(sci->scr, SCR, RIE)) {
89108 qemu_set_irq(sci->irq[ERI], 1);
90109 }
91110 } else {
92- sci->rdr = buf[0];
111+ sci->rdr = rd;
93112 sci->ssr = FIELD_DP8(sci->ssr, SSR, RDRF, 1);
94113 if (FIELD_EX8(sci->scr, SCR, RIE)) {
95114 qemu_irq_pulse(sci->irq[RXI]);
96115 }
97116 }
117+ set_next_event(sci, RXTIMER, sci->trtime);
118+}
119+
120+static void receive(void *opaque, const uint8_t *buf, int size)
121+{
122+ RSCIState *sci = RSCI(opaque);
123+ fifo8_push_all(&sci->rxfifo, buf, size);
124+
125+ if (!timer_pending(&sci->timer[RXTIMER])) {
126+ /* reciever idle state, start rx */
127+ sci_rx_event(sci);
128+ }
98129 }
99130
100131 static void send_byte(RSCIState *sci)
@@ -102,22 +133,26 @@ static void send_byte(RSCIState *sci)
102133 if (qemu_chr_fe_backend_connected(&sci->chr)) {
103134 qemu_chr_fe_write_all(&sci->chr, &sci->tdr, 1);
104135 }
105- timer_mod(&sci->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + sci->trtime);
136+ set_next_event(sci, TXTIMER, sci->trtime);
106137 sci->ssr = FIELD_DP8(sci->ssr, SSR, TEND, 0);
107138 sci->ssr = FIELD_DP8(sci->ssr, SSR, TDRE, 1);
108139 qemu_set_irq(sci->irq[TEI], 0);
109- if (FIELD_EX8(sci->scr, SCR, TIE)) {
140+ if (FIELD_EX8(sci->scr, SCR, TE) && FIELD_EX8(sci->scr, SCR, TIE)) {
110141 qemu_irq_pulse(sci->irq[TXI]);
111142 }
112143 }
113144
114-static void txend(void *opaque)
145+static void sci_tx_event(void *opaque)
115146 {
116147 RSCIState *sci = RSCI(opaque);
117- if (!FIELD_EX8(sci->ssr, SSR, TDRE)) {
148+
149+ if (FIELD_EX8(sci->ssr, SSR, TDRE) == 0) {
150+ /* next tx ready */
118151 send_byte(sci);
119152 } else {
153+ /* no next tx */
120154 sci->ssr = FIELD_DP8(sci->ssr, SSR, TEND, 1);
155+ set_next_event(sci, TXTIMER, 0);
121156 if (FIELD_EX8(sci->scr, SCR, TEIE)) {
122157 qemu_set_irq(sci->irq[TEI], 1);
123158 }
@@ -126,15 +161,15 @@ static void txend(void *opaque)
126161
127162 static void update_trtime(RSCIState *sci)
128163 {
164+ int64_t baseclk = NANOSECONDS_PER_SECOND / sci->input_freq;
165+ baseclk *= 64 - 32 * FIELD_EX8(sci->semr, SEMR, ABCS);
166+ baseclk *= 1 << (2 * FIELD_EX8(sci->smr, SMR, CKS));
167+ baseclk *= sci->brr + 1;
129168 /* char per bits */
130169 sci->trtime = 8 - FIELD_EX8(sci->smr, SMR, CHR);
131170 sci->trtime += FIELD_EX8(sci->smr, SMR, PE);
132171 sci->trtime += FIELD_EX8(sci->smr, SMR, STOP) + 1;
133- /* x bit transmit time (32 * divrate * brr) / base freq */
134- sci->trtime *= 32 * sci->brr;
135- sci->trtime *= 1 << (2 * FIELD_EX8(sci->smr, SMR, CKS));
136- sci->trtime *= NANOSECONDS_PER_SECOND;
137- sci->trtime /= sci->input_freq;
172+ sci->trtime *= baseclk;
138173 }
139174
140175 static bool sci_is_tr_enabled(RSCIState *sci)
@@ -151,23 +186,37 @@ static void sci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
151186 if (!sci_is_tr_enabled(sci)) {
152187 sci->smr = val;
153188 update_trtime(sci);
189+ } else {
190+ qemu_log_mask(LOG_GUEST_ERROR, "reneas_sci: Register 0x%"
191+ HWADDR_PRIX " write protected.\n", offset);
154192 }
155193 break;
156194 case A_BRR:
157195 if (!sci_is_tr_enabled(sci)) {
158196 sci->brr = val;
159197 update_trtime(sci);
198+ } else {
199+ qemu_log_mask(LOG_GUEST_ERROR, "reneas_sci: Register 0x%"
200+ HWADDR_PRIX " write protected.\n", offset);
160201 }
161202 break;
162203 case A_SCR:
163- sci->scr = val;
164- if (FIELD_EX8(sci->scr, SCR, TE)) {
165- sci->ssr = FIELD_DP8(sci->ssr, SSR, TDRE, 1);
166- sci->ssr = FIELD_DP8(sci->ssr, SSR, TEND, 1);
167- if (FIELD_EX8(sci->scr, SCR, TIE)) {
168- qemu_irq_pulse(sci->irq[TXI]);
204+ if (FIELD_EX8(sci->scr, SCR, TE) != FIELD_EX8(val, SCR, TE)) {
205+ if (FIELD_EX8(val, SCR, TE)) {
206+ /* Disable -> Enable to reset TX*/
207+ sci->ssr = FIELD_DP8(sci->ssr, SSR, TDRE, 1);
208+ sci->ssr = FIELD_DP8(sci->ssr, SSR, TEND, 1);
209+ if (FIELD_EX8(val, SCR, TIE)) {
210+ qemu_irq_pulse(sci->irq[TXI]);
211+ }
212+ } else {
213+ /* disable TX clock */
214+ set_next_event(sci, TXTIMER, 0);
215+ sci->ssr = FIELD_DP8(sci->ssr, SSR, TDRE, 0);
216+ sci->ssr = FIELD_DP8(sci->ssr, SSR, TEND, 1);
169217 }
170218 }
219+ sci->scr = val;
171220 if (!FIELD_EX8(sci->scr, SCR, TEIE)) {
172221 qemu_set_irq(sci->irq[TEI], 0);
173222 }
@@ -177,10 +226,14 @@ static void sci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
177226 break;
178227 case A_TDR:
179228 sci->tdr = val;
180- if (FIELD_EX8(sci->ssr, SSR, TEND)) {
181- send_byte(sci);
229+ if (FIELD_EX8(sci->scr, SCR, TE)) {
230+ if (FIELD_EX8(sci->ssr, SSR, TEND)) {
231+ send_byte(sci);
232+ } else {
233+ sci->ssr = FIELD_DP8(sci->ssr, SSR, TDRE, 0);
234+ }
182235 } else {
183- sci->ssr = FIELD_DP8(sci->ssr, SSR, TDRE, 0);
236+ qemu_log_mask(LOG_GUEST_ERROR, "reneas_sci: Transmit disabled.\n");
184237 }
185238 break;
186239 case A_SSR:
@@ -224,6 +277,9 @@ static uint64_t sci_read(void *opaque, hwaddr offset, unsigned size)
224277 sci->read_ssr = sci->ssr;
225278 return sci->ssr;
226279 case A_RDR:
280+ if (!FIELD_EX8(sci->scr, SCR, RE)) {
281+ qemu_log_mask(LOG_GUEST_ERROR, "reneas_sci: Receive disabled.\n");
282+ }
227283 sci->ssr = FIELD_DP8(sci->ssr, SSR, RDRF, 0);
228284 return sci->rdr;
229285 case A_SCMR:
@@ -255,7 +311,7 @@ static void rsci_reset(DeviceState *dev)
255311 sci->ssr = 0x84;
256312 sci->scmr = 0x00;
257313 sci->semr = 0x00;
258- sci->rx_next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
314+ update_trtime(sci);
259315 }
260316
261317 static void sci_event(void *opaque, QEMUChrEvent event)
@@ -263,6 +319,7 @@ static void sci_event(void *opaque, QEMUChrEvent event)
263319 RSCIState *sci = RSCI(opaque);
264320 if (event == CHR_EVENT_BREAK) {
265321 sci->ssr = FIELD_DP8(sci->ssr, SSR, FER, 1);
322+ sci->rdr = 0;
266323 if (FIELD_EX8(sci->scr, SCR, RIE)) {
267324 qemu_set_irq(sci->irq[ERI], 1);
268325 }
@@ -295,16 +352,19 @@ static void rsci_init(Object *obj)
295352 for (i = 0; i < SCI_NR_IRQ; i++) {
296353 sysbus_init_irq(d, &sci->irq[i]);
297354 }
298- timer_init_ns(&sci->timer, QEMU_CLOCK_VIRTUAL, txend, sci);
355+ timer_init_ns(&sci->timer[TXTIMER],
356+ QEMU_CLOCK_VIRTUAL, sci_tx_event, sci);
357+ timer_init_ns(&sci->timer[RXTIMER],
358+ QEMU_CLOCK_VIRTUAL, sci_rx_event, sci);
359+ fifo8_create(&sci->rxfifo, RXFIFO_DEPTH);
299360 }
300361
301362 static const VMStateDescription vmstate_rsci = {
302363 .name = "renesas-sci",
303- .version_id = 1,
364+ .version_id = 2,
304365 .minimum_version_id = 1,
305366 .fields = (VMStateField[]) {
306367 VMSTATE_INT64(trtime, RSCIState),
307- VMSTATE_INT64(rx_next, RSCIState),
308368 VMSTATE_UINT8(smr, RSCIState),
309369 VMSTATE_UINT8(brr, RSCIState),
310370 VMSTATE_UINT8(scr, RSCIState),
@@ -314,7 +374,7 @@ static const VMStateDescription vmstate_rsci = {
314374 VMSTATE_UINT8(scmr, RSCIState),
315375 VMSTATE_UINT8(semr, RSCIState),
316376 VMSTATE_UINT8(read_ssr, RSCIState),
317- VMSTATE_TIMER(timer, RSCIState),
377+ VMSTATE_TIMER_ARRAY(timer, RSCIState, NR_TIMER),
318378 VMSTATE_END_OF_LIST()
319379 }
320380 };
--- a/include/hw/char/renesas_sci.h
+++ b/include/hw/char/renesas_sci.h
@@ -12,6 +12,7 @@
1212 #include "chardev/char-fe.h"
1313 #include "hw/sysbus.h"
1414 #include "qom/object.h"
15+#include "qemu/fifo8.h"
1516
1617 #define TYPE_RENESAS_SCI "renesas-sci"
1718 typedef struct RSCIState RSCIState;
@@ -26,13 +27,18 @@ enum {
2627 SCI_NR_IRQ = 4
2728 };
2829
30+enum {
31+ TXTIMER = 0,
32+ RXTIMER = 1,
33+ NR_TIMER = 2,
34+};
35+
2936 struct RSCIState {
3037 /*< private >*/
3138 SysBusDevice parent_obj;
3239 /*< public >*/
3340
3441 MemoryRegion memory;
35- QEMUTimer timer;
3642 CharBackend chr;
3743 qemu_irq irq[SCI_NR_IRQ];
3844
@@ -47,8 +53,9 @@ struct RSCIState {
4753
4854 uint8_t read_ssr;
4955 int64_t trtime;
50- int64_t rx_next;
5156 uint64_t input_freq;
57+ Fifo8 rxfifo;
58+ QEMUTimer timer[NR_TIMER];
5259 };
5360
5461 #endif