Changes
=======

JSR 25-Aug-92 Written
JSR 25-Aug-92 Add new vector entry for sequence element getting transfered.
              Add example.
              Add allocation of logical DMA channels
JSR 25-Aug-92 Updated on input from DDV.
JSR 28-Aug-92 Updated on input from MT and TD.
JSR 08-Sep-92 Updated with cache control in mind.
              Updated to allow control of DMA cycle speed.
JSR 25-Sep-92 Changed method of scatter presentation to fixed length to
              avoid difficulties with memory management.
              Changed completion details to allow error passing.
JSR 25-Sep-92 Issues section added.
              Scatter list format added.
              Suspend and resume transfer detailed out.
SMC 22-Oct-92 Added transfer size to DMA_RegisterChannel flags.
              Removed SWI DMA_CacheControl

Issues
======

Page locking
------------

It is not yet agreed where the page locking activity should reside in a
memory management architecture. Page locking is the act of ensuring a
physical address space page is always available for a virtual address. The
arguments for and against are presented here with consideration of the
architecture:
application -> FileSwitch -> SCSIFS -> SCSIDriver -> DMA

i) Locked by DMA manager:
+ One thing does the locking
+ Old clients of DMA-requiring services will continue to work where
        otherwise they might fail unexpectedly
- The DMA manager cannot break up an operation to be memory manager
        friendly.

ii) Locked by SCSIDriver:
+ Old clients continue to work
- Some device drivers cannot break up operations

iii) Locked by SCSIFS:
+ Operation can be broken up to be memory manager friendly
- locks SCSIFS into being Vicky dependant
- may lock memory unnecessarily - the device driver won't necessarily need
        DMA

iv) Locked by FileSwitch
+ All file systems benefit
+ Operation can be broken up
- Lock may be unnecessary and harmful (RAMFS?)

Suggest the following:
For Vicky the DMA manager locks memory. For future OSs (eg Gold) locking can
be performed at a higher level too - no harm happens as a double-locked page
is still locked. This means least work and least Vicky-dependant modules.

Cache bashing
-------------

It is not clear how DMA<->Cache control interfacing should be performed.
Although a SWI is listed here there are issues of structure not yet clear.
On ARM a cache bash nails the whole cache, partial cache bashes are not
possible. This indicates a pre-DMA message is wanted and a DMA complete
message too. On pre-DMA the ARM cache controller would disable DMA on the
memory and then bash the whole cache. For the '486 card a similar approach
may work well. This needs resolution. Should there be MemoryV instead so
that any new subsystem which influences the cache or other memory clients
can do so without having the receivers of such messages having to be
updated?

Overview
========

DMA is controlled by a (small) number of physical DMA channels (4 on
Victoria) and services a potentially large number of devices. The DMA module
performs the necessary arbiration and switching between the devices with
help from the device drivers. The DMA module also interfaces between a
general purpose software interface and the available hardware interface to
the DMA channels. This enables future changes to the hardware DMA
configuration in future platforms.

Devices register with the DMA handler which logical channel (device) they
control. The device drivers then queue DMAs which the DMA handler processes
in order.

SWIs:

DMA_RegisterChannel     registers with DMA a client device driver
DMA_DeregisterChannel   opposite of the above
DMA_ChannelDMA          queue a DMA transfer
DMA_Terminate           stops a DMA transfer
DMA_SuspendTransfer     Pauses a DMA transfer
DMA_ResumeTransfer      Restarts a DMA transfer

Logical DMA Channels
====================

Logical
Channel Use                             Phys. channel
&000    Podule 0, DMA line 0            0
&001    Podule 0, DMA line 1              1
&010    Podule 1, DMA line 0              1
&011    Podule 1, DMA line 1                2
&020    Podule 2, DMA line 0                2
&021    Podule 2, DMA line 1                  3
&030    Podule 3, DMA line 0                  3
&031    Podule 3, DMA line 1            0
&040    Podule 4, DMA line 0            0
&041    Podule 4, DMA line 1              1
&050    Podule 5, DMA line 0              1
&051    Podule 5, DMA line 1                2
&060    Podule 6, DMA line 0                2
&061    Podule 6, DMA line 1                  3
&070    Podule 7, DMA line 0                  3
&071    Podule 7, DMA line 1            0
&100    On-board SCSI                         3
&101    On-board Floppy                 0
&102    Parallel                            2
&103    Sound out                               4
&104    Sound in                                  5

The network card always sits in slot 0, hence SCSI has been allocated slot 3
and parallel slot 2. Floppy has been given slot 0 as it can share this with
the network card transmission DMA channel (line 0, podule 0).

The network slot has been arranged this way as it is most likely to need two
channels (one for transmit and one for receive) - keeping these channels the
same for large and small means the other two channels can be allocated to
the high need fixed devices (SCSI and parallel) without danger of clashing
with the network card. Floppy has been given a random one of channels 0 and
1 - the network slot had better use this channel for transmission! Sound in
and out have their own channels so there's no problem there.

SWIs
====

The SWIs are listed below. The example is that of a FileCore style filing
system doing a background transfer.

===================
DMA_RegisterChannel
===================

