PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
sifcmd.c
Go to the documentation of this file.
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# (C)2001, Gustavo Scotti (gustavo@scotti.com)
7# (c) 2003 Marcus R. Brown (mrbrown@0xd6.org)
8# Licenced under Academic Free License version 2.0
9# Review ps2sdk README & LICENSE files for further details.
10*/
11
19#include <tamtypes.h>
20#include <kernel.h>
21#include <sifcmd.h>
22
23#define CMD_PACKET_MAX 128
24#define CMD_PACKET_DATA_MAX 112
25#define SYS_CMD_HANDLER_MAX 32
26
27/* EE DMAC registers. */
28#define DMAC_COMM_STAT 0x1000e010
29#define DMAC_SIF0_CHCR 0x1000c000
30#define CHCR_STR 0x100
31#define STAT_SIF0 0x20
32
40{
42 void *pktbuf;
43 void *unused;
45 void *iopbuf;
46 SifCmdSysHandlerData_t *sys_cmd_handlers;
47 u32 nr_sys_handlers;
48 SifCmdHandlerData_t *usr_cmd_handlers;
49 u32 nr_usr_handlers;
50 int *sregs;
51} __attribute__((aligned(64)));
52
53extern int _iop_reboot_count;
54extern struct cmd_data _sif_cmd_data;
55extern unsigned int _SifSendCmd(int cid, int mode, void *pkt, int pktsize, void *src,
56 void *dest, int size);
57extern int _SifCmdIntHandler(int channel);
58
59#ifdef F__SifSendCmd
60unsigned int _SifSendCmd(int cid, int mode, void *pkt, int pktsize, void *src,
61 void *dest, int size)
62{
63 SifDmaTransfer_t dmat[2];
64 SifCmdHeader_t *header;
65 int count = 0;
66
67 pktsize &= 0xff;
68
69 if (pktsize > CMD_PACKET_DATA_MAX)
70 return 0;
71
72 header = (SifCmdHeader_t *)pkt;
73 header->cid = cid;
74 header->psize = pktsize;
75 header->dest = NULL;
76
77 if (size > 0) {
78 header->dsize = size;
79 header->dest = dest;
80
81 if (mode & SIF_CMD_M_WBDC) /* if mode is & 4, flush reference cache */
82 sceSifWriteBackDCache(src, size);
83
84 dmat[count].src = src;
85 dmat[count].dest = dest;
86 dmat[count].size = size;
87 dmat[count].attr = 0;
88 count++;
89 }
90
91 dmat[count].src = pkt;
92 dmat[count].dest = _sif_cmd_data.iopbuf;
93 dmat[count].size = pktsize;
94 dmat[count].attr = SIF_DMA_ERT | SIF_DMA_INT_O;
95 count++;
96
97 sceSifWriteBackDCache(pkt, pktsize);
98
99 if (mode & SIF_CMD_M_INTR) /* INTERRUPT DMA TRANSFER */
100 return isceSifSetDma(dmat, count);
101 else
102 return sceSifSetDma(dmat, count);
103}
104#endif
105
106#ifdef F_sceSifSendCmd
107unsigned int sceSifSendCmd(int cid, void *packet, int packet_size, void *src_extra,
108 void *dest_extra, int size_extra)
109{
110 return _SifSendCmd(cid, 0, packet, packet_size,
111 src_extra, dest_extra, size_extra);
112}
113#endif
114
115#ifdef F_isceSifSendCmd
116unsigned int isceSifSendCmd(int cid, void *packet, int packet_size, void *src_extra,
117 void *dest_extra, int size_extra)
118{
119 return _SifSendCmd(cid, SIF_CMD_M_INTR, packet, packet_size,
120 src_extra, dest_extra, size_extra);
121}
122#endif
123
124#ifdef F__SifCmdIntHandler
125int _SifCmdIntHandler(int channel)
126{
127 u128 packet[8];
128 u128 *pktbuf;
129 struct cmd_data *cmd_data = &_sif_cmd_data;
130 SifCmdHeader_t *header;
131 int size, pktquads, id, i = 0;
132
133 (void)channel;
134
135 EI();
136
137 header = (SifCmdHeader_t *)cmd_data->pktbuf;
138
139 if (!(size = header->psize))
140 goto out;
141
142 pktquads = (size + 30) >> 4;
143 header->psize = 0;
144 if (pktquads) {
145 pktbuf = (u128 *)cmd_data->pktbuf;
146 while (pktquads--) {
147 packet[i] = pktbuf[i];
148 i++;
149 }
150 }
151
152 isceSifSetDChain();
153
154 header = (SifCmdHeader_t *)packet;
155 /* Get the command handler id and determine which handler list to
156 dispatch from. */
157 id = header->cid & ~SIF_CMD_ID_SYSTEM;
158
159 if (header->cid & SIF_CMD_ID_SYSTEM) {
160 if ((u32)id < cmd_data->nr_sys_handlers)
161 if (cmd_data->sys_cmd_handlers[id].handler)
162 cmd_data->sys_cmd_handlers[id].handler(packet, cmd_data->sys_cmd_handlers[id].harg);
163 } else {
164 if ((u32)id < cmd_data->nr_usr_handlers)
165 if (cmd_data->usr_cmd_handlers[id].handler)
166 cmd_data->usr_cmd_handlers[id].handler(packet, cmd_data->usr_cmd_handlers[id].harg);
167 }
168
169out:
170 ExitHandler();
171 return 0;
172}
173#endif
174
175#ifdef F_sif_cmd_main
176static u8 pktbuf[CMD_PACKET_MAX] __attribute__((aligned(64)));
177/* Define this so that in the unlikely case another SIF implementation decides
178 to use it, it won't crash. Otherwise unused. */
179static u8 sif_unused[64] __attribute__((aligned(64)));
180
181static SifCmdSysHandlerData_t sys_cmd_handlers[SYS_CMD_HANDLER_MAX];
182static int sregs[32];
183
184struct cmd_data _sif_cmd_data;
185static int init = 0;
186static int sif0_id = -1;
187
188struct ca_pkt
189{
190 SifCmdHeader_t header;
191 void *buf;
192};
193
194static void change_addr(void *packet, void *harg)
195{
196 struct cmd_data *cmd_data = (struct cmd_data *)harg;
197 struct ca_pkt *pkt = (struct ca_pkt *)packet;
198
199 cmd_data->iopbuf = pkt->buf;
200}
201
202struct sr_pkt
203{
204 SifCmdHeader_t header;
205 u32 sreg;
206 int val;
207};
208
209static void set_sreg(void *packet, void *harg)
210{
211 struct cmd_data *cmd_data = (struct cmd_data *)harg;
212 struct sr_pkt *pkt = (struct sr_pkt *)packet;
213
214 cmd_data->sregs[pkt->sreg] = pkt->val;
215}
216
217void sceSifInitCmd(void)
218{
219 static struct ca_pkt packet __attribute((aligned(64)));
220 int i;
221 static int _rb_count = 0;
222 if (_rb_count != _iop_reboot_count) {
223 _rb_count = _iop_reboot_count;
224 if (sif0_id >= 0) {
225 DisableDmac(DMAC_SIF0);
226 RemoveDmacHandler(DMAC_SIF0, sif0_id);
227 }
228 init = 0;
229 }
230
231 if (init)
232 return;
233
234 DI();
235
236 _sif_cmd_data.pktbuf = UNCACHED_SEG(pktbuf);
237 _sif_cmd_data.unused = UNCACHED_SEG(sif_unused);
238 _sif_cmd_data.sys_cmd_handlers = sys_cmd_handlers;
239 _sif_cmd_data.nr_sys_handlers = SYS_CMD_HANDLER_MAX;
240 _sif_cmd_data.usr_cmd_handlers = NULL;
241 _sif_cmd_data.nr_usr_handlers = 0;
242 _sif_cmd_data.sregs = sregs;
243
244 for (i = 0; i < SYS_CMD_HANDLER_MAX; i++) {
245 _sif_cmd_data.sys_cmd_handlers[i].handler = NULL;
246 _sif_cmd_data.sys_cmd_handlers[i].harg = NULL;
247 }
248
249 for (i = 0; i < 32; i++)
250 _sif_cmd_data.sregs[i] = 0;
251
252 _sif_cmd_data.sys_cmd_handlers[0].handler = change_addr;
253 _sif_cmd_data.sys_cmd_handlers[0].harg = &_sif_cmd_data;
254 _sif_cmd_data.sys_cmd_handlers[1].handler = set_sreg;
255 _sif_cmd_data.sys_cmd_handlers[1].harg = &_sif_cmd_data;
256
257 EI();
258 FlushCache(0);
259
260 if (_lw(DMAC_COMM_STAT) & STAT_SIF0)
261 _sw(STAT_SIF0, DMAC_COMM_STAT);
262
263 // If SIF0 (IOP -> EE) is not enabled, enable it.
264 if (!(_lw(DMAC_SIF0_CHCR) & CHCR_STR))
265 sceSifSetDChain();
266
267 sif0_id = AddDmacHandler(DMAC_SIF0, &_SifCmdIntHandler, 0);
268 EnableDmac(DMAC_SIF0);
269
270 init = 1;
271
272 _sif_cmd_data.iopbuf = (void *)sceSifGetReg(SIF_SYSREG_SUBADDR);
273 if (_sif_cmd_data.iopbuf) {
274 /* IOP SIF CMD is already initialized, so give it our new
275 receive address. */
276 packet.buf = _sif_cmd_data.pktbuf;
277 sceSifSendCmd(SIF_CMD_CHANGE_SADDR, &packet, sizeof packet, NULL, NULL, 0);
278 } else {
279 /* Sync with the IOP side's SIFCMD implementation. */
280 while (!(sceSifGetReg(SIF_REG_SMFLAG) & SIF_STAT_CMDINIT))
281 ;
282
283 _sif_cmd_data.iopbuf = (void *)sceSifGetReg(SIF_REG_SUBADDR);
284 sceSifSetReg(SIF_SYSREG_SUBADDR, (u32)_sif_cmd_data.iopbuf);
285 /* See the note above about struct cmd_data, and the use of
286 this register. */
287 sceSifSetReg(SIF_SYSREG_MAINADDR, (u32)&_sif_cmd_data);
288 packet.header.opt = 0; // SIFCMD initialization on the IOP (opt = 0)
289 packet.buf = _sif_cmd_data.pktbuf;
290 sceSifSendCmd(SIF_CMD_INIT_CMD, &packet, sizeof packet, NULL, NULL, 0);
291 }
292}
293
294void sceSifExitCmd(void)
295{
296 DisableDmac(DMAC_SIF0);
297 RemoveDmacHandler(DMAC_SIF0, sif0_id);
298 init = 0;
299}
300#endif
301
302#ifdef F_sceSifSetCmdBuffer
303void sceSifSetCmdBuffer(SifCmdHandlerData_t *db, int size)
304{
305 _sif_cmd_data.usr_cmd_handlers = db;
306 _sif_cmd_data.nr_usr_handlers = size;
307}
308#endif
309
310#ifdef F_sceSifSetSysCmdBuffer
311void sceSifSetSysCmdBuffer(SifCmdSysHandlerData_t *db, int size)
312{
313 _sif_cmd_data.sys_cmd_handlers = db;
314 _sif_cmd_data.nr_sys_handlers = size;
315}
316#endif
317
318#ifdef F_sceSifAddCmdHandler
319void sceSifAddCmdHandler(int cid, SifCmdHandler_t handler, void *harg)
320{
321 u32 id = cid & ~SIF_CMD_ID_SYSTEM;
322
323 if (cid & SIF_CMD_ID_SYSTEM)
324 {
325 _sif_cmd_data.sys_cmd_handlers[id].handler = handler;
326 _sif_cmd_data.sys_cmd_handlers[id].harg = harg;
327 }
328 else
329 {
330 _sif_cmd_data.usr_cmd_handlers[id].handler = handler;
331 _sif_cmd_data.usr_cmd_handlers[id].harg = harg;
332 }
333}
334#endif
335
336#ifdef F_sceSifRemoveCmdHandler
337void sceSifRemoveCmdHandler(int cid)
338{
339 u32 id = cid & ~SIF_CMD_ID_SYSTEM;
340
341 if (cid & SIF_CMD_ID_SYSTEM)
342 _sif_cmd_data.sys_cmd_handlers[id].handler = NULL;
343 else
344 _sif_cmd_data.usr_cmd_handlers[id].handler = NULL;
345}
346#endif
347
348#ifdef F_sceSifGetSreg
349unsigned int sceSifGetSreg(int sreg)
350{
351 return _sif_cmd_data.sregs[sreg];
352}
353#endif
354
355#ifdef F_sceSifSetSreg
356void sceSifSetSreg(int sreg, unsigned int value)
357{
358 _sif_cmd_data.sregs[sreg] = value;
359}
360#endif
void * iopbuf
Definition sifcmd.c:45
void * pktbuf
Definition sifcmd.c:1
void * pktbuf
Definition sifcmd.c:42
typedef __attribute__
Definition tlbfunc.c:60
#define SIF_CMD_ID_SYSTEM
#define SIF_CMD_M_INTR
#define SIF_CMD_M_WBDC
#define SIF_STAT_CMDINIT
Definition sifdma.h:48
@ SIF_REG_SUBADDR
Definition sifdma.h:32
@ SIF_REG_SMFLAG
Definition sifdma.h:36
u32 count
start sector of fragmented bd/file