PS2SDK
PS2 Homebrew Libraries
iop_sif2.c
1 /*
2 
3 This 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 
13 static int _sif2_inited = 0;
14 
15 static u32 _sif2_xfer_addr = 0;
16 static u32 _sif2_xfer_size = 0;
17 static u32 _sif2_xfer_attr = 0;
18 static u32 _sif2_xfer_chunk_size = 0;
19 static SIF2_TransferCbFunc _sif2_xfer_cb = NULL;
20 
21 extern void do_debug(u32 val);
22 
23 int SIF2_RestartDma(void);
24 
25 void 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 
48 int 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 
78 int 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
100 int _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 
126 int 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 
157 int 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 }
RegisterIntrHandler
int RegisterIntrHandler(int irq, int mode, int(*handler)(void *arg), void *arg)
Definition: intrman.c:115
IOP_CHCR_TR
#define IOP_CHCR_TR
Definition: iop_regs.h:418
DisableIntr
int DisableIntr(int irq, int *res)
Definition: intrman.c:385
CpuSuspendIntr
int CpuSuspendIntr(int *state)
Definition: intrman.c:195
ps2_sbus.h
iop_regs.h
IOP_CHCR_30
#define IOP_CHCR_30
Definition: iop_regs.h:415
EnableIntr
int EnableIntr(int irq)
Definition: intrman.c:336
tamtypes.h
CpuResumeIntr
int CpuResumeIntr(int state)
Definition: intrman.c:217
ps2_reg_defs.h