PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
sif2cmd.c
1/*
2
3Common PS2 SIF management API for both EE and IOP.
4
5This file contains all common code for both EE and IOP SIF management.
6
7*/
8
9#include <tamtypes.h>
10#include <ps2_reg_defs.h>
11#include "ps2_sbus.h"
12#include "sbus_priv.h"
13
14#ifdef _EE
15#include <stdio.h>
16#include <string.h>
17#else
18#include <sysclib.h>
19#endif
20
21#ifdef _EE
22#define DMA_BUF_ALIGNMENT 128
23#else
24#define DMA_BUF_ALIGNMENT 16
25#endif
26
27#define SBUS_IRQ_XFER (30)
28#define SBUS_IRQ_EXEC (31)
29
30// SIF2 Commands
31#define SIF2_CMD_SET_XFER_PARAMS (0)
32
33// Transfer Types
34#define SIF2_XFER_RECV (0)
35#define SIF2_XFER_SEND (1)
36
37static u32 _sif2_req_type = 0;
38static u32 _sif2_req_addr = 0;
39static u32 _sif2_req_size = 0;
40
41static int __sif2_cmd_inited = 0;
42
43static SIF2_CmdHandler _sif2_cmd_handlers[SIF2_MAX_CMD_HANDLERS];
44
45// 512 byte command buffer(aligned 16 bytes)
46static u32 _sif2_dma_cmd_buf[128] __attribute__((aligned(DMA_BUF_ALIGNMENT)));
47
48int SIF2_set_cmd_handler(int cid, SIF2_CmdHandlerFunc func, void *param)
49{
50 if ((cid < 0) || (cid >= SIF2_MAX_CMD_HANDLERS)) {
51 return (-1);
52 }
53
54 // return an error if a handler already exists(you must remove it first)
55 if (_sif2_cmd_handlers[cid].func) {
56 return (-2);
57 }
58
59 _sif2_cmd_handlers[cid].func = func;
60 _sif2_cmd_handlers[cid].param = param;
61
62 return (0);
63}
64
65int SIF2_rem_cmd_handler(int cid)
66{
67 if ((cid < 0) || (cid >= SIF2_MAX_CMD_HANDLERS)) {
68 return (-1);
69 }
70
71 _sif2_cmd_handlers[cid].func = NULL;
72 _sif2_cmd_handlers[cid].param = NULL;
73
74 return (0);
75}
76
77// called when remote requests local to setup a DMA transfer to/from remote.
78void _sif2_irq_xfer(void)
79{
80 if (_sif2_req_type == SIF2_XFER_RECV) {
81 // remote has requested us to receive a transfer from remote.
82 SIF2_set_dma(_sif2_req_addr, _sif2_req_size, PS2_DMA_TO_MEM);
83 } else if (_sif2_req_type == SIF2_XFER_SEND) {
84 // remote has requested us to send a transfer to remote.
85 SIF2_set_dma(_sif2_req_addr, _sif2_req_size, PS2_DMA_FROM_MEM);
86 }
87}
88
89void _sif2_irq_exec(void)
90{
91 int cid;
92 SIF2_CmdPkt *pkt;
93
94 // remote is waiting to DMA the command parameters
95
96 // set up a "receive" DMA transfer to the command buffer.
97 SIF2_set_dma(((u32)&_sif2_dma_cmd_buf), sizeof(_sif2_dma_cmd_buf), PS2_DMA_TO_MEM);
98
99 // wait for transfer to complete.
100 SIF2_sync_dma();
101
102#ifdef _EE
103 pkt = (SIF2_CmdPkt *)(((u32)&_sif2_dma_cmd_buf) | 0x20000000);
104#else
105 pkt = (SIF2_CmdPkt *)(((u32)&_sif2_dma_cmd_buf));
106#endif
107
108 cid = pkt->cid;
109
110 if (_sif2_cmd_handlers[cid].func) {
111 _sif2_cmd_handlers[cid].func(pkt, _sif2_cmd_handlers[cid].param);
112 } else {
113#ifdef _EE
114 // printf("unknown command: %d!\n", cid);
115#endif
116 }
117}
118
119void WriteBackDCache(void *, u32);
120
121void SIF2_send_cmd(u32 cid, void *extra, int extra_size)
122{
123 SIF2_CmdPkt *cmd = (SIF2_CmdPkt *)_sif2_dma_cmd_buf;
124
125 cmd->cid = cid;
126 cmd->size = sizeof(SIF2_CmdPkt);
127 cmd->extra = 0;
128 cmd->extra_size = 0;
129
130 if (extra) {
131 if ((unsigned int)extra_size <= (sizeof(_sif2_dma_cmd_buf) - sizeof(SIF2_CmdPkt))) {
132 memcpy((u32 *)(((u32)&_sif2_dma_cmd_buf) + sizeof(SIF2_CmdPkt)), extra, extra_size);
133 cmd->size += extra_size;
134 } else {
135 cmd->extra = (u32)extra;
136 cmd->extra_size = extra_size;
137 }
138 }
139
140#ifdef _EE
141 WriteBackDCache(_sif2_dma_cmd_buf, sizeof(_sif2_dma_cmd_buf));
142#endif
143
144 // set up the DMA transfer to send the cmd packet to remote.
145 SIF2_set_dma((u32)cmd, sizeof(_sif2_dma_cmd_buf), PS2_DMA_FROM_MEM);
146
147 // interrupt the remote CPU with "EXEC".
148 SBUS_interrupt_remote(SBUS_IRQ_EXEC);
149
150 // wait for transfer to complete.
151 SIF2_sync_dma();
152
153 if (cmd->extra) {
154#ifdef _EE
155 WriteBackDCache((void *)cmd->extra, cmd->extra_size);
156#endif
157
158 // set up the DMA transfer to send the extra data to remote.
159 SIF2_set_dma((u32)cmd->extra, cmd->extra_size, PS2_DMA_FROM_MEM);
160
161 // wait for transfer to complete.
162 SIF2_sync_dma();
163 }
164}
165
166void _sif2_cmd_set_req_params(SIF2_CmdPkt *cmd, void *param)
167{
168 u32 *p = &((u32 *)cmd)[4];
169
170 (void)param;
171
172 _sif2_req_type = p[0];
173 _sif2_req_addr = p[1];
174 _sif2_req_size = p[2];
175}
176
177int SIF2_init_cmd(void)
178{
179 if (__sif2_cmd_inited) {
180 return (-1);
181 }
182
183 _sif2_req_type = 0;
184 _sif2_req_addr = 0;
185 _sif2_req_size = 0;
186
187 // init SIF2, if not already
188 SIF2_init();
189
190 SBUS_set_irq_handler(SBUS_IRQ_XFER, (SBUS_IrqHandlerFunc)_sif2_irq_xfer, NULL);
191 SBUS_set_irq_handler(SBUS_IRQ_EXEC, (SBUS_IrqHandlerFunc)_sif2_irq_exec, NULL);
192
193 SIF2_set_cmd_handler(SIF2_CMD_SET_XFER_PARAMS, &_sif2_cmd_set_req_params, NULL);
194
195 __sif2_cmd_inited = 1;
196 return (0);
197}
typedef __attribute__
Definition tlbfunc.c:60