Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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); |
Pavel Machek | 438510f | 2005-04-16 15:25:24 -0700 | [diff] [blame] | 21 | int (*suspend)(struct device * dev, pm_message_t state); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 | |