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

1148 lines
27 KiB
C
Raw Permalink 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:
DBCUSB.C
Abstract:
Driver for USB 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 "dbcusb.h"
#ifdef ALLOC_PRAGMA
// pagable functions
#pragma alloc_text(PAGE, DBCUSB_QueryCapabilities)
#pragma alloc_text(PAGE, DBCUSB_Power)
#pragma alloc_text(PAGE, DBCUSB_Pnp)
#pragma alloc_text(PAGE, DBCUSB_StartDevice)
#pragma alloc_text(PAGE, DBCUSB_StopDevice)
#endif
//
// Globals
//
PDRIVER_OBJECT DBCUSB_DriverObject;
#ifndef DEBUG0
#ifndef DEBUG1
#ifndef DEBUG2
#ifndef DEBUG3
#if DBG
#define DEBUG1
#endif
#endif
#endif
#endif
#endif
#ifdef DEBUG0
ULONG DBCUSB_Debug_Trace_Level = 0;
#endif /* DEBUG0 */
#ifdef DEBUG1
ULONG DBCUSB_Debug_Trace_Level = 1;
#endif /* DEBUG1 */
#ifdef DEBUG2
ULONG DBCUSB_Debug_Trace_Level = 2;
#endif /* DEBUG2 */
#ifdef DEBUG3
ULONG DBCUSB_Debug_Trace_Level = 3;
#endif /* DEBUG3 */
#ifdef NTKERN_TRACE
ULONG DBCUSB_W98_Debug_Trace = 1;
#else
ULONG DBCUSB_W98_Debug_Trace = 0;
#endif
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;
DBCUSB_DriverObject = DriverObject;
//
// Create dispatch points for device control.
//
DriverObject->DriverUnload = DBCUSB_Unload;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DBCUSB_Ioctl;
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = DBCUSB_Ioctl;
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = DBCUSB_SystemControl;
DriverObject->MajorFunction[IRP_MJ_PNP] = DBCUSB_Pnp;
DriverObject->MajorFunction[IRP_MJ_POWER] = DBCUSB_Power;
DriverObject->DriverExtension->AddDevice = DBCUSB_AddDevice;
return ntStatus;
}
NTSTATUS
DBCUSB_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;
DBCUSB_ASSERT_EXT(deviceExtension);
irp = deviceExtension->PowerIrp;
ntStatus = IoStatus->Status;
IoCopyCurrentIrpStackLocationToNext(irp);
PoStartNextPowerIrp(irp);
PoCallDriver(deviceExtension->TopOfStackDeviceObject,
irp);
DBCUSB_DecrementIoCount(deviceObject);
return ntStatus;
}
#if 0
NTSTATUS
DBCUSB_PowerIrp_SetD0_Complete(
IN PDEVICE_OBJECT NullDeviceObject,
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.
--*/
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PDEVICE_OBJECT deviceObject;
PIO_STACK_LOCATION irpStack;
PDEVICE_EXTENSION deviceExtension;
deviceObject = (PDEVICE_OBJECT) Context;
deviceExtension = (PDEVICE_EXTENSION) deviceObject->DeviceExtension;
if (Irp->PendingReturned) {
IoMarkIrpPending(Irp);
}
irpStack = IoGetCurrentIrpStackLocation (Irp);
ASSERT(irpStack->MajorFunction == IRP_MJ_POWER);
ASSERT(irpStack->MinorFunction == IRP_MN_SET_POWER);
ASSERT(irpStack->Parameters.Power.Type==DevicePowerState);
// we currently only call this going to D0
ASSERT(irpStack->Parameters.Power.State.DeviceState==PowerDeviceD0);
deviceExtension->CurrentDevicePowerState = PowerDeviceD0;
// at this point our driver is 'back on'
// notify the class driver of this, it will
// drive the power on process for us
TEST_TRAP();
DBCLASS_SetD0_Complete(deviceObject, Irp);
Irp->IoStatus.Status = ntStatus;
DBCUSB_DecrementIoCount(deviceObject);
return ntStatus;
}
#endif
NTSTATUS
DBCUSB_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
DBCUSB_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,
DBCUSB_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
DBCUSB_KdPrint((0, "'QueryCapabilities failed, why?\n"));
TRAP();
}
#endif
IoFreeIrp(irp);
return STATUS_SUCCESS;
}
NTSTATUS
DBCUSB_Power(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Process the Power IRPs sent to the PDO for this device.
NOTE: The class driver will handle all power messages
the port driver should only see D-State messages
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 setD0 = FALSE;
BOOLEAN handledByClass = FALSE;
PAGED_CODE();
irpStack = IoGetCurrentIrpStackLocation (Irp);
ASSERT(irpStack->MajorFunction == IRP_MJ_POWER);
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
DBCUSB_IncrementIoCount(DeviceObject);
// let the class driver have a peek at the
// power Irp
ntStatus = DBCLASS_ClassDispatch(
DeviceObject,
Irp,
&handledByClass);
if (handledByClass) {
DBCUSB_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
//
DBCUSB_ASSERT(irpStack->MinorFunction == IRP_MN_SET_POWER);
DBCUSB_ASSERT(irpStack->Parameters.Power.Type == DevicePowerState);
DBCUSB_ASSERT(deviceExtension->CurrentDevicePowerState !=
irpStack->Parameters.Power.State.DeviceState);
deviceExtension->CurrentDevicePowerState =
irpStack->Parameters.Power.State.DeviceState;
IoCopyCurrentIrpStackLocationToNext(Irp);
PoStartNextPowerIrp(Irp);
ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject,
Irp);
DBCUSB_DecrementIoCount(DeviceObject);
return ntStatus;
}
NTSTATUS
DBCUSB_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 = FALSE;
PAGED_CODE();
irpStack = IoGetCurrentIrpStackLocation (Irp);
DBCUSB_ASSERT(irpStack->MajorFunction == IRP_MJ_PNP);
deviceExtension = DeviceObject->DeviceExtension;
DBCUSB_ASSERT_EXT(deviceExtension);
stackDeviceObject = deviceExtension->TopOfStackDeviceObject;
DBCUSB_IncrementIoCount(DeviceObject);
DBCUSB_KdPrint((1, "'IRP_MJ_PNP MN(0x%x)\n", irpStack->MinorFunction));
ntStatus = Irp->IoStatus.Status;
switch (irpStack->MinorFunction) {
case IRP_MN_START_DEVICE:
{
KEVENT event;
DBCUSB_KdPrint((1, "'IRP_MN_START_DEVICE\n"));
KeInitializeEvent(&event, NotificationEvent, FALSE);
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp,
DBCUSB_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 = DBCUSB_StartDevice(DeviceObject);
if (NT_SUCCESS(ntStatus)) {
ntStatus = DBCLASS_ClassDispatch(
DeviceObject,
Irp,
&handledByClass);
DBCUSB_ASSERT(handledByClass == FALSE);
}
// set irp to the status of the start
Irp->IoStatus.Status = ntStatus;
deviceExtension->Flags &= ~DBCUSB_FLAG_STOPPED;
//
// transition to zero signals the event
//
DBCUSB_IncrementIoCount(DeviceObject);
deviceExtension->Flags |= DBCUSB_FLAG_STARTED;
}
#ifdef DBG
else {
DBCUSB_KdPrint((0, "'Lower driver failed the START! (0x%x)\n",
ntStatus));
TRAP();
}
#endif
goto DBCUSB_Dispatch_CompleteRequest;
}
break;
case IRP_MN_STOP_DEVICE:
DBCUSB_KdPrint((1, "'IRP_MN_STOP_DEVICE\n"));
ntStatus = DBCLASS_ClassDispatch(
DeviceObject,
Irp,
&handledByClass);
DBCUSB_ASSERT(handledByClass == FALSE);
// match the inc at the begining of the dispatch
// routine
DBCUSB_DecrementIoCount(DeviceObject);
ntStatus = DBCUSB_StopDevice(DeviceObject);
deviceExtension->Flags |= DBCUSB_FLAG_STOPPED;
// note that in the complex world of PnP
// not being started is not the same
// as being stopped
deviceExtension->Flags &= ~DBCUSB_FLAG_STARTED;
IoCopyCurrentIrpStackLocationToNext(Irp);
ntStatus = IoCallDriver(stackDeviceObject,
Irp);
goto DBCUSB_Dispatch_Done;
break;
case IRP_MN_REMOVE_DEVICE:
DBCUSB_KdPrint((1, "'IRP_MN_REMOVE_DEVICE\n"));
ntStatus = DBCLASS_ClassDispatch(
DeviceObject,
Irp,
&handledByClass);
DBCUSB_ASSERT(handledByClass == FALSE);
// match the inc at the begining of the dispatch
// routine
DBCUSB_DecrementIoCount(DeviceObject);
if (!(deviceExtension->Flags & DBCUSB_FLAG_STOPPED)) {
ntStatus = DBCUSB_StopDevice(DeviceObject);
// note that in the complex world of PnP
// not being started is not the same
// as being stopped
deviceExtension->Flags &= ~DBCUSB_FLAG_STARTED;
}
// pass down the remove
IoCopyCurrentIrpStackLocationToNext(Irp);
ntStatus = IoCallDriver(stackDeviceObject,
Irp);
// Un-register with the Class Driver
DBCLASS_UnRegisterController(
DeviceObject,
deviceExtension->TopOfStackDeviceObject);
IoDetachDevice(deviceExtension->TopOfStackDeviceObject);
IoDeleteDevice (DeviceObject);
DBCUSB_KdPrint((1, "'>REMOVE DONE\n"));
goto DBCUSB_Dispatch_Done;
break;
case IRP_MN_QUERY_STOP_DEVICE:
DBCUSB_KdPrint((1, "'IRP_MN_QUERY_STOP_DEVICE\n"));
break;
case IRP_MN_QUERY_REMOVE_DEVICE:
DBCUSB_KdPrint((1, "'IRP_MN_QUERY_REMOVE_DEVICE\n"));
break;
case IRP_MN_CANCEL_STOP_DEVICE:
DBCUSB_KdPrint((1, "'IRP_MN_CANCEL_STOP_DEVICE\n"));
break;
case IRP_MN_CANCEL_REMOVE_DEVICE:
DBCUSB_KdPrint((1, "'IRP_MN_CANCEL_REMOVE_DEVICE\n"));
break;
case IRP_MN_QUERY_CAPABILITIES:
{
KEVENT event;
PDEVICE_CAPABILITIES pDevCaps;
DBCUSB_KdPrint((1, "'IRP_MN_QUERY_CAPABILITIES\n"));
KeInitializeEvent(&event, NotificationEvent, FALSE);
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp,
DBCUSB_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;
}
//
// Set surprise removal O.K.
//
irpStack = IoGetCurrentIrpStackLocation(Irp);
pDevCaps = irpStack->Parameters.DeviceCapabilities.Capabilities;
pDevCaps->SurpriseRemovalOK = TRUE;
goto DBCUSB_Dispatch_CompleteRequest;
}
break;
default:
DBCUSB_KdPrint((1,"'PnP IOCTL not handled 0x%x\n", irpStack->MinorFunction));
} /* case MinorFunction, MajorFunction == IRP_MJ_PNP_POWER */
IoCopyCurrentIrpStackLocationToNext(Irp);
//
// All PNP_POWER messages get passed to the TopOfStackDeviceObject
// we were given in PnPAddDevice
//
DBCUSB_DecrementIoCount(DeviceObject);
ntStatus = IoCallDriver(stackDeviceObject,
Irp);
goto DBCUSB_Dispatch_Done;
DBCUSB_Dispatch_CompleteRequest:
IoCompleteRequest (Irp,
IO_NO_INCREMENT);
DBCUSB_DecrementIoCount(DeviceObject);
DBCUSB_Dispatch_Done:
return ntStatus;
}
NTSTATUS
DBCUSB_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 = FALSE;
PIO_STACK_LOCATION ioStackLocation;
DBCUSB_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:
DBCUSB_KdPrint((2,"'Handle DRB\n"));
ntStatus = DBCUSB_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 */
DBCUSB_DecrementIoCount(DeviceObject);
Irp->IoStatus.Status = ntStatus;
IoCompleteRequest (Irp,
IO_NO_INCREMENT);
} else {
DBCUSB_DecrementIoCount(DeviceObject);
}
return ntStatus;
}
NTSTATUS
DBCUSB_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 = FALSE;
TEST_TRAP();
DBCUSB_IncrementIoCount(DeviceObject);
ntStatus = DBCLASS_ClassDispatch(
DeviceObject,
Irp,
&handledByClass);
// class driver should handle all system control
DBCUSB_ASSERT(handledByClass == TRUE);
DBCUSB_DecrementIoCount(DeviceObject);
return ntStatus;
}
VOID
DBCUSB_Unload(
IN PDRIVER_OBJECT DriverObject
)
/*++
Routine Description:
Free all the allocated resources, etc.
Arguments:
DriverObject - pointer to a driver object
Return Value:
--*/
{
}
NTSTATUS
DBCUSB_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 DBCUSB
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)
//
#if DBG
DBCUSB_GetClassGlobalDebugRegistryParameters();
#endif
if (NT_SUCCESS(ntStatus)) {
ntStatus =
DBCUSB_CreateDeviceObject(DriverObject, &deviceObject);
}
if (NT_SUCCESS(ntStatus)) {
deviceExtension = deviceObject->DeviceExtension;
deviceExtension->FdoDeviceObject = deviceObject;
//
// we support direct io for read/write
//
deviceObject->Flags |= DO_DIRECT_IO;
deviceObject->Flags |= DO_POWER_PAGABLE;
//** initialize our device extension
deviceExtension->Sig = DBCUSB_EXT_SIG;
deviceExtension->Flags = 0;
//
// remember the Physical device Object
//
deviceExtension->PhysicalDeviceObject=PhysicalDeviceObject;
//
// Attach to the PDO
//
deviceExtension->TopOfStackDeviceObject =
IoAttachDeviceToDeviceStack(deviceObject, PhysicalDeviceObject);
DBCUSB_QueryCapabilities(PhysicalDeviceObject,
&deviceExtension->DeviceCapabilities);
//
// display the device caps
//
#if DBG
{
ULONG i;
DBCUSB_KdPrint((1, "'>>>>>> DeviceCaps\n"));
DBCUSB_KdPrint((1, "'SystemWake = (%d)\n",
deviceExtension->DeviceCapabilities.SystemWake));
DBCUSB_KdPrint((1, "'DeviceWake = (D%d)\n",
deviceExtension->DeviceCapabilities.DeviceWake-1));
for (i=PowerSystemUnspecified; i< PowerSystemMaximum; i++) {
DBCUSB_KdPrint((1, "'Device State Map: sysstate %d = devstate 0x%x\n", i,
deviceExtension->DeviceCapabilities.DeviceState[i]));
}
DBCUSB_KdPrint((1, "'<<<<<<<<DeviceCaps\n"));
}
#endif
// Register with the Class Driver
DBCLASS_RegisterController(
DBCLASS_VERSION,
deviceObject,
deviceExtension->TopOfStackDeviceObject,
deviceExtension->PhysicalDeviceObject,
DBC_USB_CONTROLLER_SIG);
deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
}
return ntStatus;
}
NTSTATUS
DBCUSB_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\\DBCUSB-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
DBCUSB_DecrementIoCount(
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
PDEVICE_EXTENSION deviceExtension;
LONG ioCount;
deviceExtension = DeviceObject->DeviceExtension;
DBCUSB_ASSERT_EXT(deviceExtension);
ioCount = InterlockedDecrement(&deviceExtension->PendingIoCount);
DBCUSB_KdPrint ((2, "'Dec Pending io count = %x\n", ioCount));
if (ioCount==0 &&
(deviceExtension->Flags & DBCUSB_FLAG_STARTED)) {
KeSetEvent(&deviceExtension->StopEvent,
1,
FALSE);
}
return ioCount;
}
VOID
DBCUSB_IncrementIoCount(
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
PDEVICE_EXTENSION deviceExtension;
deviceExtension = DeviceObject->DeviceExtension;
DBCUSB_ASSERT_EXT(deviceExtension);
InterlockedIncrement(&deviceExtension->PendingIoCount);
}
NTSTATUS
DBCUSB_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.
--*/
{
DBCUSB_DecrementIoCount(DeviceObject);
return IoStatus->Status;
}