|
|
1.1 root 1: /*
2: Hatari - nvram.c
3:
4: This file is distributed under the GNU Public License, version 2 or at
5: your option any later version. Read the file gpl.txt for details.
6:
7: This file is partly based on GPL code taken from the Aranym project.
8: - Copyright (c) 2001-2004 Petr Stehlik of ARAnyM dev team
9: - Adaption to Hatari (c) 2006 by Thomas Huth
10:
11: Atari TT and Falcon NVRAM/RTC emulation code.
12: This is a MC146818A or compatible chip with a non-volatile RAM area.
13:
14: These are the important bytes in the nvram array:
15:
16: Byte: Description:
17:
18: 14-15 Prefered operating system (TOS, Unix)
19: 20 Language
20: 21 Keyboard layout
21: 22 Format of date/time
22: 23 Separator for date
23: 24 Boot delay
24: 28-29 Video mode
25: 30 SCSI-ID in bits 0-2, bus arbitration flag in bit 7 (1=off, 0=on)
26: 62-63 Checksum
27:
28: All other cells are reserved / unused.
29: */
1.1.1.4 ! root 30: const char NvRam_fileid[] = "Hatari nvram.c : " __DATE__ " " __TIME__;
1.1 root 31:
32: #include "main.h"
33: #include "configuration.h"
34: #include "ioMem.h"
35: #include "log.h"
36: #include "nvram.h"
37: #include "paths.h"
38:
39: #define DEBUG 0
40: #if DEBUG
1.1.1.4 ! root 41: #define Dprintf(a) printf a
1.1 root 42: #else
1.1.1.4 ! root 43: #define Dprintf(a)
1.1 root 44: #endif
45:
1.1.1.4 ! root 46:
1.1 root 47: // Defs for checksum
48: #define CKS_RANGE_START 14
49: #define CKS_RANGE_END (14+47)
50: #define CKS_RANGE_LEN (CKS_RANGE_END-CKS_RANGE_START+1)
51: #define CKS_LOC (14+48)
52:
53: #define NVRAM_START 14
54: #define NVRAM_LEN 50
55:
1.1.1.2 root 56: static Uint8 nvram[64] = { 48,255,21,255,23,255,1,25,3,33,42,14,112,128,
1.1 root 57: 0,0,0,0,0,0,0,0,17,46,32,1,255,0,1,10,135,0,0,0,0,0,0,0,
58: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
59:
60:
61: static Uint8 nvram_index;
62: static char nvram_filename[FILENAME_MAX];
63:
64:
65: /*-----------------------------------------------------------------------*/
66: /**
67: * NvRam_Reset: Called during init and reset, used for resetting the
68: * emulated chip.
69: */
70: void NvRam_Reset(void)
71: {
72: nvram_index = 0;
73: }
74:
75:
76: /*-----------------------------------------------------------------------*/
77: /**
78: * Load NVRAM data from file.
79: */
1.1.1.2 root 80: static bool NvRam_Load(void)
1.1 root 81: {
1.1.1.4 ! root 82: bool ret = false;
1.1 root 83: FILE *f = fopen(nvram_filename, "rb");
84: if (f != NULL)
85: {
1.1.1.2 root 86: Uint8 fnvram[NVRAM_LEN];
1.1 root 87: if (fread(fnvram, 1, NVRAM_LEN, f) == NVRAM_LEN)
88: {
89: memcpy(nvram+NVRAM_START, fnvram, NVRAM_LEN);
1.1.1.4 ! root 90: ret = true;
1.1 root 91: }
92: fclose(f);
93: Log_Printf(LOG_DEBUG, "NVRAM loaded from '%s'\n", nvram_filename);
94: }
95: else
96: {
97: Log_Printf(LOG_INFO, "NVRAM not found at '%s'\n", nvram_filename);
98: }
99:
100: return ret;
101: }
102:
103:
104: /*-----------------------------------------------------------------------*/
105: /**
106: * Save NVRAM data to file
107: */
1.1.1.2 root 108: static bool NvRam_Save(void)
1.1 root 109: {
1.1.1.4 ! root 110: bool ret = false;
1.1 root 111: FILE *f = fopen(nvram_filename, "wb");
112: if (f != NULL)
113: {
114: if (fwrite(nvram+NVRAM_START, 1, NVRAM_LEN, f) == NVRAM_LEN)
115: {
1.1.1.4 ! root 116: ret = true;
1.1 root 117: }
118: fclose(f);
119: }
120: else
121: {
1.1.1.2 root 122: Log_Printf(LOG_WARN, "ERROR: cannot store NVRAM to '%s'\n", nvram_filename);
1.1 root 123: }
124:
125: return ret;
126: }
127:
128:
129: /*-----------------------------------------------------------------------*/
130: /**
131: * Create NVRAM checksum. The checksum is over all bytes except the
132: * checksum bytes themselves; these are at the very end.
133: */
134: static void NvRam_SetChecksum(void)
135: {
136: int i;
137: unsigned char sum = 0;
138:
139: for(i = CKS_RANGE_START; i <= CKS_RANGE_END; ++i)
140: sum += nvram[i];
141: nvram[NVRAM_CHKSUM1] = ~sum;
142: nvram[NVRAM_CHKSUM2] = sum;
143: }
144:
145:
146: /*-----------------------------------------------------------------------*/
147: /**
148: * Initialization
149: */
150: void NvRam_Init(void)
151: {
152: const char sBaseName[] = "hatari.nvram";
153: const char *psHomeDir;
154:
155: // set up the nvram filename
156: psHomeDir = Paths_GetHatariHome();
157: if (strlen(psHomeDir)+sizeof(sBaseName)+1 < sizeof(nvram_filename))
158: sprintf(nvram_filename, "%s%c%s", psHomeDir, PATHSEP, sBaseName);
159: else
160: strcpy(nvram_filename, sBaseName);
161:
162: if (!NvRam_Load()) // load NVRAM file automatically
163: {
1.1.1.2 root 164: if (ConfigureParams.Screen.nMonitorType == MONITOR_TYPE_VGA) // VGA ?
1.1 root 165: {
166: nvram[NVRAM_MONITOR] |= 32; // VGA mode
167: }
168: else
169: {
170: nvram[NVRAM_MONITOR] &= ~32; // TV/RGB mode
171: }
172: NvRam_SetChecksum();
173: }
174:
175: NvRam_Reset();
176: }
177:
178:
179: /*-----------------------------------------------------------------------*/
180: /**
181: * De-Initialization
182: */
183: void NvRam_UnInit(void)
184: {
185: NvRam_Save(); // save NVRAM file upon exit automatically (should be conditionalized)
186: }
187:
188:
189: /*-----------------------------------------------------------------------*/
190: /**
191: * Read from RTC/NVRAM offset selection register ($ff8961)
192: */
193: void NvRam_Select_ReadByte(void)
194: {
195: IoMem_WriteByte(0xff8961, nvram_index);
196: }
197:
198:
199: /*-----------------------------------------------------------------------*/
200: /**
201: * Write to RTC/NVRAM offset selection register ($ff8961)
202: */
203: void NvRam_Select_WriteByte(void)
204: {
205: Uint8 value = IoMem_ReadByte(0xff8961);
206:
207: if (value < sizeof(nvram))
208: {
209: nvram_index = value;
210: }
211: else
212: {
213: Log_Printf(LOG_WARN, "NVRAM: trying to set out-of-bound position (%d)\n", value);
214: }
215: }
216:
217:
218: /*-----------------------------------------------------------------------*/
219: /**
220: * Read from RTC/NVRAM data register ($ff8963)
221: */
222: void NvRam_Data_ReadByte(void)
223: {
1.1.1.2 root 224: Uint8 value = 0;
1.1 root 225:
226: if (nvram_index == NVRAM_SECONDS || nvram_index == NVRAM_MINUTES || nvram_index == NVRAM_HOURS
227: || (nvram_index >=NVRAM_DAY && nvram_index <=NVRAM_YEAR) )
228: {
229: /* access to RTC? - then read host clock and return its values */
230: time_t tim = time(NULL);
231: struct tm *curtim = localtime(&tim); /* current time */
232: switch(nvram_index)
233: {
234: case NVRAM_SECONDS: value = curtim->tm_sec; break;
235: case NVRAM_MINUTES: value = curtim->tm_min; break;
236: case NVRAM_HOURS: value = curtim->tm_hour; break;
237: case NVRAM_DAY: value = curtim->tm_mday; break;
238: case NVRAM_MONTH: value = curtim->tm_mon+1; break;
239: case NVRAM_YEAR: value = curtim->tm_year - 68; break;
240: }
241: }
242: else if (nvram_index == 10)
243: {
1.1.1.2 root 244: static bool rtc_uip = true;
1.1 root 245: value = rtc_uip ? 0x80 : 0;
246: rtc_uip = !rtc_uip;
247: }
248: else if (nvram_index == 13)
249: {
250: value = 0x80; // Valid RAM and Time bit
251: }
252: else if (nvram_index < 14)
253: {
254: Log_Printf(LOG_DEBUG, "Read from unsupported RTC/NVRAM register 0x%x.\n", nvram_index);
255: value = nvram[nvram_index];
256: }
257: else
258: {
259: value = nvram[nvram_index];
260: }
1.1.1.4 ! root 261: Dprintf(("Reading NVRAM data at %d = %d ($%02x)\n", nvram_index, value, value));
1.1 root 262:
263: IoMem_WriteByte(0xff8963, value);
264: }
265:
266:
267: /*-----------------------------------------------------------------------*/
268: /**
269: * Write to RTC/NVRAM data register ($ff8963)
270: */
271:
272: void NvRam_Data_WriteByte(void)
273: {
274: Uint8 value = IoMem_ReadByte(0xff8963);
1.1.1.4 ! root 275: Dprintf(("Writing NVRAM data at %d = %d ($%02x)\n", nvram_index, value, value));
1.1 root 276: nvram[nvram_index] = value;
277: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.