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 * QEMU NVRAM emulation for DS1225Y chip 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 * Permission is hereby granted, free of charge, to any person obtaining a copy 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 7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights 8 * in the Software without restriction, including without limitation the rights
@@ -26,98 +26,169 @@ @@ -26,98 +26,169 @@
26 #include "mips.h" 26 #include "mips.h"
27 #include "nvram.h" 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 target_phys_addr_t mem_base; 33 target_phys_addr_t mem_base;
39 - uint32_t capacity;  
40 - const char *filename; 34 + uint32_t chip_size;
41 QEMUFile *file; 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 static uint32_t nvram_readb (void *opaque, target_phys_addr_t addr) 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 int64_t pos; 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 int64_t pos; 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 static CPUReadMemoryFunc *nvram_read[] = { 137 static CPUReadMemoryFunc *nvram_read[] = {
86 &nvram_readb, 138 &nvram_readb,
87 - NULL,  
88 - NULL, 139 + &nvram_readw,
  140 + &nvram_readl,
89 }; 141 };
90 142
91 static CPUWriteMemoryFunc *nvram_write[] = { 143 static CPUWriteMemoryFunc *nvram_write[] = {
92 &nvram_writeb, 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 /* Initialisation routine */ 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 ds1225y_t *s; 158 ds1225y_t *s;
107 - int mem_index1, mem_index2; 159 + int mem_indexRW, mem_indexRP;
  160 + QEMUFile *file;
108 161
109 s = qemu_mallocz(sizeof(ds1225y_t)); 162 s = qemu_mallocz(sizeof(ds1225y_t));
110 if (!s) 163 if (!s)
111 return NULL; 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 s->mem_base = mem_base; 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 /* Read/write memory */ 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 return s; 193 return s;
123 } 194 }
hw/mips.h
@@ -6,8 +6,8 @@ @@ -6,8 +6,8 @@
6 PCIBus *pci_gt64120_init(qemu_irq *pic); 6 PCIBus *pci_gt64120_init(qemu_irq *pic);
7 7
8 /* ds1225y.c */ 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 /* mipsnet.c */ 12 /* mipsnet.c */
13 void mipsnet_init(int base, qemu_irq irq, NICInfo *nd); 13 void mipsnet_init(int base, qemu_irq irq, NICInfo *nd);