\section{Buses}

A bus driver is a set of code that communicates with a peripheral bus
of a certain type. Some examples of bus drivers in the kernel include:

\begin{itemize}
\begin{footnotesize}
\item PCI
\item USB
\item SCSI
\item IDE
\item PCMCIA
\end{footnotesize}
\end{itemize}

Bus drivers maintain a list of devices that are present on the bus and
a list of drivers that have registered with it. A bus driver is an
optional compile option, and usually may be compiled as a module to be
loaded at runtime. It's existence is singular. There will never be
multiple instances of a driver for the same bus type at the same
time. Therefore most, if not all, of its internal data structures are
statically allocated. 

A bus instance represents the presence of a bus of a particular type,
such as PCI Bus 0. They are dynamically allocated when the bus
instance is discovered. They contain a list of subordinate devices, as
well as data describing the physical device the bus is connected to
(the bridge) and membership information about which bus type it
belongs to. Bus instances are not currently represented in the driver
model. However, they are mentioned here to note the distinction
between them and bus driver objects.

The driver model defines struct bus\_type to represent instances of
bus drivers, and is described below. The driver model does not define
an object to describe a bus instance yet. This feature may be added in
the future.

\begin{table}
\begin{footnotesize}
\begin{tabularx}{\linewidth}{|X|X|X|} \hline
\textit{Name}	& \textit{Type} & \textit{Description} \\ \hline \hline

name	& char *	& The name of the bus.\\\hline

subsys	& struct subsystem	& Bus's collection of subordinate
	objects.\\\hline 

drvsubsys	& struct subsystem	& Bus's collection of
	subordinate drivers. \\\hline

devsubsys	& struct subsystem	& Bus' collection of
	subordinate devices. \\\hline

devices	& struct list\_head	& Bus's list of devices registered
	with it. \\\hline

\end{tabularx} \\
\end{footnotesize}
\caption{\footnotesize{struct bus\_type Data Fields.}}
\end{table}


\begin{table}
\begin{footnotesize}
\begin{tabularx}{\linewidth}{|X|X|X|} \hline
\textit{Name}	& \textit{Type} & \textit{Description} \\ \hline \hline

match(
  struct device * dev,
  struct device\_driver * drv
)
& int
& Called during driver binding process for bus to compare a device's
	ID, with the list of Ids that the driver supports. 
\\\hline

add(
 struct device * parent,
 char * bus\_id
)
& struct device *
& Called to add a device to a bus at a certain location.
\\\hline

hotplug(
  struct device *dev, 
  char **envp, 
  int num\_envp,
  char *buffer,
  int buffer\_size
)
& int
& Called before /sbin/hotplgu is called on device insertion or
	removal, so bus can format parameters correctly. 
\\\hline

\end{tabularx} \\
\end{footnotesize}
\caption{\footnotesize{struct bus\_type Methods.}}
\end{table}


The members of struct bus\_type center around the lists of objects
that buses maintain. bus\_type contains three subordinate subsystems
and a struct list\_head to manage subordinate objects, though not all
are fully used. 

'subsys' is reserved for managing the set of bus instances of a type,
and is not currently used for that purpose. It is registered with the
kobject core, though, as a child of the global bus subsystem. This
gives the bus a node in the kobject hierarchy , and a directory in the
sysfs filesystem.

'drvsubsys' manages the set of drivers registered with the bus
type. It is currently used, and the drivers registered with the bus
are inserted into the subsystem's list. 

'devsubsys' is intended to manage the list of devices present on all
bus instances of the bus type. However, the bus must use another list
to contain the device objects. Kobjects may only belong to one
subsystem, and the embedded kobject in struct device is a member of
the global device hierarchy. Therefore, struct device contains a list
entry 'bus\_list' for insertion into the bus's list of devices. 

Note that the list of devices that the bus maintains is the list of
all devices on all buses of that type in the system. For example, a
system may have several PCI buses, including multiple Host PCI
buses. Though devices may be not be on the same physical bus, they all
belong to the same bus type. This aides in routines that must access
all devices of a bus type, like when binding a driver to devices.

