|
|
/*++
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; }
|