dma_resource_test.cpp revision c3a9fa21
145a206a7SAxel Dörfler/*
245a206a7SAxel Dörfler * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
345a206a7SAxel Dörfler * Copyright 2008, Axel D��rfler, axeld@pinc-software.de.
445a206a7SAxel Dörfler * Distributed under the terms of the MIT License.
545a206a7SAxel Dörfler */
645a206a7SAxel Dörfler
745a206a7SAxel Dörfler#include <stdio.h>
845a206a7SAxel Dörfler#include <string.h>
945a206a7SAxel Dörfler
1045a206a7SAxel Dörfler#include <device_manager.h>
1145a206a7SAxel Dörfler
128faff60cSAxel Dörfler#include <vm.h>
138faff60cSAxel Dörfler
1445a206a7SAxel Dörfler#include "dma_resources.h"
1545a206a7SAxel Dörfler#include "io_requests.h"
1633f9067bSAxel Dörfler#include "IOScheduler.h"
1745a206a7SAxel Dörfler
1845a206a7SAxel Dörfler
1933f9067bSAxel Dörfler#define DMA_TEST_BLOCK_SIZE		512
2033f9067bSAxel Dörfler#define DMA_TEST_BUFFER_COUNT	10
2145a206a7SAxel Dörfler
2245a206a7SAxel Dörfler
238faff60cSAxel Dörflerclass TestSuite;
2445a206a7SAxel Dörfler
258faff60cSAxel Dörflerclass TestSuiteContext {
268faff60cSAxel Dörflerpublic:
278faff60cSAxel Dörfler							TestSuiteContext();
288faff60cSAxel Dörfler							~TestSuiteContext();
298faff60cSAxel Dörfler
30c3a9fa21SAxel Dörfler			status_t		Init(size_t size, bool contiguous = true);
3145a206a7SAxel Dörfler
328faff60cSAxel Dörfler			addr_t			DataBase() const { return fDataBase; }
338faff60cSAxel Dörfler			addr_t			PhysicalDataBase() const
348faff60cSAxel Dörfler								{ return fPhysicalDataBase; }
35c3a9fa21SAxel Dörfler			addr_t			SecondPhysicalDataBase() const
36c3a9fa21SAxel Dörfler								{ return fSecondPhysicalDataBase; }
37c3a9fa21SAxel Dörfler
38c3a9fa21SAxel Dörfler			bool			IsContiguous() const
39c3a9fa21SAxel Dörfler								{ return fSecondPhysicalDataBase == 0; }
408faff60cSAxel Dörfler
418faff60cSAxel Dörfler			addr_t			CompareBase() const { return fCompareBase; }
428faff60cSAxel Dörfler
438faff60cSAxel Dörfler			size_t			Size() const { return fSize; }
448faff60cSAxel Dörfler
458faff60cSAxel Dörflerprivate:
46c3a9fa21SAxel Dörfler			void			_Uninit();
47c3a9fa21SAxel Dörfler
488faff60cSAxel Dörfler			area_id			fDataArea;
498faff60cSAxel Dörfler			addr_t			fDataBase;
508faff60cSAxel Dörfler			addr_t			fPhysicalDataBase;
51c3a9fa21SAxel Dörfler			addr_t			fSecondPhysicalDataBase;
528faff60cSAxel Dörfler			area_id			fCompareArea;
538faff60cSAxel Dörfler			addr_t			fCompareBase;
548faff60cSAxel Dörfler			size_t			fSize;
558faff60cSAxel Dörfler};
5645a206a7SAxel Dörfler
5745a206a7SAxel Dörflerclass Test : public DoublyLinkedListLinkImpl<Test> {
5845a206a7SAxel Dörflerpublic:
598faff60cSAxel Dörfler							Test(TestSuite& suite, off_t offset, size_t length,
608faff60cSAxel Dörfler								bool isWrite, uint32 flags);
6145a206a7SAxel Dörfler
6245a206a7SAxel Dörfler			Test&			AddSource(addr_t base, size_t length);
6345a206a7SAxel Dörfler			Test&			NextResult(off_t offset, bool partialBegin,
6445a206a7SAxel Dörfler								bool partialEnd);
6545a206a7SAxel Dörfler			Test&			AddTarget(addr_t base, size_t length,
6645a206a7SAxel Dörfler								bool usesBounceBuffer);
6745a206a7SAxel Dörfler
6845a206a7SAxel Dörfler			void			Run(DMAResource& resource);
6945a206a7SAxel Dörfler
7045a206a7SAxel Dörflerprivate:
718faff60cSAxel Dörfler			addr_t			_SourceToVirtual(addr_t source);
728faff60cSAxel Dörfler			addr_t			_SourceToCompare(addr_t source);
738faff60cSAxel Dörfler			void			_Prepare();
748faff60cSAxel Dörfler			void			_CheckCompare();
758faff60cSAxel Dörfler			void			_CheckWrite();
768faff60cSAxel Dörfler			void			_CheckResults();
778faff60cSAxel Dörfler			status_t		_DoIO(IOOperation& operation);
7845a206a7SAxel Dörfler			void			_Panic(const char* message,...);
7945a206a7SAxel Dörfler
808faff60cSAxel Dörfler			TestSuite&		fSuite;
8145a206a7SAxel Dörfler			off_t			fOffset;
8245a206a7SAxel Dörfler			size_t			fLength;
8345a206a7SAxel Dörfler			bool			fIsWrite;
8445a206a7SAxel Dörfler			uint32			fFlags;
8545a206a7SAxel Dörfler			iovec			fSourceVecs[32];
8645a206a7SAxel Dörfler			uint32			fSourceCount;
8745a206a7SAxel Dörfler
8845a206a7SAxel Dörfler			struct target_t {
8945a206a7SAxel Dörfler				addr_t		address;
9045a206a7SAxel Dörfler				size_t		length;
9145a206a7SAxel Dörfler				bool		uses_bounce_buffer;
9245a206a7SAxel Dörfler			};
9345a206a7SAxel Dörfler			struct result_t {
9445a206a7SAxel Dörfler				off_t		offset;
9545a206a7SAxel Dörfler				target_t	targets[32];
9645a206a7SAxel Dörfler				uint32		count;
9745a206a7SAxel Dörfler				bool		partial_begin;
9845a206a7SAxel Dörfler				bool		partial_end;
9945a206a7SAxel Dörfler			};
10045a206a7SAxel Dörfler			result_t		fResults[32];
10145a206a7SAxel Dörfler			uint32			fResultCount;
10245a206a7SAxel Dörfler};
10345a206a7SAxel Dörfler
10445a206a7SAxel Dörflertypedef DoublyLinkedList<Test> TestList;
10545a206a7SAxel Dörfler
10645a206a7SAxel Dörfler
10745a206a7SAxel Dörflerclass TestSuite {
10845a206a7SAxel Dörflerpublic:
1098faff60cSAxel Dörfler	TestSuite(TestSuiteContext& context, const char* name,
1108faff60cSAxel Dörfler			const dma_restrictions& restrictions, size_t blockSize)
11145a206a7SAxel Dörfler		:
1128faff60cSAxel Dörfler		fContext(context)
11345a206a7SAxel Dörfler	{
11445a206a7SAxel Dörfler		dprintf("----- Run \"%s\" tests ---------------------------\n", name);
11545a206a7SAxel Dörfler		dprintf("  DMA restrictions: address %#lx - %#lx, align %lu, boundary "
11645a206a7SAxel Dörfler			"%lu,\n    max transfer %lu, max segs %lu, max seg size %lu, "
11745a206a7SAxel Dörfler			"flags %lx\n\n", restrictions.low_address,
11845a206a7SAxel Dörfler			restrictions.high_address, restrictions.alignment,
11945a206a7SAxel Dörfler			restrictions.boundary, restrictions.max_transfer_size,
12045a206a7SAxel Dörfler			restrictions.max_segment_count, restrictions.max_segment_size,
12145a206a7SAxel Dörfler			restrictions.flags);
12245a206a7SAxel Dörfler
12345a206a7SAxel Dörfler		status_t status = fDMAResource.Init(restrictions, blockSize, 10);
12445a206a7SAxel Dörfler		if (status != B_OK)
12545a206a7SAxel Dörfler			panic("initializing DMA resource failed: %s\n", strerror(status));
12645a206a7SAxel Dörfler	}
12745a206a7SAxel Dörfler
12845a206a7SAxel Dörfler	~TestSuite()
12945a206a7SAxel Dörfler	{
13045a206a7SAxel Dörfler		while (Test* test = fTests.RemoveHead()) {
13145a206a7SAxel Dörfler			delete test;
13245a206a7SAxel Dörfler		}
13345a206a7SAxel Dörfler	}
13445a206a7SAxel Dörfler
13545a206a7SAxel Dörfler	Test& AddTest(off_t offset, size_t length, bool isWrite, uint32 flags)
13645a206a7SAxel Dörfler	{
1378faff60cSAxel Dörfler		Test* test = new(std::nothrow) Test(*this, offset, length, isWrite,
1388faff60cSAxel Dörfler			flags);
13945a206a7SAxel Dörfler		fTests.Add(test);
14045a206a7SAxel Dörfler
14145a206a7SAxel Dörfler		return *test;
14245a206a7SAxel Dörfler	}
14345a206a7SAxel Dörfler
14445a206a7SAxel Dörfler	void Run()
14545a206a7SAxel Dörfler	{
14645a206a7SAxel Dörfler		TestList::Iterator iterator = fTests.GetIterator();
14745a206a7SAxel Dörfler		uint32 count = 1;
14845a206a7SAxel Dörfler		while (Test* test = iterator.Next()) {
14945a206a7SAxel Dörfler			dprintf("test %lu...\n", count++);
15045a206a7SAxel Dörfler			test->Run(fDMAResource);
15145a206a7SAxel Dörfler		}
15245a206a7SAxel Dörfler	}
15345a206a7SAxel Dörfler
1548faff60cSAxel Dörfler	addr_t DataBase() const { return fContext.DataBase(); }
1558faff60cSAxel Dörfler	addr_t PhysicalDataBase() const { return fContext.PhysicalDataBase(); }
156c3a9fa21SAxel Dörfler	addr_t SecondPhysicalDataBase() const
157c3a9fa21SAxel Dörfler		{ return fContext.SecondPhysicalDataBase(); }
158c3a9fa21SAxel Dörfler	bool IsContiguous() const { return fContext.IsContiguous(); }
1598faff60cSAxel Dörfler	addr_t CompareBase() const { return fContext.CompareBase(); }
1608faff60cSAxel Dörfler	size_t Size() const { return fContext.Size(); }
1618faff60cSAxel Dörfler
16245a206a7SAxel Dörflerprivate:
1638faff60cSAxel Dörfler	TestSuiteContext& fContext;
16445a206a7SAxel Dörfler	DMAResource		fDMAResource;
16545a206a7SAxel Dörfler	uint8*			fBase;
16645a206a7SAxel Dörfler	uint8*			fPhysicalBase;
1678faff60cSAxel Dörfler	size_t			fSize;
16845a206a7SAxel Dörfler	TestList		fTests;
16945a206a7SAxel Dörfler};
17045a206a7SAxel Dörfler
17145a206a7SAxel Dörfler
1728faff60cSAxel Dörflerstruct device_manager_info* sDeviceManager;
1738faff60cSAxel Dörfler
1748faff60cSAxel Dörflerstatic area_id sArea;
1758faff60cSAxel Dörflerstatic size_t sAreaSize;
1768faff60cSAxel Dörflerstatic void* sAreaAddress;
1778faff60cSAxel Dörflerstatic DMAResource* sDMAResource;
17833f9067bSAxel Dörflerstatic IOScheduler* sIOScheduler;
17933f9067bSAxel Dörfler
18033f9067bSAxel Dörfler
18133f9067bSAxel Dörflerstatus_t
18233f9067bSAxel Dörflerdo_io(void* data, IOOperation* operation)
18333f9067bSAxel Dörfler{
18433f9067bSAxel Dörfler	uint8* disk = (uint8*)sAreaAddress;
18533f9067bSAxel Dörfler	off_t offset = operation->Offset();
18633f9067bSAxel Dörfler
18733f9067bSAxel Dörfler	for (uint32 i = 0; i < operation->VecCount(); i++) {
18833f9067bSAxel Dörfler		const iovec& vec = operation->Vecs()[i];
18933f9067bSAxel Dörfler		addr_t base = (addr_t)vec.iov_base;
19033f9067bSAxel Dörfler		size_t length = vec.iov_len;
19104b04600SIngo Weinhold		size_t pageOffset = base % B_PAGE_SIZE;
19233f9067bSAxel Dörfler
19333f9067bSAxel Dörfler		while (length > 0) {
19433f9067bSAxel Dörfler			size_t toCopy = min_c(length, B_PAGE_SIZE - pageOffset);
19533f9067bSAxel Dörfler
19633f9067bSAxel Dörfler			uint8* virtualAddress;
19733f9067bSAxel Dörfler			vm_get_physical_page(base - pageOffset, (addr_t*)&virtualAddress,
19833f9067bSAxel Dörfler				PHYSICAL_PAGE_NO_WAIT);
19933f9067bSAxel Dörfler
20033f9067bSAxel Dörfler			if (operation->IsWrite())
20133f9067bSAxel Dörfler				memcpy(disk + offset, virtualAddress + pageOffset, toCopy);
20233f9067bSAxel Dörfler			else
20333f9067bSAxel Dörfler				memcpy(virtualAddress + pageOffset, disk + offset, toCopy);
20433f9067bSAxel Dörfler
20591ccfa19SIngo Weinhold			vm_put_physical_page((addr_t)virtualAddress);
20691ccfa19SIngo Weinhold
20733f9067bSAxel Dörfler			length -= toCopy;
20833f9067bSAxel Dörfler			offset += toCopy;
20933f9067bSAxel Dörfler			pageOffset = 0;
21033f9067bSAxel Dörfler		}
21133f9067bSAxel Dörfler	}
21233f9067bSAxel Dörfler
21333f9067bSAxel Dörfler	if (sIOScheduler != NULL)
2147f12cc54SIngo Weinhold		sIOScheduler->OperationCompleted(operation, B_OK, operation->Length());
21533f9067bSAxel Dörfler	return B_OK;
21633f9067bSAxel Dörfler}
21733f9067bSAxel Dörfler
21833f9067bSAxel Dörfler
21933f9067bSAxel Dörfler//	#pragma mark -
2208faff60cSAxel Dörfler
2218faff60cSAxel Dörfler
2228faff60cSAxel DörflerTestSuiteContext::TestSuiteContext()
22345a206a7SAxel Dörfler	:
2248faff60cSAxel Dörfler	fDataArea(-1),
2258faff60cSAxel Dörfler	fCompareArea(-1),
2268faff60cSAxel Dörfler	fSize(0)
2278faff60cSAxel Dörfler{
2288faff60cSAxel Dörfler}
2298faff60cSAxel Dörfler
2308faff60cSAxel Dörfler
2318faff60cSAxel DörflerTestSuiteContext::~TestSuiteContext()
232c3a9fa21SAxel Dörfler{
233c3a9fa21SAxel Dörfler	_Uninit();
234c3a9fa21SAxel Dörfler}
235c3a9fa21SAxel Dörfler
236c3a9fa21SAxel Dörfler
237c3a9fa21SAxel Dörflervoid
238c3a9fa21SAxel DörflerTestSuiteContext::_Uninit()
2398faff60cSAxel Dörfler{
2408faff60cSAxel Dörfler	delete_area(fDataArea);
2418faff60cSAxel Dörfler	delete_area(fCompareArea);
2428faff60cSAxel Dörfler}
2438faff60cSAxel Dörfler
2448faff60cSAxel Dörfler
2458faff60cSAxel Dörflerstatus_t
246c3a9fa21SAxel DörflerTestSuiteContext::Init(size_t size, bool contiguous)
2478faff60cSAxel Dörfler{
248c3a9fa21SAxel Dörfler	if (!contiguous) {
249c3a9fa21SAxel Dörfler		// we can't force this, so we have to try and see
250c3a9fa21SAxel Dörfler
251c3a9fa21SAxel Dörfler		if (size != B_PAGE_SIZE * 2)
252c3a9fa21SAxel Dörfler			return B_NOT_SUPPORTED;
253c3a9fa21SAxel Dörfler
254c3a9fa21SAxel Dörfler		while (true) {
255c3a9fa21SAxel Dörfler			fDataArea = create_area("data buffer", (void**)&fDataBase,
256c3a9fa21SAxel Dörfler				B_ANY_KERNEL_ADDRESS, size, B_FULL_LOCK,
257c3a9fa21SAxel Dörfler				B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
258c3a9fa21SAxel Dörfler			if (fDataArea < B_OK)
259c3a9fa21SAxel Dörfler				return fDataArea;
260c3a9fa21SAxel Dörfler
261c3a9fa21SAxel Dörfler			// get memory map to see if we succeeded
2628faff60cSAxel Dörfler
263c3a9fa21SAxel Dörfler			physical_entry entry[2];
264c3a9fa21SAxel Dörfler			get_memory_map((void*)fDataBase, 2 * B_PAGE_SIZE, entry, 2);
2658faff60cSAxel Dörfler
266c3a9fa21SAxel Dörfler			if (entry[0].size == B_PAGE_SIZE) {
267c3a9fa21SAxel Dörfler				fPhysicalDataBase = (addr_t)entry[0].address;
268c3a9fa21SAxel Dörfler				fSecondPhysicalDataBase = (addr_t)entry[1].address;
269c3a9fa21SAxel Dörfler
270c3a9fa21SAxel Dörfler				dprintf("DMA Test area %p, physical %p, second physical %p\n",
271c3a9fa21SAxel Dörfler					(void*)fDataBase, entry[0].address, entry[1].address);
272c3a9fa21SAxel Dörfler				break;
273c3a9fa21SAxel Dörfler			}
274c3a9fa21SAxel Dörfler
275c3a9fa21SAxel Dörfler			// try again
276c3a9fa21SAxel Dörfler			delete_area(fDataArea);
277c3a9fa21SAxel Dörfler		}
278c3a9fa21SAxel Dörfler	} else {
279c3a9fa21SAxel Dörfler		fDataArea = create_area("data buffer", (void**)&fDataBase,
280c3a9fa21SAxel Dörfler			B_ANY_KERNEL_ADDRESS, size, B_CONTIGUOUS,
281c3a9fa21SAxel Dörfler			B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
282c3a9fa21SAxel Dörfler		if (fDataArea < B_OK)
283c3a9fa21SAxel Dörfler			return fDataArea;
284c3a9fa21SAxel Dörfler
285c3a9fa21SAxel Dörfler		physical_entry entry;
286c3a9fa21SAxel Dörfler		get_memory_map((void*)fDataBase, B_PAGE_SIZE, &entry, 1);
287c3a9fa21SAxel Dörfler
288c3a9fa21SAxel Dörfler		fPhysicalDataBase = (addr_t)entry.address;
289c3a9fa21SAxel Dörfler		fSecondPhysicalDataBase = 0;
290c3a9fa21SAxel Dörfler
291c3a9fa21SAxel Dörfler		dprintf("DMA Test area %p, physical %p\n", (void*)fDataBase,
292c3a9fa21SAxel Dörfler			entry.address);
293c3a9fa21SAxel Dörfler	}
2948faff60cSAxel Dörfler
2958faff60cSAxel Dörfler	fCompareArea = create_area("compare buffer", (void**)&fCompareBase,
2968faff60cSAxel Dörfler		B_ANY_KERNEL_ADDRESS, size, B_FULL_LOCK,
2978faff60cSAxel Dörfler		B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
2988faff60cSAxel Dörfler	if (fCompareArea < B_OK)
2998faff60cSAxel Dörfler		return fCompareArea;
3008faff60cSAxel Dörfler
3018faff60cSAxel Dörfler	fSize = size;
3028faff60cSAxel Dörfler	return B_OK;
3038faff60cSAxel Dörfler}
3048faff60cSAxel Dörfler
3058faff60cSAxel Dörfler
3068faff60cSAxel Dörfler//	#pragma mark -
3078faff60cSAxel Dörfler
3088faff60cSAxel Dörfler
3098faff60cSAxel DörflerTest::Test(TestSuite& suite, off_t offset, size_t length, bool isWrite,
3108faff60cSAxel Dörfler		uint32 flags)
3118faff60cSAxel Dörfler	:
3128faff60cSAxel Dörfler	fSuite(suite),
31345a206a7SAxel Dörfler	fOffset(offset),
31445a206a7SAxel Dörfler	fLength(length),
31545a206a7SAxel Dörfler	fIsWrite(isWrite),
31645a206a7SAxel Dörfler	fFlags(flags),
31745a206a7SAxel Dörfler	fSourceCount(0),
31845a206a7SAxel Dörfler	fResultCount(0)
31945a206a7SAxel Dörfler{
32045a206a7SAxel Dörfler}
32145a206a7SAxel Dörfler
32245a206a7SAxel Dörfler
32345a206a7SAxel DörflerTest&
32445a206a7SAxel DörflerTest::AddSource(addr_t address, size_t length)
32545a206a7SAxel Dörfler{
326c3a9fa21SAxel Dörfler	if (fSuite.IsContiguous() || (fFlags & B_PHYSICAL_IO_REQUEST) != 0
327c3a9fa21SAxel Dörfler		|| address < B_PAGE_SIZE) {
328c3a9fa21SAxel Dörfler		fSourceVecs[fSourceCount].iov_base
329c3a9fa21SAxel Dörfler			= (void*)(((fFlags & B_PHYSICAL_IO_REQUEST) == 0
330c3a9fa21SAxel Dörfler				? fSuite.DataBase() : fSuite.PhysicalDataBase()) + address);
331c3a9fa21SAxel Dörfler	} else {
332c3a9fa21SAxel Dörfler		fSourceVecs[fSourceCount].iov_base
333c3a9fa21SAxel Dörfler			= (void*)(fSuite.SecondPhysicalDataBase() + address);
334c3a9fa21SAxel Dörfler	}
33545a206a7SAxel Dörfler	fSourceVecs[fSourceCount].iov_len = length;
33645a206a7SAxel Dörfler	fSourceCount++;
33745a206a7SAxel Dörfler
33845a206a7SAxel Dörfler	return *this;
33945a206a7SAxel Dörfler}
34045a206a7SAxel Dörfler
34145a206a7SAxel Dörfler
34245a206a7SAxel DörflerTest&
34345a206a7SAxel DörflerTest::NextResult(off_t offset, bool partialBegin, bool partialEnd)
34445a206a7SAxel Dörfler{
34545a206a7SAxel Dörfler	fResults[fResultCount].offset = offset;
34645a206a7SAxel Dörfler	fResults[fResultCount].count = 0;
34745a206a7SAxel Dörfler	fResults[fResultCount].partial_begin = partialBegin;
34845a206a7SAxel Dörfler	fResults[fResultCount].partial_end = partialEnd;
34945a206a7SAxel Dörfler	fResultCount++;
35045a206a7SAxel Dörfler
35145a206a7SAxel Dörfler	return *this;
35245a206a7SAxel Dörfler}
35345a206a7SAxel Dörfler
35445a206a7SAxel Dörfler
35545a206a7SAxel DörflerTest&
35645a206a7SAxel DörflerTest::AddTarget(addr_t base, size_t length, bool usesBounceBuffer)
35745a206a7SAxel Dörfler{
35845a206a7SAxel Dörfler	struct result_t& result = fResults[fResultCount - 1];
35945a206a7SAxel Dörfler	struct target_t& target = result.targets[result.count++];
36045a206a7SAxel Dörfler
36145a206a7SAxel Dörfler	target.address = base;
36245a206a7SAxel Dörfler	target.length = length;
36345a206a7SAxel Dörfler	target.uses_bounce_buffer = usesBounceBuffer;
36445a206a7SAxel Dörfler
36545a206a7SAxel Dörfler	return *this;
36645a206a7SAxel Dörfler}
36745a206a7SAxel Dörfler
36845a206a7SAxel Dörfler
3698faff60cSAxel Dörfleraddr_t
3708faff60cSAxel DörflerTest::_SourceToVirtual(addr_t source)
3718faff60cSAxel Dörfler{
372c3a9fa21SAxel Dörfler	if ((fFlags & B_PHYSICAL_IO_REQUEST) != 0) {
373c3a9fa21SAxel Dörfler		if (!fSuite.IsContiguous() && source >= B_PAGE_SIZE)
374c3a9fa21SAxel Dörfler			return source - fSuite.SecondPhysicalDataBase() + fSuite.DataBase();
375c3a9fa21SAxel Dörfler
3768faff60cSAxel Dörfler		return source - fSuite.PhysicalDataBase() + fSuite.DataBase();
377c3a9fa21SAxel Dörfler	}
3788faff60cSAxel Dörfler
3798faff60cSAxel Dörfler	return source;
3808faff60cSAxel Dörfler}
3818faff60cSAxel Dörfler
3828faff60cSAxel Dörfler
3838faff60cSAxel Dörfleraddr_t
3848faff60cSAxel DörflerTest::_SourceToCompare(addr_t source)
3858faff60cSAxel Dörfler{
386c3a9fa21SAxel Dörfler	if ((fFlags & B_PHYSICAL_IO_REQUEST) != 0) {
387c3a9fa21SAxel Dörfler		if (!fSuite.IsContiguous() && source >= B_PAGE_SIZE) {
388c3a9fa21SAxel Dörfler			return source - fSuite.SecondPhysicalDataBase()
389c3a9fa21SAxel Dörfler				+ fSuite.CompareBase();
390c3a9fa21SAxel Dörfler		}
391c3a9fa21SAxel Dörfler
3928faff60cSAxel Dörfler		return source - fSuite.PhysicalDataBase() + fSuite.CompareBase();
393c3a9fa21SAxel Dörfler	}
3948faff60cSAxel Dörfler
3958faff60cSAxel Dörfler	return source - fSuite.DataBase() + fSuite.CompareBase();
3968faff60cSAxel Dörfler}
3978faff60cSAxel Dörfler
3988faff60cSAxel Dörfler
3998faff60cSAxel Dörflervoid
4008faff60cSAxel DörflerTest::_Prepare()
4018faff60cSAxel Dörfler{
4028faff60cSAxel Dörfler	// prepare disk
4038faff60cSAxel Dörfler
4048faff60cSAxel Dörfler	uint8* disk = (uint8*)sAreaAddress;
4058faff60cSAxel Dörfler	for (size_t i = 0; i < sAreaSize; i++) {
4068faff60cSAxel Dörfler		disk[i] = i % 26 + 'a';
4078faff60cSAxel Dörfler	}
4088faff60cSAxel Dörfler
4098faff60cSAxel Dörfler	// prepare data
4108faff60cSAxel Dörfler
4118faff60cSAxel Dörfler	memset((void*)fSuite.DataBase(), 0xcc, fSuite.Size());
4128faff60cSAxel Dörfler
4138faff60cSAxel Dörfler	if (fIsWrite) {
4148faff60cSAxel Dörfler		off_t offset = fOffset;
4158faff60cSAxel Dörfler		size_t length = fLength;
4168faff60cSAxel Dörfler
4178faff60cSAxel Dörfler		for (uint32 i = 0; i < fSourceCount; i++) {
4188faff60cSAxel Dörfler			uint8* data = (uint8*)_SourceToVirtual(
4198faff60cSAxel Dörfler				(addr_t)fSourceVecs[i].iov_base);
4208faff60cSAxel Dörfler			size_t vecLength = min_c(fSourceVecs[i].iov_len, length);
4218faff60cSAxel Dörfler
4228faff60cSAxel Dörfler			for (uint32 j = 0; j < vecLength; j++) {
4238faff60cSAxel Dörfler				data[j] = (offset + j) % 10 + '0';
4248faff60cSAxel Dörfler			}
4258faff60cSAxel Dörfler			offset += vecLength;
4268faff60cSAxel Dörfler			length -= vecLength;
4278faff60cSAxel Dörfler		}
4288faff60cSAxel Dörfler	}
4298faff60cSAxel Dörfler
4308faff60cSAxel Dörfler	// prepare compare data
4318faff60cSAxel Dörfler
4328faff60cSAxel Dörfler	memset((void*)fSuite.CompareBase(), 0xcc, fSuite.Size());
4338faff60cSAxel Dörfler
4348faff60cSAxel Dörfler	if (fIsWrite) {
4358faff60cSAxel Dörfler		// copy data from source
4368faff60cSAxel Dörfler		off_t offset = fOffset;
4378faff60cSAxel Dörfler		size_t length = fLength;
4388faff60cSAxel Dörfler
4398faff60cSAxel Dörfler		for (uint32 i = 0; i < fSourceCount; i++) {
4408faff60cSAxel Dörfler			uint8* compare = (uint8*)_SourceToCompare(
4418faff60cSAxel Dörfler				(addr_t)fSourceVecs[i].iov_base);
4428faff60cSAxel Dörfler			size_t vecLength = min_c(fSourceVecs[i].iov_len, length);
4438faff60cSAxel Dörfler
4448faff60cSAxel Dörfler			memcpy(compare,
4458faff60cSAxel Dörfler				(void*)_SourceToVirtual((addr_t)fSourceVecs[i].iov_base),
4468faff60cSAxel Dörfler				vecLength);
4478faff60cSAxel Dörfler			offset += vecLength;
4488faff60cSAxel Dörfler			length -= vecLength;
4498faff60cSAxel Dörfler		}
4508faff60cSAxel Dörfler	} else {
4518faff60cSAxel Dörfler		// copy data from drive
4528faff60cSAxel Dörfler		off_t offset = fOffset;
4538faff60cSAxel Dörfler		size_t length = fLength;
4548faff60cSAxel Dörfler
4558faff60cSAxel Dörfler		for (uint32 i = 0; i < fSourceCount; i++) {
4568faff60cSAxel Dörfler			uint8* compare = (uint8*)_SourceToCompare(
4578faff60cSAxel Dörfler				(addr_t)fSourceVecs[i].iov_base);
4588faff60cSAxel Dörfler			size_t vecLength = min_c(fSourceVecs[i].iov_len, length);
4598faff60cSAxel Dörfler
4608faff60cSAxel Dörfler			memcpy(compare, disk + offset, vecLength);
4618faff60cSAxel Dörfler			offset += vecLength;
4628faff60cSAxel Dörfler			length -= vecLength;
4638faff60cSAxel Dörfler		}
4648faff60cSAxel Dörfler	}
4658faff60cSAxel Dörfler
4668faff60cSAxel Dörfler	if (fIsWrite)
4678faff60cSAxel Dörfler		_CheckCompare();
4688faff60cSAxel Dörfler}
4698faff60cSAxel Dörfler
4708faff60cSAxel Dörfler
4718faff60cSAxel Dörflervoid
4728faff60cSAxel DörflerTest::_CheckCompare()
4738faff60cSAxel Dörfler{
4748faff60cSAxel Dörfler	uint8* data = (uint8*)fSuite.DataBase();
4758faff60cSAxel Dörfler	uint8* compare = (uint8*)fSuite.CompareBase();
4768faff60cSAxel Dörfler
4778faff60cSAxel Dörfler	for (size_t i = 0; i < fSuite.Size(); i++) {
4788faff60cSAxel Dörfler		if (data[i] != compare[i]) {
4798faff60cSAxel Dörfler			dprintf("offset %lu differs, %s:\n", i,
480