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.

780 lines
21 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. pppread.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__ 'rppP'
  14. #endif
  15. #include "asyncall.h"
  16. NTSTATUS
  17. AsyncSLIPCompletionRoutine(
  18. IN PDEVICE_OBJECT DeviceObject,
  19. IN PIRP Irp,
  20. IN PVOID Context);
  21. NTSTATUS
  22. AsyncWaitMaskCompletionRoutine(
  23. IN PDEVICE_OBJECT DeviceObject,
  24. IN PIRP Irp,
  25. IN PVOID Context);
  26. NTSTATUS
  27. AsyncPPPWaitMask(
  28. IN PASYNC_INFO Info)
  29. /*++
  30. Assumption -- 0 length frames are not sent (this includes headers)!!!
  31. Also, this is NOT a synchronous operation. It is always asynchronous.
  32. Routine Description:
  33. This service writes Length bytes of data from the caller's Buffer to the
  34. "port" handle. It is assumed that the handle uses non-buffered IO.
  35. --*/
  36. {
  37. NTSTATUS status;
  38. PIRP irp;
  39. PASYNC_FRAME pFrame;
  40. PASYNC_ADAPTER pAdapter=Info->Adapter;
  41. pFrame=Info->AsyncFrame;
  42. irp =
  43. IoAllocateIrp(Info->DeviceObject->StackSize, (BOOLEAN)FALSE);
  44. if (irp == NULL) {
  45. return(NDIS_STATUS_RESOURCES);
  46. }
  47. InitSerialIrp(irp,
  48. Info,
  49. IOCTL_SERIAL_WAIT_ON_MASK,
  50. sizeof(ULONG));
  51. irp->AssociatedIrp.SystemBuffer=&pFrame->WaitMask;
  52. IoSetCompletionRoutine(
  53. irp, // irp to use
  54. AsyncWaitMaskCompletionRoutine, // routine to call when irp is done
  55. Info, // context to pass routine
  56. TRUE, // call on success
  57. TRUE, // call on error
  58. TRUE); // call on cancel
  59. //
  60. // Now simply invoke the driver at its dispatch entry with the IRP.
  61. //
  62. Info->Flags |= ASYNC_FLAG_WAIT_MASK;
  63. REF_ASYNCINFO(Info, irp);
  64. status = IoCallDriver(Info->DeviceObject, irp);
  65. //
  66. // Status for a local serial driver should be
  67. // STATUS_SUCCESS since the irp should complete
  68. // immediately because there are no read timeouts.
  69. //
  70. // For a remote serial driver, it will pend.
  71. //
  72. return(status);
  73. }
  74. NTSTATUS
  75. AsyncPPPCompletionRoutine(
  76. IN PDEVICE_OBJECT DeviceObject,
  77. IN PIRP Irp,
  78. IN PVOID Context)
  79. /*++
  80. This is the IO Completion routine for ReadFrame.
  81. --*/
  82. {
  83. NTSTATUS status;
  84. PASYNC_INFO pInfo;
  85. ULONG bytesReceived;
  86. PASYNC_FRAME pFrame;
  87. PUCHAR frameStart, frameEnd;
  88. USHORT crcData;
  89. PUCHAR frameEnd2,frameStart2;
  90. LONG bytesWanted;
  91. DeviceObject; // prevent compiler warnings
  92. status = Irp->IoStatus.Status;
  93. bytesReceived=(ULONG)Irp->IoStatus.Information;
  94. IoFreeIrp(Irp);
  95. pInfo=Context;
  96. pFrame=pInfo->AsyncFrame;
  97. switch (status) {
  98. case STATUS_SUCCESS:
  99. pFrame=pInfo->AsyncFrame;
  100. //
  101. // Any bytes to process? This can happen if
  102. // the WaitMask completes late and by the time
  103. // we process the read, another event character has come
  104. // in.
  105. //
  106. if (bytesReceived==0) {
  107. break;
  108. }
  109. //
  110. // Update num of bytes read total for this frame
  111. //
  112. pInfo->BytesRead = bytesReceived = pInfo->BytesRead + bytesReceived;
  113. //
  114. // Set frameEnd to last byte processed. Initially,
  115. // we have processed nothing (i.e. processed up to
  116. // the start of the first byte).
  117. //
  118. frameStart=pFrame->Frame + PPP_PADDING;
  119. PROCESS_FRAME:
  120. //
  121. // Now we have actuallyRead bytes unused
  122. // Also, we may have a complete frame.
  123. //
  124. while (*frameStart == PPP_FLAG_BYTE && --bytesReceived) {
  125. frameStart++;
  126. }
  127. //
  128. // If we reach here, there is only a start FLAG...
  129. //
  130. if (bytesReceived == 0) {
  131. break;
  132. }
  133. //
  134. // frameEnd is set to the first byte not yet processed.
  135. // If we are starting out, that is the first byte!
  136. //
  137. frameEnd=frameStart;
  138. //
  139. // Assume the start of the frame has the PPP_FLAG_BYTE
  140. // Look for the second PPP_FLAG_BYTE (end of frame)
  141. //
  142. while (*frameEnd != PPP_FLAG_BYTE && --bytesReceived) {
  143. frameEnd++;
  144. }
  145. //
  146. // At this point...
  147. // frameStart = beginning PPP_FLAG_BYTE seen
  148. // frameEnd = end PPP_FLAG_BYTE
  149. // bytesReceived = bytes after frameEnd not processed
  150. //
  151. //
  152. // if bytesReceived is 0, we ran out of space before hitting
  153. // the END flag. We will have to wait for the next round
  154. //
  155. // NOTE: if BytesRead gets too high we trash the frame
  156. // because we could not find the FLAG_BYTE
  157. //
  158. if (bytesReceived==0) {
  159. break;
  160. }
  161. if (*(pFrame->Frame+PPP_PADDING) != PPP_FLAG_BYTE) {
  162. //
  163. // We had garbage at the start. Remove the garbage.
  164. //
  165. pInfo->SerialStats.AlignmentErrors++;
  166. //
  167. // Tell the transport above us that we dropped a packet
  168. // Hopefully, it will quickly resync.
  169. //
  170. AsyncIndicateFragment(
  171. pInfo,
  172. WAN_ERROR_ALIGNMENT);
  173. goto NEXT_PPP_FRAME;
  174. }
  175. //
  176. // Length of frame is frameEnd - frameStart
  177. //
  178. bytesWanted = (LONG)(frameEnd - frameStart);
  179. frameEnd2 = frameStart2 = frameStart;
  180. //
  181. // Replace back all control chars, ESC, and FLAG chars
  182. //
  183. while (bytesWanted-- > 0) {
  184. if ((*frameEnd2=*frameStart2++) == PPP_ESC_BYTE) {
  185. //
  186. // We have not run the CRC check yet!!
  187. // We have be careful about sending bytesWanted
  188. // back to -1 on corrupted data
  189. //
  190. bytesWanted--;
  191. *frameEnd2 = (*frameStart2++ ^ 0x20);
  192. }
  193. frameEnd2++;
  194. }
  195. if (*frameStart2 != PPP_FLAG_BYTE) {
  196. DbgTracef(-2,("BAD PPP FRAME at 0x%.8x 0x%.8x\n", frameStart, frameEnd2));
  197. }
  198. //
  199. // if CRC-16, get 16 bit CRC from end of frame
  200. //
  201. frameEnd2 -= 2;
  202. //
  203. // Little endian assumptions for CRC
  204. //
  205. crcData=(USHORT)frameEnd2[0]+(USHORT)(frameEnd2[1] << 8);
  206. crcData ^= 0xFFFF;
  207. //
  208. // Change the bytesWanted field to what it normally is
  209. // without the byte stuffing (length of frame between flags)
  210. // Note that it can be -1 if only one byte was
  211. // found in between the flag bytes
  212. //
  213. bytesWanted = (LONG)(frameEnd2 - frameStart);
  214. //
  215. // If we get some sort of garbage inbetween
  216. // the PPP flags, we just assume it is noise and
  217. // discard it. We don't record a PPP CRC error just
  218. // an alignment error.
  219. //
  220. if (bytesWanted < 3) {
  221. pInfo->SerialStats.AlignmentErrors++;
  222. //
  223. // Tell the transport above us that we dropped a packet
  224. // Hopefully, it will quickly resync.
  225. //
  226. AsyncIndicateFragment(pInfo, WAN_ERROR_ALIGNMENT);
  227. goto NEXT_PPP_FRAME;
  228. }
  229. //
  230. // get CRC from FLAG byte to FLAG byte
  231. //
  232. if (crcData != CalcCRCPPP(frameStart, bytesWanted)) {
  233. DbgTracef(0,("---CRC check failed on control char frame!\n"));
  234. //
  235. // Record the CRC error
  236. //
  237. pInfo->SerialStats.CRCErrors++;
  238. //
  239. // Tell the transport above us that we dropped a packet
  240. // Hopefully, it will quickly resync.
  241. //
  242. AsyncIndicateFragment(
  243. pInfo,
  244. WAN_ERROR_CRC);
  245. goto NEXT_PPP_FRAME;
  246. }
  247. /*
  248. for ( i = 0; (i < (ULONG)bytesWanted) && (i < 48); i++ )
  249. {
  250. if ( (i & 15) == 0 )
  251. DbgTracef(-1, ("\nrx:\t") );
  252. DbgTracef(-1, ("%.2x ", frameStart[i]) );
  253. }
  254. DbgTracef(-1, ("\n") );
  255. */
  256. {
  257. KIRQL irql;
  258. NDIS_STATUS Status;
  259. PASYNC_ADAPTER Adapter = pInfo->Adapter;
  260. KeRaiseIrql( (KIRQL)DISPATCH_LEVEL, &irql );
  261. //
  262. // Tell the transport above (or really RasHub) that the connection
  263. // is now up. We have a new link speed, frame size, quality of service
  264. //
  265. NdisMWanIndicateReceive(&Status,
  266. Adapter->MiniportHandle,
  267. pInfo->NdisLinkContext,
  268. frameStart, // ptr to start of packet
  269. bytesWanted); // Total packet length - header
  270. NdisMWanIndicateReceiveComplete(Adapter->MiniportHandle,
  271. pInfo->NdisLinkContext);
  272. KeLowerIrql( irql );
  273. }
  274. NEXT_PPP_FRAME:
  275. //
  276. // if bytesReceived == 0 no frame was found
  277. // thus we must keep the current frame and continue
  278. // processing
  279. //
  280. if (bytesReceived) {
  281. //
  282. // Calculate how much of what we received
  283. // just got passed up as a frame and move the
  284. // rest to the beginning.
  285. //
  286. frameStart=pFrame->Frame + PPP_PADDING;
  287. frameEnd2=frameStart + pInfo->BytesRead;
  288. pInfo->BytesRead =
  289. bytesReceived = (ULONG)(frameEnd2-frameEnd);
  290. ASYNC_MOVE_MEMORY(
  291. frameStart, // dest
  292. frameEnd, // src
  293. bytesReceived); // length
  294. //
  295. // Need at least four bytes for a frame to exist
  296. //
  297. if (bytesReceived > 3) {
  298. goto PROCESS_FRAME;
  299. }
  300. }
  301. break;
  302. case STATUS_PENDING:
  303. DbgTracef(0,("---ASYNC: Status PENDING on read\n"));
  304. pInfo->Flags &= ~(ASYNC_FLAG_PPP_READ);
  305. #if DBG
  306. pInfo->PppreadsCompleted++;
  307. #endif
  308. DEREF_ASYNCINFO(pInfo, Irp);
  309. // return(STATUS_MORE_PROCESSING_REQUIRED);
  310. goto done;
  311. case STATUS_CANCELLED:
  312. // else this is an anomally!
  313. DbgTracef(-2,("---ASYNC: Status cancelled on read for unknown reason!!\n"));
  314. pInfo->Flags &= ~(ASYNC_FLAG_PPP_READ);
  315. DEREF_ASYNCINFO(pInfo, Irp);
  316. #if DBG
  317. pInfo->PppreadsCompleted++;
  318. #endif
  319. //return(STATUS_MORE_PROCESSING_REQUIRED);
  320. goto done;
  321. default:
  322. #if DBG
  323. DbgPrint ("AsyncPPPCompletionRoutine: status == %x, no more reads\n", status) ;
  324. #endif
  325. pInfo->Flags &= ~(ASYNC_FLAG_PPP_READ);
  326. DEREF_ASYNCINFO(pInfo, Irp);
  327. #if DBG
  328. pInfo->PppreadsCompleted++;
  329. #endif
  330. return(STATUS_MORE_PROCESSING_REQUIRED);
  331. }
  332. if(status == STATUS_SUCCESS)
  333. {
  334. //
  335. // Here we are at the end of processing this IRP so we go
  336. // ahead and post another read from the serial port.
  337. //
  338. AsyncPPPWaitMask(pInfo);
  339. }
  340. // We return STATUS_MORE_PROCESSING_REQUIRED so that the
  341. // IoCompletionRoutine will stop working on the IRP.
  342. pInfo->Flags &= ~(ASYNC_FLAG_PPP_READ);
  343. DEREF_ASYNCINFO(pInfo, Irp);
  344. #if DBG
  345. pInfo->PppreadsCompleted++;
  346. #endif
  347. done:
  348. if(status != STATUS_SUCCESS)
  349. {
  350. if(pInfo->PortState == PORT_CLOSING ||
  351. pInfo->PortState == PORT_CLOSED)
  352. {
  353. KeSetEvent(&pInfo->ClosingEvent,
  354. 1,
  355. (BOOLEAN) FALSE);
  356. }
  357. }
  358. return(STATUS_MORE_PROCESSING_REQUIRED);
  359. }
  360. NTSTATUS
  361. AsyncPPPRead(
  362. IN PASYNC_INFO Info)
  363. /*++
  364. Assumption -- 0 length frames are not sent (this includes headers)!!!
  365. Also, this is NOT a synchronous operation. It is always asynchronous.
  366. MUST use non-paged pool to read!!!
  367. Routine Description:
  368. This service writes Length bytes of data from the caller's Buffer to the
  369. "port" handle. It is assumed that the handle uses non-buffered IO.
  370. --*/
  371. {
  372. NTSTATUS status;
  373. PIRP irp;
  374. PDEVICE_OBJECT deviceObject=Info->DeviceObject;
  375. PFILE_OBJECT fileObject=Info->FileObject;
  376. PIO_STACK_LOCATION irpSp;
  377. PASYNC_FRAME pFrame;
  378. PASYNC_ADAPTER pAdapter=Info->Adapter;
  379. PIO_COMPLETION_ROUTINE routine;
  380. pFrame=Info->AsyncFrame;
  381. //
  382. // check if this port is closing down or already closed
  383. //
  384. if (Info->PortState == PORT_CLOSING ||
  385. Info->PortState == PORT_CLOSED) {
  386. if (Info->PortState == PORT_CLOSED) {
  387. DbgTracef(-2,("ASYNC: Port closed - but still reading on it!\n"));
  388. }
  389. //
  390. // Acknowledge that the port is closed
  391. //
  392. KeSetEvent(&Info->ClosingEvent, // Event
  393. 1, // Priority
  394. (BOOLEAN)FALSE); // Wait (does not follow)
  395. //
  396. // Ok, if this happens, we are shutting down. Stop
  397. // posting reads. Don't make it try to deallocate the irp!
  398. //
  399. return(STATUS_MORE_PROCESSING_REQUIRED);
  400. }
  401. //
  402. // Has our stack counter reached its max?
  403. //
  404. if ( Info->ReadStackCounter > 1 ) {
  405. //
  406. // Send off the worker thread to compress this frame
  407. //
  408. ExInitializeWorkItem(&pFrame->WorkItem,
  409. (PWORKER_THREAD_ROUTINE) AsyncPPPRead, Info);
  410. //
  411. // reset stack counter since we are scheduling
  412. // a worker thread
  413. //
  414. Info->ReadStackCounter=0;
  415. //
  416. // We choose to be nice and use delayed.
  417. //
  418. ExQueueWorkItem(&pFrame->WorkItem, DelayedWorkQueue);
  419. return NDIS_STATUS_PENDING;
  420. }
  421. //
  422. // One more stack used up.
  423. //
  424. Info->ReadStackCounter++;
  425. // get irp from frame (each frame has an irp allocate with it)
  426. irp =
  427. IoAllocateIrp(Info->DeviceObject->StackSize, (BOOLEAN)FALSE);
  428. if (irp == NULL) {
  429. return(NDIS_STATUS_RESOURCES);
  430. }
  431. // Setup this irp with defaults
  432. AsyncSetupIrp(pFrame, irp);
  433. //
  434. // If we've read all the bytes we can and we still do not
  435. // have a frame, we trash our buffer and start over
  436. // again.
  437. //
  438. if (Info->BytesRead >= (DEFAULT_EXPANDED_PPP_MAX_FRAME_SIZE - PPP_PADDING)) {
  439. Info->SerialStats.BufferOverrunErrors++;
  440. //
  441. // Tell the transport above us that we dropped a packet
  442. // Hopefully, it will quickly resync.
  443. //
  444. AsyncIndicateFragment(Info, WAN_ERROR_BUFFEROVERRUN);
  445. Info->BytesRead=0;
  446. }
  447. irp->AssociatedIrp.SystemBuffer =
  448. pFrame->Frame + Info->BytesRead + PPP_PADDING;
  449. //
  450. // Get a pointer to the stack location for the first driver. This will be
  451. // used to pass the original function codes and parameters.
  452. //
  453. irpSp = IoGetNextIrpStackLocation(irp);
  454. irpSp->MajorFunction = IRP_MJ_READ;
  455. irpSp->FileObject = fileObject;
  456. if (fileObject->Flags & FO_WRITE_THROUGH) {
  457. irpSp->Flags = SL_WRITE_THROUGH;
  458. }
  459. //
  460. // If this write operation is to be performed without any caching, set the
  461. // appropriate flag in the IRP so no caching is performed.
  462. //
  463. irp->Flags |= IRP_READ_OPERATION;
  464. if (fileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) {
  465. irp->Flags |= IRP_NOCACHE;
  466. }
  467. //
  468. // Copy the caller's parameters to the service-specific portion of the
  469. // IRP.
  470. //
  471. irpSp->Parameters.Read.Length =
  472. DEFAULT_EXPANDED_PPP_MAX_FRAME_SIZE - Info->BytesRead - PPP_PADDING;
  473. irpSp->Parameters.Read.Key = 0; // we don't use a key
  474. irpSp->Parameters.Read.ByteOffset = fileObject->CurrentByteOffset;
  475. if ( Info->GetLinkInfo.SendFramingBits & SLIP_FRAMING ) {
  476. routine=AsyncSLIPCompletionRoutine;
  477. Info->Flags |= ASYNC_FLAG_SLIP_READ;
  478. } else {
  479. Info->Flags |= ASYNC_FLAG_PPP_READ;
  480. #if DBG
  481. Info->Pppreads++;
  482. #endif
  483. routine=AsyncPPPCompletionRoutine;
  484. }
  485. REF_ASYNCINFO(Info, irp);
  486. IoSetCompletionRoutine(
  487. irp, // irp to use
  488. routine, // routine to call when irp is done
  489. Info, // context to pass routine
  490. TRUE, // call on success
  491. TRUE, // call on error
  492. TRUE); // call on cancel
  493. //
  494. // We DO NOT insert the packet at the head of the IRP list for the thread.
  495. // because we do NOT really have an IoCompletionRoutine that does
  496. // anything with the thread.
  497. //
  498. //
  499. // Now simply invoke the driver at its dispatch entry with the IRP.
  500. //
  501. status = IoCallDriver(deviceObject, irp);
  502. //
  503. // unroll the stack counter
  504. //
  505. if ( Info->ReadStackCounter > 0 ) {
  506. Info->ReadStackCounter--;
  507. }
  508. //
  509. // Status for a local serial driver should be
  510. // STATUS_SUCCESS since the irp should complete
  511. // immediately because there are no read timeouts.
  512. //
  513. // For a remote serial driver, it will pend.
  514. //
  515. return(status);
  516. }
  517. NTSTATUS
  518. AsyncWaitMaskCompletionRoutine(
  519. IN PDEVICE_OBJECT DeviceObject,
  520. IN PIRP Irp,
  521. IN PVOID Context)
  522. /*++
  523. This is the IO Completion routine for ReadFrame.
  524. --*/
  525. {
  526. NTSTATUS status;
  527. PASYNC_INFO pInfo=Context;
  528. PASYNC_FRAME pFrame;
  529. DeviceObject; // avoid compiler warnings
  530. status = Irp->IoStatus.Status;
  531. pFrame=pInfo->AsyncFrame;
  532. IoFreeIrp(Irp);
  533. // check if this port is closing down or already closed
  534. if (pInfo->PortState == PORT_CLOSING ||
  535. pInfo->PortState == PORT_CLOSED) {
  536. if (pInfo->PortState == PORT_CLOSED) {
  537. DbgTracef(-2,("ASYNC: Port closed - but still reading on it!\n"));
  538. }
  539. //
  540. // Acknowledge that the port is closed
  541. //
  542. KeSetEvent(
  543. &pInfo->ClosingEvent, // Event
  544. 1, // Priority
  545. (BOOLEAN)FALSE); // Wait (does not follow)
  546. DbgTracef(1,("ASYNC: PPP no longer holds the wait_on_mask\n"));
  547. pInfo->Flags &= ~(ASYNC_FLAG_WAIT_MASK);
  548. DEREF_ASYNCINFO(pInfo, Irp);
  549. //
  550. // Ok, if this happens, we are shutting down. Stop
  551. // posting reads. Don't make it try to deallocate the irp!
  552. //
  553. return(STATUS_MORE_PROCESSING_REQUIRED);
  554. }
  555. // wait failed
  556. //
  557. if (status != STATUS_SUCCESS) {
  558. pInfo->PortState = PORT_FRAMING;
  559. pInfo->Flags &= ~(ASYNC_FLAG_WAIT_MASK);
  560. DEREF_ASYNCINFO(pInfo, Irp);
  561. return(STATUS_MORE_PROCESSING_REQUIRED);
  562. }
  563. //
  564. // Send off a irp to check comm status
  565. // of this port (because we suspect a problem).
  566. //
  567. if (pFrame->WaitMask & SERIAL_EV_ERR) {
  568. AsyncCheckCommStatus(pInfo);
  569. }
  570. //
  571. // Check if RLSD or DSR changed state.
  572. // If so, we probably have to complete and IRP
  573. //
  574. if (pFrame->WaitMask & (SERIAL_EV_RLSD | SERIAL_EV_DSR)) {
  575. TryToCompleteDDCDIrp(pInfo);
  576. }
  577. #if DBG
  578. if (status == STATUS_INVALID_PARAMETER) {
  579. DbgPrint("ASYNC: PPP BAD WAIT MASK! Irp is at 0x%.8x\n",Irp);
  580. DbgBreakPoint();
  581. }
  582. #endif
  583. //
  584. // If we have some more bytes (specifically the event character)
  585. // in the buffer, let's process those new bytes
  586. //
  587. if (pFrame->WaitMask & (SERIAL_EV_RXFLAG | SERIAL_EV_RX80FULL)) {
  588. //
  589. // Read current buffer and try to process a frame
  590. //
  591. AsyncPPPRead(pInfo);
  592. } else {
  593. //
  594. // Set another WaitMask call
  595. //
  596. AsyncPPPWaitMask(pInfo);
  597. }
  598. pInfo->Flags &= ~(ASYNC_FLAG_WAIT_MASK);
  599. DEREF_ASYNCINFO(pInfo, Irp);
  600. // We return STATUS_MORE_PROCESSING_REQUIRED so that the
  601. // IoCompletionRoutine will stop working on the IRP.
  602. return(STATUS_MORE_PROCESSING_REQUIRED);
  603. }