Difference between revisions of "SceSdif"

From Vita Development Wiki
Jump to navigation Jump to search
(27 intermediate revisions by 3 users not shown)
Line 1: Line 1:
SceSdif is a kernel module that is primary responsible for communicating with SD devices. This includes onboard eMMC, game card MMC, wi-fi/bluetooth SDIO devices.
+
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, wlan/bt SDIO devices.
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"
Line 6: Line 7:
 
! Device Index  !! Type !! Description
 
! Device Index  !! Type !! Description
 
|-
 
|-
| 0 || MMC || onboard eMMC
+
| 0 || MMC || eMMC (internal storage)
 +
|-
 +
| 1 || MMC || Gamecard
 
|-
 
|-
| 1 || MMC || game card
+
| 2 || SDIO || Wlan/bt
 
|-
 
|-
| 2 || SDIO || wi-fi/bluetooth
+
| 3 || UNK || used by [[SceSdstor]] "usd" device. but 0x80320013 on 3.60. maybe used on old fw.
 
|}
 
|}
  
There is one more index value that closely correlates with device index.
+
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 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.
 
  
 
{| class="wikitable"
 
{| class="wikitable"
Line 30: Line 31:
  
 
Device type index will be validated when sd_context_part* will be aquired through these functions:
 
Device type index will be validated when sd_context_part* will be aquired through these functions:
*[[SceSdif#get_sd_context_part_validate_mmc|get_sd_context_part_validate_mmc]] - device type index must be 1
+
* [[SceSdif#get_sd_context_part_validate_mmc|get_sd_context_part_validate_mmc]] - device type index must be 1
*[[SceSdif#get_sd_context_part_validate_sd|get_sd_context_part_validate_sd]] - device type index must be 2
+
* [[SceSdif#get_sd_context_part_validate_sd|get_sd_context_part_validate_sd]] - device type index must be 2
*[[SceSdif#get_sd_context_part_validate_sdio|get_sd_context_part_validate_sdio]] - device type index must be 3
+
* [[SceSdif#get_sd_context_part_validate_sdio|get_sd_context_part_validate_sdio]] - device type index must be 3
 
 
  
 
== Module ==
 
== Module ==
  
=== Known NIDs ===
 
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
! Version !! Name !! World !! Privilege !! NID
+
! Version !! World !! Privilege
 
|-
 
|-
| 1.69 || SceSdif || Non-secure || Kernel || 0xCA882EE3
+
| 1.69-3.65 || Non-secure || Kernel
|-
 
| 3.60 || SceSdif || Non-secure || Kernel || 0x2E7C52F7
 
|-
 
| 3.65 || SceSdif || Non-secure || Kernel || 0x285023ED
 
 
|}
 
|}
  
Line 70: Line 65:
 
| 0x0040 || 0x24C0 || sd_context_global (eMMC)
 
| 0x0040 || 0x24C0 || sd_context_global (eMMC)
 
|-
 
|-
| 0x2500 || 0x24C0 || sd_context_global (game card)
+
| 0x2500 || 0x24C0 || sd_context_global (gamecard)
 
|-
 
|-
 
| 0x49C0 || 0x24C0 || sd_context_global (wlan/bt)
 
| 0x49C0 || 0x24C0 || sd_context_global (wlan/bt)
Line 76: Line 71:
 
| 0x6E80 || 0x398 || sd_context_part_mmc (eMMC)
 
| 0x6E80 || 0x398 || sd_context_part_mmc (eMMC)
 
|-
 
|-
| 0x7218 || 0x398 || sd_context_part_mmc (game card)
+
| 0x7218 || 0x398 || sd_context_part_mmc (gamecard)
 
|-
 
|-
 
| 0x75B0 || 0xC0 || sd_context_part_sd (unknown) used in initialize_sd_device (c1271539)
 
| 0x75B0 || 0xC0 || sd_context_part_sd (unknown) used in initialize_sd_device (c1271539)
 
|-
 
|-
| 0x7670 || 0xC0 || sd_context_part_sd (game card) used in initialize_sd_device (c1271539)
+
| 0x7670 || 0xC0 || sd_context_part_sd (gamecard) used in initialize_sd_device (c1271539)
 
|-
 
|-
 
| 0x7730 || 0xC0 || sd_context_part_sd (unknown) used in initialize_sd_device (c1271539)
 
| 0x7730 || 0xC0 || sd_context_part_sd (unknown) used in initialize_sd_device (c1271539)
Line 93: Line 88:
 
|-
 
|-
 
| 0x9E80 || 0x118 || some wlan/bt data
 
| 0x9E80 || 0x118 || some wlan/bt data
|-
 
 
|}
 
|}
  
Line 109: Line 103:
 
First block is DMA copied to / from corresponding SceSdif<N> [[Physical_Memory|physical address]].
 
First block is DMA copied to / from corresponding SceSdif<N> [[Physical_Memory|physical address]].
  
First block looks like to have layout that corresponds to standard SD/MMC host that is described in "Physical Layer Simplified Specification"
+
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 115: Line 109:
 
=== Types ===
 
=== Types ===
  
<source lang="c">
+
<source lang="C">
 
+
typedef struct cmd_info {
typedef struct cmd_info
 
{
 
 
   uint32_t state_flags;
 
   uint32_t state_flags;
 
   uint32_t command;
 
   uint32_t command;
Line 126: Line 118:
 
   uint16_t resp_n_blocks;
 
   uint16_t resp_n_blocks;
 
    
 
    
   union
+
   union {
  {
+
     struct {
     struct
 
    {
 
 
         char data[0x10];
 
         char data[0x10];
 
     } db;
 
     } db;
     struct
+
     struct {
    {
 
 
         uint32_t dw0;
 
         uint32_t dw0;
 
         uint32_t dw1;
 
         uint32_t dw1;
Line 139: Line 128:
 
         uint32_t dw3;
 
         uint32_t dw3;
 
     } dw;
 
     } dw;
   }response;
+
   } response;
 
    
 
    
 
   uint32_t error_code;
 
   uint32_t error_code;
 
} cmd_info;
 
} cmd_info;
  
typedef struct host_info
+
typedef struct host_info {
{
 
 
     sd_mmc_registers* host_registers;
 
     sd_mmc_registers* host_registers;
 
     uint32_t unk_4;
 
     uint32_t unk_4;
Line 161: Line 149:
 
} host_info;
 
} host_info;
  
typedef struct device_info
+
typedef struct device_info {
{
 
 
     uint32_t dev_type_idx; // (1,2,3)
 
     uint32_t dev_type_idx; // (1,2,3)
 
     uint32_t unk_4;
 
     uint32_t unk_4;
Line 168: Line 155:
 
} device_info;
 
} 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 189: Line 175:
 
     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
+
   // bit 10 (shift left 0x15) - request invalidate flag - invalidate vaddr_1C0 and vaddr_200
   //this flag is used for CMD56 and CMD17
+
   // 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 (shift left 0xB) - request mem_188 free - free memblock with uid mem_188
  
   //bit 20 or bit 9 cancels invalidation (both must be clear)
+
   // 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
  
Line 205: Line 190:
 
   uint32_t argument;
 
   uint32_t argument;
 
    
 
    
   //stores normal response without command index and crc-7
+
   // stores normal response without command index and crc-7
   //can also store CID or CSD. crr-7 will be cleared
+
   // can also store CID or CSD. crr-7 will be cleared
   //storage order is reversed
+
   // storage order is reversed
   union
+
   union {
  {
+
     struct {
     struct
 
    {
 
 
         char data[0x10];
 
         char data[0x10];
 
     } db;
 
     } db;
     struct
+
     struct {
    {
 
 
         uint32_t dw0;
 
         uint32_t dw0;
 
         uint32_t dw1;
 
         uint32_t dw1;
Line 221: Line 203:
 
         uint32_t dw3;
 
         uint32_t dw3;
 
     } dw;
 
     } dw;
   }response;
+
   } response;
  
 
   void* buffer; // cmd data buffer ptr - dest for vaddr_1C0
 
   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_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
 
   uint16_t resp_n_blocks_26; // number of blocks in response. typically number of sectors to read/write
   uint32_t error_code; //error from interrupt handler (confirmed)
+
   uint32_t error_code; // error code from interrupt handler (confirmed)
 
   uint32_t unk_2C;
 
   uint32_t unk_2C;
  
Line 232: Line 214:
 
    
 
    
 
   struct cmd_input* next_cmd;
 
   struct cmd_input* next_cmd;
   uint32_t unk_64; //some flag. must be 3 for invalidation to happen
+
   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)(void* ctx);
 
   int(*set_event_flag_callback)(void* ctx);
Line 241: Line 223:
 
   uint32_t unk_7C;
 
   uint32_t unk_7C;
 
    
 
    
   char vaddr_80[0x80]; //3 - mapped to paddr_184 (invalidate 0x80)
+
   char vaddr_80[0x80]; // 3 - mapped to paddr_184 (invalidate 0x80)
  
 
   void* vaddr_100;
 
   void* vaddr_100;
Line 247: Line 229:
  
 
   uint32_t unk_180;
 
   uint32_t unk_180;
   void* paddr_184; //3 - phys address of vaddr_80
+
   void* paddr_184; // 3 - phys address of vaddr_80
   SceUID mem_188; //SceSdif memblock
+
   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)
+
   void* base_198; // dest base for vaddr_200 (also ptr for invalidate)
                   //data at base contains CMD17 data
+
                   // data at base contains CMD17 data
                   //data at base also contains fragments of CMD56 response
+
                   // data at base also contains fragments of CMD56 response
                   //data at offset is unknown (zeroes)
+
                   // data at offset is unknown (zeroes)
 
   uint32_t offset_19C; //dest offset for vaddr_200 (also size for invalidate)
 
   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_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
+
   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_1A8; // 1 - phys address of vaddr_1C0
   void* paddr_1AC; //2 - phys address of vaddr_200
+
   void* paddr_1AC; // 2 - phys address of vaddr_200
  
 
   SceInt64 wide_time1; // 0x1B0
 
   SceInt64 wide_time1; // 0x1B0
 
   SceInt64 wide_time2; // 0x1B8 - relevant for commands that need to wait for data on DAT lines
 
   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)
+
   char vaddr_1C0[0x40]; // 1 - mapped to paddr_1A8 (invalidate 0x40)
                         // - only valid if request invalidate flag is set
+
                         //   - only valid if request invalidate flag is set
                         // - contains fragments of CMD56 request/response
+
                         //   - contains fragments of CMD56 request/response
                         // - does not contain CMD17 data
+
                         //   - does not contain CMD17 data
  
   char vaddr_200[0x40]; //2 - mapped to paddr_1AC (invalidate 0x40)
+
   char vaddr_200[0x40]; // 2 - mapped to paddr_1AC (invalidate 0x40)
                         // - only valid if request invalidate flag is set
+
                         //   - only valid if request invalidate flag is set
                         // - contains unknown data (zeroes)
+
                         //   - contains unknown data (zeroes)
 
} cmd_input;
 
} cmd_input;
  
typedef struct sd_mmc_registers
+
typedef struct sd_mmc_registers {
{
 
  
}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 289: Line 269:
 
     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*)
+
     sd_context_part_base* ctx; // pointer to custom context (sd_context_part_mmc*, sd_context_part_sd*, sd_context_part_wlanbt*)
 
     uint32_t unk_18;
 
     uint32_t unk_18;
 
     uint32_t unk_1C;
 
     uint32_t unk_1C;
Line 305: Line 285:
 
     uint32_t unk_34;
 
     uint32_t unk_34;
 
     uint8_t unk_38;
 
     uint8_t unk_38;
     uint8_t slow_mode; //relevant only for 2 read and 2 write functions
+
     uint8_t slow_mode; // relevant only for 2 read and 2 write functions
 
     uint8_t unk_3A;
 
     uint8_t unk_3A;
 
     uint8_t unk_3B;
 
     uint8_t unk_3B;
Line 337: Line 317:
 
} 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 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_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
+
   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;
 
    
 
    
Line 363: Line 341:
 
} 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 370: Line 347:
 
} 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 377: Line 353:
 
} 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>
  
Line 415: Line 400:
 
<source lang="c">int return_error();</source>
 
<source lang="c">int return_error();</source>
  
=== sceSdifEnableSlowCardMode ===
+
=== sceSdifMemoryCardEnableSlowModeForDriver ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0xF37CF8E5
+
| 0.990-3.60 || 0xF37CF8E5
 
|}
 
