~jderose/ubuntu/raring/qemu/vde-again

« back to all changes in this revision

Viewing changes to hw/sh_serial.c

  • Committer: Bazaar Package Importer
  • Author(s): Aurelien Jarno, Aurelien Jarno
  • Date: 2008-08-25 04:38:35 UTC
  • mfrom: (1.1.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20080825043835-8e3tftavy8bujdch
Tags: 0.9.1-6
[ Aurelien Jarno ]
* debian/control: 
  - Update list of supported targets (Closes: bug#488339).
* debian/qemu-make-debian-root:
  - Use mktemp instead of $$ to create temporary directories (Closes: 
    bug#496394).
* debian/links:
  - Add missing links to manpages.

Show diffs side-by-side

added added

removed removed

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