/* Copyright © Feb.1997 by Michael Christoph */
/* CheckDiskCom.c - Kommandofunktionen */

/************************** INCLUDES ********************************/

#include "CheckDisk.h"

#include <pExec/Device.h>
#include <pDos/DosErrors.h>
#include <proto/pExec2.h>
#include <proto/pDos2.h>

/********************************************************************/
/* Laufwerk mit angegebener Nummer eröfnen,
** Result 'NULL' im Falle eines Fehlers
*/

struct pOS_TrackdiskIO *TDOpen(const CHAR *name, UWORD unit, ULONG flags)
{
  struct pOS_MsgPort *mp;
  struct pOS_TrackdiskIO *ioetd;

  if((mp=pOS_CreatePort(NULL,0)))
  {
    if((ioetd=(struct pOS_TrackdiskIO *) pOS_CreateIORequest(mp,sizeof(struct pOS_TrackdiskIO))))
    {
      if(pOS_OpenDevice(name,unit,(struct pOS_IORequest *)ioetd,flags,0) == 0)
      {
        ioetd->tdio_Command=CMD_INVALID;  /* für 'TDFinish() ' */
        ioetd->tdio_Count=TDSimpleIO(ioetd,TDCMD_ChangeNum);
        return( ioetd );
      }
      pOS_DeleteIORequest((struct pOS_IORequest *)ioetd);
    }
    pOS_DeletePort(mp);
  }

  return( NULL );
}

/********************************************************************/
/* Schließen eines zuvor geöffneten Laufwerks */

VOID TDClose(struct pOS_TrackdiskIO *ioetd)
{
  if(ioetd)
  {
    struct pOS_MsgPort *mp;
    TDFinish(ioetd);
    pOS_CloseDevice((struct pOS_IORequest *)ioetd);
    mp=ioetd->tdio_Message.mn_ReplyPort;
    pOS_DeleteIORequest((struct pOS_IORequest *)ioetd);
    if(mp) pOS_DeletePort(mp);
  }
}

/********************************************************************/
/* vereinfachtes I/O für Kommandos ohne Parameter:
** TD_CHANGENUM, TD_CHANGESTATE, TD_PROTSTATUS,
** TD_GETDRIVETYPE, TD_GETNUMTRACKS
*/

ULONG TDSimpleIO(struct pOS_TrackdiskIO *ioetd, UWORD command)
{
  ioetd->tdio_Command=command;
  TDDoIO(ioetd);                       /* Fehler werden ignoriert ! */

  return( ioetd->tdio_Actual );
}

/********************************************************************/
/* Laufwerksmotor ausschalten */

SBYTE TDMotorOff(struct pOS_TrackdiskIO *ioetd)
{
  ioetd->tdio_Command=TDCMD_Motor;
  ioetd->tdio_Length=0;

  return( TDDoIO(ioetd) );
}

/********************************************************************/
/* Disketten I/O abschließen */

SBYTE TDFinish(struct pOS_TrackdiskIO *ioetd)
{
  SBYTE error=ioetd->tdio_Error;

  if(ioetd->tdio_Command==TDCMDE_Write)
  {
    if(error==0)  /* vorhergehendes 'WRITE' ok! */
    {
      ioetd->tdio_Command=TDCMDE_Update;
      error=TDDoIO(ioetd);
    }
    if(error != 0)  /* entweder 'WRITE' oder 'UPDATE' fehlerhaft */
    {
      ioetd->tdio_Command=TDCMDE_Clear;
      TDDoIO(ioetd);
    }
  }
  TDMotorOff(ioetd);

  return( error );  /* bei 'READ' unverändert */
}

/********************************************************************/
/* Fehlertext zu Fehlercode rückgeben, 'NULL' bei nicht definierbarem Fehler */

CHAR *TDError(SBYTE error)
{
  CHAR *res="unknown";

  switch(error)
  {
    case IOERR_OpenFail:         res="open failed"; break;
    case IOERR_Aborted:          res="command aborted"; break;
    case IOERR_NoCMD:            res="not a valid command"; break;
    case IOERR_BadLength:        res="bad sector number"; break;
    case TDIOERR_NotSpecified:   res="not specified"; break;
    case TDIOERR_NoSecHdr:       res="no sector header"; break;
    case TDIOERR_BadSecPreamble: res="bad sector preamble"; break;
    case TDIOERR_BadSecID:       res="bad sector ID"; break;
    case TDIOERR_BadHdrSum:      res="bad header checksum"; break;
    case TDIOERR_BadSecSum:      res="bad sector checksum"; break;
    case TDIOERR_TooFewSecs:     res="too few sectors"; break;
    case TDIOERR_BadSecHdr:      res="bad sector header"; break;
    case TDIOERR_WriteProt:      res="disk is write protected"; break;
    case TDIOERR_DiskChanged:    res="disk changed or removed"; break;
    case TDIOERR_SeekError:      res="seek error"; break;
    case TDIOERR_NoMem:          res="no memory"; break;
    case TDIOERR_BadUnitNum:     res="bad unit number"; break;
    case TDIOERR_BadDriveType:   res="bad drive type"; break;
    case TDIOERR_DriveInUse:     res="drive in use"; break;
    case TDIOERR_PostReset:      res="awaiting doom"; break;
  }

  return( res );
}

/********************************************************************/
/* zentrale Funktionen für Schreiben und Lesen, wird von Macros aufgerufen */

SBYTE TDIO(struct pOS_TrackdiskIO *ioetd, UWORD command, ULONG length, UBYTE *buffer, ULONG offset)
{
  ioetd->tdio_Command=command;
  ioetd->tdio_Length=length;
  ioetd->tdio_Data=(APTR)buffer;
  ioetd->tdio_HOffset=0;
  ioetd->tdio_LOffset=length*offset;
  ioetd->tdio_SecLabel=0;

  return( TDDoIO(ioetd) );
}

/********************************************************************/