|}
  
sets slow_mode flag in sd_context_data for game card device
+
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
 
also tries to set flag for device with index 3 but it does not actually exist
  
<source lang="c">int sceSdifEnableSlowCardMode();</source>
+
<source lang="c">int sceSdifMemoryCardEnableSlowModeForDriver(void);</source>
  
=== get_card_insert_state1 ===
+
=== sceSdifDisableSlowCardModeForDriver ===
 +
{| class="wikitable"
 +
|-
 +
! Version !! NID
 +
|-
 +
| 3.60 || 0x29A71E7F
 +
|}
 +
 
 +
Temp name was sceSdifMemoryCardEnableSlowMode.
 +
 
 +
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 437: Line 440:
 
|}
 
|}
  
<source lang="c">int get_card_insert_state1(int sd_ctx_index);</source>
+
Temp name was sceSdifGetCardInsertState1ForDriver, get_card_insert_state1.
 +
 
 +
<source lang="c">int sceSdifMemoryCardGetCardInsertStateForDriver(int sd_ctx_index);</source>
  
 
=== get_card_insert_state2 ===
 
=== get_card_insert_state2 ===
Line 531: Line 536:
 
|}
 
|}
  
<source lang="c">int wlan_bt_cmd52_sdio(wlan_context* wlan_ctx);</source>
+
Called in initialization sequence.
 +
 
 +
