📄 pnp.c
字号:
KeReleaseSpinLock(&deviceData->PriorityReceiver.ListSpinLock, oldIrql);
return;
}
NTSTATUS
SmscIrEvtDevicePrepareHardware(
IN WDFDEVICE Device,
IN WDFCMRESLIST ResourceList,
IN WDFCMRESLIST ResourceListTranslated
) {
/*++
Routine Description:
This entry point is called when hardware resources are assigned to one of
our devices.
Arguments:
Device - Handle to our WDFDEVICE object
Resources - WDFCMRESLIST of hardware resources assigned
to our device.
ResourcesTranslated - A WDFCMRESLIST of hardware resources
assigned to our device, made usable.
Return Value:
NTSTATUS
--*/
WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS wakeSettings;
PSMSCIR_DATA deviceData;
NTSTATUS status;
PCM_PARTIAL_RESOURCE_DESCRIPTOR resourceTrans;
ULONG i;
UNREFERENCED_PARAMETER(ResourceList);
deviceData = (PSMSCIR_DATA)GetIrData(Device);
SmscIrTracePrint(
TRACE_LEVEL_VERBOSE,
SMSCDBG_PNP_INFO,
("SmscIrEvtDevicePrepareHardware: Entered"));
for (i=0; i < WdfCmResourceListGetCount(ResourceListTranslated); i++) {
//
// Get the i'th partial resource descriptor from the list
//
resourceTrans = WdfCmResourceListGetDescriptor(ResourceListTranslated, i);
if(!resourceTrans){
SmscIrTracePrint(
TRACE_LEVEL_ERROR,
SMSCDBG_PNP_INFO,
("SmscIrEvtDevicePrepareHardware: NULL resource returned??"));
return(STATUS_DEVICE_CONFIGURATION_ERROR);
}
//
// Let's examine and store the resources, based on their type
//
// We expect to get a port (that we'll use to talk to the device)
// and an interrupt (for, ah, interrupts).
//
switch (resourceTrans->Type) {
case CmResourceTypePort:
SmscIrTracePrint(
TRACE_LEVEL_ERROR,
SMSCDBG_PNP_INFO,
("SmscIrEvtDevicePrepareHardware: "\
"Resource %d: Port 0x%0x, Length %d.",
i,
resourceTrans->u.Port.Start.LowPart,
resourceTrans->u.Port.Length));
//
// We have two port or memory resources, one for Rx and
// one for Tx
//
if (!deviceData->BaseAddress) {
//
// First time through, gotta be the Rx port
//
//
// Should be 8 bytes long...
//
ASSERT(resourceTrans->u.Port.Length == 8);
deviceData->BaseAddress =
(PUCHAR)UlongToPtr(resourceTrans->u.Port.Start.LowPart);
//
// Indicate that the port is, indeed, in "port space" on this
// machine. PortIsMapped is used by our READ_HARDWARE_UCHAR and
// WRITE_HARDWARE_UCHAR functions to determine which HAL
// function to call to do talk to the device.
//
deviceData->PortIsMapped = FALSE;
} else {
//
// Second time through...Gotta be the Tx port
//
ASSERT(resourceTrans->u.Port.Length == 8);
deviceData->TransmitBaseAddress =
(PUCHAR)UlongToPtr(resourceTrans->u.Port.Start.LowPart);
deviceData->TransmitPortIsMapped = FALSE;
}
break;
case CmResourceTypeMemory:
SmscIrTracePrint(
TRACE_LEVEL_ERROR,
SMSCDBG_PNP_INFO,
("SmscIrEvtDevicePrepareHardware: "\
"Resource %d: Register 0x%0x:%0x Length %d.",
i,
resourceTrans->u.Memory.Start.HighPart,
resourceTrans->u.Memory.Start.LowPart,
resourceTrans->u.Memory.Length));
//
// We're running on a system where our PORTS appear in memory
// space! It's rare, but it's certainly possible.
//
// What this means is that we have to (a) Map the memory
// range into kernel virtual address space, (b) remember to
// unmap this range later, and (c) write to these registers
// using the HAL "register" functions and not the "port"
// functions.
//
//
if (!deviceData->BaseAddress) {
ASSERT(resourceTrans->u.Port.Length == 8);
//
// Map the memory-mapped "port" into kernel virtual address
// space...
//
deviceData->BaseAddress =
(PUCHAR)MmMapIoSpace(resourceTrans->u.Memory.Start,
resourceTrans->u.Memory.Length,
MmNonCached);
//
// Indicate that the port is in "memory space" on this
// machine. PortIsMapped is used by our READ_HARDWARE_UCHAR
// and WRITE_HARDWARE_UCHAR functions to determine which HAL
// function to call to do talk to the device.
//
deviceData->PortIsMapped = TRUE;
} else {
deviceData->TransmitBaseAddress =
(PUCHAR)MmMapIoSpace(resourceTrans->u.Memory.Start,
resourceTrans->u.Memory.Length,
MmNonCached);
deviceData->TransmitPortIsMapped = TRUE;
}
break;
//
// We'll need to get an interrupt resource, but note that we don't
// have to DO anything with it. The Framework will actually remember
// what our interrupt resource is, and connect it for us using the
// WDFINTERRUPT that we created in EvtDeviceAdd.
//
case CmResourceTypeInterrupt:
SmscIrTracePrint(
TRACE_LEVEL_ERROR,
SMSCDBG_PNP_INFO,
("SmscIrEvtDevicePrepareHardware: "\
"Resource %d: Interrupt level: 0x%0x, Vector: 0x%0x",
i,
resourceTrans->u.Interrupt.Level,
resourceTrans->u.Interrupt.Vector));
break;
default:
//
// This could be device-private type added by the PCI bus driver.
// We shouldn't filter this or change the information contained
// in it.
//
SmscIrTracePrint(
TRACE_LEVEL_ERROR,
SMSCDBG_PNP_INFO,
("SmscIrEvtDevicePrepareHardware: "\
"Resource %d: Unhandled resource type 0x%0x",
i,
resourceTrans->Type));
break;
} // end of switch
} // end of for
ASSERT(deviceData->BaseAddress);
ASSERT(deviceData->TransmitBaseAddress);
//
// Init wait-wake policy structure. We assign default
// waking capability for the device.
//
WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS_INIT(&wakeSettings);
status = WdfDeviceAssignSxWakeSettings(Device, &wakeSettings);
if (!NT_SUCCESS(status)) {
SmscIrTracePrint(
TRACE_LEVEL_ERROR,
SMSCDBG_PNP_INFO,
("SmscIrEvtDevicePrepareHardware: "\
"WdfDeviceAssignSxWakeSettings failed with Status code 0x%x",
status));
return status;
}
SmscIrTracePrint(
TRACE_LEVEL_VERBOSE,
SMSCDBG_PNP_INFO,
("SmscIrEvtDevicePrepareHardware: Exit"));
return STATUS_SUCCESS;
}
NTSTATUS
SmscIrEvtDeviceReleaseHardware(
IN WDFDEVICE Device,
IN WDFCMRESLIST ResourceListTranslated
) {
/*++
Routine Description:
This function is called any time we need to release our hardware resources.
In WDM terms
Arguments:
Device - The usual handle to our WDFDEVICE
ResourcesTranslated - The resources we're giving up, in case we don't
remember what they are, I suppose.
Return Value:
NTSTATUS
--*/
PSMSCIR_DATA deviceData;
UNREFERENCED_PARAMETER(ResourceListTranslated);
SmscIrTracePrint(
TRACE_LEVEL_VERBOSE,
SMSCDBG_PNP_INFO,
("SmscIrEvtDevicePrepareHardware: Entered"));
deviceData = (PSMSCIR_DATA)GetIrData(Device);
//
// If we had mapped any shared-memory into kernel virtual address space
// during EvtPrepareHardware, we'd unmap it here. The only time for THIS
// hardware that this would be necessary is in the unlikely event that our
// PORTs were located in memory space on a machine.
//
if (deviceData->PortIsMapped) {
MmUnmapIoSpace(deviceData->BaseAddress, 8);
}
if (deviceData->TransmitPortIsMapped) {
MmUnmapIoSpace(deviceData->TransmitBaseAddress, 8);
}
//
// Reset the context locations we use to track info about our device's
// register.
//
deviceData->BaseAddress = NULL;
deviceData->PortIsMapped = FALSE;
SmscIrTracePrint(
TRACE_LEVEL_VERBOSE,
SMSCDBG_PNP_INFO,
("SmscIrEvtDevicePrepareHardware: Exit"));
return STATUS_SUCCESS;
}
NTSTATUS
SmscIrEvtDeviceD0Entry(
IN WDFDEVICE Device,
IN WDF_POWER_DEVICE_STATE PreviousState
)
/*++
Routine Description:
EvtDeviceD0Entry event callback must perform any operations that are
necessary before the specified device is used. It will be called every
time the hardware needs to be (re-)initialized.
Arguments:
Device - Handle to a framework device object.
PreviousState - Device power state which the device was in most recently.
If the device is being newly started, this will be
PowerDeviceUnspecified.
Return Value:
NTSTATUS
--*/
{
PSMSCIR_DATA deviceData;
deviceData = GetIrData(Device);
SmscIrTracePrint(
TRACE_LEVEL_VERBOSE,
SMSCDBG_PNP_INFO,
("SmscIrEvtDeviceD0Entry: Device is powering up from %d",
PreviousState));
if (SmscIrDeviceWokeSystem(deviceData)) {
SmscIrTracePrint(
TRACE_LEVEL_VERBOSE,
SMSCDBG_PNP_INFO,
("SmscIrEvtDeviceD0Entry: Device used to wake system. Marking "\
"user as present"));
PoSetSystemState(ES_USER_PRESENT);
} else {
SmscIrTracePrint(
TRACE_LEVEL_VERBOSE,
SMSCDBG_PNP_INFO,
("SmscIrEvtDeviceD0Entry: Device was NOT used to wake system"));
}
//
// Restart the queues.
//
WdfIoQueueStart(deviceData->PriorityReceiver.PendingReceiveQueue);
WdfIoQueueStart(deviceData->Receiver.PendingReceiveQueue);
return STATUS_SUCCESS;
}
NTSTATUS
SmscIrEvtDeviceD0Exit(
IN WDFDEVICE Device,
IN WDF_POWER_DEVICE_STATE TargetState
)
/*++
Routine Description:
This routine undoes anything done in EvtDeviceD0Entry. It is called
whenever the device leaves the D0 state, which happens when the device is
stopped, when it is removed, and when it is powered off.
The device is still in D0 when this callback is invoked, which means that
the driver can still touch hardware in this routine.
EvtDeviceD0Exit event callback must perform any operations that are
necessary before the specified device is moved out of the D0 state. If the
driver needs to save hardware state before the device is powered down, then
that should be done here.
Arguments:
Device - Handle to a framework device object.
TargetState - Device power state which the device will be put in once this
callback is complete.
Return Value:
Success implies that the device can be used. Failure will result in the
device stack being torn down.
--*/
{
UNREFERENCED_PARAMETER(Device);
SmscIrTracePrint(
TRACE_LEVEL_VERBOSE,
SMSCDBG_PNP_INFO,
("SmscIrEvtDeviceD0Exit: Device is powering down to 0x%x",
TargetState));
return STATUS_SUCCESS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -