Statistics
| Branch: | Revision:

root / hw / etraxfs_ser.c @ 8da3ff18

History | View | Annotate | Download (5.7 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

    
30
#define D(x)
31

    
32
#define RW_TR_CTRL     0x00
33
#define RW_TR_DMA_EN   0x04
34
#define RW_REC_CTRL    0x08
35
#define RW_DOUT        0x1c
36
#define RS_STAT_DIN    0x20
37
#define R_STAT_DIN     0x24
38
#define RW_INTR_MASK   0x2c
39
#define RW_ACK_INTR    0x30
40
#define R_INTR         0x34
41
#define R_MASKED_INTR  0x38
42

    
43
#define STAT_DAV     16
44
#define STAT_TR_IDLE 22
45
#define STAT_TR_RDY  24
46

    
47
struct etrax_serial_t
48
{
49
        CPUState *env;
50
        CharDriverState *chr;
51
        qemu_irq *irq;
52

    
53
        int pending_tx;
54

    
55
        /* Control registers.  */
56
        uint32_t rw_tr_ctrl;
57
        uint32_t rw_tr_dma_en;
58
        uint32_t rw_rec_ctrl;
59
        uint32_t rs_stat_din;
60
        uint32_t r_stat_din;
61
        uint32_t rw_intr_mask;
62
        uint32_t rw_ack_intr;
63
        uint32_t r_intr;
64
        uint32_t r_masked_intr;
65
};
66

    
67
static void ser_update_irq(struct etrax_serial_t *s)
68
{
69
        uint32_t o_irq = s->r_masked_intr;
70

    
71
        s->r_intr &= ~(s->rw_ack_intr);
72
        s->r_masked_intr = s->r_intr & s->rw_intr_mask;
73

    
74
        if (o_irq != s->r_masked_intr) {
75
                D(printf("irq_mask=%x r_intr=%x rmi=%x airq=%x \n", 
76
                         s->rw_intr_mask, s->r_intr, 
77
                         s->r_masked_intr, s->rw_ack_intr));
78
                if (s->r_masked_intr)
79
                        qemu_irq_raise(s->irq[0]);
80
                else
81
                        qemu_irq_lower(s->irq[0]);
82
        }
83
        s->rw_ack_intr = 0;
84
}
85

    
86

    
87
static uint32_t ser_readb (void *opaque, target_phys_addr_t addr)
88
{
89
        D(CPUState *env = opaque);
90
        D(printf ("%s %x\n", __func__, addr));
91
        return 0;
92
}
93

    
94
static uint32_t ser_readl (void *opaque, target_phys_addr_t addr)
95
{
96
        struct etrax_serial_t *s = opaque;
97
        D(CPUState *env = s->env);
98
        uint32_t r = 0;
99

    
100
        switch (addr & 0xfff)
101
        {
102
                case RW_TR_CTRL:
103
                        r = s->rw_tr_ctrl;
104
                        break;
105
                case RW_TR_DMA_EN:
106
                        r = s->rw_tr_dma_en;
107
                        break;
108
                case RS_STAT_DIN:
109
                        r = s->rs_stat_din;
110
                        /* clear dav.  */
111
                        s->rs_stat_din &= ~(1 << STAT_DAV);
112
                        break;
113
                case R_STAT_DIN:
114
                        r = s->rs_stat_din;
115
                        break;
116
                case RW_ACK_INTR:
117
                        D(printf("load rw_ack_intr=%x\n", s->rw_ack_intr));
118
                        r = s->rw_ack_intr;
119
                        break;
120
                case RW_INTR_MASK:
121
                        r = s->rw_intr_mask;
122
                        break;
123
                case R_INTR:
124
                        D(printf("load r_intr=%x\n", s->r_intr));
125
                        r = s->r_intr;
126
                        break;
127
                case R_MASKED_INTR:
128
                        D(printf("load r_maked_intr=%x\n", s->r_masked_intr));
129
                        r = s->r_masked_intr;
130
                        break;
131

    
132
                default:
133
                        D(printf ("%s %x\n", __func__, addr));
134
                        break;
135
        }
136
        return r;
137
}
138

    
139
static void
140
ser_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
141
{
142
        D(struct etrax_serial_t *s = opaque);
143
        D(CPUState *env = s->env);
144
         D(printf ("%s %x %x\n", __func__, addr, value));
145
}
146
static void
147
ser_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
148
{
149
        struct etrax_serial_t *s = opaque;
150
        unsigned char ch = value;
151
        D(CPUState *env = s->env);
152

    
153
        switch (addr & 0xfff)
154
        {
155
                case RW_TR_CTRL:
156
                        D(printf("rw_tr_ctrl=%x\n", value));
157
                        s->rw_tr_ctrl = value;
158
                        break;
159
                case RW_TR_DMA_EN:
160
                        D(printf("rw_tr_dma_en=%x\n", value));
161
                        s->rw_tr_dma_en = value;
162
                        break;
163
                case RW_DOUT:
164
                        qemu_chr_write(s->chr, &ch, 1);
165
                        s->r_intr |= 1;
166
                        s->pending_tx = 1;
167
                        break;
168
                case RW_ACK_INTR:
169
                        D(printf("rw_ack_intr=%x\n", value));
170
                        s->rw_ack_intr = value;
171
                        if (s->pending_tx && (s->rw_ack_intr & 1)) {
172
                                s->r_intr |= 1;
173
                                s->pending_tx = 0;
174
                                s->rw_ack_intr &= ~1;
175
                        }
176
                        break;
177
                case RW_INTR_MASK:
178
                        D(printf("r_intr_mask=%x\n", value));
179
                        s->rw_intr_mask = value;
180
                        break;
181
                default:
182
                        D(printf ("%s %x %x\n",  __func__, addr, value));
183
                        break;
184
        }
185
        ser_update_irq(s);
186
}
187

    
188
static CPUReadMemoryFunc *ser_read[] = {
189
        &ser_readb,
190
        &ser_readb,
191
        &ser_readl,
192
};
193

    
194
static CPUWriteMemoryFunc *ser_write[] = {
195
        &ser_writeb,
196
        &ser_writeb,
197
        &ser_writel,
198
};
199

    
200
static void serial_receive(void *opaque, const uint8_t *buf, int size)
201
{
202
        struct etrax_serial_t *s = opaque;
203

    
204
        s->r_intr |= 8;
205
        s->rs_stat_din &= ~0xff;
206
        s->rs_stat_din |= (buf[0] & 0xff);
207
        s->rs_stat_din |= (1 << STAT_DAV); /* dav.  */
208
        ser_update_irq(s);
209
}
210

    
211
static int serial_can_receive(void *opaque)
212
{
213
        struct etrax_serial_t *s = opaque;
214
        int r;
215

    
216
        /* Is the receiver enabled?  */
217
        r = s->rw_rec_ctrl & 1;
218

    
219
        /* Pending rx data?  */
220
        r |= !(s->r_intr & 8);
221
        return r;
222
}
223

    
224
static void serial_event(void *opaque, int event)
225
{
226

    
227
}
228

    
229
void etraxfs_ser_init(CPUState *env, qemu_irq *irq, CharDriverState *chr,
230
                      target_phys_addr_t base)
231
{
232
        struct etrax_serial_t *s;
233
        int ser_regs;
234

    
235
        s = qemu_mallocz(sizeof *s);
236
        if (!s)
237
                return;
238

    
239
        s->env = env;
240
        s->irq = irq;
241
        s->chr = chr;
242

    
243
        /* transmitter begins ready and idle.  */
244
        s->rs_stat_din |= (1 << STAT_TR_RDY);
245
        s->rs_stat_din |= (1 << STAT_TR_IDLE);
246

    
247
        qemu_chr_add_handlers(chr, serial_can_receive, serial_receive,
248
                              serial_event, s);
249

    
250
        ser_regs = cpu_register_io_memory(0, ser_read, ser_write, s);
251
        cpu_register_physical_memory (base, 0x3c, ser_regs);
252
}