home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 14 / CDACTUAL.iso / cdactual / demobin / share / program / Pascal / TSRSRC30.ZIP / XMS.PAS < prev   
Encoding:
Pascal/Delphi Source File  |  1991-10-15  |  7.7 KB  |  313 lines

  1. {**************************************************************************
  2. *   XMS - unit of XMS functions                                           *
  3. *   Copyright (c) 1991 Kim Kokkonen, TurboPower Software.                 *
  4. *   May be freely distributed and used but not sold except by permission. *
  5. ***************************************************************************}
  6.  
  7. {$R-,S-,I-,V-,B-,F-,A-,E-,N-,G-,X-}
  8.  
  9. unit Xms;
  10.   {-XMS functions needed for TSR Utilities}
  11.  
  12. interface
  13.  
  14. const
  15.   ExhaustiveXms : Boolean = False;
  16.  
  17. type
  18.   XmsHandleRecord =
  19.   record
  20.     Handle : Word;
  21.     NumPages : Word;
  22.   end;
  23.   XmsHandles = array[1..16380] of XmsHandleRecord;
  24.   XmsHandlesPtr = ^XmsHandles;
  25.  
  26. function XmsInstalled : Boolean;
  27.   {-Returns True if XMS memory manager installed}
  28.  
  29. function QueryFreeExtMem(var TotalFree, LargestBlock : Word) : Byte;
  30.   {-Return info about free XMS (in k bytes)}
  31.  
  32. function GetHandleInfo(XmsHandle : Word;
  33.                        var LockCount    : Byte;
  34.                        var HandlesLeft  : Byte;
  35.                        var BlockSizeInK : Word) : Byte;
  36.   {-Return info about specified Xms handle}
  37.  
  38. function AllocateExtMem(SizeInK : Word; var XmsHandle : Word) : Byte;
  39.   {-Allocate XMS memory}
  40.  
  41. function FreeExtMem(XmsHandle : Word) : Byte;
  42.   {-Free XMS memory}
  43.  
  44. function GetXmsHandles(var XmsPages : XmsHandlesPtr) : Word;
  45.   {-Return number of XMS handles allocated, and pointer to array of handle records}
  46.  
  47. function ExtMemPossible : Boolean;
  48.   {-Return true if raw extended memory is possible}
  49.  
  50. function ExtMemTotalPrim : LongInt;
  51.   {-Returns total number of bytes of extended memory in the system}
  52.  
  53. {=======================================================================}
  54.  
  55. implementation
  56.  
  57. var
  58.   XmsControl       : Pointer;          {ptr to XMS control procedure}
  59.  
  60.   function XmsInstalled : Boolean;
  61.     {-Returns True if XMS memory manager installed}
  62.   begin
  63.     XmsInstalled := (XmsControl <> nil);
  64.   end;
  65.  
  66.   function XmsInstalledPrim : Boolean; assembler;
  67.     {-Returns True if an XMS memory manager is installed}
  68.   asm
  69.     mov ah,$30
  70.     int $21
  71.     cmp al,3
  72.     jae @Check2F
  73.     mov al,0
  74.     jmp @Done
  75. @Check2F:
  76.     mov ax,$4300
  77.     int $2F
  78.     cmp al,$80
  79.     mov al,0
  80.     jne @Done
  81.     inc al
  82. @Done:
  83.   end;
  84.  
  85.   function XmsControlAddr : Pointer; assembler;
  86.     {-Return address of XMS control function}
  87.   asm
  88.     mov ax,$4310
  89.     int $2F
  90.     mov ax,bx
  91.     mov dx,es
  92.   end;
  93.  
  94.   function QueryFreeExtMem(var TotalFree, LargestBlock : Word) : Byte; assembler;
  95.     {-Return info about free XMS}
  96.   asm
  97.     mov ah,$08
  98.     call dword ptr [XmsControl]
  99.     or ax,ax
  100.     jz @Done
  101.     les di,TotalFree
  102.     mov es:[di],dx
  103.     les di,LargestBlock
  104.     mov es:[di],ax
  105.     xor bl,bl
  106. @Done:
  107.     mov al,bl
  108.   end;
  109.  
  110.   function GetHandleInfo(XmsHandle : Word;
  111.                          var LockCount    : Byte;
  112.                          var HandlesLeft  : Byte;
  113.                          var BlockSizeInK : Word) : Byte; assembler;
  114.     {-Return info about specified Xms handle}
  115.   asm
  116.     mov ah,$0E
  117.     mov dx,XmsHandle
  118.     call dword ptr [XmsControl]
  119.     test ax,1
  120.     jz @Done
  121.     les di,LockCount
  122.     mov byte ptr es:[di],bh
  123.     les di,HandlesLeft
  124.     mov byte ptr es:[di],bl
  125.     les di,BlockSizeInK
  126.     mov es:[di],dx
  127.     xor bl,bl
  128. @Done:
  129.     mov al,bl
  130.   end;
  131.  
  132.   function AllocateExtMem(SizeInK : Word; var XmsHandle : Word) : Byte; assembler;
  133.     {-Allocate XMS memory}
  134.   asm
  135.     mov ah,$09
  136.     mov dx,SizeInK
  137.     call dword ptr [XmsControl]
  138.     test ax,1
  139.     jz @Done
  140.     les di,XmsHandle
  141.     mov es:[di],dx
  142.     xor bl,bl
  143. @Done:
  144.     mov al,bl
  145.   end;
  146.  
  147.   function FreeExtMem(XmsHandle : Word) : Byte; assembler;
  148.     {-Free XMS memory}
  149.   asm
  150.     mov ah,$0A
  151.     mov dx,XmsHandle
  152.     call dword ptr [XmsControl]
  153.     test ax,1
  154.     jz @Done
  155.     xor bl,bl
  156. @Done:
  157.     mov al,bl
  158.   end;
  159.  
  160.   function GetXmsHandles(var XmsPages : XmsHandlesPtr) : Word;
  161.     {-Return number of XMS handles allocated, and pointer to array of handle records}
  162.   var
  163.     H : Word;
  164.     H0 : Word;
  165.     H1 : Word;
  166.     HCnt : Word;
  167.     FMem : Word;
  168.     FMax : Word;
  169.     HMem : Word;
  170.     LockCount : Byte;
  171.     HandlesLeft : Byte;
  172.     Delta : Integer;
  173.     Status : Byte;
  174.     Done : Boolean;
  175.  
  176.     procedure ExhaustiveSearchHandles(var Handles : Word; XmsPages : XmsHandlesPtr);
  177.       {-Search handles exhaustively}
  178.     var
  179.       H : Word;
  180.       HCnt : Word;
  181.     begin
  182.       HCnt := 0;
  183.       for H := 0 to 65535 do
  184.         if GetHandleInfo(H, LockCount, HandlesLeft, HMem) = 0 then begin
  185.           inc(HCnt);
  186.           if XmsPages <> nil then
  187.             with XmsPages^[HCnt] do begin
  188.               Handle := H;
  189.               NumPages := HMem;
  190.             end;
  191.         end;
  192.       Handles := HCnt;
  193.     end;
  194.  
  195.   begin
  196.     GetXmsHandles := 0;
  197.  
  198.     Status := QueryFreeExtMem(FMem, FMax);
  199.     if Status = $A0 then begin
  200.       FMem := 0;
  201.       FMax := 0;
  202.     end else if Status <> 0 then
  203.       Exit;
  204.  
  205.     if ExhaustiveXms then begin
  206.       {Search all 64K XMS handles for valid ones}
  207.       HCnt := 0;
  208.       ExhaustiveSearchHandles(HCnt, nil);
  209.       if HCnt <> 0 then begin
  210.         GetMem(XmsPages, HCnt*SizeOf(XmsHandleRecord));
  211.         ExhaustiveSearchHandles(HCnt, XmsPages);
  212.         GetXmsHandles := HCnt;
  213.       end;
  214.  
  215.     end else begin
  216.       {Heuristic algorithm to find used handles quickly}
  217.  
  218.       {Allocate two dummy handles}
  219.       if FMem > 1 then
  220.         HMem := 1
  221.       else
  222.         HMem := 0;
  223.       Status := AllocateExtMem(HMem, H0);
  224.       if Status <> 0 then
  225.         Exit;
  226.       Status := AllocateExtMem(HMem, H1);
  227.       if Status <> 0 then begin
  228.         {Deallocate dummy handle}
  229.         Status := FreeExtMem(H0);
  230.         Exit;
  231.       end;
  232.       Delta := H1-H0;
  233.       {Deallocate one dummy}
  234.       Status := FreeExtMem(H1);
  235.  
  236.       {Trace back through valid handles, counting them}
  237.       HCnt := 0;
  238.       H1 := H0;
  239.       repeat
  240.         Status := GetHandleInfo(H1, LockCount, HandlesLeft, HMem);
  241.         Done := (Status <> 0);
  242.         if not Done then begin
  243.           dec(H1, Delta);
  244.           inc(HCnt);
  245.         end;
  246.       until Done;
  247.  
  248.       if HCnt > 1 then begin
  249.         dec(HCnt);
  250.         GetMem(XmsPages, HCnt*SizeOf(Word));
  251.         {Go forward again through valid handles, saving them}
  252.         inc(H1, Delta);
  253.         H := 0;
  254.         while H1 <> H0 do begin
  255.           Status := GetHandleInfo(H1, LockCount, HandlesLeft, HMem);
  256.           if Status = 0 then begin
  257.             inc(H);
  258.             with XmsPages^[H] do begin
  259.               Handle := H1;
  260.               NumPages := HMem;
  261.             end;
  262.           end;
  263.           inc(H1, Delta);
  264.         end;
  265.         GetXmsHandles := HCnt;
  266.       end;
  267.  
  268.       {Deallocate dummy handle}
  269.       Status := FreeExtMem(H0);
  270.     end;
  271.   end;
  272.  
  273.   function DosVersion : Byte; Assembler;
  274.     {-Return major DOS version number}
  275.   asm
  276.     mov     ah,$30
  277.     int     $21
  278.   end;
  279.  
  280.   function ExtMemPossible : Boolean;
  281.     {-Return true if raw extended memory is possible}
  282.   const
  283.     ATclass = $FC;              {machine ID bytes}
  284.     Model80 = $F8;
  285.   var
  286.     MachineId : Byte absolute $FFFF : $000E;
  287.   begin
  288.     {don't allow allocation if running PC or XT, or under DOS 2.x or OS/2}
  289.     ExtMemPossible := False;
  290.     case DosVersion of
  291.       3..5 :
  292.         case MachineId of
  293.           ATclass, Model80 : ExtMemPossible := True;
  294.         end;
  295.     end;
  296.   end;
  297.  
  298.   function ExtMemTotalPrim : LongInt; assembler;
  299.     {-Returns total number of bytes of extended memory in the system}
  300.   asm
  301.     mov ah,$88
  302.     int $15
  303.     mov cx,1024
  304.     mul cx
  305.   end;
  306.  
  307. begin
  308.   if XmsInstalledPrim then
  309.     XmsControl := XmsControlAddr
  310.   else
  311.     XmsControl := nil;
  312. end.
  313.