home *** CD-ROM | disk | FTP | other *** search
/ PCNET 2006 September - Disc 1 / PCNET_CD_2006_09.iso / surpriz / MSRMesh-VirtualWIFI.MSI / miniport.c < prev    next >
Encoding:
C/C++ Source or Header  |  2005-06-24  |  69.8 KB  |  2,376 lines

  1. /*++
  2.  
  3. Author   : Ranveer Chandra
  4. Directory: VirtualWiFi_Root\driver
  5. File Name: miniport.c
  6. Purpose  : NDIS Miniport Entry points and utility functions for VirtualWiFi. 
  7. */
  8.  
  9. #include "precomp.h"
  10. #pragma hdrstop
  11.  
  12. #define MODULE_NUMBER           MODULE_MINI
  13.  
  14. NDIS_OID VElanSupportedOids[] =
  15. {
  16.     OID_GEN_SUPPORTED_LIST,
  17.     OID_GEN_HARDWARE_STATUS,
  18.     OID_GEN_MEDIA_SUPPORTED,
  19.     OID_GEN_MEDIA_IN_USE,
  20.     OID_GEN_MAXIMUM_LOOKAHEAD,
  21.     OID_GEN_MAXIMUM_FRAME_SIZE,
  22.     OID_GEN_LINK_SPEED,
  23.     OID_GEN_TRANSMIT_BUFFER_SPACE,
  24.     OID_GEN_RECEIVE_BUFFER_SPACE,
  25.     OID_GEN_TRANSMIT_BLOCK_SIZE,
  26.     OID_GEN_RECEIVE_BLOCK_SIZE,
  27.     OID_GEN_VENDOR_ID,
  28.     OID_GEN_VENDOR_DESCRIPTION,
  29.     OID_GEN_VENDOR_DRIVER_VERSION,
  30.     OID_GEN_CURRENT_PACKET_FILTER,
  31.     OID_GEN_CURRENT_LOOKAHEAD,
  32.     OID_GEN_DRIVER_VERSION,
  33.     OID_GEN_MAXIMUM_TOTAL_SIZE,
  34.     OID_GEN_PROTOCOL_OPTIONS,
  35.     OID_GEN_MAC_OPTIONS,
  36.     OID_GEN_MEDIA_CONNECT_STATUS,
  37.     OID_GEN_MAXIMUM_SEND_PACKETS,
  38.     OID_GEN_XMIT_OK,
  39.     OID_GEN_RCV_OK,
  40.     OID_GEN_XMIT_ERROR,
  41.     OID_GEN_RCV_ERROR,
  42.     OID_GEN_RCV_NO_BUFFER,
  43.     OID_GEN_RCV_CRC_ERROR,
  44.     OID_GEN_TRANSMIT_QUEUE_LENGTH,
  45.     OID_802_3_PERMANENT_ADDRESS,
  46.     OID_802_3_CURRENT_ADDRESS,
  47.     OID_802_3_MULTICAST_LIST,
  48.     OID_802_3_MAXIMUM_LIST_SIZE,
  49.     OID_802_3_RCV_ERROR_ALIGNMENT,
  50.     OID_802_3_XMIT_ONE_COLLISION,
  51.     OID_802_3_XMIT_MORE_COLLISIONS,
  52.     OID_802_3_XMIT_DEFERRED,
  53.     OID_802_3_XMIT_MAX_COLLISIONS,
  54.     OID_802_3_RCV_OVERRUN,
  55.     OID_802_3_XMIT_UNDERRUN,
  56.     OID_802_3_XMIT_HEARTBEAT_FAILURE,
  57.     OID_802_3_XMIT_TIMES_CRS_LOST,
  58.     OID_802_3_XMIT_LATE_COLLISIONS,
  59.     OID_PNP_CAPABILITIES,
  60.     OID_PNP_SET_POWER,
  61.     OID_PNP_QUERY_POWER,
  62.     OID_PNP_ADD_WAKE_UP_PATTERN,
  63.     OID_PNP_REMOVE_WAKE_UP_PATTERN,
  64. #if IEEE_VLAN_SUPPORT
  65.     OID_GEN_VLAN_ID,
  66. #endif    
  67.     OID_PNP_ENABLE_WAKE_UP
  68.     
  69. };
  70.  
  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.  
  83. Routine Description:
  84.  
  85.     This is the Miniport Initialize routine which gets called as a
  86.     result of our call to NdisIMInitializeDeviceInstanceEx.
  87.     The context parameter which we pass there is the VELan structure
  88.     which we retrieve here.
  89.  
  90. Arguments:
  91.  
  92.     OpenErrorStatus            Not used by us.
  93.     SelectedMediumIndex        Place-holder for what media we are using
  94.     MediumArray                Array of ndis media passed down to us to pick from
  95.     MediumArraySize            Size of the array
  96.     MiniportAdapterHandle       The handle NDIS uses to refer to us
  97.     WrapperConfigurationContext    For use by NdisOpenConfiguration
  98.  
  99. Return Value:
  100.  
  101.     NDIS_STATUS_SUCCESS unless something goes wrong
  102.  
  103. --*/
  104. {
  105.     UINT                i;
  106.     PVELAN              pVElan;
  107.     NDIS_STATUS         Status = NDIS_STATUS_FAILURE;
  108.     NDIS_MEDIUM         Medium;
  109.     NDIS_HANDLE         ConfigurationHandle;
  110.     PVOID               NetworkAddress;
  111.  
  112. #if IEEE_VLAN_SUPPORT
  113.     PNDIS_CONFIGURATION_PARAMETER   Params;
  114.     NDIS_STRING                     strVlanId = NDIS_STRING_CONST("VlanID");
  115. #endif
  116.     
  117.     //
  118.     // Start off by retrieving our virtual miniport context (VELAN) and 
  119.     // storing the Miniport handle in it.
  120.     //
  121.     pVElan = NdisIMGetDeviceContext(MiniportAdapterHandle);
  122.  
  123.     DBGPRINT(MUX_LOUD, ("==> Miniport Initialize: VELAN %p\n", pVElan));
  124.  
  125.     ASSERT(pVElan != NULL);
  126.     ASSERT(pVElan->pAdapt != NULL);
  127.  
  128.     do
  129.     {
  130.         pVElan->MiniportAdapterHandle = MiniportAdapterHandle;
  131.  
  132.         for (i = 0; i < MediumArraySize; i++)
  133.         {
  134.             if (MediumArray[i] == VELAN_MEDIA_TYPE)
  135.             {
  136.                 *SelectedMediumIndex = i;
  137.                 break;
  138.             }
  139.         }
  140.  
  141.         if (i == MediumArraySize)
  142.         {
  143.             Status = NDIS_STATUS_UNSUPPORTED_MEDIA;
  144.             break;
  145.         }
  146.  
  147.         //
  148.         // Access configuration parameters for this miniport.
  149.         //
  150.         NdisOpenConfiguration(
  151.             &Status,
  152.             &ConfigurationHandle,
  153.             WrapperConfigurationContext);
  154.  
  155.         if (Status != NDIS_STATUS_SUCCESS)
  156.         {
  157.             break;
  158.         }
  159.  
  160.         NdisReadNetworkAddress(
  161.             &Status,
  162.             &NetworkAddress,
  163.             &i,
  164.             ConfigurationHandle);
  165.  
  166.         /*
  167.         if( pVElan->pAdapt->PhysicalMedium == NdisPhysicalMediumWirelessLan )
  168.         {
  169.             PtQueryAdapterSync(pVElan->pAdapt,
  170.                             OID_802_11_SSID,
  171.                             &pVElan->SSID,
  172.                             sizeof(pVElan->SSID));
  173.  
  174.             PtQueryAdapterSync(pVElan->pAdapt,
  175.                             OID_802_11_INFRASTRUCTURE_MODE,
  176.                             &pVElan->InfrastructureMode,
  177.                             sizeof(pVElan->InfrastructureMode));
  178.         }
  179.         */
  180.  
  181.         ETH_COPY_NETWORK_ADDRESS(
  182.             pVElan->CurrentAddress,
  183.             pVElan->pAdapt->CurrentAddress);
  184.         /* 
  185.         //
  186.         // If there is a NetworkAddress override, use it 
  187.         //
  188.         if ((Status == NDIS_STATUS_SUCCESS) && (i == ETH_LENGTH_OF_ADDRESS))
  189.         {
  190.             ETH_COPY_NETWORK_ADDRESS(
  191.                 pVElan->CurrentAddress,
  192.                 NetworkAddress);
  193.         }
  194.         else
  195.         {
  196.             MPGenerateMacAddr(pVElan);
  197.         }
  198.         */
  199.  
  200. #if IEEE_VLAN_SUPPORT
  201.         //
  202.         // Read VLAN ID
  203.         //
  204.         NdisReadConfiguration(
  205.                 &Status,
  206.                 &Params,
  207.                 ConfigurationHandle,
  208.                 &strVlanId,
  209.                 NdisParameterInteger);
  210.         if (Status == NDIS_STATUS_SUCCESS)
  211.         {
  212.             //
  213.             // Check for out of bound
  214.             //
  215.             if (Params->ParameterData.IntegerData > VLAN_ID_MAX)
  216.             {
  217.                 pVElan->VlanId = VLANID_DEFAULT;
  218.             }
  219.             else
  220.             {
  221.                 pVElan->VlanId = Params->ParameterData.IntegerData;
  222.             }
  223.         }
  224.         else 
  225.         {
  226.             //
  227.             // Should fail the initialization or use default value
  228.             //
  229.             pVElan->VlanId = VLANID_DEFAULT;
  230.             Status = NDIS_STATUS_SUCCESS;
  231.             
  232.         }
  233.                 
  234. #endif    
  235.         
  236.         NdisCloseConfiguration(ConfigurationHandle);
  237.  
  238.         //
  239.         // Set the attributes now. NDIS_ATTRIBUTE_DESERIALIZE enables us
  240.         // to make up-calls to NDIS from arbitrary execution contexts.
  241.         // This also forces us to protect our data structures using
  242.         // spinlocks where appropriate. Also in this case NDIS does not queue
  243.         // packets on our behalf.
  244.         //
  245.         NdisMSetAttributesEx(MiniportAdapterHandle,
  246.                              pVElan,
  247.                              0,                                        
  248.                              NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT    |
  249.                                 NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT|
  250.                                 NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER |
  251.                                 NDIS_ATTRIBUTE_DESERIALIZE |
  252.                                 NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND,
  253.                              0);
  254.  
  255.  
  256.         //
  257.         // Create an ioctl interface
  258.         //
  259.         (VOID)PtRegisterDevice();
  260.  
  261.         Status = NDIS_STATUS_SUCCESS;
  262.     } while (FALSE);
  263.     
  264.     //
  265.     // If we had received an UnbindAdapter notification on the underlying
  266.     // adapter, we would have blocked that thread waiting for the IM Init
  267.     // process to complete. Wake up any such thread.
  268.     //
  269.     // See PtUnbindAdapter for more details.
  270.     //
  271.     ASSERT(pVElan->MiniportInitPending == TRUE);
  272.     pVElan->MiniportInitPending = FALSE;
  273.     NdisSetEvent(&pVElan->MiniportInitEvent);
  274.  
  275.     DBGPRINT(MUX_INFO, ("<== Miniport Initialize: VELAN %p, Status %x\n", pVElan, Status));
  276.  
  277.     return Status;
  278. }
  279.  
  280. VOID
  281. MPSendPackets(
  282.     IN    NDIS_HANDLE               MiniportAdapterContext,
  283.     IN    PPNDIS_PACKET             PacketArray,
  284.     IN    UINT                      NumberOfPackets
  285.     )
  286. /*++
  287.  
  288. Routine Description:
  289.  
  290.     Send Packet Array handler. Called by NDIS whenever a protocol
  291.     bound to our VELAN miniport sends one or more packets.
  292.  
  293.     We forward each packet to the lower binding.
  294.  
  295.     NOTE: NDIS will not Halt this VELAN miniport until all
  296.     these packets are "send-completed", and we don't unbind
  297.     the lower binding until all VELANs are halted. Therefore
  298.     we don't need locks or references on VELAN or ADAPT structures.
  299.  
  300. Arguments:
  301.  
  302.     MiniportAdapterContext    Pointer to our VELAN
  303.     PacketArray               Set of packets to send
  304.     NumberOfPackets           Length of above array
  305.  
  306. Return Value:
  307.  
  308.     None - we call NdisMSendComplete whenever we are done with a packet.
  309.  
  310. --*/
  311. {
  312.     PVELAN          pVElan = (PVELAN)MiniportAdapterContext;
  313.     PADAPT          pAdapt = pVElan->pAdapt;
  314.     PNDIS_PACKET    Packet, MyPacket;
  315.     NDIS_STATUS     Status;
  316.     PVOID           MediaSpecificInfo;
  317.     ULONG           MediaSpecificInfoSize;
  318.     UINT            i;
  319.     LOCK_STATE      LockState;
  320.  
  321.     
  322.     DBGPRINT(MUX_LOUD, ("=>MPSendPackets\n"));
  323.     for (i = 0; i < NumberOfPackets; i++)
  324.     {
  325.         Packet = PacketArray[i];
  326.  
  327.         //
  328.         // Allocate a new packet to encapsulate data from the original.
  329.         //
  330.         NdisAllocatePacket(&Status,
  331.                            &MyPacket,
  332.                            pVElan->SendPacketPoolHandle);
  333.  
  334.         if (Status == NDIS_STATUS_SUCCESS)
  335.         {
  336.             PMUX_SEND_RSVD      pSendReserved;
  337.  
  338.             pSendReserved = MUX_RSVD_FROM_SEND_PACKET(MyPacket);
  339.             pSendReserved->pOriginalPacket = Packet;
  340.             pSendReserved->pVElan = pVElan;
  341.  
  342.             MyPacket->Private.Flags = NdisGetPacketFlags(Packet) |
  343.                                         MUX_SEND_PACKET_FLAGS;
  344.  
  345.             MyPacket->Private.Head = Packet->Private.Head;
  346.             MyPacket->Private.Tail = Packet->Private.Tail;
  347. #ifdef WIN9X
  348.             //
  349.             // Work around the fact that NDIS does not initialize this
  350.             // to FALSE on Win9x.
  351.             //
  352.             MyPacket->Private.ValidCounts = FALSE;
  353. #endif // WIN9X
  354.  
  355.             //
  356.             // Copy OOB data to the new packet.
  357.             //
  358.             NdisMoveMemory(NDIS_OOB_DATA_FROM_PACKET(MyPacket),
  359.                            NDIS_OOB_DATA_FROM_PACKET(Packet),
  360.                            sizeof(NDIS_PACKET_OOB_DATA));
  361.             //
  362.             // Copy relevant parts of per packet info into the new packet.
  363.             //
  364. #ifndef WIN9X
  365.             NdisIMCopySendPerPacketInfo(MyPacket, Packet);
  366. #endif
  367.  
  368.             //
  369.             // Copy Media specific information.
  370.             //
  371.             NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO(Packet,
  372.                                                 &MediaSpecificInfo,
  373.                                                 &MediaSpecificInfoSize);
  374.  
  375.             if (MediaSpecificInfo || MediaSpecificInfoSize)
  376.             {
  377.                 NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO(MyPacket,
  378.                                                     MediaSpecificInfo,
  379.                                                     MediaSpecificInfoSize);
  380.             }
  381.  
  382. #if IEEE_VLAN_SUPPORT
  383.             Status = MPHandleSendTagging(pVElan, Packet, MyPacket);
  384.             if (Status != NDIS_STATUS_SUCCESS)
  385.             {
  386.                 NdisFreePacket(MyPacket);
  387.                 NdisMSendComplete(pVElan->MiniportAdapterHandle,
  388.                                     Packet,
  389.                                     Status);
  390.                 continue;
  391.             }
  392. #endif                
  393.  
  394.             // Acquire a write lock on the adapter for queueing packets
  395.             MUX_ACQUIRE_ADAPT_WRITE_LOCK(pAdapt, &LockState);
  396.  
  397.             pAdapt->nTotalPacketsSeen[pVElan->NetworkConnection]++;
  398.             // If the VElan sending the packet does not correspond to the currently
  399.             // active connection, then buffer packets, else send them
  400.             if (pVElan->NetworkConnection == pAdapt->CurrentActiveConnection && 
  401.                 pAdapt->isSSIDActive[pAdapt->CurrentActiveConnection])
  402.             {
  403.                 DBGPRINT(MUX_LOUD, ("Sending Packet since SSID is active\n"));
  404.                 //
  405.                 // Make note of the upcoming send.
  406.                 //
  407.                 MUX_INCR_PENDING_SENDS(pVElan);
  408.  
  409.                 //
  410.                 // Send it to the lower binding.
  411.                 //
  412.                 NdisSend(&Status,
  413.                         pAdapt->BindingHandle,
  414.                         MyPacket);
  415.  
  416.                 if (Status != NDIS_STATUS_PENDING)
  417.                 {
  418.                     PtSendComplete((NDIS_HANDLE)pAdapt,
  419.                                 MyPacket,
  420.                                 Status);
  421.                 }
  422.             }
  423.             else
  424.             {
  425.                 // Buffer the packet since adapter is in a different network
  426.                 DBGPRINT(MUX_LOUD, ("Queueing Packet since SSID is NOT active\n"));
  427.  
  428.                 InsertTailQueue(&pAdapt->SendWaitQueue[pVElan->NetworkConnection], MP_GET_PACKET_MR(MyPacket));
  429.                 pAdapt->nWaitSend[pVElan->NetworkConnection]++;
  430.             }
  431.  
  432.             MUX_RELEASE_ADAPT_WRITE_LOCK(pAdapt, &LockState);
  433.         }
  434.         else
  435.         {
  436.             //
  437.             // Failed to allocate a packet.
  438.             //
  439.             break;
  440.         }
  441.     }
  442.  
  443.     //
  444.     // If we bailed out above, fail any unprocessed sends.
  445.     //
  446.     while (i < NumberOfPackets)
  447.     {
  448.         NdisMSendComplete(pVElan->MiniportAdapterHandle,
  449.                           PacketArray[i],
  450.                           NDIS_STATUS_RESOURCES);
  451.         i++;
  452.     }
  453.     DBGPRINT(MUX_LOUD, ("<=MPSendPackets\n"));
  454.  
  455. }
  456.  
  457.  
  458. NDIS_STATUS
  459. MPQueryInformation(
  460.     IN    NDIS_HANDLE               MiniportAdapterContext,
  461.     IN    NDIS_OID                  Oid,
  462.     IN    PVOID                     InformationBuffer,
  463.     IN    ULONG                     InformationBufferLength,
  464.     OUT   PULONG                    BytesWritten,
  465.     OUT   PULONG                    BytesNeeded
  466.     )
  467. /*++
  468.  
  469. Routine Description:
  470.  
  471.     Entry point called by NDIS to query for the value of the specified OID.
  472.     All OID values are responded to right here, since this is a virtual
  473.     device (not pass-through).
  474.  
  475. Arguments:
  476.  
  477.     MiniportAdapterContext      Pointer to the adapter structure
  478.     Oid                         Oid for this query
  479.     InformationBuffer           Buffer for information
  480.     InformationBufferLength     Size of this buffer
  481.     BytesWritten                Specifies how much info is written
  482.     BytesNeeded                 In case the buffer is smaller than 
  483.                                 what we need, tell them how much is needed
  484.  
  485.  
  486. Return Value:
  487.  
  488.     Return code from the NdisRequest below.
  489.  
  490. --*/
  491. {
  492.     NDIS_STATUS                 Status = NDIS_STATUS_SUCCESS;
  493.     PVELAN                      pVElan;
  494.     NDIS_HARDWARE_STATUS HardwareStatus = NdisHardwareStatusReady;
  495.     NDIS_MEDIUM                 Medium = VELAN_MEDIA_TYPE;
  496.     UCHAR                       VendorDesc[] = VELAN_VENDOR_DESC;
  497.     ULONG                       ulInfo;
  498.     ULONG64                     ulInfo64;
  499.     USHORT                      usInfo;
  500.     UCHAR                       arrInfo[ETH_LENGTH_OF_ADDRESS];
  501.     PVOID                       pInfo = (PVOID) &ulInfo;
  502.     ULONG                       ulInfoLen = sizeof(ulInfo);
  503.     // Should we forward the request to the miniport below?
  504.     BOOLEAN                     bForwardRequest = FALSE;
  505.  
  506.     
  507.     pVElan = (PVELAN) MiniportAdapterContext;
  508.  
  509.     // Initialize the result
  510.     *BytesWritten = 0;
  511.     *BytesNeeded = 0;
  512.  
  513.     switch (Oid)
  514.     {
  515.         case OID_GEN_SUPPORTED_LIST:
  516.             pInfo = (PVOID) VElanSupportedOids;
  517.             ulInfoLen = sizeof(VElanSupportedOids);
  518.             break;
  519.  
  520.         case OID_GEN_SUPPORTED_GUIDS:
  521.             //
  522.             // Do NOT forward this down, otherwise we will
  523.             // end up with spurious instances of private WMI
  524.             // classes supported by the lower driver(s).
  525.             //
  526.             Status = NDIS_STATUS_NOT_SUPPORTED;
  527.             break;
  528.  
  529.         case OID_GEN_HARDWARE_STATUS:
  530.             pInfo = (PVOID) &HardwareStatus;
  531.             ulInfoLen = sizeof(NDIS_HARDWARE_STATUS);
  532.             break;
  533.  
  534.         case OID_GEN_MEDIA_SUPPORTED:
  535.         case OID_GEN_MEDIA_IN_USE:
  536.             pInfo = (PVOID) &Medium;
  537.             ulInfoLen = sizeof(NDIS_MEDIUM);
  538.             break;
  539.  
  540.         case OID_GEN_CURRENT_LOOKAHEAD:
  541.         case OID_GEN_MAXIMUM_LOOKAHEAD:
  542.             ulInfo = pVElan->LookAhead - ETH_HEADER_SIZE;
  543.             break;            
  544.             
  545.         case OID_GEN_MAXIMUM_FRAME_SIZE:
  546.             ulInfo = ETH_MAX_PACKET_SIZE - ETH_HEADER_SIZE;
  547.  
  548. #if IEEE_VLAN_SUPPORT
  549.             ulInfo -= VLAN_TAG_HEADER_SIZE;
  550. #endif
  551.             
  552.             break;
  553.  
  554.         case OID_GEN_MAXIMUM_TOTAL_SIZE:
  555.         case OID_GEN_TRANSMIT_BLOCK_SIZE:
  556.         case OID_GEN_RECEIVE_BLOCK_SIZE:
  557.             ulInfo = (ULONG) ETH_MAX_PACKET_SIZE;
  558. #if IEEE_VLAN_SUPPORT
  559.             ulInfo -= VLAN_TAG_HEADER_SIZE;
  560. #endif            
  561.             break;
  562.             
  563.         case OID_GEN_MAC_OPTIONS:
  564.             ulInfo = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | 
  565.                      NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
  566.                      NDIS_MAC_OPTION_NO_LOOPBACK;
  567.  
  568. #if IEEE_VLAN_SUPPORT
  569.             ulInfo |= (NDIS_MAC_OPTION_8021P_PRIORITY |
  570.                         NDIS_MAC_OPTION_8021Q_VLAN);
  571. #endif
  572.             
  573.             break;
  574.  
  575.         case OID_GEN_LINK_SPEED:
  576.             bForwardRequest = TRUE;
  577.             break;
  578.  
  579.         case OID_GEN_TRANSMIT_BUFFER_SPACE:
  580.             ulInfo = ETH_MAX_PACKET_SIZE * pVElan->MaxBusySends;
  581. #if IEEE_VLAN_SUPPORT
  582.             ulInfo -= VLAN_TAG_HEADER_SIZE * pVElan->MaxBusySends;
  583. #endif            
  584.             break;
  585.  
  586.         case OID_GEN_RECEIVE_BUFFER_SPACE:
  587.             ulInfo = ETH_MAX_PACKET_SIZE * pVElan->MaxBusyRecvs;
  588. #if IEEE_VLAN_SUPPORT
  589.             ulInfo -= VLAN_TAG_HEADER_SIZE * pVElan->MaxBusyRecvs;
  590. #endif            
  591.             
  592.             break;
  593.  
  594.         case OID_GEN_VENDOR_ID:
  595.             ulInfo = VELAN_VENDOR_ID;
  596.             break;
  597.  
  598.         case OID_GEN_VENDOR_DESCRIPTION:
  599.             pInfo = VendorDesc;
  600.             ulInfoLen = sizeof(VendorDesc);
  601.             break;
  602.             
  603.         case OID_GEN_VENDOR_DRIVER_VERSION:
  604.             ulInfo = VELAN_VENDOR_ID;
  605.             break;
  606.  
  607.         case OID_GEN_DRIVER_VERSION:
  608.             usInfo = (USHORT) VELAN_DRIVER_VERSION;
  609.             pInfo = (PVOID) &usInfo;
  610.             ulInfoLen = sizeof(USHORT);
  611.             break;
  612.  
  613.         case OID_802_3_PERMANENT_ADDRESS:
  614.             pInfo = pVElan->PermanentAddress;
  615.             ulInfoLen = ETH_LENGTH_OF_ADDRESS;
  616.             break;
  617.  
  618.         case OID_802_3_CURRENT_ADDRESS:
  619.             pInfo = pVElan->CurrentAddress;
  620.             ulInfoLen = ETH_LENGTH_OF_ADDRESS;
  621.             break;
  622.  
  623.         case OID_802_3_MAXIMUM_LIST_SIZE:
  624.             ulInfo = VELAN_MAX_MCAST_LIST;
  625.             break;
  626.  
  627.         case OID_GEN_MAXIMUM_SEND_PACKETS:
  628.             ulInfo = VELAN_MAX_SEND_PKTS;
  629.             break;
  630.  
  631.         case OID_GEN_MEDIA_CONNECT_STATUS:
  632.             //
  633.             // Get this from the adapter below.
  634.             //
  635.             // bForwardRequest = TRUE;
  636.             ulInfo = FALSE;
  637.             break;
  638.  
  639.         case OID_PNP_QUERY_POWER:
  640.             // simply succeed this.
  641.             ulInfoLen = 0;
  642.             break;
  643.  
  644.         case OID_PNP_CAPABILITIES:
  645.         case OID_PNP_WAKE_UP_PATTERN_LIST:
  646.             //
  647.             // Pass down these power management/PNP OIDs.
  648.             //
  649.             bForwardRequest = TRUE;
  650.             break;
  651.  
  652.         case OID_GEN_XMIT_OK:
  653.             ulInfo64 = pVElan->GoodTransmits;
  654.             pInfo = &ulInfo64;
  655.             if (InformationBufferLength >= sizeof(ULONG64) ||
  656.                 InformationBufferLength == 0)
  657.             {
  658.                 ulInfoLen = sizeof(ULONG64);
  659.             }
  660.             else
  661.             {
  662.                 ulInfoLen = sizeof(ULONG);
  663.             }
  664.             break;
  665.     
  666.         case OID_GEN_RCV_OK:
  667.             ulInfo64 = pVElan->GoodReceives;
  668.             pInfo = &ulInfo64;
  669.             if (InformationBufferLength >= sizeof(ULONG64) ||
  670.                 InformationBufferLength == 0)
  671.             {
  672.                 ulInfoLen = sizeof(ULONG64);
  673.             }
  674.             else
  675.             {
  676.                 ulInfoLen = sizeof(ULONG);
  677.             }
  678.             break;
  679.     
  680.         case OID_GEN_XMIT_ERROR:
  681.             ulInfo = pVElan->TxAbortExcessCollisions +
  682.                 pVElan->TxDmaUnderrun +
  683.                 pVElan->TxLostCRS +
  684.                 pVElan->TxLateCollisions+
  685.                 pVElan->TransmitFailuresOther;
  686.             break;
  687.     
  688.         case OID_GEN_RCV_ERROR:
  689.             ulInfo = pVElan->RcvCrcErrors +
  690.                 pVElan->RcvAlignmentErrors +
  691.                 pVElan->RcvResourceErrors +
  692.                 pVElan->RcvDmaOverrunErrors +
  693.                 pVElan->RcvRuntErrors;
  694. #if IEEE_VLAN_SUPPORT
  695.             ulInfo +=
  696.                 (pVElan->RcvVlanIdErrors +
  697.                 pVElan->RcvFormatErrors);
  698. #endif
  699.  
  700.             break;
  701.     
  702.         case OID_GEN_RCV_NO_BUFFER:
  703.             ulInfo = pVElan->RcvResourceErrors;
  704.             break;
  705.     
  706.         case OID_GEN_RCV_CRC_ERROR:
  707.             ulInfo = pVElan->RcvCrcErrors;
  708.             break;
  709.     
  710.         case OID_GEN_TRANSMIT_QUEUE_LENGTH:
  711.             ulInfo = pVElan->RegNumTcb;
  712.             break;
  713.     
  714.         case OID_802_3_RCV_ERROR_ALIGNMENT:
  715.             ulInfo = pVElan->RcvAlignmentErrors;
  716.             break;
  717.     
  718.         case OID_802_3_XMIT_ONE_COLLISION:
  719.             ulInfo = pVElan->OneRetry;
  720.             break;
  721.     
  722.         case OID_802_3_XMIT_MORE_COLLISIONS:
  723.             ulInfo = pVElan->MoreThanOneRetry;
  724.             break;
  725.     
  726.         case OID_802_3_XMIT_DEFERRED:
  727.             ulInfo = pVElan->TxOKButDeferred;
  728.             break;
  729.     
  730.         case OID_802_3_XMIT_MAX_COLLISIONS:
  731.             ulInfo = pVElan->TxAbortExcessCollisions;
  732.             break;
  733.     
  734.         case OID_802_3_RCV_OVERRUN:
  735.             ulInfo = pVElan->RcvDmaOverrunErrors;
  736.             break;
  737.     
  738.         case OID_802_3_XMIT_UNDERRUN:
  739.             ulInfo = pVElan->TxDmaUnderrun;
  740.             break;
  741.     
  742.         case OID_802_3_XMIT_HEARTBEAT_FAILURE:
  743.             ulInfo = pVElan->TxLostCRS;
  744.             break;
  745.     
  746.         case OID_802_3_XMIT_TIMES_CRS_LOST:
  747.             ulInfo = pVElan->TxLostCRS;
  748.             break;
  749.     
  750.         case OID_802_3_XMIT_LATE_COLLISIONS:
  751.             ulInfo = pVElan->TxLateCollisions;
  752.             break;
  753.    
  754. #if IEEE_VLAN_SUPPORT            
  755.         case OID_GEN_VLAN_ID:
  756.             ulInfo = pVElan->VlanId;
  757.             break;
  758.  
  759. #endif
  760.  
  761.         default:
  762.             Status = NDIS_STATUS_INVALID_OID;
  763.             break;
  764.     }
  765.  
  766.     if (bForwardRequest == FALSE)
  767.     {
  768.         //
  769.         // No need to forward this request down.
  770.         //
  771.         if (Status == NDIS_STATUS_SUCCESS)
  772.         {
  773.             if (ulInfoLen <= InformationBufferLength)
  774.             {
  775.                 // Copy result into InformationBuffer
  776.                 *BytesWritten = ulInfoLen;
  777.                 if(ulInfoLen)
  778.                 {
  779.                     NdisMoveMemory(InformationBuffer, pInfo, ulInfoLen);
  780.                 }
  781.             }
  782.             else
  783.             {
  784.                 // too short
  785.                 *BytesNeeded = ulInfoLen;
  786.                 Status = NDIS_STATUS_BUFFER_TOO_SHORT;
  787.             }
  788.         }
  789.     }
  790.     else
  791.     {
  792.         //
  793.         // Send this request to the binding below.
  794.         //
  795.         Status = MPForwardRequest(pVElan,
  796.                                    NdisRequestQueryInformation,
  797.                                    Oid,
  798.                                    InformationBuffer,
  799.                                    InformationBufferLength,
  800.                                    BytesWritten,
  801.                                    BytesNeeded);
  802.     }
  803.  
  804.     if ((Status != NDIS_STATUS_SUCCESS) &&
  805.         (Status != NDIS_STATUS_PENDING))
  806.     {
  807.         DBGPRINT(MUX_WARN, ("MPQueryInformation VELAN %p, OID 0x%08x, Status = 0x%08x\n",
  808.                     pVElan, Oid, Status));
  809.     }
  810.     
  811.     return(Status);
  812.  
  813. }
  814.  
  815.  
  816. NDIS_STATUS
  817. MPSetInformation(
  818.     IN    NDIS_HANDLE               MiniportAdapterContext,
  819.     IN    NDIS_OID                  Oid,
  820.     IN    PVOID                     InformationBuffer,
  821.     IN    ULONG                     InformationBufferLength,
  822.     OUT   PULONG                    BytesRead,
  823.     OUT   PULONG                    BytesNeeded
  824.     )
  825. /*++
  826.  
  827. Routine Description:
  828.  
  829.     This is the handler for an OID set operation. Relevant
  830.     OIDs are forwarded down to the lower miniport for handling.
  831.  
  832. Arguments:
  833.  
  834.     MiniportAdapterContext      Pointer to the adapter structure
  835.     Oid                         Oid for this query
  836.     InformationBuffer           Buffer for information
  837.     InformationBufferLength     Size of this buffer
  838.     BytesRead                   Specifies how much info is read
  839.     BytesNeeded                 In case the buffer is smaller than what 
  840.                                 we need, tell them how much is needed
  841.  
  842. Return Value:
  843.  
  844.     Return code from the NdisRequest below.
  845.  
  846. --*/
  847. {
  848.     NDIS_STATUS             Status = NDIS_STATUS_SUCCESS;
  849.     PVELAN                  pVElan = (PVELAN) MiniportAdapterContext;
  850.     ULONG                   PacketFilter;
  851.     NDIS_DEVICE_POWER_STATE NewDeviceState;
  852.     
  853.     // Should we forward the request to the miniport below?
  854.     BOOLEAN                 bForwardRequest = FALSE;
  855.  
  856.     *BytesRead = 0;
  857.     *BytesNeeded = 0;
  858.  
  859.     switch (Oid)
  860.     {
  861.         //
  862.         // Let the miniport below handle these OIDs:
  863.         //
  864.         case OID_PNP_ADD_WAKE_UP_PATTERN:
  865.         case OID_PNP_REMOVE_WAKE_UP_PATTERN:
  866.         case OID_PNP_ENABLE_WAKE_UP:
  867.             bForwardRequest = TRUE;
  868.             break;
  869.  
  870.         case OID_PNP_SET_POWER:
  871.             //
  872.             // Store new power state and succeed the request.
  873.             //
  874.             *BytesNeeded = sizeof(NDIS_DEVICE_POWER_STATE);
  875.             if (InformationBufferLength < *BytesNeeded)
  876.             {
  877.                 Status = NDIS_STATUS_INVALID_LENGTH;
  878.                 break;
  879.             }
  880.            
  881.             NewDeviceState = (*(PNDIS_DEVICE_POWER_STATE)InformationBuffer);
  882.             
  883.             //
  884.             // Check if the VELAN adapter goes from lower power state to D0
  885.             // 
  886.             if ((MUX_IS_LOW_POWER_STATE(pVElan->MPDevicePowerState)) 
  887.                     && (!MUX_IS_LOW_POWER_STATE(NewDeviceState)))
  888.             {
  889.                 //
  890.                 // Indicate the media status is necessary
  891.                 // 
  892.                 if (pVElan->LastIndicatedStatus != pVElan->LatestUnIndicateStatus)
  893.                 {
  894.                     NdisMIndicateStatus(pVElan->MiniportAdapterHandle,
  895.                                         pVElan->LatestUnIndicateStatus,
  896.                                         (PVOID)NULL,
  897.                                         0);
  898.                     NdisMIndicateStatusComplete(pVElan->MiniportAdapterHandle);
  899.                     pVElan->LastIndicatedStatus = pVElan->LatestUnIndicateStatus;
  900.                 }
  901.             }
  902.             //
  903.             // Check if the VELAN adapter goes from D0 to lower power state
  904.             // 
  905.             if ((!MUX_IS_LOW_POWER_STATE(pVElan->MPDevicePowerState)) 
  906.                     && (MUX_IS_LOW_POWER_STATE(NewDeviceState)))
  907.             {
  908.                 //
  909.                 //  Initialize LastUnIndicateStatus 
  910.                 // 
  911.                 pVElan->LatestUnIndicateStatus = pVElan->LastIndicatedStatus;
  912.             }
  913.             
  914.             NdisMoveMemory(&pVElan->MPDevicePowerState,
  915.                            InformationBuffer,
  916.                            *BytesNeeded);
  917.  
  918.             DBGPRINT(MUX_INFO, ("SetInfo: VElan %p, new miniport power state --- %d\n",
  919.                     pVElan, pVElan->MPDevicePowerState));
  920.  
  921.             break;
  922.  
  923.         case OID_802_3_MULTICAST_LIST:
  924.             Status = MPSetMulticastList(pVElan,
  925.                                         InformationBuffer,
  926.                                         InformationBufferLength,
  927.                                         BytesRead,
  928.                                         BytesNeeded);
  929.             break;
  930.  
  931.         case OID_GEN_CURRENT_PACKET_FILTER:
  932.             if (InformationBufferLength != sizeof(ULONG))
  933.             {
  934.                 Status = NDIS_STATUS_INVALID_LENGTH;
  935.                 *BytesNeeded = sizeof(ULONG);
  936.                 break;
  937.             }
  938.  
  939.             NdisMoveMemory(&PacketFilter, InformationBuffer, sizeof(ULONG));
  940.             *BytesRead = sizeof(ULONG);
  941.  
  942.             Status = MPSetPacketFilter(pVElan,
  943.                                        PacketFilter);
  944.             break;
  945.  
  946.         case OID_GEN_CURRENT_LOOKAHEAD:
  947. #if IEEE_VLAN_SUPPORT
  948.             //
  949.             // In order to simplify parsing and to avoid excessive
  950.             // copying, we need the tag header also to be present in the
  951.             // lookahead buffer. Make sure that the driver below
  952.             // includes that.
  953.             //
  954.             *(PULONG)InformationBuffer += VLAN_TAG_HEADER_SIZE;
  955. #endif            
  956.             bForwardRequest = TRUE;
  957.             break;
  958.             
  959. #if IEEE_VLAN_SUPPORT
  960.         case OID_GEN_VLAN_ID:
  961.             if (InformationBufferLength != sizeof(ULONG))
  962.             {
  963.                 Status = NDIS_STATUS_INVALID_LENGTH;
  964.                 *BytesNeeded = sizeof(ULONG);
  965.                 break;
  966.             }
  967.             NdisMoveMemory(&(pVElan->VlanId), InformationBuffer, sizeof(ULONG));
  968.             break;
  969. #endif
  970.             
  971.         default:
  972.             Status = NDIS_STATUS_INVALID_OID;
  973.             break;
  974.  
  975.     }
  976.     
  977.     if (bForwardRequest == FALSE)
  978.     {
  979.         if (Status == NDIS_STATUS_SUCCESS)
  980.         {
  981.             *BytesRead = InformationBufferLength;
  982.         }
  983.     }
  984.     else
  985.     {
  986.         //
  987.         // Send this request to the binding below.
  988.         //
  989.         Status = MPForwardRequest(pVElan,
  990.                                   NdisRequestSetInformation,
  991.                                   Oid,
  992.                                   InformationBuffer,
  993.                                   InformationBufferLength,
  994.                                   BytesRead,
  995.                                   BytesNeeded);
  996.     }
  997.  
  998.     return(Status);
  999. }
  1000.  
  1001. VOID
  1002. MPReturnPacket(
  1003.     IN    NDIS_HANDLE             MiniportAdapterContext,
  1004.     IN    PNDIS_PACKET            Packet
  1005.     )
  1006. /*++
  1007.  
  1008. Routine Description:
  1009.  
  1010.     NDIS Miniport entry point called whenever protocols are done with
  1011.     a packet that we had indicated up and they had queued up for returning
  1012.     later.
  1013.  
  1014. Arguments:
  1015.  
  1016.     MiniportAdapterContext    - pointer to VELAN structure
  1017.     Packet    - packet being returned.
  1018.  
  1019. Return Value:
  1020.  
  1021.     None.
  1022.  
  1023. --*/
  1024. {
  1025.     PVELAN              pVElan = (PVELAN)MiniportAdapterContext;
  1026.     PNDIS_PACKET        pOriginalPacket;
  1027.     PMUX_RECV_RSVD      pRecvRsvd;
  1028. #if IEEE_VLAN_SUPPORT
  1029.     NDIS_PACKET_8021Q_INFO  NdisPacket8021qInfo;
  1030. #endif    
  1031.     
  1032.     pRecvRsvd = MUX_RSVD_FROM_RECV_PACKET(Packet);
  1033.     pOriginalPacket = pRecvRsvd->pOriginalPacket;
  1034.  
  1035.     //
  1036.     // Reclaim our packet.
  1037.     //
  1038. #if IEEE_VLAN_SUPPORT
  1039.     //
  1040.     // We would have set per-packet information if we had
  1041.     // extracted a tag header from the received packet.
  1042.     // 
  1043.     NdisPacket8021qInfo.Value = NDIS_PER_PACKET_INFO_FROM_PACKET (
  1044.                                                 Packet,
  1045.                                                 Ieee8021QInfo);
  1046.     //
  1047.     // If we did remove the tag header from the received packet,
  1048.     // we would have allocated a buffer to describe the "untagged"
  1049.     // header (see PtHandleRcvTagging); free it.
  1050.     // 
  1051.     if (NdisPacket8021qInfo.Value)
  1052.     {
  1053.         NdisFreeBuffer(Packet->Private.Head);
  1054.     }
  1055.  
  1056. #endif
  1057.     
  1058.     NdisFreePacket(Packet);
  1059.  
  1060.     //
  1061.     // Return the original packet received at our protocol
  1062.     // edge, if any.
  1063.     //
  1064.     // NOTE that we might end up calling NdisReturnPackets
  1065.     // multiple times with the same "lower" packet, based on
  1066.     // the number of VELANs to which we had indicated that
  1067.     // packet. The number of times we do so should match
  1068.     // the return value from our PtReceivePacket handler.
  1069.     //
  1070.     if (pOriginalPacket != NULL)
  1071.     {
  1072.         NdisReturnPackets(&pOriginalPacket, 1);
  1073.     }
  1074.     else
  1075.     {
  1076.         //
  1077.         // If no original packet, then we have been called
  1078.         // here to reclaim a packet used to forward up
  1079.         // a non-packet receive (see PtReceive). There
  1080.         // is nothing more to be done.
  1081.         //
  1082.     }
  1083.  
  1084.  
  1085.     MUX_DECR_PENDING_RECEIVES(pVElan);
  1086. }
  1087.  
  1088.  
  1089. NDIS_STATUS
  1090. MPTransferData(
  1091.     OUT PNDIS_PACKET                Packet,
  1092.     OUT PUINT                       BytesTransferred,
  1093.     IN  NDIS_HANDLE                 MiniportAdapterContext,
  1094.     IN  NDIS_HANDLE                 MiniportReceiveContext,
  1095.     IN  UINT                        ByteOffset,
  1096.     IN  UINT                        BytesToTransfer
  1097.     )
  1098. /*++
  1099.  
  1100. Routine Description:
  1101.  
  1102.     Miniport's transfer data handler.  This is called if we had
  1103.     indicated receive data using a non-packet API, for e.g. if
  1104.     the lookahead buffer did not contain the entire data.
  1105.  
  1106.     We need to forward this to the miniport below to that it can
  1107.     copy in the rest of the data. We call NdisTransferData to do so.
  1108.     However, when that completes (see PtTransferDataComplete), we
  1109.     have to get back at the VELAN from which this packet came so that
  1110.     we can complete this request with the right MiniportAdapterHandle.
  1111.     We therefore allocate a new packet, pointing to the same buffer
  1112.     as the packet just passed in, and use reserved space in the packet
  1113.     to hold a backpointer to the VELAN from which this came.
  1114.  
  1115. Arguments:
  1116.  
  1117.     Packet                    Destination packet
  1118.     BytesTransferred          Place to return how much data was copied
  1119.     MiniportAdapterContext    Pointer to the VELAN structure
  1120.     MiniportReceiveContext    Context
  1121.     ByteOffset                Offset into the packet for copying data
  1122.     BytesToTransfer           How much to copy.
  1123.  
  1124. Return Value:
  1125.  
  1126.     Status of transfer
  1127.  
  1128. --*/
  1129. {
  1130.     PVELAN          pVElan = (PVELAN)MiniportAdapterContext;
  1131.     NDIS_STATUS     Status;
  1132.     PNDIS_PACKET    MyPacket;
  1133.     PMUX_TD_RSVD    pTDReserved;
  1134. #if IEEE_VLAN_SUPPORT
  1135.     PMUX_RCV_CONTEXT        pMuxRcvContext;
  1136. #endif    
  1137.     
  1138.  
  1139.     do
  1140.     {
  1141.         NdisAllocatePacket(&Status,
  1142.                            &MyPacket,
  1143.                            pVElan->SendPacketPoolHandle);
  1144.  
  1145.         if (Status != NDIS_STATUS_SUCCESS)
  1146.         {
  1147.             break;
  1148.         }
  1149.  
  1150.         pTDReserved = MUX_RSVD_FROM_TD_PACKET(MyPacket);
  1151.         pTDReserved->pOriginalPacket = Packet;
  1152.         pTDReserved->pVElan = pVElan;
  1153.  
  1154.         MyPacket->Private.Flags = NdisGetPacketFlags(Packet) |
  1155.                                         MUX_SEND_PACKET_FLAGS;
  1156.  
  1157.         MyPacket->Private.Head = Packet->Private.Head;
  1158.         MyPacket->Private.Tail = Packet->Private.Tail;
  1159. #ifdef WIN9X
  1160.         //
  1161.         // Work around the fact that NDIS does not initialize this
  1162.         // field on Win9x.
  1163.         //
  1164.         MyPacket->Private.ValidCounts = FALSE;
  1165. #endif // WIN9X
  1166.  
  1167. #if IEEE_VLAN_SUPPORT
  1168.         //
  1169.         // Check if the original received packet did contain a
  1170.         // VLAN tag header. If so, make sure we get the upcoming
  1171.         // call to NdisTransferData to skip the tag header.
  1172.         //
  1173.         pMuxRcvContext = (PMUX_RCV_CONTEXT)MiniportReceiveContext;
  1174.         if (pMuxRcvContext->TagHeaderLen == VLAN_TAG_HEADER_SIZE)
  1175.         {
  1176.             //
  1177.             // There was a tag header in the received packet.
  1178.             //
  1179.             ByteOffset += VLAN_TAG_HEADER_SIZE;
  1180.  
  1181.             //
  1182.             // Copy the 8021Q info into the packet
  1183.             //
  1184.             NDIS_PER_PACKET_INFO_FROM_PACKET(Packet, Ieee8021QInfo) =
  1185.                                         pMuxRcvContext->NdisPacket8021QInfo.Value;
  1186.         }
  1187.  
  1188.         //
  1189.         // Get back the lower driver's receive context for this indication.
  1190.         //
  1191.         MiniportReceiveContext = pMuxRcvContext->MacRcvContext;
  1192. #endif
  1193.         
  1194.         NdisTransferData(&Status,
  1195.                          pVElan->pAdapt->BindingHandle,
  1196.                          MiniportReceiveContext,
  1197.                          ByteOffset,
  1198.                          BytesToTransfer,
  1199.                          MyPacket,
  1200.                          BytesTransferred);
  1201.     
  1202.         if (Status != NDIS_STATUS_PENDING)
  1203.         {
  1204.             PtTransferDataComplete(pVElan->pAdapt,
  1205.                                    MyPacket,
  1206.                                    Status,
  1207.                                    *BytesTransferred);
  1208.  
  1209.             Status = NDIS_STATUS_PENDING;
  1210.         }
  1211.     }
  1212.     while (FALSE);
  1213.  
  1214.     return(Status);
  1215. }
  1216.     
  1217.     
  1218.  
  1219. VOID
  1220. MPHalt(
  1221.     IN    NDIS_HANDLE                MiniportAdapterContext
  1222.     )
  1223. /*++
  1224.  
  1225. Routine Description:
  1226.  
  1227.     Halt handler. Add any further clean-up for the VELAN to this
  1228.     function.
  1229.  
  1230.     We wait for all pending I/O on the VELAN to complete and then
  1231.     unlink the VELAN from the adapter.
  1232.  
  1233. Arguments:
  1234.  
  1235.     MiniportAdapterContext    Pointer to the pVElan
  1236.  
  1237. Return Value:
  1238.  
  1239.     None.
  1240.  
  1241. --*/
  1242. {
  1243.     PVELAN            pVElan = (PVELAN)MiniportAdapterContext;
  1244.     PADAPT            pAdapt = pVElan->pAdapt;
  1245.     LOCK_STATE        LockState;
  1246.  
  1247.     DBGPRINT(MUX_LOUD, ("==>MiniportHalt: VELAN %p\n", pVElan));
  1248.  
  1249.     //
  1250.     // Mark the VELAN so that we don't send down any new requests or
  1251.     // sends to the adapter below, or new receives/indications to
  1252.     // protocols above.
  1253.     //
  1254.     pVElan->MiniportHalting = TRUE;
  1255.  
  1256.     // set the Buffer Signal used by the VirtualWiFi Server to be true
  1257.     pAdapt->isSSIDActive[pVElan->NetworkConnection] = TRUE;
  1258.     PtIoctlSendBufferedPackets(pAdapt);
  1259.  
  1260.     //
  1261.     // Update the packet filter on the underlying adapter if needed.
  1262.     //
  1263.     if (pVElan->PacketFilter != 0)
  1264.     {
  1265.         MPSetPacketFilter(pVElan, 0);
  1266.     }
  1267.  
  1268.     MPCancelPacketsFromVElan(pVElan);
  1269.  
  1270.     // Reduce the number of network Connections using the SSID
  1271.     pAdapt->NumActiveConnectionsOnSSID[pVElan->NetworkConnection]--;
  1272.  
  1273.     if (NumActiveConnections(pAdapt) == 0)
  1274.     {
  1275.         PtIoctlSendBufferedPackets(pAdapt);
  1276.     }
  1277.  
  1278.     if (NumActiveConnections(pAdapt) == 1)
  1279.     {
  1280.         if (pAdapt->NumActiveConnectionsOnSSID[pAdapt->CurrentActiveConnection] == 0)
  1281.         {
  1282.             if(!SetNextActiveConnection(pAdapt))
  1283.                 ASSERT(FALSE);
  1284.         }
  1285.  
  1286.         SetSSIDAndClearSendPackets(pAdapt);
  1287.     }
  1288.  
  1289.     /*
  1290.     if(pAdapt->NumActiveConnectionsOnSSID[pVElan->NetworkConnection] == 0)
  1291.     {
  1292.         MUX_ACQUIRE_ADAPT_WRITE_LOCK(pAdapt, &LockState);
  1293.         //
  1294.         // Get the packets from SendWaitQueue and complete them if any
  1295.         //
  1296.         while (!IsQueueEmpty(&pAdapt->SendWaitQueue[pVElan->NetworkConnection]))
  1297.         {
  1298.             PVELAN           pPacketVElan;
  1299.             PMUX_SEND_RSVD   pSendReserved;
  1300.             PQUEUE_ENTRY     pEntry;
  1301.             PNDIS_PACKET     Packet;
  1302.  
  1303.             pEntry = RemoveHeadQueue(&pAdapt->SendWaitQueue[pVElan->NetworkConnection]); 
  1304.  
  1305.             MUX_RELEASE_ADAPT_WRITE_LOCK(pAdapt, &LockState);
  1306.  
  1307.             ASSERT(pEntry);
  1308.             Packet = CONTAINING_RECORD(pEntry, NDIS_PACKET, MiniportReserved);
  1309.  
  1310.             pSendReserved = MUX_RSVD_FROM_SEND_PACKET(Packet);
  1311.             pPacketVElan = pSendReserved->pVElan;
  1312.  
  1313.             if(pPacketVElan == pVElan)
  1314.             {
  1315.                 NdisMSendComplete(
  1316.                     pVElan->MiniportAdapterHandle,
  1317.                     Packet,
  1318.                     NDIS_STATUS_REQUEST_ABORTED);
  1319.             }
  1320.             MUX_ACQUIRE_ADAPT_WRITE_LOCK(pAdapt, &LockState);
  1321.         } 
  1322.  
  1323.         MUX_RELEASE_ADAPT_WRITE_LOCK(pAdapt, &LockState);
  1324.     
  1325.  
  1326.         DBGPRINT(MUX_LOUD, ("<== MPCancelSendPackets while Halting\n"));
  1327.     }
  1328.     */
  1329.  
  1330.     //
  1331.     // Wait for any outstanding sends or requests to complete.
  1332.     //
  1333.     while (pVElan->OutstandingSends)
  1334.     {
  1335.         DBGPRINT(MUX_INFO, ("MiniportHalt: VELAN %p has %d outstanding sends\n",
  1336.                             pVElan, pVElan->OutstandingSends));
  1337.         NdisMSleep(20000);
  1338.     }
  1339.  
  1340.     //
  1341.     // Wait for all outstanding indications to be completed and
  1342.     // any pended receive packets to be returned to us.
  1343.     //
  1344.     while (pVElan->OutstandingReceives)
  1345.     {
  1346.         DBGPRINT(MUX_INFO, ("MiniportHalt: VELAN %p has %d outstanding receives\n",
  1347.                             pVElan, pVElan->OutstandingReceives));
  1348.         NdisMSleep(20000);
  1349.     }
  1350.  
  1351.     //
  1352.     // Delete the ioctl interface that was created when the miniport
  1353.     // was created.
  1354.     //
  1355.     (VOID)PtDeregisterDevice();
  1356.  
  1357.     //
  1358.     // Unlink the VELAN from its parent ADAPT structure. This will
  1359.     // dereference the VELAN.
  1360.     //
  1361.     pVElan->MiniportAdapterHandle = NULL;
  1362.     PtUnlinkVElanFromAdapter(pVElan);
  1363.     
  1364.     DBGPRINT(MUX_LOUD, ("<== MiniportHalt: pVElan %p\n", pVElan));
  1365. }
  1366.  
  1367.  
  1368. NDIS_STATUS
  1369. MPForwardRequest(
  1370.     IN PVELAN                       pVElan,
  1371.     IN NDIS_REQUEST_TYPE            RequestType,
  1372.     IN NDIS_OID                     Oid,
  1373.     IN PVOID                        InformationBuffer,
  1374.     IN ULONG                        InformationBufferLength,
  1375.     OUT PULONG                      BytesReadOrWritten,
  1376.     OUT PULONG                      BytesNeeded
  1377.     )
  1378. /*++
  1379.  
  1380. Routine Description:
  1381.  
  1382.     Utility routine that forwards an NDIS request made on a VELAN to the
  1383.     lower binding. Since at most a single request can be pended on a VELAN,
  1384.     we use the pre-allocated request structure embedded in the VELAN struct.
  1385.  
  1386. Arguments:
  1387.  
  1388.  
  1389. Return Value:
  1390.  
  1391.     NDIS_STATUS_PENDING if a request was sent down.
  1392.  
  1393. --*/
  1394. {
  1395.     NDIS_STATUS         Status;
  1396.     PMUX_NDIS_REQUEST   pMuxNdisRequest = &pVElan->Request;
  1397.  
  1398.     //DBGPRINT(MUX_LOUD, ("MPForwardRequest: VELAN %p, OID %x\n", pVElan, Oid));
  1399.  
  1400.     do
  1401.     {
  1402.         MUX_INCR_PENDING_SENDS(pVElan);
  1403.  
  1404.         //
  1405.         // If the virtual miniport edge is at a low power
  1406.         // state, fail this request.
  1407.         //
  1408.         if (MUX_IS_LOW_POWER_STATE(pVElan->MPDevicePowerState))
  1409.         {
  1410.             MUX_DECR_PENDING_SENDS(pVElan);
  1411.             Status = NDIS_STATUS_ADAPTER_NOT_READY;
  1412.             break;
  1413.         }
  1414.  
  1415.         pVElan->BytesNeeded = BytesNeeded;
  1416.         pVElan->BytesReadOrWritten = BytesReadOrWritten;
  1417.         pMuxNdisRequest->pCallback = PtCompleteForwardedRequest;
  1418.  
  1419.         switch (RequestType)
  1420.         {
  1421.             case NdisRequestQueryInformation:
  1422.                 pMuxNdisRequest->Request.RequestType = NdisRequestQueryInformation;
  1423.                 pMuxNdisRequest->Request.DATA.QUERY_INFORMATION.Oid = Oid;
  1424.                 pMuxNdisRequest->Request.DATA.QUERY_INFORMATION.InformationBuffer = 
  1425.                                             InformationBuffer;
  1426.                 pMuxNdisRequest->Request.DATA.QUERY_INFORMATION.InformationBufferLength = 
  1427.                                             InformationBufferLength;
  1428.                 break;
  1429.  
  1430.             case NdisRequestSetInformation:
  1431.                 pMuxNdisRequest->Request.RequestType = NdisRequestSetInformation;
  1432.                 pMuxNdisRequest->Request.DATA.SET_INFORMATION.Oid = Oid;
  1433.                 pMuxNdisRequest->Request.DATA.SET_INFORMATION.InformationBuffer = 
  1434.                                             InformationBuffer;
  1435.                 pMuxNdisRequest->Request.DATA.SET_INFORMATION.InformationBufferLength = 
  1436.                                             InformationBufferLength;
  1437.                 break;
  1438.  
  1439.             default:
  1440.                 ASSERT(FALSE);
  1441.                 break;
  1442.         }
  1443.  
  1444.         //
  1445.         // If the lower binding has been notified of a low
  1446.         // power state, queue this request; it will be picked
  1447.         // up again when the lower binding returns to D0.
  1448.         //
  1449.         if (MUX_IS_LOW_POWER_STATE(pVElan->pAdapt->PtDevicePowerState))
  1450.         {
  1451.             DBGPRINT(MUX_INFO, ("ForwardRequest: VELAN %p, Adapt %p power"
  1452.                                 " state is %d, queueing OID %x\n",
  1453.                                 pVElan, pVElan->pAdapt,
  1454.                                 pVElan->pAdapt->PtDevicePowerState, Oid));
  1455.  
  1456.             pVElan->QueuedRequest = TRUE;
  1457.             Status = NDIS_STATUS_PENDING;
  1458.             break;
  1459.         }
  1460.  
  1461.         NdisRequest(&Status,
  1462.                     pVElan->BindingHandle,
  1463.                     &pMuxNdisRequest->Request);
  1464.  
  1465.         if (Status != NDIS_STATUS_PENDING)
  1466.         {
  1467.             PtRequestComplete(pVElan->pAdapt, &pMuxNdisRequest->Request, Status);
  1468.             Status = NDIS_STATUS_PENDING;
  1469.             break;
  1470.         }
  1471.     }
  1472.     while (FALSE);
  1473.  
  1474.     return (Status);
  1475. }
  1476.  
  1477. NDIS_STATUS
  1478. MPSetPacketFilter(
  1479.     IN PVELAN               pVElan,
  1480.     IN ULONG                PacketFilter
  1481.     )
  1482. /*++
  1483. Routine Description:
  1484.  
  1485.     This routine will set up the VELAN so that it accepts packets 
  1486.     that match the specified packet filter.  The only filter bits   
  1487.     that can truly be toggled are for broadcast and promiscuous.
  1488.  
  1489.     The MUX driver always sets the lower binding to promiscuous
  1490.     mode, but we do some optimization here to avoid turning on
  1491.     receives too soon. That is, we set the packet filter on the lower
  1492.     binding to a non-zero value iff at least one of the VELANs
  1493.     has a non-zero filter value.
  1494.     
  1495.     NOTE: setting the lower binding to promiscuous mode can
  1496.     impact CPU utilization. The only reason we set the lower binding
  1497.     to promiscuous mode in this sample is that we need to be able
  1498.     to receive unicast frames directed to MAC address(es) that do not
  1499.     match the local adapter's MAC address. If VELAN MAC addresses
  1500.     are set to be equal to that of the adapter below, it is sufficient
  1501.     to set the lower packet filter to the bitwise OR'ed value of
  1502.     packet filter settings on all VELANs.
  1503.                                     
  1504.  
  1505. Arguments:
  1506.  
  1507.     pVElan - pointer to VELAN
  1508.     PacketFilter - the new packet filter 
  1509.     
  1510. Return Value:
  1511.  
  1512.     NDIS_STATUS_SUCCESS
  1513.     NDIS_STATUS_NOT_SUPPORTED
  1514.     
  1515. --*/
  1516. {
  1517.     NDIS_STATUS     Status = NDIS_STATUS_SUCCESS;
  1518.     PADAPT          pAdapt;
  1519.     PVELAN          pTmpVElan;
  1520.     PLIST_ENTRY     p;
  1521.     ULONG           AdapterFilter;
  1522.     BOOLEAN         bSendUpdate = FALSE;
  1523.     LOCK_STATE      LockState;
  1524.  
  1525.     DBGPRINT(MUX_LOUD, ("=> SetPacketFilter VELAN %p, Filter %x\n", pVElan, PacketFilter));
  1526.     
  1527.     do
  1528.     {
  1529.         //
  1530.         // Any bits not supported?
  1531.         //
  1532.         if (PacketFilter & ~VELAN_SUPPORTED_FILTERS)
  1533.         {
  1534.             Status = NDIS_STATUS_NOT_SUPPORTED;
  1535.             break;
  1536.         }
  1537.     
  1538.         AdapterFilter = 0;
  1539.         pAdapt = pVElan->pAdapt;
  1540.  
  1541.         //
  1542.         // Grab a Write lock on the adapter so that this operation
  1543.         // does not interfere with any receives that might be accessing
  1544.         // filter information.
  1545.         //
  1546.         MUX_ACQUIRE_ADAPT_WRITE_LOCK(pAdapt, &LockState);
  1547.  
  1548.         //
  1549.         // Save the new packet filter value
  1550.         //
  1551.         pVElan->PacketFilter = PacketFilter;
  1552.  
  1553.         //
  1554.         // Compute the new combined filter for all VELANs on this
  1555.         // adapter.
  1556.         //
  1557.         for (p = pAdapt->VElanList.Flink;
  1558.              p != &pAdapt->VElanList;
  1559.              p = p->Flink)
  1560.         {
  1561.             pTmpVElan = CONTAINING_RECORD(p, VELAN, Link);
  1562.             AdapterFilter |= pTmpVElan->PacketFilter;
  1563.         }
  1564.  
  1565.         //
  1566.         // If all VELANs have packet filters set to 0, turn off
  1567.         // receives on the lower adapter, if not already done.
  1568.         //
  1569.         if ((AdapterFilter == 0) && (pAdapt->PacketFilter != 0))
  1570.         {
  1571.             bSendUpdate = TRUE;
  1572.             pAdapt->PacketFilter = 0;
  1573.         }
  1574.         else
  1575.         //
  1576.         // If receives had been turned off on the lower adapter, and
  1577.         // the new filter is non-zero, turn on the lower adapter.
  1578.         // We set the adapter to promiscuous mode in this sample
  1579.         // so that we are able to receive packets directed to
  1580.         // any of the VELAN MAC addresses.
  1581.         //
  1582.         if ((AdapterFilter != 0) && (pAdapt->PacketFilter == 0))
  1583.         {
  1584.             bSendUpdate = TRUE;
  1585.             //pAdapt->PacketFilter = MUX_ADAPTER_PACKET_FILTER;
  1586.             pAdapt->PacketFilter = NDIS_PACKET_TYPE_DIRECTED 
  1587.             | NDIS_PACKET_TYPE_BROADCAST;
  1588.         }
  1589.         
  1590.         MUX_RELEASE_ADAPT_WRITE_LOCK(pAdapt, &LockState);
  1591.  
  1592.         if (bSendUpdate)
  1593.         {
  1594.             PtRequestAdapterAsync(
  1595.                 pAdapt,
  1596.                 NdisRequestSetInformation,
  1597.                 OID_GEN_CURRENT_PACKET_FILTER,
  1598.                 &pAdapt->PacketFilter,
  1599.                 sizeof(pAdapt->PacketFilter),
  1600.                 PtDiscardCompletedRequest);
  1601.         }
  1602.  
  1603.         break;
  1604.     }
  1605.     while (FALSE);
  1606.  
  1607.     DBGPRINT(MUX_INFO, ("<= SetPacketFilter VELAN %p, Status %x\n", pVElan, Status));
  1608.     
  1609.     return(Status);
  1610. }
  1611.  
  1612.  
  1613. NDIS_STATUS
  1614. MPSetMulticastList(
  1615.     IN PVELAN                   pVElan,
  1616.     IN PVOID                    InformationBuffer,
  1617.     IN ULONG                    InformationBufferLength,
  1618.     OUT PULONG                  pBytesRead,
  1619.     OUT PULONG                  pBytesNeeded
  1620.     )
  1621. /*++
  1622.  
  1623. Routine Description:
  1624.  
  1625.     Set the multicast list on the specified VELAN miniport.
  1626.     We simply validate all information and copy in the multicast
  1627.     list.
  1628.  
  1629.     We don't forward the multicast list information down since
  1630.     we set the lower binding to promisc. mode.
  1631.  
  1632. Arguments:
  1633.  
  1634.     pVElan - VELAN on which to set the multicast list
  1635.     InformationBuffer - pointer to new multicast list
  1636.     InformationBufferLength - length in bytes of above list
  1637.     pBytesRead - place to return # of bytes read from the above
  1638.     pBytesNeeded - place to return expected min # of bytes
  1639.  
  1640. Return Value:
  1641.  
  1642.     NDIS_STATUS
  1643.  
  1644. --*/
  1645. {
  1646.     NDIS_STATUS         Status;
  1647.     PADAPT              pAdapt;
  1648.     LOCK_STATE          LockState;
  1649.  
  1650.     //
  1651.     // Initialize.
  1652.     //
  1653.     *pBytesNeeded = sizeof(MUX_MAC_ADDRESS);
  1654.     *pBytesRead = 0;
  1655.     Status = NDIS_STATUS_SUCCESS;
  1656.  
  1657.     do
  1658.     {
  1659.         if (InformationBufferLength % sizeof(MUX_MAC_ADDRESS))
  1660.         {
  1661.             Status = NDIS_STATUS_INVALID_LENGTH;
  1662.             break;
  1663.         }
  1664.  
  1665.         if (InformationBufferLength > (VELAN_MAX_MCAST_LIST * sizeof(MUX_MAC_ADDRESS)))
  1666.         {
  1667.             Status = NDIS_STATUS_MULTICAST_FULL;
  1668.             *pBytesNeeded = VELAN_MAX_MCAST_LIST * sizeof(MUX_MAC_ADDRESS);
  1669.             break;
  1670.         }
  1671.  
  1672.         pAdapt = pVElan->pAdapt;
  1673.  
  1674.         //
  1675.         // Grab a Write lock on the adapter so that this operation
  1676.         // does not interfere with any receives that might be accessing
  1677.         // multicast list information.
  1678.         //
  1679.         MUX_ACQUIRE_ADAPT_WRITE_LOCK(pAdapt, &LockState);
  1680.  
  1681.         NdisZeroMemory(&pVElan->McastAddrs[0],
  1682.                        VELAN_MAX_MCAST_LIST * sizeof(MUX_MAC_ADDRESS));
  1683.         
  1684.         NdisMoveMemory(&pVElan->McastAddrs[0],
  1685.                        InformationBuffer,
  1686.                        InformationBufferLength);
  1687.         
  1688.         pVElan->McastAddrCount = InformationBufferLength / sizeof(MUX_MAC_ADDRESS);
  1689.         
  1690.         MUX_RELEASE_ADAPT_WRITE_LOCK(pAdapt, &LockState);
  1691.     }
  1692.     while (FALSE);
  1693.  
  1694.     return (Status);
  1695. }
  1696.  
  1697.  
  1698. //
  1699. // Careful! Uses static storage for string. Used to simplify DbgPrints
  1700. // of MAC addresses.
  1701. //
  1702. PUCHAR
  1703. MacAddrToString(PVOID In)
  1704. {
  1705.     static UCHAR String[20];
  1706.     static PUCHAR HexChars = "0123456789abcdef";
  1707.     PUCHAR EthAddr = (PUCHAR) In;
  1708.     UINT i;
  1709.     PUCHAR s;
  1710.     
  1711.     for (i = 0, s = String; i < 6; i++, EthAddr++)
  1712.     {
  1713.         *s++ = HexChars[(*EthAddr) >> 4];
  1714.         *s++ = HexChars[(*EthAddr) & 0xf];
  1715.     }
  1716.     *s = '\0';
  1717.     return String; 
  1718. }
  1719.  
  1720.  
  1721. VOID
  1722. MPGenerateMacAddr(
  1723.     PVELAN                    pVElan
  1724. )
  1725. /*++
  1726.  
  1727. Routine Description:
  1728.  
  1729.     Generates a "virtual" MAC address for a VELAN.
  1730.     NOTE: this is only a sample implementation of selecting
  1731.     a MAC address for the VELAN. Other implementations are possible,
  1732.     including using the MAC address of the underlying adapter as
  1733.     the MAC address of the VELAN.
  1734.     
  1735. Arguments:
  1736.  
  1737.     pVElan  - Pointer to velan structure
  1738.  
  1739. Return Value:
  1740.  
  1741.     None
  1742.  
  1743. --*/
  1744. {
  1745.  
  1746.     pVElan->PermanentAddress[0] = 
  1747.         0x02 | (((UCHAR)pVElan->VElanNumber & 0x3f) << 2);
  1748.     pVElan->PermanentAddress[1] = 
  1749.         0x02 | (((UCHAR)pVElan->VElanNumber & 0x3f) << 3);
  1750.  
  1751.     ETH_COPY_NETWORK_ADDRESS(
  1752.             pVElan->CurrentAddress,
  1753.             pVElan->PermanentAddress);
  1754.     
  1755.     DBGPRINT(MUX_LOUD, ("%d CurrentAddress %s\n",
  1756.         pVElan->VElanNumber, MacAddrToString(&pVElan->CurrentAddress)));
  1757.     DBGPRINT(MUX_LOUD, ("%d PermanentAddress  %s\n",
  1758.         pVElan->VElanNumber, MacAddrToString(&pVElan->PermanentAddress)));
  1759.  
  1760. }
  1761.  
  1762. VOID
  1763. MPCancelPacketsFromVElan(
  1764.     IN PVELAN              pVElan
  1765.     )
  1766. /*++
  1767.  
  1768. Routine Description:
  1769.  
  1770.     The miniport entry point to handle cancellation of all send packets
  1771.     that are sent from the particular VElan. If we have queued any packets that match
  1772.     this, then we should dequeue them and call NdisMSendComplete for all
  1773.     such packets, with a status of NDIS_STATUS_REQUEST_ABORTED.
  1774.  
  1775.     We should also call NdisCancelSendPackets in turn, on each lower binding
  1776.     that this adapter corresponds to. This is to let miniports below cancel
  1777.     any matching packets.
  1778.  
  1779. Arguments:
  1780.  
  1781.     pVElan:  The VElan that is halting
  1782.  
  1783. Return Value:
  1784.  
  1785.     None
  1786.  
  1787. --*/
  1788. {
  1789.     PADAPT pAdapt = pVElan->pAdapt;
  1790.     PQUEUE_ENTRY    pEntry, pPrevEntry, pNextEntry;
  1791.     PNDIS_PACKET    Packet;
  1792.     LOCK_STATE      LockState;
  1793.  
  1794.     DBGPRINT(MUX_LOUD, ("==> MPCancelSendPackets\n"));
  1795.  
  1796.     pPrevEntry = NULL;
  1797.  
  1798.     MUX_ACQUIRE_ADAPT_WRITE_LOCK(pAdapt, &LockState);
  1799.  
  1800.     //
  1801.     // Walk through the send wait queue and complete the sends with matching Id
  1802.     //
  1803.     pEntry = pAdapt->SendWaitQueue[pVElan->NetworkConnection].Head;                        
  1804.  
  1805.     while (pEntry)
  1806.     {
  1807.         PVELAN           pPacketVElan;
  1808.         PMUX_SEND_RSVD   pSendReserved;
  1809.  
  1810.         Packet = CONTAINING_RECORD(pEntry, NDIS_PACKET, MiniportReserved);
  1811.  
  1812.         pSendReserved = MUX_RSVD_FROM_SEND_PACKET(Packet);
  1813.         pPacketVElan = pSendReserved->pVElan;
  1814.  
  1815.         if (pPacketVElan == pVElan)
  1816.         {
  1817.             pAdapt->nWaitSend[pVElan->NetworkConnection]--;
  1818.         
  1819.             //
  1820.             // This packet has the right CancelId
  1821.             //
  1822.             pNextEntry = pEntry->Next;
  1823.  
  1824.             if (pPrevEntry == NULL)
  1825.             {
  1826.                 pAdapt->SendWaitQueue[pVElan->NetworkConnection].Head = pNextEntry;
  1827.                 if (pNextEntry == NULL)
  1828.                 {
  1829.                     pAdapt->SendWaitQueue[pVElan->NetworkConnection].Tail = NULL;
  1830.                 }
  1831.             }
  1832.             else
  1833.             {
  1834.                 pPrevEntry->Next = pNextEntry;
  1835.                 if (pNextEntry == NULL)
  1836.                 {
  1837.                     pAdapt->SendWaitQueue[pVElan->NetworkConnection].Tail = pPrevEntry;
  1838.                 }
  1839.             }
  1840.  
  1841.             pEntry = pEntry->Next;
  1842.             
  1843.             // Put this packet on SendCancelQueue
  1844.             InsertTailQueue(&pAdapt->SendCancelQueue, MP_GET_PACKET_MR(Packet));
  1845.             pAdapt->nCancelSend++;
  1846.         }
  1847.         else
  1848.         {
  1849.             // This packet doesn't have the right CancelId
  1850.             pPrevEntry = pEntry;
  1851.             pEntry = pEntry->Next;
  1852.         }
  1853.     }
  1854.  
  1855.     DBGPRINT(MUX_LOUD, ("MPCancelSendPacketsFromVElan:  Put stuff in Cancel Queue successful\n"));
  1856.     //
  1857.     // Get the packets from SendCancelQueue and complete them if any
  1858.     //
  1859.     while (!IsQueueEmpty(&pAdapt->SendCancelQueue))
  1860.     {
  1861.         pEntry = RemoveHeadQueue(&pAdapt->SendCancelQueue); 
  1862.         pAdapt->nCancelSend--;
  1863.  
  1864.         MUX_RELEASE_ADAPT_WRITE_LOCK(pAdapt, &LockState);
  1865.  
  1866.         ASSERT(pEntry);
  1867.         Packet = CONTAINING_RECORD(pEntry, NDIS_PACKET, MiniportReserved);
  1868.  
  1869.         NdisMSendComplete(
  1870.             pVElan->MiniportAdapterHandle,
  1871.             Packet,
  1872.             NDIS_STATUS_REQUEST_ABORTED);
  1873.         
  1874.         MUX_ACQUIRE_ADAPT_WRITE_LOCK(pAdapt, &LockState);
  1875.     } 
  1876.  
  1877.     MUX_RELEASE_ADAPT_WRITE_LOCK(pAdapt, &LockState);
  1878.  
  1879.     DBGPRINT(MUX_LOUD, ("<== MPCancelSendPackets\n"));
  1880.  
  1881.     //
  1882.     // If we queue packets on our VELAN/adapter structure, this would be 
  1883.     // the place to acquire a spinlock to it, unlink any packets whose
  1884.     // Id matches CancelId, release the spinlock and call NdisMSendComplete
  1885.     // with NDIS_STATUS_REQUEST_ABORTED for all unlinked packets.
  1886.     //
  1887.  
  1888.     //
  1889.     // Next, pass this down so that we let the miniport(s) below cancel
  1890.     // any packets that they might have queued.
  1891.     //
  1892.     NdisCancelSendPackets(pVElan->pAdapt->BindingHandle, pVElan);
  1893.  
  1894.     return;
  1895. }
  1896.  
  1897.  
  1898. #ifdef NDIS51_MINIPORT
  1899.  
  1900. VOID
  1901. MPCancelSendPackets(
  1902.     IN NDIS_HANDLE              MiniportAdapterContext,
  1903.     IN PVOID                    CancelId
  1904.     )
  1905. /*++
  1906.  
  1907. Routine Description:
  1908.  
  1909.     The miniport entry point to handle cancellation of all send packets
  1910.     that match the given CancelId. If we have queued any packets that match
  1911.     this, then we should dequeue them and call NdisMSendComplete for all
  1912.     such packets, with a status of NDIS_STATUS_REQUEST_ABORTED.
  1913.  
  1914.     We should also call NdisCancelSendPackets in turn, on each lower binding
  1915.     that this adapter corresponds to. This is to let miniports below cancel
  1916.     any matching packets.
  1917.  
  1918. Arguments:
  1919.  
  1920.     MiniportAdapterContext    - pointer to VELAN structure
  1921.     CancelId    - ID of packets to be cancelled.
  1922.  
  1923. Return Value:
  1924.  
  1925.     None
  1926.  
  1927. --*/
  1928. {
  1929.     PVELAN  pVElan = (PVELAN)MiniportAdapterContext;
  1930.     PADAPT pAdapt = pVElan->pAdapt;
  1931.     PQUEUE_ENTRY    pEntry, pPrevEntry, pNextEntry;
  1932.     PNDIS_PACKET    Packet;
  1933.     PVOID           PacketId;
  1934.     LOCK_STATE      LockState;
  1935.  
  1936.     DBGPRINT(MUX_LOUD, ("==> MPCancelSendPackets\n"));
  1937.  
  1938.     pPrevEntry = NULL;
  1939.  
  1940.     MUX_ACQUIRE_ADAPT_WRITE_LOCK(pAdapt, &LockState);
  1941.  
  1942.     //
  1943.     // Walk through the send wait queue and complete the sends with matching Id
  1944.     //
  1945.     pEntry = pAdapt->SendWaitQueue[pVElan->NetworkConnection].Head;                        
  1946.  
  1947.     while (pEntry)
  1948.     {
  1949.         Packet = CONTAINING_RECORD(pEntry, NDIS_PACKET, MiniportReserved);
  1950.         DBGPRINT(MUX_LOUD, ("In While loop of Cancel PAckets\n"));
  1951.  
  1952.         PacketId = NdisGetPacketCancelId(Packet);
  1953.         if (PacketId == CancelId)
  1954.         {
  1955.             pAdapt->nWaitSend[pVElan->NetworkConnection]--;
  1956.         
  1957.             //
  1958.             // This packet has the right CancelId
  1959.             //
  1960.             pNextEntry = pEntry->Next;
  1961.  
  1962.             if (pPrevEntry == NULL)
  1963.             {
  1964.                 pAdapt->SendWaitQueue[pVElan->NetworkConnection].Head = pNextEntry;
  1965.                 if (pNextEntry == NULL)
  1966.                 {
  1967.                     pAdapt->SendWaitQueue[pVElan->NetworkConnection].Tail = NULL;
  1968.                 }
  1969.             }
  1970.             else
  1971.             {
  1972.                 pPrevEntry->Next = pNextEntry;
  1973.                 if (pNextEntry == NULL)
  1974.                 {
  1975.                     pAdapt->SendWaitQueue[pVElan->NetworkConnection].Tail = pPrevEntry;
  1976.                 }
  1977.             }
  1978.  
  1979.             pEntry = pEntry->Next;
  1980.             
  1981.             // Put this packet on SendCancelQueue
  1982.             InsertTailQueue(&pAdapt->SendCancelQueue, MP_GET_PACKET_MR(Packet));
  1983.             pAdapt->nCancelSend++;
  1984.         }
  1985.         else
  1986.         {
  1987.             // This packet doesn't have the right CancelId
  1988.             pPrevEntry = pEntry;
  1989.             pEntry = pEntry->Next;
  1990.         }
  1991.     }
  1992.  
  1993.     //
  1994.     // Get the packets from SendCancelQueue and complete them if any
  1995.     //
  1996.     while (!IsQueueEmpty(&pAdapt->SendCancelQueue))
  1997.     {
  1998.         pEntry = RemoveHeadQueue(&pAdapt->SendCancelQueue); 
  1999.  
  2000.         MUX_RELEASE_ADAPT_WRITE_LOCK(pAdapt, &LockState);
  2001.  
  2002.         ASSERT(pEntry);
  2003.         Packet = CONTAINING_RECORD(pEntry, NDIS_PACKET, MiniportReserved);
  2004.  
  2005.         NdisMSendComplete(
  2006.             pVElan->MiniportAdapterHandle,
  2007.             Packet,
  2008.             NDIS_STATUS_REQUEST_ABORTED);
  2009.         
  2010.         MUX_ACQUIRE_ADAPT_WRITE_LOCK(pAdapt, &LockState);
  2011.     } 
  2012.  
  2013.     MUX_RELEASE_ADAPT_WRITE_LOCK(pAdapt, &LockState);
  2014.  
  2015.  
  2016.     //
  2017.     // If we queue packets on our VELAN/adapter structure, this would be 
  2018.     // the place to acquire a spinlock to it, unlink any packets whose
  2019.     // Id matches CancelId, release the spinlock and call NdisMSendComplete
  2020.     // with NDIS_STATUS_REQUEST_ABORTED for all unlinked packets.
  2021.     //
  2022.  
  2023.     //
  2024.     // Next, pass this down so that we let the miniport(s) below cancel
  2025.     // any packets that they might have queued.
  2026.     //
  2027.     NdisCancelSendPackets(pVElan->pAdapt->BindingHandle, CancelId);
  2028.  
  2029.     DBGPRINT(MUX_LOUD, ("<== MPCancelSendPackets\n"));
  2030.  
  2031.     return;
  2032. }
  2033.  
  2034. VOID
  2035. MPDevicePnPEvent(
  2036.     IN NDIS_HANDLE              MiniportAdapterContext,
  2037.     IN NDIS_DEVICE_PNP_EVENT    DevicePnPEvent,
  2038.     IN PVOID                    InformationBuffer,
  2039.     IN ULONG                    InformationBufferLength
  2040.     )
  2041. /*++
  2042.  
  2043. Routine Description:
  2044.  
  2045.     This handler is called to notify us of PnP events directed to
  2046.     our miniport device object.
  2047.  
  2048. Arguments:
  2049.  
  2050.     MiniportAdapterContext - pointer to VELAN structure
  2051.     DevicePnPEvent - the event
  2052.     InformationBuffer - Points to additional event-specific information
  2053.     InformationBufferLength - length of above
  2054.  
  2055. Return Value:
  2056.  
  2057.     None
  2058. --*/
  2059. {
  2060.     // TBD - add code/comments about processing this.
  2061.  
  2062.     return;
  2063. }
  2064.  
  2065.  
  2066. VOID
  2067. MPAdapterShutdown(
  2068.     IN NDIS_HANDLE              MiniportAdapterContext
  2069.     )
  2070. /*++
  2071.  
  2072. Routine Description:
  2073.  
  2074.     This handler is called to notify us of an impending system shutdown.
  2075.     Since this is not a hardware driver, there isn't anything specific
  2076.     we need to do about this.
  2077.  
  2078. Arguments:
  2079.  
  2080.     MiniportAdapterContext  - pointer to VELAN structure
  2081.  
  2082. Return Value:
  2083.  
  2084.     None
  2085. --*/
  2086. {
  2087.     return;
  2088. }
  2089.  
  2090.  
  2091. #endif // NDIS51_MINIPORT
  2092.  
  2093. VOID
  2094. MPUnload(
  2095.     IN    PDRIVER_OBJECT        DriverObject
  2096.     )
  2097. {
  2098.     NDIS_STATUS Status;
  2099.     
  2100.     DBGPRINT(MUX_LOUD, ("==> MPUnload: DriverObj %p\n", DriverObject));  
  2101.     NdisDeregisterProtocol(&Status, ProtHandle);
  2102.     DBGPRINT(MUX_LOUD, ("<== MPUnload \n"));    
  2103. }
  2104.  
  2105. #if IEEE_VLAN_SUPPORT
  2106. NDIS_STATUS
  2107. MPHandleSendTagging(
  2108.     IN  PVELAN              pVElan,
  2109.     IN  PNDIS_PACKET        Packet,
  2110.     IN  OUT PNDIS_PACKET    MyPacket
  2111.     )
  2112. /*++
  2113.  
  2114. Routine Description:
  2115.  
  2116.     This function is called when the driver supports IEEE802Q tagging.
  2117.     It checks the packet to be sent on a VELAN and inserts a tag header
  2118.     if necessary.
  2119.  
  2120. Arguments:
  2121.  
  2122.     PVELAN  - pointer to VELAN structure
  2123.     Packet - pointer to original packet
  2124.     MyPacket - pointer to the new allocated packet
  2125.     
  2126. Return Value:
  2127.  
  2128.     NDIS_STATUS_SUCCESS if the packet was successfully parsed
  2129.     and hence should be passed down to the lower driver. NDIS_STATUS_XXX
  2130.     otherwise.
  2131.     
  2132. --*/
  2133. {
  2134.     NDIS_PACKET_8021Q_INFO      NdisPacket8021qInfo;
  2135.     PVOID                       pEthTagBuffer;
  2136.     PNDIS_BUFFER                pNdisBuffer;
  2137.     PVOID                       pVa;
  2138.     ULONG                       BufferLength;
  2139.     PNDIS_BUFFER                pFirstBuffer;
  2140.     PNDIS_BUFFER                pSecondBuffer;
  2141.     NDIS_STATUS                 Status;
  2142.     NDIS_STATUS                 Status2;
  2143.     PVOID                       pStartVa;
  2144.     BOOLEAN                     IsFirstVa;
  2145.     PVLAN_TAG_HEADER            pTagHeader;
  2146.     PUSHORT                     TypeLength;
  2147.     PUSHORT                     pTpid;
  2148.     ULONG                       BytesToSkip;
  2149.     PUSHORT                     pTypeLength;
  2150.     //
  2151.     // Add tag header here
  2152.     //
  2153.     Status = NDIS_STATUS_SUCCESS;
  2154.     
  2155.     NdisPacket8021qInfo.Value =  NDIS_PER_PACKET_INFO_FROM_PACKET(
  2156.                                                             MyPacket,         
  2157.                                                             Ieee8021QInfo);
  2158.             
  2159.     do
  2160.     {
  2161.         //
  2162.         // Insert a tag only if we have a configured VLAN ID
  2163.         // or there is non-zero VLAN/priority information to be
  2164.         // sent with the packet.
  2165.         //
  2166.         if ((pVElan->VlanId == 0) && (NdisPacket8021qInfo.Value == 0))
  2167.         {
  2168.             //
  2169.             // No tag header needed.
  2170.             //
  2171.             break;
  2172.         }
  2173.             
  2174.         //
  2175.         // We don't support E-RIF
  2176.         // 
  2177.         if (NdisPacket8021qInfo.TagHeader.CanonicalFormatId)
  2178.         {
  2179.             //
  2180.             // skip the packet, return NDIS_STATUS_FAILURE
  2181.             //
  2182.             Status = NDIS_STATUS_INVALID_PACKET;
  2183.             break;
  2184.         }
  2185.  
  2186.         //
  2187.         // The Vlan Id must be the same as the configured VLAN ID if it is non-zero
  2188.         // 
  2189.         if ((NdisPacket8021qInfo.TagHeader.VlanId)
  2190.                 && (pVElan->VlanId)
  2191.                 && (NdisPacket8021qInfo.TagHeader.VlanId != pVElan->VlanId))
  2192.         {
  2193.             Status = NDIS_STATUS_INVALID_PACKET;
  2194.             break;
  2195.         }
  2196.                 
  2197.         //
  2198.         // Find the virtual address after the Ethernet Header
  2199.         //
  2200.         BytesToSkip = ETH_HEADER_SIZE;
  2201.         pNdisBuffer = Packet->Private.Head;
  2202.         IsFirstVa = TRUE;
  2203.             
  2204.         //
  2205.         // Assume the Ethernet Header is in the first buffer of the packet.
  2206.         // The following loop is to find the start address of the data after
  2207.         // the ethernet header. This may be either in the first NDIS buffer
  2208.         // or in the second.
  2209.         // 
  2210.         while (TRUE)
  2211.         {
  2212. #ifdef NDIS51_MINIPORT
  2213.             NdisQueryBufferSafe(pNdisBuffer, &pVa, &BufferLength, NormalPagePriority);
  2214. #else
  2215.             NdisQueryBuffer(pNdisBuffer, &pVa, &BufferLength);
  2216. #endif
  2217.             //
  2218.             // The query can fail if the system is low on resources.
  2219.             // 
  2220.             if (pVa == NULL)
  2221.             {
  2222.                 break;
  2223.             }
  2224.  
  2225.             //
  2226.             // Remember the start of the ethernet header for later.
  2227.             // 
  2228.             if (IsFirstVa)
  2229.             {
  2230.                 pStartVa = pVa;
  2231.                 IsFirstVa = FALSE;
  2232.             }
  2233.  
  2234.             //
  2235.             // Have we gone far enough into the packet?
  2236.             // 
  2237.             if (BytesToSkip == 0)
  2238.             {
  2239.                 break;
  2240.             }
  2241.  
  2242.             //
  2243.             // Does the current buffer contain bytes past the Ethernet
  2244.             // header? If so, stop.
  2245.             // 
  2246.             if (BufferLength > BytesToSkip)
  2247.             {
  2248.                 pVa = (PVOID)((PUCHAR)pVa + BytesToSkip);
  2249.                 BufferLength -= BytesToSkip;
  2250.                 break;
  2251.             }
  2252.  
  2253.             //
  2254.             // We haven't gone past the Ethernet header yet, so go
  2255.             // to the next buffer.
  2256.             //
  2257.             BytesToSkip -= BufferLength;
  2258.             pNdisBuffer = NDIS_BUFFER_LINKAGE(pNdisBuffer);
  2259.         }
  2260.  
  2261.         if (pVa == NULL)
  2262.         {
  2263.             Status = NDIS_STATUS_RESOURCES;
  2264.             break;
  2265.         }
  2266.  
  2267.         //
  2268.         // Allocate space for the Ethernet + VLAN tag header.
  2269.         // 
  2270.         pEthTagBuffer = NdisAllocateFromNPagedLookasideList(&pVElan->TagLookaside);
  2271.             
  2272.         //
  2273.         // Memory allocation failed, can't send out the packet
  2274.         // 
  2275.         if (pEthTagBuffer == NULL)
  2276.         {
  2277.             Status = NDIS_STATUS_RESOURCES;
  2278.             break;
  2279.         }
  2280.  
  2281.         //
  2282.         // Allocate NDIS buffers for the Ethernet + VLAN tag header and
  2283.         // the data that follows these.
  2284.         //
  2285.         NdisAllocateBuffer(&Status,
  2286.                             &pSecondBuffer,
  2287.                             pVElan->BufferPoolHandle,
  2288.                             pVa,    // byte following the Eth+tag headers
  2289.                             BufferLength);
  2290.         
  2291.         NdisAllocateBuffer(&Status2,
  2292.                             &pFirstBuffer,
  2293.                             pVElan->BufferPoolHandle,
  2294.                             pEthTagBuffer,
  2295.                             ETH_HEADER_SIZE + VLAN_TAG_HEADER_SIZE);
  2296.  
  2297.         if (Status != NDIS_STATUS_SUCCESS || Status2 != NDIS_STATUS_SUCCESS)
  2298.         {
  2299.             //
  2300.             // One of the buffer allocations failed.
  2301.             //
  2302.             if (Status == NDIS_STATUS_SUCCESS)
  2303.             {
  2304.                 NdisFreeBuffer(pSecondBuffer);
  2305.             }   
  2306.         
  2307.             if (Status2 == NDIS_STATUS_SUCCESS)
  2308.             {
  2309.                 NdisFreeBuffer(pFirstBuffer);
  2310.             }
  2311.  
  2312.             NdisFreeToNPagedLookasideList(&pVElan->TagLookaside, pEthTagBuffer);
  2313.         
  2314.             Status = NDIS_STATUS_RESOURCES;
  2315.             break;
  2316.         }
  2317.  
  2318.         //
  2319.         // All allocations were successful, now prepare the packet
  2320.         // to be sent down to the lower driver.
  2321.         //
  2322.         MyPacket->Private.Head = NDIS_BUFFER_LINKAGE(pNdisBuffer);
  2323.         NdisChainBufferAtFront(MyPacket, pSecondBuffer)
  2324.         NdisChainBufferAtFront(MyPacket, pFirstBuffer)
  2325.         
  2326.         //
  2327.         // Prepare the Ethernet and tag headers.
  2328.         //
  2329.         NdisMoveMemory(pEthTagBuffer, pStartVa, 2 * ETH_LENGTH_OF_ADDRESS);
  2330.         pTpid = (PUSHORT)((PUCHAR)pEthTagBuffer + 2 * ETH_LENGTH_OF_ADDRESS);
  2331.         *pTpid = TPID;
  2332.         pTagHeader = (PVLAN_TAG_HEADER)(pTpid + 1);
  2333.     
  2334.         //
  2335.         // Write Ieee 802Q info to packet frame
  2336.         // 
  2337.         INITIALIZE_TAG_HEADER_TO_ZERO(pTagHeader);
  2338.         if (NdisPacket8021qInfo.Value)
  2339.         {
  2340.             SET_USER_PRIORITY_TO_TAG(pTagHeader, NdisPacket8021qInfo.TagHeader.UserPriority);
  2341.         }
  2342.         else
  2343.         {
  2344.             SET_USER_PRIORITY_TO_TAG(pTagHeader, 0);
  2345.         }
  2346.  
  2347.         SET_CANONICAL_FORMAT_ID_TO_TAG (pTagHeader, 0);
  2348.             
  2349.         if (NdisPacket8021qInfo.TagHeader.VlanId)
  2350.         {
  2351.             SET_VLAN_ID_TO_TAG (pTagHeader, NdisPacket8021qInfo.TagHeader.VlanId);
  2352.         }
  2353.         else
  2354.         {
  2355.             SET_VLAN_ID_TO_TAG (pTagHeader, pVElan->VlanId);
  2356.         }   
  2357.  
  2358.         pTypeLength = (PUSHORT)((PUCHAR)pTagHeader + sizeof(pTagHeader->TagInfo));
  2359.         *pTypeLength = *((PUSHORT)((PUCHAR)pStartVa + 2 * ETH_LENGTH_OF_ADDRESS));
  2360.  
  2361.         //
  2362.         // Clear the Ieee8021QInfo field in packet being sent down
  2363.         // to prevent double tag insertion!
  2364.         // 
  2365.         NDIS_PER_PACKET_INFO_FROM_PACKET(MyPacket, Ieee8021QInfo) = 0;
  2366.         break;
  2367.     }
  2368.     while (FALSE);
  2369.     
  2370.     return Status;
  2371. }
  2372.     
  2373. #endif // IEEE_VLAN_SUPPORT 
  2374.                 
  2375.  
  2376.