/[gxemul]/upstream/0.3.1/devices/dev_au1x00.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /upstream/0.3.1/devices/dev_au1x00.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3 - (show annotations)
Mon Oct 8 16:17:52 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 9868 byte(s)
0.3.1
1 /*
2 * Copyright (C) 2004-2005 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: dev_au1x00.c,v 1.11 2005/02/21 09:37:43 debug Exp $
29 *
30 * Au1x00 (eg Au1500) pseudo device. See aureg.h for bitfield details.
31 *
32 * The MeshCube uses an Au1500 CPU.
33 *
34 * This is basically just a huge TODO. :-)
35 */
36
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40
41 #include "console.h"
42 #include "cpu.h"
43 #include "devices.h"
44 #include "machine.h"
45 #include "memory.h"
46 #include "misc.h"
47
48 #include "aureg.h"
49
50
51 struct au1x00_uart_data {
52 int console_handle;
53 int uart_nr;
54 int irq_nr;
55 uint32_t int_enable;
56 uint32_t modem_control;
57 };
58
59
60 struct au1x00_pc_data {
61 uint32_t reg[PC_SIZE/4 + 2];
62 int irq_nr;
63 };
64
65
66 /*
67 * dev_au1x00_ic_access():
68 *
69 * Interrupt Controller.
70 */
71 int dev_au1x00_ic_access(struct cpu *cpu, struct memory *mem,
72 uint64_t relative_addr, unsigned char *data, size_t len,
73 int writeflag, void *extra)
74 {
75 struct au1x00_ic_data *d = extra;
76 uint64_t idata = 0, odata = 0;
77
78 idata = memory_readmax64(cpu, data, len);
79
80 /* TODO */
81
82 switch (relative_addr) {
83 case IC_CONFIG0_READ: /* READ or SET */
84 if (writeflag == MEM_READ)
85 odata = d->config0;
86 else
87 d->config0 |= idata;
88 break;
89 case IC_CONFIG0_CLEAR:
90 if (writeflag == MEM_READ)
91 odata = d->config0;
92 else
93 d->config0 &= ~idata;
94 break;
95 case IC_CONFIG1_READ: /* READ or SET */
96 if (writeflag == MEM_READ)
97 odata = d->config1;
98 else
99 d->config1 |= idata;
100 break;
101 case IC_CONFIG1_CLEAR:
102 if (writeflag == MEM_READ)
103 odata = d->config1;
104 else
105 d->config1 &= ~idata;
106 break;
107 case IC_CONFIG2_READ: /* READ or SET */
108 if (writeflag == MEM_READ)
109 odata = d->config2;
110 else
111 d->config2 |= idata;
112 break;
113 case IC_CONFIG2_CLEAR: /* or IC_REQUEST0_INT */
114 if (writeflag == MEM_READ)
115 odata = d->request0_int;
116 else
117 d->config2 &= ~idata;
118 break;
119 case IC_SOURCE_READ: /* READ or SET */
120 if (writeflag == MEM_READ)
121 odata = d->source;
122 else
123 d->source |= idata;
124 break;
125 case IC_SOURCE_CLEAR: /* or IC_REQUEST1_INT */
126 if (writeflag == MEM_READ)
127 odata = d->request1_int;
128 else
129 d->source &= ~idata;
130 break;
131 case IC_ASSIGN_REQUEST_READ: /* READ or SET */
132 if (writeflag == MEM_READ)
133 odata = d->assign_request;
134 else
135 d->assign_request |= idata;
136 break;
137 case IC_ASSIGN_REQUEST_CLEAR:
138 if (writeflag == MEM_READ)
139 odata = d->assign_request;
140 else
141 d->assign_request &= ~idata;
142 break;
143 case IC_WAKEUP_READ: /* READ or SET */
144 if (writeflag == MEM_READ)
145 odata = d->wakeup;
146 else
147 d->wakeup |= idata;
148 break;
149 case IC_WAKEUP_CLEAR:
150 if (writeflag == MEM_READ)
151 odata = d->wakeup;
152 else
153 d->wakeup &= ~idata;
154 break;
155 case IC_MASK_READ: /* READ or SET */
156 if (writeflag == MEM_READ)
157 odata = d->mask;
158 else
159 d->mask |= idata;
160 break;
161 case IC_MASK_CLEAR:
162 if (writeflag == MEM_READ)
163 odata = d->mask;
164 else
165 d->mask &= ~idata;
166 break;
167 default:
168 if (writeflag == MEM_READ) {
169 debug("[ au1x00_ic%i: read from 0x%08lx: 0x%08x ]\n",
170 d->ic_nr, (long)relative_addr, odata);
171 } else {
172 debug("[ au1x00_ic%i: write to 0x%08lx: 0x%08x ]\n",
173 d->ic_nr, (long)relative_addr, idata);
174 }
175 }
176
177 if (writeflag == MEM_WRITE)
178 cpu_interrupt(cpu, 8 + 64);
179
180 if (writeflag == MEM_READ)
181 memory_writemax64(cpu, data, len, odata);
182
183 return 1;
184 }
185
186
187 /*
188 * dev_au1x00_uart_access():
189 *
190 * UART (Serial controllers).
191 */
192 int dev_au1x00_uart_access(struct cpu *cpu, struct memory *mem,
193 uint64_t relative_addr, unsigned char *data, size_t len,
194 int writeflag, void *extra)
195 {
196 struct au1x00_uart_data *d = extra;
197 uint64_t idata = 0, odata = 0;
198
199 idata = memory_readmax64(cpu, data, len);
200
201 switch (relative_addr) {
202 case UART_RXDATA: /* 0x00 */
203 odata = console_readchar(d->console_handle);
204 break;
205 case UART_TXDATA: /* 0x04 */
206 console_putchar(d->console_handle, idata);
207 break;
208 case UART_INTERRUPT_ENABLE: /* 0x08 */
209 if (writeflag == MEM_READ)
210 odata = d->int_enable;
211 else
212 d->int_enable = idata;
213 break;
214 case UART_MODEM_CONTROL: /* 0x18 */
215 if (writeflag == MEM_READ)
216 odata = d->modem_control;
217 else
218 d->modem_control = idata;
219 break;
220 case UART_LINE_STATUS: /* 0x1c */
221 odata = ULS_TE + ULS_TFE;
222 if (console_charavail(d->console_handle))
223 odata |= ULS_DR;
224 break;
225 case UART_CLOCK_DIVIDER: /* 0x28 */
226 break;
227 default:
228 if (writeflag == MEM_READ) {
229 debug("[ au1x00_uart%i: read from 0x%08lx ]\n",
230 d->uart_nr, (long)relative_addr);
231 } else {
232 debug("[ au1x00_uart%i: write to 0x%08lx: 0x%08llx"
233 " ]\n", d->uart_nr, (long)relative_addr,
234 (long long)idata);
235 }
236 }
237
238 if (writeflag == MEM_READ)
239 memory_writemax64(cpu, data, len, odata);
240
241 return 1;
242 }
243
244
245 /*
246 * dev_au1x00_pc_tick():
247 *
248 * Cause periodic ticks. (The PC is supposed to give interrupts at
249 * 32768 Hz?)
250 */
251 void dev_au1x00_pc_tick(struct cpu *cpu, void *extra)
252 {
253 struct au1x00_pc_data *d = extra;
254
255 if (d->reg[PC_COUNTER_CONTROL/4] & CC_EN1)
256 cpu_interrupt(cpu, 8 + d->irq_nr);
257 }
258
259
260 /*
261 * dev_au1x00_pc_access():
262 *
263 * Programmable Counters.
264 */
265 int dev_au1x00_pc_access(struct cpu *cpu, struct memory *mem,
266 uint64_t relative_addr, unsigned char *data, size_t len,
267 int writeflag, void *extra)
268 {
269 struct au1x00_pc_data *d = extra;
270 uint64_t idata = 0, odata = 0;
271
272 idata = memory_readmax64(cpu, data, len);
273
274 if (writeflag == MEM_READ)
275 odata = d->reg[relative_addr / sizeof(uint32_t)];
276 else
277 d->reg[relative_addr / sizeof(uint32_t)] = idata;
278
279 switch (relative_addr) {
280 default:
281 if (writeflag == MEM_READ) {
282 debug("[ au1x00_pc: read from 0x%08lx: 0x%08x ]\n",
283 (long)relative_addr, odata);
284 } else {
285 debug("[ au1x00_pc: write to 0x%08lx: 0x%08x ]\n",
286 (long)relative_addr, idata);
287 }
288 }
289
290 if (writeflag == MEM_READ)
291 memory_writemax64(cpu, data, len, odata);
292
293 return 1;
294 }
295
296
297 /*
298 * dev_au1x00_init():
299 */
300 struct au1x00_ic_data *dev_au1x00_init(struct machine *machine,
301 struct memory *mem)
302 {
303 struct au1x00_ic_data *d_ic0;
304 struct au1x00_ic_data *d_ic1;
305 struct au1x00_uart_data *d0;
306 struct au1x00_uart_data *d1;
307 struct au1x00_uart_data *d2;
308 struct au1x00_uart_data *d3;
309 struct au1x00_pc_data *d_pc;
310
311 d_ic0 = malloc(sizeof(struct au1x00_ic_data));
312 d_ic1 = malloc(sizeof(struct au1x00_ic_data));
313 d0 = malloc(sizeof(struct au1x00_uart_data));
314 d1 = malloc(sizeof(struct au1x00_uart_data));
315 d2 = malloc(sizeof(struct au1x00_uart_data));
316 d3 = malloc(sizeof(struct au1x00_uart_data));
317 d_pc = malloc(sizeof(struct au1x00_pc_data));
318
319 if (d0 == NULL || d1 == NULL || d2 == NULL ||
320 d3 == NULL || d_pc == NULL || d_ic0 == NULL
321 || d_ic1 == NULL) {
322 fprintf(stderr, "out of memory\n");
323 exit(1);
324 }
325 memset(d_ic0, 0, sizeof(struct au1x00_ic_data));
326 memset(d_ic1, 0, sizeof(struct au1x00_ic_data));
327 memset(d0, 0, sizeof(struct au1x00_uart_data));
328 memset(d1, 0, sizeof(struct au1x00_uart_data));
329 memset(d2, 0, sizeof(struct au1x00_uart_data));
330 memset(d3, 0, sizeof(struct au1x00_uart_data));
331 memset(d_pc, 0, sizeof(struct au1x00_pc_data));
332
333 d_ic0->ic_nr = 0;
334 d_ic1->ic_nr = 1;
335
336 d0->uart_nr = 0; d0->irq_nr = 0;
337 d1->uart_nr = 1; d1->irq_nr = 1;
338 d2->uart_nr = 2; d2->irq_nr = 2;
339 d3->uart_nr = 3; d3->irq_nr = 3;
340
341 d0->console_handle = console_start_slave(machine, "AU1x00 port 0");
342 d1->console_handle = console_start_slave(machine, "AU1x00 port 1");
343 d2->console_handle = console_start_slave(machine, "AU1x00 port 2");
344 d3->console_handle = console_start_slave(machine, "AU1x00 port 3");
345
346 d_pc->irq_nr = 14;
347
348 memory_device_register(mem, "au1x00_ic0",
349 IC0_BASE, 0x100, dev_au1x00_ic_access, d_ic0, MEM_DEFAULT, NULL);
350 memory_device_register(mem, "au1x00_ic1",
351 IC1_BASE, 0x100, dev_au1x00_ic_access, d_ic1, MEM_DEFAULT, NULL);
352
353 memory_device_register(mem, "au1x00_uart0", UART0_BASE, UART_SIZE,
354 dev_au1x00_uart_access, d0, MEM_DEFAULT, NULL);
355 memory_device_register(mem, "au1x00_uart1", UART1_BASE, UART_SIZE,
356 dev_au1x00_uart_access, d1, MEM_DEFAULT, NULL);
357 memory_device_register(mem, "au1x00_uart2", UART2_BASE, UART_SIZE,
358 dev_au1x00_uart_access, d2, MEM_DEFAULT, NULL);
359 memory_device_register(mem, "au1x00_uart3", UART3_BASE, UART_SIZE,
360 dev_au1x00_uart_access, d3, MEM_DEFAULT, NULL);
361
362 memory_device_register(mem, "au1x00_pc", PC_BASE, PC_SIZE + 0x8,
363 dev_au1x00_pc_access, d_pc, MEM_DEFAULT, NULL);
364 machine_add_tickfunction(machine, dev_au1x00_pc_tick, d_pc, 15);
365
366 return d_ic0;
367 }
368

  ViewVC Help
Powered by ViewVC 1.1.26