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

📄 dmatrans.cpp

📁 windows mobile 5 下的底层驱动包
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    
    memcpy( vOutputBuffer, (PUCHAR)writeBytes, vOutputPB->ioDataLength );
    
    DWORD index = channel - NUM_DMA_FIRST_CHANNEL;	// offset channel to match array indices
    
    // Write physical address to port to trigger an actual write
    WRITE_PORT_ULONG( DMA_IO_OUTPUT_REG(index), ( ULONG )outputPB );
    
    if ( vOutputPB->ioStatus != 0 )	// Error, return failure
    {
        vOutputPB->ioDataLength = -1;
    }
    
    LeaveCriticalSection( &writeMutex );
    
    return vOutputPB->ioDataLength;

    }
NewWriteCode:
    // Enter critical section so no other write call can interfere
    EnterCriticalSection( &writeMutex );
    DWORD index = 0;
    DWORD bytesWritten = 0;

    if (channel < VIRTUAL_BASE )
    {
        index = channel - NUM_DMA_FIRST_CHANNEL; // offset channel to match array indices
    }
    else
    {
        DEBUGMSG( TRUE, (TEXT("DMA Transport:WRITE virtual on channel %x\n"), channel) );
        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;
    }
    
    DEBUGMSG( TRUE, (TEXT("DMA Transport:WRITE virtual %x/%x bytes on channel %x \n"), numBytes, vOutputPB->ioDataLength, channel) );
    memcpy( vOutputBuffer, (PUCHAR)writeBytes, vOutputPB->ioDataLength );
    
    DEBUGMSG( TRUE, (TEXT("DMA Transport:WRITE wrote out the data on %x \n"), channel) );
    // 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 )
    {
        DEBUGMSG( TRUE, (TEXT("DMA Transport:WRITE virtual on channel %x (Cleared W_REG)\n"), channel) );
        WRITE_PORT_ULONG( DMA_V_CHANNEL_WRITE, 0 );
    }

    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
                            )
{
    if ( channel >= VIRTUAL_BASE )
        goto NewReadCode;
    else 
    {
    DWORD bytesRead = 0;

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

    EnterCriticalSection( &readMutex );

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

    DWORD index = channel - NUM_DMA_FIRST_CHANNEL;	// offset channel to match array indices
    
    if ( *(channels[index].vPFlags) & 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
        {
            vInputPB->ioDataLength = -1;		// 0 indicates error
        }
    }
    else
    {
        vInputPB->ioDataLength = 0;	// Nothing to read, 0 indicates end of file
    }

    bytesRead = vInputPB->ioDataLength;

    LeaveCriticalSection( &readMutex );

    return bytesRead;
    }

NewReadCode:
    DWORD bytesRead = 0;

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

    EnterCriticalSection( &readMutex );
    DWORD index = 0;

    if (channel < VIRTUAL_BASE )
    {
        index = channel - NUM_DMA_FIRST_CHANNEL; // offset channel to match array indices
    }
    else
    {
        DEBUGMSG( TRUE, (TEXT("DMA Transport:READ virtual on channel %x\n"), channel) );
        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.
            DEBUGMSG( TRUE, (TEXT("DMA Transport:READ %x bytes SUCCESS on channel %d\n"), vInputPB->ioDataLength, channel) );
            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
    {
        DEBUGMSG( TRUE, (TEXT("DMA Transport:READ nothing to read on channel %x\n"), channel) );
        vInputPB->ioDataLength = 0;	// Nothing to read, 0 indicates end of file
    }

    bytesRead = vInputPB->ioDataLength;

    if (channel >= VIRTUAL_BASE )
    {
        DEBUGMSG( TRUE, (TEXT("DMA Transport:READ virtual on channel %x (Cleared R_REG)\n"), channel) );
        WRITE_PORT_ULONG( DMA_V_CHANNEL_READ, 0 );
    }

    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
                                    )
{
    if ( code == IOCTL_GET_DMA_CHANNEL_INFO ) 
    {
        DEBUGMSG( TRUE, (TEXT("DMA Transport:Processing IOCTL - %x \n"), 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 );
        // 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) );
            goto ErrorGetInfo;
        }

        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()) );
            goto ErrorGetInfo;
        }

        // Write out the channel number
        *((DWORD *)outBuf) = channel;
        *actualOut = 8;
        LeaveCriticalSection( &vchannelAccess );

        DEBUGMSG( TRUE, (TEXT("DMA Transport:SUCCESS IOCTL for channel %x\n"), channel) );
        return TRUE;

ErrorGetInfo:
        LeaveCriticalSection( &vchannelAccess );
        return FALSE;
    }
    else if ( code == IOCTL_GET_DMA_CHANNEL_CONNECTED )
    {
        DEBUGMSG( TRUE, (TEXT("DMA Transport:Processing IOCTL - %x \n"), 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 < 4)
        {
            DEBUGMSG( TRUE, (TEXT("DMA Transport:FAILED IOCTL for channel %x - invalid buffer arguments\n"), channel) );
            return FALSE;
        }

        EnterCriticalSection( &vchannelAccess );
        // 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) );
            goto ErrorGetConnected;
        }
        // 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;

        DEBUGMSG( TRUE, (TEXT("DMA Transport:Channel status for %x is %x \n"),channel, *((DWORD *)outBuf)) );
        LeaveCriticalSection( &vchannelAccess );

        DEBUGMSG( TRUE, (TEXT("DMA Transport:SUCCESS IOCTL for channel %x\n"), channel) );
        return TRUE;

ErrorGetConnected:
        LeaveCriticalSection( &vchannelAccess );
        return FALSE;
    }
    return FALSE;
}


/*------------------------------------------------------------------
    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 + -