/[gxemul]/upstream/0.4.1/src/devices/dev_ram.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.4.1/src/devices/dev_ram.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 29 - (hide annotations)
Mon Oct 8 16:20:32 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 5435 byte(s)
0.4.1
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 22 * $Id: dev_ram.c,v 1.21 2006/01/01 13:17:17 debug Exp $
29 dpavlin 4 *
30 dpavlin 18 * A generic RAM (memory) device. Can also be used to mirror/alias another
31 dpavlin 4 * part of RAM.
32     */
33    
34     #include <stdio.h>
35     #include <stdlib.h>
36     #include <string.h>
37     #include <sys/types.h>
38     #include <sys/mman.h>
39    
40     #include "cpu.h"
41     #include "devices.h"
42 dpavlin 18 #include "machine.h"
43 dpavlin 4 #include "memory.h"
44     #include "misc.h"
45    
46    
47     /* #define RAM_DEBUG */
48    
49     struct ram_data {
50     int mode;
51     uint64_t otheraddress;
52    
53 dpavlin 18 /* If mode = DEV_RAM_MIRROR: */
54     uint64_t offset;
55    
56 dpavlin 4 /* If mode = DEV_RAM_RAM: */
57     unsigned char *data;
58     uint64_t length;
59     };
60    
61    
62     /*
63     * dev_ram_access():
64     */
65 dpavlin 22 DEVICE_ACCESS(ram)
66 dpavlin 4 {
67     struct ram_data *d = extra;
68    
69     #ifdef RAM_DEBUG
70     if (writeflag==MEM_READ) {
71     debug("[ ram: read from 0x%x, len=%i ]\n",
72     (int)relative_addr, (int)len);
73     } else {
74     int i;
75     debug("[ ram: write to 0x%x:", (int)relative_addr);
76     for (i=0; i<len; i++)
77     debug(" %02x", data[i]);
78     debug(" (len=%i) ]\n", len);
79     }
80     #endif
81    
82     switch (d->mode) {
83     case DEV_RAM_MIRROR:
84     /* TODO: how about caches? */
85     return cpu->memory_rw(cpu, mem,
86     d->otheraddress + relative_addr, data, len,
87     writeflag, PHYSICAL);
88     case DEV_RAM_RAM:
89     if (writeflag == MEM_WRITE)
90     memcpy(&d->data[relative_addr], data, len);
91     else
92     memcpy(data, &d->data[relative_addr], len);
93     break;
94     default:
95     fatal("dev_ram_access(): unknown mode %i\n", d->mode);
96     exit(1);
97     }
98    
99     return 1;
100     }
101    
102    
103     /*
104     * dev_ram_init():
105 dpavlin 18 *
106     * Initializes a RAM or mirror device. Things get a bit complicated because
107     * of dyntrans (i.e. mirrored memory ranges should be entered into the
108     * translation arrays just as normal memory and other devices are).
109 dpavlin 4 */
110 dpavlin 18 void dev_ram_init(struct machine *machine, uint64_t baseaddr, uint64_t length,
111 dpavlin 4 int mode, uint64_t otheraddress)
112     {
113     struct ram_data *d;
114 dpavlin 20 int flags = DM_DEFAULT, points_to_ram = 1;
115 dpavlin 4
116     d = malloc(sizeof(struct ram_data));
117     if (d == NULL) {
118     fprintf(stderr, "out of memory\n");
119     exit(1);
120     }
121    
122     memset(d, 0, sizeof(struct ram_data));
123    
124 dpavlin 18 if (mode & DEV_RAM_MIGHT_POINT_TO_DEVICES) {
125     mode &= ~DEV_RAM_MIGHT_POINT_TO_DEVICES;
126     points_to_ram = 0;
127     }
128    
129 dpavlin 4 d->mode = mode;
130     d->otheraddress = otheraddress;
131    
132     switch (d->mode) {
133 dpavlin 18
134 dpavlin 4 case DEV_RAM_MIRROR:
135 dpavlin 18 /*
136     * Calculate the amount that the mirror memory is offset from
137     * the real (physical) memory. This is used in src/memory_rw.c
138 dpavlin 20 * with dyntrans accesses if DM_EMULATED_RAM is set.
139 dpavlin 18 */
140     d->offset = baseaddr - otheraddress;
141    
142     /* Aligned RAM? Then it works with dyntrans. */
143     if (points_to_ram &&
144     (baseaddr & (machine->arch_pagesize-1)) == 0 &&
145     (otheraddress & (machine->arch_pagesize - 1)) == 0 &&
146     (length & (machine->arch_pagesize - 1)) == 0)
147 dpavlin 20 flags |= DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK
148     | DM_EMULATED_RAM;
149 dpavlin 18
150     memory_device_register(machine->memory, "ram [mirror]",
151     baseaddr, length, dev_ram_access, d, flags
152 dpavlin 20 | DM_READS_HAVE_NO_SIDE_EFFECTS, (void *) &d->offset);
153 dpavlin 4 break;
154 dpavlin 18
155 dpavlin 4 case DEV_RAM_RAM:
156     /*
157     * Allocate zero-filled RAM using mmap(). If mmap() failed,
158     * try malloc(), but then we also have to memset(), which
159     * can be slow for large chunks of memory.
160     */
161     d->length = length;
162     d->data = (unsigned char *) mmap(NULL, length,
163     PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
164     if (d->data == NULL) {
165     d->data = malloc(length);
166     if (d->data == NULL) {
167     fprintf(stderr, "out of memory\n");
168     exit(1);
169     }
170     memset(d->data, 0, length);
171     }
172 dpavlin 18
173     /* Aligned memory? Then it works with dyntrans. */
174     if ((baseaddr & (machine->arch_pagesize - 1)) == 0 &&
175     (length & (machine->arch_pagesize - 1)) == 0)
176 dpavlin 20 flags |= DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK;
177 dpavlin 18
178     memory_device_register(machine->memory, "ram", baseaddr,
179     d->length, dev_ram_access, d, flags
180 dpavlin 20 | DM_READS_HAVE_NO_SIDE_EFFECTS, d->data);
181 dpavlin 4 break;
182 dpavlin 18
183 dpavlin 4 default:
184     fatal("dev_ram_access(): unknown mode %i\n", d->mode);
185     exit(1);
186     }
187     }
188    

  ViewVC Help
Powered by ViewVC 1.1.26