|
|
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"
1.1.1.3 ! root 11: #include "dsp.h"
1.1 root 12: #include "sysReg.h"
1.1.1.3 ! root 13: #include "rtcnvram.h"
1.1 root 14: #include "statusbar.h"
15:
16:
1.1.1.3 ! root 17: #define LOG_HARDCLOCK_LEVEL LOG_DEBUG
! 18: #define LOG_SOFTINT_LEVEL LOG_DEBUG
! 19:
1.1 root 20: #define IO_SEG_MASK 0x1FFFF
21:
1.1.1.3 ! root 22: int SCR_ROM_overlay=0;
! 23:
1.1 root 24: static Uint32 scr1=0x00000000;
25:
26: static Uint8 scr2_0=0x00;
27: static Uint8 scr2_1=0x00;
1.1.1.3 ! root 28: static Uint8 scr2_2=0x00;
1.1 root 29: static Uint8 scr2_3=0x00;
30:
31: static Uint32 intStat=0x00000000;
32: static Uint32 intMask=0x00000000;
33:
34:
35:
36: void SID_Read(void) {
37: Log_Printf(LOG_WARN,"SID read at $%08x PC=$%08x\n", IoAccessCurrentAddress,m68k_getpc());
38: IoMem[IoAccessCurrentAddress & 0x1FFFF]=0x00; // slot ID 0
39: }
40:
41: /* System Control Register 1
42: *
43: * These values are valid for all non-Turbo systems:
44: * -------- -------- -------- ------xx bits 0:1 --> cpu speed
45: * -------- -------- -------- ----xx-- bits 2:3 --> reserved
46: * -------- -------- -------- --xx---- bits 4:5 --> main memory speed
47: * -------- -------- -------- xx------ bits 6:7 --> video memory speed
48: * -------- -------- ----xxxx -------- bits 8:11 --> board revision
49: * -------- -------- xxxx---- -------- bits 12:15 --> cpu type
50: * -------- xxxxxxxx -------- -------- bits 16:23 --> dma revision
51: * ----xxxx -------- -------- -------- bits 24:27 --> reserved
52: * xxxx---- -------- -------- -------- bits 28:31 --> slot id
53: *
54: * cpu speed: 0 = 40MHz, 1 = 20MHz, 2 = 25MHz, 3 = 33MHz
55: * main mem speed: 0 = 120ns, 1 = 100ns, 2 = 80ns, 3 = 60ns
56: * video mem speed: 0 = 120ns, 1 = 100ns, 2 = 80ns, 3 = 60ns
57: * board revision: for 030 Cube:
58: * 0 = DCD input inverted
59: * 1 = DCD polarity fixed
60: * 2 = must disable DSP mem before reset
61: * cpu type: 0 = NeXT Computer (68030)
62: * 1 = NeXTstation monochrome
63: * 2 = NeXTcube
64: * 3 = NeXTstation color
65: * 4 = all Turbo systems
66: * dma revision: 1 on all systems ?
67: * slot id: f on Turbo systems (cube too?), 0 on other systems
68: *
69: *
70: * These bits are always 0 on all Turbo systems:
71: * ----xxxx xxxxxxxx ----xxxx xxxxxxxx
72: */
73:
74: /* for Slab 040:
75: * 0000 0000 0000 0001 0001 0000 0101 0010
76: * 00 01 10 52
77: *
78: * for Cube 030:
79: * 0000 0000 0000 0001 0000 0001 0101 0010
80: * 00 01 01 52
81: */
82: #define SCR1_NEXT_COMPUTER 0x00010152
83: #define SCR1_SLAB_MONO 0x00011052
84: #define SCR1_SLAB_COLOR 0x00013052
85: #define SCR1_CUBE 0x00012052
1.1.1.3 ! root 86: #define SCR1_TURBO 0x00004000
1.1 root 87:
88: #define SCR1_CONST_MASK 0xFFFFFF00
89:
90: void SCR_Reset(void) {
1.1.1.3 ! root 91: SCR_ROM_overlay = 0;
! 92:
1.1 root 93: scr2_0=0x00;
94: scr2_1=0x00;
1.1.1.3 ! root 95: if (ConfigureParams.System.bTurbo) {
! 96: scr2_2=0x10;
! 97: scr2_3=0x80;
! 98: } else {
! 99: scr2_2=0x00;
! 100: scr2_3=0x00;
! 101: }
! 102:
1.1 root 103: intStat=0x00000000;
104: intMask=0x00000000;
105:
106: if (ConfigureParams.System.bTurbo) {
107: scr1 = SCR1_TURBO;
1.1.1.3 ! root 108: scr1 |= (ConfigureParams.System.nMachineType==NEXT_CUBE040)?0:0xF0000000;
1.1 root 109: return;
110: } else {
111: switch (ConfigureParams.System.nMachineType) {
112: case NEXT_CUBE030:
113: scr1 = SCR1_NEXT_COMPUTER & SCR1_CONST_MASK;
114: break;
115: case NEXT_CUBE040:
116: scr1 = SCR1_CUBE & SCR1_CONST_MASK;
117: break;
118: case NEXT_STATION:
119: if (ConfigureParams.System.bColor)
120: scr1 = SCR1_SLAB_COLOR & SCR1_CONST_MASK;
121: else
122: scr1 = SCR1_SLAB_MONO & SCR1_CONST_MASK;
123: break;
124: default:
125: break;
126: }
127: }
128:
1.1.1.3 ! root 129: Uint8 cpu_speed;
1.1 root 130: Uint8 memory_speed;
1.1.1.3 ! root 131:
! 132: if (ConfigureParams.System.nCpuFreq<20) {
! 133: cpu_speed = 0;
! 134: } else if (ConfigureParams.System.nCpuFreq<25) {
! 135: cpu_speed = 1;
! 136: } else if (ConfigureParams.System.nCpuFreq<33) {
! 137: cpu_speed = 2;
! 138: } else {
! 139: cpu_speed = 3;
! 140: }
! 141:
1.1 root 142: switch (ConfigureParams.Memory.nMemorySpeed) {
143: case MEMORY_120NS: memory_speed = 0x00; break;
144: case MEMORY_100NS: memory_speed = 0x50; break;
145: case MEMORY_80NS: memory_speed = 0xA0; break;
146: case MEMORY_60NS: memory_speed = 0xF0; break;
147: default: Log_Printf(LOG_WARN, "SCR1 error: unknown memory speed\n"); break;
148: }
149: scr1 |= ((memory_speed&0xF0)|(cpu_speed&0x03));
150: }
151:
152: void SCR1_Read0(void)
153: {
154: Log_Printf(LOG_WARN,"SCR1 read at $%08x PC=$%08x\n", IoAccessCurrentAddress,m68k_getpc());
155: IoMem[IoAccessCurrentAddress&IO_SEG_MASK] = (scr1&0xFF000000)>>24;
156: }
157: void SCR1_Read1(void)
158: {
159: Log_Printf(LOG_WARN,"SCR1 read at $%08x PC=$%08x\n", IoAccessCurrentAddress,m68k_getpc());
160: IoMem[IoAccessCurrentAddress&IO_SEG_MASK] = (scr1&0x00FF0000)>>16;
161: }
162: void SCR1_Read2(void)
163: {
164: Log_Printf(LOG_WARN,"SCR1 read at $%08x PC=$%08x\n", IoAccessCurrentAddress,m68k_getpc());
165: IoMem[IoAccessCurrentAddress&IO_SEG_MASK] = (scr1&0x0000FF00)>>8;
166: }
167: void SCR1_Read3(void)
168: {
169: Log_Printf(LOG_WARN,"SCR1 read at $%08x PC=$%08x\n", IoAccessCurrentAddress,m68k_getpc());
170: IoMem[IoAccessCurrentAddress&IO_SEG_MASK] = scr1&0x000000FF;
171: }
172:
173:
174: /* System Control Register 2
175:
176: s_dsp_reset : 1,
177: s_dsp_block_end : 1,
178: s_dsp_unpacked : 1,
179: s_dsp_mode_B : 1,
180: s_dsp_mode_A : 1,
181: s_remote_int : 1,
182: s_local_int : 2,
183: s_dram_256K : 4,
184: s_dram_1M : 4,
185: s_timer_on_ipl7 : 1,
186: s_rom_wait_states : 3,
187: s_rom_1M : 1,
188: s_rtdata : 1,
189: s_rtclk : 1,
190: s_rtce : 1,
191: s_rom_overlay : 1,
192: s_dsp_int_en : 1,
193: s_dsp_mem_en : 1,
194: s_reserved : 4,
195: s_led : 1;
196:
197: */
198:
1.1.1.3 ! root 199: /* byte 0 */
! 200: #define SCR2_DSP_RESET 0x80
! 201: #define SCR2_DSP_BLK_END 0x40
! 202: #define SCR2_DSP_UNPKD 0x20
! 203: #define SCR2_DSP_MODE_B 0x10
! 204: #define SCR2_DSP_MODE_A 0x08
1.1 root 205: #define SCR2_SOFTINT2 0x02
206: #define SCR2_SOFTINT1 0x01
207:
1.1.1.3 ! root 208: /* byte 2 */
1.1 root 209: #define SCR2_TIMERIPL7 0x80
210: #define SCR2_RTDATA 0x04
211: #define SCR2_RTCLK 0x02
212: #define SCR2_RTCE 0x01
213:
1.1.1.3 ! root 214: /* byte 3 */
1.1 root 215: #define SCR2_ROM 0x80
1.1.1.3 ! root 216: #define SCR2_DSP_INT_EN 0x40
! 217: #define SCR2_DSP_MEM_EN 0x20
! 218: #define SCR2_LED 0x01
1.1 root 219:
220:
221: void SCR2_Write0(void)
222: {
223: Uint8 old_scr2_0=scr2_0;
224: // Log_Printf(LOG_WARN,"SCR2 write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress,IoMem[IoAccessCurrentAddress & IO_SEG_MASK],m68k_getpc());
225: scr2_0=IoMem[IoAccessCurrentAddress & 0x1FFFF];
226:
227: if ((old_scr2_0&SCR2_SOFTINT1)!=(scr2_0&SCR2_SOFTINT1)) {
1.1.1.3 ! root 228: Log_Printf(LOG_SOFTINT_LEVEL,"SCR2 SCR2_SOFTINT1 change at $%08x val=%x PC=$%08x\n",
1.1 root 229: IoAccessCurrentAddress,scr2_0&SCR2_SOFTINT1,m68k_getpc());
230: if (scr2_0&SCR2_SOFTINT1)
231: set_interrupt(INT_SOFT1,SET_INT);
232: else
233: set_interrupt(INT_SOFT1,RELEASE_INT);
234: }
235:
236: if ((old_scr2_0&SCR2_SOFTINT2)!=(scr2_0&SCR2_SOFTINT2)) {
1.1.1.3 ! root 237: Log_Printf(LOG_SOFTINT_LEVEL,"SCR2 SCR2_SOFTINT2 change at $%08x val=%x PC=$%08x\n",
1.1 root 238: IoAccessCurrentAddress,scr2_0&SCR2_SOFTINT2,m68k_getpc());
239: if (scr2_0&SCR2_SOFTINT2)
240: set_interrupt(INT_SOFT2,SET_INT);
241: else
242: set_interrupt(INT_SOFT2,RELEASE_INT);
243: }
1.1.1.3 ! root 244:
! 245: /* DSP bits */
! 246: if (scr2_0&SCR2_DSP_MODE_A) {
! 247: Log_Printf(LOG_WARN,"[SCR2] DSP Mode A");
! 248: }
! 249: if (scr2_0&SCR2_DSP_MODE_B) {
! 250: Log_Printf(LOG_WARN,"[SCR2] DSP Mode B");
! 251: }
! 252: if (!(scr2_0&SCR2_DSP_RESET) && (old_scr2_0&SCR2_DSP_RESET)) {
! 253: Log_Printf(LOG_WARN,"[SCR2] DSP Reset");
! 254: DSP_Reset();
! 255: } else if ((scr2_0&SCR2_DSP_RESET) && !(old_scr2_0&SCR2_DSP_RESET)) {
! 256: Log_Printf(LOG_WARN,"[SCR2] DSP Start (mode %i)",(~(scr2_0>>3))&3);
! 257: DSP_Start((~(scr2_0>>3))&3);
! 258: }
! 259: dsp_intr_at_block_end = scr2_0&SCR2_DSP_BLK_END;
! 260: if ((old_scr2_0&SCR2_DSP_BLK_END) != (scr2_0&SCR2_DSP_BLK_END)) {
! 261: Log_Printf(LOG_WARN,"[SCR2] %s DSP interrupt from DMA at block end",dsp_intr_at_block_end?"Enable":"Disable");
! 262: }
! 263: dsp_dma_unpacked = scr2_0&SCR2_DSP_UNPKD;
! 264: if ((old_scr2_0&SCR2_DSP_UNPKD) != (scr2_0&SCR2_DSP_UNPKD)) {
! 265: Log_Printf(LOG_WARN,"[SCR2] %s DSP DMA unpacked mode",dsp_dma_unpacked?"Enable":"Disable");
! 266: }
1.1 root 267: }
268:
269: void SCR2_Read0(void)
270: {
271: // Log_Printf(LOG_WARN,"SCR2 read at $%08x PC=$%08x\n", IoAccessCurrentAddress,m68k_getpc());
272: IoMem[IoAccessCurrentAddress & 0x1FFFF]=scr2_0;
273: }
274:
275: void SCR2_Write1(void)
276: {
277: // Log_Printf(LOG_WARN,"SCR2 write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress,IoMem[IoAccessCurrentAddress & IO_SEG_MASK],m68k_getpc());
278: scr2_1=IoMem[IoAccessCurrentAddress & 0x1FFFF];
279: }
280:
281: void SCR2_Read1(void)
282: {
283: // Log_Printf(LOG_WARN,"SCR2 read at $%08x PC=$%08x\n", IoAccessCurrentAddress,m68k_getpc());
284: IoMem[IoAccessCurrentAddress & 0x1FFFF]=scr2_1;
285: }
286:
287: void SCR2_Write2(void)
1.1.1.3 ! root 288: {
1.1 root 289: Uint8 old_scr2_2=scr2_2;
290:
291: scr2_2=IoMem[IoAccessCurrentAddress & 0x1FFFF];
292:
293: if ((old_scr2_2&SCR2_TIMERIPL7)!=(scr2_2&SCR2_TIMERIPL7)) {
294: Log_Printf(LOG_WARN,"SCR2 TIMER IPL7 change at $%08x val=%x PC=$%08x\n",
295: IoAccessCurrentAddress,scr2_2&SCR2_TIMERIPL7,m68k_getpc());
296: }
297:
1.1.1.3 ! root 298: /* RTC enabled */
1.1 root 299: if (scr2_2&SCR2_RTCE) {
300: if (((old_scr2_2&SCR2_RTCLK)!=(scr2_2&SCR2_RTCLK)) && ((scr2_2&SCR2_RTCLK)==0) ) {
1.1.1.3 ! root 301: Uint8 rtdata = scr2_2&SCR2_RTDATA;
! 302: scr2_2 &= ~SCR2_RTDATA;
! 303: scr2_2 |= rtc_interface_io(rtdata)?SCR2_RTDATA:0;
! 304: }
! 305: } else {
! 306: rtc_interface_reset();
! 307: }
1.1 root 308: }
309:
310: void SCR2_Read2(void)
311: {
312: // Log_Printf(LOG_WARN,"SCR2 read at $%08x PC=$%08x\n", IoAccessCurrentAddress,m68k_getpc());
313: // IoMem[IoAccessCurrentAddress & 0x1FFFF]=scr2_2 & (SCR2_RTDATA|SCR2_RTCLK|SCR2_RTCE)); // + data
314: IoMem[IoAccessCurrentAddress & 0x1FFFF]=scr2_2;
315: }
316:
317: void SCR2_Write3(void)
318: {
319: Uint8 old_scr2_3=scr2_3;
320: // Log_Printf(LOG_WARN,"SCR2 write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress,IoMem[IoAccessCurrentAddress & IO_SEG_MASK],m68k_getpc());
321: scr2_3=IoMem[IoAccessCurrentAddress & 0x1FFFF];
322: if ((old_scr2_3&SCR2_ROM)!=(scr2_3&SCR2_ROM)) {
323: Log_Printf(LOG_WARN,"SCR2 ROM change at $%08x val=%x PC=$%08x\n",
324: IoAccessCurrentAddress,scr2_3&SCR2_ROM,m68k_getpc());
325: SCR_ROM_overlay=scr2_3&SCR2_ROM;
326: }
327: if ((old_scr2_3&SCR2_LED)!=(scr2_3&SCR2_LED)) {
1.1.1.3 ! root 328: Log_Printf(LOG_DEBUG,"SCR2 LED change at $%08x val=%x PC=$%08x\n",
1.1 root 329: IoAccessCurrentAddress,scr2_3&SCR2_LED,m68k_getpc());
1.1.1.3 ! root 330: Statusbar_SetSystemLed(scr2_3&SCR2_LED);
! 331: }
! 332:
! 333: if ((old_scr2_3&SCR2_DSP_INT_EN) != (scr2_3&SCR2_DSP_INT_EN)) {
! 334: Log_Printf(LOG_WARN,"[SCR2] DSP interrupt at level %i",(scr2_3&SCR2_DSP_INT_EN)?4:3);
! 335: if (intStat&(INT_DSP_L3|INT_DSP_L4)) {
! 336: Log_Printf(LOG_WARN,"[SCR2] Switching DSP interrupt to level %i",(scr2_3&SCR2_DSP_INT_EN)?4:3);
! 337: set_interrupt(INT_DSP_L3|INT_DSP_L4, RELEASE_INT);
! 338: set_dsp_interrupt(SET_INT);
! 339: }
! 340: }
! 341: if ((old_scr2_3&SCR2_DSP_MEM_EN) != (scr2_3&SCR2_DSP_MEM_EN)) {
! 342: Log_Printf(LOG_WARN,"[SCR2] %s DSP memory",(scr2_3&SCR2_DSP_MEM_EN)?"Enable":"Disable");
1.1 root 343: }
344: }
345:
346:
347: void SCR2_Read3(void)
348: {
349: // Log_Printf(LOG_WARN,"SCR2 read at $%08x PC=$%08x\n", IoAccessCurrentAddress,m68k_getpc());
350: IoMem[IoAccessCurrentAddress & 0x1FFFF]=scr2_3;
351: }
352:
353:
354:
355: /* Interrupt Status Register */
356:
357: void IntRegStatRead(void) {
358: IoMem_WriteLong(IoAccessCurrentAddress & IO_SEG_MASK, intStat);
359: }
360:
361: void IntRegStatWrite(void) {
362: intStat = IoMem_ReadLong(IoAccessCurrentAddress & IO_SEG_MASK);
363: }
364:
1.1.1.3 ! root 365: void set_dsp_interrupt(Uint8 state) {
! 366: if (scr2_3&SCR2_DSP_INT_EN || ConfigureParams.System.bTurbo) {
! 367: set_interrupt(INT_DSP_L4, state);
1.1 root 368: } else {
1.1.1.3 ! root 369: set_interrupt(INT_DSP_L3, state);
1.1 root 370: }
1.1.1.3 ! root 371: }
! 372:
! 373: void set_interrupt(Uint32 intr, Uint8 state) {
! 374: /* The interrupt gets polled by the cpu via intlev()
! 375: * --> see previous-glue.c
! 376: */
! 377: if (state==SET_INT) {
! 378: intStat |= intr;
! 379: } else {
! 380: intStat &= ~intr;
1.1 root 381: }
1.1.1.3 ! root 382: }
! 383:
! 384: int get_interrupt_level(void) {
! 385: Uint32 interrupt = intStat&intMask;
! 386:
! 387: if (!interrupt) {
! 388: return 0;
! 389: } else if (interrupt&INT_L7_MASK) {
! 390: return 7;
! 391: } else if ((interrupt&INT_TIMER) && (scr2_2&SCR2_TIMERIPL7)) {
! 392: return 7;
! 393: } else if (interrupt&INT_L6_MASK) {
! 394: return 6;
! 395: } else if (interrupt&INT_L5_MASK) {
! 396: return 5;
! 397: } else if (interrupt&INT_L4_MASK) {
! 398: return 4;
! 399: } else if (interrupt&INT_L3_MASK) {
! 400: return 3;
! 401: } else if (interrupt&INT_L2_MASK) {
! 402: return 2;
! 403: } else if (interrupt&INT_L1_MASK) {
! 404: return 1;
1.1 root 405: } else {
1.1.1.3 ! root 406: abort();
1.1 root 407: }
408: }
409:
410: /* Interrupt Mask Register */
411:
412: void IntRegMaskRead(void) {
413: IoMem_WriteLong(IoAccessCurrentAddress & IO_SEG_MASK,intMask);
414: }
415:
416: void IntRegMaskWrite(void) {
417: intMask = IoMem_ReadLong(IoAccessCurrentAddress & IO_SEG_MASK);
418: Log_Printf(LOG_WARN,"Interrupt mask: %08x", intMask);
419: }
420:
1.1.1.3 ! root 421:
! 422: /* Hardclock internal interrupt */
1.1 root 423:
424: #define HARDCLOCK_ENABLE 0x80
425: #define HARDCLOCK_LATCH 0x40
1.1.1.3 ! root 426: #define HARDCLOCK_ZERO 0x3F
1.1 root 427:
428: Uint8 hardclock_csr=0;
429: Uint8 hardclock1=0;
430: Uint8 hardclock0=0;
1.1.1.3 ! root 431: int hardclock_delay=0;
1.1 root 432: int latch_hardclock=0;
433:
434: void Hardclock_InterruptHandler ( void )
435: {
436: CycInt_AcknowledgeInterrupt();
437: if ((hardclock_csr&HARDCLOCK_ENABLE) && (latch_hardclock>0)) {
438: // Log_Printf(LOG_WARN,"[INT] throwing hardclock");
1.1.1.3 ! root 439: set_interrupt(INT_TIMER,SET_INT);
! 440: CycInt_AddRelativeInterrupt(hardclock_delay, INT_CPU_CYCLE, INTERRUPT_HARDCLOCK);
1.1 root 441: }
442: }
443:
444:
445: void HardclockRead0(void){
1.1.1.3 ! root 446: IoMem[IoAccessCurrentAddress & 0x1FFFF]=(latch_hardclock>>8);
! 447: Log_Printf(LOG_HARDCLOCK_LEVEL,"[hardclock] read at $%08x val=%02x PC=$%08x", IoAccessCurrentAddress,IoMem[IoAccessCurrentAddress & 0x1FFFF],m68k_getpc());
1.1 root 448: }
449: void HardclockRead1(void){
1.1.1.3 ! root 450: IoMem[IoAccessCurrentAddress & 0x1FFFF]=latch_hardclock&0xff;
! 451: Log_Printf(LOG_HARDCLOCK_LEVEL,"[hardclock] read at $%08x val=%02x PC=$%08x", IoAccessCurrentAddress,IoMem[IoAccessCurrentAddress & 0x1FFFF],m68k_getpc());
1.1 root 452: }
453:
454: void HardclockWrite0(void){
1.1.1.3 ! root 455: Log_Printf(LOG_HARDCLOCK_LEVEL,"[hardclock] write at $%08x val=%02x PC=$%08x", IoAccessCurrentAddress,IoMem[IoAccessCurrentAddress & 0x1FFFF],m68k_getpc());
1.1 root 456: hardclock0=IoMem[IoAccessCurrentAddress & 0x1FFFF];
457: }
458: void HardclockWrite1(void){
1.1.1.3 ! root 459: Log_Printf(LOG_HARDCLOCK_LEVEL,"[hardclock] write at $%08x val=%02x PC=$%08x",IoAccessCurrentAddress,IoMem[IoAccessCurrentAddress & 0x1FFFF],m68k_getpc());
1.1 root 460: hardclock1=IoMem[IoAccessCurrentAddress & 0x1FFFF];
461: }
462:
463: void HardclockWriteCSR(void) {
1.1.1.3 ! root 464: Log_Printf(LOG_HARDCLOCK_LEVEL,"[hardclock] write at $%08x val=%02x PC=$%08x", IoAccessCurrentAddress,IoMem[IoAccessCurrentAddress & 0x1FFFF],m68k_getpc());
1.1 root 465: hardclock_csr=IoMem[IoAccessCurrentAddress & 0x1FFFF];
1.1.1.3 ! root 466: if (hardclock_csr&HARDCLOCK_LATCH) {
! 467: hardclock_csr&= ~HARDCLOCK_LATCH;
1.1 root 468: latch_hardclock=(hardclock0<<8)|hardclock1;
1.1.1.3 ! root 469: hardclock_delay=latch_hardclock*11;
1.1 root 470: }
471: if ((hardclock_csr&HARDCLOCK_ENABLE) && (latch_hardclock>0)) {
1.1.1.3 ! root 472: Log_Printf(LOG_HARDCLOCK_LEVEL,"[hardclock] enable periodic interrupt (%i microseconds).", latch_hardclock);
! 473: CycInt_AddRelativeInterrupt(hardclock_delay, INT_CPU_CYCLE, INTERRUPT_HARDCLOCK);
! 474: } else {
! 475: Log_Printf(LOG_HARDCLOCK_LEVEL,"[hardclock] disable periodic interrupt.");
! 476: }
! 477: set_interrupt(INT_TIMER,RELEASE_INT);
1.1 root 478: }
479: void HardclockReadCSR(void) {
480: IoMem[IoAccessCurrentAddress & 0x1FFFF]=hardclock_csr;
481: // Log_Printf(LOG_WARN,"[hardclock] read at $%08x val=%02x PC=$%08x", IoAccessCurrentAddress,IoMem[IoAccessCurrentAddress & 0x1FFFF],m68k_getpc());
482: set_interrupt(INT_TIMER,RELEASE_INT);
483: }
484:
485:
1.1.1.3 ! root 486: /* Event counter register */
! 487: #define EVENTC_DEBUG 0
! 488: Uint32 lasteventc; /* debugging code */
! 489:
! 490: Uint32 eventcounter;
! 491:
! 492: #if USE_FREQ_DIVIDER
! 493: void System_Timer_Read(void) { /* tuned for power-on test */
! 494: #if EVENTC_DEBUG
! 495: lasteventc = eventcounter; /* for debugging */
! 496: #endif
! 497: if (ConfigureParams.System.nCpuLevel == 3) {
! 498: if (NEXTRom[0xFFAB]==0x04) { // HACK for ROM version 0.8.31 power-on test, WARNING: this causes slowdown of emulation
! 499: eventcounter = (nCyclesMainCounter/(240/nCpuFreqDivider))&0xFFFFF;
! 500: } else {
! 501: eventcounter = (nCyclesMainCounter/(48/nCpuFreqDivider))&0xFFFFF;
! 502: }
! 503: } else { // System has 68040 CPU
! 504: eventcounter = (nCyclesMainCounter/(72/nCpuFreqDivider))&0xFFFFF;
! 505: }
! 506: IoMem_WriteLong(IoAccessCurrentAddress&IO_SEG_MASK, eventcounter);
! 507:
! 508: #if EVENTC_DEBUG
! 509: Log_Printf(LOG_WARN, "[Eventcounter] Difference = %i (Frequency = %i, Divider = %i)",
! 510: eventcounter-lasteventc,ConfigureParams.System.nCpuFreq,nCpuFreqDivider);
! 511: #endif
! 512: }
! 513: #else
! 514: void System_Timer_Read(void) { // tuned for power-on test
! 515: // lasteventc = eventcounter; // debugging code
! 516: if (ConfigureParams.System.nCpuLevel == 3) {
! 517: if (NEXTRom[0xFFAB]==0x04) { // HACK for ROM version 0.8.31 power-on test, WARNING: this causes slowdown of emulation
! 518: // eventcounter = (nCyclesMainCounter/((1280/ConfigureParams.System.nCpuFreq)*3))&0xFFFFF; // debugging code
! 519: IoMem_WriteLong(IoAccessCurrentAddress&0x1FFFF, (nCyclesMainCounter/((1280/ConfigureParams.System.nCpuFreq)*3))&0xFFFFF);
! 520: } else {
! 521: // eventcounter = (nCyclesMainCounter/((128/ConfigureParams.System.nCpuFreq)*3))&0xFFFFF; // debugging code
! 522: IoMem_WriteLong(IoAccessCurrentAddress&0x1FFFF, (nCyclesMainCounter/((128/ConfigureParams.System.nCpuFreq)*3))&0xFFFFF);
! 523: }
! 524: } else { // System has 68040 CPU
! 525: // eventcounter = (nCyclesMainCounter/((64/ConfigureParams.System.nCpuFreq)*9))&0xFFFFF; // debugging code
! 526: IoMem_WriteLong(IoAccessCurrentAddress&0x1FFFF, (nCyclesMainCounter/((64/ConfigureParams.System.nCpuFreq)*9))&0xFFFFF);
! 527: }
! 528: // printf("DIFFERENCE = %i PC = %08X\n",eventcounter-lasteventc,m68k_getpc());
! 529: }
! 530: #endif
! 531:
! 532:
! 533: /* Color Video Interrupt Register */
! 534:
! 535: #define VID_CMD_CLEAR_INT 0x01
! 536: #define VID_CMD_ENABLE_INT 0x02
! 537: #define VID_CMD_UNBLANK 0x04
! 538:
! 539: Uint8 col_vid_intr = 0;
! 540:
! 541: void ColorVideo_CMD_Write(void) {
! 542: col_vid_intr=IoMem[IoAccessCurrentAddress & 0x1FFFF];
! 543: Log_Printf(LOG_DEBUG,"[Color Video] Command write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
! 544:
! 545: if (col_vid_intr&VID_CMD_CLEAR_INT) {
! 546: set_interrupt(INT_DISK, RELEASE_INT);
! 547: }
! 548: }
! 549:
! 550: void color_video_interrupt(void) {
! 551: if (col_vid_intr&VID_CMD_ENABLE_INT) {
! 552: set_interrupt(INT_DISK, SET_INT);
! 553: col_vid_intr &= ~VID_CMD_ENABLE_INT;
! 554: }
! 555: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.