home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware 1 2 the Maxx
/
sw_1.zip
/
sw_1
/
PROGRAM
/
SPAWNO40.ZIP
/
SOURCE.ZIP
/
SWAP_EMS.ASM
< prev
next >
Wrap
Assembly Source File
|
1991-11-17
|
11KB
|
390 lines
IFNDEF __TPINC
NAME swap_ems
TITLE SPAWNO EMS swapping code
PAGE 60,132
;-----------------------------------
; (c) Copyright 1990,1991 Ralf Brown All Rights Reserved
; This file may be redistributed as a part of the complete SPAWNO package,
; under its distribution conditions
;
; SPAWNO v4.00
; Overlaying spawnv()
;
; File: SWAP_EMS
;-----------------------------------
__BSS__ equ 1 ; yes, we are using uninitialized storage
INCLUDE RULES.ASI ; define the various standard macros
INCLUDE SPAWNO.INC
Header@ ; set up segment and group definitions
ENDIF ;ndef __TPINC
;-----------------------------------------------------------
; data with relocatable items
JSeg@
public@ __SPAWNO_FUNCS_EMS
__SPAWNO_FUNCS_EMS label byte
dw spawno_init_ems ; called to determine whether to swap to EMS
dw write_block_ems ; called to write out memory
dw spawno_swapdone_ems ; called when all memory written out
dw spawno_swapin_ems ; called when ready to read back memory
dw read_ems ; called to read back a section of memory
dw spawno_finish_ems ; called to clean up at very end of swap
dw $ems_overlay ; address of code to append to resident stub
dw ems_overlay_size ; total size of code to be appended
dw ems_overlay_res ; number of bytes which must stay resident
JSegEnd@
;-----------------------------------------------------------
; initialized data
DSeg@
EMM_name DB "EMMXXXX0"
IFNDEF RBcomm
PubSym@ __spawn_ems,<DB 1>,__CDECL__ ; are we allowed to swap to EMS?
ELSE
ExtSym@ __spawn_ems,BYTE,__CDECL__
ENDIF ;RBcomm
DSegEnd@
;----------------------------------------------------------------
; uninitialized data storage area
BSeg@
ems_page_num dw ? ; current page number for EMS handle
ems_page_offset dw ? ; offset (in para) withing page
ems_page_num$ dw ? ; page number after reading in PSP
ems_page_offset$ dw ? ; offset (in bytes) after reading in PSP
BSegEnd@
;----------------------------------------------------------------
CSeg@
;----------------------------------------------------------------
; section of code to append to the common code when using EMS for
; swapping
;
; on entry,
; DX = segment at which to start reloading memory
; CS = DS = segment of program's PSP
; AX, BX, CX, SI, DI, ES unpredictable
; at exit:
; SS:SP must be preserved, but all other registers can be destroyed
; The device-specific code is always entered at the very beginning and
; must exit either by falling off the end or by branching to "abort_offset"
; bytes prior to its beginning with DS=CS (the latter only if it detects
; an error from which it cannot recover).
;
$ems_overlay proc far
ems_reloc_factor equ (offset $ems_overlay - resident_addr)
ASSUME DS:NOTHING
mov es,dx ; ES <- seg at which to start loading
ASSUME ES:NOTHING
xor bx,bx ; start on logical page 0
mov dx,0 ; DX <- EMS handle (will be patched)
$ems_handle equ word ptr ($-2)
ems_reload_loop:
mov ax,4400h ; map logical page into physical page 0
int 67h
or ah,ah ; was "map" call successful?
jnz short ($ems_overlay - abort_offset) ; quit if not
mov ax,0 ; AX <- EMS page frame seg (will patch)
page_frame_seg equ word ptr ($-2)
mov ds,ax ; DS -> page frame
ASSUME DS:NOTHING
mov cx,2000h ; 16K bytes = 8K words
$ems_partial equ word ptr ($-2)
xor si,si ; source offset is 0
xor di,di ; dest offset is 0
rep movsw
jmp short copied_page ; flush prefetch queue
ems_overlay_res equ $ - $ems_overlay
;
; everything beyond this point may be overwritten by the child program, since
; the first read above will restore it back to memory
;
$ems_pages dw 0 ; number of pages, excluding partial last
; will be filled in before copy to PSP
copied_page:
inc bx ; go to next logical page
mov ax,es ; move 16K higher in memory
add ax,400h
mov es,ax
dec word ptr cs:($ems_pages - ems_reloc_factor)
jg ems_reload_loop ; if not yet last, go do another full page
mov word ptr cs:($ems_partial - ems_reloc_factor),0
$ems_partial_size equ word ptr ($-2)
jz ems_reload_loop ; loop one last time if count reached 0
;
; exit by falling out of this subroutine
;
$ems_overlay endp
ems_overlay_size equ $ - $ems_overlay
;----------------------------------------------------------------
; entry: AX = start segment within EMS page frame
; ES = conventional-memory transfer segment
; exit: DS, ES = source, destination of copy
; DX = new conventional-memory transfer address
;----------------------------------------------------------------
set_segment_read proc near
mov ds,ax ; AX = start segment in EMS page frame
ASSUME DS:NOTHING
mov dx,es
ret
set_segment_read endp
set_segment_write proc near
mov dx,es
mov ds,dx
mov es,ax ; AX = start segment in EMS page frame
ret
set_segment_write endp
;----------------------------------------------------------------
; enter: AX=starting segment
; BX = handle
; DX=num paras
; return: CF clear on success, set if failed
; AX, BX, CX, DX, ES destroyed
;----------------------------------------------------------------
read_ems proc near
ASSUME DS:DGROUP
mov cx,offset __TEXT:set_segment_read
jmp short transfer_EMS
read_ems endp
;----------------------------------------------------------------
; entry: AX = starting segment
; BX = handle
; DX = number of paragraphs
; return: CF clear on success, set if failed
; AX, BX, CX, DX, ES destroyed
;----------------------------------------------------------------
write_block_ems proc near
mov cx,offset __TEXT:set_segment_write
transfer_EMS:
push bp
mov bp,bx ; store handle
ASSUME DS:DGROUP
mov es,ax
ASSUME ES:NOTHING
push di
push si
xchg cx,dx
xfer_ems_loop:
push dx
mov ax,4400h ; map physical page 0
mov bx,ems_page_num
mov dx,bp ; DX <- handle
int 67h ; map in the appropriate EMS page
or ah,ah
jnz EMS_mapping_failed
mov bx,ems_page_offset
mov dx,bx
sub bx,400h ; 1024 paragraphs in a 16K EMS page
neg bx ; adjust for doing sub the wrong way
cmp bx,cx
jbe xfer_ems_fullpage
mov bx,cx
add ems_page_offset,bx
jmp short xfer_ems_do_it
xfer_ems_fullpage:
xor ax,ax
mov ems_page_offset,ax
inc ems_page_num
xfer_ems_do_it:
mov ax,page_frame_seg
add ax,dx
cmp ax,ax ; set ZF to indicate success
EMS_mapping_failed:
pop dx
jnz xfer_ems_failed
push ds
push dx
call dx ; set DS, ES, and DX
ASSUME DS:NOTHING,ES:NOTHING
xor si,si
xor di,di
push cx
mov cx,bx
shl cx,1
shl cx,1
shl cx,1 ; paragraphs to words
cld
rep movsw ; copy as much memory as we can
pop cx
add dx,bx
mov es,dx ; move higher in mem by amount copied
pop dx
pop ds
ASSUME DS:DGROUP
sub cx,bx ; update amount remaining
jnz xfer_ems_loop
clc ; tell caller we succeeded
xfer_ems_done:
pop si
pop di
pop bp
ret
xfer_ems_failed:
stc ; tell caller we failed
jmp xfer_ems_done
write_block_ems endp
;----------------------------------------------------------------
; return the number of EMS pages which are available (0 if no EMS) in AX
;
IFDEF RBcomm
public _EMS_available
ENDIF ;RBcomm
_EMS_available proc near
ASSUME DS:DGROUP
push es
push si
push di
mov ax,3567h
int 21h ; get vector for EMS driver
mov di,10 ; ES:DI -> driver name
mov si,offset DGROUP:EMM_name
mov cx,8 ; length EMM_name
cld
xor ax,ax ; assume no match
repz cmps EMM_name,byte ptr es:[di]
jnz EMS_avail_done
mov ah,42h
int 67h
or ah,ah ; was call successful?
mov ax,bx ; assume yes, return # of pages available
jz EMS_avail_done
xor ax,ax ; nope, so return zero
EMS_avail_done:
pop di
pop si
pop es
ret
_EMS_available endp
;----------------------------------------------------------------
; Determine whether able to swap to EMS, and prepare for swapping to EMS
; if able.
; on entry:
; AX = total number of paragraphs to swap out
; DX = number of paragraphs in PSP block to swap out
; return: CF set on error
; CF clear if able to swap
; AX = handle
;----------------------------------------------------------------
spawno_init_ems proc near
ASSUME DS:DGROUP
cmp __spawn_ems@,0 ; are we allowed to use EMS?
je no_EMS ; if not, try next method
push ax ; remember total paragraphs required
mov cx,(16*1024) ; 16K per page, but 16 bytes per para
mov ax,16 ; 16 bytes per paragraph
push ax
mul dx ; paragraphs to bytes
div cx ; DX:AX bytes to EMS pages
mov ems_page_num$,ax
mov ems_page_offset$,dx
or dx,dx ; partial last page?
jne got_last_page
dec ax ; if not, say we have a "partial" last
mov dx,(16*1024) ; page of 16K
got_last_page:
mov $ems_pages,ax
mov $ems_partial_size,dx
xor ax,ax
mov ems_page_num,ax
mov ems_page_offset,ax
pop dx ; DX <- 16
pop ax ; get back total paragraphs required
mul dx ; paragraphs to bytes
div cx ; DX:AX bytes to EMS pages
or dx,dx
jz no_partial_page_ems
inc ax
no_partial_page_ems:
push ax ; remember required number of pages
call _EMS_available ; find out how many EMS pages are free
pop cx ; get back required number of pages
cmp ax,cx ; enough EMS memory for swapping?
jb no_EMS ; if not, swap to disk
mov ah,41h ; get EMS page frame segment
int 67h
or ah,ah ; was call successful
jnz no_EMS ; swap to disk if not
mov page_frame_seg,bx ; store page frame seg in swap-in code
mov ah,43h ; allocate EMS for swapping
mov bx,cx ; BX <- total number of EMS pages needed
int 67h
or ah,ah
jnz no_EMS ; if error, try next method
mov ah,47h ; save mapping context for handle DX
int 67h
mov ax,dx ; return the EMS handle
mov $ems_handle,ax
clc
ret
no_EMS:
stc
ret
spawno_init_ems endp
;----------------------------------------------------------------
; Clean up at end of spawn.
; entry: AX = handle returned by spawno_init_*
;----------------------------------------------------------------
spawno_finish_ems proc near
assume DS:DGROUP,ES:NOTHING
mov dx,ax ; DX <- handle
mov ah,48h ; restore mapping context
int 67h
mov ah,45h
int 67h ; free EMS handle and memory
;
; assume the free works, since there's not much we can do if it doesn't
;
spawno_swapdone_ems: ; don't need to do anything after
; writing out the memory, so piggy-
; back an empty subroutine onto an
; existing return instruction
ret
spawno_finish_ems endp
;----------------------------------------------------------------
; Prepare to read back the swapped-out program's memory
; entry: AX = handle returned by spawno_init_ems
;----------------------------------------------------------------
spawno_swapin_ems proc near
ASSUME DS:DGROUP
mov ax,ems_page_num$
mov ems_page_num,ax
mov ax,ems_page_offset$
mov cl,4
shr ax,cl
mov ems_page_offset,ax
ret
spawno_swapin_ems endp
CSegEnd@
IFNDEF __TPINC
NOWARN OPI
END
ENDIF