|
|
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.