11#include "irx_imports.h"
14IRX_ID(
"S147LINK", 2, 7);
22 unsigned int nodemask;
26 unsigned int R_remain;
28 unsigned int R_lost[16];
29 unsigned int R_pd[16];
34 unsigned int T_remain;
37 unsigned int T_pd[16];
38 unsigned int T_time[16];
43 unsigned int offtimer;
48static int InitS147link(
int maxnode,
int mynode,
int priority);
49static unsigned int alarm_handler(
void *userdata);
50static void s147link_loop(
void *userdata);
51static void *dispatch(
int fno,
void *buf,
int size);
54static u8 rpc_buf[32784];
55static u8 rx_buff[512][64];
56static u8 tx_buff[256][64];
59int _start(
int argc,
char **argv)
65 maxnode = (argc >= 2) ? strtol(argv[1], 0, 10) : 0;
66 if ( maxnode < 2 || maxnode >= 16 )
68 mynode = (argc >= 3) ? strtol(argv[2], 0, 10) : 0;
69 if ( mynode <= 0 || maxnode < mynode )
71 priority = (argc >= 4) ? strtol(argv[3], 0, 10) : 0;
72 if ( priority < 9 || priority >= 124 )
74 gbBRE = (argc >= 5 && toupper(*argv[4]) ==
'N' && toupper(argv[4][1]) ==
'B' && toupper(argv[4][2]) ==
'R') ? 0 : 1;
75 printf(
"== S147LINK (%d/%d)@%d ", mynode, maxnode, priority);
79 if ( InitS147link(maxnode, mynode, priority) )
81 printf(
"S147LINK: Can't Initialize driver thread.\n");
82 return MODULE_NO_RESIDENT_END;
84 return MODULE_RESIDENT_END;
87static void T_fix(
CL_COM *io_pCommon)
89 if ( io_pCommon->T_remain >= 0x101 )
91 io_pCommon->T_remain = 0x100;
92 io_pCommon->T_out = 0;
93 io_pCommon->T_in = io_pCommon->T_out;
94 io_pCommon->rbfix += 1;
95 if ( !io_pCommon->rbfix )
96 io_pCommon->rbfix -= 1;
98 if ( io_pCommon->T_remain == 0x100 && io_pCommon->T_in != io_pCommon->T_out )
100 io_pCommon->T_out = 0;
101 io_pCommon->T_in = io_pCommon->T_out;
102 io_pCommon->rbfix += 1;
103 if ( !io_pCommon->rbfix )
104 io_pCommon->rbfix -= 1;
108static int clink_InterruptHandler(
void *userdata)
119 USE_S147LINK_DEV9_MEM_MMIO();
121 io_pCommon = (
CL_COM *)userdata;
122 stsH = s147link_dev9_mem_mmio->m_stsH_unk12;
123 stsL = s147link_dev9_mem_mmio->m_stsL_unk13;
124 if ( (stsL & 8) != 0 )
126 if ( (s147link_dev9_mem_mmio->m_unk03 & 8) != 0 )
128 s147link_dev9_mem_mmio->m_unk17 = 1;
129 s147link_dev9_mem_mmio->m_unk17 = 0xE;
131 if ( (s147link_dev9_mem_mmio->m_unk01 & 4) != 0 )
133 s147link_dev9_mem_mmio->m_unk17 = 0x16;
134 if ( !io_pCommon->ontimer )
135 io_pCommon->offtimer = 1;
136 io_pCommon->ontimer = 1;
141 ((s147link_dev9_mem_mmio->m_rxfc_hi_unk1E << 8) | s147link_dev9_mem_mmio->m_rxfc_lo_unk1F) & io_pCommon->nodemask;
144 for ( i = 1; io_pCommon->maxnode >= i; i += 1 )
146 if ( i != io_pCommon->mynode )
150 if ( (rxfs & (1 << i)) == 0 )
154 s147link_dev9_mem_mmio->m_node_unk05 = i | 0xC0;
155 s147link_dev9_mem_mmio->m_unk07 = 0;
156 unk09_tmp = s147link_dev9_mem_mmio->m_unk09;
157 if ( unk09_tmp == io_pCommon->mynode )
160 if ( s147link_dev9_mem_mmio->m_unk09 == 4 && !s147link_dev9_mem_mmio->m_unk09 )
164 rnum = s147link_dev9_mem_mmio->m_unk09;
165 if ( io_pCommon->R_number[i] != rnum )
167 unk09_tmp = s147link_dev9_mem_mmio->m_unk09;
168 if ( io_pCommon->R_remain )
172 bufptr = &io_pCommon->R_top[0x40 * io_pCommon->R_in];
174 bufptr[1] = io_pCommon->mynode;
178 bufptr[5] = unk09_tmp;
179 for ( j = 0; j < 0x3A; j += 1 )
180 bufptr[j + 6] = s147link_dev9_mem_mmio->m_unk09;
181 io_pCommon->R_remain -= 1;
182 io_pCommon->R_in += 1;
183 io_pCommon->R_in &= 0x1FF;
184 io_pCommon->R_number[i] = rnum;
186 else if ( io_pCommon->R_pd[i] )
188 io_pCommon->R_lost[i] += 1;
189 if ( !io_pCommon->R_lost[i] )
190 io_pCommon->R_lost[i] += 1;
199 else if ( !unk09_tmp )
201 if ( s147link_dev9_mem_mmio->m_unk09 == 0x38 )
203 s147link_dev9_mem_mmio->m_node_unk05 = i | 0xC0;
204 s147link_dev9_mem_mmio->m_unk07 = 0x38;
205 unk09_tmp = s147link_dev9_mem_mmio->m_unk09;
206 if ( (unk09_tmp & 0xE0) == 0x20 || (unk09_tmp & 0xE0) == 0x60 )
208 if ( io_pCommon->R_remain )
210 bufptr = &io_pCommon->R_top[0x40 * io_pCommon->R_in];
214 bufptr[56] = unk09_tmp;
215 bufptr[57] = s147link_dev9_mem_mmio->m_unk09;
216 bufptr[58] = s147link_dev9_mem_mmio->m_unk09;
217 bufptr[59] = s147link_dev9_mem_mmio->m_unk09;
218 bufptr[60] = s147link_dev9_mem_mmio->m_unk09;
219 bufptr[61] = s147link_dev9_mem_mmio->m_unk09;
220 bufptr[62] = s147link_dev9_mem_mmio->m_unk09;
221 bufptr[63] = s147link_dev9_mem_mmio->m_unk09;
222 io_pCommon->R_remain -= 1;
223 io_pCommon->R_in += 1;
224 io_pCommon->R_in &= 0x1FF;
226 else if ( io_pCommon->R_pd[i] )
228 io_pCommon->R_lost[i] += 1;
229 if ( !io_pCommon->R_lost[i] )
230 io_pCommon->R_lost[i] += 1;
244 if ( (stsL & 0x10) != 0 )
246 s147link_dev9_mem_mmio->m_unk17 = 1;
247 s147link_dev9_mem_mmio->m_unk17 = 0xE;
249 if ( (stsL & 2) != 0 && (stsL & 4) == 0 && io_pCommon->timeout )
253 else if ( (stsL & 1) != 0 )
255 io_pCommon->timeout = 0;
258 if ( io_pCommon->T_remain == 0x100 )
260 s147link_dev9_mem_mmio->m_unk15 = 0x1A;
263 bufptr = &io_pCommon->T_top[0x40 * io_pCommon->T_out];
264 if ( *bufptr == io_pCommon->mynode )
266 io_pCommon->T_node = bufptr[1];
267 if ( !io_pCommon->T_error[io_pCommon->T_node] || !io_pCommon->T_pd[io_pCommon->T_node] )
269 s147link_dev9_mem_mmio->m_node_unk05 = (io_pCommon->mynode & 0xFF) | 0x40;
270 s147link_dev9_mem_mmio->m_unk07 = 0;
271 for ( i = 0; i < 0x40; i += 1 )
272 s147link_dev9_mem_mmio->m_unk09 = bufptr[i];
273 io_pCommon->T_remain += 1;
274 io_pCommon->T_out += 1;
275 io_pCommon->T_out &= 0xFF;
277 s147link_dev9_mem_mmio->m_unk15 = 0x1B;
279 io_pCommon->timeout = 1;
283 io_pCommon->T_remain += 1;
284 io_pCommon->T_out += 1;
285 io_pCommon->T_out &= 0xFF;
291 s147link_dev9_mem_mmio->m_unk17 = 3;
294 s147link_dev9_mem_mmio->m_rxfc_hi_unk1E = (rxfc >> 8) & 0xFF;
295 s147link_dev9_mem_mmio->m_rxfc_lo_unk1F = rxfc;
297 s147link_dev9_mem_mmio->m_stsH_unk12 = stsH;
298 s147link_dev9_mem_mmio->m_stsL_unk13 = stsL;
303static int cl_mread(
void *dstptr,
int count)
310 size = 0x200 - cl_info.R_remain;
311 if ( cl_info.R_remain == 0x200 )
320 packs = cl_info.R_out + size - 0x200;
325 memcpy(dstptr, rx_buff[cl_info.R_out], size);
326 memcpy((
char *)dstptr + size, rx_buff, packs << 6);
330 memcpy(dstptr, rx_buff[cl_info.R_out], size << 6);
332 cl_info.R_remain +=
count;
333 cl_info.R_out +=
count;
334 cl_info.R_out &= 0x1FF;
335 if ( cl_info.R_remain >= 0x201 )
337 cl_info.R_remain = 0x200;
341 if ( !cl_info.rbfix )
345 if ( cl_info.R_remain == 512 && cl_info.R_in != cl_info.R_out )
350 if ( !cl_info.rbfix )
358static int cl_write(
int node, u8 *srcptr,
int size)
361 USE_S147LINK_DEV9_MEM_MMIO();
364 if ( !cl_info.T_remain || size >= 0x41 )
369 memcpy(tx_buff[cl_info.T_in], srcptr, size);
370 tx_buff[cl_info.T_in][0] = cl_info.mynode;
371 tx_buff[cl_info.T_in][1] = node & 0xFF;
372 tx_buff[cl_info.T_in][2] = 4;
373 tx_buff[cl_info.T_in][3] = 0;
374 cl_info.T_number += 1;
375 tx_buff[cl_info.T_in][4] = cl_info.T_number;
376 cl_info.T_remain -= 1;
378 cl_info.T_in &= 0xFF;
379 s147link_dev9_mem_mmio->m_unk15 = 0x1B;
380 clink_InterruptHandler(&cl_info);
385static int cl_write_custom(
int node, u8 *srcptr,
int cpVal)
388 USE_S147LINK_DEV9_MEM_MMIO();
391 if ( !cl_info.T_remain )
396 memcpy(tx_buff[cl_info.T_in], srcptr,
sizeof(u8[64]));
397 tx_buff[cl_info.T_in][0] = cl_info.mynode;
398 tx_buff[cl_info.T_in][1] = node & 0xFF;
399 tx_buff[cl_info.T_in][2] = cpVal & 0xFF;
400 cl_info.T_remain -= 1;
402 cl_info.T_in &= 0xFF;
403 s147link_dev9_mem_mmio->m_unk15 = 0x1B;
404 clink_InterruptHandler(&cl_info);
409static int cl_mwrite(u8 *srcptr,
int count)
414 USE_S147LINK_DEV9_MEM_MMIO();
416 if ( cl_info.T_remain < (
unsigned int)
count )
418 if (
count >= 0x101 )
420 for ( i = 0; i <
count; i += 1 )
422 srcptr[(i * 0x40)] = cl_info.mynode;
423 srcptr[(i * 0x40) + 2] = 4;
424 srcptr[(i * 0x40) + 3] = 0;
425 srcptr[(i * 0x40) + 4] = cl_info.T_number + i + 1;
427 cl_info.T_number += i;
429 if ( cl_info.T_remain < (
unsigned int)
count )
434 packs = cl_info.T_in +
count - 0x100;
437 memcpy(tx_buff[cl_info.T_in], srcptr, (
count - packs) << 6);
438 memcpy(tx_buff, &srcptr[0x40 * (
count - packs)], packs << 6);
442 memcpy(tx_buff[cl_info.T_in], srcptr,
count << 6);
444 cl_info.T_remain -=
count;
445 cl_info.T_in +=
count;
446 cl_info.T_in &= 0xFF;
447 s147link_dev9_mem_mmio->m_unk15 = 0x1B;
448 clink_InterruptHandler(&cl_info);
453static int InitS147link(
int maxnode,
int mynode,
int priority)
462 USE_S147LINK_DEV9_MEM_MMIO();
464 s147link_dev9_mem_mmio->m_unk0D |= 0x80;
465 s147link_dev9_mem_mmio->m_unk22 = 2;
466 s147link_dev9_mem_mmio->m_unk23 = gbBRE ? 0x51 : 0x11;
467 s147link_dev9_mem_mmio->m_maxnode_unk2B = maxnode;
468 s147link_dev9_mem_mmio->m_mynode_unk2D = mynode;
469 s147link_dev9_mem_mmio->m_unk31 = 0;
470 s147link_dev9_mem_mmio->m_unk2F = 2;
471 for ( i = 0; i < 4; i += 1 )
473 s147link_dev9_mem_mmio->m_node_unk05 = i | 0x40;
474 s147link_dev9_mem_mmio->m_unk07 = 0;
475 for ( j = 0; j < 256; j += 1 )
476 s147link_dev9_mem_mmio->m_unk09 = 0;
478 s147link_dev9_mem_mmio->m_unk28 = 0;
479 s147link_dev9_mem_mmio->m_unk29 = 0;
480 s147link_dev9_mem_mmio->m_unk21 = 0;
481 s147link_dev9_mem_mmio->m_unk24 = 0;
482 s147link_dev9_mem_mmio->m_unk25 = 0xFF;
483 s147link_dev9_mem_mmio->m_unk0D &= 0x7F;
484 s147link_dev9_mem_mmio->m_unk22 |= 1;
485 s147link_dev9_mem_mmio->m_node_unk05 = mynode | 0x40;
486 s147link_dev9_mem_mmio->m_unk07 = 0;
487 s147link_dev9_mem_mmio->m_unk09 = mynode;
488 s147link_dev9_mem_mmio->m_unk09 = 2;
489 s147link_dev9_mem_mmio->m_unk09 = 4;
490 cl_info.mynode = mynode;
491 cl_info.maxnode = maxnode;
493 for ( i = 0; i < maxnode; i += 1 )
497 cl_info.nodemask = j;
498 cl_info.R_top = rx_buff[0];
499 cl_info.R_remain = 0x200;
502 for ( i = 0; i < 16; i += 1 )
504 cl_info.R_number[i] = 0;
505 cl_info.T_error[i] = 0;
506 cl_info.R_lost[i] = 0;
509 cl_info.T_time[i] = 2;
511 cl_info.T_top = tx_buff[0];
512 cl_info.T_remain = 0x100;
513 cl_info.offtimer = 0;
519 cl_info.T_number = 0;
525 s147link_dev9_mem_mmio->m_unk01 = 0xC;
526 s147link_dev9_mem_mmio->m_unk14 = 0x8E;
527 s147link_dev9_mem_mmio->m_unk15 = 0x1A;
528 s147link_dev9_mem_mmio->m_unk1C = 0xFF;
529 s147link_dev9_mem_mmio->m_unk1D = 0xFF;
530 s147link_dev9_mem_mmio->m_rxfc_hi_unk1E = 0xFF;
531 s147link_dev9_mem_mmio->m_rxfc_lo_unk1F = 0xFF;
532 stsH = s147link_dev9_mem_mmio->m_stsH_unk12;
533 stsL = s147link_dev9_mem_mmio->m_stsL_unk13;
534 s147link_dev9_mem_mmio->m_stsH_unk12 = stsH;
535 s147link_dev9_mem_mmio->m_stsL_unk13 = stsL;
540 param.thread = s147link_loop;
541 param.priority = priority;
542 param.stacksize = 0x800;
544 thid = CreateThread(¶m);
547 printf(
"S147LINK: Cannot create RPC server thread ...\n");
550 if ( StartThread(thid, 0) )
552 printf(
"S147LINK: Cannot start RPC server thread ...\n");
556 USec2SysClock(0x7D0, &cl_info.sys_clock);
557 if ( SetAlarm(&cl_info.sys_clock, alarm_handler, &cl_info) )
559 printf(
"S147LINK: Cannot set alarm handler ...\n");
567static void reset_circlink(
void)
573 USE_S147LINK_DEV9_MEM_MMIO();
575 s147link_dev9_mem_mmio->m_unk0D |= 0x80;
576 s147link_dev9_mem_mmio->m_unk22 = 2;
577 s147link_dev9_mem_mmio->m_unk23 = gbBRE ? 0x51 : 0x11;
578 s147link_dev9_mem_mmio->m_maxnode_unk2B = cl_info.maxnode;
579 s147link_dev9_mem_mmio->m_mynode_unk2D = cl_info.mynode;
580 s147link_dev9_mem_mmio->m_unk31 = 0;
581 s147link_dev9_mem_mmio->m_unk2F = 2;
582 for ( i = 0; i < 4; i += 1 )
584 s147link_dev9_mem_mmio->m_node_unk05 = i | 0x40;
585 s147link_dev9_mem_mmio->m_unk07 = 0;
586 for ( j = 0; j < 256; j += 1 )
587 s147link_dev9_mem_mmio->m_unk09 = 0;
589 s147link_dev9_mem_mmio->m_unk28 = 0;
590 s147link_dev9_mem_mmio->m_unk29 = 0;
591 s147link_dev9_mem_mmio->m_unk21 = 0;
592 s147link_dev9_mem_mmio->m_unk24 = 0;
593 s147link_dev9_mem_mmio->m_unk25 = 0xFF;
594 s147link_dev9_mem_mmio->m_unk0D &= 0x7F;
595 s147link_dev9_mem_mmio->m_unk22 |= 1;
596 s147link_dev9_mem_mmio->m_node_unk05 = (cl_info.mynode & 0xFF) | 0x40;
597 s147link_dev9_mem_mmio->m_unk07 = 0;
598 s147link_dev9_mem_mmio->m_unk09 = cl_info.mynode;
599 s147link_dev9_mem_mmio->m_unk09 = 2;
600 s147link_dev9_mem_mmio->m_unk09 = 4;
601 s147link_dev9_mem_mmio->m_unk01 = 0xC;
602 s147link_dev9_mem_mmio->m_unk14 = 0x8E;
603 s147link_dev9_mem_mmio->m_unk15 = 0x1A;
604 s147link_dev9_mem_mmio->m_unk1C = 0xFF;
605 s147link_dev9_mem_mmio->m_unk1D = 0xFF;
606 s147link_dev9_mem_mmio->m_rxfc_hi_unk1E = 0xFF;
607 s147link_dev9_mem_mmio->m_rxfc_lo_unk1F = 0xFF;
608 stsH = s147link_dev9_mem_mmio->m_stsH_unk12;
609 stsL = s147link_dev9_mem_mmio->m_stsL_unk13;
610 s147link_dev9_mem_mmio->m_stsH_unk12 = stsH;
611 s147link_dev9_mem_mmio->m_stsL_unk13 = stsL;
615static unsigned int alarm_handler(
void *userdata)
619 USE_S147LINK_DEV9_MEM_MMIO();
621 io_pCommon = (
CL_COM *)userdata;
622 if ( io_pCommon->timeout )
624 if ( io_pCommon->T_time[io_pCommon->T_node] )
626 if ( io_pCommon->T_time[io_pCommon->T_node] >= io_pCommon->timeout )
628 io_pCommon->timeout += 1;
633 (void)s147link_dev9_mem_mmio->m_stsL_unk13;
634 io_pCommon->timeout = 0;
635 s147link_dev9_mem_mmio->m_unk17 = 1;
636 s147link_dev9_mem_mmio->m_unk17 = 0xE;
637 cl_info.T_error[cl_info.T_node] = 0xFFFFFFFE;
638 s147link_dev9_mem_mmio->m_unk15 = 0x1B;
639 clink_InterruptHandler(&cl_info);
645 io_pCommon->timeout = 0;
648 if ( io_pCommon->ontimer )
650 if ( io_pCommon->ontimer < 0xFA )
652 io_pCommon->ontimer += 1;
656 io_pCommon->online = 1;
657 io_pCommon->offtimer = 0;
658 io_pCommon->ontimer = io_pCommon->offtimer;
661 if ( io_pCommon->offtimer )
663 if ( io_pCommon->offtimer < 0xFA )
664 io_pCommon->offtimer += 1;
666 io_pCommon->online = 0;
668 return io_pCommon->sys_clock.lo;
671static void s147link_loop(
void *userdata)
677 sceSifSetRpcQueue(&qd, GetThreadId());
678 sceSifRegisterRpc(&sd, 0x14799, dispatch, rpc_buf, 0, 0, &qd);
682static void *dispatch(
int fno,
void *buf,
int size)
688 USE_S147LINK_DEV9_MEM_MMIO();
693 sizeb = (fno & 0xFFFF00) >> 8;
700 cl_info.R_pd[node] = *(u32 *)buf;
701 cl_info.T_pd[node] = *((u32 *)buf + 1);
702 cl_info.T_time[node] = *((u32 *)buf + 2);
708 cl_info.T_remain = 0x100;
709 s147link_dev9_mem_mmio->m_unk17 = 1;
710 s147link_dev9_mem_mmio->m_unk17 = 0xE;
711 cl_info.T_error[cl_info.T_node] = 0xFFFFFFFD;
712 *(u32 *)buf = cl_info.T_node;
716 *(u32 *)buf = cl_info.rbfix;
719 *(u32 *)buf = cl_mread((
char *)buf + 4, *(u32 *)buf);
721 clink_InterruptHandler(&cl_info);
725 *(u32 *)buf = cl_write(node, (u8 *)buf, sizeb);
728 *(u32 *)buf = cl_mwrite((u8 *)buf, sizeb);
734 cl_info.R_remain = 0x200;
738 *(u32 *)buf = cl_info.R_remain;
741 *(u32 *)buf = cl_info.T_remain;
744 *(u32 *)buf = cl_info.online;
747 *(u32 *)buf = cl_info.T_error[node];
751 cl_info.T_error[node] = 0;
752 s147link_dev9_mem_mmio->m_unk15 = 0x1B;
753 clink_InterruptHandler(&cl_info);
758 s147link_dev9_mem_mmio->m_unk17 = 1;
759 s147link_dev9_mem_mmio->m_unk17 = 0xE;
760 cl_info.T_error[cl_info.T_node] = 0xFFFFFFFD;
761 *(u32 *)buf = cl_info.T_node;
762 s147link_dev9_mem_mmio->m_unk15 = 0x1B;
763 clink_InterruptHandler(&cl_info);
767 *(u32 *)buf = cl_info.R_lost[node];
768 cl_info.R_lost[node] = 0;
771 *(u32 *)buf = cl_write_custom(node, (u8 *)buf, sizeb);
775 clink_InterruptHandler(&cl_info);
779 printf(
"S147LINK: Unknown RPC command (%X)\n", fno);
782 *(u32 *)buf |= (cl_info.online ? 0x10000 : 0);
783 for ( i = 1; i < cl_info.maxnode; i += 1 )
785 if ( cl_info.T_error[i] )
786 *(u32 *)buf |= 0x10000 << i;
787 if ( cl_info.R_lost[i] )
788 *(u32 *)buf |= 0x10000 << i;
int CpuResumeIntr(int state)
int ReleaseIntrHandler(int irq)
int CpuSuspendIntr(int *state)
int RegisterIntrHandler(int irq, int mode, int(*handler)(void *arg), void *arg)
u32 count
start sector of fragmented bd/file