|
|
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.3 ! root 30: const char NvRam_rcsid[] = "Hatari $Id: nvram.c,v 1.8 2008-08-05 23:26:47 thothy Exp $";
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: #include "araglue.h"
39:
40: #define DEBUG 0
41:
42: #if DEBUG
43: #define D(x) x
44: #else
45: #define D(x)
46: #endif
47:
48: // Defs for checksum
49: #define CKS_RANGE_START 14
50: #define CKS_RANGE_END (14+47)
51: #define CKS_RANGE_LEN (CKS_RANGE_END-CKS_RANGE_START+1)
52: #define CKS_LOC (14+48)
53:
54: #define NVRAM_START 14
55: #define NVRAM_LEN 50
56:
1.1.1.2 root 57: static Uint8 nvram[64] = { 48,255,21,255,23,255,1,25,3,33,42,14,112,128,
1.1 root 58: 0,0,0,0,0,0,0,0,17,46,32,1,255,0,1,10,135,0,0,0,0,0,0,0,
59: 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 };
60:
61:
62: static Uint8 nvram_index;
63: static char nvram_filename[FILENAME_MAX];
64:
65:
66: /*-----------------------------------------------------------------------*/
67: /**
68: * NvRam_Reset: Called during init and reset, used for resetting the
69: * emulated chip.
70: */
71: void NvRam_Reset(void)
72: {
73: nvram_index = 0;
74: }
75:
76:
77: /*-----------------------------------------------------------------------*/
78: /**
79: * Load NVRAM data from file.
80: */
1.1.1.2 root 81: static bool NvRam_Load(void)
1.1 root 82: {
1.1.1.2 root 83: bool ret = FALSE;
1.1 root 84: FILE *f = fopen(nvram_filename, "rb");
85: if (f != NULL)
86: {
1.1.1.2 root 87: Uint8 fnvram[NVRAM_LEN];
1.1 root 88: if (fread(fnvram, 1, NVRAM_LEN, f) == NVRAM_LEN)
89: {
90: memcpy(nvram+NVRAM_START, fnvram, NVRAM_LEN);
91: ret = TRUE;
92: }
93: fclose(f);
94: Log_Printf(LOG_DEBUG, "NVRAM loaded from '%s'\n", nvram_filename);
95: }
96: else
97: {
98: Log_Printf(LOG_INFO, "NVRAM not found at '%s'\n", nvram_filename);
99: }
100:
101: return ret;
102: }
103:
104:
105: /*-----------------------------------------------------------------------*/
106: /**
107: * Save NVRAM data to file
108: */
1.1.1.2 root 109: static bool NvRam_Save(void)
1.1 root 110: {
1.1.1.2 root 111: bool ret = FALSE;
1.1 root 112: FILE *f = fopen(nvram_filename, "wb");
113: if (f != NULL)
114: {
115: if (fwrite(nvram+NVRAM_START, 1, NVRAM_LEN, f) == NVRAM_LEN)
116: {
117: ret = TRUE;
118: }
119: fclose(f);
120: }
121: else
122: {
1.1.1.2 root 123: Log_Printf(LOG_WARN, "ERROR: cannot store NVRAM to '%s'\n", nvram_filename);
1.1 root 124: }
125:
126: return ret;
127: }
128:
129:
130: /*-----------------------------------------------------------------------*/
131: /**
132: * Create NVRAM checksum. The checksum is over all bytes except the
133: * checksum bytes themselves; these are at the very end.
134: */
135: static void NvRam_SetChecksum(void)
136: {
137: int i;
138: unsigned char sum = 0;
139:
140: for(i = CKS_RANGE_START; i <= CKS_RANGE_END; ++i)
141: sum += nvram[i];
142: nvram[NVRAM_CHKSUM1] = ~sum;
143: nvram[NVRAM_CHKSUM2] = sum;
144: }
145:
146:
147: /*-----------------------------------------------------------------------*/
148: /**
149: * Initialization
150: */
151: void NvRam_Init(void)
152: {
153: const char sBaseName[] = "hatari.nvram";
154: const char *psHomeDir;
155:
156: // set up the nvram filename
157: psHomeDir = Paths_GetHatariHome();
158: if (strlen(psHomeDir)+sizeof(sBaseName)+1 < sizeof(nvram_filename))
159: sprintf(nvram_filename, "%s%c%s", psHomeDir, PATHSEP, sBaseName);
160: else
161: strcpy(nvram_filename, sBaseName);
162:
163: if (!NvRam_Load()) // load NVRAM file automatically
164: {
1.1.1.2 root 165: if (ConfigureParams.Screen.nMonitorType == MONITOR_TYPE_VGA) // VGA ?
1.1 root 166: {
167: nvram[NVRAM_MONITOR] |= 32; // VGA mode
168: }
169: else
170: {
171: nvram[NVRAM_MONITOR] &= ~32; // TV/RGB mode
172: }
173: NvRam_SetChecksum();
174: }
175:
176: NvRam_Reset();
177: }
178:
179:
180: /*-----------------------------------------------------------------------*/
181: /**
182: * De-Initialization
183: */
184: void NvRam_UnInit(void)
185: {
186: NvRam_Save(); // save NVRAM file upon exit automatically (should be conditionalized)
187: }
188:
189:
190: /*-----------------------------------------------------------------------*/
191: /**
192: * Read from RTC/NVRAM offset selection register ($ff8961)
193: */
194: void NvRam_Select_ReadByte(void)
195: {
196: IoMem_WriteByte(0xff8961, nvram_index);
197: }
198:
199:
200: /*-----------------------------------------------------------------------*/
201: /**
202: * Write to RTC/NVRAM offset selection register ($ff8961)
203: */
204: void NvRam_Select_WriteByte(void)
205: {
206: Uint8 value = IoMem_ReadByte(0xff8961);
207:
208: if (value < sizeof(nvram))
209: {
210: nvram_index = value;
211: }
212: else
213: {
214: Log_Printf(LOG_WARN, "NVRAM: trying to set out-of-bound position (%d)\n", value);
215: }
216: }
217:
218:
219: /*-----------------------------------------------------------------------*/
220: /**
221: * Read from RTC/NVRAM data register ($ff8963)
222: */
223: void NvRam_Data_ReadByte(void)
224: {
1.1.1.2 root 225: Uint8 value = 0;
1.1 root 226:
227: if (nvram_index == NVRAM_SECONDS || nvram_index == NVRAM_MINUTES || nvram_index == NVRAM_HOURS
228: || (nvram_index >=NVRAM_DAY && nvram_index <=NVRAM_YEAR) )
229: {
230: /* access to RTC? - then read host clock and return its values */
231: time_t tim = time(NULL);
232: struct tm *curtim = localtime(&tim); /* current time */
233: switch(nvram_index)
234: {
235: case NVRAM_SECONDS: value = curtim->tm_sec; break;
236: case NVRAM_MINUTES: value = curtim->tm_min; break;
237: case NVRAM_HOURS: value = curtim->tm_hour; break;
238: case NVRAM_DAY: value = curtim->tm_mday; break;
239: case NVRAM_MONTH: value = curtim->tm_mon+1; break;
240: case NVRAM_YEAR: value = curtim->tm_year - 68; break;
241: }
242: }
243: else if (nvram_index == 10)
244: {
1.1.1.2 root 245: static bool rtc_uip = true;
1.1 root 246: value = rtc_uip ? 0x80 : 0;
247: rtc_uip = !rtc_uip;
248: }
249: else if (nvram_index == 13)
250: {
251: value = 0x80; // Valid RAM and Time bit
252: }
253: else if (nvram_index < 14)
254: {
255: Log_Printf(LOG_DEBUG, "Read from unsupported RTC/NVRAM register 0x%x.\n", nvram_index);
256: value = nvram[nvram_index];
257: }
258: else
259: {
260: value = nvram[nvram_index];
261: }
262: D(bug("Reading NVRAM data at %d = %d ($%02x)", nvram_index, value, value));
263:
264: IoMem_WriteByte(0xff8963, value);
265: }
266:
267:
268: /*-----------------------------------------------------------------------*/
269: /**
270: * Write to RTC/NVRAM data register ($ff8963)
271: */
272:
273: void NvRam_Data_WriteByte(void)
274: {
275: Uint8 value = IoMem_ReadByte(0xff8963);
276: D(bug("Writing NVRAM data at %d = %d ($%02x)", nvram_index, value, value));
277: nvram[nvram_index] = value;
278: }
279:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.