Commit 4af396115a1722dfaf8f7d4ecee59202dd7d5ea8

Authored by Paul Brook
1 parent dcc5e4a0

Syborg (Symbian Virtual Platform) board

A virtual reference platform for SymbianOS development/debugging.

Signed-off-by: Paul Brook <paul@codesourcery.com>
Makefile.target
... ... @@ -655,6 +655,8 @@ OBJS+= nseries.o blizzard.o onenand.o vga.o cbus.o tusb6010.o usb-musb.o
655 655 OBJS+= mst_fpga.o mainstone.o
656 656 OBJS+= musicpal.o pflash_cfi02.o
657 657 OBJS+= framebuffer.o
  658 +OBJS+= syborg.o syborg_fb.o syborg_interrupt.o syborg_keyboard.o
  659 +OBJS+= syborg_serial.o syborg_timer.o syborg_pointer.o syborg_rtc.o
658 660 CPPFLAGS += -DHAS_AUDIO
659 661 endif
660 662 ifeq ($(TARGET_BASE_ARCH), sh4)
... ...
hw/boards.h
... ... @@ -128,4 +128,7 @@ extern QEMUMachine musicpal_machine;
128 128 /* tosa.c */
129 129 extern QEMUMachine tosapda_machine;
130 130  
  131 +/* syborg.c */
  132 +extern QEMUMachine syborg_machine;
  133 +
131 134 #endif
... ...
hw/syborg.c 0 → 100644
  1 +/*
  2 + * Syborg (Symbian Virtual Platform) reference board
  3 + *
  4 + * Copyright (c) 2009 CodeSourcery
  5 + *
  6 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 + * of this software and associated documentation files (the "Software"), to deal
  8 + * in the Software without restriction, including without limitation the rights
  9 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 + * copies of the Software, and to permit persons to whom the Software is
  11 + * furnished to do so, subject to the following conditions:
  12 + *
  13 + * The above copyright notice and this permission notice shall be included in
  14 + * all copies or substantial portions of the Software.
  15 + *
  16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 + * THE SOFTWARE.
  23 + */
  24 +
  25 +#include "sysbus.h"
  26 +#include "boards.h"
  27 +#include "arm-misc.h"
  28 +#include "sysemu.h"
  29 +
  30 +static struct arm_boot_info syborg_binfo;
  31 +
  32 +static void syborg_init(ram_addr_t ram_size,
  33 + const char *boot_device,
  34 + const char *kernel_filename, const char *kernel_cmdline,
  35 + const char *initrd_filename, const char *cpu_model)
  36 +{
  37 + CPUState *env;
  38 + qemu_irq *cpu_pic;
  39 + qemu_irq pic[64];
  40 + ram_addr_t ram_addr;
  41 + DeviceState *dev;
  42 + int i;
  43 +
  44 + if (!cpu_model)
  45 + cpu_model = "cortex-a8";
  46 + env = cpu_init(cpu_model);
  47 + if (!env) {
  48 + fprintf(stderr, "Unable to find CPU definition\n");
  49 + exit(1);
  50 + }
  51 +
  52 + /* RAM at address zero. */
  53 + ram_addr = qemu_ram_alloc(ram_size);
  54 + cpu_register_physical_memory(0, ram_size, ram_addr | IO_MEM_RAM);
  55 +
  56 + cpu_pic = arm_pic_init_cpu(env);
  57 + dev = sysbus_create_simple("syborg,interrupt", 0xC0000000,
  58 + cpu_pic[ARM_PIC_CPU_IRQ]);
  59 + for (i = 0; i < 64; i++) {
  60 + pic[i] = qdev_get_irq_sink(dev, i);
  61 + }
  62 +
  63 + sysbus_create_simple("syborg,rtc", 0xC0001000, NULL);
  64 +
  65 + dev = qdev_create(NULL, "syborg,timer");
  66 + qdev_set_prop_int(dev, "frequency", 1000000);
  67 + qdev_init(dev);
  68 + sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0xC0002000);
  69 + sysbus_connect_irq(sysbus_from_qdev(dev), 0, pic[1]);
  70 +
  71 + sysbus_create_simple("syborg,keyboard", 0xC0003000, pic[2]);
  72 + sysbus_create_simple("syborg,pointer", 0xC0004000, pic[3]);
  73 + sysbus_create_simple("syborg,framebuffer", 0xC0005000, pic[4]);
  74 + sysbus_create_simple("syborg,serial", 0xC0006000, pic[5]);
  75 + sysbus_create_simple("syborg,serial", 0xC0007000, pic[6]);
  76 + sysbus_create_simple("syborg,serial", 0xC0008000, pic[7]);
  77 + sysbus_create_simple("syborg,serial", 0xC0009000, pic[8]);
  78 +
  79 + syborg_binfo.ram_size = ram_size;
  80 + syborg_binfo.kernel_filename = kernel_filename;
  81 + syborg_binfo.kernel_cmdline = kernel_cmdline;
  82 + syborg_binfo.initrd_filename = initrd_filename;
  83 + syborg_binfo.board_id = 0;
  84 + arm_load_kernel(env, &syborg_binfo);
  85 +}
  86 +
  87 +QEMUMachine syborg_machine = {
  88 + .name = "syborg",
  89 + .desc = "Syborg (Symbian Virtual Platform)",
  90 + .init = syborg_init,
  91 +};
... ...
hw/syborg.h 0 → 100644
  1 +#ifndef _SYBORG_H
  2 +#define _SYBORG_H
  3 +
  4 +#define SYBORG_ID_PLATFORM 0xc51d1000
  5 +#define SYBORG_ID_INT 0xc51d0000
  6 +#define SYBORG_ID_SERIAL 0xc51d0001
  7 +#define SYBORG_ID_KEYBOARD 0xc51d0002
  8 +#define SYBORG_ID_TIMER 0xc51d0003
  9 +#define SYBORG_ID_RTC 0xc51d0004
  10 +#define SYBORG_ID_MOUSE 0xc51d0005
  11 +#define SYBORG_ID_TOUCHSCREEN 0xc51d0006
  12 +#define SYBORG_ID_FRAMEBUFFER 0xc51d0007
  13 +#define SYBORG_ID_HOSTFS 0xc51d0008
  14 +#define SYBORG_ID_SNAPSHOT 0xc51d0009
  15 +#define SYBORG_ID_VIRTIO 0xc51d000a
  16 +#define SYBORG_ID_NAND 0xc51d000b
  17 +
  18 +#endif
