/dev/sdio

From WiiBrew
Jump to navigation Jump to search

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

Upper 16 bits:

  • 0: SD is not initialized (or busy)
  • 1: SD is initialized

Lower 16 bits:

  • 1: SD card is inserted.
  • 2: No SD card is inserted (sdio interrupt)

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