<source lang="c">int wlan_bt_acquiredev(wlan_context* wlan_ctx);</source>
  
 
=== wlan_bt_cmd52_sdio ===
 
=== wlan_bt_cmd52_sdio ===
Line 541: Line 548:
 
|}
 
|}
  
<source lang="c">int wlan_bt_cmd52_sdio(wlan_context* wlan_ctx);</source>
+
Called in failures. Assumed to be release of sdio device.
 +
 
 +
<source lang="c">int wlan_bt_release(wlan_context* wlan_ctx);</source>
  
=== wlan_bt_cmd52_sdio ===
+
=== sceSdioReadForDriver ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0xd0f78d9b
+
| 3.60 || 0xD0F78D9B
 
|}
 
|}
  
<source lang="c">int wlan_bt_cmd52_sdio(wlan_context* wlan_ctx, int num0, int num1, void* unk2, int num3);</source>
+
Reads from wlan sdio device.
 +
 
 +
Type variable seems to define which access to use. 1 is for register access, 2 is for data access.
  
=== wlan_bt_cmd52_sdio ===
+
<source lang="c">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 || 0x3c4cdc8b
+
| 3.60 || 0x3C4CDC8B
 
|}
 
|}
  
<source lang="c">int wlan_bt_cmd52_sdio(wlan_context* wlan_ctx, int num0, int num1, void* unk2, int num3);</source>
+
Writes from wlan sdio device.
  
