/******************************************************************************
 * isr8.c - Chapter 7 DBUF sample code                                        *
 *                                                                            *
 * mach64 functions to handle interrupt chaining.                             *
 *                                                                            *
 * Copyright (c) 1994-1997 ATI Technologies Inc.  All rights reserved.        *
 ******************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <i86.h>
#include "..\util\atim64.h"
#include "..\util\defines.h"
#include "..\util\main.h"

extern void int_off ();
#pragma aux int_off = "cli";

extern void int_on ();
#pragma aux int_on = "sti";

unsigned long CrtcPitchOffset1;
unsigned long CrtcPitchOffset2;
short SwapFlag = 1;
void (__interrupt __far *prev_int)(void);


/******************************************************************************
 * __interrupt Int8ISR                                                        *
 *  Function: Interrupt routine that is chained with interrupt 0x08           *
 *            Actually, interrupt 1C is used instead, but serves the same     *
 *            purpose, since 1C is hooked to 08.  This function flips the     *
 *            swap flag, and changes the page that is updated.                *
 *    Inputs: NONE                                                            *
 *   Outputs: NONE                                                            *
 ******************************************************************************/

void __interrupt Int8ISR (void)
{
    int_off ();
    if (SwapFlag == 0)
    {
        iow32 (CRTC_OFF_PITCH, CrtcPitchOffset1);
        SwapFlag = 1;
    }
    else
    {
        iow32 (CRTC_OFF_PITCH, CrtcPitchOffset2);
        SwapFlag = 0;
    } // if
    _chain_intr (prev_int);
    int_on ();

    return;

} // Int8ISR


/******************************************************************************
 * init_timer_isr                                                             *
 *  Function: Initiates the interrupt routine by saving the old interrupt     *
 *            vector of int 0x1C, and chaining in the new interrupt           *
 *            routine, Int8ISR.                                               *
 *    Inputs: NONE                                                            *
 *   Outputs: NONE                                                            *
 ******************************************************************************/

void init_timer_isr (void)
{
    prev_int = _dos_getvect (0x1C);
    _dos_setvect (0x1C, Int8ISR);

    return;

} // init_timer_isr


/******************************************************************************
 * cancel_timer_isr                                                           *
 *  Function: Restores the old interrupt vector to the vector table.          *
 *    Inputs: NONE                                                            *
 *   Outputs: NONE                                                            *
 ******************************************************************************/

void cancel_timer_isr (void)
{
    _dos_setvect (0x1C, prev_int);

    return;

} // cancel_timer_isr


/******************************************************************************
 * get_swap_flag                                                              *
 *  Function: returns the value of the SwapFlag used to determine which       *
 *            page is to be updated.                                          *
 *    Inputs: NONE                                                            *
 *   Outputs: SwapFlag - either 0 or 1.                                       *
 ******************************************************************************/

short get_swap_flag (void)
{
    return (SwapFlag);
} // get_swap_flag


/******************************************************************************
 * interrupts_off                                                             *
 *  Function: assembly code <cli>, turns off interrupts                       *
 *    Inputs: NONE                                                            *
 *   Outputs: NONE                                                            *
 ******************************************************************************/

void interrupts_off (void)
{
    int_off ();

    return;

} // interrupts_off


/******************************************************************************
 * interrupts_on                                                              *
 *  Function: assembly code <sti>, turns on interrupts                        *
 *    Inputs: NONE                                                            *
 *   Outputs: NONE                                                            *
 ******************************************************************************/

void interrupts_on (void)
{
    int_on ();
    
    return;

} // interrupts_on


/******************************************************************************
 * set_crtc_offset                                                            *
 *  Function: Sets the offset for the on screen and off screen pages that     *
 *            are flipped and updated in accordance to the DOS clock.         *
 *            This swapping and updating generates an animated sequence.      *
 *    Inputs: offset - off screen offset.                                     *
 *   Outputs: NONE                                                            *
 ******************************************************************************/

void set_crtc_offset (unsigned long offset)
{
    CrtcPitchOffset1 = offset;
    CrtcPitchOffset2 = (ior32 (CRTC_OFF_PITCH) & 0xFFC00000);

    return;

} // set_crtc_offset
