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