/[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 20 - (show annotations)
Mon Oct 8 16:19:23 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 9989 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1055 2005/11/25 22:48:36 debug Exp $
20051031	Adding disassembly support for more ARM instructions (clz,
		smul* etc), and adding a hack to support "new tiny" pages
		for StrongARM.
20051101	Minor documentation updates (NetBSD 2.0.2 -> 2.1, and OpenBSD
		3.7 -> 3.8, and lots of testing).
		Changing from 1-sector PIO mode 0 transfers to 128-sector PIO
		mode 3 (in dev_wdc).
		Various minor ARM dyntrans updates (pc-relative loads from
		within the same page as the instruction are now treated as
		constant "mov").
20051102	Re-enabling instruction combinations (they were accidentally
		disabled).
		Dyntrans TLB entries are now overwritten using a round-robin
		scheme instead of randomly. This increases performance.
		Fixing a typo in file.c (thanks to Chuan-Hua Chang for
		noticing it).
		Experimenting with adding ATAPI support to dev_wdc (to make
		emulated *BSD detect cdroms as cdroms, not harddisks).
20051104	Various minor updates.
20051105	Continuing on the ATAPI emulation. Seems to work well enough
		for a NetBSD/cats installation, but not OpenBSD/cats.
		Various other updates.
20051106	Modifying the -Y command line option to allow scaleup with
		certain graphic controllers (only dev_vga so far), not just
		scaledown.
		Some minor dyntrans cleanups.
20051107	Beginning a cleanup up the PCI subsystem (removing the
		read_register hack, etc).
20051108	Continuing the cleanup; splitting up some pci devices into a
		normal autodev device and some separate pci glue code.
20051109	Continuing on the PCI bus stuff; all old pci_*.c have been
		incorporated into normal devices and/or rewritten as glue code
		only, adding a dummy Intel 82371AB PIIX4 for Malta (not really
		tested yet).
		Minor pckbc fix so that Linux doesn't complain.
		Working on the DEC 21143 NIC (ethernet mac rom stuff mostly).
		Various other minor fixes.
20051110	Some more ARM dyntrans fine-tuning (e.g. some instruction
		combinations (cmps followed by conditional branch within the
		same page) and special cases for DPIs with regform when the
		shifter isn't used).
20051111	ARM dyntrans updates: O(n)->O(1) for just-mark-as-non-
		writable in the generic pc_to_pointers function, and some other
		minor hacks.
		Merging Cobalt and evbmips (Malta) ISA interrupt handling,
		and some minor fixes to allow Linux to accept harddisk irqs.
20051112	Minor device updates (pckbc, dec21143, lpt, ...), most
		importantly fixing the ALI M1543/M5229 so that harddisk irqs
		work with Linux/CATS.
20051113	Some more generalizations of the PCI subsystem.
		Finally took the time to add a hack for SCSI CDROM TOCs; this
		enables OpenBSD to use partition 'a' (as needed by the OpenBSD
		installer), and Windows NT's installer to get a bit further.
		Also fixing dev_wdc to allow Linux to detect ATAPI CDROMs.
		Continuing on the DEC 21143.
20051114	Minor ARM dyntrans tweaks; ARM cmps+branch optimization when
		comparing with 0, and generalizing the xchg instr. comb.
		Adding disassembly of ARM mrrc/mcrr and q{,d}{add,sub}.
20051115	Continuing on various PPC things (BATs, other address trans-
		lation things, various loads/stores, BeBox emulation, etc.).
		Beginning to work on PPC interrupt/exception support.
20051116	Factoring out some code which initializes legacy ISA devices
		from those machines that use them (bus_isa).
		Continuing on PPC interrupt/exception support.
20051117	Minor Malta fixes: RTC year offset = 80, disabling a speed hack
		which caused NetBSD to detect a too fast cpu, and adding a new
		hack to make Linux detect a faster cpu.
		Continuing on the Artesyn PM/PPC emulation mode.
		Adding an Algor emulation skeleton (P4032 and P5064);
		implementing some of the basics.
		Continuing on PPC emulation in general; usage of unimplemented
		SPRs is now easier to track, continuing on memory/exception
		related issues, etc.
20051118	More work on PPC emulation (tgpr0..3, exception handling,
		memory stuff, syscalls, etc.).
20051119	Changing the ARM dyntrans code to mostly use cpu->pc, and not
		necessarily use arm reg 15. Seems to work.
		Various PPC updates; continuing on the PReP emulation mode.
20051120	Adding a workaround/hack to dev_mc146818 to allow NetBSD/prep
		to detect the clock.
20051121	More cleanup of the PCI bus (memory and I/O bases, etc).
		Continuing on various PPC things (decrementer and timebase,
		WDCs on obio (on PReP) use irq 13, not 14/15).
20051122	Continuing on the CPC700 controller (interrupts etc) for PMPPC,
		and on PPC stuff in general.
		Finally! After some bug fixes to the virtual to physical addr
		translation, NetBSD/{prep,pmppc} 2.1 reach userland and are
		stable enough to be interacted with.
		More PCI updates; reverse-endian device access for PowerPC etc.
20051123	Generalizing the IEEE floating point subsystem (moving it out
		from src/cpus/cpu_mips_coproc.c into a new src/float_emul.c).
		Input via slave xterms was sometimes not really working; fixing
		this for ns16550, and a warning message is now displayed if
		multiple non-xterm consoles are active.
		Adding some PPC floating point support, etc.
		Various interrupt related updates (dev_wdc, _ns16550, _8259,
		and the isa32 common code in machine.c).
		NetBSD/prep can now be installed! :-) (Well, with some manual
		commands necessary before running sysinst.) Updating the
		documentation and various other things to reflect this.
20051124	Various minor documentation updates.
		Continuing the work on the DEC 21143 NIC.
20051125	LOTS of work on the 21143. Both OpenBSD and NetBSD work fine
		with it now, except that OpenBSD sometimes gives a time-out
		warning.
		Minor documentation updates.

==============  RELEASE 0.3.7  ==============


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.14 2005/11/13 00:14:08 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 if (writeflag == MEM_WRITE)
79 idata = memory_readmax64(cpu, data, len);
80
81 /* TODO */
82
83 switch (relative_addr) {
84 case IC_CONFIG0_READ: /* READ or SET */
85 if (writeflag == MEM_READ)
86 odata = d->config0;
87 else
88 d->config0 |= idata;
89 break;
90 case IC_CONFIG0_CLEAR:
91 if (writeflag == MEM_READ)
92 odata = d->config0;
93 else
94 d->config0 &= ~idata;
95 break;
96 case IC_CONFIG1_READ: /* READ or SET */
97 if (writeflag == MEM_READ)
98 odata = d->config1;
99 else
100 d->config1 |= idata;
101 break;
102 case IC_CONFIG1_CLEAR:
103 if (writeflag == MEM_READ)
104 odata = d->config1;
105 else
106 d->config1 &= ~idata;
107 break;
108 case IC_CONFIG2_READ: /* READ or SET */
109 if (writeflag == MEM_READ)
110 odata = d->config2;
111 else
112 d->config2 |= idata;
113 break;
114 case IC_CONFIG2_CLEAR: /* or IC_REQUEST0_INT */
115 if (writeflag == MEM_READ)
116 odata = d->request0_int;
117 else
118 d->config2 &= ~idata;
119 break;
120 case IC_SOURCE_READ: /* READ or SET */
121 if (writeflag == MEM_READ)
122 odata = d->source;
123 else
124 d->source |= idata;
125 break;
126 case IC_SOURCE_CLEAR: /* or IC_REQUEST1_INT */
127 if (writeflag == MEM_READ)
128 odata = d->request1_int;
129 else
130 d->source &= ~idata;
131 break;
132 case IC_ASSIGN_REQUEST_READ: /* READ or SET */
133 if (writeflag == MEM_READ)
134 odata = d->assign_request;
135 else
136 d->assign_request |= idata;
137 break;
138 case IC_ASSIGN_REQUEST_CLEAR:
139 if (writeflag == MEM_READ)
140 odata = d->assign_request;
141 else
142 d->assign_request &= ~idata;
143 break;
144 case IC_WAKEUP_READ: /* READ or SET */
145 if (writeflag == MEM_READ)
146 odata = d->wakeup;
147 else
148 d->wakeup |= idata;
149 break;
150 case IC_WAKEUP_CLEAR:
151 if (writeflag == MEM_READ)
152 odata = d->wakeup;
153 else
154 d->wakeup &= ~idata;
155 break;
156 case IC_MASK_READ: /* READ or SET */
157 if (writeflag == MEM_READ)
158 odata = d->mask;
159 else
160 d->mask |= idata;
161 break;
162 case IC_MASK_CLEAR:
163 if (writeflag == MEM_READ)
164 odata = d->mask;
165 else
166 d->mask &= ~idata;
167 break;
168 default:
169 if (writeflag == MEM_READ) {
170 debug("[ au1x00_ic%i: read from 0x%08lx: 0x%08x ]\n",
171 d->ic_nr, (long)relative_addr, odata);
172 } else {
173 debug("[ au1x00_ic%i: write to 0x%08lx: 0x%08x ]\n",
174 d->ic_nr, (long)relative_addr, idata);
175 }
176 }
177
178 if (writeflag == MEM_WRITE)
179 cpu_interrupt(cpu, 8 + 64);
180
181 if (writeflag == MEM_READ)
182 memory_writemax64(cpu, data, len, odata);
183
184 return 1;
185 }
186
187
188 /*
189 * dev_au1x00_uart_access():
190 *
191 * UART (Serial controllers).
192 */
193 int dev_au1x00_uart_access(struct cpu *cpu, struct memory *mem,
194 uint64_t relative_addr, unsigned char *data, size_t len,
195 int writeflag, void *extra)
196 {
197 struct au1x00_uart_data *d = extra;
198 uint64_t idata = 0, odata = 0;
199
200 if (writeflag == MEM_WRITE)
201 idata = memory_readmax64(cpu, data, len);
202
203 switch (relative_addr) {
204 case UART_RXDATA: /* 0x00 */
205 odata = console_readchar(d->console_handle);
206 break;
207 case UART_TXDATA: /* 0x04 */
208 console_putchar(d->console_handle, idata);
209 break;
210 case UART_INTERRUPT_ENABLE: /* 0x08 */
211 if (writeflag == MEM_READ)
212 odata = d->int_enable;
213 else
214 d->int_enable = idata;
215 break;
216 case UART_MODEM_CONTROL: /* 0x18 */
217 if (writeflag == MEM_READ)
218 odata = d->modem_control;
219 else
220 d->modem_control = idata;
221 break;
222 case UART_LINE_STATUS: /* 0x1c */
223 odata = ULS_TE + ULS_TFE;
224 if (console_charavail(d->console_handle))
225 odata |= ULS_DR;
226 break;
227 case UART_CLOCK_DIVIDER: /* 0x28 */
228 break;
229 default:
230 if (writeflag == MEM_READ) {
231 debug("[ au1x00_uart%i: read from 0x%08lx ]\n",
232 d->uart_nr, (long)relative_addr);
233 } else {
234 debug("[ au1x00_uart%i: write to 0x%08lx: 0x%08llx"
235 " ]\n", d->uart_nr, (long)relative_addr,
236 (long long)idata);
237 }
238 }
239
240 if (writeflag == MEM_READ)
241 memory_writemax64(cpu, data, len, odata);
242
243 return 1;
244 }
245
246
247 /*
248 * dev_au1x00_pc_tick():
249 *
250 * Cause periodic ticks. (The PC is supposed to give interrupts at
251 * 32768 Hz?)
252 */
253 void dev_au1x00_pc_tick(struct cpu *cpu, void *extra)
254 {
255 struct au1x00_pc_data *d = extra;
256
257 if (d->reg[PC_COUNTER_CONTROL/4] & CC_EN1)
258 cpu_interrupt(cpu, 8 + d->irq_nr);
259 }
260
261
262 /*
263 * dev_au1x00_pc_access():
264 *
265 * Programmable Counters.
266 */
267 int dev_au1x00_pc_access(struct cpu *cpu, struct memory *mem,
268 uint64_t relative_addr, unsigned char *data, size_t len,
269 int writeflag, void *extra)
270 {
271 struct au1x00_pc_data *d = extra;
272 uint64_t idata = 0, odata = 0;
273
274 if (writeflag == MEM_WRITE)
275 idata = memory_readmax64(cpu, data, len);
276
277 if (writeflag == MEM_READ)
278 odata = d->reg[relative_addr / sizeof(uint32_t)];
279 else
280 d->reg[relative_addr / sizeof(uint32_t)] = idata;
281
282 switch (relative_addr) {
283 default:
284 if (writeflag == MEM_READ) {
285 debug("[ au1x00_pc: read from 0x%08lx: 0x%08x ]\n",
286 (long)relative_addr, odata);
287 } else {
288 debug("[ au1x00_pc: write to 0x%08lx: 0x%08x ]\n",
289 (long)relative_addr, idata);
290 }
291 }
292
293 if (writeflag == MEM_READ)
294 memory_writemax64(cpu, data, len, odata);
295
296 return 1;
297 }
298
299
300 /*
301 * dev_au1x00_init():
302 */
303 struct au1x00_ic_data *dev_au1x00_init(struct machine *machine,
304 struct memory *mem)
305 {
306 struct au1x00_ic_data *d_ic0;
307 struct au1x00_ic_data *d_ic1;
308 struct au1x00_uart_data *d0;
309 struct au1x00_uart_data *d1;
310 struct au1x00_uart_data *d2;
311 struct au1x00_uart_data *d3;
312 struct au1x00_pc_data *d_pc;
313
314 d_ic0 = malloc(sizeof(struct au1x00_ic_data));
315 d_ic1 = malloc(sizeof(struct au1x00_ic_data));
316 d0 = malloc(sizeof(struct au1x00_uart_data));
317 d1 = malloc(sizeof(struct au1x00_uart_data));
318 d2 = malloc(sizeof(struct au1x00_uart_data));
319 d3 = malloc(sizeof(struct au1x00_uart_data));
320 d_pc = malloc(sizeof(struct au1x00_pc_data));
321
322 if (d0 == NULL || d1 == NULL || d2 == NULL ||
323 d3 == NULL || d_pc == NULL || d_ic0 == NULL
324 || d_ic1 == NULL) {
325 fprintf(stderr, "out of memory\n");
326 exit(1);
327 }
328 memset(d_ic0, 0, sizeof(struct au1x00_ic_data));
329 memset(d_ic1, 0, sizeof(struct au1x00_ic_data));
330 memset(d0, 0, sizeof(struct au1x00_uart_data));
331 memset(d1, 0, sizeof(struct au1x00_uart_data));
332 memset(d2, 0, sizeof(struct au1x00_uart_data));
333 memset(d3, 0, sizeof(struct au1x00_uart_data));
334 memset(d_pc, 0, sizeof(struct au1x00_pc_data));
335
336 d_ic0->ic_nr = 0;
337 d_ic1->ic_nr = 1;
338
339 d0->uart_nr = 0; d0->irq_nr = 0;
340 d1->uart_nr = 1; d1->irq_nr = 1;
341 d2->uart_nr = 2; d2->irq_nr = 2;
342 d3->uart_nr = 3; d3->irq_nr = 3;
343
344 d0->console_handle = console_start_slave(machine, "AU1x00 port 0");
345 d1->console_handle = console_start_slave(machine, "AU1x00 port 1");
346 d2->console_handle = console_start_slave(machine, "AU1x00 port 2");
347 d3->console_handle = console_start_slave(machine, "AU1x00 port 3");
348
349 d_pc->irq_nr = 14;
350
351 memory_device_register(mem, "au1x00_ic0",
352 IC0_BASE, 0x100, dev_au1x00_ic_access, d_ic0, DM_DEFAULT, NULL);
353 memory_device_register(mem, "au1x00_ic1",
354 IC1_BASE, 0x100, dev_au1x00_ic_access, d_ic1, DM_DEFAULT, NULL);
355
356 memory_device_register(mem, "au1x00_uart0", UART0_BASE, UART_SIZE,
357 dev_au1x00_uart_access, d0, DM_DEFAULT, NULL);
358 memory_device_register(mem, "au1x00_uart1", UART1_BASE, UART_SIZE,
359 dev_au1x00_uart_access, d1, DM_DEFAULT, NULL);
360 memory_device_register(mem, "au1x00_uart2", UART2_BASE, UART_SIZE,
361 dev_au1x00_uart_access, d2, DM_DEFAULT, NULL);
362 memory_device_register(mem, "au1x00_uart3", UART3_BASE, UART_SIZE,
363 dev_au1x00_uart_access, d3, DM_DEFAULT, NULL);
364
365 memory_device_register(mem, "au1x00_pc", PC_BASE, PC_SIZE + 0x8,
366 dev_au1x00_pc_access, d_pc, DM_DEFAULT, NULL);
367 machine_add_tickfunction(machine, dev_au1x00_pc_tick, d_pc, 15);
368
369 return d_ic0;
370 }
371

  ViewVC Help
Powered by ViewVC 1.1.26