summary refs log tree commit diff
path: root/Documentation/driver-model
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /Documentation/driver-model
downloadlinux-1da177e4c3f41524e886b7f1b8a0c1fc7321cac2.tar.gz
Linux-2.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')
-rw-r--r--Documentation/driver-model/binding.txt102
-rw-r--r--Documentation/driver-model/bus.txt160
-rw-r--r--Documentation/driver-model/class.txt162
-rw-r--r--Documentation/driver-model/device.txt154
-rw-r--r--Documentation/driver-model/driver.txt287
-rw-r--r--Documentation/driver-model/interface.txt129
-rw-r--r--Documentation/driver-model/overview.txt114
-rw-r--r--Documentation/driver-model/platform.txt99
-rw-r--r--Documentation/driver-model/porting.txt445
9 files changed, 1652 insertions, 0 deletions
diff --git a/Documentation/driver-model/binding.txt b/Documentation/driver-model/binding.txt
new file mode 100644
index 000000000000..f7ec9d625bfc
--- /dev/null
+++ b/Documentation/driver-model/binding.txt
@@ -0,0 +1,102 @@
+
+Driver Binding
+
+Driver binding is the process of associating a device with a device
+driver that can control it. Bus drivers have typically handled this
+because there have been bus-specific structures to represent the
+devices and the drivers. With generic device and device driver
+structures, most of the binding can take place using common code.
+
+
+Bus
+~~~
+
+The bus type structure contains a list of all devices that are on that bus
+type in the system. When device_register is called for a device, it is
+inserted into the end of this list. The bus object also contains a
+list of all drivers of that bus type. When driver_register is called
+for a driver, it is inserted at the end of this list. These are the
+two events which trigger driver binding.
+
+
+device_register
+~~~~~~~~~~~~~~~
+
+When a new device is added, the bus's list of drivers is iterated over
+to find one that supports it. In order to determine that, the device
+ID of the device must match one of the device IDs that the driver
+supports. The format and semantics for comparing IDs is bus-specific. 
+Instead of trying to derive a complex state machine and matching
+algorithm, it is up to the bus driver to provide a callback to compare
+a device against the IDs of a driver. The bus returns 1 if a match was
+found; 0 otherwise.
+
+int match(struct device * dev, struct device_driver * drv);
+
+If a match is found, the device's driver field is set to the driver
+and the driver's probe callback is called. This gives the driver a
+chance to verify that it really does support the hardware, and that
+it's in a working state. 
+
+Device Class
+~~~~~~~~~~~~
+
+Upon the successful completion of probe, the device is registered with
+the class to which it belongs. Device drivers belong to one and only one
+class, and that is set in the driver's devclass field. 
+devclass_add_device is called to enumerate the device within the class
+and actually register it with the class, which happens with the
+class's register_dev callback.
+
+NOTE: The device class structures and core routines to manipulate them
+are not in the mainline kernel, so the discussion is still a bit
+speculative. 
+
+
+Driver
+~~~~~~
+
+When a driver is attached to a device, the device is inserted into the
+driver's list of devices. 
+
+
+sysfs
+~~~~~
+
+A symlink is created in the bus's 'devices' directory that points to
+the device's directory in the physical hierarchy.
+
+A symlink is created in the driver's 'devices' directory that points
+to the device's directory in the physical hierarchy.
+
+A directory for the device is created in the class's directory. A
+symlink is created in that directory that points to the device's
+physical location in the sysfs tree. 
+
+A symlink can be created (though this isn't done yet) in the device's
+physical directory to either its class directory, or the class's
+top-level directory. One can also be created to point to its driver's
+directory also. 
+
+
+driver_register
+~~~~~~~~~~~~~~~
+
+The process is almost identical for when a new driver is added. 
+The bus's list of devices is iterated over to find a match. Devices
+that already have a driver are skipped. All the devices are iterated
+over, to bind as many devices as possible to the driver.
+
+
+Removal
+~~~~~~~
+
+When a device is removed, the reference count for it will eventually
+go to 0. When it does, the remove callback of the driver is called. It
+is removed from the driver's list of devices and the reference count
+of the driver is decremented. All symlinks between the two are removed.
+
+When a driver is removed, the list of devices that it supports is
+iterated over, and the driver's remove callback is called for each
+one. The device is removed from that list and the symlinks removed. 
+
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 @@
+
+Bus Types 
+
+Definition
+~~~~~~~~~~
+
+struct bus_type {
+	char			* name;
+
+	struct subsystem	subsys;
+	struct kset		drivers;
+	struct kset		devices;
+
+	struct bus_attribute	* bus_attrs;
+	struct device_attribute	* dev_attrs;
+	struct driver_attribute	* drv_attrs;
+
+	int		(*match)(struct device * dev, struct device_driver * drv);
+	int		(*hotplug) (struct device *dev, char **envp, 
+				    int num_envp, char *buffer, int buffer_size);
+	int		(*suspend)(struct device * dev, u32 state);
+	int		(*resume)(struct device * dev);
+};
+
+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 provide 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 *);
+
+
diff --git a/Documentation/driver-model/class.txt b/Documentation/driver-model/class.txt
new file mode 100644
index 000000000000..2d1d893a5e5d
--- /dev/null
+++ b/Documentation/driver-model/class.txt
@@ -0,0 +1,162 @@
+
+Device Classes
+
+
+Introduction
+~~~~~~~~~~~~
+A device class describes a type of device, like an audio or network
+device. The following device classes have been identified:
+
+<Insert List of Device Classes Here>
+
+
+Each device class defines a set of semantics and a programming interface
+that devices of that class adhere to. Device drivers are the
+implemention of that programming interface for a particular device on
+a particular bus. 
+
+Device classes are agnostic with respect to what bus a device resides
+on. 
+
+
+Programming Interface
+~~~~~~~~~~~~~~~~~~~~~
+The device class structure looks like: 
+
+
+typedef int (*devclass_add)(struct device *);
+typedef void (*devclass_remove)(struct device *);
+
+struct device_class {
+	char			* name;
+	rwlock_t		lock;
+	u32			devnum;
+	struct list_head	node;
+
+	struct list_head	drivers;
+	struct list_head	intf_list;
+
+	struct driver_dir_entry	dir;
+	struct driver_dir_entry	device_dir;
+	struct driver_dir_entry	driver_dir;
+
+	devclass_add		add_device;
+	devclass_remove		remove_device;
+};
+
+A typical device class definition would look like: 
+
+struct device_class input_devclass = {
+        .name		= "input",
+        .add_device	= input_add_device,
+	.remove_device	= input_remove_device,
+};
+
+Each device class structure should be exported in a header file so it
+can be used by drivers, extensions and interfaces.
+
+Device classes are registered and unregistered with the core using: 
+
+int devclass_register(struct device_class * cls);
+void devclass_unregister(struct device_class * cls);
+
+
+Devices
+~~~~~~~
+As devices are bound to drivers, they are added to the device class
+that the driver belongs to. Before the driver model core, this would
+typically happen during the driver's probe() callback, once the device
+has been initialized. It now happens after the probe() callback
+finishes from the core. 
+
+The device is enumerated in the class. Each time a device is added to
+the class, the class's devnum field is incremented and assigned to the
+device. The field is never decremented, so if the device is removed
+from the class and re-added, it will receive a different enumerated
+value. 
+
+The class is allowed to create a class-specific structure for the
+device and store it in the device's class_data pointer. 
+
+There is no list of devices in the device class. Each driver has a
+list of devices that it supports. The device class has a list of
+drivers of that particular class. To access all of the devices in the
+class, iterate over the device lists of each driver in the class.
+
+
+Device Drivers
+~~~~~~~~~~~~~~
+Device drivers are added to device classes when they are registered
+with the core. A driver specifies the class it belongs to by setting
+the struct device_driver::devclass field. 
+
+
+sysfs directory structure
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+There is a top-level sysfs directory named 'class'. 
+
+Each class gets a directory in the class directory, along with two
+default subdirectories:
+
+        class/
+        `-- input
+            |-- devices
+            `-- drivers
+
+
+Drivers registered with the class get a symlink in the drivers/ directory 
+that points to the driver's directory (under its bus directory):
+
+   class/
+   `-- input
+       |-- devices
+       `-- drivers
+           `-- usb:usb_mouse -> ../../../bus/drivers/usb_mouse/
+
+
+Each device gets a symlink in the devices/ directory that points to the 
+device's directory in the physical hierarchy:
+
+   class/
+   `-- input
+       |-- devices
+       |   `-- 1 -> ../../../root/pci0/00:1f.0/usb_bus/00:1f.2-1:0/
+       `-- drivers
+
+
+Exporting Attributes
+~~~~~~~~~~~~~~~~~~~~
+struct devclass_attribute {
+        struct attribute        attr;
+        ssize_t (*show)(struct device_class *, char * buf, size_t count, loff_t off);
+        ssize_t (*store)(struct device_class *, const char * buf, size_t count, loff_t off);
+};
+
+Class drivers can export attributes using the DEVCLASS_ATTR macro that works
+similarly to the DEVICE_ATTR macro for devices. For example, a definition 
+like this:
+
+static DEVCLASS_ATTR(debug,0644,show_debug,store_debug);
+
+is equivalent to declaring:
+
+static devclass_attribute devclass_attr_debug;
+
+The bus driver can add and remove the attribute from the class's
+sysfs directory using:
+
+int devclass_create_file(struct device_class *, struct devclass_attribute *);
+void devclass_remove_file(struct device_class *, struct devclass_attribute *);
+
+In the example above, the file will be named 'debug' in placed in the
+class's directory in sysfs. 
+
+
+Interfaces
+~~~~~~~~~~
+There may exist multiple mechanisms for accessing the same device of a
+particular class type. Device interfaces describe these mechanisms. 
+
+When a device is added to a device class, the core attempts to add it
+to every interface that is registered with the device class.
+
diff --git a/Documentation/driver-model/device.txt b/Documentation/driver-model/device.txt
new file mode 100644
index 000000000000..58cc5dc8fd3e
--- /dev/null
+++ b/Documentation/driver-model/device.txt
@@ -0,0 +1,154 @@
+
+The Basic Device Structure
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+struct device {
+        struct list_head g_list;
+        struct list_head node;
+        struct list_head bus_list;
+        struct list_head driver_list;
+        struct list_head intf_list;
+        struct list_head children;
+        struct device   * parent;
+
+        char    name[DEVICE_NAME_SIZE];
+        char    bus_id[BUS_ID_SIZE];
+
+        spinlock_t      lock;
+        atomic_t        refcount;
+
+        struct bus_type * bus;
+        struct driver_dir_entry dir;
+
+	u32		class_num;
+
+        struct device_driver *driver;
+        void            *driver_data;
+        void            *platform_data;
+
+        u32             current_state;
+        unsigned char *saved_state;
+
+        void    (*release)(struct device * dev);
+};
+
+Fields 
+~~~~~~
+g_list:	Node in the global device list.
+
+node:	Node in device's parent's children list.
+
+bus_list: Node in device's bus's devices list.
+
+driver_list:   Node in device's driver's devices list.
+
+intf_list:     List of intf_data. There is one structure allocated for
+	       each interface that the device supports.
+
+children:      List of child devices.
+
+parent:        *** FIXME ***
+
+name:	       ASCII description of device. 
+	       Example: " 3Com Corporation 3c905 100BaseTX [Boomerang]"
+
+bus_id:	       ASCII representation of device's bus position. This 
+	       field should be a name unique across all devices on the
+	       bus type the device belongs to. 
+
+	       Example: PCI bus_ids are in the form of
+	       <bus number>:<slot number>.<function number> 
+	       This name is unique across all PCI devices in the system.
+
+lock:	       Spinlock for the device. 
+
+refcount:      Reference count on the device.
+
+bus:	       Pointer to struct bus_type that device belongs to.
+
+dir:	       Device's sysfs directory.
+
+class_num:     Class-enumerated value of the device.
+
+driver:	       Pointer to struct device_driver that controls the device.
+
+driver_data:   Driver-specific data.
+
+platform_data: Platform data specific to the device.
+
+current_state: Current power state of the device.
+
+saved_state:   Pointer to saved state of the device. This is usable by
+	       the device driver controlling the device.
+
+release:       Callback to free the device after all references have 
+	       gone away. This should be set by the allocator of the 
+	       device (i.e. the bus driver that discovered the device).
+
+
+Programming Interface
+~~~~~~~~~~~~~~~~~~~~~
+The bus driver that discovers the device uses this to register the
+device with the core:
+
+int device_register(struct device * dev);
+
+The bus should initialize the following fields:
+
+    - parent
+    - name
+    - bus_id
+    - bus
+
+A device is removed from the core when its reference count goes to
+0. The reference count can be adjusted using:
+
+struct device * get_device(struct device * dev);
+void put_device(struct device * dev);
+
+get_device() will return a pointer to the struct device passed to it
+if the reference is not already 0 (if it's in the process of being
+removed already).
+
+A driver can access the lock in the device structure using: 
+
+void lock_device(struct device * dev);
+void unlock_device(struct device * dev);
+
+
+Attributes
+~~~~~~~~~~
+struct device_attribute {
+        struct attribute        attr;
+        ssize_t (*show)(struct device * dev, char * buf, size_t count, loff_t off);
+        ssize_t (*store)(struct device * dev, const char * buf, size_t count, loff_t off);
+};
+
+Attributes of devices can be exported via drivers using a simple
+procfs-like interface. 
+
+Please see Documentation/filesystems/sysfs.txt for more information
+on how sysfs works.
+
+Attributes are declared using a macro called DEVICE_ATTR:
+
+#define DEVICE_ATTR(name,mode,show,store)
+
+Example:
+
+DEVICE_ATTR(power,0644,show_power,store_power);
+
+This declares a structure of type struct device_attribute named
+'dev_attr_power'. This can then be added and removed to the device's
+directory using:
+
+int device_create_file(struct device *device, struct device_attribute * entry);
+void device_remove_file(struct device * dev, struct device_attribute * attr);
+
+Example:
+
+device_create_file(dev,&dev_attr_power);
+device_remove_file(dev,&dev_attr_power);
+
+The file name will be 'power' with a mode of 0644 (-rw-r--r--).
+
diff --git a/Documentation/driver-model/driver.txt b/Documentation/driver-model/driver.txt
new file mode 100644
index 000000000000..12447787d329
--- /dev/null
+++ b/Documentation/driver-model/driver.txt
@@ -0,0 +1,287 @@
+
+Device Drivers
+
+struct device_driver {
+        char                    * name;
+        struct bus_type         * bus;
+
+        rwlock_t                lock;
+        atomic_t                refcount;
+
+        list_t                  bus_list;
+        list_t                  devices;
+
+        struct driver_dir_entry dir;
+
+        int     (*probe)        (struct device * dev);
+        int     (*remove)       (struct device * dev);
+
+        int     (*suspend)      (struct device * dev, u32 state, u32 level);
+        int     (*resume)       (struct device * dev, u32 level);
+
+        void    (*release)      (struct device_driver * drv);
+};
+
+
+
+Allocation
+~~~~~~~~~~
+
+Device drivers are statically allocated structures. Though there may
+be multiple devices in a system that a driver supports, struct
+device_driver represents the driver as a whole (not a particular
+device instance).
+
+Initialization
+~~~~~~~~~~~~~~
+
+The driver must initialize at least the name and bus fields. It should
+also initialize the devclass field (when it arrives), so it may obtain
+the proper linkage internally. It should also initialize as many of
+the callbacks as possible, though each is optional.
+
+Declaration
+~~~~~~~~~~~
+
+As stated above, struct device_driver objects are statically
+allocated. Below is an example declaration of the eepro100
+driver. This declaration is hypothetical only; it relies on the driver
+being converted completely to the new model. 
+
+static struct device_driver eepro100_driver = {
+       .name		= "eepro100",
+       .bus		= &pci_bus_type,
+       .devclass	= &ethernet_devclass,	/* when it's implemented */
+       
+       .probe		= eepro100_probe,
+       .remove		= eepro100_remove,
+       .suspend		= eepro100_suspend,
+       .resume		= eepro100_resume,
+};
+
+Most drivers will not be able to be converted completely to the new
+model because the bus they belong to has a bus-specific structure with
+bus-specific fields that cannot be generalized. 
+
+The most common example of this are device ID structures. A driver
+typically defines an array of device IDs that it supports. The format
+of these structures and the semantics for comparing device IDs are
+completely bus-specific. Defining them as bus-specific entities would
+sacrifice type-safety, so we keep bus-specific structures around. 
+
+Bus-specific drivers should include a generic struct device_driver in
+the definition of the bus-specific driver. Like this:
+
+struct pci_driver {
+       const struct pci_device_id *id_table;
+       struct device_driver	  driver;
+};
+
+A definition that included bus-specific fields would look like
+(using the eepro100 driver again):
+
+static struct pci_driver eepro100_driver = {
+       .id_table       = eepro100_pci_tbl,
+       .driver	       = {
+		.name		= "eepro100",
+		.bus		= &pci_bus_type,
+		.devclass	= &ethernet_devclass,	/* when it's implemented */
+		.probe		= eepro100_probe,
+		.remove		= eepro100_remove,
+		.suspend	= eepro100_suspend,
+		.resume		= eepro100_resume,
+       },
+};
+
+Some may find the syntax of embedded struct initialization awkward or
+even a bit ugly. So far, it's the best way we've found to do what we want...
+
+Registration
+~~~~~~~~~~~~
+
+int driver_register(struct device_driver * drv);
+
+The driver registers the structure on startup. For drivers that have
+no bus-specific fields (i.e. don't have a bus-specific driver
+structure), they would use driver_register and pass a pointer to their
+struct device_driver object. 
+
+Most drivers, however, will have a bus-specific structure and will
+need to register with the bus using something like pci_driver_register.
+
+It is important that drivers register their driver structure as early as
+possible. Registration with the core initializes several fields in the
+struct device_driver object, including the reference count and the
+lock. These fields are assumed to be valid at all times and may be
+used by the device model core or the bus driver.
+
+
+Transition Bus Drivers
+~~~~~~~~~~~~~~~~~~~~~~
+
+By defining wrapper functions, the transition to the new model can be
+made easier. Drivers can ignore the generic structure altogether and
+let the bus wrapper fill in the fields. For the callbacks, the bus can
+define generic callbacks that forward the call to the bus-specific
+callbacks of the drivers. 
+
+This solution is intended to be only temporary. In order to get class
+information in the driver, the drivers must be modified anyway. Since
+converting drivers to the new model should reduce some infrastructural
+complexity and code size, it is recommended that they are converted as
+class information is added.
+
+Access
+~~~~~~
+
+Once the object has been registered, it may access the common fields of
+the object, like the lock and the list of devices. 
+
+int driver_for_each_dev(struct device_driver * drv, void * data, 
+		        int (*callback)(struct device * dev, void * data));
+
+The devices field is a list of all the devices that have been bound to
+the driver. The LDM core provides a helper function to operate on all
+the devices a driver controls. This helper locks the driver on each
+node access, and does proper reference counting on each device as it
+accesses it. 
+
+
+sysfs
+~~~~~
+
+When a driver is registered, a sysfs directory is created in its
+bus's directory. In this directory, the driver can export an interface
+to userspace to control operation of the driver on a global basis;
+e.g. toggling debugging output in the driver.
+
+A future feature of this directory will be a 'devices' directory. This
+directory will contain symlinks to the directories of devices it
+supports.
+
+
+
+Callbacks
+~~~~~~~~~
+
+	int	(*probe)	(struct device * dev);
+
+probe is called to verify the existence of a certain type of
+hardware. This is called during the driver binding process, after the
+bus has verified that the device ID of a device matches one of the
+device IDs supported by the driver. 
+
+This callback only verifies that there actually is supported hardware
+present. It may allocate a driver-specific structure, but it should
+not do any initialization of the hardware itself. The device-specific
+structure may be stored in the device's driver_data field. 
+
+	int	(*init)		(struct device * dev);
+
+init is called during the binding stage. It is called after probe has
+successfully returned and the device has been registered with its
+class. It is responsible for initializing the hardware.
+
+	int 	(*remove)	(struct device * dev);
+
+remove is called to dissociate a driver with a device. This may be
+called if a device is physically removed from the system, if the
+driver module is being unloaded, or during a reboot sequence. 
+
+It is up to the driver to determine if the device is present or
+not. It should free any resources allocated specifically for the
+device; i.e. anything in the device's driver_data field. 
+
+If the device is still present, it should quiesce the device and place
+it into a supported low-power state.
+
+	int	(*suspend)	(struct device * dev, u32 state, u32 level);
+
+suspend is called to put the device in a low power state. There are
+several stages to successfully suspending a device, which is denoted in
+the @level parameter. Breaking the suspend transition into several
+stages affords the platform flexibility in performing device power
+management based on the requirements of the system and the
+user-defined policy.
+
+SUSPEND_NOTIFY notifies the device that a suspend transition is about
+to happen. This happens on system power state transitions to verify
+that all devices can successfully suspend.
+
+A driver may choose to fail on this call, which should cause the
+entire suspend transition to fail. A driver should fail only if it
+knows that the device will not be able to be resumed properly when the
+system wakes up again. It could also fail if it somehow determines it
+is in the middle of an operation too important to stop.
+
+SUSPEND_DISABLE tells the device to stop I/O transactions. When it
+stops transactions, or what it should do with unfinished transactions
+is a policy of the driver. After this call, the driver should not
+accept any other I/O requests.
+
+SUSPEND_SAVE_STATE tells the device to save the context of the
+hardware. This includes any bus-specific hardware state and
+device-specific hardware state. A pointer to this saved state can be
+stored in the device's saved_state field.
+
+SUSPEND_POWER_DOWN tells the driver to place the device in the low
+power state requested. 
+
+Whether suspend is called with a given level is a policy of the
+platform. Some levels may be omitted; drivers must not assume the
+reception of any level. However, all levels must be called in the
+order above; i.e. notification will always come before disabling;
+disabling the device will come before suspending the device.
+
+All calls are made with interrupts enabled, except for the
+SUSPEND_POWER_DOWN level.
+
+	int	(*resume)	(struct device * dev, u32 level);
+
+Resume is used to bring a device back from a low power state. Like the
+suspend transition, it happens in several stages. 
+
+RESUME_POWER_ON tells the driver to set the power state to the state
+before the suspend call (The device could have already been in a low
+power state before the suspend call to put in a lower power state). 
+
+RESUME_RESTORE_STATE tells the driver to restore the state saved by
+the SUSPEND_SAVE_STATE suspend call. 
+
+RESUME_ENABLE tells the driver to start accepting I/O transactions
+again. Depending on driver policy, the device may already have pending
+I/O requests. 
+
+RESUME_POWER_ON is called with interrupts disabled. The other resume
+levels are called with interrupts enabled. 
+
+As with the various suspend stages, the driver must not assume that
+any other resume calls have been or will be made. Each call should be
+self-contained and not dependent on any external state.
+
+
+Attributes
+~~~~~~~~~~
+struct driver_attribute {
+        struct attribute        attr;
+        ssize_t (*show)(struct device_driver *, char * buf, size_t count, loff_t off);
+        ssize_t (*store)(struct device_driver *, const char * buf, size_t count, loff_t off);
+};
+
+Device drivers can export attributes via their sysfs directories. 
+Drivers can declare attributes using a DRIVER_ATTR macro that works
+identically to the DEVICE_ATTR macro. 
+
+Example:
+
+DRIVER_ATTR(debug,0644,show_debug,store_debug);
+
+This is equivalent to declaring:
+
+struct driver_attribute driver_attr_debug;
+
+This can then be used to add and remove the attribute from the
+driver's directory using:
+
+int driver_create_file(struct device_driver *, struct driver_attribute *);
+void driver_remove_file(struct device_driver *, struct driver_attribute *);
diff --git a/Documentation/driver-model/interface.txt b/Documentation/driver-model/interface.txt
new file mode 100644
index 000000000000..c66912bfe866
--- /dev/null
+++ b/Documentation/driver-model/interface.txt
@@ -0,0 +1,129 @@
+
+Device Interfaces
+
+Introduction
+~~~~~~~~~~~~
+
+Device interfaces are the logical interfaces of device classes that correlate
+directly to userspace interfaces, like device nodes. 
+   
+Each device class may have multiple interfaces through which you can 
+access the same device. An input device may support the mouse interface, 
+the 'evdev' interface, and the touchscreen interface. A SCSI disk would 
+support the disk interface, the SCSI generic interface, and possibly a raw 
+device interface. 
+
+Device interfaces are registered with the class they belong to. As devices
+are added to the class, they are added to each interface registered with
+the class. The interface is responsible for determining whether the device
+supports the interface or not. 
+
+
+Programming Interface
+~~~~~~~~~~~~~~~~~~~~~
+
+struct device_interface {
+	char			* name;
+	rwlock_t		lock;
+	u32			devnum;
+	struct device_class	* devclass;
+
+	struct list_head	node;
+	struct driver_dir_entry	dir;
+
+	int (*add_device)(struct device *);
+	int (*add_device)(struct intf_data *);
+};
+
+int interface_register(struct device_interface *);
+void interface_unregister(struct device_interface *);
+
+
+An interface must specify the device class it belongs to. It is added
+to that class's list of interfaces on registration.
+
+
+Interfaces can be added to a device class at any time. Whenever it is
+added, each device in the class is passed to the interface's
+add_device callback. When an interface is removed, each device is
+removed from the interface.
+
+
+Devices
+~~~~~~~
+Once a device is added to a device class, it is added to each
+interface that is registered with the device class. The class
+is expected to place a class-specific data structure in 
+struct device::class_data. The interface can use that (along with
+other fields of struct device) to determine whether or not the driver
+and/or device support that particular interface.
+
+
+Data
+~~~~
+
+struct intf_data {
+	struct list_head	node;
+	struct device_interface	* intf;
+	struct device 		* dev;
+	u32			intf_num;
+};
+
+int interface_add_data(struct interface_data *);
+
+The interface is responsible for allocating and initializing a struct 
+intf_data and calling interface_add_data() to add it to the device's list
+of interfaces it belongs to. This list will be iterated over when the device
+is removed from the class (instead of all possible interfaces for a class).
+This structure should probably be embedded in whatever per-device data 
+structure the interface is allocating anyway.
+   
+Devices are enumerated within the interface. This happens in interface_add_data()
+and the enumerated value is stored in the struct intf_data for that device. 
+
+sysfs
+~~~~~
+Each interface is given a directory in the directory of the device
+class it belongs to:
+
+Interfaces get a directory in the class's directory as well:
+
+   class/
+   `-- input
+       |-- devices
+       |-- drivers
+       |-- mouse
+       `-- evdev
+
+When a device is added to the interface, a symlink is created that points 
+to the device's directory in the physical hierarchy:
+
+   class/
+   `-- input
+       |-- devices
+       |   `-- 1 -> ../../../root/pci0/00:1f.0/usb_bus/00:1f.2-1:0/
+       |-- drivers
+       |   `-- usb:usb_mouse -> ../../../bus/drivers/usb_mouse/
+       |-- mouse
+       |   `-- 1 -> ../../../root/pci0/00:1f.0/usb_bus/00:1f.2-1:0/
+       `-- evdev
+           `-- 1 -> ../../../root/pci0/00:1f.0/usb_bus/00:1f.2-1:0/
+
+
+Future Plans
+~~~~~~~~~~~~
+A device interface is correlated directly with a userspace interface
+for a device, specifically a device node. For instance, a SCSI disk
+exposes at least two interfaces to userspace: the standard SCSI disk
+interface and the SCSI generic interface. It might also export a raw
+device interface. 
+
+Many interfaces have a major number associated with them and each
+device gets a minor number. Or, multiple interfaces might share one
+major number, and each will receive a range of minor numbers (like in
+the case of input devices).
+
+These major and minor numbers could be stored in the interface
+structure. Major and minor allocations could happen when the interface
+is registered with the class, or via a helper function. 
+
diff --git a/Documentation/driver-model/overview.txt b/Documentation/driver-model/overview.txt
new file mode 100644
index 000000000000..44662735cf81
--- /dev/null
+++ b/Documentation/driver-model/overview.txt
@@ -0,0 +1,114 @@
+The Linux Kernel Device Model
+
+Patrick Mochel	<mochel@osdl.org>
+
+26 August 2002
+
+
+Overview
+~~~~~~~~
+
+This driver model is a unification of all the current, disparate driver models
+that are currently in the kernel. It is intended to augment the
+bus-specific drivers for bridges and devices by consolidating a set of data
+and operations into globally accessible data structures.
+
+Current driver models implement some sort of tree-like structure (sometimes
+just a list) for the devices they control. But, there is no linkage between
+the different bus types.
+
+A common data structure can provide this linkage with little overhead: when a
+bus driver discovers a particular device, it can insert it into the global
+tree as well as its local tree. In fact, the local tree becomes just a subset
+of the global tree.
+
+Common data fields can also be moved out of the local bus models into the
+global model. Some of the manipulations of these fields can also be
+consolidated. Most likely, manipulation functions will become a set
+of helper functions, which the bus drivers wrap around to include any
+bus-specific items.
+
+The common device and bridge interface currently reflects the goals of the
+modern PC: namely the ability to do seamless Plug and Play, power management,
+and hot plug. (The model dictated by Intel and Microsoft (read: ACPI) ensures
+us that any device in the system may fit any of these criteria.)
+
+In reality, not every bus will be able to support such operations. But, most
+buses will support a majority of those operations, and all future buses will.
+In other words, a bus that doesn't support an operation is the exception,
+instead of the other way around.
+
+
+
+Downstream Access
+~~~~~~~~~~~~~~~~~
+
+Common data fields have been moved out of individual bus layers into a common
+data structure. But, these fields must still be accessed by the bus layers,
+and sometimes by the device-specific drivers.
+
+Other bus layers are encouraged to do what has been done for the PCI layer.
+struct pci_dev now looks like this:
+
+struct pci_dev {
+	...
+
+	struct device device;
+};
+
+Note first that it is statically allocated. This means only one allocation on
+device discovery. Note also that it is at the _end_ of struct pci_dev. This is
+to make people think about what they're doing when switching between the bus
+driver and the global driver; and to prevent against mindless casts between
+the two.
+
+The PCI bus layer freely accesses the fields of struct device. It knows about
+the structure of struct pci_dev, and it should know the structure of struct
+device. PCI devices that have been converted generally do not touch the fields
+of struct device. More precisely, device-specific drivers should not touch
+fields of struct device unless there is a strong compelling reason to do so.
+
+This abstraction is prevention of unnecessary pain during transitional phases.
+If the name of the field changes or is removed, then every downstream driver
+will break. On the other hand, if only the bus layer (and not the device
+layer) accesses struct device, it is only that layer that needs to change.
+
+
+User Interface
+~~~~~~~~~~~~~~
+
+By virtue of having a complete hierarchical view of all the devices in the
+system, exporting a complete hierarchical view to userspace becomes relatively
+easy. This has been accomplished by implementing a special purpose virtual
+file system named sysfs. It is hence possible for the user to mount the
+whole sysfs filesystem anywhere in userspace.
+
+This can be done permanently by providing the following entry into the
+/etc/fstab (under the provision that the mount point does exist, of course):
+
+none     	/sys	sysfs    defaults		0	0
+
+Or by hand on the command line:
+
+# mount -t sysfs sysfs /sys
+
+Whenever a device is inserted into the tree, a directory is created for it.
+This directory may be populated at each layer of discovery - the global layer,
+the bus layer, or the device layer.
+
+The global layer currently creates two files - 'name' and 'power'. The
+former only reports the name of the device. The latter reports the
+current power state of the device. It will also be used to set the current
+power state. 
+
+The bus layer may also create files for the devices it finds while probing the
+bus. For example, the PCI layer currently creates 'irq' and 'resource' files
+for each PCI device.
+
+A device-specific driver may also export files in its directory to expose
+device-specific data or tunable interfaces.
+
+More information about the sysfs directory layout can be found in
+the other documents in this directory and in the file 
+Documentation/filesystems/sysfs.txt.
+
diff --git a/Documentation/driver-model/platform.txt b/Documentation/driver-model/platform.txt
new file mode 100644
index 000000000000..5eee3e0bfc4c
--- /dev/null
+++ b/Documentation/driver-model/platform.txt
@@ -0,0 +1,99 @@
+Platform Devices and Drivers
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Platform devices
+~~~~~~~~~~~~~~~~
+Platform devices are devices that typically appear as autonomous
+entities in the system. This includes legacy port-based devices and
+host bridges to peripheral buses. 
+
+
+Platform drivers
+~~~~~~~~~~~~~~~~
+Drivers for platform devices are typically very simple and
+unstructured. Either the device was present at a particular I/O port
+and the driver was loaded, or it was not. There was no possibility
+of hotplugging or alternative discovery besides probing at a specific
+I/O address and expecting a specific response.
+
+
+Other Architectures, Modern Firmware, and new Platforms
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+These devices are not always at the legacy I/O ports. This is true on
+other architectures and on some modern architectures. In most cases,
+the drivers are modified to discover the devices at other well-known
+ports for the given platform. However, the firmware in these systems
+does usually know where exactly these devices reside, and in some
+cases, it's the only way of discovering them. 
+
+
+The Platform Bus
+~~~~~~~~~~~~~~~~
+A platform bus has been created to deal with these issues. First and
+foremost, it groups all the legacy devices under a common bus, and
+gives them a common parent if they don't already have one. 
+
+But, besides the organizational benefits, the platform bus can also
+accommodate firmware-based enumeration. 
+
+
+Device Discovery
+~~~~~~~~~~~~~~~~
+The platform bus has no concept of probing for devices. Devices
+discovery is left up to either the legacy drivers or the
+firmware. These entities are expected to notify the platform of
+devices that it discovers via the bus's add() callback:
+
+	platform_bus.add(parent,bus_id).
+
+
+Bus IDs
+~~~~~~~
+Bus IDs are the canonical names for the devices. There is no globally
+standard addressing mechanism for legacy devices. In the IA-32 world,
+we have Pnp IDs to use, as well as the legacy I/O ports. However,
+neither tell what the device really is or have any meaning on other
+platforms. 
+
+Since both PnP IDs and the legacy I/O ports (and other standard I/O
+ports for specific devices) have a 1:1 mapping, we map the
+platform-specific name or identifier to a generic name (at least
+within the scope of the kernel).
+
+For example, a serial driver might find a device at I/O 0x3f8. The
+ACPI firmware might also discover a device with PnP ID (_HID)
+PNP0501. Both correspond to the same device and should be mapped to the
+canonical name 'serial'. 
+
+The bus_id field should be a concatenation of the canonical name and
+the instance of that type of device. For example, the device at I/O
+port 0x3f8 should have a bus_id of "serial0". This places the
+responsibility of enumerating devices of a particular type up to the
+discovery mechanism. But, they are the entity that should know best
+(as opposed to the platform bus driver).
+
+
+Drivers 
+~~~~~~~
+Drivers for platform devices should have a name that is the same as
+the canonical name of the devices they support. This allows the
+platform bus driver to do simple matching with the basic data
+structures to determine if a driver supports a certain device. 
+
+For example, a legacy serial driver should have a name of 'serial' and
+register itself with the platform bus. 
+
+
+Driver Binding
+~~~~~~~~~~~~~~
+Legacy drivers assume they are bound to the device once they start up
+and probe an I/O port. Divorcing them from this will be a difficult
+process. However, that shouldn't prevent us from implementing
+firmware-based enumeration. 
+
+The firmware should notify the platform bus about devices before the
+legacy drivers have had a chance to load. Once the drivers are loaded,
+they driver model core will attempt to bind the driver to any
+previously-discovered devices. Once that has happened, it will be free
+to discover any other devices it pleases.
+
diff --git a/Documentation/driver-model/porting.txt b/Documentation/driver-model/porting.txt
new file mode 100644
index 000000000000..ff2fef2107f0
--- /dev/null
+++ b/Documentation/driver-model/porting.txt
@@ -0,0 +1,445 @@
+
+Porting Drivers to the New Driver Model
+
+Patrick Mochel
+
+7 January 2003
+
+
+Overview
+
+Please refer to Documentation/driver-model/*.txt for definitions of
+various driver types and concepts. 
+
+Most 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.
+
+In 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. 
+
+The 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 
+
+	# mount -t sysfs sysfs /sys
+
+
+
+The Process
+
+Step 0: Read include/linux/device.h for object and function definitions. 
+
+Step 1: Registering the bus driver. 
+
+
+- Define a struct bus_type for the bus driver.
+
+struct bus_type pci_bus_type = {
+        .name           = "pci",
+};
+
+
+- Register 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);
+
+
+- Export 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.
+
+From include/linux/pci.h:
+
+extern struct bus_type pci_bus_type;
+
+
+From file the above code appears in:
+
+EXPORT_SYMBOL(pci_bus_type);
+
+
+
+- This 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
+
+
+
+Step 2: Registering Devices. 
+
+struct device represents a single device. It mainly contains metadata
+describing the relationship the device has to other entities. 
+
+
+- Embedd 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).
+
+
+- Initialize 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.
+
+
+- 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
+
+
+
+Step 3: Registering Drivers.
+
+struct device_driver is a simple driver structure that contains a set
+of operations that the driver model core may call. 
+
+
+- Embed a struct device_driver in the bus-specific driver. 
+
+  Just like with devices, do something like:
+
+struct pci_driver {
+       ...
+       struct device_driver    driver;
+};
+
+
+- Initialize 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. 
+
+
+- Register 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.
+
+
+- Sysfs 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
+
+
+Step 4: Define Generic Methods for Drivers.
+
+struct 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. 
+
+It 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: 
+
+
+static 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;
+}
+
+
+The generic driver should be initialized with these methods before it
+is registered. 
+
+        /* 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);
+
+
+Ideally, the bus should only initialize the fields if they are not
+already set. This allows the drivers to implement their own generic
+methods. 
+
+
+Step 5: Support generic driver binding. 
+
+The 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. 
+
+A 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. 
+
+Instead, a bus may supply a method in struct bus_type that does the
+comparison: 
+
+  int (*match)(struct device * dev, struct device_driver * drv);
+
+match should return '1' if the driver supports the device, and '0'
+otherwise. 
+
+When 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. 
+
+When 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. 
+
+When a device is successfully bound to a device, 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:
+
+/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
+
+
+This driver binding should replace the existing driver binding
+mechanism the bus currently uses. 
+
+
+Step 6: Supply a hotplug callback.
+
+Whenever 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. 
+
+The driver model core passes several arguments to userspace via
+environment variables, including
+
+- ACTION: set to 'add' or 'remove'
+- DEVPATH: set to the device's physical path in sysfs. 
+
+A 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:
+
+     int (*hotplug) (struct device *dev, char **envp, 
+                     int num_envp, char *buffer, int buffer_size);
+
+This is called immediately before /sbin/hotplug is executed. 
+
+
+Step 7: Cleaning up the bus driver.
+
+The generic bus, device, and driver structures provide several fields
+that can replace those defined privately to the bus driver. 
+
+- Device list.
+
+struct bus_type contains a list of all devices registered with the bus
+type. This includes all devices on all instances of that bus type.
+An internal list that the bus uses may be removed, in favor of using
+this one.
+
+The core provides an iterator to access these devices. 
+
+int bus_for_each_dev(struct bus_type * bus, struct device * start, 
+                     void * data, int (*fn)(struct device *, void *));
+
+
+- Driver list.
+
+struct bus_type also contains a list of all drivers registered with
+it. An internal list of drivers that the bus driver maintains may 
+be removed in favor of using the generic one. 
+
+The drivers may be iterated over, like devices: 
+
+int bus_for_each_drv(struct bus_type * bus, struct device_driver * start,
+                     void * data, int (*fn)(struct device_driver *, void *));
+
+
+Please see drivers/base/bus.c for more information.
+
+
+- rwsem 
+
+struct bus_type contains an rwsem that protects all core accesses to
+the device and driver lists. This can be used by the bus driver
+internally, and should be used when accessing the device or driver
+lists the bus maintains. 
+
+
+- Device and driver fields. 
+
+Some of the fields in struct device and struct device_driver duplicate
+fields in the bus-specific representations of these objects. Feel free
+to remove the bus-specific ones and favor the generic ones. Note
+though, that this will likely mean fixing up all the drivers that
+reference the bus-specific fields (though those should all be 1-line
+changes).
+