ohcd.c
上传用户:qiulin1960
上传日期:2013-10-16
资源大小:2844k
文件大小:14k
源码类别:

Windows CE

开发平台:

Windows_Unix

  1. /*++
  2. THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  3. ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  4. THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  5. PARTICULAR PURPOSE.
  6. Copyright (c) 2001. Samsung Electronics, co. ltd  All rights reserved.
  7. Module Name:  
  8.     ohcd.c
  9.     
  10. Abstract:  
  11.     Platform dependant part of the USB Open Host Controller Driver (OHCD).
  12. rev:
  13. 2001.12.26 : OHC base pointer is changed(with VirtaulAlloc&VirtualCopy) (kwangyoon LEE, kwangyoon@samsung.com)
  14.   Because Windows CE may not run in Full-Kernel thread mode (when ROMFLAGS bit 1 is cleared)
  15.   CHECK IMGNOTALLKMODE environment variable!!!
  16. 2001.12.26 : code clean-up (kwangyoon LEE, kwangyoon@samsung.com)
  17. Notes: 
  18. --*/
  19. #include <windows.h>
  20. #include <nkintr.h>
  21. #include <oalintr.h>
  22. #include <ceddk.h>
  23. #include <ohcdddsi.h>
  24. // Registry key and value names
  25. #define OHCI_DRIVER_KEY         TEXT("Drivers\BuiltIn\OHCI")
  26. #define USE_EXISTING_VALUE_NAME TEXT("UseExistingSettings")
  27. #define IRQ_VALUE_NAME          TEXT("Irq")
  28. #define IOBASE_VALUE_NAME       TEXT("MemBase")
  29. // Amount of memory to use for HCD buffer
  30. static const DWORD gcTotalAvailablePhysicalMemory = 65536;  // 64K
  31. static const DWORD gcHighPriorityPhysicalMemory   = 0x4000; // 16K
  32. typedef struct _SOhcdPdd
  33. {
  34. LPVOID lpvMemoryObject;
  35. LPVOID lpvOhcdMddObject;
  36. } SOhcdPdd;
  37. #define UnusedParameter(x)  x = x
  38. #define USB_INTR                        11
  39. #define USB_BASE                        0xB0900000
  40. #define USB_PHYSICAL_BASE               0x49000000
  41. #define USB_OPERATIONAL_REGISTER_SIZE   0x4096
  42. #define ZONE_ERROR 1
  43. volatile ULONG *v_USBreg;
  44. /* OhcdPdd_DllMain
  45.  * 
  46.  *  DLL Entry point.
  47.  *
  48.  * Return Value:
  49.  */
  50. extern BOOL HcdPdd_DllMain(HANDLE hinstDLL, DWORD dwReason, LPVOID lpvReserved)
  51. {
  52. UnusedParameter(hinstDLL);
  53. UnusedParameter(dwReason);
  54. UnusedParameter(lpvReserved);
  55. return TRUE;
  56. }
  57. /* GetRegistryConfig
  58.  *
  59.  *   Function to get the IRQ and I/O port range from the registry.  
  60.  *   Note: Will need to be changed to support multiple instances.
  61.  *
  62.  * Return Value:
  63.  *   TRUE for success, FALSE for error
  64.  */
  65. static BOOL
  66. GetRegistryConfig( DWORD * lpdwUseExistingSettings, // OUT- Receives value that indicates whether to 
  67. //      just use the resources assigned by the BIOS.  
  68. DWORD * lpdwIrq, // OUT- Receives IRQ value
  69. DWORD * lpdwIoBase ) // OUT- Receives I/O base
  70. {
  71. HKEY hKey;
  72. DWORD dwData;
  73. DWORD dwSize;
  74. DWORD dwType;
  75. BOOL  fRet=FALSE;
  76. DWORD dwRet;
  77. dwRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,OHCI_DRIVER_KEY,0,0,&hKey);
  78. if (dwRet != ERROR_SUCCESS)
  79. {
  80. RETAILMSG(ZONE_ERROR,(TEXT("!OHCD:GetRegistryConfig RegOpenKeyEx(%s) failed %drn"),
  81. OHCI_DRIVER_KEY, dwRet));
  82. return FALSE;
  83. }
  84. dwSize = sizeof(dwData);
  85. dwRet = RegQueryValueEx(hKey,USE_EXISTING_VALUE_NAME,0,&dwType,(PUCHAR)&dwData,&dwSize);
  86. if (dwRet != ERROR_SUCCESS)
  87. {
  88. RETAILMSG(ZONE_ERROR, (TEXT("!OHCD:GetRegistryConfig RegQueryValueEx(%s) failed %drn"),
  89. USE_EXISTING_VALUE_NAME, dwRet));
  90. goto GetRegistryConfig_exit;
  91. }
  92. *lpdwUseExistingSettings = dwData;
  93. dwSize = sizeof(dwData);
  94. dwRet = RegQueryValueEx(hKey,IRQ_VALUE_NAME,0,&dwType,(PUCHAR)&dwData,&dwSize);
  95. if (dwRet != ERROR_SUCCESS)
  96. {
  97. RETAILMSG(ZONE_ERROR, (TEXT("!OHCD:GetRegistryConfig RegQueryValueEx(%s) failed %drn"),
  98. IRQ_VALUE_NAME, dwRet));
  99. goto GetRegistryConfig_exit;
  100. }
  101. *lpdwIrq = dwData;
  102. dwSize = sizeof(dwData);
  103. dwRet = RegQueryValueEx(hKey,IOBASE_VALUE_NAME,0,&dwType,(PUCHAR)&dwData,&dwSize);
  104. if (dwRet != ERROR_SUCCESS)
  105. {
  106. RETAILMSG(ZONE_ERROR,(TEXT("!OHCD:GetRegistryConfig RegQueryValueEx(%s) failed %drn"),
  107. IOBASE_VALUE_NAME, dwRet));
  108. goto GetRegistryConfig_exit;
  109. }
  110. *lpdwIoBase = dwData;
  111.     fRet = TRUE;
  112. GetRegistryConfig_exit:
  113. RegCloseKey(hKey);
  114. return fRet;
  115. }   // GetRegistryConfig
  116. /* SetRegistryConfig
  117.  *
  118.  *   Function to set the IRQ and I/O port range in the registry.
  119.  *   Note: Will need to be changed to support multiple instances.
  120.  *
  121.  * Return Value:
  122.  *   TRUE for success, FALSE for error
  123.  */
  124. static BOOL
  125. SetRegistryConfig( DWORD dwIrq,    // IN - IRQ value
  126. DWORD dwIoBase  ) // IN - I/O base
  127. {
  128. HKEY hKey;
  129. BOOL  fRet=FALSE;
  130. DWORD dwRet;
  131. dwRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,OHCI_DRIVER_KEY,0,0,&hKey);
  132. if (dwRet != ERROR_SUCCESS)
  133. {
  134. RETAILMSG(ZONE_ERROR,(TEXT("!OHCD:SetRegistryConfig RegOpenKeyEx(%s) failed %drn"),
  135. OHCI_DRIVER_KEY, dwRet));
  136. return FALSE;
  137. }
  138. dwRet = RegSetValueEx(hKey,IRQ_VALUE_NAME,0,REG_DWORD,(PUCHAR)&dwIrq,sizeof(DWORD));
  139. if (dwRet != ERROR_SUCCESS)
  140. {
  141. RETAILMSG(ZONE_ERROR, (TEXT("!OHCD:SetRegistryConfig RegQueryValueEx(%s) failed %drn"),
  142. IRQ_VALUE_NAME, dwRet));
  143. goto SetRegistryConfig_exit;
  144. }
  145. dwRet = RegSetValueEx(hKey,IOBASE_VALUE_NAME,0,REG_DWORD,(PUCHAR)&dwIoBase,sizeof(DWORD));
  146. if (dwRet != ERROR_SUCCESS)
  147. {
  148. RETAILMSG(ZONE_ERROR,(TEXT("!OHCD:SetRegistryConfig RegQueryValueEx(%s) failed %drn"),
  149. IOBASE_VALUE_NAME, dwRet));
  150. goto SetRegistryConfig_exit;
  151. }
  152. fRet = TRUE;
  153. SetRegistryConfig_exit:
  154. RegCloseKey(hKey);
  155. return fRet;
  156. }   // SetRegistryConfig
  157. /* ConfigureOHCICard
  158.  * 
  159.  *    Configure OHCI controller I/O base and IRQ based on settings read from registry.
  160.  *    This should really call routines which access the IRQ routing and memory base through
  161.  *    the PCI BIOS and reconfigure the card.  Since we currently don't have the routines
  162.  *    to do this, use the following algorithm:
  163.  *        -- If fUseExisting flag is set, read the values from the PCI config registers on the
  164.  *           card, and update pioPortBase and pIrq.
  165.  *        -- If fUseExisting is not set, verify that the passed in values of pioPortBase and
  166.  *           pIrq match, and return FALSE if they do not. (change - don't fail if mem base
  167.  *           doesn't match, since this is determined by the PCI config mechanism, it will not
  168.  *           conflict with other cards.)
  169.  *
  170.  * Return Value
  171.  *    Return TRUE if successful, FALSE if card could not be detected, or if configuration
  172.  *    does not match what was specified in the registry, and fUseExistingSettings is not set.
  173.  */
  174. BOOL
  175. ConfigureOHCICard( BOOL fUseExistingSettings,
  176. PUCHAR *pioPortBase, // IN - contains physical address of register base
  177. // OUT- contains virtual address of register base
  178. ULONG *pIrq  ) // IN - contains IRQ value
  179. // OUT- (if fUseExistingSettings) contains actual IRQ value
  180. {
  181. const USHORT cDefaultOhcdPortRange = 0x70;
  182. const ULONG cHTBAMemorySpace = 0;
  183. const ULONG cHTBAIOSpace = 1;
  184. ULONG portRange = cDefaultOhcdPortRange;
  185. ULONG inIoSpace = cHTBAMemorySpace;
  186. *pIrq = USB_INTR;
  187. (DWORD)*pioPortBase = USB_BASE; // This address must be changed to the virtual address.
  188.                                  // In this time, I don't konw the virtual address map.
  189.                                  // The physical IO address on the 2400 board.
  190.                                  // This value must be defined in the config.bib.
  191.                                  // by hjcho 04/16
  192. // Virtual address allocation. 
  193. // In the MDD, the USB operational registers are accessed.
  194. v_USBreg = (ULONG*)VirtualAlloc(0, USB_OPERATIONAL_REGISTER_SIZE, MEM_RESERVE, PAGE_NOACCESS);
  195. if (v_USBreg == NULL)
  196. {
  197. ERRORMSG(1, (TEXT("USB Operational Register Addresses: VirtualAlloc failed!rn")));
  198. goto error_return;
  199. }
  200. if (!VirtualCopy((PVOID)v_USBreg,
  201. (PVOID)USB_BASE,
  202.   USB_OPERATIONAL_REGISTER_SIZE,
  203. PAGE_READWRITE|PAGE_NOCACHE) )
  204. {
  205. ERRORMSG(1, (TEXT("USB Operational Register Addresses: VirtualCopy failed!rn")));
  206. goto error_return;
  207. }
  208. SetRegistryConfig(*pIrq, (DWORD)*pioPortBase);
  209. *pioPortBase = v_USBreg;
  210. RETAILMSG(1,(TEXT("USB:*pIrq=%d, *pioPortBase=0x%Xrn"),*pIrq, *pioPortBase));    
  211. return TRUE;
  212. error_return:
  213. if (v_USBreg)
  214. VirtualFree((PVOID)v_USBreg, 0, MEM_RELEASE);
  215. v_USBreg = 0;
  216. return FALSE;
  217. }
  218. /* InitializeOHCI
  219.  *
  220.  *  Configure and initialize OHCI card
  221.  *
  222.  * Return Value:
  223.  *  Return TRUE if card could be located and configured, otherwise FALSE
  224.  */
  225. static BOOL 
  226. InitializeOHCI( SOhcdPdd * pPddObject,    // IN - Pointer to PDD structure
  227. LPCWSTR szDriverRegKey )   // IN - Pointer to active registry key string
  228. {
  229. DWORD dwUseExistingSettings;
  230. PUCHAR ioPortBase = NULL;
  231. DWORD dwSysIntr, dwIRQ;
  232. BOOL fResult = FALSE;
  233. LPVOID pobMem = NULL;
  234. LPVOID pobOhcd = NULL;
  235. RETAILMSG(1, (TEXT("++InitializeOHCIrn")));
  236. #if 0 // LKY 2001.12, currently We don't use registry!
  237. if (!GetRegistryConfig(&dwUseExistingSettings, &dwIRQ, (DWORD *)&ioPortBase))
  238. {
  239. RETAILMSG(1,(TEXT("!OHCD: Error reading registry settingsrn")));
  240. return FALSE;
  241.     }
  242. RETAILMSG(1, (TEXT("OHCD: Read config from registry: Use existing: %u, IRQ: %u, I/O base: %Xrn"),
  243. dwUseExistingSettings,dwIRQ,ioPortBase));
  244. #endif
  245. fResult = ConfigureOHCICard(!!dwUseExistingSettings, &ioPortBase, &dwIRQ);
  246. if (fResult)
  247. {
  248. // The "MapIrq2SysIntr()" makes the system IRQ value be mapped to the physical interrupt.
  249. // This function is defined in the 'oalintr.h' in the directory 'INC'.
  250. // The dwIRQ may be used a higher value than 10. The value 0 to 10 is alreay used. 
  251. // by hjcho. 04/16
  252. // dwSysIntr = SYSINTR_USB = SYSINTR_FIRMWARE + dwIRQ
  253. // dwIRQ = 11. I decided its value temporary.
  254. // by hjcho 04/17
  255. dwSysIntr = MapIrq2SysIntr(dwIRQ);
  256. RETAILMSG(1,(TEXT("OHCD: MapIrq2SysIntr(%u): %urn"),dwIRQ,dwSysIntr));
  257. // The PDD can supply a buffer of contiguous physical memory here, or can let the 
  258. // MDD try to allocate the memory from system RAM.  In our case, let the MDD do it.
  259. pobMem = HcdMdd_CreateMemoryObject(gcTotalAvailablePhysicalMemory, gcHighPriorityPhysicalMemory, NULL,NULL); 
  260. if(pobMem)
  261. {
  262. RETAILMSG(1,(TEXT("OHCD: Memory Objectrn")));
  263. pobOhcd = HcdMdd_CreateHcdObject(pPddObject, pobMem, szDriverRegKey, ioPortBase, dwSysIntr);
  264. fResult = pobOhcd ? TRUE : FALSE;
  265. }
  266. else
  267. fResult = FALSE;
  268. if (!fResult)
  269. {
  270. if (pobOhcd)
  271. HcdMdd_DestroyHcdObject(pobOhcd);
  272. if (pobMem)
  273. HcdMdd_DestroyMemoryObject(pobMem);
  274. pobOhcd = NULL;
  275. pobMem = NULL;
  276. RETAILMSG(1, (TEXT("--InitializeOHCI FAILED!!!rn")));
  277.      return fResult;
  278. }
  279. }
  280. else
  281. {
  282. RETAILMSG(1, (TEXT("ConfigureOHCICard() FAILED!!!rn")));
  283. return fResult;
  284. }
  285. pPddObject->lpvMemoryObject = pobMem;
  286. pPddObject->lpvOhcdMddObject = pobOhcd;
  287. RETAILMSG(1, (TEXT("--InitializeOHCIrn")));
  288.     
  289. return fResult;
  290. }
  291. /* OhcdPdd_Init
  292.  *
  293.  *   PDD Entry point - called at system init to detect and configure OHCI card.
  294.  *
  295.  * Return Value:
  296.  *   Return pointer to PDD specific data structure, or NULL if error.
  297.  */
  298. extern DWORD 
  299. HcdPdd_Init(DWORD dwContext) // IN - Pointer to context value. For device.exe, this is a string 
  300. //      indicating our active registry key.
  301. {
  302. SOhcdPdd *  pPddObject = malloc(sizeof(SOhcdPdd));
  303. BOOL        fRet = FALSE;
  304. RETAILMSG(1, (TEXT("USB:OhcdPdd_Initrn")));    
  305. fRet = InitializeOHCI(pPddObject, (LPCWSTR)dwContext);
  306. if(!fRet)
  307. {
  308. free(pPddObject);
  309. pPddObject = NULL;
  310. }
  311.     
  312. return (DWORD)pPddObject;
  313. }
  314. /* OhcdPdd_CheckConfigPower
  315.  *
  316.  *    Check power required by specific device configuration and return whether it
  317.  *    can be supported on this platform.  For CEPC, this is trivial, just limit to
  318.  *    the 500mA requirement of USB.  For battery powered devices, this could be 
  319.  *    more sophisticated, taking into account current battery status or other info.
  320.  *
  321.  * Return Value:
  322.  *    Return TRUE if configuration can be supported, FALSE if not.
  323.  */
  324. extern BOOL HcdPdd_CheckConfigPower(UCHAR bPort,         // IN - Port number
  325. DWORD dwCfgPower,    // IN - Power required by configuration
  326. DWORD dwTotalPower)  // IN - Total power currently in use on port
  327. {
  328. return ((dwCfgPower + dwTotalPower) > 500) ? FALSE : TRUE;
  329. }
  330. extern void HcdPdd_PowerUp(DWORD hDeviceContext)
  331. {
  332. SOhcdPdd * pPddObject = (SOhcdPdd *)hDeviceContext;
  333. HcdMdd_PowerUp(pPddObject->lpvOhcdMddObject);
  334. return;
  335. }
  336. extern void HcdPdd_PowerDown(DWORD hDeviceContext)
  337. {
  338. SOhcdPdd * pPddObject = (SOhcdPdd *)hDeviceContext;
  339. HcdMdd_PowerDown(pPddObject->lpvOhcdMddObject);
  340. return;
  341. }
  342. extern BOOL HcdPdd_Deinit(DWORD hDeviceContext)
  343. {
  344. SOhcdPdd * pPddObject = (SOhcdPdd *)hDeviceContext;
  345. if(pPddObject->lpvOhcdMddObject)
  346. HcdMdd_DestroyHcdObject(pPddObject->lpvOhcdMddObject);
  347. if(pPddObject->lpvMemoryObject)
  348. HcdMdd_DestroyMemoryObject(pPddObject->lpvMemoryObject);
  349. return TRUE;
  350. }
  351. extern DWORD HcdPdd_Open(DWORD hDeviceContext, DWORD AccessCode, DWORD ShareMode)
  352. {
  353. UnusedParameter(hDeviceContext);
  354. UnusedParameter(AccessCode);
  355. UnusedParameter(ShareMode);
  356. return 1; // we can be opened, but only once!
  357. }
  358. extern BOOL HcdPdd_Close(DWORD hOpenContext)
  359. {
  360. UnusedParameter(hOpenContext);
  361. return TRUE;
  362. }
  363. extern DWORD HcdPdd_Read(DWORD hOpenContext, LPVOID pBuffer, DWORD Count)
  364. {
  365. UnusedParameter(hOpenContext);
  366. UnusedParameter(pBuffer);
  367. UnusedParameter(Count);
  368. return (DWORD)-1; // an error occured
  369. }
  370. extern DWORD HcdPdd_Write(DWORD hOpenContext, LPCVOID pSourceBytes, DWORD NumberOfBytes)
  371. {
  372. UnusedParameter(hOpenContext);
  373. UnusedParameter(pSourceBytes);
  374. UnusedParameter(NumberOfBytes);
  375. return (DWORD)-1;
  376. }
  377. extern DWORD HcdPdd_Seek(DWORD hOpenContext, LONG Amount, DWORD Type)
  378. {
  379. UnusedParameter(hOpenContext);
  380. UnusedParameter(Amount);
  381. UnusedParameter(Type);
  382. return (DWORD)-1;
  383. }
  384. extern BOOL HcdPdd_IOControl(DWORD hOpenContext, DWORD dwCode, PBYTE pBufIn,
  385.         DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut, PDWORD pdwActualOut)
  386. {
  387. UnusedParameter(hOpenContext);
  388. UnusedParameter(dwCode);
  389. UnusedParameter(pBufIn);
  390. UnusedParameter(dwLenIn);
  391. UnusedParameter(pBufOut);
  392. UnusedParameter(dwLenOut);
  393. UnusedParameter(pdwActualOut);
  394. return FALSE;
  395. }
  396. extern void HcdPdd_InitiatePowerUp(void)
  397. {
  398. return;
  399. }