Как написать драйвер для pci устройства
Есть новое PCI Express устройство. Устройство новое в том смысле, что полностью проектируется и разрабатывается буквально «с нуля» нашей группой.
Моя задача — написать драйвер для этого устройства. Никогда раньше не занимался разработкой драйверов.
Сейчас стоит вопрос об инструменте. Как я понял, есть несколько вариантов:
— WDM
— WDF
— средства типа Jungo WinDriver
Специалисты советовали использовать WDM. WinDriver рекомендовали, как «простое и быстрое» средство.
А WDF, как я понимаю, относительно свежая вещь. О ней мало что узнать удалось.
Но с тех пор, думаю, много что изменилось.
Итак, вопрос. Какой инструмент посоветуйте?
С уваженеим,
Сергей
От: | Геннадий Майко | |
Дата: | 06.04.10 14:29 | |
Оценка: | 2 (1) +1 |
Здравствуйте, chaika_sv,
_>Есть новое PCI Express устройство. Устройство новое в том смысле, что полностью проектируется и разрабатывается буквально «с нуля» нашей группой.
_>Моя задача — написать драйвер для этого устройства. Никогда раньше не занимался разработкой драйверов.
_>Сейчас стоит вопрос об инструменте. Как я понял, есть несколько вариантов:
_> — WDM
_> — WDF
_> — средства типа Jungo WinDriver
_>Специалисты советовали использовать WDM. WinDriver рекомендовали, как «простое и быстрое» средство.
_>А WDF, как я понимаю, относительно свежая вещь. О ней мало что узнать удалось.
_>Итак, вопрос. Какой инструмент посоветуйте?
—
Я разрабатывал драйвера для PCI Express микросхем и в виде WDM, и в виде WDF/KMDF драйверов. Однозначно разработка такого драйвера с использование WDF для меня была проще (в одном из прошлых проектов у меня были два дрйвера WDM и WDF с идентичной функциональностью). Правда, при этом потребовалось некоторое время, чтобы освоить WDF. Сейчас время освоения WDF можно значительно сократить, ибо есть уже, например, книга «Developing Drivers with Windows Driver Foundation» by Penny Orwick and Guy Smith.
Так что мой совет — только WDF.
C Jungo WinDriver знаком, но для себя решил принципиально его не использовать, чтобы не попадать в зависимость от другой компании.
C уважением,
Геннадий Майко.
От: | Pzz | https://github.com/alexpevzner | |
Дата: | 06.04.10 16:21 | ||
Оценка: | 2 (1) |
Здравствуйте, chaika_sv, Вы писали:
_>Есть новое PCI Express устройство. Устройство новое в том смысле, что полностью проектируется и разрабатывается буквально «с нуля» нашей группой.
_>Моя задача — написать драйвер для этого устройства. Никогда раньше не занимался разработкой драйверов.
_>Сейчас стоит вопрос об инструменте. Как я понял, есть несколько вариантов:
_> — WDM
_> — WDF
_> — средства типа Jungo WinDriver
Ну для начала надо определиться с тем, что делает данное устройство. Потому что для некоторых классов устройств (например, для сетевых карт) драйвера пишутся совсем по-другому.
WinDriver’ом я бы пользоваться не посоветовал, если устройство будет выпускаться не в единичных экземплярах. Драйвер, написанный на WinDriver’е невозможно сертифицировать по мелкософтовским правилам, а значит, у пользователей будут проблемы с инсталляцией.
_>Специалисты советовали использовать WDM. WinDriver рекомендовали, как «простое и быстрое» средство.
_>А WDF, как я понимаю, относительно свежая вещь. О ней мало что узнать удалось.
WDF — это обертка над WDM, которая должна, по идее, упрощать жизнь. Мелкософт ее сейчас активно продвигает. Я думаю, WDF — это безопасный выбор, но AFAIK не все классы устройств им все еще поддержаны.
От: | eagersh | |
Дата: | 06.04.10 19:59 | |
Оценка: | 2 (1) |
_>Но с тех пор, думаю, много что изменилось.
_>Итак, вопрос. Какой инструмент посоветуйте?
_>С уваженеим,
_>Сергей
Если ваше устройство не будет принадлежать к какому то определенному классу или другими словами управляться Port драйвером, как например NDIS, то однозначно WDF.Особенно если ты раньше драйвера не писал. WDK содержит хороший пример драйвера для PCI устройства.
\WinDDK\XXXXX\src\general\PLX9x5x
Это драйвер для устройства на базе PLX чипа.Пример также показывает как работать с DMA которые часто имеют PCI устройства.
Так как ты не писал драйвера раньше то рекомендую купить железо для этого драйвера. Будет легче разбираться с примером. OSR писал этот драйвер и на OSR по-моему можно купить железо для драйвера.
От: | chaika_sv | wmryb.ru | |
Дата: | 07.04.10 06:25 | ||
Оценка: |
Здравствуйте, Геннадий Майко, Вы писали:
От: | chaika_sv | wmryb.ru | |
Дата: | 07.04.10 07:12 | ||
Оценка: |
Здравствуйте, Pzz, Вы писали:
Pzz>WDF — это обертка над WDM, которая должна, по идее, упрощать жизнь. Мелкософт ее сейчас активно продвигает. Я думаю, WDF — это безопасный выбор, но AFAIK не все классы устройств им все еще поддержаны.
Спасибо большое за советы. По устройству.
Это устройство для соединения двух компьютеров по схеме «точка-точка». На обоих компьютерах есть микросхемы PCI Express, которые собственно и соединены кабелем.
Не вдаваясь в особенности нашей схемы соедения, скажу, что вся соль именно в кабеле.
Моя же задача (задача драйвера) — работать с буфером микросхемы. Помещать в него данные на микросхеме передатчика и извлекать данные из буфера на микросхеме приёмника.
От: | chaika_sv | wmryb.ru | |
Дата: | 07.04.10 07:15 | ||
Оценка: |
_>>Но с тех пор, думаю, много что изменилось.
_>>Итак, вопрос. Какой инструмент посоветуйте?
_>>С уваженеим,
_>>Сергей
E>Если ваше устройство не будет принадлежать к какому то определенному классу или другими словами управляться Port драйвером, как например NDIS, то однозначно WDF.Особенно если ты раньше драйвера не писал. WDK содержит хороший пример драйвера для PCI устройства.
E>\WinDDK\XXXXX\src\general\PLX9x5x
E>Это драйвер для устройства на базе PLX чипа.Пример также показывает как работать с DMA которые часто имеют PCI устройства.
E>Так как ты не писал драйвера раньше то рекомендую купить железо для этого драйвера. Будет легче разбираться с примером. OSR писал этот драйвер и на OSR по-моему можно купить железо для драйвера.
Спасибо за советы.
Особенно за ссылку на пример в WDK.
От: | Pzz | https://github.com/alexpevzner | |
Дата: | 07.04.10 14:10 | ||
Оценка: |
Здравствуйте, chaika_sv, Вы писали:
_>Спасибо большое за советы. По устройству.
_>Это устройство для соединения двух компьютеров по схеме «точка-точка». На обоих компьютерах есть микросхемы PCI Express, которые собственно и соединены кабелем.
_>Не вдаваясь в особенности нашей схемы соедения, скажу, что вся соль именно в кабеле.
_>Моя же задача (задача драйвера) — работать с буфером микросхемы. Помещать в него данные на микросхеме передатчика и извлекать данные из буфера на микросхеме приёмника.
Ну так по описанию звучит как WDM (или WDF).
А не хотите из своего устройства сетевой интерфейс сделать, который выглядел бы как Ethernet? Тогда вы сможете использовать сокеты для пересылки собственно данных, вместо того, чтобы изобретать самодельные протоколы.
От: | chaika_sv | wmryb.ru | |
Дата: | 08.04.10 05:40 | ||
Оценка: |
Здравствуйте, Pzz, Вы писали:
Pzz>А не хотите из своего устройства сетевой интерфейс сделать, который выглядел бы как Ethernet? Тогда вы сможете использовать сокеты для пересылки собственно данных, вместо того, чтобы изобретать самодельные протоколы.
Уточните, пожалуйста, что Вы имели ввиду?
Расскажу подробнее о соединении:
Есть плата PCI Express. На ней передатчик — лазеры и приёмник — фотодиоды (соединение оптоволоконное).
Передатчик и приёмник управляются микроконтроллером платы, там свои драйвера.
Моя задача — написать драйвер, который получается реализует протоколы сетевого и транспортного уровней.
Функции этих протоколов в общих чертах — разбивка потока данных на пакеты на стороне передатчика и обратная их сборка на приёмнике.
Пакеты надо по одному передавать в PCI Express (в его буфер).
От: | Pzz | https://github.com/alexpevzner | |
Дата: | 08.04.10 10:21 | ||
Оценка: |
Здравствуйте, chaika_sv, Вы писали:
Pzz>>А не хотите из своего устройства сетевой интерфейс сделать, который выглядел бы как Ethernet? Тогда вы сможете использовать сокеты для пересылки собственно данных, вместо того, чтобы изобретать самодельные протоколы.
_>Уточните, пожалуйста, что Вы имели ввиду?
Можно было бы написать к вашей железке драйвер, который с точки зрения операционной системы выглядит, как сетевой. Соответственно, все пакеты, которые система хочет через него отправить, он должен пересылать на другую сторону веревки. Все, что из веревки пришло, он должен отдавать системе как принятый пакет.
Если так сделать, то между компьютерами, соединенными вашей веревкой, можно будет гонять настоящую сеть — все эти TCP, UDP, IP и т.п. Причем реализация их есть в системе уже готовая, и это будет не ваша забота.
От: | eagersh | |
Дата: | 08.04.10 17:11 | |
Оценка: |
Здравствуйте, Pzz, Вы писали:
Pzz>Здравствуйте, chaika_sv, Вы писали:
Pzz>>>А не хотите из своего устройства сетевой интерфейс сделать, который выглядел бы как Ethernet? Тогда вы сможете использовать сокеты для пересылки собственно данных, вместо того, чтобы изобретать самодельные протоколы.
_>>Уточните, пожалуйста, что Вы имели ввиду?
Pzz>Можно было бы написать к вашей железке драйвер, который с точки зрения операционной системы выглядит, как сетевой. Соответственно, все пакеты, которые система хочет через него отправить, он должен пересылать на другую сторону веревки. Все, что из веревки пришло, он должен отдавать системе как принятый пакет.
Pzz>Если так сделать, то между компьютерами, соединенными вашей веревкой, можно будет гонять настоящую сеть — все эти TCP, UDP, IP и т.п. Причем реализация их есть в системе уже готовая, и это будет не ваша забота.
А зачем ему эмулировать настоящую сеть если у него растояние между компьютерами пару метров и соединение точка-точка? В любом случае ему надо будет писать обмен через PCI и для твоего решения эмулировать Ethernet, разрабатывая что-то типа virtual NDIS miniport driver.Дополнительная работа без явных преимуществ.
От: | Pzz | https://github.com/alexpevzner | |
Дата: | 08.04.10 21:37 | ||
Оценка: |
Здравствуйте, eagersh, Вы писали:
E>А зачем ему эмулировать настоящую сеть если у него растояние между компьютерами пару метров и соединение точка-точка? В любом случае ему надо будет писать обмен через PCI и для твоего решения эмулировать Ethernet, разрабатывая что-то типа virtual NDIS miniport driver.Дополнительная работа без явных преимуществ.
Ему все равно какой-то драйвер писать, почему бы не NDIS miniport? Тем более, что их проще писать, чем многие другие. Но зато это избавит его от написания стека протоколов более высокого уровня — а иначе от него не отвертеться.
написать драйвер для своего устройства
Есть некое устройство (на базе ПЛИС), которое видится в системе через lspci, оно сконфигурировано, назначены адресные пространства и т.д. Осилена книга «PCI Express Technology. Comprehensive Guide to Generations 1.x, 2.x, 3.0», принципы работы PCI Express стали полностью понятны.
Теперь нужно с этим устройством работать. Для этого требуется свой драйвер для ОС Linux. Есть крохи информации в LDD3 (почти бесполезные), есть такой пример http://www.fpga4fun.com/PCI6.html
Подскажите какой-нибудь простейший пример PCI драйвера (самый маленький в ядре), или может есть руководство или книжка на эту тему.
Требуется: самый наипростейший интерфейс, чтобы устройство виделось как файл и его можно было бинарно считывать (с большой скоростью, разумеется).
Ух ты! Люто спасибирую анонимуса!
Так что ответы еще принимаются, всё же надо что-то более полноценное.
А что, разве в LDD не описано, как писать драйвер для PCI-устройств? Для доступа из user space можно оформить все это хозяйство как char-устройство, к примеру.
А вариант сделать мост на usb3 (для большой скорости) через ftdi или cypress рассматривался? Ведь подключить эти не очень дорогие чипы, наверняка, довольно просто. С программной точки зрения, по-моему, это простые FIFO. Да ещё и гибко в плане подключения ПЛИС к ПК.
Суть не просто связать устройство с ПК (и не только ПК!) максимально простым способом (а таких куча, в том числе и через USB3 тех же FTDI и др.), а разработать именно полноценное PCI устройство.
а разработать именно полноценное PCI устройство
занимались мы такой работой в одной компании. причём много лет. в среднем, на разработку, отладку и выкатку в продакшен одной серьёзной PCIe платы уходило не меньше года. это если специалисты опытные, заранее знают всё о шине и уже имеют опыт разработки, разводки и т.д. и если все схемы с заказом печати и пайки отлажены.
там проблемы не столько в протоколе, сколько в реальной работе с разными мамками. вот когда настоящий зоопарк появляется! потому что стандарты стандартами, а в реальной жизни это нифига не так. и у каждой мамки свои косяки. мелкие, но часто достаточные для того, чтобы долго колупаться с осциллом (а там ещё и осцилл нужен недешёвый, кстати), чтобы понять, почему оно не работает.
Я такой еж, что меня голой не напугаешь 🙂
Если не секрет, что вы в Vendor ID писали? 🙂
Если не секрет, что вы в Vendor ID писали?
мы сначала делали ваще ISA платы. потом PCI. потом купили мост PCI-PCIe и начали «по-быстрому» переводить платы на PCIе, потому что PCI чипы к тому времени вообще уже снимали с производства. но PCIe тогда только начинался. возможно, он был ещё довольно сырой. но по-быстрому у нас не получилось. поимели много тараканов с синхронизацией сигналов на шине. причём с некоторыми мамками всё работало искаропки, а с некоторыми возникали таинственные глюки. иногда оказывалось, что мамки не совсем точно соблюдают стандарты и кое-где тайминги выше, чем допустимо, например. вплоть до тупых несоответствий по размеру слота (да, и такое бывало) или хреновых контактов в этих слотах. а нам надо было обмен скоростной организовать через DMA, это был захват изображений, очень большой поток данных и его ещё надо было ещё всяко нарезать на лету, чтобы скармливать программистам уже более-менее готовенькое. в итоге мы года полтора корячились и таки заставили это всё работать. но гемора было много и документации пришлось перелопатить просто тыщи страниц.
потом ещё долго искали, кто нам напечатает платы. в итоге, печатали их в Тайване и BGA запаивали там же. зато тайцы сделали всё как полагается. ни одной(!) бракованной платы из партии в несколько тыщ штук. при том, что BGA-шек там было много, платы восьмислойные и шаг местами был до 0.1. и они нигде не накосячили с металлизацией и пропаем BGA-шек. в сравнении с нашими, где отсев по браку иногда составлял до 40% плат, это было просто небо и земля.
а как тогда вообще материнки с рандомными ширпотребными девайсами работают? 🙂 Их же должны как-то тестировать на производстве, втыканием какой-нибудь эталонной PCIe карты хотя бы
На самом низком физическом уровне PCIe прост как тапок, достаточно соблюдать несложные правила, к тому же стабильность клока допустима до 300 ppm если не ошибаюсь, что весьма комфортно. Да и пакеты тоже стандартизированы.
Ладно, спасибо Iron_Bug за предупреждение, буду иметь ввиду что могут быть проблемы.
Топовым видеокартам не нужны скорости и нагрузки? Ладно, не суть.
Раз ваша фирма создавала устройства, то по каким учебным материалам сотрудники учились писать драйвер для скоростей?
Раз ваша фирма создавала устройства, то по каким учебным материалам сотрудники учились писать драйвер для скоростей?
кстати, правильно замечено, что под Linux писать дрова гораздо проще. мне приходилось писать и под маздай, причём даже ещё под 98-й. под Linux-ом хоть отлаживать это всё по-человечески можно, это вообще праздник по сравнению с офтопиком.
Сам же юзер-интерфейс там таков, что надо генерить TLP пакеты самому, хотя без CRC, заголовки соображать и т.д., это чуть сложнее чем у тех же Xilinx, но так даже интереснее.
Наверное пару недель у меня займет подготовка. А потом хочется сделать так, чтобы драйвер запрашивал один маленький простой пакет, а я в ответ бы пытался что-то выслать.
O_o А я учился еще по LDD2.
Чего не хватает в профильной главе LDD3?
Я потом скажу, вероятно обработка прерываний и работа через mmap описана в других разделах, может поэтому мне, нубу, эта инфа показалась отрывочной, надо читать с нуля походу всю книгу.
Iron_Bug В общем, сделал устройство со своими ID (AAAA/BBBB), один регион памяти 4 килобайта:
А теперь конкретный вопрос: где смотреть результаты pci_request_regions? В lspci видно что в данный конкретный момент моему устройству выделена память начиная с fe9ff000 и так до fe9fffff, т.е. 4К. Где увидеть этот адрес в драйвере, через какие структуры? Как осуществить запись N байт начиная с fe9ff000? Но для начала этот адрес еще узнать надо.
Обычно после pci_request_regions() (или аналогичного request_mem_region()) вызывается ioremap_nocache() или аналоги, после чего можно читать и писать в регистры PCI-устройства через ядерные процедуры
Пример: https://github.com/bluecherrydvr/linux/blob/tw5864/drivers/media/pci/tw5864/t. (хотел бы дать пример из основного репозитория ядра, но пример из своего драйвера, которого ещё там нет, кажется более простым для понимания).
Память мапится примерно так:
Макросы, упомянутые в предыдущем посте, нужно делать типобезопасными inline-функциями:
В дальнейшем я конечно сделаю гораздо больший регион памяти, и буду считывать поочередно разные участки (типа swap buffers).
как считать сразу весь блок 4К при помощи механизма DMA
Насколько я понимаю DMA, тебе нужно дать команду своему PCI-устройству о том, чтобы устройство записало 4К в заданный физический адрес в оперативке. Саму команду опять же обычно отправляют через запись в какой-то регистр.
Дело в том что на стороне ПЛИС само понятие DMA в моем случае бессмысленно, я там просто получаю ряд пакетов, в которых есть команда записать N байт начиная с некоторого адреса, может я их вообще в FIFO запихивать буду, не важно.
А вот как на стороне драйвера ОС Linux инициировать процесс записи (например 1 мегабайта) без участия процессора? Этакое memcpy где я просто откуда куда и сколько байт.
Равно как и чтение, чтобы прочитать сразу N байт начиная с определенного адреса (а этот адрес как раз начало того что записано у меня в BAR0).