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.

2089 lines
61 KiB

  1. /*++
  2. Copyright (c) 1992-2000 Microsoft Corporation
  3. Module Name:
  4. miniport.c
  5. Abstract:
  6. NDIS Miniport Entry points and utility functions for the NDIS
  7. MUX Intermediate Miniport sample. The driver exposes zero or more
  8. Virtual Ethernet LANs (VELANs) as NDIS miniport instances over
  9. each lower (protocol-edge) binding to an underlying adapter.
  10. Environment:
  11. Kernel mode.
  12. Revision History:
  13. --*/
  14. #include "precomp.h"
  15. #pragma hdrstop
  16. #define MODULE_NUMBER MODULE_MINI
  17. NDIS_OID VElanSupportedOids[] =
  18. {
  19. OID_GEN_SUPPORTED_LIST,
  20. OID_GEN_HARDWARE_STATUS,
  21. OID_GEN_MEDIA_SUPPORTED,
  22. OID_GEN_MEDIA_IN_USE,
  23. OID_GEN_MAXIMUM_LOOKAHEAD,
  24. OID_GEN_MAXIMUM_FRAME_SIZE,
  25. OID_GEN_LINK_SPEED,
  26. OID_GEN_TRANSMIT_BUFFER_SPACE,
  27. OID_GEN_RECEIVE_BUFFER_SPACE,
  28. OID_GEN_TRANSMIT_BLOCK_SIZE,
  29. OID_GEN_RECEIVE_BLOCK_SIZE,
  30. OID_GEN_VENDOR_ID,
  31. OID_GEN_VENDOR_DESCRIPTION,
  32. OID_GEN_VENDOR_DRIVER_VERSION,
  33. OID_GEN_CURRENT_PACKET_FILTER,
  34. OID_GEN_CURRENT_LOOKAHEAD,
  35. OID_GEN_DRIVER_VERSION,
  36. OID_GEN_MAXIMUM_TOTAL_SIZE,
  37. OID_GEN_PROTOCOL_OPTIONS,
  38. OID_GEN_MAC_OPTIONS,
  39. OID_GEN_MEDIA_CONNECT_STATUS,
  40. OID_GEN_MAXIMUM_SEND_PACKETS,
  41. OID_GEN_XMIT_OK,
  42. OID_GEN_RCV_OK,
  43. OID_GEN_XMIT_ERROR,
  44. OID_GEN_RCV_ERROR,
  45. OID_GEN_RCV_NO_BUFFER,
  46. OID_GEN_RCV_CRC_ERROR,
  47. OID_GEN_TRANSMIT_QUEUE_LENGTH,
  48. OID_802_3_PERMANENT_ADDRESS,
  49. OID_802_3_CURRENT_ADDRESS,
  50. OID_802_3_MULTICAST_LIST,
  51. OID_802_3_MAXIMUM_LIST_SIZE,
  52. OID_802_3_RCV_ERROR_ALIGNMENT,
  53. OID_802_3_XMIT_ONE_COLLISION,
  54. OID_802_3_XMIT_MORE_COLLISIONS,
  55. OID_802_3_XMIT_DEFERRED,
  56. OID_802_3_XMIT_MAX_COLLISIONS,
  57. OID_802_3_RCV_OVERRUN,
  58. OID_802_3_XMIT_UNDERRUN,
  59. OID_802_3_XMIT_HEARTBEAT_FAILURE,
  60. OID_802_3_XMIT_TIMES_CRS_LOST,
  61. OID_802_3_XMIT_LATE_COLLISIONS,
  62. OID_PNP_CAPABILITIES,
  63. OID_PNP_SET_POWER,
  64. OID_PNP_QUERY_POWER,
  65. OID_PNP_ADD_WAKE_UP_PATTERN,
  66. OID_PNP_REMOVE_WAKE_UP_PATTERN,
  67. #if IEEE_VLAN_SUPPORT
  68. OID_GEN_VLAN_ID,
  69. #endif
  70. OID_PNP_ENABLE_WAKE_UP
  71. };
  72. NDIS_STATUS
  73. MPInitialize(
  74. OUT PNDIS_STATUS OpenErrorStatus,
  75. OUT PUINT SelectedMediumIndex,
  76. IN PNDIS_MEDIUM MediumArray,
  77. IN UINT MediumArraySize,
  78. IN NDIS_HANDLE MiniportAdapterHandle,
  79. IN NDIS_HANDLE WrapperConfigurationContext
  80. )
  81. /*++
  82. Routine Description:
  83. This is the Miniport Initialize routine which gets called as a
  84. result of our call to NdisIMInitializeDeviceInstanceEx.
  85. The context parameter which we pass there is the VELan structure
  86. which we retrieve here.
  87. Arguments:
  88. OpenErrorStatus Not used by us.
  89. SelectedMediumIndex Place-holder for what media we are using
  90. MediumArray Array of ndis media passed down to us to pick from
  91. MediumArraySize Size of the array
  92. MiniportAdapterHandle The handle NDIS uses to refer to us
  93. WrapperConfigurationContext For use by NdisOpenConfiguration
  94. Return Value:
  95. NDIS_STATUS_SUCCESS unless something goes wrong
  96. --*/
  97. {
  98. UINT i;
  99. PVELAN pVElan;
  100. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  101. NDIS_HANDLE ConfigurationHandle;
  102. PVOID NetworkAddress;
  103. #if IEEE_VLAN_SUPPORT
  104. PNDIS_CONFIGURATION_PARAMETER Params;
  105. NDIS_STRING strVlanId = NDIS_STRING_CONST("VlanID");
  106. #endif
  107. //
  108. // Start off by retrieving our virtual miniport context (VELAN) and
  109. // storing the Miniport handle in it.
  110. //
  111. pVElan = NdisIMGetDeviceContext(MiniportAdapterHandle);
  112. DBGPRINT(MUX_LOUD, ("==> Miniport Initialize: VELAN %p\n", pVElan));
  113. ASSERT(pVElan != NULL);
  114. ASSERT(pVElan->pAdapt != NULL);
  115. do
  116. {
  117. pVElan->MiniportAdapterHandle = MiniportAdapterHandle;
  118. for (i = 0; i < MediumArraySize; i++)
  119. {
  120. if (MediumArray[i] == VELAN_MEDIA_TYPE)
  121. {
  122. *SelectedMediumIndex = i;
  123. break;
  124. }
  125. }
  126. if (i == MediumArraySize)
  127. {
  128. Status = NDIS_STATUS_UNSUPPORTED_MEDIA;
  129. break;
  130. }
  131. //
  132. // Access configuration parameters for this miniport.
  133. //
  134. NdisOpenConfiguration(
  135. &Status,
  136. &ConfigurationHandle,
  137. WrapperConfigurationContext);
  138. if (Status != NDIS_STATUS_SUCCESS)
  139. {
  140. break;
  141. }
  142. NdisReadNetworkAddress(
  143. &Status,
  144. &NetworkAddress,
  145. &i,
  146. ConfigurationHandle);
  147. //
  148. // If there is a NetworkAddress override, use it
  149. //
  150. if (((Status == NDIS_STATUS_SUCCESS)
  151. && (i == ETH_LENGTH_OF_ADDRESS))
  152. && ((!ETH_IS_MULTICAST(NetworkAddress))
  153. && (ETH_IS_LOCALLY_ADMINISTERED (NetworkAddress))))
  154. {
  155. ETH_COPY_NETWORK_ADDRESS(
  156. pVElan->CurrentAddress,
  157. NetworkAddress);
  158. }
  159. else
  160. {
  161. MPGenerateMacAddr(pVElan);
  162. }
  163. #if IEEE_VLAN_SUPPORT
  164. //
  165. // Read VLAN ID
  166. //
  167. NdisReadConfiguration(
  168. &Status,
  169. &Params,
  170. ConfigurationHandle,
  171. &strVlanId,
  172. NdisParameterInteger);
  173. if (Status == NDIS_STATUS_SUCCESS)
  174. {
  175. //
  176. // Check for out of bound
  177. //
  178. if (Params->ParameterData.IntegerData > VLAN_ID_MAX)
  179. {
  180. pVElan->VlanId = VLANID_DEFAULT;
  181. }
  182. else
  183. {
  184. pVElan->VlanId = Params->ParameterData.IntegerData;
  185. }
  186. }
  187. else
  188. {
  189. //
  190. // Should fail the initialization or use default value
  191. //
  192. pVElan->VlanId = VLANID_DEFAULT;
  193. Status = NDIS_STATUS_SUCCESS;
  194. }
  195. #endif
  196. NdisCloseConfiguration(ConfigurationHandle);
  197. //
  198. // Set the attributes now. NDIS_ATTRIBUTE_DESERIALIZE enables us
  199. // to make up-calls to NDIS from arbitrary execution contexts.
  200. // This also forces us to protect our data structures using
  201. // spinlocks where appropriate. Also in this case NDIS does not queue
  202. // packets on our behalf.
  203. //
  204. NdisMSetAttributesEx(MiniportAdapterHandle,
  205. pVElan,
  206. 0,
  207. NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT |
  208. NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT|
  209. NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER |
  210. NDIS_ATTRIBUTE_DESERIALIZE |
  211. NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND,
  212. 0);
  213. //
  214. // Create an ioctl interface
  215. //
  216. (VOID)PtRegisterDevice();
  217. Status = NDIS_STATUS_SUCCESS;
  218. } while (FALSE);
  219. //
  220. // If we had received an UnbindAdapter notification on the underlying
  221. // adapter, we would have blocked that thread waiting for the IM Init
  222. // process to complete. Wake up any such thread.
  223. //
  224. // See PtUnbindAdapter for more details.
  225. //
  226. ASSERT(pVElan->MiniportInitPending == TRUE);
  227. pVElan->MiniportInitPending = FALSE;
  228. NdisSetEvent(&pVElan->MiniportInitEvent);
  229. DBGPRINT(MUX_INFO, ("<== Miniport Initialize: VELAN %p, Status %x\n", pVElan, Status));
  230. *OpenErrorStatus = Status;
  231. return Status;
  232. }
  233. VOID
  234. MPSendPackets(
  235. IN NDIS_HANDLE MiniportAdapterContext,
  236. IN PPNDIS_PACKET PacketArray,
  237. IN UINT NumberOfPackets
  238. )
  239. /*++
  240. Routine Description:
  241. Send Packet Array handler. Called by NDIS whenever a protocol
  242. bound to our VELAN miniport sends one or more packets.
  243. We forward each packet to the lower binding.
  244. NOTE: NDIS will not Halt this VELAN miniport until all
  245. these packets are "send-completed", and we don't unbind
  246. the lower binding until all VELANs are halted. Therefore
  247. we don't need locks or references on VELAN or ADAPT structures.
  248. Arguments:
  249. MiniportAdapterContext Pointer to our VELAN
  250. PacketArray Set of packets to send
  251. NumberOfPackets Length of above array
  252. Return Value:
  253. None - we call NdisMSendComplete whenever we are done with a packet.
  254. --*/
  255. {
  256. PVELAN pVElan = (PVELAN)MiniportAdapterContext;
  257. PADAPT pAdapt = pVElan->pAdapt;
  258. PNDIS_PACKET Packet, MyPacket;
  259. NDIS_STATUS Status;
  260. PVOID MediaSpecificInfo;
  261. ULONG MediaSpecificInfoSize;
  262. UINT i;
  263. for (i = 0; i < NumberOfPackets; i++)
  264. {
  265. Packet = PacketArray[i];
  266. //
  267. // Allocate a new packet to encapsulate data from the original.
  268. //
  269. NdisAllocatePacket(&Status,
  270. &MyPacket,
  271. pVElan->SendPacketPoolHandle);
  272. if (Status == NDIS_STATUS_SUCCESS)
  273. {
  274. PMUX_SEND_RSVD pSendReserved;
  275. pSendReserved = MUX_RSVD_FROM_SEND_PACKET(MyPacket);
  276. pSendReserved->pOriginalPacket = Packet;
  277. pSendReserved->pVElan = pVElan;
  278. MyPacket->Private.Flags = NdisGetPacketFlags(Packet) |
  279. MUX_SEND_PACKET_FLAGS;
  280. MyPacket->Private.Head = Packet->Private.Head;
  281. MyPacket->Private.Tail = Packet->Private.Tail;
  282. #ifdef WIN9X
  283. //
  284. // Work around the fact that NDIS does not initialize this
  285. // to FALSE on Win9x.
  286. //
  287. MyPacket->Private.ValidCounts = FALSE;
  288. #endif // WIN9X
  289. //
  290. // Copy OOB data to the new packet.
  291. //
  292. NdisMoveMemory(NDIS_OOB_DATA_FROM_PACKET(MyPacket),
  293. NDIS_OOB_DATA_FROM_PACKET(Packet),
  294. sizeof(NDIS_PACKET_OOB_DATA));
  295. //
  296. // Copy relevant parts of per packet info into the new packet.
  297. //
  298. #ifndef WIN9X
  299. NdisIMCopySendPerPacketInfo(MyPacket, Packet);
  300. #endif
  301. //
  302. // Copy Media specific information.
  303. //
  304. NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO(Packet,
  305. &MediaSpecificInfo,
  306. &MediaSpecificInfoSize);
  307. if (MediaSpecificInfo || MediaSpecificInfoSize)
  308. {
  309. NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO(MyPacket,
  310. MediaSpecificInfo,
  311. MediaSpecificInfoSize);
  312. }
  313. #if IEEE_VLAN_SUPPORT
  314. Status = MPHandleSendTagging(pVElan, Packet, MyPacket);
  315. if (Status != NDIS_STATUS_SUCCESS)
  316. {
  317. NdisFreePacket(MyPacket);
  318. NdisMSendComplete(pVElan->MiniportAdapterHandle,
  319. Packet,
  320. Status);
  321. continue;
  322. }
  323. #endif
  324. //
  325. // Make note of the upcoming send.
  326. //
  327. MUX_INCR_PENDING_SENDS(pVElan);
  328. //
  329. // Send it to the lower binding.
  330. //
  331. NdisSend(&Status,
  332. pAdapt->BindingHandle,
  333. MyPacket);
  334. if (Status != NDIS_STATUS_PENDING)
  335. {
  336. PtSendComplete((NDIS_HANDLE)pAdapt,
  337. MyPacket,
  338. Status);
  339. }
  340. }
  341. else
  342. {
  343. //
  344. // Failed to allocate a packet.
  345. //
  346. break;
  347. }
  348. }
  349. //
  350. // If we bailed out above, fail any unprocessed sends.
  351. //
  352. while (i < NumberOfPackets)
  353. {
  354. NdisMSendComplete(pVElan->MiniportAdapterHandle,
  355. PacketArray[i],
  356. NDIS_STATUS_RESOURCES);
  357. i++;
  358. }
  359. }
  360. NDIS_STATUS
  361. MPQueryInformation(
  362. IN NDIS_HANDLE MiniportAdapterContext,
  363. IN NDIS_OID Oid,
  364. IN PVOID InformationBuffer,
  365. IN ULONG InformationBufferLength,
  366. OUT PULONG BytesWritten,
  367. OUT PULONG BytesNeeded
  368. )
  369. /*++
  370. Routine Description:
  371. Entry point called by NDIS to query for the value of the specified OID.
  372. All OID values are responded to right here, since this is a virtual
  373. device (not pass-through).
  374. Arguments:
  375. MiniportAdapterContext Pointer to the adapter structure
  376. Oid Oid for this query
  377. InformationBuffer Buffer for information
  378. InformationBufferLength Size of this buffer
  379. BytesWritten Specifies how much info is written
  380. BytesNeeded In case the buffer is smaller than
  381. what we need, tell them how much is needed
  382. Return Value:
  383. Return code from the NdisRequest below.
  384. --*/
  385. {
  386. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  387. PVELAN pVElan;
  388. NDIS_HARDWARE_STATUS HardwareStatus = NdisHardwareStatusReady;
  389. NDIS_MEDIUM Medium = VELAN_MEDIA_TYPE;
  390. UCHAR VendorDesc[] = VELAN_VENDOR_DESC;
  391. ULONG ulInfo;
  392. ULONG64 ulInfo64;
  393. USHORT usInfo;
  394. PVOID pInfo = (PVOID) &ulInfo;
  395. ULONG ulInfoLen = sizeof(ulInfo);
  396. // Should we forward the request to the miniport below?
  397. BOOLEAN bForwardRequest = FALSE;
  398. pVElan = (PVELAN) MiniportAdapterContext;
  399. // Initialize the result
  400. *BytesWritten = 0;
  401. *BytesNeeded = 0;
  402. switch (Oid)
  403. {
  404. case OID_GEN_SUPPORTED_LIST:
  405. pInfo = (PVOID) VElanSupportedOids;
  406. ulInfoLen = sizeof(VElanSupportedOids);
  407. break;
  408. case OID_GEN_SUPPORTED_GUIDS:
  409. //
  410. // Do NOT forward this down, otherwise we will
  411. // end up with spurious instances of private WMI
  412. // classes supported by the lower driver(s).
  413. //
  414. Status = NDIS_STATUS_NOT_SUPPORTED;
  415. break;
  416. case OID_GEN_HARDWARE_STATUS:
  417. pInfo = (PVOID) &HardwareStatus;
  418. ulInfoLen = sizeof(NDIS_HARDWARE_STATUS);
  419. break;
  420. case OID_GEN_MEDIA_SUPPORTED:
  421. case OID_GEN_MEDIA_IN_USE:
  422. pInfo = (PVOID) &Medium;
  423. ulInfoLen = sizeof(NDIS_MEDIUM);
  424. break;
  425. case OID_GEN_CURRENT_LOOKAHEAD:
  426. case OID_GEN_MAXIMUM_LOOKAHEAD:
  427. ulInfo = pVElan->LookAhead - ETH_HEADER_SIZE;
  428. break;
  429. case OID_GEN_MAXIMUM_FRAME_SIZE:
  430. ulInfo = ETH_MAX_PACKET_SIZE - ETH_HEADER_SIZE;
  431. #if IEEE_VLAN_SUPPORT
  432. ulInfo -= VLAN_TAG_HEADER_SIZE;
  433. #endif
  434. break;
  435. case OID_GEN_MAXIMUM_TOTAL_SIZE:
  436. case OID_GEN_TRANSMIT_BLOCK_SIZE:
  437. case OID_GEN_RECEIVE_BLOCK_SIZE:
  438. ulInfo = (ULONG) ETH_MAX_PACKET_SIZE;
  439. #if IEEE_VLAN_SUPPORT
  440. ulInfo -= VLAN_TAG_HEADER_SIZE;
  441. #endif
  442. break;
  443. case OID_GEN_MAC_OPTIONS:
  444. ulInfo = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |
  445. NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
  446. NDIS_MAC_OPTION_NO_LOOPBACK;
  447. #if IEEE_VLAN_SUPPORT
  448. ulInfo |= (NDIS_MAC_OPTION_8021P_PRIORITY |
  449. NDIS_MAC_OPTION_8021Q_VLAN);
  450. #endif
  451. break;
  452. case OID_GEN_LINK_SPEED:
  453. bForwardRequest = TRUE;
  454. break;
  455. case OID_GEN_TRANSMIT_BUFFER_SPACE:
  456. ulInfo = ETH_MAX_PACKET_SIZE * pVElan->MaxBusySends;
  457. #if IEEE_VLAN_SUPPORT
  458. ulInfo -= VLAN_TAG_HEADER_SIZE * pVElan->MaxBusySends;
  459. #endif
  460. break;
  461. case OID_GEN_RECEIVE_BUFFER_SPACE:
  462. ulInfo = ETH_MAX_PACKET_SIZE * pVElan->MaxBusyRecvs;
  463. #if IEEE_VLAN_SUPPORT
  464. ulInfo -= VLAN_TAG_HEADER_SIZE * pVElan->MaxBusyRecvs;
  465. #endif
  466. break;
  467. case OID_GEN_VENDOR_ID:
  468. ulInfo = VELAN_VENDOR_ID;
  469. break;
  470. case OID_GEN_VENDOR_DESCRIPTION:
  471. pInfo = VendorDesc;
  472. ulInfoLen = sizeof(VendorDesc);
  473. break;
  474. case OID_GEN_VENDOR_DRIVER_VERSION:
  475. ulInfo = VELAN_VENDOR_ID;
  476. break;
  477. case OID_GEN_DRIVER_VERSION:
  478. usInfo = (USHORT) VELAN_DRIVER_VERSION;
  479. pInfo = (PVOID) &usInfo;
  480. ulInfoLen = sizeof(USHORT);
  481. break;
  482. case OID_802_3_PERMANENT_ADDRESS:
  483. pInfo = pVElan->PermanentAddress;
  484. ulInfoLen = ETH_LENGTH_OF_ADDRESS;
  485. break;
  486. case OID_802_3_CURRENT_ADDRESS:
  487. pInfo = pVElan->CurrentAddress;
  488. ulInfoLen = ETH_LENGTH_OF_ADDRESS;
  489. break;
  490. case OID_802_3_MAXIMUM_LIST_SIZE:
  491. ulInfo = VELAN_MAX_MCAST_LIST;
  492. break;
  493. case OID_GEN_MAXIMUM_SEND_PACKETS:
  494. ulInfo = VELAN_MAX_SEND_PKTS;
  495. break;
  496. case OID_GEN_MEDIA_CONNECT_STATUS:
  497. //
  498. // Get this from the adapter below.
  499. //
  500. bForwardRequest = TRUE;
  501. break;
  502. case OID_PNP_QUERY_POWER:
  503. // simply succeed this.
  504. ulInfoLen = 0;
  505. break;
  506. case OID_PNP_CAPABILITIES:
  507. case OID_PNP_WAKE_UP_PATTERN_LIST:
  508. //
  509. // Pass down these power management/PNP OIDs.
  510. //
  511. bForwardRequest = TRUE;
  512. break;
  513. case OID_GEN_XMIT_OK:
  514. ulInfo64 = pVElan->GoodTransmits;
  515. pInfo = &ulInfo64;
  516. if (InformationBufferLength >= sizeof(ULONG64) ||
  517. InformationBufferLength == 0)
  518. {
  519. ulInfoLen = sizeof(ULONG64);
  520. }
  521. else
  522. {
  523. ulInfoLen = sizeof(ULONG);
  524. }
  525. break;
  526. case OID_GEN_RCV_OK:
  527. ulInfo64 = pVElan->GoodReceives;
  528. pInfo = &ulInfo64;
  529. if (InformationBufferLength >= sizeof(ULONG64) ||
  530. InformationBufferLength == 0)
  531. {
  532. ulInfoLen = sizeof(ULONG64);
  533. }
  534. else
  535. {
  536. ulInfoLen = sizeof(ULONG);
  537. }
  538. break;
  539. case OID_GEN_XMIT_ERROR:
  540. ulInfo = pVElan->TxAbortExcessCollisions +
  541. pVElan->TxDmaUnderrun +
  542. pVElan->TxLostCRS +
  543. pVElan->TxLateCollisions+
  544. pVElan->TransmitFailuresOther;
  545. break;
  546. case OID_GEN_RCV_ERROR:
  547. ulInfo = pVElan->RcvCrcErrors +
  548. pVElan->RcvAlignmentErrors +
  549. pVElan->RcvResourceErrors +
  550. pVElan->RcvDmaOverrunErrors +
  551. pVElan->RcvRuntErrors;
  552. #if IEEE_VLAN_SUPPORT
  553. ulInfo +=
  554. (pVElan->RcvVlanIdErrors +
  555. pVElan->RcvFormatErrors);
  556. #endif
  557. break;
  558. case OID_GEN_RCV_NO_BUFFER:
  559. ulInfo = pVElan->RcvResourceErrors;
  560. break;
  561. case OID_GEN_RCV_CRC_ERROR:
  562. ulInfo = pVElan->RcvCrcErrors;
  563. break;
  564. case OID_GEN_TRANSMIT_QUEUE_LENGTH:
  565. ulInfo = pVElan->RegNumTcb;
  566. break;
  567. case OID_802_3_RCV_ERROR_ALIGNMENT:
  568. ulInfo = pVElan->RcvAlignmentErrors;
  569. break;
  570. case OID_802_3_XMIT_ONE_COLLISION:
  571. ulInfo = pVElan->OneRetry;
  572. break;
  573. case OID_802_3_XMIT_MORE_COLLISIONS:
  574. ulInfo = pVElan->MoreThanOneRetry;
  575. break;
  576. case OID_802_3_XMIT_DEFERRED:
  577. ulInfo = pVElan->TxOKButDeferred;
  578. break;
  579. case OID_802_3_XMIT_MAX_COLLISIONS:
  580. ulInfo = pVElan->TxAbortExcessCollisions;
  581. break;
  582. case OID_802_3_RCV_OVERRUN:
  583. ulInfo = pVElan->RcvDmaOverrunErrors;
  584. break;
  585. case OID_802_3_XMIT_UNDERRUN:
  586. ulInfo = pVElan->TxDmaUnderrun;
  587. break;
  588. case OID_802_3_XMIT_HEARTBEAT_FAILURE:
  589. ulInfo = pVElan->TxLostCRS;
  590. break;
  591. case OID_802_3_XMIT_TIMES_CRS_LOST:
  592. ulInfo = pVElan->TxLostCRS;
  593. break;
  594. case OID_802_3_XMIT_LATE_COLLISIONS:
  595. ulInfo = pVElan->TxLateCollisions;
  596. break;
  597. #if IEEE_VLAN_SUPPORT
  598. case OID_GEN_VLAN_ID:
  599. ulInfo = pVElan->VlanId;
  600. break;
  601. #endif
  602. default:
  603. Status = NDIS_STATUS_INVALID_OID;
  604. break;
  605. }
  606. if (bForwardRequest == FALSE)
  607. {
  608. //
  609. // No need to forward this request down.
  610. //
  611. if (Status == NDIS_STATUS_SUCCESS)
  612. {
  613. if (ulInfoLen <= InformationBufferLength)
  614. {
  615. // Copy result into InformationBuffer
  616. *BytesWritten = ulInfoLen;
  617. if(ulInfoLen)
  618. {
  619. NdisMoveMemory(InformationBuffer, pInfo, ulInfoLen);
  620. }
  621. }
  622. else
  623. {
  624. // too short
  625. *BytesNeeded = ulInfoLen;
  626. Status = NDIS_STATUS_BUFFER_TOO_SHORT;
  627. }
  628. }
  629. }
  630. else
  631. {
  632. //
  633. // Send this request to the binding below.
  634. //
  635. Status = MPForwardRequest(pVElan,
  636. NdisRequestQueryInformation,
  637. Oid,
  638. InformationBuffer,
  639. InformationBufferLength,
  640. BytesWritten,
  641. BytesNeeded);
  642. }
  643. if ((Status != NDIS_STATUS_SUCCESS) &&
  644. (Status != NDIS_STATUS_PENDING))
  645. {
  646. DBGPRINT(MUX_WARN, ("MPQueryInformation VELAN %p, OID 0x%08x, Status = 0x%08x\n",
  647. pVElan, Oid, Status));
  648. }
  649. return(Status);
  650. }
  651. NDIS_STATUS
  652. MPSetInformation(
  653. IN NDIS_HANDLE MiniportAdapterContext,
  654. IN NDIS_OID Oid,
  655. IN PVOID InformationBuffer,
  656. IN ULONG InformationBufferLength,
  657. OUT PULONG BytesRead,
  658. OUT PULONG BytesNeeded
  659. )
  660. /*++
  661. Routine Description:
  662. This is the handler for an OID set operation. Relevant
  663. OIDs are forwarded down to the lower miniport for handling.
  664. Arguments:
  665. MiniportAdapterContext Pointer to the adapter structure
  666. Oid Oid for this query
  667. InformationBuffer Buffer for information
  668. InformationBufferLength Size of this buffer
  669. BytesRead Specifies how much info is read
  670. BytesNeeded In case the buffer is smaller than what
  671. we need, tell them how much is needed
  672. Return Value:
  673. Return code from the NdisRequest below.
  674. --*/
  675. {
  676. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  677. PVELAN pVElan = (PVELAN) MiniportAdapterContext;
  678. ULONG PacketFilter;
  679. NDIS_DEVICE_POWER_STATE NewDeviceState;
  680. // Should we forward the request to the miniport below?
  681. BOOLEAN bForwardRequest = FALSE;
  682. *BytesRead = 0;
  683. *BytesNeeded = 0;
  684. switch (Oid)
  685. {
  686. //
  687. // Let the miniport below handle these OIDs:
  688. //
  689. case OID_PNP_ADD_WAKE_UP_PATTERN:
  690. case OID_PNP_REMOVE_WAKE_UP_PATTERN:
  691. case OID_PNP_ENABLE_WAKE_UP:
  692. bForwardRequest = TRUE;
  693. break;
  694. case OID_PNP_SET_POWER:
  695. //
  696. // Store new power state and succeed the request.
  697. //
  698. *BytesNeeded = sizeof(NDIS_DEVICE_POWER_STATE);
  699. if (InformationBufferLength < *BytesNeeded)
  700. {
  701. Status = NDIS_STATUS_INVALID_LENGTH;
  702. break;
  703. }
  704. NewDeviceState = (*(PNDIS_DEVICE_POWER_STATE)InformationBuffer);
  705. //
  706. // Check if the VELAN adapter goes from lower power state to D0
  707. //
  708. if ((MUX_IS_LOW_POWER_STATE(pVElan->MPDevicePowerState))
  709. && (!MUX_IS_LOW_POWER_STATE(NewDeviceState)))
  710. {
  711. //
  712. // Indicate the media status is necessary
  713. //
  714. if (pVElan->LastIndicatedStatus != pVElan->LatestUnIndicateStatus)
  715. {
  716. NdisMIndicateStatus(pVElan->MiniportAdapterHandle,
  717. pVElan->LatestUnIndicateStatus,
  718. (PVOID)NULL,
  719. 0);
  720. NdisMIndicateStatusComplete(pVElan->MiniportAdapterHandle);
  721. pVElan->LastIndicatedStatus = pVElan->LatestUnIndicateStatus;
  722. }
  723. }
  724. //
  725. // Check if the VELAN adapter goes from D0 to lower power state
  726. //
  727. if ((!MUX_IS_LOW_POWER_STATE(pVElan->MPDevicePowerState))
  728. && (MUX_IS_LOW_POWER_STATE(NewDeviceState)))
  729. {
  730. //
  731. // Initialize LastUnIndicateStatus
  732. //
  733. pVElan->LatestUnIndicateStatus = pVElan->LastIndicatedStatus;
  734. }
  735. NdisMoveMemory(&pVElan->MPDevicePowerState,
  736. InformationBuffer,
  737. *BytesNeeded);
  738. DBGPRINT(MUX_INFO, ("SetInfo: VElan %p, new miniport power state --- %d\n",
  739. pVElan, pVElan->MPDevicePowerState));
  740. break;
  741. case OID_802_3_MULTICAST_LIST:
  742. Status = MPSetMulticastList(pVElan,
  743. InformationBuffer,
  744. InformationBufferLength,
  745. BytesRead,
  746. BytesNeeded);
  747. break;
  748. case OID_GEN_CURRENT_PACKET_FILTER:
  749. if (InformationBufferLength != sizeof(ULONG))
  750. {
  751. Status = NDIS_STATUS_INVALID_LENGTH;
  752. *BytesNeeded = sizeof(ULONG);
  753. break;
  754. }
  755. NdisMoveMemory(&PacketFilter, InformationBuffer, sizeof(ULONG));
  756. *BytesRead = sizeof(ULONG);
  757. Status = MPSetPacketFilter(pVElan,
  758. PacketFilter);
  759. break;
  760. case OID_GEN_CURRENT_LOOKAHEAD:
  761. #if IEEE_VLAN_SUPPORT
  762. //
  763. // In order to simplify parsing and to avoid excessive
  764. // copying, we need the tag header also to be present in the
  765. // lookahead buffer. Make sure that the driver below
  766. // includes that.
  767. //
  768. *(UNALIGNED PULONG)InformationBuffer += VLAN_TAG_HEADER_SIZE;
  769. #endif
  770. bForwardRequest = TRUE;
  771. break;
  772. #if IEEE_VLAN_SUPPORT
  773. case OID_GEN_VLAN_ID:
  774. if (InformationBufferLength != sizeof(ULONG))
  775. {
  776. Status = NDIS_STATUS_INVALID_LENGTH;
  777. *BytesNeeded = sizeof(ULONG);
  778. break;
  779. }
  780. NdisMoveMemory(&(pVElan->VlanId), InformationBuffer, sizeof(ULONG));
  781. break;
  782. #endif
  783. default:
  784. Status = NDIS_STATUS_INVALID_OID;
  785. break;
  786. }
  787. if (bForwardRequest == FALSE)
  788. {
  789. if (Status == NDIS_STATUS_SUCCESS)
  790. {
  791. *BytesRead = InformationBufferLength;
  792. }
  793. }
  794. else
  795. {
  796. //
  797. // Send this request to the binding below.
  798. //
  799. Status = MPForwardRequest(pVElan,
  800. NdisRequestSetInformation,
  801. Oid,
  802. InformationBuffer,
  803. InformationBufferLength,
  804. BytesRead,
  805. BytesNeeded);
  806. }
  807. return(Status);
  808. }
  809. VOID
  810. MPReturnPacket(
  811. IN NDIS_HANDLE MiniportAdapterContext,
  812. IN PNDIS_PACKET Packet
  813. )
  814. /*++
  815. Routine Description:
  816. NDIS Miniport entry point called whenever protocols are done with
  817. a packet that we had indicated up and they had queued up for returning
  818. later.
  819. Arguments:
  820. MiniportAdapterContext - pointer to VELAN structure
  821. Packet - packet being returned.
  822. Return Value:
  823. None.
  824. --*/
  825. {
  826. PVELAN pVElan = (PVELAN)MiniportAdapterContext;
  827. PNDIS_PACKET pOriginalPacket;
  828. PMUX_RECV_RSVD pRecvRsvd;
  829. #if IEEE_VLAN_SUPPORT
  830. NDIS_PACKET_8021Q_INFO NdisPacket8021qInfo;
  831. #endif
  832. pRecvRsvd = MUX_RSVD_FROM_RECV_PACKET(Packet);
  833. pOriginalPacket = pRecvRsvd->pOriginalPacket;
  834. //
  835. // Reclaim our packet.
  836. //
  837. #if IEEE_VLAN_SUPPORT
  838. //
  839. // We would have set per-packet information if we had
  840. // extracted a tag header from the received packet.
  841. //
  842. NdisPacket8021qInfo.Value = NDIS_PER_PACKET_INFO_FROM_PACKET (
  843. Packet,
  844. Ieee8021QInfo);
  845. //
  846. // If we did remove the tag header from the received packet,
  847. // we would have allocated a buffer to describe the "untagged"
  848. // header (see PtHandleRcvTagging); free it.
  849. //
  850. if (NdisPacket8021qInfo.Value)
  851. {
  852. NdisFreeBuffer(Packet->Private.Head);
  853. }
  854. #endif
  855. NdisFreePacket(Packet);
  856. //
  857. // Return the original packet received at our protocol
  858. // edge, if any.
  859. //
  860. // NOTE that we might end up calling NdisReturnPackets
  861. // multiple times with the same "lower" packet, based on
  862. // the number of VELANs to which we had indicated that
  863. // packet. The number of times we do so should match
  864. // the return value from our PtReceivePacket handler.
  865. //
  866. if (pOriginalPacket != NULL)
  867. {
  868. NdisReturnPackets(&pOriginalPacket, 1);
  869. }
  870. else
  871. {
  872. //
  873. // If no original packet, then we have been called
  874. // here to reclaim a packet used to forward up
  875. // a non-packet receive (see PtReceive). There
  876. // is nothing more to be done.
  877. //
  878. }
  879. MUX_DECR_PENDING_RECEIVES(pVElan);
  880. }
  881. NDIS_STATUS
  882. MPTransferData(
  883. OUT PNDIS_PACKET Packet,
  884. OUT PUINT BytesTransferred,
  885. IN NDIS_HANDLE MiniportAdapterContext,
  886. IN NDIS_HANDLE MiniportReceiveContext,
  887. IN UINT ByteOffset,
  888. IN UINT BytesToTransfer
  889. )
  890. /*++
  891. Routine Description:
  892. Miniport's transfer data handler. This is called if we had
  893. indicated receive data using a non-packet API, for e.g. if
  894. the lookahead buffer did not contain the entire data.
  895. We need to forward this to the miniport below to that it can
  896. copy in the rest of the data. We call NdisTransferData to do so.
  897. However, when that completes (see PtTransferDataComplete), we
  898. have to get back at the VELAN from which this packet came so that
  899. we can complete this request with the right MiniportAdapterHandle.
  900. We therefore allocate a new packet, pointing to the same buffer
  901. as the packet just passed in, and use reserved space in the packet
  902. to hold a backpointer to the VELAN from which this came.
  903. Arguments:
  904. Packet Destination packet
  905. BytesTransferred Place to return how much data was copied
  906. MiniportAdapterContext Pointer to the VELAN structure
  907. MiniportReceiveContext Context
  908. ByteOffset Offset into the packet for copying data
  909. BytesToTransfer How much to copy.
  910. Return Value:
  911. Status of transfer
  912. --*/
  913. {
  914. PVELAN pVElan = (PVELAN)MiniportAdapterContext;
  915. NDIS_STATUS Status;
  916. PNDIS_PACKET MyPacket;
  917. PMUX_TD_RSVD pTDReserved;
  918. #if IEEE_VLAN_SUPPORT
  919. PMUX_RCV_CONTEXT pMuxRcvContext;
  920. #endif
  921. do
  922. {
  923. NdisAllocatePacket(&Status,
  924. &MyPacket,
  925. pVElan->SendPacketPoolHandle);
  926. if (Status != NDIS_STATUS_SUCCESS)
  927. {
  928. break;
  929. }
  930. pTDReserved = MUX_RSVD_FROM_TD_PACKET(MyPacket);
  931. pTDReserved->pOriginalPacket = Packet;
  932. pTDReserved->pVElan = pVElan;
  933. MyPacket->Private.Flags = NdisGetPacketFlags(Packet) |
  934. MUX_SEND_PACKET_FLAGS;
  935. MyPacket->Private.Head = Packet->Private.Head;
  936. MyPacket->Private.Tail = Packet->Private.Tail;
  937. #ifdef WIN9X
  938. //
  939. // Work around the fact that NDIS does not initialize this
  940. // field on Win9x.
  941. //
  942. MyPacket->Private.ValidCounts = FALSE;
  943. #endif // WIN9X
  944. #if IEEE_VLAN_SUPPORT
  945. //
  946. // Check if the original received packet did contain a
  947. // VLAN tag header. If so, make sure we get the upcoming
  948. // call to NdisTransferData to skip the tag header.
  949. //
  950. pMuxRcvContext = (PMUX_RCV_CONTEXT)MiniportReceiveContext;
  951. if (pMuxRcvContext->TagHeaderLen == VLAN_TAG_HEADER_SIZE)
  952. {
  953. //
  954. // There was a tag header in the received packet.
  955. //
  956. ByteOffset += VLAN_TAG_HEADER_SIZE;
  957. //
  958. // Copy the 8021Q info into the packet
  959. //
  960. NDIS_PER_PACKET_INFO_FROM_PACKET(Packet, Ieee8021QInfo) =
  961. pMuxRcvContext->NdisPacket8021QInfo.Value;
  962. }
  963. //
  964. // Get back the lower driver's receive context for this indication.
  965. //
  966. MiniportReceiveContext = pMuxRcvContext->MacRcvContext;
  967. #endif
  968. NdisTransferData(&Status,
  969. pVElan->pAdapt->BindingHandle,
  970. MiniportReceiveContext,
  971. ByteOffset,
  972. BytesToTransfer,
  973. MyPacket,
  974. BytesTransferred);
  975. if (Status != NDIS_STATUS_PENDING)
  976. {
  977. PtTransferDataComplete(pVElan->pAdapt,
  978. MyPacket,
  979. Status,
  980. *BytesTransferred);
  981. Status = NDIS_STATUS_PENDING;
  982. }
  983. }
  984. while (FALSE);
  985. return(Status);
  986. }
  987. VOID
  988. MPHalt(
  989. IN NDIS_HANDLE MiniportAdapterContext
  990. )
  991. /*++
  992. Routine Description:
  993. Halt handler. Add any further clean-up for the VELAN to this
  994. function.
  995. We wait for all pending I/O on the VELAN to complete and then
  996. unlink the VELAN from the adapter.
  997. Arguments:
  998. MiniportAdapterContext Pointer to the pVElan
  999. Return Value:
  1000. None.
  1001. --*/
  1002. {
  1003. PVELAN pVElan = (PVELAN)MiniportAdapterContext;
  1004. DBGPRINT(MUX_LOUD, ("==>MiniportHalt: VELAN %p\n", pVElan));
  1005. //
  1006. // Mark the VELAN so that we don't send down any new requests or
  1007. // sends to the adapter below, or new receives/indications to
  1008. // protocols above.
  1009. //
  1010. pVElan->MiniportHalting = TRUE;
  1011. //
  1012. // Update the packet filter on the underlying adapter if needed.
  1013. //
  1014. if (pVElan->PacketFilter != 0)
  1015. {
  1016. MPSetPacketFilter(pVElan, 0);
  1017. }
  1018. //
  1019. // Wait for any outstanding sends or requests to complete.
  1020. //
  1021. while (pVElan->OutstandingSends)
  1022. {
  1023. DBGPRINT(MUX_INFO, ("MiniportHalt: VELAN %p has %d outstanding sends\n",
  1024. pVElan, pVElan->OutstandingSends));
  1025. NdisMSleep(20000);
  1026. }
  1027. //
  1028. // Wait for all outstanding indications to be completed and
  1029. // any pended receive packets to be returned to us.
  1030. //
  1031. while (pVElan->OutstandingReceives)
  1032. {
  1033. DBGPRINT(MUX_INFO, ("MiniportHalt: VELAN %p has %d outstanding receives\n",
  1034. pVElan, pVElan->OutstandingReceives));
  1035. NdisMSleep(20000);
  1036. }
  1037. //
  1038. // Delete the ioctl interface that was created when the miniport
  1039. // was created.
  1040. //
  1041. (VOID)PtDeregisterDevice();
  1042. //
  1043. // Unlink the VELAN from its parent ADAPT structure. This will
  1044. // dereference the VELAN.
  1045. //
  1046. pVElan->MiniportAdapterHandle = NULL;
  1047. PtUnlinkVElanFromAdapter(pVElan);
  1048. DBGPRINT(MUX_LOUD, ("<== MiniportHalt: pVElan %p\n", pVElan));
  1049. }
  1050. NDIS_STATUS
  1051. MPForwardRequest(
  1052. IN PVELAN pVElan,
  1053. IN NDIS_REQUEST_TYPE RequestType,
  1054. IN NDIS_OID Oid,
  1055. IN PVOID InformationBuffer,
  1056. IN ULONG InformationBufferLength,
  1057. OUT PULONG BytesReadOrWritten,
  1058. OUT PULONG BytesNeeded
  1059. )
  1060. /*++
  1061. Routine Description:
  1062. Utility routine that forwards an NDIS request made on a VELAN to the
  1063. lower binding. Since at most a single request can be pended on a VELAN,
  1064. we use the pre-allocated request structure embedded in the VELAN struct.
  1065. Arguments:
  1066. Return Value:
  1067. NDIS_STATUS_PENDING if a request was sent down.
  1068. --*/
  1069. {
  1070. NDIS_STATUS Status;
  1071. PMUX_NDIS_REQUEST pMuxNdisRequest = &pVElan->Request;
  1072. DBGPRINT(MUX_LOUD, ("MPForwardRequest: VELAN %p, OID %x\n", pVElan, Oid));
  1073. do
  1074. {
  1075. MUX_INCR_PENDING_SENDS(pVElan);
  1076. //
  1077. // If the miniport below is going away, fail the request
  1078. //
  1079. NdisAcquireSpinLock(&pVElan->Lock);
  1080. if (pVElan->DeInitializing == TRUE)
  1081. {
  1082. NdisReleaseSpinLock(&pVElan->Lock);
  1083. MUX_DECR_PENDING_SENDS(pVElan);
  1084. Status = NDIS_STATUS_FAILURE;
  1085. break;
  1086. }
  1087. NdisReleaseSpinLock(&pVElan->Lock);
  1088. //
  1089. // If the virtual miniport edge is at a low power
  1090. // state, fail this request.
  1091. //
  1092. if (MUX_IS_LOW_POWER_STATE(pVElan->MPDevicePowerState))
  1093. {
  1094. MUX_DECR_PENDING_SENDS(pVElan);
  1095. Status = NDIS_STATUS_ADAPTER_NOT_READY;
  1096. break;
  1097. }
  1098. pVElan->BytesNeeded = BytesNeeded;
  1099. pVElan->BytesReadOrWritten = BytesReadOrWritten;
  1100. pMuxNdisRequest->pCallback = PtCompleteForwardedRequest;
  1101. switch (RequestType)
  1102. {
  1103. case NdisRequestQueryInformation:
  1104. pMuxNdisRequest->Request.RequestType = NdisRequestQueryInformation;
  1105. pMuxNdisRequest->Request.DATA.QUERY_INFORMATION.Oid = Oid;
  1106. pMuxNdisRequest->Request.DATA.QUERY_INFORMATION.InformationBuffer =
  1107. InformationBuffer;
  1108. pMuxNdisRequest->Request.DATA.QUERY_INFORMATION.InformationBufferLength =
  1109. InformationBufferLength;
  1110. break;
  1111. case NdisRequestSetInformation:
  1112. pMuxNdisRequest->Request.RequestType = NdisRequestSetInformation;
  1113. pMuxNdisRequest->Request.DATA.SET_INFORMATION.Oid = Oid;
  1114. pMuxNdisRequest->Request.DATA.SET_INFORMATION.InformationBuffer =
  1115. InformationBuffer;
  1116. pMuxNdisRequest->Request.DATA.SET_INFORMATION.InformationBufferLength =
  1117. InformationBufferLength;
  1118. break;
  1119. default:
  1120. ASSERT(FALSE);
  1121. break;
  1122. }
  1123. //
  1124. // If the miniport below is going away
  1125. //
  1126. NdisAcquireSpinLock(&pVElan->Lock);
  1127. if (pVElan->DeInitializing == TRUE)
  1128. {
  1129. NdisReleaseSpinLock(&pVElan->Lock);
  1130. MUX_DECR_PENDING_SENDS(pVElan);
  1131. Status = NDIS_STATUS_FAILURE;
  1132. break;
  1133. }
  1134. // If the lower binding has been notified of a low
  1135. // power state, queue this request; it will be picked
  1136. // up again when the lower binding returns to D0.
  1137. //
  1138. if (MUX_IS_LOW_POWER_STATE(pVElan->pAdapt->PtDevicePowerState))
  1139. {
  1140. DBGPRINT(MUX_INFO, ("ForwardRequest: VELAN %p, Adapt %p power"
  1141. " state is %d, queueing OID %x\n",
  1142. pVElan, pVElan->pAdapt,
  1143. pVElan->pAdapt->PtDevicePowerState, Oid));
  1144. pVElan->QueuedRequest = TRUE;
  1145. NdisReleaseSpinLock(&pVElan->Lock);
  1146. Status = NDIS_STATUS_PENDING;
  1147. break;
  1148. }
  1149. NdisReleaseSpinLock(&pVElan->Lock);
  1150. NdisRequest(&Status,
  1151. pVElan->BindingHandle,
  1152. &pMuxNdisRequest->Request);
  1153. if (Status != NDIS_STATUS_PENDING)
  1154. {
  1155. PtRequestComplete(pVElan->pAdapt, &pMuxNdisRequest->Request, Status);
  1156. Status = NDIS_STATUS_PENDING;
  1157. break;
  1158. }
  1159. }
  1160. while (FALSE);
  1161. return (Status);
  1162. }
  1163. NDIS_STATUS
  1164. MPSetPacketFilter(
  1165. IN PVELAN pVElan,
  1166. IN ULONG PacketFilter
  1167. )
  1168. /*++
  1169. Routine Description:
  1170. This routine will set up the VELAN so that it accepts packets
  1171. that match the specified packet filter. The only filter bits
  1172. that can truly be toggled are for broadcast and promiscuous.
  1173. The MUX driver always sets the lower binding to promiscuous
  1174. mode, but we do some optimization here to avoid turning on
  1175. receives too soon. That is, we set the packet filter on the lower
  1176. binding to a non-zero value iff at least one of the VELANs
  1177. has a non-zero filter value.
  1178. NOTE: setting the lower binding to promiscuous mode can
  1179. impact CPU utilization. The only reason we set the lower binding
  1180. to promiscuous mode in this sample is that we need to be able
  1181. to receive unicast frames directed to MAC address(es) that do not
  1182. match the local adapter's MAC address. If VELAN MAC addresses
  1183. are set to be equal to that of the adapter below, it is sufficient
  1184. to set the lower packet filter to the bitwise OR'ed value of
  1185. packet filter settings on all VELANs.
  1186. Arguments:
  1187. pVElan - pointer to VELAN
  1188. PacketFilter - the new packet filter
  1189. Return Value:
  1190. NDIS_STATUS_SUCCESS
  1191. NDIS_STATUS_NOT_SUPPORTED
  1192. --*/
  1193. {
  1194. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  1195. PADAPT pAdapt;
  1196. PVELAN pTmpVElan;
  1197. PLIST_ENTRY p;
  1198. ULONG AdapterFilter;
  1199. BOOLEAN bSendUpdate = FALSE;
  1200. LOCK_STATE LockState;
  1201. DBGPRINT(MUX_LOUD, ("=> SetPacketFilter VELAN %p, Filter %x\n", pVElan, PacketFilter));
  1202. do
  1203. {
  1204. //
  1205. // Any bits not supported?
  1206. //
  1207. if (PacketFilter & ~VELAN_SUPPORTED_FILTERS)
  1208. {
  1209. Status = NDIS_STATUS_NOT_SUPPORTED;
  1210. break;
  1211. }
  1212. AdapterFilter = 0;
  1213. pAdapt = pVElan->pAdapt;
  1214. //
  1215. // Grab a Write lock on the adapter so that this operation
  1216. // does not interfere with any receives that might be accessing
  1217. // filter information.
  1218. //
  1219. MUX_ACQUIRE_ADAPT_WRITE_LOCK(pAdapt, &LockState);
  1220. //
  1221. // Save the new packet filter value
  1222. //
  1223. pVElan->PacketFilter = PacketFilter;
  1224. //
  1225. // Compute the new combined filter for all VELANs on this
  1226. // adapter.
  1227. //
  1228. for (p = pAdapt->VElanList.Flink;
  1229. p != &pAdapt->VElanList;
  1230. p = p->Flink)
  1231. {
  1232. pTmpVElan = CONTAINING_RECORD(p, VELAN, Link);
  1233. AdapterFilter |= pTmpVElan->PacketFilter;
  1234. }
  1235. //
  1236. // If all VELANs have packet filters set to 0, turn off
  1237. // receives on the lower adapter, if not already done.
  1238. //
  1239. if ((AdapterFilter == 0) && (pAdapt->PacketFilter != 0))
  1240. {
  1241. bSendUpdate = TRUE;
  1242. pAdapt->PacketFilter = 0;
  1243. }
  1244. else
  1245. //
  1246. // If receives had been turned off on the lower adapter, and
  1247. // the new filter is non-zero, turn on the lower adapter.
  1248. // We set the adapter to promiscuous mode in this sample
  1249. // so that we are able to receive packets directed to
  1250. // any of the VELAN MAC addresses.
  1251. //
  1252. if ((AdapterFilter != 0) && (pAdapt->PacketFilter == 0))
  1253. {
  1254. bSendUpdate = TRUE;
  1255. pAdapt->PacketFilter = MUX_ADAPTER_PACKET_FILTER;
  1256. }
  1257. MUX_RELEASE_ADAPT_WRITE_LOCK(pAdapt, &LockState);
  1258. if (bSendUpdate)
  1259. {
  1260. PtRequestAdapterAsync(
  1261. pAdapt,
  1262. NdisRequestSetInformation,
  1263. OID_GEN_CURRENT_PACKET_FILTER,
  1264. &pAdapt->PacketFilter,
  1265. sizeof(pAdapt->PacketFilter),
  1266. PtDiscardCompletedRequest);
  1267. }
  1268. }
  1269. while (FALSE);
  1270. DBGPRINT(MUX_INFO, ("<= SetPacketFilter VELAN %p, Status %x\n", pVElan, Status));
  1271. return(Status);
  1272. }
  1273. NDIS_STATUS
  1274. MPSetMulticastList(
  1275. IN PVELAN pVElan,
  1276. IN PVOID InformationBuffer,
  1277. IN ULONG InformationBufferLength,
  1278. OUT PULONG pBytesRead,
  1279. OUT PULONG pBytesNeeded
  1280. )
  1281. /*++
  1282. Routine Description:
  1283. Set the multicast list on the specified VELAN miniport.
  1284. We simply validate all information and copy in the multicast
  1285. list.
  1286. We don't forward the multicast list information down since
  1287. we set the lower binding to promisc. mode.
  1288. Arguments:
  1289. pVElan - VELAN on which to set the multicast list
  1290. InformationBuffer - pointer to new multicast list
  1291. InformationBufferLength - length in bytes of above list
  1292. pBytesRead - place to return # of bytes read from the above
  1293. pBytesNeeded - place to return expected min # of bytes
  1294. Return Value:
  1295. NDIS_STATUS
  1296. --*/
  1297. {
  1298. NDIS_STATUS Status;
  1299. PADAPT pAdapt;
  1300. LOCK_STATE LockState;
  1301. //
  1302. // Initialize.
  1303. //
  1304. *pBytesNeeded = sizeof(MUX_MAC_ADDRESS);
  1305. *pBytesRead = 0;
  1306. Status = NDIS_STATUS_SUCCESS;
  1307. do
  1308. {
  1309. if (InformationBufferLength % sizeof(MUX_MAC_ADDRESS))
  1310. {
  1311. Status = NDIS_STATUS_INVALID_LENGTH;
  1312. break;
  1313. }
  1314. if (InformationBufferLength > (VELAN_MAX_MCAST_LIST * sizeof(MUX_MAC_ADDRESS)))
  1315. {
  1316. Status = NDIS_STATUS_MULTICAST_FULL;
  1317. *pBytesNeeded = VELAN_MAX_MCAST_LIST * sizeof(MUX_MAC_ADDRESS);
  1318. break;
  1319. }
  1320. pAdapt = pVElan->pAdapt;
  1321. //
  1322. // Grab a Write lock on the adapter so that this operation
  1323. // does not interfere with any receives that might be accessing
  1324. // multicast list information.
  1325. //
  1326. MUX_ACQUIRE_ADAPT_WRITE_LOCK(pAdapt, &LockState);
  1327. NdisZeroMemory(&pVElan->McastAddrs[0],
  1328. VELAN_MAX_MCAST_LIST * sizeof(MUX_MAC_ADDRESS));
  1329. NdisMoveMemory(&pVElan->McastAddrs[0],
  1330. InformationBuffer,
  1331. InformationBufferLength);
  1332. pVElan->McastAddrCount = InformationBufferLength / sizeof(MUX_MAC_ADDRESS);
  1333. MUX_RELEASE_ADAPT_WRITE_LOCK(pAdapt, &LockState);
  1334. }
  1335. while (FALSE);
  1336. return (Status);
  1337. }
  1338. //
  1339. // Careful! Uses static storage for string. Used to simplify DbgPrints
  1340. // of MAC addresses.
  1341. //
  1342. PUCHAR
  1343. MacAddrToString(PVOID In)
  1344. {
  1345. static UCHAR String[20];
  1346. static PCHAR HexChars = "0123456789abcdef";
  1347. PUCHAR EthAddr = (PUCHAR) In;
  1348. UINT i;
  1349. PUCHAR s;
  1350. for (i = 0, s = String; i < 6; i++, EthAddr++)
  1351. {
  1352. *s++ = HexChars[(*EthAddr) >> 4];
  1353. *s++ = HexChars[(*EthAddr) & 0xf];
  1354. }
  1355. *s = '\0';
  1356. return String;
  1357. }
  1358. VOID
  1359. MPGenerateMacAddr(
  1360. PVELAN pVElan
  1361. )
  1362. /*++
  1363. Routine Description:
  1364. Generates a "virtual" MAC address for a VELAN.
  1365. NOTE: this is only a sample implementation of selecting
  1366. a MAC address for the VELAN. Other implementations are possible,
  1367. including using the MAC address of the underlying adapter as
  1368. the MAC address of the VELAN.
  1369. Arguments:
  1370. pVElan - Pointer to velan structure
  1371. Return Value:
  1372. None
  1373. --*/
  1374. {
  1375. pVElan->PermanentAddress[0] =
  1376. 0x02 | (((UCHAR)pVElan->VElanNumber & 0x3f) << 2);
  1377. pVElan->PermanentAddress[1] =
  1378. 0x02 | (((UCHAR)pVElan->VElanNumber & 0x3f) << 3);
  1379. ETH_COPY_NETWORK_ADDRESS(
  1380. pVElan->CurrentAddress,
  1381. pVElan->PermanentAddress);
  1382. DBGPRINT(MUX_LOUD, ("%d CurrentAddress %s\n",
  1383. pVElan->VElanNumber, MacAddrToString(&pVElan->CurrentAddress)));
  1384. DBGPRINT(MUX_LOUD, ("%d PermanentAddress %s\n",
  1385. pVElan->VElanNumber, MacAddrToString(&pVElan->PermanentAddress)));
  1386. }
  1387. #ifdef NDIS51_MINIPORT
  1388. VOID
  1389. MPCancelSendPackets(
  1390. IN NDIS_HANDLE MiniportAdapterContext,
  1391. IN PVOID CancelId
  1392. )
  1393. /*++
  1394. Routine Description:
  1395. The miniport entry point to handle cancellation of all send packets
  1396. that match the given CancelId. If we have queued any packets that match
  1397. this, then we should dequeue them and call NdisMSendComplete for all
  1398. such packets, with a status of NDIS_STATUS_REQUEST_ABORTED.
  1399. We should also call NdisCancelSendPackets in turn, on each lower binding
  1400. that this adapter corresponds to. This is to let miniports below cancel
  1401. any matching packets.
  1402. Arguments:
  1403. MiniportAdapterContext - pointer to VELAN structure
  1404. CancelId - ID of packets to be cancelled.
  1405. Return Value:
  1406. None
  1407. --*/
  1408. {
  1409. PVELAN pVElan = (PVELAN)MiniportAdapterContext;
  1410. //
  1411. // If we queue packets on our VELAN/adapter structure, this would be
  1412. // the place to acquire a spinlock to it, unlink any packets whose
  1413. // Id matches CancelId, release the spinlock and call NdisMSendComplete
  1414. // with NDIS_STATUS_REQUEST_ABORTED for all unlinked packets.
  1415. //
  1416. //
  1417. // Next, pass this down so that we let the miniport(s) below cancel
  1418. // any packets that they might have queued.
  1419. //
  1420. NdisCancelSendPackets(pVElan->pAdapt->BindingHandle, CancelId);
  1421. return;
  1422. }
  1423. VOID
  1424. MPDevicePnPEvent(
  1425. IN NDIS_HANDLE MiniportAdapterContext,
  1426. IN NDIS_DEVICE_PNP_EVENT DevicePnPEvent,
  1427. IN PVOID InformationBuffer,
  1428. IN ULONG InformationBufferLength
  1429. )
  1430. /*++
  1431. Routine Description:
  1432. This handler is called to notify us of PnP events directed to
  1433. our miniport device object.
  1434. Arguments:
  1435. MiniportAdapterContext - pointer to VELAN structure
  1436. DevicePnPEvent - the event
  1437. InformationBuffer - Points to additional event-specific information
  1438. InformationBufferLength - length of above
  1439. Return Value:
  1440. None
  1441. --*/
  1442. {
  1443. // TBD - add code/comments about processing this.
  1444. UNREFERENCED_PARAMETER(MiniportAdapterContext);
  1445. UNREFERENCED_PARAMETER(DevicePnPEvent);
  1446. UNREFERENCED_PARAMETER(InformationBuffer);
  1447. UNREFERENCED_PARAMETER(InformationBufferLength);
  1448. return;
  1449. }
  1450. VOID
  1451. MPAdapterShutdown(
  1452. IN NDIS_HANDLE MiniportAdapterContext
  1453. )
  1454. /*++
  1455. Routine Description:
  1456. This handler is called to notify us of an impending system shutdown.
  1457. Since this is not a hardware driver, there isn't anything specific
  1458. we need to do about this.
  1459. Arguments:
  1460. MiniportAdapterContext - pointer to VELAN structure
  1461. Return Value:
  1462. None
  1463. --*/
  1464. {
  1465. UNREFERENCED_PARAMETER(MiniportAdapterContext);
  1466. return;
  1467. }
  1468. #endif // NDIS51_MINIPORT
  1469. VOID
  1470. MPUnload(
  1471. IN PDRIVER_OBJECT DriverObject
  1472. )
  1473. {
  1474. NDIS_STATUS Status;
  1475. #if !DBG
  1476. UNREFERENCED_PARAMETER(DriverObject);
  1477. #endif
  1478. DBGPRINT(MUX_LOUD, ("==> MPUnload: DriverObj %p\n", DriverObject));
  1479. NdisDeregisterProtocol(&Status, ProtHandle);
  1480. DBGPRINT(MUX_LOUD, ("<== MPUnload \n"));
  1481. }
  1482. #if IEEE_VLAN_SUPPORT
  1483. NDIS_STATUS
  1484. MPHandleSendTagging(
  1485. IN PVELAN pVElan,
  1486. IN PNDIS_PACKET Packet,
  1487. IN OUT PNDIS_PACKET MyPacket
  1488. )
  1489. /*++
  1490. Routine Description:
  1491. This function is called when the driver supports IEEE802Q tagging.
  1492. It checks the packet to be sent on a VELAN and inserts a tag header
  1493. if necessary.
  1494. Arguments:
  1495. PVELAN - pointer to VELAN structure
  1496. Packet - pointer to original packet
  1497. MyPacket - pointer to the new allocated packet
  1498. Return Value:
  1499. NDIS_STATUS_SUCCESS if the packet was successfully parsed
  1500. and hence should be passed down to the lower driver. NDIS_STATUS_XXX
  1501. otherwise.
  1502. --*/
  1503. {
  1504. NDIS_PACKET_8021Q_INFO NdisPacket8021qInfo;
  1505. PVOID pEthTagBuffer;
  1506. PNDIS_BUFFER pNdisBuffer;
  1507. PVOID pVa;
  1508. ULONG BufferLength;
  1509. PNDIS_BUFFER pFirstBuffer;
  1510. PNDIS_BUFFER pSecondBuffer;
  1511. NDIS_STATUS Status;
  1512. NDIS_STATUS Status2;
  1513. PVOID pStartVa = NULL;
  1514. BOOLEAN IsFirstVa;
  1515. PVLAN_TAG_HEADER pTagHeader;
  1516. PUSHORT pTpid;
  1517. ULONG BytesToSkip;
  1518. PUSHORT pTypeLength;
  1519. //
  1520. // Add tag header here
  1521. //
  1522. Status = NDIS_STATUS_SUCCESS;
  1523. NdisPacket8021qInfo.Value = NDIS_PER_PACKET_INFO_FROM_PACKET(
  1524. MyPacket,
  1525. Ieee8021QInfo);
  1526. do
  1527. {
  1528. //
  1529. // If the vlan ID of the virtual miniport is 0, the miniport should act like it doesn't
  1530. // support VELAN tag processing
  1531. //
  1532. if (pVElan->VlanId == 0)
  1533. {
  1534. break;
  1535. }
  1536. //
  1537. // Insert a tag only if we have a configured VLAN ID
  1538. //
  1539. //
  1540. // We don't support E-RIF
  1541. //
  1542. if (NdisPacket8021qInfo.TagHeader.CanonicalFormatId)
  1543. {
  1544. //
  1545. // skip the packet, return NDIS_STATUS_FAILURE
  1546. //
  1547. Status = NDIS_STATUS_INVALID_PACKET;
  1548. break;
  1549. }
  1550. //
  1551. // The Vlan Id must be the same as the configured VLAN ID if it is non-zero
  1552. //
  1553. if ((NdisPacket8021qInfo.TagHeader.VlanId)
  1554. && (NdisPacket8021qInfo.TagHeader.VlanId != pVElan->VlanId))
  1555. {
  1556. Status = NDIS_STATUS_INVALID_PACKET;
  1557. break;
  1558. }
  1559. //
  1560. // Find the virtual address after the Ethernet Header
  1561. //
  1562. BytesToSkip = ETH_HEADER_SIZE;
  1563. pNdisBuffer = Packet->Private.Head;
  1564. IsFirstVa = TRUE;
  1565. //
  1566. // Assume the Ethernet Header is in the first buffer of the packet.
  1567. // The following loop is to find the start address of the data after
  1568. // the ethernet header. This may be either in the first NDIS buffer
  1569. // or in the second.
  1570. //
  1571. while (TRUE)
  1572. {
  1573. #ifdef NDIS51_MINIPORT
  1574. NdisQueryBufferSafe(pNdisBuffer, &pVa, (PUINT)&BufferLength, NormalPagePriority);
  1575. #else
  1576. NdisQueryBuffer(pNdisBuffer, &pVa, &BufferLength);
  1577. #endif
  1578. //
  1579. // The query can fail if the system is low on resources.
  1580. //
  1581. if (pVa == NULL)
  1582. {
  1583. break;
  1584. }
  1585. //
  1586. // Remember the start of the ethernet header for later.
  1587. //
  1588. if (IsFirstVa)
  1589. {
  1590. pStartVa = pVa;
  1591. IsFirstVa = FALSE;
  1592. }
  1593. //
  1594. // Have we gone far enough into the packet?
  1595. //
  1596. if (BytesToSkip == 0)
  1597. {
  1598. break;
  1599. }
  1600. //
  1601. // Does the current buffer contain bytes past the Ethernet
  1602. // header? If so, stop.
  1603. //
  1604. if (BufferLength > BytesToSkip)
  1605. {
  1606. pVa = (PVOID)((PUCHAR)pVa + BytesToSkip);
  1607. BufferLength -= BytesToSkip;
  1608. break;
  1609. }
  1610. //
  1611. // We haven't gone past the Ethernet header yet, so go
  1612. // to the next buffer.
  1613. //
  1614. BytesToSkip -= BufferLength;
  1615. pNdisBuffer = NDIS_BUFFER_LINKAGE(pNdisBuffer);
  1616. }
  1617. if (pVa == NULL)
  1618. {
  1619. Status = NDIS_STATUS_RESOURCES;
  1620. break;
  1621. }
  1622. //
  1623. // Allocate space for the Ethernet + VLAN tag header.
  1624. //
  1625. pEthTagBuffer = NdisAllocateFromNPagedLookasideList(&pVElan->TagLookaside);
  1626. //
  1627. // Memory allocation failed, can't send out the packet
  1628. //
  1629. if (pEthTagBuffer == NULL)
  1630. {
  1631. Status = NDIS_STATUS_RESOURCES;
  1632. break;
  1633. }
  1634. //
  1635. // Allocate NDIS buffers for the Ethernet + VLAN tag header and
  1636. // the data that follows these.
  1637. //
  1638. NdisAllocateBuffer(&Status,
  1639. &pSecondBuffer,
  1640. pVElan->BufferPoolHandle,
  1641. pVa, // byte following the Eth+tag headers
  1642. BufferLength);
  1643. NdisAllocateBuffer(&Status2,
  1644. &pFirstBuffer,
  1645. pVElan->BufferPoolHandle,
  1646. pEthTagBuffer,
  1647. ETH_HEADER_SIZE + VLAN_TAG_HEADER_SIZE);
  1648. if (Status != NDIS_STATUS_SUCCESS || Status2 != NDIS_STATUS_SUCCESS)
  1649. {
  1650. //
  1651. // One of the buffer allocations failed.
  1652. //
  1653. if (Status == NDIS_STATUS_SUCCESS)
  1654. {
  1655. NdisFreeBuffer(pSecondBuffer);
  1656. }
  1657. if (Status2 == NDIS_STATUS_SUCCESS)
  1658. {
  1659. NdisFreeBuffer(pFirstBuffer);
  1660. }
  1661. NdisFreeToNPagedLookasideList(&pVElan->TagLookaside, pEthTagBuffer);
  1662. Status = NDIS_STATUS_RESOURCES;
  1663. break;
  1664. }
  1665. //
  1666. // All allocations were successful, now prepare the packet
  1667. // to be sent down to the lower driver.
  1668. //
  1669. MyPacket->Private.Head = NDIS_BUFFER_LINKAGE(pNdisBuffer);
  1670. NdisChainBufferAtFront(MyPacket, pSecondBuffer)
  1671. NdisChainBufferAtFront(MyPacket, pFirstBuffer)
  1672. //
  1673. // Prepare the Ethernet and tag headers.
  1674. //
  1675. NdisMoveMemory(pEthTagBuffer, pStartVa, 2 * ETH_LENGTH_OF_ADDRESS);
  1676. pTpid = (PUSHORT)((PUCHAR)pEthTagBuffer + 2 * ETH_LENGTH_OF_ADDRESS);
  1677. *pTpid = TPID;
  1678. pTagHeader = (PVLAN_TAG_HEADER)(pTpid + 1);
  1679. //
  1680. // Write Ieee 802Q info to packet frame
  1681. //
  1682. INITIALIZE_TAG_HEADER_TO_ZERO(pTagHeader);
  1683. if (NdisPacket8021qInfo.Value)
  1684. {
  1685. SET_USER_PRIORITY_TO_TAG(pTagHeader, NdisPacket8021qInfo.TagHeader.UserPriority);
  1686. }
  1687. else
  1688. {
  1689. SET_USER_PRIORITY_TO_TAG(pTagHeader, 0);
  1690. }
  1691. SET_CANONICAL_FORMAT_ID_TO_TAG (pTagHeader, 0);
  1692. if (NdisPacket8021qInfo.TagHeader.VlanId)
  1693. {
  1694. SET_VLAN_ID_TO_TAG (pTagHeader, NdisPacket8021qInfo.TagHeader.VlanId);
  1695. }
  1696. else
  1697. {
  1698. SET_VLAN_ID_TO_TAG (pTagHeader, pVElan->VlanId);
  1699. }
  1700. pTypeLength = (PUSHORT)((PUCHAR)pTagHeader + sizeof(pTagHeader->TagInfo));
  1701. *pTypeLength = *((PUSHORT)((PUCHAR)pStartVa + 2 * ETH_LENGTH_OF_ADDRESS));
  1702. //
  1703. // Clear the Ieee8021QInfo field in packet being sent down
  1704. // to prevent double tag insertion!
  1705. //
  1706. NDIS_PER_PACKET_INFO_FROM_PACKET(MyPacket, Ieee8021QInfo) = 0;
  1707. }
  1708. while (FALSE);
  1709. return Status;
  1710. }
  1711. #endif // IEEE_VLAN_SUPPORT