summaryrefslogtreecommitdiff
path: root/static/freebsd/man4/proto.4 3.html
blob: c4eb5aed4cfa0a12306ee7a4d5b31c592bc9d037 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
<table class="head">
  <tr>
    <td class="head-ltitle">PROTO(4)</td>
    <td class="head-vol">Device Drivers Manual</td>
    <td class="head-rtitle">PROTO(4)</td>
  </tr>
</table>
<div class="manual-text">
<section class="Sh">
<h1 class="Sh" id="NAME"><a class="permalink" href="#NAME">NAME</a></h1>
<p class="Pp"><code class="Nm">proto</code> &#x2014; <span class="Nd">Generic
    prototyping and diagnostics driver</span></p>
</section>
<section class="Sh">
<h1 class="Sh" id="SYNOPSIS"><a class="permalink" href="#SYNOPSIS">SYNOPSIS</a></h1>
<p class="Pp">To compile this driver into the kernel, place the following line
    in your kernel configuration file:</p>
<div class="Bd Pp Bd-indent"><code class="Cd">device proto</code></div>
<p class="Pp">Alternatively, to load the driver as a module at boot time, place
    the following line in <a class="Xr">loader.conf(5)</a>:</p>
<div class="Bd Pp Bd-indent Li">
<pre>proto_load=&quot;YES&quot;</pre>
</div>
<p class="Pp">To have the driver attach to a device instead of its regular
    driver, mention it in the list of devices assigned to the following loader
    variable:</p>
<div class="Bd Pp Bd-indent">hw.proto.attach=&quot;desc[,desc]&quot;</div>
</section>
<section class="Sh">
<h1 class="Sh" id="DESCRIPTION"><a class="permalink" href="#DESCRIPTION">DESCRIPTION</a></h1>
<p class="Pp">The <code class="Nm">proto</code> device driver attaches to PCI or
    ISA devices when no other device drivers are present for those devices and
    it creates device special files for all resources associated with the
    device. The driver itself has no knowledge of the device it attaches to.
    Programs can open these device special files and perform register-level
    reads and writes. As such, the <code class="Nm">proto</code> device driver
    is nothing but a conduit or gateway between user space programs and the
    hardware device.</p>
<p class="Pp">Examples for why this is useful include hardware diagnostics and
    prototyping. In both these use cases, it is far more convenient to develop
    and run the logic in user space. Especially hardware diagnostics requires a
    somewhat user-friendly interface and adequate reporting. Neither is done
    easily as kernel code.</p>
<section class="Ss">
<h2 class="Ss" id="I/O_port_resources"><a class="permalink" href="#I/O_port_resources">I/O
  port resources</a></h2>
<p class="Pp">Device special files created for I/O port resources allow
    <a class="Xr">lseek(2)</a>, <a class="Xr">read(2)</a>,
    <a class="Xr">write(2)</a> and <a class="Xr">ioctl(2)</a> operations to be
    performed on them. The <a class="Xr">read(2)</a> and
    <a class="Xr">write(2)</a> system calls are used to perform input and output
    (resp.) on the port. The amount of data that can be read or written at any
    single time is either 1, 2 or 4 bytes. While the
    <code class="Nm">proto</code> driver does not prevent reading or writing 8
    bytes at a time for some architectures, it should not be assumed that such
    actually produces correct results. The <a class="Xr">lseek(2)</a> system
    call is used to select the port number, relative to the I/O port region
    being represented by the device special file. If, for example, the device
    special file corresponds to an I/O port region from 0x3f8 to 0x3ff
    inclusive, then an offset of 4 given to lseek with a whence value of
    SEEK_SET will target port 0x3fc on the next read or write operation. The
    <a class="Xr">ioctl(2)</a> system call can be used for the
    <code class="Dv">PROTO_IOC_REGION</code> request. This ioctl request returns
    the extend of the resource covered by this device special file. The extend
    is returned in the following structure:</p>
<div class="Bd Pp Li">
<pre>struct proto_ioc_region {
        unsigned long   address;
        unsigned long   size;
};</pre>
</div>
</section>
<section class="Ss">
<h2 class="Ss" id="Memory_mapped_I/O_resources"><a class="permalink" href="#Memory_mapped_I/O_resources">Memory
  mapped I/O resources</a></h2>
<p class="Pp">The device special files created for memory mapped I/O resources
    behave in the same way as those created for I/O port resources.
    Additionally, device special files for memory mapped I/O resources allow the
    memory to be mapped into the process' address space using
    <a class="Xr">mmap(2)</a>. Reads and writes to the memory address returned
    by <a class="Xr">mmap(2)</a> go directly to the hardware. As such the use of
    <a class="Xr">read(2)</a> and <a class="Xr">write(2)</a> can be avoided,
    reducing the access overhead significantly. Alignment and access width
    constraints put forth by the underlying device apply. Also, make sure the
    compiler does not optimize memory accesses away or has them coalesced into
    bigger accesses.</p>
