Statistics
| Branch: | Revision:

root / hw / etraxfs_ser.c @ 4af39611

History | View | Annotate | Download (4.5 kB)

1 83fa1010 ths
/*
2 83fa1010 ths
 * QEMU ETRAX System Emulator
3 83fa1010 ths
 *
4 83fa1010 ths
 * Copyright (c) 2007 Edgar E. Iglesias, Axis Communications AB.
5 83fa1010 ths
 *
6 83fa1010 ths
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 83fa1010 ths
 * of this software and associated documentation files (the "Software"), to deal
8 83fa1010 ths
 * in the Software without restriction, including without limitation the rights
9 83fa1010 ths
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 83fa1010 ths
 * copies of the Software, and to permit persons to whom the Software is
11 83fa1010 ths
 * furnished to do so, subject to the following conditions:
12 83fa1010 ths
 *
13 83fa1010 ths
 * The above copyright notice and this permission notice shall be included in
14 83fa1010 ths
 * all copies or substantial portions of the Software.
15 83fa1010 ths
 *
16 83fa1010 ths
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 83fa1010 ths
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 83fa1010 ths
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 83fa1010 ths
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 83fa1010 ths
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 83fa1010 ths
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 83fa1010 ths
 * THE SOFTWARE.
23 83fa1010 ths
 */
