aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiodrag Dinic <miodrag.dinic@imgtec.com>2015-06-16 17:24:06 +0200
committerMiodrag Dinic <miodrag.dinic@imgtec.com>2015-06-23 12:31:10 +0200
commit7673fd2cd207de3774cbf2e0bea9f1f99bab7c87 (patch)
tree51a6507d255f560acbbf0ddd8c20a69078ea6900
parent5e29087a9444d323bbab1ed7c7120ea7ef3739f2 (diff)
downloadqemu-android-master.tar.gz
Re-implement Goldfish TTY device to work directly with physical addresses instead of virtual. Main idea behind this approach is to move away from using cpu_memory_rw_debug() -> cpu_phys_page_debug() path for VA-PA translation, which does not guarantee that it will return a valid mapping. Using physical addresses is the correct way to go, ensures less overhead and faster serial communication. Change-Id: Ib31f3cb33ac6630816f901a39834c87188ac09aa
-rw-r--r--hw/char/goldfish_tty.c71
1 files changed, 42 insertions, 29 deletions
diff --git a/hw/char/goldfish_tty.c b/hw/char/goldfish_tty.c
index 5525e3f3d6..7223c604d7 100644
--- a/hw/char/goldfish_tty.c
+++ b/hw/char/goldfish_tty.c
@@ -17,6 +17,8 @@
#include "hw/sysbus.h"
#include "sysemu/sysemu.h"
+#define TTY_DEVICE_VERSION 1
+
enum {
TTY_PUT_CHAR = 0x00,
TTY_BYTES_READY = 0x04,
@@ -26,6 +28,8 @@ enum {
TTY_DATA_LEN = 0x14,
TTY_DATA_PTR_HIGH = 0x18,
+ TTY_VERSION = 0x20,
+
TTY_CMD_INT_DISABLE = 0,
TTY_CMD_INT_ENABLE = 1,
TTY_CMD_WRITE_BUFFER = 2,
@@ -96,6 +100,8 @@ static uint64_t goldfish_tty_read(void *opaque, hwaddr offset, unsigned size)
switch (offset) {
case TTY_BYTES_READY:
return s->data_count;
+ case TTY_VERSION:
+ return TTY_DEVICE_VERSION;
default:
cpu_abort(current_cpu,
"goldfish_tty_read: Bad offset %" HWADDR_PRIx "\n",
@@ -104,7 +110,8 @@ static uint64_t goldfish_tty_read(void *opaque, hwaddr offset, unsigned size)
}
}
-static void goldfish_tty_write(void *opaque, hwaddr offset, uint64_t value, unsigned size)
+static void goldfish_tty_write(void *opaque, hwaddr offset,
+ uint64_t value, unsigned size)
{
struct tty_state *s = (struct tty_state *)opaque;
@@ -135,39 +142,42 @@ static void goldfish_tty_write(void *opaque, hwaddr offset, uint64_t value, unsi
case TTY_CMD_WRITE_BUFFER:
if(s->cs) {
- int len;
- target_ulong buf;
-
- buf = s->ptr;
- len = s->ptr_len;
-
- while (len) {
- char temp[64];
- int to_write = sizeof(temp);
- if (to_write > len)
- to_write = len;
-
- cpu_memory_rw_debug(current_cpu, buf, (uint8_t*)temp, to_write, 0);
- qemu_chr_fe_write(s->cs, (const uint8_t*)temp, to_write);
- buf += to_write;
- len -= to_write;
- }
+ hwaddr l = s->ptr_len;
+ void *ptr;
+
+ ptr = cpu_physical_memory_map(s->ptr, &l, 0);
+ qemu_chr_fe_write(s->cs, (const uint8_t*)ptr, l);
+ cpu_physical_memory_unmap(ptr, l, 0, 0);
}
break;
case TTY_CMD_READ_BUFFER:
- if(s->ptr_len > s->data_count)
- cpu_abort(current_cpu, "goldfish_tty_write: reading more data than available %d %d\n", s->ptr_len, s->data_count);
- cpu_memory_rw_debug(current_cpu, s->ptr, s->data, s->ptr_len,1);
- if(s->data_count > s->ptr_len)
- memmove(s->data, s->data + s->ptr_len, s->data_count - s->ptr_len);
- s->data_count -= s->ptr_len;
- if(s->data_count == 0 && s->ready)
- qemu_set_irq(s->irq, 0);
+ {
+ hwaddr l = s->ptr_len;
+ void *ptr;
+
+ if(s->ptr_len > s->data_count)
+ cpu_abort(current_cpu,
+ "goldfish_tty_write: reading"
+ " more data than available %d %d\n",
+ s->ptr_len, s->data_count);
+
+ ptr = cpu_physical_memory_map(s->ptr, &l, 1);
+ memcpy(ptr, s->data, l);
+ cpu_physical_memory_unmap(ptr, l, 1, l);
+
+ if(s->data_count > l)
+ memmove(s->data, s->data + l, s->data_count - l);
+ s->data_count -= l;
+ if(s->data_count == 0 && s->ready)
+ qemu_set_irq(s->irq, 0);
+ }
break;
default:
- cpu_abort(current_cpu, "goldfish_tty_write: Bad command %" PRIx64 "\n", value);
+ cpu_abort(current_cpu,
+ "goldfish_tty_write: Bad command %" PRIx64 "\n",
+ value);
};
break;
@@ -224,7 +234,9 @@ static void goldfish_tty_realize(DeviceState *dev, Error **errp)
int i;
if ((instance_id + 1) == MAX_SERIAL_PORTS) {
- cpu_abort(current_cpu, "goldfish_tty: MAX_SERIAL_PORTS(%d) reached\n", MAX_SERIAL_PORTS);
+ cpu_abort(current_cpu,
+ "goldfish_tty: MAX_SERIAL_PORTS(%d) reached\n",
+ MAX_SERIAL_PORTS);
}
memory_region_init_io(&s->iomem, OBJECT(s), &mips_qemu_ops, s,
@@ -235,7 +247,8 @@ static void goldfish_tty_realize(DeviceState *dev, Error **errp)
for(i = 0; i < MAX_SERIAL_PORTS; i++) {
if(serial_hds[i]) {
s->cs = serial_hds[i];
- qemu_chr_add_handlers(serial_hds[i], tty_can_receive, tty_receive, NULL, s);
+ qemu_chr_add_handlers(serial_hds[i], tty_can_receive,
+ tty_receive, NULL, s);
break;
}
}