(* * * * * * * * * * * * * * * * * * *
 *
 * _ems.pas
 *
 * Ems and Emm related definitions,
 * structures and function prototypes
 *
 * * * * * * * * * * * * * * * * * * *)

unit _ems;

INTERFACE

uses _globals,
     dos;

const

    EMS_STD_PAGE_SIZE=   16384;
    EMS_PAGE_FRAME_SIZE= 4;

(*
 *  Define a couple of constants for the move and exchange operations.
 *)
    EMS_MOVE_CONV=       0;
    EMS_MOVE_EMS=        1;

(*
 *  Define the EMS error codes.
 *)
    EMSErrOK=            $00;   { No error }
    EMSErrInternal=      $80;   { Internal EMM error }
    EMSErrHardware=      $81;   { EM Hardware error }
    EMSErrEMMBusy=       $82;   { EMM Busy }
    EMSErrHandInv=       $83;   { Handle Invalid }
    EMSErrUnimp=         $84;   { Undefined EMS function }
    EMSErrNoHandles=     $85;   { Handles Exhausted }
    EMSErrSaveRest=      $86;   { Error in save/restore of context }
    EMSErrReqGTPhys=     $87;   { Not enough physical EM for request }
    EMSErrReqGTAvail=    $88;   { Not enough available EM for request }
    EMSErrReqIsZero=     $89;   { Cannot allocate zero pages }
    EMSErrLogPgInv=      $8A;   { Invalid logical page number }
    EMSErrPhysPgInv=     $8B;   { Invalid physical page number }
    EMSErrSSAreaFull=    $8C;   { Mapping save area is full }
    EMSErrSaveFail=      $8D;   { Mapping save failed }
    EMSErrRestFail=      $8E;   { Mapping restore failed }
    EMSErrParameter=     $8F;   { Subfunction parameter not defined }
    EMSErrAttribute=     $90;   { Attribute type not defined }
    EMSErrUnsupported=   $91;   { Feature not supported }
    EMSErrOverlap=       $92;   { Source/dest of move overlap, move done }
    EMSErrLenInv=        $93;   { Length of move request invalid }
    EMSErrOverlapCE=     $94;   { Overlap of conventional and extended }
    EMSErrOffsetInv=     $95;   { Offset outside logical page }
    EMSErrRegionGT1MB=   $96;   { Region size > 1 megabyte }
    EMSErrOverlapFatal=  $97;   { Source/dest overlap prevented move }
    EMSErrMemTypeInv=    $98;   { Memory source/dest types invalid }
    EMSErrDMARegUnsupp=  $9A;   { Specified register set unsupported }
    EMSErrNoDMARegs=     $9B;   { No available alternate register sets }
    EMSErrAltRegsUnsupp= $9C;   { Alternate registers unsupported }
    EMSErrDMARegUndef=   $9D;   { Specified register set undefined }
    EMSErrDMAChanUnsupp= $9E;   { Dedicated DMA channels unsupported }
    EMSErrChanUnsupp=    $9F;   { Specified DMA channel unsupported }
    EMSErrNameNotFound=  $A0;   { No handle found for name }
    EMSErrNameExists=    $A1;   { Handle with same name already exists }
    EMSErrPointerInv=    $A3;   { Invalid pointer or source array bogus }
    EMSErrAccess=        $A4;   { Access denied by operating system }



type



    EMS_HandleName= array[0..7] of Char;

