Statistics
| Branch: | Revision:

root / hw / sh_serial.c @ c701b35b

History | View | Annotate | Download (8.5 kB)

1 2f062c72 ths
/*
2 2f062c72 ths
 * QEMU SCI/SCIF serial port emulation
3 2f062c72 ths
 *
4 2f062c72 ths
 * Copyright (c) 2007 Magnus Damm
5 2f062c72 ths
 *
6 2f062c72 ths
 * Based on serial.c - QEMU 16450 UART emulation
7 2f062c72 ths
 * Copyright (c) 2003-2004 Fabrice Bellard
8 2f062c72 ths
 *
9 2f062c72 ths
 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 2f062c72 ths
 * of this software and associated documentation files (the "Software"), to deal
11 2f062c72 ths
 * in the Software without restriction, including without limitation the rights
12 2f062c72 ths
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 2f062c72 ths
 * copies of the Software, and to permit persons to whom the Software is
14 2f062c72 ths
 * furnished to do so, subject to the following conditions:
15 2f062c72 ths
 *
16 2f062c72 ths
 * The above copyright notice and this permission notice shall be included in
17 2f062c72 ths
 * all copies or substantial portions of the Software.
18 2f062c72 ths
 *
19 2f062c72 ths
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 2f062c72 ths
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 2f062c72 ths
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 2f062c72 ths
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 2f062c72 ths
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 2f062c72 ths
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 2f062c72 ths
 * THE SOFTWARE.
26 2f062c72 ths
 */
