[ Content | View menu ]

Linux kernel: определение совместимости драйвера с устройством

Опубликовано 29.01.2008

Иногда бывает необходимо определить, поддерживает ли имеющийся драйвер некое устройство. Например, когда планируется установка новой сетевой карты на работающий сервер или запуск специально собранного ядра на сервере с новейшим RAID-контроллером.

Как обычно, имеется несколько способов решения.

Способ первый: списки совместимости железа (HCL, hardware compatible lists).

Если используется родное ядро дистрибутива, то достаточно зайти на сайт производителя используемого дистрибутива Linux и найти там Hardware Compatibility List. Ещё производители серверного железа пишут, с какими ОС совместимы их устройства и иногда даже выкладывают драйвера с исходниками. Если с производителем оборудования повезло, то можно просто скачать и собрать последнюю версию драйвера.

Можно обратиться к Linux Hardware Compatibility HOWTO, но на данный момент (январь 2008) последняя дата обновления этого документа — 22 мая 2007 года, т.е. по меркам развития технологий очень давно. Ещё я не нашёл там ни одного контроллера Serial ATA, которые в последнее время очень распространены. Тем не менее, если интересующее вас устройство присутствует в этом документе, то оно наверняка поддерживается вашим ядром.

Существует несколько десятков сайтов, имеющих своей целью собрать абсолютно всю информацию о совместимости различного железа с Linux. Как правило, информация на таких сайтах добавляется посетителями и имеет формат «такая-то штука заработала под таким-то ядром в такой-то ОС после таких-то манипуляций с modprobe.conf» и может быть неверной или устаревшей. Примером такого сайта может являться Linux on laptops, содержащий список ссылок на статьи и заметки на тему установки различных дистрибутивов Linux на ноутбуки.

Способ второй: ручная проверка PCI IDs.

Вышеописанный метод гугления может лишь дать представление о том, поддерживается ли данное устройство вообще. Ответ на вопрос «поддерживается ли данный девайс данным ядром» можете дать только вы сами :)

Каждое устройство, подключаемое через шину PCI, имеет 8-байтный код, называемый PCI ID (и еще 8 байт, называемые Vendor ID, но нас они не интересуют). Первые четыре байта означают производителя, оставшиеся — собственно код устройства. Существует единый список известных кодов устройств http://pciids.sourceforge.net, используемый, в частности, командой lspci для отображения читабельного писка установленного оборудования (однако факт включения устройства в этот список вовсе не означает, что оно поддерживается Linux’ом :))

Драйвера Linux «подцепляют» железо по его PCI ID; список совместимых с данным драйвером девайсов «зашит» в структуре pci_device_id, Например, в драйвере sata_nv версии 0.09 из ядра 2.6.15 эта структура выглядит таким образом:

static const struct pci_device_id nv_pci_tbl[] = {
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NFORCE2 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NFORCE3 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NFORCE3 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA,PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
{ PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE<<8, 0xffff00, GENERIC },
{ PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_RAID<<8, 0xffff00, GENERIC },
{ 0, }
};

Поскольку драйвер sata_nv входит в состав ядра, то константы PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA и т.д. определены в файле /usr/src/linux/include/linux/pci_ids.h. Если же драйвер был скачан с сайта производителя, то необходимые константы могут быть переопределены в коде самого драйвера, grep вам в помощь :) Комбинируя значения этих констант со значением PCI_VENDOR_ID_NVIDIA, определённой в том же pci_ids.h, можно получить полный PCI ID устройства.

Эту же информацию можно извлечь из уже скомпилированного драйвера с помощью команды modinfo sata_nv, которая также выдаст список PCI IDs устройств, поддерживаемых данным драйвером. Есть еще файл /lib/modules/`uname -r`/modules.pcimap, содержащий сводную информацию о том, какие pci ids и vendor ids к какому модулю относятся, но в более подходящем для парсинга формате.Но в случае, если драйвер «вкомпилен» в ядро (например, в конфиге ядра (/usr/src/linux/.config или /proc/config.gz) указано CONFIG_SCSI_SATA_NV=y), то из скомпилированного ядра вытащить этот список очень проблематично . Хотя, наверно, как-то можно. Мне кажется, что проще залезть в исходники, надеясь, что в интересующей вас части они не изменились со времени последней компиляции.

Собственно определение совместимости драйвера с устройством состоит из двух этапов:

  1. выяснение PCI ID данного контроллера. Можно поискать его название, указанное в прилагаемой документации или на чипсете, в файле /usr/share/hwinfo/pci.ids (не забывайте его периодически обновлять с сайта http://pciids.sourceforge.net.) или на сайте производителя устройства. Если устройство уже подключено, то поможет команда lspci -nn
  2. проверка вхождения этого PCI ID в драйвер. Тут можно либо лезть в исходники драйвера, как описано выше, либо воспользоваться командой modinfo driver_name.

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

Бонус для тех, кто дочитал до этого места. Если у вас есть устройство, при загрузке оно почему-то не подцепляется автоматически и вы не знаете, какой драйвер с ним работает, вам поможет сервис Debian GNU/Linux device driver check page (никогда не устану ссылаться на эту страницу!). Он принимает вывод команды lspci -n и сообщает, какие драйвера подходят для имеющихся устройств. Можно просто указать PCI ID и это сработает.

«
»

4 комментария

Write a comment - TrackBack - RSS Comments

  1. Comment by WW:

    Спасибо! Добавил в RSS.

    30.01.2008 @ 01:40
  2. Comment by boombick:

    Спасибо большое! Очень хорошая статья.
    А отдельное спасибо за Debian GNU/Linux device driver check page

    30.01.2008 @ 15:32
  3. Pingback from Linux kernel: построение списка совместимости устройств для своего ядра | Bappoy’s blog:

    [...] предыдущей заметке был рассмотрен способ ручного определения [...]

    30.01.2008 @ 21:48
  4. Comment by softer:

    Спасибо за информацию.

    16.05.2008 @ 19:31
Write comment

Я не робот.