Source code of Windows XP (NT5)
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.

429 lines
15 KiB

  1. /*
  2. (C) Copyright 1999
  3. All rights reserved.
  4. Portions of this software are:
  5. (C) Copyright 1995 TriplePoint, Inc. -- http://www.TriplePoint.com
  6. License to use this software is granted under the same terms
  7. outlined in the Microsoft Windows Device Driver Development Kit.
  8. (C) Copyright 1992 Microsoft Corp. -- http://www.Microsoft.com
  9. License to use this software is granted under the terms outlined in
  10. the Microsoft Windows Device Driver Development Kit.
  11. @doc INTERNAL Interrupt Interrupt_c
  12. @module Interrupt.c |
  13. This module implements the Miniport interrupt processing routines and
  14. asynchronous processing routines.
  15. The sample driver does not support physical hardware, so there is no need
  16. for the typical interrupt handler routines. However, the driver does
  17. have an asynchronous event handler which is contained in this module.
  18. @comm
  19. This module is very dependent on the hardware/firmware interface and should
  20. be looked at whenever changes to these interfaces occur.
  21. @head3 Contents |
  22. @index class,mfunc,func,msg,mdata,struct,enum | Interupt_c
  23. @end
  24. */
  25. #define __FILEID__ INTERRUPT_OBJECT_TYPE
  26. // Unique file ID for error logging
  27. #include "Miniport.h" // Defines all the miniport objects
  28. #if defined(NDIS_LCODE)
  29. # pragma NDIS_LCODE // Windows 9x wants this code locked down!
  30. # pragma NDIS_LDATA
  31. #endif
  32. /* @doc EXTERNAL INTERNAL Interupt Interupt_c MiniportCheckForHang
  33. @func
  34. <f MiniportCheckForHang> reports the state of the network interface card.
  35. @comm
  36. The NDIS library calls <f MiniportCheckForHang> once every two seconds to
  37. check the state of the network interface card. If this function returns
  38. TRUE, the NDIS library then attempts to reset the NIC by calling
  39. <f MiniportReset>. <f MiniportCheckForHang> should do nothing more than
  40. check the internal state of the NIC and return TRUE if it detects that
  41. the NIC is not operating correctly.
  42. Interrupts can be in any state when MiniportCheckForHang is called.
  43. <f Note>:
  44. If your hardware/firmware is flakey you can request that the NDIS
  45. wrapper call your MiniportReset routine by returning TRUE from this
  46. routine. For well behaved hardware/firmware you should always return
  47. FALSE from this routine.
  48. @rdesc
  49. <f MiniportCheckForHang> returns FALSE if the NIC is working properly.<nl>
  50. Otherwise, a TRUE return value indicates that the NIC needs to be reset.
  51. */
  52. BOOLEAN MiniportCheckForHang(
  53. IN PMINIPORT_ADAPTER_OBJECT pAdapter // @parm
  54. // A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance.
  55. )
  56. {
  57. DBG_FUNC("MiniportCheckForHang")
  58. // If your hardware can lockup, then you can return TRUE here.
  59. // If you return TRUE, your MiniportReset routine will be called.
  60. return (FALSE);
  61. }
  62. #if defined(CARD_REQUEST_ISR)
  63. #if (CARD_REQUEST_ISR == FALSE)
  64. /* @doc EXTERNAL INTERNAL Interupt Interupt_c MiniportDisableInterrupt
  65. @func
  66. <f MiniportDisableInterrupt> disables the NIC from generating interrupts.
  67. @comm
  68. Typically, this function disables interrupts by writing a mask value
  69. specific to the network interface card.
  70. If the NIC does not support enabling and disabling interrupts, the
  71. miniport driver must register a miniport interrupt service routine with
  72. the NDIS library. Within the interrupt service routine, the miniport
  73. driver must acknowledge and save the interrupt information.
  74. In some cases, the NIC must be in a certain state for
  75. <f MiniportDisableInterrupt> to execute correctly. In these cases, the
  76. miniport driver must encapsulate within a function all portions of the
  77. driver which violate the required state and which can be called when
  78. interrupts are enabled. Then the miniport driver must call the
  79. encapsulated code through the NdisMSynchronizeWithInterrupt function.
  80. For example, on some network interface cards, the I/O ports are paged
  81. and must be set to page 0 for the deferred processing routine to run
  82. correctly. With this kind of NIC, the DPC must be synchronized with
  83. interrupts.
  84. Interrupts can be in any state when <f MiniportDisableInterrupt> is
  85. called.
  86. */
  87. void MiniportDisableInterrupt(
  88. IN PMINIPORT_ADAPTER_OBJECT pAdapter // @parm
  89. // A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance.
  90. )
  91. {
  92. DBG_FUNC("MiniportDisableInterrupt")
  93. DBG_ERROR(pAdapter,("This should not be called!\n"));
  94. }
  95. /* @doc EXTERNAL INTERNAL Interupt Interupt_c MiniportEnableInterrupt
  96. @func
  97. <f MiniportEnableInterrupt> enables the NIC to generate interrupts.
  98. @comm
  99. Typically, this function enables interrupts by writing a mask value
  100. specific to the network interface card.
  101. If the NIC does not support enabling and disabling interrupts, the
  102. miniport driver must register a miniport interrupt service routine with
  103. the NDIS library. Within the interrupt service routine, the miniport
  104. driver must acknowledge and save the interrupt information.
  105. Interrupts can be in any state when <f MiniportEnableInterrupt> is called.
  106. */
  107. void MiniportEnableInterrupt(
  108. IN PMINIPORT_ADAPTER_OBJECT pAdapter // @parm
  109. // A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance.
  110. )
  111. {
  112. DBG_FUNC("MiniportEnableInterrupt")
  113. DBG_ERROR(pAdapter,("This should not be called!\n"));
  114. }
  115. #else // !(CARD_REQUEST_ISR == FALSE)
  116. /* @doc EXTERNAL INTERNAL Interupt Interupt_c MiniportISR
  117. @func
  118. <f MiniportISR> is the miniport driver's interrupt service routine. This
  119. function runs at a high priority in response to an interrupt. The driver
  120. should do as little work as possible in this function. It should set
  121. <p InterruptRecognized> to TRUE if it recognizes the interrupt as
  122. belonging to its network interface card, or FALSE otherwise. It should
  123. return FALSE as soon as possible if the interrupt is not generated by
  124. its NIC. It should set <f QueueMiniportHandleInterrupt> to TRUE if a
  125. call to <f MiniportHandleInterrupt> at a lower priority is required to
  126. complete the handling of the interrupt.
  127. <f Note>: <f MiniportISR> must not call any support functions in the NDIS
  128. interface library or the transport driver.
  129. @comm
  130. <f MiniportISR> is called in the following cases:<nl>
  131. o The NIC generates an interrupt when there is an outstanding call to
  132. <f MiniportInitialize>.
  133. o The miniport driver supports sharing its interrupt line with another
  134. NIC.
  135. o The miniport driver specifies that this function must be called for
  136. every interrupt.
  137. <f Note>: A deferred processing routine is not queued if the miniport
  138. driver is currently executing <f MiniportHalt> or <f MiniportInitialize>.
  139. */
  140. void MiniportISR(
  141. OUT PBOOLEAN InterruptRecognized, // @parm
  142. // If the miniport driver is sharing an interrupt line and it detects
  143. // that the interrupt came from its NIC, <f MiniportISR> should set
  144. // this parameter to TRUE.
  145. OUT PBOOLEAN QueueMiniportHandleInterrupt, // @parm
  146. // If the miniport driver is sharing an interrupt line and if
  147. // <f MiniportHandleInterrupt> must be called to complete handling of
  148. // the interrupt, <f MiniportISR> should set this parameter to TRUE.
  149. IN PMINIPORT_ADAPTER_OBJECT pAdapter // @parm
  150. // A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance.
  151. )
  152. {
  153. DBG_FUNC("MiniportISR")
  154. ULONG InterruptStatus;
  155. // TODO: Get the interrupt status from your card.
  156. if ((InterruptStatus = pAdapter->TODO) == 0)
  157. {
  158. *InterruptRecognized =
  159. *QueueMiniportHandleInterrupt = FALSE;
  160. }
  161. else
  162. {
  163. pAdapter->pCard->InterruptStatus = InterruptStatus;
  164. *InterruptRecognized =
  165. *QueueMiniportHandleInterrupt = TRUE;
  166. }
  167. }
  168. #endif // (CARD_REQUEST_ISR == FALSE)
  169. #endif // defined(CARD_REQUEST_ISR)
  170. /* @doc EXTERNAL INTERNAL Interupt Interupt_c MiniportHandleInterrupt
  171. @func
  172. <f MiniportHandleInterrupt> is called by the deferred processing routine
  173. in the NDIS library to process an interrupt.
  174. @comm
  175. During a call to <f MiniportHandleInterrupt>, the miniport driver should
  176. handle all outstanding interrupts and start any new operations.
  177. Interrupts are disabled during a call to <f MiniportHandleInterrupt>.
  178. */
  179. void MiniportHandleInterrupt(
  180. IN PMINIPORT_ADAPTER_OBJECT pAdapter // @parm
  181. // A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance.
  182. )
  183. {
  184. DBG_FUNC("MiniportHandleInterrupt")
  185. PBCHANNEL_OBJECT pBChannel;
  186. // A Pointer to one of our <t BCHANNEL_OBJECT>'s.
  187. ULONG BChannelIndex;
  188. // Index into the pBChannelArray.
  189. /*
  190. // Process NIC interrupt.
  191. */
  192. CardInterruptHandler(pAdapter->pCard);
  193. /*
  194. // Walk through all the links to see if there is any post-proccessing
  195. // that needs to be done.
  196. */
  197. for (BChannelIndex = 0; BChannelIndex < pAdapter->NumBChannels; ++BChannelIndex)
  198. {
  199. pBChannel = GET_BCHANNEL_FROM_INDEX(pAdapter, BChannelIndex);
  200. if (pBChannel->IsOpen)
  201. {
  202. /*
  203. // Indicate a receive complete if it's needed.
  204. */
  205. if (pBChannel->NeedReceiveCompleteIndication)
  206. {
  207. pBChannel->NeedReceiveCompleteIndication = FALSE;
  208. /*
  209. // Indicate receive complete to the NDIS wrapper.
  210. */
  211. DBG_RXC(pAdapter, pBChannel->ObjectID);
  212. NdisMCoReceiveComplete(pAdapter->MiniportAdapterHandle);
  213. }
  214. }
  215. }
  216. /*
  217. // Indicate a status complete if it's needed.
  218. */
  219. if (pAdapter->NeedStatusCompleteIndication)
  220. {
  221. pAdapter->NeedStatusCompleteIndication = FALSE;
  222. NdisMIndicateStatusComplete(pAdapter->MiniportAdapterHandle);
  223. }
  224. }
  225. /* @doc EXTERNAL INTERNAL Interupt Interupt_c MiniportTimer
  226. @func
  227. <f MiniportTimer> is a required function if a Minipor's NIC does not
  228. generate interrupts. Otherwise, one or more <f MiniportTimer> functions
  229. are optional.
  230. The driver of a NIC that does not generate interrupts must have a <f
  231. MiniportTimer> function to poll the state of the NIC. After such a
  232. Miniport's MiniportInitialize function sets up the driver-allocated timer
  233. object with NdisMInitializeTimer, a call to NdisMSetPeriodicTimer causes
  234. the <f MiniportTimer> function associated with the timer object to be run
  235. repeatedly and automatically at the interval specified by
  236. MillisecondsPeriod. Such a polling <f MiniportTimer> function monitors the
  237. state of the NIC to determine when to make indications, when to complete
  238. pending sends, and so forth. In effect, such a polling <f MiniportTimer>
  239. function has the same functionality as the MiniportHandleInterrupt
  240. function in the driver of a NIC that does generate interrupts.
  241. By contrast, calling NdisMSetTimer causes the <f MiniportTimer> function
  242. associated with the timer object to be run once when the given
  243. MillisecondsToDelay expires. Such a <f MiniportTimer> function usually
  244. performs some driver-determined action if a particular operation times
  245. out.
  246. If either type of <f MiniportTimer> function shares resources with other
  247. driver functions, the driver should synchronize access to those resources
  248. with a spin lock.
  249. A Miniport can have more than one <f MiniportTimer> function at the
  250. discretion of the driver writer. Each such <f MiniportTimer> function must
  251. be associated with a driver-allocated and initialized timer object.
  252. A call to NdisMCancelTimer cancels execution of a nonpolling
  253. <f MiniportTimer> function, provided that the interval passed in the
  254. immediately preceding call to NdisMSetTimer has not yet expired. After a
  255. call to NdisMSetPeriodicTimer, a call to NdisMSetTimer or NdisMCancelTimer
  256. with the same timer object disables a polling <f MiniportTimer> function:
  257. either the <f MiniportTimer> function runs once, or it is canceled.
  258. The MiniportHalt function of any driver with a <f MiniportTimer> function
  259. should call NdisMCancelTimer to ensure that the <f MiniportTimer> function
  260. does not attempt to access resources that MiniportHalt has already
  261. released.
  262. By default, <f MiniportTimer> runs at IRQL DISPATCH_LEVEL.
  263. */
  264. void MiniportTimer(
  265. IN PVOID SystemSpecific1, // @parm
  266. // UNREFERENCED_PARAMETER
  267. IN PMINIPORT_ADAPTER_OBJECT pAdapter, // @parm
  268. // A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance.
  269. IN PVOID SystemSpecific2, // @parm
  270. // UNREFERENCED_PARAMETER
  271. IN PVOID SystemSpecific3 // @parm
  272. // UNREFERENCED_PARAMETER
  273. )
  274. {
  275. DBG_FUNC("MiniportTimer")
  276. // DBG_ENTER(pAdapter);
  277. /*
  278. // If this is a nested callback, just return, and we'll loop back to
  279. // the DoItAgain before leaving the outermost callback.
  280. */
  281. if (++(pAdapter->NestedEventHandler) > 1)
  282. {
  283. DBG_WARNING(pAdapter,("NestedEventHandler=%d > 1\n",
  284. pAdapter->NestedEventHandler));
  285. return;
  286. }
  287. DoItAgain:
  288. #if defined(SAMPLE_DRIVER)
  289. /*
  290. // This sample driver uses timer to simulate interrupts.
  291. */
  292. MiniportHandleInterrupt(pAdapter);
  293. #else // SAMPLE_DRIVER
  294. // TODO - Add code here to handle timer interrupt events.
  295. #endif // SAMPLE_DRIVER
  296. /*
  297. // If we got a nested callback, we have to loop back around.
  298. */
  299. if (--(pAdapter->NestedEventHandler) > 0)
  300. {
  301. goto DoItAgain;
  302. }
  303. else if (pAdapter->NestedEventHandler < 0)
  304. {
  305. DBG_ERROR(pAdapter,("NestedEventHandler=%d < 0\n",
  306. pAdapter->NestedEventHandler));
  307. }
  308. // DBG_LEAVE(pAdapter);
  309. UNREFERENCED_PARAMETER(SystemSpecific1);
  310. UNREFERENCED_PARAMETER(SystemSpecific2);
  311. UNREFERENCED_PARAMETER(SystemSpecific3);
  312. }