(* * * * * * * * * * * *
 *
 * structures
 *
 * * * * * * * * * * * *)

    EMS_MapByNumber = record
        logicalPage:        Word;   { Logical page }
        physicalPage:       Word;   { Physical page number }
        end;

    EMS_MapByAddress= record
        logicalPage:        Word;   { Logical page }
        physicalSeg:        Word;   { Physical segment number }
        end;

    EMS_HandleInfo= record
        handle:             Word;   { ems handle }
        numPages:           Word;   { ems pages associated with handle }
        end;
    EMS_HandleInfoArr= array[0..0] of EMS_HandleInfo;

    EMS_MappablePagesInfo= record
        pageSegment:        Word;   { Segment base address }
        physNumber:         Word;   { Physical page number }
        end;
    EMS_MappablePagesInfoArr= array[0..0] of EMS_MappablePagesInfo;

    EMS_HandleNameInfo= record
        handle:             Word;   { ems handle }
        name:               EMS_HandleName;
                                    { ems name (version 4.0) }
        end;
    EMS_HandleNameInfoArr= array[0..0] of EMS_HandleNameInfo;

    EMS_MoveMemoryInfo= record
        length:             DWord;  { memory length }
        srcType:            Byte;   { 0=conventional,1=expanded }
        srcHandle:          Word;   { source handle }
        srcOffset:          Word;   { source offset }
        srcPage:            Word;   { source segment or logical page }
        destType:           Byte;   { 0=conventional,1=expanded }
        destHandle:         Word;   { destination handle }
        destOffset:         Word;   { destination offset }
        destPage:           Word;   { destination segment or logical page }
        end;

    EMS_HardwareConfigInfo= record
        rawPgSize:          Word;   { size of raw pages in paragraphs }
        altRegSets:         Word;   { number of alternate reg sets }
        saveAreaSz:         Word;   { size of mapping save area in bytes }
        regsDma:            Word;   { num of regs can be assigned to dma }
        dmaType:            Word;   { 0=alt dma regs OK,1=one dma reg only }
        end;

    
    EMS_Page= array[0..(EMS_STD_PAGE_SIZE-1)] of Byte;
    EMS_PageFrameArea= array [0..2] of EMS_Page;
    EMS_PageFrame= ^EMS_PageFrameArea;

(* * * * * * * * * * * *
 * 
 *  function prototypes
 *)


    EMS_Ems= object
        function        init
                            : Boolean;
        function        getStatus
                            : Boolean;
        function        getPFA(
                            var page_frame: EMS_PageFrame)
                            : Boolean;
        function        getFreeEM(
                            var total:      Word;
                            var free:       Word)
                            : Boolean;
        function        getVersion(
                            var version:    Word)
                            : Boolean;
        function        getNumActiveHandles(
                            var num_handles: Word)
                            : Boolean;
        function        getPagesAllHandles(
                            var info:        EMS_HandleInfoArr;
                            var num_handles: Word)
                            : Boolean;


        function        savePageMap32(
                            save_buffer:    Pointer)
                            : Boolean;
        function        restPageMap32(
                            restore_buffer: Pointer)
                            : Boolean;
        function        swapPageMap32(
                            rest_buffer:    Pointer;
                            save_buffer:    Pointer)
                            : Boolean;
        function        getMapInfoSize32(
                            var size:       Word)
                            : Boolean;


        function        savePartialMap40(
                            map:            Pointer;
                            buffer:         Pointer)
                            : Boolean;
        function        restPartialMap40(
                            buffer:         Pointer)
                            : Boolean;
        function        getPMapInfoSize40(
                            pages: Word;
                            var buffSize:   Word)
                            : Boolean;

        function        getAttrCapability40(
                            var capability: Word)
                            : Boolean;

        function        getAllHandleNames40(
                            var info_list:  EMS_HandleNameInfoArr)
                            : Boolean;
        function        getTotalHandles40(
                            var handles:    Word)
                            : Boolean;

        function        getStackNeeded40(
                            var stack_space: Word)
                            : Boolean;

        function        moveMemRegion40(
                            var buffer:     EMS_MoveMemoryInfo)
                            : Boolean;
        function        swapMemRegions40(
                            var buffer:     EMS_MoveMemoryInfo)
                            : Boolean;

        function        getAddrsMappable40(
                            var buffer:     EMS_MappablePagesInfoArr;
                            var num_entries: Word)
                            : Boolean;
        function        getNumMappable40(
                            var mappablePages: Word)
                            : Boolean;

        function        getHWConfig40(
                            var buffer:     EMS_HardwareConfigInfo)
                            : Boolean;

        function        getNumRawPages40(
                            var total_pages: Word;
                            var free_pages: Word)
                            : Boolean;

        function        getAltMapRegs40(
                            var active_map: Byte;
                            var regs_area:  Byte)
                            : Boolean;
        function        setAltMapRegs40(
                            alt_set:        Byte;
                            var regs_area:  Byte)
                            : Boolean;
        function        getAltMapRegSize40(
                            var buf_size:   Word)
                            : Boolean;
        function        allocAltMapRegs40(
                            var alt_map:    Byte)
                            : Boolean;
        function        releaseAltMapRegs40(
                            alt_map:        Byte)
                            : Boolean;

        function        allocDMARegs40(
                            var regSet:     Byte)
                            : Boolean;
        function        enableDMA40(
                            regSet:         Byte;
                            channel:        Byte)
                            : Boolean;
        function        disableDMA40(
                            regSet:         Byte)
                            : Boolean;
        function        releaseDMARegs40(
                            regSet:         Byte)
                            : Boolean;

        function        prepEmmWarmBoot40
                            : Boolean;
        function        enableEmmOSFuncs40(
                            a1:             Word;
                            a2:             Word;
                            var a3:         Word;
                            var a4:         Word)
                            : Boolean;
        function        disableEmmOSFuncs40(
                            a1:             Word;
                            a2:             Word;
                            var a3:         Word;
                            var a4:         Word)
                            : Boolean;
        function        releaseAccessKey40(
                            a1:             Word;
                            a2:             Word)
                            : Boolean;

        function        errorText(
                            err:            Word)
                            : String;
        end;


