; =====================================================
; Это интерфейсный модуль для вызова функций
; XMS из Си. Текст программы рассчитан на
; модель памяти Small
;
; (C) A. Frolov, 1997
;
; E-mail: frolov@glas.apc.org
; WWW:    http://www.glasnet.ru/~frolov
;            or
;         http://www.dials.ccas.ru/frolov
; =====================================================
  .model small

  .DATA

; В этом месте будет храниться адрес
; управляющей функции XMM

XMM_Control  dd   ?

          .CODE

; Макроопределения для выполнения соглашения об
; использовании регистров в процедурах Си

c_begin macro
  push bp
  mov  bp,sp
  push si
  push di
  endm

c_end   macro
  pop  di
  pop  si
  mov  sp,bp
  pop  bp
  ret
  endm

; Все процедуры должны быть public

  public _XMM_Installed
  public _XMM_Version
  public _XMM_RequestHMA
  public _XMM_ReleaseHMA
  public _XMM_GlobalEnableA20
  public _XMM_GlobalDisableA20
  public _XMM_EnableA20
  public _XMM_DisableA20
  public _XMM_QueryA20
  public _XMM_QueryLargestFree
  public _XMM_QueryTotalFree
  public _XMM_AllocateExtended
  public _XMM_FreeExtended
  public _XMM_MoveExtended
  public _XMM_LockExtended
  public _XMM_UnLockExtended
  public _XMM_GetHandleLength
  public _XMM_GetHandleInfo
  public _XMM_ReallocateExtended
  public _XMM_RequestUMB
  public _XMM_ReleaseUMB

;**
;.Name         _XMM_Installed
;.Title        Получение адреса управляющей функции
;
;.Descr        Эта функция проверяет наличие драйвера
;              HIMEM.SYS и в случае его присуствия
;              запоминает адрес управляющей функции.
;
;.Proto        unsigned XMM_Installed(void);
;
;.Params       Не используются
;
;.Return       0 - драйвер HIMEM.SYS не установлен;
;              1 - драйвер HIMEM.SYS установлен.
;
;**

_XMM_Installed proc near
          c_begin

          mov  ax, 4300h
          int  2fh
          cmp  al, 80h
          jne  NotInstalled

          mov  ax, 4310h
          int  2fh
          mov  word ptr [XMM_Control], bx
          mov  word ptr [XMM_Control+2], es
          mov  ax,1
          jmp  Installed

NotInstalled:
          mov  ax, 0
Installed:
          c_end
_XMM_Installed endp

;**
;.Name         _XMM_Version
;.Title        Определение версии драйвера HIMEM.SYS
;
;.Descr        Эта функция определяет версию драйвера
;              HIMEM.SYS
;
;.Proto        long  XMM_Version(void);
;
;.Params       Не используются
;
;.Return       Номер версии в младших 16 битах,
;              номер изменений - в старших 16 битах
;              возвращаемого значения
;
;**

_XMM_Version proc near
          push si
          push di
          xor  ah, ah
          call [XMM_Control]
          mov  dx, bx
          pop  di
          pop  si
          ret
_XMM_Version endp

;**
;.Name         _XMM_RequestHMA
;.Title        Запросить область HMA
;
;.Descr        Эта функция пытается зарезервировать для
;              программы область HMA
;
;.Proto        long  XMM_RequestHMA(unsigned space);
;
;.Params       space - размер требуемой области для
;                      TSR-программы или драйвера,
;                      0xffff для прикладной программы;
;
;.Return       < 0 - область HMA не назначена программе,
;                    код ошибки находится в старшем байте.
;              0L  - область HMA назначена программе.
;
;**

_XMM_RequestHMA proc near
          c_begin
          mov  ah, 1
          mov  dx, [bp+4]
          call [XMM_Control]
          xor  dx, dx
          dec  ax
          jz   @success
          mov  dh, bl
@success:
          c_end
_XMM_RequestHMA endp

;**
;.Name         _XMM_ReleaseHMA
;.Title        Освободить область HMA
;
;.Descr        Эта функция пытается освободить
;              область HMA
;
;.Proto        long  XMM_ReleaseHMA(void);
;
;.Params       Не используются
;
;.Return       < 0 - область HMA не освобождена,
;                    код ошибки находится в старшем байте.
;              0L - область HMA освобождена.
;
;**

_XMM_ReleaseHMA proc near
          c_begin
          mov  ah, 2
          call [XMM_Control]
          xor  dx, dx
          dec  ax
          jz   @success1
          mov  dh, bl
@success1:
          c_end
_XMM_ReleaseHMA endp

