/*DDK*************************************************************************/
/*                                                                           */
/* COPYRIGHT (C) Microsoft Corporation, 1989                                 */
/* COPYRIGHT    Copyright (C) 1995 IBM Corporation                           */
/*                                                                           */
/*    The following IBM OS/2 WARP source code is provided to you solely for  */
/*    the purpose of assisting you in your development of OS/2 WARP device   */
/*    drivers. You may use this code in accordance with the IBM License      */
/*    Agreement provided in the IBM Device Driver Source Kit for OS/2. This  */
/*    Copyright statement may not be removed.                                */
/*                                                                           */
/*****************************************************************************/
/**************************************************************************
 *
 * SOURCE FILE NAME = svgasubs.c
 *
 * DESCRIPTIVE NAME = Super VGA memory and list-processing routines.  
 *
 *
 * VERSION = V2.0
 *
 * DATE
 *
 * DESCRIPTION Base video device handler - memory management routines.
 *                                                                     
 * FUNCTIONS   
 *
 * DEPENDENCIES:
 *
 * NOTES
 *
 * STRUCTURES
 *
 * EXTERNAL REFERENCES
 *
 * EXTERNAL FUNCTIONS
 *
*/

/*
**      Include files
*/

#define  INCL_BASE                     /* ALL of OS/2 Base                  */
#define  INCL_DOSDEVICES               /* Device specific, ring 2 support   */
#include <os2.h>
#include "svgatype.h"                  /* Type definitions                  */

extern USHORT APIENTRY FAR DosSMFreeMem(VOID FAR *);
extern USHORT APIENTRY FAR DosSMGetMem(VOID FAR *, USHORT);

/*****************************************************************************
 *
 *  FUNCTION NAME:    SVGAGetMem()
 *
 *
 *  DESCRIPTIVE NAME: Get memory
 *
 *  FUNCTION:
 *
 *  ENTRY POINT:
 *
 *  INPUT: (Passed on stack)
 *
 *  EXIT-NORMAL: AX = 0
 *
 *  EXIT-ERROR: AX = return code from DosSMGetMem()
 *
 *  EFFECTS:
 *
 *  NOTES:
 *	DosSMGetMem requires the first 4 bytes to be reserved for its own use.
 *	The pointer returned is therefore adjusted here to point to the actual
 *	memory requested.
 *
 *  INTERNAL REFERENCES:
 *    ROUTINES:
 *
 *  EXTERNAL REFERENCES:
 *    ROUTINES:
 *
 ****************************************************************************/

USHORT PASCAL NEAR SVGAGetMem(VOID FAR * p, USHORT size)
{
    USHORT	rc;

    if ( !(rc = DosSMGetMem(p, size)) )
      *(USHORT FAR *)p += 4;
    return(rc);
}

/*****************************************************************************
 *
 *  FUNCTION NAME:    SVGAFreeMem()
 *
 *
 *  DESCRIPTIVE NAME: Free memory previously allocated by SVGAGetMem()
 *
 *  FUNCTION:
 *
 *  ENTRY POINT:
 *
 *  INPUT: (Passed on stack)
 *
 *  EXIT-NORMAL: AX = 0
 *
 *  EXIT-ERROR: AX = return code from DosSMFreeMem()
 *
 *  EFFECTS:
 *
 *  NOTES:
 *	Note the adjustment of 4 bytes to compensate for reserved space.
 *
 *  INTERNAL REFERENCES:
 *    ROUTINES:
 *
 *  EXTERNAL REFERENCES:
 *    ROUTINES:
 *
 ****************************************************************************/

USHORT PASCAL NEAR SVGAFreeMem(VOID FAR * * p)
{
    USHORT rc;

    if ( !(rc = DosSMFreeMem((USHORT FAR *)*p-2)) )
      *p = NULL;
    return(rc);
}

/*****************************************************************************
 *
 *  FUNCTION NAME:    SVGAGetListSize()
 *
 *
 *  DESCRIPTIVE NAME:
 *
 *  FUNCTION:
 *	Traverse the given list and determine how much memory it uses.
 *
 *  ENTRY POINT:
 *
 *  INPUT: (Passed on stack)
 *
 *  EXIT-NORMAL:
 *	Return no of bytes.
 *
 *  EFFECTS:
 *
 *  NOTES:
 *
 ****************************************************************************/

USHORT PASCAL NEAR SVGAGetListSize(FPHWCOMMAND pCmd)
{
  USHORT usSize = 0;

  while (OFFSETOF(pCmd))
  {
    usSize += sizeof(HWCOMMAND);
    pCmd = MAKEP(SELECTOROF(pCmd),pCmd->pNextCmd);
  }

  return usSize;
}

