Skip to main content

dma-bucket

source
Expand description

A dma-bucket is used to organize dma data into groups called buckets.

Each bucket is a linked list of DMA. At DMA time, the buckets are sent in order.



A dma-bucket is a 16 byte thing that lives in the dma-buffer.

buckets live consecutively in the dma-buffer, and can mark the start of a DMA chain

location anywhere.



The bucket doesn't own the data, but rather is a beginning of a linked list of DMA data associated with that bucket

that's stored somewhere else.



At the end, all the buckets are spliced together.



The typical process is:

- empty buckets are allocated with add-buckets

- tags are put somewhere and added to the appropriate bucket with insert-tag, updating last as needed.

- buckets are patched to link to each other with dma-buffer-patch-buckets.



the idea here is that you can build the buckets in whatever order you want, but the buckets

will be DMAd in the bucket allocation order.



Each bucket contains:

a tag, (64-bits), to point to the chain of the bucket

last, a pointer to the last tag of this bucket, so that the bucket can be patched to point to the next.

Functions


dma-bucket-insert-tag

dma-bucket-insert-tag(arg0: inline-array, arg1: bucket-id, arg2: pointer, arg3: pointer) => pointersource

Add a DMA chain to the bucket

dma-buffer-add-buckets

dma-buffer-add-buckets(arg0: dma-buffer, arg1: int) => inline-arraysource

Add count buckets. Each bucket is initialized as empty and won't transfer anything.

dma-buffer-patch-buckets

dma-buffer-patch-buckets(arg0: inline-array, arg1: int) => inline-arraysource

After adding all data to buckets, call this to stitch together the chains for
count consecutive buckets

dma-buffer

source
Expand description

DMA buffers store data to be sent over DMA.

They are a very simple wrapper around the data.

Typically a dma-buffer will store dma-buckets or other more complicated data structures.



The main display list uses a "chain transfer". In this mode, the DMA system reads dma-tags which

tell it what to transfer next. This can be used to construct linked lists of DMA data.



If the DMA is configured correctly, it is possible to make the first quadword contain

both a dma-tag and a tag for the peripheral. This allows you to have a single quadword

tag that controls both the DMA and peripheral. We call these a "dma-packet" for some reason.



Ex:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

32-bit vifcode ;; 32-bit vifcode ;; 64-bit dma-tag ;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

in this case, the vifcodes will be sent to the vif, if

the dma transfer has tte set.

note that the second vifcode can also hold other stuff depending on the mode.

Types


dma-buffer

dma-buffer: basicsource
Fields
type: type
allocated-length: int32
base: pointer
end: pointer
data: uint64
data-buffer: uint8

dma-gif

dma-gif: structuresource
Fields
gif: uint64
quad: uint128
gif0: uint64
gif1: uint64

dma-gif-packet

dma-gif-packet: structuresource
Fields
dma-vif: dma-packet
gif: uint64
gif0: uint64
gif1: uint64
quad: uint128

dma-packet

dma-packet: structuresource
Fields
dma: dma-tag
vif0: vif-tag
vif1: vif-tag
quad: uint128

dma-packet-array

dma-packet-array: inline-array-classsource
Fields
type: type
length: int32
allocated-length: int32
_data: uint8
data: dma-packet

Functions


dma-buffer-add-vu-function

dma-buffer-add-vu-function(dma-buf: dma-buffer, vu-func: vu-function, flush-path-3: int) => symbolsource

Add DMA tags to load the given VU function. The destination in vu instruction memory
is specific inside the vu-function. This does NOT copy the vu-function into the buffer,
but creates a reference to the existing VU function.

dma-buffer-free

dma-buffer-free(arg0: dma-buffer) => intsource

Get the number of free quadwords, rounded down, between base and end pointers.

dma-buffer-inplace-new

dma-buffer-inplace-new(arg0: dma-buffer, arg1: int) => dma-buffersource

Create a dma-buffer in-place. Does not set the type of the dma-buffer object.

dma-buffer-length

dma-buffer-length(arg0: dma-buffer) => intsource

