|
|
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: {
1.1.1.5 ! root 166: nvram[NVRAM_VMODE1] &= ~0x01; // No doublescan
! 167: nvram[NVRAM_VMODE2] |= 0x10; // VGA mode
! 168: nvram[NVRAM_VMODE2] &= ~0x20; // 60 Hz
1.1 root 169: }
170: else
171: {
1.1.1.5 ! root 172: nvram[NVRAM_VMODE1] |= 0x01; // Interlaced
! 173: nvram[NVRAM_VMODE2] &= ~0x10; // TV/RGB mode
! 174: nvram[NVRAM_VMODE2] |= 0x20; // 50 Hz
1.1 root 175: }
176: NvRam_SetChecksum();
177: }
178:
179: NvRam_Reset();
180: }
181:
182:
183: /*-----------------------------------------------------------------------*/
184: /**
185: * De-Initialization
186: */
187: void NvRam_UnInit(void)
188: {
189: NvRam_Save(); // save NVRAM file upon exit automatically (should be conditionalized)
190: }
191:
192:
193: /*-----------------------------------------------------------------------*/
194: /**
195: * Read from RTC/NVRAM offset selection register ($ff8961)
196: */
197: void NvRam_Select_ReadByte(void)
198: {
199: IoMem_WriteByte(0xff8961, nvram_index);
200: }
201:
202:
203: /*-----------------------------------------------------------------------*/
204: /**
205: * Write to RTC/NVRAM offset selection register ($ff8961)
206: */
207: void NvRam_Select_WriteByte(void)
208: {
209: Uint8 value = IoMem_ReadByte(0xff8961);
210:
211: if (value < sizeof(nvram))
212: {
213: nvram_index = value;
214: }
215: else
216: {
217: Log_Printf(LOG_WARN, "NVRAM: trying to set out-of-bound position (%d)\n", value);
218: }
219: }
220:
221:
222: /*-----------------------------------------------------------------------*/
223: /**
224: * Read from RTC/NVRAM data register ($ff8963)
225: */
226: void NvRam_Data_ReadByte(void)
227: {
1.1.1.2 root 228: Uint8 value = 0;
1.1 root 229:
230: if (nvram_index == NVRAM_SECONDS || nvram_index == NVRAM_MINUTES || nvram_index == NVRAM_HOURS
231: || (nvram_index >=NVRAM_DAY && nvram_index <=NVRAM_YEAR) )
232: {
233: /* access to RTC? - then read host clock and return its values */
234: time_t tim = time(NULL);
235: struct tm *curtim = localtime(&tim); /* current time */
236: switch(nvram_index)
237: {
238: case NVRAM_SECONDS: value = curtim->tm_sec; break;
239: case NVRAM_MINUTES: value = curtim->tm_min; break;
240: case NVRAM_HOURS: value = curtim->tm_hour; break;
241: case NVRAM_DAY: value = curtim->tm_mday; break;
242: case NVRAM_MONTH: value = curtim->tm_mon+1; break;
243: case NVRAM_YEAR: value = curtim->tm_year - 68; break;
244: }
245: }
246: else if (nvram_index == 10)
247: {
1.1.1.2 root 248: static bool rtc_uip = true;
1.1 root 249: value = rtc_uip ? 0x80 : 0;
250: rtc_uip = !rtc_uip;
251: }
252: else if (nvram_index == 13)
253: {
254: value = 0x80; // Valid RAM and Time bit
255: }
256: else if (nvram_index < 14)
257: {
258: Log_Printf(LOG_DEBUG, "Read from unsupported RTC/NVRAM register 0x%x.\n", nvram_index);
259: value = nvram[nvram_index];
260: }
261: else
262: {
263: value = nvram[nvram_index];
264: }
1.1.1.4 root 265: Dprintf(("Reading NVRAM data at %d = %d ($%02x)\n", nvram_index, value, value));
1.1 root 266:
267: IoMem_WriteByte(0xff8963, value);
268: }
269:
270:
271: /*-----------------------------------------------------------------------*/
272: /**
273: * Write to RTC/NVRAM data register ($ff8963)
274: */
275:
276: void NvRam_Data_WriteByte(void)
277: {
278: Uint8 value = IoMem_ReadByte(0xff8963);
1.1.1.4 root 279: Dprintf(("Writing NVRAM data at %d = %d ($%02x)\n", nvram_index, value, value));
1.1 root 280: nvram[nvram_index] = value;
281: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.