]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | |
2 | Bus Types | |
3 | ||
4 | Definition | |
5 | ~~~~~~~~~~ | |
6 | ||
7 | struct bus_type { | |
8 | char * name; | |
9 | ||
10 | struct subsystem subsys; | |
11 | struct kset drivers; | |
12 | struct kset devices; | |
13 | ||
14 | struct bus_attribute * bus_attrs; | |
15 | struct device_attribute * dev_attrs; | |
16 | struct driver_attribute * drv_attrs; | |
17 | ||
18 | int (*match)(struct device * dev, struct device_driver * drv); | |
19 | int (*hotplug) (struct device *dev, char **envp, | |
20 | int num_envp, char *buffer, int buffer_size); | |
438510f6 | 21 | int (*suspend)(struct device * dev, pm_message_t state); |
1da177e4 LT |
22 | int (*resume)(struct device * dev); |
23 | }; | |
24 | ||
25 | int bus_register(struct bus_type * bus); | |
26 | ||
27 | ||
28 | Declaration | |
29 | ~~~~~~~~~~~ | |
30 | ||
31 | Each bus type in the kernel (PCI, USB, etc) should declare one static | |
32 | object of this type. They must initialize the name field, and may | |
33 | optionally initialize the match callback. | |
34 | ||
35 | struct bus_type pci_bus_type = { | |
36 | .name = "pci", | |
37 | .match = pci_bus_match, | |
38 | }; | |
39 | ||
40 | The structure should be exported to drivers in a header file: | |
41 | ||
42 | extern struct bus_type pci_bus_type; | |
43 | ||
44 | ||
45 | Registration | |
46 | ~~~~~~~~~~~~ | |
47 | ||
48 | When a bus driver is initialized, it calls bus_register. This | |
49 | initializes the rest of the fields in the bus object and inserts it | |
50 | into a global list of bus types. Once the bus object is registered, | |
51 | the fields in it are usable by the bus driver. | |
52 | ||
53 | ||
54 | Callbacks | |
55 | ~~~~~~~~~ | |
56 | ||
57 | match(): Attaching Drivers to Devices | |
58 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
59 | ||
60 | The format of device ID structures and the semantics for comparing | |
61 | them are inherently bus-specific. Drivers typically declare an array | |
62 | of device IDs of devices they support that reside in a bus-specific | |
63 | driver structure. | |
64 | ||
65 | The purpose of the match callback is provide the bus an opportunity to | |
66 | determine if a particular driver supports a particular device by | |
67 | comparing the device IDs the driver supports with the device ID of a | |
68 | particular device, without sacrificing bus-specific functionality or | |
69 | type-safety. | |
70 | ||
71 | When a driver is registered with the bus, the bus's list of devices is | |
72 | iterated over, and the match callback is called for each device that | |
73 | does not have a driver associated with it. | |
74 | ||
75 | ||
76 | ||
77 | Device and Driver Lists | |
78 | ~~~~~~~~~~~~~~~~~~~~~~~ | |
79 | ||
80 | The lists of devices and drivers are intended to replace the local | |
81 | lists that many buses keep. They are lists of struct devices and | |
82 | struct device_drivers, respectively. Bus drivers are free to use the | |
83 | lists as they please, but conversion to the bus-specific type may be | |
84 | necessary. | |
85 | ||
86 | The LDM core provides helper functions for iterating over each list. | |
87 | ||
88 | int bus_for_each_dev(struct bus_type * bus, struct device * start, void * data, | |
89 | int (*fn)(struct device *, void *)); | |
90 | ||
91 | int bus_for_each_drv(struct bus_type * bus, struct device_driver * start, | |
92 | void * data, int (*fn)(struct device_driver *, void *)); | |
93 | ||
94 | These helpers iterate over the respective list, and call the callback | |
95 | for each device or driver in the list. All list accesses are | |
96 | synchronized by taking the bus's lock (read currently). The reference | |
97 | count on each object in the list is incremented before the callback is | |
98 | called; it is decremented after the next object has been obtained. The | |
99 | lock is not held when calling the callback. | |
100 | ||
101 | ||
102 | sysfs | |
103 | ~~~~~~~~ | |
104 | There is a top-level directory named 'bus'. | |
105 | ||
106 | Each bus gets a directory in the bus directory, along with two default | |
107 | directories: | |
108 | ||
109 | /sys/bus/pci/ | |
110 | |-- devices | |
111 | `-- drivers | |
112 | ||
113 | Drivers registered with the bus get a directory in the bus's drivers | |
114 | directory: | |
115 | ||
116 | /sys/bus/pci/ | |
117 | |-- devices | |
118 | `-- drivers | |
119 | |-- Intel ICH | |
120 | |-- Intel ICH Joystick | |
121 | |-- agpgart | |
122 | `-- e100 | |
123 | ||
124 | Each device that is discovered on a bus of that type gets a symlink in | |
125 | the bus's devices directory to the device's directory in the physical | |
126 | hierarchy: | |
127 | ||
128 | /sys/bus/pci/ | |
129 | |-- devices | |
130 | | |-- 00:00.0 -> ../../../root/pci0/00:00.0 | |
131 | | |-- 00:01.0 -> ../../../root/pci0/00:01.0 | |
132 | | `-- 00:02.0 -> ../../../root/pci0/00:02.0 | |
133 | `-- drivers | |
134 | ||
135 | ||
136 | Exporting Attributes | |
137 | ~~~~~~~~~~~~~~~~~~~~ | |
138 | struct bus_attribute { | |
139 | struct attribute attr; | |
140 | ssize_t (*show)(struct bus_type *, char * buf); | |
141 | ssize_t (*store)(struct bus_type *, const char * buf, size_t count); | |
142 | }; | |
143 | ||
144 | Bus drivers can export attributes using the BUS_ATTR macro that works | |
145 | similarly to the DEVICE_ATTR macro for devices. For example, a definition | |
146 | like this: | |
147 | ||
148 | static BUS_ATTR(debug,0644,show_debug,store_debug); | |
149 | ||
150 | is equivalent to declaring: | |
151 | ||
152 | static bus_attribute bus_attr_debug; | |
153 | ||
154 | This can then be used to add and remove the attribute from the bus's | |
155 | sysfs directory using: | |
156 | ||
157 | int bus_create_file(struct bus_type *, struct bus_attribute *); | |
158 | void bus_remove_file(struct bus_type *, struct bus_attribute *); | |
159 | ||
160 |