Metropoli BBS
VIEWER: 2m-fdtr.c MODE: TEXT (CP437)
/*********************************************************************
*                                                                    *
*  2M-FDTR 2.1  -  Cálculo de la tasa de transferencia de disquetes. *
*                       (C) 1994 Ciriaco García de Celis.            *
*                                                                    *
*    Para Borland C++ 2.0 ó superior en modelo de memoria large.     *
*                                                                    *
*********************************************************************/


#define  SMAX  23*512L   /* máximo soportado: 63 sectores por pista */
#define  RD    2
#define  WR    3


#include <dos.h>
#include <alloc.h>
#include <math.h>
#include <string.h>


int   	 evalua_io(), biosdsk(), HablaSp();
void  	 ayuda();
unsigned long tiempo();

int    sp;                    /* 1-español 0-inglés */


void main (int argc, char **argv)
{
  unsigned char sector0[512], far *buf;
  unsigned long dir;
  int      unidad, cilindros, sectores, cabezales;
  struct   dfree dsk;

  sp=HablaSp();  /* determinar idioma del país */

  if ((!strcmp(strupr(argv[1]),"/I")) || (!strcmp(strupr(argv[2]),"/I")))
    sp^=1;  /* parámetro /I */

  printf("\n 2M-FDTR 2.1\n");

  unidad=(*argv[1] | 0x20)-'a';

  if ((argc<2) || ((unidad!=0) && (unidad!=1))) ayuda();

  getdfree (unidad+1, &dsk);

  if (dsk.df_sclus==65535) {
    if (sp)
        printf("   ■ Error de acceso a la unidad.\n");
      else
        printf("   ■ Error on drive access.\n");
    exit (3);
    }

  if ((long) dsk.df_total*dsk.df_sclus>65535L) {
    if (sp)
        printf("   ■ Unidades de más de 32M no soportadas.\n");
      else
        printf("   ■ Drive above 32M can not be tested.\n");
    exit (1);
    }

  if ((buf=farmalloc (SMAX << 1))==NULL) {
    if (sp)
        printf("   ■ ¡Memoria insuficiente!.\n");
      else
        printf("   ■ Insufficient memory!.\n");
    exit (2);
    }

  dir = ((unsigned long) FP_SEG(buf) <<4) + FP_OFF(buf);
  if ((dir>>16)!=((dir+SMAX)>>16)) buf+=SMAX;  /* por el DMA */

  if (biosdsk (2, unidad, 0, 0, 1, 1, sector0)) {
    printf("   ■ Fatal ????.\n");
    exit (4);
    }

  sectores=sector0[24]+256*sector0[25]; cabezales=sector0[26];
  cilindros=(sector0[19]+256*sector0[20])/sectores/cabezales;

  if (sectores>63) {
    if (sp)
        printf("   ■ ¡No soportados más de 63 sectores por pista!.\n");
      else
        printf("   ■ Not supported more than 63 sectors per track!.\n");
    exit (3);
    }

  if (sp) {
      printf(" ■ Determinando tasa de transferencia BIOS a disco.\n");
      printf("   + Rendimiento en lectura:\n");
      }
    else {
      printf(" ■ Computing BIOS floppy data transfer rate.\n");
      printf("   + Read performance:\n");
      }

  if (evalua_io (RD, buf, unidad, cilindros, sectores, cabezales)) {
    if (dsk.df_avail < dsk.df_total) {
      if (sp)
          printf("   + Disquete no vacío -> test de escritura omitido.\n");
        else
          printf("   + Diskette not empty -> write test skipped.\n");
      exit (4);
      }
    if (sp)
        printf("   + Rendimiento en escritura:\n");
      else
        printf("   + Write performance:\n");
    evalua_io (WR, buf, unidad, cilindros, sectores, cabezales);
    }
}


void ayuda()
{
  printf(" (C) 1994 Ciriaco García de Celis.\n");
  if (sp) {
      printf("     ■ Indica la unidad A: o B: para medir su velocidad.\n");
      printf("       - El test se realiza accediendo a través de las funciones BIOS.\n");
      printf("       - El buffer E/S no cruza nunca una frontera de DMA de 64K.\n");
      printf("       - El acceso afecta siempre a pistas completas.\n");
      printf("       - El software residente puede alterar el resultado.\n");
      printf("       - El test de escritura no se realiza si el disquete contiene datos.\n");
      }
    else {
      printf("     ■ Choose drive A: or B: to test it absolute speed.\n");
      printf("       - Test is performed always through BIOS functions.\n");
      printf("       - The I/O buffer never cross a 64K DMA frontier.\n");
      printf("       - Access is done always using the whole track.\n");
      printf("       - The TSR software may alter results.\n");
      printf("       - Write test is not performed if diskette contains data.\n");
      }
  exit (255);
}


