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.

330 lines
7.9 KiB

  1. /*++
  2. Copyright (c) 1996-1999 Microsoft Corporation
  3. Module Name:
  4. clstate.c
  5. Abstract:
  6. state machine for gpc client vcs
  7. Author:
  8. Yoram Bernet (yoramb) 28-Dec-1997
  9. Rajesh Sundaram (rajeshsu) 01-Aug-1998
  10. Environment:
  11. Kernel Mode
  12. Revision History:
  13. Rajesh Sundaram (rajeshsu) 04-Apr-1998 - reworked completly as another state
  14. (CL_INTERNAL_CALL_COMPLETE) added.
  15. --*/
  16. #include "psched.h"
  17. #pragma hdrstop
  18. /* External */
  19. /* Static */
  20. /* Forward */
  21. /* End Forward */
  22. /*++
  23. Routine Description:
  24. Initiate a close call on this VC and notify the GPC. Always called with the VC lock held.
  25. Return Value:
  26. None
  27. --*/
  28. VOID
  29. InternalCloseCall(
  30. PGPC_CLIENT_VC Vc
  31. )
  32. {
  33. PADAPTER Adapter = Vc->Adapter;
  34. PsDbgOut(DBG_INFO,
  35. DBG_STATE,
  36. ("[InternalCloseCall]: Adapter %08X, ClVcState is %s on VC %x\n",
  37. Vc->Adapter, GpcVcState[Vc->ClVcState], Vc));
  38. switch(Vc->ClVcState){
  39. case CL_INTERNAL_CLOSE_PENDING:
  40. //
  41. // We could get here if we get an unbind at our wan instance with a
  42. // NDIS_STATUS_WAN_LINE_DOWN. We could be trying to do an InternalClose
  43. // from both places.
  44. //
  45. PsAssert(Vc->Flags & INTERNAL_CLOSE_REQUESTED);
  46. PS_UNLOCK_DPC(&Vc->Lock);
  47. PS_UNLOCK(&Adapter->Lock);
  48. break;
  49. case CL_CALL_PENDING:
  50. case CL_MODIFY_PENDING:
  51. //
  52. // We've been asked to close before the call
  53. // has completed.
  54. //
  55. // Set a flag so that we'll close it when the
  56. // call completes.
  57. //
  58. PsAssert(!(Vc->Flags & GPC_CLOSE_REQUESTED));
  59. Vc->Flags |= INTERNAL_CLOSE_REQUESTED;
  60. PS_UNLOCK_DPC(&Vc->Lock);
  61. PS_UNLOCK(&Adapter->Lock);
  62. break;
  63. case CL_INTERNAL_CALL_COMPLETE:
  64. //
  65. // The call has been completed, but we may or may not
  66. // have told the GPC. Wait till we tell the GPC. We will
  67. // complete this when we transistion to CL_CALL_COMPLETE
  68. //
  69. PsAssert(!IsBestEffortVc(Vc));
  70. Vc->Flags |= INTERNAL_CLOSE_REQUESTED;
  71. PS_UNLOCK_DPC(&Vc->Lock);
  72. PS_UNLOCK(&Adapter->Lock);
  73. break;
  74. case CL_CALL_COMPLETE:
  75. //
  76. // Transition to CL_INTERNAL_CLOSE_PENDING and
  77. // ask the GPC to close.
  78. //
  79. Vc->ClVcState = CL_INTERNAL_CLOSE_PENDING;
  80. Vc->Flags |= INTERNAL_CLOSE_REQUESTED;
  81. PS_UNLOCK_DPC(&Vc->Lock);
  82. PS_UNLOCK(&Adapter->Lock);
  83. CmCloseCall(Vc);
  84. break;
  85. case CL_GPC_CLOSE_PENDING:
  86. //
  87. // The GPC has already asked us to close. Now,
  88. // we are also closing down - We need not do
  89. // anything here - Need not even inform the GPC.
  90. // we can just pretend as the InternalClose never
  91. // happened
  92. Vc->Flags &= ~INTERNAL_CLOSE_REQUESTED;
  93. PS_UNLOCK_DPC(&Vc->Lock);
  94. PS_UNLOCK(&Adapter->Lock);
  95. break;
  96. default:
  97. PS_UNLOCK_DPC(&Vc->Lock);
  98. PS_UNLOCK(&Adapter->Lock);
  99. PsDbgOut(DBG_FAILURE,
  100. DBG_STATE,
  101. ("[InternalCloseCall]: invalid state %s on VC %x\n",
  102. GpcVcState[Vc->ClVcState], Vc));
  103. PsAssert(0);
  104. break;
  105. }
  106. }
  107. VOID
  108. CallSucceededStateTransition(
  109. PGPC_CLIENT_VC Vc
  110. )
  111. {
  112. PsDbgOut(DBG_INFO,
  113. DBG_STATE,
  114. ("[CallSucceededStateTransition]: Adapter %08X, ClVcState is %s on VC %x\n",
  115. Vc->Adapter, GpcVcState[Vc->ClVcState], Vc));
  116. PS_LOCK(&Vc->Lock);
  117. switch(Vc->ClVcState){
  118. case CL_GPC_CLOSE_PENDING:
  119. PS_UNLOCK(&Vc->Lock);
  120. PsDbgOut(DBG_FAILURE,
  121. DBG_STATE,
  122. ("[CallSucceededStateTransition]: bad state %s on VC %x\n",
  123. GpcVcState[Vc->ClVcState], Vc));
  124. PsAssert(0);
  125. break;
  126. case CL_INTERNAL_CALL_COMPLETE:
  127. PsAssert(!IsBestEffortVc(Vc));
  128. #if DBG
  129. if(Vc->Flags & GPC_MODIFY_REQUESTED) {
  130. PsAssert(! (Vc->Flags & GPC_CLOSE_REQUESTED));
  131. }
  132. if(Vc->Flags & GPC_CLOSE_REQUESTED) {
  133. PsAssert(! (Vc->Flags & GPC_MODIFY_REQUESTED));
  134. }
  135. #endif
  136. //
  137. // Note that if both a modify & a internal remove is requested,
  138. // we just satisfy the modify. When the modify goes into internal
  139. // call complete, we will satify the remove
  140. //
  141. if(Vc->Flags & GPC_MODIFY_REQUESTED) {
  142. NDIS_STATUS Status;
  143. Vc->ClVcState = CL_MODIFY_PENDING;
  144. Vc->Flags &= ~GPC_MODIFY_REQUESTED;
  145. PS_UNLOCK(&Vc->Lock);
  146. Status = CmModifyCall(Vc);
  147. if(Status != NDIS_STATUS_PENDING) {
  148. CmModifyCallComplete(Status, Vc, Vc->ModifyCallParameters);
  149. }
  150. break;
  151. }
  152. if(Vc->Flags & GPC_CLOSE_REQUESTED) {
  153. //
  154. // The GPC has asked us to close after it
  155. // was notified of the call completion but
  156. // before we managed to transition to the
  157. // CL_CALL_COMPLETE state.
  158. //
  159. Vc->ClVcState = CL_GPC_CLOSE_PENDING;
  160. PS_UNLOCK(&Vc->Lock);
  161. CmCloseCall(Vc);
  162. break;
  163. }
  164. if(Vc->Flags & INTERNAL_CLOSE_REQUESTED){
  165. //
  166. // We had an internal close request while
  167. // the call was pending. The GPC has already
  168. // been notified, so - we need to ask it to
  169. // close.
  170. //
  171. Vc->ClVcState = CL_INTERNAL_CLOSE_PENDING;
  172. PS_UNLOCK(&Vc->Lock);
  173. CmCloseCall(Vc);
  174. break;
  175. }
  176. Vc->ClVcState = CL_CALL_COMPLETE;
  177. PS_UNLOCK(&Vc->Lock);
  178. break;
  179. case CL_MODIFY_PENDING:
  180. //
  181. // Typically, just transition to CL_CALL_COMPLETE
  182. //
  183. PsAssert(!(Vc->Flags & GPC_CLOSE_REQUESTED));
  184. PsAssert(!(Vc->Flags & GPC_MODIFY_REQUESTED));
  185. PsAssert(!IsBestEffortVc(Vc));
  186. Vc->ClVcState = CL_INTERNAL_CALL_COMPLETE;
  187. PS_UNLOCK(&Vc->Lock);
  188. break;
  189. case CL_CALL_PENDING:
  190. //
  191. // Typically, just transition to CL_INTERNAL_CALL_COMPLETE.
  192. //
  193. PsAssert(!(Vc->Flags & GPC_CLOSE_REQUESTED));
  194. PsAssert(!(Vc->Flags & GPC_MODIFY_REQUESTED));
  195. //
  196. // Call succeeded. Leave it up.
  197. //
  198. if(IsBestEffortVc(Vc))
  199. {
  200. Vc->ClVcState = CL_CALL_COMPLETE;
  201. }
  202. else
  203. {
  204. Vc->ClVcState = CL_INTERNAL_CALL_COMPLETE;
  205. }
  206. PS_UNLOCK(&Vc->Lock);
  207. break;
  208. default:
  209. PS_UNLOCK(&Vc->Lock);
  210. PsDbgOut(DBG_FAILURE,
  211. DBG_STATE,
  212. ("[CallSucceededStateTransition]: invalid state %s on VC %x\n",
  213. GpcVcState[Vc->ClVcState], Vc));
  214. PsAssert(0);
  215. }
  216. }
  217. /* end clstate.c */