|
|
1.1 root 1: /* NeXT system registers emulation */
2:
3: #include <stdlib.h>
4: #include "main.h"
5: #include "ioMem.h"
6: #include "ioMemTables.h"
7: #include "video.h"
8: #include "configuration.h"
9: #include "sysdeps.h"
10: #include "m68000.h"
11: #include "sysReg.h"
12: #include "statusbar.h"
13:
14:
15: #define IO_SEG_MASK 0x1FFFF
16:
17: static Uint32 scr1=0x00000000;
18: static Uint32 turboscr1=0x00000000;
19:
20: static Uint8 scr2_0=0x00;
21: static Uint8 scr2_1=0x00;
22: static Uint8 scr2_2=0x80;
23: static Uint8 scr2_3=0x00;
24:
25: static Uint32 intStat=0x00000000;
26: static Uint32 intMask=0x00000000;
27:
28:
29: /* RTC NVRAM */
30:
31: // file mon/nvram.h
32: // struct nvram_info {
33: // #define NI_RESET 9
34: // u_int ni_reset : 4,
35: // #define SCC_ALT_CONS 0x08000000
36: // ni_alt_cons : 1,
37: // #define ALLOW_EJECT 0x04000000
38: // ni_allow_eject : 1,
39: // ni_vol_r : 6,
40: // ni_brightness : 6,
41: // #define HW_PWD 0x6
42: // ni_hw_pwd : 4,
43: // ni_vol_l : 6,
44: // ni_spkren : 1,
45: // ni_lowpass : 1,
46: // #define BOOT_ANY 0x00000002
47: // ni_boot_any : 1,
48: // #define ANY_CMD 0x00000001
49: // ni_any_cmd : 1;
50: // #define NVRAM_HW_PASSWD 6
51: // u_char ni_ep[NVRAM_HW_PASSWD];
52: // #define ni_enetaddr ni_ep
53: // #define ni_hw_passwd ni_ep
54: // u_short ni_simm; /* 4 SIMMs, 4 bits per SIMM */
55: // char ni_adobe[2];
56: // u_char ni_pot[3];
57: // u_char ni_new_clock_chip : 1,
58: // ni_auto_poweron : 1,
59: // ni_use_console_slot : 1, /* Console slot was set by user. */
60: // ni_console_slot : 2, /* Preferred console dev slot>>1 */
61: // ni_use_parity_mem : 1, /* Use parity RAM if available? */
62: // : 2;
63: // #define NVRAM_BOOTCMD 12
64: // char ni_bootcmd[NVRAM_BOOTCMD];
65: // u_short ni_cksum;
66: // };
67:
68: // #define N_brightness 0
69: // #define N_volume_l 1
70: // #define N_volume_r 2
71:
72: /* nominal values during self test */
73: // #define BRIGHT_NOM 20
74: // #define VOL_NOM 0
75:
76: /* bits in ni_pot[0] */
77: #define POT_ON 0x01
78: #define EXTENDED_POT 0x02
79: #define LOOP_POT 0x04
80: #define VERBOSE_POT 0x08
81: #define TEST_DRAM_POT 0x10
82: #define BOOT_POT 0x20
83: #define TEST_MONITOR_POT 0x40
84:
85: /* bits in byte 17 */
86: #define NEW_CLOCK_CHIP 0x80
87: #define AUTO_POWERON 0x40
88: #define USE_CONSOLE_SLOT 0x20
89: #define CONSOLE_SLOT 0x18
90: #define USE_PARITY_MEM 0x40
91:
92: /* bits in ni_simm (rtc ram byte 10 and 11) *
93: * -------- -----xxx bit 0 - 2: 1st simm: bit 1+2 define size, bit 3 defines page mode
94: * -------- --xxx--- bit 3 - 5: 2nd simm: bit 1+2 define size, bit 3 defines page mode
95: * -------x xx------ bit 6 - 8: 3rd simm: bit 1+2 define size, bit 3 defines page mode
96: * ----xxx- -------- bit 9 -11: 4th simm: bit 1+2 define size, bit 3 defines page mode
97: * xxxx---- -------- bit 12-15: defines parity, 1 bit for each simm (ignored on 68030)
98: */
99: /* for 68030 and monochrome non-turbo systems */
100: #define SIMM_EMPTY 0x0
101: #define SIMM_16MB 0x1 /* Group of four 4 Mbyte SIMMs */
102: #define SIMM_4MB 0x2 /* Group of four 1 Mbyte SIMMs */
103: #define SIMM_1MB 0x3 /* Group of four 256 KByte SIMMs */
104: #define SIMM_PAGE_MODE 0x4 /* SIMM type is page mode, else nibble mode */
105: /* for all 68040 systems */
106: #define SIMM_PARITY 0x8 /* SIMMs support parity */
107: /* for non-turbo color systems */
108: #define SIMM_8MB_C 0x1 /* Pair of 4 Mbyte SIMMs */
109: #define SIMM_2MB_C 0x2 /* Pair of 1 Mbyte SIMMs */
110: #define SIMM_EMPTY2 0x3 /* reserved */
111: /* for turbo systems */
112: #define SIMM_32MB_T 0x1 /* Pair of 16 or 32 MByte SIMMs (front or back) */
113: #define SIMM_8MB_T 0x2 /* Pair of 4 or 8 MByte SIMMs (front or back) */
114: #define SIMM_2MB_T 0x3 /* Pair of 1 or 2 MByte SIMMs (front or back) */
115:
116:
117: /* RTC RAM */
118: Uint8 rtc_ram[32]={
119: 0x94,0x0f,0x40,0x00, // byte 0 - 3
120: 0x00,0x00,0x00,0x00,0x00,0x00, // byte 4 - 9: hardware password, ethernet address (?)
121: 0x00,0x00, // byte 10, 11: simm type and size (4 simms, 4 bits per simm), see bits in ni_simm above
122: 0x00,0x00, // byte 12, 13: adobe (?)
123: 0x4b,0x00,0x00, // byte 14: POT, byte 15: oldest ..., byte 16: most recent selftest error code
124: 0x00, // byte 17: bit7:clock chip; 6:auto poweron; 5:enable console slot; 3,4:console slot; 2:parity mem
125: 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // byte 18 - 29: boot command
126: 0x0F,0x13 // byte 30, 31: checksum
127: };
128: Uint8 read_rtc_ram(Uint8 position) {
129: return rtc_ram[position];
130: }
131:
132: Uint8 rtc_ram_default[32]={
133: 0x94,0x0f,0x40,0x00,0x00,0x00,0x00,0x00,
134: 0x00,0x00,0x00,0x00,0x00,0x00,0x4b,0x00,
135: 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
136: 0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x13
137: };
138:
139: /*
140: Uint8 rtc_ram[32]={ // values from nextcomputers.org forums
141: 0x94,0x0f,0x40,0x03,0x00,0x00,0x00,0x00,
142: 0x00,0x00,0xfb,0x6d,0x00,0x00,0x4b,0x00,
143: 0x41,0x00,0x20,0x00,0x00,0x00,0x00,0x00,
144: 0x00,0x00,0x00,0x00,0x00,0x00,0x84,0x7e
145: };
146: */
147:
148: /*
149: old value (boot to network diagnostics)
150: Uint8 rtc_ram[32]={
151: 0x94,0x0f,0x40,0x00,0x00,0x00,0x00,0x00,
152: 0x00,0x00,0xfb,0x6d,0x00,0x00,0x7B,0x00,
153: 0x00,0x00,0x65,0x6e,0x00,0x00,0x00,0x00,
154: 0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x13
155: };
156: */
157:
158: void nvram_init(void) {
159: /* Reset RTC RAM to default values */
160: memcpy(rtc_ram, rtc_ram_default, sizeof(rtc_ram_default));
161:
162: /* Build boot command */
163: switch (ConfigureParams.Boot.nBootDevice) {
164: case BOOT_ROM:
165: rtc_ram[18] = 0x00;
166: rtc_ram[19] = 0x00;
167: break;
168: case BOOT_SCSI:
169: rtc_ram[18] = 's';
170: rtc_ram[19] = 'd';
171: break;
172: case BOOT_ETHERNET:
173: rtc_ram[18] = 'e';
174: rtc_ram[19] = 'n';
175: break;
176: case BOOT_MO:
177: rtc_ram[18] = 'o';
178: rtc_ram[19] = 'd';
179: break;
180: case BOOT_FLOPPY:
181: rtc_ram[18] = 'f';
182: rtc_ram[19] = 'd';
183: break;
184:
185: default: break;
186: }
187:
188: /* Copy ethernet address from ROM to RTC RAM */
189: int i;
190: for (i = 0; i<6; i++) {
191: rtc_ram[i+4]=NEXTRom[i+8];
192: }
193:
194: /* Build SIMM bytes (for now only valid on monochrome systems) */
195: Uint16 SIMMconfig = 0x0000;
196: Uint8 simm[4];
197: Uint8 parity = 0xF0;
198: if (ConfigureParams.System.bTurbo) {
199: for (i = 0; i<4; i++) {
200: switch (MemBank_Size[i]>>20) {
201: case 0: simm[i] = SIMM_EMPTY; parity &= ~(0x10<<i); break;
202: case 2: simm[i] = SIMM_2MB_T; break;
203: case 8: simm[i] = SIMM_8MB_T; break;
204: case 32: simm[i] = SIMM_32MB_T; break;
205: default: simm[i] = SIMM_EMPTY; break;
206: }
207: }
208:
209: } else if (ConfigureParams.System.bColor) {
210: for (i = 0; i<4; i++) {
211: switch (MemBank_Size[i]>>20) {
212: case 0: simm[i] = SIMM_EMPTY; parity &= ~(0x10<<i); break;
213: case 2: simm[i] = SIMM_2MB_C; break;
214: case 8: simm[i] = SIMM_8MB_C; break;
215: default: simm[i] = SIMM_EMPTY; break;
216: }
217: }
218:
219: } else {
220: for (i = 0; i<4; i++) {
221: switch (MemBank_Size[i]>>20) {
222: case 0: simm[i] = SIMM_EMPTY; parity &= ~(0x10<<i); break;
223: case 1: simm[i] = SIMM_1MB | SIMM_PAGE_MODE; break;
224: case 4: simm[i] = SIMM_4MB | SIMM_PAGE_MODE; break;
225: case 16: simm[i] = SIMM_16MB | SIMM_PAGE_MODE; break;
226: default: simm[i] = SIMM_EMPTY | SIMM_PAGE_MODE; break;
227: }
228: }
229: }
230:
231: SIMMconfig = ((parity&0xF0)<<8) | (simm[3]<<9) | (simm[2]<<6) | (simm[1]<<3) | simm[0];
232: rtc_ram[10] = (SIMMconfig>>8)&0xFF;
233: rtc_ram[11] = SIMMconfig&0xFF;
234:
235: /* Build POT byte[0] */
236: rtc_ram[14] = 0x00;
237: if (ConfigureParams.Boot.bEnableDRAMTest)
238: rtc_ram[14] |= TEST_DRAM_POT;
239: if (ConfigureParams.Boot.bEnablePot)
240: rtc_ram[14] |= POT_ON;
241: if (ConfigureParams.Boot.bEnableSoundTest)
242: rtc_ram[14] |= TEST_MONITOR_POT;
243: if (ConfigureParams.Boot.bEnableSCSITest)
244: rtc_ram[14] |= EXTENDED_POT;
245: if (ConfigureParams.Boot.bLoopPot)
246: rtc_ram[14] |= LOOP_POT;
247: if (ConfigureParams.Boot.bVerbose)
248: rtc_ram[14] |= VERBOSE_POT;
249: if (ConfigureParams.Boot.bExtendedPot)
250: rtc_ram[14] |= BOOT_POT;
251:
252: /* Set clock chip bit */
253: switch (ConfigureParams.System.nRTC) {
254: case MCS1850: rtc_ram[17] |= NEW_CLOCK_CHIP; break;
255: case MC68HC68T1: rtc_ram[17] &= ~NEW_CLOCK_CHIP; break;
256: default: break;
257: }
258:
259: /* Re-calculate checksum */
260: rtc_checksum(1);
261: }
262:
263: void rtc_checksum(int force) {
264: int sum,i;
265: sum=0;
266: for (i=0;i<30;i+=2) {
267: sum+=(rtc_ram[i]<<8)|(rtc_ram[i+1]);
268: if (sum>=0x10000) {
269: sum-=0x10000;
270: sum+=1;
271: }
272: }
273:
274: sum=0xFFFF-sum;
275:
276: if (force) {
277: rtc_ram[30]=(sum&0xFF00)>>8;
278: rtc_ram[31]=(sum&0xFF);
279: Log_Printf(LOG_WARN,"Forcing RTC checksum to %x %x",rtc_ram[30],rtc_ram[31]);
280: } else {
281: Log_Printf(LOG_WARN,"Check RTC checksum to %x %x %x %x",
282: rtc_ram[30],(sum&0xFF00)>>8,
283: rtc_ram[31],(sum&0xFF));
284: }
285: }
286:
287: static char rtc_ram_info[1024];
288: char * get_rtc_ram_info(void) {
289: char buf[256];
290: int sum;
291: int i;
292: int ni_vol_l,ni_vol_r,ni_brightness;
293: int ni_hw_pwd,ni_spkren,ni_lowpass;
294: sprintf(buf,"Rtc info:\n");
295: strcpy(rtc_ram_info,buf);
296:
297: // struct nvram_info {
298: // #define NI_RESET 9
299: // u_int ni_reset : 4,
300:
301: sprintf(buf,"RTC RESET:x%1X ",rtc_ram[0]>>4);
302: strcat(rtc_ram_info,buf);
303:
304: // #define SCC_ALT_CONS 0x08000000
305: // ni_alt_cons : 1,
306: if (rtc_ram[0]&0x08) strcat(rtc_ram_info,"ALT_CONS ");
307: // #define ALLOW_EJECT 0x04000000
308: // ni_allow_eject : 1,
309: if (rtc_ram[0]&0x04) strcat(rtc_ram_info,"ALLOW_EJECT ");
310: // ni_vol_r : 6,
311: // ni_brightness : 6,
312: // #define HW_PWD 0x6
313: // ni_hw_pwd : 4,
314: // ni_vol_l : 6,
315: // ni_spkren : 1,
316: // ni_lowpass : 1,
317: // #define BOOT_ANY 0x00000002
318: // ni_boot_any : 1,
319: // #define ANY_CMD 0x00000001
320: // ni_any_cmd : 1;
321:
322: ni_vol_r=(((rtc_ram[0]&0x3)<<4)|((rtc_ram[1]&0xF0)>>4));
323: ni_brightness=(((rtc_ram[1]&0xF)<<2)|((rtc_ram[2]&0xC0)>>6));
324: ni_vol_l=((rtc_ram[2]&0x3F)<<2);
325: ni_hw_pwd=(rtc_ram[3]&0xF0)>>4;
326: 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);
327: strcat(rtc_ram_info,buf);
328:
329: if (rtc_ram[3]&0x08) strcat(rtc_ram_info,"SPK_ENABLE ");
330: if (rtc_ram[3]&0x04) strcat(rtc_ram_info,"LOW_PASS ");
331: if (rtc_ram[3]&0x02) strcat(rtc_ram_info,"BOOT_ANY ");
332: if (rtc_ram[3]&0x01) strcat(rtc_ram_info,"ANY_CMD ");
333:
334:
335:
336: // #define NVRAM_HW_PASSWD 6
337: // u_char ni_ep[NVRAM_HW_PASSWD];
338:
339: 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]);
340: strcat(rtc_ram_info,buf);
341: // #define ni_enetaddr ni_ep
342: // #define ni_hw_passwd ni_ep
343: // u_short ni_simm; /* 4 SIMMs, 4 bits per SIMM */
344: sprintf(buf,"SIMM:%1X %1X %1X %1X ",rtc_ram[10]>>4,rtc_ram[10]&0x0F,rtc_ram[11]>>4,rtc_ram[11]&0x0F);
345: strcat(rtc_ram_info,buf);
346:
347:
348: // char ni_adobe[2];
349: sprintf(buf,"ADOBE:%2X %2X ",rtc_ram[12],rtc_ram[13]);
350: strcat(rtc_ram_info,buf);
351:
352: // u_char ni_pot[3];
353: sprintf(buf,"POT:%2X %2X %2X ",rtc_ram[14],rtc_ram[15],rtc_ram[16]);
354: strcat(rtc_ram_info,buf);
355:
356: // u_char ni_new_clock_chip : 1,
357: // ni_auto_poweron : 1,
358: // ni_use_console_slot : 1, /* Console slot was set by user. */
359: // ni_console_slot : 2, /* Preferred console dev slot>>1 */
360: // ni_use_parity_mem : 1, /* Use parity RAM if available? */
361: // : 2;
362: if (rtc_ram[17]&0x80) strcat(rtc_ram_info,"NEW_CLOCK_CHIP ");
363: if (rtc_ram[17]&0x40) strcat(rtc_ram_info,"AUTO_POWERON ");
364: if (rtc_ram[17]&0x20) strcat(rtc_ram_info,"CONSOLE_SLOT ");
365:
366: sprintf(buf,"console_slot:%X ",(rtc_ram[17]&0x18)>>3);
367: strcat(rtc_ram_info,buf);
368:
369: if (rtc_ram[17]&0x04) strcat(rtc_ram_info,"USE_PARITY ");
370:
371:
372: strcat(rtc_ram_info,"boot_command:");
373: for (i=0;i<12;i++) {
374: if ((rtc_ram[18+i]>=0x20) && (rtc_ram[18+i]<=0x7F)) {
375: sprintf(buf,"%c",rtc_ram[18+i]);
376: strcat(rtc_ram_info,buf);
377: }
378: }
379:
380: strcat(rtc_ram_info," ");
381: sprintf(buf,"CKSUM:%2X %2X ",rtc_ram[30],rtc_ram[31]);
382: strcat(rtc_ram_info,buf);
383:
384:
385: sum=0;
386: for (i=0;i<30;i+=2) {
387: sum+=(rtc_ram[i]<<8)|(rtc_ram[i+1]);
388: if (sum>=0x10000) { sum-=0x10000;
389: sum+=1;
390: }
391: }
392:
393: sum=0xFFFF-sum;
394:
395: sprintf(buf,"CALC_CKSUM:%04X ",sum&0xFFFF);
396: strcat(rtc_ram_info,buf);
397:
398: // #define NVRAM_BOOTCMD 12
399: // char ni_bootcmd[NVRAM_BOOTCMD];
400: // u_short ni_cksum;
401: // };
402:
403: return rtc_ram_info;
404: }
405:
406:
407: void SID_Read(void) {
408: Log_Printf(LOG_WARN,"SID read at $%08x PC=$%08x\n", IoAccessCurrentAddress,m68k_getpc());
409: IoMem[IoAccessCurrentAddress & 0x1FFFF]=0x00; // slot ID 0
410: }
411:
412: /* System Control Register 1
413: *
414: * These values are valid for all non-Turbo systems:
415: * -------- -------- -------- ------xx bits 0:1 --> cpu speed
416: * -------- -------- -------- ----xx-- bits 2:3 --> reserved
417: * -------- -------- -------- --xx---- bits 4:5 --> main memory speed
418: * -------- -------- -------- xx------ bits 6:7 --> video memory speed
419: * -------- -------- ----xxxx -------- bits 8:11 --> board revision
420: * -------- -------- xxxx---- -------- bits 12:15 --> cpu type
421: * -------- xxxxxxxx -------- -------- bits 16:23 --> dma revision
422: * ----xxxx -------- -------- -------- bits 24:27 --> reserved
423: * xxxx---- -------- -------- -------- bits 28:31 --> slot id
424: *
425: * cpu speed: 0 = 40MHz, 1 = 20MHz, 2 = 25MHz, 3 = 33MHz
426: * main mem speed: 0 = 120ns, 1 = 100ns, 2 = 80ns, 3 = 60ns
427: * video mem speed: 0 = 120ns, 1 = 100ns, 2 = 80ns, 3 = 60ns
428: * board revision: for 030 Cube:
429: * 0 = DCD input inverted
430: * 1 = DCD polarity fixed
431: * 2 = must disable DSP mem before reset
432: * cpu type: 0 = NeXT Computer (68030)
433: * 1 = NeXTstation monochrome
434: * 2 = NeXTcube
435: * 3 = NeXTstation color
436: * 4 = all Turbo systems
437: * dma revision: 1 on all systems ?
438: * slot id: f on Turbo systems (cube too?), 0 on other systems
439: *
440: *
441: * These bits are always 0 on all Turbo systems:
442: * ----xxxx xxxxxxxx ----xxxx xxxxxxxx
443: */
444:
445: /* for Slab 040:
446: * 0000 0000 0000 0001 0001 0000 0101 0010
447: * 00 01 10 52
448: *
449: * for Cube 030:
450: * 0000 0000 0000 0001 0000 0001 0101 0010
451: * 00 01 01 52
452: */
453: #define SCR1_NEXT_COMPUTER 0x00010152
454: #define SCR1_SLAB_MONO 0x00011052
455: #define SCR1_SLAB_COLOR 0x00013052
456: #define SCR1_CUBE 0x00012052
457: #define SCR1_TURBO 0xF0004000
458:
459: #define SCR1_CONST_MASK 0xFFFFFF00
460:
461: void SCR_Reset(void) {
462: scr2_0=0x00;
463: scr2_1=0x00;
464: scr2_2=0x80;
465: scr2_3=0x00;
466:
467: intStat=0x00000000;
468: intMask=0x00000000;
469:
470: if (ConfigureParams.System.bTurbo) {
471: scr1 = SCR1_TURBO;
472: TurboSCR1_Reset();
473: return;
474: } else {
475: switch (ConfigureParams.System.nMachineType) {
476: case NEXT_CUBE030:
477: scr1 = SCR1_NEXT_COMPUTER & SCR1_CONST_MASK;
478: break;
479: case NEXT_CUBE040:
480: scr1 = SCR1_CUBE & SCR1_CONST_MASK;
481: break;
482: case NEXT_STATION:
483: if (ConfigureParams.System.bColor)
484: scr1 = SCR1_SLAB_COLOR & SCR1_CONST_MASK;
485: else
486: scr1 = SCR1_SLAB_MONO & SCR1_CONST_MASK;
487: break;
488: default:
489: break;
490: }
491: }
492:
493: Uint8 cpu_speed = ((ConfigureParams.System.nCpuFreq/8)-1)%4;
494: Uint8 memory_speed;
495: switch (ConfigureParams.Memory.nMemorySpeed) {
496: case MEMORY_120NS: memory_speed = 0x00; break;
497: case MEMORY_100NS: memory_speed = 0x50; break;
498: case MEMORY_80NS: memory_speed = 0xA0; break;
499: case MEMORY_60NS: memory_speed = 0xF0; break;
500: default: Log_Printf(LOG_WARN, "SCR1 error: unknown memory speed\n"); break;
501: }
502: scr1 |= ((memory_speed&0xF0)|(cpu_speed&0x03));
503: }
504:
505: void SCR1_Read0(void)
506: {
507: Log_Printf(LOG_WARN,"SCR1 read at $%08x PC=$%08x\n", IoAccessCurrentAddress,m68k_getpc());
508: IoMem[IoAccessCurrentAddress&IO_SEG_MASK] = (scr1&0xFF000000)>>24;
509: }
510: void SCR1_Read1(void)
511: {
512: Log_Printf(LOG_WARN,"SCR1 read at $%08x PC=$%08x\n", IoAccessCurrentAddress,m68k_getpc());
513: IoMem[IoAccessCurrentAddress&IO_SEG_MASK] = (scr1&0x00FF0000)>>16;
514: }
515: void SCR1_Read2(void)
516: {
517: Log_Printf(LOG_WARN,"SCR1 read at $%08x PC=$%08x\n", IoAccessCurrentAddress,m68k_getpc());
518: IoMem[IoAccessCurrentAddress&IO_SEG_MASK] = (scr1&0x0000FF00)>>8;
519: }
520: void SCR1_Read3(void)
521: {
522: Log_Printf(LOG_WARN,"SCR1 read at $%08x PC=$%08x\n", IoAccessCurrentAddress,m68k_getpc());
523: IoMem[IoAccessCurrentAddress&IO_SEG_MASK] = scr1&0x000000FF;
524: }
525:
526:
527: /* Additional System Control Register for Turbo systems:
528: * -------- -------- -------- -----?xx bits 0:2 --> cpu speed
529: * -------- -------- -------- --xx---- bits 4:5 --> main memory speed
530: * -------- -------- -------- xx------ bits 6:7 --> video memory speed
531: * -------- -------- xxxx---- -------- bits 8:11 --> cpu type
532: * xxxxxxxx xxxxxxxx ----xxxx ----?--- all other bits: 1
533: *
534: * cpu speed: 7 = 33MHz?
535: * main mem speed: 0 = 120ns?, 1 = 100ns?, 2 = 70ns, 3 = 60ns
536: * video mem speed: 3 on all Turbo systems (60ns)?
537: * cpu type: 4 = NeXTstation turbo monochrome
538: * 5 = NeXTstation turbo color
539: */
540:
541: #define TURBOSCR_FMASK 0xFFFF0F08
542:
543: void TurboSCR1_Reset(void) {
544: Uint8 memory_speed;
545: Uint8 cpu_speed = 0x07; // 33 MHz
546: switch (ConfigureParams.Memory.nMemorySpeed) {
547: case MEMORY_120NS: memory_speed = 0xC0; break;
548: case MEMORY_100NS: memory_speed = 0xD0; break;
549: case MEMORY_80NS: memory_speed = 0xE0; break;
550: case MEMORY_60NS: memory_speed = 0xF0; break;
551: default: Log_Printf(LOG_WARN, "Turbo SCR1 error: unknown memory speed\n"); break;
552: }
553: turboscr1 = ((memory_speed&0xF0)|(cpu_speed&0x07));
554: if (ConfigureParams.System.bColor) {
555: turboscr1 |= 0x5000;
556: } else {
557: turboscr1 |= 0x4000;
558: }
559: turboscr1 |= TURBOSCR_FMASK;
560: }
561:
562: void TurboSCR1_Read0(void) {
563: Log_Printf(LOG_WARN,"Turbo SCR1 read at $%08x PC=$%08x\n", IoAccessCurrentAddress,m68k_getpc());
564: IoMem_WriteWord(IoAccessCurrentAddress&0x1FFFF, (turboscr1&0xFFFF0000)>>16);
565: }
566: void TurboSCR1_Read2(void) {
567: Log_Printf(LOG_WARN,"Turbo SCR1 read at $%08x PC=$%08x\n", IoAccessCurrentAddress,m68k_getpc());
568: IoMem_WriteWord(IoAccessCurrentAddress&0x1FFFF, turboscr1&0x0000FFFF);
569: }
570:
571:
572:
573: /* System Control Register 2
574:
575: s_dsp_reset : 1,
576: s_dsp_block_end : 1,
577: s_dsp_unpacked : 1,
578: s_dsp_mode_B : 1,
579: s_dsp_mode_A : 1,
580: s_remote_int : 1,
581: s_local_int : 2,
582: s_dram_256K : 4,
583: s_dram_1M : 4,
584: s_timer_on_ipl7 : 1,
585: s_rom_wait_states : 3,
586: s_rom_1M : 1,
587: s_rtdata : 1,
588: s_rtclk : 1,
589: s_rtce : 1,
590: s_rom_overlay : 1,
591: s_dsp_int_en : 1,
592: s_dsp_mem_en : 1,
593: s_reserved : 4,
594: s_led : 1;
595:
596: */
597:
598: #define SCR2_SOFTINT2 0x02
599: #define SCR2_SOFTINT1 0x01
600:
601: #define SCR2_TIMERIPL7 0x80
602: #define SCR2_RTDATA 0x04
603: #define SCR2_RTCLK 0x02
604: #define SCR2_RTCE 0x01
605:
606: #define SCR2_LED 0x01
607: #define SCR2_ROM 0x80
608:
609:
610: void SCR2_Write0(void)
611: {
612: Uint8 old_scr2_0=scr2_0;
613: // Log_Printf(LOG_WARN,"SCR2 write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress,IoMem[IoAccessCurrentAddress & IO_SEG_MASK],m68k_getpc());
614: scr2_0=IoMem[IoAccessCurrentAddress & 0x1FFFF];
615:
616: if ((old_scr2_0&SCR2_SOFTINT1)!=(scr2_0&SCR2_SOFTINT1)) {
617: Log_Printf(LOG_WARN,"SCR2 SCR2_SOFTINT1 change at $%08x val=%x PC=$%08x\n",
618: IoAccessCurrentAddress,scr2_0&SCR2_SOFTINT1,m68k_getpc());
619: if (scr2_0&SCR2_SOFTINT1)
620: set_interrupt(INT_SOFT1,SET_INT);
621: else
622: set_interrupt(INT_SOFT1,RELEASE_INT);
623: }
624:
625: if ((old_scr2_0&SCR2_SOFTINT2)!=(scr2_0&SCR2_SOFTINT2)) {
626: Log_Printf(LOG_WARN,"SCR2 SCR2_SOFTINT2 change at $%08x val=%x PC=$%08x\n",
627: IoAccessCurrentAddress,scr2_0&SCR2_SOFTINT2,m68k_getpc());
628: if (scr2_0&SCR2_SOFTINT2)
629: set_interrupt(INT_SOFT2,SET_INT);
630: else
631: set_interrupt(INT_SOFT2,RELEASE_INT);
632: }
633: }
634:
635: void SCR2_Read0(void)
636: {
637: // Log_Printf(LOG_WARN,"SCR2 read at $%08x PC=$%08x\n", IoAccessCurrentAddress,m68k_getpc());
638: IoMem[IoAccessCurrentAddress & 0x1FFFF]=scr2_0;
639: }
640:
641: void SCR2_Write1(void)
642: {
643: // Log_Printf(LOG_WARN,"SCR2 write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress,IoMem[IoAccessCurrentAddress & IO_SEG_MASK],m68k_getpc());
644: scr2_1=IoMem[IoAccessCurrentAddress & 0x1FFFF];
645: }
646:
647: void SCR2_Read1(void)
648: {
649: // Log_Printf(LOG_WARN,"SCR2 read at $%08x PC=$%08x\n", IoAccessCurrentAddress,m68k_getpc());
650: IoMem[IoAccessCurrentAddress & 0x1FFFF]=scr2_1;
651: }
652:
653: void SCR2_Write2(void)
654: {
655: static int phase=0;
656: static bool burst=false;
657: static Uint8 rtc_command=0;
658: static Uint8 rtc_value=0;
659: static Uint8 rtc_return=0;
660: static Uint8 rtc_status=0x00;
661: static Uint8 rtc_ccr=0x00;
662: static Uint8 rtc_icr=0x00;
663:
664: static int day_in_week=0x02;
665: static int day=0x31;
666: static int month=0x12;
667: static int year=0x98;
668: static int century=0x19;
669:
670:
671: Uint8 old_scr2_2=scr2_2;
672:
673: scr2_2=IoMem[IoAccessCurrentAddress & 0x1FFFF];
674:
675: if ((old_scr2_2&SCR2_TIMERIPL7)!=(scr2_2&SCR2_TIMERIPL7)) {
676: Log_Printf(LOG_WARN,"SCR2 TIMER IPL7 change at $%08x val=%x PC=$%08x\n",
677: IoAccessCurrentAddress,scr2_2&SCR2_TIMERIPL7,m68k_getpc());
678: }
679:
680: // treat only if CE is set to 1
681: if (scr2_2&SCR2_RTCE) {
682: if (phase==-1) {phase=0;}
683:
684: // if we are in going down clock... do something
685: if (((old_scr2_2&SCR2_RTCLK)!=(scr2_2&SCR2_RTCLK)) && ((scr2_2&SCR2_RTCLK)==0) ) {
686: if (phase<8)
687: rtc_command=(rtc_command<<1)|((scr2_2&SCR2_RTDATA)?1:0);
688:
689: // now reading or writing register (one bit at a time)
690: if ((phase>=8) && (phase<16)) {
691: rtc_value=(rtc_value<<1)|((scr2_2&SCR2_RTDATA)?1:0);
692:
693: // if we read RAM register, output RT_DATA bit
694: if (rtc_command<=0x1F) {
695: scr2_2=scr2_2&(~SCR2_RTDATA);
696: if (rtc_ram[rtc_command]&(0x80>>(phase-8)))
697: scr2_2|=SCR2_RTDATA;
698: rtc_return=(rtc_return<<1)|((scr2_2&SCR2_RTDATA)?1:0);
699: }
700: // read the status 0x30
701: if (rtc_command==0x30) {
702: scr2_2=scr2_2&(~SCR2_RTDATA);
703: // for now status = 0x98 (new rtc + FTU)
704: if (rtc_status&(0x80>>(phase-8)))
705: scr2_2|=SCR2_RTDATA;
706: rtc_return=(rtc_return<<1)|((scr2_2&SCR2_RTDATA)?1:0);
707: }
708: // read the status 0x31
709: if (rtc_command==0x31) {
710: scr2_2=scr2_2&(~SCR2_RTDATA);
711: if (rtc_ccr&(0x80>>(phase-8)))
712: scr2_2|=SCR2_RTDATA;
713: rtc_return=(rtc_return<<1)|((scr2_2&SCR2_RTDATA)?1:0);
714: }
715: // read the status 0x32
716: if (rtc_command==0x32) {
717: scr2_2=scr2_2&(~SCR2_RTDATA);
718: if (rtc_icr&(0x80>>(phase-8)))
719: scr2_2|=SCR2_RTDATA;
720: rtc_return=(rtc_return<<1)|((scr2_2&SCR2_RTDATA)?1:0);
721: }
722: if ((rtc_command>=0x20) && (rtc_command<=0x2F)) {
723: unsigned char v;
724: static time_t t;
725: static struct tm * ts;
726:
727: scr2_2=scr2_2&(~SCR2_RTDATA);
728: // get time at once to avoid problems (in burst mode only).
729: if (!burst) {
730: t=time(NULL);
731: ts=localtime(&t);
732: burst=true;
733: }
734: v=0;
735: switch (rtc_command) {
736: case 0x20 : // seconds
737: v=(((ts->tm_sec)/10)<<4)|(ts->tm_sec%10);
738: break;
739: case 0x21 : //min
740: v=(((ts->tm_min)/10)<<4)|(ts->tm_min%10);
741: break;
742: case 0x22 : // hour
743: v=(((ts->tm_hour)/10)<<4)|(ts->tm_hour%10);
744: break;
745: case 0x23 :
746: v=day_in_week;
747: break;
748: case 0x24 :
749: v=day;
750: break;
751: case 0x25 :
752: v=month;
753: break;
754: case 0x26 :
755: v=year;
756: break;
757: case 0x27 :
758: v=century;
759: break;
760: }
761: if (v&(0x80>>(phase-8)))
762: scr2_2|=SCR2_RTDATA;
763: rtc_return=(rtc_return<<1)|((scr2_2&SCR2_RTDATA)?1:0);
764: }
765:
766: } // of read/write phase
767:
768: phase++;
769: if (phase==16) {
770: Log_Printf(LOG_WARN,"SCR2 RTC command complete %x %x %x at PC=$%08x\n",
771: rtc_command,rtc_value,rtc_return,m68k_getpc());
772: if ((rtc_command>=0x80) && (rtc_command<=0x9F))
773: rtc_ram[rtc_command-0x80]=rtc_value;
774:
775: // write to x31 register
776: if (rtc_command==0xB1) {
777: rtc_ccr=rtc_value;
778:
779:
780: // clear FTU
781: if (rtc_value & 0x04) {
782: rtc_status=rtc_status&(~0x18);
783: intStat=intStat&(~0x04);
784: }
785:
786:
787: }
788: // write to x32 register
789: if (rtc_command==0xB2) {
790: rtc_icr=rtc_value;
791: }
792:
793: if (rtc_command==0xA3) {
794: day_in_week=rtc_value;
795: }
796: if (rtc_command==0xA4) {
797: day=rtc_value;
798: }
799: if (rtc_command==0xA5) {
800: month=rtc_value;
801: }
802: if (rtc_command==0xA6) {
803: year=rtc_value;
804: }
805: if (rtc_command==0xA7) {
806: century=rtc_value;
807: }
808:
809: // burst mode
810: phase=8;
811: rtc_command++;
812: } // of phase==16
813: } // of going down clock
814: } // of scr2_2&SCR2_RTCE
815: else {
816: // else end or abort
817: phase=-1;
818: rtc_command=0;
819: rtc_value=0;
820: burst=false;
821: }
822:
823: }
824:
825: void SCR2_Read2(void)
826: {
827: // Log_Printf(LOG_WARN,"SCR2 read at $%08x PC=$%08x\n", IoAccessCurrentAddress,m68k_getpc());
828: // IoMem[IoAccessCurrentAddress & 0x1FFFF]=scr2_2 & (SCR2_RTDATA|SCR2_RTCLK|SCR2_RTCE)); // + data
829: IoMem[IoAccessCurrentAddress & 0x1FFFF]=scr2_2;
830: }
831:
832: int SCR_ROM_overlay=0;
833:
834: void SCR2_Write3(void)
835: {
836: Uint8 old_scr2_3=scr2_3;
837: // Log_Printf(LOG_WARN,"SCR2 write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress,IoMem[IoAccessCurrentAddress & IO_SEG_MASK],m68k_getpc());
838: scr2_3=IoMem[IoAccessCurrentAddress & 0x1FFFF];
839: if ((old_scr2_3&SCR2_ROM)!=(scr2_3&SCR2_ROM)) {
840: Log_Printf(LOG_WARN,"SCR2 ROM change at $%08x val=%x PC=$%08x\n",
841: IoAccessCurrentAddress,scr2_3&SCR2_ROM,m68k_getpc());
842: SCR_ROM_overlay=scr2_3&SCR2_ROM;
843: }
844: if ((old_scr2_3&SCR2_LED)!=(scr2_3&SCR2_LED)) {
845: Log_Printf(LOG_WARN,"SCR2 LED change at $%08x val=%x PC=$%08x\n",
846: IoAccessCurrentAddress,scr2_3&SCR2_LED,m68k_getpc());
847: Statusbar_SetSCR2Led(scr2_3&SCR2_LED);
848: }
849: }
850:
851:
852: void SCR2_Read3(void)
853: {
854: // Log_Printf(LOG_WARN,"SCR2 read at $%08x PC=$%08x\n", IoAccessCurrentAddress,m68k_getpc());
855: IoMem[IoAccessCurrentAddress & 0x1FFFF]=scr2_3;
856: }
857:
858:
859:
860: /* Interrupt Status Register */
861:
862: void IntRegStatRead(void) {
863: IoMem_WriteLong(IoAccessCurrentAddress & IO_SEG_MASK, intStat);
864: }
865:
866: void IntRegStatWrite(void) {
867: intStat = IoMem_ReadLong(IoAccessCurrentAddress & IO_SEG_MASK);
868: }
869:
870: void set_interrupt(Uint32 interrupt_val, Uint8 int_set_release) {
871:
872: Uint8 interrupt_level;
873:
874: if(int_set_release == SET_INT) {
875: intStat = intStat | interrupt_val;
876: } else {
877: intStat = intStat & ~interrupt_val;
878: }
879:
880: switch (interrupt_val) {
881: case INT_SOFT1: interrupt_level = 1;
882: break;
883: case INT_SOFT2: interrupt_level = 2;
884: break;
885: case INT_POWER:
886: case INT_KEYMOUSE:
887: case INT_MONITOR:
888: case INT_VIDEO:
889: case INT_DSP_L3:
890: case INT_PHONE:
891: case INT_SOUND_OVRUN:
892: case INT_EN_RX:
893: case INT_EN_TX:
894: case INT_PRINTER:
895: case INT_SCSI:
896: case INT_DISK: interrupt_level = 3;
897: break;
898: case INT_DSP_L4: interrupt_level = 4;
899: break;
900: case INT_BUS:
901: case INT_REMOTE:
902: case INT_SCC: interrupt_level = 5;
903: break;
904: case INT_R2M_DMA:
905: case INT_M2R_DMA:
906: case INT_DSP_DMA:
907: case INT_SCC_DMA:
908: case INT_SND_IN_DMA:
909: case INT_SND_OUT_DMA:
910: case INT_PRINTER_DMA:
911: case INT_DISK_DMA:
912: case INT_SCSI_DMA:
913: case INT_EN_RX_DMA:
914: case INT_EN_TX_DMA:
915: interrupt_level = 6;
916: break;
917: case INT_TIMER:
918: if (scr2_2&SCR2_TIMERIPL7)
919: interrupt_level = 7;
920: else
921: interrupt_level = 6;
922: break;
923: case INT_PFAIL:
924: case INT_NMI: interrupt_level = 7;
925: break;
926: default: interrupt_level = 0;
927: break;
928: }
929:
930: if ((interrupt_val & intMask)==0) {
931: Log_Printf(LOG_WARN,"[INT] interrupt is masked %04x mask %04x %s at %d",interrupt_val,intMask,__FILE__,__LINE__);
932: return;
933: }
934:
935: if(int_set_release == SET_INT) {
936: Log_Printf(LOG_DEBUG,"Interrupt Level: %i", interrupt_level);
937: M68000_Exception(((24+interrupt_level)*4), M68000_EXC_SRC_AUTOVEC);
938: } else {
939: // M68000_Exception(((24+0)*4), M68000_EXC_SRC_AUTOVEC); // release interrupt - does this work???
940: }
941: }
942:
943: /* Interrupt Mask Register */
944:
945: void IntRegMaskRead(void) {
946: IoMem_WriteLong(IoAccessCurrentAddress & IO_SEG_MASK,intMask);
947: }
948:
949: void IntRegMaskWrite(void) {
950: intMask = IoMem_ReadLong(IoAccessCurrentAddress & IO_SEG_MASK);
951: Log_Printf(LOG_WARN,"Interrupt mask: %08x", intMask);
952: }
953:
954: /*
955: * Hardclock internal interrupt
956: *
957: */
958:
959: #define HARDCLOCK_ENABLE 0x80
960: #define HARDCLOCK_LATCH 0x40
961:
962: Uint8 hardclock_csr=0;
963: Uint8 hardclock1=0;
964: Uint8 hardclock0=0;
965: int pseudo_counter=0;
966: int latch_hardclock=0;
967:
968: void Hardclock_InterruptHandler ( void )
969: {
970: CycInt_AcknowledgeInterrupt();
971: if ((hardclock_csr&HARDCLOCK_ENABLE) && (latch_hardclock>0)) {
972: // Log_Printf(LOG_WARN,"[INT] throwing hardclock");
973: set_interrupt(INT_TIMER,SET_INT);
974: CycInt_AddRelativeInterrupt(latch_hardclock*33, INT_CPU_CYCLE, INTERRUPT_HARDCLOCK);
975: pseudo_counter=latch_hardclock;
976: }
977: }
978:
979:
980: void HardclockRead0(void){
981: IoMem[IoAccessCurrentAddress & 0x1FFFF]=(pseudo_counter>>8);
982: ;
1.1.1.2 ! root 983: if (pseudo_counter>0) pseudo_counter--;
1.1 root 984:
985: Log_Printf(LOG_WARN,"[hardclock] read at $%08x val=%02x PC=$%08x", IoAccessCurrentAddress,IoMem[IoAccessCurrentAddress & 0x1FFFF],m68k_getpc());
986: }
987: void HardclockRead1(void){
988: IoMem[IoAccessCurrentAddress & 0x1FFFF]=pseudo_counter&0xff;
989: if (pseudo_counter>0) pseudo_counter--;
990: Log_Printf(LOG_WARN,"[hardclock] read at $%08x val=%02x PC=$%08x", IoAccessCurrentAddress,IoMem[IoAccessCurrentAddress & 0x1FFFF],m68k_getpc());
991: }
992:
993: void HardclockWrite0(void){
994: Log_Printf(LOG_WARN,"[hardclock] write at $%08x val=%02x PC=$%08x", IoAccessCurrentAddress,IoMem[IoAccessCurrentAddress & 0x1FFFF],m68k_getpc());
995: hardclock0=IoMem[IoAccessCurrentAddress & 0x1FFFF];
996: }
997: void HardclockWrite1(void){
998: Log_Printf(LOG_WARN,"[hardclock] write at $%08x val=%02x PC=$%08x",IoAccessCurrentAddress,IoMem[IoAccessCurrentAddress & 0x1FFFF],m68k_getpc());
999: hardclock1=IoMem[IoAccessCurrentAddress & 0x1FFFF];
1000: }
1001:
1002: void HardclockWriteCSR(void) {
1003: Log_Printf(LOG_WARN,"[hardclock] write at $%08x val=%02x PC=$%08x", IoAccessCurrentAddress,IoMem[IoAccessCurrentAddress & 0x1FFFF],m68k_getpc());
1004: hardclock_csr=IoMem[IoAccessCurrentAddress & 0x1FFFF];
1005: if ((hardclock_csr&HARDCLOCK_LATCH)) {
1006: latch_hardclock=(hardclock0<<8)|hardclock1;
1007: pseudo_counter=latch_hardclock;
1008: }
1009: if ((hardclock_csr&HARDCLOCK_ENABLE) && (latch_hardclock>0)) {
1.1.1.2 ! root 1010: CycInt_AddRelativeInterrupt(latch_hardclock*33, INT_CPU_CYCLE, INTERRUPT_HARDCLOCK);
! 1011: // set_interrupt(INT_TIMER, SET_INT);
1.1 root 1012: }
1013: }
1014: void HardclockReadCSR(void) {
1015: IoMem[IoAccessCurrentAddress & 0x1FFFF]=hardclock_csr;
1016: // Log_Printf(LOG_WARN,"[hardclock] read at $%08x val=%02x PC=$%08x", IoAccessCurrentAddress,IoMem[IoAccessCurrentAddress & 0x1FFFF],m68k_getpc());
1017: set_interrupt(INT_TIMER,RELEASE_INT);
1018: }
1019:
1020:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.