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