Страниц: [1] 2 3 ... 11
  Печать  
Автор Тема: Помогите с DMA  (Прочитано 47172 раз)
vladx
Участник
*
Offline Offline

Сообщений: 0


Просмотр профиля
« : Января 19, 2005, 11:45:24 am »

Есть моя плата PCI. Пишу под нее драйвер. Все работает нормально: инициализируется, идут обмены с ПК (FIFO, DPRAM), т.е. с адресным пространством платы работаю нормально. Возникает естественное желание использовать DMA. Начинаю прграммировать PCI-контроллер(PLX9056), и возник у меня вопрос: программировать контроллер через его адресное пространство, полученное с помощью pci_attach_device(CpuBaseAddress[0]) или с помощью ф-ции pci_write_config? Попробовал и так и так - результат - один и тот же - DMA не запускается, хотя входное FIFO заполняется и запросы идут. Привожу кусок листинга, где пытаюсь программировать DMA:

uint32_t *addr; // Массив для получения данных
unsigned int __config_dma(unsigned int LID, unsigned int direction, volatile unsigned int *buffer, unsigned int size) {
unsigned int status, t=0, mode, *pd, i;

module_setup[LID].base_pci_addr = (volatile uint32_t*)mmap_device_memory(0, module_setup[LID].info_pci.BaseAddressSize[0], PROT_READ | PROT_WRITE | PROT_NOCACHE,  0,module_setup[LID].info_pci.CpuBaseAddress[0]);

addr = (uint32_t*)mmap( 0, 4096, PROT_READ|PROT_WRITE|PROT_NOCACHE, MAP_PHYS|MAP_ANON, NOFD, 0 );
mode = 0x19C3;
i = pci_write_config( module_setup[LID].pci_dev_hndl, P9X5X_DMA_MODE, 1, 4, (unsigned int *)&mode);
//module_setup[LID].base_pci_addr[P9X5X_DMA_MODE] = 0x19C3;
i = pci_write_config( module_setup[LID].pci_dev_hndl, P9X5X_DMA_PCI_ADDR, 1, 4, addr);
//(uint32_t *)module_setup[LID].base_pci_addr[P9X5X_DMA_PCI_ADDR] = addr;
mode = 0x08;
i = pci_write_config( module_setup[LID].pci_dev_hndl, P9X5X_DMA_LOC_ADDR, 1, 4, (unsigned int *)&mode);
//module_setup[LID].base_pci_addr[P9X5X_DMA_LOC_ADDR] = 0x08;
mode = 4096;
i = pci_write_config( module_setup[LID].pci_dev_hndl, P9X5X_DMA_SIZE, 1, 4, (unsigned int *)&mode);
//module_setup[LID].base_pci_addr[P9X5X_DMA_SIZE] = size;
mode = 0x9;
i = pci_write_config( module_setup[LID].pci_dev_hndl, P9X5X_DMA_PTR, 1, 4, (unsigned int *)&mode);
//module_setup[LID].base_pci_addr[P9X5X_DMA_PTR] = 0x09;
mode = 0x3;
i = pci_write_config( module_setup[LID].pci_dev_hndl, P9X5X_DMA_CMD, 1, 4, (unsigned int *)&mode);
//module_setup[LID].base_pci_addr[P9X5X_DMA_CMD] = 0x03;

Здесь P9X5X_DMA_XXX - PCI (OFFSET from Base Addres), заремленные строки - лезу через адресное пространство контроллера.
В винде это все нормально работает. Может в QNX еще что-нибудь сделать надо ? Или я что-то с памятью, куда данные хочу принимать, нахомутал ? Нужно выделить для приема - Value is a physical addres. Mmap может не подходит ?
Записан
lestat
QOR.Moderator
*****
Offline Offline

Сообщений: 985


I don't trust anything


Просмотр профиля WWW
« Ответ #1 : Января 19, 2005, 12:13:33 pm »

vladx
Привожу кусок листинга, где пытаюсь программировать DMA:

Это специфическое программирование BM DMA под PLX9056.
vladx
Или я что-то с памятью, куда данные хочу принимать, нахомутал ?

Именно !
vladx
Нужно выделить для приема - Value is a physical addres. Mmap может не подходит ?

Подходит, только надо еще и физический адрес получить, вот кусочек кода из моего аудио драйвера под vt8233:


   vt8233->array_tables = mmap(NULL, vt8233->array_tables_size, PROT_READ | PROT_WRITE | PROT_NOCACHE, MAP_ANON | MAP_PHYS, NOFD, 0);

   if (vt8233->array_tables == MAP_FAILED)
   {
      ado_error("ctrl_init(): VT8233: Unable to allocate array of pointers (%s) !
", strerror(errno));
      ado_mutex_destroy(&vt8233->hw_lock);
      ado_pci_release(vt8233->pci);
      ado_free(vt8233);
      return -1;
   }

   mem_offset64(vt8233->array_tables, NOFD, 1, &vt8233->array_physical, 0);

Записан

lestat
QOR.Moderator
*****
Offline Offline

Сообщений: 985


I don't trust anything


Просмотр профиля WWW
« Ответ #2 : Января 19, 2005, 12:21:53 pm »

Отправил раньше времени пост

Так вот vt8233->array_physical есть физический адрес в примере, который и следует использовать при программировании BM DMA. То что он 64 бит - не важно, нас устроит и младшие 32 бита.

P.S. Я бы посоветовал бы перегрузиться после этих неверных тестов с неправильным указателем ... мало ли куда попал этот адрес - я себе так один раз уже убил QNX 6.2
Записан

vladx
Участник
*
Offline Offline

Сообщений: 0


Просмотр профиля
« Ответ #3 : Января 19, 2005, 01:00:04 pm »

Huh?Huh?? ?? Huh???. Huh?Huh? Huh?Huh? Huh?:

unsigned int __config_dma(unsigned int LID, unsigned int direction, volatile unsigned int buffer, unsigned int size) {

off64_t       offset;
unsigned int *addr;

addr = (unsigned int*)mmap( 0, 4096, PROT_READ|PROT_WRITE|PROT_NOCACHE, MAP_PHYS|MAP_ANON, NOFD, 0 );
mem_offset64(addr, NOFD, 1, &offset, 0);

................................................... Huh?Huh? PCI Huh?Huh?
(unsigned long)module_setup[LID].base_pci_addr[P9X5X_DMA_PCI_ADDR] = offset;
....................................................

Huh?Huh?Huh? Huh? ??:  ? gdb ?? Huh?Huh? offset Huh?Huh?Huh?Huh?Huh?? Huh??....
Записан
vladx
Участник
*
Offline Offline

Сообщений: 0


Просмотр профиля
« Ответ #4 : Января 19, 2005, 01:06:04 pm »

Прошу прщения ))

Сделал так:

unsigned int __config_dma(unsigned int LID, unsigned int direction, volatile unsigned int buffer, unsigned int size) {

off64_t offset;
unsigned int *addr;

addr = (unsigned int*)mmap( 0, 4096, PROT_READ|PROT_WRITE|PROT_NOCACHE, MAP_PHYS|MAP_ANON, NOFD, 0 );
mem_offset64(addr, NOFD, 1, &offset, 0);

..................... Записываю PCI адрес
(unsigned long)module_setup[LID].base_pci_addr[P9X5X_DMA_PCI_ADDR] = offset;
....................................................

Результат то же: в gdb  по адресу offset наблюдаю сплошные нули ((
Записан
lestat
QOR.Moderator
*****
Offline Offline

Сообщений: 985


I don't trust anything


Просмотр профиля WWW
« Ответ #5 : Января 19, 2005, 01:12:13 pm »

vladx
в gdb по адресу offset наблюдаю сплошные нули

В gdb надо наблюдать по адресу addr.
Записан

vladx
Участник
*
Offline Offline

Сообщений: 0


Просмотр профиля
« Ответ #6 : Января 19, 2005, 01:13:07 pm »

о как! ща попробую.
Записан
lestat
QOR.Moderator
*****
Offline Offline

Сообщений: 985


I don't trust anything


Просмотр профиля WWW
« Ответ #7 : Января 19, 2005, 01:36:38 pm »

vladx
о как! ща попробую.

Физический адрес нужен только физическим устройствам, все остальное работает с виртуальными адресами.
Записан

vladx
Участник
*
Offline Offline

Сообщений: 0


Просмотр профиля
« Ответ #8 : Января 20, 2005, 10:16:01 am »

А есть ли в QNX разница между следующими способами работы с конф. пространством контроллера PCI:
1.*(module_setup[LID].base_pci_addr+P9X5X_DMA_PCI_ADDR) = offset;
2. pci_write_config( module_setup[LID].pci_dev_hndl, P9X5X_DMA_PCI_ADDR, 1, 4, addr);
Записан
lestat
QOR.Moderator
*****
Offline Offline

Сообщений: 985


I don't trust anything


Просмотр профиля WWW
« Ответ #9 : Января 20, 2005, 10:39:54 am »

vladx
1.*(module_setup[LID].base_pci_addr+P9X5X_DMA_PCI_ADDR) = offset;

Это способ доступа к конфигурационным регистрам, специфический только для P9X5X, запись идет через память.

К тому же в этом коде есть ошибка. Напрямую в base_pci_addr писать нельзя !!! Ибо эта память физическая ! Из нее нужно сделать указатель на виртуальную, которая принадлежит процессу.

mmap_device_memory - map a device's physical memory into a process's address space

Т.е. это обратное преобразование из физики в адрес процесса, функция обратная mem_offset64().

vladx
2. pci_write_config( module_setup[LID].pci_dev_hndl, P9X5X_DMA_PCI_ADDR, 1, 4, addr);


Тут тоже есть ошибка. В конфигурационный регистр P9X5X_DMA_PCI_ADDR запишется 4 байта, которые лежат по адресу addr. А нужно то, что содержит addr. Почему-то я видел везде в коде (unsigned int *)&mode, а тут просто addr Huh? Это сознательный ход ?

Это раз. Два - некоторые PCI адаптеры болезненно реагируют на запись под одному байту, если регистр по-настоящему 32-ух битовый (это неправильно, адаптеру должно быть все равно), но чтобы избегать таких проблем есть функция: pci_write_config32() которая пишет по 32 бита за раз. Это просто к сведению.

Три - всегда полезно читать из регистра и сверять с записанным значением, а действительно ли записалось то, что мы туда писали - убирает также много проблем с отладкой.

vladx
А есть ли в QNX разница между следующими способами работы с конф. пространством контроллера PCI

Если в обоих случаях убрать ошибки, то в принципе без разницы
Записан

vladx
Участник
*
Offline Offline

Сообщений: 0


Просмотр профиля
« Ответ #10 : Января 20, 2005, 10:54:08 am »

1. Не указал просто:
получаю base_pci_addr
module_setup[LID].base_pci_addr = (uint32_t*)mmap_device_memory(0, module_setup[LID].info_pci.BaseAddressSize[0], PROT_READ | PROT_WRITE | PROT_NOCACHE, 0, module_setup[LID].info_pci.CpuBaseAddress[0]);

2. Да, у меня идет так (просто старый код кинул, т.к. принципиально понять хотел ):
addr = (unsigned int*)mmap( 0, 1, PROT_READ|PROT_WRITE|PROT_NOCACHE, MAP_PHYS|MAP_ANON, NOFD, 0 );
mem_offset64(addr, NOFD, 1, &offset, 0);
 pci_write_config( module_setup[LID].pci_dev_hndl, P9X5X_DMA_PCI_ADDR, 1, 4, &offset);

Сейчас правильно ?
Записан
lestat
QOR.Moderator
*****
Offline Offline

Сообщений: 985


I don't trust anything


Просмотр профиля WWW
« Ответ #11 : Января 20, 2005, 11:07:08 am »

vladx
pci_write_config( module_setup[LID].pci_dev_hndl, P9X5X_DMA_PCI_ADDR, 1, 4, &offset);
Сейчас правильно ?

Вроде да.
Записан

vladx
Участник
*
Offline Offline

Сообщений: 0


Просмотр профиля
« Ответ #12 : Января 20, 2005, 11:21:09 am »

lestat
   Два - некоторые PCI адаптеры болезненно реагируют на      запись под одному байту, если регистр по-настоящему        32-ух битовый (это неправильно, адаптеру должно быть все   равно), но чтобы избегать таких проблем есть функция:      pci_write_config32() которая пишет по 32 бита за раз.

а разве данная запись не предполагает запись 4 байт:
pci_write_config( module_setup[LID].pci_dev_hndl, P9X5X_DMA_PCI_ADDR, 1, 4, &offset);
или
*(module_setup[LID].base_pci_addr+P9X5X_DMA_PCI_ADDR) = offset;
off64_t offset;
Записан
lestat
QOR.Moderator
*****
Offline Offline

Сообщений: 985


I don't trust anything


Просмотр профиля WWW
« Ответ #13 : Января 20, 2005, 11:39:02 am »

vladx
а разве данная запись не предполагает запись 4 байт:
pci_write_config( module_setup[LID].pci_dev_hndl, P9X5X_DMA_PCI_ADDR, 1, 4, &offset);

Нет, 4 раза по байту.
А тип module_setup[LID].base_pci_addr какой ? Не char* случайно ? Если да, то запишется один байт.
Записан

vladx
Участник
*
Offline Offline

Сообщений: 0


Просмотр профиля
« Ответ #14 : Января 20, 2005, 11:41:28 am »

lestat
   А тип module_setup[LID].base_pci_addr какой ? Не char*     случайно ?  Если да, то запишется один байт.

uint32_t       *base_pci_addr;
Записан
Страниц: [1] 2 3 ... 11
  Печать  
 
Перейти в: