2025-04-27 07:49:33 -04:00

1576 lines
38 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1998 Microsoft Corporation
Module Name:
DBCACPI.C
Abstract:
Driver for ACPI based device bay contoller
Environment:
kernel mode only
Notes:
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
PURPOSE.
Copyright (c) 1998 Microsoft Corporation. All Rights Reserved.
Revision History:
5-4-98 : created, jdunn
--*/
#include "wdm.h"
#include "stdarg.h"
#include "stdio.h"
#include "dbci.h"
#include "dbclib.h"
#include "dbcacpi.h"
#ifdef ALLOC_PRAGMA
// pagable functions
#pragma alloc_text(PAGE, DBCACPI_QueryCapabilities)
#pragma alloc_text(PAGE, DBCACPI_Power)
#pragma alloc_text(PAGE, DBCACPI_Pnp)
#pragma alloc_text(PAGE, DBCACPI_StartDevice)
#pragma alloc_text(PAGE, DBCACPI_StopDevice)
#endif
//
// Globals
//
PDRIVER_OBJECT DBCACPI_DriverObject;
ULONG TotalHeapSace = 0;
ULONG DBCACPI_BIOS = 1;
ULONG DBCACPI_PollMode = 0;
#ifndef DEBUG0
#ifndef DEBUG1
#ifndef DEBUG2
#ifndef DEBUG3
#if DBG
#define DEBUG0
#endif
#endif
#endif
#endif
#endif
ULONG DBCACPI_W98_Debug_Trace = 0;
#ifdef DEBUG0
ULONG DBCACPI_Debug_Trace_Level = 0;
#endif /* DEBUG0 */
#ifdef DEBUG1
ULONG DBCACPI_Debug_Trace_Level = 1;
#endif /* DEBUG1 */
#ifdef DEBUG2
ULONG DBCACPI_Debug_Trace_Level = 2;
#endif /* DEBUG2 */
#ifdef DEBUG3
ULONG DBCACPI_Debug_Trace_Level = 3;
#endif /* DEBUG3 */
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
/*++
Routine Description:
Installable driver initialization entry point.
This entry point is called directly by the I/O system.
Arguments:
DriverObject - pointer to the driver object
RegistryPath - pointer to a unicode string representing the path
to driver-specific key in the registry
Return Value:
STATUS_SUCCESS if successful,
STATUS_UNSUCCESSFUL otherwise
--*/
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PDEVICE_OBJECT deviceObject = NULL;
DBCACPI_DriverObject = DriverObject;
//
// Create dispatch points for device control.
//
DriverObject->DriverUnload = DBCACPI_Unload;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DBCACPI_Ioctl;
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = DBCACPI_Ioctl;
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = DBCACPI_SystemControl;
DriverObject->MajorFunction[IRP_MJ_PNP] = DBCACPI_Pnp;
DriverObject->MajorFunction[IRP_MJ_POWER] = DBCACPI_Power;
DriverObject->DriverExtension->AddDevice = DBCACPI_AddDevice;
return ntStatus;
}
NTSTATUS
DBCACPI_PoRequestCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN UCHAR MinorFunction,
IN POWER_STATE PowerState,
IN PVOID Context,
IN PIO_STATUS_BLOCK IoStatus
)
/*++
Routine Description:
This routine is called when the port driver completes an IRP.
Arguments:
DeviceObject - Pointer to the device object for the class device.
Context - Driver defined context.
Return Value:
The function value is the final status from the operation.
--*/
{
PIRP irp;
PDEVICE_EXTENSION deviceExtension;
PDEVICE_OBJECT deviceObject = Context;
NTSTATUS ntStatus;
deviceExtension = deviceObject->DeviceExtension;
DBCACPI_ASSERT_EXT(deviceExtension);
irp = deviceExtension->PowerIrp;
ntStatus = IoStatus->Status;
IoCopyCurrentIrpStackLocationToNext(irp);
PoStartNextPowerIrp(irp);
PoCallDriver(deviceExtension->TopOfStackDeviceObject,
irp);
DBCACPI_DecrementIoCount(deviceObject);
return ntStatus;
}
NTSTATUS
DBCACPI_DeferIrpCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
/*++
Routine Description:
This routine is called when the port driver completes an IRP.
Arguments:
DeviceObject - Pointer to the device object for the class device.
Irp - Irp completed.
Context - Driver defined context.
Return Value:
The function value is the final status from the operation.
--*/
{
PKEVENT event = Context;
KeSetEvent(event,
1,
FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
DBCACPI_QueryCapabilities(
IN PDEVICE_OBJECT PdoDeviceObject,
IN PDEVICE_CAPABILITIES DeviceCapabilities
)
/*++
Routine Description:
This routine reads or write config space.
Arguments:
DeviceObject - Physical DeviceObject for this USB controller.
Return Value:
None.
--*/
{
PIO_STACK_LOCATION nextStack;
PIRP irp;
NTSTATUS ntStatus;
KEVENT event;
PAGED_CODE();
irp = IoAllocateIrp(PdoDeviceObject->StackSize, FALSE);
if (!irp) {
return STATUS_INSUFFICIENT_RESOURCES;
}
nextStack = IoGetNextIrpStackLocation(irp);
ASSERT(nextStack != NULL);
nextStack->MajorFunction= IRP_MJ_PNP;
nextStack->MinorFunction= IRP_MN_QUERY_CAPABILITIES;
KeInitializeEvent(&event, NotificationEvent, FALSE);
IoSetCompletionRoutine(irp,
DBCACPI_DeferIrpCompletion,
&event,
TRUE,
TRUE,
TRUE);
nextStack->Parameters.DeviceCapabilities.Capabilities = DeviceCapabilities;
// PnP rule:
// init all pnp irps we initiate with status_not_supported
irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
ntStatus = IoCallDriver(PdoDeviceObject,
irp);
if (ntStatus == STATUS_PENDING) {
// wait for irp to complete
TEST_TRAP(); // first time we hit this
KeWaitForSingleObject(
&event,
Suspended,
KernelMode,
FALSE,
NULL);
ntStatus = irp->IoStatus.Status;
}
#if DBG
if (!NT_SUCCESS(ntStatus)) {
// failed? this is probably a bug
DBCACPI_KdPrint((0, "'QueryCapabilities failed, why?\n"));
TRAP();
}
#endif
IoFreeIrp(irp);
return STATUS_SUCCESS;
}
NTSTATUS
DBCACPI_Power(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Process the Power IRPs sent to the PDO for this device.
Arguments:
DeviceObject - pointer to a hcd device object (FDO)
Irp - pointer to an I/O Request Packet
Return Value:
NT status code
--*/
{
PIO_STACK_LOCATION irpStack;
NTSTATUS ntStatus = STATUS_SUCCESS;
PDEVICE_EXTENSION deviceExtension;
BOOLEAN handledByClass;
PAGED_CODE();
irpStack = IoGetCurrentIrpStackLocation (Irp);
ASSERT(irpStack->MajorFunction == IRP_MJ_POWER);
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
DBCACPI_IncrementIoCount(DeviceObject);
// let the class driver have a peek at the
// power Irp
ntStatus = DBCLASS_ClassDispatch(
DeviceObject,
Irp,
&handledByClass);
if (handledByClass) {
DBCACPI_DecrementIoCount(DeviceObject);
return ntStatus;
}
//
// We must handle the D state messages, the class driver
// makes sure we only see changes from the current state
// it also inteprets all the nasty wake rules so that the
// code remains as simple as possible
//
//
// these asserts mean we have a bug in the class driver
// please 'fix' the class driver not this driver
//
DBCACPI_ASSERT(irpStack->MinorFunction == IRP_MN_SET_POWER);
DBCACPI_ASSERT(irpStack->Parameters.Power.Type == DevicePowerState);
DBCACPI_ASSERT(deviceExtension->CurrentDevicePowerState !=
irpStack->Parameters.Power.State.DeviceState);
deviceExtension->CurrentDevicePowerState =
irpStack->Parameters.Power.State.DeviceState;
IoCopyCurrentIrpStackLocationToNext(Irp);
PoStartNextPowerIrp(Irp);
ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject,
Irp);
DBCACPI_DecrementIoCount(DeviceObject);
return ntStatus;
}
NTSTATUS
DBCACPI_Pnp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Process the IRPs sent to this device.
Arguments:
DeviceObject - pointer to a device object
Irp - pointer to an I/O Request Packet
Return Value:
--*/
{
PIO_STACK_LOCATION irpStack;
PDEVICE_EXTENSION deviceExtension;
NTSTATUS ntStatus = STATUS_SUCCESS;
PDEVICE_OBJECT stackDeviceObject;
BOOLEAN handledByClass;
PAGED_CODE();
irpStack = IoGetCurrentIrpStackLocation (Irp);
DBCACPI_ASSERT(irpStack->MajorFunction == IRP_MJ_PNP);
deviceExtension = DeviceObject->DeviceExtension;
DBCACPI_ASSERT_EXT(deviceExtension);
stackDeviceObject = deviceExtension->TopOfStackDeviceObject;
DBCACPI_IncrementIoCount(DeviceObject);
DBCACPI_KdPrint((2, "'IRP_MJ_PNP\n"));
ntStatus = Irp->IoStatus.Status;
switch (irpStack->MinorFunction) {
case IRP_MN_START_DEVICE:
{
KEVENT event;
DBCACPI_KdPrint((1, "'IRP_MN_START_DEVICE\n"));
LOGENTRY(LOG_MISC, "Strt", 0, 0, 0);
KeInitializeEvent(&event, NotificationEvent, FALSE);
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp,
DBCACPI_DeferIrpCompletion,
&event,
TRUE,
TRUE,
TRUE);
ntStatus = IoCallDriver(stackDeviceObject,
Irp);
if (ntStatus == STATUS_PENDING) {
// wait for irp to complete
KeWaitForSingleObject(
&event,
Suspended,
KernelMode,
FALSE,
NULL);
ntStatus = Irp->IoStatus.Status;
}
if (NT_SUCCESS(ntStatus)) {
ntStatus = DBCACPI_StartDevice(DeviceObject);
if (NT_SUCCESS(ntStatus)) {
ntStatus = DBCLASS_ClassDispatch(
DeviceObject,
Irp,
&handledByClass);
DBCACPI_ASSERT(handledByClass == FALSE);
if (NT_SUCCESS(ntStatus) && DBCACPI_PollMode) {
DBCACPI_StartPolling(DeviceObject);
}
}
// update irp with status of start
Irp->IoStatus.Status = ntStatus;
}
#ifdef DBG
else {
DBCACPI_KdPrint((0, "'Lower driver failed the START! (0x%x)\n",
ntStatus));
TRAP();
}
#endif
goto DBCACPI_Dispatch_CompleteRequest;
}
break;
case IRP_MN_STOP_DEVICE:
DBCACPI_KdPrint((1, "'IRP_MN_STOP_DEVICE\n"));
LOGENTRY(LOG_MISC, "Stop", 0, 0, deviceExtension->Flags);
if (deviceExtension->Flags & DBCACPI_FLAG_STARTED) {
deviceExtension->Flags &= ~DBCACPI_FLAG_STARTED;
ntStatus = DBCLASS_ClassDispatch(
DeviceObject,
Irp,
&handledByClass);
DBCACPI_ASSERT(handledByClass == FALSE);
if (NT_SUCCESS(ntStatus)) {
ntStatus = DBCACPI_StopDevice(DeviceObject);
}
}
LOGENTRY(LOG_MISC, "StpD", 0, 0, ntStatus);
break;
case IRP_MN_REMOVE_DEVICE:
DBCACPI_KdPrint((1, "'IRP_MN_REMOVE_DEVICE\n"));
LOGENTRY(LOG_MISC, "REMv", 0, 0, 0);
// let the class driver do some cleanup
ntStatus = DBCLASS_ClassDispatch(
DeviceObject,
Irp,
&handledByClass);
DBCACPI_ASSERT(handledByClass == FALSE);
if (!(deviceExtension->Flags & DBCACPI_FLAG_STOPPED)) {
DBCACPI_StopDevice(DeviceObject);
}
// match the inc at the begining of the dispatch
// routine
DBCACPI_DecrementIoCount(DeviceObject);
if (deviceExtension->WakeIrp) {
IoCancelIrp(deviceExtension->WakeIrp);
deviceExtension->WakeIrp = NULL;
}
//
// ounce this flag is set no irps will be pased
// down the stack to lower drivers
//
deviceExtension->AcceptingRequests = FALSE;
if (NT_SUCCESS(ntStatus)) {
LONG pendingIoCount;
IoCopyCurrentIrpStackLocationToNext(Irp);
ntStatus = IoCallDriver(stackDeviceObject,
Irp);
//
// final decrement will trigger the remove
//
pendingIoCount = DBCACPI_DecrementIoCount(DeviceObject);
{
NTSTATUS status;
// wait for any io request pending in our driver to
// complete for finishing the remove
LOGENTRY(LOG_MISC, "ReWT", 0, 0, ntStatus);
status = KeWaitForSingleObject(
&deviceExtension->RemoveEvent,
Suspended,
KernelMode,
FALSE,
NULL);
LOGENTRY(LOG_MISC, "ReWD", 0, 0, ntStatus);
}
//
// Delete the link and FDO we created
//
IoDetachDevice(deviceExtension->TopOfStackDeviceObject);
IoDeleteDevice (DeviceObject);
DBCACPI_KdPrint((1, "'>REMOVE DONE\n"));
LOGENTRY(LOG_MISC, "RemD", 0, 0, ntStatus);
goto DBCACPI_Dispatch_Done;
}
break;
case IRP_MN_QUERY_STOP_DEVICE:
DBCACPI_KdPrint((1, "'IRP_MN_QUERY_STOP_DEVICE\n"));
break;
case IRP_MN_QUERY_REMOVE_DEVICE:
DBCACPI_KdPrint((1, "'IRP_MN_QUERY_REMOVE_DEVICE\n"));
break;
case IRP_MN_CANCEL_STOP_DEVICE:
DBCACPI_KdPrint((1, "'IRP_MN_CANCEL_STOP_DEVICE\n"));
break;
case IRP_MN_CANCEL_REMOVE_DEVICE:
DBCACPI_KdPrint((1, "'IRP_MN_CANCEL_REMOVE_DEVICE\n"));
break;
default:
DBCACPI_KdPrint((1,"'PnP IOCTL not handled\n"));
} /* case MinorFunction, MajorFunction == IRP_MJ_PNP_POWER */
IoCopyCurrentIrpStackLocationToNext(Irp);
//
// All PNP_POWER messages get passed to the TopOfStackDeviceObject
// we were given in PnPAddDevice
//
ntStatus = IoCallDriver(stackDeviceObject,
Irp);
DBCACPI_DecrementIoCount(DeviceObject);
goto DBCACPI_Dispatch_Done;
DBCACPI_Dispatch_CompleteRequest:
IoCompleteRequest (Irp,
IO_NO_INCREMENT);
DBCACPI_DecrementIoCount(DeviceObject);
DBCACPI_Dispatch_Done:
DBCACPI_KdPrint((3, "'DBCACPI_Pnp() = %x\n", ntStatus));
return ntStatus;
}
NTSTATUS
DBCACPI_Ioctl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Arguments:
DeviceObject - pointer to a hcd device object (FDO)
Irp - pointer to an I/O Request Packet
Return Value:
NT status code
--*/
{
NTSTATUS ntStatus;
BOOLEAN handledByClass;
PIO_STACK_LOCATION ioStackLocation;
DBCACPI_IncrementIoCount(DeviceObject);
ntStatus = DBCLASS_ClassDispatch(
DeviceObject,
Irp,
&handledByClass);
if (!handledByClass) {
// we need to handle this IRP
ioStackLocation = IoGetCurrentIrpStackLocation(Irp);
switch (ioStackLocation->MajorFunction) {
case IRP_MJ_INTERNAL_DEVICE_CONTROL:
{
ULONG ioControlCode;
ioControlCode = ioStackLocation->Parameters.DeviceIoControl.IoControlCode;
switch (ioControlCode) {
case IOCTL_INTERNAL_DBC_SUBMIT_DRB:
DBCACPI_KdPrint((2,"'Handle DRB\n"));
ntStatus = DBCACPI_ProcessDrb(DeviceObject,
Irp);
if (ntStatus == STATUS_PENDING) {
// we queued the irp, don't complete
// it here
return ntStatus;
}
break;
default:
ntStatus = STATUS_NOT_SUPPORTED;
} /* ioControlCode */
}
break;
default:
ntStatus = STATUS_NOT_SUPPORTED;
break;
} /* ioStackLocation->MajorFunction */
DBCACPI_DecrementIoCount(DeviceObject);
Irp->IoStatus.Status = ntStatus;
IoCompleteRequest (Irp,
IO_NO_INCREMENT);
} else {
DBCACPI_DecrementIoCount(DeviceObject);
}
return ntStatus;
}
NTSTATUS
DBCACPI_SystemControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Arguments:
DeviceObject - pointer to a hcd device object (FDO)
Irp - pointer to an I/O Request Packet
Return Value:
NT status code
--*/
{
NTSTATUS ntStatus;
BOOLEAN handledByClass;
TEST_TRAP();
DBCACPI_IncrementIoCount(DeviceObject);
ntStatus = DBCLASS_ClassDispatch(
DeviceObject,
Irp,
&handledByClass);
// class driver should handle all system control
DBCACPI_ASSERT(handledByClass == TRUE);
DBCACPI_DecrementIoCount(DeviceObject);
return ntStatus;
}
VOID
DBCACPI_Unload(
IN PDRIVER_OBJECT DriverObject
)
/*++
Routine Description:
Free all the allocated resources, etc.
Arguments:
DriverObject - pointer to a driver object
Return Value:
--*/
{
}
NTSTATUS
DBCACPI_RemoveDevice(
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
Arguments:
DeviceObject - pointer to FDO
Return Value:
NT status code
--*/
{
PDEVICE_EXTENSION deviceExtension;
NTSTATUS ntStatus = STATUS_SUCCESS;
deviceExtension = DeviceObject->DeviceExtension;
DBCACPI_ASSERT_EXT(deviceExtension);
return ntStatus;
}
NTSTATUS
DBCACPI_AddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject
)
/*++
Routine Description:
This routine is called to create a new instance of the device
Arguments:
DriverObject - pointer to the driver object for this instance of DBCACPI
PhysicalDeviceObject - pointer to a device object created by the bus
Return Value:
STATUS_SUCCESS if successful,
STATUS_UNSUCCESSFUL otherwise
--*/
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PDEVICE_OBJECT deviceObject = NULL;
PDEVICE_EXTENSION deviceExtension;
//
// create our funtional device object (FDO)
//
DBCACPI_KdPrint((0,"'Device Bay ACPI Controller Driver (ADD)\n"));
DBCACPI_LogInit();
#if DBG
DBCACPI_GetClassGlobalDebugRegistryParameters();
#endif
DBCACPI_GetClassGlobalRegistryParameters();
ntStatus = DBCACPI_GetAcpiInterfaces(PhysicalDeviceObject);
if (NT_SUCCESS(ntStatus)) {
ntStatus =
DBCACPI_CreateDeviceObject(DriverObject, &deviceObject);
}
if (NT_SUCCESS(ntStatus)) {
deviceExtension = deviceObject->DeviceExtension;
deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
//
// we support direct io for read/write
//
deviceObject->Flags |= DO_DIRECT_IO;
deviceObject->Flags |= DO_POWER_PAGABLE;
//** initialize our device extension
deviceExtension->Sig = DBCACPI_EXT_SIG;
//
// remember the Physical device Object
//
deviceExtension->PhysicalDeviceObject=PhysicalDeviceObject;
KeInitializeSpinLock(&deviceExtension->FlagsSpin);
KeInitializeSpinLock(&deviceExtension->ChangeRequestSpin);
//
// Attach to the PDO
//
deviceExtension->TopOfStackDeviceObject =
IoAttachDeviceToDeviceStack(deviceObject, PhysicalDeviceObject);
DBCACPI_QueryCapabilities(PhysicalDeviceObject,
&deviceExtension->DeviceCapabilities);
//
// display the device caps
//
#if DBG
{
ULONG i;
DBCACPI_KdPrint((1, "'>>>>>> DeviceCaps\n"));
DBCACPI_KdPrint((1, "'SystemWake = (%d)\n",
deviceExtension->DeviceCapabilities.SystemWake));
DBCACPI_KdPrint((1, "'DeviceWake = (D%d)\n",
deviceExtension->DeviceCapabilities.DeviceWake-1));
for (i=PowerSystemUnspecified; i< PowerSystemMaximum; i++) {
DBCACPI_KdPrint((1, "'Device State Map: sysstate %d = devstate 0x%x\n", i,
deviceExtension->DeviceCapabilities.DeviceState[i]));
}
DBCACPI_KdPrint((1, "'<<<<<<<<DeviceCaps\n"));
}
#endif
// kill the ACPI BIOS
if (DBCACPI_BIOS ) {
DBCACPI_KdPrint((0,"'Disable BIOS Control\n"));
DBCACPI_BIOSControl(deviceObject,
FALSE);
}
// Register with the Class Driver
DBCLASS_RegisterController(
DBCLASS_VERSION,
deviceObject,
deviceExtension->TopOfStackDeviceObject,
deviceExtension->PhysicalDeviceObject,
DBC_ACPI_CONTROLLER_SIG);
//
// transition to zero signals the event
//
DBCACPI_IncrementIoCount(deviceObject);
}
return ntStatus;
}
NTSTATUS
DBCACPI_CreateDeviceObject(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT *DeviceObject
)
/*++
Routine Description:
Creates a Functional DeviceObject
Arguments:
DriverObject - pointer to the driver object for device
DeviceObject - pointer to DeviceObject pointer to return
created device object.
Instance - instnace of the device create.
Return Value:
STATUS_SUCCESS if successful,
STATUS_UNSUCCESSFUL otherwise
--*/
{
NTSTATUS ntStatus;
WCHAR deviceNameBuffer[] = L"\\Device\\DBCACPI-0";
UNICODE_STRING deviceNameUnicodeString;
ULONG i = 0;
// do we need a name?
do {
deviceNameBuffer[15] = (USHORT) ('0' + i);
RtlInitUnicodeString (&deviceNameUnicodeString,
deviceNameBuffer);
ntStatus = IoCreateDevice (DriverObject,
sizeof (DEVICE_EXTENSION),
&deviceNameUnicodeString,
FILE_DEVICE_UNKNOWN,
0,
FALSE,
DeviceObject);
i++;
} while (!NT_SUCCESS(ntStatus));
return ntStatus;
}
LONG
DBCACPI_DecrementIoCount(
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
PDEVICE_EXTENSION deviceExtension;
LONG ioCount;
deviceExtension = DeviceObject->DeviceExtension;
DBCACPI_ASSERT_EXT(deviceExtension);
ioCount = InterlockedDecrement(&deviceExtension->PendingIoCount);
DBCACPI_KdPrint ((2, "'Dec Pending io count = %x\n", ioCount));
if (ioCount==0) {
LOGENTRY(LOG_MISC, "ReWK", 0, 0, 0);
KeSetEvent(&deviceExtension->RemoveEvent,
1,
FALSE);
}
return ioCount;
}
VOID
DBCACPI_IncrementIoCount(
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
PDEVICE_EXTENSION deviceExtension;
deviceExtension = DeviceObject->DeviceExtension;
DBCACPI_ASSERT_EXT(deviceExtension);
InterlockedIncrement(&deviceExtension->PendingIoCount);
}
NTSTATUS
DBCACPI_WaitWakeIrpCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN UCHAR MinorFunction,
IN POWER_STATE DeviceState,
IN PVOID Context,
IN PIO_STATUS_BLOCK IoStatus
)
/*++
Routine Description:
Called when a wake irp completes for a hub
Arguments:
DeviceObject - Pointer to the device object for the class device.
Irp - Irp completed.
Context - Driver defined context.
Return Value:
The function value is the final status from the operation.
--*/
{
DBCACPI_DecrementIoCount(DeviceObject);
return IoStatus->Status;
}
NTSTATUS
DBCACPI_GetRegistryKeyValueForPdo(
IN PDEVICE_OBJECT PhysicalDeviceObject,
IN PWCHAR KeyNameString,
IN ULONG KeyNameStringLength,
IN PVOID Data,
IN ULONG DataLength
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
NTSTATUS ntStatus = STATUS_INSUFFICIENT_RESOURCES;
UNICODE_STRING keyNameUnicodeString;
ULONG length;
PKEY_VALUE_FULL_INFORMATION fullInfo;
HANDLE handle;
PAGED_CODE();
ntStatus=IoOpenDeviceRegistryKey(PhysicalDeviceObject,
//PLUGPLAY_REGKEY_DRIVER,
PLUGPLAY_REGKEY_DEVICE,
STANDARD_RIGHTS_ALL,
&handle);
if (NT_SUCCESS(ntStatus)) {
RtlInitUnicodeString(&keyNameUnicodeString, KeyNameString);
length = sizeof(KEY_VALUE_FULL_INFORMATION) +
KeyNameStringLength + DataLength;
fullInfo = ExAllocatePoolWithTag(PagedPool, length, 'dbca');
DBCACPI_KdPrint((2,"' DBCAPI_GetRegistryKeyValueForPdo buffer = 0x%x\n", fullInfo));
if (fullInfo) {
ntStatus = ZwQueryValueKey(handle,
&keyNameUnicodeString,
KeyValueFullInformation,
fullInfo,
length,
&length);
if (NT_SUCCESS(ntStatus)){
DBCACPI_ASSERT(DataLength == fullInfo->DataLength);
RtlCopyMemory(Data, ((PUCHAR) fullInfo) + fullInfo->DataOffset, DataLength);
}
ExFreePool(fullInfo);
}
}
return ntStatus;
}
NTSTATUS
DBCACPI_SetRegistryKeyValueForPdo(
IN PDEVICE_OBJECT PhysicalDeviceObject,
IN BOOLEAN SoftwareBranch,
IN ULONG Type,
IN PWCHAR KeyNameString,
IN ULONG KeyNameStringLength,
IN PVOID Data,
IN ULONG DataLength
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
NTSTATUS ntStatus = STATUS_INSUFFICIENT_RESOURCES;
UNICODE_STRING keyNameUnicodeString;
HANDLE handle;
PAGED_CODE();
if (SoftwareBranch) {
ntStatus=IoOpenDeviceRegistryKey(PhysicalDeviceObject,
PLUGPLAY_REGKEY_DRIVER,
STANDARD_RIGHTS_ALL,
&handle);
} else {
ntStatus=IoOpenDeviceRegistryKey(PhysicalDeviceObject,
PLUGPLAY_REGKEY_DEVICE,
STANDARD_RIGHTS_ALL,
&handle);
}
if (NT_SUCCESS(ntStatus)) {
RtlInitUnicodeString(&keyNameUnicodeString, KeyNameString);
ntStatus = ZwSetValueKey(handle,
&keyNameUnicodeString,
0,
Type,
Data,
DataLength);
}
return ntStatus;
}
NTSTATUS
DBCACPI_GetRegistryParameters(
PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
PDEVICE_EXTENSION deviceExtension;
NTSTATUS ntStatus = STATUS_SUCCESS, keyStatus;
PDBC_SUBSYSTEM_DESCRIPTOR subsystemDescriptor;
WCHAR guidFor1394Key[] = L"GuidFor1394";
WCHAR bayCountKey[] = L"BayCount";
ULONG bayCount = 0;
PAGED_CODE();
deviceExtension = DeviceObject->DeviceExtension;
DBCACPI_ASSERT_EXT(deviceExtension);
subsystemDescriptor =
&deviceExtension->SubsystemDescriptor;
//
// see if we have a guid
//
keyStatus = DBCACPI_GetRegistryKeyValueForPdo(
deviceExtension->PhysicalDeviceObject,
guidFor1394Key,
sizeof(guidFor1394Key),
&subsystemDescriptor->guid1394Link[0],
8);
if (NT_SUCCESS(keyStatus)){
DBCACPI_KdPrint((0,"'**** Reading Reg Key for busted DBC BIOS\n"));
DBCACPI_KdPrint((0,"'**** key - 1394 Link GUID\n"));
}
keyStatus = DBCACPI_GetRegistryKeyValueForPdo(
deviceExtension->PhysicalDeviceObject,
bayCountKey,
sizeof(bayCountKey),
&bayCount,
sizeof(bayCount));
if (NT_SUCCESS(keyStatus)) {
subsystemDescriptor->bmAttributes.BayCount = bayCount;
DBCACPI_KdPrint((0,"'**** Reading Reg Key for busted DBC BIOS\n"));
DBCACPI_KdPrint((0,"'**** key - Bay Count\n"));
}
return ntStatus;
}
NTSTATUS
DBCACPI_GetBayRegistryParameters(
PDEVICE_OBJECT DeviceObject,
USHORT BayNumber,
PULONG PortUSBMap,
PULONG Port1394Map
)
/*++
Routine Description:
//#ifdef COMPAQ_TYPE4
if (bayDescriptor->bBayNumber == 1) {
bayDescriptor->bPHYPortNumber = 2;
bayDescriptor->bHubPortNumber = 1;
} else if (bayDescriptor->bBayNumber == 2) {
bayDescriptor->bPHYPortNumber = 4;
bayDescriptor->bHubPortNumber = 2;
}
//#endif
Arguments:
Return Value:
--*/
{
PDEVICE_EXTENSION deviceExtension;
NTSTATUS ntStatus = STATUS_SUCCESS, keyStatus;
WCHAR portUSBMapKey[] = L"PORTUSBMAP00";
WCHAR port1394MapKey[] = L"PORT1394MAP00";
PAGED_CODE();
portUSBMapKey[11] = '0' + BayNumber;
port1394MapKey[12] = '0' + BayNumber;
deviceExtension = DeviceObject->DeviceExtension;
DBCACPI_ASSERT_EXT(deviceExtension);
//
// see if we have a guid
//
keyStatus = DBCACPI_GetRegistryKeyValueForPdo(
deviceExtension->PhysicalDeviceObject,
portUSBMapKey,
sizeof(portUSBMapKey),
PortUSBMap,
sizeof(*PortUSBMap));
if (NT_SUCCESS(keyStatus)){
DBCACPI_KdPrint((0,"'**** Reading Reg Key for busted DBC BIOS\n"));
DBCACPI_KdPrint((0,"'**** key - USB port map\n"));
}
keyStatus = DBCACPI_GetRegistryKeyValueForPdo(
deviceExtension->PhysicalDeviceObject,
port1394MapKey,
sizeof(port1394MapKey),
Port1394Map,
sizeof(*Port1394Map));
if (NT_SUCCESS(keyStatus)){
DBCACPI_KdPrint((0,"'**** Reading Reg Key for busted DBC BIOS\n"));
DBCACPI_KdPrint((0,"'**** key - 1394 port map\n"));
}
return ntStatus;
}
VOID
DBCACPI_PollDpc(
IN PKDPC Dpc,
IN PVOID DeferredContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2
)
/*++
Routine Description:
This routine runs at DISPATCH_LEVEL IRQL.
Arguments:
Dpc - Pointer to the DPC object.
DeferredContext - supplies the device object.
SystemArgument1 - not used.
SystemArgument2 - not used.
Return Value:
None.
--*/
{
PDEVICE_OBJECT fdoDeviceObject = DeferredContext;
KIRQL oldIrql;
PDEVICE_EXTENSION deviceExtension;
PDBCACPI_WORKITEM workItem;
DBCACPI_KdPrint((1, "'DBC Notification Poll\n"));
// do we have a workitem scheduled?
deviceExtension = fdoDeviceObject->DeviceExtension;
DBCACPI_ASSERT_EXT(deviceExtension);
KeAcquireSpinLock(&deviceExtension->FlagsSpin, &oldIrql);
if (deviceExtension->Flags & DBCACPI_FLAG_WORKITEM_PENDING) {
// yes, bail
KeReleaseSpinLock(&deviceExtension->FlagsSpin, oldIrql);
} else {
// no, schedule one
DBCACPI_IncrementIoCount(fdoDeviceObject);
workItem = &deviceExtension->WorkItem;
deviceExtension->Flags |= DBCACPI_FLAG_WORKITEM_PENDING;
KeReleaseSpinLock(&deviceExtension->FlagsSpin, oldIrql);
workItem->Sig = DBC_WORKITEM_SIG;
ExInitializeWorkItem(&workItem->WorkQueueItem,
DBCACPI_NotifyWorker,
fdoDeviceObject);
ExQueueWorkItem(&workItem->WorkQueueItem,
DelayedWorkQueue);
}
LOGENTRY(LOG_MISC, "Nop-", 0, 0, 0);
}
NTSTATUS
DBCACPI_StartPolling(
PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
PDEVICE_EXTENSION deviceExtension;
NTSTATUS ntStatus = STATUS_SUCCESS;
LARGE_INTEGER dueTime;
LONG period;
deviceExtension = DeviceObject->DeviceExtension;
KeInitializeTimer(&deviceExtension->PollTimer);
KeInitializeDpc(&deviceExtension->PollDpc,
DBCACPI_PollDpc,
DeviceObject);
dueTime.QuadPart = -10000 * 32;
period = 1000; //every 1000 ms
// UHCD_KdPrint((2, "'UHCD Poll Interval = (0x%x) %x %x\n",
// endpoint->Interval, dueTime.LowPart, dueTime.HighPart));
KeSetTimerEx(&deviceExtension->PollTimer,
dueTime,
period,
&deviceExtension->PollDpc);
return ntStatus;
}
NTSTATUS
DBCACPI_GetConfigValue(
IN PWSTR ValueName,
IN ULONG ValueType,
IN PVOID ValueData,
IN ULONG ValueLength,
IN PVOID Context,
IN PVOID EntryContext
)
/*++
Routine Description:
This routine is a callback routine for RtlQueryRegistryValues
It is called for each entry in the Parameters
node to set the config values. The table is set up
so that this function will be called with correct default
values for keys that are not present.
Arguments:
ValueName - The name of the value (ignored).
ValueType - The type of the value
ValueData - The data for the value.
ValueLength - The length of ValueData.
Context - A pointer to the CONFIG structure.
EntryContext - The index in Config->Parameters to save the value.
Return Value:
--*/
{
NTSTATUS ntStatus = STATUS_SUCCESS;
DBCACPI_KdPrint((2, "'Type 0x%x, Length 0x%x\n", ValueType, ValueLength));
switch (ValueType) {
case REG_DWORD:
*(PVOID*)EntryContext = *(PVOID*)ValueData;
break;
case REG_BINARY:
// we are only set up to read a byte
RtlCopyMemory(EntryContext, ValueData, 1);
break;
default:
ntStatus = STATUS_INVALID_PARAMETER;
}
return ntStatus;
}
NTSTATUS
DBCACPI_GetClassGlobalRegistryParameters(
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
NTSTATUS ntStatus;
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
PWCHAR dbc = L"class\\dbc";
PAGED_CODE();
//
// Set up QueryTable to do the following:
//
// spew level
QueryTable[0].QueryRoutine = DBCACPI_GetConfigValue;
QueryTable[0].Flags = 0;
QueryTable[0].Name = POLL_MODE_KEY;
QueryTable[0].EntryContext = &DBCACPI_PollMode;
QueryTable[0].DefaultType = REG_DWORD;
QueryTable[0].DefaultData = &DBCACPI_PollMode;
QueryTable[0].DefaultLength = sizeof(DBCACPI_PollMode);
//
// Stop
//
QueryTable[1].QueryRoutine = NULL;
QueryTable[1].Flags = 0;
QueryTable[1].Name = NULL;
ntStatus = RtlQueryRegistryValues(
RTL_REGISTRY_SERVICES,
dbc,
QueryTable, // QueryTable
NULL, // Context
NULL); // Environment
if (NT_SUCCESS(ntStatus)) {
if (DBCACPI_PollMode) {
DBCACPI_KdPrint((0, "'DBC Poll mode is ON\n"));
}
}
if ( STATUS_OBJECT_NAME_NOT_FOUND == ntStatus ) {
ntStatus = STATUS_SUCCESS;
}
return ntStatus;
}