Exemplo n.º 1
0
NTSTATUS
NICHandleSetOidRequest(
    __in  PFDO_DATA                   FdoData,
    __in  PIRP                       Irp
    )
/*++

Routine Description:

    This routine handles ioctl request for Set OIDs. Most of
    the IOCTL requests are only if the upper edge is NDIS.

Arguments:


Return Value:


--*/
{
    NTSTATUS                status = STATUS_SUCCESS;
    PNDISPROT_SET_OID       pSet;
    NDIS_OID                Oid;
    ULONG                   PacketFilter;
    PVOID                   InformationBuffer = NULL;
    ULONG                   InformationBufferLength = 0;
    KIRQL                   oldIrql;
    PVOID                   DataBuffer;
    ULONG                   BufferLength, unUsed;
    PIO_STACK_LOCATION      pIrpSp;
    DEVICE_POWER_STATE      newDeviceState, oldDeviceState;

    pIrpSp = IoGetCurrentIrpStackLocation(Irp);
    DataBuffer = Irp->AssociatedIrp.SystemBuffer;
    BufferLength = pIrpSp->Parameters.DeviceIoControl.InputBufferLength;

    DebugPrint(LOUD, DBG_IOCTLS, "--> HandleSetOIDRequest\n");

    Oid = 0;

    do
    {
        if (BufferLength < sizeof(NDISPROT_SET_OID))
        {
            status = STATUS_BUFFER_OVERFLOW;
            break;
        }

        pSet = (PNDISPROT_SET_OID)DataBuffer;
        Oid = pSet->Oid;
        InformationBuffer = &pSet->Data[0];
        InformationBufferLength = BufferLength - FIELD_OFFSET(NDISPROT_SET_OID, Data);
        switch(Oid)
        {

        case OID_802_3_MULTICAST_LIST:
            //
            // Verify the length
            //
            if (InformationBufferLength % ETH_LENGTH_OF_ADDRESS != 0)
            {
                return(STATUS_INVALID_BUFFER_SIZE);
            }

            //
            // Save the number of MC list size
            //
            FdoData->MCAddressCount = InformationBufferLength / ETH_LENGTH_OF_ADDRESS;
            ASSERT(FdoData->MCAddressCount <= NIC_MAX_MCAST_LIST);
            InformationBufferLength = InformationBufferLength > sizeof(FdoData->MCList)
					? sizeof(FdoData->MCList):InformationBufferLength;

            //
            // Save the MC list
            //
            RtlMoveMemory(
                FdoData->MCList,
                InformationBuffer,
                InformationBufferLength);

            KeAcquireSpinLock(&FdoData->Lock, &oldIrql);
            KeAcquireSpinLockAtDpcLevel(&FdoData->RcvLock);

            status = NICSetMulticastList(FdoData);

            KeReleaseSpinLockFromDpcLevel(&FdoData->RcvLock);
            KeReleaseSpinLock(&FdoData->Lock, oldIrql);
            break;

        case OID_GEN_CURRENT_PACKET_FILTER:
            //
            // Verify the Length
            //
            if (InformationBufferLength != sizeof(ULONG))
            {
                return(STATUS_INVALID_BUFFER_SIZE);
            }

            RtlMoveMemory(&PacketFilter, InformationBuffer, sizeof(ULONG));

            //
            // any bits not supported?
            //
            if (PacketFilter & ~NIC_SUPPORTED_FILTERS)
            {
                return(STATUS_NOT_SUPPORTED);
            }

            //
            // any filtering changes?
            //
            if (PacketFilter == FdoData->PacketFilter)
            {
                break;
            }

            KeAcquireSpinLock(&FdoData->Lock, &oldIrql);
            KeAcquireSpinLockAtDpcLevel(&FdoData->RcvLock);

            if (MP_TEST_FLAG(FdoData, fMP_ADAPTER_LINK_DETECTION))
            {

                //
                // The device is busy doing link detection. Let us queue
                // the IRP. When the link detection is over, the watchdog
                // timer DPC will complete this IRP.
                //
                ASSERT(!FdoData->SetRequest);
                status = PciDrvQueueIoctlIrp(FdoData, Irp);

                KeReleaseSpinLockFromDpcLevel(&FdoData->RcvLock);
                KeReleaseSpinLock(&FdoData->Lock, oldIrql);
                break;
            }

            status = NICSetPacketFilter(
                         FdoData,
                         PacketFilter);

            KeReleaseSpinLockFromDpcLevel(&FdoData->RcvLock);
            KeReleaseSpinLock(&FdoData->Lock, oldIrql);

            if (status == STATUS_SUCCESS)
            {
                FdoData->PacketFilter = PacketFilter;
            }

            break;

        case OID_PNP_SET_POWER:

            if (InformationBufferLength != sizeof(NDIS_DEVICE_POWER_STATE ))
            {
                return(STATUS_BUFFER_TOO_SMALL);
            }

            newDeviceState = *(PDEVICE_POWER_STATE UNALIGNED)InformationBuffer;
            oldDeviceState = FdoData->DevicePowerState;
            FdoData->DevicePowerState = newDeviceState;

            if (oldDeviceState == PowerDeviceD0) {

                status = PciDrvPowerBeginQueuingIrps(
                    FdoData->Self,
                    1,              // One for current OID request.
                    FALSE           // Do not query for state change.
                    );

                ASSERT(NT_SUCCESS(status));
            }

            //
            // Set the power state - Cannot fail this request
            //
            status = NICSetPower(FdoData, newDeviceState );

            if (status != STATUS_SUCCESS)
            {
                DebugPrint(ERROR, DBG_IOCTLS, "SET Power: Hardware error !!!\n");
                break;
            }

            if (newDeviceState == PowerDeviceD0) {

                //
                // Our hardware is now on again. Here we empty our existing queue of
                // requests and let in new ones.
                //
                FdoData->QueueState = AllowRequests;
                PciDrvProcessQueuedRequests(FdoData);
            }

            status = STATUS_SUCCESS;
            break;

        case OID_PNP_ADD_WAKE_UP_PATTERN:
            //
            // call a function that would program the adapter's wake
            // up pattern, return success
            //
            DebugPrint(TRACE, DBG_IOCTLS, "--> OID_PNP_ADD_WAKE_UP_PATTERN\n");

            if (IsPoMgmtSupported(FdoData) )
            {
                status = NICAddWakeUpPattern(FdoData,
                                            InformationBuffer,
                                            InformationBufferLength,
                                            &unUsed,
                                            &unUsed);
            }
            else
            {
                status = STATUS_NOT_SUPPORTED;
            }
            break;


        case OID_PNP_REMOVE_WAKE_UP_PATTERN:

            //
            // call a function that would remove the adapter's wake
            // up pattern, return success
            //
            DebugPrint(TRACE, DBG_IOCTLS, "--> OID_PNP_ADD_WAKE_UP_PATTERN\n");

            if (IsPoMgmtSupported(FdoData) )
            {
                status = NICRemoveWakeUpPattern(FdoData,
                                               InformationBuffer,
                                               InformationBufferLength,
                                               &unUsed,
                                               &unUsed);

            }
            else
            {
                status = STATUS_NOT_SUPPORTED;
            }
            break;

        case OID_PNP_ENABLE_WAKE_UP:
            //
            // call a function that would enable wake up on the adapter
            // return success
            //
            DebugPrint(TRACE, DBG_IOCTLS, "--> OID_PNP_ENABLE_WAKE_UP\n");
            if (IsPoMgmtSupported(FdoData))
            {
                ULONG       WakeUpEnable;
                RtlMoveMemory(&WakeUpEnable, InformationBuffer,sizeof(ULONG));
                //
                // The WakeUpEable can only be 0, or NDIS_PNP_WAKE_UP_PATTERN_MATCH since the driver only
                // supports wake up pattern match
                //
                if ((WakeUpEnable != 0)
                       && ((WakeUpEnable & NDIS_PNP_WAKE_UP_PATTERN_MATCH) != NDIS_PNP_WAKE_UP_PATTERN_MATCH ))
                {
                    status = STATUS_NOT_SUPPORTED;
                    FdoData->AllowWakeArming = FALSE;
                    break;
                }
                //
                // When the driver goes to low power state, it would check WakeUpEnable to decide
                // which wake up methed it should use to wake up the machine. If WakeUpEnable is 0,
                // no wake up method is enabled.
                //
                FdoData->AllowWakeArming = TRUE;

                status = STATUS_SUCCESS;
            }
            else
            {
                status = STATUS_NOT_SUPPORTED;
            }

            break;
        default:
            status = STATUS_NOT_SUPPORTED;
            break;
        }
    }while (FALSE);

    DebugPrint(LOUD, DBG_IOCTLS, "<-- HandleSetOIDRequest\n");

    return (status);
}
Exemplo n.º 2
0
NTSTATUS
NICConfigureForWakeUp(
    IN PFDO_DATA FdoData,
    IN BOOLEAN  AddPattern
    )
