/*++
*******************************************************************************
* Copyright (c) 1990-98 Digi International Inc., All Rights Reserved          *
*                                                                             *
* This software contains proprietary and confidential information of Digi     *
* International Inc.  By accepting transfer of this copy, Recipient agrees    *
* to retain this software in confidence, to prevent disclosure to others,     *
* and to make no use of this software other than that for which it was        *
* delivered.  This is an unpublished copyrighted work of Digi International   *
* Inc.  Except as permitted by federal law, 17 USC 117, copying is strictly   *
* prohibited.                                                                 *
*                                                                             *
* Restricted Rights Legend                                                    *
*                                                                             *
* Use, duplication, or disclosure by the Government is subject to             *
* restrictions set forth in sub-paragraph (c)(1)(ii) of The Rights in         *
* Technical Data and Computer Software clause at DFARS 252.227-7031 or        *
* subparagraphs (c)(1) and (2) of the Commercial Computer Software -          *
* Restricted Rights at 48 CFR 52.227-19, as applicable.                       *
*                                                                             *
* Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343          *
*                                                                             *
*******************************************************************************

Module Name:

   dxbslave.c

Abstract:

   Routines to access adapter memory in slave mode (i.e. direct reads and writes to 
   adapter shared memory).  The adapter extension contains a table of function 
   pointers for read/write routines which are setup using the initialization 
        routines below.  Supports both windowed and flat memory adapters.
   
   These routines abstract the windowed nature of ISA adapters, presenting all 
   adapters as if shared memory were flat, like that of PCI adapters.

Author:

   Michael Zarns

--*/

#include "digidxb.h"

NTSTATUS 
dxbMapMemory( 
        IN PDIGI_IO_RESOURCE    pResource,
        IN OUT PDXB_IO_RESOURCE pDxbMem )
/*++

Description:

        Map in a single memory resource described by pResource.  Initialize the 
        DXB_IO_RESOURCE struct as appropriate for the mapped memory block.

Parameters:

        pResources
                Digi resource list defining PCI assigned resources for this adapter.

        pDxbMem
                Dxb resource descriptor struct in the device extension to hold the addresses
                and length for this memory block.

Return Value:

        STATUS_SUCCESS or failure status.

--*/
{
    NTSTATUS Status = STATUS_SUCCESS;
    PVOID pVirtual;

    // Default to FALSE.  Only set fUnmap to TRUE if we called MmMapIoSpace and 
    // successfully got an address!
    pDxbMem->fUnmap = FALSE;

    if ( pResource->AddressSpace == 0 )
    {
        pVirtual = MmMapIoSpace( pResource->BaseAddressTranslated, pResource->Length, FALSE );
        if ( pVirtual )
            pDxbMem->fUnmap = TRUE;
    } 
    else
        pVirtual = (PVOID)pResource->BaseAddressTranslated.LowPart;

    if ( pVirtual )
    {
        pDxbMem->Physical = pResource->BaseAddress;
        pDxbMem->Length   = pDxbMem->cbWindow = pResource->Length;
        pDxbMem->Virtual  = pVirtual;
    }
    else
    {
        pDxbMem->fUnmap = FALSE;
        Status = STATUS_UNSUCCESSFUL;
    }
    return Status;
}


STATIC INLINE VOID
dxbSlaveWriteFlat(
        PDXB_DEVICE_EXTENSION pExt,
        VOID const * const    pBuf,
        ULONG const           AdapterOffset,
        ULONG const           cbWrite )
