/*DDK*************************************************************************/
/*                                                                           */
/* COPYRIGHT    Copyright (C) 1992 IBM Corporation                           */
/*                                                                           */
/*    The following IBM OS/2 source code is provided to you solely for       */
/*    the purpose of assisting you in your development of OS/2 device        */
/*    drivers. You may use this code in accordance with the IBM License      */
/*    Agreement provided in the IBM Developer Connection Device Driver       */
/*    Source Kit for OS/2. This Copyright statement may not be removed.      */
/*                                                                           */
/*****************************************************************************/
/*static char *SCCSID = "%w% %e%";*/
/**************************************************************************
 *
 * SOURCE FILE NAME = S506APM.C
 *
 * DESCRIPTIVE NAME = IBM1S506.ADD - Adapter Driver for ST506/IDE DASD
 *
 *
 * VERSION = V3.0
 *
 * DATE    = 3/30/96 - new for Warm Docking
 *
 * DESCRIPTION : Adapter Driver APM callback routines
 *
 * Purpose:
 *
 *
*/
#define INCL_NOBASEAPI
#define INCL_NOPMAPI
#define INCL_NO_SCB
#define INCL_INITRP_ONLY
#define INCL_DOSERRORS
#include "os2.h"
#include "dos.h"
#include "bseerr.h"
#include "dskinit.h"
#include <scb.h>
#include <abios.h>

#include "iorb.h"
#include "reqpkt.h"
#include "dhcalls.h"
#include "addcalls.h"
#include "devclass.h"

#include "s506cons.h"
#include "s506type.h"
#include "s506regs.h"
#include "s506ext.h"
#include "s506pro.h"
#include "s506misc.h"


/*------------------------------------*/
/* APM Suspend/Resume Support         */
/* Reinitializes adapters and units   */
/* following a resume event.          */
/*------------------------------------*/

USHORT FAR APMEventHandler(PAPMEVENT Event)
{
  USHORT Message = (USHORT)Event->ulParm1;
  USHORT PwrState;

  if ( Message == APM_SETPWRSTATE )
  {
    PwrState = (USHORT)(Event->ulParm2 >> 16);
    if (PwrState != APM_PWRSTATEREADY)
    {
      return ( APMSuspend() );
    }
  }
  else if ( Message == APM_NORMRESUMEEVENT || Message == APM_CRITRESUMEEVENT )
  {
    return(APMResume());
  }
  return 0;
}


/*
 * APMSuspend is currently a no-op
 */
USHORT NEAR APMSuspend()
{
  return 0;
}

USHORT NEAR APMResume()
{
  NPATBL npAT = AdapterTable;
  NPACB  npACB;
  NPUCB  npUCB;
  USHORT i;
  USHORT j;
   USHORT Data;
   USHORT Port;
  for (i=0; i< cAdapters; i++, npAT++ )
  {
		if  (npAT->Flags & ATBF_FORCE)
		{
	   	if ( !(npAT->Flags & ATBF_DISABLED) )
   		{
      		if ( !ReConfigureController( npAT ) )
      		{
        			npACB = npAT->npACB;
        			for (j=0; j < npACB->cUnits; j++)
        			{
          			ReConfigureUnit( npAT, j );
        			}
				}
      	}
  		}
		else
		{
        	npACB = npAT->npACB;
        	for (j=0; j < npACB->cUnits; j++)
        	{
			   npUCB = &npACB->UnitCB[j];
				if ( !(npUCB->Flags & UCBF_ATAPIDEVICE)) continue;
		       SelectUnit( npACB, j );
				// Do atapi reset in case unit is locked up by BIOS
		   	Data = FX_ATAPI_RESET;
		   	Port = npACB->IOPorts[FI_PCMD];
		   	outp( Port, Data );
			}
		}
  }
  return 0;
}


USHORT NEAR ReConfigureController( NPATBL npAT )
{
  NPACB         npACB = npAT->npACB;                                /*@V155162*/
  USHORT        rc = 0;
  USHORT        i;
  USHORT	Forced = 0;

  npAT->Status = ATS_OK;
  if ( CheckController( npAT ) )
  {
    if ( npAT->Flags & ATBF_FORCE )
    {
      Forced = 1;
    }
    else
    {
      npAT->Status = ATS_NOT_PRESENT;
      goto ReConfigureControllerExit;
    }
  }

  if ( !(npAT->Flags & ATBF_DISABLERESET) && (npAT->BasePort != FX_PRIMARY) )
  {
    ResetController( npACB );
  }

ReConfigureControllerExit:

  return ( npAT->Status );
}


USHORT ReConfigureUnit( NPATBL npAT, USHORT UnitId )
{
  NPACB         npACB;
  NPGEOMETRY    npGEO;
  NPUTBL        npUT;
  USHORT        rc;

  npACB = npAT->npACB;
  npUT  = &npAT->Unit[UnitId];

  /*----------------------------------------*/
  /* Select unit and check status for READY */
  /*----------------------------------------*/

  /*------------------------------------------*/
  /* COMPAQ machines throw an interrupt when  */
  /* a non-installed unit is selected.        */
  /*------------------------------------------*/

  DISABLE
  SelectUnit( npACB, UnitId );
  rc = CheckReady( npACB );
	SelectUnit( npACB, 0 );
  ENABLE

  if (npUT->Flags & UTBF_FORCE)
  {
    NPUCB npUCB = &npACB->UnitCB[UnitId];
    npUCB->Flags |= UCBF_FORCE;
    if ( rc )
    {
      /*------------------------------------------*/
      /* Force Unit to be recognized as present.  */
      /*------------------------------------------*/
      npUCB->Flags |= UCBF_NOTPRESENT;
      rc = 0;
    }
    else
    {

		npUCB->Flags |= UCBF_CHANGED;
      npUCB->Flags &= ~(UCBF_NOTPRESENT|UCBF_LOCKED);
    }
  }

  if ( rc )
  {
    rc = npUT->Status = UTS_NOT_PRESENT;
  }
  return ( rc );
}


