1
votes

I have a Bus Driver that creates a PDO for each physical port of a custom Ethernet card. I also have an NDIS Miniport Driver that installs onto each PDO.

The Bus Driver is based on the static Toaster example. The NDIS Miniport is based on the Netvmini modified to match the hardware.

ToasterInterface.InterfaceHeader.InterfaceReference =
    WdfDeviceInterfaceReferenceNoOp;
ToasterInterface.InterfaceHeader.InterfaceDereference =
    WdfDeviceInterfaceDereferenceNoOp;

ToasterInterface.GetCrispinessLevel  = Bus_GetCrispinessLevel;
ToasterInterface.SetCrispinessLevel  = Bus_SetCrispinessLevel;
ToasterInterface.IsSafetyLockEnabled = Bus_IsSafetyLockEnabled;

WDF_QUERY_INTERFACE_CONFIG_INIT(&qiConfig,
                                (PINTERFACE) &ToasterInterface,
                                &GUID_TOASTER_INTERFACE_STANDARD,
                                NULL);

status = WdfDeviceAddQueryInterface(hChild, &qiConfig);

How do I call a KMDF WDF defined interface from an NDIS Driver? Thanks

2

2 Answers

1
votes

From the NDIS side of your driver, you can call NdisMGetDeviceProperty to obtain the FDO of the individual miniport. From there, call IoCallDriver (or IoSynchronousCallDriver to save a couple lines of code) in the usual fashion to issue IRP_MN_QUERY_INTERFACE.

You need to ensure that you dereference the bus interface before your MiniportHalt completes.

1
votes

Here is the code that worked for me.

    // ***********************************
    // Inside Header (Both Drivers, Shared)
    // ***********************************

    typedef
    NTSTATUS
    (*PMY_BUS_INTERFACE_TEST) (
        _In_ PINTERFACE InterfaceHeader,
        _In_ PVOID pDataIn,
        _In_ size_t szDataInSize
        );

    typedef struct _MY_BUS_INTERFACE {
        INTERFACE InterfaceHeader;
        PMY_BUS_INTERFACE_TEST InterfaceTest;
    } MY_BUS_INTERFACE, *PMY_BUS_INTERFACE;

    #define MY_BUS_INTERFACE_VERSION 1
    DEFINE_GUID(GUID_MY_BUS_INTERFACE, 0x12345678, 0x1234, 0x1234, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88);


    // ***********************************
    // pdo.c: inside Bus_CreatePdo
    // ***********************************


    //
    // Test Interface
    //
    MY_BUS_INTERFACE arincInterface;
    RtlZeroMemory(&arincInterface, sizeof(MY_BUS_INTERFACE));
    arincInterface.InterfaceHeader.Size = sizeof(MY_BUS_INTERFACE);
    arincInterface.InterfaceHeader.Version = MY_BUS_INTERFACE_VERSION;
    arincInterface.InterfaceHeader.Context = (PVOID)hChild;
    arincInterface.InterfaceHeader.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;
    arincInterface.InterfaceHeader.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;

    arincInterface.InterfaceTest = Bus_InterfaceTest;

    WDF_QUERY_INTERFACE_CONFIG qic;
    WDF_QUERY_INTERFACE_CONFIG_INIT(&qic,
        (PINTERFACE)&arincInterface,
        &GUID_MY_BUS_INTERFACE,
        NULL);


    // ***********************************
    // Inside pdo.c
    // ***********************************

    NTSTATUS
    Bus_InterfaceTest(
        _In_ PINTERFACE InterfaceHeader,
        _In_ PVOID pDataIn,
        _In_ size_t szDataInSize
    )
    {
        NTSTATUS status = STATUS_SUCCESS;

        UNREFERENCED_PARAMETER(InterfaceHeader);
        UNREFERENCED_PARAMETER(pDataIn);
        UNREFERENCED_PARAMETER(szDataInSize);

        KdPrint(("Bus_InterfaceTest: pDataIn [%p] [%llu] \n", pDataIn, szDataInSize));

        status = -678;

        return status;
    }



    // ***********************************
    // Inside Miniport Driver
    // ***********************************

    //
    // Query Interface Setup
    //
    MY_BUS_INTERFACE myBusInterface;
    PMY_BUS_INTERFACE pMyBusInterface = &myBusInterface;

    //
    // Initialize an event to block on
    //
    KEVENT event;
    KeInitializeEvent(&event, SynchronizationEvent, FALSE);

    //
    // Build an irp
    //
    IO_STATUS_BLOCK     ioStatus;

    PIRP irp = IoBuildSynchronousFsdRequest(
        IRP_MJ_PNP,
        Adapter->NextDeviceObject,
        NULL,
        0,
        NULL,
        &event,
        &ioStatus
    );

    if (!irp) {
        pMyBusInterface = NULL;
        Status = STATUS_INSUFFICIENT_RESOURCES;
        break;
    }

    irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
    irp->IoStatus.Information = 0;

    //
    // Get the irp stack location
    //
    PIO_STACK_LOCATION irpSp = IoGetNextIrpStackLocation(irp);

    //
    // Use QUERY_INTERFACE to get the address of the direct-call
    // ACPI interfaces.
    //
    irpSp->MajorFunction = IRP_MJ_PNP;
    irpSp->MinorFunction = IRP_MN_QUERY_INTERFACE;
    irpSp->Parameters.QueryInterface.InterfaceType = (LPGUID)&GUID_MY_BUS_INTERFACE;
    irpSp->Parameters.QueryInterface.Version = MY_BUS_INTERFACE_VERSION;
    irpSp->Parameters.QueryInterface.Size = sizeof(MY_BUS_INTERFACE);
    irpSp->Parameters.QueryInterface.Interface = (PINTERFACE)pMyBusInterface;
    irpSp->Parameters.QueryInterface.InterfaceSpecificData = NULL;

    //
    // send the request down
    //
    NTSTATUS status = IoCallDriver(Adapter->NextDeviceObject, irp);
    if (status == STATUS_PENDING) {
        KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
        status = ioStatus.Status;
    }
    else if (!NT_SUCCESS(status))
    {
        KdPrint(("IoCallDriver was not pending or success \n"));
        break;
    }

    //
    // test interface
    //
    char testData[260] = "TEST";
    NTSTATUS interfaceTestStatus = (*myBusInterface.InterfaceTest)(
        (PINTERFACE)pMyBusInterface,
        (PVOID)testData,
        strlen(testData)
        );
    if (interfaceTestStatus == -678)
    {
        KdPrint(("************************************** \n"));
        KdPrint(("***     InterfaceTest SUCCESS      *** \n"));
        KdPrint(("************************************** \n"));

        status = STATUS_SUCCESS;
    }
    else {
        KdPrint(("************************************** \n"));
        KdPrint(("***     InterfaceTest FAILURE      *** \n"));
        KdPrint(("************************************** \n"));
        status = STATUS_UNSUCCESSFUL;
        (*myBusInterface.InterfaceHeader.InterfaceDereference)(myBusInterface.InterfaceHeader.Context);
        break;
    }

    //
    // Dereference Interface
    //
    (*myBusInterface.InterfaceHeader.InterfaceDereference)(myBusInterface.InterfaceHeader.Context);