* Added a kludge to the test environment to be able to support two pages sized

non-contiguous areas.
* Added a test that allowed to reproduce #2595.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26917 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2008-08-10 15:32:13 +00:00
parent b74ede5b2c
commit c3a9fa2150

View File

@ -27,20 +27,28 @@ public:
TestSuiteContext();
~TestSuiteContext();
status_t Init(size_t size);
status_t Init(size_t size, bool contiguous = true);
addr_t DataBase() const { return fDataBase; }
addr_t PhysicalDataBase() const
{ return fPhysicalDataBase; }
addr_t SecondPhysicalDataBase() const
{ return fSecondPhysicalDataBase; }
bool IsContiguous() const
{ return fSecondPhysicalDataBase == 0; }
addr_t CompareBase() const { return fCompareBase; }
size_t Size() const { return fSize; }
private:
void _Uninit();
area_id fDataArea;
addr_t fDataBase;
addr_t fPhysicalDataBase;
addr_t fSecondPhysicalDataBase;
area_id fCompareArea;
addr_t fCompareBase;
size_t fSize;
@ -145,6 +153,9 @@ public:
addr_t DataBase() const { return fContext.DataBase(); }
addr_t PhysicalDataBase() const { return fContext.PhysicalDataBase(); }
addr_t SecondPhysicalDataBase() const
{ return fContext.SecondPhysicalDataBase(); }
bool IsContiguous() const { return fContext.IsContiguous(); }
addr_t CompareBase() const { return fContext.CompareBase(); }
size_t Size() const { return fContext.Size(); }
@ -218,6 +229,13 @@ TestSuiteContext::TestSuiteContext()
TestSuiteContext::~TestSuiteContext()
{
_Uninit();
}
void
TestSuiteContext::_Uninit()
{
delete_area(fDataArea);
delete_area(fCompareArea);
@ -225,19 +243,54 @@ TestSuiteContext::~TestSuiteContext()
status_t
TestSuiteContext::Init(size_t size)
TestSuiteContext::Init(size_t size, bool contiguous)
{
fDataArea = create_area("data buffer", (void**)&fDataBase,
B_ANY_KERNEL_ADDRESS, size, B_CONTIGUOUS,
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
if (fDataArea < B_OK)
return fDataArea;
if (!contiguous) {
// we can't force this, so we have to try and see
physical_entry entry;
get_memory_map((void*)fDataBase, size, &entry, 1);
if (size != B_PAGE_SIZE * 2)
return B_NOT_SUPPORTED;
dprintf("DMA Test area %p, physical %p\n", (void*)fDataBase, entry.address);
fPhysicalDataBase = (addr_t)entry.address;
while (true) {
fDataArea = create_area("data buffer", (void**)&fDataBase,
B_ANY_KERNEL_ADDRESS, size, B_FULL_LOCK,
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
if (fDataArea < B_OK)
return fDataArea;
// get memory map to see if we succeeded
physical_entry entry[2];
get_memory_map((void*)fDataBase, 2 * B_PAGE_SIZE, entry, 2);
if (entry[0].size == B_PAGE_SIZE) {
fPhysicalDataBase = (addr_t)entry[0].address;
fSecondPhysicalDataBase = (addr_t)entry[1].address;
dprintf("DMA Test area %p, physical %p, second physical %p\n",
(void*)fDataBase, entry[0].address, entry[1].address);
break;
}
// try again
delete_area(fDataArea);
}
} else {
fDataArea = create_area("data buffer", (void**)&fDataBase,
B_ANY_KERNEL_ADDRESS, size, B_CONTIGUOUS,
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
if (fDataArea < B_OK)
return fDataArea;
physical_entry entry;
get_memory_map((void*)fDataBase, B_PAGE_SIZE, &entry, 1);
fPhysicalDataBase = (addr_t)entry.address;
fSecondPhysicalDataBase = 0;
dprintf("DMA Test area %p, physical %p\n", (void*)fDataBase,
entry.address);
}
fCompareArea = create_area("compare buffer", (void**)&fCompareBase,
B_ANY_KERNEL_ADDRESS, size, B_FULL_LOCK,
@ -270,9 +323,15 @@ Test::Test(TestSuite& suite, off_t offset, size_t length, bool isWrite,
Test&
Test::AddSource(addr_t address, size_t length)
{
fSourceVecs[fSourceCount].iov_base
= (void*)(((fFlags & B_PHYSICAL_IO_REQUEST) == 0
? fSuite.DataBase() : fSuite.PhysicalDataBase()) + address);
if (fSuite.IsContiguous() || (fFlags & B_PHYSICAL_IO_REQUEST) != 0
|| address < B_PAGE_SIZE) {
fSourceVecs[fSourceCount].iov_base
= (void*)(((fFlags & B_PHYSICAL_IO_REQUEST) == 0
? fSuite.DataBase() : fSuite.PhysicalDataBase()) + address);
} else {
fSourceVecs[fSourceCount].iov_base
= (void*)(fSuite.SecondPhysicalDataBase() + address);
}
fSourceVecs[fSourceCount].iov_len = length;
fSourceCount++;
@ -310,8 +369,12 @@ Test::AddTarget(addr_t base, size_t length, bool usesBounceBuffer)
addr_t
Test::_SourceToVirtual(addr_t source)
{
if ((fFlags & B_PHYSICAL_IO_REQUEST) != 0)
if ((fFlags & B_PHYSICAL_IO_REQUEST) != 0) {
if (!fSuite.IsContiguous() && source >= B_PAGE_SIZE)
return source - fSuite.SecondPhysicalDataBase() + fSuite.DataBase();
return source - fSuite.PhysicalDataBase() + fSuite.DataBase();
}
return source;
}
@ -320,8 +383,14 @@ Test::_SourceToVirtual(addr_t source)
addr_t
Test::_SourceToCompare(addr_t source)
{
if ((fFlags & B_PHYSICAL_IO_REQUEST) != 0)
if ((fFlags & B_PHYSICAL_IO_REQUEST) != 0) {
if (!fSuite.IsContiguous() && source >= B_PAGE_SIZE) {
return source - fSuite.SecondPhysicalDataBase()
+ fSuite.CompareBase();
}
return source - fSuite.PhysicalDataBase() + fSuite.CompareBase();
}
return source - fSuite.DataBase() + fSuite.CompareBase();
}
@ -548,8 +617,12 @@ Test::Run(DMAResource& resource)
if (target.uses_bounce_buffer) {
address = (void*)(target.address
+ (addr_t)buffer->PhysicalBounceBuffer());
} else
} else if (fSuite.IsContiguous() || target.address < B_PAGE_SIZE) {
address = (void*)(target.address + fSuite.PhysicalDataBase());
} else {
address = (void*)(target.address - B_PAGE_SIZE
+ fSuite.SecondPhysicalDataBase());
}
if (address != vec.iov_base) {
_Panic("[%lu] address differs: %p, should be %p", i,
@ -958,6 +1031,33 @@ run_tests_mean_restrictions(TestSuiteContext& context)
}
static void
run_tests_non_contiguous_no_restrictions(TestSuiteContext& context)
{
const dma_restrictions restrictions = {
0x0, // low
0x0, // high
0, // alignment
0, // boundary
0, // max transfer
0, // max segment count
0, // max segment size
0 // flags
};
TestSuite suite(context, "non contiguous, no restrictions", restrictions,
512);
suite.AddTest(0, 8192, false, 0)
.AddSource(0, 8192)
.NextResult(0, false, false)
.AddTarget(0, 4096, false)
.AddTarget(4096, 4096, false);
suite.Run();
}
static void
run_test()
{
@ -975,6 +1075,14 @@ run_test()
run_tests_interesting_restrictions(context);
run_tests_mean_restrictions(context);
// physical non-contiguous
status = context.Init(2 * B_PAGE_SIZE, false);
if (status != B_OK)
return;
run_tests_non_contiguous_no_restrictions(context);
dprintf("All tests passed!\n");
}