/* * \brief Block driver * \author Josef Söntgen * \date 2014-04-16 */ /* * Copyright (C) 2014 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 _BLOCK_DRIVER_H_ #define _BLOCK_DRIVER_H_ /* General includes */ #include #include #include #include /* local includes */ #include "cgd.h" class Driver : public Block::Driver { private: Block::Session::Operations _ops; Genode::size_t _blk_sz; Block::sector_t _blk_cnt; Cgd::Device *_cgd_device; public: Driver(Server::Entrypoint &ep) : _blk_sz(0), _blk_cnt(0), _cgd_device(0) { try { _cgd_device = Cgd::init(Genode::env()->heap(), ep); } catch (...) { PERR("could not initialize cgd device."); throw Genode::Root::Unavailable(); } _blk_cnt = _cgd_device->block_count(); _blk_sz = _cgd_device->block_size(); /* * XXX We need write access to satisfy RUMP but we have to check * the client policy in the session interface. */ _ops.set_operation(Block::Packet_descriptor::READ); _ops.set_operation(Block::Packet_descriptor::WRITE); } ~Driver() { Cgd::deinit(Genode::env()->heap(), _cgd_device); } bool _range_valid(Block::sector_t num, Genode::size_t count) { if (num + count > _blk_cnt) { PERR("requested block %llu-%llu out of range!", num, num + count); return false; } return true; } /**************************** ** Block-driver interface ** ****************************/ Genode::size_t block_size() { return _blk_sz; } Block::sector_t block_count() { return _blk_cnt; } Block::Session::Operations ops() { return _ops; } void read(Block::sector_t block_number, Genode::size_t block_count, char* buffer, Block::Packet_descriptor &packet) { if (!_ops.supported(Block::Packet_descriptor::READ)) throw Io_error(); if(!_range_valid(block_number, block_count)) throw Io_error(); _cgd_device->read(buffer, block_count * _blk_sz, block_number * _blk_sz); ack_packet(packet); } void write(Block::sector_t block_number, Genode::size_t block_count, const char * buffer, Block::Packet_descriptor &packet) { if (!_ops.supported(Block::Packet_descriptor::WRITE)) throw Io_error(); if(!_range_valid(block_number, block_count)) throw Io_error(); _cgd_device->write(buffer, block_count * _blk_sz, block_number * _blk_sz); ack_packet(packet); } void sync() { } }; #endif /* _BLOCK_DRIVER_H_ */