/*
* QEMU JAZZ LED emulator.
*
- * Copyright (c) 2007 Hervé Poussineau
+ * Copyright (c) 2007-2012 Herve Poussineau
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* THE SOFTWARE.
*/
-#include "hw.h"
-#include "mips.h"
+#include "qemu-common.h"
#include "console.h"
#include "pixel_ops.h"
-
-//#define DEBUG_LED
+#include "trace.h"
+#include "sysbus.h"
typedef enum {
REDRAW_NONE = 0, REDRAW_SEGMENTS = 1, REDRAW_BACKGROUND = 2,
} screen_state_t;
typedef struct LedState {
- target_phys_addr_t base;
+ SysBusDevice busdev;
+ MemoryRegion iomem;
uint8_t segments;
DisplayState *ds;
- QEMUConsole *console;
screen_state_t state;
} LedState;
-static uint32_t led_readb(void *opaque, target_phys_addr_t addr)
+static uint64_t jazz_led_read(void *opaque, hwaddr addr,
+ unsigned int size)
{
LedState *s = opaque;
- int relative_addr = addr - s->base;
- uint32_t val;
+ uint8_t val;
- switch (relative_addr) {
- case 0:
- val = s->segments;
- break;
- default:
-#ifdef DEBUG_LED
- printf("jazz led: invalid read [0x%x]\n", relative_addr);
-#endif
- val = 0;
- }
+ val = s->segments;
+ trace_jazz_led_read(addr, val);
return val;
}
-static uint32_t led_readw(void *opaque, target_phys_addr_t addr)
-{
- uint32_t v;
-#ifdef TARGET_WORDS_BIGENDIAN
- v = led_readb(opaque, addr) << 8;
- v |= led_readb(opaque, addr + 1);
-#else
- v = led_readb(opaque, addr);
- v |= led_readb(opaque, addr + 1) << 8;
-#endif
- return v;
-}
-
-static uint32_t led_readl(void *opaque, target_phys_addr_t addr)
-{
- uint32_t v;
-#ifdef TARGET_WORDS_BIGENDIAN
- v = led_readb(opaque, addr) << 24;
- v |= led_readb(opaque, addr + 1) << 16;
- v |= led_readb(opaque, addr + 2) << 8;
- v |= led_readb(opaque, addr + 3);
-#else
- v = led_readb(opaque, addr);
- v |= led_readb(opaque, addr + 1) << 8;
- v |= led_readb(opaque, addr + 2) << 16;
- v |= led_readb(opaque, addr + 3) << 24;
-#endif
- return v;
-}
-
-static void led_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
+static void jazz_led_write(void *opaque, hwaddr addr,
+ uint64_t val, unsigned int size)
{
LedState *s = opaque;
- int relative_addr = addr - s->base;
+ uint8_t new_val = val & 0xff;
- switch (relative_addr) {
- case 0:
- s->segments = val;
- s->state |= REDRAW_SEGMENTS;
- break;
- default:
-#ifdef DEBUG_LED
- printf("jazz led: invalid write of 0x%02x at [0x%x]\n", val, relative_addr);
-#endif
- break;
- }
-}
-
-static void led_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-#ifdef TARGET_WORDS_BIGENDIAN
- led_writeb(opaque, addr, (val >> 8) & 0xff);
- led_writeb(opaque, addr + 1, val & 0xff);
-#else
- led_writeb(opaque, addr, val & 0xff);
- led_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-#endif
-}
+ trace_jazz_led_write(addr, new_val);
-static void led_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-#ifdef TARGET_WORDS_BIGENDIAN
- led_writeb(opaque, addr, (val >> 24) & 0xff);
- led_writeb(opaque, addr + 1, (val >> 16) & 0xff);
- led_writeb(opaque, addr + 2, (val >> 8) & 0xff);
- led_writeb(opaque, addr + 3, val & 0xff);
-#else
- led_writeb(opaque, addr, val & 0xff);
- led_writeb(opaque, addr + 1, (val >> 8) & 0xff);
- led_writeb(opaque, addr + 2, (val >> 16) & 0xff);
- led_writeb(opaque, addr + 3, (val >> 24) & 0xff);
-#endif
+ s->segments = new_val;
+ s->state |= REDRAW_SEGMENTS;
}
-static CPUReadMemoryFunc *led_read[3] = {
- led_readb,
- led_readw,
- led_readl,
-};
-
-static CPUWriteMemoryFunc *led_write[3] = {
- led_writeb,
- led_writew,
- led_writel,
+static const MemoryRegionOps led_ops = {
+ .read = jazz_led_read,
+ .write = jazz_led_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .impl.min_access_size = 1,
+ .impl.max_access_size = 1,
};
/***********************************************************/
uint8_t *d;
int x, bpp;
- bpp = (ds->depth + 7) >> 3;
- d = ds->data + ds->linesize * posy + bpp * posx1;
+ bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
+ d = ds_get_data(ds) + ds_get_linesize(ds) * posy + bpp * posx1;
switch(bpp) {
case 1:
for (x = posx1; x <= posx2; x++) {
uint8_t *d;
int y, bpp;
- bpp = (ds->depth + 7) >> 3;
- d = ds->data + ds->linesize * posy1 + bpp * posx;
+ bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
+ d = ds_get_data(ds) + ds_get_linesize(ds) * posy1 + bpp * posx;
switch(bpp) {
case 1:
for (y = posy1; y <= posy2; y++) {
*((uint8_t *)d) = color;
- d += ds->linesize;
+ d += ds_get_linesize(ds);
}
break;
case 2:
for (y = posy1; y <= posy2; y++) {
*((uint16_t *)d) = color;
- d += ds->linesize;
+ d += ds_get_linesize(ds);
}
break;
case 4:
for (y = posy1; y <= posy2; y++) {
*((uint32_t *)d) = color;
- d += ds->linesize;
+ d += ds_get_linesize(ds);
}
break;
}
if (s->state & REDRAW_BACKGROUND) {
/* clear screen */
- bpp = (ds->depth + 7) >> 3;
- d1 = ds->data;
- for (y = 0; y < ds->height; y++) {
- memset(d1, 0x00, ds->width * bpp);
- d1 += ds->linesize;
+ bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
+ d1 = ds_get_data(ds);
+ for (y = 0; y < ds_get_height(ds); y++) {
+ memset(d1, 0x00, ds_get_width(ds) * bpp);
+ d1 += ds_get_linesize(ds);
}
}
if (s->state & REDRAW_SEGMENTS) {
/* set colors according to bpp */
- switch (ds->depth) {
+ switch (ds_get_bits_per_pixel(ds)) {
case 8:
color_segment = rgb_to_pixel8(0xaa, 0xaa, 0xaa);
color_led = rgb_to_pixel8(0x00, 0xff, 0x00);
}
s->state = REDRAW_NONE;
- dpy_update(ds, 0, 0, ds->width, ds->height);
+ dpy_gfx_update(ds, 0, 0, ds_get_width(ds), ds_get_height(ds));
}
static void jazz_led_invalidate_display(void *opaque)
s->state |= REDRAW_SEGMENTS | REDRAW_BACKGROUND;
}
-static void jazz_led_screen_dump(void *opaque, const char *filename)
-{
- printf("jazz_led_screen_dump() not implemented\n");
-}
-
static void jazz_led_text_update(void *opaque, console_ch_t *chardata)
{
LedState *s = opaque;
char buf[2];
- dpy_cursor(s->ds, -1, -1);
- qemu_console_resize(s->console, 2, 1);
+ dpy_text_cursor(s->ds, -1, -1);
+ qemu_console_resize(s->ds, 2, 1);
/* TODO: draw the segments */
snprintf(buf, 2, "%02hhx\n", s->segments);
console_write_ch(chardata++, 0x00200100 | buf[0]);
console_write_ch(chardata++, 0x00200100 | buf[1]);
- dpy_update(s->ds, 0, 0, 2, 1);
+ dpy_text_update(s->ds, 0, 0, 2, 1);
}
-void jazz_led_init(DisplayState *ds, target_phys_addr_t base)
+static int jazz_led_post_load(void *opaque, int version_id)
{
- LedState *s;
- int io;
+ /* force refresh */
+ jazz_led_invalidate_display(opaque);
+
+ return 0;
+}
+
+static const VMStateDescription vmstate_jazz_led = {
+ .name = "jazz-led",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .post_load = jazz_led_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT8(segments, LedState),
+ VMSTATE_END_OF_LIST()
+ }
+};
- s = qemu_mallocz(sizeof(LedState));
- if (!s)
- return;
+static int jazz_led_init(SysBusDevice *dev)
+{
+ LedState *s = FROM_SYSBUS(LedState, dev);
+
+ memory_region_init_io(&s->iomem, &led_ops, s, "led", 1);
+ sysbus_init_mmio(dev, &s->iomem);
+
+ s->ds = graphic_console_init(jazz_led_update_display,
+ jazz_led_invalidate_display,
+ NULL,
+ jazz_led_text_update, s);
+
+ return 0;
+}
- s->base = base;
- s->ds = ds;
+static void jazz_led_reset(DeviceState *d)
+{
+ LedState *s = DO_UPCAST(LedState, busdev.qdev, d);
+
+ s->segments = 0;
s->state = REDRAW_SEGMENTS | REDRAW_BACKGROUND;
+ qemu_console_resize(s->ds, 60, 80);
+}
+
+static void jazz_led_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- io = cpu_register_io_memory(0, led_read, led_write, s);
- cpu_register_physical_memory(s->base, 1, io);
+ k->init = jazz_led_init;
+ dc->desc = "Jazz LED display",
+ dc->vmsd = &vmstate_jazz_led;
+ dc->reset = jazz_led_reset;
+}
+
+static TypeInfo jazz_led_info = {
+ .name = "jazz-led",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(LedState),
+ .class_init = jazz_led_class_init,
+};
- s->console = graphic_console_init(ds, jazz_led_update_display,
- jazz_led_invalidate_display,
- jazz_led_screen_dump,
- jazz_led_text_update, s);
- qemu_console_resize(s->console, 60, 80);
+static void jazz_led_register(void)
+{
+ type_register_static(&jazz_led_info);
}
+
+type_init(jazz_led_register);