Multiport Ethernet Device

If the underlying bus is queueing the dpc state with the pkdc, you are tearing state with what the wdfdpc thinks the state of the pkdc is. You are better off just declaring a KDPC without the wdf object so you don’t have the torn state.

d

debt from my phone


From: xxxxx@gmail.com
Sent: 10/1/2012 4:54 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Multiport Ethernet Device

I know it has something to do with my WDFDPC calls…I’m just not sure what. The parent device of the DPC object is the device object of the miniport driver, and I pass this DPC object to the bus driver, which enqueues it whenever a interrupt arrives for the miniport.

STATE

Miniport Running
Device PnP REMOVED
Datapath Normal
Operational status DORMANT
Operational flags 00000004 ? DORMANT_PAUSED
Admin status ADMIN_UP
Media Connected
Power D0
References 8
User Handles 0
Total Resets 0
Pending OID None
Flags 2c452208
? BUS_MASTER, SG_DMA, DEFAULT_PORT_ACTIVATED, SUPPORTS_MEDIA_SENSE,
DOES_NOT_DO_LOOPBACK, MEDIA_CONNECTED
PnPFlags 00200012
? VIRTUAL_DEVICE, REMOVE_IN_PROGRESS, HARDWARE_DEVICE


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

Doran,

When you say declaing a KDPC, what do you mean? I basically need a way to notify a child PDO of an interrupt (calling a child ISR). This works by creating a DPC in the PDO, and passing it to the bus driver. However, on teardown, my device gets stuck (the PDO), and does not disable. I know it has to do with my DPCs, but I don’t know how to solve the problem.

Directly, is there a way to call a PDO function from the bus driver?

Can you disable the child(miniport) from device manager?

On Tue, Oct 2, 2012 at 2:50 PM, wrote:

> Doran,
>
> When you say declaing a KDPC, what do you mean? I basically need a way to
> notify a child PDO of an interrupt (calling a child ISR). This works by
> creating a DPC in the PDO, and passing it to the bus driver. However, on
> teardown, my device gets stuck (the PDO), and does not disable. I know it
> has to do with my DPCs, but I don’t know how to solve the problem.
>
> Directly, is there a way to call a PDO function from the bus driver?
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>

No. That is the problem. The child (miniport) won’t disable with my current configuration. It just stalls (the device manager stalls), and it keeps receiving and processing interrupts (packets).

Are you absolutely sure you don’t have a tx packet stuck in the miniport
not being completed?

On Tue, Oct 2, 2012 at 4:02 PM, wrote:

> No. That is the problem. The child (miniport) won’t disable with my
> current configuration. It just stalls (the device manager stalls), and it
> keeps receiving and processing interrupts (packets).
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>

Ignoring this problem that query remove is hanging. You said you had a wdfdpc kmdf object, got the underlying kdpc pointer and sent that to the bus driver to queue on your behalf. That is not a good idea. The wdfdpc doesn’t know about the dpc state and can lead to weird race conditions and memory corruption during device deletion

d

debt from my phone


From: xxxxx@gmail.com
Sent: 10/2/2012 2:46 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Multiport Ethernet Device

Doran,

When you say declaing a KDPC, what do you mean? I basically need a way to notify a child PDO of an interrupt (calling a child ISR). This works by creating a DPC in the PDO, and passing it to the bus driver. However, on teardown, my device gets stuck (the PDO), and does not disable. I know it has to do with my DPCs, but I don’t know how to solve the problem.

Directly, is there a way to call a PDO function from the bus driver?


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

@Doran, where should I create the DPC then? I’m not sure how to create a DPC in the bus driver, that calls a function in the child device.

On 03-Oct-2012 22:48, xxxxx@gmail.com wrote:

I’m not sure how to create a DPC in the bus driver, that calls a function in the child device.

Why not? yes, create a DPC in the bus driver. How? read documentation.
Register a callback from the child. Call it from the bus driver.
Remember that KMDF objects should not cross the boundary between two
drivers. Do the proper locking when registering & unregistering the
callback.
– pa

Well, you have two choices

  1. use a KDPC in your function driver for the child device, not a WDFDPC. Add it as a field to your context on your WDFDEVICE

Or

  1. instead of sending down a KDPC pointer down the stack to the PDO you send your PKDEFERRED_ROUTINE DpcRoutine down the stack to the PDO and initialize the PDO’s DPC with this DpcRoutine

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@gmail.com
Sent: Wednesday, October 3, 2012 1:48 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Multiport Ethernet Device