Get length used in quadwords, rounded down

dma-buffer-send

dma-buffer-send(chan: dma-bank, buf: dma-buffer) => nonesource

Send the DMA buffer! DOES NOT TRANSFER TAG, you probably want dma-buffer-send-chain instead.

dma-buffer-send-chain

dma-buffer-send-chain(chan: dma-bank-source, buf: dma-buffer) => nonesource

Send the DMA buffer! Sends the tags

dma-disasm

source
Expand description

Debug tool to print out a DMA list.

Types


vif-disasm-element

vif-disasm-element: structuresource
Fields
mask: uint32
tag: vif-cmd-32
val: uint32
print: uint32
string1: string
string2: string

Variables


*dma-disasm*

*dma-disasm*: symbolsource

*vif-disasm-table*

*vif-disasm-table*: arraysource
Expand description

Constants/type for the PS2 DMA hardware

There are a number of DMA channels.

The PS2 supports several types of DMA, including simple chunk transfer and more complicated

"chain" transfers, where the hardware can follow a linked data-structure.



The code is organized into dma, dma-buffer, and dma-bucket

- dma interacts with the hardware and actually sends the DMA data.

- dma-buffer is memory management for the data to be sent

- dma-bucket is organization of all the frame's DMA data in the correct order

Types


dma-bank

dma-bank: structuresource
Fields
chcr: dma-chcr
madr: uint32
qwc: uint32

dma-bank-control

dma-bank-control: structuresource
Fields
ctrl: dma-ctrl
stat: uint32
pcr: uint32
sqwc: dma-sqwc
rbsr: uint32
rbor: uint32
stadr: uint32
enabler: uint32
enablew: uint32

dma-bank-source

dma-bank-source: dma-banksource
Fields
chcr: dma-chcr
madr: uint32
qwc: uint32
tadr: uint32

dma-bank-spr

dma-bank-spr: dma-bank-sourcesource
Fields
chcr: dma-chcr
madr: uint32
qwc: uint32
tadr: uint32
sadr: uint32

dma-bank-vif

dma-bank-vif: dma-bank-sourcesource
Fields
chcr: dma-chcr
madr: uint32
qwc: uint32
tadr: uint32
as0: uint32
as1: uint32

dma-bucket

dma-bucket: structuresource
Fields
tag: dma-tag
last: pointer
dummy: uint32
next: uint32
clear: uint64
vif0: uint32
vif1: uint32

dma-chcr

dma-chcr: uint32source

dma-ctrl

dma-ctrl: uint32source

dma-enable

dma-enable: uint32source

dma-sqwc

dma-sqwc: uint32source

dma-tag

dma-tag: uint64source

vif-mask

vif-mask: uint32source

vif-stcycl-imm

vif-stcycl-imm: uint16source

vif-tag

vif-tag: uint32source

vif-unpack-imm

vif-unpack-imm: uint16source

vu-code-block

vu-code-block: basicsource
Fields
type: type
name: basic
code: uint32
size: int32
dest-address: uint32

vu-stat

vu-stat: uint64source

Functions


dma-count-until-done

dma-count-until-done(bank: dma-bank, count: pointer) => intsource

Very similar to above, but won't change count if dma is already done.

dma-send-no-scratch

dma-send-no-scratch(bank: dma-bank, madr: uint32, qwc: uint32) => nonesource

Send from main memory. Wait for dma to be ready, flush the cache, and go!

dma-sync-fast

dma-sync-fast(bank: dma-bank) => nonesource

Wait for dma to finish.

dma-sync-with-count

dma-sync-with-count(bank: dma-bank, count: pointer) => intsource

Sync, and 'count' how many iterations of checking for done.
This 'count' is often refered to as the 'wait'

Variables


GIF_DMA_BANK

GIF_DMA_BANK: unknownsource

SPR_FROM_BANK

SPR_FROM_BANK: unknownsource

SPR_TO_BANK

SPR_TO_BANK: unknownsource

VIF0_DMA_BANK

VIF0_DMA_BANK: unknownsource

VIF1_DMA_BANK