/*++
Routine Description:


Arguments:

    FdoData                 FdoData structure

Return Value:

    Success - if successful.

--*/
{
#define MAX_WAKEUP_PATTERN_LENGTH  128

    UCHAR           Buffer[sizeof(NDIS_PM_PACKET_PATTERN) +
                                MAX_WAKEUP_PATTERN_LENGTH];
    PCHAR           patternBuffer, nextMask, nextPattern;
    ULONG           maskLen;
    PNDIS_PM_PACKET_PATTERN ndisPattern;
    ULONG           bufLen;
    NTSTATUS        status;
    ULONG           unUsed;
    CHAR            wakePattern[]={0xff,0xff,0xff,0xff,0xff,0xff}; //broadcast address

    patternBuffer = (PCHAR)&Buffer[0];

    ndisPattern = (PNDIS_PM_PACKET_PATTERN)patternBuffer;
    RtlZeroMemory(ndisPattern, sizeof(NDIS_PM_PACKET_PATTERN));


    ndisPattern->PatternSize = sizeof(wakePattern);

    maskLen = (ndisPattern->PatternSize-1)/8 + 1;

    nextMask = (PCHAR)patternBuffer + sizeof(NDIS_PM_PACKET_PATTERN);

    nextPattern = nextMask + maskLen;

    *nextMask = 0x3f;

    ndisPattern->MaskSize = maskLen;
    ndisPattern->PatternOffset = (ULONG) ((ULONG_PTR) nextPattern - (ULONG_PTR) patternBuffer);

    bufLen = sizeof(NDIS_PM_PACKET_PATTERN) + maskLen + ndisPattern->PatternSize;

    RtlCopyMemory(nextPattern, FdoData->CurrentAddress, ETHERNET_ADDRESS_LENGTH);

    if(AddPattern){
        status = NICAddWakeUpPattern(FdoData, Buffer, bufLen, &unUsed, &unUsed);
        if(!NT_SUCCESS(status)){
            TraceEvents(TRACE_LEVEL_VERBOSE, DBG_POWER, "NICAddWakeupPattern failed %x\n", status);
        }
    }else{
        status = NICRemoveWakeUpPattern(FdoData, Buffer, bufLen, &unUsed, &unUsed);
        if(!NT_SUCCESS(status)){
            TraceEvents(TRACE_LEVEL_VERBOSE, DBG_POWER, "NICRemoveWakeUpPattern failed %x\n", status);
        }
    }

    return status;
}