-
Notifications
You must be signed in to change notification settings - Fork 4
/
rtcram.c
126 lines (103 loc) · 3.55 KB
/
rtcram.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/*
Simulation of the non-volatile RAM in the MC146818 RTC chip.
*/
/*
SPDX-License-Identifier: MIT
Copyright (c) 2024 Ewen McNeill <[email protected]>
*/
#include <assert.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
#include "emu.h"
#include "log.h"
#include "rtcram.h"
#include "emscripten_env.h"
// Debug logging (shared with the RTC clock portion)
#define RTC_LOG(msg_level, format_and_args...) \
log_printf(LOG_SRC_RTC, msg_level, format_and_args)
#define RTC_LOG_DEBUG(format_and_args...) RTC_LOG(LOG_DEBUG, format_and_args)
#define RTC_LOG_INFO(format_and_args...) RTC_LOG(LOG_INFO, format_and_args)
#define RTC_LOG_NOTICE(format_and_args...) RTC_LOG(LOG_NOTICE, format_and_args)
#define RTC_LOG_WARNING(format_and_args...) RTC_LOG(LOG_WARNING, format_and_args)
//autoboot enabled, only HD on ID=0 LUN=0
unsigned char rtcram_default_contents[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x20,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
};
struct rtcram_t {
uint8_t reg[64];
const char *filename;
};
void rtcram_write8(void *obj, unsigned int a, unsigned int val) {
rtcram_t *r=(rtcram_t*)obj;
FILE *rtcramfile = NULL;
size_t written = 0;
a=a/2; //rtc is on odd addresses
assert(a < sizeof(r->reg));
r->reg[a]=val;
RTC_LOG_DEBUG("RTC: wrote 0x%02x to RAM position 0x%02x\n", val, a);
if ((rtcramfile = fopen(r->filename, "wb"))) {
written = fwrite(r->reg, sizeof(r->reg), 1, rtcramfile);
fclose(rtcramfile);
}
if (written == 1) {
RTC_LOG_DEBUG("RTC: RAM persisted to %s\n", r->filename);
} else {
RTC_LOG_WARNING("RTC: Failed to persist RTC RAM to %s\n", r->filename);
}
#ifdef __EMSCRIPTEN__
emscripten_syncfs();
#endif
}
void rtcram_write16(void *obj, unsigned int a, unsigned int val) {
rtcram_write8(obj, a+1, val);
}
// RTC RAM is at every second address, so write32 writes to
// - lower 8 bits of top 16 bits
// - lower 8 bits of bottom 16 bits
void rtcram_write32(void *obj, unsigned int a, unsigned int val) {
rtcram_write8(obj, a+1, (val >> 16) & 0xFFFF); // lower 8 of upper 16
rtcram_write8(obj, a+3, val & 0xFFFF); // lower 8 of lower 16
}
unsigned int rtcram_read8(void *obj, unsigned int a) {
rtcram_t *r=(rtcram_t*)obj;
a=a/2; //rtc is on odd addresses
assert(a < sizeof(r->reg));
int ret=r->reg[a];
return ret;
}
unsigned int rtcram_read16(void *obj, unsigned int a) {
return rtcram_read8(obj, a+1);
}
// RTC RAM is at every second address, so read32 reads from
// - lower 8 bits of top 16 bits
// - lower 8 bits of bottom 16 bits
unsigned int rtcram_read32(void *obj, unsigned int a) {
return (((rtcram_read8(obj, a+1) & 0XFFFF) << 16) |
((rtcram_read8(obj, a+3) & 0xFFFF)));
}
rtcram_t *rtcram_new(const char *filename) {
rtcram_t *r=calloc(sizeof(rtcram_t), 1);
r->filename=strdup(filename);
FILE *rtcramfile = NULL;
size_t rtcread = 0;
if ((rtcramfile = fopen(r->filename, "rb"))) {
rtcread = fread(r->reg, sizeof(r->reg), 1, rtcramfile);
fclose(rtcramfile);
}
if (rtcread == 1) {
RTC_LOG_INFO("RTC: Loaded persistent RTC RAM from %s\n", r->filename);
} else {
memcpy(r->reg, rtcram_default_contents, sizeof(r->reg));
RTC_LOG_NOTICE("RTC: Unable to load persistent RTC RAM from %s; using defaults\n",
r->filename);
}
return r;
}