\section{Devices}

A device is a physical component of a computer that performs a
discrete function that the kernel can exert some control over. A
device contains the electrical components to perform its specified
function, also known as its device class. A device resides on a bus of
a certain type. A bus defines a standard architectures for devices
that reside on it, so devices of any function exist on it.

The driver model defines struct device to describe a device
independent of the bus it resides on, or the function it
performs. This generic description contains few members related
directly to physical attributes of the device. It instead is a means
to consolidate the similar aspects of the disparate device
representations into a common place.


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

bus\_list	& struct list\_head	& List entry in bus's list of
	devices. \\\hline

driver\_list	& struct list\_head	& List entry in driver's list
	of devices. \\\hline

intf\_list	& struct list\_head	& List of interface
	descriptors for the device.\\\hline

parent	& struct device		& Pointer to parent
	device. \\\hline

kobj	& struct kobject	& Generic kernel object
	metadata. \\\hline

name	& char[DEVICE\_NAME\_SIZE]	& ASCII description of
	device. \\\hline

bus\_id	& char[BUS\_ID\_SIZE]	& ASCII representation of
	device's bus-specific address. \\\hline

bus	& struct bus\_type *	& Pointer to bus type device belongs
	to. \\\hline

driver	& struct device\_driver *	& Pointer to device's
	controlling driver. \\\hline

driver\_data	& void *	& Device-specific data private to
	driver. \\\hline

class\_num	& u32	& Enumerated number of device within its
	class. \\\hline

class\_data	& void *	& Device-specific data private to
	class.\\\hline

platform\_data	& void *	& Device-specific data private to the
	platform.\\\hline

power\_state	& u32	& Current power state of the device.\\\hline

saved\_state	& void *	& Pointer to saved state for device. \\\hline

dma\_mask	& dma\_mask\_t *	& DMA address mask the device
	can support.\\\hline

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


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

release(
  struct device *
)
& void
& Garbage collection method for tearing down devices.
\\\hline

\end{tabularx} \\
\end{footnotesize}
\caption{\footnotesize{struct device Method.}}
\end{table}

Struct device members fall into three basic categories - meta data,
linkage information, and physical attributes. A device's meta data
consists of fields to describe the device and its reference count.

A device's embedded kobject contains the reference count of the device
and a short 'name' field. Kobjects are described in detail in Appendix
A. Additionally, struct device contains a 'name' field of its own and
a 'bus\_id' field. The latter serves the same purpose as the kobject's
name field - to provide an ASCII identifier unique only in a local
context, i.e. among siblings of a common parent. This redundancy is
known, and will be resolved in the future.

A device's 'name' field provides a longer string which can be used to
provide a user-friendly description of a device, such as "ATI
Technologies Inc Radeon QD" This description is provided by the bus
driver when a device is discovered by looking the device's ID up in a
table of names. 

Struct device also contains several pointers to describe the objects
that the device is associated with. Many of these fields are used by
the core when registering and unregistering a device to determine the
objects to notify. The 'bus' field should be set by the bus driver
before registering a device. The core uses this to determine which bus
to add it to. The 'driver' and field is set by the core when a device
is bound to a driver. The 'class\_num' field is set once the device is
registered with and enumerated by the class its driver belongs to.

The data fields are used so subsystems can share data about an object
without having to setup auxillary means of associating a device
structure with a subsystem-specific object. 'driver\_data' may be used
by the driver to store a driver-specific object for the
device. 'class\_data' may be used by the class to store a
class-specific object for the device. This should be set during the
class's add\_device() callback, as that is when the object is usually
allocated. This object may also be used by a class's interfaces, since
they are conscience of the class's internal representations. 

'platform\_data' is a pointer that the platform driver can use to
store platform-specific data about the device. For example, in
ACPI-based system, the firmware enumerates and stores data about many
devices in the system. The ACPI driver can store a pointer to this
data in 'platform\_data' for later use. 

This feature was an early requirement by ACPI. It has not been used
since its addition, nor has it proven useful to other platforms
besides ACPI-enabled ones. Therefore, it may be removed in the near
future. 

