toutxbus.s
2.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include <rsp.h>
#include "mbi.h"
#include "tdmem_label.h"
#include "tst_regs.h"
.name dmemp, $20
.name dramp, $19
.name outsz, $18 # set by caller to max size to write
############################################################################
#
# Output coordination routines:
#
# We support two cases:
#
# 1.) output directly to RDP using DMEM as buffer. Requires
# producer/consumer synchronization.
#
# 2.) output routed to DRAM. In this case, we use DMEM as
# a temporary buffer, then DMA out to DRAM.
#
# Goals:
#
# - small code size.
# - efficient and non-obtrusive
# - flexible, can easily route to DRAM or RDP.
#
# In order to do this, and make it transparent to the parts of the
# code which do the writing, we implement an open/close interface.
#
# FUNCTION: OUTPUT TO RDP: OUTPUT TO DRAM:
#-------------------------------------------------------------------------
# open(size) - wait for size avail in - does nothing
# ring buffer.
# - possibly handle wrap
# - wait for 'current' to get
# out of the way
#
# close() - advance CP0 pointer - do DMA of cmd to DRAM
# - increment pointers
# - reset DMEM buffer
#
# In between the open() and close(), the ucode writes the data to DMEM.
# (to either the RDP ring buffer or a temp buffer to be DMA'd)
#
############################################################################
.ent OutputOpen
OutputOpen:
# check if the packet will fit in the buffer
addi dramp, zero, (RSP_OUTPUT_OFFSET + RSP_OUTPUT_SIZE8)
add dmemp, outp, outsz
sub dramp, dramp, dmemp
bgez dramp, CurrentFit
nop
WrapBuffer:
# packet will not fit, wait for current to wrap
mfc0 dramp, CMD_STATUS
andi dramp, dramp, 0x0400
bne dramp, zero, WrapBuffer
# note delay slot
# wait for current to advance
AdvanceCurrent:
mfc0 dramp, CMD_CURRENT
addi outp, zero, RSP_OUTPUT_OFFSET
beq dramp, outp, AdvanceCurrent
nop
mtc0 outp, CMD_START # reset START
CurrentFit:
# done if current_address <= outp
mfc0 dramp, CMD_CURRENT
sub dmemp, outp, dramp
bgez dmemp, OpenDone
# note delay slot
# loop if current_address <= (outp + outsz)
add dmemp, outp, outsz
sub dramp, dmemp, dramp
bgez dramp, CurrentFit
nop
OpenDone:
jr return
nop
.end OutputOpen
##################################################################
## OutputClose ##
##################################################################
.ent OutputClose
OutputClose:
#
# XBUS RDP output
#
jr return
mtc0 outp, CMD_END
.end OutputClose
.unname outsz
.unname dramp
.unname dmemp