Реализация драйвера устройства PCIe Linux (хочу получить доступ к регистрам моей карты из драйвера ядра) - PullRequest
4 голосов
/ 03 марта 2011

Я пишу драйвер устройства для доступа к памяти в FPGA на карте PCIe.
Карта загружается и проверяется / обнаруживается: -

/ proc / iomem

80000000-840fffff : PCI Bus #03
  80000000-83ffffff : 0000:03:00.0
  84000000-840fffff : 0000:03:00.0

Итак, читая ldd / etc, я кодировал вызов request_mem_region на 80000000 и запрашивал указатель на него через ioremap_nocache

1) Нужно ли request_mem_region какну как ioremap_nocache, я не могу использовать только последнее?

/ proc / iomem После insmod мой драйвер устройства: -

80000000-840fffff : PCI Bus #03
  80000000-83ffffff : 0000:03:00.0
    80000000-8003ffff : fp2
  84000000-840fffff : 0000:03:00.0

2) Мне не совсем подходит...?

В любом случае, чтение не работает (не кодировано, как показано ниже, есть проверки и т. Д.) : -

#define BAR_ADDR 0x80000000
void *base = ioremap_nocache(BAR_ADDR, 0x40000);
void *address = base + KNOWN_REG_LOCATION;
int data = ioread32(address);
printk("fp2: address:0x%08x, data:0x%08x\n", address, data);

Выходы: -

address:0xfd500000, data:0xffffffff

Я могу прочитать x80000000+KNOWN_REG_LOCATION из пользовательского пространства mmap.

3) Я попытался __raw_readl / readl, но тоже не повезло.

4) Могу ли я просто прочитать по текущему сопоставленному адресу x80000000?

1 Ответ

6 голосов
/ 04 марта 2011

Ian

Я написал драйвер PCI для устройства ( полный источник ). Однако отображение пространства регистров должно быть таким же. Вот как я это делаю.

dm7820_device->pci[region].virt_addr = ioremap_nocache(address, length);
if (dm7820_device->pci[region].virt_addr == NULL) {
    printk(KERN_ERR "%s: ERROR: BAR%u remapping FAILED\n",
        &((dm7820_device->device_name)[0]), region);
    dm7820_release_resources();
    return -ENOMEM;
}

if (request_mem_region(address, length, &((dm7820_device->device_name)[0])) == NULL) {
    printk(KERN_ERR "%s: ERROR: I/O memory range %#lx-%#lx allocation FAILED\n",
        &((dm7820_device->device_name)[0]), address, (address + length - 1));
    dm7820_release_resources();
    return -EBUSY;
}

Значения адреса и длины возвращаются из вызовов pci_resource_start() и pci_resource_length().

Затем вы можете получить к нему доступ, используя ioread32(), используя dm7820_device->pci[region].virt_addr + <register offset>

Дайте мне знать, если у вас есть какие-либо вопросы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...