.. _nv1-pfifo:

====================
NV1:NV4 PFIFO engine
====================

.. contents::


Introduction
============

PFIFO is the functional unit in charge of collecting engine commands from user
applications and delivering them to PGRAPH. See fifo/intro.txt for an overview
of its construction.

PFIFO is controlled by PMC.ENABLE bit 8 and is connected to PMC interrupt 8.
Setting PMC.ENABLE bit 8 to 0 forces the following registers to 0 [but doesn't
otherwise affect PFIFO]:

- :obj:`WAIT_RETRY <pfifo-wait-retry>`
- :obj:`INTR_ENABLE <nv1-pfifo-intr-enable>`
- :obj:`RAMHT <nv1-pfifo-ramht>` [on NV3 only]
- :obj:`RAMFC <nv1-pfifo-ramfc>` [on NV3 only] - forced to 0x1c00 instead
- :obj:`RAMRO <nv1-pfifo-ramro>` [on NV3 only] - forced to 0x1e00 instead
- :obj:`CHSW_ENABLE <nv1-pfifo-chsw-enable>`
- :obj:`CACHE*.PUSH_ACCESS <nv1-pfifo-cache-push-access>`
- :obj:`CACHE*.PULL_CTRL <nv1-pfifo-cache-pull-ctrl>` bit 0
- :obj:`CACHE1.DMA_CTRL <nv1-pfifo-dma-ctrl>`
- :obj:`CACHE1.PULL_STATE <nv1-pfifo-cache-pull-state>` [on NV3 only]


The MMIO registers
==================

.. space:: 8 nv1-pfifo 0x2000 MMIO-mapped FIFO submission to PGRAPH
   0x0040 WAIT_RETRY pfifo-wait-retry
   0x0080 CACHE_ERROR pfifo-cache-error
   0x0100 INTR nv1-pfifo-intr
   0x0140 INTR_ENABLE nv1-pfifo-intr-enable
   0x0200 CONFIG nv1-pfifo-config
   0x0210 RAMHT nv1-pfifo-ramht NV3:
   0x0214 RAMFC nv1-pfifo-ramfc NV3:
   0x0218 RAMRO nv1-pfifo-ramro NV3:
   0x0400 RUNOUT_STATUS pfifo-runout-status
   0x0410 RUNOUT_PUT pfifo-runout-put
   0x0420 RUNOUT_GET pfifo-runout-get
   0x0500 CHSW_ENABLE nv1-pfifo-chsw-enable
   0x0800 DEVICE nv1-pfifo-device
   0x1000 CACHE0 nv1-pfifo-cache0
   0x1200 CACHE1 nv1-pfifo-cache1

.. space:: 8 nv1-pfifo-cache0 0x200 aux cache
   0x000 PUSH_ACCESS nv1-pfifo-cache-push-access
   0x010 CHID nv1-pfifo-cache-chid NV1:NV3
   0x020 STATUS nv1-pfifo-cache-status NV1:NV3
   0x030 PUT nv1-pfifo-cache-put NV1:NV3
   0x004 CHID nv1-pfifo-cache-chid NV3:NV4
   0x010 PUT nv1-pfifo-cache-put NV3:NV4
   0x014 STATUS nv1-pfifo-cache-status NV3:NV4
   0x040 PULL_CTRL nv1-pfifo-cache-pull-ctrl
   0x050 PULL_STATE nv1-pfifo-cache-pull-state NV1:NV3
   0x070 PUT nv1-pfifo-cache-get
   0x080 CTX nv1-pfifo-cache-ctx
   0x100 ADDR nv1-pfifo-cache-addr
   0x104 DATA nv1-pfifo-cache-data

