Annotation of tme/host/posix/posix-memory.c, revision 1.1.1.2

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.