PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
iop_sif2.c
1/*
2
3This file contains IOP-specific SIF-related code.
4
5*/
6
7#include <tamtypes.h>
8#include <ps2_reg_defs.h>
9#include "iop_regs.h"
10#include "ps2_sbus.h"
11#include <sbus_priv.h>
12
13static int _sif2_inited = 0;
14
15static u32 _sif2_xfer_addr = 0;
16static u32 _sif2_xfer_size = 0;
17static u32 _sif2_xfer_attr = 0;
18static u32 _sif2_xfer_chunk_size = 0;
19static SIF2_TransferCbFunc _sif2_xfer_cb = NULL;
20
21extern void do_debug(u32 val);
22
23int SIF2_RestartDma(void);
24
25void SIF2_sync_dma(void)
26{
27 while (1) {
28 if (!(*R_IOP_D2_CHCR & IOP_CHCR_TR)) {
29 if ((_sif2_xfer_addr != 0) && (_sif2_xfer_size > 0)) {
30 _sif2_xfer_addr += _sif2_xfer_chunk_size;
31 _sif2_xfer_size -= _sif2_xfer_chunk_size;
32 }
33
34 if ((_sif2_xfer_addr != 0) && (_sif2_xfer_size > 0)) {
35 SIF2_RestartDma();
36 } else {
37 _sif2_xfer_addr = 0;
38 _sif2_xfer_size = 0;
39 if (_sif2_xfer_cb) {
40 _sif2_xfer_cb();
41 }
42 return;
43 }
44 }
45 }
46}
47
48int SIF2_RestartDma(void)
49{
50 int bc, bs;
51
52 if (!(*R_LOCAL_SBUS(PS2_SBUS_REG4) & 0x80)) {
53 *R_LOCAL_SBUS(PS2_SBUS_REG4) = 0x80;
54 }
55
56 *R_IOP_D2_CHCR = 0;
57 (void)(*R_IOP_D2_CHCR);
58
59 *R_IOP_D2_MADR = (_sif2_xfer_addr & 0x00FFFFFF);
60
61 _sif2_xfer_chunk_size = (_sif2_xfer_size > SIF2_XFER_CHUNK_SIZE) ? SIF2_XFER_CHUNK_SIZE : _sif2_xfer_size;
62
63 bs = ((_sif2_xfer_chunk_size + 3) / 4);
64 if (bs > 32) {
65 bs = 32;
66 }
67
68 bc = (_sif2_xfer_chunk_size + ((bs * 4) - 1)) / (bs * 4);
69
70 *R_IOP_D2_BCR_BS = bs;
71 *R_IOP_D2_BCR_BC = bc;
72 *R_IOP_D2_CHCR = _sif2_xfer_attr;
73 (void)(*R_IOP_D2_CHCR);
74
75 return (0);
76}
77
78int SIF2_set_dma(u32 addr, u32 size, u32 attr)
79{
80 // just a precaution...
81 while (*R_IOP_D2_CHCR & IOP_CHCR_TR)
82 ;
83
84 size = ((size + 3) / 4) * 4;
85
86 _sif2_xfer_addr = addr;
87 _sif2_xfer_size = size;
88
89 if (!(attr & PS2_DMA_FROM_MEM)) {
90 attr |= IOP_CHCR_30;
91 }
92
93 _sif2_xfer_attr = IOP_CHCR_TR | attr;
94
95 SIF2_RestartDma();
96 return (0);
97}
98
99#if 0
100int _sif2_intr_handler(void)
101{
102 u32 chcr = *R_IOP_D2_CHCR;
103
104 // is transfer stopped?
105 if (!(chcr & IOP_CHCR_TR)) {
106 if ((_sif2_xfer_addr != 0) && (_sif2_xfer_size > 0)) {
107 _sif2_xfer_addr += _sif2_xfer_chunk_size;
108 _sif2_xfer_size -= _sif2_xfer_chunk_size;
109 }
110
111 if ((_sif2_xfer_addr != 0) && (_sif2_xfer_size > 0)) {
112 SIF2_RestartDma();
113 } else {
114 _sif2_xfer_addr = 0;
115 _sif2_xfer_size = 0;
116 if (_sif2_xfer_cb) {
117 _sif2_xfer_cb();
118 }
119 }
120 }
121
122 return (1);
123}
124#endif
125
126int SIF2_init(void)
127{
128 int oldStat, old_irq;
129
130 if (_sif2_inited) {
131 return (-1);
132 }
133
134 CpuSuspendIntr(&oldStat);
135 *R_IOP_D2_CHCR = 0;
136
137 // Enable DMA CH2
138 if (!(*R_IOP_DPCR & 0x0800)) {
139 *R_IOP_DPCR |= 0x0800;
140 (void)(*R_IOP_DPCR);
141 }
142
143 DisableIntr(IOP_IRQ_DMA_SIF2, &old_irq);
144
145#if 0
146 RegisterIntrHandler(IOP_IRQ_DMA_SIF2, 1, (void *)&_sif2_intr_handler, NULL);
147
148 EnableIntr(IOP_IRQ_DMA_SIF2);
149#endif
150
151 CpuResumeIntr(oldStat);
152
153 _sif2_inited = 1;
154 return (0);
155}
156
157int SIF2_deinit(void)
158{
159 int oldStat, old_irq;
160
161 if (!_sif2_inited) {
162 return (-1);
163 }
164
165 CpuSuspendIntr(&oldStat);
166
167 *R_IOP_D2_CHCR = 0;
168
169 // Disable DMA CH2
170 if ((*R_IOP_DPCR & 0x0800)) {
171 *R_IOP_DPCR |= 0x0800;
172 (void)(*R_IOP_DPCR);
173 }
174
175 DisableIntr(IOP_IRQ_DMA_SIF2, &old_irq);
176
177 CpuResumeIntr(oldStat);
178
179 _sif2_inited = 0;
180 return (0);
181}
int CpuResumeIntr(int state)
Definition intrman.c:227
int RegisterIntrHandler(int irq, int mode, int(*handler)(void *), void *arg)
Definition intrman.c:125
int DisableIntr(int irq, int *res)
Definition intrman.c:395
int CpuSuspendIntr(int *state)
Definition intrman.c:205
int EnableIntr(int irq)
Definition intrman.c:346
#define IOP_CHCR_TR
Definition iop_regs.h:418
#define IOP_CHCR_30
Definition iop_regs.h:415