27 87ecb68b pbrook
#include "hw.h"
28 87ecb68b pbrook
#include "sh.h"
29 87ecb68b pbrook
#include "qemu-char.h"
30 2f062c72 ths
#include <assert.h>
31 2f062c72 ths
32 2f062c72 ths
//#define DEBUG_SERIAL
33 2f062c72 ths
34 2f062c72 ths
#define SH_SERIAL_FLAG_TEND (1 << 0)
35 2f062c72 ths
#define SH_SERIAL_FLAG_TDE  (1 << 1)
36 2f062c72 ths
#define SH_SERIAL_FLAG_RDF  (1 << 2)
37 2f062c72 ths
#define SH_SERIAL_FLAG_BRK  (1 << 3)
38 2f062c72 ths
#define SH_SERIAL_FLAG_DR   (1 << 4)
39 2f062c72 ths
40 2f062c72 ths
typedef struct {
41 2f062c72 ths
    uint8_t smr;
42 2f062c72 ths
    uint8_t brr;
43 2f062c72 ths
    uint8_t scr;
44 2f062c72 ths
    uint8_t dr; /* ftdr / tdr */
45 2f062c72 ths
    uint8_t sr; /* fsr / ssr */
46 2f062c72 ths
    uint16_t fcr;
47 2f062c72 ths
    uint8_t sptr;
48 2f062c72 ths
49 2f062c72 ths
    uint8_t rx_fifo[16]; /* frdr / rdr */
50 2f062c72 ths
    uint8_t rx_cnt;
51 2f062c72 ths
52 2f062c72 ths
    target_phys_addr_t base;
53 2f062c72 ths
    int freq;
54 2f062c72 ths
    int feat;
55 2f062c72 ths
    int flags;
56 2f062c72 ths
57 2f062c72 ths
    CharDriverState *chr;
58 bf5b7423 aurel32
59 bf5b7423 aurel32
    struct intc_source *eri;
60 bf5b7423 aurel32
    struct intc_source *rxi;
61 bf5b7423 aurel32
    struct intc_source *txi;
62 bf5b7423 aurel32
    struct intc_source *tei;
63 bf5b7423 aurel32
    struct intc_source *bri;
64 2f062c72 ths
} sh_serial_state;
65 2f062c72 ths
66 2f062c72 ths
static void sh_serial_ioport_write(void *opaque, uint32_t offs, uint32_t val)
67 2f062c72 ths
{
68 2f062c72 ths
    sh_serial_state *s = opaque;
69 2f062c72 ths
    unsigned char ch;
70 2f062c72 ths
71 2f062c72 ths
#ifdef DEBUG_SERIAL
72 2f062c72 ths
    printf("sh_serial: write base=0x%08lx offs=0x%02x val=0x%02x\n",
73 2f062c72 ths
           (unsigned long) s->base, offs, val);
74 2f062c72 ths
#endif
75 2f062c72 ths
    switch(offs) {
76 2f062c72 ths
    case 0x00: /* SMR */
77 2f062c72 ths
        s->smr = val & ((s->feat & SH_SERIAL_FEAT_SCIF) ? 0x7b : 0xff);
78 2f062c72 ths
        return;
79 2f062c72 ths
    case 0x04: /* BRR */
80 2f062c72 ths
        s->brr = val;
81 2f062c72 ths
        return;
82 2f062c72 ths
    case 0x08: /* SCR */
83 bf5b7423 aurel32
        s->scr = val & ((s->feat & SH_SERIAL_FEAT_SCIF) ? 0xfa : 0xff);
84 2f062c72 ths
        if (!(val & (1 << 5)))
85 2f062c72 ths
            s->flags |= SH_SERIAL_FLAG_TEND;
86 bf5b7423 aurel32
        if ((s->feat & SH_SERIAL_FEAT_SCIF) && s->txi) {
87 bf5b7423 aurel32
            if ((val & (1 << 7)) && !(s->txi->asserted))
88 bf5b7423 aurel32
                sh_intc_toggle_source(s->txi, 0, 1);
89 bf5b7423 aurel32
            else if (!(val & (1 << 7)) && s->txi->asserted)
90 bf5b7423 aurel32
                sh_intc_toggle_source(s->txi, 0, -1);
91 bf5b7423 aurel32
        }
92 2f062c72 ths
        return;
93 2f062c72 ths
    case 0x0c: /* FTDR / TDR */
94 2f062c72 ths
        if (s->chr) {
95 2f062c72 ths
            ch = val;
96 2f062c72 ths
            qemu_chr_write(s->chr, &ch, 1);
97 2f062c72 ths
        }
98 2f062c72 ths
        s->dr = val;
99 2f062c72 ths
        s->flags &= ~SH_SERIAL_FLAG_TDE;
100 2f062c72 ths
        return;
101 2f062c72 ths
#if 0
102 2f062c72 ths
    case 0x14: /* FRDR / RDR */
103 2f062c72 ths
        ret = 0;
104 2f062c72 ths
        break;
105 2f062c72 ths
#endif
106 2f062c72 ths
    }
107 2f062c72 ths
    if (s->feat & SH_SERIAL_FEAT_SCIF) {
108 2f062c72 ths
        switch(offs) {
109 2f062c72 ths
        case 0x10: /* FSR */
110 2f062c72 ths
            if (!(val & (1 << 6)))
111 2f062c72 ths
                s->flags &= ~SH_SERIAL_FLAG_TEND;
112 2f062c72 ths
            if (!(val & (1 << 5)))
113 2f062c72 ths
                s->flags &= ~SH_SERIAL_FLAG_TDE;
114 2f062c72 ths
            if (!(val & (1 << 4)))
115 2f062c72 ths
                s->flags &= ~SH_SERIAL_FLAG_BRK;
116 2f062c72 ths
            if (!(val & (1 << 1)))
117 2f062c72 ths
                s->flags &= ~SH_SERIAL_FLAG_RDF;
118 2f062c72 ths
            if (!(val & (1 << 0)))
119 2f062c72 ths
                s->flags &= ~SH_SERIAL_FLAG_DR;
120 2f062c72 ths
            return;
121 2f062c72 ths
        case 0x18: /* FCR */
122 2f062c72 ths
            s->fcr = val;
123 2f062c72 ths
            return;
124 2f062c72 ths
        case 0x20: /* SPTR */
125 2f062c72 ths
            s->sptr = val;
126 2f062c72 ths
            return;
127 2f062c72 ths
        case 0x24: /* LSR */
128 2f062c72 ths
            return;
129 2f062c72 ths
        }
130 2f062c72 ths
    }
131 2f062c72 ths
    else {
132 2f062c72 ths
#if 0
133 2f062c72 ths
        switch(offs) {
134 2f062c72 ths
        case 0x0c:
135 2f062c72 ths
            ret = s->dr;
136 2f062c72 ths
            break;
137 2f062c72 ths
        case 0x10:
138 2f062c72 ths
            ret = 0;
139 2f062c72 ths
            break;
140 2f062c72 ths
        case 0x1c:
141 2f062c72 ths
            ret = s->sptr;
142 2f062c72 ths
            break;
143 2f062c72 ths
        }
144 2f062c72 ths
#endif
145 2f062c72 ths
    }
146 2f062c72 ths
147 2f062c72 ths
    fprintf(stderr, "sh_serial: unsupported write to 0x%02x\n", offs);
148 2f062c72 ths
    assert(0);
149 2f062c72 ths
}
150 2f062c72 ths
151 2f062c72 ths
static uint32_t sh_serial_ioport_read(void *opaque, uint32_t offs)
152 2f062c72 ths
{
153 2f062c72 ths
    sh_serial_state *s = opaque;
154 2f062c72 ths
    uint32_t ret = ~0;
155 2f062c72 ths
156 2f062c72 ths
#if 0
157 2f062c72 ths
    switch(offs) {
158 2f062c72 ths
    case 0x00:
159 2f062c72 ths
        ret = s->smr;
160 2f062c72 ths
        break;
161 2f062c72 ths
    case 0x04:
162 2f062c72 ths
        ret = s->brr;
163 2f062c72 ths
        break;
164 2f062c72 ths
    case 0x08:
165 2f062c72 ths
        ret = s->scr;
166 2f062c72 ths
        break;
167 2f062c72 ths
    case 0x14:
168 2f062c72 ths
        ret = 0;
169 2f062c72 ths
        break;
170 2f062c72 ths
    }
171 2f062c72 ths
#endif
172 2f062c72 ths
    if (s->feat & SH_SERIAL_FEAT_SCIF) {
173 2f062c72 ths
        switch(offs) {
174 bf5b7423 aurel32
        case 0x00: /* SMR */
175 bf5b7423 aurel32
            ret = s->smr;
176 bf5b7423 aurel32
            break;
177 bf5b7423 aurel32
        case 0x08: /* SCR */
178 bf5b7423 aurel32
            ret = s->scr;
179 bf5b7423 aurel32
            break;
180 2f062c72 ths
        case 0x10: /* FSR */
181 2f062c72 ths
            ret = 0;
182 2f062c72 ths
            if (s->flags & SH_SERIAL_FLAG_TEND)
183 2f062c72 ths
                ret |= (1 << 6);
184 2f062c72 ths
            if (s->flags & SH_SERIAL_FLAG_TDE)
185 2f062c72 ths
                ret |= (1 << 5);
186 2f062c72 ths
            if (s->flags & SH_SERIAL_FLAG_BRK)
187 2f062c72 ths
                ret |= (1 << 4);
188 2f062c72 ths
            if (s->flags & SH_SERIAL_FLAG_RDF)
189 2f062c72 ths
                ret |= (1 << 1);
190 2f062c72 ths
            if (s->flags & SH_SERIAL_FLAG_DR)
191 2f062c72 ths
                ret |= (1 << 0);
192 2f062c72 ths
193 2f062c72 ths
            if (s->scr & (1 << 5))
194 2f062c72 ths
                s->flags |= SH_SERIAL_FLAG_TDE | SH_SERIAL_FLAG_TEND;
195 2f062c72 ths
196 2f062c72 ths
            break;
197 2f062c72 ths
#if 0
198 2f062c72 ths
        case 0x18:
199 2f062c72 ths
            ret = s->fcr;
200 2f062c72 ths
            break;
201 2f062c72 ths
#endif
202 2f062c72 ths
        case 0x1c:
203 2f062c72 ths
            ret = s->rx_cnt;
204 2f062c72 ths
            break;
205 2f062c72 ths
        case 0x20:
206 2f062c72 ths
            ret = s->sptr;
207 2f062c72 ths
            break;
208 2f062c72 ths
        case 0x24:
209 2f062c72 ths
            ret = 0;
210 2f062c72 ths
            break;
211 2f062c72 ths
        }
212 2f062c72 ths
    }
213 2f062c72 ths
    else {
214 2f062c72 ths
#if 0
215 2f062c72 ths
        switch(offs) {
216 2f062c72 ths
        case 0x0c:
217 2f062c72 ths
            ret = s->dr;
218 2f062c72 ths
            break;
219 2f062c72 ths
        case 0x10:
220 2f062c72 ths
            ret = 0;
221 2f062c72 ths
            break;
222 2f062c72 ths
        case 0x1c:
223 2f062c72 ths
            ret = s->sptr;
224 2f062c72 ths
            break;
225 2f062c72 ths
        }
226 2f062c72 ths
#endif
227 2f062c72 ths
    }
228 2f062c72 ths
#ifdef DEBUG_SERIAL
229 2f062c72 ths
    printf("sh_serial: read base=0x%08lx offs=0x%02x val=0x%x\n",
230 2f062c72 ths
           (unsigned long) s->base, offs, ret);
231 2f062c72 ths
#endif
232 2f062c72 ths
233 2f062c72 ths
    if (ret & ~((1 << 16) - 1)) {
234 2f062c72 ths
        fprintf(stderr, "sh_serial: unsupported read from 0x%02x\n", offs);
235 2f062c72 ths
        assert(0);
236 2f062c72 ths
    }
237 2f062c72 ths
238 2f062c72 ths
    return ret;
239 2f062c72 ths
}
240 2f062c72 ths
241 2f062c72 ths
static int sh_serial_can_receive(sh_serial_state *s)
242 2f062c72 ths
{
243 2f062c72 ths
    return 0;
244 2f062c72 ths
}
245 2f062c72 ths
246 2f062c72 ths
static void sh_serial_receive_byte(sh_serial_state *s, int ch)
247 2f062c72 ths
{
248 2f062c72 ths
}
249 2f062c72 ths
250 2f062c72 ths
static void sh_serial_receive_break(sh_serial_state *s)
251 2f062c72 ths
{
252 2f062c72 ths
}
253 2f062c72 ths
254 2f062c72 ths
static int sh_serial_can_receive1(void *opaque)
255 2f062c72 ths
{
256 2f062c72 ths
    sh_serial_state *s = opaque;
257 2f062c72 ths
    return sh_serial_can_receive(s);
258 2f062c72 ths
}
259 2f062c72 ths
260 2f062c72 ths
static void sh_serial_receive1(void *opaque, const uint8_t *buf, int size)
261 2f062c72 ths
{
262 2f062c72 ths
    sh_serial_state *s = opaque;
263 2f062c72 ths
    sh_serial_receive_byte(s, buf[0]);
264 2f062c72 ths
}
265 2f062c72 ths
266 2f062c72 ths
static void sh_serial_event(void *opaque, int event)
267 2f062c72 ths
{
268 2f062c72 ths
    sh_serial_state *s = opaque;
269 2f062c72 ths
    if (event == CHR_EVENT_BREAK)
270 2f062c72 ths
        sh_serial_receive_break(s);
271 2f062c72 ths
}
272 2f062c72 ths
273 9596ebb7 pbrook
static uint32_t sh_serial_read (void *opaque, target_phys_addr_t addr)
274 2f062c72 ths
{
275 2f062c72 ths
    sh_serial_state *s = opaque;
276 2f062c72 ths
    return sh_serial_ioport_read(s, addr - s->base);
277 2f062c72 ths
}
278 2f062c72 ths
279 9596ebb7 pbrook
static void sh_serial_write (void *opaque,
280 9596ebb7 pbrook
                             target_phys_addr_t addr, uint32_t value)
