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

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