mirror of
https://github.com/reactos/reactos.git
synced 2024-12-29 10:35:28 +00:00
187 lines
6.1 KiB
C
187 lines
6.1 KiB
C
/*++
|
|
|
|
Copyright (C) Microsoft Corporation. All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
mmc.h
|
|
|
|
Abstract:
|
|
|
|
Functions/macros for using the scratch buffer and scratch request/SRB
|
|
in the serial I/O queue context
|
|
|
|
Author:
|
|
|
|
Environment:
|
|
|
|
kernel mode only
|
|
|
|
Notes:
|
|
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#ifndef __SCRATCH_H__
|
|
#define __SCRATCH_H__
|
|
|
|
|
|
_IRQL_requires_max_(APC_LEVEL)
|
|
VOID
|
|
ScratchBuffer_Deallocate(
|
|
_Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension
|
|
);
|
|
|
|
_IRQL_requires_max_(APC_LEVEL)
|
|
BOOLEAN
|
|
ScratchBuffer_Allocate(
|
|
_Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension
|
|
);
|
|
|
|
VOID
|
|
ScratchBuffer_ResetItems(
|
|
_Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension,
|
|
_In_ BOOLEAN ResetRequestHistory
|
|
);
|
|
|
|
_IRQL_requires_max_(APC_LEVEL)
|
|
VOID
|
|
ScratchBuffer_SetupSrb(
|
|
_Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension,
|
|
_In_opt_ WDFREQUEST OriginalRequest,
|
|
_In_ ULONG MaximumTransferLength,
|
|
_In_ BOOLEAN GetDataFromDevice
|
|
);
|
|
|
|
VOID
|
|
ScratchBuffer_SetupReadWriteSrb(
|
|
_Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension,
|
|
_In_ WDFREQUEST OriginalRequest,
|
|
_In_ LARGE_INTEGER StartingOffset,
|
|
_In_ ULONG RequiredLength,
|
|
_Inout_updates_bytes_(RequiredLength) UCHAR* DataBuffer,
|
|
_In_ BOOLEAN IsReadRequest,
|
|
_In_ BOOLEAN UsePartialMdl
|
|
);
|
|
|
|
NTSTATUS
|
|
ScratchBuffer_SendSrb(
|
|
_Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension,
|
|
_In_ BOOLEAN SynchronousSrb,
|
|
_When_(SynchronousSrb, _Pre_null_)
|
|
_When_(!SynchronousSrb, _In_opt_)
|
|
PSRB_HISTORY_ITEM *SrbHistoryItem
|
|
);
|
|
|
|
NTSTATUS
|
|
ScratchBuffer_PerformNextReadWrite(
|
|
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
|
|
_In_ BOOLEAN FirstTry
|
|
);
|
|
|
|
#if DBG
|
|
#define ScratchBuffer_BeginUse(context) ScratchBuffer_BeginUseX((context), __FILE__, __LINE__)
|
|
#else
|
|
#define ScratchBuffer_BeginUse(context) ScratchBuffer_BeginUseX((context), NULL, (ULONG)-1)
|
|
#endif
|
|
|
|
FORCEINLINE VOID ScratchBuffer_BeginUseX(_Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_opt_ LPCSTR File, ULONG Line)
|
|
{
|
|
// NOTE: these are not "real" locks. They are simply to help
|
|
// avoid multiple uses of the scratch buffer. Thus, it
|
|
// is not critical to have atomic operations here.
|
|
PVOID tmp = InterlockedCompareExchangePointer((PVOID)&(DeviceExtension->ScratchContext.ScratchInUse), (PVOID)-1, NULL);
|
|
NT_ASSERT(tmp == NULL);
|
|
UNREFERENCED_PARAMETER(tmp); //defensive coding, avoid PREFAST warning.
|
|
DeviceExtension->ScratchContext.ScratchInUseFileName = File;
|
|
DeviceExtension->ScratchContext.ScratchInUseLineNumber = Line;
|
|
ScratchBuffer_ResetItems(DeviceExtension, TRUE);
|
|
RequestClearSendTime(DeviceExtension->ScratchContext.ScratchRequest);
|
|
return;
|
|
}
|
|
FORCEINLINE VOID ScratchBuffer_EndUse(_Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension)
|
|
{
|
|
// NOTE: these are not "real" locks. They are simply to help
|
|
// avoid multiple uses of the scratch buffer. Thus, it
|
|
// is not critical to have atomic operations here.
|
|
|
|
// On lock release, we erase ScratchInUseFileName and ScratchInUseLineNumber _before_ releasing ScratchInUse,
|
|
// because otherwise we may erase these after the lock has been acquired again by another thread. We store the
|
|
// old values of ScratchInUseFileName and ScratchInUseLineNumber in local variables to facilitate debugging,
|
|
// if the ASSERT at the end of the function is hit.
|
|
PCSTR scratchInUseFileName;
|
|
ULONG scratchInUseLineNumber;
|
|
PVOID tmp;
|
|
|
|
scratchInUseFileName = DeviceExtension->ScratchContext.ScratchInUseFileName;
|
|
scratchInUseLineNumber = DeviceExtension->ScratchContext.ScratchInUseLineNumber;
|
|
UNREFERENCED_PARAMETER(scratchInUseFileName);
|
|
UNREFERENCED_PARAMETER(scratchInUseLineNumber);
|
|
DeviceExtension->ScratchContext.ScratchInUseFileName = NULL;
|
|
DeviceExtension->ScratchContext.ScratchInUseLineNumber = 0;
|
|
|
|
//
|
|
// If we have used the PartialMdl in the scratch context we should notify MM that we will be reusing it
|
|
// otherwise it may leak System VA if some one below us has mapped the same.
|
|
//
|
|
|
|
if (DeviceExtension->ScratchContext.PartialMdlIsBuilt != FALSE)
|
|
{
|
|
MmPrepareMdlForReuse(DeviceExtension->ScratchContext.PartialMdl);
|
|
DeviceExtension->ScratchContext.PartialMdlIsBuilt = FALSE;
|
|
}
|
|
|
|
tmp = InterlockedCompareExchangePointer((PVOID)&(DeviceExtension->ScratchContext.ScratchInUse), NULL, (PVOID)-1);
|
|
NT_ASSERT(tmp == ((PVOID)-1));
|
|
UNREFERENCED_PARAMETER(tmp); //defensive coding, avoid PREFAST warning.
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
CompressSrbHistoryData(
|
|
_Inout_ PSRB_HISTORY RequestHistory
|
|
);
|
|
|
|
VOID
|
|
ValidateSrbHistoryDataPresumptions(
|
|
_In_ SRB_HISTORY const* RequestHistory
|
|
);
|
|
|
|
_IRQL_requires_max_(APC_LEVEL)
|
|
NTSTATUS
|
|
ScratchBuffer_ExecuteCdbEx(
|
|
_Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension,
|
|
_In_opt_ WDFREQUEST OriginalRequest,
|
|
_In_ ULONG TransferSize,
|
|
_In_ BOOLEAN GetDataFromDevice,
|
|
_In_ PCDB Cdb,
|
|
_In_ UCHAR OprationLength,
|
|
_In_ ULONG TimeoutValue
|
|
);
|
|
|
|
_IRQL_requires_max_(APC_LEVEL)
|
|
FORCEINLINE // __REACTOS__
|
|
NTSTATUS
|
|
ScratchBuffer_ExecuteCdb(
|
|
_Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension,
|
|
_In_opt_ WDFREQUEST OriginalRequest,
|
|
_In_ ULONG TransferSize,
|
|
_In_ BOOLEAN GetDataFromDevice,
|
|
_In_ PCDB Cdb,
|
|
_In_ UCHAR OprationLength
|
|
)
|
|
{
|
|
return ScratchBuffer_ExecuteCdbEx(DeviceExtension,
|
|
OriginalRequest,
|
|
TransferSize,
|
|
GetDataFromDevice,
|
|
Cdb,
|
|
OprationLength,
|
|
0);
|
|
}
|
|
|
|
KDEFERRED_ROUTINE ScratchBuffer_ReadWriteTimerRoutine;
|
|
|
|
#endif //__SCRATCH_H__
|