📄 deviosup.c
字号:
/*++
Copyright (c) 1989-2000 Microsoft Corporation
Module Name:
DevIoSup.c
Abstract:
This module implements the low lever disk read/write support for Cdfs.
--*/
#include "CdProcs.h"
//
// The Bug check file id for this module
//
#define BugCheckFileId (CDFS_BUG_CHECK_DEVIOSUP)
//
// Local structure definitions
//
//
// An array of these structures is passed to CdMultipleAsync describing
// a set of runs to execute in parallel.
//
typedef struct _IO_RUN {
//
// Disk offset to read from and number of bytes to read. These
// must be a multiple of 2048 and the disk offset is also a
// multiple of 2048.
//
LONGLONG DiskOffset;
ULONG DiskByteCount;
//
// Current position in user buffer. This is the final destination for
// this portion of the Io transfer.
//
PVOID UserBuffer;
//
// Buffer to perform the transfer to. If this is the same as the
// user buffer above then we are using the user's buffer. Otherwise
// we either allocated a temporary buffer or are using a different portion
// of the user's buffer.
//
// TransferBuffer - Read full sectors into this location. This can
// be a pointer into the user's buffer at the exact location the
// data should go. It can also be an earlier point in the user's
// buffer if the complete I/O doesn't start on a sector boundary.
// It may also be a pointer into an allocated buffer.
//
// TransferByteCount - Count of bytes to transfer to user's buffer. A
// value of zero indicates that we did do the transfer into the
// user's buffer directly.
//
// TransferBufferOffset - Offset in this buffer to begin the transfer
// to the user's buffer.
//
PVOID TransferBuffer;
ULONG TransferByteCount;
ULONG TransferBufferOffset;
//
// This is the Mdl describing the locked pages in memory. It may
// be allocated to describe the allocated buffer. Or it may be
// the Mdl in the originating Irp. The MdlOffset is the offset of
// the current buffer from the beginning of the buffer described by
// the Mdl below. If the TransferMdl is not the same as the Mdl
// in the user's Irp then we know we have allocated it.
//
PMDL TransferMdl;
PVOID TransferVirtualAddress;
//
// Associated Irp used to perform the Io.
//
PIRP SavedIrp;
} IO_RUN;
typedef IO_RUN *PIO_RUN;
#define MAX_PARALLEL_IOS 5
//
// Local support routines
//
BOOLEAN
CdPrepareBuffers (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp,
IN PFCB Fcb,
IN PVOID UserBuffer,
IN ULONG UserBufferOffset,
IN LONGLONG StartingOffset,
IN ULONG ByteCount,
IN PIO_RUN IoRuns,
IN PULONG RunCount,
IN PULONG ThisByteCount
);
VOID
CdPrepareXABuffers (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp,
IN PFCB Fcb,
IN PVOID UserBuffer,
IN ULONG UserBufferOffset,
IN LONGLONG StartingOffset,
IN ULONG ByteCount,
IN PIO_RUN IoRuns,
IN PULONG RunCount,
IN PULONG ThisByteCount
);
BOOLEAN
CdFinishBuffers (
IN PIRP_CONTEXT IrpContext,
IN PIO_RUN IoRuns,
IN ULONG RunCount,
IN BOOLEAN FinalCleanup,
IN BOOLEAN SaveXABuffer
);
VOID
CdMultipleAsync (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb,
IN ULONG RunCount,
IN PIO_RUN IoRuns
);
VOID
CdMultipleXAAsync (
IN PIRP_CONTEXT IrpContext,
IN ULONG RunCount,
IN PIO_RUN IoRuns,
IN PRAW_READ_INFO RawReads,
IN TRACK_MODE_TYPE TrackMode
);
VOID
CdSingleAsync (
IN PIRP_CONTEXT IrpContext,
IN PIO_RUN Run,
IN PFCB Fcb
);
VOID
CdWaitSync (
IN PIRP_CONTEXT IrpContext
);
NTSTATUS
CdMultiSyncCompletionRoutine (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
);
NTSTATUS
CdMultiAsyncCompletionRoutine (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
);
NTSTATUS
CdSingleSyncCompletionRoutine (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
);
NTSTATUS
CdSingleAsyncCompletionRoutine (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
);
VOID
CdReadAudioSystemFile (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb,
IN LONGLONG StartingOffset,
IN ULONG ByteCount,
IN PVOID SystemBuffer
);
VOID
CdReadDirDataThroughCache(
IN PIRP_CONTEXT IrpContext,
IN PIO_RUN Run
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, CdCreateUserMdl)
#pragma alloc_text(PAGE, CdMultipleAsync)
#pragma alloc_text(PAGE, CdMultipleXAAsync)
#pragma alloc_text(PAGE, CdNonCachedRead)
#pragma alloc_text(PAGE, CdNonCachedXARead)
#pragma alloc_text(PAGE, CdFinishBuffers)
#pragma alloc_text(PAGE, CdPerformDevIoCtrl)
#pragma alloc_text(PAGE, CdPerformDevIoCtrlEx)
#pragma alloc_text(PAGE, CdPrepareBuffers)
#pragma alloc_text(PAGE, CdReadAudioSystemFile)
#pragma alloc_text(PAGE, CdReadSectors)
#pragma alloc_text(PAGE, CdSingleAsync)
#pragma alloc_text(PAGE, CdWaitSync)
#pragma alloc_text(PAGE, CdReadDirDataThroughCache)
#pragma alloc_text(PAGE, CdFreeDirCache)
#pragma alloc_text(PAGE, CdLbnToMmSsFf)
#endif
VOID
CdLbnToMmSsFf(
IN ULONG Blocks,
OUT PUCHAR Msf
)
/*++
Routine Description:
Convert Lbn to MSF format.
Arguments:
Msf - on output, set to 0xMmSsFf representation of blocks.
--*/
{
Blocks += 150; // Lbn 0 == 00:02:00, 1sec == 75 frames.
Msf[0] = (UCHAR)(Blocks % 75); // Frames
Blocks /= 75; // -> Seconds
Msf[1] = (UCHAR)(Blocks % 60); // Seconds
Blocks /= 60; // -> Minutes
Msf[2] = (UCHAR)Blocks; // Minutes
}
__inline
TRACK_MODE_TYPE
CdFileTrackMode (
IN PFCB Fcb
)
/*++
Routine Description:
This routine converts FCB XA file type flags to the track mode
used by the device drivers.
Arguments:
Fcb - Fcb representing the file to read.
Return Value:
TrackMode of the file represented by the Fcb.
--*/
{
ASSERT( FlagOn( Fcb->FcbState, FCB_STATE_MODE2FORM2_FILE |
FCB_STATE_MODE2_FILE |
FCB_STATE_DA_FILE ));
if (FlagOn( Fcb->FcbState, FCB_STATE_MODE2FORM2_FILE )) {
return XAForm2;
} else if (FlagOn( Fcb->FcbState, FCB_STATE_DA_FILE )) {
return CDDA;
}
//
// FCB_STATE_MODE2_FILE
//
return YellowMode2;
}
NTSTATUS
CdNonCachedRead (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb,
IN LONGLONG StartingOffset,
IN ULONG ByteCount
)
/*++
Routine Description:
This routine performs the non-cached reads to 'cooked' sectors (2048 bytes
per sector). This is done by performing the following in a loop.
Fill in the IoRuns array for the next block of Io.
Send the Io to the device.
Perform any cleanup on the Io runs array.
We will not do async Io to any request that generates non-aligned Io.
Also we will not perform async Io if it will exceed the size of our
IoRuns array. These should be the unusual cases but we will raise
or return CANT_WAIT in this routine if we detect this case.
Arguments:
Fcb - Fcb representing the file to read.
StartingOffset - Logical offset in the file to read from.
ByteCount - Number of bytes to read.
Return Value:
NTSTATUS - Status indicating the result of the operation.
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
IO_RUN IoRuns[MAX_PARALLEL_IOS];
ULONG RunCount = 0;
ULONG CleanupRunCount = 0;
PVOID UserBuffer;
ULONG UserBufferOffset = 0;
LONGLONG CurrentOffset = StartingOffset;
ULONG RemainingByteCount = ByteCount;
ULONG ThisByteCount;
BOOLEAN Unaligned;
BOOLEAN FlushIoBuffers = FALSE;
BOOLEAN FirstPass = TRUE;
PAGED_CODE();
//
// We want to make sure the user's buffer is locked in all cases.
//
if (IrpContext->Irp->MdlAddress == NULL) {
CdCreateUserMdl( IrpContext, ByteCount, TRUE );
}
CdMapUserBuffer( IrpContext, &UserBuffer);
//
// Special case the root directory and path table for a music volume.
//
if (FlagOn( Fcb->Vcb->VcbState, VCB_STATE_AUDIO_DISK ) &&
((SafeNodeType( Fcb ) == CDFS_NTC_FCB_INDEX) ||
(SafeNodeType( Fcb ) == CDFS_NTC_FCB_PATH_TABLE))) {
CdReadAudioSystemFile( IrpContext,
Fcb,
StartingOffset,
ByteCount,
UserBuffer );
return STATUS_SUCCESS;
}
//
// If we're going to use the sector cache for this request, then
// mark the request waitable.
//
if ((SafeNodeType( Fcb) == CDFS_NTC_FCB_INDEX) &&
(NULL != Fcb->Vcb->SectorCacheBuffer) &&
(VcbMounted == IrpContext->Vcb->VcbCondition)) {
SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
}
//
// Use a try-finally to perform the final cleanup.
//
try {
//
// Loop while there are more bytes to transfer.
//
do {
//
// Call prepare buffers to set up the next entries
// in the IoRuns array. Remember if there are any
// unaligned entries. This routine will raise CANT_WAIT
// if there are unaligned entries for an async request.
//
RtlZeroMemory( IoRuns, sizeof( IoRuns ));
Unaligned = CdPrepareBuffers( IrpContext,
IrpContext->Irp,
Fcb,
UserBuffer,
UserBufferOffset,
CurrentOffset,
RemainingByteCount,
IoRuns,
&CleanupRunCount,
&ThisByteCount );
RunCount = CleanupRunCount;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -