PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
eeconf.c
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#include <dev5_mmio_hwport.h>
13#include <iop_mmio_hwport.h>
14
15IRX_ID("EEConfig", 1, 1);
16// Based on the module from ROM 2.20+.
17
18static int eeconf_config_numblocks;
19
20static int eeconf_writeread_scmd(char cmd, const char *sdata, int sdlen, char *rdata, int rdlen)
21{
22 int rdlen_tmp;
23 int i;
24 char rdata_tmp[64];
25 USE_DEV5_MMIO_HWPORT();
26
27 rdlen_tmp = rdlen;
28 if ( (dev5_mmio_hwport->m_dev5_reg_017 & 0x80) != 0 )
29 return 0;
30 while ( (dev5_mmio_hwport->m_dev5_reg_017 & 0x40) == 0 )
31 ;
32 for ( i = 0; i < sdlen; i += 1 )
33 dev5_mmio_hwport->m_dev5_reg_017 = sdata[i];
34 dev5_mmio_hwport->m_dev5_reg_016 = cmd;
35 while ( (dev5_mmio_hwport->m_dev5_reg_017 & 0x80) != 0 )
36 ;
37 for ( i = 0; (dev5_mmio_hwport->m_dev5_reg_017 & 0x40) == 0; i += 1 )
38 rdata_tmp[i] = dev5_mmio_hwport->m_dev5_reg_018;
39 if ( rdlen_tmp > i )
40 rdlen_tmp = i;
41 for ( i = 0; i < rdlen_tmp; i += 1 )
42 rdata[i] = rdata_tmp[i];
43 return 1;
44}
45
46static int eeconf_open_config(int block, int mode, int NumBlocks, char *status)
47{
48 int wdata;
49
50 wdata = (u8)mode | ((u8)block << 8) | ((u8)NumBlocks << 16);
51 eeconf_config_numblocks = NumBlocks;
52 return eeconf_writeread_scmd(64, (const char *)&wdata, 3, status, 1);
53}
54
55static int eeconf_close_config(char *status)
56{
57 int result;
58
59 result = eeconf_writeread_scmd(67, 0, 0, status, 1);
60 eeconf_config_numblocks = 0;
61 return result;
62}
63
64static int read_config_process(u32 *arg1, char *status)
65{
66 int result;
67 char rdata[16];
68
69 result = eeconf_writeread_scmd(65, 0, 0, rdata, 16);
70 *status = (u8)(rdata[14] + rdata[13] + rdata[12] + rdata[11] + rdata[10] + rdata[9] + rdata[8] + rdata[7] + rdata[6]
71 + rdata[5] + rdata[4] + rdata[3] + rdata[2] + rdata[0] + rdata[1])
72 != (u8)rdata[15];
73 arg1[0] = *(u32 *)&rdata[0];
74 arg1[1] = *(u32 *)&rdata[4];
75 arg1[2] = *(u32 *)&rdata[8];
76 *((u8 *)arg1 + 12) = rdata[12];
77 *((u8 *)arg1 + 13) = rdata[13];
78 *((u8 *)arg1 + 14) = rdata[14];
79 return result;
80}
81
82static int eeconf_read_config(void *buffer, char *status)
83{
84 int i;
85
86 for ( i = 0; i < eeconf_config_numblocks; i += 1 )
87 if ( !read_config_process((u32 *)((char *)buffer + (15 * i)), status) || *status )
88 break;
89 return i;
90}
91
92static int write_config_process(char *inval, char *status)
93{
94 char wdata[16];
95
96 *status = 0;
97 *(u32 *)&wdata[0] = *(u32 *)inval;
98 *(u32 *)&wdata[4] = *((u32 *)inval + 1);
99 *(u32 *)&wdata[8] = *((u32 *)inval + 2);
100 wdata[12] = inval[12];
101 wdata[13] = inval[13];
102 wdata[14] = inval[14];
103 wdata[15] = inval[14] + inval[13] + inval[12] + inval[11] + inval[10] + inval[9] + inval[8] + inval[7] + inval[6]
104 + inval[5] + inval[4] + inval[3] + inval[2] + inval[0] + inval[1];
105 return eeconf_writeread_scmd(66, wdata, 16, status, 1);
106}
107
108static int eeconf_write_config(const void *buffer, char *status)
109{
110 int i;
111
112 for ( i = 0; i < eeconf_config_numblocks; i += 1 )
113 if ( !write_config_process((char *)buffer + (15 * i), status) || *status )
114 break;
115 return i;
116}
117
118static void eeconf_ieee1394_reset()
119{
120 USE_IOP_MMIO_HWPORT();
121
122 iop_mmio_hwport->ieee1394.PHYAccess = 0x417F0000;
123 while ( !(iop_mmio_hwport->ieee1394.NodeID & 1) )
124 ;
125 iop_mmio_hwport->ieee1394.ubufReceiveClear = -1;
126 iop_mmio_hwport->ieee1394.intr0 = -1;
127 iop_mmio_hwport->ieee1394.intr1 = -1;
128 iop_mmio_hwport->ieee1394.intr2 = -1;
129}
130
131static int eeconf_ieee1394_available()
132{
133 USE_IOP_MMIO_HWPORT();
134
135 return (iop_mmio_hwport->ieee1394.UnknownRegister7C & 0xF0000000) == 0x10000000;
136}
137
138static int eeconf_ee_ssbus_available()
139{
140 USE_IOP_MMIO_HWPORT();
141
142 return iop_mmio_hwport->iop_sbus_ctrl[0] & 0x80000000;
143}
144
145static void eeconf_dve_magic()
146{
147 USE_IOP_MMIO_HWPORT();
148
149 if ( (unsigned int)(iop_mmio_hwport->exp2_r2[4612]) - 96 < 2 )
150 {
151 iop_mmio_hwport->exp2_r2[4632] = 0;
152 return;
153 }
154 if ( (iop_mmio_hwport->dev9c[14] & 0xF0) != '0' )
155 {
156 *(vu16 *)&iop_mmio_hwport->dev9c[16] = 0;
157 *(vu16 *)&iop_mmio_hwport->dev9c[18] = 0;
158 return;
159 }
160 *((vu16 *)0xB600000A) = 0;
161}
162
163static void eeconf_handle_mac_address()
164{
165 char rdata[16];
166 int i;
167
168 for ( i = 0; i < 100; i += 1 )
169 if ( eeconf_writeread_scmd(55, 0, 0, rdata, 9) )
170 break;
171 if ( i >= 100 || (rdata[0] & 0x80) != 0 )
172 memset(rdata, 255, sizeof(rdata));
173 *((vu32 *)0xFFFE0188) = ((u8)rdata[4] << 24) | ((u8)rdata[3] << 16) | ((u8)rdata[2] << 8) | (u8)rdata[1];
174 *((vu32 *)0xFFFE018C) = ((u8)rdata[8] << 24) | ((u8)rdata[7] << 16) | ((u8)rdata[6] << 8) | (u8)rdata[5];
175}
176
177static void eeconf_handle_region_param()
178{
179 char rdata[16];
180 int i;
181
182 for ( i = 0; i < 100; i += 1 )
183 if ( eeconf_writeread_scmd(54, 0, 0, rdata, 15) )
184 break;
185 if ( i < 100 && (rdata[0] & 0x80) == 0 )
186 {
187 // The following address is the byte at index 5 of ROMVER
188 *((vu32 *)0xFFFE0180) = 0xBFC7FF04;
189 *((vu32 *)0xFFFE0184) = (u8)rdata[3];
190 // The following address is the byte at index 34 of VERSTR
191 *((vu32 *)0xFFFE0180) = 0xBFC7FF52;
192 *((vu32 *)0xFFFE0184) = (u8)rdata[8];
193 }
194 *((vu32 *)0xFFFE0180) = 0xFFFFFFFF;
195}
196
197static void eeconf_handle_eegs_config(const u8 *buf)
198{
199 *((vu32 *)0xFFFE0190) = buf ? (buf[1] & 0xF) : 3;
200}
201
202int _start(int ac, char **av)
203{
204 const int *p_bootmode3;
205 int read_conf_succeeded;
206 char *cfgblock_mem;
207 int any_ps1drv_flag_set;
208 int i;
209 char cfgblock_tmp[16];
210 char cfgstatus;
211 USE_DEV5_MMIO_HWPORT();
212
213 (void)ac;
214 (void)av;
215
216 p_bootmode3 = QueryBootMode(3);
217 if ( p_bootmode3 && (p_bootmode3[1] & (1 | 2)) )
218 return 1;
219#pragma GCC diagnostic push
220#pragma GCC diagnostic ignored "-Warray-bounds"
221 *((void **)0x3C0) = 0;
222#pragma GCC diagnostic pop
223 for ( i = 0; i < 0x30000; i += 1 )
224 if ( !(dev5_mmio_hwport->m_dev5_reg_005 & 8) )
225 break;
226 if ( i >= 0x30000 )
227 return 1;
228 read_conf_succeeded = 0;
229 cfgblock_mem = (char *)AllocSysMemory(1, 96, 0);
230 if ( cfgblock_mem )
231 {
232 read_conf_succeeded = 1;
233#pragma GCC diagnostic push
234#pragma GCC diagnostic ignored "-Warray-bounds"
235 *((void **)0x3C0) = cfgblock_mem;
236#pragma GCC diagnostic pop
237 for ( i = 0; i < 90; i += 1 )
238 cfgblock_mem[i] = 0;
239 for ( i = 0; i < 0x10000; i += 1 )
240 if ( eeconf_open_config(0, 0, 4, &cfgstatus) && !(cfgstatus & 9) )
241 break;
242 if ( i >= 0x10000 )
243 read_conf_succeeded = 0;
244 for ( i = 0; i < 0x10000; i += 1 )
245 if ( eeconf_read_config(cfgblock_mem, &cfgstatus) && !(cfgstatus & 9) )
246 break;
247 if ( i >= 0x10000 )
248 read_conf_succeeded = 0;
249 for ( i = 0; i < 0x10000; i += 1 )
250 if ( eeconf_close_config(&cfgstatus) && !(cfgstatus & 9) )
251 break;
252 if ( i >= 0x10000 )
253 read_conf_succeeded = 0;
254 for ( i = 0; i < 0x10000; i += 1 )
255 if ( eeconf_open_config(1u, 0, 2, &cfgstatus) && !(cfgstatus & 9) )
256 break;
257 if ( i >= 0x10000 )
258 read_conf_succeeded = 0;
259 for ( i = 0; i < 0x10000; i += 1 )
260 if ( eeconf_read_config(cfgblock_mem + 60, &cfgstatus) && !(cfgstatus & 9) )
261 break;
262 if ( i >= 0x10000 )
263 read_conf_succeeded = 0;
264 for ( i = 0; i < 0x10000; i += 1 )
265 if ( eeconf_close_config(&cfgstatus) && !(cfgstatus & 9) )
266 break;
267 if ( i >= 0x10000 )
268 read_conf_succeeded = 0;
269 cfgblock_mem[15] &= ~8;
270 cfgblock_mem[15] |= ((cfgblock_mem[75] & 8) != 0);
271 }
272 if ( !read_conf_succeeded )
273#pragma GCC diagnostic push
274#pragma GCC diagnostic ignored "-Warray-bounds"
275 *((void **)0x3C0) = 0;
276#pragma GCC diagnostic pop
277 // The following block is only in EECONF module in 1.60+, 1.70+, 2.20+, PS3 ps2_emu ROMs.
278 if ( !*(u16 *)QueryBootMode(4) )
279 {
280 // The following block is only in EECONF module in 1.60+, 1.70+, 2.20+ ROMs.
281 eeconf_dve_magic();
282 // The following block is only in EECONF module in 2.20+ ROMs.
283 if ( eeconf_ee_ssbus_available() )
284 {
285 eeconf_handle_region_param();
286 eeconf_handle_mac_address();
287#pragma GCC diagnostic push
288#pragma GCC diagnostic ignored "-Warray-bounds"
289 eeconf_handle_eegs_config((u8 *)(void **)0x3C0);
290#pragma GCC diagnostic pop
291 }
292 // The following block is only in EECONF module in 1.70+, 2.20+, PS3 ps2_emu ROMs.
293 if ( eeconf_ieee1394_available() )
294 eeconf_ieee1394_reset();
295 }
296 if ( !(dev5_mmio_hwport->m_dev5_reg_005 & 2) || (dev5_mmio_hwport->m_dev5_reg_005 & 4) )
297 return 1;
298 for ( i = 0; i < 0x10000; i += 1 )
299 if ( eeconf_open_config(1u, 0, 1, &cfgstatus) && !(cfgstatus & 9) )
300 break;
301 for ( i = 0; i < 0x10000; i += 1 )
302 if ( eeconf_read_config(cfgblock_tmp, &cfgstatus) && !(cfgstatus & 9) )
303 break;
304 for ( i = 0; i < 0x10000; i += 1 )
305 if ( eeconf_close_config(&cfgstatus) && !(cfgstatus & 9) )
306 break;
307 any_ps1drv_flag_set = 0;
308 for ( i = 0; i < 15; i += 1 )
309 {
310 if ( cfgblock_tmp[i] )
311 {
312 any_ps1drv_flag_set = 1;
313 cfgblock_tmp[i] = 0;
314 }
315 }
316 if ( any_ps1drv_flag_set )
317 {
318 for ( i = 0; i < 0x10000; i += 1 )
319 if ( eeconf_open_config(1u, 1u, 1, &cfgstatus) && !(cfgstatus & 9) )
320 break;
321 for ( i = 0; i < 0x10000; i += 1 )
322 if ( eeconf_write_config(cfgblock_tmp, &cfgstatus) && !(cfgstatus & 9) )
323 break;
324 for ( i = 0; i < 0x10000; i += 1 )
325 if ( eeconf_close_config(&cfgstatus) && !(cfgstatus & 9) )
326 break;
327 }
328 return 1;
329}