Revision 4af39611

b/Makefile.target
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)
b/hw/boards.h
128 128
/* tosa.c */
129 129
extern QEMUMachine tosapda_machine;
130 130

  
131
/* syborg.c */
132
extern QEMUMachine syborg_machine;
133

  
131 134
#endif
b/hw/syborg.c
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
};
b/hw/syborg.h
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
b/hw/syborg_fb.c
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)
b/hw/syborg_interrupt.c
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)
b/hw/syborg_keyboard.c
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)
b/hw/syborg_pointer.c
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)
b/hw/syborg_rtc.c
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) {
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff