windows-nt/Source/XPSP1/NT/base/mvdm/wow16/kernel31/2protect.asm
2020-09-26 16:20:57 +08:00

4142 lines
116 KiB
NASM

PAGE ,132
TITLE Windows Protect Mode Routines
.list
include kernel.inc
include protect.inc
include pdb.inc
include newexe.inc
.list
.286p
ifdef WOW
;
; the dpmi func 04f1h is idential to function 00h, except that
; the descriptor base and limit are not initialized to zero.
;
;
; the dpmi func 04f2h is identical to 0ch except that it
; sets 'count' (in cx) LDTs at one time. The first selector is in
; register bx. The descriptor data is in gdtdsc[bx], gdtdsc[bx+8]
; etc. This data is shared between dpmi (dosx.exe) and us and thus
; need not be passed in es:di
WOW_DPMIFUNC_00 equ 04f1h
WOW_DPMIFUNC_0C equ 04f2h
endif
MovsDsc Macro ;Move (copy) a descriptor (4 words)
cld
rept 4
movsw
endm
endm
CheckDS Macro
local okDS
push ax
mov ax, ds
cmp ax, pGlobalHeap
je okDS
int 3
okDS:
pop ax
endm
CheckLDT Macro selector
if KDEBUG
test selector,SEL_LDT
jnz @F
int 3
@@:
endif
Endm
DPMICALL MACRO callno
mov ax, callno
call DPMIProc
ENDM
CHECKSEL MACRO selector
ENDM
extrn GlobalHandle:FAR
extrn GlobalRealloc:FAR
extrn GlobalFix:FAR
extrn GlobalUnFix:FAR
extrn IGlobalFix:FAR ;Far calls in this segment
extrn IGlobalFlags:FAR
IF KDEBUG
extrn GlobalHandleNorip:FAR
ELSE
extrn IGlobalHandle:FAR
ENDIF
DataBegin
ifdef WOW
externW SelectorFreeBlock
externW UserSelArray
endif
externW WinFlags
extrn kr1dsc:WORD
extrn kr2dsc:WORD
extrn blotdsc:WORD
extrn DemandLoadSel:WORD
extrn temp_sel:WORD
externW MyCSSeg
externW selWoaPdb
externW cpLowHeap
externW selLowHeap
externW pGlobalHeap
externW SelTableLen
externW MyCSAlias
extrn SelTableStart:DWORD
extrn sel_alias_array:WORD
if ROM
externW selROMTOC
externW selROMLDT
externW sel1stAvail
endif
if ROM
externD lmaHiROM
externD cbHiROM
endif
globalD lpProc,0
DataEnd
DataBegin INIT
RModeCallStructure STRUC
RMCS_DI dw 0
dw 0
RMCS_ESI dd 0
RMCS_EBP dd 0
RMCS_Res dd 0
RMCS_EBX dd 0
RMCS_EDX dd 0
RMCS_ECX dd 0
RMCS_EAX dd 0
RMCS_Flags dw 0
RMCS_ES dw 0
RMCS_DS dw 0
RMCS_FS dw 0
RMCS_GS dw 0
RMCS_IP dw 0
RMCS_CS dw 0
RMCS_SP dw 0
RMCS_SS dw 0
RModeCallStructure ENDS
MyCallStruc RModeCallStructure <>
public MS_DOS_Name_String
MS_DOS_Name_String db "MS-DOS", 0
DataEnd INIT
sBegin CODE
externW MyCSDS
externW gdtdsc
ifdef WOW
externD prevInt31proc
endif
sEnd CODE
sBegin INITCODE
assumes cs,CODE
;-----------------------------------------------------------------------;
; SwitchToPMODE ;
; ;
; Entry: ;
; In Real or Virtual Mode ;
; DS -> Data Segment ;
; ES -> PSP ;
; ;
; Returns: ;
; In Protect Mode ;
; BX -> LDT selector ;
; SI -> Segment of start of available memory ;
; ES -> PSP ;
; ;
; Error Returns: ;
; Exits via DOS call 4Ch ;
; ;
; Registers Preserved: ;
; ;
; ;
; Registers Destroyed: ;
; ;
; Calls: ;
; ;
; History: ;
; ;
;-----------------------------------------------------------------------;
assumes ds,DATA
assumes es,nothing
ife ROM
cProc SwitchToPMODE,<PUBLIC,NEAR>
cBegin nogen
push cx
push es ; Current PSP
mov ax, 1687h
int 2Fh ; Get PMODE switch entry
or ax, ax ; Can we do it?
jz @F
NoPMODEj:
jmp NoPMODE
@@:
xor bh, bh ; Set CPU type now
mov bl,WF_CPU286
cmp cl, 2 ; At least a 286?
jb NoPMODEj ; No, Fail
je @F ; It is a 286?
mov bl,WF_CPU386
cmp cl,3 ; No, 386?
je @F
mov bl,WF_CPU486 ; No, assume 486 for now
@@:
mov WinFlags, bx ; Save away CPU type
mov word ptr [lpProc][0], di
mov word ptr [lpProc][2], es
pop ax ; PSP
add ax, 10h ; Skip the PSP
mov es, ax ; Give this to the DOS extender
add si, ax ; Start of memory available to us
mov selWoaPdb, si ; PDB for WOA
add si, 10h ; Move start on another 256 bytes
xor ax, ax ; 16-bit app
call [lpProc] ; Switch to PROTECTED mode
jc short NoPMODEj ; No, still Real/Virtual mode
mov ax, cs
and al, 7 ; LDT, Ring 3
cmp al, 7
je @F
jmp BadDPMI ; Insist on Ring 3!
@@:
mov bx, cs ; Allocate CS Alias
DPMICALL 000Ah
mov MyCSAlias, ax ; Save CS Alias in DS
mov bx, ds ; Use alias to update code seg var
mov ds, ax
assumes ds, CODE
mov MyCSDS, bx ; The DS selector
mov ds, bx
ReSetKernelDS
push si ; Unlock all of our memory
mov bx, si ; Segment address of start of our memory
mov di, es:[PDB_block_len] ; End of our memory
sub di, bx ; Size of our block in paragraphs
mov cpLowHeap, di ; (MAY NEED INCREMENTING!!!)
xor si, si ; Calculate # bytes in SI:DI
REPT 4
shl di, 1
rcl si, 1
ENDM
mov cx, bx ; Convert start of block to linear
xor bx, bx ; address
REPT 4
shl cx, 1
rcl bx, 1
ENDM
mov ax, 0602h
;BUGBUGBUGBUG
int 31h ; Mark region as pageable.
pop bx
DPMICALL 0002h ; Convert start of memory to selector
mov si, ax
mov selLowHeap, ax ; Save for WOA (MAY NEED PARA LESS!!!)
mov bx, selWoaPdb ; Convert WOA PDB segment to selector
DPMICALL 0002h
mov selWoaPdb, ax
push si
push es
mov ax, 168Ah ; See if we have MS-DOS extensions
mov si, dataOffset MS_DOS_Name_String
int 2Fh
cmp al, 8Ah
je short BadDPMI ; No extensions, screwed
mov word ptr [lpProc][0], di ; Save CallBack address
mov word ptr [lpProc][2], es
mov ax, 0100h ; Get base of LDT
call [lpProc]
jc short NoLDTParty
ifndef WOW
verw ax ; Writeable?
else
verr ax ; for WOW we can use read access
endif
jnz short NoLDTParty ; nope, don't bother with it
mov es, MyCSAlias
assumes es,CODE
mov gdtdsc, ax
assumes es,nothing
NoLDTParty: ; Well, we'll just have to use DPMI!
pop es
pop si
xor bx, bx
pop cx
ret
BadDPMI:
;
; Call real/virtual mode to whine
;
xor cx, cx ; Nothing on stack to copy
xor bh, bh ; Flags to DPMI
mov ax, MyCSSeg
mov MyCallStruc.RMCS_DS, ax ; Real mode DS will be parent PDB
mov MyCallStruc.RMCS_ES, cx ; Real mode ES will be 0
mov MyCallStruc.RMCS_CS, ax ; Real mode CS
mov MyCallStruc.RMCS_IP, codeoffset RModeCode ; Real mode IP
smov es, ds
mov di, dataoffset MyCallStruc ; ES:DI points to call structure
mov ax, 0301h ; Call Real Mode Procedure
int 31h
jmps GoodBye
RModeCode:
mov dx, codeoffset szInadequate
mov ah, 9
int 21h
retf
;szInadequate:
; DB 'KRNL286: Inadequate DPMI Server',13,10,'$'
externB <szNoPMode, szInadequate>
NoPMODE: ; NOTE: stack trashed...
ifdef WOW
;** Put Up a Dialog Box If we fail to Enter Protect Mode
;** Prepare the dialog box
push cs ;In our DS
push codeOFFSET szNoPMode ; -> unable to enter Prot Mode
push ds
externB <syserr>
push dataOffset syserr ;Caption
push 0 ;No left button
push SEB_CLOSE + SEB_DEFBUTTON ;Button 1 style
push 0 ;No right button
externFP kSYSERRORBOX
call kSYSERRORBOX ;Put up the system error message
externNP ExitKernel
jmp ExitKernel
else ; Not WOW
mov dx, codeoffset szNoPMode
; call complain
; DB 'KRNL286: Unable to enter Protected Mode',7,7,7,13,10,'$'
;complain:
; pop dx
push cs
pop ds ; DS:DX -> error message
mov ah,9 ; Print error message
int 21h
endif ; WOW
GoodBye:
mov ax, 4CFFh
int 21h
cEnd nogen
endif ;ROM
;-----------------------------------------------------------------------;
; LDT_Init ;
; ;
; Entry: ;
; ;
; Returns: ;
; ;
; Error Returns: ;
; ;
; Registers Preserved: ;
; AX,BX,CX,DX,DI,SI,DS,ES ;
; ;
; Registers Destroyed: ;
; ;
; Calls: ;
; ;
; History: ;
; ;
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc LDT_Init,<PUBLIC,NEAR>,<ax,bx,cx,di,es>
cBegin
ReSetKernelDS
mov es, bx ; Selector for LDT if any
push es ; Get random selectors
smov es, ds
ReSetKernelDS es
assumes ds,nothing
mov cx, 1 ; Argument to get_sel
call get_sel
mov kr1dsc, si
call get_sel
mov blotdsc, si
call get_sel
or si, SEG_RING
mov DemandLoadSel, si
mov ax, DSC_DATA+DSC_PRESENT; Get an array of 16 selectors
cCall alloc_sel,<0000h,0BADh,0FFFFh> ; This covers 1Mb.
mov kr2dsc, ax
smov ds, es
pop es
assumes es,nothing
cEnd
sEnd INITCODE
sBegin CODE
assumes cs,CODE
;-----------------------------------------------------------------------;
; AllocSelector
;
;
; Entry:
;
; Returns:
; AX = New selector
; = 0 if out of selectors
;
; Registers Destroyed:
;
; History:
; Thu 08-Dec-1988 14:17:38 -by- David N. Weise [davidw]
; Wrote it!
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc AllocSelectorWOW,<PUBLIC,FAR>
parmW selector
cBegin
; same as allocselector but doesn't set the descriptor
cCall inner_alloc_selector,<selector,0ffffh>
cEnd
cProc AllocSelector,<PUBLIC,FAR>
parmW selector
cBegin
cCall inner_alloc_selector,<selector,0>
cEnd
labelFP <PUBLIC, IAllocCStoDSAlias>
;-----------------------------------------------------------------------;
; AllocAlias
;
; This allocates a data alias for the passed in selector, which
; can be either code or data. The alias will track segment
; motion.
;
; Entry:
; parmW selector selector to get an alias for
;
; Returns:
; AX = selector
; = 0 failure
;
; Registers Destroyed:
;
; History:
; Sat 20-Jan-1990 23:40:32 -by- David N. Weise [davidw]
; Cleaning up.
;
; Fri 02-Dec-1988 11:04:58 -by- David N. Weise [davidw]
; Wrote it!
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc AllocAlias,<FAR,PUBLIC>
parmW selector
cBegin
ifdef WOW
push bx ; Whitewater tool ObjDraw needs this too
endif
cCall inner_alloc_selector,<selector,1>
; WhiteWater Resource Toolkit (shipped with Borland's Turbo
; Pascal) depends on dx being the data selector which was true
; in 3.0 but in 3.1 validation layer destroys it.
mov dx,selector
ifdef WOW
pop bx
endif
cEnd
;-----------------------------------------------------------------------;
; AllocDStoCSAlias
;
; This allocates a code alias for the passed in selector, which
; should be data. The alias will track segment motion. The
; passed in selector must be less than 64K.
;
; Entry:
; parmW selector selector to get an alias for
;
; Returns:
; AX = selector
; = 0 failure
;
; Registers Destroyed:
;
; History:
; Sat 20-Jan-1990 23:40:32 -by- David N. Weise [davidw]
; Cleaning up.
;
; Fri 02-Dec-1988 11:04:58 -by- David N. Weise [davidw]
; Wrote it!
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc IAllocDStoCSAlias,<FAR,PUBLIC>, <cx,si,di>
parmW data_selector
cBegin
;** AllocDStoCSAlias has an interesting hack. A fix was made to
;** not allow apps to GlobalAlloc fixed memory. This was done
;** for performance reasons. The only reason we can ascertain
;** for an app needing fixed GlobalAlloc'ed memory is in the case
;** of alias selectors. We assume that all apps needing alias
;** selectors will use this function to make the alias. So, if
;** we see a DStoCS alias being made, we make sure the DS is fixed.
mov ax, data_selector ;Get handle
push ax
IF KDEBUG
call GlobalHandleNorip ;Make sure it's really a handle
ELSE
call IGlobalHandle ;Make sure it's really a handle
ENDIF
test ax, 1 ;Fixed blocks have low bit set
jnz ADCA_Already_Fixed ;It's already a fixed block!
;** If the block is not fixed, it may be locked so we must check this.
push ax ;Save returned selector
push ax ;Use as parameter
call IGlobalFlags ;Returns lock count if any
or al, al ;Non-zero lock count?
pop ax ;Get selector back
jnz ADCA_Already_Fixed ;Yes, don't mess with it
;** Fix the memory. Note that we're only doing this for
;** apps that are calling this on non-fixed or -locked memory.
;** This will cause them to rip on the GlobalFree call to this
;** memory, but at least it won't move on them!
push ax ;Fix it
call IGlobalFix
ADCA_Already_Fixed:
cCall inner_alloc_selector,<data_selector,2>
if ALIASES
or ax,ax
jz ada_nope
mov bx,data_selector
call add_alias
ada_nope:
endif
smov es,0
; WhiteWater Resource Toolkit (shipped with Borland's Turbo
; Pascal) depends on dx being the data selector which was
; true in 3.0 but in 3.1 validation layer destroys it.
mov dx,data_selector
cEnd
;-----------------------------------------------------------------------;
; inner_alloc_selector
;
;
; Entry:
;
; Returns:
;
; Registers Destroyed:
;
; History:
; Sat 20-Jan-1990 23:40:32 -by- David N. Weise [davidw]
;
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc inner_alloc_selector,<PUBLIC,NEAR>,<di,si>
parmW selector
parmW sel_type
localV DscBuf,DSC_LEN
cBegin
mov cx, 1
mov di, selector
and di, not SEG_RING_MASK
jnz as1
call get_sel
jnz short as_exit ; We got it
jmps as_exit1
as1:
mov bx, selector
lea di, DscBuf
smov es, ss
ifdef WOW
DPMICALL 000Bh ; Get existing descriptor
else
push ds
mov ds, gdtdsc
push si ; Get Descriptor
mov si, bx
and si, not 7
MovsDsc
lea di, [di-DSC_LEN] ; Restore DI
pop si
pop ds
endif
mov cl, DscBuf.dsc_hlimit
and cl, 0Fh
inc cl ; # selectors
call get_sel
jz short as_exit1
ifdef WOW
cmp sel_type, 0ffffh ; called from AllocSelectorWOW ?
jz as_exit ; yes . dont set descriptor
endif
cmp sel_type,0 ; called from AllocSelector?
jz as_fill ; done if so
mov al,DSC_PRESENT+DSC_DATA
cmp sel_type,1 ; called from AllocAlias?
jz @F
or al,DSC_CODE_BIT ; called from AllocDStoCSAlias
@@:
mov DscBuf.dsc_access,al
as_fill:
mov bx, si
or bl, SEG_RING
call fill_in_selector_array
as_exit:
or si, SEG_RING
as_exit1:
mov ax,si
smov es, 0
cEnd
;-----------------------------------------------------------------------;
; get_sel ;
; ;
; Entry: ;
; CX = # of selectors required ;
; ;
; Returns: ;
; SI = First Selector ;
; DS = LDT ;
; ZF = 0 ;
; ;
; Error Returns: ;
; SI = 0 ;
; ZF = 1 ;
; ;
; Registers Preserved: ;
; AX,BX,CX,DX,DI,ES ;
; ;
; Registers Destroyed: ;
; ;
; Calls: ;
; ;
; History: ;
; ;
;-----------------------------------------------------------------------;
cProc AllocSelectorArray,<PUBLIC,FAR>,<si>
parmW nSels
cBegin
mov cx, nSels
call get_sel
mov ax, si
jz asa_fail
or si, SEG_RING
mov bx, si
mov dx, cx
mov cx, DSC_DATA+DSC_PRESENT ; Mark all as Data and Present
ifdef WOW
fill_in_access:
DPMICALL 0009h
lea bx, [bx+DSC_LEN]
dec dx
jnz fill_in_access
else
push ds
mov ds, gdtdsc
push bx
and bl, not 7
fill_in_access:
mov word ptr ds:[bx].dsc_access, cx
if 0 ;;ROM and KDEBUG
call CheckROMSelector
endif
lea bx, [bx+DSC_LEN]
dec dx
jnz fill_in_access
pop bx
pop ds
endif; WOW
mov ax, si
asa_fail:
cEnd
cProc get_sel,<PUBLIC,NEAR>
cBegin nogen
call SetKernelDSProc ; Must call procedure here
ReSetKernelDS
push ax
push cx
xor ax, ax
cmp cx, 1 ; One selector only?
jne gs_int31
cmp temp_sel, ax ; Have one waiting?
je gs_int31 ; no, get one
xchg temp_sel, ax ; Use the waiting selector
jmps gs_got_sel
gs_int31:
DPMICALL 0000h
CHECKSEL ax
gs_got_sel:
mov si, ax
and si, not SEG_RING_MASK
if KDEBUG
jnz got_sel
push es
pusha
kerror 0,<Out of selectors>
popa
pop es
jmps gs_exit
got_sel:
endif
mov ax, si
shr ax, 2
cmp ax, SelTableLen ; Make sure we can associate it
jae gs_free_sels
gs_exit:
mov ds, gdtdsc ; SIDE EFFECT...
UnSetKernelDS
gs_exit_2:
pop cx
pop ax
or si, si
ret
gs_free_sels:
ReSetKernelDS
cmp SelTableLen, 0
je gs_exit ; Not set yet, so we are ok
mov ds, gdtdsc
UnSetKernelDS
push bx
mov bx, si ; Could not associate, so free them
xor si, si
or bl, SEG_RING
as_free:
DPMICALL 0001h
lea bx, [bx+DSC_LEN]
loop as_free
pop bx
jmps gs_exit_2
cEnd nogen
;-----------------------------------------------------------------------;
; FreeSelector ;
; free_sel ;
; FreeSelArray
; ;
; Entry: ;
; ;
; Returns: ;
; ;
; Error Returns: ;
; ;
; Registers Preserved: ;
; BX,CX,DX,DI,SI,DS,ES ;
; ;
; Registers Destroyed: ;
; ;
; Calls: ;
; ;
; History: ;
; ;
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc IFreeSelector,<FAR,PUBLIC>,<di,si>
parmW selector
cBegin
CheckLDT selector
if ALIASES
mov ax,selector
call delete_alias
endif
xor ax, ax
mov es, ax ; GRRRRRRRR!
cCall FreeSelArray,<selector>
cEnd
assumes ds,nothing
assumes es,nothing
cProc free_sel,<PUBLIC,NEAR>,<ax,bx>
parmW selector
cBegin
pushf ; !! for the nonce
mov bx,selector ; must be careful in gcompact
; to ignore error return
if KDEBUG
or bx, SEG_RING ; Ensure Table bit correct
endif
DPMICALL 0001h
popf
cEnd
assumes ds,nothing
assumes es,nothing
cProc FreeSelArray,<PUBLIC,NEAR>,<ax,bx,cx>
parmW selector
cBegin
mov bx,selector ; to ignore error return
cCall GetSelectorCount
mov cx, ax
fsa_loop:
DPMICALL 0001h
lea bx, [bx+DSC_LEN]
loop fsa_loop ; Any left to free
cEnd
;-----------------------------------------------------------------------;
; GrowSelArray ;
; ;
; This is called from within grealloc. The point is to grow the ;
; number of contiguous selectors to tile the memory object. ;
; If we can't get a contiguous set then we attempt to find a set ;
; anywhere. ;
; ;
; Entry: ;
; ES => arena header ;
; ;
; Returns: ;
; AX => new selector array ;
; CX => new number of selectors ;
; ;
; Error Returns: ;
; ;
; Registers Preserved: ;
; BX,DX,DI,SI,DS,ES ;
; ;
; Registers Destroyed: ;
; ;
; Calls: ;
; ;
; History: ;
; ;
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc GrowSelArray,<PUBLIC,NEAR>,<bx,si,di,ds>
localV DscBuf,DSC_LEN
localW oldCount
cBegin
mov bx, es:[ga_handle]
mov di, bx
cCall GetSelectorCount
mov word ptr oldCount, ax
mov cx, si ; New size
dec cx ; Paragraph limit
shr cx, 12
inc cx ; new # selectors
cmp al, cl ; Same # of selectors required?
je gsa_done ; yes, just return!
call get_sel ; get a new selector array
jz short gsa_nosels
xchg si, di ; DI now new array, SI old array
push es
push cx
and bx, SEG_RING_MASK ; Ring bits
or bx, di ; New handle
mov cx, word ptr oldCount
push ds ; Copy Descriptor(s)
push si
mov es, gdtdsc
mov ds, gdtdsc
and si, not 7
shl cx, 2 ; CX = 4 * Descriptors = words to copy
rep movsw
pop si
pop ds
ifdef WOW
; set the descriptors
push bx
mov cx, word ptr oldCount
or bx, SEG_RING_MASK ; start selector
DPMICALL WOW_DPMIFUNC_0C
pop bx
endif; WOW
pop cx
pop es
SetKernelDS
mov ds, pGlobalHeap
UnSetKernelDS
cCall AssociateSelector,<si,0>
mov es:[ga_handle], bx
cCall AssociateSelector,<bx,es>
jmps gsa_done
gsa_nosels:
xor bx, bx ; Indicate failure
gsa_done:
mov ax, bx
or ax, ax ; Indicate success
gsa_ret:
cEnd
assumes ds, nothing
assumes es, nothing
cProc PreallocSel,<PUBLIC,NEAR>
cBegin nogen
push ds
push cx
push si
mov cx, 1
call get_sel
call SetKernelDSProc
ReSetKernelDS
mov temp_sel, si
or si, si ; Set flags for caller
pop si
pop cx
pop ds
UnSetKernelDS
ret
cEnd nogen
;-----------------------------------------------------------------------;
; alloc_sel ;
; alloc_data_sel
; ;
; Entry: ;
; parmD Address 32 bit address ;
; parmW Limit limit in paragraphs (limit of 1 meg) ;
; AX = flags alloc_sel only ;
; ;
; Returns: ;
; AX = new selector ;
; ;
; Error Returns: ;
; AX = 0 ;
; ;
; Registers Preserved: ;
; AX,BX,CX,DX,DI,SI,DS,ES ;
; ;
; Registers Destroyed: ;
; ;
; Calls: ;
; ;
; History: ;
; ;
; Thu 07-Apr-1988 21:33:27 -by- David N. Weise [davidw] ;
; Added the GlobalNotify check. ;
; ;
; Sun Feb 01, 1987 07:48:39p -by- David N. Weise [davidw] ;
; Added this nifty comment block. ;
;-----------------------------------------------------------------------;
assumes ds, nothing
assumes es, nothing
if ROM
public far_alloc_data_sel16
far_alloc_data_sel16 equ this far
endif
cProc far_alloc_data_sel,<PUBLIC,FAR>
parmD Address
parmW Limit
cBegin
cCall alloc_data_sel,<Address,Limit>
cEnd
if ROM
public alloc_data_sel16
alloc_data_sel16 equ this near
endif
cProc alloc_data_sel,<PUBLIC,NEAR>
; parmD Address
; parmW Limit
cBegin nogen
mov ax, DSC_DATA+DSC_PRESENT
errn$ alloc_sel
cEnd nogen
cProc alloc_sel,<PUBLIC,NEAR>,<bx,cx,dx,si,di,ds,es>
parmD Address
parmW Limit
localV DscBuf,DSC_LEN
cBegin
mov cx, 1
test al, DSC_PRESENT
jz as_oneonly
mov cx, Limit ; Calculate how many selectors required
add cx, 0FFFh
rcr cx, 1 ; 17 bitdom
shr cx, 11
as_oneonly:
call get_sel
jz short a_s_exit
mov bx, si ; Selector in bx for DPMI
or bl, SEL_LDT
lea di, DscBuf
smov es, ss ; es:di points to descriptor buffer
push ax ; Save access word
mov ax, Address.lo ; Set descriptor base
mov DscBuf.dsc_lbase, ax
mov ax, Address.hi
mov DscBuf.dsc_mbase, al
mov DscBuf.dsc_hbase, ah
pop ax ; Access word
test al, DSC_PRESENT ; If selector not present, limit is
jnz short set_everything ; as passed, not a paragraph count
mov word ptr DscBuf.dsc_access, ax
mov ax, word ptr Limit
mov DscBuf.dsc_limit, ax
ifdef WOW
DPMICALL 000Ch ; Fill in our stuff in the descriptor
else
push ds
push bx ; Set Descriptor
mov ds, gdtdsc
and bl, not 7
mov ax, es:[di] ; This looks slow but it isn't...
mov ds:[bx], ax
mov ax, es:[di][2]
mov ds:[bx][2], ax
mov ax, es:[di][4]
mov ds:[bx][4], ax
mov ax, es:[di][6]
mov ds:[bx][6], ax
if 0 ;;ROM and KDEBUG
call CheckROMSelector
endif
pop bx
pop ds
endif; WOW
jmps as_done
set_everything:
dec cl
and ah, not 0Fh ; Zero limit 19:16
or ah, cl ; Fill in limit 19:16
inc cl
mov word ptr DscBuf.dsc_access, ax
mov ax, Limit
shl ax, 4 ; Convert paragraphs to byte limit
dec ax
mov DscBuf.dsc_limit, ax
call fill_in_selector_array
as_done:
or si, SEG_RING
a_s_exit:
mov ax, si
cEnd
;-----------------------------------------------------------------------;
; fill_in_selector_array ;
; ;
; Entry: ;
; AX = size of object in paragraphs ;
; DH = Discard bit for descriptors ;
; DL = Access bits ;
; CX:BX = 32 bit base address of object ;
; SI = index into LDT ;
; Returns: ;
; ;
; Error Returns: ;
; ;
; Registers Preserved: ;
; SI, DI, DS, ES ;
; ;
; Registers Destroyed: ;
; AX,BX,CX,DX ;
; ;
; Calls: ;
; ;
; History: ;
; ;
;-----------------------------------------------------------------------;
assumes ds, nothing
assumes es, nothing
cProc fill_in_selector_array,<PUBLIC,NEAR>
cBegin nogen
CheckLDT bl
push ds
push es:[di].dsc_limit ; Save limit for last selector
SetKernelDS
test WinFlags, WF_CPU286 ; protect mode on a 286?
jz next_sel
mov es:[di].dsc_limit, 0FFFFh ; Others get 64k limit on 286
next_sel:
cmp cx, 1 ; Last selector?
jne fsa_not_last
pop es:[di].dsc_limit ; yes, get its limit
fsa_not_last:
DPMICALL 000Ch ; Set this descriptor
lea bx, [bx+DSC_LEN] ; On to next selector
add es:[di].dsc_mbase, 1 ; Add 64kb to address
adc es:[di].dsc_hbase, 0
dec es:[di].dsc_hlimit ; subtract 64kb from limit
loop next_sel
pop ds
ret
cEnd nogen
;-----------------------------------------------------------------------;
; GetSelectorBase
; get_physical_address
;
;
; Entry:
;
; Returns:
; DX:AX 32 bit physical address
; Registers Destroyed:
; none
;
; History:
; Sat 09-Jul-1988 16:40:59 -by- David N. Weise [davidw]
;
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc GetSelectorBase,<PUBLIC,FAR>
parmW selector
cBegin
cCall get_physical_address,<selector>
cEnd
cProc get_physical_address,<PUBLIC,NEAR>
parmW selector
cBegin
push bx
push cx
mov bx, selector
CheckLDT bl
ifdef WOWJUNK
DPMICALL 0006h
mov ax, dx
mov dx, cx
else
push ds ; Get Segment Base Address
mov ds, gdtdsc
and bl, not 7
mov ax, ds:[bx].dsc_lbase
mov dl, ds:[bx].dsc_mbase
mov dh, ds:[bx].dsc_hbase
pop ds
endif; WOW
pop cx
pop bx
cEnd
;-----------------------------------------------------------------------;
; set_physical_address
;
;
; Entry:
; DX:AX 32 bit physical address
; Returns:
;
; Registers Destroyed:
;
; History:
; Sat 09-Jul-1988 16:40:59 -by- David N. Weise [davidw]
;
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc set_physical_address,<PUBLIC,NEAR>,<ax,bx,cx,dx>
parmW selector
cBegin
CheckLDT selector
push di
push ax ; save low bits of address
mov bx, selector
call GetSelectorCount
mov di, ax
mov cx, dx ; CX:DX has new address
pop dx
set_bases:
DPMICALL 0007h ; Set selector base
lea bx, [bx+DSC_LEN] ; On to next selector
inc cx ; Add 64k to base
dec di
jnz set_bases
pop di
cEnd
;-----------------------------------------------------------------------;
; get_selector_length16
;
;
; Entry:
;
; Returns:
; AX 16 bit segment length
; Registers Destroyed:
;
; History:
; Sat 09-Jul-1988 16:40:59 -by- David N. Weise [davidw]
;
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc get_selector_length16,<PUBLIC,NEAR>
parmW selector
cBegin
mov ax, -1
lsl ax, selector
inc ax ; length is one bigger!
cEnd
;-----------------------------------------------------------------------;
; set_sel_limit
; SIDE EFFECT: descriptor bases and access are set based
; on the first in the array
;
; Entry:
; CX:BX = length of segment
; Returns:
;
; Registers Destroyed:
; CX
;
; History:
; Fri 15-Jul-1988 19:41:44 -by- David N. Weise [davidw]
;
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc set_sel_limit,<PUBLIC,NEAR>,<ax,bx,dx>
parmW selector
localV DscBuf,DSC_LEN
cBegin
push es
push di
push bx ; Get existing descriptor
smov es, ss
lea di, DscBuf
mov bx, selector
CheckLDT bl
ifdef WOW
DPMICALL 000Bh
else
push ds ; Get Descriptor
mov ds, gdtdsc
push si
mov si, bx
and si, not 7
MovsDsc
lea di, [di-DSC_LEN] ; Restore DI
pop si
pop ds
endif; WOW
pop bx
mov dx, word ptr [DscBuf.dsc_access]
and dh, 0F0h ; Zap old hlimit bits
sub bx, 1 ; Turn length into linit
sbb cx, 0
and cx, 0Fh ; Get bits 19:16 of new limit
or dh, cl ; Set new hlimit bits
mov word ptr DscBuf.dsc_access, dx
mov DscBuf.dsc_limit, bx
mov bx, Selector
jcxz ssl_set_limit1 ; Only one, fast out
inc cx ; Turn CX into selector count
call fill_in_selector_array
jmps ssl_done
ssl_set_limit1: ; Fast out for one only
ifdef WOW
DPMICALL 000Ch
else
push ds
push bx ; Set Descriptor
mov ds, gdtdsc
and bl, not 7
mov ax, es:[di] ; This looks slow but it isn't...
mov ds:[bx], ax
mov ax, es:[di][2]
mov ds:[bx][2], ax
mov ax, es:[di][4]
mov ds:[bx][4], ax
mov ax, es:[di][6]
mov ds:[bx][6], ax
if 0 ;;ROM and KDEBUG
call CheckROMSelector
endif
pop bx
pop ds
endif; WOW
ssl_done:
pop di
pop es
smov ss,ss ; It might be SS we're changing
cEnd
;-----------------------------------------------------------------------;
; mark_sel_NP
;
;
; Entry:
;
; Returns:
;
; Registers Destroyed:
;
; History:
; Fri 15-Jul-1988 21:37:22 -by- David N. Weise [davidw]
;
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc mark_sel_NP,<PUBLIC,NEAR>
parmW selector
parmW owner
localV DscBuf,DSC_LEN
cBegin
push es
push ax
push bx
push di
ifdef WOW
lea di, DscBuf
smov es, ss
mov bx, selector
DPMICALL 000Bh
and DscBuf.dsc_access, not DSC_PRESENT
or DscBuf.dsc_hlimit, DSC_DISCARDABLE
mov ax, owner
mov DscBuf.dsc_owner, ax
DPMICALL 000Ch
else
push ds ; Get Descriptor
mov ds, gdtdsc
mov bx, selector
and bl, not 7
and [bx].dsc_access, not DSC_PRESENT
or [bx].dsc_hlimit, DSC_DISCARDABLE
mov ax, owner
mov [bx].dsc_owner, ax
pop ds
endif; WOW
SetKernelDS
mov ds, pGlobalHeap
UnSetKernelDS
cCall AssociateSelector,<bx,owner>
pop di
pop bx
pop ax
pop es
cEnd
;-----------------------------------------------------------------------;
; mark_sel_PRESENT
;
; This little routine is called from grealloc, specifically
; racreate.
;
; Entry:
; parmW arena_sel
; parmW selector
;
; Returns:
; SI = selector to client area (may have changed)
;
; Registers Destroyed:
;
; History:
; Tue 06-Feb-1990 00:29:56 -by- David N. Weise [davidw]
; Cleaning up tony's int 1's way too late.
;
; Fri 15-Jul-1988 21:37:22 -by- David N. Weise [davidw]
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc mark_sel_PRESENT,<PUBLIC,NEAR>,<ax,bx,cx,dx,di,ds>
parmW arena_sel
parmW selector
localV DscBuf,DSC_LEN
cBegin
push es
smov es, ss
lea di, DscBuf ; ES:DI -> descriptor buffer
mov bx, selector
ifdef WOW
DPMICALL 000Bh ; Get old descriptor
else
push ds ; Get Descriptor
mov ds, gdtdsc
push si
mov si, bx
and si, not 7
MovsDsc
lea di, [di-DSC_LEN] ; Restore DI
pop si
pop ds
endif; WOW
or DscBuf.dsc_access, DSC_PRESENT
mov ds, arena_sel
mov bl, DscBuf.dsc_hlimit
and bl, 0Fh ; Current number of selectors - 1
inc bl
mov ax, ds:[ga_size]
mov cx, ax
dec cx
shr cx, 12 ; New number of selectors - 1
inc cl
sub bl, cl
jz go_ahead ; Same number, just fill in array
jb get_big ; More, must get more
; here to get small
and DscBuf.dsc_hlimit, NOT 0Fh
dec cl
or DscBuf.dsc_hlimit, cl ; Put new number of selectors in limit
inc cl
push cx
xor bh,bh ; BX = number of selectors to free
shl cx,3
.errnz DSC_LEN - 8
add cx,selector ; CX = selector to start to free
xchg bx,cx
@@: cCall free_sel,<bx>
lea bx, [bx+DSC_LEN]
loop @B
pop cx
jmps go_ahead ; And fill in remaining selectors
get_big:
push ax ; # paragraphs
mov bx, ds
DPMICALL 0006h ; Get base address of arena
add dx, 10h ; Move on to block
adc cx, 0
pop bx ; # paragraphs
mov ax, word ptr DscBuf.dsc_access ; Access bits in ax
cCall alloc_sel,<cx,dx,bx>
mov si, ax
or ax,ax ; did we get a set?
jz return_new_handle
or si, SEG_RING
test selector, IS_SELECTOR
jnz @F
StoH si
HtoS selector
@@:
SetKernelDS
mov ds, pGlobalHeap
UnSetKernelDS
cCall AssociateSelector,<selector,0>
cCall FreeSelArray,<selector> ; Zap old handle
jmps return_new_handle
go_ahead:
shl ax, 4 ; AX had length in paras
dec ax ; now limit in bytes
mov DscBuf.dsc_limit, ax ; Put in descriptor
push cx
mov bx, ds
DPMICALL 0006h ; Get base address of arena
add dx, 10h ; Move on to block
adc cx, 0
mov DscBuf.dsc_lbase, dx
mov DscBuf.dsc_mbase, cl
mov DscBuf.dsc_hbase, ch
pop cx ; # selectors
mov bx, selector
call fill_in_selector_array
mov si, selector ; return old selector in SI
return_new_handle:
pop es
cEnd
;-----------------------------------------------------------------------;
; alloc_data_sel_below
;
;
; Entry:
;
; Returns:
;
; Registers Destroyed:
;
; History:
; Sat 09-Jul-1988 19:10:14 -by- David N. Weise [davidw]
;
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc alloc_data_sel_below,<PUBLIC,NEAR>,<bx,cx,dx>
parmW selector
parmW paras
cBegin
mov bx, paras
xor cx, cx
rept 4
shl bx, 1
rcl cx, 1
endm
cCall get_physical_address,<selector>
sub ax, bx
sbb dx, cx
cCall alloc_data_sel,<dx, ax, 1>
cEnd
;-----------------------------------------------------------------------;
; alloc_data_sel_above
;
;
; Entry:
;
; Returns:
;
; Registers Destroyed:
;
; History:
; Sat 09-Jul-1988 19:10:14 -by- David N. Weise [davidw]
;
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc alloc_data_sel_above,<PUBLIC,NEAR>,<bx,cx,dx>
parmW selector
parmW paras
cBegin
mov bx, paras
xor cx, cx
rept 4
shl bx, 1
rcl cx, 1
endm
cCall get_physical_address,<selector>
add ax, bx
adc dx, cx
cCall alloc_data_sel,<dx, ax, 1>
cEnd
;-----------------------------------------------------------------------;
; cmp_sel_address
;
; Compares the physical addresses corresponding to two selectors
;
; Entry:
;
; Returns:
;
; Registers Destroyed:
;
; History:
; Sat 09-Jul-1988 19:10:14 -by- David N. Weise [davidw]
;
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc cmp_sel_address,<PUBLIC,NEAR>,<ax,bx,cx,dx>
parmW sel1
parmW sel2
cBegin
cCall get_physical_address,<sel1>
mov cx, dx
mov bx, ax
cCall get_physical_address,<sel2>
cmp cx, dx
jne csa_done
cmp bx, ax
csa_done:
cEnd
;-----------------------------------------------------------------------;
; get_arena_pointer
;
;
; Entry:
;
; Returns:
;
; Registers Destroyed:
;
; History:
; Sat 09-Jul-1988 20:11:27 -by- David N. Weise [davidw]
;
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc far_get_arena_pointer,<FAR,PUBLIC>
parmW selector
cBegin
cCall get_arena_pointer,<selector>
cEnd
cProc get_arena_pointer,<PUBLIC,NEAR>
parmW selector
cBegin
push bx
push ds
push es
mov bx, selector
cCall get_selector_association
ReSetKernelDS es
if ROM
test al,1 ; If the low bit isn't set
jnz @f ; then it's either 0 or the
xor ax,ax ; special ROM owner selector
jmps gap_exit ; (see Get/SetROMOwner)
@@:
endif
if KDEBUG
or ax, ax
jz gap_exit
mov ds, ax ; Sanity checks:
cmp ds:[ne_magic], NEMAGIC
je gap_exit
cmp ds:[0], 020CDh ; PSP - not a very good check,
je gap_exit ; but OK for DEBUG
push si
mov si, ds:[ga_handle] ; Make sure handle matches
sel_check si
or si, si
jz short gap_match ; Boot time...
sub bx, word ptr SelTableStart
shl bx, 2
cmp bx, si
je short gap_match
xor ax, ax ; put back in 5 feb 90, alias avoided
;;; xor ax, ax ; Removed - may be an alias!
gap_match:
pop si
endif ; KDEBUG
gap_exit:
pop es
pop ds
pop bx
cEnd
;-----------------------------------------------------------------------;
; AssociateSelector
;
; Put the arena pointer or owner in the selector table slot
; corresponding to the given selector.
;
;
; Entry:
;
; Returns:
;
; Registers Destroyed:
; flags
;
; History:
;
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc FarAssociateSelector,<PUBLIC,FAR>
parmW Selector
parmW ArenaSel
cBegin
cCall AssociateSelector,<Selector,ArenaSel>
cEnd
cProc AssociateSelector,<PUBLIC,NEAR>,<ax,bx,es>
parmW selector
parmW ArenaSel
cBegin
SetKernelDS es
CheckDS ; DS must bp pGlobalHeap
mov bx, selector
and bl, NOT SEG_RING_MASK
shr bx, 2 ; 2 bytes per selector: divide by 4
if KDEBUG
cmp bx, SelTableLen ; More sanity
jb @F
INT3_WARN
jmps bad
@@:
endif
add bx, word ptr SelTableStart
mov ax, ArenaSel
if KDEBUG
or ax, ax ; Zero means deleting entry
jz okay
CheckLDT al ; Ensure we won't GP fault later
okay:
endif
mov ds:[bx], ax ; Finally fill in table entry
bad:
cEnd
;-----------------------------------------------------------------------;
; get_selector_association
;
; Returns the arena pointer or owner field from the selector table that
; was set by AssociateSelector.
;
;
; Entry:
; BX = selector to get associated arena pointer/owner
;
; Returns:
; AX = arena pointer/owner or 0
; DS = pGlobalHeap
; ES = Kernel DS
;
; Registers Destroyed:
; BX, flags
;
; History:
;
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc get_selector_association,<PUBLIC,NEAR>
cBegin nogen
SetKernelDS es
mov ds, pGlobalHeap
and bl, NOT SEG_RING_MASK
shr bx, 2 ; 2 bytes per selector: divide by 4
if ROM ;-------------------------------
cmp bx, SelTableLen ; Selector in range? Make this check
jb gsa_in_range ; even if not debug kernel.
xor ax,ax ; No, just fail
jmps gsa_exit
gsa_in_range:
else ;ROM ------------------------
if KDEBUG
cmp bx, SelTableLen ; Selector in range?
jb @F
INT3_WARN
xor ax, ax ; No, just fail
jmps gsa_exit
@@:
endif
endif ;ROM ------------------------
add bx, word ptr SelTableStart
mov ax, ds:[bx] ; Get associated value
gsa_exit:
ret
cEnd nogen
;-----------------------------------------------------------------------;
; pdref ;
; ;
; Dereferences the given global handle, i.e. gives back abs. address. ;
; ;
; Arguments: ;
; DX = selector ;
; DS:DI = BURGERMASTER ;
; ;
; Returns: ;
; ES:DI = address of arena header ;
; AX = address of client data ;
; CH = lock count or 0 for fixed objects ;
; CL = flags ;
; SI = handle, 0 for fixed objects ;
; ;
; Error Returns: ;
; ZF = 1 if invalid or discarded ;
; AX = 0 ;
; BX = owner of discarded object ;
; ;
; Registers Preserved: ;
; ;
; Registers Destroyed: ;
; ;
; Calls: ;
; ghdref ;
; ;
; History: ;
; ;
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc pdref,<PUBLIC,NEAR>
cBegin nogen
mov si, dx
sel_check si
or si, si ; Null handle?
mov ax, si
jz pd_exit ; yes, return 0
cCall GetAccessWord,<dx> ; Get the access bits
or ax, ax
jz pd_totally_bogus
; We should beef up the check for a valid discarded sel.
xor cx,cx
test ah, DSC_DISCARDABLE
jz pd_not_discardable
or cl,GA_DISCARDABLE
; Discardable, is it code?
test al,DSC_CODE_BIT
jz pd_not_code
or cl,GA_DISCCODE
pd_not_code:
pd_not_discardable:
test al,DSC_PRESENT
jnz pd_not_discarded
; object discarded
or cl,HE_DISCARDED
ife RING-1
or si, SEG_RING+1 ; Handles are RING 2
else
or si, SEG_RING-1 ; Handles are RING 2
endif
cCall get_arena_pointer,<si> ; get the owner
mov bx, ax
xor ax,ax
jmps pd_exit
pd_not_discarded:
if KDEBUG
or si, SEG_RING ; For the sel_check later
endif
cCall get_arena_pointer,<si>
or ax, ax
jz pd_nomatch
mov es, ax
mov ax, es:[ga_handle] ; The real thing
mov si, ax
cmp ax, dx ; Quick check - handle in header
je pd_match ; matches what we were given?
test dl, IS_SELECTOR ; NOW, we MUST have been given
jz pd_totally_bogus ; a selector!!
test al, GA_FIXED ; Fixed segment?
jnz pd_nomatch ; Doesn't match arena header...
push ax
HtoS al
cmp ax, dx ; Selector must match
pop ax
jne pd_nomatch
pd_match:
or cl, es:[ga_flags]
and cl, NOT HE_DISCARDED ; same as GA_NOTIFY!!
test al, GA_FIXED
jnz pd_fixed
mov ch, es:[ga_count]
HtoS al ; Back to ring 1
pd_exit:
or ax,ax
ret
pd_totally_bogus:
if KDEBUG
or dx,dx
jnz dref_invalid
pd_null_passed:
endif
xor dx,dx
pd_nomatch: ; Handle did not match...
mov ax, dx ; Must be an alias...
pd_fixed:
xor si, si
xor dx, dx
jmps pd_exit
if KDEBUG
dref_invalid:
push ax
kerror ERR_GMEMHANDLE,<gdref: invalid handle>,0,dx
pop ax
jmps pd_null_passed
endif
cEnd nogen
;-----------------------------------------------------------------------;
; get_rover_2 ;
; ;
; Entry: ;
; ;
; Returns: ;
; ;
; Error Returns: ;
; ;
; Registers Preserved: ;
; AX,BX,CX,DX,DI,SI,DS ;
; ;
; Registers Destroyed: ;
; ;
; Calls: ;
; ;
; History: ;
; ;
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc get_rover_2,<PUBLIC,NEAR>,<ax,bx,di>
localV DscBuf,DSC_LEN
cBegin
mov bx, es
lea di, DscBuf
smov es, ss
ifdef WOW
DPMICALL 000Bh ; Get source descriptor
else
push ds ; Get Descriptor
mov ds, gdtdsc
push si
mov si, bx
and si, not 7
MovsDsc
lea di, [di-DSC_LEN] ; Restore DI
pop si
pop ds
endif; WOW
SetKernelDS es
mov bx, kr2dsc ; Will set kr2 to point there
or bl, SEG_RING
mov word ptr DscBuf.dsc_access, DSC_PRESENT+DSC_DATA
mov DscBuf.dsc_limit, 0FFFFh
smov es, ss
UnSetKernelDS es
ifdef WOW
DPMICALL 000Ch
else
push ds
mov ds, gdtdsc
push bx ; Set Descriptor
and bl, not 7
mov ax, es:[di] ; This looks slow but it isn't...
mov ds:[bx], ax
mov ax, es:[di][2]
mov ds:[bx][2], ax
mov ax, es:[di][4]
mov ds:[bx][4], ax
mov ax, es:[di][6]
mov ds:[bx][6], ax
if 0 ;;ROM and KDEBUG
call CheckROMSelector
endif
pop bx
pop ds
endif; WOW
mov es, bx
cEnd
;-----------------------------------------------------------------------;
; get_blotto
;
;
; Entry:
; AX = arena header
;
; Returns:
;
; Registers Destroyed:
;
; History:
; Sun 31-Jul-1988 16:20:53 -by- David N. Weise [davidw]
;
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc get_blotto,<PUBLIC,NEAR>,<bx,di,es>
localV DscBuf,DSC_LEN
cBegin
mov bx, ax
lea di, DscBuf
smov es, ss
ifdef WOW
DPMICALL 000Bh ; Get source descriptor
else
push ds ; Get Descriptor
mov ds, gdtdsc
push si
mov si, bx
and si, not 7
MovsDsc
lea di, [di-DSC_LEN] ; Restore DI
pop si
pop ds
endif
SetKernelDS es
mov bx, blotdsc ; Will set kr2 to point there
or bl, SEG_RING
mov word ptr DscBuf.dsc_access, DSC_PRESENT+DSC_DATA
mov DscBuf.dsc_limit, 0FFFFh
mov DscBuf.dsc_hlimit, 0Fh
add DscBuf.dsc_lbase, 10h ; Move on to object from arena
adc DscBuf.dsc_mbase, 0
adc DscBuf.dsc_hbase, 0
smov es, ss
UnSetKernelDS es
ifdef WOW
DPMICALL 000Ch ; Set new descriptor
else
push ds
mov ds, gdtdsc
push bx ; Set Descriptor
and bl, not 7
mov ax, es:[di] ; This looks slow but it isn't...
mov ds:[bx], ax
mov ax, es:[di][2]
mov ds:[bx][2], ax
mov ax, es:[di][4]
mov ds:[bx][4], ax
mov ax, es:[di][6]
mov ds:[bx][6], ax
if 0 ;;ROM and KDEBUG
call CheckROMSelector
endif
pop bx
pop ds
endif ;WOW
mov ax, bx ; Return new selector
cEnd
;-----------------------------------------------------------------------;
; get_temp_sel
; far_get_temp_sel
;
;
; Entry:
;
; Returns:
;
; Registers Destroyed:
;
; History:
; Mon 08-Aug-1988 19:14:45 -by- David N. Weise [davidw]
;
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc far_get_temp_sel,<FAR,PUBLIC>
cBegin nogen
cCall get_temp_sel
ret
cEnd nogen
cProc get_temp_sel,<PUBLIC,NEAR>,<ax,bx,cx,di,si,ds>
localV DscBuf,DSC_LEN
cBegin
mov cx, 1
call get_sel
mov ax, si
jz gts_exit
mov bx, es
smov es, ss
lea di, DscBuf
ifdef WOW
DPMICALL 000Bh ; Get existing descriptor
else
push ds ; Get Descriptor
mov ds, gdtdsc
push si
mov si, bx
and si, not 7
MovsDsc
lea di, [di-DSC_LEN] ; Restore DI
pop si
pop ds
endif ; WOW
mov DscBuf.dsc_access,DSC_PRESENT+DSC_DATA
mov DscBuf.dsc_limit,0ffffh
IFNDEF WOW
or DscBuf.dsc_hlimit, 0Fh ; Max length ; bugbug daveh
ENDIF
mov bx, si
or bl, SEG_RING
ifdef WOW
DPMICALL 000Ch ; Set new descriptor
else
push ds
mov ds, gdtdsc
push bx ; Set Descriptor
and bl, not 7
mov ax, es:[di] ; This looks slow but it isn't...
mov ds:[bx], ax
mov ax, es:[di][2]
mov ds:[bx][2], ax
mov ax, es:[di][4]
mov ds:[bx][4], ax
mov ax, es:[di][6]
mov ds:[bx][6], ax
if 0 ;;ROM and KDEBUG
call CheckROMSelector
endif
pop bx
pop ds
endif ; WOW
mov es, bx ; and return selector in ES
gts_exit:
cEnd
cProc far_free_temp_sel,<FAR,PUBLIC>
parmW selector
cBegin
cCall free_sel,<selector>
cEnd
;-----------------------------------------------------------------------;
; PrestoChangoSel
;
;
; Entry:
;
; Returns:
;
; Registers Destroyed:
;
; History:
; Thu 08-Dec-1988 14:17:38 -by- David N. Weise [davidw]
; Wrote it!
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc IPrestoChangoSelector,<PUBLIC,FAR>,<di,si>
parmW sourcesel
parmW destsel
localV DscBuf,DSC_LEN
cBegin
smov es, ss
lea di, DscBuf
mov bx, sourcesel
ifdef WOW
DPMICALL 000Bh
else
push ds ; Get Descriptor
mov ds, gdtdsc
push si
mov si, bx
and si, not 7
MovsDsc
lea di, [di-DSC_LEN] ; Restore DI
pop si
pop ds
endif ; WOW
xor DscBuf.dsc_access, DSC_CODE_BIT
mov bx, destsel
ifdef WOW
DPMICALL 000Ch
else
push ds
mov ds, gdtdsc
push bx ; Set Descriptor
and bl, not 7
mov ax, es:[di] ; This looks slow but it isn't...
mov ds:[bx], ax
mov ax, es:[di][2]
mov ds:[bx][2], ax
mov ax, es:[di][4]
mov ds:[bx][4], ax
mov ax, es:[di][6]
mov ds:[bx][6], ax
if 0 ;;ROM and KDEBUG
call CheckROMSelector
endif
pop bx
pop ds
endif; WOW
mov ax, bx
smov es, 0
cEnd
if 0
;-----------------------------------------------------------------------;
; pmnum ;
; ;
; Enumerates the allocated selectors in the GDT with the ;
; specified discard level. ;
; ;
; Arguments: ;
; SI = zero first time called. Otherwise contains a pointer ;
; to the last handle returned. ;
; CX = #handles remaining. Zero first time called. ;
; DI = address of local arena information structure. ;
; ;
; Returns: ;
; SI = address of handle table entry ;
; CX = #handles remaining, including the one returned. ;
; ZF = 1 if SI = 0 and no more handle table entries. ;
; ;
; Error Returns: ;
; ;
; Registers Preserved: ;
; ;
; Registers Destroyed: ;
; AX ;
; ;
; Calls: ;
; nothing ;
; ;
; History: ;
; ;
; Tue Oct 14, 1986 04:19:15p -by- David N. Weise [davidw] ;
; Added this nifty comment block. ;
;-----------------------------------------------------------------------;
cProc pmnum,<PUBLIC,NEAR>
cBegin nogen
or si,si ; Beginning of enumeration?
jnz lcdhenext ; No, return next handle
mov ax,[di].hi_htable ; Yes, start with last handle table block
lcdhtloop:
mov si,ax ; SI = address of handle table block
or si,si ; Any more handle table blocks?
jz lcdheall ; No, return zero
lodsw ; Get # handles in this block
errnz ht_count
mov cx,ax ; into CX
lcdheloop: ; Loop to process each handle table entry
mov ax,word ptr [si].lhe_flags
errnz <lhe_flags - he_flags>
errnz <2-lhe_flags>
errnz <3-lhe_count>
inc ax ; Free handle?
jz lcdhenext ; Yes, skip this handle
errnz <LHE_FREEHANDLE - 0FFFFh>
errnz <LHE_FREEHANDLE - HE_FREEHANDLE >
dec ax
cmp [di].hi_dislevel,0 ; Enumerating all allocated handles?
je lcdheall ; Yes, return this handle
test al,LHE_DISCARDED ; No, handle already discarded?
jnz lcdhenext ; Yes, skip this handle
and al,LHE_DISCARDABLE ; Test if DISCARDABLE
cmp [di].hi_dislevel,al ; at the current discard level
jne lcdhenext ; No, skip this handle
or ah,ah ; Is handle locked?
jnz lcdhenext ; Yes, skip this handle
lcdheall:
or si,si ; No, then return handle to caller
ret ; with Z flag clear
lcdhenext:
lea si,[si].SIZE LocalHandleEntry ; Point to next handle table entry
errnz <LocalHandleEntry - HandleEntry>
loop lcdheloop ; Process next handle table entry
lodsw ; end of this block, go to next
jmp lcdhtloop
cEnd nogen
endif
;-----------------------------------------------------------------------;
; LongPtrAdd
;
; Performs segment arithmetic on a long pointer and a DWORD offset
; The resulting pointer is normalized to a paragraph boundary.
; The offset cannot be greater than a megabyte.
;
; Entry:
;
; Returns:
; DX:AX new segment:offset
;
; Error returns:
; DX:AX = 0
;
; Registers Destroyed:
; BX,CX
;
; History:
; Mon 19-Dec-1988 18:37:23 -by- David N. Weise [davidw]
; Wrote it!
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
ifdef WOW
LPTRADDWOW_SETBASE equ 01h
;cProc LongPtrAddWOW,<PUBLIC,FAR>,<si,di>
; parmD long_ptr
; parmD delta
; parmW RefSelector
; parmW flBaseSetting
;
; effectively pops RefSelector and flBaseSetting into dx and ax.
; and jumps to longptrAddWorker.
;
; RefSelector is used only if the descriptor needs to be set.
;
labelFP <PUBLIC,LongPtrAddWOW>
pop ax
pop dx ; far return address
mov bx,sp
xchg ax, ss:[bx] ; replace the 'dword' with the return address
xchg dx, ss:[bx+2]
jmps LongPtrAddWorker ; ax = flags; dx = reference selector
labelFP <PUBLIC,LongPtrAdd>
mov ax, LPTRADDWOW_SETBASE
xor dx, dx
; fall through
cProc LongPtrAddWorker,<PUBLIC,FAR>,<si,di>
parmD long_ptr
parmD delta
localV DscBuf,DSC_LEN
localW flBaseSetting
localW RefSelector
cBegin
mov flBaseSetting, ax ; save in localvariables
mov RefSelector, dx
or dx, dx ; if RefSelector is nonzero
jz @F ; use it for querying descriptor info.
xchg dx, word ptr long_ptr[2] ; and store the selector to be set in
mov RefSelector, dx ; the localvariable
@@:
else
cProc LongPtrAdd,<PUBLIC,FAR>,<si,di>
parmD long_ptr
parmD delta
localV DscBuf,DSC_LEN
cBegin
endif
mov bx,word ptr long_ptr[2]
lea di, DscBuf
smov es, ss
ifdef WOW
DPMICALL 000Bh ; Pick up old descriptor
else
push ds ; Get Descriptor
mov ds, gdtdsc
push si
mov si, bx
and si, not 7
MovsDsc
lea di, [di-DSC_LEN] ; Restore DI
pop si
pop ds
endif ; WOW
mov ax,word ptr long_ptr[0] ; get the pointer into SI:AX
and ax,0FFF0h
mov si, DscBuf.dsc_lbase ; DX:SI gets old base
mov dl, DscBuf.dsc_mbase
mov dh, DscBuf.dsc_hbase
add si, ax ; Add in old pointer offset
adc dx, 0
mov cx, word ptr delta[2] ; add the segment and MSW
test cx, 0FFF0h
ifdef WOW
jz @F
test flBaseSetting, LPTRADDWOW_SETBASE
jnz lptr_mustset
jmp short lpa_too_big
@@:
else
jnz short lpa_too_big
endif
add si, word ptr delta[0]
adc dx, cx
ifdef WOW
lptr_mustset:
endif
mov cl, DscBuf.dsc_hlimit ; Calculate # selectors now in array
and cl, 0Fh
xor ch, ch
inc cx
ifdef WOW
test flBaseSetting, LPTRADDWOW_SETBASE
jz lptr_dontset
cmp RefSelector, 0
jz @F
mov bx, RefSelector
mov word ptr long_ptr[2], bx
@@:
endif
mov DscBuf.dsc_lbase, si ; Put new base back in descriptor
mov DscBuf.dsc_mbase, dl
mov DscBuf.dsc_hbase, dh
call fill_in_selector_array
ifdef WOW
lptr_dontset:
test word ptr delta[2], 0fff0h
jz @F
mov cx, word ptr delta[2]
jmps lpa_too_big
@@:
endif
mov dx,word ptr long_ptr[2]
mov ax,word ptr long_ptr[0]
and ax, 0Fh
jmps lpa_exit
lpa_too_big:
xor ax,ax
xor dx,dx
lpa_exit:
smov es,0
cEnd
;-----------------------------------------------------------------------;
; SetSelectorBase
;
; Sets the base and limit of the given selector.
;
; Entry:
; parmW selector
; parmD selbase
;
; Returns:
; AX = selector
;
; Error Returns:
; AX = 0
;
; History:
; Tue 23-May-1989 21:10:29 -by- David N. Weise [davidw]
; Wrote it!
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc SetSelectorBase,<PUBLIC,FAR>
parmW selector
parmD selbase
cBegin
mov bx, selector
mov dx, selbase.lo
mov cx, selbase.hi
ifdef WOW
DPMICALL 0007h
else
push ds
mov ds, gdtdsc
push bx
and bl, not 7
mov ds:[bx].dsc_lbase, dx
mov ds:[bx].dsc_mbase, cl
mov ds:[bx].dsc_hbase, ch
pop bx
pop ds
endif ; WOW
mov ax, 0
jc ssb_exit
mov ax, selector ; Return selector
ssb_exit:
cEnd
;-----------------------------------------------------------------------;
; GetSelectorLimit
;
; Gets the limit of the given selector.
;
; Entry:
; parmW selector
;
; Returns:
; DX:AX = limit of selector
;
; Registers Destroyed:
;
; History:
; Tue 23-May-1989 21:10:29 -by- David N. Weise [davidw]
; Wrote it!
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc GetSelectorLimit,<PUBLIC,FAR>
parmW selector
localV DscBuf,DSC_LEN
cBegin
mov bx, selector
ifdef WOW
lea di, DscBuf
smov es, ss
DPMICALL 000Bh
xor dx, dx
mov ax, DscBuf.dsc_limit
mov dl, DscBuf.dsc_hlimit
and dx, 0Fh ; AND out flags
else
push ds ; Get Descriptor
mov ds, gdtdsc
and bl, not 7
mov ax, [bx].dsc_limit
mov dl, [bx].dsc_hlimit
and dx, 0Fh ; AND out flags
pop ds
endif ; WOW
cEnd
;-----------------------------------------------------------------------;
; SetSelectorLimit
;
; Sets the limit of the given selector.
;
; Entry:
; parmW selector
; parmD sellimit
;
; Returns:
; AX = 0 success
;
; Registers Destroyed:
;
; History:
; Tue 23-May-1989 21:10:29 -by- David N. Weise [davidw]
; Wrote it!
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc SetSelectorLimit,<PUBLIC,FAR>
parmW selector
parmD sellimit
localV DscBuf,DSC_LEN
cBegin
mov bx, selector
ifdef WOW
push di
lea di, DscBuf
smov es, ss
DPMICALL 000Bh
mov ax, word ptr sellimit[0]
mov DscBuf.dsc_limit, ax
mov al, byte ptr sellimit[2]
and al, 0Fh
and DscBuf.dsc_hlimit, 0F0h
or DscBuf.dsc_hlimit, al
DPMICALL 000Ch
pop di
else
push ds ; Get Descriptor
mov ds, gdtdsc
push si
mov si, bx
and si, not 7
mov ax, sellimit.lo
mov [si].dsc_limit, ax
mov ax, sellimit.hi
and al, 0Fh
and [si].dsc_hlimit, 0F0h
or [si].dsc_hlimit, al
pop si
pop ds
endif ;WOW
xor ax,ax ; for now always return success
cEnd
;-----------------------------------------------------------------------;
; SelectorAccessRights
;
; Sets the access and other bytes of the given selector.
;
; Entry:
; parmW selector
; parmW getsetflag
; parmD selrights
;
; Returns:
; AX = 0 success
;
; Registers Destroyed:
;
; History:
; Tue 23-May-1989 21:10:29 -by- David N. Weise [davidw]
; Wrote it!
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc SelectorAccessRights,<PUBLIC,FAR>
parmW selector
parmW getsetflag
parmW selrights
localV DscBuf,DSC_LEN
cBegin
cCall GetAccessWord,<selector>
cmp getsetflag,0
jnz short sar_set
and ax, 0D01Eh ; Hide bits they can't play with
jmps sar_exit
sar_set:
mov cx, selrights
and cx, 0D01Eh ; Zap bits they can't set and
and ax, NOT 0D01Eh ; get them from existing access rights
or cx, ax
mov bx, selector
ifdef WOW
push di
lea di, DscBuf
smov es, ss
DPMICALL 000Bh ; Set new access rights
mov word ptr DscBuf.dsc_access, cx
DPMICALL 000Ch
pop di
else
push ds ; Get Descriptor
mov ds, gdtdsc
and bx, not 7
mov word ptr [bx].dsc_access, cx
pop ds
endif ;WOW
xor ax,ax ; for now always return success
sar_exit:
cEnd
;
; Direct GDT access is really helpful here - you are supposed
; to use LAR to get the high access bits, but this
; cannot be done on a 286 where we are STILL using
; these bits in a 386 compatible manner
;
cProc GetAccessWord,<PUBLIC,NEAR>
parmW selector
localV DscBuf,DSC_LEN
cBegin
push bx
push es
cmp gdtdsc, 0 ; Do we have LDT access?
je do_it_the_really_slow_way ; no, must make DPMI call
mov es, gdtdsc ; Go grab it out of the LDT
mov bx, selector
sel_check bl
mov ax, word ptr es:[bx].dsc_access
jmps gaw_exit
do_it_the_really_slow_way:
push di
lea di, DscBuf
smov es, ss
mov bx, selector
DPMICALL 000Bh
mov ax, word ptr DscBuf.dsc_access
pop di
gaw_exit:
pop es
pop bx
gaw_exit1:
cEnd
;
; Setting it is WORSE....
;
cProc SetAccessWord,<PUBLIC,NEAR>,<ax,bx,es>
parmW selector
parmW access
localV DscBuf,DSC_LEN
cBegin
mov bx, selector
ifndef WOW ; For WOW we have to call DMPI, LATER for mips this should party directly
cmp gdtdsc, 0
je slow_again
mov es, gdtdsc ; Go stuff it in the LDT
sel_check bl
mov ax, access
mov word ptr es:[bx].dsc_access, ax
jmps saw_exit
endif ; WOW
slow_again:
;
; The DPMI guys changed their mind, NOW call 9h
; WILL set the AVL bit in the descriptor on
; all implementations.
;
sel_check bl
push cx
mov cx, access
DPMICALL 0009h
pop cx
saw_exit:
cEnd
;
; Selector in BX
;
cProc GetSelectorCount,<PUBLIC,NEAR>
cBegin nogen
cmp gdtdsc, 0
je @F
push ds
push bx
mov ds, gdtdsc
sel_check bl
mov al, ds:[bx].dsc_hlimit
pop bx
pop ds
and ax, 0Fh
inc al
ret
@@:
push es
push di
sub sp, DSC_LEN
mov di, sp
smov es, ss
DPMICALL 000Bh
mov al, es:[di].dsc_hlimit
add sp, DSC_LEN
pop di
pop es
and ax, 0Fh
inc al
ret
cEnd nogen
;-----------------------------------------------------------------------;
; GlobalPageLock
;
; Page locks the memory associated with the Handle.
;
; Entry:
; parmW handle
;
; Returns:
; AX = new lock count
;
; History:
; Fri 16-Feb-1990 02:13:09 -by- David N. Weise [davidw]
; Should it or shouldn't it? At the very least it must lock
; the object to be consitent with 386pmode.
;
; Wed 31-May-1989 22:14:21 -by- David N. Weise [davidw]
; Wrote it!
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc IGlobalPageLock,<PUBLIC,FAR>,<si,di>
parmW handle
cBegin
cCall GlobalFix,<handle>
cCall GetSelectorLimit,<handle>
mov si, dx
mov di, ax
cCall get_physical_address,<handle>
mov bx, dx
mov cx, ax
DPMICALL 0600h
mov ax, 1
cEnd
;-----------------------------------------------------------------------;
; GlobalPageUnlock
;
; Page unlocks the memory associated with the Handle.
;
; Entry:
; parmW handle
;
; Returns:
; AX = new lock count
;
; History:
; Fri 16-Feb-1990 02:13:09 -by- David N. Weise [davidw]
; Should it or shouldn't it? At the very least it must unlock
; the object to be consitent with 386pmode.
;
; Wed 31-May-1989 22:14:21 -by- David N. Weise [davidw]
; Wrote it!
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc IGlobalPageUnlock,<PUBLIC,FAR>,<si,di>
parmW handle
cBegin
cCall GlobalUnFix,<handle>
cCall GetSelectorLimit,<handle>
mov si, dx
mov di, ax
cCall get_physical_address,<handle>
mov bx, dx
mov cx, ax
DPMICALL 0601h
xor ax,ax ; page lock count is zero
cEnd
if ROM ;----------------------------------------------------------------
;-----------------------------------------------------------------------
; ChangeROMHandle
;
; Changes the handle of an allocated memory block. Used when loading
; segments from ROM to RAM so RAM copy can use the handle expected by
; other ROM code.
;
; Entry:
; parmW hOld
; parmW hNew
;
; Returns:
; AX = hNew if successful, 0 if not
;
; History:
;
;-----------------------------------------------------------------------
assumes ds,nothing
assumes es,nothing
cProc ChangeROMHandle,<PUBLIC,FAR>,<bx,si,di,ds,es>
parmW hOld
parmW hNew
localV DscBuf,DSC_LEN
cBegin
mov bx,hOld ; Get arena pointer for old handle
cCall get_arena_pointer,<bx>
or ax,ax
if KDEBUG
jnz @f
INT3_WARN
jmps ch_ret
@@:
else
jz ch_ret
endif
push ax
mov si, bx
and bx, SEG_RING_MASK ; Ring bits
or bx, hNew ; New handle
smov es, ss
lea di, DscBuf
xchg bx ,si
DPMICALL 000Bh ; Get old descriptor
xchg bx, si
DPMICALL 000Ch ; Set new descriptor
pop es ; es -> arena (or owner)
SetKernelDS
mov ds, pGlobalHeap
UnSetKernelDS
cCall AssociateSelector,<si,0> ; Old sel has not association
test DscBuf.dsc_access,DSC_PRESENT ; Change handle in arena
jz crh_np ; if selector is present
mov es:[ga_handle], bx
crh_np:
cCall AssociateSelector,<bx,es> ; New sel associated with this
; arena or owner
cCall FreeSelArray,<hOld> ; Free old selector
mov ax,bx
ch_ret:
cEnd
;-----------------------------------------------------------------------
; CloneROMSelector
;
; Changes the base and limit of the clone selector to point to the
; ROM selector's original ROM segment. ROM segment selectors may be
; changed when loading a ROM segment to RAM.
;
; Entry:
; parmW selROM
; parmW selClone
;
; Returns:
;
; History:
;
;-----------------------------------------------------------------------
assumes ds,nothing
assumes es,nothing
cProc CloneROMSelector,<PUBLIC,NEAR>,<bx, si, di, ds, es>
parmW selROM
parmW selClone
localV DscBuf,DSC_LEN
cBegin
SetKernelDS es
mov ax,selROMLDT
mov es,selROMToc
assumes es,nothing
mov bx,selROM
if KDEBUG
cmp bx,es:[FirstROMsel] ; sanity checks to make sure
jae @f ; selector is within ROM range
INT3_WARN
@@:
push bx
and bl,not SEG_RING_MASK
sub bx,es:[FirstROMsel]
shr bx,3
cmp bx,es:[cROMsels]
jbe @f
INT3_WARN
@@:
pop bx
endif
mov si, bx
and si, NOT SEG_RING_MASK
sub si, es:[FirstROMsel] ; si = offset in ROM LDT of descriptor
mov ds, ax ; copy ROM desciptor to stack buffer
smov es, ss
lea di, DscBuf
errnz <8 - DSC_LEN>
movsw
movsw
movsw
movsw
mov bx, selClone ; clone descriptor to orig ROM contents
lea di, DscBuf
DPMICALL 000Ch
SetKernelDS
mov ds, pGlobalHeap
UnSetKernelDS
cCall AssociateSelector,<bx,0> ; no arena/owner currently
mov ax,bx ; return with selClone in AX
cEnd
endif ;ROM ---------------------------------------------------------
cProc SetKernelCSDwordProc,<PUBLIC,NEAR>,<ax,bx,ds>
parmw addr
parmw hiword
parmw loword
cBegin
SetKernelDS
mov ds, MyCSAlias
UnSetKernelDS
mov bx, addr
mov ax, loword
mov [bx], ax
mov ax, hiword
mov [bx+2], ax
cEnd
cProc GetKernelDataSeg,<PUBLIC,NEAR>
cBegin nogen
mov ax, cs:MyCSDS
ret
cEnd nogen
cProc SetKernelDSProc,<PUBLIC,NEAR>
cBegin nogen
mov ds, cs:MyCSDS
ret
cEnd nogen
cProc SetKernelESProc,<PUBLIC,NEAR>
cBegin nogen
mov es, cs:MyCSDS
ret
cEnd nogen
cProc CheckKernelDSProc,<PUBLIC,NEAR>
cBegin nogen
if KDEBUG
cmp ax, cs:MyCSDS
je dsok
INT3_WARN
dsok:
endif
ret
cEnd nogen
assumes ds, nothing
assumes es, nothing
cProc FarGetOwner,<PUBLIC,FAR>,<bx>
parmW Selector
cBegin
cCall GetOwner,<Selector>
cEnd
cProc GetOwner,<PUBLIC,NEAR>,<es>
parmW Selector
cBegin
cCall get_arena_pointer,<Selector>
if ROM
or ax,ax ; get_arena_pointer fails on
jnz go_got_it ; ROM segments so give it
cCall GetROMOwner,<Selector> ; another try
jmps go_end
go_got_it:
else
or ax, ax
jz go_end
endif
mov es, ax
mov ax, es:[ga_owner]
go_end:
cEnd
assumes ds, nothing
assumes es, nothing
cProc FarSetOwner,<PUBLIC,FAR>
parmW Selector
parmW owner
cBegin
cCall SetOwner,<Selector,owner>
cEnd
assumes ds, nothing
assumes es, nothing
cProc SetOwner,<PUBLIC,NEAR>,<ax,es>
parmW Selector
parmW owner
cBegin
cCall get_arena_pointer,<Selector>
mov es, ax
push owner
pop es:[ga_owner]
cEnd
if ROM ;----------------------------------------------------------------
;-----------------------------------------------------------------------
; Set/GetROMOwner
;
; The Get/SetROMOwner routines use AssociateSelector and the inverse
; get_selector_association routines to track the owner of an object
; in ROM. ROM objects (like code segments and resources) don't have
; a global heap arena to store the owner's ID in.
;
; NOTE: THIS CODE DEPENDS ON WINDOWS RUNNING IN RING 1 OR 3!! The low
; bit of the associated value is set to zero to indicate the object is
; in ROM. SetROMOwner expects the owner selector to have the low bit
; set, and GetROMOwner returns the owner field with the low bit set.
;
;-----------------------------------------------------------------------
assumes ds, nothing
assumes es, nothing
cProc FarSetROMOwner,<PUBLIC,FAR>
parmW Selector
parmW Owner
cBegin
cCall SetROMOwner,<Selector,Owner>
cEnd
cProc SetROMOwner,<PUBLIC,NEAR>,<ds>
parmW Selector
parmW Owner
cBegin
mov ax,Owner
and al,NOT 1 ; mark this as a ROM selector
SetKernelDS
mov ds,pGlobalHeap
UnSetKernelDS
cCall AssociateSelector,<Selector,ax>
cEnd
cProc GetROMOwner,<PUBLIC,NEAR>,<bx,es,ds>
parmW Selector
cBegin
mov bx,Selector
cCall get_selector_association
or ax,ax
jz gro_exit
test al,1 ; low bit off if ROM owner
jnz gro_not_rom_owner
or al,1 ; restore bit cleared by SetROMOwner
jmps gro_exit
gro_not_rom_owner:
xor ax,ax
gro_exit:
cEnd
;-----------------------------------------------------------------------;
; IsROMObject
;
; Determines if a given selector points into the ROM area.
;
; Entry:
; selector selector to check
;
; Returns:
; AX != 0 & CY set if selector points to ROM
; AX = 0 & CY clr if selector does not point to ROM
;
; Registers Destroyed:
; none
;
; History:
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc FarIsROMObject, <PUBLIC, FAR>
parmW selector
cBegin
cCall IsROMObject, <selector>
cEnd
cProc IsROMObject,<PUBLIC,NEAR>,<bx,di,es>
parmW selector
localV DscBuf,DSC_LEN
cBegin
push ds
SetKernelDS
if KDEBUG
mov ax,selector
sel_check ax
endif
mov bx,selector
smov es,ss
lea di,DscBuf
DPMICALL 000Bh ; Get current descriptor
mov bh,DscBuf.dsc_hbase ; is descriptor base at or
mov bl,DscBuf.dsc_mbase ; above start of ROM?
mov ax,DscBuf.dsc_lbase
sub ax,lmaHiROM.off
sbb bx,lmaHiROM.sel
jc iro_not_rom
sub ax,cbHiROM.off ; make sure it's not above
sbb bx,cbHiROM.sel ; the end of the ROM
jnc iro_not_rom
mov al,1 ; in ROM range, ret AX != 0 & CY set
jmps iro_exit
iro_not_rom:
xor ax,ax ; not in ROM, AX = 0 & CY clear
iro_exit:
pop ds
assumes ds,nothing
cEnd
endif ;ROM ---------------------------------------------------------
assumes ds, nothing
assumes es, nothing
cProc FarValidatePointer,<PUBLIC,FAR>
parmD p
cBegin
cCall ValidatePointer,<p>
cEnd
cProc ValidatePointer,<PUBLIC,NEAR>
parmD p
cBegin
lsl ax, seg_p
jnz short bad_p ; can we access this selector?
cmp ax, off_p ; yes, is the offset valid?
jae short good_p
bad_p:
xor ax, ax
jmps vp_done
good_p:
mov ax, 1
vp_done:
cEnd
assumes ds, nothing
assumes es, nothing
OneParaBytes dw 10h
cProc SelToSeg,<PUBLIC,NEAR>,<dx>
parmW selector
cBegin
cCall get_physical_address,<selector>
div OneParaBytes ; Smaller than rotates
cEnd
cProc SegToSelector,<PUBLIC,NEAR>,<bx>
parmW smegma
cBegin
mov bx, smegma
DPMICALL 0002h
cEnd
;-----------------------------------------------------------------------;
; set_discarded_sel_owner
;
; Sets the owner of a selector that points to a discarded object,
; which lives in the limit field.
;
; Entry:
; BX = selector to mark
; ES = owner
;
; Returns:
; nothing
;
; Registers Destroyed:
; BX
;
; History:
; Sun 03-Dec-1989 21:02:24 -by- David N. Weise [davidw]
; Wrote it!
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc set_discarded_sel_owner,<PUBLIC,FAR>,<ds,di>
localV DscBuf,DSC_LEN
cBegin
mov cx, es
ifdef WOW
push ax
lea di, DscBuf
smov es, ss
DPMICALL 000Bh
mov DscBuf.dsc_owner, cx
DPMICALL 000Ch
pop ax
else
push ds ; Get Descriptor
mov ds, gdtdsc
push di
mov di, bx
and di, not 7
mov [di].dsc_owner, cx
pop di
pop ds
endif ; WOW
SetKernelDS
mov ds, pGlobalHeap
UnSetKernelDS
cCall AssociateSelector,<bx,cx>
mov es, cx ; Restore ES
cEnd
;-----------------------------------------------------------------------;
; SetResourceOwner
;
; Sets the owner of a selector that points to a not present resource
;
; Entry:
;
; Returns:
; nothing
;
; Registers Destroyed:
;
; History:
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc SetResourceOwner,<PUBLIC,NEAR>,<ax,bx,cx,di,ds,es>
parmW selector
parmW owner
parmW selCount
localV DscBuf,DSC_LEN
cBegin
mov bx, selector
mov cx, owner
ifdef WOW
smov es, ss
lea di, DscBuf
DPMICALL 000Bh ; Get current descriptor
mov DscBuf.dsc_owner, cx
mov DscBuf.dsc_access, DSC_DATA
mov cx,selCount
dec cl
and cl,00001111b
or cl,DSC_DISCARDABLE
mov DscBuf.dsc_hlimit, cl ; Save number of selectors here
DPMICALL 000Ch ; Set it with new owner
else
push ds ; Get Descriptor
mov ds, gdtdsc
push bx
and bx, not 7
mov [bx].dsc_owner, cx
mov [bx].dsc_access, DSC_DATA
mov cx,selCount
dec cl
and cl,00001111b
or cl,DSC_DISCARDABLE
mov [bx].dsc_hlimit, cl ; Save number of selectors here
pop bx
pop ds
endif ; WOW
SetKernelDS
mov ds, pGlobalHeap
UnSetKernelDS
cCall AssociateSelector,<bx,owner> ; And save in selector table
cEnd
;-----------------------------------------------------------------------;
;
; Alias stuff moved out due to gross bloating of this file
;
;-----------------------------------------------------------------------;
if ALIASES
include aliases.asm
endif
;-----------------------------------------------------------------------;
; DPMIProc
;
; Called NEAR by the DPMICALL macro -
; this is better than intercepting int 31h
;
; By sheer fluke, all intercepts return with
; Carry clear ie no error.
;
;-----------------------------------------------------------------------;
cProc DPMIProc,<PUBLIC,NEAR>
cBegin nogen
or ah, ah
jz @F
CallServer:
ifndef WOW
int 31h ; Nope, call DPMI server
ret
else
test word ptr [prevInt31Proc + 2],0FFFFh
jz dp30
dp20: pushf
call [prevInt31Proc]
ret
endif
@@:
if ROM
cmp al, 01h ; Free selector?
jne @f
push ds
SetKernelDS
cmp bx,sel1stAvail ; Yes, don't free selectors in
pop ds ; the preallocated ROM range
UnSetKernelDS
jae CallServer
ret
@@:
endif ;ROM
ifdef WOW
cmp gdtdsc, 0 ; Can we party?
jz CallServer ; Nope
endif
push ds
mov ds, gdtdsc
ifdef WOW
or al, al
jnz @F
mov ax, WOW_DPMIFUNC_00
pop ds
jmps CallServer
@@:
endif
cmp al, 0Bh
jne @F
test bx,4
jnz xx1
; On MIPS if Win87EM is processing an NPX exception the selector
; to Dosx's stack is being looked up here. Since it is a global
; selector the normal lookup will not find it and Win87EM will
; fault. This is solved by calling Dosx since it knows about the
; global selectors that we don't. - MarkRi [6/93]
;
pop ds
jmps CallServer
xx1: push si ; Get Descriptor - used very often!
mov si, bx
and si, not 7
MovsDsc
lea di, [di-DSC_LEN] ; Restore DI
pop si
pop ds
ret
ifndef WOW
@@:
cmp al, 0Ch
jne @F
push bx ; Set Descriptor
and bl, not 7
mov ax, es:[di] ; This looks slow but it isn't...
mov ds:[bx], ax
mov ax, es:[di][2]
mov ds:[bx][2], ax
mov ax, es:[di][4]
mov ds:[bx][4], ax
mov ax, es:[di][6]
mov ds:[bx][6], ax
if 0 ;;ROM and KDEBUG
call CheckROMSelector
endif
pop bx
pop ds
ret
@@:
cmp al, 07h ; Set Segment Base Address
jne @F
push bx
and bl, not 7
mov ds:[bx].dsc_lbase, dx
mov ds:[bx].dsc_mbase, cl
mov ds:[bx].dsc_hbase, ch
pop bx
pop ds
ret
endif
@@:
cmp al, 06h ; Get Segment Base Address
jne @F
push bx
and bl, not 7
mov dx, ds:[bx].dsc_lbase
mov cl, ds:[bx].dsc_mbase
mov ch, ds:[bx].dsc_hbase
pop bx
pop ds
ret
ifndef WOW
@@:
cmp al, 09h ; Set Descriptor Access Rights
jne @F
push bx
and bl, not 7
mov word ptr ds:[bx].dsc_access, cx
if 0 ;;ROM and KDEBUG
call CheckROMSelector
endif
pop bx
pop ds
ret
endif
@@:
pop ds
jmp CallServer
ifdef WOW
dp30: int 31h
ret
endif
cEnd nogen
if ROM
if1
%out CheckROMSelector -- fix me!! (what exactly is wrong?)
endif
endif
if 0 ;;ROM and KDEBUG
;------------------------------------------------------------------------
; CheckROMSelector
;
; ROM Windows debug hack to ensure that Windows code doesn't try writing
; to the ROM image. It does this by making any data selector to the
; ROM read only.
;
; Entry:
; DS:BX -> descriptor to check
;
; Returns:
; nothing
;
; Registers Destroyed:
; none
;
;------------------------------------------------------------------------
assumes ds,nothing
assumes es,nothing
cProc CheckROMSelector,<PUBLIC,NEAR>
cBegin nogen
test ds:[bx].dsc_access,DSC_CODEDATA ; code or data dsc?
jz crs_exit ; no, skip it
test ds:[bx].dsc_access,DSC_CODE_BIT ; code?
jnz crs_exit ; yes, skip it
push ax
push dx
mov dh,ds:[bx].dsc_hbase ; is descriptor base at or
mov dl,ds:[bx].dsc_mbase ; above start of ROM?
mov ax,ds:[bx].dsc_lbase
sub ax,lmaHiROM.off
sbb dx,lmaHiROM.sel
jc crs_exit1
sub ax,cbHiROM.off ; make sure it's not above
sbb dx,cbHiROM.sel ; the end of the ROM
jnc crs_exit1
and ds:[bx].dsc_access,NOT DSC_RW_BIT ; make it read only
crs_exit1:
pop dx
pop ax
crs_exit:
ret
cEnd nogen
endif ;ROM and KDEBUG
ifdef WOW
cProc alloc_special_sel,<PUBLIC,NEAR>,<bx,cx,dx,si,di,ds>
parmW AllocFlags
parmW SelFreeBlock
parmW SizeFreeBlock
parmW SizeNewFreeBlock
parmW AdjustedSize
parmB fBaseAddressToUse
localD AddressNewFreeBlock
localD Address
localW Limit
localW cFreeBlock
localW cTotalSelectors
localW EachSelectorLimit
cBegin
;
; this will be our ds
;
mov ds, gdtdsc
;
; replace allocflags with accessword
;
mov bx, AllocFlags
and bx, ((GA_CODE_DATA+GA_DISCARDABLE) shl 8) + GA_DGROUP
or bl, bh
xor bh, bh
shl bx, 1
mov ax, cs:SelAccessWord[bx] ; Pick up access rights for selector
mov AllocFlags, ax ; allocflags = access rights
;
; Limit for data selectors
;
mov ax, AdjustedSize
dec ax
mov Limit, ax
;
; compute base address for new freeblock and the first selector
; the base address is dependent on fBaseAddressToUse flag
;
cCall get_physical_address,<SelFreeBlock>
cmp fBaseAddressToUse, ga_prev
jne @F
mov bx, SizeNewFreeBlock
xor cx,cx
REPT 4
shl bx,1
rcl cx,1
ENDM
add ax, bx
adc dx, cx
mov AddressNewFreeBlock.lo, ax
mov AddressNewFreeBlock.hi, dx
;
; compute base address for first selector
;
add ax, 10h
adc dx, 00h
mov Address.lo, ax
mov Address.hi, dx
jmps alloc_checkforfreeblock
@@:
push ax ; save base address of freeblock
push dx
add ax, 10h
adc dx, 00h
mov Address.lo, ax ; address of first selector
mov Address.hi, dx
pop dx
pop ax
mov bx, AdjustedSize
xor cx,cx
REPT 4
shl bx,1
rcl cx,1
ENDM
add ax, bx
adc dx, cx
mov AddressNewFreeBlock.lo, ax
mov AddressNewFreeBlock.hi, dx
alloc_checkforfreeblock:
;
; check if a 'new' free block needs to be created.
; cFreeBlock = (SizeNewFreeBlock) ? 1 : 0;
;
mov cFreeBlock, 0
mov cx, SizeNewFreeBlock
jcxz alloc_nofreeblock
mov cFreeBlock, 1
alloc_nofreeblock:
;
; start of processing
;
mov cx, 1
mov ax, AllocFlags
test al, DSC_PRESENT
jz allocspecial_oneonly
; limit in paras
mov cx, Limit ; Calculate how many selectors required
add cx, 0FFFh
rcr cx, 1 ; 17 bitdom
shr cx, 11
allocspecial_oneonly:
push cx
add cx, cFreeBlock ; cFreeBlock is zero or one
mov cTotalSelectors, cx
;
; the dpmi func is 04f1h. This is idential to function 00h, except that
; the descriptor base and limit are not initialized to zero.
;
DPMICALL WOW_DPMIFUNC_00
pop cx
jnz allocspecial_continue
jmp allocspecial_exit
allocspecial_continue:
push ax ; save the first selector
and ax, not SEG_RING
mov bx, ax ; Selector in bx for DPMI
mov ax, Address.lo ; Set descriptor base
mov [bx].dsc_lbase, ax
mov di, ax ; used later
mov ax, Address.hi
mov [bx].dsc_mbase, al
mov [bx].dsc_hbase, ah
mov ax, AllocFlags
test al, DSC_PRESENT ; If selector not present, limit is
jnz short allocspecial_present ; as passed, not a paragraph count
allocspecial_not_present:
mov word ptr [bx].dsc_access, ax
mov ax, word ptr Limit
mov [bx].dsc_limit, ax
jmps allocspecial_done
allocspecial_present:
dec cl
and ah, not 0Fh ; Zero limit 19:16
or ah, cl ; Fill in limit 19:16
inc cl
mov word ptr [bx].dsc_access, ax
mov si, ax ; save for later use
mov ax, Limit
shl ax, 4 ; Convert paragraphs to byte limit
dec ax
mov [bx].dsc_limit, ax
dec cx
jcxz allocspecial_done ; if sel=1 done.
mov EachSelectorLimit, ax ; ax the limit from above
mov al, [bx].dsc_mbase ;
mov ah, [bx].dsc_hbase
mov dl, [bx].dsc_hlimit
push ds
SetKernelDS
test WinFlags, WF_CPU286 ; protect mode on a 286?
pop ds
push [bx].dsc_limit ; Save limit for last selector
jz allocspecial_next_sel ; the result of the test above
mov EachSelectorLimit, 0FFFFh ; Others get 64k limit on 286
allocspecial_next_sel:
push ax
mov ax, EachSelectorLimit
mov [bx].dsc_limit, ax ; limit for current selector
pop ax
lea bx, [bx+DSC_LEN] ; On to next selector
cmp cx, 1 ; Last selector?
jne allocspecial_fsa_not_last
pop [bx].dsc_limit ; yes, get its limit
allocspecial_fsa_not_last:
mov [bx].dsc_lbase, di
mov word ptr [bx].dsc_access, si
inc ax
mov [bx].dsc_mbase, al ; Add 64kb to address
mov [bx].dsc_hbase, ah
dec dl
mov [bx].dsc_hlimit, dl ; subtract 64kb from limit
loop allocspecial_next_sel
allocspecial_done:
cmp cFreeBlock, 1
jne allocspecial_nofreeblock
allocspecial_freeblock:
mov ax, AddressNewFreeBlock.lo ; the base for freeblock
mov dx, AddressNewFreeBlock.hi
lea bx, [bx+DSC_LEN] ; On to next selector
mov [bx].dsc_limit, 0fh ; = 1 para
mov [bx].dsc_lbase, ax
mov [bx].dsc_mbase, dl
mov [bx].dsc_hbase, dh
mov ax, DSC_DATA+DSC_PRESENT
and ah, not 0Fh ; Zero limit 19:16
mov word ptr [bx].dsc_access, ax
allocspecial_nofreeblock:
pop si ; restore the first selector
push bx
mov cx, cTotalSelectors
mov bx, si
;
; the dpmi func is 04f2h. This is identical to 0ch except that it
; sets 'count' (in cx) LDTs at one time. The first selector is in
; register bx. The descriptor data is in gdtdsc[bx], gdtdsc[bx+8]
; etc. This data is shared between dpmi (dosx.exe) and us and thus
; need not be passed in es:di
DPMICALL WOW_DPMIFUNC_0C
pop bx
SetKernelDS
;
; sanity check. done so late because if this check was done
; somewhere eariler, we would have had to Save and Restor DS. Since
; this check would be successful most of the time, it is quite Ok
; to do it now and we would avoid unneccessary loading of DS.
mov ax, bx
shr ax, 2
cmp ax, SelTableLen ; Make sure we can associate it
jb @F
xor ax, ax ; set zero flag
jmps allocspecial_exit
@@:
mov UserSelArray, si ; the selector for user data
mov ax, bx
or ax, SEG_RING ; selector of new freeblock, if one is
; created. sets nz flag.
mov SelectorFreeBlock, ax ;
allocspecial_exit:
cEnd
;----------------------------------------------------------------------------
; grabbed from 2gmem.asm
;
;----------------------------------------------------------------------------
SelAccessWord dw DSC_DATA+DSC_PRESENT
dw (DSC_DISCARDABLE SHL 8) + DSC_DATA+DSC_PRESENT
dw DSC_CODE+DSC_PRESENT
dw (DSC_DISCARDABLE SHL 8) + DSC_CODE+DSC_PRESENT
dw DSC_DATA+DSC_PRESENT
dw (DSC_DISCARDABLE SHL 8) + DSC_DATA+DSC_PRESENT
dw DSC_DATA+DSC_PRESENT
dw (DSC_DISCARDABLE SHL 8) + DSC_DATA+DSC_PRESENT
;-----------------------------------------------------------------------------
; Grab the selector 0x47 so that we dont need to special case the biosdata
; selector (0x40) while converting seg:off address to flat 32bit address
;
; This, however should not be part of Krnl286 heap.
;
; - Nanduri Ramakrishna
;-----------------------------------------------------------------------------
cProc AllocSelector_0x47,<PUBLIC,FAR>, <ax, bx, cx, ds>
cBegin
; alloc the specific selector
mov bx, 047h
DPMICALL 0dh
jc as47_exit
; initialize the LDT
and bx, not SEG_RING
mov ds, gdtdsc
mov [bx].dsc_limit, 00h ; = 1 byte
mov [bx].dsc_lbase, 0400h
mov [bx].dsc_mbase, 00h
mov [bx].dsc_hbase, 00h
mov ax, DSC_DATA+DSC_PRESENT
and ah, not 0Fh ; Zero limit 19:16
mov word ptr [bx].dsc_access, ax
; set the LDT
mov cx,1
mov bx, 047h
DPMICALL WOW_DPMIFUNC_0C
as47_exit:
cEnd
sEnd CODE
sBegin NRESCODE
assumes CS,NRESCODE
assumes DS,NOTHING
assumes ES,NOTHING
cProc get_sel_flags,<PUBLIC,NEAR>
parmW selector
cBegin
; Not used in krnl286
xor ax,ax
xor dx,dx
cEnd
cProc set_sel_for_dib,<PUBLIC,NEAR>
parmW selector
parmW flags
parmD address
parmW csel
cBegin
; Not used in krnl286
xor ax,ax
xor dx,dx
cEnd
cProc RestoreDib,<PUBLIC,NEAR>
parmW selector
parmW flags
parmD address
cBegin
; Not used in krnl286
xor ax,ax
xor dx,dx
cEnd
cProc DibRealloc,<PUBLIC,FAR>
parmW Selector
parmW NewSize
cBegin
cEnd
endif
sEnd NRESCODE
end