|
|
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.