⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 init.c

📁 网络驱动开发
💻 C
📖 第 1 页 / 共 4 页
字号:
    //
    // We need to know whether the device has been assigned any resources
    // by the bus driver because this enables has to decide whether to
    // indicate the received packets at PASSIVE_LEVEL or DISPATCH_LEVEL.
    // NDIS makes an assumption that any device that uses hardware resources
    // will indicate packets from a DPC routine. 
    //
    if (Status == NDIS_STATUS_SUCCESS) {
        //
        // There is possibility that we are enumerated by the toaster bus
        // driver. The toaster bus driver just for illustration purpose
        // assigns a port resource to every child it pops.
        //
        Adapter->IsHardwareDevice = TRUE;        
        
    } else {
        //
        // No hardware resources. So we will indicate the packets at 
        // PASSIVE_LEVEL.
        //
        Adapter->IsHardwareDevice = FALSE;        
        
    }
    //
    // Set our media state of disconnected unitl we are successfully connected
    // to the target device. This flag will be cleared by the 
    //
    MP_SET_FLAG(Adapter, fMP_DISCONNECTED);
    
#ifdef NDIS50_MINIPORT
    //
    // Register a shutdown handler for NDIS50 or earlier miniports
    // For NDIS51 miniports, set AdapterShutdownHandler.
    //
    NdisMRegisterAdapterShutdownHandler(
        Adapter->AdapterHandle,
        (PVOID) Adapter,
        (ADAPTER_SHUTDOWN_HANDLER) MPShutdown);
#endif         


    ntStatus = NICInitAdapterWorker(Adapter);  
    if (ntStatus == STATUS_OBJECT_NAME_NOT_FOUND){
        //
        // If the target device doesn't exist, we will register for ExCallback.
        // Our callback routine will be called at PASSIVE_LEVEL when the
        // target driver (NDISPROT) gets loaded and notifies the callback.
        //
        DEBUGP (MP_INFO, ( "Target device doesn't exist at this time %x\n", ntStatus ));
            
        if(NICRegisterExCallback(Adapter)){
            ntStatus = STATUS_SUCCESS;
        }                
    }else if(ntStatus == STATUS_NO_MORE_ENTRIES){
        ntStatus = STATUS_SUCCESS;
    }

    NT_STATUS_TO_NDIS_STATUS(ntStatus, &Status);
    
    DEBUGP(MP_TRACE, ("<--- InitializeAdapter, Status=%x\n", Status));

    return Status;

}


VOID 
NICInitWorkItemCallback(
    PNDIS_WORK_ITEM WorkItem, 
    PVOID Context) 
/*++
Routine Description:

    Workitme to retry our Initialization work as a result of notifiction
    from the target driver.

Arguments:

    WorkItem - Pointer to workitem
    
    Dummy - Unused
    
Return Value:


--*/    
{

    PMP_ADAPTER Adapter = (PMP_ADAPTER)Context;
    NTSTATUS ntStatus;
    
    DEBUGP(MP_TRACE, ("--> NICInitWorkItemCallback\n"));

    PAGED_CODE();

    NdisFreeMemory(WorkItem, sizeof(NDIS_WORK_ITEM), 0);
    
    ntStatus = NICInitAdapterWorker(Adapter);  
    
    if (NT_SUCCESS(ntStatus)){
        //
        // Let us indicate our media state to protocol drivers.
        //
        NdisMIndicateStatus(Adapter->AdapterHandle, 
                                NDIS_STATUS_MEDIA_CONNECT, 
                                (PVOID)0, 0);
        
        NdisMIndicateStatusComplete(Adapter->AdapterHandle);                
        
    } else {
        
        if(ntStatus == STATUS_OBJECT_NAME_NOT_FOUND){        
            //
            // This could be a spurious notification as a result
            // of another instance of our miniport registering
            // the callaback.
            //
            DEBUGP (MP_ERROR, ( "NDISPROT is not ready yet\n"));        
         }else {
            //
            // I guess something irrecoverable happened. So let
            // us remove our adapter instance by calling.
            //
            DEBUGP (MP_ERROR, ( "Removing miniport...\n"));                 
            NdisMRemoveMiniport(Adapter->AdapterHandle);
         }
    }

    MP_DEC_REF(Adapter);     

    DEBUGP(MP_TRACE, ("<-- NICInitWorkItemCallback\n"));

    return;
}

