You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
586 lines
15 KiB
586 lines
15 KiB
/*++
|
|
|
|
Copyright (c) 1991 - 2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
## ## ### #### ## # #### ##### #####
|
|
### ### ### ## ### # ## # ## ## ## ##
|
|
######## ## ## ## #### # ## ## ## ## ##
|
|
# ### ## ## ## ## # #### ## ## ## ## ##
|
|
# # ## ####### ## # ### ## ##### #####
|
|
# ## ## ## ## # ## ## ## # ## ##
|
|
# ## ## ## #### # # ## #### ## ##
|
|
|
|
Abstract:
|
|
|
|
This module contains the code for all driver initializtion
|
|
and create/close IRP processing.
|
|
|
|
Author:
|
|
|
|
Wesley Witt (wesw) 1-Oct-2001
|
|
|
|
Environment:
|
|
|
|
Kernel mode only.
|
|
|
|
Notes:
|
|
|
|
|
|
--*/
|
|
|
|
#include "internal.h"
|
|
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(INIT,DriverEntry)
|
|
#pragma alloc_text(PAGE,SaPortCreate)
|
|
#pragma alloc_text(PAGE,SaPortClose)
|
|
#pragma alloc_text(PAGE,SaPortSystemControl)
|
|
#pragma alloc_text(PAGE,SaPortCleanup)
|
|
#endif
|
|
|
|
|
|
|
|
#if DBG
|
|
extern ULONG SaPortDebugLevel[5];
|
|
#endif
|
|
|
|
ULONG OsMajorVersion;
|
|
ULONG OsMinorVersion;
|
|
|
|
|
|
|
|
NTSTATUS
|
|
DllInitialize(
|
|
IN PUNICODE_STRING RegistryPath
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
DLL initialization funtion.
|
|
|
|
Arguments:
|
|
|
|
RegistryPath - String containing the path to the driver's registry data
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS
|
|
|
|
--*/
|
|
|
|
{
|
|
UNREFERENCED_PARAMETER(RegistryPath);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
DriverEntry(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PUNICODE_STRING RegistryPath
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Temporary entry point needed to initialize the scsi port driver.
|
|
|
|
Arguments:
|
|
|
|
DriverObject - Pointer to the driver object created by the system.
|
|
RegistryPath - String containing the path to the driver's registry data
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// NOTE: This routine should not be needed ! DriverEntry is defined
|
|
// in the miniport driver.
|
|
//
|
|
|
|
UNREFERENCED_PARAMETER(DriverObject);
|
|
UNREFERENCED_PARAMETER(RegistryPath);
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
SaPortDefaultDispatch(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is the default dispatch which passes down to the next layer.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - Supplies the device object.
|
|
Irp - Supplies the IO request packet.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
|
|
--*/
|
|
|
|
{
|
|
UNREFERENCED_PARAMETER(DeviceObject);
|
|
return CompleteRequest( Irp, STATUS_INVALID_DEVICE_REQUEST, 0 );
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
SaPortInitialize(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PUNICODE_STRING RegistryPath,
|
|
IN PSAPORT_INITIALIZATION_DATA SaPortInitData
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is the port driver's substitute for the miniport's DriverEntry
|
|
routine. The miniport driver MUST call this function from it's DriverEntry
|
|
to initialize the driver stack.
|
|
|
|
Arguments:
|
|
|
|
DriverObject - Pointer to the driver object created by the system.
|
|
RegistryPath - String containing the path to the driver's registry data
|
|
SaPortInitData - Pointer to the miniport's SAPORT_INITIALIZATION_DATA data structure
|
|
|
|
Return Value:
|
|
|
|
NT status code
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
PSAPORT_DRIVER_EXTENSION DriverExtension;
|
|
PKEY_VALUE_FULL_INFORMATION KeyInformation = NULL;
|
|
|
|
|
|
//
|
|
// Create and initialize the driver extension
|
|
//
|
|
|
|
DriverExtension = (PSAPORT_DRIVER_EXTENSION)IoGetDriverObjectExtension( DriverObject, SaPortInitialize );
|
|
if (DriverExtension == NULL) {
|
|
Status = IoAllocateDriverObjectExtension(
|
|
DriverObject,
|
|
SaPortInitialize,
|
|
sizeof(SAPORT_DRIVER_EXTENSION),
|
|
(PVOID*)&DriverExtension
|
|
);
|
|
if (!NT_SUCCESS(Status)) {
|
|
DebugPrint(( SaPortInitData->DeviceType, SAPORT_DEBUG_ERROR_LEVEL, "IoAllocateDriverObjectExtension failed [0x%08x]\n", Status ));
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
RtlCopyMemory( &DriverExtension->InitData, SaPortInitData, sizeof(SAPORT_INITIALIZATION_DATA) );
|
|
|
|
DriverExtension->RegistryPath.Buffer = (PWSTR) ExAllocatePool( NonPagedPool, RegistryPath->MaximumLength );
|
|
if (DriverExtension->RegistryPath.Buffer == NULL) {
|
|
REPORT_ERROR( SaPortInitData->DeviceType, "Failed to allocate pool for string", STATUS_INSUFFICIENT_RESOURCES );
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
RtlCopyMemory( DriverExtension->RegistryPath.Buffer, RegistryPath->Buffer, RegistryPath->Length );
|
|
|
|
DriverExtension->RegistryPath.Length = RegistryPath->Length;
|
|
DriverExtension->RegistryPath.MaximumLength = RegistryPath->MaximumLength;
|
|
|
|
DriverExtension->DriverObject = DriverObject;
|
|
|
|
//
|
|
// Get the OS version; this is used by the
|
|
// port driver and the mini-ports to have
|
|
// OS dependent code that is dynamic at runtime
|
|
//
|
|
|
|
GetOsVersion();
|
|
|
|
//
|
|
// Get the debug level value from the registry
|
|
//
|
|
|
|
#if DBG
|
|
SaPortDebugLevel[SaPortInitData->DeviceType] = 0;
|
|
|
|
Status = ReadRegistryValue( DriverExtension, RegistryPath, L"DebugLevel", &KeyInformation );
|
|
if (NT_SUCCESS(Status) && KeyInformation->Type == REG_DWORD) {
|
|
SaPortDebugLevel[SaPortInitData->DeviceType] = *(PULONG)((PUCHAR)KeyInformation + KeyInformation->DataOffset);
|
|
}
|
|
if (KeyInformation) {
|
|
ExFreePool( KeyInformation );
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Print a banner that includes the
|
|
// OS version and the version/build date
|
|
// of the driver
|
|
//
|
|
|
|
#if DBG
|
|
PrintDriverVersion( SaPortInitData->DeviceType, DriverObject );
|
|
#endif
|
|
|
|
//
|
|
// Parameter validation
|
|
//
|
|
|
|
if (SaPortInitData == NULL || SaPortInitData->StructSize != sizeof(SAPORT_INITIALIZATION_DATA) ||
|
|
SaPortInitData->HwInitialize == NULL || SaPortInitData->DeviceIoctl == NULL) {
|
|
|
|
DebugPrint(( SaPortInitData->DeviceType, SAPORT_DEBUG_ERROR_LEVEL, "SAPORT_INITIALIZATION_DATA fields are invalid [0x%08x]\n", STATUS_INVALID_PARAMETER ));
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// Now check the device specific callbacks
|
|
//
|
|
|
|
switch (SaPortInitData->DeviceType) {
|
|
case SA_DEVICE_DISPLAY:
|
|
if (SaPortInitData->Write == NULL) {
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
Status = STATUS_SUCCESS;
|
|
break;
|
|
|
|
case SA_DEVICE_KEYPAD:
|
|
if (SaPortInitData->Read == NULL) {
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
Status = STATUS_SUCCESS;
|
|
break;
|
|
|
|
case SA_DEVICE_NVRAM:
|
|
Status = STATUS_SUCCESS;
|
|
break;
|
|
|
|
case SA_DEVICE_WATCHDOG:
|
|
Status = STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
DebugPrint(( SaPortInitData->DeviceType, SAPORT_DEBUG_ERROR_LEVEL, "SAPORT_INITIALIZATION_DATA fields are invalid [0x%08x]\n", Status ));
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Do any device specific initialization
|
|
//
|
|
|
|
switch (SaPortInitData->DeviceType) {
|
|
case SA_DEVICE_DISPLAY:
|
|
Status = SaDisplayDeviceInitialization( DriverExtension );
|
|
break;
|
|
|
|
case SA_DEVICE_KEYPAD:
|
|
Status = SaKeypadDeviceInitialization( DriverExtension );
|
|
break;
|
|
|
|
case SA_DEVICE_NVRAM:
|
|
Status = SaNvramDeviceInitialization( DriverExtension );
|
|
break;
|
|
|
|
case SA_DEVICE_WATCHDOG:
|
|
Status = SaWatchdogDeviceInitialization( DriverExtension );
|
|
break;
|
|
}
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
DebugPrint(( SaPortInitData->DeviceType, SAPORT_DEBUG_ERROR_LEVEL, "Device specific initialization failed [0x%08x]\n", Status ));
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Set up the device driver entry points.
|
|
//
|
|
|
|
for (ULONG i=0; i<=IRP_MJ_MAXIMUM_FUNCTION; i++) {
|
|
DriverObject->MajorFunction[i] = SaPortDefaultDispatch;
|
|
}
|
|
|
|
DriverObject->MajorFunction[IRP_MJ_CREATE] = SaPortCreate;
|
|
DriverObject->MajorFunction[IRP_MJ_CLOSE] = SaPortClose;
|
|
DriverObject->MajorFunction[IRP_MJ_READ] = SaPortRead;
|
|
DriverObject->MajorFunction[IRP_MJ_WRITE] = SaPortWrite;
|
|
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = SaPortDeviceControl;
|
|
DriverObject->MajorFunction[IRP_MJ_PNP] = SaPortPnp;
|
|
DriverObject->MajorFunction[IRP_MJ_POWER] = SaPortPower;
|
|
DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = SaPortShutdown;
|
|
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = SaPortSystemControl;
|
|
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = SaPortCleanup;
|
|
|
|
//
|
|
// Set up the device driver's pnp-power routine & add routine
|
|
//
|
|
|
|
DriverObject->DriverExtension->AddDevice = SaPortAddDevice;
|
|
DriverObject->DriverStartIo = SaPortStartIo;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
SaPortCleanup(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is the dispatch routine for IRP cleanup.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - a pointer to the object that represents the device that I/O is to be done on.
|
|
Irp - a pointer to the I/O Request Packet for this request.
|
|
|
|
Return Value:
|
|
|
|
Always returns STATUS_SUCCESS, since this is a null operation.
|
|
|
|
--*/
|
|
|
|
{
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
IoCompleteRequest( Irp, IO_NO_INCREMENT );
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
SaPortCreate(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called only rarely by the I/O system; it's mainly
|
|
for layered drivers to call. All it does is complete the IRP
|
|
successfully.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - a pointer to the object that represents the device that I/O is to be done on.
|
|
Irp - a pointer to the I/O Request Packet for this request.
|
|
|
|
Return Value:
|
|
|
|
Always returns STATUS_SUCCESS, since this is a null operation.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
|
|
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
PVOID FsContext = NULL;
|
|
|
|
|
|
UNREFERENCED_PARAMETER( DeviceObject );
|
|
DebugPrint(( DeviceExtension->DeviceType, SAPORT_DEBUG_INFO_LEVEL, "SaPortCreate [fo=%08x]\n", IrpSp->FileObject ));
|
|
|
|
if (DeviceExtension->InitData->CreateRoutine) {
|
|
if (DeviceExtension->InitData->FileContextSize) {
|
|
FsContext = ExAllocatePool( PagedPool, DeviceExtension->InitData->FileContextSize );
|
|
if (FsContext == NULL) {
|
|
return CompleteRequest( Irp, STATUS_INSUFFICIENT_RESOURCES, 0 );
|
|
}
|
|
RtlZeroMemory( FsContext, DeviceExtension->InitData->FileContextSize );
|
|
}
|
|
Status = DeviceExtension->InitData->CreateRoutine(
|
|
DeviceExtension->MiniPortDeviceExtension,
|
|
Irp,
|
|
FsContext
|
|
);
|
|
if (!NT_SUCCESS(Status)) {
|
|
REPORT_ERROR( DeviceExtension->DeviceType, "Miniport create routine failed", Status );
|
|
if (FsContext) {
|
|
ExFreePool( FsContext );
|
|
}
|
|
} else {
|
|
IrpSp->FileObject->FsContext = FsContext;
|
|
}
|
|
}
|
|
|
|
return CompleteRequest( Irp, STATUS_SUCCESS, 0 );
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
SaPortClose(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called only rarely by the I/O system; it's mainly
|
|
for layered drivers to call. All it does is complete the IRP
|
|
successfully.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - a pointer to the object that represents the device that I/O is to be done on.
|
|
Irp - a pointer to the I/O Request Packet for this request.
|
|
|
|
Return Value:
|
|
|
|
Always returns STATUS_SUCCESS, since this is a null operation.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
|
|
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
PVOID FsContext;
|
|
|
|
|
|
UNREFERENCED_PARAMETER( DeviceObject );
|
|
DebugPrint(( DeviceExtension->DeviceType, SAPORT_DEBUG_INFO_LEVEL, "SaPortClose [fo=%08x]\n", IrpSp->FileObject ));
|
|
|
|
FsContext = (PVOID) IrpSp->FileObject->FsContext;
|
|
|
|
if (DeviceExtension->InitData->CloseRoutine) {
|
|
Status = DeviceExtension->InitData->CloseRoutine(
|
|
DeviceExtension->MiniPortDeviceExtension,
|
|
Irp,
|
|
FsContext
|
|
);
|
|
if (!NT_SUCCESS(Status)) {
|
|
REPORT_ERROR( DeviceExtension->DeviceType, "Miniport close routine failed", Status );
|
|
}
|
|
} else {
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
|
|
if (FsContext) {
|
|
IrpSp->FileObject->FsContext = NULL;
|
|
ExFreePool( FsContext );
|
|
}
|
|
|
|
return CompleteRequest( Irp, STATUS_SUCCESS, 0 );
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
SaPortShutdown(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called only rarely by the I/O system; it's mainly
|
|
for layered drivers to call. All it does is complete the IRP
|
|
successfully.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - a pointer to the object that represents the device that I/O is to be done on.
|
|
Irp - a pointer to the I/O Request Packet for this request.
|
|
|
|
Return Value:
|
|
|
|
Always returns STATUS_SUCCESS, since this is a null operation.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
|
|
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
switch (DeviceExtension->DriverExtension->InitData.DeviceType) {
|
|
case SA_DEVICE_DISPLAY:
|
|
Status = SaDisplayShutdownNotification( (PDISPLAY_DEVICE_EXTENSION)DeviceExtension, Irp, IrpSp );
|
|
break;
|
|
|
|
case SA_DEVICE_KEYPAD:
|
|
Status = SaKeypadShutdownNotification( (PKEYPAD_DEVICE_EXTENSION)DeviceExtension, Irp, IrpSp );
|
|
break;
|
|
|
|
case SA_DEVICE_NVRAM:
|
|
Status = SaNvramShutdownNotification( (PNVRAM_DEVICE_EXTENSION)DeviceExtension, Irp, IrpSp );
|
|
break;
|
|
|
|
case SA_DEVICE_WATCHDOG:
|
|
Status = SaWatchdogShutdownNotification( (PWATCHDOG_DEVICE_EXTENSION)DeviceExtension, Irp, IrpSp );
|
|
break;
|
|
}
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
REPORT_ERROR( DeviceExtension->DeviceType, "Device specific shutdown notification failed", Status );
|
|
}
|
|
|
|
return ForwardRequest( Irp, DeviceExtension->TargetObject );
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
SaPortSystemControl(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
IRP_MJ_SYSTEM_CONTROL dispatch routine. Currently, we don't handle
|
|
this. So, if this is FDO just pass it to the lower driver. If this
|
|
is PDO complete the irp with changing the irp status.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - a pointer to the object that represents the device that I/O is to be done on.
|
|
Irp - a pointer to the I/O Request Packet for this request.
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
|
|
|
|
|
|
IoSkipCurrentIrpStackLocation( Irp );
|
|
return IoCallDriver( DeviceExtension->TargetObject, Irp );
|
|
}
|