In
 r0=flags
        bit     meaning
        0-1     DMA cycle speed (0-3)
        2-6     transfer size (1,2,4 or 16)
        7       1=device supports disconnection in mid transfer
        8-31    reserved - set to 0
 r1=logical channel
 r2=routine vector
 r3=value of r12 to be passed to vectored routines

Out
 r0=channel registration handle

This registers a channel handling vector with the DMA handler. This vector
of routines will be called by the DMA handler to control the specified
channel. It is an error to register with a channel more than once.

=====================
DMA_DeregisterChannel
=====================

In
 r0=channel registration handle

Out

This removes the vector of routines from the specified channel. Before
removal all DMAs will be terminated on that channel.

==============
DMA_ChannelDMA
==============

In
 r0=flags
        bit     meaning
        0       transfer direction:
                0 - from device to memory (read)
                1 - from memory to device (write)
        1-31    reserved (set to 0)
 r1=channel registration handle
 r2=value of r11 to call vectored routines with
 r3=address of scatter list (word aligned)
 r4=length of transfer (in bytes)

Out
 r0=DMA tag

This queues a DMA to the specified channel. The value in r2 specified here
will be quoted in r11 whenever the DMA handler calls one of the vectored
routines to handle this DMA transfer. The scatter list will be updated as
the transfer goes on to reflect the data that has been transfered. A fixed
(not indeterminate) length transfer has been chosen as this avoids
difficulties with page locking on VM systems. Although this is not an issue
for RISC OS, it is better not to store up difficulties for future operating
systems.

The scatter list is a word aligned table of (address,length) pairs. Both
address and length are 32-bit values. The addresses reference a virtual
address in the domain current at the time the DMA_ChannelDMA is issued. The
lengths are in bytes. The scatter list is updated in the same way as
other scatter lists are updated in RISC OS. A way to think about the advance
of the scatter list is as each byte is transfered the address is advanced
and the length reduced by one until that entry has length 0 then the next
entry is advanced in the same way and so on. In fact the advance of the list
will only be done as IOMD completes each of its transfer sections.

The vectored routines
---------------------

        routine use
        0       Enable device DMA.
        1       Disable device DMA.
        2       Start.
        3       Completion.

These routines are described below. An ordinary transfer will go as follows:

Start
Enable DMA
<transfer>
 .
 .
 .
<transfer>
Disable DMA
Completion

The r12 value is expected to be the module's workspace. The r11 value is
expected to describe the particular device/controller/transfer. However, if
your driver wishes to put different meanings on these this won't cause a
problem.

Example: r12 is module workspace, r11 is drive record pointer.


Enable device DMA
.................

In
 r11
 r12
Out
 -

It is assumed that the default state is for device DMA to be disabled. The
DMA handler will enable device DMA before starting the DMA transfers.

Example: Enable DMA on the controller.


Disable device DMA
..................

In
 r11
 r12
Out
 -

As DMA channels are in short supply a DMA receiving device must be prepared
to disable and reenable its DMA during a transfer so that a DMA channel may
be shared amoungst different devices. This call is a request for a device's
DMA channel to be disabled. DMA disable will be requested once the transfer
has completed.

Example: Disable DMA on the controler.


Start
.....

In
 r11
 r12
Out
 -

This routine will be called to start a DMA sequence. The enable device DMA
will be called after this to get DMA going.

Example: Nothing much to do as FileCore won't send operations for queueing.


Completion
..........

In
 r0=0 (VC) or error (VS)
 r11
 r12
Out
 -

This is called once the DMA transfer has finished. DMA will have been
disabled and the scatter list will be fully up to date before the completion
routine is called. Errors possible include:
        DMA channel deregistered
        Insufficient memory pages available
        No readable memory at this address

Example: Call the FileCore complete entry for the transfer. Tidy up the
controller.


=============
DMA_Terminate
=============

In
 r0=error
 r1=DMA tag
Out
 -

This removes the specified DMA from its queue. The removed DMA will have
these routines called:
'disable device DMA' (only if its currently enabled for the terminated DMA)
'complete' (always)
The 'complete' routine will be called with VS and r0=error supplied to
DMA_Terminate.

If the terminated DMA operation was blocking a logical channel (ie. SWI
DMA_SuspendTransfer had been called with bit 0 clear) then the logical
channel becomes unblocked and queued transfers are started again.


===================
DMA_SuspendTransfer
===================

In
 r0=flags
        bit     meaning
        0       0=dont start queued transfers
                1=start next queued transfer
        1-31    reserved - set to 0
 r1=DMA tag
Out
 -

This suspends the given active DMA transfer. The following will be performed:

The Disable DMA entry will be called
DMA on the relevant IOMD channel will be suspended
The scatter list will be brought up to date

If bit 0 is set then the next DMA transfer in the queue to that channel will
then be started, otherwise that DMA channel will wait for the suspended DMA
to be resumed.

Examples:
A SCSI driver would suspend a transfer on a Disconnection request from a
target device with bit 0 set - any queued requests to other devices on the
SCSI bus would be started.
A DMAing serial device may suspend transmission on flow-control signals, but
with bit 0 clear - it is inappropriate to start other transfers in this
situation.


==================
DMA_ResumeTransfer
==================

In
 r0=flags
        bit     meaning
        0-31    reserved - set to 0
 r1=DMA tag
Out
 -

This resumes the DMA transfer. DMA on IOMD will be enabled then device DMA
will be enabled.