281 2f062c72 ths
{
282 2f062c72 ths
    sh_serial_state *s = opaque;
283 2f062c72 ths
    sh_serial_ioport_write(s, addr - s->base, value);
284 2f062c72 ths
}
285 2f062c72 ths
286 2f062c72 ths
static CPUReadMemoryFunc *sh_serial_readfn[] = {
287 2f062c72 ths
    &sh_serial_read,
288 2f062c72 ths
    &sh_serial_read,
289 2f062c72 ths
    &sh_serial_read,
290 2f062c72 ths
};
291 2f062c72 ths
292 2f062c72 ths
static CPUWriteMemoryFunc *sh_serial_writefn[] = {
293 2f062c72 ths
    &sh_serial_write,
294 2f062c72 ths
    &sh_serial_write,
295 2f062c72 ths
    &sh_serial_write,
296 2f062c72 ths
};
297 2f062c72 ths
298 2f062c72 ths
void sh_serial_init (target_phys_addr_t base, int feat,
299 bf5b7423 aurel32
                     uint32_t freq, CharDriverState *chr,
300 bf5b7423 aurel32
                     struct intc_source *eri_source,
301 bf5b7423 aurel32
                     struct intc_source *rxi_source,
302 bf5b7423 aurel32
                     struct intc_source *txi_source,
303 bf5b7423 aurel32
                     struct intc_source *tei_source,
304 bf5b7423 aurel32
                     struct intc_source *bri_source)
