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