windpmi.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 566 行 · 第 1/2 页
C
566 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: DPMI function wrappers for Win386.
*
****************************************************************************/
#include <stddef.h>
#include <windows.h>
#include "winext.h"
#include "dpmi.h"
#define MAX_CACHE 48
#define MAX_SELECTORS 8192
extern DWORD StackSize;
extern DWORD SaveSP;
extern WORD DataSelector;
extern WORD StackSelector;
extern WORD Int21Selector;
extern addr_48 CodeEntry;
extern DWORD CodeSelectorBase;
extern DWORD DataSelectorBase;
extern DWORD DataHandle;
extern WORD DPL;
#define Align64K( x ) ( ((x) + 0xffffL) & ~0xffffL )
typedef struct {
WORD sel;
WORD limit;
DWORD base;
char in_use;
} alias_cache_entry;
typedef struct memblk {
struct memblk *next;
DWORD handle;
DWORD addr;
DWORD size;
} memblk;
static WORD WrapAround;
static WORD hugeIncrement;
static WORD firstCacheSel,lastCacheSel;
static WORD cacheUseCount;
static WORD StackCacheSel;
static DWORD StackBase, StackBase_64K;
static alias_cache_entry aliasCache[ MAX_CACHE ];
static WORD currSelCount;
static char SelBitArray[MAX_SELECTORS/8];
memblk *MemBlkList;
static char BitMask[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
/*
* addToSelList - add selector to list of non-cached selectors
*/
static void addToSelList( WORD sel )
{
SelBitArray[ sel >> 6 ] |= BitMask[ (sel >> 3) & 7 ];
currSelCount++;
} /* addToSelList */
/*
* removeFromSelList - remove selector from list of non-cached selectors
*/
static void removeFromSelList( WORD sel )
{
SelBitArray[ sel >> 6 ] &= ~ BitMask[ (sel >> 3) & 7 ];
currSelCount--;
} /* removeFromSelList */
/*
* DPMIGetAliases - get alias descriptors for some memory
*/
#pragma aux DPMIGetAliases parm[dx ax] [es si] [cx] value[ax];
WORD DPMIGetAliases( DWORD offset, DWORD far *res, WORD cnt)
{
long rc;
WORD sel,i;
DWORD limit,base;
alias_cache_entry *ace;
if( offset == 0L ) {
(*res) = 0L;
return( 0 );
}
/*
* optimize alias requests. If we are only asking for 1 alias,
* then we look for a free cache entry. The selector cache is
* a collection of pre-allocated selectors with their access rights
* pre-set and a default limit of 64K. Thus, we only need to set
* the base address and, very rarely, reset the limit (this only
* happens when we are aliasing a chunk in the last 64K of the
* 32-bit segment).
*/
if( cnt == 1 ) {
if( offset < StackBase_64K && offset >= StackBase ) {
*res = (((DWORD) StackCacheSel) << 16) + offset - StackBase;
return( 0 );
}
if( cacheUseCount < MAX_CACHE ) {
ace = &aliasCache[0];
for( i=0;i<MAX_CACHE;i++ ) {
if( !ace->in_use ) {
base = DataSelectorBase+offset;
if( base != ace->base ) {
ace->base = base;
DPMISetSegmentBaseAddress( ace->sel, base );
}
*res = ((DWORD) ace->sel) << 16;
ace->in_use = TRUE;
cacheUseCount++;
return( 0 );
}
ace += 1;
}
}
}
if( cnt == 0 ) {
cnt = 1;
}
/*
* get a descriptor
*/
*res = 0L;
rc = DPMIAllocateLDTDescriptors( cnt );
if( rc < 0L ) {
return( 666 );
}
sel = (WORD) rc;
*res = ((DWORD) sel) << 16;
limit = cnt * 0x10000 - 1;
for( i=0;i<cnt;i++ ) {
#if 0
/*
* We no longer restrict the limit to being 64K, since
* Windows sets the limits of their huge selectors to be
* for the entire linear space, not just 64K
*/
if( limit > 0xFFFF ) {
limit = 0xFFFF;
}
#endif
/*
* set new limit, address, and access rights
*/
if( limit > 1024L*1024L ) { /* 05-oct-93 */
DPMISetDescriptorAccessRights( sel, DPL+ACCESS_DATA16BIG );
} else {
DPMISetDescriptorAccessRights( sel, DPL+ACCESS_DATA16 );
}
DPMISetSegmentBaseAddress( sel, DataSelectorBase + offset );
DPMISetSegmentLimit( sel, limit );
addToSelList( sel );
sel += hugeIncrement;
offset += 0x10000;
limit -= 0x10000;
}
return( 0 );
} /* DPMIGetAliases */
void DPMIFreeAlias( WORD sel )
{
alias_cache_entry *ace;
if( sel == 0 || sel == StackCacheSel ) {
return;
}
if( sel >= firstCacheSel && sel <= lastCacheSel ) {
ace = &aliasCache[ (sel-firstCacheSel)/hugeIncrement ];
if( ace->in_use ) {
ace->in_use = FALSE;
cacheUseCount--;
}
return;
}
removeFromSelList( sel );
DPMIFreeLDTDescriptor( sel );
} /* DPMIFreeAlias */
WORD DPMIGetHugeAlias( DWORD offset, DWORD far *res, DWORD size )
{
DWORD no64k;
no64k = Align64K( size );
return( DPMIGetAliases( offset, res, 1+(WORD) (no64k/0x10000L) ));
}
void DPMIFreeHugeAlias( DWORD desc, DWORD size )
{
DWORD no64k;
WORD cnt,sel,i;
sel = desc >> 16;
if( sel == 0 ) {
return;
}
no64k = Align64K( size );
cnt = 1+(WORD) (no64k/0x10000L);
for( i=0;i<cnt;i++ ) {
removeFromSelList( sel );
DPMIFreeLDTDescriptor( sel );
sel += hugeIncrement;
}
}
/*
* __DPMI fns are the ones called by the 32-bit application
*/
WORD FAR PASCAL __DPMIGetAlias( DWORD offset, DWORD far *res )
{
return( DPMIGetAliases( offset, res, 1 ) );
}
void PASCAL FAR __DPMIFreeAlias( DWORD desc )
{
DPMIFreeAlias( desc >> 16 );
}
WORD FAR PASCAL __DPMIGetHugeAlias( DWORD offset, DWORD far *res, DWORD size )
{
return( DPMIGetHugeAlias( offset, res, size ) );
}
void PASCAL FAR __DPMIFreeHugeAlias( DWORD desc, DWORD size )
{
DPMIFreeHugeAlias( desc, size );
}
/*
* setLimitAndAddr - set the limit and address of a 32-bit selector
*/
void setLimitAndAddr( WORD sel, DWORD addr, DWORD len, WORD type )
{
DPMISetSegmentBaseAddress( sel, addr );
--len;
if( len >= 1024L*1024L ) {
if( type == ACCESS_CODE ) {
DPMISetDescriptorAccessRights( sel, DPL+ACCESS_CODE32BIG );
} else {
DPMISetDescriptorAccessRights( sel, DPL+ACCESS_DATA32BIG );
}
} else {
if( type == ACCESS_CODE ) {
DPMISetDescriptorAccessRights( sel, DPL+ACCESS_CODE32SMALL );
} else {
DPMISetDescriptorAccessRights( sel, DPL+ACCESS_DATA32SMALL );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?