* Introduced type generic_io_vec, which is similar to iovec, but uses types

that are wide enough for both virtual and physical addresses.
* DMABuffer, IORequest, IOScheduler,... and code using them: Use
  generic_io_vec and generic_{addr,size}_t where necessary.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@36997 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2010-06-02 18:42:20 +00:00
parent 4a57f84396
commit 435c43f591
24 changed files with 515 additions and 471 deletions
+13 -15
View File
@@ -33,6 +33,7 @@
struct attr_info;
struct file_descriptor;
struct generic_io_vec;
struct kernel_args;
struct net_stat;
struct pollfd;
@@ -59,11 +60,6 @@ typedef struct io_context {
uint32 max_monitors;
} io_context;
/* macro to allocate a iovec array on the stack */
#define IOVECS(name, size) \
uint8 _##name[sizeof(iovecs) + (size)*sizeof(iovec)]; \
iovecs *name = (iovecs *)_##name
#ifdef __cplusplus
extern "C" {
@@ -100,11 +96,11 @@ void vfs_acquire_vnode(struct vnode *vnode);
status_t vfs_get_cookie_from_fd(int fd, void **_cookie);
bool vfs_can_page(struct vnode *vnode, void *cookie);
status_t vfs_read_pages(struct vnode *vnode, void *cookie, off_t pos,
const iovec *vecs, size_t count, uint32 flags,
size_t *_numBytes);
const struct generic_io_vec *vecs, size_t count, uint32 flags,
generic_size_t *_numBytes);
status_t vfs_write_pages(struct vnode *vnode, void *cookie, off_t pos,
const iovec *vecs, size_t count, uint32 flags,
size_t *_numBytes);
const struct generic_io_vec *vecs, size_t count, uint32 flags,
generic_size_t *_numBytes);
status_t vfs_vnode_io(struct vnode* vnode, void* cookie,
io_request* request);
status_t vfs_synchronous_io(io_request* request,
@@ -287,12 +283,12 @@ public:
virtual void IOFinished(status_t status,
bool partialTransfer,
size_t bytesTransferred) = 0;
generic_size_t bytesTransferred) = 0;
static status_t IORequestCallback(void* data,
io_request* request, status_t status,
bool partialTransfer,
size_t transferEndOffset);
generic_size_t transferEndOffset);
};
@@ -306,12 +302,14 @@ protected:
status_t vfs_asynchronous_read_pages(struct vnode* vnode, void* cookie,
off_t pos, const iovec* vecs, size_t count, size_t numBytes,
uint32 flags, AsyncIOCallback* callback);
off_t pos, const struct generic_io_vec* vecs, size_t count,
generic_size_t numBytes, uint32 flags,
AsyncIOCallback* callback);
status_t vfs_asynchronous_write_pages(struct vnode* vnode, void* cookie,
off_t pos, const iovec* vecs, size_t count, size_t numBytes,
uint32 flags, AsyncIOCallback* callback);
off_t pos, const struct generic_io_vec* vecs, size_t count,
generic_size_t numBytes, uint32 flags,
AsyncIOCallback* callback);
#endif // __cplusplus
+8 -6
View File
@@ -129,13 +129,15 @@ public:
virtual status_t Commit(off_t size, int priority);
virtual bool HasPage(off_t offset);
virtual status_t Read(off_t offset, const iovec *vecs,
virtual status_t Read(off_t offset, const generic_io_vec *vecs,
size_t count,uint32 flags,
size_t *_numBytes);
virtual status_t Write(off_t offset, const iovec *vecs, size_t count,
uint32 flags, size_t *_numBytes);
virtual status_t WriteAsync(off_t offset, const iovec* vecs,
size_t count, size_t numBytes, uint32 flags,
generic_size_t *_numBytes);
virtual status_t Write(off_t offset, const generic_io_vec *vecs,
size_t count, uint32 flags,
generic_size_t *_numBytes);
virtual status_t WriteAsync(off_t offset,
const generic_io_vec* vecs, size_t count,
generic_size_t numBytes, uint32 flags,
AsyncIOCallback* callback);
virtual bool CanWritePage(off_t offset);
+2 -2
View File
@@ -14,7 +14,7 @@
#include <vm_defs.h>
struct iovec;
struct generic_io_vec;
struct kernel_args;
struct ObjectCache;
struct system_memory_info;
@@ -93,7 +93,7 @@ area_id vm_map_physical_memory(team_id team, const char *name, void **address,
phys_addr_t physicalAddress, bool alreadyWired);
area_id vm_map_physical_memory_vecs(team_id team, const char* name,
void** _address, uint32 addressSpec, addr_t* _size, uint32 protection,
struct iovec* vecs, uint32 vecCount);
struct generic_io_vec* vecs, uint32 vecCount);
area_id vm_map_file(team_id aid, const char *name, void **address,
uint32 addressSpec, addr_t size, uint32 protection, uint32 mapping,
bool unmapAddressRange, int fd, off_t offset);
@@ -770,7 +770,7 @@ cd_read(void* cookie, off_t pos, void* buffer, size_t* _length)
return B_DEV_NO_MEDIA;
IORequest request;
status_t status = request.Init(pos, buffer, length, false, 0);
status_t status = request.Init(pos, (addr_t)buffer, length, false, 0);
if (status != B_OK)
return status;
@@ -798,7 +798,7 @@ cd_write(void* cookie, off_t pos, const void* buffer, size_t* _length)
return B_DEV_NO_MEDIA;
IORequest request;
status_t status = request.Init(pos, (void*)buffer, length, true, 0);
status_t status = request.Init(pos, (addr_t)buffer, length, true, 0);
if (status != B_OK)
return status;
@@ -265,7 +265,7 @@ das_read(void* cookie, off_t pos, void* buffer, size_t* _length)
size_t length = *_length;
IORequest request;
status_t status = request.Init(pos, buffer, length, false, 0);
status_t status = request.Init(pos, (addr_t)buffer, length, false, 0);
if (status != B_OK)
return status;
@@ -290,7 +290,7 @@ das_write(void* cookie, off_t pos, const void* buffer, size_t* _length)
size_t length = *_length;
IORequest request;
status_t status = request.Init(pos, (void*)buffer, length, true, 0);
status_t status = request.Init(pos, (addr_t)buffer, length, true, 0);
if (status != B_OK)
return status;
+66 -62
View File
@@ -72,7 +72,7 @@ struct file_cache_ref {
class PrecacheIO : public AsyncIOCallback {
public:
PrecacheIO(file_cache_ref* ref, off_t offset,
size_t size);
generic_size_t size);
~PrecacheIO();
status_t Prepare(vm_page_reservation* reservation);
@@ -80,7 +80,7 @@ public:
virtual void IOFinished(status_t status,
bool partialTransfer,
size_t bytesTransferred);
generic_size_t bytesTransferred);
private:
file_cache_ref* fRef;
@@ -88,10 +88,10 @@ private:
vm_page** fPages;
size_t fPageCount;
ConditionVariable* fBusyConditions;
iovec* fVecs;
generic_io_vec* fVecs;
off_t fOffset;
uint32 fVecCount;
size_t fSize;
generic_size_t fSize;
#if DEBUG_PAGE_ACCESS
thread_id fAllocatingThread;
#endif
@@ -101,8 +101,8 @@ typedef status_t (*cache_func)(file_cache_ref* ref, void* cookie, off_t offset,
int32 pageOffset, addr_t buffer, size_t bufferSize, bool useBuffer,
vm_page_reservation* reservation, size_t reservePages);
static void add_to_iovec(iovec* vecs, uint32 &index, uint32 max, addr_t address,
size_t size);
static void add_to_iovec(generic_io_vec* vecs, uint32 &index, uint32 max,
generic_addr_t address, generic_size_t size);
static struct cache_module_info* sCacheModule;
@@ -110,14 +110,14 @@ static struct cache_module_info* sCacheModule;
static const uint32 kZeroVecCount = 32;
static const size_t kZeroVecSize = kZeroVecCount * B_PAGE_SIZE;
static addr_t sZeroPage; // physical address
static iovec sZeroVecs[kZeroVecCount];
static phys_addr_t sZeroPage; // physical address
static generic_io_vec sZeroVecs[kZeroVecCount];
// #pragma mark -
PrecacheIO::PrecacheIO(file_cache_ref* ref, off_t offset, size_t size)
PrecacheIO::PrecacheIO(file_cache_ref* ref, off_t offset, generic_size_t size)
:
fRef(ref),
fCache(ref->cache),
@@ -150,13 +150,13 @@ PrecacheIO::Prepare(vm_page_reservation* reservation)
if (fPages == NULL)
return B_NO_MEMORY;
fVecs = new(std::nothrow) iovec[fPageCount];
fVecs = new(std::nothrow) generic_io_vec[fPageCount];
if (fVecs == NULL)
return B_NO_MEMORY;
// allocate pages for the cache and mark them busy
uint32 i = 0;
for (size_t pos = 0; pos < fSize; pos += B_PAGE_SIZE) {
for (generic_size_t pos = 0; pos < fSize; pos += B_PAGE_SIZE) {
vm_page* page = vm_page_allocate_page(reservation,
PAGE_STATE_CACHED | VM_PAGE_ALLOC_BUSY);
@@ -187,13 +187,13 @@ PrecacheIO::ReadAsync()
void
PrecacheIO::IOFinished(status_t status, bool partialTransfer,
size_t bytesTransferred)
generic_size_t bytesTransferred)
{
AutoLocker<VMCache> locker(fCache);
// Make successfully loaded pages accessible again (partially
// transferred pages are considered failed)
size_t pagesTransferred
phys_size_t pagesTransferred
= (bytesTransferred + B_PAGE_SIZE - 1) / B_PAGE_SIZE;
if (fOffset + bytesTransferred > fCache->virtual_end)
@@ -204,8 +204,10 @@ PrecacheIO::IOFinished(status_t status, bool partialTransfer,
&& (bytesTransferred % B_PAGE_SIZE) != 0) {
// clear partial page
size_t bytesTouched = bytesTransferred % B_PAGE_SIZE;
vm_memset_physical((fPages[i]->physical_page_number << PAGE_SHIFT)
+ bytesTouched, 0, B_PAGE_SIZE - bytesTouched);
vm_memset_physical(
((phys_addr_t)fPages[i]->physical_page_number << PAGE_SHIFT)
+ bytesTouched,
0, B_PAGE_SIZE - bytesTouched);
}
DEBUG_PAGE_ACCESS_TRANSFER(fPages[i], fAllocatingThread);
@@ -231,13 +233,12 @@ PrecacheIO::IOFinished(status_t status, bool partialTransfer,
static void
add_to_iovec(iovec* vecs, uint32 &index, uint32 max, addr_t address,
size_t size)
add_to_iovec(generic_io_vec* vecs, uint32 &index, uint32 max,
generic_addr_t address, generic_size_t size)
{
if (index > 0 && (addr_t)vecs[index - 1].iov_base
+ vecs[index - 1].iov_len == address) {
if (index > 0 && vecs[index - 1].base + vecs[index - 1].length == address) {
// the iovec can be combined with the previous one
vecs[index - 1].iov_len += size;
vecs[index - 1].length += size;
return;
}
@@ -245,8 +246,8 @@ add_to_iovec(iovec* vecs, uint32 &index, uint32 max, addr_t address,
panic("no more space for iovecs!");
// we need to start a new iovec
vecs[index].iov_base = (void*)address;
vecs[index].iov_len = size;
vecs[index].base = address;
vecs[index].length = size;
index++;
}
@@ -259,7 +260,8 @@ access_is_sequential(file_cache_ref* ref)
static inline void
push_access(file_cache_ref* ref, off_t offset, size_t bytes, bool isWrite)
push_access(file_cache_ref* ref, off_t offset, generic_size_t bytes,
bool isWrite)
{
TRACE(("%p: push %Ld, %ld, %s\n", ref, offset, bytes,
isWrite ? "write" : "read"));
@@ -331,14 +333,15 @@ reserve_pages(file_cache_ref* ref, vm_page_reservation* reservation,
static inline status_t
read_pages_and_clear_partial(file_cache_ref* ref, void* cookie, off_t offset,
const iovec* vecs, size_t count, uint32 flags, size_t* _numBytes)
const generic_io_vec* vecs, size_t count, uint32 flags,
generic_size_t* _numBytes)
{
size_t bytesUntouched = *_numBytes;
generic_size_t bytesUntouched = *_numBytes;
status_t status = vfs_read_pages(ref->vnode, cookie, offset, vecs, count,
flags, _numBytes);
size_t bytesEnd = *_numBytes;
generic_size_t bytesEnd = *_numBytes;
if (offset + bytesEnd > ref->cache->virtual_end)
bytesEnd = ref->cache->virtual_end - offset;
@@ -350,9 +353,9 @@ read_pages_and_clear_partial(file_cache_ref* ref, void* cookie, off_t offset,
bytesUntouched -= bytesEnd;
for (int32 i = count; i-- > 0 && bytesUntouched != 0; ) {
size_t length = min_c(bytesUntouched, vecs[i].iov_len);
vm_memset_physical((addr_t)vecs[i].iov_base + vecs[i].iov_len
- length, 0, length);
generic_size_t length = min_c(bytesUntouched, vecs[i].length);
vm_memset_physical(vecs[i].base + vecs[i].length - length, 0,
length);
bytesUntouched -= length;
}
@@ -381,7 +384,7 @@ read_into_cache(file_cache_ref* ref, void* cookie, off_t offset,
// TODO: We're using way too much stack! Rather allocate a sufficiently
// large chunk on the heap.
iovec vecs[MAX_IO_VECS];
generic_io_vec vecs[MAX_IO_VECS];
uint32 vecCount = 0;
size_t numBytes = PAGE_ALIGN(pageOffset + bufferSize);
@@ -464,9 +467,9 @@ read_from_file(file_cache_ref* ref, void* cookie, off_t offset,
if (!useBuffer)
return B_OK;
iovec vec;
vec.iov_base = (void*)buffer;
vec.iov_len = bufferSize;
generic_io_vec vec;
vec.base = buffer;
vec.length = bufferSize;
push_access(ref, offset, bufferSize, false);
ref->cache->Unlock();
@@ -496,7 +499,7 @@ write_to_cache(file_cache_ref* ref, void* cookie, off_t offset,
{
// TODO: We're using way too much stack! Rather allocate a sufficiently
// large chunk on the heap.
iovec vecs[MAX_IO_VECS];
generic_io_vec vecs[MAX_IO_VECS];
uint32 vecCount = 0;
size_t numBytes = PAGE_ALIGN(pageOffset + bufferSize);
vm_page* pages[MAX_IO_VECS];
@@ -535,8 +538,8 @@ write_to_cache(file_cache_ref* ref, void* cookie, off_t offset,
if (pageOffset != 0) {
// This is only a partial write, so we have to read the rest of the page
// from the file to have consistent data in the cache
iovec readVec = { vecs[0].iov_base, B_PAGE_SIZE };
size_t bytesRead = B_PAGE_SIZE;
generic_io_vec readVec = { vecs[0].base, B_PAGE_SIZE };
generic_size_t bytesRead = B_PAGE_SIZE;
status = vfs_read_pages(ref->vnode, cookie, offset, &readVec, 1,
B_PHYSICAL_IO_REQUEST, &bytesRead);
@@ -545,11 +548,11 @@ write_to_cache(file_cache_ref* ref, void* cookie, off_t offset,
panic("1. vfs_read_pages() failed: %s!\n", strerror(status));
}
addr_t lastPageOffset = (pageOffset + bufferSize) & (B_PAGE_SIZE - 1);
size_t lastPageOffset = (pageOffset + bufferSize) % B_PAGE_SIZE;
if (lastPageOffset != 0) {
// get the last page in the I/O vectors
addr_t last = (addr_t)vecs[vecCount - 1].iov_base
+ vecs[vecCount - 1].iov_len - B_PAGE_SIZE;
generic_addr_t last = vecs[vecCount - 1].base
+ vecs[vecCount - 1].length - B_PAGE_SIZE;
if (offset + pageOffset + bufferSize == ref->cache->virtual_end) {
// the space in the page after this write action needs to be cleaned
@@ -558,8 +561,8 @@ write_to_cache(file_cache_ref* ref, void* cookie, off_t offset,
} else {
// the end of this write does not happen on a page boundary, so we
// need to fetch the last page before we can update it
iovec readVec = { (void*)last, B_PAGE_SIZE };
size_t bytesRead = B_PAGE_SIZE;
generic_io_vec readVec = { last, B_PAGE_SIZE };
generic_size_t bytesRead = B_PAGE_SIZE;
status = vfs_read_pages(ref->vnode, cookie,
PAGE_ALIGN(offset + pageOffset + bufferSize) - B_PAGE_SIZE,
@@ -577,9 +580,9 @@ write_to_cache(file_cache_ref* ref, void* cookie, off_t offset,
}
for (uint32 i = 0; i < vecCount; i++) {
addr_t base = (addr_t)vecs[i].iov_base;
size_t bytes = min_c(bufferSize,
size_t(vecs[i].iov_len - pageOffset));
generic_addr_t base = vecs[i].base;
generic_size_t bytes = min_c((generic_size_t)bufferSize,
generic_size_t(vecs[i].length - pageOffset));
if (useBuffer) {
// copy data from user buffer
@@ -638,7 +641,7 @@ write_to_file(file_cache_ref* ref, void* cookie, off_t offset, int32 pageOffset,
if (!useBuffer) {
while (bufferSize > 0) {
size_t written = min_c(bufferSize, kZeroVecSize);
generic_size_t written = min_c(bufferSize, kZeroVecSize);
status = vfs_write_pages(ref->vnode, cookie, offset + pageOffset,
sZeroVecs, kZeroVecCount, B_PHYSICAL_IO_REQUEST, &written);
if (status != B_OK)
@@ -650,9 +653,9 @@ write_to_file(file_cache_ref* ref, void* cookie, off_t offset, int32 pageOffset,
pageOffset += written;
}
} else {
iovec vec;
vec.iov_base = (void*)buffer;
vec.iov_len = bufferSize;
generic_io_vec vec;
vec.base = buffer;
vec.length = bufferSize;
status = vfs_write_pages(ref->vnode, cookie, offset + pageOffset,
&vec, 1, 0, &bufferSize);
}
@@ -669,8 +672,8 @@ write_to_file(file_cache_ref* ref, void* cookie, off_t offset, int32 pageOffset,
static inline status_t
satisfy_cache_io(file_cache_ref* ref, void* cookie, cache_func function,
off_t offset, addr_t buffer, bool useBuffer, int32 &pageOffset,
size_t bytesLeft, size_t &reservePages, off_t &lastOffset,
addr_t &lastBuffer, int32 &lastPageOffset, size_t &lastLeft,
generic_size_t bytesLeft, size_t &reservePages, off_t &lastOffset,
addr_t &lastBuffer, int32 &lastPageOffset, generic_size_t &lastLeft,
size_t &lastReservedPages, vm_page_reservation* reservation)
{
if (lastBuffer == buffer)
@@ -797,8 +800,9 @@ cache_io(void* _cacheRef, void* cookie, off_t offset, addr_t buffer,
locker.Unlock();
// copy the contents of the page already in memory
addr_t pageAddress = page->physical_page_number * B_PAGE_SIZE
+ pageOffset;
phys_addr_t pageAddress
= (phys_addr_t)page->physical_page_number * B_PAGE_SIZE
+ pageOffset;
if (doWrite) {
if (useBuffer) {
vm_memcpy_to_physical(pageAddress, (void*)buffer,
@@ -1095,11 +1099,11 @@ file_cache_init(void)
PAGE_STATE_WIRED | VM_PAGE_ALLOC_CLEAR);
vm_page_unreserve_pages(&reservation);
sZeroPage = (addr_t)page->physical_page_number * B_PAGE_SIZE;
sZeroPage = (phys_addr_t)page->physical_page_number * B_PAGE_SIZE;
for (uint32 i = 0; i < kZeroVecCount; i++) {
sZeroVecs[i].iov_base = (void*)sZeroPage;
sZeroVecs[i].iov_len = B_PAGE_SIZE;
sZeroVecs[i].base = sZeroPage;
sZeroVecs[i].length = B_PAGE_SIZE;
}
register_generic_syscall(CACHE_SYSCALLS, file_cache_control, 1, 0);
@@ -1280,9 +1284,9 @@ file_cache_read(void* _cacheRef, void* cookie, off_t offset, void* buffer,
if (ref->disabled_count > 0) {
// Caching is disabled -- read directly from the file.
iovec vec;
vec.iov_base = buffer;
vec.iov_len = *_size;
generic_io_vec vec;
vec.base = (addr_t)buffer;
vec.length = *_size;
return vfs_read_pages(ref->vnode, cookie, offset, &vec, 1, 0, _size);
}
@@ -1300,9 +1304,9 @@ file_cache_write(void* _cacheRef, void* cookie, off_t offset,
// Caching is disabled -- write directly to the file.
if (buffer != NULL) {
iovec vec;
vec.iov_base = (void*)buffer;
vec.iov_len = *_size;
generic_io_vec vec;
vec.base = (addr_t)buffer;
vec.length = *_size;
return vfs_write_pages(ref->vnode, cookie, offset, &vec, 1, 0,
_size);
}
@@ -1311,7 +1315,7 @@ file_cache_write(void* _cacheRef, void* cookie, off_t offset,
size_t size = *_size;
while (size > 0) {
size_t toWrite = min_c(size, kZeroVecSize);
size_t written = toWrite;
generic_size_t written = toWrite;
status_t error = vfs_write_pages(ref->vnode, cookie, offset,
sZeroVecs, kZeroVecCount, B_PHYSICAL_IO_REQUEST, &written);
if (error != B_OK)
+12 -12
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2004-2007, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License.
*/
@@ -42,15 +42,15 @@ VMVnodeCache::HasPage(off_t offset)
status_t
VMVnodeCache::Read(off_t offset, const iovec *vecs, size_t count,
uint32 flags, size_t *_numBytes)
VMVnodeCache::Read(off_t offset, const generic_io_vec *vecs, size_t count,
uint32 flags, generic_size_t *_numBytes)
{
size_t bytesUntouched = *_numBytes;
generic_size_t bytesUntouched = *_numBytes;
status_t status = vfs_read_pages(fVnode, NULL, offset, vecs, count,
flags, _numBytes);
size_t bytesEnd = *_numBytes;
generic_size_t bytesEnd = *_numBytes;
if (offset + bytesEnd > virtual_end)
bytesEnd = virtual_end - offset;
@@ -66,13 +66,13 @@ VMVnodeCache::Read(off_t offset, const iovec *vecs, size_t count,
// doing this here so that not every file system/device has to implement
// this
for (int32 i = count; i-- > 0 && bytesUntouched != 0;) {
size_t length = min_c(bytesUntouched, vecs[i].iov_len);
generic_size_t length = min_c(bytesUntouched, vecs[i].length);
addr_t address = (addr_t)vecs[i].iov_base + vecs[i].iov_len - length;
generic_addr_t address = vecs[i].base + vecs[i].length - length;
if ((flags & B_PHYSICAL_IO_REQUEST) != 0)
vm_memset_physical(address, 0, length);
else
memset((void*)address, 0, length);
memset((void*)(addr_t)address, 0, length);
bytesUntouched -= length;
}
@@ -82,16 +82,16 @@ VMVnodeCache::Read(off_t offset, const iovec *vecs, size_t count,
status_t
VMVnodeCache::Write(off_t offset, const iovec *vecs, size_t count,
uint32 flags, size_t *_numBytes)
VMVnodeCache::Write(off_t offset, const generic_io_vec *vecs, size_t count,
uint32 flags, generic_size_t *_numBytes)
{
return vfs_write_pages(fVnode, NULL, offset, vecs, count, flags, _numBytes);
}
status_t
VMVnodeCache::WriteAsync(off_t offset, const iovec* vecs, size_t count,
size_t numBytes, uint32 flags, AsyncIOCallback* callback)
VMVnodeCache::WriteAsync(off_t offset, const generic_io_vec* vecs, size_t count,
generic_size_t numBytes, uint32 flags, AsyncIOCallback* callback)
{
return vfs_asynchronous_write_pages(fVnode, NULL, offset, vecs, count,
numBytes, flags, callback);
+7 -6
View File
@@ -20,14 +20,15 @@ public:
virtual bool HasPage(off_t offset);
virtual status_t Read(off_t offset, const iovec *vecs,
virtual status_t Read(off_t offset, const generic_io_vec *vecs,
size_t count, uint32 flags,
size_t *_numBytes);
virtual status_t Write(off_t offset, const iovec *vecs,
generic_size_t *_numBytes);
virtual status_t Write(off_t offset, const generic_io_vec *vecs,
size_t count, uint32 flags,
size_t *_numBytes);
virtual status_t WriteAsync(off_t offset, const iovec* vecs,
size_t count, size_t numBytes, uint32 flags,
generic_size_t *_numBytes);
virtual status_t WriteAsync(off_t offset,
const generic_io_vec* vecs, size_t count,
generic_size_t numBytes, uint32 flags,
AsyncIOCallback* callback);
virtual bool CanWritePage(off_t offset);
+14 -13
View File
@@ -113,9 +113,9 @@ IOCache::Init(const char* name)
}
fCache = area->cache;
// allocate arrays for pages and iovecs
// allocate arrays for pages and io vecs
fPages = new(std::nothrow) vm_page*[fPagesPerLine];
fVecs = new(std::nothrow) iovec[fPagesPerLine];
fVecs = new(std::nothrow) generic_io_vec[fPagesPerLine];
if (fPages == NULL || fVecs == NULL)
return B_NO_MEMORY;
@@ -171,7 +171,7 @@ IOCache::ScheduleRequest(IORequest* request)
// we completely serialize all I/O in FIFO order
MutexLocker serializationLocker(fSerializationLock);
size_t bytesTransferred = 0;
generic_size_t bytesTransferred = 0;
error = _DoRequest(request, bytesTransferred);
serializationLocker.Unlock();
@@ -200,7 +200,7 @@ IOCache::AbortRequest(IORequest* request, status_t status)
void
IOCache::OperationCompleted(IOOperation* operation, status_t status,
size_t transferredBytes)
generic_size_t transferredBytes)
{
if (status == B_OK) {
// always fail in case of partial transfers
@@ -220,10 +220,10 @@ IOCache::Dump() const
status_t
IOCache::_DoRequest(IORequest* request, size_t& _bytesTransferred)
IOCache::_DoRequest(IORequest* request, generic_size_t& _bytesTransferred)
{
off_t offset = request->Offset();
size_t length = request->Length();
generic_size_t length = request->Length();
TRACE("%p->IOCache::ScheduleRequest(%p): offset: %" B_PRIdOFF
", length: %" B_PRIuSIZE "\n", this, request, offset, length);
@@ -439,7 +439,7 @@ IOCache::_TransferRequestLineUncached(IORequest* request, off_t lineOffset,
if (actualRequestOffset < requestOffset)
request->Advance(requestOffset - actualRequestOffset);
size_t requestRemaining = request->RemainingBytes() - requestLength;
generic_size_t requestRemaining = request->RemainingBytes() - requestLength;
// Process single operations until the specified part of the request is
// finished or until an error occurs.
@@ -513,23 +513,24 @@ IOCache::_TransferPages(size_t firstPage, size_t pageCount, bool isWrite,
off_t firstPageOffset = (off_t)fPages[firstPage]->cache_offset
* B_PAGE_SIZE;
size_t requestLength = std::min(
generic_size_t requestLength = std::min(
firstPageOffset + (off_t)pageCount * B_PAGE_SIZE, fDeviceCapacity)
- firstPageOffset;
// prepare the I/O vecs
size_t vecCount = 0;
size_t endPage = firstPage + pageCount;
addr_t vecsEndAddress = 0;
phys_addr_t vecsEndAddress = 0;
for (size_t i = firstPage; i < endPage; i++) {
addr_t pageAddress = fPages[i]->physical_page_number * B_PAGE_SIZE;
phys_addr_t pageAddress
= (phys_addr_t)fPages[i]->physical_page_number * B_PAGE_SIZE;
if (vecCount == 0 || pageAddress != vecsEndAddress) {
fVecs[vecCount].iov_base = (void*)pageAddress;
fVecs[vecCount++].iov_len = B_PAGE_SIZE;
fVecs[vecCount].base = pageAddress;
fVecs[vecCount++].length = B_PAGE_SIZE;
vecsEndAddress = pageAddress + B_PAGE_SIZE;
} else {
// extend the previous vec
fVecs[vecCount - 1].iov_len += B_PAGE_SIZE;
fVecs[vecCount - 1].length += B_PAGE_SIZE;
vecsEndAddress += B_PAGE_SIZE;
}
}
+4 -3
View File
@@ -33,7 +33,8 @@ public:
virtual void AbortRequest(IORequest* request,
status_t status = B_CANCELED);
virtual void OperationCompleted(IOOperation* operation,
status_t status, size_t transferredBytes);
status_t status,
generic_size_t transferredBytes);
virtual void Dump() const;
@@ -42,7 +43,7 @@ private:
private:
status_t _DoRequest(IORequest* request,
size_t& _bytesTransferred);
generic_size_t& _bytesTransferred);
status_t _TransferRequestLine(IORequest* request,
off_t lineOffset, size_t lineSize,
off_t requestOffset, size_t requestLength);
@@ -76,7 +77,7 @@ private:
vm_page_reservation fMappingReservation;
VMCache* fCache;
vm_page** fPages;
iovec* fVecs;
generic_io_vec* fVecs;
};
+117 -110
View File
@@ -4,6 +4,7 @@
* Distributed under the terms of the MIT License.
*/
#include "IORequest.h"
#include <string.h>
@@ -56,18 +57,18 @@ IORequestChunk::~IORequestChunk()
struct virtual_vec_cookie {
uint32 vec_index;
size_t vec_offset;
area_id mapped_area;
void* physical_page_handle;
addr_t virtual_address;
uint32 vec_index;
generic_size_t vec_offset;
area_id mapped_area;
void* physical_page_handle;
addr_t virtual_address;
};
IOBuffer*
IOBuffer::Create(uint32 count, bool vip)
{
size_t size = sizeof(IOBuffer) + sizeof(iovec) * (count - 1);
size_t size = sizeof(IOBuffer) + sizeof(generic_io_vec) * (count - 1);
IOBuffer* buffer
= (IOBuffer*)(malloc_etc(size, vip ? HEAP_PRIORITY_VIP : 0));
if (buffer == NULL)
@@ -95,19 +96,20 @@ IOBuffer::Delete()
void
IOBuffer::SetVecs(size_t firstVecOffset, const iovec* vecs, uint32 count,
size_t length, uint32 flags)
IOBuffer::SetVecs(generic_size_t firstVecOffset, const generic_io_vec* vecs,
uint32 count, generic_size_t length, uint32 flags)
{
memcpy(fVecs, vecs, sizeof(iovec) * count);
memcpy(fVecs, vecs, sizeof(generic_io_vec) * count);
if (count > 0 && firstVecOffset > 0) {
fVecs[0].iov_base = (uint8*)fVecs[0].iov_base + firstVecOffset;
fVecs[0].iov_len -= firstVecOffset;
fVecs[0].base += firstVecOffset;
fVecs[0].length -= firstVecOffset;
}
fVecCount = count;
fLength = length;
fPhysical = (flags & B_PHYSICAL_IO_REQUEST) != 0;
fUser = !fPhysical && IS_USER_ADDRESS(vecs[0].iov_base);
fUser = !fPhysical && IS_USER_ADDRESS(vecs[0].base);
}
@@ -141,12 +143,13 @@ IOBuffer::GetNextVirtualVec(void*& _cookie, iovec& vector)
return B_BAD_INDEX;
if (!fPhysical) {
vector = fVecs[cookie->vec_index++];
vector.iov_base = (void*)(addr_t)fVecs[cookie->vec_index].base;
vector.iov_len = fVecs[cookie->vec_index++].length;
return B_OK;
}
if (cookie->vec_index == 0
&& (fVecCount > 1 || fVecs[0].iov_len > B_PAGE_SIZE)) {
&& (fVecCount > 1 || fVecs[0].length > B_PAGE_SIZE)) {
void* mappedAddress;
addr_t mappedSize;
@@ -158,7 +161,7 @@ IOBuffer::GetNextVirtualVec(void*& _cookie, iovec& vector)
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, fVecs, fVecCount);
if (cookie->mapped_area >= 0) {
vector.iov_base = (void*)mappedAddress;
vector.iov_base = mappedAddress;
vector.iov_len = mappedSize;
return B_OK;
} else
@@ -166,9 +169,9 @@ IOBuffer::GetNextVirtualVec(void*& _cookie, iovec& vector)
}
// fallback to page wise mapping
iovec& currentVec = fVecs[cookie->vec_index];
addr_t address = (addr_t)currentVec.iov_base + cookie->vec_offset;
addr_t pageOffset = address % B_PAGE_SIZE;
generic_io_vec& currentVec = fVecs[cookie->vec_index];
generic_addr_t address = currentVec.base + cookie->vec_offset;
size_t pageOffset = address % B_PAGE_SIZE;
// TODO: This is a potential violation of the VIP requirement, since
// vm_get_physical_page() may allocate memory without special flags!
@@ -177,14 +180,14 @@ IOBuffer::GetNextVirtualVec(void*& _cookie, iovec& vector)
if (result != B_OK)
return result;
size_t length = min_c(currentVec.iov_len - cookie->vec_offset,
generic_size_t length = min_c(currentVec.length - cookie->vec_offset,
B_PAGE_SIZE - pageOffset);
vector.iov_base = (void*)(cookie->virtual_address + pageOffset);
vector.iov_len = length;
cookie->vec_offset += length;
if (cookie->vec_offset >= currentVec.iov_len) {
if (cookie->vec_offset >= currentVec.length) {
cookie->vec_index++;
cookie->vec_offset = 0;
}
@@ -214,8 +217,8 @@ IOBuffer::LockMemory(team_id team, bool isWrite)
}
for (uint32 i = 0; i < fVecCount; i++) {
status_t status = lock_memory_etc(team, fVecs[i].iov_base,
fVecs[i].iov_len, isWrite ? 0 : B_READ_DEVICE);
status_t status = lock_memory_etc(team, (void*)(addr_t)fVecs[i].base,
fVecs[i].length, isWrite ? 0 : B_READ_DEVICE);
if (status != B_OK) {
_UnlockMemory(team, i, isWrite);
return status;
@@ -231,7 +234,7 @@ void
IOBuffer::_UnlockMemory(team_id team, size_t count, bool isWrite)
{
for (uint32 i = 0; i < count; i++) {
unlock_memory_etc(team, fVecs[i].iov_base, fVecs[i].iov_len,
unlock_memory_etc(team, (void*)(addr_t)fVecs[i].base, fVecs[i].length,
isWrite ? 0 : B_READ_DEVICE);
}
}
@@ -262,7 +265,8 @@ IOBuffer::Dump() const
kprintf(" vecs: %lu\n", fVecCount);
for (uint32 i = 0; i < fVecCount; i++) {
kprintf(" [%lu] %p, %lu\n", i, fVecs[i].iov_base, fVecs[i].iov_len);
kprintf(" [%" B_PRIu32 "] %#" B_PRIxGENADDR ", %" B_PRIuGENADDR "\n",
i, fVecs[i].base, fVecs[i].length);
}
}
@@ -280,7 +284,7 @@ IOOperation::Finish()
if (fPhase == PHASE_READ_BEGIN) {
TRACE(" phase read begin\n");
// repair phase adjusted vec
fDMABuffer->VecAt(fSavedVecIndex).iov_len = fSavedVecLength;
fDMABuffer->VecAt(fSavedVecIndex).length = fSavedVecLength;
// partial write: copy partial begin to bounce buffer
bool skipReadEndPhase;
@@ -301,10 +305,9 @@ IOOperation::Finish()
} else if (fPhase == PHASE_READ_END) {
TRACE(" phase read end\n");
// repair phase adjusted vec
iovec& vec = fDMABuffer->VecAt(fSavedVecIndex);
vec.iov_base = (uint8*)vec.iov_base
+ vec.iov_len - fSavedVecLength;
vec.iov_len = fSavedVecLength;
generic_io_vec& vec = fDMABuffer->VecAt(fSavedVecIndex);
vec.base += vec.length - fSavedVecLength;
vec.length = fSavedVecLength;
// partial write: copy partial end to bounce buffer
status_t error = _CopyPartialEnd(true);
@@ -327,26 +330,27 @@ IOOperation::Finish()
TRACE(" read with bounce buffer\n");
// copy the bounce buffer segments to the final location
uint8* bounceBuffer = (uint8*)fDMABuffer->BounceBufferAddress();
addr_t bounceBufferStart = fDMABuffer->PhysicalBounceBufferAddress();
addr_t bounceBufferEnd = bounceBufferStart
phys_addr_t bounceBufferStart
= fDMABuffer->PhysicalBounceBufferAddress();
phys_addr_t bounceBufferEnd = bounceBufferStart
+ fDMABuffer->BounceBufferSize();
const iovec* vecs = fDMABuffer->Vecs();
const generic_io_vec* vecs = fDMABuffer->Vecs();
uint32 vecCount = fDMABuffer->VecCount();
status_t error = B_OK;
// We iterate through the vecs we have read, moving offset (the device
// offset) as we go. If [offset, offset + vec.iov_len) intersects with
// offset) as we go. If [offset, offset + vec.length) intersects with
// [startOffset, endOffset) we copy to the final location.
off_t offset = fOffset;
const off_t startOffset = fOriginalOffset;
const off_t endOffset = fOriginalOffset + fOriginalLength;
for (uint32 i = 0; error == B_OK && i < vecCount; i++) {
const iovec& vec = vecs[i];
addr_t base = (addr_t)vec.iov_base;
size_t length = vec.iov_len;
const generic_io_vec& vec = vecs[i];
generic_addr_t base = vec.base;
generic_size_t length = vec.length;
if (offset < startOffset) {
// If the complete vector is before the start offset, skip it.
@@ -357,7 +361,7 @@ IOOperation::Finish()
// The vector starts before the start offset, but intersects
// with it. Skip the part we aren't interested in.
size_t diff = startOffset - offset;
generic_size_t diff = startOffset - offset;
offset += diff;
base += diff;
length -= diff;
@@ -408,14 +412,14 @@ IOOperation::Prepare(IORequest* request)
if (UsesBounceBuffer()) {
TRACE(" write with bounce buffer\n");
uint8* bounceBuffer = (uint8*)fDMABuffer->BounceBufferAddress();
addr_t bounceBufferStart
phys_addr_t bounceBufferStart
= fDMABuffer->PhysicalBounceBufferAddress();
addr_t bounceBufferEnd = bounceBufferStart
phys_addr_t bounceBufferEnd = bounceBufferStart
+ fDMABuffer->BounceBufferSize();
const iovec* vecs = fDMABuffer->Vecs();
const generic_io_vec* vecs = fDMABuffer->Vecs();
uint32 vecCount = fDMABuffer->VecCount();
size_t vecOffset = 0;
generic_size_t vecOffset = 0;
uint32 i = 0;
off_t offset = fOffset;
@@ -423,10 +427,10 @@ IOOperation::Prepare(IORequest* request)
if (HasPartialBegin()) {
// skip first block
size_t toSkip = fBlockSize;
generic_size_t toSkip = fBlockSize;
while (toSkip > 0) {
if (vecs[i].iov_len <= toSkip) {
toSkip -= vecs[i].iov_len;
if (vecs[i].length <= toSkip) {
toSkip -= vecs[i].length;
i++;
} else {
vecOffset = toSkip;
@@ -439,10 +443,10 @@ IOOperation::Prepare(IORequest* request)
if (HasPartialEnd()) {
// skip last block
size_t toSkip = fBlockSize;
generic_size_t toSkip = fBlockSize;
while (toSkip > 0) {
if (vecs[vecCount - 1].iov_len <= toSkip) {
toSkip -= vecs[vecCount - 1].iov_len;
if (vecs[vecCount - 1].length <= toSkip) {
toSkip -= vecs[vecCount - 1].length;
vecCount--;
} else
break;
@@ -452,9 +456,9 @@ IOOperation::Prepare(IORequest* request)
}
for (; i < vecCount; i++) {
const iovec& vec = vecs[i];
addr_t base = (addr_t)vec.iov_base + vecOffset;
size_t length = vec.iov_len - vecOffset;
const generic_io_vec& vec = vecs[i];
generic_addr_t base = vec.base + vecOffset;
generic_size_t length = vec.length - vecOffset;
vecOffset = 0;
if (base >= bounceBufferStart && base < bounceBufferEnd) {
@@ -488,7 +492,7 @@ IOOperation::Prepare(IORequest* request)
void
IOOperation::SetOriginalRange(off_t offset, size_t length)
IOOperation::SetOriginalRange(off_t offset, generic_size_t length)
{
fOriginalOffset = fOffset = offset;
fOriginalLength = fLength = length;
@@ -496,7 +500,7 @@ IOOperation::SetOriginalRange(off_t offset, size_t length)
void
IOOperation::SetRange(off_t offset, size_t length)
IOOperation::SetRange(off_t offset, generic_size_t length)
{
fOffset = offset;
fLength = length;
@@ -510,14 +514,14 @@ IOOperation::Offset() const
}
size_t
generic_size_t
IOOperation::Length() const
{
return fPhase == PHASE_DO_ALL ? fLength : fBlockSize;
}
iovec*
generic_io_vec*
IOOperation::Vecs() const
{
switch (fPhase) {
@@ -574,34 +578,33 @@ IOOperation::_PrepareVecs()
{
// we need to prepare the vecs for consumption by the drivers
if (fPhase == PHASE_READ_BEGIN) {
iovec* vecs = fDMABuffer->Vecs();
generic_io_vec* vecs = fDMABuffer->Vecs();
uint32 vecCount = fDMABuffer->VecCount();
size_t vecLength = fBlockSize;
generic_size_t vecLength = fBlockSize;
for (uint32 i = 0; i < vecCount; i++) {
iovec& vec = vecs[i];
if (vec.iov_len >= vecLength) {
generic_io_vec& vec = vecs[i];
if (vec.length >= vecLength) {
fSavedVecIndex = i;
fSavedVecLength = vec.iov_len;
vec.iov_len = vecLength;
fSavedVecLength = vec.length;
vec.length = vecLength;
break;
}
vecLength -= vec.iov_len;
vecLength -= vec.length;
}
} else if (fPhase == PHASE_READ_END) {
iovec* vecs = fDMABuffer->Vecs();
generic_io_vec* vecs = fDMABuffer->Vecs();
uint32 vecCount = fDMABuffer->VecCount();
size_t vecLength = fBlockSize;
generic_size_t vecLength = fBlockSize;
for (int32 i = vecCount - 1; i >= 0; i--) {
iovec& vec = vecs[i];
if (vec.iov_len >= vecLength) {
generic_io_vec& vec = vecs[i];
if (vec.length >= vecLength) {
fSavedVecIndex = i;
fSavedVecLength = vec.iov_len;
vec.iov_base = (uint8*)vec.iov_base
+ vec.iov_len - vecLength;
vec.iov_len = vecLength;
fSavedVecLength = vec.length;
vec.base += vec.length - vecLength;
vec.length = vecLength;
break;
}
vecLength -= vec.iov_len;
vecLength -= vec.length;
}
}
}
@@ -610,8 +613,8 @@ IOOperation::_PrepareVecs()
status_t
IOOperation::_CopyPartialBegin(bool isWrite, bool& singleBlockOnly)
{
size_t relativeOffset = OriginalOffset() - fOffset;
size_t length = fBlockSize - relativeOffset;
generic_size_t relativeOffset = OriginalOffset() - fOffset;
generic_size_t length = fBlockSize - relativeOffset;
singleBlockOnly = length >= OriginalLength();
if (singleBlockOnly)
@@ -636,14 +639,15 @@ IOOperation::_CopyPartialEnd(bool isWrite)
{
TRACE("_CopyPartialEnd(%s)\n", isWrite ? "write" : "read");
const iovec& lastVec = fDMABuffer->VecAt(fDMABuffer->VecCount() - 1);
const generic_io_vec& lastVec
= fDMABuffer->VecAt(fDMABuffer->VecCount() - 1);
off_t lastVecPos = fOffset + fLength - fBlockSize;
uint8* base = (uint8*)fDMABuffer->BounceBufferAddress()
+ ((addr_t)lastVec.iov_base + lastVec.iov_len - fBlockSize
+ (lastVec.base + lastVec.length - fBlockSize
- fDMABuffer->PhysicalBounceBufferAddress());
// NOTE: this won't work if we don't use the bounce buffer contiguously
// (because of boundary alignments).
size_t length = OriginalOffset() + OriginalLength() - lastVecPos;
generic_size_t length = OriginalOffset() + OriginalLength() - lastVecPos;
if (isWrite)
return fParent->CopyData(lastVecPos, base, length);
@@ -716,19 +720,20 @@ IORequest::Create(bool vip)
status_t
IORequest::Init(off_t offset, void* buffer, size_t length, bool write,
uint32 flags)
IORequest::Init(off_t offset, generic_addr_t buffer, generic_size_t length,
bool write, uint32 flags)
{
iovec vec;
vec.iov_base = buffer;
vec.iov_len = length;
generic_io_vec vec;
vec.base = buffer;
vec.length = length;
return Init(offset, &vec, 1, length, write, flags);
}
status_t
IORequest::Init(off_t offset, size_t firstVecOffset, const iovec* vecs,
size_t count, size_t length, bool write, uint32 flags)
IORequest::Init(off_t offset, generic_size_t firstVecOffset,
const generic_io_vec* vecs, size_t count, generic_size_t length, bool write,
uint32 flags)
{
fBuffer = IOBuffer::Create(count, (flags & B_VIP_IO_REQUEST) != 0);
if (fBuffer == NULL)
@@ -763,35 +768,35 @@ IORequest::Init(off_t offset, size_t firstVecOffset, const iovec* vecs,
status_t
IORequest::CreateSubRequest(off_t parentOffset, off_t offset, size_t length,
IORequest*& _subRequest)
IORequest::CreateSubRequest(off_t parentOffset, off_t offset,
generic_size_t length, IORequest*& _subRequest)
{
ASSERT(parentOffset >= fOffset && length <= fLength
&& parentOffset - fOffset <= fLength - length);
// find start vec
size_t vecOffset = parentOffset - fOffset;
iovec* vecs = fBuffer->Vecs();
generic_size_t vecOffset = parentOffset - fOffset;
generic_io_vec* vecs = fBuffer->Vecs();
int32 vecCount = fBuffer->VecCount();
int32 startVec = 0;
for (; startVec < vecCount; startVec++) {
const iovec& vec = vecs[startVec];
if (vecOffset < vec.iov_len)
const generic_io_vec& vec = vecs[startVec];
if (vecOffset < vec.length)
break;
vecOffset -= vec.iov_len;
vecOffset -= vec.length;
}
// count vecs
size_t currentVecOffset = vecOffset;
generic_size_t currentVecOffset = vecOffset;
int32 endVec = startVec;
size_t remainingLength = length;
generic_size_t remainingLength = length;
for (; endVec < vecCount; endVec++) {
const iovec& vec = vecs[endVec];
if (vec.iov_len - currentVecOffset >= remainingLength)
const generic_io_vec& vec = vecs[endVec];
if (vec.length - currentVecOffset >= remainingLength)
break;
remainingLength -= vec.iov_len - currentVecOffset;
remainingLength -= vec.length - currentVecOffset;
currentVecOffset = 0;
}
@@ -925,7 +930,8 @@ IORequest::NotifyFinished()
io_request_finished_callback finishedCallback = fFinishedCallback;
void* finishedCookie = fFinishedCookie;
status_t status = fStatus;
size_t lastTransferredOffset = fRelativeParentOffset + fTransferSize;
generic_size_t lastTransferredOffset
= fRelativeParentOffset + fTransferSize;
bool partialTransfer = status != B_OK || fPartialTransfer;
bool deleteRequest = (fFlags & B_DELETE_IO_REQUEST) != 0;
@@ -984,7 +990,7 @@ IORequest::SetStatusAndNotify(status_t status)
void
IORequest::OperationFinished(IOOperation* operation, status_t status,
bool partialTransfer, size_t transferEndOffset)
bool partialTransfer, generic_size_t transferEndOffset)
{
TRACE("IORequest::OperationFinished(%p, %#lx): request: %p\n", operation,
status, this);
@@ -1016,7 +1022,7 @@ IORequest::OperationFinished(IOOperation* operation, status_t status,
void
IORequest::SubRequestFinished(IORequest* request, status_t status,
bool partialTransfer, size_t transferEndOffset)
bool partialTransfer, generic_size_t transferEndOffset)
{
TRACE("IORequest::SubrequestFinished(%p, %#lx, %d, %lu): request: %p\n",
request, status, partialTransfer, transferEndOffset, this);
@@ -1056,7 +1062,8 @@ IORequest::SetUnfinished()
void
IORequest::SetTransferredBytes(bool partialTransfer, size_t transferredBytes)
IORequest::SetTransferredBytes(bool partialTransfer,
generic_size_t transferredBytes)
{
TRACE("%p->IORequest::SetTransferredBytes(%d, %lu)\n", this,
partialTransfer, transferredBytes);
@@ -1076,18 +1083,18 @@ IORequest::SetSuppressChildNotifications(bool suppress)
void
IORequest::Advance(size_t bySize)
IORequest::Advance(generic_size_t bySize)
{
TRACE("IORequest::Advance(%lu): remaining: %lu -> %lu\n", bySize,
fRemainingBytes, fRemainingBytes - bySize);
fRemainingBytes -= bySize;
fTransferSize += bySize;
iovec* vecs = fBuffer->Vecs();
generic_io_vec* vecs = fBuffer->Vecs();
uint32 vecCount = fBuffer->VecCount();
while (fVecIndex < vecCount
&& vecs[fVecIndex].iov_len - fVecOffset <= bySize) {
bySize -= vecs[fVecIndex].iov_len - fVecOffset;
&& vecs[fVecIndex].length - fVecOffset <= bySize) {
bySize -= vecs[fVecIndex].length - fVecOffset;
fVecOffset = 0;
fVecIndex++;
}
@@ -1170,24 +1177,24 @@ IORequest::_CopyData(void* _buffer, off_t offset, size_t size, bool copyIn)
}
// skip bytes if requested
iovec* vecs = fBuffer->Vecs();
size_t skipBytes = offset - fOffset;
size_t vecOffset = 0;
generic_io_vec* vecs = fBuffer->Vecs();
generic_size_t skipBytes = offset - fOffset;
generic_size_t vecOffset = 0;
while (skipBytes > 0) {
if (vecs[0].iov_len > skipBytes) {
if (vecs[0].length > skipBytes) {
vecOffset = skipBytes;
break;
}
skipBytes -= vecs[0].iov_len;
skipBytes -= vecs[0].length;
vecs++;
}
// copy iovec-wise
// copy vector-wise
while (size > 0) {
size_t toCopy = min_c(size, vecs[0].iov_len - vecOffset);
generic_size_t toCopy = min_c(size, vecs[0].length - vecOffset);
status_t error = copyFunction(buffer,
(uint8*)vecs[0].iov_base + vecOffset, toCopy, fTeam, copyIn);
(uint8*)vecs[0].base + vecOffset, toCopy, fTeam, copyIn);
if (error != B_OK)
return error;
+53 -48
View File
@@ -1,16 +1,17 @@
/*
* Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2008, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License.
*/
#ifndef IO_REQUEST_H
#define IO_REQUEST_H
#include <sys/uio.h>
#include <new>
#include <SupportDefs.h>
#include <fs_interface.h>
#include <condition_variable.h>
#include <lock.h>
@@ -38,25 +39,25 @@ public:
bool IsPhysical() const { return fPhysical; }
bool IsUser() const { return fUser; }
void SetVecs(size_t firstVecOffset,
const iovec* vecs, uint32 count,
size_t length, uint32 flags);
void SetVecs(generic_size_t firstVecOffset,
const generic_io_vec* vecs, uint32 count,
generic_size_t length, uint32 flags);
void SetPhysical(bool physical)
{ fPhysical = physical; }
void SetUser(bool user) { fUser = user; }
void SetLength(size_t length) { fLength = length; }
void SetLength(generic_size_t length)
{ fLength = length; }
void SetVecCount(uint32 count) { fVecCount = count; }
size_t Length() const { return fLength; }
generic_size_t Length() const { return fLength; }
iovec* Vecs() { return fVecs; }
iovec& VecAt(size_t index) { return fVecs[index]; }
generic_io_vec* Vecs() { return fVecs; }
generic_io_vec& VecAt(size_t index) { return fVecs[index]; }
size_t VecCount() const { return fVecCount; }
size_t Capacity() const { return fCapacity; }
status_t GetNextVirtualVec(void*& cookie,
iovec& vector);
status_t GetNextVirtualVec(void*& cookie, iovec& vector);
void FreeVirtualVecCookie(void* cookie);
status_t LockMemory(team_id team, bool isWrite);
@@ -77,10 +78,10 @@ private:
bool fPhysical;
bool fVIP;
bool fMemoryLocked;
size_t fLength;
generic_size_t fLength;
size_t fVecCount;
size_t fCapacity;
iovec fVecs[1];
generic_io_vec fVecs[1];
};
@@ -127,26 +128,27 @@ public:
// returns true, if it can be recycled
status_t Prepare(IORequest* request);
void SetOriginalRange(off_t offset, size_t length);
void SetOriginalRange(off_t offset,
generic_size_t length);
// also sets range
void SetRange(off_t offset, size_t length);
void SetRange(off_t offset, generic_size_t length);
void SetStatus(status_t status)
{ IORequestChunk::SetStatus(status); }
off_t Offset() const;
size_t Length() const;
generic_size_t Length() const;
off_t OriginalOffset() const
{ return fOriginalOffset; }
size_t OriginalLength() const
generic_size_t OriginalLength() const
{ return fOriginalLength; }
size_t TransferredBytes() const
generic_size_t TransferredBytes() const
{ return fTransferredBytes; }
void SetTransferredBytes(size_t bytes)
void SetTransferredBytes(generic_size_t bytes)
{ fTransferredBytes = bytes; }
iovec* Vecs() const;
generic_io_vec* Vecs() const;
uint32 VecCount() const;
void SetPartial(bool partialBegin, bool partialEnd);
@@ -157,7 +159,7 @@ public:
bool IsWrite() const;
bool IsRead() const;
void SetBlockSize(size_t blockSize)
void SetBlockSize(generic_size_t blockSize)
{ fBlockSize = blockSize; }
bool UsesBounceBuffer() const
@@ -180,10 +182,10 @@ protected:
DMABuffer* fDMABuffer;
off_t fOffset;
off_t fOriginalOffset;
size_t fLength;
size_t fOriginalLength;
size_t fTransferredBytes;
size_t fBlockSize;
generic_size_t fLength;
generic_size_t fOriginalLength;
generic_size_t fTransferredBytes;
generic_size_t fBlockSize;
uint16 fSavedVecIndex;
uint16 fSavedVecLength;
uint8 fPhase;
@@ -199,7 +201,7 @@ typedef DoublyLinkedList<IOOperation> IOOperationList;
typedef struct IORequest io_request;
typedef status_t (*io_request_finished_callback)(void* data,
io_request* request, status_t status, bool partialTransfer,
size_t transferEndOffset);
generic_size_t transferEndOffset);
// TODO: Return type: status_t -> void
typedef status_t (*io_request_iterate_callback)(void* data,
io_request* request, bool* _partialTransfer);
@@ -211,23 +213,26 @@ struct IORequest : IORequestChunk, DoublyLinkedListLinkImpl<IORequest> {
static IORequest* Create(bool vip);
status_t Init(off_t offset, void* buffer, size_t length,
bool write, uint32 flags);
status_t Init(off_t offset, const iovec* vecs,
size_t count, size_t length, bool write,
uint32 flags)
status_t Init(off_t offset, generic_addr_t buffer,
generic_size_t length, bool write,
uint32 flags);
status_t Init(off_t offset, const generic_io_vec* vecs,
size_t count, generic_size_t length,
bool write, uint32 flags)
{ return Init(offset, 0, vecs, count,
length, write, flags); }
status_t Init(off_t offset, size_t firstVecOffset,
const iovec* vecs, size_t count,
size_t length, bool write, uint32 flags);
status_t Init(off_t offset,
generic_size_t firstVecOffset,
const generic_io_vec* vecs, size_t count,
generic_size_t length, bool write,
uint32 flags);
void SetOwner(IORequestOwner* owner)
{ fOwner = owner; }
IORequestOwner* Owner() const { return fOwner; }
status_t CreateSubRequest(off_t parentOffset,
off_t offset, size_t length,
off_t offset, generic_size_t length,
IORequest*& subRequest);
void DeleteSubRequests();
@@ -251,20 +256,20 @@ struct IORequest : IORequestChunk, DoublyLinkedListLinkImpl<IORequest> {
void OperationFinished(IOOperation* operation,
status_t status, bool partialTransfer,
size_t transferEndOffset);
generic_size_t transferEndOffset);
void SubRequestFinished(IORequest* request,
status_t status, bool partialTransfer,
size_t transferEndOffset);
generic_size_t transferEndOffset);
void SetUnfinished();
size_t RemainingBytes() const
generic_size_t RemainingBytes() const
{ return fRemainingBytes; }
size_t TransferredBytes() const
generic_size_t TransferredBytes() const
{ return fTransferSize; }
bool IsPartialTransfer() const
{ return fPartialTransfer; }
void SetTransferredBytes(bool partialTransfer,
size_t transferredBytes);
generic_size_t transferredBytes);
void SetSuppressChildNotifications(bool suppress);
bool SuppressChildNotifications() const
@@ -278,14 +283,14 @@ struct IORequest : IORequestChunk, DoublyLinkedListLinkImpl<IORequest> {
IOBuffer* Buffer() const { return fBuffer; }
off_t Offset() const { return fOffset; }
size_t Length() const { return fLength; }
generic_size_t Length() const { return fLength; }
void SetOffset(off_t offset) { fOffset = offset; }
uint32 VecIndex() const { return fVecIndex; }
size_t VecOffset() const { return fVecOffset; }
generic_size_t VecOffset() const { return fVecOffset; }
void Advance(size_t bySize);
void Advance(generic_size_t bySize);
IORequest* FirstSubRequest();
IORequest* NextSubRequest(IORequest* previous);
@@ -315,13 +320,13 @@ private:
IORequestOwner* fOwner;
IOBuffer* fBuffer;
off_t fOffset;
size_t fLength;
size_t fTransferSize;
generic_size_t fLength;
generic_size_t fTransferSize;
// After all subrequests/operations have
// finished, number of contiguous bytes at
// the beginning of the request that have
// actually been transferred.
size_t fRelativeParentOffset;
generic_size_t fRelativeParentOffset;
// offset of this request relative to its
// parent
IORequestChunkList fChildren;
@@ -342,8 +347,8 @@ private:
// these are for iteration
uint32 fVecIndex;
size_t fVecOffset;
size_t fRemainingBytes;
generic_size_t fVecOffset;
generic_size_t fRemainingBytes;
};
@@ -53,8 +53,8 @@ public:
virtual void AbortRequest(IORequest* request,
status_t status = B_CANCELED) = 0;
virtual void OperationCompleted(IOOperation* operation,
status_t status, size_t transferredBytes)
= 0;
status_t status,
generic_size_t transferredBytes) = 0;
// called by the driver when the operation
// has been completed successfully or failed
// for some reason
@@ -284,7 +284,7 @@ IOSchedulerSimple::AbortRequest(IORequest* request, status_t status)
void
IOSchedulerSimple::OperationCompleted(IOOperation* operation, status_t status,
size_t transferredBytes)
generic_size_t transferredBytes)
{
InterruptsSpinLocker _(fFinisherLock);
@@ -295,7 +295,8 @@ IOSchedulerSimple::OperationCompleted(IOOperation* operation, status_t status,
operation->SetStatus(status);
// set the bytes transferred (of the net data)
size_t partialBegin = operation->OriginalOffset() - operation->Offset();
generic_size_t partialBegin
= operation->OriginalOffset() - operation->Offset();
operation->SetTransferredBytes(
transferredBytes > partialBegin ? transferredBytes - partialBegin : 0);
@@ -353,7 +354,7 @@ IOSchedulerSimple::_Finisher()
// notify request and remove operation
IORequest* request = operation->Parent();
if (request != NULL) {
size_t operationOffset = operation->OriginalOffset()
generic_size_t operationOffset = operation->OriginalOffset()
- request->Offset();
request->OperationFinished(operation, operation->Status(),
operation->TransferredBytes() < operation->OriginalLength(),
@@ -29,7 +29,8 @@ public:
virtual void AbortRequest(IORequest* request,
status_t status = B_CANCELED);
virtual void OperationCompleted(IOOperation* operation,
status_t status, size_t transferredBytes);
status_t status,
generic_size_t transferredBytes);
// called by the driver when the operation
// has been completed successfully or failed
// for some reason
@@ -84,7 +85,7 @@ private:
RequestOwnerList fActiveRequestOwners;
RequestOwnerList fUnusedRequestOwners;
RequestOwnerHashTable* fRequestOwners;
size_t fBlockSize;
generic_size_t fBlockSize;
int32 fPendingOperations;
off_t fIterationBandwidth;
off_t fMinOwnerBandwidth;
@@ -4,6 +4,7 @@
* Distributed under the terms of the MIT License.
*/
#include "dma_resources.h"
#include <device_manager.h>
@@ -24,14 +25,14 @@
extern device_manager_info gDeviceManagerModule;
const size_t kMaxBounceBufferSize = 4 * B_PAGE_SIZE;
const phys_size_t kMaxBounceBufferSize = 4 * B_PAGE_SIZE;
DMABuffer*
DMABuffer::Create(size_t count)
{
DMABuffer* buffer = (DMABuffer*)malloc(
sizeof(DMABuffer) + sizeof(iovec) * (count - 1));
sizeof(DMABuffer) + sizeof(generic_io_vec) * (count - 1));
if (buffer == NULL)
return NULL;
@@ -49,11 +50,11 @@ DMABuffer::SetVecCount(uint32 count)
void
DMABuffer::AddVec(void* base, size_t size)
DMABuffer::AddVec(generic_addr_t base, generic_size_t size)
{
iovec& vec = fVecs[fVecCount++];
vec.iov_base = base;
vec.iov_len = size;
generic_io_vec& vec = fVecs[fVecCount++];
vec.base = base;
vec.length = size;
}
@@ -63,8 +64,8 @@ DMABuffer::UsesBounceBufferAt(uint32 index)
if (index >= fVecCount || fBounceBuffer == NULL)
return false;
return (addr_t)fVecs[index].iov_base >= fBounceBuffer->physical_address
&& (addr_t)fVecs[index].iov_base
return fVecs[index].base >= fBounceBuffer->physical_address
&& fVecs[index].base
< fBounceBuffer->physical_address + fBounceBuffer->size;
}
@@ -80,7 +81,8 @@ DMABuffer::Dump() const
kprintf(" vecs: %lu\n", fVecCount);
for (uint32 i = 0; i < fVecCount; i++) {
kprintf(" [%lu] %p, %lu\n", i, fVecs[i].iov_base, fVecs[i].iov_len);
kprintf(" [%" B_PRIu32 "] %#" B_PRIxGENADDR ", %" B_PRIuGENADDR "\n",
i, fVecs[i].base, fVecs[i].length);
}
}
@@ -104,8 +106,8 @@ DMAResource::~DMAResource()
status_t
DMAResource::Init(device_node* node, size_t blockSize, uint32 bufferCount,
uint32 bounceBufferCount)
DMAResource::Init(device_node* node, generic_size_t blockSize,
uint32 bufferCount, uint32 bounceBufferCount)
{
dma_restrictions restrictions;
memset(&restrictions, 0, sizeof(dma_restrictions));
@@ -138,8 +140,8 @@ DMAResource::Init(device_node* node, size_t blockSize, uint32 bufferCount,
status_t
DMAResource::Init(const dma_restrictions& restrictions, size_t blockSize,
uint32 bufferCount, uint32 bounceBufferCount)
DMAResource::Init(const dma_restrictions& restrictions,
generic_size_t blockSize, uint32 bufferCount, uint32 bounceBufferCount)
{
fRestrictions = restrictions;
fBlockSize = blockSize == 0 ? 1 : blockSize;
@@ -148,15 +150,15 @@ DMAResource::Init(const dma_restrictions& restrictions, size_t blockSize,
fBounceBufferSize = 0;
if (fRestrictions.high_address == 0)
fRestrictions.high_address = ~(addr_t)0;
fRestrictions.high_address = ~(generic_addr_t)0;
if (fRestrictions.max_segment_count == 0)
fRestrictions.max_segment_count = 16;
if (fRestrictions.alignment == 0)
fRestrictions.alignment = 1;
if (fRestrictions.max_transfer_size == 0)
fRestrictions.max_transfer_size = ~(size_t)0;
fRestrictions.max_transfer_size = ~(generic_size_t)0;
if (fRestrictions.max_segment_size == 0)
fRestrictions.max_segment_size = ~(size_t)0;
fRestrictions.max_segment_size = ~(generic_size_t)0;
if (_NeedsBoundsBuffers()) {
fBounceBufferSize = fRestrictions.max_segment_size
@@ -174,8 +176,8 @@ DMAResource::Init(const dma_restrictions& restrictions, size_t blockSize,
fRestrictions.boundary, fRestrictions.max_transfer_size,
fRestrictions.max_segment_size);
fScratchVecs = (iovec*)malloc(
sizeof(iovec) * fRestrictions.max_segment_count);
fScratchVecs = (generic_io_vec*)malloc(
sizeof(generic_io_vec) * fRestrictions.max_segment_count);
if (fScratchVecs == NULL)
return B_NO_MEMORY;
@@ -218,9 +220,9 @@ status_t
DMAResource::CreateBounceBuffer(DMABounceBuffer** _buffer)
{
void* bounceBuffer = NULL;
addr_t physicalBase = 0;
phys_addr_t physicalBase = 0;
area_id area = -1;
size_t size = ROUNDUP(fBounceBufferSize, B_PAGE_SIZE);
phys_size_t size = ROUNDUP(fBounceBufferSize, B_PAGE_SIZE);
if (fRestrictions.alignment > B_PAGE_SIZE)
dprintf("dma buffer restrictions not yet implemented: alignment %lu\n", fRestrictions.alignment);
@@ -264,12 +266,13 @@ DMAResource::CreateBounceBuffer(DMABounceBuffer** _buffer)
inline void
DMAResource::_RestrictBoundaryAndSegmentSize(addr_t base, addr_t& length)
DMAResource::_RestrictBoundaryAndSegmentSize(generic_addr_t base,
generic_addr_t& length)
{
if (length > fRestrictions.max_segment_size)
length = fRestrictions.max_segment_size;
if (fRestrictions.boundary > 0) {
addr_t baseBoundary = base / fRestrictions.boundary;
generic_addr_t baseBoundary = base / fRestrictions.boundary;
if (baseBoundary
!= (base + (length - 1)) / fRestrictions.boundary) {
length = (baseBoundary + 1) * fRestrictions.boundary - base;
@@ -279,13 +282,13 @@ DMAResource::_RestrictBoundaryAndSegmentSize(addr_t base, addr_t& length)
void
DMAResource::_CutBuffer(DMABuffer& buffer, addr_t& physicalBounceBuffer,
size_t& bounceLeft, size_t toCut)
DMAResource::_CutBuffer(DMABuffer& buffer, phys_addr_t& physicalBounceBuffer,
phys_size_t& bounceLeft, generic_size_t toCut)
{
int32 vecCount = buffer.VecCount();
for (int32 i = vecCount - 1; toCut > 0 && i >= 0; i--) {
iovec& vec = buffer.VecAt(i);
size_t length = vec.iov_len;
generic_io_vec& vec = buffer.VecAt(i);
generic_size_t length = vec.length;
bool inBounceBuffer = buffer.UsesBounceBufferAt(i);
if (length <= toCut) {
@@ -297,7 +300,7 @@ DMAResource::_CutBuffer(DMABuffer& buffer, addr_t& physicalBounceBuffer,
physicalBounceBuffer -= length;
}
} else {
vec.iov_len -= toCut;
vec.length -= toCut;
if (inBounceBuffer) {
bounceLeft += toCut;
@@ -321,9 +324,10 @@ DMAResource::_CutBuffer(DMABuffer& buffer, addr_t& physicalBounceBuffer,
TODO: is that what we want here?
\return >0 the number of bytes added to the buffer.
*/
size_t
DMAResource::_AddBounceBuffer(DMABuffer& buffer, addr_t& physicalBounceBuffer,
size_t& bounceLeft, size_t length, bool fixedLength)
phys_size_t
DMAResource::_AddBounceBuffer(DMABuffer& buffer,
phys_addr_t& physicalBounceBuffer, phys_size_t& bounceLeft,
generic_size_t length, bool fixedLength)
{
if (bounceLeft < length) {
if (fixedLength)
@@ -332,27 +336,27 @@ DMAResource::_AddBounceBuffer(DMABuffer& buffer, addr_t& physicalBounceBuffer,
length = bounceLeft;
}
size_t bounceUsed = 0;
phys_size_t bounceUsed = 0;
uint32 vecCount = buffer.VecCount();
if (vecCount > 0) {
// see if we can join the bounce buffer with the previously last vec
iovec& vec = buffer.VecAt(vecCount - 1);
addr_t vecBase = (addr_t)vec.iov_base;
size_t vecLength = vec.iov_len;
generic_io_vec& vec = buffer.VecAt(vecCount - 1);
generic_addr_t vecBase = vec.base;
generic_size_t vecLength = vec.length;
if (vecBase + vecLength == physicalBounceBuffer) {
vecLength += length;
_RestrictBoundaryAndSegmentSize(vecBase, vecLength);
size_t lengthDiff = vecLength - vec.iov_len;
generic_size_t lengthDiff = vecLength - vec.length;
length -= lengthDiff;
physicalBounceBuffer += lengthDiff;
bounceLeft -= lengthDiff;
bounceUsed += lengthDiff;
vec.iov_len = vecLength;
vec.length = vecLength;
}
}
@@ -362,10 +366,10 @@ DMAResource::_AddBounceBuffer(DMABuffer& buffer, addr_t& physicalBounceBuffer,
if (vecCount == fRestrictions.max_segment_count)
return fixedLength ? 0 : bounceUsed;
addr_t vecLength = length;
generic_addr_t vecLength = length;
_RestrictBoundaryAndSegmentSize(physicalBounceBuffer, vecLength);
buffer.AddVec((void*)physicalBounceBuffer, vecLength);
buffer.AddVec(physicalBounceBuffer, vecLength);
vecCount++;
physicalBounceBuffer += vecLength;
@@ -380,18 +384,18 @@ DMAResource::_AddBounceBuffer(DMABuffer& buffer, addr_t& physicalBounceBuffer,
status_t
DMAResource::TranslateNext(IORequest* request, IOOperation* operation,
size_t maxOperationLength)
generic_size_t maxOperationLength)
{
IOBuffer* buffer = request->Buffer();
off_t originalOffset = request->Offset() + request->Length()
- request->RemainingBytes();
off_t offset = originalOffset;
size_t partialBegin = offset & (fBlockSize - 1);
generic_size_t partialBegin = offset & (fBlockSize - 1);
// current iteration state
uint32 vecIndex = request->VecIndex();
uint32 vecOffset = request->VecOffset();
size_t totalLength = min_c(request->RemainingBytes(),
generic_size_t totalLength = min_c(request->RemainingBytes(),
fRestrictions.max_transfer_size);
if (maxOperationLength > 0
@@ -407,7 +411,7 @@ DMAResource::TranslateNext(IORequest* request, IOOperation* operation,
dmaBuffer->SetVecCount(0);
iovec* vecs = NULL;
generic_io_vec* vecs = NULL;
uint32 segmentCount = 0;
TRACE(" offset %Ld, remaining size: %lu, block size %lu -> partial: %lu\n",
@@ -421,14 +425,14 @@ DMAResource::TranslateNext(IORequest* request, IOOperation* operation,
// TODO: !partialOperation || totalLength >= fBlockSize
// TODO: Maybe enforce fBounceBufferSize >= 2 * fBlockSize.
if (true) {
size_t transferLeft = totalLength;
generic_size_t transferLeft = totalLength;
vecs = fScratchVecs;
TRACE(" create physical map (for %ld vecs)\n", buffer->VecCount());
for (uint32 i = vecIndex; i < buffer->VecCount(); i++) {
iovec& vec = buffer->VecAt(i);
addr_t base = (addr_t)vec.iov_base + vecOffset;
size_t size = vec.iov_len - vecOffset;
generic_io_vec& vec = buffer->VecAt(i);
generic_addr_t base = vec.base + vecOffset;
generic_size_t size = vec.length - vecOffset;
vecOffset = 0;
if (size > transferLeft)
size = transferLeft;
@@ -440,8 +444,8 @@ DMAResource::TranslateNext(IORequest* request, IOOperation* operation,
get_memory_map_etc(request->Team(), (void*)base, size,
&entry, &count);
vecs[segmentCount].iov_base = (void*)(addr_t)entry.address;
vecs[segmentCount].iov_len = entry.size;
vecs[segmentCount].base = entry.address;
vecs[segmentCount].length = entry.size;
transferLeft -= entry.size;
base += entry.size;
@@ -469,8 +473,8 @@ DMAResource::TranslateNext(IORequest* request, IOOperation* operation,
#ifdef TRACE_DMA_RESOURCE
TRACE(" physical count %lu\n", segmentCount);
for (uint32 i = 0; i < segmentCount; i++) {
TRACE(" [%lu] %p, %lu\n", i, vecs[vecIndex + i].iov_base,
vecs[vecIndex + i].iov_len);
TRACE(" [%" B_PRIu32 "] %#" B_PRIxGENADDR ", %" B_PRIxGENADDR "\n",
i, vecs[vecIndex + i].base, vecs[vecIndex + i].length);
}
#endif
@@ -486,15 +490,15 @@ DMAResource::TranslateNext(IORequest* request, IOOperation* operation,
}
dmaBuffer->SetBounceBuffer(bounceBuffer);
size_t dmaLength = 0;
addr_t physicalBounceBuffer = dmaBuffer->PhysicalBounceBufferAddress();
size_t bounceLeft = fBounceBufferSize;
size_t transferLeft = totalLength;
generic_size_t dmaLength = 0;
phys_addr_t physicalBounceBuffer = dmaBuffer->PhysicalBounceBufferAddress();
phys_size_t bounceLeft = fBounceBufferSize;
generic_size_t transferLeft = totalLength;
// If the offset isn't block-aligned, use the bounce buffer to bridge the
// gap to the start of the vec.
if (partialBegin > 0) {
size_t length;
generic_size_t length;
if (request->IsWrite()) {
// we always need to read in a whole block for the partial write
length = fBlockSize;
@@ -511,7 +515,7 @@ DMAResource::TranslateNext(IORequest* request, IOOperation* operation,
dmaLength += length;
size_t transferred = length - partialBegin;
generic_size_t transferred = length - partialBegin;
vecOffset += transferred;
offset -= partialBegin;
@@ -529,18 +533,18 @@ DMAResource::TranslateNext(IORequest* request, IOOperation* operation,
if (dmaBuffer->VecCount() >= fRestrictions.max_segment_count)
break;
const iovec& vec = vecs[i];
if (vec.iov_len <= vecOffset) {
vecOffset -= vec.iov_len;
const generic_io_vec& vec = vecs[i];
if (vec.length <= vecOffset) {
vecOffset -= vec.length;
i++;
continue;
}
addr_t base = (addr_t)vec.iov_base + vecOffset;
size_t maxLength = vec.iov_len - vecOffset;
generic_addr_t base = vec.base + vecOffset;
generic_size_t maxLength = vec.length - vecOffset;
if (maxLength > transferLeft)
maxLength = transferLeft;
size_t length = maxLength;
generic_size_t length = maxLength;
// Cut the vec according to transfer size, segment size, and boundary.
@@ -551,7 +555,7 @@ DMAResource::TranslateNext(IORequest* request, IOOperation* operation,
}
_RestrictBoundaryAndSegmentSize(base, length);
size_t useBounceBufferSize = 0;
phys_size_t useBounceBufferSize = 0;
// Check low address: use bounce buffer for range to low address.
// Check alignment: if not aligned, use bounce buffer for complete vec.
@@ -599,7 +603,7 @@ DMAResource::TranslateNext(IORequest* request, IOOperation* operation,
TRACE(" vec %lu: final bounce length: %lu\n", i, length);
} else {
TRACE(" vec %lu: final length restriction: %lu\n", i, length);
dmaBuffer->AddVec((void*)base, length);
dmaBuffer->AddVec(base, length);
}
dmaLength += length;
@@ -612,7 +616,7 @@ DMAResource::TranslateNext(IORequest* request, IOOperation* operation,
// the first phase).
off_t requestEnd = request->Offset() + request->Length();
if (request->IsWrite()) {
size_t diff = dmaLength & (fBlockSize - 1);
generic_size_t diff = dmaLength & (fBlockSize - 1);
// If the transfer length is block aligned and we're writing past the
// end of the given data, we still have to check the whether the last
@@ -620,16 +624,16 @@ DMAResource::TranslateNext(IORequest* request, IOOperation* operation,
// have to cut back the complete block and use a bounce buffer for it
// entirely.
if (diff == 0 && offset + dmaLength > requestEnd) {
const iovec& dmaVec = dmaBuffer->VecAt(dmaBuffer->VecCount() - 1);
ASSERT((addr_t)dmaVec.iov_base
>= dmaBuffer->PhysicalBounceBufferAddress()
&& (addr_t)dmaVec.iov_base
const generic_io_vec& dmaVec
= dmaBuffer->VecAt(dmaBuffer->VecCount() - 1);
ASSERT(dmaVec.base >= dmaBuffer->PhysicalBounceBufferAddress()
&& dmaVec.base
< dmaBuffer->PhysicalBounceBufferAddress()
+ fBounceBufferSize);
// We can be certain that the last vec is a bounce buffer vec,
// since otherwise the DMA buffer couldn't exceed the end of the
// request data.
if (dmaVec.iov_len < fBlockSize)
if (dmaVec.length < fBlockSize)
diff = fBlockSize;
}
@@ -657,7 +661,8 @@ DMAResource::TranslateNext(IORequest* request, IOOperation* operation,
// case only).
while ((dmaLength & (fBlockSize - 1)) != 0) {
TRACE(" dmaLength not block aligned: %lu\n", dmaLength);
size_t length = (dmaLength + fBlockSize - 1) & ~(fBlockSize - 1);
generic_size_t length
= (dmaLength + fBlockSize - 1) & ~(fBlockSize - 1);
// If total length > max transfer size, segment count > max segment
// count, truncate.
@@ -669,7 +674,7 @@ DMAResource::TranslateNext(IORequest* request, IOOperation* operation,
// cut the part of dma length
TRACE(" can't align length due to max transfer size, segment "
"count restrictions, or lacking bounce buffer space\n");
size_t toCut = dmaLength
generic_size_t toCut = dmaLength
& (max_c(fBlockSize, fRestrictions.alignment) - 1);
dmaLength -= toCut;
if (dmaLength == 0) {
@@ -677,11 +682,11 @@ DMAResource::TranslateNext(IORequest* request, IOOperation* operation,
// and hit the max segment count. In this case we just use the
// bounce buffer for as much as possible of the total length.
dmaBuffer->SetVecCount(0);
addr_t base = dmaBuffer->PhysicalBounceBufferAddress();
generic_addr_t base = dmaBuffer->PhysicalBounceBufferAddress();
dmaLength = min_c(totalLength, fBounceBufferSize)
& ~(max_c(fBlockSize, fRestrictions.alignment) - 1);
_RestrictBoundaryAndSegmentSize(base, dmaLength);
dmaBuffer->AddVec((void*)base, dmaLength);
dmaBuffer->AddVec(base, dmaLength);
physicalBounceBuffer = base + dmaLength;
bounceLeft = fBounceBufferSize - dmaLength;
@@ -745,7 +750,7 @@ DMAResource::_NeedsBoundsBuffers() const
{
return fRestrictions.alignment > 1
|| fRestrictions.low_address != 0
|| fRestrictions.high_address != ~(addr_t)0
|| fRestrictions.high_address != ~(generic_addr_t)0
|| fBlockSize > 1;
}
@@ -1,13 +1,16 @@
/*
* Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2008, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License.
*/
#ifndef DMA_RESOURCES_H
#define DMA_RESOURCES_H
#include <sys/uio.h>
#include <fs_interface.h>
#include <lock.h>
#include <util/DoublyLinkedList.h>
@@ -17,22 +20,28 @@ struct IOOperation;
struct IORequest;
typedef struct generic_io_vec {
generic_addr_t base;
generic_size_t length;
} generic_io_vec;
struct dma_restrictions {
addr_t low_address;
addr_t high_address;
size_t alignment;
size_t boundary;
size_t max_transfer_size;
uint32 max_segment_count;
size_t max_segment_size;
uint32 flags;
generic_addr_t low_address;
generic_addr_t high_address;
generic_size_t alignment;
generic_size_t boundary;
generic_size_t max_transfer_size;
uint32 max_segment_count;
generic_size_t max_segment_size;
uint32 flags;
};
struct DMABounceBuffer : public DoublyLinkedListLinkImpl<DMABounceBuffer> {
void* address;
addr_t physical_address;
size_t size;
void* address;
phys_addr_t physical_address;
phys_size_t size;
};
typedef DoublyLinkedList<DMABounceBuffer> DMABounceBufferList;
@@ -42,12 +51,13 @@ class DMABuffer : public DoublyLinkedListLinkImpl<DMABuffer> {
public:
static DMABuffer* Create(size_t count);
iovec* Vecs() { return fVecs; }
iovec& VecAt(size_t index) { return fVecs[index]; }
generic_io_vec* Vecs() { return fVecs; }
generic_io_vec& VecAt(size_t index) { return fVecs[index]; }
uint32 VecCount() const { return fVecCount; }
void SetVecCount(uint32 count);
void AddVec(void* base, size_t size);
void AddVec(generic_addr_t base,
generic_size_t size);
void SetBounceBuffer(DMABounceBuffer* bounceBuffer)
{ fBounceBuffer = bounceBuffer; }
@@ -56,11 +66,11 @@ public:
void* BounceBufferAddress() const
{ return fBounceBuffer
? fBounceBuffer->address : NULL; }
addr_t PhysicalBounceBufferAddress() const
phys_addr_t PhysicalBounceBufferAddress() const
{ return fBounceBuffer
? fBounceBuffer->physical_address
: 0; }
size_t BounceBufferSize() const
phys_size_t BounceBufferSize() const
{ return fBounceBuffer
? fBounceBuffer->size : 0; }
@@ -71,7 +81,7 @@ public:
private:
DMABounceBuffer* fBounceBuffer;
uint32 fVecCount;
iovec fVecs[1];
generic_io_vec fVecs[1];
};
@@ -84,9 +94,11 @@ public:
~DMAResource();
status_t Init(const dma_restrictions& restrictions,
size_t blockSize, uint32 bufferCount,
generic_size_t blockSize,
uint32 bufferCount,
uint32 bounceBufferCount);
status_t Init(device_node* node, size_t blockSize,
status_t Init(device_node* node,
generic_size_t blockSize,
uint32 bufferCount,
uint32 bounceBufferCount);
@@ -95,33 +107,35 @@ public:
status_t TranslateNext(IORequest* request,
IOOperation* operation,
size_t maxOperationLength);
generic_size_t maxOperationLength);
void RecycleBuffer(DMABuffer* buffer);
size_t BlockSize() const { return fBlockSize; }
generic_size_t BlockSize() const { return fBlockSize; }
uint32 BufferCount() const { return fBufferCount; }
private:
bool _NeedsBoundsBuffers() const;
void _RestrictBoundaryAndSegmentSize(addr_t base,
addr_t& length);
void _RestrictBoundaryAndSegmentSize(
generic_addr_t base,
generic_addr_t& length);
void _CutBuffer(DMABuffer& buffer,
addr_t& physicalBounceBuffer,
size_t& bounceLeft, size_t toCut);
size_t _AddBounceBuffer(DMABuffer& buffer,
addr_t& physicalBounceBuffer,
size_t& bounceLeft, size_t length,
bool fixedLength);
phys_addr_t& physicalBounceBuffer,
phys_size_t& bounceLeft,
generic_size_t toCut);
phys_size_t _AddBounceBuffer(DMABuffer& buffer,
phys_addr_t& physicalBounceBuffer,
phys_size_t& bounceLeft,
generic_size_t length, bool fixedLength);
mutex fLock;
dma_restrictions fRestrictions;
size_t fBlockSize;
generic_size_t fBlockSize;
uint32 fBufferCount;
uint32 fBounceBufferCount;
size_t fBounceBufferSize;
phys_size_t fBounceBufferSize;
DMABufferList fDMABuffers;
DMABounceBufferList fBounceBuffers;
iovec* fScratchVecs;
generic_io_vec* fScratchVecs;
};
#endif // DMA_RESOURCES_H
+10 -6
View File
@@ -3892,6 +3892,7 @@ volume_for_vnode(fs_vnode* _vnode)
}
#if 0
extern "C" status_t
read_pages(int fd, off_t pos, const iovec* vecs, size_t count,
size_t* _numBytes)
@@ -3928,6 +3929,7 @@ write_pages(int fd, off_t pos, const iovec* vecs, size_t count,
put_fd(descriptor);
return status;
}
#endif
extern "C" status_t
@@ -4495,14 +4497,15 @@ vfs_can_page(struct vnode* vnode, void* cookie)
extern "C" status_t
vfs_read_pages(struct vnode* vnode, void* cookie, off_t pos, const iovec* vecs,
size_t count, uint32 flags, size_t* _numBytes)
vfs_read_pages(struct vnode* vnode, void* cookie, off_t pos,
const generic_io_vec* vecs, size_t count, uint32 flags,
generic_size_t* _numBytes)
{
FUNCTION(("vfs_read_pages: vnode %p, vecs %p, pos %Ld\n", vnode, vecs,
pos));
#if VFS_PAGES_IO_TRACING
size_t bytesRequested = *_numBytes;
generic_size_t bytesRequested = *_numBytes;
#endif
IORequest request;
@@ -4522,14 +4525,15 @@ vfs_read_pages(struct vnode* vnode, void* cookie, off_t pos, const iovec* vecs,
extern "C" status_t
vfs_write_pages(struct vnode* vnode, void* cookie, off_t pos, const iovec* vecs,
size_t count, uint32 flags, size_t* _numBytes)
vfs_write_pages(struct vnode* vnode, void* cookie, off_t pos,
const generic_io_vec* vecs, size_t count, uint32 flags,
generic_size_t* _numBytes)
{
FUNCTION(("vfs_write_pages: vnode %p, vecs %p, pos %Ld\n", vnode, vecs,
pos));
#if VFS_PAGES_IO_TRACING
size_t bytesRequested = *_numBytes;
generic_size_t bytesRequested = *_numBytes;
#endif
IORequest request;
+8 -8
View File
@@ -27,7 +27,7 @@ AsyncIOCallback::~AsyncIOCallback()
/* static */ status_t
AsyncIOCallback::IORequestCallback(void* data, io_request* request,
status_t status, bool partialTransfer, size_t transferEndOffset)
status_t status, bool partialTransfer, generic_size_t transferEndOffset)
{
((AsyncIOCallback*)data)->IOFinished(status, partialTransfer,
transferEndOffset);
@@ -259,14 +259,14 @@ do_synchronous_iterative_vnode_io(struct vnode* vnode, void* openCookie,
iovec vector;
void* virtualVecCookie = NULL;
off_t offset = request->Offset();
size_t length = request->Length();
generic_size_t length = request->Length();
status_t error = B_OK;
for (; error == B_OK && length > 0
&& buffer->GetNextVirtualVec(virtualVecCookie, vector) == B_OK;) {
uint8* vecBase = (uint8*)vector.iov_base;
size_t vecLength = min_c(vector.iov_len, length);
generic_size_t vecLength = min_c(vector.iov_len, length);
while (error == B_OK && vecLength > 0) {
file_io_vec fileVecs[8];
@@ -317,17 +317,17 @@ synchronous_io(io_request* request, DoIO& io)
iovec vector;
void* virtualVecCookie = NULL;
off_t offset = request->Offset();
size_t length = request->Length();
generic_size_t length = request->Length();
for (; length > 0
&& buffer->GetNextVirtualVec(virtualVecCookie, vector) == B_OK;) {
void* vecBase = vector.iov_base;
void* vecBase = (void*)(addr_t)vector.iov_base;
size_t vecLength = min_c(vector.iov_len, length);
TRACE_RIO("[%ld] I/O: offset: %lld, vecBase: %p, length: %lu\n",
find_thread(NULL), offset, vecBase, vecLength);
size_t transferred = vecLength;
generic_size_t transferred = vecLength;
status_t error = io.IO(offset, vecBase, &transferred);
if (error != B_OK) {
TRACE_RIO("[%ld] I/O failed: %#lx\n", find_thread(NULL), error);
@@ -382,7 +382,7 @@ vfs_synchronous_io(io_request* request,
status_t
vfs_asynchronous_read_pages(struct vnode* vnode, void* cookie, off_t pos,
const iovec* vecs, size_t count, size_t numBytes, uint32 flags,
const generic_io_vec* vecs, size_t count, size_t numBytes, uint32 flags,
AsyncIOCallback* callback)
{
IORequest* request = IORequest::Create((flags & B_VIP_IO_REQUEST) != 0);
@@ -408,7 +408,7 @@ vfs_asynchronous_read_pages(struct vnode* vnode, void* cookie, off_t pos,
status_t
vfs_asynchronous_write_pages(struct vnode* vnode, void* cookie, off_t pos,
const iovec* vecs, size_t count, size_t numBytes, uint32 flags,
const generic_io_vec* vecs, size_t count, size_t numBytes, uint32 flags,
AsyncIOCallback* callback)
{
IORequest* request = IORequest::Create((flags & B_VIP_IO_REQUEST) != 0);
+21 -20
View File
@@ -390,7 +390,7 @@ public:
}
virtual void IOFinished(status_t status, bool partialTransfer,
size_t bytesTransferred)
generic_size_t bytesTransferred)
{
if (fNewSlot) {
if (status == B_OK) {
@@ -568,8 +568,8 @@ VMAnonymousCache::DebugHasPage(off_t offset)
status_t
VMAnonymousCache::Read(off_t offset, const iovec* vecs, size_t count,
uint32 flags, size_t* _numBytes)
VMAnonymousCache::Read(off_t offset, const generic_io_vec* vecs, size_t count,
uint32 flags, generic_size_t* _numBytes)
{
off_t pageIndex = offset >> PAGE_SHIFT;
@@ -600,16 +600,16 @@ VMAnonymousCache::Read(off_t offset, const iovec* vecs, size_t count,
status_t
VMAnonymousCache::Write(off_t offset, const iovec* vecs, size_t count,
uint32 flags, size_t* _numBytes)
VMAnonymousCache::Write(off_t offset, const generic_io_vec* vecs, size_t count,
uint32 flags, generic_size_t* _numBytes)
{
off_t pageIndex = offset >> PAGE_SHIFT;
AutoLocker<VMCache> locker(this);
uint32 totalPages = 0;
page_num_t totalPages = 0;
for (uint32 i = 0; i < count; i++) {
uint32 pageCount = (vecs[i].iov_len + B_PAGE_SIZE - 1) >> PAGE_SHIFT;
page_num_t pageCount = (vecs[i].length + B_PAGE_SIZE - 1) >> PAGE_SHIFT;
swap_addr_t slotIndex = _SwapBlockGetAddress(pageIndex + totalPages);
if (slotIndex != SWAP_SLOT_NONE) {
swap_slot_dealloc(slotIndex, pageCount);
@@ -627,17 +627,17 @@ VMAnonymousCache::Write(off_t offset, const iovec* vecs, size_t count,
fAllocatedSwapSize += totalSize;
locker.Unlock();
uint32 pagesLeft = totalPages;
page_num_t pagesLeft = totalPages;
totalPages = 0;
for (uint32 i = 0; i < count; i++) {
uint32 pageCount = (vecs[i].iov_len + B_PAGE_SIZE - 1) >> PAGE_SHIFT;
page_num_t pageCount = (vecs[i].length + B_PAGE_SIZE - 1) >> PAGE_SHIFT;
void* vectorBase = vecs[i].iov_base;
size_t vectorLength = vecs[i].iov_len;
uint32 n = pageCount;
generic_addr_t vectorBase = vecs[i].base;
generic_size_t vectorLength = vecs[i].length;
page_num_t n = pageCount;
for (uint32 j = 0; j < pageCount; j += n) {
for (page_num_t j = 0; j < pageCount; j += n) {
swap_addr_t slotIndex;
// try to allocate n slots, if fail, try to allocate n/2
while ((slotIndex = swap_slot_alloc(n)) == SWAP_SLOT_NONE && n >= 2)
@@ -653,10 +653,10 @@ VMAnonymousCache::Write(off_t offset, const iovec* vecs, size_t count,
off_t pos = (off_t)(slotIndex - swapFile->first_slot) * B_PAGE_SIZE;
size_t length = n * B_PAGE_SIZE;
iovec vector[1];
vector->iov_base = vectorBase;
vector->iov_len = length;
generic_size_t length = (phys_addr_t)n * B_PAGE_SIZE;
generic_io_vec vector[1];
vector->base = vectorBase;
vector->length = length;
status_t status = vfs_write_pages(swapFile->vnode, swapFile->cookie,
pos, vector, 1, flags, &length);
@@ -673,7 +673,7 @@ VMAnonymousCache::Write(off_t offset, const iovec* vecs, size_t count,
pagesLeft -= n;
if (n != pageCount) {
vectorBase = (void*)((addr_t)vectorBase + n * B_PAGE_SIZE);
vectorBase = vectorBase + n * B_PAGE_SIZE;
vectorLength -= n * B_PAGE_SIZE;
}
}
@@ -687,8 +687,9 @@ VMAnonymousCache::Write(off_t offset, const iovec* vecs, size_t count,
status_t
VMAnonymousCache::WriteAsync(off_t offset, const iovec* vecs, size_t count,
size_t numBytes, uint32 flags, AsyncIOCallback* _callback)
VMAnonymousCache::WriteAsync(off_t offset, const generic_io_vec* vecs,
size_t count, generic_size_t numBytes, uint32 flags,
AsyncIOCallback* _callback)
{
// TODO: Currently this method is only used for single pages. Either make
// more flexible use of it or change the interface!
+8 -7
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License.
*
@@ -44,14 +44,15 @@ public:
virtual bool HasPage(off_t offset);
virtual bool DebugHasPage(off_t offset);
virtual status_t Read(off_t offset, const iovec* vecs,
virtual status_t Read(off_t offset, const generic_io_vec* vecs,
size_t count, uint32 flags,
size_t* _numBytes);
virtual status_t Write(off_t offset, const iovec* vecs,
generic_size_t* _numBytes);
virtual status_t Write(off_t offset, const generic_io_vec* vecs,
size_t count, uint32 flags,
size_t* _numBytes);
virtual status_t WriteAsync(off_t offset, const iovec* vecs,
size_t count, size_t numBytes, uint32 flags,
generic_size_t* _numBytes);
virtual status_t WriteAsync(off_t offset,
const generic_io_vec* vecs, size_t count,
generic_size_t numBytes, uint32 flags,
AsyncIOCallback* callback);
virtual bool CanWritePage(off_t offset);
+7 -7
View File
@@ -1163,27 +1163,27 @@ VMCache::HasPage(off_t offset)
status_t
VMCache::Read(off_t offset, const iovec *vecs, size_t count, uint32 flags,
size_t *_numBytes)
VMCache::Read(off_t offset, const generic_io_vec *vecs, size_t count,
uint32 flags, generic_size_t *_numBytes)
{
return B_ERROR;
}
status_t
VMCache::Write(off_t offset, const iovec *vecs, size_t count, uint32 flags,
size_t *_numBytes)
VMCache::Write(off_t offset, const generic_io_vec *vecs, size_t count,
uint32 flags, generic_size_t *_numBytes)
{
return B_ERROR;
}
status_t
VMCache::WriteAsync(off_t offset, const iovec* vecs, size_t count,
size_t numBytes, uint32 flags, AsyncIOCallback* callback)
VMCache::WriteAsync(off_t offset, const generic_io_vec* vecs, size_t count,
generic_size_t numBytes, uint32 flags, AsyncIOCallback* callback)
{
// Not supported, fall back to the synchronous hook.
size_t transferred = numBytes;
generic_size_t transferred = numBytes;
status_t error = Write(offset, vecs, count, flags, &transferred);
if (callback != NULL)
+12 -14
View File
@@ -1504,8 +1504,8 @@ vm_map_physical_memory(team_id team, const char* name, void** _address,
*/
area_id
vm_map_physical_memory_vecs(team_id team, const char* name, void** _address,
uint32 addressSpec, addr_t* _size, uint32 protection, struct iovec* vecs,
uint32 vecCount)
uint32 addressSpec, addr_t* _size, uint32 protection,
struct generic_io_vec* vecs, uint32 vecCount)
{
TRACE(("vm_map_physical_memory_vecs(team = %ld, \"%s\", virtual = %p, "
"spec = %ld, _size = %p, protection = %ld, vecs = %p, "
@@ -1526,18 +1526,17 @@ vm_map_physical_memory_vecs(team_id team, const char* name, void** _address,
addr_t size = 0;
for (uint32 i = 0; i < vecCount; i++) {
if ((addr_t)vecs[i].iov_base % B_PAGE_SIZE != 0
|| vecs[i].iov_len % B_PAGE_SIZE != 0) {
if (vecs[i].base % B_PAGE_SIZE != 0
|| vecs[i].length % B_PAGE_SIZE != 0) {
return B_BAD_VALUE;
}
size += vecs[i].iov_len;
size += vecs[i].length;
}
// create a device cache
VMCache* cache;
status_t result = VMCacheFactory::CreateDeviceCache(cache,
(addr_t)vecs[0].iov_base);
status_t result = VMCacheFactory::CreateDeviceCache(cache, vecs[0].base);
if (result != B_OK)
return result;
@@ -1573,7 +1572,7 @@ vm_map_physical_memory_vecs(team_id team, const char* name, void** _address,
uint32 vecIndex = 0;
size_t vecOffset = 0;
for (addr_t offset = 0; offset < size; offset += B_PAGE_SIZE) {
while (vecOffset >= vecs[vecIndex].iov_len && vecIndex < vecCount) {
while (vecOffset >= vecs[vecIndex].length && vecIndex < vecCount) {
vecOffset = 0;
vecIndex++;
}
@@ -1581,9 +1580,8 @@ vm_map_physical_memory_vecs(team_id team, const char* name, void** _address,
if (vecIndex >= vecCount)
break;
map->Map(area->Base() + offset,
(addr_t)vecs[vecIndex].iov_base + vecOffset, protection,
area->MemoryType(), &reservation);
map->Map(area->Base() + offset, vecs[vecIndex].base + vecOffset,
protection, area->MemoryType(), &reservation);
vecOffset += B_PAGE_SIZE;
}
@@ -4033,9 +4031,9 @@ fault_get_page(PageFaultContext& context)
context.UnlockAll();
// read the page in
iovec vec;
vec.iov_base = (void*)(page->physical_page_number * B_PAGE_SIZE);
size_t bytesRead = vec.iov_len = B_PAGE_SIZE;
generic_io_vec vec;
vec.base = (phys_addr_t)page->physical_page_number * B_PAGE_SIZE;
generic_size_t bytesRead = vec.length = B_PAGE_SIZE;
status_t status = cache->Read(context.cacheOffset, &vec, 1,
B_PHYSICAL_IO_REQUEST, &bytesRead);
+13 -13
View File
@@ -1548,7 +1548,7 @@ private:
int32 fMaxPages;
status_t fStatus;
uint32 fVecCount;
iovec fVecs[32]; // TODO: make dynamic/configurable
generic_io_vec fVecs[32]; // TODO: make dynamic/configurable
};
@@ -1685,8 +1685,8 @@ PageWriteTransfer::SetTo(PageWriterRun* run, vm_page* page, int32 maxPages)
fMaxPages = maxPages;
fStatus = B_OK;
fVecs[0].iov_base = (void*)(page->physical_page_number << PAGE_SHIFT);
fVecs[0].iov_len = B_PAGE_SIZE;
fVecs[0].base = (phys_addr_t)page->physical_page_number << PAGE_SHIFT;
fVecs[0].length = B_PAGE_SIZE;
fVecCount = 1;
}
@@ -1700,23 +1700,23 @@ PageWriteTransfer::AddPage(vm_page* page)
|| (fMaxPages >= 0 && fPageCount >= (uint32)fMaxPages))
return false;
phys_addr_t nextBase = (phys_addr_t)fVecs[fVecCount - 1].iov_base
+ fVecs[fVecCount - 1].iov_len;
phys_addr_t nextBase = fVecs[fVecCount - 1].base
+ fVecs[fVecCount - 1].length;
if (page->physical_page_number << PAGE_SHIFT == nextBase
&& page->cache_offset == fOffset + fPageCount) {
// append to last iovec
fVecs[fVecCount - 1].iov_len += B_PAGE_SIZE;
fVecs[fVecCount - 1].length += B_PAGE_SIZE;
fPageCount++;
return true;
}
nextBase = (phys_addr_t)fVecs[0].iov_base - B_PAGE_SIZE;
nextBase = fVecs[0].base - B_PAGE_SIZE;
if (page->physical_page_number << PAGE_SHIFT == nextBase
&& page->cache_offset == fOffset - 1) {
// prepend to first iovec and adjust offset
fVecs[0].iov_base = (void*)nextBase;
fVecs[0].iov_len += B_PAGE_SIZE;
fVecs[0].base = nextBase;
fVecs[0].length += B_PAGE_SIZE;
fOffset = page->cache_offset;
fPageCount++;
return true;
@@ -1737,9 +1737,9 @@ PageWriteTransfer::AddPage(vm_page* page)
} else
vectorIndex = fVecCount;
fVecs[vectorIndex].iov_base
= (void*)(page->physical_page_number << PAGE_SHIFT);
fVecs[vectorIndex].iov_len = B_PAGE_SIZE;
fVecs[vectorIndex].base
= (phys_addr_t)page->physical_page_number << PAGE_SHIFT;
fVecs[vectorIndex].length = B_PAGE_SIZE;
fVecCount++;
fPageCount++;
@@ -1754,7 +1754,7 @@ status_t
PageWriteTransfer::Schedule(uint32 flags)
{
off_t writeOffset = (off_t)fOffset << PAGE_SHIFT;
size_t writeLength = (size_t)fPageCount << PAGE_SHIFT;
generic_size_t writeLength = (phys_size_t)fPageCount << PAGE_SHIFT;
if (fRun != NULL) {
return fCache->WriteAsync(writeOffset, fVecs, fVecCount, writeLength,