1:
2:
3:
4:
5:
6:
7:
8: #include "hw.h"
9: #include "mcf.h"
10: #include "qemu-char.h"
11:
12: typedef struct {
13: uint8_t mr[2];
14: uint8_t sr;
15: uint8_t isr;
16: uint8_t imr;
17: uint8_t bg1;
18: uint8_t bg2;
19: uint8_t fifo[4];
20: uint8_t tb;
21: int current_mr;
22: int fifo_len;
23: int tx_enabled;
24: int rx_enabled;
25: qemu_irq irq;
26: CharDriverState *chr;
27: } mcf_uart_state;
28:
29:
30: #define MCF_UART_RxRDY 0x01
31: #define MCF_UART_FFULL 0x02
32: #define MCF_UART_TxRDY 0x04
33: #define MCF_UART_TxEMP 0x08
34: #define MCF_UART_OE 0x10
35: #define MCF_UART_PE 0x20
36: #define MCF_UART_FE 0x40
37: #define MCF_UART_RB 0x80
38:
39:
40: #define MCF_UART_TxINT 0x01
41: #define MCF_UART_RxINT 0x02
42: #define MCF_UART_DBINT 0x04
43: #define MCF_UART_COSINT 0x80
44:
45:
46: #define MCF_UART_BC0 0x01
47: #define MCF_UART_BC1 0x02
48: #define MCF_UART_PT 0x04
49: #define MCF_UART_PM0 0x08
50: #define MCF_UART_PM1 0x10
51: #define MCF_UART_ERR 0x20
52: #define MCF_UART_RxIRQ 0x40
53: #define MCF_UART_RxRTS 0x80
54:
55: static void mcf_uart_update(mcf_uart_state *s)
56: {
57: s->isr &= ~(MCF_UART_TxINT | MCF_UART_RxINT);
58: if (s->sr & MCF_UART_TxRDY)
59: s->isr |= MCF_UART_TxINT;
60: if ((s->sr & ((s->mr[0] & MCF_UART_RxIRQ)
61: ? MCF_UART_FFULL : MCF_UART_RxRDY)) != 0)
62: s->isr |= MCF_UART_RxINT;
63:
64: qemu_set_irq(s->irq, (s->isr & s->imr) != 0);
65: }
66:
67: uint32_t mcf_uart_read(void *opaque, target_phys_addr_t addr)
68: {
69: mcf_uart_state *s = (mcf_uart_state *)opaque;
70: switch (addr & 0x3f) {
71: case 0x00:
72: return s->mr[s->current_mr];
73: case 0x04:
74: return s->sr;
75: case 0x0c:
76: {
77: uint8_t val;
78: int i;
79:
80: if (s->fifo_len == 0)
81: return 0;
82:
83: val = s->fifo[0];
84: s->fifo_len--;
85: for (i = 0; i < s->fifo_len; i++)
86: s->fifo[i] = s->fifo[i + 1];
87: s->sr &= ~MCF_UART_FFULL;
88: if (s->fifo_len == 0)
89: s->sr &= ~MCF_UART_RxRDY;
90: mcf_uart_update(s);
91: qemu_chr_accept_input(s->chr);
92: return val;
93: }
94: case 0x10:
95:
96: return 0;
97: case 0x14:
98: return s->isr;
99: case 0x18:
100: return s->bg1;
101: case 0x1c:
102: return s->bg2;
103: default:
104: return 0;
105: }
106: }
107:
108:
109: static void mcf_uart_do_tx(mcf_uart_state *s)
110: {
111: if (s->tx_enabled && (s->sr & MCF_UART_TxEMP) == 0) {
112: if (s->chr)
113: qemu_chr_write(s->chr, (unsigned char *)&s->tb, 1);
114: s->sr |= MCF_UART_TxEMP;
115: }
116: if (s->tx_enabled) {
117: s->sr |= MCF_UART_TxRDY;
118: } else {
119: s->sr &= ~MCF_UART_TxRDY;
120: }
121: }
122:
123: static void mcf_do_command(mcf_uart_state *s, uint8_t cmd)
124: {
125:
126: switch ((cmd >> 4) & 3) {
127: case 0:
128: break;
129: case 1:
130: s->current_mr = 0;
131: break;
132: case 2:
133: s->rx_enabled = 0;
134: s->fifo_len = 0;
135: s->sr &= ~(MCF_UART_RxRDY | MCF_UART_FFULL);
136: break;
137: case 3:
138: s->tx_enabled = 0;
139: s->sr |= MCF_UART_TxEMP;
140: s->sr &= ~MCF_UART_TxRDY;
141: break;
142: case 4:
143: break;
144: case 5:
145: s->isr &= ~MCF_UART_DBINT;
146: break;
147: case 6:
148: case 7:
149: break;
150: }
151:
152:
153: switch ((cmd >> 2) & 3) {
154: case 0:
155: break;
156: case 1:
157: s->tx_enabled = 1;
158: mcf_uart_do_tx(s);
159: break;
160: case 2:
161: s->tx_enabled = 0;
162: mcf_uart_do_tx(s);
163: break;
164: case 3:
165: fprintf(stderr, "mcf_uart: Bad TX command\n");
166: break;
167: }
168:
169:
170: switch (cmd & 3) {
171: case 0:
172: break;
173: case 1:
174: s->rx_enabled = 1;
175: break;
176: case 2:
177: s->rx_enabled = 0;
178: break;
179: case 3:
180: fprintf(stderr, "mcf_uart: Bad RX command\n");
181: break;
182: }
183: }
184:
185: void mcf_uart_write(void *opaque, target_phys_addr_t addr, uint32_t val)
186: {
187: mcf_uart_state *s = (mcf_uart_state *)opaque;
188: switch (addr & 0x3f) {
189: case 0x00:
190: s->mr[s->current_mr] = val;
191: s->current_mr = 1;
192: break;
193: case 0x04:
194:
195: break;
196: case 0x08:
197: mcf_do_command(s, val);
198: break;
199: case 0x0c:
200: s->sr &= ~MCF_UART_TxEMP;
201: s->tb = val;
202: mcf_uart_do_tx(s);
203: break;
204: case 0x10:
205:
206: break;
207: case 0x14:
208: s->imr = val;
209: break;
210: default:
211: break;
212: }
213: mcf_uart_update(s);
214: }
215:
216: static void mcf_uart_reset(mcf_uart_state *s)
217: {
218: s->fifo_len = 0;
219: s->mr[0] = 0;
220: s->mr[1] = 0;
221: s->sr = MCF_UART_TxEMP;
222: s->tx_enabled = 0;
223: s->rx_enabled = 0;
224: s->isr = 0;
225: s->imr = 0;
226: }
227:
228: static void mcf_uart_push_byte(mcf_uart_state *s, uint8_t data)
229: {
230:
231: if (s->fifo_len == 4)
232: s->fifo_len--;
233:
234: s->fifo[s->fifo_len] = data;
235: s->fifo_len++;
236: s->sr |= MCF_UART_RxRDY;
237: if (s->fifo_len == 4)
238: s->sr |= MCF_UART_FFULL;
239:
240: mcf_uart_update(s);
241: }
242:
243: static void mcf_uart_event(void *opaque, int event)
244: {
245: mcf_uart_state *s = (mcf_uart_state *)opaque;
246:
247: switch (event) {
248: case CHR_EVENT_BREAK:
249: s->isr |= MCF_UART_DBINT;
250: mcf_uart_push_byte(s, 0);
251: break;
252: default:
253: break;
254: }
255: }
256:
257: static int mcf_uart_can_receive(void *opaque)
258: {
259: mcf_uart_state *s = (mcf_uart_state *)opaque;
260:
261: return s->rx_enabled && (s->sr & MCF_UART_FFULL) == 0;
262: }
263:
264: static void mcf_uart_receive(void *opaque, const uint8_t *buf, int size)
265: {
266: mcf_uart_state *s = (mcf_uart_state *)opaque;
267:
268: mcf_uart_push_byte(s, buf[0]);
269: }
270:
271: void *mcf_uart_init(qemu_irq irq, CharDriverState *chr)
272: {
273: mcf_uart_state *s;
274:
275: s = qemu_mallocz(sizeof(mcf_uart_state));
276: s->chr = chr;
277: s->irq = irq;
278: if (chr) {
279: qemu_chr_add_handlers(chr, mcf_uart_can_receive, mcf_uart_receive,
280: mcf_uart_event, s);
281: }
282: mcf_uart_reset(s);
283: return s;
284: }
285:
286:
287: static CPUReadMemoryFunc *mcf_uart_readfn[] = {
288: mcf_uart_read,
289: mcf_uart_read,
290: mcf_uart_read
291: };
292:
293: static CPUWriteMemoryFunc *mcf_uart_writefn[] = {
294: mcf_uart_write,
295: mcf_uart_write,
296: mcf_uart_write
297: };
298:
299: void mcf_uart_mm_init(target_phys_addr_t base, qemu_irq irq,
300: CharDriverState *chr)
301: {
302: mcf_uart_state *s;
303: int iomemtype;
304:
305: s = mcf_uart_init(irq, chr);
306: iomemtype = cpu_register_io_memory(0, mcf_uart_readfn,
307: mcf_uart_writefn, s);
308: cpu_register_physical_memory(base, 0x40, iomemtype);
309: }