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