/*++

Description:

        Writes data to adapter assuming flat memory structure (i.e. no windowing) like 
        that on a PCI adapter.

Parameters:

        pExt
                The device extension defining the adapter

        pBuf
                The data to be written to the adapter

        AdapterOffset
                Offset into adapter memory at which to start writing

        cbWrite
                Count of bytes to write

Return Value:

        None

--*/
{
    CHAR const * pIn = pBuf;
    CHAR * const pStart = (PCHAR)pExt->Hardware.Memory.Virtual + AdapterOffset;
    PCHAR pOut = pStart;
    ULONG cb = cbWrite;

    ASSERT( pExt->Hardware.Memory.Virtual != NULL);
    ASSERT( AdapterOffset + cb <= pExt->Hardware.Memory.Length );
    ASSERT( cb != 0 );

    if ( pExt->Hardware.Memory.Virtual )
    {
        // Dword-Align pOut
        if ( !IsDwordAligned( pOut ) )
        {
            if ( !IsWordAligned( pOut ) && cb >= sizeof (UCHAR) )
            {
                // Byte-aligned.  Write a byte
                WRITE_REGISTER_UCHAR( pOut, *pIn );
                pOut += sizeof (UCHAR);
                pIn  += sizeof (UCHAR);
                cb   -= sizeof (UCHAR);
            }

            // Word-aligned, could be Dword aligned.  Write a word only if !dword-aligned.
            if ( !IsDwordAligned( pOut ) && cb >= sizeof (USHORT) )
            {
                WRITE_REGISTER_USHORT( (PVOID)pOut, *(PUSHORT)pIn );
                pOut += sizeof (USHORT);
                pIn  += sizeof (USHORT);
                cb   -= sizeof (USHORT);
            }
        }

        // Write Dwords, as many as possible
        {
            ULONG nWrite = cb / sizeof (ULONG);
            if ( nWrite )
            {
                WRITE_REGISTER_BUFFER_ULONG( (PVOID)pOut, (PVOID)pIn, nWrite );
                pOut += nWrite * sizeof (ULONG);
                pIn  += nWrite * sizeof (ULONG);
                cb   -= nWrite * sizeof (ULONG);
            }
        }

        // Write remaining bytes
        switch ( cb )
        {
        case 0:
            break;

        case sizeof (USHORT):
            WRITE_REGISTER_USHORT( (PVOID)pOut, *(PUSHORT)pIn );
            pIn  += sizeof (USHORT);
            pOut += sizeof (USHORT);
            cb   -= sizeof (USHORT);
            break;

        default:
            WRITE_REGISTER_BUFFER_UCHAR( (PVOID)pOut, (PVOID)pIn, cb );
            pOut += cb;
            pIn  += cb;
            cb   -= cb;
            break;
        }

        ASSERT( pOut == pStart + cbWrite );
        ASSERT( pIn  == (PCHAR)pBuf + cbWrite );
        ASSERT( cb == 0 );
    }
}


STATIC INLINE VOID
dxbSlaveWriteDwordFlat(
        PDXB_DEVICE_EXTENSION pExt,
        ULONG                 Offset,
        ULONG                 Data )
/*++

Description:

        Write a dword to adapter assuming flat memory structure (i.e. no windowing) like 
        that on a PCI adapter.

Parameters:

        pExt
                The device extension defining the adapter

        Offset
                Offset into adapter memory at which to start writing

        Data
                Data to write

Return Value:

        None

--*/
{
    ASSERT( pExt->Hardware.Memory.Virtual != NULL );
    ASSERT( Offset + sizeof Data <= pExt->Hardware.Memory.Length );
    if ( pExt->Hardware.Memory.Virtual )
        WRITE_REGISTER_ULONG( (PVOID)( (PUCHAR)pExt->Hardware.Memory.Virtual + Offset ), Data );
}


STATIC INLINE VOID
dxbSlaveWriteWordFlat(
        PDXB_DEVICE_EXTENSION pExt,
        ULONG                 Offset,
        USHORT                Data )
/*++

Description:

        Write a word to adapter assuming flat memory structure (i.e. no windowing) like 
        that on a PCI adapter.

Parameters:

        pExt
                The device extension defining the adapter

        Offset
                Offset into adapter memory at which to start writing

        Data
                Data to write

Return Value:

        None

--*/
{
    ASSERT( pExt->Hardware.Memory.Virtual != NULL );
    ASSERT( Offset + sizeof Data <= pExt->Hardware.Memory.Length );
    if ( pExt->Hardware.Memory.Virtual )
        WRITE_REGISTER_USHORT( (PVOID)( (PUCHAR)pExt->Hardware.Memory.Virtual + Offset ), Data );
}


