|
|
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: */ ! 30: const char NvRam_rcsid[] = "Hatari $Id: nvram.c,v 1.4 2008/02/23 21:15:56 thothy Exp $"; ! 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: ! 57: static uint8 nvram[64] = { 48,255,21,255,23,255,1,25,3,33,42,14,112,128, ! 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: */ ! 81: static BOOL NvRam_Load(void) ! 82: { ! 83: BOOL ret = FALSE; ! 84: FILE *f = fopen(nvram_filename, "rb"); ! 85: if (f != NULL) ! 86: { ! 87: uint8 fnvram[NVRAM_LEN]; ! 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: */ ! 109: static BOOL NvRam_Save(void) ! 110: { ! 111: BOOL ret = FALSE; ! 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: { ! 123: Log_Printf(LOG_ERROR, "ERROR: cannot store NVRAM to '%s'\n", nvram_filename); ! 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: { ! 165: if (ConfigureParams.Screen.MonitorType == MONITOR_TYPE_VGA) // VGA ? ! 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: { ! 225: uint8 value = 0; ! 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: { ! 245: static BOOL rtc_uip = TRUE; ! 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.