home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / cpm / utils / dskutl / swp-ms10.ark / TRAMDF.IF5 < prev    next >
Text File  |  1989-09-27  |  13KB  |  318 lines

  1.  
  2. {* ------------------------------------------------------------------------- *}
  3. {*         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
  4. {* ------------------------------------------------------------------------- *}
  5.  
  6. procedure DisplayMsdosDiskParameters ;
  7. {*
  8.  * Display the physical parameters of the last, which is possibly also
  9.  * the current MS-DOS disk read.
  10.  *}
  11. begin
  12.    DisplayTitle( 'MS-DOS disk parameters' ) ;
  13.    Write  ( ^M^J'Disk parameters of the ' ) ;
  14.    if MsdosDriveName='?' then
  15.      Write( 'last' )
  16.    else
  17.      Write( 'current' ) ;
  18.    WriteLn( ' MS-DOS disk.'^M^J ) ;
  19.    WriteLn( 'System Identification = ', SystemIdent ) ;
  20.    WriteLn( 'Media descriptor      =  $', Hex(FormatIdent,2) ) ;
  21.    WriteLn ;
  22.    WriteLn( '# bytes per sector    = ',    BytesPerSector:4 ) ;
  23.    WriteLn( '# sectors per track   = ',   SectorsPerTrack:4 ) ;
  24.    WriteLn( '# heads               = ',      SidesPerDisk:4 ) ;
  25.    WriteLn( '# sectors per disk    = ',    SectorsPerDisk:4 ) ;
  26.    WriteLn( '# cylinders per disk  = ',  CylindersPerDisk:4 ) ;
  27.    WriteLn ;
  28.    WriteLn( '# sectors per FAT     = ',     SectorsPerFat:4 ) ;
  29.    WriteLn( '# sectors per cluster = ', SectorsPerCluster:4 ) ;
  30.    WriteLn( '# FATs                = ',       FatsPerDisk:4 ) ;
  31.    WriteLn( '# reserved sectors    = ',    FirstFatSector:4 ) ;
  32.    WriteLn ;
  33.    Continue ;
  34. end ;  { of DisplayMsdosDiskParameters }
  35.  
  36. function GetMsdosFreeSpace: Integer ;
  37. {*
  38.  * Return the amount of free space, in Kbyte, on the MS-DOS disk.
  39.  *}
  40. const
  41.    BytesPerKilo= 1024 ;  { One KByte }
  42. var
  43.    FreeClusters: Integer ;  { Counter of free clusters }
  44.    I           : Integer ;  { Loop control variable }
  45. begin
  46.    FreeClusters:= 0 ;
  47.    for I:= 2 to ClustersPerDisk do
  48.      if GetFatEntry(I)=0 then
  49.        FreeClusters:= Succ( FreeClusters ) ;
  50. {*
  51.  * Compute the free disk space in KiloBytes.  Note that the parenthesis
  52.  * in the next expression are needed to prevent integer overflow!
  53.  *}
  54.    GetMsdosFreeSpace:= FreeClusters*(SectorsPerCluster*BytesPerSector div
  55.                                      BytesPerKilo) ;
  56. end ;  { of GetMsdosFreeSpace }
  57.  
  58. procedure UnInstallMsdosDrive ;
  59. {*
  60.  * Remove the MS-DOS DPB from the BIOS internal tables and restore the
  61.  * original CP/M DPB.
  62.  *}
  63. begin
  64.    if MsdosDriveName<>'?' then
  65.     begin
  66.      MsdosDpb^        := SavedDpb ;  { Restore XLT and DPB }
  67.      MsdosDpb         :=      Nil ;  { Remove pointer }
  68.      MsdosDriveName   :=      '?' ;  { Signal absence of MS-DOS drive }
  69.      MsdosDriveAddress:=      254 ;  { Remove allocation of physical drive }
  70.     end ;  { of if }
  71. end ;  { of UnInstallMsdosDrive }
  72.  
  73. procedure InstallMsdosDrive ;
  74. {*
  75.  * Install the MS-DOS drive in BIOS.  The disk parameters are read from the
  76.  * bootsector on the disk.  Then the fields within the CP/M DPB are modified
  77.  * accordingly.  Thus upon successfull completion of this routine, BIOS is
  78.  * set up to read and write the MS-DOS disk.
  79.  *
  80.  * This routine will fail if one of the following conditions occur:
  81.  * - The bootsector cannot be read from the disk.  A possible cause is that
  82.  *   there is no disk inserted in the disk drive.
  83.  * - The parameters of the disk and the drive are not compatible: either the
  84.  *   number of cylinders or the number of heads of the disk drive is less
  85.  *   than required to read the floppy disk.
  86.  *
  87.  * In case of an error is detected, the global error flag is set and this
  88.  * procedure will leave the DPB in an undetermined state!
  89.  *
  90.  * CAUTION : This procedure is very system dependent!  It sets the various
  91.  *           fields in the extension of the DPB.
  92.  *}
  93. type
  94.    MsdosBoots = record              { Layout of the MS-DOS boot sector }
  95.                   BJumpCode         : array[0..2] of byte ;
  96.                   BSystemIdent      : array[0..7] of char ;
  97.                   BBytesPerSector   : Integer ;
  98.                   BSectorsPerCluster:    Byte ;
  99.                   BReservedSectors  : Integer ;
  100.                   BFatsPerDisk      :    Byte ;
  101.                   BEntriesInRoot    : Integer ;
  102.                   BSectorsPerDisk   : Integer ;
  103.                   BFormatIdent      :    Byte ;
  104.                   BSectorsPerFat    : Integer ;
  105.                   BsectorsPerTrack  : Integer ;
  106.                   BSidesPerDisk     : Integer ;
  107.                   BSpecResvSectors  : Integer ;
  108.                 end ;  { of MsdosBoot record }
  109.  
  110. var
  111.    BootSector: MsdosBoots absolute ClusterBuffer ;
  112.  
  113.  procedure ReadBootSector ;
  114.  {*
  115.   * Read the bootsector of an MS-DOS disk.  In this sector the actual
  116.   * characteristics of the disk can be found.  FlushCache reads the
  117.   * bootsector in order to force the BIOS cache to be flushed:
  118.   * therefore only procedure FlushCache is invoked!
  119.   *}
  120.  begin
  121.     FlushCache ;
  122.  end ;  { of ReadBootSector }
  123.  
  124. begin
  125. {*
  126.  * Copy the MS-DOS DPB into the BIOS tables and fill it with the currently
  127.  * known information.
  128.  *}
  129.    MsdosDpb^    :=         SkeletDpb ;  { Install skeleton of MS-DOS DPB }
  130.    MsdosDpb^.PDA:= MsdosDriveAddress ;  { Set the physical drive address }
  131.    if MsdosDriveAddress=3 then          { Build the drive select mask : }
  132.      MsdosDpb^.DDS:= $B0                {  MFM & Drive_3 }
  133.    else
  134.      MsdosDpb^.DDS:= $A0 + ($01 shl MsdosDriveAddress) ;  {  MFM & Drive_n }
  135. {*
  136.  * Read the disk parameters of the MS-DOS floppy disk: they are saved in the
  137.  * first sector, the boot sector, of the disk.
  138.  *}
  139.    ReadBootSector ;
  140.    if ErrorDetected then  Exit ;
  141.  
  142.    SystemIdent      := BootSector.BSystemIdent ;
  143.    FormatIdent      := Bootsector.BFormatIdent ;
  144.    BytesPerSector   := BootSector.BBytesPerSector ;
  145.    SectorsPerFat    := BootSector.BSectorsPerFat ;
  146.    SectorsPerCluster:= BootSector.BSectorsPerCluster ;
  147.    SectorsPerTrack  := BootSector.BSectorsPerTrack ;
  148.    SectorsPerDisk   := BootSector.BSectorsPerDisk ;
  149.    FatsPerDisk      := BootSector.BFatsPerDisk ;
  150.    SidesPerDisk     := BootSector.BSidesPerDisk ;
  151.  
  152.    FcbsPerSector     := BytesPerSector div BytesPerFcb ;
  153.    FirstFatSector    := BootSector.BReservedSectors ;
  154.    RootDirectoryStart:= FirstFatSector + SectorsPerFat*FatsPerDisk ;
  155.    RootDirectorySize := BootSector.BEntriesInRoot div FcbsPerSector ;
  156.    FirstDataSector   := RootDirectoryStart + RootDirectorySize ;
  157.  
  158.    RecordsPerSector :=  BytesPerSector div BytesPerRecord ;
  159.    RecordsPerCluster:=  RecordsPerSector * SectorsPerCluster ;
  160.    CylindersPerDisk :=  SectorsPerDisk div (SectorsPerTrack*SidesPerDisk) ;
  161. {*
  162.  * Compute the index of the last cluster on the disk.  This is almost the
  163.  * number of clusters on the disk: the FAT contains two dummy entries in the
  164.  * beginning, thus the 1st cluster is given index 2.
  165.  *}
  166.    ClustersPerDisk  := (SectorsPerDisk - FirstDataSector) div
  167.                         SectorsPerCluster + 1 ;
  168.  
  169.    DirectoryStartCls:=                  0 ;  { Go to root directory }
  170.    DirectoryStartSct:= RootDirectoryStart ;
  171.    DirectorySize    :=  RootDirectorySize ;
  172.    DirectoryNesting :=                  0 ;
  173.  
  174. {*
  175.  * Check whether the format of the disk and the drive are compatible, that is
  176.  * the number of heads and cylinders of the drive must be big enough.
  177.  *}
  178.    if ( DriveAttribute[MsdosDriveName].Heads    <    SidesPerDisk ) or
  179.       ( DriveAttribute[MsdosDriveName].Cylinders<CylindersPerDisk ) then
  180.      FlagError( 'InsMD: Incompatible drive selected : ' + MsdosDriveName )
  181.    else
  182. {*
  183.  * Check whether the cluster buffer and the FAT buffer are big enough.
  184.  *}
  185.      if (SectorsPerCluster*BytesPerSector>Succ(ClusterSize)) or
  186.         (SectorsPerFat    *BytesPerSector>Succ(FatSize    )) then
  187.        FlagError( 'InsMD: Cluster/FAT buffer too small' )
  188.      else
  189. {*
  190.  * Fill in the other fields of the DPB; Besides all the extension fields in
  191.  * the DPB also the fields SPT and BLM need to be set properly.  One CP/M
  192.  * block is associated with one physical sector
  193.  *}
  194.       begin
  195.        with MsdosDpb^ do
  196.         begin
  197.          SPT:= SectorsPerTrack*RecordsPerSector ;
  198.          BLM:= Pred( RecordsPerSector ) ;
  199.          PSS:= RecordsPerSector ;
  200.          PCD:= CylindersPerDisk ;
  201.          PST:= SectorsPerTrack ;
  202.          if SidesPerDisk=1 then
  203.            FNO:= $00 ;        { Select single sided format }
  204.          if CylindersPerDisk<DriveAttribute[MsdosDriveName].Cylinders then
  205.            FNO:= FNO + $10 ;  { Select double step }
  206.         end ;  { of with }
  207.       end ;  { of else/else }
  208. end ;  { of InstallMsdosDrive }
  209.  
  210. procedure SetMsdosDrive ;
  211. {*
  212.  * Select another (?) drive as the MS-DOS disk drive.  It
  213.  * must meet the following criteria:
  214.  *  - it is a floppy disk drive,
  215.  *  - it is not the CP/M default  and
  216.  *  - the physical addresses of that drive and the default drive differ.
  217.  *}
  218. var
  219.    NewDriveName :    Char ;  { Name of drive for MS-DOS disk }
  220.    NewMsdosDrive: Integer ;  { Ordinal of selected drive }
  221.    Success      : Boolean ;  { Assignment was successfull }
  222. begin
  223.    Write( 'Enter MS-DOS drive : ' ) ;
  224.    Read ( Kbd, NewDriveName ) ;  NewDriveName:= UpCase( NewDriveName ) ;
  225.    Write( NewDriveName ) ;
  226.  
  227.    Success:= False ;
  228.    if NewDriveName in (FloppyDrives-[ExtractDisk(CpmDriveName)]) then
  229.      with DriveAttribute[NewDriveName] do
  230.       begin
  231.        NewMsdosDrive:= Ord(NewDriveName) - Ord('A') ;
  232.        if DevAddress <> CpmDriveAddress then
  233.         begin
  234.          Success:= True ;
  235.          UnInstallMsdosDrive ;  { Remove previous selection }
  236.  
  237.          MsdosDpb         :=    DpbAddress ;  { Save address of XLT and DPB }
  238.          MsdosDrive       := NewMsdosDrive ;  { Save drive number }
  239.          MsdosDriveAddress:=    DevAddress ;  { Claim physical drive }
  240.          MsdosDriveName   :=  NewDriveName ;  { Save drive name }
  241.          SavedDpb         :=     MsdosDpb^ ;  { Save original XLT and DPB }
  242.  
  243.          InstallMsdosDrive ;  { Modify BIOS, determine disk pars }
  244. {*
  245.  * Complete the MS-DOS disk installation by reading the FAT.  If reading of
  246.  * the first FAT fails, use the second FAT (if present).
  247.  *}
  248.          if not ErrorDetected then
  249.           begin
  250.            ReadFat( 0 ) ;  { Try the primary FAT }
  251.            if ErrorDetected and (FatsPerDisk>1) then
  252.             begin
  253.              ClearError ;
  254.              ReadFat( 1 ) ;  { Read the back-up FAT }
  255.             end ;  { of if }
  256.           end ;  {of if }
  257. {*
  258.  * One final check on the internal consistency can be performed now: the
  259.  * media descriptor byte in the boot sector and in the FAT should be
  260.  * identical.
  261.  *}
  262.          if not ErrorDetected then
  263.            if FormatIdent<>FatBuffer[0] then
  264.              FlagError( 'SetMD: Media descriptors don''t match' ) ;
  265.  
  266.          if ErrorDetected then
  267.            UnInstallMsdosDrive ;  { Undo install in case of an error }
  268.         end ;  { of if }
  269.       end ;  { of with/if }
  270.  
  271.    if not Success then
  272.      FlagError( 'SetMD: Illegal specification: '+NewDriveName ) ;
  273. end ;  { of SetMsdosDrive }
  274.  
  275. procedure ReadMsdosDirectory ;
  276. {*
  277.  * Build the filelist from the current MS-DOS directory.
  278.  *}
  279. var
  280.    EntryType : EntryTypes ;  { Type of MS-DOS directory entry }
  281. begin
  282.    PresetFileList ;          { Clear the file list }
  283.    DirectorySearchPos:= BeforeFirstEntry ;
  284.    repeat
  285. {*
  286.  * Read the next directory entry and return its type.  If an error is
  287.  * detected, the returned EntryType will be EndOfDirectory.  This will
  288.  * cause an immediate termination of this procedure.
  289.  *}
  290.      GetNextDirEntry( EntryType ) ;
  291.      if ErrorDetected then
  292.       begin
  293.        BuildErrorTrace( 'ReaMD_' ) ;
  294.        Exit ;
  295.       end ;  { of if }
  296. {*
  297.  * If a name is encountered, build a file entry from it.  The file entry
  298.  * is inserted in the filelist, which is ordered on the name field.
  299.  *}
  300.      if EntryType in [VolumeNameEntry,SubDirectoryNameEntry,FileNameEntry] then
  301.        with MsdosFcb^ do
  302.         begin
  303.          New( FileEntry ) ;
  304.          FileEntry^.Next:=       Nil ;
  305.          FileEntry^.Prev:=       Nil ;
  306.          FileEntry^.Name:=  FileName ;
  307.          FileEntry^.Attr:= Attribute ;
  308.          FileEntry^.Mark:=     False ;
  309.          FileEntry^.Size:= (GetMsdosFileSize + 7) div 8 ;
  310.  
  311.          EnterFileInList ;
  312.         end ;  { of with/if }
  313.    until EntryType in [UnusedEntry,EndOfDirectory] ;
  314.    FileEntry:= HeadFileList ;  { Preset 'current' file }
  315.    FileIndex:=            1 ;
  316. end ;  { of ReadMsdosDirectory }
  317.  
  318.