Annotation of hatari/src/falcon/nvram.c, revision 1.1.1.6

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.