qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Shin-ichiro KAWASAKI <kawasaki@juno.dti.ne.jp>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH] [RESEND] SH4 : Serial controller improvement
Date: Mon, 15 Sep 2008 14:42:45 +0900	[thread overview]
Message-ID: <48CDF5D5.6010506@juno.dti.ne.jp> (raw)
In-Reply-To: <20080914165648.GE22422@volta.aurel32.net>

Aurelien Jarno wrote:
>> @@ -194,6 +224,15 @@
>>                  s->flags |= SH_SERIAL_FLAG_TDE | SH_SERIAL_FLAG_TEND;
>>  
>>              break;
>> +        case 0x14:
>> +	    if (s->rx_cnt > 0) {
>> +	        ret = s->rx_fifo[0];
>> +		s->rx_cnt--;
>> +		memmove(&s->rx_fifo[0], &s->rx_fifo[1], s->rx_cnt);
> 
> I don't think moving the whole buffer each time a character is read is a
> good idea. I would suggest to use a circular buffer instead. Have a look
> at hw/serial.c how it is done.

I see.  I'm sending the patch with a circular buffer.
Thanks for your comments!

Regards,
Shin-ichiro KAWASAKI


Index: trunk/hw/sh_serial.c
===================================================================
--- trunk/hw/sh_serial.c	(revision 5219)
+++ trunk/hw/sh_serial.c	(working copy)
@@ -37,6 +37,8 @@
 #define SH_SERIAL_FLAG_BRK  (1 << 3)
 #define SH_SERIAL_FLAG_DR   (1 << 4)
 
+#define SH_RX_FIFO_LENGTH (16)
+
 typedef struct {
     uint8_t smr;
     uint8_t brr;
@@ -46,13 +48,16 @@
     uint16_t fcr;
     uint8_t sptr;
 
-    uint8_t rx_fifo[16]; /* frdr / rdr */
+    uint8_t rx_fifo[SH_RX_FIFO_LENGTH]; /* frdr / rdr */
     uint8_t rx_cnt;
+    uint8_t rx_tail;
+    uint8_t rx_head;
 
     target_phys_addr_t base;
     int freq;
     int feat;
     int flags;
+    int rtrg;
 
     CharDriverState *chr;
 
@@ -63,6 +68,14 @@
     struct intc_source *bri;
 } sh_serial_state;
 
+static void sh_serial_clear_fifo(sh_serial_state * s)
+{
+    memset(s->rx_fifo, 0, SH_RX_FIFO_LENGTH);
+    s->rx_cnt = 0;
+    s->rx_head = 0;
+    s->rx_tail = 0;
+}
+
 static void sh_serial_ioport_write(void *opaque, uint32_t offs, uint32_t val)
 {
     sh_serial_state *s = opaque;
@@ -80,6 +93,7 @@
         s->brr = val;
 	return;
     case 0x08: /* SCR */
+        /* TODO : For SH7751, SCIF mask should be 0xfb. */
         s->scr = val & ((s->feat & SH_SERIAL_FEAT_SCIF) ? 0xfa : 0xff);
         if (!(val & (1 << 5)))
             s->flags |= SH_SERIAL_FLAG_TEND;
@@ -89,6 +103,9 @@
             else if (!(val & (1 << 7)) && s->txi->asserted)
                 sh_intc_toggle_source(s->txi, 0, -1);
         }
+        if (!(val & (1 << 6)) && s->rxi->asserted) {
+	    sh_intc_toggle_source(s->rxi, 0, -1);
+	}
         return;
     case 0x0c: /* FTDR / TDR */
         if (s->chr) {
@@ -117,12 +134,37 @@
                 s->flags &= ~SH_SERIAL_FLAG_RDF;
             if (!(val & (1 << 0)))
                 s->flags &= ~SH_SERIAL_FLAG_DR;
+
+            if (!(val & (1 << 1)) || !(val & (1 << 0))) {
+	        if (s->rxi && s->rxi->asserted) {
+		    sh_intc_toggle_source(s->rxi, 0, -1);
+		}
+	    }
             return;
         case 0x18: /* FCR */
             s->fcr = val;
+	    switch ((val >> 6) & 3) {
+	    case 0:
+	        s->rtrg = 1;
+	        break;
+	    case 1:
+	        s->rtrg = 4;
+	        break;
+	    case 2:
+	        s->rtrg = 8;
+	        break;
+	    case 3:
+	        s->rtrg = 14;
+	        break;
+	    }
+	    if (val & (1 << 1)) {
+	        sh_serial_clear_fifo(s);
+		s->sr &= ~(1 << 1);
+	    }
+
             return;
         case 0x20: /* SPTR */
-            s->sptr = val;
+            s->sptr = val & 0xf3;
             return;
         case 0x24: /* LSR */
             return;
@@ -194,6 +236,16 @@
                 s->flags |= SH_SERIAL_FLAG_TDE | SH_SERIAL_FLAG_TEND;
 
             break;
+        case 0x14:
+	    if (s->rx_cnt > 0) {
+	        ret = s->rx_fifo[s->rx_tail++];
+		s->rx_cnt--;
+		if (s->rx_tail == SH_RX_FIFO_LENGTH)
+		    s->rx_tail = 0;
+		if (s->rx_cnt < s->rtrg)
+		    s->flags &= ~SH_SERIAL_FLAG_RDF;
+	    }
+	    break;
 #if 0
         case 0x18:
             ret = s->fcr;
@@ -219,6 +271,9 @@
         case 0x10:
             ret = 0;
             break;
+        case 0x14:
+	    ret = s->rx_fifo[0];
+	    break;
         case 0x1c:
             ret = s->sptr;
             break;
@@ -240,15 +295,33 @@
 
 static int sh_serial_can_receive(sh_serial_state *s)
 {
-    return 0;
+    return s->scr & (1 << 4);
 }
 
 static void sh_serial_receive_byte(sh_serial_state *s, int ch)
 {
+    if (s->feat & SH_SERIAL_FEAT_SCIF) {
+        if (s->rx_cnt < SH_RX_FIFO_LENGTH) {
+	    s->rx_fifo[s->rx_head++] = ch;
+	    if (s->rx_head == SH_RX_FIFO_LENGTH)
+	        s->rx_head = 0;
+	    s->rx_cnt++;
+	    if (s->rx_cnt >= s->rtrg) {
+		s->flags |= SH_SERIAL_FLAG_RDF;
+		if (s->scr & (1 << 6) && s->rxi) {
+		    sh_intc_toggle_source(s->rxi, 0, 1);
+		}
+	    }
+	}
+    } else {
+        s->rx_fifo[0] = ch;
+    }
 }
 
 static void sh_serial_receive_break(sh_serial_state *s)
 {
+    if (s->feat & SH_SERIAL_FEAT_SCIF)
+        s->sr |= (1 << 4);
 }
 
 static int sh_serial_can_receive1(void *opaque)
@@ -313,6 +386,7 @@
     s->base = base;
     s->feat = feat;
     s->flags = SH_SERIAL_FLAG_TEND | SH_SERIAL_FLAG_TDE;
+    s->rtrg = 1;
 
     s->smr = 0;
     s->brr = 0xff;
@@ -326,7 +400,7 @@
         s->dr = 0xff;
     }
 
-    s->rx_cnt = 0;
+    sh_serial_clear_fifo(s);
 
     s_io_memory = cpu_register_io_memory(0, sh_serial_readfn,
 					 sh_serial_writefn, s);

  parent reply	other threads:[~2008-09-15  5:42 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-09-07 14:34 [Qemu-devel] [PATCH] SH4: Serial controller improvement and sleep op bug fix Shin-ichiro KAWASAKI
2008-09-14 16:56 ` Aurelien Jarno
2008-09-15  5:28   ` [PATCH] [RESEND] SH4 : sleep instruction bug fix (was Re: [Qemu-devel] [PATCH] SH4: Serial controller improvement and sleep op bug fix) Shin-ichiro KAWASAKI
2008-09-15  6:42     ` Aurelien Jarno
2008-09-15  5:42   ` Shin-ichiro KAWASAKI [this message]
2008-09-15  7:06     ` [Qemu-devel] [PATCH] [RESEND] SH4 : Serial controller improvement Aurelien Jarno

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=48CDF5D5.6010506@juno.dti.ne.jp \
    --to=kawasaki@juno.dti.ne.jp \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).