Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5909 lines
153 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. miniport.c
  5. Abstract:
  6. ATM Ethernet PVC driver
  7. Author:
  8. ADube - created
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. //--------------------------------------------------------------------------------
  14. // //
  15. // Global Variables used by miniports //
  16. // //
  17. //--------------------------------------------------------------------------------
  18. static
  19. NDIS_OID EthernetSupportedOids[] = {
  20. OID_GEN_SUPPORTED_LIST,
  21. OID_GEN_HARDWARE_STATUS,
  22. OID_GEN_MEDIA_CONNECT_STATUS,
  23. OID_GEN_MEDIA_SUPPORTED,
  24. OID_GEN_MEDIA_IN_USE,
  25. OID_GEN_MAXIMUM_LOOKAHEAD,
  26. OID_GEN_MAXIMUM_FRAME_SIZE,
  27. OID_GEN_MAXIMUM_TOTAL_SIZE,
  28. OID_GEN_MAC_OPTIONS,
  29. OID_GEN_PROTOCOL_OPTIONS,
  30. OID_GEN_LINK_SPEED,
  31. OID_GEN_TRANSMIT_BUFFER_SPACE,
  32. OID_GEN_RECEIVE_BUFFER_SPACE,
  33. OID_GEN_TRANSMIT_BLOCK_SIZE,
  34. OID_GEN_RECEIVE_BLOCK_SIZE,
  35. OID_GEN_MAXIMUM_SEND_PACKETS,
  36. OID_GEN_VENDOR_DESCRIPTION,
  37. OID_GEN_VENDOR_ID,
  38. OID_GEN_DRIVER_VERSION,
  39. OID_GEN_VENDOR_DRIVER_VERSION,
  40. OID_GEN_CURRENT_PACKET_FILTER,
  41. OID_GEN_CURRENT_LOOKAHEAD,
  42. OID_GEN_XMIT_OK,
  43. OID_GEN_RCV_OK,
  44. OID_GEN_XMIT_ERROR,
  45. OID_GEN_RCV_ERROR,
  46. OID_GEN_RCV_NO_BUFFER,
  47. OID_802_3_PERMANENT_ADDRESS,
  48. OID_802_3_CURRENT_ADDRESS,
  49. OID_802_3_MULTICAST_LIST,
  50. OID_802_3_MAXIMUM_LIST_SIZE,
  51. OID_802_3_RCV_ERROR_ALIGNMENT,
  52. OID_802_3_XMIT_ONE_COLLISION,
  53. OID_802_3_XMIT_MORE_COLLISIONS,
  54. OID_GEN_NETWORK_LAYER_ADDRESSES,
  55. };
  56. MP_REG_ENTRY NICRegTable[] = {
  57. // reg value name Offset in MP_ADAPTER Field size Default Value Min Max
  58. {NDIS_STRING_CONST("VCI"), 0, MP_OFFSET(config.vci), MP_SIZE(config.vci), 0, 0, 65535},
  59. {NDIS_STRING_CONST("VPI"), 0, MP_OFFSET(config.vpi), MP_SIZE(config.vpi), 0, 0, 255},
  60. {NDIS_STRING_CONST("Encap"), 0, MP_OFFSET(Encap), MP_SIZE(Encap), 2, 0, 3},
  61. };
  62. BOOLEAN g_bDumpPackets = FALSE;
  63. BOOLEAN g_fDiscardNonUnicastPackets = DISCARD_NON_UNICAST;
  64. //-------------------------------------------------------------//
  65. // //
  66. // Pre defined LLC, SNAP and Other Headers for encapsulation //
  67. // //
  68. //-------------------------------------------------------------//
  69. //
  70. // Ethernet Encapsulation
  71. //
  72. UCHAR LLCSnapEthernet[] =
  73. {
  74. 0xaa, 0xaa,0x03, // LLC
  75. 0x00, 0x80,0xc2, // OUI
  76. 0x00, 0x07, // PID
  77. 0x00, 0x00 // PAD
  78. };
  79. //
  80. // Ip v4 encapsulation
  81. //
  82. UCHAR LLCSnapIpv4[8] =
  83. {
  84. 0xaa, 0xaa,0x03, // LLC
  85. 0x00, 0x00,0x00, // OUI
  86. 0x08, 0x00 // PID
  87. };
  88. UCHAR gPaddingBytes[MINIMUM_ETHERNET_LENGTH] =
  89. {
  90. 0,0,0,0,0,0,0,0,0,0,
  91. 0,0,0,0,0,0,0,0,0,0,
  92. 0,0,0,0,0,0,0,0,0,0,
  93. 0,0,0,0,0,0,0,0,0,0,
  94. 0,0,0,0,0,0,0,0,0,0,
  95. 0,0,0,0,0,0,0,0,0,0,
  96. 0,0,0,0
  97. };
  98. //--------------------------------------------------------------------------------
  99. // //
  100. // miniports functions //
  101. // //
  102. //--------------------------------------------------------------------------------
  103. VOID
  104. epvcReturnPacketUsingAllocation(
  105. IN PEPVC_I_MINIPORT pMiniport,
  106. IN PNDIS_PACKET Packet,
  107. OUT PNDIS_PACKET *ppOriginalPacket,
  108. IN PRM_STACK_RECORD pSR
  109. )
  110. /*++
  111. Routine Description:
  112. Extracts the original packet
  113. frees all the ndis buffers in new packet
  114. returns the original packet
  115. Arguments:
  116. Return Value:
  117. --*/
  118. {
  119. PNDIS_PACKET pOrigPacket = NULL;
  120. PEPVC_PKT_CONTEXT pPktContext = NULL;
  121. TRACE (TL_T, TM_Recv , ("==>epvcReturnPacketUsingAllocation pMiniport %p, pPacket %p",
  122. pMiniport,
  123. Packet));
  124. pPktContext = (PEPVC_PKT_CONTEXT )(Packet->MiniportReservedEx);
  125. pOrigPacket = pPktContext->pOriginalPacket;
  126. if (pMiniport->fDoIpEncapsulation == TRUE)
  127. {
  128. //
  129. // Extract the lookaside buffer from the packet
  130. //
  131. PNDIS_BUFFER pBuffer = Packet->Private.Head;
  132. PEPVC_IP_RCV_BUFFER pIpBuffer= pPktContext ->Stack.ipv4Recv.pIpBuffer;
  133. if (pIpBuffer == NULL)
  134. {
  135. return ; // early return because of failure
  136. }
  137. ASSERT (pIpBuffer == NdisBufferVirtualAddress (pBuffer));
  138. //
  139. // Free the Lookaside Buffer
  140. //
  141. epvcFreeToNPagedLookasideList (&pMiniport->rcv.LookasideList,
  142. (PVOID)pIpBuffer);
  143. //
  144. // In this case, we have allocated a new ndis buffer
  145. // so delete it and free the local memory
  146. epvcFreeBuffer (pBuffer);
  147. //
  148. // The original packet is unchanged and well./
  149. //
  150. }
  151. else
  152. {
  153. //
  154. // This code path is used in both Ethernet and Ethernet+LLC encaps
  155. //
  156. // We only need to free the head of the packet as that was allocated
  157. // by us
  158. PNDIS_BUFFER pNdisBuffer = Packet->Private.Head;
  159. if (pNdisBuffer != NULL)
  160. {
  161. epvcFreeBuffer (pNdisBuffer);
  162. }
  163. }
  164. epvcFreePacket(Packet,&pMiniport->PktPool.Recv);
  165. *ppOriginalPacket = pOrigPacket;
  166. TRACE (TL_T, TM_Recv , ("<==epvcReturnPacketUsingAllocation pOrigPacket %p",
  167. *ppOriginalPacket));
  168. return;
  169. }
  170. VOID
  171. epvcReturnPacketUsingStacks (
  172. IN PEPVC_I_MINIPORT pMiniport,
  173. IN PNDIS_PACKET Packet,
  174. IN PRM_STACK_RECORD pSR
  175. )
  176. /*++
  177. Routine Description:
  178. ipv4 - Restores the orginal Head and tail to this packet
  179. Arguments:
  180. Return Value:
  181. --*/
  182. {
  183. PEPVC_PKT_CONTEXT pPktContext = NULL;
  184. BOOLEAN Remaining = FALSE; // Unused
  185. PNDIS_BUFFER pOldHead = NULL;
  186. PNDIS_BUFFER pOldTail = NULL;
  187. TRACE (TL_T, TM_Recv , ("==>epvcReturnPacketUsingStacks pMiniport %p, pPacket %p",
  188. pMiniport,
  189. Packet));
  190. pPktContext = (PEPVC_PKT_CONTEXT ) NdisIMGetCurrentPacketStack(Packet, &Remaining);
  191. if (pMiniport->fDoIpEncapsulation == TRUE)
  192. {
  193. //
  194. // Extract the lookaside buffer from the packet
  195. //
  196. PNDIS_BUFFER pBuffer = Packet->Private.Head;
  197. PEPVC_IP_RCV_BUFFER pIpBuffer= pPktContext ->Stack.ipv4Recv.pIpBuffer;
  198. if (pIpBuffer == NULL)
  199. {
  200. return; // early return
  201. }
  202. //
  203. // Extract the old head and tail from the packet
  204. //
  205. pOldHead = pIpBuffer->pOldHead;
  206. pOldTail = pIpBuffer->pOldTail;
  207. // check to see if we are in this code path because of a failure
  208. if (pOldHead == NULL)
  209. {
  210. return; // early return
  211. }
  212. ASSERT (pOldHead != NULL);
  213. ASSERT (pOldTail != NULL);
  214. ASSERT (&pIpBuffer->u.Byte[0] == NdisBufferVirtualAddress (pBuffer));
  215. //
  216. // Set The original Head and Tail
  217. //
  218. Packet->Private.Head = pOldHead;
  219. Packet->Private.Tail = pOldTail;
  220. Packet->Private.ValidCounts= FALSE;
  221. //
  222. // Free the Lookaside Buffer
  223. //
  224. epvcFreeToNPagedLookasideList (&pMiniport->rcv.LookasideList,
  225. (PVOID)pIpBuffer);
  226. //
  227. // In this case, we have allocated a new ndis buffer
  228. // so delete it and free the local memory
  229. epvcFreeBuffer (pBuffer);
  230. }
  231. else
  232. {
  233. //
  234. // This code path is used in both Ethernet and Ethernet+LLC encaps
  235. //
  236. //
  237. // We need to free the head as that was locally allocated/
  238. // We need to revert back to the old Head and tail stored
  239. // in the context
  240. //
  241. if (pPktContext->Stack.EthLLC.pOldHead == NULL)
  242. {
  243. return ; //early return
  244. }
  245. epvcFreeBuffer (Packet->Private.Head);
  246. Packet->Private.Head = pPktContext->Stack.EthLLC.pOldHead;
  247. Packet->Private.Tail = pPktContext->Stack.EthLLC.pOldTail;
  248. Packet->Private.ValidCounts= FALSE;
  249. }
  250. TRACE (TL_T, TM_Recv , ("<==epvcReturnPacketUsingStacks ",pMiniport, Packet));
  251. return;
  252. }
  253. VOID
  254. epvcProcessReturnPacket (
  255. IN PEPVC_I_MINIPORT pMiniport,
  256. IN PNDIS_PACKET Packet,
  257. OUT PPNDIS_PACKET ppOrigPacket,
  258. IN PRM_STACK_RECORD pSR
  259. )
  260. /*++
  261. Routine Description:
  262. Free all the locally allocated structures in the packet (packet , mdl, memory)
  263. Also be able to handle failure cases
  264. Arguments:
  265. Return Value:
  266. --*/
  267. {
  268. ENTER("epvcProcessReturnPacket", 0x7fafa89d)
  269. PNDIS_PACKET pOrigPacket = NULL;
  270. TRACE (TL_T, TM_Recv , ("==>epvcProcessReturnPacket pMiniport %p, pPacket %p",
  271. pMiniport,
  272. Packet));
  273. if (Packet == NULL)
  274. {
  275. return;
  276. }
  277. //
  278. // Packet stacking: Check if this packet belongs to us.
  279. //
  280. if (NdisGetPoolFromPacket(Packet) != pMiniport->PktPool.Recv.Handle)
  281. {
  282. //
  283. // We reused the original packet in a receive indication.
  284. //
  285. epvcReturnPacketUsingStacks (pMiniport, Packet, pSR);
  286. pOrigPacket = Packet;
  287. }
  288. else
  289. {
  290. //
  291. // This is a packet allocated from this IM's receive packet pool.
  292. // Reclaim our packet, and return the original to the driver below.
  293. //
  294. epvcReturnPacketUsingAllocation(pMiniport, Packet, &pOrigPacket, pSR);
  295. }
  296. //
  297. // Update the output variable
  298. //
  299. if (ppOrigPacket)
  300. {
  301. *ppOrigPacket = pOrigPacket;
  302. }
  303. EXIT()
  304. }
  305. VOID
  306. EpvcReturnPacket(
  307. IN NDIS_HANDLE MiniportAdapterContext,
  308. IN PNDIS_PACKET Packet
  309. )
  310. /*++
  311. Routine Description:
  312. Arguments:
  313. Return Value:
  314. --*/
  315. {
  316. ENTER ("EpvcReturnPacket",0x58d2259e)
  317. PEPVC_I_MINIPORT pMiniport = (PEPVC_I_MINIPORT)MiniportAdapterContext;
  318. PNDIS_PACKET pOrigPacket = NULL;
  319. RM_DECLARE_STACK_RECORD (SR);
  320. // Free all the locally allocated structures in the packet
  321. //
  322. epvcProcessReturnPacket (pMiniport, Packet, &pOrigPacket ,&SR);
  323. // Return the original packet to ndis
  324. //
  325. if (pOrigPacket != NULL)
  326. {
  327. epvcReturnPacketToNdis(pMiniport, pOrigPacket, &SR);
  328. }
  329. else
  330. {
  331. ASSERT (!"Original packet is NULL\n");
  332. }
  333. EXIT();
  334. }
  335. NDIS_STATUS
  336. MPTransferData(
  337. OUT PNDIS_PACKET Packet,
  338. OUT PUINT BytesTransferred,
  339. IN NDIS_HANDLE MiniportAdapterContext,
  340. IN NDIS_HANDLE MiniportReceiveContext,
  341. IN UINT ByteOffset,
  342. IN UINT BytesToTransfer
  343. )
  344. /*++
  345. Routine Description:
  346. Miniport's transfer data handler.
  347. Arguments:
  348. Packet Destination packet
  349. BytesTransferred Place-holder for how much data was copied
  350. MiniportAdapterContext Pointer to the adapter structure
  351. MiniportReceiveContext Context
  352. ByteOffset Offset into the packet for copying data
  353. BytesToTransfer How much to copy.
  354. Return Value:
  355. Status of transfer
  356. --*/
  357. {
  358. PEPVC_I_MINIPORT pMiniport= (PEPVC_I_MINIPORT)MiniportAdapterContext;
  359. NDIS_STATUS Status;
  360. //
  361. // Return, if the device is OFF
  362. //
  363. if (MiniportTestFlag (pMiniport, fMP_MiniportInitialized) == FALSE)
  364. {
  365. return NDIS_STATUS_FAILURE;
  366. }
  367. NdisTransferData(&Status,
  368. pMiniport->pAdapter->bind.BindingHandle,
  369. MiniportReceiveContext,
  370. ByteOffset,
  371. BytesToTransfer,
  372. Packet,
  373. BytesTransferred);
  374. return(Status);
  375. }
  376. NDIS_STATUS
  377. MPReset(
  378. OUT PBOOLEAN AddressingReset,
  379. IN NDIS_HANDLE MiniportAdapterContext
  380. )
  381. /*++
  382. Routine Description:
  383. Reset Handler. We just don't do anything.
  384. Arguments:
  385. AddressingReset To let NDIS know whether we need help from it with our reset
  386. MiniportAdapterContext Pointer to our adapter
  387. Return Value:
  388. --*/
  389. {
  390. PADAPT pAdapt = (PADAPT)MiniportAdapterContext;
  391. *AddressingReset = FALSE;
  392. return(NDIS_STATUS_SUCCESS);
  393. }
  394. //
  395. // The functions that do the LBFO work and bundling.
  396. // If LBFO is turned off, then the Set Scondary API is never called and there are no bundles
  397. //
  398. //--------------------------------------------------------------------------------
  399. // //
  400. // Intermediate Miniports. We have one instantiation per address family. //
  401. // Entry points used by the RM Apis //
  402. // //
  403. // //
  404. // //
  405. //--------------------------------------------------------------------------------
  406. PRM_OBJECT_HEADER
  407. epvcIMiniportCreate(
  408. PRM_OBJECT_HEADER pParentObject,
  409. PVOID pCreateParams,
  410. PRM_STACK_RECORD psr
  411. )
  412. /*++
  413. Routine Description:
  414. Allocate and initialize an object of type EPVC_I_MINIPORT.
  415. Arguments:
  416. pParentObject - Object that is to be the parent of the adapter.
  417. pCreateParams - Actually a pointer to a EPVC_I_MINIPORT_PARAMS structure,
  418. which contains information required to create the adapter.
  419. Return Value:
  420. Pointer to the allocated and initialized object on success.
  421. NULL otherwise.
  422. --*/
  423. {
  424. PEPVC_I_MINIPORT pIM;
  425. PEPVC_I_MINIPORT_PARAMS pParams = (PEPVC_I_MINIPORT_PARAMS)pCreateParams;
  426. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  427. extern RM_STATIC_OBJECT_INFO EpvcGlobals_I_MiniportStaticInfo;
  428. ENTER("IMiniport Create", 0x075b24c1);
  429. TRACE (TL_V, TM_Pt, ("--> epvcIMiniportCreate") );
  430. EPVC_ALLOCSTRUCT(pIM, TAG_MINIPORT );
  431. do
  432. {
  433. if (pIM == NULL)
  434. {
  435. break;
  436. }
  437. EPVC_ZEROSTRUCT(pIM);
  438. pIM->Hdr.Sig = TAG_MINIPORT;
  439. //
  440. // Do all the initialization work here
  441. //
  442. RmInitializeLock(
  443. &pIM->Lock,
  444. LOCKLEVEL_MINIPORT
  445. );
  446. RmInitializeHeader(
  447. pParentObject,
  448. &pIM->Hdr,
  449. TAG_MINIPORT,
  450. &pIM->Lock,
  451. &EpvcGlobals_I_MiniportStaticInfo,
  452. NULL,
  453. psr
  454. );
  455. //
  456. // Now initialize the adapter structure with the parameters
  457. // that were passed in.
  458. //
  459. Status = epvcCopyUnicodeString(
  460. &(pIM->ndis.DeviceName),
  461. pParams->pDeviceName,
  462. TRUE // Upcase
  463. );
  464. if (FAIL(Status))
  465. {
  466. pIM->ndis.DeviceName.Buffer=NULL; // so we don't try to free it later
  467. break;
  468. }
  469. //
  470. // initialize the informational stuff on the miniport
  471. //
  472. pIM->pAdapter = pParams->pAdapter;
  473. pIM->info.PacketFilter = 0;
  474. pIM->info.CurLookAhead = pParams->CurLookAhead;
  475. pIM->info.NumberOfMiniports = pParams->NumberOfMiniports;
  476. pIM->info.LinkSpeed = pParams->LinkSpeed.Outbound;
  477. pIM->info.MediaState = pParams->MediaState;
  478. //
  479. // Start by using the real ATM card's MAC address
  480. //
  481. NdisMoveMemory(
  482. &pIM->MacAddressEth,
  483. &pIM->pAdapter->info.MacAddress,
  484. sizeof(MAC_ADDRESS)
  485. );
  486. //
  487. // Not Elan number zero so generate a locally
  488. // administered address by manipulating the first two bytes.
  489. //
  490. pIM->MacAddressEth.Byte[0] =
  491. 0x02 | (((UCHAR)pIM->info.NumberOfMiniports & 0x3f) << 2);
  492. pIM->MacAddressEth.Byte[1] =
  493. (pIM->pAdapter->info.MacAddress.Byte[1] & 0x3f) |
  494. ((UCHAR)pIM->info.NumberOfMiniports & 0x3f);
  495. pIM->info.MacAddressDummy = pIM->MacAddressEth;
  496. pIM->info.MacAddressDummy.Byte[0]++;
  497. pIM->info.MacAddressDummy.Byte[1]++;
  498. pIM->info.MacAddressDummy.Byte[2]++;
  499. {
  500. //
  501. // Create a Dummy Mac address for receive indications
  502. //
  503. pIM->info.MacAddressDest = pIM->MacAddressEth;
  504. }
  505. {
  506. //
  507. // Create an Ethernet Header to be used
  508. //
  509. PEPVC_ETH_HEADER pRcvEnetHeader = &pIM->RcvEnetHeader ;
  510. pRcvEnetHeader->eh_daddr = pIM->info.MacAddressDest;
  511. pRcvEnetHeader->eh_saddr = pIM->info.MacAddressDummy;
  512. pRcvEnetHeader->eh_type = net_short (IP_PROT_TYPE );
  513. }
  514. pIM->info.McastAddrCount = 0;
  515. Status = NDIS_STATUS_SUCCESS;
  516. }
  517. while(FALSE);
  518. if (FAIL(Status))
  519. {
  520. if (pIM != NULL)
  521. {
  522. epvcIMiniportDelete ((PRM_OBJECT_HEADER) pIM, psr);
  523. pIM = NULL;
  524. }
  525. }
  526. TRACE (TL_V, TM_Pt, ("<-- epvcIMiniportCreate pIMiniport. %p",pIM) );
  527. return (PRM_OBJECT_HEADER) pIM;
  528. }
  529. VOID
  530. epvcIMiniportDelete (
  531. PRM_OBJECT_HEADER pObj,
  532. PRM_STACK_RECORD psr
  533. )
  534. /*++
  535. Routine Description:
  536. Free an object of type EPVC_I_MINIPORT.
  537. Arguments:
  538. pHdr - Actually a pointer to the EPVC_I_MINIPORT to be deleted.
  539. --*/
  540. {
  541. PEPVC_I_MINIPORT pMiniport = (PEPVC_I_MINIPORT) pObj;
  542. TRACE (TL_V, TM_Pt, ("-- epvcIMiniportDelete pAdapter %p",pMiniport) );
  543. pMiniport->Hdr.Sig = TAG_FREED;
  544. EPVC_FREE (pMiniport);
  545. }
  546. BOOLEAN
  547. epvcIMiniportCompareKey(
  548. PVOID pKey,
  549. PRM_HASH_LINK pItem
  550. )
  551. /*++
  552. Routine Description:
  553. Hash comparison function for EPVC_I_MINIPORT.
  554. Arguments:
  555. pKey - Points to a Epvc Protocol object.
  556. pItem - Points to EPVC_I_MINIPORT.Hdr.HashLink.
  557. Return Value:
  558. TRUE IFF the key (adapter name) exactly matches the key of the specified
  559. adapter object.
  560. --*/
  561. {
  562. PEPVC_I_MINIPORT pIM = NULL;
  563. PNDIS_STRING pName = (PNDIS_STRING) pKey;
  564. BOOLEAN fCompare;
  565. pIM = CONTAINING_RECORD(pItem, EPVC_I_MINIPORT, Hdr.HashLink);
  566. //
  567. // TODO: maybe case-insensitive compare?
  568. //
  569. if ( (pIM->ndis.DeviceName.Length == pName->Length)
  570. && NdisEqualMemory(pIM->ndis.DeviceName.Buffer, pName->Buffer, pName->Length))
  571. {
  572. return TRUE;
  573. }
  574. else
  575. {
  576. return FALSE;
  577. }
  578. TRACE (TL_V, TM_Pt, ("-- epvcProtocolCompareKey pIM %p, pKey, return %x",pIM, pKey, fCompare ) );
  579. return fCompare;
  580. }
  581. ULONG
  582. epvcIMiniportHash(
  583. PVOID pKey
  584. )
  585. /*++
  586. Routine Description:
  587. Hash function responsible for returning a hash of pKey, which
  588. we expect to be a pointer to an Epvc Protocol block.
  589. Return Value:
  590. ULONG-sized hash of the string.
  591. --*/
  592. {
  593. TRACE(TL_T, TM_Mp, ("epvcIMiniportHash %x", pKey));
  594. {
  595. PNDIS_STRING pName = (PNDIS_STRING) pKey;
  596. WCHAR *pwch = pName->Buffer;
  597. WCHAR *pwchEnd = pName->Buffer + pName->Length/sizeof(*pwch);
  598. ULONG Hash = 0;
  599. for (;pwch < pwchEnd; pwch++)
  600. {
  601. Hash ^= (Hash<<1) ^ *pwch;
  602. }
  603. return Hash;
  604. }
  605. }
  606. NDIS_STATUS
  607. epvcTaskVcSetup(
  608. IN struct _RM_TASK * pTask,
  609. IN RM_TASK_OPERATION Code,
  610. IN UINT_PTR UserParam,
  611. IN PRM_STACK_RECORD pSR
  612. )
  613. /*++
  614. Routine Description:
  615. Arguments:
  616. UserParam for (Code == RM_TASKOP_START) : UnbindContext
  617. --*/
  618. {
  619. ENTER("epvcTaskVcSetup", 0x64085960)
  620. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  621. PEPVC_I_MINIPORT pMiniport = (PEPVC_I_MINIPORT ) RM_PARENT_OBJECT(pTask);
  622. PTASK_VC pTaskVc = (PTASK_VC) pTask;
  623. PEPVC_ADAPTER pAdapter = (PEPVC_ADAPTER)pMiniport->Hdr.pParentObject;
  624. NDIS_HANDLE NdisVcHandle = NULL;
  625. PCO_CALL_PARAMETERS pCallParameters = NULL;
  626. enum
  627. {
  628. Stage_Start =0, // default
  629. Stage_CreateVc,
  630. Stage_MakeCall,
  631. Stage_DeleteVc, // in case of failure
  632. Stage_TaskCompleted,
  633. Stage_End
  634. }; // To be used in pTask->Hdr.State to indicate the state of the Task
  635. TRACE ( TL_T, TM_Pt, ("==> epvcTaskVcSetup %x",pTask->Hdr.State ) );
  636. switch (pTask->Hdr.State)
  637. {
  638. case Stage_Start:
  639. {
  640. LOCKOBJ (pMiniport, pSR);
  641. if (epvcIsThisTaskPrimary ( pTask, &(PRM_TASK)(pMiniport->vc.pTaskVc)) == FALSE)
  642. {
  643. PRM_TASK pOtherTask = (PRM_TASK)(pMiniport->vc.pTaskVc);
  644. RmTmpReferenceObject (&pOtherTask->Hdr, pSR);
  645. //
  646. // Set The state so we restart this code after main task completes
  647. //
  648. pTask->Hdr.State = Stage_Start;
  649. UNLOCKOBJ(pMiniport, pSR);
  650. RmPendTaskOnOtherTask (pTask, 0, pOtherTask, pSR);
  651. RmTmpDereferenceObject(&pOtherTask->Hdr,pSR);
  652. Status = NDIS_STATUS_PENDING;
  653. break;
  654. }
  655. //
  656. // We are the primary task
  657. //
  658. ASSERT (pMiniport->vc.pTaskVc == pTaskVc);
  659. //
  660. // Check to see if our work is already done
  661. //
  662. if (MiniportTestFlag(pMiniport, fMP_MakeCallSucceeded) == TRUE)
  663. {
  664. //
  665. // Our work had been done. So break out and complete the task
  666. //
  667. Status = NDIS_STATUS_SUCCESS;
  668. pTaskVc->ReturnStatus = NDIS_STATUS_SUCCESS;
  669. pTask->Hdr.State = Stage_TaskCompleted;
  670. UNLOCKOBJ(pMiniport, pSR);
  671. break;
  672. }
  673. MiniportClearFlag (pMiniport,fMP_InfoCallClosed);
  674. MiniportSetFlag (pMiniport, fMP_InfoMakingCall);
  675. UNLOCKOBJ(pMiniport, pSR);
  676. //
  677. // Now begin the real work
  678. //
  679. //
  680. // Set up the call parameters. If it fails ,then exit
  681. //
  682. epvcSetupMakeCallParameters(pMiniport, &pCallParameters);
  683. if (pCallParameters == NULL)
  684. {
  685. Status = NDIS_STATUS_FAILURE;
  686. pTaskVc->ReturnStatus = NDIS_STATUS_FAILURE;
  687. pTask->Hdr.State = Stage_TaskCompleted;
  688. break;
  689. }
  690. //
  691. // Create Vc - Syncronous call
  692. //
  693. ASSERT (pAdapter->Hdr.Sig = TAG_ADAPTER);
  694. Status = epvcCoCreateVc(pAdapter->bind.BindingHandle,
  695. pMiniport->af.AfHandle OPTIONAL, // For CM signalling VCs
  696. pMiniport,
  697. &NdisVcHandle);
  698. ASSERT (PEND(Status) == FALSE); // this is a synchronous call
  699. if (FAIL(Status) == TRUE)
  700. {
  701. //
  702. // We have failed. This task is done. There are not
  703. // resources to be freed, although a flag has to be
  704. // cleared
  705. //
  706. NdisVcHandle = NULL;
  707. pMiniport->vc.VcHandle = NULL;
  708. pTask->Hdr.State = Stage_TaskCompleted;
  709. break;
  710. }
  711. ASSERT (Status == NDIS_STATUS_SUCCESS);
  712. //
  713. // Store the Vc Handle
  714. //
  715. LOCKOBJ (pMiniport, pSR);
  716. pMiniport->vc.VcHandle = NdisVcHandle;
  717. epvcLinkToExternal( &pMiniport->Hdr,
  718. 0xf52962f1,
  719. (UINT_PTR)pMiniport->vc.VcHandle,
  720. EPVC_ASSOC_MINIPORT_OPEN_VC,
  721. " VcHandle %p\n",
  722. pSR);
  723. UNLOCKOBJ (pMiniport, pSR);
  724. //
  725. // Do a Make Call
  726. //
  727. pTask->Hdr.State = Stage_MakeCall;
  728. RmSuspendTask(pTask, 0, pSR);
  729. Status = epvcClMakeCall(NdisVcHandle,
  730. pCallParameters,
  731. NULL, //Party Context
  732. NULL // PartyHandle
  733. );
  734. if (NDIS_STATUS_PENDING !=Status)
  735. {
  736. EpvcCoMakeCallComplete(Status,
  737. pMiniport,
  738. NULL,
  739. 0);
  740. }
  741. break;
  742. }
  743. case Stage_MakeCall:
  744. {
  745. //
  746. // The make call has been completed.
  747. // If we have succeeded then we update our flags
  748. // and exit.
  749. //
  750. // If the make call has failed, then I need to delete the VC
  751. //
  752. ASSERT (NDIS_STATUS_CALL_ACTIVE != pTaskVc->ReturnStatus);
  753. if (NDIS_STATUS_SUCCESS == pTaskVc->ReturnStatus)
  754. {
  755. LOCKOBJ(pMiniport, pSR);
  756. MiniportSetFlag (pMiniport, fMP_MakeCallSucceeded);
  757. MiniportClearFlag (pMiniport, fMP_InfoMakingCall);
  758. UNLOCKOBJ (pMiniport, pSR);
  759. }
  760. else
  761. {
  762. NDIS_HANDLE VcHandle = NULL;
  763. //
  764. // Delete the VC, as we do not want a VC without an active
  765. // Make call on it.
  766. //
  767. ASSERT (NDIS_STATUS_SUCCESS == pTaskVc->ReturnStatus);
  768. LOCKOBJ(pMiniport, pSR);
  769. VcHandle = pMiniport->vc.VcHandle;
  770. epvcUnlinkFromExternal( &pMiniport->Hdr,
  771. 0xa914405a,
  772. (UINT_PTR)pMiniport->vc.VcHandle,
  773. EPVC_ASSOC_MINIPORT_OPEN_VC,
  774. pSR);
  775. pMiniport->vc.VcHandle = NULL;
  776. UNLOCKOBJ (pMiniport, pSR);
  777. TRACE (TL_I, TM_Mp,("Deleting Vc because of a failure in MakeCall"));
  778. Status = epvcCoDeleteVc(VcHandle);
  779. //
  780. // TODO: Fix Failure case
  781. //
  782. ASSERT (NDIS_STATUS_SUCCESS == Status );
  783. }
  784. //
  785. // This task is over. Now do the indications
  786. //
  787. pTask->Hdr.State = Stage_TaskCompleted;
  788. Status = NDIS_STATUS_SUCCESS;
  789. break;
  790. }
  791. case Stage_End:
  792. {
  793. Status = NDIS_STATUS_SUCCESS;
  794. break;
  795. }
  796. default:
  797. {
  798. ASSERTEX(!"Unknown task op", pTask);
  799. }
  800. } // end of switch
  801. if ( Stage_TaskCompleted == pTask->Hdr.State )
  802. {
  803. pTask->Hdr.State = Stage_End;
  804. ASSERT (NDIS_STATUS_PENDING !=Status );
  805. //
  806. // Do any cleanup indications to NDIS over here
  807. //
  808. epvcVcSetupDone ( pTaskVc, pMiniport);
  809. LOCKOBJ(pMiniport, pSR);
  810. pMiniport->vc.pTaskVc = NULL;
  811. UNLOCKOBJ (pMiniport, pSR);
  812. }
  813. TRACE ( TL_T, TM_Mp, ("<== epvcTaskVcSetup , Status %x",Status) );
  814. RM_ASSERT_NOLOCKS(pSR);
  815. EXIT()
  816. return Status;
  817. }
  818. VOID
  819. epvcVcSetupDone (
  820. PTASK_VC pTaskVc,
  821. PEPVC_I_MINIPORT pMiniport
  822. )
  823. /*++
  824. Routine Description:
  825. If the task was queued because of SetPacket Filter request then
  826. this function completes the request.
  827. If the task was run because of the Indicate Media Connect event, then
  828. this thread indicates a Media Connect to NDIS
  829. Arguments:
  830. Status - Did the VcSetup Succeed or Fail
  831. pTaskVc - Task in question
  832. pMiniport - the Miniport that the task operated on
  833. Return Value:
  834. None:
  835. --*/
  836. {
  837. if (TaskCause_NdisRequest == pTaskVc->Cause )
  838. {
  839. //
  840. // Since requests are serialized, we don't acquire the lock
  841. //
  842. TRACE (TL_V, TM_Rq, ("Completing SetPacketFilter Request %x", pTaskVc->ReturnStatus ));
  843. if (pTaskVc->ReturnStatus == NDIS_STATUS_SUCCESS)
  844. {
  845. pMiniport->info.PacketFilter = pTaskVc->PacketFilter;
  846. }
  847. NdisMSetInformationComplete (pMiniport->ndis.MiniportAdapterHandle, pTaskVc->ReturnStatus);
  848. }
  849. else
  850. {
  851. ASSERT (TaskCause_MediaConnect == pTaskVc->Cause );
  852. pMiniport->info.MediaState = NdisMediaStateConnected;
  853. NdisMIndicateStatus ( pMiniport->ndis.MiniportAdapterHandle,
  854. NDIS_STATUS_MEDIA_CONNECT,
  855. NULL,
  856. 0);
  857. }
  858. }
  859. NDIS_STATUS
  860. epvcTaskVcTeardown(
  861. IN struct _RM_TASK * pTask,
  862. IN RM_TASK_OPERATION Code,
  863. IN UINT_PTR UserParam,
  864. IN PRM_STACK_RECORD pSR
  865. )
  866. /*++
  867. Routine Description:
  868. Arguments:
  869. UserParam for (Code == RM_TASKOP_START) : UnbindContext
  870. --*/
  871. {
  872. ENTER("epvcTaskVcTeardown", 0x68c96c4d)
  873. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  874. PEPVC_I_MINIPORT pMiniport = (PEPVC_I_MINIPORT ) RM_PARENT_OBJECT(pTask);
  875. PTASK_VC pTaskVc = (PTASK_VC) pTask;
  876. PEPVC_ADAPTER pAdapter = (PEPVC_ADAPTER)pMiniport->Hdr.pParentObject;
  877. NDIS_HANDLE NdisVcHandle = NULL;
  878. PCO_CALL_PARAMETERS pCallParameters = NULL;
  879. enum
  880. {
  881. Stage_Start =0, // default
  882. Stage_CloseCallComplete,
  883. Stage_DeleteVc,
  884. Stage_TaskCompleted,
  885. Stage_End
  886. }; // To be used in pTask->Hdr.State to indicate the state of the Task
  887. TRACE ( TL_T, TM_Pt, ("==> epvcTaskVcTeardown %x",pTask->Hdr.State ) );
  888. switch (pTask->Hdr.State)
  889. {
  890. case Stage_Start:
  891. {
  892. LOCKOBJ (pMiniport, pSR);
  893. if (epvcIsThisTaskPrimary ( pTask, &(PRM_TASK)(pMiniport->vc.pTaskVc)) == FALSE)
  894. {
  895. PRM_TASK pOtherTask = (PRM_TASK)(pMiniport->vc.pTaskVc);
  896. RmTmpReferenceObject (&pOtherTask->Hdr, pSR);
  897. //
  898. // Set The state so we restart this code after main task completes
  899. //
  900. pTask->Hdr.State = Stage_Start;
  901. UNLOCKOBJ(pMiniport, pSR);
  902. RmPendTaskOnOtherTask (pTask, 0, pOtherTask, pSR);
  903. RmTmpDereferenceObject(&pOtherTask->Hdr,pSR);
  904. Status = NDIS_STATUS_PENDING;
  905. break;
  906. }
  907. //
  908. // We are the primary task
  909. //
  910. ASSERT (pMiniport->vc.pTaskVc == pTaskVc);
  911. //
  912. // Check to see if our work is already done
  913. //
  914. if (MiniportTestFlag(pMiniport, fMP_MakeCallSucceeded) == FALSE)
  915. {
  916. //
  917. // Our work had been done. So break out and complete the task
  918. //
  919. Status = NDIS_STATUS_SUCCESS;
  920. pTask->Hdr.State = Stage_TaskCompleted;
  921. UNLOCKOBJ(pMiniport, pSR);
  922. break;
  923. }
  924. MiniportClearFlag (pMiniport, fMP_MakeCallSucceeded);
  925. MiniportSetFlag (pMiniport, fMP_InfoClosingCall);
  926. UNLOCKOBJ(pMiniport, pSR);
  927. //
  928. // Now close the call - Asynchronously.
  929. //
  930. pTask->Hdr.State = Stage_CloseCallComplete;
  931. RmSuspendTask (pTask, 0, pSR);
  932. Status = epvcClCloseCall( pMiniport->vc.VcHandle);
  933. if (NDIS_STATUS_PENDING != Status)
  934. {
  935. EpvcCoCloseCallComplete (Status,
  936. pMiniport,
  937. NULL
  938. );
  939. }
  940. Status = NDIS_STATUS_PENDING;
  941. break;
  942. }
  943. case Stage_CloseCallComplete:
  944. {
  945. NDIS_HANDLE VcHandle = NULL;
  946. LOCKOBJ(pMiniport, pSR);
  947. VcHandle = pMiniport->vc.VcHandle;
  948. epvcUnlinkFromExternal(&pMiniport->Hdr,
  949. 0x5d7b5ea8,
  950. (UINT_PTR)pMiniport->vc.VcHandle,
  951. EPVC_ASSOC_MINIPORT_OPEN_VC,
  952. pSR);
  953. pMiniport->vc.VcHandle = NULL;
  954. UNLOCKOBJ(pMiniport, pSR);
  955. Status = epvcCoDeleteVc(VcHandle);
  956. //
  957. // This is an assertion because the DeleteVc cannot fail.
  958. // We do a DeleteVc in one place only and it is serialized.
  959. //
  960. ASSERT (Status == NDIS_STATUS_SUCCESS);
  961. pTask->Hdr.State = Stage_TaskCompleted;
  962. break;
  963. }
  964. case Stage_End:
  965. {
  966. Status = NDIS_STATUS_SUCCESS;
  967. break;
  968. }
  969. default:
  970. {
  971. ASSERTEX(!"Unknown task op", pTask);
  972. }
  973. }
  974. if (Stage_TaskCompleted == pTask->Hdr.State )
  975. {
  976. pTask->Hdr.State = Stage_End;
  977. //
  978. // Complete the request or the Media Disconnect;
  979. //
  980. epvcVcTeardownDone(pTaskVc, pMiniport);
  981. LOCKOBJ (pMiniport, pSR);
  982. //
  983. // Update informational flags
  984. //
  985. MiniportClearFlag (pMiniport, fMP_InfoClosingCall);
  986. MiniportSetFlag (pMiniport, fMP_InfoCallClosed);
  987. pMiniport->vc.pTaskVc = NULL;
  988. UNLOCKOBJ(pMiniport, pSR);
  989. }
  990. TRACE ( TL_T, TM_Mp, ("<== epvcTaskVcTeardown , Status %x",Status) );
  991. RM_ASSERT_NOLOCKS(pSR);
  992. EXIT()
  993. return Status;
  994. }
  995. VOID
  996. epvcVcTeardownDone(
  997. PTASK_VC pTaskVc,
  998. PEPVC_I_MINIPORT pMiniport
  999. )
  1000. {
  1001. TRACE ( TL_T, TM_Mp, ("==> epvcVcTeardownDone ") );
  1002. switch (pTaskVc->Cause)
  1003. {
  1004. case TaskCause_NdisRequest:
  1005. {
  1006. ASSERT (pTaskVc->ReturnStatus != NDIS_STATUS_PENDING);
  1007. //
  1008. // Since requests are serialized, we don't acquire the lock
  1009. //
  1010. pMiniport->info.PacketFilter = pTaskVc->PacketFilter;
  1011. NdisMSetInformationComplete(pMiniport->ndis.MiniportAdapterHandle,
  1012. pTaskVc->ReturnStatus);
  1013. break;
  1014. }
  1015. case TaskCause_MediaDisconnect:
  1016. {
  1017. pMiniport->info.MediaState = NdisMediaStateDisconnected;
  1018. epvcMIndicateStatus ( pMiniport,
  1019. NDIS_STATUS_MEDIA_DISCONNECT,
  1020. NULL,
  1021. 0);
  1022. break;
  1023. }
  1024. default:
  1025. {
  1026. // Do nothing.
  1027. //
  1028. }
  1029. }
  1030. TRACE ( TL_T, TM_Mp, ("<== epvcVcTeardownDone ") );
  1031. }
  1032. NDIS_STATUS
  1033. EpvcInitialize(
  1034. OUT PNDIS_STATUS OpenErrorStatus,
  1035. OUT PUINT SelectedMediumIndex,
  1036. IN PNDIS_MEDIUM MediumArray,
  1037. IN UINT MediumArraySize,
  1038. IN NDIS_HANDLE MiniportAdapterHandle,
  1039. IN NDIS_HANDLE WrapperConfigurationContext
  1040. )
  1041. /*++
  1042. Routine Description:
  1043. This is the initialize handler which gets called as a result of the BindAdapter handler
  1044. calling NdisIMInitializeDeviceInstanceEx(). The context parameter which we pass there is
  1045. the adapter structure which we retreive here. We also need to initialize the Power Management
  1046. variable.
  1047. LoadBalalncing- We keep a global list of all the passthru miniports installed and bundle
  1048. two of them together if they have the same BundleId (read from registry)
  1049. Arguments:
  1050. OpenErrorStatus Not used by us.
  1051. SelectedMediumIndex Place-holder for what media we are using
  1052. MediumArray Array of ndis media passed down to us to pick from
  1053. MediumArraySize Size of the array
  1054. MiniportAdapterHandle The handle NDIS uses to refer to us
  1055. WrapperConfigurationContext For use by NdisOpenConfiguration
  1056. Return Value:
  1057. NDIS_STATUS_SUCCESS unless something goes wrong
  1058. --*/
  1059. {
  1060. ENTER ("EpvcInitialize", 0xa935a2a5)
  1061. UINT i;
  1062. PEPVC_I_MINIPORT pMiniport = NULL;
  1063. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  1064. KIRQL OldIrql;
  1065. enum
  1066. {
  1067. Stage_Start,
  1068. Stage_AllocatedPacketPools,
  1069. Stage_AllocatedLookasideLists
  1070. };
  1071. ULONG State = Stage_Start;
  1072. RM_DECLARE_STACK_RECORD (SR);
  1073. TRACE (TL_T, TM_Mp, ("==>EpvcInitialize MiniportAdapterHandle %x", MiniportAdapterHandle));
  1074. //
  1075. // Start off by retrieving the adapter context and storing the Miniport handle in it
  1076. //
  1077. pMiniport = NdisIMGetDeviceContext(MiniportAdapterHandle);
  1078. if (pMiniport->Hdr.Sig != TAG_MINIPORT)
  1079. {
  1080. ASSERT (pMiniport->Hdr.Sig == TAG_MINIPORT);
  1081. return NDIS_STATUS_FAILURE;
  1082. }
  1083. pMiniport->ndis.MiniportAdapterHandle = MiniportAdapterHandle;
  1084. //
  1085. // Make sure the medium saved is one of the ones being offered
  1086. //
  1087. for (i = 0; i < MediumArraySize; i++)
  1088. {
  1089. if (MediumArray[i] == ATMEPVC_MP_MEDIUM )
  1090. {
  1091. *SelectedMediumIndex = i;
  1092. break;
  1093. }
  1094. }
  1095. if (i == MediumArraySize)
  1096. {
  1097. return(NDIS_STATUS_UNSUPPORTED_MEDIA);
  1098. }
  1099. //
  1100. // Set the attributes now. The NDIS_ATTRIBUTE_DESERIALIZE is the key. This enables us
  1101. // to make up-calls to NDIS w/o having to call NdisIMSwitchToMiniport/NdisIMQueueCallBack.
  1102. // This also forces us to protect our data using spinlocks where appropriate. Also in this
  1103. // case NDIS does not queue packets on out behalf. Since this is a very simple pass-thru
  1104. // miniport, we do not have a need to protect anything. However in a general case there
  1105. // will be a need to use per-adapter spin-locks for the packet queues at the very least.
  1106. //
  1107. NdisMSetAttributesEx(MiniportAdapterHandle,
  1108. pMiniport,
  1109. 0, // CheckForHangTimeInSeconds
  1110. NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT |
  1111. NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT|
  1112. NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER |
  1113. NDIS_ATTRIBUTE_DESERIALIZE,
  1114. 0);
  1115. //
  1116. // We are done, with the no failure stuff. From now on we need to undo
  1117. //
  1118. do
  1119. {
  1120. Status = epvcMiniportReadConfig(pMiniport, WrapperConfigurationContext,&SR );
  1121. if (Status != NDIS_STATUS_SUCCESS)
  1122. {
  1123. //
  1124. // Undo Configuration values
  1125. //
  1126. ASSERT (Status == NDIS_STATUS_SUCCESS);
  1127. break;
  1128. }
  1129. epvcInitializeMiniportParameters(pMiniport);
  1130. //
  1131. // allocate Packet pools.
  1132. //
  1133. Status = epvcInitializeMiniportPacketPools (pMiniport);
  1134. if (Status != NDIS_STATUS_SUCCESS)
  1135. {
  1136. ASSERT (Status == NDIS_STATUS_SUCCESS);
  1137. break;
  1138. }
  1139. State = Stage_AllocatedPacketPools;
  1140. //
  1141. // Allocate lookaside lists
  1142. //
  1143. epvcInitializeMiniportLookasideLists(pMiniport);
  1144. State = Stage_AllocatedLookasideLists;
  1145. Status = NDIS_STATUS_SUCCESS;
  1146. } while (FALSE);
  1147. TRACE (TL_T, TM_Mp, ("<==EpvcInitialize pMiniport %x, Status %x", pMiniport, Status ));
  1148. if (Status == NDIS_STATUS_SUCCESS)
  1149. {
  1150. BOOLEAN fSetDeInit = FALSE;
  1151. LOCKOBJ(pMiniport, &SR);
  1152. MiniportSetFlag(pMiniport, fMP_MiniportInitialized);
  1153. if (MiniportTestFlag (pMiniport, fMP_MiniportCancelInstance))
  1154. {
  1155. fSetDeInit = TRUE;
  1156. }
  1157. UNLOCKOBJ(pMiniport, &SR);
  1158. //
  1159. // Check to see if we have a DeInit Waiting for us.
  1160. // This will only be set if a Cancel Device Instance fails.
  1161. //
  1162. if (fSetDeInit == TRUE)
  1163. {
  1164. epvcSetEvent (&pMiniport->pnp.DeInitEvent);
  1165. }
  1166. }
  1167. else
  1168. {
  1169. //
  1170. // Undo Code
  1171. //
  1172. ASSERT (FAIL(Status) == TRUE);
  1173. switch (State)
  1174. {
  1175. case Stage_AllocatedLookasideLists:
  1176. epvcDeleteMiniportLookasideLists (pMiniport);
  1177. FALL_THROUGH
  1178. case Stage_AllocatedPacketPools:
  1179. epvcDeleteMiniportPacketPools(pMiniport);
  1180. FALL_THROUGH
  1181. default:
  1182. break;
  1183. }
  1184. }
  1185. RM_ASSERT_CLEAR(&SR);
  1186. EXIT();
  1187. return Status;
  1188. }
  1189. VOID
  1190. EpvcHalt(
  1191. IN NDIS_HANDLE MiniportAdapterContext
  1192. )
  1193. /*++
  1194. Routine Description:
  1195. Halt handler. All the hard-work for clean-up is done here.
  1196. Arguments:
  1197. MiniportAdapterContext Pointer to the Adapter
  1198. Return Value:
  1199. None.
  1200. --*/
  1201. {
  1202. ENTER("EpvcHalt",0x6b407ae1)
  1203. PEPVC_I_MINIPORT pMiniport = (PEPVC_I_MINIPORT)MiniportAdapterContext;
  1204. PEPVC_ADAPTER pAdapter = pMiniport->pAdapter;
  1205. PRM_TASK pTask = NULL;
  1206. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  1207. RM_DECLARE_STACK_RECORD (SR);
  1208. TRACE (TL_V, TM_Mp, ("==>Epvc MPHaltMiniport"));
  1209. do
  1210. {
  1211. LOCKOBJ (pMiniport, &SR);
  1212. //
  1213. // Clear the flag so we can block all sends/receives/requests
  1214. //
  1215. MiniportClearFlag(pMiniport, fMP_MiniportInitialized);
  1216. MiniportSetFlag(pMiniport, fMP_InfoHalting);
  1217. //
  1218. // Ref the miniport, this indirectly refs the adpater as well
  1219. //
  1220. RmTmpReferenceObject (&pMiniport->Hdr, &SR);
  1221. //
  1222. // Kick of the miniport halt task and wait for it to complete
  1223. //
  1224. Status = epvcAllocateTask(
  1225. &pMiniport->Hdr, // pParentObject,
  1226. epvcTaskHaltMiniport, // pfnHandler,
  1227. 0, // Timeout,
  1228. "Task: Halt Intermediate Miniport", // szDescription
  1229. &pTask,
  1230. &SR
  1231. );
  1232. if (FAIL(Status))
  1233. {
  1234. pTask = NULL;
  1235. break;
  1236. }
  1237. //
  1238. // Reference the task so it is around until our Wait for completion
  1239. // is complete
  1240. //
  1241. RmTmpReferenceObject (&pTask->Hdr, &SR);
  1242. UNLOCKOBJ (pMiniport, &SR);
  1243. //
  1244. // This Kicks of the task that will close the Call, Delete
  1245. // the VC and close the AF. We do this all synchronously
  1246. //
  1247. {
  1248. PTASK_HALT pHalt = (PTASK_HALT) pTask;
  1249. epvcInitializeEvent (&pHalt->CompleteEvent);
  1250. RmStartTask(pTask, 0, &SR);
  1251. TRACE (TL_V, TM_Mp, ("About to Wait - for Halt Complete Event"));
  1252. epvcWaitEvent (&pHalt->CompleteEvent, WAIT_INFINITE);
  1253. TRACE (TL_V, TM_Mp, ("Wait Complete- for Halt Complete Event"));
  1254. }
  1255. LOCKOBJ (pMiniport, &SR);
  1256. //
  1257. // Deref the task . Ref was made above.
  1258. //
  1259. RmTmpDereferenceObject (&pTask->Hdr, &SR);
  1260. } while (FALSE);
  1261. MiniportClearFlag(pMiniport, fMP_InfoHalting);
  1262. UNLOCKOBJ(pMiniport, &SR);
  1263. RmTmpDereferenceObject(&pMiniport->Hdr, &SR);
  1264. RM_ASSERT_CLEAR(&SR);
  1265. TRACE (TL_V, TM_Mp, ("<==Epvc MPHaltMiniport"));
  1266. }
  1267. VOID
  1268. epvcSetPacketFilterWorkItem (
  1269. PNDIS_WORK_ITEM pWorkItem,
  1270. PVOID Context
  1271. )
  1272. /*++
  1273. Routine Description:
  1274. Decrements the refcount on the filter and processes the new packet filter
  1275. Return Value:
  1276. None
  1277. --*/
  1278. {
  1279. ENTER ("epvcSetPacketFilterWorkItem ",0x3e1cdbba )
  1280. PEPVC_I_MINIPORT pMiniport = NULL;
  1281. PRM_TASK pTask = NULL;
  1282. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  1283. UINT Filter ;
  1284. RM_DECLARE_STACK_RECORD (SR);
  1285. do
  1286. {
  1287. pMiniport = CONTAINING_RECORD (pWorkItem,
  1288. EPVC_I_MINIPORT,
  1289. vc.PacketFilterWorkItem) ;
  1290. //
  1291. // Dereference the workitem off the miniport
  1292. //
  1293. epvcUnlinkFromExternal( &pMiniport->Hdr,
  1294. 0xa1f5e3cc,
  1295. (UINT_PTR)pWorkItem,
  1296. EPVC_ASSOC_SET_FILTER_WORKITEM,
  1297. &SR);
  1298. //
  1299. // Start the task to create or delete the VC
  1300. //
  1301. Filter = pMiniport->vc.NewFilter ;
  1302. //
  1303. // If this is a repition, then succeed it synchronously
  1304. //
  1305. if (Filter == pMiniport->info.PacketFilter)
  1306. {
  1307. Status = NDIS_STATUS_SUCCESS;
  1308. break;
  1309. }
  1310. LOCKOBJ(pMiniport, &SR);
  1311. //
  1312. // Are we moving to a Zero filter value
  1313. //
  1314. if (Filter == 0)
  1315. {
  1316. //
  1317. // Delete the Vc, so that we stop doing any receives
  1318. //
  1319. Status = epvcAllocateTask(
  1320. &pMiniport->Hdr, // pParentObject,
  1321. epvcTaskVcTeardown, // pfnHandler,
  1322. 0, // Timeout,
  1323. "Task: Delete Vc", // szDescription
  1324. &pTask,
  1325. &SR
  1326. );
  1327. }
  1328. else
  1329. {
  1330. //
  1331. // We are moving a non-zero values
  1332. //
  1333. //
  1334. // Create the Vc, so that we can send
  1335. //
  1336. Status = epvcAllocateTask(
  1337. &pMiniport->Hdr, // pParentObject,
  1338. epvcTaskVcSetup, // pfnHandler,
  1339. 0, // Timeout,
  1340. "Task: Create Vc", // szDescription
  1341. &pTask,
  1342. &SR
  1343. );
  1344. }
  1345. UNLOCKOBJ(pMiniport, &SR);
  1346. if (FAIL(Status) == TRUE)
  1347. {
  1348. // Ugly situation. We'll just leave things as they are...
  1349. //
  1350. pTask = NULL;
  1351. TR_WARN(("FATAL: couldn't allocate create/ delete Vc task!\n"));
  1352. ASSERT (0);
  1353. break;
  1354. }
  1355. //
  1356. // Update the cause if the task
  1357. //
  1358. ((PTASK_VC)pTask)->Cause = TaskCause_NdisRequest;
  1359. ((PTASK_VC)pTask)->PacketFilter = Filter ;
  1360. RmStartTask(pTask, 0, &SR);
  1361. Status = NDIS_STATUS_PENDING;
  1362. } while (FALSE);
  1363. //
  1364. // complete the request if the task has not been started
  1365. //
  1366. if (PEND(Status) != TRUE)
  1367. {
  1368. NdisMSetInformationComplete (pMiniport->ndis.MiniportAdapterHandle, Status);
  1369. }
  1370. EXIT();
  1371. }
  1372. NDIS_STATUS
  1373. epvcSetPacketFilter(
  1374. IN PEPVC_I_MINIPORT pMiniport,
  1375. IN ULONG Filter,
  1376. PRM_STACK_RECORD pSR
  1377. )
  1378. /*++
  1379. Routine Description:
  1380. This routine is called when a miniport get a set packet filter.
  1381. It validates the arguments, If all is well then it process the request
  1382. For a non-zero filter, a create VC and a Make call is done.
  1383. For a zero filter, the call is closed and the Vc Deleted
  1384. Return Value:
  1385. NDIS_STATUS_SUCCESS unless something goes wrong
  1386. --*/
  1387. {
  1388. ENTER ("epvcSetPacketFilter", 0x97c6b961)
  1389. NDIS_STATUS Status = NDIS_STATUS_PENDING;
  1390. PNDIS_WORK_ITEM pSetFilterWorItem = &pMiniport->vc.PacketFilterWorkItem;
  1391. PRM_TASK pTask = NULL;
  1392. TRACE (TL_T, TM_Mp, ("==>epvcSetPacketFilter Filter %X", Filter ));
  1393. do
  1394. {
  1395. LOCKOBJ (pMiniport, pSR);
  1396. epvcLinkToExternal( &pMiniport->Hdr,
  1397. 0x20bc1fbf,
  1398. (UINT_PTR)pSetFilterWorItem,
  1399. EPVC_ASSOC_SET_FILTER_WORKITEM,
  1400. " PacketFilterWorkItem %p\n",
  1401. pSR);
  1402. //
  1403. // Update the cause of the task
  1404. //
  1405. UNLOCKOBJ(pMiniport, pSR);
  1406. //
  1407. // Now schedule the work item so it runs at passive level and pass the Vc as
  1408. // an argument
  1409. //
  1410. pMiniport->vc.NewFilter = Filter;
  1411. NdisInitializeWorkItem ( pSetFilterWorItem ,
  1412. (NDIS_PROC)epvcSetPacketFilterWorkItem ,
  1413. (PVOID)pTask );
  1414. NdisScheduleWorkItem (pSetFilterWorItem );
  1415. Status = NDIS_STATUS_PENDING;
  1416. } while (FALSE);
  1417. TRACE (TL_T, TM_Mp, ("<==epvcSetPacketFilter %x", Status));
  1418. EXIT();
  1419. return Status;
  1420. }
  1421. NDIS_STATUS
  1422. EpvcMpQueryInformation(
  1423. IN NDIS_HANDLE MiniportAdapterContext,
  1424. IN NDIS_OID Oid,
  1425. IN PVOID InformationBuffer,
  1426. IN ULONG InformationBufferLength,
  1427. OUT PULONG BytesWritten,
  1428. OUT PULONG BytesNeeded
  1429. )
  1430. /*++
  1431. Routine Description:
  1432. The QueryInformation Handler for the virtual miniport.
  1433. Arguments:
  1434. MiniportAdapterContext - a pointer to the Elan.
  1435. Oid - the NDIS_OID to process.
  1436. InformationBuffer - a pointer into the NdisRequest->InformationBuffer
  1437. into which store the result of the query.
  1438. InformationBufferLength - a pointer to the number of bytes left in the
  1439. InformationBuffer.
  1440. BytesWritten - a pointer to the number of bytes written into the
  1441. InformationBuffer.
  1442. BytesNeeded - If there is not enough room in the information
  1443. buffer then this will contain the number of bytes
  1444. needed to complete the request.
  1445. Return Value:
  1446. The function value is the status of the operation.
  1447. --*/
  1448. {
  1449. ENTER ("EpvcMpQueryInformation", 0x3da2473b)
  1450. UINT BytesLeft = InformationBufferLength;
  1451. PUCHAR InfoBuffer = (PUCHAR)(InformationBuffer);
  1452. NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
  1453. NDIS_HARDWARE_STATUS HardwareStatus = NdisHardwareStatusReady;
  1454. NDIS_MEDIUM Medium;
  1455. PEPVC_I_MINIPORT pMiniport = NULL;
  1456. PEPVC_ADAPTER pAdapter= NULL;
  1457. ULONG GenericULong =0;
  1458. USHORT GenericUShort=0;
  1459. UCHAR GenericArray[6];
  1460. UINT MoveBytes = sizeof(ULONG);
  1461. PVOID MoveSource = (PVOID)(&GenericULong);
  1462. ULONG i=0;
  1463. BOOLEAN IsShuttingDown = FALSE;
  1464. RM_DECLARE_STACK_RECORD (SR);
  1465. TRACE(TL_T, TM_Rq, ("==>EpvcMpQueryInformation pMiniport %x, Oid, Buffer %x, Length, %x",
  1466. pMiniport,
  1467. Oid,
  1468. InformationBuffer,
  1469. InformationBufferLength));
  1470. pMiniport = (PEPVC_I_MINIPORT)MiniportAdapterContext;
  1471. LOCKOBJ(pMiniport, &SR);
  1472. IsShuttingDown = (! MiniportTestFlag(pMiniport, fMP_MiniportInitialized));
  1473. pAdapter = pMiniport->pAdapter;
  1474. UNLOCKOBJ(pMiniport,&SR);
  1475. //
  1476. // Switch on request type
  1477. //
  1478. switch (Oid)
  1479. {
  1480. case OID_GEN_MAC_OPTIONS:
  1481. TRACE (TL_V, TM_Rq,(" Miniport Query OID_GEN_MAC_OPTIONS"));
  1482. GenericULong =
  1483. NDIS_MAC_OPTION_NO_LOOPBACK;
  1484. break;
  1485. case OID_GEN_SUPPORTED_LIST:
  1486. TRACE (TL_V, TM_Rq,(" Miniport Query OID_GEN_SUPPORTED_LIST"));
  1487. MoveSource = (PVOID)(EthernetSupportedOids);
  1488. MoveBytes = sizeof(EthernetSupportedOids);
  1489. break;
  1490. case OID_GEN_HARDWARE_STATUS:
  1491. TRACE (TL_V, TM_Rq,(" Miniport Query OID_GEN_HARDWARE_STATUS"));
  1492. HardwareStatus = NdisHardwareStatusReady;
  1493. MoveSource = (PVOID)(&HardwareStatus);
  1494. MoveBytes = sizeof(NDIS_HARDWARE_STATUS);
  1495. break;
  1496. case OID_GEN_MEDIA_CONNECT_STATUS:
  1497. TRACE (TL_V, TM_Rq,(" Miniport Query OID_GEN_MEDIA_CONNECT_STATUS"));
  1498. MoveSource = (PVOID)(&pMiniport->info.MediaState);
  1499. MoveBytes = sizeof(NDIS_MEDIA_STATE);
  1500. break;
  1501. case OID_GEN_MEDIA_SUPPORTED:
  1502. case OID_GEN_MEDIA_IN_USE:
  1503. TRACE (TL_V, TM_Rq,(" Miniport Query OID_GEN_MEDIA_SUPPORTED"));
  1504. Medium = ATMEPVC_MP_MEDIUM;
  1505. MoveSource = (PVOID) (&Medium);
  1506. MoveBytes = sizeof(NDIS_MEDIUM);
  1507. break;
  1508. case OID_GEN_MAXIMUM_LOOKAHEAD:
  1509. TRACE (TL_V, TM_Rq,(" Miniport Query OID_GEN_MAXIMUM_LOOKAHEAD"));
  1510. GenericULong = pMiniport->info.CurLookAhead;
  1511. break;
  1512. case OID_GEN_CURRENT_LOOKAHEAD:
  1513. TRACE (TL_V, TM_Rq,(" Miniport Query OID_GEN_CURRENT_LOOKAHEAD"));
  1514. GenericULong = pMiniport->info.CurLookAhead ;
  1515. break;
  1516. case OID_GEN_MAXIMUM_FRAME_SIZE:
  1517. TRACE (TL_V, TM_Rq,(" Miniport Query OID_GEN_MAXIMUM_FRAME_SIZE"));
  1518. //
  1519. // Similiar to AtmLane . Take the size of the Ethernet frame and strip the
  1520. // ethernet header off.
  1521. //
  1522. GenericULong = EPVC_MAX_FRAME_SIZE - EPVC_ETH_HEADERSIZE ;
  1523. break;
  1524. case OID_GEN_MAXIMUM_TOTAL_SIZE:
  1525. TRACE (TL_V, TM_Rq,(" Miniport Query OID_GEN_MAXIMUM_TOTAL_SIZE"));
  1526. //
  1527. // This value is inclusive of headers
  1528. //
  1529. GenericULong = EPVC_MAX_FRAME_SIZE;
  1530. break;
  1531. case OID_GEN_TRANSMIT_BLOCK_SIZE:
  1532. TRACE (TL_V, TM_Rq,(" Miniport Query OID_GEN_TRANSMIT_BLOCK_SIZE"));
  1533. //
  1534. // This is inclusive of headers.
  1535. //
  1536. GenericULong = EPVC_MAX_FRAME_SIZE;
  1537. break;
  1538. case OID_GEN_RECEIVE_BLOCK_SIZE:
  1539. TRACE (TL_V, TM_Rq,(" Miniport Query OID_GEN_RECEIVE_BLOCK_SIZE"));
  1540. GenericULong = EPVC_MAX_FRAME_SIZE ;
  1541. break;
  1542. case OID_GEN_MAXIMUM_SEND_PACKETS:
  1543. TRACE (TL_V, TM_Rq,(" Miniport Query OID_GEN_MAXIMUM_SEND_PACKETS"));
  1544. GenericULong = 32; // XXX What is our limit? From adapter?
  1545. break;
  1546. case OID_GEN_LINK_SPEED:
  1547. TRACE (TL_V, TM_Rq,(" Miniport Query OID_GEN_LINK_SPEED"));
  1548. GenericULong = pMiniport->info.LinkSpeed;
  1549. break;
  1550. case OID_GEN_TRANSMIT_BUFFER_SPACE:
  1551. case OID_GEN_RECEIVE_BUFFER_SPACE:
  1552. TRACE (TL_V, TM_Rq,(" Miniport Query OID_GEN_RECEIVE_BUFFER_SPACE"));
  1553. GenericULong = 32 * 1024; // XXX What should this really be?
  1554. break;
  1555. case OID_GEN_VENDOR_ID:
  1556. TRACE (TL_V, TM_Rq,(" Miniport Query OID_GEN_VENDOR_ID"));
  1557. NdisMoveMemory(
  1558. (PVOID)&GenericULong,
  1559. &pMiniport->MacAddressEth,
  1560. 3
  1561. );
  1562. GenericULong &= 0xFFFFFF00;
  1563. MoveSource = (PVOID)(&GenericULong);
  1564. MoveBytes = sizeof(GenericULong);
  1565. break;
  1566. case OID_GEN_VENDOR_DESCRIPTION:
  1567. TRACE (TL_V, TM_Rq,(" Miniport Query OID_GEN_VENDOR_DESCRIPTION"));
  1568. MoveSource = (PVOID)"Microsoft ATM Ethernet Emulation";
  1569. MoveBytes = 28;
  1570. break;
  1571. case OID_GEN_DRIVER_VERSION:
  1572. case OID_GEN_VENDOR_DRIVER_VERSION:
  1573. TRACE (TL_V, TM_Rq,(" Miniport Query OID_GEN_DRIVER_VERSION"));
  1574. GenericUShort = ((USHORT)5 << 8) | 0;
  1575. MoveSource = (PVOID)(&GenericUShort);
  1576. MoveBytes = sizeof(GenericUShort);
  1577. break;
  1578. case OID_802_3_PERMANENT_ADDRESS:
  1579. case OID_802_3_CURRENT_ADDRESS:
  1580. TRACE (TL_V, TM_Rq,(" Miniport Query OID_802_3_CURRENT_ADDRESS"));
  1581. NdisMoveMemory((PCHAR)GenericArray,
  1582. &pMiniport->MacAddressEth,
  1583. sizeof(MAC_ADDRESS));
  1584. MoveSource = (PVOID)(GenericArray);
  1585. MoveBytes = sizeof(MAC_ADDRESS);
  1586. break;
  1587. case OID_802_3_MULTICAST_LIST:
  1588. TRACE (TL_V, TM_Rq,(" Miniport Query OID_802_3_MULTICAST_LIST"));
  1589. MoveSource = (PVOID) &pMiniport->info.McastAddrs[0];
  1590. MoveBytes = pMiniport->info.McastAddrCount * sizeof(MAC_ADDRESS);
  1591. break;
  1592. case OID_802_3_MAXIMUM_LIST_SIZE:
  1593. TRACE (TL_V, TM_Rq,(" Miniport Query OID_802_3_MAXIMUM_LIST_SIZE"));
  1594. GenericULong = MCAST_LIST_SIZE;
  1595. break;
  1596. case OID_GEN_XMIT_OK:
  1597. TRACE (TL_V, TM_Rq,(" Miniport Query OID_GEN_XMIT_OK"));
  1598. GenericULong = (UINT)(pMiniport->count.FramesXmitOk);
  1599. break;
  1600. case OID_GEN_RCV_OK:
  1601. TRACE (TL_V, TM_Rq,(" Miniport Query OID_GEN_RCV_OK"));
  1602. GenericULong = (UINT)(pMiniport->count.FramesRecvOk);
  1603. break;
  1604. case OID_GEN_RCV_ERROR:
  1605. TRACE (TL_V, TM_Rq,(" Miniport Query OID_GEN_RCV_OK"));
  1606. GenericULong = pMiniport->count.RecvDropped ;
  1607. break;
  1608. case OID_GEN_XMIT_ERROR:
  1609. case OID_GEN_RCV_NO_BUFFER:
  1610. case OID_802_3_RCV_ERROR_ALIGNMENT:
  1611. case OID_802_3_XMIT_ONE_COLLISION:
  1612. case OID_802_3_XMIT_MORE_COLLISIONS:
  1613. TRACE (TL_V, TM_Rq,(" Miniport Query - Unimplemented Stats Oid"));
  1614. GenericULong = 0;
  1615. break;
  1616. default:
  1617. StatusToReturn = NDIS_STATUS_INVALID_OID;
  1618. break;
  1619. }
  1620. if (StatusToReturn == NDIS_STATUS_SUCCESS)
  1621. {
  1622. if (MoveBytes > BytesLeft)
  1623. {
  1624. //
  1625. // Not enough room in InformationBuffer. Punt
  1626. //
  1627. *BytesNeeded = MoveBytes;
  1628. StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
  1629. }
  1630. else
  1631. {
  1632. //
  1633. // Store and print result.
  1634. //
  1635. NdisMoveMemory(InfoBuffer, MoveSource, MoveBytes);
  1636. TRACE (TL_V, TM_Rq, ("Query Request Oid %x", Oid));
  1637. DUMPDW( TL_V, TM_Rq, MoveSource, MoveBytes);
  1638. (*BytesWritten) = MoveBytes;
  1639. }
  1640. }
  1641. TRACE(TL_T, TM_Rq, ("<==EpvcMpQueryInformation Status %x",StatusToReturn));
  1642. RM_ASSERT_CLEAR(&SR);
  1643. return StatusToReturn;
  1644. }
  1645. NDIS_STATUS
  1646. EpvcMpSetInformation(
  1647. IN NDIS_HANDLE MiniportAdapterContext,
  1648. IN NDIS_OID Oid,
  1649. IN PVOID InformationBuffer,
  1650. IN ULONG InformationBufferLength,
  1651. OUT PULONG BytesRead,
  1652. OUT PULONG BytesNeeded
  1653. )
  1654. /*++
  1655. Routine Description:
  1656. Handles a set operation for a single OID.
  1657. Arguments:
  1658. MiniportAdapterContext - a pointer to the Elan.
  1659. Oid - the NDIS_OID to process.
  1660. InformationBuffer - Holds the data to be set.
  1661. InformationBufferLength - The length of InformationBuffer.
  1662. BytesRead - If the call is successful, returns the number
  1663. of bytes read from InformationBuffer.
  1664. BytesNeeded - If there is not enough data in InformationBuffer
  1665. to satisfy the OID, returns the amount of storage
  1666. needed.
  1667. Return Value:
  1668. NDIS_STATUS_SUCCESS
  1669. NDIS_STATUS_PENDING
  1670. NDIS_STATUS_INVALID_LENGTH
  1671. NDIS_STATUS_INVALID_OID
  1672. --*/
  1673. {
  1674. ENTER ("EpvcMpSetInformation", 0x619a7528)
  1675. NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
  1676. UINT BytesLeft = InformationBufferLength;
  1677. PUCHAR InfoBuffer = (PUCHAR)(InformationBuffer);
  1678. UINT OidLength;
  1679. ULONG LookAhead;
  1680. ULONG Filter;
  1681. PEPVC_I_MINIPORT pMiniport = NULL;
  1682. PEPVC_ADAPTER pAdapter = NULL;
  1683. BOOLEAN IsShuttingDown = FALSE;
  1684. RM_DECLARE_STACK_RECORD (SR);
  1685. TRACE(TL_T, TM_Mp, ("==>EpvcMpSetInformation pMiniport %x, Oid, Buffer %x, Length, %x",
  1686. pMiniport,
  1687. Oid,
  1688. InformationBuffer,
  1689. InformationBufferLength));
  1690. pMiniport = (PEPVC_I_MINIPORT)MiniportAdapterContext;
  1691. LOCKOBJ(pMiniport, &SR);
  1692. IsShuttingDown =(! MiniportTestFlag(pMiniport, fMP_MiniportInitialized));
  1693. pAdapter = pMiniport->pAdapter;
  1694. UNLOCKOBJ(pMiniport,&SR);
  1695. if (IsShuttingDown)
  1696. {
  1697. TRACE (TL_I, TM_Mp,(" Miniport shutting down. Trivially succeeding Set OID %x \n", Oid ));
  1698. *BytesRead = 0;
  1699. *BytesNeeded = 0;
  1700. StatusToReturn = NDIS_STATUS_SUCCESS;
  1701. return (StatusToReturn);
  1702. }
  1703. //
  1704. // Get Oid and Length of request
  1705. //
  1706. OidLength = BytesLeft;
  1707. switch (Oid)
  1708. {
  1709. case OID_802_3_MULTICAST_LIST:
  1710. TRACE (TL_V, TM_Rq,(" Miniport Set OID_802_3_MULTICAST_LIST"));
  1711. if (OidLength % sizeof(MAC_ADDRESS))
  1712. {
  1713. StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
  1714. *BytesRead = 0;
  1715. *BytesNeeded = 0;
  1716. break;
  1717. }
  1718. if (OidLength > (MCAST_LIST_SIZE * sizeof(MAC_ADDRESS)))
  1719. {
  1720. StatusToReturn = NDIS_STATUS_MULTICAST_FULL;
  1721. *BytesRead = 0;
  1722. *BytesNeeded = 0;
  1723. break;
  1724. }
  1725. NdisZeroMemory(
  1726. &pMiniport->info.McastAddrs[0],
  1727. MCAST_LIST_SIZE * sizeof(MAC_ADDRESS)
  1728. );
  1729. NdisMoveMemory(
  1730. &pMiniport->info.McastAddrs[0],
  1731. InfoBuffer,
  1732. OidLength
  1733. );
  1734. pMiniport->info.McastAddrCount = OidLength / sizeof(MAC_ADDRESS);
  1735. break;
  1736. case OID_GEN_CURRENT_PACKET_FILTER:
  1737. TRACE (TL_V, TM_Rq,(" Miniport Set OID_GEN_CURRENT_PACKET_FILTER"));
  1738. //
  1739. // Verify length
  1740. //
  1741. if (OidLength != sizeof(ULONG))
  1742. {
  1743. StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
  1744. *BytesRead = 0;
  1745. *BytesNeeded = sizeof(ULONG);
  1746. ASSERT (0);
  1747. break;
  1748. }
  1749. BytesLeft = sizeof (ULONG);
  1750. //
  1751. // Store the new value.
  1752. //
  1753. NdisMoveMemory(&Filter, InfoBuffer, BytesLeft );
  1754. //
  1755. // Don't allow promisc mode, because we can't support that.
  1756. //
  1757. if (Filter & NDIS_PACKET_TYPE_PROMISCUOUS)
  1758. {
  1759. StatusToReturn = NDIS_STATUS_NOT_SUPPORTED;
  1760. break;
  1761. }
  1762. StatusToReturn = epvcSetPacketFilter(pMiniport, Filter, &SR);
  1763. break;
  1764. case OID_802_5_CURRENT_FUNCTIONAL:
  1765. case OID_802_5_CURRENT_GROUP:
  1766. TRACE (TL_V, TM_Rq,(" Miniport Set OID_802_5_CURRENT_GROUP"));
  1767. // XXX just accept whatever for now ???
  1768. break;
  1769. case OID_GEN_CURRENT_LOOKAHEAD:
  1770. TRACE (TL_V, TM_Rq,(" Miniport Set OID_GEN_CURRENT_LOOKAHEAD"));
  1771. //
  1772. // Verify length
  1773. //
  1774. if (OidLength != 4)
  1775. {
  1776. StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
  1777. *BytesRead = 0;
  1778. *BytesNeeded = 0;
  1779. break;
  1780. }
  1781. //
  1782. // Store the new value.
  1783. //
  1784. NdisMoveMemory(&LookAhead, InfoBuffer, 4);
  1785. ASSERT (pMiniport->pAdapter != NULL);
  1786. if (LookAhead <= pAdapter->info.MaxAAL5PacketSize)
  1787. {
  1788. pMiniport->info.CurLookAhead = LookAhead;
  1789. TRACE (TL_V, TM_Mp, ("New Lookahead size %x \n",pMiniport->info.CurLookAhead ));
  1790. }
  1791. else
  1792. {
  1793. StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
  1794. }
  1795. break;
  1796. case OID_GEN_NETWORK_LAYER_ADDRESSES:
  1797. TRACE (TL_V, TM_Rq,(" Miniport Set OID_GEN_NETWORK_LAYER_ADDRESSES"));
  1798. StatusToReturn = epvcMpSetNetworkAddresses(
  1799. pMiniport,
  1800. InformationBuffer,
  1801. InformationBufferLength,
  1802. &SR,
  1803. BytesRead,
  1804. BytesNeeded);
  1805. break;
  1806. default:
  1807. StatusToReturn = NDIS_STATUS_INVALID_OID;
  1808. *BytesRead = 0;
  1809. *BytesNeeded = 0;
  1810. break;
  1811. }
  1812. if (StatusToReturn == NDIS_STATUS_SUCCESS)
  1813. {
  1814. *BytesRead = BytesLeft;
  1815. *BytesNeeded = 0;
  1816. DUMPDW( TL_V, TM_Rq, InformationBuffer, *BytesRead );
  1817. }
  1818. TRACE(TL_T, TM_Mp, ("<==EpvcMpSetInformation Status %x",StatusToReturn));
  1819. RM_ASSERT_CLEAR(&SR);
  1820. return StatusToReturn;
  1821. }
  1822. VOID
  1823. epvcMPLocalRequestComplete (
  1824. PEPVC_NDIS_REQUEST pEpvcRequest,
  1825. NDIS_STATUS Status
  1826. )
  1827. /*++
  1828. Routine Description:
  1829. Miniport's local Request Completion handler for the occasion
  1830. when a locally allocated NdisRequest was sent to the miniport below us.
  1831. We look up to see if a request to our miniport edge initiated this request.
  1832. If so, we complete the Set/Query
  1833. Assumes that the epvcRequest was allocated from the HEAP
  1834. Arguments:
  1835. pEpvcRequest - Locally allocated Request structure
  1836. Return Value:
  1837. --*/
  1838. {
  1839. ENTER("epvcMPLocalRequestComplete ", 0x77d107ae)
  1840. PEPVC_I_MINIPORT pMiniport = pEpvcRequest->pMiniport;
  1841. RM_DECLARE_STACK_RECORD (SR);
  1842. //
  1843. // First complete the request that we have pended
  1844. //
  1845. do
  1846. {
  1847. if (pMiniport == NULL || pEpvcRequest->fPendedRequest == FALSE)
  1848. {
  1849. //
  1850. // No pended request to complete
  1851. //
  1852. break;
  1853. }
  1854. if (pEpvcRequest->fSet == TRUE)
  1855. {
  1856. NdisMSetInformationComplete (pMiniport->ndis.MiniportAdapterHandle,
  1857. Status);
  1858. }
  1859. else
  1860. {
  1861. NdisMQueryInformationComplete (pMiniport->ndis.MiniportAdapterHandle,
  1862. Status);
  1863. }
  1864. } while (FALSE);
  1865. if (pMiniport != NULL)
  1866. {
  1867. //
  1868. // Deref the miniport
  1869. //
  1870. epvcUnlinkFromExternal( &pMiniport->Hdr, //pHdr
  1871. 0xaa625b37, // Luid
  1872. (UINT_PTR)pEpvcRequest,// External entity
  1873. EPVC_ASSOC_MINIPORT_REQUEST, // AssocID
  1874. &SR
  1875. );
  1876. }
  1877. //
  1878. // now free the memory that was allocated.
  1879. //
  1880. NdisFreeMemory (pEpvcRequest, sizeof (*pEpvcRequest), 0);
  1881. }
  1882. NDIS_STATUS
  1883. epvcMpSetNetworkAddresses(
  1884. IN PEPVC_I_MINIPORT pMiniport,
  1885. IN PVOID InformationBuffer,
  1886. IN ULONG InformationBufferLength,
  1887. IN PRM_STACK_RECORD pSR,
  1888. OUT PULONG BytesRead,
  1889. OUT PULONG BytesNeeded
  1890. )
  1891. /*++
  1892. Routine Description:
  1893. Called when the protocol above us wants to let us know about
  1894. the network address(es) assigned to this interface. If this is TCP/IP,
  1895. then we reformat and send a request to the ATM Call Manager to set
  1896. its atmfMyIpNmAddress object. We pick the first IP address given to us.
  1897. Arguments:
  1898. pMiniport - Pointer to the ELAN
  1899. InformationBuffer - Holds the data to be set.
  1900. InformationBufferLength - The length of InformationBuffer.
  1901. BytesRead - If the call is successful, returns the number
  1902. of bytes read from InformationBuffer.
  1903. BytesNeeded - If there is not enough data in InformationBuffer
  1904. to satisfy the OID, returns the amount of storage
  1905. needed.
  1906. Return Value:
  1907. NDIS_STATUS_SUCCESS
  1908. NDIS_STATUS_PENDING
  1909. NDIS_STATUS_INVALID_LENGTH
  1910. --*/
  1911. {
  1912. ENTER("epvcMpSetNetworkAddresses" , 0x385441e2)
  1913. NETWORK_ADDRESS_LIST UNALIGNED * pAddrList = NULL;
  1914. NETWORK_ADDRESS UNALIGNED * pAddr = NULL;
  1915. NETWORK_ADDRESS_IP UNALIGNED * pIpAddr= NULL;
  1916. ULONG Size;
  1917. PUCHAR pNetworkAddr = NULL;
  1918. NDIS_HANDLE NdisAdapterHandle;
  1919. NDIS_HANDLE NdisAfHandle;
  1920. NDIS_STATUS Status;
  1921. PEPVC_ADAPTER pAdapter = (PEPVC_ADAPTER)pMiniport->pAdapter;
  1922. //
  1923. // Initialize.
  1924. //
  1925. *BytesRead = 0;
  1926. Status = NDIS_STATUS_SUCCESS;
  1927. pAddrList = (NETWORK_ADDRESS_LIST UNALIGNED *)InformationBuffer;
  1928. do
  1929. {
  1930. *BytesNeeded = sizeof(*pAddrList) -
  1931. FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address) +
  1932. sizeof(NETWORK_ADDRESS) -
  1933. FIELD_OFFSET(NETWORK_ADDRESS, Address);
  1934. if (InformationBufferLength < *BytesNeeded)
  1935. {
  1936. Status = NDIS_STATUS_INVALID_LENGTH;
  1937. break;
  1938. }
  1939. if (pAddrList->AddressType != NDIS_PROTOCOL_ID_TCP_IP)
  1940. {
  1941. // Not interesting.
  1942. break;
  1943. }
  1944. if (pAddrList->AddressCount <= 0)
  1945. {
  1946. Status = NDIS_STATUS_INVALID_DATA;
  1947. break;
  1948. }
  1949. pAddr = (NETWORK_ADDRESS UNALIGNED *)&pAddrList->Address[0];
  1950. if ((pAddr->AddressLength > InformationBufferLength - *BytesNeeded) ||
  1951. (pAddr->AddressLength == 0))
  1952. {
  1953. Status = NDIS_STATUS_INVALID_LENGTH;
  1954. break;
  1955. }
  1956. if (pAddr->AddressType != NDIS_PROTOCOL_ID_TCP_IP)
  1957. {
  1958. // Not interesting.
  1959. break;
  1960. }
  1961. if (pAddr->AddressLength < sizeof(NETWORK_ADDRESS_IP))
  1962. {
  1963. Status = NDIS_STATUS_INVALID_LENGTH;
  1964. break;
  1965. }
  1966. pIpAddr = (NETWORK_ADDRESS_IP UNALIGNED *)&pAddr->Address[0];
  1967. //
  1968. // Allocate an NDIS request to send down to the call manager.
  1969. //
  1970. Size = sizeof(pIpAddr->in_addr);
  1971. Status = epvcAllocateMemoryWithTag(&pNetworkAddr, Size, TAG_DEFAULT );
  1972. if ((FAIL(Status) == TRUE) || pNetworkAddr == NULL)
  1973. {
  1974. Status = NDIS_STATUS_RESOURCES;
  1975. pNetworkAddr = NULL;
  1976. break;
  1977. }
  1978. //
  1979. // Copy the network address in.
  1980. //
  1981. NdisMoveMemory(pNetworkAddr, &pIpAddr->in_addr, sizeof(pIpAddr->in_addr));
  1982. TRACE (TL_V, TM_Mp, (" Set network layer addr: length %d\n", pAddr->AddressLength));
  1983. #if DBG
  1984. if (pAddr->AddressLength >= 4)
  1985. {
  1986. TRACE(TL_V, TM_Mp, ("Network layer addr: %d.%d.%d.%d\n",
  1987. pNetworkAddr[0],
  1988. pNetworkAddr[1],
  1989. pNetworkAddr[2],
  1990. pNetworkAddr[3]));
  1991. }
  1992. #endif // DBG
  1993. //
  1994. // Send off the request.
  1995. //
  1996. {
  1997. PEPVC_NDIS_REQUEST pRequest;
  1998. do
  1999. {
  2000. Status = epvcAllocateMemoryWithTag (&pRequest, sizeof(*pRequest), TAG_DEFAULT) ;
  2001. if (Status != NDIS_STATUS_SUCCESS)
  2002. {
  2003. pRequest = NULL;
  2004. break;
  2005. }
  2006. //
  2007. // There is no failure code path in prepareandsendrequest.
  2008. // Our completion handler will get called and free the memory
  2009. //
  2010. Status = epvcPrepareAndSendNdisRequest(
  2011. pAdapter,
  2012. pRequest,
  2013. epvcMPLocalRequestComplete,
  2014. OID_ATM_MY_IP_NM_ADDRESS,
  2015. pNetworkAddr,
  2016. sizeof(pIpAddr->in_addr),
  2017. NdisRequestSetInformation,
  2018. pMiniport,
  2019. TRUE, // We have Pended a Request
  2020. TRUE, // The Pended request is a Set
  2021. pSR
  2022. );
  2023. } while (FALSE);
  2024. }
  2025. break;
  2026. }
  2027. while (FALSE);
  2028. EXIT();
  2029. return (Status);
  2030. }
  2031. VOID
  2032. epvcSetupMakeCallParameters(
  2033. PEPVC_I_MINIPORT pMiniport,
  2034. PCO_CALL_PARAMETERS *ppCallParameters
  2035. )
  2036. /*++
  2037. Routine Description:
  2038. Sets up the Call parameters after reading the information
  2039. from the miniport block
  2040. Arguments:
  2041. pMiniport - Miniport in question
  2042. ppCallParameter - Location of Call Parameters
  2043. Return Value:
  2044. return value *ppCallParamter is NULL on Failure
  2045. --*/
  2046. {
  2047. ULONG RequestSize = 0;
  2048. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  2049. PCO_CALL_PARAMETERS pCallParameters = NULL;
  2050. PCO_CALL_MANAGER_PARAMETERS pCallMgrParameters = NULL;
  2051. PCO_MEDIA_PARAMETERS pMediaParameters = NULL;
  2052. PATM_MEDIA_PARAMETERS pAtmMediaParameters = NULL;
  2053. do
  2054. {
  2055. Status = epvcAllocateMemoryWithTag( &pCallParameters,
  2056. CALL_PARAMETER_SIZE,
  2057. TAG_DEFAULT);
  2058. if (Status != NDIS_STATUS_SUCCESS || pCallParameters == NULL)
  2059. {
  2060. pCallParameters = NULL;
  2061. Status = NDIS_STATUS_RESOURCES;
  2062. break;
  2063. }
  2064. NdisZeroMemory (pCallParameters, CALL_PARAMETER_SIZE);
  2065. //
  2066. // Distribute space and link up pointers amongst the various
  2067. // structures for the PVC.
  2068. //
  2069. // pCallParameters------->+----------------------------+
  2070. // | CO_CALL_PARAMETERS |
  2071. // pCallMgrParameters---->+----------------------------+
  2072. // | CO_CALL_MANAGER_PARAMETERS |
  2073. // pMediaParameters------>+----------------------------+
  2074. // | CO_MEDIA_PARAMETERS |
  2075. // pAtmMediaParameters--->+----------------------------+
  2076. // | ATM_MEDIA_PARAMETERS |
  2077. // +----------------------------+
  2078. //
  2079. pCallMgrParameters = (PCO_CALL_MANAGER_PARAMETERS)
  2080. ((PUCHAR)pCallParameters +
  2081. sizeof(CO_CALL_PARAMETERS));
  2082. pCallParameters->CallMgrParameters = pCallMgrParameters;
  2083. pCallMgrParameters->CallMgrSpecific.ParamType = 0;
  2084. pCallMgrParameters->CallMgrSpecific.Length = 0;
  2085. pMediaParameters = (PCO_MEDIA_PARAMETERS)
  2086. pCallMgrParameters->CallMgrSpecific.Parameters;
  2087. pCallParameters->MediaParameters = pMediaParameters;
  2088. pAtmMediaParameters = (PATM_MEDIA_PARAMETERS)
  2089. pMediaParameters->MediaSpecific.Parameters;
  2090. //
  2091. // Call Manager generic flow paramters:
  2092. //
  2093. pCallMgrParameters->Transmit.TokenRate =
  2094. pMiniport->pAdapter->info.LinkSpeed.Outbound/8*100; // cnvt decibits to bytes
  2095. pCallMgrParameters->Transmit.PeakBandwidth =
  2096. pMiniport->pAdapter->info.LinkSpeed.Outbound/8*100; // cnvt decibits to bytes
  2097. pCallMgrParameters->Transmit.ServiceType = SERVICETYPE_BESTEFFORT;
  2098. pCallMgrParameters->Receive.TokenRate =
  2099. pMiniport->pAdapter->info.LinkSpeed.Inbound/8*100; // cnvt decibits to bytes
  2100. pCallMgrParameters->Receive.PeakBandwidth =
  2101. pMiniport->pAdapter->info.LinkSpeed.Inbound/8*100; // cnvt decibits to bytes
  2102. pCallMgrParameters->Receive.ServiceType = SERVICETYPE_BESTEFFORT;
  2103. //
  2104. // use 1516 per spec
  2105. //
  2106. pCallMgrParameters->Transmit.TokenBucketSize =
  2107. pCallMgrParameters->Transmit.MaxSduSize =
  2108. pCallMgrParameters->Receive.TokenBucketSize =
  2109. pCallMgrParameters->Receive.MaxSduSize =
  2110. 1516;
  2111. //
  2112. // PVC Generic and ATM-specific Media Parameters
  2113. //
  2114. pMediaParameters->Flags = TRANSMIT_VC | RECEIVE_VC;
  2115. pMediaParameters->MediaSpecific.ParamType = ATM_MEDIA_SPECIFIC;
  2116. pMediaParameters->MediaSpecific.Length = sizeof(ATM_MEDIA_PARAMETERS);
  2117. pAtmMediaParameters->ConnectionId.Vpi = pMiniport->config.vpi; //0
  2118. pAtmMediaParameters->ConnectionId.Vci = pMiniport->config.vci;
  2119. TRACE (TL_I, TM_Mp, ("Miniport Configuration vci %x ,vpi %x",
  2120. pMiniport->config.vci ,
  2121. pMiniport->config.vpi ));
  2122. ASSERT (pMiniport->MaxAcceptablePkt > 1000);
  2123. pAtmMediaParameters->AALType = AAL_TYPE_AAL5;
  2124. pAtmMediaParameters->Transmit.PeakCellRate =
  2125. LINKSPEED_TO_CPS(pMiniport->pAdapter->info.LinkSpeed.Outbound);
  2126. pAtmMediaParameters->Transmit.MaxSduSize = pMiniport->MaxAcceptablePkt ;
  2127. pAtmMediaParameters->Transmit.ServiceCategory =
  2128. ATM_SERVICE_CATEGORY_UBR;
  2129. pAtmMediaParameters->Receive.PeakCellRate =
  2130. LINKSPEED_TO_CPS(pMiniport->pAdapter->info.LinkSpeed.Outbound);
  2131. pAtmMediaParameters->Receive.MaxSduSize = pMiniport->MaxAcceptablePkt ;
  2132. pAtmMediaParameters->Receive.ServiceCategory =
  2133. ATM_SERVICE_CATEGORY_UBR;
  2134. //
  2135. // Set PVC flag here
  2136. //
  2137. pCallParameters->Flags |= PERMANENT_VC;
  2138. } while (FALSE);
  2139. if (Status == NDIS_STATUS_SUCCESS && pCallParameters != NULL)
  2140. {
  2141. //
  2142. // Set up the return value here
  2143. //
  2144. *ppCallParameters = pCallParameters;
  2145. }
  2146. else
  2147. {
  2148. //
  2149. // Clear the Failure case
  2150. //
  2151. *ppCallParameters = NULL;
  2152. }
  2153. }
  2154. VOID
  2155. epvcRefRecvPkt(
  2156. PNDIS_PACKET pNdisPacket,
  2157. PRM_OBJECT_HEADER pHdr // either an adapter or a miniport
  2158. )
  2159. {
  2160. // The following macros are just so that we can make
  2161. // the proper debug association
  2162. // depending on how closely we are tracking outstanding packets.
  2163. //
  2164. #define OUR_EXTERNAL_ENTITY ((UINT_PTR) pNdisPacket)
  2165. #define szEPVCASSOC_EXTLINK_INDICATED_PKT_FORMAT " indicated pkt 0x%p\n"
  2166. //
  2167. // If ARPDBG_REF_EVERY_PKT
  2168. // We add an "external" link for EVERY packet. We'll later remove this
  2169. // reference when the send completes for this packet.
  2170. // else
  2171. // Only a transition from zero to non-zero outstanding sends, we
  2172. // add an "external" link. We'll later remove this link when the
  2173. // transition from non-zero to zero happens.
  2174. //
  2175. #if RM_EXTRA_CHECKING
  2176. RM_DECLARE_STACK_RECORD(sr)
  2177. epvcLinkToExternal (
  2178. pHdr, // pHdr
  2179. 0x92036e12, // LUID
  2180. OUR_EXTERNAL_ENTITY, // External entity
  2181. EPVC_ASSOC_EXTLINK_INDICATED_PKT, // AssocID
  2182. szEPVCASSOC_EXTLINK_INDICATED_PKT_FORMAT ,
  2183. &sr
  2184. );
  2185. #else // !RM_EXTRA_CHECKING
  2186. RmLinkToExternalFast(pHdr);
  2187. #endif // !RM_EXTRA_CHECKING
  2188. #undef OUR_EXTERNAL_ENTITY
  2189. #undef szEPVCASSOC_EXTLINK_INDICATED_PKT_FORMAT
  2190. #if RM_EXTRA_CHECKING
  2191. RM_ASSERT_CLEAR(&sr);
  2192. #endif
  2193. }
  2194. VOID
  2195. epvcDerefRecvPkt (
  2196. PNDIS_PACKET pNdisPacket,
  2197. PRM_OBJECT_HEADER pHdr
  2198. )
  2199. {
  2200. // The following macros are just so that we can make
  2201. // the proper debug association
  2202. // depending on how closely we are tracking outstanding send packets.
  2203. //
  2204. #if RM_EXTRA_CHECKING
  2205. RM_DECLARE_STACK_RECORD(sr)
  2206. epvcUnlinkFromExternal(
  2207. pHdr, // pHdr
  2208. 0x110ad55b, // LUID
  2209. (UINT_PTR)pNdisPacket, // External entity
  2210. EPVC_ASSOC_EXTLINK_INDICATED_PKT, // AssocID
  2211. &sr
  2212. );
  2213. #else // !RM_EXTRA_CHECKING
  2214. RmUnlinkFromExternalFast (pHdr);
  2215. #endif // !RM_EXTRA_CHECKING
  2216. #if RM_EXTRA_CHECKING
  2217. RM_ASSERT_CLEAR(&sr);
  2218. #endif
  2219. }
  2220. VOID
  2221. epvcDerefSendPkt (
  2222. PNDIS_PACKET pNdisPacket,
  2223. PRM_OBJECT_HEADER pHdr
  2224. )
  2225. {
  2226. // The following macros are just so that we can make
  2227. // the proper debug association
  2228. // depending on how closely we are tracking outstanding send packets.
  2229. //
  2230. #if RM_EXTRA_CHECKING
  2231. RM_DECLARE_STACK_RECORD(sr)
  2232. epvcUnlinkFromExternal(
  2233. pHdr, // pHdr
  2234. 0xf43e0a10, // LUID
  2235. (UINT_PTR)pNdisPacket, // External entity
  2236. EPVC_ASSOC_EXTLINK_PKT_TO_SEND, // AssocID
  2237. &sr
  2238. );
  2239. #else // !RM_EXTRA_CHECKING
  2240. RmUnlinkFromExternalFast (pHdr);
  2241. #endif // !RM_EXTRA_CHECKING
  2242. #if RM_EXTRA_CHECKING
  2243. RM_ASSERT_CLEAR(&sr);
  2244. #endif
  2245. }
  2246. VOID
  2247. epvcRefSendPkt(
  2248. PNDIS_PACKET pNdisPacket,
  2249. PRM_OBJECT_HEADER pHdr // either an adapter or a miniport
  2250. )
  2251. {
  2252. // The following macros are just so that we can make
  2253. // the proper debug association
  2254. // depending on how closely we are tracking outstanding send packets.
  2255. //
  2256. #define OUR_EXTERNAL_ENTITY ((UINT_PTR) pNdisPacket)
  2257. #define szEPVCASSOC_EXTLINK_DEST_TO_PKT_FORMAT " send pkt 0x%p\n"
  2258. #if RM_EXTRA_CHECKING
  2259. RM_DECLARE_STACK_RECORD(sr)
  2260. epvcLinkToExternal (
  2261. pHdr, // pHdr
  2262. 0xabd17475, // LUID
  2263. OUR_EXTERNAL_ENTITY, // External entity
  2264. EPVC_ASSOC_EXTLINK_PKT_TO_SEND, // AssocID
  2265. szEPVCASSOC_EXTLINK_DEST_TO_PKT_FORMAT ,
  2266. &sr
  2267. );
  2268. #else // !RM_EXTRA_CHECKING
  2269. RmLinkToExternalFast(pHdr);
  2270. #endif // !RM_EXTRA_CHECKING
  2271. #undef OUR_EXTERNAL_ENTITY
  2272. #undef szEPVCASSOC_EXTLINK_DEST_TO_PKT_FORMAT
  2273. #if RM_EXTRA_CHECKING
  2274. RM_ASSERT_CLEAR(&sr);
  2275. #endif
  2276. }
  2277. VOID
  2278. epvcExtractPktInfo (
  2279. PEPVC_I_MINIPORT pMiniport,
  2280. PNDIS_PACKET pPacket ,
  2281. PEPVC_SEND_STRUCT pSendStruct
  2282. )
  2283. /*++
  2284. Routine Description:
  2285. Arguments:
  2286. Return Value:
  2287. --*/
  2288. {
  2289. pSendStruct->pOldPacket = pPacket;
  2290. pSendStruct->pMiniport = pMiniport;
  2291. epvcSetSendPktStats();
  2292. }
  2293. NDIS_STATUS
  2294. epvcSendRoutine(
  2295. IN PEPVC_I_MINIPORT pMiniport,
  2296. IN PNDIS_PACKET Packet,
  2297. PRM_STACK_RECORD pSR
  2298. )
  2299. /*++
  2300. Routine Description:
  2301. This routine does all the hard work.
  2302. It responds to arps if necessary..
  2303. It removes Ethernet Headers if necessary
  2304. It allocates a new packet if necessary
  2305. It sends the new packet on the wire
  2306. Arguments:
  2307. pMiniport - Miniport in question
  2308. Packet - Packet to be sent
  2309. Return Value:
  2310. Returns Pending, otherwise expects the calling
  2311. routine to complete the packet
  2312. --*/
  2313. {
  2314. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  2315. PNDIS_PACKET pNewPkt = NULL;
  2316. EPVC_SEND_STRUCT SendStruct;
  2317. TRACE (TL_T, TM_Send, ("==>epvcSendRoutine") );
  2318. EPVC_ZEROSTRUCT (&SendStruct);
  2319. do
  2320. {
  2321. epvcExtractPktInfo (pMiniport, Packet, &SendStruct );
  2322. //
  2323. // if we are doing IP encapsulation, then respond
  2324. // to the Arp
  2325. //
  2326. if (pMiniport->fDoIpEncapsulation == TRUE)
  2327. {
  2328. //
  2329. // We need to do some special processing for this packet
  2330. //
  2331. SendStruct.fIsThisAnArp = \
  2332. epvcCheckAndReturnArps (pMiniport,
  2333. Packet ,
  2334. &SendStruct,
  2335. pSR);
  2336. if (SendStruct.fIsThisAnArp == TRUE )
  2337. {
  2338. Status = NDIS_STATUS_SUCCESS;
  2339. break ; // Arps are not sent to the atm driver
  2340. }
  2341. if (SendStruct.fNotIPv4Pkt == TRUE)
  2342. {
  2343. // This is not an IPv4 packet. Fail the send.
  2344. Status = NDIS_STATUS_FAILURE;
  2345. break;
  2346. }
  2347. }
  2348. //
  2349. // Allocate a new packet to be sent
  2350. //
  2351. epvcGetSendPkt(pMiniport,
  2352. Packet,
  2353. &SendStruct,
  2354. pSR);
  2355. if (SendStruct.pNewPacket == NULL)
  2356. {
  2357. ASSERTAndBreak (SendStruct.pNewPacket != NULL);
  2358. }
  2359. //
  2360. // SendStruct.pNewPacket is guaranteed to have the NdisBuffers Set up
  2361. //
  2362. // Remove Ethernet Header - if necessary
  2363. //
  2364. Status = epvcRemoveEthernetHeader (&SendStruct, pSR);
  2365. if (Status != NDIS_STATUS_SUCCESS)
  2366. {
  2367. ASSERTAndBreak (Status == NDIS_STATUS_SUCCESS)
  2368. }
  2369. //
  2370. // Add Ethernet Padding - if necessary
  2371. //
  2372. Status = epvcAddEthernetTail (&SendStruct, pSR);
  2373. if (Status != NDIS_STATUS_SUCCESS)
  2374. {
  2375. ASSERTAndBreak (Status == NDIS_STATUS_SUCCESS)
  2376. }
  2377. //
  2378. // Add Ethernet Pad 0x00 0x00 to head of packet - if necessary
  2379. //
  2380. Status = epvcAddEthernetPad (&SendStruct, pSR);
  2381. if (Status != NDIS_STATUS_SUCCESS)
  2382. {
  2383. ASSERTAndBreak (Status == NDIS_STATUS_SUCCESS)
  2384. }
  2385. //
  2386. // Add LLC Encapsulation - if necessary
  2387. //
  2388. Status = epvcAddLLCEncapsulation (pMiniport , Packet, SendStruct.pNewPacket, pSR);
  2389. if (Status != NDIS_STATUS_SUCCESS)
  2390. {
  2391. ASSERTAndBreak (Status == NDIS_STATUS_SUCCESS)
  2392. }
  2393. //
  2394. // set the context information for the send complete
  2395. //
  2396. epvcSetPacketContext (&SendStruct, pSR);
  2397. //
  2398. // Only Send if successful
  2399. //
  2400. epvcDumpPkt (SendStruct.pNewPacket);
  2401. Status = epvcAdapterSend(pMiniport,
  2402. SendStruct.pNewPacket,
  2403. pSR);
  2404. } while (FALSE);
  2405. if (Status != NDIS_STATUS_PENDING && // We had a failure
  2406. SendStruct.pNewPacket != NULL ) // but we were able to get a packet
  2407. {
  2408. epvcFreeSendPkt (pMiniport, &SendStruct);
  2409. }
  2410. TRACE (TL_T, TM_Send, ("<==epvcSendRoutine") );
  2411. return Status;
  2412. }
  2413. VOID
  2414. EpvcSendPackets(
  2415. IN NDIS_HANDLE MiniportAdapterContext,
  2416. IN PPNDIS_PACKET PacketArray,
  2417. IN UINT NumberOfPackets
  2418. )
  2419. /*++
  2420. Routine Description:
  2421. Send Packet Array handler. Either this or our SendPacket handler is called
  2422. based on which one is enabled in our Miniport Characteristics.
  2423. Arguments:
  2424. MiniportAdapterContext Pointer to our adapter
  2425. PacketArray Set of packets to send
  2426. NumberOfPackets Self-explanatory
  2427. Return Value:
  2428. None
  2429. --*/
  2430. {
  2431. PEPVC_I_MINIPORT pMiniport = (PEPVC_I_MINIPORT)MiniportAdapterContext;
  2432. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  2433. UINT i;
  2434. RM_DECLARE_STACK_RECORD (SR);
  2435. DBGMARK(0xdaab68c3);
  2436. TRACE (TL_T, TM_Send, ("==>EpvcSendPackets pMiniport %p, pPktArray %p, Num %x",
  2437. pMiniport, PacketArray, NumberOfPackets));
  2438. for (i = 0; i < NumberOfPackets; i++)
  2439. {
  2440. PEPVC_PKT_CONTEXT Rsvd;
  2441. PNDIS_PACKET Packet = NULL;
  2442. Packet = PacketArray[i];
  2443. epvcValidatePacket (Packet);
  2444. Status= epvcSendRoutine (pMiniport, Packet, &SR);
  2445. if (Status != NDIS_STATUS_PENDING)
  2446. {
  2447. epvcMSendComplete(pMiniport, Packet , Status);
  2448. }
  2449. }
  2450. TRACE (TL_T, TM_Send, ("<==EpvcSendPackets "));
  2451. RM_ASSERT_CLEAR(&SR);
  2452. return;
  2453. }
  2454. VOID
  2455. epvcFreeSendPkt(
  2456. PEPVC_I_MINIPORT pMiniport,
  2457. IN PEPVC_SEND_STRUCT pSendStruct
  2458. )
  2459. /*++
  2460. Routine Description:
  2461. Pops the packet stack if stacks were used or free the new packet after
  2462. copying the per packet info
  2463. Arguments:
  2464. pMiniport - which the packet was sent to
  2465. pSentPkt - The packet that is being sent.
  2466. ppPkt - the new packet that was allocated or the old one if a stack was available
  2467. --*/
  2468. {
  2469. ENTER ("epvcFreeSendPkt", 0xff3ce0fd)
  2470. PNDIS_PACKET pOldPkt = pSendStruct->pOldPacket;
  2471. PNDIS_PACKET pNewPkt = pSendStruct->pNewPacket;
  2472. TRACE (TL_T, TM_Send, ("==>epvcFreeSendPkt pNewPkt %x, pPOldPkt ",pNewPkt, pOldPkt));
  2473. //
  2474. // Remove the ethernet padding - if necessary
  2475. //
  2476. epvcRemoveEthernetPad (pMiniport, pNewPkt);
  2477. //
  2478. // Remove the Ethernet Tail- if necessary
  2479. //
  2480. epvcRemoveEthernetTail(pMiniport, pNewPkt, &pSendStruct->Context);
  2481. //
  2482. // If the two packets are the same, then we used Packet Stacks
  2483. //
  2484. if (pNewPkt != NULL && pSendStruct->fUsingStacks== FALSE)
  2485. {
  2486. NdisIMCopySendCompletePerPacketInfo (pOldPkt, pNewPkt);
  2487. epvcFreePacket(pNewPkt,&pMiniport->PktPool.Send);
  2488. pNewPkt = pSendStruct->pNewPacket = NULL;
  2489. }
  2490. TRACE (TL_T, TM_Send, ("<==epvcFreeSendPkt pNewPkt %x, pPOldPkt ",pNewPkt, pOldPkt));
  2491. EXIT()
  2492. return;
  2493. }
  2494. VOID
  2495. epvcGetSendPkt (
  2496. IN PEPVC_I_MINIPORT pMiniport,
  2497. IN PNDIS_PACKET pSentPkt,
  2498. OUT PEPVC_SEND_STRUCT pSendStruct,
  2499. IN PRM_STACK_RECORD pSR
  2500. )
  2501. /*++
  2502. Routine Description:
  2503. Allocates an NdisPkt or pushes a Pkt Stack to get a valid NdisPkt that
  2504. can be sent to the adapter below.
  2505. Arguments:
  2506. pMiniport - which the packet was sent to
  2507. pSentPkt - The packet that is being sent.
  2508. ppPkt - the new packet that was allocated or the old one if a stack was available
  2509. --*/
  2510. {
  2511. ENTER ("epvcGetSendPkt", 0x5734054f)
  2512. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  2513. PNDIS_PACKET pNewPkt = NULL;
  2514. BOOLEAN Remaining = FALSE;
  2515. PVOID MediaSpecificInfo = NULL;
  2516. UINT MediaSpecificInfoSize = 0;
  2517. TRACE (TL_T, TM_Send, ("==>epvcGetSendPkt pSentPkt %x",pSentPkt));
  2518. do
  2519. {
  2520. #if PKT_STACKS
  2521. //
  2522. // Packet stacks: Check if we can use the same packet for sending down.
  2523. //
  2524. pStack = NdisIMGetCurrentPacketStack(Packet, &Remaining);
  2525. if (Remaining)
  2526. {
  2527. //
  2528. // We can reuse "Packet".
  2529. //
  2530. // NOTE: if we needed to keep per-packet information in packets
  2531. // sent down, we can use pStack->IMReserved[].
  2532. //
  2533. pNewPkt = pSentPkt;
  2534. pSendStruct->pPktStack = pStack;
  2535. pSendStruct->fUsingStacks = TRUE;
  2536. break;
  2537. }
  2538. #endif
  2539. pSendStruct->fUsingStacks = FALSE;
  2540. epvcAllocatePacket(&Status,
  2541. &pNewPkt,
  2542. &pMiniport->PktPool.Send);
  2543. if (Status == NDIS_STATUS_SUCCESS)
  2544. {
  2545. PNDIS_PACKET_EXTENSION Old, New;
  2546. PEPVC_PKT_CONTEXT Rsvd = NULL;
  2547. Rsvd = (PEPVC_PKT_CONTEXT)(pNewPkt->ProtocolReserved);
  2548. Rsvd->pOriginalPacket = pSentPkt;
  2549. pNewPkt->Private.Flags = NdisGetPacketFlags(pSentPkt);
  2550. pNewPkt->Private.Head = pSentPkt->Private.Head;
  2551. pNewPkt->Private.Tail = pSentPkt->Private.Tail;
  2552. //
  2553. // Copy the OOB Offset from the original packet to the new
  2554. // packet.
  2555. //
  2556. NdisMoveMemory(NDIS_OOB_DATA_FROM_PACKET(pNewPkt),
  2557. NDIS_OOB_DATA_FROM_PACKET(pSentPkt),
  2558. sizeof(NDIS_PACKET_OOB_DATA));
  2559. //
  2560. // Copy relevant parts of the per packet info into the new packet
  2561. //
  2562. NdisIMCopySendPerPacketInfo(pNewPkt, pSentPkt);
  2563. //
  2564. // Copy the Media specific information
  2565. //
  2566. NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO(pSentPkt,
  2567. &MediaSpecificInfo,
  2568. &MediaSpecificInfoSize);
  2569. if (MediaSpecificInfo || MediaSpecificInfoSize)
  2570. {
  2571. NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO(pNewPkt,
  2572. MediaSpecificInfo,
  2573. MediaSpecificInfoSize);
  2574. }
  2575. }
  2576. else
  2577. {
  2578. pNewPkt = NULL;
  2579. }
  2580. } while (FALSE);
  2581. pSendStruct->pNewPacket = pNewPkt;
  2582. TRACE (TL_T, TM_Send, ("<==epvcGetSendPkt pSentPkt %p ppNewPkt %p",pSentPkt, pSendStruct->pNewPacket ));
  2583. EXIT()
  2584. return;
  2585. }
  2586. NDIS_STATUS
  2587. epvcAdapterSend(
  2588. IN PEPVC_I_MINIPORT pMiniport,
  2589. IN PNDIS_PACKET pPkt,
  2590. PRM_STACK_RECORD pSR
  2591. )
  2592. {
  2593. BOOLEAN fDoSend = FALSE;
  2594. PEPVC_ADAPTER pAdapter = pMiniport->pAdapter;
  2595. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  2596. ENTER("epvcAdapterSend", 0x5b014909)
  2597. TRACE (TL_T, TM_Send, (" ==>epvcAdapterSend" ) )
  2598. do
  2599. {
  2600. //
  2601. // Check to see if we have a valid Send Case
  2602. //
  2603. LOCKOBJ (pMiniport, pSR);
  2604. fDoSend = MiniportTestFlag (pMiniport, fMP_MakeCallSucceeded);
  2605. if (fDoSend == FALSE)
  2606. {
  2607. TRACE (TL_V, TM_Send,("Send - MakeCall Not Succeeded"));
  2608. }
  2609. //
  2610. // Add an association while holding the lock
  2611. //
  2612. if (fDoSend == TRUE)
  2613. {
  2614. epvcRefSendPkt(pPkt, &pMiniport->Hdr);
  2615. }
  2616. UNLOCKOBJ (pMiniport, pSR);
  2617. if (fDoSend == TRUE)
  2618. {
  2619. epvcCoSendPackets(pMiniport->vc.VcHandle,
  2620. &pPkt,
  2621. 1
  2622. );
  2623. Status = NDIS_STATUS_PENDING;
  2624. }
  2625. else
  2626. {
  2627. Status = NDIS_STATUS_FAILURE;
  2628. }
  2629. } while (FALSE);
  2630. TRACE (TL_T, TM_Send, (" <==epvcAdapterSend fDoSend %x, Status %x", fDoSend, Status ) )
  2631. return Status;
  2632. }
  2633. VOID
  2634. epvcFormulateArpResponse (
  2635. IN PEPVC_I_MINIPORT pMiniport,
  2636. IN PEPVC_ARP_CONTEXT pArpContext,
  2637. IN PRM_STACK_RECORD pSR
  2638. )
  2639. /*++
  2640. Routine Description:
  2641. This allocates an Arp Packet, looks at the Arp Request, formulates
  2642. a response and sends it up back to the protocol
  2643. Arguments:
  2644. pMiniport - which the packet was sent to
  2645. pArpContext - Contains all the information relating to the Arp.
  2646. the Context Is Allocated on the stack
  2647. Return:
  2648. --*/
  2649. {
  2650. ENTER("epvcFormulateArpResponse", 0x7a763fce)
  2651. PEPVC_ARP_PACKET pResponse = NULL;
  2652. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  2653. PTASK_ARP pTask = NULL;
  2654. TRACE (TL_T, TM_Send, ("==>epvcFormulateArpResponse pMiniport %x, pArpContext %x",
  2655. pMiniport, pArpContext))
  2656. do
  2657. {
  2658. //
  2659. // Allocate a buffer from a lookaside list
  2660. //
  2661. Status = epvcAllocateTask(
  2662. &pMiniport->Hdr, // pParentObject,
  2663. epvcTaskRespondToArp, // pfnHandler,
  2664. 0, // Timeout,
  2665. "Task: Arp Response", // szDescription
  2666. &(PRM_TASK)pTask,
  2667. pSR
  2668. );
  2669. if (FAIL(Status))
  2670. {
  2671. pTask = NULL;
  2672. break;
  2673. }
  2674. //
  2675. // Set up Arp Response
  2676. //
  2677. pResponse = &pTask->Pkt;
  2678. EPVC_ZEROSTRUCT (pResponse);
  2679. {
  2680. //
  2681. // Construct the Ethernet Header
  2682. //
  2683. PEPVC_ETH_HEADER pRespHeader = &pResponse->Header;
  2684. PEPVC_ETH_HEADER pSrcHeader = (PEPVC_ETH_HEADER)pArpContext->pEthHeader;
  2685. ASSERT (pSrcHeader != NULL);
  2686. ASSERT (pRespHeader != NULL);
  2687. //
  2688. // set up the Eth header
  2689. //
  2690. NdisMoveMemory (&pRespHeader->eh_daddr,
  2691. &pSrcHeader->eh_saddr,
  2692. ARP_802_ADDR_LENGTH ) ;
  2693. NdisMoveMemory ( &pRespHeader->eh_saddr,
  2694. &pMiniport->info.MacAddressDummy,
  2695. ARP_802_ADDR_LENGTH );
  2696. pRespHeader->eh_type = pSrcHeader->eh_type; // copy 08 06 over
  2697. }
  2698. {
  2699. //
  2700. // Construct the Arp Response
  2701. //
  2702. PEPVC_ARP_BODY pRespBody = &pResponse->Body;
  2703. PEPVC_ARP_BODY pSrcBody = pArpContext ->pBody;
  2704. ASSERT (pRespBody != NULL);
  2705. ASSERT (pSrcBody != NULL);
  2706. pRespBody->hw = pSrcBody->hw; // Hardware address space. = 00 01
  2707. pRespBody->pro = pSrcBody->pro; // Protocol address space. = 08 00
  2708. pRespBody->hlen = ARP_802_ADDR_LENGTH; // 6
  2709. pRespBody->plen = sizeof (IP_ADDR); // 4
  2710. pRespBody->opcode = net_short(ARP_RESPONSE); // Opcode.
  2711. pRespBody->SenderHwAddr= pMiniport->info.MacAddressDummy; // Source HW address.
  2712. pRespBody->SenderIpAddr = pSrcBody->DestIPAddr ; // Source protocol address.
  2713. pRespBody->DestHwAddr = pSrcBody->SenderHwAddr; // Destination HW address.
  2714. pRespBody->DestIPAddr = pSrcBody->SenderIpAddr; // Destination protocol address.
  2715. }
  2716. //
  2717. // So we have the packet ready for transmission.
  2718. //
  2719. RmStartTask ((PRM_TASK)pTask, 0 , pSR);
  2720. } while (FALSE);
  2721. TRACE (TL_T, TM_Send, ("<==epvcFormulateArpResponse "))
  2722. }
  2723. NDIS_STATUS
  2724. epvcTaskRespondToArp(
  2725. IN struct _RM_TASK * pTask,
  2726. IN RM_TASK_OPERATION Code,
  2727. IN UINT_PTR UserParam,
  2728. IN PRM_STACK_RECORD pSR
  2729. )
  2730. /*++
  2731. Routine Description:
  2732. This function queues a zero timeout timer and indicates a receive
  2733. Arguments:
  2734. Return:
  2735. --*/
  2736. {
  2737. ENTER("epvcTaskRespondToArp", 0xd05c4942)
  2738. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  2739. PEPVC_I_MINIPORT pMiniport = (PEPVC_I_MINIPORT ) RM_PARENT_OBJECT(pTask);
  2740. PTASK_ARP pTaskArp = (PTASK_ARP) pTask;
  2741. PEPVC_ADAPTER pAdapter = (PEPVC_ADAPTER)pMiniport->Hdr.pParentObject;
  2742. enum
  2743. {
  2744. Stage_Start =0, // default
  2745. Stage_DoAllocations,
  2746. Stage_QueuedTimer,
  2747. Stage_PacketReturned,
  2748. Stage_TaskCompleted,
  2749. Stage_End
  2750. }; // To be used in pTask->Hdr.State to indicate the state of the Task
  2751. TRACE ( TL_T, TM_Pt, ("==> epvcTaskRespondToArp %x",pTask->Hdr.State ) );
  2752. switch (pTask->Hdr.State)
  2753. {
  2754. case Stage_Start:
  2755. {
  2756. LOCKOBJ (pMiniport, pSR);
  2757. if (epvcIsThisTaskPrimary ( pTask, &(PRM_TASK)(pMiniport->arps.pTask)) == FALSE)
  2758. {
  2759. PRM_TASK pOtherTask = (PRM_TASK)(pMiniport->arps.pTask);
  2760. RmTmpReferenceObject (&pOtherTask->Hdr, pSR);
  2761. //
  2762. // Set The state so we restart this code after main task completes
  2763. //
  2764. pTask->Hdr.State = Stage_Start;
  2765. UNLOCKOBJ(pMiniport, pSR);
  2766. RmPendTaskOnOtherTask (pTask, 0, pOtherTask, pSR);
  2767. RmTmpDereferenceObject(&pOtherTask->Hdr,pSR);
  2768. Status = NDIS_STATUS_PENDING;
  2769. break;
  2770. }
  2771. //
  2772. // We are the primary task
  2773. //
  2774. //
  2775. // Check to see if the miniport is still active.
  2776. // If it is halting, then we don't need to do any work
  2777. //
  2778. if (MiniportTestFlag(pMiniport, fMP_MiniportInitialized) == FALSE)
  2779. {
  2780. //
  2781. // Our work had been done. So break out and complete the task
  2782. //
  2783. Status = NDIS_STATUS_SUCCESS;
  2784. pTask->Hdr.State = Stage_TaskCompleted;
  2785. UNLOCKOBJ(pMiniport, pSR);
  2786. break;
  2787. }
  2788. UNLOCKOBJ(pMiniport, pSR);
  2789. pTask->Hdr.State = Stage_DoAllocations;
  2790. FALL_THROUGH
  2791. }
  2792. case Stage_DoAllocations:
  2793. {
  2794. PNDIS_BUFFER pBuffer = NULL;
  2795. TRACE (TL_V, TM_Send, ("epvcTaskRespondToArp Stage_DoAllocations Task %p", pTask) );
  2796. //
  2797. // Allocate An NDis Buffer
  2798. //
  2799. epvcAllocateBuffer(&Status,
  2800. &pBuffer,
  2801. NULL, // Pool Handle
  2802. (PVOID)&pTaskArp->Pkt,
  2803. sizeof(pTaskArp->Pkt) ); //Length
  2804. ASSERT (sizeof(pTaskArp->Pkt) == 0x2a);
  2805. if (FAIL(Status) == TRUE)
  2806. {
  2807. pBuffer = NULL;
  2808. pTask->Hdr.State = Stage_TaskCompleted;
  2809. ASSERTAndBreak (!FAIL(Status));
  2810. break;
  2811. }
  2812. //
  2813. // Allocate An Ndis Packet
  2814. //
  2815. epvcAllocatePacket (&Status,
  2816. &pTaskArp->pNdisPacket,
  2817. &pMiniport->PktPool.Recv);
  2818. if (FAIL(Status) == TRUE)
  2819. {
  2820. pTask->Hdr.State = Stage_TaskCompleted;
  2821. pTaskArp->pNdisPacket = NULL;
  2822. //
  2823. // Undo allocations
  2824. //
  2825. epvcFreeBuffer (pBuffer);
  2826. ASSERTAndBreak( !FAIL(Status) );
  2827. }
  2828. //
  2829. // Set up the Ndis Buffer within the NdisPacket
  2830. //
  2831. {
  2832. PNDIS_PACKET_PRIVATE pPktPriv = &pTaskArp->pNdisPacket->Private;
  2833. pPktPriv->Head = pBuffer;
  2834. pPktPriv->Tail = pBuffer;
  2835. pBuffer->Next = NULL;
  2836. }
  2837. //
  2838. // Set up the Arp response
  2839. //
  2840. //
  2841. // Queue the timer
  2842. //
  2843. NdisMInitializeTimer ( &pTaskArp->Timer,
  2844. pMiniport->ndis.MiniportAdapterHandle,
  2845. epvcArpTimer,
  2846. pTaskArp );
  2847. pTask->Hdr.State = Stage_QueuedTimer;
  2848. //
  2849. // Now prepare to be called back througha timer to do the
  2850. // receive indication
  2851. //
  2852. RmSuspendTask(pTask, 0,pSR);
  2853. Status = NDIS_STATUS_PENDING;
  2854. NdisMSetTimer (&pTaskArp->Timer, 0); // Zero timeout
  2855. break;
  2856. }
  2857. case Stage_QueuedTimer:
  2858. {
  2859. TRACE (TL_V, TM_Send, ("epvcTaskRespondToArp Stage_QueuedTimer Task %p", pTask) );
  2860. //
  2861. // The miniport could have been halted during the timer
  2862. //
  2863. if (MiniportTestFlag (pMiniport, fMP_MiniportInitialized) == FALSE)
  2864. {
  2865. pTask->Hdr.State = Stage_TaskCompleted;
  2866. ASSERTAndBreak(MiniportTestFlag (pMiniport, fMP_MiniportInitialized) == TRUE);
  2867. }
  2868. NDIS_SET_PACKET_HEADER_SIZE(pTaskArp->pNdisPacket ,
  2869. sizeof (pMiniport->RcvEnetHeader)) ;
  2870. NDIS_SET_PACKET_STATUS (pTaskArp->pNdisPacket, NDIS_STATUS_RESOURCES);
  2871. pTask->Hdr.State = Stage_PacketReturned;
  2872. epvcMIndicateReceivePacket (pMiniport,
  2873. &pTaskArp->pNdisPacket,
  2874. 1 );
  2875. FALL_THROUGH
  2876. }
  2877. case Stage_PacketReturned:
  2878. {
  2879. pTask->Hdr.State = Stage_TaskCompleted;
  2880. Status = NDIS_STATUS_SUCCESS;
  2881. break;
  2882. }
  2883. case Stage_TaskCompleted:
  2884. case Stage_End :
  2885. {
  2886. Status = NDIS_STATUS_SUCCESS;
  2887. break;
  2888. }
  2889. default:
  2890. {
  2891. ASSERTEX(!"Unknown task op", pTask);
  2892. }
  2893. }
  2894. if (pTask->Hdr.State == Stage_TaskCompleted)
  2895. {
  2896. //
  2897. // Free the packet
  2898. //
  2899. pTask->Hdr.State = Stage_End;
  2900. if (pTaskArp->pNdisPacket != NULL)
  2901. {
  2902. //
  2903. // Free the buffer
  2904. //
  2905. PNDIS_PACKET_PRIVATE pPrivate = & pTaskArp->pNdisPacket->Private;
  2906. if (pPrivate -> Head != NULL)
  2907. {
  2908. epvcFreeBuffer (pPrivate->Head );
  2909. pPrivate->Head = pPrivate->Tail = NULL;
  2910. }
  2911. //
  2912. // free the arp packet
  2913. //
  2914. epvcFreePacket (pTaskArp->pNdisPacket , &pMiniport->PktPool.Recv);
  2915. pTaskArp->pNdisPacket = NULL;
  2916. }
  2917. LOCKOBJ (pMiniport, pSR);
  2918. epvcClearPrimaryTask (&(PRM_TASK)(pMiniport->arps.pTask));
  2919. UNLOCKOBJ (pMiniport, pSR);
  2920. Status = NDIS_STATUS_SUCCESS;
  2921. }
  2922. TRACE ( TL_T, TM_Pt, ("<== epvcTaskRespondToArp %x",Status) );
  2923. return Status;
  2924. }
  2925. VOID
  2926. epvcArpTimer(
  2927. IN PVOID SystemSpecific1,
  2928. IN PVOID FunctionContext,
  2929. IN PVOID SystemSpecific2,
  2930. IN PVOID SystemSpecific3
  2931. )
  2932. /*++
  2933. Routine Description:
  2934. Resume the epvcTaskRespondToArp Task
  2935. Arguments:
  2936. Return:
  2937. --*/
  2938. {
  2939. ENTER ("epvcArpTimer",0xf2adae0e)
  2940. PRM_TASK pTask = (PRM_TASK) FunctionContext;
  2941. RM_DECLARE_STACK_RECORD (SR);
  2942. RmResumeTask (pTask,0,&SR);
  2943. EXIT()
  2944. }
  2945. BOOLEAN
  2946. epvcCheckAndReturnArps (
  2947. IN PEPVC_I_MINIPORT pMiniport,
  2948. IN PNDIS_PACKET pPkt,
  2949. IN PEPVC_SEND_STRUCT pSendStruct,
  2950. IN PRM_STACK_RECORD pSR
  2951. )
  2952. /*++
  2953. Routine Description:
  2954. Looks at the packet that is being sent. If it is an Arp request,
  2955. then it formulates a responses and queues a timer of timeout zero to
  2956. return the Arp
  2957. Arguments:
  2958. pMiniport - which the packet was sent to
  2959. pPkt - the packet being sent
  2960. Return:
  2961. True - if this is an Arp Request.
  2962. --*/
  2963. {
  2964. ENTER("epvcCheckAndReturnArps ", 0xb8e6a3c4)
  2965. EPVC_ARP_CONTEXT ArpContext;
  2966. TRACE (TL_T, TM_Send, ("==>epvcCheckAndReturnArps "));
  2967. EPVC_ZEROSTRUCT (&ArpContext);
  2968. do
  2969. {
  2970. ArpContext.pFirstBuffer = pPkt->Private.Head;
  2971. //
  2972. // Do some sanity checks
  2973. //
  2974. if (ArpContext.pFirstBuffer == NULL)
  2975. {
  2976. break;
  2977. }
  2978. NdisQueryBufferSafe( ArpContext.pFirstBuffer ,
  2979. &(PVOID)ArpContext.pEthHeader,
  2980. &ArpContext.BufferLength,
  2981. LowPagePriority );
  2982. if (ArpContext.pEthHeader == NULL)
  2983. {
  2984. break;
  2985. }
  2986. //
  2987. // It the is not an ARP request then ignore it --
  2988. // during testing only
  2989. //
  2990. if (ArpContext.pEthHeader->eh_daddr.Byte[0] == 0xff &&
  2991. ArpContext.pEthHeader->eh_daddr.Byte[1] == 0xff )
  2992. {
  2993. pSendStruct->fNonUnicastPacket = TRUE;
  2994. }
  2995. if (ARP_ETYPE_ARP != net_short(ArpContext.pEthHeader->eh_type))
  2996. {
  2997. //
  2998. // This is not an Arp packet. Is this an IPv4 packet
  2999. //
  3000. if (IP_PROT_TYPE != net_short(ArpContext.pEthHeader->eh_type))
  3001. {
  3002. // If this is not an IPv4 packet, then mark it so that it can
  3003. // be discarded
  3004. pSendStruct->fNotIPv4Pkt = TRUE;
  3005. }
  3006. break;
  3007. }
  3008. //
  3009. // We'll parse the structure using pre-defined structs
  3010. //
  3011. ArpContext.pArpPkt = (PEPVC_ARP_PACKET)ArpContext.pEthHeader;
  3012. ASSERT (ArpContext.BufferLength >= sizeof (EPVC_ARP_PACKET));
  3013. if (ArpContext.BufferLength < sizeof (EPVC_ARP_PACKET))
  3014. {
  3015. //
  3016. // TODO : Add Code to handle this case.
  3017. //
  3018. break;
  3019. }
  3020. ArpContext.pBody = (PEPVC_ARP_BODY)&ArpContext.pArpPkt->Body;
  3021. TRACE (TL_V, TM_Send, ("Received an ARP %p, Body %x\n", ArpContext.pEthHeader, ArpContext.pBody));
  3022. //
  3023. // Validate the Opcode, the prot type, hard size, prot size
  3024. //
  3025. if (ARP_REQUEST != net_short (ArpContext.pBody->opcode ))
  3026. {
  3027. //
  3028. // This is not an Arp request
  3029. //
  3030. break;
  3031. }
  3032. if (IP_PROT_TYPE != net_short(ArpContext.pBody->pro) ||
  3033. ARP_802_ADDR_LENGTH != ArpContext.pBody->hlen ||
  3034. sizeof (IP_ADDR) != ArpContext.pBody->plen )
  3035. {
  3036. //
  3037. // these are just sanity checks
  3038. //
  3039. ASSERT (!"Invalid ARP Packet");
  3040. break;
  3041. }
  3042. //
  3043. // We have a valid ArpRequest
  3044. //
  3045. ArpContext.fIsThisAnArp = TRUE;
  3046. //
  3047. // If tcp/ip is arping for itself, then do not respond... but return
  3048. // TRUE, so that this packet is not sent on the wire
  3049. //
  3050. if (ArpContext.pArpPkt->Body.SenderIpAddr == ArpContext.pArpPkt->Body.DestIPAddr)
  3051. {
  3052. break;
  3053. }
  3054. //
  3055. // Formulate and indicate an Arp Response
  3056. //
  3057. epvcFormulateArpResponse (pMiniport, &ArpContext, pSR);
  3058. } while (FALSE);
  3059. EXIT()
  3060. return ArpContext.fIsThisAnArp ;
  3061. TRACE (TL_T, TM_Send, ("<==epvcCheckAndReturnArps "));
  3062. }
  3063. NDIS_STATUS
  3064. epvcRemoveEthernetHeader(
  3065. PEPVC_SEND_STRUCT pSendStruct,
  3066. IN PRM_STACK_RECORD pSR
  3067. )
  3068. /*++
  3069. Routine Description:
  3070. Expects that the new packet is already set up with
  3071. the Ndis Bufferz
  3072. Arguments:
  3073. pSendStruct - Contains all the arguments that are needed.
  3074. Return:
  3075. True - if this is an Arp Request.
  3076. --*/
  3077. {
  3078. ENTER ("epvcAddLLCEncapsulation" , 0x3ec589c9)
  3079. BOOLEAN fUsedPktStack = pSendStruct->fUsingStacks;
  3080. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  3081. PNDIS_PACKET pNewPkt = pSendStruct->pNewPacket;
  3082. PEPVC_I_MINIPORT pMiniport = pSendStruct->pMiniport;
  3083. TRACE (TL_T, TM_Send, ("==>epvcRemoveEthernetHeader "));
  3084. do
  3085. {
  3086. ULONG BufferLength = 0;
  3087. PNDIS_BUFFER pBuffer = NULL;
  3088. if (pMiniport->fDoIpEncapsulation == FALSE)
  3089. {
  3090. NdisStatus = NDIS_STATUS_SUCCESS;
  3091. break; // we are done
  3092. }
  3093. //
  3094. // There are three ways we can be given a ether net header
  3095. // 1. In a seperate MDL - most often
  3096. // 2. As part of a large MDL - We need to adhust the Virtual address
  3097. // 3. EthernetHeader is seperated across multiple
  3098. // MDLs - not implemented or expected
  3099. //
  3100. pBuffer = pNewPkt->Private.Head;
  3101. BufferLength = NdisBufferLength (pBuffer);
  3102. if (BufferLength < sizeof (EPVC_ETH_HEADER) )
  3103. {
  3104. ASSERTAndBreak (BufferLength >= sizeof (EPVC_ETH_HEADER)) ; // we are done
  3105. }
  3106. //
  3107. // At this point the first buffer is going to be replaced so keep a record of it
  3108. //
  3109. pSendStruct->Context.Stack.ipv4Send.pOldHeadNdisBuffer = pBuffer;
  3110. //
  3111. // New we check to see if all we need to do is make the
  3112. // Packet->Private.Head point to the next MDL
  3113. //
  3114. if (BufferLength == sizeof (EPVC_ETH_HEADER))
  3115. {
  3116. //
  3117. // These are error conditions that should not
  3118. // be handled in our software
  3119. //
  3120. ASSERT (pBuffer->Next != NULL); // no tcp header after the Eth header
  3121. pNewPkt->Private.Head = pBuffer->Next;
  3122. NdisStatus = NDIS_STATUS_SUCCESS;
  3123. break ; // we are done
  3124. }
  3125. if (BufferLength > sizeof (EPVC_ETH_HEADER))
  3126. {
  3127. //
  3128. // Allocate a new NDIS Buffer pointing to start of the IP header w
  3129. // within the current Head (pBuffer)
  3130. //
  3131. PNDIS_BUFFER pNewBuffer = NULL;
  3132. PUCHAR pIpHeader = NdisBufferVirtualAddress(pBuffer);
  3133. UINT LenRemaining = BufferLength - sizeof (EPVC_ETH_HEADER);
  3134. if (pIpHeader == NULL)
  3135. {
  3136. //
  3137. // we did not get the virtual address from the system.
  3138. // Start to fail this packet
  3139. //
  3140. ASSERTAndBreak(pIpHeader != NULL);
  3141. }
  3142. //
  3143. // Now move the Ip Header past the Ethernet Header (where it currently points to)
  3144. //
  3145. pIpHeader += sizeof (EPVC_ETH_HEADER) ;
  3146. //
  3147. // Now allocate the new NdisBuffer
  3148. //
  3149. epvcAllocateBuffer ( &NdisStatus,
  3150. &pNewBuffer,
  3151. NULL,
  3152. pIpHeader,
  3153. LenRemaining);
  3154. if (NdisStatus != NDIS_STATUS_SUCCESS)
  3155. {
  3156. pNewBuffer = NULL;
  3157. ASSERTAndBreak (!"Ndis Buffer Allocation failed");
  3158. }
  3159. //
  3160. // Make the New Buffer the Head of the new packet
  3161. //
  3162. // We might have to make it the tail if there is
  3163. // only one ndis buffer in the packet
  3164. //
  3165. if (pNewPkt->Private.Head == pNewPkt->Private.Tail)
  3166. {
  3167. pNewPkt->Private.Tail = pNewBuffer;
  3168. }
  3169. pNewBuffer->Next= pNewPkt->Private.Head->Next;
  3170. pNewPkt->Private.Head = pNewBuffer;
  3171. NdisStatus = NDIS_STATUS_SUCCESS;
  3172. break ; // we are done
  3173. }
  3174. } while (FALSE);
  3175. TRACE (TL_T, TM_Send, ("<==epvcRemoveEthernetHeader "));
  3176. return NdisStatus ;
  3177. }
  3178. VOID
  3179. epvcSetPacketContext (
  3180. IN PEPVC_SEND_STRUCT pSendStruct,
  3181. PRM_STACK_RECORD pSR
  3182. )
  3183. /*++
  3184. Routine Description:
  3185. No allocations, just add a few pointers and exit
  3186. Arguments:
  3187. pSendStruct - Contains all the arguments that are needed.
  3188. Return:
  3189. None:
  3190. --*/
  3191. {
  3192. PNDIS_PACKET pPkt = pSendStruct->pNewPacket;
  3193. PEPVC_STACK_CONTEXT pStack = NULL;
  3194. //
  3195. // first point the context to the correct place
  3196. // in the new ndis pakcet
  3197. //
  3198. if (pSendStruct->fUsingStacks == TRUE)
  3199. {
  3200. pStack = (PEPVC_STACK_CONTEXT)(&pSendStruct->pPktStack->IMReserved[0]);
  3201. }
  3202. else
  3203. {
  3204. PEPVC_PKT_CONTEXT pContext = NULL;
  3205. pContext = (PEPVC_PKT_CONTEXT )(&pPkt->ProtocolReserved[0]);
  3206. pContext->pOriginalPacket = pSendStruct->pOldPacket;
  3207. pStack = &pContext->Stack;
  3208. }
  3209. //
  3210. // Update the packet
  3211. //
  3212. ASSERT (sizeof (pStack) <= (2 *sizeof (PVOID) ));
  3213. //
  3214. // Now copy the stack portion of the context over
  3215. // into the packet
  3216. //
  3217. *pStack = pSendStruct->Context.Stack;
  3218. }
  3219. NDIS_STATUS
  3220. epvcAddLLCEncapsulation (
  3221. PEPVC_I_MINIPORT pMiniport ,
  3222. PNDIS_PACKET pOldPkt,
  3223. PNDIS_PACKET pNewPkt,
  3224. PRM_STACK_RECORD pSR
  3225. )
  3226. /*++
  3227. Routine Description:
  3228. Expects that the new packet is already set up with
  3229. the Ndis Bufferz
  3230. Arguments:
  3231. pSendStruct - Contains all the arguments that are needed.
  3232. Return:
  3233. True - if this is an Arp Request.
  3234. --*/
  3235. {
  3236. ENTER ("epvcAddLLCEncapsulation" , 0x3ec589c9)
  3237. BOOLEAN fDoSend = TRUE;
  3238. BOOLEAN fUsedPktStack = (pOldPkt == pNewPkt);
  3239. NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS;
  3240. PNDIS_BUFFER pNewBuffer = NULL;
  3241. TRACE (TL_T, TM_Send, ("==>epvcAddLLCEncapsulation "));
  3242. do
  3243. {
  3244. if (pMiniport->fAddLLCHeader == FALSE)
  3245. {
  3246. break; // we are done
  3247. }
  3248. //
  3249. // Allocate an MDL that points to the LLC Header
  3250. //
  3251. epvcAllocateBuffer ( &NdisStatus,
  3252. &pNewBuffer,
  3253. NULL,
  3254. pMiniport->pLllcHeader,
  3255. pMiniport->LlcHeaderLength);
  3256. if (NdisStatus != NDIS_STATUS_SUCCESS)
  3257. {
  3258. pNewBuffer = NULL;
  3259. break;
  3260. }
  3261. //
  3262. // Insert the New Buffer as the Head of the new Packet
  3263. //
  3264. pNewBuffer->Next = pNewPkt->Private.Head;
  3265. pNewPkt->Private.Head = pNewBuffer;
  3266. pNewPkt->Private.ValidCounts= FALSE;
  3267. NdisStatus = NDIS_STATUS_SUCCESS;
  3268. } while (FALSE);
  3269. if (NdisStatus != NDIS_STATUS_SUCCESS)
  3270. {
  3271. if (pNewBuffer!= NULL)
  3272. {
  3273. epvcFreeBuffer (pNewBuffer);
  3274. pNewBuffer = NULL;
  3275. }
  3276. }
  3277. TRACE (TL_T, TM_Send, ("<==epvcAddLLCEncapsulation "));
  3278. return NdisStatus ;
  3279. }
  3280. NDIS_STATUS
  3281. epvcRemoveSendEncapsulation (
  3282. PEPVC_I_MINIPORT pMiniport ,
  3283. PNDIS_PACKET pNewPkt
  3284. )
  3285. {
  3286. return NDIS_STATUS_SUCCESS;
  3287. }
  3288. NDIS_STATUS
  3289. epvcRemoveRecvEncapsulation (
  3290. PEPVC_I_MINIPORT pMiniport ,
  3291. PNDIS_PACKET pNewPkt
  3292. )
  3293. {
  3294. return NDIS_STATUS_SUCCESS;
  3295. }
  3296. VOID
  3297. epvcDumpPkt (
  3298. IN PNDIS_PACKET pPkt
  3299. )
  3300. {
  3301. PNDIS_BUFFER pPrevBuffer;
  3302. do
  3303. {
  3304. PNDIS_BUFFER pBuffer = NULL;
  3305. if (g_bDumpPackets == FALSE)
  3306. {
  3307. break;
  3308. }
  3309. pBuffer = pPkt->Private.Head;
  3310. //
  3311. // Now iterate through all the buffers
  3312. // and print out the packet.
  3313. //
  3314. TRACE (TL_A, TM_Mp, ("pPkt %p, Head %p, tail %p\n ",
  3315. pPkt, pPkt->Private.Head, pPkt->Private.Tail));
  3316. //
  3317. // As we always expect the first buffer to be present
  3318. // I do not check
  3319. //
  3320. do
  3321. {
  3322. PVOID pVa = NULL;
  3323. ULONG Len = 0;
  3324. pPrevBuffer = NULL;
  3325. Len = NdisBufferLength (pBuffer);
  3326. pVa = NdisBufferVirtualAddress(pBuffer);
  3327. pPrevBuffer = pBuffer;
  3328. pBuffer = pBuffer->Next;
  3329. if (pVa == NULL)
  3330. {
  3331. continue;
  3332. }
  3333. DbgPrint ("Mdl %p, Va %p. Len %x\n", pPrevBuffer, pVa,Len);
  3334. Dump( (CHAR* )pVa, Len, 0, 1 );
  3335. } while (pBuffer != NULL);
  3336. } while (FALSE);
  3337. }
  3338. NDIS_STATUS
  3339. epvcMiniportReadConfig(
  3340. IN PEPVC_I_MINIPORT pMiniport,
  3341. NDIS_HANDLE WrapperConfigurationContext,
  3342. PRM_STACK_RECORD pSR
  3343. )
  3344. {
  3345. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  3346. NDIS_HANDLE ConfigurationHandle;
  3347. PMP_REG_ENTRY pRegEntry;
  3348. UINT i;
  3349. UINT value;
  3350. PUCHAR pointer;
  3351. PNDIS_CONFIGURATION_PARAMETER ReturnedValue;
  3352. PUCHAR NetworkAddress;
  3353. UINT Length;
  3354. // Open the registry for this pMiniport
  3355. NdisOpenConfiguration(
  3356. &Status,
  3357. &ConfigurationHandle,
  3358. WrapperConfigurationContext);
  3359. if(Status != NDIS_STATUS_SUCCESS)
  3360. {
  3361. TRACE (TL_I, TM_Mp,("NdisOpenConfiguration failed\n"));
  3362. return Status;
  3363. }
  3364. // read all the registry values
  3365. for(i = 0, pRegEntry = NICRegTable; i < NIC_NUM_REG_PARAMS; i++, pRegEntry++)
  3366. {
  3367. pointer = (PUCHAR) pMiniport + pRegEntry->FieldOffset;
  3368. // Get the configuration value for a specific parameter. Under NT the
  3369. // parameters are all read in as DWORDs.
  3370. NdisReadConfiguration(
  3371. &Status,
  3372. &ReturnedValue,
  3373. ConfigurationHandle,
  3374. &pRegEntry->RegName,
  3375. NdisParameterInteger);
  3376. // If the parameter was present, then check its value for validity.
  3377. if(Status == NDIS_STATUS_SUCCESS)
  3378. {
  3379. // Check that param value is not too small or too large
  3380. if(ReturnedValue->ParameterData.IntegerData < pRegEntry->Min ||
  3381. ReturnedValue->ParameterData.IntegerData > pRegEntry->Max)
  3382. {
  3383. value = pRegEntry->Default;
  3384. }
  3385. else
  3386. {
  3387. value = ReturnedValue->ParameterData.IntegerData;
  3388. }
  3389. TRACE (TL_I, TM_Mp, ("= 0x%x", value));
  3390. }
  3391. else if(pRegEntry->bRequired)
  3392. {
  3393. TRACE (TL_I, TM_Mp,(" -- failed"));
  3394. ASSERT(FALSE);
  3395. Status = NDIS_STATUS_FAILURE;
  3396. break;
  3397. }
  3398. else
  3399. {
  3400. value = pRegEntry->Default;
  3401. TRACE (TL_I, TM_Mp,("= 0x%x (default)", value));
  3402. Status = NDIS_STATUS_SUCCESS;
  3403. }
  3404. // Store the value in the pMiniport structure.
  3405. switch(pRegEntry->FieldSize)
  3406. {
  3407. case 1:
  3408. *((PUCHAR) pointer) = (UCHAR) value;
  3409. break;
  3410. case 2:
  3411. *((PUSHORT) pointer) = (USHORT) value;
  3412. break;
  3413. case 4:
  3414. *((PULONG) pointer) = (ULONG) value;
  3415. break;
  3416. default:
  3417. TRACE (TL_I,TM_Mp, ("Bogus field size %d", pRegEntry->FieldSize));
  3418. break;
  3419. }
  3420. }
  3421. // Read NetworkAddress registry value
  3422. // Use it as the current address if any
  3423. // Close the registry
  3424. NdisCloseConfiguration(ConfigurationHandle);
  3425. TRACE (TL_I, TM_Mp,("vci %d\n", pMiniport->config.vci));
  3426. TRACE (TL_I, TM_Mp,("vpi %d\n", pMiniport->config.vpi));
  3427. TRACE (TL_I, TM_Mp,("Encap Type %x\n", pMiniport->Encap));
  3428. TRACE (TL_T, TM_Mp, ("<-- NICReadRegParameters, Status=%x", Status));
  3429. return Status;
  3430. }
  3431. VOID
  3432. epvcInitializeMiniportLookasideLists (
  3433. IN PEPVC_I_MINIPORT pMiniport
  3434. )
  3435. /*++
  3436. Routine Description:
  3437. Initialize all the lookaside lists in the adapter block
  3438. Arguments:
  3439. Return Value:
  3440. None.
  3441. --*/
  3442. {
  3443. USHORT DefaultDepth = 15;
  3444. extern const UINT MaxEthernetFrameSize ;
  3445. TRACE( TL_T, TM_Mp, ( "==> nicInitializeMiniportLookasideLists pMiniport %x ", pMiniport ) );
  3446. switch (pMiniport->Encap)
  3447. {
  3448. case IPV4_ENCAP_TYPE:
  3449. case IPV4_LLC_SNAP_ENCAP_TYPE:
  3450. {
  3451. epvcInitializeLookasideList ( &pMiniport->arps.LookasideList,
  3452. sizeof (EPVC_TASK),
  3453. TAG_TASK,
  3454. DefaultDepth );
  3455. epvcInitializeLookasideList ( &pMiniport->rcv.LookasideList,
  3456. sizeof (EPVC_IP_RCV_BUFFER),
  3457. TAG_RCV ,
  3458. DefaultDepth );
  3459. break;
  3460. }
  3461. case ETHERNET_ENCAP_TYPE:
  3462. case ETHERNET_LLC_SNAP_ENCAP_TYPE:
  3463. {
  3464. break;
  3465. }
  3466. default:
  3467. {
  3468. }
  3469. }
  3470. TRACE( TL_T, TM_Mp, ( "<== nicInitializeMiniportLookasideLists " ) );
  3471. }
  3472. VOID
  3473. epvcDeleteMiniportLookasideLists (
  3474. IN PEPVC_I_MINIPORT pMiniport
  3475. )
  3476. /*++
  3477. Routine Description:
  3478. Delete all the lookaside lists in the adapter block
  3479. Arguments:
  3480. Return Value:
  3481. None.
  3482. --*/
  3483. {
  3484. TRACE( TL_T, TM_Mp, ( "== epvcDeleteMiniportLookasideLists pMiniport %x ", pMiniport) );
  3485. //
  3486. // Deletes the lookaside lists if they have been allocated
  3487. //
  3488. epvcDeleteLookasideList (&pMiniport->rcv.LookasideList);
  3489. epvcDeleteLookasideList (&pMiniport->arps.LookasideList);
  3490. }
  3491. NDIS_STATUS
  3492. epvcInitializeMiniportPacketPools (
  3493. IN PEPVC_I_MINIPORT pMiniport
  3494. )
  3495. /*++
  3496. Routine Description:
  3497. Initializr all the packet pools in the miniport
  3498. Arguments:
  3499. Return Value:
  3500. None.
  3501. --*/
  3502. {
  3503. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  3504. TRACE( TL_T, TM_Mp, ( "==> epvcInitializeMiniportPacketPools pMiniport %x ", pMiniport ) );
  3505. do
  3506. {
  3507. epvcAllocatePacketPool (&Status,
  3508. &pMiniport->PktPool.Send,
  3509. MIN_PACKET_POOL_SIZE,
  3510. MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE,
  3511. sizeof(EPVC_PKT_CONTEXT));
  3512. if (Status != NDIS_STATUS_SUCCESS)
  3513. {
  3514. EPVC_ZEROSTRUCT (&pMiniport->PktPool.Send);
  3515. ASSERT (Status == NDIS_STATUS_SUCCESS);
  3516. break;
  3517. }
  3518. epvcAllocatePacketPool (&Status,
  3519. &pMiniport->PktPool.Recv,
  3520. MIN_PACKET_POOL_SIZE,
  3521. MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE,
  3522. PROTOCOL_RESERVED_SIZE_IN_PACKET);
  3523. if (Status != NDIS_STATUS_SUCCESS)
  3524. {
  3525. EPVC_ZEROSTRUCT (&pMiniport->PktPool.Recv);
  3526. ASSERT (Status == NDIS_STATUS_SUCCESS);
  3527. break;
  3528. }
  3529. } while ( FALSE);
  3530. if (Status != NDIS_STATUS_SUCCESS)
  3531. {
  3532. epvcDeleteMiniportPacketPools (pMiniport);
  3533. }
  3534. TRACE( TL_T, TM_Mp, ( "<== epvcInitializeMiniportPacketPools Status %x ", Status ) );
  3535. return Status;
  3536. }
  3537. VOID
  3538. epvcDeleteMiniportPacketPools (
  3539. IN PEPVC_I_MINIPORT pMiniport
  3540. )
  3541. /*++
  3542. Routine Description:
  3543. Delete all the packet pools in the miniport block
  3544. Arguments:
  3545. Return Value:
  3546. None.
  3547. --*/
  3548. {
  3549. TRACE( TL_T, TM_Mp, ( "== epvcDeleteMiniportPacketPools pMiniport %x ", pMiniport ) );
  3550. //
  3551. // Freeing packet pools
  3552. //
  3553. if (pMiniport->PktPool.Recv.Handle != NULL)
  3554. {
  3555. epvcFreePacketPool (&pMiniport->PktPool.Recv);
  3556. }
  3557. if (pMiniport->PktPool.Send.Handle != NULL)
  3558. {
  3559. epvcFreePacketPool (&pMiniport->PktPool.Send);
  3560. }
  3561. }
  3562. VOID
  3563. epvcInitializeMiniportParameters(
  3564. PEPVC_I_MINIPORT pMiniport
  3565. )
  3566. {
  3567. //ipv4 - 0
  3568. //ipv4 with llc header = 1
  3569. //Ethernet - 2
  3570. //Ethernet with llc header- 3
  3571. //
  3572. // Defaults for all flags are FALSE
  3573. //
  3574. pMiniport->fDoIpEncapsulation = FALSE;
  3575. pMiniport->fAddLLCHeader = FALSE;
  3576. switch (pMiniport->Encap )
  3577. {
  3578. case IPV4_ENCAP_TYPE:
  3579. {
  3580. pMiniport->fDoIpEncapsulation = TRUE;
  3581. pMiniport->MinAcceptablePkt =sizeof (IPHeader) ;
  3582. pMiniport->MaxAcceptablePkt = EPVC_MAX_FRAME_SIZE -EPVC_ETH_HEADERSIZE ;
  3583. break;
  3584. }
  3585. case IPV4_LLC_SNAP_ENCAP_TYPE:
  3586. {
  3587. pMiniport->fAddLLCHeader = TRUE;
  3588. pMiniport->fDoIpEncapsulation = TRUE;
  3589. pMiniport->pLllcHeader = &LLCSnapIpv4[0];
  3590. pMiniport->LlcHeaderLength = sizeof(LLCSnapIpv4);
  3591. pMiniport->MinAcceptablePkt = sizeof (IPHeader) + sizeof(LLCSnapIpv4);
  3592. pMiniport->MaxAcceptablePkt = EPVC_MAX_FRAME_SIZE + sizeof(LLCSnapIpv4)-EPVC_ETH_HEADERSIZE ;
  3593. break;
  3594. }
  3595. case ETHERNET_LLC_SNAP_ENCAP_TYPE:
  3596. {
  3597. pMiniport->fAddLLCHeader = TRUE;
  3598. pMiniport->pLllcHeader = &LLCSnapEthernet[0];
  3599. pMiniport->LlcHeaderLength = sizeof(LLCSnapEthernet);
  3600. pMiniport->MinAcceptablePkt = MIN_ETHERNET_SIZE + sizeof(LLCSnapEthernet);
  3601. pMiniport->MaxAcceptablePkt = EPVC_MAX_FRAME_SIZE +sizeof(LLCSnapEthernet);
  3602. break;
  3603. }
  3604. case ETHERNET_ENCAP_TYPE:
  3605. {
  3606. pMiniport->MinAcceptablePkt = MIN_ETHERNET_SIZE;
  3607. pMiniport->MaxAcceptablePkt = EPVC_MAX_FRAME_SIZE + EPVC_ETH_ENCAP_SIZE;
  3608. break;
  3609. }
  3610. default:
  3611. {
  3612. ASSERT (!"Not supported - defaulting to Ethernet Encapsulation");
  3613. }
  3614. }
  3615. }
  3616. NDIS_STATUS
  3617. epvcTaskHaltMiniport(
  3618. IN struct _RM_TASK * pTask,
  3619. IN RM_TASK_OPERATION Code,
  3620. IN UINT_PTR UserParam,
  3621. IN PRM_STACK_RECORD pSR
  3622. )
  3623. /*++
  3624. Routine Description:
  3625. Task handler for opening address families on an underlying adapters.
  3626. The number of address families instantiated is determined by the
  3627. configuration read in the registry
  3628. Arguments:
  3629. UserParam for (Code == RM_TASKOP_START) : UnbindContext
  3630. --*/
  3631. {
  3632. ENTER("epvcTaskHaltMiniport", 0xaac34d81)
  3633. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  3634. PEPVC_I_MINIPORT pMiniport = (PEPVC_I_MINIPORT ) RM_PARENT_OBJECT(pTask);
  3635. PEPVC_ADAPTER pAdapter = pMiniport->pAdapter;
  3636. PTASK_HALT pTaskHalt = (PTASK_HALT)pTask;
  3637. BOOLEAN fTaskCompleted = FALSE;
  3638. ULONG State;
  3639. enum
  3640. {
  3641. Stage_Start =0, // default
  3642. Stage_DeleteVc,
  3643. Stage_CloseAfComplete,
  3644. Stage_TaskCompleted,
  3645. Stage_End
  3646. }; // To be used in pTask->Hdr.State to indicate the state of the Task
  3647. TRACE(TL_T, TM_Mp, ("==>epvcTaskHaltMiniport State %x", pTask->Hdr.State));
  3648. State = pTask->Hdr.State;
  3649. switch (pTask->Hdr.State)
  3650. {
  3651. case Stage_Start:
  3652. {
  3653. TRACE (TL_V, TM_Mp, (" Task Halt miniport Stage_Start"));
  3654. //
  3655. // Check to see if the miniport has already halting.
  3656. // If so exit
  3657. //
  3658. LOCKOBJ (pMiniport, pSR );
  3659. if (epvcIsThisTaskPrimary ( pTask, &(PRM_TASK)(pMiniport->pnp.pTaskHalt)) == FALSE)
  3660. {
  3661. PRM_TASK pOtherTask = (PRM_TASK)(pMiniport->pnp.pTaskHalt);
  3662. RmTmpReferenceObject (&pOtherTask->Hdr, pSR);
  3663. //
  3664. // Set The state so we restart this code after main task completes
  3665. //
  3666. pTask->Hdr.State = Stage_Start;
  3667. UNLOCKOBJ(pMiniport, pSR);
  3668. RmPendTaskOnOtherTask (pTask, 0, pOtherTask, pSR);
  3669. RmTmpDereferenceObject(&pOtherTask->Hdr,pSR);
  3670. Status = NDIS_STATUS_PENDING;
  3671. break;
  3672. }
  3673. // We are the primary task and we have the lock
  3674. //
  3675. ASSERT (pMiniport->pnp.pTaskHalt == pTaskHalt);
  3676. //
  3677. // Lets close the Call and Delete the Vc
  3678. //
  3679. UNLOCKOBJ (pMiniport, pSR);
  3680. if (MiniportTestFlag (pMiniport, fMP_MakeCallSucceeded) == TRUE)
  3681. {
  3682. PRM_TASK pVcTask = NULL;
  3683. //
  3684. // We need to start a task to complete the Close Call And DeleteVC
  3685. //
  3686. Status = epvcAllocateTask(
  3687. &pMiniport->Hdr, // pParentObject,
  3688. epvcTaskVcTeardown, // pfnHandler,
  3689. 0, // Timeout,
  3690. "Task: TearDown Vc", // szDescription
  3691. &pVcTask ,
  3692. pSR
  3693. );
  3694. if (FAIL(Status))
  3695. {
  3696. fTaskCompleted = TRUE;
  3697. pVcTask = NULL;
  3698. ASSERT (Status == NDIS_STATUS_SUCCESS);
  3699. break;
  3700. }
  3701. //
  3702. // Now we will pend the halt on the completion of the delete VC
  3703. // task
  3704. //
  3705. pTask->Hdr.State = Stage_DeleteVc;
  3706. RmPendTaskOnOtherTask(pTask,
  3707. 0,
  3708. pVcTask,
  3709. pSR
  3710. );
  3711. //
  3712. // Start the Vc TearDown
  3713. //
  3714. RmStartTask (pVcTask , 0, pSR);
  3715. //
  3716. // Exit - We expect to complete this task in another thread
  3717. //
  3718. Status = NDIS_STATUS_PENDING;
  3719. break;
  3720. }
  3721. else //if (MiniportTestFlag (pMiniport, fMP_MakeCallSucceeded) == TRUE)
  3722. {
  3723. pTask->Hdr.State = Stage_DeleteVc;
  3724. //
  3725. // Continue On - the Vc has already been deleted
  3726. //
  3727. }
  3728. }
  3729. case Stage_DeleteVc:
  3730. {
  3731. //
  3732. // Now we check to see if the address family is still
  3733. // open for this miniport
  3734. //
  3735. TRACE (TL_V, TM_Mp, (" Task Halt miniport Stage_DeleteVc"));
  3736. if (MiniportTestFlag(pMiniport, fMP_AddressFamilyOpened) == TRUE)
  3737. {
  3738. PRM_TASK pAfTask = NULL;
  3739. //
  3740. // We need to start a task to complete the Close Call And DeleteVC
  3741. //
  3742. Status = epvcAllocateTask(
  3743. &pMiniport->Hdr, // pParentObject,
  3744. epvcTaskCloseIMiniport, // pfnHandler,
  3745. 0, // Timeout,
  3746. "Task: Close Miniport", // szDescription
  3747. &pAfTask ,
  3748. pSR
  3749. );
  3750. if (FAIL(Status))
  3751. {
  3752. fTaskCompleted = TRUE;
  3753. pAfTask = NULL;
  3754. ASSERT (Status == NDIS_STATUS_SUCCESS);
  3755. break;
  3756. }
  3757. ((PTASK_AF)pAfTask)->Cause = TaskCause_MiniportHalt;
  3758. //
  3759. // Now we will pend the halt on the completion of the delete VC
  3760. // task
  3761. //
  3762. pTask->Hdr.State = Stage_CloseAfComplete;
  3763. RmPendTaskOnOtherTask(pTask,
  3764. 0,
  3765. pAfTask,
  3766. pSR
  3767. );
  3768. //
  3769. // Start the Af TearDown
  3770. //
  3771. RmStartTask (pAfTask , 0, pSR);
  3772. //
  3773. // Exit - We expect to complete this task in another thread
  3774. //
  3775. Status = NDIS_STATUS_PENDING;
  3776. break;
  3777. }
  3778. else //if (MiniportTestFlag (pMiniport, fMP_MakeCallSucceeded) == TRUE)
  3779. {
  3780. pTask->Hdr.State = Stage_CloseAfComplete;
  3781. //
  3782. // Continue On - the Af has already been deleted
  3783. //
  3784. }
  3785. }
  3786. case Stage_CloseAfComplete:
  3787. {
  3788. //
  3789. // Free all miniport resources here .- packet pools etc.
  3790. //
  3791. TRACE (TL_V, TM_Mp, (" Task Halt miniport Stage_CloseAfComplete"));
  3792. //
  3793. // Freeing Lookaside lists
  3794. //
  3795. epvcDeleteMiniportLookasideLists (pMiniport);
  3796. //
  3797. // Freeing packet pools
  3798. //
  3799. epvcDeleteMiniportPacketPools(pMiniport);
  3800. //
  3801. // If the miniport is halting we do not shut down the protocol's adapter
  3802. // object
  3803. //
  3804. fTaskCompleted = TRUE;
  3805. Status = NDIS_STATUS_SUCCESS;
  3806. break;
  3807. }
  3808. case Stage_TaskCompleted:
  3809. {
  3810. ASSERT(0);
  3811. break;
  3812. }
  3813. case Stage_End:
  3814. {
  3815. TRACE (TL_V, TM_Mp, (" Task Halt miniport Stage_End"));
  3816. Status = NDIS_STATUS_SUCCESS;
  3817. break;
  3818. }
  3819. default:
  3820. {
  3821. ASSERT (pTask->Hdr.State <= Stage_End);
  3822. }
  3823. } // end of switch
  3824. //
  3825. // if this thread has completed the postprocessing,
  3826. // then signal the event.
  3827. //
  3828. if (TRUE == fTaskCompleted)
  3829. {
  3830. BOOLEAN fSetWaitEvent = FALSE;
  3831. TRACE (TL_V, TM_Mp, ("Task Halt Miniport - Stage End"));
  3832. pTask->Hdr.State = Stage_End;
  3833. if (FAIL(Status))
  3834. {
  3835. ASSERT (0);
  3836. }
  3837. LOCKOBJ (pMiniport, pSR);
  3838. pMiniport->pnp.pTaskHalt = NULL;
  3839. if (MiniportTestFlag (pMiniport, fMP_WaitingForHalt)== TRUE)
  3840. {
  3841. MiniportClearFlag (pMiniport, fMP_WaitingForHalt);
  3842. fSetWaitEvent = TRUE;
  3843. }
  3844. UNLOCKOBJ (pMiniport, pSR);
  3845. //
  3846. // This first event is for the MiniportHalt handler
  3847. // which fired off this task
  3848. //
  3849. epvcSetEvent (&pTaskHalt->CompleteEvent);
  3850. //
  3851. // This second event is for the epvcMiniportDoUnbind
  3852. // which wants to wait until the Halt is complete ,
  3853. // before it shuts off the lower binding to the phy. adapter
  3854. //
  3855. if (fSetWaitEvent)
  3856. {
  3857. epvcSetEvent (&pMiniport->pnp.HaltCompleteEvent);
  3858. }
  3859. Status = NDIS_STATUS_SUCCESS;
  3860. }
  3861. TRACE(TL_T, TM_Mp, ("<==epvcTaskHaltMiniport Status %x", Status));
  3862. EXIT()
  3863. RM_ASSERT_NOLOCKS(pSR);
  3864. return Status;
  3865. }
  3866. NDIS_STATUS
  3867. epvcAddEthernetTail(
  3868. PEPVC_SEND_STRUCT pSendStruct,
  3869. IN PRM_STACK_RECORD pSR
  3870. )
  3871. /*++
  3872. Routine Description:
  3873. Makes sure the ethernet packet is greater than 64 bytes
  3874. Arguments:
  3875. pSendStruct - Contains all the arguments that are needed.
  3876. Return:
  3877. Success - if the padding was not needed or the MDL
  3878. was successfully appended
  3879. --*/
  3880. {
  3881. ENTER ("epvcAddEthernetTail" , 0x3ec589c9)
  3882. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  3883. PNDIS_PACKET pNewPkt = pSendStruct->pNewPacket;
  3884. PEPVC_I_MINIPORT pMiniport = pSendStruct->pMiniport;
  3885. ULONG PacketLength = 0;
  3886. ULONG LengthRemaining = 0;
  3887. PNDIS_BUFFER pNewTailBuffer = NULL;
  3888. PNDIS_BUFFER pLastBuffer;
  3889. TRACE (TL_T, TM_Send, ("==>epvcAddEthernetTail"));
  3890. do
  3891. {
  3892. ULONG BufferLength = 0;
  3893. PNDIS_BUFFER pBuffer = NULL;
  3894. if (pMiniport->fDoIpEncapsulation == TRUE)
  3895. {
  3896. NdisStatus = NDIS_STATUS_SUCCESS;
  3897. break; // we are done
  3898. }
  3899. //
  3900. // Check the length of the Ethernet packet
  3901. //
  3902. NdisQueryPacketLength(pNewPkt, &PacketLength);
  3903. //
  3904. // Is the packet length greater than 64
  3905. //
  3906. if (PacketLength >= MINIMUM_ETHERNET_LENGTH)
  3907. {
  3908. NdisStatus= NDIS_STATUS_SUCCESS;
  3909. break;
  3910. }
  3911. //
  3912. // Add padding to fill up the minimum Ethernet frame length.
  3913. // This is a new buffer that is appended to the original
  3914. // NDIS_BUFFER chain.
  3915. //
  3916. LengthRemaining = MINIMUM_ETHERNET_LENGTH - PacketLength;
  3917. NdisAllocateBuffer(&NdisStatus, &pNewTailBuffer, NULL, &gPaddingBytes,LengthRemaining);
  3918. if (NdisStatus != NDIS_STATUS_SUCCESS || pNewTailBuffer == NULL)
  3919. {
  3920. pNewTailBuffer = NULL;
  3921. NdisStatus = NDIS_STATUS_RESOURCES;
  3922. break;
  3923. }
  3924. //
  3925. // Append the new buffer to the tail of the packet.
  3926. //
  3927. //
  3928. // Locate the last NDIS_BUFFER in the packet. Do it the hard
  3929. // way since Packet->Private.Tail is not reliable:
  3930. //
  3931. pLastBuffer = pNewPkt->Private.Head;
  3932. while (pLastBuffer->Next != NULL)
  3933. {
  3934. pLastBuffer = pLastBuffer->Next;
  3935. }
  3936. //
  3937. // Save a pointer to this last MDL so that we can set its
  3938. // Next field back to NULL when we complete this send.
  3939. //
  3940. pSendStruct->Context.Stack.EthernetSend.pOldLastNdisBuffer = pLastBuffer;
  3941. //
  3942. // Append the new buffer to the tail of the chain.
  3943. //
  3944. pLastBuffer->Next = pNewTailBuffer;
  3945. pNewTailBuffer->Next = NULL;
  3946. //
  3947. // Update our packet.
  3948. //
  3949. pNewPkt->Private.Tail = pNewTailBuffer;
  3950. pNewPkt->Private.ValidCounts = FALSE;
  3951. NdisStatus = NDIS_STATUS_SUCCESS;
  3952. break ; // we are done
  3953. } while (FALSE);
  3954. if (NdisStatus != NDIS_STATUS_SUCCESS && pNewTailBuffer != NULL)
  3955. {
  3956. NdisFreeBuffer (pNewTailBuffer);
  3957. }
  3958. TRACE (TL_T, TM_Send, ("<==epvcAddEthernetTail "));
  3959. return NdisStatus ;
  3960. }
  3961. VOID
  3962. epvcRemoveEthernetTail (
  3963. IN PEPVC_I_MINIPORT pMiniport,
  3964. IN PNDIS_PACKET pPacket,
  3965. IN PEPVC_PKT_CONTEXT pContext
  3966. )
  3967. /*++
  3968. Routine Description:
  3969. Removes the extra MDL that was added to make
  3970. this packet greater than MINIUMUM_ETHERNET_SIZE
  3971. Used for Ethernet , Eth +LLC Encapsulations only
  3972. Arguments:
  3973. pMiniport - Miniport structure
  3974. pPacket - Packet allocated by EPVC
  3975. pContext - Context of the packet - used to store the original last mdl
  3976. Return:
  3977. None
  3978. --*/
  3979. {
  3980. PNDIS_BUFFER pOldLastNdisBuffer = NULL;
  3981. do
  3982. {
  3983. //
  3984. // Ethernet encapsulation ? If not, then exit
  3985. //
  3986. if (pMiniport->fDoIpEncapsulation == TRUE)
  3987. {
  3988. break; // there was no ethernet encapsulation, so exit
  3989. }
  3990. //
  3991. // if there is no old buffer, then we can exit
  3992. //
  3993. pOldLastNdisBuffer = pContext->Stack.EthernetSend.pOldLastNdisBuffer;
  3994. if (pOldLastNdisBuffer == NULL)
  3995. {
  3996. break;
  3997. }
  3998. //
  3999. // Free the last buffer in the packet (this is the padding
  4000. // we added for a runt packet).
  4001. //
  4002. NdisFreeBuffer(pPacket->Private.Tail);
  4003. //
  4004. // Set the Next pointer of the original "last buffer" to NULL.
  4005. //
  4006. pOldLastNdisBuffer->Next = NULL;
  4007. } while (FALSE);
  4008. }
  4009. NDIS_STATUS
  4010. epvcAddEthernetPad(
  4011. PEPVC_SEND_STRUCT pSendStruct,
  4012. IN PRM_STACK_RECORD pSR
  4013. )
  4014. /*++
  4015. Routine Description:
  4016. Makes sure the ethernet packet w/o LLC header has a pad of
  4017. 0x00, 0x00
  4018. Arguments:
  4019. pSendStruct - Contains all the arguments that are needed.
  4020. Return:
  4021. Success - if the padding was not needed or the MDL
  4022. was successfully added
  4023. --*/
  4024. {
  4025. ENTER ("epvcAddEthernetPad" , 0x3ec589c9)
  4026. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  4027. PNDIS_PACKET pNewPkt = pSendStruct->pNewPacket;
  4028. PEPVC_I_MINIPORT pMiniport = pSendStruct->pMiniport;
  4029. PNDIS_BUFFER pPaddingBuffer = NULL;
  4030. TRACE (TL_T, TM_Send, ("==>epvcAddEthernetPad"));
  4031. do
  4032. {
  4033. ULONG BufferLength = 0;
  4034. PNDIS_BUFFER pBuffer = NULL;
  4035. if (pMiniport->Encap != ETHERNET_ENCAP_TYPE)
  4036. {
  4037. NdisStatus = NDIS_STATUS_SUCCESS;
  4038. break; // we are done
  4039. }
  4040. //
  4041. // It is pure Ethernet. We need to precede the packet
  4042. // with a 00,00
  4043. //
  4044. NdisAllocateBuffer(&NdisStatus,
  4045. &pPaddingBuffer,
  4046. NULL,
  4047. &gPaddingBytes,
  4048. ETHERNET_PADDING_LENGTH);
  4049. if (NdisStatus != NDIS_STATUS_SUCCESS || pPaddingBuffer == NULL)
  4050. {
  4051. pPaddingBuffer = NULL;
  4052. NdisStatus = NDIS_STATUS_RESOURCES;
  4053. break;
  4054. }
  4055. //
  4056. // no more allocations - we cannot fail from here
  4057. //
  4058. NdisStatus = NDIS_STATUS_SUCCESS;
  4059. //
  4060. // Add the new buffer to the head of the packet
  4061. //
  4062. NdisChainBufferAtFront(pNewPkt,pPaddingBuffer);
  4063. break ; // we are done
  4064. } while (FALSE);
  4065. if (NdisStatus != NDIS_STATUS_SUCCESS && pPaddingBuffer != NULL)
  4066. {
  4067. NdisFreeBuffer (pPaddingBuffer);
  4068. }
  4069. TRACE (TL_T, TM_Send, ("<==epvcAddEthernetPad "));
  4070. return NdisStatus ;
  4071. }
  4072. VOID
  4073. epvcRemoveEthernetPad (
  4074. IN PEPVC_I_MINIPORT pMiniport,
  4075. IN PNDIS_PACKET pPacket
  4076. )
  4077. /*++
  4078. Routine Description:
  4079. Removes the padding that was added to the
  4080. head of the packet Ethernet Head
  4081. Used for Ethernet Encapsulation only
  4082. Arguments:
  4083. pMiniport - Miniport structure
  4084. pPacket - Packet
  4085. Return:
  4086. None
  4087. --*/
  4088. {
  4089. PNDIS_BUFFER pPaddingBuffer= NULL;
  4090. do
  4091. {
  4092. if (pMiniport->Encap != ETHERNET_ENCAP_TYPE)
  4093. {
  4094. break; // we are done
  4095. }
  4096. //
  4097. // it is in pure ethernet mode - remove the Padding
  4098. //
  4099. //
  4100. // First - a simple sanity check
  4101. //
  4102. {
  4103. PNDIS_BUFFER pBuffer = pPacket->Private.Head;
  4104. ULONG PaddingLength = NdisBufferLength(pBuffer);
  4105. if (PaddingLength !=ETHERNET_PADDING_LENGTH)
  4106. {
  4107. // this is not our MDL
  4108. ASSERT (PaddingLength !=ETHERNET_PADDING_LENGTH);
  4109. break;
  4110. }
  4111. }
  4112. //
  4113. // Free the padding buffer at the front of the Packet
  4114. //
  4115. NdisUnchainBufferAtFront(pPacket,&pPaddingBuffer );
  4116. NdisFreeBuffer (pPaddingBuffer );
  4117. } while (FALSE);
  4118. }
  4119. VOID
  4120. epvcCancelDeviceInstance(
  4121. IN PEPVC_I_MINIPORT pMiniport ,
  4122. IN PRM_STACK_RECORD pSR
  4123. )
  4124. /*++
  4125. Routine Description:
  4126. This function cancels an outstanding Device Instance.
  4127. If the NDIS call fails. it waits for an event in the miniprot to fire.
  4128. After that it goes ahead and DeInitializes the Device Instance
  4129. Arguments:
  4130. pMiniport - Miniport in question.
  4131. Return Value:
  4132. Success
  4133. --*/
  4134. {
  4135. ENTER("epvcCancelDeviceInstance", 0x0e42d778)
  4136. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  4137. UINT iteration =0;
  4138. BOOLEAN bWaitSuccess = FALSE;
  4139. BOOLEAN fNeedToInitEvent = FALSE;
  4140. do
  4141. {
  4142. LOCKOBJ (pMiniport, pSR);
  4143. // Prepare the event, and mark the structure as being Canceled
  4144. epvcResetEvent (&pMiniport->pnp.DeInitEvent);
  4145. // Set the flag to mark it as cancelled
  4146. MiniportSetFlag (pMiniport, fMP_MiniportCancelInstance);
  4147. UNLOCKOBJ (pMiniport, pSR);
  4148. // Cancel the device instance
  4149. Status = epvcIMCancelInitializeDeviceInstance(pMiniport);
  4150. if (Status == NDIS_STATUS_SUCCESS)
  4151. {
  4152. break;
  4153. }
  4154. //
  4155. // If the Cancel has not Succeeded then we should wait for
  4156. // the Initialize to complete
  4157. //
  4158. {
  4159. BOOLEAN bWaitSuccessful;
  4160. bWaitSuccessful = epvcWaitEvent (&pMiniport->pnp.DeInitEvent,WAIT_INFINITE);
  4161. if (bWaitSuccessful == FALSE)
  4162. {
  4163. ASSERT (bWaitSuccessful == TRUE);
  4164. }
  4165. }
  4166. //
  4167. // If cancel fails. Wait for the miniport to be initialized
  4168. //
  4169. ASSERT (pMiniport->ndis.MiniportAdapterHandle != NULL);
  4170. //
  4171. // If cancel fails. Wait for the miniport to be initialized
  4172. //
  4173. TRACE (TL_N, TM_Mp, ("Call DeInit after Cancel failed %p , ",pMiniport));
  4174. epvcIMDeInitializeDeviceInstance (pMiniport);
  4175. Status = NDIS_STATUS_SUCCESS;
  4176. } while (FALSE);
  4177. LOCKOBJ(pMiniport, pSR);
  4178. MiniportClearFlag (pMiniport, fMP_MiniportCancelInstance);
  4179. UNLOCKOBJ (pMiniport, pSR);
  4180. return ;
  4181. }