mirror of
https://github.com/fail0verflow/mini.git
synced 2024-11-30 23:24:19 +01:00
proper CSD handling, so we can detect SD card capacity
and format the card appropriately for BackupMii
This commit is contained in:
parent
aed064fa37
commit
12ac9bc4eb
1
ipc.h
1
ipc.h
@ -43,6 +43,7 @@
|
|||||||
#define IPC_SD_GETSTATE 0x0002
|
#define IPC_SD_GETSTATE 0x0002
|
||||||
#define IPC_SD_READ 0x0003
|
#define IPC_SD_READ 0x0003
|
||||||
#define IPC_SD_WRITE 0x0004
|
#define IPC_SD_WRITE 0x0004
|
||||||
|
#define IPC_SD_GETSIZE 0x0005
|
||||||
|
|
||||||
#define IPC_KEYS_GETOTP 0x0000
|
#define IPC_KEYS_GETOTP 0x0000
|
||||||
#define IPC_KEYS_GETEEP 0x0001
|
#define IPC_KEYS_GETEEP 0x0001
|
||||||
|
65
sdhc.c
65
sdhc.c
@ -833,42 +833,45 @@ static int __sd_getcid(sdhci_t *sdhci) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int __sd_getcsd(sdhci_t *sdhci) {
|
static int __sd_getcsd(sdhci_t *sdhci) {
|
||||||
u32 resp[4];
|
u8 resp[16];
|
||||||
u32 swapped[4];
|
sdhc_debug(sdhci->reg_base, "requesting CSD");
|
||||||
sdhc_debug(sdhci->reg_base, "requesting CSD noW!!");
|
int retval = __sd_cmd(sdhci, SD_CMD_SEND_CSD, SD_R2, sdhci->rca << 16, 0, NULL, (u32 *)resp, 16);
|
||||||
int retval = __sd_cmd(sdhci, SD_CMD_SEND_CSD, SD_R2, sdhci->rca << 16, 0, NULL, resp, 16);
|
|
||||||
if (retval < 0) {
|
if (retval < 0) {
|
||||||
sdhc_error(sdhci->reg_base, "failed to get CSD register (%d)", retval);
|
sdhc_error(sdhci->reg_base, "failed to get CSD register (%d)", retval);
|
||||||
__sd_reset(sdhci, 1);
|
__sd_reset(sdhci, 1);
|
||||||
return SDHC_EIO;
|
return SDHC_EIO;
|
||||||
}
|
}
|
||||||
swapped[0] = bswap32(resp[3]);
|
sdhc_error(sdhci->reg_base, "CSD = %02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x",
|
||||||
swapped[1] = bswap32(resp[2]);
|
resp[14], resp[13], resp[12], resp[11], resp[10], resp[9], resp[8],
|
||||||
swapped[2] = bswap32(resp[1]);
|
resp[7], resp[6], resp[5], resp[4], resp[3], resp[2], resp[1], resp[0]);
|
||||||
swapped[3] = bswap32(resp[0]);
|
|
||||||
|
|
||||||
memcpy(&sdhci->csd, swapped, sizeof swapped);
|
if (resp[13] == 0xe) { // sdhc
|
||||||
sdhc_error(sdhci->reg_base, "CSD = %08x%08x%08x%08x", swapped[0], swapped[1], swapped[2], swapped[3]);
|
unsigned int c_size = resp[7] << 16 | resp[6] << 8 | resp[5];
|
||||||
unsigned int card_size = 0; // in kilobytes, so as to not overflow
|
sdhc_error(sdhci->reg_base, "sdhc mode, c_size=%u, card size = %uk", c_size, (c_size + 1)* 512);
|
||||||
sdhc_error(sdhci->reg_base, "CSD: csd_structure=%x taac=%x nsac=%x tran_speed=%x",
|
sdhci->timeout = 250 * 1000000; // spec says read timeout is 100ms and write/erase timeout is 250ms
|
||||||
sdhci->csd.csd_structure, sdhci->csd.taac, sdhci->csd.nsac, sdhci->csd.tran_speed);
|
sdhci->num_sectors = (c_size + 1) * 1024; // number of 512-byte sectors
|
||||||
sdhc_error(sdhci->reg_base, "CSD: ccc=%x read_bl_len=%x read_bl_partial=%x write_blk_misalign=%x",
|
}
|
||||||
sdhci->csd.ccc, sdhci->csd.read_bl_len, sdhci->csd.read_bl_partial, sdhci->csd.write_blk_misalign);
|
else {
|
||||||
if (sdhci->csd.csd_structure) { // SDHC
|
unsigned int taac, nsac, read_bl_len, c_size, c_size_mult;
|
||||||
sdhc_error(sdhci->reg_base, "CSD: read_blk_misalign=%x dsr_imp=%x c_size_hc=%x",
|
taac = resp[13];
|
||||||
sdhci->csd.read_blk_misalign, sdhci->csd.dsr_imp, sdhci->csd.c_size_hc);
|
nsac = resp[12];
|
||||||
// card_size = (sdhci->csd.c_size_hc + 1) * 512;
|
read_bl_len = resp[9] & 0xF;
|
||||||
card_size = ((swapped[2] >> 16) | ((swapped[1] & 0x3f) << 16)) * 512;
|
|
||||||
} else {
|
c_size = (resp[8] & 3) << 10;
|
||||||
sdhc_error(sdhci->reg_base, "CSD: read_blk_misalign=%x dsr_imp=%x c_size=%x c_size_mult=%x",
|
c_size |= (resp[7] << 2);
|
||||||
sdhci->csd.read_blk_misalign, sdhci->csd.dsr_imp, sdhci->csd.c_size, sdhci->csd.c_size_mult);
|
c_size |= (resp[6] >> 6);
|
||||||
// card_size = (sdhci->csd.c_size + 1) * (4 << sdhci->csd.c_size_mult) * (1 << sdhci->csd.read_bl_len) / 1024;
|
c_size_mult = (resp[5] & 3) << 1;
|
||||||
unsigned int c_size = (swapped[1] & 3) << 10 | (swapped[2] >> 22);
|
c_size_mult |= resp[4] >> 7;
|
||||||
unsigned int c_size_mult = (swapped[2] >> 15) & 7;
|
sdhc_error(sdhci->reg_base, "taac=%u nsac=%u read_bl_len=%u c_size=%u c_size_mult=%u card size=%u bytes",
|
||||||
sdhc_error(sdhci->reg_base, "calc c_size=%x, c_size_mult=%x", c_size, c_size_mult);
|
taac, nsac, read_bl_len, c_size, c_size_mult, (c_size + 1) * (4 << c_size_mult) * (1 << read_bl_len));
|
||||||
card_size = (c_size + 1) * (4 << c_size_mult) * (1 << sdhci->csd.read_bl_len) / 1024;
|
unsigned int time_unit[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000};
|
||||||
|
unsigned int time_value[] = {1, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80}; // must div by 10
|
||||||
|
sdhci->timeout = time_unit[taac & 7] * time_value[(taac >> 3) & 0xf] / 10;
|
||||||
|
sdhc_error(sdhci->reg_base, "calculated timeout = %uns", sdhci->timeout);
|
||||||
|
sdhci->num_sectors = (c_size + 1) * (4 << c_size_mult) * (1 << read_bl_len) / 512;
|
||||||
}
|
}
|
||||||
sdhc_error(sdhci->reg_base, "card size = %uK (%uM)", card_size, card_size / 1024);
|
sdhc_error(sdhci->reg_base, "num sectors = %u", sdhci->num_sectors);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1176,6 +1179,10 @@ void sd_ipc(volatile ipc_request *req)
|
|||||||
ipc_post(req->code, req->tag, 1, retval);
|
ipc_post(req->code, req->tag, 1, retval);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case IPC_SD_GETSIZE:
|
||||||
|
ipc_post(req->code, req->tag, 1, sdhci.num_sectors);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
gecko_printf("IPC: unknown SLOW SDHC request %04x\n",
|
gecko_printf("IPC: unknown SLOW SDHC request %04x\n",
|
||||||
req->req);
|
req->req);
|
||||||
|
38
sdhc.h
38
sdhc.h
@ -33,41 +33,6 @@ typedef struct {
|
|||||||
unsigned short mdt;
|
unsigned short mdt;
|
||||||
} __attribute__((packed)) cid_str;
|
} __attribute__((packed)) cid_str;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
unsigned char dummy;
|
|
||||||
unsigned csd_structure : 2;
|
|
||||||
unsigned reserved0 : 6;
|
|
||||||
unsigned char taac;
|
|
||||||
unsigned char nsac;
|
|
||||||
unsigned char tran_speed;
|
|
||||||
unsigned ccc : 12;
|
|
||||||
unsigned read_bl_len : 4;
|
|
||||||
unsigned read_bl_partial : 1;
|
|
||||||
unsigned write_blk_misalign : 1;
|
|
||||||
unsigned read_blk_misalign : 1;
|
|
||||||
unsigned dsr_imp : 1;
|
|
||||||
union {
|
|
||||||
struct {
|
|
||||||
unsigned reserved : 2;
|
|
||||||
unsigned c_size : 12;
|
|
||||||
unsigned vdd_r_curr_min : 3;
|
|
||||||
unsigned vdd_r_curr_max : 3;
|
|
||||||
unsigned vdd_w_curr_min : 3;
|
|
||||||
unsigned vdd_w_curr_max : 3;
|
|
||||||
unsigned c_size_mult : 3;
|
|
||||||
};
|
|
||||||
struct {
|
|
||||||
unsigned reserved2 : 6;
|
|
||||||
unsigned c_size_hc : 22;
|
|
||||||
unsigned reserved3 : 1;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
unsigned erase_blk_en : 1;
|
|
||||||
unsigned sector_size : 7;
|
|
||||||
unsigned wp_grp_size : 7;
|
|
||||||
unsigned int stuff;
|
|
||||||
} __attribute__((packed)) csd_str;
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
u32 reg_base;
|
u32 reg_base;
|
||||||
@ -80,7 +45,8 @@ typedef struct
|
|||||||
u32 ocr;
|
u32 ocr;
|
||||||
|
|
||||||
cid_str cid;
|
cid_str cid;
|
||||||
csd_str csd;
|
u32 timeout;
|
||||||
|
u32 num_sectors;
|
||||||
} sdhci_t;
|
} sdhci_t;
|
||||||
|
|
||||||
int sd_init(sdhci_t *sdhci, int slot);
|
int sd_init(sdhci_t *sdhci, int slot);
|
||||||
|
Loading…
Reference in New Issue
Block a user