|
| 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 | + |
| 15 | +IRX_ID("EEConfig", 1, 1); |
| 16 | +// Based on the module from ROM 2.20+. |
| 17 | + |
| 18 | +static int eeconf_config_numblocks; |
| 19 | + |
| 20 | +static 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 | + |
| 46 | +static 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 | + |
| 55 | +static 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 | + |
| 64 | +static 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 | + |
| 82 | +static 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 | + |
| 92 | +static 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 | + |
| 108 | +static 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 | + |
| 118 | +static 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 | + |
| 131 | +static int eeconf_ieee1394_available() |
| 132 | +{ |
| 133 | + USE_IOP_MMIO_HWPORT(); |
| 134 | + |
| 135 | + return (iop_mmio_hwport->ieee1394.UnknownRegister7C & 0xF0000000) == 0x10000000; |
| 136 | +} |
| 137 | + |
| 138 | +static int eeconf_ee_ssbus_available() |
| 139 | +{ |
| 140 | + USE_IOP_MMIO_HWPORT(); |
| 141 | + |
| 142 | + return iop_mmio_hwport->iop_sbus_ctrl[0] & 0x80000000; |
| 143 | +} |
| 144 | + |
| 145 | +static 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 | + |
| 163 | +static 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 | + |
| 177 | +static 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 | + |
| 197 | +static void eeconf_handle_eegs_config(const u8 *buf) |
| 198 | +{ |
| 199 | + *((vu32 *)0xFFFE0190) = buf ? (buf[1] & 0xF) : 3; |
| 200 | +} |
| 201 | + |
| 202 | +int _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 | +} |
0 commit comments