|
|
1.1 root 1: /* $Id: posix-memory.c,v 1.4 2003/05/16 21:48:09 fredette Exp $ */
2:
3: /* host/posix/memory.c - implementation of memory on a POSIX system: */
4:
5: /*
6: * Copyright (c) 2003 Matt Fredette
7: * All rights reserved.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: * 3. All advertising materials mentioning features or use of this software
18: * must display the following acknowledgement:
19: * This product includes software developed by Matt Fredette.
20: * 4. The name of the author may not be used to endorse or promote products
21: * derived from this software without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
27: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33: * POSSIBILITY OF SUCH DAMAGE.
34: */
35:
36: #include <tme/common.h>
37: _TME_RCSID("$Id: posix-memory.c,v 1.4 2003/05/16 21:48:09 fredette Exp $");
38:
39: /* includes: */
40: #include <tme/generic/bus-device.h>
41: #include <fcntl.h>
42: #include <stdio.h>
43: #include <strings.h>
44: #include <sys/stat.h>
45: #ifdef HAVE_MMAP
46: #include <sys/types.h>
47: #include <sys/mman.h>
48: #endif /* HAVE_MMAP */
49:
50: /* macros: */
51: #define TME_POSIX_MEMORY_RAM (0)
52: #define TME_POSIX_MEMORY_ROM (1)
53: #define TME_POSIX_MEMORY_PERSISTENT (2)
54:
55: /* structures: */
56: struct tme_posix_memory {
57:
58: /* our simple bus device header: */
59: struct tme_bus_device tme_posix_memory_device;
60:
61: /* our memory type: */
62: unsigned int tme_posix_memory_type;
63:
64: /* the file descriptor to any backing file: */
65: int tme_posix_memory_fd;
66:
67: /* this is nonzero if the backing file is mmapped: */
68: int tme_posix_memory_mapped;
69:
70: /* our rwlock: */
71: tme_mutex_t tme_posix_memory_rwlock;
72:
73: /* our memory contents: */
74: tme_uint8_t *tme_posix_memory_contents;
75: };
76:
77: /* the memory bus cycle handler: */
78: static int
79: _tme_posix_memory_bus_cycle(void *_memory, struct tme_bus_cycle *cycle)
80: {
81: struct tme_posix_memory *memory;
82:
83: /* recover our data structure: */
84: memory = (struct tme_posix_memory *) _memory;
85:
86: /* run the cycle: */
87: tme_bus_cycle_xfer_memory(cycle,
88: ((cycle->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE
89: && memory->tme_posix_memory_type == TME_POSIX_MEMORY_ROM)
90: ? NULL
91: : memory->tme_posix_memory_contents),
92: memory->tme_posix_memory_device.tme_bus_device_address_last);
93:
94: /* no faults: */
95: return (TME_OK);
96: }
97:
98: /* the memory TLB filler: */
99: static int
100: _tme_posix_memory_tlb_fill(void *_memory, struct tme_bus_tlb *tlb,
101: tme_bus_addr_t address, unsigned int cycles)
102: {
103: struct tme_posix_memory *memory;
104: tme_bus_addr_t memory_address_last;
105:
106: /* recover our data structure: */
107: memory = (struct tme_posix_memory *) _memory;
108:
109: /* the address must be within range: */
110: memory_address_last = memory->tme_posix_memory_device.tme_bus_device_address_last;
111: assert(address <= memory_address_last);
112:
113: /* initialize the TLB entry: */
114: tme_bus_tlb_initialize(tlb);
115:
116: /* this TLB entry can cover the whole device: */
117: TME_ATOMIC_WRITE(tme_bus_addr_t, tlb->tme_bus_tlb_addr_first, 0);
118: TME_ATOMIC_WRITE(tme_bus_addr_t, tlb->tme_bus_tlb_addr_last, memory_address_last);
119:
120: /* all memory devices allow fast reading. all memory devices except
121: ROMs allow fast writing: */
122: tlb->tme_bus_tlb_emulator_off_read = memory->tme_posix_memory_contents;
123: if (memory->tme_posix_memory_type != TME_POSIX_MEMORY_ROM) {
124: tlb->tme_bus_tlb_emulator_off_write = memory->tme_posix_memory_contents;
125: }
126: tlb->tme_bus_tlb_rwlock = &memory->tme_posix_memory_rwlock;
127:
128: /* all memory devices allow reading and writing: */
129: tlb->tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE;
130:
131: /* our bus cycle handler: */
132: tlb->tme_bus_tlb_cycle_private = memory;
133: tlb->tme_bus_tlb_cycle = _tme_posix_memory_bus_cycle;
134:
135: return (TME_OK);
136: }
137:
138: /* the new memory function: */
139: TME_ELEMENT_SUB_NEW_DECL(tme_host_posix,memory) {
140: unsigned int memory_type;
141: unsigned long memory_size;
142: const char *filename;
143: int fd;
144: struct stat statbuf;
145: struct tme_posix_memory *memory;
146: ssize_t bytes_read;
147: int arg_i;
148: int usage;
149:
150: /* assume we have no backing file: */
151: filename = NULL;
152: memory_type = -1;
153: memory_size = 0;
154: arg_i = 1;
155: usage = FALSE;
156:
157: /* we are regular RAM if our arguments are:
158:
159: ram SIZE
160:
161: */
162: if (TME_ARG_IS(args[arg_i + 0], "ram")
163: && (memory_size = tme_bus_addr_parse(args[arg_i + 1], 0)) > 0) {
164: memory_type = TME_POSIX_MEMORY_RAM;
165: arg_i += 2;
166: }
167:
168: /* we are ROM if our arguments are:
169:
170: rom FILE
171:
172: */
173: else if (TME_ARG_IS(args[arg_i + 0], "rom")
174: && (filename = args[arg_i + 1]) != NULL) {
175: memory_type = TME_POSIX_MEMORY_ROM;
176: arg_i += 2;
177: }
178:
179: /* we are nonvolatile storage if our arguments are:
180:
181: nonvolatile FILE
182:
183: */
184: else if (TME_ARG_IS(args[arg_i + 0], "persistent")
185: && (filename = args[arg_i + 1]) != NULL) {
186: memory_type = TME_POSIX_MEMORY_PERSISTENT;
187: arg_i += 2;
188: }
189:
190: else {
191: usage = TRUE;
192: }
193:
194: if (args[arg_i + 0] != NULL) {
195: tme_output_append_error(_output,
196: "%s %s",
197: args[arg_i],
198: _("unexpected"));
199: usage = TRUE;
200: }
201:
202: if (usage) {
203: tme_output_append_error(_output,
204: "%s %s { rom %s | ram %s | persistent %s }",
205: _("usage:"),
206: args[0],
207: _("ROM-FILE"),
208: _("SIZE"),
209: _("PERSISTENT-FILE"));
210: return (-1);
211: }
212:
213: /* start the memory structure: */
214: memory = tme_new0(struct tme_posix_memory, 1);
215: memory->tme_posix_memory_type = memory_type;
216:
217: /* if we have a backing file: */
218: fd = -1;
219: if (filename != NULL) {
220:
221: /* open the file for reading: */
222: fd = open(filename, (memory_type == TME_POSIX_MEMORY_ROM
223: ? O_RDONLY
224: : O_RDWR));
225: if (fd < 0) {
226: tme_output_append_error(_output,
227: "%s",
228: filename);
229: tme_free(memory);
230: return (errno);
231: }
232:
233: /* stat the file: */
234: if (fstat(fd, &statbuf) < 0) {
235: tme_output_append_error(_output,
236: "%s",
237: filename);
238: close(fd);
239: tme_free(memory);
240: return (errno);
241: }
242: memory_size = statbuf.st_size;
243: if (memory_size == 0) {
244: tme_output_append_error(_output,
245: "%s",
246: filename);
247: close(fd);
248: tme_free(memory);
249: return (EINVAL);
250: }
251:
252: #ifdef HAVE_MMAP
253: /* try to mmap the file: */
254: memory->tme_posix_memory_contents =
255: mmap(NULL,
256: statbuf.st_size,
257: PROT_READ
258: | (memory_type != TME_POSIX_MEMORY_ROM
259: ? PROT_WRITE
260: : 0),
261: MAP_SHARED,
262: fd,
263: 0);
264: if (memory->tme_posix_memory_contents != MAP_FAILED) {
265: memory->tme_posix_memory_mapped = TRUE;
266: }
267: #endif /* HAVE_MMAP */
268: }
269:
270: /* if we have to, allocate memory space: */
271: if (!memory->tme_posix_memory_mapped) {
272: memory->tme_posix_memory_contents = tme_new0(tme_uint8_t, memory_size);
273:
274: /* if we have to, read in the backing file: */
275: if (fd >= 0) {
276: bytes_read = read(fd, memory->tme_posix_memory_contents, memory_size);
277: if (bytes_read < 0
278: || memory_size != (unsigned long) bytes_read) {
279: /* XXX diagnostic: */
280: close(fd);
281: tme_free(memory->tme_posix_memory_contents);
282: tme_free(memory);
283: return (-1);
284: }
285:
286: /* if this is a ROM, we can close the file now: */
287: if (memory_type == TME_POSIX_MEMORY_ROM) {
288: close(fd);
289: fd = -1;
290: }
291: }
292: }
293:
294: /* remember any backing fd: */
295: memory->tme_posix_memory_fd = fd;
296:
297: /* initialize our rwlock: */
298: tme_rwlock_init(&memory->tme_posix_memory_rwlock);
299:
300: /* initialize our simple bus device descriptor: */
301: memory->tme_posix_memory_device.tme_bus_device_tlb_fill = _tme_posix_memory_tlb_fill;
302: memory->tme_posix_memory_device.tme_bus_device_address_last = (memory_size - 1);
303:
304: /* fill the element: */
305: element->tme_element_private = memory;
306: element->tme_element_connections_new = tme_bus_device_connections_new;
307:
308: return (0);
309: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.