STATIC INLINE VOID
dxbSlaveWriteByteFlat(
        PDXB_DEVICE_EXTENSION pExt,
        ULONG                 Offset,
        UCHAR                 Data )
/*++

Description:

        Write a byte to adapter assuming flat memory structure (i.e. no windowing) like 
        that on a PCI adapter.

Parameters:

        pExt
                The device extension defining the adapter

        Offset
                Offset into adapter memory at which to start writing

        Data
                Data to write

Return Value:

        None

--*/
{
    ASSERT( pExt->Hardware.Memory.Virtual != NULL );
    ASSERT( Offset + sizeof Data <= pExt->Hardware.Memory.Length );
    if ( pExt->Hardware.Memory.Virtual )
        WRITE_REGISTER_UCHAR( (PUCHAR)pExt->Hardware.Memory.Virtual + Offset, Data );
}


STATIC VOID
dxbSlaveWriteWindowed(
        PDXB_DEVICE_EXTENSION pExt,
        VOID CONST            *pBuf,
        ULONG                 AdapterOffset,
        ULONG                 cb )
/*++

Description:

        Writes data to adapter assuming windowed memory structure like that on a ISA or 
        MCA adapter.

Parameters:

        pExt
                The device extension defining the adapter

        pBuf
                The data to be written to the adapter

        AdapterOffset
                Offset into adapter memory at which to start writing

        cb
                Count of bytes to write

Return Value:

        None

--*/
{
    ASSERT( pExt->Hardware.Memory.Virtual != NULL );
    if ( pExt->Hardware.Memory.Virtual )
    {
        ULONG Window = AdapterOffset / pExt->Hardware.Memory.cbWindow;
        ULONG Offset = AdapterOffset % pExt->Hardware.Memory.cbWindow;
        ULONG cbLeft = cb;
        UCHAR CONST *pSrc = pBuf;

        while ( cbLeft != 0 )
        {
            ULONG cbCurrent = Offset + cbLeft <= pExt->Hardware.Memory.cbWindow ? 
                cbLeft : pExt->Hardware.Memory.cbWindow - Offset;
            ASSERT( Window < MAXUSHORT );
            DxbEnableWindow( pExt, (USHORT)Window );
            dxbSlaveWriteFlat( pExt, pSrc, Offset, cbCurrent );
            DxbDisableWindow( pExt );

            // Prepare for next iteration 
            cbLeft -= cbCurrent;
            pSrc   += cbCurrent;
            Offset = 0;
            Window++;
        }
        ASSERT( pSrc == (PUCHAR)pBuf + cb );
    }
}


STATIC VOID
dxbSlaveWriteDwordWindowed(
        PDXB_DEVICE_EXTENSION pExt,
        ULONG                 AdapterOffset,
        ULONG                 Data )
/*++

Description:

        Writes data to adapter assuming windowed memory structure like that on a ISA or 
        MCA adapter.

Parameters:

        pExt
                The device extension defining the adapter

        AdapterOffset
                Offset into adapter memory at which to start writing

        Data
                Data to write

Return Value:

        None

--*/
{
    ASSERT( pExt->Hardware.Memory.Virtual != NULL );
    if ( pExt->Hardware.Memory.Virtual )
    {
        ULONG Window = AdapterOffset / pExt->Hardware.Memory.cbWindow;
        ULONG Offset = AdapterOffset % pExt->Hardware.Memory.cbWindow;

        ASSERT( Offset == dxbAlign32( Offset ) );
        ASSERT( Offset + sizeof Data <= pExt->Hardware.Memory.Length );

        DxbEnableWindow( pExt, (USHORT)Window );
        WRITE_REGISTER_ULONG( (PVOID)( (PUCHAR)pExt->Hardware.Memory.Virtual + Offset ), Data );
        DxbDisableWindow( pExt );
    }
}


