Псевдокод алгоритма обнаружения устройства PCIe

У меня есть модель PCIe, написанная в System Verilog, хотя я думаю, что этот вопрос не зависит от языка. Модель выполняет чтение и запись конфигурации PCIe, а также чтение и запись в память при симуляции. Однако мне нужно «обнаружить» мое устройство PCIe и настроить регистры конфигурационного пространства в симуляции. Есть ли шаблонный фрагмент псевдокода, который представляет процесс перечисления Linux PCIe, что я могу просто добавить свои собственные функции транзакций моделей, чтобы я мог получить "Автобусную прогулку", за которой следует программирование BAR, включение SR-IOV, если оно обнаружено, Конфигурация MSIx? Похоже, это обычное упражнение для устройства PCIe, так что, возможно, есть модель.


person Rich Maes    schedule 18.01.2017    source источник


Ответы (1)


Сделать это не так уж и сложно. В основном вы просматриваете пространство конфигурации, проверяя каждое возможное устройство на первой корневой шине 0. Когда устройство найдено, вы выделяете для него пространство памяти на основе его запрошенного размера и соответственно программируете полосы BAR. Если вы обнаружите какие-либо мосты, вы также сконфигурируете и активируете их - базовые регистры моста для этого являются стандартными. Это включает в себя назначение номеров восходящей и нисходящей шины, что затем позволяет вам пронумеровать новую нисходящую шину и так далее.

Мне пришлось сделать это один раз, чтобы получить доступ к карте ввода-вывода PCI в системе, в которой не было ОС или другой программной среды. Это было неплохо, и это было через два моста от двух производителей, а также регистры карты ввода-вывода и настройку корневого моста шины ЦП. Это был PCI, а не PCIe, но он был бы почти таким же. Вы даже могли бы сделать это с полностью жестко закодированными числами, если бы оборудование никогда не менялось, но в моем случае было несколько вариантов, поэтому мне действительно пришлось выполнить простое перечисление, чтобы найти номера устройств динамически. Одна из проблем заключается в том, что вам, возможно, придется немного подождать или повторить попытку, чтобы дать всем устройствам время подключиться к сети, прежде чем вы попытаетесь получить к ним доступ.

При этом я нашел эту книгу бесценной: Архитектура системы PCI (4-е издание). Я заметил, что есть также версия для PCIe: Архитектура системы PCI Express (1-е издание). Я бы определенно получил один из них, если вы еще этого не сделали. Эти книги содержат подробные алгоритмы и объяснения того, как все это делать. В то время я действительно не использовал и не ссылался на какой-либо код, но ...

Лучший ресурс кода, который я нашел, - это U-Boot. Он работает на столь же низком уровне, полностью автономен, при этом довольно мал и максимально прост. Например, перечисление начинается с того, что функция pci_init() вызывает конкретную плату pci_xxx_init(). Затем это устанавливает корневой мост, а затем вызывает pci_hose_scan_bus() в drivers / pci / pci.c, чтобы выполнить реальную работу. Также ознакомьтесь с подпрограммами в drivers / pci / pci_auto.c, а также остальную часть папки.

Для вашей задачи вам, вероятно, понадобится очень небольшое подмножество, и вы можете просто вырезать части этих файлов в простой драйвер. В основном цикл for () и некоторые вызовы pci_read / write_config () с логикой для распознавания идентификаторов вашего устройства и моста.

person Anders    schedule 31.01.2017