isphinx.addnodesdocument)}( rawsourcechildren]( translations LanguagesNode)}(hhh](h pending_xref)}(hhh]docutils.nodesTextChinese (Simplified)}parenthsba attributes}(ids]classes]names]dupnames]backrefs] refdomainstdreftypedoc reftarget3/translations/zh_CN/driver-api/driver-model/portingmodnameN classnameN refexplicitutagnamehhh ubh)}(hhh]hChinese (Traditional)}hh2sbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget3/translations/zh_TW/driver-api/driver-model/portingmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hItalian}hhFsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget3/translations/it_IT/driver-api/driver-model/portingmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hJapanese}hhZsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget3/translations/ja_JP/driver-api/driver-model/portingmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hKorean}hhnsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget3/translations/ko_KR/driver-api/driver-model/portingmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hSpanish}hhsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget3/translations/sp_SP/driver-api/driver-model/portingmodnameN classnameN refexplicituh1hhh ubeh}(h]h ]h"]h$]h&]current_languageEnglishuh1h hh _documenthsourceNlineNubhsection)}(hhh](htitle)}(h'Porting Drivers to the New Driver Modelh]h'Porting Drivers to the New Driver Model}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhhhM/var/lib/git/docbuild/linux/Documentation/driver-api/driver-model/porting.rsthKubh paragraph)}(hPatrick Mochelh]hPatrick Mochel}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(h7 January 2003h]h7 January 2003}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(hOverviewh]hOverview}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK hhhhubh)}(hsPlease refer to `Documentation/driver-api/driver-model/*.rst` for definitions of various driver types and concepts.h](hPlease refer to }(hhhhhNhNubhtitle_reference)}(h-`Documentation/driver-api/driver-model/*.rst`h]h+Documentation/driver-api/driver-model/*.rst}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhubh6 for definitions of various driver types and concepts.}(hhhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhK hhhhubh)}(hMost of the work of porting devices drivers to the new model happens at the bus driver layer. This was intentional, to minimize the negative effect on kernel drivers, and to allow a gradual transition of bus drivers.h]hMost of the work of porting devices drivers to the new model happens at the bus driver layer. This was intentional, to minimize the negative effect on kernel drivers, and to allow a gradual transition of bus drivers.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(hIn a nutshell, the driver model consists of a set of objects that can be embedded in larger, bus-specific objects. Fields in these generic objects can replace fields in the bus-specific objects.h]hIn a nutshell, the driver model consists of a set of objects that can be embedded in larger, bus-specific objects. Fields in these generic objects can replace fields in the bus-specific objects.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(hThe generic objects must be registered with the driver model core. By doing so, they will exported via the sysfs filesystem. sysfs can be mounted by doing::h]hThe generic objects must be registered with the driver model core. By doing so, they will exported via the sysfs filesystem. sysfs can be mounted by doing:}(hj!hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh literal_block)}(h# mount -t sysfs sysfs /sysh]h# mount -t sysfs sysfs /sys}hj1sbah}(h]h ]h"]h$]h&] xml:spacepreserveuh1j/hhhKhhhhubh)}(h The Processh]h The Process}(hjAhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK hhhhubh)}(hHStep 0: Read include/linux/device.h for object and function definitions.h]hHStep 0: Read include/linux/device.h for object and function definitions.}(hjOhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK"hhhhubh)}(h#Step 1: Registering the bus driver.h]h#Step 1: Registering the bus driver.}(hj]hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK$hhhhubh bullet_list)}(hhh](h list_item)}(hyDefine a struct bus_type for the bus driver:: struct bus_type pci_bus_type = { .name = "pci", }; h](h)}(h-Define a struct bus_type for the bus driver::h]h,Define a struct bus_type for the bus driver:}(hjvhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK'hjrubj0)}(hBstruct bus_type pci_bus_type = { .name = "pci", };h]hBstruct bus_type pci_bus_type = { .name = "pci", };}hjsbah}(h]h ]h"]h$]h&]j?j@uh1j/hhhK)hjrubeh}(h]h ]h"]h$]h&]uh1jphjmhhhhhNubjq)}(hXRegister the bus type. This should be done in the initialization function for the bus type, which is usually the module_init(), or equivalent, function:: static int __init pci_driver_init(void) { return bus_register(&pci_bus_type); } subsys_initcall(pci_driver_init); The bus type may be unregistered (if the bus driver may be compiled as a module) by doing:: bus_unregister(&pci_bus_type); h](h)}(hRegister the bus type.h]hRegister the bus type.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK.hjubh)}(hThis should be done in the initialization function for the bus type, which is usually the module_init(), or equivalent, function::h]hThis should be done in the initialization function for the bus type, which is usually the module_init(), or equivalent, function:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK0hjubj0)}(hzstatic int __init pci_driver_init(void) { return bus_register(&pci_bus_type); } subsys_initcall(pci_driver_init);h]hzstatic int __init pci_driver_init(void) { return bus_register(&pci_bus_type); } subsys_initcall(pci_driver_init);}hjsbah}(h]h ]h"]h$]h&]j?j@uh1j/hhhK3hjubh)}(h[The bus type may be unregistered (if the bus driver may be compiled as a module) by doing::h]hZThe bus type may be unregistered (if the bus driver may be compiled as a module) by doing:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK;hjubj0)}(hbus_unregister(&pci_bus_type);h]hbus_unregister(&pci_bus_type);}hjsbah}(h]h ]h"]h$]h&]j?j@uh1j/hhhK>hjubeh}(h]h ]h"]h$]h&]uh1jphjmhhhhhNubjq)}(hExport the bus type for others to use. Other code may wish to reference the bus type, so declare it in a shared header file and export the symbol. h](h)}(h&Export the bus type for others to use.h]h&Export the bus type for others to use.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKAhjubh)}(hkOther code may wish to reference the bus type, so declare it in a shared header file and export the symbol.h]hkOther code may wish to reference the bus type, so declare it in a shared header file and export the symbol.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKChjubeh}(h]h ]h"]h$]h&]uh1jphjmhhhhhNubeh}(h]h ]h"]h$]h&]bullet-uh1jkhhhK'hhhhubh)}(hFrom include/linux/pci.h::h]hFrom include/linux/pci.h:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKFhhhhubj0)}(h$extern struct bus_type pci_bus_type;h]h$extern struct bus_type pci_bus_type;}hj$sbah}(h]h ]h"]h$]h&]j?j@uh1j/hhhKHhhhhubh)}(h%From file the above code appears in::h]h$From file the above code appears in:}(hj2hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKKhhhhubj0)}(hEXPORT_SYMBOL(pci_bus_type);h]hEXPORT_SYMBOL(pci_bus_type);}hj@sbah}(h]h ]h"]h$]h&]j?j@uh1j/hhhKMhhhhubjl)}(hhh]jq)}(hThis will cause the bus to show up in /sys/bus/pci/ with two subdirectories: 'devices' and 'drivers':: # tree -d /sys/bus/pci/ /sys/bus/pci/ |-- devices `-- drivers h](h)}(hfThis will cause the bus to show up in /sys/bus/pci/ with two subdirectories: 'devices' and 'drivers'::h]hmThis will cause the bus to show up in /sys/bus/pci/ with two subdirectories: ‘devices’ and ‘drivers’:}(hjUhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKQhjQubj0)}(h=# tree -d /sys/bus/pci/ /sys/bus/pci/ |-- devices `-- driversh]h=# tree -d /sys/bus/pci/ /sys/bus/pci/ |-- devices `-- drivers}hjcsbah}(h]h ]h"]h$]h&]j?j@uh1j/hhhKThjQubeh}(h]h ]h"]h$]h&]uh1jphjNhhhhhNubah}(h]h ]h"]h$]h&]jjuh1jkhhhKQhhhhubh)}(hStep 2: Registering Devices.h]hStep 2: Registering Devices.}(hj}hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK[hhhhubh)}(hstruct device represents a single device. It mainly contains metadata describing the relationship the device has to other entities.h]hstruct device represents a single device. It mainly contains metadata describing the relationship the device has to other entities.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK]hhhhubjl)}(hhh](jq)}(hXEmbed a struct device in the bus-specific device type:: struct pci_dev { ... struct device dev; /* Generic device interface */ ... }; It is recommended that the generic device not be the first item in the struct to discourage programmers from doing mindless casts between the object types. Instead macros, or inline functions, should be created to convert from the generic object type:: #define to_pci_dev(n) container_of(n, struct pci_dev, dev) or static inline struct pci_dev * to_pci_dev(struct kobject * kobj) { return container_of(n, struct pci_dev, dev); } This allows the compiler to verify type-safety of the operations that are performed (which is Good). h](h)}(h7Embed a struct device in the bus-specific device type::h]h6Embed a struct device in the bus-specific device type:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKahjubj0)}(hostruct pci_dev { ... struct device dev; /* Generic device interface */ ... };h]hostruct pci_dev { ... struct device dev; /* Generic device interface */ ... };}hjsbah}(h]h ]h"]h$]h&]j?j@uh1j/hhhKdhjubh)}(hIt is recommended that the generic device not be the first item in the struct to discourage programmers from doing mindless casts between the object types. Instead macros, or inline functions, should be created to convert from the generic object type::h]hIt is recommended that the generic device not be the first item in the struct to discourage programmers from doing mindless casts between the object types. Instead macros, or inline functions, should be created to convert from the generic object type:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKjhjubj0)}(h#define to_pci_dev(n) container_of(n, struct pci_dev, dev) or static inline struct pci_dev * to_pci_dev(struct kobject * kobj) { return container_of(n, struct pci_dev, dev); }h]h#define to_pci_dev(n) container_of(n, struct pci_dev, dev) or static inline struct pci_dev * to_pci_dev(struct kobject * kobj) { return container_of(n, struct pci_dev, dev); }}hjsbah}(h]h ]h"]h$]h&]j?j@uh1j/hhhKphjubh)}(hdThis allows the compiler to verify type-safety of the operations that are performed (which is Good).h]hdThis allows the compiler to verify type-safety of the operations that are performed (which is Good).}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKyhjubeh}(h]h ]h"]h$]h&]uh1jphjhhhhhNubjq)}(hXInitialize the device on registration. When devices are discovered or registered with the bus type, the bus driver should initialize the generic device. The most important things to initialize are the bus_id, parent, and bus fields. The bus_id is an ASCII string that contains the device's address on the bus. The format of this string is bus-specific. This is necessary for representing devices in sysfs. parent is the physical parent of the device. It is important that the bus driver sets this field correctly. The driver model maintains an ordered list of devices that it uses for power management. This list must be in order to guarantee that devices are shutdown before their physical parents, and vice versa. The order of this list is determined by the parent of registered devices. Also, the location of the device's sysfs directory depends on a device's parent. sysfs exports a directory structure that mirrors the device hierarchy. Accurately setting the parent guarantees that sysfs will accurately represent the hierarchy. The device's bus field is a pointer to the bus type the device belongs to. This should be set to the bus_type that was declared and initialized before. Optionally, the bus driver may set the device's name and release fields. The name field is an ASCII string describing the device, like "ATI Technologies Inc Radeon QD" The release field is a callback that the driver model core calls when the device has been removed, and all references to it have been released. More on this in a moment. h](h)}(h&Initialize the device on registration.h]h&Initialize the device on registration.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK}hjubh)}(hWhen devices are discovered or registered with the bus type, the bus driver should initialize the generic device. The most important things to initialize are the bus_id, parent, and bus fields.h]hWhen devices are discovered or registered with the bus type, the bus driver should initialize the generic device. The most important things to initialize are the bus_id, parent, and bus fields.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubh)}(hThe bus_id is an ASCII string that contains the device's address on the bus. The format of this string is bus-specific. This is necessary for representing devices in sysfs.h]hThe bus_id is an ASCII string that contains the device’s address on the bus. The format of this string is bus-specific. This is necessary for representing devices in sysfs.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubh)}(hkparent is the physical parent of the device. It is important that the bus driver sets this field correctly.h]hkparent is the physical parent of the device. It is important that the bus driver sets this field correctly.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubh)}(hXThe driver model maintains an ordered list of devices that it uses for power management. This list must be in order to guarantee that devices are shutdown before their physical parents, and vice versa. The order of this list is determined by the parent of registered devices.h]hXThe driver model maintains an ordered list of devices that it uses for power management. This list must be in order to guarantee that devices are shutdown before their physical parents, and vice versa. The order of this list is determined by the parent of registered devices.}(hj(hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubh)}(hAlso, the location of the device's sysfs directory depends on a device's parent. sysfs exports a directory structure that mirrors the device hierarchy. Accurately setting the parent guarantees that sysfs will accurately represent the hierarchy.h]hAlso, the location of the device’s sysfs directory depends on a device’s parent. sysfs exports a directory structure that mirrors the device hierarchy. Accurately setting the parent guarantees that sysfs will accurately represent the hierarchy.}(hj6hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubh)}(hThe device's bus field is a pointer to the bus type the device belongs to. This should be set to the bus_type that was declared and initialized before.h]hThe device’s bus field is a pointer to the bus type the device belongs to. This should be set to the bus_type that was declared and initialized before.}(hjDhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubh)}(hHOptionally, the bus driver may set the device's name and release fields.h]hJOptionally, the bus driver may set the device’s name and release fields.}(hjRhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubh)}(h=The name field is an ASCII string describing the device, likeh]h=The name field is an ASCII string describing the device, like}(hj`hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubh block_quote)}(h!"ATI Technologies Inc Radeon QD" h]h)}(h "ATI Technologies Inc Radeon QD"h]h$“ATI Technologies Inc Radeon QD”}(hjthhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjpubah}(h]h ]h"]h$]h&]uh1jnhhhKhjubh)}(hThe release field is a callback that the driver model core calls when the device has been removed, and all references to it have been released. More on this in a moment.h]hThe release field is a callback that the driver model core calls when the device has been removed, and all references to it have been released. More on this in a moment.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubeh}(h]h ]h"]h$]h&]uh1jphjhhhhhNubjq)}(hX<Register the device. Once the generic device has been initialized, it can be registered with the driver model core by doing:: device_register(&dev->dev); It can later be unregistered by doing:: device_unregister(&dev->dev); This should happen on buses that support hotpluggable devices. If a bus driver unregisters a device, it should not immediately free it. It should instead wait for the driver model core to call the device's release method, then free the bus-specific object. (There may be other code that is currently referencing the device structure, and it would be rude to free the device while that is happening). When the device is registered, a directory in sysfs is created. The PCI tree in sysfs looks like:: /sys/devices/pci0/ |-- 00:00.0 |-- 00:01.0 | `-- 01:00.0 |-- 00:02.0 | `-- 02:1f.0 | `-- 03:00.0 |-- 00:1e.0 | `-- 04:04.0 |-- 00:1f.0 |-- 00:1f.1 | |-- ide0 | | |-- 0.0 | | `-- 0.1 | `-- ide1 | `-- 1.0 |-- 00:1f.2 |-- 00:1f.3 `-- 00:1f.5 Also, symlinks are created in the bus's 'devices' directory that point to the device's directory in the physical hierarchy:: /sys/bus/pci/devices/ |-- 00:00.0 -> ../../../devices/pci0/00:00.0 |-- 00:01.0 -> ../../../devices/pci0/00:01.0 |-- 00:02.0 -> ../../../devices/pci0/00:02.0 |-- 00:1e.0 -> ../../../devices/pci0/00:1e.0 |-- 00:1f.0 -> ../../../devices/pci0/00:1f.0 |-- 00:1f.1 -> ../../../devices/pci0/00:1f.1 |-- 00:1f.2 -> ../../../devices/pci0/00:1f.2 |-- 00:1f.3 -> ../../../devices/pci0/00:1f.3 |-- 00:1f.5 -> ../../../devices/pci0/00:1f.5 |-- 01:00.0 -> ../../../devices/pci0/00:01.0/01:00.0 |-- 02:1f.0 -> ../../../devices/pci0/00:02.0/02:1f.0 |-- 03:00.0 -> ../../../devices/pci0/00:02.0/02:1f.0/03:00.0 `-- 04:04.0 -> ../../../devices/pci0/00:1e.0/04:04.0 h](h)}(hRegister the device.h]hRegister the device.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubh)}(hhOnce the generic device has been initialized, it can be registered with the driver model core by doing::h]hgOnce the generic device has been initialized, it can be registered with the driver model core by doing:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubj0)}(hdevice_register(&dev->dev);h]hdevice_register(&dev->dev);}hjsbah}(h]h ]h"]h$]h&]j?j@uh1j/hhhKhjubh)}(h'It can later be unregistered by doing::h]h&It can later be unregistered by doing:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubj0)}(hdevice_unregister(&dev->dev);h]hdevice_unregister(&dev->dev);}hjsbah}(h]h ]h"]h$]h&]j?j@uh1j/hhhKhjubh)}(hXThis should happen on buses that support hotpluggable devices. If a bus driver unregisters a device, it should not immediately free it. It should instead wait for the driver model core to call the device's release method, then free the bus-specific object. (There may be other code that is currently referencing the device structure, and it would be rude to free the device while that is happening).h]hXThis should happen on buses that support hotpluggable devices. If a bus driver unregisters a device, it should not immediately free it. It should instead wait for the driver model core to call the device’s release method, then free the bus-specific object. (There may be other code that is currently referencing the device structure, and it would be rude to free the device while that is happening).}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubh)}(hbWhen the device is registered, a directory in sysfs is created. The PCI tree in sysfs looks like::h]haWhen the device is registered, a directory in sysfs is created. The PCI tree in sysfs looks like:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubj0)}(hX /sys/devices/pci0/ |-- 00:00.0 |-- 00:01.0 | `-- 01:00.0 |-- 00:02.0 | `-- 02:1f.0 | `-- 03:00.0 |-- 00:1e.0 | `-- 04:04.0 |-- 00:1f.0 |-- 00:1f.1 | |-- ide0 | | |-- 0.0 | | `-- 0.1 | `-- ide1 | `-- 1.0 |-- 00:1f.2 |-- 00:1f.3 `-- 00:1f.5h]hX /sys/devices/pci0/ |-- 00:00.0 |-- 00:01.0 | `-- 01:00.0 |-- 00:02.0 | `-- 02:1f.0 | `-- 03:00.0 |-- 00:1e.0 | `-- 04:04.0 |-- 00:1f.0 |-- 00:1f.1 | |-- ide0 | | |-- 0.0 | | `-- 0.1 | `-- ide1 | `-- 1.0 |-- 00:1f.2 |-- 00:1f.3 `-- 00:1f.5}hjsbah}(h]h ]h"]h$]h&]j?j@uh1j/hhhKhjubh)}(h|Also, symlinks are created in the bus's 'devices' directory that point to the device's directory in the physical hierarchy::h]hAlso, symlinks are created in the bus’s ‘devices’ directory that point to the device’s directory in the physical hierarchy:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubj0)}(hX/sys/bus/pci/devices/ |-- 00:00.0 -> ../../../devices/pci0/00:00.0 |-- 00:01.0 -> ../../../devices/pci0/00:01.0 |-- 00:02.0 -> ../../../devices/pci0/00:02.0 |-- 00:1e.0 -> ../../../devices/pci0/00:1e.0 |-- 00:1f.0 -> ../../../devices/pci0/00:1f.0 |-- 00:1f.1 -> ../../../devices/pci0/00:1f.1 |-- 00:1f.2 -> ../../../devices/pci0/00:1f.2 |-- 00:1f.3 -> ../../../devices/pci0/00:1f.3 |-- 00:1f.5 -> ../../../devices/pci0/00:1f.5 |-- 01:00.0 -> ../../../devices/pci0/00:01.0/01:00.0 |-- 02:1f.0 -> ../../../devices/pci0/00:02.0/02:1f.0 |-- 03:00.0 -> ../../../devices/pci0/00:02.0/02:1f.0/03:00.0 `-- 04:04.0 -> ../../../devices/pci0/00:1e.0/04:04.0h]hX/sys/bus/pci/devices/ |-- 00:00.0 -> ../../../devices/pci0/00:00.0 |-- 00:01.0 -> ../../../devices/pci0/00:01.0 |-- 00:02.0 -> ../../../devices/pci0/00:02.0 |-- 00:1e.0 -> ../../../devices/pci0/00:1e.0 |-- 00:1f.0 -> ../../../devices/pci0/00:1f.0 |-- 00:1f.1 -> ../../../devices/pci0/00:1f.1 |-- 00:1f.2 -> ../../../devices/pci0/00:1f.2 |-- 00:1f.3 -> ../../../devices/pci0/00:1f.3 |-- 00:1f.5 -> ../../../devices/pci0/00:1f.5 |-- 01:00.0 -> ../../../devices/pci0/00:01.0/01:00.0 |-- 02:1f.0 -> ../../../devices/pci0/00:02.0/02:1f.0 |-- 03:00.0 -> ../../../devices/pci0/00:02.0/02:1f.0/03:00.0 `-- 04:04.0 -> ../../../devices/pci0/00:1e.0/04:04.0}hjsbah}(h]h ]h"]h$]h&]j?j@uh1j/hhhKhjubeh}(h]h ]h"]h$]h&]uh1jphjhhhhhNubeh}(h]h ]h"]h$]h&]jjuh1jkhhhKahhhhubh)}(hStep 3: Registering Drivers.h]hStep 3: Registering Drivers.}(hj8hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(hxstruct device_driver is a simple driver structure that contains a set of operations that the driver model core may call.h]hxstruct device_driver is a simple driver structure that contains a set of operations that the driver model core may call.}(hjFhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhhhubjl)}(hhh](jq)}(hEmbed a struct device_driver in the bus-specific driver. Just like with devices, do something like:: struct pci_driver { ... struct device_driver driver; }; h](h)}(h8Embed a struct device_driver in the bus-specific driver.h]h8Embed a struct device_driver in the bus-specific driver.}(hj[hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjWubh)}(h+Just like with devices, do something like::h]h*Just like with devices, do something like:}(hjihhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjWubj0)}(hHstruct pci_driver { ... struct device_driver driver; };h]hHstruct pci_driver { ... struct device_driver driver; };}hjwsbah}(h]h ]h"]h$]h&]j?j@uh1j/hhhKhjWubeh}(h]h ]h"]h$]h&]uh1jphjThhhhhNubjq)}(hInitialize the generic driver structure. When the driver registers with the bus (e.g. doing pci_register_driver()), initialize the necessary fields of the driver: the name and bus fields. h](h)}(h(Initialize the generic driver structure.h]h(Initialize the generic driver structure.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubh)}(hWhen the driver registers with the bus (e.g. doing pci_register_driver()), initialize the necessary fields of the driver: the name and bus fields.h]hWhen the driver registers with the bus (e.g. doing pci_register_driver()), initialize the necessary fields of the driver: the name and bus fields.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubeh}(h]h ]h"]h$]h&]uh1jphjThhhhhNubjq)}(hXRegister the driver. After the generic driver has been initialized, call:: driver_register(&drv->driver); to register the driver with the core. When the driver is unregistered from the bus, unregister it from the core by doing:: driver_unregister(&drv->driver); Note that this will block until all references to the driver have gone away. Normally, there will not be any. h](h)}(hRegister the driver.h]hRegister the driver.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubh)}(h5After the generic driver has been initialized, call::h]h4After the generic driver has been initialized, call:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubj0)}(hdriver_register(&drv->driver);h]hdriver_register(&drv->driver);}hjsbah}(h]h ]h"]h$]h&]j?j@uh1j/hhhKhjubh)}(h%to register the driver with the core.h]h%to register the driver with the core.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjubh)}(hTWhen the driver is unregistered from the bus, unregister it from the core by doing::h]hSWhen the driver is unregistered from the bus, unregister it from the core by doing:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjubj0)}(h driver_unregister(&drv->driver);h]h driver_unregister(&drv->driver);}hjsbah}(h]h ]h"]h$]h&]j?j@uh1j/hhhMhjubh)}(hmNote that this will block until all references to the driver have gone away. Normally, there will not be any.h]hmNote that this will block until all references to the driver have gone away. Normally, there will not be any.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjubeh}(h]h ]h"]h$]h&]uh1jphjThhhhhNubjq)}(hSysfs representation. Drivers are exported via sysfs in their bus's 'driver's directory. For example:: /sys/bus/pci/drivers/ |-- 3c59x |-- Ensoniq AudioPCI |-- agpgart-amdk7 |-- e100 `-- serial h](h)}(hSysfs representation.h]hSysfs representation.}(hj!hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM hjubh)}(hPDrivers are exported via sysfs in their bus's 'driver's directory. For example::h]hUDrivers are exported via sysfs in their bus’s ‘driver’s directory. For example:}(hj/hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjubj0)}(hZ/sys/bus/pci/drivers/ |-- 3c59x |-- Ensoniq AudioPCI |-- agpgart-amdk7 |-- e100 `-- serialh]hZ/sys/bus/pci/drivers/ |-- 3c59x |-- Ensoniq AudioPCI |-- agpgart-amdk7 |-- e100 `-- serial}hj=sbah}(h]h ]h"]h$]h&]j?j@uh1j/hhhMhjubeh}(h]h ]h"]h$]h&]uh1jphjThhhhhNubeh}(h]h ]h"]h$]h&]jjuh1jkhhhKhhhhubh)}(h+Step 4: Define Generic Methods for Drivers.h]h+Step 4: Define Generic Methods for Drivers.}(hjWhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhhhhubh)}(hstruct device_driver defines a set of operations that the driver model core calls. Most of these operations are probably similar to operations the bus already defines for drivers, but taking different parameters.h]hstruct device_driver defines a set of operations that the driver model core calls. Most of these operations are probably similar to operations the bus already defines for drivers, but taking different parameters.}(hjehhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhhhhubh)}(hXIt would be difficult and tedious to force every driver on a bus to simultaneously convert their drivers to generic format. Instead, the bus driver should define single instances of the generic methods that forward call to the bus-specific drivers. For instance::h]hXIt would be difficult and tedious to force every driver on a bus to simultaneously convert their drivers to generic format. Instead, the bus driver should define single instances of the generic methods that forward call to the bus-specific drivers. For instance:}(hjshhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM hhhhubj0)}(hXCstatic int pci_device_remove(struct device * dev) { struct pci_dev * pci_dev = to_pci_dev(dev); struct pci_driver * drv = pci_dev->driver; if (drv) { if (drv->remove) drv->remove(pci_dev); pci_dev->driver = NULL; } return 0; }h]hXCstatic int pci_device_remove(struct device * dev) { struct pci_dev * pci_dev = to_pci_dev(dev); struct pci_driver * drv = pci_dev->driver; if (drv) { if (drv->remove) drv->remove(pci_dev); pci_dev->driver = NULL; } return 0; }}hjsbah}(h]h ]h"]h$]h&]j?j@uh1j/hhhM&hhhhubh)}(hUThe generic driver should be initialized with these methods before it is registered::h]hTThe generic driver should be initialized with these methods before it is registered:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM4hhhhubj0)}(hX=/* initialize common driver fields */ drv->driver.name = drv->name; drv->driver.bus = &pci_bus_type; drv->driver.probe = pci_device_probe; drv->driver.resume = pci_device_resume; drv->driver.suspend = pci_device_suspend; drv->driver.remove = pci_device_remove; /* register with core */ driver_register(&drv->driver);h]hX=/* initialize common driver fields */ drv->driver.name = drv->name; drv->driver.bus = &pci_bus_type; drv->driver.probe = pci_device_probe; drv->driver.resume = pci_device_resume; drv->driver.suspend = pci_device_suspend; drv->driver.remove = pci_device_remove; /* register with core */ driver_register(&drv->driver);}hjsbah}(h]h ]h"]h$]h&]j?j@uh1j/hhhM7hhhhubh)}(hIdeally, the bus should only initialize the fields if they are not already set. This allows the drivers to implement their own generic methods.h]hIdeally, the bus should only initialize the fields if they are not already set. This allows the drivers to implement their own generic methods.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMChhhhubh)}(h'Step 5: Support generic driver binding.h]h'Step 5: Support generic driver binding.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMHhhhhubh)}(hThe model assumes that a device or driver can be dynamically registered with the bus at any time. When registration happens, devices must be bound to a driver, or drivers must be bound to all devices that it supports.h]hThe model assumes that a device or driver can be dynamically registered with the bus at any time. When registration happens, devices must be bound to a driver, or drivers must be bound to all devices that it supports.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMJhhhhubh)}(hXA driver typically contains a list of device IDs that it supports. The bus driver compares these IDs to the IDs of devices registered with it. The format of the device IDs, and the semantics for comparing them are bus-specific, so the generic model does attempt to generalize them.h]hXA driver typically contains a list of device IDs that it supports. The bus driver compares these IDs to the IDs of devices registered with it. The format of the device IDs, and the semantics for comparing them are bus-specific, so the generic model does attempt to generalize them.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMOhhhhubh)}(hPInstead, a bus may supply a method in struct bus_type that does the comparison::h]hOInstead, a bus may supply a method in struct bus_type that does the comparison:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMThhhhubj0)}(h>int (*match)(struct device * dev, struct device_driver * drv);h]h>int (*match)(struct device * dev, struct device_driver * drv);}hjsbah}(h]h ]h"]h$]h&]j?j@uh1j/hhhMWhhhhubh)}(hmatch should return positive value if the driver supports the device, and zero otherwise. It may also return error code (for example -EPROBE_DEFER) if determining that given driver supports the device is not possible.h]hmatch should return positive value if the driver supports the device, and zero otherwise. It may also return error code (for example -EPROBE_DEFER) if determining that given driver supports the device is not possible.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMYhhhhubh)}(hWhen a device is registered, the bus's list of drivers is iterated over. bus->match() is called for each one until a match is found.h]hWhen a device is registered, the bus’s list of drivers is iterated over. bus->match() is called for each one until a match is found.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM^hhhhubh)}(hWhen a driver is registered, the bus's list of devices is iterated over. bus->match() is called for each device that is not already claimed by a driver.h]hWhen a driver is registered, the bus’s list of devices is iterated over. bus->match() is called for each device that is not already claimed by a driver.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMahhhhubh)}(hWhen a device is successfully bound to a driver, device->driver is set, the device is added to a per-driver list of devices, and a symlink is created in the driver's sysfs directory that points to the device's physical directory::h]hWhen a device is successfully bound to a driver, device->driver is set, the device is added to a per-driver list of devices, and a symlink is created in the driver’s sysfs directory that points to the device’s physical directory:}(hj)hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMehhhhubj0)}(h/sys/bus/pci/drivers/ |-- 3c59x | `-- 00:0b.0 -> ../../../../devices/pci0/00:0b.0 |-- Ensoniq AudioPCI |-- agpgart-amdk7 | `-- 00:00.0 -> ../../../../devices/pci0/00:00.0 |-- e100 | `-- 00:0c.0 -> ../../../../devices/pci0/00:0c.0 `-- serialh]h/sys/bus/pci/drivers/ |-- 3c59x | `-- 00:0b.0 -> ../../../../devices/pci0/00:0b.0 |-- Ensoniq AudioPCI |-- agpgart-amdk7 | `-- 00:00.0 -> ../../../../devices/pci0/00:00.0 |-- e100 | `-- 00:0c.0 -> ../../../../devices/pci0/00:0c.0 `-- serial}hj7sbah}(h]h ]h"]h$]h&]j?j@uh1j/hhhMjhhhhubh)}(h`This driver binding should replace the existing driver binding mechanism the bus currently uses.h]h`This driver binding should replace the existing driver binding mechanism the bus currently uses.}(hjEhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMuhhhhubh)}(h"Step 6: Supply a hotplug callback.h]h"Step 6: Supply a hotplug callback.}(hjShhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMyhhhhubh)}(hWhenever a device is registered with the driver model core, the userspace program /sbin/hotplug is called to notify userspace. Users can define actions to perform when a device is inserted or removed.h]hWhenever a device is registered with the driver model core, the userspace program /sbin/hotplug is called to notify userspace. Users can define actions to perform when a device is inserted or removed.}(hjahhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM{hhhhubh)}(h`The driver model core passes several arguments to userspace via environment variables, includingh]h`The driver model core passes several arguments to userspace via environment variables, including}(hjohhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhhhhubjl)}(hhh](jq)}(h ACTION: set to 'add' or 'remove'h]h)}(hjh]h(ACTION: set to ‘add’ or ‘remove’}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjubah}(h]h ]h"]h$]h&]uh1jphj}hhhhhNubjq)}(h5DEVPATH: set to the device's physical path in sysfs. h]h)}(h4DEVPATH: set to the device's physical path in sysfs.h]h6DEVPATH: set to the device’s physical path in sysfs.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjubah}(h]h ]h"]h$]h&]uh1jphj}hhhhhNubeh}(h]h ]h"]h$]h&]jjuh1jkhhhMhhhhubh)}(hA bus driver may also supply additional parameters for userspace to consume. To do this, a bus must implement the 'hotplug' method in struct bus_type::h]hA bus driver may also supply additional parameters for userspace to consume. To do this, a bus must implement the ‘hotplug’ method in struct bus_type:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhhhhubj0)}(hnint (*hotplug) (struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size);h]hnint (*hotplug) (struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size);}hjsbah}(h]h ]h"]h$]h&]j?j@uh1j/hhhMhhhhubh)}(h