</section>
<section class="Ss">
<h2 class="Ss" id="DMA_pseudo_resource"><a class="permalink" href="#DMA_pseudo_resource">DMA
  pseudo resource</a></h2>
<p class="Pp">A device special file named <span class="Pa">busdma</span> is
    created for the purpose of doing DMA. It only supports
    <a class="Xr">ioctl(2)</a> and only for the
    <code class="Dv">PROTO_IOC_BUSDMA</code> request. This device special file
    does not support <a class="Xr">read(2)</a> nor <a class="Xr">write(2)</a>.
    The <code class="Dv">PROTO_IOC_BUSDMA</code> request has an argument that is
    both in and out and is defined as follows:</p>
<div class="Bd Pp Li">
<pre>struct proto_ioc_busdma {
        unsigned int    request;
        unsigned long   key;
        union {
                struct {
                        unsigned long   align;
                        unsigned long   bndry;
                        unsigned long   maxaddr;
                        unsigned long   maxsz;
                        unsigned long   maxsegsz;
                        unsigned int    nsegs;
                        unsigned int    datarate;
                        unsigned int    flags;
                } tag;
                struct {
                        unsigned long   tag;
                        unsigned int    flags;
                        unsigned long   virt_addr;
                        unsigned long   virt_size;
                        unsigned int    phys_nsegs;
                        unsigned long   phys_addr;
                        unsigned long   bus_addr;
                        unsigned int    bus_nsegs;
                } md;
                struct {
                        unsigned int    op;
                        unsigned long   base;
                        unsigned long   size;
                } sync;
        } u;
        unsigned long   result;
};</pre>
</div>
The <var class="Va">request</var> field is used to specify which DMA operation
  is to be performed. The <var class="Va">key</var> field is used to specify
  which object the operation applies to. An object is either a tag or a memory
  descriptor (md). The following DMA operations are defined:
<dl class="Bl-tag">
  <dt>PROTO_IOC_BUSDMA_TAG_CREATE</dt>
  <dd>Create a root tag. The <var class="Va">result</var> field is set on output
      with the key of the DMA tag. The tag is created with the constraints given
      by the <var class="Va">tag</var> sub-structure. These constraints
      correspond roughly to those that can be given to the
      <a class="Xr">bus_dma_tag_create(9)</a> function.</dd>
  <dt>PROTO_IOC_BUSDMA_TAG_DERIVE</dt>
  <dd>Create a derived tag. The <var class="Va">key</var> field is used to
      identify the parent tag from which to derive the new tag. The key of the
      derived tag is returned in the <var class="Va">result</var> field. The
      derived tag combines the constraints of the parent tag with those given by
      the <var class="Va">tag</var> sub-structure. The combined constraints are
      written back to the <var class="Va">tag</var> sub-structure on
    return.</dd>
  <dt>PROTO_IOC_BUSDMA_TAG_DESTROY</dt>
  <dd>Destroy a root or derived tag previously created. The
      <var class="Va">key</var> field specifies the tag to destroy. A tag can
      only be destroyed when not referenced anymore. This means that derived
      tags that have this tag as a parent and memory descriptors created from
      this tag must be destroyed first.</dd>
  <dt>PROTO_IOC_BUSDMA_MEM_ALLOC</dt>
  <dd>Allocate memory that satisfies the constraints put forth by the tag given
      in the <var class="Va">tag</var> field of the <var class="Va">md</var>
      sub-structure. The key of the memory descriptor for this memory is
      returned in the <var class="Va">result</var> field. The
      <var class="Va">md</var> sub-structure is filled on return with details of
      the allocation. The kernel virtual address and the size of the allocated
      memory are returned in the <var class="Va">virt_addr</var> and
      <var class="Va">virt_size</var> fields. The number of contiguous physical
      memory segments and the address of the first segment are returned in the
      <var class="Va">phys_nsegs</var> and <var class="Va">phys_addr</var>
      fields. Allocated memory is automatically loaded and thus mapped into bus
      space. The number of bus segments and the address of the first segment are
      returned in the <var class="Va">bus_nsegs</var> and
      <var class="Va">bus_addr</var> fields. The behaviour of this operation
      banks heavily on how <a class="Xr">bus_dmamem_alloc(9)</a> is implemented,
      which means that memory is currently always allocated as a single
      contiguous region of physical memory. In practice this also tends to give
      a single contiguous region in bus space. This may change over time.</dd>
  <dt>PROTO_IOC_BUSDMA_MEM_FREE</dt>
  <dd>Free previously allocated memory and destroy the memory descriptor. The
      <code class="Nm">proto</code> driver is not in a position to track whether
      the memory has been mapped in the process' address space, so the
      application is responsible for unmapping the memory before it is freed.
      The <code class="Nm">proto</code> driver also cannot protect against the
      hardware writing to or reading from the memory, even after it has been
      freed. When the memory is reused for other purposes it can be corrupted or
      cause the hardware to behave in unpredictable ways when DMA has not
      stopped completely before freeing.</dd>
  <dt>PROTO_IOC_BUSDMA_MD_CREATE</dt>
  <dd>Create an empty memory descriptor with the tag specified in the
      <var class="Va">tag</var> field of the <var class="Va">md</var>
      sub-structure. The key of the memory descriptor is returned in the
      <var class="Va">result</var> field.</dd>
  <dt>PROTO_IOC_BUSDMA_MD_DESTROY</dt>
  <dd>Destroy the previously created memory descriptor specified by the
      <var class="Va">key</var> field. When the memory descriptor is still
      loaded, it is unloaded first.</dd>
  <dt>PROTO_IOC_BUSDMA_MD_LOAD</dt>
  <dd>Load a contiguous region of memory in the memory descriptor specified by
      the <var class="Va">key</var> field. The size and address in the process'
      virtual address space are specified by the <var class="Va">virt_size</var>
      and <var class="Va">virt_addr</var> fields. On return, the
      <var class="Va">md</var> sub-structure contains the result of the
      operation. The number of physical segments and the address of the first
      segment is returned in the <var class="Va">phys_nsegs</var> and
      <var class="Va">phys_addr</var> fields. The number of bus space segments
      and the address of the first segment in bus space is returned in the
      <var class="Va">bus_nsegs</var> and <var class="Va">bus_addr</var>
    fields.</dd>
  <dt>PROTO_IOC_BUSDMA_MD_UNLOAD</dt>
  <dd>Unload the memory descriptor specified by the <var class="Va">key</var>
      field.</dd>
  <dt>PROTO_IOC_BUSDMA_SYNC</dt>
  <dd>Guarantee that all hardware components have a coherent view of the memory
      tracked by the memory descriptor, specified by the
      <var class="Va">key</var> field. A sub-section of the memory can be
      targeted by specifying the relative offset and size of the memory to make
      coherent. The offset and size are given by the <var class="Va">base</var>
      and <var class="Va">size</var> fields of the <var class="Va">sync</var>
      sub-structure. The <var class="Va">op</var> field holds the sync operation
      to be performed. This is similar to the
      <a class="Xr">bus_dmamap_sync(9)</a> function.</dd>