STATIC VOID
dxbSlaveWriteWordWindowed(
        PDXB_DEVICE_EXTENSION pExt,
        ULONG                 AdapterOffset,
        USHORT                Data )
/*++

Description:

        Writes data to adapter assuming windowed memory structure like that on a ISA or 
        MCA adapter.

Parameters:

        pExt
                The device extension defining the adapter

        AdapterOffset
                Offset into adapter memory at which to start writing

        Data
                Data to write

Return Value:

        None

--*/
{
    ASSERT( pExt->Hardware.Memory.Virtual != NULL );
    if ( pExt->Hardware.Memory.Virtual )
    {
        ULONG Window = AdapterOffset / pExt->Hardware.Memory.cbWindow;
        ULONG Offset = AdapterOffset % pExt->Hardware.Memory.cbWindow;

        ASSERT( Offset == dxbAlign16( Offset ) );
        ASSERT( Offset + sizeof Data <= pExt->Hardware.Memory.Length );

        DxbEnableWindow( pExt, (USHORT)Window );
        WRITE_REGISTER_USHORT( (PVOID)( (PUCHAR)pExt->Hardware.Memory.Virtual + Offset ), Data );
        DxbDisableWindow( pExt );
    }
}


STATIC VOID
dxbSlaveWriteByteWindowed(
        PDXB_DEVICE_EXTENSION pExt,
        ULONG                 AdapterOffset,
        UCHAR                 Data )
/*++

Description:

        Writes data to adapter assuming windowed memory structure like that on a ISA or 
        MCA adapter.

Parameters:

        pExt
                The device extension defining the adapter

        AdapterOffset
                Offset into adapter memory at which to start writing

        Data
                Data to write

Return Value:

        None

--*/
{
    ASSERT( pExt->Hardware.Memory.Virtual != NULL );
    if ( pExt->Hardware.Memory.Virtual )
    {
        ULONG Window = AdapterOffset / pExt->Hardware.Memory.cbWindow;
        ULONG Offset = AdapterOffset % pExt->Hardware.Memory.cbWindow;

        ASSERT( Offset + sizeof Data <= pExt->Hardware.Memory.Length );

        DxbEnableWindow( pExt, (USHORT)Window );
        WRITE_REGISTER_UCHAR( (PUCHAR)pExt->Hardware.Memory.Virtual + Offset, Data );
        DxbDisableWindow( pExt );
    }
}


STATIC INLINE VOID
dxbSlaveReadFlat(
        PDXB_DEVICE_EXTENSION pExt,
        PVOID const           pBuf,
        ULONG const           AdapterOffset,
        ULONG const           cbRead )
/*++

Description:

        Read data from an adapter assuming flat memory structure (i.e. no windowing) like 
        that on a PCI adapter.

Parameters:

        pExt
                The device extension defining the adapter

        pBuf
                Buffer into which data should be copied

        Offset
                Offset into adapter memory window at which to start reading

        cb
                Count of bytes to read

Return Value:

        None

--*/
{
    ASSERT( pExt->Hardware.Memory.Virtual != NULL );
    if ( pExt->Hardware.Memory.Virtual )
    {
        CHAR const * const pStart = (PCHAR)pExt->Hardware.Memory.Virtual + AdapterOffset;
        CHAR const * pIn = pStart;
        CHAR * pOut = pBuf;
        ULONG cb = cbRead;

        ASSERT( AdapterOffset + cb <= pExt->Hardware.Memory.Length );
        ASSERT( cb != 0 );

        // Dword-Align pIn
        if ( !IsDwordAligned( pIn ) )
        {
            if ( !IsWordAligned( pIn ) && cb >= sizeof (UCHAR) )
            {
                // Byte-aligned.  Read a byte
                *pOut = READ_REGISTER_UCHAR( (PVOID)pIn );
                pOut++;
                pIn++;
                cb--;
            }

            // Word-aligned.  Read a word
            if ( !IsDwordAligned( pIn ) && cb >= sizeof (USHORT) )
            {
                *(PUSHORT)pOut = READ_REGISTER_USHORT( (PVOID)pIn );
                pOut += sizeof (USHORT);
                pIn  += sizeof (USHORT);
                cb   -= sizeof (USHORT);
            }
        }

        // Read Dwords, as many as possible
        {
            ULONG nRead = cb / sizeof (ULONG);
            if ( nRead )
            {
                READ_REGISTER_BUFFER_ULONG( (PVOID)pIn, (PVOID)pOut, nRead );
                pOut += nRead * sizeof (ULONG);
                pIn  += nRead * sizeof (ULONG);
                cb   -= nRead * sizeof (ULONG);
            }
        }

        // Read remaining bytes
        switch ( cb )
        {
        case 0:
            break;

        case sizeof (USHORT):
            *(PUSHORT)pOut = READ_REGISTER_USHORT( (PVOID)pIn );
            pIn  += sizeof (USHORT);
            pOut += sizeof (USHORT);
            cb   -= sizeof (USHORT);
            break;

        default:
            READ_REGISTER_BUFFER_UCHAR( (PVOID)pIn, (PVOID)pOut, cb );
            pOut += cb;
            pIn  += cb;
            cb   -= cb;
            break;
        }

        ASSERT( pIn == pStart + cbRead );
        ASSERT( pOut == (PCHAR)pBuf + cbRead );
        ASSERT( cb == 0 );
    }
    else
        RtlFillMemory(pBuf,cbRead,0xff);
}


