diff --git a/os/src/drivers/sd_card/omap4/bench/target.mk b/os/src/drivers/sd_card/omap4/bench/target.mk index 7bc110b91..f6c3950f9 100644 --- a/os/src/drivers/sd_card/omap4/bench/target.mk +++ b/os/src/drivers/sd_card/omap4/bench/target.mk @@ -2,4 +2,4 @@ TARGET = sd_card_bench REQUIRES = omap4 SRC_CC = main.cc LIBS = base -INC_DIR += $(PRG_DIR)/.. +INC_DIR += $(PRG_DIR)/.. $(PRG_DIR)/../.. diff --git a/os/src/drivers/sd_card/omap4/driver.h b/os/src/drivers/sd_card/omap4/driver.h index e65f07261..22fcd508c 100644 --- a/os/src/drivers/sd_card/omap4/driver.h +++ b/os/src/drivers/sd_card/omap4/driver.h @@ -121,8 +121,7 @@ class Block::Omap4_driver : public Block::Driver bool dma_enabled() { return _use_dma; } Ram_dataspace_capability alloc_dma_buffer(size_t size) { - /* unused */ - return Ram_dataspace_capability(); } + return Genode::env()->ram_session()->alloc(size, false); } }; #endif /* _DRIVER_H_ */ diff --git a/os/src/drivers/sd_card/omap4/sd_card.h b/os/src/drivers/sd_card/omap4/sd_card.h deleted file mode 100644 index 161e8cc51..000000000 --- a/os/src/drivers/sd_card/omap4/sd_card.h +++ /dev/null @@ -1,368 +0,0 @@ -/* - * \brief SD card protocol definitions - * \author Norman Feske - * \date 2012-07-06 - */ - -#ifndef _SD_CARD_H_ -#define _SD_CARD_H_ - -/* Genode includes */ -#include - -namespace Sd_card { - - using namespace Genode; - - /** - * Returned by 'Sd_send_op_cond' - */ - struct Ocr : Register<32> - { - struct Busy : Bitfield<31, 1> { }; - }; - - struct Cid { - uint32_t raw_0; - uint32_t raw_1; - uint32_t raw_2; - uint32_t raw_3; - }; - - struct Csd0 : Register<32> - { - }; - - struct Csd1 : Register<32> - { - enum { BIT_BASE = 1*sizeof(access_t)*8 }; - - struct Device_size_lo : Bitfield<48 - BIT_BASE, 16> { }; - }; - - struct Csd2 : Register<32> - { - enum { BIT_BASE = 2*sizeof(access_t)*8 }; - - struct Device_size_hi : Bitfield<64 - BIT_BASE, 6> { }; - }; - - struct Csd3 : Register<32> - { - enum { BIT_BASE = 3*sizeof(access_t)*8 }; - - struct Version : Bitfield<126 - BIT_BASE, 2> - { - enum { HIGH_CAPACITY = 1 }; - }; - }; - - struct Csd - { - Csd0::access_t csd0; - Csd1::access_t csd1; - Csd2::access_t csd2; - Csd3::access_t csd3; - }; - - struct Arg : Register<32> { }; - - enum Response { RESPONSE_NONE, - RESPONSE_136_BIT, - RESPONSE_48_BIT, - RESPONSE_48_BIT_WITH_BUSY }; - - enum Transfer { TRANSFER_NONE, TRANSFER_READ, TRANSFER_WRITE }; - - struct Command_base - { - unsigned index; /* command opcode */ - Arg::access_t arg; /* argument */ - Response rsp_type; /* response type */ - Transfer transfer; /* data transfer type */ - - Command_base(unsigned op, Response rsp_type, Transfer transfer) - : - index(op), arg(0), rsp_type(rsp_type), transfer(transfer) - { } - }; - - template - struct Command : Command_base - { - enum { INDEX = _INDEX }; - Command() : Command_base(_INDEX, RSP_TYPE, TRANSFER) { } - }; - - template - struct Prefixed_command : private Command_base - { - Prefixed_command() : Command_base(INDEX, RSP_TYPE, TRANSFER) { } - - using Command_base::arg; - - /** - * Used by ACMD overload of 'issue_command()' - */ - Command_base const &base() const { return *this; } - }; - - struct Go_idle_state : Command<0, RESPONSE_NONE> { }; - - struct All_send_cid : Command<2, RESPONSE_136_BIT> { }; - - struct Send_relative_addr : Command<3, RESPONSE_48_BIT> - { - struct Response : Sd_card::Arg - { - struct Rca : Bitfield<16, 16> { }; - }; - }; - - struct Select_card : Command<7, RESPONSE_48_BIT> - { - struct Arg : Sd_card::Arg - { - struct Rca : Bitfield<16, 16> { }; - }; - - Select_card(unsigned rca) - { - Arg::Rca::set(arg, rca); - } - }; - - struct Send_if_cond : Command<8, RESPONSE_48_BIT> - { - struct Arg : Sd_card::Arg - { - struct Check_pattern : Bitfield<0, 8> { }; - struct Supply_voltage : Bitfield<8, 4> { }; - }; - - Send_if_cond() - { - Arg::Check_pattern::set(arg, 0xaa); - Arg::Supply_voltage::set(arg, 1); - } - }; - - struct Send_csd : Command<9, RESPONSE_136_BIT> - { - struct Arg : Sd_card::Arg - { - struct Rca : Bitfield<16, 16> { }; - }; - - Send_csd(unsigned rca) - { - Arg::Rca::set(arg, rca); - } - }; - - struct Set_block_count : Command<23, RESPONSE_48_BIT> - { - Set_block_count(size_t count) - { - arg = count; - }; - }; - - struct Read_multiple_block : Command<18, RESPONSE_48_BIT, TRANSFER_READ> - { - Read_multiple_block(unsigned long addr) - { - arg = addr; - } - }; - - struct Write_multiple_block : Command<25, RESPONSE_48_BIT, TRANSFER_WRITE> - { - Write_multiple_block(unsigned long addr) - { - arg = addr; - } - }; - - struct Set_bus_width : Prefixed_command<6, RESPONSE_48_BIT> - { - struct Arg : Sd_card::Arg - { - struct Bus_width : Bitfield<0, 2> - { - enum Width { ONE_BIT = 0, FOUR_BITS = 2 }; - }; - }; - - Set_bus_width(Arg::Bus_width::Width width) - { - Arg::Bus_width::set(arg, width); - } - }; - - struct Sd_send_op_cond : Prefixed_command<41, RESPONSE_48_BIT> - { - struct Arg : Sd_card::Arg - { - /** - * Operating condition register - */ - struct Ocr : Bitfield<0, 24> { }; - - /** - * Host capacity support - */ - struct Hcs : Bitfield<30, 1> { }; - }; - - Sd_send_op_cond(unsigned ocr, bool hcs) - { - Arg::Ocr::set(arg, ocr); - Arg::Hcs::set(arg, hcs); - } - }; - - struct Acmd_prefix : Command<55, RESPONSE_48_BIT> - { - struct Arg : Sd_card::Arg - { - struct Rca : Bitfield<16, 16> { }; - }; - - Acmd_prefix(unsigned rca) - { - Arg::Rca::set(arg, rca); - } - }; - - class Card_info - { - private: - - unsigned _rca; - size_t _capacity_mb; - - public: - - Card_info(unsigned rca, size_t capacity_mb) - : _rca(rca), _capacity_mb(capacity_mb) - { } - - /** - * Return capacity in megabytes - */ - size_t capacity_mb() const { return _capacity_mb; } - - /** - * Return relative card address - */ - unsigned rca() const { return _rca; } - }; - - - /** - * SD card host controller - */ - class Host_controller - { - public: - - /** - * Exception type - */ - struct Detection_failed { }; - - protected: - - virtual bool _issue_command(Command_base const &command) = 0; - - virtual Cid _read_cid() = 0; - - virtual Csd _read_csd() = 0; - - virtual unsigned _read_rca() = 0; - - public: - - virtual Card_info card_info() const = 0; - - bool issue_command(Command_base const &command) - { - return _issue_command(command); - } - - /** - * Issue application-specific command - * - * This overload is selected if the supplied command type has - * 'Prefixed_command' as its base class. In this case, we need to - * issue a CMD55 as command prefix followed by the actual command. - * - * \param prefix_rca argument to CMD55 prefix command - */ - template - bool issue_command(Prefixed_command const &command, - unsigned prefix_rca = 0) - { - /* send CMD55 prefix */ - if (!_issue_command(Acmd_prefix(prefix_rca))) { - PERR("prefix command timed out"); - return false; - } - - /* send actual command */ - return _issue_command(command.base()); - } - - protected: - - /** - * Perform SD card detection sequence - * - * \throw Detection_failed - */ - Card_info _detect() - { - if (!issue_command(All_send_cid())) { - PWRN("All_send_cid command failed"); - throw Detection_failed(); - } - - Cid const cid = _read_cid(); - PLOG("CID: 0x%08x 0x%08x 0x%08x 0x%08x", - cid.raw_0, cid.raw_1, cid.raw_2, cid.raw_3); - - if (!issue_command(Send_relative_addr())) { - PERR("Send_relative_addr timed out"); - throw Detection_failed(); - } - - unsigned const rca = _read_rca(); - PLOG("RCA: 0x%04x", rca); - - if (!issue_command(Send_csd(rca))) { - PERR("Send_csd failed"); - throw Detection_failed(); - } - - 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))) { - PERR("Select_card failed"); - throw Detection_failed(); - } - - return Card_info(rca, device_size / 2); - } - }; -} - -#endif /* _SD_CARD_H_ */ diff --git a/os/src/drivers/sd_card/omap4/target.mk b/os/src/drivers/sd_card/omap4/target.mk index 32da61670..45dc4ab4e 100644 --- a/os/src/drivers/sd_card/omap4/target.mk +++ b/os/src/drivers/sd_card/omap4/target.mk @@ -2,4 +2,4 @@ TARGET = sd_card_drv REQUIRES = omap4 SRC_CC = main.cc LIBS = base -INC_DIR += $(PRG_DIR) +INC_DIR += $(PRG_DIR) $(PRG_DIR)/.. diff --git a/os/src/drivers/sd_card/host_driver.h b/os/src/drivers/sd_card/pl180/host_driver.h similarity index 100% rename from os/src/drivers/sd_card/host_driver.h rename to os/src/drivers/sd_card/pl180/host_driver.h diff --git a/os/src/drivers/sd_card/pl180/sd_card.h b/os/src/drivers/sd_card/pl180/sd_card.h new file mode 100644 index 000000000..837ca4215 --- /dev/null +++ b/os/src/drivers/sd_card/pl180/sd_card.h @@ -0,0 +1,140 @@ +/* + * \brief SD-card protocol + * \author Christian Helmuth + * \date 2011-05-19 + */ + +/* + * Copyright (C) 2011-2013 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _SD_CARD_H_ +#define _SD_CARD_H_ + +#include + +#include "host_driver.h" + + +class Sd_card : public Block::Driver +{ + private: + + Host_driver &_hd; + + enum { BLOCK_SIZE = 512 }; + + public: + + Sd_card(Host_driver &host_driver) : _hd(host_driver) + { + unsigned resp; + + /* CMD0: go idle state */ + _hd.request(0, 0); + + /* + * CMD8: send interface condition + * + * XXX only one hard-coded value currently. + */ + _hd.request(8, 0x1aa, &resp); + + /* + * ACMD41: card send operating condition + * + * This is an application-specific command and, therefore, consists + * of prefix command CMD55 + CMD41. + */ + _hd.request(55, 0, &resp); + _hd.request(41, 0x4000, &resp); + + /* CMD2: all send card identification (CID) */ + _hd.request(2, &resp); + + /* CMD3: send relative card address (RCA) */ + _hd.request(3, &resp); + unsigned short rca = resp >> 16; + + /* + * Now, the card is in transfer mode... + */ + + /* CMD7: select card */ + _hd.request(7, rca << 16, &resp); + } + + Host_driver &host_driver() { return _hd; } + + /**************************** + ** Block-driver interface ** + ****************************/ + + Genode::size_t block_size() { return BLOCK_SIZE; } + /* + * TODO report (and support) real capacity not just 512M + */ + Genode::size_t block_count() { return 0x20000000 / BLOCK_SIZE; } + + void read(Genode::size_t block_number, + Genode::size_t block_count, + char *out_buffer) + { + unsigned resp; + unsigned length = BLOCK_SIZE; + + for (Genode::size_t i = 0; i < block_count; ++i) { + /* + * CMD17: read single block + * + * SDSC cards use a byte address as argument while SDHC/SDSC uses a + * block address here. + */ + _hd.read_request(17, (block_number + i) * BLOCK_SIZE, + length, &resp); + _hd.read_data(length, out_buffer + (i * BLOCK_SIZE)); + } + } + + void write(Genode::size_t block_number, + Genode::size_t block_count, + char const *buffer) + { + unsigned resp; + unsigned length = BLOCK_SIZE; + + for (Genode::size_t i = 0; i < block_count; ++i) { + /* + * CMD24: write single block + * + * SDSC cards use a byte address as argument while SDHC/SDSC uses a + * block address here. + */ + _hd.write_request(24, (block_number + i) * BLOCK_SIZE, + length, &resp); + _hd.write_data(length, buffer + (i * BLOCK_SIZE)); + } + } + + /* + * This driver does not support DMA operation, currently. + */ + + void read_dma(Genode::size_t, Genode::size_t, Genode::addr_t) { + throw Io_error(); } + + void write_dma(Genode::size_t, Genode::size_t, Genode::addr_t) { + throw Io_error(); } + + bool dma_enabled() { return false; } + + Genode::Ram_dataspace_capability alloc_dma_buffer(Genode::size_t size) + { + return Genode::env()->ram_session()->alloc(size, false); + } +}; + +#endif /* _SD_CARD_H_ */ diff --git a/os/src/drivers/sd_card/pl180/target.mk b/os/src/drivers/sd_card/pl180/target.mk index c19a50696..958f87843 100644 --- a/os/src/drivers/sd_card/pl180/target.mk +++ b/os/src/drivers/sd_card/pl180/target.mk @@ -3,4 +3,4 @@ REQUIRES = pl180 SRC_CC = main.cc LIBS = base -INC_DIR += $(PRG_DIR) $(PRG_DIR)/.. +INC_DIR += $(PRG_DIR) diff --git a/os/src/drivers/sd_card/sd_card.h b/os/src/drivers/sd_card/sd_card.h index 837ca4215..161e8cc51 100644 --- a/os/src/drivers/sd_card/sd_card.h +++ b/os/src/drivers/sd_card/sd_card.h @@ -1,140 +1,368 @@ /* - * \brief SD-card protocol - * \author Christian Helmuth - * \date 2011-05-19 - */ - -/* - * Copyright (C) 2011-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. + * \brief SD card protocol definitions + * \author Norman Feske + * \date 2012-07-06 */ #ifndef _SD_CARD_H_ #define _SD_CARD_H_ -#include +/* Genode includes */ +#include -#include "host_driver.h" +namespace Sd_card { + using namespace Genode; -class Sd_card : public Block::Driver -{ - private: + /** + * Returned by 'Sd_send_op_cond' + */ + struct Ocr : Register<32> + { + struct Busy : Bitfield<31, 1> { }; + }; - Host_driver &_hd; + struct Cid { + uint32_t raw_0; + uint32_t raw_1; + uint32_t raw_2; + uint32_t raw_3; + }; - enum { BLOCK_SIZE = 512 }; + struct Csd0 : Register<32> + { + }; - public: + struct Csd1 : Register<32> + { + enum { BIT_BASE = 1*sizeof(access_t)*8 }; - Sd_card(Host_driver &host_driver) : _hd(host_driver) + struct Device_size_lo : Bitfield<48 - BIT_BASE, 16> { }; + }; + + struct Csd2 : Register<32> + { + enum { BIT_BASE = 2*sizeof(access_t)*8 }; + + struct Device_size_hi : Bitfield<64 - BIT_BASE, 6> { }; + }; + + struct Csd3 : Register<32> + { + enum { BIT_BASE = 3*sizeof(access_t)*8 }; + + struct Version : Bitfield<126 - BIT_BASE, 2> { - unsigned resp; + enum { HIGH_CAPACITY = 1 }; + }; + }; - /* CMD0: go idle state */ - _hd.request(0, 0); + struct Csd + { + Csd0::access_t csd0; + Csd1::access_t csd1; + Csd2::access_t csd2; + Csd3::access_t csd3; + }; - /* - * CMD8: send interface condition - * - * XXX only one hard-coded value currently. - */ - _hd.request(8, 0x1aa, &resp); + struct Arg : Register<32> { }; - /* - * ACMD41: card send operating condition - * - * This is an application-specific command and, therefore, consists - * of prefix command CMD55 + CMD41. - */ - _hd.request(55, 0, &resp); - _hd.request(41, 0x4000, &resp); + enum Response { RESPONSE_NONE, + RESPONSE_136_BIT, + RESPONSE_48_BIT, + RESPONSE_48_BIT_WITH_BUSY }; - /* CMD2: all send card identification (CID) */ - _hd.request(2, &resp); + enum Transfer { TRANSFER_NONE, TRANSFER_READ, TRANSFER_WRITE }; - /* CMD3: send relative card address (RCA) */ - _hd.request(3, &resp); - unsigned short rca = resp >> 16; + struct Command_base + { + unsigned index; /* command opcode */ + Arg::access_t arg; /* argument */ + Response rsp_type; /* response type */ + Transfer transfer; /* data transfer type */ - /* - * Now, the card is in transfer mode... - */ + Command_base(unsigned op, Response rsp_type, Transfer transfer) + : + index(op), arg(0), rsp_type(rsp_type), transfer(transfer) + { } + }; - /* CMD7: select card */ - _hd.request(7, rca << 16, &resp); - } + template + struct Command : Command_base + { + enum { INDEX = _INDEX }; + Command() : Command_base(_INDEX, RSP_TYPE, TRANSFER) { } + }; - Host_driver &host_driver() { return _hd; } + template + struct Prefixed_command : private Command_base + { + Prefixed_command() : Command_base(INDEX, RSP_TYPE, TRANSFER) { } - /**************************** - ** Block-driver interface ** - ****************************/ + using Command_base::arg; - Genode::size_t block_size() { return BLOCK_SIZE; } - /* - * TODO report (and support) real capacity not just 512M + /** + * Used by ACMD overload of 'issue_command()' */ - Genode::size_t block_count() { return 0x20000000 / BLOCK_SIZE; } + Command_base const &base() const { return *this; } + }; - void read(Genode::size_t block_number, - Genode::size_t block_count, - char *out_buffer) + struct Go_idle_state : Command<0, RESPONSE_NONE> { }; + + struct All_send_cid : Command<2, RESPONSE_136_BIT> { }; + + struct Send_relative_addr : Command<3, RESPONSE_48_BIT> + { + struct Response : Sd_card::Arg { - unsigned resp; - unsigned length = BLOCK_SIZE; + struct Rca : Bitfield<16, 16> { }; + }; + }; - for (Genode::size_t i = 0; i < block_count; ++i) { - /* - * CMD17: read single block - * - * SDSC cards use a byte address as argument while SDHC/SDSC uses a - * block address here. - */ - _hd.read_request(17, (block_number + i) * BLOCK_SIZE, - length, &resp); - _hd.read_data(length, out_buffer + (i * BLOCK_SIZE)); + struct Select_card : Command<7, RESPONSE_48_BIT> + { + struct Arg : Sd_card::Arg + { + struct Rca : Bitfield<16, 16> { }; + }; + + Select_card(unsigned rca) + { + Arg::Rca::set(arg, rca); + } + }; + + struct Send_if_cond : Command<8, RESPONSE_48_BIT> + { + struct Arg : Sd_card::Arg + { + struct Check_pattern : Bitfield<0, 8> { }; + struct Supply_voltage : Bitfield<8, 4> { }; + }; + + Send_if_cond() + { + Arg::Check_pattern::set(arg, 0xaa); + Arg::Supply_voltage::set(arg, 1); + } + }; + + struct Send_csd : Command<9, RESPONSE_136_BIT> + { + struct Arg : Sd_card::Arg + { + struct Rca : Bitfield<16, 16> { }; + }; + + Send_csd(unsigned rca) + { + Arg::Rca::set(arg, rca); + } + }; + + struct Set_block_count : Command<23, RESPONSE_48_BIT> + { + Set_block_count(size_t count) + { + arg = count; + }; + }; + + struct Read_multiple_block : Command<18, RESPONSE_48_BIT, TRANSFER_READ> + { + Read_multiple_block(unsigned long addr) + { + arg = addr; + } + }; + + struct Write_multiple_block : Command<25, RESPONSE_48_BIT, TRANSFER_WRITE> + { + Write_multiple_block(unsigned long addr) + { + arg = addr; + } + }; + + struct Set_bus_width : Prefixed_command<6, RESPONSE_48_BIT> + { + struct Arg : Sd_card::Arg + { + struct Bus_width : Bitfield<0, 2> + { + enum Width { ONE_BIT = 0, FOUR_BITS = 2 }; + }; + }; + + Set_bus_width(Arg::Bus_width::Width width) + { + Arg::Bus_width::set(arg, width); + } + }; + + struct Sd_send_op_cond : Prefixed_command<41, RESPONSE_48_BIT> + { + struct Arg : Sd_card::Arg + { + /** + * Operating condition register + */ + struct Ocr : Bitfield<0, 24> { }; + + /** + * Host capacity support + */ + struct Hcs : Bitfield<30, 1> { }; + }; + + Sd_send_op_cond(unsigned ocr, bool hcs) + { + Arg::Ocr::set(arg, ocr); + Arg::Hcs::set(arg, hcs); + } + }; + + struct Acmd_prefix : Command<55, RESPONSE_48_BIT> + { + struct Arg : Sd_card::Arg + { + struct Rca : Bitfield<16, 16> { }; + }; + + Acmd_prefix(unsigned rca) + { + Arg::Rca::set(arg, rca); + } + }; + + class Card_info + { + private: + + unsigned _rca; + size_t _capacity_mb; + + public: + + Card_info(unsigned rca, size_t capacity_mb) + : _rca(rca), _capacity_mb(capacity_mb) + { } + + /** + * Return capacity in megabytes + */ + size_t capacity_mb() const { return _capacity_mb; } + + /** + * Return relative card address + */ + unsigned rca() const { return _rca; } + }; + + + /** + * SD card host controller + */ + class Host_controller + { + public: + + /** + * Exception type + */ + struct Detection_failed { }; + + protected: + + virtual bool _issue_command(Command_base const &command) = 0; + + virtual Cid _read_cid() = 0; + + virtual Csd _read_csd() = 0; + + virtual unsigned _read_rca() = 0; + + public: + + virtual Card_info card_info() const = 0; + + bool issue_command(Command_base const &command) + { + return _issue_command(command); } - } - void write(Genode::size_t block_number, - Genode::size_t block_count, - char const *buffer) - { - unsigned resp; - unsigned length = BLOCK_SIZE; + /** + * Issue application-specific command + * + * This overload is selected if the supplied command type has + * 'Prefixed_command' as its base class. In this case, we need to + * issue a CMD55 as command prefix followed by the actual command. + * + * \param prefix_rca argument to CMD55 prefix command + */ + template + bool issue_command(Prefixed_command const &command, + unsigned prefix_rca = 0) + { + /* send CMD55 prefix */ + if (!_issue_command(Acmd_prefix(prefix_rca))) { + PERR("prefix command timed out"); + return false; + } - for (Genode::size_t i = 0; i < block_count; ++i) { - /* - * CMD24: write single block - * - * SDSC cards use a byte address as argument while SDHC/SDSC uses a - * block address here. - */ - _hd.write_request(24, (block_number + i) * BLOCK_SIZE, - length, &resp); - _hd.write_data(length, buffer + (i * BLOCK_SIZE)); + /* send actual command */ + return _issue_command(command.base()); } - } - /* - * This driver does not support DMA operation, currently. - */ + protected: - void read_dma(Genode::size_t, Genode::size_t, Genode::addr_t) { - throw Io_error(); } + /** + * Perform SD card detection sequence + * + * \throw Detection_failed + */ + Card_info _detect() + { + if (!issue_command(All_send_cid())) { + PWRN("All_send_cid command failed"); + throw Detection_failed(); + } - void write_dma(Genode::size_t, Genode::size_t, Genode::addr_t) { - throw Io_error(); } + Cid const cid = _read_cid(); + PLOG("CID: 0x%08x 0x%08x 0x%08x 0x%08x", + cid.raw_0, cid.raw_1, cid.raw_2, cid.raw_3); - bool dma_enabled() { return false; } + if (!issue_command(Send_relative_addr())) { + PERR("Send_relative_addr timed out"); + throw Detection_failed(); + } - Genode::Ram_dataspace_capability alloc_dma_buffer(Genode::size_t size) - { - return Genode::env()->ram_session()->alloc(size, false); - } -}; + unsigned const rca = _read_rca(); + PLOG("RCA: 0x%04x", rca); + + if (!issue_command(Send_csd(rca))) { + PERR("Send_csd failed"); + throw Detection_failed(); + } + + 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))) { + PERR("Select_card failed"); + throw Detection_failed(); + } + + return Card_info(rca, device_size / 2); + } + }; +} #endif /* _SD_CARD_H_ */