Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

432 lines
9.2 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. roothub.c
  5. Abstract:
  6. miniport root hub
  7. Environment:
  8. kernel mode only
  9. Notes:
  10. THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  11. KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  12. IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  13. PURPOSE.
  14. Copyright (c) 1999 Microsoft Corporation. All Rights Reserved.
  15. Revision History:
  16. 2-19-99 : created, jdunn
  17. implements the following miniport functions:
  18. MINIPORT_RH_GetStatus
  19. MINIPORT_RH_GetPortStatus
  20. MINIPORT_RH_GethubStatus
  21. MINIPORT_RH_SetFeaturePortReset
  22. MINIPORT_RH_SetFeaturePortSuspend
  23. MINIPORT_RH_SetFeaturePortPower
  24. MINIPORT_RH_ClearFeaturePortEnable
  25. MINIPORT_RH_ClearFeaturePortSuspend
  26. MINIPORT_RH_ClearFeaturePortPower
  27. MINIPORT_RH_ClearFeaturePortConnectChange
  28. MINIPORT_RH_ClearFeaturePortResetChange
  29. MINIPORT_RH_ClearFeaturePortEnableChange
  30. MINIPORT_RH_ClearFeaturePortSuspendChange
  31. MINIPORT_RH_ClearFeaturePortOvercurrentChange
  32. --*/
  33. #include "common.h"
  34. VOID
  35. OHCI_RH_GetRootHubData(
  36. PDEVICE_DATA DeviceData,
  37. PROOTHUB_DATA HubData
  38. )
  39. /*++
  40. return info about the root hub
  41. --*/
  42. {
  43. HC_RH_DESCRIPTOR_A descrA;
  44. PHC_OPERATIONAL_REGISTER hc;
  45. hc = DeviceData->HC;
  46. descrA.ul = OHCI_ReadRhDescriptorA(DeviceData);
  47. OHCI_ASSERT(DeviceData, (descrA.ul) && (!(descrA.ul & HcDescA_RESERVED)));
  48. HubData->NumberOfPorts = descrA.s.NumberDownstreamPorts;
  49. DeviceData->NumberOfPorts = HubData->NumberOfPorts;
  50. HubData->HubCharacteristics.us = (USHORT)descrA.s.HubChars;
  51. HubData->PowerOnToPowerGood = descrA.s.PowerOnToPowerGoodTime;
  52. // This may upset the stopwatch fanatics, but it appears that a minimum
  53. // delay is necessary here in some cases. One example being resuming from
  54. // hibernation on a 7800 with a USB IntelliMouse Explorer attached.
  55. // (The delay happens in the hub driver after powering on each port).
  56. //
  57. HubData->PowerOnToPowerGood = max(descrA.s.PowerOnToPowerGoodTime, 25);
  58. // OHCI controllers generally use the 1.0 USB spec.
  59. // HubChars were revised in 1.1 so we need to do some
  60. // mapping.
  61. // We will assume it is gang switched unless the port
  62. // power switching bit is set
  63. HubData->HubCharacteristics.PowerSwitchType =
  64. USBPORT_RH_POWER_SWITCH_GANG;
  65. if (descrA.ul & HcDescA_PowerSwitchingModePort) {
  66. HubData->HubCharacteristics.PowerSwitchType =
  67. USBPORT_RH_POWER_SWITCH_PORT;
  68. }
  69. // this value is the current consumed by the hub
  70. // brains, for the embedded hub this doesn't make
  71. // much sense.
  72. // so we report zero.
  73. //
  74. HubData->HubControlCurrent = 0;
  75. }
  76. USB_MINIPORT_STATUS
  77. OHCI_RH_GetStatus(
  78. PDEVICE_DATA DeviceData,
  79. PUSHORT Status
  80. )
  81. /*++
  82. get the device status
  83. --*/
  84. {
  85. // the root hub is self powered
  86. *Status = USB_GETSTATUS_SELF_POWERED;
  87. return USBMP_STATUS_SUCCESS;
  88. }
  89. USB_MINIPORT_STATUS
  90. OHCI_RH_ClearFeaturePortEnable (
  91. PDEVICE_DATA DeviceData,
  92. USHORT PortNumber
  93. )
  94. {
  95. PHC_OPERATIONAL_REGISTER hc;
  96. hc = DeviceData->HC;
  97. WRITE_REGISTER_ULONG(&hc->HcRhPortStatus[PortNumber-1], HcRhPS_ClearPortEnable);
  98. return USBMP_STATUS_SUCCESS;
  99. }
  100. USB_MINIPORT_STATUS
  101. OHCI_RH_ClearFeaturePortPower (
  102. PDEVICE_DATA DeviceData,
  103. USHORT PortNumber
  104. )
  105. {
  106. PHC_OPERATIONAL_REGISTER hc;
  107. hc = DeviceData->HC;
  108. WRITE_REGISTER_ULONG(&hc->HcRhPortStatus[PortNumber-1], HcRhPS_ClearPortPower);
  109. return USBMP_STATUS_SUCCESS;
  110. }
  111. USB_MINIPORT_STATUS
  112. OHCI_RH_GetPortStatus(
  113. PDEVICE_DATA DeviceData,
  114. USHORT PortNumber,
  115. PRH_PORT_STATUS portStatus
  116. )
  117. /*++
  118. get the status of a partuclar port
  119. --*/
  120. {
  121. PHC_OPERATIONAL_REGISTER hc;
  122. PULONG pulRegister;
  123. ULONG statusAsUlong;
  124. ULONG i;
  125. hc = DeviceData->HC;
  126. // hw array is zero based
  127. //
  128. pulRegister = &hc->HcRhPortStatus[PortNumber-1];
  129. //
  130. // by coincedence rhStatus register defined in OHCI is an
  131. // exact match of the RH_PORT_STATUS define in the USB core
  132. // spec.
  133. //
  134. // If this register reads as all zero or any of the reserved bits are set
  135. // then try reading the register again. This is a workaround for some
  136. // early revs of the AMD K7 chipset, which can sometimes return bogus values
  137. // if the root hub registers are read while the host controller is
  138. // performing PCI bus master ED & TD reads.
  139. //
  140. for (i = 0; i < 10; i++)
  141. {
  142. statusAsUlong = READ_REGISTER_ULONG(pulRegister);
  143. if ((statusAsUlong) && (!(statusAsUlong & HcRhPS_RESERVED)))
  144. {
  145. break;
  146. }
  147. else
  148. {
  149. KeStallExecutionProcessor(5);
  150. }
  151. }
  152. portStatus->ul = statusAsUlong;
  153. return USBMP_STATUS_SUCCESS;
  154. }
  155. USB_MINIPORT_STATUS
  156. OHCI_RH_SetFeaturePortReset(
  157. PDEVICE_DATA DeviceData,
  158. USHORT PortNumber
  159. )
  160. /*++
  161. Put a port in reset
  162. --*/
  163. {
  164. PHC_OPERATIONAL_REGISTER hc;
  165. hc = DeviceData->HC;
  166. WRITE_REGISTER_ULONG(&hc->HcRhPortStatus[PortNumber-1], HcRhPS_SetPortReset);
  167. return USBMP_STATUS_SUCCESS;
  168. }
  169. USB_MINIPORT_STATUS
  170. OHCI_RH_SetFeaturePortSuspend(
  171. PDEVICE_DATA DeviceData,
  172. USHORT PortNumber
  173. )
  174. /*++
  175. Put a port in suspend
  176. --*/
  177. {
  178. PHC_OPERATIONAL_REGISTER hc;
  179. hc = DeviceData->HC;
  180. WRITE_REGISTER_ULONG(&hc->HcRhPortStatus[PortNumber-1], HcRhPS_SetPortSuspend);
  181. return USBMP_STATUS_SUCCESS;
  182. }
  183. USB_MINIPORT_STATUS
  184. OHCI_RH_ClearFeaturePortSuspend(
  185. PDEVICE_DATA DeviceData,
  186. USHORT PortNumber
  187. )
  188. /*++
  189. --*/
  190. {
  191. PHC_OPERATIONAL_REGISTER hc;
  192. hc = DeviceData->HC;
  193. WRITE_REGISTER_ULONG(&hc->HcRhPortStatus[PortNumber-1], HcRhPS_ClearPortSuspend);
  194. return USBMP_STATUS_SUCCESS;
  195. }
  196. USB_MINIPORT_STATUS
  197. OHCI_RH_ClearFeaturePortSuspendChange(
  198. PDEVICE_DATA DeviceData,
  199. USHORT PortNumber
  200. )
  201. /*++
  202. --*/
  203. {
  204. PHC_OPERATIONAL_REGISTER hc;
  205. hc = DeviceData->HC;
  206. WRITE_REGISTER_ULONG(&hc->HcRhPortStatus[PortNumber-1], HcRhPS_ClearPortSuspendStatusChange);
  207. return USBMP_STATUS_SUCCESS;
  208. }
  209. USB_MINIPORT_STATUS
  210. OHCI_RH_ClearFeaturePortOvercurrentChange(
  211. PDEVICE_DATA DeviceData,
  212. USHORT PortNumber
  213. )
  214. /*++
  215. --*/
  216. {
  217. PHC_OPERATIONAL_REGISTER hc;
  218. hc = DeviceData->HC;
  219. if (PortNumber == 0) {
  220. WRITE_REGISTER_ULONG(&hc->HcRhStatus, HcRhS_ClearOverCurrentIndicatorChange);
  221. } else {
  222. WRITE_REGISTER_ULONG(&hc->HcRhPortStatus[PortNumber-1], HcRhPS_ClearPortOverCurrentChange);
  223. }
  224. return USBMP_STATUS_SUCCESS;
  225. }
  226. USB_MINIPORT_STATUS
  227. OHCI_RH_SetFeaturePortPower(
  228. PDEVICE_DATA DeviceData,
  229. USHORT PortNumber
  230. )
  231. /*++
  232. --*/
  233. {
  234. PHC_OPERATIONAL_REGISTER hc;
  235. hc = DeviceData->HC;
  236. WRITE_REGISTER_ULONG(&hc->HcRhPortStatus[PortNumber-1], HcRhPS_SetPortPower);
  237. return USBMP_STATUS_SUCCESS;
  238. }
  239. USB_MINIPORT_STATUS
  240. OHCI_RH_SetFeaturePortEnable(
  241. PDEVICE_DATA DeviceData,
  242. USHORT PortNumber
  243. )
  244. /*++
  245. --*/
  246. {
  247. PHC_OPERATIONAL_REGISTER hc;
  248. hc = DeviceData->HC;
  249. WRITE_REGISTER_ULONG(&hc->HcRhPortStatus[PortNumber-1], HcRhPS_SetPortEnable);
  250. return USBMP_STATUS_SUCCESS;
  251. }
  252. USB_MINIPORT_STATUS
  253. OHCI_RH_ClearFeaturePortConnectChange(
  254. PDEVICE_DATA DeviceData,
  255. USHORT PortNumber
  256. )
  257. /*++
  258. --*/
  259. {
  260. PHC_OPERATIONAL_REGISTER hc;
  261. hc = DeviceData->HC;
  262. WRITE_REGISTER_ULONG(&hc->HcRhPortStatus[PortNumber-1],
  263. HcRhPS_ClearConnectStatusChange);
  264. return USBMP_STATUS_SUCCESS;
  265. }
  266. USB_MINIPORT_STATUS
  267. OHCI_RH_ClearFeaturePortEnableChange(
  268. PDEVICE_DATA DeviceData,
  269. USHORT PortNumber
  270. )
  271. /*++
  272. --*/
  273. {
  274. PHC_OPERATIONAL_REGISTER hc;
  275. hc = DeviceData->HC;
  276. WRITE_REGISTER_ULONG(&hc->HcRhPortStatus[PortNumber-1],
  277. HcRhPS_ClearPortEnableStatusChange);
  278. return USBMP_STATUS_SUCCESS;
  279. }
  280. USB_MINIPORT_STATUS
  281. OHCI_RH_GetHubStatus(
  282. PDEVICE_DATA DeviceData,
  283. PRH_HUB_STATUS HubStatus
  284. )
  285. {
  286. PHC_OPERATIONAL_REGISTER hc;
  287. ULONG statusAsUlong;
  288. hc = DeviceData->HC;
  289. // we will never report a localpower change
  290. HubStatus->LocalPowerLost = 0;
  291. HubStatus->LocalPowerChange = 0;
  292. // see if we should reort an overcurrent condition
  293. //
  294. statusAsUlong =
  295. READ_REGISTER_ULONG(&hc->HcRhStatus);
  296. HubStatus->OverCurrent =
  297. (statusAsUlong & HcRhS_OverCurrentIndicator) ? 1: 0;
  298. HubStatus->OverCurrentChange =
  299. (statusAsUlong & HcRhS_OverCurrentIndicatorChange) ? 1: 0;
  300. return USBMP_STATUS_SUCCESS;
  301. }
  302. USB_MINIPORT_STATUS
  303. OHCI_RH_ClearFeaturePortResetChange(
  304. PDEVICE_DATA DeviceData,
  305. USHORT PortNumber
  306. )
  307. /*++
  308. --*/
  309. {
  310. PHC_OPERATIONAL_REGISTER hc;
  311. hc = DeviceData->HC;
  312. WRITE_REGISTER_ULONG(&hc->HcRhPortStatus[PortNumber-1],
  313. HcRhPS_ClearPortResetStatusChange);
  314. return USBMP_STATUS_SUCCESS;
  315. }