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.

769 lines
21 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. NdisMoveMemory(pAddr,
  138. &WanLink->RecvHeader,
  139. FIELD_OFFSET(ETH_HEADER, Type));
  140. PS_UNLOCK(&Adapter->Lock);
  141. }
  142. NdisIMGetCurrentPacketStack(MpPacket, &Remaining);
  143. if(Remaining != 0)
  144. {
  145. Status = NDIS_GET_PACKET_STATUS(MpPacket);
  146. if (TimeStmpRecvPacket) {
  147. if (!(TimeStmpRecvPacket)(
  148. NULL,
  149. NULL,
  150. NULL,
  151. MpPacket,
  152. Adapter->MediaType
  153. )) {
  154. PsDbgRecv(DBG_FAILURE, DBG_RECEIVE, CL_RECV_PACKET, OURS, Adapter, MpPacket, 0);
  155. }
  156. }
  157. NdisMIndicateReceivePacket(Adapter->PsNdisHandle, &MpPacket, 1);
  158. return((Status != NDIS_STATUS_RESOURCES) ? 1 : 0);
  159. }
  160. else
  161. {
  162. PsAllocateRecvPacket(&Status, &OurPacket, Adapter);
  163. if(Status == NDIS_STATUS_SUCCESS)
  164. {
  165. PsDbgRecv(DBG_INFO, DBG_RECEIVE, CL_RECV_PACKET, ENTER, Adapter, OurPacket, MpPacket);
  166. //
  167. // Save Original Packet
  168. //
  169. ContextArea = PS_RECV_PACKET_CONTEXT_FROM_PACKET(OurPacket);
  170. ContextArea->OriginalPacket = MpPacket;
  171. OurPacket->Private.Head = MpPacket->Private.Head;
  172. OurPacket->Private.Tail = MpPacket->Private.Tail;
  173. //
  174. // Get the original packet (it could be the same packet as one received or a different one
  175. // based on # of layered MPs) and set it on the indicated packet so the OOB stuff is visible
  176. // correctly at the top.
  177. //
  178. NDIS_SET_ORIGINAL_PACKET(OurPacket, NDIS_GET_ORIGINAL_PACKET(MpPacket));
  179. NDIS_SET_PACKET_HEADER_SIZE(OurPacket, NDIS_GET_PACKET_HEADER_SIZE(MpPacket));
  180. //
  181. // Set Packet Flags
  182. //
  183. NdisGetPacketFlags(OurPacket) = NdisGetPacketFlags(MpPacket);
  184. Status = NDIS_GET_PACKET_STATUS(MpPacket);
  185. NDIS_SET_PACKET_STATUS(OurPacket, Status);
  186. if (TimeStmpRecvPacket) {
  187. if (!(TimeStmpRecvPacket)(
  188. NULL,
  189. NULL,
  190. NULL,
  191. OurPacket,
  192. Adapter->MediaType
  193. )) {
  194. PsDbgRecv(DBG_FAILURE, DBG_RECEIVE, CL_RECV_PACKET, OURS, Adapter, OurPacket, OurPacket);
  195. }
  196. }
  197. NdisMIndicateReceivePacket(Adapter->PsNdisHandle, &OurPacket, 1);
  198. if (Status == NDIS_STATUS_RESOURCES)
  199. {
  200. NdisDprFreePacket(OurPacket);
  201. }
  202. return((Status != NDIS_STATUS_RESOURCES) ? 1 : 0);
  203. }
  204. else
  205. {
  206. //
  207. // out of resources. indicate that we're not hanging onto the packet
  208. //
  209. PsDbgRecv(DBG_FAILURE, DBG_RECEIVE, CL_RECV_PACKET, NO_RESOURCES,
  210. Adapter, 0, MpPacket);
  211. Adapter->Stats.OutOfPackets ++;
  212. return 0;
  213. }
  214. }
  215. } // ClReceivePacket
  216. VOID
  217. MpReturnPacket(
  218. IN NDIS_HANDLE MiniportAdapterContext,
  219. IN PNDIS_PACKET Packet
  220. )
  221. /*++
  222. Routine Description:
  223. Potentially return a packet we indicated previously to the
  224. underlying miniport. It might be one of ours from a ProtocolReceive
  225. indication, so we disassemble it and return the packet and its
  226. buffers to their respective S Lists
  227. Arguments:
  228. See the DDK...
  229. Return Values:
  230. None
  231. --*/
  232. {
  233. PADAPTER Adapter = (PADAPTER)MiniportAdapterContext;
  234. PPS_RECV_PACKET_CONTEXT PktContext;
  235. PNDIS_PACKET MyPacket;
  236. BOOLEAN Remaining;
  237. PsStructAssert(Adapter);
  238. NdisIMGetCurrentPacketStack(Packet, &Remaining);
  239. if(Remaining != 0)
  240. {
  241. NdisReturnPackets(&Packet, 1);
  242. }
  243. else
  244. {
  245. //
  246. // see if the OriginalPacket field indicates that this belongs
  247. // to someone below us and return it now
  248. //
  249. PktContext = PS_RECV_PACKET_CONTEXT_FROM_PACKET(Packet);
  250. MyPacket = PktContext->OriginalPacket;
  251. PsDbgRecv(DBG_INFO, DBG_RECEIVE, MP_RETURN_PACKET, RETURNING, Adapter, Packet, MyPacket);
  252. NdisDprFreePacket(Packet);
  253. NdisReturnPackets(&MyPacket, 1);
  254. }
  255. } // MpReturnPacket
  256. NDIS_STATUS
  257. ClReceiveIndication(
  258. IN NDIS_HANDLE ProtocolBindingContext,
  259. IN NDIS_HANDLE MacReceiveContext,
  260. IN PVOID HeaderBuffer,
  261. IN UINT HeaderBufferSize,
  262. IN PVOID LookAheadBuffer,
  263. IN UINT LookAheadBufferSize,
  264. IN UINT PacketSize
  265. )
  266. /*++
  267. Routine Description:
  268. Called by NIC to notify protocol of incoming data. Copy the data
  269. into a cached packet we set up during initialization and indicate
  270. that packet to the higher layer.
  271. Arguments:
  272. See the DDK...
  273. Return Values:
  274. None
  275. --*/
  276. {
  277. PADAPTER Adapter = (PADAPTER)ProtocolBindingContext;
  278. PNDIS_PACKET MyPacket, Packet;
  279. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  280. PsStructAssert(Adapter);
  281. if(!Adapter->PsNdisHandle)
  282. {
  283. Status = NDIS_STATUS_FAILURE;
  284. }
  285. else
  286. {
  287. do
  288. {
  289. //
  290. // If this was indicated by the miniport below as a packet, then get that packet
  291. // pointer and indicate it as a packet as well (with appropriate status).
  292. // This way the OOB stuff is accessible to the transport above us.
  293. //
  294. Packet = NdisGetReceivedPacket(Adapter->LowerMpHandle, MacReceiveContext);
  295. if (Packet != NULL)
  296. {
  297. BOOLEAN Remaining;
  298. //
  299. // Check if there are any more packet stacks left. If there is need to keep per packet information,
  300. // then the packet stack (which is returned by the api) can be used to store that
  301. //
  302. NdisIMGetCurrentPacketStack(Packet, &Remaining);
  303. if (Remaining != 0)
  304. {
  305. NDIS_STATUS OldPacketStatus;
  306. if (TimeStmpRecvPacket) {
  307. if (!(TimeStmpRecvPacket)(
  308. NULL,
  309. NULL,
  310. NULL,
  311. Packet,
  312. Adapter->MediaType
  313. )) {
  314. PsDbgRecv(DBG_FAILURE, DBG_RECEIVE, CL_RECV_IND, OURS, Adapter, Packet, Packet);
  315. }
  316. }
  317. //
  318. // Save the old status, and set packet status to NDIS_STATUS_RESOURCES
  319. // because we can't have the protocol above us retain the packet -- it
  320. // can go away as soon as we return from this function.
  321. //
  322. OldPacketStatus = NDIS_GET_PACKET_STATUS(Packet);
  323. NDIS_SET_PACKET_STATUS(Packet, NDIS_STATUS_RESOURCES);
  324. NdisMIndicateReceivePacket(Adapter->PsNdisHandle, &Packet, 1);
  325. //
  326. // Restore the old Status
  327. //
  328. NDIS_SET_PACKET_STATUS(Packet, OldPacketStatus);
  329. // Since we had set the packet status to NDIS_STATUS_RESOURCES, our
  330. // ReturnPacket handler won't be called for this packet.
  331. break;
  332. }
  333. //
  334. // Get a packet off the pool and indicate that up
  335. //
  336. PsAllocateRecvPacket(&Status,
  337. &MyPacket,
  338. Adapter);
  339. if (Status == NDIS_STATUS_SUCCESS)
  340. {
  341. MyPacket->Private.Head = Packet->Private.Head;
  342. MyPacket->Private.Tail = Packet->Private.Tail;
  343. //
  344. // Get the original packet (it could be the same packet as one received or
  345. // a different one based on # of layered MPs) and set it on the indicated
  346. // packet so the OOB stuff is visible correctly at the top.
  347. //
  348. NDIS_SET_ORIGINAL_PACKET(MyPacket, NDIS_GET_ORIGINAL_PACKET(Packet));
  349. NDIS_SET_PACKET_HEADER_SIZE(MyPacket, HeaderBufferSize);
  350. //
  351. // Set Packet Flags
  352. //
  353. NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet);
  354. //
  355. // Make sure the status is set to NDIS_STATUS_RESOURCES.
  356. //
  357. NDIS_SET_PACKET_STATUS(MyPacket, NDIS_STATUS_RESOURCES);
  358. if (TimeStmpRecvPacket) {
  359. if (!(TimeStmpRecvPacket)(
  360. NULL,
  361. NULL,
  362. NULL,
  363. MyPacket,
  364. Adapter->MediaType
  365. )) {
  366. PsDbgRecv(DBG_FAILURE, DBG_RECEIVE, CL_RECV_IND, OURS, Adapter, MyPacket, MyPacket);
  367. }
  368. }
  369. NdisMIndicateReceivePacket(Adapter->PsNdisHandle, &MyPacket, 1);
  370. PsAssert (NDIS_GET_PACKET_STATUS(MyPacket) == NDIS_STATUS_RESOURCES);
  371. NdisDprFreePacket(MyPacket);
  372. break;
  373. }
  374. }
  375. //
  376. // Fall through if the miniport below us has either not indicated a packet or we
  377. // could not allocate one
  378. //
  379. Adapter->IndicateRcvComplete = TRUE;
  380. //
  381. // If the timestamp driver is present.
  382. //
  383. //
  384. if (TimeStmpRecvIndication) {
  385. if (!(TimeStmpRecvIndication)(
  386. NULL,
  387. NULL,
  388. NULL,
  389. HeaderBuffer,
  390. HeaderBufferSize,
  391. LookAheadBuffer,
  392. LookAheadBufferSize,
  393. PacketSize,
  394. Adapter->IPHeaderOffset
  395. )) {
  396. PsDbgRecv(DBG_FAILURE, DBG_RECEIVE, CL_RECV_IND, OURS, Adapter, (PNDIS_PACKET) LookAheadBuffer, NULL);
  397. }
  398. }
  399. switch (Adapter->MediaType)
  400. {
  401. case NdisMedium802_3:
  402. case NdisMediumWan:
  403. NdisMEthIndicateReceive(Adapter->PsNdisHandle,
  404. MacReceiveContext,
  405. HeaderBuffer,
  406. HeaderBufferSize,
  407. LookAheadBuffer,
  408. LookAheadBufferSize,
  409. PacketSize);
  410. break;
  411. case NdisMedium802_5:
  412. NdisMTrIndicateReceive(Adapter->PsNdisHandle,
  413. MacReceiveContext,
  414. HeaderBuffer,
  415. HeaderBufferSize,
  416. LookAheadBuffer,
  417. LookAheadBufferSize,
  418. PacketSize);
  419. break;
  420. case NdisMediumFddi:
  421. NdisMFddiIndicateReceive(Adapter->PsNdisHandle,
  422. MacReceiveContext,
  423. HeaderBuffer,
  424. HeaderBufferSize,
  425. LookAheadBuffer,
  426. LookAheadBufferSize,
  427. PacketSize);
  428. break;
  429. default:
  430. PsAssert (0);
  431. Status = NDIS_STATUS_FAILURE;
  432. break;
  433. }
  434. } while (FALSE);
  435. }
  436. return Status;
  437. } // ClReceiveIndication
  438. VOID
  439. ClReceiveComplete(
  440. IN NDIS_HANDLE ProtocolBindingContext
  441. )
  442. /*++
  443. Routine Description:
  444. Called by NIC via NdisIndicateReceiveComplete. Continue this indication
  445. up to the higher layer
  446. Arguments:
  447. See the DDK...
  448. Return Values:
  449. None
  450. --*/
  451. {
  452. PADAPTER Adapter = (PADAPTER)ProtocolBindingContext;
  453. PsStructAssert(Adapter);
  454. PsDbgRecv(DBG_INFO, DBG_RECEIVE, CL_RECV_COMPL, ENTER, Adapter, 0, 0);
  455. if((Adapter->PsNdisHandle != NULL) && Adapter->IndicateRcvComplete) {
  456. switch(Adapter->MediaType){
  457. case NdisMediumWan:
  458. case NdisMedium802_3:
  459. NdisMEthIndicateReceiveComplete(Adapter->PsNdisHandle);
  460. break;
  461. case NdisMedium802_5:
  462. NdisMTrIndicateReceiveComplete(Adapter->PsNdisHandle);
  463. break;
  464. case NdisMediumFddi:
  465. NdisMFddiIndicateReceiveComplete(Adapter->PsNdisHandle);
  466. break;
  467. default:
  468. PsAssert(FALSE);
  469. }
  470. }
  471. Adapter->IndicateRcvComplete = FALSE;
  472. } // ClReceiveComplete
  473. NDIS_STATUS
  474. MpTransferData(
  475. OUT PNDIS_PACKET Packet,
  476. OUT PUINT BytesTransferred,
  477. IN NDIS_HANDLE MiniportAdapterContext,
  478. IN NDIS_HANDLE MiniportReceiveContext,
  479. IN UINT ByteOffset,
  480. IN UINT BytesToTransfer
  481. )
  482. /*++
  483. Routine Description:
  484. Arguments:
  485. See the DDK...
  486. Return Values:
  487. None
  488. --*/
  489. {
  490. PADAPTER Adapter = (PADAPTER)MiniportAdapterContext;
  491. NDIS_STATUS Status;
  492. PsStructAssert(Adapter);
  493. PsDbgRecv(DBG_INFO, DBG_RECEIVE, MP_XFER_DATA, ENTER, Adapter, 0, 0);
  494. if(IsDeviceStateOn(Adapter) == FALSE)
  495. {
  496. return NDIS_STATUS_FAILURE;
  497. }
  498. NdisTransferData(
  499. &Status,
  500. Adapter->LowerMpHandle,
  501. MiniportReceiveContext,
  502. ByteOffset,
  503. BytesToTransfer,
  504. Packet,
  505. BytesTransferred);
  506. return Status;
  507. } // MpTransferData
  508. VOID
  509. ClTransferDataComplete(
  510. IN NDIS_HANDLE ProtocolBindingContext,
  511. IN PNDIS_PACKET Packet,
  512. IN NDIS_STATUS Status,
  513. IN UINT BytesTransferred
  514. )
  515. /*++
  516. Routine Description:
  517. Completion routine for NdisTransferData
  518. Arguments:
  519. See the DDK...
  520. Return Values:
  521. None
  522. --*/
  523. {
  524. PADAPTER Adapter = (PADAPTER)ProtocolBindingContext;
  525. PPS_RECV_PACKET_CONTEXT PktContext;
  526. PsStructAssert(Adapter);
  527. PsDbgRecv(DBG_INFO, DBG_RECEIVE, CL_XFER_COMPL, ENTER, Adapter, Packet, 0);
  528. if(Adapter->PsNdisHandle)
  529. {
  530. NdisMTransferDataComplete(
  531. Adapter->PsNdisHandle,
  532. Packet,
  533. Status,
  534. BytesTransferred);
  535. }
  536. } // ClTransferDataComplete
  537. UINT
  538. ClCoReceivePacket(
  539. IN NDIS_HANDLE ProtocolBindingContext,
  540. IN NDIS_HANDLE ProtocolVcContext,
  541. IN PNDIS_PACKET Packet
  542. )
  543. {
  544. //
  545. // We don't do anything special in the coreceive path. Just call ClReceivePacket.
  546. //
  547. return ClReceivePacket(ProtocolBindingContext, Packet);
  548. } // ClCoReceivePacket
  549. /* end recv.c */