/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ\ ³ ³ ³ ÛÛÛÛÛ Û Û Ûßßßß ³ ³ Û ÛÛ ÛÛ Û ³ ³ ÛÛÛÛÛ Û Û Û Ûßß ³ ³ Û Û Û Û ³ ³ ÛÛÛÛÛ Û Û Û ³ ³ ³ ³ 2MF.C 2.1 - UTILIDAD DE FORMATEO DE DISQUETES 2M ³ ³ ³ ³ (c) 1994 Ciriaco Garc¡a de Celis. ³ ³ ³ ³ - Para Borland C++ 2.0 ¢ superior en modelo de memoria LARGE. ³ ³ - Este programa se compila abriendo un proyecto e introduciendo ³ ³ en ‚l 2MF.C, 2MFKIT.OBJ, 2MFBOTHD.OBJ y 2MFBOTDD.OBJ ³ ³ ³ ³ - NOTA: Las funciones de bajo nivel que acceden directamente a ³ ³ la controladora de disquetes no son indispensables, tan ³ ³ s¢lo se emplean para producir menos ruido al detectar ³ ³ la introducci¢n de un nuevo disquete en la unidad. ³ ³ ³ \ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/ #include #include #include #include #include #include #include unsigned _stklen=16384; #define MAXSECT 46 /* m ximo n£mero de sectores por pista */ #define MAXFAT 6128 /* mayor FAT de 12 bits posible */ #define FD_DATA 0x3F5 /* registro de datos del 765 */ #define FD_STATUS 0x3F4 /* registro principal de estado del 765 */ #define FD_DOR 0x3F2 /* registro de salida digital */ #define FD_DIR 0x3F7 /* registro de entrada digital (RD) */ #define FD_DCR 0x3F7 /* registro de control del disquete (WR) */ struct boot { /* sector arranque disquetes 2M */ unsigned char Salto[3], IdSis[8]; short BytesSect; char SectCluster; short SectReserv; char NumFats; short FichRaiz, NumSect; char MediaId; short SectFat, SectPista, Caras; long Especiales, Sect32; char Unidad, Reservado, Flag; long NumSerie; char Titulo[11], TipoFat[8]; char NoUsado; char CheckSum; char VersionFmt, FlagWr, VelPista0, VelPistaX; short OffsetJmp, OffsetPista0, OffsetPistaX, OffsetListaTam; char Resto[512-76]; }; struct parametros { /* par metros en l¡nea de comandos */ int Unidad, HD, ED, TipoFmt, NoVerify, MarcaPoco, Pistas, FichRaiz, Silencioso, NoPausa, X, Y, G; }; int HablaSp(), Hay2m(), Hay2mBoot(), FormatearDisco(), MarcaFat(), TipoDrive(), InicializaDisco(), EsperarCambioDisco(), infdc(); void Ayuda(), ProcesarParametros(), CrearSector0(), DiagnosticoError(), InformeError(), InformeDisco(), SonidoSube(), SonidoBaja(), SonidoError(), SonidoOn(), SonidoOff(), Sonido(), posicionar(), outfdc(), EsperarInt(); extern BootHDPrg, BootHDPrgLong, BootDDPrg, BootDDPrgLong, Boot2mCode, Boot2mLong, biosdsk(); extern void PicoRetardo(); int sp; /* 1-espa¤ol 0-ingl‚s */ unsigned char far *fat; /* para contener toda la FAT */ unsigned char far *buffer; /* para contener toda una pista */ unsigned long far *cbios=MK_FP(0x40, 0x6C); /* reloj del sistema */ unsigned char far *irq6=MK_FP(0x40, 0x3E); /* flag BIOS de IRQ6 */ void main (int argc, char **argv) { struct boot sector0; struct parametros cmd; int salir, result, sg; long bytes_err, dir; sp=HablaSp(); /* determinar idioma del pa¡s */ ProcesarParametros (argc, argv, &cmd); if (!Hay2m()) if (!Hay2mBoot()) { if (sp) printf(" 2M ¢ 2MX 2.1 no est  instalado, imposible formatear.\n"); else printf(" 2M or 2MX 2.1 is not installed, impossible to format.\n"); exit(128); } else { if (sp) printf(" Modo SuperBOOT: instale 2M para dar formato.\n"); else printf(" SuperBOOT mode: needed to install 2M to format.\n"); exit(127); } if (((fat=farmalloc( (unsigned long) MAXFAT))==NULL) || ((buffer=farmalloc( (unsigned long) MAXSECT<<10))==NULL)) { if (sp) printf(" Memoria insuficiente.\n"); else printf(" Insufficient memory.\n"); exit(126); } /* Definir el buffer para que no cruce una frontera de DMA */ dir = ((unsigned long) FP_SEG(buffer) <<4) + FP_OFF(buffer); if ((dir >> 16) != ((dir + ((unsigned long) MAXSECT << 9)) >> 16)) buffer+=(unsigned long) MAXSECT << 9; if (!cmd.NoPausa) { if (sp) printf(" Pulsa una tecla para formatear en"); else printf(" Press any key to format on"); printf(" %c:", cmd.Unidad+'A'); salir=getch()==27; } else salir=0; while (!salir) { CrearSector0 (§or0, cmd); if (!cmd.Silencioso) SonidoSube(); switch (result=FormatearDisco (§or0, &cmd, &bytes_err, &sg)) { case 0: InformeDisco (§or0, bytes_err, sg); if (!cmd.Silencioso) SonidoBaja(); break; case 1: DiagnosticoError (result); break; default: DiagnosticoError (result); if (!cmd.Silencioso) SonidoError(); break; } if (sp) printf("\n Introduce otro disquete para formatear en"); else printf("\n Please insert another disk to format in"); printf(" %c:", cmd.Unidad+'A'); if (!EsperarCambioDisco(cmd.Unidad)) salir=1; } printf("\r \r"); } void ProcesarParametros(int argc, char **argv, struct parametros *cmd) { int pm, error=0, hlp=0, id=1; cmd->Unidad=cmd->TipoFmt=cmd->ED=cmd->NoVerify=cmd->MarcaPoco=0; cmd->HD=1; cmd->Pistas=82; cmd->FichRaiz=cmd->Silencioso=cmd->NoPausa=0; cmd->X=cmd->Y=cmd->G=-1; for (pm=1; pmUnidad=*argv[pm]-'A'; else if (strstr(argv[pm],"/DD")!=NULL) cmd->HD=0; else if (strstr(argv[pm],"/D0")!=NULL) cmd->HD=2; else if (strstr(argv[pm],"/D1")!=NULL) cmd->HD=3; else if (strstr(argv[pm],"/F")!=NULL) cmd->TipoFmt=0; else if (strstr(argv[pm],"/M")!=NULL) cmd->TipoFmt=1; else if (strstr(argv[pm],"/E")!=NULL) cmd->ED=1; else if (strstr(argv[pm],"/N")!=NULL) cmd->NoVerify=1; else if (strstr(argv[pm],"/W")!=NULL) cmd->MarcaPoco=1; else if (strstr(argv[pm],"/T")!=NULL) cmd->Pistas = atoi (&argv[pm][3]); else if (strstr(argv[pm],"/R")!=NULL) cmd->FichRaiz = atoi (&argv[pm][3]); else if (strstr(argv[pm],"/S")!=NULL) { cmd->Silencioso=1; id++; } else if (strstr(argv[pm],"/K")!=NULL) cmd->NoPausa=1; else if (strstr(argv[pm],"/X")!=NULL) cmd->X=atoi(&argv[pm][3]); else if (strstr(argv[pm],"/Y")!=NULL) cmd->Y=atoi(&argv[pm][3]); else if (strstr(argv[pm],"/G")!=NULL) cmd->G=atoi(&argv[pm][3]); else if (strstr(argv[pm],"/I")!=NULL) { sp^=1; id++; } else error=1; } if (cmd->ED && (cmd->HD!=1)) cmd->HD=1; /* /DD ¢ /Dx + /E = /E */ if ((argc<=1) || (argc==id)) hlp++; if (hlp) Ayuda(); if (sp) printf("\n2MF 2.1 - Utilidad de formateo de disquetes 2M (ESC Salir)\n"); else printf("\n2MF 2.1 - Format utility program for 2M diskettes (ESC Aborts)\n"); if (error) { if (sp) printf(" Error de sintaxis. Ejecute 2MF /?.\n"); else printf(" Incorrect parameter(s). Execute 2MF /?.\n"); exit (2); } if (TipoDrive(cmd->Unidad)==0) { if (sp) printf(" La unidad f¡sica indicada no existe.\n"); else printf(" Physical drive indicated does not exist.\n"); exit (2); } if ((TipoDrive(cmd->Unidad)!=2) && (TipoDrive(cmd->Unidad)<4)) { if (sp) printf(" La unidad indicada no es de alta densidad.\n"); else printf(" Drive indicated it is not high density one.\n"); exit (2); } if ((TipoDrive(cmd->Unidad)<5) && (cmd->ED==1)) { if (sp) printf(" Necesaria unidad de 2.88M para formato ED.\n"); else printf(" Needs a 2.88M drive to perform ED format.\n"); exit (2); } if ((cmd->Pistas<80) || (cmd->Pistas>86)) { if (sp) printf(" Error: N£mero de pistas incorrecto.\n"); else printf(" Error: Incorrect number of tracks.\n"); exit (2); } if (cmd->FichRaiz && ((cmd->FichRaiz<1) || (cmd->FichRaiz>240))) { if (sp) printf(" Error: N§ de ficheros en directorio raiz err¢neo.\n"); else printf(" Error: Bad number of files in root directory.\n"); exit (2); } } void Ayuda(void) { if (sp) { printf("\n\n" " 2MF 2.1 - UTILIDAD ESTANDAR DE FORMATEO DE DISQUETES PARA 2M\n" " (c) 1994 Ciriaco Garc¡a de Celis - Grupo Universitario de Inform tica\n" " C/Renedo, 2, 4-C; 47005 Valladolid (Espa¤a) - ciri@gui.uva.es - 2:341/21.8\n\n" " 2MF U: [/DD] [/F|M] [/E] [/N] [/T=nn] [/R=nn] [/S] [/K]\n\n" " Este programa formatea disquetes a una mayor capacidad y/o velocidad de la\n" " normal. Para que estos nuevos disquetes funcionen debe estar instalado 2M en\n" " memoria. Alternativamente, si son de alta densidad se pueden dejar dentro de\n" " la unidad A: y reinicializar el ordenador, que botar  pese a todo del disco\n" " duro y podr  acceder a los disquetes 2M sin problemas en lectura y escritura\n" " normales. Este programa es gratu¡to y de tipo ®CARDWARE¯. Opciones:\n\n" " /DD Solicita un formateo en doble densidad -por defecto se hace en alta-.\n" " /F Disquetes r pidos y seguros -por defecto- (5¬:820-1476K, 3«:984-1804K).\n" " /M Formatear disquetes a la m xima capacidad (5¬:902-1558K, 3«:1066-1886K).\n" " /E Formatear disquetes de 3«-ED (3608K por defecto o 3772K indicando /M).\n" " /N No verificar el disquete destino (peligroso en modo /M).\n\n" " /T Modificar el n£mero de pistas por defecto (80-86).\n" " /R Modificar el n£mero de ficheros permitidos en directorio ra¡z (1-240).\n" " /S Funcionamiento silencioso sin emitir sonido.\n" " /K No realizar pausa inicial antes de comenzar.\n"); } else { printf("\n\n" " 2MF 2.1 - STANDARD FORMAT UTILITY FOR 2M DISKETTES\n" " (c) 1994 Ciriaco Garc¡a de Celis - Grupo Universitario de Inform tica\n" " C/Renedo, 2, 4-C; 47005 Valladolid (Spain) - ciri@gui.uva.es - 2:341/21.8\n\n" " 2MF U: [/DD] [/F|M] [/E] [/N] [/T=nn] [/R=nn] [/S] [/K]\n\n" " This program formats diskettes at a higher capacity and/or speed than the\n" " normal ones. 2M must be installed on memory to provide support for the new\n" " diskettes. Also, high-density diskettes can be left into A: drive and then\n" " computer can be rebooted: really it will boot from hard disk and after this\n" " moment 2M diskettes will be supported in the standard read-write operation.\n" " 2MF is a 100%% CARDWARE utility. Meaning of switches:\n\n" " /DD Request a double-density format (by default it will be high-density).\n" " /F Fast and secure diskettes -by default- (5¬:820-1476K, 3«:984-1804K).\n" " /M Formats diskettes up to maximum capacity (5¬:902-1558K, 3«:1066-1886K).\n" " /E Formats 3.5-ED diskettes at 3608K (or 3772K if /M option enabled).\n" " /N Do not verify target diskette (dangerous in /M mode).\n\n" " /T Sets the number of tracks to be used (80-86).\n" " /R Sets the number of root directory entries (1-240).\n" " /S Tells 2MF not to make sound effects.\n" " /K No initial pause before formatting.\n"); } exit (1); } int Hay2m() /* devolver 1 si 2M est  instalado */ { int entrada, instalado=0; union REGS r; struct SREGS s; for (entrada=0xc0; (entrada<=0xff) && (!instalado); entrada++) { r.x.ax=entrada << 8; s.es=0x1492; r.x.di=0x1992; int86x (0x2f, &r, &r, &s); if (r.x.ax==0xFFFF) if ((peek(s.es,r.x.di-4)==9002) && (peek(s.es,r.x.di-2)==10787)) if (strstr (MK_FP(s.es, r.x.di),"2M:2.1")) instalado=1; if (strstr (MK_FP(s.es, r.x.di),"2MX:2.1")) instalado=1; } return (instalado); } int Hay2mBoot() /* devolver 1 si 2M instalado en modo SuperBOOT */ { return (strstr(MK_FP(((unsigned) peek(0x40, 0x13) * 64), 4), "2M-STV")!=NULL); } void CrearSector0 (struct boot *s0, struct parametros cmd) { unsigned tipo, tabla, i, j, k, m, t, s, tam, ini, fin, inc; char id[8]="2M-STV00", ch, sum, far *p; static unsigned char infofis [2][3][2][4][20] = {{{{{10,176,7,0,1,1}, {9,80,1,1}, /* 5¬-DD /F */ {5,100,3,1,1} }, {{11,176,7,1,1,1}, {9,80,1,1}, /* /M */ {32,4,5,3,1,4,2,0}, {4,2,4,3,0} }}, {{{18,224,7,0,0,0}, {16,60,1,1}, /* 5¬-HD /F */ {9,50,3,1,2} }, {{19,224,7,1,0,0}, {17,25,1,2}, /* /M */ {53,3,6,4,1,5,2,6,3}, {4,4,2,4,4,3} }}, {{{0,0,0,0,0,0}, {0,0,0,0}, /* no usado */ {0,0,0,0,0}, }, {{14,192,7,1,2,1}, {9,80,1,1}, /* 3«-DD /D1 */ {38,2,4,3,1,4,2}, {4,3,4,4} }}}, {{{{12,192,7,0,2,1}, {9,80,1,1}, /* 3«-DD /F */ {6,100,3,1,1} }, {{13,192,7,1,2,1}, {9,80,1,1}, /* /M */ {38,5,6,3,1,4,2,0,0}, {4,2,4,4,0,0} }}, {{{22,224,7,0,0,0}, {19,70,1,1}, /* 3«-HD /F */ {11,40,3,1,2} }, {{23,224,7,1,0,0}, {19,70,1,1}, /* /M */ {64,3,7,4,1,5,2,6,3,7}, {4,4,4,4,4,3,2} }}, {{{44,240,7,0,3,3}, {36,108,1,1}, /* 3«-ED /F */ {11,126,4,1,2} }, {{46,240,7,1,3,3}, {36,108,1,1}, /* /M */ {127,5,12,1,7,2,8,3,9,4,10,5,11,6,12}, {4,4,4,4,4,4,4,4,4,4,4,3} }}}}; /* Significado de la tabla /F: {SectLogPistaX, fichraiz, verFmt, flagWr, velpista0, velpistaX}, {sectpista0, GAP3pista0, primsectpista0, interleavepista0}, {SectFisPistaX, GAP3pistaX, tamsectpistaX, /X, /Y} Significado de la tabla /M: {SectLogPistaX, fichraiz, verFmt, flagWr, velpista0, velpistaX}, {sectpista0, GAP3pista0, primsectpista0, interleavepista0}, {Sectpreformat, GAP3pistaX, SectFisPistaX, sects numerados...}, {tama¤os de sectores por orden...} */ if ((cmd.HD==2) && (TipoDrive(cmd.Unidad)>=4)) { cmd.HD=0; tabla=0; tipo=0; infofis[0][0][cmd.TipoFmt][0][4]=2; /* 3«-DD a 250 Kbps */ infofis[0][0][cmd.TipoFmt][0][5]=2; } else if ((cmd.HD==3) && (TipoDrive(cmd.Unidad)>=4)) { cmd.HD=tipo=0; cmd.TipoFmt=1; tabla=2; /* 3«-DD con 1148K */ } else { if (cmd.HD>1) cmd.HD=0; tabla=cmd.HD+cmd.ED; /* seleccionar tabla de datos */ if (TipoDrive(cmd.Unidad)<3) tipo=0; /* 5¬ */ else tipo=1; /* 3« */ } s0->NoUsado=0; ch=1+cmd.HD; if (TipoDrive(cmd.Unidad)>2) ch+=2; if (!cmd.TipoFmt) ch+=4; if (cmd.ED) ch=10-cmd.TipoFmt; id[6]=(ch/10)+'0'; id[7]=(ch % 10)+'0'; strncpy (s0->IdSis, id, 8); s0->BytesSect=512; s0->SectCluster = s0->SectReserv = 1; s0->NumFats=2; if (cmd.ED) s0->SectCluster=2; if (!cmd.FichRaiz) s0->FichRaiz=infofis[tipo][tabla][cmd.TipoFmt][0][1]; else if (cmd.FichRaiz % 16) s0->FichRaiz=((cmd.FichRaiz >> 4) + 1) << 4; else s0->FichRaiz=cmd.FichRaiz; if (ch==6) s0->MediaId=0xF0; /* compatible SCANDISK */ else s0->MediaId=0xFA; /* compatible SCANDISK */ s0->SectPista=infofis[tipo][tabla][cmd.TipoFmt][0][0]; s0->Caras=2; s0->NumSect=cmd.Pistas*s0->Caras*s0->SectPista; j = 3 * (s0->NumSect - (s0->FichRaiz>>4) - 1); k = 6 + 1024 * s0->SectCluster; s0->SectFat = j/k; if (j % k) s0->SectFat++; s0->Unidad = s0->Reservado = 0; s0->Especiales = s0->Sect32 = 0L; s0->Flag=0x29; randomize(); for (i=0; i<4; i++) s0->NumSerie = (s0->NumSerie<<8) | (unsigned char) random(32767); strncpy (s0->Titulo, "NO NAME ", 11); strncpy (s0->TipoFat, "FAT12 ", 8); s0->VersionFmt=infofis[tipo][tabla][cmd.TipoFmt][0][2]; s0->FlagWr=infofis[tipo][tabla][cmd.TipoFmt][0][3]; s0->VelPista0=infofis[tipo][tabla][cmd.TipoFmt][0][4]; s0->VelPistaX=infofis[tipo][tabla][cmd.TipoFmt][0][5]; tam=76; /* lo que precede a la primera tabla */ s0->OffsetPista0=tam; s0->Resto[0]=infofis[tipo][tabla][cmd.TipoFmt][1][0]; s0->Resto[1]=infofis[tipo][tabla][cmd.TipoFmt][1][1]; ch=infofis[tipo][tabla][cmd.TipoFmt][1][2]; inc=infofis[tipo][tabla][cmd.TipoFmt][1][3]; ini=tam+2; fin=ini+s0->Resto[0]; k=0; for (i=j=0; jResto[0]; j++) { s0->Salto[ini+i]=ch++; if (ch>s0->Resto[0]) ch=1; i+=inc; if (ini+i>=fin) i=++k; } ini=fin; s0->OffsetPistaX=ini; if (!s0->FlagWr) { k=infofis[tipo][tabla][cmd.TipoFmt][2][0]; j=5; for (i=0; iSalto[ini+i]=infofis[tipo][tabla][cmd.TipoFmt][2][i]; if (cmd.X!=-1) s0->Salto[ini+3]=cmd.X; if (cmd.Y!=-1) s0->Salto[ini+4]=cmd.Y; } else { k=infofis[tipo][tabla][cmd.TipoFmt][2][2]; j=(k+1)*3; for (i=0; i<3; i++) s0->Salto[ini+i]=infofis[tipo][tabla][cmd.TipoFmt][2][i]; m=129; for (i=3; i<=k*3; i+=3) { s0->Salto[ini+i]=m; s=infofis[tipo][tabla][cmd.TipoFmt][2][i/3+2]; s0->Salto[ini+i+1]=s; t=infofis[tipo][tabla][cmd.TipoFmt][3][s-1]; switch (t) { case 0: m+=1; break; case 1: m+=2; break; case 2: m+=3; break; case 3: m+=6; break; case 4: m+=11; break; case 5: m+=22; break; } s0->Salto[ini+i+2]=t; } } if (cmd.G!=-1) s0->Salto[ini+1]=cmd.G; fin=ini+j; ini=fin; s0->OffsetListaTam=ini; if (!s0->FlagWr) for (i=0; iSalto[ini+i]=infofis[tipo][tabla][cmd.TipoFmt][2][2]; else for (i=0; iSalto[ini+i]=infofis[tipo][tabla][cmd.TipoFmt][3][i]; fin=ini+k; ini=fin; s0->OffsetJmp=ini; s0->Salto[0]=0xE9; s0->Salto[1]=(ini-3) % 256; s0->Salto[2]=(ini-3) >> 8; if (cmd.HD == 0) { p=(char far *) &BootDDPrg; k=BootDDPrgLong; } else { p=(char far *) &BootHDPrg; k=BootHDPrgLong; } for (i=0; (iSalto[ini+i]=*p++; fin=ini+i; for (i=fin; i<510; i++) s0->Salto[i]=0; if (fin<497) strncpy (&s0->Salto[496], "Made in Spain", 13); s0->Salto[509]=0; s0->Salto[510]=0x55; s0->Salto[511]=0xAA; for (sum=0, j=64; jSalto[j]; /* checksum */ s0->CheckSum=-sum; } int FormatearDisco (sector0, cmd, bytes_defectuosos, segundos) struct boot *sector0; struct parametros *cmd; long *bytes_defectuosos; int *segundos; { unsigned long dir, tiempo, rest, tini, hist[86], i; int cilindros, cilindro, cabezal, intento, error=1, spista, t; unsigned long fase, fases; if (cmd->G!=-1) if (sp) printf("\r AVISO: ­Valor de GAP alterado con opci¢n /G!\n"); else printf("\r WARNING: GAP value modified with /G switch!\n"); if (cmd->HD>1) if (sp) printf("\r AVISO: ­Par metro indocumentado /D%d activo!\n", cmd->HD-2); else printf("\r WARNING: Undocumented /D%d switch activated!\n", cmd->HD-2); if (cmd->MarcaPoco) if (sp) printf("\r AVISO: ­Par metro indocumentado /W activo!\n"); else printf("\r WARNING: Undocumented /W switch activated!\n"); if ((cmd->X!=-1) || (cmd->Y!=-1)) if (sp) printf("\r AVISO: ­Par metro indocumentado /X ¢ /Y activo!\n"); else printf("\r WARNING: Undocumented /X or /Y switch activated!\n"); if (sp) printf("\r Formateo de disquete "); else printf("\r Formatting "); switch (TipoDrive (cmd->Unidad)) { case 2: printf("%s", cmd->HD==1?"5¬-1.2M":"5¬-360K"); break; case 4: printf("%s", cmd->HD==1?"3«-1.44M":"3«-720K"); break; default: if (cmd->ED) printf("3«-2.88M"); else printf("%s", cmd->HD==1?"3«-1.44M":"3«-720K"); } if (sp) printf(" en %c: con %dK \n", cmd->Unidad+'A', sector0->NumSect>>1); else printf(" diskette on %c: with %dK \n", cmd->Unidad+'A', sector0->NumSect>>1); for (i=0; iMediaId; fat[1]=fat[2]=0xFF; for (i=0; i < ((unsigned long) MAXSECT <<9); i++) buffer[i]=0; cilindros=sector0->NumSect/(sector0->SectPista*sector0->Caras); spista=sector0->SectPista; *bytes_defectuosos=0L; fases=1L*cilindros*sector0->Caras*(1+(1-cmd->NoVerify)+sector0->FlagWr); fase=0L; tini=*cbios; for (cilindro=0; cilindro < cilindros; cilindro++) { for (cabezal=0; cabezalCaras; cabezal++) { for (intento=0; intento<3; intento++) { if (sp) printf("\r Cilindro %2d - Cara %d [F-] %3lu%%", cilindro, cabezal, fase*100/fases); else printf("\r Cylinder %2d - Side %d [F-] %3lu%%", cilindro, cabezal, fase*100/fases); if (error) biosdsk (0, cmd->Unidad); t=0; while (bioskey(1)) t=bioskey(0); if ((t & 0xFF)==0x1B) { error=1; goto AbortFormat; } else if ((t==0x1000) && (cilindro>1)) goto FinFormat; error=biosdsk (5, cmd->Unidad, cabezal, cilindro, 0, 0x7F, sector0); if (sector0->FlagWr==1) if (!error && (cilindro | cabezal)) { printf ("\b\b\b\b\b\b\b\b\bI-] %3lu%%",(fase+1)*100/fases); error=biosdsk (3, cmd->Unidad, cabezal | 0x80, cilindro, 1, spista, buffer); } if (!error&&(!cmd->NoVerify||(cmd->NoVerify && cilindro<2))) { printf ("\b\b\b\b\b\b\b\b\b-V] %3lu%%", (fase+1+sector0->FlagWr)*100/fases); error=biosdsk (2, cmd->Unidad, cabezal, cilindro, 1, spista, buffer); } if (!error) break; } if (error) if ((error==128) || (error==3) || (error==6)) goto AbortFormat; /* error fatal */ else if (!MarcaFat(cmd->Unidad, cmd->MarcaPoco, sector0, cilindro, cabezal, fat, bytes_defectuosos)) goto AbortFormat; /* error en  reas del sistema */ fase+=(1+(1-cmd->NoVerify)+sector0->FlagWr); } hist[cilindro]=*cbios; tiempo=(*cbios-tini)*10/182; printf(" [%2lu:%02lu ]", tiempo/60, tiempo % 60); if (cilindro>5) { rest=(*cbios-hist[cilindro-5])*(cilindros-cilindro)*10/910; printf("\b+%2lu:%02lu =%2lu:%02lu ]", rest/60, rest % 60, (tiempo+rest)/60, (tiempo+rest) % 60); } } FinFormat: error=InicializaDisco (cmd->Unidad, sector0, fat); AbortFormat: printf("\r"); for (i=0; i<79; i++) printf(" "); *segundos=(*cbios-tini)*10/182; return (error); } void InformeDisco (struct boot *s0, long bd, int tiempo) { unsigned long st, ua, bt; st = s0->NumSect - s0->NumFats * s0->SectFat - s0->SectReserv - (s0->FichRaiz>>4); ua = st / (unsigned long) s0->SectCluster; bt = st*512L; if (sp) { printf ("\r Tiempo transcurrido formateando %2d:%02d\n", tiempo/60, tiempo % 60); printf (" Vol£men con n£mero de serie %04X-%04X\n", (int) (s0->NumSerie >> 16), (int) s0->NumSerie); printf ("%9d ficheros permitidos en el ra¡z.\n", s0->FichRaiz); printf ("%9d unidades de asignaci¢n.\n", ua); printf ("%9d bytes por unidad de asignaci¢n.\n", s0->SectCluster*512); printf ("%9lu bytes totales en el disco.\n", bt); printf ("%9lu bytes en sectores defectuosos.\n", bd); printf ("%9lu bytes disponibles en el disco.\n", bt-bd); } else { printf ("\r Time elapsed in the process %2d:%02d\n", tiempo/60, tiempo % 60); printf (" Volume serial number is %04X-%04X\n", (int) (s0->NumSerie >> 16), (int) s0->NumSerie); printf ("%9d file capacity of root directory.\n", s0->FichRaiz); printf ("%9d total clusters on disk.\n", ua); printf ("%9d bytes per cluster.\n", s0->SectCluster*512); printf ("%9lu total bytes on disk.\n", bt); printf ("%9lu bytes on bad sectors.\n", bd); printf ("%9lu bytes available on disk.\n", bt-bd); } } void DiagnosticoError (int codigo) { if (sp) { switch (codigo) { case 1: printf("\r Formateo interrumpido por el usuario."); break; case 2: printf("\r La densidad seleccionada es incorrecta."); break; case 3: printf("\r Disquete protegido contra escritura."); break; case 6: case 128: printf("\r Unidad no preparada (¨puerta abierta?)."); break; default: printf("\r Anomal¡a general: ¨densidad incorrecta?."); break; } } else { switch (codigo) { case 1: printf("\r Format aborted by user."); break; case 2: printf("\r Selected density is incorrect."); break; case 3: printf("\r Diskette is write-protected."); break; case 6: case 128: printf("\r Drive not ready (door open?)."); break; default: printf("\r General failure: incorrect density?."); break; } } printf(" \n"); } int MarcaFat (unidad, modosuave, sector0, cil, cab, fat, bytes_mal) struct boot *sector0; int unidad, modosuave, cil, cab; unsigned char far *fat; long *bytes_mal; { unsigned malclus, i, ini, tamsys; tamsys = sector0->NumFats*sector0->SectFat+(sector0->FichRaiz>>4)+1; for (i=1; i<=sector0->SectPista; i++) { ini=(cil*sector0->Caras+cab)*sector0->SectPista+i-1; if (modosuave) malclus=biosdsk (2, unidad, cab, cil, i, 1, buffer); else malclus=1; /* por defecto marcar la pista entera */ if (malclus) { if (iniSectCluster*512L; ini-=tamsys; ini=ini/sector0->SectCluster+2; if (ini % 2) { /* posici¢n impar */ fat [ini*3/2] = fat [ini*3/2] & 0x0F | 0x70; fat [ini*3/2+1] = 0xFF; } else { /* posici¢n par */ fat [ini*3/2] = 0xF7; fat [ini*3/2+1] = fat [ini*3/2+1] & 0xF0 | 0x0F; } ini=0x7FFF; } } return (ini>=tamsys); } int TipoDrive (int unidad) { union REGS r; r.h.ah=8; r.h.dl=unidad; int86 (0x13, &r, &r); return ((unsigned char) r.h.bl); } InicializaDisco (unidad, sector0, fat1) int unidad; struct boot *sector0; unsigned char far *fat1; { unsigned char far *p; int sectpista0=sector0->Salto[sector0->OffsetPista0]; p=buffer; memcpy (p, sector0, 512); /* BOOT f¡sico */ p+=512; memcpy (p, fat1, sector0->SectFat*512); /* FAT1 (la 2 emulada) */ p+=sector0->SectFat*512; memcpy (p, sector0, 512); /* BOOT virtual */ p+=512; memcpy (p, &Boot2mCode, Boot2mLong); /* c¢digo SuperBOOT */ biosdsk (0, unidad); return (biosdsk(3, unidad, 0x80, 0, 1, sectpista0, buffer)); } void SonidoSube() { int frec=50; SonidoOn(); while (frec<5000) { Sonido (frec); PicoRetardo(); Sonido (frec+1000); PicoRetardo(); frec+=10; } SonidoOff(); } void SonidoBaja() { int frec=6000; SonidoOn(); while (frec>1050) { Sonido (frec); PicoRetardo(); Sonido (frec-1000); PicoRetardo(); frec-=10; } SonidoOff(); } void SonidoError() { int frec1=50, frec2=6000; SonidoOn(); while (frec1<5000) { Sonido (frec1); PicoRetardo(); Sonido (frec1+1000); PicoRetardo(); Sonido (frec2); PicoRetardo(); Sonido (frec2-1000); PicoRetardo(); frec1+=10; frec2-=10; } SonidoOff(); } void SonidoOn() { disable(); outportb (0x61, inportb (0x61) | 3); enable(); outportb (0x43, 182); /* preparar canal 2 */ } void SonidoOff() { disable(); outportb (0x61, inportb (0x61) & 0xFC); enable(); } void Sonido (int frecuencia) { unsigned periodo; periodo=1193180L/frecuencia; outportb (0x42, periodo & 0xFF); outportb (0x42, periodo >> 8); } int EsperarCambioDisco (int unidad) { int i; long hora; while (bioskey(1)) (void) bioskey(0); /* limpiar buffer teclado */ pokeb(0x40,0x3F, peekb(0x40, 0x3F) & 0xF0); /* "motores apagados" */ do { /* esperar que retiren el disquete */ hora=*cbios+5; while (*cbios> 7) | bioskey(1); } while (!i); /* intento de bajar la l¡nea de cambio */ while (i && !bioskey(1)) { /* y parpadeo del LED */ hora=*cbios+7; pokeb (0x40, 0x40, 0xFF); /* para BIOS pelmas no est ndar */ outportb (FD_DOR,(1<<(unidad+4)) | unidad | 4+8); /* encender */ posicionar (unidad, 1); while ((*cbios> 7; /* leer l¡nea de cambio */ outportb (FD_DOR, unidad | 4+8); /* apagar motor */ while ((*cbios>7)==0)); } while ((i<8) && !rd); if (rd) outportb (FD_DATA, dato); } int infdc (void) /* leer byte del FDC */ { /* no esperando m s de 440 ms */ int i=0, rd; long t; do { i++; t=*cbios; while ((t==*cbios) && ((rd=inportb(FD_STATUS)>>7)==0)); } while ((i<8) && !rd); if (rd) return (inportb (FD_DATA)); else return (-1); /* fallo */ } void EsperarInt (void) /* Esperar interrupci¢n no m s de 2 seg. */ { int i=0; long t; do { i++; t=*cbios; while ((t==*cbios) && !(*irq6 & 0x80)); } while ((i<37) && !(*irq6 & 0x80)); *irq6=*irq6 & 0x7F; } 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); }