/dev/sdio
The drivers in this directory control access to the front SD slot, as well as an unused space for a second slot.
Ioctl listing
Request number | Name | Input | Output | Notes |
---|---|---|---|---|
1 | sd_hc_write8 | 6-word param array: [reg, 0, 0, 1 (reg size), data, 0] | none | reg and data should both be 8-bit values |
2 | sd_hc_read8 | 6-word param array: [reg, 0, 0, 1 (reg size), 0, 0] | 32-bit word | |
4 | sd_reset_card | none | 32-bit word | |
6 | sd_set_clock | 32-bit word: one half of the sdclk divisor: a power of two or zero. (usually, 1) | none | |
7 | sd_command | 9-word param array: [cmd, cmd_type, resp_type, arg, block_count, block_size, (u32)addr, 0, 0] | 4-word reply buffer ?? | input or output from command will go into the address point to by addr, which should be a physical pointer |
7 (ioctlv) | sd_data_command | 9-word param array: [cmd, cmd_type, resp_type, arg, block_count, block_size, (u32)addr, 0, 0], data buffer of arbitrary size (block_count * block_size?) | 4-word reply buffer? | |
11 | sd_get_status | none | 32-bit status register | |
12 | sd_get_ocr | none | 32-bit register |
GetDeviceStatus
SD_GetDeviceStatus
u32 buffer
ios_ioctl( sd_fd, 0x0B, 0, 0, &buffer, 4);
buffer contains the status of the SD slot
- Bit 0: SD card is inserted.
- Bit 1: No SD card is inserted.
- Bit 2: Write protect switch is down
- Bit 16: SD is initialized
- Bit 20: This is an SDHC card
ResetDevice
SD_ResetDevice
ios_ioctl( sd_fd, 4, 0, 0, buffer, 4);
buffer contains the rca and stuff bits
Upper 16 bits: rca (relative card address)
Lower 16 bits: stuff bits
GetOCRegister
SD_GetOCRegister
ios_ioctl( sd_fd, 0xC, 0, 0, buffer, 4);
GetHCRegister
The host controller is just a standard SD host controller and you can directly read and write to its registers using the following two functions.
SD_GetHCRegister (untested iirc)
((u32*)inbuf)[0] = register_offset;
((u32*)inbuf)[3] = 1;
((u32*)inbuf)[4] = 0;
ios_ioctl( sd_fd, 2, inbuf, 0x18, outbuf, 4);
SetHCRegister
SD_SetHCRegister
((u32*)inbuf)[0] = register_offset;
((u32*)inbuf)[3] = 1;
((u32*)inbuf)[4] = value;
ios_ioctl( sd_fd, 1, inbuf, 0x18, 0, 0);
SendCMD
SD_SendCMD(cmd, cmd_type, resp_type, arg, buffer, block_count, sector_size)
((u32*)inbuf)[0]=cmd;
((u32*)inbuf)[1]=cmd_type;
((u32*)inbuf)[2]=resp_type;
((u32*)inbuf)[3]=arg;
((u32*)inbuf)[4]=block_count;
((u32*)inbuf)[5]=sector_size;
((u32*)inbuf)[6]=buffer;
((u32*)inbuf)[7]=0; // ?
((u32*)inbuf)[8]=0; // ?
ios_ioctl( sd_fd, 7, inbuf, 0x24, outbuf, 0x10);
SD Commands
SD_SendCmd(0x10, 3, 1, 0x200, 0, 0, 0) card_set_blocklen(0x200)
SD_SendCmd(0x37, 3, 1, rca&0xFFFF0000, 0, 0, 0) set data bus width
SD_SendCmd(7, 3, 2, rca&0xFFFF0000, 0, 0, 0) // select
SD_SendCmd(7, 3, 2, 0, 0, 0, 0) // deselect
IOS_Ioctl(fd, 11, 0, 0, (u32 *)&status, 4); // get status
IOS_Ioctl(fd, 4, 0, 0, (u32 *)&rca, 4) // reset and get rca
IOS_Ioctl(fd, 6, (u32 *)&clock, 4, 0, 0) // using 1 as clock seems to work
Set bus width to 4
SD_SendCmd(0x37, 3, 1, rca&0xFFFF0000, 0, 0, 0)
SD_SendCmd(6, 3, 1, 2, 0, 0, 0)
//To set the Bus Width to 4: Read the HCR register and AND it with 0x2. Then OR it 0x2 and write that result back.
Block Read
IOS_ioctlv(fd, 7, 2, 1, vectors)
// Vector Table: {InputBuffer, 0x24, &buffer, 0x200, ReplyBuffer, 0x10}
// First vector (InputBuffer) is {0x12, 3, 1, blockno * 0x200, 1, 0x200, &buffer (yes the same &buffer that's in the Vector Table), 1, 0}
// 0x12 is CMD18 READ_MULTI_BLOCK. Blockno * 0x200 is the physical address of the SD card
// The Second Vector is the buffer where SD contents are read (dumped) to. If doing a Block Write, these are the contents that get written to the SD.
// The Third Vector is a simple 0x10 Reply Buffer.
// blockno * 0x200 is the physical address of the SD card
Block Write
Works the same way as reading does. Just use 0x19 instead of 0x12 in the first vector. 0x19 is CMD25 WRITE_MULTIPLE_BLOCK
How to Read/Write
1. IOS_Open /dev/sdio/slotX (0); fd is returned from IOS_Open
2. Reset the SD
3. Select the SD
4. Set Block Length to 0x200
5. Do all the necessary IOCTL calls to set Bus Width to 4 (SD CMD 0x37, SD CMD 6, Get HCR, Set HCR)
6. Clock the SD using value of 1
7. Execute READ_MULTI_BLOCK / Execute WRITE_MULTI_BLOCK
8. IOS_Close /dev/sdio/slotX
Async device state monitoring
SD_SendCmd(0x40, 0, 0, 1, 0, 0, 0) get card insertion event (waits until event happens or request is cancelled)
SD_SendCmd(0x40, 0, 0, 2, 0, 0, 0) get card removal event (as above)
SD_SendCmd(0x41, 0, 0, ?, 0, 0, 0) cancel event request (arg is 1 or 2)
Devices
- /dev/sdio/slot0 - the front slot
- /dev/sdio/slot1 - unused second slot?
- /dev/sdio/slotw - exists in the SDK strings, but not in IOS. Possibly previously used for WiFi on the main host controller?
- /dev/sdio/WiFi - exists in IOS4 only. Connects to the WiFi host controller.