View | Details | Raw Unified | Return to bug 42557 | Differences between
and this patch

Collapse All | Expand All

(-)newbus.sgml (+363 lines)
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>

Return to bug 42557