/*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 = 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 )
           {
              if( ShouldSetDevParams)                                           
              {                                                                 
                  NPABRB_DSKT_SETDEVPARMS pRB = (NPABRB_DSKT_SETDEVPARMS)RequestBlock;
                  pRB->abrbh.Function = ABFC_SET_DEVICE_PARMS;                  
                  pRB->abrbh.Unit     = pHeadIORB->UnitHandle;                  
                  pRB->Reserved_1     = 0;                                      
                  pRB->BlockSize      = CurrentBlockSize;                       
                                                                                
                  pRB->abrbh.RC       = ABRC_START;                             
                                                                                
                  CompletionRoutine   = SetDevParamsForRWV;                     
                  Retry = 0;                                                    
                  Stage = ABIOS_EP_START;                                       
                  NextStage();                                                  
                  return;                                                       
              }                                                                 
              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_DETERMINE_MEDIA pRB = (NPABRB_DETERMINE_MEDIA)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_DETERMINE_MEDIA;                    
      pRB->abrbh.Unit           = pHeadIORB->UnitHandle;                        
      pRB->RSpeed               = 1;                            
      pRB->Reserved_1           = 0;                                            
      pRB->Cylinder             = 0;                                            
      pRB->Head                 = 0;                                            
      pRB->abrbh.RC             = ABRC_START;                                   
      CompletionRoutine         = DetermineMedia2;                              
      CurrentBlockSize          = 2;   
      ShouldSetDevParams        = 0;                                            
      Retry = 0;
      Stage = ABIOS_EP_START;
      NextStage();
   }

}

/*Japan Only******************************************************************/ 
/*                                                                           */ 
/*   Routine     : SetDevParamsForRWV                                        */ 
/*                                                                           */ 
/*   Description :                                                           */ 
/*                                                                           */ 
/*                                                                           */ 
/*                                                                           */ 
/*****************************************************************************/ 
                                                                                
VOID FAR SetDevParamsForRWV()                                                   
{                                                                               
      NPABRB_DSKT_SETDEVPARMS pRB = (NPABRB_DSKT_SETDEVPARMS)RequestBlock;      
                                                                                
      if( pRB->abrbh.RC == ABRC_COMPLETEOK )                                    
      {                                                                         
          pHeadIORB->Status &= ~IORB_ERROR;                                     
          pHeadIORB->ErrorCode = 0;                                             
      }                                                                         
      else                                                                      
          pHeadIORB->ErrorCode = TranslateErrorCode( pRB->abrbh.RC );           
      (*Drive[pHeadIORB->UnitHandle].DetermineComplete)();                      
      return;                                                                   
}                                                                               
/*Japan Only******************************************************************/ 
/*                                                                           */ 
/*   Routine     : DetermineMedia2                                           */ 
/*                                                                           */ 
/*   Description :                                                           */ 
/*                                                                           */ 
/*                                                                           */ 
/*                                                                           */ 
/*****************************************************************************/ 
                                                                                
VOID FAR DetermineMedia2()                                                      
{                                                                               
      NPABRB_DETERMINE_MEDIA pRB = (NPABRB_DETERMINE_MEDIA)RequestBlock;        
                                                                                
      if ( pRB->abrbh.RC == ABRC_UNSUPPORTED_FUNCTION )                         
          EndDetermineMedia1();                                                 
      else if ( pRB->abrbh.RC == ABRC_COMPLETEOK )                              
      {                                                                         
          if( pRB->BlockSize != 2)                                              
          {                                                                     
              ShouldSetDevParams = 1;                                           
              CurrentBlockSize   = pRB->BlockSize;                              
          }                                                                     
          EndDetermineMedia2();                                                 
      }                                                                         
      else                                                                      
      {                                                                         
          /* Error case                                         */              
          /* Just after boot, meida change line is active.      */              
          /* MEDIA_CHANGED information from ABIOS can be ignore.*/              
          /* Try again.                                         */              
          if (pRB->abrbh.RC == ABRC_DSKT_MEDIA_CHANGED)                         
              Drive[pHeadIORB->UnitHandle].Flags.UnknownMedia = TRUE;           
          pHeadIORB->ErrorCode = TranslateErrorCode( pRB->abrbh.RC );           
          (*Drive[pHeadIORB->UnitHandle].DetermineComplete)();                  
      }                                                                         
}                                                                               
/*Japan Only******************************************************************/ 
/*                                                                           */ 
/*   Routine     : EndDetermineMedia1                                        */ 
/*                                                                           */ 
/*   Description :                                                           */ 
/*                                                                           */ 
/*                                                                           */ 
/*                                                                           */ 
/*****************************************************************************/ 
                                                                                
VOID FAR EndDetermineMedia1()                                                   
{                                                                               
      NPABRB_DSKT_RWV pRB = (NPABRB_DSKT_RWV)RequestBlock;                      
      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  */                   
                                                                                
      ShouldSetDevParams  = 0;                                                  
      CompletionRoutine   = DetermineVerifyComplete;                            
      Retry = 0;                                                                
      Stage = ABIOS_EP_START;                                                   
      NextStage();                                                              
}                                                                               
/*Japan Only******************************************************************/ 
/*                                                                           */ 
/*   Routine     : EndDetermineMedia2                                        */ 
/*                                                                           */ 
/*   Description :                                                           */ 
/*                                                                           */ 
/*                                                                           */ 
/*                                                                           */ 
/*****************************************************************************/ 
                                                                                
VOID FAR EndDetermineMedia2()                                                   
{                                                                               
      NPABRB_DSKT_SETDEVPARMS pRB = (NPABRB_DSKT_SETDEVPARMS)RequestBlock;      
      pRB->abrbh.Function = ABFC_SET_DEVICE_PARMS;                              
      pRB->abrbh.Unit     = pHeadIORB->UnitHandle;                              
      pRB->Reserved_1     = 0;                                                  
                                                                                
      pRB->abrbh.RC       = ABRC_START;                                         
                                                                                
      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;
         if( pRB->SectorsPerTrack == 8)                                         
             pGeometry->BytesPerSector  = 1024;                                 
         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)();
}
