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