Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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