#include "vl.h"
#include "m48t59.h"
-//#define NVRAM_DEBUG
+//#define DEBUG_NVRAM
-#if defined(NVRAM_DEBUG)
+#if defined(DEBUG_NVRAM)
#define NVRAM_PRINTF(fmt, args...) do { printf(fmt , ##args); } while (0)
#else
#define NVRAM_PRINTF(fmt, args...) do { } while (0)
struct m48t59_t {
/* Hardware parameters */
int IRQ;
+ int mem_index;
+ uint32_t mem_base;
uint32_t io_base;
uint16_t size;
/* RTC management */
struct QEMUTimer *alrm_timer;
struct QEMUTimer *wd_timer;
/* NVRAM storage */
+ uint8_t lock;
uint16_t addr;
uint8_t *buffer;
};
time_t t;
t = time(NULL) + NVRAM->time_offset;
- localtime_r(&t, tm);
+#ifdef _WIN32
+ memcpy(tm,localtime(&t),sizeof(*tm));
+#else
+ localtime_r (&t, tm) ;
+#endif
}
static void set_time (m48t59_t *NVRAM, struct tm *tm)
static void get_alarm (m48t59_t *NVRAM, struct tm *tm)
{
- localtime_r(&NVRAM->alarm, tm);
+#ifdef _WIN32
+ memcpy(tm,localtime(&NVRAM->alarm),sizeof(*tm));
+#else
+ localtime_r (&NVRAM->alarm, tm);
+#endif
}
static void set_alarm (m48t59_t *NVRAM, struct tm *tm)
if (NVRAM->buffer[0x1FF7] & 0x80) {
NVRAM->buffer[0x1FF7] = 0x00;
NVRAM->buffer[0x1FFC] &= ~0x40;
- // reset_CPU();
+ /* May it be a hw CPU Reset instead ? */
+ qemu_system_reset_request();
} else {
pic_set_irq(NVRAM->IRQ, 1);
pic_set_irq(NVRAM->IRQ, 0);
}
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 < 0x1FF0 ||
(NVRAM->addr > 0x1FFF && NVRAM->addr < NVRAM->size)) {
NVRAM->buffer[NVRAM->addr] = val & 0xFF;
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 < 0x1FF0 ||
(NVRAM->addr > 0x1FFF && NVRAM->addr < NVRAM->size)) {
do_read:
NVRAM->addr = addr;
}
+void m48t59_toggle_lock (m48t59_t *NVRAM, int lock)
+{
+ NVRAM->lock ^= 1 << lock;
+}
+
/* IO access to NVRAM */
static void NVRAM_writeb (void *opaque, uint32_t addr, uint32_t val)
{
m48t59_t *NVRAM = opaque;
addr -= NVRAM->io_base;
+ NVRAM_PRINTF("0x%08x => 0x%08x\n", addr, val);
switch (addr) {
case 0:
NVRAM->addr &= ~0x00FF;
static uint32_t NVRAM_readb (void *opaque, uint32_t addr)
{
m48t59_t *NVRAM = opaque;
+ uint32_t retval;
+
+ addr -= NVRAM->io_base;
+ switch (addr) {
+ case 3:
+ retval = m48t59_read(NVRAM);
+ break;
+ default:
+ retval = -1;
+ break;
+ }
+ NVRAM_PRINTF("0x%08x <= 0x%08x\n", addr, retval);
+
+ return retval;
+}
+
+static void nvram_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+ m48t59_t *NVRAM = opaque;
+
+ addr -= NVRAM->mem_base;
+ if (addr < 0x1FF0)
+ NVRAM->buffer[addr] = value;
+}
+
+static void nvram_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+ m48t59_t *NVRAM = opaque;
+
+ addr -= NVRAM->mem_base;
+ if (addr < 0x1FF0) {
+ NVRAM->buffer[addr] = value >> 8;
+ NVRAM->buffer[addr + 1] = value;
+ }
+}
+
+static void nvram_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+ m48t59_t *NVRAM = opaque;
+
+ addr -= NVRAM->mem_base;
+ if (addr < 0x1FF0) {
+ NVRAM->buffer[addr] = value >> 24;
+ NVRAM->buffer[addr + 1] = value >> 16;
+ NVRAM->buffer[addr + 2] = value >> 8;
+ NVRAM->buffer[addr + 3] = value;
+ }
+}
+
+static uint32_t nvram_readb (void *opaque, target_phys_addr_t addr)
+{
+ m48t59_t *NVRAM = opaque;
+ uint32_t retval = 0;
+
+ addr -= NVRAM->mem_base;
+ if (addr < 0x1FF0)
+ retval = NVRAM->buffer[addr];
+
+ return retval;
+}
+
+static uint32_t nvram_readw (void *opaque, target_phys_addr_t addr)
+{
+ m48t59_t *NVRAM = opaque;
+ uint32_t retval = 0;
+
+ addr -= NVRAM->mem_base;
+ if (addr < 0x1FF0) {
+ retval = NVRAM->buffer[addr] << 8;
+ retval |= NVRAM->buffer[addr + 1];
+ }
- if (addr == NVRAM->io_base + 3)
- return m48t59_read(NVRAM);
+ return retval;
+}
- return 0xFF;
+static uint32_t nvram_readl (void *opaque, target_phys_addr_t addr)
+{
+ m48t59_t *NVRAM = opaque;
+ uint32_t retval = 0;
+
+ addr -= NVRAM->mem_base;
+ if (addr < 0x1FF0) {
+ retval = NVRAM->buffer[addr] << 24;
+ retval |= NVRAM->buffer[addr + 1] << 16;
+ retval |= NVRAM->buffer[addr + 2] << 8;
+ retval |= NVRAM->buffer[addr + 3];
+ }
+
+ return retval;
}
+static CPUWriteMemoryFunc *nvram_write[] = {
+ &nvram_writeb,
+ &nvram_writew,
+ &nvram_writel,
+};
+
+static CPUReadMemoryFunc *nvram_read[] = {
+ &nvram_readb,
+ &nvram_readw,
+ &nvram_readl,
+};
/* Initialisation routine */
-m48t59_t *m48t59_init (int IRQ, uint32_t io_base, uint16_t size)
+m48t59_t *m48t59_init (int IRQ, uint32_t mem_base,
+ uint32_t io_base, uint16_t size)
{
m48t59_t *s;
}
s->IRQ = IRQ;
s->size = size;
+ s->mem_base = mem_base;
s->io_base = io_base;
s->addr = 0;
register_ioport_read(io_base, 0x04, 1, NVRAM_readb, s);
register_ioport_write(io_base, 0x04, 1, NVRAM_writeb, s);
+ 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);
+ }
s->alrm_timer = qemu_new_timer(vm_clock, &alarm_cb, s);
s->wd_timer = qemu_new_timer(vm_clock, &watchdog_cb, s);
+ s->lock = 0;
+
return s;
}