qemu/hw/ds1225y.c
<<
>>
Prefs
   1/*
   2 * QEMU NVRAM emulation for DS1225Y chip
   3 *
   4 * Copyright (c) 2007-2008 Hervé Poussineau
   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 "mips.h"
  27#include "nvram.h"
  28
  29//#define DEBUG_NVRAM
  30
  31typedef struct ds1225y_t
  32{
  33    uint32_t chip_size;
  34    QEMUFile *file;
  35    uint8_t *contents;
  36    uint8_t protection;
  37} ds1225y_t;
  38
  39
  40static uint32_t nvram_readb (void *opaque, target_phys_addr_t addr)
  41{
  42    ds1225y_t *s = opaque;
  43    uint32_t val;
  44
  45    val = s->contents[addr];
  46
  47#ifdef DEBUG_NVRAM
  48    printf("nvram: read 0x%x at " TARGET_FMT_lx "\n", val, addr);
  49#endif
  50    return val;
  51}
  52
  53static uint32_t nvram_readw (void *opaque, target_phys_addr_t addr)
  54{
  55    uint32_t v;
  56    v = nvram_readb(opaque, addr);
  57    v |= nvram_readb(opaque, addr + 1) << 8;
  58    return v;
  59}
  60
  61static uint32_t nvram_readl (void *opaque, target_phys_addr_t addr)
  62{
  63    uint32_t v;
  64    v = nvram_readb(opaque, addr);
  65    v |= nvram_readb(opaque, addr + 1) << 8;
  66    v |= nvram_readb(opaque, addr + 2) << 16;
  67    v |= nvram_readb(opaque, addr + 3) << 24;
  68    return v;
  69}
  70
  71static void nvram_writeb (void *opaque, target_phys_addr_t addr, uint32_t val)
  72{
  73    ds1225y_t *s = opaque;
  74
  75#ifdef DEBUG_NVRAM
  76    printf("nvram: write 0x%x at " TARGET_FMT_lx "\n", val, addr);
  77#endif
  78
  79    s->contents[addr] = val & 0xff;
  80    if (s->file) {
  81        qemu_fseek(s->file, addr, SEEK_SET);
  82        qemu_put_byte(s->file, (int)val);
  83        qemu_fflush(s->file);
  84    }
  85}
  86
  87static void nvram_writew (void *opaque, target_phys_addr_t addr, uint32_t val)
  88{
  89    nvram_writeb(opaque, addr, val & 0xff);
  90    nvram_writeb(opaque, addr + 1, (val >> 8) & 0xff);
  91}
  92
  93static void nvram_writel (void *opaque, target_phys_addr_t addr, uint32_t val)
  94{
  95    nvram_writeb(opaque, addr, val & 0xff);
  96    nvram_writeb(opaque, addr + 1, (val >> 8) & 0xff);
  97    nvram_writeb(opaque, addr + 2, (val >> 16) & 0xff);
  98    nvram_writeb(opaque, addr + 3, (val >> 24) & 0xff);
  99}
 100
 101static void nvram_writeb_protected (void *opaque, target_phys_addr_t addr, uint32_t val)
 102{
 103    ds1225y_t *s = opaque;
 104
 105    if (s->protection != 7) {
 106#ifdef DEBUG_NVRAM
 107    printf("nvram: prevent write of 0x%x at " TARGET_FMT_lx "\n", val, addr);
 108#endif
 109        return;
 110    }
 111
 112    nvram_writeb(opaque, addr, val);
 113}
 114
 115static void nvram_writew_protected (void *opaque, target_phys_addr_t addr, uint32_t val)
 116{
 117    nvram_writeb_protected(opaque, addr, val & 0xff);
 118    nvram_writeb_protected(opaque, addr + 1, (val >> 8) & 0xff);
 119}
 120
 121static void nvram_writel_protected (void *opaque, target_phys_addr_t addr, uint32_t val)
 122{
 123    nvram_writeb_protected(opaque, addr, val & 0xff);
 124    nvram_writeb_protected(opaque, addr + 1, (val >> 8) & 0xff);
 125    nvram_writeb_protected(opaque, addr + 2, (val >> 16) & 0xff);
 126    nvram_writeb_protected(opaque, addr + 3, (val >> 24) & 0xff);
 127}
 128
 129static CPUReadMemoryFunc *nvram_read[] = {
 130    &nvram_readb,
 131    &nvram_readw,
 132    &nvram_readl,
 133};
 134
 135static CPUWriteMemoryFunc *nvram_write[] = {
 136    &nvram_writeb,
 137    &nvram_writew,
 138    &nvram_writel,
 139};
 140
 141static CPUWriteMemoryFunc *nvram_write_protected[] = {
 142    &nvram_writeb_protected,
 143    &nvram_writew_protected,
 144    &nvram_writel_protected,
 145};
 146
 147/* Initialisation routine */
 148void *ds1225y_init(target_phys_addr_t mem_base, const char *filename)
 149{
 150    ds1225y_t *s;
 151    int mem_indexRW, mem_indexRP;
 152    QEMUFile *file;
 153
 154    s = qemu_mallocz(sizeof(ds1225y_t));
 155    s->chip_size = 0x2000; /* Fixed for ds1225y chip: 8 KiB */
 156    s->contents = qemu_mallocz(s->chip_size);
 157    s->protection = 7;
 158
 159    /* Read current file */
 160    file = qemu_fopen(filename, "rb");
 161    if (file) {
 162        /* Read nvram contents */
 163        qemu_get_buffer(file, s->contents, s->chip_size);
 164        qemu_fclose(file);
 165    }
 166    s->file = qemu_fopen(filename, "wb");
 167    if (s->file) {
 168        /* Write back contents, as 'wb' mode cleaned the file */
 169        qemu_put_buffer(s->file, s->contents, s->chip_size);
 170        qemu_fflush(s->file);
 171    }
 172
 173    /* Read/write memory */
 174    mem_indexRW = cpu_register_io_memory(nvram_read, nvram_write, s);
 175    cpu_register_physical_memory(mem_base, s->chip_size, mem_indexRW);
 176    /* Read/write protected memory */
 177    mem_indexRP = cpu_register_io_memory(nvram_read, nvram_write_protected, s);
 178    cpu_register_physical_memory(mem_base + s->chip_size, s->chip_size, mem_indexRP);
 179    return s;
 180}
 181