1576 lines
		
	
	
		
			38 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1576 lines
		
	
	
		
			38 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*++
 | 
						||
 | 
						||
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;
 | 
						||
}
 | 
						||
 |