|
|
1.1.1.2 ! root 1: /* $Id: posix-memory.c,v 1.5 2003/07/29 18:20:30 fredette Exp $ */ 1.1 root 2: 1.1.1.2 ! root 3: /* host/posix/posix-memory.c - implementation of memory on a POSIX system: */ 1.1 root 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> 1.1.1.2 ! root 37: _TME_RCSID("$Id: posix-memory.c,v 1.5 2003/07/29 18:20:30 fredette Exp $"); 1.1 root 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: 1.1.1.2 ! root 179: /* we are persistent storage if our arguments are: 1.1 root 180: 1.1.1.2 ! root 181: persistent FILE 1.1 root 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.