home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
caway349.zip
/
SOURCE
/
ALL
/
MEMORY.ASM
< prev
next >
Wrap
Assembly Source File
|
1996-06-12
|
51KB
|
2,530 lines
;-------------------------------------------------------------------------------
;
;Get memory using RAW/VCPI.
;
;On Entry:-
;
;BX:CX - Size of block.
;
;On Exit:-
;
;Carry on error else,
;
;SI:DI - Handle.
;BX:CX - Logical address of block.
;
RAWGetMemory proc near
call RAWCopyCheck
;
pushm eax,edx,ebp,ds,es
mov ax,KernalDS ;make data addresable.
mov ds,ax
assume ds:_cwRaw
push ebx
push ecx
push edx
xor ebx,ebx
mov bx,ss
mov ecx,esp
pushf
cli
mov edx,d[RawStackPos]
sub d[RawStackPos],RawStackDif
popf
mov ax,KernalSS
mov ss,ax
mov esp,edx
add ecx,4+4+4
pushm ebx,ecx
sub ecx,4+4+4
push es
mov es,bx
mov edx,es:[ecx]
mov ebx,es:[ecx+4+4]
mov ecx,es:[ecx+4]
pop es
mov ax,KernalZero
mov es,ax
shl ebx,16 ;get block size as 32-bit.
mov bx,cx
add ebx,4095 ;round up to next 4k.
shr ebx,12
or ebx,ebx
jz @@error
@@start: mov edi,LinearBase ;Get starting point.
mov ecx,LinearLimit
sub ecx,edi ;Get memory present.
shr ecx,12 ;Get pages.
shr edi,12 ;Get page number.
shl edi,2 ;dword per entry.
add edi,1024*4096*1022 ;point to page details.
;
;Look for a big enough block of free memory.
;
xor eax,eax ;value to look for.
cld
;
;EAX - zero, what we're looking for.
;ECX - entries to check.
;EDI - address of entries to check.
;
;EBX - number of entries we want.
;
@@l0: repne scasd
;
;Nothing found means extend end of memory map.
;
jnz @@ExtendNew
;
;Point everything back to the matching value.
;
sub edi,4
inc ecx
;
;Save current position as start of last free block incase
;this block extends to the end of memory.
;
mov esi,edi ;save last position.
;
;If we only wanted one page then we're done, this is it!
;
cmp ebx,1
jz @@l2 ;Speed up 4K allocations.
;
;Set the number of pages to scan. This should be the number of
;pages we want but has to be reduced to the number of pages
;actually available when the request would go off the end of
;memory.
;
mov edx,ebx
cmp ecx,ebx ;Enough space to check?
jnc @@l1
mov edx,ecx
;
;Scan specified number of entries to see if their all free.
;
@@l1: pushm ecx,edi
mov ecx,edx
repe scasd ;Scan for free pages.
popm ecx,edi
jnz @@l3 ;not enough free entries.
;
;All the entries were free, now check if we were truncating the
;length to stop us running off the end of memory.
;
cmp edx,ebx ;Truncated length?
jnz @@ExtendEnd
jmp @@l2
;
;One way or another we didn't find the number of entries we were
;after so restart the search.
;
@@l3: add edi,4
dec ecx
jmp @@l0
;
;We've found what we wanted without any extra messing around so
;hand this over to the marker.
;
@@l2: sub esi,1024*4096*1022 ;point to page details.
shr esi,2
jmp @@MarkMemRet
;
;Last block is free so use it as the basis for extension.
;
@@ExtendEnd: mov edi,ecx ;remaining entries.
sub esi,(1024*4096*1022)
shr esi,2 ;Get start page number.
mov ecx,ebx ;Total pages needed.
sub ecx,edi ;Pages found so far.
jmp @@Extend
;
@@ExtendNew: ;Last block not free so new block will start at LinearLimit.
;
mov ecx,ebx ;Set pages needed.
mov esi,LinearLimit ;New start address.
shr esi,12
;
@@Extend: ;Memory map needs extending so get on with it.
;
call ExtendLinearMemory ;Try and extend memory map.
jnc @@MarkMemRet ;Mark the block as used.
;
;Not enough memory so report failure.
;
stc
jmp @@exit
;
@@MarkMemRet: ;Got the memory so mark it in use.
;
sub FreePages,ebx ;reduce free page count.
add medAllocPages,ebx
;
mov ecx,ebx ;Get number of pages again.
mov edx,esi
mov edi,esi ;Get base page again.
shl edi,2
add edi,1024*4096*1022
mov eax,MEM_END
rep stosd
mov es:d[(1024*4096*1022)+edx*4],MEM_START
;
;Now return details to caller.
;
shl esi,12 ;Convert back to a real address.
mov di,si
shr esi,16
mov cx,di
mov bx,si
clc
jmp @@exit
;
@@error: stc
;
@@exit:
lss esp,f[esp]
pushf
add d[RawStackPos],RawStackDif
popf
popm eax,edx,ebp,ds,es
ret
assume ds:_cwDPMIEMU
RAWGetMemory endp
;-------------------------------------------------------------------------------
;
;Re-size a block of memory.
;
;On Entry:-
;
;SI:DI - Handle.
;BX:CX - New block size.
;
;On Exit:-
;
;SI:DI - New handle.
;BX:CX - New address.
;
RAWResMemory proc near
call RAWCopyCheck
;
pushm eax,edx,ebp,ds,es
mov ax,KernalDS
mov ds,ax
assume ds:_cwRaw
push ebx
push ecx
push edx
xor ebx,ebx
mov bx,ss
mov ecx,esp
pushf
cli
mov edx,d[RawStackPos]
sub d[RawStackPos],RawStackDif
popf
mov ax,KernalSS
mov ss,ax
mov esp,edx
add ecx,4+4+4
pushm ebx,ecx
sub ecx,4+4+4
push es
mov es,bx
mov edx,es:[ecx]
mov ebx,es:[ecx+4+4]
mov ecx,es:[ecx+4]
pop es
mov ax,KernalZero
mov es,ax
shl esi,16
mov si,di ;Get real address.
shl ecx,16
mov cx,bx
ror ecx,16
add ecx,4095
shr ecx,12 ;Get new block size.
or ecx,ecx
jz @@error
;
;Check for a valid address.
;
test esi,4095 ;all memory on page boundaries.
jnz @@error
cmp esi,LinearBase
jc @@error
cmp esi,LinearLimit
jnc @@error
shr esi,12 ;Get page number.
mov eax,es:d[1024*4096*1022+esi*4]
and eax,MEM_MASK
cmp eax,MEM_START
jnz @@error
;
;Work out the blocks current size.
;
push ecx
mov ebp,1
mov edx,esi
inc edx
mov ecx,LinearLimit
shr ecx,12
sub ecx,edx
jz @@l1
@@l0: mov eax,es:d[(1024*4096*1022)+edx*4]
and eax,MEM_MASK
cmp eax,MEM_END
jnz @@l1
inc ebp
inc edx
dec ecx
jnz @@l0
;
@@l1: ;Shrinking or expanding?
;
pop ecx
cmp ecx,ebp
jz @@RetNewAddr
jnc @@Bigger
;
@@Smaller: ;Shrinking the block so get on with it.
;
;ECX - New size in pages.
;EBP - Current size in pages.
;ESI - Current start page.
;
mov edx,esi
add edx,ecx ;move to new block end.
sub ebp,ecx ;get number of pages to lose.
mov ecx,ebp
;
add FreePages,ebp ;update number of free pages.
sub medAllocPages,ebp
;
@@s0: and es:d[(1024*4096*1022)+edx*4],not MEM_MASK
or es:d[(1024*4096*1022)+edx*4],MEM_FREE
and es:d[(1024*4096*1023)+edx*4],not (1 shl 6)
inc edx
dec ecx
jnz @@s0
call EMUCR3Flush
jmp @@RetNewAddr
;
@@Bigger: ;Want to expand the block so get on with it.
;
;ECX - New size in pages.
;EBP - Current size in pages.
;ESI - Current start page.
;
@@b0: mov edx,esi
add edx,ebp ;move to end of this block.
mov ebx,LinearLimit
shr ebx,12
sub ebx,edx ;get pages to end of memory.
or ebx,ebx
jz @@Extend
;
;See if the next block is free.
;
mov eax,es:d[(1024*4096*1022)+edx*4]
and eax,MEM_MASK
cmp eax,MEM_FREE
jnz @@NewBlock ;no hope so get a new block.
;
;Check how big this next block is.
;
mov edi,ebp ;use current size as basis.
@@b1: mov eax,es:d[(1024*4096*1022)+edx*4]
and eax,MEM_MASK
cmp eax,MEM_FREE
jnz @@NewBlock ;No hope so get a new block.
inc edi
cmp edi,ecx ;Got enough yet?
jz @@MarkAndRet
inc edx
dec ebx
jnz @@b1 ;keep trying.
;
;Reached the end of the memory map so try extending it.
;
pushad
sub ecx,edi ;pages still needed.
call ExtendLinearMemory
popad
jc @@error
jmp @@MarkAndRet
;
@@Extend: ;Need to extend the memory map to provide a block of free memory
;after the current block.
;
pushad
sub ecx,ebp ;pages needed.
call ExtendLinearMemory
popad
jc @@error
;
@@MarkAndRet: ;Mark the new memory as in use and exit.
;
;ECX - New size in pages.
;EBP - Current size in pages.
;ESI - Current start page.
;
mov edx,esi
add edx,ebp ;move to start of new memory.
sub ecx,ebp ;pages to mark.
;
sub FreePages,ecx ;update number of free pages.
add medAllocPages,ecx
;
@@mr0: and es:d[(1024*4096*1022)+edx*4],not MEM_MASK
or es:d[(1024*4096*1022)+edx*4],MEM_END
inc edx
dec ecx
jnz @@mr0
jmp @@RetNewAddr
;
@@NewBlock: ;Nothing for it but to try and allocate a new block of memory.
;
pushm ecx,ebp,esi
shl ecx,12
mov ebx,ecx
shr ebx,16
call RawGetMemory
pushf
shl ebx,16
mov bx,cx
popf
popm ecx,ebp,esi
jc @@error
;
;Copy current block to new block.
;
pushad
mov ecx,ebp
shl ecx,12
shl esi,12
mov edi,ebx
pushm ds,es
pop ds
shr ecx,2
rep movsd
pop ds
popad
;
;Release current block.
;
pushad
shl esi,12
mov di,si
shr esi,16
call RawRelMemory
popad
;
;Use new block in place of origional.
;
mov esi,ebx
shr esi,12
;
@@RetNewAddr: ;Return possibly new address/handle to caller.
;
shl esi,12 ;Get a real address again and
mov di,si ;use it as both the memory
mov cx,si ;address to return and the handle.
shr esi,16
mov bx,si
clc
jmp @@exit
;
@@error: stc
@@exit:
lss esp,f[esp]
pushf
add d[RawStackPos],RawStackDif
popf
popm eax,edx,ebp,ds,es
ret
assume ds:_cwDPMIEMU
RAWResMemory endp
;-------------------------------------------------------------------------------
;
;Release block of memory using RAW/VCPI.
;
;On Entry:-
;
;SI:DI - handle (Base linear address).
;
RAWRelMemory proc near
call RAWCopyCheck
;
pushad
pushm ds,es
;
shl esi,16 ;Get block base address.
mov si,di
mov ax,KernalDS ;make data addresable.
mov ds,ax
assume ds:_cwRaw
push ebx
push ecx
push edx
xor ebx,ebx
mov bx,ss
mov ecx,esp
pushf
cli
mov edx,d[RawStackPos]
sub d[RawStackPos],RawStackDif
popf
mov ax,KernalSS
mov ss,ax
mov esp,edx
add ecx,4+4+4
pushm ebx,ecx
sub ecx,4+4+4
push es
mov es,bx
mov edx,es:[ecx]
mov ebx,es:[ecx+4+4]
mov ecx,es:[ecx+4]
pop es
mov ax,KernalZero
mov es,ax
;
;Check for a legal address.
;
test esi,4095
jnz @@error
cmp esi,LinearBase ;inside logical memory map?
jc @@error
cmp esi,LinearLimit
jnc @@error
shr esi,12 ;Get page number.
mov eax,es:d[1024*4096*1022+esi*4]
and eax,MEM_MASK
cmp eax,MEM_START
jnz @@error
;
;Mark all this blocks pages as free.
;
inc FreePages
dec medAllocPages
;
and es:d[1024*4096*1022+esi*4],not MEM_MASK
or es:d[1024*4096*1022+esi*4],MEM_FREE
and es:d[1024*4096*1023+esi*4],not (1 shl 6)
inc esi
mov ecx,LinearLimit
shr ecx,12
sub ecx,esi ;Get pages remaining.
jz @@1
@@0: mov eax,es:d[1024*4096*1022+esi*4]
and eax,MEM_MASK
cmp eax,MEM_END
jnz @@1
inc FreePages
dec medAllocPages
and es:d[1024*4096*1022+esi*4],not MEM_MASK
or es:d[1024*4096*1022+esi*4],MEM_FREE
and es:d[1024*4096*1023+esi*4],not (1 shl 6)
inc esi
dec ecx
jnz @@0
;
@@1: call EMUCR3Flush
;
clc
jmp @@exit
;
@@error: stc
@@exit:
lss esp,f[esp]
pushf
add d[RawStackPos],RawStackDif
popf
popm ds,es
popad
ret
assume ds:_cwDPMIEMU
RAWRelMemory endp
;-------------------------------------------------------------------------------
;
;Reset dirty bit for specified memory.
;
;On Entry:
;
;BX:CX Starting linear address of pages to discard
;SI:DI Number of bytes to discard
;
;On Exit:
;
;Carry clear, all other registers preserved.
;
;-------------------------------------------------------------------------------
RawDiscardPages proc near
pushm ds,es
pushad
mov ax,KernalDS
mov ds,ax
assume ds:_cwRaw
mov ax,KernalZero
mov es,ax
;
;Get base address.
;
shl ebx,16
mov bx,cx
;
;Get length.
;
shl esi,16
mov si,di
;
;Round start up a page.
;
mov eax,ebx
add ebx,4095
and ebx,not 4095
sub eax,ebx
neg eax
cmp eax,esi
jnc @@8
sub esi,eax
;
;Round length down a page.
;
and esi,not 4095
or esi,esi
jz @@8
;
;Get page values.
;
mov edx,ebx
shr ebx,12
shr esi,12
mov ecx,esi
;
;Modify all page tables.
;
mov esi,4096*1024*1023 ;base of page alias memory.
@@0: cmp edx,LinearBase
jc @@1
cmp edx,LinearLimit
jnc @@2
and es:d[esi+ebx*4],not ((1 shl 6)+(1 shl 11)) ;clear dirty & disk bits.
@@1: add edx,4096
inc ebx
dec ecx
jnz @@0
;
@@2: call EMUCR3Flush ;update page cache.
;
@@8: clc
popad
assume ds:_cwDPMIEMU
popm ds,es
ret
RawDiscardPages endp
;-------------------------------------------------------------------------------
;
;Map physical memory into address space and return linear access address.
;
;BX:CX Physical address of memory
;SI:DI Size of region to map in bytes
;
;Returns
;
;Carry set on error else,
;
;BX:CX Linear address that can be used to access the physical memory.
;
RawMapPhys2Lin proc near
pushm ds,es
pushm eax,edx,esi,edi,ebp
mov ax,KernalDS
mov ds,ax
assume ds:_cwRaw
mov ax,KernalZero
mov es,ax
;
;Get physical address as 32-bit & check for none-page boundary.
;
shl ebx,16
mov bx,cx
test ebx,4095
jnz @@9
;
;Get length as number of pages.
;
shl esi,16
mov si,di
add esi,4095
shr esi,12
test esi,esi
jz @@9
; MED 06/13/96, remove 4M restriction
;; MED 04/18/96, don't allow more than a 4M mapping (not supported by CW)
; cmp esi,400h
; ja @@9
;
;Deal with addresses below 1 Meg.
;
mov edi,ebx
mov eax,esi
shl eax,12
add eax,edi
dec eax
cmp eax,100000h+10000h
jc @@8
;
;Find first un-used physical mapping space.
;
mov ebp,PageDirLinear
mov eax,1021
@@0:
; MED 04/18/96
mov ecx,es:[ebp+eax*4]
and ecx,(NOT 4095) ; get linear address
cmp ecx,ebx ; see if matches desired linear address
jne med2 ; no, continue as before
mov edi,eax
shl edi,22 ; convert index to 4M space
jmp @@8
med2:
cmp es:d[ebp+eax*4],0
jz @@1
; dec eax
sub eax,1
jc @@9
jmp @@0
;
;Work out how many page tables we need and set first tables index.
;
@@1: mov ecx,esi
shr ecx,10
sub eax,ecx
inc ecx
;
;Make sure we can get enough memory for physical page tables.
;
call PhysicalGetPages
add edx,NoneLockedPages
cmp edx,ecx
jc @@9
;
;Put all the page tables into place.
;
lea edi,[ebp+eax*4]
push edi
mov ebp,ecx
@@2: call PhysicalGetPage
jnc @@3
call UnMapPhysical
jc @@10
@@3: and ecx,1 ;put user bits in useful place.
shl ecx,10
and edx,0FFFFFFFFh-4095 ;lose user bits.
or edx,111b ;present+user+write.
or edx,ecx ;set use flags.
mov es:d[edi],edx ;store this tables address.
push edi
sub edi,PageDIRLinear
add edi,PageAliasLinear ;get alias table address.
mov es:d[edi],edx ;setup in alias table as well.
pop edi
;
;Clear this page to 0.
;
pushm ecx,edi
sub edi,PageDIRLinear
shl edi,10
add edi,1024*4096*1023 ;base of page alias's.
mov ecx,4096/4
xor eax,eax
cld
rep stosd
popm ecx,edi
;
add edi,4
dec ebp
jnz @@2
pop edi
;
;Now map specified physical address range into place.
;
sub edi,PageDIRLinear
shl edi,10 ;start of first page table
push edi
add edi,1024*4096*1023
or ebx,111b
@@4: mov es:[edi],ebx
add edi,4
add ebx,4096
dec esi
jnz @@4
pop edi
;
;Return linear address to caller.
;
shl edi,12-2
@@8: xor ecx,ecx
xor ebx,ebx
mov cx,di
shr edi,16
mov bx,di
clc
jmp @@11
;
@@10: pop edi
@@9: stc
@@11: popm eax,edx,esi,edi,ebp
assume ds:_cwDPMIEMU
popm ds,es
ret
RawMapPhys2Lin endp
;-------------------------------------------------------------------------------
;
;Un-Do a physical to linear address mapping.
;
RawUnMapPhys2Lin proc near
clc
ret
RawUnMapPhys2Lin endp
;-------------------------------------------------------------------------------
RAWLockMemory proc near
call RAWCopyCheck
;
pushm eax,ebx,ecx,edx,esi,edi,ebp,ds,es,fs,gs
mov ax,KernalDS
mov ds,ax
assume ds:_cwRaw
push ebx
push ecx
push edx
xor ebx,ebx
mov bx,ss
mov ecx,esp
pushf
cli
mov edx,d[RawStackPos]
sub d[RawStackPos],RawStackDif
popf
mov ax,KernalSS
mov ss,ax
mov esp,edx
add ecx,4+4+4
pushm ebx,ecx
sub ecx,4+4+4
push es
mov es,bx
mov edx,es:[ecx]
mov ebx,es:[ecx+4+4]
mov ecx,es:[ecx+4]
pop es
;
shl ebx,16
mov bx,cx
shl esi,16
mov si,di
add esi,ebx
and ebx,not 4095 ;round down to nearest page.
mov d[_LM_BlockBase],ebx
add esi,4095
and esi,not 4095 ;round up to next page.
dec esi
mov d[_LM_BlockEnd],esi ;store address of last page.
;
;Check if start above end now!
;
mov eax,d[_LM_BlockBase]
cmp eax,d[_LM_BlockEnd]
jnc @@10
;
;Count number of pages we need for this range.
;
mov d[_LM_Needed],0
mov eax,NoneLockedPages
mov d[_LM_Got],eax
mov eax,d[_LM_BlockBase]
@@04: cmp eax,LinearBase ;must be in our memory pool.
jc @@05
cmp eax,LinearLimit
jnc @@05
push eax
call GetPageStatus
pop eax
jc @@15 ;ignore not present tables.
test edx,1
jz @@005 ;already present.
call RawPageLocked ;locked page?
jnz @@05
dec d[_LM_Got] ;reduce available pages.
jmp @@05
@@005: inc d[_LM_Needed]
@@05: add eax,4096
cmp eax,d[_LM_BlockEnd] ;done them all yet?
jc @@04
;
;Check if we actually need any more pages to lock this region.
;
cmp d[_LM_Needed],0
jz @@OK
;
;If VMM isn't active then pages can always be locked assumeing they exist.
;
cmp VMMHandle,0
jnz @@VMM
mov eax,d[_LM_Needed]
cmp eax,d[_LM_Got]
jc @@OK
jz @@OK
jmp @@15
;
;VMM is active and pages are required so we need to make sure enough pages are
;left for swapping.
;
@@VMM: mov eax,d[_LM_Needed]
add eax,16 ;arbitrary safety buffer.
cmp eax,d[_LM_Got]
jc @@OK
jz @@OK
jmp @@15
;
;Enough free pages so lock the region.
;
@@OK: mov eax,d[_LM_BlockBase]
@@4: cmp eax,LinearBase ;must be in our memory pool.
jc @@5
cmp eax,LinearLimit
jnc @@5
push eax
call GetPageStatus
pop eax
jc @@15 ;ignore not present tables.
test edx,1 ;is it present?
jnz @@6
;
@@11: ;Need to allocate a physical page first.
;
push eax
call UnMapPhysical
pop eax
jc @@15 ;this shouldn't happen.
mov LinearEntry,eax
shr LinearEntry,12 ;store page number to allocate at.
push eax
call MapPhysical ;map this page in.
pop eax
;
@@6: ;Now mark this page as locked.
;
call RawLockPage
;
@@5: add eax,4096
cmp eax,d[_LM_BlockEnd] ;done them all yet?
jc @@4
;
@@10: clc
jmp @@1
;
@@15: stc
;
@@1:
lss esp,f[esp]
pushf
add d[RawStackPos],RawStackDif
popf
popm eax,ebx,ecx,edx,esi,edi,ebp,ds,es,fs,gs
ret
assume ds:_cwDPMIEMU
RAWLockMemory endp
;-------------------------------------------------------------------------------
RAWUnLockMemory proc near
call RAWCopyCheck
;
pushm eax,ebx,ecx,edx,esi,edi,ebp,ds,es,fs,gs
mov ax,KernalDS
mov ds,ax
assume ds:_cwRaw
;
push ebx
push ecx
push edx
xor ebx,ebx
mov bx,ss
mov ecx,esp
pushf
cli
mov edx,d[RawStackPos]
sub d[RawStackPos],RawStackDif
popf
mov ax,KernalSS
mov ss,ax
mov esp,edx
add ecx,4+4+4
pushm ebx,ecx
sub ecx,4+4+4
push es
mov es,bx
mov edx,es:[ecx]
mov ebx,es:[ecx+4+4]
mov ecx,es:[ecx+4]
pop es
shl ebx,16
mov bx,cx
shl esi,16
mov si,di
add esi,ebx
and ebx,0FFFFFFFFh-4095 ;round down to nearest page.
mov d[_LM_BlockBase],ebx
add esi,4095
and esi,0FFFFFFFFh-4095 ;round up to next page.
dec esi
mov d[_LM_BlockEnd],esi ;store address of last page.
;
;Now run through all pages in this range un-locking them.
;
mov eax,d[_LM_BlockBase]
@@4: cmp eax,LinearBase ;must be in our memory pool.
jc @@5
cmp eax,LinearLimit
jnc @@5
push eax
call GetPageStatus
pop eax
jc @@5 ;ignore not present tables.
test edx,1 ;is it present?
jz @@5
call RawUnLockPage ;unlock the page.
@@5: add eax,4096
cmp eax,d[_LM_BlockEnd] ;done them all yet?
jc @@4
clc
@@1:
lss esp,f[esp]
pushf
add d[RawStackPos],RawStackDif
popf
popm eax,ebx,ecx,edx,esi,edi,ebp,ds,es,fs,gs
ret
assume ds:_cwDPMIEMU
RAWUnLockMemory endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
RAWGetMemoryMax proc near
;
;Work out biggest memory block remaining.
;
call RAWCopyCheck
;
pushm eax,ecx,edx,esi,edi,ebp,ds,es
mov ax,KernalDS ;make data addresable.
mov ds,ax
assume ds:_cwRaw
push ebx
push ecx
push edx
xor ebx,ebx
mov bx,ss
mov ecx,esp
pushf
cli
mov edx,d[RawStackPos]
sub d[RawStackPos],RawStackDif
popf
mov ax,KernalSS
mov ss,ax
mov esp,edx
add ecx,4+4+4
pushm ebx,ecx
sub ecx,4+4+4
push es
mov es,bx
mov edx,es:[ecx]
mov ebx,es:[ecx+4+4]
mov ecx,es:[ecx+4]
pop es
mov ax,KernalZero
mov es,ax
;
;Look in existing memory first.
;
mov edx,LinearBase ;Get starting point.
mov ecx,LinearLimit
sub ecx,edx ;Get memory present.
shr ecx,12 ;Get pages.
shr edx,12 ;Get page number.
xor edi,edi ;Clear flag.
xor ebp,ebp ;Clear biggest so far.
;
@@l0: ;Look for a bigest block of free memory.
;
mov eax,es:d[(1024*4096*1022)+edx*4] ;Get page details.
and eax,MEM_MASK
cmp eax,MEM_FREE ;Free block?
jnz @@l2
or edi,edi ;Got any yet?
jnz @@l1
mov esi,edx ;Get base page number.
@@l1: inc edi
cmp edi,ebp ;Biggest yet?
jc @@l3
mov ebx,esi ;Get base.
mov ebp,edi ;Get size.
jmp @@l3
@@l2: xor edi,edi
@@l3: inc edx ;Next page.
dec ecx
jnz @@l0
;
;See if biggest block found is the last block in the map.
;
xor edx,edx ;reset end of chain value.
or edi,edi ;last block free?
jz @@l4
cmp ebx,esi ;same base?
jnz @@l4
mov edx,ebp ;setup extra block size.
mov ebp,0 ;reset normal block size.
jmp @@l5
;
@@l4: ;Get size of the last block in the memory map.
;
mov eax,LinearBase
mov esi,LinearLimit
shr esi,12
dec esi
shr eax,12
mov ecx,esi
sub ecx,eax
@@l6: jecxz @@l5
mov eax,es:d[(1024*4096*1022)+esi*4] ;Get page details.
and eax,MEM_MASK
cmp eax,MEM_FREE ;Free block?
jnz @@l5
dec esi
inc edx
dec ecx
jmp @@l6
;
@@l5: ;See what extra memory we can get hold of.
;
mov ebx,edx
call PhysicalGetPages ;Get extra memory available.
mov ecx,ebx ;Save origional value.
add ebx,edx ;update extra memory value.
;
;See how many pages of real memory would be lost to page tables.
;
mov eax,LinearLimit
shr eax,12
add eax,edx
shr eax,10
mov edx,LinearLimit
shr edx,12
dec edx
shr edx,10
sub eax,edx
add eax,eax ;Page + Det
sub ebx,eax
;
;See what extra memory the VMM can get hold of.
;
cmp VMMHandle,0
jz @@l8
mov ebx,ecx
pushm ebx,ebp
;
;Get free disk space remaining.
;
mov dl,VMMName ;get drive letter for this media.
sub dl,'A' ;make it real.
inc dl ;adjust for current type select.
mov ah,36h ;get free space.
int 21h ;/
xor edx,edx
cmp ax,-1 ;invalid drive?
jz @@l7
mul cx ;Get bytes per cluster.
mul bx ;Get bytes available.
shl edx,16
mov dx,ax
@@l7: ;
;Get current swap file size.
;
push edx
mov bx,VMMHandle
mov ax,4202h
xor cx,cx
mov dx,cx
int 21h
shl edx,16
mov dx,ax
pop eax
add edx,eax
and edx,not 65535
shr edx,12
popm ebx,ebp
;
;Work out how much of the VMM space is extra.
;
mov eax,LinearLimit
sub eax,LinearBase
shr eax,12
sub edx,eax
add ebx,edx
;
@@l8: ;Check which block is bigger and exit.
;
push ecx
mov eax,ebx
shl eax,12
mov ecx,LinearLimit
sub ecx,LinearBase
sub eax,ecx
js @@l89
cmp eax,MaxMemLin
jc @@l89
mov ebx,MaxMemLin
sub ebx,ecx
shr ebx,12
@@l89: pop ecx
cmp ebx,ebp
jnc @@l9
mov ebx,ebp
@@l9: shl ebx,12
clc
lss esp,f[esp]
pushf
add d[RawStackPos],RawStackDif
popf
popm eax,ecx,edx,esi,edi,ebp,ds,es
ret
assume ds:_cwDPMIEMU
RAWGetMemoryMax endp
;-------------------------------------------------------------------------------
;
;Extend the linear memory map by allocateing physical memory if available or
;virtual memory if not, or even a combination of the two.
;
;On Entry:
;
;ECX - Pages to extend by.
;
;On Exit:
;
;Carry set on error else memory map extended.
;
ExtendLinearMemory proc near
pushad
pushm ds,es
mov ax,KernalDS
mov ds,ax
assume ds:_cwRaw
mov ax,KernalZero
mov es,ax
mov ebp,ecx
mov eax,ecx
shl eax,12
dec eax
add eax,LinearLimit
dec eax
sub eax,LinearBase
cmp eax,MaxMemLin
jnc @@error
;
;Try extending useing physical memory first.
;
@@f0: mov eax,LinearLimit ;get new entry number.
shr eax,12 ;page number.
mov LinearEntry,eax
shr eax,10 ;/1024 for page dir entry.
mov edi,PageDirLinear ;get page table address.
mov eax,es:d[edi+eax*4] ;this page present?
test eax,1 ;do we have a page table?
jnz @@f1 ;keep going till we do.
;
;No page table so make sure we can get 2 pages (page and det)
;
call PhysicalGetPages
cmp edx,2
jc @@virtual
;
;both pages available so go to it.
;
@@f2: call PhysicalGetPage ;get a page.
jc @@error ;it lied.
mov eax,LinearLimit ;get new entry number.
shr eax,12 ;page number.
mov LinearEntry,eax
push LinearEntry
call MapPhysical ;use this page for page table.
call PhysicalGetPage ;get a page.
pop LinearEntry
jc @@error ;it lied.
call MapPhysical ;use this page for page table.
;
@@f1: call PhysicalGetPage ;get a page.
jc @@Virtual ;use virtual memory.
mov eax,LinearLimit ;get new entry number.
shr eax,12 ;page number.
mov LinearEntry,eax
call MapPhysical ;use this page for page table.
;
;Update details.
;
mov eax,LinearLimit
shr eax,12
mov es:d[(1024*4096*1022)+eax*4],0
inc FreePages
; dec medAllocPages
inc TotalPages
add LinearLimit,4096 ;bump up the end of the memory map.
dec ebp ;update the counter.
jnz @@f0 ;keep looking.
clc
jmp @@exit ;All physical so exit.
;
@@Virtual: ;Virtual memory will be needed so see if we can provide any.
;
cmp VMMHandle,0 ;Virtual memory active?
jz @@error
;
;Find out how much disk space is left for swap file to grow into.
;
mov dl,VMMName ;get drive letter for this media.
sub dl,'A' ;make it real.
inc dl ;adjust for current type select.
mov ah,36h ;get free space.
push ebp
int 21h ;/
pop ebp
cmp ax,-1 ;invalid drive?
jz @@error
mul cx ;Get bytes per cluster.
mul bx ;Get bytes available.
shl edx,16
mov dx,ax ;make 32 bit.
and edx,not 65535
add edx,SwapFileLength ;add existing size.
mov eax,LinearLimit
sub eax,LinearBase ;get current real memory.
sub edx,eax
shr edx,12 ;get it as pages.
cmp edx,ebp ;Enough pages?
jc @@error
;
;Find out how many un-locked pages we currently have.
;
mov edx,NoneLockedPages
;
;Enough page's for minimum requirement?
;
cmp edx,16 ;un-locked pages < 16?
jc @@error ;force minimum of 16.
sub edx,16
;
;Work out how many new page/det tables are required.
;
mov eax,LinearLimit
shr eax,12
mov ebx,eax
dec eax ;Last definatly valid page table.
add ebx,ebp ;New end page.
shr eax,10
shr ebx,10 ;Get page table units (4Meg)
sub ebx,eax ;get the differance.
jz @@DoneTables
add ebx,ebx ;Page + Det
mov ecx,ebp
cmp ebx,edx
jc @@OK
jz @@OK
jmp @@error
;
@@OK: ;Allocate new page tables.
;
mov esi,PageDirLinear ;get page directory address.
mov edx,LinearLimit
shr edx,12
@@v2: mov eax,edx ;get new entry number.
shr eax,10 ;/1024 for page dir entry.
test es:d[esi+eax*4],1 ;this page present?
jnz @@v3
;
;get DET page.
;
pushm ecx,edx
call UnMapPhysical ;get a physical page for us to use.
mov eax,edx
mov ebx,ecx
popm ecx,edx
jc @@error ;not enough physical memory to support virtual memory.
pushm ecx,edx
mov LinearEntry,edx ;set logical page address.
mov edx,eax ;get physical address again.
mov ecx,ebx
call MapPhysical ;use this to add a new page table.
popm ecx,edx
;
;And again for page table.
;
pushm ecx,edx
call UnMapPhysical ;get a physical page for us to use.
mov eax,edx
mov ebx,ecx
popm ecx,edx
jc @@error ;not enough physical memory to support virtual memory.
pushm ecx,edx
mov LinearEntry,edx ;set logical page address.
mov edx,eax ;get physical address again.
mov ecx,ebx
call MapPhysical ;use this to add a new page table.
popm ecx,edx
@@v3: inc edx
dec ecx
jnz @@v2
;
@@DoneTables: ;Now mark all the new pages as un-locked/free
;
mov eax,LinearLimit
mov ecx,ebp
@@v4: call RawClearPageLock ;clear page locking for this entry.
push eax
shr eax,12
mov es:d[1024*4096*1022+eax*4],0
pop eax
add eax,4096
dec ecx
jnz @@v4
;
;Extend the swap file.
;
mov ecx,LinearLimit ;current end position.
sub ecx,LinearBase ;length.
mov eax,ebp ;extension needed in pages.
shl eax,12
add ecx,eax ;New extremity desired.
cmp ecx,SwapFileLength
jc @@Extended
add ecx,65535
and ecx,not 65535
push ecx
mov dx,cx
shr ecx,16
mov bx,VMMHandle ;get swap file handle.
mov ax,4200h
mov edi,offset PageInt
push edi
mov Real_EAX[edi],eax
mov Real_EBX[edi],ebx
mov Real_ECX[edi],ecx
mov Real_EDX[edi],edx
mov Real_SS[edi],0
mov Real_SP[edi],0
mov bl,21h
push ds
pop es
call EMURawSimulateInt ;move to right place.
pop edi
mov ah,40h
mov bx,VMMHandle ;get swap file handle.
mov cx,0
push edi
mov edi,offset PageInt
mov Real_EAX[edi],eax
mov Real_EBX[edi],ebx
mov Real_ECX[edi],ecx
mov Real_EDX[edi],edx
mov Real_SS[edi],0
mov Real_SP[edi],0
mov bl,21h
push ds
pop es
call EMURawSimulateInt ;move to right place.
pop edi
pop ecx
test Real_Flags[edi],1
jnz @@disk_error
mov SwapFileLength,ecx
;
xor cx,cx
xor dx,dx
mov ax,4201h
mov bx,VMMHandle
push edi
mov edi,offset PageInt
mov Real_EAX[edi],eax
mov Real_EBX[edi],ebx
mov Real_ECX[edi],ecx
mov Real_EDX[edi],edx
mov Real_SS[edi],0
mov Real_SP[edi],0
mov bl,21h
push ds
pop es
call EMURawSimulateInt ;move to right place.
pop edi
test Real_Flags[edi],1
jnz @@disk_error
mov edx,Real_EDX[edi]
mov eax,Real_EAX[edi]
shl edx,16
mov dx,ax
cmp edx,SwapFileLength
jnz @@disk_error
;
@@Extended: ;Update the end of the memory map.
;
add FreePages,ebp
; sub medAllocPages,ebp
shl ebp,12
add LinearLimit,ebp
clc
jmp @@Exit
;
@@error: stc
@@Exit: ;
popm ds,es
popad
ret
;
@@Disk_Error: jmp @@error
assume ds:_cwDPMIEMU
ExtendLinearMemory endp
;-------------------------------------------------------------------------------
;
;Map physical page supplied into logical address space. If a new page table is needed, the page
;supplied will become a page table.
;
;On Entry:-
;
;CL - Use flags 0-3. 1 being used for VCPI memory to allow release later.
;EDX - Physical address to map.
;
MapPhysical proc near
pushad
pushm ds,es
mov ax,KernalDS
mov ds,ax
assume ds:_cwRaw
mov ax,KernalZero ;make everything addresable.
mov es,ax
;
and ecx,1 ;put user bits in useful place.
shl ecx,10
and edx,0FFFFFFFFh-4095 ;lose user bits.
mov eax,LinearEntry ;get new entry number.
shr eax,10 ;/1024 for page dir entry.
;
mov esi,PageDirLinear ;get page table address.
test es:d[esi+eax*4],1 ;this page present?
jnz @@AddPage
;
cmp PageDETLinear,0 ;DET in use yet?
jz @@AddTable
mov esi,PageDETLinear ;get page table address.
test es:d[esi+eax*4],1 ;DET page present?
jnz @@AddTable
;
@@AddDET: ;Need a new DET page.
;
or edx,111b ;present+user+write.
or edx,ecx ;set use flags.
mov es:d[esi+eax*4],edx ;store this tables address.
;
;Clear this page to locked.
;
mov edi,1024*4096*1022 ;base of page DET's.
mov eax,LinearEntry ;get the entry number again.
shl eax,2 ;4 bytes per entry.
add edi,eax
mov ecx,4096/4
mov eax,MEM_FILL
cld
rep stosd
;
jmp @@Finished
;
@@AddTable: ;Need a new page table.
;
mov eax,LinearEntry ;get new entry number.
shr eax,10 ;/1024 for page dir entry.
mov esi,PageDirLinear ;get page table address.
or edx,111b ;present+user+write.
or edx,ecx ;set use flags.
mov es:d[esi+eax*4],edx ;store this tables address.
mov esi,PageAliasLinear ;get alias table address.
mov es:d[esi+eax*4],edx ;setup in alias table as well.
;
;Clear this page to 0.
;
mov edi,1024*4096*1023 ;base of page alias's.
mov eax,LinearEntry ;get the entry number again.
shl eax,2 ;4 bytes per entry.
add edi,eax
mov ecx,4096/4
xor eax,eax
cld
rep stosd
;
jmp @@Finished
;
@@AddPage: ;Update recent page usage stack.
;
pushm ecx,es,ds
pop es
mov edi,offset RecentMapStack+(4*PageStackSize)-4
mov esi,offset RecentMapStack+(4*PageStackSize)-8
mov ecx,PageStackSize-1
std
rep movsd
popm ecx,es
cld
mov eax,LinearEntry
shl eax,12
mov RecentMapStack,eax
;
;Add this to the relavent page table.
;
mov eax,LinearEntry ;get the entry number again.
mov esi,1024*4096*1023 ;base of page alias's.
mov ebx,es:d[esi+eax*4] ;get current details.
and ebx,1 shl 11
or edx,ebx
or edx,111b ;present+user+write.
or edx,ecx ;set use flags.
mov es:d[esi+eax*4],edx ;set physical address.
;
cmp PageDETLinear,0
jz @@NoLocking
mov eax,LinearEntry
shl eax,12
call RawClearPageLock ;clear page locking for this entry.
;
;Update number of un-locked physical pages present.
;
inc NoneLockedPages
;
@@NoLocking: ;Check if this page needs fetching from swap space.
;
cmp VMMHandle,0
jz @@NoRead
;
test ebx,1 shl 11
jz @@NoRead
;
mov esi,BreakAddress
mov al,es:[esi]
mov es:b[esi],0
push eax
;
mov ecx,LinearEntry ;get page number.
shl ecx,12 ;get linear address.
sub ecx,LinearBase
mov dx,cx
shr ecx,16
mov bx,VMMHandle
mov ax,4200h
mov edi,offset PageInt
mov Real_EBX[edi],ebx
mov Real_EAX[edi],eax
mov Real_EDX[edi],edx
mov Real_ECX[edi],ecx
mov Real_SS[edi],0
mov Real_SP[edi],0
mov bl,21h
pushm es,ds
pop es
call EMURawSimulateInt ;move to right place.
mov edi,offset PageInt
mov ax,VMMHandle
mov Real_EBX[edi],eax
mov ax,PageBufferReal
mov Real_DS[edi],ax
mov Real_EAX[edi],3f00h
mov Real_EDX[edi],0
mov Real_ECX[edi],4096
mov Real_SS[edi],0
mov Real_SP[edi],0
mov bl,21h
call EMURawSimulateInt ;read it from disk.
pop es
test Real_Flags[edi],1
jz @@ok
mov esi,BreakAddress
pop eax
mov es:[esi],al
jmp @@Finished2
;
@@ok: mov esi,BreakAddress
pop eax
mov es:[esi],al
;
mov esi,PageBufferLinear
mov edi,LinearEntry
shl edi,12 ;get linear address again.
mov ecx,4096/4
pushm ds,es
pop ds
cld
rep movsd ;copy back into place.
pop ds
;
mov eax,LinearEntry ;get new entry number.
mov esi,1024*4096*1023 ;base of page alias's.
and es:d[esi+eax*4],0FFFFFFFFh-(3 shl 5) ;clear accesed & dirty bits.
call EMUCR3Flush
;
@@NoRead: inc LinearEntry ;update counter.
;
@@Finished: clc
;
@@Finished2: popm ds,es
popad
ret
assume ds:_cwDPMIEMU
MapPhysical endp
;-------------------------------------------------------------------------------
;
;Retrieve the address of the most un-needed physical memory and mark its current page table entry
;as not present after writing to disk if needed.
;
;On Entry:-
;
;On Exit:-
;
;EDX - Physical address of page.
;CL - User flags.
;
UnMapPhysical proc near
pushm eax,ebx,esi,edi,ebp,ds,es,fs
;
mov ax,KernalDS
mov ds,ax
mov es,ax
assume ds:_cwRaw
mov ax,KernalZero
mov fs,ax
;
mov ProposedPresentFlag,0
mov ProposedRecentFlag,0
mov CompareCount,0
;
mov esi,PageDirLinear
mov edi,1024*4096*1023 ;base of page alias's.
mov ebp,1024*4096*1022
mov ecx,PageingPointer ;get current position.
mov ebx,LinearLimit ;maximum size of scan we can do.
sub ebx,LinearBase
shr ebx,12
inc ebx
cld
;
@@ScanLoop: dec ebx
jnz @@80 ;shit, we've been all the way round.
;
cmp ProposedPresentFlag,0
jnz @@UseProposed
jmp @@8
;
@@80: cmp ecx,LinearBase
jnc @@80_0
mov ecx,LinearBase
sub ecx,4096
@@80_0: add ecx,4096
cmp ecx,LinearLimit ;End of memory map yet?
jc @@NoWrap
mov ecx,LinearBase
;
@@NoWrap: mov eax,ecx
shr eax,12 ;get page number.
test fs:d[edi+eax*4],1 ;this page present?
jz @@ScanLoop
test fs:d[ebp+eax*4],MEM_LOCK_MASK shl MEM_LOCK_SHIFT
jnz @@ScanLoop
;
inc CompareCount
;
;Check against recent stack.
;
pushm ecx,edi
mov eax,ecx
mov edi,offset RecentMapStack
mov ecx,PageStackSize
repnz scasd
popm ecx,edi
jz @@IsRecent
shr eax,12 ;get page number again.
test fs:d[edi+eax*4],1 shl 6
jz @@GotPage
;
cmp ProposedPresentFlag,0
jz @@SetProposed
cmp ProposedRecentFlag,0
jz @@UseProposed?
@@SetProposed: mov ProposedPresentFlag,-1
mov ProposedPage,ecx
mov CompareCount,0
mov ProposedRecentFlag,0
jmp @@ScanLoop
;
@@UseProposed?: mov eax,NoneLockedPages
shr eax,2
cmp eax,4096
jc @@UP0
mov eax,4096
@@UP0: cmp CompareCount,eax
jc @@UseProposed
jmp @@ScanLoop
;
@@IsRecent: cmp ProposedPresentFlag,0
jnz @@ProposedRecent?
mov ProposedPresentFlag,-1
mov ProposedPage,ecx
mov ProposedRecentFlag,-1
mov CompareCount,0
jmp @@ScanLoop
;
@@ProposedRecent?:
cmp ProposedRecentFlag,0
jnz @@LookedEnough?
mov eax,NoneLockedPages
shr eax,2
cmp eax,4096
jc @@PR0
mov eax,4096
@@PR0: cmp CompareCount,eax
jnc @@UseProposed
jmp @@ScanLoop
;
@@LookedEnough?:
mov eax,NoneLockedPages
cmp CompareCount,eax
jnc @@UseProposed
jmp @@ScanLoop
;
@@UseProposed: mov ecx,ProposedPage
;
@@GotPage: mov PageingPointer,ecx
;
mov eax,ecx
shr eax,12 ;get page number again.
shl eax,2
add edi,eax
;
;Check if it needs to go to the swap file.
;
test fs:d[edi],1 shl 6 ;is it dirty?
jz @@5 ;no need to write it if not.
;
;Flush this page to disk.
;
push edi
mov esi,BreakAddress
mov al,fs:[esi]
mov fs:b[esi],0
push eax
;
sub edi,1024*4096*1023 ;get page table entry number.
shr edi,2 ;page number.
shl edi,12 ;get linear address.
push edi
mov esi,edi
pushm ds,es
mov edi,PageBufferLinear ;copy it to somewhere we can deal with it.
mov ax,KernalZero
mov ds,ax
mov es,ax
mov ecx,4096/4
rep movsd
popm es,ds
pop edi
;
sub edi,LinearBase
mov ebp,edi
mov dx,di
shr edi,16
mov cx,di
mov ax,4200h
mov bx,VMMHandle
mov edi,offset PageInt
mov Real_EBX[edi],ebx
mov Real_EAX[edi],eax
mov Real_EDX[edi],edx
mov Real_ECX[edi],ecx
mov Real_SS[edi],0
mov Real_SP[edi],0
mov bl,21h
push ds
pop es
call EMURawSimulateInt ;move to right place.
;
test Real_Flags[edi],1
stc
jnz @@error_anyway
mov edx,Real_EDX[edi]
mov eax,Real_EAX[edi]
shl edx,16
mov dx,ax
cmp edx,ebp
jnz @@force_error
;
mov edi,offset PageInt
mov ax,VMMHandle
mov Real_EBX[edi],eax
mov ax,PageBufferReal
mov Real_DS[edi],ax
mov Real_EAX[edi],4000h
mov Real_EDX[edi],0
mov Real_ECX[edi],4096
mov Real_SS[edi],0
mov Real_SP[edi],0
mov bl,21h
call EMURawSimulateInt ;write it to disk.
test Real_Flags[edi],1
stc
jnz @@error_anyway
mov eax,Real_EAX[edi]
cmp ax,4096
jz @@error_anyway
@@force_error: stc
@@error_anyway: ;
mov esi,BreakAddress
pop eax
mov fs:[esi],al
;
pop edi
jc @@8
or fs:d[edi],1 shl 11 ;signal it living on disk.
;
@@5: ;Now remove it from the page table and exit.
;
and fs:d[edi],0FFFFFFFFh-1 ;mark as not present.
mov edx,fs:[edi] ;get page entry.
mov ecx,edx
and edx,0FFFFFFFFh-4095 ;lose flag bits.
shr ecx,10
and ecx,1 ;preserve user flags.
call EMUCR3Flush
;
;Update number of un-locked physical pages present.
;
dec NoneLockedPages
;
clc
jmp @@9
;
@@8: stc ;failed to find free page.
;
@@9: popm eax,ebx,esi,edi,ebp,ds,es,fs
ret
assume ds:_cwDPMIEMU
UnMapPhysical endp
;-------------------------------------------------------------------------------
;
;Lock page indicated.
;
;On Entry:-
;
;EAX - Linear address to lock.
;
RawLockPage proc near
pushm eax,ebx,esi,es
shr eax,12 ;get page number.
mov bx,KernalZero
mov es,bx
mov esi,1024*4096*1022 ;base of page DET's.
mov ebx,es:[esi+eax*4]
shr ebx,MEM_LOCK_SHIFT
and ebx,MEM_LOCK_MASK
jnz @@WasLocked
;
;Update number of un-locked physical pages present.
;
pushm ax,ds
mov ax,KernalDS
mov ds,ax
assume ds:_cwRaw
dec NoneLockedPages
assume ds:_cwDPMIEMU
popm ax,ds
;
@@WasLocked: cmp ebx,MEM_LOCK_MASK
jz @@0
add es:d[esi+eax*4],1 shl MEM_LOCK_SHIFT ;lock it.
@@0: popm eax,ebx,esi,es
ret
RawLockPage endp
;-------------------------------------------------------------------------------
RawClearPageLock proc near
pushm eax,ebx,ecx,esi,es
mov bx,KernalZero
mov es,bx
shr eax,12
mov esi,1024*4096*1022 ;base of page alias's.
mov ebx,MEM_LOCK_MASK shl MEM_LOCK_SHIFT
xor ebx,-1
and es:d[esi+eax*4],ebx ;un-lock it.
popm eax,ebx,ecx,esi,es
ret
RawClearPageLock endp
;-------------------------------------------------------------------------------
;
;Un-lock a linear page.
;
;On Entry:-
;
;EAX - Linear address of page to unlock.
;
RawUnLockPage proc near
call RawPageLocked
jz @@9
pushm eax,ebx,esi,es
mov bx,KernalZero
mov es,bx
shr eax,12
mov esi,1024*4096*1022 ;base of page alias's.
sub es:d[esi+eax*4],1 shl MEM_LOCK_SHIFT ;un-lock it.
mov eax,es:d[esi+eax*4]
shr eax,MEM_LOCK_SHIFT
and eax,MEM_LOCK_MASK
jnz @@NotUnLocked
;
;Update number of un-locked physical pages present.
;
push ds
mov ax,KernalDS
mov ds,ax
assume ds:_cwRaw
inc NoneLockedPages
assume ds:_cwDPMIEMU
pop ds
;
@@NotUnLocked: popm eax,ebx,esi,es
@@9: ret
RawUnLockPage endp
;-------------------------------------------------------------------------------
;
;Check if page lock count is zero.
;
;On Entry:-
;
;EAX - Linear page address.
;
;On Exit:-
;
;Zero set if page count=0.
;
RawPageLocked proc near
pushm eax,ebx,esi,es
mov bx,KernalZero
mov es,bx
shr eax,12 ;get page number.
mov esi,1024*4096*1022 ;base of page alias's.
mov ebx,es:d[esi+eax*4]
shr ebx,MEM_LOCK_SHIFT
and ebx,MEM_LOCK_MASK
popm eax,ebx,esi,es
ret
RawPageLocked endp
;-------------------------------------------------------------------------------
;
;Return page table entry for a particular linear address.
;
;On Entry:-
;
;EAX - linear address.
;
;On Exit:-
;
;Carry set if page table not present else,
;
;EDX - Page table entry.
;
GetPageStatus proc near
pushm eax,ebx,esi,ds,es
push ax
mov ax,KernalDS
mov ds,ax
pop ax
assume ds:_cwRaw
mov bx,KernalZero
mov es,bx
push eax
mov esi,PageDirLinear
shr eax,12 ;get page number.
shr eax,10 ;get dir entry number.
test es:d[esi+eax*4],1 ;page table present?
pop eax
jz @@8
mov esi,4096*1024*1023 ;base of page alias memory.
shr eax,12 ;get page number.
mov edx,es:[esi+eax*4] ;get page details.
clc
jmp @@9
;
@@8: xor edx,edx
stc
@@9: popm eax,ebx,esi,ds,es
ret
assume ds:_cwDPMIEMU
GetPageStatus endp
;-------------------------------------------------------------------------------
;
;The Exception 14 handler. This gets a shout whenever a not present page table is encountered by
;the processor. We check if the faulting address is within our range, passing to old handler if
;its not, re-aranging memory if it is.
;
VirtualFault proc far
pushm eax,ecx,edx,ds
mov ax,DpmiEmuDS
mov ds,ax
mov eax,ExceptionCR2
mov cx,KernalDS
mov ds,cx
assume ds:_cwRaw
cmp eax,LinearBase ;address below our memory space?
jc @@OldExit
cmp eax,LinearLimit ;address above our memory space?
jnc @@OldExit
;
push eax ;save the linear address.
call UnMapPhysical ;retrieve a physical page to use.
pop eax
jc @@Disk_Error ;This should only happen on disk errors.
shr eax,12
push LinearEntry
mov LinearEntry,eax ;setup linear address we want to map.
call MapPhysical ;map new page into faulting linear address space.
pop LinearEntry
jc @@Disk_Error ;This should only happen on disk errors.
;
popm eax,ecx,edx,ds
assume ds:nothing
test cs:DpmiEmuSystemFlags,1 ;check exit size.
assume ds:_cwRaw
jz @@Use32Bit3
db 66h
retf ;16 bit exit.
@@Use32Bit3: ;
retf
;
@@disk_error: jmp @@OldExit
;
assume ds:nothing
@@OldExit: popm eax,ecx,edx,ds
jmp cs:f[OldExcep14] ;32 bit chaining.
OldExcep14 df ?
assume ds:_cwDPMIEMU
VirtualFault endp
;-------------------------------------------------------------------------------
;
;Allocate a block of DOS memory & provide a selector to access it with.
;
RawGetDOSMemory proc near
pushm ecx,esi,edi,ebp,ds,es
mov ax,KernalDS
mov ds,ax
assume ds:_cwRaw
;
cmp bx,-1 ;maximum?
jz @@0
inc ebx ;para extra for us.
@@0: ;
push ebx
mov edi,offset MemIntBuffer
push ds
pop es
mov Real_EAX[edi],4800h ;get memory.
mov Real_EBX[edi],ebx ;memory size.
mov Real_SS[edi],0
mov Real_SP[edi],0
mov bl,21h
call EMURawSimulateINT ;allocate it.
pop ecx
mov eax,Real_EAX[edi] ;get result.
mov ebx,Real_EBX[edi]
test Real_Flags[edi],1
jz @@1
or bx,bx ;nothing available?
jz @@9
dec ebx ;leave space for us!
jmp @@9
;
@@1: ;Now try and allocate enough selectors.
;
pushm eax,ecx
dec cx ;lose our para.
shr cx,12 ;get number of 64k chunks.
inc cx ;+1 for base.
call RawGetDescriptors
popm ebx,ecx
jc @@8
;
;Store block size.
;
push ecx
mov dx,KernalZero
mov es,dx
movzx esi,bx ;get segment address.
shl esi,4 ;get linear address.
mov es:w[esi],cx ;store block size.
dec es:w[esi] ;lose our para.
pop ecx
;
;Setup selectors.
;
dec cx ;lose our para.
inc bx ;/
push ds
pop es
push eax
push ebx
;
@@2: pushm eax,ebx,ecx,eax
mov edi,offset RawSelBuffer
add edi,7
and edi,not 7
movzx esi,bx
shl esi,4
movzx ecx,cx
shl ecx,4
dec ecx
mov al,0
mov ah,DescPresent+DescPL3+DescMemory+DescRWData
call EMUMakeDesc
pop ebx
call RawBPutDescriptor
popm eax,ebx,ecx
add eax,8 ;next selector.
add ebx,1000h ;update segment base.
movzx ecx,cx
sub ecx,1000h ;reduce segment size.
jns @@2 ;keep going till all done.
;
pop eax ;Get base segment again.
pop edx ;Get base selector again.
clc
jmp @@10
;
@@8: ;Release memory we managed to allocate.
;
mov edi,offset MemIntBuffer
mov ax,KernalDS
mov es,ax
mov es:Real_EAX[edi],4900h ;release memory.
mov es:Real_ES[edi],bx ;segment.
mov es:Real_SS[edi],0
mov es:Real_SP[edi],0
mov bl,21h
call EMURawSimulateINT ;release it.
;
@@9: stc
@@10: popm ecx,esi,edi,ebp,ds,es
ret
assume ds:_cwDPMIEMU
RawGetDOSMemory endp
;-------------------------------------------------------------------------------
;
;Re-size a block of DOS memory.
;
RawResDOSMemory proc near
pushm ecx,edx,esi,edi,ebp,ds,es,fs,gs
mov ax,KernalDS
mov ds,ax
assume ds:_cwRaw
;
pushm bx,dx
mov bx,dx
call RawGetSelBase
shl ecx,16
mov cx,dx
mov esi,ecx
sub esi,16 ;back to our stuff.
popm bx,dx
mov ax,KernalZero
mov es,ax
cmp bx,es:w[esi] ;shrinking or expanding?
jz @@8
jnc @@Expand
;
@@Shrink: ;Attempt to shrink the memory block.
;
pushm ebx,edx
inc ebx ;include our para.
push ds
pop es
mov edi,offset MemIntBuffer
mov eax,esi
shr eax,4 ;get real mode segment.
mov Real_EAX[edi],4a00h
mov Real_EBX[edi],ebx
mov Real_ES[edi],ax
mov Real_SS[edi],0
mov Real_SP[edi],0
mov bl,21h
call EMURawSimulateINT
mov eax,Real_EAX[edi]
mov ebx,Real_EBX[edi]
test Real_Flags[edi],1
popm ecx,edx
jnz @@9 ;DOS failed it!
;
;Lose any selectors that are no longer needed.
;
pushm ecx,edx
mov ebx,edx
call RawGetSelBase
shl ecx,16
mov cx,dx
mov esi,ecx
sub esi,16 ;back to our stuff.
popm ecx,edx
pushm ecx,edx
mov ax,KernalZero
mov es,ax
mov ax,es:w[esi] ;get old size.
mov es:w[esi],cx ;store new size.
shr ax,12
inc eax
mov ebx,eax ;need existing number.
shr cx,12 ;get 64k chunks.
inc ecx ;+ base.
sub ax,cx ;get number of selectors to lose.
jz @@0
popm ecx,edx ;need base selector again.
pushm ecx,edx
shl bx,3
add dx,bx ;move to end of descriptors.
movzx ecx,ax
shl ax,3
sub edx,eax ;reduce by number to lose.
mov ebx,edx
@@1: pushm ebx,ecx
call RawRelDescriptor ;release this selector.
popm ebx,ecx
add ebx,8
dec ecx
jnz @@1
@@0: popm ecx,edx
;
;Re-set all selector base & limits to affect new last selector.
;
pushm ecx,edx
mov ebx,edx
call RawGetSelBase
shl ecx,16
mov cx,dx
mov ebx,ecx
shr ebx,4 ;get real mode segment.
popm ecx,edx
mov eax,edx
; shr ax,3 ;lose TI & RPL
; shr ax,3 ;get descriptor number.
push ds
pop es
;
@@2: pushm eax,ebx,ecx,eax
mov edi,offset RawSelBuffer
add edi,7
and edi,0fffffff8h
movzx esi,bx
shl esi,4
movzx ecx,cx
shl ecx,4
dec ecx
mov al,0
mov ah,DescPresent+DescPL3+DescMemory+DescRWData
call EMUMakeDesc
pop ebx
call RawBPutDescriptor
popm eax,ebx,ecx
add eax,8 ;next selector.
add ebx,1000h ;update segment base.
movzx ecx,cx
sub ecx,1000h ;reduce segment size.
jns @@2 ;keep going till all done.
;
@@8: clc
jmp @@10
;
@@Expand: ;Attempt to expand the memory block.
;
mov bx,es:w[esi] ;return current length as maximum.
mov ax,8
@@9: stc
@@10: popm ecx,edx,esi,edi,ebp,ds,es,fs,gs
ret
assume ds:_cwDPMIEMU
RawResDOSMemory endp
;-------------------------------------------------------------------------------
;
;Release a block of DOS memory.
;
RawRelDOSMemory proc near
pushm eax,ebx,ecx
mov ebx,edx
and ebx,0ffffh-7
xor ecx,ecx
xor eax,eax
mov ax,ds
and eax,not 7
cmp eax,ebx
jnz @@z0
mov ds,cx
@@z0: mov ax,es
and eax,not 7
cmp eax,ebx
jnz @@z1
mov es,cx
@@z1: mov ax,fs
and eax,not 7
cmp eax,ebx
jnz @@z2
mov fs,cx
@@z2: mov ax,gs
and eax,not 7
cmp eax,ebx
jnz @@z3
mov gs,cx
@@z3: popm eax,ebx,ecx
pushm ebx,ecx,edx,esi,edi,ebp
pushm ds,es
mov ax,KernalDS
mov ds,ax
assume ds:_cwRaw
;
;Get segment base address.
;
push edx
mov ebx,edx
call RawGetSelBase
shl ecx,16
mov cx,dx
mov esi,ecx
pop ebx
sub esi,16 ;back to our stuff.
mov eax,esi
shr eax,4 ;real mode paragraph address.
mov dx,KernalZero
mov es,dx
mov cx,es:w[esi] ;get block size.
;
;Release selectors.
;
@@0: pushm eax,ebx,ecx
call RawRelDescriptor
popm eax,ebx,ecx
add ebx,8 ;next descriptor.
movzx ecx,cx
sub ecx,1000h
jns @@0 ;release all selectors.
;
;Release DOS memory block.
;
push ds
pop es
mov edi,offset MemIntBuffer
mov Real_EAX[edi],4900h ;release block.
mov Real_ES[edi],ax ;block to release.
mov Real_SS[edi],0
mov Real_SP[edi],0
mov bl,21h
call EMURawSimulateINT ;release it.
mov eax,Real_EAX[edi]
test Real_Flags[edi],1
clc
jz @@noc
stc
@@noc: ;
popm ds,es
popm ebx,ecx,edx,esi,edi,ebp
ret
RawRelDOSMemory endp