home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / 1987 / 09 / dskcache / cache.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1987-06-29  |  11.3 KB  |  292 lines

  1. (* ----------------------------------------------------------------------- *)
  2. (*                               CACHE.PAS                                 *)
  3. (*     Ein Platten-Cache-System fuer MS-DOS-kompatible in Turbo-Pascal     *)
  4. (* ----------------------------------------------------------------------- *)
  5.  
  6. PROGRAM  Cache;
  7.  
  8.     {$K-}
  9.     {$U-}
  10.     {$R-}
  11.     {$V-}
  12.     {$I-}
  13.     {$C-}
  14.  
  15.     {$I REGS8088.INC}
  16.     {$I CRITICAL.INC}
  17.     {$I MAKEINT.INC}
  18.     {$I QUEUESET.INC}
  19.     {$I COMPARE.INC}
  20.  
  21.     CONST
  22.       DiskReset_                = $00;
  23.       DiskStatus_               = $01;
  24.       DiskReadSector_           = $02;
  25.       DiskWriteSector_          = $03;
  26.       DiskVerifySector_         = $04;
  27.       DiskFormatTrack_          = $05;
  28.       DiskFormatTrackBadSector_ = $06;
  29.       DiskFormatDrive_          = $07;
  30.       DiskDriveParameters_      = $08;
  31.       DiskInit_                 = $09;
  32.       DiskReadLong_             = $0A;
  33.       DiskWriteLong_            = $0B;
  34.       DiskSeek_                 = $0C;
  35.       DiskAlternateReset_       = $0D;
  36.       DiskReadSectorBuffer_     = $0E;
  37.       DiskWriteSectorBuffer_    = $0F;
  38.       DiskReady_                = $10;
  39.       DiskRecalibrate_          = $11;
  40.       DiskRamDiagnostic_        = $12;
  41.       DiskDriveDiagnostic_      = $13;
  42.       DiskControllerDiagnostic_ = $14;
  43.  
  44.       DiskOk_                   = $00;
  45.       DiskBadCommand_           = $01;
  46.       DiskBadAddressMark_       = $02;
  47.       DiskSectorNotFound_       = $04;
  48.       DiskBadReset_             = $05;
  49.       DiskInitFailed_           = $07;
  50.       DiskDmaBoundary_          = $09;
  51.       DiskBadTrack_             = $0B;
  52.       DiskBadEcc_               = $10;
  53.       DiskDataCorrected_        = $11;
  54.       DiskBadController_        = $20;
  55.       DiskBadSeek_              = $40;
  56.       DiskTimeOut_              = $80;
  57.       DiskUndefinedError_       = $BB;
  58.       DiskSenseFailed_          = $FF;
  59.  
  60.       IntDisk                   = $13;
  61.  
  62.       CacheSize                 = 256;
  63.       CacheSectorSize           = 512;
  64.       CacheCarry                = $0001;
  65.  
  66.     TYPE
  67.       CacheLocation_            = RECORD
  68.                                     DriveNumber,
  69.                                     HeadNumber          : BYTE;
  70.                                     CylinderNr          : INTEGER;
  71.                                     SectorNumber        : BYTE;
  72.                                   END;
  73.  
  74.       CacheSector_              = ARRAY [1..CacheSectorSize] OF BYTE;
  75.       CacheSectorAddr_          = ^CacheSector_;
  76.  
  77.       CacheElement_             = RECORD
  78.                                     Link                : QuLink_;
  79.                                     Location            : CacheLocation_;
  80.                                     Sector              : CacheSector_;
  81.                                   END;
  82.  
  83.       CacheElementAddr_         = ^CacheElement_;
  84.  
  85.     VAR
  86.       CacheActive,
  87.       CacheFree                 : QuHead_;
  88.       CacheLocation             : CacheLocation_;
  89.       CacheBufferAddr           : CacheSectorAddr_;
  90.       CacheSectorCount          : BYTE;
  91.       CacheElement              : CacheElementAddr_;
  92.       CacheElementOld           : CacheElementAddr_;
  93. (* ----------------------------------------------------------------------- *)
  94.    FUNCTION
  95.       CacheSearchElement (VAR Location: CacheLocation_) : CacheElementAddr_;
  96.  
  97.         VAR Element: CacheElementAddr_;
  98.  
  99.         BEGIN
  100.           Element:= Addr (CacheActive.Next^);
  101.           WHILE Element <> Addr (CacheActive) DO
  102.             IF Equal(Element^.Location,Location,SizeOf(CacheLocation_)) THEN
  103.                 BEGIN CacheSearchElement:= Element; Exit; END
  104.             ELSE
  105.                 Element:= Addr (Element^.Link.Next^);
  106.           CacheSearchElement:= NIL;
  107.         END;
  108. (* ----------------------------------------------------------------------- *)
  109.     PROCEDURE CacheBufferToSector (Location   : CacheLocation_;
  110.                                    SectorAddr : CacheSectorAddr_;
  111.                                    SectorCount: BYTE);
  112.  
  113.         VAR I                     : INTEGER;
  114.             Element               : CacheElementAddr_;
  115.  
  116.         BEGIN
  117.            WITH Location DO
  118.              FOR I:= 1 TO SectorCount DO
  119.                BEGIN
  120.                  Element:= CacheSearchElement (Location);
  121.                  IF Element = NIL THEN
  122.                  BEGIN
  123.                    IF QuEmpty(CacheFree) THEN
  124.                      Element:= Addr(CacheActive.Prev^)
  125.                    ELSE
  126.                      Element:= Addr (CacheFree.Prev^);
  127.                    Element^.Location:= Location;
  128.                  END;
  129.                  Move (SectorAddr^, Element^.Sector, CacheSectorSize);
  130.                  QuInto (CacheActive, Element^.Link);
  131.                  SectorAddr:=
  132.                    Ptr(Seg(SectorAddr^),Ofs(SectorAddr^)+CacheSectorSize);
  133.                  Location.SectorNumber:= Location.SectorNumber + 1;
  134.                END;
  135.         END;
  136. (* ----------------------------------------------------------------------- *)
  137.     FUNCTION CacheSectorToBuffer (Location   : CacheLocation_;
  138.                                   SectorAddr : CacheSectorAddr_;
  139.                                   SectorCount: BYTE) : BOOLEAN;
  140.  
  141.         VAR I                     : INTEGER;
  142.             Element               : CacheElementAddr_;
  143.  
  144.         BEGIN
  145.            WITH Location DO
  146.              FOR I:= 1 TO SectorCount DO
  147.                BEGIN
  148.                  Element:= CacheSearchElement (Location);
  149.                  IF Element = NIL THEN
  150.                      BEGIN CacheSectorToBuffer:= FALSE; Exit; END
  151.                  ELSE
  152.                      Move (Element^.Sector, SectorAddr^, CacheSectorSize);
  153.                  QuInto (CacheActive, Element^.Link);
  154.                  SectorAddr:=
  155.                    Ptr(Seg(SectorAddr^),Ofs(SectorAddr^)+CacheSectorSize);
  156.                  Location.SectorNumber:= Location.SectorNumber + 1;
  157.                END;
  158.            CacheSectorToBuffer:= TRUE;
  159.         END;
  160. (* ----------------------------------------------------------------------- *)
  161.     PROCEDURE CacheClearActive (DriveNumber: BYTE);
  162.  
  163.         VAR Element               : CacheElementAddr_;
  164.  
  165.         BEGIN
  166.           Element:= Addr (CacheActive.Next^);
  167.           WHILE Element <> Addr (CacheActive) DO
  168.             BEGIN
  169.               IF Element^.Location.DriveNumber = DriveNumber THEN
  170.                   BEGIN
  171.                     Element:= Addr (Element^.Link.Next^);
  172.                     QuInto (CacheFree, Element^.Link.Prev^);
  173.                   END
  174.               ELSE
  175.                   Element:= Addr (Element^.Link.Next^);
  176.             END;
  177.         END;
  178. (* ----------------------------------------------------------------------- *)
  179.     CONST CacheOldInterrupt         : IntEntry_ = (Offset:0; Segment:0);
  180. (* ----------------------------------------------------------------------- *)
  181.     PROCEDURE CacheInterrupt;
  182.  
  183.        {$I BEGININT.INC}
  184.           WITH PgmRegs DO
  185.             BEGIN
  186.               WITH CacheLocation DO
  187.                 BEGIN
  188.                   DriveNumber := PgmDl;
  189.                   HeadNumber  := PgmDh;
  190.                   CylinderNr  := PgmCh;
  191.                   SectorNumber:= PgmCl;
  192.                   CacheBufferAddr:= Ptr (PgmEs, PgmBx);
  193.                   CacheSectorCount:= PgmAl;
  194.                   CASE PgmAh OF
  195.  
  196.                     DiskReadSector_  :
  197.                       BEGIN
  198.                         CacheElement:= NIL;
  199.                         IF DriveNumber < $80 THEN
  200.                             IF HeadNumber = 0 THEN
  201.                                 IF CylinderNr = 0 THEN
  202.                                     IF SectorNumber IN [2, 6] THEN
  203.                                       BEGIN
  204.                                         CacheElement:=
  205.                                           CacheSearchElement(CacheLocation);
  206.                                         IF CacheElement <> NIL THEN
  207.                                            QuOut (CacheElement^.Link);
  208.                                       END;
  209.                         IF NOT CacheSectorToBuffer
  210.                              (CacheLocation,CacheBufferAddr,CacheSectorCount)
  211.                         THEN
  212.                           BEGIN
  213.                             {$I CALLINT.INC}
  214.                               CacheOldInterrupt);
  215.                             {$I CALLINTE.INC};
  216.                             IF PgmAh = 0 THEN
  217.                               BEGIN
  218.                                 PgmFlags:= PgmFlags AND (NOT CacheCarry);
  219.                                 CacheBufferToSector (CacheLocation,
  220.                                                      CacheBufferAddr,
  221.                                                      CacheSectorCount);
  222.                                 IF CacheElement <> NIL THEN
  223.                                   BEGIN
  224.                                     CacheElementOld:=
  225.                                       CacheSearchElement (CacheLocation);
  226.                                     IF NOT Equal(CacheElement^.Sector,
  227.                                                  CacheElementOld^.Sector,
  228.                                                  CacheSectorSize)
  229.                                     THEN
  230.                                       CacheClearActive (DriveNumber);
  231.                                   END;
  232.                               END
  233.                             ELSE
  234.                               BEGIN
  235.                                 PgmFlags:= PgmFlags OR CacheCarry;
  236.                                 CacheClearActive (DriveNumber);
  237.                               END;
  238.                           END;
  239.                         IF CacheElement <> NIL THEN
  240.                           QuInto (CacheFree, CacheElement^.Link);
  241.                       END;
  242.  
  243.                     DiskWriteSector_ :
  244.                       BEGIN
  245.                         CacheBufferToSector
  246.                           (CacheLocation, CacheBufferAddr, CacheSectorCount);
  247.                         {$I EXITINT.INC}
  248.                           CacheOldInterrupt);
  249.                       END;
  250.  
  251.                     ELSE
  252.                       BEGIN
  253.                         CacheClearActive (DriveNumber);
  254.                         {$I EXITINT.INC}
  255.                           CacheOldInterrupt);
  256.                       END;
  257.                   END;
  258.                 END;
  259.             END;
  260.         {$I ENDINT.INC};
  261. (* ----------------------------------------------------------------------- *)
  262.     PROCEDURE CacheInstall;
  263.  
  264.         VAR I                     : INTEGER;
  265.             Element               : ^CacheElement_;
  266.  
  267.         BEGIN
  268.           QuInit (CacheActive);
  269.           QuInit (CacheFree);
  270.           FOR I:= 1 TO CacheSize DO
  271.             BEGIN
  272.               New (Element);
  273.               IF Element <> NIL THEN
  274.                 BEGIN
  275.                   QuInit (Element^.Link);
  276.                   QuInto (CacheFree, Element^);
  277.                 END;
  278.             END;
  279.           WITH CacheOldInterrupt DO
  280.             IntGet (IntDisk, Segment, Offset);
  281.           IntSet (IntDisk, Cseg, Ofs (CacheInterrupt));
  282.         END;
  283. (* ----------------------------------------------------------------------- *)
  284.     BEGIN
  285.       CacheInstall;
  286.       WriteLn; WriteLn;
  287.       WriteLn('Platten-Cache aktiv...');
  288.       WriteLn('(C) 1987 W. Hofmeister-Dunkel & PASCAL INT.');
  289.       WriteLn;
  290.       MakeResident;
  291.     END.
  292.