mirror of
https://github.com/fail0verflow/mini.git
synced 2024-11-30 23:24:19 +01:00
correctly handle CID and CSD (but the volume size calc is borked)
This commit is contained in:
parent
69102c9b0c
commit
aed064fa37
111
sdhc.c
111
sdhc.c
@ -195,6 +195,11 @@ void sd_irq(void)
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int bswap32(unsigned int input) {
|
||||
return ((input & 0x000000FF) << 24) | ((input & 0x0000FF00) << 8) |
|
||||
((input & 0x00FF0000) >> 8) | ((input & 0xFF000000) >> 24);
|
||||
}
|
||||
|
||||
u8 __sd_read8(u32 addr)
|
||||
{
|
||||
u32 mask;
|
||||
@ -641,7 +646,7 @@ static s32 __sd_cmd(sdhci_t *sdhci, u32 cmd, u32 type, u32 arg, u32 blk_cnt, voi
|
||||
__sd_dumpregs(sdhci);
|
||||
|
||||
for(i = 0; i < 4; i++)
|
||||
sdhc_debug(sdhci->reg_base, "response %d: %X", i, __sd_read32(sdhci->reg_base + SDHC_RESPONSE + 4*i));
|
||||
sdhc_debug(sdhci->reg_base, "response %d: %08X", i, __sd_read32(sdhci->reg_base + SDHC_RESPONSE + 4*i));
|
||||
if(rlen < 4 && type & SD_RSP_PRESENT)
|
||||
{
|
||||
sdhc_debug(sdhci->reg_base, "response buffer not big enough for response...");
|
||||
@ -802,11 +807,76 @@ void __sd_print_status(sdhci_t *sdhci)
|
||||
return;
|
||||
}
|
||||
|
||||
static int __sd_getcid(sdhci_t *sdhci) {
|
||||
u32 resp[4];
|
||||
u32 swapped[4];
|
||||
sdhc_debug(sdhci->reg_base, "sending ALL_SEND_CID command to get connected card");
|
||||
int retval = __sd_cmd(sdhci, SD_CMD_ALL_SEND_CID, SD_R2, 0, 0, NULL, resp, 16);
|
||||
if(retval < 0)
|
||||
{
|
||||
sdhc_error(sdhci->reg_base, "__sd_cmd returned %d, resetting controller.", retval);
|
||||
__sd_reset(sdhci, 1);
|
||||
return SDHC_EIO;
|
||||
}
|
||||
swapped[0] = bswap32(resp[3]);
|
||||
swapped[1] = bswap32(resp[2]);
|
||||
swapped[2] = bswap32(resp[1]);
|
||||
swapped[3] = bswap32(resp[0]);
|
||||
|
||||
memcpy(&sdhci->cid, swapped, sizeof swapped);
|
||||
|
||||
sdhc_error(sdhci->reg_base, "MID=%02x OID='%c%c' PNM='%c%c%c%c%c' PRV=%d.%d PSN=%08x MDT=200%d/%02d\n",
|
||||
sdhci->cid.mid, sdhci->cid.oid[0], sdhci->cid.oid[1],
|
||||
sdhci->cid.pnm[0], sdhci->cid.pnm[1], sdhci->cid.pnm[2], sdhci->cid.pnm[3], sdhci->cid.pnm[4],
|
||||
sdhci->cid.prv >> 4, sdhci->cid.prv & 0xf, sdhci->cid.psn, sdhci->cid.mdt >> 4, sdhci->cid.mdt & 0xf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __sd_getcsd(sdhci_t *sdhci) {
|
||||
u32 resp[4];
|
||||
u32 swapped[4];
|
||||
sdhc_debug(sdhci->reg_base, "requesting CSD noW!!");
|
||||
int retval = __sd_cmd(sdhci, SD_CMD_SEND_CSD, SD_R2, sdhci->rca << 16, 0, NULL, resp, 16);
|
||||
if (retval < 0) {
|
||||
sdhc_error(sdhci->reg_base, "failed to get CSD register (%d)", retval);
|
||||
__sd_reset(sdhci, 1);
|
||||
return SDHC_EIO;
|
||||
}
|
||||
swapped[0] = bswap32(resp[3]);
|
||||
swapped[1] = bswap32(resp[2]);
|
||||
swapped[2] = bswap32(resp[1]);
|
||||
swapped[3] = bswap32(resp[0]);
|
||||
|
||||
memcpy(&sdhci->csd, swapped, sizeof swapped);
|
||||
sdhc_error(sdhci->reg_base, "CSD = %08x%08x%08x%08x", swapped[0], swapped[1], swapped[2], swapped[3]);
|
||||
unsigned int card_size = 0; // in kilobytes, so as to not overflow
|
||||
sdhc_error(sdhci->reg_base, "CSD: csd_structure=%x taac=%x nsac=%x tran_speed=%x",
|
||||
sdhci->csd.csd_structure, sdhci->csd.taac, sdhci->csd.nsac, sdhci->csd.tran_speed);
|
||||
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);
|
||||
if (sdhci->csd.csd_structure) { // SDHC
|
||||
sdhc_error(sdhci->reg_base, "CSD: read_blk_misalign=%x dsr_imp=%x c_size_hc=%x",
|
||||
sdhci->csd.read_blk_misalign, sdhci->csd.dsr_imp, sdhci->csd.c_size_hc);
|
||||
// card_size = (sdhci->csd.c_size_hc + 1) * 512;
|
||||
card_size = ((swapped[2] >> 16) | ((swapped[1] & 0x3f) << 16)) * 512;
|
||||
} else {
|
||||
sdhc_error(sdhci->reg_base, "CSD: read_blk_misalign=%x dsr_imp=%x c_size=%x c_size_mult=%x",
|
||||
sdhci->csd.read_blk_misalign, sdhci->csd.dsr_imp, sdhci->csd.c_size, sdhci->csd.c_size_mult);
|
||||
// card_size = (sdhci->csd.c_size + 1) * (4 << sdhci->csd.c_size_mult) * (1 << sdhci->csd.read_bl_len) / 1024;
|
||||
unsigned int c_size = (swapped[1] & 3) << 10 | (swapped[2] >> 22);
|
||||
unsigned int c_size_mult = (swapped[2] >> 15) & 7;
|
||||
sdhc_error(sdhci->reg_base, "calc c_size=%x, c_size_mult=%x", c_size, c_size_mult);
|
||||
card_size = (c_size + 1) * (4 << c_size_mult) * (1 << sdhci->csd.read_bl_len) / 1024;
|
||||
}
|
||||
sdhc_error(sdhci->reg_base, "card size = %uK (%uM)", card_size, card_size / 1024);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_mount(sdhci_t *sdhci)
|
||||
{
|
||||
u32 caps;
|
||||
s32 retval;
|
||||
u32 resp[5];
|
||||
u32 resp[64];
|
||||
int tries;
|
||||
|
||||
__sd_dumpregs(sdhci);
|
||||
@ -904,25 +974,9 @@ int sd_mount(sdhci_t *sdhci)
|
||||
sdhci->is_sdhc = 0;
|
||||
}
|
||||
|
||||
sdhc_debug(sdhci->reg_base, "sending ALL_SEND_CID command to get connected card");
|
||||
retval = __sd_cmd(sdhci, SD_CMD_ALL_SEND_CID, SD_R3, 0, 0, NULL, resp, 16);
|
||||
if(retval < 0)
|
||||
{
|
||||
sdhc_error(sdhci->reg_base, "__sd_cmd returned %d, resetting controller.", retval);
|
||||
__sd_reset(sdhci, 1);
|
||||
return SDHC_EIO;
|
||||
}
|
||||
retval = __sd_getcid(sdhci);
|
||||
if (retval) return retval;
|
||||
|
||||
memcpy(sdhci->cid, resp, 128/8);
|
||||
|
||||
/* sdhc_error(sdhci->reg_base, "CID: %08X%08x%08x%08x, requesting RCA",
|
||||
sdhci->cid[0],
|
||||
sdhci->cid[1],
|
||||
sdhci->cid[2],
|
||||
sdhci->cid[3]); */
|
||||
sdhc_error(sdhci->reg_base, "MID=%02x OID=%02x%02x PNM='%c%c%c%c%c' PRV=%02x PSN=%02x%02x%02x%02x MDT=%d/%d [%02x]\n",
|
||||
sdhci->cid[0], sdhci->cid[1], sdhci->cid[2], sdhci->cid[3], sdhci->cid[4], sdhci->cid[5], sdhci->cid[6], sdhci->cid[7],
|
||||
sdhci->cid[8], sdhci->cid[9], sdhci->cid[10], sdhci->cid[11], sdhci->cid[12], sdhci->cid[13], sdhci->cid[14], sdhci->cid[15]);
|
||||
retval = __sd_cmd(sdhci, SD_CMD_SEND_RELATIVE_ADDR, SD_R6, 0, 0, NULL, resp, 6);
|
||||
if(retval < 0)
|
||||
{
|
||||
@ -933,21 +987,8 @@ int sd_mount(sdhci_t *sdhci)
|
||||
|
||||
sdhci->rca = (resp[0] >> 16) & 0xffff;
|
||||
sdhc_debug(sdhci->reg_base, "RCA: %04X", sdhci->rca);
|
||||
|
||||
sdhc_debug(sdhci->reg_base, "requesting CSD noW!!");
|
||||
retval = __sd_cmd(sdhci, SD_CMD_SEND_CSD, SD_R2, sdhci->rca << 16, 0, NULL, resp,
|
||||
16);
|
||||
if (retval < 0) {
|
||||
sdhc_error(sdhci->reg_base, "failed to get CSD register (%d)", retval);
|
||||
__sd_reset(sdhci, 1);
|
||||
}
|
||||
memcpy(sdhci->csd, resp, 128/8);
|
||||
sdhc_error(sdhci->reg_base, "CSD: %08X%08x%08x%08x",
|
||||
sdhci->csd[0],
|
||||
sdhci->csd[1],
|
||||
sdhci->csd[2],
|
||||
sdhci->csd[3]);
|
||||
|
||||
retval = __sd_getcsd(sdhci);
|
||||
if (retval) return retval;
|
||||
|
||||
__sd_print_status(sdhci);
|
||||
|
||||
|
61
sdhc.h
61
sdhc.h
@ -11,6 +11,63 @@
|
||||
#define SDHC_EINVAL -0x1005
|
||||
#define SDHC_EIO -0x1006
|
||||
|
||||
/*struct {
|
||||
unsigned int manfid;
|
||||
char prod_name[8];
|
||||
unsigned int serial;
|
||||
unsigned short oemid;
|
||||
unsigned short year;
|
||||
unsigned char hwrev;
|
||||
unsigned char fwrev;
|
||||
unsigned char month;
|
||||
} __attribute((packed) cid_str;
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
unsigned char dummy;
|
||||
unsigned char mid;
|
||||
char oid[2];
|
||||
char pnm[5];
|
||||
unsigned char prv;
|
||||
unsigned int psn;
|
||||
unsigned short mdt;
|
||||
} __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
|
||||
{
|
||||
u32 reg_base;
|
||||
@ -22,8 +79,8 @@ typedef struct
|
||||
u16 rca;
|
||||
u32 ocr;
|
||||
|
||||
u8 cid[16];
|
||||
u8 csd[16];
|
||||
cid_str cid;
|
||||
csd_str csd;
|
||||
} sdhci_t;
|
||||
|
||||
int sd_init(sdhci_t *sdhci, int slot);
|
||||
|
Loading…
Reference in New Issue
Block a user