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.
8029 lines
280 KiB
8029 lines
280 KiB
/*
|
|
|
|
Copyright (c) 1997 M-Systems
|
|
|
|
Module Name:
|
|
|
|
tffsport.c
|
|
|
|
Author:
|
|
|
|
Alexander Geller
|
|
|
|
Environment:
|
|
|
|
Kernel mode
|
|
|
|
--*/
|
|
|
|
#include "ntddk.h"
|
|
#include "scsi.h"
|
|
#include "ntdddisk.h"
|
|
#include "ntddscsi.h"
|
|
#include "string.h"
|
|
#include "stdio.h"
|
|
#include "stdarg.h"
|
|
#include "ntddstor.h"
|
|
#include "initguid.h"
|
|
#include "ntddscsi.h"
|
|
|
|
#include "blockdev.h"
|
|
#include "nfdc2148.h"
|
|
//#include "mdocplus.h"
|
|
#include "tffsport.h"
|
|
#include "ntioctl.h"
|
|
|
|
#define TFFSPORT_POOL_TAG 'dffT' // - Tffd Tffsport Driver Tag
|
|
|
|
KTIMER timerObject;
|
|
KDPC timerDpc;
|
|
BOOLEAN timerWasStarted = FALSE;
|
|
BOOLEAN patitionTwo = FALSE;
|
|
|
|
|
|
|
|
|
|
/* Private GUID for WMI */
|
|
DEFINE_GUID(WmiTffsportAddressGuid,
|
|
0xd9a8f150,
|
|
0xf830,
|
|
0x11d2,
|
|
0xb5, 0x72, 0x00, 0xc0, 0x4f, 0x65, 0xb3, 0xd9
|
|
);
|
|
|
|
TempINFO info[VOLUMES];
|
|
|
|
ULONG TrueffsNextDeviceNumber_tffsport = 0;
|
|
CRASHDUMP_DATA DumpData;
|
|
extern NTsocketParams driveInfo[SOCKETS];
|
|
ULONG VerifyWriteState[SOCKETS];
|
|
FAST_MUTEX driveInfoReferenceMutex;
|
|
|
|
const TFFS_DEVICE_TYPE TffsDeviceType_tffsport[] = {
|
|
{"Disk", "GenDisk", "DiskPeripheral"}
|
|
};
|
|
|
|
const TFFS_DEVICE_TYPE TffsDeviceTypeFDO_tffsport[] = {
|
|
{"Controller", "FlashDiskController", "FlashDiskPeripheral"}
|
|
};
|
|
|
|
|
|
BOOLEAN
|
|
DebugLogEvent(IN PDRIVER_OBJECT DriverObject, IN ULONG Value);
|
|
|
|
|
|
NTSTATUS
|
|
TrueffsStartDeviceOnDetect(IN PDEVICE_EXTENSION deviceExtension, IN PCM_RESOURCE_LIST ResourceList, IN BOOLEAN CheckResources);
|
|
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(INIT, DriverEntry)
|
|
#pragma alloc_text(PAGE, TrueffsThread)
|
|
#endif
|
|
|
|
|
|
NTSTATUS
|
|
DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called at system initialization time so we can fill in the basic dispatch points
|
|
|
|
Arguments:
|
|
|
|
DriverObject - Supplies the driver object.
|
|
|
|
RegistryPath - Supplies the registry path for this driver.
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS
|
|
|
|
--*/
|
|
|
|
{
|
|
PTRUEFFSDRIVER_EXTENSION trueffsDriverExtension;
|
|
NTSTATUS status;
|
|
ULONG i;
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DriverEntry\n"));
|
|
DebugLogEvent(DriverObject, 1);
|
|
DebugLogEvent(DriverObject, 2);
|
|
DebugLogEvent(DriverObject, 3);
|
|
|
|
for (i = 0; i < SOCKETS; i++) {
|
|
driveInfo[i].interfAlive = 0;
|
|
driveInfo[i].fdoExtension = NULL;
|
|
}
|
|
|
|
for (i = 0; i < VOLUMES; i++) {
|
|
info[i].baseAddress= 0;
|
|
info[i].nextPartition= 0;
|
|
}
|
|
|
|
ExInitializeFastMutex(&driveInfoReferenceMutex);
|
|
|
|
if (!DriverObject) {
|
|
|
|
return TrueffsCrashDumpDriverEntry(RegistryPath);
|
|
}
|
|
|
|
// Allocate Driver Object Extension for storing the RegistryPath
|
|
status = IoAllocateDriverObjectExtension(
|
|
DriverObject,
|
|
DRIVER_OBJECT_EXTENSION_ID,
|
|
sizeof (DRIVER_EXTENSION),
|
|
&trueffsDriverExtension
|
|
);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
|
|
TffsDebugPrint ((TFFS_DEB_ERROR,"Trueffs: DriverEntry: Unable to create driver extension\n"));
|
|
return status;
|
|
}
|
|
|
|
RtlZeroMemory (
|
|
trueffsDriverExtension,
|
|
sizeof (DRIVER_EXTENSION)
|
|
);
|
|
|
|
// make copy of the RegistryPath
|
|
trueffsDriverExtension->RegistryPath.Buffer = ExAllocatePoolWithTag (NonPagedPool, RegistryPath->Length * sizeof(WCHAR), TFFSPORT_POOL_TAG);
|
|
if (trueffsDriverExtension->RegistryPath.Buffer == NULL) {
|
|
TffsDebugPrint ((TFFS_DEB_ERROR,"Trueffs: DriverEntry: Unable to allocate memory for registry path\n"));
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
trueffsDriverExtension->RegistryPath.Length = 0;
|
|
trueffsDriverExtension->RegistryPath.MaximumLength = RegistryPath->Length;
|
|
RtlCopyUnicodeString (&trueffsDriverExtension->RegistryPath, RegistryPath);
|
|
|
|
// Initialize the Driver Object with driver's entry points
|
|
DriverObject->MajorFunction[IRP_MJ_CREATE] = TrueffsCreateClose;
|
|
DriverObject->MajorFunction[IRP_MJ_CLOSE] = TrueffsCreateClose;
|
|
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = TrueffsDeviceControl;
|
|
DriverObject->MajorFunction[IRP_MJ_SCSI] = TrueffsScsiRequests;
|
|
|
|
DriverObject->DriverExtension->AddDevice = TrueffsAddDevice;
|
|
DriverObject->MajorFunction[IRP_MJ_PNP] = TrueffsPnpDeviceControl;
|
|
DriverObject->MajorFunction[IRP_MJ_POWER] = TrueffsPowerControl;
|
|
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = TrueffsDispatchSystemControl;
|
|
|
|
DriverObject->DriverStartIo = TrueffsStartIo;
|
|
DriverObject->DriverUnload = TrueffsUnload;
|
|
|
|
TrueffsWmiInit();
|
|
TrueffsDetectDiskOnChip(DriverObject, RegistryPath);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
TrueffsFetchKeyValue(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PUNICODE_STRING RegistryPath,
|
|
IN PWSTR KeyName,
|
|
IN OUT ULONG* KeyValue
|
|
)
|
|
{
|
|
RTL_QUERY_REGISTRY_TABLE Table[3]; //must be parmaters + 2
|
|
UNICODE_STRING SubPath;
|
|
WCHAR PathNameBuffer[30];
|
|
NTSTATUS ntStatus;
|
|
|
|
//TffsDebugPrint(("Trueffs: TrueffsFetchKeyValue Start\n"));
|
|
|
|
// Prepare Table - Must be Zero Terminated
|
|
RtlZeroMemory(Table, sizeof(Table));
|
|
|
|
// Create name string for the query Table
|
|
SubPath.Buffer = PathNameBuffer;
|
|
SubPath.MaximumLength = sizeof(PathNameBuffer);
|
|
SubPath.Length = 0;
|
|
|
|
RtlAppendUnicodeToString(&SubPath,L"Parameters");
|
|
|
|
// 0 - just move us to the correct place under "Parameters" subkey
|
|
Table[0].Name = SubPath.Buffer;
|
|
Table[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
|
|
|
|
Table[1].Name = KeyName;
|
|
Table[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
|
Table[1].EntryContext = KeyValue;
|
|
|
|
*KeyValue = -1;
|
|
|
|
ntStatus = RtlQueryRegistryValues(
|
|
RTL_REGISTRY_ABSOLUTE,
|
|
RegistryPath->Buffer,
|
|
Table,
|
|
NULL,NULL);
|
|
|
|
if ( ((*KeyValue)==-1) || (!NT_SUCCESS(ntStatus)) )
|
|
{
|
|
//TffsDebugPrint(("Trueffs: TrueffsFetchKeyValue End, Key Not Found\n"));
|
|
return STATUS_OBJECT_NAME_NOT_FOUND;
|
|
}
|
|
else
|
|
{
|
|
//TffsDebugPrint(("Trueffs: TrueffsFetchKeyValue End, Key Found\n"));
|
|
return ntStatus;
|
|
}
|
|
|
|
}
|
|
|
|
NTSTATUS
|
|
TrueffsDetectRegistryValues(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PUNICODE_STRING RegistryPath
|
|
)
|
|
{
|
|
RTL_QUERY_REGISTRY_TABLE Table[14]; //must be parmaters + 2
|
|
|
|
|
|
NTSTATUS ntStatus;
|
|
ULONG prevValue;
|
|
ULONG keyValue;
|
|
FLStatus status = flOK;
|
|
ULONG CurrVerifyWriteState;
|
|
ULONG currSocket = 0;
|
|
|
|
|
|
|
|
//TffsDebugPrint(("Trueffs: TrueffsDetectRegistryValues Start\n"));
|
|
#ifdef ENVIRONMENT_VARS
|
|
ntStatus = TrueffsFetchKeyValue(DriverObject,RegistryPath,L"FL_ISRAM_CHECK_ENABLED",&keyValue);
|
|
if (NT_SUCCESS(ntStatus))
|
|
status = flSetEnvAll(FL_IS_RAM_CHECK_ENABLED,keyValue,&prevValue);
|
|
|
|
ntStatus = TrueffsFetchKeyValue(DriverObject,RegistryPath,L"FL_TL_CACHE_ENABLED",&keyValue);
|
|
if (NT_SUCCESS(ntStatus))
|
|
status = flSetEnvAll(FL_TL_CACHE_ENABLED,keyValue,&prevValue);
|
|
|
|
ntStatus = TrueffsFetchKeyValue(DriverObject,RegistryPath,L"FL_DOC_8BIT_ACCESS",&keyValue);
|
|
if (NT_SUCCESS(ntStatus))
|
|
status = flSetEnvAll(FL_DOC_8BIT_ACCESS,keyValue,&prevValue);
|
|
|
|
ntStatus = TrueffsFetchKeyValue(DriverObject,RegistryPath,L"FL_SUSPEND_MODE",&keyValue);
|
|
if (NT_SUCCESS(ntStatus))
|
|
status = flSetEnvAll(FL_SUSPEND_MODE,keyValue,&prevValue);
|
|
|
|
ntStatus = TrueffsFetchKeyValue(DriverObject,RegistryPath,L"FL_MTD_BUS_ACCESS_TYPE",&keyValue);
|
|
if (NT_SUCCESS(ntStatus))
|
|
status = flSetEnvAll(FL_MTD_BUS_ACCESS_TYPE,keyValue,&prevValue);
|
|
|
|
ntStatus = TrueffsFetchKeyValue(DriverObject,RegistryPath,L"FL_SET_POLICY",&keyValue);
|
|
if (NT_SUCCESS(ntStatus))
|
|
status = flSetEnvAll(FL_SET_POLICY,keyValue,&prevValue);
|
|
|
|
|
|
|
|
ntStatus = TrueffsFetchKeyValue(DriverObject,RegistryPath,L"FL_VERIFY_WRITE_BDTL0",&CurrVerifyWriteState);
|
|
if (NT_SUCCESS(ntStatus) && currSocket++<SOCKETS)
|
|
VerifyWriteState[0] = CurrVerifyWriteState;
|
|
|
|
ntStatus = TrueffsFetchKeyValue(DriverObject,RegistryPath,L"FL_VERIFY_WRITE_BDTL1",&CurrVerifyWriteState);
|
|
if (NT_SUCCESS(ntStatus)&& currSocket++<SOCKETS)
|
|
VerifyWriteState[1] = CurrVerifyWriteState;
|
|
|
|
ntStatus = TrueffsFetchKeyValue(DriverObject,RegistryPath,L"FL_VERIFY_WRITE_BDTL2",&CurrVerifyWriteState);
|
|
if (NT_SUCCESS(ntStatus)&& currSocket++<SOCKETS)
|
|
VerifyWriteState[2] = CurrVerifyWriteState;
|
|
|
|
ntStatus = TrueffsFetchKeyValue(DriverObject,RegistryPath,L"FL_VERIFY_WRITE_BDTL3",&CurrVerifyWriteState);
|
|
if (NT_SUCCESS(ntStatus)&& currSocket++<SOCKETS)
|
|
VerifyWriteState[3] = CurrVerifyWriteState;
|
|
|
|
ntStatus = TrueffsFetchKeyValue(DriverObject,RegistryPath,L"FL_VERIFY_WRITE_BDTL4",&CurrVerifyWriteState);
|
|
if (NT_SUCCESS(ntStatus)&& currSocket++<SOCKETS)
|
|
VerifyWriteState[4] = CurrVerifyWriteState;
|
|
|
|
ntStatus = TrueffsFetchKeyValue(DriverObject,RegistryPath,L"FL_VERIFY_WRITE_BDTL5",&CurrVerifyWriteState);
|
|
if (NT_SUCCESS(ntStatus)&& currSocket++<SOCKETS)
|
|
VerifyWriteState[5] = CurrVerifyWriteState;
|
|
|
|
ntStatus = TrueffsFetchKeyValue(DriverObject,RegistryPath,L"FL_VERIFY_WRITE_BDTL6",&CurrVerifyWriteState);
|
|
if (NT_SUCCESS(ntStatus)&& currSocket++<SOCKETS)
|
|
VerifyWriteState[6] = CurrVerifyWriteState;
|
|
|
|
ntStatus = TrueffsFetchKeyValue(DriverObject,RegistryPath,L"FL_VERIFY_WRITE_BDTL7",&CurrVerifyWriteState);
|
|
if (NT_SUCCESS(ntStatus)&& currSocket++<SOCKETS)
|
|
VerifyWriteState[7] = CurrVerifyWriteState;
|
|
|
|
ntStatus = TrueffsFetchKeyValue(DriverObject,RegistryPath,L"FL_SECTORS_VERIFIED_PER_FOLDING",&keyValue);
|
|
if (NT_SUCCESS(ntStatus))
|
|
status = flSetEnvAll(FL_SECTORS_VERIFIED_PER_FOLDING,keyValue,&prevValue);
|
|
|
|
ntStatus = TrueffsFetchKeyValue(DriverObject,RegistryPath,L"FL_VERIFY_WRITE_BINARY",&keyValue);
|
|
if (NT_SUCCESS(ntStatus))
|
|
status = flSetEnvAll(FL_VERIFY_WRITE_BINARY,keyValue,&prevValue);
|
|
|
|
ntStatus = TrueffsFetchKeyValue(DriverObject,RegistryPath,L"FL_VERIFY_WRITE_OTHER",&keyValue);
|
|
if (NT_SUCCESS(ntStatus))
|
|
status = flSetEnvAll(FL_VERIFY_WRITE_OTHER,keyValue,&prevValue);
|
|
|
|
ntStatus = TrueffsFetchKeyValue(DriverObject,RegistryPath,L"FL_SET_MAX_CHAIN",&keyValue);
|
|
if (NT_SUCCESS(ntStatus))
|
|
status = flSetEnvAll(FL_SET_MAX_CHAIN,keyValue,&prevValue);
|
|
|
|
ntStatus = TrueffsFetchKeyValue(DriverObject,RegistryPath,L"FL_MARK_DELETE_ON_FLASH",&keyValue);
|
|
if (NT_SUCCESS(ntStatus))
|
|
status = flSetEnvAll(FL_MARK_DELETE_ON_FLASH,keyValue,&prevValue);
|
|
|
|
return ntStatus;
|
|
#endif /* ENVIRONMENT_VARS*/
|
|
//TffsDebugPrint(("Trueffs: TrueffsDetectRegistryValues End\n"));
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
ULONG
|
|
TrueffsCrashDumpDriverEntry (
|
|
PVOID Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
dump driver entry point
|
|
|
|
Arguments:
|
|
|
|
Context - PCRASHDUMP_INIT_DATA
|
|
|
|
Return Value:
|
|
|
|
NT Status
|
|
|
|
--*/
|
|
{
|
|
PINITIALIZATION_CONTEXT context = Context;
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: CrashDumpDriverEntry\n"));
|
|
|
|
DumpData.CrashInitData = (PCRASHDUMP_INIT_DATA) context->PortConfiguration;
|
|
DumpData.StallRoutine = context->StallRoutine;
|
|
|
|
context->OpenRoutine = TrueffsCrashDumpOpen;
|
|
context->WriteRoutine = TrueffsCrashDumpWrite;
|
|
context->FinishRoutine = TrueffsCrashDumpFinish;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
TrueffsCrashDumpOpen (
|
|
IN LARGE_INTEGER PartitionOffset
|
|
)
|
|
{
|
|
TffsDebugPrint((TFFS_DEB_INFO, "Trueffs: CrashDumpOpen: PartitionOffset = 0x%x%08x...\n", PartitionOffset.HighPart, PartitionOffset.LowPart));
|
|
DumpData.PartitionOffset = PartitionOffset;
|
|
RtlMoveMemory (&DumpData.fdoExtension,DumpData.CrashInitData->cdFdoExtension,sizeof (DEVICE_EXTENSION));
|
|
DumpData.MaxBlockSize = DumpData.fdoExtension.BytesPerSector * 256;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
TrueffsCrashDumpWrite (
|
|
IN PLARGE_INTEGER DiskByteOffset,
|
|
IN PMDL Mdl
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
ULONG blockSize;
|
|
ULONG bytesWritten = 0;
|
|
ULONG startingSector;
|
|
FLStatus tffsStatus;
|
|
IOreq ioreq;
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,
|
|
"TrueffsCrashDumpWrite: Write memory at 0x%x for 0x%x bytes\n",
|
|
Mdl->MappedSystemVa,
|
|
Mdl->ByteCount));
|
|
|
|
if (Mdl->ByteCount % DumpData.fdoExtension.BytesPerSector) {
|
|
// must be complete sectors
|
|
TffsDebugPrint((TFFS_DEB_ERROR, "TrueffsCrashDumpWrite ERROR: not writing full sectors\n"));
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
if ((Mdl->ByteCount / DumpData.fdoExtension.BytesPerSector) > 256) {
|
|
// need code to split request up
|
|
TffsDebugPrint((TFFS_DEB_ERROR, "TrueffsCrashDumpWrite ERROR: can't handle large write\n"));
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
do {
|
|
if ((Mdl->ByteCount - bytesWritten) > DumpData.MaxBlockSize) {
|
|
blockSize = DumpData.MaxBlockSize;
|
|
TffsDebugPrint((TFFS_DEB_INFO, "Trueffs: TrueffsCrashDumpWrite: can't do a single write\n"));
|
|
|
|
} else {
|
|
blockSize = Mdl->ByteCount - bytesWritten;
|
|
}
|
|
status = STATUS_UNSUCCESSFUL;
|
|
startingSector = (ULONG)((DumpData.PartitionOffset.QuadPart +
|
|
(*DiskByteOffset).QuadPart +
|
|
(ULONGLONG) bytesWritten) / DumpData.fdoExtension.BytesPerSector);
|
|
|
|
ioreq.irHandle = DumpData.fdoExtension.UnitNumber;
|
|
ioreq.irSectorNo = startingSector;
|
|
ioreq.irSectorCount = blockSize / DumpData.fdoExtension.BytesPerSector;
|
|
ioreq.irData = ((PUCHAR) Mdl->MappedSystemVa) + bytesWritten;
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: CrashDumpWrite: Starting sector is %x, Number of bytes %x\n",
|
|
startingSector,
|
|
blockSize));
|
|
tffsStatus = flAbsWrite(&ioreq);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: CrashDumpWrite: Write status %Xh\n", tffsStatus));
|
|
|
|
if (tffsStatus == flOK) {
|
|
status = STATUS_SUCCESS;
|
|
bytesWritten += blockSize;
|
|
}
|
|
} while (bytesWritten < Mdl->ByteCount);
|
|
return status;
|
|
}
|
|
|
|
|
|
VOID
|
|
TrueffsCrashDumpFinish (
|
|
VOID
|
|
)
|
|
{
|
|
TffsDebugPrint((TFFS_DEB_INFO, "Trueffs: TrueffsCrashDumpFinish\n"));
|
|
return;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
TrueffsDispatchSystemControl(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN OUT PIRP Irp
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dispatch routine for IRP_MJ_SYSTEM_CONTROL (WMI) IRPs
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - Pointer to the device object for which this IRP applies.
|
|
|
|
Irp - Pointer to the IRP_MJ_PNP_POWER IRP to dispatch.
|
|
|
|
Return Value:
|
|
|
|
NT status.
|
|
|
|
--*/
|
|
{
|
|
PIO_STACK_LOCATION thisIrpSp;
|
|
NTSTATUS status;
|
|
PDEVICE_EXTENSION deviceExtension;
|
|
PPDO_EXTENSION pdoExtension;
|
|
PDEVICE_EXTENSION_HEADER devExtension;
|
|
|
|
thisIrpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
devExtension = (PDEVICE_EXTENSION_HEADER) DeviceObject->DeviceExtension;
|
|
if (IS_FDO(devExtension)) {
|
|
|
|
TffsDebugPrint((TFFS_DEB_WARN,"Trueffs: DispatchSystemControl: WMI IRP (FDO) %Xh not handled. Passing it down.\n",thisIrpSp->MinorFunction));
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
status = IoCallDriver(devExtension->LowerDeviceObject, Irp);
|
|
}
|
|
else {
|
|
|
|
if (thisIrpSp->MinorFunction < NUM_WMI_MINOR_FUNCTION) {
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DispatchSystemControl (WMI) %Xh PDO\n",thisIrpSp->MinorFunction));
|
|
status = TrueffsWmiSystemControl(DeviceObject, Irp);
|
|
} else {
|
|
|
|
TffsDebugPrint((TFFS_DEB_WARN,"Trueffs: DispatchSystemControl (WMI) %Xh PDO unsupported\n",thisIrpSp->MinorFunction));
|
|
status = Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
}
|
|
}
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DispatchSystemControl status %Xh\n", status));
|
|
return status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
TrueffsFindDiskOnChip(
|
|
IN INTERFACE_TYPE InterfaceType,
|
|
IN ULONG BusNumber,
|
|
IN ULONG StartSearchAddress,
|
|
IN LONG WindowSize,
|
|
IN BOOLEAN StartSearch,
|
|
OUT PVOID *WindowBase
|
|
)
|
|
|
|
{
|
|
ULONG DOCAddressSpace = TFFS_MEMORY_SPACE;
|
|
PVOID DOCAddressBase = NULL;
|
|
PHYSICAL_ADDRESS DOCAddressMemoryBase;
|
|
NTSTATUS status;
|
|
ULONG winBase;
|
|
volatile UCHAR chipId;
|
|
volatile UCHAR toggle1;
|
|
volatile UCHAR toggle2;
|
|
volatile UCHAR deviceSearch;
|
|
|
|
DOC2window *memDOC2000WinPtr = NULL;
|
|
MDOCPwindow *memWinPtr = NULL;
|
|
|
|
status = TrueffsTranslateAddress(InterfaceType,
|
|
BusNumber,
|
|
RtlConvertLongToLargeInteger(StartSearchAddress),
|
|
WindowSize,
|
|
&DOCAddressSpace,
|
|
&DOCAddressBase,
|
|
&DOCAddressMemoryBase);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
if (status == STATUS_NOT_IMPLEMENTED) {
|
|
status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: tffsport.c :TrueffsFindDiskOnChip():Failed to alloc memory\n"));
|
|
return status;
|
|
}
|
|
|
|
/* DOC2000*/
|
|
memDOC2000WinPtr = (DOC2window *) DOCAddressBase;
|
|
|
|
tffsWriteByte(memDOC2000WinPtr->DOCcontrol, ASIC_NORMAL_MODE);
|
|
tffsWriteByte(memDOC2000WinPtr->DOCcontrol, ASIC_NORMAL_MODE);
|
|
|
|
chipId = tffsReadByte(memDOC2000WinPtr->chipId);
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: tffsport.c :TrueffsFindDiskOnChip():After read DOC2000 chipID\n"));
|
|
if ((chipId == CHIP_ID_DOC) || (chipId == CHIP_ID_MDOC)) {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: tffsport.c :TrueffsFindDiskOnChip():In chip ID DOC2000 or MDOC\n"));
|
|
if (chipId == CHIP_ID_MDOC) {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: tffsport.c :TrueffsFindDiskOnChip():In the MDOC\n"));
|
|
toggle1 = tffsReadByte(memDOC2000WinPtr->ECCconfig);
|
|
toggle2 = toggle1 ^ tffsReadByte(memDOC2000WinPtr->ECCconfig);
|
|
}
|
|
else {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: tffsport.c :TrueffsFindDiskOnChip():In the DOC2000\n"));
|
|
toggle1 = tffsReadByte(memDOC2000WinPtr->ECCstatus);
|
|
toggle2 = toggle1 ^ tffsReadByte(memDOC2000WinPtr->ECCstatus);
|
|
}
|
|
|
|
if (!StartSearch) {
|
|
if ((toggle2 & TOGGLE) != 0) {
|
|
if (chipId == CHIP_ID_MDOC) {
|
|
tffsWriteByte(memDOC2000WinPtr->aliasResolution, ALIAS_RESOLUTION);
|
|
}
|
|
else {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: tffsport.c :TrueffsFindDiskOnChip():Failed Toggle\n"));
|
|
tffsWriteByte(memDOC2000WinPtr->deviceSelector, ALIAS_RESOLUTION);
|
|
}
|
|
*WindowBase = DOCAddressBase;
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DiskOnChip detected on %Xh\n",StartSearchAddress));
|
|
return STATUS_SUCCESS;
|
|
}
|
|
}
|
|
else {
|
|
deviceSearch = ( chipId == CHIP_ID_MDOC ) ? tffsReadByte(memDOC2000WinPtr->aliasResolution) :
|
|
tffsReadByte(memDOC2000WinPtr->deviceSelector);
|
|
if (((toggle2 & TOGGLE) != 0) && (deviceSearch == ALIAS_RESOLUTION)) {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: tffsport.c :TrueffsFindDiskOnChip():Free Window pointer\n"));
|
|
TrueffsFreeTranslatedAddress(
|
|
DOCAddressBase,
|
|
WindowSize,
|
|
DOCAddressSpace
|
|
);
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: Alias detected on %Xh\n",StartSearchAddress));
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
}
|
|
}
|
|
|
|
//Start MDOCP code
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: tffsport.c :TrueffsFindDiskOnChip():Start looking for MDOCP\n"));
|
|
memWinPtr = (MDOCPwindow *) DOCAddressBase;
|
|
|
|
memWinPtr->DOCcontrol = (unsigned char)0x05; /* Set RESET Mode */
|
|
memWinPtr->DocCntConfirmReg = (unsigned char)0xfa;
|
|
|
|
chipId = memWinPtr->chipId;
|
|
|
|
|
|
if (chipId == 0x40)
|
|
{
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: tffsport.c :TrueffsFindDiskOnChip():Identify as MDOCP\n"));
|
|
toggle1 = tffsReadByte(memWinPtr->EccCntReg);
|
|
toggle2 = toggle1 ^ tffsReadByte(memWinPtr->EccCntReg);
|
|
|
|
if (!StartSearch)
|
|
{
|
|
//if ((toggle2 & ECC_CNTRL_TOGGLE_MASK) != 0)
|
|
if ((toggle2 & 0x4) != 0)
|
|
{
|
|
tffsWriteByte(memWinPtr->AliasResolution, ALIAS_RESOLUTION);
|
|
*WindowBase = DOCAddressBase;
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: MDOCP detected on %Xh\n",StartSearchAddress));
|
|
return STATUS_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
|
|
deviceSearch = tffsReadByte(memWinPtr->AliasResolution);
|
|
//if (((toggle2 & ECC_CNTRL_TOGGLE_MASK) != 0) && (deviceSearch == ALIAS_RESOLUTION))
|
|
if (((toggle2 & 0x4) != 0) && (deviceSearch == ALIAS_RESOLUTION))
|
|
|
|
{
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: tffsport.c :TrueffsFindDiskOnChip():MDOCP Failed togfle - Free memory\n"));
|
|
TrueffsFreeTranslatedAddress(
|
|
DOCAddressBase,
|
|
WindowSize,
|
|
DOCAddressSpace
|
|
);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: Alias detected on %Xh\n",StartSearchAddress));
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TrueffsFreeTranslatedAddress(
|
|
DOCAddressBase,
|
|
WindowSize,
|
|
DOCAddressSpace
|
|
);
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DiskOnChip not detected on %Xh\n", StartSearchAddress));
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
TrueffsCheckDiskOnChip(
|
|
IN INTERFACE_TYPE InterfaceType,
|
|
IN ULONG BusNumber,
|
|
IN ULONG StartSearchAddress,
|
|
IN LONG WindowSize,
|
|
OUT PVOID *WindowBase,
|
|
OUT PULONG AddressSpace
|
|
)
|
|
|
|
{
|
|
ULONG DOCAddressSpace = TFFS_MEMORY_SPACE;
|
|
PVOID DOCAddressBase = NULL;
|
|
PHYSICAL_ADDRESS DOCAddressMemoryBase;
|
|
NTSTATUS status;
|
|
volatile UCHAR chipId;
|
|
volatile UCHAR toggle1;
|
|
volatile UCHAR toggle2;
|
|
|
|
DOC2window *memDOC2000WinPtr;
|
|
MDOCPwindow *memWinPtr;
|
|
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: tffsport.c: TrueffsCheckDiskOnChip() Started ...\n"));
|
|
status = TrueffsTranslateAddress(InterfaceType,
|
|
BusNumber,
|
|
RtlConvertLongToLargeInteger(StartSearchAddress),
|
|
WindowSize,
|
|
&DOCAddressSpace,
|
|
&DOCAddressBase,
|
|
&DOCAddressMemoryBase);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
return status;
|
|
}
|
|
|
|
memDOC2000WinPtr = (DOC2window *) DOCAddressBase;
|
|
|
|
tffsWriteByte(memDOC2000WinPtr->DOCcontrol, 0x84);
|
|
tffsWriteByte(memDOC2000WinPtr->DOCcontrol, 0x84);
|
|
tffsWriteByte(memDOC2000WinPtr->DOCcontrol, 0x85);
|
|
tffsWriteByte(memDOC2000WinPtr->DOCcontrol, 0x85);
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: tffsport.c: TrueffsCheckDiskOnChip() DOC2000 read chip ID\n"));
|
|
chipId = tffsReadByte(memDOC2000WinPtr->chipId);
|
|
if ((chipId == CHIP_ID_DOC) || (chipId == CHIP_ID_MDOC)) {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: tffsport.c: TrueffsCheckDiskOnChip() DOC2000 chipID = 0x%x\n", chipId));
|
|
if (chipId == CHIP_ID_MDOC) {
|
|
toggle1 = tffsReadByte(memDOC2000WinPtr->ECCconfig);
|
|
toggle2 = toggle1 ^ tffsReadByte(memDOC2000WinPtr->ECCconfig);
|
|
}
|
|
else {
|
|
toggle1 = tffsReadByte(memDOC2000WinPtr->ECCstatus);
|
|
toggle2 = toggle1 ^ tffsReadByte(memDOC2000WinPtr->ECCstatus);
|
|
}
|
|
if ((toggle2 & TOGGLE) != 0) {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: tffsport.c: TrueffsCheckDiskOnChip() DOC2000 Finished toggle successfuly\n"));
|
|
*WindowBase = DOCAddressBase;
|
|
*AddressSpace = DOCAddressSpace;
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DiskOnChip2000 found on %Xh\n",StartSearchAddress));
|
|
return STATUS_SUCCESS;
|
|
}
|
|
}
|
|
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: tffsport.c: TrueffsCheckDiskOnChip() MDOCPLUS Start....\n"));
|
|
memWinPtr = (MDOCPwindow *) DOCAddressBase;
|
|
tffsWriteByte(memWinPtr->DOCcontrol, (unsigned char)0x04);
|
|
tffsWriteByte(memWinPtr->DocCntConfirmReg, (unsigned char)0xfb);
|
|
tffsWriteByte(memWinPtr->DOCcontrol, (unsigned char)0x05);
|
|
tffsWriteByte(memWinPtr->DocCntConfirmReg, (unsigned char)0xfa);
|
|
chipId = tffsReadByte(memWinPtr->chipId);
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: tffsport.c: TrueffsCheckDiskOnChip() MDOCPLUS chipID = 0x%x\n", chipId));
|
|
|
|
//if (chipId == CHIP_ID_MDOCP)
|
|
if (chipId == 0x40)
|
|
{
|
|
toggle1 = tffsReadByte(memWinPtr->EccCntReg);
|
|
toggle2 = toggle1 ^ tffsReadByte(memWinPtr->EccCntReg);
|
|
|
|
//if ((toggle2 & ECC_CNTRL_TOGGLE_MASK) != 0)
|
|
if ((toggle2 & 0x4) != 0)
|
|
{
|
|
*WindowBase = DOCAddressBase;
|
|
*AddressSpace = DOCAddressSpace;
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: MDOCPLUS found on %Xh\n",StartSearchAddress));
|
|
return STATUS_SUCCESS;
|
|
}
|
|
}
|
|
|
|
|
|
TrueffsFreeTranslatedAddress(
|
|
DOCAddressBase,
|
|
WindowSize,
|
|
DOCAddressSpace
|
|
);
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
|
|
VOID
|
|
TrueffsResetDiskOnChip(
|
|
IN INTERFACE_TYPE InterfaceType,
|
|
IN ULONG BusNumber,
|
|
IN ULONG StartSearchAddress,
|
|
IN LONG WindowSize
|
|
)
|
|
|
|
{
|
|
ULONG DOCAddressSpace = TFFS_MEMORY_SPACE;
|
|
PVOID DOCAddressBase = NULL;
|
|
PHYSICAL_ADDRESS DOCAddressMemoryBase;
|
|
NTSTATUS status;
|
|
|
|
DOC2window *memDOC2000WinPtr;
|
|
|
|
MDOCPwindow *memWinPtr;
|
|
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: tffsport.c:TrueffsResetDiskOnChip()b start\n"));
|
|
status = TrueffsTranslateAddress(InterfaceType,
|
|
BusNumber,
|
|
RtlConvertLongToLargeInteger(StartSearchAddress),
|
|
WindowSize,
|
|
&DOCAddressSpace,
|
|
&DOCAddressBase,
|
|
&DOCAddressMemoryBase);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
return;
|
|
}
|
|
/* DOC2000 CHANGES*/
|
|
memDOC2000WinPtr = (DOC2window *) DOCAddressBase;
|
|
tffsWriteByte(memDOC2000WinPtr->DOCcontrol, 0x84);
|
|
tffsWriteByte(memDOC2000WinPtr->DOCcontrol, 0x84);
|
|
|
|
memWinPtr = (MDOCPwindow *) DOCAddressBase;
|
|
tffsWriteByte(memWinPtr->DOCcontrol,(unsigned char)0x04 );
|
|
tffsWriteByte(memWinPtr->DocCntConfirmReg,(unsigned char)0xfb );
|
|
|
|
TrueffsFreeTranslatedAddress(
|
|
DOCAddressBase,
|
|
WindowSize,
|
|
DOCAddressSpace
|
|
);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: tffsport.c:TrueffsResetDiskOnChip()b End\n"));
|
|
return;
|
|
}
|
|
|
|
NTSTATUS
|
|
TrueffsStartSubDevice(
|
|
IN UCHAR deviceNo,
|
|
IN UCHAR partitionNumber,
|
|
IN PDEVICE_EXTENSION deviceExtension,
|
|
IN PCM_RESOURCE_LIST ResourceList,
|
|
IN BOOLEAN CheckResources
|
|
)
|
|
{
|
|
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
|
|
|
ExAcquireFastMutex(&driveInfoReferenceMutex);
|
|
|
|
deviceExtension->UnitNumber = (partitionNumber << 4) + deviceNo;
|
|
if (!(deviceExtension->DeviceFlags & DEVICE_FLAG_STARTED)) {
|
|
status = TrueffsCreateSymblicLinks(deviceExtension);
|
|
if (!NT_SUCCESS(status)) {
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
}
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: StartDevice OK\n"));
|
|
ExReleaseFastMutex(&driveInfoReferenceMutex);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
TrueffsDetectDiskOnChip(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PUNICODE_STRING RegistryPath
|
|
)
|
|
|
|
{
|
|
ULONG cmResourceListSize;
|
|
PCM_RESOURCE_LIST cmResourceList = NULL;
|
|
PCM_FULL_RESOURCE_DESCRIPTOR cmFullResourceDescriptor;
|
|
PCM_PARTIAL_RESOURCE_LIST cmPartialResourceList;
|
|
PCM_PARTIAL_RESOURCE_DESCRIPTOR cmPartialDescriptors;
|
|
BOOLEAN conflictDetected;
|
|
PDEVICE_OBJECT detectedPhysicalDeviceObject;
|
|
PDEVICE_EXTENSION fdoExtensions[VOLUMES];
|
|
NTSTATUS status;
|
|
ULONG legacyDetection = 0;
|
|
ULONG searchBase, aliasSearchBase, aliasCounter;
|
|
PVOID mappedWindowBase = NULL;
|
|
KIRQL cIrql;
|
|
BOOLEAN startSearch = FALSE;
|
|
int noOfDevices = 0;
|
|
int deviceNo = 0;
|
|
UCHAR currSockets = 0;
|
|
int index = 0;
|
|
CM_RESOURCE_LIST arrayResourceList[VOLUMES];
|
|
ULONG prevValue;
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DetectDiskOnChip\n"));
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DetectDiskOnChip, go to Registry\n"));
|
|
// Set Registry Vars to TrueFFS
|
|
TrueffsDetectRegistryValues(DriverObject,RegistryPath);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DetectDiskOnChip, back from Registry\n"));
|
|
|
|
|
|
if (!TrueffsOkToDetectLegacy(DriverObject)) {
|
|
// legacy detection is not enabled
|
|
TffsDebugPrint((TFFS_DEB_WARN,"Trueffs: DetectDiskOnChip: detection is not enabled\n"));
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
// disable legacy detection for next boot
|
|
TrueffsGetParameterFromServiceSubKey (
|
|
DriverObject,
|
|
LEGACY_DETECTION,
|
|
REG_DWORD,
|
|
FALSE,
|
|
(PVOID) &legacyDetection,
|
|
sizeof (legacyDetection)
|
|
);
|
|
|
|
cmResourceListSize = sizeof (CM_RESOURCE_LIST);
|
|
cmResourceList = ExAllocatePoolWithTag (PagedPool, cmResourceListSize, TFFSPORT_POOL_TAG);
|
|
if (cmResourceList == NULL){
|
|
status = STATUS_NO_MEMORY;
|
|
goto GetOut;
|
|
}
|
|
|
|
RtlZeroMemory(cmResourceList, cmResourceListSize);
|
|
|
|
for(index = 0; index < VOLUMES; index++){
|
|
fdoExtensions[index] = NULL;
|
|
//arrayResourceList[index] = ExAllocatePoolWithTag (PagedPool, cmResourceListSize, TFFSPORT_POOL_TAG);
|
|
//RtlZeroMemory(arrayResourceList[index], cmResourceListSize );
|
|
|
|
}
|
|
RtlZeroMemory(arrayResourceList, cmResourceListSize * VOLUMES);
|
|
|
|
// Build resource requirement list
|
|
cmResourceList->Count = 1;
|
|
cmFullResourceDescriptor = cmResourceList->List;
|
|
cmFullResourceDescriptor->InterfaceType = DISKONCHIP_INTERFACE;
|
|
cmFullResourceDescriptor->BusNumber = DISKONCHIP_BUSNUMBER;
|
|
cmPartialResourceList = &cmFullResourceDescriptor->PartialResourceList;
|
|
cmPartialResourceList->Version = 1;
|
|
cmPartialResourceList->Revision = 1;
|
|
cmPartialResourceList->Count = 1;
|
|
cmPartialDescriptors = cmPartialResourceList->PartialDescriptors;
|
|
|
|
cmPartialDescriptors[0].Type = CmResourceTypeMemory;
|
|
cmPartialDescriptors[0].ShareDisposition = CmResourceShareShared;
|
|
cmPartialDescriptors[0].Flags = CM_RESOURCE_MEMORY_READ_ONLY;
|
|
cmPartialDescriptors[0].u.Memory.Length = DISKONCHIP_WINDOW_SIZE;
|
|
|
|
|
|
for(searchBase = START_SEARCH_ADDRESS; searchBase < END_SEARCH_ADDRESS ; searchBase += DISKONCHIP_WINDOW_SIZE) {
|
|
cmPartialDescriptors[0].u.Memory.Start.QuadPart = searchBase;
|
|
|
|
// check to see if the resource is available
|
|
status = IoReportResourceForDetection (
|
|
DriverObject,
|
|
cmResourceList,
|
|
cmResourceListSize,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
&conflictDetected
|
|
);
|
|
if (!NT_SUCCESS(status) || conflictDetected) {
|
|
if (NT_SUCCESS(status)) {
|
|
IoReportResourceForDetection (
|
|
DriverObject,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
&conflictDetected
|
|
);
|
|
status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
}
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: IoReportResourceForDetection with status %Xh\n",status));
|
|
|
|
if (!NT_SUCCESS (status)) {
|
|
continue;
|
|
}
|
|
|
|
|
|
TrueffsResetDiskOnChip(cmFullResourceDescriptor->InterfaceType,cmFullResourceDescriptor->BusNumber,searchBase,DISKONCHIP_WINDOW_SIZE);
|
|
|
|
// release the resources
|
|
IoReportResourceForDetection (
|
|
DriverObject,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
&conflictDetected
|
|
);
|
|
|
|
|
|
|
|
// check to see if the resource is available
|
|
status = IoReportResourceForDetection (
|
|
DriverObject,
|
|
cmResourceList,
|
|
cmResourceListSize,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
&conflictDetected
|
|
);
|
|
if (!NT_SUCCESS(status) || conflictDetected) {
|
|
if (NT_SUCCESS(status)) {
|
|
IoReportResourceForDetection (
|
|
DriverObject,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
&conflictDetected
|
|
);
|
|
status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
}
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: IoReportResourceForDetection with status %Xh\n",status));
|
|
|
|
// if (!NT_SUCCESS (status)) {
|
|
// continue;
|
|
// }
|
|
|
|
if (NT_SUCCESS (status)) {
|
|
status = TrueffsFindDiskOnChip(cmFullResourceDescriptor->InterfaceType,cmFullResourceDescriptor->BusNumber,searchBase,DISKONCHIP_WINDOW_SIZE, startSearch,&mappedWindowBase);
|
|
}
|
|
else{
|
|
continue;
|
|
}
|
|
|
|
// release the resources we have grab, IoReportDetectedDevice()
|
|
// will grab them for us again when we call and it will grab them
|
|
// on behalf of the detected PDO.
|
|
IoReportResourceForDetection (
|
|
DriverObject,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
&conflictDetected
|
|
);
|
|
|
|
if (NT_SUCCESS (status)) {
|
|
detectedPhysicalDeviceObject = NULL;
|
|
|
|
status = IoReportDetectedDevice(DriverObject,
|
|
Isa,
|
|
0,
|
|
0,
|
|
cmResourceList,
|
|
NULL,
|
|
FALSE,
|
|
&detectedPhysicalDeviceObject);
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: IoReportDetectedDevice returned status %Xh\n",status));
|
|
|
|
if (NT_SUCCESS (status)) {
|
|
|
|
// create a FDO and attach it to the detected PDO
|
|
status = TrueffsCreateDevObject(
|
|
DriverObject,
|
|
detectedPhysicalDeviceObject,
|
|
&fdoExtensions[noOfDevices]
|
|
);
|
|
}
|
|
if (NT_SUCCESS (status)) {
|
|
status = TrueffsStartDeviceOnDetect(fdoExtensions[noOfDevices],cmResourceList,TRUE);
|
|
if (NT_SUCCESS (status)) {
|
|
memcpy(&arrayResourceList[noOfDevices++],cmResourceList, cmResourceListSize);
|
|
//moti tffscpy(&arrayResourceList[noOfDevices++],cmResourceList, cmResourceListSize);
|
|
//tffscpy(arrayResourceList[noOfDevices++],cmResourceList, cmResourceListSize);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//Mounting all devices includes sub handles
|
|
for(deviceNo = 0;deviceNo < noOfDevices;deviceNo++) {
|
|
FLStatus flStatus = flOK;
|
|
status = STATUS_SUCCESS;
|
|
status = TrueffsMountMedia(fdoExtensions[deviceNo]);
|
|
if (!NT_SUCCESS (status)) {
|
|
// go through the remove sequence
|
|
if (fdoExtensions[deviceNo]) {
|
|
IoDetachDevice(fdoExtensions[deviceNo]->LowerDeviceObject);
|
|
IoDeleteDevice(fdoExtensions[deviceNo]->DeviceObject);
|
|
}
|
|
continue;
|
|
}
|
|
else {
|
|
IOreq ioreq;
|
|
int partitionNumber = 0;
|
|
int noOfPartitions = 0;
|
|
ioreq.irHandle = deviceNo;
|
|
flStatus= flCountVolumes(&ioreq);
|
|
if(flStatus == flOK)
|
|
noOfPartitions = ioreq.irFlags;
|
|
else
|
|
noOfPartitions = 1;
|
|
KeAcquireSpinLock(&fdoExtensions[deviceNo]->ExtensionDataSpinLock,&cIrql);
|
|
fdoExtensions[deviceNo]->DeviceFlags &= ~DEVICE_FLAG_STOPPED;
|
|
fdoExtensions[deviceNo]->DeviceFlags |= DEVICE_FLAG_STARTED;
|
|
KeReleaseSpinLock(&fdoExtensions[deviceNo]->ExtensionDataSpinLock,cIrql);
|
|
|
|
//Handle sub partitions
|
|
for(partitionNumber = 1;partitionNumber < noOfPartitions;partitionNumber++){
|
|
PDEVICE_EXTENSION fdoExtension = NULL;
|
|
status = STATUS_SUCCESS;
|
|
|
|
// release the resources we have grab, IoReportDetectedDevice()
|
|
// will grab them for us again when we call and it will grab them
|
|
// on behalf of the detected PDO.
|
|
/* IoReportResourceForDetection (
|
|
DriverObject,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
&conflictDetected
|
|
);
|
|
*/
|
|
|
|
detectedPhysicalDeviceObject = NULL;
|
|
status = IoReportDetectedDevice(DriverObject,
|
|
Isa,
|
|
0,
|
|
0,
|
|
&arrayResourceList[deviceNo],
|
|
//arrayResourceList[deviceNo],
|
|
NULL,
|
|
FALSE,
|
|
&detectedPhysicalDeviceObject);
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: IoReportDetectedDevice returned status %Xh\n",status));
|
|
|
|
if (NT_SUCCESS (status)) {
|
|
|
|
// create a FDO and attach it to the detected PDO
|
|
|
|
status = TrueffsCreateDevObject(
|
|
DriverObject,
|
|
detectedPhysicalDeviceObject,
|
|
&fdoExtension
|
|
);
|
|
}
|
|
if (NT_SUCCESS (status)) {
|
|
status = TrueffsStartSubDevice((unsigned char)deviceNo,
|
|
(unsigned char)partitionNumber,
|
|
fdoExtension,
|
|
&arrayResourceList[deviceNo],
|
|
//arrayResourceList[deviceNo],
|
|
TRUE);
|
|
}
|
|
if (NT_SUCCESS (status)) {
|
|
status = TrueffsMountMedia(fdoExtension);
|
|
if (!NT_SUCCESS (status)) {
|
|
// go through the remove sequence
|
|
if (fdoExtension) {
|
|
IoDetachDevice(fdoExtension->LowerDeviceObject);
|
|
IoDeleteDevice(fdoExtension->DeviceObject);
|
|
}
|
|
continue;
|
|
}
|
|
else{
|
|
KeAcquireSpinLock(&fdoExtension->ExtensionDataSpinLock,&cIrql);
|
|
fdoExtension->DeviceFlags &= ~DEVICE_FLAG_STOPPED;
|
|
fdoExtension->DeviceFlags |= DEVICE_FLAG_STARTED;
|
|
KeReleaseSpinLock(&fdoExtension->ExtensionDataSpinLock,cIrql);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
GetOut:
|
|
|
|
if (cmResourceList) {
|
|
ExFreePool (cmResourceList);
|
|
cmResourceList = NULL;
|
|
}
|
|
|
|
for(index = 0; index < VOLUMES; index++){
|
|
fdoExtensions[index] = NULL;
|
|
}
|
|
|
|
|
|
#ifdef ENVIRONMENT_VARS
|
|
|
|
for ( currSockets = 0; currSockets < SOCKETS; currSockets++) {
|
|
if (VerifyWriteState[currSockets])
|
|
status = flSetEnvSocket(FL_VERIFY_WRITE_BDTL,currSockets,VerifyWriteState[currSockets],&prevValue);
|
|
}
|
|
|
|
#endif /*ENVIRONMENT_VARS */
|
|
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DetectDiskOnChip with status %Xh\n",status));
|
|
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS
|
|
TrueffsTranslateAddress(
|
|
IN INTERFACE_TYPE InterfaceType,
|
|
IN ULONG BusNumber,
|
|
IN PHYSICAL_ADDRESS StartAddress,
|
|
IN LONG Length,
|
|
IN OUT PULONG AddressSpace,
|
|
OUT PVOID *TranslatedAddress,
|
|
OUT PPHYSICAL_ADDRESS TranslatedMemoryAddress
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
translate i/o address
|
|
|
|
Arguments:
|
|
|
|
InterfaceType - bus interface
|
|
|
|
BusNumber - bus number
|
|
|
|
StartAddress - address to translate
|
|
|
|
Length - number of byte to translate
|
|
|
|
AddressSpace - address space for the given address
|
|
|
|
Return Value:
|
|
|
|
AddressSpace - address space for the translated address
|
|
|
|
TranslatedAddress - translated address
|
|
|
|
TranslatedMemoryAddress - tranlated memory address if translated to memory space
|
|
|
|
NT Status
|
|
|
|
--*/
|
|
{
|
|
PHYSICAL_ADDRESS translatedAddress;
|
|
|
|
*TranslatedAddress = NULL;
|
|
TranslatedMemoryAddress->QuadPart = (ULONGLONG) NULL;
|
|
|
|
if (HalTranslateBusAddress(InterfaceType,
|
|
BusNumber,
|
|
StartAddress,
|
|
AddressSpace,
|
|
&translatedAddress)) {
|
|
|
|
|
|
if (*AddressSpace == TFFS_IO_SPACE) {
|
|
*TranslatedMemoryAddress = translatedAddress;
|
|
*TranslatedAddress = (PVOID) translatedAddress.QuadPart;
|
|
|
|
} else if (*AddressSpace == TFFS_MEMORY_SPACE) {
|
|
|
|
// translated address is in memory space,
|
|
*TranslatedMemoryAddress = translatedAddress;
|
|
|
|
*TranslatedAddress = MmMapIoSpace(
|
|
translatedAddress,
|
|
Length,
|
|
FALSE);
|
|
}
|
|
}
|
|
if (*TranslatedAddress) {
|
|
return STATUS_SUCCESS;
|
|
|
|
} else {
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
TrueffsFreeTranslatedAddress(
|
|
IN PVOID TranslatedAddress,
|
|
IN LONG Length,
|
|
IN ULONG AddressSpace
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
free resources created for a translated address
|
|
|
|
Arguments:
|
|
|
|
TranslatedAddress - translated address
|
|
|
|
Length - number of byte to translated
|
|
|
|
AddressSpace - address space for the translated address
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
if (TranslatedAddress) {
|
|
if (AddressSpace == TFFS_MEMORY_SPACE) {
|
|
MmUnmapIoSpace (
|
|
TranslatedAddress,
|
|
Length
|
|
);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
TrueffsAddDevice(
|
|
PDRIVER_OBJECT DriverObject,
|
|
PDEVICE_OBJECT Pdo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is our PNP AddDevice called with the PDO ejected from the bus driver
|
|
|
|
Arguments:
|
|
|
|
Argument1 - Driver Object.
|
|
Argument2 - PDO.
|
|
|
|
|
|
Return Value:
|
|
|
|
A valid return code for a DriverEntry routine.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
NTSTATUS status;
|
|
PDEVICE_EXTENSION fdoExtension;
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: AddDevice\n"));
|
|
status = TrueffsCreateDevObject (DriverObject,Pdo,&fdoExtension);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: AddDevice with status %Xh\n", status));
|
|
return status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
TrueffsCreateDevObject(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PDEVICE_OBJECT Pdo,
|
|
OUT PDEVICE_EXTENSION *FdoExtension
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine creates an object for the physical device specified and
|
|
sets up the deviceExtension.
|
|
|
|
Arguments:
|
|
|
|
DriverObject - Pointer to driver object created by system.
|
|
|
|
PhysicalDeviceObject = PDO we should attach to.
|
|
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
|
|
--*/
|
|
|
|
{
|
|
PDEVICE_EXTENSION deviceExtension;
|
|
NTSTATUS status;
|
|
PDEVICE_OBJECT deviceObject = NULL;
|
|
STRING deviceName;
|
|
CCHAR deviceNameBuffer[64];
|
|
UNICODE_STRING unicodeDeviceNameString;
|
|
UNICODE_STRING driverName;
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: CreateDevObject\n"));
|
|
|
|
sprintf(deviceNameBuffer, "\\Device\\TffsPort%d",TrueffsNextDeviceNumber_tffsport);
|
|
RtlInitString(&deviceName, deviceNameBuffer);
|
|
status = RtlAnsiStringToUnicodeString(&unicodeDeviceNameString,
|
|
&deviceName,
|
|
TRUE);
|
|
if (!NT_SUCCESS (status)) {
|
|
return status;
|
|
}
|
|
status = IoCreateDevice(DriverObject,
|
|
sizeof(DEVICE_EXTENSION),
|
|
&unicodeDeviceNameString, // our name
|
|
FILE_DEVICE_CONTROLLER,
|
|
FILE_DEVICE_SECURE_OPEN,
|
|
FALSE,
|
|
&deviceObject);
|
|
|
|
RtlFreeUnicodeString (&unicodeDeviceNameString);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
TffsDebugPrint((TFFS_DEB_ERROR,"Trueffs: CreateDevObject: IoCreateDevice failed with status %Xh\n",status));
|
|
return status;
|
|
}
|
|
else {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: Created FDO %Xh\n",deviceObject));
|
|
}
|
|
|
|
deviceExtension = deviceObject->DeviceExtension;
|
|
RtlZeroMemory(deviceExtension,sizeof(DEVICE_EXTENSION));
|
|
|
|
if (Pdo != NULL) {
|
|
if ((deviceExtension->LowerDeviceObject =
|
|
IoAttachDeviceToDeviceStack(deviceObject,Pdo))==NULL){
|
|
TffsDebugPrint((TFFS_DEB_ERROR,"Trueffs: CreateDevObject: cannot attach device\n"));
|
|
|
|
IoDeleteDevice(deviceObject);
|
|
return status;
|
|
}
|
|
}
|
|
|
|
KeInitializeSemaphore(&deviceExtension->requestSemaphore,0L,MAXLONG);
|
|
|
|
KeInitializeSpinLock(&deviceExtension->listSpinLock);
|
|
|
|
InitializeListHead(&deviceExtension->listEntry);
|
|
|
|
KeInitializeSpinLock(&deviceExtension->ExtensionDataSpinLock);
|
|
|
|
KeInitializeEvent(&deviceExtension->PendingIRPEvent, SynchronizationEvent, FALSE);
|
|
|
|
deviceExtension->threadReferenceCount = -1;
|
|
|
|
deviceExtension->pcmciaParams.physWindow = 0;
|
|
deviceExtension->pcmciaParams.windowSize = 0;
|
|
deviceExtension->pcmciaParams.windowBase = NULL;
|
|
|
|
deviceObject->Flags |= DO_DIRECT_IO;
|
|
deviceExtension->DeviceObject = deviceObject;
|
|
deviceExtension->MainPdo = Pdo;
|
|
deviceExtension->DriverObject = DriverObject;
|
|
deviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT;
|
|
deviceObject->Flags &=~DO_DEVICE_INITIALIZING;
|
|
deviceExtension->DeviceFlags |= DEVICE_FLAG_STOPPED;
|
|
|
|
#if 0 //Pcmcia cards don't have removable media
|
|
RtlInitUnicodeString(&driverName, L"\\Driver\\Pcmcia");
|
|
if (!RtlCompareUnicodeString(&Pdo->DriverObject->DriverName,&driverName,TRUE)) {
|
|
deviceExtension->removableMedia = TRUE;
|
|
}
|
|
#endif
|
|
|
|
deviceExtension->TrueffsDeviceNumber = TrueffsNextDeviceNumber_tffsport;
|
|
TrueffsNextDeviceNumber_tffsport++;
|
|
deviceExtension->ScsiDeviceType = DIRECT_ACCESS_DEVICE;
|
|
|
|
*FdoExtension = deviceExtension;
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: CreateDevObject with status %Xh\n",status));
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
TrueffsStartDeviceOnDetect(
|
|
IN PDEVICE_EXTENSION deviceExtension,
|
|
IN PCM_RESOURCE_LIST ResourceList,
|
|
IN BOOLEAN CheckResources
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is our START_DEVICE, called when we get an IPR_MN_START_DEVICE.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
|
|
--*/
|
|
|
|
{
|
|
PCM_FULL_RESOURCE_DESCRIPTOR fullResourceList;
|
|
PCM_PARTIAL_RESOURCE_LIST partialResourceList;
|
|
PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDescriptors;
|
|
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
|
ULONG i;
|
|
ULONG j;
|
|
PVOID mappedWindowBase = NULL;
|
|
ULONG addressSpace;
|
|
|
|
// assume we have DOC
|
|
ExAcquireFastMutex(&driveInfoReferenceMutex);
|
|
if (!(deviceExtension->DeviceFlags & DEVICE_FLAG_STARTED)) {
|
|
for (i = 0; i < DOC_DRIVES; i++) {
|
|
if (driveInfo[i].fdoExtension == NULL) {
|
|
deviceExtension->UnitNumber = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
// Check resources
|
|
if (CheckResources) {
|
|
if (ResourceList == NULL || ResourceList->List == NULL) {
|
|
TffsDebugPrint((TFFS_DEB_ERROR,"Trueffs: StartDevice: No resources !\n"));
|
|
goto exitStartDevice;
|
|
}
|
|
fullResourceList = ResourceList->List;
|
|
for (i = 0; i < ResourceList->Count; i++) {
|
|
|
|
partialResourceList = &(fullResourceList->PartialResourceList);
|
|
partialDescriptors = fullResourceList->PartialResourceList.PartialDescriptors;
|
|
|
|
for (j = 0; j < partialResourceList->Count; j++) {
|
|
|
|
if (partialDescriptors[j].Type == CmResourceTypeMemory) {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: Memory %Xh Size %Xh Interf %Xh Bus %Xh\n",
|
|
partialDescriptors[j].u.Memory.Start.LowPart,
|
|
partialDescriptors[j].u.Memory.Length,
|
|
fullResourceList->InterfaceType,
|
|
fullResourceList->BusNumber));
|
|
status = TrueffsCheckDiskOnChip(
|
|
fullResourceList->InterfaceType,
|
|
fullResourceList->BusNumber,
|
|
partialDescriptors[j].u.Memory.Start.LowPart,
|
|
partialDescriptors[j].u.Memory.Length,
|
|
&mappedWindowBase,
|
|
&addressSpace
|
|
);
|
|
if (NT_SUCCESS(status)) {
|
|
deviceExtension->pcmciaParams.windowBase = mappedWindowBase;
|
|
deviceExtension->pcmciaParams.windowSize = partialDescriptors[j].u.Memory.Length;
|
|
deviceExtension->pcmciaParams.addressSpace = addressSpace;
|
|
deviceExtension->pcmciaParams.phWindowBase = RtlConvertLongToLargeInteger(partialDescriptors[j].u.Memory.Start.LowPart);
|
|
deviceExtension->pcmciaParams.physWindow = partialDescriptors[j].u.Memory.Start.QuadPart;
|
|
deviceExtension->pcmciaParams.InterfaceType = fullResourceList->InterfaceType;
|
|
deviceExtension->pcmciaParams.BusNumber = fullResourceList->BusNumber;
|
|
updateDocSocketParams(deviceExtension);
|
|
goto goodResources;
|
|
}
|
|
}
|
|
}
|
|
fullResourceList = (PCM_FULL_RESOURCE_DESCRIPTOR) (partialDescriptors + partialResourceList->Count);
|
|
}
|
|
|
|
// DiskOnChip was not found, assume this is PCMCIA
|
|
if (!(deviceExtension->DeviceFlags & DEVICE_FLAG_STARTED)) {
|
|
for (i = DOC_DRIVES; i < SOCKETS; i++) {
|
|
if (driveInfo[i].fdoExtension == NULL) {
|
|
deviceExtension->UnitNumber = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
fullResourceList = ResourceList->List;
|
|
for (i = 0; i < ResourceList->Count; i++) {
|
|
|
|
partialResourceList = &(fullResourceList->PartialResourceList);
|
|
partialDescriptors = fullResourceList->PartialResourceList.PartialDescriptors;
|
|
|
|
for (j = 0; j < partialResourceList->Count; j++) {
|
|
|
|
if (partialDescriptors[j].Type == CmResourceTypeMemory) {
|
|
PHYSICAL_ADDRESS AddressMemoryBase;
|
|
ULONG PcmciaAddressSpace = TFFS_MEMORY_SPACE;
|
|
deviceExtension->pcmciaParams.windowSize = partialDescriptors[j].u.Memory.Length;
|
|
deviceExtension->pcmciaParams.phWindowBase = RtlConvertLongToLargeInteger(partialDescriptors[j].u.Memory.Start.LowPart);
|
|
deviceExtension->pcmciaParams.physWindow = partialDescriptors[j].u.Memory.Start.QuadPart;
|
|
deviceExtension->pcmciaParams.InterfaceType = fullResourceList->InterfaceType;
|
|
deviceExtension->pcmciaParams.BusNumber = fullResourceList->BusNumber;
|
|
mappedWindowBase = NULL;
|
|
status = TrueffsTranslateAddress(
|
|
deviceExtension->pcmciaParams.InterfaceType,
|
|
deviceExtension->pcmciaParams.BusNumber,
|
|
deviceExtension->pcmciaParams.phWindowBase,
|
|
deviceExtension->pcmciaParams.windowSize,
|
|
&PcmciaAddressSpace,
|
|
&mappedWindowBase,
|
|
&AddressMemoryBase);
|
|
deviceExtension->pcmciaParams.windowBase = mappedWindowBase;
|
|
deviceExtension->pcmciaParams.addressSpace = PcmciaAddressSpace;
|
|
if (!NT_SUCCESS(status)) {
|
|
goto exitStartDevice;
|
|
}
|
|
status = updatePcmciaSocketParams(deviceExtension);
|
|
if (NT_SUCCESS(status)) {
|
|
goto goodResources;
|
|
}
|
|
}
|
|
}
|
|
fullResourceList = (PCM_FULL_RESOURCE_DESCRIPTOR) (partialDescriptors + partialResourceList->Count);
|
|
}
|
|
TffsDebugPrint((TFFS_DEB_ERROR,"Trueffs: StartDevice: pnp manager gave me bad resources!\n"));
|
|
status = STATUS_INVALID_PARAMETER;
|
|
goto exitStartDevice;
|
|
}
|
|
|
|
goodResources:
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: Window at %Xh\n",mappedWindowBase));
|
|
if (!(deviceExtension->DeviceFlags & DEVICE_FLAG_STARTED)) {
|
|
|
|
// Create legacy object names
|
|
status = TrueffsCreateSymblicLinks(deviceExtension);
|
|
if (!NT_SUCCESS(status)) {
|
|
goto exitStartDevice;
|
|
}
|
|
}
|
|
ExReleaseFastMutex(&driveInfoReferenceMutex);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: StartDevice OK\n"));
|
|
return STATUS_SUCCESS;
|
|
|
|
exitStartDevice:
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
TrueffsStopRemoveDevice(deviceExtension);
|
|
TrueffsDeleteSymblicLinks(deviceExtension);
|
|
}
|
|
ExReleaseFastMutex(&driveInfoReferenceMutex);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: StartDevice: exit with status %Xh\n",status));
|
|
return status;
|
|
}
|
|
//==============================================
|
|
NTSTATUS
|
|
TrueffsStartDevice(
|
|
IN PDEVICE_EXTENSION deviceExtension,
|
|
IN PCM_RESOURCE_LIST ResourceList,
|
|
IN BOOLEAN CheckResources
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is our START_DEVICE, called when we get an IPR_MN_START_DEVICE.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
|
|
--*/
|
|
|
|
{
|
|
PCM_FULL_RESOURCE_DESCRIPTOR fullResourceList;
|
|
PCM_PARTIAL_RESOURCE_LIST partialResourceList;
|
|
PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDescriptors;
|
|
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
|
ULONG i;
|
|
ULONG j;
|
|
PVOID mappedWindowBase = NULL;
|
|
ULONG addressSpace;
|
|
|
|
// assume we have DOC
|
|
ExAcquireFastMutex(&driveInfoReferenceMutex);
|
|
|
|
// Check resources
|
|
if (CheckResources) {
|
|
if (ResourceList == NULL || ResourceList->List == NULL) {
|
|
TffsDebugPrint((TFFS_DEB_ERROR,"Trueffs: StartDevice: No resources !\n"));
|
|
goto exitStartDevice;
|
|
}
|
|
fullResourceList = ResourceList->List;
|
|
for (i = 0; i < ResourceList->Count; i++) {
|
|
|
|
partialResourceList = &(fullResourceList->PartialResourceList);
|
|
partialDescriptors = fullResourceList->PartialResourceList.PartialDescriptors;
|
|
|
|
for (j = 0; j < partialResourceList->Count; j++) {
|
|
|
|
if (partialDescriptors[j].Type == CmResourceTypeMemory) {
|
|
//Get handle here
|
|
int deviceIndex = 0;
|
|
long baseAddress = partialDescriptors[j].u.Memory.Start.LowPart;
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: Memory %Xh Size %Xh Interf %Xh Bus %Xh\n",
|
|
partialDescriptors[j].u.Memory.Start.LowPart,
|
|
partialDescriptors[j].u.Memory.Length,
|
|
fullResourceList->InterfaceType,
|
|
fullResourceList->BusNumber));
|
|
|
|
status = TrueffsCheckDiskOnChip(
|
|
fullResourceList->InterfaceType,
|
|
fullResourceList->BusNumber,
|
|
partialDescriptors[j].u.Memory.Start.LowPart,
|
|
partialDescriptors[j].u.Memory.Length,
|
|
&mappedWindowBase,
|
|
&addressSpace
|
|
);
|
|
|
|
if (NT_SUCCESS(status)) {
|
|
for(deviceIndex = 0; deviceIndex < DOC_DRIVES; deviceIndex++) {
|
|
//If Main partition exists
|
|
if(info[deviceIndex].baseAddress == baseAddress){
|
|
deviceExtension->UnitNumber = deviceIndex + (info[deviceIndex].nextPartition << 4);
|
|
info[deviceIndex].nextPartition++;
|
|
break;
|
|
}
|
|
//In case of Main partition doesn't exist
|
|
else if((info[deviceIndex].baseAddress == 0) && (baseAddress != 0)){
|
|
info[deviceIndex].baseAddress = baseAddress;
|
|
deviceExtension->UnitNumber = deviceIndex;
|
|
info[deviceIndex].nextPartition++;
|
|
break;
|
|
}
|
|
}
|
|
if(deviceIndex == DOC_DRIVES){
|
|
goto pcmciaResources;
|
|
}
|
|
}
|
|
if (NT_SUCCESS(status)) {
|
|
deviceExtension->pcmciaParams.windowBase = mappedWindowBase;
|
|
deviceExtension->pcmciaParams.windowSize = partialDescriptors[j].u.Memory.Length;
|
|
deviceExtension->pcmciaParams.addressSpace = addressSpace;
|
|
deviceExtension->pcmciaParams.phWindowBase = RtlConvertLongToLargeInteger(partialDescriptors[j].u.Memory.Start.LowPart);
|
|
deviceExtension->pcmciaParams.physWindow = partialDescriptors[j].u.Memory.Start.QuadPart;
|
|
deviceExtension->pcmciaParams.InterfaceType = fullResourceList->InterfaceType;
|
|
deviceExtension->pcmciaParams.BusNumber = fullResourceList->BusNumber;
|
|
|
|
//In case of Main partition
|
|
if((deviceExtension->UnitNumber & 0xf0) == 0)
|
|
updateDocSocketParams(deviceExtension);
|
|
goto goodResources;
|
|
}
|
|
}
|
|
}
|
|
fullResourceList = (PCM_FULL_RESOURCE_DESCRIPTOR) (partialDescriptors + partialResourceList->Count);
|
|
}
|
|
|
|
|
|
pcmciaResources:
|
|
// DiskOnChip was not found, assume this is PCMCIA
|
|
if (!(deviceExtension->DeviceFlags & DEVICE_FLAG_STARTED)) {
|
|
for (i = DOC_DRIVES; i < SOCKETS; i++) {
|
|
if (driveInfo[i].fdoExtension == NULL) {
|
|
deviceExtension->UnitNumber = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
fullResourceList = ResourceList->List;
|
|
for (i = 0; i < ResourceList->Count; i++) {
|
|
|
|
partialResourceList = &(fullResourceList->PartialResourceList);
|
|
partialDescriptors = fullResourceList->PartialResourceList.PartialDescriptors;
|
|
|
|
for (j = 0; j < partialResourceList->Count; j++) {
|
|
|
|
if (partialDescriptors[j].Type == CmResourceTypeMemory) {
|
|
PHYSICAL_ADDRESS AddressMemoryBase;
|
|
ULONG PcmciaAddressSpace = TFFS_MEMORY_SPACE;
|
|
deviceExtension->pcmciaParams.windowSize = partialDescriptors[j].u.Memory.Length;
|
|
deviceExtension->pcmciaParams.phWindowBase = RtlConvertLongToLargeInteger(partialDescriptors[j].u.Memory.Start.LowPart);
|
|
deviceExtension->pcmciaParams.physWindow = partialDescriptors[j].u.Memory.Start.QuadPart;
|
|
deviceExtension->pcmciaParams.InterfaceType = fullResourceList->InterfaceType;
|
|
deviceExtension->pcmciaParams.BusNumber = fullResourceList->BusNumber;
|
|
mappedWindowBase = NULL;
|
|
status = TrueffsTranslateAddress(
|
|
deviceExtension->pcmciaParams.InterfaceType,
|
|
deviceExtension->pcmciaParams.BusNumber,
|
|
deviceExtension->pcmciaParams.phWindowBase,
|
|
deviceExtension->pcmciaParams.windowSize,
|
|
&PcmciaAddressSpace,
|
|
&mappedWindowBase,
|
|
&AddressMemoryBase);
|
|
deviceExtension->pcmciaParams.windowBase = mappedWindowBase;
|
|
deviceExtension->pcmciaParams.addressSpace = PcmciaAddressSpace;
|
|
if (!NT_SUCCESS(status)) {
|
|
goto exitStartDevice;
|
|
}
|
|
status = updatePcmciaSocketParams(deviceExtension);
|
|
|
|
if (NT_SUCCESS(status)) {
|
|
goto goodResources;
|
|
}
|
|
}
|
|
}
|
|
fullResourceList = (PCM_FULL_RESOURCE_DESCRIPTOR) (partialDescriptors + partialResourceList->Count);
|
|
}
|
|
TffsDebugPrint((TFFS_DEB_ERROR,"Trueffs: StartDevice: pnp manager gave me bad resources!\n"));
|
|
status = STATUS_INVALID_PARAMETER;
|
|
goto exitStartDevice;
|
|
}
|
|
|
|
goodResources:
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: Window at %Xh\n",mappedWindowBase));
|
|
if (!(deviceExtension->DeviceFlags & DEVICE_FLAG_STARTED)) {
|
|
|
|
// Create legacy object names
|
|
status = TrueffsCreateSymblicLinks(deviceExtension);
|
|
if (!NT_SUCCESS(status)) {
|
|
goto exitStartDevice;
|
|
}
|
|
}
|
|
ExReleaseFastMutex(&driveInfoReferenceMutex);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: StartDevice OK\n"));
|
|
return STATUS_SUCCESS;
|
|
|
|
exitStartDevice:
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
TrueffsStopRemoveDevice(deviceExtension);
|
|
TrueffsDeleteSymblicLinks(deviceExtension);
|
|
}
|
|
ExReleaseFastMutex(&driveInfoReferenceMutex);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: StartDevice: exit with status %Xh\n",status));
|
|
return status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
TrueffsMountMedia(
|
|
IN PDEVICE_EXTENSION deviceExtension
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is a part of START_DEVICE, called when we get an IPR_MN_START_DEVICE.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS status;
|
|
FLStatus flStatus = flOK;
|
|
FLStatus flStatusProt = flOK;
|
|
IOreq ioreq;
|
|
IOreq ioreqProt;
|
|
HANDLE threadHandle;
|
|
ULONG heads, sectors, cylinders;
|
|
ULONG prevValue;
|
|
UCHAR currSockets = 0;
|
|
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: MountMedia\n"));
|
|
|
|
ioreq.irHandle = deviceExtension->UnitNumber;
|
|
flStatus = flAbsMountVolume(&ioreq);
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: MountMedia: flMountVolume returned status %Xh\n",flStatus));
|
|
|
|
if (flStatus != flOK) {
|
|
status = STATUS_UNRECOGNIZED_MEDIA;
|
|
goto exitMountMedia;
|
|
}
|
|
|
|
//Identify Write Protected Disk
|
|
ioreqProt.irHandle = ioreq.irHandle;
|
|
ioreqProt.irFlags = 0;
|
|
flStatusProt = flIdentifyProtection(&ioreqProt);
|
|
if(flStatusProt == flOK){
|
|
if(ioreqProt.irFlags& WRITE_PROTECTED){
|
|
|
|
deviceExtension->IsWriteProtected = TRUE;
|
|
deviceExtension->IsPartitonTableWritten = FALSE;
|
|
RtlZeroMemory (deviceExtension->PartitonTable, sizeof(deviceExtension->PartitonTable));
|
|
}
|
|
else{
|
|
deviceExtension->IsWriteProtected = FALSE;
|
|
deviceExtension->IsPartitonTableWritten = FALSE;
|
|
}
|
|
}
|
|
else{
|
|
|
|
deviceExtension->IsWriteProtected = FALSE;
|
|
deviceExtension->IsPartitonTableWritten = FALSE;
|
|
}
|
|
|
|
//Identify SW Write Protected Disk
|
|
deviceExtension->IsSWWriteProtected = FALSE;
|
|
|
|
/* flStatusProt = flIdentifySWProtection(&ioreqProt);
|
|
if(flStatusProt == flOK){
|
|
if(ioreqProt.irFlags& WRITE_PROTECTED){
|
|
|
|
deviceExtension->IsSWWriteProtected = TRUE;
|
|
}
|
|
else{
|
|
deviceExtension->IsSWWriteProtected = FALSE;
|
|
}
|
|
}
|
|
else{
|
|
|
|
deviceExtension->IsSWWriteProtected = FALSE;
|
|
}
|
|
*/
|
|
//In case of protection allocate Partiton table
|
|
flSectorsInVolume(&ioreq);
|
|
deviceExtension->totalSectors = ioreq.irLength;
|
|
deviceExtension->BytesPerSector = SECTOR_SIZE;
|
|
flBuildGeometry(deviceExtension->totalSectors, &cylinders, &heads, §ors,0);
|
|
deviceExtension->SectorsPerTrack = sectors;
|
|
deviceExtension->NumberOfHeads = heads;
|
|
deviceExtension->Cylinders = cylinders;
|
|
|
|
deviceExtension->totalSectors = deviceExtension->SectorsPerTrack *
|
|
deviceExtension->NumberOfHeads *
|
|
deviceExtension->Cylinders;
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: internal geometry #sectors %x, #heads %x, #cylinders %x #total %x\n",
|
|
deviceExtension->SectorsPerTrack,
|
|
deviceExtension->NumberOfHeads,
|
|
deviceExtension->Cylinders,
|
|
deviceExtension->totalSectors));
|
|
|
|
if (!(deviceExtension->DeviceFlags & DEVICE_FLAG_STARTED)) {
|
|
|
|
if (AllocatePdo(deviceExtension) == NULL) {
|
|
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto exitMountMedia;
|
|
}
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: Created PDO %Xh\n",deviceExtension->ChildPdo));
|
|
|
|
if (++(deviceExtension->threadReferenceCount) == 0) {
|
|
deviceExtension->threadReferenceCount++;
|
|
|
|
// Create the thread
|
|
status = PsCreateSystemThread(&threadHandle,
|
|
(ACCESS_MASK) 0L,
|
|
NULL,
|
|
(HANDLE) 0L,
|
|
NULL,
|
|
TrueffsThread,
|
|
deviceExtension);
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: PsCreateSystemThread returned status %Xh\n", status));
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
deviceExtension->threadReferenceCount = -1;
|
|
goto exitMountMedia;
|
|
}
|
|
else {
|
|
status = ObReferenceObjectByHandle( threadHandle,
|
|
SYNCHRONIZE,
|
|
NULL,
|
|
KernelMode,
|
|
&deviceExtension->TffsportThreadObject,
|
|
NULL );
|
|
|
|
ASSERT(NT_SUCCESS(status));
|
|
|
|
// Not needed.. we have the TffsportThreadObject
|
|
// deviceExtension->DeviceFlags |= DEVICE_FLAG_THREAD;
|
|
}
|
|
|
|
ZwClose(threadHandle);
|
|
}
|
|
}
|
|
|
|
#ifdef ENVIRONMENT_VARS
|
|
|
|
for ( currSockets = 0; currSockets < SOCKETS; currSockets++) {
|
|
if (VerifyWriteState[currSockets])
|
|
status = flSetEnvSocket(FL_VERIFY_WRITE_BDTL,currSockets,VerifyWriteState[currSockets],&prevValue);
|
|
}
|
|
|
|
#endif /*ENVIRONMENT_VARS */
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
exitMountMedia:
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
TrueffsStopRemoveDevice(deviceExtension);
|
|
TrueffsDeleteSymblicLinks(deviceExtension);
|
|
}
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: MountMedia: exit with status %Xh\n",status));
|
|
return status;
|
|
}
|
|
|
|
UCHAR
|
|
TrueffsGetInfoNumber
|
|
(
|
|
PDEVICE_EXTENSION deviceExtension
|
|
)
|
|
{
|
|
UCHAR unitNumber;
|
|
UCHAR i = 0;
|
|
for(; i < (UCHAR)DOC_DRIVES;i++){
|
|
if(info[i].baseAddress == (long)deviceExtension->pcmciaParams.phWindowBase.LowPart)
|
|
break;
|
|
}
|
|
|
|
return i;
|
|
}
|
|
|
|
NTSTATUS
|
|
TrueffsStopRemoveDevice(
|
|
PDEVICE_EXTENSION deviceExtension
|
|
)
|
|
{
|
|
IOreq ioreq;
|
|
UCHAR deviceIndex;
|
|
|
|
TffsDebugPrint((TFFS_DEB_ERROR,"Trueffs: StopRemoveDevice: removed deviceExtension->UnitNumber = %0x\n", deviceExtension->UnitNumber));
|
|
if (deviceExtension->pcmciaParams.windowBase == NULL &&
|
|
deviceExtension->pcmciaParams.physWindow == 0 &&
|
|
driveInfo[deviceExtension->UnitNumber].fdoExtension == NULL) {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: StopRemoveDevice: Device was already stopped or removed\n"));
|
|
return STATUS_SUCCESS;
|
|
}
|
|
ioreq.irHandle = deviceExtension->UnitNumber;
|
|
flDismountVolume(&ioreq);
|
|
|
|
deviceIndex = TrueffsGetInfoNumber(deviceExtension);
|
|
//In case of DiskOnChip (especially MDOCP)
|
|
if( deviceIndex < DOC_DRIVES){
|
|
|
|
/* TrueffsFreeTranslatedAddress(deviceExtension->pcmciaParams.windowBase,
|
|
deviceExtension->pcmciaParams.windowSize,
|
|
deviceExtension->pcmciaParams.addressSpace
|
|
);
|
|
*/
|
|
|
|
deviceExtension->pcmciaParams.windowBase = NULL;
|
|
deviceExtension->pcmciaParams.physWindow = 0;
|
|
|
|
//In case of MainPartition
|
|
if((deviceExtension->UnitNumber & 0xf0) == 0){
|
|
driveInfo[deviceExtension->UnitNumber].fdoExtension = NULL;
|
|
driveInfo[deviceExtension->UnitNumber].interfAlive = 0;
|
|
info[deviceIndex].baseAddress = 0;
|
|
}
|
|
info[deviceIndex].nextPartition = (unsigned char)(((deviceExtension->UnitNumber & 0xf0) )>>4);
|
|
// info[deviceIndex].nextPartition--;
|
|
|
|
}
|
|
//PCMCIA
|
|
else{
|
|
TrueffsFreeTranslatedAddress(deviceExtension->pcmciaParams.windowBase,
|
|
deviceExtension->pcmciaParams.windowSize,
|
|
deviceExtension->pcmciaParams.addressSpace
|
|
);
|
|
deviceExtension->pcmciaParams.windowBase = NULL;
|
|
deviceExtension->pcmciaParams.physWindow = 0;
|
|
driveInfo[deviceExtension->UnitNumber].fdoExtension = NULL;
|
|
driveInfo[deviceExtension->UnitNumber].interfAlive = 0;
|
|
}
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: RemoveDevice\n"));
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
TrueffsCreateSymblicLinks (
|
|
PDEVICE_EXTENSION FdoExtension
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
ULONG i;
|
|
PULONG scsiportNumber;
|
|
|
|
STRING deviceName;
|
|
CCHAR deviceNameBuffer[64];
|
|
WCHAR deviceSymbolicNameBuffer[64];
|
|
UNICODE_STRING unicodeDeviceNameString;
|
|
UNICODE_STRING unicodeDeviceSymbolicNameString;
|
|
UNICODE_STRING unicodeDeviceArcNameString;
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: CreateSymblicLinks\n"));
|
|
|
|
sprintf(deviceNameBuffer, "\\Device\\TffsPort%d", FdoExtension->TrueffsDeviceNumber);
|
|
RtlInitString(&deviceName, deviceNameBuffer);
|
|
status = RtlAnsiStringToUnicodeString(&unicodeDeviceNameString,
|
|
&deviceName,
|
|
TRUE);
|
|
if (!NT_SUCCESS (status)) {
|
|
|
|
return status;
|
|
}
|
|
|
|
scsiportNumber = &IoGetConfigurationInformation()->ScsiPortCount;
|
|
|
|
unicodeDeviceSymbolicNameString.Length = 0;
|
|
unicodeDeviceSymbolicNameString.MaximumLength = 64 * sizeof(WCHAR);
|
|
unicodeDeviceSymbolicNameString.Buffer = deviceSymbolicNameBuffer;
|
|
|
|
for (i=0; i <= (*scsiportNumber); i++) {
|
|
|
|
sprintf(deviceNameBuffer, "\\Device\\ScsiPort%d", i);
|
|
RtlInitString(&deviceName, deviceNameBuffer);
|
|
status = RtlAnsiStringToUnicodeString(&unicodeDeviceSymbolicNameString,
|
|
&deviceName,
|
|
FALSE);
|
|
|
|
if (!NT_SUCCESS (status)) {
|
|
|
|
break;
|
|
}
|
|
|
|
status = IoCreateSymbolicLink(
|
|
&unicodeDeviceSymbolicNameString,
|
|
&unicodeDeviceNameString
|
|
);
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: IoCreateSymbolicLink returned status %Xh\n",status));
|
|
|
|
if (NT_SUCCESS (status)) {
|
|
|
|
sprintf(deviceNameBuffer, "\\DosDevices\\Scsi%d:", i);
|
|
RtlInitString(&deviceName, deviceNameBuffer);
|
|
status = RtlAnsiStringToUnicodeString(&unicodeDeviceArcNameString,
|
|
&deviceName,
|
|
TRUE);
|
|
|
|
if (!NT_SUCCESS (status)) {
|
|
|
|
break;
|
|
}
|
|
|
|
IoAssignArcName (
|
|
&unicodeDeviceArcNameString,
|
|
&unicodeDeviceNameString
|
|
);
|
|
|
|
RtlFreeUnicodeString (&unicodeDeviceArcNameString);
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
if (NT_SUCCESS(status)) {
|
|
|
|
FdoExtension->SymbolicLinkCreated = TRUE;
|
|
FdoExtension->ScsiPortNumber = i;
|
|
(*scsiportNumber)++;
|
|
}
|
|
|
|
RtlFreeUnicodeString (&unicodeDeviceNameString);
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: CreateSymblicLinks exit with status %Xh\n",status));
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
TrueffsDeleteSymblicLinks (
|
|
PDEVICE_EXTENSION FdoExtension
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
ULONG i;
|
|
STRING deviceName;
|
|
CCHAR deviceNameBuffer[64];
|
|
UNICODE_STRING unicodeDeviceSymbolicNameString;
|
|
UNICODE_STRING unicodeDeviceArcNameString;
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeleteSymblicLinks\n"));
|
|
|
|
if (!FdoExtension->SymbolicLinkCreated) {
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
sprintf(deviceNameBuffer, "\\Device\\ScsiPort%d", FdoExtension->ScsiPortNumber);
|
|
RtlInitString(&deviceName, deviceNameBuffer);
|
|
status = RtlAnsiStringToUnicodeString(&unicodeDeviceSymbolicNameString,
|
|
&deviceName,
|
|
TRUE);
|
|
if (NT_SUCCESS (status)) {
|
|
|
|
sprintf(deviceNameBuffer, "\\DosDevices\\Scsi%d:", FdoExtension->ScsiPortNumber);
|
|
RtlInitString(&deviceName, deviceNameBuffer);
|
|
status = RtlAnsiStringToUnicodeString(&unicodeDeviceArcNameString,
|
|
&deviceName,
|
|
TRUE);
|
|
|
|
if (NT_SUCCESS (status)) {
|
|
|
|
status = IoDeleteSymbolicLink(
|
|
&unicodeDeviceSymbolicNameString
|
|
);
|
|
|
|
if (NT_SUCCESS (status)) {
|
|
|
|
IoDeassignArcName(&unicodeDeviceArcNameString);
|
|
FdoExtension->SymbolicLinkCreated = FALSE;
|
|
|
|
IoGetConfigurationInformation()->ScsiPortCount--;
|
|
}
|
|
|
|
RtlFreeUnicodeString (&unicodeDeviceArcNameString);
|
|
}
|
|
|
|
RtlFreeUnicodeString (&unicodeDeviceSymbolicNameString);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
VOID
|
|
TrueffsUnload(
|
|
IN PDRIVER_OBJECT DriverObject
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Does nothing really...
|
|
|
|
Arguments:
|
|
|
|
DriverObject - the driver being unloaded
|
|
|
|
Return Value:
|
|
|
|
none
|
|
|
|
--*/
|
|
|
|
{
|
|
PTRUEFFSDRIVER_EXTENSION trueffsDriverExtension;
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: Unload\n"));
|
|
flExit();
|
|
trueffsDriverExtension = IoGetDriverObjectExtension(
|
|
DriverObject,
|
|
DRIVER_OBJECT_EXTENSION_ID
|
|
);
|
|
|
|
if (trueffsDriverExtension && trueffsDriverExtension->RegistryPath.Buffer != NULL)
|
|
{
|
|
ExFreePool(trueffsDriverExtension->RegistryPath.Buffer);
|
|
}
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: Exitting Unload\n"));
|
|
return;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
TrueffsDeviceControl(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is the device control dispatcher.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject
|
|
Irp
|
|
|
|
Return Value:
|
|
|
|
|
|
NTSTATUS
|
|
|
|
--*/
|
|
|
|
{
|
|
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
|
|
PSTORAGE_PROPERTY_QUERY query;
|
|
//Amir
|
|
PGET_MEDIA_TYPES getMediaTypes;
|
|
NTSTATUS status;
|
|
PDEVICE_EXTENSION deviceExtension;
|
|
PPDO_EXTENSION pdoExtension;
|
|
PDEVICE_EXTENSION_HEADER devExtension;
|
|
BOOLEAN Fdo = FALSE;
|
|
//Amir
|
|
FLStatus tffsStatus;
|
|
IOreq ioreq;
|
|
flIOctlRecord flIoctlRec;
|
|
//End Amir
|
|
devExtension = (PDEVICE_EXTENSION_HEADER) DeviceObject->DeviceExtension;
|
|
if (IS_FDO(devExtension)) {
|
|
deviceExtension = DeviceObject->DeviceExtension;
|
|
Fdo = TRUE;
|
|
}
|
|
else {
|
|
pdoExtension = DeviceObject->DeviceExtension;
|
|
deviceExtension = pdoExtension->Pext;
|
|
}
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: Code %Xh\n",irpStack->Parameters.DeviceIoControl.IoControlCode));
|
|
|
|
switch (irpStack->Parameters.DeviceIoControl.IoControlCode) {
|
|
|
|
case IOCTL_DISK_GET_DRIVE_GEOMETRY: {
|
|
|
|
PDISK_GEOMETRY pDiskGeometry = NULL;
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: GET_DISK_GEOMETRY\n"));
|
|
|
|
// Check size of return buffer
|
|
if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
|
|
sizeof(DISK_GEOMETRY)) {
|
|
|
|
status = Irp->IoStatus.Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
Irp->IoStatus.Information = 0;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
break;
|
|
}
|
|
|
|
pDiskGeometry = (PDISK_GEOMETRY)Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
// Trueffs is always Fixed Media
|
|
pDiskGeometry->MediaType = FixedMedia;
|
|
|
|
// All the fields neccesary are filled in during mount-media
|
|
pDiskGeometry->TracksPerCylinder = deviceExtension->NumberOfHeads;
|
|
pDiskGeometry->SectorsPerTrack = deviceExtension->SectorsPerTrack;
|
|
pDiskGeometry->BytesPerSector = deviceExtension->BytesPerSector;
|
|
pDiskGeometry->Cylinders.QuadPart =
|
|
(LONGLONG)(deviceExtension->totalSectors /
|
|
(pDiskGeometry->TracksPerCylinder * pDiskGeometry->SectorsPerTrack));
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: TracksPerCylinder 0x%x, "
|
|
"SectorsPerTrack 0x%x, BytesPerSector: 0x%x, Cylinders 0x%x\n",
|
|
pDiskGeometry->TracksPerCylinder, pDiskGeometry->SectorsPerTrack,
|
|
pDiskGeometry->BytesPerSector, pDiskGeometry->Cylinders.QuadPart
|
|
));
|
|
|
|
status = Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
Irp->IoStatus.Information = sizeof(DISK_GEOMETRY);
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
break;
|
|
}
|
|
|
|
//AmirM
|
|
/*case IOCTL_STORAGE_GET_MEDIA_TYPES: {
|
|
PGET_MEDIA_TYPES mediaTypes = Irp->AssociatedIrp.SystemBuffer;
|
|
PDEVICE_MEDIA_INFO mediaInfo = &mediaTypes->MediaInfo[0];
|
|
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"$$$$$$$$$$$$$IOCTL_STORAGE_GET_MEDIA_TYPES_EX \n"));
|
|
|
|
//
|
|
// Ensure that buffer is large enough.
|
|
//
|
|
|
|
if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
|
|
sizeof(GET_MEDIA_TYPES)) {
|
|
|
|
//
|
|
// Buffer too small.
|
|
//
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
status = STATUS_INFO_LENGTH_MISMATCH;
|
|
break;
|
|
}
|
|
|
|
mediaTypes->DeviceType = FILE_DEVICE_DISK;
|
|
mediaTypes->MediaInfoCount = 1;
|
|
mediaInfo->DeviceSpecific.RemovableDiskInfo.Cylinders.QuadPart = (LONGLONG)(deviceExtension->totalSectors /
|
|
(deviceExtension->NumberOfHeads * deviceExtension->SectorsPerTrack));
|
|
mediaInfo->DeviceSpecific.RemovableDiskInfo.TracksPerCylinder = deviceExtension->NumberOfHeads;
|
|
mediaInfo->DeviceSpecific.RemovableDiskInfo.SectorsPerTrack = deviceExtension->SectorsPerTrack;
|
|
mediaInfo->DeviceSpecific.RemovableDiskInfo.BytesPerSector = deviceExtension->BytesPerSector;
|
|
|
|
//
|
|
// Set the type.
|
|
//
|
|
mediaInfo->DeviceSpecific.RemovableDiskInfo.MediaType = FixedMedia;
|
|
mediaInfo->DeviceSpecific.RemovableDiskInfo.NumberMediaSides = 1;
|
|
mediaInfo->DeviceSpecific.RemovableDiskInfo.MediaCharacteristics = MEDIA_WRITE_PROTECTED;
|
|
|
|
status = Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
Irp->IoStatus.Information = sizeof(GET_MEDIA_TYPES);
|
|
IoCompleteRequest(Irp, 0);
|
|
break;
|
|
}
|
|
*/
|
|
case IOCTL_STORAGE_QUERY_PROPERTY: {
|
|
|
|
// Validate the query
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: StorageQueryProperty\n"));
|
|
|
|
query = Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
if(irpStack->Parameters.DeviceIoControl.InputBufferLength <
|
|
sizeof(STORAGE_PROPERTY_QUERY)) {
|
|
|
|
status = Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
|
|
Irp->IoStatus.Information = 0;
|
|
IoCompleteRequest(Irp, 0);
|
|
break;
|
|
}
|
|
|
|
status = TrueffsQueryProperty(deviceExtension, Irp);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: QueryProperty returned status %Xh\n", status));
|
|
break;
|
|
}
|
|
|
|
case IOCTL_SCSI_GET_DUMP_POINTERS:
|
|
|
|
DebugLogEvent(DeviceObject->DriverObject, 300);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: ScsiGetDumpPointers\n"));
|
|
|
|
if (Fdo) {
|
|
status = Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
|
Irp->IoStatus.Information = 0;
|
|
IoCompleteRequest(Irp, 0);
|
|
return status;
|
|
}
|
|
if (Irp->RequestorMode != KernelMode) {
|
|
status = Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
|
|
|
|
} else if (irpStack->Parameters.DeviceIoControl.OutputBufferLength
|
|
< sizeof(DUMP_POINTERS)) {
|
|
status = Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
|
|
|
|
} else {
|
|
PCRASHDUMP_INIT_DATA dumpInitData;
|
|
|
|
dumpInitData = ExAllocatePoolWithTag (NonPagedPool, sizeof (CRASHDUMP_INIT_DATA), TFFSPORT_POOL_TAG);
|
|
if (dumpInitData) {
|
|
PDUMP_POINTERS dumpPointers;
|
|
dumpPointers = (PDUMP_POINTERS)Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
RtlZeroMemory (dumpInitData, sizeof (CRASHDUMP_INIT_DATA));
|
|
dumpInitData->cdFdoExtension = pdoExtension->Pext;
|
|
dumpPointers->AdapterObject = NULL;
|
|
dumpPointers->MappedRegisterBase = NULL;
|
|
dumpPointers->DumpData = dumpInitData;
|
|
dumpPointers->CommonBufferVa = NULL;
|
|
dumpPointers->CommonBufferPa.QuadPart = 0;
|
|
dumpPointers->CommonBufferSize = 0;
|
|
dumpPointers->DeviceObject = pdoExtension->DeviceObject;
|
|
dumpPointers->AllocateCommonBuffers = FALSE;
|
|
|
|
status = Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
Irp->IoStatus.Information = sizeof(DUMP_POINTERS);
|
|
} else {
|
|
status = Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
}
|
|
IoCompleteRequest(Irp, 0);
|
|
break;
|
|
case IOCTL_TFFSFL_UNIQUE_ID:
|
|
DebugLogEvent(DeviceObject->DriverObject, 200);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: TffsGetUniqueId\n"));
|
|
status = QueueIrpToThread(Irp, deviceExtension);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: TffsGetUniqueId Completed\n"));
|
|
Irp->IoStatus.Status = status;
|
|
break;
|
|
|
|
case IOCTL_TFFS_FORMAT_PHYSICAL_DRIVE:
|
|
DebugLogEvent(DeviceObject->DriverObject, 200);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: IOCTL_TFFS_FORMAT_PHYSICAL_DRIVE\n"));
|
|
status = QueueIrpToThread(Irp, deviceExtension);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: MOTIR: IOCTL_TFFS_FORMAT_PHYSICAL_DRIVE Completed\n"));
|
|
Irp->IoStatus.Status = status;
|
|
break;
|
|
|
|
#ifdef HW_PROTECTION
|
|
case IOCTL_TFFS_BDTL_HW_PROTECTION:
|
|
DebugLogEvent(DeviceObject->DriverObject, 200);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: IOCTL_TFFS_BDTL_HW_PROTECTION\n"));
|
|
status = QueueIrpToThread(Irp, deviceExtension);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: MOTIR: IOCTL_TFFS_BDTL_HW_PROTECTION Completed\n"));
|
|
Irp->IoStatus.Status = status;
|
|
break;
|
|
case IOCTL_TFFS_BINARY_HW_PROTECTION:
|
|
DebugLogEvent(DeviceObject->DriverObject, 200);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: IOCTL_TFFS_BINARY_HW_PROTECTION\n"));
|
|
status = QueueIrpToThread(Irp, deviceExtension);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: MOTIR: IOCTL_TFFS_BINARY_HW_PROTECTION Completed\n"));
|
|
Irp->IoStatus.Status = status;
|
|
break;
|
|
#endif /*HW_PROTECTION*/
|
|
#ifdef HW_OTP
|
|
case IOCTL_TFFS_OTP:
|
|
DebugLogEvent(DeviceObject->DriverObject, 200);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: IOCTL_TFFS_OTP\n"));
|
|
status = QueueIrpToThread(Irp, deviceExtension);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: MOTIR: IOCTL_TFFS_OTP Completed\n"));
|
|
Irp->IoStatus.Status = status;
|
|
break;
|
|
#endif /*HW_OTP*/
|
|
#ifdef WRITE_EXB_IMAGE
|
|
case IOCTL_TFFS_PLACE_EXB_BY_BUFFER:
|
|
DebugLogEvent(DeviceObject->DriverObject, 200);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: IOCTL_TFFS_PLACE_EXB_BY_BUFFER\n"));
|
|
status = QueueIrpToThread(Irp, deviceExtension);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: MOTIR: IOCTL_TFFS_PLACE_EXB_BY_BUFFER Completed\n"));
|
|
Irp->IoStatus.Status = status;
|
|
break;
|
|
#endif /*WRITE_EXB_IMAGE*/
|
|
case IOCTL_TFFS_DEEP_POWER_DOWN_MODE:
|
|
DebugLogEvent(DeviceObject->DriverObject, 200);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: IOCTL_TFFS_DEEP_POWER_DOWN_MODE\n"));
|
|
status = QueueIrpToThread(Irp, deviceExtension);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: MOTIR: IOCTL_TFFS_DEEP_POWER_DOWN_MODE Completed\n"));
|
|
Irp->IoStatus.Status = status;
|
|
break;
|
|
case IOCTL_TFFSFL_INQUIRE_CAPABILITIES:
|
|
DebugLogEvent(DeviceObject->DriverObject, 200);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: TffsGetInquireCapabilities\n"));
|
|
status = QueueIrpToThread(Irp, deviceExtension);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: MOTIR: TffsGetInquireCapabilities Completed\n"));
|
|
Irp->IoStatus.Status = status;
|
|
break;
|
|
|
|
case IOCTL_TFFS_GET_INFO: // User TFFS IOCTL - FL_GET_INFO
|
|
|
|
DebugLogEvent(DeviceObject->DriverObject, 200);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: TffsGetInfo\n"));
|
|
status = QueueIrpToThread(Irp, deviceExtension);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: TffsGetInfo start get info\n"));
|
|
Irp->IoStatus.Status = status;
|
|
break;
|
|
|
|
case IOCTL_TFFS_DEFRAGMENT: // User TFFS IOCTL - FL_DEFRAGMENT
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: TffsDefragment\n"));
|
|
status = QueueIrpToThread(Irp, deviceExtension);
|
|
Irp->IoStatus.Status = status;
|
|
break;
|
|
#ifdef VERIFY_VOLUME
|
|
case IOCTL_TFFS_VERIFY_VOLUME:
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: TffsVerifyVolume\n"));
|
|
status = QueueIrpToThread(Irp, deviceExtension);
|
|
Irp->IoStatus.Status = status;
|
|
break;
|
|
#endif VERIFY_VOLUME
|
|
|
|
case IOCTL_TFFS_WRITE_PROTECT: // User TFFS IOCTL - FL_WRITE_PROTECT
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: TffsWriteProtect\n"));
|
|
status = QueueIrpToThread(Irp, deviceExtension);
|
|
Irp->IoStatus.Status = status;
|
|
break;
|
|
|
|
case IOCTL_TFFS_MOUNT_VOLUME: // User TFFS IOCTL - FL_MOUNT_VOLUME
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: TffsMountVolume\n"));
|
|
status = QueueIrpToThread(Irp, deviceExtension);
|
|
Irp->IoStatus.Status = status;
|
|
break;
|
|
|
|
case IOCTL_TFFS_FORMAT_VOLUME: // User TFFS IOCTL - FL_FORMAT_VOLUME
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: TffsFormatVolume\n"));
|
|
status = QueueIrpToThread(Irp, deviceExtension);
|
|
Irp->IoStatus.Status = status;
|
|
break;
|
|
|
|
case IOCTL_TFFS_BDK_OPERATION: // User TFFS IOCTL - FL_BDK_OPERATION
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: IOCTL_TFFS_BDK_OPERATION\n"));
|
|
status = QueueIrpToThread(Irp, deviceExtension);
|
|
Irp->IoStatus.Status = status;
|
|
break;
|
|
|
|
case IOCTL_TFFS_DELETE_SECTORS: // User TFFS IOCTL - FL_DELETE_SECTORS
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: TffsDeleteSectors\n"));
|
|
status = QueueIrpToThread(Irp, deviceExtension);
|
|
Irp->IoStatus.Status = status;
|
|
break;
|
|
case IOCTL_TFFS_CUSTOMER_ID: // User TFFS IOCTL - FL_IOCTL_NUMBER_OF_PARTITIONS
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: IOCTL_TFFS_CUSTOMER_ID\n"));
|
|
status = QueueIrpToThread(Irp, deviceExtension);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : start IOCTL_TFFS_CUSTOMER_ID\n"));
|
|
Irp->IoStatus.Status = status;
|
|
break;
|
|
|
|
case IOCTL_TFFS_EXTENDED_WRITE_IPL: // User TFFS IOCTL -
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: IOCTL_TFFS_EXTENDED_WRITE_IPL\n"));
|
|
status = QueueIrpToThread(Irp, deviceExtension);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : start IOCTL_TFFS_EXTENDED_WRITE_IPL\n"));
|
|
Irp->IoStatus.Status = status;
|
|
break;
|
|
|
|
#ifdef ENVIRONMENT_VARS
|
|
case IOCTL_TFFS_EXTENDED_ENVIRONMENT_VARIABLES: // User TFFS IOCTL -
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: IOCTL_TFFS_EXTENDED_ENVIRONMENT_VARIABLES\n"));
|
|
status = QueueIrpToThread(Irp, deviceExtension);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : start IOCTL_TFFS_EXTENDED_ENVIRONMENT_VARIABLES\n"));
|
|
Irp->IoStatus.Status = status;
|
|
break;
|
|
#endif /* ENVIRONMENT_VARS */
|
|
|
|
case IOCTL_TFFS_NUMBER_OF_PARTITIONS: // User TFFS IOCTL - FL_IOCTL_NUMBER_OF_PARTITIONS
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: FL_IOCTL_NUMBER_OF_PARTITIONS\n"));
|
|
status = QueueIrpToThread(Irp, deviceExtension);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : start FL_IOCTL_NUMBER_OF_PARTITIONS\n"));
|
|
Irp->IoStatus.Status = status;
|
|
break;
|
|
|
|
/* case IOCTL_DISK_IS_WRITABLE:
|
|
TffsDebugPrint((TFFS_DEB_ERROR,"#$$%^%$%#%$#%#%$#%#%#%#%#%#%#%$#%#%\n"));
|
|
status = Irp->IoStatus.Status = STATUS_MEDIA_WRITE_PROTECTED;
|
|
Irp->IoStatus.Information = 0;
|
|
IoCompleteRequest(Irp, 0);
|
|
break;
|
|
*/
|
|
default:
|
|
|
|
TffsDebugPrint((TFFS_DEB_WARN,"Trueffs: DeviceControl: not suported\n"));
|
|
status = Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
|
Irp->IoStatus.Information = 0;
|
|
IoCompleteRequest(Irp, 0);
|
|
break;
|
|
|
|
}
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: exit with status %Xh\n", status));
|
|
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS
|
|
TrueffsQueryProperty(
|
|
IN PDEVICE_EXTENSION deviceExtension,
|
|
IN PIRP QueryIrp
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine will handle a property query request.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - a pointer to the device object being queried
|
|
|
|
QueryIrp - a pointer to the irp for the query
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS if the query was successful
|
|
|
|
other error values as applicable
|
|
|
|
--*/
|
|
|
|
{
|
|
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(QueryIrp);
|
|
PSTORAGE_PROPERTY_QUERY query = QueryIrp->AssociatedIrp.SystemBuffer;
|
|
STORAGE_DEVICE_DESCRIPTOR deviceDescriptor;
|
|
STORAGE_ADAPTER_DESCRIPTOR adapterDescriptor;
|
|
PSTORAGE_DEVICE_DESCRIPTOR storageDeviceDescriptor;
|
|
ULONG outBufferSize;
|
|
ULONG numBytesToCopy;
|
|
PUCHAR outBuffer;
|
|
PUCHAR outBufferBegin;
|
|
CHAR vendorString[] = VENDORSTRING;
|
|
CHAR productString[] = PRODUCTSTRING;
|
|
CHAR revisionString[] = REVISIONSTRING;
|
|
CHAR serialString[] = SERIALSTRING;
|
|
NTSTATUS status;
|
|
|
|
|
|
if(query->QueryType >= PropertyMaskQuery) {
|
|
|
|
status = STATUS_NOT_IMPLEMENTED;
|
|
QueryIrp->IoStatus.Status = status;
|
|
QueryIrp->IoStatus.Information = 0;
|
|
IoCompleteRequest(QueryIrp, IO_NO_INCREMENT);
|
|
return status;
|
|
}
|
|
|
|
if(query->QueryType == PropertyExistsQuery) {
|
|
|
|
status = STATUS_SUCCESS;
|
|
QueryIrp->IoStatus.Status = status;
|
|
IoCompleteRequest(QueryIrp, IO_DISK_INCREMENT);
|
|
return status;
|
|
}
|
|
|
|
switch(query->PropertyId) {
|
|
|
|
case StorageDeviceProperty: {
|
|
|
|
outBufferSize = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
|
|
RtlZeroMemory (&deviceDescriptor, sizeof(STORAGE_DEVICE_DESCRIPTOR));
|
|
|
|
//
|
|
// The buffer needs to be large enough to hold the base
|
|
// structure and all the strings [ null terminated ]
|
|
//
|
|
deviceDescriptor.Version = sizeof(STORAGE_DEVICE_DESCRIPTOR);
|
|
deviceDescriptor.Size = sizeof(STORAGE_DEVICE_DESCRIPTOR) + 1 + VENDORSTRINGSIZE + 1 + PRODUCTSTRINGSIZE + 1 + REVISIONSTRINGSIZE + 1 + SERIALSTRINGSIZE + 1;
|
|
|
|
deviceDescriptor.DeviceType = deviceExtension->ScsiDeviceType;
|
|
|
|
if (deviceExtension->removableMedia)
|
|
{
|
|
deviceDescriptor.RemovableMedia = TRUE;
|
|
}
|
|
|
|
deviceDescriptor.BusType = BusTypeAta;
|
|
|
|
if (outBufferSize >= deviceDescriptor.Size)
|
|
{
|
|
numBytesToCopy = deviceDescriptor.Size;
|
|
}
|
|
else
|
|
{
|
|
numBytesToCopy = outBufferSize;
|
|
}
|
|
|
|
QueryIrp->IoStatus.Information = numBytesToCopy;
|
|
outBuffer = QueryIrp->AssociatedIrp.SystemBuffer;
|
|
outBufferBegin = outBuffer;
|
|
status = STATUS_SUCCESS;
|
|
|
|
storageDeviceDescriptor = (PSTORAGE_DEVICE_DESCRIPTOR) QueryIrp->AssociatedIrp.SystemBuffer;
|
|
|
|
if (numBytesToCopy > sizeof(STORAGE_DEVICE_DESCRIPTOR))
|
|
{
|
|
RtlCopyMemory (outBuffer, &deviceDescriptor, sizeof(STORAGE_DEVICE_DESCRIPTOR));
|
|
|
|
numBytesToCopy -= sizeof(STORAGE_DEVICE_DESCRIPTOR);
|
|
outBuffer += sizeof(STORAGE_DEVICE_DESCRIPTOR);
|
|
}
|
|
else
|
|
{
|
|
RtlCopyMemory (outBuffer, &deviceDescriptor, numBytesToCopy);
|
|
break;
|
|
}
|
|
|
|
storageDeviceDescriptor->VendorIdOffset = (ULONG) (outBuffer - outBufferBegin);
|
|
|
|
if (numBytesToCopy > VENDORSTRINGSIZE + 1)
|
|
{
|
|
RtlCopyMemory (outBuffer, vendorString, VENDORSTRINGSIZE);
|
|
outBuffer[VENDORSTRINGSIZE] = '\0';
|
|
|
|
numBytesToCopy -= VENDORSTRINGSIZE + 1;
|
|
outBuffer += VENDORSTRINGSIZE + 1;
|
|
}
|
|
else
|
|
{
|
|
RtlCopyMemory (outBuffer, vendorString, numBytesToCopy);
|
|
break;
|
|
}
|
|
|
|
storageDeviceDescriptor->ProductIdOffset = (ULONG) (outBuffer - outBufferBegin);
|
|
|
|
if (numBytesToCopy > PRODUCTSTRINGSIZE + 1)
|
|
{
|
|
RtlCopyMemory (outBuffer, productString, PRODUCTSTRINGSIZE);
|
|
outBuffer[PRODUCTSTRINGSIZE] = '\0';
|
|
|
|
numBytesToCopy -= PRODUCTSTRINGSIZE + 1;
|
|
outBuffer += PRODUCTSTRINGSIZE + 1;
|
|
}
|
|
else
|
|
{
|
|
RtlCopyMemory (outBuffer, productString, numBytesToCopy);
|
|
break;
|
|
}
|
|
|
|
storageDeviceDescriptor->ProductRevisionOffset = (ULONG) (outBuffer - outBufferBegin);
|
|
|
|
if (numBytesToCopy > REVISIONSTRINGSIZE + 1)
|
|
{
|
|
RtlCopyMemory (outBuffer, revisionString, REVISIONSTRINGSIZE);
|
|
outBuffer[REVISIONSTRINGSIZE] = '\0';
|
|
|
|
numBytesToCopy -= REVISIONSTRINGSIZE + 1;
|
|
outBuffer += REVISIONSTRINGSIZE + 1;
|
|
}
|
|
else
|
|
{
|
|
RtlCopyMemory (outBuffer, revisionString, numBytesToCopy);
|
|
break;
|
|
}
|
|
|
|
storageDeviceDescriptor->SerialNumberOffset = (ULONG) (outBuffer - outBufferBegin);
|
|
|
|
if (numBytesToCopy > SERIALSTRINGSIZE + 1)
|
|
{
|
|
RtlCopyMemory (outBuffer, serialString, SERIALSTRINGSIZE);
|
|
outBuffer[SERIALSTRINGSIZE] = '\0';
|
|
}
|
|
else
|
|
{
|
|
RtlCopyMemory (outBuffer, serialString, numBytesToCopy);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case StorageAdapterProperty: {
|
|
|
|
RtlZeroMemory (&adapterDescriptor, sizeof(adapterDescriptor));
|
|
|
|
adapterDescriptor.Version = sizeof (STORAGE_ADAPTER_DESCRIPTOR);
|
|
adapterDescriptor.Size = sizeof (STORAGE_ADAPTER_DESCRIPTOR);
|
|
adapterDescriptor.MaximumTransferLength = MAX_TRANSFER_SIZE_PER_SRB;
|
|
adapterDescriptor.MaximumPhysicalPages = 0xffffffff;
|
|
adapterDescriptor.AlignmentMask = 0x1;
|
|
adapterDescriptor.AdapterUsesPio = TRUE;
|
|
adapterDescriptor.AdapterScansDown = FALSE;
|
|
adapterDescriptor.CommandQueueing = FALSE;
|
|
adapterDescriptor.AcceleratedTransfer = FALSE;
|
|
adapterDescriptor.BusType = BusTypeAta;
|
|
adapterDescriptor.BusMajorVersion = 1;
|
|
adapterDescriptor.BusMinorVersion = 0;
|
|
|
|
if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
|
|
sizeof(STORAGE_ADAPTER_DESCRIPTOR)) {
|
|
|
|
outBufferSize = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
|
|
|
|
} else {
|
|
|
|
outBufferSize = sizeof(STORAGE_ADAPTER_DESCRIPTOR);
|
|
}
|
|
|
|
RtlCopyMemory (QueryIrp->AssociatedIrp.SystemBuffer,
|
|
&adapterDescriptor,
|
|
outBufferSize);
|
|
|
|
QueryIrp->IoStatus.Information = outBufferSize;
|
|
status = STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
|
|
default: {
|
|
|
|
status = STATUS_NOT_IMPLEMENTED;
|
|
QueryIrp->IoStatus.Information = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
QueryIrp->IoStatus.Status = status;
|
|
IoCompleteRequest(QueryIrp, IO_DISK_INCREMENT);
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
TrueffsCreateClose(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
create and close routine. This is called by the I/O system
|
|
when the device is opened or closed.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - Pointer to device object
|
|
Irp - IRP involved.
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS.
|
|
|
|
--*/
|
|
|
|
{
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: CreateClose\n"));
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
IoCompleteRequest( Irp, IO_NO_INCREMENT );
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
TrueffsPnpDeviceControl(
|
|
PDEVICE_OBJECT DeviceObject,
|
|
PIRP Irp
|
|
)
|
|
{
|
|
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
|
|
PDEVICE_EXTENSION deviceExtension;
|
|
PPDO_EXTENSION pdoExtension = NULL;
|
|
PDEVICE_EXTENSION_HEADER devExtension;
|
|
NTSTATUS status;
|
|
KIRQL cIrql;
|
|
KEVENT event;
|
|
BOOLEAN Fdo = FALSE;
|
|
BOOLEAN processHeldRequests = FALSE;
|
|
|
|
devExtension = (PDEVICE_EXTENSION_HEADER) DeviceObject->DeviceExtension;
|
|
|
|
if (IS_FDO(devExtension))
|
|
{
|
|
deviceExtension = DeviceObject->DeviceExtension;
|
|
Fdo = TRUE;
|
|
}
|
|
else
|
|
{
|
|
pdoExtension = DeviceObject->DeviceExtension;
|
|
deviceExtension = pdoExtension->Pext;
|
|
}
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: PnpDeviceControl: Function %Xh %cDO.\n",irpStack->MinorFunction, Fdo ? 'F':'P'));
|
|
|
|
KeInitializeEvent(&event, NotificationEvent, FALSE);
|
|
|
|
switch (irpStack->MinorFunction)
|
|
{
|
|
|
|
case IRP_MN_START_DEVICE:
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO, "Trueffs: PnpDeviceControl: START_DEVICE\n"));
|
|
|
|
if (Fdo)
|
|
{
|
|
KeAcquireSpinLock(&deviceExtension->ExtensionDataSpinLock,&cIrql);
|
|
deviceExtension->DeviceFlags |= DEVICE_FLAG_STOPPED;
|
|
if (deviceExtension->DeviceFlags & DEVICE_FLAG_STARTED)
|
|
{
|
|
processHeldRequests = TRUE;
|
|
}
|
|
KeReleaseSpinLock(&deviceExtension->ExtensionDataSpinLock,cIrql);
|
|
|
|
status = TrueffsStartDevice(deviceExtension, irpStack->Parameters.StartDevice.AllocatedResourcesTranslated, TRUE);
|
|
|
|
if (NT_SUCCESS(status))
|
|
{
|
|
//
|
|
// Forward this request down synchronously, so that the lower drivers can be started
|
|
//
|
|
IoCopyCurrentIrpStackLocationToNext(Irp);
|
|
status = TrueffsCallDriverSync(deviceExtension->LowerDeviceObject, Irp);
|
|
|
|
if (NT_SUCCESS(status))
|
|
{
|
|
status = TrueffsMountMedia(deviceExtension);
|
|
|
|
KeAcquireSpinLock(&deviceExtension->ExtensionDataSpinLock,&cIrql);
|
|
deviceExtension->DeviceFlags &= ~DEVICE_FLAG_STOPPED;
|
|
deviceExtension->DeviceFlags |= DEVICE_FLAG_STARTED;
|
|
KeReleaseSpinLock(&deviceExtension->ExtensionDataSpinLock,cIrql);
|
|
|
|
if (processHeldRequests && !KeReadStateSemaphore(&deviceExtension->requestSemaphore))
|
|
{
|
|
KeReleaseSemaphore(&deviceExtension->requestSemaphore, (KPRIORITY) 0, 1, FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
Irp->IoStatus.Status = status;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
}
|
|
else
|
|
{
|
|
status = STATUS_SUCCESS;
|
|
|
|
if (!pdoExtension->CrashDumpPathCount)
|
|
{
|
|
DEVICE_POWER_STATE devicePowerState = PowerDeviceD3;
|
|
|
|
pdoExtension->IdleCounter = PoRegisterDeviceForIdleDetection(pdoExtension->DeviceObject,
|
|
DEVICE_DEFAULT_IDLE_TIMEOUT,
|
|
DEVICE_DEFAULT_IDLE_TIMEOUT,
|
|
devicePowerState);
|
|
}
|
|
|
|
KeAcquireSpinLock(&deviceExtension->ExtensionDataSpinLock,&cIrql);
|
|
deviceExtension->DeviceFlags &= ~DEVICE_FLAG_CHILD_REMOVED;
|
|
KeReleaseSpinLock(&deviceExtension->ExtensionDataSpinLock,cIrql);
|
|
|
|
TrueffsWmiRegister ((PDEVICE_EXTENSION_HEADER)pdoExtension);
|
|
|
|
Irp->IoStatus.Status = status;
|
|
IoCompleteRequest(Irp,IO_NO_INCREMENT);
|
|
}
|
|
break;
|
|
|
|
case IRP_MN_QUERY_STOP_DEVICE:
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: PnpDeviceControl: QUERY_STOP_DEVICE\n"));
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
if (Fdo)
|
|
{
|
|
if (deviceExtension->PagingPathCount || deviceExtension->CrashDumpPathCount)
|
|
{
|
|
status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (pdoExtension->PagingPathCount || pdoExtension->CrashDumpPathCount)
|
|
{
|
|
status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
}
|
|
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
Irp->IoStatus.Status = status;
|
|
IoCompleteRequest(Irp,IO_NO_INCREMENT);
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: PnpDeviceControl: Failing QUERY_STOP: we are in PagingPath or CrashDumpPath\n"));
|
|
break;
|
|
}
|
|
|
|
KeAcquireSpinLock(&deviceExtension->ExtensionDataSpinLock,&cIrql);
|
|
deviceExtension->DeviceFlags |= DEVICE_FLAG_QUERY_STOP_REMOVE;
|
|
KeReleaseSpinLock(&deviceExtension->ExtensionDataSpinLock,cIrql);
|
|
|
|
if (Fdo)
|
|
{
|
|
if (deviceExtension->TffsportThreadObject)
|
|
{
|
|
KeWaitForSingleObject(&deviceExtension->PendingIRPEvent, Executive, KernelMode, FALSE, NULL);
|
|
}
|
|
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
status = IoCallDriver(deviceExtension->LowerDeviceObject, Irp);
|
|
}
|
|
else
|
|
{
|
|
Irp->IoStatus.Status = status;
|
|
IoCompleteRequest(Irp,IO_NO_INCREMENT);
|
|
}
|
|
break;
|
|
|
|
case IRP_MN_STOP_DEVICE:
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: PnpDeviceControl: STOP_DEVICE\n"));
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
if (Fdo)
|
|
{
|
|
TrueffsStopRemoveDevice(deviceExtension);
|
|
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
status = IoCallDriver(deviceExtension->LowerDeviceObject, Irp);
|
|
|
|
KeAcquireSpinLock(&deviceExtension->ExtensionDataSpinLock,&cIrql);
|
|
deviceExtension->DeviceFlags |= DEVICE_FLAG_STOPPED;
|
|
deviceExtension->DeviceFlags |= DEVICE_FLAG_QUERY_STOP_REMOVE;
|
|
KeReleaseSpinLock(&deviceExtension->ExtensionDataSpinLock,cIrql);
|
|
}
|
|
else
|
|
{
|
|
DEVICE_POWER_STATE devicePowerState = PowerDeviceD3;
|
|
|
|
if (pdoExtension->IdleCounter)
|
|
{
|
|
PoRegisterDeviceForIdleDetection(pdoExtension->DeviceObject, 0, 0, devicePowerState);
|
|
pdoExtension->IdleCounter = NULL;
|
|
}
|
|
|
|
Irp->IoStatus.Status = status;
|
|
IoCompleteRequest(Irp,IO_NO_INCREMENT);
|
|
}
|
|
break;
|
|
|
|
case IRP_MN_QUERY_REMOVE_DEVICE:
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: PnpDeviceControl: QUERY_REMOVE_DEVICE\n"));
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
if (Fdo)
|
|
{
|
|
if (deviceExtension->PagingPathCount || deviceExtension->CrashDumpPathCount)
|
|
{
|
|
status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (pdoExtension->PagingPathCount || pdoExtension->CrashDumpPathCount)
|
|
{
|
|
status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
}
|
|
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
Irp->IoStatus.Status = status;
|
|
IoCompleteRequest(Irp,IO_NO_INCREMENT);
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: PnpDeviceControl: Failing QUERY_REMOVE: we are in PagingPath or CrashDumpPath\n"));
|
|
break;
|
|
}
|
|
|
|
//
|
|
// We're not going to queue irps during remove device
|
|
// KLUDGE
|
|
//
|
|
//
|
|
// KeAcquireSpinLock(&deviceExtension->ExtensionDataSpinLock,&cIrql);
|
|
// deviceExtension->DeviceFlags |= DEVICE_FLAG_QUERY_STOP_REMOVE;
|
|
// KeReleaseSpinLock(&deviceExtension->ExtensionDataSpinLock,cIrql);
|
|
//
|
|
|
|
if (Fdo)
|
|
{
|
|
// No need to wait for the thread to become idle
|
|
// KLUDGE
|
|
// if (deviceExtension->DeviceFlags & DEVICE_FLAG_THREAD) {
|
|
// KeWaitForSingleObject(&deviceExtension->PendingIRPEvent,
|
|
// Executive, KernelMode, FALSE, NULL);
|
|
// }
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
status = IoCallDriver(deviceExtension->LowerDeviceObject, Irp);
|
|
}
|
|
else
|
|
{
|
|
Irp->IoStatus.Status = status;
|
|
IoCompleteRequest(Irp,IO_NO_INCREMENT);
|
|
}
|
|
break;
|
|
|
|
case IRP_MN_CANCEL_STOP_DEVICE:
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: PnpDeviceControl: CANCEL_STOP_DEVICE\n"));
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
if (Fdo)
|
|
{
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
status = IoCallDriver(deviceExtension->LowerDeviceObject, Irp);
|
|
}
|
|
else
|
|
{
|
|
Irp->IoStatus.Status = status;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
}
|
|
|
|
KeAcquireSpinLock(&deviceExtension->ExtensionDataSpinLock,&cIrql);
|
|
deviceExtension->DeviceFlags &= ~DEVICE_FLAG_QUERY_STOP_REMOVE;
|
|
KeReleaseSpinLock(&deviceExtension->ExtensionDataSpinLock,cIrql);
|
|
|
|
if (!KeReadStateSemaphore(&deviceExtension->requestSemaphore))
|
|
{
|
|
KeReleaseSemaphore(&deviceExtension->requestSemaphore,(KPRIORITY) 0, 1, FALSE);
|
|
}
|
|
break;
|
|
|
|
case IRP_MN_CANCEL_REMOVE_DEVICE:
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: PnpDeviceControl: CANCEL_REMOVE_DEVICE\n"));
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
if (Fdo)
|
|
{
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
status = IoCallDriver(deviceExtension->LowerDeviceObject, Irp);
|
|
}
|
|
else
|
|
{
|
|
Irp->IoStatus.Status = status;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
}
|
|
|
|
//
|
|
// This flas was never set by QUERY_REMOVE
|
|
// due to the KLUDGE we added, for not queuing IRPS's during QUERY_REMOVE
|
|
//
|
|
// KeAcquireSpinLock(&deviceExtension->ExtensionDataSpinLock,&cIrql);
|
|
// deviceExtension->DeviceFlags &= ~DEVICE_FLAG_QUERY_STOP_REMOVE;
|
|
// KeReleaseSpinLock(&deviceExtension->ExtensionDataSpinLock,cIrql);
|
|
|
|
if (!KeReadStateSemaphore(&deviceExtension->requestSemaphore))
|
|
{
|
|
KeReleaseSemaphore(&deviceExtension->requestSemaphore,(KPRIORITY) 0, 1, FALSE);
|
|
}
|
|
break;
|
|
|
|
case IRP_MN_REMOVE_DEVICE:
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: PnpDeviceControl: REMOVE_DEVICE\n"));
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
if (Fdo)
|
|
{
|
|
if (!(deviceExtension->DeviceFlags & DEVICE_FLAG_REMOVED))
|
|
{
|
|
// Set the QUERY_STOP_REMOVE FLAG
|
|
// Part of the KLUDGE, we had removed this from the QUERY_REMOVE IRP
|
|
// processing
|
|
KeAcquireSpinLock(&deviceExtension->ExtensionDataSpinLock,&cIrql);
|
|
deviceExtension->DeviceFlags |= DEVICE_FLAG_QUERY_STOP_REMOVE;
|
|
KeReleaseSpinLock(&deviceExtension->ExtensionDataSpinLock,cIrql);
|
|
|
|
// Now wait for the thread to complete any work its doing
|
|
// Better wait for the thread to complete the current IRP it may be
|
|
// working on
|
|
//
|
|
// if (deviceExtension->DeviceFlags & DEVICE_FLAG_THREAD) {
|
|
//
|
|
if (deviceExtension->TffsportThreadObject)
|
|
{
|
|
KeWaitForSingleObject(&deviceExtension->PendingIRPEvent, Executive, KernelMode, FALSE, NULL);
|
|
}
|
|
|
|
KeAcquireSpinLock(&deviceExtension->ExtensionDataSpinLock,&cIrql);
|
|
deviceExtension->DeviceFlags |= DEVICE_FLAG_REMOVED;
|
|
deviceExtension->DeviceFlags &= ~DEVICE_FLAG_QUERY_STOP_REMOVE;
|
|
deviceExtension->DeviceFlags &= ~DEVICE_FLAG_HOLD_IRPS;
|
|
KeReleaseSpinLock(&deviceExtension->ExtensionDataSpinLock,cIrql);
|
|
|
|
while (ExInterlockedRemoveHeadList(&deviceExtension->listEntry, &deviceExtension->listSpinLock))
|
|
{
|
|
;
|
|
}
|
|
|
|
KeAcquireSpinLock(&deviceExtension->ExtensionDataSpinLock,&cIrql);
|
|
deviceExtension->threadReferenceCount = 0;
|
|
KeReleaseSpinLock(&deviceExtension->ExtensionDataSpinLock,cIrql);
|
|
|
|
if (!KeReadStateSemaphore(&deviceExtension->requestSemaphore))
|
|
{
|
|
KeReleaseSemaphore(&deviceExtension->requestSemaphore,(KPRIORITY) 0,1,FALSE);
|
|
}
|
|
|
|
//
|
|
// if (deviceExtension->DeviceFlags & DEVICE_FLAG_THREAD) {
|
|
//
|
|
if (deviceExtension->TffsportThreadObject)
|
|
{
|
|
KeWaitForSingleObject(deviceExtension->TffsportThreadObject, Executive, KernelMode, FALSE, NULL);
|
|
ObDereferenceObject(deviceExtension->TffsportThreadObject);
|
|
deviceExtension->TffsportThreadObject = NULL;
|
|
}
|
|
|
|
TrueffsStopRemoveDevice(deviceExtension);
|
|
}
|
|
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
status = IoCallDriver(deviceExtension->LowerDeviceObject, Irp);
|
|
|
|
//
|
|
// Clean up resources here
|
|
//
|
|
if (deviceExtension->ChildPdo != NULL)
|
|
{
|
|
IoDeleteDevice(deviceExtension->ChildPdo);
|
|
}
|
|
|
|
TrueffsDeleteSymblicLinks(deviceExtension);
|
|
IoDetachDevice(deviceExtension->LowerDeviceObject);
|
|
IoDeleteDevice(DeviceObject);
|
|
}
|
|
else
|
|
{
|
|
if (!(deviceExtension->DeviceFlags & DEVICE_FLAG_CHILD_REMOVED))
|
|
{
|
|
DEVICE_POWER_STATE devicePowerState;
|
|
|
|
KeAcquireSpinLock(&deviceExtension->ExtensionDataSpinLock,&cIrql);
|
|
deviceExtension->DeviceFlags |= DEVICE_FLAG_CHILD_REMOVED;
|
|
deviceExtension->DeviceFlags &= ~DEVICE_FLAG_QUERY_STOP_REMOVE;
|
|
deviceExtension->DeviceFlags &= ~DEVICE_FLAG_HOLD_IRPS;
|
|
KeReleaseSpinLock(&deviceExtension->ExtensionDataSpinLock,cIrql);
|
|
|
|
while (ExInterlockedRemoveHeadList(&deviceExtension->listEntry, &deviceExtension->listSpinLock))
|
|
{
|
|
;
|
|
}
|
|
|
|
devicePowerState = PowerDeviceD3;
|
|
|
|
if (pdoExtension->IdleCounter)
|
|
{
|
|
PoRegisterDeviceForIdleDetection(pdoExtension->DeviceObject, 0, 0, devicePowerState);
|
|
pdoExtension->IdleCounter = NULL;
|
|
}
|
|
|
|
TrueffsWmiDeregister((PDEVICE_EXTENSION_HEADER)pdoExtension);
|
|
}
|
|
|
|
Irp->IoStatus.Status = status;
|
|
IoCompleteRequest(Irp,IO_NO_INCREMENT);
|
|
}
|
|
break;
|
|
|
|
case IRP_MN_SURPRISE_REMOVAL:
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: PnpDeviceControl: SURPRISE_REMOVAL\n"));
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
if (Fdo)
|
|
{
|
|
KeAcquireSpinLock(&deviceExtension->ExtensionDataSpinLock,&cIrql);
|
|
deviceExtension->DeviceFlags |= DEVICE_FLAG_REMOVED;
|
|
deviceExtension->DeviceFlags &= ~DEVICE_FLAG_QUERY_STOP_REMOVE;
|
|
deviceExtension->DeviceFlags &= ~DEVICE_FLAG_HOLD_IRPS;
|
|
KeReleaseSpinLock(&deviceExtension->ExtensionDataSpinLock,cIrql);
|
|
|
|
while (ExInterlockedRemoveHeadList(&deviceExtension->listEntry,&deviceExtension->listSpinLock))
|
|
{
|
|
;
|
|
}
|
|
|
|
KeAcquireSpinLock(&deviceExtension->ExtensionDataSpinLock,&cIrql);
|
|
deviceExtension->threadReferenceCount = 0;
|
|
KeReleaseSpinLock(&deviceExtension->ExtensionDataSpinLock,cIrql);
|
|
|
|
if (!KeReadStateSemaphore(&deviceExtension->requestSemaphore))
|
|
{
|
|
KeReleaseSemaphore(&deviceExtension->requestSemaphore,(KPRIORITY) 0, 1, FALSE);
|
|
}
|
|
|
|
//
|
|
// if (deviceExtension->DeviceFlags & DEVICE_FLAG_THREAD) {
|
|
//
|
|
if (deviceExtension->TffsportThreadObject)
|
|
{
|
|
KeWaitForSingleObject(deviceExtension->TffsportThreadObject, Executive, KernelMode, FALSE, NULL);
|
|
ObDereferenceObject(deviceExtension->TffsportThreadObject);
|
|
deviceExtension->TffsportThreadObject = NULL;
|
|
}
|
|
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
status = IoCallDriver(deviceExtension->LowerDeviceObject, Irp);
|
|
|
|
TrueffsStopRemoveDevice(deviceExtension);
|
|
TrueffsDeleteSymblicLinks(deviceExtension);
|
|
}
|
|
else
|
|
{
|
|
DEVICE_POWER_STATE devicePowerState;
|
|
|
|
IoInvalidateDeviceRelations(deviceExtension->MainPdo,BusRelations);
|
|
|
|
KeAcquireSpinLock(&deviceExtension->ExtensionDataSpinLock,&cIrql);
|
|
deviceExtension->DeviceFlags |= DEVICE_FLAG_CHILD_REMOVED;
|
|
KeReleaseSpinLock(&deviceExtension->ExtensionDataSpinLock,cIrql);
|
|
|
|
devicePowerState = PowerDeviceD3;
|
|
|
|
if (pdoExtension->IdleCounter)
|
|
{
|
|
PoRegisterDeviceForIdleDetection(pdoExtension->DeviceObject, 0, 0, devicePowerState);
|
|
pdoExtension->IdleCounter = NULL;
|
|
}
|
|
|
|
TrueffsWmiDeregister((PDEVICE_EXTENSION_HEADER)pdoExtension);
|
|
|
|
Irp->IoStatus.Status = status;
|
|
IoCompleteRequest(Irp,IO_NO_INCREMENT);
|
|
}
|
|
break;
|
|
|
|
case IRP_MN_QUERY_ID:
|
|
|
|
status = TrueffsDeviceQueryId(DeviceObject, Irp, Fdo);
|
|
break;
|
|
|
|
case IRP_MN_QUERY_DEVICE_RELATIONS:
|
|
|
|
status = TrueffsQueryDeviceRelations(DeviceObject, Irp, Fdo);
|
|
break;
|
|
|
|
case IRP_MN_QUERY_CAPABILITIES:
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: PnpDeviceControl: QUERY_CAPABILITIES\n"));
|
|
|
|
if (Fdo)
|
|
{
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
status = IoCallDriver(deviceExtension->LowerDeviceObject, Irp);
|
|
}
|
|
else
|
|
{
|
|
status = TrueffsDeviceQueryCapabilities(deviceExtension, irpStack->Parameters.DeviceCapabilities.Capabilities);
|
|
|
|
Irp->IoStatus.Status = status;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
}
|
|
break;
|
|
|
|
case IRP_MN_DEVICE_USAGE_NOTIFICATION:
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: PnpDeviceControl: DEVICE_USAGE_NOTIFICATION, Type %Xh\n", irpStack->Parameters.UsageNotification.Type));
|
|
|
|
if (Fdo)
|
|
{
|
|
PULONG deviceUsageCount = NULL;
|
|
|
|
if (!(deviceExtension->DeviceFlags & DEVICE_FLAG_STARTED))
|
|
{
|
|
status = STATUS_DEVICE_NOT_READY;
|
|
|
|
Irp->IoStatus.Status = status;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
break;
|
|
}
|
|
|
|
switch (irpStack->Parameters.UsageNotification.Type)
|
|
{
|
|
case DeviceUsageTypePaging:
|
|
deviceUsageCount = &deviceExtension->PagingPathCount;
|
|
break;
|
|
|
|
case DeviceUsageTypeHibernation:
|
|
deviceUsageCount = &deviceExtension->HiberPathCount;
|
|
break;
|
|
|
|
case DeviceUsageTypeDumpFile:
|
|
deviceUsageCount = &deviceExtension->CrashDumpPathCount;
|
|
break;
|
|
|
|
default:
|
|
deviceUsageCount = NULL;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Forward this request down synchronously, in case a lower driver wants to veto it
|
|
//
|
|
IoCopyCurrentIrpStackLocationToNext(Irp);
|
|
status = TrueffsCallDriverSync(deviceExtension->LowerDeviceObject, Irp);
|
|
|
|
if (NT_SUCCESS(status))
|
|
{
|
|
if (deviceUsageCount)
|
|
{
|
|
IoAdjustPagingPathCount(deviceUsageCount, irpStack->Parameters.UsageNotification.InPath);
|
|
}
|
|
}
|
|
|
|
Irp->IoStatus.Status = status;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
}
|
|
else
|
|
{
|
|
PULONG deviceUsageCount = NULL;
|
|
|
|
if (pdoExtension)
|
|
{
|
|
PDEVICE_OBJECT targetDeviceObject;
|
|
IO_STATUS_BLOCK ioStatus = { 0 };
|
|
|
|
switch (irpStack->Parameters.UsageNotification.Type)
|
|
{
|
|
case DeviceUsageTypePaging:
|
|
deviceUsageCount = &pdoExtension->PagingPathCount;
|
|
break;
|
|
|
|
case DeviceUsageTypeHibernation:
|
|
deviceUsageCount = &pdoExtension->HiberPathCount;
|
|
break;
|
|
|
|
case DeviceUsageTypeDumpFile:
|
|
deviceUsageCount = &pdoExtension->CrashDumpPathCount;
|
|
break;
|
|
|
|
default:
|
|
deviceUsageCount = NULL;
|
|
break;
|
|
}
|
|
|
|
targetDeviceObject = IoGetAttachedDeviceReference(deviceExtension->DeviceObject);
|
|
|
|
ioStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
|
|
status = TrueffsSyncSendIrp(targetDeviceObject, irpStack, &ioStatus);
|
|
|
|
ObDereferenceObject(targetDeviceObject);
|
|
|
|
if (NT_SUCCESS(status))
|
|
{
|
|
if (deviceUsageCount)
|
|
{
|
|
IoAdjustPagingPathCount(deviceUsageCount, irpStack->Parameters.UsageNotification.InPath);
|
|
}
|
|
|
|
if (irpStack->Parameters.UsageNotification.Type == DeviceUsageTypeDumpFile)
|
|
{
|
|
|
|
POWER_STATE powerState;
|
|
DEVICE_POWER_STATE devicePowerState = PowerDeviceD3;
|
|
|
|
//
|
|
// Reset the idle timeout to "forever"
|
|
//
|
|
pdoExtension->IdleCounter = PoRegisterDeviceForIdleDetection(pdoExtension->DeviceObject,
|
|
DEVICE_VERY_LONG_IDLE_TIMEOUT,
|
|
DEVICE_VERY_LONG_IDLE_TIMEOUT,
|
|
devicePowerState);
|
|
if (pdoExtension->IdleCounter)
|
|
{
|
|
PoSetDeviceBusy(pdoExtension->IdleCounter);
|
|
}
|
|
|
|
powerState.DeviceState = PowerDeviceD0;
|
|
|
|
PoRequestPowerIrp(pdoExtension->DeviceObject, IRP_MN_SET_POWER, powerState, NULL, NULL, NULL);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
status = STATUS_NO_SUCH_DEVICE;
|
|
}
|
|
|
|
Irp->IoStatus.Status = status;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
|
|
if (Fdo)
|
|
{
|
|
//
|
|
// Forward this request down, in case a lower driver understands it
|
|
//
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
status = IoCallDriver(deviceExtension->LowerDeviceObject, Irp);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Complete this request without altering its status
|
|
//
|
|
status = Irp->IoStatus.Status;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
}
|
|
break;
|
|
}
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: PnpDeviceControl status %Xh\n", status));
|
|
return status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
TrueffsSyncSendIrp (
|
|
IN PDEVICE_OBJECT TargetDeviceObject,
|
|
IN PIO_STACK_LOCATION IrpSp,
|
|
IN OUT OPTIONAL PIO_STATUS_BLOCK IoStatus
|
|
)
|
|
{
|
|
PIO_STACK_LOCATION newIrpSp;
|
|
PIRP newIrp;
|
|
KEVENT event;
|
|
NTSTATUS status;
|
|
|
|
newIrp = IoAllocateIrp (TargetDeviceObject->StackSize, FALSE);
|
|
if (newIrp == NULL) {
|
|
TffsDebugPrint((TFFS_DEB_ERROR,"Trueffs: SyncSendIrp: Unable to allocate an irp\n"));
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
newIrpSp = IoGetNextIrpStackLocation(newIrp);
|
|
RtlMoveMemory (newIrpSp, IrpSp, sizeof (*IrpSp));
|
|
|
|
if (IoStatus) {
|
|
newIrp->IoStatus.Status = IoStatus->Status;
|
|
} else {
|
|
newIrp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
|
|
}
|
|
|
|
KeInitializeEvent(&event, NotificationEvent, FALSE);
|
|
IoSetCompletionRoutine (
|
|
newIrp,
|
|
TrueffsSyncSendIrpCompletionRoutine,
|
|
&event,
|
|
TRUE,
|
|
TRUE,
|
|
TRUE);
|
|
status = IoCallDriver (TargetDeviceObject, newIrp);
|
|
if (status == STATUS_PENDING) {
|
|
|
|
status = KeWaitForSingleObject(&event,
|
|
Executive,
|
|
KernelMode,
|
|
FALSE,
|
|
NULL);
|
|
}
|
|
status = newIrp->IoStatus.Status;
|
|
if (IoStatus) {
|
|
*IoStatus = newIrp->IoStatus;
|
|
}
|
|
IoFreeIrp (newIrp);
|
|
return status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
TrueffsSyncSendIrpCompletionRoutine (
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN PVOID Context
|
|
)
|
|
{
|
|
PKEVENT event = Context;
|
|
KeSetEvent(event, EVENT_INCREMENT,FALSE);
|
|
return STATUS_MORE_PROCESSING_REQUIRED;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
TrueffsCallDriverSync(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN OUT PIRP Irp
|
|
)
|
|
{
|
|
KEVENT event;
|
|
NTSTATUS status;
|
|
|
|
PAGED_CODE();
|
|
|
|
KeInitializeEvent(&event, NotificationEvent, FALSE);
|
|
|
|
IoSetCompletionRoutine(Irp, TrueffsCallDriverSyncCompletion, &event, TRUE, TRUE, TRUE);
|
|
|
|
status = IoCallDriver(DeviceObject, Irp);
|
|
|
|
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
|
|
|
|
status = Irp->IoStatus.Status;
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
TrueffsCallDriverSyncCompletion(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN PVOID Context
|
|
)
|
|
{
|
|
PKEVENT event = (PKEVENT)Context;
|
|
|
|
ASSERT(Irp->IoStatus.Status != STATUS_IO_TIMEOUT);
|
|
|
|
KeSetEvent(event, 0, FALSE);
|
|
return STATUS_MORE_PROCESSING_REQUIRED;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
TrueffsPowerControl(
|
|
PDEVICE_OBJECT DeviceObject,
|
|
PIRP Irp
|
|
)
|
|
{
|
|
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
|
|
PDEVICE_EXTENSION deviceExtension;
|
|
PDEVICE_EXTENSION_HEADER devExtension;
|
|
BOOLEAN Fdo = FALSE;
|
|
NTSTATUS status;
|
|
|
|
devExtension = (PDEVICE_EXTENSION_HEADER) DeviceObject->DeviceExtension;
|
|
|
|
if (IS_FDO(devExtension))
|
|
{
|
|
deviceExtension = DeviceObject->DeviceExtension;
|
|
Fdo = TRUE;
|
|
}
|
|
else
|
|
{
|
|
PPDO_EXTENSION pdoExtension = DeviceObject->DeviceExtension;
|
|
deviceExtension = pdoExtension->Pext;
|
|
}
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: PowerControl: Function %Xh %cDO.\n", irpStack->MinorFunction,Fdo ? 'F':'P'));
|
|
|
|
switch (irpStack->MinorFunction)
|
|
{
|
|
|
|
case IRP_MN_SET_POWER:
|
|
|
|
if (Fdo)
|
|
{
|
|
status = TrueffsSetFdoPowerState(DeviceObject, Irp);
|
|
}
|
|
else
|
|
{
|
|
status = TrueffsSetPdoPowerState(DeviceObject, Irp);
|
|
}
|
|
break;
|
|
|
|
case IRP_MN_QUERY_POWER:
|
|
|
|
status = STATUS_SUCCESS;
|
|
PoStartNextPowerIrp(Irp);
|
|
|
|
if (Fdo)
|
|
{
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
status = PoCallDriver(deviceExtension->LowerDeviceObject, Irp);
|
|
}
|
|
else
|
|
{
|
|
Irp->IoStatus.Status = status;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
|
|
PoStartNextPowerIrp(Irp);
|
|
|
|
if (Fdo)
|
|
{
|
|
//
|
|
// Forward this request down, in case a lower driver understands it
|
|
//
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
status = PoCallDriver(deviceExtension->LowerDeviceObject, Irp);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Complete this request without altering its status
|
|
//
|
|
status = Irp->IoStatus.Status;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
}
|
|
break;
|
|
}
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: PowerControl status %Xh\n", status));
|
|
return status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
TrueffsSetFdoPowerState (
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN OUT PIRP Irp
|
|
)
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Dispatches the IRP based on whether a system power state
|
|
or device power state transition is requested
|
|
|
|
Arguments
|
|
|
|
DeviceObject - Pointer to the functional device object for the pcmcia controller
|
|
Irp - Pointer to the Irp for the power dispatch
|
|
|
|
Return value
|
|
|
|
status
|
|
|
|
--*/
|
|
{
|
|
PDEVICE_EXTENSION fdoExtension;
|
|
PIO_STACK_LOCATION irpStack;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
PFDO_POWER_CONTEXT context = NULL;
|
|
BOOLEAN passItDown;
|
|
|
|
fdoExtension = DeviceObject->DeviceExtension;
|
|
|
|
context = ExAllocatePoolWithTag (NonPagedPool, sizeof(FDO_POWER_CONTEXT), TFFSPORT_POOL_TAG);
|
|
if (context == NULL) {
|
|
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
} else {
|
|
|
|
RtlZeroMemory (context, sizeof(FDO_POWER_CONTEXT));
|
|
irpStack = IoGetCurrentIrpStackLocation (Irp);
|
|
|
|
passItDown = TRUE;
|
|
context->PowerType = irpStack->Parameters.Power.Type;
|
|
context->PowerState = irpStack->Parameters.Power.State;
|
|
|
|
if (irpStack->Parameters.Power.Type == SystemPowerState) {
|
|
|
|
if (fdoExtension->SystemPowerState == irpStack->Parameters.Power.State.SystemState) {
|
|
|
|
// We are already in the given state
|
|
passItDown = FALSE;
|
|
}
|
|
|
|
} else if (irpStack->Parameters.Power.Type == DevicePowerState) {
|
|
|
|
if (fdoExtension->DevicePowerState != irpStack->Parameters.Power.State.DeviceState) {
|
|
|
|
if (fdoExtension->DevicePowerState == PowerDeviceD0) {
|
|
|
|
// getting out of D0 state, better call PoSetPowerState now
|
|
PoSetPowerState (
|
|
DeviceObject,
|
|
DevicePowerState,
|
|
irpStack->Parameters.Power.State
|
|
);
|
|
}
|
|
|
|
} else {
|
|
|
|
// We are already in the given state
|
|
passItDown = FALSE;
|
|
}
|
|
} else {
|
|
|
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
|
}
|
|
}
|
|
|
|
if (NT_SUCCESS(status) && passItDown) {
|
|
|
|
if ((irpStack->Parameters.Power.Type == DevicePowerState) &&
|
|
(irpStack->Parameters.Power.State.DeviceState == PowerDeviceD3)) {
|
|
|
|
// Getting out of D0 - cancel the timer
|
|
if (timerWasStarted) {
|
|
KeCancelTimer(&timerObject);
|
|
timerWasStarted = FALSE;
|
|
}
|
|
}
|
|
|
|
if (irpStack->Parameters.Power.Type == SystemPowerState) {
|
|
|
|
//
|
|
// When we get a System Power IRP (S IRP) the correct thing to do
|
|
// is to request a D, and pass the S IRP as context to the D IRP
|
|
// completion routine. Once the D IRP completes we can pass
|
|
// down the S IRP
|
|
//
|
|
|
|
POWER_STATE powerState;
|
|
|
|
// Switch to the appropriate device power state
|
|
if (context->PowerState.SystemState == PowerSystemWorking) {
|
|
|
|
powerState.DeviceState = PowerDeviceD0;
|
|
|
|
} else {
|
|
|
|
// We don't need to take special care of leaving the device
|
|
// in powered state in case of hibernation, because it cannot
|
|
// be switched off. Since the device is always on it is enough
|
|
// to send PowerDeviceD3 thus simulating power off.
|
|
|
|
powerState.DeviceState = PowerDeviceD3;
|
|
}
|
|
|
|
// Transitioned to system state
|
|
fdoExtension->SystemPowerState = context->PowerState.SystemState;
|
|
|
|
// Request the IRP for D Power
|
|
status = PoRequestPowerIrp (
|
|
DeviceObject,
|
|
IRP_MN_SET_POWER,
|
|
powerState,
|
|
TrueffsFdoDevicePowerIrpCompletionRoutine,
|
|
Irp,
|
|
NULL
|
|
);
|
|
|
|
if (NT_SUCCESS(status)) {
|
|
status = STATUS_PENDING;
|
|
}
|
|
|
|
// In this case we should free the context pool because it wont
|
|
// reach the completion callback routine
|
|
ExFreePool(context);
|
|
|
|
|
|
} else {
|
|
|
|
//
|
|
// Its a D irp, we just want to pass down (device power)
|
|
//
|
|
// Send the IRP to the pdo
|
|
IoCopyCurrentIrpStackLocationToNext (Irp);
|
|
|
|
IoSetCompletionRoutine(Irp,
|
|
TrueffsFdoPowerCompletionRoutine,
|
|
context,
|
|
TRUE,
|
|
TRUE,
|
|
TRUE);
|
|
|
|
status = PoCallDriver(fdoExtension->LowerDeviceObject, Irp);
|
|
|
|
}
|
|
|
|
return (status);
|
|
|
|
|
|
} else {
|
|
|
|
// Unblock the power IRPs and complete the current IRP
|
|
Irp->IoStatus.Information = 0;
|
|
Irp->IoStatus.Status = status;
|
|
PoStartNextPowerIrp (Irp);
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
if (context) {
|
|
ExFreePool (context);
|
|
}
|
|
return status;
|
|
}
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
TrueffsFdoDevicePowerIrpCompletionRoutine(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN UCHAR MinorFunction,
|
|
IN POWER_STATE PowerState,
|
|
IN PVOID contextIrp,
|
|
IN PIO_STATUS_BLOCK IoStatus
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Completion routine for Device Power IRPS. The context will be the S power IRP
|
|
that was received, and we can now send down the stack
|
|
|
|
Parameters
|
|
|
|
DeviceObject - Pointer to FDO for the controller
|
|
Irp - Pointer to the D power irp which is completing
|
|
context - Pointer to the S power irp that can now be sent down the stack
|
|
|
|
--*/
|
|
{
|
|
PIRP systemPowerIrp = (PIRP) contextIrp;
|
|
PDEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
|
|
NTSTATUS status;
|
|
PFDO_POWER_CONTEXT context = NULL;
|
|
PIO_STACK_LOCATION irpStack = NULL;
|
|
|
|
if (!NT_SUCCESS(IoStatus->Status)) {
|
|
// The D IRP is not allowed to fail
|
|
ASSERT(0);
|
|
}
|
|
|
|
//
|
|
// Allocate space for the context of the S IRP completion routine
|
|
//
|
|
context = ExAllocatePoolWithTag (NonPagedPool, sizeof(FDO_POWER_CONTEXT), TFFSPORT_POOL_TAG);
|
|
if (context == NULL) {
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
// Unblock the power IRPs and complete the current IRP
|
|
systemPowerIrp->IoStatus.Information = 0;
|
|
systemPowerIrp->IoStatus.Status = status;
|
|
PoStartNextPowerIrp (systemPowerIrp);
|
|
IoCompleteRequest(systemPowerIrp, IO_NO_INCREMENT);
|
|
|
|
} else {
|
|
|
|
// Clear the memory we just allocated
|
|
RtlZeroMemory (context, sizeof(FDO_POWER_CONTEXT));
|
|
|
|
// Get current IRP Stack for S-IRP
|
|
irpStack = IoGetCurrentIrpStackLocation (systemPowerIrp);
|
|
ASSERT(irpStack);
|
|
|
|
context->PowerType = irpStack->Parameters.Power.Type;
|
|
context->PowerState = irpStack->Parameters.Power.State;
|
|
|
|
// The D IRP has completed, now we can send the S IRP down
|
|
IoCopyCurrentIrpStackLocationToNext (systemPowerIrp);
|
|
IoSetCompletionRoutine(systemPowerIrp,
|
|
TrueffsFdoPowerCompletionRoutine,
|
|
context,
|
|
TRUE,
|
|
TRUE,
|
|
TRUE);
|
|
|
|
status = PoCallDriver(fdoExtension->LowerDeviceObject, systemPowerIrp);
|
|
}
|
|
|
|
return (status);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
TrueffsFdoPowerCompletionRoutine (
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN PVOID Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Completion routine for the power IRP sent down to the PDO for the
|
|
controller. If we are getting out of a working system state,
|
|
requests a power IRP to put the device in an appropriate device power state.
|
|
|
|
Parameters
|
|
|
|
DeviceObject - Pointer to FDO for the controller
|
|
Irp - Pointer to the IRP for the power request
|
|
Context - Pointer to the FDO_POWER_CONTEXT which is
|
|
filled in when the IRP is passed down
|
|
Return Value
|
|
|
|
Status
|
|
|
|
--*/
|
|
{
|
|
PFDO_POWER_CONTEXT context = Context;
|
|
BOOLEAN callPoSetPowerState;
|
|
PDEVICE_EXTENSION fdoExtension;
|
|
|
|
fdoExtension = DeviceObject->DeviceExtension;
|
|
|
|
if ((NT_SUCCESS(Irp->IoStatus.Status))) {
|
|
|
|
callPoSetPowerState = TRUE;
|
|
|
|
if (context->PowerType == SystemPowerState) {
|
|
// Do Nothing
|
|
|
|
} else if (context->PowerType == DevicePowerState) {
|
|
|
|
if (fdoExtension->DevicePowerState == PowerDeviceD0) {
|
|
|
|
// PoSetPowerState is called before we get out of D0
|
|
callPoSetPowerState = FALSE;
|
|
|
|
}
|
|
else if (context->PowerState.DeviceState == PowerDeviceD0) {
|
|
|
|
// Getting back to D0, set the timer on
|
|
startIntervalTimer();
|
|
|
|
}
|
|
fdoExtension->DevicePowerState = context->PowerState.DeviceState;
|
|
} else {
|
|
// How did we not get either a SystemPowerState or a DevicePowerState
|
|
ASSERT(0);
|
|
}
|
|
|
|
if (callPoSetPowerState) {
|
|
|
|
PoSetPowerState (
|
|
DeviceObject,
|
|
context->PowerType,
|
|
context->PowerState
|
|
);
|
|
}
|
|
|
|
}
|
|
ExFreePool(Context);
|
|
|
|
PoStartNextPowerIrp (Irp);
|
|
return Irp->IoStatus.Status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
TrueffsSetPdoDevicePowerState( IN PDEVICE_OBJECT Pdo,
|
|
IN OUT PIRP Irp
|
|
)
|
|
{
|
|
PPDO_EXTENSION pdoExtension = Pdo->DeviceExtension;
|
|
PDEVICE_EXTENSION deviceExtension;
|
|
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
|
|
DEVICE_POWER_STATE newDevicePowerState;
|
|
NTSTATUS status;
|
|
BOOLEAN setPowerRequest, powerUp, powerUpParent;
|
|
KIRQL cIrql;
|
|
|
|
status = STATUS_SUCCESS;
|
|
newDevicePowerState = irpStack->Parameters.Power.State.DeviceState;
|
|
|
|
deviceExtension = pdoExtension->Pext;
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: Transition to device power state: %d\n", newDevicePowerState));
|
|
|
|
setPowerRequest = FALSE;
|
|
powerUp = FALSE;
|
|
powerUpParent=FALSE;
|
|
|
|
if (pdoExtension->DevicePowerState == newDevicePowerState) {
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
if (pdoExtension->DevicePowerState == PowerDeviceD0) {
|
|
|
|
// Getting out of D0 - Call PoSetPowerState first
|
|
POWER_STATE newPowerState;
|
|
|
|
newPowerState.DeviceState = newDevicePowerState;
|
|
PoSetPowerState(Pdo,
|
|
DevicePowerState,
|
|
newPowerState);
|
|
}
|
|
|
|
if (newDevicePowerState == PowerDeviceD0 ||
|
|
newDevicePowerState == PowerDeviceD1 ||
|
|
newDevicePowerState == PowerDeviceD2) {
|
|
|
|
if (pdoExtension->DevicePowerState == PowerDeviceD3) {
|
|
// D3 --> D0, D1 or D2 .. Wake up
|
|
powerUpParent = TRUE;
|
|
setPowerRequest = TRUE;
|
|
powerUp = TRUE;
|
|
}
|
|
}
|
|
else { /* newDevicePowerState == D3 */
|
|
if (pdoExtension->DevicePowerState != PowerDeviceD3) {
|
|
// We need to power down now.
|
|
setPowerRequest=TRUE;
|
|
}
|
|
}
|
|
|
|
if (setPowerRequest && NT_SUCCESS(status)) {
|
|
// Parent might have to be powered up..
|
|
if (powerUpParent) {
|
|
status = TrueffsFdoChildRequestPowerUp(pdoExtension->Pext,
|
|
pdoExtension,
|
|
Irp);
|
|
} else {
|
|
|
|
if (powerUp) {
|
|
/* MDOC PLUS */
|
|
/*
|
|
DOC2window *memWinPtr;
|
|
memWinPtr = (DOC2window *) pdoExtension->Pext->pcmciaParams.windowBase;
|
|
tffsWriteByte(memWinPtr->DOCcontrol, ASIC_RESET_MODE);
|
|
tffsWriteByte(memWinPtr->DOCcontrol, ASIC_RESET_MODE);
|
|
tffsWriteByte(memWinPtr->DOCcontrol, ASIC_NORMAL_MODE);
|
|
tffsWriteByte(memWinPtr->DOCcontrol, ASIC_NORMAL_MODE);
|
|
*/
|
|
|
|
MDOCPwindow *memWinPtr;
|
|
memWinPtr = (MDOCPwindow *) pdoExtension->Pext->pcmciaParams.windowBase;
|
|
tffsWriteByte(memWinPtr->DOCcontrol, (unsigned char)0x04);
|
|
tffsWriteByte(memWinPtr->DocCntConfirmReg, (unsigned char)0xfb);
|
|
tffsWriteByte(memWinPtr->DOCcontrol, (unsigned char)0x05);
|
|
tffsWriteByte(memWinPtr->DocCntConfirmReg, (unsigned char)0xfa);
|
|
|
|
|
|
KeAcquireSpinLock(&pdoExtension->Pext->ExtensionDataSpinLock,&cIrql);
|
|
pdoExtension->Pext->DeviceFlags &= ~DEVICE_FLAG_HOLD_IRPS;
|
|
KeReleaseSpinLock(&pdoExtension->Pext->ExtensionDataSpinLock,cIrql);
|
|
if (!KeReadStateSemaphore(&pdoExtension->Pext->requestSemaphore)) {
|
|
KeReleaseSemaphore(&pdoExtension->Pext->requestSemaphore,(KPRIORITY) 0,1,FALSE);
|
|
}
|
|
} else {
|
|
|
|
KeAcquireSpinLock(&pdoExtension->Pext->ExtensionDataSpinLock,&cIrql);
|
|
pdoExtension->Pext->DeviceFlags |= DEVICE_FLAG_HOLD_IRPS;
|
|
KeReleaseSpinLock(&pdoExtension->Pext->ExtensionDataSpinLock,cIrql);
|
|
|
|
//
|
|
// if (pdoExtension->Pext->DeviceFlags & DEVICE_FLAG_THREAD) {
|
|
//
|
|
if (deviceExtension->TffsportThreadObject) {
|
|
KeWaitForSingleObject(&pdoExtension->Pext->PendingIRPEvent, Executive, KernelMode, FALSE, NULL);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
TrueffsSetPdoSystemPowerState (
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN OUT PIRP Irp
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
PIO_STACK_LOCATION irpStack;
|
|
PPDO_EXTENSION pdoExtension;
|
|
SYSTEM_POWER_STATE newSystemState;
|
|
POWER_STATE powerState;
|
|
|
|
pdoExtension = DeviceObject->DeviceExtension;
|
|
status = STATUS_SUCCESS;
|
|
|
|
irpStack = IoGetCurrentIrpStackLocation (Irp);
|
|
newSystemState = irpStack->Parameters.Power.State.SystemState;
|
|
|
|
if (pdoExtension->SystemPowerState != newSystemState) {
|
|
if (pdoExtension->SystemPowerState == PowerSystemWorking) {
|
|
|
|
// Getting out of working state.
|
|
if ((newSystemState == PowerSystemHibernate) &&
|
|
pdoExtension->HiberPathCount) {
|
|
|
|
// spin up for the hiber dump driver
|
|
powerState.DeviceState = PowerDeviceD0;
|
|
|
|
} else {
|
|
|
|
// put the device to D3
|
|
// Issue a D3 to top of my drive stack
|
|
powerState.DeviceState = PowerDeviceD3;
|
|
}
|
|
status = PoRequestPowerIrp (
|
|
DeviceObject,
|
|
IRP_MN_SET_POWER,
|
|
powerState,
|
|
TrueffsPdoRequestPowerCompletionRoutine,
|
|
Irp,
|
|
NULL
|
|
);
|
|
|
|
if (NT_SUCCESS(status)) {
|
|
|
|
status = STATUS_PENDING;
|
|
}
|
|
} else {
|
|
if (newSystemState == PowerSystemWorking) {
|
|
powerState.DeviceState = PowerDeviceD0;
|
|
} else {
|
|
powerState.DeviceState = PowerDeviceD3;
|
|
}
|
|
|
|
status = PoRequestPowerIrp (
|
|
DeviceObject,
|
|
IRP_MN_SET_POWER,
|
|
powerState,
|
|
TrueffsPdoRequestPowerCompletionRoutine,
|
|
Irp,
|
|
NULL
|
|
);
|
|
|
|
if (NT_SUCCESS(status)) {
|
|
status = STATUS_PENDING;
|
|
}
|
|
}
|
|
}
|
|
return status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
TrueffsSetPdoPowerState(
|
|
IN PDEVICE_OBJECT Pdo,
|
|
IN OUT PIRP Irp
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
IoMarkIrpPending(Irp);
|
|
|
|
if (irpStack->Parameters.Power.Type == DevicePowerState) {
|
|
status = TrueffsSetPdoDevicePowerState(Pdo, Irp);
|
|
} else if (irpStack->Parameters.Power.Type == SystemPowerState) {
|
|
status = TrueffsSetPdoSystemPowerState(Pdo, Irp);
|
|
} else {
|
|
status = STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
if (status != STATUS_PENDING) {
|
|
Irp->IoStatus.Status = status;
|
|
TrueffsPdoCompletePowerIrp(Pdo, Irp);
|
|
}
|
|
return status;
|
|
}
|
|
|
|
|
|
VOID
|
|
TrueffsPdoCompletePowerIrp (
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
{
|
|
PPDO_EXTENSION pdoExtension;
|
|
PDEVICE_EXTENSION fdoExtension;
|
|
PIO_STACK_LOCATION irpStack;
|
|
BOOLEAN callPoSetPowerState;
|
|
|
|
irpStack = IoGetCurrentIrpStackLocation (Irp);
|
|
pdoExtension = DeviceObject->DeviceExtension;
|
|
fdoExtension = pdoExtension->Pext;
|
|
|
|
if (NT_SUCCESS(Irp->IoStatus.Status)) {
|
|
|
|
callPoSetPowerState = TRUE;
|
|
|
|
Irp->IoStatus.Information = irpStack->Parameters.Power.State.DeviceState;
|
|
|
|
if (irpStack->Parameters.Power.Type == SystemPowerState) {
|
|
|
|
if (pdoExtension->SystemPowerState != irpStack->Parameters.Power.State.SystemState) {
|
|
|
|
pdoExtension->SystemPowerState = Irp->IoStatus.Information;
|
|
}
|
|
|
|
} else { /* if (irpStack->Parameters.Power.Type == DevicePowerState) */
|
|
|
|
if (pdoExtension->DevicePowerState == PowerDeviceD0) {
|
|
|
|
// PoSetPowerState is called before we power down
|
|
callPoSetPowerState = FALSE;
|
|
}
|
|
|
|
if (pdoExtension->DevicePowerState != irpStack->Parameters.Power.State.DeviceState) {
|
|
if (irpStack->Parameters.Power.State.DeviceState == PowerDeviceD3) {
|
|
|
|
// tell parent that we just fell to sleep
|
|
TrueffsFdoChildReportPowerDown(fdoExtension);
|
|
}
|
|
|
|
pdoExtension->DevicePowerState = Irp->IoStatus.Information;
|
|
}
|
|
}
|
|
|
|
if (callPoSetPowerState) {
|
|
|
|
// we didn't get out of device D0 state. calling PoSetPowerState now
|
|
PoSetPowerState (
|
|
pdoExtension->DeviceObject,
|
|
irpStack->Parameters.Power.Type,
|
|
irpStack->Parameters.Power.State
|
|
);
|
|
}
|
|
|
|
}
|
|
|
|
PoStartNextPowerIrp (Irp);
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
}
|
|
|
|
|
|
VOID
|
|
TrueffsPdoRequestPowerCompletionRoutine(
|
|
IN PDEVICE_OBJECT Pdo,
|
|
IN UCHAR MinorFunction,
|
|
IN POWER_STATE PowerState,
|
|
IN PVOID Context,
|
|
IN PIO_STATUS_BLOCK IoStatus
|
|
)
|
|
{
|
|
PIO_STACK_LOCATION irpStack;
|
|
PIRP irp = Context;
|
|
|
|
irp->IoStatus.Status = IoStatus->Status;
|
|
TrueffsPdoCompletePowerIrp (Pdo,irp);
|
|
return;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
TrueffsParentPowerUpCompletionRoutine(
|
|
IN PVOID Context,
|
|
IN NTSTATUS FdoStatus
|
|
)
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Completion routine for powering up the controller.
|
|
|
|
Arguments
|
|
|
|
Context - Context passed in - this is a pointer to the device extension of
|
|
the disk which originally triggered the power-up of the controller
|
|
|
|
FdoStatus - Status of the power up operation of the controller
|
|
|
|
Return Value
|
|
|
|
status
|
|
|
|
--*/
|
|
{
|
|
|
|
PPDO_EXTENSION pdoExtension = Context;
|
|
PIRP irp;
|
|
NTSTATUS status = FdoStatus;
|
|
KIRQL cIrql;
|
|
|
|
if (NT_SUCCESS(FdoStatus)) {
|
|
|
|
// Parent woke up..
|
|
/* MDOC PLUS */
|
|
MDOCPwindow *memWinPtr;
|
|
DOC2window *memDOC2000WinPtr;
|
|
volatile UCHAR chipId = 0;
|
|
|
|
memDOC2000WinPtr = (DOC2window *) pdoExtension->Pext->pcmciaParams.windowBase;
|
|
tffsWriteByte(memDOC2000WinPtr->DOCcontrol, ASIC_RESET_MODE);
|
|
tffsWriteByte(memDOC2000WinPtr->DOCcontrol, ASIC_RESET_MODE);
|
|
tffsWriteByte(memDOC2000WinPtr->DOCcontrol, ASIC_NORMAL_MODE);
|
|
tffsWriteByte(memDOC2000WinPtr->DOCcontrol, ASIC_NORMAL_MODE);
|
|
chipId = tffsReadByte(memDOC2000WinPtr->chipId);
|
|
if((chipId == 0x20) || (chipId == 0x30)){
|
|
|
|
}
|
|
else{
|
|
/* MDOC PLUS */
|
|
memWinPtr = (MDOCPwindow *) pdoExtension->Pext->pcmciaParams.windowBase;
|
|
tffsWriteByte(memWinPtr->DOCcontrol, (unsigned char)0x04);
|
|
tffsWriteByte(memWinPtr->DocCntConfirmReg, (unsigned char)0xfb);
|
|
tffsWriteByte(memWinPtr->DOCcontrol, (unsigned char)0x05);
|
|
tffsWriteByte(memWinPtr->DocCntConfirmReg, (unsigned char)0xfa);
|
|
}
|
|
|
|
|
|
KeAcquireSpinLock(&pdoExtension->Pext->ExtensionDataSpinLock,&cIrql);
|
|
pdoExtension->Pext->DeviceFlags &= ~DEVICE_FLAG_HOLD_IRPS;
|
|
KeReleaseSpinLock(&pdoExtension->Pext->ExtensionDataSpinLock,cIrql);
|
|
if (!KeReadStateSemaphore(&pdoExtension->Pext->requestSemaphore)) {
|
|
KeReleaseSemaphore(&pdoExtension->Pext->requestSemaphore,(KPRIORITY) 0,1,FALSE);
|
|
}
|
|
}
|
|
|
|
if ((irp = pdoExtension->PendingPowerIrp)!=NULL) {
|
|
|
|
// This is the IRP (for the pdo) that originally caused us to power up the parent
|
|
// Complete it now
|
|
irp->IoStatus.Status = status;
|
|
pdoExtension->PendingPowerIrp = NULL;
|
|
TrueffsPdoCompletePowerIrp(pdoExtension->DeviceObject, irp);
|
|
}
|
|
return status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
TrueffsFdoChildRequestPowerUp (
|
|
IN PDEVICE_EXTENSION FdoExtension,
|
|
IN PPDO_EXTENSION PdoExtension,
|
|
IN PIRP Irp
|
|
)
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
This routine is called whenever a disk needs to be powered up due to
|
|
a device state change. This routine would then check if the controller
|
|
is powered down and if so, it would request a power IRP to power up the
|
|
controller
|
|
|
|
Arguments
|
|
|
|
FdoExtension - Pointer to the device extension for the FDO of the
|
|
controller
|
|
|
|
PdoExtension - Pointer to the device extension for the PDO of the
|
|
disk. This is required so that this routine can
|
|
call a completion routine on behalf of the PDO when
|
|
the controller is powered up with the appropriate context
|
|
|
|
Irp - Irp that needs to be completed when the controller is
|
|
powered up
|
|
|
|
Return Value:
|
|
|
|
status
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status;
|
|
POWER_STATE powerState;
|
|
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
if (InterlockedCompareExchange(&FdoExtension->NumberOfDisksPoweredUp, 0, 0) == 0) {
|
|
|
|
// One of the children is coming out of sleep,
|
|
// we need to power up the parent (the controller)
|
|
powerState.DeviceState = PowerDeviceD0;
|
|
|
|
// Passed in IRP needs to be completed after
|
|
// parent powers up
|
|
PdoExtension->PendingPowerIrp = Irp;
|
|
|
|
status = PoRequestPowerIrp (FdoExtension->DeviceObject,
|
|
IRP_MN_SET_POWER,
|
|
powerState,
|
|
TrueffsFdoChildRequestPowerUpCompletionRoutine,
|
|
PdoExtension, // Context
|
|
NULL
|
|
);
|
|
if (!NT_SUCCESS(status)) {
|
|
return status;
|
|
}
|
|
status = STATUS_PENDING;
|
|
} else {
|
|
InterlockedIncrement(&FdoExtension->NumberOfDisksPoweredUp);
|
|
TrueffsParentPowerUpCompletionRoutine(
|
|
PdoExtension,
|
|
(NTSTATUS) STATUS_SUCCESS
|
|
);
|
|
}
|
|
return status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
TrueffsFdoChildRequestPowerUpCompletionRoutine (
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN UCHAR MinorFunction,
|
|
IN POWER_STATE PowerState,
|
|
IN PVOID Context,
|
|
IN PIO_STATUS_BLOCK IoStatus
|
|
)
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Completion routine for a request by a disk to power-up the parent controller.
|
|
|
|
Arguments
|
|
|
|
DeviceObject - Pointer to the Fdo for the controller
|
|
MinorFunction - Minor function of the IRP_MJ_POWER request
|
|
PowerState - Power state requested (should be D0)
|
|
Context - Context passed in to the completion routine
|
|
IoStatus - Pointer to the status block which will contain
|
|
the returned status
|
|
|
|
Return Value:
|
|
|
|
status
|
|
|
|
--*/
|
|
{
|
|
PDEVICE_EXTENSION fdoExtension;
|
|
fdoExtension = DeviceObject->DeviceExtension;
|
|
|
|
if (NT_SUCCESS(IoStatus->Status)) {
|
|
InterlockedIncrement(&fdoExtension->NumberOfDisksPoweredUp);
|
|
}
|
|
|
|
TrueffsParentPowerUpCompletionRoutine(
|
|
Context,
|
|
(NTSTATUS) IoStatus->Status
|
|
);
|
|
return IoStatus->Status;
|
|
}
|
|
|
|
|
|
VOID
|
|
TrueffsFdoChildReportPowerDown (
|
|
IN PDEVICE_EXTENSION FdoExtension
|
|
)
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
This routine is called whenever a disk is powered down due to
|
|
a device state change. This routine would then determine if ALL
|
|
disks controlled by the controller are powered down, and if
|
|
so, it would request a power IRP to power the controller itself down
|
|
|
|
Arguments
|
|
|
|
FdoExtension - Pointer to the device extension for the FDO of the controller
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
POWER_STATE powerState;
|
|
|
|
InterlockedDecrement(&FdoExtension->NumberOfDisksPoweredUp);
|
|
|
|
if (InterlockedCompareExchange(&FdoExtension->NumberOfDisksPoweredUp, 0, 0) == 0) {
|
|
|
|
// All the children are powered down, we can now power down
|
|
// the parent (the controller)
|
|
powerState.DeviceState = PowerDeviceD3;
|
|
PoRequestPowerIrp (
|
|
FdoExtension->DeviceObject,
|
|
IRP_MN_SET_POWER,
|
|
powerState,
|
|
NULL,
|
|
NULL,
|
|
NULL
|
|
);
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
TrueffsScsiRequests(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
{
|
|
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
|
|
PDEVICE_EXTENSION_HEADER devExtension;
|
|
PDEVICE_EXTENSION deviceExtension;
|
|
PSCSI_REQUEST_BLOCK srb;
|
|
NTSTATUS status;
|
|
KIRQL cIrql;
|
|
|
|
devExtension = (PDEVICE_EXTENSION_HEADER) DeviceObject->DeviceExtension;
|
|
|
|
if (IS_FDO(devExtension))
|
|
{
|
|
deviceExtension = DeviceObject->DeviceExtension;
|
|
}
|
|
else
|
|
{
|
|
PPDO_EXTENSION pdoExtension = DeviceObject->DeviceExtension;
|
|
deviceExtension = pdoExtension->Pext;
|
|
}
|
|
|
|
//
|
|
// Get a pointer to the scsi request block
|
|
//
|
|
srb = irpStack->Parameters.Scsi.Srb;
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: ScsiRequests for %Xh device object, function %Xh\n", DeviceObject, srb->Function));
|
|
|
|
if (deviceExtension->DeviceFlags & DEVICE_FLAG_REMOVED)
|
|
{
|
|
TffsDebugPrint((TFFS_DEB_ERROR,"Trueffs: ScsiRequests: Device does not exist\n"));
|
|
|
|
status = STATUS_DEVICE_DOES_NOT_EXIST;
|
|
srb->SrbStatus = SRB_STATUS_NO_DEVICE;
|
|
|
|
Irp->IoStatus.Status = status;
|
|
IoCompleteRequest(Irp,IO_NO_INCREMENT);
|
|
|
|
return status;
|
|
}
|
|
|
|
if (srb->Function == SRB_FUNCTION_CLAIM_DEVICE)
|
|
{
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: ScsiRequests: ClaimDevice\n"));
|
|
|
|
KeAcquireSpinLock(&deviceExtension->ExtensionDataSpinLock,&cIrql);
|
|
if (deviceExtension->DeviceFlags & DEVICE_FLAG_CLAIMED)
|
|
{
|
|
status = STATUS_DEVICE_BUSY;
|
|
srb->SrbStatus = SRB_STATUS_BUSY;
|
|
}
|
|
else
|
|
{
|
|
deviceExtension->DeviceFlags |= DEVICE_FLAG_CLAIMED;
|
|
srb->DataBuffer = DeviceObject;
|
|
|
|
status = STATUS_SUCCESS;
|
|
srb->SrbStatus = SRB_STATUS_SUCCESS;
|
|
}
|
|
KeReleaseSpinLock(&deviceExtension->ExtensionDataSpinLock,cIrql);
|
|
|
|
Irp->IoStatus.Status = status;
|
|
IoCompleteRequest(Irp,IO_NO_INCREMENT);
|
|
|
|
return status;
|
|
}
|
|
|
|
if (srb->Function == SRB_FUNCTION_RELEASE_DEVICE)
|
|
{
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: ScsiRequests: ReleaseDevice\n"));
|
|
|
|
KeAcquireSpinLock(&deviceExtension->ExtensionDataSpinLock,&cIrql);
|
|
deviceExtension->DeviceFlags &= ~DEVICE_FLAG_CLAIMED;
|
|
KeReleaseSpinLock(&deviceExtension->ExtensionDataSpinLock,cIrql);
|
|
|
|
status = STATUS_SUCCESS;
|
|
srb->SrbStatus = SRB_STATUS_SUCCESS;
|
|
|
|
Irp->IoStatus.Status = status;
|
|
IoCompleteRequest(Irp,IO_NO_INCREMENT);
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
if ((srb->Function == SRB_FUNCTION_FLUSH_QUEUE) || (srb->Function == SRB_FUNCTION_FLUSH))
|
|
{
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: ScsiRequests: Flush or FlushQueue\n"));
|
|
|
|
srb->SrbStatus = SRB_STATUS_SUCCESS;
|
|
status = STATUS_SUCCESS;
|
|
|
|
Irp->IoStatus.Status = status;
|
|
IoCompleteRequest(Irp,IO_NO_INCREMENT);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
if (srb->Function == SRB_FUNCTION_RESET_BUS)
|
|
{
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: ScsiRequests: ResetBus\n"));
|
|
|
|
srb->SrbStatus = SRB_STATUS_SUCCESS;
|
|
status = STATUS_SUCCESS;
|
|
|
|
Irp->IoStatus.Status = status;
|
|
IoCompleteRequest(Irp,IO_NO_INCREMENT);
|
|
|
|
return status;
|
|
}
|
|
|
|
if (srb->Function != SRB_FUNCTION_EXECUTE_SCSI)
|
|
{
|
|
TffsDebugPrint((TFFS_DEB_WARN,"Trueffs: ScsiRequests: unsupported function\n"));
|
|
|
|
status = STATUS_NOT_SUPPORTED;
|
|
srb->SrbStatus = SRB_STATUS_ERROR;
|
|
|
|
Irp->IoStatus.Status = status;
|
|
IoCompleteRequest(Irp,IO_NO_INCREMENT);
|
|
|
|
return status;
|
|
}
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: ScsiRequests: ExecuteScsi\n"));
|
|
|
|
IoMarkIrpPending(Irp);
|
|
IoStartPacket(DeviceObject, Irp, NULL, NULL);
|
|
|
|
return STATUS_PENDING;
|
|
}
|
|
|
|
|
|
VOID
|
|
TrueffsStartIo (
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - Supplies pointer to Adapter device object.
|
|
Irp - Supplies a pointer to an IRP.
|
|
|
|
Return Value:
|
|
|
|
Nothing.
|
|
|
|
--*/
|
|
|
|
{
|
|
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
|
|
PSCSI_REQUEST_BLOCK srb = irpStack->Parameters.Scsi.Srb;
|
|
PDEVICE_EXTENSION_HEADER devExtension;
|
|
PPDO_EXTENSION pdoExtension;
|
|
PDEVICE_EXTENSION deviceExtension;
|
|
NTSTATUS status;
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: StartIo\n"));
|
|
|
|
devExtension = (PDEVICE_EXTENSION_HEADER) DeviceObject->DeviceExtension;
|
|
if (IS_FDO(devExtension)) {
|
|
deviceExtension = DeviceObject->DeviceExtension;
|
|
pdoExtension = deviceExtension->ChildPdo->DeviceExtension;
|
|
}
|
|
else {
|
|
pdoExtension = DeviceObject->DeviceExtension;
|
|
deviceExtension = pdoExtension->Pext;
|
|
}
|
|
|
|
if (deviceExtension->DeviceFlags & DEVICE_FLAG_REMOVED) {
|
|
|
|
// we got REMOVE_DEVICE, we can't accept any more requests...
|
|
TffsDebugPrint((TFFS_DEB_ERROR,"Trueffs: StartIo: Device does not exist\n"));
|
|
status = STATUS_DEVICE_DOES_NOT_EXIST;
|
|
srb->SrbStatus = SRB_STATUS_NO_DEVICE;
|
|
Irp->IoStatus.Status = status;
|
|
IoCompleteRequest(Irp,IO_NO_INCREMENT);
|
|
IoStartNextPacket(DeviceObject,FALSE);
|
|
return;
|
|
|
|
}
|
|
|
|
status = QueueIrpToThread(Irp, deviceExtension);
|
|
|
|
if (status != STATUS_PENDING) {
|
|
TffsDebugPrint((TFFS_DEB_ERROR,"Trueffs: StartIo: QueueIrpToThread failed with status %Xh\n", status));
|
|
Irp->IoStatus.Status = status;
|
|
srb->SrbStatus = SRB_STATUS_ERROR;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
return;
|
|
}
|
|
if (pdoExtension->IdleCounter) {
|
|
|
|
PoSetDeviceBusy(pdoExtension->IdleCounter);
|
|
}
|
|
if (pdoExtension->DevicePowerState != PowerDeviceD0 &&
|
|
pdoExtension->SystemPowerState == PowerSystemWorking) {
|
|
|
|
// We are not powered up.
|
|
// issue an power up
|
|
POWER_STATE powerState;
|
|
|
|
powerState.DeviceState = PowerDeviceD0;
|
|
PoRequestPowerIrp (
|
|
pdoExtension->DeviceObject,
|
|
IRP_MN_SET_POWER,
|
|
powerState,
|
|
NULL,
|
|
NULL,
|
|
NULL
|
|
);
|
|
}
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: StartIo: Irp queued\n"));
|
|
Irp->IoStatus.Status = STATUS_PENDING;
|
|
srb->SrbStatus = SRB_STATUS_PENDING;
|
|
IoStartNextPacket(DeviceObject,FALSE);
|
|
return;
|
|
}
|
|
|
|
|
|
VOID
|
|
TrueffsThread(
|
|
PVOID Context
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the code executed by the system thread created when the
|
|
Trueffs driver initializes. This thread loops forever (or until a
|
|
flag is set telling the thread to kill itself) processing packets
|
|
put into the queue by the dispatch routines.
|
|
|
|
Arguments:
|
|
|
|
Context - not used.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
PIRP irp;
|
|
PIO_STACK_LOCATION irpSp;
|
|
PLIST_ENTRY request;
|
|
PDEVICE_EXTENSION deviceExtension = Context;
|
|
PSCSI_REQUEST_BLOCK Srb;
|
|
NTSTATUS ntStatus;
|
|
NTSTATUS waitStatus;
|
|
LARGE_INTEGER queueWait;
|
|
ULONG status;
|
|
ULONG i;
|
|
ULONG startingSector;
|
|
PUCHAR dataOffset;
|
|
PVOID storedSrbDataBuffer = NULL;
|
|
FLStatus tffsStatus = flOK;
|
|
FLStatus flStatusProt = flOK;
|
|
IOreq ioreq;
|
|
IOreq ioreqProt;
|
|
|
|
flIOctlRecord flIoctlRec;
|
|
int l;
|
|
|
|
CHAR vendorString[8];// = VENDORSTRING;
|
|
CHAR productString[16];// = PRODUCTSTRING;
|
|
CHAR revisionString[4];// = REVISIONSTRING;
|
|
|
|
PCHAR pageData;
|
|
ULONG parameterHeaderLength;
|
|
ULONG blockDescriptorLength;
|
|
PCDB cdb;
|
|
BOOLEAN transferForbidden;
|
|
flFormatPhysicalInput flFp;
|
|
flBDKOperationInput bdkOperationInput;
|
|
flOtpInput otpInput;
|
|
flIplInput iplInput;
|
|
flProtectionInput protectionInput;
|
|
void * userInput = NULL;
|
|
void * userOutput = NULL;
|
|
|
|
PAGED_CODE();
|
|
|
|
queueWait.QuadPart = -(3 * 1000 * 10000);
|
|
|
|
do {
|
|
|
|
KeSetEvent(&deviceExtension->PendingIRPEvent, 0, FALSE);
|
|
|
|
// Wait for a request from the dispatch routines.
|
|
waitStatus = KeWaitForSingleObject(
|
|
(PVOID) &deviceExtension->requestSemaphore,
|
|
Executive,
|
|
KernelMode,
|
|
FALSE,
|
|
&queueWait );
|
|
|
|
if (waitStatus == STATUS_SUCCESS && !(deviceExtension->DeviceFlags & DEVICE_FLAG_QUERY_STOP_REMOVE)
|
|
&& !(deviceExtension->DeviceFlags & DEVICE_FLAG_HOLD_IRPS)) {
|
|
if(deviceExtension->threadReferenceCount == 0) {
|
|
//TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: Thread: going to kill the thread\n"));
|
|
deviceExtension->threadReferenceCount = -1;
|
|
PsTerminateSystemThread( STATUS_SUCCESS );
|
|
}
|
|
}
|
|
else
|
|
continue;
|
|
|
|
while (request = ExInterlockedRemoveHeadList(&deviceExtension->listEntry,&deviceExtension->listSpinLock)) {
|
|
|
|
KeClearEvent(&deviceExtension->PendingIRPEvent);
|
|
irp = CONTAINING_RECORD( request, IRP, Tail.Overlay.ListEntry );
|
|
|
|
irpSp = IoGetCurrentIrpStackLocation( irp );
|
|
//TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: Thread: Irp %Xh, IrpSp %Xh\n", irp, irpSp));
|
|
|
|
Srb = irpSp->Parameters.Scsi.Srb;
|
|
//TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: Thread: Srb %Xh DataBuffer %Xh MdlAddress %Xh\n", Srb, Srb->DataBuffer, irp->MdlAddress));
|
|
|
|
transferForbidden = FALSE;
|
|
if (irp->MdlAddress != NULL) {
|
|
PVOID tmpDataBuffer = NULL;
|
|
MM_PAGE_PRIORITY tffsPriority =
|
|
(deviceExtension->PagingPathCount || deviceExtension->CrashDumpPathCount) ?
|
|
HighPagePriority : NormalPagePriority;
|
|
|
|
storedSrbDataBuffer = Srb->DataBuffer;
|
|
|
|
dataOffset = MmGetSystemAddressForMdlSafe(irp->MdlAddress, tffsPriority);
|
|
if (dataOffset != NULL) {
|
|
tmpDataBuffer = dataOffset + (ULONG)((PUCHAR)Srb->DataBuffer -
|
|
(PCCHAR)MmGetMdlVirtualAddress(irp->MdlAddress));
|
|
|
|
//TffsDebugPrint((TFFS_DEB_INFO, "Trueffs: TmpDataBuffer= 0x%x Srb->DataBuffer= 0x%x\n", tmpDataBuffer, Srb->DataBuffer));
|
|
Srb->DataBuffer = tmpDataBuffer;
|
|
}
|
|
else {
|
|
transferForbidden = TRUE;
|
|
TffsDebugPrint ((TFFS_DEB_ERROR,"Trueffs: MmGetSystemAddressForMdlSafe Failed\n"));
|
|
}
|
|
}
|
|
|
|
switch (irpSp->Parameters.DeviceIoControl.IoControlCode) {
|
|
case IOCTL_TFFS_EXTENDED_WRITE_IPL:
|
|
{
|
|
if( irpSp->Parameters.DeviceIoControl.OutputBufferLength <
|
|
sizeof(flOutputStatusRecord)) {
|
|
|
|
status = STATUS_INVALID_PARAMETER;
|
|
irp->IoStatus.Information = 0;
|
|
}
|
|
else if ( irpSp->Parameters.DeviceIoControl.InputBufferLength >
|
|
sizeof(flUserIplInput)){
|
|
status = STATUS_INVALID_PARAMETER;
|
|
irp->IoStatus.Information = 0;
|
|
}
|
|
else {
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : TffsGetInfo start get info\n"));
|
|
|
|
ioreq.irHandle = deviceExtension->UnitNumber;
|
|
ioreq.irFlags = FL_IOCTL_EXTENDED_WRITE_IPL;
|
|
ioreq.irData = &flIoctlRec;
|
|
|
|
iplInput.buf = ((flUserIplInput *)(irp->AssociatedIrp.SystemBuffer))->buf;
|
|
iplInput.bufLen = ((flUserIplInput *)(irp->AssociatedIrp.SystemBuffer))->bufLen;
|
|
flIoctlRec.inputRecord = &iplInput;
|
|
flIoctlRec.outputRecord = (VOID *)(irp->AssociatedIrp.SystemBuffer);
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : TffsGetInfo before flioctl\n"));
|
|
tffsStatus = flIOctl(&ioreq);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : TffsGetInfo after flioctl\n"));
|
|
|
|
if( tffsStatus == flOK ) {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : TffsGetInfo FLOK\n"));
|
|
irp->IoStatus.Information = sizeof(flOutputStatusRecord);
|
|
status = STATUS_SUCCESS;
|
|
|
|
}
|
|
else {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : TffsGetInfo !FLOK!\n"));
|
|
irp->IoStatus.Information = 0;
|
|
status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
}
|
|
|
|
irp->IoStatus.Status = status;
|
|
IoCompleteRequest( irp, IO_DISK_INCREMENT );
|
|
continue;
|
|
}
|
|
|
|
#ifdef ENVIRONMENT_VARS
|
|
case IOCTL_TFFS_EXTENDED_ENVIRONMENT_VARIABLES:
|
|
{
|
|
if( irpSp->Parameters.DeviceIoControl.OutputBufferLength <
|
|
sizeof(flOutputStatusRecord)) {
|
|
|
|
status = STATUS_INVALID_PARAMETER;
|
|
irp->IoStatus.Information = 0;
|
|
}
|
|
else if ( irpSp->Parameters.DeviceIoControl.InputBufferLength >
|
|
sizeof(flExtendedEnvVarsInput)){
|
|
status = STATUS_INVALID_PARAMETER;
|
|
irp->IoStatus.Information = 0;
|
|
}
|
|
else {
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : IOCTL_TFFS_EXTENDED_ENVIRONMENT_VARIABLES\n"));
|
|
|
|
ioreq.irHandle = deviceExtension->UnitNumber;
|
|
ioreq.irFlags = FL_IOCTL_EXTENDED_ENVIRONMENT_VARIABLES;
|
|
ioreq.irData = &flIoctlRec;
|
|
|
|
flIoctlRec.inputRecord = (VOID *)(irp->AssociatedIrp.SystemBuffer);
|
|
flIoctlRec.outputRecord = (VOID *)(irp->AssociatedIrp.SystemBuffer);
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : IOCTL_TFFS_EXTENDED_ENVIRONMENT_VARIABLES before flioctl\n"));
|
|
tffsStatus = flIOctl(&ioreq);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : IOCTL_TFFS_EXTENDED_ENVIRONMENT_VARIABLES after flioctl\n"));
|
|
|
|
if( tffsStatus == flOK ) {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : IOCTL_TFFS_EXTENDED_ENVIRONMENT_VARIABLES FLOK\n"));
|
|
irp->IoStatus.Information = sizeof(flExtendedEnvVarsOutput);
|
|
status = STATUS_SUCCESS;
|
|
|
|
}
|
|
else {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : IOCTL_TFFS_EXTENDED_ENVIRONMENT_VARIABLES !FLOK!\n"));
|
|
irp->IoStatus.Information = 0;
|
|
status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
}
|
|
|
|
irp->IoStatus.Status = status;
|
|
IoCompleteRequest( irp, IO_DISK_INCREMENT );
|
|
continue;
|
|
}
|
|
#endif /* ENVIRONMENT_VARS */
|
|
|
|
case IOCTL_TFFS_CUSTOMER_ID:
|
|
{
|
|
if( irpSp->Parameters.DeviceIoControl.OutputBufferLength <
|
|
sizeof(flCustomerIdOutput)) {
|
|
|
|
status = STATUS_INVALID_PARAMETER;
|
|
irp->IoStatus.Information = 0;
|
|
}
|
|
else {
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : TffsGetInfo start get info\n"));
|
|
|
|
ioreq.irHandle = deviceExtension->UnitNumber;
|
|
ioreq.irFlags = FL_IOCTL_CUSTOMER_ID;
|
|
ioreq.irData = &flIoctlRec;
|
|
flIoctlRec.outputRecord = (VOID *)(irp->AssociatedIrp.SystemBuffer);
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : TffsGetInfo before flioctl\n"));
|
|
tffsStatus = flIOctl(&ioreq);
|
|
//tffsStatus = flOK;
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : TffsGetInfo after flioctl\n"));
|
|
|
|
if( tffsStatus == flOK ) {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : TffsGetInfo FLOK\n"));
|
|
irp->IoStatus.Information = sizeof(flCustomerIdOutput);
|
|
status = STATUS_SUCCESS;
|
|
|
|
}
|
|
else {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : TffsGetInfo !FLOK!\n"));
|
|
irp->IoStatus.Information = 0;
|
|
status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
}
|
|
|
|
irp->IoStatus.Status = status;
|
|
IoCompleteRequest( irp, IO_DISK_INCREMENT );
|
|
continue;
|
|
}
|
|
|
|
case IOCTL_TFFS_NUMBER_OF_PARTITIONS: { // User TFFS IOCTL - FL_GET_INFO
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: TffsGetInfo\n"));
|
|
|
|
if( irpSp->Parameters.DeviceIoControl.OutputBufferLength <
|
|
sizeof(flCountPartitionsOutput)) {
|
|
|
|
status = STATUS_INVALID_PARAMETER;
|
|
irp->IoStatus.Information = 0;
|
|
}
|
|
else {
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : TffsGetInfo start get info\n"));
|
|
|
|
ioreq.irHandle = deviceExtension->UnitNumber;
|
|
ioreq.irFlags = FL_IOCTL_NUMBER_OF_PARTITIONS;
|
|
ioreq.irData = &flIoctlRec;
|
|
flIoctlRec.outputRecord = (VOID *)(irp->AssociatedIrp.SystemBuffer);
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : TffsGetInfo before flioctl\n"));
|
|
tffsStatus = flIOctl(&ioreq);
|
|
//tffsStatus = flOK;
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : TffsGetInfo after flioctl\n"));
|
|
|
|
if( tffsStatus == flOK ) {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : TffsGetInfo FLOK\n"));
|
|
irp->IoStatus.Information = sizeof(flCountPartitionsOutput);
|
|
status = STATUS_SUCCESS;
|
|
|
|
}
|
|
else {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : TffsGetInfo !FLOK!\n"));
|
|
irp->IoStatus.Information = 0;
|
|
status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
}
|
|
|
|
irp->IoStatus.Status = status;
|
|
IoCompleteRequest( irp, IO_DISK_INCREMENT );
|
|
continue;
|
|
}
|
|
case IOCTL_TFFSFL_UNIQUE_ID:
|
|
{ // User TFFS IOCTL -
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: FL_IOCTL_UNIQUE_ID \n"));
|
|
|
|
if( irpSp->Parameters.DeviceIoControl.OutputBufferLength <
|
|
sizeof(flUniqueIdOutput)) {
|
|
|
|
status = STATUS_INVALID_PARAMETER;
|
|
irp->IoStatus.Information = 0;
|
|
}
|
|
else {
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : FL_IOCTL_UNIQUE_ID Start\n"));
|
|
|
|
ioreq.irHandle = deviceExtension->UnitNumber;
|
|
ioreq.irFlags = FL_IOCTL_UNIQUE_ID;
|
|
ioreq.irData = &flIoctlRec;
|
|
flIoctlRec.outputRecord = (VOID *)(irp->AssociatedIrp.SystemBuffer);
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : TffsGetInfo before flioctl\n"));
|
|
tffsStatus = flIOctl(&ioreq);
|
|
//tffsStatus = flOK;
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : TffsGetInfo after flioctl\n"));
|
|
|
|
if( tffsStatus == flOK ) {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : TffsGetInfo FLOK\n"));
|
|
irp->IoStatus.Information = sizeof(flUniqueIdOutput);
|
|
status = STATUS_SUCCESS;
|
|
|
|
}
|
|
else {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : TffsGetInfo !FLOK!\n"));
|
|
irp->IoStatus.Information = 0;
|
|
status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
}
|
|
|
|
irp->IoStatus.Status = status;
|
|
IoCompleteRequest( irp, IO_DISK_INCREMENT );
|
|
continue;
|
|
}
|
|
|
|
case IOCTL_TFFS_FORMAT_PHYSICAL_DRIVE:
|
|
{ // User TFFS IOCTL - IOCTL_TFFSFL_INQUIRE_CAPABILITIES
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: IOCTL_TFFS_FORMAT_PHYSICAL_DRIVE\n"));
|
|
|
|
if( (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
|
|
sizeof(flOutputStatusRecord)) ||
|
|
(irpSp->Parameters.DeviceIoControl.InputBufferLength <
|
|
sizeof(flUserFormatPhysicalInput))) {
|
|
|
|
status = STATUS_INVALID_PARAMETER;
|
|
irp->IoStatus.Information = 0;
|
|
}
|
|
else {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : IOCTL_TFFS_FORMAT_PHYSICAL_DRIVE Start\n"));
|
|
userInput = (VOID *)(irp->AssociatedIrp.SystemBuffer); //Get input parameters
|
|
|
|
flFp.formatType = ((flUserFormatPhysicalInput *)userInput)->formatType;
|
|
TffsDebugPrint((TFFS_DEB_INFO,"TrueffsFORMAT: formatType:%Xh \n",flFp.formatType));
|
|
|
|
flFp.fp.percentUse = (unsigned char)((flUserFormatPhysicalInput *)userInput)->fp.percentUse;
|
|
TffsDebugPrint((TFFS_DEB_INFO,"TrueffsFORMAT: percentUse:%Xh \n",flFp.fp.percentUse));
|
|
|
|
flFp.fp.noOfBDTLPartitions = ((flUserFormatPhysicalInput *)userInput)->fp.noOfBDTLPartitions;
|
|
TffsDebugPrint((TFFS_DEB_INFO,"TrueffsFORMAT: noOfBDTLPartitions:%Xh \n",flFp.fp.noOfBDTLPartitions));
|
|
flFp.fp.noOfBinaryPartitions = ((flUserFormatPhysicalInput *)userInput)->fp.noOfBinaryPartitions;
|
|
TffsDebugPrint((TFFS_DEB_INFO,"TrueffsFORMAT: noOfBinaryPartitions:%Xh \n",flFp.fp.noOfBinaryPartitions));
|
|
flFp.fp.BDTLPartitionInfo = ((flUserFormatPhysicalInput *)userInput)->fp.BDTLPartitionInfo;
|
|
TffsDebugPrint((TFFS_DEB_INFO,"TrueffsFORMAT: BDTLPartitionInfo:%Xh \n",flFp.fp.BDTLPartitionInfo));
|
|
flFp.fp.binaryPartitionInfo = ((flUserFormatPhysicalInput *)userInput)->fp.binaryPartitionInfo;
|
|
TffsDebugPrint((TFFS_DEB_INFO,"TrueffsFORMAT: binaryPartitionInfo:%Xh \n",flFp.fp.binaryPartitionInfo));
|
|
|
|
#ifdef WRITE_EXB_IMAGE
|
|
flFp.fp.exbBuffer = ((flUserFormatPhysicalInput *)userInput)->fp.exbBuffer;
|
|
TffsDebugPrint((TFFS_DEB_INFO,"TrueffsFORMAT: exbBuffer:%Xh \n",flFp.fp.exbBuffer));
|
|
flFp.fp.exbBufferLen = ((flUserFormatPhysicalInput *)userInput)->fp.exbBufferLen;
|
|
TffsDebugPrint((TFFS_DEB_INFO,"TrueffsFORMAT: exbBufferLen:%Xh \n",flFp.fp.exbBufferLen));
|
|
flFp.fp.exbLen = ((flUserFormatPhysicalInput *)userInput)->fp.exbLen;
|
|
TffsDebugPrint((TFFS_DEB_INFO,"TrueffsFORMAT: exbLen:%Xh \n",flFp.fp.exbLen));
|
|
flFp.fp.exbWindow = ((flUserFormatPhysicalInput *)userInput)->fp.exbWindow;
|
|
TffsDebugPrint((TFFS_DEB_INFO,"TrueffsFORMAT: exbWindow:%Xh \n",flFp.fp.exbWindow));
|
|
flFp.fp.exbFlags = ((flUserFormatPhysicalInput *)userInput)->fp.exbFlags;
|
|
TffsDebugPrint((TFFS_DEB_INFO,"TrueffsFORMAT: exbFlags:%Xh \n",flFp.fp.exbFlags));
|
|
#endif /*WRITE_EXB_IMAGE*/
|
|
|
|
flFp.fp.cascadedDeviceNo = ((flUserFormatPhysicalInput *)userInput)->fp.cascadedDeviceNo;
|
|
TffsDebugPrint((TFFS_DEB_INFO,"TrueffsFORMAT: cascadedDeviceNo:%Xh \n",flFp.fp.cascadedDeviceNo));
|
|
flFp.fp.noOfCascadedDevices = ((flUserFormatPhysicalInput *)userInput)->fp.noOfCascadedDevices;
|
|
TffsDebugPrint((TFFS_DEB_INFO,"TrueffsFORMAT: noOfCascadedDevices:%Xh \n",flFp.fp.noOfCascadedDevices));
|
|
flFp.fp.progressCallback = NULL;
|
|
flFp.fp.vmAddressingLimit = ((flUserFormatPhysicalInput *)userInput)->fp.vmAddressingLimit;
|
|
TffsDebugPrint((TFFS_DEB_INFO,"TrueffsFORMAT: vmAddressingLimit:%Xh \n",flFp.fp.vmAddressingLimit));
|
|
flFp.fp.embeddedCISlength = (unsigned short)((flUserFormatPhysicalInput *)userInput)->fp.embeddedCISlength;
|
|
TffsDebugPrint((TFFS_DEB_INFO,"TrueffsFORMAT: embeddedCISlength:%Xh \n",flFp.fp.embeddedCISlength));
|
|
flFp.fp.embeddedCIS = ((flUserFormatPhysicalInput *)userInput)->fp.embeddedCIS;
|
|
TffsDebugPrint((TFFS_DEB_INFO,"TrueffsFORMAT: embeddedCIS:%Xh \n",flFp.fp.embeddedCIS));
|
|
|
|
ioreq.irHandle = deviceExtension->UnitNumber;
|
|
ioreq.irFlags = FL_IOCTL_FORMAT_PHYSICAL_DRIVE;
|
|
ioreq.irData = &flIoctlRec;
|
|
flIoctlRec.inputRecord = &flFp;//(VOID *)(irp->AssociatedIrp.SystemBuffer);
|
|
flIoctlRec.outputRecord = (VOID *)(irp->AssociatedIrp.SystemBuffer);
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : IOCTL_TFFS_FORMAT_PHYSICAL_DRIVE before flioctl\n"));
|
|
tffsStatus = flIOctl(&ioreq);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : IOCTL_TFFS_FORMAT_PHYSICAL_DRIVE after flioctl\n"));
|
|
userInput = NULL;
|
|
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : IOCTL_TFFS_FORMAT_PHYSICAL_DRIVE after flioctl - clean userPointer\n"));
|
|
if( tffsStatus == flOK ) {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : IOCTL_TFFS_FORMAT_PHYSICAL_DRIVE FLOK\n"));
|
|
irp->IoStatus.Information = sizeof(flOutputStatusRecord);
|
|
status = STATUS_SUCCESS;
|
|
|
|
}
|
|
else {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : IOCTL_TFFS_FORMAT_PHYSICAL_DRIVE Failed!\n"));
|
|
irp->IoStatus.Information = 0;
|
|
status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
}
|
|
|
|
irp->IoStatus.Status = status;
|
|
IoCompleteRequest( irp, IO_DISK_INCREMENT );
|
|
continue;
|
|
}
|
|
|
|
#ifdef VERIFY_VOLUME
|
|
case IOCTL_TFFS_VERIFY_VOLUME:
|
|
{
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: IOCTL_TFFS_VERIFY_VOLUME\n"));
|
|
|
|
if( (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
|
|
sizeof(flOutputStatusRecord)) ||
|
|
(irpSp->Parameters.DeviceIoControl.InputBufferLength <
|
|
sizeof(flVerifyVolumeInput))) {
|
|
|
|
status = STATUS_INVALID_PARAMETER;
|
|
irp->IoStatus.Information = 0;
|
|
}
|
|
else {
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: IOCTL_TFFS_VERIFY_VOLUME Start\n"));
|
|
|
|
ioreq.irHandle = deviceExtension->UnitNumber;
|
|
ioreq.irFlags = IOCTL_TFFS_VERIFY_VOLUME;
|
|
ioreq.irData = &flIoctlRec;
|
|
flIoctlRec.inputRecord = (VOID *)(irp->AssociatedIrp.SystemBuffer);
|
|
flIoctlRec.outputRecord = (VOID *)(irp->AssociatedIrp.SystemBuffer);
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: IOCTL_TFFS_VERIFY_VOLUME before flioctl\n"));
|
|
tffsStatus = flIOctl(&ioreq);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: IOCTL_TFFS_VERIFY_VOLUME after flioctl\n"));
|
|
|
|
if( tffsStatus == flOK ) {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: IOCTL_TFFS_VERIFY_VOLUME FLOK\n"));
|
|
irp->IoStatus.Information = sizeof(flVerifyVolumeOutput);
|
|
status = STATUS_SUCCESS;
|
|
|
|
|
|
}//if( tffsStatus == flOK )
|
|
else {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: IOCTL_TFFS_VERIFY_VOLUME Failed!\n"));
|
|
irp->IoStatus.Information = 0;
|
|
status = STATUS_UNSUCCESSFUL;
|
|
}//else( tffsStatus == flOK )
|
|
|
|
}//if( (irpSp->Parameters
|
|
irp->IoStatus.Status = status;
|
|
IoCompleteRequest( irp, IO_DISK_INCREMENT );
|
|
continue;
|
|
}
|
|
|
|
#endif /* VERIFY_VOLUME */
|
|
|
|
|
|
#ifdef HW_PROTECTION
|
|
case IOCTL_TFFS_BDTL_HW_PROTECTION:
|
|
{ // User TFFS IOCTL - IOCTL_TFFS_BDTL_HW_PROTECTION
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: IOCTL_TFFS_BDTL_HW_PROTECTION\n"));
|
|
|
|
if( (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
|
|
sizeof(flOutputStatusRecord)) ||
|
|
(irpSp->Parameters.DeviceIoControl.InputBufferLength <
|
|
sizeof(flProtectionInput))) {
|
|
|
|
status = STATUS_INVALID_PARAMETER;
|
|
irp->IoStatus.Information = 0;
|
|
}
|
|
else {
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : IOCTL_TFFS_BDTL_HW_PROTECTION Start\n"));
|
|
|
|
ioreq.irHandle = deviceExtension->UnitNumber;
|
|
ioreq.irFlags = FL_IOCTL_BDTL_HW_PROTECTION;
|
|
ioreq.irData = &flIoctlRec;
|
|
flIoctlRec.inputRecord = (VOID *)(irp->AssociatedIrp.SystemBuffer);
|
|
flIoctlRec.outputRecord = (VOID *)(irp->AssociatedIrp.SystemBuffer);
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : IOCTL_TFFS_BDTL_HW_PROTECTION before flioctl\n"));
|
|
tffsStatus = flIOctl(&ioreq);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : IOCTL_TFFS_BDTL_HW_PROTECTION after flioctl\n"));
|
|
|
|
if( tffsStatus == flOK ) {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : IOCTL_TFFS_BDTL_HW_PROTECTION FLOK\n"));
|
|
irp->IoStatus.Information = sizeof(flOutputStatusRecord);
|
|
status = STATUS_SUCCESS;
|
|
|
|
//Change if protection has been changed
|
|
/*
|
|
//If key inserted
|
|
if(((flProtectionInput *)flIoctlRec.inputRecord)->type == PROTECTION_INSERT_KEY){
|
|
deviceExtension->IsWriteProtected = FALSE;
|
|
}
|
|
//If type changed to protected
|
|
else if((((flProtectionInput *)flIoctlRec.inputRecord)->type == PROTECTION_CHANGE_TYPE) &&
|
|
((flProtectionInput *)flIoctlRec.inputRecord)->type & (READ_PROTECTED|WRITE_PROTECTED))){
|
|
deviceExtension->IsWriteProtected = TRUE;
|
|
}
|
|
//If type changed to unprotected
|
|
else if((((flProtectionInput *)flIoctlRec.inputRecord)->type == PROTECTION_CHANGE_TYPE) &&
|
|
((flProtectionInput *)flIoctlRec.inputRecord)->type == PROTECTABLE)){
|
|
deviceExtension->IsWriteProtected = FALSE;
|
|
}
|
|
//If remove key - ask if we are in protectable state.
|
|
else if(((flProtectionInput *)flIoctlRec.inputRecord)->type == PROTECTION_REMOVE_KEY){
|
|
*/
|
|
|
|
flStatusProt = flOK;
|
|
ioreqProt.irHandle = ioreq.irHandle;
|
|
ioreqProt.irFlags = 0;
|
|
flStatusProt = flIdentifyProtection(&ioreqProt);
|
|
if(flStatusProt == flOK){
|
|
if((ioreqProt.irFlags & (WRITE_PROTECTED |READ_PROTECTED))
|
|
&& !(ioreqProt.irFlags & KEY_INSERTED )){
|
|
deviceExtension->IsWriteProtected = TRUE;
|
|
}
|
|
else{
|
|
deviceExtension->IsWriteProtected = FALSE;
|
|
}
|
|
}
|
|
else{
|
|
deviceExtension->IsWriteProtected = FALSE;
|
|
}//(flStatusProt == flOK)
|
|
|
|
}//if( tffsStatus == flOK )
|
|
else {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : IOCTL_TFFS_BDTL_HW_PROTECTION Failed!\n"));
|
|
irp->IoStatus.Information = 0;
|
|
status = STATUS_UNSUCCESSFUL;
|
|
}//else( tffsStatus == flOK )
|
|
|
|
}//if( (irpSp->Parameters
|
|
irp->IoStatus.Status = status;
|
|
IoCompleteRequest( irp, IO_DISK_INCREMENT );
|
|
continue;
|
|
}
|
|
case IOCTL_TFFS_BINARY_HW_PROTECTION:
|
|
{ // User TFFS IOCTL - IOCTL_TFFS_BDTL_HW_PROTECTION
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: IOCTL_TFFS_BINARY_HW_PROTECTION\n"));
|
|
|
|
if( (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
|
|
sizeof(flOutputStatusRecord)) ||
|
|
(irpSp->Parameters.DeviceIoControl.InputBufferLength <
|
|
sizeof(flProtectionInput))) {
|
|
|
|
status = STATUS_INVALID_PARAMETER;
|
|
irp->IoStatus.Information = 0;
|
|
}
|
|
else {
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : IOCTL_TFFS_BINARY_HW_PROTECTION Start\n"));
|
|
|
|
//ioreq.irHandle = deviceExtension->UnitNumber;
|
|
ioreq.irFlags = FL_IOCTL_BINARY_HW_PROTECTION;
|
|
ioreq.irData = &flIoctlRec;
|
|
|
|
//Update protectionInput with flBDKProtectionInput members
|
|
protectionInput.protectionType = ((flBDKProtectionInput *)(irp->AssociatedIrp.SystemBuffer))->protectionType;
|
|
protectionInput.type = ((flBDKProtectionInput *)(irp->AssociatedIrp.SystemBuffer))->type;
|
|
tffscpy(protectionInput.key , ((flBDKProtectionInput *)(irp->AssociatedIrp.SystemBuffer))->key, sizeof(protectionInput.key));
|
|
ioreq.irHandle = (deviceExtension->UnitNumber & 0x0f) + (((flBDKProtectionInput *)(irp->AssociatedIrp.SystemBuffer))->partitionNumber << 4);
|
|
|
|
//flIoctlRec.inputRecord = (VOID *)(irp->AssociatedIrp.SystemBuffer);
|
|
flIoctlRec.inputRecord = &protectionInput;
|
|
flIoctlRec.outputRecord = (VOID *)(irp->AssociatedIrp.SystemBuffer);
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : IOCTL_TFFS_BINARY_HW_PROTECTION before flioctl\n"));
|
|
tffsStatus = flIOctl(&ioreq);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : IOCTL_TFFS_BINARY_HW_PROTECTION after flioctl\n"));
|
|
|
|
if( tffsStatus == flOK ) {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : IOCTL_TFFS_BINARY_HW_PROTECTION FLOK\n"));
|
|
irp->IoStatus.Information = sizeof(flOutputStatusRecord);
|
|
status = STATUS_SUCCESS;
|
|
|
|
}
|
|
else {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : IOCTL_TFFS_BINARY_HW_PROTECTION Failed!\n"));
|
|
irp->IoStatus.Information = 0;
|
|
status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
}
|
|
|
|
irp->IoStatus.Status = status;
|
|
IoCompleteRequest( irp, IO_DISK_INCREMENT );
|
|
continue;
|
|
}
|
|
|
|
#endif /*HW_PROTECTION*/
|
|
#ifdef WRITE_EXB_IMAGE
|
|
case IOCTL_TFFS_PLACE_EXB_BY_BUFFER:
|
|
{
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: IOCTL_TFFS_PLACE_EXB_BY_BUFFER\n"));
|
|
|
|
if( (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
|
|
sizeof(flOutputStatusRecord) )
|
|
|| (irpSp->Parameters.DeviceIoControl.InputBufferLength <
|
|
sizeof(flUserPlaceExbInput) )) {
|
|
|
|
status = STATUS_INVALID_PARAMETER;
|
|
irp->IoStatus.Information = 0;
|
|
}
|
|
else {
|
|
|
|
flPlaceExbInput placeExbInput;
|
|
ioreq.irHandle = deviceExtension->UnitNumber;
|
|
ioreq.irFlags = FL_IOCTL_PLACE_EXB_BY_BUFFER;
|
|
ioreq.irData = &flIoctlRec;
|
|
flIoctlRec.outputRecord = (VOID *)(irp->AssociatedIrp.SystemBuffer);
|
|
flIoctlRec.inputRecord = &placeExbInput;
|
|
|
|
//Update placeExbInput with flUserPlaceExbInput memebers
|
|
placeExbInput.buf = ((flUserPlaceExbInput *)(irp->AssociatedIrp.SystemBuffer))->buf;
|
|
placeExbInput.bufLen = ((flUserPlaceExbInput *)(irp->AssociatedIrp.SystemBuffer))->bufLen;
|
|
placeExbInput.exbFlags = ((flUserPlaceExbInput *)(irp->AssociatedIrp.SystemBuffer))->exbFlags;
|
|
placeExbInput.exbWindow = ((flUserPlaceExbInput *)(irp->AssociatedIrp.SystemBuffer))->exbWindow;
|
|
tffsStatus = flIOctl(&ioreq);
|
|
|
|
if( tffsStatus == flOK ) {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : TffsGetInfo FLOK\n"));
|
|
irp->IoStatus.Information = sizeof(flCountPartitionsOutput);
|
|
status = STATUS_SUCCESS;
|
|
|
|
}
|
|
else {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : TffsGetInfo !FLOK!\n"));
|
|
irp->IoStatus.Information = 0;
|
|
status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
}
|
|
|
|
irp->IoStatus.Status = status;
|
|
IoCompleteRequest( irp, IO_DISK_INCREMENT );
|
|
continue;
|
|
}
|
|
#endif /*WRITE_EXB_IMAGE*/
|
|
|
|
#ifdef HW_OTP
|
|
case IOCTL_TFFS_OTP:
|
|
{ // User TFFS IOCTL - IOCTL_TFFS_BDTL_HW_PROTECTION
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: IOCTL_TFFS_OTP\n"));
|
|
|
|
if( (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
|
|
sizeof(UserOtpOutput)) ||
|
|
(irpSp->Parameters.DeviceIoControl.InputBufferLength <
|
|
sizeof(UserOtpInput))) {
|
|
|
|
status = STATUS_INVALID_PARAMETER;
|
|
irp->IoStatus.Information = 0;
|
|
}
|
|
else {
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : IOCTL_TFFS_OTP Start\n"));
|
|
userInput = (VOID *)(irp->AssociatedIrp.SystemBuffer);
|
|
userOutput = (VOID *)(irp->AssociatedIrp.SystemBuffer);
|
|
|
|
otpInput.type = ((UserOtpInput *)userInput)->type;
|
|
if(otpInput.type != OTP_SIZE){
|
|
otpInput.length = ((UserOtpInput *)userInput)->length;
|
|
if(otpInput.type != OTP_WRITE_LOCK)
|
|
otpInput.usedSize = ((UserOtpInput *)userInput)->usedSize;
|
|
}
|
|
|
|
//Updating OTP i/o buffer
|
|
if(otpInput.type == OTP_WRITE_LOCK)
|
|
otpInput.buffer = ((UserOtpInput *)userInput)->buffer;
|
|
else
|
|
otpInput.buffer = ((UserOtpOutput *)userOutput)->buffer;
|
|
|
|
ioreq.irHandle = deviceExtension->UnitNumber;
|
|
ioreq.irFlags = FL_IOCTL_OTP;
|
|
ioreq.irData = &flIoctlRec;
|
|
|
|
flIoctlRec.inputRecord = (VOID *)&otpInput;
|
|
flIoctlRec.outputRecord = (VOID *)(&(((UserOtpOutput *)userOutput)->statusRec));
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : IOCTL_TFFS_OTP before flioctl\n"));
|
|
tffsStatus = flIOctl(&ioreq);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : IOCTL_TFFS_OTP after flioctl\n"));
|
|
|
|
if( tffsStatus == flOK ) {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : IOCTL_TFFS_OTP FLOK\n"));
|
|
irp->IoStatus.Information = sizeof(UserOtpInput);
|
|
status = STATUS_SUCCESS;
|
|
if(otpInput.type == OTP_SIZE){
|
|
((UserOtpOutput *)userOutput)->length = otpInput.length;
|
|
((UserOtpOutput *)userOutput)->usedSize = otpInput.usedSize;
|
|
((UserOtpOutput *)userOutput)->lockedFlag = otpInput.lockedFlag;
|
|
((UserOtpOutput *)userOutput)->statusRec.status = tffsStatus;
|
|
}
|
|
|
|
}
|
|
else {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : IOCTL_TFFS_OTP Failed!\n"));
|
|
irp->IoStatus.Information = 0;
|
|
status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
}
|
|
userInput = NULL;
|
|
userOutput = NULL;
|
|
irp->IoStatus.Status = status;
|
|
IoCompleteRequest( irp, IO_DISK_INCREMENT );
|
|
continue;
|
|
}
|
|
#endif /* HW_OTP*/
|
|
case IOCTL_TFFS_DEEP_POWER_DOWN_MODE:
|
|
{ // User TFFS IOCTL - IOCTL_TFFSFL_INQUIRE_CAPABILITIES
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: FL_IOCTL_DEEP_POWER_DOWN_MODE\n"));
|
|
|
|
if( (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
|
|
sizeof(flOutputStatusRecord)) ||
|
|
(irpSp->Parameters.DeviceIoControl.InputBufferLength <
|
|
sizeof(flPowerDownInput))) {
|
|
|
|
status = STATUS_INVALID_PARAMETER;
|
|
irp->IoStatus.Information = 0;
|
|
}
|
|
else {
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : FL_IOCTL_DEEP_POWER_DOWN_MODE Start\n"));
|
|
|
|
ioreq.irHandle = deviceExtension->UnitNumber;
|
|
ioreq.irFlags = FL_IOCTL_DEEP_POWER_DOWN_MODE;
|
|
ioreq.irData = &flIoctlRec;
|
|
flIoctlRec.inputRecord = (VOID *)(irp->AssociatedIrp.SystemBuffer);
|
|
flIoctlRec.outputRecord = (VOID *)(irp->AssociatedIrp.SystemBuffer);
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : FL_IOCTL_DEEP_POWER_DOWN_MODE before flioctl\n"));
|
|
tffsStatus = flIOctl(&ioreq);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : FL_IOCTL_DEEP_POWER_DOWN_MODE after flioctl\n"));
|
|
|
|
if( tffsStatus == flOK ) {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : FL_IOCTL_DEEP_POWER_DOWN_MODE FLOK\n"));
|
|
irp->IoStatus.Information = sizeof(flOutputStatusRecord);
|
|
status = STATUS_SUCCESS;
|
|
|
|
}
|
|
else {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : FL_IOCTL_DEEP_POWER_DOWN_MODE Failed!\n"));
|
|
irp->IoStatus.Information = 0;
|
|
status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
}
|
|
|
|
irp->IoStatus.Status = status;
|
|
IoCompleteRequest( irp, IO_DISK_INCREMENT );
|
|
continue;
|
|
}
|
|
|
|
case IOCTL_TFFSFL_INQUIRE_CAPABILITIES:
|
|
{ // User TFFS IOCTL - IOCTL_TFFSFL_INQUIRE_CAPABILITIES
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: FL_IOCTL_UNIQUE_ID \n"));
|
|
|
|
if( (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
|
|
sizeof(flCapabilityOutput)) ||
|
|
(irpSp->Parameters.DeviceIoControl.InputBufferLength <
|
|
sizeof(flCapabilityInput))) {
|
|
|
|
status = STATUS_INVALID_PARAMETER;
|
|
irp->IoStatus.Information = 0;
|
|
}
|
|
else {
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : FL_IOCTL_INQUIRE_CAPABILITIES Start\n"));
|
|
|
|
ioreq.irHandle = deviceExtension->UnitNumber;
|
|
ioreq.irFlags = FL_IOCTL_INQUIRE_CAPABILITIES;
|
|
ioreq.irData = &flIoctlRec;
|
|
flIoctlRec.inputRecord = (VOID *)(irp->AssociatedIrp.SystemBuffer);
|
|
flIoctlRec.outputRecord = (VOID *)(irp->AssociatedIrp.SystemBuffer);
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : FL_IOCTL_INQUIRE_CAPABILITIES before flioctl\n"));
|
|
tffsStatus = flIOctl(&ioreq);
|
|
//tffsStatus = flOK;
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : FL_IOCTL_INQUIRE_CAPABILITIES after flioctl\n"));
|
|
|
|
if( tffsStatus == flOK ) {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : FL_IOCTL_INQUIRE_CAPABILITIES FLOK\n"));
|
|
irp->IoStatus.Information = sizeof(flCapabilityInput);
|
|
status = STATUS_SUCCESS;
|
|
|
|
}
|
|
else {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : FL_IOCTL_INQUIRE_CAPABILITIES Failed!\n"));
|
|
irp->IoStatus.Information = 0;
|
|
status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
}
|
|
|
|
irp->IoStatus.Status = status;
|
|
IoCompleteRequest( irp, IO_DISK_INCREMENT );
|
|
continue;
|
|
}
|
|
|
|
case IOCTL_TFFS_GET_INFO: { // User TFFS IOCTL - FL_GET_INFO
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: TffsGetInfo\n"));
|
|
|
|
if( irpSp->Parameters.DeviceIoControl.OutputBufferLength <
|
|
sizeof(flDiskInfoOutput)) {
|
|
|
|
status = STATUS_INVALID_PARAMETER;
|
|
irp->IoStatus.Information = 0;
|
|
}
|
|
else {
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : TffsGetInfo start get info\n"));
|
|
|
|
ioreq.irHandle = deviceExtension->UnitNumber;
|
|
ioreq.irFlags = FL_IOCTL_GET_INFO;
|
|
ioreq.irData = &flIoctlRec;
|
|
flIoctlRec.outputRecord = (VOID *)(irp->AssociatedIrp.SystemBuffer);
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : TffsGetInfo before flioctl\n"));
|
|
tffsStatus = flIOctl(&ioreq);
|
|
//tffsStatus = flOK;
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : TffsGetInfo after flioctl\n"));
|
|
|
|
if( tffsStatus == flOK ) {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : TffsGetInfo FLOK\n"));
|
|
irp->IoStatus.Information = sizeof(flDiskInfoOutput);
|
|
status = STATUS_SUCCESS;
|
|
|
|
}
|
|
else {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : TffsGetInfo !FLOK!\n"));
|
|
irp->IoStatus.Information = 0;
|
|
status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
}
|
|
|
|
irp->IoStatus.Status = status;
|
|
IoCompleteRequest( irp, IO_DISK_INCREMENT );
|
|
continue;
|
|
}
|
|
|
|
case IOCTL_TFFS_DEFRAGMENT: { // User TFFS IOCTL - FL_DEFRAGMENT
|
|
flDefragInput iDefrag;
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: TffsDefragment\n"));
|
|
|
|
if( irpSp->Parameters.DeviceIoControl.OutputBufferLength <
|
|
sizeof(flDefragOutput)) {
|
|
|
|
status = STATUS_INVALID_PARAMETER;
|
|
irp->IoStatus.Information = 0;
|
|
}
|
|
else {
|
|
if( irpSp->Parameters.DeviceIoControl.InputBufferLength == 0 )
|
|
iDefrag.requiredNoOfSectors = -1;
|
|
else
|
|
iDefrag.requiredNoOfSectors = *((LONG *)(irp->AssociatedIrp.SystemBuffer));
|
|
|
|
ioreq.irHandle = deviceExtension->UnitNumber;
|
|
ioreq.irFlags = FL_IOCTL_DEFRAGMENT;
|
|
ioreq.irData = &flIoctlRec;
|
|
flIoctlRec.inputRecord = (VOID *)&iDefrag;
|
|
flIoctlRec.outputRecord = (VOID *)(irp->AssociatedIrp.SystemBuffer);
|
|
|
|
tffsStatus = flIOctl(&ioreq);
|
|
//tffsStatus = flOK;
|
|
|
|
if( tffsStatus == flOK ) {
|
|
irp->IoStatus.Information = sizeof(flDefragOutput);
|
|
status = STATUS_SUCCESS;
|
|
}
|
|
else {
|
|
irp->IoStatus.Information = 0;
|
|
status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
}
|
|
irp->IoStatus.Status = status;
|
|
IoCompleteRequest( irp, IO_DISK_INCREMENT );
|
|
continue;
|
|
}
|
|
|
|
case IOCTL_TFFS_WRITE_PROTECT: { // User TFFS IOCTL - FL_WRITE_PROTECT
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: TffsWriteProtect\n"));
|
|
|
|
if( irpSp->Parameters.DeviceIoControl.InputBufferLength <
|
|
sizeof(flWriteProtectInput)) {
|
|
|
|
status = STATUS_INVALID_PARAMETER;
|
|
irp->IoStatus.Information = 0;
|
|
}
|
|
else {
|
|
ioreq.irHandle = deviceExtension->UnitNumber;
|
|
ioreq.irFlags = FL_IOCTL_WRITE_PROTECT;
|
|
ioreq.irData = &flIoctlRec;
|
|
flIoctlRec.inputRecord = (VOID *)(irp->AssociatedIrp.SystemBuffer);
|
|
flIoctlRec.outputRecord = (VOID *)(irp->AssociatedIrp.SystemBuffer);
|
|
tffsStatus = flIOctl(&ioreq);
|
|
|
|
if( tffsStatus == flOK ) {
|
|
irp->IoStatus.Information = sizeof(flOutputStatusRecord);
|
|
status = STATUS_SUCCESS;
|
|
|
|
//Handling Enable and disable of write portected media
|
|
if(((flWriteProtectInput *)flIoctlRec.inputRecord)->type == FL_PROTECT){
|
|
deviceExtension->IsSWWriteProtected = TRUE;
|
|
}
|
|
else if(((flWriteProtectInput *)flIoctlRec.inputRecord)->type == FL_UNPROTECT){
|
|
deviceExtension->IsSWWriteProtected = FALSE;
|
|
}
|
|
else if(((flWriteProtectInput *)flIoctlRec.inputRecord)->type == FL_UNLOCK){
|
|
deviceExtension->IsSWWriteProtected = FALSE;
|
|
}
|
|
}
|
|
else {
|
|
irp->IoStatus.Information = 0;
|
|
status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
}
|
|
irp->IoStatus.Status = status;
|
|
IoCompleteRequest( irp, IO_DISK_INCREMENT );
|
|
continue;
|
|
}
|
|
|
|
case IOCTL_TFFS_MOUNT_VOLUME: // User TFFS IOCTL - FL_MOUNT_VOLUME
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: TffsMountVolume\n"));
|
|
|
|
if( (irpSp->Parameters.DeviceIoControl.InputBufferLength <
|
|
sizeof(flMountInput)) ||
|
|
(irpSp->Parameters.DeviceIoControl.OutputBufferLength <
|
|
sizeof(flOutputStatusRecord)) ) {
|
|
|
|
status = STATUS_INVALID_PARAMETER;
|
|
irp->IoStatus.Information = 0;
|
|
}
|
|
else {
|
|
ioreq.irHandle = deviceExtension->UnitNumber;
|
|
ioreq.irFlags = FL_IOCTL_MOUNT_VOLUME;
|
|
ioreq.irData = &flIoctlRec;
|
|
flIoctlRec.inputRecord = (VOID *)(irp->AssociatedIrp.SystemBuffer);
|
|
flIoctlRec.outputRecord = (VOID *)(irp->AssociatedIrp.SystemBuffer);
|
|
|
|
tffsStatus = flIOctl(&ioreq);
|
|
|
|
if( tffsStatus == flOK ) {
|
|
irp->IoStatus.Information = sizeof(flOutputStatusRecord);
|
|
status = STATUS_SUCCESS;
|
|
}
|
|
else {
|
|
irp->IoStatus.Information = 0;
|
|
status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
}
|
|
irp->IoStatus.Status = status;
|
|
IoCompleteRequest( irp, IO_DISK_INCREMENT );
|
|
continue;
|
|
|
|
case IOCTL_TFFS_FORMAT_VOLUME: // User TFFS IOCTL - FL_FORMAT_VOLUME
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: TffsFormatVolume\n"));
|
|
|
|
if( (irpSp->Parameters.DeviceIoControl.InputBufferLength <
|
|
sizeof(flFormatInput)) ||
|
|
(irpSp->Parameters.DeviceIoControl.OutputBufferLength <
|
|
sizeof(flOutputStatusRecord)) ) {
|
|
|
|
status = STATUS_INVALID_PARAMETER;
|
|
irp->IoStatus.Information = 0;
|
|
}
|
|
else {
|
|
ioreq.irHandle = deviceExtension->UnitNumber;
|
|
ioreq.irFlags = FL_IOCTL_FORMAT_VOLUME;
|
|
ioreq.irData = &flIoctlRec;
|
|
flIoctlRec.inputRecord = (VOID *)(irp->AssociatedIrp.SystemBuffer);
|
|
flIoctlRec.outputRecord = (VOID *)(irp->AssociatedIrp.SystemBuffer);
|
|
|
|
tffsStatus = flIOctl(&ioreq);
|
|
|
|
if( tffsStatus == flOK ) {
|
|
irp->IoStatus.Information = sizeof(flOutputStatusRecord);
|
|
status = STATUS_SUCCESS;
|
|
}
|
|
else {
|
|
irp->IoStatus.Information = 0;
|
|
status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
}
|
|
irp->IoStatus.Status = status;
|
|
IoCompleteRequest( irp, IO_DISK_INCREMENT );
|
|
continue;
|
|
|
|
case IOCTL_TFFS_BDK_OPERATION:
|
|
{ // User TFFS IOCTL - IOCTL_TFFSFL_INQUIRE_CAPABILITIES
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: IOCTL_TFFS_BDK_OPERATION\n"));
|
|
|
|
if( (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
|
|
sizeof(flUserBDKOperationOutput)) ||
|
|
(irpSp->Parameters.DeviceIoControl.InputBufferLength <
|
|
sizeof(flUserBDKOperationInput))) {
|
|
|
|
status = STATUS_INVALID_PARAMETER;
|
|
irp->IoStatus.Information = 0;
|
|
}
|
|
else {
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : FL_IOCTL_DEEP_POWER_DOWN_MODE Start\n"));
|
|
userInput = (VOID *)(irp->AssociatedIrp.SystemBuffer);
|
|
userOutput = (VOID *)(irp->AssociatedIrp.SystemBuffer);
|
|
|
|
bdkOperationInput.type = ((flUserBDKOperationInput *)userInput)->type;
|
|
//Copy new and old signature
|
|
for(i = 0; i < BDK_SIGNATURE_NAME; i++){
|
|
bdkOperationInput.bdkStruct.oldSign[i] = ((flUserBDKOperationInput *)userInput)->bdkStruct.oldSign[i];
|
|
bdkOperationInput.bdkStruct.newSign[i] = ((flUserBDKOperationInput *)userInput)->bdkStruct.newSign[i];
|
|
}
|
|
|
|
|
|
bdkOperationInput.bdkStruct.signOffset = ((flUserBDKOperationInput *)userInput)->bdkStruct.signOffset;
|
|
bdkOperationInput.bdkStruct.startingBlock = ((flUserBDKOperationInput *)userInput)->bdkStruct.startingBlock;
|
|
bdkOperationInput.bdkStruct.length = ((flUserBDKOperationInput *)userInput)->bdkStruct.length;
|
|
bdkOperationInput.bdkStruct.flags = ((flUserBDKOperationInput *)userInput)->bdkStruct.flags;
|
|
|
|
|
|
if(bdkOperationInput.type != BDK_READ)
|
|
bdkOperationInput.bdkStruct.bdkBuffer = ((flUserBDKOperationInput *)userInput)->bdkStruct.bdkBuffer;
|
|
else
|
|
bdkOperationInput.bdkStruct.bdkBuffer = ((flUserBDKOperationOutput *)userOutput)->bdkStruct.bdkBuffer;
|
|
|
|
ioreq.irHandle = (deviceExtension->UnitNumber & 0x0f) + (((flUserBDKOperationInput *)userOutput)->partitionNumber << 4);
|
|
ioreq.irFlags = FL_IOCTL_BDK_OPERATION;
|
|
ioreq.irData = &flIoctlRec;
|
|
flIoctlRec.inputRecord = &bdkOperationInput;
|
|
flIoctlRec.outputRecord = (VOID *) (&(((flUserBDKOperationOutput *)userOutput)->statusRec));
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : IOCTL_TFFS_BDK_OPERATION before flioctl\n"));
|
|
tffsStatus = flIOctl(&ioreq);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : IOCTL_TFFS_BDK_OPERATION after flioctl\n"));
|
|
|
|
if( tffsStatus == flOK ) {
|
|
if(bdkOperationInput.type == BDK_GET_INFO){
|
|
((flUserBDKOperationOutput *)userOutput)->bdkStruct.signOffset = bdkOperationInput.bdkStruct.signOffset;
|
|
((flUserBDKOperationOutput *)userOutput)->bdkStruct.startingBlock = bdkOperationInput.bdkStruct.startingBlock;
|
|
((flUserBDKOperationOutput *)userOutput)->bdkStruct.length = bdkOperationInput.bdkStruct.length;
|
|
((flUserBDKOperationOutput *)userOutput)->bdkStruct.flags = bdkOperationInput.bdkStruct.flags;
|
|
}
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : IOCTL_TFFS_BDK_OPERATION FLOK\n"));
|
|
irp->IoStatus.Information = sizeof(flUserBDKOperationOutput);
|
|
status = STATUS_SUCCESS;
|
|
|
|
}
|
|
else {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: : IOCTL_TFFS_BDK_OPERATION Failed!\n"));
|
|
irp->IoStatus.Information = 0;
|
|
status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
}
|
|
|
|
irp->IoStatus.Status = status;
|
|
IoCompleteRequest( irp, IO_DISK_INCREMENT );
|
|
continue;
|
|
}
|
|
case IOCTL_TFFS_DELETE_SECTORS: // User TFFS IOCTL - FL_DELETE_SECTORS
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: DeviceControl: TffsDeleteSectors\n"));
|
|
|
|
if( irpSp->Parameters.DeviceIoControl.InputBufferLength <
|
|
sizeof(flDeleteSectorsInput) ) {
|
|
|
|
status = STATUS_INVALID_PARAMETER;
|
|
irp->IoStatus.Information = 0;
|
|
}
|
|
else {
|
|
ioreq.irHandle = deviceExtension->UnitNumber;
|
|
ioreq.irFlags = FL_IOCTL_DELETE_SECTORS;
|
|
ioreq.irData = &flIoctlRec;
|
|
flIoctlRec.inputRecord = (VOID *)(irp->AssociatedIrp.SystemBuffer);
|
|
flIoctlRec.outputRecord = (VOID *)(irp->AssociatedIrp.SystemBuffer);
|
|
|
|
tffsStatus = flIOctl(&ioreq);
|
|
|
|
if( tffsStatus == flOK ) {
|
|
irp->IoStatus.Information = sizeof(flOutputStatusRecord);
|
|
status = STATUS_SUCCESS;
|
|
}
|
|
else {
|
|
irp->IoStatus.Information = 0;
|
|
status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
}
|
|
irp->IoStatus.Status = status;
|
|
IoCompleteRequest( irp, IO_DISK_INCREMENT );
|
|
continue;
|
|
}
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: StartIo: SrbFunction %Xh Command %Xh Unit %Xh\n",Srb->Function, Srb->Cdb[0], deviceExtension->UnitNumber));
|
|
switch (Srb->Function) {
|
|
|
|
case SRB_FUNCTION_EXECUTE_SCSI:
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: StartIo: ExecuteScsi\n"));
|
|
|
|
// Sanity check. Only one request can be outstanding on a
|
|
// controller.
|
|
if (deviceExtension->CurrentSrb) {
|
|
|
|
// Restore the srb->DataBuffer if necesary
|
|
if (irp->MdlAddress != NULL) {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: Restoration of Srb->DataBuffer done\n"));
|
|
Srb->DataBuffer = storedSrbDataBuffer;
|
|
}
|
|
|
|
|
|
TffsDebugPrint((TFFS_DEB_ERROR,"Trueffs: StartIo: Already have a request!\n"));
|
|
Srb->SrbStatus = SRB_STATUS_BUSY;
|
|
irp->IoStatus.Information = 0;
|
|
irp->IoStatus.Status = STATUS_DEVICE_BUSY;
|
|
IoCompleteRequest(irp,IO_NO_INCREMENT);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Indicate that a request is active
|
|
deviceExtension->CurrentSrb = Srb;
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: StartIo: Command %x to device %d\n",
|
|
Srb->Cdb[0],
|
|
Srb->TargetId));
|
|
|
|
switch (Srb->Cdb[0]) {
|
|
case SCSIOP_INQUIRY:
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: StartIo: Inquiry\n"));
|
|
|
|
if (Srb->Lun != 0 || Srb->TargetId != 0) {
|
|
|
|
status = SRB_STATUS_SELECTION_TIMEOUT;
|
|
break;
|
|
|
|
} else {
|
|
|
|
PINQUIRYDATA inquiryData = Srb->DataBuffer;
|
|
|
|
if (transferForbidden) {
|
|
status = SRB_STATUS_ERROR;
|
|
break;
|
|
}
|
|
// Zero INQUIRY data structure.
|
|
for (i = 0; i < Srb->DataTransferLength; i++) {
|
|
((PUCHAR)Srb->DataBuffer)[i] = 0;
|
|
}
|
|
|
|
inquiryData->DeviceType = deviceExtension->ScsiDeviceType;
|
|
|
|
if (deviceExtension->removableMedia) {
|
|
inquiryData->RemovableMedia = 1;
|
|
}
|
|
|
|
for (i = 0; i < 8; i++)
|
|
inquiryData->VendorId[i] = vendorString[i];
|
|
|
|
for (i = 0; i < 16; i++)
|
|
inquiryData->ProductId[i] = productString[i];
|
|
|
|
for (i = 0; i < 4; i++)
|
|
inquiryData->ProductRevisionLevel[i] = revisionString[i];
|
|
|
|
status = SRB_STATUS_SUCCESS;
|
|
}
|
|
|
|
break;
|
|
|
|
case SCSIOP_MODE_SENSE:
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: StartIo: ModeSense\n"));
|
|
|
|
cdb = (PCDB) Srb->Cdb;
|
|
|
|
if ((cdb->MODE_SENSE.PageCode != MODE_SENSE_RETURN_ALL) ||
|
|
(cdb->MODE_SENSE.AllocationLength != MODE_DATA_SIZE )) {
|
|
|
|
status = SRB_STATUS_INVALID_REQUEST;
|
|
break;
|
|
}
|
|
|
|
if (transferForbidden) {
|
|
status = SRB_STATUS_ERROR;
|
|
break;
|
|
}
|
|
|
|
// Set mode page data(only a geometry) for DISK class driver.
|
|
// DISK class driver get the geometry of all media(scsi ata) by mode sense.
|
|
pageData = Srb->DataBuffer;
|
|
|
|
((PMODE_PARAMETER_HEADER) pageData)->ModeDataLength = MODE_DATA_SIZE;
|
|
parameterHeaderLength = sizeof(MODE_PARAMETER_HEADER);
|
|
blockDescriptorLength = ((PMODE_PARAMETER_HEADER) pageData)->BlockDescriptorLength = 0x8;
|
|
|
|
pageData += parameterHeaderLength + blockDescriptorLength;
|
|
|
|
// MODE_PAGE_ERROR_RECOVERY data.
|
|
((PMODE_DISCONNECT_PAGE) pageData)->PageCode = MODE_PAGE_ERROR_RECOVERY;
|
|
((PMODE_DISCONNECT_PAGE) pageData)->PageLength = 0x6;
|
|
|
|
// Advance to the next page.
|
|
pageData += ((PMODE_DISCONNECT_PAGE) pageData)->PageLength + 2;
|
|
|
|
// MODE_PAGE_FORMAT_DEVICE data set.
|
|
((PMODE_DISCONNECT_PAGE) pageData)->PageCode = MODE_PAGE_FORMAT_DEVICE;
|
|
((PMODE_DISCONNECT_PAGE) pageData)->PageLength = 0x16;
|
|
|
|
// SectorsPerTrack
|
|
((PFOUR_BYTE)&((PMODE_FORMAT_PAGE) pageData)->SectorsPerTrack[0])->Byte1
|
|
= ((PFOUR_BYTE)&deviceExtension->SectorsPerTrack)->Byte0;
|
|
|
|
((PFOUR_BYTE)&((PMODE_FORMAT_PAGE) pageData)->SectorsPerTrack[0])->Byte0
|
|
= ((PFOUR_BYTE)&deviceExtension->SectorsPerTrack)->Byte1;
|
|
|
|
// Advance to the next page.
|
|
pageData += ((PMODE_DISCONNECT_PAGE) pageData)->PageLength + 2;
|
|
|
|
// MODE_PAGE_RIGID_GEOMETRY data set.
|
|
((PMODE_DISCONNECT_PAGE) pageData)->PageCode = MODE_PAGE_RIGID_GEOMETRY;
|
|
((PMODE_DISCONNECT_PAGE) pageData)->PageLength = 0x12;
|
|
|
|
// NumberOfHeads
|
|
((PMODE_RIGID_GEOMETRY_PAGE) pageData)->NumberOfHeads
|
|
= (UCHAR)deviceExtension->NumberOfHeads;
|
|
|
|
// NumberOfCylindersfahjbbjknz
|
|
((PFOUR_BYTE)&((PMODE_RIGID_GEOMETRY_PAGE) pageData)->NumberOfCylinders)->Byte2
|
|
= ((PFOUR_BYTE)&deviceExtension->Cylinders)->Byte0;
|
|
((PFOUR_BYTE)&((PMODE_RIGID_GEOMETRY_PAGE) pageData)->NumberOfCylinders)->Byte1
|
|
= ((PFOUR_BYTE)&deviceExtension->Cylinders)->Byte1;
|
|
((PFOUR_BYTE)&((PMODE_RIGID_GEOMETRY_PAGE) pageData)->NumberOfCylinders)->Byte0
|
|
= ((PFOUR_BYTE)&deviceExtension->Cylinders)->Byte2;
|
|
Srb->DataTransferLength = MODE_DATA_SIZE;
|
|
status = SRB_STATUS_SUCCESS;
|
|
|
|
break;
|
|
|
|
case SCSIOP_TEST_UNIT_READY:
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: StartIo: TestUnitReady\n"));
|
|
status = SRB_STATUS_SUCCESS;
|
|
break;
|
|
|
|
case SCSIOP_READ_CAPACITY:
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: StartIo: ReadCapacity\n"));
|
|
|
|
if (transferForbidden) {
|
|
status = SRB_STATUS_ERROR;
|
|
break;
|
|
}
|
|
|
|
// Claim 512 byte blocks (big-endian).
|
|
((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000;
|
|
|
|
// Calculate last sector.
|
|
i = deviceExtension->totalSectors - 1;
|
|
|
|
((PFOUR_BYTE)& ((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress)->Byte0 =
|
|
((PFOUR_BYTE)&i)->Byte3;
|
|
((PFOUR_BYTE)& ((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress)->Byte1 =
|
|
((PFOUR_BYTE)&i)->Byte2;
|
|
((PFOUR_BYTE)& ((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress)->Byte2 =
|
|
((PFOUR_BYTE)&i)->Byte1;
|
|
((PFOUR_BYTE)& ((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress)->Byte3 =
|
|
((PFOUR_BYTE)&i)->Byte0;
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: StartIo: DiskOnChip %x - #sectors %x, #heads %x, #cylinders %x #total %x\n",
|
|
Srb->TargetId,
|
|
deviceExtension->SectorsPerTrack,
|
|
deviceExtension->NumberOfHeads,
|
|
deviceExtension->Cylinders,
|
|
i));
|
|
|
|
status = SRB_STATUS_SUCCESS;
|
|
break;
|
|
|
|
case SCSIOP_VERIFY:
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: StartIo: Verify\n"));
|
|
status = SRB_STATUS_SUCCESS;
|
|
break;
|
|
|
|
case SCSIOP_READ:
|
|
case SCSIOP_WRITE:
|
|
|
|
deviceExtension->DataBuffer = (PUSHORT)Srb->DataBuffer;
|
|
startingSector = ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte3 |
|
|
((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte2 << 8 |
|
|
((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte1 << 16 |
|
|
((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte0 << 24;
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: StartIo: ReadWrite: Starting sector is %x, Number of bytes %x\n",startingSector,Srb->DataTransferLength));
|
|
|
|
if (transferForbidden) {
|
|
status = SRB_STATUS_ERROR;
|
|
break;
|
|
}
|
|
|
|
ioreq.irHandle = deviceExtension->UnitNumber;
|
|
ioreq.irSectorNo = startingSector;
|
|
ioreq.irSectorCount = Srb->DataTransferLength >> SECTOR_SIZE_BITS;
|
|
ioreq.irData = deviceExtension->DataBuffer;
|
|
|
|
if (startingSector >= deviceExtension->totalSectors) {
|
|
tffsStatus = flSectorNotFound;
|
|
}
|
|
else {
|
|
if (Srb->SrbFlags & SRB_FLAGS_DATA_IN) {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: StartIo: Read\n"));
|
|
|
|
if(deviceExtension->IsWriteProtected && deviceExtension->IsPartitonTableWritten && (ioreq.irSectorNo == 0)){
|
|
tffscpy(deviceExtension->DataBuffer, deviceExtension->PartitonTable, sizeof(deviceExtension->PartitonTable));
|
|
tffsStatus = flOK;
|
|
status = (UCHAR)(tffsStatus == flOK) ? SRB_STATUS_SUCCESS : SRB_STATUS_ERROR;
|
|
|
|
}
|
|
else{
|
|
tffsStatus = flAbsRead(&ioreq);
|
|
if (irp->MdlAddress) {
|
|
KeFlushIoBuffers(irp->MdlAddress, TRUE, FALSE);
|
|
}
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: StartIo: Read status %Xh\n", tffsStatus));
|
|
status = (UCHAR)(tffsStatus == flOK) ? SRB_STATUS_SUCCESS : SRB_STATUS_ERROR;
|
|
}
|
|
}
|
|
else {
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: StartIo: Write\n"));
|
|
//Handle partiton table - simulate write to sector 0 (Volume Manager signature - write it to buffer in RAM) only once.
|
|
if((deviceExtension->IsWriteProtected || deviceExtension->IsSWWriteProtected) && (ioreq.irSectorNo == 0) && (deviceExtension->IsPartitonTableWritten == FALSE)){
|
|
tffscpy(deviceExtension->PartitonTable, deviceExtension->DataBuffer, sizeof(deviceExtension->PartitonTable));
|
|
deviceExtension->IsPartitonTableWritten = TRUE;
|
|
status = tffsStatus = STATUS_MEDIA_WRITE_PROTECTED;
|
|
//tffsStatus = flOK;
|
|
//status = SRB_STATUS_SUCCESS;
|
|
}//In case of writing to Write Protected Device
|
|
else if(deviceExtension->IsWriteProtected || deviceExtension->IsSWWriteProtected){
|
|
status = tffsStatus = STATUS_MEDIA_WRITE_PROTECTED;
|
|
}
|
|
else{
|
|
tffsStatus = flAbsWrite(&ioreq);
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: StartIo: Write status %Xh\n", tffsStatus));
|
|
//For the first time trying to write to SW protected media
|
|
if(tffsStatus==flWriteProtect){
|
|
deviceExtension->IsSWWriteProtected = TRUE;
|
|
if((ioreq.irSectorNo == 0) && (deviceExtension->IsPartitonTableWritten == FALSE)){
|
|
tffscpy(deviceExtension->PartitonTable, deviceExtension->DataBuffer, sizeof(deviceExtension->PartitonTable));
|
|
deviceExtension->IsPartitonTableWritten = TRUE;
|
|
}
|
|
status = tffsStatus = STATUS_MEDIA_WRITE_PROTECTED;
|
|
}
|
|
else
|
|
{
|
|
//status = (UCHAR)(tffsStatus == flOK) ? SRB_STATUS_SUCCESS : SRB_STATUS_ERROR;
|
|
if(tffsStatus==flOK)
|
|
status = SRB_STATUS_SUCCESS;
|
|
else
|
|
status = SRB_STATUS_ERROR;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: StartIo: ReadWrite status %Xh\n", tffsStatus));
|
|
//status = (UCHAR)(tffsStatus == flOK) ? SRB_STATUS_SUCCESS : SRB_STATUS_ERROR;
|
|
break;
|
|
|
|
case SCSIOP_START_STOP_UNIT:
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: StartIo: StartStopUnit\n"));
|
|
status = SRB_STATUS_SUCCESS;
|
|
break;
|
|
|
|
case SCSIOP_REQUEST_SENSE:
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: StartIo: RequestSense\n"));
|
|
// this function makes sense buffers to report the results
|
|
// of the original GET_MEDIA_STATUS command
|
|
// status = SRB_STATUS_SUCCESS;
|
|
break;
|
|
|
|
default:
|
|
|
|
TffsDebugPrint((TFFS_DEB_WARN,"Trueffs: StartIo: Unsupported command %Xh\n",Srb->Cdb[0]));
|
|
|
|
status = SRB_STATUS_INVALID_REQUEST;
|
|
|
|
} // end switch
|
|
|
|
break;
|
|
|
|
case SRB_FUNCTION_ABORT_COMMAND:
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: StartIo: AbortCommand\n"));
|
|
|
|
// Verify that SRB to abort is still outstanding.
|
|
if (!deviceExtension->CurrentSrb) {
|
|
|
|
TffsDebugPrint((TFFS_DEB_ERROR,"Trueffs: StartIo: SRB to abort already completed\n"));
|
|
status = SRB_STATUS_ABORT_FAILED;
|
|
break;
|
|
}
|
|
|
|
case SRB_FUNCTION_RESET_BUS:
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: StartIo: Reset bus request received\n"));
|
|
status = SRB_STATUS_SUCCESS;
|
|
break;
|
|
|
|
default:
|
|
|
|
// Indicate unsupported command.
|
|
TffsDebugPrint((TFFS_DEB_WARN,"Trueffs: StartIo: unsupported function\n"));
|
|
status = SRB_STATUS_INVALID_REQUEST;
|
|
break;
|
|
|
|
} // end switch
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: StartIo: Srb %Xh complete with status %Xh\n", Srb, status));
|
|
|
|
// Clear current SRB.
|
|
deviceExtension->CurrentSrb = NULL;
|
|
|
|
Srb->SrbStatus = (UCHAR)status;
|
|
|
|
if (status == SRB_STATUS_SUCCESS) {
|
|
irp->IoStatus.Information = Srb->DataTransferLength;
|
|
}
|
|
else {
|
|
irp->IoStatus.Information = 0;
|
|
}
|
|
|
|
// Restore the srb->DataBuffer if necesary
|
|
if (irp->MdlAddress != NULL) {
|
|
TffsDebugPrint((TFFS_DEB_INFO, "Trueffs: Restoration of Srb->DataBuffer done\n"));
|
|
Srb->DataBuffer = storedSrbDataBuffer;
|
|
}
|
|
|
|
irp->IoStatus.Status = TrueffsTranslateSRBStatus(status);
|
|
IoCompleteRequest( irp, IO_DISK_INCREMENT );
|
|
|
|
} // while there's packets to process
|
|
|
|
} while ( TRUE );
|
|
}
|
|
|
|
NTSTATUS
|
|
QueueIrpToThread(
|
|
IN OUT PIRP Irp,
|
|
IN OUT PDEVICE_EXTENSION deviceExtension
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine queues the given irp to be serviced by the Trueffs
|
|
thread. If the thread is down then this routine creates the thread.
|
|
|
|
Arguments:
|
|
|
|
Irp - Supplies the IRP to queue to the thread.
|
|
|
|
Return Value:
|
|
|
|
May return an error if PsCreateSystemThread fails.
|
|
Otherwise returns STATUS_PENDING and marks the IRP pending.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS status;
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: QueueIrpToThread\n"));
|
|
|
|
IoMarkIrpPending(Irp);
|
|
|
|
ExInterlockedInsertTailList(&deviceExtension->listEntry,&Irp->Tail.Overlay.ListEntry,&deviceExtension->listSpinLock);
|
|
|
|
if (!KeReadStateSemaphore(&deviceExtension->requestSemaphore)) {
|
|
KeReleaseSemaphore(&deviceExtension->requestSemaphore,(KPRIORITY) 0,1,FALSE);
|
|
}
|
|
|
|
TffsDebugPrint((TFFS_DEB_INFO,"Trueffs: QueueIrpToThread: Irp %Xh queued\n", Irp));
|
|
return STATUS_PENDING;
|
|
}
|
|
|
|
NTSTATUS
|
|
TrueffsTranslateSRBStatus(
|
|
ULONG status
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine translates an srb status into an ntstatus.
|
|
|
|
Arguments:
|
|
|
|
SRB status
|
|
|
|
Return Value:
|
|
|
|
An nt status approprate for the error.
|
|
|
|
--*/
|
|
|
|
{
|
|
switch (status) {
|
|
case SRB_STATUS_INTERNAL_ERROR:
|
|
return(STATUS_MEDIA_WRITE_PROTECTED); //(STATUS_WMI_READ_ONLY);
|
|
case SRB_STATUS_SELECTION_TIMEOUT:
|
|
return(STATUS_DEVICE_NOT_CONNECTED);
|
|
case SRB_STATUS_SUCCESS:
|
|
return (STATUS_SUCCESS);
|
|
case SRB_STATUS_INVALID_REQUEST:
|
|
return(STATUS_INVALID_DEVICE_REQUEST);
|
|
case SRB_STATUS_ABORT_FAILED:
|
|
default:
|
|
return(STATUS_DISK_OPERATION_FAILED);
|
|
}
|
|
return(STATUS_DISK_OPERATION_FAILED);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
TrueffsDeviceQueryId(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN OUT PIRP Irp,
|
|
BOOLEAN Fdo
|
|
)
|
|
{
|
|
PIO_STACK_LOCATION thisIrpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
PDEVICE_EXTENSION deviceExtension;
|
|
PWSTR idString = NULL;
|
|
BOOLEAN bHandled = TRUE;
|
|
NTSTATUS status;
|
|
|
|
if (Fdo)
|
|
{
|
|
deviceExtension = DeviceObject->DeviceExtension;
|
|
}
|
|
else
|
|
{
|
|
PPDO_EXTENSION pdoExtension = DeviceObject->DeviceExtension;
|
|
deviceExtension = pdoExtension->Pext;
|
|
}
|
|
|
|
switch (thisIrpSp->Parameters.QueryId.IdType)
|
|
{
|
|
case BusQueryDeviceID:
|
|
|
|
TffsDebugPrint ((TFFS_DEB_INFO, "Trueffs: QueryDeviceID\n"));
|
|
|
|
idString = DeviceBuildBusId(deviceExtension, Fdo);
|
|
break;
|
|
|
|
case BusQueryInstanceID:
|
|
|
|
TffsDebugPrint ((TFFS_DEB_INFO, "Trueffs: QueryInstanceID\n"));
|
|
|
|
idString = DeviceBuildInstanceId(deviceExtension, Fdo);
|
|
break;
|
|
|
|
case BusQueryCompatibleIDs:
|
|
|
|
TffsDebugPrint ((TFFS_DEB_INFO, "Trueffs: QueryCompatibleIDs\n"));
|
|
|
|
idString = DeviceBuildCompatibleId(deviceExtension, Fdo);
|
|
break;
|
|
|
|
case BusQueryHardwareIDs:
|
|
|
|
TffsDebugPrint ((TFFS_DEB_INFO, "Trueffs: QueryHardwareIDs\n"));
|
|
|
|
idString = DeviceBuildHardwareId(deviceExtension, Fdo);
|
|
break;
|
|
|
|
default:
|
|
|
|
//
|
|
// The PDO should complete this request without altering its status
|
|
//
|
|
status = Irp->IoStatus.Status;
|
|
|
|
bHandled = FALSE;
|
|
break;
|
|
}
|
|
|
|
if (bHandled)
|
|
{
|
|
if (idString == NULL)
|
|
{
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
bHandled = FALSE;
|
|
}
|
|
}
|
|
|
|
if (bHandled)
|
|
{
|
|
if (Fdo)
|
|
{
|
|
//
|
|
// Forward this request down synchronously, in case a lower driver wants to handle it
|
|
//
|
|
IoCopyCurrentIrpStackLocationToNext(Irp);
|
|
status = TrueffsCallDriverSync(deviceExtension->LowerDeviceObject, Irp);
|
|
|
|
if (status == STATUS_NOT_SUPPORTED)
|
|
{
|
|
Irp->IoStatus.Information = (UINT_PTR) idString;
|
|
status = STATUS_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Someone lower down took care of this request
|
|
//
|
|
ExFreePool(idString);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Irp->IoStatus.Information = (UINT_PTR) idString;
|
|
status = STATUS_SUCCESS;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (Fdo)
|
|
{
|
|
//
|
|
// Forward this request down synchronously, in case a lower driver understands it
|
|
//
|
|
IoCopyCurrentIrpStackLocationToNext(Irp);
|
|
status = TrueffsCallDriverSync(deviceExtension->LowerDeviceObject, Irp);
|
|
}
|
|
}
|
|
|
|
Irp->IoStatus.Status = status;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
return status;
|
|
}
|
|
|
|
|
|
PWSTR
|
|
DeviceBuildBusId(
|
|
IN PDEVICE_EXTENSION deviceExtension,
|
|
BOOLEAN Fdo
|
|
)
|
|
{
|
|
PUCHAR idString;
|
|
PCSTR compatibleIdString;
|
|
CCHAR compatibleId[10];
|
|
ULONG compatibleIdLen;
|
|
USHORT idStringBufLen;
|
|
NTSTATUS status;
|
|
UCHAR tffsBusIdFormat[] = "FlashMedia\\%s_%s_%s%s_%s";
|
|
PWCHAR typeString;
|
|
ANSI_STRING ansiBusIdString;
|
|
UNICODE_STRING unicodeIdString;
|
|
|
|
if (Fdo) {
|
|
compatibleIdString = TrueffsGetCompatibleIdStringFDO (
|
|
deviceExtension->ScsiDeviceType
|
|
);
|
|
}
|
|
else {
|
|
compatibleIdString = TrueffsGetCompatibleIdString (
|
|
deviceExtension->ScsiDeviceType
|
|
);
|
|
}
|
|
|
|
if (compatibleIdString == NULL) {
|
|
sprintf (compatibleId,
|
|
"Type%d",
|
|
deviceExtension->ScsiDeviceType);
|
|
compatibleIdString = compatibleId;
|
|
}
|
|
compatibleIdLen = strlen(compatibleIdString);
|
|
|
|
idStringBufLen = (USHORT) (( strlen( tffsBusIdFormat ) +
|
|
compatibleIdLen +
|
|
VENDORSTRINGSIZE +
|
|
PRODUCTSTRINGSIZE +
|
|
REVISIONSTRINGSIZE +
|
|
SERIALSTRINGSIZE +
|
|
1) * sizeof( WCHAR ));
|
|
|
|
idString = ExAllocatePoolWithTag( PagedPool, idStringBufLen * 2, TFFSPORT_POOL_TAG);
|
|
|
|
if (idString){
|
|
|
|
sprintf (idString + idStringBufLen,
|
|
tffsBusIdFormat,
|
|
compatibleIdString,
|
|
VENDORSTRING,
|
|
PRODUCTSTRING,
|
|
REVISIONSTRING,
|
|
SERIALSTRING
|
|
);
|
|
|
|
RtlInitAnsiString (
|
|
&ansiBusIdString,
|
|
idString + idStringBufLen
|
|
);
|
|
|
|
unicodeIdString.Length = 0;
|
|
unicodeIdString.MaximumLength = idStringBufLen;
|
|
unicodeIdString.Buffer = (PWSTR) idString;
|
|
|
|
RtlAnsiStringToUnicodeString(
|
|
&unicodeIdString,
|
|
&ansiBusIdString,
|
|
FALSE
|
|
);
|
|
|
|
unicodeIdString.Buffer[unicodeIdString.Length/2 + 0] = L'\0';
|
|
}
|
|
|
|
return (PWSTR) idString;
|
|
}
|
|
|
|
PWSTR
|
|
DeviceBuildInstanceId(
|
|
IN PDEVICE_EXTENSION deviceExtension,
|
|
BOOLEAN Fdo
|
|
)
|
|
{
|
|
PWSTR idString;
|
|
ULONG idStringBufLen;
|
|
NTSTATUS status;
|
|
WCHAR tffsUniqueIdFormat[] = L"%x.%x.%x";
|
|
UCHAR firstId = 'A';
|
|
UCHAR secondId = 'G';
|
|
|
|
idStringBufLen = 50 * sizeof( WCHAR );
|
|
idString = ExAllocatePoolWithTag (PagedPool, idStringBufLen, TFFSPORT_POOL_TAG);
|
|
if( idString == NULL ){
|
|
|
|
return NULL;
|
|
}
|
|
|
|
// Form the string and return it.
|
|
swprintf( idString,
|
|
tffsUniqueIdFormat,
|
|
firstId,
|
|
secondId,
|
|
deviceExtension->TrueffsDeviceNumber);
|
|
|
|
return idString;
|
|
}
|
|
|
|
|
|
PWSTR
|
|
DeviceBuildCompatibleId(
|
|
IN PDEVICE_EXTENSION deviceExtension,
|
|
BOOLEAN Fdo
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
|
|
ULONG idStringBufLen;
|
|
PCSTR compatibleIdString;
|
|
|
|
ANSI_STRING ansiCompatibleIdString;
|
|
UNICODE_STRING unicodeIdString;
|
|
|
|
if (Fdo) {
|
|
compatibleIdString = TrueffsGetCompatibleIdStringFDO (deviceExtension->ScsiDeviceType);
|
|
}
|
|
else {
|
|
compatibleIdString = TrueffsGetCompatibleIdString (deviceExtension->ScsiDeviceType);
|
|
}
|
|
|
|
|
|
RtlInitAnsiString (
|
|
&ansiCompatibleIdString,
|
|
compatibleIdString
|
|
);
|
|
|
|
idStringBufLen = RtlAnsiStringToUnicodeSize (
|
|
&ansiCompatibleIdString
|
|
);
|
|
|
|
unicodeIdString.Length = 0;
|
|
unicodeIdString.MaximumLength = (USHORT) idStringBufLen;
|
|
|
|
idStringBufLen += 2 * sizeof (WCHAR);
|
|
|
|
unicodeIdString.Buffer = ExAllocatePoolWithTag (PagedPool, idStringBufLen, TFFSPORT_POOL_TAG);
|
|
|
|
if (unicodeIdString.Buffer) {
|
|
|
|
RtlAnsiStringToUnicodeString(
|
|
&unicodeIdString,
|
|
&ansiCompatibleIdString,
|
|
FALSE
|
|
);
|
|
|
|
unicodeIdString.Buffer[unicodeIdString.Length/2 + 0] = L'\0';
|
|
unicodeIdString.Buffer[unicodeIdString.Length/2 + 1] = L'\0';
|
|
}
|
|
|
|
return unicodeIdString.Buffer;
|
|
}
|
|
|
|
PWSTR
|
|
DeviceBuildHardwareId(
|
|
IN PDEVICE_EXTENSION deviceExtension,
|
|
BOOLEAN Fdo
|
|
)
|
|
{
|
|
#define NUMBER_HARDWARE_STRINGS 5
|
|
|
|
ULONG i;
|
|
PWSTR idMultiString;
|
|
PWSTR idString;
|
|
UCHAR scratch[64] = { 0 };
|
|
ULONG idStringLen;
|
|
NTSTATUS status;
|
|
ANSI_STRING ansiCompatibleIdString;
|
|
UNICODE_STRING unicodeIdString;
|
|
|
|
PCSTR deviceTypeCompIdString;
|
|
UCHAR deviceTypeCompId[20];
|
|
PCSTR deviceTypeIdString;
|
|
UCHAR deviceTypeId[20];
|
|
|
|
UCHAR ScsiDeviceType;
|
|
|
|
ScsiDeviceType = deviceExtension->ScsiDeviceType;
|
|
|
|
idStringLen = (64 * NUMBER_HARDWARE_STRINGS + sizeof (UCHAR)) * sizeof (WCHAR);
|
|
idMultiString = ExAllocatePoolWithTag (PagedPool, idStringLen, TFFSPORT_POOL_TAG);
|
|
if (idMultiString == NULL) {
|
|
|
|
return NULL;
|
|
}
|
|
|
|
if (Fdo) {
|
|
deviceTypeIdString = TrueffsGetDeviceTypeStringFDO(ScsiDeviceType);
|
|
}
|
|
else {
|
|
deviceTypeIdString = TrueffsGetDeviceTypeString(ScsiDeviceType);
|
|
}
|
|
|
|
if (deviceTypeIdString == NULL) {
|
|
|
|
sprintf (deviceTypeId,
|
|
"Type%d",
|
|
ScsiDeviceType);
|
|
|
|
deviceTypeIdString = deviceTypeId;
|
|
}
|
|
|
|
if (Fdo)
|
|
deviceTypeCompIdString = TrueffsGetCompatibleIdStringFDO (ScsiDeviceType);
|
|
else
|
|
deviceTypeCompIdString = TrueffsGetCompatibleIdString (ScsiDeviceType);
|
|
|
|
if (deviceTypeCompIdString == NULL) {
|
|
|
|
sprintf (deviceTypeCompId,
|
|
"GenType%d",
|
|
ScsiDeviceType);
|
|
|
|
deviceTypeCompIdString = deviceTypeCompId;
|
|
}
|
|
|
|
// Zero out the string buffer
|
|
RtlZeroMemory(idMultiString, idStringLen);
|
|
idString = idMultiString;
|
|
|
|
for(i = 0; i < NUMBER_HARDWARE_STRINGS; i++) {
|
|
|
|
// Build each of the hardware id's
|
|
switch(i) {
|
|
|
|
// Bus + Dev Type + Vendor + Product + Revision
|
|
case 0: {
|
|
|
|
sprintf(scratch, "FlashMedia\\%s", deviceTypeIdString);
|
|
|
|
CopyField(scratch + strlen(scratch),
|
|
VENDORSTRING,
|
|
VENDORSTRINGSIZE,
|
|
'_');
|
|
CopyField(scratch + strlen(scratch),
|
|
PRODUCTSTRING,
|
|
PRODUCTSTRINGSIZE,
|
|
'_');
|
|
CopyField(scratch + strlen(scratch),
|
|
REVISIONSTRING,
|
|
REVISIONSTRINGSIZE,
|
|
'_');
|
|
break;
|
|
}
|
|
|
|
// bus + vendor + product + revision[0]
|
|
case 1: {
|
|
|
|
sprintf(scratch, "FlashMedia\\");
|
|
|
|
CopyField(scratch + strlen(scratch),
|
|
VENDORSTRING,
|
|
VENDORSTRINGSIZE,
|
|
'_');
|
|
CopyField(scratch + strlen(scratch),
|
|
PRODUCTSTRING,
|
|
PRODUCTSTRINGSIZE,
|
|
'_');
|
|
CopyField(scratch + strlen(scratch),
|
|
REVISIONSTRING,
|
|
REVISIONSTRINGSIZE,
|
|
'_');
|
|
break;
|
|
}
|
|
|
|
// bus + device + vendor + product
|
|
case 2: {
|
|
|
|
sprintf(scratch, "FlashMedia\\%s", deviceTypeIdString);
|
|
|
|
CopyField(scratch + strlen(scratch),
|
|
VENDORSTRING,
|
|
VENDORSTRINGSIZE,
|
|
'_');
|
|
break;
|
|
}
|
|
|
|
// vendor + product + revision[0] (win9x)
|
|
case 3: {
|
|
|
|
CopyField(scratch,
|
|
VENDORSTRING,
|
|
VENDORSTRINGSIZE,
|
|
'_');
|
|
CopyField(scratch + strlen(scratch),
|
|
PRODUCTSTRING,
|
|
PRODUCTSTRINGSIZE,
|
|
'_');
|
|
CopyField(scratch + strlen(scratch),
|
|
REVISIONSTRING,
|
|
REVISIONSTRINGSIZE,
|
|
'_');
|
|
break;
|
|
}
|
|
|
|
case 4: {
|
|
|
|
strncpy(scratch, deviceTypeCompIdString, sizeof(scratch) - 1);
|
|
break;
|
|
}
|
|
|
|
default: {
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
RtlInitAnsiString (
|
|
&ansiCompatibleIdString,
|
|
scratch
|
|
);
|
|
|
|
unicodeIdString.Length = 0;
|
|
unicodeIdString.MaximumLength = (USHORT) RtlAnsiStringToUnicodeSize(
|
|
&ansiCompatibleIdString
|
|
);
|
|
unicodeIdString.Buffer = idString;
|
|
|
|
RtlAnsiStringToUnicodeString(
|
|
&unicodeIdString,
|
|
&ansiCompatibleIdString,
|
|
FALSE
|
|
);
|
|
|
|
idString[unicodeIdString.Length / 2] = L'\0';
|
|
idString += unicodeIdString.Length / 2+ 1;
|
|
}
|
|
idString[0] = L'\0';
|
|
|
|
return idMultiString;
|
|
|
|
#undef NUMBER_HARDWARE_STRINGS
|
|
}
|
|
|
|
|
|
VOID
|
|
CopyField(
|
|
IN PUCHAR Destination,
|
|
IN PUCHAR Source,
|
|
IN ULONG Count,
|
|
IN UCHAR Change
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine will copy Count string bytes from Source to Destination. If
|
|
it finds a nul byte in the Source it will translate that and any subsequent
|
|
bytes into Change. It will also replace spaces with the specified character.
|
|
|
|
Arguments:
|
|
|
|
Destination - the location to copy bytes
|
|
|
|
Source - the location to copy bytes from
|
|
|
|
Count - the number of bytes to be copied
|
|
|
|
Return Value:
|
|
|
|
none
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG i = 0;
|
|
BOOLEAN pastEnd = FALSE;
|
|
|
|
for(i = 0; i < Count; i++) {
|
|
if(!pastEnd) {
|
|
if(Source[i] == 0) {
|
|
pastEnd = TRUE;
|
|
Destination[i] = Change;
|
|
} else if(Source[i] == L' ') {
|
|
Destination[i] = Change;
|
|
} else {
|
|
Destination[i] = Source[i];
|
|
}
|
|
} else {
|
|
Destination[i] = Change;
|
|
}
|
|
}
|
|
Destination[i] = L'\0';
|
|
return;
|
|
}
|
|
|
|
|
|
PCSTR
|
|
TrueffsGetDeviceTypeString (
|
|
IN ULONG DeviceType
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
look up SCSI device type string
|
|
|
|
Arguments:
|
|
|
|
DeviceType - SCSI device type
|
|
|
|
Return Value:
|
|
|
|
device type string
|
|
|
|
--*/
|
|
{
|
|
if (DeviceType < (sizeof (TffsDeviceType_tffsport) / sizeof (TFFS_DEVICE_TYPE))) {
|
|
return TffsDeviceType_tffsport[DeviceType].DeviceTypeString;
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
PCSTR
|
|
TrueffsGetDeviceTypeStringFDO (
|
|
IN ULONG DeviceType
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
look up SCSI device type string
|
|
|
|
Arguments:
|
|
|
|
DeviceType - SCSI device type
|
|
|
|
Return Value:
|
|
|
|
device type string
|
|
|
|
--*/
|
|
{
|
|
if (DeviceType < (sizeof (TffsDeviceType_tffsport) / sizeof (TFFS_DEVICE_TYPE))) {
|
|
return TffsDeviceTypeFDO_tffsport[DeviceType].DeviceTypeString;
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
PCSTR
|
|
TrueffsGetCompatibleIdString (
|
|
IN ULONG DeviceType
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
look up compatible ID string
|
|
|
|
Arguments:
|
|
|
|
DeviceType - SCSI device type
|
|
|
|
Return Value:
|
|
|
|
compatible ID string
|
|
|
|
--*/
|
|
{
|
|
if (DeviceType < (sizeof (TffsDeviceType_tffsport) / sizeof (TFFS_DEVICE_TYPE))) {
|
|
return TffsDeviceType_tffsport[DeviceType].CompatibleIdString;
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
PCSTR
|
|
TrueffsGetCompatibleIdStringFDO (
|
|
IN ULONG DeviceType
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
look up compatible ID string
|
|
|
|
Arguments:
|
|
|
|
DeviceType - SCSI device type
|
|
|
|
Return Value:
|
|
|
|
compatible ID string
|
|
|
|
--*/
|
|
{
|
|
if (DeviceType < (sizeof (TffsDeviceType_tffsport) / sizeof (TFFS_DEVICE_TYPE))) {
|
|
return TffsDeviceTypeFDO_tffsport[DeviceType].CompatibleIdString;
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
PCSTR
|
|
TrueffsGetPeripheralIdString (
|
|
IN ULONG DeviceType
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
look up peripheral ID string
|
|
|
|
Arguments:
|
|
|
|
DeviceType - SCSI device type
|
|
|
|
Return Value:
|
|
|
|
Peripheral ID string
|
|
|
|
--*/
|
|
{
|
|
if (DeviceType < (sizeof (TffsDeviceType_tffsport) / sizeof (TFFS_DEVICE_TYPE))) {
|
|
return TffsDeviceType_tffsport[DeviceType].PeripheralIdString;
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
PCSTR
|
|
TrueffsGetPeripheralIdStringFDO (
|
|
IN ULONG DeviceType
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
look up peripheral ID string
|
|
|
|
Arguments:
|
|
|
|
DeviceType - SCSI device type
|
|
|
|
Return Value:
|
|
|
|
Peripheral ID string
|
|
|
|
--*/
|
|
{
|
|
if (DeviceType < (sizeof (TffsDeviceType_tffsport) / sizeof (TFFS_DEVICE_TYPE))) {
|
|
return TffsDeviceTypeFDO_tffsport[DeviceType].PeripheralIdString;
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
TrueffsQueryDeviceRelations (
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN OUT PIRP Irp,
|
|
BOOLEAN Fdo
|
|
)
|
|
{
|
|
PIO_STACK_LOCATION thisIrpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
PDEVICE_RELATIONS deviceRelations;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
if (Fdo)
|
|
{
|
|
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
|
|
|
|
switch (thisIrpSp->Parameters.QueryDeviceRelations.Type)
|
|
{
|
|
case BusRelations:
|
|
|
|
TffsDebugPrint ((TFFS_DEB_INFO,"Trueffs: QueryDeviceRelations: bus relations\n"));
|
|
|
|
if (deviceExtension->ChildPdo != NULL)
|
|
{
|
|
deviceRelations = ExAllocatePoolWithTag(NonPagedPool, sizeof(DEVICE_RELATIONS), TFFSPORT_POOL_TAG);
|
|
|
|
if (deviceRelations)
|
|
{
|
|
ObReferenceObject(deviceExtension->ChildPdo);
|
|
|
|
deviceRelations->Objects[0] = deviceExtension->ChildPdo;
|
|
deviceRelations->Count = 1;
|
|
|
|
Irp->IoStatus.Information = (ULONG_PTR) deviceRelations;
|
|
}
|
|
else
|
|
{
|
|
TffsDebugPrint ((TFFS_DEB_ERROR,"Trueffs: QueryDeviceRelations: Unable to allocate DeviceRelations structures\n"));
|
|
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
Irp->IoStatus.Information = (ULONG_PTR) NULL;
|
|
}
|
|
}
|
|
|
|
Irp->IoStatus.Status = status;
|
|
|
|
if (NT_SUCCESS(status))
|
|
{
|
|
//
|
|
// Send the request down in case a lower driver wants to append to the device relations
|
|
//
|
|
IoCopyCurrentIrpStackLocationToNext(Irp);
|
|
status = IoCallDriver(deviceExtension->LowerDeviceObject, Irp);
|
|
}
|
|
else
|
|
{
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
|
|
//
|
|
// Forward this request down, in case a lower driver understands it
|
|
//
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
status = IoCallDriver(deviceExtension->LowerDeviceObject, Irp);
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (thisIrpSp->Parameters.QueryDeviceRelations.Type)
|
|
{
|
|
case TargetDeviceRelation:
|
|
|
|
TffsDebugPrint ((TFFS_DEB_INFO,"Trueffs: QueryDeviceRelations: target relations\n"));
|
|
|
|
deviceRelations = ExAllocatePoolWithTag(NonPagedPool, sizeof(DEVICE_RELATIONS), TFFSPORT_POOL_TAG);
|
|
|
|
if (deviceRelations)
|
|
{
|
|
ObReferenceObject(DeviceObject);
|
|
|
|
deviceRelations->Objects[0] = DeviceObject;
|
|
deviceRelations->Count = 1;
|
|
|
|
Irp->IoStatus.Information = (ULONG_PTR) deviceRelations;
|
|
}
|
|
else
|
|
{
|
|
TffsDebugPrint ((TFFS_DEB_ERROR,"Trueffs: QueryDeviceRelations: Unable to allocate DeviceRelations structures\n"));
|
|
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
Irp->IoStatus.Information = (ULONG_PTR) NULL;
|
|
}
|
|
|
|
Irp->IoStatus.Status = status;
|
|
break;
|
|
|
|
default:
|
|
|
|
//
|
|
// Complete this request without altering its status
|
|
//
|
|
status = Irp->IoStatus.Status;
|
|
break;
|
|
}
|
|
|
|
Irp->IoStatus.Status = status;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
TrueffsOkToDetectLegacy (
|
|
IN PDRIVER_OBJECT DriverObject
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
ULONG legacyDetection;
|
|
|
|
status = TrueffsGetParameterFromServiceSubKey (
|
|
DriverObject,
|
|
LEGACY_DETECTION,
|
|
REG_DWORD,
|
|
TRUE,
|
|
(PVOID) &legacyDetection,
|
|
0
|
|
);
|
|
|
|
if (!NT_SUCCESS(status) || legacyDetection) {
|
|
return TRUE;
|
|
}
|
|
else {
|
|
return FALSE;
|
|
}
|
|
|
|
}
|
|
|
|
NTSTATUS
|
|
TrueffsGetParameterFromServiceSubKey (
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PWSTR ParameterName,
|
|
IN ULONG ParameterType,
|
|
IN BOOLEAN Read,
|
|
OUT PVOID *ParameterValue,
|
|
IN ULONG ParameterValueWriteSize
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
HANDLE deviceParameterHandle;
|
|
RTL_QUERY_REGISTRY_TABLE queryTable[2] = { 0 };
|
|
ULONG defaultParameterValue;
|
|
|
|
CCHAR deviceBuffer[50];
|
|
ANSI_STRING ansiString;
|
|
UNICODE_STRING subKeyPath;
|
|
HANDLE subServiceKey;
|
|
|
|
UNICODE_STRING unicodeParameterName;
|
|
|
|
RtlZeroMemory(ParameterValue, ParameterValueWriteSize);
|
|
|
|
sprintf (deviceBuffer, DRIVER_PARAMETER_SUBKEY);
|
|
RtlInitAnsiString(&ansiString, deviceBuffer);
|
|
status = RtlAnsiStringToUnicodeString(&subKeyPath, &ansiString, TRUE);
|
|
|
|
if (NT_SUCCESS(status)) {
|
|
|
|
subServiceKey = TrueffsOpenServiceSubKey (
|
|
DriverObject,
|
|
&subKeyPath
|
|
);
|
|
|
|
RtlFreeUnicodeString (&subKeyPath);
|
|
|
|
if (subServiceKey) {
|
|
|
|
if (Read) {
|
|
|
|
queryTable->QueryRoutine = TrueffsRegQueryRoutine;
|
|
queryTable->Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_NOEXPAND;
|
|
queryTable->Name = ParameterName;
|
|
queryTable->EntryContext = ParameterValue;
|
|
queryTable->DefaultType = 0;
|
|
queryTable->DefaultData = NULL;
|
|
queryTable->DefaultLength = 0;
|
|
status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
|
|
(PWSTR) subServiceKey,
|
|
queryTable,
|
|
ULongToPtr( ParameterType ),
|
|
NULL);
|
|
|
|
} else {
|
|
|
|
RtlInitUnicodeString (&unicodeParameterName, ParameterName);
|
|
status = ZwSetValueKey(
|
|
subServiceKey,
|
|
&unicodeParameterName,
|
|
0,
|
|
ParameterType,
|
|
ParameterValue,
|
|
ParameterValueWriteSize
|
|
);
|
|
}
|
|
|
|
// close what we open
|
|
TrueffsCloseServiceSubKey (
|
|
subServiceKey
|
|
);
|
|
}
|
|
}
|
|
return status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
TrueffsRegQueryRoutine (
|
|
IN PWSTR ValueName,
|
|
IN ULONG ValueType,
|
|
IN PVOID ValueData,
|
|
IN ULONG ValueLength,
|
|
IN PVOID Context,
|
|
IN PVOID EntryContext
|
|
)
|
|
{
|
|
PVOID *parameterValue = EntryContext;
|
|
ULONG parameterType = PtrToUlong(Context);
|
|
|
|
if (ValueType == parameterType) {
|
|
|
|
if (ValueType == REG_MULTI_SZ) {
|
|
|
|
*parameterValue = ExAllocatePoolWithTag(PagedPool, ValueLength, TFFSPORT_POOL_TAG);
|
|
if (*parameterValue) {
|
|
|
|
RtlMoveMemory(*parameterValue, ValueData, ValueLength);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
} else if (ValueType == REG_DWORD) {
|
|
|
|
PULONG ulongValue;
|
|
|
|
ulongValue = (PULONG) parameterValue;
|
|
*ulongValue = *((PULONG) ValueData);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
}
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
|
|
HANDLE
|
|
TrueffsOpenServiceSubKey (
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PUNICODE_STRING SubKeyPath
|
|
)
|
|
{
|
|
PTRUEFFSDRIVER_EXTENSION trueffsDriverExtension;
|
|
OBJECT_ATTRIBUTES objectAttributes;
|
|
HANDLE serviceKey;
|
|
HANDLE subServiceKey;
|
|
NTSTATUS status;
|
|
ULONG disposition;
|
|
|
|
trueffsDriverExtension = IoGetDriverObjectExtension(
|
|
DriverObject,
|
|
DRIVER_OBJECT_EXTENSION_ID
|
|
);
|
|
if (!trueffsDriverExtension) {
|
|
|
|
return NULL;
|
|
}
|
|
InitializeObjectAttributes(&objectAttributes,
|
|
&trueffsDriverExtension->RegistryPath,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
(PSECURITY_DESCRIPTOR) NULL);
|
|
|
|
status = ZwOpenKey(&serviceKey,
|
|
KEY_ALL_ACCESS,
|
|
&objectAttributes);
|
|
if (!NT_SUCCESS(status)) {
|
|
|
|
return NULL;
|
|
}
|
|
InitializeObjectAttributes(&objectAttributes,
|
|
SubKeyPath,
|
|
OBJ_CASE_INSENSITIVE,
|
|
serviceKey,
|
|
(PSECURITY_DESCRIPTOR) NULL);
|
|
|
|
status = ZwCreateKey(&subServiceKey,
|
|
KEY_READ | KEY_WRITE,
|
|
&objectAttributes,
|
|
0,
|
|
(PUNICODE_STRING) NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
&disposition);
|
|
|
|
ZwClose(serviceKey);
|
|
if (NT_SUCCESS(status)) {
|
|
|
|
return subServiceKey;
|
|
} else {
|
|
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
TrueffsCloseServiceSubKey (
|
|
IN HANDLE SubServiceKey
|
|
)
|
|
{
|
|
ZwClose(SubServiceKey);
|
|
}
|
|
|
|
|
|
PPDO_EXTENSION
|
|
AllocatePdo(
|
|
IN PDEVICE_EXTENSION FdoExtension
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create physical device object
|
|
|
|
Arguments:
|
|
|
|
DeviceExtension
|
|
|
|
Return Value:
|
|
|
|
Physical device object
|
|
|
|
|
|
--*/
|
|
{
|
|
PDEVICE_OBJECT physicalDeviceObject = NULL;
|
|
PPDO_EXTENSION pdoExtension;
|
|
NTSTATUS status;
|
|
STRING deviceName;
|
|
CCHAR deviceNameBuffer[64];
|
|
UNICODE_STRING unicodeDeviceNameString;
|
|
|
|
sprintf(deviceNameBuffer, "\\Device\\TrueffsDevice%d",
|
|
FdoExtension->TrueffsDeviceNumber
|
|
);
|
|
RtlInitString(&deviceName, deviceNameBuffer);
|
|
status = RtlAnsiStringToUnicodeString(&unicodeDeviceNameString,
|
|
&deviceName,
|
|
TRUE);
|
|
if (!NT_SUCCESS (status)) {
|
|
|
|
return NULL;
|
|
}
|
|
|
|
status = IoCreateDevice(
|
|
FdoExtension->DriverObject, // our driver object
|
|
sizeof(PDO_EXTENSION), // size of our extension
|
|
&unicodeDeviceNameString, // our name
|
|
FILE_DEVICE_DISK, // device type
|
|
FILE_DEVICE_SECURE_OPEN, // device characteristics
|
|
FALSE, // not exclusive
|
|
&physicalDeviceObject // store new device object here
|
|
);
|
|
|
|
if (NT_SUCCESS(status)) {
|
|
|
|
pdoExtension = physicalDeviceObject->DeviceExtension;
|
|
RtlZeroMemory (pdoExtension, sizeof(PDO_EXTENSION));
|
|
pdoExtension->DeviceObject = physicalDeviceObject;
|
|
pdoExtension->DriverObject = FdoExtension->DriverObject;
|
|
pdoExtension->Pext = FdoExtension;
|
|
pdoExtension->SystemPowerState = PowerSystemWorking;
|
|
pdoExtension->DevicePowerState = PowerDeviceD0;
|
|
|
|
}
|
|
RtlFreeUnicodeString (&unicodeDeviceNameString);
|
|
|
|
if (physicalDeviceObject == NULL) {
|
|
|
|
return NULL;
|
|
}
|
|
FdoExtension->ChildPdo = physicalDeviceObject;
|
|
physicalDeviceObject->Flags |= DO_DIRECT_IO;
|
|
physicalDeviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT;
|
|
physicalDeviceObject->Flags &=~DO_DEVICE_INITIALIZING;
|
|
|
|
return pdoExtension;
|
|
}
|
|
|
|
NTSTATUS
|
|
TrueffsDeviceQueryCapabilities(IN PDEVICE_EXTENSION deviceExtension,
|
|
IN PDEVICE_CAPABILITIES Capabilities
|
|
)
|
|
{
|
|
|
|
Capabilities->UniqueID = FALSE;
|
|
Capabilities->LockSupported = FALSE;
|
|
Capabilities->EjectSupported = FALSE;
|
|
Capabilities->DockDevice = FALSE;
|
|
Capabilities->SilentInstall = FALSE;
|
|
Capabilities->RawDeviceOK = FALSE;
|
|
|
|
Capabilities->Removable = deviceExtension->removableMedia;
|
|
Capabilities->DeviceState[PowerSystemSleeping1] = PowerDeviceD3;
|
|
Capabilities->DeviceState[PowerSystemSleeping2] = PowerDeviceD3;
|
|
Capabilities->DeviceState[PowerSystemSleeping3] = PowerDeviceD3;
|
|
Capabilities->DeviceState[PowerSystemHibernate] = PowerDeviceD3;
|
|
|
|
Capabilities->SystemWake = PowerSystemUnspecified;
|
|
Capabilities->DeviceWake = PowerDeviceUnspecified;
|
|
Capabilities->D1Latency = 0;
|
|
Capabilities->D2Latency = 0;
|
|
Capabilities->D3Latency = 10; // 1ms
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
typedef enum {
|
|
FlashDiskInfo = 0
|
|
} WMI_DATA_BLOCK_TYPE;
|
|
|
|
#define MOFRESOURCENAME L"MofResourceName"
|
|
|
|
#define NUMBER_OF_WMI_GUID 1
|
|
WMIGUIDREGINFO TrueffsWmiGuidList[NUMBER_OF_WMI_GUID];
|
|
|
|
|
|
VOID
|
|
TrueffsWmiInit (VOID)
|
|
{
|
|
TrueffsWmiGuidList[FlashDiskInfo].Guid = &WmiTffsportAddressGuid;
|
|
TrueffsWmiGuidList[FlashDiskInfo].InstanceCount = 1;
|
|
TrueffsWmiGuidList[FlashDiskInfo].Flags = 0;
|
|
return;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
TrueffsWmiRegister(
|
|
PDEVICE_EXTENSION_HEADER DevExtension
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
|
|
DevExtension->WmiLibInfo.GuidCount = NUMBER_OF_WMI_GUID;
|
|
DevExtension->WmiLibInfo.GuidList = TrueffsWmiGuidList;
|
|
|
|
DevExtension->WmiLibInfo.QueryWmiDataBlock = TrueffsQueryWmiDataBlock;
|
|
DevExtension->WmiLibInfo.QueryWmiRegInfo = TrueffsQueryWmiRegInfo;
|
|
DevExtension->WmiLibInfo.SetWmiDataBlock = TrueffsSetWmiDataBlock;
|
|
DevExtension->WmiLibInfo.SetWmiDataItem = TrueffsSetWmiDataItem;
|
|
DevExtension->WmiLibInfo.ExecuteWmiMethod = NULL;
|
|
DevExtension->WmiLibInfo.WmiFunctionControl = NULL;
|
|
|
|
status = IoWMIRegistrationControl(DevExtension->DeviceObject,WMIREG_ACTION_REGISTER);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
TffsDebugPrint((TFFS_DEB_ERROR,
|
|
"TrueffsWmiRegister: IoWMIRegistrationControl(%x, WMI_ACTION_REGISTER) failed\n",
|
|
DevExtension->DeviceObject));
|
|
}
|
|
return status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
TrueffsWmiDeregister(
|
|
PDEVICE_EXTENSION_HEADER DevExtension
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
|
|
status = IoWMIRegistrationControl(DevExtension->DeviceObject,WMIREG_ACTION_DEREGISTER);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
TffsDebugPrint((TFFS_DEB_ERROR,
|
|
"TrueffsWmiRegister: IoWMIRegistrationControl(%x, WMIREG_ACTION_DEREGISTER) failed\n",
|
|
DevExtension->DeviceObject));
|
|
}
|
|
return status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
TrueffsWmiSystemControl(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
/*++
|
|
Routine Description
|
|
|
|
We have just received a System Control IRP.
|
|
|
|
Assume that this is a WMI IRP and call into the WMI system library and let
|
|
it handle this IRP for us.
|
|
|
|
--*/
|
|
{
|
|
PPDO_EXTENSION pdoExtension;
|
|
SYSCTL_IRP_DISPOSITION disposition;
|
|
NTSTATUS status;
|
|
|
|
pdoExtension = DeviceObject->DeviceExtension;
|
|
if (pdoExtension) {
|
|
|
|
status = WmiSystemControl(&pdoExtension->WmiLibInfo,
|
|
DeviceObject,
|
|
Irp,
|
|
&disposition);
|
|
switch(disposition)
|
|
{
|
|
case IrpProcessed:
|
|
{
|
|
// This irp has been processed and may be completed or pending.
|
|
break;
|
|
}
|
|
|
|
case IrpNotCompleted:
|
|
{
|
|
// This irp has not been completed, but has been fully
|
|
// processed. We will complete it now
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
break;
|
|
}
|
|
|
|
case IrpForward:
|
|
case IrpNotWmi:
|
|
default:
|
|
{
|
|
Irp->IoStatus.Status = status = STATUS_NOT_SUPPORTED;
|
|
IoCompleteRequest( Irp, IO_NO_INCREMENT );
|
|
break;
|
|
}
|
|
}
|
|
|
|
} else {
|
|
|
|
Irp->IoStatus.Status = status = STATUS_UNSUCCESSFUL;
|
|
IoCompleteRequest( Irp, IO_NO_INCREMENT );
|
|
}
|
|
return status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
TrueffsQueryWmiDataBlock(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN ULONG GuidIndex,
|
|
IN ULONG InstanceIndex,
|
|
IN ULONG InstanceCount,
|
|
IN OUT PULONG InstanceLengthArray,
|
|
IN ULONG OutBufferSize,
|
|
OUT PUCHAR Buffer
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is a callback into the driver to query for the contents of
|
|
a data block. When the driver has finished filling the data block it
|
|
must call ClassWmiCompleteRequest to complete the irp. The driver can
|
|
return STATUS_PENDING if the irp cannot be completed immediately.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject is the device whose data block is being queried
|
|
|
|
Irp is the Irp that makes this request
|
|
|
|
GuidIndex is the index into the list of guids provided when the
|
|
device registered
|
|
|
|
InstanceIndex is the index that denotes which instance of the data block
|
|
is being queried.
|
|
|
|
InstanceCount is the number of instances expected to be returned for
|
|
the data block.
|
|
|
|
InstanceLengthArray is a pointer to an array of ULONG that returns the
|
|
lengths of each instance of the data block. If this is NULL then
|
|
there was not enough space in the output buffer to fufill the request
|
|
so the irp should be completed with the buffer needed.
|
|
|
|
BufferAvail on has the maximum size available to write the data
|
|
block.
|
|
|
|
Buffer on return is filled with the returned data block
|
|
|
|
|
|
Return Value:
|
|
|
|
status
|
|
|
|
--*/
|
|
{
|
|
PPDO_EXTENSION pdoExtension;
|
|
NTSTATUS status;
|
|
ULONG numBytesReturned = sizeof(WMI_FLASH_DISK_INFO);
|
|
|
|
pdoExtension = DeviceObject->DeviceExtension;
|
|
|
|
if (!pdoExtension) {
|
|
|
|
Irp->IoStatus.Status = status = STATUS_UNSUCCESSFUL;
|
|
IoCompleteRequest( Irp, IO_NO_INCREMENT );
|
|
return status;
|
|
}
|
|
|
|
switch (GuidIndex) {
|
|
case FlashDiskInfo: {
|
|
|
|
PWMI_FLASH_DISK_INFO flashDiskInfo;
|
|
|
|
if (OutBufferSize < sizeof(WMI_FLASH_DISK_INFO)) {
|
|
status = STATUS_BUFFER_TOO_SMALL;
|
|
|
|
} else {
|
|
|
|
flashDiskInfo = (PWMI_FLASH_DISK_INFO) Buffer;
|
|
|
|
flashDiskInfo->Number = pdoExtension->Pext->TrueffsDeviceNumber;
|
|
flashDiskInfo->Address = (ULONG) pdoExtension->Pext->pcmciaParams.physWindow;
|
|
flashDiskInfo->Size = pdoExtension->Pext->pcmciaParams.windowSize;
|
|
|
|
*InstanceLengthArray = sizeof(WMI_FLASH_DISK_INFO);
|
|
status = STATUS_SUCCESS;
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
status = STATUS_WMI_GUID_NOT_FOUND;
|
|
break;
|
|
}
|
|
|
|
status = WmiCompleteRequest( DeviceObject,
|
|
Irp,
|
|
status,
|
|
numBytesReturned,
|
|
IO_NO_INCREMENT
|
|
);
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
TrueffsQueryWmiRegInfo(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
OUT PULONG RegFlags,
|
|
OUT PUNICODE_STRING InstanceName,
|
|
OUT PUNICODE_STRING *RegistryPath,
|
|
OUT PUNICODE_STRING MofResourceName,
|
|
OUT PDEVICE_OBJECT *Pdo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is a callback into the driver to retrieve the list of
|
|
guids or data blocks that the driver wants to register with WMI. This
|
|
routine may not pend or block. Driver should NOT call
|
|
ClassWmiCompleteRequest.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject is the device whose data block is being queried
|
|
|
|
*RegFlags returns with a set of flags that describe the guids being
|
|
registered for this device. If the device wants enable and disable
|
|
collection callbacks before receiving queries for the registered
|
|
guids then it should return the WMIREG_FLAG_EXPENSIVE flag. Also the
|
|
returned flags may specify WMIREG_FLAG_INSTANCE_PDO in which case
|
|
the instance name is determined from the PDO associated with the
|
|
device object. Note that the PDO must have an associated devnode. If
|
|
WMIREG_FLAG_INSTANCE_PDO is not set then Name must return a unique
|
|
name for the device.
|
|
|
|
InstanceName returns with the instance name for the guids if
|
|
WMIREG_FLAG_INSTANCE_PDO is not set in the returned *RegFlags. The
|
|
caller will call ExFreePool with the buffer returned.
|
|
|
|
*RegistryPath returns with the registry path of the driver
|
|
|
|
*MofResourceName returns with the name of the MOF resource attached to
|
|
the binary file. If the driver does not have a mof resource attached
|
|
then this can be returned as NULL.
|
|
|
|
*Pdo returns with the device object for the PDO associated with this
|
|
device if the WMIREG_FLAG_INSTANCE_PDO flag is retured in
|
|
*RegFlags.
|
|
|
|
Return Value:
|
|
|
|
status
|
|
|
|
--*/
|
|
{
|
|
PTRUEFFSDRIVER_EXTENSION trueffsDriverExtension;
|
|
PPDO_EXTENSION pdoExtension;
|
|
NTSTATUS status;
|
|
|
|
pdoExtension = DeviceObject->DeviceExtension;
|
|
|
|
if (!pdoExtension) {
|
|
|
|
status = STATUS_UNSUCCESSFUL;
|
|
} else {
|
|
|
|
trueffsDriverExtension = IoGetDriverObjectExtension(
|
|
pdoExtension->DriverObject,
|
|
DRIVER_OBJECT_EXTENSION_ID
|
|
);
|
|
|
|
if (!trueffsDriverExtension) {
|
|
|
|
status = STATUS_UNSUCCESSFUL;
|
|
|
|
} else {
|
|
|
|
*RegFlags = WMIREG_FLAG_INSTANCE_PDO;
|
|
*RegistryPath = &trueffsDriverExtension->RegistryPath;
|
|
*Pdo = pdoExtension->DeviceObject;
|
|
RtlInitUnicodeString(MofResourceName, MOFRESOURCENAME);
|
|
status = STATUS_SUCCESS;
|
|
}
|
|
}
|
|
return status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
TrueffsSetWmiDataBlock(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN ULONG GuidIndex,
|
|
IN ULONG InstanceIndex,
|
|
IN ULONG BufferSize,
|
|
IN PUCHAR Buffer
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is a callback into the driver to set the contents of
|
|
a data block. When the driver has finished filling the data block it
|
|
must call ClassWmiCompleteRequest to complete the irp. The driver can
|
|
return STATUS_PENDING if the irp cannot be completed immediately.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject is the device whose data block is being queried
|
|
|
|
Irp is the Irp that makes this request
|
|
|
|
GuidIndex is the index into the list of guids provided when the
|
|
device registered
|
|
|
|
InstanceIndex is the index that denotes which instance of the data block
|
|
is being set.
|
|
|
|
BufferSize has the size of the data block passed
|
|
|
|
Buffer has the new values for the data block
|
|
|
|
|
|
Return Value:
|
|
|
|
status
|
|
|
|
--*/
|
|
{
|
|
PPDO_EXTENSION pdoExtension;
|
|
NTSTATUS status;
|
|
|
|
pdoExtension = DeviceObject->DeviceExtension;
|
|
|
|
if (!pdoExtension) {
|
|
|
|
status = STATUS_UNSUCCESSFUL;
|
|
} else {
|
|
|
|
switch (GuidIndex) {
|
|
case FlashDiskInfo: {
|
|
status = /*STATUS_WMI_READ_ONLY;*/ STATUS_INVALID_DEVICE_REQUEST;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
status = STATUS_WMI_GUID_NOT_FOUND;
|
|
}
|
|
status = WmiCompleteRequest( DeviceObject,
|
|
Irp,
|
|
status,
|
|
0,
|
|
IO_NO_INCREMENT
|
|
);
|
|
|
|
}
|
|
return status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
TrueffsSetWmiDataItem(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN ULONG GuidIndex,
|
|
IN ULONG InstanceIndex,
|
|
IN ULONG DataItemId,
|
|
IN ULONG BufferSize,
|
|
IN PUCHAR Buffer
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is a callback into the driver to set for the contents of
|
|
a data block. When the driver has finished filling the data block it
|
|
must call ClassWmiCompleteRequest to complete the irp. The driver can
|
|
return STATUS_PENDING if the irp cannot be completed immediately.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject is the device whose data block is being queried
|
|
|
|
Irp is the Irp that makes this request
|
|
|
|
GuidIndex is the index into the list of guids provided when the
|
|
device registered
|
|
|
|
InstanceIndex is the index that denotes which instance of the data block
|
|
is being set.
|
|
|
|
DataItemId has the id of the data item being set
|
|
|
|
BufferSize has the size of the data item passed
|
|
|
|
Buffer has the new values for the data item
|
|
|
|
|
|
Return Value:
|
|
|
|
status
|
|
|
|
--*/
|
|
{
|
|
PPDO_EXTENSION pdoExtension;
|
|
NTSTATUS status;
|
|
|
|
pdoExtension = DeviceObject->DeviceExtension;
|
|
|
|
if (!pdoExtension) {
|
|
|
|
status = STATUS_UNSUCCESSFUL;
|
|
} else {
|
|
|
|
switch(GuidIndex) {
|
|
|
|
case FlashDiskInfo: {
|
|
status = /*STATUS_WMI_READ_ONLY;*/ STATUS_INVALID_DEVICE_REQUEST;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
status = STATUS_WMI_GUID_NOT_FOUND;
|
|
break;
|
|
}
|
|
status = WmiCompleteRequest( DeviceObject,
|
|
Irp,
|
|
status,
|
|
0,
|
|
IO_NO_INCREMENT
|
|
);
|
|
|
|
}
|
|
return status;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
DebugLogEvent(IN PDRIVER_OBJECT DriverObject, IN ULONG Value)
|
|
{
|
|
NTSTATUS status;
|
|
ULONG DebugValue = Value;
|
|
|
|
DebugValue++;
|
|
|
|
// write registry debug value
|
|
status = TrueffsGetParameterFromServiceSubKey(DriverObject,
|
|
L"DebugValue",
|
|
REG_DWORD,
|
|
FALSE,
|
|
(PVOID) &DebugValue,
|
|
sizeof(DebugValue));
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
#if DBG
|
|
|
|
ULONG TffsDebugPrintLevel = TFFS_DEB_ERROR;
|
|
|
|
VOID
|
|
TrueffsDebugPrint(ULONG DebugPrintLevel, PCHAR DebugMessage, ...)
|
|
{
|
|
va_list ap;
|
|
|
|
va_start(ap, DebugMessage);
|
|
|
|
if (DebugPrintLevel & TffsDebugPrintLevel)
|
|
{
|
|
DbgPrint(DebugMessage, ap);
|
|
}
|
|
|
|
va_end(ap);
|
|
}
|
|
|
|
VOID
|
|
PRINTF(PCHAR DebugMessage, ...)
|
|
{
|
|
va_list ap;
|
|
|
|
va_start(ap, DebugMessage);
|
|
|
|
TrueffsDebugPrint(TFFS_DEB_INFO, DebugMessage, ap);
|
|
|
|
va_end(ap);
|
|
}
|
|
|
|
#else
|
|
|
|
VOID
|
|
PRINTF(PCHAR DebugMessage, ...)
|
|
{
|
|
}
|
|
|
|
#endif
|