/*
 * 5799-WZQ (C) COPYRIGHT IBM CORPORATION 1986,1987
 * LICENSED MATERIALS - PROPERTY OF IBM
 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
 */
/*=============================================================================
FDUTILS - Utility Procedures for FDISK Fixed Disk Partitioning Utility
David Berkowitz
Academic Information Systems (Kingston)
=============================================================================*/

/* $Header:fdutils.c 12.0$ */
/* $ACIS:fdutils.c 12.0$ */
/* $Source: /ibm/acis/usr/sys/standca/RCS/fdutils.c,v $ */

#ifndef lint
static char *rcsid = "$Header:fdutils.c 12.0$";
#endif

/*
 *  this table defines all known PC family operating systems and their ids
 */

struct system systems[NSYSTEMS+1] =
  {
    { "DOS       ", 0x01 },                       /*    DOS, 12-bit FAT      */
    { "XENIX root", 0x02 },                       /*    XENIX root (/)       */
    { "XENIX user", 0x03 },                       /*    XENIX user (/usr)    */
    { "DOS       ", 0x04 },                       /*    DOS, 16-bit FAT      */
    { "PC/IX     ", 0x75 },                       /*    PC/IX                */
    { "ACIS 4.3  ", 0xDB },                       /*    ACIS 4.3             */
    { "UNKNOWN   ", 0x00 },                       /*    Unknown system       */
  };

/*=============================================================================
DECODE
convert a partition table entry into presentable information
=============================================================================*/
decode()
{
struct brpt_entry *pentry;
struct partdata  *info;
int i;

for ( i=0; i<NP; i++)
  {
  pentry = &bootrecord[current_drive].t_entry[i];
  info	 = &partdata[current_drive][i];

  info->sysno	 = getsysno( pentry->sys_ind );
  info->bootable = (char) ( ( pentry->boot_ind == 0x80 ) ? TRUE : FALSE );
  info->start = pentry->start_cyl | ((((U16) pentry->start_sect)<<2 ) & 0x0300);
  info->startsect = pentry->start_sect & 0x3F;
  info->starthead = pentry->start_hd;
  info->end  = pentry->end_cyl	 | ((((U16) pentry->end_sect  )<<2 ) & 0x0300);
  info->endsect   = pentry->end_sect   & 0x3F;
  info->endhead   = pentry->end_hd;
  }
}

#ifdef DEBUG
/*=============================================================================
DUMPPARTS
dumps the contents of variable partitions (sorted pointers to partiton entries)
=============================================================================*/
dumpparts()  /* for current drive */
{
int j;

printf ( "\nvalid parts: %d \n", valid_parts[current_drive] );
printf ( "====%d====\n",current_drive );
for ( j=0; j<NP; j++ )
  printf ( "[%d]: %lx\n", j, partitions[current_drive][j] );
printf ( "====%d====\n",current_drive );
}
#endif DEBUG

/*=============================================================================
ENCODE
convert presentable information into a partition table entry
=============================================================================*/
encode()
{
struct partdata  *info;
struct brpt_entry *pentry;
int ntpc, nspc, shead, ehead, ssect, esect, i;
U16 start, end;
U32 temp;

for ( i=0; i<NP; i++)
  {
  info = partitions[current_drive][i];
  pentry = &bootrecord[current_drive].t_entry[i];

  if (info != NULL) /* real data to fill in */
    {
    ntpc  = pcdiskinfo[current_drive].ntpc;
    nspc  = ntpc * NSPT;
    start = info->start;
    end   = info->end;
    shead = info->starthead;
    ehead = info->endhead;
    ssect = info->startsect;
    esect = info->endsect;

    pentry->sys_ind  = systems[info->sysno].id;
    pentry->boot_ind = (info->bootable) ? 0x80 : 0;

    pentry->start_cyl  = (char) (start & 0x00FF);
    pentry->end_cyl    = (char) (end   & 0x00FF);

    pentry->start_sect = (char) ( (start & 0x0300) >>2 | ssect );
    pentry->end_sect   = (char) ( (end	 & 0x0300) >>2 | esect );

    pentry->start_hd   = shead;
    pentry->end_hd     = ehead;

    temp   = (U32) (end-start+1)*nspc + (shead-ehead-1+ntpc)*NSPT
		       + (ssect-esect-1+NSPT);
    pentry->num_sect   = wordswap(temp);

    temp   = (U32) start*nspc + shead*NSPT + ssect-1;
    pentry->rel_sect   = wordswap(temp);
    }
  else /* just zero out this entry */
    {
    pentry->sys_ind    = 0;
    pentry->boot_ind   = 0;
    pentry->start_cyl  = 0;
    pentry->end_cyl    = 0;
    pentry->start_sect = 0;
    pentry->end_sect   = 0;
    pentry->start_hd   = 0;
    pentry->end_hd     = 0;
    pentry->rel_sect   = 0;
    pentry->num_sect   = 0;
    }
  }
}

/*=============================================================================
GETSYSNO
convert a system identifier to a system number
=============================================================================*/
U16 getsysno(id)
char id;
{
int i;

for ( i=0; ( (i < NSYSTEMS) && (systems[i].id != id) ); i++ ) ;
return( (U16) i );
}

/*=============================================================================
PRINTHEADER
prints the header portion of each option screen
=============================================================================*/
printheader(string)
char *string;
{
printnewlines(9);
printf ( "%s\n\n", string );
printf ( "Current Fixed Disk Drive: %d \n\n", current_drive );
printf ( "Cylinders: %d ", pcdiskinfo[current_drive].ncpd );
printf ( "Heads: %d \n\n", pcdiskinfo[current_drive].ntpc );
}

/*=============================================================================
PRINTINFO
prints the partition information of the current drive
=============================================================================*/
printinfo()
{
int i = -1;

if ( valid_parts[current_drive] == 0 )
  printf ("No Partitions Defined \n");

else
  {
  printf ("Partition System      Active  Start  End    Length\n");

  for ( i=0; i<valid_parts[current_drive]; i++ )
    {
    printf("    %d     ",i);
    showinfo( partitions[current_drive][i] );
    }
  }

printnewlines (10-i);
}

/*=============================================================================
PRINTNEWLINES
=============================================================================*/
printnewlines(n)
int n;
{
while ( (n--) > 0 )
  printf ("\n");
}

/*=============================================================================
PRINTSYSTEMS
=============================================================================*/
printsystems()
{
int i;

printf( "Number System \n" );
for ( i=0; i<NSYSTEMS; i++ )
  printf( "  %d   %s \n", i, systems[i].name );
printf("\n");
}

/*=============================================================================
SHOWENTRY
print one partition table entry
=============================================================================*/
showentry(num)
int num;
{
struct brpt_entry *pentry = &bootrecord[current_drive].t_entry[num];
printf ( "%-9d "  , num );
printf ( "%-6x "  , pentry->sys_ind );
printf ( "%-6x "  , pentry->boot_ind );
printf ( "%-8d "  , pentry->start_cyl );
printf ( "%-6d "  , pentry->start_sect );
printf ( "%-4d "  , pentry->start_hd );
printf ( "%-8d "  , pentry->end_cyl );
printf ( "%-6d "  , pentry->end_sect );
printf ( "%-4d "  , pentry->end_hd );
/*
printf ( "%-5ld " , pentry->rel_sect );
printf ( "%-6ld\n", pentry->num_sect );
*/
printf ( "%-5ld " , wordswap(pentry->rel_sect) );
printf ( "%-6ld\n", wordswap(pentry->num_sect) );
}

/*=============================================================================
SHOWINFO
print the partition information
=============================================================================*/
showinfo(info)
struct partdata *info;
{
printf ("%s  ",      systems[info->sysno].name);
printf ("   %s    ", YorN(info->bootable));
printf ("%-6d ",     info->start);
printf ("%-6d ",     info->end);
printf ("%-6d \n", (info->end) ? info->end - info->start + 1 : 0  );
}

/*=============================================================================
SHOWTABLE
print the partition table
=============================================================================*/
showtable()
{
int i;

printf ("\nPartition System Active Cylinder Sector Head ");
printf ("Cylinder Sector Head Start Length\n");

for ( i=0; i<NP; i++ )
  showentry(i);

printf("\n");
}

/*=============================================================================
WAITFORESC
absorbs keystrokes and beeps until the "Escape" key is pressed
=============================================================================*/
waitforesc()
{
printf("Press Esc to return to FDISK Options");

while ( getchar() != ESCAPE )
  beep();
}

