Здравствуйте.
Режим DMA под XP работает, а вот под windows 7 (32 бит) не хочет.
У меня алгоритм работы следующий.
1) Создаю объект AdapterObject;
2) Выделяю непрерывную физическую память под таблицу дескрипторов( Scatter/Gatcher для движка DMA контроллера ) и под буфер для DMA данных.
3) Подготавливаю таблицу дескрипторов.
4) Записываю в регистр контроллера физический адрес на первый дескриптор.
5) Запускаю движок DMA. (А он отрабатывает так как будто по этому физическому адресу он ничего не смог прочитать или прочитал ерунду).
Создаём AdapterObject, выделяем память и подготавливаем таблицу дескрипторов.
//Создаём AdapterObject, выделяем память и подготавливаем таблицу дескрипторов.
DEVICE_DESCRIPTION dd;
RtlZeroMemory(&dd, sizeof(dd));
dd.Version = DEVICE_DESCRIPTION_VERSION;
dd.Master = TRUE;
dd.ScatterGather = FALSE;
dd.InterfaceType = InterfaceTypeUndefined; //PCIBus; //InterfaceTypeUndefined;
dd.MaximumLength = PAGE_SIZE;
dd.Dma32BitAddresses = TRUE;
pdx->AdapterObject = IoGetDmaAdapter(pdx->Pdo, &dd, &pdx->nMapRegisters);
KdPrint(("pdx->nMapRegisters = %X\n", pdx->nMapRegisters)); //Возвращает цифру 8
...
//Выделим память для таблицы дескрипторов
rdDMA->VAdrDescTable[i] = (PDescriptorTable)(*pdx->AdapterObject->DmaOperations->AllocateCommonBuffer)
(pdx->AdapterObject, sizeTablDesc, &rdDMA->PhAdrDescTable[i], FALSE);
RtlZeroMemory( rdDMA->VAdrDescTable[i], sizeTablDesc );
//Выделим память для буффера
rdDMA->VAdrBufDma[i] = (PUCHAR)(*pdx->AdapterObject->DmaOperations->AllocateCommonBuffer)
(pdx->AdapterObject, sBufRd, &rdDMA->PhAdrBufDma[i], FALSE);
RtlZeroMemory(rdDMA->VAdrBufDma[i], sBufRd);
//Создадим mdl для буфера чтения DMA (для того чтобы можно было получить указатель USER_MODE)
rdDMA->MdlList[i] = IoAllocateMdl(rdDMA->VAdrBufDma[i], sBufRd, FALSE, FALSE, NULL);
MmBuildMdlForNonPagedPool(rdDMA->MdlList[i]);
//Подготовка таблиц чтения
PDescriptorTable rdt = rdDMA->VAdrDescTable[i];
ULONG sDescTabl = sizeof(DescriptorTable);
for (ULONG j = 0; j < cDescRead; j++)
{
rdt[j].source = 0;
rdt[j].destination = rdDMA->PhAdrBufDma[i].LowPart+(j*sDesc); //Физический адресс куда контроллер будет передовать данные
rdt[j].next_desc_ptr = (j==cDescRead-1) ? 0 : rdDMA->PhAdrDescTable[i].LowPart+(sDescTabl*(j+1)); //Физический адресс следующей таблицы дескрипторов
rdt[j].bytes_to_transfer = sDesc;
rdt[j].desc_control = OWNED_BY_HW;
rdt[j].desc_status = 0;
}
Выполняем чтение из DMA
WRITE_REGISTER_ULONG( NextDeskReg, pdx->workReadDMA->PhAdrDescTable[bufInReadDma->buf_id].LowPart ); //Записывается физический адрес первой таблицы дескрипторов
WRITE_REGISTER_ULONG( StatusReg, 0x1f);
WRITE_REGISTER_ULONG( ControlReg, 0);
//Запуск движка DMA
WRITE_REGISTER_ULONG( ControlReg, RUN | IE_ERROR | IE_EOP_ENCOUNTERED | IE_DESCRIPTOR_COMPLETED | IE_CHAIN_COMPLETED | IE_GLOBAL | PARK | CLEAR_INTERRUPT);
//
//Ожидание данных
//Дождемся окончания работы движка
while(TRUE)
{
st = READ_REGISTER_ULONG( StatusReg );
if (st & CHAIN_COMPLETED) // CHAIN_COMPLETED = 0x8
break;
KeQuerySystemTime(&curr);
if ((curr.QuadPart - start.QuadPart) > tout_interval.QuadPart)
{
*retErrCode = 0xFFFFFFFF;
pdx->lastCodeError = 7;
WRITE_REGISTER_ULONG( ControlReg, SW_RESET);
break;
}
}
//READ_REGISTER_ULONG( StatusReg ) под Windows 7 этот регистр равен 0x8 (Движок закончил работу но ни один из дескрипторов не был выполение)
if (READ_REGISTER_ULONG( StatusReg ) == 0xC) //0xС 1100 (2 бит - хотя бы один дескриптор был выполнен, 3 бит - движок ДМА закончил работу)
{
//Данные успешно сняты
}
else
{
//Ошибка
}
Я не могу понять почему под XP работает а под windows 7 не хочет.
Подскажите где надо искать проблему???
Спасибо.