|
|
1.1 ! root 1: /* Previous - rtcnvram.c ! 2: ! 3: This file is distributed under the GNU Public License, version 2 or at ! 4: your option any later version. Read the file gpl.txt for details. ! 5: ! 6: Emulation of Real Time Clock including NVRAM. ! 7: ! 8: Old systems use MC68HC68T1 chip, new systems use MCCS1850 chip. ! 9: ! 10: */ ! 11: ! 12: #include "ioMem.h" ! 13: #include "ioMemTables.h" ! 14: #include "m68000.h" ! 15: #include "configuration.h" ! 16: #include "dimension.hpp" ! 17: #include "sysReg.h" ! 18: #include "rtcnvram.h" ! 19: ! 20: #include <time.h> ! 21: ! 22: ! 23: #define LOG_RTC_LEVEL LOG_DEBUG ! 24: ! 25: ! 26: /* RTC interface */ ! 27: #define RTC_ADDR_WRITE 0x80 ! 28: #define RTC_ADDR_CLOCK 0x20 ! 29: #define RTC_ADDR_MASK 0x7F ! 30: Uint8 rtc_addr = 0; ! 31: Uint8 rtc_val = 0; ! 32: int phase = 0; ! 33: ! 34: int oldrtc_interface_io(Uint8 rtdatabit); ! 35: int newrtc_interface_io(Uint8 rtdatabit); ! 36: ! 37: int rtc_interface_io(Uint8 rtdatabit) { ! 38: switch (ConfigureParams.System.nRTC) { ! 39: case MC68HC68T1: return oldrtc_interface_io(rtdatabit); ! 40: case MCCS1850: return newrtc_interface_io(rtdatabit); ! 41: default: ! 42: Log_Printf(LOG_WARN, "[RTC] error: no I/O function for this chip!"); ! 43: return oldrtc_interface_io(rtdatabit); /* trying old chip */ ! 44: } ! 45: } ! 46: ! 47: void rtc_interface_reset(void) { ! 48: phase = 0; ! 49: rtc_addr = 0; ! 50: rtc_val = 0; ! 51: } ! 52: ! 53: ! 54: /* RTC power down request */ ! 55: void oldrtc_request_power_down(void); ! 56: void newrtc_request_power_down(void); ! 57: ! 58: void oldrtc_stop_pdown_request(void); ! 59: void newrtc_stop_pdown_request(void); ! 60: ! 61: void rtc_request_power_down(void) { ! 62: switch (ConfigureParams.System.nRTC) { ! 63: case MC68HC68T1: oldrtc_request_power_down(); return; ! 64: case MCCS1850: newrtc_request_power_down(); return; ! 65: default: ! 66: Log_Printf(LOG_WARN, "[RTC] error: no power down function for this chip!"); ! 67: oldrtc_request_power_down(); return; /* trying old chip */ ! 68: } ! 69: } ! 70: ! 71: void rtc_stop_pdown_request(void) { ! 72: switch (ConfigureParams.System.nRTC) { ! 73: case MC68HC68T1: oldrtc_stop_pdown_request(); return; ! 74: case MCCS1850: newrtc_stop_pdown_request(); return; ! 75: default: ! 76: Log_Printf(LOG_WARN, "[RTC] error: no power down function for this chip!"); ! 77: oldrtc_stop_pdown_request(); return; /* trying old chip */ ! 78: } ! 79: } ! 80: ! 81: ! 82: ! 83: /* --------------------- MC68HC68T1 --------------------- */ ! 84: ! 85: /* RTC NVRAM is located at address 0x00 to 0x1F (32 bytes), ! 86: * time registers, alarm registers and control/status ! 87: * registers are located at address 0x20 to 0x32. ! 88: */ ! 89: ! 90: Uint8 rtc_get_clock(Uint8 addr); ! 91: void rtc_put_clock(Uint8 addr, Uint8 val); ! 92: ! 93: /* All time values in RTC clock are in packed decimal format */ ! 94: ! 95: typedef struct { ! 96: Uint8 sec; /* 00 - 59 */ ! 97: Uint8 min; /* 00 - 59 */ ! 98: Uint8 hour; /* 01 - 12 or 00 - 24; bit 7: 1 = 12 hr, 0 = 24 hr; bit 5: 1 = pm, 0 = am */ ! 99: Uint8 wday; /* 01 - 07; 1 = sunday */ ! 100: Uint8 mday; /* 01 - 31 */ ! 101: Uint8 month; /* 01 - 12; 1 = january */ ! 102: Uint8 year; /* 00 - 99 */ ! 103: } RTC_TIME; ! 104: ! 105: RTC_TIME get_rtc_time(void); ! 106: ! 107: typedef struct { ! 108: Uint8 sec; /* 00 - 59 */ ! 109: Uint8 min; /* 00 - 59 */ ! 110: Uint8 hour; /* 01 - 12 or 00 - 24; bit 5: 1 = pm, 0 = am in 24 hr mode */ ! 111: } RTC_ALARM; ! 112: ! 113: ! 114: /* There are 3 status and control registers inside the chip */ ! 115: ! 116: /* RTC Status Register at 0x30 (r only) ! 117: * ! 118: * 0-0- ---- always 0 (0 in bit 7 identifies MC68HC68T1 chip) ! 119: * -x-- ---- watchdog detected cpu failure ! 120: * ---x ---- first time up ! 121: * ---- x--- interrupt true (one of following interrupts is valid) ! 122: * ---- -x-- power sense interrupt ! 123: * ---- --x- alarm interrupt ! 124: * ---- ---x clock interrupt ! 125: */ ! 126: ! 127: #define RTC_CPUFAIL 0x40 ! 128: #define RTC_FIRSTUP 0x10 ! 129: #define RTC_INT 0x08 ! 130: #define RTC_INT_SENSE 0x04 ! 131: #define RTC_INT_ALARM 0x02 ! 132: #define RTC_INT_CLOCK 0x01 ! 133: ! 134: ! 135: /* RTC Clock Control Register at 0x31 (r) or 0xB1 (w) ! 136: * ! 137: * x--- ---- 1 = start, 0 = stop counter ! 138: * -x-- ---- 1 = enable line input, 0 = enable chrystal input ! 139: * --xx ---- chrystal select: 0 = 4.194304 MHz, 1 = 2.097152, 2 = 1.048576, 3 = 32.768 kHz ! 140: * ---- x--- 1 = line input 50 Hz, 0 = line input 60 Hz ! 141: * ---- -xxx clock out frequency: ! 142: * ! 143: * 0 = chrystal ! 144: * 1 = chrystal/2 ! 145: * 2 = chrystal/4 ! 146: * 3 = chrystal/8 ! 147: * 4 = disable ! 148: * 5 = 1 Hz ! 149: * 6 = 2 Hz ! 150: * 7 = 50/60 Hz for line operation; 64 Hz for chrystal operation ! 151: */ ! 152: ! 153: #define RTC_START 0x80 ! 154: #define RTC_STOP 0x00 ! 155: #define RTC_LINE 0x40 ! 156: #define RTC_XTAL 0x30 ! 157: #define RTC_L50HZ 0x08 ! 158: #define RTC_FREQ 0x07 ! 159: ! 160: ! 161: /* RTC Interrupt Control Register at 0x32 (r) or 0xB2 (w) ! 162: * ! 163: * x--- ---- watchdog enable ! 164: * -x-- ---- initiate power down ! 165: * --x- ---- power sense ! 166: * ---x ---- enable alarm ! 167: * ---- xxxx select frequency of periodic interrupt: ! 168: * ! 169: * 0 = diable ! 170: * chrystal: ! 171: * 1 = 2048 Hz, 2 = 1024 Hz, ... , C = 1 Hz ! 172: * D = 1 per min, E = 1 per hour, F = 1 per day ! 173: * line: ! 174: * 6 = 50 or 60 Hz, B = 2 Hz, C = 1 Hz ! 175: * D = 1 per min, E = 1 per hour, F = 1 per day ! 176: */ ! 177: ! 178: #define RTC_WATCHDOG 0x80 ! 179: #define RTC_POWERDOWN 0x40 ! 180: #define RTC_PWRSENSE 0x20 ! 181: #define RTC_ENABLEALRM 0x10 ! 182: #define RTC_PERIODIC 0x0F ! 183: ! 184: struct { ! 185: Uint8 ram[32]; /* 0x00 - 0x1F (r), 0x80 - 0x9F (w) */ ! 186: RTC_TIME time; /* 0x20 - 0x26 (r), 0xA0 - 0xA6 (w) */ ! 187: RTC_ALARM alarm; /* 0xA8 - 0xAA (w) */ ! 188: Uint8 status; /* 0x30 (r) */ ! 189: Uint8 clkctrl; /* 0x31 (r), 0xB1 (w) */ ! 190: Uint8 intctrl; /* 0x32 (r), 0xB2 (w) */ ! 191: } rtc; ! 192: ! 193: ! 194: int oldrtc_interface_io(Uint8 rtdatabit) { ! 195: ! 196: phase++; ! 197: ! 198: if (phase<=8) { ! 199: rtc_addr = (rtc_addr<<1)|(rtdatabit?1:0); ! 200: } else { ! 201: ! 202: if (phase==9) { ! 203: if (!(rtc_addr&RTC_ADDR_WRITE)) { ! 204: if (rtc_addr&RTC_ADDR_CLOCK) { ! 205: rtc_val = rtc_get_clock(rtc_addr); ! 206: } else { ! 207: rtc_val = rtc.ram[rtc_addr&RTC_ADDR_MASK]; ! 208: } ! 209: ! 210: Log_Printf(LOG_RTC_LEVEL,"[RTC] reading val $%02X from addr $%02X at PC=$%08x\n", ! 211: rtc_val,rtc_addr,m68k_getpc()); ! 212: } ! 213: } ! 214: ! 215: if (rtc_addr&RTC_ADDR_WRITE) { ! 216: rtc_val = (rtc_val<<1)|(rtdatabit?1:0); ! 217: } else { ! 218: rtdatabit = (rtc_val&(1<<(16-phase)))?1:0; ! 219: } ! 220: ! 221: if (phase==16) { ! 222: if (rtc_addr&RTC_ADDR_WRITE) { ! 223: Log_Printf(LOG_RTC_LEVEL,"[RTC] writing val $%02X to addr $%02X at PC=$%08x\n", ! 224: rtc_val,rtc_addr,m68k_getpc()); ! 225: ! 226: if (rtc_addr&RTC_ADDR_CLOCK) { ! 227: rtc_put_clock(rtc_addr, rtc_val); ! 228: } else { ! 229: rtc.ram[rtc_addr&RTC_ADDR_MASK] = rtc_val; ! 230: } ! 231: } ! 232: ! 233: switch (rtc_addr) { ! 234: case 0x1F: ! 235: case 0x9F: rtc_addr = 0x00; break; ! 236: case 0x32: ! 237: case 0xB2: rtc_addr = 0x20; break; ! 238: default: rtc_addr++; break; ! 239: } ! 240: phase-=8; ! 241: } ! 242: } ! 243: ! 244: /* RTC returns 0 or 1 */ ! 245: return rtdatabit; ! 246: } ! 247: ! 248: static Uint8 toBCD(int val) { ! 249: return (((val/10)%10)<<4)|(val%10); ! 250: } ! 251: ! 252: /* Year is supported up to 2050 through overflow of decimal decade */ ! 253: static Uint8 toBCDyr(int val) { ! 254: return (((val/10)&0xF)<<4)|(val%10); ! 255: } ! 256: ! 257: static int fromBCD(Uint8 bcd) { ! 258: return ((bcd&0xF0)>>4)*10+(bcd&0xF); ! 259: } ! 260: ! 261: static void my_get_rtc_time(void) { ! 262: time_t tmp = host_unix_time(); ! 263: struct tm t =*gmtime(&tmp); ! 264: ! 265: rtc.time.sec = toBCD(t.tm_sec); ! 266: rtc.time.min = toBCD(t.tm_min); ! 267: rtc.time.hour = toBCD(t.tm_hour); ! 268: rtc.time.wday = toBCD(t.tm_wday+1); ! 269: rtc.time.mday = toBCD(t.tm_mday); ! 270: rtc.time.month = toBCD(t.tm_mon+1); ! 271: rtc.time.year = toBCDyr(t.tm_year); ! 272: } ! 273: ! 274: static void my_set_rtc_time(int which,int val) { ! 275: static struct tm t; ! 276: ! 277: t.tm_sec = fromBCD(rtc.time.sec); ! 278: t.tm_min = fromBCD(rtc.time.min); ! 279: t.tm_hour = fromBCD(rtc.time.hour); ! 280: t.tm_wday = fromBCD(rtc.time.wday) - 1; ! 281: t.tm_mday = fromBCD(rtc.time.mday); ! 282: t.tm_mon = fromBCD(rtc.time.month) - 1; ! 283: t.tm_year = fromBCD(rtc.time.year); ! 284: ! 285: val = fromBCD(val); ! 286: ! 287: switch (which) { ! 288: case 0: ! 289: t.tm_sec=val; ! 290: break; ! 291: case 1: ! 292: t.tm_min=val; ! 293: break; ! 294: case 2: ! 295: t.tm_hour=val; ! 296: break; ! 297: case 3: ! 298: t.tm_mday=val; ! 299: break; ! 300: case 4: ! 301: t.tm_mon=val-1; ! 302: break; ! 303: case 5: ! 304: t.tm_year=val; ! 305: break; ! 306: } ! 307: ! 308: Log_Printf(LOG_WARN,"setting %d to %x",which,val); ! 309: ! 310: host_set_unix_time(mktime(&t)); ! 311: } ! 312: ! 313: Uint8 rtc_get_clock(Uint8 addr) { ! 314: Uint8 val = 0x00; ! 315: ! 316: my_get_rtc_time(); ! 317: ! 318: switch (rtc_addr&RTC_ADDR_MASK) { ! 319: case 0x20: /* seconds */ ! 320: val = rtc.time.sec; break; ! 321: case 0x21: /* minutes */ ! 322: val = rtc.time.min; break; ! 323: case 0x22: /* hours */ ! 324: val = rtc.time.hour; break; ! 325: case 0x23: /* day of week (sunday = 1) */ ! 326: val = rtc.time.wday; break; ! 327: case 0x24: /* day of month */ ! 328: val = rtc.time.mday; break; ! 329: case 0x25: /* month */ ! 330: val = rtc.time.month; break; ! 331: case 0x26: /* year (0 - 99) */ ! 332: val = rtc.time.year ; break; ! 333: case 0x30: /* status register */ ! 334: val = rtc.status; ! 335: rtc.status &= RTC_INT_SENSE; ! 336: break; ! 337: case 0x31: /* clock control register */ ! 338: val = rtc.clkctrl; break; ! 339: case 0x32: /* interrupt control register */ ! 340: val = rtc.intctrl; break; ! 341: ! 342: default: break; ! 343: } ! 344: ! 345: return val; ! 346: } ! 347: ! 348: void my_set_rtc_time(int which,int val); ! 349: ! 350: void rtc_put_clock(Uint8 addr, Uint8 val) { ! 351: switch (rtc_addr&RTC_ADDR_MASK) { ! 352: case 0x20: /* seconds */ ! 353: my_set_rtc_time(0,val); ! 354: break; ! 355: case 0x21: /* minutes */ ! 356: my_set_rtc_time(1,val); ! 357: break; ! 358: case 0x22: /* hours */ ! 359: my_set_rtc_time(2,val); ! 360: break; ! 361: case 0x23: /* day of week (sunday = 1) */ ! 362: break; ! 363: case 0x24: /* day of month */ ! 364: my_set_rtc_time(3,val); ! 365: break; ! 366: case 0x25: /* month */ ! 367: my_set_rtc_time(4,val); ! 368: break; ! 369: case 0x26: /* year (0 - 99) */ ! 370: my_set_rtc_time(5,val); ! 371: break; ! 372: ! 373: case 0x28: /* alarm: seconds */ ! 374: case 0x29: /* alarm: minutes */ ! 375: case 0x2A: /* alarm: hours */ ! 376: Log_Printf(LOG_WARN,"Trying to program alarm (not implemented) %x",val); ! 377: break; /* not yet! */ ! 378: ! 379: case 0x31: /* clock control register */ ! 380: rtc.clkctrl = val; ! 381: break; ! 382: case 0x32: /* interrupt control register */ ! 383: rtc.intctrl = val; ! 384: if (rtc.intctrl&RTC_POWERDOWN) { ! 385: Log_Printf(LOG_WARN, "[RTC] Power down!"); ! 386: M68000_Stop(); ! 387: } ! 388: break; ! 389: ! 390: default: break; ! 391: } ! 392: } ! 393: ! 394: void oldrtc_request_power_down(void) { ! 395: set_interrupt(INT_POWER, SET_INT); ! 396: } ! 397: ! 398: void oldrtc_stop_pdown_request(void) { ! 399: set_interrupt(INT_POWER, RELEASE_INT); ! 400: } ! 401: ! 402: ! 403: /* ------------------------- MCCS1850 ------------------------- */ ! 404: ! 405: /* RTC NVRAM (64 bytes) is located at address 0x00 to 0x1F ! 406: * and 0x40 to 0x5F, time registers, alarm registers and ! 407: * control/status registers are located at address 0x20 to 0x31. ! 408: */ ! 409: ! 410: Uint8 newrtc_get_clock(Uint8 addr); ! 411: void newrtc_put_clock(Uint8 addr, Uint8 val); ! 412: ! 413: /* New RTC has two 32 bit counters, one for time and one for alarm */ ! 414: ! 415: /* There are 3 status and control registers inside the chip */ ! 416: ! 417: /* RTC Status Register at 0x30 (r only) ! 418: * ! 419: * 1--- ---- always 1 (identifies MCCS1850 chip) ! 420: * -0-- ---- always 0 ! 421: * --x- ---- test mode status ! 422: * ---x ---- first time up ! 423: * ---- x--- interrupt true (one of following interrupts is valid) ! 424: * ---- -x-- low battery interrupt ! 425: * ---- --x- alarm interrupt ! 426: * ---- ---x power down interrupt ! 427: */ ! 428: ! 429: #define NRTC_NEWCHIP 0x80 ! 430: #define NRTC_TMODE 0x20 ! 431: #define NRTC_FIRSTUP 0x10 ! 432: #define NRTC_INT 0x08 ! 433: #define NRTC_INT_LBAT 0x04 ! 434: #define NRTC_INT_ALARM 0x02 ! 435: #define NRTC_INT_PDOWN 0x01 ! 436: ! 437: ! 438: /* RTC Control Register at 0x31 (r) or 0xB1 (w) ! 439: * ! 440: * x--- ---- 1 = start, 0 = stop counter ! 441: * -x-- ---- initiate power down ! 442: * --x- ---- enable auto restart sequence ! 443: * ---x ---- enable alarm ! 444: * ---- x--- alarm clear (clear alarm int bit in status) ! 445: * ---- -x-- first time up clear (clear first up bit in status) ! 446: * ---- --x- enable low battery interrupting ! 447: * ---- ---x request power down clear (clear power down int bit in status) ! 448: * ! 449: * ---- xx-x always read as 0 ! 450: */ ! 451: ! 452: #define NRTC_CTRL_0 0x0D ! 453: ! 454: #define NRTC_START 0x80 ! 455: #define NRTC_STOP 0x00 ! 456: #define NRTC_POWERDOWN 0x40 ! 457: #define NRTC_AR 0x20 ! 458: #define NRTC_ENABLEALRM 0x10 ! 459: #define NRTC_CLRALARM 0x08 ! 460: #define NRTC_CLRFTU 0x04 ! 461: #define NRTC_LBE 0x02 ! 462: #define NRTC_CLRPDOWN 0x01 ! 463: ! 464: ! 465: struct { ! 466: /* --> see old chip * 0x00 - 0x1F (r), 0x80 - 0x9F (w) */ ! 467: Uint32 timecntr; /* 0x20 - 0x23 (r), 0xA0 - 0xA3 (w) */ ! 468: Uint32 alarmcntr; /* 0x24 - 0x27 (r), 0xA4 - 0xA7 (w) */ ! 469: Uint8 status; /* 0x30 (r) */ ! 470: Uint8 control; /* 0x31 (r), 0xB1 (w) */ ! 471: Uint8 ram2[32]; /* 0x40 - 0x5F (r), 0xC0 - 0xDF (w) */ ! 472: } newrtc; ! 473: ! 474: #define RTC_ADDR_NEWRAM 0x40 ! 475: ! 476: int newrtc_interface_io(Uint8 rtdatabit) { ! 477: ! 478: phase++; ! 479: ! 480: if (phase<=8) { ! 481: rtc_addr = (rtc_addr<<1)|(rtdatabit?1:0); ! 482: } else { ! 483: ! 484: if (phase==9) { ! 485: if (!(rtc_addr&RTC_ADDR_WRITE)) { ! 486: if (rtc_addr&RTC_ADDR_CLOCK) { ! 487: rtc_val = newrtc_get_clock(rtc_addr); ! 488: } else { ! 489: if (rtc_addr&RTC_ADDR_NEWRAM) { ! 490: rtc_val = newrtc.ram2[rtc_addr&0x1F]; ! 491: } else { ! 492: rtc_val = rtc.ram[rtc_addr&0x1F]; ! 493: } ! 494: } ! 495: ! 496: Log_Printf(LOG_RTC_LEVEL,"[newRTC] reading val $%02X from addr $%02X at PC=$%08x\n", ! 497: rtc_val,rtc_addr,m68k_getpc()); ! 498: } ! 499: } ! 500: ! 501: if (rtc_addr&RTC_ADDR_WRITE) { ! 502: rtc_val = (rtc_val<<1)|(rtdatabit?1:0); ! 503: } else { ! 504: rtdatabit = (rtc_val&(1<<(16-phase)))?1:0; ! 505: } ! 506: ! 507: if (phase==16) { ! 508: if (rtc_addr&RTC_ADDR_WRITE) { ! 509: Log_Printf(LOG_RTC_LEVEL,"[newRTC] writing val $%02X to addr $%02X at PC=$%08x\n", ! 510: rtc_val,rtc_addr,m68k_getpc()); ! 511: ! 512: if (rtc_addr&RTC_ADDR_CLOCK) { ! 513: newrtc_put_clock(rtc_addr, rtc_val); ! 514: } else { ! 515: if (rtc_addr&RTC_ADDR_NEWRAM) { ! 516: newrtc.ram2[rtc_addr&0x1F] = rtc_val; ! 517: } else { ! 518: rtc.ram[rtc_addr&0x1F] = rtc_val; ! 519: } ! 520: } ! 521: } ! 522: ! 523: switch (rtc_addr) { ! 524: case 0x7F: rtc_addr = 0x00; break; ! 525: case 0xFF: rtc_addr = 0x80; break; ! 526: default: rtc_addr++; break; ! 527: } ! 528: phase-=8; ! 529: } ! 530: } ! 531: ! 532: /* RTC returns 0 or 1 */ ! 533: return rtdatabit; ! 534: } ! 535: ! 536: ! 537: Uint8 newrtc_get_clock(Uint8 addr) { ! 538: Uint8 val = 0x00; ! 539: ! 540: newrtc.timecntr = host_unix_time(); ! 541: ! 542: switch (rtc_addr&RTC_ADDR_MASK) { ! 543: case 0x20: ! 544: val = (newrtc.timecntr>>24); ! 545: break; ! 546: case 0x21: ! 547: val = (newrtc.timecntr>>16); ! 548: break; ! 549: case 0x22: ! 550: val = (newrtc.timecntr>>8); ! 551: break; ! 552: case 0x23: ! 553: val = newrtc.timecntr; ! 554: break; ! 555: ! 556: case 0x24: ! 557: val = (newrtc.alarmcntr>>24); ! 558: break; ! 559: case 0x25: ! 560: val = (newrtc.alarmcntr>>16); ! 561: break; ! 562: case 0x26: ! 563: val = (newrtc.alarmcntr>>8); ! 564: break; ! 565: case 0x27: ! 566: val = newrtc.alarmcntr; ! 567: break; ! 568: ! 569: case 0x30: /* status register */ ! 570: val = newrtc.status|NRTC_NEWCHIP; ! 571: break; ! 572: case 0x31: /* control register */ ! 573: val = newrtc.control&~NRTC_CTRL_0; ! 574: break; ! 575: ! 576: default: ! 577: break; ! 578: } ! 579: ! 580: return val; ! 581: } ! 582: ! 583: void newrtc_put_clock(Uint8 addr, Uint8 val) { ! 584: switch (rtc_addr&RTC_ADDR_MASK) { ! 585: case 0x20: ! 586: newrtc.timecntr &= 0x00FFFFFF; ! 587: newrtc.timecntr |= val << 24; ! 588: host_set_unix_time(newrtc.timecntr); ! 589: break; ! 590: case 0x21: ! 591: newrtc.timecntr &= 0xFF00FFFF; ! 592: newrtc.timecntr |= val << 16; ! 593: host_set_unix_time(newrtc.timecntr); ! 594: break; ! 595: case 0x22: ! 596: newrtc.timecntr &= 0xFFFF00FF; ! 597: newrtc.timecntr |= val << 8; ! 598: host_set_unix_time(newrtc.timecntr); ! 599: break; ! 600: case 0x23: ! 601: newrtc.timecntr &= 0xFFFFFF00; ! 602: newrtc.timecntr |= val; ! 603: host_set_unix_time(newrtc.timecntr); ! 604: break; ! 605: case 0x24: ! 606: newrtc.alarmcntr &= 0x00FFFFFF; ! 607: newrtc.alarmcntr |= val << 24; ! 608: break; ! 609: case 0x25: ! 610: newrtc.alarmcntr &= 0xFF00FFFF; ! 611: newrtc.alarmcntr |= val << 16; ! 612: break; ! 613: case 0x26: ! 614: newrtc.alarmcntr &= 0xFFFF00FF; ! 615: newrtc.alarmcntr |= val << 8; ! 616: break; ! 617: case 0x27: ! 618: newrtc.alarmcntr &= 0xFFFFFF00; ! 619: newrtc.alarmcntr |= val; ! 620: break; ! 621: ! 622: case 0x31: /* control register */ ! 623: newrtc.control = val; ! 624: if (newrtc.control&NRTC_CLRFTU) { ! 625: newrtc.status&= ~NRTC_FIRSTUP; ! 626: } ! 627: if (newrtc.control&NRTC_CLRALARM) { ! 628: newrtc.status&= ~NRTC_INT_ALARM; ! 629: } ! 630: if (newrtc.control&NRTC_CLRPDOWN) { ! 631: newrtc.status&= ~NRTC_INT_PDOWN; ! 632: } ! 633: if (newrtc.control&NRTC_POWERDOWN) { ! 634: Log_Printf(LOG_WARN, "[newRTC] Power down!"); ! 635: M68000_Stop(); ! 636: } ! 637: break; ! 638: ! 639: default: break; ! 640: } ! 641: } ! 642: ! 643: void newrtc_request_power_down(void) { ! 644: newrtc.status |= (NRTC_INT|NRTC_INT_PDOWN); ! 645: set_interrupt(INT_POWER, SET_INT); ! 646: } ! 647: ! 648: void newrtc_stop_pdown_request(void) { ! 649: set_interrupt(INT_POWER, RELEASE_INT); ! 650: } ! 651: ! 652: ! 653: /* ---------------------- RTC NVRAM ---------------------- */ ! 654: ! 655: // file mon/nvram.h ! 656: // struct nvram_info { ! 657: // #define NI_RESET 9 ! 658: // u_int ni_reset : 4, ! 659: // #define SCC_ALT_CONS 0x08000000 ! 660: // ni_alt_cons : 1, ! 661: // #define ALLOW_EJECT 0x04000000 ! 662: // ni_allow_eject : 1, ! 663: // ni_vol_r : 6, ! 664: // ni_brightness : 6, ! 665: // #define HW_PWD 0x6 ! 666: // ni_hw_pwd : 4, ! 667: // ni_vol_l : 6, ! 668: // ni_spkren : 1, ! 669: // ni_lowpass : 1, ! 670: // #define BOOT_ANY 0x00000002 ! 671: // ni_boot_any : 1, ! 672: // #define ANY_CMD 0x00000001 ! 673: // ni_any_cmd : 1; ! 674: // #define NVRAM_HW_PASSWD 6 ! 675: // u_char ni_ep[NVRAM_HW_PASSWD]; ! 676: // #define ni_enetaddr ni_ep ! 677: // #define ni_hw_passwd ni_ep ! 678: // u_short ni_simm; /* 4 SIMMs, 4 bits per SIMM */ ! 679: // char ni_adobe[2]; ! 680: // u_char ni_pot[3]; ! 681: // u_char ni_new_clock_chip : 1, ! 682: // ni_auto_poweron : 1, ! 683: // ni_use_console_slot : 1, /* Console slot was set by user. */ ! 684: // ni_console_slot : 2, /* Preferred console dev slot>>1 */ ! 685: // ni_use_parity_mem : 1, /* Use parity RAM if available? */ ! 686: // : 2; ! 687: // #define NVRAM_BOOTCMD 12 ! 688: // char ni_bootcmd[NVRAM_BOOTCMD]; ! 689: // u_short ni_cksum; ! 690: // }; ! 691: ! 692: // #define N_brightness 0 ! 693: // #define N_volume_l 1 ! 694: // #define N_volume_r 2 ! 695: ! 696: /* nominal values during self test */ ! 697: // #define BRIGHT_NOM 20 ! 698: // #define VOL_NOM 0 ! 699: ! 700: /* bits in ni_pot[0] */ ! 701: #define POT_ON 0x01 ! 702: #define EXTENDED_POT 0x02 ! 703: #define LOOP_POT 0x04 ! 704: #define VERBOSE_POT 0x08 ! 705: #define TEST_DRAM_POT 0x10 ! 706: #define BOOT_POT 0x20 ! 707: #define TEST_MONITOR_POT 0x40 ! 708: ! 709: /* bits in byte 17 */ ! 710: #define NEW_CLOCK_CHIP 0x80 ! 711: #define AUTO_POWERON 0x40 ! 712: #define USE_CONSOLE_SLOT 0x20 ! 713: #define CONSOLE_SLOT 0x18 ! 714: #define USE_PARITY_MEM 0x04 ! 715: ! 716: /* bits in ni_simm (rtc ram byte 10 and 11) * ! 717: * -------- -----xxx bit 0 - 2: 1st simm: bit 1+2 define size, bit 3 defines page mode ! 718: * -------- --xxx--- bit 3 - 5: 2nd simm: bit 1+2 define size, bit 3 defines page mode ! 719: * -------x xx------ bit 6 - 8: 3rd simm: bit 1+2 define size, bit 3 defines page mode ! 720: * ----xxx- -------- bit 9 -11: 4th simm: bit 1+2 define size, bit 3 defines page mode ! 721: * xxxx---- -------- bit 12-15: defines parity, 1 bit for each simm (ignored on 68030) ! 722: */ ! 723: /* for 68030 and monochrome non-turbo systems */ ! 724: #define SIMM_EMPTY 0x0 ! 725: #define SIMM_16MB 0x1 /* Group of four 4 Mbyte SIMMs */ ! 726: #define SIMM_4MB 0x2 /* Group of four 1 Mbyte SIMMs */ ! 727: #define SIMM_1MB 0x3 /* Group of four 256 KByte SIMMs */ ! 728: #define SIMM_PAGE_MODE 0x4 /* SIMM type is page mode, else nibble mode */ ! 729: /* for all 68040 systems */ ! 730: #define SIMM_PARITY 0x8 /* SIMMs support parity */ ! 731: /* for non-turbo color systems */ ! 732: #define SIMM_8MB_C 0x1 /* Pair of 4 Mbyte SIMMs */ ! 733: #define SIMM_2MB_C 0x2 /* Pair of 1 Mbyte SIMMs */ ! 734: #define SIMM_EMPTY2 0x3 /* reserved */ ! 735: /* for turbo systems */ ! 736: #define SIMM_32MB_T 0x1 /* Pair of 16 or 32 MByte SIMMs (front or back) */ ! 737: #define SIMM_8MB_T 0x2 /* Pair of 4 or 8 MByte SIMMs (front or back) */ ! 738: #define SIMM_2MB_T 0x3 /* Pair of 1 or 2 MByte SIMMs (front or back) */ ! 739: ! 740: /* bits in ni_reset (rtc ram byte 0 to 3) * ! 741: * -------- -------- -------- -------x bit 0: any cmd ! 742: * -------- -------- -------- ------x- bit 1: boot any ! 743: * -------- -------- -------- -----x-- bit 2: enable lowpass filter ! 744: * -------- -------- -------- ----x--- bit 3: disable speaker ! 745: * -------- -------- ------xx xxxx---- bit 4-9: volume left (max 0, min 0x2B) ! 746: * -------- -------- --xxxx-- -------- bit 10-13: hardware password ! 747: * -------- ----xxxx xx------ -------- bit 14-19: brightness (max 0x3D, min 0) ! 748: * ------xx xxxx---- -------- -------- bit 20-25: volume right (max 0, min 0x2B) ! 749: * -----x-- -------- -------- -------- bit 26: allow eject ! 750: * ----x--- -------- -------- -------- bit 27: alt cons ! 751: * xxxx---- -------- -------- -------- bit 28-31: reset ! 752: */ ! 753: ! 754: /* RTC RAM */ ! 755: Uint8 nvram_default[32]={ ! 756: 0x94,0x0f,0x40,0x00, // byte 0 - 3: volume, brightness, ... ! 757: 0x00,0x00,0x00,0x00,0x00,0x00, // byte 4 - 9: hardware password, ethernet address (?) ! 758: 0x00,0x00, // byte 10, 11: simm type and size (4 simms, 4 bits per simm), see bits in ni_simm above ! 759: 0x00,0x00, // byte 12, 13: adobe (?) ! 760: 0x4b,0x00,0x00, // byte 14: POT, byte 15: oldest ..., byte 16: most recent selftest error code ! 761: 0x00, // byte 17: bit7:clock chip; 6:auto poweron; 5:enable console slot; 3,4:console slot; 2:parity mem ! 762: 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // byte 18 - 29: boot command ! 763: 0x0F,0x13 // byte 30, 31: checksum ! 764: }; ! 765: ! 766: void nvram_init(void) { ! 767: /* Reset RTC RAM */ ! 768: memset(rtc.ram, 0, 32); ! 769: ! 770: /* Build configuration bytes */ ! 771: Uint32 config = 0x94000000; /* reset = 9, allow eject = 1 */ ! 772: config |= 0x3D<<14; /* brightness */ ! 773: ! 774: rtc.ram[0] = config>>24; ! 775: rtc.ram[1] = config>>16; ! 776: rtc.ram[2] = config>>8; ! 777: rtc.ram[3] = config; ! 778: ! 779: /* Build boot command */ ! 780: switch (ConfigureParams.Boot.nBootDevice) { ! 781: case BOOT_ROM: ! 782: rtc.ram[18] = 0x00; ! 783: rtc.ram[19] = 0x00; ! 784: break; ! 785: case BOOT_SCSI: ! 786: rtc.ram[18] = 's'; ! 787: rtc.ram[19] = 'd'; ! 788: break; ! 789: case BOOT_ETHERNET: ! 790: rtc.ram[18] = 'e'; ! 791: rtc.ram[19] = 'n'; ! 792: break; ! 793: case BOOT_MO: ! 794: rtc.ram[18] = 'o'; ! 795: rtc.ram[19] = 'd'; ! 796: break; ! 797: case BOOT_FLOPPY: ! 798: rtc.ram[18] = 'f'; ! 799: rtc.ram[19] = 'd'; ! 800: break; ! 801: ! 802: default: break; ! 803: } ! 804: ! 805: /* Copy ethernet address from ROM to RTC RAM */ ! 806: int i; ! 807: for (i = 0; i<6; i++) { ! 808: rtc.ram[i+4]=NEXTRom[i+8]; ! 809: } ! 810: ! 811: /* Build SIMM bytes */ ! 812: Uint16 SIMMconfig = 0x0000; ! 813: Uint8 simm[4]; ! 814: Uint8 parity = 0xF0; ! 815: if (ConfigureParams.System.bTurbo) { ! 816: parity = 0x00; ! 817: for (i = 0; i<4; i++) { ! 818: switch (ConfigureParams.Memory.nMemoryBankSize[i]) { ! 819: case 0: simm[i] = SIMM_EMPTY; break; ! 820: case 2: simm[i] = SIMM_2MB_T; break; ! 821: case 8: simm[i] = SIMM_8MB_T; break; ! 822: case 32: simm[i] = SIMM_32MB_T; break; ! 823: default: simm[i] = SIMM_EMPTY; break; ! 824: } ! 825: } ! 826: ! 827: } else if (ConfigureParams.System.bColor) { ! 828: for (i = 0; i<4; i++) { ! 829: switch (ConfigureParams.Memory.nMemoryBankSize[i]) { ! 830: case 0: simm[i] = SIMM_EMPTY; parity &= ~(0x10<<i); break; ! 831: case 2: simm[i] = SIMM_2MB_C; break; ! 832: case 8: simm[i] = SIMM_8MB_C; break; ! 833: default: simm[i] = SIMM_EMPTY; break; ! 834: } ! 835: } ! 836: ! 837: } else { ! 838: for (i = 0; i<4; i++) { ! 839: switch (ConfigureParams.Memory.nMemoryBankSize[i]) { ! 840: case 0: simm[i] = SIMM_EMPTY; parity &= ~(0x10<<i); break; ! 841: case 1: simm[i] = SIMM_1MB | SIMM_PAGE_MODE; break; ! 842: case 4: simm[i] = SIMM_4MB | SIMM_PAGE_MODE; break; ! 843: case 16: simm[i] = SIMM_16MB | SIMM_PAGE_MODE; break; ! 844: default: simm[i] = SIMM_EMPTY | SIMM_PAGE_MODE; break; ! 845: } ! 846: } ! 847: } ! 848: ! 849: SIMMconfig = ((parity&0xF0)<<8) | (simm[3]<<9) | (simm[2]<<6) | (simm[1]<<3) | simm[0]; ! 850: rtc.ram[10] = (SIMMconfig>>8)&0xFF; ! 851: rtc.ram[11] = SIMMconfig&0xFF; ! 852: ! 853: /* Build POT byte[0] */ ! 854: rtc.ram[14] = 0x00; ! 855: if (ConfigureParams.Boot.bEnableDRAMTest) ! 856: rtc.ram[14] |= TEST_DRAM_POT; ! 857: if (ConfigureParams.Boot.bEnablePot) ! 858: rtc.ram[14] |= POT_ON; ! 859: if (ConfigureParams.Boot.bEnableSoundTest) ! 860: rtc.ram[14] |= TEST_MONITOR_POT; ! 861: if (ConfigureParams.Boot.bEnableSCSITest) ! 862: rtc.ram[14] |= EXTENDED_POT; ! 863: if (ConfigureParams.Boot.bLoopPot) ! 864: rtc.ram[14] |= LOOP_POT; ! 865: if (ConfigureParams.Boot.bVerbose) ! 866: rtc.ram[14] |= VERBOSE_POT; ! 867: if (ConfigureParams.Boot.bExtendedPot) ! 868: rtc.ram[14] |= BOOT_POT; ! 869: ! 870: /* Set clock chip bit */ ! 871: switch (ConfigureParams.System.nRTC) { ! 872: case MCCS1850: rtc.ram[17] |= NEW_CLOCK_CHIP; break; ! 873: case MC68HC68T1: rtc.ram[17] &= ~NEW_CLOCK_CHIP; break; ! 874: default: break; ! 875: } ! 876: ! 877: /* Set prefered console slot */ ! 878: rtc.ram[17] |= USE_CONSOLE_SLOT; ! 879: for (i = 0; i < ND_MAX_BOARDS; i++) { ! 880: if (ConfigureParams.Dimension.bMainDisplay && ! 881: (ConfigureParams.Dimension.nMainDisplay == i) && ! 882: ConfigureParams.Dimension.board[i].bEnabled) { ! 883: rtc.ram[17] |= (ND_SLOT(i)>>1)<<3; ! 884: break; ! 885: } ! 886: } ! 887: ! 888: /* Re-calculate checksum */ ! 889: nvram_checksum(1); ! 890: } ! 891: ! 892: void nvram_checksum(int force) { ! 893: int sum,i; ! 894: sum=0; ! 895: for (i=0;i<30;i+=2) { ! 896: sum+=(rtc.ram[i]<<8)|(rtc.ram[i+1]); ! 897: if (sum>=0x10000) { ! 898: sum-=0x10000; ! 899: sum+=1; ! 900: } ! 901: } ! 902: ! 903: sum=0xFFFF-sum; ! 904: ! 905: if (force) { ! 906: rtc.ram[30]=(sum&0xFF00)>>8; ! 907: rtc.ram[31]=(sum&0xFF); ! 908: Log_Printf(LOG_WARN,"Forcing RTC checksum to %x %x",rtc.ram[30],rtc.ram[31]); ! 909: } else { ! 910: Log_Printf(LOG_WARN,"Check RTC checksum to %x %x %x %x", ! 911: rtc.ram[30],(sum&0xFF00)>>8, ! 912: rtc.ram[31],(sum&0xFF)); ! 913: } ! 914: } ! 915: ! 916: ! 917: #if 1 ! 918: static char rtc_ram_info[1024]; ! 919: char * get_rtc_ram_info(void) { ! 920: char buf[256]; ! 921: int sum; ! 922: int i; ! 923: int ni_vol_l,ni_vol_r,ni_brightness; ! 924: int ni_hw_pwd; ! 925: sprintf(buf,"Rtc info:\n"); ! 926: strcpy(rtc_ram_info,buf); ! 927: ! 928: // struct nvram_info { ! 929: // #define NI_RESET 9 ! 930: // u_int ni_reset : 4, ! 931: ! 932: sprintf(buf,"RTC RESET:x%1X ",rtc.ram[0]>>4); ! 933: strcat(rtc_ram_info,buf); ! 934: ! 935: // #define SCC_ALT_CONS 0x08000000 ! 936: // ni_alt_cons : 1, ! 937: if (rtc.ram[0]&0x08) strcat(rtc_ram_info,"ALT_CONS "); ! 938: // #define ALLOW_EJECT 0x04000000 ! 939: // ni_allow_eject : 1, ! 940: if (rtc.ram[0]&0x04) strcat(rtc_ram_info,"ALLOW_EJECT "); ! 941: // ni_vol_r : 6, ! 942: // ni_brightness : 6, ! 943: // #define HW_PWD 0x6 ! 944: // ni_hw_pwd : 4, ! 945: // ni_vol_l : 6, ! 946: // ni_spkren : 1, ! 947: // ni_lowpass : 1, ! 948: // #define BOOT_ANY 0x00000002 ! 949: // ni_boot_any : 1, ! 950: // #define ANY_CMD 0x00000001 ! 951: // ni_any_cmd : 1; ! 952: ! 953: ni_vol_r=(((rtc.ram[0]&0x3)<<4)|((rtc.ram[1]&0xF0)>>4)); ! 954: ni_brightness=(((rtc.ram[1]&0xF)<<2)|((rtc.ram[2]&0xC0)>>6)); ! 955: ni_vol_l=((rtc.ram[2]&0x3F)<<2); ! 956: ni_hw_pwd=(rtc.ram[3]&0xF0)>>4; ! 957: sprintf(buf,"VOL_R:x%1X BRIGHT:x%1X HWPWD:x%1X VOL_L:x%1X",ni_vol_r,ni_brightness,ni_vol_l,ni_hw_pwd); ! 958: strcat(rtc_ram_info,buf); ! 959: ! 960: if (rtc.ram[3]&0x08) strcat(rtc_ram_info,"SPK_ENABLE "); ! 961: if (rtc.ram[3]&0x04) strcat(rtc_ram_info,"LOW_PASS "); ! 962: if (rtc.ram[3]&0x02) strcat(rtc_ram_info,"BOOT_ANY "); ! 963: if (rtc.ram[3]&0x01) strcat(rtc_ram_info,"ANY_CMD "); ! 964: ! 965: ! 966: ! 967: // #define NVRAM_HW_PASSWD 6 ! 968: // u_char ni_ep[NVRAM_HW_PASSWD]; ! 969: ! 970: sprintf(buf,"NVRAM_HW_PASSWD:%2X %2X %2X %2X %2X %2X ",rtc.ram[4],rtc.ram[5],rtc.ram[6],rtc.ram[7],rtc.ram[8],rtc.ram[9]); ! 971: strcat(rtc_ram_info,buf); ! 972: // #define ni_enetaddr ni_ep ! 973: // #define ni_hw_passwd ni_ep ! 974: // u_short ni_simm; /* 4 SIMMs, 4 bits per SIMM */ ! 975: sprintf(buf,"SIMM:%1X %1X %1X %1X ",rtc.ram[10]>>4,rtc.ram[10]&0x0F,rtc.ram[11]>>4,rtc.ram[11]&0x0F); ! 976: strcat(rtc_ram_info,buf); ! 977: ! 978: ! 979: // char ni_adobe[2]; ! 980: sprintf(buf,"ADOBE:%2X %2X ",rtc.ram[12],rtc.ram[13]); ! 981: strcat(rtc_ram_info,buf); ! 982: ! 983: // u_char ni_pot[3]; ! 984: sprintf(buf,"POT:%2X %2X %2X ",rtc.ram[14],rtc.ram[15],rtc.ram[16]); ! 985: strcat(rtc_ram_info,buf); ! 986: ! 987: // u_char ni_new_clock_chip : 1, ! 988: // ni_auto_poweron : 1, ! 989: // ni_use_console_slot : 1, /* Console slot was set by user. */ ! 990: // ni_console_slot : 2, /* Preferred console dev slot>>1 */ ! 991: // ni_use_parity_mem : 1, /* Use parity RAM if available? */ ! 992: // : 2; ! 993: if (rtc.ram[17]&0x80) strcat(rtc_ram_info,"NEW_CLOCK_CHIP "); ! 994: if (rtc.ram[17]&0x40) strcat(rtc_ram_info,"AUTO_POWERON "); ! 995: if (rtc.ram[17]&0x20) strcat(rtc_ram_info,"CONSOLE_SLOT "); ! 996: ! 997: sprintf(buf,"console_slot:%X ",(rtc.ram[17]&0x18)>>3); ! 998: strcat(rtc_ram_info,buf); ! 999: ! 1000: if (rtc.ram[17]&0x04) strcat(rtc_ram_info,"USE_PARITY "); ! 1001: ! 1002: ! 1003: strcat(rtc_ram_info,"boot_command:"); ! 1004: for (i=0;i<12;i++) { ! 1005: if ((rtc.ram[18+i]>=0x20) && (rtc.ram[18+i]<=0x7F)) { ! 1006: sprintf(buf,"%c",rtc.ram[18+i]); ! 1007: strcat(rtc_ram_info,buf); ! 1008: } ! 1009: } ! 1010: ! 1011: strcat(rtc_ram_info," "); ! 1012: sprintf(buf,"CKSUM:%2X %2X ",rtc.ram[30],rtc.ram[31]); ! 1013: strcat(rtc_ram_info,buf); ! 1014: ! 1015: ! 1016: sum=0; ! 1017: for (i=0;i<30;i+=2) { ! 1018: sum+=(rtc.ram[i]<<8)|(rtc.ram[i+1]); ! 1019: if (sum>=0x10000) { sum-=0x10000; ! 1020: sum+=1; ! 1021: } ! 1022: } ! 1023: ! 1024: sum=0xFFFF-sum; ! 1025: ! 1026: sprintf(buf,"CALC_CKSUM:%04X ",sum&0xFFFF); ! 1027: strcat(rtc_ram_info,buf); ! 1028: ! 1029: // #define NVRAM_BOOTCMD 12 ! 1030: // char ni_bootcmd[NVRAM_BOOTCMD]; ! 1031: // u_short ni_cksum; ! 1032: // }; ! 1033: ! 1034: return rtc_ram_info; ! 1035: } ! 1036: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.