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;
}

Re: Slave DMA working??? by Maxim

Maxim
Wed Oct 13 12:27:39 CDT 2004

> Will Maptransfer do the Dma operation?

For ISA DMA, Maptransfer arms the DMA controller to hold the references to this
provided chunk. Then the device-generated hardware DMA cycles will transfer
to/from this chunk.

--
Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
maxim@storagecraft.com
http://www.storagecraft.com



Re: Slave DMA working??? by vikramuv

vikramuv
Mon Oct 18 01:09:07 CDT 2004

Hello sir,
i need to perform a simple DMA transfer between two memory using
system DMA controller on the motherboard of the computer.(slave DMA)
Is it possible to do a DMA trnsfer b/w two kernal memory(one as Source &
other As the target memory)
how would i go about it. i dont have clear understanding of working of
slave dma..:(



"Maxim S. Shatskih" wrote:

> > Will Maptransfer do the Dma operation?
>
> For ISA DMA, Maptransfer arms the DMA controller to hold the references to this
> provided chunk. Then the device-generated hardware DMA cycles will transfer
> to/from this chunk.
>
> --
> Maxim Shatskih, Windows DDK MVP
> StorageCraft Corporation
> maxim@storagecraft.com
> http://www.storagecraft.com
>
>
>

Re: Slave DMA working??? by Maxim

Maxim
Tue Oct 19 07:57:11 CDT 2004

> i need to perform a simple DMA transfer between two memory using

For what? Just call RtlCopyMemory, it will be faster.

--
Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
maxim@storagecraft.com
http://www.storagecraft.com