(*
 *
 *)
    Ems_EmBlk= object
        (*
         *  There's only one data element, the handle.
         *)
        handle:         Word;

        (*
         *  Now the methods:
         *)
        function        allocEM(
                            pages:          Word)
                            : Boolean;
        function        mapPage(
                            physical_page:  Word;
                            logical_page:   Word)
                            : Boolean;
        function        freeEM
                            : Boolean;
        function        savePageMap
                            : Boolean;
        function        restorePageMap
                            : Boolean;
        function        getPagesForHandle(
                            var num_pages:  Word)
                            : Boolean;
        function        mapPagesByNum40(
                            pages:          Word;
                            buffer:         Pointer)
                            : Boolean;
        function        mapPagesByAddr40(
                            pages:          Word;
                            buffer:         Pointer)
                            : Boolean;
        function        reallocHandPages40(
                            pages:          Word)
                            : Boolean;

        function        getHandleAttr40(
                            var attribute:  Word)
                            : Boolean;
        function        setHandleAttr40(
                            attribute:      Word)
                            : Boolean;
        function        getHandleName40(
                            var handle_name: EMS_HandleName)
                            : Boolean;
        function        setHandleName40(
                            var handle_name: EMS_HandleName)
                            : Boolean;
        function        searchHandleName40(
                            var name:       EMS_HandleName)
                            : Boolean;
        function        mapPagesJumpNum40(
                            buffer:         Pointer)
                            : Boolean;
        function        mapPagesJumpSeg40(
                            buffer:         Pointer)
                            : Boolean;
        function        mapPagesCallNum40(
                            buffer:         Pointer)
                            : Boolean;
        function        mapPagesCallSeg40(
                            buffer:         Pointer)
                            : Boolean;
        function        allocHandleStd40(
                            pages:          Word)
                            : Boolean;
        function        allocHandleRaw40(
                            pages:          Word)
                            : Boolean;

        end;


    procedure       ems_demoError(
                            func: String);

IMPLEMENTATION

var
    ems:                EMS_Ems;


(*
 *  Load up the assembly language modules:
 *)

{$L EMS40}
{$L EMS41}
{$L EMS42}
{$L EMS43}
{$L EMS44}
{$L EMS45}
{$L EMS46}
{$L EMS47}
{$L EMS48}
{$L EMS4B}
{$L EMS4C}
{$L EMS4D}
{$L EMS4E0}
{$L EMS4E1}
{$L EMS4E2}
{$L EMS4E3}
{$L EMS4F0}
{$L EMS4F1}
{$L EMS4F2}
{$L EMS500}
{$L EMS501}
{$L EMS51}
{$L EMS520}
{$L EMS521}
{$L EMS522}
{$L EMS530}
{$L EMS531}
{$L EMS540}
{$L EMS541}
{$L EMS542}
{$L EMS550}
{$L EMS551}
{$L EMS560}
{$L EMS561}
{$L EMS562}
{$L EMS570}
{$L EMS571}
{$L EMS580}
{$L EMS581}
{$L EMS590}
{$L EMS591}
{$L EMS5A0}
{$L EMS5A1}
{$L EMS5B0}
{$L EMS5B1}
{$L EMS5B2}
{$L EMS5B3}
{$L EMS5B4}
{$L EMS5B5}
{$L EMS5B6}
{$L EMS5B7}
{$L EMS5B8}
{$L EMS5C}
{$L EMS5D0}
{$L EMS5D1}
{$L EMS5D2}


function        EMS_Ems.getStatus
                    : Boolean;
                    external;
function        EMS_Ems.getPFA(
                    var page_frame: EMS_PageFrame)
                    : Boolean;
                    external;
function        EMS_Ems.getFreeEM(
                    var total:      Word;
                    var free:       Word)
                    : Boolean;
                    external;
function        EMS_Ems.getVersion(
                    var version:    Word)
                    : Boolean;
                    external;
function        EMS_Ems.getNumActiveHandles(
                    var num_handles: Word)
                    : Boolean;
                    external;
function        EMS_Ems.getPagesAllHandles(
                    var info:        EMS_HandleInfoArr;
                    var num_handles: Word)
                    : Boolean;
                    external;


function        EMS_Ems.savePageMap32(
                    save_buffer:    Pointer)
                    : Boolean;
                    external;
function        EMS_Ems.restPageMap32(
                    restore_buffer: Pointer)
                    : Boolean;
                    external;
function        EMS_Ems.swapPageMap32(
                    rest_buffer:    Pointer;
                    save_buffer:    Pointer)
                    : Boolean;
                    external;
function        EMS_Ems.getMapInfoSize32(
                    var size:       Word)
                    : Boolean;
                    external;


function        EMS_Ems.savePartialMap40(
                    map:            Pointer;
                    buffer:         Pointer)
                    : Boolean;
                    external;
function        EMS_Ems.restPartialMap40(
                    buffer:         Pointer)
                    : Boolean;
                    external;
function        EMS_Ems.getPMapInfoSize40(
                    pages: Word;
                    var buffSize:   Word)
                    : Boolean;
                    external;

function        EMS_Ems.getAttrCapability40(
                    var capability: Word)
                    : Boolean;
                    external;

function        EMS_Ems.getAllHandleNames40(
                    var info_list:  EMS_HandleNameInfoArr)
                    : Boolean;
                    external;

function        EMS_Ems.getTotalHandles40(
                    var handles:    Word)
                    : Boolean;
                    external;

function        EMS_Ems.getStackNeeded40(
                    var stack_space: Word)
                    : Boolean;
                    external;

function        EMS_Ems.moveMemRegion40(
                    var buffer:     EMS_MoveMemoryInfo)
                    : Boolean;
                    external;
function        EMS_Ems.swapMemRegions40(
                    var buffer:     EMS_MoveMemoryInfo)
                    : Boolean;
                    external;

function        EMS_Ems.getAddrsMappable40(
                    var buffer:     EMS_MappablePagesInfoArr;
                    var num_entries: Word)
                    : Boolean;
                    external;
function        EMS_Ems.getNumMappable40(
                    var mappablePages: Word)
                    : Boolean;
                    external;

function        EMS_Ems.getHWConfig40(
                    var buffer:     EMS_HardwareConfigInfo)
                    : Boolean;
                    external;

function        EMS_Ems.getNumRawPages40(
                    var total_pages: Word;
                    var free_pages: Word)
                    : Boolean;
                    external;

function        EMS_Ems.getAltMapRegs40(
                    var active_map: Byte;
                    var regs_area:  Byte)
                    : Boolean;
                    external;
function        EMS_Ems.setAltMapRegs40(
                    alt_set:        Byte;
                    var regs_area:  Byte)
                    : Boolean;
                    external;
function        EMS_Ems.getAltMapRegSize40(
                    var buf_size:   Word)
                    : Boolean;
                    external;
function        EMS_Ems.allocAltMapRegs40(
                    var alt_map:    Byte)
                    : Boolean;
                    external;
function        EMS_Ems.releaseAltMapRegs40(
                    alt_map:        Byte)
                    : Boolean;
                    external;

function        EMS_Ems.allocDMARegs40(
                    var regSet:     Byte)
                    : Boolean;
                    external;
function        EMS_Ems.enableDMA40(
                    regSet:         Byte;
                    channel:        Byte)
                    : Boolean;
                    external;
function        EMS_Ems.disableDMA40(
                    regSet:         Byte)
                    : Boolean;
                    external;
function        EMS_Ems.releaseDMARegs40(
                    regSet:         Byte)
                    : Boolean;
                    external;

function        EMS_Ems.prepEmmWarmBoot40
                    : Boolean;
                    external;
function        EMS_Ems.enableEmmOSFuncs40(
                    a1:             Word;
                    a2:             Word;
                    var a3:         Word;
                    var a4:         Word)
                    : Boolean;
                    external;