;**
;.Name         _XMM_GlobalEnableA20
;.Title        Глобальное разрешение линии A20
;
;.Descr        Эта функция разрешает программе, получившей
;              доступ к области HMA использовать линию A20
;
;.Proto        long  XMM_GlobalEnableA20(void);
;
;.Params       Не используются
;
;.Return       < 0 - линия A20 не включена,
;                    код ошибки находится в старшем байте.
;              0L  - линия A20 включена.
;
;**

_XMM_GlobalEnableA20 proc near
          c_begin
          mov  ah, 3
          call [XMM_Control]
          xor  dx, dx
          dec  ax
          jz   @success2
          mov  dh, bl
@success2:
          c_end
_XMM_GlobalEnableA20 endp

;**
;.Name         _XMM_GlobalDisableA20
;.Title        Глобальное запрещение линии A20
;
;.Descr        Эта функция запрещает программе, получившей
;              доступ к области HMA использовать линию A20
;
;.Proto        long  XMM_GlobalDisableA20(void);
;
;.Params       Не используются
;
;.Return       < 0 - линия A20 не выключена,
;                    код ошибки находится в старшем байте.
;              0L  - линия A20 выключена.
;
;**

_XMM_GlobalDisableA20 proc near
          c_begin
          mov  ah, 4
          call [XMM_Control]
          xor  dx, dx
          dec  ax
          jz   @success3
          mov  dh, bl
@success3:
          c_end
_XMM_GlobalDisableA20 endp

;**
;.Name         _XMM_EnableA20
;.Title        Локальное разрешение линии A20
;
;.Descr        Эта функция разрешает программе управлять
;              областью расширенной памяти.
;
;.Proto        long  XMM_EnableA20(void);
;
;.Params       Не используются
;
;.Return       < 0 - линия A20 не включена,
;                    код ошибки находится в старшем байте.
;              0L  - линия A20 включена.
;
;**

_XMM_EnableA20 proc near
          c_begin
          mov  ah, 5
          call [XMM_Control]
          xor  dx, dx
          dec  ax
          jz   @success4
          mov  dh, bl
@success4:
          c_end
_XMM_EnableA20 endp

;**
;.Name         _XMM_DisableA20
;.Title        Локальное запрещение линии A20
;
;.Descr        Эта функция запрещает программе управлять
;              областью расширенной памяти.
;
;.Proto        long  XMM_DisableA20(void);
;
;.Params       Не используются
;
;.Return       < 0 - линия A20 не выключена,
;                    код ошибки находится в старшем байте.
;              0L  - линия A20 выключена.
;
;**

_XMM_DisableA20 proc near
          c_begin
          mov  ah, 6
          call [XMM_Control]
          xor  dx, dx
          dec  ax
          jz   @success5
          mov  dh, bl
@success5:
          c_end
_XMM_DisableA20 endp

;**
;.Name         _XMM_QueryA20
;.Title        Проверить состояние линии A20
;
;.Descr        Эта функция проверяет доступность
;              линии A20
;
;.Proto        long  XMM_QueryA20(void);
;
;.Params       Не используются
;
;.Return       < 0 - ошибка,
;                    код ошибки находится в старшем байте.
;              0L  - линия A20 выключена,
;              1L  - линия A20 включена.
;
;**

_XMM_QueryA20 proc near
          c_begin
          mov  ah, 7
          call [XMM_Control]
          xor  dx, dx
          or   ax, ax
          jnz  @success6
          mov  dh, bl
@success6:
          c_end
_XMM_QueryA20 endp

;**
;.Name         _XMM_QueryLargestFree
;.Title        Определить максимальный размер блока
;
;.Descr        Эта функция возвращает размер максимального
;              непрерывного блока расширенной памяти,
;              который доступен программе.
;
;.Proto        long  XMM_QueryLargestFree(void);
;
;.Params       Не используются
;
;.Return       < 0 - ошибка,
;                    код ошибки находится в старшем байте.
;              >= 0 - размер блока.
;
;**

_XMM_QueryLargestFree proc near
          c_begin
          mov  ah, 8
          call [XMM_Control]
          xor  dx, dx
          or   ax, ax
          jnz  @success7
          mov  dh, bl
@success7:
          c_end
_XMM_QueryLargestFree endp

;**
;.Name         _XMM_QueryTotalFree
;.Title        Определить размер расширенной памяти
;
;.Descr        Эта функция возвращает размер
;              всей имеющейся расширенной памяти.
;
;.Proto        long  XMM_QueryTotalFree(void);
;
;.Params       Не используются
;
;.Return       < 0 - ошибка,
;                    код ошибки находится в старшем байте.
;              >= 0 - размер расширенной памяти.
;
;**

