#define NVRAM_PRINTF(fmt, args...) do { } while (0)
#endif
-#define NVRAM_MAX_MEM 0xfff0
+#define NVRAM_MAX_MEM 0x1ff0
+#define NVRAM_MAXADDR 0x1fff
struct m48t08_t {
- /* Hardware parameters */
- int mem_index;
- uint32_t mem_base;
- uint16_t size;
/* RTC management */
time_t time_offset;
time_t stop_time;
/* NVRAM storage */
- uint8_t lock;
- uint16_t addr;
uint8_t *buffer;
};
}
/* Direct access to NVRAM */
-void m48t08_write (m48t08_t *NVRAM, uint32_t val)
+void m48t08_write (m48t08_t *NVRAM, uint32_t addr, uint8_t val)
{
struct tm tm;
int tmp;
- if (NVRAM->addr > NVRAM_MAX_MEM && NVRAM->addr < 0x2000)
- NVRAM_PRINTF("%s: 0x%08x => 0x%08x\n", __func__, NVRAM->addr, val);
- switch (NVRAM->addr) {
+ addr &= NVRAM_MAXADDR;
+ switch (addr) {
case 0x1FF8:
/* control */
NVRAM->buffer[0x1FF8] = (val & ~0xA0) | 0x90;
}
break;
default:
- /* Check lock registers state */
- if (NVRAM->addr >= 0x20 && NVRAM->addr <= 0x2F && (NVRAM->lock & 1))
- break;
- if (NVRAM->addr >= 0x30 && NVRAM->addr <= 0x3F && (NVRAM->lock & 2))
- break;
- if (NVRAM->addr < NVRAM_MAX_MEM ||
- (NVRAM->addr > 0x1FFF && NVRAM->addr < NVRAM->size)) {
- NVRAM->buffer[NVRAM->addr] = val & 0xFF;
- }
+ NVRAM->buffer[addr] = val & 0xFF;
break;
}
}
-uint32_t m48t08_read (m48t08_t *NVRAM)
+uint8_t m48t08_read (m48t08_t *NVRAM, uint32_t addr)
{
struct tm tm;
- uint32_t retval = 0xFF;
+ uint8_t retval = 0xFF;
- switch (NVRAM->addr) {
+ addr &= NVRAM_MAXADDR;
+ switch (addr) {
case 0x1FF8:
/* control */
goto do_read;
retval = toBCD(tm.tm_year);
break;
default:
- /* Check lock registers state */
- if (NVRAM->addr >= 0x20 && NVRAM->addr <= 0x2F && (NVRAM->lock & 1))
- break;
- if (NVRAM->addr >= 0x30 && NVRAM->addr <= 0x3F && (NVRAM->lock & 2))
- break;
- if (NVRAM->addr < NVRAM_MAX_MEM ||
- (NVRAM->addr > 0x1FFF && NVRAM->addr < NVRAM->size)) {
- do_read:
- retval = NVRAM->buffer[NVRAM->addr];
- }
+ do_read:
+ retval = NVRAM->buffer[addr];
break;
}
- if (NVRAM->addr > NVRAM_MAX_MEM + 1 && NVRAM->addr < 0x2000)
- NVRAM_PRINTF("0x%08x <= 0x%08x\n", NVRAM->addr, retval);
-
return retval;
}
-void m48t08_set_addr (m48t08_t *NVRAM, uint32_t addr)
-{
- NVRAM->addr = addr;
-}
-
-void m48t08_toggle_lock (m48t08_t *NVRAM, int lock)
-{
- NVRAM->lock ^= 1 << lock;
-}
-
static void nvram_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
{
m48t08_t *NVRAM = opaque;
- addr -= NVRAM->mem_base;
- if (addr < NVRAM_MAX_MEM)
- NVRAM->buffer[addr] = value;
+ m48t08_write(NVRAM, addr, value);
}
static void nvram_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
{
m48t08_t *NVRAM = opaque;
- addr -= NVRAM->mem_base;
- if (addr < NVRAM_MAX_MEM) {
- NVRAM->buffer[addr] = value >> 8;
- NVRAM->buffer[addr + 1] = value;
- }
+ m48t08_write(NVRAM, addr, value);
+ m48t08_write(NVRAM, addr + 1, value >> 8);
}
static void nvram_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
{
m48t08_t *NVRAM = opaque;
- addr -= NVRAM->mem_base;
- if (addr < NVRAM_MAX_MEM) {
- NVRAM->buffer[addr] = value >> 24;
- NVRAM->buffer[addr + 1] = value >> 16;
- NVRAM->buffer[addr + 2] = value >> 8;
- NVRAM->buffer[addr + 3] = value;
- }
+ m48t08_write(NVRAM, addr, value);
+ m48t08_write(NVRAM, addr + 1, value >> 8);
+ m48t08_write(NVRAM, addr + 2, value >> 16);
+ m48t08_write(NVRAM, addr + 3, value >> 24);
}
static uint32_t nvram_readb (void *opaque, target_phys_addr_t addr)
m48t08_t *NVRAM = opaque;
uint32_t retval = 0;
- addr -= NVRAM->mem_base;
- if (addr < NVRAM_MAX_MEM)
- retval = NVRAM->buffer[addr];
-
+ retval = m48t08_read(NVRAM, addr);
return retval;
}
m48t08_t *NVRAM = opaque;
uint32_t retval = 0;
- addr -= NVRAM->mem_base;
- if (addr < NVRAM_MAX_MEM) {
- retval = NVRAM->buffer[addr] << 8;
- retval |= NVRAM->buffer[addr + 1];
- }
-
+ retval = m48t08_read(NVRAM, addr) << 8;
+ retval |= m48t08_read(NVRAM, addr + 1);
return retval;
}
m48t08_t *NVRAM = opaque;
uint32_t retval = 0;
- addr -= NVRAM->mem_base;
- if (addr < NVRAM_MAX_MEM) {
- retval = NVRAM->buffer[addr] << 24;
- retval |= NVRAM->buffer[addr + 1] << 16;
- retval |= NVRAM->buffer[addr + 2] << 8;
- retval |= NVRAM->buffer[addr + 3];
- }
-
+ retval = m48t08_read(NVRAM, addr) << 24;
+ retval |= m48t08_read(NVRAM, addr + 1) << 16;
+ retval |= m48t08_read(NVRAM, addr + 2) << 8;
+ retval |= m48t08_read(NVRAM, addr + 3);
return retval;
}
&nvram_readl,
};
+static void nvram_save(QEMUFile *f, void *opaque)
+{
+ m48t08_t *s = opaque;
+
+ qemu_put_be32s(f, (uint32_t *)&s->time_offset);
+ qemu_put_be32s(f, (uint32_t *)&s->stop_time);
+ qemu_put_buffer(f, s->buffer, 0x2000);
+}
+
+static int nvram_load(QEMUFile *f, void *opaque, int version_id)
+{
+ m48t08_t *s = opaque;
+
+ if (version_id != 1)
+ return -EINVAL;
+
+ qemu_get_be32s(f, (uint32_t *)&s->time_offset);
+ qemu_get_be32s(f, (uint32_t *)&s->stop_time);
+ qemu_get_buffer(f, s->buffer, 0x2000);
+ return 0;
+}
+
+static void m48t08_reset(void *opaque)
+{
+ m48t08_t *s = opaque;
+
+ s->time_offset = 0;
+ s->stop_time = 0;
+}
+
+
/* Initialisation routine */
m48t08_t *m48t08_init(uint32_t mem_base, uint16_t size)
{
m48t08_t *s;
- int i;
- unsigned char tmp = 0;
+ int mem_index;
s = qemu_mallocz(sizeof(m48t08_t));
if (!s)
qemu_free(s);
return NULL;
}
- s->size = size;
- s->mem_base = mem_base;
- s->addr = 0;
if (mem_base != 0) {
- s->mem_index = cpu_register_io_memory(0, nvram_read, nvram_write, s);
- cpu_register_physical_memory(mem_base, 0x4000, s->mem_index);
+ mem_index = cpu_register_io_memory(0, nvram_read, nvram_write, s);
+ cpu_register_physical_memory(mem_base, 0x2000, mem_index);
}
- s->lock = 0;
- i = 0x1fd8;
- s->buffer[i++] = 0x01;
- s->buffer[i++] = 0x80; /* Sun4m OBP */
- /* XXX: Ethernet address, etc */
-
- /* Calculate checksum */
- for (i = 0x1fd8; i < 0x1fe7; i++) {
- tmp ^= s->buffer[i];
- }
- s->buffer[0x1fe7] = tmp;
+ register_savevm("nvram", mem_base, 1, nvram_save, nvram_load, s);
+ qemu_register_reset(m48t08_reset, s);
return s;
}