|
Added
Link Here
|
| 1 |
<!-- |
| 2 |
The FreeBSD Documentation Project |
| 3 |
$FreeBSD$ |
| 4 |
|
| 5 |
Originally by: Jeroen Ruigrok van der Warven |
| 6 |
Date: newbus-draft.txt,v 1.8 2001/01/25 08:01:08 |
| 7 |
Copyright (c) 2000 Jeroen Ruigrok van der Warven (asmodai@wxs.nl) |
| 8 |
Copyright (c) 2002 Hiten Mahesh Pandya (hiten@uk.FreeBSD.org) |
| 9 |
|
| 10 |
Future Additions: |
| 11 |
|
| 12 |
o Expand the information about device_t, and explain each and |
| 13 |
every field in it. |
| 14 |
o Add information about the bus_* functions. |
| 15 |
o Add information about bus specific (e.g. PCI) functions. |
| 16 |
o Add a reference section for additional information. |
| 17 |
o Add more newbus related structures and typedefs. |
| 18 |
o Add a 'Terminology' section. |
| 19 |
o Add information on resource manager functions, busspace |
| 20 |
manager functions, newbus events related functions. |
| 21 |
o More cleanup ... ! |
| 22 |
|
| 23 |
Provided under the FreeBSD Documentation License. |
| 24 |
--> |
| 25 |
<chapter id="newbus"> |
| 26 |
<chapterinfo> |
| 27 |
<authorgroup> |
| 28 |
<author> |
| 29 |
<firstname>Jeroen</firstname> |
| 30 |
<surname>Ruigrok van der Werven</surname> |
| 31 |
<affiliation><address><email>asmodai@FreeBSD.org</email></address> |
| 32 |
</affiliation> |
| 33 |
<contrib>Written by </contrib> |
| 34 |
</author> |
| 35 |
</authorgroup> |
| 36 |
<authorgroup> |
| 37 |
<author> |
| 38 |
<firstname>Hiten</firstname> |
| 39 |
<surname>Pandya</surname> |
| 40 |
<affiliation><address><email>hiten@uk.FreeBSD.org</email></address> |
| 41 |
</affiliation> |
| 42 |
</author> |
| 43 |
</authorgroup> |
| 44 |
</chapterinfo> |
| 45 |
<title>Newbus</title> |
| 46 |
|
| 47 |
<para><emphasis>Special thanks to Mathew N. Dodd, Warner Losh, Bill Paul. |
| 48 |
Daug Rabson, Mike Smith, Peter Wemm and Scott Long.</emphasis></para> |
| 49 |
|
| 50 |
<para>This chapter explains the Newbus device framework in detail.</para> |
| 51 |
<sect1 id="devdrivers"> |
| 52 |
<title>Device Drivers</title> |
| 53 |
<sect2> |
| 54 |
<title>Purpose of a Device Driver</title> |
| 55 |
<para>A device driver is a software component which provides the |
| 56 |
interface between the kernel's generic view of a peripheral |
| 57 |
(e.g. disk, network adapter) and the actual implementation of the |
| 58 |
peripheral. The <emphasis>device driver interface (DDI)</emphasis> is |
| 59 |
the defined interface between the kernel and the device driver component. |
| 60 |
</para> |
| 61 |
</sect2> |
| 62 |
|
| 63 |
<sect2> |
| 64 |
<title>Types of Device Drivers</title> |
| 65 |
<para>There used to be days in &unix;, and thus FreeBSD, in which there |
| 66 |
were four types of devices defined:</para> |
| 67 |
|
| 68 |
<itemizedlist> |
| 69 |
<listitem><para>block device drivers</para></listitem> |
| 70 |
<listitem><para>character device drivers</para></listitem> |
| 71 |
<listitem><para>network device drivers</para></listitem> |
| 72 |
<listitem><para>pseudo-device drivers</para></listitem> |
| 73 |
</itemizedlist> |
| 74 |
|
| 75 |
<para><emphasis>Block devices</emphasis> performed in way that used |
| 76 |
fixed size blocks [of data]. This type of driver depended on the |
| 77 |
so called <emphasis>buffer cache</emphasis>, which had the purpose |
| 78 |
to cache accessed blocks of data in a dedicated part of the memory. |
| 79 |
Often this buffer cache was based on write-behind, which meant that when |
| 80 |
data was modified in memory it got synced to disk whenever the system |
| 81 |
did its periodical disk flushing, thus optimizing writes.</para> |
| 82 |
</sect2> |
| 83 |
|
| 84 |
<sect2> |
| 85 |
<title>Character devices</title> |
| 86 |
<para>However, in the versions of FreeBSD 4.0 and onward the |
| 87 |
distinction between block and character devices became non-existent. |
| 88 |
</para> |
| 89 |
</sect2> |
| 90 |
</sect1> |
| 91 |
|
| 92 |
<sect1 id="newbus-overview"> |
| 93 |
<!-- |
| 94 |
Real title: |
| 95 |
Newbus, Busspace and the Resource Manager, an Explanation of the Possibilities |
| 96 |
--> |
| 97 |
<title>Overview of Newbus</title> |
| 98 |
<para><emphasis>Newbus</emphasis> is the implementation of a new bus |
| 99 |
architecture based on abstraction layers which saw its introduction in |
| 100 |
FreeBSD 3.0 when the Alpha port was imported into the source tree. It was |
| 101 |
not until 4.0 before it became the default system to use for device |
| 102 |
drivers. Its goals are to provide a more object oriented means of |
| 103 |
interconnecting the various busses and devices which a host system |
| 104 |
provides to the <emphasis>Operating System</emphasis>.</para> |
| 105 |
|
| 106 |
<para>Its main features include amongst others:</para> |
| 107 |
|
| 108 |
<itemizedlist> |
| 109 |
<listitem><para>dynamic attaching</para></listitem> |
| 110 |
<listitem><para>easy modularization of drivers</para></listitem> |
| 111 |
<listitem><para>pseudo-busses</para></listitem> |
| 112 |
</itemizedlist> |
| 113 |
|
| 114 |
<para>One of the most prominent changes is the migration from the flat and |
| 115 |
ad-hoc system to a device tree lay-out.</para> |
| 116 |
|
| 117 |
<para>At the top level resides the <emphasis><quote>root</quote></emphasis> |
| 118 |
device which is the parent to hang all other devices on. For each |
| 119 |
architecture, there is typically a single child of <quote>root</quote> |
| 120 |
which has such things as <emphasis>host-to-PCI bridges</emphasis>, etc. |
| 121 |
attached to it. For x86, this <quote>root</quote> device is the |
| 122 |
<emphasis><quote>nexus</quote></emphasis> device and for Alpha, various |
| 123 |
different different models of Alpha have different top-level devices |
| 124 |
corresponding to the different hardware chipsets, including |
| 125 |
<emphasis>lca</emphasis>, <emphasis>apecs</emphasis>, |
| 126 |
<emphasis>cia</emphasis> and <emphasis>tsunami</emphasis>.</para> |
| 127 |
|
| 128 |
<para>A device in the Newbus context represents a single hardware entity |
| 129 |
in the system. For instance each PCI device is represented by a Newbus |
| 130 |
device. Any device in the system can have children; a device which has |
| 131 |
children is often called a <emphasis><quote>bus</quote></emphasis>. |
| 132 |
Examples of common busses in the system are ISA and PCI which manage lists |
| 133 |
of devices attached to ISA and PCI busses respectively.</para> |
| 134 |
|
| 135 |
<para>Often, a connection between different kinds of bus is represented by |
| 136 |
a <emphasis><quote>bridge</quote></emphasis> device which normally has one |
| 137 |
child for the attached bus. An example of this is a |
| 138 |
<emphasis>PCI-to-PCI bridge</emphasis> which is represented by a device |
| 139 |
<emphasis><devicename>pcibN</devicename></emphasis> on the parent PCI bus |
| 140 |
and has a child <emphasis><devicename>pciN</devicename></emphasis> for the |
| 141 |
attached bus. This layout simplifies the implementation of the PCI bus |
| 142 |
tree, allowing common code to be used for both top-level and bridged |
| 143 |
busses.</para> |
| 144 |
|
| 145 |
<para>Each device in the Newbus architecture asks its parent to map its |
| 146 |
resources. The parent then asks its own parent until the nexus is |
| 147 |
reached. So, basically the nexus is the only part of the Newbus system |
| 148 |
which knows about all resources.</para> |
| 149 |
|
| 150 |
<tip><para>An ISA device might want to map its IO port at |
| 151 |
<literal>0x23c</literal>, so it asks its parent, in this case the ISA |
| 152 |
bus. The ISA bus hands it over to the PCI-to-ISA bridge which in its turn |
| 153 |
asks the PCI bus, which reaches the host-to-PCI bridge and finally the |
| 154 |
nexus. The beauty of this transition upwards is that there is room to |
| 155 |
translate the requests. For example, the <literal>0x23c</literal> IO port |
| 156 |
request might become memory-mapped at <literal>0xb000023c</literal> on a |
| 157 |
<acronym>MIPS</acronym> box by the PCI bridge.</para></tip> |
| 158 |
|
| 159 |
<para>Resource allocation can be controlled at any place in the device |
| 160 |
tree. For instance on many Alpha platforms, ISA interrupts are managed |
| 161 |
separately from PCI interrupts and resource allocations for ISA interrupts |
| 162 |
are managed by the Alpha's ISA bus device. On IA-32, ISA and PCI |
| 163 |
interrupts are both managed by the top-level nexus device. For both |
| 164 |
ports, memory and port address space is managed by a single entity - nexus |
| 165 |
for IA-32 and the relevant chipset driver on Alpha (e.g. CIA or tsunami). |
| 166 |
</para> |
| 167 |
|
| 168 |
<para>In order to normalize access to memory and port mapped resources, |
| 169 |
Newbus integrates the <literal>bus_space</literal> APIs from NetBSD. |
| 170 |
These provide a single API to replace inb/outb and direct memory |
| 171 |
reads/writes. The advantage of this is that a single driver can easily |
| 172 |
use either memory-mapped registers or port-mapped registers |
| 173 |
(some hardware supports both).</para> |
| 174 |
|
| 175 |
<para>This support is integrated into the resource allocation mechanism. |
| 176 |
When a resource is allocated, a driver can retrieve the associated |
| 177 |
<structfield>bus_space_tag_t</structfield> and |
| 178 |
<structfield>bus_space_handle_t</structfield> from the resource.</para> |
| 179 |
|
| 180 |
<para>Newbus also allows for definitions of interface methods in files |
| 181 |
dedicated to this purpose. These are the <filename>.m</filename> files |
| 182 |
that are found under the <filename>src/sys</filename> hierarchy.</para> |
| 183 |
|
| 184 |
<para>The core of the Newbus system is an extensible |
| 185 |
<quote>object-based programming</quote> model. Each device in the system |
| 186 |
has a table of methods which it supports. The system and other devices |
| 187 |
uses those methods to control the device and request services. The |
| 188 |
different methods supported by a device are defined by a number of |
| 189 |
<quote>interfaces</quote>. An <quote>interface</quote> is simply a group |
| 190 |
of related methods which can be implemented by a device.</para> |
| 191 |
|
| 192 |
<para>In the Newbus system, the methods for a device are provided by the |
| 193 |
various device drivers in the system. When a device is attached to a |
| 194 |
driver during <emphasis>auto-configuration</emphasis>, it uses the method |
| 195 |
table declared by the driver. A device can later |
| 196 |
<emphasis>detach</emphasis> from its driver and |
| 197 |
<emphasis>re-attach</emphasis> to a new driver with a new method table. |
| 198 |
This allows dynamic replacement of drivers which can be useful for driver |
| 199 |
development.</para> |
| 200 |
|
| 201 |
<para>The interfaces are described by an interface definition language |
| 202 |
similar to the language used to define vnode operations for file systems. |
| 203 |
The interface would be stored in a methods file (which would normally named |
| 204 |
<filename>foo_if.m</filename>).</para> |
| 205 |
|
| 206 |
<example> |
| 207 |
<title>Newbus Methods</title> |
| 208 |
<programlisting> |
| 209 |
# Foo subsystem/driver (a comment...) |
| 210 |
|
| 211 |
INTERFACE foo |
| 212 |
|
| 213 |
METHOD int doit { |
| 214 |
device_t dev; |
| 215 |
}; |
| 216 |
|
| 217 |
# DEFAULT is the method that will be used, if a method was not |
| 218 |
# provided via: DEVMETHOD() |
| 219 |
|
| 220 |
METHOD void doit_to_child { |
| 221 |
device_t dev; |
| 222 |
driver_t child; |
| 223 |
} DEFAULT doit_generic_to_child; |
| 224 |
</programlisting> |
| 225 |
</example> |
| 226 |
|
| 227 |
<para>When this interface is compiled, it generates a header file |
| 228 |
<quote><filename>foo_if.h</filename></quote> which contains function |
| 229 |
declarations:</para> |
| 230 |
|
| 231 |
<programlisting> |
| 232 |
int FOO_DOIT(device_t dev); |
| 233 |
int FOO_DOIT_TO_CHILD(device_t dev, device_t child); |
| 234 |
</programlisting> |
| 235 |
|
| 236 |
<para>A source file, <quote><filename>foo_if.c</filename></quote> is |
| 237 |
also created to accompany the automatically generated header file; it |
| 238 |
contains implementations of those functions which look up the location |
| 239 |
of the relevant functions in the object's method table and call that |
| 240 |
function.</para> |
| 241 |
|
| 242 |
<para>The system defines two main interfaces. The first fundamental |
| 243 |
interface is called <emphasis><quote>device</quote></emphasis> and |
| 244 |
includes methods which are relevant to all devices. Methods in the |
| 245 |
<emphasis><quote>device</quote></emphasis> interface include |
| 246 |
<emphasis><quote>probe</quote></emphasis>, |
| 247 |
<emphasis><quote>attach</quote></emphasis> and |
| 248 |
<emphasis><quote>detach</quote></emphasis> to control detection of |
| 249 |
hardware and <emphasis><quote>shutdown</quote></emphasis>, |
| 250 |
<emphasis><quote>suspend</quote></emphasis> and |
| 251 |
<emphasis><quote>resume</quote></emphasis> for critical event |
| 252 |
notification.</para> |
| 253 |
|
| 254 |
<para>The second, more complex interface is |
| 255 |
<emphasis><quote>bus</quote></emphasis>. This interface contains |
| 256 |
methods suitable for devices which have children, including methods to |
| 257 |
access bus specific per-device information |
| 258 |
<footnote><para>&man.bus.generic.read.ivar.9; and |
| 259 |
&man.bus.generic.write.ivar.9;</para></footnote>, event notification |
| 260 |
(<emphasis><literal>child_detached</literal></emphasis>, |
| 261 |
<emphasis><literal>driver_added</literal></emphasis>) and resource |
| 262 |
management (<emphasis><literal>alloc_resource</literal></emphasis>, |
| 263 |
<emphasis><literal>activate_resource</literal></emphasis>, |
| 264 |
<emphasis><literal>deactivate_resource</literal></emphasis>, |
| 265 |
<emphasis><literal>release_resource</literal></emphasis>). |
| 266 |
|
| 267 |
<para>Many methods in the <quote>bus</quote> interface are performing |
| 268 |
services for some child of the bus device. These methods would normally |
| 269 |
use the first two arguments to specify the bus providing the service |
| 270 |
and the child device which is requesting the service. To simplify |
| 271 |
driver code, many of these methods have accessor functions which |
| 272 |
lookup the parent and call a method on the parent. For instance the |
| 273 |
method |
| 274 |
<literal>BUS_TEARDOWN_INTR(device_t dev, device_t child, ...)</literal> |
| 275 |
can be called using the function |
| 276 |
<literal>bus_teardown_intr(device_t child, ...)</literal>.</para> |
| 277 |
|
| 278 |
<para>Some bus types in the system define additional interfaces to |
| 279 |
provide access to bus-specific functionality. For instance, the PCI |
| 280 |
bus driver defines the <quote>pci</quote> interface which has two |
| 281 |
methods <emphasis><literal>read_config</literal></emphasis> and |
| 282 |
<emphasis><literal>write_config</literal></emphasis> for accessing the |
| 283 |
configuration registers of a PCI device.</para> |
| 284 |
</sect1> |
| 285 |
|
| 286 |
<sect1 id="newbus-api"> |
| 287 |
<title>Newbus API</title> |
| 288 |
<para>As the Newbus API is huge, this section makes some effort at |
| 289 |
documenting it. More information to come in the next revision of this |
| 290 |
document.</para> |
| 291 |
|
| 292 |
<sect2> |
| 293 |
<title>Important locations in the source hierarchy</title> |
| 294 |
|
| 295 |
<para><filename>src/sys/[arch]/[arch]</filename> - Kernel code for a |
| 296 |
specific machine architecture resides in this directory. for example, |
| 297 |
the <literal>i386</literal> architecture, or the |
| 298 |
<literal>SPARC64</literal> architecture.</para> |
| 299 |
|
| 300 |
<para><filename>src/sys/dev/[bus]</filename> - device support for a |
| 301 |
specific <literal>[bus]</literal> resides in this directory.</para> |
| 302 |
|
| 303 |
<para><filename>src/sys/dev/pci</filename> - PCI bus support code |
| 304 |
resides in this directory.</para> |
| 305 |
|
| 306 |
<para><filename>src/sys/[isa|pci]</filename> - PCI/ISA device drivers |
| 307 |
reside in this directory. The PCI/ISA bus support code used to exist |
| 308 |
in this directory in FreeBSD version <literal>4.0</literal>.</para> |
| 309 |
</sect2> |
| 310 |
|
| 311 |
<sect2> |
| 312 |
<title>Important structures and type definitions</title> |
| 313 |
<para><literal>devclass_t</literal> - This is a type definition of a |
| 314 |
pointer to a <literal>struct devclass</literal>.</para> |
| 315 |
|
| 316 |
<para><literal>device_method_t</literal> - This is same as |
| 317 |
<literal>kobj_method_t</literal> (see |
| 318 |
<filename>src/sys/kobj.h</filename>).</para> |
| 319 |
|
| 320 |
<para><literal>device_t</literal> - This is a type definition of a |
| 321 |
pointer to a <literal>struct device</literal>. |
| 322 |
<literal>device_t</literal> represents a device in the system. It is |
| 323 |
a kernel object. See <filename>src/sys/sys/bus_private.h</filename> |
| 324 |
for implementation details.</para> |
| 325 |
|
| 326 |
<para><literal>driver_t</literal> - This is a type definition which, |
| 327 |
references <literal>struct driver</literal>. The |
| 328 |
<literal>driver</literal> struct is a class of the |
| 329 |
<literal>device</literal> kernel object; it also holds data private |
| 330 |
to for the driver.</para> |
| 331 |
|
| 332 |
<figure> |
| 333 |
<title><emphasis>driver_t</emphasis> implementation</title> |
| 334 |
<programlisting> |
| 335 |
struct driver { |
| 336 |
KOBJ_CLASS_FIELDS; |
| 337 |
void *priv; /* driver private data */ |
| 338 |
}; |
| 339 |
</programlisting> |
| 340 |
</figure> |
| 341 |
|
| 342 |
<para>A <literal>device_state_t</literal> type, which is |
| 343 |
an enumeration, <literal>device_state</literal>. It contains |
| 344 |
the possible states of a Newbus device before and after the |
| 345 |
autoconfiguration process.</para> |
| 346 |
|
| 347 |
<figure> |
| 348 |
<title>Device states<emphasis>device_state_t</emphasis></title> |
| 349 |
<programlisting> |
| 350 |
/* |
| 351 |
* src/sys/sys/bus.h |
| 352 |
*/ |
| 353 |
typedef enum device_state { |
| 354 |
DS_NOTPRESENT, /* not probed or probe failed */ |
| 355 |
DS_ALIVE, /* probe succeeded */ |
| 356 |
DS_ATTACHED, /* attach method called */ |
| 357 |
DS_BUSY /* device is open */ |
| 358 |
} device_state_t; |
| 359 |
</programlisting> |
| 360 |
</figure> |
| 361 |
</sect2> |
| 362 |
</sect1> |
| 363 |
</chapter> |