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.

1414 lines
37 KiB

  1. // Copyright (c) 1998-1999, Microsoft Corporation, all rights reserved
  2. //
  3. // send.c
  4. //
  5. // IEEE1394 mini-port/call-manager driver
  6. //
  7. // Mini-port Send routines
  8. //
  9. // 05/15/1999 ADube Created,
  10. //
  11. #include <precomp.h>
  12. //-----------------------------------------------------------------------------
  13. // Local prototypes (alphabetically)
  14. //-----------------------------------------------------------------------------
  15. extern ULONG NdisBufferAllocated[NoMoreCodePaths];
  16. extern ULONG NdisBufferFreed[NoMoreCodePaths];
  17. NDIS_STATUS
  18. nicGetIsochDescriptors(
  19. IN UINT Num,
  20. OUT PPISOCH_DESCRIPTOR ppIsochDescriptor
  21. );
  22. NDIS_STATUS
  23. nicInitializeIsochDescriptor (
  24. IN PCHANNEL_VCCB pChannelVc,
  25. IN PMDL pMdl,
  26. IN PISOCH_DESCRIPTOR pIsochDesriptor
  27. );
  28. VOID
  29. nicIsochRxCallback (
  30. IN PVOID Context1,
  31. IN PVOID Context2
  32. );
  33. ULONG ReassemblyCompleted = 0;
  34. //-----------------------------------------------------------------------------
  35. // prototypes implementations (alphabetically)
  36. //-----------------------------------------------------------------------------
  37. NDIS_STATUS
  38. nicAllocateAndInitializeIsochDescriptors (
  39. IN PCHANNEL_VCCB pChannelVc,
  40. IN UINT NumDescriptors,
  41. IN UINT BufferLength,
  42. IN OUT PPISOCH_DESCRIPTOR ppIsochDescriptor
  43. )
  44. // Function Description:
  45. // This function allocate and initializes a
  46. // a numer of isoch descriptors all allocated
  47. // together.
  48. // This should allocate isoch desc,
  49. // get local memory, get mdls
  50. // initialize mdl, isoch _desc and then return
  51. //
  52. //
  53. // Arguments
  54. // ChannelVc- this contains all the other argumernts, size
  55. // num of descriptors,etc
  56. // ppIsochDescriptor- will contain the pointer to the allocated
  57. // array of IsochDescriptor
  58. //
  59. //
  60. // Return Value:
  61. // Success if all the memory allocations succeeded
  62. //
  63. //
  64. //
  65. {
  66. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  67. UINT Size;
  68. UINT index =0;
  69. PMDL pMdl = NULL;
  70. PVOID pLocalBuffer = NULL;
  71. TRACE( TL_T, TM_Recv, ( "==>nicAllocateAndInitializeIsochDescriptors Vc %.8x, Num %.8x",
  72. pChannelVc, NumDescriptors) );
  73. TRACE( TL_V, TM_Recv, ( "Max BuffferSize %.8x", pChannelVc, BufferLength) );
  74. do
  75. {
  76. NdisStatus = nicGetIsochDescriptors (NumDescriptors, ppIsochDescriptor);
  77. if (NdisStatus != NDIS_STATUS_SUCCESS)
  78. {
  79. BREAK ( TM_Recv, "nicGetIsochDescriptors FAILED" );
  80. }
  81. ASSERT (*ppIsochDescriptor != NULL);
  82. while (index < NumDescriptors)
  83. {
  84. //
  85. // Get a local that point to the isoch descriptor that needs to be initialized
  86. //
  87. PISOCH_DESCRIPTOR pIsochDescriptor = NULL;
  88. pIsochDescriptor = (PISOCH_DESCRIPTOR)((ULONG_PTR)(*ppIsochDescriptor)+ index*sizeof(ISOCH_DESCRIPTOR));
  89. //
  90. // Get Locally owned memory for the data
  91. //
  92. NdisStatus = nicGetLocalBuffer (BufferLength, &pLocalBuffer);
  93. if (NdisStatus != NDIS_STATUS_SUCCESS)
  94. {
  95. BREAK ( TM_Recv, ( "nicGetLocalBuffer FAILED " ) );
  96. }
  97. //
  98. // Get an MDL and initialze the MDL with the buffer
  99. //
  100. NdisStatus = nicGetMdl ( BufferLength,
  101. pLocalBuffer,
  102. &pMdl);
  103. if (NdisStatus != NDIS_STATUS_SUCCESS)
  104. {
  105. nicFreeLocalBuffer(BufferLength, pLocalBuffer);
  106. pLocalBuffer = NULL;
  107. BREAK ( TM_Recv, ( "nicGetMdl FAILED " ) );
  108. }
  109. //
  110. // this reference will be removed when the MDL will be freed
  111. // in FreeSingleIsochDescriptor
  112. //
  113. nicReferenceCall ((PVCCB)pChannelVc, "nicAllocateAndInitializeIsochDescriptors " );
  114. NdisStatus = nicInitializeIsochDescriptor (pChannelVc,
  115. pMdl,
  116. pIsochDescriptor);
  117. if (NdisStatus != NDIS_STATUS_SUCCESS)
  118. {
  119. BREAK ( TM_Recv, ( "nicInitializeIsochDescriptor FAILED " ) );
  120. }
  121. index++;
  122. }
  123. } while (FALSE);
  124. TRACE( TL_T, TM_Recv, ( "==>nicAllocateAndInitializeIsochDescriptors Status %.8x", NdisStatus) );
  125. return NdisStatus;
  126. }
  127. NDIS_STATUS
  128. nicFreeIsochDescriptors(
  129. IN UINT Num,
  130. IN PISOCH_DESCRIPTOR pIsochDescriptor,
  131. IN PVCCB pVc
  132. )
  133. // Function Description:
  134. // Free Num number of IsochDescriptors
  135. //
  136. // Arguments
  137. // Num number of descriptors
  138. // Start of the allocated memory
  139. //
  140. //
  141. // Return Value:
  142. // Success if all the memory allocations succeeded
  143. //
  144. {
  145. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  146. PISOCH_DESCRIPTOR pCurrDesc = pIsochDescriptor;
  147. UINT i=0;
  148. TRACE( TL_T, TM_Recv, ( "==>nicFreeIsochDescriptors Num %.8x, pIsochDescriptor %x", Num, pIsochDescriptor ) );
  149. do
  150. {
  151. if (pIsochDescriptor == NULL)
  152. {
  153. break;
  154. }
  155. pCurrDesc = pIsochDescriptor;
  156. while (i < Num)
  157. {
  158. nicFreeSingleIsochDescriptor( pCurrDesc, pVc);
  159. pCurrDesc = (PISOCH_DESCRIPTOR)((PUCHAR)pCurrDesc + sizeof(ISOCH_DESCRIPTOR));
  160. i++;
  161. }
  162. FREE_NONPAGED (pIsochDescriptor);
  163. } while (FALSE);
  164. NdisStatus = NDIS_STATUS_SUCCESS;
  165. TRACE( TL_T, TM_Recv, ( "<==nicGetIsochDescriptors Status %.8x", NdisStatus ) );
  166. return NdisStatus;
  167. }
  168. NDIS_STATUS
  169. nicFreeSingleIsochDescriptor(
  170. IN PISOCH_DESCRIPTOR pIsochDescriptor,
  171. IN PVCCB pVc
  172. )
  173. // Function Description:
  174. // Free IsochDescriptor and its MDL
  175. //
  176. // Arguments
  177. // Start of the isochDesc
  178. //
  179. //
  180. // Return Value:
  181. // Success if all the memory allocations succeeded
  182. //
  183. {
  184. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  185. PCHANNEL_VCCB pChannelVc = pIsochDescriptor->Context1;
  186. ASSERT (pVc == (PVCCB)pChannelVc);
  187. TRACE( TL_T, TM_Recv, ( "==>nicFreeSingleIsochDescriptor pIsochDescriptor %x", pIsochDescriptor ) );
  188. //
  189. // Lets make sure we have a VC and Channel VC
  190. //
  191. ASSERT (pChannelVc->Hdr.ulTag == MTAG_VCCB );
  192. //
  193. // Just to protect ourselves against a bad isoch descriptor
  194. //
  195. if (pIsochDescriptor->Mdl != NULL)
  196. {
  197. PVOID pVa = MmGetMdlVirtualAddress(pIsochDescriptor->Mdl);
  198. ULONG Length = MmGetMdlByteCount(pIsochDescriptor->Mdl);
  199. nicDereferenceCall ((PVCCB)pChannelVc, "nicFreeSingleIsochDescriptors ");
  200. nicFreeMdl (pIsochDescriptor->Mdl);
  201. nicFreeLocalBuffer(Length, pVa);
  202. }
  203. else
  204. {
  205. ASSERT (pIsochDescriptor->Mdl != NULL);
  206. }
  207. NdisStatus = NDIS_STATUS_SUCCESS;
  208. TRACE( TL_T, TM_Recv, ( "<==nicFreeSingleIsochDescriptors Status %.8x", NdisStatus ) );
  209. return NdisStatus;
  210. }
  211. NDIS_STATUS
  212. nicGetIsochDescriptors(
  213. IN UINT Num,
  214. OUT PPISOCH_DESCRIPTOR ppIsochDescriptor
  215. )
  216. // Function Description:
  217. // The function returns a block of contigious memory of size
  218. // Num * sizeof (ISOCH_DESCRIPTOR)
  219. //
  220. //
  221. // Arguments
  222. // Num number of descriptors
  223. // Start of the allocated memory
  224. //
  225. //
  226. // Return Value:
  227. // Success if all the memory allocations succeeded
  228. //
  229. {
  230. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  231. PVOID pMemory = NULL;
  232. TRACE( TL_T, TM_Recv, ( "==>nicGetIsochDescriptors Num %.8x", Num) );
  233. pMemory = ALLOC_NONPAGED (Num*sizeof(ISOCH_DESCRIPTOR), MTAG_CBUF );
  234. if (pMemory != NULL)
  235. {
  236. NdisStatus = NDIS_STATUS_SUCCESS;
  237. *ppIsochDescriptor = (PISOCH_DESCRIPTOR)pMemory;
  238. }
  239. else
  240. {
  241. *ppIsochDescriptor = NULL;
  242. TRACE( TL_A, TM_Recv, ( "<==nicGetIsochDescriptors About to Fail") );
  243. ASSERT (*ppIsochDescriptor != NULL);
  244. }
  245. TRACE( TL_T, TM_Recv, ( "<==nicGetIsochDescriptors Status %.8x, StartAddress %.8x", NdisStatus , *ppIsochDescriptor) );
  246. return NdisStatus;
  247. }
  248. NDIS_STATUS
  249. nicInitializeIsochDescriptor (
  250. IN PCHANNEL_VCCB pChannelVc,
  251. IN PMDL pMdl,
  252. IN OUT PISOCH_DESCRIPTOR pIsochDescriptor
  253. )
  254. // Function Description:
  255. // Initializes the Isoch_desciptor using the fields in
  256. // the Channel Vc Block and the Mdl
  257. //
  258. // Arguments
  259. // ChannelVc- Pointer to the Channel Vc which will own
  260. // Descriptor, also contains information
  261. // pMdl- The IsochDescriptor will get a pointer to this Mdl
  262. // pIsochDescriptor - is the descriptor whose fields will get
  263. // initialized
  264. //
  265. // Return Value:
  266. // Success if all the memory allocations succeeded
  267. //
  268. {
  269. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  270. TRACE( TL_T, TM_Recv, ( "==>nicInitializeIsochDescriptor Vc %.8x, Mdl ", pChannelVc, pMdl) );
  271. pIsochDescriptor->fulFlags = DESCRIPTOR_SYNCH_ON_TAG;
  272. //
  273. // Mdl pointing to buffer
  274. //
  275. pIsochDescriptor->Mdl = pMdl;
  276. //
  277. // Length of combined buffer(s) as represented by the Mdl
  278. //
  279. pIsochDescriptor->ulLength = MmGetMdlByteCount(pMdl);
  280. //
  281. // Payload size of each Isoch packet to be used in this descriptor
  282. //
  283. pIsochDescriptor->nMaxBytesPerFrame = MmGetMdlByteCount(pMdl);
  284. //
  285. // Synchronization field; equivalent to Sy in the Isoch packet
  286. //
  287. pIsochDescriptor->ulSynch= 0;
  288. //
  289. // Synchronization field; equivalent to Tag in the Isoch packet.
  290. //
  291. pIsochDescriptor->ulTag = g_IsochTag;
  292. //
  293. // Cycle time field; returns time to be sent/received or when finished
  294. //
  295. // (ULONG)pIsochDescriptor->CycleTime=0;
  296. //
  297. // Callback routine (if any) to be called when this descriptor completes
  298. //
  299. pIsochDescriptor->Callback = nicIsochRxCallback;
  300. //
  301. // First context (if any) parameter to be passed when doing callbacks
  302. //
  303. pIsochDescriptor->Context1 = pChannelVc;
  304. //
  305. // Second context (if any) parameter to be passed when doing callbacks
  306. //
  307. pIsochDescriptor->Context2 = pIsochDescriptor;
  308. //
  309. // Holds the final status of this descriptor. Assign a bogus value
  310. //
  311. pIsochDescriptor->status = STATUS_INFO_LENGTH_MISMATCH;
  312. NdisStatus = NDIS_STATUS_SUCCESS;
  313. TRACE( TL_T, TM_Recv, ( "<==nicInitializeIsochDescriptors Status %.8x, IsochDesc %.8x", NdisStatus, pIsochDescriptor) );
  314. return NdisStatus;
  315. }
  316. VOID
  317. nicIsochRxCallback (
  318. PVOID Context1,
  319. PVOID Context2
  320. )
  321. /*++
  322. Routine Description:
  323. This is the callback routine passed to bus driver
  324. This function does some channel specific work and calls the common callback routine
  325. Arguments:
  326. Context1 - pChannel Vc
  327. Context2 - pIsochDescriptor2
  328. Return Value:
  329. --*/
  330. {
  331. PISOCH_DESCRIPTOR pIsochDescriptor = (PISOCH_DESCRIPTOR)Context2;
  332. PVCCB pVc = (PVCCB) Context1;
  333. MARK_ISOCH_DESCRIPTOR_INDICATED (pIsochDescriptor);
  334. STORE_CHANNELVC_IN_DESCRIPTOR (pIsochDescriptor, pVc );
  335. NdisInterlockedIncrement (&((PCHANNEL_VCCB)pVc)->NumIndicatedIsochDesc);
  336. CLEAR_DESCRIPTOR_NEXT (pIsochDescriptor);
  337. pIsochDescriptor->Mdl->Next = NULL;
  338. nicReceiveCommonCallback (pIsochDescriptor ,
  339. pVc,
  340. IsochReceive,
  341. pIsochDescriptor->Mdl);
  342. }
  343. VOID
  344. nicReceiveCommonCallback (
  345. IN PVOID pIndicatedStruct,
  346. IN PVCCB pVc,
  347. BUS_OPERATION RecvOp,
  348. PMDL pMdl
  349. )
  350. /*++
  351. Routine Description:
  352. This function is the common receive code for Isoch and Fifo Recv
  353. It allocate an NdisBuffer that points to the Ip1394 data
  354. If packet is complete (i.e reassembly is complete) , then it allocates an ndis packet
  355. and indicates it up to Ndis
  356. Arguments:
  357. pIndicatedStruct - Isoch Desc. or Address fifo,
  358. pVc - VC on which data was indicated,
  359. RecvOp - Isoch or Fifo,
  360. pMdl - Mdl associated with the Isoch Desc or Fifo.
  361. Passed in seperately for ease of use (debugging)
  362. Return Value:
  363. None
  364. --*/
  365. {
  366. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  367. PNDIS1394_REASSEMBLY_STRUCTURE pReassembly = NULL;
  368. NIC_RECV_DATA_INFO RcvInfo;
  369. ULONG DataLength = 0;
  370. BOOLEAN fVcActive = FALSE;
  371. ULONG ulValidDataLength = 0;
  372. PVOID pStartValidData = NULL;
  373. PNDIS_BUFFER pHeadNdisBuffer = NULL;
  374. PADAPTERCB pAdapter = NULL;
  375. BOOLEAN fPacketCompleted = FALSE;
  376. PNDIS_PACKET pMyPacket = NULL;
  377. ULONG PacketLength = 0;
  378. PPKT_CONTEXT pPktContext = NULL;
  379. NDIS_STATUS IndicatedStatus = NDIS_STATUS_FAILURE;
  380. PVOID pIndicatedChain = NULL;
  381. STORE_CURRENT_IRQL;
  382. ASSERT (RecvOp == IsochReceive || RecvOp == AddressRange);
  383. TRACE( TL_T, TM_Recv, ( "==>nicReceiveCommonCallback pVc %x, IndicatedStruc %x, Mdl %x",
  384. pVc, pIndicatedStruct , pMdl ) );
  385. do
  386. {
  387. if (pVc->Hdr.ulTag != MTAG_VCCB)
  388. {
  389. ASSERT (pVc->Hdr.ulTag == MTAG_VCCB);
  390. NdisStatus = NDIS_STATUS_VC_NOT_ACTIVATED;
  391. break;
  392. }
  393. //
  394. // First, we need to check if we still have an active make call. VC will be present will bus driver
  395. // has buffers
  396. //
  397. fVcActive = VC_ACTIVE (pVc) ;
  398. if (fVcActive == TRUE)
  399. {
  400. pAdapter = pVc->Hdr.pAF->pAdapter;
  401. }
  402. if (fVcActive == FALSE )
  403. {
  404. TRACE( TL_N, TM_Recv, ( "We do not have a valid VC Block %x ",pVc) );
  405. NdisStatus = NDIS_STATUS_VC_NOT_ACTIVATED;
  406. break;
  407. }
  408. NdisStatus = nicValidateRecvData ( pMdl,
  409. RecvOp,
  410. pIndicatedStruct,
  411. pVc ,
  412. &RcvInfo);
  413. if (NdisStatus != NDIS_STATUS_SUCCESS)
  414. {
  415. TRACE (TL_A, TM_Recv, ("Invalid Data Received pMdl %x, RecvOp %x, pVc %x",
  416. pMdl, RecvOp, pVc) );
  417. break;
  418. }
  419. nicDumpMdl (pMdl, RcvInfo.Length1394, "Received Mdl\n");
  420. #ifdef PKT_LOG
  421. {
  422. if (RecvOp == IsochReceive)
  423. {
  424. PPACKET_FORMAT pPacketFormat = (PPACKET_FORMAT)RcvInfo.p1394Data;
  425. GASP_HEADER GaspHeader = pPacketFormat->IsochReceiveNonFragmented.GaspHeader;
  426. GaspHeader.FirstQuadlet.GaspHeaderHigh = SWAPBYTES_ULONG (GaspHeader.FirstQuadlet.GaspHeaderHigh);
  427. NIC1394_LOG_PKT(
  428. pVc->Hdr.pAF->pAdapter,
  429. NIC1394_LOGFLAGS_RECV_CHANNEL,
  430. GaspHeader.FirstQuadlet.u.GH_Source_ID, // SourceID
  431. ((PCHANNEL_VCCB)pVc)->Channel, // DestID
  432. RcvInfo.p1394Data,
  433. RcvInfo.DataLength );
  434. }
  435. else
  436. {
  437. PNOTIFICATION_INFO pNotificationInfo = (PNOTIFICATION_INFO)pIndicatedStruct;
  438. ULONG NodeNumber = ((PASYNC_PACKET)pNotificationInfo->RequestPacket)->AP_Source_ID.NA_Node_Number;
  439. NIC1394_LOG_PKT(
  440. pVc->Hdr.pAF->pAdapter,
  441. NIC1394_LOGFLAGS_RECV_FIFO ,
  442. NodeNumber , // SourceID
  443. pAdapter->BCRData.LocalNodeNumber,
  444. RcvInfo.p1394Data,
  445. RcvInfo.DataLength );
  446. }
  447. }
  448. #endif
  449. //
  450. // Sanity check
  451. //
  452. if (RcvInfo.fFragmented == FALSE)
  453. {
  454. //
  455. // Pack the mdl into an ndispacket and indicate it to Ndis.
  456. // SHOULD BE NDIS_BUFFERS
  457. //
  458. ulValidDataLength = RcvInfo.DataLength;
  459. pStartValidData = (PVOID)RcvInfo.pEncapHeader;
  460. NdisStatus = nicGetNdisBuffer ( ulValidDataLength,
  461. pStartValidData,
  462. &pHeadNdisBuffer);
  463. if (NdisStatus != NDIS_STATUS_SUCCESS)
  464. {
  465. pHeadNdisBuffer = NULL;
  466. break;
  467. }
  468. nicIncRecvBuffer(pVc->Hdr.VcType == NIC1394_RecvFIFO);
  469. pIndicatedChain = RcvInfo.NdisPktContext.pCommon;
  470. fPacketCompleted = TRUE;
  471. }
  472. else // Recv Data is fragemented
  473. {
  474. PREMOTE_NODE pRemoteNode= NULL;
  475. USHORT SourceNodeAddress = 0xff;
  476. //
  477. // First extract all the useful information from the indicated structure, rem node, dgl, first frag, etc
  478. //
  479. nicInitRecvDataFragmented (pMdl, RecvOp, pIndicatedStruct, &RcvInfo);
  480. RcvInfo.pRemoteNode = nicGetRemoteNodeFromTable (RcvInfo.SourceID,pAdapter);
  481. TRACE( TL_T, TM_Recv, ( " pRemoteNode %x", RcvInfo.pRemoteNode) );
  482. //
  483. // If there is no remote node present , break out
  484. //
  485. if (RcvInfo.pRemoteNode == NULL)
  486. {
  487. NdisStatus = NDIS_STATUS_FAILURE;
  488. nicRecvNoRemoteNode (pAdapter);
  489. BREAK (TM_Recv, (" Rx - Did not find a remote Node for reassembly" ) );
  490. }
  491. //
  492. // Try and use the indicated data to reassemble
  493. //
  494. NdisStatus = nicDoReassembly (&RcvInfo, &pReassembly, &fPacketCompleted );
  495. if (NdisStatus != NDIS_STATUS_SUCCESS)
  496. {
  497. TRACE (TL_N, TM_Recv, ("Generic RX - Reassembly Failed") );
  498. break;
  499. }
  500. ASSERT (pReassembly != NULL);
  501. if (fPacketCompleted == TRUE &&
  502. REASSEMBLY_ACTIVE (pReassembly))
  503. {
  504. TRACE( TL_V, TM_Recv, ( " pReassembly->ReassemblyComplete %x ", pReassembly->fReassemblyComplete ) );
  505. pHeadNdisBuffer = pReassembly->pHeadNdisBuffer;
  506. pIndicatedChain = pReassembly->Head.pCommon;
  507. nicReassemblyCompleted(pAdapter);
  508. }
  509. else
  510. {
  511. //
  512. // Do not call the return packet as reassembly is in progress. Dereference the ref made
  513. // when the reaassembly was found in nicFindReassembly...
  514. //
  515. ASSERT (pHeadNdisBuffer == NULL);
  516. NdisStatus = NDIS_STATUS_SUCCESS;
  517. }
  518. ASSERT (NdisStatus == NDIS_STATUS_SUCCESS);
  519. //
  520. // Dereference the ref that was made nicFindReassembly. After this only one thread
  521. // should have the reassembly struct. And there should be one ref on it.
  522. //
  523. nicDereferenceReassembly (pReassembly, "nicIsochRxCallback Reassembly Incomplete");
  524. } // Completed the ifFragmented code
  525. if (RcvInfo.pRemoteNode != NULL)
  526. {
  527. //
  528. // Deref the ref made earlier in the if fragmented code path within this function
  529. //
  530. nicDereferenceRemoteNode(RcvInfo.pRemoteNode , GetRemoteNodeFromTable );
  531. RcvInfo.pRemoteNode = NULL;
  532. }
  533. if (fPacketCompleted == FALSE)
  534. {
  535. //
  536. // If the packet is not completely reassembled, then there is no
  537. // more work to be done
  538. //
  539. pReassembly = NULL;
  540. NdisStatus = NDIS_STATUS_SUCCESS;
  541. break;
  542. }
  543. //
  544. // Now we package the data into an NdisPacket
  545. //
  546. nicAllocatePacket (&NdisStatus,
  547. &pMyPacket,
  548. RcvInfo.pPacketPool);
  549. if (NdisStatus != NDIS_STATUS_SUCCESS)
  550. {
  551. pMyPacket = NULL;
  552. ASSERT(NdisStatus == NDIS_STATUS_SUCCESS);
  553. break;
  554. }
  555. //
  556. // Set the NdisBuffer as Head and Tail of the Packet
  557. //
  558. NdisChainBufferAtFront (pMyPacket, pHeadNdisBuffer);
  559. NdisQueryPacket( pMyPacket,
  560. NULL,
  561. NULL,
  562. NULL,
  563. &PacketLength);
  564. TRACE( TL_V, TM_Recv, ( "Packet %x Length %x", pMyPacket, PacketLength ) );
  565. NDIS_SET_PACKET_STATUS (pMyPacket, NDIS_STATUS_SUCCESS);
  566. // Insert the node address if we are in bridge mode
  567. //
  568. if (ADAPTER_TEST_FLAG(pAdapter,fADAPTER_BridgeMode)== TRUE)
  569. {
  570. nicInsertNodeAddressAtHead (pMyPacket, &RcvInfo);
  571. }
  572. //
  573. // Set up the context in the ndis packet . Contains the Vc, and
  574. // the Buffer registered with the bus driver
  575. //
  576. pPktContext = (PPKT_CONTEXT)&pMyPacket->MiniportReserved;
  577. pPktContext->Receive.pVc = pVc;
  578. pPktContext->Receive.IndicatedStruct.pCommon = pIndicatedChain ;
  579. //
  580. // Its time to indicate the packet to NDIS
  581. //
  582. IndicatedStatus = NDIS_GET_PACKET_STATUS(pMyPacket);
  583. nicIndicateNdisPacketToNdis (pMyPacket,
  584. pVc,
  585. pVc->Hdr.pAF->pAdapter);
  586. //
  587. // Dereference the reassembly here . so that pReassembly is valid and it will catch all
  588. // failures prior this
  589. //
  590. if (pReassembly != NULL)
  591. {
  592. //
  593. // This should free the reassembly
  594. //
  595. nicFreeReassemblyStructure (pReassembly);
  596. pReassembly = NULL;
  597. }
  598. } while (FALSE);
  599. ASSERT (IndicatedStatus != NDIS_STATUS_RESOURCES);
  600. if (IndicatedStatus == NDIS_STATUS_RESOURCES)
  601. {
  602. //
  603. // The packet was completed with a status of resources.
  604. // It is gauranteed to be valid and we need to call the
  605. // return packet handler
  606. //
  607. nicInternalReturnPacket (pVc, pMyPacket);
  608. }
  609. //
  610. // Failure code path
  611. //
  612. if (NdisStatus != NDIS_STATUS_SUCCESS)
  613. {
  614. //
  615. // if there was a valid reassembly structure and the failure occured after that
  616. // then we need to abort the reaasembly
  617. //
  618. if (pMyPacket)
  619. {
  620. nicFreePacket (pMyPacket, RcvInfo.pPacketPool);
  621. }
  622. //
  623. // There could still be NdisBuffers that are allocated.
  624. //
  625. if (pReassembly != NULL)
  626. {
  627. nicDereferenceReassembly (pReassembly, "Indication failure");
  628. nicAbortReassembly(pReassembly);
  629. }
  630. else
  631. {
  632. //
  633. // We need to return this descriptor or fifo back to the bus driver
  634. //
  635. if (pVc->Hdr.VcType == NIC1394_SendRecvChannel ||
  636. pVc->Hdr.VcType == NIC1394_RecvChannel )
  637. {
  638. nicReturnDescriptorChain ((PISOCH_DESCRIPTOR)pIndicatedStruct,
  639. (PCHANNEL_VCCB) pVc);
  640. }
  641. else
  642. {
  643. ASSERT (pVc->Hdr.VcType == NIC1394_RecvFIFO);
  644. ASSERT (((PNOTIFICATION_INFO)pIndicatedStruct)->Fifo != NULL);
  645. nicReturnFifoChain ( ((PNOTIFICATION_INFO)pIndicatedStruct)->Fifo,
  646. (PRECVFIFO_VCCB) pVc);
  647. }
  648. if (pHeadNdisBuffer != NULL)
  649. {
  650. nicReturnNdisBufferChain(pHeadNdisBuffer, pVc);
  651. }
  652. }
  653. }
  654. TRACE( TL_T, TM_Recv, ( "<==nicReceiveCommonCallback " ) );
  655. }
  656. VOID
  657. nicChannelReturnPacket (
  658. IN PVCCB pVc,
  659. IN PNDIS_PACKET pMyPacket
  660. )
  661. // Function Description:
  662. // Return Packets Handler -
  663. // For FIFO's will reinsert the buffer (MDL) into the Fifo SList
  664. // Check for the VC Active and then return it ot the SList . Free it otherwise
  665. //
  666. // Arguments
  667. // RecvFIFOVc - Vc of the packet
  668. // pPacket = Packet in question
  669. //
  670. // Return Value:
  671. //
  672. //
  673. //
  674. {
  675. PCHANNEL_VCCB pChannelVc = (PCHANNEL_VCCB)pVc;
  676. PNDIS_BUFFER pMyNdisBuffer;
  677. PPKT_CONTEXT pPktContext = (PPKT_CONTEXT)&pMyPacket->MiniportReserved;
  678. PISOCH_DESCRIPTOR pIsochDescriptor = NULL;
  679. TRACE( TL_T, TM_Recv, ( "==>nicChannelReturnPacket pVc %x, pPacket %x",
  680. pChannelVc, pMyPacket) );
  681. ASSERT (pMyPacket != NULL);
  682. NdisUnchainBufferAtFront (pMyPacket,
  683. &pMyNdisBuffer);
  684. while (pMyNdisBuffer != NULL)
  685. {
  686. NdisFreeBuffer(pMyNdisBuffer);
  687. nicDecChannelRecvBuffer();
  688. pMyNdisBuffer = NULL;
  689. NdisUnchainBufferAtFront (pMyPacket,
  690. &pMyNdisBuffer);
  691. }
  692. //
  693. // Return the Descriptors to the bus driver
  694. //
  695. pIsochDescriptor = pPktContext->IsochListen.pIsochDescriptor;
  696. //
  697. // temporary sanity check asserts
  698. //
  699. ASSERT (pIsochDescriptor != NULL);
  700. nicReturnDescriptorChain (pIsochDescriptor, pChannelVc);
  701. //
  702. // Free The packet
  703. //
  704. nicFreePacket(pMyPacket, &pChannelVc->PacketPool);
  705. //
  706. // Update Count
  707. //
  708. //NdisInterlockedDecrement (&pChannelVc->OutstandingPackets ) ;
  709. TRACE( TL_T, TM_Recv, ( "<==nicChannelReturnPacket " ) );
  710. }
  711. VOID
  712. nicReturnDescriptorChain (
  713. IN PISOCH_DESCRIPTOR pIsochDescriptor,
  714. IN PCHANNEL_VCCB pChannelVc
  715. )
  716. {
  717. //
  718. // Walk the list of isoch descriptors and mark them as returned
  719. //
  720. PISOCH_DESCRIPTOR pCurr = NULL;
  721. PVOID pNext = NULL;
  722. PMDL pMdl = NULL;
  723. PVOID pVa = NULL;
  724. ULONG Len = 0;
  725. TRACE( TL_T, TM_Recv, ( "==> nicReturnDescriptorChain pIsochDescriptor %x",pIsochDescriptor ) );
  726. pCurr = pIsochDescriptor ;
  727. while (pCurr != NULL)
  728. {
  729. //ASSERT (pChannelVc == (PCHANNEL_VCCB)GET_CHANNELVC_FROM_DESCRIPTOR(pCurr));
  730. if (pNext != NULL)
  731. {
  732. pCurr = CONTAINING_RECORD (pNext,
  733. ISOCH_DESCRIPTOR,
  734. DeviceReserved[IsochNext] );
  735. }
  736. pNext = (PVOID)NEXT_ISOCH_DESCRIPTOR(pCurr);
  737. TRACE (TL_V, TM_Recv ,(" Isoch Descriptors Curr %x, next %x" , pCurr, pNext) );
  738. CLEAR_DESCRIPTOR_OF_NDIS_TAG(pCurr);
  739. CLEAR_DESCRIPTOR_NEXT(pCurr);
  740. //
  741. // Zero out the data that is being returned to the bus driver
  742. //
  743. #if 0
  744. pMdl = pCurr->Mdl;
  745. pVa = NIC_GET_SYSTEM_ADDRESS_FOR_MDL (pMdl);
  746. if (pVa != NULL)
  747. {
  748. Len = NIC_GET_BYTE_COUNT_FOR_MDL(pMdl);
  749. NdisZeroMemory(pVa, Len);
  750. }
  751. #endif
  752. pCurr = pNext;
  753. //
  754. // Update the count, The close call will wait for this count to go to zero
  755. //
  756. NdisInterlockedDecrement (&pChannelVc->NumIndicatedIsochDesc);
  757. //
  758. // Clear the Variables
  759. //
  760. pMdl = NULL;
  761. pVa = NULL;
  762. Len = 0;
  763. }
  764. TRACE( TL_T, TM_Recv, ( "<== nicReturnDescriptorChain pIsochDescriptor %x",pIsochDescriptor ) );
  765. }
  766. VOID
  767. nicRecvNoRemoteNode(
  768. PADAPTERCB pAdapter
  769. )
  770. /*++
  771. Routine Description:
  772. Queues a work item to go and update the node addresses of all the remote node
  773. Arguments:
  774. Return Value:
  775. --*/
  776. {
  777. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  778. TRACE( TL_T, TM_Send, ( "==>nicRecvNoRemoteNode ") );
  779. ASSERT (pAdapter != NULL);
  780. do
  781. {
  782. PNDIS_WORK_ITEM pUpdateTableWorkItem = NULL;
  783. BOOLEAN fWorkItemAlreadyLaunched = FALSE;
  784. //
  785. // We need to update the generation count
  786. //
  787. pUpdateTableWorkItem = ALLOC_NONPAGED (sizeof(NDIS_WORK_ITEM), MTAG_WORKITEM);
  788. if (pUpdateTableWorkItem == NULL)
  789. {
  790. TRACE( TL_A, TM_Cm, ( "Local Alloc failed for WorkItem - GetGeneration FAILED" ) );
  791. break;
  792. }
  793. ADAPTER_ACQUIRE_LOCK (pAdapter);
  794. if (ADAPTER_TEST_FLAGS (pAdapter, fADAPTER_UpdateNodeTable))
  795. {
  796. fWorkItemAlreadyLaunched = TRUE;
  797. }
  798. else
  799. {
  800. ADAPTER_SET_FLAG (pAdapter, fADAPTER_UpdateNodeTable);
  801. //
  802. // Ref the adapter. Deref in workitem
  803. //
  804. nicReferenceAdapter (pAdapter, "nicRecvNoRemoteNode" );
  805. fWorkItemAlreadyLaunched = FALSE;
  806. }
  807. ADAPTER_RELEASE_LOCK (pAdapter);
  808. if (fWorkItemAlreadyLaunched == TRUE)
  809. {
  810. FREE_NONPAGED(pUpdateTableWorkItem);
  811. break;
  812. }
  813. //
  814. // Set the Workitem
  815. //
  816. NdisInitializeWorkItem ( pUpdateTableWorkItem,
  817. (NDIS_PROC)nicUpdateNodeTable,
  818. (PVOID)pAdapter );
  819. NdisInterlockedIncrement(&pAdapter->OutstandingWorkItems);
  820. NdisScheduleWorkItem (pUpdateTableWorkItem);
  821. NdisStatus = NDIS_STATUS_SUCCESS;
  822. } while (FALSE);
  823. TRACE( TL_T, TM_Send, ( "<==nicRecvNoRemoteNode %x", NdisStatus) );
  824. }
  825. VOID
  826. nicUpdateNodeTable(
  827. NDIS_WORK_ITEM* pUpdateTable,
  828. IN PVOID Context
  829. )
  830. /*++
  831. Routine Description:
  832. This is called when the reassembly cannot find
  833. a remote node for reassembly
  834. For simplicity's sake, we go through all 63 entries
  835. We find a remote node, get its address. now the address' entry
  836. in the Node Table may already have another node there, so we take that
  837. node out put the new remote Node in that location. Then we go
  838. and update the node address of that remote node
  839. This is the WorkItem version of nicUpdateRemoteNodeTable
  840. Arguments:
  841. pAdapter Local host
  842. Return Value:
  843. --*/
  844. {
  845. ULONG i = 0;
  846. ULONG NumNodes = 0;
  847. PREMOTE_NODE pRemoteNode = NULL;
  848. NODE_ADDRESS NodeAddress ;
  849. NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS;
  850. PADAPTERCB pAdapter = (PADAPTERCB)Context;
  851. NdisZeroMemory (&NodeAddress, sizeof(NODE_ADDRESS));
  852. do
  853. {
  854. ADAPTER_ACQUIRE_LOCK (pAdapter);
  855. //
  856. // Get a remote node
  857. //
  858. pRemoteNode = NULL;
  859. while (i<NIC1394_MAX_NUMBER_NODES)
  860. {
  861. pRemoteNode = pAdapter->NodeTable.RemoteNode[i];
  862. if (pRemoteNode != NULL)
  863. {
  864. break;
  865. }
  866. i++;
  867. }
  868. if (pRemoteNode != NULL)
  869. {
  870. nicReferenceRemoteNode (pRemoteNode, UpdateNodeTable);
  871. }
  872. ADAPTER_RELEASE_LOCK (pAdapter);
  873. //
  874. // break out if we are the end of the loop
  875. //
  876. if (i>=NIC1394_MAX_NUMBER_NODES)
  877. {
  878. ASSERT (pRemoteNode == NULL)
  879. break;
  880. }
  881. if (pRemoteNode == NULL)
  882. {
  883. break;
  884. }
  885. i++;
  886. //
  887. // Now update the table. The new location of the Node in the
  888. // NodeTable may already have a Node, so we we will need to
  889. // update that remote node's address as well
  890. //
  891. do
  892. {
  893. PREMOTE_NODE pRemNodeOld = NULL;
  894. nicGet1394AddressOfRemoteNode (pRemoteNode,
  895. &NodeAddress,
  896. 0);
  897. if (NdisStatus != NDIS_STATUS_SUCCESS)
  898. {
  899. //
  900. // Just use the old node address, if it fails
  901. //
  902. NodeAddress = pRemoteNode->RemoteAddress;
  903. }
  904. ADAPTER_ACQUIRE_LOCK (pAdapter);
  905. //
  906. // Extract the occupant of the location
  907. //
  908. pRemNodeOld = pAdapter->NodeTable.RemoteNode[NodeAddress.NA_Node_Number];
  909. //
  910. // Update RemoteNode Address
  911. //
  912. pRemoteNode->RemoteAddress = NodeAddress ;
  913. if (pRemNodeOld == pRemoteNode)
  914. {
  915. //
  916. // The remote nodes are the same, so we do not
  917. // care about the old remote node
  918. //
  919. pRemNodeOld = NULL;
  920. }
  921. //
  922. // Only Reference And Update the Old remoteNode'address
  923. // if it is not our current remote node
  924. //
  925. if ( pRemNodeOld != NULL )
  926. {
  927. //
  928. // This location is already occupied.
  929. // Take it out, reference it and update its address
  930. //
  931. nicReferenceRemoteNode (pRemNodeOld, UpdateNodeTable);
  932. }
  933. //
  934. // Update the Master Node Table
  935. //
  936. pAdapter->NodeTable.RemoteNode[NodeAddress.NA_Node_Number] = pRemoteNode;
  937. //
  938. // This either derefs' the remote node or pRemNodeOld from a previous interation
  939. //
  940. nicDereferenceRemoteNode (pRemoteNode, UpdateNodeTable);
  941. //
  942. // Update pRemoteNode so that it loops again
  943. // and we can update the node addres of this pRemNodeOld
  944. // else it will be null and we exit this loop
  945. //
  946. pRemoteNode = pRemNodeOld;
  947. ADAPTER_RELEASE_LOCK (pAdapter);
  948. } while (pRemoteNode != NULL);
  949. //
  950. // If we have not gone through all the nodes .
  951. // get the next remote node
  952. //
  953. }while (i<NIC1394_MAX_NUMBER_NODES);
  954. ADAPTER_ACQUIRE_LOCK (pAdapter);
  955. ADAPTER_CLEAR_FLAG (pAdapter, fADAPTER_UpdateNodeTable);
  956. ADAPTER_RELEASE_LOCK (pAdapter);
  957. FREE_NONPAGED (pUpdateTable);
  958. NdisInterlockedDecrement(&pAdapter->OutstandingWorkItems);
  959. nicDereferenceAdapter(pAdapter, "nicRecvNoRemoteNode Derefed in nicUpdateNodeTable" );
  960. }
  961. VOID
  962. nicInsertNodeAddressAtHead (
  963. IN PNDIS_PACKET pPacket,
  964. IN PNIC_RECV_DATA_INFO pRcvInfo
  965. )
  966. /*++
  967. Routine Description:
  968. Adds the Node Address to the first 16 bits in the packet.
  969. It fails quietly if it is not able to do so
  970. Arguments:
  971. pPacket pPacket in Question
  972. pRcvInfo -> With the correct Gasp Header
  973. Return Value:
  974. --*/
  975. {
  976. PNDIS1394_UNFRAGMENTED_HEADER pHeader = NULL;
  977. TRACE( TL_T, TM_Recv, ( "nicInsertNodeAddressAtHead , pPacket %x pRecvInfo %x",pPacket, pRcvInfo ) );
  978. do
  979. {
  980. pHeader = nicNdisBufferVirtualAddress (pPacket->Private.Head);
  981. if (pHeader == NULL)
  982. {
  983. break;
  984. }
  985. //
  986. // Assert for now. Will not work if there are 1394 bridges with bus number != 0;
  987. //
  988. ASSERT (pRcvInfo->SourceID < 64);
  989. pHeader->u1.SourceAddress= (UCHAR)(pRcvInfo->SourceID);
  990. pHeader->u1.fHeaderHasSourceAddress = TRUE;
  991. } while (FALSE);
  992. TRACE( TL_T, TM_Recv, ( "nicInsertNodeAddressAtHead , pHeader %x = *pHeader %x", pHeader, pHeader->HeaderUlong ) );
  993. }