/*DDK*************************************************************************/
/*                                                                           */
/* 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.                                */
/*                                                                           */
/*****************************************************************************/
/*static char *SCCSID = "%w% %e%";*/
/**************************************************************************
 *
 * SOURCE FILE NAME = FL2GEO.C
 *
 * DESCRIPTIVE NAME = IBM2FLPY.ADD - Adapter Driver for ABIOS Diskette
 *
 *
 *
 * VERSION = V2.0
 *
 * DATE
 *
 * DESCRIPTION : Routines to implement the geometry commands.
 *
 *
 *
*/

#define INCL_NOBASEAPI
#define INCL_NOPMAPI
#include <os2.h>
#include <dhcalls.h>
#include <strat2.h>     /* needed to keep reqpkt.h happy */
#include <reqpkt.h>
#include <scb.h>        /* needed to keey abios.h happy */
#include <abios.h>
#include <iorb.h>
#include <addcalls.h>
#include "fl2def.h"
#include "fl2proto.h"
#include "fl2data.h"


/*****************************************************************************/
/*                                                                           */
/*   Routine     : Determine Media                                           */
/*                                                                           */
/*   Description : This routine starts a media determination sequence:       */
/*                                                                           */
/*                 Check the Changeline                                      */
/*                                                                           */
/*                                                                           */
/*****************************************************************************/

VOID NEAR DetermineMedia( PCFN DetermineComplete  )
{
   NPABRB_DSKT_READCHGLINE pRB = (NPABRB_DSKT_READCHGLINE)RequestBlock;

   Drive[pHeadIORB->UnitHandle].DetermineComplete = DetermineComplete;

   pRB->abrbh.Function  = ABFC_DSKT_READ_CHGSIGNAL;
   pRB->abrbh.Unit      = pHeadIORB->UnitHandle;
   pRB->abrbh.RC        = ABRC_START;
   pRB->Reserved_1      = 0;     /* +16H reserved field  */


   CompletionRoutine = DetermineChkChgComplete;
   Retry = 0;
   Stage = ABIOS_EP_START;
   NextStage();
}

/*****************************************************************************/
/*                                                                           */
/*   Routine     : DetermineChkChgComplete                                   */
/*                                                                           */
/*   Description : If the media has not changed, complete if:                */
/*                 - Previous media state = Unformatted                      */
/*                 - Previous media state = Known                            */
/*                 Else read verify RBA 0 (CHS=0,0,1)                        */
/*                                                                           */
/*****************************************************************************/

VOID FAR DetermineChkChgComplete()
{
   NPABRB_DSKT_READCHGLINE pRB = (NPABRB_DSKT_READCHGLINE)RequestBlock;
   USHORT                        ChgLine = TRUE;
   USHORT                        PrevMotorState;


   /*---------------------------------------------------------*/
   /* Collect the results from the changeline check. If       */
   /* the drive does not support changeline, then use         */
   /* the previous motor state, i.e. if the motor was started */
   /* previously, then the media was not changed.             */
   /*---------------------------------------------------------*/

   PrevMotorState = Drive[pHeadIORB->UnitHandle].Flags.MotorOn;

   Drive[pHeadIORB->UnitHandle].Flags.MotorOn = TRUE;

   if ( pRB->abrbh.RC == ABRC_COMPLETEOK )
      {

         if ( !(pRB->ChangeLineStatus & CHANGELINE_ACTIVE) )
            {
               ChgLine = FALSE;
            }
      }
   else
      {
         if ( PrevMotorState )
            {
               ChgLine = FALSE;
            }
      }

   /*-------------------------------------------------*/
   /* If there was no media change, then report the   */
   /* previous media state.                           */
   /*-------------------------------------------------*/

   if ( !ChgLine )
      {
        if ( Drive[pHeadIORB->UnitHandle].Flags.MediaNotFormatted )
           {
              pHeadIORB->ErrorCode = IOERR_MEDIA_NOT_FORMATTED;
              (*Drive[pHeadIORB->UnitHandle].DetermineComplete)();
              return;
           }
        if ( !Drive[pHeadIORB->UnitHandle].Flags.UnknownMedia )
           {
              pHeadIORB->Status &= ~IORB_ERROR;
              pHeadIORB->ErrorCode = 0;
              (*Drive[pHeadIORB->UnitHandle].DetermineComplete)();
              return;
           }

      }

   /*-------------------------------------------------*/
   /* Issue a read verify so ABIOS can figure out the */
   /* media geometry.                                 */
   /*-------------------------------------------------*/

   {
      NPABRB_DSKT_RWV pRB = (NPABRB_DSKT_RWV)RequestBlock;

      Drive[pHeadIORB->UnitHandle].Flags.UnknownMedia      = TRUE;
      Drive[pHeadIORB->UnitHandle].Flags.MediaNotFormatted = FALSE;
      Drive[pHeadIORB->UnitHandle].Flags.LogicalMedia      = FALSE;

      /* Verify the first sector on the diskette */
      pRB->abrbh.Function = ABFC_DSKT_VERIFY;
      pRB->abrbh.Unit     = pHeadIORB->UnitHandle;
      pRB->Cylinder       = 0;
      pRB->Head           = 0;
      pRB->Sector         = 1;
      pRB->cSectors       = 1;
      pRB->abrbh.RC       = ABRC_START;
      pRB->Reserved_2     = 0;     /* +16H reserved field  */
      pRB->Reserved_3     = 0;     /* +1EH reserved field  */

      CompletionRoutine = DetermineVerifyComplete;
      Retry = 0;
      Stage = ABIOS_EP_START;
      NextStage();
   }

}

