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.

1829 lines
48 KiB

  1. /*++
  2. Copyright (c) 1989, 1990, 1991 Microsoft Corporation
  3. Module Name:
  4. packet.c
  5. Abstract:
  6. This module contains code that implements the TP_PACKET object, which
  7. describes a DLC I-frame at some point in its lifetime. Routines are
  8. provided to allocate packets for shipment, to ship packets, to reference
  9. packets, to dereference packets, to mark a connection as waiting for a
  10. packet to become available, to satisfy the next waiting connection for
  11. a packet, and to destroy packets (return them to the pool).
  12. Author:
  13. David Beaver (dbeaver) 1-July-1991
  14. Environment:
  15. Kernel mode
  16. Revision History:
  17. --*/
  18. #include "precomp.h"
  19. #pragma hdrstop
  20. //
  21. // This is temporary; this is the quota that we charge for a receive
  22. // packet for now, until we fix the problem with token-ring needing
  23. // big packets and using all the memory. The number is the actual
  24. // value for Ethernet.
  25. //
  26. #if 1
  27. #define RECEIVE_BUFFER_QUOTA(_DeviceContext) 1533
  28. #else
  29. #define RECEIVE_BUFFER_QUOTA(_DeviceContext) (_DeviceContext)->ReceiveBufferLength
  30. #endif
  31. #define PACKET_POOL_GROW_COUNT 32
  32. #if DBG
  33. ULONG NbfCreatePacketThreshold = 5;
  34. extern ULONG NbfPacketPanic;
  35. #endif
  36. NDIS_STATUS
  37. NbfAllocateNdisSendPacket(
  38. IN PDEVICE_CONTEXT DeviceContext,
  39. OUT PNDIS_PACKET *NdisPacket
  40. )
  41. /*++
  42. Routine Description:
  43. This routine allocates a recieve packet from the receive packet pool.
  44. It Grows the packet pool if necessary.
  45. NOTE: This routine is called with the device context spinlock
  46. held, or at such a time as synchronization is unnecessary.
  47. Arguments:
  48. DeviceContext - Pointer to our device context to charge the packet to.
  49. UIFrame - Returns a pointer to the frame, or NULL if no storage
  50. can be allocated.
  51. Return Value:
  52. None.
  53. --*/
  54. {
  55. PNBF_POOL_LIST_DESC SendPacketPoolDesc;
  56. NDIS_STATUS NdisStatus;
  57. KIRQL oldirql;
  58. NdisStatus = NDIS_STATUS_RESOURCES;
  59. ACQUIRE_SPIN_LOCK (&DeviceContext->SendPoolListLock, &oldirql);
  60. for (SendPacketPoolDesc = DeviceContext->SendPacketPoolDesc;
  61. SendPacketPoolDesc != NULL;
  62. SendPacketPoolDesc = SendPacketPoolDesc->Next) {
  63. NdisAllocatePacket (
  64. &NdisStatus,
  65. NdisPacket,
  66. SendPacketPoolDesc->PoolHandle);
  67. if (NdisStatus == NDIS_STATUS_SUCCESS) {
  68. RELEASE_SPIN_LOCK (&DeviceContext->SendPoolListLock, oldirql);
  69. return(NdisStatus);
  70. }
  71. }
  72. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  73. if ((DeviceContext->MemoryLimit != 0) &&
  74. ((DeviceContext->MemoryUsage +
  75. PACKET_POOL_GROW_COUNT *
  76. (sizeof(NDIS_PACKET) + sizeof(SEND_PACKET_TAG))) >
  77. DeviceContext->MemoryLimit)) {
  78. PANIC("NBF: Could not grow packet pool: limit\n");
  79. NbfWriteResourceErrorLog(
  80. DeviceContext,
  81. EVENT_TRANSPORT_RESOURCE_LIMIT,
  82. 106,
  83. DeviceContext->UIFrameLength,
  84. UI_FRAME_RESOURCE_ID);
  85. RELEASE_SPIN_LOCK (&DeviceContext->SendPoolListLock, oldirql);
  86. return(NdisStatus);
  87. }
  88. }
  89. DeviceContext->MemoryUsage +=
  90. (PACKET_POOL_GROW_COUNT *
  91. (sizeof(NDIS_PACKET) + sizeof(SEND_PACKET_TAG)));
  92. // Allocate Packet pool descriptors for dynamic packet allocation.
  93. SendPacketPoolDesc = ExAllocatePoolWithTag(
  94. NonPagedPool,
  95. sizeof(NBF_POOL_LIST_DESC),
  96. NBF_MEM_TAG_POOL_DESC);
  97. if (SendPacketPoolDesc == NULL) {
  98. RELEASE_SPIN_LOCK (&DeviceContext->SendPoolListLock, oldirql);
  99. return(NdisStatus);
  100. }
  101. RtlZeroMemory(SendPacketPoolDesc, sizeof(NBF_POOL_LIST_DESC));
  102. SendPacketPoolDesc->NumElements =
  103. SendPacketPoolDesc->TotalElements = PACKET_POOL_GROW_COUNT;
  104. // To track packet pools in NDIS allocated on NBF's behalf
  105. #if NDIS_POOL_TAGGING
  106. SendPacketPoolDesc->PoolHandle = (NDIS_HANDLE) NDIS_PACKET_POOL_TAG_FOR_NBF;
  107. #endif
  108. NdisAllocatePacketPoolEx ( &NdisStatus, &SendPacketPoolDesc->PoolHandle,
  109. PACKET_POOL_GROW_COUNT, 0, sizeof (SEND_PACKET_TAG));
  110. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  111. #if DBG
  112. NbfPrint1 ("NbfGrowSendPacketPool: NdisInitializePacketPool failed, reason: %s.\n",
  113. NbfGetNdisStatus (NdisStatus));
  114. #endif
  115. RELEASE_SPIN_LOCK (&DeviceContext->SendPoolListLock, oldirql);
  116. ExFreePool (SendPacketPoolDesc);
  117. return(NdisStatus);
  118. }
  119. NdisSetPacketPoolProtocolId (SendPacketPoolDesc->PoolHandle, NDIS_PROTOCOL_ID_NBF);
  120. SendPacketPoolDesc->Next = DeviceContext->SendPacketPoolDesc;
  121. DeviceContext->SendPacketPoolDesc = SendPacketPoolDesc;
  122. RELEASE_SPIN_LOCK (&DeviceContext->SendPoolListLock, oldirql);
  123. NdisAllocatePacket ( &NdisStatus, NdisPacket,
  124. SendPacketPoolDesc->PoolHandle);
  125. return(NdisStatus);
  126. }
  127. NDIS_STATUS
  128. NbfAllocateNdisRcvPacket(
  129. IN PDEVICE_CONTEXT DeviceContext,
  130. OUT PNDIS_PACKET *NdisPacket
  131. )
  132. /*++
  133. Routine Description:
  134. This routine allocates a recieve packet from the receive packet pool.
  135. It Grows the packet pool if necessary.
  136. NOTE: This routine is called with the device context spinlock
  137. held, or at such a time as synchronization is unnecessary.
  138. Arguments:
  139. DeviceContext - Pointer to our device context to charge the packet to.
  140. UIFrame - Returns a pointer to the frame, or NULL if no storage
  141. can be allocated.
  142. Return Value:
  143. None.
  144. --*/
  145. {
  146. PNBF_POOL_LIST_DESC RcvPacketPoolDesc;
  147. NDIS_STATUS NdisStatus;
  148. KIRQL oldirql;
  149. NdisStatus = NDIS_STATUS_RESOURCES;
  150. ACQUIRE_SPIN_LOCK (&DeviceContext->RcvPoolListLock, &oldirql);
  151. for (RcvPacketPoolDesc = DeviceContext->ReceivePacketPoolDesc;
  152. RcvPacketPoolDesc != NULL;
  153. RcvPacketPoolDesc = RcvPacketPoolDesc->Next) {
  154. NdisAllocatePacket (
  155. &NdisStatus,
  156. NdisPacket,
  157. RcvPacketPoolDesc->PoolHandle);
  158. if (NdisStatus == NDIS_STATUS_SUCCESS) {
  159. RELEASE_SPIN_LOCK (&DeviceContext->RcvPoolListLock, oldirql);
  160. return(NdisStatus);
  161. }
  162. }
  163. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  164. if ((DeviceContext->MemoryLimit != 0) &&
  165. ((DeviceContext->MemoryUsage +
  166. PACKET_POOL_GROW_COUNT *
  167. (sizeof(NDIS_PACKET) + sizeof(SEND_PACKET_TAG))) >
  168. DeviceContext->MemoryLimit)) {
  169. PANIC("NBF: Could not grow packet pool: limit\n");
  170. NbfWriteResourceErrorLog(
  171. DeviceContext,
  172. EVENT_TRANSPORT_RESOURCE_LIMIT,
  173. 106,
  174. DeviceContext->UIFrameLength,
  175. UI_FRAME_RESOURCE_ID);
  176. RELEASE_SPIN_LOCK (&DeviceContext->RcvPoolListLock, oldirql);
  177. return(NdisStatus);
  178. }
  179. }
  180. DeviceContext->MemoryUsage +=
  181. (PACKET_POOL_GROW_COUNT *
  182. (sizeof(NDIS_PACKET) + sizeof(SEND_PACKET_TAG)));
  183. // Allocate Packet pool descriptors for dynamic packet allocation.
  184. RcvPacketPoolDesc = ExAllocatePoolWithTag(
  185. NonPagedPool,
  186. sizeof(NBF_POOL_LIST_DESC),
  187. NBF_MEM_TAG_POOL_DESC);
  188. if (RcvPacketPoolDesc == NULL) {
  189. RELEASE_SPIN_LOCK (&DeviceContext->RcvPoolListLock, oldirql);
  190. return(NdisStatus);
  191. }
  192. RtlZeroMemory(RcvPacketPoolDesc, sizeof(NBF_POOL_LIST_DESC));
  193. RcvPacketPoolDesc->NumElements =
  194. RcvPacketPoolDesc->TotalElements = PACKET_POOL_GROW_COUNT;
  195. // To track packet pools in NDIS allocated on NBF's behalf
  196. #if NDIS_POOL_TAGGING
  197. RcvPacketPoolDesc->PoolHandle = (NDIS_HANDLE) NDIS_PACKET_POOL_TAG_FOR_NBF;
  198. #endif
  199. NdisAllocatePacketPoolEx ( &NdisStatus, &RcvPacketPoolDesc->PoolHandle,
  200. PACKET_POOL_GROW_COUNT, 0, sizeof (RECEIVE_PACKET_TAG));
  201. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  202. #if DBG
  203. NbfPrint1 ("NbfGrowSendPacketPool: NdisInitializePacketPool failed, reason: %s.\n",
  204. NbfGetNdisStatus (NdisStatus));
  205. #endif
  206. RELEASE_SPIN_LOCK (&DeviceContext->RcvPoolListLock, oldirql);
  207. ExFreePool (RcvPacketPoolDesc);
  208. return(NdisStatus);
  209. }
  210. NdisSetPacketPoolProtocolId (RcvPacketPoolDesc->PoolHandle, NDIS_PROTOCOL_ID_NBF);
  211. RcvPacketPoolDesc->Next = DeviceContext->ReceivePacketPoolDesc;
  212. DeviceContext->ReceivePacketPoolDesc = RcvPacketPoolDesc;
  213. RELEASE_SPIN_LOCK (&DeviceContext->RcvPoolListLock, oldirql);
  214. NdisAllocatePacket ( &NdisStatus, NdisPacket,
  215. RcvPacketPoolDesc->PoolHandle);
  216. return(NdisStatus);
  217. }
  218. VOID
  219. NbfAllocateUIFrame(
  220. IN PDEVICE_CONTEXT DeviceContext,
  221. OUT PTP_UI_FRAME *TransportUIFrame
  222. )
  223. /*++
  224. Routine Description:
  225. This routine allocates storage for a UI frame. Some initialization
  226. is done here.
  227. NOTE: This routine is called with the device context spinlock
  228. held, or at such a time as synchronization is unnecessary.
  229. Arguments:
  230. DeviceContext - Pointer to our device context to charge the packet to.
  231. UIFrame - Returns a pointer to the frame, or NULL if no storage
  232. can be allocated.
  233. Return Value:
  234. None.
  235. --*/
  236. {
  237. NDIS_STATUS NdisStatus;
  238. PNDIS_PACKET NdisPacket;
  239. PSEND_PACKET_TAG SendTag;
  240. PTP_UI_FRAME UIFrame;
  241. PNDIS_BUFFER NdisBuffer;
  242. PNBF_POOL_LIST_DESC SendPacketPoolDesc;
  243. if ((DeviceContext->MemoryLimit != 0) &&
  244. ((DeviceContext->MemoryUsage + DeviceContext->UIFrameLength) >
  245. DeviceContext->MemoryLimit)) {
  246. PANIC("NBF: Could not allocate UI frame: limit\n");
  247. NbfWriteResourceErrorLog(
  248. DeviceContext,
  249. EVENT_TRANSPORT_RESOURCE_LIMIT,
  250. 106,
  251. DeviceContext->UIFrameLength,
  252. UI_FRAME_RESOURCE_ID);
  253. *TransportUIFrame = NULL;
  254. return;
  255. }
  256. UIFrame = (PTP_UI_FRAME) ExAllocatePoolWithTag (
  257. NonPagedPool,
  258. DeviceContext->UIFrameLength,
  259. NBF_MEM_TAG_TP_UI_FRAME);
  260. if (UIFrame == NULL) {
  261. PANIC("NBF: Could not allocate UI frame: no pool\n");
  262. NbfWriteResourceErrorLog(
  263. DeviceContext,
  264. EVENT_TRANSPORT_RESOURCE_POOL,
  265. 206,
  266. DeviceContext->UIFrameLength,
  267. UI_FRAME_RESOURCE_ID);
  268. *TransportUIFrame = NULL;
  269. return;
  270. }
  271. RtlZeroMemory (UIFrame, DeviceContext->UIFrameLength);
  272. DeviceContext->MemoryUsage += DeviceContext->UIFrameLength;
  273. NdisStatus = NbfAllocateNdisSendPacket(DeviceContext, &NdisPacket);
  274. #if 0
  275. for (SendPacketPoolDesc = DeviceContext->SendPacketPoolDesc;
  276. SendPacketPoolDesc != NULL;
  277. SendPacketPoolDesc = SendPacketPoolDesc->Next) {
  278. NdisAllocatePacket (
  279. &NdisStatus,
  280. &NdisPacket,
  281. SendPacketPoolDesc->PoolHandle);
  282. if (NdisStatus == NDIS_STATUS_SUCCESS)
  283. break;
  284. }
  285. #endif
  286. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  287. ExFreePool (UIFrame);
  288. #if 0
  289. NbfWriteResourceErrorLog(
  290. DeviceContext,
  291. EVENT_TRANSPORT_RESOURCE_SPECIFIC,
  292. 306,
  293. 0,
  294. UI_FRAME_RESOURCE_ID);
  295. #endif
  296. *TransportUIFrame = NULL;
  297. return;
  298. }
  299. UIFrame->NdisPacket = NdisPacket;
  300. UIFrame->DataBuffer = NULL;
  301. SendTag = (PSEND_PACKET_TAG)NdisPacket->ProtocolReserved;
  302. SendTag->Type = TYPE_UI_FRAME;
  303. SendTag->Frame = UIFrame;
  304. SendTag->Owner = DeviceContext;
  305. //
  306. // Make the packet header known to the packet descriptor
  307. //
  308. NdisAllocateBuffer(
  309. &NdisStatus,
  310. &NdisBuffer,
  311. DeviceContext->NdisBufferPool,
  312. UIFrame->Header,
  313. DeviceContext->UIFrameHeaderLength);
  314. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  315. NbfWriteResourceErrorLog(
  316. DeviceContext,
  317. EVENT_TRANSPORT_RESOURCE_SPECIFIC,
  318. 406,
  319. 0,
  320. UI_FRAME_RESOURCE_ID);
  321. NdisFreePacket (NdisPacket);
  322. ExFreePool (UIFrame);
  323. *TransportUIFrame = NULL;
  324. return;
  325. }
  326. NdisChainBufferAtFront (NdisPacket, NdisBuffer);
  327. ++DeviceContext->UIFrameAllocated;
  328. *TransportUIFrame = UIFrame;
  329. } /* NbfAllocateUIFrame */
  330. VOID
  331. NbfDeallocateUIFrame(
  332. IN PDEVICE_CONTEXT DeviceContext,
  333. IN PTP_UI_FRAME TransportUIFrame
  334. )
  335. /*++
  336. Routine Description:
  337. This routine frees storage for a UI frame.
  338. NOTE: This routine is called with the device context spinlock
  339. held, or at such a time as synchronization is unnecessary.
  340. Arguments:
  341. DeviceContext - Pointer to our device context to charge the packet to.
  342. UIFrame - A pointer to the frame.
  343. Return Value:
  344. None.
  345. --*/
  346. {
  347. PNDIS_PACKET NdisPacket = TransportUIFrame->NdisPacket;
  348. PNDIS_BUFFER NdisBuffer;
  349. NdisUnchainBufferAtFront (NdisPacket, &NdisBuffer);
  350. if (NdisBuffer != NULL) {
  351. NdisFreeBuffer (NdisBuffer);
  352. }
  353. NdisFreePacket (NdisPacket);
  354. ExFreePool (TransportUIFrame);
  355. --DeviceContext->UIFrameAllocated;
  356. DeviceContext->MemoryUsage -= DeviceContext->UIFrameLength;
  357. } /* NbfDeallocateUIFrame */
  358. VOID
  359. NbfAllocateSendPacket(
  360. IN PDEVICE_CONTEXT DeviceContext,
  361. OUT PTP_PACKET *TransportSendPacket
  362. )
  363. /*++
  364. Routine Description:
  365. This routine allocates storage for a send packet. Some initialization
  366. is done here.
  367. NOTE: This routine is called with the device context spinlock
  368. held, or at such a time as synchronization is unnecessary.
  369. Arguments:
  370. DeviceContext - Pointer to our device context to charge the packet to.
  371. TransportSendPacket - Returns a pointer to the packet, or NULL if no
  372. storage can be allocated.
  373. Return Value:
  374. None.
  375. --*/
  376. {
  377. PTP_PACKET Packet;
  378. NDIS_STATUS NdisStatus;
  379. PNDIS_PACKET NdisPacket;
  380. PSEND_PACKET_TAG SendTag;
  381. PNDIS_BUFFER NdisBuffer;
  382. PNBF_POOL_LIST_DESC SendPacketPoolDesc;
  383. if ((DeviceContext->MemoryLimit != 0) &&
  384. ((DeviceContext->MemoryUsage + DeviceContext->PacketLength) >
  385. DeviceContext->MemoryLimit)) {
  386. PANIC("NBF: Could not allocate send packet: limit\n");
  387. NbfWriteResourceErrorLog(
  388. DeviceContext,
  389. EVENT_TRANSPORT_RESOURCE_LIMIT,
  390. 107,
  391. DeviceContext->PacketLength,
  392. PACKET_RESOURCE_ID);
  393. *TransportSendPacket = NULL;
  394. return;
  395. }
  396. Packet = (PTP_PACKET)ExAllocatePoolWithTag (
  397. NonPagedPool,
  398. DeviceContext->PacketLength,
  399. NBF_MEM_TAG_TP_PACKET);
  400. if (Packet == NULL) {
  401. PANIC("NBF: Could not allocate send packet: no pool\n");
  402. NbfWriteResourceErrorLog(
  403. DeviceContext,
  404. EVENT_TRANSPORT_RESOURCE_POOL,
  405. 207,
  406. DeviceContext->PacketLength,
  407. PACKET_RESOURCE_ID);
  408. *TransportSendPacket = NULL;
  409. return;
  410. }
  411. RtlZeroMemory (Packet, DeviceContext->PacketLength);
  412. DeviceContext->MemoryUsage += DeviceContext->PacketLength;
  413. NdisStatus = NbfAllocateNdisSendPacket(DeviceContext, &NdisPacket);
  414. #if 0
  415. for (SendPacketPoolDesc = DeviceContext->SendPacketPoolDesc;
  416. SendPacketPoolDesc != NULL;
  417. SendPacketPoolDesc = SendPacketPoolDesc->Next) {
  418. NdisAllocatePacket (
  419. &NdisStatus,
  420. &NdisPacket,
  421. SendPacketPoolDesc->PoolHandle);
  422. if (NdisStatus == NDIS_STATUS_SUCCESS)
  423. break;
  424. }
  425. #endif
  426. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  427. ExFreePool (Packet);
  428. #if 0
  429. NbfWriteResourceErrorLog(
  430. DeviceContext,
  431. EVENT_TRANSPORT_RESOURCE_SPECIFIC,
  432. 307,
  433. 0,
  434. PACKET_RESOURCE_ID);
  435. #endif
  436. *TransportSendPacket = NULL;
  437. return;
  438. }
  439. NdisAllocateBuffer(
  440. &NdisStatus,
  441. &NdisBuffer,
  442. DeviceContext->NdisBufferPool,
  443. Packet->Header,
  444. DeviceContext->PacketHeaderLength);
  445. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  446. NbfWriteResourceErrorLog(
  447. DeviceContext,
  448. EVENT_TRANSPORT_RESOURCE_SPECIFIC,
  449. 407,
  450. 0,
  451. PACKET_RESOURCE_ID);
  452. NdisFreePacket (NdisPacket);
  453. ExFreePool (Packet);
  454. *TransportSendPacket = NULL;
  455. return;
  456. }
  457. NdisChainBufferAtFront (NdisPacket, NdisBuffer);
  458. Packet->NdisPacket = NdisPacket;
  459. SendTag = (PSEND_PACKET_TAG)NdisPacket->ProtocolReserved;
  460. SendTag->Type = TYPE_I_FRAME;
  461. SendTag->Frame = Packet;
  462. SendTag->Owner = DeviceContext;
  463. Packet->Type = NBF_PACKET_SIGNATURE;
  464. Packet->Size = sizeof (TP_PACKET);
  465. Packet->Provider = DeviceContext;
  466. Packet->Owner = NULL; // no connection/irpsp yet.
  467. Packet->Action = PACKET_ACTION_IRP_SP;
  468. Packet->PacketizeConnection = FALSE;
  469. Packet->PacketNoNdisBuffer = FALSE;
  470. Packet->ProviderInterlock = &DeviceContext->Interlock;
  471. // KeInitializeSpinLock (&Packet->Interlock);
  472. ++DeviceContext->PacketAllocated;
  473. *TransportSendPacket = Packet;
  474. } /* NbfAllocateSendPacket */
  475. VOID
  476. NbfDeallocateSendPacket(
  477. IN PDEVICE_CONTEXT DeviceContext,
  478. IN PTP_PACKET TransportSendPacket
  479. )
  480. /*++
  481. Routine Description:
  482. This routine frees storage for a send packet.
  483. NOTE: This routine is called with the device context spinlock
  484. held, or at such a time as synchronization is unnecessary.
  485. Arguments:
  486. DeviceContext - Pointer to our device context to charge the packet to.
  487. TransportSendPacket - A pointer to the send packet.
  488. Return Value:
  489. None.
  490. --*/
  491. {
  492. PNDIS_PACKET NdisPacket = TransportSendPacket->NdisPacket;
  493. PNDIS_BUFFER NdisBuffer;
  494. NdisUnchainBufferAtFront (NdisPacket, &NdisBuffer);
  495. if (NdisBuffer != NULL) {
  496. NdisFreeBuffer (NdisBuffer);
  497. }
  498. NdisFreePacket (NdisPacket);
  499. ExFreePool (TransportSendPacket);
  500. --DeviceContext->PacketAllocated;
  501. DeviceContext->MemoryUsage -= DeviceContext->PacketLength;
  502. } /* NbfDeallocateSendPacket */
  503. VOID
  504. NbfAllocateReceivePacket(
  505. IN PDEVICE_CONTEXT DeviceContext,
  506. OUT PNDIS_PACKET *TransportReceivePacket
  507. )
  508. /*++
  509. Routine Description:
  510. This routine allocates storage for a receive packet. Some initialization
  511. is done here.
  512. NOTE: This routine is called with the device context spinlock
  513. held, or at such a time as synchronization is unnecessary.
  514. Arguments:
  515. DeviceContext - Pointer to our device context to charge the packet to.
  516. TransportReceivePacket - Returns a pointer to the packet, or NULL if no
  517. storage can be allocated.
  518. Return Value:
  519. None.
  520. --*/
  521. {
  522. NDIS_STATUS NdisStatus;
  523. PNDIS_PACKET NdisPacket;
  524. PRECEIVE_PACKET_TAG ReceiveTag;
  525. //
  526. // This does not count in DeviceContext->MemoryUsage because
  527. // the storage is allocated when we allocate the packet pool.
  528. //
  529. NdisStatus = NbfAllocateNdisRcvPacket(DeviceContext, &NdisPacket);
  530. #if 0
  531. NdisAllocatePacket (
  532. &NdisStatus,
  533. &NdisPacket,
  534. DeviceContext->ReceivePacketPoolDesc->PoolHandle);
  535. #endif
  536. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  537. #if 0
  538. NbfWriteResourceErrorLog(
  539. DeviceContext,
  540. EVENT_TRANSPORT_RESOURCE_SPECIFIC,
  541. 309,
  542. 0,
  543. RECEIVE_PACKET_RESOURCE_ID);
  544. #endif
  545. *TransportReceivePacket = NULL;
  546. return;
  547. }
  548. ReceiveTag = (PRECEIVE_PACKET_TAG)(NdisPacket->ProtocolReserved);
  549. ReceiveTag->PacketType = TYPE_AT_INDICATE;
  550. ++DeviceContext->ReceivePacketAllocated;
  551. *TransportReceivePacket = NdisPacket;
  552. } /* NbfAllocateReceivePacket */
  553. VOID
  554. NbfDeallocateReceivePacket(
  555. IN PDEVICE_CONTEXT DeviceContext,
  556. IN PNDIS_PACKET TransportReceivePacket
  557. )
  558. /*++
  559. Routine Description:
  560. This routine frees storage for a receive packet.
  561. NOTE: This routine is called with the device context spinlock
  562. held, or at such a time as synchronization is unnecessary.
  563. Arguments:
  564. DeviceContext - Pointer to our device context to charge the packet to.
  565. TransportReceivePacket - A pointer to the packet.
  566. Return Value:
  567. None.
  568. --*/
  569. {
  570. NdisFreePacket (TransportReceivePacket);
  571. --DeviceContext->ReceivePacketAllocated;
  572. } /* NbfDeallocateReceivePacket */
  573. VOID
  574. NbfAllocateReceiveBuffer(
  575. IN PDEVICE_CONTEXT DeviceContext,
  576. OUT PBUFFER_TAG *TransportReceiveBuffer
  577. )
  578. /*++
  579. Routine Description:
  580. This routine allocates storage for a receive buffer. Some initialization
  581. is done here.
  582. NOTE: This routine is called with the device context spinlock
  583. held, or at such a time as synchronization is unnecessary.
  584. Arguments:
  585. DeviceContext - Pointer to our device context to charge the packet to.
  586. TransportReceiveBuffer - Returns a pointer to the buffer, or NULL if no
  587. storage can be allocated.
  588. Return Value:
  589. None.
  590. --*/
  591. {
  592. PBUFFER_TAG BufferTag;
  593. NDIS_STATUS NdisStatus;
  594. PNDIS_BUFFER NdisBuffer;
  595. if ((DeviceContext->MemoryLimit != 0) &&
  596. ((DeviceContext->MemoryUsage + RECEIVE_BUFFER_QUOTA(DeviceContext)) >
  597. DeviceContext->MemoryLimit)) {
  598. PANIC("NBF: Could not allocate receive buffer: limit\n");
  599. NbfWriteResourceErrorLog(
  600. DeviceContext,
  601. EVENT_TRANSPORT_RESOURCE_LIMIT,
  602. 108,
  603. RECEIVE_BUFFER_QUOTA(DeviceContext),
  604. RECEIVE_BUFFER_RESOURCE_ID);
  605. *TransportReceiveBuffer = NULL;
  606. return;
  607. }
  608. //
  609. // The Aligned doesn't help since the header makes it unaligned.
  610. //
  611. BufferTag = (PBUFFER_TAG)ExAllocatePoolWithTag (
  612. NonPagedPoolCacheAligned,
  613. DeviceContext->ReceiveBufferLength,
  614. NBF_MEM_TAG_RCV_BUFFER);
  615. if (BufferTag == NULL) {
  616. PANIC("NBF: Could not allocate receive buffer: no pool\n");
  617. NbfWriteResourceErrorLog(
  618. DeviceContext,
  619. EVENT_TRANSPORT_RESOURCE_POOL,
  620. 208,
  621. DeviceContext->ReceiveBufferLength,
  622. RECEIVE_BUFFER_RESOURCE_ID);
  623. *TransportReceiveBuffer = NULL;
  624. return;
  625. }
  626. DeviceContext->MemoryUsage += RECEIVE_BUFFER_QUOTA(DeviceContext);
  627. //
  628. // point to the buffer for NDIS
  629. //
  630. NdisAllocateBuffer(
  631. &NdisStatus,
  632. &NdisBuffer,
  633. DeviceContext->NdisBufferPool,
  634. BufferTag->Buffer,
  635. DeviceContext->MaxReceivePacketSize);
  636. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  637. PANIC("NBF: Could not allocate receive buffer: no buffer\n");
  638. NbfWriteResourceErrorLog(
  639. DeviceContext,
  640. EVENT_TRANSPORT_RESOURCE_SPECIFIC,
  641. 308,
  642. 0,
  643. RECEIVE_BUFFER_RESOURCE_ID);
  644. ExFreePool (BufferTag);
  645. *TransportReceiveBuffer = NULL;
  646. return;
  647. }
  648. BufferTag->Length = DeviceContext->MaxReceivePacketSize;
  649. BufferTag->NdisBuffer = NdisBuffer;
  650. ++DeviceContext->ReceiveBufferAllocated;
  651. *TransportReceiveBuffer = BufferTag;
  652. } /* NbfAllocateReceiveBuffer */
  653. VOID
  654. NbfDeallocateReceiveBuffer(
  655. IN PDEVICE_CONTEXT DeviceContext,
  656. IN PBUFFER_TAG TransportReceiveBuffer
  657. )
  658. /*++
  659. Routine Description:
  660. This routine frees storage for a receive buffer.
  661. NOTE: This routine is called with the device context spinlock
  662. held, or at such a time as synchronization is unnecessary.
  663. Arguments:
  664. DeviceContext - Pointer to our device context to charge the packet to.
  665. TransportReceiveBuffer - A pointer to the buffer.
  666. Return Value:
  667. None.
  668. --*/
  669. {
  670. NdisFreeBuffer (TransportReceiveBuffer->NdisBuffer);
  671. ExFreePool (TransportReceiveBuffer);
  672. --DeviceContext->ReceiveBufferAllocated;
  673. DeviceContext->MemoryUsage -= RECEIVE_BUFFER_QUOTA(DeviceContext);
  674. } /* NbfDeallocateReceiveBuffer */
  675. NTSTATUS
  676. NbfCreatePacket(
  677. PDEVICE_CONTEXT DeviceContext,
  678. PTP_LINK Link,
  679. PTP_PACKET *Packet
  680. )
  681. /*++
  682. Routine Description:
  683. This routine allocates a packet from the device context's pool,
  684. and prepares the MAC and DLC headers for use by the connection.
  685. Arguments:
  686. DeviceContext - Pointer to our device context to charge the packet to.
  687. Link - The link the packet will be sent over.
  688. Packet - Pointer to a place where we will return a pointer to the
  689. allocated packet.
  690. Return Value:
  691. NTSTATUS - status of operation.
  692. --*/
  693. {
  694. KIRQL oldirql;
  695. PSINGLE_LIST_ENTRY s;
  696. PTP_PACKET ThePacket;
  697. PDLC_I_FRAME DlcHdr;
  698. #if DBG
  699. PNBF_HDR_CONNECTION NbfHdr;
  700. #endif
  701. typedef struct _SIXTEEN_BYTES {
  702. ULONG Data[4];
  703. } SIXTEEN_BYTES, *PSIXTEEN_BYTES;
  704. ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
  705. IF_NBFDBG (NBF_DEBUG_RESOURCE) {
  706. NbfPrint0 ("NbfCreatePacket: Entered.\n");
  707. }
  708. //
  709. // Make sure that structure packing hasn't happened.
  710. //
  711. ASSERT (sizeof(NBF_HDR_CONNECTION) == 14);
  712. #if defined(NBF_UP)
  713. s = DeviceContext->PacketPool.Next;
  714. if (s != NULL) {
  715. DeviceContext->PacketPool.Next = s->Next;
  716. }
  717. #else
  718. s = ExInterlockedPopEntryList (
  719. &DeviceContext->PacketPool,
  720. &DeviceContext->Interlock);
  721. #endif
  722. if (s == NULL) {
  723. NbfGrowSendPacketPool(DeviceContext);
  724. #if defined(NBF_UP)
  725. s = DeviceContext->PacketPool.Next;
  726. if (s != NULL) {
  727. DeviceContext->PacketPool.Next = s->Next;
  728. }
  729. #else
  730. s = ExInterlockedPopEntryList (
  731. &DeviceContext->PacketPool,
  732. &DeviceContext->Interlock);
  733. #endif
  734. if (s == NULL) {
  735. #if DBG
  736. ++Link->CreatePacketFailures;
  737. if ((ULONG)Link->CreatePacketFailures >= NbfCreatePacketThreshold) {
  738. if (NbfPacketPanic) {
  739. NbfPrint1 ("NbfCreatePacket: PANIC! no more packets in provider's pool (%d times).\n",
  740. Link->CreatePacketFailures);
  741. }
  742. Link->CreatePacketFailures = 0;
  743. }
  744. #endif
  745. ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql);
  746. ++DeviceContext->PacketExhausted;
  747. RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
  748. return STATUS_INSUFFICIENT_RESOURCES;
  749. }
  750. }
  751. #if DBG
  752. Link->CreatePacketFailures = 0;
  753. #endif
  754. ThePacket = CONTAINING_RECORD (s, TP_PACKET, Linkage);
  755. //
  756. // NOTE: ThePacket->Action and ThePacket->Owner are filled
  757. // in by the caller of this function.
  758. //
  759. ThePacket->ReferenceCount = 1; // automatic ref count of 1.
  760. ThePacket->Link = NULL; // no link yet.
  761. ThePacket->PacketSent = FALSE;
  762. ASSERT (ThePacket->Action == PACKET_ACTION_IRP_SP);
  763. ASSERT (ThePacket->PacketNoNdisBuffer == FALSE);
  764. ASSERT (ThePacket->PacketizeConnection == FALSE);
  765. //
  766. // Initialize the MAC header for this packet, using the connection's
  767. // link pre-built header.
  768. //
  769. if (Link->HeaderLength <= 14) {
  770. *(PSIXTEEN_BYTES)ThePacket->Header = *(PSIXTEEN_BYTES)Link->Header;
  771. } else {
  772. RtlCopyMemory(
  773. ThePacket->Header,
  774. Link->Header,
  775. Link->HeaderLength);
  776. //
  777. // Initialize the TP_FRAME_CONNECTION header for this packet.
  778. //
  779. DlcHdr = (PDLC_I_FRAME)&(ThePacket->Header[Link->HeaderLength]);
  780. DlcHdr->Dsap = DSAP_NETBIOS_OVER_LLC;
  781. DlcHdr->Ssap = DSAP_NETBIOS_OVER_LLC;
  782. #if DBG
  783. DlcHdr->SendSeq = 0; // known values, will assist debugging.
  784. DlcHdr->RcvSeq = 0; // these are assigned at shipment time.
  785. #endif
  786. }
  787. #if DBG
  788. NbfHdr = (PNBF_HDR_CONNECTION)&(ThePacket->Header[Link->HeaderLength + sizeof(DLC_I_FRAME)]);
  789. NbfHdr->Command = 0xff; // to assist debugging-- assigned later.
  790. NbfHdr->Data1 = 0xff; // to assist debugging-- assigned later.
  791. NbfHdr->Data2Low = 0xff; // to assist debugging-- assigned later.
  792. NbfHdr->Data2High = 0xff; // to assist debugging-- assigned later.
  793. TRANSMIT_CORR(NbfHdr) = 0xffff; // to assist debugging-- assigned later.
  794. RESPONSE_CORR(NbfHdr) = 0xffff; // to assist debugging-- assigned later.
  795. NbfHdr->DestinationSessionNumber = 0xff; // to assist debugging-- assigned later.
  796. NbfHdr->SourceSessionNumber = 0xff; // to assist debugging-- assigned later.
  797. #endif
  798. *Packet = ThePacket; // return pointer to the packet.
  799. return STATUS_SUCCESS;
  800. } /* NbfCreatePacket */
  801. NTSTATUS
  802. NbfCreateRrPacket(
  803. PDEVICE_CONTEXT DeviceContext,
  804. PTP_LINK Link,
  805. PTP_PACKET *Packet
  806. )
  807. /*++
  808. Routine Description:
  809. This routine allocates an RR packet from the device context's pool,
  810. and prepares the MAC and DLC headers for use by the connection.
  811. It first looks in the special RR packet pool, then in the regular
  812. packet pool.
  813. Arguments:
  814. DeviceContext - Pointer to our device context to charge the packet to.
  815. Link - The link the packet will be sent over.
  816. Packet - Pointer to a place where we will return a pointer to the
  817. allocated packet.
  818. Return Value:
  819. NTSTATUS - status of operation.
  820. --*/
  821. {
  822. PSINGLE_LIST_ENTRY s;
  823. PTP_PACKET ThePacket;
  824. PDLC_I_FRAME DlcHdr;
  825. NTSTATUS Status;
  826. #if DBG
  827. PNBF_HDR_CONNECTION NbfHdr;
  828. #endif
  829. typedef struct _SIXTEEN_BYTES {
  830. ULONG Data[4];
  831. } SIXTEEN_BYTES, *PSIXTEEN_BYTES;
  832. IF_NBFDBG (NBF_DEBUG_RESOURCE) {
  833. NbfPrint0 ("NbfCreateRrPacket: Entered.\n");
  834. }
  835. //
  836. // Make sure that structure packing hasn't happened.
  837. //
  838. ASSERT (sizeof(NBF_HDR_CONNECTION) == 14);
  839. #if defined(NBF_UP)
  840. s = DeviceContext->RrPacketPool.Next;
  841. if (s != NULL) {
  842. DeviceContext->RrPacketPool.Next = s->Next;
  843. }
  844. #else
  845. s = ExInterlockedPopEntryList (
  846. &DeviceContext->RrPacketPool,
  847. &DeviceContext->Interlock);
  848. #endif
  849. if (s == NULL) {
  850. #if DBG
  851. ++Link->CreatePacketFailures;
  852. if ((ULONG)Link->CreatePacketFailures >= NbfCreatePacketThreshold) {
  853. if (NbfPacketPanic) {
  854. NbfPrint1 ("NbfCreateRrPacket: PANIC! no more packets in provider's pool (%d times).\n",
  855. Link->CreatePacketFailures);
  856. }
  857. Link->CreatePacketFailures = 0;
  858. }
  859. #endif
  860. //
  861. // Try to get one from the regular pool, and mark it so
  862. // it goes back there.
  863. //
  864. Status = NbfCreatePacket(
  865. DeviceContext,
  866. Link,
  867. Packet);
  868. if (Status == STATUS_SUCCESS) {
  869. (*Packet)->Action = PACKET_ACTION_NULL;
  870. }
  871. return Status;
  872. }
  873. #if DBG
  874. Link->CreatePacketFailures = 0;
  875. #endif
  876. ThePacket = CONTAINING_RECORD (s, TP_PACKET, Linkage);
  877. //
  878. // NOTE: ThePacket->Owner is filled in by the caller of this
  879. // function.
  880. //
  881. ThePacket->ReferenceCount = 1; // automatic ref count of 1.
  882. ThePacket->Link = NULL; // no link yet.
  883. ThePacket->PacketSent = FALSE;
  884. ASSERT (ThePacket->Action == PACKET_ACTION_RR);
  885. ASSERT (ThePacket->PacketNoNdisBuffer == FALSE);
  886. //
  887. // Initialize the MAC header for this packet, using the connection's
  888. // link pre-built header.
  889. //
  890. if (Link->HeaderLength <= 14) {
  891. *(PSIXTEEN_BYTES)ThePacket->Header = *(PSIXTEEN_BYTES)Link->Header;
  892. } else {
  893. RtlCopyMemory(
  894. ThePacket->Header,
  895. Link->Header,
  896. Link->HeaderLength);
  897. //
  898. // Initialize the TP_FRAME_CONNECTION header for this packet.
  899. //
  900. DlcHdr = (PDLC_I_FRAME)&(ThePacket->Header[Link->HeaderLength]);
  901. DlcHdr->Dsap = DSAP_NETBIOS_OVER_LLC;
  902. DlcHdr->Ssap = DSAP_NETBIOS_OVER_LLC;
  903. #if DBG
  904. DlcHdr->SendSeq = 0; // known values, will assist debugging.
  905. DlcHdr->RcvSeq = 0; // these are assigned at shipment time.
  906. #endif
  907. }
  908. #if DBG
  909. NbfHdr = (PNBF_HDR_CONNECTION)&(ThePacket->Header[Link->HeaderLength + sizeof(DLC_I_FRAME)]);
  910. NbfHdr->Command = 0xff; // to assist debugging-- assigned later.
  911. NbfHdr->Data1 = 0xff; // to assist debugging-- assigned later.
  912. NbfHdr->Data2Low = 0xff; // to assist debugging-- assigned later.
  913. NbfHdr->Data2High = 0xff; // to assist debugging-- assigned later.
  914. TRANSMIT_CORR(NbfHdr) = 0xffff; // to assist debugging-- assigned later.
  915. RESPONSE_CORR(NbfHdr) = 0xffff; // to assist debugging-- assigned later.
  916. NbfHdr->DestinationSessionNumber = 0xff; // to assist debugging-- assigned later.
  917. NbfHdr->SourceSessionNumber = 0xff; // to assist debugging-- assigned later.
  918. #endif
  919. *Packet = ThePacket; // return pointer to the packet.
  920. return STATUS_SUCCESS;
  921. } /* NbfCreateRrPacket */
  922. VOID
  923. NbfDestroyPacket(
  924. PTP_PACKET Packet
  925. )
  926. /*++
  927. Routine Description:
  928. This routine destroys a packet, thereby returning it to the pool. If
  929. it is determined that there is at least one connection waiting for a
  930. packet to become available (and it just has), then the connection is
  931. removed from the device context's list and AdvanceSend is called to
  932. prep the connection further.
  933. Arguments:
  934. Packet - Pointer to a packet to be returned to the pool.
  935. Return Value:
  936. none.
  937. --*/
  938. {
  939. PDEVICE_CONTEXT DeviceContext;
  940. PTP_CONNECTION Connection;
  941. PLIST_ENTRY p;
  942. PNDIS_BUFFER HeaderBuffer;
  943. PNDIS_BUFFER NdisBuffer;
  944. ULONG Flags;
  945. IF_NBFDBG (NBF_DEBUG_RESOURCE) {
  946. NbfPrint2 ("NbfDestroyPacket: Entered, Packet: %lx, NdisPacket: %lx\n",
  947. Packet, Packet->NdisPacket);
  948. }
  949. DeviceContext = Packet->Provider;
  950. //
  951. // Strip off and unmap the buffers describing data and header.
  952. //
  953. if (Packet->PacketNoNdisBuffer) {
  954. //
  955. // If the NDIS_BUFFER chain is not ours, then we can't
  956. // start unchaining since that would mess up the queue;
  957. // instead we just drop the rest of the chain after the
  958. // header.
  959. //
  960. NdisQueryPacket (Packet->NdisPacket, NULL, NULL, &HeaderBuffer, NULL);
  961. ASSERT (HeaderBuffer != NULL);
  962. NDIS_BUFFER_LINKAGE(HeaderBuffer) = (PNDIS_BUFFER)NULL;
  963. NdisRecalculatePacketCounts (Packet->NdisPacket);
  964. Packet->PacketNoNdisBuffer = FALSE;
  965. } else {
  966. NdisUnchainBufferAtFront (Packet->NdisPacket, &HeaderBuffer);
  967. ASSERT (HeaderBuffer != NULL);
  968. //
  969. // Return all the NDIS_BUFFERs to the system.
  970. //
  971. NdisUnchainBufferAtFront (Packet->NdisPacket, &NdisBuffer);
  972. while (NdisBuffer != NULL) {
  973. NdisFreeBuffer (NdisBuffer);
  974. NdisUnchainBufferAtFront (Packet->NdisPacket, &NdisBuffer);
  975. }
  976. NDIS_BUFFER_LINKAGE(HeaderBuffer) = (PNDIS_BUFFER)NULL;
  977. NdisChainBufferAtFront (Packet->NdisPacket, HeaderBuffer);
  978. }
  979. //
  980. // invoke the packet deallocate action specified in this packet.
  981. //
  982. switch (Packet->Action) {
  983. case PACKET_ACTION_NULL:
  984. // PANIC ("NbfDestroyPacket: no action.\n");
  985. Packet->Action = PACKET_ACTION_IRP_SP;
  986. break;
  987. case PACKET_ACTION_IRP_SP:
  988. IF_NBFDBG (NBF_DEBUG_REQUEST) {
  989. NbfPrint2 ("NbfDestroyPacket: Packet %x deref IrpSp %x.\n", Packet, Packet->Owner);
  990. }
  991. NbfDereferenceSendIrp("Destroy packet", (PIO_STACK_LOCATION)(Packet->Owner), RREF_PACKET);
  992. break;
  993. case PACKET_ACTION_CONNECTION:
  994. NbfDereferenceConnection ("Destroy packet", (PTP_CONNECTION)(Packet->Owner), CREF_FRAME_SEND);
  995. Packet->Action = PACKET_ACTION_IRP_SP;
  996. break;
  997. case PACKET_ACTION_END:
  998. NbfDereferenceConnection ("SessionEnd destroyed", (PTP_CONNECTION)(Packet->Owner), CREF_FRAME_SEND);
  999. NbfDereferenceConnection ("SessionEnd destroyed", (PTP_CONNECTION)(Packet->Owner), CREF_LINK);
  1000. Packet->Action = PACKET_ACTION_IRP_SP;
  1001. break;
  1002. case PACKET_ACTION_RR:
  1003. #if defined(NBF_UP)
  1004. ((PSINGLE_LIST_ENTRY)&Packet->Linkage)->Next =
  1005. DeviceContext->RrPacketPool.Next;
  1006. DeviceContext->RrPacketPool.Next =
  1007. &((PSINGLE_LIST_ENTRY)&Packet->Linkage)->Next;
  1008. #else
  1009. ExInterlockedPushEntryList (
  1010. &DeviceContext->RrPacketPool,
  1011. (PSINGLE_LIST_ENTRY)&Packet->Linkage,
  1012. &DeviceContext->Interlock);
  1013. #endif
  1014. return;
  1015. default:
  1016. IF_NBFDBG (NBF_DEBUG_RESOURCE) {
  1017. NbfPrint1 ("NbfDestroyPacket: invalid action (%ld).\n", Packet->Action);
  1018. }
  1019. ASSERT (FALSE);
  1020. }
  1021. //
  1022. // Put the packet back for use again.
  1023. //
  1024. #if defined(NBF_UP)
  1025. ((PSINGLE_LIST_ENTRY)&Packet->Linkage)->Next =
  1026. DeviceContext->PacketPool.Next;
  1027. DeviceContext->PacketPool.Next =
  1028. &((PSINGLE_LIST_ENTRY)&Packet->Linkage)->Next;
  1029. #else
  1030. ExInterlockedPushEntryList (
  1031. &DeviceContext->PacketPool,
  1032. (PSINGLE_LIST_ENTRY)&Packet->Linkage,
  1033. &DeviceContext->Interlock);
  1034. #endif
  1035. //
  1036. // If there is a connection waiting to ship out more packets, then
  1037. // wake it up and start packetizing again.
  1038. //
  1039. // We do a quick check without the lock; there is a small
  1040. // window where we may not take someone off, but this
  1041. // window exists anyway and we assume that more packets
  1042. // will be freed in the future.
  1043. //
  1044. if (IsListEmpty (&DeviceContext->PacketWaitQueue)) {
  1045. return;
  1046. }
  1047. ACQUIRE_DPC_SPIN_LOCK (&DeviceContext->SpinLock);
  1048. if (!(IsListEmpty(&DeviceContext->PacketWaitQueue))) {
  1049. //
  1050. // Remove a connection from the "packet starved" queue.
  1051. //
  1052. p = RemoveHeadList (&DeviceContext->PacketWaitQueue);
  1053. Connection = CONTAINING_RECORD (p, TP_CONNECTION, PacketWaitLinkage);
  1054. Connection->OnPacketWaitQueue = FALSE;
  1055. RELEASE_DPC_SPIN_LOCK (&DeviceContext->SpinLock);
  1056. ACQUIRE_DPC_SPIN_LOCK (Connection->LinkSpinLock);
  1057. //
  1058. // If this connection is starved because it couldn't send a
  1059. // control packet (SI, SC, RO, RC, or DA) then start that
  1060. // operation up again. Otherwise, just start packetizing.
  1061. //
  1062. if (Connection->Flags & CONNECTION_FLAGS_STARVED) {
  1063. Flags = Connection->Flags & CONNECTION_FLAGS_STARVED;
  1064. if ((Flags & (Flags-1)) != 0) {
  1065. //
  1066. // More than one bit is on, use only the low one
  1067. // (an arbitrary choice).
  1068. //
  1069. #if DBG
  1070. DbgPrint ("NBF: Connection %lx has two flag bits on %lx\n", Connection, Connection->Flags);
  1071. #endif
  1072. Flags &= ~(Flags-1);
  1073. }
  1074. Connection->Flags &= ~Flags;
  1075. if ((Connection->Flags & CONNECTION_FLAGS_W_PACKETIZE) ||
  1076. (Connection->Flags & CONNECTION_FLAGS_STARVED)) {
  1077. //
  1078. // We are waiting for both a specific packet and
  1079. // to packetize, or for two specific packets, so
  1080. // put ourselves back on the queue.
  1081. //
  1082. ACQUIRE_DPC_SPIN_LOCK (&DeviceContext->SpinLock);
  1083. if (!Connection->OnPacketWaitQueue) {
  1084. Connection->OnPacketWaitQueue = TRUE;
  1085. InsertTailList(
  1086. &DeviceContext->PacketWaitQueue,
  1087. &Connection->PacketWaitLinkage);
  1088. }
  1089. RELEASE_DPC_SPIN_LOCK (&DeviceContext->SpinLock);
  1090. }
  1091. RELEASE_DPC_SPIN_LOCK (Connection->LinkSpinLock);
  1092. if (Flags & CONNECTION_FLAGS_SEND_SI) {
  1093. NbfSendSessionInitialize (Connection);
  1094. } else if (Flags & CONNECTION_FLAGS_SEND_SC) {
  1095. NbfSendSessionConfirm (Connection);
  1096. } else if (Flags & CONNECTION_FLAGS_SEND_RO) {
  1097. NbfSendReceiveOutstanding (Connection);
  1098. } else if (Flags & CONNECTION_FLAGS_SEND_RC) {
  1099. NbfSendReceiveContinue (Connection);
  1100. } else if (Flags & CONNECTION_FLAGS_SEND_SE) {
  1101. NbfSendSessionEnd (
  1102. Connection,
  1103. FALSE);
  1104. } else if (Flags & CONNECTION_FLAGS_SEND_DA) {
  1105. NbfSendDataAck (Connection);
  1106. } else {
  1107. IF_NBFDBG (NBF_DEBUG_PACKET) {
  1108. NbfPrint0 ("NbfDestroyPacket: connection flags mismanaged.\n");
  1109. }
  1110. }
  1111. } else {
  1112. //
  1113. // Place the connection on the packetize queue and start
  1114. // packetizing the next connection to be serviced. If he
  1115. // is already on the packetize queue for some reason, then
  1116. // don't do this.
  1117. //
  1118. // We shouldn't be packetizing in this case!! - adb (7/3/91).
  1119. // This used to be a check that did nothing if FLAGS_PACKETIZE
  1120. // was set, but if that happens something is wrong...
  1121. //
  1122. ASSERT (Connection->Flags & CONNECTION_FLAGS_W_PACKETIZE);
  1123. Connection->Flags &= ~CONNECTION_FLAGS_W_PACKETIZE;
  1124. Connection->SendState = CONNECTION_SENDSTATE_PACKETIZE;
  1125. if ((Connection->Flags & CONNECTION_FLAGS_READY) &&
  1126. !(Connection->Flags & CONNECTION_FLAGS_PACKETIZE)) {
  1127. Connection->Flags |= CONNECTION_FLAGS_PACKETIZE;
  1128. NbfReferenceConnection ("Packet available", Connection, CREF_PACKETIZE_QUEUE);
  1129. ExInterlockedInsertTailList(
  1130. &DeviceContext->PacketizeQueue,
  1131. &Connection->PacketizeLinkage,
  1132. &DeviceContext->SpinLock);
  1133. }
  1134. RELEASE_DPC_SPIN_LOCK (Connection->LinkSpinLock);
  1135. PacketizeConnections (DeviceContext);
  1136. }
  1137. } else {
  1138. RELEASE_DPC_SPIN_LOCK (&DeviceContext->SpinLock);
  1139. }
  1140. } /* NbfDestroyPacket */
  1141. VOID NbfGrowSendPacketPool(PDEVICE_CONTEXT DeviceContext)
  1142. {
  1143. NDIS_STATUS NdisStatus;
  1144. PNBF_POOL_LIST_DESC SendPacketPoolDesc;
  1145. PTP_PACKET TransportSendPacket;
  1146. UINT i;
  1147. if ((DeviceContext->MemoryLimit != 0) &&
  1148. ((DeviceContext->MemoryUsage + DeviceContext->PacketLength) >
  1149. DeviceContext->MemoryLimit)) {
  1150. PANIC("NBF: Could not grow send packet pool: limit\n");
  1151. NbfWriteResourceErrorLog(
  1152. DeviceContext,
  1153. EVENT_TRANSPORT_RESOURCE_LIMIT,
  1154. 107,
  1155. DeviceContext->PacketLength,
  1156. PACKET_RESOURCE_ID);
  1157. return;
  1158. }
  1159. for (i = 0; i < PACKET_POOL_GROW_COUNT; i += 1) {
  1160. NbfAllocateSendPacket(DeviceContext, &TransportSendPacket);
  1161. if (TransportSendPacket != NULL) {
  1162. ExInterlockedPushEntryList(&(DeviceContext)->PacketPool,
  1163. (PSINGLE_LIST_ENTRY)&TransportSendPacket->Linkage,
  1164. &(DeviceContext)->Interlock);
  1165. }
  1166. else {
  1167. break;
  1168. }
  1169. }
  1170. if (i == PACKET_POOL_GROW_COUNT) {
  1171. return;
  1172. }
  1173. #ifdef DBG
  1174. DbgBreakPoint();
  1175. #endif // DBG
  1176. }
  1177. #if DBG
  1178. VOID
  1179. NbfReferencePacket(
  1180. PTP_PACKET Packet
  1181. )
  1182. /*++
  1183. Routine Description:
  1184. This routine increases the number of reasons why a packet cannot be
  1185. discarded.
  1186. Arguments:
  1187. Packet - Pointer to a packet to be referenced.
  1188. Return Value:
  1189. none.
  1190. --*/
  1191. {
  1192. LONG result;
  1193. IF_NBFDBG (NBF_DEBUG_PACKET) {
  1194. NbfPrint3 ("NbfReferencePacket: Entered, NdisPacket: %lx Packet: %lx Ref Count: %lx.\n",
  1195. Packet->NdisPacket, Packet, Packet->ReferenceCount);
  1196. }
  1197. result = InterlockedIncrement (&Packet->ReferenceCount);
  1198. ASSERT (result >= 0);
  1199. } /* NbfReferencePacket */
  1200. VOID
  1201. NbfDereferencePacket(
  1202. PTP_PACKET Packet
  1203. )
  1204. /*++
  1205. Routine Description:
  1206. This routine dereferences a transport packet by decrementing the
  1207. reference count contained in the structure. If, after being
  1208. decremented, the reference count is zero, then this routine calls
  1209. NbfDestroyPacket to remove it from the system.
  1210. Arguments:
  1211. Packet - Pointer to a packet object.
  1212. Return Value:
  1213. none.
  1214. --*/
  1215. {
  1216. LONG result;
  1217. result = InterlockedDecrement (&Packet->ReferenceCount);
  1218. //
  1219. // If we have deleted all references to this packet, then we can
  1220. // destroy the object. It is okay to have already released the spin
  1221. // lock at this point because there is no possible way that another
  1222. // stream of execution has access to the packet any longer.
  1223. //
  1224. IF_NBFDBG (NBF_DEBUG_PACKET) {
  1225. NbfPrint1 ("NbfDereferencePacket: Entered, result: %lx\n", result);
  1226. }
  1227. ASSERT (result >= 0);
  1228. if (result == 0) {
  1229. NbfDestroyPacket (Packet);
  1230. }
  1231. } /* NbfDereferencePacket */
  1232. #endif
  1233. VOID
  1234. NbfWaitPacket(
  1235. PTP_CONNECTION Connection,
  1236. ULONG Flags
  1237. )
  1238. /*++
  1239. Routine Description:
  1240. This routine causes the specified connection to be put into a wait
  1241. state pending the availability of a packet to send the specified
  1242. frame.
  1243. Arguments:
  1244. Connection - Pointer to the connection object to be paused.
  1245. Flags - Bitflag indicating which specific frame should be resent.
  1246. Return Value:
  1247. none.
  1248. --*/
  1249. {
  1250. PDEVICE_CONTEXT DeviceContext;
  1251. IF_NBFDBG (NBF_DEBUG_PACKET) {
  1252. NbfPrint0 ("NbfWaitPacket: Entered.\n");
  1253. }
  1254. DeviceContext = Connection->Provider;
  1255. ACQUIRE_DPC_SPIN_LOCK (Connection->LinkSpinLock);
  1256. //
  1257. // Now put this connection on the device context's PacketWaitQueue,
  1258. // but only if it isn't already queued there. This state is managed
  1259. // with the OnPacketWaitQueue variable.
  1260. //
  1261. // If the connection is stopping, don't queue him either.
  1262. //
  1263. if ((Connection->Flags & CONNECTION_FLAGS_READY) ||
  1264. (Flags == CONNECTION_FLAGS_SEND_SE)) {
  1265. ACQUIRE_DPC_SPIN_LOCK (&DeviceContext->SpinLock);
  1266. //
  1267. // Turn on the bitflag that indicates which frame we couldn't send.
  1268. //
  1269. #if DBG
  1270. if (Flags == CONNECTION_FLAGS_SEND_SE) {
  1271. DbgPrint ("NBF: Inserting connection %lx on PacketWait for SESSION_END\n", Connection);
  1272. }
  1273. #endif
  1274. Connection->Flags |= Flags;
  1275. if (!Connection->OnPacketWaitQueue) {
  1276. Connection->OnPacketWaitQueue = TRUE;
  1277. InsertTailList (
  1278. &DeviceContext->PacketWaitQueue,
  1279. &Connection->PacketWaitLinkage);
  1280. }
  1281. RELEASE_DPC_SPIN_LOCK (&DeviceContext->SpinLock);
  1282. }
  1283. RELEASE_DPC_SPIN_LOCK (Connection->LinkSpinLock);
  1284. } /* NbfWaitPacket */
  1285. #if MAGIC
  1286. VOID
  1287. NbfSendMagicBullet (
  1288. IN PDEVICE_CONTEXT DeviceContext,
  1289. IN PTP_LINK Link
  1290. )
  1291. /*++
  1292. Routine Description:
  1293. This routine sends a magic bullet on the net that can be used to trigger
  1294. sniffers or other such things.
  1295. Arguments:
  1296. DeviceContext - pointer to the device context
  1297. Link - This is needed to call NbfCreatePacket
  1298. Return Value:
  1299. none.
  1300. --*/
  1301. {
  1302. NTSTATUS Status;
  1303. NDIS_STATUS NdisStatus;
  1304. PTP_UI_FRAME RawFrame;
  1305. PUCHAR Header;
  1306. PNDIS_BUFFER NdisBuffer;
  1307. UINT i;
  1308. UNREFERENCED_PARAMETER (Link); // no longer needed
  1309. Status = NbfCreateConnectionlessFrame (DeviceContext, &RawFrame);
  1310. if (!NT_SUCCESS (Status)) { // couldn't make frame.
  1311. #if DBG
  1312. DbgPrint ("NbfSendMagicBullet: Couldn't allocate frame!\n");
  1313. #endif
  1314. return;
  1315. }
  1316. NdisAllocateBuffer(
  1317. &NdisStatus,
  1318. &NdisBuffer,
  1319. DeviceContext->NdisBufferPool,
  1320. DeviceContext->MagicBullet,
  1321. 32);
  1322. if (NdisStatus == NDIS_STATUS_SUCCESS) {
  1323. Header = (PUCHAR)&RawFrame->Header;
  1324. for (i=0;i<6;i++) {
  1325. Header[i] = MAGIC_BULLET_FOOD;
  1326. Header[i+6] = DeviceContext->LocalAddress.Address[i];
  1327. }
  1328. Header[12] = 0;
  1329. Header[13] = (UCHAR)(DeviceContext->UIFrameHeaderLength + 18);
  1330. for (i=14;i<DeviceContext->UIFrameHeaderLength;i++) {
  1331. Header[i] = MAGIC_BULLET_FOOD;
  1332. }
  1333. NdisChainBufferAtBack (RawFrame->NdisPacket, NdisBuffer);
  1334. NbfSendUIFrame (
  1335. DeviceContext,
  1336. RawFrame,
  1337. FALSE); // no loopback
  1338. }
  1339. return;
  1340. }
  1341. #endif