The 'name' field of the bus is the name of the bus. This field is
redundant with the name field of the embedded subsystem's
kobject. This field may be removed in the future. 

The methods of struct bus\_type are helpers that the core can call to
perform bus-specific actions too specific for the core to efficiently
handle. 

The 'match' method is used during the process of attaching devices to
drivers. Devices drivers typically maintain a table of device IDs that
they supports, and devices each contain an ID. These IDs are
bus-specific, as are the semantics for comparing them. The driver
model core can perform most of the actions of driver binding, such as
walking the list of drivers when a device is inserted, or walking the
list of devices when a driver module is loaded. But, it does not know
what format the device ID table is in, or how it should compare them
(i.e. if it should take into account any masks in the device IDs). The
core instead calls the bus's match method to check if a driver
supports a particular device.

The 'add' callback is available for other kernel objects to tell the
bus driver to look for a particular device at a particular
location. Other objects may know the format of a device's ID, but only
the bus driver knows how to communicate with the device over the bus.

This is useful for firmware drivers that can obtain a list of devices
from the firmware, and wish to tell the kernel about them, instead of
having the kernel probe for them. So far, this method is not
implemented by any bus drivers, or used by any code in the kernel.
This method is not being considered for removal, though, since its
neglect is due to a lack of time rather than a lack of usefulness.

The 'hotplug' method is called by the driver model core before
executing the user mode hotplug agent. The bus is allowed to specify
additional environment variables when the agent is executed.


\subsection*{Programming Interface}

The programming interface for bus drivers consists of registration and
reference counting functions. Bus drivers should be registered in
their startup routines, whether compiled statically or as a
module. They should be unregistered in their module exit
routines. Reference counts for bus drivers should be incremented
before a bus driver is used and decremented once use of the driver is
done.  

\begin{table}
\begin{footnotesize}
\begin{tabularx}{\linewidth}{|X|X|X|} \hline
\textit{Name}	& \textit{Return Type} & \textit{Description} \\ \hline \hline

bus\_register(
  struct bus\_type * bus)
& int
& Register bus driver with driver model core.
\\\hline

bus\_unregister(
  struct bus\_type * bus)
& void
& Unregister bus driver from driver model core.
\\\hline

get\_bus(
  struct bus\_type * bus)
& struct bus\_type *
& Increment reference count of bus driver.
\\\hline

put\_bus(
  struct bus\_type * bus)
& void
& Decrement reference count of bus driver.
\\\hline

\end{tabularx} \\
\end{footnotesize}
\caption{\footnotesize{struct subsystem Programming Interface.}}
\end{table}


There are two caveats of using bus drivers as they are currently
implemented in the driver model . First, the de facto means of
referencing a bus driver is via a pointer to its struct
bus\_type. This implies that the bus drivers must not declare the
object as 'static' and must be explicitly exported for modules to
use. An alternative is to provide a helper that searches for and
returns a bus with a specified name. This is a more desirable solution
from an abstraction perspective, and will likely be added to the
model.  

Secondly, bus drivers contain no internal means of preventing their
module to unload while their reference count is positive. This causes
the referring object to access invalid memory if the module is
unloaded. The proposed solution is to use a semaphore, like device
drivers contain, that bus\_unregister() waits on, and is only unlocked
when the reference count reaches 0. This will be fixed in the near
future. 


\subsection*{Driver Binding}

Device drivers are discussed in a later section, but that does hinder
the discussion of describing the process of binding devices to
drivers. Binding happens whenever either a device or a driver is added
to a bus. The end result is the same, though the means are slightly
different. During attaching or detaching devices or drivers, the bus's
rwsem is taken to serialize these operations. 

