Annotation of hatari/src/int.c, revision 1.1.1.7

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.