|
|
1.1 root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.