/* -*-C-*-
********************************************************************************
*
* File:         rwdisk.c
* RCS:          $Header: rwdisk.c,v 1.1 93/03/19 14:24:54 mjp Exp $
* Description:  Read and Write Emax Disc Banks from disk
* Author:       Mike Prudence, (mjp@hplb.hpl.hp.com)
* Created:      Wed Mar 17 15:04:03 1993
* Modified:     Fri Mar 19 17:33:39 1993 (Mike Prudence) mjp@prudence
* Language:     C
*
* (c) Copyright 1993, Mike Prudence
*
********************************************************************************
*/

#include "rwdisk.h"

#define RWDISK_VERSION	"1.1"
#define RWDISK_DATE	"Fri Mar 19 13:31:05 1993"

TRACK_BUF t;          /* Where data is stored temporarily */
unsigned long total;   /* How many sectors we have read/written so far */
unsigned long target;  /* Total number of sectors to be set */

int ReadDisk (int drive, char *fn)
{
  int result, fh;
  char hdr[EMAXUTIL_HDRLEN];
 
  if ((fh = open(fn,O_CREAT|O_WRONLY|O_BINARY,
		    S_IREAD|S_IWRITE)) == -1)
  {
        write_error("Error opening file for write.");
        return(result);
  }

  write_text (26, 15, 6, "Starting read");

  cursor_off();

  sprintf (hdr, EMAXUTIL_HDR, RWDISK_VERSION, RWDISK_DATE);

  if ((result = write (fh, hdr, (unsigned int)EMAXUTIL_HDRLEN)) == -1)
    {
      write_error("Error writing to file.");
      cursor_on();
      return(result);
    }

  total=0;
  target=TOTAL_BLKS;

  if (ReadDiskRegion (fh, drive, BANK_LOW, BANK_HIGH) == -1)
     return (-1);

  if (ReadDiskRegion (fh, drive, SAMPLE_LOW, SAMPLE_HIGH) == -1)
     return (-1);

  cursor_on();

  if (kbhit()) getch();

  return close(fh);
}

int WriteDisk (char *fn, int drive)
{
  int result, fh;
  int hdr[EMAXUTIL_HDRLEN];
  int fhdr[EMAXUTIL_HDRLEN];

  if ((fh = open(fn,O_RDONLY|O_BINARY,S_IREAD|S_IWRITE)) == -1)
  {
        write_error("Error opening file for read.");
        return(result);
  }

  write_text (26, 15, 6, "Starting write");

  cursor_off();

  sprintf (hdr, EMAXUTIL_HDR, RWDISK_VERSION, RWDISK_DATE);

  if ((result = read (fh, fhdr, (unsigned int) EMAXUTIL_HDRLEN)) == -1)
    {
      write_error("Error reading from file.");
      cursor_on();
      return(result);
    }

  if (strncmp(fhdr, hdr, EMAXUTIL_HDRLEN)!=0)
    {
      char s[160];

      fhdr[EMAXUTIL_HDRLEN-1]=0;
      sprintf (s, "Wrong version: disk says %s", fhdr);
      write_error (s);
      return(-1);
    }

  total=0;
  target=TOTAL_BLKS;

  if (WriteDiskRegion (fh, drive, BANK_LOW, BANK_HIGH) == -1)
     return (-1);
  if (WriteDiskRegion (fh, drive, SAMPLE_LOW, SAMPLE_HIGH) == -1)
     return (-1);

  cursor_on();

  if (kbhit()) getch();

  return close(fh);
}

int VerifyDisk (int drive)
{
  int trk, hd, sctr, numerr, result;
  char s[80];

  write_text (26, 15, 6, "Starting verify");

  cursor_off();

  numerr = 0;
  for (trk=0; trk<TRK_CYL; trk++)
  {
    if (kbhit()) break;
    for (hd=0; hd<HEADS; hd++)
    {
      if (kbhit()) break;

      sprintf (s,  "Verifying Track %2d Head %2d",trk,hd);
      write_text (26, 15, 6, s);

      if (result = VerifyAbsSectors(drive,hd,trk,START_SCTR,SCTR_TRK,t[0]))
      {
        /* There's an error on this track somewhere! */

        write_error("Verify Errors!");
	for (sctr=0; sctr<SCTR_TRK; sctr++)
	{
	  if (result = VerifyAbsSectors(drive,hd,trk,sctr,1,t[0]))
	  {
            sprintf (s, "--> sector %2d: %s\n",sctr,emax_io_error(result));
	    write_error(s);
	    numerr++;
	  }
	}
      }
    }
  }

  if (kbhit())
  {
    write_text(26, 15, 6, "        Aborted by keypress!                ");
    getch();
  } else {
    printf(26, 15, 6, "                 Done!                         ");
  }

  cursor_on();
  return(numerr);
}

int BlkToTrk (int blk)
{
  return (blk / (HEADS * SCTR_TRK));
}

int BlkToSect (int blk)
{
  return ((blk % SCTR_TRK) + START_SCTR);
}

int BlkToHead (int blk)
{
  return ((blk / SCTR_TRK) % HEADS);
}

