summaryrefslogtreecommitdiffstats
path: root/private/mvdm/dpmi/dxvcpi.asm
diff options
context:
space:
mode:
Diffstat (limited to 'private/mvdm/dpmi/dxvcpi.asm')
-rw-r--r--private/mvdm/dpmi/dxvcpi.asm586
1 files changed, 586 insertions, 0 deletions
diff --git a/private/mvdm/dpmi/dxvcpi.asm b/private/mvdm/dpmi/dxvcpi.asm
new file mode 100644
index 000000000..b9d9a0308
--- /dev/null
+++ b/private/mvdm/dpmi/dxvcpi.asm
@@ -0,0 +1,586 @@
+ 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