|
|
PAGE ,132 TITLE DXVCPI.ASM -- Dos Extender VCPI Support Code
; Copyright (c) Microsoft Corporation 1990-1991. All Rights Reserved.
;*** dxvcpi.asm - vcpi detection/maintenance/cleanup code (resident) ; ; Copyright <C> 1990, Microsoft Corporation ; ; Purpose: ; ; Revision History: ; ; ; 08-07-90 earleh Allow program to boot without LIM 3.2 page frame. ; 05/07/90 jimmat Started incorporating VCPI changes from languages group. ; ; [] 20-Feb-1990 Dans Created ; ;************************************************************************/
.286p
; ------------------------------------------------------- ; INCLUDE FILE DEFINITIONS ; -------------------------------------------------------
.xlist .sall include segdefs.inc include gendefs.inc include pmdefs.inc .list
; This entire file is only for VCPI support
if VCPI
.xlist .sall include dxvcpi.inc .list ; ; miscellaneous equates ; ; ; also in dxmmgr.asm ; .ERRE CB_MEMHDR EQ 10h ;size of memory block header ; ; also in dxmmgr.asm ; ; ; data ;
DXDATA segment
; ; Externs ;
extrn idCpuType:word extrn bpGDT:fword
extrn cKbInitialHeapSize:word extrn cbHeapSize:dword extrn dsegCurrent:word extrn hmemHeap:word extrn lpfnXMSFunc:DWORD
extrn selGDT:WORD ; ; Definitions, data ;
public fEms fEMS db 0 ; ems present
public fVCPI fVCPI db 0 ; vcpi present
public iddxsystype iddxsystype db DXINDOS ; type of memory used to hold ; final dx Pmode data. public segBootPmode segBootPmode dw 0 ; segment of block used to ; build system tables in real align 4
public cFreePages cFreePages dd 0 ; free 4k pages, updated on each ; allocation. public bpdxsyspages bpdxsyspages dd DXPMPAGES-1 dup(0) ; ; pointer (off of SEL_DXPT) where next free page table entry is ; ; we initialize dxpt1 to have cptdx+2 entries in it (see ; SetupPageTables in dxvcpibt.asm) ;
; ; Offset in zeroth page table of first page table entry that belongs ; to DX. Set by initial call to GetVCPIInterface. ; public pPteFirst pPteFirst dd 0
; ; Offset in block pointed to by SEL_DXPT of where to put next page ; table entry when allocating extended memory by the page. ; public pPteNext pPteNext dd 0
; ; Maximum number of user page table entries that will fit in our ; original page table buffers. ; public cPteMax cPteMax dd 0
EXTRN hmem_XMS_Table:WORD EXTRN hmem_XMS_Count:WORD
public hmem_System_Block hmem_System_Block dw 0
DXDATA ends
DXPMCODE segment
IFDEF ROM %OUT VCPI Support not compatible with ROM! Code segment variables!
.ERR ENDIF
; ; Data set up in real mode prior to relocation of DX into vcpi ; (read only after init time anyway) ;
public fnVCPIPM, fnVCPIPMoff
fnVCPIPM label fword ; vcpi interface entrypoint fnVCPIPMoff dd 0 ; set up in GetVCPIInterface dw SEL_VCPI ; we know what this is.
externFP NSetSegmentDscr extrn XMScontrol:FAR
pmxmssvc macro fcn ifnb <fcn> mov ah, fcn endif call XMScontrol endm
DXPMCODE ends
DXCODE segment ; ; Data set up in real mode prior to relocation of DX into vcpi ; (read only after init time anyway) ;
public WdebVCPI, fnVCPI, fnVCPIoff
;--------- WdebVCPIInfo structure -----------
public laVTP, V86ToPm
; ; Begin WDEB386 VCPI notification structure. The following variables ; are copied by WDEB386 when we send it a VCPI presence notification, ; just after entering protected mode. The structure of this block of variables ; must not be changed without also changing the format of the data ; structure used by WDEB386. ; ;--------- WdebVCPIInfo structure ----------- WdebVCPI LABEL BYTE
fnVCPI label fword ; vcpi interface entrypoint fnVCPIoff dd 0 ; set up in GetVCPIInterface dw SEL_VCPI ; we know what this is.
dw SEL_VCPIALLMEM ; for Wdeb386 information
laVTP dd 0 ; linear address of next structure ; ; End WDEB386 VCPI notification structure. ;
; Structure for switching from v86 mode to protect mode via VCPI
EXTRN epmVCPI:BYTE
V86ToPm VTP <,,, SEL_LDT, SEL_TSS, OFFSET epmVCPI, 0, SEL_DXCODE0>
externFP AddXMStoVCPIHeap
DXCODE ends
DXCODE segment
assume cs:DXCODE, ds:DXDATA, es:nothing
;*** FreeEMSHandle - free DX system memory ; ; Purpose: free the VCPI pages OR XMS block we allocated for system use ; ; Register ; Usage: eax, edx, si, cx ; ; Input: none ; ; Output: VCPI DOS Extender system pages freed ; XMS handle deallocated ; ; Returns: nothing ; ; Exceptions: No operation if none of these entities have been ; allocated yet ; ; Notes: ; ;************************************************************************/ cProc FreeEMSHandle,<NEAR,PUBLIC,<> cBegin lea si,bpdxsyspages ; Load VCPI system pages array. mov cx,DXPMPAGES-1 ; (First page was in PSP block.) cld .386 FreeVCPI_syspage: lodsd ; fetch next page or eax,eax ; page present? jz FreeVCPI_Done ; No, could have been XMS. and ax,0f000h ; Yes, clear lower 12 bits. mov edx,eax RMvcpi vcpiFREEPAGE ; and free it. loop FreeVCPI_syspage ; loop until all freed .286p FreeVCPI_Done: test iddxsystype,DXINXMS ; loaded in XMS? jz FreeEMSHandle_ret ; No. mov dx,hmem_System_Block ; Yes, load block xmssvc 0dh ; unlock XMS block mov dx,hmem_System_Block xmssvc 0ah ; free XMS block FreeEMSHandle_ret: cEnd
DXCODE ends
;************************************************************** ; 386 only code from here on down!!! ;************************************************************** .386p
include prot386.inc
DXCODE segment
assume cs:DXCODE, ds:DXDATA, es:nothing
DXCODE ends
DXPMCODE segment assume cs:DXPMCODE
;************************************************************** ;*** CallVCPIPM ; ; Utility routine to call VCPI server in protected mode. Masks out ; interrupts during the call because QEMM enables the processor ; interrupt flag when you call it. ; ; Entry: AX = VCPI function code. ; Uses: Depends upon call. ; ; Note: There is a copy of this routine in dxvcpi.asm and another ; in dxvcpibt.asm. This is to allow near calls. The copy ; in dxvcpibt.asm is discarded after initialization time. ; ;************************************************************** cProc CallVCPIPM,<NEAR>,<si> cBegin
push ax ; save function code ; ; Shut out all interrupts. ; QEMM 5.0 enables interrupts during this call. All our interrupt ; handlers are in the user code ring. A workaround is to shut off ; hardware interrupts during the call. ;
in al,INTA01 IO_Delay mov si, ax mov al,0FFh out INTA01,al IO_Delay
pop ax ;restore function code db 9Ah ;call far SEL_CALLVCPI:0 dw 0,SEL_CALLVCPI or STD_RING
; Restore the state of the interrupt mask register
xchg si, ax out INTA01,al IO_Delay xchg si, ax cEnd
;************************************************************************/ ;*** AllocVCPIMem ; ; Purpose: to allocate a block of memory from VCPI ; ; Register ; Usage: eax, ebx, edx, ecx, es ; ; Input: ECX has number of 4k pages to allocate ; ES:EDI points to page table entries to fill. ; ; Output: pPteNext updated with next free pte ; cFreePages updated with number of free 4k pages from vcpi ; ; Returns: if success, linear ptr in eax ; if fail, eax 0, ebx has number of 4k pages available. ; ; Exceptions: ; ; Notes: maximum allocation is 65535 4k pages (more than enough) ; at one time. ; Also, this is PROTECT MODE ONLY. ; ;************************************************************************/ cProc AllocVCPIMem,<NEAR,PUBLIC>,<bx,dx> cBegin ; ; Compute the number of entries free in our page table ; mov edx, cPteMax cmp ecx, edx ; compare request with PTEs jb @F ; ; our page tables have less room than the vcpi server can allocate, ; so adjust our count downward to reflect that ; mov ecx, edx @@: cmp ecx, cFreePages ; compare request with pages we are ; allowed to allocate jb @F ; request < max.? mov ecx, cFreePages ; No, clip. @@: jecxz AVM_exit ; ECX = pages to allocate
AVM_getpage:
PMvcpi vcpiALLOCPAGE
or ah, ah jnz AVM_exit ; something happened...not as much ; as vcpi said was there. dec cPteMax ; fix up free PTEs dec cFreePages ; and free VCPI pages ; ; make it a page table entry, and store into page table ; don't need to worry about the tlb here, since not-present ; pages are not cached in the tlb. ; or dx, NEWPTEMASK mov eax, edx stos dword ptr es:[edi]
dec ecx jnz AVM_getpage ; next allocate
AVM_exit: cEnd
;************************************************************************/ ;*** VCPISpace ; ; Purpose: Return maximum possible VCPI memory allocation. ; ; Uses: ; ; Input: ; ; Output: ; ; Return: EAX = maximum possible VCPI pages we can get. ; ; Exceptions: ; ; Notes: ; ;************************************************************************/ cProc VCPISpace,<NEAR,PUBLIC>,<edx> cBegin
PMvcpi vcpiCFREEPAGES ; EDX = free VCPI pages cmp edx,cFreePages ; clip to maximum EMS allocation jb VS_00 mov edx,cFreePages VS_00: mov eax,cPteMax ; clip to space in page tables cmp edx,eax jb VS_01 mov edx,eax VS_01: mov eax,edx cEnd
;************************************************************************/ ;*** FreeVCPIHeap ; ; Purpose: To free the Extended Memory heap memory. ; ; Register ; Usage: eax, ebx, ecx, edx ; ; Input: ; ; Output: All VCPI pages allocated for the heap are freed. ; All XMS blocks allocated for the heap are freed. ; Page table entries are set to zero. ; ; ; Returns: nothing ; ; Exceptions: none ; ; Notes: Protect mode only ; ;************************************************************************/ cProc FreeVCPIHeap,<NEAR,PUBLIC>,<es,edi,si,eax,edx> cBegin
mov ax, SEL_DXPT ; set up es with the selector mov es, ax ; for our page tables mov edi, pPteFirst ; point to first page allocated mov ecx, pPteNext ; point to first unallocated PTE sub ecx, edi jbe Free_XMS_Handles shr ecx, 2 ; ECX = pages to free
startloop: mov edx, es:[edi] ; get pte into edx and dx, 0f000h ; mask off 12 lsb's
PMvcpi vcpiFREEPAGE ; free the page
xor eax, eax stos dword ptr es:[edi] ; clear out PTE dec ecx jnz startloop @@: Free_XMS_Handles: lea si, hmem_XMS_Table ; si points to XMS handle array mov cx,[hmem_XMS_Count] jcxz No_XMS_Handles
Free_XMS_Handles_Loop: mov dx,[si] pmxmssvc 0dh ; unlock any XMS blocks mov dx,[si] pmxmssvc 0ah ; free any XMS blocks add si,2 ; point to next slot in handle array loop Free_XMS_Handles_Loop ; loop if more handle slots
No_XMS_Handles:
cEnd
AddXMStoVCPIHeapCall label dword dw offset dxcode:AddXMStoVCPIHeap,SEL_DXCODE or STD_RING
;*** AddVCPIHeap ; ; Purpose: to replace the himem specific code in AddToXmemHeap ; ; Register ; Usage: all preserved except return values in bx:dx ; ; Input: dx:cx is the minimum block length required (bytes). ; ; Output: cbHeapSize is updated if a heap is allocated ; ; Returns: bx:dx is 32bit linear address of allocated block if success, ; cy clear, else cy set ; ; Exceptions: ; ; Notes: ; ;************************************************************************/ cProc AddVCPIHeap,<NEAR,PUBLIC>,<eax,ecx> localD cbNeeded cBegin
push ebx ; save extended registers push edx
add cx, CB_MEMHDR * 3 ; add memory manager overhead adc dx, 0 movzx ecx,cx shl edx,16d or ecx,edx ; ECX = minimum bytes wanted mov cbNeeded,ecx add ecx,CBPAGE386-1 shr ecx,12d ; ECX = minimum pages wanted mov eax, cPteMax cmp ecx,eax ; make sure we have enough jna AVH_00 ; page table entries mov ecx,eax ; ECX = minimum pages wanted AVH_00:
mov cbHeapSize,0
mov ax, SEL_DXPT ; ES -> user page tables mov es, ax mov edi, pPteNext ; Point to first unused PTE or edi, edi ; Initialized? jnz AVH_10 ; Yes, skip XMS allocate. mov edi, pPteFirst ; No, initialize first unused PTE. mov pPteNext, edi
cCall AddXMStoVCPIHeapCall
mov pPteFirst,edi ; VCPI allocations start here
AVH_10: mov ebx, pPteNext ; EBX = first PTE shl ebx, 10d ; EBX = linear address of start of block mov dx, bx shr ebx, 16d ; DX:BX = linear address of block
mov eax, edi sub eax, pPteNext shr eax, 2 ; AX = count of pages allocated sub ecx, eax ; Get what we asked for? jbe AVH_Done ; Yes.
cCall AllocVCPIMem ; allocate it from VCPI ; cx has number of 4k pages AVH_Done: mov eax, edi sub eax, pPteNext mov pPteNext, edi or eax, eax jz AVH_BadExit shl eax, 10d ; EAX = count of bytes allocated sub eax, CB_MEMHDR * 3 ; deduct overhead mov cbHeapSize, eax clc jmp AVH_Exit AVH_BadExit: stc AVH_Exit: ; ; Result is in BX:DX, but we have to save restore the MSW of EBX and ; that of EDX before we return to our caller. ; mov ax,dx pop edx mov dx,ax mov ax,bx pop ebx mov bx,ax cEnd
DXPMCODE ends
endif ;VCPI
end
|