=== wlan_bt_cmd52_sdio ===
+
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 || 0x733bc373
+
| 3.60 || 0x733BC373
 
|}
 
|}
  
<source lang="c">int wlan_bt_cmd52_sdio(wlan_context* wlan_ctx, int num);</source>
+
<source lang="c">int sceSdioSetBlockLenForDriver(wlan_context* wlan_ctx, int num);</source>
  
 
=== wlan_bt_cmd52_sdio ===
 
=== wlan_bt_cmd52_sdio ===
Line 593: Line 610:
 
<source lang="c">int wlan_bt_cmd52_sdio(sd_context_part* ctx, int num0, int num1, void* unk2);</source>
 
<source lang="c">int wlan_bt_cmd52_sdio(sd_context_part* ctx, int num0, int num1, void* unk2);</source>
  
=== wlan_bt_cmd52_sdio ===
+
=== sceSdioChangeBusSpeedForDriver ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0xbc45c83d
+
| 3.60 || 0xBC45C83D
 
|}
 
|}
  
<source lang="c">int wlan_bt_cmd52_sdio(sd_context_part* ctx, int num);</source>
+
<source lang="c">int sceSdioChangeBusSpeedForDriver(sd_context_part* ctx, int num);</source>
  
 
=== wlan_bt_initialize_custom_context2 ===
 
