Русские Блоги
Подробное объяснение разработки драйвера устройства PCI под Linux
1. Описание шины PCI
PCI — это высокоскоростная шина передачи данных для связи между процессором и периферийными устройствами. Обычный PCIПропускная способность шиныОбычно 132 МБ / с (до 32 бит / 33 МГц) или 264 МБ / с (до 32 бит / 66 МГц).
Архитектура шины PCI представляет собой иерархическую архитектуру. Мостовое устройство PCI занимает важное место: оно соединяет родительскую шину и дочернюю шину вместе, так что вся система выглядит как перевернутая древовидная структура.
Мосты PCI включают в себя следующее:
Мост Host / PCI: используется для соединения ЦП и корневой шины PCI. В ПК контроллер памяти также обычно интегрирован в микросхему устройства моста Host / PCI. Мост Host / PCI обычно называют «чипсетом северного моста».
Мост PCI / ISA: используется для подключения старой шины ISA. Мост PCI / ISA также известен как «чипсет южного моста».
Мост PCI-PCI: используется для соединения основной шины PCI и вторичной шины.
Во-вторых, доступ к конфигурации пространства PCI
PCI имеет три типа адресного пространства: пространство PCI / IO, адресное пространство памяти PCI и пространство конфигурации PCI.
Пространство конфигурации PCI (всего 256 байт):
- Идентификация производителя: присваивается производителю организацией PCI.
- Идентификация оборудования: пронумеруйте эту карту согласно классификации продукта.
- Классификационный код: классификационный код этой функции карты.
- Подать заявку на пространство памяти: память или регистры и пространство ввода / вывода адресованы памятью на карте PCI, поэтому драйверы и приложения могут получить к ним доступ. Для этого используется регистр базовых адресов пространства конфигурации.
- Подать заявку на пространство ввода / вывода: Сконфигурируйте регистр базовых адресов пространства для применения к пространству ввода / вывода системы
- Приложение ресурса прерывания: применить к системе ресурс прерывания.
Ядро предоставляет функции для доступа драйвера к пространству конфигурации:
pci_read_config_byte/word/dword(struct pci_dev *pdev, int offset, int *value); pci_write_config_byte/word/dword(struct pci_dev *pdev, int offset, int *value);
PCI из I/O И пространство памяти:
получить I/O Или ресурсы памяти:
pci_resource_start (struct pci_dev * dev, int bar); / * Диапазон значений бара 0-5 * /
Эта функция возвращает первый адрес (адрес памяти или номер порта ввода / вывода) одной из шести областей ввода / вывода PCI.
pci_resource_end (struct pci_dev * dev, int bar) / * Диапазон значений бара 0-5 * /
Эта функция возвращает последний адрес области ввода / вывода панели. Обратите внимание, что это последний доступный адрес, а не первый адрес после области.
pci_resource_flags (struct pci_dev * dev, int bar) / * Диапазон значений бара 0-5 * /
Эта функция возвращает флаг, связанный с ресурсом. Флаг ресурса используется для определения определенных характеристик отдельного ресурса. Для ресурсов PCI, связанных с областью ввода / вывода PCI, эта информация получается из регистра базовых адресов, но для других ресурсов, не связанных с устройствами PCI, она может поступать откуда угодно. Все флаги ресурсов определены в , наиболее важные из них перечислены ниже:
Если соответствующая область ввода / вывода существует, будет установлен один из приведенных выше флагов, а есть только один.
Указанный выше флаг определяет, что область памяти может быть предварительно выбрана или защищена от записи. Для ресурсов PCI последний флаг никогда не устанавливается. Используя pci_resource_flags Функция драйвера устройства может полностью игнорировать основные регистры PCI, поскольку система использует эти регистры для построения информации о ресурсах.
приложение / релиз I/O Или ресурсы памяти:
int pci_request_regions(struct pci_dev *pdev, const char *res_name); void pci_release_regions(struct pci_dev *pdev);
получить / Установить личные данные диска:
void *pci_get_drvdata(struct pci_dev *pdev); void pci_set_drvdata((struct pci_dev *pdev, void *data);
Включить / запрет PCI оборудование:
int pci_enable_device(struct pci_dev *pdev); int pci_disable_device(struct pci_dev *pdev);
Установите основной автобус на DMA Режим:
void pci_set_master(struct pci_dev *pdev);
Ищем указанный слот указанного автобуса PCI оборудование:
struct pci_dev *pci_find_slot (unsigned int bus,unsigned int devfn);
Настроить PCI Статус энергоменеджмента:
int pci_set_power_state(struct pci_dev *pdev, pci_power_t state);
Найдите указанную емкость в таблице возможностей оборудования:
int pci_find_capability(struct pci_dev *pdev, int cap);
Включить недопустимую запись в память устройства:
int pci_set_mwi(struct pci_dev *pdev);
Отключить запись в память устройства недопустимой транзакции:
void pci_clear_mwi(struct pci_dev *pdev);
Три, состав драйвера устройства PCI
PCI По сути, это автобус, специфический PCI Устройство может быть символьным устройством, сетевым устройством, USB Подожди PCI Драйвер устройства должен состоять из двух частей:
Драйверы устройств на основе спроса являются конечной целью, PCI Драйвер является лишь средством, помогающим требуемому драйверу устройства достичь конечной цели. Другими словами PCI Драйверы устройств должны быть реализованы не только PCI Драйвер также должен реализовать драйвер устройства в соответствии с требованием.
Регистрация и отмена драйвера PCI:
int pci_register_driver(struct pci_driver * driver); int pci_unregister_driver(struct pci_driver * driver);
4. Резюме
Шина PCI в настоящее время широко используется в стандарте компьютерной шины, и это компьютерная шина с самой сильной совместимостью и наиболее полными функциями. Linux, как новая операционная система, также позволяет связывать шину PCI с различными новыми устройствами. Поскольку исходный код Linux открыт, относительно легко написать драйверы для любого устройства, подключенного к шине PCI. В этой статье рассказывается, как написать ключевой функциональный интерфейс драйвера PCI под Linux.