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