SceSdif: Difference between revisions
(→Types) |
|||
(119 intermediate revisions by 5 users not shown) | |||
Line 1: | Line 1: | ||
SceSdif is a kernel module that is primary responsible for communicating with SD devices. This includes | Sdif likely stands for Storage Device InterFace. SceSdif is a kernel module that is primary responsible for communicating with SD devices. This includes eMMC (internal storage), gamecard MMC, SD/micro SD card, Wlan/Bt SDIO devices. Memory Card is handled by [[SceMsif]] instead as it uses an authentication security layer. | ||
To communicate with particular device SceSdif module uses device index (sd_ctx_index) | |||
To communicate with a particular device SceSdif module uses device index (sd_ctx_index). | |||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Device Index | ! Device Index !! Device !! Device Type !! Description | ||
! Type | |||
! Description | |||
|- | |- | ||
| 0 | | 0 || Internal || MMC || eMMC (internal storage) | ||
| MMC | |||
| | |||
|- | |- | ||
| 1 | | 1 || Game card || MMC/SD || Gamecard/?SD card? | ||
| MMC | |||
| | |||
|- | |- | ||
| 2 | | 2 || Wlan/Bt || SDIO || Wlan/Bt | ||
| SDIO | |- | ||
| | | 3 || Micro SD || SD || Used by [[SceSdstor]] "usd" device. Related to error 0x80320013 on release FW 3.600.011 but maybe used on old FW versions. | ||
|} | |} | ||
There is one more index value that closely correlates with | There is one more index value that closely correlates with Device Index. This is speculated to be Device Type Index. It is initialized by internal subroutine that does preinitialization (cmd0, cmd8, cmd5_sdio, cmd55, acmd41). Value is typically stored in sd_context_data structure in field dev_type_idx. | ||
This is speculated to be | |||
Value is typically stored in sd_context_data structure in field dev_type_idx. | |||
{| class="wikitable" | {| class="wikitable" | ||
! Device Type Index !! Device Type !! Associated SceSdif init function | |||
|- | |- | ||
| 0 || Unknown (invalid?) || None? | |||
|- | |- | ||
| | | 1 || MMC || [[#get_sd_context_part_validate_mmc|get_sd_context_part_validate_mmc]] | ||
| | |||
|- | |- | ||
| | | 2 || SD || [[#get_sd_context_part_validate_sd|get_sd_context_part_validate_sd]] | ||
| | |||
|- | |- | ||
| | | 3 || SDIO || [[#get_sd_context_part_validate_sdio|get_sd_context_part_validate_sdio]] | ||
| | |||
| | |||
| | |||
| | |||
|} | |} | ||
== Module == | == Module == | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Version | ! Version !! World !! Privilege | ||
|- | |- | ||
| 3. | | 0.990.000-3.740.011 || Non-secure || Kernel | ||
|} | |} | ||
Line 69: | Line 47: | ||
! Version !! Name !! World !! Visibility !! NID | ! Version !! Name !! World !! Visibility !! NID | ||
|- | |- | ||
| | | 0.990.000-3.740.011 || [[SceSdif#SceSdifForDriver|SceSdifForDriver]] || Non-secure || Kernel || 0x96D306FA | ||
|} | |} | ||
Line 84: | Line 60: | ||
| 0x0040 || 0x24C0 || sd_context_global (eMMC) | | 0x0040 || 0x24C0 || sd_context_global (eMMC) | ||
|- | |- | ||
| 0x2500 || 0x24C0 || sd_context_global ( | | 0x2500 || 0x24C0 || sd_context_global (gamecard) | ||
|- | |- | ||
| 0x49C0 || 0x24C0 || sd_context_global (wlan/bt) | | 0x49C0 || 0x24C0 || sd_context_global (wlan/bt) | ||
Line 90: | Line 66: | ||
| 0x6E80 || 0x398 || sd_context_part_mmc (eMMC) | | 0x6E80 || 0x398 || sd_context_part_mmc (eMMC) | ||
|- | |- | ||
| 0x7218 || 0x398 || sd_context_part_mmc ( | | 0x7218 || 0x398 || sd_context_part_mmc (gamecard) | ||
|- | |- | ||
| 0x75B0 || 0xC0 || sd_context_part_sd (unknown) used in initialize_sd_device | | 0x75B0 || 0xC0 || sd_context_part_sd (unknown) used in [[#initialize_sd_device|initialize_sd_device]] | ||
|- | |- | ||
| 0x7670 || 0xC0 || sd_context_part_sd ( | | 0x7670 || 0xC0 || sd_context_part_sd (gamecard) used in [[#initialize_sd_device|initialize_sd_device]] | ||
|- | |- | ||
| 0x7730 || 0xC0 || sd_context_part_sd (unknown) used in initialize_sd_device | | 0x7730 || 0xC0 || sd_context_part_sd (unknown) used in [[#initialize_sd_device|initialize_sd_device]] | ||
|- | |- | ||
| 0x77F0 || 0xD38 || custom context used in | | 0x77F0 || 0xD38 || custom context used in [[#wlan_bt_initialize_custom_context2|wlan_bt_initialize_custom_context2]] | ||
|- | |- | ||
| 0x8528 || 0xD38 || custom context used in | | 0x8528 || 0xD38 || custom context used in [[#wlan_bt_initialize_custom_context2|wlan_bt_initialize_custom_context2]] | ||
|- | |- | ||
| 0x9260 || 0x398 || sd_context_part_wlanbt (wlan/bt) | | 0x9260 || 0x398 || sd_context_part_wlanbt (wlan/bt) | ||
Line 107: | Line 83: | ||
|- | |- | ||
| 0x9E80 || 0x118 || some wlan/bt data | | 0x9E80 || 0x118 || some wlan/bt data | ||
|} | |} | ||
== Allocated blocks == | == Allocated blocks == | ||
During initialization step Sdif driver allocates couple of memory blocks. | During initialization step Sdif driver allocates couple of memory blocks. This happens when 'module_start' function is called, inside 'init' function. | ||
This happens when 'module_start' function is called, inside 'init' function. | |||
There are 2 blocks per device context. Each block is named as SceSdif<N> where N is array index. | There are 2 blocks per device context. Each block is named as SceSdif<N> where N is array index. | ||
Line 121: | Line 95: | ||
Second block is of size 0x10000 - SceUID and void* are stored in sd_context_data per device context. | Second block is of size 0x10000 - SceUID and void* are stored in sd_context_data per device context. | ||
First block is DMA copied to / from corresponding SceSdif<N> [[Physical_Memory|physical address]]. | |||
First | First block looks like to have layout that corresponds to standard SD/MMC host that is described in "Physical Layer Simplified Specification". | ||
== SceSdifForDriver == | == SceSdifForDriver == | ||
Line 174: | Line 103: | ||
=== Types === | === Types === | ||
<source lang=" | <source lang="C"> | ||
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 | 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 | typedef struct host_info { | ||
{ | sd_mmc_registers* host_registers; | ||
uint32_t unk_4; | uint32_t unk_4; | ||
uint32_t | uint32_t base_clock; // = 48000000 dec | ||
uint32_t | uint32_t bus_width; // = 1 / 4 / 8 (bits) | ||
uint32_t | uint32_t clock_frequency; // = base_clock >> (SDCLK Frequency Select) | ||
uint8_t | uint8_t timeout_control_register; | ||
uint8_t | uint8_t specification_version_number; // = 1 / 2 / 3 | ||
uint8_t | uint8_t vendor_version_number; | ||
uint8_t unk_17; | uint8_t unk_17; | ||
uint32_t unk_18; | uint32_t unk_18; | ||
Line 199: | Line 155: | ||
uint32_t unk_20; | uint32_t unk_20; | ||
uint32_t unk_24; | uint32_t unk_24; | ||
} | } host_info; | ||
typedef struct | typedef struct device_info { | ||
{ | uint32_t dev_type_idx; // (1,2,3) | ||
uint32_t | |||
uint32_t unk_4; | uint32_t unk_4; | ||
uint16_t unk_8; | uint16_t unk_8; | ||
} | } device_info; | ||
typedef struct sdif_context_general //size is 0x40 | typedef struct sdif_context_general { //size is 0x40 | ||
SceUID suspend_callback_id; | SceUID suspend_callback_id; | ||
uint32_t max_array_index; //typically 3 | uint32_t max_array_index; // typically 3 | ||
uint32_t unk_8; | uint32_t unk_8; | ||
uint32_t unk_C; | uint32_t unk_C; | ||
Line 229: | Line 183: | ||
uint32_t unk_38; | uint32_t unk_38; | ||
uint32_t unk_3C; | uint32_t unk_3C; | ||
}sdif_context_general; | } sdif_context_general; | ||
typedef struct cmd_input // size is 0x240 | typedef struct cmd_input { // size is 0x240 | ||
uint32_t size; // 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 state_flags; // interrupt handler completion flag | ||
uint32_t command; | uint32_t command; | ||
uint32_t argument; | uint32_t argument; | ||
uint32_t | // 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 | void* buffer; // cmd data buffer ptr - dest for vaddr_1C0 | ||
uint16_t | uint16_t resp_block_size_24; // block size of response. typically 0x200 which is default sector size | ||
uint16_t | uint16_t resp_n_blocks_26; // number of blocks in response. typically number of sectors to read/write | ||
uint32_t error_code; //from interrupt handler | uint32_t error_code; // error code from interrupt handler (confirmed) | ||
uint32_t unk_2C; | uint32_t unk_2C; | ||
Line 252: | Line 222: | ||
struct cmd_input* next_cmd; | struct cmd_input* next_cmd; | ||
uint32_t unk_64; | uint32_t unk_64; // some flag. must be 3 for invalidation to happen | ||
uint32_t array_index; | uint32_t array_index; | ||
int(set_event_flag_callback | int(*set_event_flag_callback)(void* ctx); | ||
SceUID evid; // event id SceSdif0, SceSdif1, SceSdif2 (SceSdif3 ?) | SceUID evid; // event id SceSdif0, SceSdif1, SceSdif2 (SceSdif3 ?) | ||
Line 261: | Line 231: | ||
uint32_t unk_7C; | uint32_t unk_7C; | ||
char vaddr_80[0x80]; // 3 - mapped to paddr_184 (invalidate 0x80) | |||
uint8_t | void* vaddr_100; | ||
uint8_t data_104[0x7C]; | |||
uint32_t unk_180; | uint32_t unk_180; | ||
void* paddr_184; //3 | void* paddr_184; // 3 - phys address of vaddr_80 | ||
SceUID mem_188; // SceSdif memblock | |||
uint32_t unk_18C; | uint32_t unk_18C; | ||
uint32_t unk_190; | uint32_t unk_190; | ||
uint32_t unk_194; | uint32_t unk_194; | ||
void* base_198; // dest base for vaddr_200 (also ptr for invalidate) | |||
uint32_t | // 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 | uint32_t size_1A0; // size of vaddr_1C0 - only valid if request invalidate flag is set | ||
uint32_t | uint32_t size_1A4; // size of vaddr_200 - only valid if request invalidate flag is set | ||
void* paddr_1A8; //1 | void* paddr_1A8; // 1 - phys address of vaddr_1C0 | ||
void* paddr_1AC; //2 | 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_mmc_registers { | |||
} sd_mmc_registers; | |||
} | |||
typedef struct sd_context_data // size is 0xC0 | typedef struct sd_context_data { // size is 0xC0 | ||
struct cmd_input* cmd_ptr; | struct cmd_input* cmd_ptr; | ||
struct cmd_input* cmd_ptr_next; | struct cmd_input* cmd_ptr_next; | ||
Line 310: | Line 277: | ||
uint32_t unk_C; | uint32_t unk_C; | ||
uint32_t dev_type_idx; // (1,2,3) | 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 | 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 unk_1C; | ||
Line 320: | Line 287: | ||
uint8_t unk_26; | uint8_t unk_26; | ||
uint8_t unk_27; | uint8_t unk_27; | ||
cmd_input* cmd_28; | |||
cmd_input* cmd_2C; | |||
sd_mmc_registers* host_registers; // membase of SceSdif (0,1,2) memblock of size 0x1000 | |||
uint32_t unk_34; | uint32_t unk_34; | ||
uint8_t unk_38; | |||
SceUID | 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 ?) | SceUID evid; // event id SceSdif0, SceSdif1, SceSdif2 (SceSdif3 ?) | ||
fast_mutex 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 | //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 | 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 | void* membase_10000; // membase of SceSdif (0,1,2) memblock of size 0x10000 | ||
Line 371: | Line 325: | ||
} sd_context_data; | } sd_context_data; | ||
typedef struct sd_context_part_base | typedef struct sd_context_part_base { | ||
{ | |||
struct sd_context_global* gctx_ptr; | struct sd_context_global* gctx_ptr; | ||
uint32_t unk_4; | uint32_t unk_4; | ||
uint32_t | uint32_t def_sector_size_mmc; // looks like default sector size - used in mmc read/write commands for resp_block_size_24 | ||
uint32_t | 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 unk_10; // can be padding | ||
uint8_t CID[15]; //this is CID data but in reverse | uint8_t CID[15]; // this is CID data but in reverse | ||
uint8_t unk_20; //can be padding | uint8_t unk_20; // can be padding | ||
uint8_t CSD[15]; //this is CSD data but in reverse | uint8_t CSD[15]; // this is CSD data but in reverse | ||
}sd_context_part_base; | } sd_context_part_base; | ||
typedef struct sd_context_part_mmc // size is 0x398 | typedef struct sd_context_part_mmc { // size is 0x398 | ||
sd_context_part_base ctxb; | sd_context_part_base ctxb; | ||
uint8_t | uint8_t EXT_CSD[0x200]; // 0x30 | ||
uint8_t data_230[0x160]; | |||
void* unk_390; | void* unk_390; | ||
Line 395: | Line 349: | ||
} sd_context_part_mmc; | } sd_context_part_mmc; | ||
typedef struct sd_context_part_sd // size is 0xC0 | typedef struct sd_context_part_sd { // size is 0xC0 | ||
sd_context_part_base ctxb; | sd_context_part_base ctxb; | ||
Line 402: | Line 355: | ||
} sd_context_part_sd; | } sd_context_part_sd; | ||
typedef struct sd_context_part_wlanbt // size is 0x398 | typedef struct sd_context_part_wlanbt { // size is 0x398 | ||
struct sd_context_global* gctx_ptr; | struct sd_context_global* gctx_ptr; | ||
Line 409: | Line 361: | ||
} sd_context_part_wlanbt; | } sd_context_part_wlanbt; | ||
typedef struct sd_context_global // size is 0x24C0 | typedef struct sd_context_global { // size is 0x24C0 | ||
struct cmd_input commands[16]; | struct cmd_input commands[16]; | ||
struct sd_context_data ctx_data; | struct sd_context_data ctx_data; | ||
} sd_context_global; | } 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; | |||
} | |||
</source> | </source> | ||
=== | === sceSdifInitForDriver === | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
Line 435: | Line 386: | ||
|} | |} | ||
<source lang="c"> | <source lang="c">SceInt32 sceSdifInitForDriver(void);</source> | ||
=== deinit === | === deinit === | ||
Line 457: | Line 408: | ||
<source lang="c">int return_error();</source> | <source lang="c">int return_error();</source> | ||
=== | === sceSdifMemoryCardEnableSlowModeForDriver === | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Version !! NID | ! Version !! NID | ||
|- | |- | ||
| 3.60 || | | 0.990-3.60 || 0xF37CF8E5 | ||
|} | |} | ||
<source lang="c">int | Temp name was sceSdifEnableSlowCardModeForDriver. | ||
sets slow_mode flag in sd_context_data for gamecard device | |||
also tries to set flag for device with index 3 but it does not actually exist | |||
<source lang="c">int sceSdifMemoryCardEnableSlowModeForDriver(void);</source> | |||
=== | === sceSdifDisableSlowCardModeForDriver === | ||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 3.60 || 0x29A71E7F | |||
|} | |||
Temp name was sceSdifMemoryCardEnableSlowModeForDriver. | |||
resets slow_mode flag in sd_context_data for gamecard device | |||
also tries to reset flag for device with index 3 but it does not actually exist | |||
<source lang="c">int sceSdifDisableSlowCardModeForDriver(void);</source> | |||
=== sceSdifMemoryCardGetCardInsertStateForDriver === | |||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
Line 475: | Line 448: | ||
|} | |} | ||
<source lang="c">int | gc/gcsd. | ||
Temp name was sceSdifGetCardInsertState1ForDriver, get_card_insert_state1. | |||
<source lang="c">int sceSdifMemoryCardGetCardInsertStateForDriver(SceSdifDevice dev);</source> | |||
=== get_card_insert_state2 === | === get_card_insert_state2 === | ||
Line 492: | Line 469: | ||
! Version !! NID | ! Version !! NID | ||
|- | |- | ||
| 3.60 || | | 3.60 || 0x134E06C4 | ||
|} | |} | ||
<source lang="c">int gc_cmd56_response(sd_context_part* ctx, | <source lang="c">int gc_cmd56_response(sd_context_part *ctx, void *buffer, SceSize length);</source> | ||
=== gc_cmd56_request === | === gc_cmd56_request === | ||
Line 502: | Line 479: | ||
! Version !! NID | ! Version !! NID | ||
|- | |- | ||
| 3.60 || | | 3.60 || 0xB0996641 | ||
|} | |} | ||
<source lang="c">int gc_cmd56_request(sd_context_part* ctx, | sceMmcSendGeneralCmdData | ||
<source lang="c">int gc_cmd56_request(sd_context_part *ctx, const void *buffer, SceSize length);</source> | |||
=== get_sd_context_global === | === get_sd_context_global === | ||
Line 559: | Line 538: | ||
it is confirmed that this function sends sequence of commands that correspond to MMC initialization protocol | it is confirmed that this function sends sequence of commands that correspond to MMC initialization protocol | ||
<source lang="c">int initialize_mmc_device( | <source lang="c">int initialize_mmc_device(SceSdifDevice dev, sd_context_part** result);</source> | ||
=== | === wlan_bt_acquiredev === | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
Line 569: | Line 548: | ||
|} | |} | ||
<source lang="c">int | Called in initialization sequence. | ||
<source lang="c">int wlan_bt_acquiredev(wlan_context* wlan_ctx);</source> | |||
=== | === wlan_bt_release === | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
Line 579: | Line 560: | ||
|} | |} | ||
<source lang="c">int | Called in failures. Assumed to be release of sdio device. | ||
<source lang="c">int wlan_bt_release(wlan_context* wlan_ctx);</source> | |||
=== | === sceSdioReadForDriver === | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Version !! NID | ! Version !! NID | ||
|- | |- | ||
| 3.60 || | | 3.60 || 0xD0F78D9B | ||
|} | |} | ||
<source lang="c">int | Reads from Wlan/BT SDIO device. | ||
Example from [[SceWlanBt]]: | |||
<source lang="C">ret = sceSdioReadForDriver(wlan_ctx, 0x5C, 1, &g_card_rev, 1);</source> | |||
<source lang="c"> | |||
// type: 1 for register access, 2 for data access | |||
int sceSdioReadForDriver(wlan_context* wlan_ctx, int reg, int count, void* dst, int type); | |||
</source> | |||
=== | === sceSdioWriteForDriver === | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Version !! NID | ! Version !! NID | ||
|- | |- | ||
| 3.60 || | | 3.60 || 0x3C4CDC8B | ||
|} | |} | ||
<source lang="c">int | Writes from wlan sdio device. | ||
Type variable seems to define which access to use. 1 is for register access, 2 is for data access. | |||
<source lang="c">int sceSdioWriteForDriver(wlan_context* wlan_ctx, int reg, int count, void *src, int type);</source> | |||
=== | === sceSdioSetBlockLenForDriver === | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Version !! NID | ! Version !! NID | ||
|- | |- | ||
| 3.60 || | | 3.60 || 0x733BC373 | ||
|} | |} | ||
<source lang="c">int | <source lang="c">int sceSdioSetBlockLenForDriver(wlan_context* wlan_ctx, int num);</source> | ||
=== wlan_bt_cmd52_sdio === | === wlan_bt_cmd52_sdio === | ||
Line 626: | Line 621: | ||
! Version !! NID | ! Version !! NID | ||
|- | |- | ||
| 3. | | 0.996.090-3.740.011 || 0x5D65E66B | ||
|} | |} | ||
<source lang="c">int wlan_bt_cmd52_sdio(sd_context_part* ctx, int | <source lang="c"> | ||
// cond: wakeup condition as in scePowerSetWakeupConditionForDriver | |||
int wlan_bt_cmd52_sdio(sd_context_part* ctx, int cond, SceBool num1, SceUInt32* pOut); | |||
</source> | |||
=== | === sceSdioChangeBusSpeedForDriver === | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Version !! NID | ! Version !! NID | ||
|- | |- | ||
| 3.60 || | | 3.60 || 0xBC45C83D | ||
|} | |} | ||
<source lang="c">int | <source lang="c">int sceSdioChangeBusSpeedForDriver(sd_context_part* ctx, int num);</source> | ||
=== wlan_bt_initialize_custom_context2 === | === wlan_bt_initialize_custom_context2 === | ||
Line 646: | Line 644: | ||
! Version !! NID | ! Version !! NID | ||
|- | |- | ||
| 3. | | 0.990.000-3.740.011 || 0xAABAA0F0 | ||
|} | |} | ||
Line 661: | Line 659: | ||
<source lang="c">int wlan_bt_initialize_custom_context2(int sd_ctx_index, sd_context_part** ctx);</source> | <source lang="c">int wlan_bt_initialize_custom_context2(int sd_ctx_index, sd_context_part** ctx);</source> | ||
=== | === wlan_bt_bulk_transfer === | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Version !! NID | ! Version !! NID | ||
|- | |- | ||
| 3.60 || | | 3.60 || 0x855C95E1 | ||
|} | |} | ||
<source lang="c">int | This is a guessed name. | ||
This function is used in aggregated frame transmit when more than one packet is being transmitted over Wlan. | |||
<source lang="c">int wlan_bt_bulk_transfer(wlan_context* wlan_ctx, bulk_transfer* b, void* unk1);</source> | |||
=== | === wlan_bt_get_wlan_context === | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
Line 679: | Line 681: | ||
|} | |} | ||
<source lang="c">int | Get wlan_context for sdio device. Vidpid is an array with Marvell Vid and Wlan/Bt pid. | ||
For Wlan: vidpid = [0x2df, 0x911a]. For Bt: vidpid = [0x2df, 0x9119]. | |||
<source lang="c">int wlan_bt_get_wlan_context(sd_context_part* ctx, int vidpid[2]);</source> | |||
=== | === sceSdifGoStandbyStateForDriver === | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Version !! NID | ! Version !! NID | ||
|- | |- | ||
| 3.60 || | | 0.990-3.60 || 0xAB0222F2 | ||
|} | |} | ||
<source lang="c">int | Temp name was wlan_bt_cmd7. | ||
<source lang="c">int sceSdifGoStandbyStateForDriver(sd_context_part* ctx);</source> | |||
=== wlan_bt_cmd52_sdio === | === wlan_bt_cmd52_sdio === | ||
Line 779: | Line 787: | ||
|} | |} | ||
This function is just a wrapper for [[SceSdif#wlan_bt_initialize_custom_context2|wlan_bt_initialize_custom_context2]]. | |||
<source lang="c">int wlan_bt_initialize_custom_context1(int sd_ctx_index);</source> | <source lang="c">int wlan_bt_initialize_custom_context1(int sd_ctx_index);</source> | ||
Line 833: | Line 841: | ||
<source lang="c">int wlan_bt(wlan_context *wlan_ctx, int unk0);</source> | <source lang="c">int wlan_bt(wlan_context *wlan_ctx, int unk0);</source> | ||
=== | === sceMmcReadSectorForDriver === | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Version !! NID | ! Version !! NID | ||
|- | |- | ||
| 3.60 || | | 0.990-3.60 || 0x6F8D529B | ||
|} | |} | ||
<source lang="c">int | <source lang="c">int sceMmcReadSectorForDriver(sd_context_part* ctx, int sector, char* buffer, int nSectors);</source> | ||
=== | === sdstor_read_sector_sd === | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
Line 851: | Line 859: | ||
|} | |} | ||
<source lang="c">int | If <code>nSectors</code> is <code>1</code>, then issues command <code>0x11</code> (<code>READ_SINGLE_BLOCK</code>), and otherwise, command <code>0x12</code> (<code>READ_MULTIPLE_BLOCK</code>). | ||
<source lang="c">int sdstor_read_sector_sd(sd_context_part* ctx, int sector, char* buffer, int nSectors);</source> | |||
=== | === sceMmcWriteSectorForDriver === | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Version !! NID | ! Version !! NID | ||
|- | |- | ||
| 3.60 || | | 0.990-3.60 || 0x175543D2 | ||
|} | |} | ||
<source lang="c">int | <source lang="c">int sceMmcWriteSectorForDriver(sd_context_part* ctx, int sector, char* buffer, int nSectors);</source> | ||
=== | === sceSdWriteSectorForDriver === | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Version !! NID | ! Version !! NID | ||
|- | |- | ||
| 3.60 || | | 0.990-3.60 || 0xE0781171 | ||
|} | |} | ||
<source lang="c">int | <source lang="c">int sceSdWriteSectorForDriver(sd_context_part* ctx, int sector, char* buffer, int nSectors);</source> | ||
=== | === sddev_get_sd_cidForDriver === | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Version !! NID | ! Version !! NID | ||
|- | |- | ||
| 3. | | 0.931.010-3.20 || not present | ||
|- | |||
| 3.300.041-3.740.011 || 0x23A4EF01 | |||
|} | |} | ||
<source lang="c">int | This is the name of the subroutine. Temp name was sdstor_get_cidForDriver, sceSdifGetCIDForDriver. | ||
<source lang="c"> | |||
//size of cid is 0x10 | |||
int sddev_get_sd_cidForDriver(sd_context_part* ctx, char* cid); | |||
</source> | |||
=== sdstor_cmd0_cmd13 === | === sdstor_cmd0_cmd13 === | ||
Line 893: | Line 910: | ||
<source lang="c">int sdstor_cmd0_cmd13(int sd_ctx_index);</source> | <source lang="c">int sdstor_cmd0_cmd13(int sd_ctx_index);</source> | ||
=== | === sceSdEraseForDriver === | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
Line 901: | Line 918: | ||
|} | |} | ||
<source lang=" | This is a guessed name. | ||
Temp name was sdstor_cmd32_cmd33_cmd38_sdio. | |||
Used by [[SceSdstor]]. | |||
<source lang="C">int sceSdEraseForDriver(SceSdifDevice dev, SceUID callback_id);</source> | |||
=== initialize_sd_device === | === initialize_sd_device === | ||
Line 908: | Line 931: | ||
! Version !! NID | ! Version !! NID | ||
|- | |- | ||
| 3.60 || | | 3.60 || 0xC1271539 | ||
|} | |} | ||
This function sends sequence of commands that correspond to SD initialization protocol. These commands include: cmd0, cmd8, cmd5_sdio, cmd2, cmd3, cmd6, cmd9, cmd7, cmd16. Some paired commands are: (cmd55, acmd41), (cmd55, acmd42), (cmd55, acmd13), (cmd55, acmd51). | |||
* it does not check sd_ctx_index argument. | * it does not check sd_ctx_index argument. | ||
* it uses array of 3 custom contexts instead of sd_context_part structures. | * it uses array of 3 custom contexts instead of sd_context_part structures. | ||
Line 924: | Line 940: | ||
* it only initializes device with device type index 2. otherwise 0x80320017 error is returned. | * it only initializes device with device type index 2. otherwise 0x80320017 error is returned. | ||
<source lang="c">int initialize_sd_device( | <source lang="c">int initialize_sd_device(SceSdifDevice dev, int* result);</source> | ||
=== | === sceMmcHasWriteProtectForDriver === | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Version !! NID | ! Version !! NID | ||
|- | |- | ||
| 3.60 || | | 3.60-3.65 || 0x995748EA | ||
|} | |} | ||
This is a guessed name. | |||
Temp name was sdstor_cmd6_cmd30, sendWriteProtectStatusForDriver. | |||
<source lang="c">int | <source lang="c">int sceMmcHasWriteProtectForDriver(sd_context_part *input, SceUInt32 posSector, SceUInt32 nSector, SceBool *result);</source> | ||
=== | === sceSdHasWriteProtectForDriver === | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Version !! NID | ! Version !! NID | ||
|- | |- | ||
| 3.60 || | | 3.60 || 0xE091BA2E | ||
|} | |} | ||
<source lang="c">int | This is a guessed name. | ||
<source lang="c">int sceSdHasWriteProtectForDriver(sd_context_part *input, SceUInt32 posSector, SceUInt32 nSector, SceBool *result);</source> | |||
=== | === sceMmcWriteSectorInternalForDriver === | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Version !! NID | ! Version !! NID | ||
|- | |- | ||
| 3.60 || | | 0.990-3.60 || 0x60642F49 | ||
|} | |} | ||
<source lang="c">int | Temp name was sceMmcWriteSector2ForDriver. | ||
<source lang="c">int sceMmcWriteSectorInternalForDriver(sd_context_part *ctx, int unk0, int unk1);</source> | |||
=== | === sceSdWriteSectorInternalForDriver === | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Version !! NID | ! Version !! NID | ||
|- | |- | ||
| 3.60 || | | 0.990-3.60 || 0x0203ECDC | ||
|} | |} | ||
<source lang="c">int | Temp name was sceSdWriteSector2ForDriver. | ||
<source lang="c">int sceSdWriteSectorInternalForDriver(sd_context_part *ctx, int unk0, int unk1);</source> | |||
=== sdif_cmd0_cmd13=== | === sdif_cmd0_cmd13=== | ||
Line 986: | Line 1,002: | ||
<source lang="c">int sdif_cmd0_cmd13(sd_context_global *ctx, int *result);</source> | <source lang="c">int sdif_cmd0_cmd13(sd_context_global *ctx, int *result);</source> | ||
=== | === reset_to_low_speed_mode === | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
Line 994: | Line 1,010: | ||
|} | |} | ||
<source lang="c">int | this function sends CMD0 reset command to the card | ||
then enables (Internal Clock Enable) bit | |||
then waits til clock is stable (Internal Clock Stable) | |||
then enables (SD Clock Enable) bit for sdio device | |||
then resets (High Speed Enable) bit | |||
then resets (Data Transfer Width) bit | |||
then resets (Extended Data Transfer Width) bit | |||
<source lang="c">int reset_to_low_speed_mode(int sd_ctx_index);</source> | |||
=== | === get_host_info === | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
Line 1,004: | Line 1,034: | ||
|} | |} | ||
<source lang="c">int | <source lang="c">int get_host_info(int sd_ctx_index, host_info *info);</source> | ||
=== | === get_device_info === | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
Line 1,014: | Line 1,044: | ||
|} | |} | ||
<source lang="c">int | <source lang="c">int get_device_info(int sd_ctx_index, device_info* result);</source> | ||
=== | === sdif_cmd_exec=== | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
Line 1,024: | Line 1,054: | ||
|} | |} | ||
<source lang="c">int | <source lang="c">int sdif_cmd_exec(int sd_ctx_index, cmd_info* info);</source> | ||
=== | === set_default_sector_size_mmc=== | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
Line 1,034: | Line 1,064: | ||
|} | |} | ||
<source lang="c">int | this function internally also executes CMD16 which sets BLOCKLEN | ||
<source lang="c"> | |||
// default_sector_size should be equal to 0x200 | |||
int set_default_sector_size_mmc(sd_context_part* ctx, int default_sector_size); | |||
</source> | |||
=== sdif_cmd0_cmd16=== | === sdif_cmd0_cmd16=== | ||
Line 1,046: | Line 1,081: | ||
<source lang="c">int sdif_cmd0_cmd16(sd_context_part* ctx, int num_200);</source> | <source lang="c">int sdif_cmd0_cmd16(sd_context_part* ctx, int num_200);</source> | ||
[[Category:ARM]] | |||
[[Category:Kernel]] | |||
[[Category:Modules]] | [[Category:Modules]] | ||
[[Category: | [[Category:Library]] |
Latest revision as of 17:14, 20 January 2024
Sdif likely stands for Storage Device InterFace. SceSdif is a kernel module that is primary responsible for communicating with SD devices. This includes eMMC (internal storage), gamecard MMC, SD/micro SD card, Wlan/Bt SDIO devices. Memory Card is handled by SceMsif instead as it uses an authentication security layer.
To communicate with a particular device SceSdif module uses device index (sd_ctx_index).
Device Index | Device | Device Type | Description |
---|---|---|---|
0 | Internal | MMC | eMMC (internal storage) |
1 | Game card | MMC/SD | Gamecard/?SD card? |
2 | Wlan/Bt | SDIO | Wlan/Bt |
3 | Micro SD | SD | Used by SceSdstor "usd" device. Related to error 0x80320013 on release FW 3.600.011 but maybe used on old FW versions. |
There is one more index value that closely correlates with Device Index. This is speculated to be Device Type Index. It is initialized by internal subroutine that does preinitialization (cmd0, cmd8, cmd5_sdio, cmd55, acmd41). Value is typically stored in sd_context_data structure in field dev_type_idx.
Device Type Index | Device Type | Associated SceSdif init function |
---|---|---|
0 | Unknown (invalid?) | None? |
1 | MMC | get_sd_context_part_validate_mmc |
2 | SD | get_sd_context_part_validate_sd |
3 | SDIO | get_sd_context_part_validate_sdio |
Module
Version | World | Privilege |
---|---|---|
0.990.000-3.740.011 | Non-secure | Kernel |
Libraries
Known NIDs
Version | Name | World | Visibility | NID |
---|---|---|---|---|
0.990.000-3.740.011 | SceSdifForDriver | Non-secure | Kernel | 0x96D306FA |
Data segment layout
Address | Size | Description |
---|---|---|
0x0000 | 0x40 | sdif_context_general |
0x0040 | 0x24C0 | sd_context_global (eMMC) |
0x2500 | 0x24C0 | sd_context_global (gamecard) |
0x49C0 | 0x24C0 | sd_context_global (wlan/bt) |
0x6E80 | 0x398 | sd_context_part_mmc (eMMC) |
0x7218 | 0x398 | sd_context_part_mmc (gamecard) |
0x75B0 | 0xC0 | sd_context_part_sd (unknown) used in initialize_sd_device |
0x7670 | 0xC0 | sd_context_part_sd (gamecard) used in initialize_sd_device |
0x7730 | 0xC0 | sd_context_part_sd (unknown) used in initialize_sd_device |
0x77F0 | 0xD38 | custom context used in wlan_bt_initialize_custom_context2 |
0x8528 | 0xD38 | custom context used in wlan_bt_initialize_custom_context2 |
0x9260 | 0x398 | sd_context_part_wlanbt (wlan/bt) |
0x95F8 | 0x888 | unknown |
0x9E80 | 0x118 | some wlan/bt data |
Allocated blocks
During initialization step Sdif driver allocates couple of memory blocks. This happens when 'module_start' function is called, inside 'init' function.
There are 2 blocks per device context. Each block is named as SceSdif<N> where N is array index.
First block is of size 0x1000 - SceUID and void* are stored in sd_context_data per device context.
Second block is of size 0x10000 - SceUID and void* are stored in sd_context_data per device context.
First block is DMA copied to / from corresponding SceSdif<N> physical address.
First block looks like to have layout that corresponds to standard SD/MMC host that is described in "Physical Layer Simplified Specification".
SceSdifForDriver
Types
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 { sd_mmc_registers* 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_mmc_registers { } sd_mmc_registers; 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; sd_mmc_registers* 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 ?) fast_mutex 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_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 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; }
sceSdifInitForDriver
Version | NID |
---|---|
3.60 | 0x0eb0ef86 |
SceInt32 sceSdifInitForDriver(void);
deinit
Version | NID |
---|---|
3.60 | 0xe5e5f42e |
int deinit();
return_error
Version | NID |
---|---|
3.60 | 0x235ad556 |
int return_error();
sceSdifMemoryCardEnableSlowModeForDriver
Version | NID |
---|---|
0.990-3.60 | 0xF37CF8E5 |
Temp name was sceSdifEnableSlowCardModeForDriver.
sets slow_mode flag in sd_context_data for gamecard device
also tries to set flag for device with index 3 but it does not actually exist
int sceSdifMemoryCardEnableSlowModeForDriver(void);
sceSdifDisableSlowCardModeForDriver
Version | NID |
---|---|
3.60 | 0x29A71E7F |
Temp name was sceSdifMemoryCardEnableSlowModeForDriver.
resets slow_mode flag in sd_context_data for gamecard device
also tries to reset flag for device with index 3 but it does not actually exist
int sceSdifDisableSlowCardModeForDriver(void);
sceSdifMemoryCardGetCardInsertStateForDriver
Version | NID |
---|---|
3.60 | 0x36a2b01b |
gc/gcsd.
Temp name was sceSdifGetCardInsertState1ForDriver, get_card_insert_state1.
int sceSdifMemoryCardGetCardInsertStateForDriver(SceSdifDevice dev);
get_card_insert_state2
Version | NID |
---|---|
3.60 | 0xfd9e5cfa |
int get_card_insert_state2(int sd_ctx_index);
gc_cmd56_response
Version | NID |
---|---|
3.60 | 0x134E06C4 |
int gc_cmd56_response(sd_context_part *ctx, void *buffer, SceSize length);
gc_cmd56_request
Version | NID |
---|---|
3.60 | 0xB0996641 |
sceMmcSendGeneralCmdData
int gc_cmd56_request(sd_context_part *ctx, const void *buffer, SceSize length);
get_sd_context_global
Version | NID |
---|---|
3.60 | 0xdc8f52f8 |
sd_context_global* get_sd_context_global(int sd_ctx_index);
get_sd_context_part_validate_mmc
Version | NID |
---|---|
3.60 | 0x6a71987f |
sd_context_part* get_sd_context_part_validate_mmc(int sd_ctx_index);
get_sd_context_part_validate_sd
Version | NID |
---|---|
3.60 | 0xb9ea5b1e |
sd_context_part* get_sd_context_part_validate_sd(int sd_ctx_index);
get_sd_context_part_validate_sdio
Version | NID |
---|---|
3.60 | 0x6a8235fc |
sd_context_part* get_sd_context_part_validate_sdio(int sd_ctx_index);
initialize_mmc_device
Version | NID |
---|---|
3.60 | 0x22c82e79 |
this function only initializes devices with sd_ctx_index 0 and 1 and returns 0x80320013 on any other sd_ctx_index
it is confirmed that this function sends sequence of commands that correspond to MMC initialization protocol
int initialize_mmc_device(SceSdifDevice dev, sd_context_part** result);
wlan_bt_acquiredev
Version | NID |
---|---|
3.60 | 0x3428884d |
Called in initialization sequence.
int wlan_bt_acquiredev(wlan_context* wlan_ctx);
wlan_bt_release
Version | NID |
---|---|
3.60 | 0xe80293ef |
Called in failures. Assumed to be release of sdio device.
int wlan_bt_release(wlan_context* wlan_ctx);
sceSdioReadForDriver
Version | NID |
---|---|
3.60 | 0xD0F78D9B |
Reads from Wlan/BT SDIO device.
Example from SceWlanBt:
ret = sceSdioReadForDriver(wlan_ctx, 0x5C, 1, &g_card_rev, 1);
// type: 1 for register access, 2 for data access int sceSdioReadForDriver(wlan_context* wlan_ctx, int reg, int count, void* dst, int type);
sceSdioWriteForDriver
Version | NID |
---|---|
3.60 | 0x3C4CDC8B |
Writes from wlan sdio device.
Type variable seems to define which access to use. 1 is for register access, 2 is for data access.
int sceSdioWriteForDriver(wlan_context* wlan_ctx, int reg, int count, void *src, int type);
sceSdioSetBlockLenForDriver
Version | NID |
---|---|
3.60 | 0x733BC373 |
int sceSdioSetBlockLenForDriver(wlan_context* wlan_ctx, int num);
wlan_bt_cmd52_sdio
Version | NID |
---|---|
3.60 | 0xdece963b |
int wlan_bt_cmd52_sdio(sd_context_part* ctx, int num0, int num1, void* unk2);
wlan_bt_cmd52_sdio
Version | NID |
---|---|
0.996.090-3.740.011 | 0x5D65E66B |
// cond: wakeup condition as in scePowerSetWakeupConditionForDriver int wlan_bt_cmd52_sdio(sd_context_part* ctx, int cond, SceBool num1, SceUInt32* pOut);
sceSdioChangeBusSpeedForDriver
Version | NID |
---|---|
3.60 | 0xBC45C83D |
int sceSdioChangeBusSpeedForDriver(sd_context_part* ctx, int num);
wlan_bt_initialize_custom_context2
Version | NID |
---|---|
0.990.000-3.740.011 | 0xAABAA0F0 |
this function can send these commands: cmd3, cmd52_sdio, cmd0, cmd5_sdio, cmd55, acmd41, cmd7, cmd8
this function uses array of 2 custom contexts.
this function can either set device type index to 3 and use custom context for initialization.
or it can use preinitialization (cmd0, cmd8, cmd5_sdio, cmd55, acmd41) and then check that device type index is 3.
if device type index is not 3 then 0x80320017 error is returned.
int wlan_bt_initialize_custom_context2(int sd_ctx_index, sd_context_part** ctx);
wlan_bt_bulk_transfer
Version | NID |
---|---|
3.60 | 0x855C95E1 |
This is a guessed name.
This function is used in aggregated frame transmit when more than one packet is being transmitted over Wlan.
int wlan_bt_bulk_transfer(wlan_context* wlan_ctx, bulk_transfer* b, void* unk1);
wlan_bt_get_wlan_context
Version | NID |
---|---|
3.60 | 0x0c66e36f |
Get wlan_context for sdio device. Vidpid is an array with Marvell Vid and Wlan/Bt pid.
For Wlan: vidpid = [0x2df, 0x911a]. For Bt: vidpid = [0x2df, 0x9119].
int wlan_bt_get_wlan_context(sd_context_part* ctx, int vidpid[2]);
sceSdifGoStandbyStateForDriver
Version | NID |
---|---|
0.990-3.60 | 0xAB0222F2 |
Temp name was wlan_bt_cmd7.
int sceSdifGoStandbyStateForDriver(sd_context_part* ctx);
wlan_bt_cmd52_sdio
Version | NID |
---|---|
3.60 | 0x55baeb2d |
int wlan_bt_cmd52_sdio(wlan_context* wlan_ctx);
wlan_bt_cmd52_sdio
Version | NID |
---|---|
3.60 | 0xfe6f3e7b |
int wlan_bt_cmd52_sdio(wlan_context* wlan_ctx);
wlan_bt_cmd52_sdio
Version | NID |
---|---|
3.60 | 0xf1a24edd |
int wlan_bt_cmd52_sdio(wlan_context* wlan_ctx);
wlan_bt_cmd52_sdio
Version | NID |
---|---|
3.60 | 0x1847b18c |
int wlan_bt_cmd52_sdio(wlan_context* wlan_ctx);
wlan_bt_cmd52_sdio
Version | NID |
---|---|
3.60 | 0xd3c1e2b6 |
int wlan_bt_cmd52_sdio(wlan_context* wlan_ctx, int unk0, int unk1, int unk2);
wlan_bt_cmd52_sdio
Version | NID |
---|---|
3.60 | 0x5bac6e70 |
int wlan_bt_cmd52_sdio(wlan_context* wlan_ctx, int unk0, int unk1, int unk2);
wlan_bt_cmd52_sdio
Version | NID |
---|---|
3.60 | 0x01e8eb6c |
int wlan_bt_cmd52_sdio(sd_context_part* ctx, char* output, int destLength_100);
wlan_bt_cmd52_sdio
Version | NID |
---|---|
3.60 | 0x763f1075 |
int wlan_bt_cmd52_sdio(sd_context_part* ctx);
wlan_bt_initialize_custom_context1
Version | NID |
---|---|
3.60 | 0x53962379 |
This function is just a wrapper for wlan_bt_initialize_custom_context2.
int wlan_bt_initialize_custom_context1(int sd_ctx_index);
wlan_bt_cmd0
Version | NID |
---|---|
3.60 | 0x3b6ab29e |
int wlan_bt_cmd0(wlan_context* wlan_ctx, void* unk0, int* result);
wlan_bt_cmd0_cmd52_sdio
Version | NID |
---|---|
3.60 | 0x180e7395 |
int wlan_bt_cmd0_cmd52_sdio(wlan_context* wlan_ctx, char* output, int destLength_100);
wlan_bt
Version | NID |
---|---|
3.60 | 0x0f157f49 |
int wlan_bt(wlan_context* wlan_ctx);
wlan_bt
Version | NID |
---|---|
3.60 | 0x849e3216 |
int wlan_bt(wlan_context* wlan_ctx);
wlan_bt
Version | NID |
---|---|
3.60 | 0xb05eff68 |
int wlan_bt(wlan_context *wlan_ctx, int unk0);
sceMmcReadSectorForDriver
Version | NID |
---|---|
0.990-3.60 | 0x6F8D529B |
int sceMmcReadSectorForDriver(sd_context_part* ctx, int sector, char* buffer, int nSectors);
sdstor_read_sector_sd
Version | NID |
---|---|
3.60 | 0xb9593652 |
If nSectors
is 1
, then issues command 0x11
(READ_SINGLE_BLOCK
), and otherwise, command 0x12
(READ_MULTIPLE_BLOCK
).
int sdstor_read_sector_sd(sd_context_part* ctx, int sector, char* buffer, int nSectors);
sceMmcWriteSectorForDriver
Version | NID |
---|---|
0.990-3.60 | 0x175543D2 |
int sceMmcWriteSectorForDriver(sd_context_part* ctx, int sector, char* buffer, int nSectors);
sceSdWriteSectorForDriver
Version | NID |
---|---|
0.990-3.60 | 0xE0781171 |
int sceSdWriteSectorForDriver(sd_context_part* ctx, int sector, char* buffer, int nSectors);
sddev_get_sd_cidForDriver
Version | NID |
---|---|
0.931.010-3.20 | not present |
3.300.041-3.740.011 | 0x23A4EF01 |
This is the name of the subroutine. Temp name was sdstor_get_cidForDriver, sceSdifGetCIDForDriver.
//size of cid is 0x10 int sddev_get_sd_cidForDriver(sd_context_part* ctx, char* cid);
sdstor_cmd0_cmd13
Version | NID |
---|---|
3.60 | 0x6cc8e28d |
int sdstor_cmd0_cmd13(int sd_ctx_index);
sceSdEraseForDriver
Version | NID |
---|---|
3.60 | 0x35ba9df8 |
This is a guessed name.
Temp name was sdstor_cmd32_cmd33_cmd38_sdio.
Used by SceSdstor.
int sceSdEraseForDriver(SceSdifDevice dev, SceUID callback_id);
initialize_sd_device
Version | NID |
---|---|
3.60 | 0xC1271539 |
This function sends sequence of commands that correspond to SD initialization protocol. These commands include: cmd0, cmd8, cmd5_sdio, cmd2, cmd3, cmd6, cmd9, cmd7, cmd16. Some paired commands are: (cmd55, acmd41), (cmd55, acmd42), (cmd55, acmd13), (cmd55, acmd51).
- it does not check sd_ctx_index argument.
- it uses array of 3 custom contexts instead of sd_context_part structures.
- it checks device type index after preinitialization (cmd0, cmd8, cmd5_sdio, cmd55, acmd41)
- it only initializes device with device type index 2. otherwise 0x80320017 error is returned.
int initialize_sd_device(SceSdifDevice dev, int* result);
sceMmcHasWriteProtectForDriver
Version | NID |
---|---|
3.60-3.65 | 0x995748EA |
This is a guessed name.
Temp name was sdstor_cmd6_cmd30, sendWriteProtectStatusForDriver.
int sceMmcHasWriteProtectForDriver(sd_context_part *input, SceUInt32 posSector, SceUInt32 nSector, SceBool *result);
sceSdHasWriteProtectForDriver
Version | NID |
---|---|
3.60 | 0xE091BA2E |
This is a guessed name.
int sceSdHasWriteProtectForDriver(sd_context_part *input, SceUInt32 posSector, SceUInt32 nSector, SceBool *result);
sceMmcWriteSectorInternalForDriver
Version | NID |
---|---|
0.990-3.60 | 0x60642F49 |
Temp name was sceMmcWriteSector2ForDriver.
int sceMmcWriteSectorInternalForDriver(sd_context_part *ctx, int unk0, int unk1);
sceSdWriteSectorInternalForDriver
Version | NID |
---|---|
0.990-3.60 | 0x0203ECDC |
Temp name was sceSdWriteSector2ForDriver.
int sceSdWriteSectorInternalForDriver(sd_context_part *ctx, int unk0, int unk1);
sdif_cmd0_cmd13
Version | NID |
---|---|
3.60 | 0x53518827 |
int sdif_cmd0_cmd13(sd_context_global *ctx, int *result);
reset_to_low_speed_mode
Version | NID |
---|---|
3.60 | 0x475d8e45 |
this function sends CMD0 reset command to the card
then enables (Internal Clock Enable) bit
then waits til clock is stable (Internal Clock Stable)
then enables (SD Clock Enable) bit for sdio device
then resets (High Speed Enable) bit
then resets (Data Transfer Width) bit
then resets (Extended Data Transfer Width) bit
int reset_to_low_speed_mode(int sd_ctx_index);
get_host_info
Version | NID |
---|---|
3.60 | 0x3df7e207 |
int get_host_info(int sd_ctx_index, host_info *info);
get_device_info
Version | NID |
---|---|
3.60 | 0x76d2b87b |
int get_device_info(int sd_ctx_index, device_info* result);
sdif_cmd_exec
Version | NID |
---|---|
3.60 | 0xb83f7518 |
int sdif_cmd_exec(int sd_ctx_index, cmd_info* info);
set_default_sector_size_mmc
Version | NID |
---|---|
3.60 | 0xb32776c7 |
this function internally also executes CMD16 which sets BLOCKLEN
// default_sector_size should be equal to 0x200 int set_default_sector_size_mmc(sd_context_part* ctx, int default_sector_size);
sdif_cmd0_cmd16
Version | NID |
---|---|
3.60 | 0xaf702fe7 |
int sdif_cmd0_cmd16(sd_context_part* ctx, int num_200);