_XMM_QueryTotalFree proc near
          c_begin
          mov  ah, 8
          call [XMM_Control]
          or   ax, ax
          mov  ax, dx
          mov  dx, 0
          jnz  @success8
          mov  dh, bl
@success8:
          c_end
_XMM_QueryTotalFree endp

;**
;.Name         _XMM_AllocateExtended
;.Title        Запросить блок расширенной памяти
;
;.Descr        Эта функция выделяет программе блок
;              расширенной памяти, в случае успеха
;              возвращает индекс полученного блока.
;
;.Proto        long XMM_AllocateExtended(unsigned space);
;
;.Params       space - размер требуемого блока памяти
;                      в килобайтах;
;
;.Return       < 0 - блок не распределен,
;                    код ошибки находится в старшем байте.
;              > 0L  - младший байт содержит индекс
;                      полученного блока памяти.
;
;**

_XMM_AllocateExtended proc near
          c_begin
          mov  ah, 9
          mov  dx,  [bp+4]
          call [XMM_Control]
          or   ax, ax
          mov  ax, dx
          mov  dx, 0
          jnz  @success9
          mov  dh, bl
@success9:
          c_end
_XMM_AllocateExtended endp

;**
;.Name         _XMM_FreeExtended
;.Title        Освободить блок расширенной памяти
;
;.Descr        Эта функция освобождает блок
;              расширенной памяти, полученный функцией
;              XMM_AllocateExtended().
;
;.Proto        long XMM_FreeExtended(unsigned handle);
;
;.Params       handle - индекс освобождаемого блока памяти;
;
;.Return       < 0 - блок не распределен,
;                    код ошибки находится в старшем байте.
;              0L  - блок освобожден.
;
;**

_XMM_FreeExtended proc near
          c_begin
          mov  ah, 0Ah
          mov  dx, [bp+4]
          call [XMM_Control]
          xor  dx, dx
          dec  ax
          jz   @successA
          mov  dh, bl
@successA:
          c_end
_XMM_FreeExtended endp

;**
;.Name         _XMM_MoveExtended
;.Title        Копировать блок расширенной памяти
;
;.Descr        Эта функция копирует блок
;              расширенной памяти, используя структуру
;              struct XMM_Move:
;
;                 struct   XMM_Move {
;                    unsigned long  Length;
;                    unsigned short SourceHandle;
;                    unsigned long  SourceOffset;
;                    unsigned short DestHandle;
;                    unsigned long  DestOffset;
;                 };
;
;.Proto        long  XMM_MoveExtended(struct
;                       XMM_Move *move_descr);
;
;.Params       struct XMM_Move *move_descr -
;                 указатель на структуру, описывающую
;                 что, откуда и куда надо копировать.
;
;.Return       < 0 - ошибка при копировании,
;                    код ошибки находится в старшем байте.
;              0L  - блок скопирован успешно.
;
;**

_XMM_MoveExtended proc near
          c_begin
          mov  ah, 0Bh
          mov  si, [bp+4];
          call [XMM_Control]
          xor  dx, dx
          dec  ax
          jz   @successB
          mov  dh, bl
@successB:
          c_end
_XMM_MoveExtended endp

;**
;.Name         _XMM_LockExtended
;.Title        Заблокировать блок расширенной памяти
;
;.Descr        Эта функция блокирует блок расширенной
;              памяти и возвращает 31 разряд его
;              физического адреса.
;
;.Proto        long XMM_LockExtended(unsigned handle);
;
;.Params       handle - индекс блокируемого блока памяти;
;
;.Return       < 0 - блок не заблокирован,
;                    код ошибки находится в старшем байте.
;              > 0L  - блок заблокирован, функция
;                      возвращает физический адрес блока
;                      памяти.
;
;**

_XMM_LockExtended proc near
          c_begin
          mov  ah, 0Ch
          mov  dx, [bp+4]
          call [XMM_Control]
          xchg ax, bx
          dec  bx
          jz   XMML_Success
          mov  dh, al
XMML_Success:
                c_end
_XMM_LockExtended endp

;**
;.Name         _XMM_UnLockExtended
;.Title        Разблокировать блок расширенной памяти
;
;.Descr        Эта функция разблокирует блок расширенной
;              памяти.
;
;.Proto        long XMM_UnLockExtended(unsigned handle);
;
;.Params       handle - индекс блока памяти;
;
;.Return       < 0 - блок не разблокирован,
;                    код ошибки находится в старшем байте.
;              0L  - блок разблокирован.
;
;**

_XMM_UnLockExtended proc near
          c_begin
          mov  ah, 0Dh
          mov  dx, [bp+4]
          call [XMM_Control]
          xor  dx, dx
          dec  ax
          jz   @successC
          mov  dh, bl
