Beispiel #1
0
// IRP_MJ_DEVICE_CONTROL callback.
NTSTATUS
TapDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)

/*++

Routine Description:

    This routine is called by the I/O system to perform a device I/O
    control function.

Arguments:

    DeviceObject - a pointer to the object that represents the device
        that I/O is to be done on.

    Irp - a pointer to the I/O Request Packet for this request.

Return Value:

    NT status code

--*/

{
  NTSTATUS ntStatus = STATUS_SUCCESS;  // Assume success
  PIO_STACK_LOCATION irpSp;            // Pointer to current stack location
  PTAP_ADAPTER_CONTEXT adapter = NULL;
  ULONG inBufLength;    // Input buffer length
  ULONG outBufLength;   // Output buffer length
  PCHAR inBuf, outBuf;  // pointer to Input and output buffer
  PMDL mdl = NULL;
  PCHAR buffer = NULL;

  PAGED_CODE();

  irpSp = IoGetCurrentIrpStackLocation(Irp);

  //
  // Fetch adapter context for this device.
  // --------------------------------------
  // Adapter pointer was stashed in FsContext when handle was opened.
  //
  adapter = (PTAP_ADAPTER_CONTEXT)(irpSp->FileObject)->FsContext;

  ASSERT(adapter);

  inBufLength = irpSp->Parameters.DeviceIoControl.InputBufferLength;
  outBufLength = irpSp->Parameters.DeviceIoControl.OutputBufferLength;

  if (!inBufLength || !outBufLength) {
    ntStatus = STATUS_INVALID_PARAMETER;
    goto End;
  }

  //
  // Determine which I/O control code was specified.
  //
  switch (irpSp->Parameters.DeviceIoControl.IoControlCode) {
    case TAP_WIN_IOCTL_GET_MAC: {
      if (outBufLength >= MACADDR_SIZE) {
        ETH_COPY_NETWORK_ADDRESS(Irp->AssociatedIrp.SystemBuffer, adapter->CurrentAddress);

        Irp->IoStatus.Information = MACADDR_SIZE;
      } else {
        NOTE_ERROR();
        Irp->IoStatus.Status = ntStatus = STATUS_BUFFER_TOO_SMALL;
      }
    } break;

    case TAP_WIN_IOCTL_GET_VERSION: {
      const ULONG size = sizeof(ULONG) * 3;

      if (outBufLength >= size) {
        ((PULONG)(Irp->AssociatedIrp.SystemBuffer))[0] = TAP_DRIVER_MAJOR_VERSION;

        ((PULONG)(Irp->AssociatedIrp.SystemBuffer))[1] = TAP_DRIVER_MINOR_VERSION;

        ((PULONG)(Irp->AssociatedIrp.SystemBuffer))[2]
#if DBG
            = 1;
#else
            = 0;
#endif
        Irp->IoStatus.Information = size;
      } else {
/**********************************************************
Required NDIS handler
Initialize adapter context, prepare it for operation,
set in PAUSED STATE
Return value:
    SUCCESS or kind of error
***********************************************************/
static NDIS_STATUS ParaNdis6_Initialize(
    NDIS_HANDLE miniportAdapterHandle,
    NDIS_HANDLE miniportDriverContext,
    PNDIS_MINIPORT_INIT_PARAMETERS miniportInitParameters)
{
    NDIS_MINIPORT_ADAPTER_ATTRIBUTES        miniportAttributes;
    NDIS_STATUS  status = NDIS_STATUS_SUCCESS;
    BOOLEAN bNoPauseOnSuspend = FALSE;
    PARANDIS_ADAPTER *pContext;

    UNREFERENCED_PARAMETER(miniportDriverContext);
    DEBUG_ENTRY(0);
    /* allocate context structure */
    pContext = (PARANDIS_ADAPTER *)
        NdisAllocateMemoryWithTagPriority(
            miniportAdapterHandle,
            sizeof(PARANDIS_ADAPTER),
            PARANDIS_MEMORY_TAG,
            NormalPoolPriority);

    /* This call is for Static Driver Verifier only - has no real functionality*/
    __sdv_save_adapter_context(pContext);

    if (!pContext)
    {
        DPrintf(0, ("[%s] ERROR: Memory allocation failed!\n", __FUNCTION__));
        status = NDIS_STATUS_RESOURCES;
    }

    if (status == NDIS_STATUS_SUCCESS)
    {
        /* set mandatory fields which Common use */
        NdisZeroMemory(pContext, sizeof(PARANDIS_ADAPTER));
        pContext->ulUniqueID = NdisInterlockedIncrement(&gID);
        pContext->DriverHandle = DriverHandle;
        pContext->MiniportHandle = miniportAdapterHandle;
    }

    if (status == NDIS_STATUS_SUCCESS)
    {
        NdisZeroMemory(&miniportAttributes, sizeof(miniportAttributes));
        miniportAttributes.RegistrationAttributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES;
        miniportAttributes.RegistrationAttributes.Header.Revision = NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;
        miniportAttributes.RegistrationAttributes.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;
        miniportAttributes.RegistrationAttributes.MiniportAdapterContext = pContext;
        miniportAttributes.RegistrationAttributes.AttributeFlags =
            // actual for USB
            // NDIS_MINIPORT_ATTRIBUTES_SURPRISE_REMOVE_OK
            NDIS_MINIPORT_ATTRIBUTES_HARDWARE_DEVICE |
            NDIS_MINIPORT_ATTRIBUTES_BUS_MASTER;
#ifndef NO_VISTA_POWER_MANAGEMENT
        miniportAttributes.RegistrationAttributes.AttributeFlags |= NDIS_MINIPORT_ATTRIBUTES_NO_HALT_ON_SUSPEND;
#endif
#if NDIS_SUPPORT_NDIS630
        miniportAttributes.RegistrationAttributes.AttributeFlags |= NDIS_MINIPORT_ATTRIBUTES_NO_PAUSE_ON_SUSPEND;
        bNoPauseOnSuspend = TRUE;
#endif
        miniportAttributes.RegistrationAttributes.CheckForHangTimeInSeconds = 4;
        miniportAttributes.RegistrationAttributes.InterfaceType = NdisInterfacePci;
        status = NdisMSetMiniportAttributes(miniportAdapterHandle, &miniportAttributes);
        if (status != NDIS_STATUS_SUCCESS)
        {
            DPrintf(0, ("[%s] ERROR: NdisMSetMiniportAttributes 1 failed (%X)!\n", __FUNCTION__, status));
        }
    }

    if (status == NDIS_STATUS_SUCCESS)
    {
        /* prepare statistics struct for further reports */
        pContext->Statistics.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
        pContext->Statistics.Header.Revision = NDIS_STATISTICS_INFO_REVISION_1;
        pContext->Statistics.Header.Size = NDIS_SIZEOF_STATISTICS_INFO_REVISION_1;
        /* let Common do all the rest */
        status = ParaNdis_InitializeContext(pContext, miniportInitParameters->AllocatedResources);
        if (status != NDIS_STATUS_SUCCESS)
        {
            DPrintf(0, ("[%s] ERROR: ParaNdis6_InitializeContext failed (%X)!\n", __FUNCTION__, status));
        }
        pContext->bNoPauseOnSuspend = bNoPauseOnSuspend; 
    }

    if (status == NDIS_STATUS_SUCCESS)
    {
        ULONG i;
        NDIS_PNP_CAPABILITIES power60Caps;
#if NDIS_SUPPORT_NDIS620
        NDIS_PM_CAPABILITIES power620Caps;
#endif
#ifdef NO_VISTA_POWER_MANAGEMENT
        pPowerCaps = NULL;
#endif
        ParaNdis_FillPowerCapabilities(&power60Caps);

        NdisZeroMemory(&miniportAttributes, sizeof(miniportAttributes));
        miniportAttributes.GeneralAttributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES;
        miniportAttributes.GeneralAttributes.Header.Revision = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1;
        miniportAttributes.GeneralAttributes.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1;
#if NDIS_SUPPORT_NDIS620
        miniportAttributes.GeneralAttributes.Header.Revision = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_2;
        miniportAttributes.GeneralAttributes.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_2;
        miniportAttributes.GeneralAttributes.PowerManagementCapabilitiesEx = &power620Caps;
        ParaNdis6_Fill620PowerCapabilities(&power620Caps);
#else
        miniportAttributes.GeneralAttributes.PowerManagementCapabilities = &power60Caps;
#endif
        miniportAttributes.GeneralAttributes.MediaType = NdisMedium802_3;
        miniportAttributes.GeneralAttributes.PhysicalMediumType = NdisPhysicalMedium802_3;
        miniportAttributes.GeneralAttributes.MtuSize = pContext->MaxPacketSize.nMaxDataSize;
        miniportAttributes.GeneralAttributes.LookaheadSize = pContext->MaxPacketSize.nMaxFullSizeOS;
        miniportAttributes.GeneralAttributes.MaxXmitLinkSpeed =
        miniportAttributes.GeneralAttributes.MaxRcvLinkSpeed  =  PARANDIS_FORMAL_LINK_SPEED;
        miniportAttributes.GeneralAttributes.MediaConnectState =
            pContext->bConnected ? MediaConnectStateConnected : MediaConnectStateDisconnected;
        miniportAttributes.GeneralAttributes.XmitLinkSpeed =
        miniportAttributes.GeneralAttributes.RcvLinkSpeed = pContext->bConnected ?
            PARANDIS_FORMAL_LINK_SPEED : NDIS_LINK_SPEED_UNKNOWN;
        miniportAttributes.GeneralAttributes.MediaDuplexState = MediaDuplexStateFull;
        miniportAttributes.GeneralAttributes.MacOptions =
                    NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |       /* NIC has no internal loopback support */
                    NDIS_MAC_OPTION_TRANSFERS_NOT_PEND  |       /* Must be set since using  NdisMIndicateReceivePacket */
                    NDIS_MAC_OPTION_NO_LOOPBACK;                /* NIC has no internal loopback support */
        if (IsPrioritySupported(pContext))
            miniportAttributes.GeneralAttributes.MacOptions |= NDIS_MAC_OPTION_8021P_PRIORITY;
        if (IsVlanSupported(pContext))
            miniportAttributes.GeneralAttributes.MacOptions |= NDIS_MAC_OPTION_8021Q_VLAN;
        miniportAttributes.GeneralAttributes.SupportedPacketFilters = PARANDIS_PACKET_FILTERS;
        miniportAttributes.GeneralAttributes.MaxMulticastListSize = PARANDIS_MULTICAST_LIST_SIZE;
        miniportAttributes.GeneralAttributes.MacAddressLength =     ETH_LENGTH_OF_ADDRESS;

#if PARANDIS_SUPPORT_RSS
        if(pContext->bRSSOffloadSupported)
        {
            miniportAttributes.GeneralAttributes.RecvScaleCapabilities =
                ParaNdis6_RSSCreateConfiguration(
                                                &pContext->RSSParameters,
                                                &pContext->RSSCapabilities,
                                                pContext->RSSMaxQueuesNumber);
            pContext->bRSSInitialized = TRUE;
        }
#endif

        for(i = 0; i < ARRAYSIZE(pContext->ReceiveQueues); i++)
        {
            NdisAllocateSpinLock(&pContext->ReceiveQueues[i].Lock);
            InitializeListHead(&pContext->ReceiveQueues[i].BuffersList);

            pContext->ReceiveQueues[i].BatchReceiveArray =
                ParaNdis_AllocateMemory(pContext, sizeof(*pContext->ReceiveQueues[i].BatchReceiveArray)*pContext->NetMaxReceiveBuffers);
            if(!pContext->ReceiveQueues[i].BatchReceiveArray)
            {
                pContext->ReceiveQueues[i].BatchReceiveArray = &pContext->ReceiveQueues[i].BatchReceiveEmergencyItem;
                pContext->ReceiveQueues[i].BatchReceiveArraySize = 1;
            }
            else
            {
                pContext->ReceiveQueues[i].BatchReceiveArraySize = pContext->NetMaxReceiveBuffers;
            }
        }

        pContext->ReceiveQueuesInitialized = TRUE;

        miniportAttributes.GeneralAttributes.AccessType = NET_IF_ACCESS_BROADCAST;
        miniportAttributes.GeneralAttributes.DirectionType = NET_IF_DIRECTION_SENDRECEIVE;
        miniportAttributes.GeneralAttributes.IfType = IF_TYPE_ETHERNET_CSMACD;
        miniportAttributes.GeneralAttributes.IfConnectorPresent = TRUE;
        miniportAttributes.GeneralAttributes.ConnectionType = NET_IF_CONNECTION_DEDICATED;

        ETH_COPY_NETWORK_ADDRESS(miniportAttributes.GeneralAttributes.PermanentMacAddress, pContext->PermanentMacAddress);
        ETH_COPY_NETWORK_ADDRESS(miniportAttributes.GeneralAttributes.CurrentMacAddress, pContext->CurrentMacAddress);

        ParaNdis6_GetSupportedOid(&miniportAttributes.GeneralAttributes);
        /* update also SupportedStatistics in ready to use statistics block */
        pContext->Statistics.SupportedStatistics = ParaNdis6_GetSupportedStatisticsFlags();
        status = NdisMSetMiniportAttributes(miniportAdapterHandle, &miniportAttributes);
        if (status != NDIS_STATUS_SUCCESS)
        {
            DPrintf(0, ("[%s] ERROR: NdisMSetMiniportAttributes 2 failed (%X)!\n", __FUNCTION__, status));
        }
    }

    if (pContext && status != NDIS_STATUS_SUCCESS && status != NDIS_STATUS_PENDING)
    {
        // no need to cleanup
        NdisFreeMemory(pContext, 0, 0);
        pContext = NULL;
    }

    if (pContext && status == NDIS_STATUS_SUCCESS)
    {
        status = ParaNdis_FinishInitialization(pContext);
        if (status != NDIS_STATUS_SUCCESS)
        {
            ParaNdis_CleanupContext(pContext);
            NdisFreeMemory(pContext, 0, 0);
            pContext = NULL;
        }
    }
    if (pContext && status == NDIS_STATUS_SUCCESS)
    {
        if (NDIS_STATUS_SUCCESS ==
            ParaNdis6_GetRegistrationOffloadInfo(pContext,
                &miniportAttributes.OffloadAttributes))
            status = NdisMSetMiniportAttributes(miniportAdapterHandle, &miniportAttributes);
            if (status != NDIS_STATUS_SUCCESS)
            {
                DPrintf(0, ("[%s] ERROR: NdisMSetMiniportAttributes 3 failed (%X)!\n", __FUNCTION__, status));
            }
    }

    if (pContext && status == NDIS_STATUS_SUCCESS)
    {
        ParaNdis_DebugRegisterMiniport(pContext, TRUE);
    }

    DEBUG_EXIT_STATUS(status ? 0 : 2, status);
    return status;
}
Beispiel #3
0
VOID
Hw11ReadRegistryConfiguration(
    __in  PHW                     Hw,
    __in  NDIS_HANDLE             ConfigurationHandle
    )
{
    NDIS_STATUS                 ndisStatus = NDIS_STATUS_SUCCESS;
    PUCHAR                      NetworkAddress;
    UINT                        Length;

    // TODO: These should be read from the registry
    Hw->RegInfo.RTSThreshold = 2347;
    Hw->RegInfo.FragmentationThreshold = 2346;
    Hw->RegInfo.BeaconPeriod = 100;

    Hw->RegInfo.NumRXBuffersUpperLimit = HW11_MAX_RX_MSDUS;
    Hw->RegInfo.NumRXBuffersLowerBase = HW11_MIN_RX_MSDUS;
    
    //
    // read all the non-hardware specific registry values 
    //
    MpReadRegistry((PVOID)Hw, ConfigurationHandle, HWRegTable, HW_NUM_REG_PARAMS);

    //
    // Read NetworkAddress registry value. Use it as the current address if any.
    //
    if (ConfigurationHandle != NULL) 
    {
        NdisReadNetworkAddress(&ndisStatus,
                               (void **)&NetworkAddress,
                               &Length,
                               ConfigurationHandle);

        //
        // If there is a valid NetworkAddress override in registry,use it 
        //
        if ((ndisStatus == NDIS_STATUS_SUCCESS) && (Length == sizeof(DOT11_MAC_ADDRESS))) 
        {
            // Dont use multicast/broadcast or 00* addresses
            if (!ETH_IS_MULTICAST(NetworkAddress) && !ETH_IS_BROADCAST(NetworkAddress)) 
            {
                if ((NetworkAddress[0] == 0x00) &&
                    (NetworkAddress[1] == 0x00) &&
                    (NetworkAddress[2] == 0x00) &&
                    (NetworkAddress[3] == 0x00) &&
                    (NetworkAddress[4] == 0x00) &&
                    (NetworkAddress[5] == 0x00)) 
                {   
                    // Network addr = 00 00 00 00 00 00
                    Hw->RegInfo.AddressOverrideEnabled = FALSE;
                }
                else if ((NetworkAddress[0] & 0x02) != 0x02)
                {
                    // Not a locally administered address
                    Hw->RegInfo.AddressOverrideEnabled = FALSE;
                }
                else
                {
                    ETH_COPY_NETWORK_ADDRESS(Hw->RegInfo.OverrideAddress,NetworkAddress);
                    Hw->RegInfo.AddressOverrideEnabled = TRUE;
                }
            }
        }

        ndisStatus = NDIS_STATUS_SUCCESS;

    }

}