|
|
1.1 root 1: /*
2: Hatari - nvram.c
3:
1.1.1.6 root 4: This file is distributed under the GNU General Public License, version 2
5: or at your option any later version. Read the file gpl.txt for details.
1.1 root 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:
1.1.1.6 root 18: 14-15 Preferred operating system (TOS, Unix)
1.1 root 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"
1.1.1.6 root 38: #include "vdi.h"
1.1 root 39:
1.1.1.4 root 40:
1.1 root 41: // Defs for checksum
42: #define CKS_RANGE_START 14
43: #define CKS_RANGE_END (14+47)
44: #define CKS_RANGE_LEN (CKS_RANGE_END-CKS_RANGE_START+1)
45: #define CKS_LOC (14+48)
46:
47: #define NVRAM_START 14
48: #define NVRAM_LEN 50
49:
1.1.1.2 root 50: static Uint8 nvram[64] = { 48,255,21,255,23,255,1,25,3,33,42,14,112,128,
1.1 root 51: 0,0,0,0,0,0,0,0,17,46,32,1,255,0,1,10,135,0,0,0,0,0,0,0,
52: 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 };
53:
54:
55: static Uint8 nvram_index;
56: static char nvram_filename[FILENAME_MAX];
57:
58:
59: /*-----------------------------------------------------------------------*/
60: /**
61: * Load NVRAM data from file.
62: */
1.1.1.2 root 63: static bool NvRam_Load(void)
1.1 root 64: {
1.1.1.4 root 65: bool ret = false;
1.1 root 66: FILE *f = fopen(nvram_filename, "rb");
67: if (f != NULL)
68: {
1.1.1.2 root 69: Uint8 fnvram[NVRAM_LEN];
1.1 root 70: if (fread(fnvram, 1, NVRAM_LEN, f) == NVRAM_LEN)
71: {
72: memcpy(nvram+NVRAM_START, fnvram, NVRAM_LEN);
1.1.1.7 root 73: LOG_TRACE(TRACE_NVRAM, "NVRAM: loaded from '%s'\n", nvram_filename);
1.1.1.4 root 74: ret = true;
1.1 root 75: }
1.1.1.7 root 76: else
77: {
1.1.1.8 ! root 78: Log_Printf(LOG_WARN, "NVRAM loading from '%s' failed\n", nvram_filename);
1.1.1.7 root 79: }
1.1 root 80: fclose(f);
81: }
82: else
83: {
84: Log_Printf(LOG_INFO, "NVRAM not found at '%s'\n", nvram_filename);
85: }
86:
87: return ret;
88: }
89:
90:
91: /*-----------------------------------------------------------------------*/
92: /**
93: * Save NVRAM data to file
94: */
1.1.1.2 root 95: static bool NvRam_Save(void)
1.1 root 96: {
1.1.1.4 root 97: bool ret = false;
1.1 root 98: FILE *f = fopen(nvram_filename, "wb");
99: if (f != NULL)
100: {
101: if (fwrite(nvram+NVRAM_START, 1, NVRAM_LEN, f) == NVRAM_LEN)
102: {
1.1.1.7 root 103: LOG_TRACE(TRACE_NVRAM, "NVRAM: saved to '%s'\n", nvram_filename);
1.1.1.4 root 104: ret = true;
1.1 root 105: }
1.1.1.7 root 106: else
107: {
1.1.1.8 ! root 108: Log_Printf(LOG_WARN, "Writing NVRAM to '%s' failed\n", nvram_filename);
1.1.1.7 root 109: }
1.1 root 110: fclose(f);
111: }
112: else
113: {
1.1.1.8 ! root 114: Log_Printf(LOG_WARN, "Storing NVRAM to '%s' failed\n", nvram_filename);
1.1 root 115: }
116:
117: return ret;
118: }
119:
120:
121: /*-----------------------------------------------------------------------*/
122: /**
123: * Create NVRAM checksum. The checksum is over all bytes except the
124: * checksum bytes themselves; these are at the very end.
125: */
126: static void NvRam_SetChecksum(void)
127: {
128: int i;
129: unsigned char sum = 0;
130:
131: for(i = CKS_RANGE_START; i <= CKS_RANGE_END; ++i)
132: sum += nvram[i];
133: nvram[NVRAM_CHKSUM1] = ~sum;
134: nvram[NVRAM_CHKSUM2] = sum;
135: }
136:
1.1.1.6 root 137: /*-----------------------------------------------------------------------*/
138: /**
139: * NvRam_Reset: Called during init and reset, used for resetting the
140: * emulated chip.
141: */
142: void NvRam_Reset(void)
143: {
144: if (bUseVDIRes)
145: {
146: /* The objective is to start the TOS with a video mode similar
147: * to the requested one. This is important for the TOS to initialize
148: * the right font height and palette. */
149: if (VDIHeight < 400)
150: {
151: /* This will select the 8x8 system font */
152: switch(VDIPlanes)
153: {
154: /* The case 1 is not handled, because that would result in 0x0000
155: * which is an invalide video mode. This does not matter,
156: * since any color palette is good for monochrome, anyway. */
157: case 2: /* set 320x200x4 colors */
158: nvram[NVRAM_VMODE1] = 0x00;
159: nvram[NVRAM_VMODE2] = 0x01;
160: break;
161: case 4: /* set 320x200x16 colors */
162: default:
163: nvram[NVRAM_VMODE1] = 0x00;
164: nvram[NVRAM_VMODE2] = 0x02;
165: }
166: }
167: else
168: {
169: /* This will select the 8x16 system font */
170: switch(VDIPlanes)
171: {
172: case 4: /* set 640x400x16 colors */
173: nvram[NVRAM_VMODE1] = 0x01;
174: nvram[NVRAM_VMODE2] = 0x0a;
175: break;
176: case 2: /* set 640x400x4 colors */
177: nvram[NVRAM_VMODE1] = 0x01;
178: nvram[NVRAM_VMODE2] = 0x09;
179: break;
180: case 1: /* set 640x400x2 colors */
181: default:
182: nvram[NVRAM_VMODE1] = 0x01;
183: nvram[NVRAM_VMODE2] = 0x08;
184: }
185: }
186: NvRam_SetChecksum();
187: }
188: nvram_index = 0;
189: }
1.1 root 190:
191: /*-----------------------------------------------------------------------*/
192: /**
193: * Initialization
194: */
195: void NvRam_Init(void)
196: {
197: const char sBaseName[] = "hatari.nvram";
198: const char *psHomeDir;
199:
200: // set up the nvram filename
201: psHomeDir = Paths_GetHatariHome();
202: if (strlen(psHomeDir)+sizeof(sBaseName)+1 < sizeof(nvram_filename))
203: sprintf(nvram_filename, "%s%c%s", psHomeDir, PATHSEP, sBaseName);
204: else
205: strcpy(nvram_filename, sBaseName);
206:
207: if (!NvRam_Load()) // load NVRAM file automatically
208: {
1.1.1.2 root 209: if (ConfigureParams.Screen.nMonitorType == MONITOR_TYPE_VGA) // VGA ?
1.1 root 210: {
1.1.1.5 root 211: nvram[NVRAM_VMODE1] &= ~0x01; // No doublescan
212: nvram[NVRAM_VMODE2] |= 0x10; // VGA mode
213: nvram[NVRAM_VMODE2] &= ~0x20; // 60 Hz
1.1 root 214: }
215: else
216: {
1.1.1.5 root 217: nvram[NVRAM_VMODE1] |= 0x01; // Interlaced
218: nvram[NVRAM_VMODE2] &= ~0x10; // TV/RGB mode
219: nvram[NVRAM_VMODE2] |= 0x20; // 50 Hz
1.1 root 220: }
221: NvRam_SetChecksum();
222: }
223:
224: NvRam_Reset();
225: }
226:
227:
228: /*-----------------------------------------------------------------------*/
229: /**
230: * De-Initialization
231: */
232: void NvRam_UnInit(void)
233: {
234: NvRam_Save(); // save NVRAM file upon exit automatically (should be conditionalized)
235: }
236:
237:
238: /*-----------------------------------------------------------------------*/
239: /**
240: * Read from RTC/NVRAM offset selection register ($ff8961)
241: */
242: void NvRam_Select_ReadByte(void)
243: {
244: IoMem_WriteByte(0xff8961, nvram_index);
245: }
246:
247:
248: /*-----------------------------------------------------------------------*/
249: /**
250: * Write to RTC/NVRAM offset selection register ($ff8961)
251: */
252: void NvRam_Select_WriteByte(void)
253: {
254: Uint8 value = IoMem_ReadByte(0xff8961);
255:
256: if (value < sizeof(nvram))
257: {
258: nvram_index = value;
259: }
260: else
261: {
262: Log_Printf(LOG_WARN, "NVRAM: trying to set out-of-bound position (%d)\n", value);
263: }
264: }
265:
266:
267: /*-----------------------------------------------------------------------*/
268: /**
269: * Read from RTC/NVRAM data register ($ff8963)
270: */
271: void NvRam_Data_ReadByte(void)
272: {
1.1.1.2 root 273: Uint8 value = 0;
1.1 root 274:
275: if (nvram_index == NVRAM_SECONDS || nvram_index == NVRAM_MINUTES || nvram_index == NVRAM_HOURS
276: || (nvram_index >=NVRAM_DAY && nvram_index <=NVRAM_YEAR) )
277: {
278: /* access to RTC? - then read host clock and return its values */
279: time_t tim = time(NULL);
280: struct tm *curtim = localtime(&tim); /* current time */
281: switch(nvram_index)
282: {
283: case NVRAM_SECONDS: value = curtim->tm_sec; break;
284: case NVRAM_MINUTES: value = curtim->tm_min; break;
285: case NVRAM_HOURS: value = curtim->tm_hour; break;
286: case NVRAM_DAY: value = curtim->tm_mday; break;
287: case NVRAM_MONTH: value = curtim->tm_mon+1; break;
288: case NVRAM_YEAR: value = curtim->tm_year - 68; break;
289: }
290: }
291: else if (nvram_index == 10)
292: {
1.1.1.2 root 293: static bool rtc_uip = true;
1.1 root 294: value = rtc_uip ? 0x80 : 0;
295: rtc_uip = !rtc_uip;
296: }
297: else if (nvram_index == 13)
298: {
299: value = 0x80; // Valid RAM and Time bit
300: }
301: else if (nvram_index < 14)
302: {
303: Log_Printf(LOG_DEBUG, "Read from unsupported RTC/NVRAM register 0x%x.\n", nvram_index);
304: value = nvram[nvram_index];
305: }
306: else
307: {
308: value = nvram[nvram_index];
309: }
310:
1.1.1.7 root 311: LOG_TRACE(TRACE_NVRAM, "NVRAM: read data at %d = %d ($%02x)\n", nvram_index, value, value);
1.1 root 312: IoMem_WriteByte(0xff8963, value);
313: }
314:
315:
316: /*-----------------------------------------------------------------------*/
317: /**
318: * Write to RTC/NVRAM data register ($ff8963)
319: */
320:
321: void NvRam_Data_WriteByte(void)
322: {
323: Uint8 value = IoMem_ReadByte(0xff8963);
1.1.1.7 root 324: LOG_TRACE(TRACE_NVRAM, "NVRAM: write data at %d = %d ($%02x)\n", nvram_index, value, value);
1.1 root 325: nvram[nvram_index] = value;
326: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.