A device's linkage information is represented in the several list
entry structures in the object. It becomes a member of several groups
when it is registered with various drivers. The embedded kobject also
contains a list entry representing membership in the global device
subsystem. A device also has a pointer to its parent device, which is
used by the core to determine some a device's ancestry. 

There are few physical attribute s contained in struct device,  since
the number of physical attributes common to a majority of devices are
very few in number. 'power\_state' is the current power state of the
device. Many bus types define multiple device power states. PCI
defines four power states, D0-D3 for PCI devices, and ACPI 
modeled their generic device power state definition after this. The D0
state is defined as being on and running, and the D3 state is defined
as being off. All devices support these states by default. D1 and D2
are intermediate power states are usually optional for devices to
support, even if the underlying bus can support these states. In these
states, the device is unusable, but not all of the components of the
device have been powered down. This reduces the latency of restoring
the device to the usable D0 state. 

When a device is suspended, physical components in the device are
turned off to save power. When these components are turned back on,
they are supposed to be restored to the identical state they were in
before they were suspended. 'saved\_state' is a field that the device
driver can use to store device context when the device is placed in a
low power state.

Both 'power\_state' and 'saved\_state' are fields that were added to
struct device when the sole motivation was implementing sane power
management infrastructure. Not all devices support power management
beyond being 'On' or 'Off'. Many systems also do not support global
power management, and many configurations do not support any type of
power management mechanism. Because of this, these fields are being
considered for removal. In order to do, though, some other mechanism
for attaching power state information to the device must be
derived. Note that such a mechanism could be used to attach
platform-specific data to a device only when the system and the device
support it. 

'dma\_mask' describes the DMA address mask that the device can
support. This is obviously only relevant if the device supports
DMA-able I/O. Several bus structures contain a dma\_mask, which
motivated the transition of it to the generic struct device. It is to
be set by the bus driver when the device is discovered. Currently,
dma\_mask is only a pointer, which should point to the field in the
bus-specific structure. This should be set by the bus driver before
the device is registered. In the future, the field will be moved
entirely to the generic device.


The 'release' method acts as a desctructor for the device object. It
is called when a device's reference count reaches 0 to inform the
object that allocated it that it is safe to free the device. Since
struct device is usually embedded in a larger object, the larger
object should be freed. 

This method should be initialized by the object that discovers and
allocates the device. This is typically the device's bus driver. Since
there should be only one type of device object that a bus controls,
this method may be moved to the struct bus\_type object in the
future. 



\subsection*{Programming Interface}

The struct device programming interface consists of two parallel
models. One model is the basic registration and reference counting
model common throughout the driver model. However, the interface
exposes the intermediate calls that device\_register() and
device\_unregister() use to express a finer level of control over the
lifetime of a device.  The functions are described in the table
below. 

device\_register() calls device\_initialize() and device\_add() to
initialize a device and insert it into the device hierarchy
respectively. Calling device\_register() is the preferred means of
registering a device, though the intermediate calls may be used
instead to achieve the same result. 

Analogously, device\_unregister() calls device\_del() and
put\_device() to remove the device from the device hierarchy and
decrement its reference count. These intermediate calls may also be
used to achieve the same  result. 

The intermediate interface is exposed to let bus drivers reference and
use device objects before advertising their presence via the hierarchy
and sysfs. This is necessary for USB devices and hot-pluggable bus
types. To initialize a device after it is discovered, a series of I/O
transfers must take place. The device may be removed during this
process, so the subsystem must be aware of its reference count and
potential garbage collection. However, the device is not fully
functional yet, and must not be registered in the hierarchy.


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

device\_register(
  struct device * dev
)
& int
& Initialize device and add it to hierarchy.
\\\hline

device\_unregister(
  struct device * dev
)
& void
& Remove device from hierarchy and decrement reference count.
\\\hline

device\_initialize(
  struct device * dev
)
& void
& Initialize device structure. 
\\\hline

device\_add(
  struct device * dev
)
& int
& Add device to device hierarchy.
\\\hline

device\_del(
  struct device * dev
)
& void
& Remove device from hierarchy.
\\\hline

get\_device(
  struct device * dev
)
& struct device *
& Increment reference count of device.
\\\hline

put\_device(
  struct device * dev
)
& void
& Decrement device reference count.
\\\hline

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