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

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

unix.superglobalmegacorp.com

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