/*****************************************************************************/
/*                                                                           */
/*   Routine     : VerifyComplete                                            */
/*                                                                           */
/*   Description : This routine is called when the Verify operation          */
/*                 completes.  If the Verify completed successfully          */
/*                 then call Read Media Parameters.                          */
/*                                                                           */
/*****************************************************************************/

VOID FAR DetermineVerifyComplete()
{
   NPABRB_DSKT_READMEDIAPARMS pRB = (NPABRB_DSKT_READMEDIAPARMS)RequestBlock;

   /*-----------------------------------------------------------*/
   /* If the Read Verify completed O.K., issue ABIOS Read Media */
   /* Parameters to extract the media information from ABIOS    */
   /*-----------------------------------------------------------*/

   if ( pRB->abrbh.RC == ABRC_COMPLETEOK )
      {
         /* Call Read Media Parameters */
         pRB->abrbh.Function  = ABFC_DSKT_READ_MEDIA_PARMS;
         pRB->abrbh.RC        = ABRC_START;
         pRB->Reserved_1      = 0;     /* +16H reserved field  */

         CompletionRoutine = DetermineReadParmsComplete;
         Retry = 0;
         Stage = ABIOS_EP_START;
         NextStage();
      }

   /*----------------------------------------------------------------*/
   /* If the Read Verify failed, and the cause was not due           */
   /* to NOT READY or MEDIA CHANGED, then set the MediaNotFormatted  */
   /* flag                                                           */
   /*----------------------------------------------------------------*/

   else
      {


         Drive[pHeadIORB->UnitHandle].Flags.UnknownMedia = TRUE;

         if ( pRB->abrbh.RC != ABRC_DSKT_MEDIA_CHANGED &&
              pRB->abrbh.RC != ABRC_DSKT_MEDIA_NOT_PRESENT )
            {
               Drive[pHeadIORB->UnitHandle].Flags.MediaNotFormatted = TRUE;
            }

         pHeadIORB->ErrorCode = TranslateErrorCode( pRB->abrbh.RC );
         (*Drive[pHeadIORB->UnitHandle].DetermineComplete)();
      }
}


/*****************************************************************************/
/*                                                                           */
/*   Routine     : ReadMediaParamsComplete                                   */
/*                                                                           */
/*   Description : This routine is called when Read Media Parameters         */
/*                 is complete.  If it completed successfully then           */
/*                 this routine updates the drive media geometry             */
/*                 structure with the new geometry and RWV is called         */
/*                 to do the read, write or verify.                          */
/*                                                                           */
/*****************************************************************************/

VOID FAR DetermineReadParmsComplete()
{
   NPABRB_DSKT_READMEDIAPARMS pRB = (NPABRB_DSKT_READMEDIAPARMS)RequestBlock;
   NPGEOMETRY pGeometry;

   if ( pRB->abrbh.RC == ABRC_COMPLETEOK )
      {
         pGeometry = &(Drive[pHeadIORB->UnitHandle].Geometry[MEDIA]);

         pGeometry->BytesPerSector  = 512;
         pGeometry->NumHeads        = pRB->cHeads;
         pGeometry->TotalCylinders  = pRB->cCylinders;
         pGeometry->SectorsPerTrack = pRB->SectorsPerTrack;
         pGeometry->TotalSectors    =
            pRB->cCylinders * pRB->cHeads * pRB->SectorsPerTrack;

         Drive[pHeadIORB->UnitHandle].Flags.UnknownMedia      = FALSE;

         Drive[pHeadIORB->UnitHandle].FormatGap = pRB->FormatGap;
      }

  (*Drive[pHeadIORB->UnitHandle].DetermineComplete)();
}
