275 lines
8.0 KiB
C
275 lines
8.0 KiB
C
#ifndef GC_H
|
|
#define GC_H 1
|
|
|
|
// shamelessly stolen from the henkaku wiki.
|
|
typedef struct sd_context_part_base {
|
|
struct sd_context_global* gctx_ptr;
|
|
uint32_t unk_4;
|
|
uint32_t def_sector_size_mmc; // looks like default sector size - used in mmc read/write commands for resp_block_size_24
|
|
uint32_t def_sector_size_sd; // looks like default sector size - used in sd read/write commands for resp_block_size_24
|
|
|
|
uint8_t unk_10; // can be padding
|
|
uint8_t CID[15]; // this is CID data but in reverse
|
|
|
|
uint8_t unk_20; // can be padding
|
|
uint8_t CSD[15]; // this is CSD data but in reverse
|
|
} sd_context_part_base;
|
|
|
|
typedef enum SceSdifDevice {
|
|
SCE_SDIF_DEVICE_EMMC = 0,
|
|
SCE_SDIF_DEVICE_GC = 1,
|
|
SCE_SDIF_DEVICE_SDIO = 2,
|
|
SCE_SDIF_DEVICE_USD = 3,
|
|
} SceSdifDevice;
|
|
|
|
typedef enum SceSdifDeviceType {
|
|
SCE_SDIF_DEVICE_TYPE_INVALID = 0,
|
|
SCE_SDIF_DEVICE_TYPE_MMC = 1,
|
|
SCE_SDIF_DEVICE_TYPE_SD = 2,
|
|
SCE_SDIF_DEVICE_TYPE_SDIO = 3,
|
|
} SceSdifDeviceType;
|
|
|
|
typedef struct cmd_info {
|
|
uint32_t state_flags;
|
|
uint32_t command;
|
|
uint32_t argument;
|
|
void* buffer;
|
|
uint16_t resp_block_size;
|
|
uint16_t resp_n_blocks;
|
|
|
|
union {
|
|
struct {
|
|
char data[0x10];
|
|
} db;
|
|
struct {
|
|
uint32_t dw0;
|
|
uint32_t dw1;
|
|
uint32_t dw2;
|
|
uint32_t dw3;
|
|
} dw;
|
|
} response;
|
|
|
|
uint32_t error_code;
|
|
} cmd_info;
|
|
|
|
typedef struct host_info {
|
|
void** host_registers;
|
|
uint32_t unk_4;
|
|
uint32_t base_clock; // = 48000000 dec
|
|
uint32_t bus_width; // = 1 / 4 / 8 (bits)
|
|
uint32_t clock_frequency; // = base_clock >> (SDCLK Frequency Select)
|
|
uint8_t timeout_control_register;
|
|
uint8_t specification_version_number; // = 1 / 2 / 3
|
|
uint8_t vendor_version_number;
|
|
uint8_t unk_17;
|
|
uint32_t unk_18;
|
|
uint32_t unk_1C;
|
|
uint32_t unk_20;
|
|
uint32_t unk_24;
|
|
} host_info;
|
|
|
|
typedef struct device_info {
|
|
uint32_t dev_type_idx; // (1,2,3)
|
|
uint32_t unk_4;
|
|
uint16_t unk_8;
|
|
} device_info;
|
|
|
|
typedef struct sdif_context_general { //size is 0x40
|
|
SceUID suspend_callback_id;
|
|
uint32_t max_array_index; // typically 3
|
|
uint32_t unk_8;
|
|
uint32_t unk_C;
|
|
|
|
uint32_t unk_10;
|
|
uint32_t unk_14;
|
|
uint32_t unk_18;
|
|
uint32_t unk_1C;
|
|
|
|
uint32_t unk_20;
|
|
uint32_t unk_24;
|
|
uint32_t unk_28;
|
|
uint32_t unk_2C;
|
|
|
|
uint32_t unk_30;
|
|
uint32_t unk_34;
|
|
uint32_t unk_38;
|
|
uint32_t unk_3C;
|
|
} sdif_context_general;
|
|
|
|
typedef struct cmd_input { // size is 0x240
|
|
uint32_t size; // 0x240
|
|
|
|
// bit 10 (shift left 0x15) - request invalidate flag - invalidate vaddr_1C0 and vaddr_200
|
|
// this flag is used for CMD56 and CMD17
|
|
// bit 20 (shift left 0xB) - request mem_188 free - free memblock with uid mem_188
|
|
|
|
// bit 20 or bit 9 cancels invalidation (both must be clear)
|
|
uint32_t state_flags; // interrupt handler completion flag
|
|
|
|
uint32_t command;
|
|
uint32_t argument;
|
|
|
|
// stores normal response without command index and crc-7
|
|
// can also store CID or CSD. crr-7 will be cleared
|
|
// storage order is reversed
|
|
union {
|
|
struct {
|
|
char data[0x10];
|
|
} db;
|
|
struct {
|
|
uint32_t dw0;
|
|
uint32_t dw1;
|
|
uint32_t dw2;
|
|
uint32_t dw3;
|
|
} dw;
|
|
} response;
|
|
|
|
void* buffer; // cmd data buffer ptr - dest for vaddr_1C0
|
|
uint16_t resp_block_size_24; // block size of response. typically 0x200 which is default sector size
|
|
uint16_t resp_n_blocks_26; // number of blocks in response. typically number of sectors to read/write
|
|
uint32_t error_code; // error code from interrupt handler (confirmed)
|
|
uint32_t unk_2C;
|
|
|
|
uint8_t data0[0x30];
|
|
|
|
struct cmd_input* next_cmd;
|
|
uint32_t unk_64; // some flag. must be 3 for invalidation to happen
|
|
uint32_t array_index;
|
|
int(*set_event_flag_callback)(void* ctx);
|
|
|
|
SceUID evid; // event id SceSdif0, SceSdif1, SceSdif2 (SceSdif3 ?)
|
|
struct cmd_input* secondary_cmd; // (when multiple commands are sent)
|
|
struct sd_context_global* gctx_ptr;
|
|
uint32_t unk_7C;
|
|
|
|
char vaddr_80[0x80]; // 3 - mapped to paddr_184 (invalidate 0x80)
|
|
|
|
void* vaddr_100;
|
|
uint8_t data_104[0x7C];
|
|
|
|
uint32_t unk_180;
|
|
void* paddr_184; // 3 - phys address of vaddr_80
|
|
SceUID mem_188; // SceSdif memblock
|
|
uint32_t unk_18C;
|
|
|
|
uint32_t unk_190;
|
|
uint32_t unk_194;
|
|
void* base_198; // dest base for vaddr_200 (also ptr for invalidate)
|
|
// data at base contains CMD17 data
|
|
// data at base also contains fragments of CMD56 response
|
|
// data at offset is unknown (zeroes)
|
|
uint32_t offset_19C; //dest offset for vaddr_200 (also size for invalidate)
|
|
|
|
uint32_t size_1A0; // size of vaddr_1C0 - only valid if request invalidate flag is set
|
|
uint32_t size_1A4; // size of vaddr_200 - only valid if request invalidate flag is set
|
|
void* paddr_1A8; // 1 - phys address of vaddr_1C0
|
|
void* paddr_1AC; // 2 - phys address of vaddr_200
|
|
|
|
SceInt64 wide_time1; // 0x1B0
|
|
SceInt64 wide_time2; // 0x1B8 - relevant for commands that need to wait for data on DAT lines
|
|
|
|
char vaddr_1C0[0x40]; // 1 - mapped to paddr_1A8 (invalidate 0x40)
|
|
// - only valid if request invalidate flag is set
|
|
// - contains fragments of CMD56 request/response
|
|
// - does not contain CMD17 data
|
|
|
|
char vaddr_200[0x40]; // 2 - mapped to paddr_1AC (invalidate 0x40)
|
|
// - only valid if request invalidate flag is set
|
|
// - contains unknown data (zeroes)
|
|
} cmd_input;
|
|
|
|
|
|
typedef struct sd_context_data { // size is 0xC0
|
|
struct cmd_input* cmd_ptr;
|
|
struct cmd_input* cmd_ptr_next;
|
|
uint32_t unk_8;
|
|
uint32_t unk_C;
|
|
|
|
uint32_t dev_type_idx; // (1, 2, 3)
|
|
sd_context_part_base* ctx; // pointer to custom context (sd_context_part_mmc*, sd_context_part_sd*, sd_context_part_wlanbt*)
|
|
uint32_t voltages; // MMC_VDD_165_195, MMC_VDD_32_33, etc. Values seen: SDIF0 and SDIF2: 0x80, SDIF1 and SDIF3: 0x300000
|
|
uint32_t unk_1C;
|
|
|
|
uint32_t array_idx; // (0,1,2)
|
|
uint8_t unk_24;
|
|
uint8_t unk_25;
|
|
uint8_t unk_26;
|
|
uint8_t unk_27;
|
|
cmd_input* cmd_28;
|
|
cmd_input* cmd_2C;
|
|
|
|
void** host_registers; // membase of SceSdif (0,1,2) memblock of size 0x1000
|
|
uint32_t unk_34;
|
|
uint8_t unk_38;
|
|
uint8_t slow_mode; // relevant only for 2 read and 2 write functions
|
|
uint8_t unk_3A;
|
|
uint8_t unk_3B;
|
|
|
|
SceUID host_registers_uid; // UID of SceSdif (0,1,2) memblock of size 0x1000
|
|
|
|
SceUID evid; // event id SceSdif0, SceSdif1, SceSdif2 (SceSdif3 ?)
|
|
void* sdif_fast_mutex; //size is 0x40 - SceSdif0, SceSdif1, SceSdif2 (SceSdif3 ?)
|
|
|
|
//it looks like this chunk is separate structure since offset 0x2480 is used too often
|
|
|
|
//offset 0x2484
|
|
SceUID uid_10000; // UID of SceSdif (0,1,2) memblock of size 0x10000
|
|
void* membase_10000; // membase of SceSdif (0,1,2) memblock of size 0x10000
|
|
uint32_t unk_8C;
|
|
|
|
uint32_t unk_90;
|
|
int lockable_int;
|
|
uint32_t unk_98;
|
|
uint32_t unk_9C;
|
|
|
|
uint32_t unk_A0;
|
|
uint32_t unk_A4;
|
|
uint32_t unk_A8;
|
|
uint32_t unk_AC;
|
|
|
|
uint32_t unk_B0;
|
|
uint32_t unk_B4;
|
|
uint32_t unk_B8;
|
|
uint32_t unk_BC;
|
|
} sd_context_data;
|
|
|
|
typedef struct sd_context_part_mmc { // size is 0x398
|
|
sd_context_part_base ctxb;
|
|
|
|
uint8_t EXT_CSD[0x200]; // 0x30
|
|
|
|
uint8_t data_230[0x160];
|
|
|
|
void* unk_390;
|
|
uint32_t unk_394;
|
|
} sd_context_part_mmc;
|
|
|
|
typedef struct sd_context_part_sd { // size is 0xC0
|
|
sd_context_part_base ctxb;
|
|
|
|
uint8_t data[0x90];
|
|
} sd_context_part_sd;
|
|
|
|
typedef struct sd_context_part_wlanbt { // size is 0x398
|
|
struct sd_context_global* gctx_ptr;
|
|
|
|
uint8_t data[0x394];
|
|
} sd_context_part_wlanbt;
|
|
|
|
typedef struct sd_context_global { // size is 0x24C0
|
|
struct cmd_input commands[16];
|
|
struct sd_context_data ctx_data;
|
|
} sd_context_global;
|
|
|
|
typedef struct bulk_transfer {
|
|
uint32_t unk0;
|
|
uint32_t unk1;
|
|
uint32_t count;
|
|
uint32_t unk2;
|
|
uint32_t type; // 1: register access, 2: memory access
|
|
uint32_t unk3;
|
|
void * (*get_next)(void *); // callback to get next buffer
|
|
uint32_t unk4;
|
|
} bulk_transfer;
|
|
|
|
#endif |