24 83fa1010 ths
25 83fa1010 ths
#include <stdio.h>
26 83fa1010 ths
#include <ctype.h>
27 87ecb68b pbrook
#include "hw.h"
28 f062058f edgar_igl
#include "qemu-char.h"
29 cc53adbc edgar_igl
#include "etraxfs.h"
30 83fa1010 ths
31 bbaf29c7 edgar_igl
#define D(x)
32 bbaf29c7 edgar_igl
33 72af9170 Edgar E. Iglesias
#define RW_TR_CTRL     (0x00 / 4)
34 72af9170 Edgar E. Iglesias
#define RW_TR_DMA_EN   (0x04 / 4)
35 72af9170 Edgar E. Iglesias
#define RW_REC_CTRL    (0x08 / 4)
36 72af9170 Edgar E. Iglesias
#define RW_DOUT        (0x1c / 4)
37 72af9170 Edgar E. Iglesias
#define RS_STAT_DIN    (0x20 / 4)
38 72af9170 Edgar E. Iglesias
#define R_STAT_DIN     (0x24 / 4)
39 72af9170 Edgar E. Iglesias
#define RW_INTR_MASK   (0x2c / 4)
40 72af9170 Edgar E. Iglesias
#define RW_ACK_INTR    (0x30 / 4)
41 72af9170 Edgar E. Iglesias
#define R_INTR         (0x34 / 4)
42 72af9170 Edgar E. Iglesias
#define R_MASKED_INTR  (0x38 / 4)
43 72af9170 Edgar E. Iglesias
#define R_MAX          (0x3c / 4)
44 83fa1010 ths
45 f062058f edgar_igl
#define STAT_DAV     16
46 f062058f edgar_igl
#define STAT_TR_IDLE 22
47 f062058f edgar_igl
#define STAT_TR_RDY  24
48 f062058f edgar_igl
49 f2964260 Edgar E. Iglesias
struct etrax_serial
50 83fa1010 ths
{
51 f062058f edgar_igl
        CPUState *env;
52 f062058f edgar_igl
        CharDriverState *chr;
53 f062058f edgar_igl
        qemu_irq *irq;
54 f062058f edgar_igl
55 72af9170 Edgar E. Iglesias
        /* This pending thing is a hack.  */
56 f062058f edgar_igl
        int pending_tx;
57 f062058f edgar_igl
58 f062058f edgar_igl
        /* Control registers.  */
59 72af9170 Edgar E. Iglesias
        uint32_t regs[R_MAX];
60 f062058f edgar_igl
};
61 f062058f edgar_igl
62 f2964260 Edgar E. Iglesias
static void ser_update_irq(struct etrax_serial *s)
63 f062058f edgar_igl
{
64 72af9170 Edgar E. Iglesias
        s->regs[R_INTR] &= ~(s->regs[RW_ACK_INTR]);
65 72af9170 Edgar E. Iglesias
        s->regs[R_MASKED_INTR] = s->regs[R_INTR] & s->regs[RW_INTR_MASK];
66 72af9170 Edgar E. Iglesias
67 72af9170 Edgar E. Iglesias
        qemu_set_irq(s->irq[0], !!s->regs[R_MASKED_INTR]);
68 72af9170 Edgar E. Iglesias
        s->regs[RW_ACK_INTR] = 0;
69 83fa1010 ths
}
70 f062058f edgar_igl
71 83fa1010 ths
static uint32_t ser_readl (void *opaque, target_phys_addr_t addr)
72 83fa1010 ths
{
73 f2964260 Edgar E. Iglesias
        struct etrax_serial *s = opaque;
74 f062058f edgar_igl
        D(CPUState *env = s->env);
75 83fa1010 ths
        uint32_t r = 0;
76 83fa1010 ths
77 72af9170 Edgar E. Iglesias
        addr >>= 2;
78 0db74b07 edgar_igl
        switch (addr)
79 83fa1010 ths
        {
80 83fa1010 ths
                case R_STAT_DIN:
81 72af9170 Edgar E. Iglesias
                        r = s->regs[RS_STAT_DIN];
82 f062058f edgar_igl
                        break;
83 72af9170 Edgar E. Iglesias
                case RS_STAT_DIN:
84 72af9170 Edgar E. Iglesias
                        r = s->regs[addr];
85 72af9170 Edgar E. Iglesias
                        /* Read side-effect: clear dav.  */
86 72af9170 Edgar E. Iglesias
                        s->regs[addr] &= ~(1 << STAT_DAV);
87 83fa1010 ths
                        break;
88 83fa1010 ths
                default:
89 72af9170 Edgar E. Iglesias
                        r = s->regs[addr];
90 72af9170 Edgar E. Iglesias
                        D(printf ("%s %x=%x\n", __func__, addr, r));
91 83fa1010 ths
                        break;
92 83fa1010 ths
        }
93 83fa1010 ths
        return r;
94 83fa1010 ths
}
95 83fa1010 ths
96 83fa1010 ths
static void
97 83fa1010 ths
ser_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
98 83fa1010 ths
{
99 f2964260 Edgar E. Iglesias
        struct etrax_serial *s = opaque;
100 f062058f edgar_igl
        unsigned char ch = value;
101 f062058f edgar_igl
        D(CPUState *env = s->env);
102 83fa1010 ths
103 72af9170 Edgar E. Iglesias
        D(printf ("%s %x %x\n",  __func__, addr, value));
104 72af9170 Edgar E. Iglesias
        addr >>= 2;
105 0db74b07 edgar_igl
        switch (addr)
106 83fa1010 ths
        {
107 83fa1010 ths
                case RW_DOUT:
108 f062058f edgar_igl
                        qemu_chr_write(s->chr, &ch, 1);
109 72af9170 Edgar E. Iglesias
                        s->regs[R_INTR] |= 1;
110 f062058f edgar_igl
                        s->pending_tx = 1;
111 72af9170 Edgar E. Iglesias
                        s->regs[addr] = value;
112 f062058f edgar_igl
                        break;
113 f062058f edgar_igl
                case RW_ACK_INTR:
114 72af9170 Edgar E. Iglesias
                        s->regs[addr] = value;
115 72af9170 Edgar E. Iglesias
                        if (s->pending_tx && (s->regs[addr] & 1)) {
116 72af9170 Edgar E. Iglesias
                                s->regs[R_INTR] |= 1;
117 f062058f edgar_igl
                                s->pending_tx = 0;
118 72af9170 Edgar E. Iglesias
                                s->regs[addr] &= ~1;
119 f062058f edgar_igl
                        }
120 f062058f edgar_igl
                        break;
121 83fa1010 ths
                default:
122 72af9170 Edgar E. Iglesias
                        s->regs[addr] = value;
123 83fa1010 ths
                        break;
124 83fa1010 ths
        }
125 f062058f edgar_igl
        ser_update_irq(s);
126 83fa1010 ths
}
127 83fa1010 ths
128 83fa1010 ths
static CPUReadMemoryFunc *ser_read[] = {
129 4ad804df Edgar E. Iglesias
        NULL, NULL,
130 ca87d03b edgar_igl
        &ser_readl,
131 83fa1010 ths
};
132 83fa1010 ths
133 83fa1010 ths
static CPUWriteMemoryFunc *ser_write[] = {
134 4ad804df Edgar E. Iglesias
        NULL, NULL,
135 ca87d03b edgar_igl
        &ser_writel,
136 83fa1010 ths
};
137 83fa1010 ths
138 f062058f edgar_igl
static void serial_receive(void *opaque, const uint8_t *buf, int size)
139 83fa1010 ths
{
140 f2964260 Edgar E. Iglesias
        struct etrax_serial *s = opaque;
141 f062058f edgar_igl
142 72af9170 Edgar E. Iglesias
        s->regs[R_INTR] |= 8;
143 72af9170 Edgar E. Iglesias
        s->regs[RS_STAT_DIN] &= ~0xff;
144 72af9170 Edgar E. Iglesias
        s->regs[RS_STAT_DIN] |= (buf[0] & 0xff);
145 72af9170 Edgar E. Iglesias
        s->regs[RS_STAT_DIN] |= (1 << STAT_DAV); /* dav.  */
146 f062058f edgar_igl
        ser_update_irq(s);
147 f062058f edgar_igl
}
148 f062058f edgar_igl
149 f062058f edgar_igl
static int serial_can_receive(void *opaque)
150 f062058f edgar_igl
{
151 f2964260 Edgar E. Iglesias
        struct etrax_serial *s = opaque;
152 f062058f edgar_igl
        int r;
153 f062058f edgar_igl
154 f062058f edgar_igl
        /* Is the receiver enabled?  */
155 72af9170 Edgar E. Iglesias
        r = s->regs[RW_REC_CTRL] & 1;
156 f062058f edgar_igl
157 f062058f edgar_igl
        /* Pending rx data?  */
158 72af9170 Edgar E. Iglesias
        r |= !(s->regs[R_INTR] & 8);
159 f062058f edgar_igl
        return r;
160 f062058f edgar_igl
}
161 f062058f edgar_igl
162 f062058f edgar_igl
static void serial_event(void *opaque, int event)
163 f062058f edgar_igl
{
164 f062058f edgar_igl
165 f062058f edgar_igl
}
166 f062058f edgar_igl
167 f062058f edgar_igl
void etraxfs_ser_init(CPUState *env, qemu_irq *irq, CharDriverState *chr,
168 f062058f edgar_igl
                      target_phys_addr_t base)