.. space:: 8 nv1-pfifo-cache1 0xe00 main cache
   0x000 PUSH_ACCESS nv1-pfifo-cache-push-access
   0x010 CHID nv1-pfifo-cache-chid NV1:NV3
   0x020 STATUS nv1-pfifo-cache-status NV1:NV3
   0x030 PUT nv1-pfifo-cache-put NV1:NV3
   0x004 CHID nv1-pfifo-cache-chid NV3:NV4
   0x010 PUT nv1-pfifo-cache-put NV3:NV4
   0x014 STATUS nv1-pfifo-cache-status NV3:NV4
   0x018 DMA_STATE nv1-pfifo-dma-state NV3:NV4
   0x020 DMA_CTRL nv1-pfifo-dma-ctrl NV3:NV4
   0x024 DMA_COUNT nv1-pfifo-dma-count NV3:NV4
   0x028 DMA_GET nv1-pfifo-dma-get NV3:NV4
   0x02c DMA_TARGET nv1-pfifo-dma-target NV3:NV4
   0x030 DMA_TLB_TAG nv1-pfifo-dma-tlb-tag NV3:NV4
   0x034 DMA_TLB_PTE nv1-pfifo-dma-tlb-pte NV3:NV4
   0x038 DMA_PT nv1-pfifo-dma-pt NV3:NV4
   0x040 PULL_CTRL nv1-pfifo-cache-pull-ctrl
   0x050 PULL_STATE nv1-pfifo-cache-pull-state
   0x070 PUT nv1-pfifo-cache-get
   0x080 CTX[8/0x10] nv1-pfifo-cache-ctx
   0x100 ADDR[0x20/8] nv1-pfifo-cache-addr NV1:NV3T
   0x104 DATA[0x20/8] nv1-pfifo-cache-data NV1:NV3T
   0x200 ADDR[0x40/8] nv1-pfifo-cache-addr NV3T:NV4
   0x204 DATA[0x40/8] nv1-pfifo-cache-data NV3T:NV4


.. _nv1-pfifo-intr:

Interrupt reporting
===================

The following registers deal with reporting PFIFO interrupts:

.. reg:: 32 nv1-pfifo-intr interrupt status / acknowledge

   Status of interrupts generated by PFIFO. On read, returns 1 for bits
   corresponding to pending interrupts. On write, if 1 is written to a bit,
   its interrupt gets cleared, if 0 is written nothing happens.

.. reg:: 32 nv1-pfifo-intr-enable interrupt enable

   Interrupt enable bitmask. Set to enable, clear to disable. Interrupts that
   are masked will still show up in INTR when they're triggered, but won't
   cause the PFIFO interrupt line to go active.

The bitfields common to these registers are:
  === =============== ===========
  Bit Name            Description
  === =============== ===========
  0   PULLER_ERROR    puller had a problem while processing a command
  4   RUNOUT          pusher rejected a PIO FIFO access and wrote an entry to RAMRO
  8   RUNOUT_OVERFLOW like above, but RAMRO was full and the entry was discarded
  12  DMA_PUSHER      the DMA pusher read a malformed command stream [NV3+]
  16  DMA_PTE         the DMA pusher got a page fault when reading the command stream [NV3+]
  === =============== ===========

.. reg:: 32 pfifo-cache-error puller error status

   .. todo:: write me

The memory structures
=====================

The NV1/NV3 PFIFO uses three memory structures that reside in RAMIN:

- RAMHT, the puller hash table - can be 0x1000, 0x2000, 0x4000, or 0x8000
  bytes long, depending on configuration
- RAMFC, the puller context save area - 0x20 bytes per channel, on NV1
  it's always half the size of RAMHT, thus using 0x1000-byte RAMHT makes
  half the channels useless, and using >0x2000-byte RAMHT wastes RAMIN
  space. On NV3, it's always 0x1000 bytes [128 channels] long.
- RAMRO, the pusher runout area - made of 8-byte entries, always half
  the size of RAMHT on NV1, either 0x200 or 0x2000 bytes long on NV3.

In addition to these, NV3 also uses the page table part of standard DMA
object structure to access the DMA command buffer.

On NV1, these three structures reside at fixed addresses in RAMIN, selected
based on the PRAM size configuration [see :obj:`nv1-pram-config`]. There are
special MMIO areas provided for easy access to them. On NV3, the structures
can be located anywhere in the first 64kB of RAMIN, settable via the
configuration registers:

.. reg:: 32 nv1-pfifo-ramht RAMHT pointer and configuration

   - bits 12-15 bits 12-15 of RAMHT start address inside RAMIN

   - bits 16-17 RAMHT size

     = ========
     0 0x1000 bytes
     1 0x2000 bytes
     2 0x4000 bytes
     3 0x8000 bytes
     = ========

   The RAMHT address always has to be 0x1000-byte aligned.


.. reg:: 32 nv1-pfifo-ramfc RAMFC pointer

   - bits 9-15: bits 9-15 of RAMFC start address inside RAMIN

   The RAMFC address always has to be 0x200-byte aligned.


