diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /Documentation/driver-model/bus.txt |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'Documentation/driver-model/bus.txt')
-rw-r--r-- | Documentation/driver-model/bus.txt | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/Documentation/driver-model/bus.txt b/Documentation/driver-model/bus.txt new file mode 100644 index 000000000000..dd62c7b80b3f --- /dev/null +++ b/Documentation/driver-model/bus.txt | |||
@@ -0,0 +1,160 @@ | |||
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); | ||
21 | int (*suspend)(struct device * dev, u32 state); | ||
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 | |||