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.

1317 lines
29 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. Sanjay Anand (SanjayAn) - 22-Sept-1995
  13. BackFill optimization changes added under #if BACK_FILL
  14. --*/
  15. #include "precomp.h"
  16. #pragma hdrstop
  17. NTSTATUS
  18. IpxInitializeSendPacket(
  19. IN PDEVICE Device,
  20. IN PIPX_SEND_PACKET Packet,
  21. IN PUCHAR Header
  22. )
  23. /*++
  24. Routine Description:
  25. This routine initializes a send packet by chaining the
  26. buffer for the header on it.
  27. Arguments:
  28. Device - The device.
  29. Packet - The packet to initialize.
  30. Header - Points to storage for the header.
  31. Return Value:
  32. None.
  33. --*/
  34. {
  35. NDIS_STATUS NdisStatus;
  36. NTSTATUS Status;
  37. PNDIS_BUFFER NdisMacBuffer;
  38. PNDIS_BUFFER NdisIpxBuffer;
  39. PIPX_SEND_RESERVED Reserved;
  40. IpxAllocateSendPacket (Device, Packet, &Status);
  41. if (Status != STATUS_SUCCESS) {
  42. // ERROR LOG
  43. return Status;
  44. }
  45. NdisAllocateBuffer(
  46. &NdisStatus,
  47. &NdisMacBuffer,
  48. Device->NdisBufferPoolHandle,
  49. Header,
  50. MAC_HEADER_SIZE);
  51. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  52. IpxFreeSendPacket (Device, Packet);
  53. // ERROR LOG
  54. return STATUS_INSUFFICIENT_RESOURCES;
  55. }
  56. NdisAllocateBuffer(
  57. &NdisStatus,
  58. &NdisIpxBuffer,
  59. Device->NdisBufferPoolHandle,
  60. Header + MAC_HEADER_SIZE,
  61. IPX_HEADER_SIZE + RIP_PACKET_SIZE);
  62. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  63. IpxFreeSendPacket (Device, Packet);
  64. // ERROR LOG
  65. return STATUS_INSUFFICIENT_RESOURCES;
  66. }
  67. NdisChainBufferAtFront (PACKET(Packet), NdisMacBuffer);
  68. NdisChainBufferAtBack (PACKET(Packet), NdisIpxBuffer);
  69. //
  70. // This flag optimizes the virtual to physical address X-ln
  71. // in the MAC drivers on x86
  72. //
  73. NdisMacBuffer->MdlFlags|=MDL_NETWORK_HEADER;
  74. NdisIpxBuffer->MdlFlags|=MDL_NETWORK_HEADER;
  75. Reserved = SEND_RESERVED(Packet);
  76. Reserved->Identifier = IDENTIFIER_IPX;
  77. Reserved->SendInProgress = FALSE;
  78. Reserved->Header = Header;
  79. Reserved->HeaderBuffer = NdisMacBuffer;
  80. Reserved->PaddingBuffer = NULL;
  81. #if BACK_FILL
  82. Reserved->BackFill = FALSE;
  83. #endif
  84. ExInterlockedInsertHeadList(
  85. &Device->GlobalSendPacketList,
  86. &Reserved->GlobalLinkage,
  87. &Device->Lock);
  88. return STATUS_SUCCESS;
  89. } /* IpxInitializeSendPacket */
  90. #if BACK_FILL
  91. NTSTATUS
  92. IpxInitializeBackFillPacket(
  93. IN PDEVICE Device,
  94. IN PIPX_SEND_PACKET Packet,
  95. IN PUCHAR Header
  96. )
  97. /*++
  98. Routine Description:
  99. This routine initializes a send packet by chaining the
  100. buffer for the header on it.
  101. Arguments:
  102. Device - The device.
  103. Packet - The packet to initialize.
  104. Header - Points to storage for the header.
  105. Return Value:
  106. None.
  107. --*/
  108. {
  109. NDIS_STATUS NdisStatus;
  110. NTSTATUS Status;
  111. PNDIS_BUFFER NdisMacBuffer;
  112. PNDIS_BUFFER NdisIpxBuffer;
  113. PIPX_SEND_RESERVED Reserved;
  114. IPX_DEBUG (PACKET, ("Initializing backfill packet\n"));
  115. IpxAllocateSendPacket (Device, Packet, &Status);
  116. if (Status != STATUS_SUCCESS) {
  117. // ERROR LOG
  118. return Status;
  119. }
  120. Reserved = SEND_RESERVED(Packet);
  121. Reserved->Identifier = IDENTIFIER_IPX;
  122. Reserved->SendInProgress = FALSE;
  123. Reserved->Header = NULL;
  124. Reserved->HeaderBuffer = NULL;
  125. Reserved->PaddingBuffer = NULL;
  126. Reserved->BackFill = TRUE;
  127. ExInterlockedInsertHeadList(
  128. &Device->GlobalBackFillPacketList,
  129. &Reserved->GlobalLinkage,
  130. &Device->Lock);
  131. IPX_DEBUG (PACKET, ("Initializing backfill packet Done\n"));
  132. return STATUS_SUCCESS;
  133. } /* IpxInitializeBackFillPacket */
  134. #endif
  135. NTSTATUS
  136. IpxInitializeReceivePacket(
  137. IN PDEVICE Device,
  138. IN PIPX_RECEIVE_PACKET Packet
  139. )
  140. /*++
  141. Routine Description:
  142. This routine initializes a receive packet.
  143. Arguments:
  144. Device - The device.
  145. Packet - The packet to initialize.
  146. Return Value:
  147. None.
  148. --*/
  149. {
  150. NTSTATUS Status;
  151. PIPX_RECEIVE_RESERVED Reserved;
  152. IpxAllocateReceivePacket (Device, Packet, &Status);
  153. if (Status != STATUS_SUCCESS) {
  154. // ERROR LOG
  155. return Status;
  156. }
  157. Reserved = RECEIVE_RESERVED(Packet);
  158. Reserved->Identifier = IDENTIFIER_IPX;
  159. Reserved->TransferInProgress = FALSE;
  160. Reserved->SingleRequest = NULL;
  161. Reserved->ReceiveBuffer = NULL;
  162. InitializeListHead (&Reserved->Requests);
  163. ExInterlockedInsertHeadList(
  164. &Device->GlobalReceivePacketList,
  165. &Reserved->GlobalLinkage,
  166. &Device->Lock);
  167. return STATUS_SUCCESS;
  168. } /* IpxInitializeReceivePacket */
  169. NTSTATUS
  170. IpxInitializeReceiveBuffer(
  171. IN PADAPTER Adapter,
  172. IN PIPX_RECEIVE_BUFFER ReceiveBuffer,
  173. IN PUCHAR DataBuffer,
  174. IN ULONG DataBufferLength
  175. )
  176. /*++
  177. Routine Description:
  178. This routine initializes a receive buffer by allocating
  179. an NDIS_BUFFER to describe the data buffer.
  180. Arguments:
  181. Adapter - The adapter.
  182. ReceiveBuffer - The receive buffer to initialize.
  183. DataBuffer - The data buffer.
  184. DataBufferLength - The length of the data buffer.
  185. Return Value:
  186. None.
  187. --*/
  188. {
  189. NDIS_STATUS NdisStatus;
  190. PNDIS_BUFFER NdisBuffer;
  191. PDEVICE Device = Adapter->Device;
  192. NdisAllocateBuffer(
  193. &NdisStatus,
  194. &NdisBuffer,
  195. Device->NdisBufferPoolHandle,
  196. DataBuffer,
  197. DataBufferLength);
  198. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  199. // ERROR LOG
  200. return STATUS_INSUFFICIENT_RESOURCES;
  201. }
  202. ReceiveBuffer->NdisBuffer = NdisBuffer;
  203. ReceiveBuffer->Data = DataBuffer;
  204. ReceiveBuffer->DataLength = 0;
  205. ExInterlockedInsertHeadList(
  206. &Device->GlobalReceiveBufferList,
  207. &ReceiveBuffer->GlobalLinkage,
  208. &Device->Lock);
  209. return STATUS_SUCCESS;
  210. } /* IpxInitializeReceiveBuffer */
  211. NTSTATUS
  212. IpxInitializePaddingBuffer(
  213. IN PDEVICE Device,
  214. IN PIPX_PADDING_BUFFER PaddingBuffer,
  215. IN ULONG DataBufferLength
  216. )
  217. /*++
  218. Routine Description:
  219. This routine initializes a padding buffer by allocating
  220. an NDIS_BUFFER to describe the data buffer.
  221. Arguments:
  222. Adapter - The adapter.
  223. PaddingBuffer - The receive buffer to initialize.
  224. DataBufferLength - The length of the data buffer.
  225. Return Value:
  226. None.
  227. --*/
  228. {
  229. NDIS_STATUS NdisStatus;
  230. PNDIS_BUFFER NdisBuffer;
  231. NdisAllocateBuffer(
  232. &NdisStatus,
  233. &NdisBuffer,
  234. Device->NdisBufferPoolHandle,
  235. PaddingBuffer->Data,
  236. DataBufferLength);
  237. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  238. // ERROR LOG
  239. return STATUS_INSUFFICIENT_RESOURCES;
  240. }
  241. NDIS_BUFFER_LINKAGE(NdisBuffer) = (PNDIS_BUFFER)NULL;
  242. PaddingBuffer->NdisBuffer = NdisBuffer;
  243. PaddingBuffer->DataLength = DataBufferLength;
  244. RtlZeroMemory (PaddingBuffer->Data, DataBufferLength);
  245. return STATUS_SUCCESS;
  246. } /* IpxInitializePaddingBuffer */
  247. VOID
  248. IpxDeinitializeSendPacket(
  249. IN PDEVICE Device,
  250. IN PIPX_SEND_PACKET Packet
  251. )
  252. /*++
  253. Routine Description:
  254. This routine deinitializes a send packet.
  255. Arguments:
  256. Device - The device.
  257. Packet - The packet to deinitialize.
  258. Return Value:
  259. None.
  260. --*/
  261. {
  262. PNDIS_BUFFER NdisBuffer;
  263. PNDIS_BUFFER NdisIpxBuffer;
  264. PIPX_SEND_RESERVED Reserved;
  265. CTELockHandle LockHandle;
  266. Reserved = SEND_RESERVED(Packet);
  267. CTEGetLock (&Device->Lock, &LockHandle);
  268. RemoveEntryList (&Reserved->GlobalLinkage);
  269. CTEFreeLock (&Device->Lock, LockHandle);
  270. //
  271. // Free the packet in a slightly unconventional way; this
  272. // allows us to not have to NULL out HeaderBuffer's linkage
  273. // field during normal operations when we put it back in
  274. // the free pool.
  275. //
  276. NdisBuffer = Reserved->HeaderBuffer;
  277. NdisIpxBuffer = NDIS_BUFFER_LINKAGE(NdisBuffer);
  278. NDIS_BUFFER_LINKAGE (NdisBuffer) = NULL;
  279. NDIS_BUFFER_LINKAGE (NdisIpxBuffer) = NULL;
  280. #if 0
  281. NdisAdjustBufferLength (NdisBuffer, PACKET_HEADER_SIZE);
  282. #endif
  283. NdisAdjustBufferLength (NdisBuffer, MAC_HEADER_SIZE);
  284. NdisAdjustBufferLength (NdisIpxBuffer, IPX_HEADER_SIZE + RIP_PACKET_SIZE);
  285. NdisFreeBuffer (NdisBuffer);
  286. NdisFreeBuffer (NdisIpxBuffer);
  287. NdisReinitializePacket (PACKET(Packet));
  288. IpxFreeSendPacket (Device, Packet);
  289. } /* IpxDeinitializeSendPacket */
  290. #if BACK_FILL
  291. VOID
  292. IpxDeinitializeBackFillPacket(
  293. IN PDEVICE Device,
  294. IN PIPX_SEND_PACKET Packet
  295. )
  296. /*++
  297. Routine Description:
  298. This routine deinitializes a back fill packet.
  299. Arguments:
  300. Device - The device.
  301. Packet - The packet to deinitialize.
  302. Return Value:
  303. None.
  304. --*/
  305. {
  306. PNDIS_BUFFER NdisBuffer;
  307. PNDIS_BUFFER NdisIpxBuffer;
  308. PIPX_SEND_RESERVED Reserved;
  309. CTELockHandle LockHandle;
  310. IPX_DEBUG (PACKET, ("DeInitializing backfill packet\n"));
  311. Reserved = SEND_RESERVED(Packet);
  312. CTEGetLock (&Device->Lock, &LockHandle);
  313. RemoveEntryList (&Reserved->GlobalLinkage);
  314. CTEFreeLock (&Device->Lock, LockHandle);
  315. NdisReinitializePacket (PACKET(Packet));
  316. IpxFreeSendPacket (Device, Packet);
  317. IPX_DEBUG (PACKET, ("DeInitializing backfill packet Done\n"));
  318. } /* IpxDeinitializeBackFillPacket */
  319. #endif
  320. VOID
  321. IpxDeinitializeReceivePacket(
  322. IN PDEVICE Device,
  323. IN PIPX_RECEIVE_PACKET Packet
  324. )
  325. /*++
  326. Routine Description:
  327. This routine initializes a receive packet.
  328. Arguments:
  329. Device - The device.
  330. Packet - The packet to initialize.
  331. Return Value:
  332. None.
  333. --*/
  334. {
  335. PIPX_RECEIVE_RESERVED Reserved;
  336. CTELockHandle LockHandle;
  337. Reserved = RECEIVE_RESERVED(Packet);
  338. CTEGetLock (&Device->Lock, &LockHandle);
  339. RemoveEntryList (&Reserved->GlobalLinkage);
  340. CTEFreeLock (&Device->Lock, LockHandle);
  341. IpxFreeReceivePacket (Device, Packet);
  342. } /* IpxDeinitializeReceivePacket */
  343. VOID
  344. IpxDeinitializeReceiveBuffer(
  345. IN PADAPTER Adapter,
  346. IN PIPX_RECEIVE_BUFFER ReceiveBuffer,
  347. IN ULONG DataBufferLength
  348. )
  349. /*++
  350. Routine Description:
  351. This routine deinitializes a receive buffer.
  352. Arguments:
  353. Device - The device.
  354. ReceiveBuffer - The receive buffer.
  355. DataBufferLength - The allocated length of the receive buffer.
  356. Return Value:
  357. None.
  358. --*/
  359. {
  360. CTELockHandle LockHandle;
  361. PDEVICE Device = Adapter->Device;
  362. CTEGetLock (&Device->Lock, &LockHandle);
  363. RemoveEntryList (&ReceiveBuffer->GlobalLinkage);
  364. CTEFreeLock (&Device->Lock, LockHandle);
  365. NdisAdjustBufferLength (ReceiveBuffer->NdisBuffer, DataBufferLength);
  366. NdisFreeBuffer (ReceiveBuffer->NdisBuffer);
  367. } /* IpxDeinitializeReceiveBuffer */
  368. VOID
  369. IpxDeinitializePaddingBuffer(
  370. IN PDEVICE Device,
  371. IN PIPX_PADDING_BUFFER PaddingBuffer,
  372. IN ULONG DataBufferLength
  373. )
  374. /*++
  375. Routine Description:
  376. This routine deinitializes a padding buffer.
  377. Arguments:
  378. Device - The device.
  379. PaddingBuffer - The padding buffer.
  380. DataBufferLength - The allocated length of the padding buffer.
  381. Return Value:
  382. None.
  383. --*/
  384. {
  385. NdisAdjustBufferLength (PaddingBuffer->NdisBuffer, DataBufferLength);
  386. NdisFreeBuffer (PaddingBuffer->NdisBuffer);
  387. } /* IpxDeinitializePaddingBuffer */
  388. VOID
  389. IpxAllocateSendPool(
  390. IN PDEVICE Device
  391. )
  392. /*++
  393. Routine Description:
  394. This routine adds 10 packets to the pool for this device.
  395. Arguments:
  396. Device - The device.
  397. Return Value:
  398. None.
  399. --*/
  400. {
  401. PIPX_SEND_POOL SendPool;
  402. UINT HeaderSize;
  403. UINT PacketNum;
  404. IPX_SEND_PACKET Packet;
  405. PIPX_SEND_RESERVED Reserved;
  406. PUCHAR Header;
  407. NDIS_STATUS Status;
  408. CTELockHandle LockHandle;
  409. SendPool = (PIPX_SEND_POOL)IpxAllocateMemory (sizeof(IPX_SEND_POOL), MEMORY_PACKET, "SendPool");
  410. if (SendPool == NULL) {
  411. IPX_DEBUG (PACKET, ("Could not allocate send pool memory\n"));
  412. return;
  413. }
  414. HeaderSize = PACKET_HEADER_SIZE * Device->InitDatagrams;
  415. Header = (PUCHAR)IpxAllocateMemory (HeaderSize, MEMORY_PACKET, "SendPool");
  416. if (Header == NULL) {
  417. IPX_DEBUG (PACKET, ("Could not allocate header memory\n"));
  418. //290901
  419. IpxFreeMemory(SendPool, sizeof(IPX_SEND_POOL), MEMORY_PACKET, "SendPool");
  420. return;
  421. }
  422. SendPool->PoolHandle = (void *) NDIS_PACKET_POOL_TAG_FOR_NWLNKIPX;
  423. NdisAllocatePacketPoolEx(
  424. &Status,
  425. &SendPool->PoolHandle,
  426. Device->InitDatagrams,
  427. 0,
  428. sizeof(IPX_SEND_RESERVED)
  429. );
  430. if (Status == NDIS_STATUS_RESOURCES) {
  431. IPX_DEBUG (PACKET, ("Could not allocate Ndis pool memory\n"));
  432. //290901
  433. IpxFreeMemory(SendPool, sizeof(IPX_SEND_POOL), MEMORY_PACKET, "SendPool");
  434. IpxFreeMemory(Header, HeaderSize, MEMORY_PACKET, "SendPool");
  435. return;
  436. }
  437. NdisSetPacketPoolProtocolId(SendPool->PoolHandle, NDIS_PROTOCOL_ID_IPX);
  438. Device->MemoryUsage += Device->InitDatagrams * sizeof(IPX_SEND_RESERVED);
  439. IPX_DEBUG (PACKET, ("Initializing send pool %lx, %d packets\n",
  440. SendPool, Device->InitDatagrams));
  441. SendPool->Header = Header;
  442. for (PacketNum = 0; PacketNum < Device->InitDatagrams; PacketNum++) {
  443. NdisAllocatePacket(&Status, &PACKET(&Packet), SendPool->PoolHandle);
  444. if (IpxInitializeSendPacket (Device, &Packet, Header) != STATUS_SUCCESS) {
  445. IPX_DEBUG (PACKET, ("Could not initialize packet %lx\n", Packet));
  446. break;
  447. }
  448. Reserved = SEND_RESERVED(&Packet);
  449. Reserved->Address = NULL;
  450. Reserved->OwnedByAddress = FALSE;
  451. #ifdef IPX_TRACK_POOL
  452. Reserved->Pool = SendPool;
  453. #endif
  454. IPX_PUSH_ENTRY_LIST (&Device->SendPacketList, &Reserved->PoolLinkage, &Device->SListsLock);
  455. Header += PACKET_HEADER_SIZE;
  456. }
  457. CTEGetLock (&Device->Lock, &LockHandle);
  458. Device->AllocatedDatagrams += PacketNum;
  459. InsertTailList (&Device->SendPoolList, &SendPool->Linkage);
  460. CTEFreeLock (&Device->Lock, LockHandle);
  461. } /* IpxAllocateSendPool */
  462. #if BACK_FILL
  463. VOID
  464. IpxAllocateBackFillPool(
  465. IN PDEVICE Device
  466. )
  467. /*++
  468. Routine Description:
  469. This routine adds 10 packets to the pool for this device.
  470. Arguments:
  471. Device - The device.
  472. Return Value:
  473. None.
  474. --*/
  475. {
  476. UINT PacketNum;
  477. IPX_SEND_PACKET Packet;
  478. PIPX_SEND_RESERVED Reserved;
  479. CTELockHandle LockHandle;
  480. PIPX_SEND_POOL BackFillPool;
  481. NDIS_STATUS Status;
  482. IPX_DEBUG (PACKET, ("Allocating backfill pool\n"));
  483. // Allocate pool for back fillable packets
  484. BackFillPool = (PIPX_SEND_POOL)IpxAllocateMemory (sizeof(IPX_SEND_POOL), MEMORY_PACKET, "BafiPool");
  485. if (BackFillPool == NULL) {
  486. IPX_DEBUG (PACKET, ("Could not allocate backfill pool memory\n"));
  487. return;
  488. }
  489. BackFillPool->PoolHandle = (void *) NDIS_PACKET_POOL_TAG_FOR_NWLNKIPX;
  490. NdisAllocatePacketPoolEx(
  491. &Status,
  492. &BackFillPool->PoolHandle,
  493. Device->InitDatagrams,
  494. 0,
  495. sizeof(IPX_SEND_RESERVED)
  496. );
  497. if (Status == NDIS_STATUS_RESOURCES) {
  498. IPX_DEBUG (PACKET, ("Could not allocate Ndis pool memory\n"));
  499. return;
  500. }
  501. NdisSetPacketPoolProtocolId(BackFillPool->PoolHandle, NDIS_PROTOCOL_ID_IPX);
  502. Device->MemoryUsage += Device->InitDatagrams * sizeof(IPX_SEND_RESERVED);
  503. for (PacketNum = 0; PacketNum < Device->InitDatagrams; PacketNum++) {
  504. NdisAllocatePacket(&Status, &PACKET(&Packet), BackFillPool->PoolHandle);
  505. if (IpxInitializeBackFillPacket (Device, &Packet, NULL) != STATUS_SUCCESS) {
  506. IPX_DEBUG (PACKET, ("Could not initialize packet %lx\n", Packet));
  507. break;
  508. }
  509. Reserved = SEND_RESERVED(&Packet);
  510. Reserved->Address = NULL;
  511. Reserved->OwnedByAddress = FALSE;
  512. #ifdef IPX_TRACK_POOL
  513. Reserved->Pool = BackFillPool;
  514. #endif
  515. IPX_PUSH_ENTRY_LIST (&Device->BackFillPacketList, &Reserved->PoolLinkage, &Device->SListsLock);
  516. }
  517. CTEGetLock (&Device->Lock, &LockHandle);
  518. InsertTailList (&Device->BackFillPoolList, &BackFillPool->Linkage);
  519. CTEFreeLock (&Device->Lock, LockHandle);
  520. } /* IpxAllocateBackFillPool */
  521. #endif
  522. VOID
  523. IpxAllocateReceivePool(
  524. IN PDEVICE Device
  525. )
  526. /*++
  527. Routine Description:
  528. This routine adds receive packets to the pool for this device.
  529. Arguments:
  530. Device - The device.
  531. Return Value:
  532. None.
  533. --*/
  534. {
  535. PIPX_RECEIVE_POOL ReceivePool;
  536. UINT PacketNum;
  537. IPX_RECEIVE_PACKET Packet;
  538. PIPX_RECEIVE_RESERVED Reserved;
  539. CTELockHandle LockHandle;
  540. NDIS_STATUS Status;
  541. ReceivePool = (PIPX_SEND_POOL)IpxAllocateMemory (sizeof(IPX_RECEIVE_POOL), MEMORY_PACKET, "ReceivePool");
  542. if (ReceivePool == NULL) {
  543. IPX_DEBUG (PACKET, ("Could not allocate receive pool memory\n"));
  544. return;
  545. }
  546. ReceivePool->PoolHandle = (void *) NDIS_PACKET_POOL_TAG_FOR_NWLNKIPX;
  547. NdisAllocatePacketPoolEx(
  548. &Status,
  549. &ReceivePool->PoolHandle,
  550. Device->InitDatagrams,
  551. 0,
  552. sizeof(IPX_SEND_RESERVED)
  553. );
  554. if (Status == NDIS_STATUS_RESOURCES) {
  555. IPX_DEBUG (PACKET, ("Could not allocate receive pool memory\n"));
  556. return;
  557. }
  558. NdisSetPacketPoolProtocolId(ReceivePool->PoolHandle, NDIS_PROTOCOL_ID_IPX);
  559. IPX_DEBUG (PACKET, ("Initializing receive pool %lx, %d packets\n",
  560. ReceivePool, Device->InitReceivePackets));
  561. Device->MemoryUsage += Device->InitDatagrams * sizeof(IPX_SEND_RESERVED);
  562. for (PacketNum = 0; PacketNum < Device->InitReceivePackets; PacketNum++) {
  563. NdisAllocatePacket(&Status, &PACKET(&Packet), ReceivePool->PoolHandle);
  564. if (IpxInitializeReceivePacket (Device, &Packet) != STATUS_SUCCESS) {
  565. IPX_DEBUG (PACKET, ("Could not initialize packet %lx\n", Packet));
  566. break;
  567. }
  568. Reserved = RECEIVE_RESERVED(&Packet);
  569. Reserved->Address = NULL;
  570. Reserved->OwnedByAddress = FALSE;
  571. #ifdef IPX_TRACK_POOL
  572. Reserved->Pool = ReceivePool;
  573. #endif
  574. IPX_PUSH_ENTRY_LIST (&Device->ReceivePacketList, &Reserved->PoolLinkage, &Device->SListsLock);
  575. }
  576. CTEGetLock (&Device->Lock, &LockHandle);
  577. Device->AllocatedReceivePackets += PacketNum;
  578. InsertTailList (&Device->ReceivePoolList, &ReceivePool->Linkage);
  579. CTEFreeLock (&Device->Lock, LockHandle);
  580. } /* IpxAllocateReceivePool */
  581. VOID
  582. IpxAllocateReceiveBufferPool(
  583. IN PADAPTER Adapter
  584. )
  585. /*++
  586. Routine Description:
  587. This routine adds receive buffers to the pool for this adapter.
  588. Arguments:
  589. Adapter - The adapter.
  590. Return Value:
  591. None.
  592. --*/
  593. {
  594. PIPX_RECEIVE_BUFFER ReceiveBuffer;
  595. UINT ReceiveBufferPoolSize;
  596. UINT BufferNum;
  597. PIPX_RECEIVE_BUFFER_POOL ReceiveBufferPool;
  598. PDEVICE Device = Adapter->Device;
  599. UINT DataLength;
  600. PUCHAR Data;
  601. CTELockHandle LockHandle;
  602. DataLength = Adapter->MaxReceivePacketSize;
  603. ReceiveBufferPoolSize = FIELD_OFFSET (IPX_RECEIVE_BUFFER_POOL, Buffers[0]) +
  604. (sizeof(IPX_RECEIVE_BUFFER) * Device->InitReceiveBuffers) +
  605. (DataLength * Device->InitReceiveBuffers);
  606. ReceiveBufferPool = (PIPX_RECEIVE_BUFFER_POOL)IpxAllocateMemory (ReceiveBufferPoolSize, MEMORY_PACKET, "ReceiveBufferPool");
  607. if (ReceiveBufferPool == NULL) {
  608. IPX_DEBUG (PACKET, ("Could not allocate receive buffer pool memory\n"));
  609. return;
  610. }
  611. IPX_DEBUG (PACKET, ("Init recv buffer pool %lx, %d buffers, data %d\n",
  612. ReceiveBufferPool, Device->InitReceiveBuffers, DataLength));
  613. Data = (PUCHAR)(&ReceiveBufferPool->Buffers[Device->InitReceiveBuffers]);
  614. for (BufferNum = 0; BufferNum < Device->InitReceiveBuffers; BufferNum++) {
  615. ReceiveBuffer = &ReceiveBufferPool->Buffers[BufferNum];
  616. if (IpxInitializeReceiveBuffer (Adapter, ReceiveBuffer, Data, DataLength) != STATUS_SUCCESS) {
  617. IPX_DEBUG (PACKET, ("Could not initialize buffer %lx\n", ReceiveBuffer));
  618. break;
  619. }
  620. #ifdef IPX_TRACK_POOL
  621. ReceiveBuffer->Pool = ReceiveBufferPool;
  622. #endif
  623. Data += DataLength;
  624. }
  625. ReceiveBufferPool->BufferCount = BufferNum;
  626. ReceiveBufferPool->BufferFree = BufferNum;
  627. CTEGetLock (&Device->Lock, &LockHandle);
  628. for (BufferNum = 0; BufferNum < ReceiveBufferPool->BufferCount; BufferNum++) {
  629. ReceiveBuffer = &ReceiveBufferPool->Buffers[BufferNum];
  630. IPX_PUSH_ENTRY_LIST (&Adapter->ReceiveBufferList, &ReceiveBuffer->PoolLinkage, &Device->SListsLock);
  631. }
  632. InsertTailList (&Adapter->ReceiveBufferPoolList, &ReceiveBufferPool->Linkage);
  633. Adapter->AllocatedReceiveBuffers += ReceiveBufferPool->BufferCount;
  634. CTEFreeLock (&Device->Lock, LockHandle);
  635. } /* IpxAllocateReceiveBufferPool */
  636. PSLIST_ENTRY
  637. IpxPopSendPacket(
  638. PDEVICE Device
  639. )
  640. /*++
  641. Routine Description:
  642. This routine allocates a packet from the device context's pool.
  643. If there are no packets in the pool, it allocates one up to
  644. the configured limit.
  645. Arguments:
  646. Device - Pointer to our device to charge the packet to.
  647. Return Value:
  648. The pointer to the Linkage field in the allocated packet.
  649. --*/
  650. {
  651. PSLIST_ENTRY s;
  652. s = IPX_POP_ENTRY_LIST(
  653. &Device->SendPacketList,
  654. &Device->SListsLock);
  655. if (s != NULL) {
  656. return s;
  657. }
  658. //
  659. // No packets in the pool, see if we can allocate more.
  660. //
  661. if (Device->AllocatedDatagrams < Device->MaxDatagrams) {
  662. //
  663. // Allocate a pool and try again.
  664. //
  665. IpxAllocateSendPool (Device);
  666. s = IPX_POP_ENTRY_LIST(
  667. &Device->SendPacketList,
  668. &Device->SListsLock);
  669. return s;
  670. } else {
  671. return NULL;
  672. }
  673. } /* IpxPopSendPacket */
  674. #if BACK_FILL
  675. PSLIST_ENTRY
  676. IpxPopBackFillPacket(
  677. PDEVICE Device
  678. )
  679. /*++
  680. Routine Description:
  681. This routine allocates a packet from the device context's pool.
  682. If there are no packets in the pool, it allocates one up to
  683. the configured limit.
  684. Arguments:
  685. Device - Pointer to our device to charge the packet to.
  686. Return Value:
  687. The pointer to the Linkage field in the allocated packet.
  688. --*/
  689. {
  690. PSLIST_ENTRY s;
  691. IPX_DEBUG (PACKET, ("Popping backfill packet\n"));
  692. s = IPX_POP_ENTRY_LIST(
  693. &Device->BackFillPacketList,
  694. &Device->SListsLock);
  695. if (s != NULL) {
  696. return s;
  697. }
  698. //
  699. // No packets in the pool, see if we can allocate more.
  700. //
  701. if (Device->AllocatedDatagrams < Device->MaxDatagrams) {
  702. //
  703. // Allocate a pool and try again.
  704. //
  705. IpxAllocateBackFillPool (Device);
  706. s = IPX_POP_ENTRY_LIST(
  707. &Device->BackFillPacketList,
  708. &Device->SListsLock);
  709. IPX_DEBUG (PACKET, ("Popping backfill packet done\n"));
  710. return s;
  711. } else {
  712. return NULL;
  713. }
  714. } /* IpxPopBackFillPacket */
  715. #endif //BackFill
  716. PSLIST_ENTRY
  717. IpxPopReceivePacket(
  718. IN PDEVICE Device
  719. )
  720. /*++
  721. Routine Description:
  722. This routine allocates a packet from the device context's pool.
  723. If there are no packets in the pool, it allocates one up to
  724. the configured limit.
  725. Arguments:
  726. Device - Pointer to our device to charge the packet to.
  727. Return Value:
  728. The pointer to the Linkage field in the allocated packet.
  729. --*/
  730. {
  731. PSLIST_ENTRY s;
  732. s = IPX_POP_ENTRY_LIST(
  733. &Device->ReceivePacketList,
  734. &Device->SListsLock);
  735. if (s != NULL) {
  736. return s;
  737. }
  738. //
  739. // No packets in the pool, see if we can allocate more.
  740. //
  741. if (Device->AllocatedReceivePackets < Device->MaxReceivePackets) {
  742. //
  743. // Allocate a pool and try again.
  744. //
  745. IpxAllocateReceivePool (Device);
  746. s = IPX_POP_ENTRY_LIST(
  747. &Device->ReceivePacketList,
  748. &Device->SListsLock);
  749. return s;
  750. } else {
  751. return NULL;
  752. }
  753. } /* IpxPopReceivePacket */
  754. PSLIST_ENTRY
  755. IpxPopReceiveBuffer(
  756. IN PADAPTER Adapter
  757. )
  758. /*++
  759. Routine Description:
  760. This routine allocates a receive buffer from the adapter's pool.
  761. If there are no buffers in the pool, it allocates one up to
  762. the configured limit.
  763. Arguments:
  764. Adapter - Pointer to our adapter to charge the buffer to.
  765. Return Value:
  766. The pointer to the Linkage field in the allocated receive buffer.
  767. --*/
  768. {
  769. PSLIST_ENTRY s;
  770. PDEVICE Device = Adapter->Device;
  771. s = IPX_POP_ENTRY_LIST(
  772. &Adapter->ReceiveBufferList,
  773. &Device->SListsLock);
  774. if (s != NULL) {
  775. return s;
  776. }
  777. //
  778. // No buffer in the pool, see if we can allocate more.
  779. //
  780. if (Adapter->AllocatedReceiveBuffers < Device->MaxReceiveBuffers) {
  781. //
  782. // Allocate a pool and try again.
  783. //
  784. IpxAllocateReceiveBufferPool (Adapter);
  785. s = IPX_POP_ENTRY_LIST(
  786. &Adapter->ReceiveBufferList,
  787. &Device->SListsLock);
  788. return s;
  789. } else {
  790. return NULL;
  791. }
  792. } /* IpxPopReceiveBuffer */
  793. PIPX_PADDING_BUFFER
  794. IpxAllocatePaddingBuffer(
  795. IN PDEVICE Device
  796. )
  797. /*++
  798. Routine Description:
  799. This routine allocates a padding buffer for use by all devices.
  800. Arguments:
  801. Device - Pointer to our device to charge the packet to.
  802. Return Value:
  803. The pointer to the allocated padding buffer.
  804. --*/
  805. {
  806. PIPX_PADDING_BUFFER PaddingBuffer;
  807. ULONG PaddingBufferSize;
  808. //
  809. // We are assuming that we can use 1 global padding buffer for ALL
  810. // transmits! We must therefore test to make sure that EthernetExtraPadding
  811. // is not greater than 1. Otherwise, we must assume that the extra padding
  812. // is being used for something and we therefore cannot share across all
  813. // transmit requests.
  814. //
  815. //
  816. // We cannot support more than 1 byte padding space, since we allocate only
  817. // one buffer for all transmit requests.
  818. //
  819. if ( Device->EthernetExtraPadding > 1 ) {
  820. IPX_DEBUG (PACKET, ("Padding buffer cannot be more than 1 byte\n"));
  821. DbgBreakPoint();
  822. }
  823. //
  824. // Allocate a padding buffer if possible.
  825. //
  826. PaddingBufferSize = FIELD_OFFSET (IPX_PADDING_BUFFER, Data[0]) + Device->EthernetExtraPadding;
  827. PaddingBuffer = IpxAllocateMemory (PaddingBufferSize, MEMORY_PACKET, "PaddingBuffer");
  828. if (PaddingBuffer != NULL) {
  829. if (IpxInitializePaddingBuffer (Device, PaddingBuffer, Device->EthernetExtraPadding) !=
  830. STATUS_SUCCESS) {
  831. IpxFreeMemory (PaddingBuffer, PaddingBufferSize, MEMORY_PACKET, "Padding Buffer");
  832. } else {
  833. IPX_DEBUG (PACKET, ("Allocate padding buffer %lx\n", PaddingBuffer));
  834. return PaddingBuffer;
  835. }
  836. }
  837. return NULL;
  838. } /* IpxAllocatePaddingBuffer */
  839. VOID
  840. IpxFreePaddingBuffer(
  841. IN PDEVICE Device
  842. )
  843. /*++
  844. Routine Description:
  845. This routine deallocates the padding buffer.
  846. Arguments:
  847. Device - Pointer to our device to charge the packet to.
  848. Return Value:
  849. None
  850. --*/
  851. {
  852. ULONG PaddingBufferSize;
  853. if ( IpxPaddingBuffer == (PIPX_PADDING_BUFFER)NULL ) {
  854. return;
  855. }
  856. PaddingBufferSize = FIELD_OFFSET (IPX_PADDING_BUFFER, Data[0]) + Device->EthernetExtraPadding;
  857. IpxFreeMemory( IpxPaddingBuffer, PaddingBufferSize, MEMORY_PACKET, "Padding Buffer" );
  858. IpxPaddingBuffer = (PIPX_PADDING_BUFFER)NULL;
  859. } /* IpxFreePaddingBuffer */