ps2sdk  1.1
A collection of Open Source libraries used for developing applications on Sony's PlayStation 2® (PS2).
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 #define USR_CMD_HANDLER_MAX 32
27 
28 
29 /* EE DMAC registers. */
30 #define DMAC_COMM_STAT 0x1000e010
31 #define DMAC_SIF0_CHCR 0x1000c000
32 #define CHCR_STR 0x100
33 #define STAT_SIF0 0x20
34 
41 struct cmd_data {
43  void *pktbuf;
44  void *unused;
46  void *iopbuf;
51  int *sregs;
52 };
53 
54 extern int _iop_reboot_count;
55 extern struct cmd_data _sif_cmd_data;
56 int _SifCmdIntHandler(int channel);
57 
58 #ifdef F_sif_cmd_send
59 static unsigned int _SifSendCmd(int cid, int mode, void *pkt, int pktsize, void *src,
60  void *dest, int size)
61 {
62  SifDmaTransfer_t dmat[2];
63  SifCmdHeader_t *header;
64  int count = 0;
65 
66  pktsize &= 0xff;
67 
68  if (pktsize > CMD_PACKET_DATA_MAX)
69  return 0;
70 
71  header = (SifCmdHeader_t *)pkt;
72  header->cid = cid;
73  header->psize = pktsize;
74  header->dest = NULL;
75 
76  if (size > 0) {
77  header->dsize = size;
78  header->dest = dest;
79 
80  if (mode & SIF_CMD_M_WBDC) /* if mode is & 4, flush reference cache */
81  SifWriteBackDCache(src, size);
82 
83  dmat[count].src = src;
84  dmat[count].dest = dest;
85  dmat[count].size = size;
86  dmat[count].attr = 0;
87  count++;
88  }
89 
90  dmat[count].src = pkt;
91  dmat[count].dest = _sif_cmd_data.iopbuf;
92  dmat[count].size = pktsize;
93  dmat[count].attr = SIF_DMA_ERT | SIF_DMA_INT_O;
94  count++;
95 
96  SifWriteBackDCache(pkt, pktsize);
97 
98  if (mode & SIF_CMD_M_INTR) /* INTERRUPT DMA TRANSFER */
99  return iSifSetDma(dmat, count);
100  else
101  return SifSetDma(dmat, count);
102 }
103 
104 unsigned int
105 SifSendCmd( int command, void *send_data, int send_len,
106  void *extra_from, void *extra_dest, int extra_len)
107 {
108  return _SifSendCmd( command, 0, send_data, send_len,
109  extra_from, extra_dest, extra_len);
110 }
111 
112 unsigned int
113 iSifSendCmd( int command, void *send_data, int send_len,
114  void *extra_from, void *extra_dest, int extra_len)
115 {
116  return _SifSendCmd( command, SIF_CMD_M_INTR, send_data, send_len,
117  extra_from, extra_dest, extra_len);
118 }
119 #endif
120 
121 #ifdef F__sif_cmd_int_handler
122 int _SifCmdIntHandler(int channel)
123 {
124  u128 packet[8];
125  u128 *pktbuf;
126  struct cmd_data *cmd_data = &_sif_cmd_data;
127  SifCmdHeader_t *header;
128  SifCmdHandlerData_t *cmd_handlers;
129  int size, pktquads, id, i = 0;
130 
131  EI();
132 
133  header = (SifCmdHeader_t *)cmd_data->pktbuf;
134 
135  if (!(size = header->psize))
136  goto out;
137 
138  pktquads = (size + 30) >> 4;
139  header->psize = 0;
140  if (pktquads) {
141  pktbuf = (u128 *)cmd_data->pktbuf;
142  while (pktquads--) {
143  packet[i] = pktbuf[i];
144  i++;
145  }
146  }
147 
148  iSifSetDChain();
149 
150  header = (SifCmdHeader_t *)packet;
151  /* Get the command handler id and determine which handler list to
152  dispatch from. */
153  id = header->cid & ~SIF_CMD_ID_SYSTEM;
154 
155  if (header->cid & SIF_CMD_ID_SYSTEM) {
156  if (id < cmd_data->nr_sys_handlers)
157  cmd_handlers = cmd_data->sys_cmd_handlers;
158  else
159  goto out;
160  }
161  else {
162  if (id < cmd_data->nr_usr_handlers)
163  cmd_handlers = cmd_data->usr_cmd_handlers;
164  else
165  goto out;
166  }
167 
168  if (cmd_handlers[id].handler)
169  cmd_handlers[id].handler(packet, cmd_handlers[id].harg);
170 
171 out:
172  ExitHandler();
173  return 0;
174 }
175 #endif
176 
177 #ifdef F_sif_cmd_main
178 static u8 pktbuf[CMD_PACKET_MAX] __attribute__((aligned(64)));
179 /* Define this so that in the unlikely case another SIF implementation decides
180  to use it, it won't crash. Otherwise unused. */
181 static u8 sif_unused[64] __attribute__((aligned(64)));
182 
185 static int sregs[32];
186 
187 struct cmd_data _sif_cmd_data;
188 static int init = 0;
189 static int sif0_id = -1;
190 
191 struct ca_pkt {
192  SifCmdHeader_t header;
193  void *buf;
194 };
195 
196 static void change_addr(void *packet, void *harg)
197 {
198  struct cmd_data *cmd_data = (struct cmd_data *)harg;
199  struct ca_pkt *pkt = (struct ca_pkt *)packet;
200 
201  cmd_data->iopbuf = pkt->buf;
202 }
203 
204 struct sr_pkt {
205  SifCmdHeader_t header;
206  u32 sreg;
207  int val;
208 };
209 
210 static void set_sreg(void *packet, void *harg)
211 {
212  struct cmd_data *cmd_data = (struct cmd_data *)harg;
213  struct sr_pkt *pkt = (struct sr_pkt *)packet;
214 
215  cmd_data->sregs[pkt->sreg] = pkt->val;
216 }
217 
218 void SifInitCmd(void)
219 {
220  static struct ca_pkt packet __attribute((aligned(64)));
221  int i;
222  static int _rb_count = 0;
223  if(_rb_count != _iop_reboot_count)
224  {
225  _rb_count = _iop_reboot_count;
226  if (sif0_id >= 0)
227  {
229  RemoveDmacHandler(DMAC_SIF0, sif0_id);
230  }
231  init = 0;
232  }
233 
234  if (init)
235  return;
236 
237  DI();
238 
240  _sif_cmd_data.unused = UNCACHED_SEG(sif_unused);
241  _sif_cmd_data.sys_cmd_handlers = sys_cmd_handlers;
243  _sif_cmd_data.usr_cmd_handlers = usr_cmd_handlers;
245  _sif_cmd_data.sregs = sregs;
246 
247  for (i = 0; i < SYS_CMD_HANDLER_MAX; i++) {
250  }
251 
252  for (i = 0; i < 32; i++)
253  _sif_cmd_data.sregs[i] = 0;
254 
255  _sif_cmd_data.sys_cmd_handlers[0].handler = change_addr;
257  _sif_cmd_data.sys_cmd_handlers[1].handler = set_sreg;
259 
260  EI();
261  FlushCache(0);
262 
265 
266  //If SIF0 (IOP -> EE) is not enabled, enable it.
267  if (!(_lw(DMAC_SIF0_CHCR) & CHCR_STR))
268  SifSetDChain();
269 
272 
273  init = 1;
274 
276  if (_sif_cmd_data.iopbuf) {
277  /* IOP SIF CMD is already initialized, so give it our new
278  receive address. */
281  } else {
282  /* Sync with the IOP side's SIFCMD implementation. */
284 
287  /* See the note above about struct cmd_data, and the use of
288  this register. */
290  packet.header.opt = 0; //SIFCMD initialization on the IOP (opt = 0)
293  }
294 }
295 
296 void SifExitCmd(void)
297 {
299  RemoveDmacHandler(DMAC_SIF0, sif0_id);
300  init = 0;
301 }
302 #endif
303 
304 #ifdef F_sif_cmd_client
306 {
307  SifCmdHandlerData_t *old;
308 
312 
313  return old;
314 }
315 
316 void SifAddCmdHandler(int pos, SifCmdHandler_t handler, void *harg)
317 {
318  SifCmdHandlerData_t *cmd_handlers;
319  u32 id = pos & ~SIF_CMD_ID_SYSTEM;
320 
322 
323  cmd_handlers[id].handler = handler;
324  cmd_handlers[id].harg = harg;
325 }
326 #endif
327 
328 #ifdef F_sif_cmd_remove_cmdhandler
329 void SifRemoveCmdHandler(int pos)
330 {
331  u32 id = pos & ~SIF_CMD_ID_SYSTEM;
332 
333  if (pos & SIF_CMD_ID_SYSTEM)
335  else
337 }
338 #endif
339 
340 #ifdef F_sif_sreg_get
341 int SifGetSreg(int sreg)
342 {
343  return _sif_cmd_data.sregs[sreg];
344 }
345 #endif
packet_t packet
Definition: font.c:24
#define ExitHandler()
Definition: kernel.h:28
int DisableDmac(int dmac)
u32 SifSetDma(SifDmaTransfer_t *sdd, s32 len)
void SifSetDChain(void)
u32 iSifSetDma(SifDmaTransfer_t *sdd, s32 len)
void iSifSetDChain(void)
@ DMAC_SIF0
Definition: kernel.h:121
#define UNCACHED_SEG(x)
Definition: kernel.h:35
s32 AddDmacHandler(s32 channel, s32(*handler)(s32 channel), s32 next)
int SifSetReg(u32 register_num, int register_value)
s32 RemoveDmacHandler(s32 channel, s32 handler_id)
void FlushCache(s32 operation)
#define DI
Definition: kernel.h:24
#define EI
Definition: kernel.h:25
int SifGetReg(u32 register_num)
int EnableDmac(int dmac)
struct @29::@30 pos
s32 command
Definition: libpad.c:156
s32 mode
Definition: rpc_client.c:15
#define DMAC_COMM_STAT
Definition: sifcmd.c:30
#define CMD_PACKET_MAX
Definition: sifcmd.c:23
int _SifCmdIntHandler(int channel)
int _iop_reboot_count
#define CHCR_STR
Definition: sifcmd.c:32
struct cmd_data _sif_cmd_data
#define SYS_CMD_HANDLER_MAX
Definition: sifcmd.c:25
#define CMD_PACKET_DATA_MAX
Definition: sifcmd.c:24
#define STAT_SIF0
Definition: sifcmd.c:33
#define DMAC_SIF0_CHCR
Definition: sifcmd.c:31
#define USR_CMD_HANDLER_MAX
Definition: sifcmd.c:26
void SifRemoveCmdHandler(int pos)
void SifExitCmd(void)
int SifGetSreg(int index)
unsigned int SifSendCmd(int cmd, void *packet, int packet_size, void *src_extra, void *dest_extra, int size_extra)
#define SIF_CMD_ID_SYSTEM
Definition: sifcmd.h:37
#define SIF_CMD_CHANGE_SADDR
Definition: sifcmd.h:39
#define SIF_CMD_M_INTR
Definition: sifcmd.h:100
void SifWriteBackDCache(void *ptr, int size)
SifCmdHandlerData_t * SifSetCmdBuffer(SifCmdHandlerData_t *db, int size)
void(* SifCmdHandler_t)(void *data, void *harg)
Definition: sifcmd.h:63
#define SIF_CMD_INIT_CMD
Definition: sifcmd.h:41
void SifInitCmd(void)
#define SIF_CMD_M_WBDC
Definition: sifcmd.h:102
void SifAddCmdHandler(int pos, SifCmdHandler_t handler, void *harg)
unsigned int iSifSendCmd(int cmd, void *packet, int packet_size, void *src_extra, void *dest_extra, int size_extra)
#define SIF_STAT_CMDINIT
Definition: sifdma.h:48
#define SIF_DMA_ERT
Definition: sifdma.h:24
#define SIF_DMA_INT_O
Definition: sifdma.h:22
@ SIF_SYSREG_SUBADDR
Definition: sifdma.h:39
@ SIF_SYSREG_MAINADDR
Definition: sifdma.h:40
@ SIF_REG_SUBADDR
Definition: sifdma.h:32
@ SIF_REG_SMFLAG
Definition: sifdma.h:36
SifCmdHandler_t handler
Definition: sifcmd.h:67
void * dest
Definition: sifcmd.h:29
void * dest
Definition: sifdma.h:55
void * src
Definition: sifdma.h:54
u32 nr_usr_handlers
Definition: sifcmd.c:50
int * sregs
Definition: sifcmd.c:51
void * unused
Definition: sifcmd.c:44
void * iopbuf
Definition: sifcmd.c:46
SifCmdHandlerData_t * usr_cmd_handlers
Definition: sifcmd.c:49
SifCmdHandlerData_t * sys_cmd_handlers
Definition: sifcmd.c:47
void * pktbuf
Definition: sifcmd.c:43
u32 nr_sys_handlers
Definition: sifcmd.c:48
#define NULL
Definition: tamtypes.h:91
unsigned int u32
Definition: tamtypes.h:30
unsigned int u128
Definition: tamtypes.h:36
static u32 _lw(u32 addr)
Definition: tamtypes.h:96
static void _sw(u32 val, u32 addr)
Definition: tamtypes.h:100
unsigned char u8
Definition: tamtypes.h:23