windpmi.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 566 行 · 第 1/2 页

C
566
字号
    }
    DPMISetSegmentLimit( sel, len );

} /* setLimitAndAddr */

/*
 * DPMIGet32 - get a 32-bit segment
 */
WORD DPMIGet32( DWORD _FAR *addr_data, DWORD len )
{
    int         rc;
    long        adata[2];

    /*
     * the return codes 4 and 5 are the same as WINMEM32.DLL's return
     * codes.  Hysterical raisins.
     */

    /*
     * get memory region
     */
#ifdef DLL32
    rc = _fDPMIAllocateMemoryBlock( adata, len );
#else
    rc = DPMIAllocateMemoryBlock( adata, len );
#endif
    if( rc ) {
        return( 5 );
    }
    addr_data[0] = adata[0];
    addr_data[1] = adata[1];
    return( 0 );

} /* DPMIGet32 */

/*
 * InitFlatAddrSpace - initialize flat address space
 */
WORD InitFlatAddrSpace( DWORD baseaddr, DWORD len )
{
    long        rc;
    WORD        sel;
    descriptor  desc;

    hugeIncrement = DPMIGetNextSelectorIncrementValue();
    /*
     * get a code selector pointing to the memory
     */
    rc = DPMIAllocateLDTDescriptors( 1 );
    if( rc < 0L ) {
        return( 4 );
    }
    sel = (WORD) rc;
    CodeEntry.seg = sel;
    setLimitAndAddr( sel, baseaddr, len, ACCESS_CODE );
    CodeSelectorBase = baseaddr;

    /*
     * get a data and stack selector pointing to the memory
     */
    rc = DPMIAllocateLDTDescriptors( 2 );
    if( rc < 0L ) {
        DPMIFreeLDTDescriptor( sel );
        return( 4 );
    }
    sel = (WORD) rc;
    DataSelector = sel;
    setLimitAndAddr( sel, baseaddr, len, ACCESS_DATA );
    StackSelector = sel + hugeIncrement;
//    setLimitAndAddr( StackSelector, baseaddr, StackSize, ACCESS_DATA );
//      The code generator sometimes uses EBP as general purpose
//      register for accessing data that is not in the STACK segment
//      so we must access the same space as DS
    setLimitAndAddr( StackSelector, baseaddr, len, ACCESS_DATA );
    WrapAround = FALSE;
    if( DPMIGetDescriptor( DataSelector, &desc ) == 0 ) {
        if( desc.lim_16_19 == 0x0F && desc.lim_0_15 == 0xFFFF ) {
            WrapAround = TRUE;
        } else {
            WrapAround = FALSE;
        }
    }
    return( 0 );

} /* InitFlatAddrSpace */

/*
 * DPMIFree32 - free a 32-bit handle
 */
void DPMIFree32( DWORD handle )
{
    DPMIFreeLDTDescriptor( DataSelector );
    DPMIFreeLDTDescriptor( StackSelector );
    DPMIFreeLDTDescriptor( CodeEntry.seg );
    DPMIFreeMemoryBlock( handle );

} /* DPMIFree32 */

/*
 * __DPMIAlloc - allocate a new block of memory
 */
DWORD FAR PASCAL __DPMIAlloc( DWORD size )
{
    int         rc;
    DWORD       adata[2];
    memblk      *p;

    for(;;) {
        rc = DPMIGet32( adata, size );
        if( rc != 0 ) {
            adata[0] = DataSelectorBase;        // cause NULL to be returned
            break;
        }
        p = (memblk *)LocalAlloc( LMEM_FIXED, sizeof(memblk) );
        if( p == NULL ) {
            DPMIFreeMemoryBlock( adata[1] );
            adata[0] = DataSelectorBase;        // cause NULL to be returned
            break;
        }
        p->next = MemBlkList;
        p->handle = adata[1];
        p->addr   = adata[0];
        p->size   = size;
        MemBlkList = p;
        if( WrapAround || adata[0] >= DataSelectorBase ) break;
        // if we are on NT or OS/2, try again until we get a memory
        // block with address higher than our DataSelectorBase 05-jul-95
    }
    if( (! WrapAround) && MemBlkList != NULL ) {
        /* free up any memory allocated that is below DataSelectorBase */
        for(;;) {
            p = MemBlkList->next;
            if( p == NULL ) break;
            if( p->addr >= DataSelectorBase ) break;
            DPMIFreeMemoryBlock( p->handle );
            MemBlkList->next = p->next;
            LocalFree( (HLOCAL)p );
        }
        p = MemBlkList;
        if( p->addr < DataSelectorBase ) {
            DPMIFreeMemoryBlock( p->handle );
            MemBlkList = p->next;
            LocalFree( (HLOCAL)p );
        }
    }
    return( adata[0] - DataSelectorBase ); // return address of memory block
}

