⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dmatrans.cpp

📁 我自己编译的armv4i wince60模拟器的bps源文件,已经验证可以使用,欢迎下载
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    
    Writes indicated number of bytes to DMA device, up to a
    maximum of 4K. (The DMATransport device transmits data in 4K
    chunks. We leave it up to the client of this driver to handle
    breaking up packets.)
    
    Returns failure, or the number of bytes actually written.
------------------------------------------------------------------*/

DWORD
DMA_Write( DWORD    channel,    // In: channel number: 4-7
           LPCVOID	writeBytes,	// In: Data to write
           DWORD	numBytes	// In: number of bytes to write
                                )
{   
    DWORD bytesWritten = 0;

    // Enter critical section so no other write call can interfere
    EnterCriticalSection( &writeMutex );
    // Security:  try/except is used to ensure that readMutex doesn't remain locked if the buffer
    //            memory becomes inaccessible during the read operation.
    __try  
    {
        DWORD index = 0;

        if (channel < VIRTUAL_BASE )
        {
            index = channel - NUM_DMA_FIRST_CHANNEL; // offset channel to match array indices
        }
        else
        {
            WRITE_PORT_ULONG( DMA_V_CHANNEL_WRITE, channel );
        }

        vOutputPB->ioStatus		= 0;
        vOutputPB->ioDataPtr	= (ULONG)outputBuffer; // specify physical address
        
        if ( numBytes > DMA_PACKET_SIZE )	// Trying to write too many bytes, can only write at the max DMA_PACKET_SIZE
        {
            vOutputPB->ioDataLength = DMA_PACKET_SIZE;
        }
        else	// Writing numBytes
        {
            vOutputPB->ioDataLength = numBytes;
        }
        
        memcpy( vOutputBuffer, (PUCHAR)writeBytes, vOutputPB->ioDataLength );
        
        // Write physical address to port to trigger an actual write
        WRITE_PORT_ULONG( DMA_IO_OUTPUT_REG(index), ( ULONG )outputPB );
        
        bytesWritten = vOutputPB->ioDataLength;

        if ( vOutputPB->ioStatus != 0 )	// Error, return failure
        {
            DEBUGMSG( TRUE, (TEXT("DMA Transport:WRITE failed on channel %x with code %x\n"), channel, vOutputPB->ioStatus) );
            if (channel >= VIRTUAL_BASE )
            {
                // Propagate the error code
                SetLastError(vOutputPB->ioStatus);
            }
            bytesWritten = -1;
        }
        
        if (channel >= VIRTUAL_BASE )
        {
            WRITE_PORT_ULONG( DMA_V_CHANNEL_WRITE, 0 );
        }
    } 
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        bytesWritten = -1;
    }

    LeaveCriticalSection( &writeMutex );
    
    return bytesWritten;
}


/*------------------------------------------------------------------
    DMA_Read
    
    Reads packets from device. Can only read 4 KB chunks, will
    fail if another value is specified. (The DMATransport device
    transmits data in 4K chunks. We leave it up to the client
    of this driver to handle breaking up packets.)
------------------------------------------------------------------*/

