Драйвер шины что делает

До сих пор мы видели немало низкоуровневой инфраструктуры и относительно мало примеров. Мы постараемся компенсировать это в оставшейся части этой главы, как только мы перейдём на более высокие уровни модели устройства Linux. С этой целью мы вводим новую виртуальную шину, которую мы называем lddbus (* Логичным именем для этой шины, конечно, было бы «sbus», но это название уже было взято настоящей, физической шиной.) , и изменяем драйвер scullp для «подключения» к этой шине. Ещё раз, большая часть прочитанного здесь никогда не потребуется многим авторам драйверов. Подробности этого уровня, как правило, обрабатываются на уровне шины, и небольшому числу авторов потребуется добавить новый тип шины. Однако, эта информация является полезной для тех, кому интересно, что происходит внутри PCI, USB и других уровнях или кому требуется сделать изменения на этом уровне.

Шина является каналом между процессором и одним или несколькими устройствами. Для целей модели устройства, все устройства подключаются через шину, даже если она является внутренней, виртуальной, «инструментальной» шиной. Шины могут подключаться друг в друга — контроллер USB, к примеру, обычно представляет собой PCI устройство. Модель устройства отражает фактические связи между шинами и устройствами, которыми они управляют.

В модели устройства Linux шина представлена структурой bus_type , определённой в
. Эта структура выглядит следующим образом:

int (*match)(struct device *dev, struct device_driver *drv);

struct device *(*add)(struct device * parent, char * bus_id);

int (*hotplug) (struct device *dev, char **envp,

int num_envp, char *buffer, int buffer_size);

Поля name является именем этой шины, что-нибудь такое, как pci. Вы можете видеть из структуры, что каждая шина имеет собственную подсистему; однако, эти подсистемы не живут на верхнем уровне в sysfs. Вместо этого, они находятся под шинной подсистемой. Шина содержит два kset-а, представляющих известные драйверы для этой шины и все устройства, подключенные к шине. Затем существует набор методов, которые мы получим в ближайшее время.

Регистрация шины

Как мы уже отмечали, исходник примера включает реализацию виртуальной шины под названием lddbus . Эта шина создаёт свою структуру bus_type следующим образом:

struct bus_type ldd_bus_type = bus_id, driver->name, strlen(driver->name));

Когда речь идёт о реальном оборудовании, функция match обычно делает какое-то сравнение между идентификационным номером оборудования, предоставляемым самим устройством, и идентификаторами, поддерживаемыми драйвером.

Читайте также: Резина рейтинг летних шин r16

Метод горячего подключения в lddbus выглядит следующим образом:

static int ldd_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)

