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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 5 - (hide annotations)
Mon Oct 8 16:18:06 2007 UTC (16 years, 8 months ago) by dpavlin
File MIME type: text/plain
File size: 9868 byte(s)
0.3.2
1 dpavlin 4 /*
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