📄 drivertut6.html
字号:
Read/write ordering is not the same as cache coherency, which is handled
separately and is not an issue.
</p><p>
The Alpha architecture also contains a write buffer (as do many
high-performance RISC CPUs, including the MIPS R3000).
This write buffer can coalesce multiple writes to identical
or adjacent addresses into a single write, effectively losing earlier
write requests.
Similarly, multiple reads to the same identical or adjacent addresses
can be coalesced into a single read.
</p><p>
This coalescing has implications for multiprocessor systems, as well as systems
with off-board I/O or DMA engines that can read or modify memory asynchronously
or that can require multiple writes to actually issue multiple data
items.
The
<tt>mb</tt>
(memory barrier) interface guarantees ordering of operations.
The
<tt>mb</tt>
interface is derived from the
<tt>MB</tt>
instruction, which is described in the
<cite>Alpha Architecture Reference Manual</cite>.
</p><p>
The
<tt>mb</tt>
interface is a superset of the
<tt>wbflush</tt>
interface that ULTRIX drivers use.
For compatibility,
<tt>wbflush</tt>
is aliased to
<tt>mb</tt>
on Digital UNIX Alpha systems.
</p><p>
</p><p>
You call
<tt>mb</tt>
in a device driver under the following circumstances:
</p><ul>
<p></p><li>
To force a barrier between load/store operations
<p></p></li><li>
After the CPU has prepared a data buffer in memory and before the device
driver
tries to perform a DMA out of the buffer
<p></p></li><li>
Before attempting to read any device CSRs after taking a device
interrupt
<p></p></li><li>
Between writes
</li></ul><p>
Each of these is briefly discussed in the following sections.
</p><blockquote><p align="center"><font size="+1"><strong>Note</strong></font></p><p>
</p></blockquote>
<p>
Device drivers and the Digital UNIX operating system are the primary
users of the
<tt>mb</tt>
interface.
However, some user programs, such as a graphics program that directly
maps the frame buffer and manipulates registers, might need to call
<tt>mb</tt>.
The
Digital UNIX operating system does not provide a C library interface for
<tt>mb</tt>.
User programs that require use of
<tt>mb</tt>
should use the following
<tt>asm</tt>
construct:
</p><p>
</p><pre>#include <c_asm.h>
asm ("mb");
</pre>
<p>
</p><p>
<a name="ForceBarLoadStore"></a>
</p><p></p><hr><p align="center">
<a href="http://h30097.www3.hp.com/docs/base_doc/DOCUMENTATION/HTML/Digital_UNIX_Bookshelf.html"><img src="drivertut6_files/BOOKSHELF.GIF" alt="[Return to Library]" border="0"></a>
<a href="http://h30097.www3.hp.com/docs/base_doc/DOCUMENTATION/HTML/AA-PUBVD-TE_html/TOC.html"><img src="drivertut6_files/TOC.GIF" alt="[Contents]" border="0"></a>
<a href="#CPUandBusIssues"><img src="drivertut6_files/REW.GIF" alt="[Previous Chapter]" border="0"></a>
<a href="#MemoryBarriers"><img src="drivertut6_files/PREV.GIF" alt="[Previous Section]" border="0"></a>
<a href="#AfterCPUPrepBuffer"><img src="drivertut6_files/NEXT.GIF" alt="[Next Section]" border="0"></a>
<a href="http://h30097.www3.hp.com/docs/base_doc/DOCUMENTATION/HTML/AA-PUBVD-TE_html/drivertut7.html"><img src="drivertut6_files/FF.GIF" alt="[Next Chapter]" border="0"></a>
<a href="http://h30097.www3.hp.com/docs/base_doc/DOCUMENTATION/HTML/AA-PUBVD-TE_html/INDEX.html"><img src="drivertut6_files/INDEX.GIF" alt="[Index]" border="0"></a>
<a href="http://h30097.www3.hp.com/docs/base_doc/DOCUMENTATION/HTML/HELP.html"><img src="drivertut6_files/HELP.GIF" alt="[Help]" border="0"></a>
</p><p></p><hr><p>
</p><h3>
3.1.6.1牋牋Forcing a Barrier Between Load/Store Operations
</h3>
<p>
You can call the
<tt>mb</tt>
interface to force a barrier between load/store operations.
This call ensures that all previous load/store operations access memory or I/O
space before any subsequent load/store operations.
The following call to
<tt>mb</tt>
ensures that the first register is physically written before the load
attempts to read the second register.
The call assumes that
device
is
an I/O handle that you can use to reference a device register or memory
located in bus address space (either I/O space or memory space).
You can perform standard C mathematical operations (addition and
subtraction only) on the I/O handle.
For example, this code fragment adds the I/O handle and general register 1
and general register 2 in the calls to
<tt>write_io_port</tt>
and
<tt>read_io_port</tt>.
</p><p>
</p><pre><br>.<br>.<br>.<br>
#define csr 0 /* Command/Status register */
#define reg1 8 /* General register 1 */
#define reg2 16 /* General register 2 */
io_handle_t device;
<br>.<br>.<br>.<br>
write_io_port(device + reg1, 4, 0, value); <a name="co_id_17_rtn_1"></a><a href="#co_id_17_1"><strong>[1]</strong></a>
mb (); <a name="co_id_17_rtn_2"></a><a href="#co_id_17_2"><strong>[2]</strong></a>
next_value = read_io_port(device + reg2, 4, 0); <a name="co_id_17_rtn_3"></a><a href="#co_id_17_3"><strong>[3]</strong></a>
<br>.<br>.<br>.<br>
</pre>
<p>
</p><ol>
<p></p><li>
<a name="co_id_17_1"></a>
Writes the first value to general register 1 by calling the
<tt>write_io_port</tt>
interface.
See
<a href="http://h30097.www3.hp.com/docs/base_doc/DOCUMENTATION/HTML/AA-PUBVD-TE_html/drivertut11.html#probeReadandWriteData">Section 7.1.9</a>
for a detailed discussion of
<tt>write_io_port</tt>.
<a href="#co_id_17_rtn_1">[Return to example]</a>
<p></p></li><li>
<a name="co_id_17_2"></a>
Calls the
<tt>mb</tt>
interface to ensure that the write of the value is completed.
<a href="#co_id_17_rtn_2">[Return to example]</a>
<p></p></li><li>
<a name="co_id_17_3"></a>
Reads the new value from general register 2 by calling the
<tt>read_io_port</tt>
interface.
See
<a href="http://h30097.www3.hp.com/docs/base_doc/DOCUMENTATION/HTML/AA-PUBVD-TE_html/drivertut11.html#probeReadandWriteData">Section 7.1.9</a>
for a detailed discussion of
<tt>read_io_port</tt>.
<a href="#co_id_17_rtn_3">[Return to example]</a>
</li></ol><p>
<a name="AfterCPUPrepBuffer"></a>
</p><p></p><hr><p align="center">
<a href="http://h30097.www3.hp.com/docs/base_doc/DOCUMENTATION/HTML/Digital_UNIX_Bookshelf.html"><img src="drivertut6_files/BOOKSHELF.GIF" alt="[Return to Library]" border="0"></a>
<a href="http://h30097.www3.hp.com/docs/base_doc/DOCUMENTATION/HTML/AA-PUBVD-TE_html/TOC.html"><img src="drivertut6_files/TOC.GIF" alt="[Contents]" border="0"></a>
<a href="#CPUandBusIssues"><img src="drivertut6_files/REW.GIF" alt="[Previous Chapter]" border="0"></a>
<a href="#ForceBarLoadStore"><img src="drivertut6_files/PREV.GIF" alt="[Previous Section]" border="0"></a>
<a href="#BeforeReadAnyCSR"><img src="drivertut6_files/NEXT.GIF" alt="[Next Section]" border="0"></a>
<a href="http://h30097.www3.hp.com/docs/base_doc/DOCUMENTATION/HTML/AA-PUBVD-TE_html/drivertut7.html"><img src="drivertut6_files/FF.GIF" alt="[Next Chapter]" border="0"></a>
<a href="http://h30097.www3.hp.com/docs/base_doc/DOCUMENTATION/HTML/AA-PUBVD-TE_html/INDEX.html"><img src="drivertut6_files/INDEX.GIF" alt="[Index]" border="0"></a>
<a href="http://h30097.www3.hp.com/docs/base_doc/DOCUMENTATION/HTML/HELP.html"><img src="drivertut6_files/HELP.GIF" alt="[Help]" border="0"></a>
</p><p></p><hr><p>
</p><h3>
3.1.6.2牋牋After the CPU Has Prepared a Data Buffer in Memory
</h3>
<p>
You call the
<tt>mb</tt>
interface after the CPU has prepared a data buffer in memory and before
the device driver tries to perform a DMA out of the buffer.
You also call
<tt>mb</tt>
in device drivers that perform a DMA into memory and before using the
data in the DMA buffer.
The following calls to
<tt>mb</tt>
ensure that data is available (out of memory
pipelines/write buffers) and that the data cache is coherent.
The call assumes that
device
is
an I/O handle that you can use to reference a device register or memory
located in bus address space (either I/O space or memory space).
You can perform standard C mathematical operations (addition and
subtraction only) on the I/O handle.
For example, this code fragment adds the I/O handle and the
command/status register in the call to
<tt>read_io_port</tt>.
</p><p>
</p><pre><br>.<br>.<br>.<br>
#define csr 0 /* Command/Status register */
#define reg1 8 /* General register 1 */
#define reg2 16 /* General register 2 */
io_handle_t device;
<br>.<br>.<br>.<br>
bcopy (data, dma_buf, nbytes); <a name="co_id_18_rtn_1"></a><a href="#co_id_18_1"><strong>[1]</strong></a>
mb (); <a name="co_id_18_rtn_2"></a><a href="#co_id_18_2"><strong>[2]</strong></a>
write_io_port(device + csr, 4, 0, START_DMA); <a name="co_id_18_rtn_3"></a><a href="#co_id_18_3"><strong>[3]</strong></a>
/* or */ <a name="co_id_18_rtn_4"></a><a href="#co_id_18_4"><strong>[4]</strong></a>
if (read_io_port(device + csr, 4, 0) | DMA_DONE) {
mb ();
bcopy (dma_buf, data, nbytes);
}
<br>.<br>.<br>.<br>
</pre>
<p>
</p><ol>
<p></p><li>
<a name="co_id_18_1"></a>
Writes the data into the DMA buffer.
<a href="#co_id_18_rtn_1">[Return to example]</a>
<p></p></li><li>
<a name="co_id_18_2"></a>
Calls the
<tt>mb</tt>
interface to ensure that the write of the data is completed.
<a href="#co_id_18_rtn_2">[Return to example]</a>
<p></p></li><li>
<a name="co_id_18_3"></a>
Issues the start command to the device.
<a href="#co_id_18_rtn_3">[Return to example]</a>
<p></p></li><li>
<a name="co_id_18_4"></a>
This sequence of code presents another way to accomplish
the same thing as the previous code.
See
<a href="http://h30097.www3.hp.com/docs/base_doc/DOCUMENTATION/HTML/AA-PUBVD-TE_html/drivertut11.html#probeReadandWriteData">Section 7.1.9</a>
for a detailed discussion of
<tt>read_io_port</tt>.
<br>
<p>
If the DMA is finished:
</p><ul>
<p></p><li>
Calls the
<tt>mb</tt>
interface to ensure that the buffer is correct.
<p></p></li><li>
Gets the data from the DMA buffer.
</li></ul><p>
<a href="#co_id_18_rtn_4">[Return to example]</a>
</p></li></ol><p>
<a name="BeforeReadAnyCSR"></a>
</p><p></p><hr><p align="center">
<a href="http://h30097.www3.hp.com/docs/base_doc/DOCUMENTATION/HTML/Digital_UNIX_Bookshelf.html"><img src="drivertut6_files/BOOKSHELF.GIF" alt="[Return to Library]" border="0"></a>
<a href="http://h30097.www3.hp.com/docs/base_doc/DOCUMENTATION/HTML/AA-PUBVD-TE_html/TOC.html"><img src="drivertut6_files/TOC.GIF" alt="[Contents]" border="0"></a>
<a href="#CPUandBusIssues"><img src="drivertut6_files/REW.GIF" alt="[Previous Chapter]" border="0"></a>
<a href="#AfterCPUPrepBuffer"><img src="drivertut6_files/PREV.GIF" alt="[Previous Section]" border="0"></a>
<a href="#BetweenWrites"><img src="drivertut6_files/NEXT.GIF" alt="[Next Section]" border="0"></a>
<a href="http://h30097.www3.hp.com/docs/base_doc/DOCUMENTATION/HTML/AA-PUBVD-TE_html/drivertut7.html"><img src="drivertut6_files/FF.GIF" alt="[Next Chapter]" border="0"></a>
<a href="http://h30097.www3.hp.com/docs/base_doc/DOCUMENTATION/HTML/AA-PUBVD-TE_html/INDEX.html"><img src="drivertut6_files/INDEX.GIF" alt="[Index]" border="0"></a>
<a href="http://h30097.www3.hp.com/docs/base_doc/DOCUMENTATION/HTML/HELP.html"><img src="drivertut6_files/HELP.GIF" alt="[Help]" border="0"></a>
</p><p></p><hr><p>
</p><h3>
3.1.6.3牋牋Before Attempting to Read Any Device CSRs
</h3>
<p>
You call the
<tt>mb</tt>
interface before attempting to read any device CSRs after taking a
device interrupt.
The call assumes that
device
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -