
/*--------------------------------------------------------------------*/
/* modelo de memoria: SMALL                                           */
/*--------------------------------------------------------------------*/
/* Llamada        : PARTI [ N§ de unidad ]                         */
/*                  Ajuste por defecto es unidad 0 ("C")              */
/**********************************************************************/

#include <dos.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

/*== Constantes ======================================================*/

#define TRUE  ( 1 == 1 )
#define FALSE ( 1 == 0 )

/*== Macros ==========================================================*/

#define HI(x) ( *((BYTE *) (&x)+1) )    /*devuelve byte alto de un WORD*/
#define LO(x) ( *((BYTE *) &x) )        /*devuelve byte bajo de un WORD*/

/*== Declaraci¢n de tipos ============================================*/

typedef unsigned char BYTE;
typedef unsigned int WORD;

typedef struct {                   /*describe la posici¢n de un sector*/
					 BYTE Head;              /*cabezal de lectura/escritura*/
					 WORD SecZyl;                 /*n§ de sector y cilindro*/
					} SECPOS;

typedef struct {                  /*entrada en la tabla de particiones*/
					 BYTE          Status;            /*estado de partici¢n*/
					 SECPOS        StartSec;                /*primer sector*/
					 BYTE          PartTyp;             /*tipo de partici¢n*/
					 SECPOS        EndSec;                  /*£ltimo sector*/
					 unsigned long SecOfs;      /*offset del sector de arr.*/
					 unsigned long SecAnz;                 /*n§ de sectores*/
					} PARTENTRY;

typedef struct {                         /*describe el sector de part.*/
					 BYTE      BootCode[ ???? ];
					 PARTENTRY PartTable[ 4 ];
					 WORD      IdCode;                             /*0xAA55*/
					} PARTSEC;

typedef PARTSEC far *PARSPTR; /*puntero al sector de partici¢n en mem.*/

/**********************************************************************/
/* LeerPartSec : Lee un sector de partici¢n del disco duro a          */
/*               un buffer                                            */
/* Entrada: - Unidad : C¢digo BIOS de la unidad (0x80, 0x81 etc.)     */
/*          - Head   : N£mero del cabezal de lectura/escritura        */
/*          - SekZyl : N§ de sector y cilindro en formato BIOS        */
/*          - Buf    : buffer, en el que se carga el primer sector    */
/* Salida : TRUE, si se pudo leer el sector sin problemas             */
/*          sino FALSE                                                */
/**********************************************************************/

BYTE LeerPartSec( BYTE LaUnidad, BYTE Head, WORD SekZyl, PARSPTR Buf )

{
 union REGS   Regs;    /*reg. de procesador para la llamada de interr.*/
 struct SREGS SRegs;

 Regs.x.ax = ???????;                /*N§ fun.c para "Read", 1er sector*/
 Regs.h.dl = ???????;                              /*cargar los otros*/
 Regs.h.dh = ???????;                                  /*a los diferentes*/
 Regs.x.cx = ???????;                                       /*registros*/
 Regs.x.bx = FP_OFF( Buf );
 SRegs.es  = FP_SEG( Buf );

 int86x( ?, ?, ?, ? );     /*llamar int. de disco duro*/
 return !Regs.x.cflag;
}

/**********************************************************************/
/* GetSecZyl: obtiene de la codificaci¢n combinada de sector/cilindro */
/*            de la BIOS el n§ de sector y cilindro                   */
/* Entrada: -SekZyl   : el valor a decodificar                        */
/*          -Sector   : referencia a la variable de sector            */
/*          -Cylinder : referencia a la variable del cilindro         */
/* Salida : ninguna                                                   */
/**********************************************************************/

void GetSecZyl( WORD SekZyl, int *Sector, int *Cylinder )

{
 *Sector   = SekZyl & 63;                          /*apagar bits 6 y 7*/
 *Cylinder = HI(SekZyl) + ( ( (WORD) LO(SekZyl) & 192 ) << 2 );
}

/**********************************************************************/
/* MostrarParticion: muestra las particiones de un disco duro            */
/*                en la pantalla                                      */
/* Entrada: LW : N£mero de la unidad de disco duro direccionada       */
/*               (0, 1, 2 etc.)                                       */
/* Salida : ninguna                                                   */
/**********************************************************************/

void MostrarParticion( BYTE LW )
{
 #define AP ( ParSec.PartTable[ Entry ] )

 BYTE       Head,                     /*cabezal de la partici¢n actual*/
	    Entry;                                 /*contador de bucle*/
	    
 int        Sector,                            /*acogen n§ de sector y*/
	   Cylinder;                                       /*cilindro*/
 
 PARTSEC    ParSec;                    /*el sector de partici¢n actual*/
 
 union REGS Regs;      /*reg. de procesador para la llamada de interr.*/

 printf("\n");
 
 LW = LW | 0x80;                      /*preparar n§ de unidad para la BIOS*/
 
 if ( LeerPartSec( LW, 0, 1, &ParSec ) )    /*leer sector de partici¢n*/
  {                                              /*sector se pudo leer*/
	Regs.h.ah = 8;                         /*obtener datos de la unidad*/
	Regs.h.dl = LW;
	int86( 0x13, &Regs, &Regs );            /*llamar int. de disco duro*/
	
	
	GetSecZyl( Regs.x.cx, &Sector, &Cylinder );
	printf( "ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ"
			  "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\n");
	
	printf( "º Unidad   %2d:    %2d Cabezales con %4d"
			  " Cilindros a %3d Sectores          º\n",
			  LW-0x80, Regs.h.dh+1, Cylinder, Sector );
	
	
	printf( "º Tabla de part. en el sector de partici¢n  "
			  "                              º\n");
	
	printf( "ÌÍÍÑÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍÍÑ"
			  "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍ¹\n");
	
	printf( "º  ³    ³                   ³     Inicio   ³"
			  "    Final     ³Distanc³       º\n");
	printf( "ºNr³Boot³Tipo               ³Cbzl Cil. Sec.³"
			  "Cbzl Cil. Sec.³SecArrq³N£mero º\n");
	printf( "ÌÍÍØÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÍØ"
			  "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍØÍÍÍÍÍÍÍ¹\n");

	/*-- recorrer la tabla de particiones -----------------------------*/
	
	
	for ( Entry=0; Entry < 4; ++Entry )
	 {
	  printf( "º %d³", Entry );
	  if ( AP.Status == 0x80 )                      /*partici¢n activa?*/
		printf(" S¡ ");
	  else
		printf (" No ");
	  printf("³");
	  switch( AP.PartTyp )                  /*evaluar tipo de partici¢n*/
		{
			???								ParSec.PartTable[ Entry ].PartTyp );
		}

	  /*-- evaluar datos f¡sicos y l¢gicos ----------------------------*/
	  GetSecZyl( AP.StartSec.SecZyl, &Sector, &Cylinder );
	  printf( "³%2d %5d  %3d ", AP.StartSec.Head, Cylinder, Sector );
	  GetSecZyl( AP.EndSec.SecZyl, &Sector, &Cylinder );
	  printf( "³%2d %5d  %3d ", AP.EndSec.Head, Cylinder, Sector );
	  printf( "³%6lu ³%6lu º\n", AP.SecOfs, AP.SecAnz );
	 }
	printf( "ÈÍÍÏÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÏ"
			  "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍ¼\n" );
  }
 else
  printf("­Error al acceder al sector de arranque!\n");
}

/**********************************************************************/
/*                 P R O G A M A   P R I N C I P A L                  */
/**********************************************************************/

int main( int argc, char *argv[] )
{
 int LaUnidad;

 printf( "\nPráctica 6 - Periféricos Avanzados.\n" );

 LaUnidad = 0;                        /*defecto en el primer disco duro*/
 
 if ( argc == 2 )                                      /*¨otra unidad?*/
  {                                                               /*Si*/
	LaUnidad = atoi ( argv[1] );
	if ( LaUnidad == 0 && *argv[1] != '0' )
	 {
	  printf("\nN£mero de unidad no v lido!");
	  return( 1 );                                        /*el programa*/
	 }
  }
 MostrarParticion( (BYTE) LaUnidad );       /*mostrar sector de partici¢n*/
 return( 0 );
}
