home *** CD-ROM | disk | FTP | other *** search
- {
- COMPILED ON TURBO PASCAL 3.xx for PC or MS-DOS
- this is sent in answer to Tom Douglass' letter to TUG issue 24 wanting to
- format a disk from a program. This is a routine I wrote to format and verify
- a disk. To make the disk usable you need to read the Boot Sector, the FAT,
- and the directory sectors from a formatted disk into some kind of data file
- and use the WRITESCT procedure below to write them to the correct place.
- There are no references to the WriteSct and ReadSct procedures in the program.
- They are provided so you can read the Boot,Fat,and Dir in and write them out.
- I realize this doesn't do everything Tom wanted but it should provide a good
- start. And Tom, If you do get this into one procedure to format a data disk,
- I could problably use it someday if you could send it to me.
- }
-
-
- program diskver;
- {
- this program was written by Michael Bush 1/5/87
- The purpose of this program is to verify the surface of the disk by putting
- a normal DOS format on the disk and then reading it back. It does NOT put
- Directory and FAT info on the disk. To use it to format this would be
- neccecary. It will destroy all data on the disk.
- }
- {$U+,C+}{allow user breaks}
- const drivea = 0;
- driveb = 1;
-
- type {these are field definitions for the format intterupt to use}
- FieldType = record
- Track,Head,Sector,Bytes:byte;
- end;
-
- AddressFieldsType = array[1..18] of FieldType;
-
- buffertype = array[1..9] of array[1..512] of byte;
-
- var HeadSettleOfs,HeadSettleSeg : integer;
- DiskPointerVectorOfs : integer absolute $0000:$0078;
- DiskPointerVectorSeg : integer absolute $0000:$007a;
- regs :record
- ax,bx,cx,dx,bp,si,di,ds,es,flags:integer;
- end;
- i,oldax :integer;
- track,head,drive,sector :integer;
- ok :boolean;
- ch :char;
- AddressFields :AddressFieldsType;
- Field :FieldType;
- buffer0,buffer1 :buffertype;
-
- procedure beep;
- begin
- sound(440);
- delay(100);
- nosound;
- end;
-
- procedure beeep;
- begin
- sound(880);
- delay(25);
- nosound;
- end;
-
- procedure diskspeed;
- {
- this procedure was written by Michael Bush 1/5/87
- The purpose of this program is to speed up diskcopy and format
- and other reads and writes of more than one track at a time
- }
- var
- b,srt:byte;
- begin
- b:=mem[DiskpointerVectorSeg:DiskPointerVectorOfs];
- b:= (b shl 4) shr 4;
- srt:=$D shl 4;{new Step Rate Time}
- b:=b+srt;
- mem[DiskpointerVectorSeg:DiskPointerVectorOfs]:=b;
-
- {new Head Settle Time}
- mem[DiskpointerVectorSeg:DiskPointerVectorOfs+9]:=00;
- end;
-
- procedure Verify(Track,head,drive:integer);
- begin
- with regs do begin
- ax:=$0409;{ah=command=verify sectors, al=# of sectors}
- {
- 0=reset, 1=read the status of the system into al, 2=read sectors,
- 3=write sectors, 4=verify sectors, 5=format track
- }
- head:=swap(head);
- dx:=drive+head;{dh=head, dl=drive=0=a:}
- track:=swap(track);
- cx:=track+$0001;{ch=track, cl=sector}
- {es:bx = address of buffer for read or write}
- end;
- intr($13,regs);{BIOS diskette interrupt}
- end;
-
- procedure readsct(drive,Track,head,sector:integer;var buf);
- var buffer : byte absolute buf;
- begin
- with regs do begin
- ax:=$0201;{ah=command=read sectors, al=# of sectors}
- {
- 0=reset, 1=read the status of the system into al, 2=read sectors,
- 3=write sectors, 4=verify sectors, 5=format track
- }
- head:=swap(head);
- dx:=drive+head;{dh=head, dl=drive=0=a:}
- track:=swap(track);
- cx:=track+sector;{ch=track, cl=sector}
- {es:bx = address of buffer for read or write}
- es:=seg(buffer);
- bx:=ofs(buffer);
- end;
- intr($13,regs);{BIOS diskette interrupt}
- end;
-
- procedure writesct(drive,Track,head,sector:integer;var buf);
- var buffer : byte absolute buf;
- begin
- with regs do begin
- ax:=$0309;{ah=command=verify sectors, al=# of sectors}
- {
- 0=reset, 1=read the status of the system into al, 2=read sectors,
- 3=write sectors, 4=verify sectors, 5=format track
- }
- head:=swap(head);
- dx:=drive+head;{dh=head, dl=drive=0=a:}
- track:=swap(track);
- cx:=track+sector;{ch=track, cl=sector}
- {es:bx = address of buffer for read or write}
- es:=seg(buffer);
- bx:=ofs(buffer);
- end;
- intr($13,regs);{BIOS diskette interrupt}
- end;
-
- procedure Format(Track,head,drive:integer;var AddrField);
- var AddressFields : byte absolute AddrField;
- begin
- with regs do begin
- ax:=$0509;{ah=command=format a track , al=# of sectors}
- {
- 0=reset, 1=read the status of the system into al, 2=read sectors,
- 3=write sectors, 4=verify sectors, 5=format track
- }
- {
- look at source code for jformat for clues as to how to format a disk
- }
- dx:=swap(head)+drive;{dl=head=0, dh=drive 0=a: 1=b:}
- track:=swap(track);
- cx:=track+$0001;{ch=track=0, cl=sector=01}
- {es:bx = address of buffer for read or write}
- es:=seg(AddressFields);
- bx:=ofs(AddressFields);
- end;
- intr($13,regs);{BIOS diskette interrupt}
- end;
-
- procedure SctErrChk;
- var
- err :boolean;
- ErrMsg:string[128];
- begin
- {
- regs.flags bits = 11=overflow, 10=direction, 9=interrupt, 8=Trap, 7=Sign
- 6=Zero, 4=Auxiliary carry, 2=Parity, 0=Carry
- }
- ErrMsg:='';
- if hi(regs.ax)=$20 then regs.ax:=$0200;
- err:=((regs.flags shl 15)shr 15)=1;
- if err then begin
- ok:=false;
- case hi(regs.ax) of
- $80:ErrMsg:='Attachment failed to respond';
- $40:ErrMsg:='SEEK operation failed';
- $20:ErrMsg:='Controller failure';
- $10:ErrMsg:='Bad CRC on diskette read';
- $08:ErrMsg:='DMA overrun on operation';
- $04:ErrMsg:='Requested sector not found';
- $03:ErrMsg:='Write attempt on write-protected diskette';
- $02:ErrMsg:='Address mark not found';
- else ErrMsg:='Unknown Error';
- end;
- beeep;
- writeln(ErrMsg,' on Track ',track);
- end;
- end;
-
- procedure ResetDisk(drive:integer);
- begin
- with regs do begin
- ax:=$0000;{ah=command=reset drive, al=#sectors=0}
- dx:=$0000+drive;{dl=head=0, dh=drive=a:}
- cx:=$0001;
- end;
- intr($13,regs);
- end;
-
- begin
- DiskSpeed;
- writeln(^G'Warning this program DESTROYS ALL DATA on the floppy disks');
- writeln('It alternates drives so both A: and B: will be formatted');
- writeln('use Ctrl-C or Break to stop');
- writeln('It will certify the surface (not the data) on that disk');
- writeln;
- write('Should I continue (Y/N)');
- repeat read(kbd,ch);ch:=upcase(ch);until ch in ['Y','N'];
- writeln;
- if ch ='Y' then begin
- {initialize the AddressFields for the format}
- Field.Track:=0;
- Field.Head:=0;
- Field.Sector:=1;
- Field.Bytes:=2;{2=512 bytes}
- for i:=1 to 9 do begin
- Field.Sector:=i;
- AddressFields[i]:=Field;
- end;
- field.head:=1;
- for i:=10 to 18 do begin
- field.sector:=i-9;
- AddressFields[i]:=field;
- end;
- drive:=1;
- repeat
- if drive=1 then drive:=0 else drive:=1;{alternate drives}
- ResetDisk(drive);
- ok:=true;
- track:=-1;
- repeat
- track:=track+1;
- for i:=1 to 18 do AddressFields[i].track:=track;
- Format(track,0,drive,addressfields[1]);
- SctErrChk;
- format(track,1,drive,addressfields[10]);
- SctErrChk;
- Verify(track,0,drive);
- SctErrChk;
- Verify(track,1,drive);
- SctErrChk;
- until not ok or(track>38);
- if not ok then writeln(^G,'This disk is bad.') else
- writeln('Disk ',chr(65+drive),': is Good.');
- writeln;
- beep;
- until true=false;
- end;
- end.
-