if (snprintf(buffer, buffer_size, «LDDBUS_VERSION=%s»,

Здесь мы добавляем в него номер текущей версии исходного кода lddbus , на случай, если кто-нибудь полюбопытствует.

Перебор устройств и драйверов

Если вы пишете код шинного уровня, вам может потребоваться выполнять некоторые операции со всеми устройствами или драйверами, которые были зарегистрированы на вашей шине. Может быть заманчиво копаться непосредственно в структурах в структуре bus_type , но лучше использовать предоставленные вспомогательные функции.

Для работы с каждым устройством, известном шине, используйте:

int bus_for_each_dev(struct bus_type *bus, struct device *start,

void *data, int (*fn)(struct device *, void *));

Эта функция перебирает все устройства на шине, передавая связанную структуру device в fn , вместе со значением, передаваемым как data . Если start является NULL, итерация начинается с первого устройства на шине; в противном случае итерация начинается с первого устройства после start . Если fn возвращает ненулевое значение, итерация останавливается и такое значение является возвращённым из bus_for_each_dev .

Существует аналогичная функция для перебора драйверов:

int bus_for_each_drv(struct bus_type *bus, struct device_driver *start,

void *data, int (*fn)(struct device_driver *, void *));

Эта функция работает подобно bus_for_each_dev , за исключением, конечно, что вместо этого она работает с драйверами.

Следует отметить, что обе эти функции в течение работы удерживают шинный семафор подсистемы чтения/записи. Так что попытка использовать их обе вместе приведёт к взаимоблокировке, каждая будет пытаться получить один и тот же семафор. Операции, которые изменяют шину (такие, как отмена регистрации устройств), также будут блокироваться. Таким образом, используйте функцию bus_for_each с некоторой осторожностью.

Атрибуты шины

Почти каждый слой в модели устройства Linux предоставляет интерфейс для добавления атрибутов и уровень шины не является исключением. Тип bus_attribute определён в
следующим образом:

ssize_t (*show)(struct bus_type *bus, char *buf);

ssize_t (*store)(struct bus_type *bus, const char *buf, size_t count);

Мы уже видели struct attribute в разделе «Атрибуты по умолчанию». Тип bus_attribute также включает в себя два метода для отображения и установки значения атрибута. Большинство уровней модели устройства над уровнем kobject-а работают таким образом. Для создания во время компиляции и инициализации структуры bus_attribute был предусмотрен удобный макрос:

BUS_ATTR(name, mode, show, store);

Этот макрос декларирует структуру, создавая её название, предваряя заданное name строкой bus_attr_ .

Любые атрибуты, принадлежащие шине, должны быть созданы явно с помощью bus_create_file :

int bus_create_file(struct bus_type *bus, struct bus_attribute *attr);

Атрибуты также могут быть удалены с помощью:

void bus_remove_file(struct bus_type *bus, struct bus_attribute *attr);

Драйвер lddbus создаёт простой файл атрибута, опять же содержащий номер версии исходника. Метод show и структура bus_attribute создаются следующим образом:

static ssize_t show_bus_version(struct bus_type *bus, char *buf)

return snprintf(buf, PAGE_SIZE, «%s\n», Version);

static BUS_ATTR(version, S_IRUGO, show_bus_version, NULL);

Создание атрибутного файла производится на время загрузки модуля:

if (bus_create_file(&ldd_bus_type, &bus_attr_version))

printk(KERN_NOTICE «Unable to create version attribute\n»);

Этот вызов создаёт атрибутный файл ( /sys/bus/ldd/version ), содержащее номер ревизии кода lddbus .

Видео:Код 28 — для устройства не установлены драйверы в Windows 10 и Windows 7 (решение)Скачать

Код 28 — для устройства не установлены драйверы в Windows 10 и Windows 7 (решение)

Устройства

На самом низком уровне, каждое устройство в системе Linux представлено экземпляром struct device :

struct device_driver *driver;

void (*release)(struct device *dev);

Есть много других полей struct device , которые представляют интерес только для кода ядра устройства. Эти поля, однако, стоит знать:

Устройство-«родитель» для устройства — то устройство, к которому оно подключено. В большинстве случаев родительским устройством является какая-то шина или хост-контроллер. Если parent является NULL, устройство является устройством верхнего уровня, которое обычно не то, что вы хотите.

Kobject, который представляет это устройство и подсоединяет его в эту иерархию. Заметим, что как правило device->kobj->parent эквивалентен &device-parent->kobj .

Строка, которая однозначно идентифицирует это устройство на этой шине. PCI устройства, например, используют стандартный формат PCI идентификатора, содержащий домен, шину, устройство и функциональные номера.

Определяет, на каком виде шины находится устройство.

struct device_driver *driver;

Драйвер, который управляет этим устройством; мы изучаем struct device_driver в следующем разделе.

Читайте также: Количество звеньев цепи для шины 50 см

Поле собственных данных, которые могут быть использованы драйвером устройства.

void (*release)(struct device *dev);

Метод вызывается, когда удаляется последняя ссылка на устройство; он вызывается из метода release встроенного kobject-а. Все структуры устройства, зарегистрированные в ядре, должны иметь метод release , или ядро распечатывает страшные жалобы.

Перед тем, как структура устройства может быть зарегистрирована, должны быть установлены, по крайней мере, поля parent , bus_id , bus и release .

Регистрация устройства

Существует обычный набор функций регистрации и её отмены:

int device_register(struct device *dev);

void device_unregister(struct device *dev);

Мы видели, как код lddbus регистрирует свой тип шины. Тем не менее, настоящая шина является устройством и должна быть зарегистрирована отдельно. Для простоты, модуль lddbus поддерживает только одну виртуальную шину, так что драйвер создаёт свои устройства во время компиляции:

static void ldd_bus_release(struct device *dev)

printk(KERN_DEBUG «lddbus release\n»);

Это шина верхнего уровня, поэтому поля parent и bus остались NULL. У нас есть простой метод release , не делающий ничего, и, как первая (и единственная) шина, она имеет имя ldd0 . Это устройство шины регистрируется так:

printk(KERN_NOTICE «Unable to register ldd0\n»);

Как только этот вызов будет завершён, в sysfs в каталоге /sys/devices можно увидеть новую шину. Любые устройства, добавленные к этой шине, показываются затем в /sys/devices/ldd0/ .

Атрибуты устройства

Записи устройств в sysfs могут иметь атрибуты. Соответствующей структурой является:

ssize_t (*show)(struct device *dev, char *buf);

ssize_t (*store)(struct device *dev, const char *buf, size_t count);

Эти структуры атрибутов могут быть созданы во время компиляции с помощью этого макроса:

DEVICE_ATTR(name, mode, show, store);

Результирующая структура называется, предваряя dev_attr_ заданное name . Фактическое управление файлами атрибутов осуществляется обычной парой функций:

int device_create_file(struct device *device, struct device_attribute *entry);

void device_remove_file(struct device *dev, struct device_attribute *attr);

Поле dev_attrs в struct bus_type указывает на список атрибутов по умолчанию, создаваемых для каждого добавляемого к шине устройства.

Внедрение структуры устройства

Структура device содержит информацию, которая необходима ядру модели устройства для моделирования системы. Однако, большинство подсистем отслеживают дополнительную информацию о тех устройств, которые они содержат. Как результат, редкие устройства представлены голыми структурами device ; вместо этого, эта структура, как и структуры kobject, как правило, встроены в представление устройства более высокого уровня. Если вы посмотрите на определения struct pci_dev или struct usb_device , вы найдете похороненную внутри struct device . Как правило, низкоуровневые драйверы даже не знают об этой struct device , но здесь могут быть исключения.

Драйвер lddbus создаёт свой собственный тип устройства ( struct ldd_device ) и ожидает, что отдельные драйверы устройств зарегистрировали свои устройства, используя этот тип. Он является простой структурой:

#define to_ldd_device(_dev) container_of(_dev, struct ldd_device, dev);

Читайте также: Peugeot 408 какие шины

static ssize_t sculld_show_dev(struct device *ddev, char *buf) struct sculld_dev *dev = ddev->driver_data; return print_dev_t(buf, dev->cdev.dev); static DEVICE_ATTR(dev, S_IRUGO, sculld_show_dev, NULL); Затем, во время инициализации, устройство регистрируется и создается атрибут dev посредством следующей функции: static void sculld_register_dev(struct sculld_dev *dev, int index) sprintf(dev->devname, «sculld%d», index); Обратите внимание, что мы используем поле driver_data для сохранения указателя на нашу собственную внутреннюю структуру устройства.

Видео:Как устранить проблему с sm контроллер шиныСкачать

Как устранить проблему с sm контроллер шины

Драйверы устройств

Модель устройства отслеживает все драйверы, известные в системе. Основной причиной для этого отслеживания является необходимость разрешить драйверному ядру сопоставлять драйверы с новыми устройствами. Однако, хотя драйверы представляют собой известные объекты внутри системы, стал возможным ряд других вещей. Драйверы устройств могут, например, экспортировать переменные информации и конфигурации, которые не зависят от какого-либо особого устройства. Драйверы определяются следующей структурой: int (*probe)(struct device *dev); int (*remove)(struct device *dev); void (*shutdown) (struct device *dev); Снова, некоторые поля этой структуры были опущены (смотрите
для полной информации). Здесь, name является именем драйвера (оно появляется в sysfs), bus является типом шины, с которой работает этот драйвер, kobj является неизбежным kobject, devices является списком всех устройств в настоящее время связанных с этим драйвером, probe является функцией, вызываемой для запроса наличия определённого устройства (и может ли этот драйвер работать с ним), remove вызывается, когда устройство удаляется из системы, и shutdown вызывается во время выключения для перевода устройства в пассивное состояние. Форма функций для работы со структурами device_driver должны теперь выглядеть уже знакомо (так что мы рассматриваем их очень быстро). Функциями регистрации являются: int driver_register(struct device_driver *drv); void driver_unregister(struct device_driver *drv); Существует обычная структура атрибута: ssize_t (*show)(struct device_driver *drv, char *buf); ssize_t (*store)(struct device_driver *drv, const char *buf, size_t count); DRIVER_ATTR(name, mode, show, store); И атрибутные файлы создаются обычным образом: int driver_create_file(struct device_driver *drv, struct driver_attribute *attr); void driver_remove_file(struct device_driver *drv, struct driver_attribute *attr); Структура bus_type содержит поле ( drv_attrs ), которое указывает на набор атрибутов по умолчанию, создаваемых для всех драйверов, связанных с этой шиной.

Внедрение структуры драйвера

Как и в случае с большинством структур драйверного ядра, структура device_driver обычно внедрена в высокоуровневую, зависимую от шины структуру. Подсистема lddbus никогда не пойдёт против такой тенденции, поэтому она определяет свою собственную структуру ldd_driver : struct device_driver driver; struct driver_attribute version_attr; #define to_ldd_driver(drv) container_of(drv, struct ldd_driver, driver); Здесь мы требуем, чтобы каждый драйвер предоставлял свою текущую версию программного обеспечения, а lddbus экспортирует эту строку версии для каждого драйвера о котором она знает. Шинно-зависимой функцией регистрации драйвера является: int register_ldd_driver(struct ldd_driver *driver) Первая половина функции просто регистрирует в ядре низкоуровневую структуру device_driver ; остальная устанавливает атрибут version . Так как этот атрибут создаётся во время выполнения, мы не можем использовать макрос DRIVER_ATTR ; вместо этого структура driver_attribute должна быть заполнена вручную. Обратите внимание, что мы установили владельцем атрибута модуль драйвера, а не модуль lddbus ; причину этого можно увидеть в реализации функции show для этого атрибута: static ssize_t show_version(struct device_driver *driver, char *buf) struct ldd_driver *ldriver = to_ldd_driver(driver); sprintf(buf, «%s\n», ldriver->version); Можно подумать, что владельцем атрибута должен быть модуль lddbus , поскольку функция, которая реализует данный атрибут, определяется здесь. Однако, эта функция работает со структурой ldd_driver , созданной (и принадлежащей) самим драйвером. Если бы эта структура ушла в то время, как процесс в пользовательском пространстве попытался прочитать номер версии, всё могло бы поломаться. Назначение модуля драйвера в качестве владельца атрибута предохраняет модулю от выгрузки, пока пользовательское пространство удерживает файл атрибута открытым. Так как каждый модуль драйвера создаёт ссылку на модуль lddbus , мы можем быть уверены, что lddbus не будет выгружена в неподходящее время. Для полноты, sculld создаёт свою структуру ldd_driver следующим образом: static struct ldd_driver sculld_driver = Источник

  • Свежие записи
    • Нужно ли менять пружины при замене амортизаторов
    • Скрипят амортизаторы на машине что делать
    • Из чего состоит стойка амортизатора передняя
    • Чем стянуть пружину амортизатора без стяжек
    • Для чего нужны амортизаторы в автомобиле
    • Правообладателям
    • Политика конфиденциальности


    🎦 Видео

    Другие устройства в диспетчере устройств как убрать Windows 11.Неизвестное устройство.PCI-контроллерСкачать

    Другие устройства в диспетчере устройств как убрать Windows 11.Неизвестное устройство.PCI-контроллер

    🖥️ Периферийное устройство Bluetooth драйвер WindowsСкачать

    🖥️ Периферийное устройство Bluetooth драйвер Windows

    Система Windows не смогла найти драйверы. Что делать?Скачать

    Система Windows не смогла найти драйверы. Что делать?

    ❓ Неизвестное устройство в Windows. Как решить проблему?Скачать

    ❓ Неизвестное устройство в Windows. Как решить проблему?

    Для устройства не установлены драйверы КОД 28Скачать

    Для устройства не установлены драйверы КОД 28

    Sm контроллер шины что это, 1Скачать

    Sm контроллер шины что это, 1

    Sm контроллер шины windows 7/32 bit chipset SM Bus controller and others driversСкачать

    Sm контроллер шины windows 7/32 bit chipset SM Bus controller and others drivers

    Восклицательный знак в диспетчере устройств Windows. Исправляем и правильно устанавливаем драйверСкачать

    Восклицательный знак в диспетчере устройств Windows. Исправляем и правильно устанавливаем драйвер

    Как сделать Kernel Driver - Загрузка & ВыгрузкаСкачать

    Как сделать Kernel Driver - Загрузка & Выгрузка

    Что такое Драйвера - Объяснение | Как это работаетСкачать

    Что такое Драйвера - Объяснение | Как это работает

    Периферийное устройство bluetooth и желтый треугольник - что делать?Скачать

    Периферийное устройство bluetooth и желтый треугольник - что делать?

    Для устройства не установлены драйверы Код 28Скачать

    Для устройства не установлены драйверы Код 28

    Не работают USB порты - 3 способа Решения! Windows 7/8/10/11Скачать

    Не работают USB порты - 3 способа Решения! Windows 7/8/10/11

    Как найти и установить нужный драйвер на компьютерСкачать

    Как найти и установить нужный драйвер на компьютер

    Установка ВСЕХ Драйверов на Windows 7/8/10 в Один Клик | UnderMindСкачать

    Установка ВСЕХ Драйверов на Windows 7/8/10 в Один Клик | UnderMind

    Для Устройства не Установлены Драйверы (код 28) Windows 7 8 10 11 ✅ РЕШЕНИЕСкачать

    Для Устройства не Установлены Драйверы (код 28) Windows 7 8 10 11 ✅ РЕШЕНИЕ

    Установка и обновление драйверов в Windows 10/11 БесплатноСкачать

    Установка и обновление драйверов в Windows 10/11 Бесплатно

    Что такое драйвера на компьютереСкачать

    Что такое драйвера на компьютере
Поделиться или сохранить к себе:
Технарь знаток