Commit 02cb1585fdf732f2b776c079f736028520aab4f4

Authored by aurel32
1 parent f442e08b

ds1225y nvram: Fix some bugs

- whole nvram was erased in some conditions
- fix out of range accesses
- improve reading speed by keeping contents in memory
- rename capacity to chip_size

(Hervé Poussineau)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4051 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 2 changed files with 130 additions and 59 deletions
hw/ds1225y.c
1 1 /*
2 2 * QEMU NVRAM emulation for DS1225Y chip
3   - *
4   - * Copyright (c) 2007 Hervé Poussineau
5   - *
  3 + *
  4 + * Copyright (c) 2007-2008 Hervé Poussineau
  5 + *
6 6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 7 * of this software and associated documentation files (the "Software"), to deal
8 8 * in the Software without restriction, including without limitation the rights
... ... @@ -26,98 +26,169 @@
26 26 #include "mips.h"
27 27 #include "nvram.h"
28 28  
29   -typedef enum
30   -{
31   - none = 0,
32   - readmode,
33   - writemode,
34   -} nvram_open_mode;
  29 +//#define DEBUG_NVRAM
35 30  
36   -struct ds1225y_t
  31 +typedef struct ds1225y_t
37 32 {
38 33 target_phys_addr_t mem_base;
39   - uint32_t capacity;
40   - const char *filename;
  34 + uint32_t chip_size;
41 35 QEMUFile *file;
42   - nvram_open_mode open_mode;
43   -};
  36 + uint8_t *contents;
  37 + uint8_t protection;
  38 +} ds1225y_t;
44 39  
45   -static int ds1225y_set_to_mode(ds1225y_t *NVRAM, nvram_open_mode mode, const char *filemode)
46   -{
47   - if (NVRAM->open_mode != mode)
48   - {
49   - if (NVRAM->file)
50   - qemu_fclose(NVRAM->file);
51   - NVRAM->file = qemu_fopen(NVRAM->filename, filemode);
52   - NVRAM->open_mode = mode;
53   - }
54   - return (NVRAM->file != NULL);
55   -}
56 40  
57 41 static uint32_t nvram_readb (void *opaque, target_phys_addr_t addr)
58 42 {
59   - ds1225y_t *NVRAM = opaque;
  43 + ds1225y_t *s = opaque;
60 44 int64_t pos;
  45 + uint32_t val;
  46 +
  47 + pos = addr - s->mem_base;
  48 + if (pos >= s->chip_size)
  49 + pos -= s->chip_size;
  50 +
  51 + val = s->contents[pos];
  52 +
  53 +#ifdef DEBUG_NVRAM
  54 + printf("nvram: read 0x%x at " TARGET_FMT_lx "\n", val, addr);
  55 +#endif
  56 + return val;
  57 +}
61 58  
62   - pos = addr - NVRAM->mem_base;
63   - if (addr >= NVRAM->capacity)
64   - addr -= NVRAM->capacity;
  59 +static uint32_t nvram_readw (void *opaque, target_phys_addr_t addr)
  60 +{
  61 + uint32_t v;
  62 + v = nvram_readb(opaque, addr);
  63 + v |= nvram_readb(opaque, addr + 1) << 8;
  64 + return v;
  65 +}
65 66  
66   - if (!ds1225y_set_to_mode(NVRAM, readmode, "rb"))
67   - return 0;
68   - qemu_fseek(NVRAM->file, pos, SEEK_SET);
69   - return (uint32_t)qemu_get_byte(NVRAM->file);
  67 +static uint32_t nvram_readl (void *opaque, target_phys_addr_t addr)
  68 +{
  69 + uint32_t v;
  70 + v = nvram_readb(opaque, addr);
  71 + v |= nvram_readb(opaque, addr + 1) << 8;
  72 + v |= nvram_readb(opaque, addr + 2) << 16;
  73 + v |= nvram_readb(opaque, addr + 3) << 24;
  74 + return v;
70 75 }
71 76  
72   -static void nvram_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
  77 +static void nvram_writeb (void *opaque, target_phys_addr_t addr, uint32_t val)
73 78 {
74   - ds1225y_t *NVRAM = opaque;
  79 + ds1225y_t *s = opaque;
75 80 int64_t pos;
76 81  
77   - pos = addr - NVRAM->mem_base;
78   - if (ds1225y_set_to_mode(NVRAM, writemode, "wb"))
79   - {
80   - qemu_fseek(NVRAM->file, pos, SEEK_SET);
81   - qemu_put_byte(NVRAM->file, (int)value);
  82 +#ifdef DEBUG_NVRAM
  83 + printf("nvram: write 0x%x at " TARGET_FMT_lx "\n", val, addr);
  84 +#endif
  85 +
  86 + pos = addr - s->mem_base;
  87 + s->contents[pos] = val & 0xff;
  88 + if (s->file) {
  89 + qemu_fseek(s->file, pos, SEEK_SET);
  90 + qemu_put_byte(s->file, (int)val);
  91 + qemu_fflush(s->file);
82 92 }
83 93 }
84 94  
  95 +static void nvram_writew (void *opaque, target_phys_addr_t addr, uint32_t val)
  96 +{
  97 + nvram_writeb(opaque, addr, val & 0xff);
  98 + nvram_writeb(opaque, addr + 1, (val >> 8) & 0xff);
  99 +}
  100 +
  101 +static void nvram_writel (void *opaque, target_phys_addr_t addr, uint32_t val)
  102 +{
  103 + nvram_writeb(opaque, addr, val & 0xff);
  104 + nvram_writeb(opaque, addr + 1, (val >> 8) & 0xff);
  105 + nvram_writeb(opaque, addr + 2, (val >> 16) & 0xff);
  106 + nvram_writeb(opaque, addr + 3, (val >> 24) & 0xff);
  107 +}
  108 +
  109 +static void nvram_writeb_protected (void *opaque, target_phys_addr_t addr, uint32_t val)
  110 +{
  111 + ds1225y_t *s = opaque;
  112 +
  113 + if (s->protection != 7) {
  114 +#ifdef DEBUG_NVRAM
  115 + printf("nvram: prevent write of 0x%x at " TARGET_FMT_lx "\n", val, addr);
  116 +#endif
  117 + return;
  118 + }
  119 +
  120 + nvram_writeb(opaque, addr - s->chip_size, val);
  121 +}
  122 +
  123 +static void nvram_writew_protected (void *opaque, target_phys_addr_t addr, uint32_t val)
  124 +{
  125 + nvram_writeb_protected(opaque, addr, val & 0xff);
  126 + nvram_writeb_protected(opaque, addr + 1, (val >> 8) & 0xff);
  127 +}
  128 +
  129 +static void nvram_writel_protected (void *opaque, target_phys_addr_t addr, uint32_t val)
  130 +{
  131 + nvram_writeb_protected(opaque, addr, val & 0xff);
  132 + nvram_writeb_protected(opaque, addr + 1, (val >> 8) & 0xff);
  133 + nvram_writeb_protected(opaque, addr + 2, (val >> 16) & 0xff);
  134 + nvram_writeb_protected(opaque, addr + 3, (val >> 24) & 0xff);
  135 +}
  136 +
85 137 static CPUReadMemoryFunc *nvram_read[] = {
86 138 &nvram_readb,
87   - NULL,
88   - NULL,
  139 + &nvram_readw,
  140 + &nvram_readl,
89 141 };
90 142  
91 143 static CPUWriteMemoryFunc *nvram_write[] = {
92 144 &nvram_writeb,
93   - NULL,
94   - NULL,
  145 + &nvram_writew,
  146 + &nvram_writel,
95 147 };
96 148  
97   -static CPUWriteMemoryFunc *nvram_none[] = {
98   - NULL,
99   - NULL,
100   - NULL,
  149 +static CPUWriteMemoryFunc *nvram_write_protected[] = {
  150 + &nvram_writeb_protected,
  151 + &nvram_writew_protected,
  152 + &nvram_writel_protected,
101 153 };
102 154  
103 155 /* Initialisation routine */
104   -ds1225y_t *ds1225y_init(target_phys_addr_t mem_base, const char *filename)
  156 +void *ds1225y_init(target_phys_addr_t mem_base, const char *filename)