=== wlan_bt_initialize_custom_context2 ===
Line 630: Line 647:
 
| 3.60 || 0x855c95e1
 
| 3.60 || 0x855c95e1
 
|}
 
|}
 +
]
 +
 +
This function is used in aggregated frame transmit when more than one packet is being transmitted over wlan.
  
<source lang="c">int wlan_bt(wlan_context* wlan_ctx, void* unk0, void* unk1);</source>
+
<source lang="c">int wlan_bt_bulk_transfer(wlan_context* wlan_ctx, bulk_transfer* b, void* unk1);</source>
  
 
=== wlan_bt ===
 
=== wlan_bt ===
Line 641: Line 661:
 
|}
 
|}
  
<source lang="c">int wlan_bt(sd_context_part* ctx, void* unk0);</source>
+
Get wlan_context for sdio device. Vidpid is array with Marvell Vid and wlan/bt pid.
 +
 
 +
For wlan: vidpid = [0x02df, 0x911a]
 +
 
 +
For bt: vidpid = [0x2df, 0x9119]
 +
 
 +
<source lang="c">int wlan_bt_get_wlan_context(sd_context_part* ctx, int vidpid[2]);</source>
  
=== wlan_bt_cmd7 ===
+
=== sceSdifGoStandbyStateForDriver ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0xab0222f2
+
| 0.990-3.60 || 0xAB0222F2
 
|}
 
|}
 +
 +
Temp name was wlan_bt_cmd7.
  
 
<source lang="c">int wlan_bt_cmd7(sd_context_part* ctx);</source>
 
<source lang="c">int wlan_bt_cmd7(sd_context_part* ctx);</source>
Line 911: Line 939:
 
<source lang="c">int sdstor(sd_context_part* unk, int unk0, int unk1, int* unk2);</source>
 
<source lang="c">int sdstor(sd_context_part* unk, int unk0, int unk1, int* unk2);</source>
  
=== sdif_write===
+
=== sceMmcWriteSector2ForDriver ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0x60642f49
+
| 0.990-3.60 || 0x60642F49
 
|}
 
|}
  
<source lang="c">int sdif_write(sd_context_part *ctx, int unk0, int unk1);</source>
+
<source lang="c">int sceMmcWriteSector2ForDriver(sd_context_part *ctx, int unk0, int unk1);</source>
  
=== sdif_write===
+
=== sceSdWriteSector2ForDriver ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0x0203ecdc
+
| 0.990-3.60 || 0x0203ECDC
 
|}
 
|}
  
<source lang="c">int sdif_write(sd_context_part *ctx, int unk0, int unk1);</source>
+
<source lang="c">int sceSdWriteSector2ForDriver(sd_context_part *ctx, int unk0, int unk1);</source>
 
 
=== sceSdifDisableSlowCardMode ===
 
{| class="wikitable"
 
|-
 
! Version !! NID
 
|-
 
| 3.60 || 0x29A71E7F
 
|}
 
 
 
resets slow_mode flag in sd_context_data for game card device
 
 
 
also tries to reset flag for device with index 3 but it does not actually exist
 
 
 
<source lang="c">int sceSdifDisableSlowCardMode(void);</source>
 
  
 
=== sdif_cmd0_cmd13===
 
=== sdif_cmd0_cmd13===
Line 967: Line 981:
 
then enables (Internal Clock Enable) bit
 
then enables (Internal Clock Enable) bit
  
then waits till clock is table (Internal Clock Stable)
+
then waits til clock is stable (Internal Clock Stable)
  
 
then enables (SD Clock Enable) bit for sdio device
 
then enables (SD Clock Enable) bit for sdio device
Line 1,020: Line 1,034:
  
 
<source lang="c">
 
<source lang="c">
//default_sector_size should be equal to 0x200
+
// default_sector_size should be equal to 0x200
 
int set_default_sector_size_mmc(sd_context_part* ctx, int default_sector_size);
 
int set_default_sector_size_mmc(sd_context_part* ctx, int default_sector_size);
 
</source>
 
</source>
Line 1,033: Line 1,047:
  
 
<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:Modules]]
 
[[Category:Modules]]
 
