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.

1494 lines
36 KiB

  1. /*++
  2. Copyright (c) 1989-1993 Microsoft Corporation
  3. Module Name:
  4. packet.c
  5. Abstract:
  6. This module contains code that implements the SEND_PACKET and
  7. RECEIVE_PACKET objects, which describe NDIS packets used
  8. by the transport.
  9. Environment:
  10. Kernel mode
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. //
  16. // Local Function Protos
  17. //
  18. #if defined(_PNP_POWER)
  19. #if !defined(DBG)
  20. __inline
  21. #endif
  22. VOID
  23. NbiFreeReceiveBufferPool (
  24. IN PNB_RECEIVE_BUFFER_POOL ReceiveBufferPool
  25. );
  26. #endif _PNP_POWER
  27. NTSTATUS
  28. NbiInitializeSendPacket(
  29. IN PDEVICE Device,
  30. IN NDIS_HANDLE PoolHandle OPTIONAL,
  31. IN PNB_SEND_PACKET Packet,
  32. IN PUCHAR Header,
  33. IN ULONG HeaderLength
  34. )
  35. /*++
  36. Routine Description:
  37. This routine initializes a send packet by chaining the
  38. buffer for the header on it.
  39. NOTE: THIS ROUTINE IS CALLED WITH THE DEVICE LOCK HELD,
  40. AND RETURNS WITH IT HELD.
  41. Arguments:
  42. Device - The device.
  43. PoolHandle - Ndis packet pool handle if !NB_OWN_PACKETS
  44. Packet - The packet to initialize.
  45. Header - Points to storage for the header.
  46. HeaderLength - The length of the header.
  47. Return Value:
  48. None.
  49. --*/
  50. {
  51. NDIS_STATUS NdisStatus;
  52. NTSTATUS Status;
  53. PNDIS_BUFFER NdisBuffer;
  54. PNDIS_BUFFER NdisNbBuffer;
  55. PNB_SEND_RESERVED Reserved;
  56. ULONG MacHeaderNeeded = NbiDevice->Bind.MacHeaderNeeded;
  57. NbiAllocateSendPacket (Device, PoolHandle, Packet, &Status);
  58. if (Status != STATUS_SUCCESS) {
  59. // ERROR LOG
  60. return Status;
  61. }
  62. // DbgPrint("NbiInitializeSendPacket: PACKET is (%x)\n", PACKET(Packet));
  63. //
  64. // allocate the mac header.
  65. //
  66. NdisAllocateBuffer(
  67. &NdisStatus,
  68. &NdisBuffer,
  69. Device->NdisBufferPoolHandle,
  70. Header,
  71. MacHeaderNeeded);
  72. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  73. NbiFreeSendPacket (Device, Packet);
  74. // ERROR LOG
  75. return STATUS_INSUFFICIENT_RESOURCES;
  76. }
  77. NdisChainBufferAtFront (PACKET(Packet), NdisBuffer);
  78. // DbgPrint("NbiInitializeSendPacket: MAC header address is (%x)\n", NdisBuffer);
  79. //
  80. // Allocate the nb header
  81. //
  82. NdisAllocateBuffer(
  83. &NdisStatus,
  84. &NdisNbBuffer,
  85. Device->NdisBufferPoolHandle,
  86. Header + MacHeaderNeeded,
  87. HeaderLength - MacHeaderNeeded);
  88. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  89. NdisBuffer = NULL;
  90. NdisUnchainBufferAtFront (PACKET(Packet), &NdisBuffer);
  91. CTEAssert (NdisBuffer);
  92. if (NdisBuffer)
  93. {
  94. NdisAdjustBufferLength (NdisBuffer, MacHeaderNeeded);
  95. NdisFreeBuffer (NdisBuffer);
  96. }
  97. NbiFreeSendPacket (Device, Packet);
  98. // ERROR LOG
  99. return STATUS_INSUFFICIENT_RESOURCES;
  100. }
  101. // DbgPrint("NbiInitializeSendPacket: IPX header address is (%x)\n", NdisNbBuffer);
  102. NdisChainBufferAtBack (PACKET(Packet), NdisNbBuffer);
  103. Reserved = SEND_RESERVED(Packet);
  104. Reserved->Identifier = IDENTIFIER_NB;
  105. Reserved->SendInProgress = FALSE;
  106. Reserved->OwnedByConnection = FALSE;
  107. Reserved->Header = Header;
  108. Reserved->HeaderBuffer = NdisBuffer;
  109. Reserved->Reserved[0] = NULL;
  110. Reserved->Reserved[1] = NULL;
  111. InsertHeadList(
  112. &Device->GlobalSendPacketList,
  113. &Reserved->GlobalLinkage);
  114. return STATUS_SUCCESS;
  115. } /* NbiInitializeSendPacket */
  116. NTSTATUS
  117. NbiInitializeReceivePacket(
  118. IN PDEVICE Device,
  119. IN NDIS_HANDLE PoolHandle OPTIONAL,
  120. IN PNB_RECEIVE_PACKET Packet
  121. )
  122. /*++
  123. Routine Description:
  124. This routine initializes a receive packet.
  125. NOTE: THIS ROUTINE IS CALLED WITH THE DEVICE LOCK HELD,
  126. AND RETURNS WITH IT HELD.
  127. Arguments:
  128. Device - The device.
  129. PoolHandle - Ndis packet pool handle if !NB_OWN_PACKETS
  130. Packet - The packet to initialize.
  131. Return Value:
  132. None.
  133. --*/
  134. {
  135. NTSTATUS Status;
  136. PNB_RECEIVE_RESERVED Reserved;
  137. NbiAllocateReceivePacket (Device, PoolHandle, Packet, &Status);
  138. if (Status != STATUS_SUCCESS) {
  139. // ERROR LOG
  140. return Status;
  141. }
  142. Reserved = RECEIVE_RESERVED(Packet);
  143. Reserved->Identifier = IDENTIFIER_NB;
  144. Reserved->TransferInProgress = FALSE;
  145. InsertHeadList(
  146. &Device->GlobalReceivePacketList,
  147. &Reserved->GlobalLinkage);
  148. return STATUS_SUCCESS;
  149. } /* NbiInitializeReceivePacket */
  150. NTSTATUS
  151. NbiInitializeReceiveBuffer(
  152. IN PDEVICE Device,
  153. IN PNB_RECEIVE_BUFFER ReceiveBuffer,
  154. IN PUCHAR DataBuffer,
  155. IN ULONG DataBufferLength
  156. )
  157. /*++
  158. Routine Description:
  159. This routine initializes a receive buffer by allocating
  160. an NDIS_BUFFER to describe the data buffer.
  161. NOTE: THIS ROUTINE IS CALLED WITH THE DEVICE LOCK HELD,
  162. AND RETURNS WITH IT HELD.
  163. Arguments:
  164. Device - The device.
  165. ReceiveBuffer - The receive buffer to initialize.
  166. DataBuffer - The data buffer.
  167. DataBufferLength - The length of the data buffer.
  168. Return Value:
  169. None.
  170. --*/
  171. {
  172. NDIS_STATUS NdisStatus;
  173. PNDIS_BUFFER NdisBuffer;
  174. NdisAllocateBuffer(
  175. &NdisStatus,
  176. &NdisBuffer,
  177. Device->NdisBufferPoolHandle,
  178. DataBuffer,
  179. DataBufferLength);
  180. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  181. // ERROR LOG
  182. return STATUS_INSUFFICIENT_RESOURCES;
  183. }
  184. ReceiveBuffer->NdisBuffer = NdisBuffer;
  185. ReceiveBuffer->Data = DataBuffer;
  186. ReceiveBuffer->DataLength = 0;
  187. InsertHeadList(
  188. &Device->GlobalReceiveBufferList,
  189. &ReceiveBuffer->GlobalLinkage);
  190. return STATUS_SUCCESS;
  191. } /* NbiInitializeReceiveBuffer */
  192. VOID
  193. NbiDeinitializeSendPacket(
  194. IN PDEVICE Device,
  195. IN PNB_SEND_PACKET Packet,
  196. IN ULONG HeaderLength
  197. )
  198. /*++
  199. Routine Description:
  200. This routine deinitializes a send packet.
  201. Arguments:
  202. Device - The device.
  203. Packet - The packet to deinitialize.
  204. HeaderLength - The length of the first buffer on the packet.
  205. Return Value:
  206. None.
  207. --*/
  208. {
  209. PNDIS_BUFFER NdisBuffer = NULL;
  210. PNB_SEND_RESERVED Reserved;
  211. CTELockHandle LockHandle;
  212. ULONG MacHeaderNeeded = NbiDevice->Bind.MacHeaderNeeded;
  213. CTEAssert(HeaderLength > MacHeaderNeeded);
  214. Reserved = SEND_RESERVED(Packet);
  215. NB_GET_LOCK (&Device->Lock, &LockHandle);
  216. RemoveEntryList (&Reserved->GlobalLinkage);
  217. NB_FREE_LOCK (&Device->Lock, LockHandle);
  218. //
  219. // Free the mac header
  220. //
  221. // DbgPrint("NbiDeinitializeSendPacket: PACKET is (%x)\n", PACKET(Packet));
  222. NdisUnchainBufferAtFront (PACKET(Packet), &NdisBuffer);
  223. CTEAssert (NdisBuffer);
  224. // DbgPrint("NbiDeinitializeSendPacket: MAC header address is (%x)\n", NdisBuffer);
  225. if (NdisBuffer)
  226. {
  227. NdisAdjustBufferLength (NdisBuffer, MacHeaderNeeded);
  228. NdisFreeBuffer (NdisBuffer);
  229. }
  230. //
  231. // Free the nb header
  232. //
  233. NdisBuffer = NULL;
  234. NdisUnchainBufferAtFront (PACKET(Packet), &NdisBuffer);
  235. // DbgPrint("NbiDeinitializeSendPacket: IPX header address is (%x)\n", NdisBuffer);
  236. CTEAssert (NdisBuffer);
  237. if (NdisBuffer)
  238. {
  239. NdisAdjustBufferLength (NdisBuffer, HeaderLength - MacHeaderNeeded);
  240. NdisFreeBuffer (NdisBuffer);
  241. }
  242. //
  243. // free the packet
  244. //
  245. NbiFreeSendPacket (Device, Packet);
  246. } /* NbiDeinitializeSendPacket */
  247. VOID
  248. NbiDeinitializeReceivePacket(
  249. IN PDEVICE Device,
  250. IN PNB_RECEIVE_PACKET Packet
  251. )
  252. /*++
  253. Routine Description:
  254. This routine initializes a receive packet.
  255. Arguments:
  256. Device - The device.
  257. Packet - The packet to initialize.
  258. Return Value:
  259. None.
  260. --*/
  261. {
  262. PNB_RECEIVE_RESERVED Reserved;
  263. CTELockHandle LockHandle;
  264. Reserved = RECEIVE_RESERVED(Packet);
  265. NB_GET_LOCK (&Device->Lock, &LockHandle);
  266. RemoveEntryList (&Reserved->GlobalLinkage);
  267. NB_FREE_LOCK (&Device->Lock, LockHandle);
  268. NbiFreeReceivePacket (Device, Packet);
  269. } /* NbiDeinitializeReceivePacket */
  270. VOID
  271. NbiDeinitializeReceiveBuffer(
  272. IN PDEVICE Device,
  273. IN PNB_RECEIVE_BUFFER ReceiveBuffer
  274. )
  275. /*++
  276. Routine Description:
  277. This routine deinitializes a receive buffer.
  278. Arguments:
  279. Device - The device.
  280. ReceiveBuffer - The receive buffer.
  281. Return Value:
  282. None.
  283. THIS ROUTINE SHOULD BE CALLED WITH THE DEVICE LOCK HELD. If this
  284. routine also called from the DestroyDevice routine, it is not
  285. necessary to call this with the lock.
  286. --*/
  287. {
  288. #if defined(_PNP_POWER)
  289. RemoveEntryList (&ReceiveBuffer->GlobalLinkage);
  290. #else
  291. CTELockHandle LockHandle;
  292. NB_GET_LOCK (&Device->Lock, &LockHandle);
  293. RemoveEntryList (&ReceiveBuffer->GlobalLinkage);
  294. NB_FREE_LOCK (&Device->Lock, LockHandle);
  295. #endif _PNP_POWER
  296. NdisFreeBuffer (ReceiveBuffer->NdisBuffer);
  297. } /* NbiDeinitializeReceiveBuffer */
  298. VOID
  299. NbiAllocateSendPool(
  300. IN PDEVICE Device
  301. )
  302. /*++
  303. Routine Description:
  304. This routine adds 10 packets to the pool for this device.
  305. NOTE: THIS ROUTINE IS CALLED WITH THE DEVICE LOCK HELD AND
  306. RETURNS WITH IT HELD.
  307. Arguments:
  308. Device - The device.
  309. Return Value:
  310. None.
  311. --*/
  312. {
  313. PNB_SEND_POOL SendPool;
  314. UINT SendPoolSize;
  315. UINT PacketNum;
  316. PNB_SEND_PACKET Packet;
  317. PNB_SEND_RESERVED Reserved;
  318. PUCHAR Header;
  319. ULONG HeaderLength;
  320. NTSTATUS Status;
  321. HeaderLength = Device->Bind.MacHeaderNeeded + sizeof(NB_CONNECTIONLESS);
  322. SendPoolSize = FIELD_OFFSET (NB_SEND_POOL, Packets[0]) +
  323. (sizeof(NB_SEND_PACKET) * Device->InitPackets) +
  324. (HeaderLength * Device->InitPackets);
  325. SendPool = (PNB_SEND_POOL)NbiAllocateMemory (SendPoolSize, MEMORY_PACKET, "SendPool");
  326. if (SendPool == NULL) {
  327. NB_DEBUG (PACKET, ("Could not allocate send pool memory\n"));
  328. return;
  329. }
  330. RtlZeroMemory (SendPool, SendPoolSize);
  331. #if !defined(NB_OWN_PACKETS)
  332. //
  333. // Now allocate the ndis packet pool
  334. //
  335. SendPool->PoolHandle = (NDIS_HANDLE) NDIS_PACKET_POOL_TAG_FOR_NWLNKNB; // Dbg info for Ndis!
  336. NdisAllocatePacketPoolEx (&Status, &SendPool->PoolHandle, Device->InitPackets, 0, sizeof(NB_SEND_RESERVED));
  337. if (!NT_SUCCESS(Status)){
  338. NB_DEBUG (PACKET, ("Could not allocate Ndis Packet Pool memory\n"));
  339. NbiFreeMemory( SendPool, SendPoolSize, MEMORY_PACKET, "Send Pool Freed");
  340. return;
  341. }
  342. NdisSetPacketPoolProtocolId (SendPool->PoolHandle, NDIS_PROTOCOL_ID_IPX);
  343. #endif
  344. NB_DEBUG2 (PACKET, ("Initializing send pool %lx, %d packets, header %d\n",
  345. SendPool, Device->InitPackets, HeaderLength));
  346. Header = (PUCHAR)(&SendPool->Packets[Device->InitPackets]);
  347. for (PacketNum = 0; PacketNum < Device->InitPackets; PacketNum++) {
  348. Packet = &SendPool->Packets[PacketNum];
  349. if (NbiInitializeSendPacket (
  350. Device,
  351. #ifdef NB_OWN_PACKETS
  352. NULL,
  353. #else
  354. SendPool->PoolHandle,
  355. #endif
  356. Packet,
  357. Header,
  358. HeaderLength) != STATUS_SUCCESS) {
  359. NB_DEBUG (PACKET, ("Could not initialize packet %lx\n", Packet));
  360. break;
  361. }
  362. Reserved = SEND_RESERVED(Packet);
  363. Reserved->u.SR_NF.Address = NULL;
  364. #ifdef NB_TRACK_POOL
  365. Reserved->Pool = SendPool;
  366. #endif
  367. Header += HeaderLength;
  368. }
  369. SendPool->PacketCount = PacketNum;
  370. SendPool->PacketFree = PacketNum;
  371. for (PacketNum = 0; PacketNum < SendPool->PacketCount; PacketNum++) {
  372. Packet = &SendPool->Packets[PacketNum];
  373. Reserved = SEND_RESERVED(Packet);
  374. ExInterlockedPushEntrySList(
  375. &Device->SendPacketList,
  376. &Reserved->PoolLinkage,
  377. &NbiGlobalPoolInterlock);
  378. }
  379. InsertTailList (&Device->SendPoolList, &SendPool->Linkage);
  380. Device->AllocatedSendPackets += SendPool->PacketCount;
  381. } /* NbiAllocateSendPool */
  382. VOID
  383. NbiAllocateReceivePool(
  384. IN PDEVICE Device
  385. )
  386. /*++
  387. Routine Description:
  388. This routine adds 5 receive packets to the pool for this device.
  389. NOTE: THIS ROUTINE IS CALLED WITH THE DEVICE LOCK HELD AND
  390. RETURNS WITH IT HELD.
  391. Arguments:
  392. Device - The device.
  393. Return Value:
  394. None.
  395. --*/
  396. {
  397. PNB_RECEIVE_POOL ReceivePool;
  398. UINT ReceivePoolSize;
  399. UINT PacketNum;
  400. PNB_RECEIVE_PACKET Packet;
  401. PNB_RECEIVE_RESERVED Reserved;
  402. NTSTATUS Status;
  403. ReceivePoolSize = FIELD_OFFSET (NB_RECEIVE_POOL, Packets[0]) +
  404. (sizeof(NB_RECEIVE_PACKET) * Device->InitPackets);
  405. ReceivePool = (PNB_RECEIVE_POOL)NbiAllocateMemory (ReceivePoolSize, MEMORY_PACKET, "ReceivePool");
  406. if (ReceivePool == NULL) {
  407. NB_DEBUG (PACKET, ("Could not allocate receive pool memory\n"));
  408. return;
  409. }
  410. RtlZeroMemory (ReceivePool, ReceivePoolSize);
  411. #if !defined(NB_OWN_PACKETS)
  412. //
  413. // Now allocate the ndis packet pool
  414. //
  415. ReceivePool->PoolHandle = (NDIS_HANDLE) NDIS_PACKET_POOL_TAG_FOR_NWLNKNB; // Dbg info for Ndis!
  416. NdisAllocatePacketPoolEx (&Status, &ReceivePool->PoolHandle, Device->InitPackets, 0, sizeof(NB_RECEIVE_RESERVED));
  417. if (!NT_SUCCESS(Status)){
  418. NB_DEBUG (PACKET, ("Could not allocate Ndis Packet Pool memory\n"));
  419. NbiFreeMemory( ReceivePool, ReceivePoolSize, MEMORY_PACKET, "Receive Pool Freed");
  420. return;
  421. }
  422. NdisSetPacketPoolProtocolId (ReceivePool->PoolHandle, NDIS_PROTOCOL_ID_IPX);
  423. #endif NB_OWN_PACKETS
  424. NB_DEBUG2 (PACKET, ("Initializing receive pool %lx, %d packets\n",
  425. ReceivePool, Device->InitPackets));
  426. for (PacketNum = 0; PacketNum < Device->InitPackets; PacketNum++) {
  427. Packet = &ReceivePool->Packets[PacketNum];
  428. if (NbiInitializeReceivePacket (
  429. Device,
  430. #ifdef NB_OWN_PACKETS
  431. NULL,
  432. #else
  433. ReceivePool->PoolHandle,
  434. #endif
  435. Packet) != STATUS_SUCCESS) {
  436. NB_DEBUG (PACKET, ("Could not initialize packet %lx\n", Packet));
  437. break;
  438. }
  439. Reserved = RECEIVE_RESERVED(Packet);
  440. #ifdef NB_TRACK_POOL
  441. Reserved->Pool = ReceivePool;
  442. #endif
  443. }
  444. ReceivePool->PacketCount = PacketNum;
  445. ReceivePool->PacketFree = PacketNum;
  446. for (PacketNum = 0; PacketNum < ReceivePool->PacketCount; PacketNum++) {
  447. Packet = &ReceivePool->Packets[PacketNum];
  448. Reserved = RECEIVE_RESERVED(Packet);
  449. ExInterlockedPushEntrySList(
  450. &Device->ReceivePacketList,
  451. &Reserved->PoolLinkage,
  452. &NbiGlobalPoolInterlock);
  453. // PushEntryList (&Device->ReceivePacketList, &Reserved->PoolLinkage);
  454. }
  455. InsertTailList (&Device->ReceivePoolList, &ReceivePool->Linkage);
  456. Device->AllocatedReceivePackets += ReceivePool->PacketCount;
  457. } /* NbiAllocateReceivePool */
  458. #if defined(_PNP_POWER)
  459. VOID
  460. NbiAllocateReceiveBufferPool(
  461. IN PDEVICE Device,
  462. IN UINT DataLength
  463. )
  464. /*++
  465. Routine Description:
  466. This routine adds receive buffers to the pool for this device.
  467. NOTE: THIS ROUTINE IS CALLED WITH THE DEVICE LOCK HELD AND
  468. RETURNS WITH IT HELD.
  469. Arguments:
  470. Device - The device.
  471. DataLength - Max length of the data in each buffer.
  472. Return Value:
  473. None.
  474. --*/
  475. {
  476. PNB_RECEIVE_BUFFER ReceiveBuffer;
  477. UINT ReceiveBufferPoolSize;
  478. UINT BufferNum;
  479. PNB_RECEIVE_BUFFER_POOL ReceiveBufferPool;
  480. PUCHAR Data;
  481. ReceiveBufferPoolSize = FIELD_OFFSET (NB_RECEIVE_BUFFER_POOL, Buffers[0]) +
  482. (sizeof(NB_RECEIVE_BUFFER) * Device->InitPackets) +
  483. (DataLength * Device->InitPackets);
  484. ReceiveBufferPool = (PNB_RECEIVE_BUFFER_POOL)NbiAllocateMemory (ReceiveBufferPoolSize, MEMORY_PACKET, "ReceiveBufferPool");
  485. if (ReceiveBufferPool == NULL) {
  486. NB_DEBUG (PACKET, ("Could not allocate receive buffer pool memory\n"));
  487. return;
  488. }
  489. RtlZeroMemory (ReceiveBufferPool, ReceiveBufferPoolSize);
  490. NB_DEBUG2 (PACKET, ("Initializing receive buffer pool %lx, %d buffers, data %d\n",
  491. ReceiveBufferPool, Device->InitPackets, DataLength));
  492. Data = (PUCHAR)(&ReceiveBufferPool->Buffers[Device->InitPackets]);
  493. for (BufferNum = 0; BufferNum < Device->InitPackets; BufferNum++) {
  494. ReceiveBuffer = &ReceiveBufferPool->Buffers[BufferNum];
  495. if (NbiInitializeReceiveBuffer (Device, ReceiveBuffer, Data, DataLength) != STATUS_SUCCESS) {
  496. NB_DEBUG (PACKET, ("Could not initialize buffer %lx\n", ReceiveBuffer));
  497. break;
  498. }
  499. ReceiveBuffer->Pool = ReceiveBufferPool;
  500. Data += DataLength;
  501. }
  502. ReceiveBufferPool->BufferCount = BufferNum;
  503. ReceiveBufferPool->BufferFree = BufferNum;
  504. ReceiveBufferPool->BufferDataSize = DataLength;
  505. for (BufferNum = 0; BufferNum < ReceiveBufferPool->BufferCount; BufferNum++) {
  506. ReceiveBuffer = &ReceiveBufferPool->Buffers[BufferNum];
  507. PushEntryList (&Device->ReceiveBufferList, &ReceiveBuffer->PoolLinkage);
  508. }
  509. InsertTailList (&Device->ReceiveBufferPoolList, &ReceiveBufferPool->Linkage);
  510. Device->AllocatedReceiveBuffers += ReceiveBufferPool->BufferCount;
  511. Device->CurMaxReceiveBufferSize = DataLength;
  512. } /* NbiAllocateReceiveBufferPool */
  513. #else
  514. VOID
  515. NbiAllocateReceiveBufferPool(
  516. IN PDEVICE Device
  517. )
  518. /*++
  519. Routine Description:
  520. This routine adds receive buffers to the pool for this device.
  521. NOTE: THIS ROUTINE IS CALLED WITH THE DEVICE LOCK HELD AND
  522. RETURNS WITH IT HELD.
  523. Arguments:
  524. Device - The device.
  525. Return Value:
  526. None.
  527. --*/
  528. {
  529. PNB_RECEIVE_BUFFER ReceiveBuffer;
  530. UINT ReceiveBufferPoolSize;
  531. UINT BufferNum;
  532. PNB_RECEIVE_BUFFER_POOL ReceiveBufferPool;
  533. UINT DataLength;
  534. PUCHAR Data;
  535. DataLength = Device->Bind.LineInfo.MaximumPacketSize;
  536. ReceiveBufferPoolSize = FIELD_OFFSET (NB_RECEIVE_BUFFER_POOL, Buffers[0]) +
  537. (sizeof(NB_RECEIVE_BUFFER) * Device->InitPackets) +
  538. (DataLength * Device->InitPackets);
  539. ReceiveBufferPool = (PNB_RECEIVE_BUFFER_POOL)NbiAllocateMemory (ReceiveBufferPoolSize, MEMORY_PACKET, "ReceiveBufferPool");
  540. if (ReceiveBufferPool == NULL) {
  541. NB_DEBUG (PACKET, ("Could not allocate receive buffer pool memory\n"));
  542. return;
  543. }
  544. RtlZeroMemory (ReceiveBufferPool, ReceiveBufferPoolSize);
  545. NB_DEBUG2 (PACKET, ("Initializing receive buffer pool %lx, %d buffers, data %d\n",
  546. ReceiveBufferPool, Device->InitPackets, DataLength));
  547. Data = (PUCHAR)(&ReceiveBufferPool->Buffers[Device->InitPackets]);
  548. for (BufferNum = 0; BufferNum < Device->InitPackets; BufferNum++) {
  549. ReceiveBuffer = &ReceiveBufferPool->Buffers[BufferNum];
  550. if (NbiInitializeReceiveBuffer (Device, ReceiveBuffer, Data, DataLength) != STATUS_SUCCESS) {
  551. NB_DEBUG (PACKET, ("Could not initialize buffer %lx\n", ReceiveBuffer));
  552. break;
  553. }
  554. #ifdef NB_TRACK_POOL
  555. ReceiveBuffer->Pool = ReceiveBufferPool;
  556. #endif
  557. Data += DataLength;
  558. }
  559. ReceiveBufferPool->BufferCount = BufferNum;
  560. ReceiveBufferPool->BufferFree = BufferNum;
  561. for (BufferNum = 0; BufferNum < ReceiveBufferPool->BufferCount; BufferNum++) {
  562. ReceiveBuffer = &ReceiveBufferPool->Buffers[BufferNum];
  563. PushEntryList (&Device->ReceiveBufferList, &ReceiveBuffer->PoolLinkage);
  564. }
  565. InsertTailList (&Device->ReceiveBufferPoolList, &ReceiveBufferPool->Linkage);
  566. Device->AllocatedReceiveBuffers += ReceiveBufferPool->BufferCount;
  567. } /* NbiAllocateReceiveBufferPool */
  568. #endif _PNP_POWER
  569. #if defined(_PNP_POWER)
  570. VOID
  571. NbiReAllocateReceiveBufferPool(
  572. IN PWORK_QUEUE_ITEM WorkItem
  573. )
  574. /*++
  575. Routine Description:
  576. This routines destroys all the existing Buffer Pools and creates
  577. new one using the larger packet size given to us by IPX because
  578. a new card was inserted with a larger packet size.
  579. Arguments:
  580. WorkItem - The work item that was allocated for this.
  581. Return Value:
  582. None.
  583. --*/
  584. {
  585. PDEVICE Device = NbiDevice;
  586. CTELockHandle LockHandle;
  587. NB_GET_LOCK ( &Device->Lock, &LockHandle );
  588. if ( Device->Bind.LineInfo.MaximumPacketSize > Device->CurMaxReceiveBufferSize ) {
  589. #if DBG
  590. DbgPrint("Reallocating new pools due to new maxpacketsize\n");
  591. #endif
  592. NbiDestroyReceiveBufferPools( Device );
  593. NbiAllocateReceiveBufferPool( Device, Device->Bind.LineInfo.MaximumPacketSize );
  594. }
  595. NB_FREE_LOCK( &Device->Lock, LockHandle );
  596. NbiFreeMemory( WorkItem, sizeof(WORK_QUEUE_ITEM), MEMORY_WORK_ITEM, "Alloc Rcv Buff Work Item freed");
  597. }
  598. #if !defined(DBG)
  599. __inline
  600. #endif
  601. VOID
  602. NbiFreeReceiveBufferPool (
  603. IN PNB_RECEIVE_BUFFER_POOL ReceiveBufferPool
  604. )
  605. /*++
  606. Routine Description:
  607. This routine frees the
  608. Arguments:
  609. Device - Pointer to our device to charge the packet to.
  610. Return Value:
  611. The pointer to the Linkage field in the allocated packet.
  612. --*/
  613. {
  614. PDEVICE Device = NbiDevice;
  615. PNB_RECEIVE_BUFFER ReceiveBuffer;
  616. UINT ReceiveBufferPoolSize,i;
  617. CTEAssert( ReceiveBufferPool->BufferDataSize );
  618. ReceiveBufferPoolSize = FIELD_OFFSET (NB_RECEIVE_BUFFER_POOL, Buffers[0]) +
  619. (sizeof(NB_RECEIVE_BUFFER) * Device->InitPackets) +
  620. (ReceiveBufferPool->BufferDataSize * Device->InitPackets);
  621. //
  622. // Check if we can free this pool
  623. //
  624. CTEAssert(ReceiveBufferPool->BufferCount == ReceiveBufferPool->BufferFree );
  625. for (i = 0; i < ReceiveBufferPool->BufferCount; i++) {
  626. ReceiveBuffer = &ReceiveBufferPool->Buffers[i];
  627. NbiDeinitializeReceiveBuffer (Device, ReceiveBuffer);
  628. }
  629. RemoveEntryList( &ReceiveBufferPool->Linkage );
  630. NB_DEBUG2 (PACKET, ("Free buffer pool %lx\n", ReceiveBufferPool));
  631. NbiFreeMemory (ReceiveBufferPool, ReceiveBufferPoolSize, MEMORY_PACKET, "ReceiveBufferPool");
  632. }
  633. VOID
  634. NbiDestroyReceiveBufferPools(
  635. IN PDEVICE Device
  636. )
  637. /*++
  638. Routine Description:
  639. This routines walks the ReceiveBufferPoolList and destroys the
  640. pool which does not have any buffer in use.
  641. Arguments:
  642. Return Value:
  643. None.
  644. THIS ROUTINE COULD BE CALLED WITH THE DEVICE LOCK HELD. If this
  645. routine is also called from the DestroyDevice routine, it is not
  646. necessary to call this with the lock.
  647. --*/
  648. {
  649. PNB_RECEIVE_BUFFER_POOL ReceiveBufferPool;
  650. PLIST_ENTRY p;
  651. PSINGLE_LIST_ENTRY Unused;
  652. //
  653. // Clean up this list before we call NbiFreeReceiveBufferPool bcoz that will
  654. // simply destroy all the buffer which might be queue here on this list.
  655. // At the end of this routine we must start with a fresh ReceiveBufferList.
  656. //
  657. do {
  658. Unused = PopEntryList( &Device->ReceiveBufferList );
  659. } while( Unused );
  660. //
  661. // Now destroy each individual ReceiveBufferPool.
  662. //
  663. for ( p = Device->ReceiveBufferPoolList.Flink;
  664. p != &Device->ReceiveBufferPoolList;
  665. ) {
  666. ReceiveBufferPool = CONTAINING_RECORD (p, NB_RECEIVE_BUFFER_POOL, Linkage);
  667. p = p->Flink;
  668. //
  669. // This will destroy and unlink this Pool if none of its buffer is
  670. // in use currently.
  671. //
  672. if ( ReceiveBufferPool->BufferCount == ReceiveBufferPool->BufferFree ) {
  673. NbiFreeReceiveBufferPool( ReceiveBufferPool );
  674. } else {
  675. //
  676. // When the device is stopping we must succeed in freeing the pool.
  677. CTEAssert( Device->State != DEVICE_STATE_STOPPING );
  678. }
  679. }
  680. }
  681. VOID
  682. NbiPushReceiveBuffer (
  683. IN PNB_RECEIVE_BUFFER ReceiveBuffer
  684. )
  685. /*++
  686. Routine Description:
  687. This routine returns the receive buffer back to the free list.
  688. It checks the size of this buffer. If it is smaller than the
  689. the CurMaxReceiveBufferSize, then it does not return this back
  690. to the free list, instead it destroys it and possibly also
  691. destroys the pool associated with it. O/w it simply returns this
  692. to the free list.
  693. Arguments:
  694. ReceiveBuffer - Pointer to the buffer to be returned to the free list.
  695. Return Value:
  696. The pointer to the Linkage field in the allocated packet.
  697. --*/
  698. {
  699. PNB_RECEIVE_BUFFER_POOL ReceiveBufferPool = (PNB_RECEIVE_BUFFER_POOL)ReceiveBuffer->Pool;
  700. PDEVICE Device = NbiDevice;
  701. CTELockHandle LockHandle;
  702. #if defined(DBG)
  703. ULONG BufLen = 0;
  704. #endif
  705. NB_GET_LOCK( &Device->Lock, &LockHandle );
  706. #if defined(DBG)
  707. NdisQueryBufferSafe (ReceiveBuffer->NdisBuffer, NULL, &BufLen, HighPagePriority);
  708. CTEAssert( BufLen == ReceiveBufferPool->BufferDataSize );
  709. #endif
  710. //
  711. // This is an old buffer which was in use when we changed
  712. // the CurMaxReceiveBufferSize due to new adapter. We must not
  713. // return this buffer back to free list. Infact, if the pool
  714. // associated with this buffer does not have any other buffers
  715. // in use, we should free the pool also.
  716. CTEAssert( ReceiveBufferPool->BufferFree < ReceiveBufferPool->BufferCount );
  717. ReceiveBufferPool->BufferFree++;
  718. if ( ReceiveBufferPool->BufferDataSize < Device->CurMaxReceiveBufferSize ) {
  719. #if DBG
  720. DbgPrint("ReceiveBuffer %lx, not returned to pool %lx( Free %d)\n", ReceiveBuffer, ReceiveBufferPool, ReceiveBufferPool->BufferFree);
  721. #endif
  722. if ( ReceiveBufferPool->BufferFree == ReceiveBufferPool->BufferCount ) {
  723. NbiFreeReceiveBufferPool( ReceiveBufferPool );
  724. }
  725. } else {
  726. PushEntryList( &Device->ReceiveBufferList, &ReceiveBuffer->PoolLinkage );
  727. }
  728. NB_FREE_LOCK( &Device->Lock, LockHandle );
  729. }
  730. #endif _PNP_POWER
  731. PSLIST_ENTRY
  732. NbiPopSendPacket(
  733. IN PDEVICE Device,
  734. IN BOOLEAN LockAcquired
  735. )
  736. /*++
  737. Routine Description:
  738. This routine allocates a packet from the device context's pool.
  739. If there are no packets in the pool, it allocates one up to
  740. the configured limit.
  741. Arguments:
  742. Device - Pointer to our device to charge the packet to.
  743. LockAcquired - TRUE if Device->Lock is acquired.
  744. Return Value:
  745. The pointer to the Linkage field in the allocated packet.
  746. --*/
  747. {
  748. PSLIST_ENTRY s;
  749. CTELockHandle LockHandle;
  750. s = ExInterlockedPopEntrySList(
  751. &Device->SendPacketList,
  752. &NbiGlobalPoolInterlock);
  753. if (s != NULL) {
  754. return s;
  755. }
  756. //
  757. // No packets in the pool, see if we can allocate more.
  758. //
  759. if (!LockAcquired) {
  760. NB_GET_LOCK (&Device->Lock, &LockHandle);
  761. }
  762. if (Device->AllocatedSendPackets < Device->MaxPackets) {
  763. //
  764. // Allocate a pool and try again.
  765. //
  766. NbiAllocateSendPool (Device);
  767. if (!LockAcquired) {
  768. NB_FREE_LOCK (&Device->Lock, LockHandle);
  769. }
  770. s = ExInterlockedPopEntrySList(
  771. &Device->SendPacketList,
  772. &NbiGlobalPoolInterlock);
  773. return s;
  774. } else {
  775. if (!LockAcquired) {
  776. NB_FREE_LOCK (&Device->Lock, LockHandle);
  777. }
  778. return NULL;
  779. }
  780. } /* NbiPopSendPacket */
  781. VOID
  782. NbiPushSendPacket(
  783. IN PNB_SEND_RESERVED Reserved
  784. )
  785. /*++
  786. Routine Description:
  787. This routine frees a packet back to the device context's pool.
  788. If there are connections waiting for packets, it removes
  789. one from the list and inserts it on the packetize queue.
  790. Arguments:
  791. Device - Pointer to our device to charge the packet to.
  792. Return Value:
  793. The pointer to the Linkage field in the allocated packet.
  794. --*/
  795. {
  796. PDEVICE Device = NbiDevice;
  797. PLIST_ENTRY p;
  798. PCONNECTION Connection;
  799. NB_DEFINE_LOCK_HANDLE (LockHandle)
  800. NB_DEFINE_LOCK_HANDLE (LockHandle1)
  801. Reserved->CurrentSendIteration = 0; // Re-initialize this field for next Send Request
  802. ExInterlockedPushEntrySList(
  803. &Device->SendPacketList,
  804. &Reserved->PoolLinkage,
  805. &NbiGlobalPoolInterlock);
  806. if (!IsListEmpty (&Device->WaitPacketConnections)) {
  807. NB_SYNC_GET_LOCK (&Device->Lock, &LockHandle);
  808. p = RemoveHeadList (&Device->WaitPacketConnections);
  809. //
  810. // Take a connection off the WaitPacketQueue and put it
  811. // on the PacketizeQueue. We don't worry about if the
  812. // connection has stopped, that will get checked when
  813. // the PacketizeQueue is run down.
  814. //
  815. // Since this is in send completion, we may not get
  816. // a receive complete. We guard against this by calling
  817. // NbiReceiveComplete from the long timer timeout.
  818. //
  819. if (p != &Device->WaitPacketConnections) {
  820. Connection = CONTAINING_RECORD (p, CONNECTION, WaitPacketLinkage);
  821. CTEAssert (Connection->OnWaitPacketQueue);
  822. Connection->OnWaitPacketQueue = FALSE;
  823. NB_SYNC_FREE_LOCK (&Device->Lock, LockHandle);
  824. NB_SYNC_GET_LOCK (&Connection->Lock, &LockHandle1);
  825. if (Connection->SubState == CONNECTION_SUBSTATE_A_W_PACKET) {
  826. CTEAssert (!Connection->OnPacketizeQueue);
  827. Connection->OnPacketizeQueue = TRUE;
  828. NbiTransferReferenceConnection (Connection, CREF_W_PACKET, CREF_PACKETIZE);
  829. NB_INSERT_TAIL_LIST(
  830. &Device->PacketizeConnections,
  831. &Connection->PacketizeLinkage,
  832. &Device->Lock);
  833. Connection->SubState = CONNECTION_SUBSTATE_A_PACKETIZE;
  834. } else {
  835. NbiDereferenceConnection (Connection, CREF_W_PACKET);
  836. }
  837. NB_SYNC_FREE_LOCK (&Connection->Lock, LockHandle1);
  838. } else {
  839. NB_SYNC_FREE_LOCK (&Device->Lock, LockHandle);
  840. }
  841. }
  842. } /* NbiPushSendPacket */
  843. VOID
  844. NbiCheckForWaitPacket(
  845. IN PCONNECTION Connection
  846. )
  847. /*++
  848. Routine Description:
  849. This routine checks if a connection is on the wait packet
  850. queue and if so takes it off and queues it to be packetized.
  851. It is meant to be called when the connection's packet has
  852. been freed.
  853. Arguments:
  854. Connection - The connection to check.
  855. Return Value:
  856. The pointer to the Linkage field in the allocated packet.
  857. --*/
  858. {
  859. PDEVICE Device = NbiDevice;
  860. NB_DEFINE_LOCK_HANDLE (LockHandle)
  861. NB_DEFINE_LOCK_HANDLE (LockHandle1)
  862. NB_SYNC_GET_LOCK (&Connection->Lock, &LockHandle);
  863. NB_SYNC_GET_LOCK (&Device->Lock, &LockHandle1);
  864. if (Connection->OnWaitPacketQueue) {
  865. Connection->OnWaitPacketQueue = FALSE;
  866. RemoveEntryList (&Connection->WaitPacketLinkage);
  867. if (Connection->SubState == CONNECTION_SUBSTATE_A_W_PACKET) {
  868. CTEAssert (!Connection->OnPacketizeQueue);
  869. Connection->OnPacketizeQueue = TRUE;
  870. NbiTransferReferenceConnection (Connection, CREF_W_PACKET, CREF_PACKETIZE);
  871. InsertTailList(
  872. &Device->PacketizeConnections,
  873. &Connection->PacketizeLinkage);
  874. Connection->SubState = CONNECTION_SUBSTATE_A_PACKETIZE;
  875. } else {
  876. NB_SYNC_FREE_LOCK (&Device->Lock, LockHandle1);
  877. NB_SYNC_FREE_LOCK (&Connection->Lock, LockHandle);
  878. NbiDereferenceConnection (Connection, CREF_W_PACKET);
  879. return;
  880. }
  881. }
  882. NB_SYNC_FREE_LOCK (&Device->Lock, LockHandle1);
  883. NB_SYNC_FREE_LOCK (&Connection->Lock, LockHandle);
  884. } /* NbiCheckForWaitPacket */
  885. PSLIST_ENTRY
  886. NbiPopReceivePacket(
  887. IN PDEVICE Device
  888. )
  889. /*++
  890. Routine Description:
  891. This routine allocates a packet from the device context's pool.
  892. If there are no packets in the pool, it allocates one up to
  893. the configured limit.
  894. Arguments:
  895. Device - Pointer to our device to charge the packet to.
  896. Return Value:
  897. The pointer to the Linkage field in the allocated packet.
  898. --*/
  899. {
  900. PSLIST_ENTRY s;
  901. CTELockHandle LockHandle;
  902. s = ExInterlockedPopEntrySList(
  903. &Device->ReceivePacketList,
  904. &NbiGlobalPoolInterlock);
  905. if (s != NULL) {
  906. return s;
  907. }
  908. //
  909. // No packets in the pool, see if we can allocate more.
  910. //
  911. if (Device->AllocatedReceivePackets < Device->MaxPackets) {
  912. //
  913. // Allocate a pool and try again.
  914. //
  915. NB_GET_LOCK (&Device->Lock, &LockHandle);
  916. NbiAllocateReceivePool (Device);
  917. NB_FREE_LOCK (&Device->Lock, LockHandle);
  918. s = ExInterlockedPopEntrySList(
  919. &Device->ReceivePacketList,
  920. &NbiGlobalPoolInterlock);
  921. return s;
  922. } else {
  923. return NULL;
  924. }
  925. } /* NbiPopReceivePacket */
  926. PSINGLE_LIST_ENTRY
  927. NbiPopReceiveBuffer(
  928. IN PDEVICE Device
  929. )
  930. /*++
  931. Routine Description:
  932. This routine allocates a receive buffer from the device context's pool.
  933. If there are no buffers in the pool, it allocates one up to
  934. the configured limit.
  935. Arguments:
  936. Device - Pointer to our device to charge the buffer to.
  937. Return Value:
  938. The pointer to the Linkage field in the allocated receive buffer.
  939. --*/
  940. {
  941. #if defined(_PNP_POWER)
  942. PSINGLE_LIST_ENTRY s;
  943. PNB_RECEIVE_BUFFER ReceiveBuffer;
  944. PNB_RECEIVE_BUFFER_POOL ReceiveBufferPool;
  945. CTELockHandle LockHandle;
  946. NB_GET_LOCK( &Device->Lock, &LockHandle );
  947. s = PopEntryList( &Device->ReceiveBufferList );
  948. if ( !s ) {
  949. //
  950. // No buffer in the pool, see if we can allocate more.
  951. //
  952. if (Device->AllocatedReceiveBuffers < Device->MaxReceiveBuffers) {
  953. //
  954. // Allocate a pool and try again.
  955. //
  956. NbiAllocateReceiveBufferPool (Device, Device->CurMaxReceiveBufferSize );
  957. s = PopEntryList(&Device->ReceiveBufferList);
  958. }
  959. }
  960. if ( s ) {
  961. //
  962. // Decrement the BufferFree count on the corresponding ReceiveBufferPool.
  963. // so that we know that
  964. ReceiveBuffer = CONTAINING_RECORD( s, NB_RECEIVE_BUFFER, PoolLinkage );
  965. ReceiveBufferPool = (PNB_RECEIVE_BUFFER_POOL)ReceiveBuffer->Pool;
  966. CTEAssert( ReceiveBufferPool->BufferFree && ( ReceiveBufferPool->BufferFree <= ReceiveBufferPool->BufferCount ) );
  967. CTEAssert( ReceiveBufferPool->BufferDataSize == Device->CurMaxReceiveBufferSize );
  968. ReceiveBufferPool->BufferFree--;
  969. }
  970. NB_FREE_LOCK (&Device->Lock, LockHandle);
  971. return s;
  972. #else
  973. PSINGLE_LIST_ENTRY s;
  974. CTELockHandle LockHandle;
  975. s = ExInterlockedPopEntryList(
  976. &Device->ReceiveBufferList,
  977. &Device->Lock.Lock);
  978. if (s != NULL) {
  979. return s;
  980. }
  981. //
  982. // No buffer in the pool, see if we can allocate more.
  983. //
  984. if (Device->AllocatedReceiveBuffers < Device->MaxReceiveBuffers) {
  985. //
  986. // Allocate a pool and try again.
  987. //
  988. NB_GET_LOCK (&Device->Lock, &LockHandle);
  989. NbiAllocateReceiveBufferPool (Device);
  990. s = PopEntryList(&Device->ReceiveBufferList);
  991. NB_FREE_LOCK (&Device->Lock, LockHandle);
  992. return s;
  993. } else {
  994. return NULL;
  995. }
  996. #endif _PNP_POWER
  997. } /* NbiPopReceiveBuffer */