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