... ...
hw/syborg_fb.c 0 → 100644
  1 +/*
  2 + * Syborg Framebuffer
  3 + *
  4 + * Copyright (c) 2009 CodeSourcery
  5 + *
  6 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 + * of this software and associated documentation files (the "Software"), to deal
  8 + * in the Software without restriction, including without limitation the rights
  9 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 + * copies of the Software, and to permit persons to whom the Software is
  11 + * furnished to do so, subject to the following conditions:
  12 + *
  13 + * The above copyright notice and this permission notice shall be included in
  14 + * all copies or substantial portions of the Software.
  15 + *
  16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 + * THE SOFTWARE.
  23 + */
  24 +
  25 +#include "sysbus.h"
  26 +#include "console.h"
  27 +#include "syborg.h"
  28 +#include "framebuffer.h"
  29 +
  30 +//#define DEBUG_SYBORG_FB
  31 +
  32 +#ifdef DEBUG_SYBORG_FB
  33 +#define DPRINTF(fmt, ...) \
  34 +do { printf("syborg_fb: " fmt , ## __VA_ARGS__); } while (0)
  35 +#define BADF(fmt, ...) \
  36 +do { fprintf(stderr, "syborg_fb: error: " fmt , ## __VA_ARGS__); \
  37 + exit(1);} while (0)
  38 +#else
  39 +#define DPRINTF(fmt, ...) do {} while(0)
  40 +#define BADF(fmt, ...) \
  41 +do { fprintf(stderr, "syborg_fb: error: " fmt , ## __VA_ARGS__);} while (0)
  42 +#endif
  43 +
  44 +enum {
  45 + FB_ID = 0,
  46 + FB_BASE = 1,
  47 + FB_HEIGHT = 2,
  48 + FB_WIDTH = 3,
  49 + FB_ORIENTATION = 4,
  50 + FB_BLANK = 5,
  51 + FB_INT_MASK = 6,
  52 + FB_INTERRUPT_CAUSE = 7,
  53 + FB_BPP = 8,
  54 + FB_COLOR_ORDER = 9,
  55 + FB_BYTE_ORDER = 10,
  56 + FB_PIXEL_ORDER = 11,
  57 + FB_ROW_PITCH = 12,
  58 + FB_ENABLED = 13,
  59 + FB_PALETTE_START = 0x400 >> 2,
  60 + FB_PALETTE_END = FB_PALETTE_START+256-1,
  61 +};
  62 +
  63 +#define FB_INT_VSYNC (1U << 0)
  64 +#define FB_INT_BASE_UPDATE_DONE (1U << 1)
  65 +
  66 +typedef struct {
  67 + SysBusDevice busdev;
  68 + DisplayState *ds;
  69 + /*QEMUConsole *console;*/
  70 + uint32_t need_update : 1;
  71 + uint32_t need_int : 1;
  72 + uint32_t enabled : 1;
  73 + uint32_t int_status;
  74 + uint32_t int_enable;
  75 + qemu_irq irq;
  76 +
  77 + uint32_t base;
  78 + uint32_t pitch;
  79 + int rows;
  80 + int cols;
  81 + int blank;
  82 + int bpp;
  83 + int rgb; /* 0 = BGR, 1 = RGB */
  84 + int endian; /* 0 = Little, 1 = Big */
  85 + uint32_t raw_palette[256];
  86 + uint32_t palette[256];
  87 +} SyborgFBState;
  88 +
  89 +enum {
  90 + BPP_SRC_1,
  91 + BPP_SRC_2,
  92 + BPP_SRC_4,
  93 + BPP_SRC_8,
  94 + BPP_SRC_16,
  95 + BPP_SRC_32,
  96 + /* TODO: Implement these. */
  97 + BPP_SRC_15 = -1,
  98 + BPP_SRC_24 = -2
  99 +};
  100 +
  101 +#include "pixel_ops.h"
  102 +
  103 +#define BITS 8
  104 +#include "pl110_template.h"
  105 +#define BITS 15
  106 +#include "pl110_template.h"
  107 +#define BITS 16
  108 +#include "pl110_template.h"
  109 +#define BITS 24
  110 +#include "pl110_template.h"
  111 +#define BITS 32
  112 +#include "pl110_template.h"
  113 +
  114 +/* Update interrupts. */
  115 +static void syborg_fb_update(SyborgFBState *s)
  116 +{
  117 + if ((s->int_status & s->int_enable) != 0) {
  118 + DPRINTF("Raise IRQ\n");
  119 + qemu_irq_raise(s->irq);
  120 + } else {
  121 + DPRINTF("Lower IRQ\n");
  122 + qemu_irq_lower(s->irq);
  123 + }
  124 +}
  125 +
  126 +static int syborg_fb_enabled(const SyborgFBState *s)
  127 +{
  128 + return s->enabled;
  129 +}
  130 +
  131 +static void syborg_fb_update_palette(SyborgFBState *s)
  132 +{
  133 + int n, i;
  134 + uint32_t raw;
  135 + unsigned int r, g, b;
  136 +
  137 + switch (s->bpp) {
  138 + case BPP_SRC_1: n = 2; break;
  139 + case BPP_SRC_2: n = 4; break;
  140 + case BPP_SRC_4: n = 16; break;
  141 + case BPP_SRC_8: n = 256; break;
  142 + default: return;
  143 + }
  144 +
  145 + for (i = 0; i < n; i++) {
  146 + raw = s->raw_palette[i];
  147 + r = (raw >> 16) & 0xff;
  148 + g = (raw >> 8) & 0xff;
  149 + b = raw & 0xff;
  150 + switch (ds_get_bits_per_pixel(s->ds)) {
  151 + case 8:
  152 + s->palette[i] = rgb_to_pixel8(r, g, b);
  153 + break;
  154 + case 15:
  155 + s->palette[i] = rgb_to_pixel15(r, g, b);
  156 + break;
  157 + case 16:
  158 + s->palette[i] = rgb_to_pixel16(r, g, b);
  159 + break;
  160 + case 24:
  161 + case 32:
  162 + s->palette[i] = rgb_to_pixel32(r, g, b);
  163 + break;
  164 + default:
  165 + abort();
  166 + }
  167 + }
  168 +
  169 +}
  170 +
  171 +static void syborg_fb_update_display(void *opaque)
  172 +{
  173 + SyborgFBState *s = (SyborgFBState *)opaque;
  174 + drawfn* fntable;
  175 + drawfn fn;
  176 + int dest_width;
  177 + int src_width;
  178 + int bpp_offset;
  179 + int first;
  180 + int last;
  181 +
  182 + if (!syborg_fb_enabled(s))
  183 + return;
  184 +
  185 + switch (ds_get_bits_per_pixel(s->ds)) {
  186 + case 0:
  187 + return;
  188 + case 8:
  189 + fntable = pl110_draw_fn_8;
  190 + dest_width = 1;
  191 + break;
  192 + case 15:
  193 + fntable = pl110_draw_fn_15;
  194 + dest_width = 2;
  195 + break;
  196 + case 16:
  197 + fntable = pl110_draw_fn_16;
  198 + dest_width = 2;
  199 + break;
  200 + case 24:
  201 + fntable = pl110_draw_fn_24;
  202 + dest_width = 3;
  203 + break;
  204 + case 32:
  205 + fntable = pl110_draw_fn_32;
  206 + dest_width = 4;
  207 + break;
  208 + default:
  209 + fprintf(stderr, "syborg_fb: Bad color depth\n");
  210 + exit(1);
  211 + }
  212 +
  213 + if (s->need_int) {
  214 + s->int_status |= FB_INT_BASE_UPDATE_DONE;
  215 + syborg_fb_update(s);
  216 + s->need_int = 0;
  217 + }
  218 +
  219 + if (s->rgb) {
  220 + bpp_offset = 18;
  221 + } else {
  222 + bpp_offset = 0;
  223 + }
  224 + if (s->endian) {
  225 + bpp_offset += 6;
  226 + }
  227 +
  228 + fn = fntable[s->bpp + bpp_offset];
  229 +
  230 + if (s->pitch) {
  231 + src_width = s->pitch;
  232 + } else {
  233 + src_width = s->cols;
  234 + switch (s->bpp) {
  235 + case BPP_SRC_1:
  236 + src_width >>= 3;
  237 + break;
  238 + case BPP_SRC_2:
  239 + src_width >>= 2;
  240 + break;
  241 + case BPP_SRC_4:
  242 + src_width >>= 1;
  243 + break;
  244 + case BPP_SRC_8:
  245 + break;
  246 + case BPP_SRC_15:
  247 + case BPP_SRC_16:
  248 + src_width <<= 1;
  249 + break;
  250 + case BPP_SRC_24:
  251 + src_width *= 3;
  252 + break;
  253 + case BPP_SRC_32:
  254 + src_width <<= 2;
  255 + break;
  256 + }
  257 + }
  258 + dest_width *= s->cols;
  259 + first = 0;
  260 + /* TODO: Implement blanking. */
  261 + if (!s->blank) {
  262 + if (s->need_update && s->bpp <= BPP_SRC_8) {
  263 + syborg_fb_update_palette(s);
  264 + }
  265 + framebuffer_update_display(s->ds,
  266 + s->base, s->cols, s->rows,
  267 + src_width, dest_width, 0,
  268 + s->need_update,
  269 + fn, s->palette,
  270 + &first, &last);
  271 + if (first >= 0) {
  272 + dpy_update(s->ds, 0, first, s->cols, last - first + 1);
  273 + }
  274 +
  275 + s->int_status |= FB_INT_VSYNC;
  276 + syborg_fb_update(s);
  277 + }
  278 +
  279 + s->need_update = 0;
  280 +}
  281 +
  282 +static void syborg_fb_invalidate_display(void * opaque)
  283 +{
  284 + SyborgFBState *s = (SyborgFBState *)opaque;
  285 + s->need_update = 1;
  286 +}
  287 +
  288 +static uint32_t syborg_fb_read(void *opaque, target_phys_addr_t offset)
  289 +{
  290 + SyborgFBState *s = opaque;
  291 +
  292 + DPRINTF("read reg %d\n", (int)offset);
  293 + offset &= 0xfff;
  294 + switch (offset >> 2) {
  295 + case FB_ID:
  296 + return SYBORG_ID_FRAMEBUFFER;
  297 +
  298 + case FB_BASE:
  299 + return s->base;
  300 +
  301 + case FB_HEIGHT:
  302 + return s->rows;
  303 +
  304 + case FB_WIDTH:
  305 + return s->cols;
  306 +
  307 + case FB_ORIENTATION:
  308 + return 0;
  309 +
  310 + case FB_BLANK:
  311 + return s->blank;
  312 +
  313 + case FB_INT_MASK:
  314 + return s->int_enable;
  315 +
  316 + case FB_INTERRUPT_CAUSE:
  317 + return s->int_status;
  318 +
  319 + case FB_BPP:
  320 + switch (s->bpp) {
  321 + case BPP_SRC_1: return 1;
  322 + case BPP_SRC_2: return 2;
  323 + case BPP_SRC_4: return 4;
  324 + case BPP_SRC_8: return 8;
  325 + case BPP_SRC_15: return 15;
  326 + case BPP_SRC_16: return 16;
  327 + case BPP_SRC_24: return 24;
  328 + case BPP_SRC_32: return 32;
  329 + default: return 0;
  330 + }
  331 +
  332 + case FB_COLOR_ORDER:
  333 + return s->rgb;
  334 +
  335 + case FB_BYTE_ORDER:
  336 + return s->endian;
  337 +
  338 + case FB_PIXEL_ORDER:
  339 + return 0;
  340 +
  341 + case FB_ROW_PITCH:
  342 + return s->pitch;
  343 +
  344 + case FB_ENABLED:
  345 + return s->enabled;
  346 +
  347 + default:
  348 + if ((offset >> 2) >= FB_PALETTE_START
  349 + && (offset >> 2) <= FB_PALETTE_END) {
  350 + return s->raw_palette[(offset >> 2) - FB_PALETTE_START];
  351 + } else {
  352 + cpu_abort (cpu_single_env, "syborg_fb_read: Bad offset %x\n",
  353 + (int)offset);
  354 + }
  355 + return 0;
  356 + }
  357 +}
  358 +
  359 +static void syborg_fb_write(void *opaque, target_phys_addr_t offset,
  360 + uint32_t val)
  361 +{
  362 + SyborgFBState *s = opaque;
  363 +
  364 + DPRINTF("write reg %d = %d\n", (int)offset, val);
  365 + s->need_update = 1;
  366 + offset &= 0xfff;
  367 + switch (offset >> 2) {
  368 + case FB_BASE:
  369 + s->base = val;
  370 + s->need_int = 1;
  371 + s->need_update = 1;
  372 + syborg_fb_update(s);
  373 + break;
  374 +
  375 + case FB_HEIGHT:
  376 + s->rows = val;
  377 + break;
  378 +
  379 + case FB_WIDTH:
  380 + s->cols = val;
  381 + break;
  382 +
  383 + case FB_ORIENTATION:
  384 + /* TODO: Implement rotation. */
  385 + break;
  386 +
  387 + case FB_BLANK:
  388 + s->blank = val & 1;
  389 + break;
  390 +
  391 + case FB_INT_MASK:
  392 + s->int_enable = val;
  393 + syborg_fb_update(s);
  394 + break;
  395 +
  396 + case FB_INTERRUPT_CAUSE:
  397 + s->int_status &= ~val;
  398 + syborg_fb_update(s);
  399 + break;
  400 +
  401 + case FB_BPP:
  402 + switch (val) {
  403 + case 1: val = BPP_SRC_1; break;
  404 + case 2: val = BPP_SRC_2; break;
  405 + case 4: val = BPP_SRC_4; break;
  406 + case 8: val = BPP_SRC_8; break;
  407 + /* case 15: val = BPP_SRC_15; break; */
  408 + case 16: val = BPP_SRC_16; break;
  409 + /* case 24: val = BPP_SRC_24; break; */
  410 + case 32: val = BPP_SRC_32; break;
  411 + default: val = s->bpp; break;
  412 + }
  413 + s->bpp = val;
  414 + break;
  415 +
  416 + case FB_COLOR_ORDER:
  417 + s->rgb = (val != 0);
  418 + break;
  419 +
  420 + case FB_BYTE_ORDER:
  421 + s->endian = (val != 0);
  422 + break;
  423 +
  424 + case FB_PIXEL_ORDER:
  425 + /* TODO: Implement this. */
  426 + break;
  427 +
  428 + case FB_ROW_PITCH:
  429 + s->pitch = val;
  430 + break;
  431 +
  432 + case FB_ENABLED:
  433 + s->enabled = val;
  434 + break;
  435 +
  436 + default:
  437 + if ((offset >> 2) >= FB_PALETTE_START
  438 + && (offset >> 2) <= FB_PALETTE_END) {
  439 + s->raw_palette[(offset >> 2) - FB_PALETTE_START] = val;
  440 + } else {
  441 + cpu_abort (cpu_single_env, "syborg_fb_write: Bad offset %x\n",
  442 + (int)offset);
  443 + }
  444 + break;
  445 + }
  446 +}
  447 +
  448 +static CPUReadMemoryFunc *syborg_fb_readfn[] = {
  449 + syborg_fb_read,
  450 + syborg_fb_read,
  451 + syborg_fb_read
  452 +};
  453 +
  454 +static CPUWriteMemoryFunc *syborg_fb_writefn[] = {
  455 + syborg_fb_write,
  456 + syborg_fb_write,
  457 + syborg_fb_write
  458 +};
  459 +
  460 +static void syborg_fb_save(QEMUFile *f, void *opaque)
  461 +{
  462 + SyborgFBState *s = opaque;
  463 + int i;
  464 +
  465 + qemu_put_be32(f, s->need_int);
  466 + qemu_put_be32(f, s->int_status);
  467 + qemu_put_be32(f, s->int_enable);
  468 + qemu_put_be32(f, s->enabled);
  469 + qemu_put_be32(f, s->base);
  470 + qemu_put_be32(f, s->pitch);
  471 + qemu_put_be32(f, s->rows);
  472 + qemu_put_be32(f, s->cols);
  473 + qemu_put_be32(f, s->bpp);
  474 + qemu_put_be32(f, s->rgb);
  475 + for (i = 0; i < 256; i++) {
  476 + qemu_put_be32(f, s->raw_palette[i]);
  477 + }
  478 +}
  479 +
  480 +static int syborg_fb_load(QEMUFile *f, void *opaque, int version_id)
  481 +{
  482 + SyborgFBState *s = opaque;
  483 + int i;
  484 +
  485 + if (version_id != 1)
  486 + return -EINVAL;
  487 +
  488 + s->need_int = qemu_get_be32(f);
  489 + s->int_status = qemu_get_be32(f);
  490 + s->int_enable = qemu_get_be32(f);
  491 + s->enabled = qemu_get_be32(f);
  492 + s->base = qemu_get_be32(f);
  493 + s->pitch = qemu_get_be32(f);
  494 + s->rows = qemu_get_be32(f);
  495 + s->cols = qemu_get_be32(f);
  496 + s->bpp = qemu_get_be32(f);
  497 + s->rgb = qemu_get_be32(f);
  498 + for (i = 0; i < 256; i++) {
  499 + s->raw_palette[i] = qemu_get_be32(f);
  500 + }
  501 + s->need_update = 1;
  502 +
  503 + return 0;
  504 +}
  505 +
  506 +static void syborg_fb_init(SysBusDevice *dev)
  507 +{
  508 + SyborgFBState *s = FROM_SYSBUS(SyborgFBState, dev);
  509 + int iomemtype;
  510 + int width;
  511 + int height;
  512 +
  513 + sysbus_init_irq(dev, &s->irq);
  514 + iomemtype = cpu_register_io_memory(0, syborg_fb_readfn,
  515 + syborg_fb_writefn, s);
  516 + sysbus_init_mmio(dev, 0x1000, iomemtype);
  517 +
  518 + width = qdev_get_prop_int(&dev->qdev, "width", 0);
  519 + height = qdev_get_prop_int(&dev->qdev, "height", 0);
  520 +
  521 + s->ds = graphic_console_init(syborg_fb_update_display,
  522 + syborg_fb_invalidate_display,
  523 + NULL, NULL, s);
  524 +
  525 + if (width != 0 && height != 0) {
  526 + qemu_console_resize(s->ds, width, height);
  527 + }
  528 +
  529 + if (!width)
  530 + width = ds_get_width(s->ds);
  531 + if (!height)
  532 + height = ds_get_height(s->ds);
  533 +
  534 + s->cols = width;
  535 + s->rows = height;
  536 +
  537 + register_savevm("syborg_framebuffer", -1, 1,
  538 + syborg_fb_save, syborg_fb_load, s);
  539 +}
  540 +
  541 +static void syborg_fb_register_devices(void)
  542 +{
  543 + sysbus_register_dev("syborg,framebuffer", sizeof(SyborgFBState),
  544 + syborg_fb_init);
  545 +}
  546 +
  547 +device_init(syborg_fb_register_devices)
... ...
hw/syborg_interrupt.c 0 → 100644
  1 +/*
  2 + * Syborg interrupt controller.
  3 + *
  4 + * Copyright (c) 2008 CodeSourcery
  5 + *
  6 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 + * of this software and associated documentation files (the "Software"), to deal
  8 + * in the Software without restriction, including without limitation the rights
  9 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 + * copies of the Software, and to permit persons to whom the Software is
  11 + * furnished to do so, subject to the following conditions:
  12 + *
  13 + * The above copyright notice and this permission notice shall be included in
  14 + * all copies or substantial portions of the Software.
  15 + *
  16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 + * THE SOFTWARE.
  23 + */
  24 +
  25 +#include "sysbus.h"
  26 +#include "syborg.h"
  27 +
  28 +//#define DEBUG_SYBORG_INT
  29 +
  30 +#ifdef DEBUG_SYBORG_INT
  31 +#define DPRINTF(fmt, ...) \
  32 +do { printf("syborg_int: " fmt , ## __VA_ARGS__); } while (0)
  33 +#define BADF(fmt, ...) \
  34 +do { fprintf(stderr, "syborg_int: error: " fmt , ## __VA_ARGS__); \
  35 + exit(1);} while (0)
  36 +#else
  37 +#define DPRINTF(fmt, ...) do {} while(0)
  38 +#define BADF(fmt, ...) \
  39 +do { fprintf(stderr, "syborg_int: error: " fmt , ## __VA_ARGS__);} while (0)
  40 +#endif
  41 +enum {
  42 + INT_ID = 0,
  43 + INT_STATUS = 1, /* number of pending interrupts */
  44 + INT_CURRENT = 2, /* next interrupt to be serviced */
  45 + INT_DISABLE_ALL = 3,
  46 + INT_DISABLE = 4,
  47 + INT_ENABLE = 5,
  48 + INT_TOTAL = 6
  49 +};
  50 +
  51 +typedef struct {
  52 + unsigned level:1;
  53 + unsigned enabled:1;
  54 +} syborg_int_flags;
  55 +
  56 +typedef struct {
  57 + SysBusDevice busdev;
  58 + int pending_count;
  59 + int num_irqs;
  60 + syborg_int_flags *flags;
  61 + qemu_irq parent_irq;
  62 +} SyborgIntState;
  63 +
  64 +static void syborg_int_update(SyborgIntState *s)
  65 +{
  66 + DPRINTF("pending %d\n", s->pending_count);
  67 + qemu_set_irq(s->parent_irq, s->pending_count > 0);
  68 +}
  69 +
  70 +static void syborg_int_set_irq(void *opaque, int irq, int level)
  71 +{
  72 + SyborgIntState *s = (SyborgIntState *)opaque;
  73 +
  74 + if (s->flags[irq].level == level)
  75 + return;
  76 +
  77 + s->flags[irq].level = level;
  78 + if (s->flags[irq].enabled) {
  79 + if (level)
  80 + s->pending_count++;
  81 + else
  82 + s->pending_count--;
  83 + syborg_int_update(s);
  84 + }
  85 +}
  86 +
  87 +static uint32_t syborg_int_read(void *opaque, target_phys_addr_t offset)
  88 +{
  89 + SyborgIntState *s = (SyborgIntState *)opaque;
  90 + int i;
  91 +
  92 + offset &= 0xfff;
  93 + switch (offset >> 2) {
  94 + case INT_ID:
  95 + return SYBORG_ID_INT;
  96 + case INT_STATUS:
  97 + DPRINTF("read status=%d\n", s->pending_count);
  98 + return s->pending_count;
  99 +
  100 + case INT_CURRENT:
  101 + for (i = 0; i < s->num_irqs; i++) {
  102 + if (s->flags[i].level & s->flags[i].enabled) {
  103 + DPRINTF("read current=%d\n", i);
  104 + return i;
  105 + }
  106 + }
  107 + DPRINTF("read current=none\n");
  108 + return 0xffffffffu;
  109 +
  110 + default:
  111 + cpu_abort(cpu_single_env, "syborg_int_read: Bad offset %x\n",
  112 + (int)offset);
  113 + return 0;
  114 + }
  115 +}
  116 +
  117 +static void syborg_int_write(void *opaque, target_phys_addr_t offset, uint32_t value)
  118 +{
  119 + SyborgIntState *s = (SyborgIntState *)opaque;
  120 + int i;
  121 + offset &= 0xfff;
  122 +
  123 + DPRINTF("syborg_int_write offset=%d val=%d\n", (int)offset, (int)value);
  124 + switch (offset >> 2) {
  125 + case INT_DISABLE_ALL:
  126 + s->pending_count = 0;
  127 + for (i = 0; i < s->num_irqs; i++)
  128 + s->flags[i].enabled = 0;
  129 + break;
  130 +
  131 + case INT_DISABLE:
  132 + if (value >= s->num_irqs)
  133 + break;
  134 + if (s->flags[value].enabled) {
  135 + if (s->flags[value].enabled)
  136 + s->pending_count--;
  137 + s->flags[value].enabled = 0;
  138 + }
  139 + break;
  140 +
  141 + case INT_ENABLE:
  142 + if (value >= s->num_irqs)
  143 + break;
  144 + if (!(s->flags[value].enabled)) {
  145 + if(s->flags[value].level)
  146 + s->pending_count++;
  147 + s->flags[value].enabled = 1;
  148 + }
  149 + break;
  150 +
  151 + default:
  152 + cpu_abort(cpu_single_env, "syborg_int_write: Bad offset %x\n",
  153 + (int)offset);
  154 + return;
  155 + }
  156 + syborg_int_update(s);
  157 +}
  158 +
  159 +static CPUReadMemoryFunc *syborg_int_readfn[] = {
  160 + syborg_int_read,
  161 + syborg_int_read,
  162 + syborg_int_read
  163 +};
  164 +
  165 +static CPUWriteMemoryFunc *syborg_int_writefn[] = {
  166 + syborg_int_write,
  167 + syborg_int_write,
  168 + syborg_int_write
  169 +};
  170 +
  171 +static void syborg_int_save(QEMUFile *f, void *opaque)
  172 +{
  173 + SyborgIntState *s = (SyborgIntState *)opaque;
  174 + int i;
  175 +
  176 + qemu_put_be32(f, s->num_irqs);
  177 + qemu_put_be32(f, s->pending_count);
  178 + for (i = 0; i < s->num_irqs; i++) {
  179 + qemu_put_be32(f, s->flags[i].enabled
  180 + | ((unsigned)s->flags[i].level << 1));
  181 + }
  182 +}
  183 +
  184 +static int syborg_int_load(QEMUFile *f, void *opaque, int version_id)
  185 +{
  186 + SyborgIntState *s = (SyborgIntState *)opaque;
  187 + uint32_t val;
  188 + int i;
  189 +
  190 + if (version_id != 1)
  191 + return -EINVAL;
  192 +
  193 + val = qemu_get_be32(f);
  194 + if (val != s->num_irqs)
  195 + return -EINVAL;
  196 + s->pending_count = qemu_get_be32(f);
  197 + for (i = 0; i < s->num_irqs; i++) {
  198 + val = qemu_get_be32(f);
  199 + s->flags[i].enabled = val & 1;
  200 + s->flags[i].level = (val >> 1) & 1;
  201 + }
  202 + return 0;
  203 +}
  204 +
  205 +static void syborg_int_init(SysBusDevice *dev)
  206 +{
  207 + SyborgIntState *s = FROM_SYSBUS(SyborgIntState, dev);
  208 + int iomemtype;
  209 +
  210 + sysbus_init_irq(dev, &s->parent_irq);
  211 + s->num_irqs = qdev_get_prop_int(&dev->qdev, "num-interrupts", 64);
  212 + qdev_init_irq_sink(&dev->qdev, syborg_int_set_irq, s->num_irqs);
  213 + iomemtype = cpu_register_io_memory(0, syborg_int_readfn,
  214 + syborg_int_writefn, s);
  215 + sysbus_init_mmio(dev, 0x1000, iomemtype);
  216 + s->flags = qemu_mallocz(s->num_irqs * sizeof(syborg_int_flags));
  217 +
  218 + register_savevm("syborg_int", -1, 1, syborg_int_save, syborg_int_load, s);
  219 +}
  220 +
  221 +static void syborg_interrupt_register_devices(void)
  222 +{
  223 + sysbus_register_dev("syborg,interrupt", sizeof(SyborgIntState),
  224 + syborg_int_init);
  225 +}
  226 +
  227 +device_init(syborg_interrupt_register_devices)
... ...
hw/syborg_keyboard.c 0 → 100644
  1 +/*
  2 + * Syborg keyboard controller.
  3 + *
  4 + * Copyright (c) 2008 CodeSourcery
  5 + *
  6 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 + * of this software and associated documentation files (the "Software"), to deal
  8 + * in the Software without restriction, including without limitation the rights
  9 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 + * copies of the Software, and to permit persons to whom the Software is
  11 + * furnished to do so, subject to the following conditions:
  12 + *
  13 + * The above copyright notice and this permission notice shall be included in
  14 + * all copies or substantial portions of the Software.
  15 + *
  16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 + * THE SOFTWARE.
  23 + */
  24 +
  25 +#include "sysbus.h"
  26 +#include "console.h"
  27 +#include "syborg.h"
  28 +
  29 +//#define DEBUG_SYBORG_KEYBOARD
  30 +
  31 +#ifdef DEBUG_SYBORG_KEYBOARD
  32 +#define DPRINTF(fmt, ...) \
  33 +do { printf("syborg_keyboard: " fmt , ##args); } while (0)
  34 +#define BADF(fmt, ...) \
  35 +do { fprintf(stderr, "syborg_keyboard: error: " fmt , ## __VA_ARGS__); \
  36 + exit(1);} while (0)
  37 +#else
  38 +#define DPRINTF(fmt, ...) do {} while(0)
  39 +#define BADF(fmt, ...) \
  40 +do { fprintf(stderr, "syborg_keyboard: error: " fmt , ## __VA_ARGS__); \
  41 +} while (0)
  42 +#endif
  43 +
  44 +enum {
  45 + KBD_ID = 0,
  46 + KBD_DATA = 1,
  47 + KBD_FIFO_COUNT = 2,
  48 + KBD_INT_ENABLE = 3,
  49 + KBD_FIFO_SIZE = 4
  50 +};
  51 +
  52 +typedef struct {
  53 + SysBusDevice busdev;
  54 + int int_enabled;
  55 + int extension_bit;
  56 + int fifo_size;
  57 + uint32_t *key_fifo;
  58 + int read_pos, read_count;
  59 + qemu_irq irq;
  60 +} SyborgKeyboardState;
  61 +
  62 +static void syborg_keyboard_update(SyborgKeyboardState *s)
  63 +{
  64 + int level = s->read_count && s->int_enabled;
  65 + DPRINTF("Update IRQ %d\n", level);
  66 + qemu_set_irq(s->irq, level);
  67 +}
  68 +
  69 +static uint32_t syborg_keyboard_read(void *opaque, target_phys_addr_t offset)
  70 +{
  71 + SyborgKeyboardState *s = (SyborgKeyboardState *)opaque;
  72 + int c;
  73 +
  74 + DPRINTF("reg read %d\n", (int)offset);
  75 + offset &= 0xfff;
  76 + switch (offset >> 2) {
  77 + case KBD_ID:
  78 + return SYBORG_ID_KEYBOARD;
  79 + case KBD_FIFO_COUNT:
  80 + return s->read_count;
  81 + case KBD_DATA:
  82 + if (s->read_count == 0) {
  83 + c = -1;
  84 + DPRINTF("FIFO underflow\n");
  85 + } else {
  86 + c = s->key_fifo[s->read_pos];
  87 + DPRINTF("FIFO read 0x%x\n", c);
  88 + s->read_count--;
  89 + s->read_pos++;
  90 + if (s->read_pos == s->fifo_size)
  91 + s->read_pos = 0;
  92 + }
  93 + syborg_keyboard_update(s);
  94 + return c;
  95 + case KBD_INT_ENABLE:
  96 + return s->int_enabled;
  97 + case KBD_FIFO_SIZE:
  98 + return s->fifo_size;
  99 + default:
  100 + cpu_abort(cpu_single_env, "syborg_keyboard_read: Bad offset %x\n",
  101 + (int)offset);
  102 + return 0;
  103 + }
  104 +}
  105 +
  106 +static void syborg_keyboard_write(void *opaque, target_phys_addr_t offset,
  107 + uint32_t value)
  108 +{
  109 + SyborgKeyboardState *s = (SyborgKeyboardState *)opaque;
  110 +
  111 + DPRINTF("reg write %d\n", (int)offset);
  112 + offset &= 0xfff;
  113 + switch (offset >> 2) {
  114 + case KBD_INT_ENABLE:
  115 + s->int_enabled = value;
  116 + syborg_keyboard_update(s);
  117 + break;
  118 + default:
  119 + cpu_abort(cpu_single_env, "syborg_keyboard_write: Bad offset %x\n",
  120 + (int)offset);
  121 + }
  122 +}
  123 +
  124 +static CPUReadMemoryFunc *syborg_keyboard_readfn[] = {
  125 + syborg_keyboard_read,
  126 + syborg_keyboard_read,
  127 + syborg_keyboard_read
  128 +};
  129 +
  130 +static CPUWriteMemoryFunc *syborg_keyboard_writefn[] = {
  131 + syborg_keyboard_write,
  132 + syborg_keyboard_write,
  133 + syborg_keyboard_write
  134 +};
  135 +
  136 +static void syborg_keyboard_event(void *opaque, int keycode)
  137 +{
  138 + SyborgKeyboardState *s = (SyborgKeyboardState *)opaque;
  139 + int slot;
  140 + uint32_t val;
  141 +
  142 + /* Strip off 0xe0 prefixes and reconstruct the full scancode. */
  143 + if (keycode == 0xe0 && !s->extension_bit) {
  144 + DPRINTF("Extension bit\n");
  145 + s->extension_bit = 0x80;
  146 + return;
  147 + }
  148 + val = (keycode & 0x7f) | s->extension_bit;
  149 + if (keycode & 0x80)
  150 + val |= 0x80000000u;
  151 + s->extension_bit = 0;
  152 +
  153 + DPRINTF("FIFO push 0x%x\n", val);
  154 + slot = s->read_pos + s->read_count;
  155 + if (slot >= s->fifo_size)
  156 + slot -= s->fifo_size;
  157 +
  158 + if (s->read_count < s->fifo_size) {
  159 + s->read_count++;
  160 + s->key_fifo[slot] = val;
  161 + } else {
  162 + fprintf(stderr, "syborg_keyboard error! FIFO overflow\n");
  163 + }
  164 +
  165 + syborg_keyboard_update(s);
  166 +}
  167 +
  168 +static void syborg_keyboard_save(QEMUFile *f, void *opaque)
  169 +{
  170 + SyborgKeyboardState *s = (SyborgKeyboardState *)opaque;
  171 + int i;
  172 +
  173 + qemu_put_be32(f, s->fifo_size);
  174 + qemu_put_be32(f, s->int_enabled);
  175 + qemu_put_be32(f, s->extension_bit);
  176 + qemu_put_be32(f, s->read_pos);
  177 + qemu_put_be32(f, s->read_count);
  178 + for (i = 0; i < s->fifo_size; i++) {
  179 + qemu_put_be32(f, s->key_fifo[i]);
  180 + }
  181 +}
  182 +
  183 +static int syborg_keyboard_load(QEMUFile *f, void *opaque, int version_id)
  184 +{
  185 + SyborgKeyboardState *s = (SyborgKeyboardState *)opaque;
  186 + uint32_t val;
  187 + int i;
  188 +
  189 + if (version_id != 1)
  190 + return -EINVAL;
  191 +
  192 + val = qemu_get_be32(f);
  193 + if (val != s->fifo_size)
  194 + return -EINVAL;
  195 +
  196 + s->int_enabled = qemu_get_be32(f);
  197 + s->extension_bit = qemu_get_be32(f);
  198 + s->read_pos = qemu_get_be32(f);
  199 + s->read_count = qemu_get_be32(f);
  200 + for (i = 0; i < s->fifo_size; i++) {
  201 + s->key_fifo[i] = qemu_get_be32(f);
  202 + }
  203 + return 0;
  204 +}
  205 +
  206 +static void syborg_keyboard_init(SysBusDevice *dev)
  207 +{
  208 + SyborgKeyboardState *s = FROM_SYSBUS(SyborgKeyboardState, dev);
  209 + int iomemtype;
  210 +
  211 + sysbus_init_irq(dev, &s->irq);
  212 + iomemtype = cpu_register_io_memory(0, syborg_keyboard_readfn,
  213 + syborg_keyboard_writefn, s);
  214 + sysbus_init_mmio(dev, 0x1000, iomemtype);
  215 + s->fifo_size = qdev_get_prop_int(&dev->qdev, "fifo-size", 16);
  216 + if (s->fifo_size <= 0) {
  217 + fprintf(stderr, "syborg_keyboard: fifo too small\n");
  218 + s->fifo_size = 16;
  219 + }
  220 + s->key_fifo = qemu_mallocz(s->fifo_size * sizeof(s->key_fifo[0]));
  221 +
  222 + qemu_add_kbd_event_handler(syborg_keyboard_event, s);
  223 +
  224 + register_savevm("syborg_keyboard", -1, 1,
  225 + syborg_keyboard_save, syborg_keyboard_load, s);
  226 +}
  227 +
  228 +static void syborg_keyboard_register_devices(void)
  229 +{
  230 + sysbus_register_dev("syborg,keyboard", sizeof(SyborgKeyboardState),
  231 + syborg_keyboard_init);
  232 +}
  233 +
  234 +device_init(syborg_keyboard_register_devices)
... ...
hw/syborg_pointer.c 0 → 100644
  1 +/*
  2 + * Syborg pointing device (mouse/touchscreen)
  3 + *
  4 + * Copyright (c) 2008 CodeSourcery
  5 + *
  6 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 + * of this software and associated documentation files (the "Software"), to deal
  8 + * in the Software without restriction, including without limitation the rights
  9 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 + * copies of the Software, and to permit persons to whom the Software is
  11 + * furnished to do so, subject to the following conditions:
  12 + *
  13 + * The above copyright notice and this permission notice shall be included in
  14 + * all copies or substantial portions of the Software.
  15 + *
  16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 + * THE SOFTWARE.
  23 + */
  24 +
  25 +#include "sysbus.h"
  26 +#include "console.h"
  27 +#include "syborg.h"
  28 +
  29 +enum {
  30 + POINTER_ID = 0,
  31 + POINTER_LATCH = 1,
  32 + POINTER_FIFO_COUNT = 2,
  33 + POINTER_X = 3,
  34 + POINTER_Y = 4,
  35 + POINTER_Z = 5,
  36 + POINTER_BUTTONS = 6,
  37 + POINTER_INT_ENABLE = 7,
  38 + POINTER_FIFO_SIZE = 8
  39 +};
  40 +
  41 +typedef struct {
  42 + int x, y, z, pointer_buttons;
  43 +} event_data;
  44 +
  45 +typedef struct {
  46 + SysBusDevice busdev;
  47 + int int_enabled;
  48 + int fifo_size;
  49 + event_data *event_fifo;
  50 + int read_pos, read_count;
  51 + qemu_irq irq;
  52 + int absolute;
  53 +} SyborgPointerState;
  54 +
  55 +static void syborg_pointer_update(SyborgPointerState *s)
  56 +{
  57 + qemu_set_irq(s->irq, s->read_count && s->int_enabled);
  58 +}
  59 +
  60 +static uint32_t syborg_pointer_read(void *opaque, target_phys_addr_t offset)
  61 +{
  62 + SyborgPointerState *s = (SyborgPointerState *)opaque;
  63 +
  64 + offset &= 0xfff;
  65 + switch (offset >> 2) {
  66 + case POINTER_ID:
  67 + return s->absolute ? SYBORG_ID_TOUCHSCREEN : SYBORG_ID_MOUSE;
  68 + case POINTER_FIFO_COUNT:
  69 + return s->read_count;
  70 + case POINTER_X:
  71 + return s->event_fifo[s->read_pos].x;
  72 + case POINTER_Y:
  73 + return s->event_fifo[s->read_pos].y;
  74 + case POINTER_Z:
  75 + return s->event_fifo[s->read_pos].z;
  76 + case POINTER_BUTTONS:
  77 + return s->event_fifo[s->read_pos].pointer_buttons;
  78 + case POINTER_INT_ENABLE:
  79 + return s->int_enabled;
  80 + case POINTER_FIFO_SIZE:
  81 + return s->fifo_size;
  82 + default:
  83 + cpu_abort(cpu_single_env, "syborg_pointer_read: Bad offset %x\n",
  84 + (int)offset);
  85 + return 0;
  86 + }
  87 +}
  88 +
  89 +static void syborg_pointer_write(void *opaque, target_phys_addr_t offset,
  90 + uint32_t value)
  91 +{
  92 + SyborgPointerState *s = (SyborgPointerState *)opaque;
  93 +
  94 + offset &= 0xfff;
  95 + switch (offset >> 2) {
  96 + case POINTER_LATCH:
  97 + if (s->read_count > 0) {
  98 + s->read_count--;
  99 + if (++s->read_pos == s->fifo_size)
  100 + s->read_pos = 0;
  101 + }
  102 + break;
  103 + case POINTER_INT_ENABLE:
  104 + s->int_enabled = value;
  105 + break;
  106 + default:
  107 + cpu_abort(cpu_single_env, "syborg_pointer_write: Bad offset %x\n",
  108 + (int)offset);
  109 + }
  110 + syborg_pointer_update(s);
  111 +}
  112 +
  113 +static CPUReadMemoryFunc *syborg_pointer_readfn[] = {
  114 + syborg_pointer_read,
  115 + syborg_pointer_read,
  116 + syborg_pointer_read
  117 +};
  118 +
  119 +static CPUWriteMemoryFunc *syborg_pointer_writefn[] = {
  120 + syborg_pointer_write,
  121 + syborg_pointer_write,
  122 + syborg_pointer_write
  123 +};
  124 +
  125 +static void syborg_pointer_event(void *opaque, int dx, int dy, int dz,
  126 + int buttons_state)
  127 +{
  128 + SyborgPointerState *s = (SyborgPointerState *)opaque;
  129 + int slot = s->read_pos + s->read_count;
  130 +
  131 + /* This first FIFO entry is used to store current register state. */
  132 + if (s->read_count < s->fifo_size - 1) {
  133 + s->read_count++;
  134 + slot++;
  135 + }
  136 +
  137 + if (slot >= s->fifo_size)
  138 + slot -= s->fifo_size;
  139 +
  140 + if (s->read_count == s->fifo_size && !s->absolute) {
  141 + /* Merge existing entries. */
  142 + s->event_fifo[slot].x += dx;
  143 + s->event_fifo[slot].y += dy;
  144 + s->event_fifo[slot].z += dz;
  145 + } else {
  146 + s->event_fifo[slot].x = dx;
  147 + s->event_fifo[slot].y = dy;
  148 + s->event_fifo[slot].z = dz;
  149 + }
  150 + s->event_fifo[slot].pointer_buttons = buttons_state;
  151 +
  152 + syborg_pointer_update(s);
  153 +}
  154 +
  155 +static void syborg_pointer_save(QEMUFile *f, void *opaque)
  156 +{
  157 + SyborgPointerState *s = (SyborgPointerState *)opaque;
  158 + int i;
  159 +
  160 + qemu_put_be32(f, s->fifo_size);
  161 + qemu_put_be32(f, s->absolute);
  162 + qemu_put_be32(f, s->int_enabled);
  163 + qemu_put_be32(f, s->read_pos);
  164 + qemu_put_be32(f, s->read_count);
  165 + for (i = 0; i < s->fifo_size; i++) {
  166 + qemu_put_be32(f, s->event_fifo[i].x);
  167 + qemu_put_be32(f, s->event_fifo[i].y);
  168 + qemu_put_be32(f, s->event_fifo[i].z);
  169 + qemu_put_be32(f, s->event_fifo[i].pointer_buttons);
  170 + }
  171 +}
  172 +
  173 +static int syborg_pointer_load(QEMUFile *f, void *opaque, int version_id)
  174 +{
  175 + SyborgPointerState *s = (SyborgPointerState *)opaque;
  176 + uint32_t val;
  177 + int i;
  178 +
  179 + if (version_id != 1)
  180 + return -EINVAL;
  181 +
  182 + val = qemu_get_be32(f);
  183 + if (val != s->fifo_size)
  184 + return -EINVAL;
  185 +
  186 + val = qemu_get_be32(f);
  187 + if (val != s->absolute)
  188 + return -EINVAL;
  189 +
  190 + s->int_enabled = qemu_get_be32(f);
  191 + s->read_pos = qemu_get_be32(f);
  192 + s->read_count = qemu_get_be32(f);
  193 + for (i = 0; i < s->fifo_size; i++) {
  194 + s->event_fifo[i].x = qemu_get_be32(f);
  195 + s->event_fifo[i].y = qemu_get_be32(f);
  196 + s->event_fifo[i].z = qemu_get_be32(f);
  197 + s->event_fifo[i].pointer_buttons = qemu_get_be32(f);
  198 + }
  199 + return 0;
  200 +}
  201 +
  202 +static void syborg_pointer_init(SysBusDevice *dev)
  203 +{
  204 + SyborgPointerState *s = FROM_SYSBUS(SyborgPointerState, dev);
  205 + int iomemtype;
  206 +
  207 + sysbus_init_irq(dev, &s->irq);
  208 + iomemtype = cpu_register_io_memory(0, syborg_pointer_readfn,
  209 + syborg_pointer_writefn, s);
  210 + sysbus_init_mmio(dev, 0x1000, iomemtype);
  211 +
  212 + s->absolute = qdev_get_prop_int(&dev->qdev, "absolute", 1);
  213 + s->fifo_size = qdev_get_prop_int(&dev->qdev, "fifo-size", 16);
  214 + if (s->fifo_size <= 0) {
  215 + fprintf(stderr, "syborg_pointer: fifo too small\n");
  216 + s->fifo_size = 16;
  217 + }
  218 + s->event_fifo = qemu_mallocz(s->fifo_size * sizeof(s->event_fifo[0]));
  219 +
  220 + qemu_add_mouse_event_handler(syborg_pointer_event, s, s->absolute,
  221 + "Syborg Pointer");
  222 +
  223 + register_savevm("syborg_pointer", -1, 1,
  224 + syborg_pointer_save, syborg_pointer_load, s);
  225 +}
  226 +
  227 +static void syborg_pointer_register_devices(void)
  228 +{
  229 + sysbus_register_dev("syborg,pointer", sizeof(SyborgPointerState),
  230 + syborg_pointer_init);
  231 +}
  232 +
  233 +device_init(syborg_pointer_register_devices)
... ...
hw/syborg_rtc.c 0 → 100644
  1 +/*
  2 + * Syborg RTC
  3 + *
  4 + * Copyright (c) 2008 CodeSourcery
  5 + *
  6 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 + * of this software and associated documentation files (the "Software"), to deal
  8 + * in the Software without restriction, including without limitation the rights
  9 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 + * copies of the Software, and to permit persons to whom the Software is
  11 + * furnished to do so, subject to the following conditions:
  12 + *
  13 + * The above copyright notice and this permission notice shall be included in
  14 + * all copies or substantial portions of the Software.
  15 + *
  16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 + * THE SOFTWARE.
  23 + */
  24 +
  25 +#include "sysbus.h"
  26 +#include "qemu-timer.h"
  27 +#include "syborg.h"
  28 +
  29 +enum {
  30 + RTC_ID = 0,
  31 + RTC_LATCH = 1,
  32 + RTC_DATA_LOW = 2,
  33 + RTC_DATA_HIGH = 3
  34 +};
  35 +
  36 +typedef struct {
  37 + SysBusDevice busdev;
  38 + int64_t offset;
  39 + int64_t data;
  40 + qemu_irq irq;
  41 +} SyborgRTCState;
  42 +
  43 +static uint32_t syborg_rtc_read(void *opaque, target_phys_addr_t offset)
  44 +{
  45 + SyborgRTCState *s = (SyborgRTCState *)opaque;
  46 + offset &= 0xfff;
  47 + switch (offset >> 2) {
  48 + case RTC_ID:
  49 + return SYBORG_ID_RTC;
  50 + case RTC_DATA_LOW:
  51 + return (uint32_t)s->data;
  52 + case RTC_DATA_HIGH:
  53 + return (uint32_t)(s->data >> 32);
  54 + default:
  55 + cpu_abort(cpu_single_env, "syborg_rtc_read: Bad offset %x\n",
  56 + (int)offset);
  57 + return 0;
  58 + }
  59 +}
  60 +
  61 +static void syborg_rtc_write(void *opaque, target_phys_addr_t offset, uint32_t value)
  62 +{
  63 + SyborgRTCState *s = (SyborgRTCState *)opaque;
  64 + uint64_t now;
  65 +
  66 + offset &= 0xfff;
  67 + switch (offset >> 2) {
  68 + case RTC_LATCH:
  69 + now = qemu_get_clock(vm_clock);
  70 + if (value >= 4) {
  71 + s->offset = s->data - now;
  72 + } else {
  73 + s->data = now + s->offset;
  74 + while (value) {
  75 + s->data /= 1000;
  76 + value--;
  77 + }
  78 + }
  79 + break;
  80 + case RTC_DATA_LOW:
  81 + s->data = (s->data & ~(uint64_t)0xffffffffu) | value;
  82 + break;
  83 + case RTC_DATA_HIGH:
  84 + s->data = (s->data & 0xffffffffu) | ((uint64_t)value << 32);
  85 + break;
  86 + default:
  87 + cpu_abort(cpu_single_env, "syborg_rtc_write: Bad offset %x\n",
  88 + (int)offset);
  89 + break;
  90 + }
  91 +}
  92 +
  93 +static CPUReadMemoryFunc *syborg_rtc_readfn[] = {
  94 + syborg_rtc_read,
  95 + syborg_rtc_read,
  96 + syborg_rtc_read
  97 +};
  98 +
  99 +static CPUWriteMemoryFunc *syborg_rtc_writefn[] = {
  100 + syborg_rtc_write,
  101 + syborg_rtc_write,
  102 + syborg_rtc_write
  103 +};
  104 +
  105 +static void syborg_rtc_save(QEMUFile *f, void *opaque)
  106 +{
  107 + SyborgRTCState *s = opaque;
  108 +
  109 + qemu_put_be64(f, s->offset);
  110 + qemu_put_be64(f, s->data);
  111 +}
  112 +
  113 +static int syborg_rtc_load(QEMUFile *f, void *opaque, int version_id)
  114 +{
  115 + SyborgRTCState *s = opaque;
  116 +
  117 + if (version_id != 1)
  118 + return -EINVAL;
  119 +
  120 + s->offset = qemu_get_be64(f);
  121 + s->data = qemu_get_be64(f);
  122 +
  123 + return 0;
  124 +}
  125 +
  126 +static void syborg_rtc_init(SysBusDevice *dev)
  127 +{
  128 + SyborgRTCState *s = FROM_SYSBUS(SyborgRTCState, dev);
  129 + struct tm tm;
  130 + int iomemtype;
  131 +
  132 + iomemtype = cpu_register_io_memory(0, syborg_rtc_readfn,
  133 + syborg_rtc_writefn, s);
  134 + sysbus_init_mmio(dev, 0x1000, iomemtype);
  135 +
  136 + qemu_get_timedate(&tm, 0);
  137 + s->offset = (uint64_t)mktime(&tm) * 1000000000;
  138 +
  139 + register_savevm("syborg_rtc", -1, 1, syborg_rtc_save, syborg_rtc_load, s);
  140 +}
  141 +
  142 +static void syborg_rtc_register_devices(void)
  143 +{
  144 + sysbus_register_dev("syborg,rtc", sizeof(SyborgRTCState), syborg_rtc_init);
  145 +}
  146 +
  147 +device_init(syborg_rtc_register_devices)
... ...
hw/syborg_serial.c 0 → 100644
  1 +/*
  2 + * Syborg serial port
  3 + *
  4 + * Copyright (c) 2008 CodeSourcery
  5 + *
  6 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 + * of this software and associated documentation files (the "Software"), to deal
  8 + * in the Software without restriction, including without limitation the rights
  9 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 + * copies of the Software, and to permit persons to whom the Software is
  11 + * furnished to do so, subject to the following conditions:
  12 + *
  13 + * The above copyright notice and this permission notice shall be included in
  14 + * all copies or substantial portions of the Software.
  15 + *
  16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 + * THE SOFTWARE.
  23 + */
  24 +
  25 +#include "sysbus.h"
  26 +#include "qemu-char.h"
  27 +#include "syborg.h"
  28 +
  29 +//#define DEBUG_SYBORG_SERIAL
  30 +
  31 +#ifdef DEBUG_SYBORG_SERIAL
  32 +#define DPRINTF(fmt, ...) \
  33 +do { printf("syborg_serial: " fmt , ##args); } while (0)
  34 +#define BADF(fmt, ...) \
  35 +do { fprintf(stderr, "syborg_serial: error: " fmt , ## __VA_ARGS__); \
  36 + exit(1);} while (0)
  37 +#else
  38 +#define DPRINTF(fmt, ...) do {} while(0)
  39 +#define BADF(fmt, ...) \
  40 +do { fprintf(stderr, "syborg_serial: error: " fmt , ## __VA_ARGS__);} while (0)
  41 +#endif
  42 +
  43 +enum {
  44 + SERIAL_ID = 0,
  45 + SERIAL_DATA = 1,
  46 + SERIAL_FIFO_COUNT = 2,
  47 + SERIAL_INT_ENABLE = 3,
  48 + SERIAL_DMA_TX_ADDR = 4,
  49 + SERIAL_DMA_TX_COUNT = 5, /* triggers dma */
  50 + SERIAL_DMA_RX_ADDR = 6,
  51 + SERIAL_DMA_RX_COUNT = 7, /* triggers dma */
  52 + SERIAL_FIFO_SIZE = 8
  53 +};
  54 +
  55 +#define SERIAL_INT_FIFO (1u << 0)
  56 +#define SERIAL_INT_DMA_TX (1u << 1)
  57 +#define SERIAL_INT_DMA_RX (1u << 2)
  58 +
  59 +typedef struct {
  60 + SysBusDevice busdev;
  61 + uint32_t int_enable;
  62 + int fifo_size;
  63 + uint32_t *read_fifo;
  64 + int read_pos;
  65 + int read_count;
  66 + CharDriverState *chr;
  67 + qemu_irq irq;
  68 + uint32_t dma_tx_ptr;
  69 + uint32_t dma_rx_ptr;
  70 + uint32_t dma_rx_size;
  71 +} SyborgSerialState;
  72 +
  73 +static void syborg_serial_update(SyborgSerialState *s)
  74 +{
  75 + int level;
  76 + level = 0;
  77 + if ((s->int_enable & SERIAL_INT_FIFO) && s->read_count)
  78 + level = 1;
  79 + if (s->int_enable & SERIAL_INT_DMA_TX)
  80 + level = 1;
  81 + if ((s->int_enable & SERIAL_INT_DMA_RX) && s->dma_rx_size == 0)
  82 + level = 1;
  83 +
  84 + qemu_set_irq(s->irq, level);
  85 +}
  86 +
  87 +static uint32_t fifo_pop(SyborgSerialState *s)
  88 +{
  89 + const uint32_t c = s->read_fifo[s->read_pos];
  90 + s->read_count--;
  91 + s->read_pos++;
  92 + if (s->read_pos == s->fifo_size)
  93 + s->read_pos = 0;
  94 +
  95 + DPRINTF("FIFO pop %x (%d)\n", c, s->read_count);
  96 + return c;
  97 +}
  98 +
  99 +static void fifo_push(SyborgSerialState *s, uint32_t new_value)
  100 +{
  101 + int slot;
  102 +
  103 + DPRINTF("FIFO push %x (%d)\n", new_value, s->read_count);
  104 + slot = s->read_pos + s->read_count;
  105 + if (slot >= s->fifo_size)
  106 + slot -= s->fifo_size;
  107 + s->read_fifo[slot] = new_value;
  108 + s->read_count++;
  109 +}
  110 +
  111 +static void do_dma_tx(SyborgSerialState *s, uint32_t count)
  112 +{
  113 + unsigned char ch;
  114 +
  115 + if (count == 0)
  116 + return;
  117 +
  118 + if (s->chr != NULL) {
  119 + /* optimize later. Now, 1 byte per iteration */
  120 + while (count--) {
  121 + cpu_physical_memory_read(s->dma_tx_ptr, &ch, 1);
  122 + qemu_chr_write(s->chr, &ch, 1);
  123 + s->dma_tx_ptr++;
  124 + }
  125 + } else {
  126 + s->dma_tx_ptr += count;
  127 + }
  128 + /* QEMU char backends do not have a nonblocking mode, so we transmit all
  129 + the data imediately and the interrupt status will be unchanged. */
  130 +}
  131 +
  132 +/* Initiate RX DMA, and transfer data from the FIFO. */
  133 +static void dma_rx_start(SyborgSerialState *s, uint32_t len)
  134 +{
  135 + uint32_t dest;
  136 + unsigned char ch;
  137 +
  138 + dest = s->dma_rx_ptr;
  139 + if (s->read_count < len) {
  140 + s->dma_rx_size = len - s->read_count;
  141 + len = s->read_count;
  142 + } else {
  143 + s->dma_rx_size = 0;
  144 + }
  145 +
  146 + while (len--) {
  147 + ch = fifo_pop(s);
  148 + cpu_physical_memory_write(dest, &ch, 1);
  149 + dest++;
  150 + }
  151 + s->dma_rx_ptr = dest;
  152 + syborg_serial_update(s);
  153 +}
  154 +
  155 +static uint32_t syborg_serial_read(void *opaque, target_phys_addr_t offset)
  156 +{
  157 + SyborgSerialState *s = (SyborgSerialState *)opaque;
  158 + uint32_t c;
  159 +
  160 + offset &= 0xfff;
  161 + DPRINTF("read 0x%x\n", (int)offset);
  162 + switch(offset >> 2) {
  163 + case SERIAL_ID:
  164 + return SYBORG_ID_SERIAL;
  165 + case SERIAL_DATA:
  166 + if (s->read_count > 0)
  167 + c = fifo_pop(s);
  168 + else
  169 + c = -1;
  170 + syborg_serial_update(s);
  171 + return c;
  172 + case SERIAL_FIFO_COUNT:
  173 + return s->read_count;
  174 + case SERIAL_INT_ENABLE:
  175 + return s->int_enable;
  176 + case SERIAL_DMA_TX_ADDR:
  177 + return s->dma_tx_ptr;
  178 + case SERIAL_DMA_TX_COUNT:
  179 + return 0;
  180 + case SERIAL_DMA_RX_ADDR:
  181 + return s->dma_rx_ptr;
  182 + case SERIAL_DMA_RX_COUNT:
  183 + return s->dma_rx_size;
  184 + case SERIAL_FIFO_SIZE:
  185 + return s->fifo_size;
  186 +
  187 + default:
  188 + cpu_abort(cpu_single_env, "syborg_serial_read: Bad offset %x\n",
  189 + (int)offset);
  190 + return 0;
  191 + }
  192 +}
  193 +
  194 +static void syborg_serial_write(void *opaque, target_phys_addr_t offset,
  195 + uint32_t value)
  196 +{
  197 + SyborgSerialState *s = (SyborgSerialState *)opaque;
  198 + unsigned char ch;
  199 +
  200 + offset &= 0xfff;
  201 + DPRINTF("Write 0x%x=0x%x\n", (int)offset, value);
  202 + switch (offset >> 2) {
  203 + case SERIAL_DATA:
  204 + ch = value;
  205 + if (s->chr)
  206 + qemu_chr_write(s->chr, &ch, 1);
  207 + break;
  208 + case SERIAL_INT_ENABLE:
  209 + s->int_enable = value;
  210 + syborg_serial_update(s);
  211 + break;
  212 + case SERIAL_DMA_TX_ADDR:
  213 + s->dma_tx_ptr = value;
  214 + break;
  215 + case SERIAL_DMA_TX_COUNT:
  216 + do_dma_tx(s, value);
  217 + break;
  218 + case SERIAL_DMA_RX_ADDR:
  219 + /* For safety, writes to this register cancel any pending DMA. */
  220 + s->dma_rx_size = 0;
  221 + s->dma_rx_ptr = value;
  222 + break;
  223 + case SERIAL_DMA_RX_COUNT:
  224 + dma_rx_start(s, value);
  225 + break;
  226 + default:
  227 + cpu_abort(cpu_single_env, "syborg_serial_write: Bad offset %x\n",
  228 + (int)offset);
  229 + break;
  230 + }
  231 +}
  232 +
  233 +static int syborg_serial_can_receive(void *opaque)
  234 +{
  235 + SyborgSerialState *s = (SyborgSerialState *)opaque;
  236 +
  237 + if (s->dma_rx_size)
  238 + return s->dma_rx_size;
  239 + return s->fifo_size - s->read_count;
  240 +}
  241 +
  242 +static void syborg_serial_receive(void *opaque, const uint8_t *buf, int size)
  243 +{
  244 + SyborgSerialState *s = (SyborgSerialState *)opaque;
  245 +
  246 + if (s->dma_rx_size) {
  247 + /* Place it in the DMA buffer. */
  248 + cpu_physical_memory_write(s->dma_rx_ptr, buf, size);
  249 + s->dma_rx_size -= size;
  250 + s->dma_rx_ptr += size;
  251 + } else {
  252 + while (size--)
  253 + fifo_push(s, *buf);
  254 + }
  255 +
  256 + syborg_serial_update(s);
  257 +}
  258 +
  259 +static void syborg_serial_event(void *opaque, int event)
  260 +{
  261 + /* TODO: Report BREAK events? */
  262 +}
  263 +
  264 +static CPUReadMemoryFunc *syborg_serial_readfn[] = {
  265 + syborg_serial_read,
  266 + syborg_serial_read,
  267 + syborg_serial_read
  268 +};
  269 +
  270 +static CPUWriteMemoryFunc *syborg_serial_writefn[] = {
  271 + syborg_serial_write,
  272 + syborg_serial_write,
  273 + syborg_serial_write
  274 +};
  275 +
  276 +static void syborg_serial_save(QEMUFile *f, void *opaque)
  277 +{
  278 + SyborgSerialState *s = opaque;
  279 + int i;
  280 +
  281 + qemu_put_be32(f, s->fifo_size);
  282 + qemu_put_be32(f, s->int_enable);
  283 + qemu_put_be32(f, s->read_pos);
  284 + qemu_put_be32(f, s->read_count);
  285 + qemu_put_be32(f, s->dma_tx_ptr);
  286 + qemu_put_be32(f, s->dma_rx_ptr);
  287 + qemu_put_be32(f, s->dma_rx_size);
  288 + for (i = 0; i < s->fifo_size; i++) {
  289 + qemu_put_be32(f, s->read_fifo[i]);
  290 + }
  291 +}
  292 +
  293 +static int syborg_serial_load(QEMUFile *f, void *opaque, int version_id)
  294 +{
  295 + SyborgSerialState *s = opaque;
  296 + int i;
  297 +
  298 + if (version_id != 1)
  299 + return -EINVAL;
  300 +
  301 + i = qemu_get_be32(f);
  302 + if (s->fifo_size != i)
  303 + return -EINVAL;
  304 +
  305 + s->int_enable = qemu_get_be32(f);
  306 + s->read_pos = qemu_get_be32(f);
  307 + s->read_count = qemu_get_be32(f);
  308 + s->dma_tx_ptr = qemu_get_be32(f);
  309 + s->dma_rx_ptr = qemu_get_be32(f);
  310 + s->dma_rx_size = qemu_get_be32(f);
  311 + for (i = 0; i < s->fifo_size; i++) {
  312 + s->read_fifo[i] = qemu_get_be32(f);
  313 + }
  314 +
  315 + return 0;
  316 +}
  317 +
  318 +static void syborg_serial_init(SysBusDevice *dev)
  319 +{
  320 + SyborgSerialState *s = FROM_SYSBUS(SyborgSerialState, dev);
  321 + int iomemtype;
  322 +
  323 + sysbus_init_irq(dev, &s->irq);
  324 + iomemtype = cpu_register_io_memory(0, syborg_serial_readfn,
  325 + syborg_serial_writefn, s);
  326 + sysbus_init_mmio(dev, 0x1000, iomemtype);
  327 + s->chr = qdev_init_chardev(&dev->qdev);
  328 + if (s->chr) {
  329 + qemu_chr_add_handlers(s->chr, syborg_serial_can_receive,
  330 + syborg_serial_receive, syborg_serial_event, s);
  331 + }
  332 + s->fifo_size = qdev_get_prop_int(&dev->qdev, "fifo-size", 16);
  333 + if (s->fifo_size <= 0) {
  334 + fprintf(stderr, "syborg_serial: fifo too small\n");
  335 + s->fifo_size = 16;
  336 + }
  337 + s->read_fifo = qemu_mallocz(s->fifo_size * sizeof(s->read_fifo[0]));
  338 +
  339 + register_savevm("syborg_serial", -1, 1,
  340 + syborg_serial_save, syborg_serial_load, s);
  341 +}
  342 +
  343 +static void syborg_serial_register_devices(void)
  344 +{
  345 + sysbus_register_dev("syborg,serial", sizeof(SyborgSerialState),
  346 + syborg_serial_init);
  347 +}
  348 +
  349 +device_init(syborg_serial_register_devices)
... ...
hw/syborg_timer.c 0 → 100644
  1 +/*
  2 + * Syborg Interval Timer.
  3 + *
  4 + * Copyright (c) 2008 CodeSourcery
  5 + *
  6 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 + * of this software and associated documentation files (the "Software"), to deal
  8 + * in the Software without restriction, including without limitation the rights
  9 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 + * copies of the Software, and to permit persons to whom the Software is
  11 + * furnished to do so, subject to the following conditions:
  12 + *
  13 + * The above copyright notice and this permission notice shall be included in
  14 + * all copies or substantial portions of the Software.
  15 + *
  16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 + * THE SOFTWARE.
  23 + */
  24 +
  25 +#include "sysbus.h"
  26 +#include "qemu-timer.h"
  27 +#include "syborg.h"
  28 +
  29 +//#define DEBUG_SYBORG_TIMER
  30 +
  31 +#ifdef DEBUG_SYBORG_TIMER
  32 +#define DPRINTF(fmt, ...) \
  33 +do { printf("syborg_timer: " fmt , ##args); } while (0)
  34 +#define BADF(fmt, ...) \
  35 +do { fprintf(stderr, "syborg_timer: error: " fmt , ## __VA_ARGS__); \
  36 + exit(1);} while (0)
  37 +#else
  38 +#define DPRINTF(fmt, ...) do {} while(0)
  39 +#define BADF(fmt, ...) \
  40 +do { fprintf(stderr, "syborg_timer: error: " fmt , ## __VA_ARGS__);} while (0)
  41 +#endif
  42 +
  43 +enum {
  44 + TIMER_ID = 0,
  45 + TIMER_RUNNING = 1,
  46 + TIMER_ONESHOT = 2,
  47 + TIMER_LIMIT = 3,
  48 + TIMER_VALUE = 4,
  49 + TIMER_INT_ENABLE = 5,
  50 + TIMER_INT_STATUS = 6,
  51 + TIMER_FREQ = 7
  52 +};
  53 +
  54 +typedef struct {
  55 + SysBusDevice busdev;
  56 + ptimer_state *timer;
  57 + int running;
  58 + int oneshot;
  59 + uint32_t limit;
  60 + uint32_t freq;
  61 + uint32_t int_level;
  62 + uint32_t int_enabled;
  63 + qemu_irq irq;
  64 +} SyborgTimerState;
  65 +
  66 +static void syborg_timer_update(SyborgTimerState *s)
  67 +{
  68 + /* Update interrupt. */
  69 + if (s->int_level && s->int_enabled) {
  70 + qemu_irq_raise(s->irq);
  71 + } else {
  72 + qemu_irq_lower(s->irq);
  73 + }
  74 +}
  75 +
  76 +static void syborg_timer_tick(void *opaque)
  77 +{
  78 + SyborgTimerState *s = (SyborgTimerState *)opaque;
  79 + //DPRINTF("Timer Tick\n");
  80 + s->int_level = 1;
  81 + if (s->oneshot)
  82 + s->running = 0;
  83 + syborg_timer_update(s);
  84 +}
  85 +
  86 +static uint32_t syborg_timer_read(void *opaque, target_phys_addr_t offset)
  87 +{
  88 + SyborgTimerState *s = (SyborgTimerState *)opaque;
  89 +
  90 + DPRINTF("Reg read %d\n", (int)offset);
  91 + offset &= 0xfff;
  92 + switch (offset >> 2) {
  93 + case TIMER_ID:
  94 + return SYBORG_ID_TIMER;
  95 + case TIMER_RUNNING:
  96 + return s->running;
  97 + case TIMER_ONESHOT:
  98 + return s->oneshot;
  99 + case TIMER_LIMIT:
  100 + return s->limit;
  101 + case TIMER_VALUE:
  102 + return ptimer_get_count(s->timer);
  103 + case TIMER_INT_ENABLE:
  104 + return s->int_enabled;
  105 + case TIMER_INT_STATUS:
  106 + return s->int_level;
  107 + case TIMER_FREQ:
  108 + return s->freq;
  109 + default:
  110 + cpu_abort(cpu_single_env, "syborg_timer_read: Bad offset %x\n",
  111 + (int)offset);
  112 + return 0;
  113 + }
  114 +}
  115 +
  116 +static void syborg_timer_write(void *opaque, target_phys_addr_t offset,
  117 + uint32_t value)
  118 +{
  119 + SyborgTimerState *s = (SyborgTimerState *)opaque;
  120 +
  121 + DPRINTF("Reg write %d\n", (int)offset);
  122 + offset &= 0xfff;
  123 + switch (offset >> 2) {
  124 + case TIMER_RUNNING:
  125 + if (value == s->running)
  126 + break;
  127 + s->running = value;
  128 + if (value) {
  129 + ptimer_run(s->timer, s->oneshot);
  130 + } else {
  131 + ptimer_stop(s->timer);
  132 + }
  133 + break;
  134 + case TIMER_ONESHOT:
  135 + if (s->running) {
  136 + ptimer_stop(s->timer);
  137 + }
  138 + s->oneshot = value;
  139 + if (s->running) {
  140 + ptimer_run(s->timer, s->oneshot);
  141 + }
  142 + break;
  143 + case TIMER_LIMIT:
  144 + s->limit = value;
  145 + ptimer_set_limit(s->timer, value, 1);
  146 + break;
  147 + case TIMER_VALUE:
  148 + ptimer_set_count(s->timer, value);
  149 + break;
  150 + case TIMER_INT_ENABLE:
  151 + s->int_enabled = value;
  152 + syborg_timer_update(s);
  153 + break;
  154 + case TIMER_INT_STATUS:
  155 + s->int_level &= ~value;
  156 + syborg_timer_update(s);
  157 + break;
  158 + default:
  159 + cpu_abort(cpu_single_env, "syborg_timer_write: Bad offset %x\n",
  160 + (int)offset);
  161 + break;
  162 + }
  163 +}
  164 +
  165 +static CPUReadMemoryFunc *syborg_timer_readfn[] = {
  166 + syborg_timer_read,
  167 + syborg_timer_read,
  168 + syborg_timer_read
  169 +};
  170 +
  171 +static CPUWriteMemoryFunc *syborg_timer_writefn[] = {
  172 + syborg_timer_write,
  173 + syborg_timer_write,
  174 + syborg_timer_write
  175 +};
  176 +
  177 +static void syborg_timer_save(QEMUFile *f, void *opaque)
  178 +{
  179 + SyborgTimerState *s = opaque;
  180 +
  181 + qemu_put_be32(f, s->running);
  182 + qemu_put_be32(f, s->oneshot);
  183 + qemu_put_be32(f, s->limit);
  184 + qemu_put_be32(f, s->int_level);
  185 + qemu_put_be32(f, s->int_enabled);
  186 + qemu_put_ptimer(f, s->timer);
  187 +}
  188 +
  189 +static int syborg_timer_load(QEMUFile *f, void *opaque, int version_id)
  190 +{
  191 + SyborgTimerState *s = opaque;
  192 +
  193 + if (version_id != 1)
  194 + return -EINVAL;
  195 +
  196 + s->running = qemu_get_be32(f);
  197 + s->oneshot = qemu_get_be32(f);
  198 + s->limit = qemu_get_be32(f);
  199 + s->int_level = qemu_get_be32(f);
  200 + s->int_enabled = qemu_get_be32(f);
  201 + qemu_get_ptimer(f, s->timer);
  202 +
  203 + return 0;
  204 +}
  205 +
  206 +static void syborg_timer_init(SysBusDevice *dev)
  207 +{
  208 + SyborgTimerState *s = FROM_SYSBUS(SyborgTimerState, dev);
  209 + QEMUBH *bh;
  210 + int iomemtype;
  211 +
  212 + s->freq = qdev_get_prop_int(&dev->qdev, "frequency", 0);
  213 + if (s->freq == 0) {
  214 + fprintf(stderr, "syborg_timer: Zero/unset frequency\n");
  215 + exit(1);
  216 + }
  217 + sysbus_init_irq(dev, &s->irq);
  218 + iomemtype = cpu_register_io_memory(0, syborg_timer_readfn,
  219 + syborg_timer_writefn, s);
  220 + sysbus_init_mmio(dev, 0x1000, iomemtype);
  221 +
  222 + bh = qemu_bh_new(syborg_timer_tick, s);
  223 + s->timer = ptimer_init(bh);
  224 + ptimer_set_freq(s->timer, s->freq);
  225 + register_savevm("syborg_timer", -1, 1,
  226 + syborg_timer_save, syborg_timer_load, s);
  227 +}
  228 +
  229 +static void syborg_timer_register_devices(void)
  230 +{
  231 + sysbus_register_dev("syborg,timer", sizeof(SyborgTimerState),
  232 + syborg_timer_init);
  233 +}
  234 +
  235 +device_init(syborg_timer_register_devices)
... ...
qemu-doc.texi
... ... @@ -91,6 +91,7 @@ For system emulation, the following hardware targets are supported:
91 91 @item MusicPal (MV88W8618 ARM processor)
92 92 @item Gumstix "Connex" and "Verdex" motherboards (PXA255/270).
93 93 @item Siemens SX1 smartphone (OMAP310 processor)
  94 +@item Syborg SVP base model (ARM Cortex-A8).
94 95 @end itemize
95 96  
96 97 For user emulation, x86, PowerPC, ARM, 32-bit MIPS, Sparc32/64 and ColdFire(m68k) CPUs are supported.
... ... @@ -2172,6 +2173,28 @@ Secure Digital card connected to OMAP MMC/SD host
2172 2173 Three on-chip UARTs
2173 2174 @end itemize
2174 2175  
  2176 +The "Syborg" Symbian Virtual Platform base model includes the following
  2177 +elements:
  2178 +
  2179 +@itemize @minus
  2180 +@item
  2181 +ARM Cortex-A8 CPU
  2182 +@item
  2183 +Interrupt controller
  2184 +@item
  2185 +Timer
  2186 +@item
  2187 +Real Time Clock
  2188 +@item
  2189 +Keyboard
  2190 +@item
  2191 +Framebuffer
  2192 +@item
  2193 +Touchscreen
  2194 +@item
  2195 +UARTs
  2196 +@end itemize
  2197 +
2175 2198 A Linux 2.6 test image is available on the QEMU web site. More
2176 2199 information is available in the QEMU mailing-list archive.
2177 2200  
... ...
target-arm/machine.c
... ... @@ -23,6 +23,7 @@ void register_machines(void)
23 23 qemu_register_machine(&mainstone2_machine);
24 24 qemu_register_machine(&musicpal_machine);
25 25 qemu_register_machine(&tosapda_machine);
  26 + qemu_register_machine(&syborg_machine);
26 27 }
27 28  
28 29 void cpu_save(QEMUFile *f, void *opaque)
... ...