function        EMS_Ems.disableEmmOSFuncs40(
                    a1:             Word;
                    a2:             Word;
                    var a3:         Word;
                    var a4:         Word)
                    : Boolean;
                    external;
function        EMS_Ems.releaseAccessKey40(
                    a1:             Word;
                    a2:             Word)
                    : Boolean;
                    external;


function        EMS_EmBlk.allocEM(
                    pages:          Word)
                    : Boolean;
                    external;
function        EMS_EmBlk.mapPage(
                    physical_page:  Word;
                    logical_page:   Word)
                    : Boolean;
                    external;
function        EMS_EmBlk.freeEM
                    : Boolean;
                    external;
function        EMS_EmBlk.savePageMap
                    : Boolean;
                    external;
function        EMS_EmBlk.restorePageMap
                    : Boolean;
                    external;
function        EMS_EmBlk.getPagesForHandle(
                    var num_pages:  Word)
                    : Boolean;
                    external;
function        EMS_EmBlk.mapPagesByNum40(
                    pages:          Word;
                    buffer:         Pointer)
                    : Boolean;
                    external;
function        EMS_EmBlk.mapPagesByAddr40(
                    pages:          Word;
                    buffer:         Pointer)
                    : Boolean;
                    external;
function        EMS_EmBlk.reallocHandPages40(
                    pages:          Word)
                    : Boolean;
                    external;

function        EMS_EmBlk.getHandleAttr40(
                    var attribute:  Word)
                    : Boolean;
                    external;
function        EMS_EmBlk.setHandleAttr40(
                    attribute:      Word)
                    : Boolean;
                    external;
function        EMS_EmBlk.getHandleName40(
                    var handle_name: EMS_HandleName)
                    : Boolean;
                    external;
function        EMS_EmBlk.setHandleName40(
                    var handle_name: EMS_HandleName)
                    : Boolean;
                    external;
function        EMS_EmBlk.searchHandleName40(
                    var name:       EMS_HandleName)
                    : Boolean;
                    external;
function        EMS_EmBlk.mapPagesJumpNum40(
                    buffer:         Pointer)
                    : Boolean;
                    external;
function        EMS_EmBlk.mapPagesJumpSeg40(
                    buffer:         Pointer)
                    : Boolean;
                    external;
function        EMS_EmBlk.mapPagesCallNum40(
                    buffer:         Pointer)
                    : Boolean;
                    external;
function        EMS_EmBlk.mapPagesCallSeg40(
                    buffer:         Pointer)
                    : Boolean;
                    external;
function        EMS_EmBlk.allocHandleStd40(
                    pages:          Word)
                    : Boolean;
                    external;
function        EMS_EmBlk.allocHandleRaw40(
                    pages:          Word)
                    : Boolean;
                    external;


function EMS_Ems.init: Boolean;

var
    emmxxxx0_name:      String;
    emmxxxx0_handle:    Word;

    regs:               Registers;
    

begin
    (*
     *  Assume an error:
     *)
    errno:= EMSErrUnimp;

    (*
     *  Initialize the name:
     *)
    emmxxxx0_name:= 'EMMXXXX0'#0;

    (*
     *  Now try opening the device "EMMXXXX0"
     *)
    regs.DS:= Seg(emmxxxx0_name[1]);
    regs.DX:= Ofs(emmxxxx0_name[1]);
    regs.AL:= 0;                     { O_RDONLY }
    regs.AH:= $3D;                   { OPEN }
    regs.BX:= 0;
    regs.CX:= 0;
    regs.SI:= 0;
    regs.DI:= 0;
    MsDos(regs);

    if (regs.FLAGS and FCarry) <> 0 then begin
        (*
         *  There was some kind of error. EMS must be unavailable.
         *)

        init:= True;
        exit;        
        end;
    emmxxxx0_handle:= regs.AX;

    (*
     *  Now we've got something. We need to make sure it's not
     *  a file, but a device. ioctl() can give us this info.
     *)
    regs.AH:= $44;                   { IOCTL }
    regs.DS:= 0;
    regs.DX:= 0;
    regs.CX:= 0;
    regs.BX:= emmxxxx0_handle;
    regs.AL:= 0;
    MsDos(regs);
    if ((regs.FLAGS and FCarry) <> 0) or ((regs.DX and $80) = 0) then begin
        (*
         *  Error occured, or status was for a file. Close
         *  handle, and return FALSE.
         *)
        regs.AH:= $3E;
        regs.BX:= emmxxxx0_handle;
        MsDos(regs);

        init:= True;
        exit;
        end;

    (*
     *  Finally, check the output status. If it's 0 that's bad.
     *)
    regs.AH:= $44;                   { IOCTL }
    regs.DS:= 0;
    regs.DX:= 0;
    regs.CX:= 0;
    regs.BX:= emmxxxx0_handle;
    regs.AL:= 7;
    MsDos(regs);
    if ((regs.FLAGS and FCarry) <> 0) or (regs.AL = 0) then begin
        (*
         *  Error occured, or status was bad. Close
         *  handle, and return FALSE.
         *)
        regs.AH:= $3E;
        regs.BX:= emmxxxx0_handle;
        MsDos(regs);

        init:= True;
        exit;
        end;

    (*
     *  If we got here, we must be golden. Close the handle
     *  and return True.
     *)
    regs.AH:= $3E;
    regs.BX:= emmxxxx0_handle;
    MsDos(regs);

    (*
     *  No error:
     *)
    errno:= EMSErrOK;
    init:= False;