@Doran, where should I create the DPC then? I’m not sure how to create a DPC in the bus driver, that calls a function in the child device.


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

When you say KDPC, what object is this (I looked for this before)?

Also, how would I send the DPC “up” the stack?

I see the KDPC is created by the framework when I call WdfDpcCreate. Are you saying pass this from the bus driver to the child device?

xxxxx@gmail.com wrote:

When you say KDPC, what object is this (I looked for this before)?

Where did you look? It’s the second hit on Google.

The KDPC is the actual kernel structure that represents a DPC. WDFDPC
is just KMDF’s wrapper around the native KDPC structure.

Also, how would I send the DPC “up” the stack?

Why do you need to? The issue, as I understand it, is that you need a
lower driver to fire a DPC in an upper driver. The alternatives have
been shared with you already.

  1. Create the WDFDPC in the upper driver. Use WdfDpcWdmGetDpc to fetch
    the embedded PKDPC, and pass that to the bus driver for firing.

  2. Call KeInitializeDpc instead of using the KMDF wrapper. Pass the
    PKDPC down to the bus driver as above.

  3. Pass the DPC function address down to the bus driver, and let it
    create and queue the DPC.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Option 1) you list below is not kosher. You are manipulating the KDPC state behind the WDFDPC object’s back, leading to torn state. This is completely untested. I have been repeatedly saying this in every reply to this thread.

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Tim Roberts
Sent: Wednesday, October 3, 2012 2:33 PM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Multiport Ethernet Device

xxxxx@gmail.com wrote:

When you say KDPC, what object is this (I looked for this before)?

Where did you look? It’s the second hit on Google.

The KDPC is the actual kernel structure that represents a DPC. WDFDPC is just KMDF’s wrapper around the native KDPC structure.

Also, how would I send the DPC “up” the stack?

Why do you need to? The issue, as I understand it, is that you need a lower driver to fire a DPC in an upper driver. The alternatives have been shared with you already.

  1. Create the WDFDPC in the upper driver. Use WdfDpcWdmGetDpc to fetch the embedded PKDPC, and pass that to the bus driver for firing.

  2. Call KeInitializeDpc instead of using the KMDF wrapper. Pass the PKDPC down to the bus driver as above.

  3. Pass the DPC function address down to the bus driver, and let it create and queue the DPC.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

Respected gurus, you’ve already beaten the OP into high impedance state.
It shouldn’t be this complicated.

  1. The bus driver defines an interface with 2 functions: register
    callback and unregister callback.
    The child driver gets it using QI (WDF or WDM flavor).

  2. Then the child driver calls the bus driver to register its callback,
    with some context ptr or data meaningful to both.
    It isn’t a system-defined DPC routine.
    The OP should decide whether to let each child device instance to
    register a callback, or the child driver will register one callback and
    poll all its devices internally.

  3. The bus driver connects to the system interrupt, defines its own DPC,
    and opens the hardware interrupt. When the interrupt fires, it queues
    this DPC as usual (WDF or WDM, whatever).
    The DPC calls the callback (if it is still registered - proper sync with
    register/unregister routines is needed here).

that’s all…

Regards,
– pa

Thanks

Thanks Pavel. Final question, what’s the best way to pass context info with a DPC?

  1. the child device “registers” and interrupt by passing a pointer to its callback function, and a ptr to its mini port adapter context.
  2. the bus driver creates a DPC with this callback, and stores the context info pass to it in the DPC’s context area I created.

Whenever the DPC is called, the child device successfully calls the callback function. However, when I access the context of the DPC with the access function, NULL is returned.

Post your dpc init and queue code

d

debt from my phone


From: xxxxx@gmail.com
Sent: 10/5/2012 11:48 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Multiport Ethernet Device

Thanks Pavel. Final question, what’s the best way to pass context info with a DPC?

  1. the child device “registers” and interrupt by passing a pointer to its callback function, and a ptr to its mini port adapter context.
  2. the bus driver creates a DPC with this callback, and stores the context info pass to it in the DPC’s context area I created.

Whenever the DPC is called, the child device successfully calls the callback function. However, when I access the context of the DPC with the access function, NULL is returned.


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

Here is my code…

---- BUS CODE ----

