📄 readwrite.cpp
字号:
/*
ReadWrite.cpp
Sheldon Instruments, Inc.
Abstract:
Read \ Write processors for WDM driver. Handles calls to IRP_MJ_READ, IRP_MJ_WRITE,
IRP_MJ_CREATE, IRP_MJ_CLOSE, and the interrupt handling for busmastered transfers.
Revision History:
02Dec1998 - created by Robert Updike
24Feb2000 - changed DoBusMasteredRead and DoBusMasteredWrite to not timeout if the value
is zero. Robert Updike
20Mar2000 - added Sheldon_Cleanup. Robert Updike
2002-07-11: mik
Better error checking on large counts.
2002-07-22: mik
DoBMRead/Write now correctly returning TRUE and FALSE.
Commented out example WRITE_REGISTER_ULONG in ISR.
*/
#include "driver.h"
#include "../../common/siddkapi_win.h"
IO_ALLOCATION_ACTION SheldonReadAdapterControl(PDEVICE_OBJECT DeviceObject, \
PIRP Irp, \
PVOID MapRegisterBase, \
PVOID Context);
IO_ALLOCATION_ACTION SheldonWriteAdapterControl(PDEVICE_OBJECT DeviceObject, \
PIRP Irp, \
PVOID MapRegisterBase, \
PVOID Context);
BOOLEAN DoBusMasteredRead(IN PDEVICE_EXTENSION pdx);
BOOLEAN DoBusMasteredWrite(IN PDEVICE_EXTENSION pdx);
/*
Function Name:
Sheldon_Create
Routine Description:
Handles create requests.
Arguments:
fdo - pointer to a functional device object
Return Value:
STATUS_SUCCESS
*/
NTSTATUS Sheldon_Create(IN PDEVICE_OBJECT fdo, IN PIRP Irp)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
KdPrint(("SIWDM - Entering Sheldon_Create: IRP_MJ_CREATE\n"));
// Handling this IRP allows applications to open handles to the device.
KdPrint(("SIWDM - Exiting Sheldon_Create (%x)\n", ntStatus));
return CompleteRequest(Irp, ntStatus, 0);
}
/*
Function Name:
Sheldon_Read
Routine Description:
Handles read requests.
Arguments:
fdo - pointer to a functional device object
Irp - I/O request being serviced
Return Value:
STATUS_SUCCESS
*/
NTSTATUS Sheldon_Read(IN PDEVICE_OBJECT fdo, IN PIRP Irp)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
KdPrint(("SIWDM - Entering Sheldon_Read: IRP_MJ_READ\n"));
// This function would normally handle IRP_MJ_READ requests.
KdPrint(("SIWDM - Exiting Sheldon_Read (%x)\n", ntStatus));
return CompleteRequest(Irp, ntStatus, 0);
}
/*
Function Name:
Sheldon_Write
Routine Description:
Handles write requests.
Arguments:
fdo - pointer to a functional device object
Irp - I/O request being serviced
Return Value:
STATUS_SUCCESS
*/
NTSTATUS Sheldon_Write(IN PDEVICE_OBJECT fdo, IN PIRP Irp)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
KdPrint(("SIWDM - Entering Sheldon_Write: IRP_MJ_WRITE\n"));
// This function would normally handle IRP_MJ_WRITE requests.
KdPrint(("SIWDM - Exiting Sheldon_Write (%x)\n", ntStatus));
return CompleteRequest(Irp, ntStatus, 0);
}
/*
Function Name:
Sheldon_Cleanup
Routine Description:
Handles cleanup requests.
Arguments:
fdo - pointer to a functional device object
Irp - I/O request being serviced
Return Value:
STATUS_SUCCESS
*/
NTSTATUS Sheldon_Cleanup(PDEVICE_OBJECT fdo, PIRP Irp)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
KdPrint(("SIWDM - Entering Sheldon_Cleanup: IRP_MJ_CLEANUP\n"));
CleanupRequests(&pdx->dqReadWrite, stack->FileObject, STATUS_CANCELLED);
KdPrint(("SIWDM - Exiting Sheldon_Cleanup\n"));
return CompleteRequest(Irp, ntStatus, 0);
}
/*
Function Name:
Sheldon_Close
Routine Description:
Handles close requests.
Arguments:
fdo - pointer to a functional device object
Irp - I/O request being serviced
Return Value:
STATUS_SUCCESS
*/
NTSTATUS Sheldon_Close(IN PDEVICE_OBJECT fdo, IN PIRP Irp)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
KdPrint(("SIWDM - Entering Sheldon_Close: IRP_MJ_CLOSE\n"));
// Handling this IRP allows applications to close handles to the device.
ntStatus = SheldonUnMapDirect(pdx);
KdPrint(("SIWDM - Exiting Sheldon_Close (%x)\n", ntStatus));
return CompleteRequest(Irp, ntStatus, 0);
}
/*
Function Name:
Sheldon_StartIo
Routine Description:
Handles Irps sent by the I/O Manager.
Arguments:
fdo - pointer to a functional device object
Irp - I/O request being serviced
Return Value:
*/
VOID Sheldon_StartIo(IN PDEVICE_OBJECT fdo, IN PIRP Irp)
{
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
KIRQL oldirql;
ULONG ControlCode;
PIO_STACK_LOCATION IrpStack;
NTSTATUS ntStatus;
PMDL Mdl;
KdPrint(("SIWDM - Entering Sheldon_StartIo\n"));
if(!LockDevice(fdo))
{
CompleteRequest(Irp, STATUS_DELETE_PENDING, 0);
return;
}
Mdl = Irp->MdlAddress;
IrpStack = IoGetCurrentIrpStackLocation(Irp);
ControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
switch(ControlCode)
{
case IOCTL_SHELDON_BUSMASTERED_READ:
KdPrint(("SIWDM - Sheldon_StartIo: SHELDON_BUSMASTERED_READ\n"));
pdx->ReadTransfer.pIrp = Irp;
ntStatus = pdx->ReadTransfer.Adapter->DmaOperations->AllocateAdapterChannel
(pdx->ReadTransfer.Adapter, fdo, pdx->ReadTransfer.NumberOfMapRegisters,
SheldonReadAdapterControl, pdx);
break;
case IOCTL_SHELDON_BUSMASTERED_WRITE:
KdPrint(("SIWDM - Sheldon_StartIo: SHELDON_BUSMASTERED_WRITE\n"));
pdx->WriteTransfer.pIrp = Irp;
ntStatus = pdx->WriteTransfer.Adapter->DmaOperations->AllocateAdapterChannel
(pdx->WriteTransfer.Adapter, fdo, pdx->WriteTransfer.NumberOfMapRegisters,
SheldonWriteAdapterControl, pdx);
break;
default:
KdPrint(("SIWDM - Sheldon_StartIo: DEFAULT\n"));
ntStatus = STATUS_NOT_SUPPORTED;
break;
}
// something went wrong, either the code isn't supported or there was an error
// in either case, retire this IRP
if(!NT_SUCCESS(ntStatus))
{
StartNextPacket(&pdx->dqReadWrite, fdo);
UnlockDevice(fdo);
CompleteRequest(Irp, ntStatus, 0);
}
KdPrint(("SIWDM - Exiting Sheldon_StartIo (%x)\n", ntStatus));
}
/*
Function Name:
OnCancel
Routine Description:
Handles cancellation of active IRPs.
Arguments:
fdo - pointer to a functional device object
IRP - I/O request being serviced
Return Value:
*/
VOID OnCancel(PDEVICE_OBJECT fdo, PIRP Irp)
{
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
CancelRequest(&pdx->dqReadWrite, Irp);
}
/*
Function Name:
SheldonReadAdapterControl
Routine Description:
Setup the Adapter Control for Busmastered Reads.
Arguments:
DeviceObject - pointer to a device object
Irp - I/O request being serviced
MapRegisterBase - list of physical addresses and lengths of pages
Context - pointer to a device extension
Return Value:
STATUS_SUCCESS if adapter object has been allocated
STATUS_INSUFFICIENT_RESOURCES if NumberOfMapRegisters larger than
value returned by IoGetDmaAdapter
*/
IO_ALLOCATION_ACTION SheldonReadAdapterControl(PDEVICE_OBJECT DeviceObject, \
PIRP junk, \
PVOID MapRegisterBase, \
PVOID Context)
{
KdPrint(("SIWDM - Entering SheldonReadAdapterControl\n"));
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) Context;
PIRP Irp = GetCurrentIrp(&pdx->dqReadWrite);
PMDL Mdl = Irp->MdlAddress;
PULONG OP = pdx->base[AMCC_OPREGS];
pdx->ReadTransfer.BytesRequested = MmGetMdlByteCount(Mdl);
pdx->ReadTransfer.BytesRemaining = pdx->ReadTransfer.BytesRequested;
pdx->ReadTransfer.LogicalAddress = (UCHAR *) MmGetMdlVirtualAddress(Mdl);
pdx->ReadTransfer.MapRegisterBase = MapRegisterBase;
pdx->ReadTransfer.Mdl = Mdl;
// We now have the physical address and size of the first chunk to send
// Let's now set up the PCI hardware so that when we load MWTC and MWAR
// a transfer will occur
/////////////////
// IO and memory mapped
/////////////////
if( (ULONG)pdx->base[AMCC_OPREGS] & 0xffff0000 ) {
// Disable Add-on to PCI FIFO Bus Mastering MCSR bit 10 set 0
OP[AMCC_MCSR] = OP[AMCC_MCSR] & ~0x00000400;
// Disable Ints from Transfer Count = 0 INTCSR bits 14 15 both zeroed
OP[AMCC_INTCSR] = OP[AMCC_INTCSR] & ~AMCC_BUSMASTERED_READ_INT_ENABLE_MASK;
// Clear FIFO MCSR bit 26 written with one
// Will clear fifo before every transfer if executed(implementation dependent)
// OP[AMCC_MCSR] = OP[AMCC_MCSR] | 0x04000000;
// Define FIFO Management Scheme as go-on-half-way (4 words) MCSR bit 9 written as 1
OP[AMCC_MCSR] = OP[AMCC_MCSR] | 0x00000200;
// Define Read-Write Priority as equal (see ERRATA for AMCC chip)
// MCSR bit 8 one and 12 written as one
OP[AMCC_MCSR] = (OP[AMCC_MCSR] & ~0x00001000) | 0x00000100;
// Write zero into the MRTC
OP[AMCC_MRTC] = 0x0000;
// Set the transfer flag before allowing ints
pdx->ReadTransfer.TransferInProgress = TRUE;
// Ok, let's do the first call to the code which loads the registers and (re)starts
// the transfer. Later calls will be made by the DPC after each interrupt, until
// the transfer is complete.
DoBusMasteredRead(pdx);
// Now re-enable the interrupts and set TIProgress
// Enable Ints from Transfer Count = 0 INTCSR bits 14 15 both zeroed
OP[AMCC_INTCSR] = OP[AMCC_INTCSR] | AMCC_BUSMASTERED_READ_INT_ENABLE_MASK;
// Enable Add-on to PCI FIFO Bus Mastering MCSR bit 10 set 1
OP[AMCC_MCSR] = OP[AMCC_MCSR] | 0x00000400;
}
else {
// Disable Add-on to PCI FIFO Bus Mastering MCSR bit 10 set 0
WRITE_PORT_ULONG(OP + AMCC_MCSR, READ_PORT_ULONG(OP + AMCC_MCSR) & ~0x00000400);
// Disable Ints from Transfer Count = 0 INTCSR bits 14 15 both zeroed
WRITE_PORT_ULONG(OP + AMCC_INTCSR, READ_PORT_ULONG(OP + AMCC_INTCSR) & ~AMCC_BUSMASTERED_READ_INT_ENABLE_MASK);
// Clear FIFO MCSR bit 26 written with one
// Will clear fifo before every transfer if executed(implementation dependent)
// OP[AMCC_MCSR] = OP[AMCC_MCSR] | 0x04000000;
// Define FIFO Management Scheme as go-on-half-way (4 words) MCSR bit 9 written as 1
WRITE_PORT_ULONG(OP + AMCC_MCSR, READ_PORT_ULONG(OP + AMCC_MCSR) | 0x00000200);
// Define Read-Write Priority as equal (see ERRATA for AMCC chip)
// MCSR bit 8 one and 12 written as one
WRITE_PORT_ULONG(OP + AMCC_MCSR, (READ_PORT_ULONG(OP + AMCC_MCSR) & ~0x00001000) | 0x00000100);
// Write zero into the MRTC
WRITE_PORT_ULONG(OP + AMCC_MRTC, 0x0000);
// Set the transfer flag before allowing ints
pdx->ReadTransfer.TransferInProgress = TRUE;
// Ok, let's do the first call to the code which loads the registers and (re)starts
// the transfer. Later calls will be made by the DPC after each interrupt, until
// the transfer is complete.
DoBusMasteredRead(pdx);
// Now re-enable the interrupts and set TIProgress
// Enable Ints from Transfer Count = 0 INTCSR bits 14 15 both zeroed
WRITE_PORT_ULONG(OP + AMCC_INTCSR, READ_PORT_ULONG(OP + AMCC_INTCSR) | AMCC_BUSMASTERED_READ_INT_ENABLE_MASK);
// Enable Add-on to PCI FIFO Bus Mastering MCSR bit 10 set 1
WRITE_PORT_ULONG(OP + AMCC_MCSR, READ_PORT_ULONG(OP + AMCC_MCSR) | 0x00000400);
}
KdPrint(("SIWDM - Exiting SheldonReadAdapterControl\n"));
return DeallocateObjectKeepRegisters;
}
/*
Function Name:
SheldonWriteAdapterControl
Routine Description:
Setup the Adapter Control for Busmastered Writes.
Arguments:
DeviceObject - pointer to a device object
Irp - I/O request being serviced
MapRegisterBase - list of physical addresses and lengths of pages
Context - pointer to a device extension
Return Value:
STATUS_SUCCESS if adapter object has been allocated
STATUS_INSUFFICIENT_RESOURCES if NumberOfMapRegisters larger than
value returned by IoGetDmaAdapter
*/
IO_ALLOCATION_ACTION SheldonWriteAdapterControl(PDEVICE_OBJECT DeviceObject, \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -