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.

3178 lines
94 KiB

  1. //
  2. // Copyright (c) 1998-1999, Microsoft Corporation, all rights reserved
  3. //
  4. // send.c
  5. //
  6. // IEEE1394 mini-port/call-manager driver
  7. //
  8. // Mini-port Send routines
  9. //
  10. // 12/28/1998 ADube Created,
  11. //
  12. //
  13. // A Send follows this simple algorithm:
  14. // Copy incoming data to local buffers
  15. // Create an Mdl for the local copy
  16. // Store the IRB and VC in the ndispacket
  17. // Use the ndispacket as context in the irp's completion routine
  18. //
  19. #include <precomp.h>
  20. //-----------------------------------------------------------------------------
  21. // Global counts
  22. //-----------------------------------------------------------------------------
  23. extern UINT BusSendCompletes;
  24. extern UINT NicSendCompletes;
  25. extern UINT BusSends;
  26. extern ULONG MdlsAllocated[NoMoreCodePaths];
  27. extern ULONG MdlsFreed[NoMoreCodePaths];
  28. //-----------------------------------------------------------------------------
  29. // prototypes implementations (alphabetically)
  30. //-----------------------------------------------------------------------------
  31. NDIS_STATUS
  32. nicCopyNdisBufferChainToBuffer(
  33. IN PNDIS_BUFFER pInBuffer,
  34. IN OUT PVOID pLocalBuffer,
  35. IN UINT BufferLength )
  36. {
  37. //
  38. // This function copies the data the belongs to the
  39. // pInMdl chain to the local Buffer.
  40. // BufferLength is used for validation purposes only
  41. // Fragmentation and insertion of headers will take place here
  42. //
  43. NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS;
  44. UINT LocalBufferIndex = 0; // Used as an index to the LocalBuffer, used for validation
  45. UINT MdlLength = 0;
  46. PVOID MdlAddress = 0;
  47. PNDIS_BUFFER pCurrBuffer;
  48. TRACE( TL_T, TM_Send, ( "==>nicCopyNdisBufferChainToBuffer pNdisbuffer %x, Buffer %x, Length %x",
  49. pInBuffer, pLocalBuffer,BufferLength ) );
  50. ASSERT (pLocalBuffer != NULL);
  51. pCurrBuffer = pInBuffer;
  52. do
  53. {
  54. MdlLength = nicNdisBufferLength(pCurrBuffer);
  55. MdlAddress= nicNdisBufferVirtualAddress(pCurrBuffer);
  56. if (MdlLength != 0)
  57. {
  58. if (MdlAddress == NULL)
  59. {
  60. NdisStatus = NDIS_STATUS_FAILURE;
  61. TRACE (TL_A, TM_Send, ("Ndis Buffer at %x", pCurrBuffer) );
  62. BREAK (TM_Send, (" nicCopyNdisBufferChainToBuffer: Mdl Address = NULL") );
  63. }
  64. if ( LocalBufferIndex + MdlLength > BufferLength)
  65. {
  66. ASSERT(LocalBufferIndex + MdlLength <= BufferLength);
  67. NdisStatus = NDIS_STATUS_BUFFER_TOO_SHORT;
  68. BREAK (TM_Send, ("nicCopyNdisBufferChainToBuffer Copy Failed" ) );
  69. }
  70. //
  71. // Copy the Data to local memory.
  72. //
  73. NdisMoveMemory((PVOID)((ULONG_PTR)pLocalBuffer+LocalBufferIndex),
  74. MdlAddress,
  75. MdlLength);
  76. LocalBufferIndex += MdlLength;
  77. }
  78. pCurrBuffer = pCurrBuffer->Next;
  79. } while (pCurrBuffer!= NULL);
  80. TRACE( TL_T, TM_Send, ( "<==nicCopyNdisBufferChainToBuffer %x",NdisStatus ) );
  81. return NdisStatus;
  82. }
  83. VOID
  84. nicFreeIrb(PIRB pIrb)
  85. //
  86. // Frees the Memory occcupied by the Irb
  87. //
  88. {
  89. ASSERT(pIrb != NULL);
  90. TRACE( TL_T, TM_Irp, ( "==>nicFreeIrb %x", pIrb ) );
  91. if (pIrb != NULL)
  92. {
  93. FREE_NONPAGED(pIrb);
  94. }
  95. TRACE( TL_T, TM_Irp, ( "<==nicFreeIrb") );
  96. return;
  97. }
  98. VOID
  99. nicFreeIrp(PIRP pIrp)
  100. //
  101. // Frees the memory occupied by the Irp
  102. //
  103. {
  104. ASSERT(pIrp != NULL);
  105. TRACE( TL_T, TM_Irp, ( "==>nicFreeIrp at %x",pIrp ) );
  106. if (pIrp != NULL)
  107. {
  108. IoFreeIrp(pIrp);
  109. }
  110. TRACE( TL_T, TM_Irp, ( "<==nicFreeIrp") );
  111. return;
  112. }
  113. VOID
  114. nicFreeLocalBuffer (
  115. IN UINT Length,
  116. IN PVOID Address )
  117. //
  118. // Free the Memory pointed to by Address.
  119. // The Length parameter is superfluous and will be removed
  120. // once I am sure we don;t need it
  121. //
  122. {
  123. NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS;
  124. ASSERT(Address != NULL);
  125. TRACE( TL_T, TM_Send, ( "==>nicFreeLocalBuffer , Address %x", Address) );
  126. if (Address != NULL)
  127. {
  128. FREE_NONPAGED((PVOID)Address);
  129. }
  130. TRACE( TL_T, TM_Send, ( "<==niFreeLocalBuffer, NdisStatus %x",NdisStatus ) );
  131. return;
  132. }
  133. VOID
  134. nicFreeMdl(PMDL pMdl)
  135. //
  136. // This frees the memory belonging to the Mdl. Does not free the
  137. // memory that the Mdl Points to
  138. //
  139. {
  140. ASSERT (pMdl != NULL)
  141. TRACE( TL_T, TM_Send, ( "==> nicFreeMdl pMdl %x", pMdl ) );
  142. if (pMdl != NULL)
  143. {
  144. IoFreeMdl(pMdl);
  145. }
  146. TRACE( TL_T, TM_Send, ( "<== nicFreeMdl") );
  147. return ;
  148. }
  149. VOID
  150. nicFreeToNPagedLookasideList (
  151. IN PNIC_NPAGED_LOOKASIDE_LIST pLookasideList,
  152. IN PVOID pBuffer
  153. )
  154. // Function Description:
  155. // Return the local buffer to the lookaside list
  156. //
  157. // Atguments
  158. // Lookaside list and its buffer
  159. // Return Value:
  160. // None
  161. {
  162. TRACE( TL_T, TM_Send, ( "==> nicFreeToNPagedLookasideList , Lookaside list %x, plocalbuffer %x",pLookasideList, pBuffer ) );
  163. NdisFreeToNPagedLookasideList (&pLookasideList->List, pBuffer);
  164. NdisInterlockedDecrement (&pLookasideList->OutstandingPackets);
  165. TRACE( TL_T, TM_Send, ( "<== nicFreeToNPagedLookasideList ") );
  166. }
  167. NDIS_STATUS
  168. nicGetIrb(
  169. OUT PIRB *ppIrb )
  170. //
  171. // This function is to be used in retrieving a free IRB.
  172. // that will be supplied as an argument for an IRP
  173. //
  174. // Initially, this will simple allocate an IRB
  175. // Intiailization could be added here
  176. //
  177. {
  178. NDIS_STATUS NdisStatus;
  179. TRACE( TL_T, TM_Irp, ( "==>nicGetIrb" ) );
  180. *ppIrb = (PIRB)ALLOC_NONPAGED ( sizeof(IRB), MTAG_HBUFPOOL );
  181. if (*ppIrb != NULL)
  182. {
  183. NdisZeroMemory ( *ppIrb, sizeof(IRB) );
  184. NdisStatus = NDIS_STATUS_SUCCESS;
  185. TRACE( TL_V, TM_Send, ( " nicGetIrb: Irb allocated at %x", *ppIrb ) );
  186. }
  187. else
  188. {
  189. nicIncrementMallocFailure();
  190. NdisStatus = NDIS_STATUS_FAILURE;
  191. }
  192. TRACE( TL_T, TM_Irp, ( "<==nicGetIrb NdisStatus %x",NdisStatus ) );
  193. return NdisStatus;
  194. }
  195. NDIS_STATUS
  196. nicGetIrp(
  197. IN PDEVICE_OBJECT pPdo,
  198. OUT PIRP *ppIrp
  199. )
  200. //
  201. // This function returns am irp to the calling routine
  202. // The irp is free and is owned by the nic1394.
  203. // NEED TO CHANGE THE STACK SIZE
  204. //
  205. {
  206. NDIS_STATUS NdisStatus;
  207. PIRP pIrp;
  208. CCHAR StackSize =0;
  209. ASSERT (pPdo != NULL);
  210. TRACE( TL_T, TM_Irp, ( "==>nicGetIrp Pdo %x", pPdo ) );
  211. if (pPdo == NULL)
  212. {
  213. ASSERT (pPdo != NULL);
  214. NdisStatus = NDIS_STATUS_FAILURE;
  215. *ppIrp = NULL;
  216. return NdisStatus;
  217. }
  218. //
  219. // Allocate the Irp with the correct stacksize
  220. //
  221. StackSize = pPdo->StackSize+1;
  222. pIrp = IoAllocateIrp (StackSize, FALSE);
  223. do
  224. {
  225. if (pIrp == NULL)
  226. {
  227. NdisStatus = NDIS_STATUS_FAILURE;
  228. break;
  229. }
  230. TRACE( TL_V, TM_Send, ( " Irp allocated at %x, Stacksize %x",pIrp , StackSize ) );
  231. *ppIrp = pIrp;
  232. //
  233. // Initialize the Irp
  234. //
  235. IoInitializeIrp ( *ppIrp, sizeof(IRP), StackSize );
  236. if (*ppIrp != NULL)
  237. {
  238. NdisStatus = NDIS_STATUS_SUCCESS;
  239. }
  240. else
  241. {
  242. nicIncrementMallocFailure();
  243. NdisStatus = NDIS_STATUS_FAILURE;
  244. }
  245. } while (FALSE);
  246. TRACE( TL_T, TM_Irp, ( "<==nicGetIrp ,irp %x",*ppIrp ) );
  247. return NdisStatus;
  248. }
  249. NDIS_STATUS
  250. nicGetLocalBuffer(
  251. OPTIONAL IN ULONG Length,
  252. OUT PVOID *ppLocalBuffer
  253. )
  254. //
  255. // This function allocates memory of size 'Length' and returns
  256. // a pointer to this memory
  257. //
  258. {
  259. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  260. TRACE( TL_T, TM_Send, ( "==>nicGetLocalBuffer Length %x", Length ) );
  261. //
  262. // There is a bug in the Nic if this is zero
  263. //
  264. ASSERT (Length != 0 );
  265. //
  266. // There is no lookaside list, We need to allocate memory
  267. //
  268. *ppLocalBuffer = ALLOC_NONPAGED (Length, MTAG_FBUFPOOL);
  269. if (*ppLocalBuffer != NULL)
  270. {
  271. NdisStatus = NDIS_STATUS_SUCCESS;
  272. }
  273. else
  274. {
  275. nicIncrementMallocFailure();
  276. NdisStatus = NDIS_STATUS_FAILURE;
  277. }
  278. TRACE( TL_T, TM_Send, ( "<==nicGetLocalBuffer, NdisStatus %x at %x",NdisStatus,*ppLocalBuffer ) );
  279. return NdisStatus;
  280. }
  281. PVOID
  282. nicGetLookasideBuffer(
  283. IN PNIC_NPAGED_LOOKASIDE_LIST pLookasideList
  284. )
  285. // Function Description:
  286. // Allocate an buffer from the lookaside list.
  287. // will be changed to a macro
  288. //
  289. //
  290. //
  291. // Arguments
  292. // Lookaside list - from which the buffer is allocated
  293. //
  294. //
  295. // Return Value:
  296. // Return buffer can be NULL
  297. //
  298. {
  299. PVOID pLocalBuffer = NULL;
  300. TRACE( TL_T, TM_Send, ( "==>nicGetLookasideBuffer pLookasideList %x", pLookasideList) );
  301. ASSERT (pLookasideList != NULL);
  302. //
  303. // Optimize the lookaside list code path
  304. //
  305. pLocalBuffer = NdisAllocateFromNPagedLookasideList (&pLookasideList->List);
  306. if (pLocalBuffer != NULL)
  307. {
  308. NdisZeroMemory (pLocalBuffer, pLookasideList->Size);
  309. NdisInterlockedIncrement (&pLookasideList->OutstandingPackets);
  310. }
  311. else
  312. {
  313. nicIncrementMallocFailure();
  314. }
  315. TRACE( TL_T, TM_Send, ( "<==nicGetLookasideBuffer, %x", pLocalBuffer ) );
  316. return pLocalBuffer ;
  317. }
  318. NDIS_STATUS
  319. nicGetMdl(
  320. IN UINT Length,
  321. IN PVOID pLocalBuffer,
  322. OUT PMDL *ppMyMdl)
  323. //
  324. // Return a locally owned Mdl to the caller.
  325. // This will also initialize the MDl with the localbuffer
  326. // Initial implementation will allocate mdls
  327. //
  328. {
  329. NDIS_STATUS NdisStatus;
  330. TRACE( TL_T, TM_Send, ( "==>nicGetMdl" ) );
  331. ASSERT(pLocalBuffer != NULL);
  332. //
  333. // Allocate an MDl to point to the structure
  334. //
  335. (*ppMyMdl) = IoAllocateMdl( pLocalBuffer,
  336. Length,
  337. FALSE,
  338. FALSE,
  339. NULL );
  340. //
  341. // Initialize the data structures with correct values
  342. //
  343. if (*ppMyMdl != NULL)
  344. {
  345. MmBuildMdlForNonPagedPool(*ppMyMdl);
  346. (*ppMyMdl)->Next = NULL;
  347. NdisStatus = NDIS_STATUS_SUCCESS;
  348. }
  349. else
  350. {
  351. nicIncrementMallocFailure();
  352. NdisStatus = NDIS_STATUS_FAILURE;
  353. *ppMyMdl = NULL;
  354. }
  355. TRACE( TL_T, TM_Send, ( "<==nicGetMdl, Mdl %x, LocalBuffer %x",
  356. *ppMyMdl, pLocalBuffer) );
  357. return NdisStatus;
  358. }
  359. VOID
  360. nicInitAsyncStreamIrb(
  361. IN PCHANNEL_VCCB pChannelVc,
  362. IN PMDL pMdl,
  363. IN OUT PIRB pIrb
  364. )
  365. // This function initializes the Irb that will be used in the Irb
  366. // It specifically handles the AsyncStream IRB
  367. // It arguments are the Vc block (for destination address),
  368. // Mdl (Memory desctiptor for the data and a pointer to the
  369. // Irb structure that will be initialized
  370. {
  371. ASSERT (pMdl != NULL);
  372. ASSERT (pIrb != NULL);
  373. NdisZeroMemory (pIrb, sizeof (IRB) );
  374. pIrb->FunctionNumber = REQUEST_ASYNC_STREAM;
  375. pIrb->Flags = 0;
  376. pIrb->u.AsyncStream.nNumberOfBytesToStream = MmGetMdlByteCount(pMdl);
  377. pIrb->u.AsyncStream.fulFlags = 0;
  378. //
  379. // See comments for ISOCH_TAG
  380. //
  381. pIrb->u.AsyncStream.ulTag = g_IsochTag;
  382. pIrb->u.AsyncStream.nChannel = pChannelVc->Channel;
  383. pIrb->u.AsyncStream.ulSynch = pChannelVc->ulSynch;
  384. pIrb->u.AsyncStream.nSpeed = (INT)pChannelVc->Speed;
  385. pIrb->u.AsyncStream.Mdl = pMdl;
  386. TRACE( TL_V, TM_Send, ( "Number of Bytes to Stream %x ", pIrb->u.AsyncStream.nNumberOfBytesToStream ) );
  387. TRACE( TL_V, TM_Send, ( "fulFlags %x ", pIrb->u.AsyncStream.fulFlags ) );
  388. TRACE( TL_V, TM_Send, ( "ulTag %x ", pIrb->u.AsyncStream.ulTag ) );
  389. TRACE( TL_V, TM_Send, ( "Channel %x", pIrb->u.AsyncStream.nChannel ) );
  390. TRACE( TL_V, TM_Send, ( "Synch %x", pIrb->u.AsyncStream.ulSynch ) );
  391. TRACE( TL_V, TM_Send, ( "Speed %x", pIrb->u.AsyncStream.nSpeed ) );
  392. TRACE( TL_V, TM_Send, ( "Mdl %x", pIrb->u.AsyncStream.Mdl ) );
  393. }
  394. VOID
  395. nicInitAsyncWriteIrb(
  396. IN PSENDFIFO_VCCB pSendFIFOVc,
  397. IN PMDL pMyMdl,
  398. IN OUT PIRB pMyIrb
  399. )
  400. // This function initializes the Irb that will be used in the Irb
  401. // It specifically handles the AsyncWrite IRB
  402. // It arguments are the Vc block (for destination address),
  403. // Mdl (Memory desctiptor for the data and a pointer to the
  404. // Irb structure that will be initialized
  405. {
  406. //
  407. // Sanity check
  408. //
  409. ASSERT ((*(PULONG)pMyIrb) == 0)
  410. pMyIrb->u.AsyncWrite.nNumberOfBytesToWrite = MmGetMdlByteCount(pMyMdl);
  411. pMyIrb->u.AsyncWrite.nBlockSize = 0;
  412. pMyIrb->u.AsyncWrite.fulFlags = 0;
  413. pMyIrb->u.AsyncWrite.Mdl = pMyMdl;
  414. pMyIrb->FunctionNumber = REQUEST_ASYNC_WRITE;
  415. pMyIrb->Flags = 0;
  416. pMyIrb->u.AsyncWrite.nSpeed = (UCHAR)pSendFIFOVc->MaxSendSpeed ;
  417. pMyIrb->u.AsyncWrite.DestinationAddress.IA_Destination_Offset.Off_High = pSendFIFOVc->FifoAddress.Off_High;
  418. pMyIrb->u.AsyncWrite.DestinationAddress.IA_Destination_Offset.Off_Low = pSendFIFOVc->FifoAddress.Off_Low;
  419. pMyIrb->u.AsyncWrite.ulGeneration = *pSendFIFOVc->Hdr.pGeneration;
  420. pMyIrb->u.AsyncWrite.nBlockSize = 0;
  421. pMyIrb->u.AsyncWrite.fulFlags = ASYNC_FLAGS_NONINCREMENTING;
  422. pMyIrb->u.AsyncWrite.DestinationAddress.IA_Destination_ID.NA_Bus_Number = 0x3ff;
  423. TRACE(TL_V, TM_Send, ("DestinationAddress.IA_Destination_ID.NA_Bus_Number = 0x%x\n", pMyIrb->u.AsyncWrite.DestinationAddress.IA_Destination_ID.NA_Bus_Number) );
  424. TRACE(TL_V, TM_Send, ("DestinationAddress.IA_Destination_ID.NA_Node_Number = 0x%x\n", pMyIrb->u.AsyncWrite.DestinationAddress.IA_Destination_ID.NA_Node_Number) );
  425. TRACE(TL_V, TM_Send, ("DestinationAddress.IA_Destination_Offset.Off_High = 0x%x at 0x%x\n", pMyIrb->u.AsyncWrite.DestinationAddress.IA_Destination_Offset.Off_High, &pMyIrb->u.AsyncWrite.DestinationAddress.IA_Destination_Offset.Off_High) );
  426. TRACE(TL_V, TM_Send, ("DestinationAddress.IA_Destination_Offset.Off_Low = 0x%x at 0x%x\n", pMyIrb->u.AsyncWrite.DestinationAddress.IA_Destination_Offset.Off_Low,&pMyIrb->u.AsyncWrite.DestinationAddress.IA_Destination_Offset.Off_Low) );
  427. TRACE(TL_V, TM_Send, ("nNumberOfBytesToWrite = 0x%x\n", pMyIrb->u.AsyncWrite.nNumberOfBytesToWrite));
  428. TRACE(TL_V, TM_Send, ("nBlockSize = 0x%x\n", pMyIrb->u.AsyncWrite.nBlockSize));
  429. TRACE(TL_V, TM_Send, ("fulFlags = 0x%x\n", pMyIrb->u.AsyncWrite.fulFlags));
  430. TRACE(TL_V, TM_Send, ("Mdl = 0x%x\n", pMyIrb->u.AsyncWrite.Mdl ));
  431. TRACE(TL_V, TM_Send, ("ulGeneration = 0x%x at 0x%x \n", pMyIrb->u.AsyncWrite.ulGeneration, &pMyIrb->u.AsyncWrite.ulGeneration));
  432. TRACE(TL_V, TM_Send, ("chPriority = 0x%x\n", pMyIrb->u.AsyncWrite.chPriority));
  433. TRACE(TL_V, TM_Send, ("nSpeed = 0x%x\n", pMyIrb->u.AsyncWrite.nSpeed));
  434. }
  435. NDIS_STATUS
  436. DummySendPacketsHandler(
  437. IN PVCCB pVc,
  438. IN PNDIS_PACKET pPacket
  439. )
  440. //
  441. // To be used on a non-send VC
  442. //
  443. {
  444. return NDIS_STATUS_FAILURE;
  445. }
  446. VOID
  447. nicSendFailureInvalidGeneration(
  448. PVCCB pVc
  449. )
  450. // Function Description:
  451. //
  452. // An AsyncStream or AnsyncWrite Irp may be completed
  453. // with a status of InvalidGeneration. This function will try and
  454. // get a new generation, so that future sends will not be blocked
  455. //
  456. // Arguments
  457. //
  458. //
  459. //
  460. // Return Value:
  461. //
  462. //
  463. //
  464. //
  465. {
  466. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  467. PADAPTERCB pAdapter = pVc->Hdr.pAF->pAdapter;
  468. TRACE( TL_T, TM_Send, ( "==>nicSendFailureInvalidGeneration ") );
  469. ASSERT (pVc != NULL);
  470. do
  471. {
  472. PNDIS_WORK_ITEM pGetGenerationWorkItem = NULL;
  473. BOOLEAN fWorkItemAlreadyLaunched = FALSE;
  474. BOOLEAN fQueueWorkItem = FALSE;
  475. TRACE( TL_A, TM_Send, ( "Cause: Invalid generation on the asyncwrite packet" ) );
  476. VC_ACQUIRE_LOCK (pVc);
  477. if (VC_ACTIVE(pVc) == TRUE)
  478. {
  479. fQueueWorkItem = TRUE;
  480. }
  481. fWorkItemAlreadyLaunched = (VC_TEST_FLAGS (pVc, VCBF_GenerationWorkItem));
  482. if (fWorkItemAlreadyLaunched)
  483. {
  484. //
  485. // If the Work Item has already been launched, then do not launch another instance
  486. //
  487. fQueueWorkItem = FALSE;
  488. }
  489. if ( fQueueWorkItem )
  490. {
  491. nicReferenceCall (pVc, "nicSendFailureInvalidGeneration");
  492. }
  493. VC_RELEASE_LOCK (pVc);
  494. if (fQueueWorkItem == FALSE)
  495. {
  496. // this thread simply exits
  497. break;
  498. }
  499. //
  500. // We need to update the generation count
  501. //
  502. pGetGenerationWorkItem = ALLOC_NONPAGED (sizeof(NDIS_WORK_ITEM), MTAG_WORKITEM);
  503. if (pGetGenerationWorkItem == NULL)
  504. {
  505. TRACE( TL_A, TM_Cm, ( "Local Alloc failed for WorkItem - GetGeneration FAILED" ) );
  506. break;
  507. }
  508. VC_ACQUIRE_LOCK (pVc);
  509. VC_SET_FLAG(pVc, VCBF_GenerationWorkItem );
  510. VC_RELEASE_LOCK (pVc);
  511. NdisInitializeWorkItem ( pGetGenerationWorkItem ,
  512. (NDIS_PROC)nicGetGenerationWorkItem,
  513. (PVOID)pVc );
  514. NdisInterlockedIncrement(&pAdapter->OutstandingWorkItems);
  515. NdisScheduleWorkItem (pGetGenerationWorkItem );
  516. NdisStatus = NDIS_STATUS_SUCCESS;
  517. } while (FALSE);
  518. TRACE( TL_T, TM_Send, ( "<==nicSendFailureInvalidGeneration %x", NdisStatus) );
  519. }
  520. VOID
  521. nicMakeGaspHeader (
  522. IN PADAPTERCB pAdapter,
  523. IN PGASP_HEADER pGaspHeader
  524. )
  525. // Function Description:
  526. // This function will take the adapter structure and construct a Gasp Header out of it.
  527. // This will be used to make the AsyncStream packets.
  528. //
  529. //
  530. //
  531. // Arguments
  532. // pAdapter - Local Host in question
  533. // pGaspHeader - Location where the Gasp Header is to be stored
  534. //
  535. // Return Value:
  536. // None
  537. //
  538. {
  539. USHORT SourceID;
  540. NODE_ADDRESS LocalNodeAddress;
  541. NDIS_STATUS NdisStatus;
  542. TRACE( TL_T, TM_Send, ( "==>nicMakeGaspHeader padapter %x, pGaspNdisBuffer %x ", pAdapter, pGaspHeader) );
  543. ASSERT (pGaspHeader != NULL);
  544. TRACE( TL_V, TM_Send, ( "pAdapter->NodeAddress %x", pAdapter->NodeAddress) );
  545. SourceID = *((PUSHORT)&pAdapter->NodeAddress);
  546. if(SourceID ==0)
  547. {
  548. NdisStatus = nicGet1394AddressFromDeviceObject (pAdapter->pNextDeviceObject,
  549. &LocalNodeAddress,
  550. USE_LOCAL_NODE);
  551. if ( NdisStatus == NDIS_STATUS_SUCCESS)
  552. {
  553. SourceID = *((PUSHORT)&LocalNodeAddress);
  554. ADAPTER_ACQUIRE_LOCK (pAdapter);
  555. pAdapter->NodeAddress = LocalNodeAddress;
  556. ADAPTER_RELEASE_LOCK (pAdapter);
  557. }
  558. //
  559. // Do not handle failure. As the BCM or a Reset will fix this problem
  560. //
  561. }
  562. TRACE( TL_V, TM_Send, ( "SourceId %x at %x", SourceID, &SourceID) );
  563. pGaspHeader->FirstQuadlet.Bitmap.GH_Source_ID = SourceID ;
  564. pGaspHeader->FirstQuadlet.Bitmap.GH_Specifier_ID_Hi = GASP_SPECIFIER_ID_HI;
  565. pGaspHeader->SecondQuadlet.Bitmap.GH_Specifier_ID_Lo = GASP_SPECIFIER_ID_LO;
  566. pGaspHeader->SecondQuadlet.Bitmap.GH_Version = 1;
  567. pGaspHeader->FirstQuadlet.GaspHeaderHigh = SWAPBYTES_ULONG (pGaspHeader->FirstQuadlet.GaspHeaderHigh );
  568. pGaspHeader->SecondQuadlet.GaspHeaderLow = SWAPBYTES_ULONG (pGaspHeader->SecondQuadlet.GaspHeaderLow );
  569. TRACE( TL_V, TM_Send, ( "Gasp Header High %x", pGaspHeader->FirstQuadlet.GaspHeaderHigh) );
  570. TRACE( TL_V, TM_Send, ( "Gasp Header Low %x", pGaspHeader->SecondQuadlet.GaspHeaderLow ) );
  571. TRACE( TL_T, TM_Send, ( "<==nicFreeGaspHeader %x, %x ", pGaspHeader->FirstQuadlet.GaspHeaderHigh, pGaspHeader->SecondQuadlet.GaspHeaderLow ) );
  572. }
  573. NTSTATUS
  574. AsyncWriteStreamSendComplete(
  575. IN PDEVICE_OBJECT DeviceObject,
  576. IN PIRP pMyIrp,
  577. IN PVOID Context
  578. )
  579. //
  580. // N.B. this completes both Fifo and channels
  581. //
  582. //
  583. // This function is Completion handler for the Irp used to send data.
  584. // This function will invoke NDisCoSendComplete Handler
  585. // Needs to use the VC Handle stored in the MiniportReserved[0]
  586. // of the packet.
  587. // We free all the data structures allocated on the way down,
  588. // by SendPacketsHandler (the Irb. Irp and Local memory used and Mdl)
  589. //
  590. // The LookasideHeader->OutstandingFragments should normally be one for
  591. // the defualt ( non-fragmented) case. However, if a failure in SendPackets
  592. // occurs, Outstanding fragments will be zero or the context will be null,
  593. // in that case we will only free the lookaside buffer (if it exists) and exit,
  594. // it will be the responsibility of the SendPacketsHandler
  595. // to fail the packet.
  596. //
  597. {
  598. NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS;
  599. NTSTATUS IrpStatus = STATUS_UNSUCCESSFUL;
  600. PVOID pLookasideListBuffer = Context;
  601. PLOOKASIDE_BUFFER_HEADER pLookasideHeader = (PLOOKASIDE_BUFFER_HEADER)pLookasideListBuffer ;
  602. PNDIS_PACKET pPacket = NULL;
  603. PVCCB pVc = NULL;
  604. PREMOTE_NODE pRemoteNode = NULL;
  605. NDIS_HANDLE NdisVcHandle = NULL;
  606. ULONG OutstandingFragments = 0;
  607. BUS_OPERATION AsyncOp;
  608. PNIC_NPAGED_LOOKASIDE_LIST pLookasideList = NULL;
  609. STORE_CURRENT_IRQL;
  610. TRACE( TL_T, TM_Send, ( "==>AsyncWriteStreamSendComplete, pMyIrp %x, Context %x",
  611. pMyIrp, Context ) );
  612. do
  613. {
  614. if (pLookasideHeader == NULL)
  615. {
  616. TRACE( TL_V, TM_Send, ( " AsyncSendComplete - pLookasideHeader == NULL") );
  617. break;
  618. }
  619. //
  620. // This means that a lookaside buffer was allocated and
  621. // perhaps MDLS were allocated
  622. // if this is the last fragment, Free all the MDLs first
  623. //
  624. //
  625. // Get all the valuable information out of the header.
  626. //
  627. pPacket = pLookasideHeader->pNdisPacket;
  628. pVc = pLookasideHeader->pVc;
  629. pRemoteNode = pVc->Hdr.pRemoteNode;
  630. pLookasideList = pLookasideHeader->pLookasideList;
  631. AsyncOp = pLookasideHeader->AsyncOp;
  632. ASSERT (AsyncOp != InvalidOperation);
  633. TRACE( TL_V, TM_Send, ( " Vc %x,, pLookaside Buffer %x, pPacket, %x",
  634. pVc, pLookasideHeader ,pPacket ) );
  635. ASSERT (pLookasideList != NULL);
  636. //
  637. // This will tell us if this thread has received the last fragment
  638. // OustandingPackets == 0 gets to free the MDLS, and complete the packet
  639. //
  640. OutstandingFragments = NdisInterlockedDecrement (&pLookasideHeader->OutstandingFragments );
  641. if (OutstandingFragments == 0)
  642. {
  643. //
  644. // If there are no more fragments, then we need to
  645. // free all the allocated structures ( the MDLS) on this buffer
  646. //
  647. ULONG MdlsToFree = pLookasideHeader->FragmentsGenerated;
  648. PIRB pIrb = &((PUNFRAGMENTED_BUFFER)pLookasideHeader)->Irb;
  649. //
  650. // The maximum number of MDLS we can have is equal to
  651. // the maximum number of Fragments that were generated
  652. //
  653. while (MdlsToFree != 0)
  654. {
  655. PMDL pMdl = NULL;
  656. GET_MDL_FROM_IRB (pMdl, pIrb, AsyncOp);
  657. TRACE( TL_V, TM_Send, ( " Freeing Mdl %x of Irb %x ",
  658. pMdl, pIrb) );
  659. if (pMdl != NULL)
  660. {
  661. nicFreeMdl (pMdl);
  662. if (pVc->Hdr.VcType == NIC1394_SendFIFO)
  663. {
  664. nicDecFifoSendMdl();
  665. }
  666. else
  667. {
  668. nicDecChannelSendMdl();
  669. }
  670. }
  671. //
  672. // Set up for the next iteration
  673. //
  674. MdlsToFree --;
  675. pIrb = (PVOID)((ULONG_PTR)pIrb + sizeof (IRB));
  676. } //while (MdlsToFree != 0)
  677. } //if (OutstandingFragments == 0)
  678. //
  679. // Map the NT_STATUS belonging to the Irp to an NdisStatus and call NdisMCoSendComplete
  680. // Print Debug Output to help in testing. Need to Add more status cases
  681. //
  682. if (pMyIrp == NULL)
  683. {
  684. TRACE( TL_V, TM_Send, ( " AsyncSendComplete - pIrp is NULL") );
  685. IrpStatus = STATUS_UNSUCCESSFUL;
  686. }
  687. else
  688. {
  689. //
  690. // We have a valid IRP, lets see if we failed the IRP and why
  691. //
  692. IrpStatus = pMyIrp->IoStatus.Status;
  693. nicIncrementBusSendCompletes(pVc);
  694. }
  695. if (IrpStatus != STATUS_SUCCESS)
  696. {
  697. TRACE( TL_A, TM_Send, ( "==>IRP FAILED StatusCode = %x",IrpStatus ) );
  698. nicIncrementBusFailure();
  699. nicIncrementVcBusSendFailures(pVc, pPacket);
  700. //
  701. // The generation of the bus has changed. Lets get a new one.
  702. //
  703. if (IrpStatus == STATUS_INVALID_GENERATION)
  704. {
  705. nicSendFailureInvalidGeneration((PVCCB)pVc);
  706. }
  707. NdisStatus = NtStatusToNdisStatus(IrpStatus);
  708. NdisInterlockedIncrement (&pVc->Hdr.pAF->pAdapter->AdaptStats.ulXmitError);
  709. }
  710. else
  711. {
  712. NdisInterlockedIncrement(&pVc->Hdr.pAF->pAdapter->AdaptStats.ulXmitOk);
  713. nicIncrementVcBusSendSucess(pVc, pPacket);
  714. }
  715. //
  716. // Free the Irp and don't touch it after this
  717. //
  718. if (pMyIrp != NULL)
  719. {
  720. nicFreeIrp (pMyIrp);
  721. pMyIrp = NULL;
  722. }
  723. //
  724. // At this point, we know that the IRP went down to the bus driver
  725. // We know if this is the last fragment. So lets figure out if we need
  726. // to Complete the packet
  727. //
  728. if (OutstandingFragments != 0)
  729. {
  730. //
  731. // We need to wait for other fragments to complete
  732. //
  733. TRACE( TL_V, TM_Send, ( " AsyncSendComplete = NOT the last fragment") );
  734. break;
  735. }
  736. //
  737. // This means that this thread has marked the lookaside header as 'to be freed'
  738. // and it is this thread's responsibility to free it.
  739. //
  740. NdisVcHandle = pVc->Hdr.NdisVcHandle;
  741. TRACE( TL_V, TM_Send, ( "Calling NdisCoSendComplete, status %x, VcHandle %x, pPacket %x",
  742. NdisStatus,NdisVcHandle, pPacket ) );
  743. nicMpCoSendComplete (NdisStatus,
  744. pVc,
  745. pPacket);
  746. nicFreeToNPagedLookasideList (pLookasideList, pLookasideListBuffer);
  747. nicDereferenceCall (pVc, "AsyncWriteStreamSendComplete");
  748. //
  749. // Remove the reference on the PDO that the IRP was sent to
  750. //
  751. if (AsyncOp == AsyncWrite)
  752. {
  753. //
  754. // Async Write references the remote node
  755. //
  756. ASSERT (pRemoteNode != NULL);
  757. nicDereferenceRemoteNode (pRemoteNode, AsyncSendComplete);
  758. }
  759. } while (FALSE);
  760. TRACE( TL_T, TM_Send, ( "<== AsyncWriteStreamSendComplete, NdisStatus %x,IrpStatus %x ",
  761. NdisStatus, IrpStatus ) );
  762. //
  763. // ALWAYS RETURN STATUS_MORE_PROCESSING_REQUIRED
  764. //
  765. MATCH_IRQL;
  766. return STATUS_MORE_PROCESSING_REQUIRED;
  767. }
  768. NDIS_STATUS
  769. AsyncWriteSendPacketsHandler(
  770. IN PVCCB pVc,
  771. IN PNDIS_PACKET pPacket
  772. )
  773. //
  774. // This is the VC handler when packet is sent using the
  775. // AsyncWrite 1394 Bus Api
  776. // This function, copies the contents of the packet to locally
  777. // owned memory, sets up the Irb and the Irp and calls
  778. // nicSubmitIrp which is the generic cal to do a IoCallDriver
  779. //
  780. // The return value is success, if the I/o was successfully pended
  781. {
  782. PSENDFIFO_VCCB pSendFIFOVc = (SENDFIFO_VCCB*)pVc;
  783. PMDL pMyMdl = NULL;
  784. PIRB pMyIrb = NULL;
  785. PIRP pMyIrp = NULL;
  786. BOOLEAN fVcActive = TRUE;
  787. PREMOTE_NODE pRemoteNode = NULL;
  788. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  789. NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;
  790. ULONG PacketLength = 0;
  791. PVOID pLookasideListBuffer = NULL;
  792. PADAPTERCB pAdapter = NULL;
  793. USHORT FragmentLength = 0;
  794. PNDIS_BUFFER pStartNdisBuffer = NULL;
  795. PVOID pStartPacketData = NULL;
  796. PLOOKASIDE_BUFFER_HEADER pLookasideHeader = NULL;
  797. PNIC_NPAGED_LOOKASIDE_LIST pLookasideList = NULL;
  798. ENUM_LOOKASIDE_LIST WhichLookasideList = NoLookasideList;
  799. FRAGMENTATION_STRUCTURE Fragment;
  800. ULONG NumFragmentsNeeded ;
  801. STORE_CURRENT_IRQL;
  802. NdisZeroMemory (&Fragment, sizeof (FRAGMENTATION_STRUCTURE));
  803. TRACE( TL_T, TM_Send, ( "==>AsyncWriteSendPacketHandler, Vc %x,Packet %x, FragmentationStruct %x",
  804. pSendFIFOVc, pPacket , &Fragment ) );
  805. pRemoteNode = pSendFIFOVc->Hdr.pRemoteNode;
  806. ASSERT (pRemoteNode != NULL);
  807. do
  808. {
  809. VC_ACQUIRE_LOCK (pSendFIFOVc);
  810. //
  811. // Make sure that the Vc is Activated and that no close calls
  812. // are pending or that we have already completed a close call
  813. //
  814. if ( VC_ACTIVE (pSendFIFOVc) == FALSE || REMOTE_NODE_ACTIVE(pRemoteNode) == FALSE)
  815. {
  816. fVcActive = FALSE;
  817. }
  818. if (VC_TEST_FLAG( pSendFIFOVc, VCBF_GenerationWorkItem) == TRUE)
  819. {
  820. TRACE( TL_N, TM_Send, ( "AsyncWriteSendPacketHandler, Getting a new Gen, Fail send ") );
  821. fVcActive = FALSE;
  822. }
  823. //
  824. // This reference will either be dereferenced below in a call to FreeSendPacketDataStructure
  825. // below or a call to FreeSendPacketDataStructure made from the Irp's completion routine
  826. //
  827. if (fVcActive == TRUE)
  828. {
  829. nicReferenceCall (pVc, "AsyncWriteSendPacketsHandler");
  830. nicReferenceRemoteNode (pRemoteNode, AsyncWriteSendPackets);
  831. }
  832. VC_RELEASE_LOCK (pSendFIFOVc);
  833. if (fVcActive == FALSE)
  834. {
  835. TRACE( TL_N, TM_Send, ( "AsyncWriteSendPacketHandler, VC Not Active, Vc %x Flag %x", pSendFIFOVc,pSendFIFOVc->Hdr.ulFlags ) );
  836. NdisStatus = NDIS_STATUS_FAILURE;
  837. break;
  838. }
  839. pAdapter = pSendFIFOVc->Hdr.pAF->pAdapter;
  840. //
  841. // Copy NdisBuffer in Packet to Local Memory and get an Mdl that points
  842. // to this memory
  843. //
  844. NdisQueryPacket( pPacket,
  845. NULL,
  846. NULL,
  847. NULL,
  848. &PacketLength);
  849. ASSERT (pPacket->Private.Head != NULL);
  850. //
  851. // Spew out the packet if necessary
  852. //
  853. nicDumpPkt (pPacket, "AsyncWriteSendPacketsHandler");
  854. //
  855. // Initialize the start variables
  856. //
  857. pStartNdisBuffer = pPacket->Private.Head;
  858. pStartPacketData = nicNdisBufferVirtualAddress (pStartNdisBuffer);
  859. if (pStartPacketData == NULL)
  860. {
  861. NdisStatus = NDIS_STATUS_RESOURCES;
  862. TRACE( TL_N, TM_Send, ( "AsyncWriteSendPacketHandler, pStartPacketData ") );
  863. break;
  864. }
  865. TRACE( TL_V, TM_Send, ( "PacketLength %x", PacketLength) );
  866. //
  867. // Make a decision on which lookaside list to use. If the tx is unfragmented
  868. // then copy over the ndis packet as well
  869. //
  870. //
  871. // first choose the lookaside list. the actual lookaside list is chosen so that the
  872. // each can accomodate the maximum number of fragments at its payload
  873. //
  874. //
  875. if (PacketLength < PAYLOAD_100)
  876. {
  877. pLookasideList = &pAdapter->SendLookasideList100;
  878. WhichLookasideList = SendLookasideList100;
  879. TRACE( TL_V, TM_Send, ( " PAYLOAD_100 Lookaside List %x",
  880. &pAdapter->SendLookasideList100) );
  881. }
  882. else
  883. if (PacketLength < PAYLOAD_2K)
  884. {
  885. pLookasideList = &pAdapter->SendLookasideList2K;
  886. WhichLookasideList = SendLookasideList2K;
  887. TRACE( TL_V, TM_Send, ( " PAYLOAD_2K Lookaside List %x",
  888. &pAdapter->SendLookasideList2K) );
  889. }
  890. else
  891. {
  892. //
  893. // Large Sends not supported
  894. // TODO : Add code for local allocation
  895. //
  896. ASSERT (!"SendPacket Too Large - Not supported Yet" );
  897. break;
  898. }
  899. //
  900. // are we going to fragment
  901. //
  902. ASSERT (pLookasideList != NULL)
  903. //
  904. // We are not going to fragment. Optimize this path
  905. //
  906. pLookasideListBuffer = nicGetLookasideBuffer (pLookasideList);
  907. if (pLookasideListBuffer == NULL )
  908. {
  909. NdisStatus = NDIS_STATUS_FAILURE;
  910. BREAK (TM_Send, ("nicGetLookasideBuffer FAILED") );
  911. }
  912. //
  913. // Initialize the header with relevant information that the send complete
  914. // will need
  915. //
  916. pLookasideHeader = (PLOOKASIDE_BUFFER_HEADER)pLookasideListBuffer;
  917. pLookasideHeader->IsFragmented = FALSE; // Default
  918. pLookasideHeader->FragmentsGenerated = 0;
  919. pLookasideHeader->pLookasideList = pLookasideList;
  920. pLookasideHeader->pNdisPacket = pPacket;
  921. pLookasideHeader->pVc =(PVCCB)pVc;
  922. pLookasideHeader->AsyncOp = AsyncWrite;
  923. //
  924. // Initialize the Fragment structure
  925. //
  926. //
  927. // Do we fragment or not. Base it on the MaxPayload possible
  928. //
  929. TRACE( TL_V, TM_Send, ( " PacketLength %x, pSendFIFOVc->MaxPayload%x ",
  930. PacketLength ,pSendFIFOVc->Hdr.MaxPayload) );
  931. if (PacketLength <= pSendFIFOVc->Hdr.MaxPayload)
  932. {
  933. //
  934. // No need to fragment here. We will use the UNFRAGMENTED Layout
  935. //
  936. // First Get a local buffer from our lookaside list
  937. //
  938. PUNFRAGMENTED_BUFFER pUnfragmentedBuffer = (PUNFRAGMENTED_BUFFER )pLookasideHeader;
  939. NumFragmentsNeeded = 1;
  940. NdisStatus = nicCopyNdisBufferChainToBuffer (pStartNdisBuffer,
  941. (PVOID)&pUnfragmentedBuffer ->Data[0],
  942. pLookasideList->MaxSendSize );
  943. if (NdisStatus != NDIS_STATUS_SUCCESS)
  944. {
  945. pLookasideHeader->OutstandingFragments = 1; // this is our refcount
  946. BREAK ( TM_Send, ( " AsyncStreamSendPacketHandler, nicCopyNdisPacketToUnfragmentedBuffer Failed ") );
  947. }
  948. ASSERT (pLookasideListBuffer != NULL);
  949. //
  950. // Initialize all the variable needed by the Next section of the code.
  951. // This deals with setting up the Mdl and the IRB
  952. //
  953. pStartNdisBuffer = NULL;
  954. Fragment.pStartFragment = (PVOID) &pUnfragmentedBuffer ->Data[0];
  955. Fragment.FragmentLength = PacketLength;
  956. Fragment.pCurrNdisBuffer = NULL;
  957. pLookasideHeader->FragmentsGenerated = 1;
  958. pLookasideHeader->IsFragmented = FALSE;
  959. pLookasideHeader->OutstandingFragments = 1; // this is our refcount
  960. }
  961. else
  962. {
  963. //
  964. // We need to fragment
  965. //
  966. ULONG Dgl = NdisInterlockedIncrement(&pAdapter->dgl);
  967. //
  968. // Fragments will be needed . Make sure the calculation for numFragments catches the boundary conditions
  969. //
  970. NumFragmentsNeeded = nicNumFragmentsNeeded (PacketLength,
  971. pSendFIFOVc->Hdr.MaxPayload,
  972. sizeof (NDIS1394_FRAGMENT_HEADER) );
  973. //
  974. // Initialize the fragment structure. The unfragmented code path
  975. // does not care about these fields
  976. //
  977. //
  978. // This structure is local to this function and this thread.
  979. //
  980. Fragment.TxHeaderSize = sizeof (NDIS1394_FRAGMENT_HEADER);
  981. Fragment.pLookasideListBuffer = pLookasideListBuffer;
  982. Fragment.AsyncOp = AsyncWrite;
  983. Fragment.pAdapter = pRemoteNode->pAdapter;
  984. Fragment.pLookasideList = pLookasideList;
  985. Fragment.IPDatagramLength = (USHORT)PacketLength - sizeof (NDIS1394_UNFRAGMENTED_HEADER);
  986. //
  987. // Get Start of first Dest fragment
  988. //
  989. Fragment.MaxFragmentLength = pSendFIFOVc->Hdr.MaxPayload;
  990. Fragment.NumFragmentsNeeded = NumFragmentsNeeded;
  991. //
  992. // Set up the Fragment Headers that will be used in fragmentation
  993. //
  994. NdisStatus = nicFirstFragmentInitialization (pPacket->Private.Head,
  995. Dgl,
  996. &Fragment);
  997. if (pLookasideListBuffer == NULL || NdisStatus != NDIS_STATUS_SUCCESS)
  998. {
  999. BREAK (TM_Send, (" AsyncWriteSendPacketsHandler: nicFirstFragmentInitialization : FAILED" )) ;
  1000. }
  1001. ASSERT (pLookasideListBuffer != NULL);
  1002. pLookasideHeader->IsFragmented = TRUE;
  1003. pLookasideHeader->OutstandingFragments = NumFragmentsNeeded ; // this is our refcount
  1004. }
  1005. TRACE( TL_V, TM_Send, ( "NumFragments %x, pSendFIFOVc->MaxSendSize %x, Packet Size %x",
  1006. NumFragmentsNeeded,pSendFIFOVc->Hdr.MaxPayload, PacketLength) );
  1007. //
  1008. // Now begin the loop which will send n fragments
  1009. //
  1010. do
  1011. {
  1012. //
  1013. // Do we need to fragment. If so , extract one fragment out of the NdisPacket
  1014. //
  1015. if (pLookasideHeader->IsFragmented == TRUE )
  1016. {
  1017. //
  1018. // We copy one fragment over and this will allocate the lookaside list
  1019. //
  1020. NdisStatus = nicCopyOneFragment (&Fragment);
  1021. if (NDIS_STATUS_SUCCESS != NdisStatus)
  1022. {
  1023. BREAK ( TM_Send, ( " AsyncWriteSendPacketHandler, nicCopyOneFragment Failed ") );
  1024. }
  1025. //
  1026. // Get the pointer to the Irb here . Amd set it up for the next time
  1027. //
  1028. pMyIrb = Fragment.pCurrentIrb;
  1029. Fragment.pCurrentIrb = (PIRB)((ULONG_PTR)Fragment.pCurrentIrb + sizeof (IRB) );
  1030. TRACE( TL_V, TM_Send, ( " pMyIrb %x, Next Irb %x ", pMyIrb , Fragment.pCurrentIrb ) );
  1031. }
  1032. else
  1033. {
  1034. //
  1035. // No Curr NdisBuffer as this packet was never fragmented.
  1036. //
  1037. ASSERT (pLookasideHeader->IsFragmented == FALSE);
  1038. pMyIrb = &((PUNFRAGMENTED_BUFFER )pLookasideHeader)->Irb;
  1039. }
  1040. //
  1041. // At this point we have one fragment that needs to be transmitted.
  1042. // Data structures have been updated to set up the MDL and the IRB
  1043. //
  1044. ASSERT (Fragment.pStartFragment != NULL);
  1045. NdisStatus = nicGetMdl (Fragment.FragmentLength ,
  1046. Fragment.pStartFragment,
  1047. &pMyMdl);
  1048. if (NdisStatus != NDIS_STATUS_SUCCESS)
  1049. {
  1050. pMyMdl = NULL;
  1051. BREAK ( TM_Send, ( " AsyncWriteSendPacketHandler, nicCopyNdisBufferChainToBuffer Failed ") );
  1052. }
  1053. nicIncFifoSendMdl();
  1054. //
  1055. // Fill in the Irb with the correct values from the VC
  1056. // Stuff we need to add to the send VC - BlockSize,Generation
  1057. //
  1058. nicInitAsyncWriteIrb(pSendFIFOVc, pMyMdl, pMyIrb);
  1059. //
  1060. // Get a free Irp
  1061. //
  1062. NdisStatus = nicGetIrp (pRemoteNode->pPdo, &pMyIrp);
  1063. if (NdisStatus != NDIS_STATUS_SUCCESS)
  1064. {
  1065. pMyIrp = NULL;
  1066. break;
  1067. }
  1068. //
  1069. // At this point, we have a guarantee that the Completion routine will be called
  1070. //
  1071. ASSERT (NdisStatus == NDIS_STATUS_SUCCESS);
  1072. //
  1073. // Dump the Fragment
  1074. //
  1075. nicDumpMdl (pMyMdl , 0, "AsyncWrite Fragment");
  1076. NIC1394_LOG_PKT(
  1077. pAdapter,
  1078. NIC1394_LOGFLAGS_SEND_FIFO,
  1079. pAdapter->BCRData.LocalNodeNumber, // SourceID
  1080. pRemoteNode->RemoteAddress.NA_Node_Number, // DestID
  1081. Fragment.pStartFragment,
  1082. Fragment.FragmentLength
  1083. );
  1084. //
  1085. // This function implements the common functionality to be implemented by
  1086. // all other send/recv cals to IoCallDriver
  1087. //
  1088. //
  1089. // We IGNORE the NtStatus as the completion handler will be called
  1090. //
  1091. nicIncrementBusSends(pVc);
  1092. NtStatus = nicSubmitIrp(pRemoteNode->pPdo,
  1093. pMyIrp,
  1094. pMyIrb,
  1095. AsyncWriteStreamSendComplete,
  1096. (PVOID)pLookasideListBuffer);
  1097. TRACE( TL_V, TM_Send, ( " pCurrNdisBuffer %x, NdisStatus %x ", Fragment.pCurrNdisBuffer , NdisStatus ) );
  1098. } while (Fragment.pCurrNdisBuffer != NULL && NdisStatus == NDIS_STATUS_SUCCESS);
  1099. } while (FALSE);
  1100. //
  1101. // DO NOT touch the packet if status == NDIS_STATUS_SUCCESS.
  1102. //
  1103. //
  1104. // CleanUp if any of the allocations failed. We do not have a pointer
  1105. // to the LocalBuffer (it is embedded in the Mdl) so it remains NULL
  1106. //
  1107. // NdisStatus != Success means that we never got to nicSubmitIrp
  1108. //
  1109. if (NdisStatus != NDIS_STATUS_SUCCESS)
  1110. {
  1111. ASSERT (pMyIrp == NULL);
  1112. //
  1113. // fVc Active makes sure that we actually got around to allocating
  1114. // and referencing structures
  1115. //
  1116. if (fVcActive == TRUE)
  1117. {
  1118. if (pLookasideListBuffer != NULL)
  1119. {
  1120. //
  1121. // Complete this fragment, as we never submit'd the IRP to
  1122. // the 1394 bus driver
  1123. //
  1124. AsyncWriteStreamSendComplete(NULL, // PDO
  1125. NULL,
  1126. pLookasideListBuffer);
  1127. NdisStatus =NDIS_STATUS_SUCCESS;
  1128. }
  1129. else
  1130. {
  1131. //
  1132. // This thread needs to decrement the refcounts as
  1133. // AsyncWriteStreamSendComplete was not called
  1134. //
  1135. nicDereferenceCall ((PVCCB) pSendFIFOVc, "AsyncWriteSendPacketsHandler");
  1136. nicDereferenceRemoteNode (pRemoteNode, AsyncWriteSendPackets);
  1137. }
  1138. }
  1139. }
  1140. TRACE( TL_T, TM_Send, ( "<==AsyncWriteSendPacketHandler, NdisStatus %x", NdisStatus ) );
  1141. MATCH_IRQL;
  1142. return NdisStatus;
  1143. }
  1144. NDIS_STATUS
  1145. nicCopyOneFragment (
  1146. PFRAGMENTATION_STRUCTURE pFragment
  1147. )
  1148. // Function Description:
  1149. // This creates one fragment filled with valid data and returns it.
  1150. // The is complex because the Current NDisBuffer could end before the fragment
  1151. // or vice versa.
  1152. //
  1153. // Information from this fragment is stored and will be used in the next fragment
  1154. //
  1155. // Arguments
  1156. // pFragment - Copies one fragment into the next available fragement.
  1157. //
  1158. // Return Value:
  1159. // Status - Success
  1160. //
  1161. //
  1162. {
  1163. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  1164. PNDIS_BUFFER pCurrNdisBuffer = pFragment->pCurrNdisBuffer;
  1165. PVOID pSourceAddressInNdisBuffer = pFragment->pSourceAddressInNdisBuffer;
  1166. ULONG FragmentLengthRemaining = pFragment->MaxFragmentLength;
  1167. USHORT FragmentLength=0;
  1168. PVOID pSource = NULL;
  1169. PVOID pDestination = NULL;
  1170. PVOID pStartFragmentData = NULL;
  1171. ULONG NdisBufferLengthRemaining = pFragment->NdisBufferLengthRemaining;
  1172. ULONG LengthToCopy = 0;
  1173. ULONG FragmentCopyStatus=0;
  1174. PLOOKASIDE_BUFFER_HEADER pLookasideHeader = NULL;
  1175. enum
  1176. {
  1177. FRAGMENT_COPY_Invalid,
  1178. FRAGMENT_COPY_NdisBufferCompleted,
  1179. FRAGMENT_COPY_NdisBufferAndFragmentCompleted,
  1180. FRAGMENT_COPY_FragmentCompleted
  1181. };
  1182. TRACE( TL_T, TM_Send, ( "==>nicCopyOneFragment pFragment %x", pFragment ) );
  1183. ASSERT (pCurrNdisBuffer != NULL);
  1184. do
  1185. {
  1186. //
  1187. // lets get the destination. We need to account for
  1188. // ther fragment size and add it to the previous start address
  1189. //
  1190. {
  1191. ULONG CurrFragOffset;
  1192. CurrFragOffset = pFragment->MaxFragmentLength * (pFragment->CurrFragmentNum++);
  1193. pStartFragmentData = (PVOID) ((ULONG_PTR) pFragment->pStartOfFirstFragment + CurrFragOffset );
  1194. }
  1195. pFragment->pStartFragment = pStartFragmentData;
  1196. TRACE( TL_V, TM_Send, ( " pStartFragmentData %x", pStartFragmentData) );
  1197. pLookasideHeader = (PLOOKASIDE_BUFFER_HEADER)pFragment->pLookasideListBuffer;
  1198. //
  1199. // Do the bookkeeping , Increase refcount and num of fragments used. Refcount decremented in FreeSendDataStructures
  1200. //
  1201. NdisInterlockedIncrement (&pLookasideHeader->FragmentsGenerated);
  1202. //
  1203. // The Start of the data beginning with the fragment header goes here or in the
  1204. // case of async stream fragment header and gasp header go here
  1205. //
  1206. ASSERT (pFragment->TxHeaderSize == 8 || pFragment->TxHeaderSize == 16);
  1207. pDestination = (PVOID) ((ULONG_PTR)pStartFragmentData + pFragment->TxHeaderSize );
  1208. FragmentLengthRemaining -= pFragment->TxHeaderSize;
  1209. //
  1210. // Now we start the copy. Keep on copying into the current fragment until the MaxLength is reached
  1211. // or the NdisBufferChain is exhausted
  1212. //
  1213. pSource = pSourceAddressInNdisBuffer;
  1214. do
  1215. {
  1216. TRACE( TL_T, TM_Send, ( " LengthNdisBuffer %x, FragmentLengthRemaining %x, pCurrNdisBuffer %x",
  1217. NdisBufferLengthRemaining , FragmentLengthRemaining ,pCurrNdisBuffer ) );
  1218. if (FragmentLengthRemaining > NdisBufferLengthRemaining )
  1219. {
  1220. //
  1221. // Copy the complete NdisBuffer over
  1222. //
  1223. LengthToCopy = NdisBufferLengthRemaining;
  1224. FragmentCopyStatus = FRAGMENT_COPY_NdisBufferCompleted;
  1225. }
  1226. if (FragmentLengthRemaining < NdisBufferLengthRemaining )
  1227. {
  1228. //
  1229. // Copy only as much as required
  1230. //
  1231. LengthToCopy = FragmentLengthRemaining;
  1232. FragmentCopyStatus = FRAGMENT_COPY_FragmentCompleted;
  1233. }
  1234. if (FragmentLengthRemaining == NdisBufferLengthRemaining )
  1235. {
  1236. //
  1237. // Copy the complete Ndis Buffer , move to the next ndis buffer
  1238. // and update the NdisBufferLengthRemaining field
  1239. //
  1240. LengthToCopy = NdisBufferLengthRemaining;
  1241. FragmentCopyStatus = FRAGMENT_COPY_NdisBufferAndFragmentCompleted;
  1242. }
  1243. //
  1244. // Sanity check to make sure we are not overwriting into free memory.
  1245. // As this should never happen, there is no recovery mechanism in place.
  1246. //
  1247. ASSERT (((PUCHAR)pDestination + LengthToCopy) <= (((PUCHAR) pLookasideHeader) + (pLookasideHeader->pLookasideList->Size) ));
  1248. //
  1249. // Do the copy
  1250. //
  1251. TRACE ( TL_V, TM_Send, (" nicCopyOneFragment pSource %x , pDestination %x, Length %x", pSource, pDestination, LengthToCopy ) );
  1252. NdisMoveMemory (pDestination, pSource, LengthToCopy);
  1253. //
  1254. // Update the fragment length remaininig and Total Buffer Size
  1255. //
  1256. FragmentLengthRemaining -= LengthToCopy;
  1257. FragmentLength += (USHORT)LengthToCopy;
  1258. pDestination = (PVOID) ((ULONG_PTR) pDestination + LengthToCopy);
  1259. //
  1260. // Update the NdisBuffer variables
  1261. //
  1262. ASSERT (pCurrNdisBuffer != NULL);
  1263. TRACE( TL_V, TM_Send, ( " FragmentCopyStatus %x", FragmentCopyStatus) );
  1264. switch (FragmentCopyStatus)
  1265. {
  1266. case FRAGMENT_COPY_NdisBufferCompleted:
  1267. case FRAGMENT_COPY_NdisBufferAndFragmentCompleted:
  1268. {
  1269. //
  1270. // Move to the next Ndisbuffer
  1271. //
  1272. pCurrNdisBuffer = pCurrNdisBuffer->Next;
  1273. if (pCurrNdisBuffer != NULL)
  1274. {
  1275. NdisBufferLengthRemaining = nicNdisBufferLength (pCurrNdisBuffer);
  1276. pSourceAddressInNdisBuffer = nicNdisBufferVirtualAddress(pCurrNdisBuffer);
  1277. if (pSourceAddressInNdisBuffer == NULL)
  1278. {
  1279. NdisStatus = NDIS_STATUS_RESOURCES;
  1280. BREAK (TM_Send, ("nicNdisBufferVirtualAddress FAILED " ) );
  1281. }
  1282. //
  1283. // Set up the values for the next iteration
  1284. //
  1285. pSource = pSourceAddressInNdisBuffer;
  1286. NdisBufferLengthRemaining = nicNdisBufferLength (pCurrNdisBuffer);
  1287. }
  1288. else
  1289. {
  1290. //
  1291. // we have reached the end of the NdisPAcket. Mark the fragment header as such
  1292. //
  1293. pFragment->lf = lf_LastFragment;
  1294. }
  1295. break;
  1296. }
  1297. case FRAGMENT_COPY_FragmentCompleted:
  1298. {
  1299. //
  1300. // Fragment has completed. Do not move to the next NdisBuffer
  1301. // However update StartCopy Address in the NdisBuffer
  1302. //
  1303. pSourceAddressInNdisBuffer = (PVOID) ((ULONG_PTR) pSource + LengthToCopy );
  1304. NdisBufferLengthRemaining -= LengthToCopy ;
  1305. break;
  1306. }
  1307. default :
  1308. {
  1309. ASSERT (0);
  1310. }
  1311. }
  1312. TRACE( TL_T, TM_Send, ( " LengthToCopy %x, FragmentLength %x, ", LengthToCopy, FragmentLength) );
  1313. TRACE( TL_T, TM_Send, ( " FragmentLengthRemaining %x, pCurrNdisBuffer %x",FragmentLengthRemaining , pCurrNdisBuffer ) );
  1314. }while (FragmentLengthRemaining > 0 && pCurrNdisBuffer != NULL);
  1315. //
  1316. // Now that we have the buffer size. Add the fragment header
  1317. //
  1318. nicAddFragmentHeader (pStartFragmentData,
  1319. pFragment,
  1320. FragmentLength);
  1321. TRACE( TL_T, TM_Send, ( " Fragment Header added %x", *(PULONG)pStartFragmentData) );
  1322. NdisStatus = NDIS_STATUS_SUCCESS;
  1323. }while (FALSE);
  1324. //
  1325. // Now update the output parameters.
  1326. //
  1327. if (NdisStatus == NDIS_STATUS_SUCCESS)
  1328. {
  1329. //
  1330. // Update the Lookaside Header structure, to reflect the new position of all the pointers
  1331. //
  1332. pFragment->pCurrNdisBuffer = pCurrNdisBuffer;
  1333. pFragment->pSourceAddressInNdisBuffer = pSourceAddressInNdisBuffer;
  1334. //
  1335. // Update the fragment structure with the length remaining in the NdisBuffer
  1336. //
  1337. pFragment->NdisBufferLengthRemaining = NdisBufferLengthRemaining ;
  1338. pFragment->FragmentLength = FragmentLength + pFragment->TxHeaderSize;
  1339. }
  1340. TRACE( TL_T, TM_Send, ( "<==nicCopyOneFragment pStartFragmentData %x, pLookasideListBuffer %x, pSourceAddressInNdisBuffer %x, NdisStatus %x",
  1341. pStartFragmentData, pSourceAddressInNdisBuffer, NdisStatus) );
  1342. return NdisStatus;
  1343. }
  1344. VOID
  1345. nicCopyUnfragmentedHeader (
  1346. IN PNIC1394_UNFRAGMENTED_HEADER pDestUnfragmentedHeader,
  1347. IN PVOID pSrcUnfragmentedHeader
  1348. )
  1349. // Function Description:
  1350. // Expect the Src to be a big Endian unfragmented packet header
  1351. // It will reverse the byte order in a temp variable and copy it into the
  1352. // Destination provided.
  1353. //
  1354. // Arguments
  1355. // pDestUnfragmentedHeader - Destination (Little Endian
  1356. // pSrcUnfragmentedHeader - Source (Big Endian)
  1357. //
  1358. // Return Value:
  1359. //
  1360. // Success if all the pointers and copy is valid
  1361. //
  1362. {
  1363. ULONG UnfragmentedHeader;
  1364. TRACE( TL_T, TM_Send, ( "==> nicCopyUnfragmentedHeader pDestUnfragmentedHeader %x, pSrcUnfragmentedHeader %x",
  1365. pDestUnfragmentedHeader, pSrcUnfragmentedHeader ) );
  1366. ASSERT (pSrcUnfragmentedHeader != NULL && pDestUnfragmentedHeader != NULL) ;
  1367. *((PULONG)pDestUnfragmentedHeader) = SWAPBYTES_ULONG ( *(PULONG) pSrcUnfragmentedHeader);
  1368. TRACE( TL_T, TM_Send, ( "pDestUnfragmentedHeader %x, ", *(PULONG)pDestUnfragmentedHeader) );
  1369. TRACE( TL_T, TM_Send, ( " <== nicCopyUnfragmentedHeader " ) );
  1370. }
  1371. NDIS_STATUS
  1372. nicFirstFragmentInitialization (
  1373. IN PNDIS_BUFFER pStartNdisBuffer,
  1374. IN ULONG DatagramLabelLong,
  1375. IN OUT PFRAGMENTATION_STRUCTURE pFragment
  1376. )
  1377. // Function Description:
  1378. // This will set up the fragement headers that are required for
  1379. // transmitting multiple fragments.
  1380. // Sets up the first source and destination for the first fragment
  1381. //
  1382. // Arguments
  1383. // pAdapter - to be used to get the dgl label and the lookaside list
  1384. // pStartOfData - start of the packet data . To be used in extracting the Unfragmented Header
  1385. // ppLookasideListBuffer Points to the allocated lookaside buffer
  1386. // pplookasideheader - points to the lookaside header
  1387. //
  1388. // Return Value:
  1389. // Success if the allocation succeeds
  1390. //
  1391. //
  1392. {
  1393. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  1394. PNDIS1394_FRAGMENT_HEADER pHeader = NULL;
  1395. PVOID pPacketStartData = NULL;
  1396. USHORT dgl = (USHORT) DatagramLabelLong;
  1397. TRACE( TL_T, TM_Send, ( "==> nicFirstFragmentInitialization pStartNdisBuffer%x, pFragment%x dgl %x ",
  1398. pStartNdisBuffer, pFragment, dgl ) );
  1399. do
  1400. {
  1401. //
  1402. // Get the start address for the 1st NdisBuffer. This contains
  1403. // the unfragmented header
  1404. //
  1405. pPacketStartData = nicNdisBufferVirtualAddress(pStartNdisBuffer);
  1406. if (pPacketStartData == NULL)
  1407. {
  1408. NdisStatus = NDIS_STATUS_RESOURCES;
  1409. BREAK (TM_Send, ("NdisBufferVirtual Address is NULL " ) );
  1410. }
  1411. pFragment->UnfragmentedHeader.HeaderUlong =
  1412. SWAPBYTES_ULONG (((PNDIS1394_UNFRAGMENTED_HEADER)pPacketStartData)->HeaderUlong);
  1413. TRACE ( TL_V, TM_Send, (" Unfragmented Header %x, pPacketStartData %x",
  1414. pFragment->UnfragmentedHeader.HeaderUlong , pPacketStartData) );
  1415. TRACE ( TL_V, TM_Send, (" original Header lf %x, etherType %x",
  1416. pFragment->UnfragmentedHeader.u.FH_lf,
  1417. pFragment->UnfragmentedHeader.u.FH_EtherType) );
  1418. //
  1419. // Now construct a fragmentation header to be used by all the fragments.
  1420. //
  1421. pHeader = &pFragment->FragmentationHeader;
  1422. pHeader ->u.FirstQuadlet.FH_lf = lf_FirstFragment;
  1423. pHeader ->u.FirstQuadlet.FH_buffersize = pFragment->IPDatagramLength-1;
  1424. pHeader ->u.FirstQuadlet_FirstFragment.FH_EtherType
  1425. = pFragment->UnfragmentedHeader.u.FH_EtherType;
  1426. pHeader ->u1.SecondQuadlet.FH_dgl = dgl;
  1427. TRACE ( TL_V, TM_Send, (" fragmented Header Hi %x Lo %x",
  1428. pHeader->u.FH_High,
  1429. pHeader->u1.FH_Low) );
  1430. TRACE ( TL_V, TM_Send, (" fragmented Header lf %x EtherType %x",
  1431. pHeader ->u.FirstQuadlet_FirstFragment.FH_lf ,
  1432. pHeader ->u.FirstQuadlet_FirstFragment.FH_EtherType ) );
  1433. //
  1434. // temporaty debug spew
  1435. //
  1436. TRACE (TL_V, TM_Send, (" copy Header at %x, Orig Header at %x",
  1437. &pHeader ->u.FirstQuadlet_FirstFragment,
  1438. pFragment->UnfragmentedHeader) );
  1439. //
  1440. // Initialize the fragmentation structure with packet's first ndis buffer
  1441. //
  1442. pFragment->pSourceAddressInNdisBuffer = NdisBufferVirtualAddress (pStartNdisBuffer);
  1443. if (pFragment->pSourceAddressInNdisBuffer == NULL)
  1444. {
  1445. NdisStatus = NDIS_STATUS_FAILURE;
  1446. }
  1447. //
  1448. // Set up the copy source . The first four bytes of data contain the unfragmented header.
  1449. // We need to skip past these bytes and start the copy from the next byte
  1450. //
  1451. pFragment->pSourceAddressInNdisBuffer = (PVOID) ((ULONG_PTR)pFragment->pSourceAddressInNdisBuffer +
  1452. sizeof (NDIS1394_UNFRAGMENTED_HEADER) );
  1453. pFragment->NdisBufferLengthRemaining = NdisBufferLength (pStartNdisBuffer) - sizeof (NDIS1394_UNFRAGMENTED_HEADER);
  1454. pFragment->pCurrNdisBuffer = pStartNdisBuffer;
  1455. //
  1456. // Set up the destination
  1457. //
  1458. pFragment->pStartFragment = (PVOID)((ULONG_PTR)pFragment->pLookasideListBuffer
  1459. + (pFragment->NumFragmentsNeeded*sizeof(IRB)));
  1460. ((PLOOKASIDE_BUFFER_HEADER)pFragment->pLookasideListBuffer)->pStartOfData = pFragment->pStartFragment;
  1461. pFragment->pStartOfFirstFragment = pFragment->pStartFragment ;
  1462. pFragment->CurrFragmentNum = 0;
  1463. pFragment->lf = lf_FirstFragment;
  1464. //
  1465. // The First IRB will reside at the end of the lookaside-header
  1466. //
  1467. pFragment->pCurrentIrb = &((PUNFRAGMENTED_BUFFER)pFragment->pLookasideListBuffer)->Irb;
  1468. TRACE( TL_T, TM_Send, ( " pStartFragment %x, pFragment %x,NumFragmentsNeeded %x,MaxFragmentLength %x ",
  1469. pFragment->pStartFragment,
  1470. pFragment->NumFragmentsNeeded,
  1471. pFragment->MaxFragmentLength) );
  1472. NdisStatus = NDIS_STATUS_SUCCESS;
  1473. } while (FALSE);
  1474. TRACE( TL_T, TM_Send, ( " <== nicFirstFragmentInitialization NdisStautus %x, pFragment %x, ",
  1475. NdisStatus, pFragment) );
  1476. return NdisStatus;
  1477. }
  1478. VOID
  1479. nicAddFragmentHeader (
  1480. IN PVOID pStartFragmentData,
  1481. IN PFRAGMENTATION_STRUCTURE pFragmentStructure,
  1482. IN ULONG FragmentLength
  1483. )
  1484. // Function Description:
  1485. // Copies the Fragment header over after byteswapping it.
  1486. // For the the first time, the ether type and so forth is already initialized and waiting to be copied.
  1487. // This funciotn also sets up the values for the next invocation of this function
  1488. // Arguments
  1489. // pStartFragmentData - Start of the fragment. Header goes after the gasp header if necessary .
  1490. // pFragmentationHeader - Header to copy over
  1491. // fIsFirstFragment - TRUE if this is the first fragment and needs a special header
  1492. // Return Value:
  1493. // None
  1494. //
  1495. {
  1496. PNDIS1394_FRAGMENT_HEADER pDestFragmentHeader = (PNDIS1394_FRAGMENT_HEADER)pStartFragmentData;
  1497. PNDIS1394_FRAGMENT_HEADER pSrcFragmentHeader = &pFragmentStructure->FragmentationHeader;
  1498. TRACE( TL_T, TM_Send, ( "==> nicAddFragmentHeader pStartFragmentData %x, pFragmentationHeader %x, , FragmentLength %x, lf %x",
  1499. pStartFragmentData , pSrcFragmentHeader , FragmentLength, pFragmentStructure->lf) );
  1500. if (pFragmentStructure->AsyncOp == AsyncStream)
  1501. {
  1502. //
  1503. // First Copy the GaspHeader
  1504. //
  1505. NdisMoveMemory (pStartFragmentData ,
  1506. &pFragmentStructure->pAdapter->GaspHeader,
  1507. sizeof (GASP_HEADER) );
  1508. //
  1509. // Increment the pointers so that the fragment header will be copied after the gasp header
  1510. //
  1511. pStartFragmentData = (PVOID) ((ULONG_PTR) pStartFragmentData + sizeof (GASP_HEADER) );
  1512. pDestFragmentHeader = (PVOID) pStartFragmentData;
  1513. TRACE( TL_T, TM_Send, ( " nicAddFragmentHeader Added Gasp Header from %x ",
  1514. pFragmentStructure->pAdapter->GaspHeader) );
  1515. }
  1516. //
  1517. // Sanity check , are we overwriting anybody ?
  1518. //
  1519. ASSERT (*(PULONG)pDestFragmentHeader == 0);
  1520. ASSERT (*(PULONG)pFragmentStructure->pCurrentIrb == 0);
  1521. TRACE( TL_V, TM_Send, ( " pSrcFragmentHeader Hi %x,Lo %x",
  1522. pSrcFragmentHeader->u.FH_High, pSrcFragmentHeader->u1.FH_Low) );
  1523. //
  1524. // Copy over the lf;
  1525. //
  1526. pSrcFragmentHeader->u.FirstQuadlet.FH_lf = pFragmentStructure->lf;
  1527. //
  1528. // Now copy over the 8 bytes of the fragment header and byteswap them into big endian
  1529. //
  1530. pDestFragmentHeader->u.FH_High = SWAPBYTES_ULONG ( pSrcFragmentHeader->u.FH_High);
  1531. pDestFragmentHeader->u1.FH_Low = SWAPBYTES_ULONG ( pSrcFragmentHeader->u1.FH_Low);
  1532. TRACE( TL_V, TM_Send, ( " Fragment Offset %x", pSrcFragmentHeader->u.FirstQuadlet.FH_fragment_offset ) );
  1533. //
  1534. // PREPARE the FRAGMENT STRUCTURE FOR THE NEXT ITERATION
  1535. //
  1536. //
  1537. // Set the first fragment completed flag to true and set up the header for the next fragment
  1538. //
  1539. if (pFragmentStructure->lf == lf_FirstFragment)
  1540. {
  1541. pFragmentStructure->lf = lf_InteriorFragment;
  1542. pSrcFragmentHeader->u.FirstQuadlet.FH_fragment_offset = 0;
  1543. }
  1544. //
  1545. // Increase the fragment offset for use in the next fragment
  1546. //
  1547. pSrcFragmentHeader->u.FirstQuadlet.FH_fragment_offset += FragmentLength;
  1548. TRACE( TL_T, TM_Send, ( "<== nicAddFragmentHeader lf %x", pFragmentStructure->lf) );
  1549. }
  1550. NDIS_STATUS
  1551. AsyncStreamSendPacketsHandler (
  1552. IN PVCCB pVc,
  1553. IN PNDIS_PACKET pPacket
  1554. )
  1555. // Function Description:
  1556. // This function is used to send packets to the bus
  1557. // via the async stream irp. the Ndis Packet is copied
  1558. // to locally owned buffers and mdls and then sent
  1559. // down to the bus driver
  1560. //
  1561. // This code is borrowed heavily from the AsyncStreamIrp code below
  1562. //
  1563. // Arguments
  1564. // pChannelVc - The Vc which needs to send the packets
  1565. // pPacket - the packet being transmitted
  1566. //
  1567. // Return Value:
  1568. // NdisStatus - if all allocations and irp operations complete
  1569. // successfully, and the i/o will be completed asynchronously
  1570. //
  1571. {
  1572. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  1573. NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;
  1574. PCHANNEL_VCCB pChannelVc = (PCHANNEL_VCCB) pVc;
  1575. BOOLEAN fVcActive = TRUE;
  1576. PMDL pMyMdl = NULL;
  1577. PIRB pMyIrb = NULL;
  1578. PIRP pMyIrp = NULL;
  1579. ULONG PacketLength = 0;
  1580. PVOID pLookasideListBuffer = NULL;
  1581. PADAPTERCB pAdapter = NULL;
  1582. PNDIS_BUFFER pStartNdisBuffer = NULL ;
  1583. PVOID pStartPacketData= NULL ;
  1584. PNIC_NPAGED_LOOKASIDE_LIST pLookasideList = NULL;
  1585. PLOOKASIDE_BUFFER_HEADER pLookasideHeader = NULL;
  1586. ULONG NumFragmentsNeeded = 0;
  1587. FRAGMENTATION_STRUCTURE Fragment;
  1588. STORE_CURRENT_IRQL;
  1589. NdisZeroMemory (&Fragment, sizeof (FRAGMENTATION_STRUCTURE));
  1590. TRACE( TL_T, TM_Send, ( "==>AsyncStreamSendPacketsHandler , pVc %x, pPacket %x",
  1591. pChannelVc , pPacket ) );
  1592. pAdapter = pChannelVc->Hdr.pAF->pAdapter;
  1593. //
  1594. // This reference will either be dereferenced below in a call to FreeSendPacketDataStructure
  1595. // below or a call to FreeSendPacketDataStructure made from the Irp's completion routine
  1596. //
  1597. do
  1598. {
  1599. VC_ACQUIRE_LOCK (pVc);
  1600. //
  1601. // Make sure that the Vc is Activated and that no close calls
  1602. // are pending or that we have already completed a close call
  1603. //
  1604. if ( VC_ACTIVE (pChannelVc) == FALSE || ADAPTER_ACTIVE(pAdapter) == FALSE)
  1605. {
  1606. fVcActive = FALSE;
  1607. }
  1608. if (VC_TEST_FLAG( pChannelVc, VCBF_GenerationWorkItem) == TRUE)
  1609. {
  1610. TRACE( TL_N, TM_Send, ( "AsyncStreamSendPacketHandler, Getting a new Gen, Fail send ") );
  1611. fVcActive = FALSE;
  1612. }
  1613. if (fVcActive == TRUE)
  1614. {
  1615. nicReferenceCall (pVc, "AsyncStreamSendPacketsHandler");
  1616. }
  1617. VC_RELEASE_LOCK (pVc);
  1618. if (fVcActive == FALSE)
  1619. {
  1620. TRACE( TL_N, TM_Send, ( "AsyncStreamSendPacketHandler, VC Not Active VC %x , Flag %x", pVc, pVc->Hdr.ulFlags ) );
  1621. NdisStatus = NDIS_STATUS_FAILURE;
  1622. break;
  1623. }
  1624. //
  1625. // Copy NdisBuffer in Packet to Local Memory and get an Mdl that points
  1626. // to this memory (we get 1 Mdl only)
  1627. NdisQueryPacket( pPacket,
  1628. NULL,
  1629. NULL,
  1630. NULL,
  1631. &PacketLength);
  1632. ASSERT (pPacket->Private.Head != NULL);
  1633. pStartNdisBuffer = pPacket->Private.Head;
  1634. pStartPacketData = nicNdisBufferVirtualAddress (pStartNdisBuffer);
  1635. if (pStartPacketData == NULL)
  1636. {
  1637. NdisStatus = NDIS_STATUS_RESOURCES;
  1638. TRACE( TL_N, TM_Send, ( "AsyncStreamSendPacketHandler, pStartPacketData ") );
  1639. break;
  1640. }
  1641. TRACE( TL_V, TM_Send, ( "PacketLength %x", PacketLength) );
  1642. NumFragmentsNeeded = nicNumFragmentsNeeded (PacketLength,
  1643. pChannelVc->Hdr.MaxPayload,
  1644. sizeof (NDIS1394_FRAGMENT_HEADER) + ISOCH_PREFIX_LENGTH );
  1645. TRACE( TL_V, TM_Send, ( "NumFragments %x, pVc->MaxSendSize",
  1646. NumFragmentsNeeded,pVc->Hdr.MaxPayload) );
  1647. //
  1648. // first choose the lookaside list
  1649. //
  1650. //
  1651. if (PacketLength < PAYLOAD_100)
  1652. {
  1653. pLookasideList = &pAdapter->SendLookasideList100;
  1654. TRACE( TL_V, TM_Send, ( " PAYLOAD_100 Lookaside List %x",
  1655. &pAdapter->SendLookasideList100) );
  1656. }
  1657. else
  1658. if (PacketLength < PAYLOAD_2K)
  1659. {
  1660. pLookasideList = &pAdapter->SendLookasideList2K;
  1661. TRACE( TL_V, TM_Send, ( " PAYLOAD_2K Lookaside List %x",
  1662. &pAdapter->SendLookasideList2K) );
  1663. }
  1664. else
  1665. {
  1666. //
  1667. // Add code for local allocation
  1668. //
  1669. ASSERT (0);
  1670. NdisStatus = NDIS_STATUS_FAILURE;
  1671. break;
  1672. }
  1673. //
  1674. // are we going to fragment
  1675. //
  1676. ASSERT (pLookasideList != NULL)
  1677. //
  1678. // We are not going to fragment. Optimize this path
  1679. //
  1680. pLookasideListBuffer = nicGetLookasideBuffer (pLookasideList);
  1681. if (pLookasideListBuffer == NULL )
  1682. {
  1683. NdisStatus = NDIS_STATUS_FAILURE;
  1684. BREAK (TM_Send, ("nicGetLookasideBuffer FAILED") );
  1685. }
  1686. //
  1687. // Dump out the packet if necessary
  1688. //
  1689. nicDumpPkt (pPacket, "AsyncWriteStreamPacketsHandler");
  1690. //
  1691. // Initialize the header with relevant information that the send complete
  1692. // will need
  1693. //
  1694. pLookasideHeader = (PLOOKASIDE_BUFFER_HEADER)pLookasideListBuffer;
  1695. pLookasideHeader->IsFragmented = FALSE; // Default
  1696. pLookasideHeader->FragmentsGenerated = 0;
  1697. pLookasideHeader->pLookasideList = pLookasideList;
  1698. pLookasideHeader->pNdisPacket = pPacket;
  1699. pLookasideHeader->pVc =(PVCCB)pVc;
  1700. pLookasideHeader->AsyncOp = AsyncStream;
  1701. pLookasideHeader->OutstandingFragments = NumFragmentsNeeded ;
  1702. //
  1703. // Initialize the Fragment structure
  1704. //
  1705. //
  1706. // Do we fragment or not. Base it on the MaxPayload field
  1707. //
  1708. TRACE( TL_V, TM_Send, ( " Fragment PacketLength %x, pVc->MaxPayload %x ",
  1709. PacketLength ,pVc->Hdr.MaxPayload) );
  1710. //
  1711. // Do we need to fragment. Use the number of fragments generated to figure it out
  1712. //
  1713. if (NumFragmentsNeeded == 1)
  1714. {
  1715. //
  1716. // No need to fragment here. We will use the UNFRAGMENTED Layout
  1717. //
  1718. // First Get a local buffer from our lookaside list
  1719. //
  1720. PUNFRAGMENTED_BUFFER pUnfragmentedBuffer = (PUNFRAGMENTED_BUFFER )pLookasideHeader;
  1721. PPACKET_FORMAT pDestination = (PPACKET_FORMAT)&pUnfragmentedBuffer->Data[0];
  1722. //
  1723. // Add the gasp header
  1724. //
  1725. NdisMoveMemory ((PVOID)&pDestination->AsyncStreamNonFragmented.GaspHeader,
  1726. &pAdapter->GaspHeader,
  1727. sizeof (GASP_HEADER) );
  1728. //
  1729. // copy the data over, to the location just after the Gasp Header
  1730. // In the unfragmented case, the packet already has the correct header
  1731. //
  1732. NdisStatus = nicCopyNdisBufferChainToBuffer (pStartNdisBuffer,
  1733. (PVOID)&pDestination->AsyncStreamNonFragmented.NonFragmentedHeader,
  1734. pLookasideList->MaxSendSize);
  1735. if (NdisStatus != NDIS_STATUS_SUCCESS)
  1736. {
  1737. BREAK ( TM_Send, ( " AsyncStreamSendPacketHandler, nicCopyNdisPacketToUnfragmentedBuffer Failed ") );
  1738. }
  1739. ASSERT (pLookasideListBuffer != NULL);
  1740. //
  1741. // Initialize all the variable needed by the Next section of the code.
  1742. // This deals with setting up the Mdl and the IRB
  1743. //
  1744. pStartNdisBuffer = NULL;
  1745. Fragment.pStartFragment = (PVOID)pDestination;
  1746. Fragment.FragmentLength = PacketLength + sizeof (GASP_HEADER);
  1747. Fragment.pCurrNdisBuffer = NULL;
  1748. pLookasideHeader->FragmentsGenerated = 1;
  1749. pLookasideHeader->IsFragmented = FALSE;
  1750. }
  1751. else
  1752. {
  1753. //
  1754. // We need to fragment
  1755. //
  1756. ULONG Dgl = NdisInterlockedIncrement(&pAdapter->dgl);
  1757. //
  1758. // Initialize the fragment header. The unfragmented code path
  1759. // does not care about these fields
  1760. //
  1761. Fragment.TxHeaderSize = sizeof (NDIS1394_FRAGMENT_HEADER) + sizeof (GASP_HEADER);
  1762. Fragment.AsyncOp = AsyncStream;
  1763. Fragment.pLookasideList = pLookasideList;
  1764. Fragment.pAdapter = pAdapter;
  1765. Fragment.pLookasideListBuffer = pLookasideListBuffer;
  1766. Fragment.IPDatagramLength = (USHORT)PacketLength - sizeof (NDIS1394_UNFRAGMENTED_HEADER);
  1767. Fragment.MaxFragmentLength = pChannelVc->Hdr.MaxPayload;
  1768. Fragment.NumFragmentsNeeded = NumFragmentsNeeded;
  1769. //
  1770. // Allocate from the fragmented pool and initialize the fragment header structure
  1771. //
  1772. NdisStatus = nicFirstFragmentInitialization (pPacket->Private.Head,
  1773. Dgl,
  1774. &Fragment);
  1775. if (pLookasideListBuffer == NULL || NdisStatus != NDIS_STATUS_SUCCESS)
  1776. {
  1777. BREAK (TM_Send, (" AsyncStreamSendPacketsHandler: nicFirstFragmentInitialization : FAILED" )) ;
  1778. }
  1779. ASSERT (pLookasideListBuffer != NULL);
  1780. pLookasideHeader->IsFragmented = TRUE;
  1781. }
  1782. //
  1783. // Now begin the loop which will send n fragments
  1784. //
  1785. do
  1786. {
  1787. //
  1788. // Do we need to fragment. If so , extract one fragment out of the NdisPacket
  1789. //
  1790. if (pLookasideHeader->IsFragmented == TRUE )
  1791. {
  1792. //
  1793. // We copy one fragment over and this will allocate the lookaside list
  1794. //
  1795. NdisStatus = nicCopyOneFragment (&Fragment);
  1796. if (NDIS_STATUS_SUCCESS != NdisStatus)
  1797. {
  1798. BREAK ( TM_Send, ( " AsyncStreamSendPacketHandler, nicCopyOneFragment Failed ") );
  1799. }
  1800. //
  1801. // Get the pointer to the Irb here. and set it up for the next time
  1802. //
  1803. //
  1804. pMyIrb = Fragment.pCurrentIrb;
  1805. Fragment.pCurrentIrb = (PIRB)((ULONG_PTR)Fragment.pCurrentIrb + sizeof (IRB) );
  1806. }
  1807. else
  1808. {
  1809. //
  1810. // No Curr NdisBuffer as this packet was never fragmented.
  1811. //
  1812. ASSERT (pLookasideHeader->IsFragmented == FALSE);
  1813. pMyIrb = &((PUNFRAGMENTED_BUFFER )pLookasideHeader)->Irb;
  1814. }
  1815. //
  1816. // At this point we have one fragment that needs to be transmitted.
  1817. // Data structures have been updated to set up the MDL and the IRB
  1818. //
  1819. NdisStatus = nicGetMdl (Fragment.FragmentLength ,
  1820. Fragment.pStartFragment ,
  1821. &pMyMdl);
  1822. if (NdisStatus != NDIS_STATUS_SUCCESS)
  1823. {
  1824. BREAK ( TM_Send, ( " AsyncStreamSendPacketHandler, nicCopyNdisBufferChainToBuffer Failed ") );
  1825. }
  1826. nicIncChannelSendMdl()
  1827. //
  1828. // Fill in the Irb with the correct values from the VC
  1829. // Stuff we need to add to the send VC - BlockSize,Generation
  1830. //
  1831. nicInitAsyncStreamIrb((PCHANNEL_VCCB)pVc, pMyMdl, pMyIrb);
  1832. //
  1833. // Get a free Irp
  1834. //
  1835. NdisStatus = nicGetIrp (pAdapter->pNextDeviceObject, &pMyIrp);
  1836. if (NdisStatus != NDIS_STATUS_SUCCESS)
  1837. {
  1838. break;
  1839. }
  1840. //
  1841. // At this point, we have a guarantee that the Completion routine will be called
  1842. //
  1843. //
  1844. // Dump the Fragment
  1845. //
  1846. nicDumpMdl (pMyMdl , 0, "AsyncStream Fragment");
  1847. NIC1394_LOG_PKT(
  1848. pAdapter,
  1849. NIC1394_LOGFLAGS_SEND_CHANNEL,
  1850. pAdapter->BCRData.LocalNodeNumber, // SourceID
  1851. pChannelVc->Channel,
  1852. Fragment.pStartFragment,
  1853. Fragment.FragmentLength
  1854. );
  1855. //
  1856. // This function implements the common functionality to be implemented by
  1857. // all other send/recv cals to IoCallDriver
  1858. //
  1859. //
  1860. // We IGNORE the NtStatus as the completion handler will be called
  1861. //
  1862. nicIncrementBusSends(pVc);
  1863. NtStatus = nicSubmitIrp(pAdapter->pNextDeviceObject,
  1864. pMyIrp,
  1865. pMyIrb,
  1866. AsyncWriteStreamSendComplete,
  1867. (PVOID)pLookasideListBuffer);
  1868. TRACE( TL_V, TM_Send, ( " pCurrNdisBuffer %x, NdisStatus %x ", Fragment.pCurrNdisBuffer , NdisStatus ) );
  1869. } while (Fragment.pCurrNdisBuffer != NULL && NdisStatus == NDIS_STATUS_SUCCESS);
  1870. } while (FALSE);
  1871. //
  1872. // DO NOT touch the packet if status == NDIS_STATUS_SUCCESS.
  1873. //
  1874. //
  1875. // CleanUp if any of the allocations failed. We do not have a pointer
  1876. // to the LocalBuffer (it is embedded in the Mdl) so it remains NULL
  1877. //
  1878. // NdisStatus != Success means that we never got to nicSubmitIrp
  1879. //
  1880. if (NdisStatus != NDIS_STATUS_SUCCESS)
  1881. {
  1882. ASSERT (pMyIrp == NULL);
  1883. //
  1884. // fVc Active makes sure that we actually got around to allocating
  1885. // and referencing structures
  1886. //
  1887. if (fVcActive == TRUE)
  1888. {
  1889. if (pLookasideListBuffer != NULL)
  1890. {
  1891. //
  1892. // Complete this fragment, as we never submit'd the IRP to
  1893. // the 1394 bus driver
  1894. //
  1895. AsyncWriteStreamSendComplete(NULL, // PDO
  1896. NULL,
  1897. pLookasideListBuffer);
  1898. NdisStatus =NDIS_STATUS_SUCCESS;
  1899. }
  1900. else
  1901. {
  1902. //
  1903. // This thread needs to decrement the refcounts as
  1904. // AsyncWriteStreamSendComplete was not called
  1905. //
  1906. nicDereferenceCall ((PVCCB) pVc, "AsyncStreamSendPacketsHandler");
  1907. }
  1908. }
  1909. }
  1910. TRACE( TL_T, TM_Send, ( "<==AsyncStreamSendPacketHandler, NdisStatus %x", NdisStatus ) );
  1911. MATCH_IRQL;
  1912. //
  1913. // Make sure this is NDIS_STATUS_PENDING if the Irp was sent down or
  1914. // AsyncWriteStreamSendCOmplete was called.
  1915. //
  1916. return NdisStatus;
  1917. }
  1918. NDIS_STATUS
  1919. nicEthernetVcSend(
  1920. IN PVCCB pVc,
  1921. IN PNDIS_PACKET pPacket
  1922. )
  1923. /*++
  1924. Routine Description:
  1925. reroutes all sends on this VC as an CL receive
  1926. It allocates a packet, moves the NDIS buffer chain into the new packet
  1927. , sets status to Resources (to force a copy) and indicates the packet upto
  1928. the protocols.
  1929. Arguments:
  1930. pVc Ethernet VC on which this Send came in.
  1931. pPacket - which needs to be indicated up to the protocols.
  1932. Return Value:
  1933. Failure if the call to Allocate an NDIS packet fails.
  1934. --*/
  1935. {
  1936. PETHERNET_VCCB pEthernetVc = (PETHERNET_VCCB)pVc;
  1937. PADAPTERCB pAdapter = pVc->Hdr.pAF->pAdapter;
  1938. BOOLEAN fVcActive = FALSE;
  1939. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  1940. PNDIS_PACKET pMyPacket = NULL;
  1941. NDIS_STATUS IndicatedStatus= NDIS_STATUS_FAILURE;
  1942. PPKT_CONTEXT pPktContext = NULL;
  1943. TRACE( TL_T, TM_Send, ( "==>nicEthernetVcSend, pVc %x, pPacket %x",
  1944. pVc , pPacket ) );
  1945. do
  1946. {
  1947. ADAPTER_ACQUIRE_LOCK (pAdapter);
  1948. if (VC_ACTIVE (pEthernetVc)==TRUE)
  1949. {
  1950. fVcActive = TRUE;
  1951. nicReferenceCall (pVc, "nicEthernetVcSend" ) ;
  1952. }
  1953. ADAPTER_RELEASE_LOCK (pAdapter);
  1954. if (fVcActive == FALSE)
  1955. {
  1956. NdisStatus = NDIS_STATUS_FAILURE;
  1957. break;
  1958. }
  1959. nicAllocatePacket (&NdisStatus,
  1960. &pMyPacket ,
  1961. &pEthernetVc->PacketPool );
  1962. if (NdisStatus != NDIS_STATUS_SUCCESS || pMyPacket == NULL)
  1963. {
  1964. pMyPacket = NULL;
  1965. BREAK (TM_Send, "Ethernet VC - AllocatePacket failed" ) ;
  1966. }
  1967. pMyPacket->Private.Head = pPacket->Private.Head;
  1968. pMyPacket->Private.Tail = pPacket->Private.Tail;
  1969. IndicatedStatus = NDIS_STATUS_RESOURCES;
  1970. NDIS_SET_PACKET_STATUS(pMyPacket, IndicatedStatus);
  1971. //
  1972. // Set up the context
  1973. //
  1974. pPktContext = (PPKT_CONTEXT)&pMyPacket->MiniportReservedEx;
  1975. pPktContext->EthernetSend.pOrigPacket = pPacket;
  1976. //
  1977. // Dump the packet
  1978. //
  1979. {
  1980. nicDumpPkt (pMyPacket, "Conn Less Rcv ");
  1981. }
  1982. //
  1983. // Now indicate the packet
  1984. //
  1985. //
  1986. // Bluff the OOB Size. To get past an assert on debug Ndis
  1987. //
  1988. NDIS_SET_PACKET_HEADER_SIZE (pMyPacket, 14);
  1989. NdisMIndicateReceivePacket (pAdapter->MiniportAdapterHandle,
  1990. &pMyPacket,
  1991. 1);
  1992. pPktContext = (PPKT_CONTEXT)&pMyPacket->MiniportReservedEx;
  1993. ASSERT ( pPacket == pPktContext->EthernetSend.pOrigPacket );
  1994. nicMpCoSendComplete (NDIS_STATUS_SUCCESS,
  1995. pVc,
  1996. pPacket);
  1997. //
  1998. // We have successfully pended the Io/
  1999. // Now the completion routine will be called
  2000. //
  2001. NdisStatus = NDIS_STATUS_SUCCESS;
  2002. } while (FALSE);
  2003. if (pMyPacket != NULL)
  2004. {
  2005. //
  2006. // Free the locally allcoate packet
  2007. //
  2008. nicFreePacket(pMyPacket, &pEthernetVc->PacketPool);
  2009. }
  2010. if (fVcActive == TRUE)
  2011. {
  2012. nicDereferenceCall (pVc, "nicEthernetVcSend" ) ;
  2013. }
  2014. TRACE( TL_T, TM_Send, ( "<==nicEthernetVcSend, ") );
  2015. return NdisStatus;
  2016. }
  2017. VOID
  2018. nicGetGenerationWorkItem(
  2019. NDIS_WORK_ITEM* pGetGenerationWorkItem,
  2020. IN PVOID Context
  2021. )
  2022. // Function Description:
  2023. // Work Item used to submit a Get Generation IRP at Passive Level
  2024. //
  2025. // Arguments
  2026. //
  2027. // Return Value:
  2028. // Generation -
  2029. {
  2030. PVCCB pVc = (PVCCB) Context;
  2031. PADAPTERCB pAdapter = pVc->Hdr.pAF->pAdapter;
  2032. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  2033. UINT Generation = 0;
  2034. TRACE( TL_T, TM_Mp, ( "==>nicGetGenerationWorkItem, pVc", Context ) );
  2035. NdisStatus = nicGetGenerationCount (pAdapter , &Generation);
  2036. //
  2037. // Update the generation
  2038. //
  2039. VC_ACQUIRE_LOCK (pVc);
  2040. if (NdisStatus == NDIS_STATUS_SUCCESS && Generation > *pVc->Hdr.pGeneration )
  2041. {
  2042. pAdapter->Generation = Generation;
  2043. }
  2044. VC_CLEAR_FLAGS(pVc, VCBF_GenerationWorkItem);
  2045. VC_RELEASE_LOCK (pVc);
  2046. // Dereference the call, this will allow the close call to complete. Do not touch VC after this.
  2047. //
  2048. nicDereferenceCall(pVc, "nicSendFailureInvalidGeneration");
  2049. TRACE( TL_T, TM_Mp, ( "<==nicGetGenerationWorkItem, Gen %x", Generation) );
  2050. FREE_NONPAGED (pGetGenerationWorkItem);
  2051. NdisInterlockedDecrement(&pAdapter->OutstandingWorkItems);
  2052. }
  2053. VOID
  2054. nicUpdatePacketState (
  2055. IN PNDIS_PACKET pPacket,
  2056. IN ULONG Tag
  2057. )
  2058. /*++
  2059. Routine Description:
  2060. Validates and then updates that packet tag. So we can heep track of the packet
  2061. Arguments:
  2062. Return Value:
  2063. --*/
  2064. {
  2065. switch (Tag)
  2066. {
  2067. case NIC1394_TAG_COMPLETED:
  2068. {
  2069. *(PULONG)(&pPacket->MiniportReserved[0]) = NIC1394_TAG_COMPLETED;
  2070. break;
  2071. }
  2072. case NIC1394_TAG_IN_SEND:
  2073. {
  2074. *(PULONG)(&pPacket->MiniportReserved[0]) = NIC1394_TAG_IN_SEND;
  2075. break;
  2076. }
  2077. default:
  2078. {
  2079. ASSERT (!"Invalid Tag on NdisPacket");
  2080. }
  2081. }
  2082. }
  2083. VOID
  2084. nicMpCoSendComplete (
  2085. NDIS_STATUS NdisStatus,
  2086. PVCCB pVc,
  2087. PNDIS_PACKET pPacket
  2088. )
  2089. /*++
  2090. Routine Description:
  2091. Wrapper function around NdisMCoSendComplete
  2092. Arguments:
  2093. Return Value:
  2094. --*/
  2095. {
  2096. nicIncrementSendCompletes (pVc);
  2097. if (NdisStatus == NDIS_STATUS_SUCCESS)
  2098. {
  2099. nicIncrementVcSendPktCount(pVc, pPacket);
  2100. }
  2101. else
  2102. {
  2103. nicIncrementVcSendFailures (pVc, pPacket);
  2104. }
  2105. nicUpdatePacketState (pPacket, NIC1394_TAG_COMPLETED);
  2106. NdisMCoSendComplete(NdisStatus,
  2107. pVc->Hdr.NdisVcHandle,
  2108. pPacket);
  2109. }
  2110. UINT
  2111. nicNumFragmentsNeeded (
  2112. UINT PacketLength ,
  2113. UINT MaxPayload,
  2114. UINT FragmentOverhead
  2115. )
  2116. /*++
  2117. Routine Description:
  2118. Now account for the Fragment headers as well. A fragment header will be added
  2119. at the head of each fragment. The Unfragmented header at the head of the data
  2120. will be removed
  2121. Arguments:
  2122. FragmentOverhead - the size of the fragment header, in the asyncstream it includes the gasp header+fragment header.
  2123. for asyncwrite it is just the fragmentation header
  2124. Return Value:
  2125. --*/
  2126. {
  2127. UINT NewPacketSize;
  2128. UINT TotalCapacitySoFar;
  2129. UINT NumFragmentsNeeded ;
  2130. ASSERT (PacketLength != 0 );
  2131. ASSERT (MaxPayload != 0) ;
  2132. ASSERT (FragmentOverhead != 0);
  2133. //
  2134. // This division takes care of the case where PacketLength
  2135. // is an integral multiple of the MaxPayload. Since we add 1 to the fragment
  2136. // it takes care of the overhead added by the fragment headers
  2137. //
  2138. NumFragmentsNeeded = (PacketLength / MaxPayload) + 1;
  2139. //
  2140. // If we add the fragment and gasp header to our fragments, we
  2141. // might need another fragment due to an overflow
  2142. //
  2143. //
  2144. // Calculate the new packet size after fragmentation
  2145. //
  2146. {
  2147. //
  2148. // Add the length of the fragment headers
  2149. //
  2150. NewPacketSize = PacketLength + (NumFragmentsNeeded * FragmentOverhead);
  2151. //
  2152. // Now remove the default non-fragment header
  2153. //
  2154. NewPacketSize -= sizeof (NDIS1394_UNFRAGMENTED_HEADER) ;
  2155. }
  2156. //
  2157. //
  2158. //
  2159. TotalCapacitySoFar = NumFragmentsNeeded * MaxPayload;
  2160. if ( NewPacketSize > TotalCapacitySoFar)
  2161. {
  2162. //
  2163. // We'll need one more fragment
  2164. //
  2165. NumFragmentsNeeded ++;
  2166. }
  2167. return NumFragmentsNeeded ;
  2168. }
  2169. VOID
  2170. nicCheckForEthArps (
  2171. IN PNDIS_PACKET pPkt
  2172. )
  2173. /*++
  2174. Routine Description:
  2175. It will print the pkt if an eth arp or arp response goes
  2176. through nic1394
  2177. Arguments:
  2178. Return Value:
  2179. --*/
  2180. {
  2181. PNDIS_BUFFER pBuffer;
  2182. ULONG Len;
  2183. ENetHeader* pENetHeader = NULL;
  2184. PETH_ARP_PKT pArp = NULL;
  2185. USHORT PacketType;
  2186. USHORT opcode;
  2187. extern ULONG g_ulDumpEthPacket ;
  2188. do
  2189. {
  2190. if (g_ulDumpEthPacket == 0)
  2191. {
  2192. break;
  2193. }
  2194. pBuffer = pPkt->Private.Head;
  2195. Len = NdisBufferLength (pBuffer);
  2196. if (Len < sizeof (ENetHeader) )
  2197. {
  2198. ASSERT (Len >= sizeof (ENetHeader) );
  2199. break;
  2200. }
  2201. pENetHeader = (ENetHeader*) NdisBufferVirtualAddress (pBuffer);
  2202. if (pENetHeader == NULL)
  2203. {
  2204. ASSERT ( pENetHeader != NULL);
  2205. break;
  2206. }
  2207. PacketType = ntohs (pENetHeader->eh_type);
  2208. if (PacketType == ARP_ETH_ETYPE_IP)
  2209. {
  2210. break;
  2211. }
  2212. if (PacketType == ARP_ETH_ETYPE_ARP)
  2213. {
  2214. DbgPrint ("Arp Pkt - ");
  2215. }
  2216. pArp = (ETH_ARP_PKT*)pENetHeader;
  2217. opcode = ntohs(pArp->opcode);
  2218. if (opcode == ARP_ETH_REQUEST )
  2219. {
  2220. DbgPrint ("Request ");
  2221. }
  2222. else if (opcode == ARP_ETH_RESPONSE )
  2223. {
  2224. DbgPrint ("Response ");
  2225. }
  2226. else
  2227. {
  2228. break;
  2229. }
  2230. // Print the packet
  2231. DbgPrint("\n");
  2232. {
  2233. ENetAddr Addr;
  2234. Addr = pArp->sender_hw_address;
  2235. DbgPrint ("Sender Hw Addr %x %x %x %x %x %x \n",
  2236. Addr.addr[0],
  2237. Addr.addr[1],
  2238. Addr.addr[2],
  2239. Addr.addr[3],
  2240. Addr.addr[4],
  2241. Addr.addr[5]);
  2242. DbgPrint ("Ip Addr %x\n",pArp->sender_IP_address);
  2243. Addr = pArp->target_hw_address;
  2244. DbgPrint ("Target Hw Addr %x %x %x %x %x %x \n",
  2245. Addr.addr[0],
  2246. Addr.addr[1],
  2247. Addr.addr[2],
  2248. Addr.addr[3],
  2249. Addr.addr[4],
  2250. Addr.addr[5]);
  2251. DbgPrint ("Ip Addr %x\n",pArp->target_IP_address);
  2252. }
  2253. } while (FALSE);
  2254. }