genode/repos/dde_rump/src/server/rump_cgd/block_driver.h

120 lines
2.8 KiB
C++

/*
* \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 <base/printf.h>
#include <block_session/connection.h>
#include <block/component.h>
#include <os/packet_allocator.h>
/* 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_ */