/[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 30 - (show annotations)
Mon Oct 8 16:20:40 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 9666 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1325 2006/08/15 15:38:37 debug Exp $
20060723	More Transputer instructions (pfix, nfix, opr, mint, ldl, ldlp,
		eqc, rev, ajw, stl, stlf, sthf, sub, ldnl, ldnlp, ldpi, move,
		wcnt, add, bcnt).
		Adding more SPARC instructions (andcc, addcc, bl, rdpr).
		Progress on the igsfb framebuffer used by NetBSD/netwinder.
		Enabling 8-bit fills in dev_fb.
		NetBSD/netwinder 3.0.1 can now run from a disk image :-)
20060724	Cleanup/performance fix for 64-bit virtual translation table
		updates (by removing the "timestamp" stuff). A full NetBSD/pmax
		3.0.1 install for R4400 has dropped from 667 seconds to 584 :)
		Fixing the igsfb "almost vga" color (it is 24-bit, not 18-bit).
		Adding some MIPS instruction combinations (3*lw, and 3*addu).
		The 8048 keyboard now turns off interrupt enable between the
		KBR_ACK and the KBR_RSTDONE, to work better with Linux 2.6.
		Not causing PPC DEC interrupts if PPC_NO_DEC is set for a
		specific CPU; NetBSD/bebox gets slightly further than before.
		Adding some more SPARC instructions: branches, udiv.
20060725	Refreshing dev_pckbc.c a little.
		Cleanups for the SH emulation mode, and adding the first
		"compact" (16-bit) instructions: various simple movs, nop,
		shll, stc, or, ldc.
20060726	Adding dummy "pcn" (AMD PCnet NIC) PCI glue.
20060727	Various cleanups; removing stuff from cpu.h, such as
		running_translated (not really meaningful anymore), and
		page flags (breaking into the debugger clears all translations
		anyway).
		Minor MIPS instruction combination updates.
20060807	Expanding the 3*sw and 3*lw MIPS instruction combinations to
		work with 2* and 4* too, resulting in a minor performance gain.
		Implementing a usleep hack for the RM52xx/MIPS32/MIPS64 "wait"
		instruction (when emulating 1 cpu).
20060808	Experimenting with some more MIPS instruction combinations.
		Implementing support for showing a (hardcoded 12x22) text
		cursor in igsfb.
20060809	Simplifying the NetBSD/evbmips (Malta) install instructions
		somewhat (by using a NetBSD/pmax ramdisk install kernel).
20060812	Experimenting more with the MIPS 'wait' instruction.
		PCI configuration register writes can now be handled, which
		allow PCI IDE controllers to work with NetBSD/Malta 3.0.1 and
		NetBSD/cobalt 3.0.1. (Previously only NetBSD 2.1 worked.)
20060813	Updating dev_gt.c based on numbers from Alec Voropay, to enable
		Linux 2.6 to use PCI on Malta.
		Continuing on Algor interrupt stuff.
20060814	Adding support for routing ISA interrupts to two different
		interrupts, making it possible to run NetBSD/algor :-)
20060814-15	Testing for the release.

==============  RELEASE 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