DWORD
DMA_Read( DWORD     channel,    // In: Channel number
          LPVOID	buffer,		// In\Out: buffer to read data into
          DWORD		numRead		// In: Number of bytes to read into buffer
                            )
{
    DWORD bytesRead = 0;

    if ( numRead != DMA_PACKET_SIZE )	// can only read 4KB chunks
    {
        return -1;
    }

    EnterCriticalSection( &readMutex );

    // Security:  try/except is used to ensure that readMutex doesn't remain locked if the buffer
    //            memory becomes inaccessible during the read operation.
    __try  
    {
        DWORD index = 0;

        if (channel < VIRTUAL_BASE )
        {
            index = channel - NUM_DMA_FIRST_CHANNEL; // offset channel to match array indices
        }
        else
        {
            WRITE_PORT_ULONG( DMA_V_CHANNEL_READ, channel );
        }

        vInputPB->ioDataLength	= DMA_PACKET_SIZE;
        vInputPB->ioDataPtr		= (ULONG)inputBuffer; //  specify physical address
        vInputPB->ioStatus		= -1;

        if ( channel < VIRTUAL_BASE  && (*(channels[index].vPFlags) & kDMATransportDataReady) ||
             channel >= VIRTUAL_BASE && (*DMA_V_CHANNEL_READ & kDMATransportDataReady) )
        {
            WRITE_PORT_ULONG((PULONG)DMA_IO_INPUT_REG( index ), ( ULONG )inputPB);
            
            // Data and no error
            if( vInputPB->ioDataLength != 0 && vInputPB->ioStatus == 0 )
            {
                // now copy that many bytes into output buffer.
                memcpy(buffer, vInputBuffer, vInputPB->ioDataLength );
            }
            else	// error
            {
                DEBUGMSG( TRUE, (TEXT("DMA Transport:READ FAILED on channel %x\n"), channel) );
                vInputPB->ioDataLength = -1;		// 0 indicates error
            }
        }
        else
        {
            vInputPB->ioDataLength = 0;	// Nothing to read, 0 indicates end of file
        }

        bytesRead = vInputPB->ioDataLength;

        if (channel >= VIRTUAL_BASE )
        {
            WRITE_PORT_ULONG( DMA_V_CHANNEL_READ, 0 );
        }
    } 
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        bytesRead = -1;
    }

    LeaveCriticalSection( &readMutex );

    return bytesRead;
}


/*------------------------------------------------------------------
    DMA_IOControl
    
    Standard stream interface IOControl function. Does nothing here.
------------------------------------------------------------------*/

extern "C" BOOL
DMA_IOControl( DWORD channel,       // In: channel number
               DWORD code,			// In: Holds the requested operation
               PBYTE inBuf,			// In: Buffer being passed in
               DWORD inLength,		// In: Length of the inBuf
               PBYTE outBuf,		// Out: Data sent from driver to application
               DWORD outLength,		// Out: length of the outBuf
               PDWORD actualOut		// Out: actual number of bytes received
                                    )
{
    BOOL bRet = FALSE;

    if ( code == IOCTL_GET_DMA_CHANNEL_INFO ) 
    {
        *actualOut = 0;
        // Verify arguments
        if (channel < VIRTUAL_BASE )
        {
            DEBUGMSG( TRUE, (TEXT("DMA Transport:FAILED IOCTL for channel %x - invalid channel number\n"), channel) );
            return FALSE;
        }
        if (outBuf == NULL || outLength < 8)
        {
            DEBUGMSG( TRUE, (TEXT("DMA Transport:FAILED IOCTL for channel %x - invalid buffer arguments\n"), channel) );
            return FALSE;
        }

        EnterCriticalSection( &vchannelAccess );
        // Security:  try/except is used to ensure that vchannelAccess doesn't remain locked if the buffer
        //            memory becomes inaccessible during the read operation.
        __try 
        {
            // Retrieve the channel
            DMAChannel * channelObj = getVirtualChannel(channel);
            if (channelObj == NULL)
            {
                DEBUGMSG( TRUE, (TEXT("DMA Transport:FAILED IOCTL for channel %x - couldn't find the channel\n"), channel) );
            }
            else
            {
                if (!DuplicateHandle( GetCurrentProcess(), 
                                      channelObj->dataReadyEvent, 
                                      GetOwnerProcess(),
                                      (void **)&outBuf[4],
                                      0,
                                      FALSE,
                                      DUPLICATE_SAME_ACCESS ))
                {
                    DEBUGMSG( TRUE, (TEXT("DMA Transport:Couldn't duplicate event handle. Last Error %x\n"), GetLastError()) );
                }
                else 
                {
                    // Write out the channel number
                    *((DWORD *)outBuf) = channel;
                    *actualOut = 8;
                    bRet = TRUE;
                }
            }
        }
        __except(EXCEPTION_EXECUTE_HANDLER)
        {
            // Nothing needs to be done here - bRet is FALSE already
        }

        LeaveCriticalSection( &vchannelAccess );

        return bRet;
    }
    else if ( code == IOCTL_GET_DMA_CHANNEL_CONNECTED )
    {
        *actualOut = 0;
        // Verify arguments
        if (channel < VIRTUAL_BASE )
        {
            DEBUGMSG( TRUE, (TEXT("DMA Transport:FAILED IOCTL for channel %x - invalid channel number\n"), channel) );
            return FALSE;
        }
        if ( outBuf == NULL || outLength < 4)
        {
            DEBUGMSG( TRUE, (TEXT("DMA Transport:FAILED IOCTL for channel %x - invalid buffer arguments\n"), channel) );
            return FALSE;
        }

        EnterCriticalSection( &vchannelAccess );
        // Security:  try/except is used to ensure that vchannelAccess doesn't remain locked if the buffer
        //            memory becomes inaccessible during the read operation.
        __try 
        {
            // Retrieve the channel
            DMAChannel * channelObj = getVirtualChannel(channel);
            if (channelObj == NULL)
            {
                DEBUGMSG( TRUE, (TEXT("DMA Transport:FAILED IOCTL for channel %x - couldn't find the channel\n"), channel) );
            }
            else
            {
                // Get the channel status from the emulator
                WRITE_PORT_ULONG(DMA_CURR_V_CHANNEL, channel);
                WRITE_PORT_ULONG(DMA_CURR_V_OPERATION, kDMAVirtOpetationIsInUse);

                *((DWORD *)outBuf) = *DMA_CURR_V_STATUS;
                *actualOut = 4;
                bRet = TRUE;
            }
        }
        __except(EXCEPTION_EXECUTE_HANDLER)
        {
            // Nothing needs to be done here - bRet is FALSE already
        }

        LeaveCriticalSection( &vchannelAccess );
    }
    return bRet;
}


