|
|
/*++
Copyright (c) 1990 Microsoft Corporation
Module Name:
smbcpnp.c
Abstract:
SMBus Class Driver Plug and Play support
Author:
Bob Moore (Intel)
Environment:
Notes:
Revision History:
--*/
#include "smbc.h"
#include "oprghdlr.h"
#define SMBHC_DEVICE_NAME L"\\Device\\SmbHc"
extern ULONG SMBCDebug;
//
// Prototypes
//
NTSTATUS SmbCPnpDispatch( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
NTSTATUS SmbCStartDevice ( IN PDEVICE_OBJECT FDO, IN PIRP Irp );
NTSTATUS SmbCStopDevice ( IN PDEVICE_OBJECT FDO, IN PIRP Irp );
NTSTATUS SmbClassCreateFdo ( IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PDO, IN ULONG MiniportExtensionSize, IN PSMB_INITIALIZE_MINIPORT MiniportInitialize, IN PVOID MiniportContext, OUT PDEVICE_OBJECT *FDO );
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE,SmbCPnpDispatch)
#pragma alloc_text(PAGE,SmbCStartDevice)
#pragma alloc_text(PAGE,SmbClassCreateFdo)
#endif
NTSTATUS SmbCPnpDispatch( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
/*++
Routine Description:
This routine is the dispatcher for plug and play requests.
Arguments:
DeviceObject - Pointer to class device object. Irp - Pointer to the request packet.
Return Value:
Status is returned.
--*/
{ PIO_STACK_LOCATION irpStack; PSMBDATA SmbData; KEVENT syncEvent; NTSTATUS status = STATUS_NOT_SUPPORTED;
PAGED_CODE();
//
// Get a pointer to the current parameters for this request. The
// information is contained in the current stack location.
//
irpStack = IoGetCurrentIrpStackLocation(Irp); SmbData = (PSMBDATA) DeviceObject->DeviceExtension;
SmbPrint (SMB_NOTE, ("SmbCPnpDispatch: PnP dispatch, minor = %d\n", irpStack->MinorFunction));
//
// Dispatch minor function
//
switch (irpStack->MinorFunction) {
case IRP_MN_START_DEVICE: IoCopyCurrentIrpStackLocationToNext (Irp);
KeInitializeEvent(&syncEvent, SynchronizationEvent, FALSE);
IoSetCompletionRoutine(Irp, SmbCSynchronousRequest, &syncEvent, TRUE, TRUE, TRUE);
status = IoCallDriver(SmbData->Class.LowerDeviceObject, Irp);
if (status == STATUS_PENDING) { KeWaitForSingleObject(&syncEvent, Executive, KernelMode, FALSE, NULL); status = Irp->IoStatus.Status; } status = SmbCStartDevice (DeviceObject, Irp); IoCompleteRequest(Irp, IO_NO_INCREMENT); return status;
case IRP_MN_STOP_DEVICE: status = SmbCStopDevice(DeviceObject, Irp); break;
case IRP_MN_QUERY_STOP_DEVICE:
SmbPrint(SMB_LOW, ("SmbCPnp: IRP_MN_QUERY_STOP_DEVICE\n"));
status = STATUS_SUCCESS; break;
case IRP_MN_CANCEL_STOP_DEVICE:
SmbPrint(SMB_LOW, ("SmbCPnp: IRP_MN_CANCEL_STOP_DEVICE\n"));
status = STATUS_SUCCESS; break;
default: SmbPrint(SMB_LOW, ("SmbCPnp: Unimplemented PNP minor code %d\n", irpStack->MinorFunction)); }
if (status != STATUS_NOT_SUPPORTED) {
Irp->IoStatus.Status = status; }
if (NT_SUCCESS(status) || (status == STATUS_NOT_SUPPORTED)) {
IoSkipCurrentIrpStackLocation (Irp); status = IoCallDriver(SmbData->Class.LowerDeviceObject, Irp) ;
} else {
IoCompleteRequest (Irp, IO_NO_INCREMENT);
}
return status; }
NTSTATUS SmbClassCreateFdo ( IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PDO, IN ULONG MiniportExtensionSize, IN PSMB_INITIALIZE_MINIPORT MiniportInitialize, IN PVOID MiniportContext, OUT PDEVICE_OBJECT *OutFDO ) /*++
Routine Description:
This routine will create and initialize a functional device object to be attached to a SMBus Host controller PDO. It is called from the miniport AddDevice routine.
Arguments:
DriverObject - a pointer to the driver object this is created under PDO - a pointer to the SMBus HC PDO MiniportExtensionSize - Extension size required by the miniport MiniportInitialize - a pointer to the miniport init routine MiniportContext - Miniport-defined context info OutFDO - a location to store the pointer to the new device object
Return Value:
STATUS_SUCCESS if everything was successful reason for failure otherwise
--*/
{ NTSTATUS Status; UNICODE_STRING UnicodeString; PDEVICE_OBJECT FDO; PDEVICE_OBJECT lowerDevice = NULL; PSMBDATA SmbData;
//
// Allocate a device object for this miniport
//
RtlInitUnicodeString(&UnicodeString, SMBHC_DEVICE_NAME);
Status = IoCreateDevice( DriverObject, sizeof (SMBDATA) + MiniportExtensionSize, &UnicodeString, FILE_DEVICE_UNKNOWN, // DeviceType
0, FALSE, &FDO );
if (Status != STATUS_SUCCESS) { SmbPrint(SMB_LOW, ("SmbC: unable to create device object: %X\n", Status )); return(Status); }
//
// Initialize class data
//
FDO->Flags |= DO_BUFFERED_IO;
//
// Layer our FDO on top of the PDO
//
lowerDevice = IoAttachDeviceToDeviceStack(FDO,PDO);
//
// No status. Do the best we can.
//
ASSERT(lowerDevice);
//
// Fill out class data
//
SmbData = (PSMBDATA) FDO->DeviceExtension; SmbData->Class.MajorVersion = SMB_CLASS_MAJOR_VERSION; SmbData->Class.MinorVersion = SMB_CLASS_MINOR_VERSION; SmbData->Class.Miniport = SmbData + 1; SmbData->Class.DeviceObject = FDO; SmbData->Class.LowerDeviceObject = lowerDevice; SmbData->Class.PDO = PDO; SmbData->Class.CurrentIrp = NULL; SmbData->Class.CurrentSmb = NULL;
KeInitializeEvent (&SmbData->AlarmEvent, NotificationEvent, FALSE); KeInitializeSpinLock (&SmbData->SpinLock); InitializeListHead (&SmbData->WorkQueue); InitializeListHead (&SmbData->Alarms);
KeInitializeTimer (&SmbData->RetryTimer); KeInitializeDpc (&SmbData->RetryDpc, SmbCRetry, SmbData);
//
// Miniport initialization
//
Status = MiniportInitialize (&SmbData->Class, SmbData->Class.Miniport, MiniportContext); FDO->Flags |= DO_POWER_PAGABLE; FDO->Flags &= ~DO_DEVICE_INITIALIZING;
if (!NT_SUCCESS(Status)) { IoDeleteDevice (FDO); return Status; }
*OutFDO = FDO; return Status; }
NTSTATUS SmbCStartDevice ( IN PDEVICE_OBJECT FDO, IN PIRP Irp ) { NTSTATUS Status; PSMBDATA SmbData;
SmbPrint(SMB_LOW, ("SmbCStartDevice Entered with fdo %x\n", FDO));
SmbData = (PSMBDATA) FDO->DeviceExtension; //
// Initialize the Miniclass driver.
//
SmbData->Class.CurrentIrp = Irp;
Status = SmbData->Class.ResetDevice ( &SmbData->Class, SmbData->Class.Miniport );
SmbData->Class.CurrentIrp = NULL; if (!NT_SUCCESS(Status)) {
SmbPrint(SMB_ERROR, ("SmbCStartDevice: Class.ResetDevice failed. = %Lx\n", Status));
return Status; } //
// Install the Operation Region handlers
//
Status = RegisterOpRegionHandler (SmbData->Class.LowerDeviceObject, ACPI_OPREGION_ACCESS_AS_RAW, ACPI_OPREGION_REGION_SPACE_SMB, (PACPI_OP_REGION_HANDLER)SmbCRawOpRegionHandler, SmbData, 0, &SmbData->RawOperationRegionObject); if (!NT_SUCCESS(Status)) {
SmbPrint(SMB_ERROR, ("SmbCStartDevice: Could not install raw Op region handler, status = %Lx\n", Status)); //
// Failure to register opregion handler is not critical. It just reduces functionality
//
SmbData->RawOperationRegionObject = NULL; Status = STATUS_SUCCESS; }
return Status; }
NTSTATUS SmbCStopDevice ( IN PDEVICE_OBJECT FDO, IN PIRP Irp ) { NTSTATUS Status; PSMBDATA SmbData;
SmbPrint(SMB_LOW, ("SmbCStopDevice Entered with fdo %x\n", FDO));
SmbData = (PSMBDATA) FDO->DeviceExtension;
//
// Stop handling operation regions before turning off driver.
//
if (SmbData->RawOperationRegionObject) { DeRegisterOpRegionHandler (SmbData->Class.LowerDeviceObject, SmbData->RawOperationRegionObject); }
//
// Stop the device
//
SmbData->Class.CurrentIrp = Irp; Status = SmbData->Class.StopDevice ( &SmbData->Class, SmbData->Class.Miniport );
SmbData->Class.CurrentIrp = NULL;
return Status; }
NTSTATUS SmbCSynchronousRequest ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PKEVENT IoCompletionEvent ) /*++
Routine Description:
Completion function for synchronous IRPs sent to this driver. No event.
--*/ { KeSetEvent(IoCompletionEvent, IO_NO_INCREMENT, FALSE);
return STATUS_MORE_PROCESSING_REQUIRED; }
|