When a device is added to the core, the internal function
bus\_add\_device() is called. This inserts the device into the bus's
list of devices, and calls device\_attach(). This function iterates
over the bus's list of drivers and tries to bind it to each one, until
it succeeds. When the device is removed, bus\_remove\_device() is
called, which detaches it from the driver by calling the driver's
'remove' method. 

When a driver is added to the core, the internal function
bus\_add\_driver() is called. This inserts the driver into the bus's
list of drivers, and calls driver\_attach(). This function iterates
over the bus's list of devices, trying to attach to each that does not
already have a driver. It does not stop at the first successful
attachment, as there may be multiple devices that the driver may
control. When a driver module is unloaded, bus\_remove\_driver() is
called, which iterates over the list of devices that the driver is
controlling. The driver's 'remove' method is called for each one. 

During the attachment of either a device or a driver, the function
bus\_match() is called at each iteration. This calls the bus's 'match'
method is called to compare the device ID of the device with the table
of IDs that the driver supports. 'match' should return TRUE (1) if one
of the driver's IDs matched the device's, or FALSE (0) if none of them
did. 

If 'match' returns TRUE, the device's 'driver' pointer is set to point
to the driver, and the driver's 'probe' method is called. If 'probe'
returns success (0), the device is inserted into the driver's list of
devices that it supports.


\subsection*{Bus Helper Functions}

\begin{table}
\begin{footnotesize}
\begin{tabularx}{\linewidth}{|X|X|X|} \hline
\textit{Name}	& \textit{Return Type} & \textit{Description} \\ \hline \hline

bus\_for\_each\_dev(
  struct bus\_type * bus, 
  void * data, 
  int (*callback)(
    struct device * dev, 
    void * data)
  );
& int
& Iterator for accessing each device on a bus sequentially. It holds a
	read lock on the bus,while calling 'callback' for each device.
\\\hline

bus\_for\_each\_drv(
  struct bus\_type * bus, 
  void * data,
  int (*callback)(
    struct device\_driver * drv,
    void * data)
  );
& int
& Identical to bus\_for\_each\_dev(), but operates on a bus's
	registered drivers.
\\\hline

\end{tabularx} \\
\end{footnotesize}
\caption{\footnotesize{struct bus\_type Helper Functions.}}
\end{table}

Occasionally, it is useful to perform an operation on the entire space
of devices or drivers that a bus supports. To aid in this, the driver
model core exports a helper to do each. 

bus\_for\_each\_dev() iterates over each device that a bus object
knows about. For each device, it calls the callback passed in, passing
the current device pointer, and the data that was passed as a
parameter to the function. bus\_for\_each\_drv() behaves identically,
though it operates on the bus's driver-space. 

Each function checks the return value of the callback after calling
it, and returns immediately if it is non-zero.

Each function increments the reference count of the object it's
iterating on before it calls the callback, and releases it when it
returns. 

Each functions takes a read lock for the bus. This allows multiple
iterations to be taking place at the same time, but prevents against a
removal or addition happening while any iterations are in
progress. These functions always increment the reference count of the
object before calling the callback, and decrement it after it
returns. The function does not return which object caused the callback
to return a non-zero result. 

The callback must store this information if it needs to retain it. It
must also increment the reference count of the object to guarantee the
pointer remains valid until it can access it. The example below
illustrates this point.

\begin{footnotesize}
\begin{verbatim}

struct callback\_data {
       struct device * dev;
       char * id;
};

static int callback(struct device * dev, void * data)
{
        struct callback\_data * cd = (struct callback\_data *)data;
        if (!strcmp(dev->bus\_id,cd->id)) {
                cd->dev = get\_device(dev);
                return 1;
        }
        return 0;
}

static int caller(void)
{
        struct callback\_data data = {
                .id = "00:00.0",
        };

        /* find PCI device with ID 00:00.0  */
        if(bus\_for\_each\_dev(&pci\_bus\_type,&data,callback)) {
                struct device * dev = data.dev;
                /* fiddle with device */
                put\_device(dev);
        }
}

\end{verbatim}
\end{footnotesize}