/[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 4 - (show annotations)
Mon Oct 8 16:18:00 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 9868 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.707 2005/04/27 16:37:33 debug Exp $
20050408	Some minor updates to the wdc. Linux now doesn't complain
		anymore if a disk is non-present.
20050409	Various minor fixes (a bintrans bug, and some other things).
		The wdc seems to work with Playstation2 emulation, but there
		is a _long_ annoying delay when disks are detected.
		Fixing a really important bintrans bug (when devices and RAM
		are mixed within 4KB pages), which was triggered with
		NetBSD/playstation2 kernels.
20050410	Adding a dummy dev_ps2_ether (just so that NetBSD doesn't
		complain as much during bootup).
		Symbols starting with '$' are now ignored.
		Renaming dev_ps2_ohci.c to dev_ohci.c, etc.
20050411	Moving the bintrans-cache-isolation check from cpu_mips.c to
		cpu_mips_coproc.c. (I thought this would give a speedup, but
		it's not noticable.)
		Better playstation2 sbus interrupt code.
		Skip ahead many ticks if the count register is read manually.
		(This increases the speed of delay-loops that simply read
		the count register.)
20050412	Updates to the playstation2 timer/interrupt code.
		Some other minor updates.
20050413	NetBSD/cobalt runs from a disk image :-) including userland;
		updating the documentation on how to install NetBSD/cobalt
		using NetBSD/pmax (!).
		Some minor bintrans updates (no real speed improvement) and
		other minor updates (playstation2 now uses the -o options).
20050414	Adding a dummy x86 (and AMD64) mode.
20050415	Adding some (32-bit and 16-bit) x86 instructions.
		Adding some initial support for non-SCSI, non-IDE floppy
		images. (The x86 mode can boot from these, more or less.)
		Moving the devices/ and include/ directories to src/devices/
		and src/include/, respectively.
20050416	Continuing on the x86 stuff. (Adding pc_bios.c and some simple
		support for software interrupts in 16-bit mode.)
20050417	Ripping out most of the x86 instruction decoding stuff, trying
		to rewrite it in a cleaner way.
		Disabling some of the least working CPU families in the
		configure script (sparc, x86, alpha, hppa), so that they are
		not enabled by default.
20050418	Trying to fix the bug which caused problems when turning on
		and off bintrans interactively, by flushing the bintrans cache
		whenever bintrans is manually (re)enabled.
20050419	Adding the 'lswi' ppc instruction.
		Minor updates to the x86 instruction decoding.
20050420	Renaming x86 register name indices from R_xx to X86_R_xx (this
		makes building on Tru64 nicer).
20050422	Adding a check for duplicate MIPS TLB entries on tlbwr/tlbwi.
20050427	Adding screenshots to guestoses.html.
		Some minor fixes and testing for the next release.

==============  RELEASE 0.3.2  ==============


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