diff options
Diffstat (limited to 'hw')
-rw-r--r-- | hw/syborg.c | 113 | ||||
-rw-r--r-- | hw/syborg.h | 18 | ||||
-rw-r--r-- | hw/syborg_fb.c | 554 | ||||
-rw-r--r-- | hw/syborg_interrupt.c | 233 | ||||
-rw-r--r-- | hw/syborg_keyboard.c | 215 | ||||
-rw-r--r-- | hw/syborg_pointer.c | 220 | ||||
-rw-r--r-- | hw/syborg_rtc.c | 134 | ||||
-rw-r--r-- | hw/syborg_serial.c | 329 | ||||
-rw-r--r-- | hw/syborg_timer.c | 224 | ||||
-rw-r--r-- | hw/syborg_virtio.c | 307 |
10 files changed, 0 insertions, 2347 deletions
diff --git a/hw/syborg.c b/hw/syborg.c deleted file mode 100644 index 248de54c4e..0000000000 --- a/hw/syborg.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Syborg (Symbian Virtual Platform) reference board - * - * Copyright (c) 2009 CodeSourcery - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "sysbus.h" -#include "boards.h" -#include "arm-misc.h" -#include "net.h" -#include "exec-memory.h" - -static struct arm_boot_info syborg_binfo; - -static void syborg_init(ram_addr_t ram_size, - const char *boot_device, - const char *kernel_filename, const char *kernel_cmdline, - const char *initrd_filename, const char *cpu_model) -{ - CPUState *env; - MemoryRegion *sysmem = get_system_memory(); - MemoryRegion *ram = g_new(MemoryRegion, 1); - qemu_irq *cpu_pic; - qemu_irq pic[64]; - DeviceState *dev; - int i; - - if (!cpu_model) - cpu_model = "cortex-a8"; - env = cpu_init(cpu_model); - if (!env) { - fprintf(stderr, "Unable to find CPU definition\n"); - exit(1); - } - - /* RAM at address zero. */ - memory_region_init_ram(ram, NULL, "syborg.ram", ram_size); - memory_region_add_subregion(sysmem, 0, ram); - - cpu_pic = arm_pic_init_cpu(env); - dev = sysbus_create_simple("syborg,interrupt", 0xC0000000, - cpu_pic[ARM_PIC_CPU_IRQ]); - for (i = 0; i < 64; i++) { - pic[i] = qdev_get_gpio_in(dev, i); - } - - sysbus_create_simple("syborg,rtc", 0xC0001000, NULL); - - dev = qdev_create(NULL, "syborg,timer"); - qdev_prop_set_uint32(dev, "frequency", 1000000); - qdev_init_nofail(dev); - sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0xC0002000); - sysbus_connect_irq(sysbus_from_qdev(dev), 0, pic[1]); - - sysbus_create_simple("syborg,keyboard", 0xC0003000, pic[2]); - sysbus_create_simple("syborg,pointer", 0xC0004000, pic[3]); - sysbus_create_simple("syborg,framebuffer", 0xC0005000, pic[4]); - sysbus_create_simple("syborg,serial", 0xC0006000, pic[5]); - sysbus_create_simple("syborg,serial", 0xC0007000, pic[6]); - sysbus_create_simple("syborg,serial", 0xC0008000, pic[7]); - sysbus_create_simple("syborg,serial", 0xC0009000, pic[8]); - - if (nd_table[0].vlan || nd_table[0].netdev) { - DeviceState *dev; - SysBusDevice *s; - - qemu_check_nic_model(&nd_table[0], "virtio"); - dev = qdev_create(NULL, "syborg,virtio-net"); - qdev_set_nic_properties(dev, &nd_table[0]); - qdev_init_nofail(dev); - s = sysbus_from_qdev(dev); - sysbus_mmio_map(s, 0, 0xc000c000); - sysbus_connect_irq(s, 0, pic[9]); - } - - syborg_binfo.ram_size = ram_size; - syborg_binfo.kernel_filename = kernel_filename; - syborg_binfo.kernel_cmdline = kernel_cmdline; - syborg_binfo.initrd_filename = initrd_filename; - syborg_binfo.board_id = 0; - arm_load_kernel(env, &syborg_binfo); -} - -static QEMUMachine syborg_machine = { - .name = "syborg", - .desc = "Syborg (Symbian Virtual Platform)", - .init = syborg_init, -}; - -static void syborg_machine_init(void) -{ - qemu_register_machine(&syborg_machine); -} - -machine_init(syborg_machine_init); diff --git a/hw/syborg.h b/hw/syborg.h deleted file mode 100644 index b82ce4a502..0000000000 --- a/hw/syborg.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _SYBORG_H -#define _SYBORG_H - -#define SYBORG_ID_PLATFORM 0xc51d1000 -#define SYBORG_ID_INT 0xc51d0000 -#define SYBORG_ID_SERIAL 0xc51d0001 -#define SYBORG_ID_KEYBOARD 0xc51d0002 -#define SYBORG_ID_TIMER 0xc51d0003 -#define SYBORG_ID_RTC 0xc51d0004 -#define SYBORG_ID_MOUSE 0xc51d0005 -#define SYBORG_ID_TOUCHSCREEN 0xc51d0006 -#define SYBORG_ID_FRAMEBUFFER 0xc51d0007 -#define SYBORG_ID_HOSTFS 0xc51d0008 -#define SYBORG_ID_SNAPSHOT 0xc51d0009 -#define SYBORG_ID_VIRTIO 0xc51d000a -#define SYBORG_ID_NAND 0xc51d000b - -#endif diff --git a/hw/syborg_fb.c b/hw/syborg_fb.c deleted file mode 100644 index b87d7e6d10..0000000000 --- a/hw/syborg_fb.c +++ /dev/null @@ -1,554 +0,0 @@ -/* - * Syborg Framebuffer - * - * Copyright (c) 2009 CodeSourcery - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "sysbus.h" -#include "console.h" -#include "syborg.h" -#include "framebuffer.h" - -//#define DEBUG_SYBORG_FB - -#ifdef DEBUG_SYBORG_FB -#define DPRINTF(fmt, ...) \ -do { printf("syborg_fb: " fmt , ## __VA_ARGS__); } while (0) -#define BADF(fmt, ...) \ -do { fprintf(stderr, "syborg_fb: error: " fmt , ## __VA_ARGS__); \ - exit(1);} while (0) -#else -#define DPRINTF(fmt, ...) do {} while(0) -#define BADF(fmt, ...) \ -do { fprintf(stderr, "syborg_fb: error: " fmt , ## __VA_ARGS__);} while (0) -#endif - -enum { - FB_ID = 0, - FB_BASE = 1, - FB_HEIGHT = 2, - FB_WIDTH = 3, - FB_ORIENTATION = 4, - FB_BLANK = 5, - FB_INT_MASK = 6, - FB_INTERRUPT_CAUSE = 7, - FB_BPP = 8, - FB_COLOR_ORDER = 9, - FB_BYTE_ORDER = 10, - FB_PIXEL_ORDER = 11, - FB_ROW_PITCH = 12, - FB_ENABLED = 13, - FB_PALETTE_START = 0x400 >> 2, - FB_PALETTE_END = FB_PALETTE_START+256-1, -}; - -#define FB_INT_VSYNC (1U << 0) -#define FB_INT_BASE_UPDATE_DONE (1U << 1) - -typedef struct { - SysBusDevice busdev; - MemoryRegion iomem; - DisplayState *ds; - /*QEMUConsole *console;*/ - uint32_t need_update : 1; - uint32_t need_int : 1; - uint32_t enabled : 1; - uint32_t int_status; - uint32_t int_enable; - qemu_irq irq; - - uint32_t base; - uint32_t pitch; - uint32_t rows; - uint32_t cols; - int blank; - int bpp; - int rgb; /* 0 = BGR, 1 = RGB */ - int endian; /* 0 = Little, 1 = Big */ - uint32_t raw_palette[256]; - uint32_t palette[256]; -} SyborgFBState; - -enum { - BPP_SRC_1, - BPP_SRC_2, - BPP_SRC_4, - BPP_SRC_8, - BPP_SRC_16, - BPP_SRC_32, - /* TODO: Implement these. */ - BPP_SRC_15 = -1, - BPP_SRC_24 = -2 -}; - -#include "pixel_ops.h" - -#define BITS 8 -#include "pl110_template.h" -#define BITS 15 -#include "pl110_template.h" -#define BITS 16 -#include "pl110_template.h" -#define BITS 24 -#include "pl110_template.h" -#define BITS 32 -#include "pl110_template.h" - -/* Update interrupts. */ -static void syborg_fb_update(SyborgFBState *s) -{ - if ((s->int_status & s->int_enable) != 0) { - DPRINTF("Raise IRQ\n"); - qemu_irq_raise(s->irq); - } else { - DPRINTF("Lower IRQ\n"); - qemu_irq_lower(s->irq); - } -} - -static int syborg_fb_enabled(const SyborgFBState *s) -{ - return s->enabled; -} - -static void syborg_fb_update_palette(SyborgFBState *s) -{ - int n, i; - uint32_t raw; - unsigned int r, g, b; - - switch (s->bpp) { - case BPP_SRC_1: n = 2; break; - case BPP_SRC_2: n = 4; break; - case BPP_SRC_4: n = 16; break; - case BPP_SRC_8: n = 256; break; - default: return; - } - - for (i = 0; i < n; i++) { - raw = s->raw_palette[i]; - r = (raw >> 16) & 0xff; - g = (raw >> 8) & 0xff; - b = raw & 0xff; - switch (ds_get_bits_per_pixel(s->ds)) { - case 8: - s->palette[i] = rgb_to_pixel8(r, g, b); - break; - case 15: - s->palette[i] = rgb_to_pixel15(r, g, b); - break; - case 16: - s->palette[i] = rgb_to_pixel16(r, g, b); - break; - case 24: - case 32: - s->palette[i] = rgb_to_pixel32(r, g, b); - break; - default: - abort(); - } - } - -} - -static void syborg_fb_update_display(void *opaque) -{ - SyborgFBState *s = (SyborgFBState *)opaque; - drawfn* fntable; - drawfn fn; - int dest_width; - int src_width; - int bpp_offset; - int first; - int last; - - if (!syborg_fb_enabled(s)) - return; - - switch (ds_get_bits_per_pixel(s->ds)) { - case 0: - return; - case 8: - fntable = pl110_draw_fn_8; - dest_width = 1; - break; - case 15: - fntable = pl110_draw_fn_15; - dest_width = 2; - break; - case 16: - fntable = pl110_draw_fn_16; - dest_width = 2; - break; - case 24: - fntable = pl110_draw_fn_24; - dest_width = 3; - break; - case 32: - fntable = pl110_draw_fn_32; - dest_width = 4; - break; - default: - fprintf(stderr, "syborg_fb: Bad color depth\n"); - exit(1); - } - - if (s->need_int) { - s->int_status |= FB_INT_BASE_UPDATE_DONE; - syborg_fb_update(s); - s->need_int = 0; - } - - if (s->rgb) { - bpp_offset = 24; - } else { - bpp_offset = 0; - } - if (s->endian) { - bpp_offset += 8; - } - /* Our bpp constants mostly match the PL110/PL111 but - * not for the 16 bit case - */ - switch (s->bpp) { - case BPP_SRC_16: - bpp_offset += 6; - break; - default: - bpp_offset += s->bpp; - } - fn = fntable[bpp_offset]; - - if (s->pitch) { - src_width = s->pitch; - } else { - src_width = s->cols; - switch (s->bpp) { - case BPP_SRC_1: - src_width >>= 3; - break; - case BPP_SRC_2: - src_width >>= 2; - break; - case BPP_SRC_4: - src_width >>= 1; - break; - case BPP_SRC_8: - break; - case BPP_SRC_15: - case BPP_SRC_16: - src_width <<= 1; - break; - case BPP_SRC_24: - src_width *= 3; - break; - case BPP_SRC_32: - src_width <<= 2; - break; - } - } - dest_width *= s->cols; - first = 0; - /* TODO: Implement blanking. */ - if (!s->blank) { - if (s->need_update && s->bpp <= BPP_SRC_8) { - syborg_fb_update_palette(s); - } - framebuffer_update_display(s->ds, - s->base, s->cols, s->rows, - src_width, dest_width, 0, - s->need_update, - fn, s->palette, - &first, &last); - if (first >= 0) { - dpy_update(s->ds, 0, first, s->cols, last - first + 1); - } - - s->int_status |= FB_INT_VSYNC; - syborg_fb_update(s); - } - - s->need_update = 0; -} - -static void syborg_fb_invalidate_display(void * opaque) -{ - SyborgFBState *s = (SyborgFBState *)opaque; - s->need_update = 1; -} - -static uint64_t syborg_fb_read(void *opaque, target_phys_addr_t offset, - unsigned size) -{ - SyborgFBState *s = opaque; - - DPRINTF("read reg %d\n", (int)offset); - offset &= 0xfff; - switch (offset >> 2) { - case FB_ID: - return SYBORG_ID_FRAMEBUFFER; - - case FB_BASE: - return s->base; - - case FB_HEIGHT: - return s->rows; - - case FB_WIDTH: - return s->cols; - - case FB_ORIENTATION: - return 0; - - case FB_BLANK: - return s->blank; - - case FB_INT_MASK: - return s->int_enable; - - case FB_INTERRUPT_CAUSE: - return s->int_status; - - case FB_BPP: - switch (s->bpp) { - case BPP_SRC_1: return 1; - case BPP_SRC_2: return 2; - case BPP_SRC_4: return 4; - case BPP_SRC_8: return 8; - case BPP_SRC_15: return 15; - case BPP_SRC_16: return 16; - case BPP_SRC_24: return 24; - case BPP_SRC_32: return 32; - default: return 0; - } - - case FB_COLOR_ORDER: - return s->rgb; - - case FB_BYTE_ORDER: - return s->endian; - - case FB_PIXEL_ORDER: - return 0; - - case FB_ROW_PITCH: - return s->pitch; - - case FB_ENABLED: - return s->enabled; - - default: - if ((offset >> 2) >= FB_PALETTE_START - && (offset >> 2) <= FB_PALETTE_END) { - return s->raw_palette[(offset >> 2) - FB_PALETTE_START]; - } else { - cpu_abort (cpu_single_env, "syborg_fb_read: Bad offset %x\n", - (int)offset); - } - return 0; - } -} - -static void syborg_fb_write(void *opaque, target_phys_addr_t offset, - uint64_t val, unsigned size) -{ - SyborgFBState *s = opaque; - - DPRINTF("write reg %d = %d\n", (int)offset, val); - s->need_update = 1; - offset &= 0xfff; - switch (offset >> 2) { - case FB_BASE: - s->base = val; - s->need_int = 1; - s->need_update = 1; - syborg_fb_update(s); - break; - - case FB_HEIGHT: - s->rows = val; - break; - - case FB_WIDTH: - s->cols = val; - break; - - case FB_ORIENTATION: - /* TODO: Implement rotation. */ - break; - - case FB_BLANK: - s->blank = val & 1; - break; - - case FB_INT_MASK: - s->int_enable = val; - syborg_fb_update(s); - break; - - case FB_INTERRUPT_CAUSE: - s->int_status &= ~val; - syborg_fb_update(s); - break; - - case FB_BPP: - switch (val) { - case 1: val = BPP_SRC_1; break; - case 2: val = BPP_SRC_2; break; - case 4: val = BPP_SRC_4; break; - case 8: val = BPP_SRC_8; break; - /* case 15: val = BPP_SRC_15; break; */ - case 16: val = BPP_SRC_16; break; - /* case 24: val = BPP_SRC_24; break; */ - case 32: val = BPP_SRC_32; break; - default: val = s->bpp; break; - } - s->bpp = val; - break; - - case FB_COLOR_ORDER: - s->rgb = (val != 0); - break; - - case FB_BYTE_ORDER: - s->endian = (val != 0); - break; - - case FB_PIXEL_ORDER: - /* TODO: Implement this. */ - break; - - case FB_ROW_PITCH: - s->pitch = val; - break; - - case FB_ENABLED: - s->enabled = val; - break; - - default: - if ((offset >> 2) >= FB_PALETTE_START - && (offset >> 2) <= FB_PALETTE_END) { - s->raw_palette[(offset >> 2) - FB_PALETTE_START] = val; - } else { - cpu_abort (cpu_single_env, "syborg_fb_write: Bad offset %x\n", - (int)offset); - } - break; - } -} - -static const MemoryRegionOps syborg_fb_ops = { - .read = syborg_fb_read, - .write = syborg_fb_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void syborg_fb_save(QEMUFile *f, void *opaque) -{ - SyborgFBState *s = opaque; - int i; - - qemu_put_be32(f, s->need_int); - qemu_put_be32(f, s->int_status); - qemu_put_be32(f, s->int_enable); - qemu_put_be32(f, s->enabled); - qemu_put_be32(f, s->base); - qemu_put_be32(f, s->pitch); - qemu_put_be32(f, s->rows); - qemu_put_be32(f, s->cols); - qemu_put_be32(f, s->bpp); - qemu_put_be32(f, s->rgb); - for (i = 0; i < 256; i++) { - qemu_put_be32(f, s->raw_palette[i]); - } -} - -static int syborg_fb_load(QEMUFile *f, void *opaque, int version_id) -{ - SyborgFBState *s = opaque; - int i; - - if (version_id != 1) - return -EINVAL; - - s->need_int = qemu_get_be32(f); - s->int_status = qemu_get_be32(f); - s->int_enable = qemu_get_be32(f); - s->enabled = qemu_get_be32(f); - s->base = qemu_get_be32(f); - s->pitch = qemu_get_be32(f); - s->rows = qemu_get_be32(f); - s->cols = qemu_get_be32(f); - s->bpp = qemu_get_be32(f); - s->rgb = qemu_get_be32(f); - for (i = 0; i < 256; i++) { - s->raw_palette[i] = qemu_get_be32(f); - } - s->need_update = 1; - - return 0; -} - -static int syborg_fb_init(SysBusDevice *dev) -{ - SyborgFBState *s = FROM_SYSBUS(SyborgFBState, dev); - - sysbus_init_irq(dev, &s->irq); - memory_region_init_io(&s->iomem, &syborg_fb_ops, s, - "framebuffer", 0x1000); - sysbus_init_mmio(dev, &s->iomem); - - s->ds = graphic_console_init(syborg_fb_update_display, - syborg_fb_invalidate_display, - NULL, NULL, s); - - if (s->cols != 0 && s->rows != 0) { - qemu_console_resize(s->ds, s->cols, s->rows); - } - - if (!s->cols) - s->cols = ds_get_width(s->ds); - if (!s->rows) - s->rows = ds_get_height(s->ds); - - register_savevm(&dev->qdev, "syborg_framebuffer", -1, 1, - syborg_fb_save, syborg_fb_load, s); - return 0; -} - -static SysBusDeviceInfo syborg_fb_info = { - .init = syborg_fb_init, - .qdev.name = "syborg,framebuffer", - .qdev.size = sizeof(SyborgFBState), - .qdev.props = (Property[]) { - DEFINE_PROP_UINT32("width", SyborgFBState, cols, 0), - DEFINE_PROP_UINT32("height", SyborgFBState, rows, 0), - DEFINE_PROP_END_OF_LIST(), - } -}; - -static void syborg_fb_register_devices(void) -{ - sysbus_register_withprop(&syborg_fb_info); -} - -device_init(syborg_fb_register_devices) diff --git a/hw/syborg_interrupt.c b/hw/syborg_interrupt.c deleted file mode 100644 index 93e81c8660..0000000000 --- a/hw/syborg_interrupt.c +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Syborg interrupt controller. - * - * Copyright (c) 2008 CodeSourcery - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "sysbus.h" -#include "syborg.h" - -//#define DEBUG_SYBORG_INT - -#ifdef DEBUG_SYBORG_INT -#define DPRINTF(fmt, ...) \ -do { printf("syborg_int: " fmt , ## __VA_ARGS__); } while (0) -#define BADF(fmt, ...) \ -do { fprintf(stderr, "syborg_int: error: " fmt , ## __VA_ARGS__); \ - exit(1);} while (0) -#else -#define DPRINTF(fmt, ...) do {} while(0) -#define BADF(fmt, ...) \ -do { fprintf(stderr, "syborg_int: error: " fmt , ## __VA_ARGS__);} while (0) -#endif -enum { - INT_ID = 0, - INT_STATUS = 1, /* number of pending interrupts */ - INT_CURRENT = 2, /* next interrupt to be serviced */ - INT_DISABLE_ALL = 3, - INT_DISABLE = 4, - INT_ENABLE = 5, - INT_TOTAL = 6 -}; - -typedef struct { - unsigned level:1; - unsigned enabled:1; -} syborg_int_flags; - -typedef struct { - SysBusDevice busdev; - MemoryRegion iomem; - int pending_count; - uint32_t num_irqs; - syborg_int_flags *flags; - qemu_irq parent_irq; -} SyborgIntState; - -static void syborg_int_update(SyborgIntState *s) -{ - DPRINTF("pending %d\n", s->pending_count); - qemu_set_irq(s->parent_irq, s->pending_count > 0); -} - -static void syborg_int_set_irq(void *opaque, int irq, int level) -{ - SyborgIntState *s = (SyborgIntState *)opaque; - - if (s->flags[irq].level == level) - return; - - s->flags[irq].level = level; - if (s->flags[irq].enabled) { - if (level) - s->pending_count++; - else - s->pending_count--; - syborg_int_update(s); - } -} - -static uint64_t syborg_int_read(void *opaque, target_phys_addr_t offset, - unsigned size) -{ - SyborgIntState *s = (SyborgIntState *)opaque; - int i; - - offset &= 0xfff; - switch (offset >> 2) { - case INT_ID: - return SYBORG_ID_INT; - case INT_STATUS: - DPRINTF("read status=%d\n", s->pending_count); - return s->pending_count; - - case INT_CURRENT: - for (i = 0; i < s->num_irqs; i++) { - if (s->flags[i].level & s->flags[i].enabled) { - DPRINTF("read current=%d\n", i); - return i; - } - } - DPRINTF("read current=none\n"); - return 0xffffffffu; - - default: - cpu_abort(cpu_single_env, "syborg_int_read: Bad offset %x\n", - (int)offset); - return 0; - } -} - -static void syborg_int_write(void *opaque, target_phys_addr_t offset, - uint64_t value, unsigned size) -{ - SyborgIntState *s = (SyborgIntState *)opaque; - int i; - offset &= 0xfff; - - DPRINTF("syborg_int_write offset=%d val=%d\n", (int)offset, (int)value); - switch (offset >> 2) { - case INT_DISABLE_ALL: - s->pending_count = 0; - for (i = 0; i < s->num_irqs; i++) - s->flags[i].enabled = 0; - break; - - case INT_DISABLE: - if (value >= s->num_irqs) - break; - if (s->flags[value].enabled) { - if (s->flags[value].enabled) - s->pending_count--; - s->flags[value].enabled = 0; - } - break; - - case INT_ENABLE: - if (value >= s->num_irqs) - break; - if (!(s->flags[value].enabled)) { - if(s->flags[value].level) - s->pending_count++; - s->flags[value].enabled = 1; - } - break; - - default: - cpu_abort(cpu_single_env, "syborg_int_write: Bad offset %x\n", - (int)offset); - return; - } - syborg_int_update(s); -} - -static const MemoryRegionOps syborg_int_ops = { - .read = syborg_int_read, - .write = syborg_int_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void syborg_int_save(QEMUFile *f, void *opaque) -{ - SyborgIntState *s = (SyborgIntState *)opaque; - int i; - - qemu_put_be32(f, s->num_irqs); - qemu_put_be32(f, s->pending_count); - for (i = 0; i < s->num_irqs; i++) { - qemu_put_be32(f, s->flags[i].enabled - | ((unsigned)s->flags[i].level << 1)); - } -} - -static int syborg_int_load(QEMUFile *f, void *opaque, int version_id) -{ - SyborgIntState *s = (SyborgIntState *)opaque; - uint32_t val; - int i; - - if (version_id != 1) - return -EINVAL; - - val = qemu_get_be32(f); - if (val != s->num_irqs) - return -EINVAL; - s->pending_count = qemu_get_be32(f); - for (i = 0; i < s->num_irqs; i++) { - val = qemu_get_be32(f); - s->flags[i].enabled = val & 1; - s->flags[i].level = (val >> 1) & 1; - } - return 0; -} - -static int syborg_int_init(SysBusDevice *dev) -{ - SyborgIntState *s = FROM_SYSBUS(SyborgIntState, dev); - - sysbus_init_irq(dev, &s->parent_irq); - qdev_init_gpio_in(&dev->qdev, syborg_int_set_irq, s->num_irqs); - memory_region_init_io(&s->iomem, &syborg_int_ops, s, - "interrupt", 0x1000); - sysbus_init_mmio(dev, &s->iomem); - s->flags = g_malloc0(s->num_irqs * sizeof(syborg_int_flags)); - - register_savevm(&dev->qdev, "syborg_int", -1, 1, syborg_int_save, - syborg_int_load, s); - return 0; -} - -static SysBusDeviceInfo syborg_int_info = { - .init = syborg_int_init, - .qdev.name = "syborg,interrupt", - .qdev.size = sizeof(SyborgIntState), - .qdev.props = (Property[]) { - DEFINE_PROP_UINT32("num-interrupts", SyborgIntState, num_irqs, 64), - DEFINE_PROP_END_OF_LIST(), - } -}; - -static void syborg_interrupt_register_devices(void) -{ - sysbus_register_withprop(&syborg_int_info); -} - -device_init(syborg_interrupt_register_devices) diff --git a/hw/syborg_keyboard.c b/hw/syborg_keyboard.c deleted file mode 100644 index 942a7dc800..0000000000 --- a/hw/syborg_keyboard.c +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Syborg keyboard controller. - * - * Copyright (c) 2008 CodeSourcery - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "sysbus.h" -#include "console.h" -#include "syborg.h" - -//#define DEBUG_SYBORG_KEYBOARD - -#ifdef DEBUG_SYBORG_KEYBOARD -#define DPRINTF(fmt, ...) \ -do { printf("syborg_keyboard: " fmt , ##args); } while (0) -#define BADF(fmt, ...) \ -do { fprintf(stderr, "syborg_keyboard: error: " fmt , ## __VA_ARGS__); \ - exit(1);} while (0) -#else -#define DPRINTF(fmt, ...) do {} while(0) -#define BADF(fmt, ...) \ -do { fprintf(stderr, "syborg_keyboard: error: " fmt , ## __VA_ARGS__); \ -} while (0) -#endif - -enum { - KBD_ID = 0, - KBD_DATA = 1, - KBD_FIFO_COUNT = 2, - KBD_INT_ENABLE = 3, - KBD_FIFO_SIZE = 4 -}; - -typedef struct { - SysBusDevice busdev; - MemoryRegion iomem; - uint32_t int_enabled; - int extension_bit; - uint32_t fifo_size; - uint32_t *key_fifo; - uint32_t read_pos, read_count; - qemu_irq irq; -} SyborgKeyboardState; - -static void syborg_keyboard_update(SyborgKeyboardState *s) -{ - int level = s->read_count && s->int_enabled; - DPRINTF("Update IRQ %d\n", level); - qemu_set_irq(s->irq, level); -} - -static uint64_t syborg_keyboard_read(void *opaque, target_phys_addr_t offset, - unsigned size) -{ - SyborgKeyboardState *s = (SyborgKeyboardState *)opaque; - int c; - - DPRINTF("reg read %d\n", (int)offset); - offset &= 0xfff; - switch (offset >> 2) { - case KBD_ID: - return SYBORG_ID_KEYBOARD; - case KBD_FIFO_COUNT: - return s->read_count; - case KBD_DATA: - if (s->read_count == 0) { - c = -1; - DPRINTF("FIFO underflow\n"); - } else { - c = s->key_fifo[s->read_pos]; - DPRINTF("FIFO read 0x%x\n", c); - s->read_count--; - s->read_pos++; - if (s->read_pos == s->fifo_size) - s->read_pos = 0; - } - syborg_keyboard_update(s); - return c; - case KBD_INT_ENABLE: - return s->int_enabled; - case KBD_FIFO_SIZE: - return s->fifo_size; - default: - cpu_abort(cpu_single_env, "syborg_keyboard_read: Bad offset %x\n", - (int)offset); - return 0; - } -} - -static void syborg_keyboard_write(void *opaque, target_phys_addr_t offset, - uint64_t value, unsigned size) -{ - SyborgKeyboardState *s = (SyborgKeyboardState *)opaque; - - DPRINTF("reg write %d\n", (int)offset); - offset &= 0xfff; - switch (offset >> 2) { - case KBD_INT_ENABLE: - s->int_enabled = value; - syborg_keyboard_update(s); - break; - default: - cpu_abort(cpu_single_env, "syborg_keyboard_write: Bad offset %x\n", - (int)offset); - } -} - -static const MemoryRegionOps syborg_keyboard_ops = { - .read = syborg_keyboard_read, - .write = syborg_keyboard_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void syborg_keyboard_event(void *opaque, int keycode) -{ - SyborgKeyboardState *s = (SyborgKeyboardState *)opaque; - int slot; - uint32_t val; - - /* Strip off 0xe0 prefixes and reconstruct the full scancode. */ - if (keycode == 0xe0 && !s->extension_bit) { - DPRINTF("Extension bit\n"); - s->extension_bit = 0x80; - return; - } - val = (keycode & 0x7f) | s->extension_bit; - if (keycode & 0x80) - val |= 0x80000000u; - s->extension_bit = 0; - - DPRINTF("FIFO push 0x%x\n", val); - slot = s->read_pos + s->read_count; - if (slot >= s->fifo_size) - slot -= s->fifo_size; - - if (s->read_count < s->fifo_size) { - s->read_count++; - s->key_fifo[slot] = val; - } else { - fprintf(stderr, "syborg_keyboard error! FIFO overflow\n"); - } - - syborg_keyboard_update(s); -} - -static const VMStateDescription vmstate_syborg_keyboard = { - .name = "syborg_keyboard", - .version_id = 1, - .minimum_version_id = 1, - .minimum_version_id_old = 1, - .fields = (VMStateField[]) { - VMSTATE_UINT32_EQUAL(fifo_size, SyborgKeyboardState), - VMSTATE_UINT32(int_enabled, SyborgKeyboardState), - VMSTATE_UINT32(read_pos, SyborgKeyboardState), - VMSTATE_UINT32(read_count, SyborgKeyboardState), - VMSTATE_VARRAY_UINT32(key_fifo, SyborgKeyboardState, fifo_size, 1, - vmstate_info_uint32, uint32), - VMSTATE_END_OF_LIST() - } -}; - -static int syborg_keyboard_init(SysBusDevice *dev) -{ - SyborgKeyboardState *s = FROM_SYSBUS(SyborgKeyboardState, dev); - - sysbus_init_irq(dev, &s->irq); - memory_region_init_io(&s->iomem, &syborg_keyboard_ops, s, - "keyboard", 0x1000); - sysbus_init_mmio(dev, &s->iomem); - if (s->fifo_size <= 0) { - fprintf(stderr, "syborg_keyboard: fifo too small\n"); - s->fifo_size = 16; - } - s->key_fifo = g_malloc0(s->fifo_size * sizeof(s->key_fifo[0])); - - qemu_add_kbd_event_handler(syborg_keyboard_event, s); - - vmstate_register(&dev->qdev, -1, &vmstate_syborg_keyboard, s); - return 0; -} - -static SysBusDeviceInfo syborg_keyboard_info = { - .init = syborg_keyboard_init, - .qdev.name = "syborg,keyboard", - .qdev.size = sizeof(SyborgKeyboardState), - .qdev.props = (Property[]) { - DEFINE_PROP_UINT32("fifo-size", SyborgKeyboardState, fifo_size, 16), - DEFINE_PROP_END_OF_LIST(), - } -}; - -static void syborg_keyboard_register_devices(void) -{ - sysbus_register_withprop(&syborg_keyboard_info); -} - -device_init(syborg_keyboard_register_devices) diff --git a/hw/syborg_pointer.c b/hw/syborg_pointer.c deleted file mode 100644 index bb75fa42c8..0000000000 --- a/hw/syborg_pointer.c +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Syborg pointing device (mouse/touchscreen) - * - * Copyright (c) 2008 CodeSourcery - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "sysbus.h" -#include "console.h" -#include "syborg.h" - -enum { - POINTER_ID = 0, - POINTER_LATCH = 1, - POINTER_FIFO_COUNT = 2, - POINTER_X = 3, - POINTER_Y = 4, - POINTER_Z = 5, - POINTER_BUTTONS = 6, - POINTER_INT_ENABLE = 7, - POINTER_FIFO_SIZE = 8 -}; - -typedef struct { - int x, y, z, pointer_buttons; -} event_data; - -typedef struct { - SysBusDevice busdev; - MemoryRegion iomem; - int int_enabled; - uint32_t fifo_size; - event_data *event_fifo; - int read_pos, read_count; - qemu_irq irq; - uint32_t absolute; -} SyborgPointerState; - -static void syborg_pointer_update(SyborgPointerState *s) -{ - qemu_set_irq(s->irq, s->read_count && s->int_enabled); -} - -static uint64_t syborg_pointer_read(void *opaque, target_phys_addr_t offset, - unsigned size) -{ - SyborgPointerState *s = (SyborgPointerState *)opaque; - - offset &= 0xfff; - switch (offset >> 2) { - case POINTER_ID: - return s->absolute ? SYBORG_ID_TOUCHSCREEN : SYBORG_ID_MOUSE; - case POINTER_FIFO_COUNT: - return s->read_count; - case POINTER_X: - return s->event_fifo[s->read_pos].x; - case POINTER_Y: - return s->event_fifo[s->read_pos].y; - case POINTER_Z: - return s->event_fifo[s->read_pos].z; - case POINTER_BUTTONS: - return s->event_fifo[s->read_pos].pointer_buttons; - case POINTER_INT_ENABLE: - return s->int_enabled; - case POINTER_FIFO_SIZE: - return s->fifo_size; - default: - cpu_abort(cpu_single_env, "syborg_pointer_read: Bad offset %x\n", - (int)offset); - return 0; - } -} - -static void syborg_pointer_write(void *opaque, target_phys_addr_t offset, - uint64_t value, unsigned size) -{ - SyborgPointerState *s = (SyborgPointerState *)opaque; - - offset &= 0xfff; - switch (offset >> 2) { - case POINTER_LATCH: - if (s->read_count > 0) { - s->read_count--; - if (++s->read_pos == s->fifo_size) - s->read_pos = 0; - } - break; - case POINTER_INT_ENABLE: - s->int_enabled = value; - break; - default: - cpu_abort(cpu_single_env, "syborg_pointer_write: Bad offset %x\n", - (int)offset); - } - syborg_pointer_update(s); -} - -static const MemoryRegionOps syborg_pointer_ops = { - .read = syborg_pointer_read, - .write = syborg_pointer_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void syborg_pointer_event(void *opaque, int dx, int dy, int dz, - int buttons_state) -{ - SyborgPointerState *s = (SyborgPointerState *)opaque; - int slot = s->read_pos + s->read_count; - - /* This first FIFO entry is used to store current register state. */ - if (s->read_count < s->fifo_size - 1) { - s->read_count++; - slot++; - } - - if (slot >= s->fifo_size) - slot -= s->fifo_size; - - if (s->read_count == s->fifo_size && !s->absolute) { - /* Merge existing entries. */ - s->event_fifo[slot].x += dx; - s->event_fifo[slot].y += dy; - s->event_fifo[slot].z += dz; - } else { - s->event_fifo[slot].x = dx; - s->event_fifo[slot].y = dy; - s->event_fifo[slot].z = dz; - } - s->event_fifo[slot].pointer_buttons = buttons_state; - - syborg_pointer_update(s); -} - -static const VMStateDescription vmstate_event_data = { - .name = "dbma_channel", - .version_id = 0, - .minimum_version_id = 0, - .minimum_version_id_old = 0, - .fields = (VMStateField[]) { - VMSTATE_INT32(x, event_data), - VMSTATE_INT32(y, event_data), - VMSTATE_INT32(z, event_data), - VMSTATE_INT32(pointer_buttons, event_data), - VMSTATE_END_OF_LIST() - } -}; - -static const VMStateDescription vmstate_syborg_pointer = { - .name = "syborg_pointer", - .version_id = 1, - .minimum_version_id = 1, - .minimum_version_id_old = 1, - .fields = (VMStateField[]) { - VMSTATE_UINT32_EQUAL(fifo_size, SyborgPointerState), - VMSTATE_UINT32_EQUAL(absolute, SyborgPointerState), - VMSTATE_INT32(int_enabled, SyborgPointerState), - VMSTATE_INT32(read_pos, SyborgPointerState), - VMSTATE_INT32(read_count, SyborgPointerState), - VMSTATE_STRUCT_VARRAY_UINT32(event_fifo, SyborgPointerState, fifo_size, - 1, vmstate_event_data, event_data), - VMSTATE_END_OF_LIST() - } -}; - -static int syborg_pointer_init(SysBusDevice *dev) -{ - SyborgPointerState *s = FROM_SYSBUS(SyborgPointerState, dev); - - sysbus_init_irq(dev, &s->irq); - memory_region_init_io(&s->iomem, &syborg_pointer_ops, s, - "pointer", 0x1000); - sysbus_init_mmio(dev, &s->iomem); - - if (s->fifo_size <= 0) { - fprintf(stderr, "syborg_pointer: fifo too small\n"); - s->fifo_size = 16; - } - s->event_fifo = g_malloc0(s->fifo_size * sizeof(s->event_fifo[0])); - - qemu_add_mouse_event_handler(syborg_pointer_event, s, s->absolute, - "Syborg Pointer"); - - vmstate_register(&dev->qdev, -1, &vmstate_syborg_pointer, s); - return 0; -} - -static SysBusDeviceInfo syborg_pointer_info = { - .init = syborg_pointer_init, - .qdev.name = "syborg,pointer", - .qdev.size = sizeof(SyborgPointerState), - .qdev.props = (Property[]) { - DEFINE_PROP_UINT32("fifo-size", SyborgPointerState, fifo_size, 16), - DEFINE_PROP_UINT32("absolute", SyborgPointerState, absolute, 1), - DEFINE_PROP_END_OF_LIST(), - } -}; - -static void syborg_pointer_register_devices(void) -{ - sysbus_register_withprop(&syborg_pointer_info); -} - -device_init(syborg_pointer_register_devices) diff --git a/hw/syborg_rtc.c b/hw/syborg_rtc.c deleted file mode 100644 index b5f34798b6..0000000000 --- a/hw/syborg_rtc.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Syborg RTC - * - * Copyright (c) 2008 CodeSourcery - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "sysbus.h" -#include "qemu-timer.h" -#include "syborg.h" - -enum { - RTC_ID = 0, - RTC_LATCH = 1, - RTC_DATA_LOW = 2, - RTC_DATA_HIGH = 3 -}; - -typedef struct { - SysBusDevice busdev; - MemoryRegion iomem; - int64_t offset; - int64_t data; - qemu_irq irq; -} SyborgRTCState; - -static uint64_t syborg_rtc_read(void *opaque, target_phys_addr_t offset, - unsigned size) -{ - SyborgRTCState *s = (SyborgRTCState *)opaque; - offset &= 0xfff; - switch (offset >> 2) { - case RTC_ID: - return SYBORG_ID_RTC; - case RTC_DATA_LOW: - return (uint32_t)s->data; - case RTC_DATA_HIGH: - return (uint32_t)(s->data >> 32); - default: - cpu_abort(cpu_single_env, "syborg_rtc_read: Bad offset %x\n", - (int)offset); - return 0; - } -} - -static void syborg_rtc_write(void *opaque, target_phys_addr_t offset, - uint64_t value, unsigned size) -{ - SyborgRTCState *s = (SyborgRTCState *)opaque; - uint64_t now; - - offset &= 0xfff; - switch (offset >> 2) { - case RTC_LATCH: - now = qemu_get_clock_ns(vm_clock); - if (value >= 4) { - s->offset = s->data - now; - } else { - s->data = now + s->offset; - while (value) { - s->data /= 1000; - value--; - } - } - break; - case RTC_DATA_LOW: - s->data = (s->data & ~(uint64_t)0xffffffffu) | value; - break; - case RTC_DATA_HIGH: - s->data = (s->data & 0xffffffffu) | ((uint64_t)value << 32); - break; - default: - cpu_abort(cpu_single_env, "syborg_rtc_write: Bad offset %x\n", - (int)offset); - break; - } -} - -static const MemoryRegionOps syborg_rtc_ops = { - .read = syborg_rtc_read, - .write = syborg_rtc_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static const VMStateDescription vmstate_syborg_rtc = { - .name = "syborg_keyboard", - .version_id = 1, - .minimum_version_id = 1, - .minimum_version_id_old = 1, - .fields = (VMStateField[]) { - VMSTATE_INT64(offset, SyborgRTCState), - VMSTATE_INT64(data, SyborgRTCState), - VMSTATE_END_OF_LIST() - } -}; - -static int syborg_rtc_init(SysBusDevice *dev) -{ - SyborgRTCState *s = FROM_SYSBUS(SyborgRTCState, dev); - struct tm tm; - - memory_region_init_io(&s->iomem, &syborg_rtc_ops, s, "rtc", 0x1000); - sysbus_init_mmio(dev, &s->iomem); - - qemu_get_timedate(&tm, 0); - s->offset = (uint64_t)mktime(&tm) * 1000000000; - - vmstate_register(&dev->qdev, -1, &vmstate_syborg_rtc, s); - return 0; -} - -static void syborg_rtc_register_devices(void) -{ - sysbus_register_dev("syborg,rtc", sizeof(SyborgRTCState), syborg_rtc_init); -} - -device_init(syborg_rtc_register_devices) diff --git a/hw/syborg_serial.c b/hw/syborg_serial.c deleted file mode 100644 index 6f339fa7a6..0000000000 --- a/hw/syborg_serial.c +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Syborg serial port - * - * Copyright (c) 2008 CodeSourcery - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "sysbus.h" -#include "qemu-char.h" -#include "syborg.h" - -//#define DEBUG_SYBORG_SERIAL - -#ifdef DEBUG_SYBORG_SERIAL -#define DPRINTF(fmt, ...) \ -do { printf("syborg_serial: " fmt , ##args); } while (0) -#define BADF(fmt, ...) \ -do { fprintf(stderr, "syborg_serial: error: " fmt , ## __VA_ARGS__); \ - exit(1);} while (0) -#else -#define DPRINTF(fmt, ...) do {} while(0) -#define BADF(fmt, ...) \ -do { fprintf(stderr, "syborg_serial: error: " fmt , ## __VA_ARGS__);} while (0) -#endif - -enum { - SERIAL_ID = 0, - SERIAL_DATA = 1, - SERIAL_FIFO_COUNT = 2, - SERIAL_INT_ENABLE = 3, - SERIAL_DMA_TX_ADDR = 4, - SERIAL_DMA_TX_COUNT = 5, /* triggers dma */ - SERIAL_DMA_RX_ADDR = 6, - SERIAL_DMA_RX_COUNT = 7, /* triggers dma */ - SERIAL_FIFO_SIZE = 8 -}; - -#define SERIAL_INT_FIFO (1u << 0) -#define SERIAL_INT_DMA_TX (1u << 1) -#define SERIAL_INT_DMA_RX (1u << 2) - -typedef struct { - SysBusDevice busdev; - MemoryRegion iomem; - uint32_t int_enable; - uint32_t fifo_size; - uint32_t *read_fifo; - int read_pos; - int read_count; - CharDriverState *chr; - qemu_irq irq; - uint32_t dma_tx_ptr; - uint32_t dma_rx_ptr; - uint32_t dma_rx_size; -} SyborgSerialState; - -static void syborg_serial_update(SyborgSerialState *s) -{ - int level; - level = 0; - if ((s->int_enable & SERIAL_INT_FIFO) && s->read_count) - level = 1; - if (s->int_enable & SERIAL_INT_DMA_TX) - level = 1; - if ((s->int_enable & SERIAL_INT_DMA_RX) && s->dma_rx_size == 0) - level = 1; - - qemu_set_irq(s->irq, level); -} - -static uint32_t fifo_pop(SyborgSerialState *s) -{ - const uint32_t c = s->read_fifo[s->read_pos]; - s->read_count--; - s->read_pos++; - if (s->read_pos == s->fifo_size) - s->read_pos = 0; - - DPRINTF("FIFO pop %x (%d)\n", c, s->read_count); - return c; -} - -static void fifo_push(SyborgSerialState *s, uint32_t new_value) -{ - int slot; - - DPRINTF("FIFO push %x (%d)\n", new_value, s->read_count); - slot = s->read_pos + s->read_count; - if (slot >= s->fifo_size) - slot -= s->fifo_size; - s->read_fifo[slot] = new_value; - s->read_count++; -} - -static void do_dma_tx(SyborgSerialState *s, uint32_t count) -{ - unsigned char ch; - - if (count == 0) - return; - - if (s->chr != NULL) { - /* optimize later. Now, 1 byte per iteration */ - while (count--) { - cpu_physical_memory_read(s->dma_tx_ptr, &ch, 1); - qemu_chr_fe_write(s->chr, &ch, 1); - s->dma_tx_ptr++; - } - } else { - s->dma_tx_ptr += count; - } - /* QEMU char backends do not have a nonblocking mode, so we transmit all - the data immediately and the interrupt status will be unchanged. */ -} - -/* Initiate RX DMA, and transfer data from the FIFO. */ -static void dma_rx_start(SyborgSerialState *s, uint32_t len) -{ - uint32_t dest; - unsigned char ch; - - dest = s->dma_rx_ptr; - if (s->read_count < len) { - s->dma_rx_size = len - s->read_count; - len = s->read_count; - } else { - s->dma_rx_size = 0; - } - - while (len--) { - ch = fifo_pop(s); - cpu_physical_memory_write(dest, &ch, 1); - dest++; - } - s->dma_rx_ptr = dest; - syborg_serial_update(s); -} - -static uint64_t syborg_serial_read(void *opaque, target_phys_addr_t offset, - unsigned size) -{ - SyborgSerialState *s = (SyborgSerialState *)opaque; - uint32_t c; - - offset &= 0xfff; - DPRINTF("read 0x%x\n", (int)offset); - switch(offset >> 2) { - case SERIAL_ID: - return SYBORG_ID_SERIAL; - case SERIAL_DATA: - if (s->read_count > 0) - c = fifo_pop(s); - else - c = -1; - syborg_serial_update(s); - return c; - case SERIAL_FIFO_COUNT: - return s->read_count; - case SERIAL_INT_ENABLE: - return s->int_enable; - case SERIAL_DMA_TX_ADDR: - return s->dma_tx_ptr; - case SERIAL_DMA_TX_COUNT: - return 0; - case SERIAL_DMA_RX_ADDR: - return s->dma_rx_ptr; - case SERIAL_DMA_RX_COUNT: - return s->dma_rx_size; - case SERIAL_FIFO_SIZE: - return s->fifo_size; - - default: - cpu_abort(cpu_single_env, "syborg_serial_read: Bad offset %x\n", - (int)offset); - return 0; - } -} - -static void syborg_serial_write(void *opaque, target_phys_addr_t offset, - uint64_t value, unsigned size) -{ - SyborgSerialState *s = (SyborgSerialState *)opaque; - unsigned char ch; - - offset &= 0xfff; - DPRINTF("Write 0x%x=0x%x\n", (int)offset, value); - switch (offset >> 2) { - case SERIAL_DATA: - ch = value; - if (s->chr) - qemu_chr_fe_write(s->chr, &ch, 1); - break; - case SERIAL_INT_ENABLE: - s->int_enable = value; - syborg_serial_update(s); - break; - case SERIAL_DMA_TX_ADDR: - s->dma_tx_ptr = value; - break; - case SERIAL_DMA_TX_COUNT: - do_dma_tx(s, value); - break; - case SERIAL_DMA_RX_ADDR: - /* For safety, writes to this register cancel any pending DMA. */ - s->dma_rx_size = 0; - s->dma_rx_ptr = value; - break; - case SERIAL_DMA_RX_COUNT: - dma_rx_start(s, value); - break; - default: - cpu_abort(cpu_single_env, "syborg_serial_write: Bad offset %x\n", - (int)offset); - break; - } -} - -static int syborg_serial_can_receive(void *opaque) -{ - SyborgSerialState *s = (SyborgSerialState *)opaque; - - if (s->dma_rx_size) - return s->dma_rx_size; - return s->fifo_size - s->read_count; -} - -static void syborg_serial_receive(void *opaque, const uint8_t *buf, int size) -{ - SyborgSerialState *s = (SyborgSerialState *)opaque; - - if (s->dma_rx_size) { - /* Place it in the DMA buffer. */ - cpu_physical_memory_write(s->dma_rx_ptr, buf, size); - s->dma_rx_size -= size; - s->dma_rx_ptr += size; - } else { - while (size--) - fifo_push(s, *buf); - } - - syborg_serial_update(s); -} - -static void syborg_serial_event(void *opaque, int event) -{ - /* TODO: Report BREAK events? */ -} - -static const MemoryRegionOps syborg_serial_ops = { - .read = syborg_serial_read, - .write = syborg_serial_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static const VMStateDescription vmstate_syborg_serial = { - .name = "syborg_serial", - .version_id = 1, - .minimum_version_id = 1, - .minimum_version_id_old = 1, - .fields = (VMStateField[]) { - VMSTATE_UINT32_EQUAL(fifo_size, SyborgSerialState), - VMSTATE_UINT32(int_enable, SyborgSerialState), - VMSTATE_INT32(read_pos, SyborgSerialState), - VMSTATE_INT32(read_count, SyborgSerialState), - VMSTATE_UINT32(dma_tx_ptr, SyborgSerialState), - VMSTATE_UINT32(dma_rx_ptr, SyborgSerialState), - VMSTATE_UINT32(dma_rx_size, SyborgSerialState), - VMSTATE_VARRAY_UINT32(read_fifo, SyborgSerialState, fifo_size, 1, - vmstate_info_uint32, uint32), - VMSTATE_END_OF_LIST() - } -}; - -static int syborg_serial_init(SysBusDevice *dev) -{ - SyborgSerialState *s = FROM_SYSBUS(SyborgSerialState, dev); - - sysbus_init_irq(dev, &s->irq); - memory_region_init_io(&s->iomem, &syborg_serial_ops, s, - "serial", 0x1000); - sysbus_init_mmio(dev, &s->iomem); - s->chr = qdev_init_chardev(&dev->qdev); - if (s->chr) { - qemu_chr_add_handlers(s->chr, syborg_serial_can_receive, - syborg_serial_receive, syborg_serial_event, s); - } - if (s->fifo_size <= 0) { - fprintf(stderr, "syborg_serial: fifo too small\n"); - s->fifo_size = 16; - } - s->read_fifo = g_malloc0(s->fifo_size * sizeof(s->read_fifo[0])); - - return 0; -} - -static SysBusDeviceInfo syborg_serial_info = { - .init = syborg_serial_init, - .qdev.name = "syborg,serial", - .qdev.size = sizeof(SyborgSerialState), - .qdev.vmsd = &vmstate_syborg_serial, - .qdev.props = (Property[]) { - DEFINE_PROP_UINT32("fifo-size", SyborgSerialState, fifo_size, 16), - DEFINE_PROP_END_OF_LIST(), - } -}; - -static void syborg_serial_register_devices(void) -{ - sysbus_register_withprop(&syborg_serial_info); -} - -device_init(syborg_serial_register_devices) diff --git a/hw/syborg_timer.c b/hw/syborg_timer.c deleted file mode 100644 index 1498f01a62..0000000000 --- a/hw/syborg_timer.c +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Syborg Interval Timer. - * - * Copyright (c) 2008 CodeSourcery - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "sysbus.h" -#include "qemu-timer.h" -#include "syborg.h" - -//#define DEBUG_SYBORG_TIMER - -#ifdef DEBUG_SYBORG_TIMER -#define DPRINTF(fmt, ...) \ -do { printf("syborg_timer: " fmt , ##args); } while (0) -#define BADF(fmt, ...) \ -do { fprintf(stderr, "syborg_timer: error: " fmt , ## __VA_ARGS__); \ - exit(1);} while (0) -#else -#define DPRINTF(fmt, ...) do {} while(0) -#define BADF(fmt, ...) \ -do { fprintf(stderr, "syborg_timer: error: " fmt , ## __VA_ARGS__);} while (0) -#endif - -enum { - TIMER_ID = 0, - TIMER_RUNNING = 1, - TIMER_ONESHOT = 2, - TIMER_LIMIT = 3, - TIMER_VALUE = 4, - TIMER_INT_ENABLE = 5, - TIMER_INT_STATUS = 6, - TIMER_FREQ = 7 -}; - -typedef struct { - SysBusDevice busdev; - MemoryRegion iomem; - ptimer_state *timer; - int running; - int oneshot; - uint32_t limit; - uint32_t freq; - uint32_t int_level; - uint32_t int_enabled; - qemu_irq irq; -} SyborgTimerState; - -static void syborg_timer_update(SyborgTimerState *s) -{ - /* Update interrupt. */ - if (s->int_level && s->int_enabled) { - qemu_irq_raise(s->irq); - } else { - qemu_irq_lower(s->irq); - } -} - -static void syborg_timer_tick(void *opaque) -{ - SyborgTimerState *s = (SyborgTimerState *)opaque; - //DPRINTF("Timer Tick\n"); - s->int_level = 1; - if (s->oneshot) - s->running = 0; - syborg_timer_update(s); -} - -static uint64_t syborg_timer_read(void *opaque, target_phys_addr_t offset, - unsigned size) -{ - SyborgTimerState *s = (SyborgTimerState *)opaque; - - DPRINTF("Reg read %d\n", (int)offset); - offset &= 0xfff; - switch (offset >> 2) { - case TIMER_ID: - return SYBORG_ID_TIMER; - case TIMER_RUNNING: - return s->running; - case TIMER_ONESHOT: - return s->oneshot; - case TIMER_LIMIT: - return s->limit; - case TIMER_VALUE: - return ptimer_get_count(s->timer); - case TIMER_INT_ENABLE: - return s->int_enabled; - case TIMER_INT_STATUS: - return s->int_level; - case TIMER_FREQ: - return s->freq; - default: - cpu_abort(cpu_single_env, "syborg_timer_read: Bad offset %x\n", - (int)offset); - return 0; - } -} - -static void syborg_timer_write(void *opaque, target_phys_addr_t offset, - uint64_t value, unsigned size) -{ - SyborgTimerState *s = (SyborgTimerState *)opaque; - - DPRINTF("Reg write %d\n", (int)offset); - offset &= 0xfff; - switch (offset >> 2) { - case TIMER_RUNNING: - if (value == s->running) - break; - s->running = value; - if (value) { - ptimer_run(s->timer, s->oneshot); - } else { - ptimer_stop(s->timer); - } - break; - case TIMER_ONESHOT: - if (s->running) { - ptimer_stop(s->timer); - } - s->oneshot = value; - if (s->running) { - ptimer_run(s->timer, s->oneshot); - } - break; - case TIMER_LIMIT: - s->limit = value; - ptimer_set_limit(s->timer, value, 1); - break; - case TIMER_VALUE: - ptimer_set_count(s->timer, value); - break; - case TIMER_INT_ENABLE: - s->int_enabled = value; - syborg_timer_update(s); - break; - case TIMER_INT_STATUS: - s->int_level &= ~value; - syborg_timer_update(s); - break; - default: - cpu_abort(cpu_single_env, "syborg_timer_write: Bad offset %x\n", - (int)offset); - break; - } -} - -static const MemoryRegionOps syborg_timer_ops = { - .read = syborg_timer_read, - .write = syborg_timer_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static const VMStateDescription vmstate_syborg_timer = { - .name = "syborg_timer", - .version_id = 1, - .minimum_version_id = 1, - .minimum_version_id_old = 1, - .fields = (VMStateField[]) { - VMSTATE_INT32(running, SyborgTimerState), - VMSTATE_INT32(oneshot, SyborgTimerState), - VMSTATE_UINT32(limit, SyborgTimerState), - VMSTATE_UINT32(int_level, SyborgTimerState), - VMSTATE_UINT32(int_enabled, SyborgTimerState), - VMSTATE_PTIMER(timer, SyborgTimerState), - VMSTATE_END_OF_LIST() - } -}; - -static int syborg_timer_init(SysBusDevice *dev) -{ - SyborgTimerState *s = FROM_SYSBUS(SyborgTimerState, dev); - QEMUBH *bh; - - if (s->freq == 0) { - fprintf(stderr, "syborg_timer: Zero/unset frequency\n"); - exit(1); - } - sysbus_init_irq(dev, &s->irq); - memory_region_init_io(&s->iomem, &syborg_timer_ops, s, "timer", 0x1000); - sysbus_init_mmio(dev, &s->iomem); - - bh = qemu_bh_new(syborg_timer_tick, s); - s->timer = ptimer_init(bh); - ptimer_set_freq(s->timer, s->freq); - vmstate_register(&dev->qdev, -1, &vmstate_syborg_timer, s); - return 0; -} - -static SysBusDeviceInfo syborg_timer_info = { - .init = syborg_timer_init, - .qdev.name = "syborg,timer", - .qdev.size = sizeof(SyborgTimerState), - .qdev.props = (Property[]) { - DEFINE_PROP_UINT32("frequency",SyborgTimerState, freq, 0), - DEFINE_PROP_END_OF_LIST(), - } -}; - -static void syborg_timer_register_devices(void) -{ - sysbus_register_withprop(&syborg_timer_info); -} - -device_init(syborg_timer_register_devices) diff --git a/hw/syborg_virtio.c b/hw/syborg_virtio.c deleted file mode 100644 index 96a0ee651f..0000000000 --- a/hw/syborg_virtio.c +++ /dev/null @@ -1,307 +0,0 @@ -/* - * Virtio Syborg bindings - * - * Copyright (c) 2009 CodeSourcery - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "syborg.h" -#include "sysbus.h" -#include "virtio.h" -#include "virtio-net.h" - -//#define DEBUG_SYBORG_VIRTIO - -#ifdef DEBUG_SYBORG_VIRTIO -#define DPRINTF(fmt, ...) \ -do { printf("syborg_virtio: " fmt , ## __VA_ARGS__); } while (0) -#define BADF(fmt, ...) \ -do { fprintf(stderr, "syborg_virtio: error: " fmt , ## __VA_ARGS__); \ - exit(1);} while (0) -#else -#define DPRINTF(fmt, ...) do {} while(0) -#define BADF(fmt, ...) \ -do { fprintf(stderr, "syborg_virtio: error: " fmt , ## __VA_ARGS__);} while (0) -#endif - -enum { - SYBORG_VIRTIO_ID = 0, - SYBORG_VIRTIO_DEVTYPE = 1, - SYBORG_VIRTIO_HOST_FEATURES = 2, - SYBORG_VIRTIO_GUEST_FEATURES = 3, - SYBORG_VIRTIO_QUEUE_BASE = 4, - SYBORG_VIRTIO_QUEUE_NUM = 5, - SYBORG_VIRTIO_QUEUE_SEL = 6, - SYBORG_VIRTIO_QUEUE_NOTIFY = 7, - SYBORG_VIRTIO_STATUS = 8, - SYBORG_VIRTIO_INT_ENABLE = 9, - SYBORG_VIRTIO_INT_STATUS = 10 -}; - -#define SYBORG_VIRTIO_CONFIG 0x100 - -/* Device independent interface. */ - -typedef struct { - SysBusDevice busdev; - VirtIODevice *vdev; - MemoryRegion iomem; - qemu_irq irq; - uint32_t int_enable; - uint32_t id; - NICConf nic; - uint32_t host_features; - virtio_net_conf net; -} SyborgVirtIOProxy; - -static uint32_t syborg_virtio_readl(void *opaque, target_phys_addr_t offset) -{ - SyborgVirtIOProxy *s = opaque; - VirtIODevice *vdev = s->vdev; - uint32_t ret; - - DPRINTF("readl 0x%x\n", (int)offset); - if (offset >= SYBORG_VIRTIO_CONFIG) { - return virtio_config_readl(vdev, offset - SYBORG_VIRTIO_CONFIG); - } - switch(offset >> 2) { - case SYBORG_VIRTIO_ID: - ret = SYBORG_ID_VIRTIO; - break; - case SYBORG_VIRTIO_DEVTYPE: - ret = s->id; - break; - case SYBORG_VIRTIO_HOST_FEATURES: - ret = s->host_features; - break; - case SYBORG_VIRTIO_GUEST_FEATURES: - ret = vdev->guest_features; - break; - case SYBORG_VIRTIO_QUEUE_BASE: - ret = virtio_queue_get_addr(vdev, vdev->queue_sel); - break; - case SYBORG_VIRTIO_QUEUE_NUM: - ret = virtio_queue_get_num(vdev, vdev->queue_sel); - break; - case SYBORG_VIRTIO_QUEUE_SEL: - ret = vdev->queue_sel; - break; - case SYBORG_VIRTIO_STATUS: - ret = vdev->status; - break; - case SYBORG_VIRTIO_INT_ENABLE: - ret = s->int_enable; - break; - case SYBORG_VIRTIO_INT_STATUS: - ret = vdev->isr; - break; - default: - BADF("Bad read offset 0x%x\n", (int)offset); - return 0; - } - return ret; -} - -static void syborg_virtio_writel(void *opaque, target_phys_addr_t offset, - uint32_t value) -{ - SyborgVirtIOProxy *s = opaque; - VirtIODevice *vdev = s->vdev; - - DPRINTF("writel 0x%x = 0x%x\n", (int)offset, value); - if (offset >= SYBORG_VIRTIO_CONFIG) { - return virtio_config_writel(vdev, offset - SYBORG_VIRTIO_CONFIG, - value); - } - switch (offset >> 2) { - case SYBORG_VIRTIO_GUEST_FEATURES: - virtio_set_features(vdev, value); - break; - case SYBORG_VIRTIO_QUEUE_BASE: - if (value == 0) - virtio_reset(vdev); - else - virtio_queue_set_addr(vdev, vdev->queue_sel, value); - break; - case SYBORG_VIRTIO_QUEUE_SEL: - if (value < VIRTIO_PCI_QUEUE_MAX) - vdev->queue_sel = value; - break; - case SYBORG_VIRTIO_QUEUE_NOTIFY: - if (value < VIRTIO_PCI_QUEUE_MAX) { - virtio_queue_notify(vdev, value); - } - break; - case SYBORG_VIRTIO_STATUS: - virtio_set_status(vdev, value & 0xFF); - if (vdev->status == 0) - virtio_reset(vdev); - break; - case SYBORG_VIRTIO_INT_ENABLE: - s->int_enable = value; - virtio_update_irq(vdev); - break; - case SYBORG_VIRTIO_INT_STATUS: - vdev->isr &= ~value; - virtio_update_irq(vdev); - break; - default: - BADF("Bad write offset 0x%x\n", (int)offset); - break; - } -} - -static uint32_t syborg_virtio_readw(void *opaque, target_phys_addr_t offset) -{ - SyborgVirtIOProxy *s = opaque; - VirtIODevice *vdev = s->vdev; - - DPRINTF("readw 0x%x\n", (int)offset); - if (offset >= SYBORG_VIRTIO_CONFIG) { - return virtio_config_readw(vdev, offset - SYBORG_VIRTIO_CONFIG); - } - BADF("Bad halfword read offset 0x%x\n", (int)offset); - return -1; -} - -static void syborg_virtio_writew(void *opaque, target_phys_addr_t offset, - uint32_t value) -{ - SyborgVirtIOProxy *s = opaque; - VirtIODevice *vdev = s->vdev; - - DPRINTF("writew 0x%x = 0x%x\n", (int)offset, value); - if (offset >= SYBORG_VIRTIO_CONFIG) { - return virtio_config_writew(vdev, offset - SYBORG_VIRTIO_CONFIG, - value); - } - BADF("Bad halfword write offset 0x%x\n", (int)offset); -} - -static uint32_t syborg_virtio_readb(void *opaque, target_phys_addr_t offset) -{ - SyborgVirtIOProxy *s = opaque; - VirtIODevice *vdev = s->vdev; - - DPRINTF("readb 0x%x\n", (int)offset); - if (offset >= SYBORG_VIRTIO_CONFIG) { - return virtio_config_readb(vdev, offset - SYBORG_VIRTIO_CONFIG); - } - BADF("Bad byte read offset 0x%x\n", (int)offset); - return -1; -} - -static void syborg_virtio_writeb(void *opaque, target_phys_addr_t offset, - uint32_t value) -{ - SyborgVirtIOProxy *s = opaque; - VirtIODevice *vdev = s->vdev; - - DPRINTF("writeb 0x%x = 0x%x\n", (int)offset, value); - if (offset >= SYBORG_VIRTIO_CONFIG) { - return virtio_config_writeb(vdev, offset - SYBORG_VIRTIO_CONFIG, - value); - } - BADF("Bad byte write offset 0x%x\n", (int)offset); -} - -static const MemoryRegionOps syborg_virtio_ops = { - .old_mmio = { - .read = { syborg_virtio_readb, syborg_virtio_readw, syborg_virtio_readl }, - .write = { syborg_virtio_writeb, syborg_virtio_writew, syborg_virtio_writel }, - }, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void syborg_virtio_update_irq(void *opaque, uint16_t vector) -{ - SyborgVirtIOProxy *proxy = opaque; - int level; - - level = proxy->int_enable & proxy->vdev->isr; - DPRINTF("IRQ %d\n", level); - qemu_set_irq(proxy->irq, level != 0); -} - -static unsigned syborg_virtio_get_features(void *opaque) -{ - SyborgVirtIOProxy *proxy = opaque; - return proxy->host_features; -} - -static VirtIOBindings syborg_virtio_bindings = { - .notify = syborg_virtio_update_irq, - .get_features = syborg_virtio_get_features, -}; - -static int syborg_virtio_init(SyborgVirtIOProxy *proxy, VirtIODevice *vdev) -{ - proxy->vdev = vdev; - - /* Don't support multiple vectors */ - proxy->vdev->nvectors = 0; - sysbus_init_irq(&proxy->busdev, &proxy->irq); - memory_region_init_io(&proxy->iomem, &syborg_virtio_ops, proxy, - "virtio", 0x1000); - sysbus_init_mmio(&proxy->busdev, &proxy->iomem); - - proxy->id = ((uint32_t)0x1af4 << 16) | vdev->device_id; - - qemu_register_reset(virtio_reset, vdev); - - virtio_bind_device(vdev, &syborg_virtio_bindings, proxy); - proxy->host_features |= (0x1 << VIRTIO_F_NOTIFY_ON_EMPTY); - proxy->host_features = vdev->get_features(vdev, proxy->host_features); - return 0; -} - -/* Device specific bindings. */ - -static int syborg_virtio_net_init(SysBusDevice *dev) -{ - VirtIODevice *vdev; - SyborgVirtIOProxy *proxy = FROM_SYSBUS(SyborgVirtIOProxy, dev); - - vdev = virtio_net_init(&dev->qdev, &proxy->nic, &proxy->net); - return syborg_virtio_init(proxy, vdev); -} - -static SysBusDeviceInfo syborg_virtio_net_info = { - .init = syborg_virtio_net_init, - .qdev.name = "syborg,virtio-net", - .qdev.size = sizeof(SyborgVirtIOProxy), - .qdev.props = (Property[]) { - DEFINE_NIC_PROPERTIES(SyborgVirtIOProxy, nic), - DEFINE_VIRTIO_NET_FEATURES(SyborgVirtIOProxy, host_features), - DEFINE_PROP_UINT32("x-txtimer", SyborgVirtIOProxy, - net.txtimer, TX_TIMER_INTERVAL), - DEFINE_PROP_INT32("x-txburst", SyborgVirtIOProxy, - net.txburst, TX_BURST), - DEFINE_PROP_STRING("tx", SyborgVirtIOProxy, net.tx), - DEFINE_PROP_END_OF_LIST(), - } -}; - -static void syborg_virtio_register_devices(void) -{ - sysbus_register_withprop(&syborg_virtio_net_info); -} - -device_init(syborg_virtio_register_devices) |