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.

428 lines
12 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. packet.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. ULONG uniquePacketId = 0;
  18. USBPACKET *NewPacket(ADAPTEREXT *adapter)
  19. {
  20. USBPACKET *packet = AllocPool(sizeof(USBPACKET));
  21. if (packet){
  22. BOOLEAN allAllocsOk;
  23. packet->sig = DRIVER_SIG;
  24. packet->adapter = adapter;
  25. packet->cancelled = FALSE;
  26. InitializeListHead(&packet->listEntry);
  27. packet->irpPtr = IoAllocateIrp(adapter->nextDevObj->StackSize, FALSE);
  28. packet->urbPtr = AllocPool(sizeof(URB));
  29. packet->dataBuffer = AllocPool(PACKET_BUFFER_SIZE);
  30. packet->dataBufferMaxLength = PACKET_BUFFER_SIZE;
  31. if (packet->dataBuffer){
  32. packet->dataBufferMdl = IoAllocateMdl(packet->dataBuffer, PACKET_BUFFER_SIZE, FALSE, FALSE, NULL);
  33. }
  34. packet->dataBufferCurrentLength = 0;
  35. allAllocsOk = (packet->irpPtr && packet->urbPtr && packet->dataBuffer && packet->dataBufferMdl);
  36. if (allAllocsOk){
  37. packet->packetId = ++uniquePacketId;
  38. }
  39. else {
  40. if (packet->irpPtr) IoFreeIrp(packet->irpPtr);
  41. if (packet->urbPtr) FreePool(packet->urbPtr);
  42. if (packet->dataBuffer) FreePool(packet->dataBuffer);
  43. if (packet->dataBufferMdl) IoFreeMdl(packet->dataBufferMdl);
  44. FreePool(packet);
  45. packet = NULL;
  46. }
  47. }
  48. return packet;
  49. }
  50. VOID FreePacket(USBPACKET *packet)
  51. {
  52. PIRP irp = packet->irpPtr;
  53. ASSERT(packet->sig == DRIVER_SIG);
  54. packet->sig = 0xDEADDEAD;
  55. ASSERT(!irp->CancelRoutine);
  56. IoFreeIrp(irp);
  57. FreePool(packet->urbPtr);
  58. ASSERT(packet->dataBufferMdl);
  59. IoFreeMdl(packet->dataBufferMdl);
  60. ASSERT(packet->dataBuffer);
  61. FreePool(packet->dataBuffer);
  62. FreePool(packet);
  63. }
  64. VOID EnqueueFreePacket(USBPACKET *packet)
  65. {
  66. ADAPTEREXT *adapter = packet->adapter;
  67. KIRQL oldIrql;
  68. KeAcquireSpinLock(&adapter->adapterSpinLock, &oldIrql);
  69. ASSERT(IsListEmpty(&packet->listEntry));
  70. InsertTailList(&adapter->usbFreePacketPool, &packet->listEntry);
  71. adapter->numFreePackets++;
  72. ASSERT(adapter->numFreePackets <= USB_PACKET_POOL_SIZE);
  73. #if DBG
  74. packet->timeStamp = DbgGetSystemTime_msec();
  75. if (adapter->dbgInLowPacketStress){
  76. if (adapter->numFreePackets > USB_PACKET_POOL_SIZE/2){
  77. adapter->dbgInLowPacketStress = FALSE;
  78. DBGWARN(("recovered from low-packet stress"));
  79. }
  80. }
  81. #endif
  82. KeReleaseSpinLock(&adapter->adapterSpinLock, oldIrql);
  83. }
  84. USBPACKET *DequeueFreePacket(ADAPTEREXT *adapter)
  85. {
  86. USBPACKET *packet;
  87. KIRQL oldIrql;
  88. KeAcquireSpinLock(&adapter->adapterSpinLock, &oldIrql);
  89. if (IsListEmpty(&adapter->usbFreePacketPool)){
  90. packet = NULL;
  91. }
  92. else {
  93. PLIST_ENTRY listEntry = RemoveHeadList(&adapter->usbFreePacketPool);
  94. packet = CONTAINING_RECORD(listEntry, USBPACKET, listEntry);
  95. ASSERT(packet->sig == DRIVER_SIG);
  96. InitializeListHead(&packet->listEntry);
  97. ASSERT(adapter->numFreePackets > 0);
  98. adapter->numFreePackets--;
  99. }
  100. #if DBG
  101. if (adapter->numFreePackets < USB_PACKET_POOL_SIZE/8){
  102. if (!adapter->dbgInLowPacketStress){
  103. /*
  104. * We are entering low-packet stress.
  105. * Repeated debug spew can slow the system and actually
  106. * keep the system from recovering the packets.
  107. * So only spew a warning once.
  108. */
  109. DBGWARN(("low on free packets (%d free, %d reads, %d writes, %d indicated)", adapter->numFreePackets, adapter->numActiveReadPackets, adapter->numActiveWritePackets, adapter->numIndicatedReadPackets));
  110. adapter->dbgInLowPacketStress = TRUE;
  111. }
  112. }
  113. #endif
  114. KeReleaseSpinLock(&adapter->adapterSpinLock, oldIrql);
  115. return packet;
  116. }
  117. VOID EnqueuePendingReadPacket(USBPACKET *packet)
  118. {
  119. ADAPTEREXT *adapter = packet->adapter;
  120. KIRQL oldIrql;
  121. KeAcquireSpinLock(&adapter->adapterSpinLock, &oldIrql);
  122. ASSERT(IsListEmpty(&packet->listEntry));
  123. InsertTailList(&adapter->usbPendingReadPackets, &packet->listEntry);
  124. #if DBG
  125. packet->timeStamp = DbgGetSystemTime_msec();
  126. #endif
  127. adapter->numActiveReadPackets++;
  128. KeReleaseSpinLock(&adapter->adapterSpinLock, oldIrql);
  129. }
  130. /*
  131. * DequeuePendingReadPacket
  132. *
  133. */
  134. VOID DequeuePendingReadPacket(USBPACKET *packet)
  135. {
  136. ADAPTEREXT *adapter = packet->adapter;
  137. KIRQL oldIrql;
  138. KeAcquireSpinLock(&adapter->adapterSpinLock, &oldIrql);
  139. ASSERT(!IsListEmpty(&adapter->usbPendingReadPackets));
  140. ASSERT(!IsListEmpty(&packet->listEntry));
  141. RemoveEntryList(&packet->listEntry);
  142. ASSERT(packet->sig == DRIVER_SIG);
  143. InitializeListHead(&packet->listEntry);
  144. ASSERT(adapter->numActiveReadPackets > 0);
  145. adapter->numActiveReadPackets--;
  146. KeReleaseSpinLock(&adapter->adapterSpinLock, oldIrql);
  147. }
  148. VOID EnqueuePendingWritePacket(USBPACKET *packet)
  149. {
  150. ADAPTEREXT *adapter = packet->adapter;
  151. KIRQL oldIrql;
  152. KeAcquireSpinLock(&adapter->adapterSpinLock, &oldIrql);
  153. ASSERT(IsListEmpty(&packet->listEntry));
  154. InsertTailList(&adapter->usbPendingWritePackets, &packet->listEntry);
  155. adapter->numActiveWritePackets++;
  156. ASSERT(adapter->numActiveWritePackets <= USB_PACKET_POOL_SIZE);
  157. #if DBG
  158. packet->timeStamp = DbgGetSystemTime_msec();
  159. #endif
  160. KeReleaseSpinLock(&adapter->adapterSpinLock, oldIrql);
  161. }
  162. /*
  163. * DequeuePendingWritePacket
  164. *
  165. * Return either the indicated packet or the first packet in the pending queue.
  166. */
  167. VOID DequeuePendingWritePacket(USBPACKET *packet)
  168. {
  169. ADAPTEREXT *adapter = packet->adapter;
  170. KIRQL oldIrql;
  171. KeAcquireSpinLock(&adapter->adapterSpinLock, &oldIrql);
  172. ASSERT(!IsListEmpty(&adapter->usbPendingWritePackets));
  173. ASSERT(!IsListEmpty(&packet->listEntry));
  174. RemoveEntryList(&packet->listEntry);
  175. ASSERT(adapter->numActiveWritePackets > 0);
  176. adapter->numActiveWritePackets--;
  177. ASSERT(packet->sig == DRIVER_SIG);
  178. InitializeListHead(&packet->listEntry);
  179. KeReleaseSpinLock(&adapter->adapterSpinLock, oldIrql);
  180. }
  181. VOID EnqueueCompletedReadPacket(USBPACKET *packet)
  182. {
  183. ADAPTEREXT *adapter = packet->adapter;
  184. KIRQL oldIrql;
  185. KeAcquireSpinLock(&adapter->adapterSpinLock, &oldIrql);
  186. ASSERT(IsListEmpty(&packet->listEntry));
  187. InsertTailList(&adapter->usbCompletedReadPackets, &packet->listEntry);
  188. #if DBG
  189. packet->timeStamp = DbgGetSystemTime_msec();
  190. #endif
  191. adapter->numIndicatedReadPackets++;
  192. KeReleaseSpinLock(&adapter->adapterSpinLock, oldIrql);
  193. }
  194. VOID DequeueCompletedReadPacket(USBPACKET *packet)
  195. {
  196. ADAPTEREXT *adapter = packet->adapter;
  197. KIRQL oldIrql;
  198. PLIST_ENTRY listEntry;
  199. KeAcquireSpinLock(&adapter->adapterSpinLock, &oldIrql);
  200. ASSERT(!IsListEmpty(&adapter->usbCompletedReadPackets));
  201. ASSERT(!IsListEmpty(&packet->listEntry));
  202. RemoveEntryList(&packet->listEntry);
  203. InitializeListHead(&packet->listEntry);
  204. ASSERT(adapter->numIndicatedReadPackets > 0);
  205. adapter->numIndicatedReadPackets--;
  206. KeReleaseSpinLock(&adapter->adapterSpinLock, oldIrql);
  207. }
  208. VOID CancelAllPendingPackets(ADAPTEREXT *adapter)
  209. {
  210. PLIST_ENTRY listEntry;
  211. USBPACKET *packet;
  212. PIRP irp;
  213. KIRQL oldIrql;
  214. ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
  215. KeAcquireSpinLock(&adapter->adapterSpinLock, &oldIrql);
  216. /*
  217. * Cancel all pending READs.
  218. */
  219. while (!IsListEmpty(&adapter->usbPendingReadPackets)){
  220. listEntry = RemoveHeadList(&adapter->usbPendingReadPackets);
  221. packet = CONTAINING_RECORD(listEntry, USBPACKET, listEntry);
  222. irp = packet->irpPtr;
  223. ASSERT(packet->sig == DRIVER_SIG);
  224. /*
  225. * Leave the IRP in the list when we cancel it so that completion routine
  226. * can move it to the free list.
  227. */
  228. InsertTailList(&adapter->usbPendingReadPackets, &packet->listEntry);
  229. KeInitializeEvent(&packet->cancelEvent, NotificationEvent, FALSE);
  230. ASSERT(!packet->cancelled);
  231. packet->cancelled = TRUE;
  232. KeReleaseSpinLock(&adapter->adapterSpinLock, oldIrql);
  233. DBGVERBOSE((" - cancelling pending read packet #%xh @ %ph, irp=%ph ...", packet->packetId, packet, irp));
  234. IoCancelIrp(irp);
  235. /*
  236. * Wait for the completion routine to run and set the cancelEvent.
  237. * By the time we get done waiting, the packet should be back in the free list.
  238. */
  239. KeWaitForSingleObject(&packet->cancelEvent, Executive, KernelMode, FALSE, NULL);
  240. KeAcquireSpinLock(&adapter->adapterSpinLock, &oldIrql);
  241. }
  242. ASSERT(IsListEmpty(&adapter->usbPendingReadPackets));
  243. /*
  244. * Cancel all pending WRITEs.
  245. */
  246. while (!IsListEmpty(&adapter->usbPendingWritePackets)){
  247. listEntry = RemoveHeadList(&adapter->usbPendingWritePackets);
  248. packet = CONTAINING_RECORD(listEntry, USBPACKET, listEntry);
  249. irp = packet->irpPtr;
  250. ASSERT(packet->sig == DRIVER_SIG);
  251. /*
  252. * Leave the IRP in the list when we cancel it so that completion routine
  253. * can move it to the free list.
  254. */
  255. InsertTailList(&adapter->usbPendingWritePackets, &packet->listEntry);
  256. KeInitializeEvent(&packet->cancelEvent, NotificationEvent, FALSE);
  257. ASSERT(!packet->cancelled);
  258. packet->cancelled = TRUE;
  259. KeReleaseSpinLock(&adapter->adapterSpinLock, oldIrql);
  260. DBGVERBOSE((" - cancelling pending write packet #%xh @ %ph, irp=%ph ...", packet->packetId, packet, irp));
  261. IoCancelIrp(irp);
  262. /*
  263. * Wait for the completion routine to run and set the cancelEvent.
  264. * By the time we get done waiting, the packet should be back in the free list.
  265. */
  266. KeWaitForSingleObject(&packet->cancelEvent, Executive, KernelMode, FALSE, NULL);
  267. KeAcquireSpinLock(&adapter->adapterSpinLock, &oldIrql);
  268. }
  269. ASSERT(IsListEmpty(&adapter->usbPendingWritePackets));
  270. /*
  271. * Cancel the read on the NOTIFY pipe.
  272. */
  273. if (adapter->notifyPipeHandle){
  274. /*
  275. * Make sure we've actually sent the notify irp before trying
  276. * to cancel it; otherwise, we hang forever waiting for it to complete.
  277. */
  278. if (adapter->initialized){
  279. if (adapter->notifyStopped){
  280. /*
  281. * The notify irp has already stopped looping because it returned with error
  282. * in NotificationCompletion. Don't cancel it because we'll hang forever
  283. * waiting for it to complete.
  284. */
  285. DBGVERBOSE(("CancelAllPendingPackets: notify irp already stopped, no need to cancel"));
  286. }
  287. else {
  288. KeInitializeEvent(&adapter->notifyCancelEvent, NotificationEvent, FALSE);
  289. adapter->cancellingNotify = TRUE;
  290. KeReleaseSpinLock(&adapter->adapterSpinLock, oldIrql);
  291. DBGVERBOSE((" - cancelling notify irp = %ph ...", adapter->notifyIrpPtr));
  292. IoCancelIrp(adapter->notifyIrpPtr);
  293. KeWaitForSingleObject(&adapter->notifyCancelEvent, Executive, KernelMode, FALSE, NULL);
  294. KeAcquireSpinLock(&adapter->adapterSpinLock, &oldIrql);
  295. adapter->cancellingNotify = FALSE;
  296. }
  297. }
  298. }
  299. adapter->readDeficit = 0;
  300. KeReleaseSpinLock(&adapter->adapterSpinLock, oldIrql);
  301. }