169 f062058f edgar_igl
{
170 f2964260 Edgar E. Iglesias
        struct etrax_serial *s;
171 83fa1010 ths
        int ser_regs;
172 f062058f edgar_igl
173 f062058f edgar_igl
        s = qemu_mallocz(sizeof *s);
174 f062058f edgar_igl
175 f062058f edgar_igl
        s->env = env;
176 f062058f edgar_igl
        s->irq = irq;
177 f062058f edgar_igl
        s->chr = chr;
178 f062058f edgar_igl
179 f062058f edgar_igl
        /* transmitter begins ready and idle.  */
180 72af9170 Edgar E. Iglesias
        s->regs[RS_STAT_DIN] |= (1 << STAT_TR_RDY);
181 72af9170 Edgar E. Iglesias
        s->regs[RS_STAT_DIN] |= (1 << STAT_TR_IDLE);
182 f062058f edgar_igl
183 f062058f edgar_igl
        qemu_chr_add_handlers(chr, serial_can_receive, serial_receive,
184 f062058f edgar_igl
                              serial_event, s);
185 f062058f edgar_igl
186 f062058f edgar_igl
        ser_regs = cpu_register_io_memory(0, ser_read, ser_write, s);
187 72af9170 Edgar E. Iglesias
        cpu_register_physical_memory (base, R_MAX * 4, ser_regs);
188 83fa1010 ths
}