VIF1_DMA_BANK: unknownsource

VU0_DATA_MEM_MAP

VU0_DATA_MEM_MAP: unknownsource

VU1_DATA_MEM_MAP

VU1_DATA_MEM_MAP: unknownsource

Functions


clear-vu0-mem

clear-vu0-mem() => nonesource

Set the vu0 data memory to 0xabadbeef. This uses the slow EE mapping of VU memory.
Will crash on PC Port.

clear-vu1-mem

clear-vu1-mem() => nonesource

Set the vu1 data memory to 0xabadbeef. This uses the slow EE mapping of VU memory.
Will crash on PC Port.

dma-initialize

dma-initialize() => nonesource

Due to a bug in the PS2 hardware, you must always disable the DMAtag mismatch
error. This is done here.

dma-send

dma-send(arg0: dma-bank, madr: uint, qwc: uint) => nonesource

Send DMA given an address and a quadword count.
The madr can be in main memory or scratchpad.
This is appropriate for VIF0/GIF transfers.
It can be used for VIF1, but will do VIF -> madr, which is probably
not what you want.

dma-send-chain

dma-send-chain(arg0: dma-bank-source, tadr: uint) => nonesource

Send DMA! tadr should be a tag address, possibly in spad ram.
This is useful for sending to VIF.
Tag transfer is enabled, and DIR is set so a VIF1 transfer
goes from tadr -> VIF.

dma-send-chain-no-flush

dma-send-chain-no-flush(arg0: dma-bank-source, arg1: uint) => nonesource

Send DMA chain! But don't flush the cache, so be careful here. TTE enable.

dma-send-chain-no-tte

dma-send-chain-no-tte(arg0: dma-bank-source, arg1: uint) => nonesource

Send DMA chain! TTE bit is not set, don't transfer tags.
This is never used.

dma-send-from-spr

dma-send-from-spr(madr: uint, sadr: uint, qwc: uint, sync: symbol) => nonesource

Transfer from spr.

dma-send-from-spr-no-flush

dma-send-from-spr-no-flush(madr: uint, sadr: uint, qwc: uint, sync: symbol) => nonesource

Transfer from spr, don't flush the cache.

dma-send-to-spr

dma-send-to-spr(sadr: uint, madr: uint, qwc: uint, sync: symbol) => nonesource

Transfer data to spr

dma-send-to-spr-no-flush

dma-send-to-spr-no-flush(sadr: uint, madr: uint, qwc: uint, sync: symbol) => nonesource

Transfer to spr. Doesn't flush the cache first, so be careful.

dma-sync-crash

dma-sync-crash(arg0: dma-bank) => nonesource

Wait for DMA to finish for a while, then crash if we can't.
This function is unused.

dma-sync-hang

dma-sync-hang(bank: dma-bank) => nonesource

Hang here until the dma transfer is completed.
This is worse than the dma-sync-fast because it ends
up spamming the DMA bank register more often, and reduces
the speed of the DMA transfer.
This function is unused.

dump-vu1-mem

dump-vu1-mem() => nonesource

Print VU1 memory to runtime stdout.
Will crash on PC Port.

dump-vu1-range

dump-vu1-range(start: uint, total-count: uint) => symbolsource

Print part of VU1 memory to runtime stdout.
Will crash on PC Port.

reset-vif1-path

reset-vif1-path() => nonesource

When things go wrong, totally reset vif1.

symlink2

symlink2() => nonesource

symlink2 is a handwritten assembly version of the v2 linking routine.
it is not ported because the OpenGOAL linker has its own implementation already.

symlink3

symlink3() => nonesource

symlink3 is a handwritten assembly version of the v3 linking routine.
OpenGOAL uses a different format for v3, customized for x86-64, so this is not
needed. The C++ implementation is plenty fast enough

ultimate-memcpy

ultimate-memcpy(dst: pointer, src: pointer, size-bytes: uint) => nonesource

The Fastest Memory Copy, for larger transfers.
Memory is copied in ascending order, in 4 kB blocks.
The size should be a multiple of 16 bytes.