Vmware功能十分强大,支持很多硬件,特别是USB。Wince本身带了模拟器,可惜对硬件的模拟支持太差。在Vmware上面跑Wince诱惑性自然是十分强烈的。CSDN上的sting前辈就完成了这个工作,用他的VMCEPC BSP定制的系统可以支持USB、CDROM、HARD DISK以及网卡等。我很佩服sting前辈,他好像是制作外挂出身,后来转向嵌入式开发。他的博客是http://blog.csdn.net/singlerace ,上面有很多优秀文章。呵呵,希望那天我能不再佩服他。
言归正传,VMCEPC BSP的下载地址是:http://d.download.csdn.net/down/474719/singlerace 。前辈还定制了一个系统,下载地址是:http://d.download.csdn.net/source/474713 、http://d.download.csdn.net/source/474717 。估计是前辈比较忙,没有整理BSP的使用方法,使用这个BSP还要做一些辅助工作,我在这里代为整理,嘿嘿。
1:释放文件到WINCE600下。
2:需要修改源文件,这里注意备份,修改的是Public下的代码。前辈自己也不提倡这么做,只是需要支持Vmware下的USB和CD-ROM,这里没有办法。具体需要修改两处:
2.1:UHCI driver需要修改的代码(红色部分,在$(DRIVERS)/USB/HCD/UHC/system.c中):
// Inline functions
__inline static WORD
PCIConfig_ReadWord(
ULONG BusNumber,
ULONG Device,
ULONG Function,
ULONG Offset
)
{
WORD RetVal = 0;
PCI_SLOT_NUMBER SlotNumber;
SlotNumber.u.AsULONG = 0;
SlotNumber.u.bits.DeviceNumber = Device;
SlotNumber.u.bits.FunctionNumber = Function;
HalGetBusDataByOffset(PCIConfiguration, BusNumber, SlotNumber.u.AsULONG, &RetVal, Offset, sizeof(RetVal));
return RetVal;
}
__inline static void
PCIConfig_Write(
ULONG BusNumber,
ULONG Device,
ULONG Function,
ULONG Offset,
ULONG Value,
ULONG Size
)
{
PCI_SLOT_NUMBER SlotNumber;
SlotNumber.u.AsULONG = 0;
SlotNumber.u.bits.DeviceNumber = Device;
SlotNumber.u.bits.FunctionNumber = Function;
HalSetBusDataByOffset(PCIConfiguration, BusNumber, SlotNumber.u.AsULONG, &Value, Offset, Size);
}
/**//* InitializeUHCI
*
* Configure and initialize UHCI card
*
* Return Value:
* Return TRUE if card could be located and configured, otherwise FALSE
*/
static BOOL
InitializeUHCI(
SUhcdPdd * pPddObject, // IN - Pointer to PDD structure
LPCWSTR szDriverRegKey) // IN - Pointer to active registry key string
{
PUCHAR ioPortBase = NULL;
DWORD dwAddrLen;
DWORD dwIOSpace;
BOOL InstallIsr = FALSE;
BOOL fResult = FALSE;
LPVOID pobMem = NULL;
LPVOID pobUhcd = NULL;
DWORD PhysAddr;
DWORD dwHPPhysicalMemSize;
HKEY hKey;
WORD LegSup;
DDKWINDOWINFO dwi;
DDKISRINFO dii;
DDKPCIINFO dpi;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,szDriverRegKey,0,0,&hKey)!= ERROR_SUCCESS) {
DEBUGMSG(ZONE_ERROR,(TEXT("InitializeUHCI:GetRegistryConfig RegOpenKeyEx(%s) failed "),
szDriverRegKey));
return FALSE;
}
dwi.cbSize=sizeof(dwi);
dii.cbSize=sizeof(dii);
dpi.cbSize=sizeof(dpi);
if ( DDKReg_GetWindowInfo(hKey, &dwi ) !=ERROR_SUCCESS ||
DDKReg_GetIsrInfo (hKey, &dii ) != ERROR_SUCCESS ||
DDKReg_GetPciInfo (hKey, &dpi ) != ERROR_SUCCESS) {
DEBUGMSG(ZONE_ERROR,(TEXT("InitializeUHCI:DDKReg_GetWindowInfo or DDKReg_GetWindowInfo or DDKReg_GetPciInfo failed ")));
goto InitializeUHCI_Error;
}
if (dwi.dwNumMemWindows!=0) {
PhysAddr = dwi.memWindows[0].dwBase;
dwAddrLen= dwi.memWindows[0].dwLen;
dwIOSpace = 0;
}
else if (dwi.dwNumIoWindows!=0) {
PhysAddr= dwi.ioWindows[0].dwBase;
dwAddrLen = dwi.ioWindows[0].dwLen;
dwIOSpace = 1;
}
else
goto InitializeUHCI_Error;
DEBUGMSG(ZONE_INIT,(TEXT("UHCD: Read config from registry: Base Address: 0x%X, Length: 0x%X, I/O Port: %s, SysIntr: 0x%X, Interface Type: %u, Bus Number: %u "),
PhysAddr, dwAddrLen, dwIOSpace ? L"YES" : L"NO", dii.dwSysintr, dwi.dwInterfaceType, dwi.dwBusNumber));
ioPortBase = (PUCHAR)PhysAddr;
if (!(fResult = ConfigureUHCICard(pPddObject, &ioPortBase, dwAddrLen, dwIOSpace, dwi.dwInterfaceType, dwi.dwBusNumber))) {
goto InitializeUHCI_Error;
}
if (dii.szIsrDll[0] != 0 && dii.szIsrHandler[0]!=0 && dii.dwIrq<0xff && dii.dwIrq>0 ) {
// Install ISR handler
pPddObject->IsrHandle = LoadIntChainHandler(dii.szIsrDll,dii.szIsrHandler, (BYTE)dii.dwIrq);
if (!pPddObject->IsrHandle) {
DEBUGMSG(ZONE_ERROR, (L"UHCD: Couldn't install ISR handler "));
} else {
GIISR_INFO Info;
PHYSICAL_ADDRESS PortAddress = {PhysAddr, 0};
DEBUGMSG(ZONE_INIT, (L"UHCD: Installed ISR handler, Dll = '%s', Handler = '%s', Irq = %d ",
dii.szIsrDll, dii.szIsrHandler, dii.dwIrq));
if (!BusTransBusAddrToStatic(pPddObject->hParentBusHandle,dwi.dwInterfaceType, dwi.dwBusNumber, PortAddress, dwAddrLen, &dwIOSpace, &(PVOID)PhysAddr)) {
DEBUGMSG(ZONE_ERROR, (L"UHCD: Failed TransBusAddrToStatic "));
return FALSE;
}
// Set up ISR handler
Info.SysIntr = dii.dwSysintr;
Info.CheckPort = TRUE;
Info.PortIsIO = (dwIOSpace) ? TRUE : FALSE;
Info.UseMaskReg = TRUE;;
Info.PortAddr = PhysAddr + 0x2;
Info.PortSize = sizeof(WORD);
Info.MaskAddr = PhysAddr + 0x4;
if (!KernelLibIoControl(pPddObject->IsrHandle, IOCTL_GIISR_INFO, &Info, sizeof(Info), NULL, 0, NULL)) {
DEBUGMSG(ZONE_ERROR, (L"UHCD: KernelLibIoControl call failed. "));
}
}
}
// The PDD can supply a buffer of contiguous physical memory here, or can let the
// MDD try to allocate the memory from system RAM. We will use the HalAllocateCommonBuffer()
// API to allocate the memory and bus controller physical addresses and pass this information
// into the MDD.
if (GetRegistryPhysicalMemSize(szDriverRegKey,&pPddObject->dwPhysicalMemSize)) {
// A quarter for High priority Memory.
dwHPPhysicalMemSize = pPddObject->dwPhysicalMemSize/4;
// Align with page size.
pPddObject->dwPhysicalMemSize = (pPddObject->dwPhysicalMemSize + PAGE_SIZE -1) & ~(PAGE_SIZE -1);
dwHPPhysicalMemSize = ((dwHPPhysicalMemSize + PAGE_SIZE -1) & ~(PAGE_SIZE -1));
}
else {
pPddObject->dwPhysicalMemSize=0;
dwHPPhysicalMemSize = 0;
}
if (pPddObject->dwPhysicalMemSize<gcTotalAvailablePhysicalMemory) { // Setup Minimun requirement.
pPddObject->dwPhysicalMemSize = gcTotalAvailablePhysicalMemory;
dwHPPhysicalMemSize = gcHighPriorityPhysicalMemory;
}
pPddObject->AdapterObject.ObjectSize = sizeof(DMA_ADAPTER_OBJECT);
pPddObject->AdapterObject.InterfaceType = dwi.dwInterfaceType;
pPddObject->AdapterObject.BusNumber = dwi.dwBusNumber;
if ((pPddObject->pvVirtualAddress = HalAllocateCommonBuffer(&pPddObject->AdapterObject, pPddObject->dwPhysicalMemSize, &pPddObject->LogicalAddress, FALSE)) == NULL) {
goto InitializeUHCI_Error;
}
if (!(pobMem = HcdMdd_CreateMemoryObject(pPddObject->dwPhysicalMemSize, dwHPPhysicalMemSize, (PUCHAR) pPddObject->pvVirtualAddress, (PUCHAR) pPddObject->LogicalAddress.LowPart))) {
goto InitializeUHCI_Error;
}
if (!(pobUhcd = HcdMdd_CreateHcdObject(pPddObject, pobMem, szDriverRegKey, ioPortBase, dii.dwSysintr))) {
goto InitializeUHCI_Error;
}
// set LEGSUP here
LegSup = PCIConfig_ReadWord(dwi.dwBusNumber, dpi.dwDeviceNumber, dpi.dwFunctionNumber, 0xC0);
RETAILMSG(1, (TEXT("UHCD: LEGSUP=0x%08x "), LegSup));
LegSup = 0x2000;
PCIConfig_Write(dwi.dwBusNumber, dpi.dwDeviceNumber, dpi.dwFunctionNumber, 0xC0, LegSup, sizeof(LegSup));
pPddObject->lpvMemoryObject = pobMem;
pPddObject->lpvUhcdMddObject = pobUhcd;
_tcsncpy(pPddObject->szDriverRegKey, szDriverRegKey, MAX_PATH);
pPddObject->ioPortBase = ioPortBase;
pPddObject->dwSysIntr = dii.dwSysintr;
// PCI OHCI support suspend and resume
if ( hKey!=NULL) {
DWORD dwCapability;
DWORD dwType;
DWORD dwLength = sizeof(DWORD);
if (RegQueryValueEx(hKey, HCD_CAPABILITY_VALNAME, 0, &dwType, (PUCHAR)&dwCapability, &dwLength) == ERROR_SUCCESS)
HcdMdd_SetCapability (pobUhcd,dwCapability);
RegCloseKey(hKey);
}
return TRUE;
InitializeUHCI_Error:
if (pPddObject->IsrHandle) {
FreeIntChainHandler(pPddObject->IsrHandle);
pPddObject->IsrHandle = NULL;
}
if (pobUhcd)
HcdMdd_DestroyHcdObject(pobUhcd);
if (pobMem)
HcdMdd_DestroyMemoryObject(pobMem);
if(pPddObject->pvVirtualAddress)
HalFreeCommonBuffer(&pPddObject->AdapterObject, pPddObject->dwPhysicalMemSize, pPddObject->LogicalAddress, pPddObject->pvVirtualAddress, FALSE);
pPddObject->lpvMemoryObject = NULL;
pPddObject->lpvUhcdMddObject = NULL;
pPddObject->pvVirtualAddress = NULL;
if ( hKey!=NULL)
RegCloseKey(hKey);
return FALSE;
}
2.2:在$(WINCEROOT)/PUBLIC/COMMON/OAK/DRIVERS/BLOCK/ATAPI/atapipcicd.cpp中把audio command相关的IOCTL code注释掉
DWORD
CPCIDiskAndCD::MainIoctl(
PIOREQ pIOReq
)
{
DWORD dwError;
DEBUGMSG(ZONE_IOCTL, (_T(
"Atapi!CPCIDiskAndCD::MainIoctl> IOCTL(0x%x), device(%d) "
),pIOReq->dwCode, m_dwDeviceId));
dwError = CPCIDisk::MainIoctl(pIOReq);
if (dwError == ERROR_NOT_SUPPORTED) {
switch(pIOReq->dwCode) {
// supported ATAPI commands
case IOCTL_CDROM_READ_SG:
case IOCTL_CDROM_TEST_UNIT_READY:
case IOCTL_CDROM_DISC_INFO:
case IOCTL_CDROM_EJECT_MEDIA:
case IOCTL_CDROM_LOAD_MEDIA:
// supported DVD commands
case IOCTL_DVD_START_SESSION:
case IOCTL_DVD_READ_KEY:
case IOCTL_DVD_END_SESSION:
case IOCTL_DVD_SEND_KEY:
case IOCTL_DVD_GET_REGION:
#if 0
// supported audio commands
case IOCTL_CDROM_READ_TOC:
case IOCTL_CDROM_GET_CONTROL:
case IOCTL_CDROM_PLAY_AUDIO_MSF:
case IOCTL_CDROM_SEEK_AUDIO_MSF:
case IOCTL_CDROM_STOP_AUDIO:
case IOCTL_CDROM_PAUSE_AUDIO:
case IOCTL_CDROM_RESUME_AUDIO:
case IOCTL_CDROM_GET_VOLUME:
case IOCTL_CDROM_SET_VOLUME:
case IOCTL_CDROM_READ_Q_CHANNEL:
case IOCTL_CDROM_GET_LAST_SESSION:
case IOCTL_CDROM_RAW_READ:
case IOCTL_CDROM_DISK_TYPE:
case IOCTL_CDROM_SCAN_AUDIO:
case IOCTL_CDROM_ISSUE_INQUIRY:
#endif
if (IsAtapiDevice()) {
dwError = AtapiIoctl(pIOReq);
}
else {
dwError = ERROR_INVALID_OPERATION;
}
break;
default:
dwError = ERROR_NOT_SUPPORTED;
break;
}
}
return dwError;
}