Здравствуйте Уважаемы Знатоки!!!
Попала мне в руки PCIe-плата работающая с высокочастотными сигналами и соответственно с большими объемами данных, ну и конечно к ней шел мануал, где сказано: необходимо выделить два буфера по 64 МB.
Так вот написал драйвер прикрутил ДМА и получилось, как полагается, выделяется 32 МB на буфер, код настройки ДМА и буфера привожу ниже:
#define MAX_DMA_LENGTH 0x2000000 // 0x2000000 - 32 MB
//#define MAX_DMA_LENGTH 0x4000000 // 0x4000000 - 64 MB
//...
NTSTATUS MDMAIDmaAdapterAllocate(PMDMAI_DEVICE_EXTENSION pdx)
{
ULONG NumMapRegisters;
DEVICE_DESCRIPTION DeviceDescription;
KdPrint((DRIVERNAME " - Allocating DMA Adapter object...\n"));
// Verify object not already created
if (pdx->DMAAdapter)
{
KdPrint(("ERROR - DMA Adapter object already exist, unable to allocate\n"));
return STATUS_OBJECT_NAME_EXISTS;
}
// Clear device description
RtlZeroMemory(&DeviceDescription, sizeof(DEVICE_DESCRIPTION));
// Set device DMA properties
DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION; //перавя версия, нулевая исползуется только при IgnoreCounter = FALSE
DeviceDescription.Master = TRUE;
DeviceDescription.ScatterGather = FALSE;
DeviceDescription.DemandMode = TRUE;
DeviceDescription.AutoInitialize = FALSE;
DeviceDescription.Dma32BitAddresses = TRUE;
DeviceDescription.IgnoreCount = FALSE;//TRUE;
DeviceDescription.Reserved1 = FALSE;
DeviceDescription.Dma64BitAddresses = FALSE;
//devDescr.DoNotUse2 = 0; //=devDescr.BusNumber - NotUsed in WDM
DeviceDescription.DmaChannel = 0; //только для Slave устройств
DeviceDescription.InterfaceType = PCIBus;
DeviceDescription.DmaWidth = Width32Bits; // PCI default width
DeviceDescription.DmaSpeed = Compatible;//не для мастера? (только если value only if the machine's ACPI BIOS supports it)... ничего не понял
//devDescr.MaximumLength = ROUND_TO_PAGES(XXXXX/2);
DeviceDescription.MaximumLength = PAGE_SIZE; //в любом случае они просили округлить до PAGE_SIZE, да на здоровье!
//devDescr.DmaPort = 0; //говорят, что это устаревший параметр. но нужен для совместимости... для Legacy...
// OS will assign map register count
NumMapRegisters = 0;
// Allocate a DMA adapter object
pdx->DMAAdapter = IoGetDmaAdapter(pdx->PhysicalDeviceObject, &DeviceDescription, &NumMapRegisters);
if (!pdx->DMAAdapter)
{
KdPrint(("ERROR - DMA Adapter allocation failed\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
KdPrint((" MAX_DMA_LENGTH: %d, ROUND_TO_PAGES(MAX_DMA_LENGTH): %d \n", MAX_DMA_LENGTH, ROUND_TO_PAGES(MAX_DMA_LENGTH)));
//выделяем нужную память ДМА под каждый буфер...
m_DmaBuffer1 = pdx->DMAAdapter->DmaOperations->AllocateCommonBuffer(
pdx->DMAAdapter, ROUND_TO_PAGES(MAX_DMA_LENGTH), &DmaPhysAddr1, FALSE);
m_DmaBuffer2 = pdx->DMAAdapter->DmaOperations->AllocateCommonBuffer(
pdx->DMAAdapter, ROUND_TO_PAGES(MAX_DMA_LENGTH), &DmaPhysAddr2, FALSE);
if ((!m_DmaBuffer1)||(!m_DmaBuffer2))
{
pdx->DMAAdapter = NULL;
KdPrint((" Failed to allocate DMA buffer\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
DmaBufferMemory1 = IoAllocateMdl(m_DmaBuffer1, ROUND_TO_PAGES(MAX_DMA_LENGTH), FALSE, FALSE, NULL);//ROUND_TO_PAGES(MAX_DMA_LENGTH)
DmaBufferMemory2 = IoAllocateMdl(m_DmaBuffer2, ROUND_TO_PAGES(MAX_DMA_LENGTH), FALSE, FALSE, NULL);
if ((DmaBufferMemory1 != NULL)||(DmaBufferMemory2 != NULL))
{ //MmBuildMdlForNonPagedPool заполняет массив номеров физических страниц и обновляет некоторые поля заголовка MDL.
KdPrint((DRIVERNAME " - SHOW SIZE DMS 1: %d \n", DmaBufferMemory1->Size));
MmBuildMdlForNonPagedPool(DmaBufferMemory1);
KdPrint((DRIVERNAME " - SHOW SIZE DMS 2: %d \n", DmaBufferMemory2->Size));
MmBuildMdlForNonPagedPool(DmaBufferMemory2);
}
else
{
KdPrint((" Failed to allocate MDL buffer \n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
//Получаем начальные адреса буферов ДМА...
uDmaPhysAddr1 = DmaPhysAddr1.LowPart;
KdPrint((DRIVERNAME " - SHOW DMA 1 ADDRESS IN START %Xh\n", uDmaPhysAddr1));
uDmaPhysAddr2 = DmaPhysAddr2.LowPart;
KdPrint((DRIVERNAME " - SHOW DMA 2 ADDRESS IN START %Xh\n", uDmaPhysAddr2));
if ((uDmaPhysAddr1 == 0)||(uDmaPhysAddr2 == 0))
{
KdPrint((" Failed to allocate uDmaPhysAddr \n"));
MDMAIDmaAdapterFree(pdx);
return STATUS_INSUFFICIENT_RESOURCES;
}
KdPrint((DRIVERNAME " - DMA Adapter init... OK!!! \n"));
return STATUS_SUCCESS;
}
функция IoAllocateMdl не выделяет память для MDL. наверняка есть механизмы обхода такой ситуации?!
Как можно расширить буфер до 64 МВ???
чуть не забыл ОС ХР 32 бит...
Прошу Вашей помощи!
Огромное спасибо!