STATIC INLINE ULONG
dxbSlaveReadDwordFlat(
        PDXB_DEVICE_EXTENSION pExt,
        ULONG                 Offset )
/*++

Description:

        Read data from an adapter assuming flat memory structure (i.e. no windowing) like 
        that on a PCI adapter.

Parameters:

        pExt
                The device extension defining the adapter

        Offset
                Offset into adapter memory window at which to start reading

Return Value:

        Data read from adapter

--*/
{
    ASSERT( pExt->Hardware.Memory.Virtual != NULL );
    if ( pExt->Hardware.Memory.Virtual )
    {
        ASSERT( Offset == dxbAlign32( Offset ) );
        ASSERT( Offset + sizeof (ULONG) <= pExt->Hardware.Memory.Length );
        return READ_REGISTER_ULONG( (PVOID)( (PUCHAR)pExt->Hardware.Memory.Virtual + Offset ) );
    }
    else
        return 0xffffffff;
}


STATIC INLINE USHORT
dxbSlaveReadWordFlat(
        PDXB_DEVICE_EXTENSION pExt,
        ULONG                 Offset )
/*++

Description:

        Read data from an adapter assuming flat memory structure (i.e. no windowing) like 
        that on a PCI adapter.

Parameters:

        pExt
                The device extension defining the adapter

        Offset
                Offset into adapter memory window at which to start reading

Return Value:

        Data read from adapter

--*/
{
    ASSERT( pExt->Hardware.Memory.Virtual != NULL );
    if ( pExt->Hardware.Memory.Virtual )
    {
        ASSERT( Offset == dxbAlign16( Offset ) );
        ASSERT( Offset + sizeof (USHORT) <= pExt->Hardware.Memory.Length );
        return READ_REGISTER_USHORT( (PVOID)( (PUCHAR)pExt->Hardware.Memory.Virtual + Offset ) );
    }
    else
        return 0xffff;
}


STATIC INLINE UCHAR
dxbSlaveReadByteFlat(
        PDXB_DEVICE_EXTENSION pExt,
        ULONG                 Offset )
/*++

Description:

        Read data from an adapter assuming flat memory structure (i.e. no windowing) like 
        that on a PCI adapter.

Parameters:

        pExt
                The device extension defining the adapter

        Offset
                Offset into adapter memory window at which to start reading

Return Value:

        Data read from adapter

--*/
{
    ASSERT( pExt->Hardware.Memory.Virtual != NULL );
    if ( pExt->Hardware.Memory.Virtual )
    {
        ASSERT( Offset + sizeof (UCHAR) <= pExt->Hardware.Memory.Length );
        return READ_REGISTER_UCHAR( (PUCHAR)pExt->Hardware.Memory.Virtual + Offset );
    }
    else
        return 0xff;
}


