📄 kitldma.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
/*==================================================================
File: kitldma.c
Contains: Implementation of the KITL (Kernel Independent
Transport Layer) for the Emulator for Windows CE.
The Emulator provides a specialized transport
that is optimized to take advantage of the fact
that the Emulator and Platform Builder are
two processes running on the same machine.
Written by: Craig Vinet
Copyright: 2001 Connectix Corporation
==================================================================*/
#include <windows.h>
#include <nkintr.h>
#include <kitl.h>
#include <kitlprot.h>
#include <wdm.h> // for READ_REGISTER_XXXX, WRITE_REGISTER_XXXX
#include <oal.h>
#include <bsp.h>
#ifdef _MSC_VER
//#pragma warning(disable:4514) // disable unwanted C++ /W4 warning
// #pragma warning(default:4514) // use this to reenable, if necessary
#endif // _MSC_VER
/*------------------------------------------------------------------
Types and defines
------------------------------------------------------------------*/
#define kWaitForPacketSleepTime (10)
#define DMA_KITL_IRQ (0x26) // from platform.reg settings for DMA4. IRQ_EINT10
// Register values
// global
#define DMA_KITL_HANDSHAKE (1 << 0)
#define DMA_KITL_INTERRUPTS_ENABLED (1 << 8)
// flags
#define DMA_KITL_FLAGS_DATA_READY (1 << 0)
// Status
#define DMA_KITL_STATUS_ERROR_QUEUE_OVERFLOW (1 << 0)
#define DMA_KITL_STATUS_ERROR_PACKET_OVERFLOW (1 << 1)
// DMA register window
#define DMA_KITL_REG_BASE_PA (0x500f0000)
#define DMA_KITL_REG_BASE_VA (0x910f0000)
// Packet size: 4KB
#define DMA_PACKET_SIZE 0x1000
// Size of the memory window for accessing the DMA Transport peripheral device.
// This value is taken from mappediodevices.h in the Device Emulator source.
#define DMA_DEVICE_SIZE 0x211c
// Default device name (limited to 16 characters)
#define DEFAULT_DEVICE_NAME "DeviceEmulator"
// This is an IO parameter block used by the DMA Transport "hardware" device
// in the Emulator. The device will write to these fields when we attempt to
// receive a packet from the device.
typedef struct
{
volatile ULONG ioDataLength;
volatile ULONG ioDataPtr;
volatile ULONG ioStatus;
} IOParamBlock;
// Holds info for DMA channel, an instance per channel
typedef struct _DMAChannel
{
BOOL open; // True if channel is open
PULONG vPFlags; // Virtual pointer to flags
PULONG pFlags; // Physical pointer to flags
ULONG access; // Read/Write access
HANDLE dataReadyEvent; // Event is created in calling application, app passes event name to DeviceIOControl, and driver gets a handle to it
// Fired when data is ready to be read
ULONG channelNumber;
struct _DMAChannel* next;
} DMAChannel;
// Number of channels
#define NUM_DMA_CHANNELS 4
#define KITL_DMA_CHANNEL 0
/*------------------------------------------------------------------
Local storage
------------------------------------------------------------------*/
DMAChannel channels[NUM_DMA_CHANNELS];
// Global parameter block variables
// physical
IOParamBlock* inputPB;
IOParamBlock* outputPB;
// virtual
IOParamBlock* vInputPB;
IOParamBlock* vOutputPB;
// Global buffers
PUCHAR vInputBuffer;
PUCHAR vOutputBuffer;
PUCHAR inputBuffer;
PUCHAR outputBuffer;
// channel base address on the bus
#define kDMATransportBase (vInputBuffer+0x2080)
// Channel size
const ULONG kDMATransportChannelSize = 0x20;
// DMATransportDevice register offsets.
enum
{
kDMATransportGlobalRegister = 0x00,
kDMATransportFlagsRegister = 0x04,
kDMATransportIOInputRegister = 0x08,
kDMATransportIOOutputRegister = 0x0C,
kDMATransportIRQRegister = 0x10,
kDMATransportIRQAcknowledgeRegister = 0x14,
};
// Regisgter macros, given the channel returns specific register
#define DMA_GLOBAL_REG(a) ((ULONG*)(kDMATransportBase+(a*kDMATransportChannelSize)+kDMATransportGlobalRegister))
#define DMA_FLAGS_ADDRESS_REG(a) ((ULONG*)(kDMATransportBase+(a*kDMATransportChannelSize)+kDMATransportFlagsRegister))
#define DMA_IO_INPUT_REG(a) ((ULONG*)(kDMATransportBase+(a*kDMATransportChannelSize)+kDMATransportIOInputRegister))
#define DMA_IO_OUTPUT_REG(a) ((ULONG*)(kDMATransportBase+(a*kDMATransportChannelSize)+kDMATransportIOOutputRegister))
#define DMA_IRQ_REG(a) ((ULONG*)(kDMATransportBase+(a*kDMATransportChannelSize)+kDMATransportIRQRegister))
#define DMA_IRQ_ACK_REG(a) ((ULONG*)(kDMATransportBase+(a*kDMATransportChannelSize)+kDMATransportIRQAcknowledgeRegister))
#define KITL_DMA_GLOBAL_REG DMA_GLOBAL_REG( KITL_DMA_CHANNEL )
#define KITL_DMA_FLAGS_ADDRESS_REG DMA_FLAGS_ADDRESS_REG( KITL_DMA_CHANNEL )
#define KITL_DMA_IO_INPUT_REG DMA_IO_INPUT_REG( KITL_DMA_CHANNEL )
#define KITL_DMA_IO_OUTPUT_REG DMA_IO_OUTPUT_REG( KITL_DMA_CHANNEL )
#define KITL_DMA_IRQ_REG DMA_IRQ_REG( KITL_DMA_CHANNEL )
#define KITL_DMA_IRQ_ACK_REG DMA_IRQ_ACK_REG( KITL_DMA_CHANNEL )
// Virtual channel operation register offsets.
enum
{
kDMAVirtualChannel = 0x00,
kDMAVirtualOperation = 0x04,
kDMAVirtualStatus = 0x08,
kDMAFlagsChannel = 0x0C,
kDMAReadChannel = 0x10,
kDMAWriteChannel = 0x14,
};
#define DMA_CURR_V_CHANNEL ((ULONG*)(kDMATransportBase+(NUM_DMA_CHANNELS*kDMATransportChannelSize)+kDMAVirtualChannel))
#define DMA_CURR_V_OPERATION ((ULONG*)(kDMATransportBase+(NUM_DMA_CHANNELS*kDMATransportChannelSize)+kDMAVirtualOperation))
#define DMA_CURR_V_STATUS ((ULONG*)(kDMATransportBase+(NUM_DMA_CHANNELS*kDMATransportChannelSize)+kDMAVirtualStatus))
#define DMA_V_CHANNEL_FLAGS ((ULONG*)(kDMATransportBase+(NUM_DMA_CHANNELS*kDMATransportChannelSize)+kDMAFlagsChannel))
#define DMA_V_CHANNEL_READ ((ULONG*)(kDMATransportBase+(NUM_DMA_CHANNELS*kDMATransportChannelSize)+kDMAReadChannel))
#define DMA_V_CHANNEL_WRITE ((ULONG*)(kDMATransportBase+(NUM_DMA_CHANNELS*kDMATransportChannelSize)+kDMAWriteChannel))
/*------------------------------------------------------------------
Prototypes
------------------------------------------------------------------*/
BOOL InitDMAKitl(PKITLTRANSPORT pKitl);
BOOL InitializeDMATransport(void);
BOOL DMAKitlEncodePacket(LPBYTE pbFrame, USHORT cbData);
LPBYTE DMAKitlDecodePacket(LPBYTE pbFrame, PUSHORT pcbData);
BOOL DMAKitlSendPacket(LPBYTE pbFrame, USHORT cbFrame);
BOOL DMAKitlReceivePacket(LPBYTE pbFrame, PUSHORT pcbData);
BOOL DMAKitlSetHostConfiguration(LPBYTE pbConfig, USHORT cbConfig);
BOOL DMAKitlGetDeviceConfiguration(LPBYTE pbConfig, PUSHORT pcbConfig);
VOID DMAKitlEnableInts(BOOL fEnable);
/*------------------------------------------------------------------
InitDMAKitl
Called from OEMKitlInit to initialize the DMA transport and
fill in the KITLTRANSPORT struct (See the file "kitl.h"
in "WINCE400\public\common\oak\inc\" for the definition).
Returns TRUE if successful, FALSE otherwise.
------------------------------------------------------------------*/
BOOL
InitDMAKitl(
PKITLTRANSPORT inKitlTransport )
{
BOOL success = FALSE;
KITLOutputDebugString("+InitDMAKitl\n");
// Init the DMA Transport "hardware". If it works, go ahead
// and fill in the KITL transport structure.
if ( InitializeDMATransport() )
{
DWORD kDMATransport_IRQ = DMA_KITL_IRQ; // from platform.reg settings for DMA4
DWORD SysIntr;
// Zero the KITLTRANSPORT structure.
memset( inKitlTransport, 0, sizeof(KITLTRANSPORT) );
// Store a default device name.
strncpy( inKitlTransport->szName, DEFAULT_DEVICE_NAME, KITL_MAX_DEV_NAMELEN );
KITLOutputDebugString("Using device name: %s\n", inKitlTransport->szName);
if (!OEMIoControl(IOCTL_HAL_REQUEST_SYSINTR,
&kDMATransport_IRQ, sizeof(DWORD),
&SysIntr, sizeof(DWORD),
NULL))
{
KITLOutputDebugString("InitDMAKitl Failed to obtain sysintr value for data interrupt.\n");
}
else
{
// Fill in the KITLTRANSPORT struct
inKitlTransport->dwBootFlags = 0;
inKitlTransport->Interrupt = (UCHAR)SysIntr;
inKitlTransport->WindowSize = 8; // <= KITL_MAX_WINDOW_SIZE
inKitlTransport->FrmHdrSize = 0;
inKitlTransport->FrmTlrSize = 0;
inKitlTransport->pfnDecode = DMAKitlDecodePacket;
inKitlTransport->pfnEncode = DMAKitlEncodePacket;
inKitlTransport->pfnSend = DMAKitlSendPacket;
inKitlTransport->pfnRecv = DMAKitlReceivePacket;
inKitlTransport->pfnEnableInt = DMAKitlEnableInts;
inKitlTransport->pfnSetHostCfg = DMAKitlSetHostConfiguration;
inKitlTransport->pfnGetDevCfg = DMAKitlGetDeviceConfiguration;
success = TRUE;
}
KITLOutputDebugString("InitDMAKitl - succeeded\n");
}
// Print banner. Will remove when KITL-over-ethernet support is dropped
// (in M3)
KITLOutputDebugString("\n*********************************************\n");
KITLOutputDebugString("* *\n");
KITLOutputDebugString("* This image uses KITL-over-DMA *\n");
KITLOutputDebugString("* *\n");
KITLOutputDebugString("* PB Connectivity Options must be set to: *\n");
KITLOutputDebugString("* Download: \"Device Emulator (DMA)\" *\n");
KITLOutputDebugString("* Transport: \"Device Emulator (DMA)\" *\n");
KITLOutputDebugString("* *\n");
KITLOutputDebugString("*********************************************\n\n");
KITLOutputDebugString("-InitDMAKitl\n");
return success;
}
/*------------------------------------------------------------------
InitializeDMATransport
Initializes the DMA Transport "hardware" in the Emualtor.
Returns TRUE if successful, FALSE otherwise.
------------------------------------------------------------------*/
BOOL
InitializeDMATransport()
{
BOOL success = FALSE;
KITLOutputDebugString ("+InitializeDMATransport\n");
// Set up virtual addresses we've allocated
vInputBuffer = (PUCHAR)DMA_KITL_REG_BASE_VA;
vOutputBuffer = vInputBuffer + DMA_PACKET_SIZE;
channels[0].vPFlags = (PULONG)(vOutputBuffer + DMA_PACKET_SIZE);
channels[1].vPFlags = (channels[0].vPFlags + 1);
channels[2].vPFlags = (channels[1].vPFlags + 1);
channels[3].vPFlags = (channels[2].vPFlags + 1);
// PB is hard-coded to use Channel 4 for KITL
vInputPB = (IOParamBlock*)(channels[3].vPFlags + 1);
vOutputPB = (IOParamBlock*)((PUCHAR)vInputPB + sizeof(IOParamBlock));
// Set physical addresses we've allocated
inputBuffer = (PUCHAR)DMA_KITL_REG_BASE_PA;
outputBuffer = inputBuffer + DMA_PACKET_SIZE;
channels[0].pFlags = (PULONG)(outputBuffer + DMA_PACKET_SIZE);
channels[1].pFlags = (channels[0].pFlags + 1);
channels[2].pFlags = (channels[1].pFlags + 1);
channels[3].pFlags = (channels[2].pFlags + 1);
// Platform Builder is hard-coded to use Channel 4 for KITL
inputPB = (IOParamBlock*)(channels[3].pFlags + 1);
outputPB = (IOParamBlock*)((PUCHAR)inputPB + sizeof(IOParamBlock));
KITLOutputDebugString("\nKITL Using DMA channel index %d\n\n", KITL_DMA_CHANNEL);
KITLOutputDebugString("vInputBuffer = 0x%x\n", vInputBuffer);
KITLOutputDebugString("vOutputBuffer = 0x%x\n", vOutputBuffer);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -