2011-12-22 16:19:25 +01:00
|
|
|
/*
|
2012-07-09 15:00:57 +02:00
|
|
|
* \brief Block driver interface test
|
|
|
|
* \author Sebastian Sumpf
|
|
|
|
* \date 2011-08-11
|
2011-12-22 16:19:25 +01:00
|
|
|
*
|
2012-07-09 15:00:57 +02:00
|
|
|
* Test block device, read blocks add one to the data, write block back, read
|
|
|
|
* block again and compare outputs
|
2011-12-22 16:19:25 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2013-01-10 21:44:47 +01:00
|
|
|
* Copyright (C) 2011-2013 Genode Labs GmbH
|
2011-12-22 16:19:25 +01:00
|
|
|
*
|
|
|
|
* 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>
|
2012-07-09 15:00:57 +02:00
|
|
|
#include <util/string.h>
|
2011-12-22 16:19:25 +01:00
|
|
|
|
2012-07-09 15:00:57 +02:00
|
|
|
|
|
|
|
static const bool read_only = false;
|
|
|
|
|
|
|
|
class Worker : public Genode::Thread<8192>
|
2011-12-22 16:19:25 +01:00
|
|
|
{
|
|
|
|
private:
|
|
|
|
|
|
|
|
Block::Connection _blk_con;
|
2012-07-09 15:00:57 +02:00
|
|
|
Genode::size_t _blk_size;
|
2011-12-22 16:19:25 +01:00
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor
|
|
|
|
*/
|
2012-07-09 15:00:57 +02:00
|
|
|
Worker(Genode::Allocator_avl *block_alloc)
|
2011-12-22 16:19:25 +01:00
|
|
|
: _blk_con(block_alloc) { }
|
|
|
|
|
2012-07-09 15:00:57 +02:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2011-12-22 16:19:25 +01:00
|
|
|
/**
|
|
|
|
* 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;
|
2012-07-09 15:00:57 +02:00
|
|
|
_blk_con.info(&blk_cnt, &_blk_size, &ops);
|
2011-12-22 16:19:25 +01:00
|
|
|
|
|
|
|
/* 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;
|
|
|
|
}
|
|
|
|
|
2012-07-09 15:00:57 +02:00
|
|
|
printf("We have %zu blocks with a size of %zu bytes (%zu MB)\n",
|
|
|
|
blk_cnt, _blk_size, blk_cnt / (2 * 1024));
|
2011-12-22 16:19:25 +01:00
|
|
|
|
|
|
|
/* now, repeatedly invert each single block of the device */
|
2012-07-09 15:00:57 +02:00
|
|
|
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());
|
2011-12-22 16:19:25 +01:00
|
|
|
}
|
|
|
|
}
|
2012-07-09 15:00:57 +02:00
|
|
|
|
|
|
|
env()->parent()->close(_blk_con.cap());
|
|
|
|
env()->parent()->exit(0);
|
2011-12-22 16:19:25 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
int main(int argc, char **argv)
|
|
|
|
{
|
2012-07-09 15:00:57 +02:00
|
|
|
Genode::printf("--- AHCI block driver test ---\n");
|
2011-12-22 16:19:25 +01:00
|
|
|
|
|
|
|
Genode::Allocator_avl block_alloc(Genode::env()->heap());
|
2012-07-09 15:00:57 +02:00
|
|
|
Worker th(&block_alloc);
|
2011-12-22 16:19:25 +01:00
|
|
|
th.start();
|
|
|
|
Genode::sleep_forever();
|
|
|
|
return 0;
|
|
|
|
}
|