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

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


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@36997 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2010-06-02 18:42:20 +00:00
parent 4a57f84396
commit 435c43f591
24 changed files with 515 additions and 471 deletions
+13 -15
View File
@@ -33,6 +33,7 @@
struct attr_info; struct 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
+8 -6
View File
@@ -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);
+2 -2
View File
@@ -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
View File
@@ -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
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2004-2007, Axel Dörfler, axeld@pinc-software.de. * 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
View File
@@ -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);
+14 -13
View File
@@ -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;
} }
} }
+4 -3
View File
@@ -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;
}; };
+117 -110
View File
@@ -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;
+53 -48
View File
@@ -1,16 +1,17 @@
/* /*
* Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2008, Axel Dörfler, axeld@pinc-software.de. * 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
+10 -6
View File
@@ -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;
+8 -8
View File
@@ -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);
+21 -20
View File
@@ -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!
+8 -7
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@gmx.de. * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de. * 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);
+7 -7
View File
@@ -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
View File
@@ -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);
+13 -13
View File
@@ -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,