#ifndef _DRV_OMAP35X_SDMMC_HH_ #define _DRV_OMAP35X_SDMMC_HH_ #include #include "interfaces.hh" #include "exceptions.hh" #include "mmio.hh" #include "util.hh" #include "scheduler.hh" class OMAP35x_SDMMC : public IBlockDevice { public: OMAP35x_SDMMC(uintptr_t base, unsigned irq, unsigned drq_rx, unsigned drq_tx); ~OMAP35x_SDMMC(); // Get the (logical) block size of the device virtual unsigned getBlockSize() const; // Write getBlockSize()*'count' bytes of data from 'data' to the device starting at block 'pos' /* Throw an ex::error on error, containing the errno describing the error. The contents of the block device from 'pos' to 'pos'+'count' are undefined after an exception */ virtual void write(unsigned pos, char const* data, unsigned count); // Read getBlockSize()*'count' bytes of data from the device starting at block 'pos' to 'data' /* Throw an ex::error on error, containing the errno describing the error. The contents of 'data' are undefined after an exception */ virtual void read(unsigned pos, char *data, unsigned count); private: void command(unsigned cmd, uint32_t arg); uint32_t command_r1(unsigned cmd, uint32_t arg); uint32_t command_r1b(unsigned cmd, uint32_t arg); std::array command_r2(unsigned cmd, uint32_t arg); void int_handler(); void test_data(unsigned block); void acmd(); void cmd_reset(); void dat_reset(); void changeClock(unsigned cdiv); enum class CardType { sdxc, sdhc, sdv2, sdv1, mmc }; char const* cardTypeToString() const; MMIO_alloc base_; unsigned irq_, drq_rx_, drq_tx_; CardType cardType_; unsigned blockSize_, sectorSize_, cardBlocks_; unsigned rca_; unsigned readTimeout_, writeTimeout_; Scheduler::Semaphore intSem_; uint32_t intStat_; uint32_t volatile& r_sysconfig() { return _reg32(base_.get_virt(), 0x10); } uint32_t volatile& r_sysstatus() { return _reg32(base_.get_virt(), 0x14); } uint32_t volatile& r_csre() { return _reg32(base_.get_virt(), 0x24); } uint32_t volatile& r_systest() { return _reg32(base_.get_virt(), 0x28); } uint32_t volatile& r_con() { return _reg32(base_.get_virt(), 0x2c); } uint32_t volatile& r_pwcnt() { return _reg32(base_.get_virt(), 0x30); } uint32_t volatile& r_blk() { return _reg32(base_.get_virt(), 0x104); } uint32_t volatile& r_arg() { return _reg32(base_.get_virt(), 0x108); } uint32_t volatile& r_cmd() { return _reg32(base_.get_virt(), 0x10c); } uint32_t volatile& r_rsp10() { return _reg32(base_.get_virt(), 0x110); } uint32_t volatile& r_rsp32() { return _reg32(base_.get_virt(), 0x114); } uint32_t volatile& r_rsp54() { return _reg32(base_.get_virt(), 0x118); } uint32_t volatile& r_rsp76() { return _reg32(base_.get_virt(), 0x11c); } uint32_t volatile& r_data() { return _reg32(base_.get_virt(), 0x120); } uint32_t volatile& r_pstate() { return _reg32(base_.get_virt(), 0x124); } uint32_t volatile& r_hctl() { return _reg32(base_.get_virt(), 0x128); } uint32_t volatile& r_sysctl() { return _reg32(base_.get_virt(), 0x12c); } uint32_t volatile& r_stat() { return _reg32(base_.get_virt(), 0x130); } uint32_t volatile& r_ie() { return _reg32(base_.get_virt(), 0x134); } uint32_t volatile& r_ise() { return _reg32(base_.get_virt(), 0x138); } uint32_t volatile& r_ac12() { return _reg32(base_.get_virt(), 0x13c); } uint32_t volatile& r_capa() { return _reg32(base_.get_virt(), 0x140); } uint32_t volatile& r_cur_capa() { return _reg32(base_.get_virt(), 0x148); } uint32_t volatile& r_rev() { return _reg32(base_.get_virt(), 0x1fc); } }; #endif