@successC:
          c_end
_XMM_UnLockExtended endp

;**
;.Name         _XMM_GetHandleLength
;.Title        Получить длину блока расширенной памяти
;
;.Descr        Эта функция возвращает длину блока
;              расширенной памяти по его индексу.
;
;.Proto        long XMM_GetHandleLength(unsigned handle);
;
;.Params       handle - индекс блока памяти;
;
;.Return       < 0 - произошла ошибка,
;                    код ошибки находится в старшем байте.
;              > 0L  - длина блока в килобайтах.
;
;**

_XMM_GetHandleLength proc near
          c_begin
          mov  ah, 0Eh
          mov  dx, [bp+4]
          call [XMM_Control]
          or   ax, ax
          mov  ax, dx
          mov  dx, 0
          jnz  @successD
          mov  dh, bl
@successD:
          c_end
_XMM_GetHandleLength endp

;**
;.Name         _XMM_GetHandleInfo
;.Title        Получить информацию о блоке расширенной памяти
;
;.Descr        Эта функция возвращает общее
;              количество индексов в системе и
;              содержимое счетчика блокирования для
;              заданного индекса.
;
;.Proto        long XMM_GetHandleInfo(unsigned handle);
;
;.Params       handle - индекс блока памяти;
;
;.Return       < 0 - произошла ошибка,
;                    код ошибки находится в старшем байте.
;              > 0L  - младший байт - общее количество
;                      индексов в системе;
;                      старший байт - счетчик блокирования.
;
;**

_XMM_GetHandleInfo proc near
          c_begin
          mov  ah, 0Eh
          mov  dx, [bp+4]
          call [XMM_Control]
          mov  dx, bx
          or   ax, ax
          mov  ax, dx
          mov  dx, 0
          jnz  @successE
          mov  dh, bl
@successE:
          c_end
_XMM_GetHandleInfo endp

;**
;.Name         _XMM_ReallocateExtended
;.Title        Изменить размер блока расширенной памяти
;
;.Descr        Эта функция изменяет размер выделенного
;              блока расширенной памяти.
;
;.Proto        long XMM_ReallocateExtended(unsigned handle,
;                 unsigned new_size);
;
;.Params       handle - индекс блока памяти;
;              new_size - новый размер блока памяти
;                      в килобайтах;
;
;.Return       < 0 - блок не распределен,
;                    код ошибки находится в старшем байте.
;              > 0L  - младший байт содержит индекс
;                      полученного блока памяти.
;
;**

_XMM_ReallocateExtended proc near
          c_begin
          mov  ah, 0Fh
          mov  dx, [bp+4]
          mov  bx, [bp+6]
          call [XMM_Control]
          xor  dx, dx
          dec  ax
          jz   @successF
          mov  dh, bl
@successF:
          c_end
_XMM_ReallocateExtended endp

;**
;.Name         _XMM_RequestUMB
;.Title        Запросить область UMB
;
;.Descr        Эта функция пытается зарезервировать для
;              программы область UMB
;
;.Proto        long  XMM_RequestUMB(unsigned space);
;
;.Params       space - размер требуемой области
;                      в параграфах;
;
;.Return       < 0 - область UMB не назначена программе,
;                    код ошибки находится в старшем байте;
;                    максимальный размер доступного блока
;                    в младшем слове (16 разрядов);
;              > 0L  - область UMB назначена программе,
;                    младшее слово содержит сегмент блока
;                    UMB, старший - размер выделенного
;                    блока UMB.
;
;**

_XMM_RequestUMB proc near
          c_begin
          mov  ah, 10h
          mov  dx, [bp+4]
          call [XMM_Control]
          xchg bx, ax
          dec  bx
          jz   RUMB_Success
          xchg ax, dx
          mov  dh, dl
RUMB_Success:
          c_end
_XMM_RequestUMB endp

;**
;.Name         _XMM_ReleaseUMB
;.Title        Освободить область UMB
;
;.Descr        Эта функция пытается освободить
;              область UMB
;
;.Proto        long  XMM_ReleaseUMB(unsigned segment);
;
;.Params       segment - сегмент освобождаемого блока UMB*
;
;.Return       < 0 - область UMB не освобождена,
;                    код ошибки находится в старшем байте.
;              0L - область UMB освобождена.
;
;**

_XMM_ReleaseUMB proc near
          c_begin
          mov  ah, 11h
          mov  dx, [bp+4]
          call [XMM_Control]
          xor  dx, dx
          dec  ax
          jz   @success10
          mov  dh, bl
@success10:
          c_end
_XMM_ReleaseUMB endp

  END
