PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
sio2man.c
Go to the documentation of this file.
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# Copyright ps2dev - http://www.ps2dev.org
7# Licenced under Academic Free License version 2.0
8# Review ps2sdk README & LICENSE files for further details.
9*/
10
11#include "irx_imports.h"
12
18#include <iop_mmio_hwport.h>
19#include <rsio2man.h>
20
21#ifdef SIO2LOG
22#include "log.h"
23#endif
24
25#ifdef SIO2LOG
26IRX_ID("sio2man_logger", 3, 17);
27#else
28IRX_ID("sio2man", 3, 17);
29#endif
30// Based on the module from SDK 3.1.0.
31
32extern struct irx_export_table _exp_sio2man;
33extern struct irx_export_table _exp_sio2man1;
34
35// Unofficial: remove unused structure members
37{
38 // Unofficial: move inited into bss section
39 int m_inited;
40 int m_intr_sema;
41 int m_transfer_semaphore;
42 // Unofficial: backwards compatibility for libraries using 1.3 SDK
43 int m_sdk13x_flag;
44 sio2_mtap_change_slot_cb_t m_mtap_change_slot_cb;
45 sio2_mtap_get_slot_max_cb_t m_mtap_get_slot_max_cb;
46 sio2_mtap_get_slot_max2_cb_t m_mtap_get_slot_max2_cb;
47 sio2_mtap_update_slots_t m_mtap_update_slots_cb;
48};
49
50#define EPRINTF(format, args...) printf("%s: " format, _irx_id.n, ##args)
51
52static struct sio2man_internal_data g_sio2man_data;
53
54#ifdef SIO2MAN_NANO
55#define sio2_ctrl_set inl_sio2_ctrl_set
56#define sio2_ctrl_get inl_sio2_ctrl_get
57#define sio2_stat6c_get inl_sio2_stat6c_get
58#define sio2_portN_ctrl1_set inl_sio2_portN_ctrl1_set
59#define sio2_portN_ctrl2_set inl_sio2_portN_ctrl2_set
60#define sio2_regN_set inl_sio2_regN_set
61#define sio2_stat74_get inl_sio2_stat74_get
62#define sio2_data_out inl_sio2_data_out
63#define sio2_data_in inl_sio2_data_in
64#define sio2_stat_set inl_sio2_stat_set
65#define sio2_stat_get inl_sio2_stat_get
66#define sio2_set_ctrl_c inl_sio2_set_ctrl_c
67#define sio2_set_ctrl_1 inl_sio2_set_ctrl_1
68#define NANO_STATIC static inline
69#else
70#define NANO_STATIC
71#endif
72
73NANO_STATIC void sio2_ctrl_set(u32 val)
74{
75 USE_IOP_MMIO_HWPORT();
76
77 iop_mmio_hwport->sio2.ctrl = val;
78}
79
80NANO_STATIC u32 sio2_ctrl_get(void)
81{
82 USE_IOP_MMIO_HWPORT();
83
84 return iop_mmio_hwport->sio2.ctrl;
85}
86
87NANO_STATIC u32 sio2_stat6c_get(void)
88{
89 USE_IOP_MMIO_HWPORT();
90
91 return iop_mmio_hwport->sio2.recv1;
92}
93
94NANO_STATIC void sio2_portN_ctrl1_set(int N, u32 val)
95{
96 USE_IOP_MMIO_HWPORT();
97
98 iop_mmio_hwport->sio2.send1_2_buf[N * 2] = val;
99}
100
101#ifndef SIO2MAN_NANO
102u32 sio2_portN_ctrl1_get(int N)
103{
104 USE_IOP_MMIO_HWPORT();
105
106 return iop_mmio_hwport->sio2.send1_2_buf[N * 2];
107}
108#endif
109
110NANO_STATIC void sio2_portN_ctrl2_set(int N, u32 val)
111{
112 USE_IOP_MMIO_HWPORT();
113
114 iop_mmio_hwport->sio2.send1_2_buf[(N * 2) + 1] = val;
115}
116
117#ifndef SIO2MAN_NANO
118u32 sio2_portN_ctrl2_get(int N)
119{
120 USE_IOP_MMIO_HWPORT();
121
122 return iop_mmio_hwport->sio2.send1_2_buf[(N * 2) + 1];
123}
124#endif
125
126u32 sio2_stat70_get(void)
127{
128 USE_IOP_MMIO_HWPORT();
129
130 return iop_mmio_hwport->sio2.recv2;
131}
132
133NANO_STATIC void sio2_regN_set(int N, u32 val)
134{
135 USE_IOP_MMIO_HWPORT();
136
137 iop_mmio_hwport->sio2.send3_buf[N] = val;
138}
139
140#ifndef SIO2MAN_NANO
141u32 sio2_regN_get(int N)
142{
143 USE_IOP_MMIO_HWPORT();
144
145 return iop_mmio_hwport->sio2.send3_buf[N];
146}
147#endif
148
149NANO_STATIC u32 sio2_stat74_get(void)
150{
151 USE_IOP_MMIO_HWPORT();
152
153 return iop_mmio_hwport->sio2.recv3;
154}
155
156#ifndef SIO2MAN_NANO
157void sio2_unkn78_set(u32 val)
158{
159 USE_IOP_MMIO_HWPORT();
160
161 iop_mmio_hwport->sio2.unk_78 = val;
162}
163#endif
164
165#ifndef SIO2MAN_NANO
166u32 sio2_unkn78_get(void)
167{
168 USE_IOP_MMIO_HWPORT();
169
170 return iop_mmio_hwport->sio2.unk_78;
171}
172#endif
173
174#ifndef SIO2MAN_NANO
175void sio2_unkn7c_set(u32 val)
176{
177 USE_IOP_MMIO_HWPORT();
178
179 iop_mmio_hwport->sio2.unk_7c = val;
180}
181#endif
182
183#ifndef SIO2MAN_NANO
184u32 sio2_unkn7c_get(void)
185{
186 USE_IOP_MMIO_HWPORT();
187
188 return iop_mmio_hwport->sio2.unk_7c;
189}
190#endif
191
192NANO_STATIC void sio2_data_out(u8 val)
193{
194 USE_IOP_MMIO_HWPORT();
195
196 iop_mmio_hwport->sio2.out_fifo = val;
197}
198
199NANO_STATIC u8 sio2_data_in(void)
200{
201 USE_IOP_MMIO_HWPORT();
202
203 return iop_mmio_hwport->sio2.in_fifo;
204}
205
206NANO_STATIC void sio2_stat_set(u32 val)
207{
208 USE_IOP_MMIO_HWPORT();
209
210 iop_mmio_hwport->sio2.stat = val;
211}
212
213NANO_STATIC u32 sio2_stat_get(void)
214{
215 USE_IOP_MMIO_HWPORT();
216
217 return iop_mmio_hwport->sio2.stat;
218}
219
220static void send_td(sio2_transfer_data_t *td)
221{
222 int i;
223
224#ifdef SIO2LOG
225 log_default(LOG_TRS);
226#endif
227
228 for ( i = 0; i < 4; i += 1 )
229 {
230 sio2_portN_ctrl1_set(i, td->port_ctrl1[i]);
231 sio2_portN_ctrl2_set(i, td->port_ctrl2[i]);
232 }
233
234#ifdef SIO2LOG
235 log_portdata(td->port_ctrl1, td->port_ctrl2);
236#endif
237
238 for ( i = 0; i < 16; i += 1 )
239 sio2_regN_set(i, td->regdata[i]);
240
241#ifdef SIO2LOG
242 log_regdata(td->regdata);
243#endif
244
245 for ( i = 0; i < (int)td->in_size; i += 1 )
246 sio2_data_out(td->in[i]);
247#ifdef SIO2LOG
248 if ( td->in_size )
249 log_data(LOG_TRS_DATA, td->in, td->in_size);
250#endif
251 if ( td->in_dma.addr )
252 {
253 sceSetSliceDMA(IOP_DMAC_SIO2in, td->in_dma.addr, td->in_dma.size, td->in_dma.count, DMAC_FROM_MEM);
254 sceStartDMA(IOP_DMAC_SIO2in);
255#ifdef SIO2LOG
256 log_dma(LOG_TRS_DMA_IN, &td->in_dma);
257#endif
258 }
259 if ( td->out_dma.addr )
260 {
261 sceSetSliceDMA(IOP_DMAC_SIO2out, td->out_dma.addr, td->out_dma.size, td->out_dma.count, DMAC_TO_MEM);
262 sceStartDMA(IOP_DMAC_SIO2out);
263#ifdef SIO2LOG
264 log_dma(LOG_TRS_DMA_OUT, &td->out_dma);
265#endif
266 }
267}
268
269static void recv_td(sio2_transfer_data_t *td)
270{
271 int i;
272
273#ifdef SIO2LOG
274 log_default(LOG_TRR);
275#endif
276 td->stat6c = sio2_stat6c_get();
277 td->stat70 = sio2_stat70_get();
278 td->stat74 = sio2_stat74_get();
279#ifdef SIO2LOG
280 log_stat(td->stat6c, td->stat70, td->stat74);
281#endif
282 for ( i = 0; i < (int)td->out_size; i += 1 )
283 td->out[i] = sio2_data_in();
284#ifdef SIO2LOG
285 if ( td->out_size )
286 log_data(LOG_TRR_DATA, td->out, td->out_size);
287#endif
288}
289
290static int sio2_intr_handler(const struct sio2man_internal_data *arg)
291{
292 sio2_stat_set(sio2_stat_get());
293 iSignalSema(arg->m_intr_sema);
294 return 1;
295}
296
297int _start(int ac, char **av)
298{
299 iop_sema_t semaparam;
300 int state;
301
302 (void)ac;
303 (void)av;
304
305 if ( RegisterLibraryEntries(&_exp_sio2man) != 0 )
306 return 1;
307 // Unofficial: register same name but older major version for backwards compatibility
308 _exp_sio2man1.name[7] = '\x00';
309 if ( RegisterLibraryEntries(&_exp_sio2man1) != 0 )
310 return 1;
311 if ( g_sio2man_data.m_inited )
312 return 1;
313 g_sio2man_data.m_inited = 1;
314 g_sio2man_data.m_sdk13x_flag = 0;
315 // Unofficial: remove unneeded thread priority argument handler
316 g_sio2man_data.m_mtap_change_slot_cb = 0;
317 g_sio2man_data.m_mtap_get_slot_max_cb = 0;
318 g_sio2man_data.m_mtap_get_slot_max2_cb = 0;
319 g_sio2man_data.m_mtap_update_slots_cb = 0;
320 // Unofficial: inlined
321 sio2_ctrl_set(0x3BC);
322 CpuSuspendIntr(&state);
323 RegisterIntrHandler(IOP_IRQ_SIO2, 1, (int (*)(void *))sio2_intr_handler, &g_sio2man_data);
324 EnableIntr(IOP_IRQ_SIO2);
325 CpuResumeIntr(state);
326 sceSetDMAPriority(IOP_DMAC_SIO2in, 3);
327 sceSetDMAPriority(IOP_DMAC_SIO2out, 3);
328 sceEnableDMAChannel(IOP_DMAC_SIO2in);
329 sceEnableDMAChannel(IOP_DMAC_SIO2out);
330 semaparam.attr = 0;
331 semaparam.option = 0;
332 semaparam.initial = 1;
333 semaparam.max = 64;
334 g_sio2man_data.m_transfer_semaphore = CreateSema(&semaparam);
335 semaparam.attr = 0;
336 semaparam.option = 0;
337 semaparam.initial = 0;
338 semaparam.max = 64;
339 g_sio2man_data.m_intr_sema = CreateSema(&semaparam);
340#ifdef SIO2LOG
341 EPRINTF("Logging started.\n");
342#endif
343 return 0;
344}
345
346void _deinit()
347{
348 int state;
349
350 // Unofficial: check inited
351 if ( !g_sio2man_data.m_inited )
352 return;
353#ifdef SIO2LOG
354 log_flush(1);
355#endif
356 // Unofficial: unset inited
357 g_sio2man_data.m_inited = 0;
358 // Unofficial: remove unused GetThreadId
359 CpuSuspendIntr(&state);
360 DisableIntr(IOP_IRQ_SIO2, 0);
361 ReleaseIntrHandler(IOP_IRQ_SIO2);
362 CpuResumeIntr(state);
363 sceDisableDMAChannel(IOP_DMAC_SIO2in);
364 sceDisableDMAChannel(IOP_DMAC_SIO2out);
365 DeleteSema(g_sio2man_data.m_intr_sema);
366 DeleteSema(g_sio2man_data.m_transfer_semaphore);
367}
368
369#ifndef SIO2MAN_NANO
370void sio2_set_intr_handler(int (*handler)(void *), void *userdata)
371{
372 int state;
373
374 CpuSuspendIntr(&state);
375 DisableIntr(IOP_IRQ_SIO2, 0);
376 ReleaseIntrHandler(IOP_IRQ_SIO2);
378 IOP_IRQ_SIO2, 1, handler ? handler : (int (*)(void *))sio2_intr_handler, handler ? userdata : &g_sio2man_data);
379 EnableIntr(IOP_IRQ_SIO2);
380 CpuResumeIntr(state);
381}
382#endif
383
384NANO_STATIC void sio2_set_ctrl_c()
385{
386 // Unofficial: inlined
387 sio2_ctrl_set(sio2_ctrl_get() | 0xC);
388}
389
390NANO_STATIC void sio2_set_ctrl_1()
391{
392 // Unofficial: inlined
393 sio2_ctrl_set(sio2_ctrl_get() | 1);
394}
395
396void sio2_wait_for_intr()
397{
398 WaitSema(g_sio2man_data.m_intr_sema);
399}
400
401int sio2_transfer(sio2_transfer_data_t *td)
402{
403 // Unofficial: remove unused transfer data global
404 // Unofficial: replace with inlined func
405 sio2_set_ctrl_c();
406 send_td(td);
407 // Unofficial: replace with inlined func
408 sio2_set_ctrl_1();
409 sio2_wait_for_intr();
410 recv_td(td);
411 if ( g_sio2man_data.m_sdk13x_flag )
412 sio2_transfer_reset();
413#ifdef SIO2LOG
414 log_flush(0);
415#endif
416 return 1;
417}
418
419void sio2_pad_transfer_init(void)
420{
421#ifdef SIO2LOG
422 log_flush(0);
423#endif
424 WaitSema(g_sio2man_data.m_transfer_semaphore);
425#ifdef SIO2LOG
426 log_default(LOG_PAD_READY);
427#endif
428 g_sio2man_data.m_sdk13x_flag = 0;
429}
430
431void sio2_pad_transfer_init_possiblysdk13x(void)
432{
433 sio2_pad_transfer_init();
434 g_sio2man_data.m_sdk13x_flag = 1;
435}
436
437void sio2_transfer_reset(void)
438{
439 g_sio2man_data.m_sdk13x_flag = 0;
440 SignalSema(g_sio2man_data.m_transfer_semaphore);
441#ifdef SIO2LOG
442 log_default(LOG_RESET);
443#endif
444}
445
446void sio2_mtap_change_slot_set(sio2_mtap_change_slot_cb_t cb)
447{
448 g_sio2man_data.m_mtap_change_slot_cb = cb;
449}
450
451void sio2_mtap_get_slot_max_set(sio2_mtap_get_slot_max_cb_t cb)
452{
453 g_sio2man_data.m_mtap_get_slot_max_cb = cb;
454}
455
456void sio2_mtap_get_slot_max2_set(sio2_mtap_get_slot_max2_cb_t cb)
457{
458 g_sio2man_data.m_mtap_get_slot_max2_cb = cb;
459}
460
461void sio2_mtap_update_slots_set(sio2_mtap_update_slots_t cb)
462{
463 g_sio2man_data.m_mtap_update_slots_cb = cb;
464}
465
466int sio2_mtap_change_slot(s32 *arg)
467{
468 int sum;
469 int i;
470
471 g_sio2man_data.m_sdk13x_flag = 0;
472 if ( g_sio2man_data.m_mtap_change_slot_cb )
473 return g_sio2man_data.m_mtap_change_slot_cb(arg);
474 sum = 0;
475 for ( i = 0; i < 4; i += 1 )
476 {
477 arg[i + 4] = ((arg[i] + 1) < 2);
478 sum += arg[i + 4];
479 }
480 return sum == 4;
481}
482
483int sio2_mtap_get_slot_max(int port)
484{
485 return g_sio2man_data.m_mtap_get_slot_max_cb ? g_sio2man_data.m_mtap_get_slot_max_cb(port) : 1;
486}
487
488int sio2_mtap_get_slot_max2(int port)
489{
490 return g_sio2man_data.m_mtap_get_slot_max2_cb ? g_sio2man_data.m_mtap_get_slot_max2_cb(port) : 1;
491}
492
493void sio2_mtap_update_slots(void)
494{
495 if ( g_sio2man_data.m_mtap_update_slots_cb )
496 g_sio2man_data.m_mtap_update_slots_cb();
497}
int CpuResumeIntr(int state)
Definition intrman.c:227
int RegisterIntrHandler(int irq, int mode, int(*handler)(void *), void *arg)
Definition intrman.c:125
int ReleaseIntrHandler(int irq)
Definition intrman.c:167
int DisableIntr(int irq, int *res)
Definition intrman.c:395
int CpuSuspendIntr(int *state)
Definition intrman.c:205
int EnableIntr(int irq)
Definition intrman.c:346