/*
** Start @V155162 -
*/
int near CardServices(USHORT Function, USHORT Handle,
                 PVOID Pointer, USHORT ArgLength,
                 PVOID ArgPointer, PUSHORT pHandle)
{
   int rc;
   _asm
   {
      mov     ax,Function
      mov     dx,Handle
      mov     di,Pointer+2
      mov     si,Pointer
      mov     cx,ArgLength
      mov     es,ArgPointer+2
      mov     bx,ArgPointer
      call    dword ptr [pCardServices]
      jc      CSExit
      mov     bx,pHandle
      cmp     bx,pHandle+2
      jz      CSExit
      mov     es,pHandle+2
      mov     es:[bx],dx
   CSexit:
      mov     rc,ax
   }
   return rc;
}
USHORT NEAR CardRemoval(USHORT Socket)
{
}
USHORT NEAR CardInsertion(USHORT Socket)
{

   struct GTD_P Tupple;
   struct GCI_P ConfigInfo;

   // clear bufffer
   setmem((PVOID)&Tupple,0,sizeof(Tupple));
   // set identification tuple
   Tupple.GTD_DesiredTuple=CISTPL_VERS_1;
   /// set specific socket concerned with
   Tupple.GTD_Socket=Socket;
   // ask card services to find that tuple
   if (!CardServices(GetFirstTuple,ClientHandle,0,sizeof(struct GFT_P),&Tupple,0))
   {
      // get the tuple data
      if (!CardServices(GetTupleData,ClientHandle,0,sizeof(Tupple),&Tupple,0))
      {
         // verify it is for our vendor
         if (Tupple.GTD_TupleDataLen>=strlen(PacRimID))
         {
            if (strncmp(Tupple.GTD_TupleData+4, PacRimID,strlen(PacRimID)))
            {
               // ask for the config tuple
               Tupple.GTD_DesiredTuple=CISTPL_CFTABLE_ENTRY;
               if (!CardServices(GetFirstTuple,ClientHandle,0,sizeof(struct GFT_P),&Tupple,0))
               {
                  // get its data
                  if (!CardServices(GetTupleData,ClientHandle,0,sizeof(Tupple),&Tupple,0))
                  {

                  }
               }
            }
         }
      }
   }
}

int far Callback( )
{
    UCHAR   Event;                      //   Event code
    int     err;
    USHORT Socket,junk;

    _asm
    {
                push    bx
                push    cx
                push    dx
                push    ds
                push    es
                push    ss
                push    di
                push    si

                mov     Event, al       ; Store event code
                mov     Socket, cx      ; Store logical socket number
    }

    switch( Event )
    {
        case REGISTRATION_COMPLETE:
            if ( ReqBlockID )
               DevHelp_ProcRun( ReqBlockID, &junk );                     // #57
            err = 0;
            break;

        case CARD_INSERTION:
            CardInsertion(Socket);
            err = 0;
            break;

        case CARD_REMOVAL:
            CardRemoval(Socket );
            err = 0;
            break;
    }

    _asm
    {
                cmp     err, 0
                jne     CB_ERR
                clc                     ; Clear CF because of no error
                jmp     CB_END
        CB_ERR:
                stc                     ; Set CF because of reject
        CB_END:
                pop     si
                pop     di
                pop     ss
                pop     es
                pop     ds
                pop     dx
                pop     cx
                pop     bx
    }

    return( err );
}

void near PCMCIASetup()
{
   struct RC_P   RC;           // RegistrClient

   if (!DevHelp_AttachDD(PCMCIA_DDName,(NPBYTE)&PCMIDC))
   {
      pCardServices=PCMIDC.ProtIDCEntry;
      DevHelp_VirtToPhys((PVOID)&PCMCIASetup,&ReqBlockID);
      setmem((PVOID)&RC,0,sizeof(RC));
      RC.RC_Attributes = ATB_IOClient | ATB_Insert4Sharable | ATB_Insert4Exclusive;
      RC.RC_EventMask  = EM_CardDetectChange;  // event mask
      RC.RC_Data       = 0;                       // 16 bit data determined
      _asm
       {
       mov     RC.RC_Segment, ds       ; Set driver data segment
       }
      RC.RC_Offset     = 0;                       // 16 bit offset determined
      RC.RC_Reserved   = 0;                       // 16 bit reserved (reset to 0)
      RC.RC_Version    = 0x100;                   // client version number
      DISABLE;
      if(!CardServices( RegisterClient, ClientHandle, (PVOID)Callback, sizeof( RC ), (PVOID)&RC , &ClientHandle))
        DevHelp_ProcBlock(ReqBlockID,-1,0);
      ENABLE;
   }
}
/*
** End @V155162
*/
