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.

271 lines
7.9 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. recovery.c
  5. Author:
  6. ervinp
  7. Environment:
  8. Kernel mode
  9. Revision History:
  10. --*/
  11. #include <WDM.H>
  12. #include <usbdi.h>
  13. #include <usbdlib.h>
  14. #include <usbioctl.h>
  15. #include "usb8023.h"
  16. #include "debug.h"
  17. /*
  18. * USB- and WDM- specific prototypes (won't compile in common header)
  19. */
  20. NTSTATUS CallDriverSync(PDEVICE_OBJECT devObj, PIRP irp);
  21. /*
  22. * ServiceReadDeficit
  23. *
  24. * If we "owe" the BULK IN pipe some read packets, send them down now.
  25. */
  26. VOID ServiceReadDeficit(ADAPTEREXT *adapter)
  27. {
  28. ULONG numReadsToTry;
  29. KIRQL oldIrql;
  30. ASSERT(adapter->sig == DRIVER_SIG);
  31. /*
  32. * If there is a read deficit, try to fulfill it now.
  33. * Careful not to get into an infinite loop, since TryReadUSB
  34. * will re-increment readDeficit if there are still no packets.
  35. */
  36. KeAcquireSpinLock(&adapter->adapterSpinLock, &oldIrql);
  37. ASSERT(adapter->readDeficit <= NUM_READ_PACKETS);
  38. numReadsToTry = adapter->readDeficit;
  39. while ((adapter->readDeficit > 0) && (numReadsToTry > 0) && !adapter->halting){
  40. DBGWARN(("RndisReturnMessageHandler attempting to fill read DEFICIT (=%d)", adapter->readDeficit));
  41. adapter->readDeficit--;
  42. numReadsToTry--;
  43. KeReleaseSpinLock(&adapter->adapterSpinLock, oldIrql);
  44. TryReadUSB(adapter);
  45. KeAcquireSpinLock(&adapter->adapterSpinLock, &oldIrql);
  46. }
  47. KeReleaseSpinLock(&adapter->adapterSpinLock, oldIrql);
  48. }
  49. #if DO_FULL_RESET
  50. VOID AdapterFullResetAndRestore(ADAPTEREXT *adapter)
  51. {
  52. NTSTATUS status;
  53. DBGWARN(("AdapterFullResetAndRestore"));
  54. adapter->numHardResets++;
  55. adapter->needFullReset = FALSE;
  56. if (adapter->halting){
  57. DBGWARN(("AdapterFullResetAndRestore - skipping since device is halting"));
  58. }
  59. else {
  60. ULONG portStatus;
  61. ASSERT(!adapter->resetting);
  62. adapter->resetting = TRUE;
  63. status = GetUSBPortStatus(adapter, &portStatus);
  64. if (NT_SUCCESS(status) && (portStatus & USBD_PORT_CONNECTED)){
  65. CancelAllPendingPackets(adapter);
  66. // RNDIS Halt seems to put the device out of whack until power cycle
  67. // SimulateRNDISHalt(adapter);
  68. AbortPipe(adapter, adapter->readPipeHandle);
  69. ResetPipe(adapter, adapter->readPipeHandle);
  70. AbortPipe(adapter, adapter->writePipeHandle);
  71. ResetPipe(adapter, adapter->writePipeHandle);
  72. if (adapter->notifyPipeHandle){
  73. AbortPipe(adapter, adapter->notifyPipeHandle);
  74. ResetPipe(adapter, adapter->notifyPipeHandle);
  75. }
  76. /*
  77. * Now, bring the adapter back to the run state
  78. * if it was previously.
  79. */
  80. if (adapter->initialized){
  81. /*
  82. * Simulate RNDIS messages for INIT and set-packet-filter.
  83. * These simulation functions need to read and throw away
  84. * the response on the notify and control pipes, so do
  85. * this before starting the read loop on the notify pipe.
  86. */
  87. status = SimulateRNDISInit(adapter);
  88. if (NT_SUCCESS(status)){
  89. SimulateRNDISSetPacketFilter(adapter);
  90. SimulateRNDISSetCurrentAddress(adapter);
  91. /*
  92. * Restart the read loops.
  93. */
  94. if (adapter->notifyPipeHandle){
  95. SubmitNotificationRead(adapter, FALSE);
  96. }
  97. StartUSBReadLoop(adapter);
  98. }
  99. else {
  100. adapter->initialized = FALSE;
  101. }
  102. }
  103. }
  104. else {
  105. DBGWARN(("AdapterFullResetAndRestore - skipping since device is no longer connected"));
  106. }
  107. adapter->resetting = FALSE;
  108. }
  109. }
  110. NTSTATUS GetUSBPortStatus(ADAPTEREXT *adapter, PULONG portStatus)
  111. {
  112. NTSTATUS status;
  113. PIRP irp;
  114. *portStatus = 0;
  115. irp = IoAllocateIrp(adapter->nextDevObj->StackSize, FALSE);
  116. if (irp){
  117. PIO_STACK_LOCATION nextSp;
  118. nextSp = IoGetNextIrpStackLocation(irp);
  119. nextSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  120. nextSp->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_GET_PORT_STATUS;
  121. nextSp->Parameters.Others.Argument1 = portStatus;
  122. status = CallDriverSync(adapter->nextDevObj, irp);
  123. IoFreeIrp(irp);
  124. }
  125. else {
  126. status = STATUS_INSUFFICIENT_RESOURCES;
  127. }
  128. return status;
  129. }
  130. NTSTATUS AbortPipe(ADAPTEREXT *adapter, PVOID pipeHandle)
  131. {
  132. NTSTATUS status;
  133. PIRP irp;
  134. ULONG portStatus;
  135. status = GetUSBPortStatus(adapter, &portStatus);
  136. if (NT_SUCCESS(status) && (portStatus & USBD_PORT_CONNECTED)){
  137. irp = IoAllocateIrp(adapter->nextDevObj->StackSize, FALSE);
  138. if (irp){
  139. PIO_STACK_LOCATION nextSp;
  140. URB urb = {0};
  141. urb.UrbHeader.Length = sizeof (struct _URB_PIPE_REQUEST);
  142. urb.UrbHeader.Function = URB_FUNCTION_ABORT_PIPE;
  143. urb.UrbPipeRequest.PipeHandle = pipeHandle;
  144. nextSp = IoGetNextIrpStackLocation(irp);
  145. nextSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  146. nextSp->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
  147. nextSp->Parameters.Others.Argument1 = &urb;
  148. status = CallDriverSync(adapter->nextDevObj, irp);
  149. if (NT_SUCCESS(status)){
  150. }
  151. else {
  152. DBGWARN(("AbortPipe failed with %xh (urb status %xh).", status, urb.UrbHeader.Status));
  153. }
  154. IoFreeIrp(irp);
  155. }
  156. else {
  157. status = STATUS_INSUFFICIENT_RESOURCES;
  158. }
  159. }
  160. else {
  161. DBGWARN(("AbortPipe - skipping abort because device not connected (status=%xh)", status));
  162. status = STATUS_SUCCESS;
  163. }
  164. return status;
  165. }
  166. NTSTATUS ResetPipe(ADAPTEREXT *adapter, PVOID pipeHandle)
  167. {
  168. NTSTATUS status;
  169. PIRP irp;
  170. ULONG portStatus;
  171. status = GetUSBPortStatus(adapter, &portStatus);
  172. if (NT_SUCCESS(status) && (portStatus & USBD_PORT_CONNECTED)){
  173. irp = IoAllocateIrp(adapter->nextDevObj->StackSize, FALSE);
  174. if (irp){
  175. PIO_STACK_LOCATION nextSp;
  176. URB urb = {0};
  177. urb.UrbHeader.Length = sizeof (struct _URB_PIPE_REQUEST);
  178. urb.UrbHeader.Function = URB_FUNCTION_RESET_PIPE;
  179. urb.UrbPipeRequest.PipeHandle = pipeHandle;
  180. nextSp = IoGetNextIrpStackLocation(irp);
  181. nextSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  182. nextSp->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
  183. nextSp->Parameters.Others.Argument1 = &urb;
  184. status = CallDriverSync(adapter->nextDevObj, irp);
  185. if (NT_SUCCESS(status)){
  186. }
  187. else {
  188. DBGWARN(("ResetPipe failed with %xh (urb status %xh).", status, urb.UrbHeader.Status));
  189. }
  190. IoFreeIrp(irp);
  191. }
  192. else {
  193. status = STATUS_INSUFFICIENT_RESOURCES;
  194. }
  195. }
  196. else {
  197. DBGWARN(("ResetPipe - skipping reset because device not connected (status=%xh)", status));
  198. status = STATUS_SUCCESS;
  199. }
  200. return status;
  201. }
  202. #endif