home *** CD-ROM | disk | FTP | other *** search
-
- {* ------------------------------------------------------------------------- *}
- {* M S - D O S F I L E M A N A G E R U T I L I T I E S
- {* ------------------------------------------------------------------------- *}
-
- procedure DisplayMsdosDiskParameters ;
- {*
- * Display the physical parameters of the last, which is possibly also
- * the current MS-DOS disk read.
- *}
- begin
- DisplayTitle( 'MS-DOS disk parameters' ) ;
- Write ( ^M^J'Disk parameters of the ' ) ;
- if MsdosDriveName='?' then
- Write( 'last' )
- else
- Write( 'current' ) ;
- WriteLn( ' MS-DOS disk.'^M^J ) ;
- WriteLn( 'System Identification = ', SystemIdent ) ;
- WriteLn( 'Media descriptor = $', Hex(FormatIdent,2) ) ;
- WriteLn ;
- WriteLn( '# bytes per sector = ', BytesPerSector:4 ) ;
- WriteLn( '# sectors per track = ', SectorsPerTrack:4 ) ;
- WriteLn( '# heads = ', SidesPerDisk:4 ) ;
- WriteLn( '# sectors per disk = ', SectorsPerDisk:4 ) ;
- WriteLn( '# cylinders per disk = ', CylindersPerDisk:4 ) ;
- WriteLn ;
- WriteLn( '# sectors per FAT = ', SectorsPerFat:4 ) ;
- WriteLn( '# sectors per cluster = ', SectorsPerCluster:4 ) ;
- WriteLn( '# FATs = ', FatsPerDisk:4 ) ;
- WriteLn( '# reserved sectors = ', FirstFatSector:4 ) ;
- WriteLn ;
- Continue ;
- end ; { of DisplayMsdosDiskParameters }
-
- function GetMsdosFreeSpace: Integer ;
- {*
- * Return the amount of free space, in Kbyte, on the MS-DOS disk.
- *}
- const
- BytesPerKilo= 1024 ; { One KByte }
- var
- FreeClusters: Integer ; { Counter of free clusters }
- I : Integer ; { Loop control variable }
- begin
- FreeClusters:= 0 ;
- for I:= 2 to ClustersPerDisk do
- if GetFatEntry(I)=0 then
- FreeClusters:= Succ( FreeClusters ) ;
- {*
- * Compute the free disk space in KiloBytes. Note that the parenthesis
- * in the next expression are needed to prevent integer overflow!
- *}
- GetMsdosFreeSpace:= FreeClusters*(SectorsPerCluster*BytesPerSector div
- BytesPerKilo) ;
- end ; { of GetMsdosFreeSpace }
-
- procedure UnInstallMsdosDrive ;
- {*
- * Remove the MS-DOS DPB from the BIOS internal tables and restore the
- * original CP/M DPB.
- *}
- begin
- if MsdosDriveName<>'?' then
- begin
- MsdosDpb^ := SavedDpb ; { Restore XLT and DPB }
- MsdosDpb := Nil ; { Remove pointer }
- MsdosDriveName := '?' ; { Signal absence of MS-DOS drive }
- MsdosDriveAddress:= 254 ; { Remove allocation of physical drive }
- end ; { of if }
- end ; { of UnInstallMsdosDrive }
-
- procedure InstallMsdosDrive ;
- {*
- * Install the MS-DOS drive in BIOS. The disk parameters are read from the
- * bootsector on the disk. Then the fields within the CP/M DPB are modified
- * accordingly. Thus upon successfull completion of this routine, BIOS is
- * set up to read and write the MS-DOS disk.
- *
- * This routine will fail if one of the following conditions occur:
- * - The bootsector cannot be read from the disk. A possible cause is that
- * there is no disk inserted in the disk drive.
- * - The parameters of the disk and the drive are not compatible: either the
- * number of cylinders or the number of heads of the disk drive is less
- * than required to read the floppy disk.
- *
- * In case of an error is detected, the global error flag is set and this
- * procedure will leave the DPB in an undetermined state!
- *
- * CAUTION : This procedure is very system dependent! It sets the various
- * fields in the extension of the DPB.
- *}
- type
- MsdosBoots = record { Layout of the MS-DOS boot sector }
- BJumpCode : array[0..2] of byte ;
- BSystemIdent : array[0..7] of char ;
- BBytesPerSector : Integer ;
- BSectorsPerCluster: Byte ;
- BReservedSectors : Integer ;
- BFatsPerDisk : Byte ;
- BEntriesInRoot : Integer ;
- BSectorsPerDisk : Integer ;
- BFormatIdent : Byte ;
- BSectorsPerFat : Integer ;
- BsectorsPerTrack : Integer ;
- BSidesPerDisk : Integer ;
- BSpecResvSectors : Integer ;
- end ; { of MsdosBoot record }
-
- var
- BootSector: MsdosBoots absolute ClusterBuffer ;
-
- procedure ReadBootSector ;
- {*
- * Read the bootsector of an MS-DOS disk. In this sector the actual
- * characteristics of the disk can be found. FlushCache reads the
- * bootsector in order to force the BIOS cache to be flushed:
- * therefore only procedure FlushCache is invoked!
- *}
- begin
- FlushCache ;
- end ; { of ReadBootSector }
-
- begin
- {*
- * Copy the MS-DOS DPB into the BIOS tables and fill it with the currently
- * known information.
- *}
- MsdosDpb^ := SkeletDpb ; { Install skeleton of MS-DOS DPB }
- MsdosDpb^.PDA:= MsdosDriveAddress ; { Set the physical drive address }
- if MsdosDriveAddress=3 then { Build the drive select mask : }
- MsdosDpb^.DDS:= $B0 { MFM & Drive_3 }
- else
- MsdosDpb^.DDS:= $A0 + ($01 shl MsdosDriveAddress) ; { MFM & Drive_n }
- {*
- * Read the disk parameters of the MS-DOS floppy disk: they are saved in the
- * first sector, the boot sector, of the disk.
- *}
- ReadBootSector ;
- if ErrorDetected then Exit ;
-
- SystemIdent := BootSector.BSystemIdent ;
- FormatIdent := Bootsector.BFormatIdent ;
- BytesPerSector := BootSector.BBytesPerSector ;
- SectorsPerFat := BootSector.BSectorsPerFat ;
- SectorsPerCluster:= BootSector.BSectorsPerCluster ;
- SectorsPerTrack := BootSector.BSectorsPerTrack ;
- SectorsPerDisk := BootSector.BSectorsPerDisk ;
- FatsPerDisk := BootSector.BFatsPerDisk ;
- SidesPerDisk := BootSector.BSidesPerDisk ;
-
- FcbsPerSector := BytesPerSector div BytesPerFcb ;
- FirstFatSector := BootSector.BReservedSectors ;
- RootDirectoryStart:= FirstFatSector + SectorsPerFat*FatsPerDisk ;
- RootDirectorySize := BootSector.BEntriesInRoot div FcbsPerSector ;
- FirstDataSector := RootDirectoryStart + RootDirectorySize ;
-
- RecordsPerSector := BytesPerSector div BytesPerRecord ;
- RecordsPerCluster:= RecordsPerSector * SectorsPerCluster ;
- CylindersPerDisk := SectorsPerDisk div (SectorsPerTrack*SidesPerDisk) ;
- {*
- * Compute the index of the last cluster on the disk. This is almost the
- * number of clusters on the disk: the FAT contains two dummy entries in the
- * beginning, thus the 1st cluster is given index 2.
- *}
- ClustersPerDisk := (SectorsPerDisk - FirstDataSector) div
- SectorsPerCluster + 1 ;
-
- DirectoryStartCls:= 0 ; { Go to root directory }
- DirectoryStartSct:= RootDirectoryStart ;
- DirectorySize := RootDirectorySize ;
- DirectoryNesting := 0 ;
-
- {*
- * Check whether the format of the disk and the drive are compatible, that is
- * the number of heads and cylinders of the drive must be big enough.
- *}
- if ( DriveAttribute[MsdosDriveName].Heads < SidesPerDisk ) or
- ( DriveAttribute[MsdosDriveName].Cylinders<CylindersPerDisk ) then
- FlagError( 'InsMD: Incompatible drive selected : ' + MsdosDriveName )
- else
- {*
- * Check whether the cluster buffer and the FAT buffer are big enough.
- *}
- if (SectorsPerCluster*BytesPerSector>Succ(ClusterSize)) or
- (SectorsPerFat *BytesPerSector>Succ(FatSize )) then
- FlagError( 'InsMD: Cluster/FAT buffer too small' )
- else
- {*
- * Fill in the other fields of the DPB; Besides all the extension fields in
- * the DPB also the fields SPT and BLM need to be set properly. One CP/M
- * block is associated with one physical sector
- *}
- begin
- with MsdosDpb^ do
- begin
- SPT:= SectorsPerTrack*RecordsPerSector ;
- BLM:= Pred( RecordsPerSector ) ;
- PSS:= RecordsPerSector ;
- PCD:= CylindersPerDisk ;
- PST:= SectorsPerTrack ;
- if SidesPerDisk=1 then
- FNO:= $00 ; { Select single sided format }
- if CylindersPerDisk<DriveAttribute[MsdosDriveName].Cylinders then
- FNO:= FNO + $10 ; { Select double step }
- end ; { of with }
- end ; { of else/else }
- end ; { of InstallMsdosDrive }
-
- procedure SetMsdosDrive ;
- {*
- * Select another (?) drive as the MS-DOS disk drive. It
- * must meet the following criteria:
- * - it is a floppy disk drive,
- * - it is not the CP/M default and
- * - the physical addresses of that drive and the default drive differ.
- *}
- var
- NewDriveName : Char ; { Name of drive for MS-DOS disk }
- NewMsdosDrive: Integer ; { Ordinal of selected drive }
- Success : Boolean ; { Assignment was successfull }
- begin
- Write( 'Enter MS-DOS drive : ' ) ;
- Read ( Kbd, NewDriveName ) ; NewDriveName:= UpCase( NewDriveName ) ;
- Write( NewDriveName ) ;
-
- Success:= False ;
- if NewDriveName in (FloppyDrives-[ExtractDisk(CpmDriveName)]) then
- with DriveAttribute[NewDriveName] do
- begin
- NewMsdosDrive:= Ord(NewDriveName) - Ord('A') ;
- if DevAddress <> CpmDriveAddress then
- begin
- Success:= True ;
- UnInstallMsdosDrive ; { Remove previous selection }
-
- MsdosDpb := DpbAddress ; { Save address of XLT and DPB }
- MsdosDrive := NewMsdosDrive ; { Save drive number }
- MsdosDriveAddress:= DevAddress ; { Claim physical drive }
- MsdosDriveName := NewDriveName ; { Save drive name }
- SavedDpb := MsdosDpb^ ; { Save original XLT and DPB }
-
- InstallMsdosDrive ; { Modify BIOS, determine disk pars }
- {*
- * Complete the MS-DOS disk installation by reading the FAT. If reading of
- * the first FAT fails, use the second FAT (if present).
- *}
- if not ErrorDetected then
- begin
- ReadFat( 0 ) ; { Try the primary FAT }
- if ErrorDetected and (FatsPerDisk>1) then
- begin
- ClearError ;
- ReadFat( 1 ) ; { Read the back-up FAT }
- end ; { of if }
- end ; {of if }
- {*
- * One final check on the internal consistency can be performed now: the
- * media descriptor byte in the boot sector and in the FAT should be
- * identical.
- *}
- if not ErrorDetected then
- if FormatIdent<>FatBuffer[0] then
- FlagError( 'SetMD: Media descriptors don''t match' ) ;
-
- if ErrorDetected then
- UnInstallMsdosDrive ; { Undo install in case of an error }
- end ; { of if }
- end ; { of with/if }
-
- if not Success then
- FlagError( 'SetMD: Illegal specification: '+NewDriveName ) ;
- end ; { of SetMsdosDrive }
-
- procedure ReadMsdosDirectory ;
- {*
- * Build the filelist from the current MS-DOS directory.
- *}
- var
- EntryType : EntryTypes ; { Type of MS-DOS directory entry }
- begin
- PresetFileList ; { Clear the file list }
- DirectorySearchPos:= BeforeFirstEntry ;
- repeat
- {*
- * Read the next directory entry and return its type. If an error is
- * detected, the returned EntryType will be EndOfDirectory. This will
- * cause an immediate termination of this procedure.
- *}
- GetNextDirEntry( EntryType ) ;
- if ErrorDetected then
- begin
- BuildErrorTrace( 'ReaMD_' ) ;
- Exit ;
- end ; { of if }
- {*
- * If a name is encountered, build a file entry from it. The file entry
- * is inserted in the filelist, which is ordered on the name field.
- *}
- if EntryType in [VolumeNameEntry,SubDirectoryNameEntry,FileNameEntry] then
- with MsdosFcb^ do
- begin
- New( FileEntry ) ;
- FileEntry^.Next:= Nil ;
- FileEntry^.Prev:= Nil ;
- FileEntry^.Name:= FileName ;
- FileEntry^.Attr:= Attribute ;
- FileEntry^.Mark:= False ;
- FileEntry^.Size:= (GetMsdosFileSize + 7) div 8 ;
-
- EnterFileInList ;
- end ; { of with/if }
- until EntryType in [UnusedEntry,EndOfDirectory] ;
- FileEntry:= HeadFileList ; { Preset 'current' file }
- FileIndex:= 1 ;
- end ; { of ReadMsdosDirectory }
-