Statistics
| Branch: | Revision:

root / hw / etraxfs_ser.c @ 72af9170

History | View | Annotate | Download (4.5 kB)

1
/*
2
 * QEMU ETRAX System Emulator
3
 *
4
 * Copyright (c) 2007 Edgar E. Iglesias, Axis Communications AB.
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 <stdio.h>
26
#include <ctype.h>
27
#include "hw.h"
28
#include "qemu-char.h"
29
#include "etraxfs.h"
30

    
31
#define D(x)
32

    
33
#define RW_TR_CTRL     (0x00 / 4)
34
#define RW_TR_DMA_EN   (0x04 / 4)
35
#define RW_REC_CTRL    (0x08 / 4)
36
#define RW_DOUT        (0x1c / 4)
37
#define RS_STAT_DIN    (0x20 / 4)
38
#define R_STAT_DIN     (0x24 / 4)
39
#define RW_INTR_MASK   (0x2c / 4)
40
#define RW_ACK_INTR    (0x30 / 4)
41
#define R_INTR         (0x34 / 4)
42
#define R_MASKED_INTR  (0x38 / 4)
43
#define R_MAX          (0x3c / 4)
44

    
45
#define STAT_DAV     16
46
#define STAT_TR_IDLE 22
47
#define STAT_TR_RDY  24
48

    
49
struct etrax_serial
50
{
51
        CPUState *env;
52
        CharDriverState *chr;
53
        qemu_irq *irq;
54

    
55
        /* This pending thing is a hack.  */
56
        int pending_tx;
57

    
58
        /* Control registers.  */
59
        uint32_t regs[R_MAX];
60
};
61

    
62
static void ser_update_irq(struct etrax_serial *s)
63
{
64
        s->regs[R_INTR] &= ~(s->regs[RW_ACK_INTR]);
65
        s->regs[R_MASKED_INTR] = s->regs[R_INTR] & s->regs[RW_INTR_MASK];
66

    
67
        qemu_set_irq(s->irq[0], !!s->regs[R_MASKED_INTR]);
68
        s->regs[RW_ACK_INTR] = 0;
69
}
70

    
71
static uint32_t ser_readl (void *opaque, target_phys_addr_t addr)
72
{
73
        struct etrax_serial *s = opaque;
74
        D(CPUState *env = s->env);
75
        uint32_t r = 0;
76

    
77
        addr >>= 2;
78
        switch (addr)
79
        {
80
                case R_STAT_DIN:
81
                        r = s->regs[RS_STAT_DIN];
82
                        break;
83
                case RS_STAT_DIN:
84
                        r = s->regs[addr];
85
                        /* Read side-effect: clear dav.  */
86
                        s->regs[addr] &= ~(1 << STAT_DAV);
87
                        break;
88
                default:
89
                        r = s->regs[addr];
90
                        D(printf ("%s %x=%x\n", __func__, addr, r));
91
                        break;
92
        }
93
        return r;
94
}
95

    
96
static void
97
ser_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
98
{
99
        struct etrax_serial *s = opaque;
100
        unsigned char ch = value;
101
        D(CPUState *env = s->env);
102

    
103
        D(printf ("%s %x %x\n",  __func__, addr, value));
104
        addr >>= 2;
105
        switch (addr)
106
        {
107
                case RW_DOUT:
108
                        qemu_chr_write(s->chr, &ch, 1);
109
                        s->regs[R_INTR] |= 1;
110
                        s->pending_tx = 1;
111
                        s->regs[addr] = value;
112
                        break;
113
                case RW_ACK_INTR:
114
                        s->regs[addr] = value;
115
                        if (s->pending_tx && (s->regs[addr] & 1)) {
116
                                s->regs[R_INTR] |= 1;
117
                                s->pending_tx = 0;
118
                                s->regs[addr] &= ~1;
119
                        }
120
                        break;
121
                default:
122
                        s->regs[addr] = value;
123
                        break;
124
        }
125
        ser_update_irq(s);
126
}
127

    
128
static CPUReadMemoryFunc *ser_read[] = {
129
        NULL, NULL,
130
        &ser_readl,
131
};
132

    
133
static CPUWriteMemoryFunc *ser_write[] = {
134
        NULL, NULL,
135
        &ser_writel,
136
};
137

    
138
static void serial_receive(void *opaque, const uint8_t *buf, int size)
139
{
140
        struct etrax_serial *s = opaque;
141

    
142
        s->regs[R_INTR] |= 8;
143
        s->regs[RS_STAT_DIN] &= ~0xff;
144
        s->regs[RS_STAT_DIN] |= (buf[0] & 0xff);
145
        s->regs[RS_STAT_DIN] |= (1 << STAT_DAV); /* dav.  */
146
        ser_update_irq(s);
147
}
148

    
149
static int serial_can_receive(void *opaque)
150
{
151
        struct etrax_serial *s = opaque;
152
        int r;
153

    
154
        /* Is the receiver enabled?  */
155
        r = s->regs[RW_REC_CTRL] & 1;
156

    
157
        /* Pending rx data?  */
158
        r |= !(s->regs[R_INTR] & 8);
159
        return r;
160
}
161

    
162
static void serial_event(void *opaque, int event)
163
{
164

    
165
}
166

    
167
void etraxfs_ser_init(CPUState *env, qemu_irq *irq, CharDriverState *chr,
168
                      target_phys_addr_t base)
169
{
170
        struct etrax_serial *s;
171
        int ser_regs;
172

    
173
        s = qemu_mallocz(sizeof *s);
174

    
175
        s->env = env;
176
        s->irq = irq;
177
        s->chr = chr;
178

    
179
        /* transmitter begins ready and idle.  */
180
        s->regs[RS_STAT_DIN] |= (1 << STAT_TR_RDY);
181
        s->regs[RS_STAT_DIN] |= (1 << STAT_TR_IDLE);
182

    
183
        qemu_chr_add_handlers(chr, serial_can_receive, serial_receive,
184
                              serial_event, s);
185

    
186
        ser_regs = cpu_register_io_memory(0, ser_read, ser_write, s);
187
        cpu_register_physical_memory (base, R_MAX * 4, ser_regs);
188
}