|
|
1.1 root 1: /*
1.1.1.3 root 2: Hatari - int.c
3:
4: This file is distributed under the GNU Public License, version 2 or at
5: your option any later version. Read the file gpl.txt for details.
1.1 root 6:
7: This code handles our interrupt table. So we do not need to test for every possible
8: interrupt we add any pending interrupts into a table. We then scan the list if used
9: entries in the table and copy the one with the least cycle count into the global
10: 'PendingInterruptCount' variable. This is then decremented by the execution loop -
11: rather than decrement each and every entry (as the others cannot occur before this one)
12: We have two methods of adding interrupts; Absolute and Relative. Absolute will set values
13: from the time of the previous interrupt(eg, add HBL every 512 cycles), and Relative
14: will add from the current cycle time.
15: Note that interrupt may occur 'late'. Ie, if an interrupt is due in 4 cycles time but
16: the current instruction takes 20 cycles we will be 16 cycles late - this is handled in
17: the adjust functions.
18: */
1.1.1.7 ! root 19: const char Int_rcsid[] = "Hatari $Id: int.c,v 1.14 2006/06/26 23:03:09 thothy Exp $";
1.1 root 20:
21: #include "main.h"
1.1.1.6 root 22: #include "dmaSnd.h"
1.1 root 23: #include "ikbd.h"
24: #include "int.h"
25: #include "m68000.h"
26: #include "memorySnapShot.h"
27: #include "mfp.h"
28: #include "sound.h"
29: #include "video.h"
30:
1.1.1.3 root 31:
1.1.1.7 ! root 32: int nCyclesOver = 0;
! 33:
! 34:
1.1 root 35: /* List of possible interrupt handlers to be store in 'PendingInterruptTable', used for 'MemorySnapShot' */
1.1.1.7 ! root 36: static void (* const pIntHandlerFunctions[])(void) =
1.1.1.3 root 37: {
1.1 root 38: NULL,
39: Video_InterruptHandler_VBL,
40: Video_InterruptHandler_HBL,
41: Video_InterruptHandler_EndLine,
42: MFP_InterruptHandler_TimerA,
43: MFP_InterruptHandler_TimerB,
44: MFP_InterruptHandler_TimerC,
45: MFP_InterruptHandler_TimerD,
46: IKBD_InterruptHandler_ResetTimer,
47: IKBD_InterruptHandler_ACIA,
1.1.1.6 root 48: DmaSnd_InterruptHandler,
1.1 root 49: NULL
50: };
51:
1.1.1.7 ! root 52: /* Event timer structure - keeps next timer to occur in structure so don't need to check all entries */
! 53: typedef struct
! 54: {
! 55: BOOL bUsed; /* Is interrupt active? */
! 56: int Cycles;
! 57: void (*pFunction)(void);
! 58: } INTERRUPTHANDLER;
! 59:
! 60: static INTERRUPTHANDLER InterruptHandlers[MAX_INTERRUPTS];
! 61: static int ActiveInterrupt=0;
1.1 root 62:
1.1.1.2 root 63:
64: /*-----------------------------------------------------------------------*/
1.1 root 65: /*
66: Reset interrupts, handlers
67: */
68: void Int_Reset(void)
69: {
70: int i;
71:
1.1.1.2 root 72: /* Reset counts */
1.1 root 73: PendingInterruptCount = 0;
74: nCyclesOver = 0;
75:
1.1.1.2 root 76: /* Reset interrupt table */
1.1 root 77: for(i=0; i<MAX_INTERRUPTS; i++) {
78: InterruptHandlers[i].bUsed = FALSE;
79: InterruptHandlers[i].pFunction = pIntHandlerFunctions[i];
80: }
81: }
82:
1.1.1.2 root 83:
84: /*-----------------------------------------------------------------------*/
1.1 root 85: /*
86: Save/Restore snapshot of local variables('MemorySnapShot_Store' handles type)
87: */
88: void Int_MemorySnapShot_Capture(BOOL bSave)
89: {
90: int i,ID;
91:
1.1.1.2 root 92: /* Save/Restore details */
1.1 root 93: for(i=0; i<MAX_INTERRUPTS; i++) {
94: MemorySnapShot_Store(&InterruptHandlers[i].bUsed,sizeof(InterruptHandlers[i].bUsed));
95: MemorySnapShot_Store(&InterruptHandlers[i].Cycles,sizeof(InterruptHandlers[i].Cycles));
96: if (bSave) {
1.1.1.2 root 97: /* Convert function to ID */
1.1 root 98: ID = Int_HandlerFunctionToID(InterruptHandlers[i].pFunction);
99: MemorySnapShot_Store(&ID,sizeof(int));
100: }
101: else {
1.1.1.2 root 102: /* Convert ID to function */
1.1 root 103: MemorySnapShot_Store(&ID,sizeof(int));
104: InterruptHandlers[i].pFunction = Int_IDToHandlerFunction(ID);
105: }
106: }
107: MemorySnapShot_Store(&nCyclesOver,sizeof(nCyclesOver));
108: }
109:
1.1.1.2 root 110:
111: /*-----------------------------------------------------------------------*/
1.1 root 112: /*
113: Convert interrupt handler function pointer to ID, used for saving
114: */
1.1.1.7 ! root 115: int Int_HandlerFunctionToID(void (*pHandlerFunction)(void))
1.1 root 116: {
117: int i;
118:
1.1.1.2 root 119: /* Is NULL, return ID 0 */
1.1 root 120: if (pHandlerFunction==NULL)
121: return(0);
122:
1.1.1.2 root 123: /* Scan for function match */
1.1 root 124: for(i=1; i<MAX_INTERRUPTS; i++) {
125: if (pIntHandlerFunctions[i]==pHandlerFunction)
126: return(i);
127: }
128:
1.1.1.2 root 129: /* Didn't find one! Oops */
1.1.1.7 ! root 130: return 0;
1.1 root 131: }
132:
1.1.1.2 root 133:
134: /*-----------------------------------------------------------------------*/
1.1 root 135: /*
136: Convert ID back into interrupt handler function, used for restoring
137: */
138: void *Int_IDToHandlerFunction(int ID)
139: {
1.1.1.2 root 140: /* Get function pointer */
1.1 root 141: return( pIntHandlerFunctions[ID] );
142: }
143:
1.1.1.2 root 144:
145: /*-----------------------------------------------------------------------*/
1.1 root 146: /*
147: Find next interrupt to occur, and store to global variables for decrement in instruction decode loop
148: */
1.1.1.7 ! root 149: static void Int_SetNewInterrupt(void)
1.1 root 150: {
151: int LowestCycleCount=999999,LowestInterrupt=0;
152: int i;
153:
1.1.1.2 root 154: /* Find next interrupt to go off */
1.1 root 155: for(i=0; i<MAX_INTERRUPTS; i++) {
1.1.1.2 root 156: /* Is interrupt pending? */
1.1 root 157: if (InterruptHandlers[i].bUsed) {
158: if (InterruptHandlers[i].Cycles<LowestCycleCount) {
159: LowestCycleCount = InterruptHandlers[i].Cycles;
160: LowestInterrupt = i;
161: }
162: }
163: }
1.1.1.2 root 164:
165: /* Set new counts, active interrupt */
1.1 root 166: PendingInterruptCount = (short int)InterruptHandlers[LowestInterrupt].Cycles;
167: PendingInterruptFunction = InterruptHandlers[LowestInterrupt].pFunction;
168: ActiveInterrupt = LowestInterrupt;
169:
170: }
171:
1.1.1.2 root 172:
173: /*-----------------------------------------------------------------------*/
1.1 root 174: /*
175: Adjust all interrupt timings, MUST call Int_SetNewInterrupt after this
176: */
1.1.1.3 root 177: static void Int_UpdateInterrupt(void)
1.1 root 178: {
179: int CycleSubtract;
180: int i;
181:
1.1.1.2 root 182: /* Find out how many cycles we went over (<=0) */
1.1 root 183: nCyclesOver = PendingInterruptCount;
1.1.1.2 root 184: /* Calculate how many cycles have passed, included time we went over */
1.1 root 185: CycleSubtract = InterruptHandlers[ActiveInterrupt].Cycles-nCyclesOver;
186:
1.1.1.2 root 187: /* Adjust table */
1.1 root 188: for(i=0; i<MAX_INTERRUPTS; i++) {
189: if (InterruptHandlers[i].bUsed)
190: InterruptHandlers[i].Cycles -= CycleSubtract;
191: }
192: }
193:
1.1.1.2 root 194:
195: /*-----------------------------------------------------------------------*/
1.1 root 196: /*
197: Adjust all interrupt timings as 'ActiveInterrupt' has occured, and remove from active list
198: */
199: void Int_AcknowledgeInterrupt(void)
200: {
1.1.1.2 root 201: /* Update list cycle counts */
1.1 root 202: Int_UpdateInterrupt();
203:
1.1.1.2 root 204: /* Disable interrupt entry which has just occured */
1.1 root 205: InterruptHandlers[ActiveInterrupt].bUsed = FALSE;
206:
1.1.1.2 root 207: /* Set new */
1.1 root 208: Int_SetNewInterrupt();
209: }
210:
1.1.1.2 root 211:
212: /*-----------------------------------------------------------------------*/
1.1 root 213: /*
214: Add interrupt from time last one occurred
215: */
216: void Int_AddAbsoluteInterrupt(int CycleTime, int Handler)
217: {
218: InterruptHandlers[Handler].bUsed = TRUE;
219: InterruptHandlers[Handler].Cycles = CycleTime + nCyclesOver;
220:
1.1.1.2 root 221: /* Set new */
1.1 root 222: Int_SetNewInterrupt();
223: }
224:
1.1.1.2 root 225:
226: /*-----------------------------------------------------------------------*/
1.1 root 227: /*
228: Add interrupt to occur from now
229: */
230: void Int_AddRelativeInterrupt(int CycleTime, int Handler)
231: {
232: InterruptHandlers[Handler].bUsed = TRUE;
233: InterruptHandlers[Handler].Cycles = CycleTime;
234:
1.1.1.2 root 235: /* Set new */
1.1 root 236: Int_SetNewInterrupt();
237: }
238:
1.1.1.2 root 239:
240: /*-----------------------------------------------------------------------*/
1.1 root 241: /*
242: Remove a pending interrupt from our table
243: */
244: void Int_RemovePendingInterrupt(int Handler)
245: {
1.1.1.2 root 246: /* Stop interrupt */
1.1 root 247: InterruptHandlers[Handler].bUsed = FALSE;
248:
1.1.1.2 root 249: /* Update list cycle counts */
1.1 root 250: Int_UpdateInterrupt();
1.1.1.2 root 251: /* Set new */
1.1 root 252: Int_SetNewInterrupt();
253: }
254:
1.1.1.2 root 255:
256: /*-----------------------------------------------------------------------*/
1.1 root 257: /*
258: Return TRUE if interrupt is active in list
259: */
260: BOOL Int_InterruptActive(int Handler)
261: {
1.1.1.2 root 262: /* Is timer active? */
1.1 root 263: if (InterruptHandlers[Handler].bUsed)
264: return(TRUE);
265:
266: return(FALSE);
267: }
268:
1.1.1.2 root 269:
270: /*-----------------------------------------------------------------------*/
1.1 root 271: /*
272: Return cycles passed for an interrupt handler
273: */
274: int Int_FindCyclesPassed(int Handler)
275: {
276: int CyclesPassed, CyclesFromLastInterrupt;
277:
278: CyclesFromLastInterrupt = (int)InterruptHandlers[ActiveInterrupt].Cycles-PendingInterruptCount;
279: CyclesPassed = ((int)InterruptHandlers[Handler].Cycles-CyclesFromLastInterrupt);
280:
281: return(CyclesPassed);
282: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.