📄 write.c
字号:
// Setup the pointer to the next DMA_TRANSFER_ELEMENT
// for both virtual and physical address references.
//
dteVA = (PDMA_TRANSFER_ELEMENT) devExt->WriteCommonBufferBase;
dteLA = (devExt->WriteCommonBufferBaseLA.LowPart +
sizeof(DMA_TRANSFER_ELEMENT));
//
// Translate the System's SCATTER_GATHER_LIST elements
// into the device's DMA_TRANSFER_ELEMENT elements.
//
for (i=0; i < SgList->NumberOfElements; i++) {
//
// Construct this DTE.
//
// NOTE: The LocalAddress is the offset into the SRAM from
// where this Write will start.
//
dteVA->PciAddressLow = SgList->Elements[i].Address.LowPart;
dteVA->PciAddressHigh = SgList->Elements[i].Address.HighPart;
dteVA->TransferSize = SgList->Elements[i].Length;
dteVA->LocalAddress = (ULONG) offset;
dteVA->DescPtr.DescLocation = DESC_PTR_DESC_LOCATION__PCI;
dteVA->DescPtr.TermCountInt = FALSE;
dteVA->DescPtr.LastElement = FALSE;
dteVA->DescPtr.DirOfTransfer = DESC_PTR_DIRECTION__TO_DEVICE;
dteVA->DescPtr.Address = DESC_PTR_ADDR( dteLA );
//
// Increment the DmaTransaction length by this element length
//
offset += SgList->Elements[i].Length;
//
// If at end of SgList, then set LastElement bit in final NTE.
//
if (i == SgList->NumberOfElements - 1) {
dteVA->DescPtr.LastElement = TRUE;
#if 0 // set to 1 for recording the details
TraceEvents(TRACE_LEVEL_INFORMATION, DBG_WRITE,
"\tDTE[%d] : Addr #%X%08X Len %5d, Local %08X, "
"Loc(%d), Last(%d), TermInt(%d), ToPci(%d)\n",
i,
dteVA->PciAddressHigh,
dteVA->PciAddressLow,
dteVA->TransferSize,
dteVA->LocalAddress,
dteVA->DescPtr.DescLocation,
dteVA->DescPtr.LastElement,
dteVA->DescPtr.TermCountInt,
dteVA->DescPtr.DirOfTransfer );
#endif
break;
}
#if 0 // set to 1 for recording the details
TraceEvents(TRACE_LEVEL_INFORMATION, DBG_WRITE,
"\tDTE[%d] : Addr #%X%08X Len %5d, Local %08X, "
"Loc(%d), Last(%d), TermInt(%d), ToPci(%d)\n",
i,
dteVA->PciAddressHigh,
dteVA->PciAddressLow,
dteVA->TransferSize,
dteVA->LocalAddress,
dteVA->DescPtr.DescLocation,
dteVA->DescPtr.LastElement,
dteVA->DescPtr.TermCountInt,
dteVA->DescPtr.DirOfTransfer );
#endif
//
// Adjust the next DMA_TRANSFER_ELEMEMT
//
dteVA++;
dteLA += sizeof(DMA_TRANSFER_ELEMENT);
}
//
// Start the DMA operation.
// Acquire this device's InterruptSpinLock.
//
WdfInterruptAcquireLock( devExt->Interrupt );
//
// DMA 0 Mode Register - (DMAMODE0)
// Enable Scatter/Gather Mode, Interrupt On Done,
// and route Ints to PCI.
//
{
union {
DMA_MODE bits;
ULONG ulong;
} dmaMode;
dmaMode.ulong =
READ_REGISTER_ULONG( (PULONG) &devExt->Regs->Dma0_Mode );
dmaMode.bits.SgModeEnable = TRUE;
dmaMode.bits.DoneIntEnable = TRUE;
dmaMode.bits.IntToPci = TRUE;
WRITE_REGISTER_ULONG( (PULONG) &devExt->Regs->Dma0_Mode,
dmaMode.ulong );
}
//
// Interrupt CSR Register - (INTCSR)
// Enable PCI Ints and DMA Channel 0 Ints.
//
{
union {
INT_CSR bits;
ULONG ulong;
} intCSR;
intCSR.ulong =
READ_REGISTER_ULONG( (PULONG) &devExt->Regs->Int_Csr );
intCSR.bits.PciIntEnable = TRUE;
intCSR.bits.DmaChan0IntEnable = TRUE;
WRITE_REGISTER_ULONG( (PULONG) &devExt->Regs->Int_Csr,
intCSR.ulong );
}
//
// DMA 0 Descriptor Pointer Register - (DMADPR0)
// Write the base LOGICAL address of the DMA_TRANSFER_ELEMENT list.
//
{
union {
DESC_PTR bits;
ULONG ulong;
} ptr;
ptr.bits.DescLocation = DESC_PTR_DESC_LOCATION__PCI;
ptr.bits.TermCountInt = TRUE;
ptr.bits.Address =
DESC_PTR_ADDR( devExt->WriteCommonBufferBaseLA.LowPart );
WRITE_REGISTER_ULONG( (PULONG) &devExt->Regs->Dma0_Desc_Ptr,
ptr.ulong );
}
TraceEvents(TRACE_LEVEL_INFORMATION, DBG_WRITE,
" PCIEEvtProgramWriteDma: Start a Write DMA operation");
//
// DMA 0 CSR Register - (DMACSR0)
// Start the DMA operation: Set Enable and Start bits.
//
{
union {
DMA_CSR bits;
UCHAR uchar;
} dmaCSR;
dmaCSR.uchar =
READ_REGISTER_UCHAR( (PUCHAR) &devExt->Regs->Dma0_Csr );
dmaCSR.bits.Enable = TRUE;
dmaCSR.bits.Start = TRUE;
WRITE_REGISTER_UCHAR( (PUCHAR) &devExt->Regs->Dma0_Csr,
dmaCSR.uchar );
}
//
// Release our interrupt spinlock
//
WdfInterruptReleaseLock( devExt->Interrupt );
//
// NOTE: This shows how to process errors which occur in the
// PFN_WDF_PROGRAM_DMA function in general.
// Basically the DmaTransaction must be deleted and
// the Request must be completed.
//
if (errors) {
//
// Must abort the transaction before deleting it.
//
NTSTATUS status;
(VOID) WdfDmaTransactionDmaCompletedFinal(Transaction, 0, &status);
ASSERT(NT_SUCCESS(status));
PCIEWriteRequestComplete( Transaction, STATUS_INVALID_DEVICE_STATE );
TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE,
"<-- PCIEEvtProgramWriteDma: error ****");
return FALSE;
}
TraceEvents(TRACE_LEVEL_INFORMATION, DBG_WRITE,
"<-- PCIEEvtProgramWriteDma");
return TRUE;
}
VOID
PCIEWriteRequestComplete(
IN WDFDMATRANSACTION DmaTransaction,
IN NTSTATUS Status
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
WDFDEVICE device;
WDFREQUEST request;
PDEVICE_EXTENSION devExt;
size_t bytesTransferred;
//
// Initialize locals
//
device = WdfDmaTransactionGetDevice(DmaTransaction);
devExt = PCIEGetDeviceContext(device);
#ifdef ASSOC_WRITE_REQUEST_WITH_DMA_TRANSACTION
request = WdfDmaTransactionGetRequest(DmaTransaction);
#else
//
// If CreateDirect was used then there will be no assoc. Request.
//
{
PTRANSACTION_CONTEXT transContext = PCIEGetTransactionContext(DmaTransaction);
request = transContext->Request;
transContext->Request = NULL;
}
#endif
//
// Get the final bytes transferred count.
//
bytesTransferred = WdfDmaTransactionGetBytesTransferred( DmaTransaction );
TraceEvents(TRACE_LEVEL_INFORMATION, DBG_DPC,
"PCIEWriteRequestComplete: Request %p, Status %!STATUS!, "
"bytes transferred %d\n",
request, Status, (int) bytesTransferred );
WdfDmaTransactionRelease(DmaTransaction);
WdfRequestCompleteWithInformation( request, Status, bytesTransferred);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -