//
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// $Workfile:   fflnk.c  $
// $Revision:   1.1  $
//   $Author:   Doc  $
//  $Modtime:   11 Jun 1992 11:51:54  $
//      $Log:   D:/CR/ADK/VCS/FFLNK.C_V  $
// 
//    Rev 1.1   11 Jun 1992 13:32:58   Doc
// Modifications to change MPX id from 0x92 to 0xC2D2 (byte->word).
// 
//    Rev 1.0   09 Feb 1992 07:23:56   Doc
// Initial revision.
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//
//  -----------------------------------------------------------------------
//  FastFlip MPX Functions:
//  -----------------------------------------------------------------------
//
//  NOTE: FastFlip uses an mpx id of hex C2D2.
//
//  Function: Test to see if FastFlip is loaded.
//        IN: AX    = FASTFLIP_MPX_ID
//            DL    = 0
//       OUT: AX    = FFh = FastFlip IS loaded
//            AX    = any other value, FastFlip is NOT loaded
//
//  Function: Set page id.
//        IN: AX    = FASTFLIP_MPX_ID
//            DL    = 1
//            BX    = page id (0 based, i.e. 0 = page 1)
//       OUT: AX    = 0 = error
//            AX    = 1 = no error
//
//  Function: Get max # DEFINED pages.
//        IN: AX    = FASTFLIP_MPX_ID
//            DL    = 2
//       OUT: AX    = number of DEFINED pages (1 based)
//
//  Function: Set timer value.
//        IN: AX    = FASTFLIP_MPX_ID
//            DL    = 3
//            BX    = timer clicks between tasks
//       OUT: none
//
//  Function: Copy to common.
//        IN: AX    = FASTFLIP_MPX_ID
//            DL    = 4
//            BX    = offset to write to        (0 based)
//            CX    = # of bytes in data block  (1 based)
//            ES:DI = pointer to data block
//       OUT: none
//
//  Function: Copy from common.
//        IN: AX    = FASTFLIP_MPX_ID
//            DL    = 5
//            BX    = offset to read from       (0 based)
//            CX    = # of bytes to read        (1 based)
//            ES:DI = pointer to buffer
//       OUT: none
//
//  Function: Set lock state.
//        IN: AX    = FASTFLIP_MPX_ID
//            DL    = 6
//            BX    = lock state (0=off, 1=locked)
//       OUT: none
//

#include <stdio.h>
#include <stdlib.h>
#include <dos.h>

#define   byte  unsigned char
#define   word  unsigned int

#define   MPX_INT           0x2F
#define   FASTFLIP_MPX_ID   0xC2D2

#define   FF_LOADED         0x00
#define   FF_SET_PAGE       0x01
#define   FF_GET_PAGES      0x02
#define   FF_SET_TIMER      0x03
#define   FF_SET_MEM        0x04
#define   FF_GET_MEM        0x05
#define   FF_SET_LOCK       0x06

//
//------------------------------------------------------------------------
// General purpose interface into FastFlip
//------------------------------------------------------------------------
//
static word _ffISR(byte cmnd, byte op)
{
  union REGS regs;

  regs.x.ax = FASTFLIP_MPX_ID;      //our multiplex interrupt id
  regs.h.dl = cmnd;                 //command to perform
  regs.x.bx = op;                   //set option (not used by all commands)
  int86(MPX_INT,&regs,&regs);       //call multiplex interrupt
  return (regs.x.ax);               //return AX register back to caller
}

//
//------------------------------------------------------------------------
// Check to see if FastFlip is loaded
//------------------------------------------------------------------------
//
int ffLoaded(void)
{
  if (_ffISR(FF_LOADED,0) == 0xFF)    //test for load (0xFF = yes)
    return 1;                         // return TRUE
  return 0;                           //return FALSE
}

//
//------------------------------------------------------------------------
// Get the max number of pages available.
//------------------------------------------------------------------------
//
int ffGetMaxPage(void)
{
  return (_ffISR(FF_GET_PAGES,0));    //returns max # pages defined
}

//
//------------------------------------------------------------------------
// Set new active page
//------------------------------------------------------------------------
//
int ffSetPage(int page)
{
  return (_ffISR(FF_SET_PAGE,page));  //returns 1 = no err, 0 = error
}

//
//------------------------------------------------------------------------
// Set FastFlip internal timer
//------------------------------------------------------------------------
//
void ffSetTimer(int clicks)
{
  if (clicks < 1)                     //don't set timer below 1!
    clicks = 9;                       // default to 0.5 second tasks
  _ffISR(FF_SET_TIMER,clicks);        //no return value
}

//
//------------------------------------------------------------------------
// Set Common Mem
// NOTE: Common memory size is 64 bytes. NO RANGE CHECKING IS DONE.
//------------------------------------------------------------------------
//
void ffSetMem(int offset, void far *buf, int len)
{
  union   REGS  regs;
  struct  SREGS segs;

  segread(&segs);
  segs.es   = FP_SEG(buf);            //get segment of buffer
  regs.x.di = FP_OFF(buf);            //get offset of buffer
  regs.x.ax = FASTFLIP_MPX_ID;        //our multiplex interrupt id
  regs.h.dl = FF_SET_MEM;             //command
  regs.x.bx = offset;                 //0 based offset into common mem
  regs.x.cx = len;                    //# bytes to write
  int86x(MPX_INT,&regs,&regs,&segs);  //call multiplex interrupt
}

//
//------------------------------------------------------------------------
// Get Common Mem
// NOTE: Common memory size is 64 bytes. NO RANGE CHECKING IS DONE.
//------------------------------------------------------------------------
//
void ffGetMem(int offset, void far *buf, int len)
{
  union   REGS  regs;
  struct  SREGS segs;

  segread(&segs);
  segs.es   = FP_SEG(buf);            //get segment of buffer
  regs.x.di = FP_OFF(buf);            //get offset of buffer
  regs.x.ax = FASTFLIP_MPX_ID;        //our multiplex interrupt id
  regs.h.dl = FF_GET_MEM;             //command
  regs.x.bx = offset;                 //0 based offset into common mem
  regs.x.cx = len;                    //# bytes to read
  int86x(MPX_INT,&regs,&regs,&segs);  //call multiplex interrupt
}

//
//------------------------------------------------------------------------
// lock fastflip
//------------------------------------------------------------------------
//
void ffSetLock(int state)
{
  _ffISR(FF_SET_LOCK,state);          //no return value
}
