PS2 Linux Programming
Using DMAC Tags
Introduction
This tutorial will provide
further information on the use of the Direct Memory Access Controller (DMAC)
within the PS2. As mentioned in the tutorial “Using The DMAC”, SPS2 introduces
an added complication in that the memory it allocates is only physically
contiguous in 4k chunks. This means that it is only possible to send up to
4kBytes of data per transfer using normal mode, which is the simplest of the
transfer methods. It is possible to circumvent this 4k limitation using the
source chain transfer mode and this will be the subject of this tutorial.
Source chain mode allows
data to be sent from multiple places in memory to one destination using just
one transfer initiation. This is achieved by feeding the DMAC commands, called
DMA tags. These DMA Tags are used to find both the next chunk of data to send
and the next DMA tag if there is one.
The technique is
illustrated in the example code provided with this tutorial. In the example,
data is sent from main memory to scratchpad memory using source chain mode over
DMAC channel 9.
DMA tags are 128 bits
long, but only the lower 64 bits are used. Anything can be placed in the top 64
bits of the DMA tag and this will be taken advantage of in later tutorials. For
now, all of the top 64 bits are set to zero. The format and contents of the DMA
Tag can be found on page 59 of the EE Users Manual. For now only QWC, ID, and
ADDR are of interest.
The combination of the
actual stream of data and DMA tags is called a DMA chain. A DMA chain can be
thought of as being made up of links, each link has one DMA tag and associated
data. This is similar to GIF tags and primitive data that was discussed
previously. The QWC field of the DMA tag specifies how much data is in the
link, measured in quad words. Each tag can have a different type, which is set
in the identification (ID) field. The tag’s ID affects what value is put into
the ADDR field.
A comprehensive list of
all the source chain tags can be found on page 46 of the EE Users Manual. The
only tags that we can use on channel 9 are cnt, next, ref, refe, and end. The
remaining ID’s will be discussed in a later tutorial. The table below gives an
explanation of each of these tags.
Tag ID |
Description |
cnt |
This tag says to
transfer QWC of data following the tag, and then read the quad word after
that as the next DMA tag. |
next |
This tag says to
transfer QWC of data following the tag, and then read the next tag from the
address in the ADDR field. |
ref |
This tag says to
transfer QWC of data from the address in the ADDR field. Then read the quad
word following this tag as the next tag. |
refe |
Same as ref except that
it ends the transfer after transferring the data from the address in the ADDR
field. |
end |
This tag says to
transfer QWC of data following the tag, and then end the transfer. |
All of these tags are used
in the example code except for refe. After understanding this tutorial, try to
change the last tag in the sample to a refe tag (be aware that this is not
simply a case of changing the ID field).
The table below can be
used to help understand what is going on in the source chain mode given in the
example code. First the DMA chain is written to the SPS2 allocated memory. Once
this is done the memory is laid out in a manner similar to that shown in the
table (note that the addresses are relative to the start of the allocated
memory):
In the example code, the
DMA tags and data to be transferred are scattered around memory according to
the table below.
Address |
Contents |
0x0000 |
DMA Tag #1: ID = NEXT,
ADDR = 0x0030, QWC = 2 |
0x0010 |
String 1 |
0x0030 |
DMA Tag #2: ID = REF,
ADDR = 0x1000, QWC = 2 |
0x0040 |
DMA Tag #3: ID = CNT,
ADDR = 0, QWC = 2 |
0x0050 |
String 3 |
0x0070 |
DMA Tag #4: ID = END,
ADDR = 0, QWC = 2 |
0x0080 |
String 4 |
0x1000 |
String 2 |
Once initiated, the DMAC
will run through this from address 0x0000 reading in DMA Tag #1. It will
transfer the 2 quad words of string 1 to the scratchpad, and then read in DMA
Tag #2 from the address in ADDR. DMA Tag #2 causes the DMAC to transfer the two
quad words from the address in ADDR which is String 2, and then read in DMA Tag
#3. This tells the DMAC to transfer the following two quad words which is
String 3, then read the quad word after that as the next tag which is DMA Tag
#4. Finally the DMAC transfers the final two quad words (string 4) and then
ends the transfer. Therefore all the strings are transferred to the scratchpad
in order, even though they are dotted all over main memory.
As hinted at in the introduction
to this tutorial, source chain mode can be used to circumvent the 4k block
allocation limitation. There are a few methods that can be used to achieve
this, but as an example, for every 4 kilobytes block of data, a next tag can be
put in the last qword that will point the DMAC to the start of the next 4k
block to be transferred. This technique is known as “stitching” and will be
covered in a later tutorial.
Now consider the example
code that accompanies this tutorial. Initially some strings are defined and
their length in qwords is calculated. SPS2 is initialised and some convenient
pointers to the start of the allocated memory are obtained. Instances of the
DMAC registers and the DMA tags to be used are then obtained. The four tag
structures are then configured according to the format shown in the table
above. All of the DMAC tags and the strings are then written to memory in the
required order. Before any transfer is initiated, the cache is flushed to make
sure all the memory is written (notice that cached memory it being used in this
example).
Now the DMAC register are
configured. Firstly the Scratchpad address register is set to zero which is the
address in scratchpad RAM where the data is to be sent. Next the qword count
(QWC) register is set to zero. It is worth noting that when the DMAC transfer
is initiated with QWC=0, this will cause the DMAC to immediately load and
execute the tag pointed to in the tag address register, which is the required
action. The tag address register is set to point to the start of the SPS2
allocated memory which is the address of the first tag to be read. Finally, the
channel control register is set up to be a chain mode transfer and the start
bit is set to one to initiate the transfer. The instant the information in the
channel control register structure is written into the channel control register
the transfer will commence.
At this point the program
must wait until the DMAC finishes the transfer, this being achieved by the
sps2WaitForDMA() function.
In order to verify that
the transfer has been successful, the strings are printed out to the console
directly from scratchpad memory. SCRATCH_PAD is a constant with a value equal
to the address of the start of scratchpad memory. (Note that the DMAC did not
need to be used to transfer data to the scratchpad ram since a pointer to the
scratchpad memory already exists (SCRATCH_PAD), but the program is constructed
in this manner to illustrated the use of the DMAC Tags).
To end the program the
allocated memory is freed and the SPS2 device is released.
This tutorial illustrated
the source chain mode of the DMAC. This method will be used in future tutorials
to build DMAC data chains which are larger than 4kBytes.
Dr Henry S Fortuna
University of Abertay
Dundee