305 2f062c72 ths
{
306 2f062c72 ths
    sh_serial_state *s;
307 2f062c72 ths
    int s_io_memory;
308 2f062c72 ths
309 2f062c72 ths
    s = qemu_mallocz(sizeof(sh_serial_state));
310 2f062c72 ths
    if (!s)
311 2f062c72 ths
        return;
312 2f062c72 ths
313 2f062c72 ths
    s->base = base;
314 2f062c72 ths
    s->feat = feat;
315 2f062c72 ths
    s->flags = SH_SERIAL_FLAG_TEND | SH_SERIAL_FLAG_TDE;
316 2f062c72 ths
317 2f062c72 ths
    s->smr = 0;
318 2f062c72 ths
    s->brr = 0xff;
319 b7d35e65 balrog
    s->scr = 1 << 5; /* pretend that TX is enabled so early printk works */
320 2f062c72 ths
    s->sptr = 0;
321 2f062c72 ths
322 2f062c72 ths
    if (feat & SH_SERIAL_FEAT_SCIF) {
323 2f062c72 ths
        s->fcr = 0;
324 2f062c72 ths
    }
325 2f062c72 ths
    else {
326 2f062c72 ths
        s->dr = 0xff;
327 2f062c72 ths
    }
328 2f062c72 ths
329 2f062c72 ths
    s->rx_cnt = 0;
330 2f062c72 ths
331 2f062c72 ths
    s_io_memory = cpu_register_io_memory(0, sh_serial_readfn,
332 2f062c72 ths
                                         sh_serial_writefn, s);
333 2f062c72 ths
    cpu_register_physical_memory(base, 0x28, s_io_memory);
334 2f062c72 ths
335 2f062c72 ths
    s->chr = chr;
336 2f062c72 ths
337 2f062c72 ths
    if (chr)
338 2f062c72 ths
        qemu_chr_add_handlers(chr, sh_serial_can_receive1, sh_serial_receive1,
339 2f062c72 ths
                              sh_serial_event, s);
340 bf5b7423 aurel32
341 bf5b7423 aurel32
    s->eri = eri_source;
342 bf5b7423 aurel32
    s->rxi = rxi_source;
343 bf5b7423 aurel32
    s->txi = txi_source;
344 bf5b7423 aurel32
    s->tei = tei_source;
345 bf5b7423 aurel32
    s->bri = bri_source;
346 2f062c72 ths
}