home *** CD-ROM | disk | FTP | other *** search
- title expanded memory interace
- include asm.inc
-
- public ems_exchange
- public ems_in
- public ems_out
-
- EMS_MAX equ 1024 ; (must be multiple of 8)
- NULL_EMS equ 0
-
- move_source_dest_struct struc ; from "official" LIM EMS 4.0 Spec - page 3-87
- region_length dd ?
- source_memory_type db ?
- source_handle dw ?
- source_initial_offset dw ?
- source_initial_seg_page dw ?
- dest_memory_type db ?
- dest_handle dw ?
- dest_initial_offset dw ?
- dest_initial_seg_page dw ?
- move_source_dest_struct ends
-
-
- XIB segment word public 'DATA' ; enable exit intercept during
- XIB ends ; intialization
- XI segment word public 'DATA'
- dw enable_exit_intercept
- XI ends
- XIE segment word public 'DATA'
- XIE ends
-
- XCB segment word public 'DATA' ; always release EMS on termination
- XCB ends
- XC segment word public 'DATA'
- dw ems_close
- XC ends
- XCE segment word public 'DATA'
- XCE ends
-
-
- .data?
- ems_struc move_source_dest_struct <>
-
- ems_count dw ? ; number of allocated pages
- ems_handle dw ?
-
- ems_ecount dw ?
- ems_icount dw ?
- ems_ocount dw ?
-
- ems_version db ?
- ems_flag db ?
-
- ems_bits db EMS_MAX/8 dup(?)
-
-
- .const
- ertx_ems_index db 'Bad EMS index',0
- ertx_ems_error db 'Error in EMS',0
-
-
- .code
- extn set_strerror,get_vector,enable_exit_intercept
-
-
- ;; do ems function
- ;
- ; exit Cf if error (sets error string)
- ;
- do_ems_function proc
- int 67h
- or ah,ah
- jnz def1 ; if EMS error
- ret
-
- def1: lea ax,ertx_ems_error ; *Error in EMS*
- jmp set_strerror
- do_ems_function endp
-
-
- ;; do ems raw
- ;
- ; exit Cf if error (doesn't set error string)
- ;
- do_ems_raw proc
- int 67h
- or ah,ah
- jnz der1 ; if EMS error
- ret
- der1: stc
- ret
- do_ems_raw endp
-
-
- ;; ems close
- ;
- ; uses AX,DX
- ;
- ems_close proc
- movx dx,NULL_EMS
- xchg dx,ems_handle[bp]
- cmpx dx,NULL_EMS
- je ecl1 ;\ if EMS not in use
-
- mov ah,45h ; deallocate pages
- call do_ems_function
- ecl1: ret
- ems_close endp
-
-
- ;; ems exchange
- ;
- ; entry AX page index (1..n)
- ; ES:DI destination
- ; exit Cf if bad block or EMS error
- ; uses AX
- ;
- ems_exchange proc
- pushm si,ds ; adjust and set EMS page index
- dec ax
- mov ems_struc.dest_initial_seg_page[bp],ax
-
- call read_move_struc
- jc eex1 ; if no EMS
- mov dest_handle[si],ax
-
- movx ax,0 ; fill in move structure
- mov source_memory_type[si],al
- mov source_handle[si],ax
- mov source_initial_offset[si],di
- mov source_initial_seg_page[si],es
- mov dest_memory_type[si],1
- mov dest_initial_offset[si],ax
-
- mov ax,5701h ; exchange RAM and EMS
- call do_ems_function
- inc ems_ecount[bp]
-
- eex1: popm ds,si
- ret
- ems_exchange endp
-
-
- ;; ems in
- ;
- ; entry AX block index (1..n)
- ; ES:DI destination (no transfer if NULL)
- ; exit Cf if bad block or EMS error
- ; uses AX
- ;
- ems_in proc
- pushm cx,si,ds
- dec ax ; clear index bit
- js ein2 ; if bad swap index (cannot be -)
- mov si,ax
- mov cl,3 ; (divide bit number by 8 to select
- shr si,cl ; byte)
-
- mov cl,al ; (use the 3 least significant bits
- and cl,7 ; to rotate a mask)
- mov ch,10000000b
- ror ch,cl
- test ems_bits[bp+si],ch
- jz ein2 ; if bad EMS index
- xor ems_bits[bp+si],ch ; (Cf=0)
-
- mov cx,es ; do not read EMS file if NULL output
- jcxz ein1 ; if NULL destination (Cf==0)
-
- ; set structure for move memory region
- mov ems_struc.source_initial_seg_page[bp],ax
-
- call read_move_struc
- jc ein1 ; if no EMS
- mov source_handle[si],ax
-
- movx ax,0
- mov source_memory_type[si],1
- mov source_initial_offset[si],ax
- mov dest_memory_type[si],al
- mov dest_handle[si],ax
- mov dest_initial_offset[si],di
- mov dest_initial_seg_page[si],es
-
- mov ax,5700h ; move from EMS to RAM
- call do_ems_function
- inc ems_icount[bp]
-
- ein1: popm ds,si,cx
- ret
-
- ein2: lea ax,ertx_ems_index ; *Bad EMS index*
- call set_strerror
- jmp ein1
- ems_in endp
-
-
- ;; ems out
- ;
- ; entry ES:DI source
- ; exit AX block index (1..n)
- ; Cf if EMS full or EMS error
- ;
- ems_out proc
- pushm cx,si,ds
- call read_move_struc ; set structure for move memory region
- jc eou2 ; if no EMS
- mov dest_handle[si],ax
-
- movx ax,0
- mov source_memory_type[si],al
- mov source_handle[si],ax
- mov source_initial_offset[si],di
- mov source_initial_seg_page[si],es
- mov dest_memory_type[si],1
- mov dest_initial_offset[si],ax
-
- call get_ems_index ; select next free EMS block
- jc eou2 ; if EMS bit map full
- mov dest_initial_seg_page[si],ax
- mov cx,ax
-
- cmp ax,ems_count[bp] ; check EMS allocation
- jb eou1 ; if enough EMS pages allocated
- call realloc_more_ems ; else get more ESM from driver
- jc eou2 ; if EMS full
-
- eou1: mov ax,5700h ; move from EMS to RAM
- call do_ems_function
- inc ems_ocount[bp]
-
- mov ax,cx ; return EMS index (1..MAX)
- inc ax
-
- eou2: popm ds,si,cx
- ret
- ems_out endp
-
-
- ;; get ems index
- ;
- ; exit AX ems index (0..MAX-1)
- ; Cf if no (more) EMS
- ; uses CX
- ;
- get_ems_index proc
- push si
- mov al,1
- mov cx,EMS_MAX
- lea si,ems_bits-1
-
- even ; search ems bits for first free index
- gei1: ror al,1
- adc si,ZER0
- test al,[bp+si]
- loopnz gei1
- stc
- jnz gei2 ; if EMS full
- or [bp+si],al
-
- mov ax,EMS_MAX-1
- sub ax,cx
-
- gei2: pop si
- ret
- get_ems_index endp
-
-
- ;; get ems version
- ;
- ; exit AL EMS version or 0 if no EMS
- ; uses SI,DS
- ;
- get_ems_version proc
- mov al,67h
- call get_vector
- mov si,0Ah
- lodsw
- cmp ax,'ME'
- jne gev1 ; if no EMS
- lodsw
- cmp ax,'XM'
- jne gev1 ; if no EMS
- lodsw
- cmp ax,'XX'
- jne gev1 ; if no EMS
- lodsw
- cmp ax,'0X'
- jne gev1 ; if no EMS
-
- mov ah,46h ; get EMS version
- call do_ems_function
- jnc gev2
-
- gev1: movx ax,0
- stc
- gev2: ret
- get_ems_version endp
-
-
- ;; read move struc
- ;
- ; exit AX EMS handle
- ; DS:SI "move source dest" structure
- ; Cf if no EMS
- ; note all members set to zero except region_length
- ;
- read_move_struc proc
- mov ax,ems_handle[bp]
- cmpx ax,NULL_EMS
- je rms2 ; if no ems
-
- rms1: movx ds,DGROUP_SEGMENT
- lea si,ems_struc
- mov wptr region_length[si],BLOCK_SIZE
- mov wptr region_length[si+2],ZER0
- clc
- ret
-
- rms2: mov al,-1
- xchg al,ems_flag[bp]
- add al,-1
- jc rms4 ; if previous attempt failed
-
- call get_ems_version
- mov ems_version[bp],al
- cmp al,40h
- jb rms4 ; if EMS missing or out of date
-
- rms3: mov ah,43h ; get EMS handle
- pushm bx,dx
- mov bx,1 ; allocate just 1 page
- call do_ems_raw
- mov ax,dx
- popm dx,bx
- jc rms4 ; if no EMS available (probably)
- mov ems_handle[bp],ax
- mov ems_count[bp],1
-
- cmpx ax,NULL_EMS ; reject a zero EMS handle (Cf=0)
- je rms3 ; if bad handle
- jmp rms1
-
- rms4: ret
- read_move_struc endp
-
-
- ;; realloc more ems
- ;
- ; exit Cf if no more EMS
- ; uses AX
- ;
- realloc_more_ems proc
- pushm bx,dx
- mov bx,ems_count[bp]
- inc bx
- mov dx,ems_handle[bp]
- mov ah,51h
- call do_ems_raw
- jc rme1 ; if out of EMS
- mov ems_count[bp],bx
- rme1: popm dx,bx
- ret
- realloc_more_ems endp
-
- end
-