|
|
/*++
Copyright (c) 1990 Microsoft Corporation
Module Name:
smbhc.c
Abstract:
SMB Host Controller Driver
Author:
Ken Reneris
Environment:
Notes:
Revision History:
--*/
#include "smbhcp.h"
ULONG SMBHCDebug = 0x0;
//
// Prototypes
//
typedef struct { ULONG Base; ULONG Query; } NEW_HC_DEVICE, *PNEW_HC_DEVICE;
NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath );
NTSTATUS SmbHcAddDevice( IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT Pdo );
NTSTATUS SmbHcNewHc ( IN PSMB_CLASS SmbClass, IN PVOID Extension, IN PVOID Context );
NTSTATUS SmbHcSynchronousRequest ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context );
NTSTATUS SmbHcResetDevice ( IN struct _SMB_CLASS *SmbClass, IN PVOID SmbMiniport );
NTSTATUS SmbHcStopDevice ( IN struct _SMB_CLASS *SmbClass, IN PVOID SmbMiniport );
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT,DriverEntry)
#pragma alloc_text(PAGE,SmbHcAddDevice)
#pragma alloc_text(PAGE,SmbHcResetDevice)
#pragma alloc_text(PAGE,SmbHcStopDevice)
#pragma alloc_text(PAGE,SmbHcNewHc)
#pragma alloc_text(PAGE,SmbHcSynchronousRequest)
#endif
NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) /*++
Routine Description:
This routine initializes the SM Bus Host Controller Driver
Arguments:
DriverObject - Pointer to driver object created by system. RegistryPath - Pointer to the Unicode name of the registry path for this driver.
Return Value:
The function value is the final status from the initialization operation.
--*/
{ NTSTATUS Status;
//
// Have class driver allocate a new SMB miniport device
//
Status = SmbClassInitializeDevice ( SMB_HC_MAJOR_VERSION, SMB_HC_MINOR_VERSION, DriverObject );
//
// AddDevice comes directly to this miniport
//
DriverObject->DriverExtension->AddDevice = SmbHcAddDevice;
return (Status); }
NTSTATUS SmbHcAddDevice( IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT Pdo )
/*++
Routine Description:
This routine creates functional device objects for each SmbHc controller in the system and attaches them to the physical device objects for the controllers
Arguments:
DriverObject - a pointer to the object for this driver PhysicalDeviceObject - a pointer to the physical object we need to attach to
Return Value:
Status from device creation and initialization
--*/
{ NTSTATUS status; PDEVICE_OBJECT fdo = NULL;
PAGED_CODE();
SmbPrint(SMB_LOW, ("SmbHcAddDevice Entered with pdo %x\n", Pdo));
if (Pdo == NULL) {
//
// Have we been asked to do detection on our own?
// if so just return no more devices
//
SmbPrint(SMB_LOW, ("SmbHcAddDevice - asked to do detection\n")); return STATUS_NO_MORE_ENTRIES; }
//
// Create and initialize the new functional device object
//
status = SmbClassCreateFdo( DriverObject, Pdo, sizeof (SMB_DATA), SmbHcNewHc, NULL, &fdo );
if (!NT_SUCCESS(status) || fdo == NULL) { SmbPrint(SMB_LOW, ("SmbHcAddDevice - error creating Fdo. Status = %08x\n", status)); }
return status; }
NTSTATUS SmbHcNewHc ( IN PSMB_CLASS SmbClass, IN PVOID Extension, IN PVOID Context ) /*++
Routine Description:
This function is called by the smb bus class driver for the miniport to perform miniport specific initialization
Arguments:
SmbClass - Shared class driver & miniport structure. Extension - Buffer for miniport specific storage Context - Passed through class driver
Return Value:
Status
--*/
{ ACPI_EVAL_INPUT_BUFFER inputBuffer; ACPI_EVAL_OUTPUT_BUFFER outputBuffer; IO_STATUS_BLOCK ioStatusBlock; KEVENT event; NTSTATUS status; PACPI_METHOD_ARGUMENT argument; PIRP irp; PSMB_DATA smbData; ULONG cmReturn;
PAGED_CODE();
SmbPrint(SMB_LOW, ("SmbHcNewHc: Entry\n") );
smbData = (PSMB_DATA) Extension;
//
// Fill in SmbClass info
//
SmbClass->StartIo = SmbHcStartIo; SmbClass->ResetDevice = SmbHcResetDevice; SmbClass->StopDevice = SmbHcStopDevice;
//
// Lower device is the EC driver, but we will use the ACPI PDO, since
// the ACPI filter driver will pass it thru.
//
smbData->Pdo = SmbClass->PDO; smbData->LowerDeviceObject = SmbClass->LowerDeviceObject; // ACPI filter will handle it
//
// Initialize the input parameters
//
RtlZeroMemory( &inputBuffer, sizeof(ACPI_EVAL_INPUT_BUFFER) ); inputBuffer.MethodNameAsUlong = CM_EC_METHOD; inputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;
//
// Initialize the even to wait on
//
KeInitializeEvent( &event, NotificationEvent, FALSE);
//
// Build the synchronouxe request
//
irp = IoBuildDeviceIoControlRequest( IOCTL_ACPI_ASYNC_EVAL_METHOD, SmbClass->LowerDeviceObject, &inputBuffer, sizeof(ACPI_EVAL_INPUT_BUFFER), &outputBuffer, sizeof(ACPI_EVAL_OUTPUT_BUFFER), FALSE, &event, &ioStatusBlock ); if (!irp) {
SmbPrint(SMB_ERROR, ("SmbHcNewHc: Couldn't allocate Irp\n")); return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Send to ACPI driver
//
status = IoCallDriver (smbData->LowerDeviceObject, irp); if (status == STATUS_PENDING) {
KeWaitForSingleObject( &event, Suspended, KernelMode, FALSE, NULL); status = ioStatusBlock.Status;
}
argument = outputBuffer.Argument; if (!NT_SUCCESS(status) || outputBuffer.Signature != ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE || outputBuffer.Count == 0 || argument->Type != ACPI_METHOD_ARGUMENT_INTEGER) {
SmbPrint(SMB_LOW, ("SmbHcNewHc: _EC Control Method failed, status = %Lx\n", status)); return status;
}
//
// Remember the result
//
cmReturn = argument->Argument;
//
// Fill in miniport info
//
smbData->Class = SmbClass; smbData->IoState = SMB_IO_IDLE; smbData->EcQuery = (UCHAR) cmReturn; // Per ACPI Spec, LSB=Query
smbData->EcBase = (UCHAR) (cmReturn >> 8); // Per ACPI Spec, MSB=Base
SmbPrint(SMB_LOW, ("SmbHcNewHc: Exit\n")); return status; }
NTSTATUS SmbHcSynchronousRequest ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context ) /*++
Routine Description:
Completion function for synchronous IRPs sent to this driver. Context is the event to set
--*/ { PAGED_CODE(); return STATUS_MORE_PROCESSING_REQUIRED; }
NTSTATUS SmbHcResetDevice ( IN struct _SMB_CLASS *SmbClass, IN PVOID SmbMiniport ) { EC_HANDLER_REQUEST queryConnect; PSMB_DATA smbData; KEVENT event; NTSTATUS status; IO_STATUS_BLOCK ioStatusBlock; PIRP irp;
SmbPrint(SMB_LOW, ("SmbHcResetDevice: Entry\n") );
PAGED_CODE();
smbData = (PSMB_DATA) SmbMiniport;
//
// Initialize the even to wait on
//
KeInitializeEvent( &event, NotificationEvent, FALSE);
//
// Build the input data to the EC
//
queryConnect.Vector = smbData->EcQuery; queryConnect.Handler = SmbHcQueryEvent; queryConnect.Context = smbData;
//
// Connect Query notify with EC driver
//
irp = IoBuildDeviceIoControlRequest( EC_CONNECT_QUERY_HANDLER, smbData->LowerDeviceObject, &queryConnect, sizeof(EC_HANDLER_REQUEST), NULL, 0, TRUE, &event, &ioStatusBlock );
if (!irp) {
SmbPrint(SMB_ERROR, ("SmbHcResetDevice: Couldn't allocate Irp\n")); return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Send off to EC driver
//
status = IoCallDriver (smbData->LowerDeviceObject, irp); if (status == STATUS_PENDING) {
KeWaitForSingleObject( &event, Suspended, KernelMode, FALSE, NULL); status = ioStatusBlock.Status;
}
if (!NT_SUCCESS(status)) {
SmbPrint(SMB_LOW, ("SmbHcResetDevice: Connect query failed, status = %Lx\n", status));
}
SmbPrint(SMB_LOW, ("SmbHcResetDevice: Exit\n")); return status; }
NTSTATUS SmbHcStopDevice ( IN struct _SMB_CLASS *SmbClass, IN PVOID SmbMiniport ) { EC_HANDLER_REQUEST queryConnect; PSMB_DATA smbData; KEVENT event; NTSTATUS status; IO_STATUS_BLOCK ioStatusBlock; PIRP irp;
SmbPrint(SMB_LOW, ("SmbHcStopDevice: Entry\n") );
//
// There is currently no way to test this code path.
// Leaving untested code for potential future use/development
//
DbgPrint("SmbHcStopDevice: Encountered previously untested code.\n" "enter 'g' to continue, or contact the appropriate developer.\n"); DbgBreakPoint();
// Cutting code to reduce file size (see above comment)
#if 0
PAGED_CODE();
smbData = (PSMB_DATA) SmbMiniport;
//
// Initialize the even to wait on
//
KeInitializeEvent( &event, NotificationEvent, FALSE);
//
// Build the input data to the EC
//
queryConnect.Vector = smbData->EcQuery; queryConnect.Handler = SmbHcQueryEvent; queryConnect.Context = smbData;
//
// Connect Query notify with EC driver
//
irp = IoBuildDeviceIoControlRequest( EC_DISCONNECT_QUERY_HANDLER, smbData->LowerDeviceObject, &queryConnect, sizeof(EC_HANDLER_REQUEST), NULL, 0, TRUE, &event, &ioStatusBlock );
if (!irp) {
SmbPrint(SMB_ERROR, ("SmbHcStopDevice: Couldn't allocate Irp\n")); return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Send off to EC driver
//
status = IoCallDriver (smbData->LowerDeviceObject, irp); if (status == STATUS_PENDING) {
KeWaitForSingleObject( &event, Suspended, KernelMode, FALSE, NULL); status = ioStatusBlock.Status;
}
if (!NT_SUCCESS(status)) {
SmbPrint(SMB_LOW, ("SmbHcStopDevice: Connect query failed, status = %Lx\n", status));
}
SmbPrint(SMB_LOW, ("SmbHcStopDevice: Exit\n")); return status; #endif
return STATUS_SUCCESS;
}
|