/*------------------------------------------------------------------
    DMA_PowerUp
    
    Standard stream interface PowerUp function. Does nothing here.
------------------------------------------------------------------*/

extern "C" void
DMA_PowerUp( DWORD hContext )
{   
    // do nothing
}


/*------------------------------------------------------------------
    DMA_PowerDown
    
    Standard stream interface PowerDown function. Does nothing here.
------------------------------------------------------------------*/
extern "C" void
DMA_PowerDown( DWORD hContext )
{
    // do nothing
}


/*------------------------------------------------------------------
    DMA_Seek
    
    Standard stream interface seek function. Does nothing here.
------------------------------------------------------------------*/

extern "C" DWORD
DMA_Seek( DWORD hOpenContext, 
          long Amount, 
          WORD Type )
{
    // Do nothing, return fail
    return -1;
}

DMAChannel * getVirtualChannel(DWORD channelNumber)
{
    DMAChannel * currChannel = virtChannels;
    while (currChannel != NULL )
    {
        if ( currChannel->channelNumber == channelNumber)
        {
           return currChannel;
        }
        currChannel = currChannel->next;
    }
    // Failed to find the channel
    return NULL;
}

DMAChannel * addVirtualChannel(DWORD channelNumber)
{
    DMAChannel * currChannel = virtChannels;
    DMAChannel * newChannel = new DMAChannel();

    if ( newChannel == NULL )
        return NULL;

    while (currChannel != NULL && currChannel->next != NULL)
    {
        currChannel = currChannel->next;
    }

    if ( currChannel != NULL )
        currChannel->next = newChannel;
    else
        virtChannels = newChannel;

    newChannel->channelNumber = channelNumber;
    return newChannel;
}

void deleteVirtualChannel(DMAChannel * channel)
{
    DMAChannel * currChannel = virtChannels;

    if ( channel == NULL )
        return;

    // Check with the head of the list
    if (channel == virtChannels)
    {
        virtChannels = virtChannels->next;
        delete channel;
        return;
    }

    // Check the body of the list
    while (currChannel != NULL && currChannel->next != channel)
    {
        currChannel = currChannel->next;
    }

    // If found in the body - relink around it.
    if (currChannel != NULL )
    {
        currChannel->next = currChannel->next->next;
        delete channel;
    }
}

⌨️ 快捷键说明

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