symbian-qemu-0.9.1-12/qemu-symbian-svp/hw/syborg_snapshot.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 /*
       
     2  * Syborg snapshot device
       
     3  *
       
     4  * Copyright (c) 2008 CodeSourcery
       
     5  *
       
     6  * Permission is hereby granted, free of charge, to any person obtaining a copy
       
     7  * of this software and associated documentation files (the "Software"), to deal
       
     8  * in the Software without restriction, including without limitation the rights
       
     9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       
    10  * copies of the Software, and to permit persons to whom the Software is
       
    11  * furnished to do so, subject to the following conditions:
       
    12  *
       
    13  * The above copyright notice and this permission notice shall be included in
       
    14  * all copies or substantial portions of the Software.
       
    15  *
       
    16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
       
    17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
       
    18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
       
    19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
       
    20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
       
    21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
       
    22  * THE SOFTWARE.
       
    23  */
       
    24 
       
    25 #include "hw.h"
       
    26 #include "qemu-char.h"
       
    27 #include "syborg.h"
       
    28 #include "devtree.h"
       
    29 #include "sysemu.h"
       
    30 
       
    31 //#define DEBUG_SYBORG_SNAPSHOT
       
    32 
       
    33 #ifdef DEBUG_SYBORG_SNAPSHOT
       
    34 #define DPRINTF(fmt, args...) \
       
    35 do { printf("syborg_snapshot: " fmt , ##args); } while (0)
       
    36 #define BADF(fmt, args...) \
       
    37 do { fprintf(stderr, "syborg_snapshot: error: " fmt , ##args); exit(1);} while (0)
       
    38 #else
       
    39 #define DPRINTF(fmt, args...) do {} while(0)
       
    40 #define BADF(fmt, args...) \
       
    41 do { fprintf(stderr, "syborg_snapshot: error: " fmt , ##args);} while (0)
       
    42 #endif
       
    43 
       
    44 enum {
       
    45     SNAPSHOT_ID           = 0,
       
    46     SNAPSHOT_ADDRESS      = 1,
       
    47     SNAPSHOT_LENGTH       = 2,
       
    48     SNAPSHOT_TRIGGER      = 3
       
    49 };
       
    50 
       
    51 typedef struct {
       
    52     QEMUDevice *qdev;
       
    53     uint32_t address;
       
    54     uint32_t length;
       
    55 } syborg_snapshot_state;
       
    56 
       
    57 static void syborg_snapshot_trigger(syborg_snapshot_state *s, uint32_t value)
       
    58 {
       
    59     char *buf;
       
    60 
       
    61     buf = qemu_malloc(s->length + 1);
       
    62     if (!buf)
       
    63         return;
       
    64     cpu_physical_memory_read(s->address, (void *)buf, s->length);
       
    65     buf[s->length] = 0;
       
    66     switch (value) {
       
    67     case 1:
       
    68         DPRINTF("Snapshotting to %s\n", buf);
       
    69         qemu_snapshot_request(buf);
       
    70         break;
       
    71     case 2:
       
    72         DPRINTF("Restoring from %s\n", buf);
       
    73         qemu_snapshot_request_restore(buf);
       
    74         break;
       
    75     default:
       
    76         break;
       
    77     }
       
    78     qemu_free(buf);
       
    79 }
       
    80 
       
    81 static uint32_t syborg_snapshot_read(void *opaque, target_phys_addr_t offset)
       
    82 {
       
    83     syborg_snapshot_state *s = (syborg_snapshot_state *)opaque;
       
    84     
       
    85     offset &= 0xfff;
       
    86     DPRINTF("read 0x%x\n", (int)offset);
       
    87     switch(offset >>2) {
       
    88     case SNAPSHOT_ID:
       
    89         return SYBORG_ID_SNAPSHOT;
       
    90     case SNAPSHOT_ADDRESS:
       
    91         return s->address;
       
    92     case SNAPSHOT_LENGTH:
       
    93         return s->length;
       
    94     default:
       
    95         BADF("Bad read offset %x\n", (int)offset);
       
    96         return 0;  
       
    97     }
       
    98 }
       
    99 
       
   100 static void syborg_snapshot_write(void *opaque, target_phys_addr_t offset,
       
   101                                   uint32_t value)
       
   102 {
       
   103     syborg_snapshot_state *s = (syborg_snapshot_state *)opaque;
       
   104     
       
   105     offset &= 0xfff;
       
   106     DPRINTF("Write 0x%x=0x%x\n", (int)offset, value);
       
   107     switch (offset >> 2) {
       
   108     case SNAPSHOT_ADDRESS:
       
   109         s->address = value;
       
   110         break;
       
   111     case SNAPSHOT_LENGTH:
       
   112         s->length = value;
       
   113         break;
       
   114     case SNAPSHOT_TRIGGER:
       
   115         syborg_snapshot_trigger(s, value);
       
   116         break;
       
   117     default:
       
   118         BADF("Bad write offset %x\n", (int)offset);
       
   119         break;
       
   120     }
       
   121 }
       
   122 
       
   123 static CPUReadMemoryFunc *syborg_snapshot_readfn[] = {
       
   124      syborg_snapshot_read,
       
   125      syborg_snapshot_read,
       
   126      syborg_snapshot_read
       
   127 };
       
   128 
       
   129 static CPUWriteMemoryFunc *syborg_snapshot_writefn[] = {
       
   130      syborg_snapshot_write,
       
   131      syborg_snapshot_write,
       
   132      syborg_snapshot_write
       
   133 };
       
   134 
       
   135 static void syborg_snapshot_save(QEMUFile *f, void *opaque)
       
   136 {
       
   137     syborg_snapshot_state *s = opaque;
       
   138 
       
   139     qemu_put_be32(f, s->address);
       
   140     qemu_put_be32(f, s->length);
       
   141 }
       
   142 
       
   143 static int syborg_snapshot_load(QEMUFile *f, void *opaque, int version_id)
       
   144 {
       
   145     syborg_snapshot_state *s = opaque;
       
   146 
       
   147     if (version_id != 1)
       
   148         return -EINVAL;
       
   149 
       
   150     s->address = qemu_get_be32(f);
       
   151     s->length = qemu_get_be32(f);
       
   152 
       
   153     return 0;
       
   154 }
       
   155 
       
   156 static void syborg_snapshot_create(QEMUDevice *dev)
       
   157 {
       
   158     syborg_snapshot_state *s;
       
   159     s = (syborg_snapshot_state *)qemu_mallocz(sizeof(syborg_snapshot_state));
       
   160     s->qdev = dev;
       
   161     qdev_set_opaque(dev, s);
       
   162 }
       
   163 
       
   164 void syborg_snapshot_register(void)
       
   165 {
       
   166     QEMUDeviceClass *dc;
       
   167     dc = qdev_new("syborg,snapshot", syborg_snapshot_create, 0);
       
   168     qdev_add_registers(dc, syborg_snapshot_readfn, syborg_snapshot_writefn,
       
   169                        0x1000);
       
   170     qdev_add_savevm(dc, 1, syborg_snapshot_save, syborg_snapshot_load);
       
   171 }