PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
block.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2004 TyRaNiD <tiraniddo@hotmail.com>
3 * Copyright (c) 2004,2007 Lukasz Bruun <mail@lukasz.dk>
4 *
5 * See the file LICENSE included with this distribution for licensing terms.
6 */
7
13#include "types.h"
14#include <stdarg.h>
15#include "freesd.h"
16#include "spu2regs.h"
17
18u32 BlockTransBuff[2];
19u32 BlockTransAddr[2];
20u32 BlockTransSize[2];
21
22extern void SetDmaWrite(s32 chan);
23extern void SetDmaRead(s32 chan);
24extern IntrData TransIntrData[2];
25extern u32 DmaStop(u32 core);
26
27
28s32 BlockTransWriteFrom(u8 *iopaddr, u32 size, s32 chan, u16 mode, u8 *startaddr)
29{
30 s32 core = chan & 1;
31 s32 offset;
32
33 BlockTransBuff[core] = 0;
34 BlockTransSize[core] = size;
35 BlockTransAddr[core] = (u32)iopaddr;
36
37 if(startaddr == 0)
38 startaddr = iopaddr;
39
40 offset = startaddr - iopaddr;
41
42 if((u32)offset > size)
43 {
44 if(mode & SD_TRANS_LOOP)
45 {
46 offset -= size;
47 BlockTransBuff[core] = 1;
48 }
49 else
50 {
51 return -1;
52 }
53 }
54
55 if(offset & 1023) offset += 1024;
56
57 iopaddr += (BlockTransSize[core] * BlockTransBuff[core]) + offset;
58
59 if(U16_REGISTER_READ(SD_CORE_ATTR(core)) & SD_DMA_IN_PROCESS) return -1;
60 if(U32_REGISTER_READ(SD_DMA_CHCR(core)) & SD_DMA_START) return -1;
61
62 U16_REGISTER_WRITEAND(SD_CORE_ATTR(core), 0xFFCF);
63
64 U16_REGISTER_WRITE(SD_A_TSA_HI(core), 0);
65 U16_REGISTER_WRITE(SD_A_TSA_LO(core), 0);
66
67 U16_REGISTER_WRITE(U16_REGISTER(0x1B0+(core*1024)), 1 << core);
68
69 SetDmaWrite(core);
70
71 U32_REGISTER_WRITE(SD_DMA_ADDR(core), (u32)iopaddr);
72 U16_REGISTER_WRITE(SD_DMA_MODE(core), 0x10);
73 U16_REGISTER_WRITE(SD_DMA_SIZE(core), (size/64)+((size&63)>0));
74 U32_REGISTER_WRITE(SD_DMA_CHCR(core), SD_DMA_CS | SD_DMA_START | SD_DMA_DIR_IOP2SPU);
75
76 return 0;
77}
78
79s32 BlockTransWrite(u8 *iopaddr, u32 size, s32 chan)
80{
81 s32 core = chan & 1;
82
83 BlockTransBuff[core] = 0;
84 BlockTransSize[core] = size;
85 BlockTransAddr[core] = (u32)iopaddr;
86
87 if(U16_REGISTER_READ(SD_CORE_ATTR(core)) & SD_DMA_IN_PROCESS) return -1;
88 if(U32_REGISTER_READ(SD_DMA_CHCR(core)) & SD_DMA_START) return -1;
89
90 U16_REGISTER_WRITEAND(SD_CORE_ATTR(core), 0xFFCF);
91
92 U16_REGISTER_WRITE(SD_A_TSA_HI(core), 0);
93 U16_REGISTER_WRITE(SD_A_TSA_LO(core), 0);
94
95 U16_REGISTER_WRITE(U16_REGISTER(0x1B0+(core*1024)), 1 << core);
96
97 SetDmaWrite(core);
98
99 U32_REGISTER_WRITE(SD_DMA_ADDR(core), (u32)iopaddr);
100 U16_REGISTER_WRITE(SD_DMA_MODE(core), 0x10);
101 U16_REGISTER_WRITE(SD_DMA_SIZE(core), (size/64)+((size&63)>0));
102 U32_REGISTER_WRITE(SD_DMA_CHCR(core), SD_DMA_CS | SD_DMA_START | SD_DMA_DIR_IOP2SPU);
103
104 return 0;
105}
106
107
108s32 BlockTransRead(u8 *iopaddr, u32 size, s32 chan, s16 mode)
109{
110 u32 i;
111
112 s32 core = chan & 1;
113
114 BlockTransBuff[core] = 0;
115 BlockTransSize[core] = size;
116 BlockTransAddr[core] = (u32)iopaddr;
117
118 if(U16_REGISTER_READ(SD_CORE_ATTR(core)) & SD_DMA_IN_PROCESS) return -1;
119 if(U32_REGISTER_READ(SD_DMA_CHCR(core)) & SD_DMA_START) return -1;
120
121 U16_REGISTER_WRITEAND(SD_CORE_ATTR(core), 0xFFCF);
122
123 U16_REGISTER_WRITE(SD_A_TSA_HI(core), 0);
124 U16_REGISTER_WRITE(SD_A_TSA_LO(core), ((mode & 0xF00) << 1) + 0x400);
125
126 U16_REGISTER_WRITE(U16_REGISTER(0x1AE + (core*1024)), (mode & 0xF000) >> 11);
127
128 i = 0x4937;
129
130 while(i--);
131
132 U16_REGISTER_WRITE(U16_REGISTER(0x1B0+(core*1024)), 4);
133
134 SetDmaRead(core);
135
136 U32_REGISTER_WRITE(SD_DMA_ADDR(core), (u32)iopaddr);
137 U16_REGISTER_WRITE(SD_DMA_MODE(core), 0x10);
138 U16_REGISTER_WRITE(SD_DMA_SIZE(core), (size/64)+((size&63)>0));
139 U32_REGISTER_WRITE(SD_DMA_CHCR(core), SD_DMA_CS | SD_DMA_START | SD_DMA_DIR_SPU2IOP);
140
141
142 return 0;
143}
144
145
146int sceSdBlockTrans(s16 chan, u16 mode, u8 *iopaddr, u32 size, ...)
147{
148 int transfer_dir = mode & 3;
149 int core = chan & 1;
150 int _size = size;
151
152 switch(transfer_dir)
153 {
154 case SD_TRANS_WRITE:
155 {
156 TransIntrData[core].mode = 0x100 | core;
157
158 if(mode & SD_TRANS_LOOP)
159 {
160 TransIntrData[core].mode |= SD_TRANS_LOOP << 8;
161 _size /= 2;
162 }
163
164 if(BlockTransWrite(iopaddr, _size, core) >= 0)
165 return 0;
166
167 } break;
168
169 case SD_TRANS_READ:
170 {
171 TransIntrData[core].mode = 0x300 | core;
172
173 if(mode & SD_TRANS_LOOP)
174 {
175 TransIntrData[core].mode |= SD_TRANS_LOOP << 8;
176 _size /= 2;
177 }
178
179 if(BlockTransRead(iopaddr, _size, chan, mode) >= 0)
180 return 0;
181
182 } break;
183
184 case SD_TRANS_STOP:
185 {
186 return DmaStop(core);
187
188 } break;
189
190 case SD_TRANS_WRITE_FROM:
191 {
192 va_list alist;
193 u8* startaddr;
194
195 va_start(alist, size);
196 startaddr = va_arg(alist, u8*);
197 va_end(alist);
198
199 TransIntrData[core].mode = 0x100 | core;
200
201 if(mode & SD_TRANS_LOOP)
202 {
203 TransIntrData[core].mode |= SD_TRANS_LOOP << 8;
204 _size /= 2;
205 }
206
207 if(BlockTransWriteFrom(iopaddr, _size, core, mode, startaddr) >= 0)
208 return 0;
209
210
211 } break;
212
213 }
214 return -1;
215}
216
217u32 sceSdBlockTransStatus(s16 chan, s16 flag)
218{
219 u32 retval;
220
221 (void)flag;
222
223 chan &= 1;
224
225 if(U16_REGISTER_READ(U16_REGISTER(0x1B0 + (chan * 1024))) == 0)
226 retval = 0;
227 else
228 retval = U32_REGISTER_READ(SD_DMA_ADDR(chan));
229
230 retval = (BlockTransBuff[chan] << 24) | (retval & 0xFFFFFF);
231
232 return retval;
233}