PS2SDK
PS2 Homebrew Libraries
sif2cmd.c
1 /*
2 
3 Common PS2 SIF management API for both EE and IOP.
4 
5 This 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 
37 static u32 _sif2_req_type = 0;
38 static u32 _sif2_req_addr = 0;
39 static u32 _sif2_req_size = 0;
40 
41 static int __sif2_cmd_inited = 0;
42 
43 static SIF2_CmdHandler _sif2_cmd_handlers[SIF2_MAX_CMD_HANDLERS];
44 
45 // 512 byte command buffer(aligned 16 bytes)
46 static u32 _sif2_dma_cmd_buf[128] __attribute__((aligned(DMA_BUF_ALIGNMENT)));
47 
48 int 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 
65 int 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.
78 void _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 
89 void _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 
119 void WriteBackDCache(void *, u32);
120 
121 void 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 
166 void _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 
177 int 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 }
st_SIF2_CmdHandler
Definition: ps2_sbus.h:41
sysclib.h
st_SIF2_CmdPkt
Definition: ps2_sbus.h:27
ps2_sbus.h
__attribute__
typedef __attribute__
Definition: tlbfunc.c:60
tamtypes.h
stdio.h
__attribute__
Definition: gif_registers.h:38
ps2_reg_defs.h
st_SIF2_CmdPkt::cid
u32 cid
Definition: ps2_sbus.h:30