/* * \brief Block session interface. * \author Stefan Kalkowski * \date 2010-07-06 * * A block session corresponds to a block device, that can be used to read * or store data. Payload is communicated over the packet-stream interface * set up between 'Session_client' and 'Session_server'. * * Even though the functions 'tx' and 'tx_channel' are specific for the client * side of the block session interface, they are part of the abstract 'Session' * class to enable the client-side use of the block interface via a pointer to * the abstract 'Session' class. This way, we can transparently co-locate the * packet-stream server with the client in same program. */ /* * Copyright (C) 2010-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 _INCLUDE__BLOCK_SESSION__BLOCK_SESSION_H_ #define _INCLUDE__BLOCK_SESSION__BLOCK_SESSION_H_ #include #include #include namespace Block { /** * Sector type for block session */ typedef Genode::uint64_t sector_t; /** * Represents an operation request with respect to a block, * the data associated with the 'Packet_descriptor' is either * the data read from or written to the block indicated by * its number. */ class Packet_descriptor : public ::Packet_descriptor { public: enum Opcode { READ, WRITE, END }; enum Alignment { PACKET_ALIGNMENT = 11 }; private: Opcode _op; /* requested operation */ sector_t _block_number; /* requested block number */ Genode::size_t _block_count; /* number of blocks to transfer */ unsigned _success :1; /* indicates success of operation */ public: /** * Constructor */ Packet_descriptor(Genode::off_t offset=0, Genode::size_t size=0) : ::Packet_descriptor(offset, size), _op(READ), _block_number(0), _block_count(0), _success(false) { } /** * Constructor */ Packet_descriptor(Packet_descriptor p, Opcode op, sector_t blk_nr, Genode::size_t blk_count = 1) : ::Packet_descriptor(p.offset(), p.size()), _op(op), _block_number(blk_nr), _block_count(blk_count), _success(false) { } Opcode operation() const { return _op; } sector_t block_number() const { return _block_number; } Genode::size_t block_count() const { return _block_count; } bool succeeded() const { return _success; } void succeeded(bool b) { _success = b ? 1 : 0; } }; struct Session : public Genode::Session { enum { TX_QUEUE_SIZE = 256 }; /** * This class represents supported operations on a block device */ class Operations { private: unsigned _ops :Packet_descriptor::END; /* bitfield of ops */ public: Operations() : _ops(0) { } bool supported(Packet_descriptor::Opcode op) { return (_ops & (1 << op)); } void set_operation(Packet_descriptor::Opcode op) { _ops |= (1 << op); } }; typedef Packet_stream_policy Tx_policy; typedef Packet_stream_tx::Channel Tx; static const char *service_name() { return "Block"; } virtual ~Session() { } /** * Request information about the metrics of the block device * * \param blk_count will contain total number of blocks * \param blk_size will contain total size in bytes * \param ops supported operations */ virtual void info(sector_t *blk_count, Genode::size_t *blk_size, Operations *ops) = 0; /** * Synchronize with block device, like ensuring data to be written */ virtual void sync() = 0; /** * Request packet-transmission channel */ virtual Tx *tx_channel() { return 0; } /** * Request client-side packet-stream interface of tx channel */ virtual Tx::Source *tx() { return 0; } /******************* ** RPC interface ** *******************/ GENODE_RPC(Rpc_info, void, info, Block::sector_t *, Genode::size_t *, Operations *); GENODE_RPC(Rpc_tx_cap, Genode::Capability, _tx_cap); GENODE_RPC(Rpc_sync, void, sync); GENODE_RPC_INTERFACE(Rpc_info, Rpc_tx_cap, Rpc_sync); }; } #endif /* _INCLUDE__BLOCK_SESSION__BLOCK_SESSION_H_ */