int ReadDiskRegion (int fh, int drive, int loblk, int hiblk)
{
  int lotrk, lohd, losct;
  int hitrk, hihd, hisct;
  int hd, trk;
  int result;
  char s[80];

  /* Work out track/head/sector numbers for the start of the region */

  lotrk = BlkToTrk (loblk);
  losct = BlkToSect (loblk);
  lohd  = BlkToHead (loblk);

  hitrk = BlkToTrk (hiblk);
  hisct = BlkToSect (hiblk);
  hihd  = BlkToHead (hiblk);

  /* Read the region.  Set the start sector and number of sectors
     according to where we are in the region */

  for (trk=lotrk; trk <= hitrk; trk++)
    {
      int starthd;
      int endhd;

      if (trk==lotrk)
	starthd = lohd;
      else
	starthd = 0;

      if (trk==hitrk)
	endhd = hihd;
      else
	endhd = HEADS-1;

      for (hd=starthd; hd<=endhd; hd++)
	{
	  int nsects;       /* How many sectors to read from this track */
	  int startsct;

	  if (kbhit()) break;

	  nsects=SCTR_TRK;
	  startsct=START_SCTR;

          if ((trk==lotrk) && (hd==lohd))
	    {
 	      nsects = nsects - losct + START_SCTR;
	      startsct = losct;
	    }
	  else if ((trk==hitrk) && (hd==hihd))
	    nsects=nsects-SCTR_TRK+hisct;

#ifdef DEBUG
	  sprintf (s, "track %2d, head %2d, startsct %2d, nsects %2d", 
		     trk, hd, startsct, nsects);
#else
	  sprintf (s,  "%02d%% Complete                ",
                  ((unsigned long)(total*100) / (unsigned long)target));
#endif
	  write_text(26, 15, 6, s);

	  if ((result = ReadAbsSectors(drive,hd,trk,startsct,
				       nsects,t[0])) != 0)
	    {
	      write_error(emax_io_error(result));
	      return(result);
	    }

	  if ((result = write(fh,t[0],
			      (unsigned int)(nsects*SCTR_SIZE))) == -1)
	    {
	      write_error("Error writing to file.");
	      return(result);
	    }

	  total += nsects;

	}
      if (kbhit()) break;
    }
  return 0;
}

int WriteDiskRegion (int fh, int drive, int loblk, int hiblk)
{
  int lotrk, lohd, losct;
  int hitrk, hihd, hisct;
  int hd, trk;
  int result;
  char s[80];

  /* Work out track/head/sector numbers for the start of the region */

  lotrk = BlkToTrk (loblk);
  losct = BlkToSect (loblk);
  lohd  = BlkToHead (loblk);

  hitrk = BlkToTrk (hiblk);
  hisct = BlkToSect (hiblk);
  hihd  = BlkToHead (hiblk);

  /* Write the region.  Set the start sector and number of sectors
     according to where we are in the region */

  for (trk=lotrk; trk <= hitrk; trk++)
    {
      int starthd;
      int endhd;

      if (trk==lotrk)
	starthd = lohd;
      else
	starthd = 0;

      if (trk==hitrk)
	endhd = hihd;
      else
	endhd = HEADS-1;

      for (hd=starthd; hd<=endhd; hd++)
	{
	  int nsects;       /* How many sectors to read from this track */
	  int startsct;

	  if (kbhit()) break;

	  nsects=SCTR_TRK;
	  startsct=START_SCTR;

          if ((trk==lotrk) && (hd==lohd))
	    {
	      nsects = nsects - losct + START_SCTR;
	      startsct = losct;
	    }
	  else if ((trk==hitrk) && (hd==hihd))
	    nsects=nsects-SCTR_TRK+hisct;

#ifdef DEBUG
	  sprintf (s, "track %2d, head %2d, startsct %2d, nsects %2d", 
		     trk, hd, startsct, nsects);
#else
	  sprintf (s,  "%02d%% Complete                 ",
              ((unsigned long)(total*100) / (unsigned long)target));
#endif
	  write_text(26, 15, 6, s);

	  if ((result = read(fh,t[0],
			      (unsigned int)(nsects*SCTR_SIZE))) == -1)
	    {
	      write_error("Error writing to file.");
	      return(result);
	    }

	  if ((result = WriteAbsSectors(drive,hd,trk,startsct,
				       nsects,t[0])) != 0)
	    {
	      write_error(emax_io_error(result));
	      return(result);
	    }
	  total += nsects;

	}
      if (kbhit()) break;
    }
  return 0;
}

int ReadOS (int drive, char *fn)
{
  int result, fh;

  if ((fh = open(fn,O_CREAT|O_WRONLY|O_BINARY,
		    S_IREAD|S_IWRITE)) == -1)
  {
        write_error("Error opening file for write.");
        return(result);
  }

  write_text (26, 15, 6, "Starting read");

  cursor_off();

  total=0;
  target=TOTAL_OS;

  if (ReadDiskRegion (fh, drive, OS1_LOW, OS1_HIGH) == -1)
     return (-1);
  if (ReadDiskRegion (fh, drive, OS2_LOW, OS2_HIGH) == -1)
     return (-1);
  if (ReadDiskRegion (fh, drive, OS3_LOW, OS3_HIGH) == -1)
     return (-1);

  cursor_on();

  return close(fh);
}

int WriteOS (char *fn, int drive)
{
  int result, fh;

  if ((fh = open(fn,O_RDONLY|O_BINARY,S_IREAD|S_IWRITE)) == -1)
  {
        write_error("Error opening file for read.");
        return(result);
  }

  write_text (26, 15, 6, "Starting write");

  cursor_off();

  total=0;
  target=TOTAL_OS;

  if (WriteDiskRegion (fh, drive, OS1_LOW, OS1_HIGH) == -1)
      return (-1);
  if (WriteDiskRegion (fh, drive, OS2_LOW, OS2_HIGH) == -1)
      return (-1);
  if (WriteDiskRegion (fh, drive, OS3_LOW, OS3_HIGH) == -1)
      return (-1);

  cursor_on();

  return close(fh);
}

