📄 read_write.c
字号:
///////////////////////////////////////////////////////////////////////////////
//
// OsrStartWriteIrp
//
// This is routine is called by the OsrWrite and DpcForIsr routine to
// start a new Write operation. The request started is the IRP located
// at the head of the write queue.
//
// INPUTS:
//
// DeviceObject - Address of the DEVICE_OBJECT for our device.
//
// Irp - Address of the IRP representing the IRP_MJ_WRITE call.
//
// OUTPUTS:
//
// None.
//
// RETURNS:
//
// None.
//
// IRQL:
//
// This routine is called at IRQL_DISPATCH_LEVEL.
//
// NOTES:
// *** Called (and returns) with the WriteQueueLock held.
//
///////////////////////////////////////////////////////////////////////////////
VOID
OsrStartWriteIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
POSR_DEVICE_EXT devExt = DeviceObject->DeviceExtension;
PIO_STACK_LOCATION ioStack;
ULONG mapRegsNeeded;
ioStack = IoGetCurrentIrpStackLocation(Irp);
//
// In progress IRPs cannot be cancelled
//
IoSetCancelRoutine(Irp, NULL);
#if DBG
DbgPrint("OsrWrite: Transfer length %d.\n",
ioStack->Parameters.Write.Length);
#endif
//
// We're starting a request... therefore, we clear the StopEvent
// flag.
//
KeClearEvent(&devExt->StopEvent);
//
// There is no in-progress request. Start this request on the
// device.
//
devExt->CurrentWriteIrp = Irp;
devExt->WriteTotalLength = ioStack->Parameters.Write.Length;
devExt->WriteSoFar = 0;
devExt->WriteStartingOffset = 0;
//
// Start the watchdog timer on this IRP
//
(ULONG)Irp->Tail.Overlay.DriverContext[0] = OSR_WATCHDOG_INTERVAL;
//
// Since we're about to initiate a DMA operation, ensure the user's data
// buffer is flushed from the cache back into memory, on processors that
// are non-DMA cache coherent.
//
KeFlushIoBuffers(Irp->MdlAddress, FALSE, TRUE);
//
// Determine the number of map registers we'll need for this transfer
//
mapRegsNeeded =
ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(Irp->MdlAddress),
ioStack->Parameters.Write.Length);
#if DBG
DbgPrint("StartWrite: %d. map regs needed\n", mapRegsNeeded);
#endif
//
// If the number of map registers required for this transfer exceeds the
// maximum we're allowed to use (as reported to us from HalGetAdapter() ),
// we'll need to limit ourselves to the maximum we're allowed.
//
devExt->MapRegsThisWrite = ((mapRegsNeeded > devExt->WriteMapRegsGot) ?
devExt->WriteMapRegsGot : mapRegsNeeded);
#if DBG
DbgPrint("StartWrite: %d. map regs this xfer\n", devExt->MapRegsThisWrite);
#endif
//
// Ready to GO! Allocate the appropriate Adapter Object and map registers.
//
IoAllocateAdapterChannel(devExt->WriteAdapter,
DeviceObject,
devExt->MapRegsThisWrite,
OsrAdapterControlWrite,
Irp);
}
///////////////////////////////////////////////////////////////////////////////
//
// OsrStartReadIrp
//
// This is routine is called by the OsrRead and Dpc routine in order to
// begin a new Read operation.
//
// INPUTS:
//
// DeviceObject - Address of the DEVICE_OBJECT for our device.
//
// Irp - Address of the IRP representing the IRP_MJ_READ call.
//
// OUTPUTS:
//
// None.
//
// RETURNS:
//
// None.
//
// IRQL:
//
// This routine is called at IRQL_DISPATCH_LEVEL.
//
// NOTES:
// *** Called (and returns) with the WriteQueueLock held.
//
///////////////////////////////////////////////////////////////////////////////
VOID
OsrStartReadIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
POSR_DEVICE_EXT devExt = DeviceObject->DeviceExtension;
PIO_STACK_LOCATION ioStack;
ULONG mapRegsNeeded;
ioStack = IoGetCurrentIrpStackLocation(Irp);
//
// In progress IRPs cannot be cancelled
//
IoSetCancelRoutine(Irp, NULL);
#if DBG
DbgPrint("OsrRead: Transfer length %d.\n",
ioStack->Parameters.Read.Length);
#endif
//
// We're starting a request... therefore, we clear the StopEvent
// flag.
//
KeClearEvent(&devExt->StopEvent);
//
// There is no in-progress request. Start this request on the
// device.
//
devExt->CurrentReadIrp = Irp;
devExt->ReadTotalLength = ioStack->Parameters.Read.Length;
devExt->ReadSoFar = 0;
devExt->ReadStartingOffset = 0;
//
// Start the watchdog timer on this IRP
//
(ULONG)Irp->Tail.Overlay.DriverContext[0] = OSR_WATCHDOG_INTERVAL;
//
// Flush the requestor's buffer back from cache on non-dma coherent
// machines.
//
KeFlushIoBuffers(Irp->MdlAddress, TRUE, TRUE);
//
// Determine number of map registers required by this read
//
mapRegsNeeded =
ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(Irp->MdlAddress),
ioStack->Parameters.Read.Length);
#if DBG
DbgPrint("StartReadIrp: %d. map regs needed\n", mapRegsNeeded);
#endif
//
// Limit the number of map registers used to the maximum allowed by the
// HAL. We determined this max when we called HalGetAdapter() during
// our DriverEntry processing.
//
devExt->MapRegsThisRead = ((mapRegsNeeded > devExt->ReadMapRegsGot) ?
devExt->ReadMapRegsGot : mapRegsNeeded);
#if DBG
DbgPrint("StartReadIrp: %d. map regs this xfer\n", devExt->MapRegsThisRead);
#endif
IoAllocateAdapterChannel(devExt->ReadAdapter,
DeviceObject,
devExt->MapRegsThisRead,
OsrAdapterControlRead,
Irp);
}
///////////////////////////////////////////////////////////////////////////////
//
// OsrAdapterControlRead
//
// This is routine is called by the I/O Manager when the Adapter resources
// (such as map registers) requested by the OsrStartReadIrp function are
// available for our use.
//
// INPUTS:
//
// DeviceObject - Address of the DEVICE_OBJECT for our device.
//
// MapRegisterBase - Base address of the Map registers that have been
// reserved for us use.
//
// Context - address of the Read Irp for the operation to be started
//
// OUTPUTS:
//
// None.
//
// RETURNS:
//
// DeallocateObjectKeepRegisters - indicates that the Mapping Registers that
// were allocated to us should not be deallocated at this time. We
// will deallocate them from the DpcForIsr when the Read completes.
//
// IRQL:
//
// This routine is called at IRQL_DISPATCH_LEVEL.
//
// NOTES:
//
///////////////////////////////////////////////////////////////////////////////
IO_ALLOCATION_ACTION
OsrAdapterControlRead(IN PDEVICE_OBJECT DeviceObject, IN PIRP NotUsed,
IN PVOID MapRegisterBase, IN PVOID Context)
{
PIRP irp = (PIRP) Context;
PIO_STACK_LOCATION ioStack;
POSR_DEVICE_EXT devExt;
PUCHAR baseVa;
#if DBG
DbgPrint("AdapterControlRead: Irp = 0x%0x\n", irp);
DbgPrint("AdapterControlRead: Map Register Base = 0x%0x\n", MapRegisterBase);
#endif
devExt = DeviceObject->DeviceExtension;
ioStack = IoGetCurrentIrpStackLocation(irp);
devExt->ReadLength = ioStack->Parameters.Read.Length - devExt->ReadSoFar;
#if DBG
DbgPrint("AdapterControlRead: Length remaining = %d. \n", devExt->ReadLength);
#endif
//
// Get set-up for the transfer
//
devExt->ReadMapRegBase = MapRegisterBase;
devExt->ReadStartingOffset = devExt->ReadSoFar;
//
// Get requestor's virtual address of the buffer. This is used by
// IoMapTransfer() as an index into the buffer to track the progress
// of the map operation.
//
baseVa = MmGetMdlVirtualAddress(irp->MdlAddress);
//
// Get the logical base address and length of a fragment of the
// requestor's buffer.
//
// Even though we are a Busmaster device, our device does not support
// scatter/gather. Thus, we can only use a single base address and length
// at a time. If the requestor's buffer has more fragments, we will
// do additional DMA operations (one for each fragment) until the entire
// transfer has been completed.
//
devExt->ReadPaToDevice = IoMapTransfer(devExt->ReadAdapter,
irp->MdlAddress,
MapRegisterBase,
baseVa+(devExt->ReadSoFar),
&devExt->ReadLength,
FALSE); // FALSE = READ from device
//
// Track the length of the requestor's buffer we've read so far.
//
devExt->ReadSoFar += devExt->ReadLength;
//
// Start the request on the device -- Base Address and Length
// of this fragment are stored in the device extension
//
(VOID)KeSynchronizeExecution(devExt->InterruptObject,
OsrStartReadOnDevice,
DeviceObject);
return(DeallocateObjectKeepRegisters);
}
///////////////////////////////////////////////////////////////////////////////
//
// OsrAdapterControlWrite
//
// This is routine is called by the I/O Manager when the Adapter resources
// (such as map registers) requested by the OsrStartWriteIrp function are
// available for our use.
//
// INPUTS:
//
// DeviceObject - Address of the DEVICE_OBJECT for our device.
//
// MapRegisterBase - Base address of the Map registers that have been
// reserved by the I/O Manager and HAL for our use.
//
// Context - address of the Write Irp for the operation to be started on the
// device.
//
// OUTPUTS:
//
// None.
//
// RETURNS:
//
// DeallocateObjectKeepRegisters - indicates that the map registers that
// were allocated to us should not be deallocated at this time.
// We will deallocate them with the Read operation completes.
//
// IRQL:
//
// This routine is called at IRQL_DISPATCH_LEVEL.
//
// NOTES:
//
///////////////////////////////////////////////////////////////////////////////
IO_ALLOCATION_ACTION
OsrAdapterControlWrite(IN PDEVICE_OBJECT DeviceObject, IN PIRP NotUsed,
IN PVOID MapRegisterBase, IN PVOID Context)
{
PIRP irp = (PIRP) Context;
PIO_STACK_LOCATION ioStack;
POSR_DEVICE_EXT devExt;
PUCHAR baseVa;
#if DBG
DbgPrint("AdapterControlWrite: Irp = 0x%0x\n", irp);
#endif
devExt = DeviceObject->DeviceExtension;
ioStack = IoGetCurrentIrpStackLocation(irp);
devExt->WriteLength = ioStack->Parameters.Write.Length - devExt->WriteSoFar;
#if DBG
DbgPrint("AdapterControlWrite: Length remaining = %d. \n", devExt->WriteLength);
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -