Add a chapter to describe newbus.
Submitted by: Hiten Pandya <hiten@angelica.unixdaemons.com> PR: docs/42557
This commit is contained in:
parent
f4da4c5ab8
commit
7e4ba0309d
Notes:
svn2git
2020-12-08 03:00:23 +00:00
svn path=/head/; revision=14212
8 changed files with 1101 additions and 14 deletions
en_US.ISO8859-1/books
arch-handbook
developers-handbook
share/sgml
|
@ -9,6 +9,8 @@
|
|||
%bookinfo;
|
||||
<!ENTITY % man PUBLIC "-//FreeBSD//ENTITIES DocBook Manual Page Entities//EN">
|
||||
%man;
|
||||
<!ENTITY % freebsd PUBLIC "-//FreeBSD//ENTITIES DocBook Miscellaneous FreeBSD Entities//EN">
|
||||
%freebsd;
|
||||
<!ENTITY % chapters SYSTEM "chapters.ent"> %chapters;
|
||||
<!ENTITY % mac-entities SYSTEM "mac.ent"> %mac-entities;
|
||||
<!ENTITY % authors PUBLIC "-//FreeBSD//ENTITIES DocBook Author Entities//EN"> %authors
|
||||
|
@ -135,13 +137,7 @@
|
|||
&chap.pci;
|
||||
&chap.scsi;
|
||||
&chap.usb;
|
||||
|
||||
<chapter id="newbus">
|
||||
<title>* NewBus</title>
|
||||
|
||||
<para>This chapter will talk about the FreeBSD NewBus
|
||||
architecture.</para>
|
||||
</chapter>
|
||||
&chap.newbus;
|
||||
|
||||
&chap.snd;
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
<!ENTITY chap.pci SYSTEM "pci/chapter.sgml">
|
||||
<!ENTITY chap.scsi SYSTEM "scsi/chapter.sgml">
|
||||
<!ENTITY chap.usb SYSTEM "usb/chapter.sgml">
|
||||
<!ENTITY chap.newbus SYSTEM "newbus/chapter.sgml">
|
||||
<!ENTITY chap.snd SYSTEM "sound/chapter.sgml">
|
||||
|
||||
<!-- Part five - Architectures -->
|
||||
|
|
363
en_US.ISO8859-1/books/arch-handbook/newbus/chapter.sgml
Normal file
363
en_US.ISO8859-1/books/arch-handbook/newbus/chapter.sgml
Normal file
|
@ -0,0 +1,363 @@
|
|||
<!--
|
||||
The FreeBSD Documentation Project
|
||||
$FreeBSD$
|
||||
|
||||
Originally by: Jeroen Ruigrok van der Warven
|
||||
Date: newbus-draft.txt,v 1.8 2001/01/25 08:01:08
|
||||
Copyright (c) 2000 Jeroen Ruigrok van der Warven (asmodai@wxs.nl)
|
||||
Copyright (c) 2002 Hiten Mahesh Pandya (hiten@uk.FreeBSD.org)
|
||||
|
||||
Future Additions:
|
||||
|
||||
o Expand the information about device_t, and explain each and
|
||||
every field in it.
|
||||
o Add information about the bus_* functions.
|
||||
o Add information about bus specific (e.g. PCI) functions.
|
||||
o Add a reference section for additional information.
|
||||
o Add more newbus related structures and typedefs.
|
||||
o Add a 'Terminology' section.
|
||||
o Add information on resource manager functions, busspace
|
||||
manager functions, newbus events related functions.
|
||||
o More cleanup ... !
|
||||
|
||||
Provided under the FreeBSD Documentation License.
|
||||
-->
|
||||
<chapter id="newbus">
|
||||
<chapterinfo>
|
||||
<authorgroup>
|
||||
<author>
|
||||
<firstname>Jeroen</firstname>
|
||||
<surname>Ruigrok van der Werven</surname>
|
||||
<affiliation><address><email>asmodai@FreeBSD.org</email></address>
|
||||
</affiliation>
|
||||
<contrib>Written by </contrib>
|
||||
</author>
|
||||
</authorgroup>
|
||||
<authorgroup>
|
||||
<author>
|
||||
<firstname>Hiten</firstname>
|
||||
<surname>Pandya</surname>
|
||||
<affiliation><address><email>hiten@uk.FreeBSD.org</email></address>
|
||||
</affiliation>
|
||||
</author>
|
||||
</authorgroup>
|
||||
</chapterinfo>
|
||||
<title>Newbus</title>
|
||||
|
||||
<para><emphasis>Special thanks to Mathew N. Dodd, Warner Losh, Bill Paul.
|
||||
Daug Rabson, Mike Smith, Peter Wemm and Scott Long.</emphasis></para>
|
||||
|
||||
<para>This chapter explains the Newbus device framework in detail.</para>
|
||||
<sect1 id="devdrivers">
|
||||
<title>Device Drivers</title>
|
||||
<sect2>
|
||||
<title>Purpose of a Device Driver</title>
|
||||
<para>A device driver is a software component which provides the
|
||||
interface between the kernel's generic view of a peripheral
|
||||
(e.g. disk, network adapter) and the actual implementation of the
|
||||
peripheral. The <emphasis>device driver interface (DDI)</emphasis> is
|
||||
the defined interface between the kernel and the device driver component.
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
<sect2>
|
||||
<title>Types of Device Drivers</title>
|
||||
<para>There used to be days in &unix;, and thus FreeBSD, in which there
|
||||
were four types of devices defined:</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem><para>block device drivers</para></listitem>
|
||||
<listitem><para>character device drivers</para></listitem>
|
||||
<listitem><para>network device drivers</para></listitem>
|
||||
<listitem><para>pseudo-device drivers</para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para><emphasis>Block devices</emphasis> performed in way that used
|
||||
fixed size blocks [of data]. This type of driver depended on the
|
||||
so called <emphasis>buffer cache</emphasis>, which had the purpose
|
||||
to cache accessed blocks of data in a dedicated part of the memory.
|
||||
Often this buffer cache was based on write-behind, which meant that when
|
||||
data was modified in memory it got synced to disk whenever the system
|
||||
did its periodical disk flushing, thus optimizing writes.</para>
|
||||
</sect2>
|
||||
|
||||
<sect2>
|
||||
<title>Character devices</title>
|
||||
<para>However, in the versions of FreeBSD 4.0 and onward the
|
||||
distinction between block and character devices became non-existent.
|
||||
</para>
|
||||
</sect2>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="newbus-overview">
|
||||
<!--
|
||||
Real title:
|
||||
Newbus, Busspace and the Resource Manager, an Explanation of the Possibilities
|
||||
-->
|
||||
<title>Overview of Newbus</title>
|
||||
<para><emphasis>Newbus</emphasis> is the implementation of a new bus
|
||||
architecture based on abstraction layers which saw its introduction in
|
||||
FreeBSD 3.0 when the Alpha port was imported into the source tree. It was
|
||||
not until 4.0 before it became the default system to use for device
|
||||
drivers. Its goals are to provide a more object oriented means of
|
||||
interconnecting the various busses and devices which a host system
|
||||
provides to the <emphasis>Operating System</emphasis>.</para>
|
||||
|
||||
<para>Its main features include amongst others:</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem><para>dynamic attaching</para></listitem>
|
||||
<listitem><para>easy modularization of drivers</para></listitem>
|
||||
<listitem><para>pseudo-busses</para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>One of the most prominent changes is the migration from the flat and
|
||||
ad-hoc system to a device tree lay-out.</para>
|
||||
|
||||
<para>At the top level resides the <emphasis><quote>root</quote></emphasis>
|
||||
device which is the parent to hang all other devices on. For each
|
||||
architecture, there is typically a single child of <quote>root</quote>
|
||||
which has such things as <emphasis>host-to-PCI bridges</emphasis>, etc.
|
||||
attached to it. For x86, this <quote>root</quote> device is the
|
||||
<emphasis><quote>nexus</quote></emphasis> device and for Alpha, various
|
||||
different different models of Alpha have different top-level devices
|
||||
corresponding to the different hardware chipsets, including
|
||||
<emphasis>lca</emphasis>, <emphasis>apecs</emphasis>,
|
||||
<emphasis>cia</emphasis> and <emphasis>tsunami</emphasis>.</para>
|
||||
|
||||
<para>A device in the Newbus context represents a single hardware entity
|
||||
in the system. For instance each PCI device is represented by a Newbus
|
||||
device. Any device in the system can have children; a device which has
|
||||
children is often called a <emphasis><quote>bus</quote></emphasis>.
|
||||
Examples of common busses in the system are ISA and PCI which manage lists
|
||||
of devices attached to ISA and PCI busses respectively.</para>
|
||||
|
||||
<para>Often, a connection between different kinds of bus is represented by
|
||||
a <emphasis><quote>bridge</quote></emphasis> device which normally has one
|
||||
child for the attached bus. An example of this is a
|
||||
<emphasis>PCI-to-PCI bridge</emphasis> which is represented by a device
|
||||
<emphasis><devicename>pcibN</devicename></emphasis> on the parent PCI bus
|
||||
and has a child <emphasis><devicename>pciN</devicename></emphasis> for the
|
||||
attached bus. This layout simplifies the implementation of the PCI bus
|
||||
tree, allowing common code to be used for both top-level and bridged
|
||||
busses.</para>
|
||||
|
||||
<para>Each device in the Newbus architecture asks its parent to map its
|
||||
resources. The parent then asks its own parent until the nexus is
|
||||
reached. So, basically the nexus is the only part of the Newbus system
|
||||
which knows about all resources.</para>
|
||||
|
||||
<tip><para>An ISA device might want to map its IO port at
|
||||
<literal>0x23c</literal>, so it asks its parent, in this case the ISA
|
||||
bus. The ISA bus hands it over to the PCI-to-ISA bridge which in its turn
|
||||
asks the PCI bus, which reaches the host-to-PCI bridge and finally the
|
||||
nexus. The beauty of this transition upwards is that there is room to
|
||||
translate the requests. For example, the <literal>0x23c</literal> IO port
|
||||
request might become memory-mapped at <literal>0xb000023c</literal> on a
|
||||
<acronym>MIPS</acronym> box by the PCI bridge.</para></tip>
|
||||
|
||||
<para>Resource allocation can be controlled at any place in the device
|
||||
tree. For instance on many Alpha platforms, ISA interrupts are managed
|
||||
separately from PCI interrupts and resource allocations for ISA interrupts
|
||||
are managed by the Alpha's ISA bus device. On IA-32, ISA and PCI
|
||||
interrupts are both managed by the top-level nexus device. For both
|
||||
ports, memory and port address space is managed by a single entity - nexus
|
||||
for IA-32 and the relevant chipset driver on Alpha (e.g. CIA or tsunami).
|
||||
</para>
|
||||
|
||||
<para>In order to normalize access to memory and port mapped resources,
|
||||
Newbus integrates the <literal>bus_space</literal> APIs from NetBSD.
|
||||
These provide a single API to replace inb/outb and direct memory
|
||||
reads/writes. The advantage of this is that a single driver can easily
|
||||
use either memory-mapped registers or port-mapped registers
|
||||
(some hardware supports both).</para>
|
||||
|
||||
<para>This support is integrated into the resource allocation mechanism.
|
||||
When a resource is allocated, a driver can retrieve the associated
|
||||
<structfield>bus_space_tag_t</structfield> and
|
||||
<structfield>bus_space_handle_t</structfield> from the resource.</para>
|
||||
|
||||
<para>Newbus also allows for definitions of interface methods in files
|
||||
dedicated to this purpose. These are the <filename>.m</filename> files
|
||||
that are found under the <filename>src/sys</filename> hierarchy.</para>
|
||||
|
||||
<para>The core of the Newbus system is an extensible
|
||||
<quote>object-based programming</quote> model. Each device in the system
|
||||
has a table of methods which it supports. The system and other devices
|
||||
uses those methods to control the device and request services. The
|
||||
different methods supported by a device are defined by a number of
|
||||
<quote>interfaces</quote>. An <quote>interface</quote> is simply a group
|
||||
of related methods which can be implemented by a device.</para>
|
||||
|
||||
<para>In the Newbus system, the methods for a device are provided by the
|
||||
various device drivers in the system. When a device is attached to a
|
||||
driver during <emphasis>auto-configuration</emphasis>, it uses the method
|
||||
table declared by the driver. A device can later
|
||||
<emphasis>detach</emphasis> from its driver and
|
||||
<emphasis>re-attach</emphasis> to a new driver with a new method table.
|
||||
This allows dynamic replacement of drivers which can be useful for driver
|
||||
development.</para>
|
||||
|
||||
<para>The interfaces are described by an interface definition language
|
||||
similar to the language used to define vnode operations for file systems.
|
||||
The interface would be stored in a methods file (which would normally named
|
||||
<filename>foo_if.m</filename>).</para>
|
||||
|
||||
<example>
|
||||
<title>Newbus Methods</title>
|
||||
<programlisting>
|
||||
# Foo subsystem/driver (a comment...)
|
||||
|
||||
INTERFACE foo
|
||||
|
||||
METHOD int doit {
|
||||
device_t dev;
|
||||
};
|
||||
|
||||
# DEFAULT is the method that will be used, if a method was not
|
||||
# provided via: DEVMETHOD()
|
||||
|
||||
METHOD void doit_to_child {
|
||||
device_t dev;
|
||||
driver_t child;
|
||||
} DEFAULT doit_generic_to_child;
|
||||
</programlisting>
|
||||
</example>
|
||||
|
||||
<para>When this interface is compiled, it generates a header file
|
||||
<quote><filename>foo_if.h</filename></quote> which contains function
|
||||
declarations:</para>
|
||||
|
||||
<programlisting>
|
||||
int FOO_DOIT(device_t dev);
|
||||
int FOO_DOIT_TO_CHILD(device_t dev, device_t child);
|
||||
</programlisting>
|
||||
|
||||
<para>A source file, <quote><filename>foo_if.c</filename></quote> is
|
||||
also created to accompany the automatically generated header file; it
|
||||
contains implementations of those functions which look up the location
|
||||
of the relevant functions in the object's method table and call that
|
||||
function.</para>
|
||||
|
||||
<para>The system defines two main interfaces. The first fundamental
|
||||
interface is called <emphasis><quote>device</quote></emphasis> and
|
||||
includes methods which are relevant to all devices. Methods in the
|
||||
<emphasis><quote>device</quote></emphasis> interface include
|
||||
<emphasis><quote>probe</quote></emphasis>,
|
||||
<emphasis><quote>attach</quote></emphasis> and
|
||||
<emphasis><quote>detach</quote></emphasis> to control detection of
|
||||
hardware and <emphasis><quote>shutdown</quote></emphasis>,
|
||||
<emphasis><quote>suspend</quote></emphasis> and
|
||||
<emphasis><quote>resume</quote></emphasis> for critical event
|
||||
notification.</para>
|
||||
|
||||
<para>The second, more complex interface is
|
||||
<emphasis><quote>bus</quote></emphasis>. This interface contains
|
||||
methods suitable for devices which have children, including methods to
|
||||
access bus specific per-device information
|
||||
<footnote><para>&man.bus.generic.read.ivar.9; and
|
||||
&man.bus.generic.write.ivar.9;</para></footnote>, event notification
|
||||
(<emphasis><literal>child_detached</literal></emphasis>,
|
||||
<emphasis><literal>driver_added</literal></emphasis>) and resource
|
||||
management (<emphasis><literal>alloc_resource</literal></emphasis>,
|
||||
<emphasis><literal>activate_resource</literal></emphasis>,
|
||||
<emphasis><literal>deactivate_resource</literal></emphasis>,
|
||||
<emphasis><literal>release_resource</literal></emphasis>).
|
||||
|
||||
<para>Many methods in the <quote>bus</quote> interface are performing
|
||||
services for some child of the bus device. These methods would normally
|
||||
use the first two arguments to specify the bus providing the service
|
||||
and the child device which is requesting the service. To simplify
|
||||
driver code, many of these methods have accessor functions which
|
||||
lookup the parent and call a method on the parent. For instance the
|
||||
method
|
||||
<literal>BUS_TEARDOWN_INTR(device_t dev, device_t child, ...)</literal>
|
||||
can be called using the function
|
||||
<literal>bus_teardown_intr(device_t child, ...)</literal>.</para>
|
||||
|
||||
<para>Some bus types in the system define additional interfaces to
|
||||
provide access to bus-specific functionality. For instance, the PCI
|
||||
bus driver defines the <quote>pci</quote> interface which has two
|
||||
methods <emphasis><literal>read_config</literal></emphasis> and
|
||||
<emphasis><literal>write_config</literal></emphasis> for accessing the
|
||||
configuration registers of a PCI device.</para>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="newbus-api">
|
||||
<title>Newbus API</title>
|
||||
<para>As the Newbus API is huge, this section makes some effort at
|
||||
documenting it. More information to come in the next revision of this
|
||||
document.</para>
|
||||
|
||||
<sect2>
|
||||
<title>Important locations in the source hierarchy</title>
|
||||
|
||||
<para><filename>src/sys/[arch]/[arch]</filename> - Kernel code for a
|
||||
specific machine architecture resides in this directory. for example,
|
||||
the <literal>i386</literal> architecture, or the
|
||||
<literal>SPARC64</literal> architecture.</para>
|
||||
|
||||
<para><filename>src/sys/dev/[bus]</filename> - device support for a
|
||||
specific <literal>[bus]</literal> resides in this directory.</para>
|
||||
|
||||
<para><filename>src/sys/dev/pci</filename> - PCI bus support code
|
||||
resides in this directory.</para>
|
||||
|
||||
<para><filename>src/sys/[isa|pci]</filename> - PCI/ISA device drivers
|
||||
reside in this directory. The PCI/ISA bus support code used to exist
|
||||
in this directory in FreeBSD version <literal>4.0</literal>.</para>
|
||||
</sect2>
|
||||
|
||||
<sect2>
|
||||
<title>Important structures and type definitions</title>
|
||||
<para><literal>devclass_t</literal> - This is a type definition of a
|
||||
pointer to a <literal>struct devclass</literal>.</para>
|
||||
|
||||
<para><literal>device_method_t</literal> - This is same as
|
||||
<literal>kobj_method_t</literal> (see
|
||||
<filename>src/sys/kobj.h</filename>).</para>
|
||||
|
||||
<para><literal>device_t</literal> - This is a type definition of a
|
||||
pointer to a <literal>struct device</literal>.
|
||||
<literal>device_t</literal> represents a device in the system. It is
|
||||
a kernel object. See <filename>src/sys/sys/bus_private.h</filename>
|
||||
for implementation details.</para>
|
||||
|
||||
<para><literal>driver_t</literal> - This is a type definition which,
|
||||
references <literal>struct driver</literal>. The
|
||||
<literal>driver</literal> struct is a class of the
|
||||
<literal>device</literal> kernel object; it also holds data private
|
||||
to for the driver.</para>
|
||||
|
||||
<figure>
|
||||
<title><emphasis>driver_t</emphasis> implementation</title>
|
||||
<programlisting>
|
||||
struct driver {
|
||||
KOBJ_CLASS_FIELDS;
|
||||
void *priv; /* driver private data */
|
||||
};
|
||||
</programlisting>
|
||||
</figure>
|
||||
|
||||
<para>A <literal>device_state_t</literal> type, which is
|
||||
an enumeration, <literal>device_state</literal>. It contains
|
||||
the possible states of a Newbus device before and after the
|
||||
autoconfiguration process.</para>
|
||||
|
||||
<figure>
|
||||
<title>Device states<emphasis>device_state_t</emphasis></title>
|
||||
<programlisting>
|
||||
/*
|
||||
* src/sys/sys/bus.h
|
||||
*/
|
||||
typedef enum device_state {
|
||||
DS_NOTPRESENT, /* not probed or probe failed */
|
||||
DS_ALIVE, /* probe succeeded */
|
||||
DS_ATTACHED, /* attach method called */
|
||||
DS_BUSY /* device is open */
|
||||
} device_state_t;
|
||||
</programlisting>
|
||||
</figure>
|
||||
</sect2>
|
||||
</sect1>
|
||||
</chapter>
|
|
@ -9,6 +9,8 @@
|
|||
%bookinfo;
|
||||
<!ENTITY % man PUBLIC "-//FreeBSD//ENTITIES DocBook Manual Page Entities//EN">
|
||||
%man;
|
||||
<!ENTITY % freebsd PUBLIC "-//FreeBSD//ENTITIES DocBook Miscellaneous FreeBSD Entities//EN">
|
||||
%freebsd;
|
||||
<!ENTITY % chapters SYSTEM "chapters.ent"> %chapters;
|
||||
<!ENTITY % mac-entities SYSTEM "mac.ent"> %mac-entities;
|
||||
<!ENTITY % authors PUBLIC "-//FreeBSD//ENTITIES DocBook Author Entities//EN"> %authors
|
||||
|
@ -135,13 +137,7 @@
|
|||
&chap.pci;
|
||||
&chap.scsi;
|
||||
&chap.usb;
|
||||
|
||||
<chapter id="newbus">
|
||||
<title>* NewBus</title>
|
||||
|
||||
<para>This chapter will talk about the FreeBSD NewBus
|
||||
architecture.</para>
|
||||
</chapter>
|
||||
&chap.newbus;
|
||||
|
||||
&chap.snd;
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
<!ENTITY chap.pci SYSTEM "pci/chapter.sgml">
|
||||
<!ENTITY chap.scsi SYSTEM "scsi/chapter.sgml">
|
||||
<!ENTITY chap.usb SYSTEM "usb/chapter.sgml">
|
||||
<!ENTITY chap.newbus SYSTEM "newbus/chapter.sgml">
|
||||
<!ENTITY chap.snd SYSTEM "sound/chapter.sgml">
|
||||
|
||||
<!-- Part five - Architectures -->
|
||||
|
|
363
en_US.ISO8859-1/books/developers-handbook/newbus/chapter.sgml
Normal file
363
en_US.ISO8859-1/books/developers-handbook/newbus/chapter.sgml
Normal file
|
@ -0,0 +1,363 @@
|
|||
<!--
|
||||
The FreeBSD Documentation Project
|
||||
$FreeBSD$
|
||||
|
||||
Originally by: Jeroen Ruigrok van der Warven
|
||||
Date: newbus-draft.txt,v 1.8 2001/01/25 08:01:08
|
||||
Copyright (c) 2000 Jeroen Ruigrok van der Warven (asmodai@wxs.nl)
|
||||
Copyright (c) 2002 Hiten Mahesh Pandya (hiten@uk.FreeBSD.org)
|
||||
|
||||
Future Additions:
|
||||
|
||||
o Expand the information about device_t, and explain each and
|
||||
every field in it.
|
||||
o Add information about the bus_* functions.
|
||||
o Add information about bus specific (e.g. PCI) functions.
|
||||
o Add a reference section for additional information.
|
||||
o Add more newbus related structures and typedefs.
|
||||
o Add a 'Terminology' section.
|
||||
o Add information on resource manager functions, busspace
|
||||
manager functions, newbus events related functions.
|
||||
o More cleanup ... !
|
||||
|
||||
Provided under the FreeBSD Documentation License.
|
||||
-->
|
||||
<chapter id="newbus">
|
||||
<chapterinfo>
|
||||
<authorgroup>
|
||||
<author>
|
||||
<firstname>Jeroen</firstname>
|
||||
<surname>Ruigrok van der Werven</surname>
|
||||
<affiliation><address><email>asmodai@FreeBSD.org</email></address>
|
||||
</affiliation>
|
||||
<contrib>Written by </contrib>
|
||||
</author>
|
||||
</authorgroup>
|
||||
<authorgroup>
|
||||
<author>
|
||||
<firstname>Hiten</firstname>
|
||||
<surname>Pandya</surname>
|
||||
<affiliation><address><email>hiten@uk.FreeBSD.org</email></address>
|
||||
</affiliation>
|
||||
</author>
|
||||
</authorgroup>
|
||||
</chapterinfo>
|
||||
<title>Newbus</title>
|
||||
|
||||
<para><emphasis>Special thanks to Mathew N. Dodd, Warner Losh, Bill Paul.
|
||||
Daug Rabson, Mike Smith, Peter Wemm and Scott Long.</emphasis></para>
|
||||
|
||||
<para>This chapter explains the Newbus device framework in detail.</para>
|
||||
<sect1 id="devdrivers">
|
||||
<title>Device Drivers</title>
|
||||
<sect2>
|
||||
<title>Purpose of a Device Driver</title>
|
||||
<para>A device driver is a software component which provides the
|
||||
interface between the kernel's generic view of a peripheral
|
||||
(e.g. disk, network adapter) and the actual implementation of the
|
||||
peripheral. The <emphasis>device driver interface (DDI)</emphasis> is
|
||||
the defined interface between the kernel and the device driver component.
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
<sect2>
|
||||
<title>Types of Device Drivers</title>
|
||||
<para>There used to be days in &unix;, and thus FreeBSD, in which there
|
||||
were four types of devices defined:</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem><para>block device drivers</para></listitem>
|
||||
<listitem><para>character device drivers</para></listitem>
|
||||
<listitem><para>network device drivers</para></listitem>
|
||||
<listitem><para>pseudo-device drivers</para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para><emphasis>Block devices</emphasis> performed in way that used
|
||||
fixed size blocks [of data]. This type of driver depended on the
|
||||
so called <emphasis>buffer cache</emphasis>, which had the purpose
|
||||
to cache accessed blocks of data in a dedicated part of the memory.
|
||||
Often this buffer cache was based on write-behind, which meant that when
|
||||
data was modified in memory it got synced to disk whenever the system
|
||||
did its periodical disk flushing, thus optimizing writes.</para>
|
||||
</sect2>
|
||||
|
||||
<sect2>
|
||||
<title>Character devices</title>
|
||||
<para>However, in the versions of FreeBSD 4.0 and onward the
|
||||
distinction between block and character devices became non-existent.
|
||||
</para>
|
||||
</sect2>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="newbus-overview">
|
||||
<!--
|
||||
Real title:
|
||||
Newbus, Busspace and the Resource Manager, an Explanation of the Possibilities
|
||||
-->
|
||||
<title>Overview of Newbus</title>
|
||||
<para><emphasis>Newbus</emphasis> is the implementation of a new bus
|
||||
architecture based on abstraction layers which saw its introduction in
|
||||
FreeBSD 3.0 when the Alpha port was imported into the source tree. It was
|
||||
not until 4.0 before it became the default system to use for device
|
||||
drivers. Its goals are to provide a more object oriented means of
|
||||
interconnecting the various busses and devices which a host system
|
||||
provides to the <emphasis>Operating System</emphasis>.</para>
|
||||
|
||||
<para>Its main features include amongst others:</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem><para>dynamic attaching</para></listitem>
|
||||
<listitem><para>easy modularization of drivers</para></listitem>
|
||||
<listitem><para>pseudo-busses</para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>One of the most prominent changes is the migration from the flat and
|
||||
ad-hoc system to a device tree lay-out.</para>
|
||||
|
||||
<para>At the top level resides the <emphasis><quote>root</quote></emphasis>
|
||||
device which is the parent to hang all other devices on. For each
|
||||
architecture, there is typically a single child of <quote>root</quote>
|
||||
which has such things as <emphasis>host-to-PCI bridges</emphasis>, etc.
|
||||
attached to it. For x86, this <quote>root</quote> device is the
|
||||
<emphasis><quote>nexus</quote></emphasis> device and for Alpha, various
|
||||
different different models of Alpha have different top-level devices
|
||||
corresponding to the different hardware chipsets, including
|
||||
<emphasis>lca</emphasis>, <emphasis>apecs</emphasis>,
|
||||
<emphasis>cia</emphasis> and <emphasis>tsunami</emphasis>.</para>
|
||||
|
||||
<para>A device in the Newbus context represents a single hardware entity
|
||||
in the system. For instance each PCI device is represented by a Newbus
|
||||
device. Any device in the system can have children; a device which has
|
||||
children is often called a <emphasis><quote>bus</quote></emphasis>.
|
||||
Examples of common busses in the system are ISA and PCI which manage lists
|
||||
of devices attached to ISA and PCI busses respectively.</para>
|
||||
|
||||
<para>Often, a connection between different kinds of bus is represented by
|
||||
a <emphasis><quote>bridge</quote></emphasis> device which normally has one
|
||||
child for the attached bus. An example of this is a
|
||||
<emphasis>PCI-to-PCI bridge</emphasis> which is represented by a device
|
||||
<emphasis><devicename>pcibN</devicename></emphasis> on the parent PCI bus
|
||||
and has a child <emphasis><devicename>pciN</devicename></emphasis> for the
|
||||
attached bus. This layout simplifies the implementation of the PCI bus
|
||||
tree, allowing common code to be used for both top-level and bridged
|
||||
busses.</para>
|
||||
|
||||
<para>Each device in the Newbus architecture asks its parent to map its
|
||||
resources. The parent then asks its own parent until the nexus is
|
||||
reached. So, basically the nexus is the only part of the Newbus system
|
||||
which knows about all resources.</para>
|
||||
|
||||
<tip><para>An ISA device might want to map its IO port at
|
||||
<literal>0x23c</literal>, so it asks its parent, in this case the ISA
|
||||
bus. The ISA bus hands it over to the PCI-to-ISA bridge which in its turn
|
||||
asks the PCI bus, which reaches the host-to-PCI bridge and finally the
|
||||
nexus. The beauty of this transition upwards is that there is room to
|
||||
translate the requests. For example, the <literal>0x23c</literal> IO port
|
||||
request might become memory-mapped at <literal>0xb000023c</literal> on a
|
||||
<acronym>MIPS</acronym> box by the PCI bridge.</para></tip>
|
||||
|
||||
<para>Resource allocation can be controlled at any place in the device
|
||||
tree. For instance on many Alpha platforms, ISA interrupts are managed
|
||||
separately from PCI interrupts and resource allocations for ISA interrupts
|
||||
are managed by the Alpha's ISA bus device. On IA-32, ISA and PCI
|
||||
interrupts are both managed by the top-level nexus device. For both
|
||||
ports, memory and port address space is managed by a single entity - nexus
|
||||
for IA-32 and the relevant chipset driver on Alpha (e.g. CIA or tsunami).
|
||||
</para>
|
||||
|
||||
<para>In order to normalize access to memory and port mapped resources,
|
||||
Newbus integrates the <literal>bus_space</literal> APIs from NetBSD.
|
||||
These provide a single API to replace inb/outb and direct memory
|
||||
reads/writes. The advantage of this is that a single driver can easily
|
||||
use either memory-mapped registers or port-mapped registers
|
||||
(some hardware supports both).</para>
|
||||
|
||||
<para>This support is integrated into the resource allocation mechanism.
|
||||
When a resource is allocated, a driver can retrieve the associated
|
||||
<structfield>bus_space_tag_t</structfield> and
|
||||
<structfield>bus_space_handle_t</structfield> from the resource.</para>
|
||||
|
||||
<para>Newbus also allows for definitions of interface methods in files
|
||||
dedicated to this purpose. These are the <filename>.m</filename> files
|
||||
that are found under the <filename>src/sys</filename> hierarchy.</para>
|
||||
|
||||
<para>The core of the Newbus system is an extensible
|
||||
<quote>object-based programming</quote> model. Each device in the system
|
||||
has a table of methods which it supports. The system and other devices
|
||||
uses those methods to control the device and request services. The
|
||||
different methods supported by a device are defined by a number of
|
||||
<quote>interfaces</quote>. An <quote>interface</quote> is simply a group
|
||||
of related methods which can be implemented by a device.</para>
|
||||
|
||||
<para>In the Newbus system, the methods for a device are provided by the
|
||||
various device drivers in the system. When a device is attached to a
|
||||
driver during <emphasis>auto-configuration</emphasis>, it uses the method
|
||||
table declared by the driver. A device can later
|
||||
<emphasis>detach</emphasis> from its driver and
|
||||
<emphasis>re-attach</emphasis> to a new driver with a new method table.
|
||||
This allows dynamic replacement of drivers which can be useful for driver
|
||||
development.</para>
|
||||
|
||||
<para>The interfaces are described by an interface definition language
|
||||
similar to the language used to define vnode operations for file systems.
|
||||
The interface would be stored in a methods file (which would normally named
|
||||
<filename>foo_if.m</filename>).</para>
|
||||
|
||||
<example>
|
||||
<title>Newbus Methods</title>
|
||||
<programlisting>
|
||||
# Foo subsystem/driver (a comment...)
|
||||
|
||||
INTERFACE foo
|
||||
|
||||
METHOD int doit {
|
||||
device_t dev;
|
||||
};
|
||||
|
||||
# DEFAULT is the method that will be used, if a method was not
|
||||
# provided via: DEVMETHOD()
|
||||
|
||||
METHOD void doit_to_child {
|
||||
device_t dev;
|
||||
driver_t child;
|
||||
} DEFAULT doit_generic_to_child;
|
||||
</programlisting>
|
||||
</example>
|
||||
|
||||
<para>When this interface is compiled, it generates a header file
|
||||
<quote><filename>foo_if.h</filename></quote> which contains function
|
||||
declarations:</para>
|
||||
|
||||
<programlisting>
|
||||
int FOO_DOIT(device_t dev);
|
||||
int FOO_DOIT_TO_CHILD(device_t dev, device_t child);
|
||||
</programlisting>
|
||||
|
||||
<para>A source file, <quote><filename>foo_if.c</filename></quote> is
|
||||
also created to accompany the automatically generated header file; it
|
||||
contains implementations of those functions which look up the location
|
||||
of the relevant functions in the object's method table and call that
|
||||
function.</para>
|
||||
|
||||
<para>The system defines two main interfaces. The first fundamental
|
||||
interface is called <emphasis><quote>device</quote></emphasis> and
|
||||
includes methods which are relevant to all devices. Methods in the
|
||||
<emphasis><quote>device</quote></emphasis> interface include
|
||||
<emphasis><quote>probe</quote></emphasis>,
|
||||
<emphasis><quote>attach</quote></emphasis> and
|
||||
<emphasis><quote>detach</quote></emphasis> to control detection of
|
||||
hardware and <emphasis><quote>shutdown</quote></emphasis>,
|
||||
<emphasis><quote>suspend</quote></emphasis> and
|
||||
<emphasis><quote>resume</quote></emphasis> for critical event
|
||||
notification.</para>
|
||||
|
||||
<para>The second, more complex interface is
|
||||
<emphasis><quote>bus</quote></emphasis>. This interface contains
|
||||
methods suitable for devices which have children, including methods to
|
||||
access bus specific per-device information
|
||||
<footnote><para>&man.bus.generic.read.ivar.9; and
|
||||
&man.bus.generic.write.ivar.9;</para></footnote>, event notification
|
||||
(<emphasis><literal>child_detached</literal></emphasis>,
|
||||
<emphasis><literal>driver_added</literal></emphasis>) and resource
|
||||
management (<emphasis><literal>alloc_resource</literal></emphasis>,
|
||||
<emphasis><literal>activate_resource</literal></emphasis>,
|
||||
<emphasis><literal>deactivate_resource</literal></emphasis>,
|
||||
<emphasis><literal>release_resource</literal></emphasis>).
|
||||
|
||||
<para>Many methods in the <quote>bus</quote> interface are performing
|
||||
services for some child of the bus device. These methods would normally
|
||||
use the first two arguments to specify the bus providing the service
|
||||
and the child device which is requesting the service. To simplify
|
||||
driver code, many of these methods have accessor functions which
|
||||
lookup the parent and call a method on the parent. For instance the
|
||||
method
|
||||
<literal>BUS_TEARDOWN_INTR(device_t dev, device_t child, ...)</literal>
|
||||
can be called using the function
|
||||
<literal>bus_teardown_intr(device_t child, ...)</literal>.</para>
|
||||
|
||||
<para>Some bus types in the system define additional interfaces to
|
||||
provide access to bus-specific functionality. For instance, the PCI
|
||||
bus driver defines the <quote>pci</quote> interface which has two
|
||||
methods <emphasis><literal>read_config</literal></emphasis> and
|
||||
<emphasis><literal>write_config</literal></emphasis> for accessing the
|
||||
configuration registers of a PCI device.</para>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="newbus-api">
|
||||
<title>Newbus API</title>
|
||||
<para>As the Newbus API is huge, this section makes some effort at
|
||||
documenting it. More information to come in the next revision of this
|
||||
document.</para>
|
||||
|
||||
<sect2>
|
||||
<title>Important locations in the source hierarchy</title>
|
||||
|
||||
<para><filename>src/sys/[arch]/[arch]</filename> - Kernel code for a
|
||||
specific machine architecture resides in this directory. for example,
|
||||
the <literal>i386</literal> architecture, or the
|
||||
<literal>SPARC64</literal> architecture.</para>
|
||||
|
||||
<para><filename>src/sys/dev/[bus]</filename> - device support for a
|
||||
specific <literal>[bus]</literal> resides in this directory.</para>
|
||||
|
||||
<para><filename>src/sys/dev/pci</filename> - PCI bus support code
|
||||
resides in this directory.</para>
|
||||
|
||||
<para><filename>src/sys/[isa|pci]</filename> - PCI/ISA device drivers
|
||||
reside in this directory. The PCI/ISA bus support code used to exist
|
||||
in this directory in FreeBSD version <literal>4.0</literal>.</para>
|
||||
</sect2>
|
||||
|
||||
<sect2>
|
||||
<title>Important structures and type definitions</title>
|
||||
<para><literal>devclass_t</literal> - This is a type definition of a
|
||||
pointer to a <literal>struct devclass</literal>.</para>
|
||||
|
||||
<para><literal>device_method_t</literal> - This is same as
|
||||
<literal>kobj_method_t</literal> (see
|
||||
<filename>src/sys/kobj.h</filename>).</para>
|
||||
|
||||
<para><literal>device_t</literal> - This is a type definition of a
|
||||
pointer to a <literal>struct device</literal>.
|
||||
<literal>device_t</literal> represents a device in the system. It is
|
||||
a kernel object. See <filename>src/sys/sys/bus_private.h</filename>
|
||||
for implementation details.</para>
|
||||
|
||||
<para><literal>driver_t</literal> - This is a type definition which,
|
||||
references <literal>struct driver</literal>. The
|
||||
<literal>driver</literal> struct is a class of the
|
||||
<literal>device</literal> kernel object; it also holds data private
|
||||
to for the driver.</para>
|
||||
|
||||
<figure>
|
||||
<title><emphasis>driver_t</emphasis> implementation</title>
|
||||
<programlisting>
|
||||
struct driver {
|
||||
KOBJ_CLASS_FIELDS;
|
||||
void *priv; /* driver private data */
|
||||
};
|
||||
</programlisting>
|
||||
</figure>
|
||||
|
||||
<para>A <literal>device_state_t</literal> type, which is
|
||||
an enumeration, <literal>device_state</literal>. It contains
|
||||
the possible states of a Newbus device before and after the
|
||||
autoconfiguration process.</para>
|
||||
|
||||
<figure>
|
||||
<title>Device states<emphasis>device_state_t</emphasis></title>
|
||||
<programlisting>
|
||||
/*
|
||||
* src/sys/sys/bus.h
|
||||
*/
|
||||
typedef enum device_state {
|
||||
DS_NOTPRESENT, /* not probed or probe failed */
|
||||
DS_ALIVE, /* probe succeeded */
|
||||
DS_ATTACHED, /* attach method called */
|
||||
DS_BUSY /* device is open */
|
||||
} device_state_t;
|
||||
</programlisting>
|
||||
</figure>
|
||||
</sect2>
|
||||
</sect1>
|
||||
</chapter>
|
363
en_US.ISO8859-1/books/developers-handbook/newbus/newbus.sgml
Normal file
363
en_US.ISO8859-1/books/developers-handbook/newbus/newbus.sgml
Normal file
|
@ -0,0 +1,363 @@
|
|||
<!--
|
||||
The FreeBSD Documentation Project
|
||||
$FreeBSD$
|
||||
|
||||
Originally by: Jeroen Ruigrok van der Warven
|
||||
Date: newbus-draft.txt,v 1.8 2001/01/25 08:01:08
|
||||
Copyright (c) 2000 Jeroen Ruigrok van der Warven (asmodai@wxs.nl)
|
||||
Copyright (c) 2002 Hiten Mahesh Pandya (hiten@uk.FreeBSD.org)
|
||||
|
||||
Future Additions:
|
||||
|
||||
o Expand the information about device_t, and explain each and
|
||||
every field in it.
|
||||
o Add information about the bus_* functions.
|
||||
o Add information about bus specific (e.g. PCI) functions.
|
||||
o Add a reference section for additional information.
|
||||
o Add more newbus related structures and typedefs.
|
||||
o Add a 'Terminology' section.
|
||||
o Add information on resource manager functions, busspace
|
||||
manager functions, newbus events related functions.
|
||||
o More cleanup ... !
|
||||
|
||||
Provided under the FreeBSD Documentation License.
|
||||
-->
|
||||
<chapter id="newbus">
|
||||
<chapterinfo>
|
||||
<authorgroup>
|
||||
<author>
|
||||
<firstname>Jeroen</firstname>
|
||||
<surname>Ruigrok van der Werven</surname>
|
||||
<affiliation><address><email>asmodai@FreeBSD.org</email></address>
|
||||
</affiliation>
|
||||
<contrib>Written by </contrib>
|
||||
</author>
|
||||
</authorgroup>
|
||||
<authorgroup>
|
||||
<author>
|
||||
<firstname>Hiten</firstname>
|
||||
<surname>Pandya</surname>
|
||||
<affiliation><address><email>hiten@uk.FreeBSD.org</email></address>
|
||||
</affiliation>
|
||||
</author>
|
||||
</authorgroup>
|
||||
</chapterinfo>
|
||||
<title>Newbus</title>
|
||||
|
||||
<para><emphasis>Special thanks to Mathew N. Dodd, Warner Losh, Bill Paul.
|
||||
Daug Rabson, Mike Smith, Peter Wemm and Scott Long.</emphasis></para>
|
||||
|
||||
<para>This chapter explains the Newbus device framework in detail.</para>
|
||||
<sect1 id="devdrivers">
|
||||
<title>Device Drivers</title>
|
||||
<sect2>
|
||||
<title>Purpose of a Device Driver</title>
|
||||
<para>A device driver is a software component which provides the
|
||||
interface between the kernel's generic view of a peripheral
|
||||
(e.g. disk, network adapter) and the actual implementation of the
|
||||
peripheral. The <emphasis>device driver interface (DDI)</emphasis> is
|
||||
the defined interface between the kernel and the device driver component.
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
<sect2>
|
||||
<title>Types of Device Drivers</title>
|
||||
<para>There used to be days in &unix;, and thus FreeBSD, in which there
|
||||
were four types of devices defined:</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem><para>block device drivers</para></listitem>
|
||||
<listitem><para>character device drivers</para></listitem>
|
||||
<listitem><para>network device drivers</para></listitem>
|
||||
<listitem><para>pseudo-device drivers</para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para><emphasis>Block devices</emphasis> performed in way that used
|
||||
fixed size blocks [of data]. This type of driver depended on the
|
||||
so called <emphasis>buffer cache</emphasis>, which had the purpose
|
||||
to cache accessed blocks of data in a dedicated part of the memory.
|
||||
Often this buffer cache was based on write-behind, which meant that when
|
||||
data was modified in memory it got synced to disk whenever the system
|
||||
did its periodical disk flushing, thus optimizing writes.</para>
|
||||
</sect2>
|
||||
|
||||
<sect2>
|
||||
<title>Character devices</title>
|
||||
<para>However, in the versions of FreeBSD 4.0 and onward the
|
||||
distinction between block and character devices became non-existent.
|
||||
</para>
|
||||
</sect2>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="newbus-overview">
|
||||
<!--
|
||||
Real title:
|
||||
Newbus, Busspace and the Resource Manager, an Explanation of the Possibilities
|
||||
-->
|
||||
<title>Overview of Newbus</title>
|
||||
<para><emphasis>Newbus</emphasis> is the implementation of a new bus
|
||||
architecture based on abstraction layers which saw its introduction in
|
||||
FreeBSD 3.0 when the Alpha port was imported into the source tree. It was
|
||||
not until 4.0 before it became the default system to use for device
|
||||
drivers. Its goals are to provide a more object oriented means of
|
||||
interconnecting the various busses and devices which a host system
|
||||
provides to the <emphasis>Operating System</emphasis>.</para>
|
||||
|
||||
<para>Its main features include amongst others:</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem><para>dynamic attaching</para></listitem>
|
||||
<listitem><para>easy modularization of drivers</para></listitem>
|
||||
<listitem><para>pseudo-busses</para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>One of the most prominent changes is the migration from the flat and
|
||||
ad-hoc system to a device tree lay-out.</para>
|
||||
|
||||
<para>At the top level resides the <emphasis><quote>root</quote></emphasis>
|
||||
device which is the parent to hang all other devices on. For each
|
||||
architecture, there is typically a single child of <quote>root</quote>
|
||||
which has such things as <emphasis>host-to-PCI bridges</emphasis>, etc.
|
||||
attached to it. For x86, this <quote>root</quote> device is the
|
||||
<emphasis><quote>nexus</quote></emphasis> device and for Alpha, various
|
||||
different different models of Alpha have different top-level devices
|
||||
corresponding to the different hardware chipsets, including
|
||||
<emphasis>lca</emphasis>, <emphasis>apecs</emphasis>,
|
||||
<emphasis>cia</emphasis> and <emphasis>tsunami</emphasis>.</para>
|
||||
|
||||
<para>A device in the Newbus context represents a single hardware entity
|
||||
in the system. For instance each PCI device is represented by a Newbus
|
||||
device. Any device in the system can have children; a device which has
|
||||
children is often called a <emphasis><quote>bus</quote></emphasis>.
|
||||
Examples of common busses in the system are ISA and PCI which manage lists
|
||||
of devices attached to ISA and PCI busses respectively.</para>
|
||||
|
||||
<para>Often, a connection between different kinds of bus is represented by
|
||||
a <emphasis><quote>bridge</quote></emphasis> device which normally has one
|
||||
child for the attached bus. An example of this is a
|
||||
<emphasis>PCI-to-PCI bridge</emphasis> which is represented by a device
|
||||
<emphasis><devicename>pcibN</devicename></emphasis> on the parent PCI bus
|
||||
and has a child <emphasis><devicename>pciN</devicename></emphasis> for the
|
||||
attached bus. This layout simplifies the implementation of the PCI bus
|
||||
tree, allowing common code to be used for both top-level and bridged
|
||||
busses.</para>
|
||||
|
||||
<para>Each device in the Newbus architecture asks its parent to map its
|
||||
resources. The parent then asks its own parent until the nexus is
|
||||
reached. So, basically the nexus is the only part of the Newbus system
|
||||
which knows about all resources.</para>
|
||||
|
||||
<tip><para>An ISA device might want to map its IO port at
|
||||
<literal>0x23c</literal>, so it asks its parent, in this case the ISA
|
||||
bus. The ISA bus hands it over to the PCI-to-ISA bridge which in its turn
|
||||
asks the PCI bus, which reaches the host-to-PCI bridge and finally the
|
||||
nexus. The beauty of this transition upwards is that there is room to
|
||||
translate the requests. For example, the <literal>0x23c</literal> IO port
|
||||
request might become memory-mapped at <literal>0xb000023c</literal> on a
|
||||
<acronym>MIPS</acronym> box by the PCI bridge.</para></tip>
|
||||
|
||||
<para>Resource allocation can be controlled at any place in the device
|
||||
tree. For instance on many Alpha platforms, ISA interrupts are managed
|
||||
separately from PCI interrupts and resource allocations for ISA interrupts
|
||||
are managed by the Alpha's ISA bus device. On IA-32, ISA and PCI
|
||||
interrupts are both managed by the top-level nexus device. For both
|
||||
ports, memory and port address space is managed by a single entity - nexus
|
||||
for IA-32 and the relevant chipset driver on Alpha (e.g. CIA or tsunami).
|
||||
</para>
|
||||
|
||||
<para>In order to normalize access to memory and port mapped resources,
|
||||
Newbus integrates the <literal>bus_space</literal> APIs from NetBSD.
|
||||
These provide a single API to replace inb/outb and direct memory
|
||||
reads/writes. The advantage of this is that a single driver can easily
|
||||
use either memory-mapped registers or port-mapped registers
|
||||
(some hardware supports both).</para>
|
||||
|
||||
<para>This support is integrated into the resource allocation mechanism.
|
||||
When a resource is allocated, a driver can retrieve the associated
|
||||
<structfield>bus_space_tag_t</structfield> and
|
||||
<structfield>bus_space_handle_t</structfield> from the resource.</para>
|
||||
|
||||
<para>Newbus also allows for definitions of interface methods in files
|
||||
dedicated to this purpose. These are the <filename>.m</filename> files
|
||||
that are found under the <filename>src/sys</filename> hierarchy.</para>
|
||||
|
||||
<para>The core of the Newbus system is an extensible
|
||||
<quote>object-based programming</quote> model. Each device in the system
|
||||
has a table of methods which it supports. The system and other devices
|
||||
uses those methods to control the device and request services. The
|
||||
different methods supported by a device are defined by a number of
|
||||
<quote>interfaces</quote>. An <quote>interface</quote> is simply a group
|
||||
of related methods which can be implemented by a device.</para>
|
||||
|
||||
<para>In the Newbus system, the methods for a device are provided by the
|
||||
various device drivers in the system. When a device is attached to a
|
||||
driver during <emphasis>auto-configuration</emphasis>, it uses the method
|
||||
table declared by the driver. A device can later
|
||||
<emphasis>detach</emphasis> from its driver and
|
||||
<emphasis>re-attach</emphasis> to a new driver with a new method table.
|
||||
This allows dynamic replacement of drivers which can be useful for driver
|
||||
development.</para>
|
||||
|
||||
<para>The interfaces are described by an interface definition language
|
||||
similar to the language used to define vnode operations for file systems.
|
||||
The interface would be stored in a methods file (which would normally named
|
||||
<filename>foo_if.m</filename>).</para>
|
||||
|
||||
<example>
|
||||
<title>Newbus Methods</title>
|
||||
<programlisting>
|
||||
# Foo subsystem/driver (a comment...)
|
||||
|
||||
INTERFACE foo
|
||||
|
||||
METHOD int doit {
|
||||
device_t dev;
|
||||
};
|
||||
|
||||
# DEFAULT is the method that will be used, if a method was not
|
||||
# provided via: DEVMETHOD()
|
||||
|
||||
METHOD void doit_to_child {
|
||||
device_t dev;
|
||||
driver_t child;
|
||||
} DEFAULT doit_generic_to_child;
|
||||
</programlisting>
|
||||
</example>
|
||||
|
||||
<para>When this interface is compiled, it generates a header file
|
||||
<quote><filename>foo_if.h</filename></quote> which contains function
|
||||
declarations:</para>
|
||||
|
||||
<programlisting>
|
||||
int FOO_DOIT(device_t dev);
|
||||
int FOO_DOIT_TO_CHILD(device_t dev, device_t child);
|
||||
</programlisting>
|
||||
|
||||
<para>A source file, <quote><filename>foo_if.c</filename></quote> is
|
||||
also created to accompany the automatically generated header file; it
|
||||
contains implementations of those functions which look up the location
|
||||
of the relevant functions in the object's method table and call that
|
||||
function.</para>
|
||||
|
||||
<para>The system defines two main interfaces. The first fundamental
|
||||
interface is called <emphasis><quote>device</quote></emphasis> and
|
||||
includes methods which are relevant to all devices. Methods in the
|
||||
<emphasis><quote>device</quote></emphasis> interface include
|
||||
<emphasis><quote>probe</quote></emphasis>,
|
||||
<emphasis><quote>attach</quote></emphasis> and
|
||||
<emphasis><quote>detach</quote></emphasis> to control detection of
|
||||
hardware and <emphasis><quote>shutdown</quote></emphasis>,
|
||||
<emphasis><quote>suspend</quote></emphasis> and
|
||||
<emphasis><quote>resume</quote></emphasis> for critical event
|
||||
notification.</para>
|
||||
|
||||
<para>The second, more complex interface is
|
||||
<emphasis><quote>bus</quote></emphasis>. This interface contains
|
||||
methods suitable for devices which have children, including methods to
|
||||
access bus specific per-device information
|
||||
<footnote><para>&man.bus.generic.read.ivar.9; and
|
||||
&man.bus.generic.write.ivar.9;</para></footnote>, event notification
|
||||
(<emphasis><literal>child_detached</literal></emphasis>,
|
||||
<emphasis><literal>driver_added</literal></emphasis>) and resource
|
||||
management (<emphasis><literal>alloc_resource</literal></emphasis>,
|
||||
<emphasis><literal>activate_resource</literal></emphasis>,
|
||||
<emphasis><literal>deactivate_resource</literal></emphasis>,
|
||||
<emphasis><literal>release_resource</literal></emphasis>).
|
||||
|
||||
<para>Many methods in the <quote>bus</quote> interface are performing
|
||||
services for some child of the bus device. These methods would normally
|
||||
use the first two arguments to specify the bus providing the service
|
||||
and the child device which is requesting the service. To simplify
|
||||
driver code, many of these methods have accessor functions which
|
||||
lookup the parent and call a method on the parent. For instance the
|
||||
method
|
||||
<literal>BUS_TEARDOWN_INTR(device_t dev, device_t child, ...)</literal>
|
||||
can be called using the function
|
||||
<literal>bus_teardown_intr(device_t child, ...)</literal>.</para>
|
||||
|
||||
<para>Some bus types in the system define additional interfaces to
|
||||
provide access to bus-specific functionality. For instance, the PCI
|
||||
bus driver defines the <quote>pci</quote> interface which has two
|
||||
methods <emphasis><literal>read_config</literal></emphasis> and
|
||||
<emphasis><literal>write_config</literal></emphasis> for accessing the
|
||||
configuration registers of a PCI device.</para>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="newbus-api">
|
||||
<title>Newbus API</title>
|
||||
<para>As the Newbus API is huge, this section makes some effort at
|
||||
documenting it. More information to come in the next revision of this
|
||||
document.</para>
|
||||
|
||||
<sect2>
|
||||
<title>Important locations in the source hierarchy</title>
|
||||
|
||||
<para><filename>src/sys/[arch]/[arch]</filename> - Kernel code for a
|
||||
specific machine architecture resides in this directory. for example,
|
||||
the <literal>i386</literal> architecture, or the
|
||||
<literal>SPARC64</literal> architecture.</para>
|
||||
|
||||
<para><filename>src/sys/dev/[bus]</filename> - device support for a
|
||||
specific <literal>[bus]</literal> resides in this directory.</para>
|
||||
|
||||
<para><filename>src/sys/dev/pci</filename> - PCI bus support code
|
||||
resides in this directory.</para>
|
||||
|
||||
<para><filename>src/sys/[isa|pci]</filename> - PCI/ISA device drivers
|
||||
reside in this directory. The PCI/ISA bus support code used to exist
|
||||
in this directory in FreeBSD version <literal>4.0</literal>.</para>
|
||||
</sect2>
|
||||
|
||||
<sect2>
|
||||
<title>Important structures and type definitions</title>
|
||||
<para><literal>devclass_t</literal> - This is a type definition of a
|
||||
pointer to a <literal>struct devclass</literal>.</para>
|
||||
|
||||
<para><literal>device_method_t</literal> - This is same as
|
||||
<literal>kobj_method_t</literal> (see
|
||||
<filename>src/sys/kobj.h</filename>).</para>
|
||||
|
||||
<para><literal>device_t</literal> - This is a type definition of a
|
||||
pointer to a <literal>struct device</literal>.
|
||||
<literal>device_t</literal> represents a device in the system. It is
|
||||
a kernel object. See <filename>src/sys/sys/bus_private.h</filename>
|
||||
for implementation details.</para>
|
||||
|
||||
<para><literal>driver_t</literal> - This is a type definition which,
|
||||
references <literal>struct driver</literal>. The
|
||||
<literal>driver</literal> struct is a class of the
|
||||
<literal>device</literal> kernel object; it also holds data private
|
||||
to for the driver.</para>
|
||||
|
||||
<figure>
|
||||
<title><emphasis>driver_t</emphasis> implementation</title>
|
||||
<programlisting>
|
||||
struct driver {
|
||||
KOBJ_CLASS_FIELDS;
|
||||
void *priv; /* driver private data */
|
||||
};
|
||||
</programlisting>
|
||||
</figure>
|
||||
|
||||
<para>A <literal>device_state_t</literal> type, which is
|
||||
an enumeration, <literal>device_state</literal>. It contains
|
||||
the possible states of a Newbus device before and after the
|
||||
autoconfiguration process.</para>
|
||||
|
||||
<figure>
|
||||
<title>Device states<emphasis>device_state_t</emphasis></title>
|
||||
<programlisting>
|
||||
/*
|
||||
* src/sys/sys/bus.h
|
||||
*/
|
||||
typedef enum device_state {
|
||||
DS_NOTPRESENT, /* not probed or probe failed */
|
||||
DS_ALIVE, /* probe succeeded */
|
||||
DS_ATTACHED, /* attach method called */
|
||||
DS_BUSY /* device is open */
|
||||
} device_state_t;
|
||||
</programlisting>
|
||||
</figure>
|
||||
</sect2>
|
||||
</sect1>
|
||||
</chapter>
|
|
@ -11,6 +11,10 @@
|
|||
<!ENTITY os.current "&os;-CURRENT">
|
||||
<!ENTITY os.stable "&os;-STABLE">
|
||||
|
||||
<!--
|
||||
Use this entity when refering to 'UNIX' in your document.
|
||||
-->
|
||||
<!ENTITY unix "<trademark>UNIX</trademark>">
|
||||
<!-- The currently released version of FreeBSD. This value is used to
|
||||
create some links on web sites and such, so do NOT change it until
|
||||
it's really release time -->
|
||||
|
|
Loading…
Reference in a new issue