/*****************************************************************************
 *
 *  FUNCTION NAME:    SVGACopyCmdList()
 *
 *
 *  DESCRIPTIVE NAME:
 *
 *  FUNCTION:
 *
 *  ENTRY POINT:
 *
 *  INPUT: (Passed on stack)
 *
 *  EXIT-NORMAL:
 *
 *  EXIT-ERROR:
 *
 *  EFFECTS:
 *
 *  NOTES:
 *
 ****************************************************************************/

VOID PASCAL NEAR SVGACopyCmdList(FPHWCOMMAND pCmdSrc, FPHWCOMMAND * pCmdDest)
{
  FPHWCOMMAND pCmdTmp;
  NPHWCOMMAND pPrev = NULL;

  if (!SVGAGetMem(pCmdDest, SVGAGetListSize(pCmdSrc)))
  {
    pCmdTmp = *pCmdDest;
    while (OFFSETOF(pCmdSrc))
    {
      *pCmdTmp = *pCmdSrc;

      if (OFFSETOF(pCmdSrc->pNextCmd))
        pCmdTmp->pNextCmd = (NPHWCOMMAND)(OFFSETOF(pCmdTmp) + sizeof(HWCOMMAND));
      else
        pCmdTmp->pNextCmd = NULL;

      pCmdTmp->pPrevCmd = pPrev;
      pPrev = (NPHWCOMMAND)OFFSETOF(pCmdTmp);
      (PBYTE)pCmdTmp += sizeof(HWCOMMAND);

      pCmdSrc = MAKEP(SELECTOROF(pCmdSrc),pCmdSrc->pNextCmd);
    }
  }
}

/*****************************************************************************
 *
 *  FUNCTION NAME:    SVGASearchList()
 *
 *
 *  DESCRIPTIVE NAME: Search command list for entry with matching Index port.
 *
 *  FUNCTION:
 *
 *  ENTRY POINT:
 *
 *  INPUT: (Passed on stack)
 *
 *  EXIT-NORMAL:
 *
 *  EXIT-ERROR:
 *
 *  EFFECTS:
 *
 *  NOTES:
 *
 ****************************************************************************/

FPHWCOMMAND PASCAL NEAR SVGASearchList(FPHWCOMMAND pHWCmd, register USHORT usPort)
{
  for (;OFFSETOF(pHWCmd) && (pHWCmd->usIndexPort != usPort);
    pHWCmd = MAKEP(SELECTOROF(pHWCmd),pHWCmd->pNextCmd));

  return(pHWCmd);
}

/*****************************************************************************
 *
 *  FUNCTION NAME:    SVGAXlatCmdList()
 *
 *
 *  DESCRIPTIVE NAME: Translate list commands for Save/Restore
 *
 *  FUNCTION:
 *
 *  ENTRY POINT:
 *
 *  INPUT: (Passed on stack)
 *	pHWCmd  == pointer to list to translate
 *	usFlags == SAVE -> prepare list for save of registers.
 *		   RESTORE -> change list back to original for restore.
 *
 *  EXIT-NORMAL:
 *
 *  EXIT-ERROR:
 *
 *  EFFECTS:
 *
 *  NOTES:
 *	if operation is no-op, its been through here as part of SAVE processing
 *	  clear no-op flag
 *	otherwise
 *	  if SAVE translation
 *	    change any OUT command which uses regs to IN command
 *	    no-op the rest
 *	  otherwise
 *	    change any IN command which uses regs to OUT command
 *
 ****************************************************************************/

VOID PASCAL NEAR SVGAXlatCmdList(FPHWCOMMAND pHWCmd, USHORT usFlags)
{
  while (OFFSETOF(pHWCmd))
  {
    if (pHWCmd->usFlags & PMIFLAG_NOOP)

      pHWCmd->usFlags &= ~PMIFLAG_NOOP;

    else

      switch (pHWCmd->usCommand)
      {
        case PMICMD_BOUTB:			/* always uses registers */
	  pHWCmd->usFlags |= PMIFLAG_UPDATELIST;
	  pHWCmd->usCommand = PMICMD_BINB;
	  break;

        case PMICMD_BINB:			/* always uses registers */
	  pHWCmd->usFlags &= ~PMIFLAG_UPDATELIST;
	  pHWCmd->usCommand = PMICMD_BOUTB;
	  break;

	default:
          if (usFlags == SAVE)			/* for save, no-op these */
	    pHWCmd->usFlags |= PMIFLAG_NOOP;
	  break;

      }

    pHWCmd = MAKEP(SELECTOROF(pHWCmd),pHWCmd->pNextCmd);
  }
}