STATIC VOID
dxbSlaveReadWindowed(
        PDXB_DEVICE_EXTENSION pExt,
        PVOID                 pBuf,
        ULONG                 AdapterOffset,
        ULONG                 cb )
/*++

Description:

        Read data from an adapter assuming windowed memory structure like that on a ISA or 
        MCA adapter.

Parameters:

        pExt
                The device extension defining the adapter

        pBuf
                Buffer into which data should be copied

        AdapterOffset
                Offset into adapter memory at which to start read

        cb
                Count of bytes to read

Return Value:

        None

--*/
{
    ASSERT( pExt->Hardware.Memory.Virtual != NULL );
    if ( pExt->Hardware.Memory.Virtual )
    {
        ULONG Window = AdapterOffset / pExt->Hardware.Memory.cbWindow;
        ULONG Offset = AdapterOffset % pExt->Hardware.Memory.cbWindow;
        ULONG cbLeft = cb;
        PUCHAR pDest = pBuf;

        while ( cbLeft != 0 )
        {
            ULONG cbCurrent = Offset + cbLeft <= pExt->Hardware.Memory.cbWindow ? 
                cbLeft : pExt->Hardware.Memory.cbWindow - Offset;
            ASSERT( Window < MAXUSHORT );
            DxbEnableWindow( pExt, (USHORT)Window );
            dxbSlaveReadFlat( pExt, pDest, Offset, cbCurrent );
            DxbDisableWindow( pExt );

            // Prepare for next iteration 
            cbLeft -= cbCurrent;
            pDest  += cbCurrent;
            Offset = 0;
            Window++;
        }
        ASSERT( pDest == (PUCHAR)pBuf + cb );
    }
    else
        RtlFillMemory(pBuf,cb,0xff);
}


STATIC ULONG
dxbSlaveReadDwordWindowed(
        PDXB_DEVICE_EXTENSION pExt,
        ULONG                 AdapterOffset )
/*++

Description:

        Reads data from the adapter assuming windowed memory structure like that on a ISA or
        MCA adapter.

Parameters:

        pExt
                The device extension defining the adapter

        AdapterOffset
                Offset into adapter memory at which to start writing

Return Value:

        Data read from adapter.

--*/
{
    ULONG Data;

    ASSERT( pExt->Hardware.Memory.Virtual != NULL );
    if ( pExt->Hardware.Memory.Virtual )
    {
        ULONG Window = AdapterOffset / pExt->Hardware.Memory.cbWindow;
        ULONG Offset = AdapterOffset % pExt->Hardware.Memory.cbWindow;

        ASSERT( Offset == dxbAlign32( Offset ) );
        ASSERT( Offset + sizeof Data <= pExt->Hardware.Memory.Length );

        DxbEnableWindow( pExt, (USHORT)Window );
        Data = READ_REGISTER_ULONG( (PVOID)( (PUCHAR)pExt->Hardware.Memory.Virtual + Offset ) );
        DxbDisableWindow( pExt );
    }
    else
        Data = 0xffffffff;

    return Data;
}


STATIC USHORT
dxbSlaveReadWordWindowed(
        PDXB_DEVICE_EXTENSION pExt,
        ULONG                 AdapterOffset )
/*++

Description:

        Reads data from the adapter assuming windowed memory structure like that on a ISA or
        MCA adapter.

Parameters:

        pExt
                The device extension defining the adapter

        AdapterOffset
                Offset into adapter memory at which to start writing

Return Value:

        Data read from adapter.

--*/
{
    USHORT Data;

    ASSERT( pExt->Hardware.Memory.Virtual != NULL );
    if ( pExt->Hardware.Memory.Virtual )
    {
        ULONG Window = AdapterOffset / pExt->Hardware.Memory.cbWindow;
        ULONG Offset = AdapterOffset % pExt->Hardware.Memory.cbWindow;

        ASSERT( Offset == dxbAlign16( Offset ) );
        ASSERT( Offset + sizeof Data <= pExt->Hardware.Memory.Length );

        DxbEnableWindow( pExt, (USHORT)Window );
        Data = READ_REGISTER_USHORT( (PVOID)( (PUCHAR)pExt->Hardware.Memory.Virtual + Offset ) );
        DxbDisableWindow( pExt );
    }
    else
        Data = 0xffff;

    return Data;
}


STATIC UCHAR
dxbSlaveReadByteWindowed(
        PDXB_DEVICE_EXTENSION pExt,
        ULONG                 AdapterOffset )
/*++

Description:

        Reads data from the adapter assuming windowed memory structure like that on a ISA or
        MCA adapter.

Parameters:

        pExt
                The device extension defining the adapter

        AdapterOffset
                Offset into adapter memory at which to start writing

Return Value:

        Data read from adapter.

--*/
{
    UCHAR Data;

    ASSERT( pExt->Hardware.Memory.Virtual != NULL );
    if ( pExt->Hardware.Memory.Virtual )
    {
        ULONG Window = AdapterOffset / pExt->Hardware.Memory.cbWindow;
        ULONG Offset = AdapterOffset % pExt->Hardware.Memory.cbWindow;

        ASSERT( Offset + sizeof Data <= pExt->Hardware.Memory.Length );

        DxbEnableWindow( pExt, (USHORT)Window );
        Data = READ_REGISTER_UCHAR( (PUCHAR)pExt->Hardware.Memory.Virtual + Offset );
        DxbDisableWindow( pExt );
    }
    else
        Data = 0xff;

    return Data;
}


VOID 
DxbSlaveSetAdapterWindowed( 
        PDXB_DEVICE_EXTENSION      pExt,
        PDXB_MEMORY_WINDOW_ENABLE  pEnable, 
        PDXB_MEMORY_WINDOW_DISABLE pDisable )
/*++

Description:

        Initialize the device extension table of function pointers for slave memory access
        for a windowed adapter.

Parameters:

        pExt
                The device extension defining the adapter

        pEnable
                Routine which should be used for enabling an adapter memory window

        pDisable
                Routine which should be used for disabling an adapter memory window

Return Value:

        None

--*/
{
    pExt->Adapter.Read  = dxbSlaveReadWindowed;
    pExt->Adapter.Write = dxbSlaveWriteWindowed;

    pExt->Adapter.ReadByte  = dxbSlaveReadByteWindowed;
    pExt->Adapter.WriteByte = dxbSlaveWriteByteWindowed;

    pExt->Adapter.ReadWord  = dxbSlaveReadWordWindowed;
    pExt->Adapter.WriteWord = dxbSlaveWriteWordWindowed;

    pExt->Adapter.ReadDword  = dxbSlaveReadDwordWindowed;
    pExt->Adapter.WriteDword = dxbSlaveWriteDwordWindowed;

    pExt->Adapter.Enable  = pEnable;
    pExt->Adapter.Disable = pDisable;
}


VOID 
DxbSlaveSetAdapterFlatMemory( 
        PDXB_DEVICE_EXTENSION pExt )
/*++

Description:

        Initialize the device extension table of function pointers for slave memory access
        for a flat memory adapter.

Parameters:

        pExt
                The device extension defining the adapter

Return Value:

        None

--*/
{
    pExt->Adapter.Read    = dxbSlaveReadFlat;
    pExt->Adapter.Write   = dxbSlaveWriteFlat;

    pExt->Adapter.ReadByte  = dxbSlaveReadByteFlat;
    pExt->Adapter.WriteByte = dxbSlaveWriteByteFlat;

    pExt->Adapter.ReadWord  = dxbSlaveReadWordFlat;
    pExt->Adapter.WriteWord = dxbSlaveWriteWordFlat;

    pExt->Adapter.ReadDword  = dxbSlaveReadDwordFlat;
    pExt->Adapter.WriteDword = dxbSlaveWriteDwordFlat;

    pExt->Adapter.Enable  = NULL;
    pExt->Adapter.Disable = NULL;
}