/*
 * __DPMIFree - free a block of memory allocated by __DPMIAlloc 17-jan-95
 */
WORD FAR PASCAL __DPMIFree( DWORD addr )
{
    memblk      *p;
    memblk      *prev;

    addr += DataSelectorBase;           // add base address
    prev = NULL;
    for( p = MemBlkList; p != NULL; p = p->next ) {
        if( p->addr == addr ) {
            DPMIFreeMemoryBlock( p->handle );
            if( prev == NULL ) {
                MemBlkList = p->next;
            } else {
                prev->next = p->next;
            }
            LocalFree( (HLOCAL)p );
            return( 0 );                // indicate success
        }
        prev = p;
    }
    return( -1 );                       // indicate error
}

void FreeDPMIMemBlocks( void )
{
    memblk      *p;

    for(;;) {
        p = MemBlkList;
        if( p == NULL ) break;
        MemBlkList = p->next;
        DPMIFreeMemoryBlock( p->handle );
        LocalFree( (HLOCAL)p );
    }
}

/*
 * GetDataSelectorInfo - collect data about current 32-bit data segment
 */
void GetDataSelectorInfo( void )
{
    DataSelectorBase = DPMIGetSegmentBaseAddress( DataSelector );

} /* GetDataSelectorInfo */

/*
 * InitSelectorCache - allocate the selector cache
 */
int InitSelectorCache( void )
{
    long        rc;
    int         i;
    WORD        sel;

    rc = DPMIAllocateLDTDescriptors( MAX_CACHE + 2 );
    if( rc < 0L ) {
        return( rc );
    }
    firstCacheSel = (WORD) rc;
    sel = (WORD) rc;
    for( i=0; i < MAX_CACHE + 2; i++ ) {
        if( i < MAX_CACHE ) {
            aliasCache[i].sel = sel;
            aliasCache[i].limit = 0xFFFF;
            aliasCache[i].base = 0L;
            aliasCache[i].in_use = FALSE;
            lastCacheSel = sel;
        }
        DPMISetDescriptorAccessRights( sel, DPL+ACCESS_DATA16 );
        DPMISetSegmentLimit( sel, 0xFFFF );
        sel += hugeIncrement;
    }
    StackCacheSel = lastCacheSel + hugeIncrement;
    Int21Selector = StackCacheSel + hugeIncrement;
    StackBase = 0;
    if( SaveSP > 0x10000 ) {
        StackBase = SaveSP - 0x10000;
    }
    StackBase_64K = SaveSP;
    DPMISetSegmentBaseAddress( StackCacheSel, DataSelectorBase + StackBase );
    return( 0 );

} /* InitSelectorCache */

/*
 * FiniSelectorCache - clean up the selector cache
 */
void FiniSelectorCache( void )
{
    int i;

    for( i=0;i< MAX_CACHE; i++ ) {
        if( aliasCache[i].sel != NULL ) {
            DPMIFreeLDTDescriptor( aliasCache[i].sel );
        }
    }
    DPMIFreeLDTDescriptor( StackCacheSel );
    DPMIFreeLDTDescriptor( Int21Selector );             // 20-sep-94

} /* FiniSelectorCache */


/*
 * FiniSelList - free selector list array
 */
void FiniSelList( void )
{
    int         i;
    int         j;
    WORD        sel;
    unsigned char mask;

    i = currSelCount;
    j = 0;
    while( i > 0 ) {
        if( SelBitArray[j] != 0 ) {
            mask = SelBitArray[j];
            sel = (j << (3+3)) | (firstCacheSel & 7);
            while( mask != 0 ) {
                if( mask & 1 ) {
                    DPMIFreeLDTDescriptor( sel );
                    --i;
                    if( i == 0 ) return;
                }
                sel += 8;
                mask = mask >> 1;
            }
        }
        ++j;
    }
} /* FiniSelList */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?