NTSTATUS  
NICInitAdapterWorker(
    PMP_ADAPTER Adapter    
    ) 
/*++
Routine Description:

    This is the worker routine for doing all the initialization work.
    It opens the target device, allocates send & receive side resources
    and spawns a worker thread to start receiving packets from the
    target device.
    
Arguments:

    Adapter     Pointer to our adapter
    
Return Value:

    NT Status code
    
--*/    
{
    NTSTATUS            ntStatus = STATUS_UNSUCCESSFUL;
    NDIS_STATUS         Status;
    ULONG               unUsed;
    
    DEBUGP(MP_WARNING, ("--> NICInitAdapterWorker %p\n", Adapter));

    PAGED_CODE();

    //
    // Let us make sure only one thread is executing this routine by
    // waiting on this synchronization event.
    //
    DEBUGP(MP_WARNING, ("Waiting on the InitEvent...\n"));
    NdisWaitEvent(&Adapter->InitEvent, 0);

    do {
        
        if(!MP_TEST_FLAG(Adapter, fMP_INIT_IN_PROGRESS)) {
            //
            // Adapter has been initialized successfully.
            //
            ntStatus = STATUS_SUCCESS;        
            break;            
        }    
        
#ifdef INTERFACE_WITH_NDISPROT

        ntStatus = NICOpenNdisProtocolInterface(Adapter);
        if(!NT_SUCCESS(ntStatus)) {
            break;
        }
        Adapter->TargetSupportsChainedMdls = FALSE;
#else
        Adapter->TargetDeviceObject = Adapter->NextDeviceObject;
        //
        // Assuming this is driver attached to PCIDRV underneath. If you 
        // adapt this driver for someother stack, make sure the target
        // supports chanined MDLs. For example, USB stack doesn't support
        // chained MDLs.
        //
        Adapter->TargetSupportsChainedMdls = TRUE;
#endif

        Status = NICAllocSendResources(Adapter);
        if(Status != NDIS_STATUS_SUCCESS)
        {
            ntStatus = STATUS_INSUFFICIENT_RESOURCES;
            DEBUGP(MP_ERROR, ("Failed to allocate send side resources\n"));
            break;
        }
        
        Status = NICAllocRecvResources(Adapter);
        if(Status != NDIS_STATUS_SUCCESS)
        {
            ntStatus = STATUS_INSUFFICIENT_RESOURCES;
            DEBUGP(MP_ERROR, ("Failed to send side resources\n"));
            break;
        }
    
        ntStatus = NICSendRequest(Adapter, 
                        NdisRequestQueryInformation,
                        OID_GEN_LINK_SPEED,
                        &Adapter->ulLinkSpeed,
                        sizeof(ULONG),
                        &unUsed,
                        &unUsed
                        );
        
        if(!NT_SUCCESS(ntStatus)){
            DEBUGP(MP_ERROR, ("-->Unable to get link speed %x\n", ntStatus));
            break;
        }

        //
        // If the device property is set to promiscuous, we will set the
        // target NIC to promiscuous mode and use a locally administered
        // MAC address. Otherwise, we will assume the MAC address of the 
        // target NIC (We are assuming that user must have disabled the
        // binding of TCP/IP with the target NIC).
        //
        if(Adapter->Promiscuous) {
            
            ULONG PacketFilter = NDIS_PACKET_TYPE_PROMISCUOUS;
            
            DEBUGP(MP_TRACE, ("Set the physical NIC to promiscuous mode\n")); 
            
            ntStatus = NICSendRequest(Adapter, 
                            NdisRequestSetInformation,
                            OID_GEN_CURRENT_PACKET_FILTER,
                            &PacketFilter,
                            sizeof(ULONG),
                            &unUsed,
                            &unUsed
                            );
            
            if(!NT_SUCCESS(ntStatus)){
                DEBUGP(MP_ERROR, ("-->Unable to set the NIC to promiscuous mode %x\n", ntStatus));        
                break;            
            }
        } else {
        
            //
            // Then get the physical NICs MAC address and use that as our
            // MAC address. Hoping that user must have disabled TCP/IP 
            // bindings with the physcial NIC.
            //                    

            ntStatus = NICSendRequest(Adapter, 
                        NdisRequestQueryInformation,
                        OID_802_3_CURRENT_ADDRESS,
                        Adapter->PhyNicMacAddress,
                        ETH_LENGTH_OF_ADDRESS,
                        &unUsed,
                        &unUsed
                        );
        
            if(!NT_SUCCESS(ntStatus)){
                DEBUGP(MP_ERROR, ("-->Unable to get mac address %x\n", ntStatus));        
                break;            
            }

            ETH_COPY_NETWORK_ADDRESS(Adapter->CurrentAddress,
                                            Adapter->PhyNicMacAddress);

            DEBUGP(MP_WARNING, ("Current Address = %02x-%02x-%02x-%02x-%02x-%02x\n", 
                                    Adapter->CurrentAddress[0],
                                    Adapter->CurrentAddress[1],
                                    Adapter->CurrentAddress[2],
                                    Adapter->CurrentAddress[3],
                                    Adapter->CurrentAddress[4],
                                    Adapter->CurrentAddress[5]));

        }

        MP_CLEAR_FLAG(Adapter, fMP_INIT_IN_PROGRESS);
        MP_CLEAR_FLAG(Adapter, fMP_DISCONNECTED);        
        MP_SET_FLAG(Adapter, fMP_POST_WRITES);
        MP_SET_FLAG(Adapter, fMP_POST_READS);
        
        //
        // Finally schedule a workitme to start reading packets from
        // the target device. Anytime, you post an asynchronous work
        // make sure to take a reference on the Adapter to synchrnonize
        // the halt handler with the workitem.
        //
        MP_INC_REF(Adapter);           
        NdisScheduleWorkItem(&Adapter->ReadWorkItem);    

        Adapter->StatusIndicationIrp = 
            IoAllocateIrp( Adapter->TargetDeviceObject->StackSize, FALSE );
        if (NULL == Adapter->StatusIndicationIrp) {
            DEBUGP(MP_ERROR, ("IoAllocateIrp failed\n"));       
            ntStatus = STATUS_INSUFFICIENT_RESOURCES;
            break;
        }
        
        NICPostAsynchronousStatusIndicationIrp(Adapter);                
        
    }while(FALSE);

    if(!NT_SUCCESS(ntStatus)){
        NICFreeSendResources(Adapter);
        NICFreeRecvResources(Adapter);        
    }

    //
    // Signal the event so another thread can proceed.
    //
    NdisSetEvent(&Adapter->InitEvent);
    
    DEBUGP(MP_TRACE, ("<-- NICInitAdapterWorker %x\n", ntStatus));
    
    return ntStatus;
}