105 157 {
106 158 ds1225y_t *s;
107   - int mem_index1, mem_index2;
  159 + int mem_indexRW, mem_indexRP;
  160 + QEMUFile *file;
108 161  
109 162 s = qemu_mallocz(sizeof(ds1225y_t));
110 163 if (!s)
111 164 return NULL;
  165 + s->chip_size = 0x2000; /* Fixed for ds1225y chip: 8 KiB */
  166 + s->contents = qemu_mallocz(s->chip_size);
  167 + if (!s->contents) {
  168 + return NULL;
  169 + }
112 170 s->mem_base = mem_base;
113   - s->capacity = 0x2000; /* Fixed for ds1225y chip: 8K */
114   - s->filename = filename;
  171 + s->protection = 7;
  172 +
  173 + /* Read current file */
  174 + file = qemu_fopen(filename, "rb");
  175 + if (file) {
  176 + /* Read nvram contents */
  177 + qemu_get_buffer(file, s->contents, s->chip_size);
  178 + qemu_fclose(file);
  179 + }
  180 + s->file = qemu_fopen(filename, "wb");
  181 + if (s->file) {
  182 + /* Write back contents, as 'wb' mode cleaned the file */
  183 + qemu_put_buffer(s->file, s->contents, s->chip_size);
  184 + qemu_fflush(s->file);
  185 + }
115 186  
116 187 /* Read/write memory */
117   - mem_index1 = cpu_register_io_memory(0, nvram_read, nvram_write, s);
118   - cpu_register_physical_memory(mem_base, s->capacity, mem_index1);
119   - /* Read-only memory */
120   - mem_index2 = cpu_register_io_memory(0, nvram_read, nvram_none, s);
121   - cpu_register_physical_memory(mem_base + s->capacity, s->capacity, mem_index2);
  188 + mem_indexRW = cpu_register_io_memory(0, nvram_read, nvram_write, s);
  189 + cpu_register_physical_memory(mem_base, s->chip_size, mem_indexRW);
  190 + /* Read/write protected memory */
  191 + mem_indexRP = cpu_register_io_memory(0, nvram_read, nvram_write_protected, s);
  192 + cpu_register_physical_memory(mem_base + s->chip_size, s->chip_size, mem_indexRP);
122 193 return s;
123 194 }
... ...
hw/mips.h
... ... @@ -6,8 +6,8 @@
6 6 PCIBus *pci_gt64120_init(qemu_irq *pic);
7 7  
8 8 /* ds1225y.c */
9   -typedef struct ds1225y_t ds1225y_t;
10   -ds1225y_t *ds1225y_init(target_phys_addr_t mem_base, const char *filename);
  9 +void *ds1225y_init(target_phys_addr_t mem_base, const char *filename);
  10 +void ds1225y_set_protection(void *opaque, int protection);
11 11  
12 12 /* mipsnet.c */
13 13 void mipsnet_init(int base, qemu_irq irq, NICInfo *nd);
... ...