Added <!-- Local Variables: mode: sgml sgml-declaration: "../chapter.decl" sgml-indent-data: t sgml-omittag: nil sgml-shorttag: nil sgml-always-quote-attributes: t sgml-minimize-attributes: max sgml-parent-document: ("../handbook.sgml" "part" "chapter") End: --> to the bottom of each chapter.sgml file so that Emacs can do the right thing.
1666 lines
51 KiB
Text
1666 lines
51 KiB
Text
|
|
<chapter id="internals">
|
|
<title>FreeBSD Internals</title>
|
|
|
|
|
|
<sect1 id="booting">
|
|
<title>The FreeBSD Booting Process</title>
|
|
|
|
<para><emphasis>Contributed by &a.phk;. v1.1, April
|
|
26th.</emphasis></para>
|
|
|
|
<para>Booting FreeBSD is essentially a three step process: load the
|
|
kernel, determine the root filesystem and initialize user-land
|
|
things. This leads to some interesting possibilities shown
|
|
below.</para>
|
|
|
|
|
|
<sect2>
|
|
<title>Loading a kernel</title>
|
|
|
|
<para>We presently have three basic mechanisms for loading the
|
|
kernel as described below: they all pass some information to the
|
|
kernel to help the kernel decide what to do next.</para>
|
|
|
|
|
|
<variablelist>
|
|
<varlistentry><term>Biosboot</term>
|
|
<listitem>
|
|
<para>Biosboot is our “bootblocks”. It consists of two
|
|
files which will be installed in the first 8Kbytes of the
|
|
floppy or hard-disk slice to be booted from.</para>
|
|
|
|
<para>Biosboot can load a kernel from a FreeBSD
|
|
filesystem.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry><term>Dosboot</term>
|
|
|
|
<listitem>
|
|
<para>Dosboot was written by DI. Christian Gusenbauer, and
|
|
is unfortunately at this time one of the few pieces of
|
|
code that will not compile under FreeBSD itself because it
|
|
is written for Microsoft compilers.</para>
|
|
|
|
<para>Dosboot will boot the kernel from a MS-DOS file or
|
|
from a FreeBSD filesystem partition on the disk. It
|
|
attempts to negotiate with the various and strange kinds
|
|
of memory manglers that lurk in high memory on MS/DOS
|
|
systems and usually wins them for its case.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry><term>Netboot</term>
|
|
|
|
<listitem>
|
|
<para>Netboot will try to find a supported Ethernet card,
|
|
and use BOOTP, TFTP and NFS to find a kernel file to
|
|
boot.</para>
|
|
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
|
|
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Determine the root filesystem</title>
|
|
|
|
<para>Once the kernel is loaded and the boot-code jumps to it, the
|
|
kernel will initialize itself, trying to determine what hardware
|
|
is present and so on; it then needs to find a root
|
|
filesystem.</para>
|
|
|
|
<para>Presently we support the following types of root
|
|
filesystems:</para>
|
|
|
|
|
|
<variablelist>
|
|
<varlistentry><term>UFS</term>
|
|
<listitem>
|
|
<para>This is the most normal type of root filesystem. It
|
|
can reside on a floppy or on hard disk.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry><term>MSDOS</term>
|
|
|
|
<listitem>
|
|
<para>While this is technically possible, it is not
|
|
particular useful because of the <acronym>FAT</acronym> filesystem's
|
|
inability to deal with links, device nodes and other such
|
|
“UNIXisms”.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry><term>MFS</term>
|
|
|
|
<listitem>
|
|
<para>This is actually a UFS filesystem which has been
|
|
compiled into the kernel. That means that the kernel does
|
|
not really need any hard disks, floppies or other hardware
|
|
to function.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry><term>CD9660</term>
|
|
|
|
<listitem>
|
|
<para>This is for using a CD-ROM as root filesystem.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry><term>NFS</term>
|
|
|
|
<listitem>
|
|
<para>This is for using a fileserver as root filesystem,
|
|
basically making it a diskless machine.</para>
|
|
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
|
|
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Initialize user-land things</title>
|
|
|
|
<para>To get the user-land going, the kernel, when it has finished
|
|
initialization, will create a process with <literal>pid ==
|
|
1</literal> and execute a program on the root filesystem; this
|
|
program is normally <filename>/sbin/init</filename>.</para>
|
|
|
|
<para>You can substitute any program for
|
|
<command>/sbin/init</command>, as long as you keep in mind
|
|
that:</para>
|
|
|
|
<para>there is no stdin/out/err unless you open it yourself. If you
|
|
exit, the machine panics. Signal handling is special for
|
|
<literal>pid == 1</literal>.</para>
|
|
|
|
<para>An example of this is the
|
|
<command>/stand/sysinstall</command> program on the
|
|
installation floppy.</para>
|
|
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Interesting combinations</title>
|
|
|
|
<para>Boot a kernel with a MFS in it with a special
|
|
<filename>/sbin/init</filename> which...</para>
|
|
|
|
<variablelist>
|
|
<varlistentry><term>A — Using DOS</term>
|
|
<listitem>
|
|
|
|
<itemizedlist>
|
|
|
|
<listitem>
|
|
<para>mounts your <filename>C:</filename> as
|
|
<filename>/C:</filename></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Attaches <filename>C:/freebsd.fs</filename> on
|
|
<filename>/dev/vn0</filename></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>mounts <filename>/dev/vn0</filename> as
|
|
<filename>/rootfs</filename></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>makes symlinks<!-- <br> -->
|
|
<filename>/rootfs/bin</filename> ->
|
|
<filename>/bin</filename><!-- <br> -->
|
|
<filename>/rootfs/etc</filename> ->
|
|
<filename>/etc</filename><!-- <br> -->
|
|
<filename>/rootfs/sbin</filename> ->
|
|
<filename>/sbin</filename><!-- <br> --> (etc...)<!--
|
|
<br> --></para>
|
|
</listitem>
|
|
|
|
</itemizedlist>
|
|
|
|
|
|
<para>Now you are running FreeBSD without repartitioning
|
|
your hard disk...</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry><term>B — Using NFS</term>
|
|
|
|
<listitem>
|
|
<para>NFS mounts your
|
|
<filename>server:~you/FreeBSD</filename> as
|
|
<filename>/nfs</filename>, chroots to
|
|
<filename>/nfs</filename> and executes
|
|
<filename>/sbin/init</filename> there</para>
|
|
|
|
<para>Now you are running FreeBSD diskless, even though you
|
|
do not control the NFS server...</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry><term>C — Start an X-server</term>
|
|
|
|
<listitem>
|
|
<para>Now you have an X-terminal, which is better than that
|
|
dingy X-under-windows-so-slow-you-can-see-what-it-does
|
|
thing that your boss insist is better than forking out
|
|
money on hardware.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry><term>D — Using a tape</term>
|
|
|
|
<listitem>
|
|
<para>Takes a copy of <filename>/dev/rwd0</filename> and
|
|
writes it to a remote tape station or fileserver.</para>
|
|
|
|
<para>Now you finally get that backup you should have made a
|
|
year ago...</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry><term>E — Acts as a firewall/web-server/what do I
|
|
know...</term>
|
|
|
|
<listitem>
|
|
<para>This is particularly interesting since you can boot
|
|
from a write- protected floppy, but still write to your
|
|
root filesystem...</para>
|
|
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1 id="memoryuse">
|
|
<title>PC Memory Utilization</title>
|
|
|
|
<para><emphasis>Contributed by &a.joerg;.<!-- <br> --> 16 Apr
|
|
1995.</emphasis></para>
|
|
|
|
<para><emphasis>A short description of how FreeBSD uses memory on the
|
|
i386 platform</emphasis></para>
|
|
|
|
<para>The boot sector will be loaded at <literal>0:0x7c00</literal>,
|
|
and relocates itself immediately to <literal>0x7c0:0</literal>.
|
|
(This is nothing magic, just an adjustment for the
|
|
<literal>%cs</literal> selector, done by an <literal>ljmp</literal>.)</para>
|
|
|
|
<para>It then loads the first 15 sectors at <literal>0x10000</literal>
|
|
(segment <makevar>BOOTSEG</makevar> in the biosboot Makefile), and sets up the stack to
|
|
work below <literal>0x1fff0</literal>. After this, it jumps to the
|
|
entry of boot2 within that code. I.e., it jumps over itself and the
|
|
(dummy) partition table, and it is going to adjust the %cs
|
|
selector—we are still in 16-bit mode there.</para>
|
|
|
|
<para>boot2 asks for the boot file, and examines the
|
|
<filename>a.out</filename> header. It masks the file entry point
|
|
(usually <literal>0xf0100000</literal>) by
|
|
<literal>0x00ffffff</literal>, and loads the file there. Hence the
|
|
usual load point is 1 MB (<literal>0x00100000</literal>). During
|
|
load, the boot code toggles back and forth between real and
|
|
protected mode, to use the BIOS in real mode.</para>
|
|
|
|
<para>The boot code itself uses segment selectors
|
|
<literal>0x18</literal> and <literal>0x20</literal> for
|
|
<literal>%cs</literal> and <literal>%ds/%es</literal> in
|
|
protected mode, and <literal>0x28</literal> to jump back into real
|
|
mode. The kernel is finally started with <literal>%cs</literal> <literal>0x08</literal> and
|
|
<literal>%ds/%es/%ss</literal> <literal>0x10</literal>, which
|
|
refer to dummy descriptors covering the entire address space.</para>
|
|
|
|
<para>The kernel will be started at its load point. Since it has been
|
|
linked for another (high) address, it will have to execute PIC until
|
|
the page table and page directory stuff is setup properly, at which
|
|
point paging will be enabled and the kernel will finally run at the
|
|
address for which it was linked.</para>
|
|
|
|
<para><emphasis>Contributed by &a.davidg;.<!-- <br> --> 16 Apr
|
|
1995.</emphasis></para>
|
|
|
|
<para>The physical pages immediately following the kernel BSS contain
|
|
proc0's page directory, page tables, and upages. Some time later
|
|
when the VM system is initialized, the physical memory between
|
|
<literal>0x1000-0x9ffff</literal> and the physical memory after the
|
|
kernel (text+data+bss+proc0 stuff+other misc) is made available in
|
|
the form of general VM pages and added to the global free page
|
|
list.</para>
|
|
|
|
</sect1>
|
|
|
|
<sect1 id="dma">
|
|
<title>DMA: What it Is and How it Works</title>
|
|
|
|
<para><emphasis>Copyright © 1995,1997 &a.uhclem;, All Rights
|
|
Reserved.<!-- <br> --> 10 December 1996. Last Update 8 October
|
|
1997.</emphasis></para>
|
|
|
|
<para>Direct Memory Access (DMA) is a method of allowing data to be
|
|
moved from one location to another in a computer without
|
|
intervention from the central processor (CPU).</para>
|
|
|
|
<para>The way that the DMA function is implemented varies between
|
|
computer architectures, so this discussion will limit itself to the
|
|
implementation and workings of the DMA subsystem on the IBM Personal
|
|
Computer (PC), the IBM PC/AT and all of its successors and
|
|
clones.</para>
|
|
|
|
<para>The PC DMA subsystem is based on the Intel 8237 DMA controller.
|
|
The 8237 contains four DMA channels that can be programmed
|
|
independently and any one of the channels may be active at any
|
|
moment. These channels are numbered 0, 1, 2 and 3. Starting with
|
|
the PC/AT, IBM added a second 8237 chip, and numbered those channels
|
|
4, 5, 6 and 7.</para>
|
|
|
|
<para>The original DMA controller (0, 1, 2 and 3) moves one byte in
|
|
each transfer. The second DMA controller (4, 5, 6, and 7) moves
|
|
16-bits from two adjacent memory locations in each transfer, with
|
|
the first byte always coming from an even-numbered address. The two
|
|
controllers are identical components and the difference in transfer
|
|
size is caused by the way the second controller is wired into the
|
|
system.</para>
|
|
|
|
<para>The 8237 has two electrical signals for each channel, named DRQ
|
|
and -DACK. There are additional signals with the names HRQ (Hold
|
|
Request), HLDA (Hold Acknowledge), -EOP (End of Process), and the
|
|
bus control signals -MEMR (Memory Read), -MEMW (Memory Write), -IOR
|
|
(I/O Read), and -IOW (I/O Write).</para>
|
|
|
|
<para>The 8237 DMA is known as a “fly-by” DMA controller. This
|
|
means that the data being moved from one location to another does
|
|
not pass through the DMA chip and is not stored in the DMA chip.
|
|
Subsequently, the DMA can only transfer data between an I/O port and
|
|
a memory address, but not between two I/O ports or two memory
|
|
locations.</para>
|
|
|
|
<note>
|
|
<para>The 8237 does allow two channels to be connected together to
|
|
allow memory-to-memory DMA operations in a
|
|
non-“fly-by” mode, but nobody in the PC industry uses
|
|
this scarce resource this way since it is faster to move data
|
|
between memory locations using the CPU.</para>
|
|
</note>
|
|
|
|
<para>In the PC architecture, each DMA channel is normally activated
|
|
only when the hardware that uses a given DMA channel requests a
|
|
transfer by asserting the DRQ line for that channel.</para>
|
|
|
|
|
|
<sect2>
|
|
<title>A Sample DMA transfer</title>
|
|
|
|
<para>Here is an example of the steps that occur to cause and
|
|
perform a DMA transfer. In this example, the floppy disk
|
|
controller (FDC) has just read a byte from a diskette and wants
|
|
the DMA to place it in memory at location 0x00123456. The process
|
|
begins by the FDC asserting the DRQ2 signal (the DRQ line for DMA
|
|
channel 2) to alert the DMA controller.</para>
|
|
|
|
<para>The DMA controller will note that the DRQ2 signal is asserted.
|
|
The DMA controller will then make sure that DMA channel 2 has been
|
|
programmed and is unmasked (enabled). The DMA controller also
|
|
makes sure that none of the other DMA channels are active or want
|
|
to be active and have a higher priority. Once these checks are
|
|
complete, the DMA asks the CPU to release the bus so that the DMA
|
|
may use the bus. The DMA requests the bus by asserting the HRQ
|
|
signal which goes to the CPU.</para>
|
|
|
|
<para>The CPU detects the HRQ signal, and will complete executing
|
|
the current instruction. Once the processor has reached a state
|
|
where it can release the bus, it will. Now all of the signals
|
|
normally generated by the CPU (-MEMR, -MEMW, -IOR, -IOW and a few
|
|
others) are placed in a tri-stated condition (neither high or low)
|
|
and then the CPU asserts the HLDA signal which tells the DMA
|
|
controller that it is now in charge of the bus.</para>
|
|
|
|
<para>Depending on the processor, the CPU may be able to execute a
|
|
few additional instructions now that it no longer has the bus, but
|
|
the CPU will eventually have to wait when it reaches an
|
|
instruction that must read something from memory that is not in
|
|
the internal processor cache or pipeline.</para>
|
|
|
|
<para>Now that the DMA “is in charge”, the DMA activates its
|
|
-MEMR, -MEMW, -IOR, -IOW output signals, and the address outputs
|
|
from the DMA are set to 0x3456, which will be used to direct the
|
|
byte that is about to transferred to a specific memory
|
|
location.</para>
|
|
|
|
<para>The DMA will then let the device that requested the DMA
|
|
transfer know that the transfer is commencing. This is done by
|
|
asserting the -DACK signal, or in the case of the floppy disk
|
|
controller, -DACK2 is asserted.</para>
|
|
|
|
<para>The floppy disk controller is now responsible for placing the
|
|
byte to be transferred on the bus Data lines. Unless the floppy
|
|
controller needs more time to get the data byte on the bus (and if
|
|
the peripheral does need more time it alerts the DMA via the READY
|
|
signal), the DMA will wait one DMA clock, and then de-assert the
|
|
-MEMW and -IOR signals so that the memory will latch and store the
|
|
byte that was on the bus, and the FDC will know that the byte has
|
|
been transferred.</para>
|
|
|
|
<para>Since the DMA cycle only transfers a single byte at a time,
|
|
the FDC now drops the DRQ2 signal, so the DMA knows that it is no
|
|
longer needed. The DMA will de-assert the -DACK2 signal, so that
|
|
the FDC knows it must stop placing data on the bus.</para>
|
|
|
|
<para>The DMA will now check to see if any of the other DMA channels
|
|
have any work to do. If none of the channels have their DRQ lines
|
|
asserted, the DMA controller has completed its work and will now
|
|
tri-state the -MEMR, -MEMW, -IOR, -IOW and address signals.</para>
|
|
|
|
<para>Finally, the DMA will de-assert the HRQ signal. The CPU sees
|
|
this, and de-asserts the HOLDA signal. Now the CPU activates its
|
|
-MEMR, -MEMW, -IOR, -IOW and address lines, and it resumes
|
|
executing instructions and accessing main memory and the
|
|
peripherals.</para>
|
|
|
|
<para>For a typical floppy disk sector, the above process is
|
|
repeated 512 times, once for each byte. Each time a byte is
|
|
transferred, the address register in the DMA is incremented and
|
|
the counter in the DMA that shows how many bytes are to be
|
|
transferred is decremented.</para>
|
|
|
|
<para>When the counter reaches zero, the DMA asserts the EOP signal,
|
|
which indicates that the counter has reached zero and no more data
|
|
will be transferred until the DMA controller is reprogrammed by
|
|
the CPU. This event is also called the Terminal Count (TC).
|
|
There is only one EOP signal, and since only DMA channel can be
|
|
active at any instant, the DMA channel that is currently active
|
|
must be the DMA channel that just completed its task.</para>
|
|
|
|
<para>If a peripheral wants to generate an interrupt when the
|
|
transfer of a buffer is complete, it can test for its -DACKn
|
|
signal and the EOP signal both being asserted at the same time.
|
|
When that happens, it means the DMA will not transfer any more
|
|
information for that peripheral without intervention by the CPU.
|
|
The peripheral can then assert one of the interrupt signals to get
|
|
the processors' attention. In the PC architecture, the DMA chip
|
|
itself is not capable of generating an interrupt. The peripheral
|
|
and its associated hardware is responsible for generating any
|
|
interrupt that occurs. Subsequently, it is possible to have a
|
|
peripheral that uses DMA but does not use interrupts.</para>
|
|
|
|
<para>It is important to understand that although the CPU always
|
|
releases the bus to the DMA when the DMA makes the request, this
|
|
action is invisible to both applications and the operating
|
|
systems, except for slight changes in the amount of time the
|
|
processor takes to execute instructions when the DMA is active.
|
|
Subsequently, the processor must poll the peripheral, poll the
|
|
registers in the DMA chip, or receive an interrupt from the
|
|
peripheral to know for certain when a DMA transfer has
|
|
completed.</para>
|
|
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>DMA Page Registers and 16Meg address space
|
|
limitations</title>
|
|
|
|
<para>You may have noticed earlier that instead of the DMA setting
|
|
the address lines to 0x00123456 as we said earlier, the DMA only
|
|
set 0x3456. The reason for this takes a bit of explaining.</para>
|
|
|
|
<para>When the original IBM PC was designed, IBM elected to use both
|
|
DMA and interrupt controller chips that were designed for use with
|
|
the 8085, an 8-bit processor with an address space of 16 bits
|
|
(64K). Since the IBM PC supported more than 64K of memory,
|
|
something had to be done to allow the DMA to read or write memory
|
|
locations above the 64K mark. What IBM did to solve this problem
|
|
was to add an external data latch for each DMA channel that holds
|
|
the upper bits of the address to be read to or written from.
|
|
Whenever a DMA channel is active, the contents of that latch are
|
|
written to the address bus and kept there until the DMA operation
|
|
for the channel ends. IBM called these latches “Page
|
|
Registers”.</para>
|
|
|
|
<para>So for our example above, the DMA would put the 0x3456 part of
|
|
the address on the bus, and the Page Register for DMA channel 2
|
|
would put 0x0012xxxx on the bus. Together, these two values form
|
|
the complete address in memory that is to be accessed.</para>
|
|
|
|
<para>Because the Page Register latch is independent of the DMA
|
|
chip, the area of memory to be read or written must not span a 64K
|
|
physical boundary. For example, if the DMA accesses memory
|
|
location 0xffff, after that transfer the DMA will then increment
|
|
the address register and the DMA will access the next byte at
|
|
location 0x0000, not 0x10000. The results of letting this happen
|
|
are probably not intended.</para>
|
|
|
|
<note>
|
|
<para>“Physical” 64K boundaries should not be
|
|
confused with 8086-mode 64K “Segments”, which are
|
|
created by mathematically adding a segment register with an
|
|
offset register. Page Registers have no address overlap and are
|
|
mathematically OR-ed together.</para>
|
|
</note>
|
|
|
|
<para>To further complicate matters, the external DMA address
|
|
latches on the PC/AT hold only eight bits, so that gives us
|
|
8+16=24 bits, which means that the DMA can only point at memory
|
|
locations between 0 and 16Meg. For newer computers that allow
|
|
more than 16Meg of memory, the standard PC-compatible DMA cannot
|
|
access memory locations above 16Meg.</para>
|
|
|
|
<para>To get around this restriction, operating systems will reserve
|
|
a RAM buffer in an area below 16Meg that also does not span a
|
|
physical 64K boundary. Then the DMA will be programmed to
|
|
transfer data from the peripheral and into that buffer. Once the
|
|
DMA has moved the data into this buffer, the operating system will
|
|
then copy the data from the buffer to the address where the data
|
|
is really supposed to be stored.</para>
|
|
|
|
<para>When writing data from an address above 16Meg to a DMA-based
|
|
peripheral, the data must be first copied from where it resides
|
|
into a buffer located below 16Meg, and then the DMA can copy the
|
|
data from the buffer to the hardware. In FreeBSD, these reserved
|
|
buffers are called “Bounce Buffers”. In the MS-DOS world, they
|
|
are sometimes called “Smart Buffers”.</para>
|
|
|
|
<note>
|
|
<para>A new implementation of the 8237, called the 82374, allows
|
|
16 bits of page register to be specified, allows access to the
|
|
entire 32 bit address space, without the use of bounce
|
|
buffers.</para>
|
|
</note>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>DMA Operational Modes and Settings</title>
|
|
|
|
<para>The 8237 DMA can be operated in several modes. The main ones
|
|
are:</para>
|
|
|
|
|
|
<variablelist>
|
|
<varlistentry><term>Single</term>
|
|
<listitem>
|
|
<para>A single byte (or word) is transferred. The DMA must
|
|
release and re-acquire the bus for each additional byte.
|
|
This is commonly-used by devices that cannot transfer the
|
|
entire block of data immediately. The peripheral will
|
|
request the DMA each time it is ready for another
|
|
transfer.</para>
|
|
|
|
<para>The standard PC-compatible floppy disk controller (NEC
|
|
765) only has a one-byte buffer, so it uses this
|
|
mode.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry><term>Block/Demand</term>
|
|
|
|
<listitem>
|
|
<para>Once the DMA acquires the system bus, an entire block
|
|
of data is transferred, up to a maximum of 64K. If the
|
|
peripheral needs additional time, it can assert the READY
|
|
signal to suspend the transfer briefly. READY should not
|
|
be used excessively, and for slow peripheral transfers,
|
|
the Single Transfer Mode should be used instead.</para>
|
|
|
|
<para>The difference between Block and Demand is that once a
|
|
Block transfer is started, it runs until the transfer
|
|
count reaches zero. DRQ only needs to be asserted until
|
|
-DACK is asserted. Demand Mode will transfer one more
|
|
bytes until DRQ is de-asserted, at which point the DMA
|
|
suspends the transfer and releases the bus back to the
|
|
CPU. When DRQ is asserted later, the transfer resumes
|
|
where it was suspended.</para>
|
|
|
|
<para>Older hard disk controllers used Demand Mode until CPU
|
|
speeds increased to the point that it was more efficient
|
|
to transfer the data using the CPU, particularly if the
|
|
memory locations used in the transfer were above the 16Meg
|
|
mark.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry><term>Cascade</term>
|
|
|
|
<listitem>
|
|
<para>This mechanism allows a DMA channel to request the
|
|
bus, but then the attached peripheral device is
|
|
responsible for placing the addressing information on the
|
|
bus instead of the DMA. This is also used to implement a
|
|
technique known as “Bus Mastering”.</para>
|
|
|
|
<para>When a DMA channel in Cascade Mode receives control of
|
|
the bus, the DMA does not place addresses and I/O control
|
|
signals on the bus like the DMA normally does when it is
|
|
active. Instead, the DMA only asserts the -DACK signal
|
|
for the active DMA channel.</para>
|
|
|
|
<para>At this point it is up to the peripheral connected to
|
|
that DMA channel to provide address and bus control
|
|
signals. The peripheral has complete control over the
|
|
system bus, and can do reads and/or writes to any address
|
|
below 16Meg. When the peripheral is finished with the
|
|
bus, it de-asserts the DRQ line, and the DMA controller
|
|
can then return control to the CPU or to some other DMA
|
|
channel.</para>
|
|
|
|
<para>Cascade Mode can be used to chain multiple DMA
|
|
controllers together, and this is exactly what DMA Channel
|
|
4 is used for in the PC architecture. When a peripheral
|
|
requests the bus on DMA channels 0, 1, 2 or 3, the slave
|
|
DMA controller asserts HLDREQ, but this wire is actually
|
|
connected to DRQ4 on the primary DMA controller instead of
|
|
to the CPU. The primary DMA controller, thinking it has
|
|
work to do on Channel 4, requests the bus from the CPU
|
|
using HLDREQ signal. Once the CPU grants the bus to the
|
|
primary DMA controller, -DACK4 is asserted, and that wire
|
|
is actually connected to the HLDA signal on the slave DMA
|
|
controller. The slave DMA controller then transfers data
|
|
for the DMA channel that requested it (0, 1, 2 or 3), or
|
|
the slave DMA may grant the bus to a peripheral that wants
|
|
to perform its own bus-mastering, such as a SCSI
|
|
controller.</para>
|
|
|
|
<para>Because of this wiring arrangement, only DMA channels
|
|
0, 1, 2, 3, 5, 6 and 7 are usable with peripherals on
|
|
PC/AT systems.</para>
|
|
|
|
<note>
|
|
<para>DMA channel 0 was reserved for refresh operations in
|
|
early IBM PC computers, but is generally available for
|
|
use by peripherals in modern systems.</para>
|
|
</note>
|
|
|
|
<para>When a peripheral is performing Bus Mastering, it is
|
|
important that the peripheral transmit data to or from
|
|
memory constantly while it holds the system bus. If the
|
|
peripheral cannot do this, it must release the bus
|
|
frequently so that the system can perform refresh
|
|
operations on main memory.</para>
|
|
|
|
<para>The Dynamic RAM used in all PCs for main memory must
|
|
be accessed frequently to keep the bits stored in the
|
|
components “charged”. Dynamic RAM essentially consists of
|
|
millions of capacitors with each one holding one bit of
|
|
data. These capacitors are charged with power to
|
|
represent a <literal>1</literal> or drained to represent a <literal>0</literal>. Because
|
|
all capacitors leak, power must be added at regular
|
|
intervals to keep the <literal>1</literal> values intact. The RAM chips
|
|
actually handle the task of pumping power back into all of
|
|
the appropriate locations in RAM, but they must be told
|
|
when to do it by the rest of the computer so that the
|
|
refresh activity won't interfere with the computer wanting
|
|
to access RAM normally. If the computer is unable to
|
|
refresh memory, the contents of memory will become
|
|
corrupted in just a few milliseconds.</para>
|
|
|
|
<para>Since memory read and write cycles “count” as
|
|
refresh cycles (a dynamic RAM refresh cycle is actually an
|
|
incomplete memory read cycle), as long as the peripheral
|
|
controller continues reading or writing data to sequential
|
|
memory locations, that action will refresh all of
|
|
memory.</para>
|
|
|
|
<para>Bus-mastering is found in some SCSI host interfaces
|
|
and other high-performance peripheral controllers.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry><term>Autoinitialize</term>
|
|
|
|
<listitem>
|
|
<para>This mode causes the DMA to perform Byte, Block or
|
|
Demand transfers, but when the DMA transfer counter
|
|
reaches zero, the counter and address are set back to
|
|
where they were when the DMA channel was originally
|
|
programmed. This means that as long as the peripheral
|
|
requests transfers, they will be granted. It is up to the
|
|
CPU to move new data into the fixed buffer ahead of where
|
|
the DMA is about to transfer it when doing output
|
|
operations, and read new data out of the buffer behind
|
|
where the DMA is writing when doing input
|
|
operations.</para>
|
|
|
|
<para>This technique is frequently used on audio devices
|
|
that have small or no hardware “sample” buffers. There
|
|
is additional CPU overhead to manage this “circular”
|
|
buffer, but in some cases this may be the only way to
|
|
eliminate the latency that occurs when the DMA counter
|
|
reaches zero and the DMA stops transfers until it is
|
|
reprogrammed.</para>
|
|
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
|
|
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Programming the DMA</title>
|
|
|
|
<para>The DMA channel that is to be programmed should always be
|
|
“masked” before loading any settings. This is because the
|
|
hardware might unexpectedly assert the DRQ for that channel, and
|
|
the DMA might respond, even though not all of the parameters have
|
|
been loaded or updated.</para>
|
|
|
|
<para>Once masked, the host must specify the direction of the
|
|
transfer (memory-to-I/O or I/O-to-memory), what mode of DMA
|
|
operation is to be used for the transfer (Single, Block, Demand,
|
|
Cascade, etc), and finally the address and length of the transfer
|
|
are loaded. The length that is loaded is one less than the amount
|
|
you expect the DMA to transfer. The LSB and MSB of the address
|
|
and length are written to the same 8-bit I/O port, so another port
|
|
must be written to first to guarantee that the DMA accepts the
|
|
first byte as the LSB and the second byte as the MSB of the length
|
|
and address.</para>
|
|
|
|
<para>Then, be sure to update the Page Register, which is external
|
|
to the DMA and is accessed through a different set of I/O
|
|
ports.</para>
|
|
|
|
<para>Once all the settings are ready, the DMA channel can be
|
|
un-masked. That DMA channel is now considered to be “armed”,
|
|
and will respond when the DRQ line for that channel is
|
|
asserted.</para>
|
|
|
|
<para>Refer to a hardware data book for precise programming details
|
|
for the 8237. You will also need to refer to the I/O port map for
|
|
the PC system, which describes where the DMA and Page Register
|
|
ports are located. A complete port map table is located
|
|
below.</para>
|
|
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>DMA Port Map</title>
|
|
|
|
<para>All systems based on the IBM-PC and PC/AT have the DMA
|
|
hardware located at the same I/O ports. The complete list is
|
|
provided below. Ports assigned to DMA Controller #2 are undefined
|
|
on non-AT designs.</para>
|
|
|
|
|
|
<sect3>
|
|
<title>0x00–0x1f DMA Controller #1 (Channels 0, 1, 2 and
|
|
3)</title>
|
|
|
|
<para>DMA Address and Count Registers</para>
|
|
|
|
<informaltable frame="none">
|
|
<tgroup cols="3">
|
|
<tbody>
|
|
<row>
|
|
<entry>0x00</entry>
|
|
<entry>write</entry>
|
|
<entry>Channel 0 starting address</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x00</entry>
|
|
<entry>read</entry>
|
|
<entry>Channel 0 current address</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x01</entry>
|
|
<entry>write</entry>
|
|
<entry>Channel 0 starting word count</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x01</entry>
|
|
<entry>read</entry>
|
|
<entry>Channel 0 remaining word count</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x02</entry>
|
|
<entry>write</entry>
|
|
<entry>Channel 1 starting address</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x02</entry>
|
|
<entry>read</entry>
|
|
<entry>Channel 1 current address</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x03</entry>
|
|
<entry>write</entry>
|
|
<entry>Channel 1 starting word count</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x03</entry>
|
|
<entry>read</entry>
|
|
<entry>Channel 1 remaining word count</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x04</entry>
|
|
<entry>write</entry>
|
|
<entry>Channel 2 starting address</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x04</entry>
|
|
<entry>read</entry>
|
|
<entry>Channel 2 current address</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x05</entry>
|
|
<entry>write</entry>
|
|
<entry>Channel 2 starting word count</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x05</entry>
|
|
<entry>read</entry>
|
|
<entry>Channel 2 remaining word count</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x06</entry>
|
|
<entry>write</entry>
|
|
<entry>Channel 3 starting address</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x06</entry>
|
|
<entry>read</entry>
|
|
<entry>Channel 3 current address</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x07</entry>
|
|
<entry>write</entry>
|
|
<entry>Channel 3 starting word count</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x07</entry>
|
|
<entry>read</entry>
|
|
<entry>Channel 3 remaining word count</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</informaltable>
|
|
|
|
<para>DMA Command Registers</para>
|
|
|
|
<informaltable frame="none">
|
|
<tgroup cols="3">
|
|
<tbody>
|
|
<row>
|
|
<entry>0x08</entry>
|
|
<entry>write</entry>
|
|
<entry>Command Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x08</entry>
|
|
<entry>read</entry>
|
|
<entry>Status Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x09</entry>
|
|
<entry>write</entry>
|
|
<entry>Request Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x09</entry>
|
|
<entry>read</entry>
|
|
<entry>-</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x0a</entry>
|
|
<entry>write</entry>
|
|
<entry>Single Mask Register Bit</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x0a</entry>
|
|
<entry>read</entry>
|
|
<entry>-</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x0b</entry>
|
|
<entry>write</entry>
|
|
<entry>Mode Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x0b</entry>
|
|
<entry>read</entry>
|
|
<entry>-</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x0c</entry>
|
|
<entry>write</entry>
|
|
<entry>Clear LSB/MSB Flip-Flop</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x0c</entry>
|
|
<entry>read</entry>
|
|
<entry>-</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x0d</entry>
|
|
<entry>write</entry>
|
|
<entry>Master Clear/Reset</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x0d</entry>
|
|
<entry>read</entry>
|
|
<entry>Termporary Register (not available on newer
|
|
versions)</entry>
|
|
</row>
|
|
<row>
|
|
<entry>0x0e</entry>
|
|
<entry>write</entry>
|
|
<entry>Clear Mask Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x0e</entry>
|
|
<entry>read</entry>
|
|
<entry>-</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x0f</entry>
|
|
<entry>write</entry>
|
|
<entry>Write All Mask Register Bits</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x0f</entry>
|
|
<entry>read</entry>
|
|
<entry>Read All Mask Register Bits (only in Intel
|
|
82374)</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</informaltable>
|
|
</sect3>
|
|
|
|
<sect3>
|
|
<title>0xc0–0xdf DMA Controller #2 (Channels 4, 5, 6 and
|
|
7)</title>
|
|
|
|
<para>DMA Address and Count Registers</para>
|
|
|
|
<informaltable frame="none">
|
|
<tgroup cols="3">
|
|
<tbody>
|
|
<row>
|
|
<entry>0xc0</entry>
|
|
<entry>write</entry>
|
|
<entry>Channel 4 starting address</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0xc0</entry>
|
|
<entry>read</entry>
|
|
<entry>Channel 4 current address</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0xc2</entry>
|
|
<entry>write</entry>
|
|
<entry>Channel 4 starting word count</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0xc2</entry>
|
|
<entry>read</entry>
|
|
<entry>Channel 4 remaining word count</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0xc4</entry>
|
|
<entry>write</entry>
|
|
<entry>Channel 5 starting address</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0xc4</entry>
|
|
<entry>read</entry>
|
|
<entry>Channel 5 current address</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0xc6</entry>
|
|
<entry>write</entry>
|
|
<entry>Channel 5 starting word count</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0xc6</entry>
|
|
<entry>read</entry>
|
|
<entry>Channel 5 remaining word count</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0xc8</entry>
|
|
<entry>write</entry>
|
|
<entry>Channel 6 starting address</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0xc8</entry>
|
|
<entry>read</entry>
|
|
<entry>Channel 6 current address</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0xca</entry>
|
|
<entry>write</entry>
|
|
<entry>Channel 6 starting word count</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0xca</entry>
|
|
<entry>read</entry>
|
|
<entry>Channel 6 remaining word count</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0xcc</entry>
|
|
<entry>write</entry>
|
|
<entry>Channel 7 starting address</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0xcc</entry>
|
|
<entry>read</entry>
|
|
<entry>Channel 7 current address</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0xce</entry>
|
|
<entry>write</entry>
|
|
<entry>Channel 7 starting word count</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0xce</entry>
|
|
<entry>read</entry>
|
|
<entry>Channel 7 remaining word count</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</informaltable>
|
|
|
|
<para>DMA Command Registers</para>
|
|
|
|
<informaltable frame="none">
|
|
<tgroup cols="3">
|
|
<tbody>
|
|
<row>
|
|
<entry>0xd0</entry>
|
|
<entry>write</entry>
|
|
<entry>Command Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0xd0</entry>
|
|
<entry>read</entry>
|
|
<entry>Status Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0xd2</entry>
|
|
<entry>write</entry>
|
|
<entry>Request Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0xd2</entry>
|
|
<entry>read</entry>
|
|
<entry>-</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0xd4</entry>
|
|
<entry>write</entry>
|
|
<entry>Single Mask Register Bit</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0xd4</entry>
|
|
<entry>read</entry>
|
|
<entry>-</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0xd6</entry>
|
|
<entry>write</entry>
|
|
<entry>Mode Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0xd6</entry>
|
|
<entry>read</entry>
|
|
<entry>-</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0xd8</entry>
|
|
<entry>write</entry>
|
|
<entry>Clear LSB/MSB Flip-Flop</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0xd8</entry>
|
|
<entry>read</entry>
|
|
<entry>-</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0xda</entry>
|
|
<entry>write</entry>
|
|
<entry>Master Clear/Reset</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0xda</entry>
|
|
<entry>read</entry>
|
|
<entry>Termporary Register (not present in Intel
|
|
82374)</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0xdc</entry>
|
|
<entry>write</entry>
|
|
<entry>Clear Mask Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0xdc</entry>
|
|
<entry>read</entry>
|
|
<entry>-</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0xde</entry>
|
|
<entry>write</entry>
|
|
<entry>Write All Mask Register Bits</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0xdf</entry>
|
|
<entry>read</entry>
|
|
<entry>Read All Mask Register Bits (only in Intel
|
|
82374)</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</informaltable>
|
|
</sect3>
|
|
|
|
<sect3>
|
|
<title>0x80–0x9f DMA Page Registers</title>
|
|
|
|
<informaltable frame="none">
|
|
<tgroup cols="3">
|
|
<tbody>
|
|
<row>
|
|
<entry>0x87</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 0 Low byte (23-16) page Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x83</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 1 Low byte (23-16) page Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x81</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 2 Low byte (23-16) page Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x82</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 3 Low byte (23-16) page Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x8b</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 5 Low byte (23-16) page Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x89</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 6 Low byte (23-16) page Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x8a</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 7 Low byte (23-16) page Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x8f</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Low byte page Refresh</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</informaltable>
|
|
</sect3>
|
|
|
|
<sect3>
|
|
<title>0x400–0x4ff 82374 Enhanced DMA Registers</title>
|
|
|
|
<para>The Intel 82374 EISA System Component (ESC) was introduced
|
|
in early 1996 and includes a DMA controller that provides a
|
|
superset of 8237 functionality as well as other PC-compatible
|
|
core peripheral components in a single package. This chip is
|
|
targeted at both EISA and PCI platforms, and provides modern DMA
|
|
features like scatter-gather, ring buffers as well as direct
|
|
access by the system DMA to all 32 bits of address space.</para>
|
|
|
|
<para>If these features are used, code should also be included to
|
|
provide similar functionality in the previous 16 years worth of
|
|
PC-compatible computers. For compatibility reasons, some of the
|
|
82374 registers must be programmed <emphasis>after</emphasis>
|
|
programming the traditional 8237 registers for each transfer.
|
|
Writing to a traditional 8237 register forces the contents of
|
|
some of the 82374 enhanced registers to zero to provide backward
|
|
software compatibility.</para>
|
|
|
|
<informaltable frame="none">
|
|
<tgroup cols="3">
|
|
<tbody>
|
|
<row>
|
|
<entry>0x401</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 0 High byte (bits 23-16) word count</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x403</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 1 High byte (bits 23-16) word count</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x405</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 2 High byte (bits 23-16) word count</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x407</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 3 High byte (bits 23-16) word count</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x4c6</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 5 High byte (bits 23-16) word count</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x4ca</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 6 High byte (bits 23-16) word count</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x4ce</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 7 High byte (bits 23-16) word count</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x487</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 0 High byte (bits 31-24) page
|
|
Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x483</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 1 High byte (bits 31-24) page
|
|
Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x481</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 2 High byte (bits 31-24) page
|
|
Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x482</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 3 High byte (bits 31-24) page
|
|
Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x48b</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 5 High byte (bits 31-24) page
|
|
Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x489</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 6 High byte (bits 31-24) page
|
|
Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x48a</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 6 High byte (bits 31-24) page
|
|
Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x48f</entry>
|
|
<entry>r/w</entry>
|
|
<entry>High byte page Refresh</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x4e0</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 0 Stop Register (bits 7-2)</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x4e1</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 0 Stop Register (bits 15-8)</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x4e2</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 0 Stop Register (bits 23-16)</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x4e4</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 1 Stop Register (bits 7-2)</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x4e5</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 1 Stop Register (bits 15-8)</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x4e6</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 1 Stop Register (bits 23-16)</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x4e8</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 2 Stop Register (bits 7-2)</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x4e9</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 2 Stop Register (bits 15-8)</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x4ea</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 2 Stop Register (bits 23-16)</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x4ec</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 3 Stop Register (bits 7-2)</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x4ed</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 3 Stop Register (bits 15-8)</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x4ee</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 3 Stop Register (bits 23-16)</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x4f4</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 5 Stop Register (bits 7-2)</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x4f5</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 5 Stop Register (bits 15-8)</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x4f6</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 5 Stop Register (bits 23-16)</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x4f8</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 6 Stop Register (bits 7-2)</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x4f9</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 6 Stop Register (bits 15-8)</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x4fa</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 6 Stop Register (bits 23-16)</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x4fc</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 7 Stop Register (bits 7-2)</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x4fd</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 7 Stop Register (bits 15-8)</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x4fe</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 7 Stop Register (bits 23-16)</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x40a</entry>
|
|
<entry>write</entry>
|
|
<entry>Channels 0-3 Chaining Mode Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x40a</entry>
|
|
<entry>read</entry>
|
|
<entry>Channel Interrupt Status Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x4d4</entry>
|
|
<entry>write</entry>
|
|
<entry>Channels 4-7 Chaining Mode Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x4d4</entry>
|
|
<entry>read</entry>
|
|
<entry>Chaining Mode Status</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x40c</entry>
|
|
<entry>read</entry>
|
|
<entry>Chain Buffer Expiration Control Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x410</entry>
|
|
<entry>write</entry>
|
|
<entry>Channel 0 Scatter-Gather Command Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x411</entry>
|
|
<entry>write</entry>
|
|
<entry>Channel 1 Scatter-Gather Command Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x412</entry>
|
|
<entry>write</entry>
|
|
<entry>Channel 2 Scatter-Gather Command Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x413</entry>
|
|
<entry>write</entry>
|
|
<entry>Channel 3 Scatter-Gather Command Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x415</entry>
|
|
<entry>write</entry>
|
|
<entry>Channel 5 Scatter-Gather Command Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x416</entry>
|
|
<entry>write</entry>
|
|
<entry>Channel 6 Scatter-Gather Command Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x417</entry>
|
|
<entry>write</entry>
|
|
<entry>Channel 7 Scatter-Gather Command Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x418</entry>
|
|
<entry>read</entry>
|
|
<entry>Channel 0 Scatter-Gather Status Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x419</entry>
|
|
<entry>read</entry>
|
|
<entry>Channel 1 Scatter-Gather Status Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x41a</entry>
|
|
<entry>read</entry>
|
|
<entry>Channel 2 Scatter-Gather Status Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x41b</entry>
|
|
<entry>read</entry>
|
|
<entry>Channel 3 Scatter-Gather Status Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x41d</entry>
|
|
<entry>read</entry>
|
|
<entry>Channel 5 Scatter-Gather Status Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x41e</entry>
|
|
<entry>read</entry>
|
|
<entry>Channel 5 Scatter-Gather Status Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x41f</entry>
|
|
<entry>read</entry>
|
|
<entry>Channel 7 Scatter-Gather Status Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x420-0x423</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 0 Scatter-Gather Descriptor Table Pointer
|
|
Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x424-0x427</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 1 Scatter-Gather Descriptor Table Pointer
|
|
Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x428-0x42b</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 2 Scatter-Gather Descriptor Table Pointer
|
|
Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x42c-0x42f</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 3 Scatter-Gather Descriptor Table Pointer
|
|
Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x434-0x437</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 5 Scatter-Gather Descriptor Table Pointer
|
|
Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x438-0x43b</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 6 Scatter-Gather Descriptor Table Pointer
|
|
Register</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>0x43c-0x43f</entry>
|
|
<entry>r/w</entry>
|
|
<entry>Channel 7 Scatter-Gather Descriptor Table Pointer
|
|
Register</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</informaltable>
|
|
</sect3>
|
|
</sect2>
|
|
</sect1>
|
|
</chapter>
|
|
|
|
<!--
|
|
Local Variables:
|
|
mode: sgml
|
|
sgml-declaration: "../chapter.decl"
|
|
sgml-indent-data: t
|
|
sgml-omittag: nil
|
|
sgml-shorttag: nil
|
|
sgml-always-quote-attributes: t
|
|
sgml-minimize-attributes: max
|
|
sgml-parent-document: ("../handbook.sgml" "part" "chapter")
|
|
End:
|
|
-->
|
|
|