BOOLEAN bus_interrupt_isr(
IN WDFINTERRUPT Interrupt,
IN ULONG MessageID
)
{
PFDO_DEVICE_DATA fdo_data = NULL;
ULONG port_number;
ULONG imask;
ULONG ievent;
PVOID bar_address;
BOOLEAN enqueue_state;

UNREFERENCED_PARAMETER(MessageID);

fdo_data = fdo_get_data(WdfInterruptGetDevice(Interrupt));

WdfSpinLockAcquire(fdo_data->device_spin_lock);
// Send interrupt to each port
for (port_number = 1;port_number <= NUM_OF_PORTS;port_number++)
{
// Don’t do anything if interrupt is not registered for port
if (fdo_data->dpc_list[port_number-1] == NULL)
{
continue;
}

// Compute bar0 address for each port
bar_address =
(PUCHAR)(ULONG_PTR)fdo_data->pci_bus_info.pci_bar0_virtual +
((port_number - 1) * fdo_data->pci_bus_info.pci_bar0_length);

imask = READ_REGISTER_ULONG((PULONG)((PUCHAR)bar_address + IMASK_OFFSET));
ievent = READ_REGISTER_ULONG((PULONG)((PUCHAR)bar_address + IEVENT_OFFSET));

if (imask && ievent)
{
// Disable Interrupts
WRITE_REGISTER_ULONG((PULONG)((PUCHAR)bar_address + IMASK_OFFSET), 0);

// Queue DPC in miniport (upper edge)
ASSERT(fdo_data->dpc_list[port_number-1]);
enqueue_state = WdfDpcEnqueue(fdo_data->dpc_list[port_number-1]);
}
}

WdfSpinLockRelease(fdo_data->device_spin_lock);
// Acknowledge the interrupt(s)
return TRUE;
}

BOOLEAN register_interrupt(
IN WDFDEVICE child_device,
IN PVOID context,
IN PFN_WDF_DPC callback
)
{
PPDO_DEVICE_DATA pdo_data = NULL;
PFDO_DEVICE_DATA fdo_data = NULL;
NTSTATUS status = STATUS_SUCCESS;
BOOLEAN ret_val = TRUE;
WDF_OBJECT_ATTRIBUTES attributes;
WDF_DPC_CONFIG dpc_config;
PDPC_DATA dpc_data;
WDFDPC isr_dpc;

pdo_data = pdo_get_data(child_device);

fdo_data = fdo_get_data(pdo_data->bus_device);

// Initialize DPC data
WDF_DPC_CONFIG_INIT(&dpc_config, callback);
dpc_config.AutomaticSerialization = TRUE;

WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DPC_DATA);
attributes.ParentObject = pdo_data->bus_device;
status = WdfDpcCreate(&dpc_config, &attributes, &isr_dpc);
if (!NT_SUCCESS(status))
{
ret_val = FALSE;
}
else
{
dpc_data = dpc_get_data(isr_dpc);
dpc_data->context = context;
WdfSpinLockAcquire(fdo_data->device_spin_lock);
fdo_data->dpc_list[pdo_data->port_number-1] = isr_dpc;
WdfSpinLockRelease(fdo_data->device_spin_lock);
}

return ret_val;
}

---- MINIPORT CODE ----
VOID dpc_handler(
IN WDFDPC dpc
)
{
PDPC_DATA dpc_data;
PSEL_ETHLITE_ADAPTER adapter;
PSEL_ETHLITE_ISR_INFO info;
ULONG event;

// ASSUMPTIONS: interrupts have been disabled

dpc_data = WdfObjectContextGetObject(dpc);

ASSERT(dpc_data != NULL); <– THIS FAILS

adapter = dpc_data->context;

info = &(adapter->isr);
}

correction on the miniport code
–>
dpc_data = WdfObjectGetTypedContext(dpc, DPC_DATA);

ASSERT(dpc_data != NULL);

A KMDF driver doesn’t typically call WdfObjectGetTypedContext directly. Rather you declare an accessor function which is typesafe (WdfObjectGetTypedContext is not) and requires one less parameter

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@gmail.com
Sent: Monday, October 8, 2012 9:17 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Multiport Ethernet Device

correction on the miniport code
–>
dpc_data = WdfObjectGetTypedContext(dpc, DPC_DATA);

ASSERT(dpc_data != NULL);


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer