qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] SH: support 7785 serial
@ 2009-04-02 17:29 Vladimir Prus
  2009-04-06 13:15 ` Shin-ichiro KAWASAKI
  0 siblings, 1 reply; 9+ messages in thread
From: Vladimir Prus @ 2009-04-02 17:29 UTC (permalink / raw)
  To: qemu-devel

[-- Attachment #1: Type: Text/Plain, Size: 1016 bytes --]


These 3 patches make sh_serial.c support 7785 serial. The primary
difference is that on 7785, instead of single fifo count register
there are two separate ones -- for rx and tx. Patch 3 adds necessary
conditional logic. Patches 1 and 2 are cleanups that I've done alone
the way:

- Patch 1 makes it possible to change the size of RX fifo. It's 16
on 7751 and 64 on 7785. While I do not know of any breakage if we
use wrong size, it's still best to be correct.
- Patch 2 replaces a pile of hardcoded constants with macroses.
Also, the FSR register was handled strangely -- when written, we'd
look at the written value and set bits in the 'flags' field, and on
read, we'd reconstruct the value from the 'flags' field. There does
not seem to be any reason for such roundabout, so I've made the code
work with 'sr' directly.

This patch was tested both with r2d, using kernel and userland found
at:

	thttp://www.assembla.com/wiki/show/qemu-sh4/BuildingEnvironment

and with 7785, using a hand-made kernel.

- Volodya


[-- Attachment #2: 0001-Make-RX-fifo-size-configurable.patch --]
[-- Type: text/x-patch, Size: 2558 bytes --]

From 1d9dc814c6ad1e9e4c06e9b212c116716985b14e Mon Sep 17 00:00:00 2001
From: Vladimir Prus <vladimir@codesourcery.com>
Date: Thu, 2 Apr 2009 13:49:08 +0400
Subject: [PATCH 1/3] Make RX fifo size configurable.
To: qemu-devel@nongnu.org
X-KMail-Transport: CodeSourcery
X-KMail-Identity: 901867920

---
 hw/sh_serial.c |   15 ++++++++-------
 1 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/hw/sh_serial.c b/hw/sh_serial.c
index 4957c41..cb7c9d1 100644
--- a/hw/sh_serial.c
+++ b/hw/sh_serial.c
@@ -37,8 +37,6 @@
 #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;
@@ -48,10 +46,11 @@ typedef struct {
     uint16_t fcr;
     uint8_t sptr;
 
-    uint8_t rx_fifo[SH_RX_FIFO_LENGTH]; /* frdr / rdr */
+    uint8_t *rx_fifo; /* frdr / rdr */
     uint8_t rx_cnt;
     uint8_t rx_tail;
     uint8_t rx_head;
+    int rx_capacity;
 
     int freq;
     int feat;
@@ -69,7 +68,7 @@ typedef struct {
 
 static void sh_serial_clear_fifo(sh_serial_state * s)
 {
-    memset(s->rx_fifo, 0, SH_RX_FIFO_LENGTH);
+    memset(s->rx_fifo, 0, s->rx_capacity);
     s->rx_cnt = 0;
     s->rx_head = 0;
     s->rx_tail = 0;
@@ -236,7 +235,7 @@ static uint32_t sh_serial_ioport_read(void *opaque, uint32_t offs)
             if (s->rx_cnt > 0) {
                 ret = s->rx_fifo[s->rx_tail++];
                 s->rx_cnt--;
-                if (s->rx_tail == SH_RX_FIFO_LENGTH)
+                if (s->rx_tail == s->rx_capacity)
                     s->rx_tail = 0;
                 if (s->rx_cnt < s->rtrg)
                     s->flags &= ~SH_SERIAL_FLAG_RDF;
@@ -297,9 +296,9 @@ static int sh_serial_can_receive(sh_serial_state *s)
 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) {
+        if (s->rx_cnt < s->rx_capacity) {
             s->rx_fifo[s->rx_head++] = ch;
-            if (s->rx_head == SH_RX_FIFO_LENGTH)
+            if (s->rx_head == s->rx_capacity)
                 s->rx_head = 0;
             s->rx_cnt++;
             if (s->rx_cnt >= s->rtrg) {
@@ -393,6 +392,8 @@ void sh_serial_init (target_phys_addr_t base, int feat,
         s->dr = 0xff;
     }
 
+    s->rx_capacity = 16;
+    s->rx_fifo = (uint8_t *)malloc(s->rx_capacity);
     sh_serial_clear_fifo(s);
 
     s_io_memory = cpu_register_io_memory(0, sh_serial_readfn,
-- 
1.6.2.1


[-- Attachment #3: 0002-Use-symbolic-constants.patch --]
[-- Type: text/x-patch, Size: 5484 bytes --]

From a87364fd8cad59864417ec1eb87c02249f55d2fc Mon Sep 17 00:00:00 2001
From: Vladimir Prus <vladimir@codesourcery.com>
Date: Thu, 2 Apr 2009 17:20:09 +0400
Subject: [PATCH 2/3] Use symbolic constants.
To: qemu-devel@nongnu.org
X-KMail-Transport: CodeSourcery
X-KMail-Identity: 901867920

---
 hw/sh_serial.c |   72 ++++++++++++++++++++++---------------------------------
 1 files changed, 29 insertions(+), 43 deletions(-)

diff --git a/hw/sh_serial.c b/hw/sh_serial.c
index cb7c9d1..e004e28 100644
--- a/hw/sh_serial.c
+++ b/hw/sh_serial.c
@@ -31,11 +31,15 @@
 
 //#define DEBUG_SERIAL
 
-#define SH_SERIAL_FLAG_TEND (1 << 0)
-#define SH_SERIAL_FLAG_TDE  (1 << 1)
-#define SH_SERIAL_FLAG_RDF  (1 << 2)
-#define SH_SERIAL_FLAG_BRK  (1 << 3)
-#define SH_SERIAL_FLAG_DR   (1 << 4)
+#define SCR_RE   (1 << 4)
+#define SCR_TE   (1 << 5)
+#define SCR_RIE  (1 << 6)
+#define SCR_TIE  (1 << 7)
+
+#define FSR_DR   (1 << 0)
+#define FSR_RDF  (1 << 1)
+#define FSR_TDFE (1 << 5)
+#define FSR_TEND (1 << 6)
 
 typedef struct {
     uint8_t smr;
@@ -54,7 +58,6 @@ typedef struct {
 
     int freq;
     int feat;
-    int flags;
     int rtrg;
 
     CharDriverState *chr;
@@ -93,12 +96,12 @@ static void sh_serial_ioport_write(void *opaque, uint32_t offs, uint32_t val)
     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;
+        if (!(val & SCR_TE))
+            s->sr |= FSR_TEND;
         if ((s->feat & SH_SERIAL_FEAT_SCIF) && s->txi) {
-	    qemu_set_irq(s->txi, val & (1 << 7));
+	    qemu_set_irq(s->txi, val & SCR_TIE);
         }
-        if (!(val & (1 << 6))) {
+        if (!(val & SCR_RIE)) {
 	    qemu_set_irq(s->rxi, 0);
         }
         return;
@@ -108,7 +111,7 @@ static void sh_serial_ioport_write(void *opaque, uint32_t offs, uint32_t val)
             qemu_chr_write(s->chr, &ch, 1);
 	}
 	s->dr = val;
-	s->flags &= ~SH_SERIAL_FLAG_TDE;
+	s->sr &= ~FSR_TDFE;
         return;
 #if 0
     case 0x14: /* FRDR / RDR */
@@ -119,18 +122,11 @@ static void sh_serial_ioport_write(void *opaque, uint32_t offs, uint32_t val)
     if (s->feat & SH_SERIAL_FEAT_SCIF) {
         switch(offs) {
         case 0x10: /* FSR */
-            if (!(val & (1 << 6)))
-                s->flags &= ~SH_SERIAL_FLAG_TEND;
-            if (!(val & (1 << 5)))
-                s->flags &= ~SH_SERIAL_FLAG_TDE;
-            if (!(val & (1 << 4)))
-                s->flags &= ~SH_SERIAL_FLAG_BRK;
-            if (!(val & (1 << 1)))
-                s->flags &= ~SH_SERIAL_FLAG_RDF;
-            if (!(val & (1 << 0)))
-                s->flags &= ~SH_SERIAL_FLAG_DR;
-
-            if (!(val & (1 << 1)) || !(val & (1 << 0))) {
+            val &= 0xf3;
+            
+            s->sr = val;
+
+            if (!(val & FSR_RDF) || !(val & FSR_DR)) {
                 if (s->rxi) {
                     qemu_set_irq(s->rxi, 0);
                 }
@@ -214,21 +210,11 @@ static uint32_t sh_serial_ioport_read(void *opaque, uint32_t offs)
         case 0x08: /* SCR */
             ret = s->scr;
             break;
-        case 0x10: /* FSR */
-            ret = 0;
-            if (s->flags & SH_SERIAL_FLAG_TEND)
-                ret |= (1 << 6);
-            if (s->flags & SH_SERIAL_FLAG_TDE)
-                ret |= (1 << 5);
-            if (s->flags & SH_SERIAL_FLAG_BRK)
-                ret |= (1 << 4);
-            if (s->flags & SH_SERIAL_FLAG_RDF)
-                ret |= (1 << 1);
-            if (s->flags & SH_SERIAL_FLAG_DR)
-                ret |= (1 << 0);
-
-            if (s->scr & (1 << 5))
-                s->flags |= SH_SERIAL_FLAG_TDE | SH_SERIAL_FLAG_TEND;
+        case 0x10: /* FSR */            
+            ret = s->sr;
+
+            if (s->scr & SCR_TE)
+                s->sr |= FSR_TDFE | FSR_TEND;
 
             break;
         case 0x14:
@@ -238,7 +224,7 @@ static uint32_t sh_serial_ioport_read(void *opaque, uint32_t offs)
                 if (s->rx_tail == s->rx_capacity)
                     s->rx_tail = 0;
                 if (s->rx_cnt < s->rtrg)
-                    s->flags &= ~SH_SERIAL_FLAG_RDF;
+                    s->sr &= ~FSR_RDF;
             }
             break;
 #if 0
@@ -290,7 +276,7 @@ static uint32_t sh_serial_ioport_read(void *opaque, uint32_t offs)
 
 static int sh_serial_can_receive(sh_serial_state *s)
 {
-    return s->scr & (1 << 4);
+    return s->scr & SCR_RE;
 }
 
 static void sh_serial_receive_byte(sh_serial_state *s, int ch)
@@ -302,8 +288,8 @@ static void sh_serial_receive_byte(sh_serial_state *s, int ch)
                 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) {
+                s->sr |= FSR_RDF;
+                if (s->scr & SCR_RIE && s->rxi) {
                     qemu_set_irq(s->rxi, 1);
                 }
             }
@@ -377,7 +363,7 @@ void sh_serial_init (target_phys_addr_t base, int feat,
     s = qemu_mallocz(sizeof(sh_serial_state));
 
     s->feat = feat;
-    s->flags = SH_SERIAL_FLAG_TEND | SH_SERIAL_FLAG_TDE;
+    s->sr = FSR_TEND | FSR_TDFE;
     s->rtrg = 1;
 
     s->smr = 0;
-- 
1.6.2.1


[-- Attachment #4: 0003-Support-7785-s-serial.patch --]
[-- Type: text/x-patch, Size: 4585 bytes --]

From 4ae7e3fc941add72b2ff11ce95a579a09b79b4e6 Mon Sep 17 00:00:00 2001
From: Vladimir Prus <vladimir@codesourcery.com>
Date: Thu, 2 Apr 2009 20:44:01 +0400
Subject: [PATCH 3/3] Support 7785's serial.
To: qemu-devel@nongnu.org
X-KMail-Transport: CodeSourcery
X-KMail-Identity: 901867920

---
 hw/sh.h        |    1 +
 hw/sh_serial.c |   73 +++++++++++++++++++++++++++++++++++++++++++++++++------
 2 files changed, 66 insertions(+), 8 deletions(-)

diff --git a/hw/sh.h b/hw/sh.h
index 5e3c22b..da051f1 100644
--- a/hw/sh.h
+++ b/hw/sh.h
@@ -37,6 +37,7 @@ void tmu012_init(target_phys_addr_t base, int feat, uint32_t freq,
 
 /* sh_serial.c */
 #define SH_SERIAL_FEAT_SCIF (1 << 0)
+#define SH_SERIAL_FEAT_7785 (1 << 1)
 void sh_serial_init (target_phys_addr_t base, int feat,
 		     uint32_t freq, CharDriverState *chr,
 		     qemu_irq eri_source,
diff --git a/hw/sh_serial.c b/hw/sh_serial.c
index e004e28..4f606ff 100644
--- a/hw/sh_serial.c
+++ b/hw/sh_serial.c
@@ -154,10 +154,28 @@ static void sh_serial_ioport_write(void *opaque, uint32_t offs, uint32_t val)
             }
 
             return;
-        case 0x20: /* SPTR */
-            s->sptr = val & 0xf3;
+        case 0x20: 
+            if (s->feat & SH_SERIAL_FEAT_7785)
+            {
+                /* Recieve fifo data count register, not writable.  */
+            }
+            else
+            {
+                 /* SPTR */
+                s->sptr = val & 0xf3;
+            }
             return;
-        case 0x24: /* LSR */
+        case 0x24: 
+            if (s->feat & SH_SERIAL_FEAT_7785)
+            {
+                s->sptr = val & 0xf3;
+            }
+            else
+            {
+               /* LSR */
+            }
+            return;
+        case 0x28:
             return;
         }
     }
@@ -233,12 +251,47 @@ static uint32_t sh_serial_ioport_read(void *opaque, uint32_t offs)
             break;
 #endif
         case 0x1c:
-            ret = s->rx_cnt;
+            if (s->feat & SH_SERIAL_FEAT_7785)
+            {
+                /* Trasmit fifo data count.  Because we immediate send
+                   everything, we also claim the fifo is always empty.  */
+                ret = 0;
+            }
+            else
+            {
+                /* On 7751, this is unified receive/trasmit fifo data
+                   count register.  The received data count is in low
+                   8 bits. In QEMU, transmit fifo is always empty, so
+                   return just receive count.  */
+                ret = s->rx_cnt;
+            }
             break;
         case 0x20:
-            ret = s->sptr;
+            if (s->feat & SH_SERIAL_FEAT_7785)
+            {
+                /* On 7785, there's separate trasmit fifo data register.  */
+                ret = s->rx_cnt;
+            }
+            else
+            {
+                ret = s->sptr;
+            }
             break;
         case 0x24:
+            /* On 7785, this is serial port register.  On 7751, this is line
+               status register.  */
+            if (s->feat & SH_SERIAL_FEAT_7785)
+            {
+                ret = s->sptr;
+            }
+            else
+            {
+                ret = 0;
+            }
+            break;
+        case 0x28:
+            /* On 7785, this is line status register.  */
+            assert(s->feat & SH_SERIAL_FEAT_7785);
             ret = 0;
             break;
         }
@@ -359,6 +412,7 @@ void sh_serial_init (target_phys_addr_t base, int feat,
 {
     sh_serial_state *s;
     int s_io_memory;
+    int is_7785 = (feat & SH_SERIAL_FEAT_7785);
 
     s = qemu_mallocz(sizeof(sh_serial_state));
 
@@ -378,14 +432,17 @@ void sh_serial_init (target_phys_addr_t base, int feat,
         s->dr = 0xff;
     }
 
-    s->rx_capacity = 16;
+    s->rx_capacity = is_7785 ? 64 : 16;
     s->rx_fifo = (uint8_t *)malloc(s->rx_capacity);
     sh_serial_clear_fifo(s);
 
     s_io_memory = cpu_register_io_memory(0, sh_serial_readfn,
 					 sh_serial_writefn, s);
-    cpu_register_physical_memory(P4ADDR(base), 0x28, s_io_memory);
-    cpu_register_physical_memory(A7ADDR(base), 0x28, s_io_memory);
+    cpu_register_physical_memory(P4ADDR(base), 
+                                 is_7785 ? 0x2E : 0x28, s_io_memory);
+    cpu_register_physical_memory(A7ADDR(base), 
+                                 is_7785 ? 0x2E : 0x28, s_io_memory);
+
 
     s->chr = chr;
 
-- 
1.6.2.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2009-05-11 15:44 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-04-02 17:29 [Qemu-devel] SH: support 7785 serial Vladimir Prus
2009-04-06 13:15 ` Shin-ichiro KAWASAKI
2009-04-06 15:23   ` [Qemu-devel] " Vladimir Prus
2009-04-06 16:49     ` Shin-ichiro KAWASAKI
2009-04-06 18:04       ` [Qemu-devel] " Vladimir Prus
2009-04-15 13:18   ` [Qemu-devel] " Vladimir Prus
2009-04-18 11:47     ` Shin-ichiro KAWASAKI
2009-04-18 16:37       ` Aurelien Jarno
2009-05-11 15:44         ` Vladimir Prus

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).