/[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

Annotation of /trunk/src/devices/dev_au1x00.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 30 - (hide 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 dpavlin 4 /*
2 dpavlin 22 * Copyright (C) 2004-2006 Anders Gavare. All rights reserved.
3 dpavlin 4 *
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 dpavlin 30 * $Id: dev_au1x00.c,v 1.18 2006/07/23 14:37:34 debug Exp $
29 dpavlin 4 *
30     * Au1x00 (eg Au1500) pseudo device. See aureg.h for bitfield details.
31     *
32 dpavlin 10 * Used in at least the MeshCube (Au1500) and on PB1000 (evbmips) boards.
33 dpavlin 4 *
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 dpavlin 22 int in_use;
56 dpavlin 4 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 dpavlin 22 DEVICE_ACCESS(au1x00_ic)
73 dpavlin 4 {
74     struct au1x00_ic_data *d = extra;
75     uint64_t idata = 0, odata = 0;
76    
77 dpavlin 18 if (writeflag == MEM_WRITE)
78     idata = memory_readmax64(cpu, data, len);
79 dpavlin 4
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 dpavlin 22 DEVICE_ACCESS(au1x00_uart)
193 dpavlin 4 {
194     struct au1x00_uart_data *d = extra;
195     uint64_t idata = 0, odata = 0;
196    
197 dpavlin 18 if (writeflag == MEM_WRITE)
198     idata = memory_readmax64(cpu, data, len);
199 dpavlin 4
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 dpavlin 30 DEVICE_TICK(au1x00_pc)
245 dpavlin 4 {
246     struct au1x00_pc_data *d = extra;
247    
248 dpavlin 30 /* Periodic ticks at 32768 Hz? TODO */
249    
250 dpavlin 4 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 dpavlin 22 DEVICE_ACCESS(au1x00_pc)
261 dpavlin 4 {
262     struct au1x00_pc_data *d = extra;
263     uint64_t idata = 0, odata = 0;
264    
265 dpavlin 18 if (writeflag == MEM_WRITE)
266     idata = memory_readmax64(cpu, data, len);
267 dpavlin 4
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 dpavlin 22 /* 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 dpavlin 4
345     d_pc->irq_nr = 14;
346    
347     memory_device_register(mem, "au1x00_ic0",
348 dpavlin 20 IC0_BASE, 0x100, dev_au1x00_ic_access, d_ic0, DM_DEFAULT, NULL);
349 dpavlin 4 memory_device_register(mem, "au1x00_ic1",
350 dpavlin 20 IC1_BASE, 0x100, dev_au1x00_ic_access, d_ic1, DM_DEFAULT, NULL);
351 dpavlin 4
352     memory_device_register(mem, "au1x00_uart0", UART0_BASE, UART_SIZE,
353 dpavlin 20 dev_au1x00_uart_access, d0, DM_DEFAULT, NULL);
354 dpavlin 4 memory_device_register(mem, "au1x00_uart1", UART1_BASE, UART_SIZE,
355 dpavlin 20 dev_au1x00_uart_access, d1, DM_DEFAULT, NULL);
356 dpavlin 4 memory_device_register(mem, "au1x00_uart2", UART2_BASE, UART_SIZE,
357 dpavlin 20 dev_au1x00_uart_access, d2, DM_DEFAULT, NULL);
358 dpavlin 4 memory_device_register(mem, "au1x00_uart3", UART3_BASE, UART_SIZE,
359 dpavlin 20 dev_au1x00_uart_access, d3, DM_DEFAULT, NULL);
360 dpavlin 4
361     memory_device_register(mem, "au1x00_pc", PC_BASE, PC_SIZE + 0x8,
362 dpavlin 20 dev_au1x00_pc_access, d_pc, DM_DEFAULT, NULL);
363 dpavlin 24 machine_add_tickfunction(machine, dev_au1x00_pc_tick, d_pc, 15, 0.0);
364 dpavlin 4
365     return d_ic0;
366     }
367    

  ViewVC Help
Powered by ViewVC 1.1.26