</dl>
</section>
<section class="Ss">
<h2 class="Ss" id="PCI_configuration_space"><a class="permalink" href="#PCI_configuration_space">PCI
  configuration space</a></h2>
<p class="Pp">Access to PCI configuration space is possible through the
    <span class="Pa">pcicfg</span> device special file. The device special file
    supports <a class="Xr">lseek(2)</a>, <a class="Xr">read(2)</a> and
    <a class="Xr">write(2)</a>. Usage is the asme as for I/O port resources.</p>
</section>
</section>
<section class="Sh">
<h1 class="Sh" id="FILES"><a class="permalink" href="#FILES">FILES</a></h1>
<p class="Pp">All device special files corresponding to a PCI device are located
    under
    <span class="Pa">/dev/proto/pci&lt;d&gt;:&lt;b&gt;:&lt;s&gt;:&lt;f&gt;</span>
    with <span class="Pa">pci&lt;d&gt;:&lt;b&gt;:&lt;s&gt;:&lt;f&gt;</span>
    representing the location of the PCI device in the PCI hierarchy. A PCI
    location includes:</p>
<p class="Pp"></p>
<div class="Bd-indent">
<dl class="Bl-tag Bl-compact">
  <dt>&lt;d&gt;</dt>
  <dd>The PCI domain number</dd>
  <dt>&lt;b&gt;</dt>
  <dd>The PCI bus number</dd>
  <dt>&lt;s&gt;</dt>
  <dd>The PCI slot or device number</dd>
  <dt>&lt;f&gt;</dt>
  <dd>The PCI function number</dd>
</dl>
</div>
<p class="Pp">Every PCI device has a device special file called
    <span class="Pa">pcicfg</span>. This device special file gives access to the
    PCI configuration space. A device special file called
    <span class="Pa">busdma</span> is also created. This device special file
    provides the interfaces needed for doing DMA. For each valid base address
    register (BAR), a device special file is created that contains the BAR
    offset and the resource type. A resource type can be either
    <span class="Pa">io</span> or <span class="Pa">mem</span> representing I/O
    port or memory mapped I/O space (resp.)</p>
