~ubuntu-branches/ubuntu/vivid/qemu/vivid

« back to all changes in this revision

Viewing changes to hw/char/digic-uart.c

  • Committer: Package Import Robot
  • Author(s): Serge Hallyn
  • Date: 2014-02-25 22:31:43 UTC
  • mfrom: (1.8.5)
  • Revision ID: package-import@ubuntu.com-20140225223143-odhqxfc60wxrjl15
Tags: 2.0.0~rc1+dfsg-0ubuntu1
* Merge 2.0.0-rc1
* debian/rules: consolidate ppc filter entries.
* Move qemu-system-arch64 into qemu-system-arm
* debian/patches/define-trusty-machine-type.patch: define a trusty machine
  type, currently the same as pc-i440fx-2.0, to put is in a better position
  to enable live migrations from trusty onward.  (LP: #1294823)
* debian/control: build-dep on libfdt >= 1.4.0  (LP: #1295072)
* Merge latest upstream git to commit dc9528f
* Debian/rules:
  - remove -enable-uname-release=2.6.32
  - don't make the aarch64 target Ubuntu-specific.
* Remove patches which are now upstream:
  - fix-smb-security-share.patch
  - slirp-smb-redirect-port-445-too.patch 
  - linux-user-Implement-sendmmsg-syscall.patch (better version is upstream)
  - signal-added-a-wrapper-for-sigprocmask-function.patch
  - ubuntu/signal-sigsegv-protection-on-do_sigprocmask.patch
  - ubuntu/Don-t-block-SIGSEGV-at-more-places.patch
  - ubuntu/ppc-force-cpu-threads-count-to-be-power-of-2.patch
* add link for /usr/share/qemu/bios-256k.bin
* Remove all linaro patches.
* Remove all arm64/ patches.  Many but not all are upstream.
* Remove CVE-2013-4377.patch which is upstream.
* debian/control-in: don't make qemu-system-aarch64 ubuntu-specific

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * QEMU model of the Canon DIGIC UART block.
 
3
 *
 
4
 * Copyright (C) 2013 Antony Pavlov <antonynpavlov@gmail.com>
 
5
 *
 
6
 * This model is based on reverse engineering efforts
 
7
 * made by CHDK (http://chdk.wikia.com) and
 
8
 * Magic Lantern (http://www.magiclantern.fm) projects
 
9
 * contributors.
 
10
 *
 
11
 * See "Serial terminal" docs here:
 
12
 *   http://magiclantern.wikia.com/wiki/Register_Map#Misc_Registers
 
13
 *
 
14
 * The QEMU model of the Milkymist UART block by Michael Walle
 
15
 * is used as a template.
 
16
 *
 
17
 * This program is free software; you can redistribute it and/or modify
 
18
 * it under the terms of the GNU General Public License as published by
 
19
 * the Free Software Foundation; either version 2 of the License, or
 
20
 * (at your option) any later version.
 
21
 *
 
22
 * This program is distributed in the hope that it will be useful,
 
23
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
24
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 
25
 * GNU General Public License for more details.
 
26
 *
 
27
 */
 
28
 
 
29
#include "hw/hw.h"
 
30
#include "hw/sysbus.h"
 
31
#include "sysemu/char.h"
 
32
 
 
33
#include "hw/char/digic-uart.h"
 
34
 
 
35
enum {
 
36
    ST_RX_RDY = (1 << 0),
 
37
    ST_TX_RDY = (1 << 1),
 
38
};
 
39
 
 
40
static uint64_t digic_uart_read(void *opaque, hwaddr addr,
 
41
                                unsigned size)
 
42
{
 
43
    DigicUartState *s = opaque;
 
44
    uint64_t ret = 0;
 
45
 
 
46
    addr >>= 2;
 
47
 
 
48
    switch (addr) {
 
49
    case R_RX:
 
50
        s->reg_st &= ~(ST_RX_RDY);
 
51
        ret = s->reg_rx;
 
52
        break;
 
53
 
 
54
    case R_ST:
 
55
        ret = s->reg_st;
 
56
        break;
 
57
 
 
58
    default:
 
59
        qemu_log_mask(LOG_UNIMP,
 
60
                      "digic-uart: read access to unknown register 0x"
 
61
                      TARGET_FMT_plx, addr << 2);
 
62
    }
 
63
 
 
64
    return ret;
 
65
}
 
66
 
 
67
static void digic_uart_write(void *opaque, hwaddr addr, uint64_t value,
 
68
                             unsigned size)
 
69
{
 
70
    DigicUartState *s = opaque;
 
71
    unsigned char ch = value;
 
72
 
 
73
    addr >>= 2;
 
74
 
 
75
    switch (addr) {
 
76
    case R_TX:
 
77
        if (s->chr) {
 
78
            qemu_chr_fe_write_all(s->chr, &ch, 1);
 
79
        }
 
80
        break;
 
81
 
 
82
    case R_ST:
 
83
        /*
 
84
         * Ignore write to R_ST.
 
85
         *
 
86
         * The point is that this register is actively used
 
87
         * during receiving and transmitting symbols,
 
88
         * but we don't know the function of most of bits.
 
89
         *
 
90
         * Ignoring writes to R_ST is only a simplification
 
91
         * of the model. It has no perceptible side effects
 
92
         * for existing guests.
 
93
         */
 
94
        break;
 
95
 
 
96
    default:
 
97
        qemu_log_mask(LOG_UNIMP,
 
98
                      "digic-uart: write access to unknown register 0x"
 
99
                      TARGET_FMT_plx, addr << 2);
 
100
    }
 
101
}
 
102
 
 
103
static const MemoryRegionOps uart_mmio_ops = {
 
104
    .read = digic_uart_read,
 
105
    .write = digic_uart_write,
 
106
    .valid = {
 
107
        .min_access_size = 4,
 
108
        .max_access_size = 4,
 
109
    },
 
110
    .endianness = DEVICE_NATIVE_ENDIAN,
 
111
};
 
112
 
 
113
static int uart_can_rx(void *opaque)
 
114
{
 
115
    DigicUartState *s = opaque;
 
116
 
 
117
    return !(s->reg_st & ST_RX_RDY);
 
118
}
 
119
 
 
120
static void uart_rx(void *opaque, const uint8_t *buf, int size)
 
121
{
 
122
    DigicUartState *s = opaque;
 
123
 
 
124
    assert(uart_can_rx(opaque));
 
125
 
 
126
    s->reg_st |= ST_RX_RDY;
 
127
    s->reg_rx = *buf;
 
128
}
 
129
 
 
130
static void uart_event(void *opaque, int event)
 
131
{
 
132
}
 
133
 
 
134
static void digic_uart_reset(DeviceState *d)
 
135
{
 
136
    DigicUartState *s = DIGIC_UART(d);
 
137
 
 
138
    s->reg_rx = 0;
 
139
    s->reg_st = ST_TX_RDY;
 
140
}
 
141
 
 
142
static void digic_uart_realize(DeviceState *dev, Error **errp)
 
143
{
 
144
    DigicUartState *s = DIGIC_UART(dev);
 
145
 
 
146
    s->chr = qemu_char_get_next_serial();
 
147
    if (s->chr) {
 
148
        qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
 
149
    }
 
150
}
 
151
 
 
152
static void digic_uart_init(Object *obj)
 
153
{
 
154
    DigicUartState *s = DIGIC_UART(obj);
 
155
 
 
156
    memory_region_init_io(&s->regs_region, OBJECT(s), &uart_mmio_ops, s,
 
157
                          TYPE_DIGIC_UART, 0x18);
 
158
    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->regs_region);
 
159
}
 
160
 
 
161
static const VMStateDescription vmstate_digic_uart = {
 
162
    .name = "digic-uart",
 
163
    .version_id = 1,
 
164
    .minimum_version_id = 1,
 
165
    .minimum_version_id_old = 1,
 
166
    .fields = (VMStateField[]) {
 
167
        VMSTATE_UINT32(reg_rx, DigicUartState),
 
168
        VMSTATE_UINT32(reg_st, DigicUartState),
 
169
        VMSTATE_END_OF_LIST()
 
170
    }
 
171
};
 
172
 
 
173
static void digic_uart_class_init(ObjectClass *klass, void *data)
 
174
{
 
175
    DeviceClass *dc = DEVICE_CLASS(klass);
 
176
 
 
177
    dc->realize = digic_uart_realize;
 
178
    dc->reset = digic_uart_reset;
 
179
    dc->vmsd = &vmstate_digic_uart;
 
180
}
 
181
 
 
182
static const TypeInfo digic_uart_info = {
 
183
    .name = TYPE_DIGIC_UART,
 
184
    .parent = TYPE_SYS_BUS_DEVICE,
 
185
    .instance_size = sizeof(DigicUartState),
 
186
    .instance_init = digic_uart_init,
 
187
    .class_init = digic_uart_class_init,
 
188
};
 
189
 
 
190
static void digic_uart_register_types(void)
 
191
{
 
192
    type_register_static(&digic_uart_info);
 
193
}
 
194
 
 
195
type_init(digic_uart_register_types)