411 lines
7.8 KiB
C
411 lines
7.8 KiB
C
/*++
|
||
|
||
Copyright (c) 1990 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
smbclass.c
|
||
|
||
Abstract:
|
||
|
||
SMBus Class Driver
|
||
|
||
Author:
|
||
|
||
Ken Reneris
|
||
|
||
Environment:
|
||
|
||
Notes:
|
||
|
||
|
||
Revision History:
|
||
27-Feb-97
|
||
Pnp support - Bob Moore
|
||
|
||
--*/
|
||
|
||
#include "smbc.h"
|
||
|
||
|
||
|
||
ULONG SMBCDebug = SMB_ERRORS;
|
||
|
||
//
|
||
// Prototypes
|
||
//
|
||
|
||
NTSTATUS
|
||
DriverEntry (
|
||
IN PDRIVER_OBJECT DriverObject,
|
||
IN PUNICODE_STRING RegistryPath
|
||
);
|
||
|
||
NTSTATUS
|
||
SmbClassInitializeDevice (
|
||
IN ULONG MajorVersion,
|
||
IN ULONG MinorVersion,
|
||
IN PDRIVER_OBJECT DriverObject
|
||
);
|
||
|
||
NTSTATUS
|
||
SmbClassDeviceInitialize (
|
||
PSMB_CLASS SmbClass
|
||
);
|
||
|
||
VOID
|
||
SmbCUnload(
|
||
IN PDRIVER_OBJECT DriverObject
|
||
);
|
||
|
||
NTSTATUS
|
||
SmbCOpenClose(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP Irp
|
||
);
|
||
|
||
NTSTATUS
|
||
SmbCInternalIoctl(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP Irp
|
||
);
|
||
|
||
NTSTATUS
|
||
SmbCPnpDispatch(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP Irp
|
||
);
|
||
|
||
NTSTATUS
|
||
SmbCPowerDispatch(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP Irp
|
||
);
|
||
|
||
NTSTATUS
|
||
SmbCForwardRequest(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP Irp
|
||
);
|
||
|
||
#ifdef ALLOC_PRAGMA
|
||
#pragma alloc_text(PAGE,DriverEntry)
|
||
#pragma alloc_text(PAGE,SmbClassInitializeDevice)
|
||
#pragma alloc_text(PAGE,SmbCOpenClose)
|
||
#pragma alloc_text(PAGE,SmbCUnload)
|
||
#endif
|
||
|
||
|
||
NTSTATUS
|
||
DriverEntry (
|
||
IN PDRIVER_OBJECT DriverObject,
|
||
IN PUNICODE_STRING RegistryPath
|
||
)
|
||
{
|
||
|
||
return STATUS_SUCCESS;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
SmbClassInitializeDevice (
|
||
IN ULONG MajorVersion,
|
||
IN ULONG MinorVersion,
|
||
IN PDRIVER_OBJECT DriverObject
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function is called by the SM bus miniport driver/DriverEntry
|
||
to perform class specific initialization
|
||
|
||
Arguments:
|
||
|
||
MajorVersion - Version #
|
||
MinorVersion - Version #
|
||
DriverObject - From miniport DriverEntry
|
||
|
||
Return Value:
|
||
|
||
Status
|
||
|
||
--*/
|
||
{
|
||
|
||
if (MajorVersion != SMB_CLASS_MAJOR_VERSION) {
|
||
return STATUS_REVISION_MISMATCH;
|
||
}
|
||
|
||
//
|
||
// Set up the device driver entry points.
|
||
//
|
||
|
||
DriverObject->DriverUnload = SmbCUnload;
|
||
DriverObject->MajorFunction[IRP_MJ_CREATE] = SmbCOpenClose;
|
||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = SmbCOpenClose;
|
||
DriverObject->MajorFunction[IRP_MJ_POWER] = SmbCPowerDispatch;
|
||
DriverObject->MajorFunction[IRP_MJ_PNP] = SmbCPnpDispatch;
|
||
|
||
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = SmbCInternalIoctl;
|
||
|
||
// DriverObject->MajorFunction[IRP_MJ_READ] = SmbCForwardRequest;
|
||
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = SmbCForwardRequest;
|
||
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = SmbCForwardRequest;
|
||
|
||
//
|
||
// Miniport will set up the AddDevice entry
|
||
//
|
||
|
||
return STATUS_SUCCESS;
|
||
|
||
}
|
||
|
||
|
||
|
||
VOID
|
||
SmbCUnload(
|
||
IN PDRIVER_OBJECT DriverObject
|
||
)
|
||
{
|
||
SmbPrint (SMB_NOTE, ("SmBCUnLoad: \n"));
|
||
|
||
if (DriverObject->DeviceObject != NULL) {
|
||
SmbPrint (SMB_ERROR, ("SmBCUnLoad: Unload called before all devices removed.\n"));
|
||
}
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
SmbCOpenClose(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP Irp
|
||
)
|
||
{
|
||
PAGED_CODE();
|
||
|
||
//
|
||
// Complete the request and return status.
|
||
//
|
||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||
Irp->IoStatus.Information = 0;
|
||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||
return(STATUS_SUCCESS);
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
SmbCPowerDispatch(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP Irp
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This is the dispatch routine for power 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;
|
||
NTSTATUS status;
|
||
|
||
SmbData = DeviceObject->DeviceExtension;
|
||
|
||
//
|
||
// What do we do with the irp?
|
||
//
|
||
PoStartNextPowerIrp( Irp );
|
||
if (SmbData->Class.LowerDeviceObject != NULL) {
|
||
|
||
//
|
||
// Forward the request along
|
||
//
|
||
IoSkipCurrentIrpStackLocation( Irp );
|
||
status = PoCallDriver( SmbData->Class.LowerDeviceObject, Irp );
|
||
|
||
} else {
|
||
|
||
//
|
||
// Complete the request with the current status
|
||
//
|
||
status = Irp->IoStatus.Status;
|
||
IoCompleteRequest( Irp, IO_NO_INCREMENT );
|
||
|
||
}
|
||
|
||
return status;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
SmbCInternalIoctl (
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP Irp
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is the dispatch routine for internal IOCTLs.
|
||
|
||
Arguments:
|
||
|
||
DeviceObject - Pointer to class device object.
|
||
Irp - Pointer to the request packet.
|
||
|
||
Return Value:
|
||
|
||
Status is returned.
|
||
|
||
--*/
|
||
|
||
{
|
||
PIO_STACK_LOCATION IrpSp;
|
||
PSMB_REQUEST SmbReq;
|
||
PSMBDATA Smb;
|
||
NTSTATUS Status;
|
||
|
||
//
|
||
// Get a pointer to the current parameters for this request. The
|
||
// information is contained in the current stack location.
|
||
//
|
||
|
||
Status = STATUS_INVALID_PARAMETER;
|
||
Irp->IoStatus.Information = 0;
|
||
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||
|
||
Smb = (PSMBDATA) DeviceObject->DeviceExtension;
|
||
|
||
|
||
switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
|
||
case SMB_BUS_REQUEST:
|
||
|
||
//
|
||
// Verify bus request is valid
|
||
//
|
||
|
||
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(SMB_REQUEST)) {
|
||
|
||
// Invalid buffer length
|
||
SmbPrint(SMB_NOTE, ("SmbCIoctl: Invalid bus_req length\n"));
|
||
Status = STATUS_BUFFER_TOO_SMALL;
|
||
Irp->IoStatus.Information = sizeof(SMB_REQUEST);
|
||
break;
|
||
}
|
||
|
||
SmbReq = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
|
||
if (SmbReq->Protocol > SMB_MAXIMUM_PROTOCOL ||
|
||
SmbReq->Address > 0x7F ||
|
||
(SmbReq->Protocol == SMB_WRITE_BLOCK &&
|
||
SmbReq->BlockLength > SMB_MAX_DATA_SIZE)) {
|
||
|
||
// Invalid param in request
|
||
SmbPrint(SMB_NOTE, ("SmbCIoctl: Invalid bus_req\n"));
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Mark request pending and queue it to the service queue
|
||
//
|
||
|
||
Status = STATUS_PENDING;
|
||
Irp->IoStatus.Status = STATUS_PENDING;
|
||
IoMarkIrpPending (Irp);
|
||
|
||
SmbClassLockDevice (&Smb->Class);
|
||
InsertTailList (&Smb->WorkQueue, &Irp->Tail.Overlay.ListEntry);
|
||
|
||
//
|
||
// Start IO if needed
|
||
//
|
||
|
||
SmbClassStartIo (Smb);
|
||
SmbClassUnlockDevice (&Smb->Class);
|
||
break;
|
||
|
||
case SMB_REGISTER_ALARM_NOTIFY:
|
||
|
||
//
|
||
// Registry for alarm notifications
|
||
//
|
||
|
||
Status = SmbCRegisterAlarm (Smb, Irp);
|
||
break;
|
||
|
||
case SMB_DEREGISTER_ALARM_NOTIFY:
|
||
|
||
//
|
||
// Deregister for alarm notifications
|
||
//
|
||
|
||
Status = SmbCDeregisterAlarm (Smb, Irp);
|
||
break;
|
||
|
||
default:
|
||
// complete with invalid parameter
|
||
break;
|
||
}
|
||
|
||
|
||
if (Status != STATUS_PENDING) {
|
||
Irp->IoStatus.Status = Status;
|
||
IoCompleteRequest (Irp, IO_NO_INCREMENT);
|
||
}
|
||
|
||
return Status;
|
||
}
|
||
|
||
NTSTATUS
|
||
SmbCForwardRequest(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP Irp
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine forwards the irp down the stack
|
||
|
||
Arguments:
|
||
|
||
DeviceObject - The target
|
||
Irp - The request
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS Status;
|
||
PSMBDATA Smb = (PSMBDATA) DeviceObject->DeviceExtension;
|
||
|
||
if (Smb->Class.LowerDeviceObject != NULL) {
|
||
|
||
IoSkipCurrentIrpStackLocation( Irp );
|
||
Status = IoCallDriver( Smb->Class.LowerDeviceObject, Irp );
|
||
|
||
} else {
|
||
|
||
Status = Irp->IoStatus.Status;
|
||
IoCompleteRequest( Irp, IO_NO_INCREMENT );
|
||
|
||
}
|
||
|
||
return Status;
|
||
}
|