.. reg:: 32 nv1-pfifo-ramro RAMRO pointer and configuration

   - bits 9-15: bits 9-15 of RAMRO start address inside RAMIN

   - bit 16: RAMRO size

     = =========
     0 0x200 bytes [64 entries]
     1 0x2000 bytes [1024 entries]
     = =========

   The RAMRO address always has to be 0x200-byte aligned.


The cache
=========

The cache is a "waiting area" for the commands submitted through PFIFO. There
are two caches: the 32-entry [NV1, NV3] or 64-entry [NV3T] CACHE1, which is
used for normal submission and the 1-entry CACHE0, available for manually
injecting PGRAPH commands as part of software method execution, if needed.

A single cache entry holds one command and consists of:

- 3-bit subchannel id
- 11-bit method
- 32-bit data

The channel id is not stored in the cache entries - it's stored in a pusher
register instead. This means that all commands in the cache have to belong
to the same channel - pusher will refuse attempts to submit commands on
a channel different from its current channel if it's unable to switch to
it [ie. there's something in the cache already or channel switching is
manually disabled].

The CACHE1 entries are indexed in Gray code instead of normal binary code.

.. todo:: document gray code

.. reg:: 32 nv1-pfifo-cache-push-access pusher enable

   .. todo:: write me

.. reg:: 32 nv1-pfifo-cache-pull-ctrl puller control

   .. todo:: write me

.. reg:: 32 nv1-pfifo-cache-chid channel ID

   .. todo:: write me

.. reg:: 32 nv1-pfifo-cache-get puller read pointer

   .. todo:: write me

.. reg:: 32 nv1-pfifo-cache-put pusher write pointer

   .. todo:: write me

.. reg:: 32 nv1-pfifo-cache-pull-state puller state

   .. todo:: write me

.. reg:: 32 nv1-pfifo-cache-status status

   .. todo:: write me

.. reg:: 32 nv1-pfifo-cache-addr cache entry - method & subchannel

   .. todo:: write me

.. reg:: 32 nv1-pfifo-cache-data cache entry - data

   .. todo:: write me


The pusher
==========

.. todo:: write me

.. reg:: 32 nv1-pfifo-config pusher configuration

   .. todo:: write me

.. reg:: 32 nv1-pfifo-chsw-enable CACHE channel switch control

   .. todo:: write me


FIFO submission area
--------------------

.. todo:: write me

.. space:: 8 nv1-user 0x2000 PFIFO MMIO submission area

   .. todo:: document me


.. _nv1-pfifo-ramro:

RAMRO
-----

.. todo:: write me

.. reg:: 32 pfifo-runout-status RAMRO status

   .. todo:: write me

.. reg:: 32 pfifo-runout-put RAMRO write pointer

   .. todo:: write me

.. reg:: 32 pfifo-runout-get RAMRO read pointer

   .. todo:: write me


.. _nv3-pfifo-dma:

DMA submission
--------------

.. todo:: write me

.. reg:: 32 nv1-pfifo-dma-state DMA pusher state

   .. todo:: write me

.. reg:: 32 nv1-pfifo-dma-ctrl DMA pusher control and status

   .. todo:: write me

.. reg:: 32 nv1-pfifo-dma-count DMA push buffer counter

   .. todo:: write me

.. reg:: 32 nv1-pfifo-dma-get DMA push buffer pointer

   .. todo:: write me

.. reg:: 32 nv1-pfifo-dma-target DMA push buffer target

   .. todo:: write me

.. reg:: 32 nv1-pfifo-dma-tlb-tag DMA push buffer TLB tag

   .. todo:: write me

.. reg:: 32 nv1-pfifo-dma-tlb-pte DMA push buffer TLB entry

   .. todo:: write me

.. reg:: 32 nv1-pfifo-dma-pt DMA push buffer page table

   .. todo:: write me


The puller
==========

.. todo:: write me

.. reg:: 32 nv1-pfifo-cache-ctx puller context

   .. todo:: write me


.. _nv1-pfifo-ramfc:

RAMFC
=====

.. todo:: write me


.. _nv1-pfifo-ramht:

RAMHT
=====

.. todo:: write me


Unknown registers
=================

.. reg:: 32 pfifo-wait-retry ???

   .. todo:: write me

.. reg:: 32 nv1-pfifo-device PGRAPH engine status?

   .. todo:: write me
