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.

402 lines
8.5 KiB

  1. /*++
  2. Copyright (c) 1999, 2000 Microsoft Corporation
  3. Module Name:
  4. int.c
  5. Abstract:
  6. interrupt service routine
  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, 2000 Microsoft Corporation. All Rights Reserved.
  15. Revision History:
  16. 7-19-99 : created, jdunn
  17. --*/
  18. #include "common.h"
  19. BOOLEAN
  20. EHCI_InterruptService (
  21. PDEVICE_DATA DeviceData
  22. )
  23. /*++
  24. Routine Description:
  25. Arguments:
  26. Return Value:
  27. --*/
  28. {
  29. BOOLEAN usbInt;
  30. PHC_OPERATIONAL_REGISTER hcOp;
  31. ULONG enabledIrqs, frameNumber;
  32. USBSTS irqStatus;
  33. FRINDEX frameIndex;
  34. hcOp = DeviceData->OperationalRegisters;
  35. // assume it is not ours
  36. usbInt = FALSE;
  37. if (EHCI_HardwarePresent(DeviceData, FALSE) == FALSE) {
  38. return FALSE;
  39. }
  40. // get a mask of possible interrupts
  41. enabledIrqs = READ_REGISTER_ULONG(&hcOp->UsbInterruptEnable.ul);
  42. irqStatus.ul = READ_REGISTER_ULONG(&hcOp->UsbStatus.ul);
  43. // just look at the IRQ status bits
  44. irqStatus.ul &= HcInterruptStatusMask;
  45. // AND with the enabled IRQs
  46. irqStatus.ul &= enabledIrqs;
  47. // irqStatus now possibly contains bits set for any currently
  48. // enabled interrupts
  49. if (irqStatus.ul != 0) {
  50. DeviceData->IrqStatus = irqStatus.ul;
  51. WRITE_REGISTER_ULONG(&hcOp->UsbStatus.ul,
  52. irqStatus.ul);
  53. #if DBG
  54. if (irqStatus.HostSystemError) {
  55. // something has gone terribly wrong
  56. EHCI_ASSERT(DeviceData, FALSE);
  57. }
  58. #endif
  59. // This code maintains the 32-bit 1 ms frame counter
  60. // bugbug this code does not handle varaible frame list
  61. // sizes
  62. frameIndex.ul = READ_REGISTER_ULONG(&hcOp->UsbFrameIndex.ul);
  63. frameNumber = (ULONG) frameIndex.FrameListCurrentIndex;
  64. // shut off the microframes
  65. frameNumber >>= 3;
  66. // did the sign bit change ?
  67. if ((DeviceData->LastFrame ^ frameNumber) & 0x0400) {
  68. // Yes
  69. DeviceData->FrameNumberHighPart += 0x0800 -
  70. ((frameNumber ^ DeviceData->FrameNumberHighPart) & 0x0400);
  71. }
  72. // remember the last frame number
  73. DeviceData->LastFrame = frameNumber;
  74. // inications are that this came from the
  75. // USB controller
  76. usbInt = TRUE;
  77. // disable all interrupts until the DPC for ISR runs
  78. //WRITE_REGISTER_ULONG(&hcOp->UsbInterruptEnable.ul,
  79. // 0);
  80. }
  81. return usbInt;
  82. }
  83. VOID
  84. EHCI_InterruptDpc (
  85. PDEVICE_DATA DeviceData,
  86. BOOLEAN EnableInterrupts
  87. )
  88. /*++
  89. Routine Description:
  90. process an interrupt
  91. Arguments:
  92. Return Value:
  93. --*/
  94. {
  95. PHC_OPERATIONAL_REGISTER hcOp;
  96. USBSTS irqStatus, tmp;
  97. FRINDEX frameIndex;
  98. hcOp = DeviceData->OperationalRegisters;
  99. // ack all status bits asserted now
  100. //tmp.ul = READ_REGISTER_ULONG(&hcOp->UsbStatus.ul);
  101. tmp.ul = DeviceData->IrqStatus;
  102. DeviceData->IrqStatus = 0;
  103. frameIndex.ul = READ_REGISTER_ULONG(&hcOp->UsbFrameIndex.ul);
  104. LOGENTRY(DeviceData, G, '_idp', tmp.ul, 0,
  105. frameIndex.ul);
  106. //WRITE_REGISTER_ULONG(&hcOp->UsbStatus.ul,
  107. // tmp.ul);
  108. // now process status bits aserted,
  109. // just look at the IRQ status bits
  110. irqStatus.ul = tmp.ul & HcInterruptStatusMask;
  111. // AND with the enabled IRQs, these are the interrupts
  112. // we are interested in
  113. irqStatus.ul &= DeviceData->EnabledInterrupts.ul;
  114. if (irqStatus.UsbInterrupt ||
  115. irqStatus.UsbError ||
  116. irqStatus.IntOnAsyncAdvance) {
  117. LOGENTRY(DeviceData, G, '_iEP', irqStatus.ul, 0, 0);
  118. USBPORT_INVALIDATE_ENDPOINT(DeviceData, NULL);
  119. }
  120. if (irqStatus.PortChangeDetect) {
  121. USBPORT_INVALIDATE_ROOTHUB(DeviceData);
  122. }
  123. // since ehci does not provide a way to globally mask
  124. // interrupts we must mask off all interrupts in our ISR.
  125. // When the ISR DPC completes we re-enable the set of
  126. // currently enabled interrupts.
  127. if (EnableInterrupts) {
  128. LOGENTRY(DeviceData, G, '_iEE', 0, 0, 0);
  129. WRITE_REGISTER_ULONG(&hcOp->UsbInterruptEnable.ul,
  130. DeviceData->EnabledInterrupts.ul);
  131. }
  132. }
  133. VOID
  134. USBMPFN
  135. EHCI_DisableInterrupts(
  136. PDEVICE_DATA DeviceData
  137. )
  138. /*++
  139. Routine Description:
  140. Arguments:
  141. Return Value:
  142. --*/
  143. {
  144. PHC_OPERATIONAL_REGISTER hcOp = NULL;
  145. hcOp = DeviceData->OperationalRegisters;
  146. // mask off all interrupts
  147. WRITE_REGISTER_ULONG(&hcOp->UsbInterruptEnable.ul,
  148. 0);
  149. }
  150. VOID
  151. USBMPFN
  152. EHCI_FlushInterrupts(
  153. PDEVICE_DATA DeviceData
  154. )
  155. /*++
  156. Routine Description:
  157. Arguments:
  158. Return Value:
  159. --*/
  160. {
  161. PHC_OPERATIONAL_REGISTER hcOp = NULL;
  162. USBSTS irqStatus;
  163. hcOp = DeviceData->OperationalRegisters;
  164. // flush any outstanding interrupts
  165. irqStatus.ul = READ_REGISTER_ULONG(&hcOp->UsbStatus.ul);
  166. WRITE_REGISTER_ULONG(&hcOp->UsbStatus.ul,
  167. irqStatus.ul);
  168. }
  169. VOID
  170. USBMPFN
  171. EHCI_EnableInterrupts(
  172. PDEVICE_DATA DeviceData
  173. )
  174. /*++
  175. Routine Description:
  176. Arguments:
  177. Return Value:
  178. --*/
  179. {
  180. PHC_OPERATIONAL_REGISTER hcOp = NULL;
  181. hcOp = DeviceData->OperationalRegisters;
  182. // activate the controllers interrupt
  183. WRITE_REGISTER_ULONG(&hcOp->UsbInterruptEnable.ul,
  184. DeviceData->EnabledInterrupts.ul);
  185. }
  186. VOID
  187. EHCI_RH_DisableIrq(
  188. PDEVICE_DATA DeviceData
  189. )
  190. {
  191. PHC_OPERATIONAL_REGISTER hcOp = NULL;
  192. USBINTR enabledIrqs;
  193. hcOp = DeviceData->OperationalRegisters;
  194. // clear the port change interrupt
  195. enabledIrqs.ul =
  196. READ_REGISTER_ULONG(&hcOp->UsbInterruptEnable.ul);
  197. enabledIrqs.PortChangeDetect =
  198. DeviceData->EnabledInterrupts.PortChangeDetect = 0;
  199. if (enabledIrqs.UsbInterrupt) {
  200. WRITE_REGISTER_ULONG(&hcOp->UsbInterruptEnable.ul,
  201. enabledIrqs.ul);
  202. }
  203. }
  204. VOID
  205. EHCI_RH_EnableIrq(
  206. PDEVICE_DATA DeviceData
  207. )
  208. {
  209. PHC_OPERATIONAL_REGISTER hcOp = NULL;
  210. USBINTR enabledIrqs;
  211. hcOp = DeviceData->OperationalRegisters;
  212. // enable the port change interrupt
  213. enabledIrqs.ul =
  214. READ_REGISTER_ULONG(&hcOp->UsbInterruptEnable.ul);
  215. enabledIrqs.PortChangeDetect =
  216. DeviceData->EnabledInterrupts.PortChangeDetect = 1;
  217. if (enabledIrqs.UsbInterrupt) {
  218. WRITE_REGISTER_ULONG(&hcOp->UsbInterruptEnable.ul,
  219. enabledIrqs.ul);
  220. }
  221. }
  222. VOID
  223. EHCI_InterruptNextSOF(
  224. PDEVICE_DATA DeviceData
  225. )
  226. {
  227. PHC_OPERATIONAL_REGISTER hcOp = NULL;
  228. USBCMD cmd;
  229. hcOp = DeviceData->OperationalRegisters;
  230. // before we use the doorbell enable the async list
  231. EHCI_EnableAsyncList(DeviceData);
  232. cmd.ul = READ_REGISTER_ULONG(&hcOp->UsbCommand.ul);
  233. cmd.IntOnAsyncAdvanceDoorbell = 1;
  234. WRITE_REGISTER_ULONG(&hcOp->UsbCommand.ul,
  235. cmd.ul);
  236. // TEST_TRAP();
  237. }
  238. ULONG
  239. EHCI_Get32BitFrameNumber(
  240. PDEVICE_DATA DeviceData
  241. )
  242. {
  243. ULONG highPart, currentFrame, frameNumber;
  244. PHC_OPERATIONAL_REGISTER hcOp = NULL;
  245. FRINDEX frameIndex;
  246. hcOp = DeviceData->OperationalRegisters;
  247. // get Hcd's high part of frame number
  248. highPart = DeviceData->FrameNumberHighPart;
  249. // bugbug this code does not handle varaible frame list
  250. // sizes
  251. frameIndex.ul = READ_REGISTER_ULONG(&hcOp->UsbFrameIndex.ul);
  252. frameNumber = (ULONG) frameIndex.FrameListCurrentIndex;
  253. // shift off the microframes
  254. frameNumber >>= 3;
  255. currentFrame = ((frameNumber & 0x0bff) | highPart) +
  256. ((frameNumber ^ highPart) & 0x0400);
  257. return currentFrame;
  258. }
  259. BOOLEAN
  260. EHCI_HardwarePresent(
  261. PDEVICE_DATA DeviceData,
  262. BOOLEAN Notify
  263. )
  264. {
  265. ULONG tmp;
  266. PHC_OPERATIONAL_REGISTER hcOp;
  267. hcOp = DeviceData->OperationalRegisters;
  268. tmp = READ_REGISTER_ULONG(&hcOp->UsbCommand.ul);
  269. if (tmp == 0xffffffff) {
  270. if (Notify) {
  271. USBPORT_INVALIDATE_CONTROLLER(DeviceData, UsbMpControllerRemoved);
  272. }
  273. return FALSE;
  274. }
  275. return TRUE;
  276. }