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.

784 lines
22 KiB

  1. /*++
  2. Copyright (c) 1996-1999 Microsoft Corporation
  3. Module Name:
  4. recv.c
  5. Abstract:
  6. routines to handle receiving data
  7. Author:
  8. Charlie Wickham (charlwi) 08-May-1996
  9. Rajesh Sundaram (rajeshsu) 01-Aug-1998.
  10. Environment:
  11. Kernel Mode
  12. Revision History:
  13. --*/
  14. #include "psched.h"
  15. #pragma hdrstop
  16. /* External */
  17. /* Static */
  18. /* Forward */ /* Generated by Emacs 19.17.0 on Thu May 09 10:34:39 1996 */
  19. INT
  20. ClReceivePacket(
  21. IN NDIS_HANDLE ProtocolBindingContext,
  22. IN PNDIS_PACKET Packet
  23. );
  24. VOID
  25. MpReturnPacket(
  26. IN NDIS_HANDLE MiniportAdapterContext,
  27. IN PNDIS_PACKET Packet
  28. );
  29. VOID
  30. ClReceiveComplete(
  31. IN NDIS_HANDLE ProtocolBindingContext
  32. );
  33. NDIS_STATUS
  34. MpTransferData(
  35. OUT PNDIS_PACKET Packet,
  36. OUT PUINT BytesTransferred,
  37. IN NDIS_HANDLE MiniportAdapterContext,
  38. IN NDIS_HANDLE MiniportReceiveContext,
  39. IN UINT ByteOffset,
  40. IN UINT BytesToTransfer
  41. );
  42. VOID
  43. ClTransferDataComplete(
  44. IN NDIS_HANDLE ProtocolBindingContext,
  45. IN PNDIS_PACKET pNdisPacket,
  46. IN NDIS_STATUS Status,
  47. IN UINT BytesTransferred
  48. );
  49. /* End Forward */
  50. VOID
  51. PsAllocateRecvPacket(PNDIS_STATUS Status,
  52. PPNDIS_PACKET Packet,
  53. PADAPTER Adapter)
  54. {
  55. if(!Adapter->RecvPacketPool)
  56. {
  57. PS_LOCK_DPC(&Adapter->Lock);
  58. if(!Adapter->RecvPacketPool)
  59. {
  60. NDIS_HANDLE PoolHandle = (void *) NDIS_PACKET_POOL_TAG_FOR_PSCHED;
  61. NdisAllocatePacketPoolEx(Status,
  62. &PoolHandle,
  63. MIN_PACKET_POOL_SIZE,
  64. MAX_PACKET_POOL_SIZE,
  65. sizeof(PS_RECV_PACKET_CONTEXT));
  66. if(*Status != NDIS_STATUS_SUCCESS)
  67. {
  68. Adapter->Stats.OutOfPackets ++;
  69. PS_UNLOCK_DPC(&Adapter->Lock);
  70. return;
  71. }
  72. //
  73. // We successfully allocated a packet pool. We can now free the Fixed Size Block pool for the packet-stack API
  74. //
  75. Adapter->RecvPacketPool = PoolHandle;
  76. }
  77. PS_UNLOCK_DPC(&Adapter->Lock);
  78. }
  79. NdisDprAllocatePacket(Status,
  80. Packet,
  81. Adapter->RecvPacketPool);
  82. }
  83. INT
  84. ClReceivePacket(
  85. IN NDIS_HANDLE ProtocolBindingContext,
  86. IN PNDIS_PACKET MpPacket
  87. )
  88. /*++
  89. Routine Description:
  90. Called by the NIC to indicate a data as an NDIS_PACKET. Make a copy of the
  91. packet struct, switch to miniport mode and continue the packet along its way
  92. Arguments:
  93. See the DDK...
  94. Return Values:
  95. None
  96. --*/
  97. {
  98. PADAPTER Adapter = (PADAPTER)ProtocolBindingContext;
  99. NDIS_STATUS Status;
  100. PPS_RECV_PACKET_CONTEXT ContextArea;
  101. PNDIS_PACKET OurPacket;
  102. BOOLEAN Remaining;
  103. PsStructAssert( Adapter );
  104. if(!Adapter->PsNdisHandle)
  105. {
  106. return 0;
  107. }
  108. if(Adapter->MediaType == NdisMediumWan &&
  109. Adapter->ProtocolType == ARP_ETYPE_IP)
  110. {
  111. //
  112. // Munge s-mac and d-mac so that wanarp is happy.
  113. //
  114. PNDIS_BUFFER pNdisBuf;
  115. UINT Len;
  116. PETH_HEADER pAddr;
  117. PUSHORT id;
  118. PPS_WAN_LINK WanLink;
  119. pNdisBuf = MpPacket->Private.Head;
  120. NdisQueryBuffer(pNdisBuf, &pAddr, &Len);
  121. if(Len < sizeof(ETH_HEADER))
  122. {
  123. return NDIS_STATUS_FAILURE;
  124. }
  125. id = (PUSHORT)&pAddr->DestAddr[0];
  126. PS_LOCK(&Adapter->Lock);
  127. if((WanLink = (PPS_WAN_LINK)g_WanLinkTable[*id]) == 0)
  128. {
  129. PS_UNLOCK(&Adapter->Lock);
  130. return NDIS_STATUS_FAILURE;
  131. }
  132. if(WanLink->State != WanStateOpen)
  133. {
  134. PS_UNLOCK(&Adapter->Lock);
  135. return NDIS_STATUS_FAILURE;
  136. }
  137. PS_UNLOCK(&Adapter->Lock);
  138. NdisMoveMemory(pAddr,
  139. &WanLink->RecvHeader,
  140. FIELD_OFFSET(ETH_HEADER, Type));
  141. }
  142. NdisIMGetCurrentPacketStack(MpPacket, &Remaining);
  143. if(Remaining != 0)
  144. {
  145. Status = NDIS_GET_PACKET_STATUS(MpPacket);
  146. // TimeStamp will always be there; no need to check //
  147. if (!TimeStmpReceivePacket( NULL, NULL, NULL, MpPacket, Adapter->MediaType ))
  148. PsDbgRecv(DBG_FAILURE, DBG_RECEIVE, CL_RECV_PACKET, OURS, Adapter, MpPacket, 0);
  149. if (TimeStmpRecvPacket) {
  150. if (!(TimeStmpRecvPacket)(
  151. NULL,
  152. NULL,
  153. NULL,
  154. MpPacket,
  155. Adapter->MediaType
  156. )) {
  157. PsDbgRecv(DBG_FAILURE, DBG_RECEIVE, CL_RECV_PACKET, OURS, Adapter, MpPacket, 0);
  158. }
  159. }
  160. NdisMIndicateReceivePacket(Adapter->PsNdisHandle, &MpPacket, 1);
  161. return((Status != NDIS_STATUS_RESOURCES) ? 1 : 0);
  162. }
  163. else
  164. {
  165. PsAllocateRecvPacket(&Status, &OurPacket, Adapter);
  166. if(Status == NDIS_STATUS_SUCCESS)
  167. {
  168. PsDbgRecv(DBG_INFO, DBG_RECEIVE, CL_RECV_PACKET, ENTER, Adapter, OurPacket, MpPacket);
  169. //
  170. // Save Original Packet
  171. //
  172. ContextArea = PS_RECV_PACKET_CONTEXT_FROM_PACKET(OurPacket);
  173. ContextArea->OriginalPacket = MpPacket;
  174. OurPacket->Private.Head = MpPacket->Private.Head;
  175. OurPacket->Private.Tail = MpPacket->Private.Tail;
  176. //
  177. // Get the original packet (it could be the same packet as one received or a different one
  178. // based on # of layered MPs) and set it on the indicated packet so the OOB stuff is visible
  179. // correctly at the top.
  180. //
  181. NDIS_SET_ORIGINAL_PACKET(OurPacket, NDIS_GET_ORIGINAL_PACKET(MpPacket));
  182. NDIS_SET_PACKET_HEADER_SIZE(OurPacket, NDIS_GET_PACKET_HEADER_SIZE(MpPacket));
  183. //
  184. // Set Packet Flags
  185. //
  186. NdisGetPacketFlags(OurPacket) = NdisGetPacketFlags(MpPacket);
  187. Status = NDIS_GET_PACKET_STATUS(MpPacket);
  188. NDIS_SET_PACKET_STATUS(OurPacket, Status);
  189. if(!(TimeStmpReceivePacket)( NULL, NULL, NULL, OurPacket, Adapter->MediaType ))
  190. PsDbgRecv(DBG_FAILURE, DBG_RECEIVE, CL_RECV_PACKET, OURS, Adapter, OurPacket, OurPacket);
  191. if (TimeStmpRecvPacket) {
  192. if (!(TimeStmpRecvPacket)(
  193. NULL,
  194. NULL,
  195. NULL,
  196. OurPacket,
  197. Adapter->MediaType
  198. )) {
  199. PsDbgRecv(DBG_FAILURE, DBG_RECEIVE, CL_RECV_PACKET, OURS, Adapter, OurPacket, OurPacket);
  200. }
  201. }
  202. NdisMIndicateReceivePacket(Adapter->PsNdisHandle, &OurPacket, 1);
  203. if (Status == NDIS_STATUS_RESOURCES)
  204. {
  205. NdisDprFreePacket(OurPacket);
  206. }
  207. return((Status != NDIS_STATUS_RESOURCES) ? 1 : 0);
  208. }
  209. else
  210. {
  211. //
  212. // out of resources. indicate that we're not hanging onto the packet
  213. //
  214. PsDbgRecv(DBG_FAILURE, DBG_RECEIVE, CL_RECV_PACKET, NO_RESOURCES,
  215. Adapter, 0, MpPacket);
  216. Adapter->Stats.OutOfPackets ++;
  217. return 0;
  218. }
  219. }
  220. } // ClReceivePacket
  221. VOID
  222. MpReturnPacket(
  223. IN NDIS_HANDLE MiniportAdapterContext,
  224. IN PNDIS_PACKET Packet
  225. )
  226. /*++
  227. Routine Description:
  228. Potentially return a packet we indicated previously to the
  229. underlying miniport. It might be one of ours from a ProtocolReceive
  230. indication, so we disassemble it and return the packet and its
  231. buffers to their respective S Lists
  232. Arguments:
  233. See the DDK...
  234. Return Values:
  235. None
  236. --*/
  237. {
  238. PADAPTER Adapter = (PADAPTER)MiniportAdapterContext;
  239. PPS_RECV_PACKET_CONTEXT PktContext;
  240. PNDIS_PACKET MyPacket;
  241. BOOLEAN Remaining;
  242. PsStructAssert(Adapter);
  243. NdisIMGetCurrentPacketStack(Packet, &Remaining);
  244. if(Remaining != 0)
  245. {
  246. NdisReturnPackets(&Packet, 1);
  247. }
  248. else
  249. {
  250. //
  251. // see if the OriginalPacket field indicates that this belongs
  252. // to someone below us and return it now
  253. //
  254. PktContext = PS_RECV_PACKET_CONTEXT_FROM_PACKET(Packet);
  255. MyPacket = PktContext->OriginalPacket;
  256. PsDbgRecv(DBG_INFO, DBG_RECEIVE, MP_RETURN_PACKET, RETURNING, Adapter, Packet, MyPacket);
  257. NdisDprFreePacket(Packet);
  258. NdisReturnPackets(&MyPacket, 1);
  259. }
  260. } // MpReturnPacket
  261. NDIS_STATUS
  262. ClReceiveIndication(
  263. IN NDIS_HANDLE ProtocolBindingContext,
  264. IN NDIS_HANDLE MacReceiveContext,
  265. IN PVOID HeaderBuffer,
  266. IN UINT HeaderBufferSize,
  267. IN PVOID LookAheadBuffer,
  268. IN UINT LookAheadBufferSize,
  269. IN UINT PacketSize
  270. )
  271. /*++
  272. Routine Description:
  273. Called by NIC to notify protocol of incoming data. Copy the data
  274. into a cached packet we set up during initialization and indicate
  275. that packet to the higher layer.
  276. Arguments:
  277. See the DDK...
  278. Return Values:
  279. None
  280. --*/
  281. {
  282. PADAPTER Adapter = (PADAPTER)ProtocolBindingContext;
  283. PNDIS_PACKET MyPacket, Packet;
  284. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  285. PsStructAssert(Adapter);
  286. if(!Adapter->PsNdisHandle)
  287. {
  288. Status = NDIS_STATUS_FAILURE;
  289. }
  290. else
  291. {
  292. do
  293. {
  294. //
  295. // If this was indicated by the miniport below as a packet, then get that packet
  296. // pointer and indicate it as a packet as well (with appropriate status).
  297. // This way the OOB stuff is accessible to the transport above us.
  298. //
  299. Packet = NdisGetReceivedPacket(Adapter->LowerMpHandle, MacReceiveContext);
  300. if (Packet != NULL)
  301. {
  302. BOOLEAN Remaining;
  303. //
  304. // Check if there are any more packet stacks left. If there is need to keep per packet information,
  305. // then the packet stack (which is returned by the api) can be used to store that
  306. //
  307. NdisIMGetCurrentPacketStack(Packet, &Remaining);
  308. if (Remaining != 0)
  309. {
  310. NDIS_STATUS OldPacketStatus;
  311. if(!(TimeStmpReceivePacket)( NULL, NULL, NULL, Packet, Adapter->MediaType ))
  312. PsDbgRecv(DBG_FAILURE, DBG_RECEIVE, CL_RECV_IND, OURS, Adapter, Packet, Packet);
  313. if (TimeStmpRecvPacket) {
  314. if (!(TimeStmpRecvPacket)(
  315. NULL,
  316. NULL,
  317. NULL,
  318. Packet,
  319. Adapter->MediaType
  320. )) {
  321. PsDbgRecv(DBG_FAILURE, DBG_RECEIVE, CL_RECV_IND, OURS, Adapter, Packet, Packet);
  322. }
  323. }
  324. //
  325. // Save the old status, and set packet status to NDIS_STATUS_RESOURCES
  326. // because we can't have the protocol above us retain the packet -- it
  327. // can go away as soon as we return from this function.
  328. //
  329. OldPacketStatus = NDIS_GET_PACKET_STATUS(Packet);
  330. NDIS_SET_PACKET_STATUS(Packet, NDIS_STATUS_RESOURCES);
  331. NdisMIndicateReceivePacket(Adapter->PsNdisHandle, &Packet, 1);
  332. //
  333. // Restore the old Status
  334. //
  335. NDIS_SET_PACKET_STATUS(Packet, OldPacketStatus);
  336. // Since we had set the packet status to NDIS_STATUS_RESOURCES, our
  337. // ReturnPacket handler won't be called for this packet.
  338. break;
  339. }
  340. //
  341. // Get a packet off the pool and indicate that up
  342. //
  343. PsAllocateRecvPacket(&Status,
  344. &MyPacket,
  345. Adapter);
  346. if (Status == NDIS_STATUS_SUCCESS)
  347. {
  348. MyPacket->Private.Head = Packet->Private.Head;
  349. MyPacket->Private.Tail = Packet->Private.Tail;
  350. //
  351. // Get the original packet (it could be the same packet as one received or
  352. // a different one based on # of layered MPs) and set it on the indicated
  353. // packet so the OOB stuff is visible correctly at the top.
  354. //
  355. NDIS_SET_ORIGINAL_PACKET(MyPacket, NDIS_GET_ORIGINAL_PACKET(Packet));
  356. NDIS_SET_PACKET_HEADER_SIZE(MyPacket, HeaderBufferSize);
  357. //
  358. // Set Packet Flags
  359. //
  360. NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet);
  361. //
  362. // Make sure the status is set to NDIS_STATUS_RESOURCES.
  363. //
  364. NDIS_SET_PACKET_STATUS(MyPacket, NDIS_STATUS_RESOURCES);
  365. if(!(TimeStmpReceivePacket)( NULL, NULL, NULL, MyPacket, Adapter->MediaType ))
  366. PsDbgRecv(DBG_FAILURE, DBG_RECEIVE, CL_RECV_IND, OURS, Adapter, MyPacket, MyPacket);
  367. if (TimeStmpRecvPacket) {
  368. if (!(TimeStmpRecvPacket)(
  369. NULL,
  370. NULL,
  371. NULL,
  372. MyPacket,
  373. Adapter->MediaType
  374. )) {
  375. PsDbgRecv(DBG_FAILURE, DBG_RECEIVE, CL_RECV_IND, OURS, Adapter, MyPacket, MyPacket);
  376. }
  377. }
  378. NdisMIndicateReceivePacket(Adapter->PsNdisHandle, &MyPacket, 1);
  379. PsAssert (NDIS_GET_PACKET_STATUS(MyPacket) == NDIS_STATUS_RESOURCES);
  380. NdisDprFreePacket(MyPacket);
  381. break;
  382. }
  383. }
  384. //
  385. // Fall through if the miniport below us has either not indicated a packet or we
  386. // could not allocate one
  387. //
  388. Adapter->IndicateRcvComplete = TRUE;
  389. //
  390. // If the timestamp driver is present.
  391. //
  392. //
  393. if (TimeStmpRecvIndication) {
  394. if (!(TimeStmpRecvIndication)(
  395. NULL,
  396. NULL,
  397. NULL,
  398. HeaderBuffer,
  399. HeaderBufferSize,
  400. LookAheadBuffer,
  401. LookAheadBufferSize,
  402. PacketSize,
  403. Adapter->IPHeaderOffset
  404. )) {
  405. PsDbgRecv(DBG_FAILURE, DBG_RECEIVE, CL_RECV_IND, OURS, Adapter, (PNDIS_PACKET) LookAheadBuffer, NULL);
  406. }
  407. }
  408. switch (Adapter->MediaType)
  409. {
  410. case NdisMedium802_3:
  411. case NdisMediumWan:
  412. NdisMEthIndicateReceive(Adapter->PsNdisHandle,
  413. MacReceiveContext,
  414. HeaderBuffer,
  415. HeaderBufferSize,
  416. LookAheadBuffer,
  417. LookAheadBufferSize,
  418. PacketSize);
  419. break;
  420. case NdisMedium802_5:
  421. NdisMTrIndicateReceive(Adapter->PsNdisHandle,
  422. MacReceiveContext,
  423. HeaderBuffer,
  424. HeaderBufferSize,
  425. LookAheadBuffer,
  426. LookAheadBufferSize,
  427. PacketSize);
  428. break;
  429. case NdisMediumFddi:
  430. NdisMFddiIndicateReceive(Adapter->PsNdisHandle,
  431. MacReceiveContext,
  432. HeaderBuffer,
  433. HeaderBufferSize,
  434. LookAheadBuffer,
  435. LookAheadBufferSize,
  436. PacketSize);
  437. break;
  438. default:
  439. PsAssert (0);
  440. Status = NDIS_STATUS_FAILURE;
  441. break;
  442. }
  443. } while (FALSE);
  444. }
  445. return Status;
  446. } // ClReceiveIndication
  447. VOID
  448. ClReceiveComplete(
  449. IN NDIS_HANDLE ProtocolBindingContext
  450. )
  451. /*++
  452. Routine Description:
  453. Called by NIC via NdisIndicateReceiveComplete. Continue this indication
  454. up to the higher layer
  455. Arguments:
  456. See the DDK...
  457. Return Values:
  458. None
  459. --*/
  460. {
  461. PADAPTER Adapter = (PADAPTER)ProtocolBindingContext;
  462. PsStructAssert(Adapter);
  463. PsDbgRecv(DBG_INFO, DBG_RECEIVE, CL_RECV_COMPL, ENTER, Adapter, 0, 0);
  464. if((Adapter->PsNdisHandle != NULL) && Adapter->IndicateRcvComplete) {
  465. switch(Adapter->MediaType){
  466. case NdisMediumWan:
  467. case NdisMedium802_3:
  468. NdisMEthIndicateReceiveComplete(Adapter->PsNdisHandle);
  469. break;
  470. case NdisMedium802_5:
  471. NdisMTrIndicateReceiveComplete(Adapter->PsNdisHandle);
  472. break;
  473. case NdisMediumFddi:
  474. NdisMFddiIndicateReceiveComplete(Adapter->PsNdisHandle);
  475. break;
  476. default:
  477. PsAssert(FALSE);
  478. }
  479. }
  480. Adapter->IndicateRcvComplete = FALSE;
  481. } // ClReceiveComplete
  482. NDIS_STATUS
  483. MpTransferData(
  484. OUT PNDIS_PACKET Packet,
  485. OUT PUINT BytesTransferred,
  486. IN NDIS_HANDLE MiniportAdapterContext,
  487. IN NDIS_HANDLE MiniportReceiveContext,
  488. IN UINT ByteOffset,
  489. IN UINT BytesToTransfer
  490. )
  491. /*++
  492. Routine Description:
  493. Arguments:
  494. See the DDK...
  495. Return Values:
  496. None
  497. --*/
  498. {
  499. PADAPTER Adapter = (PADAPTER)MiniportAdapterContext;
  500. NDIS_STATUS Status;
  501. PsStructAssert(Adapter);
  502. PsDbgRecv(DBG_INFO, DBG_RECEIVE, MP_XFER_DATA, ENTER, Adapter, 0, 0);
  503. if(IsDeviceStateOn(Adapter) == FALSE)
  504. {
  505. return NDIS_STATUS_FAILURE;
  506. }
  507. NdisTransferData(
  508. &Status,
  509. Adapter->LowerMpHandle,
  510. MiniportReceiveContext,
  511. ByteOffset,
  512. BytesToTransfer,
  513. Packet,
  514. BytesTransferred);
  515. return Status;
  516. } // MpTransferData
  517. VOID
  518. ClTransferDataComplete(
  519. IN NDIS_HANDLE ProtocolBindingContext,
  520. IN PNDIS_PACKET Packet,
  521. IN NDIS_STATUS Status,
  522. IN UINT BytesTransferred
  523. )
  524. /*++
  525. Routine Description:
  526. Completion routine for NdisTransferData
  527. Arguments:
  528. See the DDK...
  529. Return Values:
  530. None
  531. --*/
  532. {
  533. PADAPTER Adapter = (PADAPTER)ProtocolBindingContext;
  534. PPS_RECV_PACKET_CONTEXT PktContext;
  535. PsStructAssert(Adapter);
  536. PsDbgRecv(DBG_INFO, DBG_RECEIVE, CL_XFER_COMPL, ENTER, Adapter, Packet, 0);
  537. if(Adapter->PsNdisHandle)
  538. {
  539. NdisMTransferDataComplete(
  540. Adapter->PsNdisHandle,
  541. Packet,
  542. Status,
  543. BytesTransferred);
  544. }
  545. } // ClTransferDataComplete
  546. UINT
  547. ClCoReceivePacket(
  548. IN NDIS_HANDLE ProtocolBindingContext,
  549. IN NDIS_HANDLE ProtocolVcContext,
  550. IN PNDIS_PACKET Packet
  551. )
  552. {
  553. //
  554. // We don't do anything special in the coreceive path. Just call ClReceivePacket.
  555. //
  556. return ClReceivePacket(ProtocolBindingContext, Packet);
  557. } // ClCoReceivePacket
  558. /* end recv.c */