mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-25 19:21:39 +00:00
os: detection of standard-capacity SD cards
This patch enhances the generic SD-card protocol implementation in sd-card.h with the ability to handle the version 1.0 of the CSD register (containing the capacity information of older SD cards).
This commit is contained in:
parent
26442f782b
commit
77cba65b7a
@ -45,14 +45,20 @@ namespace Sd_card {
|
|||||||
{
|
{
|
||||||
enum { BIT_BASE = 1*sizeof(access_t)*8 };
|
enum { BIT_BASE = 1*sizeof(access_t)*8 };
|
||||||
|
|
||||||
struct Device_size_lo : Bitfield<48 - BIT_BASE, 16> { };
|
struct V2_device_size_lo : Bitfield<48 - BIT_BASE, 16> { };
|
||||||
|
|
||||||
|
struct V1_c_size_lo : Bitfield<62 - BIT_BASE, 2> { };
|
||||||
|
struct V1_c_size_mult : Bitfield<47 - BIT_BASE, 3> { };
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Csd2 : Register<32>
|
struct Csd2 : Register<32>
|
||||||
{
|
{
|
||||||
enum { BIT_BASE = 2*sizeof(access_t)*8 };
|
enum { BIT_BASE = 2*sizeof(access_t)*8 };
|
||||||
|
|
||||||
struct Device_size_hi : Bitfield<64 - BIT_BASE, 6> { };
|
struct V2_device_size_hi : Bitfield<64 - BIT_BASE, 6> { };
|
||||||
|
|
||||||
|
struct V1_read_bl_len : Bitfield<80 - BIT_BASE, 4> { };
|
||||||
|
struct V1_c_size_hi : Bitfield<64 - BIT_BASE, 10> { };
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Csd3 : Register<32>
|
struct Csd3 : Register<32>
|
||||||
@ -61,7 +67,7 @@ namespace Sd_card {
|
|||||||
|
|
||||||
struct Version : Bitfield<126 - BIT_BASE, 2>
|
struct Version : Bitfield<126 - BIT_BASE, 2>
|
||||||
{
|
{
|
||||||
enum { HIGH_CAPACITY = 1, EXT_CSD = 3 };
|
enum { STANDARD_CAPACITY = 0, HIGH_CAPACITY = 1, EXT_CSD = 3 };
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Mmc_spec_vers : Bitfield<122 - BIT_BASE, 4> { };
|
struct Mmc_spec_vers : Bitfield<122 - BIT_BASE, 4> { };
|
||||||
@ -394,6 +400,48 @@ namespace Sd_card {
|
|||||||
return _issue_command(command.base());
|
return _issue_command(command.base());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract capacity information from CSD register
|
||||||
|
*
|
||||||
|
* \throw Detection_failed
|
||||||
|
* \return capacity in 512-byte blocks
|
||||||
|
*/
|
||||||
|
size_t _sd_card_device_size(Csd const csd)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The capacity is reported via the CSD register. There are
|
||||||
|
* two versions of this register. Standard-capacity cards
|
||||||
|
* use version 1 whereas high-capacity cards use version 2.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (Csd3::Version::get(csd.csd3) == Csd3::Version::STANDARD_CAPACITY) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculation of the capacity according to the
|
||||||
|
* "Physical Layer Simplified Specification Version 4.10",
|
||||||
|
* Section 5.3.2.
|
||||||
|
*/
|
||||||
|
size_t const read_bl_len = Csd2::V1_read_bl_len::get(csd.csd2);
|
||||||
|
size_t const c_size = (Csd2::V1_c_size_hi::get(csd.csd2) << 2)
|
||||||
|
| Csd1::V1_c_size_lo::get(csd.csd1);
|
||||||
|
size_t const c_size_mult = Csd1::V1_c_size_mult::get(csd.csd1);
|
||||||
|
size_t const mult = 1 << (c_size_mult + 2);
|
||||||
|
size_t const block_len = 1 << read_bl_len;
|
||||||
|
size_t const capacity = (c_size + 1)*mult*block_len;
|
||||||
|
|
||||||
|
return capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Csd3::Version::get(csd.csd3) == Csd3::Version::HIGH_CAPACITY)
|
||||||
|
return ((Csd2::V2_device_size_hi::get(csd.csd2) << 16)
|
||||||
|
| Csd1::V2_device_size_lo::get(csd.csd1)) + 1;
|
||||||
|
|
||||||
|
PERR("Could not detect SD-card capacity");
|
||||||
|
throw Detection_failed();
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -410,7 +458,7 @@ namespace Sd_card {
|
|||||||
|
|
||||||
Cid const cid = _read_cid();
|
Cid const cid = _read_cid();
|
||||||
PLOG("CID: 0x%08x 0x%08x 0x%08x 0x%08x",
|
PLOG("CID: 0x%08x 0x%08x 0x%08x 0x%08x",
|
||||||
cid.raw_0, cid.raw_1, cid.raw_2, cid.raw_3);
|
cid.raw_3, cid.raw_2, cid.raw_1, cid.raw_0);
|
||||||
|
|
||||||
if (!issue_command(Send_relative_addr())) {
|
if (!issue_command(Send_relative_addr())) {
|
||||||
PERR("Send_relative_addr timed out");
|
PERR("Send_relative_addr timed out");
|
||||||
@ -427,20 +475,12 @@ namespace Sd_card {
|
|||||||
|
|
||||||
Csd const csd = _read_csd();
|
Csd const csd = _read_csd();
|
||||||
|
|
||||||
if (Csd3::Version::get(csd.csd3) != Csd3::Version::HIGH_CAPACITY) {
|
|
||||||
PERR("Could not detect high-capacity card");
|
|
||||||
throw Detection_failed();
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t const device_size = ((Csd2::Device_size_hi::get(csd.csd2) << 16)
|
|
||||||
| Csd1::Device_size_lo::get(csd.csd1)) + 1;
|
|
||||||
|
|
||||||
if (!issue_command(Select_card(rca))) {
|
if (!issue_command(Select_card(rca))) {
|
||||||
PERR("Select_card failed");
|
PERR("Select_card failed");
|
||||||
throw Detection_failed();
|
throw Detection_failed();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Card_info(rca, device_size / 2);
|
return Card_info(rca, _sd_card_device_size(csd) / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
Card_info _detect_mmc()
|
Card_info _detect_mmc()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user