end;


function EMS_Ems.errorText(err: Word) : String;
begin

    case err of
        EMSErrOK:
            errorText:=  'No error';
        EMSErrInternal:
            errorText:=  'Internal EMM software error';
        EMSErrHardware:
            errorText:=  'EM Hardware error';
        EMSErrEMMBusy:
            errorText:=  'EMM Busy';
        EMSErrHandInv:
            errorText:=  'Handle Invalid';
        EMSErrUnimp:
            errorText:=  'Undefined EMS function';
        EMSErrNoHandles:
            errorText:=  'Handles Exhausted';
        EMSErrSaveRest:
            errorText:=  'Error in save/restore of context';
        EMSErrReqGTPhys:
            errorText:=  'Not enough physical EM for request';
        EMSErrReqGTAvail:
            errorText:=  'Not enough available EM for request';
        EMSErrReqIsZero:
            errorText:=  'Cannot allocate zero pages';
        EMSErrLogPgInv:
            errorText:=  'Invalid logical page number';
        EMSErrPhysPgInv:
            errorText:=  'Invalid physical page number';
        EMSErrSSAreaFull:
            errorText:=  'Mapping save area is full';
        EMSErrSaveFail:
            errorText:=  'Handle already has a saved state associated with it';
        EMSErrRestFail:
            errorText:=  'Handle has no saved state associated with it';
        EMSErrParameter:
            errorText:=  'Subfunction parameter not defined';
        EMSErrAttribute:
            errorText:=  'Attribute type not defined';
        EMSErrUnsupported:
            errorText:=  'Feature not supported';
        EMSErrOverlap:
            errorText:=  'Source/dest of move overlap, move performed';
        EMSErrLenInv:
            errorText:=  'Length of move request invalid';
        EMSErrOverlapCE:
            errorText:=  'Overlap of conventional and extended memory';
        EMSErrOffsetInv:
            errorText:=  'Offset outside logical page';
        EMSErrRegionGT1MB:
            errorText:=  'Region size > 1 megabyte';
        EMSErrOverlapFatal:
            errorText:=  'Source/dest overlap prevented move';
        EMSErrMemTypeInv:
            errorText:=  'Memory source/dest types invalid';
        EMSErrDMARegUnsupp:
            errorText:=  'Specified alternate register set unsupported';
        EMSErrNoDMARegs:
            errorText:=  'No available alternate register sets';
        EMSErrAltRegsUnsupp:
            errorText:=  'Alternate registers unsupported';
        EMSErrDMARegUndef:
            errorText:=  'Specified alternate register set undefined';
        EMSErrDMAChanUnsupp:
            errorText:=  'Dedicated DMA channels unsupported';
        EMSErrChanUnsupp:
            errorText:=  'Specified DMA channel unsupported';
        EMSErrNameNotFound:
            errorText:=  'No handle found for name';
        EMSErrNameExists:
            errorText:=  'Handle with same name already exists';
        EMSErrPointerInv:
            errorText:=  'Invalid pointer or source array bogus';
        EMSErrAccess:
            errorText:=  'Access denied by operating system';
    else
            errorText:= 'Unknown error 0x' + hex(err, 2);
        end;

end;

procedure ems_demoError(func: String);

begin

    (*
     *  Report the error:
     *)
    writeln('Error on ',
                func, '(): "', ems.errorText(errno), '"');
    Halt;
end;
    
end.

