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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10 - (show annotations)
Mon Oct 8 16:18:27 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 9906 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.815 2005/06/27 23:04:35 debug Exp $
20050617	Experimenting some more with netbooting OpenBSD/sgi. Adding
		a hack which allows emulated ethernet networks to be
		distributed across multiple emulator processes.
20050618	Minor updates (documentation, dummy YAMON emulation, etc).
20050620	strcpy/strcat -> strlcpy/strlcat updates.
		Some more progress on evbmips (Malta).
20050621	Adding a section to doc/configfiles.html about ethernet
		emulation across multiple hosts.
		Beginning the work on the ARM translation engine (using the
		dynamic-but-not-binary translation method).
		Fixing a bintrans bug: 0x9fc00000 should always be treated as
		PROM area, just as 0xbfc00000 is.
		Minor progress on Malta emulation (the PCI-ISA bus).
20050622	NetBSD/evbmips can now be installed (using another emulated
		machine) and run (including userland and so on). :-)
		Spliting up the bintrans haddr_entry field into two (one for
		read, one for write). Probably not much of a speed increase,
		though.
		Updating some NetBSD 2.0 -> 2.0.2 in the documentation.
20050623	Minor updates (documentation, the TODO file, etc).
		gzipped kernels are now always automagically gunzipped when
		loaded.
20050624	Adding a dummy Playstation Portable (PSP) mode, just barely
		enough to run Hello World (in weird colors :-).
		Removing the -b command line option; old bintrans is enabled
		by default instead. It makes more sense.
		Trying to finally fix the non-working performance measurement
		thing (instr/second etc).
20050625	Continuing on the essential basics for ARM emulation. Two
		instructions seem to work, a branch and a simple "mov". (The
		mov arguments are not correct yet.) Performance is definitely
		reasonable.
		Various other minor updates.
		Adding the ARM "bl" instruction.
		Adding support for combining multiple ARM instructions into one
		function call. ("mov" + "mov" is the only one implemented so
		far, but it seems to work.)
		Cleaning up some IP32 interrupt things (crime/mace); disabling
		the PS/2 keyboard controller on IP32, so that NetBSD/sgimips
		boots into userland again.
20050626	Finally! NetBSD/sgimips netboots. Adding instructions to
		doc/guestoses.html on how to set up an nfs server etc.
		Various other minor fixes.
		Playstation Portable ".pbp" files can now be used directly.
		(The ELF part of the .pbp is extracted transparently.)
		Converting some sprintf -> snprintf.
		Adding some more instructions to the ARM disassembler.
20050627	More ARM updates. Adding some simple ldr(b), str(b),
		cmps, and conditional branch instructions, enough to run
		a simple Hello World program.
		All ARM instructions are now inlined/generated for all possible
		condition codes.
		Adding add and sub, and more load/store instructions.
		Removing dummy files: cpu_alpha.c, cpu_hppa.c, and cpu_sparc.c.
		Some minor documentation updates; preparing for a 0.3.4
		release. Updating some URLs.

==============  RELEASE 0.3.4  ==============


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.12 2005/06/21 17:35:38 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 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