qemu

Форк
0
/
avr_usart.c 
321 строка · 8.9 Кб
1
/*
2
 * AVR USART
3
 *
4
 * Copyright (c) 2018 University of Kent
5
 * Author: Sarah Harris
6
 *
7
 * This library is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * This library is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with this library; if not, see
19
 * <http://www.gnu.org/licenses/lgpl-2.1.html>
20
 */
21

22
#include "qemu/osdep.h"
23
#include "hw/char/avr_usart.h"
24
#include "qemu/log.h"
25
#include "hw/irq.h"
26
#include "hw/qdev-properties.h"
27
#include "hw/qdev-properties-system.h"
28

29
static int avr_usart_can_receive(void *opaque)
30
{
31
    AVRUsartState *usart = opaque;
32

33
    if (usart->data_valid || !(usart->csrb & USART_CSRB_RXEN)) {
34
        return 0;
35
    }
36
    return 1;
37
}
38

39
static void avr_usart_receive(void *opaque, const uint8_t *buffer, int size)
40
{
41
    AVRUsartState *usart = opaque;
42
    assert(size == 1);
43
    assert(!usart->data_valid);
44
    usart->data = buffer[0];
45
    usart->data_valid = true;
46
    usart->csra |= USART_CSRA_RXC;
47
    if (usart->csrb & USART_CSRB_RXCIE) {
48
        qemu_set_irq(usart->rxc_irq, 1);
49
    }
50
}
51

52
static void update_char_mask(AVRUsartState *usart)
53
{
54
    uint8_t mode = ((usart->csrc & USART_CSRC_CSZ0) ? 1 : 0) |
55
        ((usart->csrc & USART_CSRC_CSZ1) ? 2 : 0) |
56
        ((usart->csrb & USART_CSRB_CSZ2) ? 4 : 0);
57
    switch (mode) {
58
    case 0:
59
        usart->char_mask = 0b11111;
60
        break;
61
    case 1:
62
        usart->char_mask = 0b111111;
63
        break;
64
    case 2:
65
        usart->char_mask = 0b1111111;
66
        break;
67
    case 3:
68
        usart->char_mask = 0b11111111;
69
        break;
70
    case 4:
71
        /* Fallthrough. */
72
    case 5:
73
        /* Fallthrough. */
74
    case 6:
75
        qemu_log_mask(
76
            LOG_GUEST_ERROR,
77
            "%s: Reserved character size 0x%x\n",
78
            __func__,
79
            mode);
80
        break;
81
    case 7:
82
        qemu_log_mask(
83
            LOG_GUEST_ERROR,
84
            "%s: Nine bit character size not supported (forcing eight)\n",
85
            __func__);
86
        usart->char_mask = 0b11111111;
87
        break;
88
    default:
89
        assert(0);
90
    }
91
}
92

93
static void avr_usart_reset(DeviceState *dev)
94
{
95
    AVRUsartState *usart = AVR_USART(dev);
96
    usart->data_valid = false;
97
    usart->csra = 0b00100000;
98
    usart->csrb = 0b00000000;
99
    usart->csrc = 0b00000110;
100
    usart->brrl = 0;
101
    usart->brrh = 0;
102
    update_char_mask(usart);
103
    qemu_set_irq(usart->rxc_irq, 0);
104
    qemu_set_irq(usart->txc_irq, 0);
105
    qemu_set_irq(usart->dre_irq, 0);
106
}
107

108
static uint64_t avr_usart_read(void *opaque, hwaddr addr, unsigned int size)
109
{
110
    AVRUsartState *usart = opaque;
111
    uint8_t data;
112
    assert(size == 1);
113

114
    if (!usart->enabled) {
115
        return 0;
116
    }
117

118
    switch (addr) {
119
    case USART_DR:
120
        if (!(usart->csrb & USART_CSRB_RXEN)) {
121
            /* Receiver disabled, ignore. */
122
            return 0;
123
        }
124
        if (usart->data_valid) {
125
            data = usart->data & usart->char_mask;
126
            usart->data_valid = false;
127
        } else {
128
            data = 0;
129
        }
130
        usart->csra &= 0xff ^ USART_CSRA_RXC;
131
        qemu_set_irq(usart->rxc_irq, 0);
132
        qemu_chr_fe_accept_input(&usart->chr);
133
        return data;
134
    case USART_CSRA:
135
        return usart->csra;
136
    case USART_CSRB:
137
        return usart->csrb;
138
    case USART_CSRC:
139
        return usart->csrc;
140
    case USART_BRRL:
141
        return usart->brrl;
142
    case USART_BRRH:
143
        return usart->brrh;
144
    default:
145
        qemu_log_mask(
146
            LOG_GUEST_ERROR,
147
            "%s: Bad offset 0x%"HWADDR_PRIx"\n",
148
            __func__,
149
            addr);
150
    }
151
    return 0;
152
}
153

154
static void avr_usart_write(void *opaque, hwaddr addr, uint64_t value,
155
                                unsigned int size)
