|  | 
 | Bus Types  | 
 |  | 
 | Definition | 
 | ~~~~~~~~~~ | 
 | See the kerneldoc for the struct bus_type. | 
 |  | 
 | int bus_register(struct bus_type * bus); | 
 |  | 
 |  | 
 | Declaration | 
 | ~~~~~~~~~~~ | 
 |  | 
 | Each bus type in the kernel (PCI, USB, etc) should declare one static | 
 | object of this type. They must initialize the name field, and may | 
 | optionally initialize the match callback. | 
 |  | 
 | struct bus_type pci_bus_type = { | 
 |        .name	= "pci", | 
 |        .match	= pci_bus_match, | 
 | }; | 
 |  | 
 | The structure should be exported to drivers in a header file: | 
 |  | 
 | extern struct bus_type pci_bus_type; | 
 |  | 
 |  | 
 | Registration | 
 | ~~~~~~~~~~~~ | 
 |  | 
 | When a bus driver is initialized, it calls bus_register. This | 
 | initializes the rest of the fields in the bus object and inserts it | 
 | into a global list of bus types. Once the bus object is registered,  | 
 | the fields in it are usable by the bus driver.  | 
 |  | 
 |  | 
 | Callbacks | 
 | ~~~~~~~~~ | 
 |  | 
 | match(): Attaching Drivers to Devices | 
 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 
 |  | 
 | The format of device ID structures and the semantics for comparing | 
 | them are inherently bus-specific. Drivers typically declare an array | 
 | of device IDs of devices they support that reside in a bus-specific | 
 | driver structure.  | 
 |  | 
 | The purpose of the match callback is to give the bus an opportunity to | 
 | determine if a particular driver supports a particular device by | 
 | comparing the device IDs the driver supports with the device ID of a | 
 | particular device, without sacrificing bus-specific functionality or | 
 | type-safety.  | 
 |  | 
 | When a driver is registered with the bus, the bus's list of devices is | 
 | iterated over, and the match callback is called for each device that | 
 | does not have a driver associated with it.  | 
 |  | 
 |  | 
 |  | 
 | Device and Driver Lists | 
 | ~~~~~~~~~~~~~~~~~~~~~~~ | 
 |  | 
 | The lists of devices and drivers are intended to replace the local | 
 | lists that many buses keep. They are lists of struct devices and | 
 | struct device_drivers, respectively. Bus drivers are free to use the | 
 | lists as they please, but conversion to the bus-specific type may be | 
 | necessary.  | 
 |  | 
 | The LDM core provides helper functions for iterating over each list. | 
 |  | 
 | int bus_for_each_dev(struct bus_type * bus, struct device * start, void * data, | 
 | 		     int (*fn)(struct device *, void *)); | 
 |  | 
 | int bus_for_each_drv(struct bus_type * bus, struct device_driver * start,  | 
 | 		     void * data, int (*fn)(struct device_driver *, void *)); | 
 |  | 
 | These helpers iterate over the respective list, and call the callback | 
 | for each device or driver in the list. All list accesses are | 
 | synchronized by taking the bus's lock (read currently). The reference | 
 | count on each object in the list is incremented before the callback is | 
 | called; it is decremented after the next object has been obtained. The | 
 | lock is not held when calling the callback.  | 
 |  | 
 |  | 
 | sysfs | 
 | ~~~~~~~~ | 
 | There is a top-level directory named 'bus'. | 
 |  | 
 | Each bus gets a directory in the bus directory, along with two default | 
 | directories: | 
 |  | 
 | 	/sys/bus/pci/ | 
 | 	|-- devices | 
 | 	`-- drivers | 
 |  | 
 | Drivers registered with the bus get a directory in the bus's drivers | 
 | directory: | 
 |  | 
 | 	/sys/bus/pci/ | 
 | 	|-- devices | 
 | 	`-- drivers | 
 | 	    |-- Intel ICH | 
 | 	    |-- Intel ICH Joystick | 
 | 	    |-- agpgart | 
 | 	    `-- e100 | 
 |  | 
 | Each device that is discovered on a bus of that type gets a symlink in | 
 | the bus's devices directory to the device's directory in the physical | 
 | hierarchy: | 
 |  | 
 | 	/sys/bus/pci/ | 
 | 	|-- devices | 
 | 	|   |-- 00:00.0 -> ../../../root/pci0/00:00.0 | 
 | 	|   |-- 00:01.0 -> ../../../root/pci0/00:01.0 | 
 | 	|   `-- 00:02.0 -> ../../../root/pci0/00:02.0 | 
 | 	`-- drivers | 
 |  | 
 |  | 
 | Exporting Attributes | 
 | ~~~~~~~~~~~~~~~~~~~~ | 
 | struct bus_attribute { | 
 | 	struct attribute	attr; | 
 | 	ssize_t (*show)(struct bus_type *, char * buf); | 
 | 	ssize_t (*store)(struct bus_type *, const char * buf, size_t count); | 
 | }; | 
 |  | 
 | Bus drivers can export attributes using the BUS_ATTR macro that works | 
 | similarly to the DEVICE_ATTR macro for devices. For example, a definition  | 
 | like this: | 
 |  | 
 | static BUS_ATTR(debug,0644,show_debug,store_debug); | 
 |  | 
 | is equivalent to declaring: | 
 |  | 
 | static bus_attribute bus_attr_debug; | 
 |  | 
 | This can then be used to add and remove the attribute from the bus's | 
 | sysfs directory using: | 
 |  | 
 | int bus_create_file(struct bus_type *, struct bus_attribute *); | 
 | void bus_remove_file(struct bus_type *, struct bus_attribute *); | 
 |  | 
 |  |