/[gxemul]/upstream/0.4.2/src/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.4.2/src/devices/dev_au1x00.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (show annotations)
Mon Oct 8 16:20:48 2007 UTC (16 years, 8 months ago) by dpavlin
File MIME type: text/plain
File size: 9666 byte(s)
0.4.2
1 /*
2 * Copyright (C) 2004-2006 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.18 2006/07/23 14:37:34 debug Exp $
29 *
30 * Au1x00 (eg Au1500) pseudo device. See aureg.h for bitfield details.
31 *
32 * Used in at least the MeshCube (Au1500) and on PB1000 (evbmips) boards.
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 int in_use;
56 uint32_t int_enable;
57 uint32_t modem_control;
58 };
59
60
61 struct au1x00_pc_data {
62 uint32_t reg[PC_SIZE/4 + 2];
63 int irq_nr;
64 };
65
66
67 /*
68 * dev_au1x00_ic_access():
69 *
70 * Interrupt Controller.
71 */
72 DEVICE_ACCESS(au1x00_ic)
73 {
74 struct au1x00_ic_data *d = extra;
75 uint64_t idata = 0, odata = 0;
76
77 if (writeflag == MEM_WRITE)
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 DEVICE_ACCESS(au1x00_uart)
193 {
194 struct au1x00_uart_data *d = extra;
195 uint64_t idata = 0, odata = 0;
196
197 if (writeflag == MEM_WRITE)
198 idata = memory_readmax64(cpu, data, len);
199
200 switch (relative_addr) {
201 case UART_RXDATA: /* 0x00 */
202 odata = console_readchar(d->console_handle);
203 break;
204 case UART_TXDATA: /* 0x04 */
205 console_putchar(d->console_handle, idata);
206 break;
207 case UART_INTERRUPT_ENABLE: /* 0x08 */
208 if (writeflag == MEM_READ)
209 odata = d->int_enable;
210 else
211 d->int_enable = idata;
212 break;
213 case UART_MODEM_CONTROL: /* 0x18 */
214 if (writeflag == MEM_READ)
215 odata = d->modem_control;
216 else
217 d->modem_control = idata;
218 break;
219 case UART_LINE_STATUS: /* 0x1c */
220 odata = ULS_TE + ULS_TFE;
221 if (console_charavail(d->console_handle))
222 odata |= ULS_DR;
223 break;
224 case UART_CLOCK_DIVIDER: /* 0x28 */
225 break;
226 default:
227 if (writeflag == MEM_READ) {
228 debug("[ au1x00_uart%i: read from 0x%08lx ]\n",
229 d->uart_nr, (long)relative_addr);
230 } else {
231 debug("[ au1x00_uart%i: write to 0x%08lx: 0x%08llx"
232 " ]\n", d->uart_nr, (long)relative_addr,
233 (long long)idata);
234 }
235 }
236
237 if (writeflag == MEM_READ)
238 memory_writemax64(cpu, data, len, odata);
239
240 return 1;
241 }
242
243
244 DEVICE_TICK(au1x00_pc)
245 {
246 struct au1x00_pc_data *d = extra;
247
248 /* Periodic ticks at 32768 Hz? TODO */
249
250 if (d->reg[PC_COUNTER_CONTROL/4] & CC_EN1)
251 cpu_interrupt(cpu, 8 + d->irq_nr);
252 }
253
254
255 /*
256 * dev_au1x00_pc_access():
257 *
258 * Programmable Counters.
259 */
260 DEVICE_ACCESS(au1x00_pc)
261 {
262 struct au1x00_pc_data *d = extra;
263 uint64_t idata = 0, odata = 0;
264
265 if (writeflag == MEM_WRITE)
266 idata = memory_readmax64(cpu, data, len);
267
268 if (writeflag == MEM_READ)
269 odata = d->reg[relative_addr / sizeof(uint32_t)];
270 else
271 d->reg[relative_addr / sizeof(uint32_t)] = idata;
272
273 switch (relative_addr) {
274 default:
275 if (writeflag == MEM_READ) {
276 debug("[ au1x00_pc: read from 0x%08lx: 0x%08x ]\n",
277 (long)relative_addr, odata);
278 } else {
279 debug("[ au1x00_pc: write to 0x%08lx: 0x%08x ]\n",
280 (long)relative_addr, idata);
281 }
282 }
283
284 if (writeflag == MEM_READ)
285 memory_writemax64(cpu, data, len, odata);
286
287 return 1;
288 }
289
290
291 /*
292 * dev_au1x00_init():
293 */
294 struct au1x00_ic_data *dev_au1x00_init(struct machine *machine,
295 struct memory *mem)
296 {
297 struct au1x00_ic_data *d_ic0;
298 struct au1x00_ic_data *d_ic1;
299 struct au1x00_uart_data *d0;
300 struct au1x00_uart_data *d1;
301 struct au1x00_uart_data *d2;
302 struct au1x00_uart_data *d3;
303 struct au1x00_pc_data *d_pc;
304
305 d_ic0 = malloc(sizeof(struct au1x00_ic_data));
306 d_ic1 = malloc(sizeof(struct au1x00_ic_data));
307 d0 = malloc(sizeof(struct au1x00_uart_data));
308 d1 = malloc(sizeof(struct au1x00_uart_data));
309 d2 = malloc(sizeof(struct au1x00_uart_data));
310 d3 = malloc(sizeof(struct au1x00_uart_data));
311 d_pc = malloc(sizeof(struct au1x00_pc_data));
312
313 if (d0 == NULL || d1 == NULL || d2 == NULL ||
314 d3 == NULL || d_pc == NULL || d_ic0 == NULL
315 || d_ic1 == NULL) {
316 fprintf(stderr, "out of memory\n");
317 exit(1);
318 }
319 memset(d_ic0, 0, sizeof(struct au1x00_ic_data));
320 memset(d_ic1, 0, sizeof(struct au1x00_ic_data));
321 memset(d0, 0, sizeof(struct au1x00_uart_data));
322 memset(d1, 0, sizeof(struct au1x00_uart_data));
323 memset(d2, 0, sizeof(struct au1x00_uart_data));
324 memset(d3, 0, sizeof(struct au1x00_uart_data));
325 memset(d_pc, 0, sizeof(struct au1x00_pc_data));
326
327 d_ic0->ic_nr = 0;
328 d_ic1->ic_nr = 1;
329
330 d0->uart_nr = 0; d0->irq_nr = 0;
331 d1->uart_nr = 1; d1->irq_nr = 1;
332 d2->uart_nr = 2; d2->irq_nr = 2;
333 d3->uart_nr = 3; d3->irq_nr = 3;
334
335 /* Only allow input on the first UART, by default: */
336 d0->console_handle = console_start_slave(machine, "AU1x00 port 0", 1);
337 d1->console_handle = console_start_slave(machine, "AU1x00 port 1", 0);
338 d2->console_handle = console_start_slave(machine, "AU1x00 port 2", 0);
339 d3->console_handle = console_start_slave(machine, "AU1x00 port 3", 0);
340 d0->in_use = 1;
341 d1->in_use = 0;
342 d2->in_use = 0;
343 d3->in_use = 0;
344
345 d_pc->irq_nr = 14;
346
347 memory_device_register(mem, "au1x00_ic0",
348 IC0_BASE, 0x100, dev_au1x00_ic_access, d_ic0, DM_DEFAULT, NULL);
349 memory_device_register(mem, "au1x00_ic1",
350 IC1_BASE, 0x100, dev_au1x00_ic_access, d_ic1, DM_DEFAULT, NULL);
351
352 memory_device_register(mem, "au1x00_uart0", UART0_BASE, UART_SIZE,
353 dev_au1x00_uart_access, d0, DM_DEFAULT, NULL);
354 memory_device_register(mem, "au1x00_uart1", UART1_BASE, UART_SIZE,
355 dev_au1x00_uart_access, d1, DM_DEFAULT, NULL);
356 memory_device_register(mem, "au1x00_uart2", UART2_BASE, UART_SIZE,
357 dev_au1x00_uart_access, d2, DM_DEFAULT, NULL);
358 memory_device_register(mem, "au1x00_uart3", UART3_BASE, UART_SIZE,
359 dev_au1x00_uart_access, d3, DM_DEFAULT, NULL);
360
361 memory_device_register(mem, "au1x00_pc", PC_BASE, PC_SIZE + 0x8,
362 dev_au1x00_pc_access, d_pc, DM_DEFAULT, NULL);
363 machine_add_tickfunction(machine, dev_au1x00_pc_tick, d_pc, 15, 0.0);
364
365 return d_ic0;
366 }
367

  ViewVC Help
Powered by ViewVC 1.1.26