156
{
157
    AVRUsartState *usart = opaque;
158
    uint8_t mask;
159
    uint8_t data;
160
    assert((value & 0xff) == value);
161
    assert(size == 1);
162

163
    if (!usart->enabled) {
164
        return;
165
    }
166

167
    switch (addr) {
168
    case USART_DR:
169
        if (!(usart->csrb & USART_CSRB_TXEN)) {
170
            /* Transmitter disabled, ignore. */
171
            return;
172
        }
173
        usart->csra |= USART_CSRA_TXC;
174
        usart->csra |= USART_CSRA_DRE;
175
        if (usart->csrb & USART_CSRB_TXCIE) {
176
            qemu_set_irq(usart->txc_irq, 1);
177
            usart->csra &= 0xff ^ USART_CSRA_TXC;
178
        }
179
        if (usart->csrb & USART_CSRB_DREIE) {
180
            qemu_set_irq(usart->dre_irq, 1);
181
        }
182
        data = value;
183
        qemu_chr_fe_write_all(&usart->chr, &data, 1);
184
        break;
185
    case USART_CSRA:
186
        mask = 0b01000011;
187
        /* Mask read-only bits. */
188
        value = (value & mask) | (usart->csra & (0xff ^ mask));
189
        usart->csra = value;
190
        if (value & USART_CSRA_TXC) {
191
            usart->csra ^= USART_CSRA_TXC;
192
            qemu_set_irq(usart->txc_irq, 0);
193
        }
194
        if (value & USART_CSRA_MPCM) {
195
            qemu_log_mask(
196
                LOG_GUEST_ERROR,
197
                "%s: MPCM not supported by USART\n",
198
                __func__);
199
        }
200
        break;
201
    case USART_CSRB:
202
        mask = 0b11111101;
203
        /* Mask read-only bits. */
204
        value = (value & mask) | (usart->csrb & (0xff ^ mask));
205
        usart->csrb = value;
206
        if (!(value & USART_CSRB_RXEN)) {
207
            /* Receiver disabled, flush input buffer. */
208
            usart->data_valid = false;
209
        }
210
        qemu_set_irq(usart->rxc_irq,
211
            ((value & USART_CSRB_RXCIE) &&
212
            (usart->csra & USART_CSRA_RXC)) ? 1 : 0);
213
        qemu_set_irq(usart->txc_irq,
214
            ((value & USART_CSRB_TXCIE) &&
215
            (usart->csra & USART_CSRA_TXC)) ? 1 : 0);
216
        qemu_set_irq(usart->dre_irq,
217
            ((value & USART_CSRB_DREIE) &&
218
            (usart->csra & USART_CSRA_DRE)) ? 1 : 0);
219
        update_char_mask(usart);
220
        break;
221
    case USART_CSRC:
222
        usart->csrc = value;
223
        if ((value & USART_CSRC_MSEL1) && (value & USART_CSRC_MSEL0)) {
224
            qemu_log_mask(
225
                LOG_GUEST_ERROR,
226
                "%s: SPI mode not supported by USART\n",
227
                __func__);
228
        }
229
        if ((value & USART_CSRC_MSEL1) && !(value & USART_CSRC_MSEL0)) {
230
            qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad USART mode\n", __func__);
231
        }
232
        if (!(value & USART_CSRC_PM1) && (value & USART_CSRC_PM0)) {
233
            qemu_log_mask(
234
                LOG_GUEST_ERROR,
235
                "%s: Bad USART parity mode\n",
236
                __func__);
237
        }
238
        update_char_mask(usart);
239
        break;
240
    case USART_BRRL:
241
        usart->brrl = value;
242
        break;
243
    case USART_BRRH:
244
        usart->brrh = value & 0b00001111;
245
        break;
246
    default:
247
        qemu_log_mask(
248
            LOG_GUEST_ERROR,
249
            "%s: Bad offset 0x%"HWADDR_PRIx"\n",
250
            __func__,
251
            addr);
252
    }
253
}
254

255
static const MemoryRegionOps avr_usart_ops = {
256
    .read = avr_usart_read,
257
    .write = avr_usart_write,
258
    .endianness = DEVICE_NATIVE_ENDIAN,
259
    .impl = {.min_access_size = 1, .max_access_size = 1}
260
};
261

262
static Property avr_usart_properties[] = {
263
    DEFINE_PROP_CHR("chardev", AVRUsartState, chr),
264
    DEFINE_PROP_END_OF_LIST(),
265
};
266

267
static void avr_usart_pr(void *opaque, int irq, int level)
268
{
269
    AVRUsartState *s = AVR_USART(opaque);
270

271
    s->enabled = !level;
272

273
    if (!s->enabled) {
274
        avr_usart_reset(DEVICE(s));
275
    }
276
}
277

278
static void avr_usart_init(Object *obj)
279
{
280
    AVRUsartState *s = AVR_USART(obj);
281
    sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->rxc_irq);
282
    sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->dre_irq);
283
    sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->txc_irq);
284
    memory_region_init_io(&s->mmio, obj, &avr_usart_ops, s, TYPE_AVR_USART, 7);
285
    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
286
    qdev_init_gpio_in(DEVICE(s), avr_usart_pr, 1);
287
    s->enabled = true;
288
}
289

290
static void avr_usart_realize(DeviceState *dev, Error **errp)
291
{
292
    AVRUsartState *s = AVR_USART(dev);
293
    qemu_chr_fe_set_handlers(&s->chr, avr_usart_can_receive,
294
                             avr_usart_receive, NULL, NULL,
295
                             s, NULL, true);
296
    avr_usart_reset(dev);
297
}
298

299
static void avr_usart_class_init(ObjectClass *klass, void *data)
300
{
301
    DeviceClass *dc = DEVICE_CLASS(klass);
302

303
    dc->reset = avr_usart_reset;
304
    device_class_set_props(dc, avr_usart_properties);
305
    dc->realize = avr_usart_realize;
306
}
307

308
static const TypeInfo avr_usart_info = {
309
    .name          = TYPE_AVR_USART,
310
    .parent        = TYPE_SYS_BUS_DEVICE,
311
    .instance_size = sizeof(AVRUsartState),
312
    .instance_init = avr_usart_init,
313
    .class_init    = avr_usart_class_init,
314
};
315

316
static void avr_usart_register_types(void)
317
{
318
    type_register_static(&avr_usart_info);
319
}
320

321
type_init(avr_usart_register_types)
322

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.