Hello sir,
i am using System DMA to transfer data from a buffer to a ISA device.
For understanding of DMA . i was trying to do a DMA operation between
commonBuffer to userBuffer.
Will Maptransfer do the Dma operation? Do i need to handle interrupts
for an a simple dma operation ? if so which is the irq it is connected
and what an isr typically need to do in this case.
in my driver i have got IoDmaAdapter & i have got access to
CommonBuffer..
in startIO
i call MapTransfer.. in this function which is my source and target
address??
& how w'd i verify Whether Dma has occured or not..
assuming Mdl is Destination address and CommonBuffer is Source address
for MapTransfer.i filled common buffer with known pattern
in the application i called DeviceIocontrol for DMA
i tried to check the buffer contents.. application buffer after Dma is
unequal to the commonbuffer contents.
i have attached the code.
any suggestion is appreciated..
thanks
vikram
// in pnp start device
NTSTATUS StartDevice(IN PIFU_DEVICE_EXTENSION pdx,IN PDEVICE_OBJECT
fdo)
{
NTSTATUS status;
INTERFACE_TYPE bustype;
ULONG junk;
// Try to ask for enough Map Registers
int nReqMapRegisters = BYTES_TO_PAGES (MAX_LEN_PER_DMA * 2);
pdx->nMapRegisters = nReqMapRegisters;
DEVICE_DESCRIPTION dd;
RtlZeroMemory(&dd, sizeof(dd));
dd.Version = DEVICE_DESCRIPTION_VERSION;
dd.InterfaceType = Isa;
dd.MaximumLength = MAX_LEN_PER_DMA;
dd.Dma32BitAddresses = FALSE;
dd.Master = FALSE; //slave Dma
// Init the adapterobject
pdx->AdapterObject = IoGetDmaAdapter (pdx->pdo, &dd,
&pdx->nMapRegisters);
if (!pdx->AdapterObject)
{
return STATUS_UNSUCCESSFUL;
}
// Allocate Common Buffer and get its physical address
pdx->xfer = MAX_LEN_PER_DMA ;
pdx->pv_common_buffer =(PCHAR)
(*pdx->AdapterObject->DmaOperations->AllocateCommonBuffer)
(pdx->AdapterObject, // IN The Adapter Object returned
pdx->xfer, // IN Commmon Buffer Length in Bytes
&pdx->phy_common_buffer, // OUT Return physical address
FALSE); // IN Turn Cache off for this block of Memory
RtlFillMemory(pdx->pv_common_buffer,pdx->xfer,0x55);//some known data
0x55
// Failure in getting the common buffer
if (!pdx->pv_common_buffer)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
pdx->mdlCommonBuffer = IoAllocateMdl (pdx->pv_common_buffer,
pdx->xfer, FALSE, FALSE, NULL);
if (pdx->mdlCommonBuffer == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
// updates virtual memory buffer in nonpaged pool to describe
// the underlying physical pages
MmBuildMdlForNonPagedPool (pdx->mdlCommonBuffer);
return STATUS_SUCCESS;
}
//start device ends.
in startio
void IFUStartIo(IN PDEVICE_OBJECT fdo, IN PIRP Irp)
{
PIFU_DEVICE_EXTENSION dx= (PIFU_DEVICE_EXTENSION)
fdo->DeviceExtension;
PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation (Irp);
PMDL mdl = Irp->MdlAddress;
switch (IrpStack->MajorFunction)
{
case IRP_MJ_DEVICE_CONTROL:
unsigned long ControlCode =
IrpStack->Parameters.DeviceIoControl.IoControlCode;
switch (ControlCode)
{
case IOCTL_IFU_WRITE_DMA:
{
ULONG nregs = ADDRESS_AND_SIZE_TO_SPAN_PAGES (dx->pv_common_buffer,
dx->nbytes);
if (nregs > dx->nMapRegisters)
{
nregs = dx->nMapRegisters;
dx->xfer = nregs * PAGE_SIZE - MmGetMdlByteOffset (mdl);
}
dx->nMapRegistersAllocated = nregs; // save for deallocation later
MmGetMdlByteOffset (mdl),dx->xfer,dx->nMapRegisters ));
dx->nMapRegistersAllocated = nregs;
status = (*dx->AdapterObject->DmaOperations->AllocateAdapterChannel)
(dx->AdapterObject, fdo, nregs,(PDRIVER_CONTROL) IFUAdapterControl,
dx);
if (!NT_SUCCESS (status))
{
IoReleaseRemoveLock(&pdx->RemoveLock, Irp);
(*dx->AdapterObject->DmaOperations->FreeMapRegisters)(dx->AdapterObject,
dx->regbase, dx->nMapRegistersAllocated);
CompleteIrp(Irp, status, 0);
IoStartNextPacket(fdo, true);
}
}
break;
//start io ends..
IO_ALLOCATION_ACTION IFUAdapterControl(PDEVICE_OBJECT fdo, PIRP Irp,
PVOID regbase, PIFU_DEVICE_EXTENSION pdx)
{
PMDL mdl = Irp->MdlAddress;
BOOLEAN isread = IoGetCurrentIrpStackLocation(Irp)->MajorFunction ==
IRP_MJ_READ;
pdx->regbase = regbase;
KeFlushIoBuffers(mdl, isread, TRUE);
RtlFillMemory(pdx->pv_common_buffer,pdx->xfer,0x55);
PHYSICAL_ADDRESS address=(*pdx->AdapterObject->DmaOperations->MapTransfer)
(pdx->AdapterObject, mdl, regbase, pdx->pv_common_buffer,
&pdx->xfer,!isread);
return KeepObject;
}