Hi,
In Dma callback routine, we are doing as follows.
In PCIe board, we have descriptor SRAM. We have linked list of descriptor blocks.
Each descriptor block has source address and destination address. Since this is read,
Source address is device memory address and destination address is system memory address
(given by SgList in DmaCallback parameter).we are mapping system memory and device memory.
BOOLEAN DmaCallback(WDFDMATRANSACTION dmaTransaction, WDFDEVICE device, PVOID context, WDF_DMA_DIRECTION direction, PSCATTER_GATHER_LIST SgList)
{
PDEVICE_CONTEXT deviceContext;
NTSTATUS status = STATUS_SUCCESS;
PHYSICAL_ADDRESS address;
ULONG length, elementCounter, descripterPosition, readValue;
/* Get a context to the device */
deviceContext = (PDEVICE_CONTEXT) context;
// Scatter/Gather
address = SgList->Elements[0].Address;
length = SgList->Elements[0].Length;
// Local Interrupt Input Enable, Local DMA Channel0 Interrupt Disable
SetConfigRegister(deviceContext, ((PCI_CONFIG_SPACE)+0x68), 0x00000800);
ResetConfigRegister(deviceContext, ((PCI_CONFIG_SPACE)+0x68), 0x00040000);
deviceContext->DmaLocalAddress = PCI_FIFO_ADDRESS ;
// Bus Width: 32bit(bit0,1) TA#/READY# Input : Enable(bit6) Local Burst: Enable(bit8) Scatter/Gather: Enable(bit9) DMA Done Intrrupt: Enable(bit10)
// DMA Channel0 Interrupt Select: routes the DMA Channel0 interrupts to the PCI Businterrupt(bit17)
// :When EOT is asserted, DMA transfer ends the current scatter gather transfer and continues with remaining transfers
SetConfigRegister(deviceContext, ((PCI_CONFIG_SPACE)+0x080), 0x000A0743);
// DMA Ch0 PCI Address
WriteConfigRegister(deviceContext, ((PCI_CONFIG_SPACE)+0x084), address.LowPart);
WriteConfigRegister(deviceContext, ((PCI_CONFIG_SPACE)+0x088), deviceContext->DmaLocalAddress);
// DMA Ch0 Transfer Byte Count
WriteConfigRegister(deviceContext, ((PCI_CONFIG_SPACE)+0x08C), length);
// Descriptor Start Address
WriteConfigRegister(deviceContext, ((PCI_CONFIG_SPACE)+0x090), 0x00040008); // Direction of transfer(bit3 1:transfer from the Local Bus to the PCI Bus)
// Descriptor
descripterPosition = 0x00040000;
// Descriptor
for(elementCounter = 0; elementCounter < SgList->NumberOfElements; ++elementCounter) {
address = SgList->Elements[elementCounter].Address;
length = SgList->Elements[elementCounter].Length;
//DMA Ch0 PCIB Address
WritePciSp0Register(deviceContext, descripterPosition + 0x00, address.LowPart);
WritePciSp0Register(deviceContext, descripterPosition + 0x04, deviceContext->DmaLocalAddress);
WritePciSp0Register(deviceContext, descripterPosition + 0x08, length);
if( descripterPosition >= 0x7FFFF){
length = 0;
}
if(( length <= 0 )||( (SgList->NumberOfElements-1) == elementCounter)){
// Set DMA Channel0 Descriptor Pointer Register to indicate end of list.
// Bit1 = TRUE( End-of Chain), Bit2 = TRUE( Interrupt After Terminal Count) Bit3 = TRUE ( Transfer direction - PCI to Local)
WritePciSp0Register(deviceContext, descripterPosition + 0x0C, (0x40000 | 0x000E));
}
else
{
WritePciSp0Register(deviceContext, descripterPosition + 0x0C, ((descripterPosition + SIZEOF_DESCRIPTER) | 0x08 ));
}
deviceContext->DmaLocalAddress = CalcNextStartAddress(deviceContext, length);
descripterPosition += SIZEOF_DESCRIPTER;
} // end- for loop
// DMA$BE>Aw3+;O(J
WriteConfigRegister ( deviceContext, ((PCI_CONFIG_SPACE)+0xA8), 0x0001); // DMA Channel0 Enable
WriteConfigRegister ( deviceContext, ((PCI_CONFIG_SPACE)+0xA8), 0x0003); // DMA Channel0 Start
return TRUE;
}
Thanks & Regards,
Raphel
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Mark Roddy
Sent: Wednesday, January 09, 2008 12:01 AM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] MmGetMdlVirtualAddress & WdfDmaTransactionInitialize
What does your DmaCallback routine do?
On Jan 8, 2008 7:02 AM, wrote:
Hi,
we are developing PCI express driver for VISTA OS and driver uses scatter gather DMA.
our aim is to read the data (1MB) from the device. Device splits this 1MB data in 4 packets. Device generate DMA demand interrupt for first packet and driver prepares the DMA for the transfer. Then device generate DMA End interrupt and driver completes the DMA. DMA demand interrupt & DMA End interrupt sequence is followed for each packets.
Implementation are as follows.
The following DPC is queued from ISR on DMA demand and DMA end interrupt.
In DPC routine, driver process as follows.
ReadDPC
{
status = WdfIoQueueRetrieveNextRequest(deviceContext->ReadQueue, &request);
if (DMA demand interrupt)
{
WdfRequestRetrieveOutputWdmMdl( request, &mdl);
deviceContext->CurrentVirtualAddress = MmGetMdlVirtualAddress( mdl );
(ULONG *)deviceContext->CurrentVirtualAddress += deviceContext
->TotalTransferredLength;
WdfDmaTransactionInitialize( deviceContext->DmaTransaction,
(PFN_WDF_PROGRAM_DMA) DmaCallback,
WdfDmaDirectionReadFromDevice, // DMA Direction
mdl, deviceContext->CurrentVirtualAddress,
readLength );
}
if (DMA end interrupt)
{
returnValue = WdfDmaTransactionDmaCompleted(deviceContext->DmaTransaction,
&status) ;
currentBytesTransferred = WdfDmaTransactionGetBytesTransferred(deviceContext
->DmaTransaction);
deviceContext->TotalTransferredLength += currentBytesTransferred;
WdfDmaTransactionRelease(deviceContext->DmaTransaction);
}
}
I am getting 4 packets from the driver. but data content are zero. all are invalid.
I have replaced MmGetMdlVirtualAddress with MmGetSystemAddressForMdlSafe as below. still packet content is zero.
Can you please give idea what problem is in this implementation.
Thanks & Regards,
Raphel
—
NTDEV is sponsored by OSR
For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars
To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer
–
Mark Roddy — NTDEV is sponsored by OSR For our schedule of WDF, WDM, debugging and other seminars visit: http://www.osr.com/seminars To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer