/*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     : GetMediaGeometry                                          */
/*                                                                           */
/*   Description : This routine calls DetermineMedia to establish the        */
/*                 media type in the drive.                                  */
/*                                                                           */
/*****************************************************************************/

VOID NEAR GetMediaGeometry()
{
   DetermineMedia( GetMediaGeometryComplete );
}


/*****************************************************************************/
/*                                                                           */
/*   Routine     : GetMediaGeometryComplete                                  */
/*                                                                           */
/*   Description : This routine transfers the geometry information to        */
/*                 the IORB Geometry structure and turns off the drive       */
/*                 motor.                                                    */
/*                                                                           */
/*****************************************************************************/


VOID FAR GetMediaGeometryComplete()
{
   PIORB_GEOMETRY pIORB = (PIORB_GEOMETRY)pHeadIORB;
   NPABRB_DSKT_READMEDIAPARMS pRB = (NPABRB_DSKT_READMEDIAPARMS)RequestBlock;
   NPGEOMETRY pGeometry;

   if ( !pHeadIORB->ErrorCode )
      {
         pGeometry  = &(Drive[pHeadIORB->UnitHandle].Geometry[MEDIA]);
         *(pIORB->pGeometry) = *pGeometry;
      }
   else
      {
         pHeadIORB->Status |= IORB_ERROR;
      }
   StartTimer( pHeadIORB->UnitHandle,
               Drive[pHeadIORB->UnitHandle].MotorOffDelay ,TurnOffMotor );

   IORBDone();

}


/*****************************************************************************/
/*                                                                           */
/*   Routine     : SetMediaGeometry                                          */
/*                                                                           */
/*   Description : This routine is executed in preparation for a             */
/*                 format and defines the geometry of the media to be        */
/*                 formatted.                                                */
/*                                                                           */
/*****************************************************************************/

VOID NEAR SetMediaGeometry()
{
   PIORB_GEOMETRY pIORB = (PIORB_GEOMETRY)pHeadIORB;
   NPGEOMETRY     pGeometry;
   USHORT         FormatGap;
   USHORT         RWGap;
   USHORT         SectorSizeCode;

   /*---------------------------------------------------*/           /*@V82589*/
   /* Changes for Defect 82589                          */           /*@V82589*/
   /*                                                   */           /*@V82589*/
   /* 1.) Verify BlockSize passed in IORB Geometry is   */           /*@V82589*/
   /*     supported.                                    */           /*@V82589*/
   /* 2.) Set RWGap based on IORB Geometry              */           /*@V82589*/
   /* 3.) Wait for media access to actually set new     */           /*@V82589*/
   /*     parameters.                                   */           /*@V82589*/
   /*---------------------------------------------------*/           /*@V82589*/

   SectorSizeCode = BlkSizeToN( pIORB->pGeometry->BytesPerSector );

   if ( SectorSizeCode == -1 )
      {
         Drive[pHeadIORB->UnitHandle].Flags.UnknownMedia = TRUE;
         pHeadIORB->ErrorCode = IOERR_MEDIA_NOT_SUPPORTED;
         pHeadIORB->Status   |= IORB_ERROR;
         IORBDone();
         return;
      }
   /**Japan Only**************************************/                         
   /* I could find most appropriate place for insert */                         
   /* next statement! But the CurrentBlockSize must  */                         
   /* change for it might DetermineMedia()ed as      */                         
   /* different type.                                */                         
   /**************************************************/                         
   if( CurrentBlockSize != SectorSizeCode)                                      
   {                                                                            
       ShouldSetDevParams   = 1;                                                
       CurrentBlockSize     = SectorSizeCode;                                   
   }                                                                            

   /* Set the format gap based on the media geometry */
   FormatGap = Drive[pHeadIORB->UnitHandle].FormatGap;
   RWGap     = Drive[pHeadIORB->UnitHandle].ReadGap;

   switch( pIORB->pGeometry->TotalSectors )
      {
         case 640:  FormatGap = 0x50; RWGap = 0x2A; break;  /*  320K */
         case 720:  FormatGap = 0x54; RWGap = 0x2A; break;  /*  360K */
         case 1232: FormatGap = 0x74; RWGap = 0x35; break;  /* 1.23K */         
         case 1440: FormatGap = 0x50; RWGap = 0x1B; break;  /*  720K */
         case 2400: FormatGap = 0x54; RWGap = 0x1B; break;  /*  1.2M */
         case 2880: FormatGap = 0x65; RWGap = 0x1B; break;  /* 1.44M */
         case 5760: FormatGap = 0x53; RWGap = 0x1B; break;  /* 2.88M */
      }

   Drive[pHeadIORB->UnitHandle].FormatGap = FormatGap;
   Drive[pHeadIORB->UnitHandle].ReadGap   = RWGap;

   pGeometry = &(Drive[pHeadIORB->UnitHandle].Geometry[MEDIA]);

   *pGeometry = *(pIORB->pGeometry);

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

   pHeadIORB->ErrorCode = 0;

   IORBDone();
}


/*****************************************************************************/
/*                                                                           */
/*   Routine     : GetDeviceGeometry                                         */
/*                                                                           */
/*   Description : This routine simply copies the device geometry info       */
/*                 from the drive device geometry structure to the IORB.     */
/*                 The device geometry information was obtained at           */
/*                 initialization time from ABIOS.                           */
/*                                                                           */
/*****************************************************************************/

VOID NEAR GetDeviceGeometry()
{
   PIORB_GEOMETRY pIORB = (PIORB_GEOMETRY)pHeadIORB;
   NPGEOMETRY pDeviceGeometry;

   pDeviceGeometry = &(Drive[pHeadIORB->UnitHandle].Geometry[DEVICE]);

   *(pIORB->pGeometry) = *pDeviceGeometry;

   IORBDone();
}


/*****************************************************************************/
/*                                                                           */
/*   Routine     : SetLogicalGeometry                                        */
/*                                                                           */
/*   Description : The specified logical geometry is copied from the         */
/*                 IORB to the drive media geometry structure and the        */
/*                 Logical Media flag is set.  Logical geometry means        */
/*                 that the media is formatted in some non-standard way.     */
/*                 For example: a 1.44M diskette is formatted as 720K.       */
/*                 Another example: a 1.44M diskette formatted as 1.2M.      */
/*                 ABIOS assumes that a diskette is always formatted to      */
/*                 its highest capacity.  However, this ADD can still        */
/*                 handle non-standard diskette formats by not letting       */
/*                 ABIOS cross a head boundry on an IO operation.  The       */
/*                 Logical Media flag tells the IO routines to break up      */
/*                 read, write and verify operations so that an ABIOS        */
/*                 request does not cross a head boundry.                    */
/*                                                                           */
/*****************************************************************************/

VOID NEAR SetLogicalGeometry()
{
   PIORB_GEOMETRY pIORB = (PIORB_GEOMETRY)pHeadIORB;
   NPGEOMETRY pLogicalGeometry;

   pLogicalGeometry = &(Drive[pHeadIORB->UnitHandle].Geometry[MEDIA]);

   *pLogicalGeometry = *(pIORB->pGeometry);

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

   IORBDone();
}