NTSTATUS
NICMakeSynchronousIoctl(
    IN PDEVICE_OBJECT       TopOfDeviceStack,
    IN PFILE_OBJECT         FileObject,
    IN ULONG                IoctlControlCode,
    IN OUT PVOID            InputBuffer,
    IN ULONG                InputBufferLength,
    IN OUT PVOID            OutputBuffer,
    IN ULONG                OutputBufferLength,
    OUT PULONG              BytesReadOrWritten    
    )
/*++

Routine Description:

    This routine sends a synchronous ioctl request. This has been customized
    to handle only buffered IOCTLs. It also assumes that InputBuffer and
    OutputBuffer pointers are non paged kernelmode bufferr addresses. This routine
    can be called at IRQL <= DISPATCH_LEVEL.

Arguments:

    TopOfDeviceStack    - Pointer to the target deviceobject
    
    IoctlControlCode    - Value of the IOCTL request

    InputBuffer        - Buffer to be sent to the TopOfDeviceStack

    InputBufferLength  - Size of buffer to be sent to the TopOfDeviceStack

    OutputBuffer       - Buffer for received data from the TopOfDeviceStack

    OutputBufferLength - Size of receive buffer from the TopOfDeviceStack

    BytesReadOrWritten - Number of bytes read or written
    
Return Value:

    NT status code
    
--*/ 
{
    KEVENT              event;
    PIRP                irp;
    PIO_STACK_LOCATION  irpSp;
    NTSTATUS            status;
    ULONG               length;   
    PVOID               buffer = NULL;
    
    KeInitializeEvent(&event, NotificationEvent, FALSE);

    irp = IoAllocateIrp( TopOfDeviceStack->StackSize, FALSE );
    if (NULL == irp) {
        DEBUGP(MP_ERROR, ("IoAllocateIrp failed\n"));       
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    irpSp = IoGetNextIrpStackLocation( irp );
    irpSp->MajorFunction = IRP_MJ_DEVICE_CONTROL;

    irpSp->Parameters.DeviceIoControl.OutputBufferLength = OutputBufferLength;
    irpSp->Parameters.DeviceIoControl.InputBufferLength = InputBufferLength;
    irpSp->Parameters.DeviceIoControl.IoControlCode = IoctlControlCode;
    irpSp->FileObject = FileObject;
    irp->MdlAddress = NULL;
    irp->AssociatedIrp.SystemBuffer = NULL;
    //
    // Make sure the IOCTL is a buffered IOCTL.
    //

    ASSERT((IoctlControlCode & 3) == METHOD_BUFFERED);

    //
    // Allocate a buffer that is large enough to contain
    // both the input and the output buffers.  Copy the input buffer
    // to the allocated buffer and set the appropriate IRP fields.
    //

    if (InputBufferLength != 0 || OutputBufferLength != 0) {

        length = InputBufferLength > OutputBufferLength ? 
                            InputBufferLength : OutputBufferLength;
        
        buffer = ExAllocatePoolWithTag( NonPagedPool, length, NIC_TAG);
        if (buffer == NULL) {
            IoFreeIrp( irp );
            return STATUS_INSUFFICIENT_RESOURCES;
        }
        if (InputBuffer) {
            RtlCopyMemory( buffer,
                           InputBuffer,
                           InputBufferLength );
        }
        
    } 

    irp->AssociatedIrp.SystemBuffer = buffer;
    
    IoSetCompletionRoutine(irp,
                   NICMakeSynchronousIoCtlCompletion,
                   (PVOID)&event,
                   TRUE,
                   TRUE,
                   TRUE);

    IoCallDriver(TopOfDeviceStack, irp);

    //
    // Wait for the event to be signalled by the completion
    // routine.
    //

    KeWaitForSingleObject(&event,
                        Executive,
                        KernelMode,
                        FALSE, // Not alertable
                        NULL);

    //
    // Copy the content of system buffer to output buffer.
    //
    
    if (OutputBuffer && buffer) {
        RtlCopyMemory( OutputBuffer,
                       buffer,
                       OutputBufferLength );
    }

    status = irp->IoStatus.Status; 
    *BytesReadOrWritten = (ULONG)irp->IoStatus.Information;   

    if(buffer){
        ExFreePoolWithTag(buffer, NIC_TAG);
    }
    
    IoFreeIrp(irp);
    
    return status;
} 

NTSTATUS
NICMakeSynchronousIoCtlCompletion(
    IN PDEVICE_OBJECT   DeviceObject,
    IN PIRP             Irp,
    IN PVOID            Context
    )

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -