windows-nt/Source/XPSP1/NT/drivers/input/inport/i386/pnppower.c

1120 lines
34 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
pnp.c
Abstract:
This module contains plug & play code for the inport mouse
Environment:
Kernel & user mode.
Revision History:
Feb-1998 : Initial writing, Doron Holan
--*/
#include "inport.h"
#include "inplog.h"
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, InportAddDevice)
#pragma alloc_text(PAGE, InportPnP)
#endif
NTSTATUS
InportAddDevice (
IN PDRIVER_OBJECT Driver,
IN PDEVICE_OBJECT PDO
)
/*++
Routine Description:
Arguments:
Return Value:
NTSTATUS result code.
--*/
{
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_EXTENSION deviceExtension;
PDEVICE_OBJECT device;
PAGED_CODE();
status = IoCreateDevice(Driver,
sizeof(DEVICE_EXTENSION),
NULL, // no name for this Filter DO
FILE_DEVICE_INPORT_PORT,
0,
FALSE,
&device);
if (!NT_SUCCESS(status)) {
return status;
}
deviceExtension = (PDEVICE_EXTENSION) device->DeviceExtension;
//
// Initialize the fields.
//
RtlZeroMemory(deviceExtension, sizeof(DEVICE_EXTENSION));
deviceExtension->TopOfStack = IoAttachDeviceToDeviceStack(device, PDO);
if (deviceExtension->TopOfStack == NULL) {
PIO_ERROR_LOG_PACKET errorLogEntry;
//
// Not good; in only extreme cases will this fail
//
errorLogEntry = (PIO_ERROR_LOG_PACKET)
IoAllocateErrorLogEntry(Driver,
(UCHAR) sizeof(IO_ERROR_LOG_PACKET));
if (errorLogEntry) {
errorLogEntry->ErrorCode = INPORT_ATTACH_DEVICE_FAILED;
errorLogEntry->DumpDataSize = 0;
errorLogEntry->SequenceNumber = 0;
errorLogEntry->MajorFunctionCode = 0;
errorLogEntry->IoControlCode = 0;
errorLogEntry->RetryCount = 0;
errorLogEntry->UniqueErrorValue = 0;
errorLogEntry->FinalStatus = STATUS_DEVICE_NOT_CONNECTED;
IoWriteErrorLogEntry(errorLogEntry);
}
IoDeleteDevice(device);
return STATUS_DEVICE_NOT_CONNECTED;
}
ASSERT(deviceExtension->TopOfStack);
deviceExtension->Self = device;
deviceExtension->Removed = FALSE;
deviceExtension->Started = FALSE;
deviceExtension->UnitId = 0;
IoInitializeRemoveLock (&deviceExtension->RemoveLock, INP_POOL_TAG, 1, 10);
#if defined(NEC_98)
deviceExtension->PowerState = PowerDeviceD0;
#endif // defined(NEC_98)
//
// Initialize WMI
//
deviceExtension->WmiLibInfo.GuidCount = sizeof(WmiGuidList) /
sizeof(WMIGUIDREGINFO);
deviceExtension->WmiLibInfo.GuidList = WmiGuidList;
deviceExtension->WmiLibInfo.QueryWmiRegInfo = InportQueryWmiRegInfo;
deviceExtension->WmiLibInfo.QueryWmiDataBlock = InportQueryWmiDataBlock;
deviceExtension->WmiLibInfo.SetWmiDataBlock = InportSetWmiDataBlock;
deviceExtension->WmiLibInfo.SetWmiDataItem = InportSetWmiDataItem;
deviceExtension->WmiLibInfo.ExecuteWmiMethod = NULL;
deviceExtension->WmiLibInfo.WmiFunctionControl = NULL;
IoWMIRegistrationControl(deviceExtension->Self,
WMIREG_ACTION_REGISTER
);
deviceExtension->PDO = PDO;
device->Flags &= ~DO_DEVICE_INITIALIZING;
device->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
return status;
}
BOOLEAN
InpReleaseResourcesEx(
PVOID Context
)
{
PDEVICE_EXTENSION deviceExtension = Context;
KeRemoveQueueDpc(&deviceExtension->IsrDpc);
KeRemoveQueueDpc(&deviceExtension->IsrDpcRetry);
KeRemoveQueueDpc(&deviceExtension->ErrorLogDpc);
// KeCancelTimer(&deviceExtension->DataConsumptionTimer);
if (deviceExtension->Configuration.UnmapRegistersRequired) {
MmUnmapIoSpace(deviceExtension->Configuration.DeviceRegisters[0],
deviceExtension->Configuration.PortList[0].u.Port.Length);
}
//
// Clear out the config info. If we get started again, than it will be filled
// in again. If is from a remove, then it is essentially a no-op
//
RtlZeroMemory(&deviceExtension->Configuration,
sizeof(INPORT_CONFIGURATION_INFORMATION));
return TRUE;
}
VOID
InpReleaseResources(
PDEVICE_EXTENSION DeviceExtension
)
{
InpPrint((2, "INPORT-InpReleaseResources: Enter\n"));
if (DeviceExtension->InterruptObject) {
KeSynchronizeExecution(
DeviceExtension->InterruptObject,
InpReleaseResourcesEx,
(PVOID) DeviceExtension);
IoDisconnectInterrupt(DeviceExtension->InterruptObject);
DeviceExtension->InterruptObject = NULL;
}
else {
InpReleaseResourcesEx((PVOID) DeviceExtension);
}
InpPrint((2, "INPORT-InpReleaseResources: Exit\n"));
}
NTSTATUS
InpPnPComplete (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
/*++
Routine Description:
The pnp IRP is in the process of completing.
signal
Arguments:
Context set to the device object in question.
--*/
{
PIO_STACK_LOCATION stack;
NTSTATUS status;
PKEVENT event;
InpPrint((2, "INPORT-InpPnPComplete: Enter\n"));
status = STATUS_SUCCESS;
event = (PKEVENT) Context;
stack = IoGetCurrentIrpStackLocation(Irp);
if (Irp->PendingReturned) {
IoMarkIrpPending(Irp);
}
KeSetEvent(event,
0,
FALSE);
InpPrint((2, "INPORT-InpPnPComplete: Exit\n"));
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
InportPnP (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
The plug and play dispatch routines.
Most of these this filter driver will completely ignore.
In all cases it must pass on the IRP to the lower driver.
Arguments:
DeviceObject - pointer to a device object.
Irp - pointer to an I/O Request Packet.
Return Value:
NT status code
--*/
{
PDEVICE_EXTENSION deviceExtension;
PIO_STACK_LOCATION stack;
NTSTATUS status;
KEVENT event;
PAGED_CODE();
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
stack = IoGetCurrentIrpStackLocation(Irp);
status = IoAcquireRemoveLock(&deviceExtension->RemoveLock, Irp);
if (!NT_SUCCESS(status)) {
//
// Someone gave us a pnp irp after a remove. Unthinkable!
//
ASSERT(FALSE);
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
InpPrint((2, "INPORT-InportPnP: Enter (min func=0x%x)\n", stack->MinorFunction));
switch (stack->MinorFunction) {
case IRP_MN_START_DEVICE:
#if defined(NEC_98)
Globals.DeviceObject = (PDEVICE_OBJECT)DeviceObject;
#endif // defined(NEC_98)
//
// If we have been started (and not stopped), then just ignore this start
//
if (deviceExtension->Started) {
IoSkipCurrentIrpStackLocation(Irp);
status = IoCallDriver(deviceExtension->TopOfStack, Irp);
break;
}
//
// Not allowed to touch the hardware until all of the lower DO's have
// had a chance to look at it
//
IoCopyCurrentIrpStackLocationToNext(Irp);
KeInitializeEvent(&event,
NotificationEvent,
FALSE
);
IoSetCompletionRoutine(Irp,
(PIO_COMPLETION_ROUTINE) InpPnPComplete,
&event,
TRUE,
TRUE,
TRUE);
status = IoCallDriver(deviceExtension->TopOfStack, Irp);
if (STATUS_PENDING == status) {
KeWaitForSingleObject(
&event,
Executive, // Waiting for reason of a driver
KernelMode, // Waiting in kernel mode
FALSE, // No alert
NULL); // No timeout
}
if (NT_SUCCESS (status) && NT_SUCCESS (Irp->IoStatus.Status)) {
status = InpStartDevice(
DeviceObject->DeviceExtension,
stack->Parameters.StartDevice.AllocatedResourcesTranslated);
if (NT_SUCCESS(status)) {
deviceExtension->Started = TRUE;
}
}
//
// We must now complete the IRP, since we stopped it in the
// completetion routine with MORE_PROCESSING_REQUIRED.
//
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = 0;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
break;
//
// PnP rules dictate we send the IRP down to the PDO first
//
case IRP_MN_CANCEL_REMOVE_DEVICE:
case IRP_MN_CANCEL_STOP_DEVICE:
status = InpSendIrpSynchronously(deviceExtension->TopOfStack, Irp);
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
break;
case IRP_MN_REMOVE_DEVICE:
//
// The PlugPlay system has dictacted the removal of this device. We
// have no choise but to detach and delete the device objecct.
// (If we wanted to express and interest in preventing this removal,
// we should have filtered the query remove and query stop routines.)
//
// Note! we might receive a remove WITHOUT first receiving a stop.
//
InpPrint((2, "INPORT-InportPnP: remove device \n"));
deviceExtension->Removed = TRUE;
//
// Here if we had any outstanding requests in a personal queue we should
// complete them all now.
//
// Note, the device could be GONE so we cannot send it any non-
// PNP IRPS.
//
InpReleaseResources(deviceExtension);
//
// Perform specific operations for a remove
//
IoWMIRegistrationControl(deviceExtension->Self,
WMIREG_ACTION_DEREGISTER
);
//
// Send on the remove IRP
//
IoSkipCurrentIrpStackLocation(Irp);
status = IoCallDriver(deviceExtension->TopOfStack, Irp);
//
// Wait for the remove lock to free.
//
IoReleaseRemoveLockAndWait(&deviceExtension->RemoveLock, Irp);
IoDetachDevice(deviceExtension->TopOfStack);
IoDeleteDevice(deviceExtension->Self);
InpPrint((2, "INPORT-InportPnP: exit (%x)\n", STATUS_SUCCESS));
return STATUS_SUCCESS;
// NOTE:
// handle this case if you want to add/remove resources that will be given
// during start device. Add resources before passing the irp down.
// Remove resources when the irp is coming back up
// See dd\input\pnpi8042\pnp.c, I8xFilterResourceRequirements for an example
case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
#if !defined(NEC_98)
status = InpSendIrpSynchronously(deviceExtension->TopOfStack, Irp);
//
// If the lower filter does not support this Irp, this is
// OK, we can ignore this error
//
if (status == STATUS_NOT_SUPPORTED) {
status = STATUS_SUCCESS;
}
InpFilterResourceRequirements(DeviceObject, Irp);
if (!NT_SUCCESS(status)) {
InpPrint((2, "error pending filter res req event (0x%x)\n", status));
}
//
// Irp->IoStatus.Information will contain the new i/o resource
// requirements list so leave it alone
//
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
break;
#else
InpPrint((2, "INPORT-InportPnP: IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n"));
#endif
case IRP_MN_QUERY_REMOVE_DEVICE:
case IRP_MN_QUERY_STOP_DEVICE:
#if defined(NEC_98)
//
// Don't let either of the requests succeed, otherwise the mouse might be rendered useless.
//
status = STATUS_UNSUCCESSFUL;
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
break;
#endif
case IRP_MN_STOP_DEVICE:
case IRP_MN_QUERY_DEVICE_RELATIONS:
case IRP_MN_QUERY_INTERFACE:
case IRP_MN_QUERY_CAPABILITIES:
case IRP_MN_QUERY_DEVICE_TEXT:
case IRP_MN_QUERY_RESOURCES:
case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
case IRP_MN_READ_CONFIG:
case IRP_MN_WRITE_CONFIG:
case IRP_MN_EJECT:
case IRP_MN_SET_LOCK:
case IRP_MN_QUERY_ID:
case IRP_MN_QUERY_PNP_DEVICE_STATE:
default:
//
// Here the filter driver might modify the behavior of these IRPS
// Please see PlugPlay documentation for use of these IRPs.
//
IoSkipCurrentIrpStackLocation(Irp);
status = IoCallDriver(deviceExtension->TopOfStack, Irp);
break;
}
IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp);
InpPrint((2, "INPORT-InportPnP: exit (%x)\n", status));
return status;
}
NTSTATUS
InportPower (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
NOTE:
You must write power code!!!
System power irps can be ignored.
Device power irps will be sent by mouclass. The transition from D0 to some
lower usually involves doing nothing (maybe power down h/w if you have control
over this). The transition from a lower power state to D0 must be handled by
reinitializing the device.
Please read http://titanic for Power documentation (especially on the use
of PoCallDriver and PoStartNextPowerIrp)
--*/
{
PIO_STACK_LOCATION stack;
NTSTATUS status;
PDEVICE_EXTENSION deviceExtension;
POWER_STATE powerState;
POWER_STATE_TYPE powerType;
InpPrint((2, "INPORT-InportPower: Enter\n"));
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
stack = IoGetCurrentIrpStackLocation(Irp);
powerType = stack->Parameters.Power.Type;
powerState = stack->Parameters.Power.State;
status = IoAcquireRemoveLock(&deviceExtension->RemoveLock, Irp);
if (!NT_SUCCESS(status)) {
PoStartNextPowerIrp(Irp);
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
switch (stack->MinorFunction) {
case IRP_MN_SET_POWER:
InpPrint((2, "INPORT-InportPower: Power Setting %s state to %d\n",
((powerType == SystemPowerState) ? "System"
: "Device"),
powerState.SystemState));
#if defined(NEC_98)
//
// Don't handle anything but DevicePowerState changes
//
if (stack->Parameters.Power.Type != DevicePowerState) {
InpPrint((2,"INPORT-InportPower: not a device power irp\n"));
break;
}
//
// Check for no change in state, and if none, do nothing
//
if (stack->Parameters.Power.State.DeviceState ==
deviceExtension->PowerState) {
InpPrint((2,"INPORT-InportPower: no change in state (PowerDeviceD%d)\n",
deviceExtension->PowerState-1
));
break;
}
switch (stack->Parameters.Power.State.DeviceState) {
case PowerDeviceD0:
InpPrint((2,"INPORT-InportPower: Powering up to PowerDeviceD0\n"));
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp,
InportPowerUpToD0Complete,
NULL,
TRUE, // on success
TRUE, // on error
TRUE // on cancel
);
//
// PoStartNextPowerIrp() gets called in InportPowerUpToD0Complete
//
return PoCallDriver(deviceExtension->TopOfStack, Irp);
case PowerDeviceD1:
case PowerDeviceD2:
case PowerDeviceD3:
InpPrint((
2,"INPORT-InportPower: Powering down to PowerDeviceD%d\n",
stack->Parameters.Power.State.DeviceState-1
));
PoSetPowerState(DeviceObject,
stack->Parameters.Power.Type,
stack->Parameters.Power.State
);
deviceExtension->PowerState = stack->Parameters.Power.State.DeviceState;
//
// For what we are doing, we don't need a completion routine
// since we don't race on the power requests.
//
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCopyCurrentIrpStackLocationToNext(Irp);
PoStartNextPowerIrp(Irp);
return PoCallDriver(deviceExtension->TopOfStack, Irp);
default:
InpPrint((2,"INPORT-InportPower: unknown state\n"));
break;
}
break;
#else // defined(NEC_98)
break;
#endif // defined(NEC_98)
case IRP_MN_QUERY_POWER:
InpPrint((2, "INPORT-InportPower: Power query %s status to %d\n",
((powerType == SystemPowerState) ? "System"
: "Device"),
powerState.SystemState));
break;
default:
InpPrint((2, "INPORT-InportPower: Power minor (0x%x) no known\n", stack->MinorFunction));
}
PoStartNextPowerIrp(Irp);
IoSkipCurrentIrpStackLocation(Irp);
PoCallDriver(deviceExtension->TopOfStack, Irp);
IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp);
InpPrint((2, "INPORT-InportPower: Exit\n"));
return STATUS_SUCCESS;
}
#if !defined(NEC_98)
VOID
InpFilterResourceRequirements(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Iterates through the resource requirements list contained in the IRP and removes
any duplicate requests for I/O ports. (This is a common problem on the Alphas.)
No removal is performed if more than one resource requirements list is present.
Arguments:
DeviceObject - A pointer to the device object
Irp - A pointer to the request packet which contains the resource req. list.
Return Value:
None.
--*/
{
NTSTATUS status;
PDEVICE_EXTENSION deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
PCM_RESOURCE_LIST AllocatedResources;
PIO_RESOURCE_REQUIREMENTS_LIST pReqList = NULL,
newReqList = NULL;
PIO_RESOURCE_LIST pResList = NULL,
pNewResList = NULL;
PIO_RESOURCE_DESCRIPTOR pResDesc = NULL,
pNewResDesc = NULL;
ULONG i = 0, reqCount, size = 0;
BOOLEAN foundInt = FALSE, foundPorts = FALSE;
PIO_STACK_LOCATION stack;
INTERFACE_TYPE interfaceType = Isa;
ULONG busNumber = 0;
CONFIGURATION_TYPE controllerType = PointerController;
CONFIGURATION_TYPE peripheralType = PointerPeripheral;
PAGED_CODE();
ASSERT(DeviceObject);
ASSERT(DeviceObject->DeviceExtension);
InpPrint((1, "Received IRP_MN_FILTER_RESOURCE_REQUIREMENTS for Inport\n"));
stack = IoGetCurrentIrpStackLocation(Irp);
//
// The list can be in either the information field, or in the current
// stack location. The Information field has a higher precedence over
// the stack location.
//
if (Irp->IoStatus.Information == 0) {
pReqList =
stack->Parameters.FilterResourceRequirements.IoResourceRequirementList;
Irp->IoStatus.Information = (ULONG_PTR) pReqList;
}
else {
pReqList = (PIO_RESOURCE_REQUIREMENTS_LIST) Irp->IoStatus.Information;
}
if (!pReqList) {
//
// Not much can be done here except return
//
InpPrint((1, "NULL resource list in InpFilterResourceRequirements\n"));
return;
}
ASSERT(Irp->IoStatus.Information != 0);
ASSERT(pReqList != 0);
reqCount = pReqList->AlternativeLists;
//
// Only one AlternativeList is supported. If there is more than one list,
// then there is now way of knowing which list will be chosen. Also, if
// there are multiple lists, then chances are that a list with no i/o port
// conflicts will be chosen.
//
if (reqCount > 1) {
return;
}
pResList = &pReqList->List[0];
for (i = 0; i < pResList->Count; i++) {
pResDesc = &pResList->Descriptors[i];
switch (pResDesc->Type) {
case CmResourceTypePort:
foundPorts = TRUE;
break;
case CmResourceTypeInterrupt:
foundInt = TRUE;
break;
default:
break;
}
}
if (!foundPorts && !foundInt)
size = pReqList->ListSize + 2 * sizeof(IO_RESOURCE_DESCRIPTOR);
else if (!foundPorts || !foundInt)
size = pReqList->ListSize + sizeof(IO_RESOURCE_DESCRIPTOR);
else {
//
// Nothing to filter, just leave
//
ASSERT(foundPorts);
ASSERT(foundInt);
return;
}
ASSERT(size != 0);
newReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)
ExAllocatePool(
NonPagedPool,
size
);
if (!newReqList) {
return;
}
//
// Clear out the newly allocated list
//
RtlZeroMemory(newReqList,
size
);
//
// Copy the entire old list
//
RtlCopyMemory(newReqList,
pReqList,
pReqList->ListSize
);
pResList = &newReqList->List[0];
if (!foundPorts) {
pResDesc = &pResList->Descriptors[pResList->Count++];
pResDesc->Type = CmResourceTypePort;
}
if (!foundInt) {
pResDesc = &pResList->Descriptors[pResList->Count++];
pResDesc->Type = CmResourceTypeInterrupt;
}
pResList = &newReqList->List[0];
interfaceType = Isa;
status = IoQueryDeviceDescription(
&interfaceType,
&busNumber,
&controllerType,
NULL,
&peripheralType,
NULL,
InpFindResourcesCallout,
(PVOID) pResList
);
if (!NT_SUCCESS(status)) { // fill in with defaults
PINPORT_CONFIGURATION_INFORMATION configuration = &deviceExtension->Configuration;
ULONG InterruptLevel;
InpPrint((1, "Failed IoQueryDeviceDescription, status = 0x%x\n...try the registry...\n", status));
InpServiceParameters(deviceExtension,
&Globals.RegistryPath);
InterruptLevel = configuration->MouseInterrupt.u.Interrupt.Level;
pResList = &newReqList->List[0];
for (i = 0; i < pResList->Count; i++) {
pResDesc = &pResList->Descriptors[i];
switch (pResDesc->Type) {
case CmResourceTypePort:
if (foundPorts) break;
pResDesc->Option = 0; // fixed resources
pResDesc->ShareDisposition = INPORT_REGISTER_SHARE? CmResourceShareShared:CmResourceShareDeviceExclusive;
pResDesc->Flags = CM_RESOURCE_PORT_IO;
pResDesc->u.Port.Length = INP_DEF_PORT_SPAN;
pResDesc->u.Port.Alignment = 1;
pResDesc->u.Port.MinimumAddress.HighPart = 0;
pResDesc->u.Port.MinimumAddress.LowPart = INP_DEF_PORT;
pResDesc->u.Port.MaximumAddress.HighPart = 0;
pResDesc->u.Port.MaximumAddress.LowPart = INP_DEF_PORT+INP_DEF_PORT_SPAN-1;
break;
case CmResourceTypeInterrupt:
if (foundInt) break;
pResDesc->Option = 0; // fixed resources
pResDesc->ShareDisposition = INPORT_REGISTER_SHARE? CmResourceShareShared:CmResourceShareDeviceExclusive;
pResDesc->Flags = CM_RESOURCE_INTERRUPT_LATCHED; //Isa
pResDesc->u.Interrupt.MinimumVector = InterruptLevel;
pResDesc->u.Interrupt.MaximumVector = InterruptLevel;
break;
default:
break;
}
}
}
newReqList->ListSize = size;
//
// Free the old list and place the new one in its place
//
ExFreePool(pReqList);
stack->Parameters.FilterResourceRequirements.IoResourceRequirementList =
newReqList;
Irp->IoStatus.Information = (ULONG_PTR) newReqList;
}
NTSTATUS
InpFindResourcesCallout(
IN PVOID Context,
IN PUNICODE_STRING PathName,
IN INTERFACE_TYPE BusType,
IN ULONG BusNumber,
IN PKEY_VALUE_FULL_INFORMATION *BusInformation,
IN CONFIGURATION_TYPE ControllerType,
IN ULONG ControllerNumber,
IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation,
IN CONFIGURATION_TYPE PeripheralType,
IN ULONG PeripheralNumber,
IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation
)
/*++
Routine Description:
This is the callout routine sent as a parameter to
IoQueryDeviceDescription. It grabs the keyboard controller and
peripheral configuration information.
Arguments:
Context - Context parameter that was passed in by the routine
that called IoQueryDeviceDescription.
PathName - The full pathname for the registry key.
BusType - Bus interface type (Isa, Eisa, Mca, etc.).
BusNumber - The bus sub-key (0, 1, etc.).
BusInformation - Pointer to the array of pointers to the full value
information for the bus.
ControllerType - The controller type (should be KeyboardController).
ControllerNumber - The controller sub-key (0, 1, etc.).
ControllerInformation - Pointer to the array of pointers to the full
value information for the controller key.
PeripheralType - The peripheral type (should be KeyboardPeripheral).
PeripheralNumber - The peripheral sub-key.
PeripheralInformation - Pointer to the array of pointers to the full
value information for the peripheral key.
Return Value:
None. If successful, will have the following side-effects:
- Sets DeviceObject->DeviceExtension->HardwarePresent.
- Sets configuration fields in
DeviceObject->DeviceExtension->Configuration.
--*/
{
PUCHAR controllerData;
NTSTATUS status = STATUS_UNSUCCESSFUL;
ULONG i,
listCount,
portCount = 0;
PIO_RESOURCE_LIST pResList = (PIO_RESOURCE_LIST) Context;
PIO_RESOURCE_DESCRIPTOR pResDesc;
PKEY_VALUE_FULL_INFORMATION controllerInfo = NULL;
PCM_PARTIAL_RESOURCE_DESCRIPTOR resourceDescriptor, PortResDesc = NULL, IntResDesc = NULL;
BOOLEAN foundInt = FALSE,
foundPorts = FALSE;
PAGED_CODE();
UNREFERENCED_PARAMETER(PathName);
UNREFERENCED_PARAMETER(BusType);
UNREFERENCED_PARAMETER(BusNumber);
UNREFERENCED_PARAMETER(BusInformation);
UNREFERENCED_PARAMETER(ControllerType);
UNREFERENCED_PARAMETER(ControllerNumber);
UNREFERENCED_PARAMETER(PeripheralType);
UNREFERENCED_PARAMETER(PeripheralNumber);
UNREFERENCED_PARAMETER(PeripheralInformation);
pResDesc = pResList->Descriptors + pResList->Count;
controllerInfo = ControllerInformation[IoQueryDeviceConfigurationData];
InpPrint((2, "InpFindPortCallout enter\n"));
if (controllerInfo->DataLength != 0) {
controllerData = ((PUCHAR) controllerInfo) + controllerInfo->DataOffset;
controllerData += FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR,
PartialResourceList);
listCount = ((PCM_PARTIAL_RESOURCE_LIST) controllerData)->Count;
resourceDescriptor =
((PCM_PARTIAL_RESOURCE_LIST) controllerData)->PartialDescriptors;
for (i = 0; i < listCount; i++, resourceDescriptor++) {
switch(resourceDescriptor->Type) {
case CmResourceTypePort:
PortResDesc = resourceDescriptor;
break;
case CmResourceTypeInterrupt:
IntResDesc = resourceDescriptor;
break;
default:
break;
}
}
}
for (i = 0; i < pResList->Count; i++) {
pResDesc = &pResList->Descriptors[i];
switch (pResDesc->Type) {
case CmResourceTypePort:
if (PortResDesc) {
resourceDescriptor = PortResDesc;
pResDesc->Option = 0; // fixed resources
pResDesc->ShareDisposition = INPORT_REGISTER_SHARE? CmResourceShareShared:CmResourceShareDeviceExclusive;
pResDesc->Flags = CM_RESOURCE_PORT_IO;
pResDesc->u.Port.Alignment = 1;
pResDesc->u.Port.Length = INP_DEF_PORT_SPAN;
pResDesc->u.Port.MinimumAddress.QuadPart =
resourceDescriptor->u.Port.Start.QuadPart;
pResDesc->u.Port.MaximumAddress.QuadPart =
pResDesc->u.Port.MinimumAddress.QuadPart +
pResDesc->u.Port.Length - 1;
}
break;
case CmResourceTypeInterrupt:
if (IntResDesc) {
resourceDescriptor = IntResDesc;
pResDesc->Option = 0; // fixed resources
pResDesc->ShareDisposition = INPORT_REGISTER_SHARE? CmResourceShareShared:CmResourceShareDeviceExclusive;
pResDesc->Flags = CM_RESOURCE_INTERRUPT_LATCHED; //Isa
pResDesc->u.Interrupt.MinimumVector = resourceDescriptor->u.Interrupt.Level;
pResDesc->u.Interrupt.MaximumVector = resourceDescriptor->u.Interrupt.Level;
}
break;
default:
break;
}
}
if (PortResDesc && IntResDesc)
status = STATUS_SUCCESS;
else
status = STATUS_UNSUCCESSFUL;
InpPrint((2, "InpFindPortCallout exit (0x%x)\n", status));
return status;
}
#endif
NTSTATUS
InpSendIrpSynchronously (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
KEVENT event;
NTSTATUS status;
PAGED_CODE();
KeInitializeEvent(&event,
SynchronizationEvent,
FALSE
);
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp,
InpPnPComplete,
&event,
TRUE,
TRUE,
TRUE
);
status = IoCallDriver(DeviceObject, Irp);
//
// Wait for lower drivers to be done with the Irp
//
if (status == STATUS_PENDING) {
KeWaitForSingleObject(&event,
Executive,
KernelMode,
FALSE,
NULL
);
status = Irp->IoStatus.Status;
}
return status;
}
#if defined(NEC_98)
NTSTATUS
InportPowerUpToD0Complete(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
/*++
Routine Description:
Reinitializes the Inport Mouse haardware after any type of hibernation/sleep.
Arguments:
DeviceObject - Pointer to the device object
Irp - Pointer to the request
Context - Context passed in from the funciton that set the completion
routine. UNUSED.
Return Value:
STATUS_SUCCESSFUL if successful,
an valid NTSTATUS error code otherwise
--*/
{
NTSTATUS status;
PIO_STACK_LOCATION stack;
PDEVICE_EXTENSION deviceExtension;
PWORK_QUEUE_ITEM item;
UNREFERENCED_PARAMETER(Context);
deviceExtension = DeviceObject->DeviceExtension;
status = Irp->IoStatus.Status;
stack = IoGetCurrentIrpStackLocation(Irp);
if (NT_SUCCESS(status)) {
//
// Reset the power state to powered up
//
deviceExtension->PowerState = PowerDeviceD0;
//
// Everything has been powered up, let the system know about it
//
PoSetPowerState(DeviceObject,
stack->Parameters.Power.Type,
stack->Parameters.Power.State
);
item = (PWORK_QUEUE_ITEM) ExAllocatePool(NonPagedPool,
sizeof(WORK_QUEUE_ITEM));
if (!item) {
//
// must elaborate here
//
return STATUS_INSUFFICIENT_RESOURCES;
}
ExInitializeWorkItem(item, InportReinitializeHardware, item);
ExQueueWorkItem(item, DelayedWorkQueue);
}
InpPrint((2,"INPORT-InportPowerUpToD0Complete: PowerUpToD0Complete, exit\n"));
PoStartNextPowerIrp(Irp);
return status;
}
#endif // defined(NEC_98)