<p class="Pp">ISA devices do not have a location. Instead, they are identified
    by the first I/O port address or first memory mapped I/O address.
    Consequently, all device special files corresponding to an ISA device are
    located under <span class="Pa">/dev/proto/isa:&lt;addr&gt;</span> with
    <span class="Pa">addr</span> the address in hexadecimal notation. For each
    I/O port or memory mapped I/O address, a device special file is created that
    contains the resource identification used by the kernel and the resource
    type. The resource type can be either <span class="Pa">io</span> or
    <span class="Pa">mem</span> representing I/O port or memory mapped I/O space
    (resp.) When the device has a DMA channel assigned to it, a device special
    file with the name <span class="Pa">busdma</span> is created as well. This
    device special file provides the interfaces needed for doing DMA.</p>
<p class="Pp">If the ISA device is not a Plug-and-Play device nor present in the
    ACPI device tree, it must have the appropriate hints so that the kernel can
    reserve the resources for it.</p>
</section>
<section class="Sh">
<h1 class="Sh" id="EXAMPLES"><a class="permalink" href="#EXAMPLES">EXAMPLES</a></h1>
<p class="Pp">A single function PCI device in domain 0, on bus 1, in slot 2 and
    having a single memory mapped I/O region will have the following device
    special files:</p>
<p class="Pp"></p>
<div class="Bd-indent">
<dl class="Bl-tag Bl-compact">
  <dt><span class="Pa">/dev/proto/pci0:1:2:0/10.mem</span></dt>
  <dd style="width: auto;">&#x00A0;</dd>
  <dt><span class="Pa">/dev/proto/pci0:1:2:0/pcicfg</span></dt>
  <dd style="width: auto;">&#x00A0;</dd>
</dl>
</div>
<p class="Pp">A legacy floppy controller will have the following device
  files:</p>
<p class="Pp"></p>
<div class="Bd-indent">
<dl class="Bl-tag Bl-compact">
  <dt><span class="Pa">/dev/proto/isa:0x3f0/00.io</span></dt>
  <dd style="width: auto;">&#x00A0;</dd>
  <dt><span class="Pa">/dev/proto/isa:0x3f0/01.io</span></dt>
  <dd style="width: auto;">&#x00A0;</dd>
  <dt><span class="Pa">/dev/proto/isa:0x3f0/busdma</span></dt>
  <dd style="width: auto;">&#x00A0;</dd>
</dl>
</div>
</section>
<section class="Sh">
<h1 class="Sh" id="SEE_ALSO"><a class="permalink" href="#SEE_ALSO">SEE
  ALSO</a></h1>
<p class="Pp"><a class="Xr">ioctl(2)</a>, <a class="Xr">lseek(2)</a>,
    <a class="Xr">mmap(2)</a>, <a class="Xr">read(2)</a>,
    <a class="Xr">write(2)</a>, <a class="Xr">bus_dma_tag_create(9)</a>,
    <a class="Xr">bus_dmamap_sync(9)</a>,
  <a class="Xr">bus_dmamem_alloc(9)</a></p>
</section>
<section class="Sh">
<h1 class="Sh" id="AUTHORS"><a class="permalink" href="#AUTHORS">AUTHORS</a></h1>
<p class="Pp">The <code class="Nm">proto</code> device driver and this manual
    page were written by <span class="An">Marcel Moolenaar</span>
    &lt;<a class="Mt" href="mailto:marcel@xcllnt.net">marcel@xcllnt.net</a>&gt;.</p>
</section>
<section class="Sh">
<h1 class="Sh" id="SECURITY_CONSIDERATIONS"><a class="permalink" href="#SECURITY_CONSIDERATIONS">SECURITY
  CONSIDERATIONS</a></h1>
<p class="Pp">Because programs have direct access to the hardware, the
    <code class="Nm">proto</code> driver is inherently insecure. It is not
    advisable to use this driver on a production machine.</p>
</section>
<section class="Sh">
<h1 class="Sh" id="MISSING_FUNCTIONALITY"><a class="permalink" href="#MISSING_FUNCTIONALITY">MISSING
  FUNCTIONALITY</a></h1>
<p class="Pp">The <code class="Nm">proto</code> driver does not fully support
    memory descriptors that need multiple physical memory segments or multiple
    bus space segments. At the very least, an operation is needed on the DMA
    pseudo resource for the application to obtain all segments.</p>
<p class="Pp">The <code class="Nm">proto</code> driver does not yet support
    interrupts. Since interrupts cannot be handled by the driver itself, they
    must be converted into signals and delivered to the program that has
    registered for interrupts. A satisfactory mechanism for keeping the
    interrupt masked during the signal handling is still being worked out.</p>
<p class="Pp">DMA support for devices other than busmaster devices is not
    present yet. The details of how a program is to interact with the DMA
    controller still need to be fleshed out.</p>
</section>
</div>
<table class="foot">
  <tr>
    <td class="foot-date">August 7, 2015</td>
    <td class="foot-os">FreeBSD 15.0</td>
  </tr>
</table>