> dpc_data = WdfObjectContextGetObject(dpc);
this function takes an object *CONTEXT* (ie your DPC_DATA) and gives you the object the context is tied to (the WDFDPC in this case). You already have the object (WDFDPC), you probably want to get the associated context (DPC_DATA). You should call the accessor function specified in WDF_DECLARE_CONTEXT_TYPE_WITH_NAME to get the context pointer
WdfSpinLockAcquire(fdo_data->device_spin_lock);
You cannot acquire a spinlock in this way in an ISR. A normal spinlock can be acquired at an IRQL <= DISPATCH_LEVEL. Your ISR runs at DIRQL. If you need to synchronize with your ISR from a DPC or other function that runs at IRQL < DIRQL. That means you need to acquire the interrupt spinlock (WdfInterruptAcquireLock, WdfInterruptReleaseLock) in the DPC/other function and not in the ISR (which automatically holds the lock when calling your ISR, thus if you acquire, you will deadlock)
d
-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@gmail.com
Sent: Monday, October 8, 2012 8:57 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Multiport Ethernet Device
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);
}
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