genode/os/src/test/block/main.cc
2013-10-22 08:00:07 +02:00

184 lines
4.8 KiB
C++

/*
* \brief Block driver interface test
* \author Sebastian Sumpf
* \date 2011-08-11
*
* Test block device, read blocks add one to the data, write block back, read
* block again and compare outputs
*/
/*
* 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.
*/
#include <base/allocator_avl.h>
#include <base/printf.h>
#include <base/sleep.h>
#include <base/thread.h>
#include <block_session/connection.h>
#include <util/string.h>
static const bool read_only = false;
class Worker : public Genode::Thread<8192>
{
private:
Block::Connection _blk_con;
Genode::size_t _blk_size;
public:
/**
* Constructor
*/
Worker(Genode::Allocator_avl *block_alloc)
: Thread("worker"), _blk_con(block_alloc) { }
void dump(Block::Packet_descriptor &p1, Block::Packet_descriptor &p2)
{
Block::Session::Tx::Source *source = _blk_con.tx();
unsigned *d1 = (unsigned *)source->packet_content(p1);
unsigned *d2 = (unsigned *)source->packet_content(p2);
for (int i = 0; i < 128; i += 8) {
Genode::printf("1 0x%02x: %08x %08x %08x %08x %08x %08x %08x %08x\n", i,
d1[i], d1[i+1], d1[i+2], d1[i+3], d1[i+4], d1[i+5], d1[i+6], d1[i+7]);
Genode::printf("2 0x%02x: %08x %08x %08x %08x %08x %08x %08x %08x\n\n", i,
d2[i], d2[i+1], d2[i+2], d2[i+3], d2[i+4], d2[i+5], d2[i+6], d2[i+7]);
}
}
void compare(Genode::size_t block, Block::Packet_descriptor &p1, Block::Packet_descriptor &p2)
{
using namespace Genode;
Block::Session::Tx::Source *source = _blk_con.tx();
char *d1 = source->packet_content(p1);
char *d2 = source->packet_content(p2);
bool equal = true;
for (size_t i = 0; i < _blk_size / sizeof(unsigned); i++)
if (d1[i] != d2[i]) {
equal = false;
if (!read_only)
PERR("%zu: %x != %x", i, d1[i], d2[i]);
}
printf("Comparing block %010zu: ", block);
if (equal)
printf("success\n");
else {
printf("failed\n");
dump(p1, p2);
}
}
void modify(Block::Packet_descriptor &src, Block::Packet_descriptor &dst, int val)
{
Block::Session::Tx::Source *source = _blk_con.tx();
for (unsigned j = 0; j < _blk_size; j++)
source->packet_content(dst)[j] = source->packet_content(src)[j] + val;
}
void submit(Block::Packet_descriptor &src,
Block::Packet_descriptor &dst,
int val, Genode::size_t block, bool cmp)
{
Block::Session::Tx::Source *source = _blk_con.tx();
source->submit_packet(src);
src = source->get_acked_packet();
/* check for success of operation */
if (!src.succeeded()) {
PWRN("Could not read block %zu", block);
return;
}
if (cmp)
compare(block, src, dst);
modify(src, dst, val);
if (read_only)
return;
source->submit_packet(dst);
dst = source->get_acked_packet();
/* check for success of operation */
if (!dst.succeeded())
PWRN("Could not write block %zu", block);
}
/**
* Thread's entry function.
*/
void entry()
{
using namespace Genode;
Block::Session::Tx::Source *source = _blk_con.tx();
size_t blk_cnt = 0;
Block::Session::Operations ops;
_blk_con.info(&blk_cnt, &_blk_size, &ops);
/* check for read- and write-capability */
if (!ops.supported(Block::Packet_descriptor::READ)) {
PERR("Block device not readable!");
return;
}
if (!ops.supported(Block::Packet_descriptor::WRITE)) {
PERR("Block device not writeable!");
return;
}
printf("We have %zu blocks with a size of %zu bytes (%zu MB)\n",
blk_cnt, _blk_size, blk_cnt / (2 * 1024));
/* now, repeatedly invert each single block of the device */
size_t step = blk_cnt / 32;
for (size_t i = 0; i < blk_cnt; i += step) {
try {
/* allocate packet-descriptor for reading */
Block::Packet_descriptor p(source->alloc_packet(_blk_size),
Block::Packet_descriptor::READ, i);
/* allocate a packet-descriptor for writing */
Block::Packet_descriptor q(source->alloc_packet(_blk_size),
Block::Packet_descriptor::WRITE, i);
submit(p, q, 1, i, false);
submit(p, q, -1, i, true);
/* release packets */
source->release_packet(q);
source->release_packet(p);
} catch (Block::Session::Tx::Source::Packet_alloc_failed) {
PWRN("Mmh, strange we run out of packets");
source->release_packet(source->get_acked_packet());
}
}
env()->parent()->close(_blk_con.cap());
env()->parent()->exit(0);
}
};
int main(int argc, char **argv)
{
Genode::printf("--- AHCI block driver test ---\n");
Genode::Allocator_avl block_alloc(Genode::env()->heap());
Worker th(&block_alloc);
th.start();
Genode::sleep_forever();
return 0;
}