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.

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