home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 1995 November
/
PCWK1195.iso
/
inne
/
podstawy
/
dos
/
format
/
2m30src.exe
/
2M-IN765.C
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-06
|
71KB
|
1,891 lines
/*───────────────────────────────────────────────────────────────────\
│ │
│ 765DEBUG 4.0 - Módulo avanzado de análisis de disquetes. │
│ │
│ (C) 1992-1995 Ciriaco García de Celis │
│ │
\───────────────────────────────────────────────────────────────────*/
#include <alloc.h>
#include <conio.h>
#include <dos.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <bios.h>
#include "2m-info.h"
#define SMAX 32768L /* mayor sector soportado por el programa */
#define CX 12 /* color para pantalla de "memoria insuficiente" */
#define CFX 0 /* color de fondo para "memoria insuficiente" */
#define C765 1 /* color de '765DEBUG' */
#define CM 15 /* color para el menú principal */
#define CFM 3 /* color de fondo para el menú principal */
#define C3D 10 /* color para el marco 3D */
#define CB 2 /* color para la banda de fondo del marco 3D */
#define CTIT 14 /* color del título superior */
#define CVER 4 /* color de la versión */
#define CB1 5 /* color 1 para botones del menú principal */
#define CB2 7 /* color 2 para botones del menú principal */
#define CTB1 15 /* color 1 para tinta de botones del menú principal */
#define CTB2 0 /* color 2 para tinta de botones del menú principal */
#define CI 1 /* color para informe en menú principal */
#define CMI 11 /* color para el marco del informe en menú principal */
#define CS 15 /* color para confirmar salida */
#define CFS 6 /* color de fondo para confirmar salida */
#define CD 15 /* color para advertencia del tamaño buffer DMA */
#define CFD 6 /* color de fondo advertencia tamaño buffer DMA */
#define CR 15 /* color para "ayuda" */
#define CDR 14 /* color para dirección en "ayuda" */
#define CFR 5 /* color de fondo para "ayuda" */
#define CL 15 /* color para LeerSector */
#define CFL 4 /* color de fondo para LeerSector */
#define CE 15 /* color para EscribirSector */
#define CFE 4 /* color de fondo para EscribirSector */
#define CF 15 /* color para FormatearPista */
#define CFF 5 /* color de fondo para FormatearPista */
#define CIW 15 /* color para 'Leyendo ID's...' */
#define CFIW 4 /* color de fondo para 'Leyendo ID's...' */
#define CFI 0 /* color de fondo para lectura de ID's */
#define CIC 14 /* color cabecera de lectura ID's */
#define CFIC 4 /* color de fondo cabecera de lectura ID's */
#define CIMS 15 /* color para milisegundos en lectura ID's */
#define CIS 12 /* color para sector en lectura ID's */
#define CIT 10 /* color para tamaños en lectura ID's */
#define CICC 14 /* color para cilindro/cabezal en lectura ID's */
#define CIST 13 /* color para registros STx en lectura ID's */
#define CIB 9 /* color para mensaje barra en lectura ID's */
#define CRS 15 /* color para resultados R/W/F */
#define CFRS 5 /* color de fondo para resultados R/W/F */
#define CFV 0 /* color de fondo para ver buffer */
#define CFVM 1 /* color de fondo del menu de ver buffer */
#define CVMM 11 /* color del marco del menu de ver buffer */
#define CVMI 11 /* color de la información del menu de ver buffer */
#define CVMS 15 /* color de la ayuda para salir del menu de ver buffer */
#define CVMD 14 /* color de la información del menu de ver buffer */
#define CVD 10 /* color para direcciones en menú de ver buffer */
#define CVH 11 /* color para datos hexadecimales en menú de ver buffer */
#define CVS 6 /* color para guión separador en menú de ver buffer */
#define CVA 12 /* color para datos ASCII en menú de ver buffer */
#define CVNS 15 /* color para pedir nueva sección en ver buffer */
#define CFVNS 4 /* color de fondo para pedir nueva sección en ver buffer */
#define CVNB 15 /* color para pedir nueva tamaño en ver buffer */
#define CFVNB 5 /* color de fondo para pedir nuevo tamaño en ver buffer */
#define CVMB 15 /* color para modificar en ver buffer */
#define CFVMB 1 /* color de fondo para modificar en ver buffer */
#define C2M 15 /* color para información de disco 2M */
#define CF2M 6 /* color de fondo para información de disco 2M */
extern void CursorOff (void);
extern void BrilloOn (void);
extern void ventana (int, int, int, int, int, int, int);
extern int Tecla (void);
extern void EsperaDma0 (int);
extern int es386 (void);
extern unsigned rnd (unsigned);
extern int input (char *, int, int, int, int);
extern int TipoDrive (int);
extern int Hay2M3 (void);
extern int EsOS2 (void);
extern int sp;
extern void v3dg (int, int, int, int, int, int, int, int, int);
extern void v3d (int, int, int, int, int);
extern void v3df (int, int, int, int, int, int, int, int);
extern void boton (int, int, int, int, int, int, char *);
extern char *dec2str (unsigned);
extern char *dec3str (unsigned);
extern char *dec5str (unsigned);
extern char *dec2strq (unsigned);
extern char *dec3strq (unsigned);
extern char *dec5strq (unsigned);
int infdc (void),
PeligrosoOS2 (void),
SalirConfirmado (void),
EditarTablaFmt (unsigned char *, int),
hextoi (char *);
unsigned long VDMA (unsigned *);
void TestDMA (void),
DibujaOpciones (void),
DibujaValores (int, int, int, int, int),
Informe2M (int, int *, int *, int),
SeleccionarUnidad (int, int),
ResetUnidad (int),
DensidadSpecify (int),
recalibrar (int, int, int, int),
posicionar (int, int, int, int),
LeerSector (int, int, int, int, char huge *, unsigned *, int),
EscribirSector (int, int, int, int, int, char huge *),
FormatearPista (int, int, int, int, int, int),
LeerIds (int, int, int, int),
Resultados (int, int, int),
MostrarBuffer (char huge *, unsigned *),
MotorOn (int),
MotorOff (void),
outfdc (unsigned char),
EsperarInt (void),
PreparaDma (unsigned, unsigned, char huge *);
char *hex2str (int),
*ReservarMemoria (char huge **);
void debug765()
{
char huge *buffer, /* buffer para sector */
huge *bloque,
cad[32];
int unidad=0, vunidad[2],
mf_mfm[2], cabezal[2],
cilindro[2], opc, t, opcion, refrescar,
PrimeraVez=1, discos=1, SalirEnOS2=0;
unsigned bytes=0;
mf_mfm[0]=mf_mfm[1]=1; vunidad[0]=vunidad[1]=0;
cabezal[0]=cabezal[1]=cilindro[0]=cilindro[1]=0;
t=TipoDrive(1); /* -1 si falla */
if (t==-1) t=peekb(0x40, 0x10) >> 6; /* nº unidades-1 */
if (t) discos++; /* nº unidades disquete */
if ((bloque=ReservarMemoria (&buffer))!=NULL) {
opcion=0; refrescar=1;
do {
BrilloOn();
if (refrescar) {
DibujaOpciones();
refrescar=0;
}
if (PrimeraVez) { /* recalibrar unidades al */
PrimeraVez=0; /* entrar en el programa */
SalirEnOS2=PeligrosoOS2();
if (SalirEnOS2) {
opcion=SALIR;
break;
}
TestDMA();
recalibrar (0, 0, 0, 0);
if (discos>1)
recalibrar (1, 0, 0, 0);
SeleccionarUnidad (unidad, vunidad[unidad]); /* por defecto */
}
DibujaValores (unidad, vunidad[unidad], mf_mfm[unidad],
cilindro[unidad], cabezal[unidad]);
CursorOff(); opc=getch();
if (!opc) opc=getch() << 8; /* usar Tecla() borraría el buffer */
switch (opc) {
case '0': recalibrar (0, cabezal[0], vunidad[0], 1);
if (discos>1)
recalibrar (1, cabezal[1], vunidad[1], 1);
cilindro[0]=cilindro[1]=0;
SeleccionarUnidad (unidad, vunidad[unidad]);
break;
case '1': unidad ^= 1;
SeleccionarUnidad (unidad, vunidad[unidad]);
break;
case '2': vunidad[unidad]++;
if (vunidad[unidad]>3) vunidad[unidad]=0;
DensidadSpecify (vunidad[unidad]);
break;
case '3': gotoxy (64, 19);
strcpy (cad, dec2strq (cilindro[unidad]));
if (input (cad, 1, 2, CI, CFM)) {
cilindro[unidad] = atoi (cad);
posicionar (unidad, cabezal[unidad], cilindro[unidad],
vunidad[unidad]);
}
break;
case '4': cabezal[unidad]^=1;
break;
case '5': LeerIds (unidad, mf_mfm[unidad], cabezal[unidad],
vunidad[unidad]);
refrescar=1;
break;
case '6': LeerSector (unidad, mf_mfm[unidad], cilindro[unidad],
cabezal[unidad], buffer, &bytes,
vunidad[unidad]);
break;
case '7': EscribirSector (unidad, mf_mfm[unidad], vunidad[unidad],
cilindro[unidad], cabezal[unidad], buffer);
break;
case '8': MostrarBuffer (buffer, &bytes);
refrescar=1;
break;
case '9': FormatearPista (unidad, mf_mfm[unidad], vunidad[unidad],
cilindro[unidad], cabezal[unidad], vunidad[unidad]);
break;
case 'a':
case 'A': mf_mfm[unidad]^=1; break;
case 'i':
case 'I': Informe2M (unidad, &cilindro[unidad], &cabezal[unidad],
vunidad[unidad]);
break;
case 0x1B: if (SalirConfirmado()) opcion=SALIR; break; /* ESC */
case 0x2D00: opcion=SALIR; break; /* ALT-X */
case 0x3B00: ventana (ABRIR, 3, 3, 77, 22, CR, CFR); /* F1 */
if (sp) {
gotoxy ( 2, 1); cputs(" El acceso directo a la controladora puede dejar ésta en situación no");
gotoxy ( 2, 2); cputs("estable en caso de error (por ejemplo, abortando una lectura de ID's");
gotoxy ( 2, 3); cputs("que falla). En ese caso las demás órdenes podrían fallar inicialmente.");
gotoxy ( 2, 4); cputs("Si es preciso, ejecute un reset y recalibre las unidades (opción 0).");
gotoxy ( 2, 6); cputs(" No se limitan, intencionadamente, algunas acciones aparentemente");
gotoxy ( 2, 7); cputs("ilógicas por parte del usuario, con objeto de lograr una herramienta de");
gotoxy ( 2, 8); cputs("mayor potencia. En general, pulsando INTRO cuando no se sabe qué hacer,");
gotoxy ( 2, 9); cputs("en la mayoría de las ocasiones las decisiones se toman automáticamente.");
gotoxy ( 2,11); cputs(" Si durante las operaciones con un disco de prueba se baja la línea de");
gotoxy ( 2,12); cputs("cambio, la BIOS podría no detectar luego el soporte. Si tiene problemas");
gotoxy ( 2,13); cputs("con dicho disquete al salir al DOS, sáquelo y vuelva a introducirlo.");
textcolor (CDR);
gotoxy (21,15); cputs ("¿Usuario *REGISTRADO* con problemas?");
gotoxy (22,16); cputs ("Mi buzón de correo electrónico es:");
}
else {
gotoxy ( 2, 1); cputs(" Direct access to diskette drive controller can leave it in undefined");
gotoxy ( 2, 2); cputs("state if an error occurs (for example, after aborting a failed Read IDs");
gotoxy ( 2, 3); cputs("command). In these cases, next functions can initially fail. If needed,");
gotoxy ( 2, 4); cputs("you can reset and recalibrate drives (option 0).");
gotoxy ( 2, 6); cputs(" Some apparently incorrect actions performed by the user are not");
gotoxy ( 2, 7); cputs("intentionally skipped, in order to increase the power of this program.");
gotoxy ( 2, 8); cputs("Generally, pressing ENTER key when you don't know what to do, in most");
gotoxy ( 2, 9); cputs("cases most decisions are automatically adopted by the program.");
gotoxy ( 2,11); cputs(" If during some diskette operations the disk change line is reset, the");
gotoxy ( 2,12); cputs("system BIOS may not detect disk media in future. If you have problems");
gotoxy ( 2,13); cputs("with such disk after exit to DOS, extract and then insert it again.");
textcolor (CDR);
gotoxy (21,15); cputs ("A *REGISTERED* user with problems?");
gotoxy (24,16); cputs ("My electronic mailboxes are:");
}
gotoxy (26,17); cputs ("Internet ciri@gui.uva.es");
gotoxy (26,18); cputs ("Fidonet 2:341/21.8");
CursorOff();
Tecla();
ventana (CERRAR, 3, 3, 77, 22, 0, 0);
break;
}
} while (opcion!=SALIR);
}
if ((!SalirEnOS2) && (bloque!=NULL)) {
pokeb (0x40, 0x94, cilindro[0]);
pokeb (0x40, 0x95, cilindro[1]);
outportb (FD_DCR, peekb(0x40, 0x8B) >> 6); /* velocidad normal */
}
if (bloque!=NULL) farfree ((char far *) bloque);
clrscr();
}
char *ReservarMemoria (char huge **buffer)
{
unsigned long dir;
char *bloque, *bf;
*buffer=bloque=farmalloc(SMAX << 1);
bf=farmalloc(4096L);
if ((*buffer==NULL) || (bf==NULL)) {
if (*buffer!=NULL) farfree ((char far *) *buffer);
textbackground (CFX); textcolor (CX); clrscr();
gotoxy (24,12);
if (sp)
cputs ("Memoria insuficiente para 765DEBUG");
else
cputs ("Insufficient memory for 765DEBUG");
CursorOff();
delay (2000);
return (NULL);
}
farfree (bf); /* liberar bloque "de seguridad" */
dir = ((unsigned long) FP_SEG(*buffer) <<4) + FP_OFF(*buffer);
if ( (dir>>16) != ( (dir+SMAX) >> 16) )
*buffer+=SMAX; /* evitar buffer entre dos páginas de DMA */
return (bloque);
}
void DibujaOpciones()
{
textbackground (CFM); textcolor(CM); clrscr();
v3dg (3, 2, 76, 12, 1, 2, C3D, CFM, CB);
v3d (3, 2, 76, 12, 2);
textcolor (C765); gotoxy (2,1); cputs("█▀▀▀█ █▀▀██ █▀▀▀▀ █ █ "); textcolor(CVER); cputs(" ▄ ▄ ▄▄▄▄▄");
textcolor (C765); gotoxy (2,2); cputs(" █ █ █ █ █ ▄▄▄▄▄─┼─"); textcolor(CVER); cputs(" █ █ █ █");
textcolor (C765); gotoxy (2,3); cputs(" ██ █▀▀██ ▀▀▀██ █▀▀▀█ █▀▀▀█ █▀▀▀█ █ █ █ █ "); textcolor(CVER); cputs(" █▄▄▄█▄ █ ▄█");
textcolor (C765); gotoxy (2,4); cputs(" ██ █ ██ ██ █ █ █▀▀▀▀ █ █ █ █ █ █ "); textcolor(CVER); cputs(" ██ █ ██");
textcolor (C765); gotoxy (2,5); cputs(" ▀▀ ▀▀▀▀▀ ▀▀▀▀▀ ▀▀▀▀▀ ▀▀▀▀▀ ▀▀▀▀▀ ▀▀▀▀▀ ▀▀▀▀█ "); textcolor(CVER); cputs(" ▀▀ ▀ ▀▀▀▀▀");
textcolor (C765); gotoxy (2,6); cputs(" █▄█ ");
gotoxy (2,6); textcolor (CTIT);
if (sp)
cputs("ANALISIS AVANZADO A BAJO NIVEL DE DISQUETES");
else
cputs(" ADVANCED LOW LEVEL DISK ANALYSIS UTILITY");
window (1,1,80,25);
if (sp) {
boton ( 3,15,CB1,CTB1,CM,CFM," 0 "); cputs (" Recalibrar unidades + reset.");
boton ( 3,16,CB2,CTB2,CM,CFM," 1 "); cputs (" Seleccionar unidad.");
boton ( 3,17,CB1,CTB1,CM,CFM," 2 "); cputs (" Seleccionar densidad + enviar specify.");
boton ( 3,18,CB2,CTB2,CM,CFM," 3 "); cputs (" Posicionar cabezal.");
boton ( 3,19,CB1,CTB1,CM,CFM," 4 "); cputs (" Cambiar de cabezal.");
boton ( 3,20,CB2,CTB2,CM,CFM," 5 "); cputs (" Leer ID's.");
boton ( 3,21,CB1,CTB1,CM,CFM," 6 "); cputs (" Leer sector al buffer interno.");
boton ( 3,22,CB2,CTB2,CM,CFM," 7 "); cputs (" Escribir sector del buffer interno.");
boton ( 3,23,CB1,CTB1,CM,CFM," 8 "); cputs (" Ver o editar sector del buffer interno.");
boton ( 3,24,CB2,CTB2,CM,CFM," 9 "); cputs (" Formatear pista.");
boton (51,22,CB1,CTB1,CM,CFM," A "); cputs (" Conmutar MF/MFM.");
boton (51,23,CB2,CTB2,CM,CFM," I "); cputs (" Información disco 2M.");
boton (51,24,CB1,CTB1,CM,CFM,"ESC"); cputs (" Salir (ALT-X rápido).");
}
else {
boton ( 3,15,CB1,CTB1,CM,CFM," 0 "); cputs (" Recalibrate drives & reset.");
boton ( 3,16,CB2,CTB2,CM,CFM," 1 "); cputs (" Select drive.");
boton ( 3,17,CB1,CTB1,CM,CFM," 2 "); cputs (" Select density & send specify.");
boton ( 3,18,CB2,CTB2,CM,CFM," 3 "); cputs (" Seek to new track.");
boton ( 3,19,CB1,CTB1,CM,CFM," 4 "); cputs (" Select other head.");
boton ( 3,20,CB2,CTB2,CM,CFM," 5 "); cputs (" Read ID's.");
boton ( 3,21,CB1,CTB1,CM,CFM," 6 "); cputs (" Read sector into internal buffer.");
boton ( 3,22,CB2,CTB2,CM,CFM," 7 "); cputs (" Write internal's buffer sector.");
boton ( 3,23,CB1,CTB1,CM,CFM," 8 "); cputs (" View or edit internal's buffer sector.");
boton ( 3,24,CB2,CTB2,CM,CFM," 9 "); cputs (" Format track.");
boton (51,22,CB1,CTB1,CM,CFM," A "); cputs (" Change MF/MFM.");
boton (51,23,CB2,CTB2,CM,CFM," I "); cputs (" 2M disk information.");
boton (51,24,CB1,CTB1,CM,CFM,"ESC"); cputs (" Exit (ALT-X quit!).");
}
v3df (51, 14, 26, 8, 1, 1, CMI, CFM);
}
void DibujaValores (unidad, vunidad, mf_mfm, cilindro, cabezal)
{
textcolor (CI); textbackground (CFM);
gotoxy (55, 16); if (sp) cputs("Unidad "); else cputs("Drive ");
putch(unidad+'A'); putch(':');
gotoxy (55, 17);
switch (vunidad) {
case 2: cputs ("250 Kbit"); break;
case 1: cputs ("300 Kbit"); break;
case 0: cputs ("500 Kbit"); break;
default: cputs ("1 Mbit"); break;
}
if (sp) cputs("/seg"); else cputs("/sec");
if (mf_mfm) cputs(" MFM "); else cputs(" MF ");
gotoxy (59, 18);
switch (vunidad) {
case 1: cputs("360K "); break;
case 2: cputs("720K "); break;
case 3: cputs("2.88M "); break;
default: cputs("1.2/1.44M"); break;
}
gotoxy (55, 19);
if (sp) cputs("Cilindro "); else cputs("Cylinder ");
cputs (dec2strq(cilindro)); cputs(" ");
gotoxy (67, 19);
if (sp) cputs("Cara "); else cputs("Side ");
cputs (dec2strq(cabezal));
}
int PeligrosoOS2()
{
int largarse=0, t;
if (EsOS2()) {
ventana (ABRIR, 15, 8, 64, 19, CS, CFS);
if (sp) {
gotoxy (5, 2); cputs("Esta sesión DOS está corriendo bajo OS/2");
gotoxy (5, 4); cputs("765DEBUG puede funcionar bajo OS/2, pero");
gotoxy (3, 5); cputs("sus continuos accesos al hardware de disco y");
gotoxy (3, 6); cputs("el control que realiza OS/2 de los puertos");
gotoxy (3, 7); cputs("convierten la tarea en algo conflictiva.");
gotoxy (8, 9); cputs("INTRO - CONTINUAR ESC - SALIR");
}
else {
gotoxy (6, 2); cputs("This DOS session is running under OS/2");
gotoxy (5, 4); cputs("765DEBUG can work with OS/2 loaded, but it");
gotoxy (3, 5); cputs("continuous and direct disk hardware access,");
gotoxy (3, 6); cputs("and the I/O ports control performed by OS/2");
gotoxy (3, 7); cputs("turn its functions a little conflictive.");
gotoxy (8, 9); cputs("ENTER - CONTINUE ESC - EXITS");
}
CursorOff(); t = Tecla();
if (t!=13) largarse=1;
ventana (CERRAR, 15, 8, 64, 19, 0, 0);
}
return (largarse);
}
void TestDMA (void)
{
unsigned emm;
unsigned long bytes;
if ((bytes=VDMA(&emm)) < SMAX) {
ventana (ABRIR, 21, 6, 61, 20, CD, CFD);
if (sp) {
gotoxy (17,1); cputs("AVISO");
gotoxy (2, 3); cputs("El buffer para transferencias con DMA");
gotoxy (2, 4); cputs("de su controlador de memoria admite");
gotoxy (2, 5); cputs("sólo "); cputs (dec5strq((unsigned) bytes));
cputs (" bytes (");
cputs(dec2strq((unsigned) bytes/1024)); cputs(" Kb).");
gotoxy (2, 7); cputs("El sistema podría estrellarse o puede");
gotoxy (2, 8); cputs("salir un mensaje de su controlador de");
gotoxy (2, 9); cputs("memoria si trabaja con sectores de un");
gotoxy (2,10); cputs("tamaño superior (y sólo en ese caso).");
if (emm == 20805) {
gotoxy (2,12); cputs("Con su controlador (QEMM) bastaría en");
gotoxy (2,13); cputs("ese caso añadir la opción DMA=Kbytes.");
}
}
else {
gotoxy (16,1); cputs("WARNING");
gotoxy (2, 3); cputs("The current maximum DMA buffer size");
gotoxy (2, 4); cputs("supported by your memory manager, has");
gotoxy (2, 5); cputs("only "); cputs (dec5strq((unsigned) bytes));
cputs (" bytes (");
cputs(dec2strq((unsigned) bytes/1024)); cputs(" Kb).");
gotoxy (2, 7); cputs("The system may hangs; or your memory");
gotoxy (2, 8); cputs("manager can print an error message if");
gotoxy (2, 9); cputs("you work with sectors bigger than the");
gotoxy (2,10); cputs("buffer size (and only in this case).");
if (emm == 20805) {
gotoxy (2,12); cputs("With your EMM (QEMM) you can, if you");
gotoxy (2,13); cputs("need it, to add a DMA=Kbytes option.");
}
}
CursorOff(); getch();
ventana (CERRAR, 21, 6, 61, 20, 0, 0);
}
}
unsigned long VDMA (unsigned *emm)
{
union REGS r;
struct SREGS s;
unsigned long bytes;
bytes = 65536L; /* supuesto que no hay problemas con el DMA */
*emm = 0; /* supuesto que no hay controlador de memoria */
if (es386()) {
r.x.ax = 0x354B;
int86x (0x21, &r, &r, &s);
if ((s.es | r.x.bx) && (s.es != 0xFFFF) && (r.x.bx != 0xFFFF)) {
r.x.ax = 0x8102;
r.x.dx = r.x.si = r.x.di = 0;
int86 (0x4B, &r, &r);
if ((!(r.x.flags & 1)) && (r.x.si | r.x.di)) {
bytes = ((unsigned long) r.x.si << 16) | r.x.di;
*emm = r.x.bx;
}
}
}
return (bytes);
}
int SalirConfirmado()
{
int salir, t;
t = peekb(0x40, 0x49) & 0x7F;
ventana (ABRIR, 29, 9, 60, 15, CS, CFS);
textcolor (CS);
if (sp) {
gotoxy (4,2); cputs("¿Seguro que desea salir?");
gotoxy (3,4); cputs("Pulse ");
}
else {
gotoxy (6,2); cputs("Are you sure to exit?");
gotoxy (3,4); cputs("Press ");
}
if (t!=7) {
textcolor (CFS+BLINK); textbackground (CS);
}
else {
textcolor (0); textbackground (7);
}
if (sp) {
cputs ("INTRO");
textcolor (CS); textbackground (CFS); cputs(" para confirmar");
}
else {
cputs ("ENTER");
textcolor (CS); textbackground (CFS); cputs(" key to confirm");
}
CursorOff();
t=Tecla();
if ((t==13) || (t==0x2D00)) salir=1; else salir=0;
ventana (CERRAR, 29, 9, 60, 15, 0, 0);
return (salir);
}
void Informe2M (int unidad, int *cilindro, int *cabezal, int vunidad)
{
Boot sector0, virtual;
int i, error, anio, mes, dia, hora, min, seg, dif;
*cilindro = *cabezal = 0; /* terminaremos en pista 0 */
outportb (FD_DCR, peekb(0x40, 0x8B) >> 6); /* velocidad normal */
ventana (ABRIR, 22, 7, 57, 16, C2M, CF2M);
if (sp) {
gotoxy (9, 1);
cputs("INFORME UNIDAD "); putch(unidad+'A'); putch(':');
}
else {
gotoxy (10,1);
cputs("DRIVE "); putch(unidad+'A'); putch(':'); cputs(" REPORT");
}
if (!Hay2M3()) {
if (sp) {
gotoxy (5,4); cputs("2M ó 2MX 3.X no instalado");
gotoxy (8,6); cputs("Imposible informar");
}
else {
gotoxy (6,4); cputs("2M ó 2MX 3.X not loaded");
gotoxy (5,6); cputs("Information not available");
}
}
else {
error=biosdisk(2, unidad, 0x80, 0, 1, 1, §or0);
if (error) {
biosdisk (0, unidad, 0, 0, 1, 1, §or0);
error=biosdisk(2, unidad, 0x80, 0, 1, 1, §or0);
}
if (error) error=biosdisk(2, unidad, 0x80, 0, 1, 1, §or0);
if (error==4) {
if (sp) {
gotoxy (4,5); cputs("El disquete no es de tipo 2M");
}
else {
gotoxy (4,5); cputs("Diskette is not 2M formatted");
}
}
else if (error) {
if (sp) {
gotoxy (8,4); cputs("Unidad no preparada");
gotoxy (8,5); cputs("o disquete extraño.");
}
else {
gotoxy (10,4); cputs("Drive not ready");
gotoxy (7,5); cputs("or strange disk format.");
}
}
else {
gotoxy (3,3); if (sp) cputs("Tipo de disco: ");
else cputs("Disk type: ");
for (i=0; i<8; i++) putch(sector0.IdSis[i]);
gotoxy (3,4); if (sp) cputs("Capacidad: ");
else cputs("Disk size: ");
cputs (dec5strq(sector0.NumSect/(1024/sector0.BytesSect)));
cputs(" Kb");
gotoxy (3,5); if (sp) cputs("Versión formato: ");
else cputs("Format release: ");
cputs (dec2strq(sector0.VersionFmt));
gotoxy (3,6); if (sp) cputs("Fecha formateo: ");
else cputs("Format date: ");
if (sector0.Flags & 1) {
anio=1980+(sector0.FechaF>>9);
mes=(sector0.FechaF>>5) & 15;
dia=sector0.FechaF & 31;
if (sp) {
cputs (dec2strq(dia)); putch('/');
cputs (dec2str(mes)); putch('/');
cputs (dec5strq(anio));
}
else {
cputs (dec2strq(mes)); putch('/');
cputs (dec2str(dia)); putch('/');
cputs (dec5strq(anio));
}
}
else {
if (sp) cputs("No disponible"); else cputs("Not available");
}
gotoxy (3,7); if (sp) cputs("Hora formateo: ");
else cputs("Format time: ");
if (sector0.Flags & 1) {
hora=sector0.HoraF>>11;
min=(sector0.HoraF>>5) & 63;
seg=(sector0.HoraF & 31) << 1;
cputs (dec2str(hora)); putch(':');
cputs (dec2str(min)); putch(':');
cputs (dec2str(seg));
}
else {
if (sp) cputs("No disponible"); else cputs("Not available");
}
}
}
CursorOff();
i = Tecla();
ventana (CERRAR, 22, 7, 57, 16, 0, 0);
SeleccionarUnidad (unidad, vunidad); /* restaurar condiciones iniciales */
}
void SeleccionarUnidad (unidad, vunidad)
{
pokeb(0x40,0x40,0xFF);
outportb (FD_DOR, 1<<(unidad+4) | 4+8 | unidad);
pokeb (0x40, 0x3F, peekb(0x40, 0x3F) | (1 << unidad));
DensidadSpecify (vunidad);
MotorOff();
}
void ResetUnidad (unidad)
{
int i;
pokeb (0x40, 0x3E, peekb (0x40, 0x3E) & 0x7F);
outportb (FD_DOR, 1<<(unidad+4) | unidad | 8); /* reset */
delay (2);
outportb (FD_DOR, 1<<(unidad+4) | unidad | 8+4); /* fin reset */
EsperarInt(); /* esperar interrupción */
outfdc (8); /* comando 'leer estado de interrupciones' */
(void) infdc(); /* leer y desechar resultado */
(void) infdc();
MotorOff();
}
void DensidadSpecify (int vunidad)
{
outportb (FD_DCR, vunidad); /* seleccionar densidad */
outfdc (3); /* comando Specify */
if (vunidad==3)
outfdc (0xAF); /* tiempo de acceso pista-pista y head unload */
else if (!vunidad)
outfdc (0xBF);
else
outfdc (0xDF);
outfdc (2); /* head load time = 1; modo DMA */
}
void recalibrar (unidad, cabezal, vunidad, pausa)
{
int recal, res, pis;
ventana (ABRIR, 30, 10, 50, 17, 15, 1);
gotoxy (3, 3);
if (sp) cputs("Recalibrando "); else cputs("Recalibrate ");
putch(unidad+'A'); putch(':');
CursorOff();
MotorOn (unidad); /* asegurar que el motor está en marcha */
SeleccionarUnidad (unidad, vunidad);
MotorOn (unidad);
ResetUnidad (unidad); /* aprovechar para resetear */
ResetUnidad (unidad);
DensidadSpecify (vunidad);
/**** Recalibrar hasta dos veces si es preciso ****/
for (recal=0; recal<2; recal++) {
outfdc (7); /* comando de recalibrado */
outfdc (cabezal << 2 | unidad); /* byte 1 de dicho comando */
EsperarInt(); /* esperar interrupción */
outfdc (8); /* comando 'leer estado de interrupciones' */
res=infdc(); /* leer resultado */
pis=infdc();
if (!recal) clrscr();
gotoxy (5, 1+recal*2);
if ((res>=0) && (pis>=0)) {
cputs ("ST0 = 0x"); cputs (hex2str(res));
gotoxy (5, 2+recal*2);
if (sp) cputs ("Pista = "); else cputs ("Track = ");
cputs (dec2strq(pis));
}
else
cputs ("ST0 = ??");
if (!((res ^ 32) & (0xF0))) break; /* resultado correcto */
}
MotorOff();
if (recal<2) { /* sin fallo */
CursorOff();
if (pausa) delay(750);
}
else {
gotoxy (3, 6);
if (sp) cputs ("Pulsa una tecla"); else cputs (" Press any key ");
CursorOff(); Tecla();
}
ventana (CERRAR, 30, 10, 50, 17, 0, 0);
}
void posicionar (unidad, cabezal, cilindro, vunidad)
{
int res, pis;
ventana (ABRIR, 30, 9, 50, 14, 15, 1);
gotoxy (3, 2);
if (sp) cputs("Posicionando "); else cputs(" Seek ");
putch(unidad+'A'); putch(':');
CursorOff();
MotorOn (unidad); /* asegurar que el motor está en marcha */
SeleccionarUnidad (unidad, vunidad);
MotorOn (unidad);
/**** Desplazar cabezal hasta la pista ****/
outfdc (0xF); /* comando 'Seek' */
outfdc (cabezal << 2 | unidad); /* byte 1 de dicho comando */
outfdc (cilindro);
EsperarInt(); /* esperar interrupción */
outfdc (8); /* comando 'leer estado de interrupciones' */
res=infdc();
pis=infdc();
clrscr(); gotoxy (5, 1);
if ((res>=0) && (pis>=0)) {
cputs ("ST0 = 0x"); cputs (hex2str(res)); gotoxy (5, 2);
if (sp) cputs ("Pista = "); else cputs ("Track = ");
cputs (dec2strq(pis)); gotoxy (3, 4);
}
else
cputs ("ST0 = ??");
MotorOff();
if (!(res & 0xC0)) {
CursorOff();
delay(750);
}
else {
if (sp) cputs ("Pulsa una tecla"); else cputs (" Press any key ");
CursorOff(); Tecla();
}
ventana (CERRAR, 30, 9, 50, 14, 0, 0);
}
void LeerSector (unidad, mf_mfm, cilindro, cabezal, buffer, bytes, vunidad)
char huge *buffer;
unsigned *bytes;
{
static sector=1, tsector=2, t128=128;
unsigned t;
char cad[32];
ventana (ABRIR, 23, 7, 65, 21, CL, CFL);
if (sp) {
gotoxy (12,1);
cputs("LECTURA DE SECTOR");
}
else {
gotoxy (16,1);
cputs("SECTOR READ");
}
gotoxy (2,3); cputs("Sector: ");
strcpy (cad, dec3strq (sector));
if (!input (cad, 1, 3, CL, CFL)) goto AbortaLectura;
sector = atoi (cad); if (sector>255) sector=255;
gotoxy (2, 5); if (sp) cputs("Tamaño de sector:"); else cputs("Sector size:");
gotoxy (2, 6); cputs(" 0 -> 1-128 bytes 5 -> 4096 bytes");
gotoxy (2, 7); cputs(" 1 -> 256 bytes 6 -> 8192 bytes");
gotoxy (2, 8); cputs(" 2 -> 512 bytes 7 -> 16384 bytes");
gotoxy (2, 9); cputs(" 3 -> 1024 bytes 8 -> 32768 bytes");
gotoxy (2,10); cputs(" 4 -> 2048 bytes Val");
if (sp) cputs("or: "); else cputs("ue: ");
strcpy (cad, dec2strq (tsector));
if (!input (cad, 1, 2, CL, CFL)) goto AbortaLectura;
tsector = atoi (cad);
if (tsector==0) {
gotoxy (24, 10); if (sp) cputs("Indica"); else cputs("Select");
cputs(" 1-128: ");
strcpy (cad, dec3strq (t128));
if (!input (cad, 1, 3, CL, CFL)) goto AbortaLectura;
t128 = atoi (cad); if (t128>255) t128=255;
}
gotoxy (7,12); if (sp) cputs("Cilindro: "); else cputs("Cylinder: ");
strcpy (cad, dec3strq (cilindro));
if (!input (cad, 1, 3, CL, CFL)) goto AbortaLectura;
cilindro = atoi (cad); if (cilindro>255) cilindro=255;
gotoxy (25,12); if (sp) cputs("Cara: "); else cputs("Side: ");
strcpy (cad, dec3strq (cabezal));
if (!input (cad, 1, 3, CL, CFL)) goto AbortaLectura;
cabezal = atoi (cad); if (cabezal>255) cabezal=255;
clrscr();
gotoxy (17, 6); if (sp) cputs("Leyendo..."); else cputs("Reading...");
for (t=0; t<SMAX; t+=2) {
buffer[t]=0x5A; buffer[t+1]=0xA5; /* "borrar" el buffer */
}
MotorOn (unidad);
SeleccionarUnidad (unidad, vunidad);
MotorOn (unidad);
*bytes = tsector? (unsigned) 128 << tsector: t128;
PreparaDma (0x46, *bytes, buffer);
outfdc (0x06 | mf_mfm << 6); /* comando para leer */
outfdc (cabezal << 2 | unidad); /* byte 1 de dicho comando */
outfdc (cilindro);
outfdc (cabezal);
outfdc (sector);
outfdc (tsector);
outfdc (sector);
outfdc (1); /* GAP para leer: poco importante */
outfdc (t128); /* tamaño si tsector=0 */
EsperarInt(); /* esperar interrupción */
ventana (CERRAR, 23, 7, 65, 21, 0, 0);
Resultados (LEER, unidad, cabezal);
goto FinLectura;
AbortaLectura: ventana (CERRAR, 23, 7, 65, 21, 0, 0);
FinLectura: ;
}
void EscribirSector (unidad, mf_mfm, vunidad, cilindro, cabezal, buffer)
char huge *buffer;
{
static sector=1, tsector=2, t128=128, wreset=0, dmacnt=12335;
char cad[32];
ventana (ABRIR, 23, 5, 65, 23, CE, CFE);
if (sp) {
gotoxy (11,1);
cputs("ESCRITURA DE SECTOR");
}
else {
gotoxy (16,1);
cputs("SECTOR WRITE");
}
gotoxy (2,3); cputs("Sector: ");
strcpy (cad, dec3strq (sector));
if (!input (cad, 1, 3, CE, CFE)) goto AbortaEscritura;
sector = atoi (cad); if (sector>255) sector=255;
gotoxy (2, 5); if (sp) cputs("Tamaño de sector:"); else cputs("Sector size:");
gotoxy (2, 6); cputs(" 0 -> 1-128 bytes 5 -> 4096 bytes");
gotoxy (2, 7); cputs(" 1 -> 256 bytes 6 -> 8192 bytes");
gotoxy (2, 8); cputs(" 2 -> 512 bytes 7 -> 16384 bytes");
gotoxy (2, 9); cputs(" 3 -> 1024 bytes 8 -> 32768 bytes");
gotoxy (2,10); cputs(" 4 -> 2048 bytes Val");
if (sp) cputs("or: "); else cputs("ue: ");
strcpy (cad, dec2strq (tsector));
if (!input (cad, 1, 2, CE, CFE)) goto AbortaEscritura;
tsector = atoi (cad);
if (tsector==0) {
gotoxy (24, 10); if (sp) cputs("Indica"); else cputs("Select");
cputs(" 1-128: ");
strcpy (cad, dec3strq (t128));
if (!input (cad, 1, 3, CE, CFE)) goto AbortaEscritura;
t128 = atoi (cad); if (t128>255) t128=255;
}
gotoxy (7,12); if (sp) cputs("Cilindro: "); else cputs("Cylinder: ");
strcpy (cad, dec3strq (cilindro));
if (!input (cad, 1, 3, CE, CFE)) goto AbortaEscritura;
cilindro = atoi (cad); if (cilindro>255) cilindro=255;
gotoxy (25,12); if (sp) cputs("Cara: "); else cputs("Side: ");
strcpy (cad, dec3strq (cabezal));
if (!input (cad, 1, 3, CE, CFE)) goto AbortaEscritura;
cabezal = atoi (cad); if (cabezal>255) cabezal=255;
gotoxy (2, 14);
if (sp)
cputs("¿Escritura normal sin reset? (S/N): ");
else
cputs("Normal write without reset? (Y/N): ");
if (wreset) strcpy (cad, "N"); else strcpy (cad, sp?"S":"Y");
if (!input (cad, 0, 1, CE, CFE)) goto AbortaEscritura;
if ((cad[0] | 32) == 'n') wreset=1; else wreset=0;
if (wreset) {
gotoxy (2, 16);
if (sp)
cputs("Valor del contador del DMA: ");
else
cputs("Value for DMA count: ");
strcpy (cad, dec5strq (dmacnt));
if (!input (cad, 1, 5, CE, CFE)) goto AbortaEscritura;
dmacnt = atoi (cad);
}
clrscr();
gotoxy (15, 8);
if (sp) cputs("Escribiendo..."); else cputs(" Writing...");
MotorOn (unidad);
SeleccionarUnidad (unidad, vunidad);
MotorOn (unidad);
PreparaDma (0x4A, wreset? dmacnt: tsector? 128 << tsector: 0, buffer);
outfdc (0x05 | mf_mfm << 6); /* comando para escribir */
outfdc (cabezal << 2 | unidad); /* byte 1 de dicho comando */
outfdc (cilindro);
outfdc (cabezal);
outfdc (sector);
outfdc (tsector);
outfdc (sector);
outfdc (1); /* GAP mínimo */
outfdc (t128); /* tamaño si tsector=0 */
if (wreset) {
EsperaDma0 (unidad); /* con reset precario */
ResetUnidad (unidad); /* reset en condiciones */
SeleccionarUnidad (unidad, vunidad);
}
else EsperarInt();
ventana (CERRAR, 23, 5, 65, 23, 0, 0);
if (!wreset) Resultados (ESCRIBIR, unidad, cabezal);
goto FinEscritura;
AbortaEscritura: ventana (CERRAR, 23, 5, 65, 23, 0, 0);
FinEscritura: ;
}
void FormatearPista (unidad, mf_mfm, vunidad, cilindro, cabezal, kbps)
{
unsigned char buffer[768]; /* ¡hasta 192 sectores! */
static sectores=-1,
pokete=0xE6, tsector=2, eformat=0, freset=0,
autogap=1, tunidad=4, gap=108, dmacnt=-1;
int i, b765;
long bytes;
char cad[32];
ventana (ABRIR, 23, 3, 64, 23, CF, CFF);
if (sp) {
gotoxy (12,1);
cputs("FORMATEO DE PISTA");
}
else {
gotoxy (15,1);
cputs("FORMAT TRACK");
}
gotoxy (2, 3); if (sp) cputs("Tamaño de sector:"); else cputs("Sector size:");
gotoxy (2, 4); cputs(" 0 -> 1-128 bytes 5 -> 4096 bytes");
gotoxy (2, 5); cputs(" 1 -> 256 bytes 6 -> 8192 bytes");
gotoxy (2, 6); cputs(" 2 -> 512 bytes 7 -> 16384 bytes");
gotoxy (2, 7); cputs(" 3 -> 1024 bytes 8 -> 32768 bytes");
gotoxy (2, 8); cputs(" 4 -> 2048 bytes Val");
if (sp) cputs("or: "); else cputs("ue: ");
strcpy (cad, dec2strq (tsector));
if (!input (cad, 1, 2, CF, CFF)) goto AbortaFormateo;
tsector = atoi (cad);
if (sectores==-1) { /* primera vez */
switch (TipoDrive(unidad)) {
case 2: if (kbps==0) sectores = 15; else sectores=9; break;
case 5: if (kbps==3) sectores = 36; /* sin break :-) */
case 4: if (kbps==0) sectores = 18;
if ((kbps==1) || (kbps==2)) sectores=9; break;
case 1:
case 3:
default: sectores = 9; tunidad = 1; break;
}
if (!mf_mfm) sectores >>= 1;
}
gotoxy (2,10); if (sp) cputs("Sectores: "); else cputs("Sectors: ");
strcpy (cad, dec3strq (sectores));
if (!input (cad, 1, 3, CF, CFF)) goto AbortaFormateo;
sectores = atoi (cad); if (sectores>192) sectores=192;
gotoxy (2,12);
if (sp) cputs("¿Calculo yo el GAP3? (S/N): ");
else cputs("Do I adjust the GAP3? (Y/N): ");
if (autogap) strcpy (cad, sp?"S":"Y"); else strcpy (cad, "N");
if (!input (cad, 0, 1, CF, CFF)) goto AbortaFormateo;
if ((cad[0] | 32) == 'n') autogap=0; else autogap=1;
if (autogap) {
gotoxy ( 2, 12); clreol();
if (TipoDrive(unidad)!=-1)
tunidad=TipoDrive(unidad);
else {
gotoxy (17, 11); cputs("1 - 360K");
gotoxy (17, 12); cputs("2 - 1.2M");
gotoxy (17, 13); cputs("3 - 720K");
gotoxy (17, 14); cputs("4 - 1.44M");
gotoxy (17, 15); cputs("5 - 2.88M");
gotoxy ( 2, 17); if (sp) cputs("Indica el tipo de UNIDAD: ");
else cputs("Select DRIVE type: ");
strcpy (cad, dec2strq (tunidad));
if (!input (cad, 1, 2, CF, CFF)) goto AbortaFormateo;
tunidad = atoi (cad);
if (tunidad>5) { tunidad=4; goto AbortaFormateo; }
for (i=11; i<=17; i++) { gotoxy (1, i); clreol(); }
}
if (tunidad==6) tunidad=5; /* convención AMI */
switch (tunidad) {
case 1:
case 3: switch (kbps) {
case 1: bytes = 7500; break;
default: bytes = 6250; break;
}
break;
case 2: switch (kbps) {
case 0: bytes = 10416; break;
case 2: bytes = 5208; break;
default: bytes = 6250; break;
}
break;
case 4:
case 5: switch (kbps) {
case 1: bytes = 7500; break;
case 2: bytes = 6250; break;
case 3: bytes = 25000; break;
default: bytes = 12500; break;
}
break;
}
b765=62; if (!mf_mfm) { bytes >>= 1; b765 >>= 1; }
gap = (bytes-((b765 + (128L << tsector)) * sectores)-146-32) / sectores;
if (gap>255) gap=255;
if (gap<1) {
gap=1;
gotoxy (10,12); if (sp) cputs("-> ¡No caben tantos sectores!");
else cputs("-> Too many sectors for track!");
}
gotoxy (2, 12); cputs("GAP3: "); cputs(dec5strq(gap));
}
else {
gotoxy (2,12); clreol(); cputs("GAP3: ");
strcpy (cad, dec3strq (gap));
if (!input (cad, 1, 3, CF, CFF)) goto AbortaFormateo;
gap = atoi (cad); if (gap>255) gap=255;
}
gotoxy (20,10); if (sp) cputs("Byte de relleno: "); else cputs("Fill byte: ");
strcpy (cad, dec3strq (pokete));
if (!input (cad, 1, 3, CF, CFF)) goto AbortaFormateo;
pokete = atoi (cad); if (pokete>255) pokete=255;
gotoxy (2, 14);
if (sp)
cputs("¿Usar valores normales? (S/N): ");
else
cputs("Format with standard values? (Y/N): ");
if (eformat) strcpy (cad, "N"); else strcpy (cad, sp?"S":"Y");
if (!input (cad, 0, 1, CF, CFF)) goto AbortaFormateo;
if ((cad[0] | 32) == 'n') eformat=1; else eformat=0;
gotoxy (2, 16);
if (sp)
cputs("¿Formateo normal sin reset? (S/N): ");
else
cputs("Normal format without reset? (Y/N): ");
if (freset) strcpy (cad, "N"); else strcpy (cad, sp?"S":"Y");
if (!input (cad, 0, 1, CF, CFF)) goto AbortaFormateo;
if ((cad[0] | 32) == 'n') freset=1; else freset=0;
if (freset) {
if (dmacnt==-1) dmacnt=sectores<<2;
gotoxy (2, 18);
if (sp)
cputs("Valor del contador del DMA: ");
else
cputs("Value for DMA count: ");
strcpy (cad, dec5strq (dmacnt));
if (!input (cad, 1, 5, CF, CFF)) goto AbortaFormateo;
dmacnt = atoi (cad);
}
for (i=0; i<sectores; i++) { /* tabla propuesta para formatear */
buffer[i*4]=cilindro;
buffer[i*4+1]=cabezal;
buffer[i*4+2]=i+1;
buffer[i*4+3]=tsector;
}
if (eformat)
if (!EditarTablaFmt (buffer, sectores)) /* permitir su alteración */
goto AbortaFormateo;
clrscr();
gotoxy (16, 9);
if (sp) cputs("Formateando..."); else cputs("Formatting...");
MotorOn (unidad);
SeleccionarUnidad (unidad, vunidad);
MotorOn (unidad);
PreparaDma(0x4A, freset? dmacnt: sectores << 2, buffer);
outfdc (0x0D | mf_mfm << 6); /* comando para formatear */
outfdc (cabezal << 2 | unidad); /* byte 1 de dicho comando */
outfdc (tsector);
outfdc (sectores);
outfdc (gap);
outfdc (pokete); /* byte de relleno */
if (freset) {
EsperaDma0 (unidad); /* con reset precario */
ResetUnidad (unidad); /* reset en condiciones */
SeleccionarUnidad (unidad, vunidad);
}
else EsperarInt();
ventana (CERRAR, 23, 3, 64, 23, 0, 0);
if (!freset) Resultados (FORMATEAR, unidad, cabezal);
goto FinFormateo;
AbortaFormateo: ventana (CERRAR, 23, 3, 64, 23, 0, 0);
FinFormateo: ;
}
int EditarTablaFmt (unsigned char *buffer, int numsect)
{
static sector=1, cil=-1, cab=-1, sec=-1, tse=-1, valor=0, subop=3;
int i, opcion, opc;
char cad[32];
do {
clrscr();
if (sp) {
gotoxy (5,1);
cputs("OPCIONES ESPECIALES DE FORMATEO");
}
else {
gotoxy (10,1);
cputs("SPECIAL FORMAT OPTIONS");
}
gotoxy (2,3); if (sp) cputs("Sectores: "); else cputs("Sectors: ");
for (i=0; (i<numsect) && (i<66); i++) {
cputs (dec3str(buffer[i*4+2]));
putch(' ');
}
if (numsect>65) cputs("...");
if (sp) {
gotoxy (2, 11); cputs("Opciones:");
gotoxy (2, 12); cputs(" 1 - Introducir manualmente los 4");
gotoxy (2, 13); cputs(" bytes de un sector.");
gotoxy (2, 14); cputs(" 2 - Modificar un cierto byte en");
gotoxy (2, 15); cputs(" todos los sectores.");
gotoxy (2, 16); cputs(" ESC - Cancelar orden de formateo.");
gotoxy (2, 17); cputs("INTRO - Proceder con el formateo.");
gotoxy (2, 18); cputs(" Elige: ");
}
else {
gotoxy (2, 11); cputs("Options:");
gotoxy (2, 12); cputs(" 1 - To introduce one by each the 4");
gotoxy (2, 13); cputs(" bytes of one sector.");
gotoxy (2, 14); cputs(" 2 - To modify one of the 4 bytes");
gotoxy (2, 15); cputs(" in all sectors.");
gotoxy (2, 16); cputs(" ESC - Cancel format command.");
gotoxy (2, 17); cputs("INTRO - Run now format command.");
gotoxy (2, 18); cputs(" Choose: ");
}
do opcion=Tecla();
while (((opcion<'1') || (opcion>'3')) && (opcion!=27) && (opcion!=13));
for (i=11; i<19; i++) { gotoxy (1, i); clreol(); }
if (opcion=='1') {
do {
gotoxy (2, 11); if (sp) cputs("Sector a alterar: ");
else cputs("Sector to modify: ");
strcpy (cad, dec3strq (sector));
if (!input (cad, 1, 3, CF, CFF)) break;
sector = atoi (cad); if (sector>255) sector=255;
for (i=0; (i<numsect) && (buffer[i*4+2]!=sector); i++);
if (buffer[i*4+2]!=sector) {
gotoxy (2, 13);
if (sp) cputs("Ese sector no existe.");
else cputs("Such sector does not exist.");
}
else {
gotoxy (2, 13); if (sp) cputs ("Nº Cilindro (anterior=");
else cputs ("Cylinder number (previous=");
cputs (dec3str(buffer[i*4]));
cputs ("): ");
if (cil==-1) cil=buffer[i*4];
strcpy (cad, dec3strq (cil));
if (!input (cad, 1, 3, CF, CFF)) break;
cil = atoi(cad); if (cil>255) cil=255;
gotoxy (2, 14); if (sp) cputs ("Nº Cabezal (anterior=");
else cputs ("Head number (previous=");
cputs (dec3str(buffer[i*4+1]));
cputs ("): ");
if (cab==-1) cab=buffer[i*4+1];
strcpy (cad, dec3strq (cab));
if (!input (cad, 1, 3, CF, CFF)) break;
cab = atoi(cad); if (cab>255) cab=255;
gotoxy (2, 15); if (sp) cputs ("Número sector (anterior=");
else cputs ("Sector number (previous=");
cputs (dec3str(buffer[i*4+2]));
cputs ("): ");
if (sec==-1) sec=buffer[i*4+2];
strcpy (cad, dec3strq (sec));
if (!input (cad, 1, 3, CF, CFF)) break;
sec = atoi(cad); if (sec>255) sec=255;
gotoxy (2, 16); if (sp) cputs ("Tamaño Sector (anterior=");
else cputs ("Sector size (previous=");
cputs (dec3str(buffer[i*4+3]));
cputs ("): ");
if (tse==-1) tse=buffer[i*4+3];
strcpy (cad, dec3strq (tse));
if (!input (cad, 1, 3, CF, CFF)) break;
tse = atoi(cad); if (tse>255) tse=255;
buffer[i*4]=cil;
buffer[i*4+1]=cab;
buffer[i*4+2]=sec;
buffer[i*4+3]=tse; /* hechos cambios */
}
} while (0); /* do-bobo, para poder salir con break ;-) */
}
else if (opcion=='2') {
if (sp) {
gotoxy (2, 11); cputs("Característica a cambiar: ");
gotoxy (2, 12); cputs(" 0 - Nº Cilindro");
gotoxy (2, 13); cputs(" 1 - Nº Cabezal");
gotoxy (2, 14); cputs(" 2 - Nº Sector");
gotoxy (2, 15); cputs(" 3 - Tamaño sector");
gotoxy (2, 16); cputs(" Elige: ");
}
else {
gotoxy (2, 11); cputs("Characteristic to modify: ");
gotoxy (2, 12); cputs(" 0 - Cylinder number");
gotoxy (2, 13); cputs(" 1 - Head number");
gotoxy (2, 14); cputs(" 2 - Sector number");
gotoxy (2, 15); cputs(" 3 - Sector size");
gotoxy (2, 16); cputs(" Choose: ");
}
strcpy (cad, dec2strq (subop));
if (input (cad, 1, 3, CF, CFF)) {
subop = atoi (cad);
if (subop>3)
subop=3;
else {
for (i=11; i<17; i++) { gotoxy (1, i); clreol(); }
gotoxy (2, 11); if (sp) cputs("Nuevo valor general: ");
else cputs("New general value: ");
strcpy (cad, dec3strq (valor));
if (input (cad, 1, 3, CF, CFF)) {
valor = atoi (cad); if (valor>255) valor=255;
for (i=0; i<numsect; i++) buffer[i*4+subop]=(char) valor;
}
}
}
}
} while ((opcion!=27) && (opcion!=13));
return (opcion==13);
}
void LeerIds (unidad, mf_mfm, cabezal, vunidad)
{
unsigned long tmp[24], acu;
int nec[24][7];
unsigned i, j, lectura, antlectura, cnth, primeravez=0, tec;
do {
ventana (ABRIR, 23, 11, 58, 15, CIW, CFIW);
gotoxy (3, 2);
if (sp)
cputs("Leyendo ID's... [ESC-Cancelar]");
else
cputs("Reading ID's... [ESC - Aborts]");
CursorOff();
MotorOn (unidad); /* asegurar que el motor está en marcha */
SeleccionarUnidad (unidad, vunidad);
MotorOn (unidad);
outportb (0x61, inportb(0x61) & 0xFD | 1); /* inhibir sonido */
outportb (0x43, 0xB4); /* contador 2 */
outportb (0x42, 0xFF); outportb (0x42, 0xFF); /* cuenta 0xFFFF */
for (i=0; i<24; i++) {
outfdc (0x0A | mf_mfm << 6); /* comando 'Leer ID' */
outfdc (cabezal << 2 | unidad); /* byte 1 del comando */
lectura=0xFFFF; cnth=0; /* cuenta inicial */
do { /* esperar interrupción */
antlectura=lectura;
outportb (0x43, 0x80); /* enclavamiento */
lectura=inportb(0x42); /* parte baja de la cuenta */
lectura|=inportb(0x42) << 8; /* parte alta de la cuenta */
if (lectura>antlectura) if (cnth++>8) break; /* timeout */
} while (!(peekb(0x40, 0x3E) & 0x80));
pokeb (0x40, 0x3E, peekb (0x40, 0x3E) & 0x7F); /* reset int. */
outportb (0x61, inportb(0x61) & 0xFE); /* bajar GATE */
outportb (0x61, inportb(0x61) | 1); /* subir GATE */
if (kbhit()) {
tec = getch(); if (!tec) tec=getch() << 8;
if (tec==27) { /* tecla ESC */
ventana (CERRAR, 23, 11, 58, 15, 0, 0);
goto fin_ids;
}
}
for (j=0; j<7; j++)
if ((nec[i][j]=infdc())==-1) break;
if (cnth<9)
tmp[i]=cnth*65535L + (65535-lectura);
else {
tmp[i]=0L; /* error */
nec[i][0]=-1; /* no informar */
pokeb (0x40, 0x40, 0xFF); /* asegurar motor en marcha */
} /* porque probablemente se está perdiendo mucho tiempo */
}
outportb (0x61, inportb(0x61) & 0xFC);
ventana (CERRAR, 23, 11, 58, 15, 0, 0);
textcolor (CIMS); textbackground(CFI);
if (!primeravez++) clrscr(); gotoxy (4,1);
textcolor (CIC);
textbackground (CFIC); if (sp) cputs(" Milisegundos "); else cputs(" Milliseconds ");
textbackground (CFI); putch(' ');
textbackground (CFIC); cputs(" Sector ");
textbackground (CFI); putch(' ');
textbackground (CFIC); if (sp) cputs(" Tamaño "); else cputs(" Size ");
textbackground (CFI); putch(' ');
textbackground (CFIC); if (sp) cputs(" Cilindro "); else cputs(" Cylinder ");
textbackground (CFI); putch(' ');
textbackground (CFIC); if (sp) cputs(" Cara "); else cputs(" Side ");
textbackground (CFI); putch(' ');
textbackground (CFIC); cputs(" ST0 ");
textbackground (CFI); putch(' ');
textbackground (CFIC); cputs(" ST1 ");
textbackground (CFI); putch(' ');
textbackground (CFIC); cputs(" ST2 ");
textbackground (CFI);
acu=0;
for (j=0; j<23; j++) { /* rechazar primera muestra */
gotoxy (4, j+2); textcolor (CIMS);
if (tmp[j+1] && tmp[j]) {
acu+=tmp[j+1];
cprintf("[%8.2f]%7.2f ", acu/1193.18, tmp[j+1]/1193.18);
}
else
cprintf(" N.D. ");
if (nec[j][0]>=0) {
textcolor (CIS);
cputs(" "); cputs(dec3str(nec[j][5]));
textcolor (CIT); cputs(" ");
if (nec[j][6]<9)
cputs(dec5str(128 << nec[j][6]));
else
cputs (" ?");
cputs(" ("); cputs(dec3str(nec[j][6])); putch(')');
textcolor (CICC);
cputs(" "); cputs(dec3str(nec[j][3]));
cputs(" "); cputs(dec3str(nec[j][4]));
textcolor (CIST);
cputs (" 0x"); cputs(hex2str(nec[j][0]));
cputs (" 0x"); cputs(hex2str(nec[j][1]));
cputs (" 0x"); cputs(hex2str(nec[j][2]));
}
else {
textcolor (CIMS);
cputs(" ?? ?? ?? ?? ?? ?? ?? ");
}
}
textcolor (CIB);
if (sp) {
gotoxy (17, 25);
cputs("Pulse la BARRA ESPACIADORA para leer más ID's");
}
else {
gotoxy (23, 25);
cputs("Press SPACE BAR to read more ID's");
}
CursorOff();
tec = Tecla();
} while ((tec==32) || (tec=='5'));
fin_ids: MotorOff();
}
void Resultados (operacion, unidad, cabezal)
{
int xx, yy, res, t, st[3], str, bit;
char sterr[2][10][40] =
{ { "MA (Missing Address Mark)",
"NW (Non Writable: write protect error)",
"ND (No data)",
"",
"OR (Overrun)",
"DE (Data Error)",
"",
"EN (End of cylinder)",
},
{ "MD (Missing Address Mark in Data Field",
"BC (Bad Cylinder)",
"",
"",
"WC (Wrong Cylinder)",
"DD (Data Error in Data Field)",
"CM (Control Mark)",
"",
}
};
ventana (ABRIR, 12, 7, 69, 22, CRS, CFRS);
gotoxy (2, 1);
switch (operacion) {
case LEER: if (sp) cputs ("RESULTADO LECTURA");
else cputs ("READ RESULTS");
break;
case ESCRIBIR: if (sp) cputs ("RESULTADO ESCRITURA");
else cputs ("WRITE RESULTS");
break;
case FORMATEAR: if (sp) cputs ("RESULTADO FORMATEO");
else cputs ("FORMAT RESULTS");
break;
}
xx=wherex(); yy=wherey();
gotoxy (2, 3); cputs("[ST0 0x"); st[0]=res=infdc();
if (res>=0) cputs(hex2str(res)); else cputs("??"); putch(']');
if (res<0) {
if (sp) {
cputs (" ¡El FDC no responde!");
gotoxy (xx, yy);
cputs (": ¡ERROR!");
}
else {
cputs (" FDC no answers!");
gotoxy (xx, yy);
cputs (": ERROR!");
}
}
else {
gotoxy (2, 4); cputs("[ST1 0x");
st[1]=res=infdc(); if (res<0) st[1]=0; else st[1] &= 0xB7;
if (res>=0) cputs(hex2str(res)); else cputs("??"); putch(']');
gotoxy (xx, yy);
if ((st[0] & 0xC0)==0)
cputs (sp?": CORRECTO":": OK");
else
cputs (sp?": ¡ERROR!":": ERROR!");
gotoxy (14, 3); cputs("[ST2 0x");
st[2]=res=infdc(); if (res<0) st[2]=0; else st[2] &= 0x73;
if (res>=0) cputs(hex2str(res)); else cputs("??"); putch(']');
gotoxy (26, 3); if (sp) cputs("[Cilindro "); else cputs("[Cylinder ");
res=infdc();
if (res>=0) cputs(dec3str(res)); else cputs("??"); putch(']');
gotoxy (26, 4); if (sp) cputs("[Cabezal "); else cputs("[Head ");
res=infdc();
if (res>=0) cputs(dec3str(res)); else cputs("??"); putch(']');
gotoxy (42, 3); cputs("[Sector ");
res=infdc();
if (res>=0) cputs(dec3str(res)); else cputs("??"); putch(']');
gotoxy (42, 4); if (sp) cputs("[Tamaño "); else cputs("[Size ");
res=infdc();
if (res>=0) cputs(dec3str(res)); else cputs("??"); putch(']');
outfdc (4); /* Leer ST3 */
outfdc (cabezal << 2 | unidad); /* byte 1 */
gotoxy (14, 4); cputs("[ST3 0x"); res=infdc();
if (res>=0) cputs(hex2str(res)); else cputs("??"); putch(']');
gotoxy (2, wherey()+1);
for (str=1; str<=2; str++)
for (bit=0, t=1; bit<8; bit++, t <<= 1)
if (st[str] & t) {
gotoxy (2, wherey()+1);
cputs ("ST"); putch(str+'0'); putch('(');
putch(bit+'0'); cputs("): ");
cputs (sterr[str-1][bit]);
}
}
MotorOff(); CursorOff();
while (kbhit()) getch(); while (!kbhit()); /* dejar tecla en buffer */
if ((bioskey(1) & 0xFF)==27) getch(); /* excepto si es ESC */
ventana (CERRAR, 12, 7, 69, 22, 0, 0);
}
void MostrarBuffer (char huge *buffer, unsigned *bytes)
{
static unsigned desp=0, nbytes=1, valor=0;
static parte=0;
char *pantalla;
unsigned char huge *p;
unsigned register x, off;
unsigned y, t, i;
int partes;
char cad[32];
char hexa[16]={'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
textbackground (CFV); textcolor (CVMI); clrscr();
window (1,18,80,25); textbackground (CFVM); textcolor (CVMM); clrscr();
putch('┌'); for (x=1; x<79; x++) putch ('─'); putch('┐');
for (y=2; y<8; y++) {
gotoxy (1, y); putch('│'); gotoxy (80, y); putch('│');
}
putch('└'); for (x=1; x<79; x++) putch ('─');
_wscroll=0; putch('┘'); _wscroll=1;
textcolor (CVMI);
gotoxy ( 3,3); if (sp) cputs("Cursores: "); else cputs("Cursor keys:");
cputs(" ± 256 bytes");
gotoxy ( 3,4); if (sp) cputs("AvPág/RePág:"); else cputs("PgUp/PgDn: ");
cputs (" ± 512 bytes");
gotoxy ( 3,5); if (sp) cputs("Inicio/Fin: Principio/Final");
else cputs("Home/End: First/Last");
gotoxy ( 3,6); if (sp) cputs("Intro: Nueva sección");
else cputs("Enter: New section");
gotoxy (33,3); if (sp) cputs(" Tab: Modificar bytes");
else cputs("Tab: Modify sector");
gotoxy (33,4); if (sp) cputs(" 0: Poner buffer a 0");
else cputs("0: Set buffer to 0");
gotoxy (33,5); if (sp) cputs(" X,R: Buffer con trama");
else cputs("X,R: Grid buffer");
gotoxy (33,6); if (sp) cputs(" B: Tamaño buffer");
else cputs("B: Set buffer size");
textcolor (CVMD);
gotoxy (58,3); if (sp) cputs("Sección "); else cputs("Section ");
if (sp) {
gotoxy (58,4); cputs("Sector de bytes"); }
else {
gotoxy (64,4); cputs("bytes sector"); }
textcolor (CVMS);
gotoxy (58,6); if (sp) cputs("ESC/ALT-X Abandonar");
else cputs("ESC/ALT-X Exit");
window (1, 1,80,25);
partes = (*bytes >> 8); if (*bytes & 0xFF) partes++;
if (parte>=partes) parte=0;
textbackground (CFV); /* atributos de fondo */
for (y=1; y<=16; y++) {
gotoxy (3, y);
textcolor (CVD); cputs (" ");
textcolor (CVH); cputs (" ");
textcolor (CVS); cputs (" ");
textcolor (CVH); cputs (" ");
textcolor (CVA); cputs (" ");
}
do {
p = &buffer[256*parte];
for (y=0; y<256; y += 16, p += 16) {
pantalla = MK_FP ((peekb(0x40, 0x49) & 0x7F) == 7 ? 0xB000:0xB800, 0);
textcolor (CVD); textbackground (CFV);
off = (p-buffer);
if (off >= *bytes) {
y >>= 4; for (i=0; i < (17-y)*80; i++) pantalla [(y*80+i) << 1]=' ';
break;
}
pantalla += ((y/16) * 80 + 2 ) << 1;
*pantalla=hexa[off >> 12]; pantalla+=2;
*pantalla=hexa[(off >> 8) & 15]; pantalla+=2;
*pantalla=hexa[(off >> 4) & 15]; pantalla+=2;
*pantalla=hexa[off & 15]; pantalla+=2;
*pantalla=':'; pantalla+=6;
for (x=0; x < 8; x++) {
*pantalla=hexa[p[x] >> 4]; pantalla+=2;
*pantalla=hexa[p[x] & 15]; pantalla+=4;
}
*pantalla='-'; pantalla+=4;
for (x=8; x < 16; x++) {
*pantalla=hexa[p[x] >> 4]; pantalla+=2;
*pantalla=hexa[p[x] & 15]; pantalla+=4;
}
pantalla+=4;
for (x=0; x < 16; x++) { *pantalla=p[x]?p[x]:32; pantalla+=2; }
}
textcolor (CVMD); textbackground (CFVM); gotoxy (70,20);
strcpy (cad, dec3strq(parte+1));
cputs(cad); putch('/');
strcpy (cad, dec3strq(partes));
cputs(cad); cputs(" ");
if (sp) gotoxy (68,21); else gotoxy (58, 21);
cputs(dec5str(*bytes));
CursorOff();
t=Tecla();
switch (t) {
case '-':
case 0x4800: parte--; break; /* UP */
case '+':
case 0x5000: parte++; if (parte>=partes) parte=partes-1; break; /* DN */
case ' ': parte++; if (parte>=partes) parte=0; break;
case 0x4700: parte=0; break; /* HOME */
case 0x4F00: parte=partes-1; break; /* END */
case 0x4900: parte-=2; break; /* PGUP */
case 0x5100: parte+=2; if (parte>=partes) parte=partes-1; break; /* PGDN */
case '0': t = partes << 8;
for (i=0; i < t; i++) buffer[i]=0; break;
case 'x':
case 'X': t = partes << 8;
for (i=0; i < t; i++) buffer[i]=i; break;
case 'r':
case 'R': t = partes << 8;
for (i=0; i < t; i++) buffer[i]=rnd(256); break;
case 13: ventana (ABRIR, 29, 9, 50, 11, CVNS, CFVNS);
if (sp) cputs (" Nueva sección: ");
else cputs (" New section: ");
strcpy (cad, dec3strq(parte+1));
if (input (cad, 1, 3, CVNS, CFVNS)) parte = atoi(cad)-1;
if (parte>=partes) parte=partes-1; if (parte==-1) parte++;
ventana (CERRAR, 29, 9, 50, 11, 0, 0);
break;
case 'b':
case 'B': ventana (ABRIR, 21, 11, 56, 13, CVNB, CFVNB);
if (sp) cputs (" Nuevo tamaño del sector: ");
else cputs (" New sector size: ");
strcpy (cad, dec5strq(*bytes));
t=*bytes; /* bytes previos */
if (input (cad, 1, 5, CVNB, CFVNB)) *bytes = atol(cad);
if (*bytes > SMAX) *bytes=SMAX;
partes = (*bytes >> 8); if (*bytes & 0xFF) partes++;
if (parte>=partes) parte=partes-1; if (parte==-1) parte++;
ventana (CERRAR, 21, 11, 56, 13, 0, 0); CursorOff();
for (i=t; i < *bytes; i++) buffer[i]=0;
break;
case 9: ventana (ABRIR, 15, 7, 57, 11, CVMB, CFVMB);
if (sp) cputs (" Desplazamiento inicial (hex): ");
else cputs (" Initial offset (hex): ");
strcpy (cad, hex2str(desp/256));
strcat (cad, hex2str(desp % 256));
while (*cad == ' ') strcpy (cad, cad+1);
x = wherex(); y = wherey();
if (input (cad, 2, 4, CVMB, CFVMB)) {
desp = hextoi(cad);
if (desp < SMAX) {
gotoxy (x, y);
cputs(hex2str(desp/256)); cputs(hex2str(desp % 256));
gotoxy (2, 2);
if (sp) cputs ("Número de bytes a cambiar (dec): ");
else cputs ("Number of bytes to modify (dec): ");
strcpy (cad, dec5strq(nbytes));
if (input (cad, 1, 5, CVMB, CFVMB)) {
nbytes = atoi(cad);
gotoxy (2, 3);
if (sp) cputs ("Valor de relleno (hex): ");
else cputs ("Fill byte (hex): ");
strcpy (cad, hex2str(valor));
while (*cad == ' ') strcpy (cad, cad+1);
if (input (cad, 2, 2, CVMB, CFVMB)) {
valor = hextoi(cad);
CursorOff(); /* dar sensación de aceptación */
for (i=desp; (i<desp+nbytes) && (i<SMAX); i++)
buffer[i]=valor;
}
}
}
}
ventana (CERRAR, 15, 7, 57, 11, 0, 0);
break;
default: if ((t>='1') && (t<='9')) {
parte = t - '0' - 1;
if (parte>=partes) parte=partes-1; if (parte==-1) parte++;
}
break;
}
if (parte<0) parte=0;
} while ((t != 0x1B) && (t != 0x2D00));
}
void MotorOn (unidad)
{
int i;
/**** Evitar que la BIOS pare el motor (al menos en 14") ****/
pokeb(0x40,0x40,0xFF);
/**** Si no lo está, ponerlo en marcha y esperar 1 segundo ****/
if (((i=peekb(0x40, 0x3F)) & (1 << unidad))==0) {
outportb (FD_DOR, 1<<(unidad+4) | 4+8 | unidad);
pokeb (0x40, 0x3F, i | (1 << unidad));
delay (1000);
pokeb(0x40,0x40,0xFF);
}
}
void MotorOff()
{
pokeb(0x40,0x40,55); /* la BIOS lo detendrá en 55/18.2 segundos */
}
void outfdc (unsigned char dato) /* enviar byte al FDC */
{ /* no esperando más de 440 ms */
int t, i=0, rd;
do {
i++; t=peekb(0x40, 0x6C);
while ((t==peekb(0x40, 0x6C)) && ((rd=inportb(FD_STATUS)>>7)==0));
} while ((i<8) && !rd);
if (rd) outportb (FD_DATA, dato);
}
int infdc() /* leer byte del FDC */
{ /* no esperando más de 440 ms */
int t, i=0, rd;
do {
i++; t=peekb(0x40, 0x6C);
while ((t==peekb(0x40, 0x6C)) && ((rd=inportb(FD_STATUS)>>7)==0));
} while ((i<8) && !rd);
if (rd) return (inportb (FD_DATA)); else return (-1); /* fallo */
}
void EsperarInt() /* Esperar interrupción no más de 2 seg. */
{
int t, i=0;
do {
i++; t=peekb(0x40, 0x6C);
while ((t==peekb(0x40, 0x6C)) && (!(peekb(0x40, 0x3E) & 0x80)));
} while ((i<37) && (!(peekb(0x40, 0x3E) & 0x80)));
pokeb (0x40, 0x3E, peekb (0x40, 0x3E) & 0x7F);
}
void PreparaDma (rmodo, bytes, buffer)
unsigned rmodo, bytes;
char huge *buffer;
{
unsigned long dir;
unsigned dmapag, dmaoff;
dir = ((unsigned long) FP_SEG(buffer) <<4) + FP_OFF(buffer);
dmapag = dir >> 16; dmaoff = dir & 0xFFFF;
outportb (0x81, dmapag); /* registro de página del canal 2 */
outportb (0xB, rmodo); /* programar registro de modo */
outportb (0xC, 0); /* clear first/last flip-flop */
outportb (4,dmaoff & 0xFF); /* dirección base (parte baja) */
outportb (4,dmaoff >> 8); /* dirección base (parte alta) */
outportb (5,(bytes-1) % 256); /* nº de bytes menos 1 (parte baja) */
outportb (5,(bytes-1) / 256); /* nº de bytes menos 1 (parte alta) */
outportb (0xA, 2); /* habilitar canal 2 */
}
char *hex2str (int num)
{
static char cad[32];
char hexa[16]={'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
cad[0]=hexa[num >> 4];
cad[1]=hexa[num & 15];
cad[2]=0;
return (cad);
}
int hextoi (char *cad)
{
unsigned num=0, error=0;
char *p;
p=cad; while (*p) { if (*p > '9') *p = (*p & 0xDF) - 7; p++; }
p=cad; while (*p && !error) if ((*p<'0') || (*p>'?')) error++; else p++;
p=cad; while (*p) { num <<= 4; num |= *p-'0'; p++; }
if (!error) return (num); else return(0);
}