unsigned long tiempo()
{
  unsigned long tm;

  asm {
    cli
    mov  al,6
    out  43h,al        /* enclavamiento contador 0 */
    in   al,40h
    mov  ah,al
    in   al,40h
    xchg ah,al
    neg  ax            /* ax = valor del contador 0 del 8254 */
    push ds
    mov  bx,40h
    mov  ds,bx
    mov  bx,ds:[6ch]   /* bx = contador hora BIOS */
    sti
    pop  ds
    mov  word ptr tm,ax
    mov  word ptr tm+2,bx
    }
  return (tm);
}


int biosdsk (int cmd, int drive, int head, int track, int sector,
             int nsects, void *buffer)
{
  union REGS r; struct SREGS s;

  r.h.ah=cmd; r.h.dl=drive; r.h.dh=head; r.h.ch=track; r.h.cl=sector;
  r.h.al=nsects; s.es=FP_SEG(buffer); r.x.bx=FP_OFF(buffer);

  int86x (0x13, &r, &r, &s);
  return (r.h.ah);
}


int evalua_io (operacion, buffer, unidad, cilindros, nsect, cabezales)
int operacion, unidad, cilindros, nsect, cabezales;
unsigned char far *buffer;
{
  int      cilindro, cabezal, fin_io=0, res;
  unsigned long tini, tfin;
  float	   bseg;

  /* Leer parte del cilindro 1 para colocar el cabezal al inicio. */
  /* Se leen dos sectores alejados para esquivar la caché de 2M y */
  /* forzar un auténtico posicionamiento en este cilindro         */

  outportb (0x43, 0x36);  /* asegurar que cnt0 usa byte bajo-alto */
  outportb (0x40, 0); outportb (0x40, 0);

  biosdsk (2, unidad, 0, 1, 1, 1, buffer);     /* anular caché 2M */
  biosdsk (2, unidad, 0, 1, nsect-2, 1, buffer);   /* sincronizar */

  tini=tiempo(); res=0;
  for (cilindro=1; cilindro<cilindros; cilindro++)
    for (cabezal=0; cabezal<cabezales; cabezal++) {
    if (kbhit()) if (getch()==27) goto aborta_io;
    if (res) {
      if (sp)
          printf("\r     ¡Fallo en el acceso a disco!.\n");
        else
          printf("\r     Failure on disk access!.\n");
      goto aborta_io;
      }
    if (sp)
        printf("\r\r       Cilindro %2d - Cara %d", cilindro, cabezal);
      else
        printf("\r\r       Cylinder %2d - Side %d", cilindro, cabezal);
    res=biosdsk (operacion, unidad, cabezal, cilindro, 1, nsect, buffer);
    }
  tfin=tiempo(); fin_io=1;

  bseg=(512L*nsect*(cilindros-1)*cabezales)/((tfin-tini)/1193180.0);
  if (sp)
      printf("\r     %7.2f segundos =%7.2f Kb/seg [%7.0f bits/seg]\n",
	(tfin-tini)/1193180.0, bseg/1024.0, bseg*8);
    else
      printf("\r     %7.2f seconds =%7.2f Kb/sec [%7.0f bits/sec]\n",
	(tfin-tini)/1193180.0, bseg/1024.0, bseg*8);
  aborta_io:
  printf("\r                                              \r");
  return (fin_io);
}


int HablaSp()        /* devolver 1 si mensajes en castellano */
{
  union REGS r; struct SREGS s;
  char info[64];
  int i, idioma, spl[]={54, 591, 57, 506, 56, 593, 503, 34, 63, 502,
             504, 212, 52, 505, 507, 595, 51, 80, 508, 598, 58, 3, 0};

  idioma=0;  /* supuesto el inglés */

  if (_osmajor>=3) {
    r.x.ax=0x3800; s.ds=FP_SEG(info); r.x.dx=FP_OFF(info);
    intdosx (&r, &r, &s);
    i=0; while (spl[i++]) if (spl[i-1]==r.x.bx) idioma=1;
    }
  return (idioma);
}
[ RETURN TO DIRECTORY ]