[[Category:Kernel]]
 
[[Category:Kernel]]

Revision as of 00:20, 8 September 2022

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, wlan/bt SDIO devices.

To communicate with a particular device SceSdif module uses device index (sd_ctx_index).

Device Index Type Description
0 MMC eMMC (internal storage)
1 MMC Gamecard
2 SDIO Wlan/bt
3 UNK used by SceSdstor "usd" device. but 0x80320013 on 3.60. maybe used on old fw.

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 Description
0 unknown (invalid ?)
1 MMC
2 SD
3 SDIO

Device type index will be validated when sd_context_part* will be aquired through these functions:

Module

Version World Privilege
1.69-3.65 Non-secure Kernel

Libraries

Known NIDs

Version Name World Visibility NID
1.69-3.65 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 (c1271539)
0x7670 0xC0 sd_context_part_sd (gamecard) used in initialize_sd_device (c1271539)
0x7730 0xC0 sd_context_part_sd (unknown) used in initialize_sd_device (c1271539)
0x77F0 0xD38 custom context used in aabaa0f0
0x8528 0xD38 custom context used in aabaa0f0
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 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 unk_18;
    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;
}

init

Version NID
3.60 0x0eb0ef86
int init();

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 sceSdifMemoryCardEnableSlowMode.

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

Temp name was sceSdifGetCardInsertState1ForDriver, get_card_insert_state1.

int sceSdifMemoryCardGetCardInsertStateForDriver(int sd_ctx_index);

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, char* buffer, int length);

gc_cmd56_request

Version NID
3.60 0xb0996641
int gc_cmd56_request(sd_context_part* ctx, char* buffer, int 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(int sd_ctx_index, sd_context_part** result);

wlan_bt_cmd52_sdio

Version NID
3.60 0x3428884d

Called in initialization sequence.

int wlan_bt_acquiredev(wlan_context* wlan_ctx);

wlan_bt_cmd52_sdio

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 sdio device.

Type variable seems to define which access to use. 1 is for register access, 2 is 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
3.60 0x5d65e66b
int wlan_bt_cmd52_sdio(sd_context_part* ctx, int num0, int num1, void* unk2);

sceSdioChangeBusSpeedForDriver

Version NID
3.60 0xBC45C83D
int sceSdioChangeBusSpeedForDriver(sd_context_part* ctx, int num);

wlan_bt_initialize_custom_context2

Version NID
3.60 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

Version NID
3.60 0x855c95e1

]

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

Version NID
3.60 0x0c66e36f

Get wlan_context for sdio device. Vidpid is array with Marvell Vid and wlan/bt pid.

For wlan: vidpid = [0x02df, 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 wlan_bt_cmd7(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 (aabaa0f0)

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
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);

sdstor_get_cid

Version NID
3.60 0x23a4ef01
//size of cid is 0x10
int sdstor_get_cid(sd_context_part* ctx, char* cid);

sdstor_cmd0_cmd13

Version NID
3.60 0x6cc8e28d
int sdstor_cmd0_cmd13(int sd_ctx_index);

sdstor_cmd32_cmd33_cmd38_sdio

Version NID
3.60 0x35ba9df8
int sdstor_cmd32_cmd33_cmd38_sdio(int sd_ctx_index, int unk0);

initialize_sd_device

Version NID
3.60 0xc1271539

it is confirmed that 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: (cmd55, acmd41), (cmd55, acmd42), (cmd55, acmd13), (cmd55, acmd51)

there are couple of special points:

  • 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(int sd_ctx_index, int* result);

sdstor_cmd6_cmd30

Version NID
3.60 0x995748ea
int sdstor_cmd6_cmd30(sd_context_part *input, int unk0, int unk1, void *unk2);

sdstor

Version NID
3.60 0xe091ba2e
int sdstor(sd_context_part* unk, int unk0, int unk1, int* unk2);

sceMmcWriteSector2ForDriver

Version NID
0.990-3.60 0x60642F49
int sceMmcWriteSector2ForDriver(sd_context_part *ctx, int unk0, int unk1);

sceSdWriteSector2ForDriver

Version NID
0.990-3.60 0x0203ECDC
int sceSdWriteSector2ForDriver(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);