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