Събирайки всичко

За да разберем по-добре какво прави моделът на драйвера, нека преминем през жизнения цикъл на устройство в ядрото. Описваме как взаимодейства подсистемата PCI с модела на драйвера, основните концепции за добавяне и премахване на драйвер и как устройствата се добавят и премахват от системата. Тази информация и по-специално при описването на кода на ядрото на PCI се отнася за всички други подсистеми, които използват ядрото на драйвера, за да контролират своите драйвери и устройства.

Както е показано на фигура 14-3, взаимодействието между PCI ядрото, ядрото на драйвера и отделните PCI драйвери е доста сложно.

ядрото драйвера

Фигура 14-3. Процес на създаване на устройство

Добавяне на устройство

Подсистемата PCI декларира един структурен тип_буса, наречен pci_bus_type, който се инициализира със следните стойности:

struct bus_type pci_bus_type =

Тази променлива pci_bus_type се регистрира в ядрото на драйвера, когато подсистемата PCI се зарежда в ядрото чрез извикване на bus_register. Когато това се случи, ядрото на драйвера създава директория/sys/bus/pci в sysfs, която се състои от две директории: устройства и драйвери .

Всички PCI драйвери трябва да дефинират променлива struct pci_driver, която определя различните функции, които този PCI драйвер може да изпълнява (за повече информация относно PCI подсистемата и как да напишете PCI драйвер, вижте Глава 12). Тази структура съдържа структура device_driver, която след това се инициализира от ядрото на PCI при регистрация на PCI драйвер:

/ * инициализация на обичайните полета на драйвера * /

Този код настройва шината за драйвера, като посочва указател към pci_bus_type и указатели за сондиране и премахване на функции за насочване към функции в ядрото на PCI. За да работят правилно атрибутите на PCI драйвера, ktype за драйвера kobject е зададен на променливата pci_driver_kobj_type. След това ядрото PCI регистрира PCI драйвера с ядрото на драйвера:

/ * регистрирайте се в ядрото * /

Драйверът вече е готов за комуникация с всички PCI устройства, които поддържа.

неподписан int devfn;

неподписан къс продавач;

неподписано кратко устройство;

неподписан кратък podsystem_vendor;

неподписано кратко podsystem_device;

неподписан клас int;

struct pci_driver * драйвер;

struct device dev;

Зависимите от шината полета на това PCI устройство се инициализират от ядрото PCI (devfn, доставчик, устройство и други полета) и родителската променлива на променливата struct device се задава на устройството на PCI шината, в която това PCI устройство живее. Променливата на шината е настроена да сочи към структурата pci_bus_type. След това се задават променливите name и bus_id, в зависимост от името и ID, прочетени от PCI устройството.

След инициализация на структурата на PCI устройство, устройството се регистрира в ядрото на драйвера чрез извикване:

Във функцията device_register драйверът на ядрото инициализира редица полета на устройството, регистрира устройството kobject с ядрото kobject (което задейства събитие за hotplug, но това ще обсъдим по-късно в тази глава) и след това добавя устройството към списъка с устройства съдържащи се в родителя на устройството. Това се прави, за да могат всички устройства да бъдат заобиколени в правилния ред, като винаги се знае къде в йерархията на устройствата живее всяко от тях.

След това устройството се добавя към списъка на всички устройства, зависим от шината, в този пример списъкът pci_bus_type. След това се обхожда списък на всички драйвери, регистрирани в шината и се извиква съответствието на функцията на шината за всеки драйвер, като се посочва това устройство. За pci_bus_type, преди устройството да бъде предадено на ядрото на драйвера, функцията за съвпадение беше зададена от ядрото на PCI да сочи към функцията pci_bus_match .

Функцията pci_bus_match преобразува устройството struct, предадено му от ядрото на драйвера, обратно в struct pci_dev. Той също така прехвърля struct device_driver обратно в struct pci_driver и след това разглежда специфичното за PCI устройство устройство и информация за драйвера, за да види дали драйверът твърди, че може да поддържа този вид устройство. Ако съвпадението не е успешно, функцията връща 0 към ядрото на драйвера и ядрото на драйвера преминава към следващия драйвер в списъка си.

Ако съвпадение бъде намерено успешно, функцията се връща обратно към ядрото на драйвера 1. Това кара ядрото на драйвера да зададе показалеца на драйвера към устройството struct, за да сочи към него и след това извиква функцията на сондата, посочена в struct device_driver .

По-рано, преди PCI драйверът да бъде регистриран с ядрото на драйвера, пробната променлива беше настроена да сочи към функцията pci_device_probe. Тази функция връща (отново) структурно устройство обратно към struct pci_dev и структурен драйвер, който се превръща в устройство обратно в struct pci_driver. Той проверява отново, че този драйвер твърди, че може да поддържа това устройство (което изглежда непосилна допълнителна проверка по някаква неизвестна причина), увеличава броя на референтите на устройството и след това извиква функцията на сондата на водача с указател към структурата pci_dev към която трябва да завърже.