21
21
#include "hw/ide/pci.h"
22
22
#include "hw/i2c/smbus_eeprom.h"
23
23
#include "hw/ppc/ppc.h"
24
+ #include "system/block-backend.h"
24
25
#include "system/qtest.h"
25
26
#include "system/reset.h"
26
27
#include "kvm_ppc.h"
27
28
29
+ #include <zlib.h> /* for crc32 */
30
+
28
31
#define BUS_FREQ_HZ 100000000
29
32
30
33
/*
@@ -46,6 +49,100 @@ static const char dummy_fw[] = {
46
49
0x4e , 0x80 , 0x00 , 0x20 , /* blr */
47
50
};
48
51
52
+ #define NVRAM_ADDR 0xfd0e0000
53
+ #define NVRAM_SIZE (4 * KiB)
54
+
55
+ #define TYPE_A1_NVRAM "a1-nvram"
56
+ OBJECT_DECLARE_SIMPLE_TYPE (A1NVRAMState , A1_NVRAM )
57
+
58
+ struct A1NVRAMState {
59
+ SysBusDevice parent_obj ;
60
+
61
+ MemoryRegion mr ;
62
+ BlockBackend * blk ;
63
+ };
64
+
65
+ static uint64_t nvram_read (void * opaque , hwaddr addr , unsigned int size )
66
+ {
67
+ /* read callback not used because of romd mode */
68
+ g_assert_not_reached ();
69
+ }
70
+
71
+ static void nvram_write (void * opaque , hwaddr addr , uint64_t val ,
72
+ unsigned int size )
73
+ {
74
+ A1NVRAMState * s = opaque ;
75
+ uint8_t * p = memory_region_get_ram_ptr (& s -> mr );
76
+
77
+ p [addr ] = val ;
78
+ if (s -> blk ) {
79
+ blk_pwrite (s -> blk , addr , 1 , & val , 0 );
80
+ }
81
+ }
82
+
83
+ static const MemoryRegionOps nvram_ops = {
84
+ .read = nvram_read ,
85
+ .write = nvram_write ,
86
+ .endianness = DEVICE_BIG_ENDIAN ,
87
+ .impl = {
88
+ .min_access_size = 1 ,
89
+ .max_access_size = 1 ,
90
+ },
91
+ };
92
+
93
+ static void nvram_realize (DeviceState * dev , Error * * errp )
94
+ {
95
+ A1NVRAMState * s = A1_NVRAM (dev );
96
+ void * p ;
97
+ uint32_t * c ;
98
+
99
+ memory_region_init_rom_device (& s -> mr , NULL , & nvram_ops , s , "nvram" ,
100
+ NVRAM_SIZE , & error_fatal );
101
+ sysbus_init_mmio (SYS_BUS_DEVICE (dev ), & s -> mr );
102
+ c = p = memory_region_get_ram_ptr (& s -> mr );
103
+ if (s -> blk ) {
104
+ if (blk_getlength (s -> blk ) != NVRAM_SIZE ) {
105
+ error_setg (errp , "NVRAM backing file size must be %" PRId64 "bytes" ,
106
+ NVRAM_SIZE );
107
+ return ;
108
+ }
109
+ blk_set_perm (s -> blk , BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE ,
110
+ BLK_PERM_ALL , & error_fatal );
111
+ if (blk_pread (s -> blk , 0 , NVRAM_SIZE , p , 0 ) < 0 ) {
112
+ error_setg (errp , "Cannot read NVRAM contents from backing file" );
113
+ return ;
114
+ }
115
+ }
116
+ if (* c == 0 ) {
117
+ * c = cpu_to_be32 (crc32 (0 , p + 4 , NVRAM_SIZE - 4 ));
118
+ if (s -> blk ) {
119
+ blk_pwrite (s -> blk , 0 , 4 , p , 0 );
120
+ }
121
+ }
122
+ }
123
+
124
+ static const Property nvram_properties [] = {
125
+ DEFINE_PROP_DRIVE ("drive" , A1NVRAMState , blk ),
126
+ };
127
+
128
+ static void nvram_class_init (ObjectClass * oc , void * data )
129
+ {
130
+ DeviceClass * dc = DEVICE_CLASS (oc );
131
+
132
+ dc -> realize = nvram_realize ;
133
+ device_class_set_props (dc , nvram_properties );
134
+ }
135
+
136
+ static const TypeInfo nvram_types [] = {
137
+ {
138
+ .name = TYPE_A1_NVRAM ,
139
+ .parent = TYPE_SYS_BUS_DEVICE ,
140
+ .instance_size = sizeof (A1NVRAMState ),
141
+ .class_init = nvram_class_init ,
142
+ },
143
+ };
144
+ DEFINE_TYPES (nvram_types )
145
+
49
146
static void amigaone_cpu_reset (void * opaque )
50
147
{
51
148
PowerPCCPU * cpu = opaque ;
@@ -72,7 +169,7 @@ static void amigaone_init(MachineState *machine)
72
169
DeviceState * dev ;
73
170
I2CBus * i2c_bus ;
74
171
uint8_t * spd_data ;
75
- int i ;
172
+ DriveInfo * di ;
76
173
77
174
/* init CPU */
78
175
cpu = POWERPC_CPU (cpu_create (machine -> cpu_type ));
@@ -97,6 +194,16 @@ static void amigaone_init(MachineState *machine)
97
194
memory_region_add_subregion (get_system_memory (), 0x40000000 , mr );
98
195
}
99
196
197
+ /* nvram */
198
+ dev = qdev_new (TYPE_A1_NVRAM );
199
+ di = drive_get (IF_MTD , 0 , 0 );
200
+ if (di ) {
201
+ qdev_prop_set_drive (dev , "drive" , blk_by_legacy_dinfo (di ));
202
+ }
203
+ sysbus_realize_and_unref (SYS_BUS_DEVICE (dev ), & error_fatal );
204
+ memory_region_add_subregion (get_system_memory (), NVRAM_ADDR ,
205
+ sysbus_mmio_get_region (SYS_BUS_DEVICE (dev ), 0 ));
206
+
100
207
/* allocate and load firmware */
101
208
rom = g_new (MemoryRegion , 1 );
102
209
memory_region_init_rom (rom , NULL , "rom" , PROM_SIZE , & error_fatal );
@@ -136,7 +243,7 @@ static void amigaone_init(MachineState *machine)
136
243
pci_mem = sysbus_mmio_get_region (SYS_BUS_DEVICE (dev ), 1 );
137
244
mr = g_new (MemoryRegion , 1 );
138
245
memory_region_init_alias (mr , OBJECT (dev ), "pci-mem-low" , pci_mem ,
139
- 0 , 0x1000000 );
246
+ 0 , 0xe0000 );
140
247
memory_region_add_subregion (get_system_memory (), 0xfd000000 , mr );
141
248
mr = g_new (MemoryRegion , 1 );
142
249
memory_region_init_alias (mr , OBJECT (dev ), "pci-mem-high" , pci_mem ,
@@ -153,7 +260,7 @@ static void amigaone_init(MachineState *machine)
153
260
qdev_connect_gpio_out_named (DEVICE (via ), "intr" , 0 ,
154
261
qdev_get_gpio_in (DEVICE (cpu ),
155
262
PPC6xx_INPUT_INT ));
156
- for (i = 0 ; i < PCI_NUM_PINS ; i ++ ) {
263
+ for (int i = 0 ; i < PCI_NUM_PINS ; i ++ ) {
157
264
qdev_connect_gpio_out (dev , i , qdev_get_gpio_in_named (DEVICE (via ),
158
265
"pirq" , i ));
159
266
}
0 commit comments