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.

315 lines
7.8 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. slipread.c
  5. Abstract:
  6. Author:
  7. Thomas J. Dimitri (TommyD) 08-May-1992
  8. Environment:
  9. Kernel Mode - Or whatever is the equivalent on OS/2 and DOS.
  10. Revision History:
  11. --*/
  12. #if DBG
  13. #define __FILE_SIG__ 'pliS'
  14. #endif
  15. #include "asyncall.h"
  16. NTSTATUS
  17. AsyncWaitMaskCompletionRoutine(
  18. IN PDEVICE_OBJECT DeviceObject,
  19. IN PIRP Irp,
  20. IN PVOID Context);
  21. NTSTATUS
  22. AsyncPPPWaitMask(
  23. IN PASYNC_INFO Info);
  24. NTSTATUS
  25. AsyncSLIPCompletionRoutine(
  26. IN PDEVICE_OBJECT DeviceObject,
  27. IN PIRP Irp,
  28. IN PVOID Context)
  29. /*++
  30. This is the IO Completion routine for ReadFrame.
  31. --*/
  32. {
  33. NTSTATUS status;
  34. PASYNC_INFO pInfo;
  35. ULONG bytesReceived;
  36. PASYNC_FRAME pFrame;
  37. PUCHAR frameStart, frameEnd;
  38. PUCHAR frameEnd2,frameStart2;
  39. LONG bytesWanted; // keep this a long ( < 0 is used)
  40. DeviceObject; // prevent compiler warnings
  41. status = Irp->IoStatus.Status;
  42. bytesReceived=(ULONG)Irp->IoStatus.Information;
  43. IoFreeIrp(Irp);
  44. pInfo=Context;
  45. pFrame=pInfo->AsyncFrame;
  46. switch (status) {
  47. case STATUS_SUCCESS:
  48. //
  49. // Any bytes to process? This can happen if
  50. // the WaitMask completes late and by the time
  51. // we process the read, another event character has come
  52. // in.
  53. //
  54. if (bytesReceived==0) {
  55. break;
  56. }
  57. //
  58. // Update num of bytes read total for this frame
  59. //
  60. pInfo->BytesRead = bytesReceived = pInfo->BytesRead + bytesReceived;
  61. //
  62. // Set frameEnd to last byte processed. Initially,
  63. // we have processed nothing (i.e. processed up to
  64. // the start of the first byte).
  65. //
  66. frameStart=pFrame->Frame + PPP_PADDING;
  67. PROCESS_FRAME:
  68. //
  69. // Now we have actuallyRead bytes unused
  70. // Also, we may have a complete frame.
  71. //
  72. while (*frameStart == SLIP_END_BYTE && --bytesReceived) {
  73. frameStart++;
  74. }
  75. //
  76. // If we reach here, there is no end FLAG
  77. //
  78. if (bytesReceived == 0) {
  79. break;
  80. }
  81. //
  82. // frameEnd is set to the first byte not yet processed.
  83. // If we are starting out, that is the first byte!
  84. //
  85. frameEnd=frameStart;
  86. //
  87. // Assume the start of the frame has the SLIP_END_BYTE
  88. // Look for the second SLIP_END_BYTE (end of frame)
  89. //
  90. while (*frameEnd != SLIP_END_BYTE && --bytesReceived) {
  91. frameEnd++;
  92. }
  93. //
  94. // if bytesReceived is 0, we got nothing
  95. //
  96. // NOTE: if BytesRead gets too high we trash the frame
  97. // because we could not find the FLAG_BYTE
  98. //
  99. if (bytesReceived==0) {
  100. break;
  101. }
  102. if (*(pFrame->Frame+PPP_PADDING) != SLIP_END_BYTE) {
  103. //
  104. // We had garbage at the start. Remove the garbage.
  105. //
  106. pInfo->SerialStats.AlignmentErrors++;
  107. //
  108. // Tell the transport above us that we dropped a packet
  109. // Hopefully, it will quickly resync.
  110. //
  111. AsyncIndicateFragment(
  112. pInfo,
  113. WAN_ERROR_ALIGNMENT);
  114. goto NEXT_SLIP_FRAME;
  115. }
  116. //
  117. // Length of frame is frameEnd - frameStart
  118. //
  119. bytesWanted = (LONG)(frameEnd - frameStart);
  120. frameEnd2 = frameStart2 = frameStart;
  121. //
  122. // Replace back all control chars, ESC, and FLAG chars
  123. //
  124. while (bytesWanted-- > 0) {
  125. if ((*frameEnd2=*frameStart2++) == SLIP_ESC_BYTE) {
  126. //
  127. // We have not run the CRC check yet!!
  128. // We have be careful about sending bytesWanted
  129. // back to -1 on corrupted data
  130. //
  131. bytesWanted--;
  132. *frameEnd2 = SLIP_END_BYTE;
  133. if (*frameStart2++ == SLIP_ESC_ESC_BYTE) {
  134. *frameEnd2 = SLIP_ESC_BYTE;
  135. }
  136. }
  137. frameEnd2++;
  138. }
  139. //
  140. // Change the bytesWanted field to what it normally is,
  141. // the length of the frame.
  142. //
  143. bytesWanted = (LONG)(frameEnd2 - frameStart);
  144. // Keep those stats up to date
  145. {
  146. KIRQL irql;
  147. NTSTATUS Status;
  148. PASYNC_ADAPTER Adapter = pInfo->Adapter;
  149. KeRaiseIrql( (KIRQL)DISPATCH_LEVEL, &irql );
  150. //
  151. // Compressed TCP/IP packets must at least 3 bytes long
  152. //
  153. if (bytesWanted >= 3) {
  154. NdisMWanIndicateReceive(
  155. &Status,
  156. Adapter->MiniportHandle,
  157. pInfo->NdisLinkContext,
  158. frameStart,
  159. bytesWanted);
  160. NdisMWanIndicateReceiveComplete(
  161. Adapter->MiniportHandle,
  162. pInfo->NdisLinkContext);
  163. } else {
  164. pInfo->SerialStats.AlignmentErrors++;
  165. //
  166. // Tell the transport above us that we dropped a packet
  167. // Hopefully, it will quickly resync.
  168. //
  169. AsyncIndicateFragment(
  170. pInfo,
  171. WAN_ERROR_ALIGNMENT);
  172. DbgTracef(-2,("SLIP: Frame too small %u\n", bytesWanted));
  173. }
  174. KeLowerIrql( irql );
  175. }
  176. NEXT_SLIP_FRAME:
  177. //
  178. // if bytesReceived == 0 no frame was found
  179. // thus we must keep the current frame and continue
  180. // processing
  181. //
  182. if (bytesReceived) {
  183. //
  184. // Calculate how much of what we received
  185. // just got passed up as a frame and move the
  186. // rest to the beginning.
  187. //
  188. frameStart=pFrame->Frame + PPP_PADDING;
  189. frameEnd2=frameStart + pInfo->BytesRead;
  190. pInfo->BytesRead =
  191. bytesReceived = (LONG)(frameEnd2-frameEnd);
  192. ASYNC_MOVE_MEMORY(
  193. frameStart, // dest
  194. frameEnd, // src
  195. bytesReceived); // length
  196. //
  197. // Need at least four bytes for a frame to exist
  198. //
  199. if (bytesReceived > 3) {
  200. goto PROCESS_FRAME;
  201. }
  202. }
  203. break;
  204. case STATUS_CANCELLED:
  205. // else this is an anomally!
  206. DbgTracef(-2,("---ASYNC: Status cancelled on read for unknown reason!!\n"));
  207. break;
  208. case STATUS_PENDING:
  209. DbgTracef(0,("---ASYNC: Status PENDING on read\n"));
  210. break;
  211. default:
  212. DbgTracef(-2,("---ASYNC: Unknown status 0x%.8x on read",status));
  213. break;
  214. }
  215. if(status == STATUS_SUCCESS)
  216. {
  217. AsyncPPPWaitMask(pInfo);
  218. }
  219. else if(pInfo->PortState == PORT_CLOSING ||
  220. pInfo->PortState == PORT_CLOSED)
  221. {
  222. KeSetEvent(&pInfo->ClosingEvent,
  223. 1,
  224. (BOOLEAN) FALSE);
  225. }
  226. //
  227. // Here we are at the end of processing this IRP so we go
  228. // ahead and post another read from the serial port.
  229. //
  230. pInfo->Flags &= ~(ASYNC_FLAG_SLIP_READ);
  231. DEREF_ASYNCINFO(pInfo, Irp);
  232. // We return STATUS_MORE_PROCESSING_REQUIRED so that the
  233. // IoCompletionRoutine will stop working on the IRP.
  234. return(STATUS_MORE_PROCESSING_REQUIRED);
  235. }